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 |