| File: | root/firefox-clang/security/nss/lib/ssl/tls13hkdf.c |
| Warning: | line 19, column 14 Excessive padding in 'struct (unnamed at /root/firefox-clang/security/nss/lib/ssl/tls13hkdf.c:19:14)' (8 padding bytes, where 0 is optimal). Optimal fields order: pkcs11Mech, hash, hashSize, consider reordering the fields or adding explicit padding members |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 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 { |
Excessive padding in 'struct (unnamed at /root/firefox-clang/security/nss/lib/ssl/tls13hkdf.c:19:14)' (8 padding bytes, where 0 is optimal). Optimal fields order: pkcs11Mech, hash, hashSize, consider reordering the fields or adding explicit padding members | |
| 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_SHA2560x00000250UL, 32 }, |
| 29 | { ssl_hash_sha384, CKM_SHA3840x00000260UL, 48 }, |
| 30 | { ssl_hash_sha512, CKM_SHA5120x00000270UL, 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_MAX64]; |
| 41 | SECItem zeroKeyItem = { siBuffer, CONST_CAST(PRUint8, zeroKeyBuf)((PRUint8 *)(zeroKeyBuf)), kTlsHkdfInfo[baseHash].hashSize }; |
| 42 | PK11SlotInfo *slot = NULL((void*)0); |
| 43 | PK11SymKey *newIkm2 = NULL((void*)0); |
| 44 | PK11SymKey *newIkm1 = NULL((void*)0); |
| 45 | SECStatus rv; |
| 46 | |
| 47 | params.bExtract = CK_TRUE1; |
| 48 | params.bExpand = CK_FALSE0; |
| 49 | params.prfHashMechanism = kTlsHkdfInfo[baseHash].pkcs11Mech; |
| 50 | params.pInfo = NULL((void*)0); |
| 51 | params.ulInfoLen = 0UL; |
| 52 | params.pSalt = NULL((void*)0); |
| 53 | params.ulSaltLen = 0UL; |
| 54 | params.hSaltKey = CK_INVALID_HANDLE0; |
| 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_NULL0x00000001UL; |
| 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_KEY0x00000004UL; |
| 64 | |
| 65 | /* if we have both keys, make sure they are in the same slot */ |
| 66 | if (ikm2) { |
| 67 | rv = PK11_SymKeysToSameSlot(CKM_HKDF_DERIVE0x0000402aUL, |
| 68 | CKA_DERIVE0x0000010CUL, CKA_DERIVE0x0000010CUL, |
| 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)((salt->len > 0)?((void)0):PR_Assert("salt->len > 0" ,"/root/firefox-clang/security/nss/lib/ssl/tls13hkdf.c",79)); |
| 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_DATA0x00000002UL; |
| 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)((kTlsHkdfInfo[baseHash].pkcs11Mech)?((void)0):PR_Assert("kTlsHkdfInfo[baseHash].pkcs11Mech" ,"/root/firefox-clang/security/nss/lib/ssl/tls13hkdf.c",100)); |
| 101 | PORT_Assert(kTlsHkdfInfo[baseHash].hashSize)((kTlsHkdfInfo[baseHash].hashSize)?((void)0):PR_Assert("kTlsHkdfInfo[baseHash].hashSize" ,"/root/firefox-clang/security/nss/lib/ssl/tls13hkdf.c",101)); |
| 102 | PORT_Assert(kTlsHkdfInfo[baseHash].hash == baseHash)((kTlsHkdfInfo[baseHash].hash == baseHash)?((void)0):PR_Assert ("kTlsHkdfInfo[baseHash].hash == baseHash","/root/firefox-clang/security/nss/lib/ssl/tls13hkdf.c" ,102)); |
| 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_DERIVE0x0000402aUL, NULL((void*)0)); |
| 108 | if (!slot) { |
| 109 | return SECFailure; |
| 110 | } |
| 111 | |
| 112 | newIkm2 = PK11_ImportDataKey(slot, CKM_HKDF_DERIVE0x0000402aUL, PK11_OriginUnwrap, |
| 113 | CKA_DERIVE0x0000010CUL, &zeroKeyItem, NULL((void*)0)); |
| 114 | if (!newIkm2) { |
| 115 | return SECFailure; |
| 116 | } |
| 117 | ikm2 = newIkm2; |
| 118 | } |
| 119 | PORT_Assert(ikm2)((ikm2)?((void)0):PR_Assert("ikm2","/root/firefox-clang/security/nss/lib/ssl/tls13hkdf.c" ,119)); |
| 120 | |
| 121 | PRINT_BUF(50, (NULL, "HKDF Extract: IKM1/Salt", params.pSalt, params.ulSaltLen))if (ssl_trace >= (50)) ssl_PrintBuf (((void*)0), "HKDF Extract: IKM1/Salt" , params.pSalt, params.ulSaltLen); |
| 122 | PRINT_KEY(50, (NULL, "HKDF Extract: IKM2", ikm2))if (ssl_trace >= (50)) ssl_PrintKey (((void*)0), "HKDF Extract: IKM2" , ikm2); |
| 123 | |
| 124 | prk = PK11_Derive(ikm2, CKM_HKDF_DERIVE0x0000402aUL, ¶msi, CKM_HKDF_DERIVE0x0000402aUL, |
| 125 | CKA_DERIVE0x0000010CUL, 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))if (ssl_trace >= (50)) ssl_PrintKey (((void*)0), "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((void*)0), 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){ info, 0, sizeof(info), 1 }; |
| 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)((prk)?((void)0):PR_Assert("prk","/root/firefox-clang/security/nss/lib/ssl/tls13hkdf.c" ,164)); |
| 165 | PORT_Assert(keyp)((keyp)?((void)0):PR_Assert("keyp","/root/firefox-clang/security/nss/lib/ssl/tls13hkdf.c" ,165)); |
| 166 | if ((handshakeHashLen > 255) || |
| 167 | (handshakeHash == NULL((void*)0) && handshakeHashLen > 0) || |
| 168 | (labelLen + kLabelPrefixLen > 255)) { |
| 169 | PORT_SetErrorPORT_SetError_Util(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_FALSE0; |
| 215 | params.bExpand = CK_TRUE1; |
| 216 | params.prfHashMechanism = kTlsHkdfInfo[baseHash].pkcs11Mech; |
| 217 | params.pInfo = SSL_BUFFER_BASE(&infoBuf)((&infoBuf)->buf); |
| 218 | params.ulInfoLen = SSL_BUFFER_LEN(&infoBuf)((&infoBuf)->len); |
| 219 | paramsi.data = (unsigned char *)¶ms; |
| 220 | paramsi.len = sizeof(params); |
| 221 | derived = PK11_DeriveWithFlags(prk, deriveMech, |
| 222 | ¶msi, algorithm, |
| 223 | CKA_DERIVE0x0000010CUL, keySize, |
| 224 | CKF_SIGN0x00000800UL | CKF_VERIFY0x00002000); |
| 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_Memcpymemcpy(labelStr, label, labelLen); |
| 236 | labelStr[labelLen] = 0; |
| 237 | SSL_TRC(50, ("HKDF Expand: label='tls13 %s',requested length=%d",if (ssl_trace >= (50)) ssl_Trace ("HKDF Expand: label='tls13 %s',requested length=%d" , labelStr, keySize) |
| 238 | labelStr, keySize))if (ssl_trace >= (50)) ssl_Trace ("HKDF Expand: label='tls13 %s',requested length=%d" , labelStr, keySize); |
| 239 | } |
| 240 | PRINT_KEY(50, (NULL, "PRK", prk))if (ssl_trace >= (50)) ssl_PrintKey (((void*)0), "PRK", prk ); |
| 241 | PRINT_BUF(50, (NULL, "Hash", handshakeHash, handshakeHashLen))if (ssl_trace >= (50)) ssl_PrintBuf (((void*)0), "Hash", handshakeHash , handshakeHashLen); |
| 242 | PRINT_BUF(50, (NULL, "Info", SSL_BUFFER_BASE(&infoBuf),if (ssl_trace >= (50)) ssl_PrintBuf (((void*)0), "Info", ( (&infoBuf)->buf), ((&infoBuf)->len)) |
| 243 | SSL_BUFFER_LEN(&infoBuf)))if (ssl_trace >= (50)) ssl_PrintBuf (((void*)0), "Info", ( (&infoBuf)->buf), ((&infoBuf)->len)); |
| 244 | PRINT_KEY(50, (NULL, "Derived key", derived))if (ssl_trace >= (50)) ssl_PrintKey (((void*)0), "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_DERIVE0x0000402aUL, 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((void*)0); |
| 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_DATA0x0000402bUL, prk, baseHash, |
| 276 | handshakeHash, handshakeHashLen, |
| 277 | label, labelLen, CKM_HKDF_DERIVE0x0000402aUL, 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)((rawkey->len == outputLen)?((void)0):PR_Assert("rawkey->len == outputLen" ,"/root/firefox-clang/security/nss/lib/ssl/tls13hkdf.c",293)); |
| 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_SetErrorPORT_SetError_Util(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); |
| 304 | return SECFailure; |
| 305 | } |