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 | } |