mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-30 20:37:31 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
270
security/nss/lib/ssl/tls13hkdf.c
Normal file
270
security/nss/lib/ssl/tls13hkdf.c
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* TLS 1.3 Protocol
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "keyhi.h"
|
||||
#include "pk11func.h"
|
||||
#include "secitem.h"
|
||||
#include "ssl.h"
|
||||
#include "sslt.h"
|
||||
#include "sslerr.h"
|
||||
#include "sslimpl.h"
|
||||
|
||||
/* This table contains the mapping between TLS hash identifiers and the
|
||||
* PKCS#11 identifiers */
|
||||
static const struct {
|
||||
SSLHashType hash;
|
||||
CK_MECHANISM_TYPE pkcs11Mech;
|
||||
unsigned int hashSize;
|
||||
} kTlsHkdfInfo[] = {
|
||||
{ ssl_hash_none, 0, 0 },
|
||||
{ ssl_hash_md5, 0, 0 },
|
||||
{ ssl_hash_sha1, 0, 0 },
|
||||
{ ssl_hash_sha224, 0 },
|
||||
{ ssl_hash_sha256, CKM_NSS_HKDF_SHA256, 32 },
|
||||
{ ssl_hash_sha384, CKM_NSS_HKDF_SHA384, 48 },
|
||||
{ ssl_hash_sha512, CKM_NSS_HKDF_SHA512, 64 }
|
||||
};
|
||||
|
||||
SECStatus
|
||||
tls13_HkdfExtract(PK11SymKey *ikm1, PK11SymKey *ikm2in, SSLHashType baseHash,
|
||||
PK11SymKey **prkp)
|
||||
{
|
||||
CK_NSS_HKDFParams params;
|
||||
SECItem paramsi;
|
||||
SECStatus rv;
|
||||
SECItem *salt;
|
||||
PK11SymKey *prk;
|
||||
static const PRUint8 zeroKeyBuf[HASH_LENGTH_MAX];
|
||||
PK11SymKey *zeroKey = NULL;
|
||||
PK11SlotInfo *slot = NULL;
|
||||
PK11SymKey *ikm2;
|
||||
|
||||
params.bExtract = CK_TRUE;
|
||||
params.bExpand = CK_FALSE;
|
||||
params.pInfo = NULL;
|
||||
params.ulInfoLen = 0UL;
|
||||
|
||||
if (ikm1) {
|
||||
/* TODO(ekr@rtfm.com): This violates the PKCS#11 key boundary
|
||||
* but is imposed on us by the present HKDF interface. */
|
||||
rv = PK11_ExtractKeyValue(ikm1);
|
||||
if (rv != SECSuccess)
|
||||
return rv;
|
||||
|
||||
salt = PK11_GetKeyData(ikm1);
|
||||
if (!salt)
|
||||
return SECFailure;
|
||||
|
||||
params.pSalt = salt->data;
|
||||
params.ulSaltLen = salt->len;
|
||||
PORT_Assert(salt->len > 0);
|
||||
} else {
|
||||
/* Per documentation for CKM_NSS_HKDF_*:
|
||||
*
|
||||
* If the optional salt is given, it is used; otherwise, the salt is
|
||||
* set to a sequence of zeros equal in length to the HMAC output.
|
||||
*/
|
||||
params.pSalt = NULL;
|
||||
params.ulSaltLen = 0UL;
|
||||
}
|
||||
paramsi.data = (unsigned char *)¶ms;
|
||||
paramsi.len = sizeof(params);
|
||||
|
||||
PORT_Assert(kTlsHkdfInfo[baseHash].pkcs11Mech);
|
||||
PORT_Assert(kTlsHkdfInfo[baseHash].hashSize);
|
||||
PORT_Assert(kTlsHkdfInfo[baseHash].hash == baseHash);
|
||||
|
||||
/* A zero ikm2 is a key of hash-length 0s. */
|
||||
if (!ikm2in) {
|
||||
SECItem zeroItem = {
|
||||
siBuffer,
|
||||
(unsigned char *)zeroKeyBuf,
|
||||
kTlsHkdfInfo[baseHash].hashSize
|
||||
};
|
||||
slot = PK11_GetInternalSlot();
|
||||
if (!slot) {
|
||||
return SECFailure;
|
||||
}
|
||||
zeroKey = PK11_ImportSymKey(slot,
|
||||
kTlsHkdfInfo[baseHash].pkcs11Mech,
|
||||
PK11_OriginUnwrap,
|
||||
CKA_DERIVE, &zeroItem, NULL);
|
||||
if (!zeroKey)
|
||||
return SECFailure;
|
||||
ikm2 = zeroKey;
|
||||
} else {
|
||||
ikm2 = ikm2in;
|
||||
}
|
||||
PORT_Assert(ikm2);
|
||||
|
||||
PRINT_BUF(50, (NULL, "HKDF Extract: IKM1/Salt", params.pSalt, params.ulSaltLen));
|
||||
PRINT_KEY(50, (NULL, "HKDF Extract: IKM2", ikm2));
|
||||
|
||||
prk = PK11_Derive(ikm2, kTlsHkdfInfo[baseHash].pkcs11Mech,
|
||||
¶msi, kTlsHkdfInfo[baseHash].pkcs11Mech,
|
||||
CKA_DERIVE, kTlsHkdfInfo[baseHash].hashSize);
|
||||
if (zeroKey)
|
||||
PK11_FreeSymKey(zeroKey);
|
||||
if (slot)
|
||||
PK11_FreeSlot(slot);
|
||||
if (!prk)
|
||||
return SECFailure;
|
||||
|
||||
PRINT_KEY(50, (NULL, "HKDF Extract", prk));
|
||||
*prkp = prk;
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
tls13_HkdfExpandLabel(PK11SymKey *prk, SSLHashType baseHash,
|
||||
const PRUint8 *handshakeHash, unsigned int handshakeHashLen,
|
||||
const char *label, unsigned int labelLen,
|
||||
CK_MECHANISM_TYPE algorithm, unsigned int keySize,
|
||||
PK11SymKey **keyp)
|
||||
{
|
||||
CK_NSS_HKDFParams params;
|
||||
SECItem paramsi = { siBuffer, NULL, 0 };
|
||||
/* Size of info array needs to be big enough to hold the maximum Prefix,
|
||||
* Label, plus HandshakeHash. If it's ever to small, the code will abort.
|
||||
*/
|
||||
PRUint8 info[256];
|
||||
PRUint8 *ptr = info;
|
||||
unsigned int infoLen;
|
||||
PK11SymKey *derived;
|
||||
const char *kLabelPrefix = "TLS 1.3, ";
|
||||
const unsigned int kLabelPrefixLen = strlen(kLabelPrefix);
|
||||
|
||||
if (handshakeHash) {
|
||||
if (handshakeHashLen > 255) {
|
||||
PORT_Assert(0);
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
} else {
|
||||
PORT_Assert(!handshakeHashLen);
|
||||
}
|
||||
|
||||
/*
|
||||
* [draft-ietf-tls-tls13-11] Section 7.1:
|
||||
*
|
||||
* HKDF-Expand-Label(Secret, Label, HashValue, Length) =
|
||||
* HKDF-Expand(Secret, HkdfLabel, Length)
|
||||
*
|
||||
* Where HkdfLabel is specified as:
|
||||
*
|
||||
* struct HkdfLabel {
|
||||
* uint16 length;
|
||||
* opaque label<9..255>;
|
||||
* opaque hash_value<0..255>;
|
||||
* };
|
||||
*
|
||||
* Where:
|
||||
* - HkdfLabel.length is Length
|
||||
* - HkdfLabel.hash_value is HashValue.
|
||||
* - HkdfLabel.label is "TLS 1.3, " + Label
|
||||
*
|
||||
*/
|
||||
infoLen = 2 + 1 + kLabelPrefixLen + labelLen + 1 + handshakeHashLen;
|
||||
if (infoLen > sizeof(info)) {
|
||||
PORT_Assert(0);
|
||||
goto abort;
|
||||
}
|
||||
|
||||
ptr = ssl_EncodeUintX(keySize, 2, ptr);
|
||||
ptr = ssl_EncodeUintX(labelLen + kLabelPrefixLen, 1, ptr);
|
||||
PORT_Memcpy(ptr, kLabelPrefix, kLabelPrefixLen);
|
||||
ptr += kLabelPrefixLen;
|
||||
PORT_Memcpy(ptr, label, labelLen);
|
||||
ptr += labelLen;
|
||||
ptr = ssl_EncodeUintX(handshakeHashLen, 1, ptr);
|
||||
if (handshakeHash) {
|
||||
PORT_Memcpy(ptr, handshakeHash, handshakeHashLen);
|
||||
ptr += handshakeHashLen;
|
||||
}
|
||||
PORT_Assert((ptr - info) == infoLen);
|
||||
|
||||
params.bExtract = CK_FALSE;
|
||||
params.bExpand = CK_TRUE;
|
||||
params.pInfo = info;
|
||||
params.ulInfoLen = infoLen;
|
||||
paramsi.data = (unsigned char *)¶ms;
|
||||
paramsi.len = sizeof(params);
|
||||
|
||||
derived = PK11_DeriveWithFlags(prk, kTlsHkdfInfo[baseHash].pkcs11Mech,
|
||||
¶msi, algorithm,
|
||||
CKA_DERIVE, keySize,
|
||||
CKF_SIGN | CKF_VERIFY);
|
||||
if (!derived)
|
||||
return SECFailure;
|
||||
|
||||
*keyp = derived;
|
||||
|
||||
#ifdef TRACE
|
||||
if (ssl_trace >= 10) {
|
||||
/* Make sure the label is null terminated. */
|
||||
char labelStr[100];
|
||||
PORT_Memcpy(labelStr, label, labelLen);
|
||||
labelStr[labelLen] = 0;
|
||||
SSL_TRC(50, ("HKDF Expand: label=[TLS 1.3, ] + '%s',requested length=%d",
|
||||
labelStr, keySize));
|
||||
}
|
||||
PRINT_KEY(50, (NULL, "PRK", prk));
|
||||
PRINT_BUF(50, (NULL, "Hash", handshakeHash, handshakeHashLen));
|
||||
PRINT_BUF(50, (NULL, "Info", info, infoLen));
|
||||
PRINT_KEY(50, (NULL, "Derived key", derived));
|
||||
#endif
|
||||
|
||||
return SECSuccess;
|
||||
|
||||
abort:
|
||||
PORT_SetError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
tls13_HkdfExpandLabelRaw(PK11SymKey *prk, SSLHashType baseHash,
|
||||
const PRUint8 *handshakeHash, unsigned int handshakeHashLen,
|
||||
const char *label, unsigned int labelLen,
|
||||
unsigned char *output, unsigned int outputLen)
|
||||
{
|
||||
PK11SymKey *derived = NULL;
|
||||
SECItem *rawkey;
|
||||
SECStatus rv;
|
||||
|
||||
rv = tls13_HkdfExpandLabel(prk, baseHash, handshakeHash, handshakeHashLen,
|
||||
label, labelLen,
|
||||
kTlsHkdfInfo[baseHash].pkcs11Mech, outputLen,
|
||||
&derived);
|
||||
if (rv != SECSuccess || !derived) {
|
||||
goto abort;
|
||||
}
|
||||
|
||||
rv = PK11_ExtractKeyValue(derived);
|
||||
if (rv != SECSuccess) {
|
||||
goto abort;
|
||||
}
|
||||
|
||||
rawkey = PK11_GetKeyData(derived);
|
||||
if (!rawkey) {
|
||||
goto abort;
|
||||
}
|
||||
|
||||
PORT_Assert(rawkey->len == outputLen);
|
||||
memcpy(output, rawkey->data, outputLen);
|
||||
PK11_FreeSymKey(derived);
|
||||
|
||||
return SECSuccess;
|
||||
|
||||
abort:
|
||||
if (derived) {
|
||||
PK11_FreeSymKey(derived);
|
||||
}
|
||||
PORT_SetError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue