static SECStatus ssl_canExtractMS(PK11SymKey *pms, PRBool isTLS, PRBool isDH, PRBool *pcbp) { SECStatus rv; PK11SymKey * ms = NULL; SECItem params = {siBuffer, NULL, 0}; CK_SSL3_MASTER_KEY_DERIVE_PARAMS master_params; unsigned char rand[SSL3_RANDOM_LENGTH]; CK_VERSION pms_version; CK_MECHANISM_TYPE master_derive; CK_MECHANISM_TYPE key_derive; CK_FLAGS keyFlags; if (pms == NULL) return(SECFailure); PORT_Memset(rand, 0, SSL3_RANDOM_LENGTH); if (isTLS) { if(isDH) master_derive = CKM_TLS_MASTER_KEY_DERIVE_DH; else master_derive = CKM_TLS_MASTER_KEY_DERIVE; key_derive = CKM_TLS_KEY_AND_MAC_DERIVE; keyFlags = CKF_SIGN | CKF_VERIFY; } else { if (isDH) master_derive = CKM_SSL3_MASTER_KEY_DERIVE_DH; else master_derive = CKM_SSL3_MASTER_KEY_DERIVE; key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE; keyFlags = 0; } master_params.pVersion = &pms_version; master_params.RandomInfo.pClientRandom = rand; master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH; master_params.RandomInfo.pServerRandom = rand; master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH; params.data = (unsigned char *) &master_params; params.len = sizeof master_params; ms = PK11_DeriveWithFlags(pms, master_derive, ¶ms, key_derive, CKA_DERIVE, 0, keyFlags); if (ms == NULL) return(SECFailure); rv = PK11_ExtractKeyValue(ms); *pcbp = (rv == SECSuccess); PK11_FreeSymKey(ms); return(rv); }
SECStatus tls13_HkdfExpandLabel(PK11SymKey *prk, SSLHashType baseHash, const PRUint8 *handshakeHash, unsigned int handshakeHashLen, const char *label, unsigned int labelLen, CK_MECHANISM_TYPE algorithm, unsigned int keySize, PK11SymKey **keyp) { CK_NSS_HKDFParams params; SECItem paramsi = { siBuffer, NULL, 0 }; /* Size of info array needs to be big enough to hold the maximum Prefix, * Label, plus HandshakeHash. If it's ever to small, the code will abort. */ PRUint8 info[256]; PRUint8 *ptr = info; unsigned int infoLen; PK11SymKey *derived; const char *kLabelPrefix = "TLS 1.3, "; const unsigned int kLabelPrefixLen = strlen(kLabelPrefix); if (handshakeHash) { PORT_Assert(handshakeHashLen == kTlsHkdfInfo[baseHash].hashSize * 2); } else { PORT_Assert(!handshakeHashLen); } /* * [draft-ietf-tls-tls13-11] Section 7.1: * * HKDF-Expand-Label(Secret, Label, HashValue, Length) = * HKDF-Expand(Secret, HkdfLabel, Length) * * Where HkdfLabel is specified as: * * struct HkdfLabel { * uint16 length; * opaque label<9..255>; * opaque hash_value<0..255>; * }; * * Where: * - HkdfLabel.length is Length * - HkdfLabel.hash_value is HashValue. * - HkdfLabel.label is "TLS 1.3, " + Label * */ infoLen = 2 + 1 + kLabelPrefixLen + labelLen + 1 + handshakeHashLen; if (infoLen > sizeof(info)) { PORT_Assert(0); goto abort; } ptr = tls13_EncodeUintX(keySize, 2, ptr); ptr = tls13_EncodeUintX(labelLen + kLabelPrefixLen, 1, ptr); PORT_Memcpy(ptr, kLabelPrefix, kLabelPrefixLen); ptr += kLabelPrefixLen; PORT_Memcpy(ptr, label, labelLen); ptr += labelLen; ptr = tls13_EncodeUintX(handshakeHashLen, 1, ptr); if (handshakeHash) { PORT_Memcpy(ptr, handshakeHash, handshakeHashLen); ptr += handshakeHashLen; } PORT_Assert((ptr - info) == infoLen); params.bExtract = CK_FALSE; params.bExpand = CK_TRUE; params.pInfo = info; params.ulInfoLen = infoLen; paramsi.data = (unsigned char *)¶ms; paramsi.len = sizeof(params); derived = PK11_DeriveWithFlags(prk, kTlsHkdfInfo[baseHash].pkcs11Mech, ¶msi, algorithm, CKA_DERIVE, keySize, CKF_SIGN | CKF_VERIFY); if (!derived) return SECFailure; *keyp = derived; #ifdef TRACE if (ssl_trace >= 10) { /* Make sure the label is null terminated. */ char labelStr[100]; PORT_Memcpy(labelStr, label, labelLen); labelStr[labelLen] = 0; SSL_TRC(50, ("HKDF Expand: label=[TLS 1.3, ] + '%s',requested length=%d", labelStr, keySize)); } PRINT_KEY(50, (NULL, "PRK", prk)); PRINT_BUF(50, (NULL, "Hash", handshakeHash, handshakeHashLen)); PRINT_BUF(50, (NULL, "Info", info, infoLen)); PRINT_KEY(50, (NULL, "Derived key", derived)); #endif return SECSuccess; abort: PORT_SetError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); return SECFailure; }