| OLD | NEW |
| (Empty) |
| 1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | |
| 2 /* | |
| 3 * TLS 1.3 Protocol | |
| 4 * | |
| 5 * This Source Code Form is subject to the terms of the Mozilla Public | |
| 6 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
| 8 | |
| 9 #include "keyhi.h" | |
| 10 #include "pk11func.h" | |
| 11 #include "secitem.h" | |
| 12 #include "sslt.h" | |
| 13 #include "sslerr.h" | |
| 14 | |
| 15 // TODO(ekr@rtfm.com): Export this separately. | |
| 16 unsigned char *tls13_EncodeUintX(PRUint32 value, unsigned int bytes, unsigned ch
ar *to); | |
| 17 | |
| 18 /* This table contains the mapping between TLS hash identifiers and the | |
| 19 * PKCS#11 identifiers */ | |
| 20 static const struct { | |
| 21 SSLHashType hash; | |
| 22 CK_MECHANISM_TYPE pkcs11Mech; | |
| 23 unsigned int hashSize; | |
| 24 } kTlsHkdfInfo[] = { | |
| 25 { ssl_hash_none, 0, 0 }, | |
| 26 { ssl_hash_md5, 0, 0 }, | |
| 27 { ssl_hash_sha1, 0, 0 }, | |
| 28 { ssl_hash_sha224, 0 }, | |
| 29 { ssl_hash_sha256, CKM_NSS_HKDF_SHA256, 32 }, | |
| 30 { ssl_hash_sha384, CKM_NSS_HKDF_SHA384, 48 }, | |
| 31 { ssl_hash_sha512, CKM_NSS_HKDF_SHA512, 64 } | |
| 32 }; | |
| 33 | |
| 34 SECStatus | |
| 35 tls13_HkdfExtract(PK11SymKey *ikm1, PK11SymKey *ikm2, SSLHashType baseHash, | |
| 36 PK11SymKey **prkp) | |
| 37 { | |
| 38 CK_NSS_HKDFParams params; | |
| 39 SECItem paramsi; | |
| 40 SECStatus rv; | |
| 41 SECItem *salt; | |
| 42 PK11SymKey *prk; | |
| 43 | |
| 44 params.bExtract = CK_TRUE; | |
| 45 params.bExpand = CK_FALSE; | |
| 46 params.pInfo = NULL; | |
| 47 params.ulInfoLen = 0UL; | |
| 48 | |
| 49 if (ikm1) { | |
| 50 /* TODO(ekr@rtfm.com): This violates the PKCS#11 key boundary | |
| 51 * but is imposed on us by the present HKDF interface. */ | |
| 52 rv = PK11_ExtractKeyValue(ikm1); | |
| 53 if (rv != SECSuccess) | |
| 54 return rv; | |
| 55 | |
| 56 salt = PK11_GetKeyData(ikm1); | |
| 57 if (!salt) | |
| 58 return SECFailure; | |
| 59 | |
| 60 params.pSalt = salt->data; | |
| 61 params.ulSaltLen = salt->len; | |
| 62 PORT_Assert(salt->len > 0); | |
| 63 } else { | |
| 64 /* Per documentation for CKM_NSS_HKDF_*: | |
| 65 * | |
| 66 * If the optional salt is given, it is used; otherwise, the salt is | |
| 67 * set to a sequence of zeros equal in length to the HMAC output. | |
| 68 */ | |
| 69 params.pSalt = NULL; | |
| 70 params.ulSaltLen = 0UL; | |
| 71 } | |
| 72 paramsi.data = (unsigned char *)¶ms; | |
| 73 paramsi.len = sizeof(params); | |
| 74 | |
| 75 PORT_Assert(kTlsHkdfInfo[baseHash].pkcs11Mech); | |
| 76 PORT_Assert(kTlsHkdfInfo[baseHash].hashSize); | |
| 77 PORT_Assert(kTlsHkdfInfo[baseHash].hash == baseHash); | |
| 78 prk = PK11_Derive(ikm2, kTlsHkdfInfo[baseHash].pkcs11Mech, | |
| 79 ¶msi, kTlsHkdfInfo[baseHash].pkcs11Mech, | |
| 80 CKA_DERIVE, kTlsHkdfInfo[baseHash].hashSize); | |
| 81 if (!prk) | |
| 82 return SECFailure; | |
| 83 | |
| 84 *prkp = prk; | |
| 85 return SECSuccess; | |
| 86 } | |
| 87 | |
| 88 SECStatus | |
| 89 tls13_HkdfExpandLabel(PK11SymKey *prk, SSLHashType baseHash, | |
| 90 const PRUint8 *handshakeHash, unsigned int handshakeHashLe
n, | |
| 91 const char *label, unsigned int labelLen, | |
| 92 CK_MECHANISM_TYPE algorithm, unsigned int keySize, | |
| 93 PK11SymKey **keyp) | |
| 94 { | |
| 95 CK_NSS_HKDFParams params; | |
| 96 SECItem paramsi = { siBuffer, NULL, 0 }; | |
| 97 PRUint8 info[100]; | |
| 98 PRUint8 *ptr = info; | |
| 99 unsigned int infoLen; | |
| 100 PK11SymKey *derived; | |
| 101 const char *kLabelPrefix = "TLS 1.3, "; | |
| 102 const unsigned int kLabelPrefixLen = strlen(kLabelPrefix); | |
| 103 | |
| 104 if (handshakeHash) { | |
| 105 PORT_Assert(handshakeHashLen == kTlsHkdfInfo[baseHash].hashSize); | |
| 106 } else { | |
| 107 PORT_Assert(!handshakeHashLen); | |
| 108 } | |
| 109 | |
| 110 /* | |
| 111 * [draft-ietf-tls-tls13-11] Section 7.1: | |
| 112 * | |
| 113 * HKDF-Expand-Label(Secret, Label, HashValue, Length) = | |
| 114 * HKDF-Expand(Secret, HkdfLabel, Length) | |
| 115 * | |
| 116 * Where HkdfLabel is specified as: | |
| 117 * | |
| 118 * struct HkdfLabel { | |
| 119 * uint16 length; | |
| 120 * opaque label<9..255>; | |
| 121 * opaque hash_value<0..255>; | |
| 122 * }; | |
| 123 * | |
| 124 * Where: | |
| 125 * - HkdfLabel.length is Length | |
| 126 * - HkdfLabel.hash_value is HashValue. | |
| 127 * - HkdfLabel.label is "TLS 1.3, " + Label | |
| 128 * | |
| 129 */ | |
| 130 infoLen = 2 + 1 + kLabelPrefixLen + labelLen + 1 + handshakeHashLen; | |
| 131 if (infoLen > sizeof(info)) { | |
| 132 PORT_Assert(0); | |
| 133 goto abort; | |
| 134 } | |
| 135 | |
| 136 ptr = tls13_EncodeUintX(keySize, 2, ptr); | |
| 137 ptr = tls13_EncodeUintX(labelLen + kLabelPrefixLen, 1, ptr); | |
| 138 PORT_Memcpy(ptr, kLabelPrefix, kLabelPrefixLen); | |
| 139 ptr += kLabelPrefixLen; | |
| 140 PORT_Memcpy(ptr, label, labelLen); | |
| 141 ptr += labelLen; | |
| 142 ptr = tls13_EncodeUintX(handshakeHashLen, 1, ptr); | |
| 143 if (handshakeHash) { | |
| 144 PORT_Memcpy(ptr, handshakeHash, handshakeHashLen); | |
| 145 ptr += handshakeHashLen; | |
| 146 } | |
| 147 PORT_Assert((ptr - info) == infoLen); | |
| 148 | |
| 149 params.bExtract = CK_FALSE; | |
| 150 params.bExpand = CK_TRUE; | |
| 151 params.pInfo = info; | |
| 152 params.ulInfoLen = infoLen; | |
| 153 paramsi.data = (unsigned char *)¶ms; | |
| 154 paramsi.len = sizeof(params); | |
| 155 | |
| 156 derived = PK11_DeriveWithFlags(prk, kTlsHkdfInfo[baseHash].pkcs11Mech, | |
| 157 ¶msi, algorithm, | |
| 158 CKA_DERIVE, keySize, | |
| 159 CKF_SIGN | CKF_VERIFY); | |
| 160 if (!derived) | |
| 161 return SECFailure; | |
| 162 | |
| 163 *keyp = derived; | |
| 164 | |
| 165 return SECSuccess; | |
| 166 | |
| 167 abort: | |
| 168 PORT_SetError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); | |
| 169 return SECFailure; | |
| 170 } | |
| 171 | |
| 172 SECStatus | |
| 173 tls13_HkdfExpandLabelRaw(PK11SymKey *prk, SSLHashType baseHash, | |
| 174 const PRUint8 *handshakeHash, unsigned int handshakeHas
hLen, | |
| 175 const char *label, unsigned int labelLen, | |
| 176 unsigned char *output, unsigned int outputLen) | |
| 177 { | |
| 178 PK11SymKey *derived = NULL; | |
| 179 SECItem *rawkey; | |
| 180 SECStatus rv; | |
| 181 | |
| 182 rv = tls13_HkdfExpandLabel(prk, baseHash, handshakeHash, handshakeHashLen, | |
| 183 label, labelLen, | |
| 184 kTlsHkdfInfo[baseHash].pkcs11Mech, outputLen, | |
| 185 &derived); | |
| 186 if (rv != SECSuccess || !derived) { | |
| 187 goto abort; | |
| 188 } | |
| 189 | |
| 190 rv = PK11_ExtractKeyValue(derived); | |
| 191 if (rv != SECSuccess) { | |
| 192 goto abort; | |
| 193 } | |
| 194 | |
| 195 rawkey = PK11_GetKeyData(derived); | |
| 196 if (!rawkey) { | |
| 197 goto abort; | |
| 198 } | |
| 199 | |
| 200 PORT_Assert(rawkey->len == outputLen); | |
| 201 memcpy(output, rawkey->data, outputLen); | |
| 202 PK11_FreeSymKey(derived); | |
| 203 | |
| 204 return SECSuccess; | |
| 205 | |
| 206 abort: | |
| 207 if (derived) { | |
| 208 PK11_FreeSymKey(derived); | |
| 209 } | |
| 210 PORT_SetError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); | |
| 211 return SECFailure; | |
| 212 } | |
| OLD | NEW |