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