mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-21 15:57:31 +09:00
nss: update nss to hg rev e5e10a46b9ad with vc2013 hackfix
This commit is contained in:
parent
ed1b356dfa
commit
dcdc5d70e0
133 changed files with 8084 additions and 2038 deletions
274
security/nss/lib/ssl/sslprimitive.c
Normal file
274
security/nss/lib/ssl/sslprimitive.c
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* SSL Primitives: Public HKDF and AEAD Functions
|
||||
*
|
||||
* 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 "pk11pub.h"
|
||||
#include "sechash.h"
|
||||
#include "ssl.h"
|
||||
#include "sslexp.h"
|
||||
#include "sslerr.h"
|
||||
#include "sslproto.h"
|
||||
|
||||
#include "sslimpl.h"
|
||||
#include "tls13con.h"
|
||||
#include "tls13hkdf.h"
|
||||
|
||||
struct SSLAeadContextStr {
|
||||
CK_MECHANISM_TYPE mech;
|
||||
ssl3KeyMaterial keys;
|
||||
};
|
||||
|
||||
static SECStatus
|
||||
tls13_GetHashAndCipher(PRUint16 version, PRUint16 cipherSuite,
|
||||
SSLHashType *hash, const ssl3BulkCipherDef **cipher)
|
||||
{
|
||||
if (version < SSL_LIBRARY_VERSION_TLS_1_3) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
// Lookup and check the suite.
|
||||
SSLVersionRange vrange = { version, version };
|
||||
if (!ssl3_CipherSuiteAllowedForVersionRange(cipherSuite, &vrange)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
const ssl3CipherSuiteDef *suiteDef = ssl_LookupCipherSuiteDef(cipherSuite);
|
||||
const ssl3BulkCipherDef *cipherDef = ssl_GetBulkCipherDef(suiteDef);
|
||||
if (cipherDef->type != type_aead) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
*hash = suiteDef->prf_hash;
|
||||
if (cipher != NULL) {
|
||||
*cipher = cipherDef;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
SSLExp_MakeAead(PRUint16 version, PRUint16 cipherSuite, PK11SymKey *secret,
|
||||
const char *labelPrefix, unsigned int labelPrefixLen,
|
||||
SSLAeadContext **ctx)
|
||||
{
|
||||
SSLAeadContext *out = NULL;
|
||||
char label[255]; // Maximum length label.
|
||||
static const char *const keySuffix = "key";
|
||||
static const char *const ivSuffix = "iv";
|
||||
|
||||
PORT_Assert(strlen(keySuffix) >= strlen(ivSuffix));
|
||||
if (secret == NULL || ctx == NULL ||
|
||||
(labelPrefix == NULL && labelPrefixLen > 0) ||
|
||||
labelPrefixLen + strlen(keySuffix) > sizeof(label)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
goto loser;
|
||||
}
|
||||
|
||||
SSLHashType hash;
|
||||
const ssl3BulkCipherDef *cipher;
|
||||
SECStatus rv = tls13_GetHashAndCipher(version, cipherSuite,
|
||||
&hash, &cipher);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser; /* Code already set. */
|
||||
}
|
||||
|
||||
out = PORT_ZNew(SSLAeadContext);
|
||||
if (out == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
out->mech = ssl3_Alg2Mech(cipher->calg);
|
||||
|
||||
memcpy(label, labelPrefix, labelPrefixLen);
|
||||
memcpy(label + labelPrefixLen, ivSuffix, strlen(ivSuffix));
|
||||
unsigned int labelLen = labelPrefixLen + strlen(ivSuffix);
|
||||
unsigned int ivLen = cipher->iv_size + cipher->explicit_nonce_size;
|
||||
rv = tls13_HkdfExpandLabelRaw(secret, hash,
|
||||
NULL, 0, // Handshake hash.
|
||||
label, labelLen,
|
||||
out->keys.iv, ivLen);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
memcpy(label + labelPrefixLen, keySuffix, strlen(keySuffix));
|
||||
labelLen = labelPrefixLen + strlen(keySuffix);
|
||||
rv = tls13_HkdfExpandLabel(secret, hash,
|
||||
NULL, 0, // Handshake hash.
|
||||
label, labelLen,
|
||||
out->mech, cipher->key_size, &out->keys.key);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
*ctx = out;
|
||||
return SECSuccess;
|
||||
|
||||
loser:
|
||||
SSLExp_DestroyAead(out);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
SSLExp_DestroyAead(SSLAeadContext *ctx)
|
||||
{
|
||||
if (!ctx) {
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
PK11_FreeSymKey(ctx->keys.key);
|
||||
PORT_ZFree(ctx, sizeof(*ctx));
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* Bug 1529440 exists to refactor this and the other AEAD uses. */
|
||||
static SECStatus
|
||||
ssl_AeadInner(const SSLAeadContext *ctx, PRBool decrypt, PRUint64 counter,
|
||||
const PRUint8 *aad, unsigned int aadLen,
|
||||
const PRUint8 *plaintext, unsigned int plaintextLen,
|
||||
PRUint8 *out, unsigned int *outLen, unsigned int maxOut)
|
||||
{
|
||||
if (ctx == NULL || (aad == NULL && aadLen > 0) || plaintext == NULL ||
|
||||
out == NULL || outLen == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
// Setup the nonce.
|
||||
PRUint8 nonce[12] = { 0 };
|
||||
sslBuffer nonceBuf = SSL_BUFFER_FIXED(nonce + sizeof(nonce) - sizeof(counter),
|
||||
sizeof(counter));
|
||||
SECStatus rv = sslBuffer_AppendNumber(&nonceBuf, counter, sizeof(counter));
|
||||
if (rv != SECSuccess) {
|
||||
PORT_Assert(0);
|
||||
return SECFailure;
|
||||
}
|
||||
for (int i = 0; i < sizeof(nonce); ++i) {
|
||||
nonce[i] ^= ctx->keys.iv[i];
|
||||
}
|
||||
|
||||
// Build AEAD parameters.
|
||||
CK_GCM_PARAMS gcmParams = { 0 };
|
||||
CK_NSS_AEAD_PARAMS aeadParams = { 0 };
|
||||
unsigned char *params;
|
||||
unsigned int paramsLen;
|
||||
switch (ctx->mech) {
|
||||
case CKM_AES_GCM:
|
||||
gcmParams.pIv = nonce;
|
||||
gcmParams.ulIvLen = sizeof(nonce);
|
||||
gcmParams.pAAD = (unsigned char *)aad; // const cast :(
|
||||
gcmParams.ulAADLen = aadLen;
|
||||
gcmParams.ulTagBits = 128; // GCM measures in bits.
|
||||
params = (unsigned char *)&gcmParams;
|
||||
paramsLen = sizeof(gcmParams);
|
||||
break;
|
||||
|
||||
case CKM_NSS_CHACHA20_POLY1305:
|
||||
aeadParams.pNonce = nonce;
|
||||
aeadParams.ulNonceLen = sizeof(nonce);
|
||||
aeadParams.pAAD = (unsigned char *)aad; // const cast :(
|
||||
aeadParams.ulAADLen = aadLen;
|
||||
aeadParams.ulTagLen = 16; // AEAD measures in octets.
|
||||
params = (unsigned char *)&aeadParams;
|
||||
paramsLen = sizeof(aeadParams);
|
||||
break;
|
||||
|
||||
default:
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
return tls13_AEAD(&ctx->keys, decrypt, out, outLen, maxOut,
|
||||
plaintext, plaintextLen, ctx->mech, params, paramsLen);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
SSLExp_AeadEncrypt(const SSLAeadContext *ctx, PRUint64 counter,
|
||||
const PRUint8 *aad, unsigned int aadLen,
|
||||
const PRUint8 *plaintext, unsigned int plaintextLen,
|
||||
PRUint8 *out, unsigned int *outLen, unsigned int maxOut)
|
||||
{
|
||||
// false == encrypt
|
||||
return ssl_AeadInner(ctx, PR_FALSE, counter, aad, aadLen,
|
||||
plaintext, plaintextLen, out, outLen, maxOut);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
SSLExp_AeadDecrypt(const SSLAeadContext *ctx, PRUint64 counter,
|
||||
const PRUint8 *aad, unsigned int aadLen,
|
||||
const PRUint8 *plaintext, unsigned int plaintextLen,
|
||||
PRUint8 *out, unsigned int *outLen, unsigned int maxOut)
|
||||
{
|
||||
// true == decrypt
|
||||
return ssl_AeadInner(ctx, PR_TRUE, counter, aad, aadLen,
|
||||
plaintext, plaintextLen, out, outLen, maxOut);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
SSLExp_HkdfExtract(PRUint16 version, PRUint16 cipherSuite,
|
||||
PK11SymKey *salt, PK11SymKey *ikm, PK11SymKey **keyp)
|
||||
{
|
||||
if (keyp == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
SSLHashType hash;
|
||||
SECStatus rv = tls13_GetHashAndCipher(version, cipherSuite,
|
||||
&hash, NULL);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure; /* Code already set. */
|
||||
}
|
||||
return tls13_HkdfExtract(salt, ikm, hash, keyp);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
SSLExp_HkdfExpandLabel(PRUint16 version, PRUint16 cipherSuite, PK11SymKey *prk,
|
||||
const PRUint8 *hsHash, unsigned int hsHashLen,
|
||||
const char *label, unsigned int labelLen,
|
||||
PK11SymKey **keyp)
|
||||
{
|
||||
if (prk == NULL || keyp == NULL ||
|
||||
label == NULL || labelLen == 0) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
SSLHashType hash;
|
||||
SECStatus rv = tls13_GetHashAndCipher(version, cipherSuite,
|
||||
&hash, NULL);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure; /* Code already set. */
|
||||
}
|
||||
return tls13_HkdfExpandLabel(prk, hash, hsHash, hsHashLen, label, labelLen,
|
||||
tls13_GetHkdfMechanismForHash(hash),
|
||||
tls13_GetHashSizeForHash(hash), keyp);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
SSLExp_HkdfExpandLabelWithMech(PRUint16 version, PRUint16 cipherSuite, PK11SymKey *prk,
|
||||
const PRUint8 *hsHash, unsigned int hsHashLen,
|
||||
const char *label, unsigned int labelLen,
|
||||
CK_MECHANISM_TYPE mech, unsigned int keySize,
|
||||
PK11SymKey **keyp)
|
||||
{
|
||||
if (prk == NULL || keyp == NULL ||
|
||||
label == NULL || labelLen == 0 ||
|
||||
mech == CKM_INVALID_MECHANISM || keySize == 0) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
SSLHashType hash;
|
||||
SECStatus rv = tls13_GetHashAndCipher(version, cipherSuite,
|
||||
&hash, NULL);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure; /* Code already set. */
|
||||
}
|
||||
return tls13_HkdfExpandLabel(prk, hash, hsHash, hsHashLen, label, labelLen,
|
||||
mech, keySize, keyp);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue