tls13hkdf.c (10419B)
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 "ssl.h" 13 #include "sslt.h" 14 #include "sslerr.h" 15 #include "sslimpl.h" 16 17 /* This table contains the mapping between TLS hash identifiers and the 18 * PKCS#11 identifiers */ 19 static const struct { 20 SSLHashType hash; 21 CK_MECHANISM_TYPE pkcs11Mech; 22 unsigned int hashSize; 23 } kTlsHkdfInfo[] = { 24 { ssl_hash_none, 0, 0 }, 25 { ssl_hash_md5, 0, 0 }, 26 { ssl_hash_sha1, 0, 0 }, 27 { ssl_hash_sha224, 0 }, 28 { ssl_hash_sha256, CKM_SHA256, 32 }, 29 { ssl_hash_sha384, CKM_SHA384, 48 }, 30 { ssl_hash_sha512, CKM_SHA512, 64 } 31 }; 32 33 SECStatus 34 tls13_HkdfExtract(PK11SymKey *ikm1, PK11SymKey *ikm2, SSLHashType baseHash, 35 PK11SymKey **prkp) 36 { 37 CK_HKDF_PARAMS params; 38 SECItem paramsi; 39 PK11SymKey *prk; 40 static const PRUint8 zeroKeyBuf[HASH_LENGTH_MAX]; 41 SECItem zeroKeyItem = { siBuffer, CONST_CAST(PRUint8, zeroKeyBuf), kTlsHkdfInfo[baseHash].hashSize }; 42 PK11SlotInfo *slot = NULL; 43 PK11SymKey *newIkm2 = NULL; 44 PK11SymKey *newIkm1 = NULL; 45 SECStatus rv; 46 47 params.bExtract = CK_TRUE; 48 params.bExpand = CK_FALSE; 49 params.prfHashMechanism = kTlsHkdfInfo[baseHash].pkcs11Mech; 50 params.pInfo = NULL; 51 params.ulInfoLen = 0UL; 52 params.pSalt = NULL; 53 params.ulSaltLen = 0UL; 54 params.hSaltKey = CK_INVALID_HANDLE; 55 56 if (!ikm1) { 57 /* PKCS #11 v3.0 has and explict NULL value, which equates to 58 * a sequence of zeros equal in length to the HMAC. */ 59 params.ulSaltType = CKF_HKDF_SALT_NULL; 60 } else { 61 /* PKCS #11 v3.0 can take the salt as a key handle */ 62 params.hSaltKey = PK11_GetSymKeyHandle(ikm1); 63 params.ulSaltType = CKF_HKDF_SALT_KEY; 64 65 /* if we have both keys, make sure they are in the same slot */ 66 if (ikm2) { 67 rv = PK11_SymKeysToSameSlot(CKM_HKDF_DERIVE, 68 CKA_DERIVE, CKA_DERIVE, 69 ikm2, ikm1, &newIkm2, &newIkm1); 70 if (rv != SECSuccess) { 71 SECItem *salt; 72 /* couldn't move the keys, try extracting the salt */ 73 rv = PK11_ExtractKeyValue(ikm1); 74 if (rv != SECSuccess) 75 return rv; 76 salt = PK11_GetKeyData(ikm1); 77 if (!salt) 78 return SECFailure; 79 PORT_Assert(salt->len > 0); 80 /* Set up for Salt as Data instead of Salt as key */ 81 params.pSalt = salt->data; 82 params.ulSaltLen = salt->len; 83 params.ulSaltType = CKF_HKDF_SALT_DATA; 84 } 85 /* use the new keys */ 86 if (newIkm1) { 87 /* we've moved the key, get the handle for the new key */ 88 params.hSaltKey = PK11_GetSymKeyHandle(newIkm1); 89 /* we don't use ikm1 after this, so don't bother setting it */ 90 } 91 if (newIkm2) { 92 /* new ikm2 key, use the new key */ 93 ikm2 = newIkm2; 94 } 95 } 96 } 97 paramsi.data = (unsigned char *)¶ms; 98 paramsi.len = sizeof(params); 99 100 PORT_Assert(kTlsHkdfInfo[baseHash].pkcs11Mech); 101 PORT_Assert(kTlsHkdfInfo[baseHash].hashSize); 102 PORT_Assert(kTlsHkdfInfo[baseHash].hash == baseHash); 103 104 /* A zero ikm2 is a key of hash-length 0s. */ 105 if (!ikm2) { 106 /* if we have ikm1, put the zero key in the same slot */ 107 slot = ikm1 ? PK11_GetSlotFromKey(ikm1) : PK11_GetBestSlot(CKM_HKDF_DERIVE, NULL); 108 if (!slot) { 109 return SECFailure; 110 } 111 112 newIkm2 = PK11_ImportDataKey(slot, CKM_HKDF_DERIVE, PK11_OriginUnwrap, 113 CKA_DERIVE, &zeroKeyItem, NULL); 114 if (!newIkm2) { 115 return SECFailure; 116 } 117 ikm2 = newIkm2; 118 } 119 PORT_Assert(ikm2); 120 121 PRINT_BUF(50, (NULL, "HKDF Extract: IKM1/Salt", params.pSalt, params.ulSaltLen)); 122 PRINT_KEY(50, (NULL, "HKDF Extract: IKM2", ikm2)); 123 124 prk = PK11_Derive(ikm2, CKM_HKDF_DERIVE, ¶msi, CKM_HKDF_DERIVE, 125 CKA_DERIVE, 0); 126 PK11_FreeSymKey(newIkm2); 127 PK11_FreeSymKey(newIkm1); 128 if (slot) 129 PK11_FreeSlot(slot); 130 if (!prk) { 131 return SECFailure; 132 } 133 134 PRINT_KEY(50, (NULL, "HKDF Extract", prk)); 135 *prkp = prk; 136 137 return SECSuccess; 138 } 139 140 SECStatus 141 tls13_HkdfExpandLabelGeneral(CK_MECHANISM_TYPE deriveMech, PK11SymKey *prk, 142 SSLHashType baseHash, 143 const PRUint8 *handshakeHash, unsigned int handshakeHashLen, 144 const char *label, unsigned int labelLen, 145 CK_MECHANISM_TYPE algorithm, unsigned int keySize, 146 SSLProtocolVariant variant, PK11SymKey **keyp) 147 { 148 CK_HKDF_PARAMS params; 149 SECItem paramsi = { siBuffer, NULL, 0 }; 150 /* Size of info array needs to be big enough to hold the maximum Prefix, 151 * Label, plus HandshakeHash. If it's ever to small, the code will abort. 152 */ 153 PRUint8 info[256]; 154 sslBuffer infoBuf = SSL_BUFFER(info); 155 PK11SymKey *derived; 156 SECStatus rv; 157 const char *kLabelPrefixTls = "tls13 "; 158 const char *kLabelPrefixDtls = "dtls13"; 159 const unsigned int kLabelPrefixLen = 160 (variant == ssl_variant_stream) ? strlen(kLabelPrefixTls) : strlen(kLabelPrefixDtls); 161 const char *kLabelPrefix = 162 (variant == ssl_variant_stream) ? kLabelPrefixTls : kLabelPrefixDtls; 163 164 PORT_Assert(prk); 165 PORT_Assert(keyp); 166 if ((handshakeHashLen > 255) || 167 (handshakeHash == NULL && handshakeHashLen > 0) || 168 (labelLen + kLabelPrefixLen > 255)) { 169 PORT_SetError(SEC_ERROR_INVALID_ARGS); 170 return SECFailure; 171 } 172 173 /* 174 * [draft-ietf-tls-tls13-11] Section 7.1: 175 * 176 * HKDF-Expand-Label(Secret, Label, HashValue, Length) = 177 * HKDF-Expand(Secret, HkdfLabel, Length) 178 * 179 * Where HkdfLabel is specified as: 180 * 181 * struct HkdfLabel { 182 * uint16 length; 183 * opaque label<9..255>; 184 * opaque hash_value<0..255>; 185 * }; 186 * 187 * Where: 188 * - HkdfLabel.length is Length 189 * - HkdfLabel.hash_value is HashValue. 190 * - HkdfLabel.label is "TLS 1.3, " + Label 191 * 192 */ 193 rv = sslBuffer_AppendNumber(&infoBuf, keySize, 2); 194 if (rv != SECSuccess) { 195 return SECFailure; 196 } 197 rv = sslBuffer_AppendNumber(&infoBuf, labelLen + kLabelPrefixLen, 1); 198 if (rv != SECSuccess) { 199 return SECFailure; 200 } 201 rv = sslBuffer_Append(&infoBuf, kLabelPrefix, kLabelPrefixLen); 202 if (rv != SECSuccess) { 203 return SECFailure; 204 } 205 rv = sslBuffer_Append(&infoBuf, label, labelLen); 206 if (rv != SECSuccess) { 207 return SECFailure; 208 } 209 rv = sslBuffer_AppendVariable(&infoBuf, handshakeHash, handshakeHashLen, 1); 210 if (rv != SECSuccess) { 211 return SECFailure; 212 } 213 214 params.bExtract = CK_FALSE; 215 params.bExpand = CK_TRUE; 216 params.prfHashMechanism = kTlsHkdfInfo[baseHash].pkcs11Mech; 217 params.pInfo = SSL_BUFFER_BASE(&infoBuf); 218 params.ulInfoLen = SSL_BUFFER_LEN(&infoBuf); 219 paramsi.data = (unsigned char *)¶ms; 220 paramsi.len = sizeof(params); 221 derived = PK11_DeriveWithFlags(prk, deriveMech, 222 ¶msi, algorithm, 223 CKA_DERIVE, keySize, 224 CKF_SIGN | CKF_VERIFY); 225 if (!derived) { 226 return SECFailure; 227 } 228 229 *keyp = derived; 230 231 #ifdef TRACE 232 if (ssl_trace >= 50) { 233 /* Make sure the label is null terminated. */ 234 char labelStr[100]; 235 PORT_Memcpy(labelStr, label, labelLen); 236 labelStr[labelLen] = 0; 237 SSL_TRC(50, ("HKDF Expand: label='tls13 %s',requested length=%d", 238 labelStr, keySize)); 239 } 240 PRINT_KEY(50, (NULL, "PRK", prk)); 241 PRINT_BUF(50, (NULL, "Hash", handshakeHash, handshakeHashLen)); 242 PRINT_BUF(50, (NULL, "Info", SSL_BUFFER_BASE(&infoBuf), 243 SSL_BUFFER_LEN(&infoBuf))); 244 PRINT_KEY(50, (NULL, "Derived key", derived)); 245 #endif 246 247 return SECSuccess; 248 } 249 250 SECStatus 251 tls13_HkdfExpandLabel(PK11SymKey *prk, SSLHashType baseHash, 252 const PRUint8 *handshakeHash, unsigned int handshakeHashLen, 253 const char *label, unsigned int labelLen, 254 CK_MECHANISM_TYPE algorithm, unsigned int keySize, 255 SSLProtocolVariant variant, PK11SymKey **keyp) 256 { 257 return tls13_HkdfExpandLabelGeneral(CKM_HKDF_DERIVE, prk, baseHash, 258 handshakeHash, handshakeHashLen, 259 label, labelLen, algorithm, keySize, 260 variant, keyp); 261 } 262 263 SECStatus 264 tls13_HkdfExpandLabelRaw(PK11SymKey *prk, SSLHashType baseHash, 265 const PRUint8 *handshakeHash, unsigned int handshakeHashLen, 266 const char *label, unsigned int labelLen, 267 SSLProtocolVariant variant, unsigned char *output, 268 unsigned int outputLen) 269 { 270 PK11SymKey *derived = NULL; 271 SECItem *rawkey; 272 SECStatus rv; 273 274 /* the result is not really a key, it's a data object */ 275 rv = tls13_HkdfExpandLabelGeneral(CKM_HKDF_DATA, prk, baseHash, 276 handshakeHash, handshakeHashLen, 277 label, labelLen, CKM_HKDF_DERIVE, outputLen, 278 variant, &derived); 279 if (rv != SECSuccess || !derived) { 280 goto abort; 281 } 282 283 rv = PK11_ExtractKeyValue(derived); 284 if (rv != SECSuccess) { 285 goto abort; 286 } 287 288 rawkey = PK11_GetKeyData(derived); 289 if (!rawkey) { 290 goto abort; 291 } 292 293 PORT_Assert(rawkey->len == outputLen); 294 memcpy(output, rawkey->data, outputLen); 295 PK11_FreeSymKey(derived); 296 297 return SECSuccess; 298 299 abort: 300 if (derived) { 301 PK11_FreeSymKey(derived); 302 } 303 PORT_SetError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); 304 return SECFailure; 305 }