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 |