nss: update nss to hg rev e5e10a46b9ad with vc2013 hackfix

This commit is contained in:
2019-04-04 20:47:34 +08:00
parent 067eb934c1
commit 811e2980a1
133 changed files with 8077 additions and 2031 deletions
+42 -50
View File
@@ -1,47 +1,37 @@
# This file is rendered via JSON-e in a hook with context:
# {
# tasks_for: 'hg-push',
# push: {owner, pushlog_id, pushdate},
# repository: {url, project, level},
# now,
# ownTaskId: // taskId of the task that will be created
# }
---
version: 0
metadata:
name: "NSS Continuous Integration"
description: "The Taskcluster task graph for the NSS tree"
owner: "mozilla-taskcluster-maintenance@mozilla.com"
source: {{{source}}}
scopes:
# Note the below scopes are insecure however these get overriden on the server
# side to whatever scopes are set by mozilla-taskcluster.
- queue:*
- docker-worker:*
- scheduler:*
# Available mustache parameters (see the mozilla-taskcluster source):
#
# - owner: push user (email address)
# - source: URL of this YAML file
# - url: repository URL
# - project: alias for the destination repository (basename of
# the repo url)
# - level: SCM level of the destination repository
# (1 = try, 3 = core)
# - revision: (short) hg revision of the head of the push
# - revision_hash: (long) hg revision of the head of the push
# - comment: comment of the push
# - pushlog_id: id in the pushlog table of the repository
#
# and functions:
# - as_slugid: convert a label into a slugId
# - from_now: generate a timestamp at a fixed offset from now
version: 1
tasks:
- taskId: '{{#as_slugid}}decision task{{/as_slugid}}'
reruns: 3
task:
created: '{{now}}'
deadline: '{{#from_now}}1 day{{/from_now}}'
expires: '{{#from_now}}14 days{{/from_now}}'
- $let:
# sometimes the push user is just `ffxbld` or the like, but we want an
# email-like field..
ownerEmail:
$if: '"@" in push.owner'
then: '${push.owner}'
else: '${push.owner}@noreply.mozilla.org'
# ensure there's no trailing `/` on the repo URL
repoUrl:
$if: 'repository.url[-1] == "/"'
then: {$eval: 'repository.url[:-1]'}
else: {$eval: 'repository.url'}
in:
taskId: '${ownTaskId}'
taskGroupId: '${ownTaskId}'
schedulerId: 'nss-level-${repository.level}'
created: {$fromNow: ''}
deadline: {$fromNow: '1 day'}
expires: {$fromNow: '14 days'}
metadata:
owner: mozilla-taskcluster-maintenance@mozilla.com
source: {{{source}}}
source: "${repository.url}"
name: "NSS Decision Task"
description: |
The task that creates all of the other tasks in the task graph
@@ -49,24 +39,26 @@ tasks:
workerType: "hg-worker"
provisionerId: "aws-provisioner-v1"
scopes:
- 'assume:repo:${repoUrl[8:]}:branch:default'
tags:
createdForUser: {{owner}}
createdForUser: "${ownerEmail}"
routes:
- "tc-treeherder-stage.v2.{{project}}.{{revision}}.{{pushlog_id}}"
- "tc-treeherder.v2.{{project}}.{{revision}}.{{pushlog_id}}"
- "tc-treeherder-stage.v2.${repository.project}.${push.revision}.${push.pushlog_id}"
- "tc-treeherder.v2.${repository.project}.${push.revision}.${push.pushlog_id}"
payload:
image: nssdev/nss-decision:0.0.2
# TODO: use nssdev org , not djmitche, once the image is pushed there
image: djmitche/nss-decision:0.0.3
env:
TC_OWNER: {{owner}}
TC_SOURCE: {{{source}}}
TC_PROJECT: {{project}}
TC_COMMENT: '{{comment}}'
NSS_PUSHLOG_ID: '{{pushlog_id}}'
NSS_HEAD_REPOSITORY: '{{{url}}}'
NSS_HEAD_REVISION: '{{revision}}'
TC_OWNER: "${push.owner}"
TC_SOURCE: "${repository.url}"
TC_PROJECT: ${repository.project}
NSS_PUSHLOG_ID: '${push.pushlog_id}'
NSS_HEAD_REPOSITORY: '${repository.url}'
NSS_HEAD_REVISION: '${push.revision}'
maxRunTime: 1800
@@ -1,5 +1,5 @@
1 Added function:
'function SECOidTag HASH_GetHashOidTagByHashType(HASH_HashType)' {HASH_GetHashOidTagByHashType@@NSS_3.43}
'function SECStatus CERT_GetCertificateDer(const CERTCertificate*, SECItem*)' {CERT_GetCertificateDer@@NSS_3.44}
@@ -1 +1 @@
NSS_3_42_BRANCH
NSS_3_43_BRANCH
@@ -9,6 +9,7 @@ RUN apt-get update \
locales \
mercurial \
nodejs \
npm \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get autoremove -y && apt-get clean -y
File diff suppressed because it is too large Load Diff
@@ -5,10 +5,17 @@
import * as try_syntax from "./try_syntax";
import extend from "./extend";
// Init try syntax filter.
if (process.env.TC_PROJECT == "nss-try") {
try_syntax.initFilter();
}
const main = async () => {
// Init try syntax filter.
if (process.env.TC_PROJECT == "nss-try") {
await try_syntax.initFilter();
}
// Extend the task graph.
extend().catch(console.error);
// Extend the task graph.
await extend();
};
main().catch(err => {
console.error(err);
process.exit(1);
});
@@ -5,6 +5,10 @@
import * as queue from "./queue";
import intersect from "intersect";
import parse_args from "minimist";
import util from "util";
import child_process from 'child_process';
let execFile = util.promisify(child_process.execFile);
function parseOptions(opts) {
opts = parse_args(opts.split(/\s+/), {
@@ -154,8 +158,13 @@ function filter(opts) {
}
}
export function initFilter() {
let comment = process.env.TC_COMMENT || "";
async function getCommitComment() {
const res = await execFile('hg', ['log', '-r', '.', '-T', '{desc}']);
return res.stdout;
};
export async function initFilter() {
let comment = await getCommitComment();
// Check for try syntax in changeset comment.
let match = comment.match(/^\s*try:\s*(.*)\s*$/);
+1
View File
@@ -103,6 +103,7 @@ while [ $# -gt 0 ]; do
--enable-fips) gyp_params+=(-Ddisable_fips=0) ;;
--enable-libpkix) gyp_params+=(-Ddisable_libpkix=0) ;;
--mozpkix-only) gyp_params+=(-Dmozpkix_only=1 -Ddisable_tests=1 -Dsign_libs=0) ;;
-D*) gyp_params+=("$1") ;;
*) show_help; exit 2 ;;
esac
shift
+25 -11
View File
@@ -105,7 +105,6 @@ Usage(char *progName)
"-i input");
fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
"-o output");
exit(-1);
}
int
@@ -113,12 +112,12 @@ main(int argc, char **argv)
{
char *progName;
SECStatus rv;
FILE *inFile, *outFile;
PLOptState *optstate;
FILE *inFile = NULL, *outFile = NULL;
PRBool closeIn = PR_TRUE, closeOut = PR_TRUE;
PLOptState *optstate = NULL;
PLOptStatus status;
int exitCode = -1;
inFile = 0;
outFile = 0;
progName = strrchr(argv[0], '/');
progName = progName ? progName + 1 : argv[0];
@@ -129,6 +128,7 @@ main(int argc, char **argv)
case '?':
case 'h':
Usage(progName);
goto loser;
break;
case 'i':
@@ -136,7 +136,7 @@ main(int argc, char **argv)
if (!inFile) {
fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
progName, optstate->value);
return -1;
goto loser;
}
break;
@@ -145,13 +145,15 @@ main(int argc, char **argv)
if (!outFile) {
fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
progName, optstate->value);
return -1;
goto loser;
}
break;
}
}
if (!inFile)
if (!inFile) {
inFile = stdin;
closeIn = PR_FALSE;
}
if (!outFile) {
#if defined(WIN32)
int smrv = _setmode(_fileno(stdout), _O_BINARY);
@@ -159,16 +161,28 @@ main(int argc, char **argv)
fprintf(stderr,
"%s: Cannot change stdout to binary mode. Use -o option instead.\n",
progName);
return smrv;
goto loser;
}
#endif
outFile = stdout;
closeOut = PR_FALSE;
}
rv = decode_file(outFile, inFile);
if (rv != SECSuccess) {
fprintf(stderr, "%s: lossage: error=%d errno=%d\n",
progName, PORT_GetError(), errno);
return -1;
goto loser;
}
return 0;
exitCode = 0;
loser:
if (optstate) {
PL_DestroyOptState(optstate);
}
if (inFile && closeIn) {
fclose(inFile);
}
if (outFile && closeOut) {
fclose(outFile);
}
return exitCode;
}
+24 -11
View File
@@ -99,7 +99,6 @@ Usage(char *progName)
"-w suffix");
fprintf(stderr, "%-20s (use \"c\" as a shortcut for suffix CERTIFICATE)\n",
"");
exit(-1);
}
int
@@ -107,13 +106,13 @@ main(int argc, char **argv)
{
char *progName;
SECStatus rv;
FILE *inFile, *outFile;
PLOptState *optstate;
FILE *inFile = NULL, *outFile = NULL;
PRBool closeIn = PR_TRUE, closeOut = PR_TRUE;
PLOptState *optstate = NULL;
PLOptStatus status;
char *suffix = NULL;
int exitCode = -1;
inFile = 0;
outFile = 0;
progName = strrchr(argv[0], '/');
if (!progName)
progName = strrchr(argv[0], '\\');
@@ -125,6 +124,7 @@ main(int argc, char **argv)
switch (optstate->option) {
default:
Usage(progName);
goto loser;
break;
case 'i':
@@ -132,7 +132,7 @@ main(int argc, char **argv)
if (!inFile) {
fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
progName, optstate->value);
return -1;
goto loser;
}
break;
@@ -141,7 +141,7 @@ main(int argc, char **argv)
if (!outFile) {
fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
progName, optstate->value);
return -1;
goto loser;
}
break;
@@ -166,10 +166,11 @@ main(int argc, char **argv)
fprintf(stderr,
"%s: Cannot change stdin to binary mode. Use -i option instead.\n",
progName);
return smrv;
goto loser;
}
#endif
inFile = stdin;
closeIn = PR_FALSE;
}
if (!outFile) {
#if defined(WIN32)
@@ -182,10 +183,11 @@ main(int argc, char **argv)
fprintf(stderr,
"%s: Cannot change stdout to binary mode. Use -o option instead.\n",
progName);
return smrv;
goto loser;
}
#endif
outFile = stdout;
closeOut = PR_FALSE;
}
if (suffix) {
fprintf(outFile, "-----BEGIN %s-----\n", suffix);
@@ -194,10 +196,21 @@ main(int argc, char **argv)
if (rv != SECSuccess) {
fprintf(stderr, "%s: lossage: error=%d errno=%d\n",
progName, PORT_GetError(), errno);
return -1;
goto loser;
}
if (suffix) {
fprintf(outFile, "-----END %s-----\n", suffix);
}
return 0;
exitCode = 0;
loser:
if (optstate) {
PL_DestroyOptState(optstate);
}
if (inFile && closeIn) {
fclose(inFile);
}
if (outFile && closeOut) {
fclose(outFile);
}
return exitCode;
}
+1
View File
@@ -56,6 +56,7 @@ NSS_SRCDIRS = \
p7sign \
p7verify \
pk12util \
pk11importtest \
pk11ectest \
pk11gcmtest \
pk11mode \
+43
View File
@@ -0,0 +1,43 @@
#! gmake
#
# 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/.
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
include ../platlibs.mk
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
include ../platrules.mk
@@ -0,0 +1,15 @@
# 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/.
CORE_DEPTH = ../..
MODULE = nss
CSRCS = pk11importtest.c \
$(NULL)
REQUIRES = seccmd
PROGRAM = pk11importtest
@@ -0,0 +1,406 @@
/* 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 "secutil.h"
#include "secmod.h"
#include "cert.h"
#include "secoid.h"
#include "nss.h"
#include "pk11pub.h"
#include "pk11pqg.h"
/* NSPR 2.0 header files */
#include "prinit.h"
#include "prprf.h"
#include "prsystem.h"
#include "prmem.h"
/* Portable layer header files */
#include "plstr.h"
SECOidData *
getCurveFromString(char *curve_name)
{
SECOidTag tag = SEC_OID_SECG_EC_SECP256R1;
if (PORT_Strcasecmp(curve_name, "NISTP256") == 0) {
} else if (PORT_Strcasecmp(curve_name, "NISTP384") == 0) {
tag = SEC_OID_SECG_EC_SECP384R1;
} else if (PORT_Strcasecmp(curve_name, "NISTP521") == 0) {
tag = SEC_OID_SECG_EC_SECP521R1;
} else if (PORT_Strcasecmp(curve_name, "Curve25519") == 0) {
tag = SEC_OID_CURVE25519;
}
return SECOID_FindOIDByTag(tag);
}
void
dumpItem(const char *label, const SECItem *item)
{
int i;
printf("%s = [%d bytes] {", label, item->len);
for (i = 0; i < item->len; i++) {
if ((i & 0xf) == 0)
printf("\n ");
else
printf(", ");
printf("%02x", item->data[i]);
}
printf("};\n");
}
SECStatus
handleEncryptedPrivateImportTest(char *progName, PK11SlotInfo *slot,
char *testname, CK_MECHANISM_TYPE genMech, void *params, void *pwArgs)
{
SECStatus rv = SECSuccess;
SECItem privID = { 0 };
SECItem pubID = { 0 };
SECItem pubValue = { 0 };
SECItem pbePwItem = { 0 };
SECItem nickname = { 0 };
SECItem token = { 0 };
SECKEYPublicKey *pubKey = NULL;
SECKEYPrivateKey *privKey = NULL;
PK11GenericObject *objs = NULL;
PK11GenericObject *obj = NULL;
SECKEYEncryptedPrivateKeyInfo *epki = NULL;
PRBool keyFound = 0;
KeyType keyType;
fprintf(stderr, "Testing %s PrivateKeyImport ***********************\n",
testname);
/* generate a temp key */
privKey = PK11_GenerateKeyPair(slot, genMech, params, &pubKey,
PR_FALSE, PR_TRUE, pwArgs);
if (privKey == NULL) {
SECU_PrintError(progName, "PK11_GenerateKeyPair Failed");
goto cleanup;
}
/* wrap the temp key */
pbePwItem.data = (unsigned char *)"pw";
pbePwItem.len = 2;
epki = PK11_ExportEncryptedPrivKeyInfo(slot, SEC_OID_AES_256_CBC,
&pbePwItem, privKey, 1, NULL);
if (epki == NULL) {
SECU_PrintError(progName, "PK11_ExportEncryptedPrivKeyInfo Failed");
goto cleanup;
}
/* Save the public value, which we will need on import */
keyType = pubKey->keyType;
switch (keyType) {
case rsaKey:
SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.rsa.modulus);
break;
case dhKey:
SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.dh.publicValue);
break;
case dsaKey:
SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.dsa.publicValue);
break;
case ecKey:
SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.ec.publicValue);
break;
default:
fprintf(stderr, "Unknown keytype = %d\n", keyType);
goto cleanup;
}
if (pubValue.data == NULL) {
SECU_PrintError(progName, "Unable to allocate memory");
goto cleanup;
}
dumpItem("pubValue", &pubValue);
/* when Asymetric keys represent session keys, those session keys are
* destroyed when we destroy the Asymetric key representations */
SECKEY_DestroyPublicKey(pubKey);
pubKey = NULL;
SECKEY_DestroyPrivateKey(privKey);
privKey = NULL;
/* unwrap the temp key as a perm */
nickname.data = (unsigned char *)"testKey";
nickname.len = sizeof("testKey");
rv = PK11_ImportEncryptedPrivateKeyInfoAndReturnKey(
slot, epki, &pbePwItem, &nickname, &pubValue,
PR_TRUE, PR_TRUE, keyType, 0, &privKey, NULL);
if (rv != SECSuccess) {
SECU_PrintError(progName, "PK11_ImportEncryptedPrivateKeyInfo Failed");
goto cleanup;
}
/* verify the public key exists */
rv = PK11_ReadRawAttribute(PK11_TypePrivKey, privKey, CKA_ID, &privID);
if (rv != SECSuccess) {
SECU_PrintError(progName,
"Couldn't read CKA_ID from pub key, checking next key");
goto cleanup;
}
dumpItem("privKey CKA_ID", &privID);
objs = PK11_FindGenericObjects(slot, CKO_PUBLIC_KEY);
for (obj = objs; obj; obj = PK11_GetNextGenericObject(obj)) {
rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, CKA_ID, &pubID);
if (rv != SECSuccess) {
SECU_PrintError(progName,
"Couldn't read CKA_ID from object, checking next key");
continue;
}
dumpItem("pubKey CKA_ID", &pubID);
if (!SECITEM_ItemsAreEqual(&privID, &pubID)) {
fprintf(stderr,
"CKA_ID does not match priv key, checking next key\n");
SECITEM_FreeItem(&pubID, PR_FALSE);
continue;
}
SECITEM_FreeItem(&pubID, PR_FALSE);
rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, CKA_TOKEN, &token);
if (rv == SECSuccess) {
if (token.len == 1) {
keyFound = token.data[0];
}
SECITEM_FreeItem(&token, PR_FALSE);
}
if (keyFound) {
printf("matching public key found\n");
break;
}
printf("Matching key was not a token key, checking next key\n");
}
cleanup:
if (objs) {
PK11_DestroyGenericObjects(objs);
}
SECITEM_FreeItem(&pubValue, PR_FALSE);
SECITEM_FreeItem(&privID, PR_FALSE);
PORT_FreeArena(epki->arena, PR_TRUE);
SECKEY_DestroyPublicKey(pubKey);
SECKEY_DestroyPrivateKey(privKey);
fprintf(stderr, "%s PrivateKeyImport %s ***********************\n",
testname, keyFound ? "PASSED" : "FAILED");
return keyFound ? SECSuccess : SECFailure;
}
static const char *const usageInfo[] = {
"pk11import - test PK11_PrivateKeyImport()"
"Options:",
" -d certdir directory containing cert database",
" -k keysize size of the rsa, dh, and dsa key to test (default 1024)",
" -C ecc_curve ecc curve (default )",
" -f pwFile file to fetch the password from",
" -p pwString password",
" -r skip rsa test",
" -D skip dsa test",
" -h skip dh test",
" -e skip ec test",
};
static int nUsageInfo = sizeof(usageInfo) / sizeof(char *);
static void
Usage(char *progName, FILE *outFile)
{
int i;
fprintf(outFile, "Usage: %s [ commands ] options\n", progName);
for (i = 0; i < nUsageInfo; i++)
fprintf(outFile, "%s\n", usageInfo[i]);
exit(-1);
}
enum {
opt_CertDir,
opt_KeySize,
opt_ECCurve,
opt_PWFile,
opt_PWString,
opt_NoRSA,
opt_NoDSA,
opt_NoEC,
opt_NoDH
};
static secuCommandFlag options[] =
{
{ /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE },
{ /* opt_KeySize */ 'k', PR_TRUE, 0, PR_FALSE },
{ /* opt_ECCurve */ 'C', PR_TRUE, 0, PR_FALSE },
{ /* opt_PWFile */ 'f', PR_TRUE, 0, PR_FALSE },
{ /* opt_PWString */ 'p', PR_TRUE, 0, PR_FALSE },
{ /* opt_NORSA */ 'r', PR_TRUE, 0, PR_FALSE },
{ /* opt_NoDSA */ 'D', PR_TRUE, 0, PR_FALSE },
{ /* opt_NoDH */ 'h', PR_TRUE, 0, PR_FALSE },
{ /* opt_NoEC */ 'e', PR_TRUE, 0, PR_FALSE },
};
int
main(int argc, char **argv)
{
char *progName;
SECStatus rv;
secuCommand args;
PK11SlotInfo *slot = NULL;
PRBool failed = PR_FALSE;
secuPWData pwArgs = { PW_NONE, 0 };
PRBool doRSA = PR_TRUE;
PRBool doDSA = PR_TRUE;
PRBool doDH = PR_FALSE; /* NSS currently can't export wrapped DH keys */
PRBool doEC = PR_TRUE;
PQGParams *pqgParams = NULL;
int keySize;
args.numCommands = 0;
args.numOptions = sizeof(options) / sizeof(secuCommandFlag);
args.commands = NULL;
args.options = options;
#ifdef XP_PC
progName = strrchr(argv[0], '\\');
#else
progName = strrchr(argv[0], '/');
#endif
progName = progName ? progName + 1 : argv[0];
rv = SECU_ParseCommandLine(argc, argv, progName, &args);
if (SECSuccess != rv) {
Usage(progName, stderr);
}
/* Set the certdb directory (default is ~/.netscape) */
rv = NSS_InitReadWrite(SECU_ConfigDirectory(args.options[opt_CertDir].arg));
if (rv != SECSuccess) {
SECU_PrintPRandOSError(progName);
return 255;
}
PK11_SetPasswordFunc(SECU_GetModulePassword);
/* below here, goto cleanup */
SECU_RegisterDynamicOids();
/* handle the arguments */
if (args.options[opt_PWFile].arg) {
pwArgs.source = PW_FROMFILE;
pwArgs.data = args.options[opt_PWFile].arg;
}
if (args.options[opt_PWString].arg) {
pwArgs.source = PW_PLAINTEXT;
pwArgs.data = args.options[opt_PWString].arg;
}
if (args.options[opt_NoRSA].activated) {
doRSA = PR_FALSE;
}
if (args.options[opt_NoDSA].activated) {
doDSA = PR_FALSE;
}
if (args.options[opt_NoDH].activated) {
doDH = PR_FALSE;
}
if (args.options[opt_NoEC].activated) {
doEC = PR_FALSE;
}
slot = PK11_GetInternalKeySlot();
if (slot == NULL) {
SECU_PrintError(progName, "Couldn't find the internal key slot\n");
return 255;
}
rv = PK11_Authenticate(slot, PR_TRUE, &pwArgs);
if (rv != SECSuccess) {
SECU_PrintError(progName, "Failed to log into slot");
PK11_FreeSlot(slot);
return 255;
}
keySize = 1024;
if (args.options[opt_KeySize].activated &&
args.options[opt_KeySize].arg) {
keySize = atoi(args.options[opt_KeySize].arg);
}
if (doDSA || doDH) {
PQGVerify *pqgVfy;
rv = PK11_PQG_ParamGenV2(keySize, 0, keySize / 16, &pqgParams, &pqgVfy);
if (rv == SECSuccess) {
PK11_PQG_DestroyVerify(pqgVfy);
} else {
SECU_PrintError(progName,
"PK11_PQG_ParamGenV2 failed, can't test DH or DSA");
doDSA = doDH = PR_FALSE;
failed = PR_TRUE;
}
}
if (doRSA) {
PK11RSAGenParams rsaParams;
rsaParams.keySizeInBits = keySize;
rsaParams.pe = 0x010001;
rv = handleEncryptedPrivateImportTest(progName, slot, "RSA",
CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaParams, &pwArgs);
if (rv != SECSuccess) {
fprintf(stderr, "RSA Import Failed!\n");
failed = PR_TRUE;
}
}
if (doDSA) {
rv = handleEncryptedPrivateImportTest(progName, slot, "DSA",
CKM_DSA_KEY_PAIR_GEN, pqgParams, &pwArgs);
if (rv != SECSuccess) {
fprintf(stderr, "DSA Import Failed!\n");
failed = PR_TRUE;
}
}
if (doDH) {
SECKEYDHParams dhParams;
dhParams.prime = pqgParams->prime;
dhParams.base = pqgParams->base;
rv = handleEncryptedPrivateImportTest(progName, slot, "DH",
CKM_DH_PKCS_KEY_PAIR_GEN, &dhParams, &pwArgs);
if (rv != SECSuccess) {
fprintf(stderr, "DH Import Failed!\n");
failed = PR_TRUE;
}
}
if (doEC) {
SECKEYECParams ecParams;
SECOidData *curve = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1);
if (args.options[opt_ECCurve].activated &&
args.options[opt_ECCurve].arg) {
curve = getCurveFromString(args.options[opt_ECCurve].arg);
}
ecParams.data = PORT_Alloc(curve->oid.len + 2);
if (ecParams.data == NULL) {
rv = SECFailure;
goto ec_failed;
}
ecParams.data[0] = SEC_ASN1_OBJECT_ID;
ecParams.data[1] = (unsigned char)curve->oid.len;
PORT_Memcpy(&ecParams.data[2], curve->oid.data, curve->oid.len);
ecParams.len = curve->oid.len + 2;
rv = handleEncryptedPrivateImportTest(progName, slot, "ECC",
CKM_EC_KEY_PAIR_GEN, &ecParams, &pwArgs);
PORT_Free(ecParams.data);
ec_failed:
if (rv != SECSuccess) {
fprintf(stderr, "ECC Import Failed!\n");
failed = PR_TRUE;
}
}
if (pqgParams) {
PK11_PQG_DestroyParams(pqgParams);
}
if (slot) {
PK11_FreeSlot(slot);
}
rv = NSS_Shutdown();
if (rv != SECSuccess) {
fprintf(stderr, "Shutdown failed\n");
SECU_PrintPRandOSError(progName);
return 255;
}
return failed ? 1 : 0;
}
@@ -0,0 +1,25 @@
# 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/.
{
'includes': [
'../../coreconf/config.gypi',
'../../cmd/platlibs.gypi'
],
'targets': [
{
'target_name': 'pk11importtest',
'type': 'executable',
'sources': [
'pk11importtest.c'
],
'dependencies': [
'<(DEPTH)/exports.gyp:dbm_exports',
'<(DEPTH)/exports.gyp:nss_exports'
]
}
],
'variables': {
'module': 'nss'
}
}
+36 -3
View File
@@ -121,6 +121,9 @@ static PRBool enableCertStatus = PR_FALSE;
PRIntervalTime maxInterval = PR_INTERVAL_NO_TIMEOUT;
static const SSLSignatureScheme *enabledSigSchemes = NULL;
static unsigned int enabledSigSchemeCount = 0;
char *progName;
secuPWData pwdata = { PW_NONE, 0 };
@@ -143,7 +146,8 @@ Usage(void)
"Usage: %s [-n nickname] [-p port] [-d dbdir] [-c connections]\n"
" [-BDNovqs] [-f filename] [-N | -P percentage]\n"
" [-w dbpasswd] [-C cipher(s)] [-t threads] [-W pwfile]\n"
" [-V [min-version]:[max-version]] [-a sniHostName] hostname\n"
" [-V [min-version]:[max-version]] [-a sniHostName]\n"
" [-J signatureschemes] hostname\n"
" where -v means verbose\n"
" -o flag is interpreted as follows:\n"
" 1 -o means override the result of server certificate validation.\n"
@@ -161,7 +165,17 @@ Usage(void)
" -T enable the cert_status extension (OCSP stapling)\n"
" -u enable TLS Session Ticket extension\n"
" -z enable compression\n"
" -g enable false start\n",
" -g enable false start\n"
" -J enable signature schemes\n"
" This takes a comma separated list of signature schemes in preference\n"
" order.\n"
" Possible values are:\n"
" rsa_pkcs1_sha1, rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha512,\n"
" ecdsa_sha1, ecdsa_secp256r1_sha256, ecdsa_secp384r1_sha384,\n"
" ecdsa_secp521r1_sha512,\n"
" rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512,\n"
" rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512,\n"
" dsa_sha1, dsa_sha256, dsa_sha384, dsa_sha512\n",
progName);
exit(1);
}
@@ -1158,6 +1172,14 @@ client_main(
errExit("error setting SSL/TLS version range ");
}
if (enabledSigSchemes) {
rv = SSL_SignatureSchemePrefSet(model_sock, enabledSigSchemes,
enabledSigSchemeCount);
if (rv < 0) {
errExit("SSL_SignatureSchemePrefSet");
}
}
if (bigBuf.data) { /* doing FDX */
rv = SSL_OptionSet(model_sock, SSL_ENABLE_FDX, 1);
if (rv < 0) {
@@ -1316,7 +1338,7 @@ main(int argc, char **argv)
/* XXX: 'B' was used in the past but removed in 3.28,
* please leave some time before resuing it. */
optstate = PL_CreateOptState(argc, argv,
"C:DNP:TUV:W:a:c:d:f:gin:op:qst:uvw:z");
"C:DJ:NP:TUV:W:a:c:d:f:gin:op:qst:uvw:z");
while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
switch (optstate->option) {
case 'C':
@@ -1330,6 +1352,15 @@ main(int argc, char **argv)
case 'I': /* reserved for OCSP multi-stapling */
break;
case 'J':
rv = parseSigSchemeList(optstate->value, &enabledSigSchemes, &enabledSigSchemeCount);
if (rv != SECSuccess) {
PL_DestroyOptState(optstate);
fprintf(stderr, "Bad signature scheme specified.\n");
Usage();
}
break;
case 'N':
NoReuse = 1;
break;
@@ -1516,6 +1547,8 @@ main(int argc, char **argv)
PL_strfree(hostName);
PORT_Free((SSLSignatureScheme *)enabledSigSchemes);
/* some final stats. */
printf(
"strsclnt: %ld cache hits; %ld cache misses, %ld cache not reusable\n"
+1
View File
@@ -94,6 +94,7 @@
'disable_libpkix%': 1,
'disable_werror%': 0,
'mozilla_client%': 0,
'comm_client%': 0,
'moz_fold_libs%': 0,
'moz_folded_library_name%': '',
'sanitizer_flags%': 0,
+8
View File
@@ -11,6 +11,7 @@
#include "cert.h"
#include "keyhi.h"
#include "p12.h"
#include "pk11pqg.h"
#include "pk11pub.h"
#include "pkcs11uri.h"
@@ -41,6 +42,7 @@ struct ScopedDelete {
void operator()(PLArenaPool* arena) { PORT_FreeArena(arena, PR_FALSE); }
void operator()(PK11Context* context) { PK11_DestroyContext(context, true); }
void operator()(PK11GenericObject* obj) { PK11_DestroyGenericObject(obj); }
void operator()(PQGParams* pqg) { PK11_PQG_DestroyParams(pqg); }
void operator()(SEC_PKCS12DecoderContext* dcx) {
SEC_PKCS12DecoderFinish(dcx);
}
@@ -66,6 +68,7 @@ SCOPED(CERTName);
SCOPED(CERTSubjectPublicKeyInfo);
SCOPED(PK11SlotInfo);
SCOPED(PK11SymKey);
SCOPED(PQGParams);
SCOPED(PRFileDesc);
SCOPED(SECAlgorithmID);
SCOPED(SECKEYEncryptedPrivateKeyInfo);
@@ -82,4 +85,9 @@ SCOPED(CERTDistNames);
#undef SCOPED
struct StackSECItem : public SECItem {
StackSECItem() : SECItem({siBuffer, nullptr, 0}) {}
~StackSECItem() { SECITEM_FreeItem(this, PR_FALSE); }
};
#endif // nss_scoped_ptrs_h__
+34
View File
@@ -0,0 +1,34 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef scoped_ptrs_smime_h__
#define scoped_ptrs_smime_h__
#include <memory>
#include "smime.h"
struct ScopedDeleteSmime {
void operator()(NSSCMSMessage* id) { NSS_CMSMessage_Destroy(id); }
};
template <class T>
struct ScopedMaybeDeleteSmime {
void operator()(T* ptr) {
if (ptr) {
ScopedDeleteSmime del;
del(ptr);
}
}
};
#define SCOPED(x) \
typedef std::unique_ptr<x, ScopedMaybeDeleteSmime<x> > Scoped##x
SCOPED(NSSCMSMessage);
#undef SCOPED
#endif // scoped_ptrs_smime_h__
+2
View File
@@ -14,6 +14,7 @@ struct ScopedDeleteSSL {
void operator()(SSLResumptionTokenInfo* token) {
SSL_DestroyResumptionTokenInfo(token);
}
void operator()(SSLAeadContext* ctx) { SSL_DestroyAead(ctx); }
};
template <class T>
@@ -29,6 +30,7 @@ struct ScopedMaybeDeleteSSL {
#define SCOPED(x) typedef std::unique_ptr<x, ScopedMaybeDeleteSSL<x> > Scoped##x
SCOPED(SSLResumptionTokenInfo);
SCOPED(SSLAeadContext);
#undef SCOPED
+1
View File
@@ -33,6 +33,7 @@ struct ScopedMaybeDelete {
SCOPED(SECAlgorithmID);
SCOPED(SECItem);
SCOPED(PK11URI);
SCOPED(PLArenaPool);
#undef SCOPED
+26
View File
@@ -80,6 +80,32 @@ inline std::ostream& operator<<(std::ostream& os, SSLProtocolVariant v) {
return os << ((v == ssl_variant_stream) ? "TLS" : "DTLS");
}
inline std::ostream& operator<<(std::ostream& os, SSLContentType v) {
switch (v) {
case ssl_ct_change_cipher_spec:
return os << "CCS";
case ssl_ct_alert:
return os << "alert";
case ssl_ct_handshake:
return os << "handshake";
case ssl_ct_application_data:
return os << "application data";
case ssl_ct_ack:
return os << "ack";
}
return os << "UNKNOWN content type " << static_cast<int>(v);
}
inline std::ostream& operator<<(std::ostream& os, SSLSecretDirection v) {
switch (v) {
case ssl_secret_read:
return os << "read";
case ssl_secret_write:
return os << "write";
}
return os << "UNKNOWN secret direction " << static_cast<int>(v);
}
inline bool IsDtls(uint16_t version) { return (version & 0x8000) == 0x8000; }
inline uint16_t NormalizeTlsVersion(uint16_t version) {
+4 -4
View File
@@ -21,7 +21,7 @@ all: prepare all-man all-html
prepare: date-and-version
mkdir -p html
mkdir -p nroff
clean:
rm -f date.xml version.xml *.tar.bz2
rm -f html/*.proc
@@ -45,11 +45,11 @@ version.xml:
nroff/%.1 : %.xml
$(COMPILE.1) $<
MANPAGES = \
nroff/certutil.1 nroff/cmsutil.1 nroff/crlutil.1 nroff/pk12util.1 \
nroff/modutil.1 nroff/ssltap.1 nroff/derdump.1 nroff/signtool.1 nroff/signver.1 \
nroff/pp.1 nroff/vfychain.1 nroff/vfyserv.1
nroff/pp.1 nroff/vfychain.1 nroff/vfyserv.1 nroff/nss-policy-check.1
all-man: prepare $(MANPAGES)
@@ -64,6 +64,6 @@ html/%.html : %.xml
HTMLPAGES = \
html/certutil.html html/cmsutil.html html/crlutil.html html/pk12util.html html/modutil.html \
html/ssltap.html html/derdump.html html/signtool.html html/signver.html html/pp.html \
html/vfychain.html html/vfyserv.html
html/vfychain.html html/vfyserv.html html/nss-policy-check.html
all-html: prepare $(HTMLPAGES)
+4
View File
@@ -179,6 +179,10 @@ Use the -a argument to specify ASCII output.</para></listitem>
For certificate requests, ASCII output defaults to standard output unless redirected.</para></listitem>
</varlistentry>
<varlistentry>
<term>--simple-self-signed</term>
<listitem><para>When printing the certificate chain, don't search for a chain if issuer name equals to subject name.</para></listitem>
</varlistentry>
<varlistentry>
<term>-b validity-time</term>
<listitem><para>Specify a time at which a certificate is required to be valid. Use when checking certificate validity with the <option>-V</option> option. The format of the <emphasis>validity-time</emphasis> argument is <emphasis>YYMMDDHHMMSS[+HHMM|-HHMM|Z]</emphasis>, which allows offsets to be set relative to the validity end time. Specifying seconds (<emphasis>SS</emphasis>) is optional. When specifying an explicit time, use a Z at the end of the term, <emphasis>YYMMDDHHMMSSZ</emphasis>, to close it. When specifying an offset time, use <emphasis>YYMMDDHHMMSS+HHMM</emphasis> or <emphasis>YYMMDDHHMMSS-HHMM</emphasis> for adding or subtracting time, respectively.
+97
View File
@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
<!ENTITY date SYSTEM "date.xml">
<!ENTITY version SYSTEM "version.xml">
]>
<refentry id="nss-policy-check">
<refentryinfo>
<date>&date;</date>
<title>NSS Security Tools</title>
<productname>nss-tools</productname>
<productnumber>&version;</productnumber>
</refentryinfo>
<refmeta>
<refentrytitle>NSS-POLICY-CHECK</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>nss-policy-check</refname>
<refpurpose>nss-policy-check policy-file</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>nss-policy-check</command>
</cmdsynopsis>
</refsynopsisdiv>
<refsection id="description">
<title>Description</title>
<para><command>nss-policy-check</command> verifies crypto-policy configuration that controls certain crypto algorithms are allowed/disallowed to use in the NSS library.</para>
<para>The crypto-policy configuration can be stored in either a system-wide configuration file, specified with the POLICY_PATH and POLICY_FILE build options, or in the pkcs11.txt in NSS database.</para>
</refsection>
<refsection id="basic-usage">
<title>Usage and Examples</title>
<para>To check the global crypto-policy configuration in <filename>/etc/crypto-policies/back-ends/nss.config</filename>:
</para>
<programlisting>$ nss-policy-check /etc/crypto-policies/back-ends/nss.config
NSS-POLICY-INFO: LOADED-SUCCESSFULLY
NSS-POLICY-INFO: PRIME256V1 is enabled for KX
NSS-POLICY-INFO: PRIME256V1 is enabled for CERT-SIGNATURE
NSS-POLICY-INFO: SECP256R1 is enabled for KX
NSS-POLICY-INFO: SECP256R1 is enabled for CERT-SIGNATURE
NSS-POLICY-INFO: SECP384R1 is enabled for KX
NSS-POLICY-INFO: SECP384R1 is enabled for CERT-SIGNATURE
...
NSS-POLICY-INFO: NUMBER-OF-SSL-ALG-KX: 13
NSS-POLICY-INFO: NUMBER-OF-SSL-ALG: 9
NSS-POLICY-INFO: NUMBER-OF-CERT-SIG: 9
...
NSS-POLICY-INFO: ciphersuite TLS_AES_128_GCM_SHA256 is enabled
NSS-POLICY-INFO: ciphersuite TLS_CHACHA20_POLY1305_SHA256 is enabled
NSS-POLICY-INFO: ciphersuite TLS_AES_256_GCM_SHA384 is enabled
...
NSS-POLICY-INFO: NUMBER-OF-CIPHERSUITES: 24
NSS-POLICY-INFO: NUMBER-OF-TLS-VERSIONS: 3
NSS-POLICY-INFO: NUMBER-OF-DTLS-VERSIONS: 2
</programlisting>
<para>If there is a failure or warning, it will be prefixed with
NSS-POLICY-FAIL or NSS-POLICY_WARN.
</para>
<para><command>nss-policy-check</command> exits with 2 if any
failure is found, 1 if any warning is found, or 0 if no errors are
found.</para>
</refsection>
<!-- don't change -->
<refsection id="resources">
<title>Additional Resources</title>
<para>For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at <ulink url="http://www.mozilla.org/projects/security/pki/nss/">http://www.mozilla.org/projects/security/pki/nss/</ulink>. The NSS site relates directly to NSS code changes and releases.</para>
<para>Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto</para>
<para>IRC: Freenode at #dogtag-pki</para>
</refsection>
<!-- fill in your name first; keep the other names for reference -->
<refsection id="authors">
<title>Authors</title>
<para>The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google.</para>
<para>
Authors: Elio Maldonado &lt;emaldona@redhat.com>, Deon Lackey &lt;dlackey@redhat.com>.
</para>
</refsection>
<!-- don't change -->
<refsection id="license">
<title>LICENSE</title>
<para>Licensed under 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/.
</para>
</refsection>
</refentry>
+1 -1
View File
@@ -108,7 +108,7 @@
</varlistentry>
<varlistentry>
<term>-n | --cert-key-len certKeyLength</term>
<term>--cert-key-len certKeyLength</term>
<listitem><para>Specify the desired length of the symmetric key to be used to encrypt the certificates and other meta-data.</para></listitem>
</varlistentry>
@@ -0,0 +1,47 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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 "gtest/gtest.h"
#include "nss.h"
#include "secerr.h"
#include "pk11pub.h"
#include "nss_scoped_ptrs.h"
namespace nss_test {
class CertTest : public ::testing::Test {};
// Tests CERT_GetCertificateDer for the certs we have.
TEST_F(CertTest, GetCertDer) {
// Listing all the certs should get us the default trust anchors.
ScopedCERTCertList certs(PK11_ListCerts(PK11CertListAll, nullptr));
ASSERT_FALSE(PR_CLIST_IS_EMPTY(&certs->list));
for (PRCList* cursor = PR_NEXT_LINK(&certs->list); cursor != &certs->list;
cursor = PR_NEXT_LINK(cursor)) {
CERTCertListNode* node = (CERTCertListNode*)cursor;
SECItem der;
ASSERT_EQ(SECSuccess, CERT_GetCertificateDer(node->cert, &der));
ASSERT_EQ(0, SECITEM_CompareItem(&der, &node->cert->derCert));
}
}
TEST_F(CertTest, GetCertDerBad) {
EXPECT_EQ(SECFailure, CERT_GetCertificateDer(nullptr, nullptr));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
ScopedCERTCertList certs(PK11_ListCerts(PK11CertListAll, nullptr));
ASSERT_FALSE(PR_CLIST_IS_EMPTY(&certs->list));
CERTCertListNode* node = (CERTCertListNode*)PR_NEXT_LINK(&certs->list);
EXPECT_EQ(SECFailure, CERT_GetCertificateDer(node->cert, nullptr));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
SECItem der;
EXPECT_EQ(SECFailure, CERT_GetCertificateDer(nullptr, &der));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
}
}
@@ -12,6 +12,8 @@
'type': 'executable',
'sources': [
'alg1485_unittest.cc',
'cert_unittest.cc',
'decode_certs_unittest.cc',
'<(DEPTH)/gtests/common/gtests.cc'
],
'dependencies': [
@@ -20,6 +22,7 @@
'<(DEPTH)/lib/util/util.gyp:nssutil3',
'<(DEPTH)/lib/ssl/ssl.gyp:ssl3',
'<(DEPTH)/lib/nss/nss.gyp:nss3',
'<(DEPTH)/lib/smime/smime.gyp:smime3',
]
}
],
@@ -0,0 +1,28 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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 "gtest/gtest.h"
#include "cert.h"
#include "prerror.h"
#include "secerr.h"
class DecodeCertsTest : public ::testing::Test {};
TEST_F(DecodeCertsTest, EmptyCertPackage) {
// This represents a PKCS#7 ContentInfo with a contentType of
// '2.16.840.1.113730.2.5' (Netscape data-type cert-sequence) and a content
// consisting of an empty SEQUENCE. This is valid ASN.1, but it contains no
// certificates, so CERT_DecodeCertFromPackage should just return a null
// pointer.
unsigned char emptyCertPackage[] = {0x30, 0x0f, 0x06, 0x09, 0x60, 0x86,
0x48, 0x01, 0x86, 0xf8, 0x42, 0x02,
0x05, 0xa0, 0x02, 0x30, 0x00};
EXPECT_EQ(nullptr, CERT_DecodeCertFromPackage(
reinterpret_cast<char*>(emptyCertPackage),
sizeof(emptyCertPackage)));
EXPECT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
@@ -8,6 +8,8 @@ MODULE = nss
CPPSRCS = \
alg1485_unittest.cc \
cert_unittest.cc \
decode_certs_unittest.cc \
$(NULL)
INCLUDES += -I$(CORE_DEPTH)/gtests/google_test/gtest/include \
+17 -1
View File
@@ -10,7 +10,23 @@
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
if (NSS_NoDB_Init(nullptr) != SECSuccess) {
const char *workdir = "";
uint32_t flags = NSS_INIT_READONLY;
for (int i = 0; i < argc; i++) {
if (!strcmp(argv[i], "-d")) {
if (i + 1 >= argc) {
PR_fprintf(PR_STDERR, "Usage: %s [-d <dir> [-w]]\n", argv[0]);
exit(2);
}
workdir = argv[i + 1];
i++;
} else if (!strcmp(argv[i], "-w")) {
flags &= ~NSS_INIT_READONLY;
}
}
if (NSS_Initialize(workdir, "", "", SECMOD_DB, flags) != SECSuccess) {
return 1;
}
if (NSS_SetDomesticPolicy() != SECSuccess) {
+1
View File
@@ -24,6 +24,7 @@ NSS_SRCDIRS = \
cryptohi_gtest \
der_gtest \
pk11_gtest \
smime_gtest \
softoken_gtest \
ssl_gtest \
$(SYSINIT_GTEST) \
+1 -1
View File
@@ -13,6 +13,7 @@ CPPSRCS = \
pk11_ecdsa_unittest.cc \
pk11_encrypt_derive_unittest.cc \
pk11_export_unittest.cc \
pk11_import_unittest.cc \
pk11_pbkdf2_unittest.cc \
pk11_prf_unittest.cc \
pk11_prng_unittest.cc \
@@ -33,4 +34,3 @@ EXTRA_LIBS = $(DIST)/lib/$(LIB_PREFIX)gtest.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)cpputil.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)gtestutil.$(LIB_SUFFIX) \
$(NULL)
@@ -18,6 +18,7 @@
'pk11_curve25519_unittest.cc',
'pk11_ecdsa_unittest.cc',
'pk11_encrypt_derive_unittest.cc',
'pk11_import_unittest.cc',
'pk11_pbkdf2_unittest.cc',
'pk11_prf_unittest.cc',
'pk11_prng_unittest.cc',
+43
View File
@@ -0,0 +1,43 @@
#! gmake
#
# 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/.
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
include ../common/gtest.mk
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
@@ -0,0 +1,22 @@
#
# 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/.
CORE_DEPTH = ../..
DEPTH = ../..
MODULE = nss
CPPSRCS = \
smime_unittest.cc \
$(NULL)
INCLUDES += -I$(CORE_DEPTH)/gtests/google_test/gtest/include \
-I$(CORE_DEPTH)/gtests/common \
-I$(CORE_DEPTH)/cpputil
REQUIRES = nspr gtest
PROGRAM = smime_gtest
EXTRA_LIBS = $(DIST)/lib/$(LIB_PREFIX)gtest.$(LIB_SUFFIX) $(EXTRA_OBJS) \
$(DIST)/lib/$(LIB_PREFIX)gtestutil.$(LIB_SUFFIX)
@@ -0,0 +1,30 @@
# 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/.
{
'includes': [
'../../coreconf/config.gypi',
'../common/gtest.gypi',
],
'targets': [
{
'target_name': 'smime_gtest',
'type': 'executable',
'sources': [
'smime_unittest.cc',
'<(DEPTH)/gtests/common/gtests.cc'
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
'<(DEPTH)/lib/util/util.gyp:nssutil3',
'<(DEPTH)/lib/nss/nss.gyp:nss3',
'<(DEPTH)/lib/smime/smime.gyp:smime',
'<(DEPTH)/lib/ssl/ssl.gyp:ssl3',
]
}
],
'variables': {
'module': 'nss'
}
}
@@ -0,0 +1,137 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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 <string>
#include "gtest/gtest.h"
#include "scoped_ptrs_smime.h"
#include "smime.h"
namespace nss_test {
// See bug 1507174; this is a CMS serialization (RFC 5652) that claims to be
// 12336 bytes long, which ensures CMS validates the streaming decoder's
// incorrect length.
static const unsigned char kHugeLenAsn1[] = {
0x30, 0x82, 0x30, 0x30, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
0x0D, 0x01, 0x07, 0x02, 0xA0, 0x82, 0x02, 0x30, 0x30, 0x30, 0x02,
0x01, 0x30, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x09, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x0B, 0x06,
0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x05};
// secp256r1 signature with no certs and no attrs
static unsigned char kValidSignature[] = {
0x30, 0x81, 0xFE, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
0x07, 0x02, 0xA0, 0x81, 0xF0, 0x30, 0x81, 0xED, 0x02, 0x01, 0x01, 0x31,
0x0F, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
0x02, 0x01, 0x05, 0x00, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
0xF7, 0x0D, 0x01, 0x07, 0x01, 0x31, 0x81, 0xC9, 0x30, 0x81, 0xC6, 0x02,
0x01, 0x01, 0x30, 0x5D, 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03,
0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
0x03, 0x55, 0x04, 0x08, 0x0C, 0x0A, 0x53, 0x6F, 0x6D, 0x65, 0x2D, 0x53,
0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04,
0x0A, 0x0C, 0x18, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20,
0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
0x4C, 0x74, 0x64, 0x02, 0x14, 0x6B, 0x22, 0xCA, 0x91, 0xE0, 0x71, 0x97,
0xEB, 0x45, 0x0D, 0x68, 0xC0, 0xD4, 0xB6, 0xE9, 0x45, 0x38, 0x4C, 0xDD,
0xA3, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
0x02, 0x01, 0x05, 0x00, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
0x3D, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x48, 0xEB,
0xE6, 0xBA, 0xFC, 0xFD, 0x83, 0xB3, 0xA2, 0xB5, 0x59, 0x35, 0x0C, 0xA1,
0x31, 0x0E, 0x2F, 0xE3, 0x8D, 0x81, 0xD8, 0xF5, 0x33, 0xE4, 0x83, 0x87,
0xB1, 0xFD, 0x43, 0x9D, 0x95, 0x7D, 0x02, 0x21, 0x00, 0xD0, 0x05, 0x0E,
0x05, 0xA6, 0x80, 0x3C, 0x1A, 0xFE, 0x51, 0xFC, 0x4D, 0x1A, 0x25, 0x05,
0x78, 0xB5, 0x42, 0xF5, 0xDE, 0x4E, 0x8A, 0xF8, 0xE3, 0xD8, 0x52, 0xDC,
0x2B, 0x73, 0x80, 0x4A, 0x1A};
// See bug 1507135; this is a CMS signature that contains only the OID
static unsigned char kTruncatedSignature[] = {0x30, 0x0B, 0x06, 0x09, 0x2A,
0x86, 0x48, 0x86, 0xF7, 0x0D,
0x01, 0x07, 0x02};
// secp256r1 signature that's truncated by one byte.
static unsigned char kSlightlyTruncatedSignature[] = {
0x30, 0x81, 0xFE, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
0x07, 0x02, 0xA0, 0x81, 0xF0, 0x30, 0x81, 0xED, 0x02, 0x01, 0x01, 0x31,
0x0F, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
0x02, 0x01, 0x05, 0x00, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
0xF7, 0x0D, 0x01, 0x07, 0x01, 0x31, 0x81, 0xC9, 0x30, 0x81, 0xC6, 0x02,
0x01, 0x01, 0x30, 0x5D, 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03,
0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
0x03, 0x55, 0x04, 0x08, 0x0C, 0x0A, 0x53, 0x6F, 0x6D, 0x65, 0x2D, 0x53,
0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04,
0x0A, 0x0C, 0x18, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20,
0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
0x4C, 0x74, 0x64, 0x02, 0x14, 0x6B, 0x22, 0xCA, 0x91, 0xE0, 0x71, 0x97,
0xEB, 0x45, 0x0D, 0x68, 0xC0, 0xD4, 0xB6, 0xE9, 0x45, 0x38, 0x4C, 0xDD,
0xA3, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
0x02, 0x01, 0x05, 0x00, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
0x3D, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x48, 0xEB,
0xE6, 0xBA, 0xFC, 0xFD, 0x83, 0xB3, 0xA2, 0xB5, 0x59, 0x35, 0x0C, 0xA1,
0x31, 0x0E, 0x2F, 0xE3, 0x8D, 0x81, 0xD8, 0xF5, 0x33, 0xE4, 0x83, 0x87,
0xB1, 0xFD, 0x43, 0x9D, 0x95, 0x7D, 0x02, 0x21, 0x00, 0xD0, 0x05, 0x0E,
0x05, 0xA6, 0x80, 0x3C, 0x1A, 0xFE, 0x51, 0xFC, 0x4D, 0x1A, 0x25, 0x05,
0x78, 0xB5, 0x42, 0xF5, 0xDE, 0x4E, 0x8A, 0xF8, 0xE3, 0xD8, 0x52, 0xDC,
0x2B, 0x73, 0x80, 0x4A};
class SMimeTest : public ::testing::Test {};
TEST_F(SMimeTest, InvalidDER) {
PK11SymKey* bulk_key = nullptr;
NSSCMSDecoderContext* dcx =
NSS_CMSDecoder_Start(nullptr, nullptr, nullptr, /* content callback */
nullptr, nullptr, /* password callback */
nullptr, /* key callback */
bulk_key);
ASSERT_NE(nullptr, dcx);
EXPECT_EQ(SECSuccess, NSS_CMSDecoder_Update(
dcx, reinterpret_cast<const char*>(kHugeLenAsn1),
sizeof(kHugeLenAsn1)));
EXPECT_EQ(nullptr, bulk_key);
ASSERT_FALSE(NSS_CMSDecoder_Finish(dcx));
}
TEST_F(SMimeTest, IsSignedValid) {
SECItem sig_der_item = {siBuffer, kValidSignature, sizeof(kValidSignature)};
ScopedNSSCMSMessage cms_msg(NSS_CMSMessage_CreateFromDER(
&sig_der_item, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
ASSERT_TRUE(cms_msg);
ASSERT_TRUE(NSS_CMSMessage_IsSigned(cms_msg.get()));
}
TEST_F(SMimeTest, TruncatedCmsSignature) {
SECItem sig_der_item = {siBuffer, kTruncatedSignature,
sizeof(kTruncatedSignature)};
ScopedNSSCMSMessage cms_msg(NSS_CMSMessage_CreateFromDER(
&sig_der_item, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
ASSERT_TRUE(cms_msg);
ASSERT_FALSE(NSS_CMSMessage_IsSigned(cms_msg.get()));
}
TEST_F(SMimeTest, SlightlyTruncatedCmsSignature) {
SECItem sig_der_item = {siBuffer, kSlightlyTruncatedSignature,
sizeof(kSlightlyTruncatedSignature)};
ScopedNSSCMSMessage cms_msg(NSS_CMSMessage_CreateFromDER(
&sig_der_item, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
ASSERT_FALSE(cms_msg);
ASSERT_FALSE(NSS_CMSMessage_IsSigned(cms_msg.get()));
}
TEST_F(SMimeTest, IsSignedNull) {
ASSERT_FALSE(NSS_CMSMessage_IsSigned(nullptr));
}
} // namespace nss_test
@@ -297,38 +297,6 @@ SSLKEAType SSLInt_GetKEAType(SSLNamedGroup group) {
return groupDef->keaType;
}
SECStatus SSLInt_SetCipherSpecChangeFunc(PRFileDesc *fd,
sslCipherSpecChangedFunc func,
void *arg) {
sslSocket *ss;
ss = ssl_FindSocket(fd);
if (!ss) {
return SECFailure;
}
ss->ssl3.changedCipherSpecFunc = func;
ss->ssl3.changedCipherSpecArg = arg;
return SECSuccess;
}
PK11SymKey *SSLInt_CipherSpecToKey(const ssl3CipherSpec *spec) {
return spec->keyMaterial.key;
}
SSLCipherAlgorithm SSLInt_CipherSpecToAlgorithm(const ssl3CipherSpec *spec) {
return spec->cipherDef->calg;
}
const PRUint8 *SSLInt_CipherSpecToIv(const ssl3CipherSpec *spec) {
return spec->keyMaterial.iv;
}
PRUint16 SSLInt_CipherSpecToEpoch(const ssl3CipherSpec *spec) {
return spec->epoch;
}
void SSLInt_SetTicketLifetime(uint32_t lifetime) {
ssl_ticket_lifetime = lifetime;
}
@@ -360,16 +328,14 @@ void SSLInt_RolloverAntiReplay(void) {
tls13_AntiReplayRollover(ssl_TimeUsec());
}
SECStatus SSLInt_GetEpochs(PRFileDesc *fd, PRUint16 *readEpoch,
PRUint16 *writeEpoch) {
SECStatus SSLInt_HasPendingHandshakeData(PRFileDesc *fd, PRBool *pending) {
sslSocket *ss = ssl_FindSocket(fd);
if (!ss || !readEpoch || !writeEpoch) {
if (!ss) {
return SECFailure;
}
ssl_GetSpecReadLock(ss);
*readEpoch = ss->ssl3.crSpec->epoch;
*writeEpoch = ss->ssl3.cwSpec->epoch;
ssl_ReleaseSpecReadLock(ss);
ssl_GetSSL3HandshakeLock(ss);
*pending = ss->ssl3.hs.msg_body.len > 0;
ssl_ReleaseSSL3HandshakeLock(ss);
return SECSuccess;
}
@@ -39,16 +39,7 @@ SECStatus SSLInt_AdvanceWriteSeqNum(PRFileDesc *fd, PRUint64 to);
SECStatus SSLInt_AdvanceReadSeqNum(PRFileDesc *fd, PRUint64 to);
SECStatus SSLInt_AdvanceWriteSeqByAWindow(PRFileDesc *fd, PRInt32 extra);
SSLKEAType SSLInt_GetKEAType(SSLNamedGroup group);
SECStatus SSLInt_GetEpochs(PRFileDesc *fd, PRUint16 *readEpoch,
PRUint16 *writeEpoch);
SECStatus SSLInt_SetCipherSpecChangeFunc(PRFileDesc *fd,
sslCipherSpecChangedFunc func,
void *arg);
PRUint16 SSLInt_CipherSpecToEpoch(const ssl3CipherSpec *spec);
PK11SymKey *SSLInt_CipherSpecToKey(const ssl3CipherSpec *spec);
SSLCipherAlgorithm SSLInt_CipherSpecToAlgorithm(const ssl3CipherSpec *spec);
const PRUint8 *SSLInt_CipherSpecToIv(const ssl3CipherSpec *spec);
SECStatus SSLInt_HasPendingHandshakeData(PRFileDesc *fd, PRBool *pending);
void SSLInt_SetTicketLifetime(uint32_t lifetime);
SECStatus SSLInt_SetSocketMaxEarlyDataSize(PRFileDesc *fd, uint32_t size);
void SSLInt_RolloverAntiReplay(void);
@@ -35,7 +35,9 @@ CPPSRCS = \
ssl_keyupdate_unittest.cc \
ssl_loopback_unittest.cc \
ssl_misc_unittest.cc \
ssl_primitive_unittest.cc \
ssl_record_unittest.cc \
ssl_recordsep_unittest.cc \
ssl_recordsize_unittest.cc \
ssl_resumption_unittest.cc \
ssl_renegotiation_unittest.cc \
@@ -176,6 +176,321 @@ TEST_P(TlsConnectGeneric, ClientAuth) {
CheckKeys();
}
class TlsCertificateRequestContextRecorder : public TlsHandshakeFilter {
public:
TlsCertificateRequestContextRecorder(const std::shared_ptr<TlsAgent>& a,
uint8_t handshake_type)
: TlsHandshakeFilter(a, {handshake_type}), buffer_(), filtered_(false) {
EnableDecryption();
}
bool filtered() const { return filtered_; }
const DataBuffer& buffer() const { return buffer_; }
protected:
virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
const DataBuffer& input,
DataBuffer* output) {
assert(1 < input.len());
size_t len = input.data()[0];
assert(len + 1 < input.len());
buffer_.Assign(input.data() + 1, len);
filtered_ = true;
return KEEP;
}
private:
DataBuffer buffer_;
bool filtered_;
};
// All stream only tests; DTLS isn't supported yet.
TEST_F(TlsConnectStreamTls13, PostHandshakeAuth) {
EnsureTlsSetup();
auto capture_cert_req = MakeTlsFilter<TlsCertificateRequestContextRecorder>(
server_, kTlsHandshakeCertificateRequest);
auto capture_certificate =
MakeTlsFilter<TlsCertificateRequestContextRecorder>(
client_, kTlsHandshakeCertificate);
client_->SetupClientAuth();
EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE));
size_t called = 0;
server_->SetAuthCertificateCallback(
[&called](TlsAgent*, PRBool, PRBool) -> SECStatus {
called++;
return SECSuccess;
});
Connect();
EXPECT_EQ(0U, called);
EXPECT_FALSE(capture_cert_req->filtered());
EXPECT_FALSE(capture_certificate->filtered());
// Send CertificateRequest.
EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd()))
<< "Unexpected error: " << PORT_ErrorToName(PORT_GetError());
// Need to do a round-trip so that the post-handshake message is
// handled on both client and server.
server_->SendData(50);
client_->ReadBytes(50);
client_->SendData(50);
server_->ReadBytes(50);
EXPECT_EQ(1U, called);
EXPECT_TRUE(capture_cert_req->filtered());
EXPECT_TRUE(capture_certificate->filtered());
// Check if a non-empty request context is generated and it is
// properly sent back.
EXPECT_LT(0U, capture_cert_req->buffer().len());
EXPECT_EQ(capture_cert_req->buffer().len(),
capture_certificate->buffer().len());
EXPECT_EQ(0, memcmp(capture_cert_req->buffer().data(),
capture_certificate->buffer().data(),
capture_cert_req->buffer().len()));
ScopedCERTCertificate cert1(SSL_PeerCertificate(server_->ssl_fd()));
ScopedCERTCertificate cert2(SSL_LocalCertificate(client_->ssl_fd()));
EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert));
}
static SECStatus GetClientAuthDataHook(void* self, PRFileDesc* fd,
CERTDistNames* caNames,
CERTCertificate** clientCert,
SECKEYPrivateKey** clientKey) {
ScopedCERTCertificate cert;
ScopedSECKEYPrivateKey priv;
// use a different certificate than TlsAgent::kClient
if (!TlsAgent::LoadCertificate(TlsAgent::kRsa2048, &cert, &priv)) {
return SECFailure;
}
*clientCert = cert.release();
*clientKey = priv.release();
return SECSuccess;
}
TEST_F(TlsConnectStreamTls13, PostHandshakeAuthMultiple) {
client_->SetupClientAuth();
EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE));
size_t called = 0;
server_->SetAuthCertificateCallback(
[&called](TlsAgent*, PRBool, PRBool) -> SECStatus {
called++;
return SECSuccess;
});
Connect();
EXPECT_EQ(0U, called);
EXPECT_EQ(nullptr, SSL_PeerCertificate(server_->ssl_fd()));
// Send 1st CertificateRequest.
EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd()))
<< "Unexpected error: " << PORT_ErrorToName(PORT_GetError());
server_->SendData(50);
client_->ReadBytes(50);
client_->SendData(50);
server_->ReadBytes(50);
EXPECT_EQ(1U, called);
ScopedCERTCertificate cert1(SSL_PeerCertificate(server_->ssl_fd()));
ScopedCERTCertificate cert2(SSL_LocalCertificate(client_->ssl_fd()));
EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert));
// Send 2nd CertificateRequest.
EXPECT_EQ(SECSuccess, SSL_GetClientAuthDataHook(
client_->ssl_fd(), GetClientAuthDataHook, nullptr));
EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd()))
<< "Unexpected error: " << PORT_ErrorToName(PORT_GetError());
server_->SendData(50);
client_->ReadBytes(50);
client_->SendData(50);
server_->ReadBytes(50);
EXPECT_EQ(2U, called);
ScopedCERTCertificate cert3(SSL_PeerCertificate(server_->ssl_fd()));
ScopedCERTCertificate cert4(SSL_LocalCertificate(client_->ssl_fd()));
EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert3->derCert, &cert4->derCert));
EXPECT_FALSE(SECITEM_ItemsAreEqual(&cert3->derCert, &cert1->derCert));
}
TEST_F(TlsConnectStreamTls13, PostHandshakeAuthConcurrent) {
client_->SetupClientAuth();
EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE));
Connect();
// Send 1st CertificateRequest.
EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd()))
<< "Unexpected error: " << PORT_ErrorToName(PORT_GetError());
// Send 2nd CertificateRequest.
EXPECT_EQ(SECFailure, SSL_SendCertificateRequest(server_->ssl_fd()));
EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
}
TEST_F(TlsConnectStreamTls13, PostHandshakeAuthMissingExtension) {
client_->SetupClientAuth();
Connect();
// Send CertificateRequest, should fail due to missing
// post_handshake_auth extension.
EXPECT_EQ(SECFailure, SSL_SendCertificateRequest(server_->ssl_fd()));
EXPECT_EQ(SSL_ERROR_MISSING_POST_HANDSHAKE_AUTH_EXTENSION, PORT_GetError());
}
TEST_F(TlsConnectStreamTls13, PostHandshakeAuthAfterClientAuth) {
client_->SetupClientAuth();
server_->RequestClientAuth(true);
EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE));
size_t called = 0;
server_->SetAuthCertificateCallback(
[&called](TlsAgent*, PRBool, PRBool) -> SECStatus {
called++;
return SECSuccess;
});
Connect();
EXPECT_EQ(1U, called);
ScopedCERTCertificate cert1(SSL_PeerCertificate(server_->ssl_fd()));
ScopedCERTCertificate cert2(SSL_LocalCertificate(client_->ssl_fd()));
EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert));
// Send CertificateRequest.
EXPECT_EQ(SECSuccess, SSL_GetClientAuthDataHook(
client_->ssl_fd(), GetClientAuthDataHook, nullptr));
EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd()))
<< "Unexpected error: " << PORT_ErrorToName(PORT_GetError());
server_->SendData(50);
client_->ReadBytes(50);
client_->SendData(50);
server_->ReadBytes(50);
EXPECT_EQ(2U, called);
ScopedCERTCertificate cert3(SSL_PeerCertificate(server_->ssl_fd()));
ScopedCERTCertificate cert4(SSL_LocalCertificate(client_->ssl_fd()));
EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert3->derCert, &cert4->derCert));
EXPECT_FALSE(SECITEM_ItemsAreEqual(&cert3->derCert, &cert1->derCert));
}
// Damages the request context in a CertificateRequest message.
// We don't modify a Certificate message instead, so that the client
// can compute CertificateVerify correctly.
class TlsDamageCertificateRequestContextFilter : public TlsHandshakeFilter {
public:
TlsDamageCertificateRequestContextFilter(const std::shared_ptr<TlsAgent>& a)
: TlsHandshakeFilter(a, {kTlsHandshakeCertificateRequest}) {
EnableDecryption();
}
protected:
virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
const DataBuffer& input,
DataBuffer* output) {
*output = input;
assert(1 < output->len());
// The request context has a 1 octet length.
output->data()[1] ^= 73;
return CHANGE;
}
};
TEST_F(TlsConnectStreamTls13, PostHandshakeAuthContextMismatch) {
EnsureTlsSetup();
MakeTlsFilter<TlsDamageCertificateRequestContextFilter>(server_);
client_->SetupClientAuth();
EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE));
Connect();
// Send CertificateRequest.
EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd()))
<< "Unexpected error: " << PORT_ErrorToName(PORT_GetError());
server_->SendData(50);
client_->ReadBytes(50);
client_->SendData(50);
server_->ExpectSendAlert(kTlsAlertIllegalParameter);
server_->ReadBytes(50);
EXPECT_EQ(SSL_ERROR_RX_MALFORMED_CERTIFICATE, PORT_GetError());
server_->ExpectReadWriteError();
server_->SendData(50);
client_->ExpectReceiveAlert(kTlsAlertIllegalParameter);
client_->ReadBytes(50);
EXPECT_EQ(SSL_ERROR_ILLEGAL_PARAMETER_ALERT, PORT_GetError());
}
// Replaces signature in a CertificateVerify message.
class TlsDamageSignatureFilter : public TlsHandshakeFilter {
public:
TlsDamageSignatureFilter(const std::shared_ptr<TlsAgent>& a)
: TlsHandshakeFilter(a, {kTlsHandshakeCertificateVerify}) {
EnableDecryption();
}
protected:
virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
const DataBuffer& input,
DataBuffer* output) {
*output = input;
assert(2 < output->len());
// The signature follows a 2-octet signature scheme.
output->data()[2] ^= 73;
return CHANGE;
}
};
TEST_F(TlsConnectStreamTls13, PostHandshakeAuthBadSignature) {
EnsureTlsSetup();
MakeTlsFilter<TlsDamageSignatureFilter>(client_);
client_->SetupClientAuth();
EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE));
Connect();
// Send CertificateRequest.
EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd()))
<< "Unexpected error: " << PORT_ErrorToName(PORT_GetError());
server_->SendData(50);
client_->ReadBytes(50);
client_->SendData(50);
server_->ExpectSendAlert(kTlsAlertDecodeError);
server_->ReadBytes(50);
EXPECT_EQ(SSL_ERROR_RX_MALFORMED_CERT_VERIFY, PORT_GetError());
}
TEST_F(TlsConnectStreamTls13, PostHandshakeAuthDecline) {
EnsureTlsSetup();
auto capture_cert_req = MakeTlsFilter<TlsCertificateRequestContextRecorder>(
server_, kTlsHandshakeCertificateRequest);
auto capture_certificate =
MakeTlsFilter<TlsCertificateRequestContextRecorder>(
client_, kTlsHandshakeCertificate);
client_->SetupClientAuth();
EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE));
// Client to decline the certificate request.
EXPECT_EQ(SECSuccess,
SSL_GetClientAuthDataHook(
client_->ssl_fd(),
[](void*, PRFileDesc*, CERTDistNames*, CERTCertificate**,
SECKEYPrivateKey**) -> SECStatus { return SECFailure; },
nullptr));
size_t called = 0;
server_->SetAuthCertificateCallback(
[&called](TlsAgent*, PRBool, PRBool) -> SECStatus {
called++;
return SECSuccess;
});
Connect();
EXPECT_EQ(0U, called);
// Send CertificateRequest.
EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd()))
<< "Unexpected error: " << PORT_ErrorToName(PORT_GetError());
server_->SendData(50);
client_->ReadBytes(50);
client_->SendData(50);
server_->ReadBytes(50);
// AuthCertificateCallback is not called, because the client sends
// an empty certificate_list.
EXPECT_EQ(0U, called);
EXPECT_TRUE(capture_cert_req->filtered());
EXPECT_TRUE(capture_certificate->filtered());
// Check if a non-empty request context is generated and it is
// properly sent back.
EXPECT_LT(0U, capture_cert_req->buffer().len());
EXPECT_EQ(capture_cert_req->buffer().len(),
capture_certificate->buffer().len());
EXPECT_EQ(0, memcmp(capture_cert_req->buffer().data(),
capture_certificate->buffer().data(),
capture_cert_req->buffer().len()));
}
// In TLS 1.3, the client sends its cert rejection on the
// second flight, and since it has already received the
// server's Finished, it transitions to complete and
@@ -273,9 +588,7 @@ class TlsReplaceSignatureSchemeFilter : public TlsHandshakeFilter {
TlsReplaceSignatureSchemeFilter(const std::shared_ptr<TlsAgent>& a,
SSLSignatureScheme scheme)
: TlsHandshakeFilter(a, {kTlsHandshakeCertificateVerify}),
scheme_(scheme) {
EnableDecryption();
}
scheme_(scheme) {}
protected:
virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
@@ -552,7 +865,9 @@ TEST_P(TlsConnectTls12, SignatureAlgorithmDrop) {
TEST_P(TlsConnectTls13, UnsupportedSignatureSchemeAlert) {
EnsureTlsSetup();
MakeTlsFilter<TlsReplaceSignatureSchemeFilter>(server_, ssl_sig_none);
auto filter =
MakeTlsFilter<TlsReplaceSignatureSchemeFilter>(server_, ssl_sig_none);
filter->EnableDecryption();
ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
@@ -563,8 +878,9 @@ TEST_P(TlsConnectTls13, InconsistentSignatureSchemeAlert) {
EnsureTlsSetup();
// This won't work because we use an RSA cert by default.
MakeTlsFilter<TlsReplaceSignatureSchemeFilter>(
auto filter = MakeTlsFilter<TlsReplaceSignatureSchemeFilter>(
server_, ssl_sig_ecdsa_secp256r1_sha256);
filter->EnableDecryption();
ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
@@ -62,7 +62,6 @@ TEST_P(TlsConnectGenericPre13, DamageServerSignature) {
EnsureTlsSetup();
auto filter = MakeTlsFilter<TlsLastByteDamager>(
server_, kTlsHandshakeServerKeyExchange);
filter->EnableDecryption();
ExpectAlert(client_, kTlsAlertDecryptError);
ConnectExpectFail();
client_->CheckErrorCode(SEC_ERROR_BAD_SIGNATURE);
@@ -84,7 +83,9 @@ TEST_P(TlsConnectGeneric, DamageClientSignature) {
server_->RequestClientAuth(true);
auto filter = MakeTlsFilter<TlsLastByteDamager>(
client_, kTlsHandshakeCertificateVerify);
filter->EnableDecryption();
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
filter->EnableDecryption();
}
server_->ExpectSendAlert(kTlsAlertDecryptError);
// Do these handshakes by hand to avoid race condition on
// the client processing the server's alert.
@@ -66,6 +66,38 @@ TEST_P(TlsConnectDatagramPre13, DropServerSecondFlightThrice) {
Connect();
}
static void CheckAcks(const std::shared_ptr<TlsRecordRecorder>& acks,
size_t index, std::vector<uint64_t> expected) {
ASSERT_LT(index, acks->count());
const DataBuffer& buf = acks->record(index).buffer;
size_t offset = 2;
uint64_t len;
EXPECT_EQ(2 + expected.size() * 8, buf.len());
ASSERT_TRUE(buf.Read(0, 2, &len));
ASSERT_EQ(static_cast<size_t>(len + 2), buf.len());
if ((2 + expected.size() * 8) != buf.len()) {
while (offset < buf.len()) {
uint64_t ack;
ASSERT_TRUE(buf.Read(offset, 8, &ack));
offset += 8;
std::cerr << "Ack=0x" << std::hex << ack << std::dec << std::endl;
}
return;
}
for (size_t i = 0; i < expected.size(); ++i) {
uint64_t a = expected[i];
uint64_t ack;
ASSERT_TRUE(buf.Read(offset, 8, &ack));
offset += 8;
if (a != ack) {
ADD_FAILURE() << "Wrong ack " << i << " expected=0x" << std::hex << a
<< " got=0x" << ack << std::dec;
}
}
}
class TlsDropDatagram13 : public TlsConnectDatagram13,
public ::testing::WithParamInterface<bool> {
public:
@@ -139,37 +171,6 @@ class TlsDropDatagram13 : public TlsConnectDatagram13,
std::shared_ptr<PacketFilter> chain_;
};
void CheckAcks(const DropAckChain& chain, size_t index,
std::vector<uint64_t> acks) {
const DataBuffer& buf = chain.ack_->record(index).buffer;
size_t offset = 2;
uint64_t len;
EXPECT_EQ(2 + acks.size() * 8, buf.len());
ASSERT_TRUE(buf.Read(0, 2, &len));
ASSERT_EQ(static_cast<size_t>(len + 2), buf.len());
if ((2 + acks.size() * 8) != buf.len()) {
while (offset < buf.len()) {
uint64_t ack;
ASSERT_TRUE(buf.Read(offset, 8, &ack));
offset += 8;
std::cerr << "Ack=0x" << std::hex << ack << std::dec << std::endl;
}
return;
}
for (size_t i = 0; i < acks.size(); ++i) {
uint64_t a = acks[i];
uint64_t ack;
ASSERT_TRUE(buf.Read(offset, 8, &ack));
offset += 8;
if (a != ack) {
ADD_FAILURE() << "Wrong ack " << i << " expected=0x" << std::hex << a
<< " got=0x" << ack << std::dec;
}
}
}
void CheckedHandshakeSendReceive() {
Handshake();
CheckPostHandshake();
@@ -199,7 +200,7 @@ TEST_P(TlsDropDatagram13, DropClientFirstFlightOnce) {
client_->Handshake();
server_->Handshake();
CheckedHandshakeSendReceive();
CheckAcks(server_filters_, 0, {0x0002000000000000ULL});
CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL});
}
TEST_P(TlsDropDatagram13, DropServerFirstFlightOnce) {
@@ -210,7 +211,7 @@ TEST_P(TlsDropDatagram13, DropServerFirstFlightOnce) {
server_->Handshake();
server_filters_.drop_->Disable();
CheckedHandshakeSendReceive();
CheckAcks(server_filters_, 0, {0x0002000000000000ULL});
CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL});
}
// Dropping the server's first record also does not produce
@@ -223,7 +224,7 @@ TEST_P(TlsDropDatagram13, DropServerFirstRecordOnce) {
server_->Handshake();
Handshake();
CheckedHandshakeSendReceive();
CheckAcks(server_filters_, 0, {0x0002000000000000ULL});
CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL});
}
// Dropping the second packet of the server's flight should
@@ -236,8 +237,8 @@ TEST_P(TlsDropDatagram13, DropServerSecondRecordOnce) {
HandshakeAndAck(client_);
expected_client_acks_ = 1;
CheckedHandshakeSendReceive();
CheckAcks(client_filters_, 0, {0}); // ServerHello
CheckAcks(server_filters_, 0, {0x0002000000000000ULL});
CheckAcks(client_filters_.ack_, 0, {0}); // ServerHello
CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL});
}
// Drop the server ACK and verify that the client retransmits
@@ -265,8 +266,8 @@ TEST_P(TlsDropDatagram13, DropServerAckOnce) {
EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
CheckPostHandshake();
// There should be two copies of the finished ACK
CheckAcks(server_filters_, 0, {0x0002000000000000ULL});
CheckAcks(server_filters_, 1, {0x0002000000000000ULL});
CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL});
CheckAcks(server_filters_.ack_, 1, {0x0002000000000000ULL});
}
// Drop the client certificate verify.
@@ -281,10 +282,10 @@ TEST_P(TlsDropDatagram13, DropClientCertVerify) {
expected_server_acks_ = 2;
CheckedHandshakeSendReceive();
// Ack of the Cert.
CheckAcks(server_filters_, 0, {0x0002000000000000ULL});
CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL});
// Ack of the whole client handshake.
CheckAcks(
server_filters_, 1,
server_filters_.ack_, 1,
{0x0002000000000000ULL, // CH (we drop everything after this on client)
0x0002000000000003ULL, // CT (2)
0x0002000000000004ULL}); // FIN (2)
@@ -310,11 +311,11 @@ TEST_P(TlsDropDatagram13, DropFirstHalfOfServerCertificate) {
// as the previous CT1).
EXPECT_EQ(ct1_size, server_filters_.record(0).buffer.len());
CheckedHandshakeSendReceive();
CheckAcks(client_filters_, 0,
CheckAcks(client_filters_.ack_, 0,
{0, // SH
0x0002000000000000ULL, // EE
0x0002000000000002ULL}); // CT2
CheckAcks(server_filters_, 0, {0x0002000000000000ULL});
CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL});
}
// Shrink the MTU down so that certs get split and drop the second piece.
@@ -336,13 +337,13 @@ TEST_P(TlsDropDatagram13, DropSecondHalfOfServerCertificate) {
// Check that the first record is CT1
EXPECT_EQ(ct1_size, server_filters_.record(0).buffer.len());
CheckedHandshakeSendReceive();
CheckAcks(client_filters_, 0,
CheckAcks(client_filters_.ack_, 0,
{
0, // SH
0x0002000000000000ULL, // EE
0x0002000000000001ULL, // CT1
});
CheckAcks(server_filters_, 0, {0x0002000000000000ULL});
CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL});
}
// In this test, the Certificate message is sent four times, we drop all or part
@@ -392,18 +393,18 @@ class TlsFragmentationAndRecoveryTest : public TlsDropDatagram13 {
0, // SH
0x0002000000000000ULL // EE
};
CheckAcks(client_filters_, 0, client_acks);
CheckAcks(client_filters_.ack_, 0, client_acks);
// And from the second attempt for the half was kept (we delayed this ACK).
client_acks.push_back(0x0002000000000000ULL + second_flight_count +
~dropped_half % 2);
CheckAcks(client_filters_, 1, client_acks);
CheckAcks(client_filters_.ack_, 1, client_acks);
// And the third attempt where the first and last thirds got through.
client_acks.push_back(0x0002000000000000ULL + second_flight_count +
third_flight_count - 1);
client_acks.push_back(0x0002000000000000ULL + second_flight_count +
third_flight_count + 1);
CheckAcks(client_filters_, 2, client_acks);
CheckAcks(server_filters_, 0, {0x0002000000000000ULL});
CheckAcks(client_filters_.ack_, 2, client_acks);
CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL});
}
private:
@@ -548,7 +549,7 @@ TEST_P(TlsDropDatagram13, NoDropsDuringZeroRtt) {
CheckConnected();
SendReceive();
EXPECT_EQ(0U, client_filters_.ack_->count());
CheckAcks(server_filters_, 0,
CheckAcks(server_filters_.ack_, 0,
{0x0001000000000001ULL, // EOED
0x0002000000000000ULL}); // Finished
}
@@ -567,8 +568,8 @@ TEST_P(TlsDropDatagram13, DropEEDuringZeroRtt) {
ExpectEarlyDataAccepted(true);
CheckConnected();
SendReceive();
CheckAcks(client_filters_, 0, {0});
CheckAcks(server_filters_, 0,
CheckAcks(client_filters_.ack_, 0, {0});
CheckAcks(server_filters_.ack_, 0,
{0x0001000000000002ULL, // EOED
0x0002000000000000ULL}); // Finished
}
@@ -608,22 +609,22 @@ TEST_P(TlsDropDatagram13, ReorderServerEE) {
expected_client_acks_ = 1;
HandshakeAndAck(client_);
CheckedHandshakeSendReceive();
CheckAcks(client_filters_, 0,
CheckAcks(client_filters_.ack_, 0,
{
0, // SH
0x0002000000000000, // EE
});
CheckAcks(server_filters_, 0, {0x0002000000000000ULL});
CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL});
}
// The client sends an out of order non-handshake message
// but with the handshake key.
class TlsSendCipherSpecCapturer {
public:
TlsSendCipherSpecCapturer(std::shared_ptr<TlsAgent>& agent)
: send_cipher_specs_() {
SSLInt_SetCipherSpecChangeFunc(agent->ssl_fd(), CipherSpecChanged,
(void*)this);
TlsSendCipherSpecCapturer(const std::shared_ptr<TlsAgent>& agent)
: agent_(agent), send_cipher_specs_() {
EXPECT_EQ(SECSuccess,
SSL_SecretCallback(agent_->ssl_fd(), SecretCallback, this));
}
std::shared_ptr<TlsCipherSpec> spec(size_t i) {
@@ -634,28 +635,42 @@ class TlsSendCipherSpecCapturer {
}
private:
static void CipherSpecChanged(void* arg, PRBool sending,
ssl3CipherSpec* newSpec) {
if (!sending) {
static void SecretCallback(PRFileDesc* fd, PRUint16 epoch,
SSLSecretDirection dir, PK11SymKey* secret,
void* arg) {
auto self = static_cast<TlsSendCipherSpecCapturer*>(arg);
std::cerr << self->agent_->role_str() << ": capture " << dir
<< " secret for epoch " << epoch << std::endl;
if (dir == ssl_secret_read) {
return;
}
auto self = static_cast<TlsSendCipherSpecCapturer*>(arg);
SSLPreliminaryChannelInfo preinfo;
EXPECT_EQ(SECSuccess,
SSL_GetPreliminaryChannelInfo(self->agent_->ssl_fd(), &preinfo,
sizeof(preinfo)));
EXPECT_EQ(sizeof(preinfo), preinfo.length);
EXPECT_TRUE(preinfo.valuesSet & ssl_preinfo_cipher_suite);
auto spec = std::make_shared<TlsCipherSpec>();
bool ret = spec->Init(SSLInt_CipherSpecToEpoch(newSpec),
SSLInt_CipherSpecToAlgorithm(newSpec),
SSLInt_CipherSpecToKey(newSpec),
SSLInt_CipherSpecToIv(newSpec));
EXPECT_EQ(true, ret);
SSLCipherSuiteInfo cipherinfo;
EXPECT_EQ(SECSuccess,
SSL_GetCipherSuiteInfo(preinfo.cipherSuite, &cipherinfo,
sizeof(cipherinfo)));
EXPECT_EQ(sizeof(cipherinfo), cipherinfo.length);
auto spec = std::make_shared<TlsCipherSpec>(true, epoch);
EXPECT_TRUE(spec->SetKeys(&cipherinfo, secret));
self->send_cipher_specs_.push_back(spec);
}
std::shared_ptr<TlsAgent> agent_;
std::vector<std::shared_ptr<TlsCipherSpec>> send_cipher_specs_;
};
TEST_P(TlsDropDatagram13, SendOutOfOrderAppWithHandshakeKey) {
TEST_F(TlsConnectDatagram13, SendOutOfOrderAppWithHandshakeKey) {
StartConnect();
// Capturing secrets means that we can't use decrypting filters on the client.
TlsSendCipherSpecCapturer capturer(client_);
client_->Handshake();
server_->Handshake();
@@ -680,9 +695,12 @@ TEST_P(TlsDropDatagram13, SendOutOfOrderAppWithHandshakeKey) {
EXPECT_EQ(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE, PORT_GetError());
}
TEST_P(TlsDropDatagram13, SendOutOfOrderHsNonsenseWithHandshakeKey) {
TEST_F(TlsConnectDatagram13, SendOutOfOrderHsNonsenseWithHandshakeKey) {
StartConnect();
TlsSendCipherSpecCapturer capturer(client_);
auto acks = MakeTlsFilter<TlsRecordRecorder>(server_, ssl_ct_ack);
acks->EnableDecryption();
client_->Handshake();
server_->Handshake();
client_->Handshake();
@@ -699,10 +717,10 @@ TEST_P(TlsDropDatagram13, SendOutOfOrderHsNonsenseWithHandshakeKey) {
ssl_ct_handshake,
DataBuffer(buf, sizeof(buf))));
server_->Handshake();
EXPECT_EQ(2UL, server_filters_.ack_->count());
EXPECT_EQ(2UL, acks->count());
// The server acknowledges client Finished twice.
CheckAcks(server_filters_, 0, {0x0002000000000000ULL});
CheckAcks(server_filters_, 1, {0x0002000000000000ULL});
CheckAcks(acks, 0, {0x0002000000000000ULL});
CheckAcks(acks, 1, {0x0002000000000000ULL});
}
// Shrink the MTU down so that certs get split and then swap the first and
@@ -726,7 +744,7 @@ TEST_P(TlsReorderDatagram13, ReorderServerCertificate) {
ShiftDtlsTimers();
CheckedHandshakeSendReceive();
EXPECT_EQ(2UL, server_filters_.records_->count()); // ACK + Data
CheckAcks(server_filters_, 0, {0x0002000000000000ULL});
CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL});
}
TEST_P(TlsReorderDatagram13, DataAfterEOEDDuringZeroRtt) {
@@ -761,7 +779,8 @@ TEST_P(TlsReorderDatagram13, DataAfterEOEDDuringZeroRtt) {
CheckConnected();
EXPECT_EQ(0U, client_filters_.ack_->count());
// Acknowledgements for EOED and Finished.
CheckAcks(server_filters_, 0, {0x0001000000000002ULL, 0x0002000000000000ULL});
CheckAcks(server_filters_.ack_, 0,
{0x0001000000000002ULL, 0x0002000000000000ULL});
uint8_t buf[8];
rv = PR_Read(server_->ssl_fd(), buf, sizeof(buf));
EXPECT_EQ(-1, rv);
@@ -800,7 +819,8 @@ TEST_P(TlsReorderDatagram13, DataAfterFinDuringZeroRtt) {
CheckConnected();
EXPECT_EQ(0U, client_filters_.ack_->count());
// Acknowledgements for EOED and Finished.
CheckAcks(server_filters_, 0, {0x0001000000000002ULL, 0x0002000000000000ULL});
CheckAcks(server_filters_.ack_, 0,
{0x0001000000000002ULL, 0x0002000000000000ULL});
uint8_t buf[8];
rv = PR_Read(server_->ssl_fd(), buf, sizeof(buf));
EXPECT_EQ(-1, rv);
@@ -482,6 +482,73 @@ TEST_P(TlsExtensionTestGeneric, SupportedCurvesTrailingData) {
client_, ssl_elliptic_curves_xtn, extension));
}
TEST_P(TlsExtensionTest12, SupportedCurvesDisableX25519) {
// Disable session resumption.
ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
// Ensure that we can enable its use in the key exchange.
SECStatus rv =
NSS_SetAlgorithmPolicy(SEC_OID_CURVE25519, NSS_USE_ALG_IN_SSL_KX, 0);
ASSERT_EQ(SECSuccess, rv);
rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL,
0);
ASSERT_EQ(SECSuccess, rv);
auto capture1 =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_elliptic_curves_xtn);
Connect();
EXPECT_TRUE(capture1->captured());
const DataBuffer& ext1 = capture1->extension();
uint32_t count;
ASSERT_TRUE(ext1.Read(0, 2, &count));
// Whether or not we've seen x25519 offered in this handshake.
bool seen1_x25519 = false;
for (size_t offset = 2; offset <= count; offset++) {
uint32_t val;
ASSERT_TRUE(ext1.Read(offset, 2, &val));
if (val == ssl_grp_ec_curve25519) {
seen1_x25519 = true;
break;
}
}
ASSERT_TRUE(seen1_x25519);
// Ensure that we can disable its use in the key exchange.
rv = NSS_SetAlgorithmPolicy(SEC_OID_CURVE25519, 0, NSS_USE_ALG_IN_SSL_KX);
ASSERT_EQ(SECSuccess, rv);
rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL,
0);
ASSERT_EQ(SECSuccess, rv);
// Clean up after the last run.
Reset();
auto capture2 =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_elliptic_curves_xtn);
Connect();
EXPECT_TRUE(capture2->captured());
const DataBuffer& ext2 = capture2->extension();
ASSERT_TRUE(ext2.Read(0, 2, &count));
// Whether or not we've seen x25519 offered in this handshake.
bool seen2_x25519 = false;
for (size_t offset = 2; offset <= count; offset++) {
uint32_t val;
ASSERT_TRUE(ext2.Read(offset, 2, &val));
if (val == ssl_grp_ec_curve25519) {
seen2_x25519 = true;
break;
}
}
ASSERT_FALSE(seen2_x25519);
}
TEST_P(TlsExtensionTestPre13, SupportedPointsEmpty) {
const uint8_t val[] = {0x00};
DataBuffer extension(val, sizeof(val));
@@ -547,6 +614,56 @@ TEST_P(TlsExtensionTest12, SignatureAlgorithmConfiguration) {
}
}
// This only works on TLS 1.2, since it relies on DSA.
TEST_P(TlsExtensionTest12, SignatureAlgorithmDisableDSA) {
const std::vector<SSLSignatureScheme> schemes = {
ssl_sig_dsa_sha1, ssl_sig_dsa_sha256, ssl_sig_dsa_sha384,
ssl_sig_dsa_sha512, ssl_sig_rsa_pss_rsae_sha256};
// Connect with DSA enabled by policy.
SECStatus rv = NSS_SetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE,
NSS_USE_ALG_IN_SSL_KX, 0);
ASSERT_EQ(SECSuccess, rv);
rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL,
0);
ASSERT_EQ(SECSuccess, rv);
Reset(TlsAgent::kServerDsa);
auto capture1 =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_signature_algorithms_xtn);
client_->SetSignatureSchemes(schemes.data(), schemes.size());
Connect();
// Check if all the signature algorithms are advertised.
EXPECT_TRUE(capture1->captured());
const DataBuffer& ext1 = capture1->extension();
EXPECT_EQ(2U + 2U * schemes.size(), ext1.len());
// Connect with DSA disabled by policy.
rv = NSS_SetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, 0,
NSS_USE_ALG_IN_SSL_KX);
ASSERT_EQ(SECSuccess, rv);
rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL,
0);
ASSERT_EQ(SECSuccess, rv);
Reset(TlsAgent::kServerDsa);
auto capture2 =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_signature_algorithms_xtn);
client_->SetSignatureSchemes(schemes.data(), schemes.size());
ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
// Check if no DSA algorithms are advertised.
EXPECT_TRUE(capture2->captured());
const DataBuffer& ext2 = capture2->extension();
EXPECT_EQ(2U + 2U, ext2.len());
uint32_t v = 0;
EXPECT_TRUE(ext2.Read(2, 2, &v));
EXPECT_EQ(ssl_sig_rsa_pss_rsae_sha256, v);
}
// Temporary test to verify that we choke on an empty ClientKeyShare.
// This test will fail when we implement HelloRetryRequest.
TEST_P(TlsExtensionTest13, EmptyClientKeyShare) {
@@ -1121,6 +1238,10 @@ INSTANTIATE_TEST_CASE_P(
INSTANTIATE_TEST_CASE_P(ExtensionDatagramOnly, TlsExtensionTestDtls,
TlsConnectTestBase::kTlsV11Plus);
INSTANTIATE_TEST_CASE_P(ExtensionTls12, TlsExtensionTest12,
::testing::Combine(TlsConnectTestBase::kTlsVariantsAll,
TlsConnectTestBase::kTlsV12));
INSTANTIATE_TEST_CASE_P(ExtensionTls12Plus, TlsExtensionTest12Plus,
::testing::Combine(TlsConnectTestBase::kTlsVariantsAll,
TlsConnectTestBase::kTlsV12Plus));
@@ -36,7 +36,9 @@
'ssl_keyupdate_unittest.cc',
'ssl_loopback_unittest.cc',
'ssl_misc_unittest.cc',
'ssl_primitive_unittest.cc',
'ssl_record_unittest.cc',
'ssl_recordsep_unittest.cc',
'ssl_recordsize_unittest.cc',
'ssl_resumption_unittest.cc',
'ssl_renegotiation_unittest.cc',
@@ -0,0 +1,217 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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 <memory>
#include "keyhi.h"
#include "pk11pub.h"
#include "secerr.h"
#include "ssl.h"
#include "sslerr.h"
#include "sslexp.h"
#include "sslproto.h"
#include "gtest_utils.h"
#include "nss_scoped_ptrs.h"
#include "scoped_ptrs_ssl.h"
#include "tls_connect.h"
namespace nss_test {
// From tls_hkdf_unittest.cc:
extern size_t GetHashLength(SSLHashType ht);
class AeadTest : public ::testing::Test {
public:
AeadTest() : slot_(PK11_GetInternalSlot()) {}
void InitSecret(SSLHashType hash_type) {
static const uint8_t kData[64] = {'s', 'e', 'c', 'r', 'e', 't'};
SECItem key_item = {siBuffer, const_cast<uint8_t *>(kData),
static_cast<unsigned int>(GetHashLength(hash_type))};
PK11SymKey *s =
PK11_ImportSymKey(slot_.get(), CKM_SSL3_MASTER_KEY_DERIVE,
PK11_OriginUnwrap, CKA_DERIVE, &key_item, NULL);
ASSERT_NE(nullptr, s);
secret_.reset(s);
}
void SetUp() override {
InitSecret(ssl_hash_sha256);
PORT_SetError(0);
}
protected:
static void EncryptDecrypt(const ScopedSSLAeadContext &ctx,
const uint8_t *ciphertext, size_t ciphertext_len) {
static const uint8_t kAad[] = {'a', 'a', 'd'};
static const uint8_t kPlaintext[] = {'t', 'e', 'x', 't'};
static const size_t kMaxSize = 32;
ASSERT_GE(kMaxSize, ciphertext_len);
uint8_t output[kMaxSize];
unsigned int output_len = 0;
EXPECT_EQ(SECSuccess, SSL_AeadEncrypt(ctx.get(), 0, kAad, sizeof(kAad),
kPlaintext, sizeof(kPlaintext),
output, &output_len, sizeof(output)));
ASSERT_EQ(ciphertext_len, static_cast<size_t>(output_len));
EXPECT_EQ(0, memcmp(ciphertext, output, ciphertext_len));
memset(output, 0, sizeof(output));
EXPECT_EQ(SECSuccess, SSL_AeadDecrypt(ctx.get(), 0, kAad, sizeof(kAad),
ciphertext, ciphertext_len, output,
&output_len, sizeof(output)));
ASSERT_EQ(sizeof(kPlaintext), static_cast<size_t>(output_len));
EXPECT_EQ(0, memcmp(kPlaintext, output, sizeof(kPlaintext)));
// Now for some tests of decryption failure.
// Truncate the input.
EXPECT_EQ(SECFailure, SSL_AeadDecrypt(ctx.get(), 0, kAad, sizeof(kAad),
ciphertext, ciphertext_len - 1,
output, &output_len, sizeof(output)));
EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError());
// Skip the first byte of the AAD.
EXPECT_EQ(
SECFailure,
SSL_AeadDecrypt(ctx.get(), 0, kAad + 1, sizeof(kAad) - 1, ciphertext,
ciphertext_len, output, &output_len, sizeof(output)));
EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError());
uint8_t input[kMaxSize] = {0};
// Toggle a byte of the input.
memcpy(input, ciphertext, ciphertext_len);
input[0] ^= 9;
EXPECT_EQ(SECFailure, SSL_AeadDecrypt(ctx.get(), 0, kAad, sizeof(kAad),
input, ciphertext_len, output,
&output_len, sizeof(output)));
EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError());
// Toggle the last byte (the auth tag).
memcpy(input, ciphertext, ciphertext_len);
input[ciphertext_len - 1] ^= 77;
EXPECT_EQ(SECFailure, SSL_AeadDecrypt(ctx.get(), 0, kAad, sizeof(kAad),
input, ciphertext_len, output,
&output_len, sizeof(output)));
EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError());
// Toggle some of the AAD.
memcpy(input, kAad, sizeof(kAad));
input[1] ^= 23;
EXPECT_EQ(SECFailure, SSL_AeadDecrypt(ctx.get(), 0, input, sizeof(kAad),
ciphertext, ciphertext_len, output,
&output_len, sizeof(output)));
EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError());
}
protected:
ScopedPK11SymKey secret_;
private:
ScopedPK11SlotInfo slot_;
};
// These tests all use fixed inputs: a fixed secret, a fixed label, and fixed
// inputs. So they have fixed outputs.
static const char *kLabel = "test ";
static const uint8_t kCiphertextAes128Gcm[] = {
0x11, 0x14, 0xfc, 0x58, 0x4f, 0x44, 0xff, 0x8c, 0xb6, 0xd8,
0x20, 0xb3, 0xfb, 0x50, 0xd9, 0x3b, 0xd4, 0xc6, 0xe1, 0x14};
static const uint8_t kCiphertextAes256Gcm[] = {
0xf7, 0x27, 0x35, 0x80, 0x88, 0xaf, 0x99, 0x85, 0xf2, 0x83,
0xca, 0xbb, 0x95, 0x42, 0x09, 0x3f, 0x9c, 0xf3, 0x29, 0xf0};
static const uint8_t kCiphertextChaCha20Poly1305[] = {
0x4e, 0x89, 0x2c, 0xfa, 0xfc, 0x8c, 0x40, 0x55, 0x6d, 0x7e,
0x99, 0xac, 0x8e, 0x54, 0x58, 0xb1, 0x18, 0xd2, 0x66, 0x22};
TEST_F(AeadTest, AeadBadVersion) {
SSLAeadContext *ctx = nullptr;
ASSERT_EQ(SECFailure,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256,
secret_.get(), kLabel, strlen(kLabel), &ctx));
EXPECT_EQ(nullptr, ctx);
}
TEST_F(AeadTest, AeadUnsupportedCipher) {
SSLAeadContext *ctx = nullptr;
ASSERT_EQ(SECFailure,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_RSA_WITH_NULL_MD5,
secret_.get(), kLabel, strlen(kLabel), &ctx));
EXPECT_EQ(nullptr, ctx);
}
TEST_F(AeadTest, AeadOlderCipher) {
SSLAeadContext *ctx = nullptr;
ASSERT_EQ(
SECFailure,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_RSA_WITH_AES_128_CBC_SHA,
secret_.get(), kLabel, strlen(kLabel), &ctx));
EXPECT_EQ(nullptr, ctx);
}
TEST_F(AeadTest, AeadNoLabel) {
SSLAeadContext *ctx = nullptr;
ASSERT_EQ(SECFailure,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_128_GCM_SHA256,
secret_.get(), nullptr, 12, &ctx));
EXPECT_EQ(nullptr, ctx);
}
TEST_F(AeadTest, AeadLongLabel) {
SSLAeadContext *ctx = nullptr;
ASSERT_EQ(SECFailure,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_128_GCM_SHA256,
secret_.get(), "", 254, &ctx));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
EXPECT_EQ(nullptr, ctx);
}
TEST_F(AeadTest, AeadNoPointer) {
SSLAeadContext *ctx = nullptr;
ASSERT_EQ(SECFailure,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_128_GCM_SHA256,
secret_.get(), kLabel, strlen(kLabel), nullptr));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
EXPECT_EQ(nullptr, ctx);
}
TEST_F(AeadTest, AeadAes128Gcm) {
SSLAeadContext *ctxInit;
ASSERT_EQ(SECSuccess,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_128_GCM_SHA256,
secret_.get(), kLabel, strlen(kLabel), &ctxInit));
ScopedSSLAeadContext ctx(ctxInit);
EXPECT_NE(nullptr, ctx);
EncryptDecrypt(ctx, kCiphertextAes128Gcm, sizeof(kCiphertextAes128Gcm));
}
TEST_F(AeadTest, AeadAes256Gcm) {
SSLAeadContext *ctxInit;
ASSERT_EQ(SECSuccess,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_256_GCM_SHA384,
secret_.get(), kLabel, strlen(kLabel), &ctxInit));
ScopedSSLAeadContext ctx(ctxInit);
EXPECT_NE(nullptr, ctx);
EncryptDecrypt(ctx, kCiphertextAes256Gcm, sizeof(kCiphertextAes256Gcm));
}
TEST_F(AeadTest, AeadChaCha20Poly1305) {
SSLAeadContext *ctxInit;
ASSERT_EQ(
SECSuccess,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_CHACHA20_POLY1305_SHA256,
secret_.get(), kLabel, strlen(kLabel), &ctxInit));
ScopedSSLAeadContext ctx(ctxInit);
EXPECT_NE(nullptr, ctx);
EncryptDecrypt(ctx, kCiphertextChaCha20Poly1305,
sizeof(kCiphertextChaCha20Poly1305));
}
} // namespace nss_test
@@ -0,0 +1,576 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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 "secerr.h"
#include "ssl.h"
#include "sslerr.h"
#include "sslproto.h"
extern "C" {
// This is not something that should make you happy.
#include "libssl_internals.h"
}
#include <queue>
#include "gtest_utils.h"
#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
namespace nss_test {
class HandshakeSecretTracker {
public:
HandshakeSecretTracker(const std::shared_ptr<TlsAgent>& agent,
uint16_t first_read_epoch, uint16_t first_write_epoch)
: agent_(agent),
next_read_epoch_(first_read_epoch),
next_write_epoch_(first_write_epoch) {
EXPECT_EQ(SECSuccess,
SSL_SecretCallback(agent_->ssl_fd(),
HandshakeSecretTracker::SecretCb, this));
}
void CheckComplete() const {
EXPECT_EQ(0, next_read_epoch_);
EXPECT_EQ(0, next_write_epoch_);
}
private:
static void SecretCb(PRFileDesc* fd, PRUint16 epoch, SSLSecretDirection dir,
PK11SymKey* secret, void* arg) {
HandshakeSecretTracker* t = reinterpret_cast<HandshakeSecretTracker*>(arg);
t->SecretUpdated(epoch, dir, secret);
}
void SecretUpdated(PRUint16 epoch, SSLSecretDirection dir,
PK11SymKey* secret) {
if (g_ssl_gtest_verbose) {
std::cerr << agent_->role_str() << ": secret callback for " << dir
<< " epoch " << epoch << std::endl;
}
EXPECT_TRUE(secret);
uint16_t* p;
if (dir == ssl_secret_read) {
p = &next_read_epoch_;
} else {
ASSERT_EQ(ssl_secret_write, dir);
p = &next_write_epoch_;
}
EXPECT_EQ(*p, epoch);
switch (*p) {
case 1: // 1 == 0-RTT, next should be handshake.
case 2: // 2 == handshake, next should be application data.
(*p)++;
break;
case 3: // 3 == application data, there should be no more.
// Use 0 as a sentinel value.
*p = 0;
break;
default:
ADD_FAILURE() << "Unexpected next epoch: " << *p;
}
}
std::shared_ptr<TlsAgent> agent_;
uint16_t next_read_epoch_;
uint16_t next_write_epoch_;
};
TEST_F(TlsConnectTest, HandshakeSecrets) {
ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
EnsureTlsSetup();
HandshakeSecretTracker c(client_, 2, 2);
HandshakeSecretTracker s(server_, 2, 2);
Connect();
SendReceive();
c.CheckComplete();
s.CheckComplete();
}
TEST_F(TlsConnectTest, ZeroRttSecrets) {
SetupForZeroRtt();
HandshakeSecretTracker c(client_, 2, 1);
HandshakeSecretTracker s(server_, 1, 2);
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
ExpectResumption(RESUME_TICKET);
ZeroRttSendReceive(true, true);
Handshake();
ExpectEarlyDataAccepted(true);
CheckConnected();
SendReceive();
c.CheckComplete();
s.CheckComplete();
}
class KeyUpdateTracker {
public:
KeyUpdateTracker(const std::shared_ptr<TlsAgent>& agent,
bool expect_read_secret)
: agent_(agent), expect_read_secret_(expect_read_secret), called_(false) {
EXPECT_EQ(SECSuccess, SSL_SecretCallback(agent_->ssl_fd(),
KeyUpdateTracker::SecretCb, this));
}
void CheckCalled() const { EXPECT_TRUE(called_); }
private:
static void SecretCb(PRFileDesc* fd, PRUint16 epoch, SSLSecretDirection dir,
PK11SymKey* secret, void* arg) {
KeyUpdateTracker* t = reinterpret_cast<KeyUpdateTracker*>(arg);
t->SecretUpdated(epoch, dir, secret);
}
void SecretUpdated(PRUint16 epoch, SSLSecretDirection dir,
PK11SymKey* secret) {
EXPECT_EQ(4U, epoch);
EXPECT_EQ(expect_read_secret_, dir == ssl_secret_read);
EXPECT_TRUE(secret);
called_ = true;
}
std::shared_ptr<TlsAgent> agent_;
bool expect_read_secret_;
bool called_;
};
TEST_F(TlsConnectTest, KeyUpdateSecrets) {
ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
Connect();
// The update is to the client write secret; the server read secret.
KeyUpdateTracker c(client_, false);
KeyUpdateTracker s(server_, true);
EXPECT_EQ(SECSuccess, SSL_KeyUpdate(client_->ssl_fd(), PR_FALSE));
SendReceive(50);
SendReceive(60);
CheckEpochs(4, 3);
c.CheckCalled();
s.CheckCalled();
}
// BadPrSocket is an instance of a PR IO layer that crashes the test if it is
// ever used for reading or writing. It does that by failing to overwrite any
// of the DummyIOLayerMethods, which all crash when invoked.
class BadPrSocket : public DummyIOLayerMethods {
public:
BadPrSocket(std::shared_ptr<TlsAgent>& agent) : DummyIOLayerMethods() {
static PRDescIdentity bad_identity = PR_GetUniqueIdentity("bad NSPR id");
fd_ = DummyIOLayerMethods::CreateFD(bad_identity, this);
// This is terrible, but NSPR doesn't provide an easy way to replace the
// bottom layer of an IO stack. Take the DummyPrSocket and replace its
// NSPR method vtable with the ones from this object.
dummy_layer_ =
PR_GetIdentitiesLayer(agent->ssl_fd(), DummyPrSocket::LayerId());
original_methods_ = dummy_layer_->methods;
original_secret_ = dummy_layer_->secret;
dummy_layer_->methods = fd_->methods;
dummy_layer_->secret = reinterpret_cast<PRFilePrivate*>(this);
}
// This will be destroyed before the agent, so we need to restore the state
// before we tampered with it.
virtual ~BadPrSocket() {
dummy_layer_->methods = original_methods_;
dummy_layer_->secret = original_secret_;
}
private:
ScopedPRFileDesc fd_;
PRFileDesc* dummy_layer_;
const PRIOMethods* original_methods_;
PRFilePrivate* original_secret_;
};
class StagedRecords {
public:
StagedRecords(std::shared_ptr<TlsAgent>& agent) : agent_(agent), records_() {
EXPECT_EQ(SECSuccess,
SSL_RecordLayerWriteCallback(
agent_->ssl_fd(), StagedRecords::StageRecordData, this));
}
virtual ~StagedRecords() {
// Uninstall so that the callback doesn't fire during cleanup.
EXPECT_EQ(SECSuccess,
SSL_RecordLayerWriteCallback(agent_->ssl_fd(), nullptr, nullptr));
}
bool empty() const { return records_.empty(); }
void ForwardAll(std::shared_ptr<TlsAgent>& peer) {
EXPECT_NE(agent_, peer) << "can't forward to self";
for (auto r : records_) {
r.Forward(peer);
}
records_.clear();
}
// This forwards all saved data and checks the resulting state.
void ForwardAll(std::shared_ptr<TlsAgent>& peer,
TlsAgent::State expected_state) {
ForwardAll(peer);
switch (expected_state) {
case TlsAgent::STATE_CONNECTED:
// The handshake callback should have been called, so check that before
// checking that SSL_ForceHandshake succeeds.
EXPECT_EQ(expected_state, peer->state());
EXPECT_EQ(SECSuccess, SSL_ForceHandshake(peer->ssl_fd()));
break;
case TlsAgent::STATE_CONNECTING:
// Check that SSL_ForceHandshake() blocks.
EXPECT_EQ(SECFailure, SSL_ForceHandshake(peer->ssl_fd()));
EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
// Update and check the state.
peer->Handshake();
EXPECT_EQ(TlsAgent::STATE_CONNECTING, peer->state());
break;
default:
ADD_FAILURE() << "No idea how to handle this state";
}
}
void ForwardPartial(std::shared_ptr<TlsAgent>& peer) {
if (records_.empty()) {
ADD_FAILURE() << "No records to slice";
return;
}
auto& last = records_.back();
auto tail = last.SliceTail();
ForwardAll(peer, TlsAgent::STATE_CONNECTING);
records_.push_back(tail);
EXPECT_EQ(TlsAgent::STATE_CONNECTING, peer->state());
}
private:
// A single record.
class StagedRecord {
public:
StagedRecord(const std::string role, uint16_t epoch, SSLContentType ct,
const uint8_t* data, size_t len)
: role_(role), epoch_(epoch), content_type_(ct), data_(data, len) {
if (g_ssl_gtest_verbose) {
std::cerr << role_ << ": staged epoch " << epoch_ << " "
<< content_type_ << ": " << data_ << std::endl;
}
}
// This forwards staged data to the identified agent.
void Forward(std::shared_ptr<TlsAgent>& peer) {
// Now there should be staged data.
EXPECT_FALSE(data_.empty());
if (g_ssl_gtest_verbose) {
std::cerr << role_ << ": forward " << data_ << std::endl;
}
EXPECT_EQ(SECSuccess,
SSL_RecordLayerData(peer->ssl_fd(), epoch_, content_type_,
data_.data(),
static_cast<unsigned int>(data_.len())));
}
// Slices the tail off this record and returns it.
StagedRecord SliceTail() {
size_t slice = 1;
if (data_.len() <= slice) {
ADD_FAILURE() << "record too small to slice in two";
slice = 0;
}
size_t keep = data_.len() - slice;
StagedRecord tail(role_, epoch_, content_type_, data_.data() + keep,
slice);
data_.Truncate(keep);
return tail;
}
private:
std::string role_;
uint16_t epoch_;
SSLContentType content_type_;
DataBuffer data_;
};
// This is an SSLRecordWriteCallback that stages data.
static SECStatus StageRecordData(PRFileDesc* fd, PRUint16 epoch,
SSLContentType content_type,
const PRUint8* data, unsigned int len,
void* arg) {
auto stage = reinterpret_cast<StagedRecords*>(arg);
stage->records_.push_back(StagedRecord(stage->agent_->role_str(), epoch,
content_type, data,
static_cast<size_t>(len)));
return SECSuccess;
}
std::shared_ptr<TlsAgent>& agent_;
std::deque<StagedRecord> records_;
};
// Attempting to feed application data in before the handshake is complete
// should be caught.
static void RefuseApplicationData(std::shared_ptr<TlsAgent>& peer,
uint16_t epoch) {
static const uint8_t d[] = {1, 2, 3};
EXPECT_EQ(SECFailure,
SSL_RecordLayerData(peer->ssl_fd(), epoch, ssl_ct_application_data,
d, static_cast<unsigned int>(sizeof(d))));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
}
static void SendForwardReceive(std::shared_ptr<TlsAgent>& sender,
StagedRecords& sender_stage,
std::shared_ptr<TlsAgent>& receiver) {
const size_t count = 10;
sender->SendData(count, count);
sender_stage.ForwardAll(receiver);
receiver->ReadBytes(count);
}
TEST_P(TlsConnectStream, ReplaceRecordLayer) {
StartConnect();
client_->SetServerKeyBits(server_->server_key_bits());
// BadPrSocket installs an IO layer that crashes when the SSL layer attempts
// to read or write.
BadPrSocket bad_layer_client(client_);
BadPrSocket bad_layer_server(server_);
// StagedRecords installs a handler for unprotected data from the socket, and
// captures that data.
StagedRecords client_stage(client_);
StagedRecords server_stage(server_);
// Both peers should refuse application data from epoch 0.
RefuseApplicationData(client_, 0);
RefuseApplicationData(server_, 0);
// This first call forwards nothing, but it causes the client to handshake,
// which starts things off. This stages the ClientHello as a result.
server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING);
// This processes the ClientHello and stages the first server flight.
client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTING);
RefuseApplicationData(server_, 1);
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
// Process the server flight and the client is done.
server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED);
client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED);
} else {
server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING);
RefuseApplicationData(client_, 1);
client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED);
server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED);
}
CheckKeys();
// Reading and writing application data should work.
SendForwardReceive(client_, client_stage, server_);
SendForwardReceive(server_, server_stage, client_);
}
static SECStatus AuthCompleteBlock(TlsAgent*, PRBool, PRBool) {
return SECWouldBlock;
}
TEST_P(TlsConnectStream, ReplaceRecordLayerAsyncLateAuth) {
StartConnect();
client_->SetServerKeyBits(server_->server_key_bits());
BadPrSocket bad_layer_client(client_);
BadPrSocket bad_layer_server(server_);
StagedRecords client_stage(client_);
StagedRecords server_stage(server_);
client_->SetAuthCertificateCallback(AuthCompleteBlock);
server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING);
client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTING);
server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING);
// Prior to TLS 1.3, the client sends its second flight immediately. But in
// TLS 1.3, a client won't send a Finished until it is happy with the server
// certificate. So blocking certificate validation causes the client to send
// nothing.
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
ASSERT_TRUE(client_stage.empty());
// Client should have stopped reading when it saw the Certificate message,
// so it will be reading handshake epoch, and writing cleartext.
client_->CheckEpochs(2, 0);
// Server should be reading handshake, and writing application data.
server_->CheckEpochs(2, 3);
// Handshake again and the client will read the remainder of the server's
// flight, but it will remain blocked.
client_->Handshake();
ASSERT_TRUE(client_stage.empty());
EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state());
} else {
// In prior versions, the client's second flight is always sent.
ASSERT_FALSE(client_stage.empty());
}
// Now declare the certificate good.
EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0));
client_->Handshake();
ASSERT_FALSE(client_stage.empty());
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
EXPECT_EQ(TlsAgent::STATE_CONNECTED, client_->state());
client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED);
} else {
client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED);
server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED);
}
CheckKeys();
// Reading and writing application data should work.
SendForwardReceive(client_, client_stage, server_);
}
TEST_F(TlsConnectStreamTls13, ReplaceRecordLayerAsyncPostHandshake) {
StartConnect();
client_->SetServerKeyBits(server_->server_key_bits());
BadPrSocket bad_layer_client(client_);
BadPrSocket bad_layer_server(server_);
StagedRecords client_stage(client_);
StagedRecords server_stage(server_);
client_->SetAuthCertificateCallback(AuthCompleteBlock);
server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING);
client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTING);
server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING);
ASSERT_TRUE(client_stage.empty());
client_->Handshake();
ASSERT_TRUE(client_stage.empty());
EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state());
// Now declare the certificate good.
EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0));
client_->Handshake();
ASSERT_FALSE(client_stage.empty());
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
EXPECT_EQ(TlsAgent::STATE_CONNECTED, client_->state());
client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED);
} else {
client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED);
server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED);
}
CheckKeys();
// Reading and writing application data should work.
SendForwardReceive(client_, client_stage, server_);
// Post-handshake messages should work here.
EXPECT_EQ(SECSuccess, SSL_SendSessionTicket(server_->ssl_fd(), nullptr, 0));
SendForwardReceive(server_, server_stage, client_);
}
// This test ensures that data is correctly forwarded when the handshake is
// resumed after asynchronous server certificate authentication, when
// SSL_AuthCertificateComplete() is called. The logic for resuming the
// handshake involves a different code path than the usual one, so this test
// exercises that code fully.
TEST_F(TlsConnectStreamTls13, ReplaceRecordLayerAsyncEarlyAuth) {
StartConnect();
client_->SetServerKeyBits(server_->server_key_bits());
BadPrSocket bad_layer_client(client_);
BadPrSocket bad_layer_server(server_);
StagedRecords client_stage(client_);
StagedRecords server_stage(server_);
client_->SetAuthCertificateCallback(AuthCompleteBlock);
server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING);
client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTING);
// Send a partial flight on to the client.
// This includes enough to trigger the certificate callback.
server_stage.ForwardPartial(client_);
EXPECT_TRUE(client_stage.empty());
// Declare the certificate good.
EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0));
client_->Handshake();
EXPECT_TRUE(client_stage.empty());
// Send the remainder of the server flight.
PRBool pending = PR_FALSE;
EXPECT_EQ(SECSuccess,
SSLInt_HasPendingHandshakeData(client_->ssl_fd(), &pending));
EXPECT_EQ(PR_TRUE, pending);
EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state());
server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED);
client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED);
CheckKeys();
SendForwardReceive(server_, server_stage, client_);
}
TEST_P(TlsConnectStream, ForwardDataFromWrongEpoch) {
const uint8_t data[] = {1};
Connect();
uint16_t next_epoch;
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
EXPECT_EQ(SECFailure,
SSL_RecordLayerData(client_->ssl_fd(), 2, ssl_ct_application_data,
data, sizeof(data)));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError())
<< "Passing data from an old epoch is rejected";
next_epoch = 4;
} else {
// Prior to TLS 1.3, the epoch is only updated once during the handshake.
next_epoch = 2;
}
EXPECT_EQ(SECFailure,
SSL_RecordLayerData(client_->ssl_fd(), next_epoch,
ssl_ct_application_data, data, sizeof(data)));
EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError())
<< "Passing data from a future epoch blocks";
}
TEST_F(TlsConnectStreamTls13, ForwardInvalidData) {
const uint8_t data[1] = {0};
EnsureTlsSetup();
// Zero-length data.
EXPECT_EQ(SECFailure, SSL_RecordLayerData(client_->ssl_fd(), 0,
ssl_ct_application_data, data, 0));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// NULL data.
EXPECT_EQ(SECFailure,
SSL_RecordLayerData(client_->ssl_fd(), 0, ssl_ct_application_data,
nullptr, 1));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
}
TEST_F(TlsConnectDatagram13, ForwardDataDtls) {
EnsureTlsSetup();
const uint8_t data[1] = {0};
EXPECT_EQ(SECFailure,
SSL_RecordLayerData(client_->ssl_fd(), 0, ssl_ct_application_data,
data, sizeof(data)));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
}
} // namespace nss_test
@@ -123,9 +123,11 @@ TEST_P(TlsConnectGeneric, RecordSizeMaximum) {
EnsureTlsSetup();
auto client_max = MakeTlsFilter<TlsRecordMaximum>(client_);
client_max->EnableDecryption();
auto server_max = MakeTlsFilter<TlsRecordMaximum>(server_);
server_max->EnableDecryption();
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
client_max->EnableDecryption();
server_max->EnableDecryption();
}
Connect();
client_->SendData(send_size, send_size);
@@ -140,7 +142,9 @@ TEST_P(TlsConnectGeneric, RecordSizeMaximum) {
TEST_P(TlsConnectGeneric, RecordSizeMinimumClient) {
EnsureTlsSetup();
auto server_max = MakeTlsFilter<TlsRecordMaximum>(server_);
server_max->EnableDecryption();
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
server_max->EnableDecryption();
}
client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64);
Connect();
@@ -152,7 +156,9 @@ TEST_P(TlsConnectGeneric, RecordSizeMinimumClient) {
TEST_P(TlsConnectGeneric, RecordSizeMinimumServer) {
EnsureTlsSetup();
auto client_max = MakeTlsFilter<TlsRecordMaximum>(client_);
client_max->EnableDecryption();
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
client_max->EnableDecryption();
}
server_->SetOption(SSL_RECORD_SIZE_LIMIT, 64);
Connect();
@@ -164,9 +170,11 @@ TEST_P(TlsConnectGeneric, RecordSizeMinimumServer) {
TEST_P(TlsConnectGeneric, RecordSizeAsymmetric) {
EnsureTlsSetup();
auto client_max = MakeTlsFilter<TlsRecordMaximum>(client_);
client_max->EnableDecryption();
auto server_max = MakeTlsFilter<TlsRecordMaximum>(server_);
server_max->EnableDecryption();
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
client_max->EnableDecryption();
server_max->EnableDecryption();
}
client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64);
server_->SetOption(SSL_RECORD_SIZE_LIMIT, 100);
@@ -256,9 +264,11 @@ class TlsRecordPadder : public TlsRecordFilter {
return KEEP;
}
uint16_t protection_epoch;
uint8_t inner_content_type;
DataBuffer plaintext;
if (!Unprotect(header, record, &inner_content_type, &plaintext)) {
if (!Unprotect(header, record, &protection_epoch, &inner_content_type,
&plaintext)) {
return KEEP;
}
@@ -267,8 +277,8 @@ class TlsRecordPadder : public TlsRecordFilter {
}
DataBuffer ciphertext;
bool ok =
Protect(header, inner_content_type, plaintext, &ciphertext, padding_);
bool ok = Protect(spec(protection_epoch), header, inner_content_type,
plaintext, &ciphertext, padding_);
EXPECT_TRUE(ok);
if (!ok) {
return KEEP;
@@ -334,7 +344,9 @@ TEST_P(TlsConnectGeneric, RecordSizeCapExtensionClient) {
client_->SetOption(SSL_RECORD_SIZE_LIMIT, 16385);
auto capture =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_record_size_limit_xtn);
capture->EnableDecryption();
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
capture->EnableDecryption();
}
Connect();
uint64_t val = 0;
@@ -352,7 +364,9 @@ TEST_P(TlsConnectGeneric, RecordSizeCapExtensionServer) {
server_->SetOption(SSL_RECORD_SIZE_LIMIT, 16385);
auto capture =
MakeTlsFilter<TlsExtensionCapture>(server_, ssl_record_size_limit_xtn);
capture->EnableDecryption();
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
capture->EnableDecryption();
}
Connect();
uint64_t val = 0;
@@ -393,10 +407,24 @@ TEST_P(TlsConnectGeneric, RecordSizeServerExtensionInvalid) {
static const uint8_t v[] = {0xf4, 0x1f};
auto replace = MakeTlsFilter<TlsExtensionReplacer>(
server_, ssl_record_size_limit_xtn, DataBuffer(v, sizeof(v)));
replace->EnableDecryption();
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
replace->EnableDecryption();
}
ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
}
TEST_P(TlsConnectGeneric, RecordSizeServerExtensionExtra) {
EnsureTlsSetup();
server_->SetOption(SSL_RECORD_SIZE_LIMIT, 1000);
static const uint8_t v[] = {0x01, 0x00, 0x00};
auto replace = MakeTlsFilter<TlsExtensionReplacer>(
server_, ssl_record_size_limit_xtn, DataBuffer(v, sizeof(v)));
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
replace->EnableDecryption();
}
ConnectExpectAlert(client_, kTlsAlertDecodeError);
}
class RecordSizeDefaultsTest : public ::testing::Test {
public:
void SetUp() {
@@ -214,12 +214,6 @@ class TestPolicyVersionRange
ASSERT_EQ(SECSuccess, rv);
rv = NSS_OptionSet(NSS_DTLS_VERSION_MAX_POLICY, saved_max_dtls_);
ASSERT_EQ(SECSuccess, rv);
// If it wasn't set initially, clear the bit that we set.
if (!(saved_algorithm_policy_ & NSS_USE_POLICY_IN_SSL)) {
rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, 0,
NSS_USE_POLICY_IN_SSL);
ASSERT_EQ(SECSuccess, rv);
}
}
private:
@@ -233,16 +227,12 @@ class TestPolicyVersionRange
ASSERT_EQ(SECSuccess, rv);
rv = NSS_OptionGet(NSS_DTLS_VERSION_MAX_POLICY, &saved_max_dtls_);
ASSERT_EQ(SECSuccess, rv);
rv = NSS_GetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY,
&saved_algorithm_policy_);
ASSERT_EQ(SECSuccess, rv);
}
int32_t saved_min_tls_;
int32_t saved_max_tls_;
int32_t saved_min_dtls_;
int32_t saved_max_dtls_;
uint32_t saved_algorithm_policy_;
};
VersionPolicy saved_version_policy_;
+8 -6
View File
@@ -25,10 +25,13 @@ namespace nss_test {
if (g_ssl_gtest_verbose) LOG(a); \
} while (false)
PRDescIdentity DummyPrSocket::LayerId() {
static PRDescIdentity id = PR_GetUniqueIdentity("dummysocket");
return id;
}
ScopedPRFileDesc DummyPrSocket::CreateFD() {
static PRDescIdentity test_fd_identity =
PR_GetUniqueIdentity("testtransportadapter");
return DummyIOLayerMethods::CreateFD(test_fd_identity, this);
return DummyIOLayerMethods::CreateFD(DummyPrSocket::LayerId(), this);
}
void DummyPrSocket::Reset() {
@@ -136,19 +139,18 @@ int32_t DummyPrSocket::Write(PRFileDesc *f, const void *buf, int32_t length) {
DataBuffer filtered;
PacketFilter::Action action = PacketFilter::KEEP;
if (filter_) {
LOGV("Original packet: " << packet);
action = filter_->Process(packet, &filtered);
}
switch (action) {
case PacketFilter::CHANGE:
LOG("Original packet: " << packet);
LOG("Filtered packet: " << filtered);
dst->PacketReceived(filtered);
break;
case PacketFilter::DROP:
LOG("Droppped packet: " << packet);
LOG("Drop packet");
break;
case PacketFilter::KEEP:
LOGV("Packet: " << packet);
dst->PacketReceived(packet);
break;
}
+2
View File
@@ -68,6 +68,8 @@ class DummyPrSocket : public DummyIOLayerMethods {
write_error_(0) {}
virtual ~DummyPrSocket() {}
static PRDescIdentity LayerId();
// Create a file descriptor that will reference this object. The fd must not
// live longer than this adapter; call PR_Close() before.
ScopedPRFileDesc CreateFD();
@@ -640,6 +640,16 @@ void TlsAgent::CheckAlpn(SSLNextProtoState expected_state,
}
}
void TlsAgent::CheckEpochs(uint16_t expected_read,
uint16_t expected_write) const {
uint16_t read_epoch = 0;
uint16_t write_epoch = 0;
EXPECT_EQ(SECSuccess,
SSL_GetCurrentEpoch(ssl_fd(), &read_epoch, &write_epoch));
EXPECT_EQ(expected_read, read_epoch) << role_str() << " read epoch";
EXPECT_EQ(expected_write, write_epoch) << role_str() << " write epoch";
}
void TlsAgent::EnableSrtp() {
EXPECT_TRUE(EnsureTlsSetup());
const uint16_t ciphers[] = {SRTP_AES128_CM_HMAC_SHA1_80,
@@ -139,6 +139,7 @@ class TlsAgent : public PollTarget {
const std::string& expected = "") const;
void EnableSrtp();
void CheckSrtp() const;
void CheckEpochs(uint16_t expected_read, uint16_t expected_write) const;
void CheckErrorCode(int32_t expected) const;
void WaitForErrorCode(int32_t expected, uint32_t delay) const;
// Send data on the socket, encrypting it.
+24 -12
View File
@@ -167,18 +167,8 @@ void TlsConnectTestBase::CheckShares(
void TlsConnectTestBase::CheckEpochs(uint16_t client_epoch,
uint16_t server_epoch) const {
uint16_t read_epoch = 0;
uint16_t write_epoch = 0;
EXPECT_EQ(SECSuccess,
SSLInt_GetEpochs(client_->ssl_fd(), &read_epoch, &write_epoch));
EXPECT_EQ(server_epoch, read_epoch) << "client read epoch";
EXPECT_EQ(client_epoch, write_epoch) << "client write epoch";
EXPECT_EQ(SECSuccess,
SSLInt_GetEpochs(server_->ssl_fd(), &read_epoch, &write_epoch));
EXPECT_EQ(client_epoch, read_epoch) << "server read epoch";
EXPECT_EQ(server_epoch, write_epoch) << "server write epoch";
client_->CheckEpochs(server_epoch, client_epoch);
server_->CheckEpochs(client_epoch, server_epoch);
}
void TlsConnectTestBase::ClearStats() {
@@ -193,12 +183,33 @@ void TlsConnectTestBase::ClearServerCache() {
SSL_ConfigServerSessionIDCache(1024, 0, 0, g_working_dir_path.c_str());
}
void TlsConnectTestBase::SaveAlgorithmPolicy() {
saved_policies_.clear();
for (auto it = algorithms_.begin(); it != algorithms_.end(); ++it) {
uint32_t policy;
SECStatus rv = NSS_GetAlgorithmPolicy(*it, &policy);
ASSERT_EQ(SECSuccess, rv);
saved_policies_.push_back(std::make_tuple(*it, policy));
}
}
void TlsConnectTestBase::RestoreAlgorithmPolicy() {
for (auto it = saved_policies_.begin(); it != saved_policies_.end(); ++it) {
auto algorithm = std::get<0>(*it);
auto policy = std::get<1>(*it);
SECStatus rv = NSS_SetAlgorithmPolicy(
algorithm, policy, NSS_USE_POLICY_IN_SSL | NSS_USE_ALG_IN_SSL_KX);
ASSERT_EQ(SECSuccess, rv);
}
}
void TlsConnectTestBase::SetUp() {
SSL_ConfigServerSessionIDCache(1024, 0, 0, g_working_dir_path.c_str());
SSLInt_ClearSelfEncryptKey();
SSLInt_SetTicketLifetime(30);
SSL_SetupAntiReplay(1 * PR_USEC_PER_SEC, 1, 3);
ClearStats();
SaveAlgorithmPolicy();
Init();
}
@@ -209,6 +220,7 @@ void TlsConnectTestBase::TearDown() {
SSL_ClearSessionCache();
SSLInt_ClearSelfEncryptKey();
SSL_ShutdownServerSessionIDCache();
RestoreAlgorithmPolicy();
}
void TlsConnectTestBase::Init() {
@@ -132,6 +132,9 @@ class TlsConnectTestBase : public ::testing::Test {
// Move the DTLS timers for both endpoints to pop the next timer.
void ShiftDtlsTimers();
void SaveAlgorithmPolicy();
void RestoreAlgorithmPolicy();
protected:
SSLProtocolVariant variant_;
std::shared_ptr<TlsAgent> client_;
@@ -149,6 +152,14 @@ class TlsConnectTestBase : public ::testing::Test {
// NSS will move this final entry to the front when used with ALPN.
const uint8_t alpn_dummy_val_[4] = {0x01, 0x62, 0x01, 0x61};
// A list of algorithm IDs whose policies need to be preserved
// around test cases. In particular, DSA is checked in
// ssl_extension_unittest.cc.
const std::vector<SECOidTag> algorithms_ = {SEC_OID_APPLY_SSL_POLICY,
SEC_OID_ANSIX9_DSA_SIGNATURE,
SEC_OID_CURVE25519};
std::vector<std::tuple<SECOidTag, uint32_t>> saved_policies_;
private:
void CheckResumption(SessionResumptionMode expected);
void CheckExtendedMasterSecret();
@@ -305,11 +305,14 @@ TEST_P(TlsConnectTls13, ConnectEsniHrr) {
server_, kTlsHandshakeHelloRetryRequest);
auto filter =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn);
auto cfilter =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn);
auto filter2 =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn, true);
client_->SetFilter(std::make_shared<ChainedPacketFilter>(
ChainedPacketFilterInit({filter, filter2})));
server_->SetSniCallback(SniCallback);
Connect();
CheckSniExtension(cfilter->extension());
CheckSniExtension(filter->extension());
CheckSniExtension(filter2->extension());
EXPECT_NE(0UL, hrr_capture->buffer().len());
}
+156 -75
View File
@@ -45,40 +45,65 @@ void TlsVersioned::WriteStream(std::ostream& stream) const {
}
}
void TlsRecordFilter::EnableDecryption() {
SSLInt_SetCipherSpecChangeFunc(agent()->ssl_fd(), CipherSpecChanged,
(void*)this);
TlsRecordFilter::TlsRecordFilter(const std::shared_ptr<TlsAgent>& a)
: agent_(a) {
cipher_specs_.emplace_back(a->variant() == ssl_variant_datagram, 0);
}
void TlsRecordFilter::CipherSpecChanged(void* arg, PRBool sending,
ssl3CipherSpec* newSpec) {
TlsRecordFilter* self = static_cast<TlsRecordFilter*>(arg);
PRBool isServer = self->agent()->role() == TlsAgent::SERVER;
void TlsRecordFilter::EnableDecryption() {
EXPECT_EQ(SECSuccess,
SSL_SecretCallback(agent()->ssl_fd(), SecretCallback, this));
decrypting_ = true;
}
void TlsRecordFilter::SecretCallback(PRFileDesc* fd, PRUint16 epoch,
SSLSecretDirection dir, PK11SymKey* secret,
void* arg) {
TlsRecordFilter* self = static_cast<TlsRecordFilter*>(arg);
if (g_ssl_gtest_verbose) {
std::cerr << (isServer ? "server" : "client") << ": "
<< (sending ? "send" : "receive")
<< " cipher spec changed: " << newSpec->epoch << " ("
<< newSpec->phase << ")" << std::endl;
std::cerr << self->agent()->role_str() << ": " << dir
<< " secret changed for epoch " << epoch << std::endl;
}
if (!sending) {
if (dir == ssl_secret_read) {
return;
}
uint64_t seq_no;
if (self->agent()->variant() == ssl_variant_datagram) {
seq_no = static_cast<uint64_t>(SSLInt_CipherSpecToEpoch(newSpec)) << 48;
} else {
seq_no = 0;
for (auto& spec : self->cipher_specs_) {
ASSERT_NE(spec.epoch(), epoch) << "duplicate spec for epoch " << epoch;
}
self->in_sequence_number_ = seq_no;
self->out_sequence_number_ = seq_no;
self->dropped_record_ = false;
self->cipher_spec_.reset(new TlsCipherSpec());
bool ret = self->cipher_spec_->Init(
SSLInt_CipherSpecToEpoch(newSpec), SSLInt_CipherSpecToAlgorithm(newSpec),
SSLInt_CipherSpecToKey(newSpec), SSLInt_CipherSpecToIv(newSpec));
EXPECT_EQ(true, ret);
SSLPreliminaryChannelInfo preinfo;
EXPECT_EQ(SECSuccess,
SSL_GetPreliminaryChannelInfo(self->agent()->ssl_fd(), &preinfo,
sizeof(preinfo)));
EXPECT_EQ(sizeof(preinfo), preinfo.length);
// Check the version.
if (preinfo.valuesSet & ssl_preinfo_version) {
EXPECT_EQ(SSL_LIBRARY_VERSION_TLS_1_3, preinfo.protocolVersion);
} else {
EXPECT_EQ(1U, epoch);
}
uint16_t suite;
if (epoch == 1) {
// 0-RTT
EXPECT_TRUE(preinfo.valuesSet & ssl_preinfo_0rtt_cipher_suite);
suite = preinfo.zeroRttCipherSuite;
} else {
EXPECT_TRUE(preinfo.valuesSet & ssl_preinfo_cipher_suite);
suite = preinfo.cipherSuite;
}
SSLCipherSuiteInfo cipherinfo;
EXPECT_EQ(SECSuccess,
SSL_GetCipherSuiteInfo(suite, &cipherinfo, sizeof(cipherinfo)));
EXPECT_EQ(sizeof(cipherinfo), cipherinfo.length);
bool is_dtls = self->agent()->variant() == ssl_variant_datagram;
self->cipher_specs_.emplace_back(is_dtls, epoch);
EXPECT_TRUE(self->cipher_specs_.back().SetKeys(&cipherinfo, secret));
}
bool TlsRecordFilter::is_dtls13() const {
@@ -95,6 +120,23 @@ bool TlsRecordFilter::is_dtls13() const {
info.canSendEarlyData;
}
// Gets the cipher spec that matches the specified epoch.
TlsCipherSpec& TlsRecordFilter::spec(uint16_t write_epoch) {
for (auto& sp : cipher_specs_) {
if (sp.epoch() == write_epoch) {
return sp;
}
}
// If we aren't decrypting, provide a cipher spec that does nothing other than
// count sequence numbers.
EXPECT_FALSE(decrypting_) << "No spec available for epoch " << write_epoch;
;
bool is_dtls = agent()->variant() == ssl_variant_datagram;
cipher_specs_.emplace_back(is_dtls, write_epoch);
return cipher_specs_.back();
}
PacketFilter::Action TlsRecordFilter::Filter(const DataBuffer& input,
DataBuffer* output) {
// Disable during shutdown.
@@ -108,34 +150,28 @@ PacketFilter::Action TlsRecordFilter::Filter(const DataBuffer& input,
output->Allocate(input.len());
TlsParser parser(input);
// This uses the current write spec for the purposes of parsing the epoch and
// sequence number from the header. This might be wrong because we can
// receive records from older specs, but guessing is good enough:
// - In DTLS, parsing the sequence number corrects any errors.
// - In TLS, we don't use the sequence number unless decrypting, where we use
// trial decryption to get the right epoch.
uint16_t write_epoch = 0;
SECStatus rv = SSL_GetCurrentEpoch(agent()->ssl_fd(), nullptr, &write_epoch);
if (rv != SECSuccess) {
ADD_FAILURE() << "unable to read epoch";
return KEEP;
}
uint64_t guess_seqno = static_cast<uint64_t>(write_epoch) << 48;
while (parser.remaining()) {
TlsRecordHeader header;
DataBuffer record;
if (!header.Parse(is_dtls13(), in_sequence_number_, &parser, &record)) {
if (!header.Parse(is_dtls13(), guess_seqno, &parser, &record)) {
ADD_FAILURE() << "not a valid record";
return KEEP;
}
// Track the sequence number, which is necessary for stream mode when
// decrypting and for TLS 1.3 datagram to recover the sequence number.
//
// We reset the counter when the cipher spec changes, but that notification
// appears before a record is sent. If multiple records are sent with
// different cipher specs, this would fail. This filters out cleartext
// records, so we don't get confused by handshake messages that are sent at
// the same time as encrypted records. Sequence numbers are therefore
// likely to be incorrect for cleartext records.
//
// This isn't perfectly robust: if there is a change from an active cipher
// spec to another active cipher spec (KeyUpdate for instance) AND writes
// are consolidated across that change, this code could use the wrong
// sequence numbers when re-encrypting records with the old keys.
if (header.content_type() == ssl_ct_application_data) {
in_sequence_number_ =
(std::max)(in_sequence_number_, header.sequence_number() + 1);
}
if (FilterRecord(header, record, &offset, output) != KEEP) {
changed = true;
} else {
@@ -159,14 +195,16 @@ PacketFilter::Action TlsRecordFilter::FilterRecord(
DataBuffer filtered;
uint8_t inner_content_type;
DataBuffer plaintext;
uint16_t protection_epoch = 0;
if (!Unprotect(header, record, &inner_content_type, &plaintext)) {
if (g_ssl_gtest_verbose) {
std::cerr << "unprotect failed: " << header << ":" << record << std::endl;
}
if (!Unprotect(header, record, &protection_epoch, &inner_content_type,
&plaintext)) {
std::cerr << agent()->role_str() << ": unprotect failed: " << header << ":"
<< record << std::endl;
return KEEP;
}
auto& protection_spec = spec(protection_epoch);
TlsRecordHeader real_header(header.variant(), header.version(),
inner_content_type, header.sequence_number());
@@ -174,7 +212,9 @@ PacketFilter::Action TlsRecordFilter::FilterRecord(
// In stream mode, even if something doesn't change we need to re-encrypt if
// previous packets were dropped.
if (action == KEEP) {
if (header.is_dtls() || !dropped_record_) {
if (header.is_dtls() || !protection_spec.record_dropped()) {
// Count every outgoing packet.
protection_spec.RecordProtected();
return KEEP;
}
filtered = plaintext;
@@ -182,7 +222,7 @@ PacketFilter::Action TlsRecordFilter::FilterRecord(
if (action == DROP) {
std::cerr << "record drop: " << header << ":" << record << std::endl;
dropped_record_ = true;
protection_spec.RecordDropped();
return DROP;
}
@@ -192,19 +232,18 @@ PacketFilter::Action TlsRecordFilter::FilterRecord(
std::cerr << "record new: " << filtered << std::endl;
}
uint64_t seq_num;
if (header.is_dtls() || !cipher_spec_ ||
header.content_type() != ssl_ct_application_data) {
seq_num = header.sequence_number();
} else {
seq_num = out_sequence_number_++;
uint64_t seq_num = protection_spec.next_out_seqno();
if (!decrypting_ && header.is_dtls()) {
// Copy over the epoch, which isn't tracked when not decrypting.
seq_num |= header.sequence_number() & (0xffffULL << 48);
}
TlsRecordHeader out_header(header.variant(), header.version(),
header.content_type(), seq_num);
DataBuffer ciphertext;
bool rv = Protect(out_header, inner_content_type, filtered, &ciphertext);
EXPECT_TRUE(rv);
bool rv = Protect(protection_spec, out_header, inner_content_type, filtered,
&ciphertext);
if (!rv) {
return KEEP;
}
@@ -227,15 +266,20 @@ uint64_t TlsRecordHeader::RecoverSequenceNumber(uint64_t expected,
uint32_t partial,
size_t partial_bits) {
EXPECT_GE(32U, partial_bits);
uint64_t mask = (1 << partial_bits) - 1;
uint64_t mask = (1ULL << partial_bits) - 1;
// First we determine the highest possible value. This is half the
// expressible range above the expected value.
uint64_t cap = expected + (1ULL << (partial_bits - 1));
// expressible range above the expected value, less 1.
//
// We subtract the extra 1 from the cap so that when given a choice between
// the equidistant expected+N and expected-N we want to chose the lower. With
// 0-RTT, we sometimes have to recover an epoch of 1 when we expect an epoch
// of 3 and with 2 partial bits, the alternative result of 5 is wrong.
uint64_t cap = expected + (1ULL << (partial_bits - 1)) - 1;
// Add the partial piece in. e.g., xxxx789a and 1234 becomes xxxx1234.
uint64_t seq_no = (cap & ~mask) | partial;
// If the partial value is higher than the same partial piece from the cap,
// then the real value has to be lower. e.g., xxxx1234 can't become xxxx5678.
if (partial > (cap & mask)) {
if (partial > (cap & mask) && (seq_no >= (1ULL << partial_bits))) {
seq_no -= 1ULL << partial_bits;
}
return seq_no;
@@ -375,16 +419,41 @@ size_t TlsRecordHeader::Write(DataBuffer* buffer, size_t offset,
bool TlsRecordFilter::Unprotect(const TlsRecordHeader& header,
const DataBuffer& ciphertext,
uint16_t* protection_epoch,
uint8_t* inner_content_type,
DataBuffer* plaintext) {
if (!cipher_spec_ || header.content_type() != ssl_ct_application_data) {
if (!decrypting_ || header.content_type() != ssl_ct_application_data) {
// Maintain the epoch and sequence number for plaintext records.
uint16_t ep = 0;
if (agent()->variant() == ssl_variant_datagram) {
ep = static_cast<uint16_t>(header.sequence_number() >> 48);
}
spec(ep).RecordUnprotected(header.sequence_number());
*protection_epoch = ep;
*inner_content_type = header.content_type();
*plaintext = ciphertext;
return true;
}
if (!cipher_spec_->Unprotect(header, ciphertext, plaintext)) {
return false;
uint16_t ep = 0;
if (agent()->variant() == ssl_variant_datagram) {
ep = static_cast<uint16_t>(header.sequence_number() >> 48);
if (!spec(ep).Unprotect(header, ciphertext, plaintext)) {
return false;
}
} else {
// In TLS, records aren't clearly labelled with their epoch, and we
// can't just use the newest keys because the same flight of messages can
// contain multiple epochs. So... trial decrypt!
for (size_t i = cipher_specs_.size() - 1; i > 0; --i) {
if (cipher_specs_[i].Unprotect(header, ciphertext, plaintext)) {
ep = cipher_specs_[i].epoch();
break;
}
}
if (!ep) {
return false;
}
}
size_t len = plaintext->len();
@@ -396,33 +465,45 @@ bool TlsRecordFilter::Unprotect(const TlsRecordHeader& header,
return false;
}
*protection_epoch = ep;
*inner_content_type = plaintext->data()[len - 1];
plaintext->Truncate(len - 1);
if (g_ssl_gtest_verbose) {
std::cerr << "unprotect: " << std::hex << header.sequence_number()
<< std::dec << " type=" << static_cast<int>(*inner_content_type)
std::cerr << agent()->role_str() << ": unprotect: epoch=" << ep
<< " seq=" << std::hex << header.sequence_number() << std::dec
<< " " << *plaintext << std::endl;
}
return true;
}
bool TlsRecordFilter::Protect(const TlsRecordHeader& header,
bool TlsRecordFilter::Protect(TlsCipherSpec& protection_spec,
const TlsRecordHeader& header,
uint8_t inner_content_type,
const DataBuffer& plaintext,
DataBuffer* ciphertext, size_t padding) {
if (!cipher_spec_ || header.content_type() != ssl_ct_application_data) {
if (!protection_spec.is_protected()) {
// Not protected, just keep the sequence numbers updated.
protection_spec.RecordProtected();
*ciphertext = plaintext;
return true;
}
if (g_ssl_gtest_verbose) {
std::cerr << "protect: " << header.sequence_number() << std::endl;
}
DataBuffer padded;
padded.Allocate(plaintext.len() + 1 + padding);
size_t offset = padded.Write(0, plaintext.data(), plaintext.len());
padded.Write(offset, inner_content_type, 1);
return cipher_spec_->Protect(header, padded, ciphertext);
bool ok = protection_spec.Protect(header, padded, ciphertext);
if (!ok) {
ADD_FAILURE() << "protect fail";
} else if (g_ssl_gtest_verbose) {
std::cerr << agent()->role_str()
<< ": protect: epoch=" << protection_spec.epoch()
<< " seq=" << std::hex << header.sequence_number() << std::dec
<< " " << *ciphertext << std::endl;
}
return ok;
}
bool IsHelloRetry(const DataBuffer& body) {
+13 -21
View File
@@ -97,13 +97,7 @@ inline std::shared_ptr<T> MakeTlsFilter(const std::shared_ptr<TlsAgent>& agent,
// Abstract filter that operates on entire (D)TLS records.
class TlsRecordFilter : public PacketFilter {
public:
TlsRecordFilter(const std::shared_ptr<TlsAgent>& a)
: agent_(a),
count_(0),
cipher_spec_(),
dropped_record_(false),
in_sequence_number_(0),
out_sequence_number_(0) {}
TlsRecordFilter(const std::shared_ptr<TlsAgent>& a);
std::shared_ptr<TlsAgent> agent() const { return agent_.lock(); }
@@ -118,10 +112,11 @@ class TlsRecordFilter : public PacketFilter {
// behavior.
void EnableDecryption();
bool Unprotect(const TlsRecordHeader& header, const DataBuffer& cipherText,
uint8_t* inner_content_type, DataBuffer* plaintext);
bool Protect(const TlsRecordHeader& header, uint8_t inner_content_type,
const DataBuffer& plaintext, DataBuffer* ciphertext,
size_t padding = 0);
uint16_t* protection_epoch, uint8_t* inner_content_type,
DataBuffer* plaintext);
bool Protect(TlsCipherSpec& protection_spec, const TlsRecordHeader& header,
uint8_t inner_content_type, const DataBuffer& plaintext,
DataBuffer* ciphertext, size_t padding = 0);
protected:
// There are two filter functions which can be overriden. Both are
@@ -146,20 +141,17 @@ class TlsRecordFilter : public PacketFilter {
}
bool is_dtls13() const;
TlsCipherSpec& spec(uint16_t epoch);
private:
static void CipherSpecChanged(void* arg, PRBool sending,
ssl3CipherSpec* newSpec);
static void SecretCallback(PRFileDesc* fd, PRUint16 epoch,
SSLSecretDirection dir, PK11SymKey* secret,
void* arg);
std::weak_ptr<TlsAgent> agent_;
size_t count_;
std::unique_ptr<TlsCipherSpec> cipher_spec_;
// Whether we dropped a record since the cipher spec changed.
bool dropped_record_;
// The sequence number we use for reading records as they are written.
uint64_t in_sequence_number_;
// The sequence number we use for writing modified records.
uint64_t out_sequence_number_;
size_t count_ = 0;
std::vector<TlsCipherSpec> cipher_specs_;
bool decrypting_ = false;
};
inline std::ostream& operator<<(std::ostream& stream, const TlsVersioned& v) {
@@ -7,6 +7,9 @@
#include <memory>
#include "nss.h"
#include "pk11pub.h"
#include "secerr.h"
#include "sslproto.h"
#include "sslexp.h"
#include "tls13hkdf.h"
#include "databuffer.h"
@@ -56,6 +59,39 @@ const size_t kHashLength[] = {
64, /* ssl_hash_sha512 */
};
size_t GetHashLength(SSLHashType hash) {
size_t i = static_cast<size_t>(hash);
if (i < PR_ARRAY_SIZE(kHashLength)) {
return kHashLength[i];
}
ADD_FAILURE() << "Unknown hash: " << hash;
return 0;
}
CK_MECHANISM_TYPE GetHkdfMech(SSLHashType hash) {
switch (hash) {
case ssl_hash_sha256:
return CKM_NSS_HKDF_SHA256;
case ssl_hash_sha384:
return CKM_NSS_HKDF_SHA384;
default:
ADD_FAILURE() << "Unknown hash: " << hash;
}
return CKM_INVALID_MECHANISM;
}
PRUint16 GetSomeCipherSuiteForHash(SSLHashType hash) {
switch (hash) {
case ssl_hash_sha256:
return TLS_AES_128_GCM_SHA256;
case ssl_hash_sha384:
return TLS_AES_256_GCM_SHA384;
default:
ADD_FAILURE() << "Unknown hash: " << hash;
}
return 0;
}
const std::string kHashName[] = {"None", "MD5", "SHA-1", "SHA-224",
"SHA-256", "SHA-384", "SHA-512"};
@@ -64,7 +100,7 @@ static void ImportKey(ScopedPK11SymKey* to, const DataBuffer& key,
ASSERT_LT(hash_type, sizeof(kHashLength));
ASSERT_LE(kHashLength[hash_type], key.len());
SECItem key_item = {siBuffer, const_cast<uint8_t*>(key.data()),
static_cast<unsigned int>(kHashLength[hash_type])};
static_cast<unsigned int>(GetHashLength(hash_type))};
PK11SymKey* inner =
PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, PK11_OriginUnwrap,
@@ -112,15 +148,19 @@ class TlsHkdfTest : public ::testing::Test,
ImportKey(&k2_, kKey2, hash_type_, slot_.get());
}
void VerifyKey(const ScopedPK11SymKey& key, const DataBuffer& expected) {
void VerifyKey(const ScopedPK11SymKey& key, CK_MECHANISM_TYPE expected_mech,
const DataBuffer& expected_value) {
EXPECT_EQ(expected_mech, PK11_GetMechanism(key.get()));
SECStatus rv = PK11_ExtractKeyValue(key.get());
ASSERT_EQ(SECSuccess, rv);
SECItem* key_data = PK11_GetKeyData(key.get());
ASSERT_NE(nullptr, key_data);
EXPECT_EQ(expected.len(), key_data->len);
EXPECT_EQ(0, memcmp(expected.data(), key_data->data, expected.len()));
EXPECT_EQ(expected_value.len(), key_data->len);
EXPECT_EQ(
0, memcmp(expected_value.data(), key_data->data, expected_value.len()));
}
void HkdfExtract(const ScopedPK11SymKey& ikmk1, const ScopedPK11SymKey& ikmk2,
@@ -133,7 +173,15 @@ class TlsHkdfTest : public ::testing::Test,
ScopedPK11SymKey prkk(prk);
DumpKey("Output", prkk);
VerifyKey(prkk, expected);
VerifyKey(prkk, GetHkdfMech(base_hash), expected);
// Now test the public wrapper.
PRUint16 cs = GetSomeCipherSuiteForHash(base_hash);
rv = SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3, cs, ikmk1.get(),
ikmk2.get(), &prk);
ASSERT_EQ(SECSuccess, rv);
ASSERT_NE(nullptr, prk);
VerifyKey(ScopedPK11SymKey(prk), GetHkdfMech(base_hash), expected);
}
void HkdfExpandLabel(ScopedPK11SymKey* prk, SSLHashType base_hash,
@@ -150,6 +198,32 @@ class TlsHkdfTest : public ::testing::Test,
ASSERT_EQ(SECSuccess, rv);
DumpData("Output", &output[0], output.size());
EXPECT_EQ(0, memcmp(expected.data(), &output[0], expected.len()));
// Verify that the public API produces the same result.
PRUint16 cs = GetSomeCipherSuiteForHash(base_hash);
PK11SymKey* secret;
rv = SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3, cs, prk->get(),
session_hash, session_hash_len, label, label_len,
&secret);
EXPECT_EQ(SECSuccess, rv);
ASSERT_NE(nullptr, prk);
VerifyKey(ScopedPK11SymKey(secret), GetHkdfMech(base_hash), expected);
// Verify that a key can be created with a different key type and size.
rv = SSL_HkdfExpandLabelWithMech(
SSL_LIBRARY_VERSION_TLS_1_3, cs, prk->get(), session_hash,
session_hash_len, label, label_len, CKM_DES3_CBC_PAD, 24, &secret);
EXPECT_EQ(SECSuccess, rv);
ASSERT_NE(nullptr, prk);
ScopedPK11SymKey with_mech(secret);
EXPECT_EQ(static_cast<CK_MECHANISM_TYPE>(CKM_DES3_CBC_PAD),
PK11_GetMechanism(with_mech.get()));
// Just verify that the key is the right size.
rv = PK11_ExtractKeyValue(with_mech.get());
ASSERT_EQ(SECSuccess, rv);
SECItem* key_data = PK11_GetKeyData(with_mech.get());
ASSERT_NE(nullptr, key_data);
EXPECT_EQ(24U, key_data->len);
}
protected:
@@ -175,7 +249,7 @@ TEST_P(TlsHkdfTest, HkdfNullNull) {
0x10, 0xba, 0x18, 0xe2, 0x35, 0x7e, 0x71, 0x69, 0x71, 0xf9, 0x36, 0x2f,
0x2c, 0x2f, 0xe2, 0xa7, 0x6b, 0xfd, 0x78, 0xdf, 0xec, 0x4e, 0xa9, 0xb5}};
const DataBuffer expected_data(tv[hash_type_], kHashLength[hash_type_]);
const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
HkdfExtract(nullptr, nullptr, hash_type_, expected_data);
}
@@ -193,7 +267,7 @@ TEST_P(TlsHkdfTest, HkdfKey1Only) {
0x57, 0xc2, 0x76, 0x9f, 0x3f, 0x83, 0x45, 0x2f, 0xf6, 0xf3, 0x56, 0x1f,
0x58, 0x63, 0xdb, 0x88, 0xda, 0x40, 0xce, 0x63, 0x7d, 0x24, 0x37, 0xf3}};
const DataBuffer expected_data(tv[hash_type_], kHashLength[hash_type_]);
const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
HkdfExtract(k1_, nullptr, hash_type_, expected_data);
}
@@ -211,7 +285,7 @@ TEST_P(TlsHkdfTest, HkdfKey2Only) {
0xd4, 0x6a, 0xf6, 0xe5, 0xec, 0xea, 0xf8, 0x7d, 0x91, 0x71, 0x81, 0xf1,
0xdb, 0x3b, 0xaf, 0xbf, 0xde, 0x71, 0x61, 0x15, 0xeb, 0xb5, 0x5f, 0x68}};
const DataBuffer expected_data(tv[hash_type_], kHashLength[hash_type_]);
const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
HkdfExtract(nullptr, k2_, hash_type_, expected_data);
}
@@ -229,7 +303,7 @@ TEST_P(TlsHkdfTest, HkdfKey1Key2) {
0x1c, 0x5b, 0x98, 0x0b, 0x02, 0x92, 0x3f, 0xfd, 0x73, 0x5a, 0x6f, 0x2a,
0x95, 0xa3, 0xee, 0xf6, 0xd6, 0x8e, 0x6f, 0x86, 0xea, 0x63, 0xf8, 0x33}};
const DataBuffer expected_data(tv[hash_type_], kHashLength[hash_type_]);
const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
HkdfExtract(k1_, k2_, hash_type_, expected_data);
}
@@ -247,12 +321,122 @@ TEST_P(TlsHkdfTest, HkdfExpandLabel) {
0x74, 0xf7, 0x8b, 0x06, 0x38, 0x28, 0x06, 0x37, 0x75, 0x23, 0xa2, 0xb7,
0x34, 0xb1, 0x72, 0x2e, 0x59, 0x6d, 0x5a, 0x31, 0xf5, 0x53, 0xab, 0x99}};
const DataBuffer expected_data(tv[hash_type_], kHashLength[hash_type_]);
HkdfExpandLabel(&k1_, hash_type_, kSessionHash, kHashLength[hash_type_],
const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
HkdfExpandLabel(&k1_, hash_type_, kSessionHash, GetHashLength(hash_type_),
kLabelMasterSecret, strlen(kLabelMasterSecret),
expected_data);
}
TEST_P(TlsHkdfTest, HkdfExpandLabelNoHash) {
const uint8_t tv[][48] = {
{/* ssl_hash_none */},
{/* ssl_hash_md5 */},
{/* ssl_hash_sha1 */},
{/* ssl_hash_sha224 */},
{0xb7, 0x08, 0x00, 0xe3, 0x8e, 0x48, 0x68, 0x91, 0xb1, 0x0f, 0x5e,
0x6f, 0x22, 0x53, 0x6b, 0x84, 0x69, 0x75, 0xaa, 0xa3, 0x2a, 0xe7,
0xde, 0xaa, 0xc3, 0xd1, 0xb4, 0x05, 0x22, 0x5c, 0x68, 0xf5},
{0x13, 0xd3, 0x36, 0x9f, 0x3c, 0x78, 0xa0, 0x32, 0x40, 0xee, 0x16, 0xe9,
0x11, 0x12, 0x66, 0xc7, 0x51, 0xad, 0xd8, 0x3c, 0xa1, 0xa3, 0x97, 0x74,
0xd7, 0x45, 0xff, 0xa7, 0x88, 0x9e, 0x52, 0x17, 0x2e, 0xaa, 0x3a, 0xd2,
0x35, 0xd8, 0xd5, 0x35, 0xfd, 0x65, 0x70, 0x9f, 0xa9, 0xf9, 0xfa, 0x23}};
const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
HkdfExpandLabel(&k1_, hash_type_, nullptr, 0, kLabelMasterSecret,
strlen(kLabelMasterSecret), expected_data);
}
TEST_P(TlsHkdfTest, BadExtractWrapperInput) {
PK11SymKey* key = nullptr;
// Bad version.
EXPECT_EQ(SECFailure,
SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256,
k1_.get(), k2_.get(), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Bad ciphersuite.
EXPECT_EQ(SECFailure,
SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3, TLS_RSA_WITH_NULL_SHA,
k1_.get(), k2_.get(), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Old ciphersuite.
EXPECT_EQ(SECFailure, SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_RSA_WITH_AES_128_CBC_SHA, k1_.get(),
k2_.get(), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// NULL outparam..
EXPECT_EQ(SECFailure, SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_RSA_WITH_AES_128_CBC_SHA, k1_.get(),
k2_.get(), nullptr));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
EXPECT_EQ(nullptr, key);
}
TEST_P(TlsHkdfTest, BadExpandLabelWrapperInput) {
PK11SymKey* key = nullptr;
static const char* kLabel = "label";
// Bad version.
EXPECT_EQ(
SECFailure,
SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256,
k1_.get(), nullptr, 0, kLabel, strlen(kLabel), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Bad ciphersuite.
EXPECT_EQ(
SECFailure,
SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3, TLS_RSA_WITH_NULL_MD5,
k1_.get(), nullptr, 0, kLabel, strlen(kLabel), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Old ciphersuite.
EXPECT_EQ(SECFailure,
SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_RSA_WITH_AES_128_CBC_SHA, k1_.get(),
nullptr, 0, kLabel, strlen(kLabel), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Null PRK.
EXPECT_EQ(SECFailure, SSL_HkdfExpandLabel(
SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256,
nullptr, nullptr, 0, kLabel, strlen(kLabel), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Null, non-zero-length handshake hash.
EXPECT_EQ(
SECFailure,
SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256,
k1_.get(), nullptr, 2, kLabel, strlen(kLabel), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Null, non-zero-length label.
EXPECT_EQ(SECFailure,
SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_AES_128_GCM_SHA256, k1_.get(), nullptr, 0,
nullptr, strlen(kLabel), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Null, empty label.
EXPECT_EQ(SECFailure, SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_AES_128_GCM_SHA256, k1_.get(),
nullptr, 0, nullptr, 0, &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Null key pointer..
EXPECT_EQ(SECFailure,
SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_AES_128_GCM_SHA256, k1_.get(), nullptr, 0,
kLabel, strlen(kLabel), nullptr));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
EXPECT_EQ(nullptr, key);
}
static const SSLHashType kHashTypes[] = {ssl_hash_sha256, ssl_hash_sha384};
INSTANTIATE_TEST_CASE_P(AllHashFuncs, TlsHkdfTest,
::testing::ValuesIn(kHashTypes));
+65 -112
View File
@@ -5,145 +5,98 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "tls_protect.h"
#include "sslproto.h"
#include "tls_filter.h"
namespace nss_test {
AeadCipher::~AeadCipher() {
if (key_) {
PK11_FreeSymKey(key_);
static uint64_t FirstSeqno(bool dtls, uint16_t epoc) {
if (dtls) {
return static_cast<uint64_t>(epoc) << 48;
}
return 0;
}
bool AeadCipher::Init(PK11SymKey *key, const uint8_t *iv) {
key_ = PK11_ReferenceSymKey(key);
if (!key_) return false;
TlsCipherSpec::TlsCipherSpec(bool dtls, uint16_t epoc)
: dtls_(dtls),
epoch_(epoc),
in_seqno_(FirstSeqno(dtls, epoc)),
out_seqno_(FirstSeqno(dtls, epoc)) {}
memcpy(iv_, iv, sizeof(iv_));
bool TlsCipherSpec::SetKeys(SSLCipherSuiteInfo* cipherinfo,
PK11SymKey* secret) {
SSLAeadContext* ctx;
SECStatus rv = SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3,
cipherinfo->cipherSuite, secret, "",
0, // Use the default labels.
&ctx);
if (rv != SECSuccess) {
return false;
}
aead_.reset(ctx);
return true;
}
void AeadCipher::FormatNonce(uint64_t seq, uint8_t *nonce) {
memcpy(nonce, iv_, 12);
for (size_t i = 0; i < 8; ++i) {
nonce[12 - (i + 1)] ^= seq & 0xff;
seq >>= 8;
bool TlsCipherSpec::Unprotect(const TlsRecordHeader& header,
const DataBuffer& ciphertext,
DataBuffer* plaintext) {
if (aead_ == nullptr) {
return false;
}
DataBuffer d(nonce, 12);
}
bool AeadCipher::AeadInner(bool decrypt, void *params, size_t param_length,
const uint8_t *in, size_t inlen, uint8_t *out,
size_t *outlen, size_t maxlen) {
SECStatus rv;
unsigned int uoutlen = 0;
SECItem param = {
siBuffer, static_cast<unsigned char *>(params),
static_cast<unsigned int>(param_length),
};
if (decrypt) {
rv = PK11_Decrypt(key_, mech_, &param, out, &uoutlen, maxlen, in, inlen);
} else {
rv = PK11_Encrypt(key_, mech_, &param, out, &uoutlen, maxlen, in, inlen);
}
*outlen = (int)uoutlen;
return rv == SECSuccess;
}
bool AeadCipherAesGcm::Aead(bool decrypt, const uint8_t *hdr, size_t hdr_len,
uint64_t seq, const uint8_t *in, size_t inlen,
uint8_t *out, size_t *outlen, size_t maxlen) {
CK_GCM_PARAMS aeadParams;
unsigned char nonce[12];
memset(&aeadParams, 0, sizeof(aeadParams));
aeadParams.pIv = nonce;
aeadParams.ulIvLen = sizeof(nonce);
aeadParams.pAAD = const_cast<uint8_t *>(hdr);
aeadParams.ulAADLen = hdr_len;
aeadParams.ulTagBits = 128;
FormatNonce(seq, nonce);
return AeadInner(decrypt, (unsigned char *)&aeadParams, sizeof(aeadParams),
in, inlen, out, outlen, maxlen);
}
bool AeadCipherChacha20Poly1305::Aead(bool decrypt, const uint8_t *hdr,
size_t hdr_len, uint64_t seq,
const uint8_t *in, size_t inlen,
uint8_t *out, size_t *outlen,
size_t maxlen) {
CK_NSS_AEAD_PARAMS aeadParams;
unsigned char nonce[12];
memset(&aeadParams, 0, sizeof(aeadParams));
aeadParams.pNonce = nonce;
aeadParams.ulNonceLen = sizeof(nonce);
aeadParams.pAAD = const_cast<uint8_t *>(hdr);
aeadParams.ulAADLen = hdr_len;
aeadParams.ulTagLen = 16;
FormatNonce(seq, nonce);
return AeadInner(decrypt, (unsigned char *)&aeadParams, sizeof(aeadParams),
in, inlen, out, outlen, maxlen);
}
bool TlsCipherSpec::Init(uint16_t epoc, SSLCipherAlgorithm cipher,
PK11SymKey *key, const uint8_t *iv) {
epoch_ = epoc;
switch (cipher) {
case ssl_calg_aes_gcm:
aead_.reset(new AeadCipherAesGcm());
break;
case ssl_calg_chacha20:
aead_.reset(new AeadCipherChacha20Poly1305());
break;
default:
return false;
}
return aead_->Init(key, iv);
}
bool TlsCipherSpec::Unprotect(const TlsRecordHeader &header,
const DataBuffer &ciphertext,
DataBuffer *plaintext) {
// Make space.
plaintext->Allocate(ciphertext.len());
auto header_bytes = header.header();
size_t len;
bool ret =
aead_->Aead(true, header_bytes.data(), header_bytes.len(),
header.sequence_number(), ciphertext.data(), ciphertext.len(),
plaintext->data(), &len, plaintext->len());
if (!ret) return false;
unsigned int len;
uint64_t seqno;
if (dtls_) {
seqno = header.sequence_number();
} else {
seqno = in_seqno_;
}
SECStatus rv =
SSL_AeadDecrypt(aead_.get(), seqno, header_bytes.data(),
header_bytes.len(), ciphertext.data(), ciphertext.len(),
plaintext->data(), &len, plaintext->len());
if (rv != SECSuccess) {
return false;
}
plaintext->Truncate(len);
RecordUnprotected(seqno);
plaintext->Truncate(static_cast<size_t>(len));
return true;
}
bool TlsCipherSpec::Protect(const TlsRecordHeader &header,
const DataBuffer &plaintext,
DataBuffer *ciphertext) {
bool TlsCipherSpec::Protect(const TlsRecordHeader& header,
const DataBuffer& plaintext,
DataBuffer* ciphertext) {
if (aead_ == nullptr) {
return false;
}
// Make a padded buffer.
ciphertext->Allocate(plaintext.len() +
32); // Room for any plausible auth tag
size_t len;
unsigned int len;
DataBuffer header_bytes;
(void)header.WriteHeader(&header_bytes, 0, plaintext.len() + 16);
bool ret =
aead_->Aead(false, header_bytes.data(), header_bytes.len(),
header.sequence_number(), plaintext.data(), plaintext.len(),
ciphertext->data(), &len, ciphertext->len());
if (!ret) return false;
uint64_t seqno;
if (dtls_) {
seqno = header.sequence_number();
} else {
seqno = out_seqno_;
}
SECStatus rv =
SSL_AeadEncrypt(aead_.get(), seqno, header_bytes.data(),
header_bytes.len(), plaintext.data(), plaintext.len(),
ciphertext->data(), &len, ciphertext->len());
if (rv != SECSuccess) {
return false;
}
RecordProtected();
ciphertext->Truncate(len);
return true;
+27 -50
View File
@@ -10,71 +10,48 @@
#include <cstdint>
#include <memory>
#include "databuffer.h"
#include "pk11pub.h"
#include "sslt.h"
#include "sslexp.h"
#include "databuffer.h"
#include "scoped_ptrs_ssl.h"
namespace nss_test {
class TlsRecordHeader;
class AeadCipher {
public:
AeadCipher(CK_MECHANISM_TYPE mech) : mech_(mech), key_(nullptr) {}
virtual ~AeadCipher();
bool Init(PK11SymKey *key, const uint8_t *iv);
virtual bool Aead(bool decrypt, const uint8_t *hdr, size_t hdr_len,
uint64_t seq, const uint8_t *in, size_t inlen, uint8_t *out,
size_t *outlen, size_t maxlen) = 0;
protected:
void FormatNonce(uint64_t seq, uint8_t *nonce);
bool AeadInner(bool decrypt, void *params, size_t param_length,
const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen,
size_t maxlen);
CK_MECHANISM_TYPE mech_;
PK11SymKey *key_;
uint8_t iv_[12];
};
class AeadCipherChacha20Poly1305 : public AeadCipher {
public:
AeadCipherChacha20Poly1305() : AeadCipher(CKM_NSS_CHACHA20_POLY1305) {}
protected:
bool Aead(bool decrypt, const uint8_t *hdr, size_t hdr_len, uint64_t seq,
const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen,
size_t maxlen);
};
class AeadCipherAesGcm : public AeadCipher {
public:
AeadCipherAesGcm() : AeadCipher(CKM_AES_GCM) {}
protected:
bool Aead(bool decrypt, const uint8_t *hdr, size_t hdr_len, uint64_t seq,
const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen,
size_t maxlen);
};
// Our analog of ssl3CipherSpec
class TlsCipherSpec {
public:
TlsCipherSpec() : epoch_(0), aead_() {}
TlsCipherSpec(bool dtls, uint16_t epoc);
bool SetKeys(SSLCipherSuiteInfo* cipherinfo, PK11SymKey* secret);
bool Init(uint16_t epoch, SSLCipherAlgorithm cipher, PK11SymKey *key,
const uint8_t *iv);
bool Protect(const TlsRecordHeader& header, const DataBuffer& plaintext,
DataBuffer* ciphertext);
bool Unprotect(const TlsRecordHeader& header, const DataBuffer& ciphertext,
DataBuffer* plaintext);
bool Protect(const TlsRecordHeader &header, const DataBuffer &plaintext,
DataBuffer *ciphertext);
bool Unprotect(const TlsRecordHeader &header, const DataBuffer &ciphertext,
DataBuffer *plaintext);
uint16_t epoch() const { return epoch_; }
uint64_t next_in_seqno() const { return in_seqno_; }
void RecordUnprotected(uint64_t seqno) {
// Reordering happens, so don't let this go backwards.
in_seqno_ = (std::max)(in_seqno_, seqno + 1);
}
uint64_t next_out_seqno() { return out_seqno_; }
void RecordProtected() { out_seqno_++; }
void RecordDropped() { record_dropped_ = true; }
bool record_dropped() const { return record_dropped_; }
bool is_protected() const { return aead_ != nullptr; }
private:
bool dtls_;
uint16_t epoch_;
std::unique_ptr<AeadCipher> aead_;
uint64_t in_seqno_;
uint64_t out_seqno_;
bool record_dropped_ = false;
ScopedSSLAeadContext aead_;
};
} // namespace nss_test
+2 -1
View File
@@ -6,7 +6,7 @@ Usage: build.sh [-h] [-c|-cc] [-v] [-j <n>] [--gyp|-g] [--opt|-o]
[--emit-llvm] [--no-zdefs] [--test] [--ct-verif]
[--nspr|--with-nspr=<include>:<lib>|--system-nspr]
[--system-sqlite] [--enable-fips] [--enable-libpkix]
[--mozpkix-only]
[--mozpkix-only] [-D<gyp-option>]
This script builds NSS with gyp and ninja.
@@ -51,3 +51,4 @@ NSS build tool options:
--enable-libpkix make libpkix part of the build
--mozpkix-only build only static mozpkix and mozpkix-test libraries
support for this build option is limited
-D<gyp-option> pass an option directly to gyp
+6
View File
@@ -215,6 +215,12 @@ extern void CERT_DestroyCertificate(CERTCertificate *cert);
*/
extern CERTCertificate *CERT_DupCertificate(CERTCertificate *c);
/* Access the DER of the certificate. This only creates a reference to the DER
* in the outparam not a copy. To avoid the pointer becoming invalid, use
* CERT_DupCertificate() and keep a reference to the duplicate alive.
*/
extern SECStatus CERT_GetCertificateDer(const CERTCertificate *c, SECItem *der);
/*
** Create a new certificate request. This result must be wrapped with an
** CERTSignedData to create a signed certificate request.
+11
View File
@@ -1314,6 +1314,17 @@ CERT_DupCertificate(CERTCertificate *c)
return c;
}
SECStatus
CERT_GetCertificateDer(const CERTCertificate *c, SECItem *der)
{
if (!c || !der) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
*der = c->derCert;
return SECSuccess;
}
/*
* Allow use of default cert database, so that apps(such as mozilla) don't
* have to pass the handle all over the place.
+7 -1
View File
@@ -37,7 +37,7 @@ CERT_CertTimesValid(CERTCertificate *c)
return (valid == secCertTimeValid) ? SECSuccess : SECFailure;
}
SECStatus
static SECStatus
checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicKey *key)
{
SECStatus rv;
@@ -47,6 +47,12 @@ checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicKey *key)
PRInt32 minLen, len;
sigAlg = SECOID_GetAlgorithmTag(sigAlgorithm);
rv = NSS_GetAlgorithmPolicy(sigAlg, &policyFlags);
if (rv == SECSuccess &&
!(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
return SECFailure;
}
switch (sigAlg) {
case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
+675
View File
@@ -23153,3 +23153,678 @@ CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
#
# Certificate "emSign Root CA - G1"
#
# Issuer: CN=emSign Root CA - G1,O=eMudhra Technologies Limited,OU=emSign PKI,C=IN
# Serial Number:31:f5:e4:62:0c:6c:58:ed:d6:d8
# Subject: CN=emSign Root CA - G1,O=eMudhra Technologies Limited,OU=emSign PKI,C=IN
# Not Valid Before: Sun Feb 18 18:30:00 2018
# Not Valid After : Wed Feb 18 18:30:00 2043
# Fingerprint (SHA-256): 40:F6:AF:03:46:A9:9A:A1:CD:1D:55:5A:4E:9C:CE:62:C7:F9:63:46:03:EE:40:66:15:83:3D:C8:C8:D0:03:67
# Fingerprint (SHA1): 8A:C7:AD:8F:73:AC:4E:C1:B5:75:4D:A5:40:F4:FC:CF:7C:B5:8E:8C
CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "emSign Root CA - G1"
CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
CKA_SUBJECT MULTILINE_OCTAL
\060\147\061\013\060\011\006\003\125\004\006\023\002\111\116\061
\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156
\040\120\113\111\061\045\060\043\006\003\125\004\012\023\034\145
\115\165\144\150\162\141\040\124\145\143\150\156\157\154\157\147
\151\145\163\040\114\151\155\151\164\145\144\061\034\060\032\006
\003\125\004\003\023\023\145\155\123\151\147\156\040\122\157\157
\164\040\103\101\040\055\040\107\061
END
CKA_ID UTF8 "0"
CKA_ISSUER MULTILINE_OCTAL
\060\147\061\013\060\011\006\003\125\004\006\023\002\111\116\061
\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156
\040\120\113\111\061\045\060\043\006\003\125\004\012\023\034\145
\115\165\144\150\162\141\040\124\145\143\150\156\157\154\157\147
\151\145\163\040\114\151\155\151\164\145\144\061\034\060\032\006
\003\125\004\003\023\023\145\155\123\151\147\156\040\122\157\157
\164\040\103\101\040\055\040\107\061
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\012\061\365\344\142\014\154\130\355\326\330
END
CKA_VALUE MULTILINE_OCTAL
\060\202\003\224\060\202\002\174\240\003\002\001\002\002\012\061
\365\344\142\014\154\130\355\326\330\060\015\006\011\052\206\110
\206\367\015\001\001\013\005\000\060\147\061\013\060\011\006\003
\125\004\006\023\002\111\116\061\023\060\021\006\003\125\004\013
\023\012\145\155\123\151\147\156\040\120\113\111\061\045\060\043
\006\003\125\004\012\023\034\145\115\165\144\150\162\141\040\124
\145\143\150\156\157\154\157\147\151\145\163\040\114\151\155\151
\164\145\144\061\034\060\032\006\003\125\004\003\023\023\145\155
\123\151\147\156\040\122\157\157\164\040\103\101\040\055\040\107
\061\060\036\027\015\061\070\060\062\061\070\061\070\063\060\060
\060\132\027\015\064\063\060\062\061\070\061\070\063\060\060\060
\132\060\147\061\013\060\011\006\003\125\004\006\023\002\111\116
\061\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147
\156\040\120\113\111\061\045\060\043\006\003\125\004\012\023\034
\145\115\165\144\150\162\141\040\124\145\143\150\156\157\154\157
\147\151\145\163\040\114\151\155\151\164\145\144\061\034\060\032
\006\003\125\004\003\023\023\145\155\123\151\147\156\040\122\157
\157\164\040\103\101\040\055\040\107\061\060\202\001\042\060\015
\006\011\052\206\110\206\367\015\001\001\001\005\000\003\202\001
\017\000\060\202\001\012\002\202\001\001\000\223\113\273\351\146
\212\356\235\133\325\064\223\320\033\036\303\347\236\270\144\063
\177\143\170\150\264\315\056\161\165\327\233\040\306\115\051\274
\266\150\140\212\367\041\232\126\065\132\363\166\275\330\315\232
\377\223\126\113\245\131\006\241\223\064\051\335\026\064\165\116
\362\201\264\307\226\116\255\031\025\122\112\376\074\160\165\160
\315\257\053\253\025\232\063\074\252\263\213\252\315\103\375\365
\352\160\377\355\317\021\073\224\316\116\062\026\323\043\100\052
\167\263\257\074\001\054\154\355\231\054\213\331\116\151\230\262
\367\217\101\260\062\170\141\326\015\137\303\372\242\100\222\035
\134\027\346\160\076\065\347\242\267\302\142\342\253\244\070\114
\265\071\065\157\352\003\151\372\072\124\150\205\155\326\362\057
\103\125\036\221\015\016\330\325\152\244\226\321\023\074\054\170
\120\350\072\222\322\027\126\345\065\032\100\034\076\215\054\355
\071\337\102\340\203\101\164\337\243\315\302\206\140\110\150\343
\151\013\124\000\213\344\166\151\041\015\171\116\064\010\136\024
\302\314\261\267\255\327\174\160\212\307\205\002\003\001\000\001
\243\102\060\100\060\035\006\003\125\035\016\004\026\004\024\373
\357\015\206\236\260\343\335\251\271\361\041\027\177\076\374\360
\167\053\032\060\016\006\003\125\035\017\001\001\377\004\004\003
\002\001\006\060\017\006\003\125\035\023\001\001\377\004\005\060
\003\001\001\377\060\015\006\011\052\206\110\206\367\015\001\001
\013\005\000\003\202\001\001\000\131\377\362\214\365\207\175\161
\075\243\237\033\133\321\332\370\323\234\153\066\275\233\251\141
\353\336\026\054\164\075\236\346\165\332\327\272\247\274\102\027
\347\075\221\353\345\175\335\076\234\361\317\222\254\154\110\314
\302\042\077\151\073\305\266\025\057\243\065\306\150\052\034\127
\257\071\357\215\320\065\303\030\014\173\000\126\034\315\213\031
\164\336\276\017\022\340\320\252\241\077\002\064\261\160\316\235
\030\326\010\003\011\106\356\140\340\176\266\304\111\004\121\175
\160\140\274\252\262\377\171\162\172\246\035\075\137\052\370\312
\342\375\071\267\107\271\353\176\337\004\043\257\372\234\006\007
\351\373\143\223\200\100\265\306\154\012\061\050\316\014\237\317
\263\043\065\200\101\215\154\304\067\173\201\057\200\241\100\102
\205\351\331\070\215\350\241\123\315\001\277\151\350\132\006\362
\105\013\220\372\256\341\277\235\362\256\127\074\245\256\262\126
\364\213\145\100\351\375\061\201\054\364\071\011\330\356\153\247
\264\246\035\025\245\230\367\001\201\330\205\175\363\121\134\161
\210\336\272\314\037\200\176\112
END
CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE
# Trust for "emSign Root CA - G1"
# Issuer: CN=emSign Root CA - G1,O=eMudhra Technologies Limited,OU=emSign PKI,C=IN
# Serial Number:31:f5:e4:62:0c:6c:58:ed:d6:d8
# Subject: CN=emSign Root CA - G1,O=eMudhra Technologies Limited,OU=emSign PKI,C=IN
# Not Valid Before: Sun Feb 18 18:30:00 2018
# Not Valid After : Wed Feb 18 18:30:00 2043
# Fingerprint (SHA-256): 40:F6:AF:03:46:A9:9A:A1:CD:1D:55:5A:4E:9C:CE:62:C7:F9:63:46:03:EE:40:66:15:83:3D:C8:C8:D0:03:67
# Fingerprint (SHA1): 8A:C7:AD:8F:73:AC:4E:C1:B5:75:4D:A5:40:F4:FC:CF:7C:B5:8E:8C
CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "emSign Root CA - G1"
CKA_CERT_SHA1_HASH MULTILINE_OCTAL
\212\307\255\217\163\254\116\301\265\165\115\245\100\364\374\317
\174\265\216\214
END
CKA_CERT_MD5_HASH MULTILINE_OCTAL
\234\102\204\127\335\313\013\247\056\225\255\266\363\332\274\254
END
CKA_ISSUER MULTILINE_OCTAL
\060\147\061\013\060\011\006\003\125\004\006\023\002\111\116\061
\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156
\040\120\113\111\061\045\060\043\006\003\125\004\012\023\034\145
\115\165\144\150\162\141\040\124\145\143\150\156\157\154\157\147
\151\145\163\040\114\151\155\151\164\145\144\061\034\060\032\006
\003\125\004\003\023\023\145\155\123\151\147\156\040\122\157\157
\164\040\103\101\040\055\040\107\061
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\012\061\365\344\142\014\154\130\355\326\330
END
CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
#
# Certificate "emSign ECC Root CA - G3"
#
# Issuer: CN=emSign ECC Root CA - G3,O=eMudhra Technologies Limited,OU=emSign PKI,C=IN
# Serial Number:3c:f6:07:a9:68:70:0e:da:8b:84
# Subject: CN=emSign ECC Root CA - G3,O=eMudhra Technologies Limited,OU=emSign PKI,C=IN
# Not Valid Before: Sun Feb 18 18:30:00 2018
# Not Valid After : Wed Feb 18 18:30:00 2043
# Fingerprint (SHA-256): 86:A1:EC:BA:08:9C:4A:8D:3B:BE:27:34:C6:12:BA:34:1D:81:3E:04:3C:F9:E8:A8:62:CD:5C:57:A3:6B:BE:6B
# Fingerprint (SHA1): 30:43:FA:4F:F2:57:DC:A0:C3:80:EE:2E:58:EA:78:B2:3F:E6:BB:C1
CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "emSign ECC Root CA - G3"
CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
CKA_SUBJECT MULTILINE_OCTAL
\060\153\061\013\060\011\006\003\125\004\006\023\002\111\116\061
\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156
\040\120\113\111\061\045\060\043\006\003\125\004\012\023\034\145
\115\165\144\150\162\141\040\124\145\143\150\156\157\154\157\147
\151\145\163\040\114\151\155\151\164\145\144\061\040\060\036\006
\003\125\004\003\023\027\145\155\123\151\147\156\040\105\103\103
\040\122\157\157\164\040\103\101\040\055\040\107\063
END
CKA_ID UTF8 "0"
CKA_ISSUER MULTILINE_OCTAL
\060\153\061\013\060\011\006\003\125\004\006\023\002\111\116\061
\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156
\040\120\113\111\061\045\060\043\006\003\125\004\012\023\034\145
\115\165\144\150\162\141\040\124\145\143\150\156\157\154\157\147
\151\145\163\040\114\151\155\151\164\145\144\061\040\060\036\006
\003\125\004\003\023\027\145\155\123\151\147\156\040\105\103\103
\040\122\157\157\164\040\103\101\040\055\040\107\063
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\012\074\366\007\251\150\160\016\332\213\204
END
CKA_VALUE MULTILINE_OCTAL
\060\202\002\116\060\202\001\323\240\003\002\001\002\002\012\074
\366\007\251\150\160\016\332\213\204\060\012\006\010\052\206\110
\316\075\004\003\003\060\153\061\013\060\011\006\003\125\004\006
\023\002\111\116\061\023\060\021\006\003\125\004\013\023\012\145
\155\123\151\147\156\040\120\113\111\061\045\060\043\006\003\125
\004\012\023\034\145\115\165\144\150\162\141\040\124\145\143\150
\156\157\154\157\147\151\145\163\040\114\151\155\151\164\145\144
\061\040\060\036\006\003\125\004\003\023\027\145\155\123\151\147
\156\040\105\103\103\040\122\157\157\164\040\103\101\040\055\040
\107\063\060\036\027\015\061\070\060\062\061\070\061\070\063\060
\060\060\132\027\015\064\063\060\062\061\070\061\070\063\060\060
\060\132\060\153\061\013\060\011\006\003\125\004\006\023\002\111
\116\061\023\060\021\006\003\125\004\013\023\012\145\155\123\151
\147\156\040\120\113\111\061\045\060\043\006\003\125\004\012\023
\034\145\115\165\144\150\162\141\040\124\145\143\150\156\157\154
\157\147\151\145\163\040\114\151\155\151\164\145\144\061\040\060
\036\006\003\125\004\003\023\027\145\155\123\151\147\156\040\105
\103\103\040\122\157\157\164\040\103\101\040\055\040\107\063\060
\166\060\020\006\007\052\206\110\316\075\002\001\006\005\053\201
\004\000\042\003\142\000\004\043\245\014\270\055\022\365\050\363
\261\262\335\342\002\022\200\236\071\137\111\115\237\311\045\064
\131\164\354\273\006\034\347\300\162\257\350\256\057\341\101\124
\207\024\250\112\262\350\174\202\346\133\152\265\334\263\165\316
\213\006\320\206\043\277\106\325\216\017\077\004\364\327\034\222
\176\366\245\143\302\365\137\216\056\117\241\030\031\002\053\062
\012\202\144\175\026\223\321\243\102\060\100\060\035\006\003\125
\035\016\004\026\004\024\174\135\002\204\023\324\314\212\233\201
\316\027\034\056\051\036\234\110\143\102\060\016\006\003\125\035
\017\001\001\377\004\004\003\002\001\006\060\017\006\003\125\035
\023\001\001\377\004\005\060\003\001\001\377\060\012\006\010\052
\206\110\316\075\004\003\003\003\151\000\060\146\002\061\000\276
\363\141\317\002\020\035\144\225\007\270\030\156\210\205\005\057
\203\010\027\220\312\037\212\114\350\015\033\172\261\255\325\201
\011\107\357\073\254\010\004\174\134\231\261\355\107\007\322\002
\061\000\235\272\125\374\251\112\350\355\355\346\166\001\102\173
\310\370\140\331\215\121\213\125\073\373\214\173\353\145\011\303
\370\226\315\107\250\202\362\026\125\167\044\176\022\020\225\004
\054\243
END
CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE
# Trust for "emSign ECC Root CA - G3"
# Issuer: CN=emSign ECC Root CA - G3,O=eMudhra Technologies Limited,OU=emSign PKI,C=IN
# Serial Number:3c:f6:07:a9:68:70:0e:da:8b:84
# Subject: CN=emSign ECC Root CA - G3,O=eMudhra Technologies Limited,OU=emSign PKI,C=IN
# Not Valid Before: Sun Feb 18 18:30:00 2018
# Not Valid After : Wed Feb 18 18:30:00 2043
# Fingerprint (SHA-256): 86:A1:EC:BA:08:9C:4A:8D:3B:BE:27:34:C6:12:BA:34:1D:81:3E:04:3C:F9:E8:A8:62:CD:5C:57:A3:6B:BE:6B
# Fingerprint (SHA1): 30:43:FA:4F:F2:57:DC:A0:C3:80:EE:2E:58:EA:78:B2:3F:E6:BB:C1
CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "emSign ECC Root CA - G3"
CKA_CERT_SHA1_HASH MULTILINE_OCTAL
\060\103\372\117\362\127\334\240\303\200\356\056\130\352\170\262
\077\346\273\301
END
CKA_CERT_MD5_HASH MULTILINE_OCTAL
\316\013\162\321\237\210\216\320\120\003\350\343\270\213\147\100
END
CKA_ISSUER MULTILINE_OCTAL
\060\153\061\013\060\011\006\003\125\004\006\023\002\111\116\061
\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156
\040\120\113\111\061\045\060\043\006\003\125\004\012\023\034\145
\115\165\144\150\162\141\040\124\145\143\150\156\157\154\157\147
\151\145\163\040\114\151\155\151\164\145\144\061\040\060\036\006
\003\125\004\003\023\027\145\155\123\151\147\156\040\105\103\103
\040\122\157\157\164\040\103\101\040\055\040\107\063
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\012\074\366\007\251\150\160\016\332\213\204
END
CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
#
# Certificate "emSign Root CA - C1"
#
# Issuer: CN=emSign Root CA - C1,O=eMudhra Inc,OU=emSign PKI,C=US
# Serial Number:00:ae:cf:00:ba:c4:cf:32:f8:43:b2
# Subject: CN=emSign Root CA - C1,O=eMudhra Inc,OU=emSign PKI,C=US
# Not Valid Before: Sun Feb 18 18:30:00 2018
# Not Valid After : Wed Feb 18 18:30:00 2043
# Fingerprint (SHA-256): 12:56:09:AA:30:1D:A0:A2:49:B9:7A:82:39:CB:6A:34:21:6F:44:DC:AC:9F:39:54:B1:42:92:F2:E8:C8:60:8F
# Fingerprint (SHA1): E7:2E:F1:DF:FC:B2:09:28:CF:5D:D4:D5:67:37:B1:51:CB:86:4F:01
CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "emSign Root CA - C1"
CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
CKA_SUBJECT MULTILINE_OCTAL
\060\126\061\013\060\011\006\003\125\004\006\023\002\125\123\061
\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156
\040\120\113\111\061\024\060\022\006\003\125\004\012\023\013\145
\115\165\144\150\162\141\040\111\156\143\061\034\060\032\006\003
\125\004\003\023\023\145\155\123\151\147\156\040\122\157\157\164
\040\103\101\040\055\040\103\061
END
CKA_ID UTF8 "0"
CKA_ISSUER MULTILINE_OCTAL
\060\126\061\013\060\011\006\003\125\004\006\023\002\125\123\061
\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156
\040\120\113\111\061\024\060\022\006\003\125\004\012\023\013\145
\115\165\144\150\162\141\040\111\156\143\061\034\060\032\006\003
\125\004\003\023\023\145\155\123\151\147\156\040\122\157\157\164
\040\103\101\040\055\040\103\061
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\013\000\256\317\000\272\304\317\062\370\103\262
END
CKA_VALUE MULTILINE_OCTAL
\060\202\003\163\060\202\002\133\240\003\002\001\002\002\013\000
\256\317\000\272\304\317\062\370\103\262\060\015\006\011\052\206
\110\206\367\015\001\001\013\005\000\060\126\061\013\060\011\006
\003\125\004\006\023\002\125\123\061\023\060\021\006\003\125\004
\013\023\012\145\155\123\151\147\156\040\120\113\111\061\024\060
\022\006\003\125\004\012\023\013\145\115\165\144\150\162\141\040
\111\156\143\061\034\060\032\006\003\125\004\003\023\023\145\155
\123\151\147\156\040\122\157\157\164\040\103\101\040\055\040\103
\061\060\036\027\015\061\070\060\062\061\070\061\070\063\060\060
\060\132\027\015\064\063\060\062\061\070\061\070\063\060\060\060
\132\060\126\061\013\060\011\006\003\125\004\006\023\002\125\123
\061\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147
\156\040\120\113\111\061\024\060\022\006\003\125\004\012\023\013
\145\115\165\144\150\162\141\040\111\156\143\061\034\060\032\006
\003\125\004\003\023\023\145\155\123\151\147\156\040\122\157\157
\164\040\103\101\040\055\040\103\061\060\202\001\042\060\015\006
\011\052\206\110\206\367\015\001\001\001\005\000\003\202\001\017
\000\060\202\001\012\002\202\001\001\000\317\353\251\271\361\231
\005\314\330\050\041\112\363\163\064\121\204\126\020\365\240\117
\054\022\343\372\023\232\047\320\317\371\171\032\164\137\035\171
\071\374\133\370\160\216\340\222\122\367\344\045\371\124\203\331
\035\323\310\132\205\077\136\307\266\007\356\076\300\316\232\257
\254\126\102\052\071\045\160\326\277\265\173\066\255\254\366\163
\334\315\327\035\212\203\245\373\053\220\025\067\153\034\046\107
\334\073\051\126\223\152\263\301\152\072\235\075\365\301\227\070
\130\005\213\034\021\343\344\264\270\135\205\035\203\376\170\137
\013\105\150\030\110\245\106\163\064\073\376\017\310\166\273\307
\030\363\005\321\206\363\205\355\347\271\331\062\255\125\210\316
\246\266\221\260\117\254\176\025\043\226\366\077\360\040\064\026
\336\012\306\304\004\105\171\177\247\375\276\322\251\245\257\234
\305\043\052\367\074\041\154\275\257\217\116\305\072\262\363\064
\022\374\337\200\032\111\244\324\251\225\367\236\211\136\242\211
\254\224\313\250\150\233\257\212\145\047\315\211\356\335\214\265
\153\051\160\103\240\151\013\344\271\017\002\003\001\000\001\243
\102\060\100\060\035\006\003\125\035\016\004\026\004\024\376\241
\340\160\036\052\003\071\122\132\102\276\134\221\205\172\030\252
\115\265\060\016\006\003\125\035\017\001\001\377\004\004\003\002
\001\006\060\017\006\003\125\035\023\001\001\377\004\005\060\003
\001\001\377\060\015\006\011\052\206\110\206\367\015\001\001\013
\005\000\003\202\001\001\000\302\112\126\372\025\041\173\050\242
\351\345\035\373\370\055\304\071\226\101\114\073\047\054\304\154
\030\025\200\306\254\257\107\131\057\046\013\343\066\260\357\073
\376\103\227\111\062\231\022\025\133\337\021\051\377\253\123\370
\273\301\170\017\254\234\123\257\127\275\150\214\075\151\063\360
\243\240\043\143\073\144\147\042\104\255\325\161\313\126\052\170
\222\243\117\022\061\066\066\342\336\376\000\304\243\140\017\047
\255\240\260\212\265\066\172\122\241\275\047\364\040\047\142\350
\115\224\044\023\344\012\004\351\074\253\056\310\103\011\112\306
\141\004\345\111\064\176\323\304\310\365\017\300\252\351\272\124
\136\363\143\053\117\117\120\324\376\271\173\231\214\075\300\056
\274\002\053\323\304\100\344\212\007\061\036\233\316\046\231\023
\373\021\352\232\042\014\021\031\307\136\033\201\120\060\310\226
\022\156\347\313\101\177\221\073\242\107\267\124\200\033\334\000
\314\232\220\352\303\303\120\006\142\014\060\300\025\110\247\250
\131\174\341\256\042\242\342\012\172\017\372\142\253\122\114\341
\361\337\312\276\203\015\102
END
CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE
# Trust for "emSign Root CA - C1"
# Issuer: CN=emSign Root CA - C1,O=eMudhra Inc,OU=emSign PKI,C=US
# Serial Number:00:ae:cf:00:ba:c4:cf:32:f8:43:b2
# Subject: CN=emSign Root CA - C1,O=eMudhra Inc,OU=emSign PKI,C=US
# Not Valid Before: Sun Feb 18 18:30:00 2018
# Not Valid After : Wed Feb 18 18:30:00 2043
# Fingerprint (SHA-256): 12:56:09:AA:30:1D:A0:A2:49:B9:7A:82:39:CB:6A:34:21:6F:44:DC:AC:9F:39:54:B1:42:92:F2:E8:C8:60:8F
# Fingerprint (SHA1): E7:2E:F1:DF:FC:B2:09:28:CF:5D:D4:D5:67:37:B1:51:CB:86:4F:01
CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "emSign Root CA - C1"
CKA_CERT_SHA1_HASH MULTILINE_OCTAL
\347\056\361\337\374\262\011\050\317\135\324\325\147\067\261\121
\313\206\117\001
END
CKA_CERT_MD5_HASH MULTILINE_OCTAL
\330\343\135\001\041\372\170\132\260\337\272\322\356\052\137\150
END
CKA_ISSUER MULTILINE_OCTAL
\060\126\061\013\060\011\006\003\125\004\006\023\002\125\123\061
\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156
\040\120\113\111\061\024\060\022\006\003\125\004\012\023\013\145
\115\165\144\150\162\141\040\111\156\143\061\034\060\032\006\003
\125\004\003\023\023\145\155\123\151\147\156\040\122\157\157\164
\040\103\101\040\055\040\103\061
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\013\000\256\317\000\272\304\317\062\370\103\262
END
CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
#
# Certificate "emSign ECC Root CA - C3"
#
# Issuer: CN=emSign ECC Root CA - C3,O=eMudhra Inc,OU=emSign PKI,C=US
# Serial Number:7b:71:b6:82:56:b8:12:7c:9c:a8
# Subject: CN=emSign ECC Root CA - C3,O=eMudhra Inc,OU=emSign PKI,C=US
# Not Valid Before: Sun Feb 18 18:30:00 2018
# Not Valid After : Wed Feb 18 18:30:00 2043
# Fingerprint (SHA-256): BC:4D:80:9B:15:18:9D:78:DB:3E:1D:8C:F4:F9:72:6A:79:5D:A1:64:3C:A5:F1:35:8E:1D:DB:0E:DC:0D:7E:B3
# Fingerprint (SHA1): B6:AF:43:C2:9B:81:53:7D:F6:EF:6B:C3:1F:1F:60:15:0C:EE:48:66
CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "emSign ECC Root CA - C3"
CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
CKA_SUBJECT MULTILINE_OCTAL
\060\132\061\013\060\011\006\003\125\004\006\023\002\125\123\061
\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156
\040\120\113\111\061\024\060\022\006\003\125\004\012\023\013\145
\115\165\144\150\162\141\040\111\156\143\061\040\060\036\006\003
\125\004\003\023\027\145\155\123\151\147\156\040\105\103\103\040
\122\157\157\164\040\103\101\040\055\040\103\063
END
CKA_ID UTF8 "0"
CKA_ISSUER MULTILINE_OCTAL
\060\132\061\013\060\011\006\003\125\004\006\023\002\125\123\061
\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156
\040\120\113\111\061\024\060\022\006\003\125\004\012\023\013\145
\115\165\144\150\162\141\040\111\156\143\061\040\060\036\006\003
\125\004\003\023\027\145\155\123\151\147\156\040\105\103\103\040
\122\157\157\164\040\103\101\040\055\040\103\063
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\012\173\161\266\202\126\270\022\174\234\250
END
CKA_VALUE MULTILINE_OCTAL
\060\202\002\053\060\202\001\261\240\003\002\001\002\002\012\173
\161\266\202\126\270\022\174\234\250\060\012\006\010\052\206\110
\316\075\004\003\003\060\132\061\013\060\011\006\003\125\004\006
\023\002\125\123\061\023\060\021\006\003\125\004\013\023\012\145
\155\123\151\147\156\040\120\113\111\061\024\060\022\006\003\125
\004\012\023\013\145\115\165\144\150\162\141\040\111\156\143\061
\040\060\036\006\003\125\004\003\023\027\145\155\123\151\147\156
\040\105\103\103\040\122\157\157\164\040\103\101\040\055\040\103
\063\060\036\027\015\061\070\060\062\061\070\061\070\063\060\060
\060\132\027\015\064\063\060\062\061\070\061\070\063\060\060\060
\132\060\132\061\013\060\011\006\003\125\004\006\023\002\125\123
\061\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147
\156\040\120\113\111\061\024\060\022\006\003\125\004\012\023\013
\145\115\165\144\150\162\141\040\111\156\143\061\040\060\036\006
\003\125\004\003\023\027\145\155\123\151\147\156\040\105\103\103
\040\122\157\157\164\040\103\101\040\055\040\103\063\060\166\060
\020\006\007\052\206\110\316\075\002\001\006\005\053\201\004\000
\042\003\142\000\004\375\245\141\256\173\046\020\035\351\267\042
\060\256\006\364\201\263\261\102\161\225\071\274\323\122\343\257
\257\371\362\227\065\222\066\106\016\207\225\215\271\071\132\351
\273\337\320\376\310\007\101\074\273\125\157\203\243\152\373\142
\260\201\211\002\160\175\110\305\112\343\351\042\124\042\115\223
\273\102\014\257\167\234\043\246\175\327\141\021\316\145\307\370
\177\376\365\362\251\243\102\060\100\060\035\006\003\125\035\016
\004\026\004\024\373\132\110\320\200\040\100\362\250\351\000\007
\151\031\167\247\346\303\364\317\060\016\006\003\125\035\017\001
\001\377\004\004\003\002\001\006\060\017\006\003\125\035\023\001
\001\377\004\005\060\003\001\001\377\060\012\006\010\052\206\110
\316\075\004\003\003\003\150\000\060\145\002\061\000\264\330\057
\002\211\375\266\114\142\272\103\116\023\204\162\265\256\335\034
\336\326\265\334\126\217\130\100\132\055\336\040\114\042\203\312
\223\250\176\356\022\100\307\326\207\117\370\337\205\002\060\034
\024\144\344\174\226\203\021\234\260\321\132\141\113\246\017\111
\323\000\374\241\374\344\245\377\177\255\327\060\320\307\167\177
\276\201\007\125\060\120\040\024\365\127\070\012\250\061\121
END
CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE
# Trust for "emSign ECC Root CA - C3"
# Issuer: CN=emSign ECC Root CA - C3,O=eMudhra Inc,OU=emSign PKI,C=US
# Serial Number:7b:71:b6:82:56:b8:12:7c:9c:a8
# Subject: CN=emSign ECC Root CA - C3,O=eMudhra Inc,OU=emSign PKI,C=US
# Not Valid Before: Sun Feb 18 18:30:00 2018
# Not Valid After : Wed Feb 18 18:30:00 2043
# Fingerprint (SHA-256): BC:4D:80:9B:15:18:9D:78:DB:3E:1D:8C:F4:F9:72:6A:79:5D:A1:64:3C:A5:F1:35:8E:1D:DB:0E:DC:0D:7E:B3
# Fingerprint (SHA1): B6:AF:43:C2:9B:81:53:7D:F6:EF:6B:C3:1F:1F:60:15:0C:EE:48:66
CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "emSign ECC Root CA - C3"
CKA_CERT_SHA1_HASH MULTILINE_OCTAL
\266\257\103\302\233\201\123\175\366\357\153\303\037\037\140\025
\014\356\110\146
END
CKA_CERT_MD5_HASH MULTILINE_OCTAL
\076\123\263\243\201\356\327\020\370\323\260\035\027\222\365\325
END
CKA_ISSUER MULTILINE_OCTAL
\060\132\061\013\060\011\006\003\125\004\006\023\002\125\123\061
\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156
\040\120\113\111\061\024\060\022\006\003\125\004\012\023\013\145
\115\165\144\150\162\141\040\111\156\143\061\040\060\036\006\003
\125\004\003\023\027\145\155\123\151\147\156\040\105\103\103\040
\122\157\157\164\040\103\101\040\055\040\103\063
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\012\173\161\266\202\126\270\022\174\234\250
END
CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
#
# Certificate "Hongkong Post Root CA 3"
#
# Issuer: CN=Hongkong Post Root CA 3,O=Hongkong Post,L=Hong Kong,ST=Hong Kong,C=HK
# Serial Number:08:16:5f:8a:4c:a5:ec:00:c9:93:40:df:c4:c6:ae:23:b8:1c:5a:a4
# Subject: CN=Hongkong Post Root CA 3,O=Hongkong Post,L=Hong Kong,ST=Hong Kong,C=HK
# Not Valid Before: Sat Jun 03 02:29:46 2017
# Not Valid After : Tue Jun 03 02:29:46 2042
# Fingerprint (SHA-256): 5A:2F:C0:3F:0C:83:B0:90:BB:FA:40:60:4B:09:88:44:6C:76:36:18:3D:F9:84:6E:17:10:1A:44:7F:B8:EF:D6
# Fingerprint (SHA1): 58:A2:D0:EC:20:52:81:5B:C1:F3:F8:64:02:24:4E:C2:8E:02:4B:02
CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "Hongkong Post Root CA 3"
CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
CKA_SUBJECT MULTILINE_OCTAL
\060\157\061\013\060\011\006\003\125\004\006\023\002\110\113\061
\022\060\020\006\003\125\004\010\023\011\110\157\156\147\040\113
\157\156\147\061\022\060\020\006\003\125\004\007\023\011\110\157
\156\147\040\113\157\156\147\061\026\060\024\006\003\125\004\012
\023\015\110\157\156\147\153\157\156\147\040\120\157\163\164\061
\040\060\036\006\003\125\004\003\023\027\110\157\156\147\153\157
\156\147\040\120\157\163\164\040\122\157\157\164\040\103\101\040
\063
END
CKA_ID UTF8 "0"
CKA_ISSUER MULTILINE_OCTAL
\060\157\061\013\060\011\006\003\125\004\006\023\002\110\113\061
\022\060\020\006\003\125\004\010\023\011\110\157\156\147\040\113
\157\156\147\061\022\060\020\006\003\125\004\007\023\011\110\157
\156\147\040\113\157\156\147\061\026\060\024\006\003\125\004\012
\023\015\110\157\156\147\153\157\156\147\040\120\157\163\164\061
\040\060\036\006\003\125\004\003\023\027\110\157\156\147\153\157
\156\147\040\120\157\163\164\040\122\157\157\164\040\103\101\040
\063
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\024\010\026\137\212\114\245\354\000\311\223\100\337\304\306
\256\043\270\034\132\244
END
CKA_VALUE MULTILINE_OCTAL
\060\202\005\317\060\202\003\267\240\003\002\001\002\002\024\010
\026\137\212\114\245\354\000\311\223\100\337\304\306\256\043\270
\034\132\244\060\015\006\011\052\206\110\206\367\015\001\001\013
\005\000\060\157\061\013\060\011\006\003\125\004\006\023\002\110
\113\061\022\060\020\006\003\125\004\010\023\011\110\157\156\147
\040\113\157\156\147\061\022\060\020\006\003\125\004\007\023\011
\110\157\156\147\040\113\157\156\147\061\026\060\024\006\003\125
\004\012\023\015\110\157\156\147\153\157\156\147\040\120\157\163
\164\061\040\060\036\006\003\125\004\003\023\027\110\157\156\147
\153\157\156\147\040\120\157\163\164\040\122\157\157\164\040\103
\101\040\063\060\036\027\015\061\067\060\066\060\063\060\062\062
\071\064\066\132\027\015\064\062\060\066\060\063\060\062\062\071
\064\066\132\060\157\061\013\060\011\006\003\125\004\006\023\002
\110\113\061\022\060\020\006\003\125\004\010\023\011\110\157\156
\147\040\113\157\156\147\061\022\060\020\006\003\125\004\007\023
\011\110\157\156\147\040\113\157\156\147\061\026\060\024\006\003
\125\004\012\023\015\110\157\156\147\153\157\156\147\040\120\157
\163\164\061\040\060\036\006\003\125\004\003\023\027\110\157\156
\147\153\157\156\147\040\120\157\163\164\040\122\157\157\164\040
\103\101\040\063\060\202\002\042\060\015\006\011\052\206\110\206
\367\015\001\001\001\005\000\003\202\002\017\000\060\202\002\012
\002\202\002\001\000\263\210\327\352\316\017\040\116\276\346\326
\003\155\356\131\374\302\127\337\051\150\241\203\016\076\150\307
\150\130\234\034\140\113\211\103\014\271\324\025\262\356\301\116
\165\351\265\247\357\345\351\065\231\344\314\034\347\113\137\215
\063\060\040\063\123\331\246\273\325\076\023\216\351\037\207\111
\255\120\055\120\312\030\276\001\130\242\023\160\226\273\211\210
\126\200\134\370\275\054\074\341\114\127\210\273\323\271\225\357
\313\307\366\332\061\164\050\246\346\124\211\365\101\061\312\345
\046\032\315\202\340\160\332\073\051\273\325\003\365\231\272\125
\365\144\321\140\016\263\211\111\270\212\057\005\322\204\105\050
\174\217\150\120\022\170\374\013\265\123\313\302\230\034\204\243
\236\260\276\043\244\332\334\310\053\036\332\156\105\036\211\230
\332\371\000\056\006\351\014\073\160\325\120\045\210\231\313\315
\163\140\367\325\377\065\147\305\241\274\136\253\315\112\270\105
\353\310\150\036\015\015\024\106\022\343\322\144\142\212\102\230
\274\264\306\010\010\370\375\250\114\144\234\166\001\275\057\251
\154\063\017\330\077\050\270\074\151\001\102\206\176\151\301\311
\006\312\345\172\106\145\351\302\326\120\101\056\077\267\344\355
\154\327\277\046\001\021\242\026\051\112\153\064\006\220\354\023
\322\266\373\152\166\322\074\355\360\326\055\335\341\025\354\243
\233\057\054\311\076\053\344\151\073\377\162\045\261\066\206\133
\307\177\153\213\125\033\112\305\040\141\075\256\313\120\341\010
\072\276\260\217\143\101\123\060\010\131\074\230\035\167\272\143
\221\172\312\020\120\140\277\360\327\274\225\207\217\227\305\376
\227\152\001\224\243\174\133\205\035\052\071\072\320\124\241\321
\071\161\235\375\041\371\265\173\360\342\340\002\217\156\226\044
\045\054\240\036\054\250\304\211\247\357\355\231\006\057\266\012
\114\117\333\242\314\067\032\257\107\205\055\212\137\304\064\064
\114\000\375\030\223\147\023\321\067\346\110\264\213\006\305\127
\173\031\206\012\171\313\000\311\122\257\102\377\067\217\341\243
\036\172\075\120\253\143\006\347\025\265\077\266\105\067\224\067
\261\176\362\110\303\177\305\165\376\227\215\105\217\032\247\032
\162\050\032\100\017\002\003\001\000\001\243\143\060\141\060\017
\006\003\125\035\023\001\001\377\004\005\060\003\001\001\377\060
\016\006\003\125\035\017\001\001\377\004\004\003\002\001\006\060
\037\006\003\125\035\043\004\030\060\026\200\024\027\235\315\036
\213\326\071\053\160\323\134\324\240\270\037\260\000\374\305\141
\060\035\006\003\125\035\016\004\026\004\024\027\235\315\036\213
\326\071\053\160\323\134\324\240\270\037\260\000\374\305\141\060
\015\006\011\052\206\110\206\367\015\001\001\013\005\000\003\202
\002\001\000\126\325\173\156\346\042\001\322\102\233\030\325\016
\327\146\043\134\343\376\240\307\222\322\351\224\255\113\242\306
\354\022\174\164\325\110\322\131\024\231\300\353\271\321\353\364
\110\060\133\255\247\127\163\231\251\323\345\267\321\056\131\044
\130\334\150\056\056\142\330\152\344\160\013\055\040\120\040\244
\062\225\321\000\230\273\323\375\367\062\362\111\256\306\172\340
\107\276\156\316\313\243\162\072\055\151\135\313\310\350\105\071
\324\372\102\301\021\114\167\135\222\373\152\377\130\104\345\353
\201\236\257\240\231\255\276\251\001\146\313\070\035\074\337\103
\037\364\115\156\264\272\027\106\374\175\375\207\201\171\152\015
\063\017\372\057\370\024\271\200\263\135\115\252\227\341\371\344
\030\305\370\325\070\214\046\074\375\362\050\342\356\132\111\210
\054\337\171\075\216\236\220\074\275\101\112\072\335\133\366\232
\264\316\077\045\060\177\062\175\242\003\224\320\334\172\241\122
\336\156\223\215\030\046\375\125\254\275\217\233\322\317\257\347
\206\054\313\037\011\157\243\157\251\204\324\163\277\115\241\164
\033\116\043\140\362\314\016\252\177\244\234\114\045\250\262\146
\073\070\377\331\224\060\366\162\204\276\150\125\020\017\306\163
\054\026\151\223\007\376\261\105\355\273\242\125\152\260\332\265
\112\002\045\047\205\327\267\267\206\104\026\211\154\200\053\076
\227\251\234\325\176\125\114\306\336\105\020\034\352\351\073\237
\003\123\356\356\172\001\002\026\170\324\350\302\276\106\166\210
\023\077\042\273\110\022\035\122\000\264\002\176\041\032\036\234
\045\364\363\075\136\036\322\034\371\263\055\266\367\067\134\306
\313\041\116\260\367\231\107\030\205\301\053\272\125\256\006\352
\320\007\262\334\253\320\202\226\165\316\322\120\376\231\347\317
\057\237\347\166\321\141\052\373\041\273\061\320\252\237\107\244
\262\042\312\026\072\120\127\304\133\103\147\305\145\142\003\111
\001\353\103\331\330\370\236\255\317\261\143\016\105\364\240\132
\054\233\055\305\246\300\255\250\107\364\047\114\070\015\056\033
\111\073\122\364\350\210\203\053\124\050\324\362\065\122\264\062
\203\142\151\144\014\221\234\237\227\352\164\026\375\037\021\006
\232\233\364
END
CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE
# Trust for "Hongkong Post Root CA 3"
# Issuer: CN=Hongkong Post Root CA 3,O=Hongkong Post,L=Hong Kong,ST=Hong Kong,C=HK
# Serial Number:08:16:5f:8a:4c:a5:ec:00:c9:93:40:df:c4:c6:ae:23:b8:1c:5a:a4
# Subject: CN=Hongkong Post Root CA 3,O=Hongkong Post,L=Hong Kong,ST=Hong Kong,C=HK
# Not Valid Before: Sat Jun 03 02:29:46 2017
# Not Valid After : Tue Jun 03 02:29:46 2042
# Fingerprint (SHA-256): 5A:2F:C0:3F:0C:83:B0:90:BB:FA:40:60:4B:09:88:44:6C:76:36:18:3D:F9:84:6E:17:10:1A:44:7F:B8:EF:D6
# Fingerprint (SHA1): 58:A2:D0:EC:20:52:81:5B:C1:F3:F8:64:02:24:4E:C2:8E:02:4B:02
CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "Hongkong Post Root CA 3"
CKA_CERT_SHA1_HASH MULTILINE_OCTAL
\130\242\320\354\040\122\201\133\301\363\370\144\002\044\116\302
\216\002\113\002
END
CKA_CERT_MD5_HASH MULTILINE_OCTAL
\021\374\237\275\163\060\002\212\375\077\363\130\271\313\040\360
END
CKA_ISSUER MULTILINE_OCTAL
\060\157\061\013\060\011\006\003\125\004\006\023\002\110\113\061
\022\060\020\006\003\125\004\010\023\011\110\157\156\147\040\113
\157\156\147\061\022\060\020\006\003\125\004\007\023\011\110\157
\156\147\040\113\157\156\147\061\026\060\024\006\003\125\004\012
\023\015\110\157\156\147\153\157\156\147\040\120\157\163\164\061
\040\060\036\006\003\125\004\003\023\027\110\157\156\147\153\157
\156\147\040\120\157\163\164\040\122\157\157\164\040\103\101\040
\063
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\024\010\026\137\212\114\245\354\000\311\223\100\337\304\306
\256\043\270\034\132\244
END
CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
+2 -2
View File
@@ -46,8 +46,8 @@
* It's recommend to switch back to 0 after having reached version 98/99.
*/
#define NSS_BUILTINS_LIBRARY_VERSION_MAJOR 2
#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 30
#define NSS_BUILTINS_LIBRARY_VERSION "2.30"
#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 32
#define NSS_BUILTINS_LIBRARY_VERSION "2.32"
/* These version numbers detail the semantic changes to the ckfw engine. */
#define NSS_BUILTINS_HARDWARE_VERSION_MAJOR 1
+56 -12
View File
@@ -92,23 +92,32 @@ CheckX86CPUSupport()
#endif /* NSS_X86_OR_X64 */
/* clang-format off */
#if (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__)
#if defined(__aarch64__) || defined(__arm__)
#ifndef __has_include
#define __has_include(x) 0
#endif
#if (__has_include(<sys/auxv.h>) || defined(__linux__)) && \
defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__)
/* This might be conflict with host compiler */
#if !defined(__ANDROID__)
#include <sys/auxv.h>
#endif
extern unsigned long getauxval(unsigned long type) __attribute__((weak));
#else
static unsigned long (*getauxval)(unsigned long) = NULL;
#define AT_HWCAP2 0
#define AT_HWCAP 0
#endif /* defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__)*/
#endif /* (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__) */
#ifndef AT_HWCAP2
#define AT_HWCAP2 26
#endif
#ifndef AT_HWCAP
#define AT_HWCAP 16
#endif
#endif /* defined(__aarch64__) || defined(__arm__) */
/* clang-format on */
#if defined(__aarch64__) && !defined(__ANDROID__)
#if defined(__aarch64__)
// Defines from hwcap.h in Linux kernel - ARM64
#ifndef HWCAP_AES
#define HWCAP_AES (1 << 3)
@@ -138,9 +147,9 @@ CheckARMSupport()
/* aarch64 must support NEON. */
arm_neon_support_ = disable_arm_neon == NULL;
}
#endif /* defined(__aarch64__) && !defined(__ANDROID__) */
#endif /* defined(__aarch64__) */
#if defined(__arm__) && !defined(__ANDROID__)
#if defined(__arm__)
// Defines from hwcap.h in Linux kernel - ARM
/*
* HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
@@ -165,23 +174,58 @@ CheckARMSupport()
#define HWCAP2_SHA2 (1 << 3)
#endif
PRBool
GetNeonSupport()
{
char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON");
if (disable_arm_neon) {
return PR_FALSE;
}
#if defined(__ARM_NEON) || defined(__ARM_NEON__)
// Compiler generates NEON instruction as default option.
// If no getauxval, compiler generate NEON instruction by default,
// we should allow NOEN support.
return PR_TRUE;
#elif !defined(__ANDROID__)
// Android's cpu-features.c detects features by the following logic
//
// - Call getauxval(AT_HWCAP)
// - Parse /proc/self/auxv if getauxval is nothing or returns 0
// - Parse /proc/cpuinfo if both cannot detect features
//
// But we don't use it for Android since Android document
// (https://developer.android.com/ndk/guides/cpu-features) says
// one problem with AT_HWCAP sometimes devices (Nexus 4 and emulator)
// are mistaken for IDIV.
if (getauxval) {
return (getauxval(AT_HWCAP) & HWCAP_NEON);
}
#endif /* defined(__ARM_NEON) || defined(__ARM_NEON__) */
return PR_FALSE;
}
void
CheckARMSupport()
{
char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON");
char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES");
if (getauxval) {
// Android's cpu-features.c uses AT_HWCAP2 for newer features.
// AT_HWCAP2 is implemented on newer devices / kernel, so we can trust
// it since cpu-features.c doesn't have workaround / fallback.
// Also, AT_HWCAP2 is supported by glibc 2.18+ on Linux/arm, If
// AT_HWCAP2 isn't supported by glibc or Linux kernel, getauxval will
// returns 0.
long hwcaps = getauxval(AT_HWCAP2);
arm_aes_support_ = hwcaps & HWCAP2_AES && disable_hw_aes == NULL;
arm_pmull_support_ = hwcaps & HWCAP2_PMULL;
arm_sha1_support_ = hwcaps & HWCAP2_SHA1;
arm_sha2_support_ = hwcaps & HWCAP2_SHA2;
arm_neon_support_ = hwcaps & HWCAP_NEON && disable_arm_neon == NULL;
}
arm_neon_support_ = GetNeonSupport();
}
#endif /* defined(__arm__) && !defined(__ANDROID__) */
#endif /* defined(__arm__) */
// Enable when Firefox can use it.
// Enable when Firefox can use it for Android API 16 and 17.
// #if defined(__ANDROID__) && (defined(__arm__) || defined(__aarch64__))
// #include <cpu-features.h>
// void
@@ -262,7 +306,7 @@ FreeblInit(void)
{
#ifdef NSS_X86_OR_X64
CheckX86CPUSupport();
#elif (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__)
#elif (defined(__aarch64__) || defined(__arm__))
CheckARMSupport();
#endif
return PR_SUCCESS;
@@ -157,6 +157,7 @@ ChaCha20Poly1305_DestroyContext(ChaCha20Poly1305Context *ctx, PRBool freeit)
#endif
}
#ifndef NSS_DISABLE_CHACHAPOLY
void
ChaCha20Xor(uint8_t *output, uint8_t *block, uint32_t len, uint8_t *k,
uint8_t *nonce, uint32_t ctr)
@@ -167,6 +168,7 @@ ChaCha20Xor(uint8_t *output, uint8_t *block, uint32_t len, uint8_t *k,
Hacl_Chacha20_chacha20(output, block, len, k, nonce, ctr);
}
}
#endif /* NSS_DISABLE_CHACHAPOLY */
SECStatus
ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output,
+1 -1
View File
@@ -22,7 +22,7 @@ swap8b(PRUint64 value)
return (value);
}
#elif !defined(_MSC_VER)
#elif !defined(_MSC_VER) && !__has_builtin(__builtin_bswap64)
PRUint64
swap8b(PRUint64 x)
+15 -1
View File
@@ -11,6 +11,11 @@
#include <stdlib.h>
#include "prtypes.h"
/* For non-clang platform */
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
/* Unfortunately this isn't always set when it should be. */
#if defined(HAVE_LONG_LONG)
@@ -29,11 +34,16 @@
/*
* FREEBL_HTONLL(x): swap bytes in a 64-bit integer.
*/
#if defined(IS_LITTLE_ENDIAN)
#if defined(_MSC_VER)
#pragma intrinsic(_byteswap_uint64)
#define FREEBL_HTONLL(x) _byteswap_uint64(x)
#elif __has_builtin(__builtin_bswap64)
#define FREEBL_HTONLL(x) __builtin_bswap64(x)
#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__x86_64))
PRUint64 swap8b(PRUint64 value);
@@ -48,4 +58,8 @@ PRUint64 swap8b(PRUint64 x);
#endif /* _MSC_VER */
#endif /* HAVE_LONG_LONG */
#else /* IS_LITTLE_ENDIAN */
#define FREEBL_HTONLL(x) (x)
#endif
#endif /* HAVE_LONG_LONG */
+5 -5
View File
@@ -76,11 +76,11 @@
'__SSSE3__',
],
}],
[ 'OS=="android"', {
# On Android we can't use any of the hardware acceleration :(
'defines!': [
'__ARM_NEON__',
'__ARM_NEON',
[ 'target_arch=="arm"', {
# Gecko doesn't support non-NEON platform on Android, but tier-3
# platform such as Linux/arm will need it
'cflags_mozilla': [
'-mfpu=neon'
],
}],
],
+1 -1
View File
@@ -32,7 +32,7 @@ RNG_SystemRNG(void *dest, size_t maxLen)
size_t fileBytes = 0;
unsigned char *buffer = dest;
#if defined(__OpenBSD__) || (defined(LINUX) && defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25))))
#if defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || (defined(LINUX) && defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25))))
int result;
while (fileBytes < maxLen) {
+6
View File
@@ -1145,3 +1145,9 @@ HASH_GetHashOidTagByHashType;
;+ local:
;+ *;
;+};
;+NSS_3.44 { # NSS 3.44 release
;+ global:
CERT_GetCertificateDer;
;+ local:
;+ *;
;+};
+2 -2
View File
@@ -22,9 +22,9 @@
* The format of the version string should be
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
*/
#define NSS_VERSION "3.43" _NSS_CUSTOMIZED " Beta"
#define NSS_VERSION "3.44" _NSS_CUSTOMIZED " Beta"
#define NSS_VMAJOR 3
#define NSS_VMINOR 43
#define NSS_VMINOR 44
#define NSS_VPATCH 0
#define NSS_VBUILD 0
#define NSS_BETA PR_TRUE
+108 -6
View File
@@ -1677,6 +1677,95 @@ PK11_MakeKEAPubKey(unsigned char *keyData, int length)
return pubk;
}
SECStatus
SECKEY_SetPublicValue(SECKEYPrivateKey *privKey, SECItem *publicValue)
{
SECStatus rv;
SECKEYPublicKey pubKey;
PLArenaPool *arena;
PK11SlotInfo *slot;
CK_OBJECT_HANDLE privKeyID;
if (privKey == NULL || publicValue == NULL ||
publicValue->data == NULL || publicValue->len == 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
pubKey.arena = NULL;
pubKey.keyType = privKey->keyType;
pubKey.pkcs11Slot = NULL;
pubKey.pkcs11ID = CK_INVALID_HANDLE;
/* can't use PORT_InitCheapArena here becase SECKEY_DestroyPublic is used
* to free it, and it uses PORT_FreeArena which not only frees the
* underlying arena, it also frees the allocated arena struct. */
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
pubKey.arena = arena;
if (arena == NULL) {
return SECFailure;
}
slot = privKey->pkcs11Slot;
privKeyID = privKey->pkcs11ID;
rv = SECFailure;
switch (privKey->keyType) {
default:
/* error code already set to SECFailure */
break;
case rsaKey:
pubKey.u.rsa.modulus = *publicValue;
rv = PK11_ReadAttribute(slot, privKeyID, CKA_PUBLIC_EXPONENT,
arena, &pubKey.u.rsa.publicExponent);
break;
case dsaKey:
pubKey.u.dsa.publicValue = *publicValue;
rv = PK11_ReadAttribute(slot, privKeyID, CKA_PRIME,
arena, &pubKey.u.dsa.params.prime);
if (rv != SECSuccess) {
break;
}
rv = PK11_ReadAttribute(slot, privKeyID, CKA_SUBPRIME,
arena, &pubKey.u.dsa.params.subPrime);
if (rv != SECSuccess) {
break;
}
rv = PK11_ReadAttribute(slot, privKeyID, CKA_BASE,
arena, &pubKey.u.dsa.params.base);
break;
case dhKey:
pubKey.u.dh.publicValue = *publicValue;
rv = PK11_ReadAttribute(slot, privKeyID, CKA_PRIME,
arena, &pubKey.u.dh.prime);
if (rv != SECSuccess) {
break;
}
rv = PK11_ReadAttribute(slot, privKeyID, CKA_BASE,
arena, &pubKey.u.dh.base);
break;
case ecKey:
pubKey.u.ec.publicValue = *publicValue;
pubKey.u.ec.encoding = ECPoint_Undefined;
pubKey.u.ec.size = 0;
rv = PK11_ReadAttribute(slot, privKeyID, CKA_EC_PARAMS,
arena, &pubKey.u.ec.DEREncodedParams);
break;
}
if (rv == SECSuccess) {
rv = PK11_ImportPublicKey(slot, &pubKey, PR_TRUE);
}
/* Even though pubKey is stored on the stack, we've allocated
* some of it's data from the arena. SECKEY_DestroyPublicKey
* destroys keys by freeing the arena, so this will clean up all
* the data we allocated specifically for the key above. It will
* also free any slot references which we may have picked up in
* PK11_ImportPublicKey. It won't delete the underlying key if
* its a Token/Permanent key (which it will be if
* PK11_ImportPublicKey succeeds). */
SECKEY_DestroyPublicKey(&pubKey);
return rv;
}
/*
* NOTE: This function doesn't return a SECKEYPrivateKey struct to represent
* the new private key object. If it were to create a session object that
@@ -1802,12 +1891,6 @@ try_faulty_3des:
nickname, publicValue, isPerm, isPrivate,
key_type, usage, usageCount, wincx);
if (privKey) {
if (privk) {
*privk = privKey;
} else {
SECKEY_DestroyPrivateKey(privKey);
}
privKey = NULL;
rv = SECSuccess;
goto done;
}
@@ -1837,6 +1920,25 @@ try_faulty_3des:
rv = SECFailure;
done:
if ((rv == SECSuccess) && isPerm) {
/* If we are importing a token object,
* create the corresponding public key.
* If this fails, just continue as the target
* token simply might not support persistant
* public keys. Such tokens are usable, but
* need to be authenticated before searching
* for user certs. */
(void)SECKEY_SetPublicValue(privKey, publicValue);
}
if (privKey) {
if (privk) {
*privk = privKey;
} else {
SECKEY_DestroyPrivateKey(privKey);
}
privKey = NULL;
}
if (crypto_param != NULL) {
SECITEM_ZfreeItem(crypto_param, PR_TRUE);
}
+20 -6
View File
@@ -238,6 +238,8 @@ static const oidValDef curveOptList[] = {
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
{ CIPHER_NAME("SECP521R1"), SEC_OID_SECG_EC_SECP521R1,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
{ CIPHER_NAME("CURVE25519"), SEC_OID_CURVE25519,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
/* ANSI X9.62 named elliptic curves (characteristic two field) */
{ CIPHER_NAME("C2PNB163V1"), SEC_OID_ANSIX962_EC_C2PNB163V1,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
@@ -384,18 +386,26 @@ static const oidValDef kxOptList[] = {
{ CIPHER_NAME("ECDH-RSA"), SEC_OID_TLS_ECDH_RSA, NSS_USE_ALG_IN_SSL_KX },
};
static const oidValDef signOptList[] = {
/* Signatures */
{ CIPHER_NAME("DSA"), SEC_OID_ANSIX9_DSA_SIGNATURE,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
};
typedef struct {
const oidValDef *list;
PRUint32 entries;
const char *description;
PRBool allowEmpty;
} algListsDef;
static const algListsDef algOptLists[] = {
{ curveOptList, PR_ARRAY_SIZE(curveOptList), "ECC" },
{ hashOptList, PR_ARRAY_SIZE(hashOptList), "HASH" },
{ macOptList, PR_ARRAY_SIZE(macOptList), "MAC" },
{ cipherOptList, PR_ARRAY_SIZE(cipherOptList), "CIPHER" },
{ kxOptList, PR_ARRAY_SIZE(kxOptList), "OTHER-KX" },
{ curveOptList, PR_ARRAY_SIZE(curveOptList), "ECC", PR_FALSE },
{ hashOptList, PR_ARRAY_SIZE(hashOptList), "HASH", PR_FALSE },
{ macOptList, PR_ARRAY_SIZE(macOptList), "MAC", PR_FALSE },
{ cipherOptList, PR_ARRAY_SIZE(cipherOptList), "CIPHER", PR_FALSE },
{ kxOptList, PR_ARRAY_SIZE(kxOptList), "OTHER-KX", PR_FALSE },
{ signOptList, PR_ARRAY_SIZE(signOptList), "OTHER-SIGN", PR_TRUE },
};
static const optionFreeDef sslOptList[] = {
@@ -718,7 +728,7 @@ secmod_sanityCheckCryptoPolicy(void)
for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) {
const algListsDef *algOptList = &algOptLists[i];
fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-%s: %u\n", enabledCount[i] ? sInfo : sWarn, algOptList->description, enabledCount[i]);
if (!enabledCount[i]) {
if (!enabledCount[i] && !algOptList->allowEmpty) {
haveWarning = PR_TRUE;
}
}
@@ -807,6 +817,10 @@ SECMOD_CreateModuleEx(const char *library, const char *moduleName,
mod->internal = NSSUTIL_ArgHasFlag("flags", "internal", nssc);
mod->isFIPS = NSSUTIL_ArgHasFlag("flags", "FIPS", nssc);
/* if the system FIPS mode is enabled, force FIPS to be on */
if (secmod_GetSystemFIPSEnabled()) {
mod->isFIPS = PR_TRUE;
}
mod->isCritical = NSSUTIL_ArgHasFlag("flags", "critical", nssc);
slotParams = NSSUTIL_ArgGetParamValue("slotParams", nssc);
mod->slotInfo = NSSUTIL_ArgParseSlotInfo(mod->arena, slotParams,
+27 -2
View File
@@ -95,6 +95,31 @@ SECMOD_Shutdown()
return SECSuccess;
}
int
secmod_GetSystemFIPSEnabled(void)
{
#ifdef LINUX
FILE *f;
char d;
size_t size;
f = fopen("/proc/sys/crypto/fips_enabled", "r");
if (!f) {
return 0;
}
size = fread(&d, 1, sizeof(d), f);
fclose(f);
if (size != sizeof(d)) {
return 0;
}
if (d == '1') {
return 1;
}
#endif
return 0;
}
/*
* retrieve the internal module
*/
@@ -428,7 +453,7 @@ SECMOD_DeleteInternalModule(const char *name)
SECMODModuleList **mlpp;
SECStatus rv = SECFailure;
if (pendingModule) {
if (secmod_GetSystemFIPSEnabled() || pendingModule) {
PORT_SetError(SEC_ERROR_MODULE_STUCK);
return rv;
}
@@ -963,7 +988,7 @@ SECMOD_CanDeleteInternalModule(void)
#ifdef NSS_FIPS_DISABLED
return PR_FALSE;
#else
return (PRBool)(pendingModule == NULL);
return (PRBool)((pendingModule == NULL) && !secmod_GetSystemFIPSEnabled());
#endif
}
+7
View File
@@ -115,6 +115,13 @@ PK11SymKey *pk11_TokenKeyGenWithFlagsAndKeyType(PK11SlotInfo *slot,
CK_MECHANISM_TYPE pk11_GetPBECryptoMechanism(SECAlgorithmID *algid,
SECItem **param, SECItem *pwd, PRBool faulty3DES);
/* Get the state of the system FIPS mode */
/* NSS uses this to force FIPS mode if the system bit is on. Applications which
* use the SECMOD_CanDeleteInteral() to check to see if they can switch to or
* from FIPS mode will automatically be told that they can't swith out of FIPS
* mode */
int secmod_GetSystemFIPSEnabled();
extern void pk11sdr_Init(void);
extern void pk11sdr_Shutdown(void);
+10 -8
View File
@@ -492,14 +492,16 @@ typedef struct {
static SECStatus
collect_certs(void *arg, SECItem **certs, int numcerts)
{
SECStatus rv;
collect_args *collectArgs;
collectArgs = (collect_args *)arg;
rv = SECITEM_CopyItem(collectArgs->arena, &collectArgs->cert, *certs);
return (rv);
collect_args *collectArgs = (collect_args *)arg;
if (!collectArgs || !collectArgs->arena) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (numcerts < 1 || !certs || !*certs) {
PORT_SetError(SEC_ERROR_BAD_DER);
return SECFailure;
}
return SECITEM_CopyItem(collectArgs->arena, &collectArgs->cert, *certs);
}
/*
+7 -3
View File
@@ -1815,8 +1815,6 @@ sftk_GetPubKey(SFTKObject *object, CK_KEY_TYPE key_type,
break; /* key was not DER encoded, no need to unwrap */
}
PORT_Assert(pubKey->u.ec.ecParams.name != ECCurve25519);
/* handle the encoded case */
if ((pubKey->u.ec.publicValue.data[0] == SEC_ASN1_OCTET_STRING) &&
pubKey->u.ec.publicValue.len > keyLen) {
@@ -1827,7 +1825,13 @@ sftk_GetPubKey(SFTKObject *object, CK_KEY_TYPE key_type,
SEC_ASN1_GET(SEC_OctetStringTemplate),
&pubKey->u.ec.publicValue);
/* nope, didn't decode correctly */
if ((rv != SECSuccess) || (publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) || (publicValue.len != keyLen)) {
if ((rv != SECSuccess) || (publicValue.len != keyLen)) {
crv = CKR_ATTRIBUTE_VALUE_INVALID;
break;
}
/* we don't handle compressed points except in the case of ECCurve25519 */
if ((pubKey->u.ec.ecParams.fieldID.type != ec_field_plain) &&
(publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED)) {
crv = CKR_ATTRIBUTE_VALUE_INVALID;
break;
}
+59 -43
View File
@@ -858,7 +858,6 @@ sdb_FindObjectsFinal(SDB *sdb, SDBFind *sdbFind)
return sdb_mapSQLError(sdb_p->type, sqlerr);
}
static const char GET_ATTRIBUTE_CMD[] = "SELECT ALL %s FROM %s WHERE id=$ID;";
CK_RV
sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
CK_ATTRIBUTE *template, CK_ULONG count)
@@ -866,8 +865,6 @@ sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
SDBPrivate *sdb_p = sdb->private;
sqlite3 *sqlDB = NULL;
sqlite3_stmt *stmt = NULL;
char *getStr = NULL;
char *newStr = NULL;
const char *table = NULL;
int sqlerr = SQLITE_OK;
CK_RV error = CKR_OK;
@@ -875,55 +872,74 @@ sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
int retry = 0;
unsigned int i;
if (count == 0) {
error = CKR_OBJECT_HANDLE_INVALID;
goto loser;
}
/* open a new db if necessary */
error = sdb_openDBLocal(sdb_p, &sqlDB, &table);
if (error != CKR_OK) {
goto loser;
}
char *columns = NULL;
for (i = 0; i < count; i++) {
getStr = sqlite3_mprintf("a%x", template[i].type);
if (getStr == NULL) {
char *newColumns;
if (columns) {
newColumns = sqlite3_mprintf("%s, a%x", columns, template[i].type);
sqlite3_free(columns);
columns = NULL;
} else {
newColumns = sqlite3_mprintf("a%x", template[i].type);
}
if (!newColumns) {
error = CKR_HOST_MEMORY;
goto loser;
}
columns = newColumns;
}
if (!columns) {
error = CKR_OBJECT_HANDLE_INVALID;
goto loser;
}
newStr = sqlite3_mprintf(GET_ATTRIBUTE_CMD, getStr, table);
sqlite3_free(getStr);
getStr = NULL;
if (newStr == NULL) {
error = CKR_HOST_MEMORY;
goto loser;
char *statement = sqlite3_mprintf("SELECT DISTINCT %s FROM %s where id=$ID LIMIT 1;",
columns, table);
sqlite3_free(columns);
columns = NULL;
if (!statement) {
error = CKR_HOST_MEMORY;
goto loser;
}
sqlerr = sqlite3_prepare_v2(sqlDB, statement, -1, &stmt, NULL);
sqlite3_free(statement);
statement = NULL;
if (sqlerr != SQLITE_OK) {
goto loser;
}
// NB: indices in sqlite3_bind_int are 1-indexed
sqlerr = sqlite3_bind_int(stmt, 1, object_id);
if (sqlerr != SQLITE_OK) {
goto loser;
}
do {
sqlerr = sqlite3_step(stmt);
if (sqlerr == SQLITE_BUSY) {
PR_Sleep(SDB_BUSY_RETRY_TIME);
}
sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL);
sqlite3_free(newStr);
newStr = NULL;
if (sqlerr == SQLITE_ERROR) {
template[i].ulValueLen = -1;
error = CKR_ATTRIBUTE_TYPE_INVALID;
continue;
} else if (sqlerr != SQLITE_OK) {
goto loser;
}
sqlerr = sqlite3_bind_int(stmt, 1, object_id);
if (sqlerr != SQLITE_OK) {
goto loser;
}
do {
sqlerr = sqlite3_step(stmt);
if (sqlerr == SQLITE_BUSY) {
PR_Sleep(SDB_BUSY_RETRY_TIME);
}
if (sqlerr == SQLITE_ROW) {
if (sqlerr == SQLITE_ROW) {
PORT_Assert(!found);
for (i = 0; i < count; i++) {
unsigned int blobSize;
const char *blobData;
blobSize = sqlite3_column_bytes(stmt, 0);
blobData = sqlite3_column_blob(stmt, 0);
// NB: indices in sqlite_column_{bytes,blob} are 0-indexed
blobSize = sqlite3_column_bytes(stmt, i);
blobData = sqlite3_column_blob(stmt, i);
if (blobData == NULL) {
template[i].ulValueLen = -1;
error = CKR_ATTRIBUTE_TYPE_INVALID;
@@ -945,13 +961,13 @@ sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
PORT_Memcpy(template[i].pValue, blobData, blobSize);
}
template[i].ulValueLen = blobSize;
found = 1;
}
} while (!sdb_done(sqlerr, &retry));
sqlite3_reset(stmt);
sqlite3_finalize(stmt);
stmt = NULL;
}
found = 1;
}
} while (!sdb_done(sqlerr, &retry));
sqlite3_reset(stmt);
sqlite3_finalize(stmt);
stmt = NULL;
loser:
/* fix up the error if necessary */
+96 -157
View File
@@ -859,92 +859,77 @@ static CK_RV
sftk_updateMacs(PLArenaPool *arena, SFTKDBHandle *handle,
CK_OBJECT_HANDLE id, SECItem *newKey)
{
CK_ATTRIBUTE authAttrs[] = {
{ CKA_MODULUS, NULL, 0 },
{ CKA_PUBLIC_EXPONENT, NULL, 0 },
{ CKA_CERT_SHA1_HASH, NULL, 0 },
{ CKA_CERT_MD5_HASH, NULL, 0 },
{ CKA_TRUST_SERVER_AUTH, NULL, 0 },
{ CKA_TRUST_CLIENT_AUTH, NULL, 0 },
{ CKA_TRUST_EMAIL_PROTECTION, NULL, 0 },
{ CKA_TRUST_CODE_SIGNING, NULL, 0 },
{ CKA_TRUST_STEP_UP_APPROVED, NULL, 0 },
{ CKA_NSS_OVERRIDE_EXTENSIONS, NULL, 0 },
};
CK_ULONG authAttrCount = sizeof(authAttrs) / sizeof(CK_ATTRIBUTE);
unsigned int i, count;
SFTKDBHandle *keyHandle = handle;
SDB *keyTarget = NULL;
id &= SFTK_OBJ_ID_MASK;
if (handle->type != SFTK_KEYDB_TYPE) {
keyHandle = handle->peerDB;
}
if (keyHandle == NULL) {
return CKR_OK;
}
/* old DB's don't have meta data, finished with MACs */
// Old DBs don't have metadata, so we can return early here.
keyTarget = SFTK_GET_SDB(keyHandle);
if ((keyTarget->sdb_flags & SDB_HAS_META) == 0) {
return CKR_OK;
}
/*
* STEP 1: find the MACed attributes of this object
*/
(void)sftkdb_GetAttributeValue(handle, id, authAttrs, authAttrCount);
count = 0;
/* allocate space for the attributes */
for (i = 0; i < authAttrCount; i++) {
if ((authAttrs[i].ulValueLen == -1) || (authAttrs[i].ulValueLen == 0)) {
id &= SFTK_OBJ_ID_MASK;
CK_ATTRIBUTE_TYPE authAttrTypes[] = {
CKA_MODULUS,
CKA_PUBLIC_EXPONENT,
CKA_CERT_SHA1_HASH,
CKA_CERT_MD5_HASH,
CKA_TRUST_SERVER_AUTH,
CKA_TRUST_CLIENT_AUTH,
CKA_TRUST_EMAIL_PROTECTION,
CKA_TRUST_CODE_SIGNING,
CKA_TRUST_STEP_UP_APPROVED,
CKA_NSS_OVERRIDE_EXTENSIONS,
};
const CK_ULONG authAttrTypeCount = sizeof(authAttrTypes) / sizeof(authAttrTypes[0]);
// We don't know what attributes this object has, so we update them one at a
// time.
unsigned int i;
for (i = 0; i < authAttrTypeCount; i++) {
CK_ATTRIBUTE authAttr = { authAttrTypes[i], NULL, 0 };
CK_RV rv = sftkdb_GetAttributeValue(handle, id, &authAttr, 1);
if (rv != CKR_OK) {
continue;
}
count++;
authAttrs[i].pValue = PORT_ArenaAlloc(arena, authAttrs[i].ulValueLen);
if (authAttrs[i].pValue == NULL) {
break;
}
}
/* if count was zero, none were found, finished with MACs */
if (count == 0) {
return CKR_OK;
}
(void)sftkdb_GetAttributeValue(handle, id, authAttrs, authAttrCount);
/* ignore error code, we expect some possible errors */
/* GetAttributeValue just verified the old macs, safe to write
* them out then... */
for (i = 0; i < authAttrCount; i++) {
SECItem *signText;
SECItem plainText;
SECStatus rv;
if ((authAttrs[i].ulValueLen == -1) || (authAttrs[i].ulValueLen == 0)) {
if ((authAttr.ulValueLen == -1) || (authAttr.ulValueLen == 0)) {
continue;
}
if (authAttrs[i].ulValueLen == sizeof(CK_ULONG) &&
sftkdb_isULONGAttribute(authAttrs[i].type)) {
CK_ULONG value = *(CK_ULONG *)authAttrs[i].pValue;
sftk_ULong2SDBULong(authAttrs[i].pValue, value);
authAttrs[i].ulValueLen = SDB_ULONG_SIZE;
authAttr.pValue = PORT_ArenaAlloc(arena, authAttr.ulValueLen);
if (authAttr.pValue == NULL) {
return CKR_HOST_MEMORY;
}
plainText.data = authAttrs[i].pValue;
plainText.len = authAttrs[i].ulValueLen;
rv = sftkdb_SignAttribute(arena, newKey, id,
authAttrs[i].type, &plainText, &signText);
if (rv != SECSuccess) {
rv = sftkdb_GetAttributeValue(handle, id, &authAttr, 1);
if (rv != CKR_OK) {
return rv;
}
if ((authAttr.ulValueLen == -1) || (authAttr.ulValueLen == 0)) {
return CKR_GENERAL_ERROR;
}
rv = sftkdb_PutAttributeSignature(handle, keyTarget, id,
authAttrs[i].type, signText);
if (rv != SECSuccess) {
// GetAttributeValue just verified the old macs, so it is safe to write
// them out now.
if (authAttr.ulValueLen == sizeof(CK_ULONG) &&
sftkdb_isULONGAttribute(authAttr.type)) {
CK_ULONG value = *(CK_ULONG *)authAttr.pValue;
sftk_ULong2SDBULong(authAttr.pValue, value);
authAttr.ulValueLen = SDB_ULONG_SIZE;
}
SECItem *signText;
SECItem plainText;
plainText.data = authAttr.pValue;
plainText.len = authAttr.ulValueLen;
if (sftkdb_SignAttribute(arena, newKey, id, authAttr.type, &plainText,
&signText) != SECSuccess) {
return CKR_GENERAL_ERROR;
}
if (sftkdb_PutAttributeSignature(handle, keyTarget, id, authAttr.type,
signText) != SECSuccess) {
return CKR_GENERAL_ERROR;
}
}
@@ -956,110 +941,64 @@ static CK_RV
sftk_updateEncrypted(PLArenaPool *arena, SFTKDBHandle *keydb,
CK_OBJECT_HANDLE id, SECItem *newKey)
{
CK_RV crv = CKR_OK;
CK_RV crv2;
CK_ATTRIBUTE *first, *last;
CK_ATTRIBUTE privAttrs[] = {
{ CKA_VALUE, NULL, 0 },
{ CKA_PRIVATE_EXPONENT, NULL, 0 },
{ CKA_PRIME_1, NULL, 0 },
{ CKA_PRIME_2, NULL, 0 },
{ CKA_EXPONENT_1, NULL, 0 },
{ CKA_EXPONENT_2, NULL, 0 },
{ CKA_COEFFICIENT, NULL, 0 }
CK_ATTRIBUTE_TYPE privAttrTypes[] = {
CKA_VALUE,
CKA_PRIVATE_EXPONENT,
CKA_PRIME_1,
CKA_PRIME_2,
CKA_EXPONENT_1,
CKA_EXPONENT_2,
CKA_COEFFICIENT,
};
CK_ULONG privAttrCount = sizeof(privAttrs) / sizeof(CK_ATTRIBUTE);
unsigned int i, count;
const CK_ULONG privAttrCount = sizeof(privAttrTypes) / sizeof(privAttrTypes[0]);
/*
* STEP 1. Read the old attributes in the clear.
*/
/* Get the attribute sizes.
* ignore the error code, we will have unknown attributes here */
crv2 = sftkdb_GetAttributeValue(keydb, id, privAttrs, privAttrCount);
/*
* find the valid block of attributes and fill allocate space for
* their data */
first = last = NULL;
// We don't know what attributes this object has, so we update them one at a
// time.
unsigned int i;
for (i = 0; i < privAttrCount; i++) {
/* find the block of attributes that are appropriate for this
* objects. There should only be once contiguous block, if not
* there's an error.
*
* find the first and last good entry.
*/
if ((privAttrs[i].ulValueLen == -1) || (privAttrs[i].ulValueLen == 0)) {
if (!first)
continue;
if (!last) {
/* previous entry was last good entry */
last = &privAttrs[i - 1];
}
// Read the old attribute in the clear.
CK_ATTRIBUTE privAttr = { privAttrTypes[i], NULL, 0 };
CK_RV crv = sftkdb_GetAttributeValue(keydb, id, &privAttr, 1);
if (crv != CKR_OK) {
continue;
}
if (!first) {
first = &privAttrs[i];
if ((privAttr.ulValueLen == -1) || (privAttr.ulValueLen == 0)) {
continue;
}
if (last) {
/* OOPS, we've found another good entry beyond the end of the
* last good entry, we need to fail here. */
crv = CKR_GENERAL_ERROR;
break;
privAttr.pValue = PORT_ArenaAlloc(arena, privAttr.ulValueLen);
if (privAttr.pValue == NULL) {
return CKR_HOST_MEMORY;
}
privAttrs[i].pValue = PORT_ArenaAlloc(arena, privAttrs[i].ulValueLen);
if (privAttrs[i].pValue == NULL) {
crv = CKR_HOST_MEMORY;
break;
crv = sftkdb_GetAttributeValue(keydb, id, &privAttr, 1);
if (crv != CKR_OK) {
return crv;
}
}
if (first == NULL) {
/* no valid entries found, return error based on crv2 */
return crv2;
}
if (last == NULL) {
last = &privAttrs[privAttrCount - 1];
}
if (crv != CKR_OK) {
return crv;
}
/* read the attributes */
count = (last - first) + 1;
crv = sftkdb_GetAttributeValue(keydb, id, first, count);
if (crv != CKR_OK) {
return crv;
}
/*
* STEP 2: read the encrypt the attributes with the new key.
*/
for (i = 0; i < count; i++) {
SECItem plainText;
SECItem *result;
SECStatus rv;
plainText.data = first[i].pValue;
plainText.len = first[i].ulValueLen;
rv = sftkdb_EncryptAttribute(arena, newKey, &plainText, &result);
if (rv != SECSuccess) {
if ((privAttr.ulValueLen == -1) || (privAttr.ulValueLen == 0)) {
return CKR_GENERAL_ERROR;
}
first[i].pValue = result->data;
first[i].ulValueLen = result->len;
/* clear our sensitive data out */
SECItem plainText;
SECItem *result;
plainText.data = privAttr.pValue;
plainText.len = privAttr.ulValueLen;
if (sftkdb_EncryptAttribute(arena, newKey, &plainText, &result) != SECSuccess) {
return CKR_GENERAL_ERROR;
}
privAttr.pValue = result->data;
privAttr.ulValueLen = result->len;
// Clear sensitive data.
PORT_Memset(plainText.data, 0, plainText.len);
// Write the newly encrypted attributes out directly.
CK_OBJECT_HANDLE newId = id & SFTK_OBJ_ID_MASK;
keydb->newKey = newKey;
crv = (*keydb->db->sdb_SetAttributeValue)(keydb->db, newId, &privAttr, 1);
keydb->newKey = NULL;
if (crv != CKR_OK) {
return crv;
}
}
/*
* STEP 3: write the newly encrypted attributes out directly
*/
id &= SFTK_OBJ_ID_MASK;
keydb->newKey = newKey;
crv = (*keydb->db->sdb_SetAttributeValue)(keydb->db, id, first, count);
keydb->newKey = NULL;
return crv;
return CKR_OK;
}
static CK_RV
+2 -2
View File
@@ -17,9 +17,9 @@
* The format of the version string should be
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
*/
#define SOFTOKEN_VERSION "3.43" SOFTOKEN_ECC_STRING " Beta"
#define SOFTOKEN_VERSION "3.44" SOFTOKEN_ECC_STRING " Beta"
#define SOFTOKEN_VMAJOR 3
#define SOFTOKEN_VMINOR 43
#define SOFTOKEN_VMINOR 44
#define SOFTOKEN_VPATCH 0
#define SOFTOKEN_VBUILD 0
#define SOFTOKEN_BETA PR_TRUE
+2 -2
View File
@@ -488,7 +488,7 @@ dtls13_HandleAck(sslSocket *ss, sslBuffer *databuf)
* for the holddown period to process retransmitted Finisheds.
*/
if (!ss->sec.isServer && (ss->ssl3.hs.ws == idle_handshake)) {
ssl_CipherSpecReleaseByEpoch(ss, CipherSpecRead,
ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_read,
TrafficKeyHandshake);
}
}
@@ -515,6 +515,6 @@ dtls13_HolddownTimerCb(sslSocket *ss)
{
SSL_TRC(10, ("%d: SSL3[%d]: holddown timer fired",
SSL_GETPID(), ss->fd));
ssl_CipherSpecReleaseByEpoch(ss, CipherSpecRead, TrafficKeyHandshake);
ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_read, TrafficKeyHandshake);
ssl_ClearPRCList(&ss->ssl3.hs.dtlsRcvdHandshake, NULL);
}
-1
View File
@@ -542,7 +542,6 @@ dtls_QueueMessage(sslSocket *ss, SSLContentType ct,
/* Add DTLS handshake message to the pending queue
* Empty the sendBuf buffer.
* This function returns SECSuccess or SECFailure, never SECWouldBlock.
* Always set sendBuf.len to 0, even when returning SECFailure.
*
* Called from:
+1
View File
@@ -55,6 +55,7 @@ CSRCS = \
tls13replay.c \
sslcert.c \
sslgrp.c \
sslprimitive.c \
tls13esni.c \
$(NULL)
+1
View File
@@ -35,6 +35,7 @@
'sslinit.c',
'sslmutex.c',
'sslnonce.c',
'sslprimitive.c',
'sslreveal.c',
'sslsecur.c',
'sslsnce.c',
+11
View File
@@ -299,6 +299,17 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd);
* This is disabled by default and will be removed in a future version. */
#define SSL_ENABLE_V2_COMPATIBLE_HELLO 38
/* Enables the post-handshake authentication in TLS 1.3. If it is set
* to PR_TRUE, the client will send the "post_handshake_auth"
* extension to indicate that it will process CertificateRequest
* messages after handshake.
*
* This option applies only to clients. For a server, the
* SSL_SendCertificateRequest can be used to request post-handshake
* authentication.
*/
#define SSL_ENABLE_POST_HANDSHAKE_AUTH 39
#ifdef SSL_DEPRECATED_FUNCTION
/* Old deprecated function names */
SSL_IMPORT SECStatus SSL_Enable(PRFileDesc *fd, int option, PRIntn on);
+190 -121
View File
@@ -64,6 +64,7 @@ static SECStatus ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags);
static CK_MECHANISM_TYPE ssl3_GetHashMechanismByHashType(SSLHashType hashType);
static CK_MECHANISM_TYPE ssl3_GetMgfMechanismByHashType(SSLHashType hash);
PRBool ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme);
PRBool ssl_IsDsaSignatureScheme(SSLSignatureScheme scheme);
const PRUint8 ssl_hello_retry_random[] = {
0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
@@ -553,10 +554,9 @@ SSL_AtomicIncrementLong(long *x)
}
}
static PRBool
ssl3_CipherSuiteAllowedForVersionRange(
ssl3CipherSuite cipherSuite,
const SSLVersionRange *vrange)
PRBool
ssl3_CipherSuiteAllowedForVersionRange(ssl3CipherSuite cipherSuite,
const SSLVersionRange *vrange)
{
switch (cipherSuite) {
case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
@@ -912,8 +912,8 @@ count_cipher_suites(sslSocket *ss, PRUint8 policy)
* Null compression, mac and encryption functions
*/
SECStatus
Null_Cipher(void *ctx, unsigned char *output, int *outputLen, int maxOutputLen,
const unsigned char *input, int inputLen)
Null_Cipher(void *ctx, unsigned char *output, unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
{
if (inputLen > maxOutputLen) {
*outputLen = 0; /* Match PK11_CipherOp in setting outputLen */
@@ -1394,14 +1394,14 @@ loser:
}
static SECStatus
ssl3_SetupPendingCipherSpec(sslSocket *ss, CipherSpecDirection direction,
ssl3_SetupPendingCipherSpec(sslSocket *ss, SSLSecretDirection direction,
const ssl3CipherSuiteDef *suiteDef,
ssl3CipherSpec **specp)
{
ssl3CipherSpec *spec;
const ssl3CipherSpec *prev;
prev = (direction == CipherSpecWrite) ? ss->ssl3.cwSpec : ss->ssl3.crSpec;
prev = (direction == ssl_secret_write) ? ss->ssl3.cwSpec : ss->ssl3.crSpec;
if (prev->epoch == PR_UINT16_MAX) {
PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
return SECFailure;
@@ -1417,7 +1417,7 @@ ssl3_SetupPendingCipherSpec(sslSocket *ss, CipherSpecDirection direction,
spec->epoch = prev->epoch + 1;
spec->nextSeqNum = 0;
if (IS_DTLS(ss) && direction == CipherSpecRead) {
if (IS_DTLS(ss) && direction == ssl_secret_read) {
dtls_InitRecvdRecords(&spec->recvdRecords);
}
ssl_SetSpecVersions(ss, spec);
@@ -1471,12 +1471,12 @@ ssl3_SetupBothPendingCipherSpecs(sslSocket *ss)
ss->ssl3.hs.kea_def = &kea_defs[kea];
PORT_Assert(ss->ssl3.hs.kea_def->kea == kea);
rv = ssl3_SetupPendingCipherSpec(ss, CipherSpecRead, suiteDef,
rv = ssl3_SetupPendingCipherSpec(ss, ssl_secret_read, suiteDef,
&ss->ssl3.prSpec);
if (rv != SECSuccess) {
goto loser;
}
rv = ssl3_SetupPendingCipherSpec(ss, CipherSpecWrite, suiteDef,
rv = ssl3_SetupPendingCipherSpec(ss, ssl_secret_write, suiteDef,
&ss->ssl3.pwSpec);
if (rv != SECSuccess) {
goto loser;
@@ -1554,15 +1554,15 @@ ssl3_BuildRecordPseudoHeader(DTLSEpoch epoch,
}
static SECStatus
ssl3_AESGCM(ssl3KeyMaterial *keys,
ssl3_AESGCM(const ssl3KeyMaterial *keys,
PRBool doDecrypt,
unsigned char *out,
int *outlen,
int maxout,
unsigned int *outlen,
unsigned int maxout,
const unsigned char *in,
int inlen,
unsigned int inlen,
const unsigned char *additionalData,
int additionalDataLen)
unsigned int additionalDataLen)
{
SECItem param;
SECStatus rv = SECFailure;
@@ -1616,11 +1616,11 @@ ssl3_AESGCM(ssl3KeyMaterial *keys,
}
static SECStatus
ssl3_ChaCha20Poly1305(ssl3KeyMaterial *keys, PRBool doDecrypt,
unsigned char *out, int *outlen, int maxout,
const unsigned char *in, int inlen,
ssl3_ChaCha20Poly1305(const ssl3KeyMaterial *keys, PRBool doDecrypt,
unsigned char *out, unsigned int *outlen, unsigned int maxout,
const unsigned char *in, unsigned int inlen,
const unsigned char *additionalData,
int additionalDataLen)
unsigned int additionalDataLen)
{
size_t i;
SECItem param;
@@ -1727,7 +1727,7 @@ ssl3_InitPendingContexts(sslSocket *ss, ssl3CipherSpec *spec)
spec->cipher = (SSLCipher)PK11_CipherOp;
encMechanism = ssl3_Alg2Mech(calg);
encMode = (spec->direction == CipherSpecWrite) ? CKA_ENCRYPT : CKA_DECRYPT;
encMode = (spec->direction == ssl_secret_write) ? CKA_ENCRYPT : CKA_DECRYPT;
/*
* build the context
@@ -2012,7 +2012,7 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec,
unsigned int ivLen = 0;
unsigned char pseudoHeaderBuf[13];
sslBuffer pseudoHeader = SSL_BUFFER(pseudoHeaderBuf);
int len;
unsigned int len;
if (cwSpec->cipherDef->type == type_block &&
cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
@@ -2130,15 +2130,15 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec,
memmove(SSL_BUFFER_NEXT(wrBuf) + p1Len, pIn + p1Len, oddLen);
}
if (p1Len > 0) {
int cipherBytesPart1 = -1;
unsigned int cipherBytesPart1 = 0;
rv = cwSpec->cipher(cwSpec->cipherContext,
SSL_BUFFER_NEXT(wrBuf), /* output */
&cipherBytesPart1, /* actual outlen */
p1Len, /* max outlen */
pIn,
p1Len); /* input, and inputlen */
PORT_Assert(rv == SECSuccess && cipherBytesPart1 == (int)p1Len);
if (rv != SECSuccess || cipherBytesPart1 != (int)p1Len) {
PORT_Assert(rv == SECSuccess && cipherBytesPart1 == p1Len);
if (rv != SECSuccess || cipherBytesPart1 != p1Len) {
PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
return SECFailure;
}
@@ -2146,15 +2146,15 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec,
PORT_Assert(rv == SECSuccess);
}
if (p2Len > 0) {
int cipherBytesPart2 = -1;
unsigned int cipherBytesPart2 = 0;
rv = cwSpec->cipher(cwSpec->cipherContext,
SSL_BUFFER_NEXT(wrBuf),
&cipherBytesPart2, /* output and actual outLen */
p2Len, /* max outlen */
SSL_BUFFER_NEXT(wrBuf),
p2Len); /* input and inputLen*/
PORT_Assert(rv == SECSuccess && cipherBytesPart2 == (int)p2Len);
if (rv != SECSuccess || cipherBytesPart2 != (int)p2Len) {
PORT_Assert(rv == SECSuccess && cipherBytesPart2 == p2Len);
if (rv != SECSuccess || cipherBytesPart2 != p2Len) {
PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
return SECFailure;
}
@@ -2215,7 +2215,7 @@ ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, SSLContentType ct,
unsigned int lenOffset;
SECStatus rv;
PORT_Assert(cwSpec->direction == CipherSpecWrite);
PORT_Assert(cwSpec->direction == ssl_secret_write);
PORT_Assert(SSL_BUFFER_LEN(wrBuf) == 0);
PORT_Assert(cwSpec->cipherDef->max_records <= RECORD_SEQ_MAX);
@@ -2241,7 +2241,7 @@ ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, SSLContentType ct,
#ifdef UNSAFE_FUZZER_MODE
{
int len;
unsigned int len;
rv = Null_Cipher(NULL, SSL_BUFFER_NEXT(wrBuf), &len,
SSL_BUFFER_SPACE(wrBuf), pIn, contentLen);
if (rv != SECSuccess) {
@@ -2314,8 +2314,8 @@ ssl_ProtectNextRecord(sslSocket *ss, ssl3CipherSpec *spec, SSLContentType ct,
* Returns the number of bytes of plaintext that were successfully sent
* plus the number of bytes of plaintext that were copied into the
* output (write) buffer.
* Returns SECFailure on a hard IO error, memory error, or crypto error.
* Does NOT return SECWouldBlock.
* Returns -1 on an error. PR_WOULD_BLOCK_ERROR is set if the error is blocking
* and not terminal.
*
* Notes on the use of the private ssl flags:
* (no private SSL flags)
@@ -2360,13 +2360,26 @@ ssl3_SendRecord(sslSocket *ss,
* error, so don't overwrite. */
PORT_SetError(SSL_ERROR_HANDSHAKE_FAILED);
}
return SECFailure;
return -1;
}
/* check for Token Presence */
if (!ssl3_ClientAuthTokenPresent(ss->sec.ci.sid)) {
PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);
return SECFailure;
return -1;
}
if (ss->recordWriteCallback) {
PRUint16 epoch;
ssl_GetSpecReadLock(ss);
epoch = ss->ssl3.cwSpec->epoch;
ssl_ReleaseSpecReadLock(ss);
rv = ss->recordWriteCallback(ss->fd, epoch, ct, pIn, nIn,
ss->recordWriteCallbackArg);
if (rv != SECSuccess) {
return -1;
}
return nIn;
}
if (cwSpec) {
@@ -2470,7 +2483,7 @@ loser:
#define SSL3_PENDING_HIGH_WATER 1024
/* Attempt to send the content of "in" in an SSL application_data record.
* Returns "len" or SECFailure, never SECWouldBlock, nor SECSuccess.
* Returns "len" or -1 on failure.
*/
int
ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in,
@@ -2485,21 +2498,21 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in,
PORT_Assert(!(flags & ssl_SEND_FLAG_NO_RETRANSMIT));
if (len < 0 || !in) {
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
return SECFailure;
return -1;
}
if (ss->pendingBuf.len > SSL3_PENDING_HIGH_WATER &&
!ssl_SocketIsBlocking(ss)) {
PORT_Assert(!ssl_SocketIsBlocking(ss));
PORT_SetError(PR_WOULD_BLOCK_ERROR);
return SECFailure;
return -1;
}
if (ss->appDataBuffered && len) {
PORT_Assert(in[0] == (unsigned char)(ss->appDataBuffered));
if (in[0] != (unsigned char)(ss->appDataBuffered)) {
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
return SECFailure;
return -1;
}
in++;
len--;
@@ -2548,7 +2561,7 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in,
PORT_Assert(ss->lastWriteBlocked);
break;
}
return SECFailure; /* error code set by ssl3_SendRecord */
return -1; /* error code set by ssl3_SendRecord */
}
totalSent += sent;
if (ss->pendingBuf.len) {
@@ -2577,7 +2590,6 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in,
}
/* Attempt to send buffered handshake messages.
* This function returns SECSuccess or SECFailure, never SECWouldBlock.
* Always set sendBuf.len to 0, even when returning SECFailure.
*
* Depending on whether we are doing DTLS or not, this either calls
@@ -2600,7 +2612,6 @@ ssl3_FlushHandshake(sslSocket *ss, PRInt32 flags)
}
/* Attempt to send the content of sendBuf buffer in an SSL handshake record.
* This function returns SECSuccess or SECFailure, never SECWouldBlock.
* Always set sendBuf.len to 0, even when returning SECFailure.
*
* Called from ssl3_FlushHandshake
@@ -4309,6 +4320,22 @@ ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme)
return PR_FALSE;
}
PRBool
ssl_IsDsaSignatureScheme(SSLSignatureScheme scheme)
{
switch (scheme) {
case ssl_sig_dsa_sha256:
case ssl_sig_dsa_sha384:
case ssl_sig_dsa_sha512:
case ssl_sig_dsa_sha1:
return PR_TRUE;
default:
return PR_FALSE;
}
return PR_FALSE;
}
SSLAuthType
ssl_SignatureSchemeToAuthType(SSLSignatureScheme scheme)
{
@@ -4956,9 +4983,8 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)
}
}
if (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3 &&
type == client_hello_initial) {
rv = tls13_SetupClientHello(ss);
if (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3) {
rv = tls13_SetupClientHello(ss, type);
if (rv != SECSuccess) {
goto loser;
}
@@ -6021,6 +6047,13 @@ ssl_CanUseSignatureScheme(SSLSignatureScheme scheme,
return PR_FALSE;
}
if (ssl_IsDsaSignatureScheme(scheme) &&
(NSS_GetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, &policy) ==
SECSuccess) &&
!(policy & NSS_USE_ALG_IN_SSL_KX)) {
return PR_FALSE;
}
hashType = ssl_SignatureSchemeToHashType(scheme);
if (requireSha1 && (hashType != ssl_hash_sha1)) {
return PR_FALSE;
@@ -7382,6 +7415,9 @@ ssl3_CompleteHandleCertificateRequest(sslSocket *ss,
if (ss->getClientAuthData != NULL) {
PORT_Assert((ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) ==
ssl_preinfo_all);
PORT_Assert(ss->ssl3.clientPrivateKey == NULL);
PORT_Assert(ss->ssl3.clientCertificate == NULL);
PORT_Assert(ss->ssl3.clientCertChain == NULL);
/* XXX Should pass cert_types and algorithms in this call!! */
rv = (SECStatus)(*ss->getClientAuthData)(ss->getClientAuthDataArg,
ss->fd, ca_list,
@@ -7603,7 +7639,8 @@ ssl3_SendClientSecondRound(sslSocket *ss)
" certificate authentication is still pending.",
SSL_GETPID(), ss->fd));
ss->ssl3.hs.restartTarget = ssl3_SendClientSecondRound;
return SECWouldBlock;
PORT_SetError(PR_WOULD_BLOCK_ERROR);
return SECFailure;
}
ssl_GetXmitBufLock(ss); /*******************************/
@@ -8588,6 +8625,45 @@ loser:
return SECFailure;
}
/* unwrap helper function to handle the case where the wrapKey doesn't wind
* up in the correct token for the master secret */
PK11SymKey *
ssl_unwrapSymKey(PK11SymKey *wrapKey,
CK_MECHANISM_TYPE wrapType, SECItem *param,
SECItem *wrappedKey,
CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
int keySize, CK_FLAGS keyFlags, void *pinArg)
{
PK11SymKey *unwrappedKey;
/* unwrap the master secret. */
unwrappedKey = PK11_UnwrapSymKeyWithFlags(wrapKey, wrapType, param,
wrappedKey, target, operation, keySize,
keyFlags);
if (!unwrappedKey) {
PK11SlotInfo *targetSlot = PK11_GetBestSlot(target, pinArg);
PK11SymKey *newWrapKey;
/* it's possible that we failed to unwrap because the wrapKey is in
* a slot that can't handle target. Move the wrapKey to a slot that
* can handle this mechanism and retry the operation */
if (targetSlot == NULL) {
return NULL;
}
newWrapKey = PK11_MoveSymKey(targetSlot, CKA_UNWRAP, 0,
PR_FALSE, wrapKey);
PK11_FreeSlot(targetSlot);
if (newWrapKey == NULL) {
return NULL;
}
unwrappedKey = PK11_UnwrapSymKeyWithFlags(newWrapKey, wrapType, param,
wrappedKey, target, operation, keySize,
keyFlags);
PK11_FreeSymKey(newWrapKey);
}
return unwrappedKey;
}
static SECStatus
ssl3_UnwrapMasterSecretServer(sslSocket *ss, sslSessionID *sid, PK11SymKey **ms)
{
@@ -8609,12 +8685,14 @@ ssl3_UnwrapMasterSecretServer(sslSocket *ss, sslSessionID *sid, PK11SymKey **ms)
keyFlags = CKF_SIGN | CKF_VERIFY;
}
/* unwrap the master secret. */
*ms = PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech,
NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE,
CKA_DERIVE, SSL3_MASTER_SECRET_LENGTH, keyFlags);
*ms = ssl_unwrapSymKey(wrapKey, sid->u.ssl3.masterWrapMech, NULL,
&wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE,
CKA_DERIVE, SSL3_MASTER_SECRET_LENGTH,
keyFlags, ss->pkcs11PinArg);
PK11_FreeSymKey(wrapKey);
if (!*ms) {
SSL_TRC(10, ("%d: SSL3[%d]: server wrapping key found, but couldn't unwrap MasterSecret. wrapMech=0x%0lx",
SSL_GETPID(), ss->fd, sid->u.ssl3.masterWrapMech));
return SECFailure;
}
return SECSuccess;
@@ -9495,6 +9573,14 @@ ssl3_EncodeSigAlgs(const sslSocket *ss, sslBuffer *buf)
continue;
}
/* Skip DSA scheme if it is disabled by policy. */
if (ssl_IsDsaSignatureScheme(ss->ssl3.signatureSchemes[i]) &&
(NSS_GetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, &policy) ==
SECSuccess) &&
!(policy & NSS_USE_ALG_IN_SSL_KX)) {
continue;
}
if ((NSS_GetAlgorithmPolicy(hashOID, &policy) != SECSuccess) ||
(policy & NSS_USE_ALG_IN_SSL_KX)) {
rv = sslBuffer_AppendNumber(buf, ss->ssl3.signatureSchemes[i], 2);
@@ -10737,6 +10823,9 @@ ssl3_AuthCertificate(sslSocket *ss)
}
}
if (ss->sec.ci.sid->peerCert) {
CERT_DestroyCertificate(ss->sec.ci.sid->peerCert);
}
ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
if (!ss->sec.isServer) {
@@ -10898,13 +10987,6 @@ ssl3_AuthCertificateComplete(sslSocket *ss, PRErrorCode error)
}
rv = target(ss);
/* Even if we blocked here, we have accomplished enough to claim
* success. Any remaining work will be taken care of by subsequent
* calls to SSL_ForceHandshake/PR_Send/PR_Read/etc.
*/
if (rv == SECWouldBlock) {
rv = SECSuccess;
}
} else {
SSL_TRC(3, ("%d: SSL3[%p]: certificate authentication won the race with"
" peer's finished message",
@@ -11445,7 +11527,8 @@ xmit_loser:
}
ss->ssl3.hs.restartTarget = ssl3_FinishHandshake;
return SECWouldBlock;
PORT_SetError(PR_WOULD_BLOCK_ERROR);
return SECFailure;
}
rv = ssl3_FinishHandshake(ss);
@@ -11649,9 +11732,10 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length,
* authenticate the certificate in ssl3_HandleCertificateStatus.
*/
rv = ssl3_AuthCertificate(ss); /* sets ss->ssl3.hs.ws */
PORT_Assert(rv != SECWouldBlock);
if (rv != SECSuccess) {
return rv;
/* This can't block. */
PORT_Assert(PORT_GetError() != PR_WOULD_BLOCK_ERROR);
return SECFailure;
}
}
@@ -11809,28 +11893,17 @@ ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b,
static SECStatus
ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
{
/*
* There may be a partial handshake message already in the handshake
* state. The incoming buffer may contain another portion, or a
* complete message or several messages followed by another portion.
*
* Each message is made contiguous before being passed to the actual
* message parser.
*/
sslBuffer *buf = &ss->ssl3.hs.msgState; /* do not lose the original buffer pointer */
sslBuffer buf = *origBuf; /* Work from a copy. */
SECStatus rv;
PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (buf->buf == NULL) {
*buf = *origBuf;
}
while (buf->len > 0) {
while (buf.len > 0) {
if (ss->ssl3.hs.header_bytes < 4) {
PRUint8 t;
t = *(buf->buf++);
buf->len--;
t = *(buf.buf++);
buf.len--;
if (ss->ssl3.hs.header_bytes++ == 0)
ss->ssl3.hs.msg_type = (SSLHandshakeType)t;
else
@@ -11842,12 +11915,12 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
if (ss->ssl3.hs.msg_len > MAX_HANDSHAKE_MSG_LEN) {
(void)ssl3_DecodeError(ss);
PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
return SECFailure;
goto loser;
}
#undef MAX_HANDSHAKE_MSG_LEN
/* If msg_len is zero, be sure we fall through,
** even if buf->len is zero.
** even if buf.len is zero.
*/
if (ss->ssl3.hs.msg_len > 0)
continue;
@@ -11858,43 +11931,36 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
* data available for this message. If it can be done right out
* of the original buffer, then use it from there.
*/
if (ss->ssl3.hs.msg_body.len == 0 && buf->len >= ss->ssl3.hs.msg_len) {
if (ss->ssl3.hs.msg_body.len == 0 && buf.len >= ss->ssl3.hs.msg_len) {
/* handle it from input buffer */
rv = ssl3_HandleHandshakeMessage(ss, buf->buf, ss->ssl3.hs.msg_len,
buf->len == ss->ssl3.hs.msg_len);
if (rv == SECFailure) {
/* This test wants to fall through on either
* SECSuccess or SECWouldBlock.
* ssl3_HandleHandshakeMessage MUST set the error code.
*/
return rv;
}
buf->buf += ss->ssl3.hs.msg_len;
buf->len -= ss->ssl3.hs.msg_len;
rv = ssl3_HandleHandshakeMessage(ss, buf.buf, ss->ssl3.hs.msg_len,
buf.len == ss->ssl3.hs.msg_len);
buf.buf += ss->ssl3.hs.msg_len;
buf.len -= ss->ssl3.hs.msg_len;
ss->ssl3.hs.msg_len = 0;
ss->ssl3.hs.header_bytes = 0;
if (rv != SECSuccess) { /* return if SECWouldBlock. */
return rv;
if (rv != SECSuccess) {
goto loser;
}
} else {
/* must be copied to msg_body and dealt with from there */
unsigned int bytes;
PORT_Assert(ss->ssl3.hs.msg_body.len < ss->ssl3.hs.msg_len);
bytes = PR_MIN(buf->len, ss->ssl3.hs.msg_len - ss->ssl3.hs.msg_body.len);
bytes = PR_MIN(buf.len, ss->ssl3.hs.msg_len - ss->ssl3.hs.msg_body.len);
/* Grow the buffer if needed */
rv = sslBuffer_Grow(&ss->ssl3.hs.msg_body, ss->ssl3.hs.msg_len);
if (rv != SECSuccess) {
/* sslBuffer_Grow has set a memory error code. */
return SECFailure;
goto loser;
}
PORT_Memcpy(ss->ssl3.hs.msg_body.buf + ss->ssl3.hs.msg_body.len,
buf->buf, bytes);
buf.buf, bytes);
ss->ssl3.hs.msg_body.len += bytes;
buf->buf += bytes;
buf->len -= bytes;
buf.buf += bytes;
buf.len -= bytes;
PORT_Assert(ss->ssl3.hs.msg_body.len <= ss->ssl3.hs.msg_len);
@@ -11902,30 +11968,33 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
if (ss->ssl3.hs.msg_body.len == ss->ssl3.hs.msg_len) {
rv = ssl3_HandleHandshakeMessage(
ss, ss->ssl3.hs.msg_body.buf, ss->ssl3.hs.msg_len,
buf->len == 0);
if (rv == SECFailure) {
/* This test wants to fall through on either
* SECSuccess or SECWouldBlock.
* ssl3_HandleHandshakeMessage MUST set error code.
*/
return rv;
}
buf.len == 0);
ss->ssl3.hs.msg_body.len = 0;
ss->ssl3.hs.msg_len = 0;
ss->ssl3.hs.header_bytes = 0;
if (rv != SECSuccess) { /* return if SECWouldBlock. */
return rv;
if (rv != SECSuccess) {
goto loser;
}
} else {
PORT_Assert(buf->len == 0);
PORT_Assert(buf.len == 0);
break;
}
}
} /* end loop */
origBuf->len = 0; /* So ssl3_GatherAppDataRecord will keep looping. */
buf->buf = NULL; /* not a leak. */
return SECSuccess;
loser : {
/* Make sure to remove any data that was consumed. */
unsigned int consumed = origBuf->len - buf.len;
PORT_Assert(consumed == buf.buf - origBuf->buf);
if (consumed > 0) {
memmove(origBuf->buf, origBuf->buf + consumed, buf.len);
origBuf->len = buf.len;
}
}
return SECFailure;
}
/* These macros return the given value with the MSB copied to all the other
@@ -12183,7 +12252,7 @@ ssl3_UnprotectRecord(sslSocket *ss,
unsigned int hashBytes = MAX_MAC_LENGTH + 1;
SECStatus rv;
PORT_Assert(spec->direction == CipherSpecRead);
PORT_Assert(spec->direction == ssl_secret_read);
good = ~0U;
minLength = spec->macDef->mac_size;
@@ -12213,7 +12282,7 @@ ssl3_UnprotectRecord(sslSocket *ss,
* discard it before decrypting the rest.
*/
PRUint8 iv[MAX_IV_LENGTH];
int decoded;
unsigned int decoded;
ivLen = cipher_def->iv_size;
if (ivLen < 8 || ivLen > sizeof(iv)) {
@@ -12261,12 +12330,12 @@ ssl3_UnprotectRecord(sslSocket *ss,
rType, isTLS, rVersion, IS_DTLS(ss), decryptedLen, &header);
PORT_Assert(rv == SECSuccess);
rv = spec->aead(&spec->keyMaterial,
PR_TRUE, /* do decrypt */
plaintext->buf, /* out */
(int *)&plaintext->len, /* outlen */
plaintext->space, /* maxout */
cText->buf->buf, /* in */
cText->buf->len, /* inlen */
PR_TRUE, /* do decrypt */
plaintext->buf, /* out */
&plaintext->len, /* outlen */
plaintext->space, /* maxout */
cText->buf->buf, /* in */
cText->buf->len, /* inlen */
SSL_BUFFER_BASE(&header), SSL_BUFFER_LEN(&header));
if (rv != SECSuccess) {
good = 0;
@@ -12279,7 +12348,7 @@ ssl3_UnprotectRecord(sslSocket *ss,
/* decrypt from cText buf to plaintext. */
rv = spec->cipher(
spec->cipherContext, plaintext->buf, (int *)&plaintext->len,
spec->cipherContext, plaintext->buf, &plaintext->len,
plaintext->space, cText->buf->buf + ivLen, cText->buf->len - ivLen);
if (rv != SECSuccess) {
goto decrypt_loser;
@@ -12372,7 +12441,7 @@ ssl3_HandleNonApplicationData(sslSocket *ss, SSLContentType rType,
ssl_GetSSL3HandshakeLock(ss);
/* All the functions called in this switch MUST set error code if
** they return SECFailure or SECWouldBlock.
** they return SECFailure.
*/
switch (rType) {
case ssl_ct_change_cipher_spec:
@@ -12429,7 +12498,7 @@ ssl3_GetCipherSpec(sslSocket *ss, SSL3Ciphertext *cText)
}
if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
/* Try to find the cipher spec. */
newSpec = ssl_FindCipherSpecByEpoch(ss, CipherSpecRead,
newSpec = ssl_FindCipherSpecByEpoch(ss, ssl_secret_read,
epoch);
if (newSpec != NULL) {
return newSpec;
@@ -12561,7 +12630,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
rv = SECFailure;
} else {
#ifdef UNSAFE_FUZZER_MODE
rv = Null_Cipher(NULL, plaintext->buf, (int *)&plaintext->len,
rv = Null_Cipher(NULL, plaintext->buf, &plaintext->len,
plaintext->space, cText->buf->buf, cText->buf->len);
#else
/* IMPORTANT: Unprotect functions MUST NOT send alerts
@@ -12694,8 +12763,8 @@ ssl3_InitState(sslSocket *ss)
ssl_GetSpecWriteLock(ss);
PR_INIT_CLIST(&ss->ssl3.hs.cipherSpecs);
rv = ssl_SetupNullCipherSpec(ss, CipherSpecRead);
rv |= ssl_SetupNullCipherSpec(ss, CipherSpecWrite);
rv = ssl_SetupNullCipherSpec(ss, ssl_secret_read);
rv |= ssl_SetupNullCipherSpec(ss, ssl_secret_write);
ss->ssl3.pwSpec = ss->ssl3.prSpec = NULL;
ssl_ReleaseSpecWriteLock(ss);
if (rv != SECSuccess) {
+2
View File
@@ -51,6 +51,7 @@ static const ssl3ExtensionHandler clientHelloHandlers[] = {
{ ssl_tls13_psk_key_exchange_modes_xtn, &tls13_ServerHandlePskModesXtn },
{ ssl_tls13_cookie_xtn, &tls13_ServerHandleCookieXtn },
{ ssl_tls13_encrypted_sni_xtn, &tls13_ServerHandleEsniXtn },
{ ssl_tls13_post_handshake_auth_xtn, &tls13_ServerHandlePostHandshakeAuthXtn },
{ ssl_record_size_limit_xtn, &ssl_HandleRecordSizeLimitXtn },
{ 0, NULL }
};
@@ -138,6 +139,7 @@ static const sslExtensionBuilder clientHelloSendersTLS[] =
{ ssl_tls13_cookie_xtn, &tls13_ClientSendHrrCookieXtn },
{ ssl_tls13_psk_key_exchange_modes_xtn, &tls13_ClientSendPskModesXtn },
{ ssl_tls13_encrypted_sni_xtn, &tls13_ClientSendEsniXtn },
{ ssl_tls13_post_handshake_auth_xtn, &tls13_ClientSendPostHandshakeAuthXtn },
{ ssl_record_size_limit_xtn, &ssl_SendRecordSizeLimitXtn },
/* The pre_shared_key extension MUST be last. */
{ ssl_tls13_pre_shared_key_xtn, &tls13_ClientSendPreSharedKeyXtn },
+1 -1
View File
@@ -1927,7 +1927,7 @@ ssl_HandleRecordSizeLimitXtn(const sslSocket *ss, TLSExtensionData *xtnData,
return SECFailure;
}
if (data->len != 0 || limit < 64) {
ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter);
ssl3_ExtSendAlert(ss, alert_fatal, decode_error);
PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
return SECFailure;
}
+169 -80
View File
@@ -389,7 +389,6 @@ dtls_GatherData(sslSocket *ss, sslGather *gs, int flags)
* application data is available.
* Returns 0 if ssl3_GatherData hits EOF.
* Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error.
* Returns -2 on SECWouldBlock return from ssl3_HandleRecord.
*
* Called from ssl_GatherRecord1stHandshake in sslcon.c,
* and from SSL_ForceHandshake in sslsecur.c
@@ -408,7 +407,7 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
SSL_TRC(3, ("%d: SSL3[%d] Cannot gather data; fatal alert already sent",
SSL_GETPID(), ss->fd));
PORT_SetError(SSL_ERROR_HANDSHAKE_FAILED);
return SECFailure;
return -1;
}
SSL_TRC(30, ("%d: SSL3[%d]: ssl3_GatherCompleteHandshake",
@@ -422,7 +421,6 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
do {
PRBool handleRecordNow = PR_FALSE;
PRBool processingEarlyData;
ssl_GetSSL3HandshakeLock(ss);
@@ -436,96 +434,82 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
if (ss->ssl3.hs.restartTarget) {
ssl_ReleaseSSL3HandshakeLock(ss);
PORT_SetError(PR_WOULD_BLOCK_ERROR);
return (int)SECFailure;
return -1;
}
/* Treat an empty msgState like a NULL msgState. (Most of the time
* when ssl3_HandleHandshake returns SECWouldBlock, it leaves
* behind a non-NULL but zero-length msgState).
* Test: async_cert_restart_server_sends_hello_request_first_in_separate_record
*/
if (ss->ssl3.hs.msgState.buf) {
if (ss->ssl3.hs.msgState.len == 0) {
ss->ssl3.hs.msgState.buf = NULL;
} else {
handleRecordNow = PR_TRUE;
/* If we have a detached record layer, don't ever gather. */
if (ss->recordWriteCallback) {
PRBool done = ss->firstHsDone;
ssl_ReleaseSSL3HandshakeLock(ss);
if (done) {
return 1;
}
PORT_SetError(PR_WOULD_BLOCK_ERROR);
return -1;
}
ssl_ReleaseSSL3HandshakeLock(ss);
if (handleRecordNow) {
/* ssl3_HandleHandshake previously returned SECWouldBlock and the
* as-yet-unprocessed plaintext of that previous handshake record.
* We need to process it now before we overwrite it with the next
* handshake record.
/* State for SSLv2 client hello support. */
ssl2Gather ssl2gs = { PR_FALSE, 0 };
ssl2Gather *ssl2gs_ptr = NULL;
/* If we're a server and waiting for a client hello, accept v2. */
if (ss->sec.isServer && ss->opt.enableV2CompatibleHello &&
ss->ssl3.hs.ws == wait_client_hello) {
ssl2gs_ptr = &ssl2gs;
}
/* bring in the next sslv3 record. */
if (ss->recvdCloseNotify) {
/* RFC 5246 Section 7.2.1:
* Any data received after a closure alert is ignored.
*/
SSL_DBG(("%d: SSL3[%d]: resuming handshake",
SSL_GETPID(), ss->fd));
PORT_Assert(!IS_DTLS(ss));
rv = ssl3_HandleNonApplicationData(ss, ssl_ct_handshake,
0, 0, &ss->gs.buf);
return 0;
}
if (!IS_DTLS(ss)) {
/* If we're a server waiting for a ClientHello then pass
* ssl2gs to support SSLv2 ClientHello messages. */
rv = ssl3_GatherData(ss, &ss->gs, flags, ssl2gs_ptr);
} else {
/* State for SSLv2 client hello support. */
ssl2Gather ssl2gs = { PR_FALSE, 0 };
ssl2Gather *ssl2gs_ptr = NULL;
rv = dtls_GatherData(ss, &ss->gs, flags);
if (ss->sec.isServer && ss->opt.enableV2CompatibleHello &&
ss->ssl3.hs.ws == wait_client_hello) {
ssl2gs_ptr = &ssl2gs;
/* If we got a would block error, that means that no data was
* available, so we check the timer to see if it's time to
* retransmit */
if (rv == SECFailure &&
(PORT_GetError() == PR_WOULD_BLOCK_ERROR)) {
dtls_CheckTimer(ss);
/* Restore the error in case something succeeded */
PORT_SetError(PR_WOULD_BLOCK_ERROR);
}
}
/* bring in the next sslv3 record. */
if (ss->recvdCloseNotify) {
/* RFC 5246 Section 7.2.1:
* Any data received after a closure alert is ignored.
*/
return 0;
}
if (rv <= 0) {
return rv;
}
if (!IS_DTLS(ss)) {
/* Passing a non-NULL ssl2gs here enables detection of
* SSLv2-compatible ClientHello messages. */
rv = ssl3_GatherData(ss, &ss->gs, flags, ssl2gs_ptr);
} else {
rv = dtls_GatherData(ss, &ss->gs, flags);
/* If we got a would block error, that means that no data was
* available, so we check the timer to see if it's time to
* retransmit */
if (rv == SECFailure &&
(PORT_GetError() == PR_WOULD_BLOCK_ERROR)) {
dtls_CheckTimer(ss);
/* Restore the error in case something succeeded */
PORT_SetError(PR_WOULD_BLOCK_ERROR);
}
}
if (rv <= 0) {
if (ssl2gs.isV2) {
rv = ssl3_HandleV2ClientHello(ss, ss->gs.inbuf.buf,
ss->gs.inbuf.len,
ssl2gs.padding);
if (rv < 0) {
return rv;
}
if (ssl2gs.isV2) {
rv = ssl3_HandleV2ClientHello(ss, ss->gs.inbuf.buf,
ss->gs.inbuf.len,
ssl2gs.padding);
if (rv < 0) {
return rv;
}
} else {
/* decipher it, and handle it if it's a handshake.
* If it's application data, ss->gs.buf will not be empty upon return.
* If it's a change cipher spec, alert, or handshake message,
* ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSuccess.
*
* cText only needs to be valid for this next function call, so
* it can borrow gs.hdr.
*/
cText.hdr = ss->gs.hdr;
cText.hdrLen = ss->gs.hdrLen;
cText.buf = &ss->gs.inbuf;
rv = ssl3_HandleRecord(ss, &cText);
}
} else {
/* decipher it, and handle it if it's a handshake.
* If it's application data, ss->gs.buf will not be empty upon return.
* If it's a change cipher spec, alert, or handshake message,
* ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSuccess.
*
* cText only needs to be valid for this next function call, so
* it can borrow gs.hdr.
*/
cText.hdr = ss->gs.hdr;
cText.hdrLen = ss->gs.hdrLen;
cText.buf = &ss->gs.inbuf;
rv = ssl3_HandleRecord(ss, &cText);
}
if (rv < 0) {
return ss->recvdCloseNotify ? 0 : rv;
@@ -575,7 +559,7 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
* delivered to the application before the handshake completes. */
ssl_ReleaseSSL3HandshakeLock(ss);
PORT_SetError(PR_WOULD_BLOCK_ERROR);
return SECWouldBlock;
return -1;
}
ssl_ReleaseSSL3HandshakeLock(ss);
} while (keepGoing);
@@ -596,7 +580,6 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
* Returns 1 when application data is available.
* Returns 0 if ssl3_GatherData hits EOF.
* Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error.
* Returns -2 on SECWouldBlock return from ssl3_HandleRecord.
*
* Called from DoRecv in sslsecur.c
* Caller must hold the recv buf lock.
@@ -616,3 +599,109 @@ ssl3_GatherAppDataRecord(sslSocket *ss, int flags)
return rv;
}
SECStatus
SSLExp_RecordLayerData(PRFileDesc *fd, PRUint16 epoch,
SSLContentType contentType,
const PRUint8 *data, unsigned int len)
{
SECStatus rv;
sslSocket *ss = ssl_FindSocket(fd);
if (!ss) {
return SECFailure;
}
if (IS_DTLS(ss) || data == NULL || len == 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* Run any handshake function. If SSL_RecordLayerData is the only way that
* the handshake is driven, then this is necessary to ensure that
* ssl_BeginClientHandshake or ssl_BeginServerHandshake is called. Note that
* the other function that might be set to ss->handshake,
* ssl3_GatherCompleteHandshake, does nothing when this function is used. */
ssl_Get1stHandshakeLock(ss);
rv = ssl_Do1stHandshake(ss);
if (rv != SECSuccess && PORT_GetError() != PR_WOULD_BLOCK_ERROR) {
goto early_loser; /* Rely on the existing code. */
}
/* Don't allow application data before handshake completion. */
if (contentType == ssl_ct_application_data && !ss->firstHsDone) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
goto early_loser;
}
/* Then we can validate the epoch. */
PRErrorCode epochError;
ssl_GetSpecReadLock(ss);
if (epoch < ss->ssl3.crSpec->epoch) {
epochError = SEC_ERROR_INVALID_ARGS; /* Too c/old. */
} else if (epoch > ss->ssl3.crSpec->epoch) {
epochError = PR_WOULD_BLOCK_ERROR; /* Too warm/new. */
} else {
epochError = 0; /* Just right. */
}
ssl_ReleaseSpecReadLock(ss);
if (epochError) {
PORT_SetError(epochError);
goto early_loser;
}
/* If the handshake is still running, we need to run that. */
ssl_Get1stHandshakeLock(ss);
rv = ssl_Do1stHandshake(ss);
if (rv != SECSuccess && PORT_GetError() != PR_WOULD_BLOCK_ERROR) {
ssl_Release1stHandshakeLock(ss);
return SECFailure;
}
/* Finally, save the data... */
ssl_GetRecvBufLock(ss);
rv = sslBuffer_Append(&ss->gs.buf, data, len);
if (rv != SECSuccess) {
goto loser;
}
/* ...and process it. Just saving application data is enough for it to be
* available to PR_Read(). */
if (contentType != ssl_ct_application_data) {
rv = ssl3_HandleNonApplicationData(ss, contentType, 0, 0, &ss->gs.buf);
/* This occasionally blocks, but that's OK here. */
if (rv != SECSuccess && PORT_GetError() != PR_WOULD_BLOCK_ERROR) {
goto loser;
}
}
ssl_ReleaseRecvBufLock(ss);
ssl_Release1stHandshakeLock(ss);
return SECSuccess;
loser:
/* Make sure that any data is not used again. */
ss->gs.buf.len = 0;
ssl_ReleaseRecvBufLock(ss);
early_loser:
ssl_Release1stHandshakeLock(ss);
return SECFailure;
}
SECStatus
SSLExp_GetCurrentEpoch(PRFileDesc *fd, PRUint16 *readEpoch,
PRUint16 *writeEpoch)
{
sslSocket *ss = ssl_FindSocket(fd);
if (!ss) {
return SECFailure;
}
ssl_GetSpecReadLock(ss);
if (readEpoch) {
*readEpoch = ss->ssl3.crSpec->epoch;
}
if (writeEpoch) {
*writeEpoch = ss->ssl3.cwSpec->epoch;
}
ssl_ReleaseSpecReadLock(ss);
return SECSuccess;
}
+5 -11
View File
@@ -44,17 +44,13 @@ const char *ssl_version = "SECURITY_VERSION:"
* This function acquires and releases the RecvBufLock.
*
* returns SECSuccess for success.
* returns SECWouldBlock when that value is returned by
* ssl3_GatherCompleteHandshake().
* returns SECFailure on all other errors.
* returns SECFailure on error, setting PR_WOULD_BLOCK_ERROR if only blocked.
*
* The gather functions called by ssl_GatherRecord1stHandshake are expected
* to return values interpreted as follows:
* 1 : the function completed without error.
* 0 : the function read EOF.
* -1 : read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error.
* -2 : the function wants ssl_GatherRecord1stHandshake to be called again
* immediately, by ssl_Do1stHandshake.
*
* This code is similar to, and easily confused with, DoRecv() in sslsecur.c
*
@@ -82,16 +78,14 @@ ssl_GatherRecord1stHandshake(sslSocket *ss)
ssl_ReleaseRecvBufLock(ss);
if (rv <= 0) {
if (rv == SECWouldBlock) {
/* Progress is blocked waiting for callback completion. */
SSL_TRC(10, ("%d: SSL[%d]: handshake blocked (need %d)",
SSL_GETPID(), ss->fd, ss->gs.remainder));
return SECWouldBlock;
}
if (rv == 0) {
/* EOF. Loser */
PORT_SetError(PR_END_OF_FILE_ERROR);
}
if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) {
SSL_TRC(10, ("%d: SSL[%d]: handshake blocked (need %d)",
SSL_GETPID(), ss->fd, ss->gs.remainder));
}
return SECFailure; /* rv is < 0 here. */
}
+1 -1
View File
@@ -84,7 +84,7 @@ ssl_DefRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
* For blocking sockets, always returns len or SECFailure, no short writes.
* For non-blocking sockets:
* Returns positive count if any data was written, else returns SECFailure.
* Short writes may occur. Does not return SECWouldBlock.
* Short writes may occur.
*/
int
ssl_DefSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
+1
View File
@@ -268,6 +268,7 @@ typedef enum {
SSL_ERROR_RX_MALFORMED_ESNI_EXTENSION = (SSL_ERROR_BASE + 177),
SSL_ERROR_MISSING_ESNI_EXTENSION = (SSL_ERROR_BASE + 178),
SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE = (SSL_ERROR_BASE + 179),
SSL_ERROR_MISSING_POST_HANDSHAKE_AUTH_EXTENSION = (SSL_ERROR_BASE + 180),
SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */
} SSLErrorCodes;
#endif /* NO_SECURITY_ERROR_ENUM */
+212
View File
@@ -350,6 +350,27 @@ typedef SSLHelloRetryRequestAction(PR_CALLBACK *SSLHelloRetryRequestCallback)(
(PRFileDesc * _fd, PRBool _requestUpdate), \
(fd, requestUpdate))
/* This function allows a server application to trigger
* re-authentication (TLS 1.3 only) after handshake.
*
* This function will cause a CertificateRequest message to be sent by
* a server. This can be called once at a time, and is not allowed
* until an answer is received.
*
* The AuthCertificateCallback is called when the answer is received.
* If the answer is accepted by the server, the value returned by
* SSL_PeerCertificate() is replaced. If you need to remember all the
* certificates, you will need to call SSL_PeerCertificate() and save
* what you get before calling this.
*
* If the AuthCertificateCallback returns SECFailure, the connection
* is aborted.
*/
#define SSL_SendCertificateRequest(fd) \
SSL_EXPERIMENTAL_API("SSL_SendCertificateRequest", \
(PRFileDesc * _fd), \
(fd))
/*
* Session cache API.
*/
@@ -511,6 +532,197 @@ typedef SECStatus(PR_CALLBACK *SSLResumptionTokenCallback)(
group, pubKey, pad, notBefore, notAfter, \
out, outlen, maxlen))
/* SSL_SetSecretCallback installs a callback that TLS calls when it installs new
* traffic secrets.
*
* SSLSecretCallback is called with the current epoch and the corresponding
* secret; this matches the epoch used in DTLS 1.3, even if the socket is
* operating in stream mode:
*
* - client_early_traffic_secret corresponds to epoch 1
* - {client|server}_handshake_traffic_secret is epoch 2
* - {client|server}_application_traffic_secret_{N} is epoch 3+N
*
* The callback is invoked separately for read secrets (client secrets on the
* server; server secrets on the client), and write secrets.
*
* This callback is only called if (D)TLS 1.3 is negotiated.
*/
typedef void(PR_CALLBACK *SSLSecretCallback)(
PRFileDesc *fd, PRUint16 epoch, SSLSecretDirection dir, PK11SymKey *secret,
void *arg);
#define SSL_SecretCallback(fd, cb, arg) \
SSL_EXPERIMENTAL_API("SSL_SecretCallback", \
(PRFileDesc * _fd, SSLSecretCallback _cb, void *_arg), \
(fd, cb, arg))
/* SSL_RecordLayerWriteCallback() is used to replace the TLS record layer. This
* function installs a callback that TLS calls when it would otherwise encrypt
* and write a record to the underlying NSPR IO layer. The application is
* responsible for ensuring that these records are encrypted and written.
*
* Calling this API also disables reads from the underlying NSPR layer. The
* application is expected to push data when it is available using
* SSL_RecordLayerData().
*
* When data would be written, the provided SSLRecordWriteCallback with the
* epoch, TLS content type, and the data. The data provided to the callback is
* not split into record-sized writes. If the callback returns SECFailure, the
* write will be considered to have failed; in particular, PR_WOULD_BLOCK_ERROR
* is not handled specially.
*
* If TLS 1.3 is in use, the epoch indicates the expected level of protection
* that the record would receive, this matches that used in DTLS 1.3:
*
* - epoch 0 corresponds to no record protection
* - epoch 1 corresponds to 0-RTT
* - epoch 2 corresponds to TLS handshake
* - epoch 3 and higher are application data
*
* Prior versions of TLS use epoch 1 and higher for application data.
*
* This API is not supported for DTLS.
*/
typedef SECStatus(PR_CALLBACK *SSLRecordWriteCallback)(
PRFileDesc *fd, PRUint16 epoch, SSLContentType contentType,
const PRUint8 *data, unsigned int len, void *arg);
#define SSL_RecordLayerWriteCallback(fd, writeCb, arg) \
SSL_EXPERIMENTAL_API("SSL_RecordLayerWriteCallback", \
(PRFileDesc * _fd, SSLRecordWriteCallback _wCb, \
void *_arg), \
(fd, writeCb, arg))
/* SSL_RecordLayerData() is used to provide new data to TLS. The application
* indicates the epoch (see the description of SSL_RecordLayerWriteCallback()),
* content type, and the data that was received. The application is responsible
* for removing any encryption or other protection before passing data to this
* function.
*
* This returns SECSuccess if the data was successfully processed. If this
* function is used to drive the handshake and the caller needs to know when the
* handshake is complete, a call to SSL_ForceHandshake will return SECSuccess
* when the handshake is complete.
*
* This API is not supported for DTLS sockets.
*/
#define SSL_RecordLayerData(fd, epoch, ct, data, len) \
SSL_EXPERIMENTAL_API("SSL_RecordLayerData", \
(PRFileDesc * _fd, PRUint16 _epoch, \
SSLContentType _contentType, \
const PRUint8 *_data, unsigned int _len), \
(fd, epoch, ct, data, len))
/*
* SSL_GetCurrentEpoch() returns the read and write epochs that the socket is
* currently using. NULL values for readEpoch or writeEpoch are ignored.
*
* See SSL_RecordLayerWriteCallback() for details on epochs.
*/
#define SSL_GetCurrentEpoch(fd, readEpoch, writeEpoch) \
SSL_EXPERIMENTAL_API("SSL_GetCurrentEpoch", \
(PRFileDesc * _fd, PRUint16 * _readEpoch, \
PRUint16 * _writeEpoch), \
(fd, readEpoch, writeEpoch))
/*
* The following AEAD functions expose an AEAD primitive that uses a ciphersuite
* to set parameters. The ciphersuite determines the Hash function used by
* HKDF, the AEAD function, and the size of key and IV. This is only supported
* for TLS 1.3.
*
* The key and IV are generated using the TLS KDF with a custom label. That is
* HKDF-Expand-Label(secret, labelPrefix + " key" or " iv", "", L).
*
* The encrypt and decrypt functions use a nonce construction identical to that
* used in TLS. The lower bits of the IV are XORed with the 64-bit counter to
* produce the nonce. Otherwise, this is an AEAD interface similar to that
* described in RFC 5116.
*/
typedef struct SSLAeadContextStr SSLAeadContext;
#define SSL_MakeAead(version, cipherSuite, secret, \
labelPrefix, labelPrefixLen, ctx) \
SSL_EXPERIMENTAL_API("SSL_MakeAead", \
(PRUint16 _version, PRUint16 _cipherSuite, \
PK11SymKey * _secret, \
const char *_labelPrefix, \
unsigned int _labelPrefixLen, \
SSLAeadContext **_ctx), \
(version, cipherSuite, secret, \
labelPrefix, labelPrefixLen, ctx))
#define SSL_AeadEncrypt(ctx, counter, aad, aadLen, in, inLen, \
output, outputLen, maxOutputLen) \
SSL_EXPERIMENTAL_API("SSL_AeadEncrypt", \
(const SSLAeadContext *_ctx, PRUint64 _counter, \
const PRUint8 *_aad, unsigned int _aadLen, \
const PRUint8 *_in, unsigned int _inLen, \
PRUint8 *_out, unsigned int *_outLen, \
unsigned int _maxOut), \
(ctx, counter, aad, aadLen, in, inLen, \
output, outputLen, maxOutputLen))
#define SSL_AeadDecrypt(ctx, counter, aad, aadLen, in, inLen, \
output, outputLen, maxOutputLen) \
SSL_EXPERIMENTAL_API("SSL_AeadDecrypt", \
(const SSLAeadContext *_ctx, PRUint64 _counter, \
const PRUint8 *_aad, unsigned int _aadLen, \
const PRUint8 *_in, unsigned int _inLen, \
PRUint8 *_output, unsigned int *_outLen, \
unsigned int _maxOut), \
(ctx, counter, aad, aadLen, in, inLen, \
output, outputLen, maxOutputLen))
#define SSL_DestroyAead(ctx) \
SSL_EXPERIMENTAL_API("SSL_DestroyAead", \
(SSLAeadContext * _ctx), \
(ctx))
/* SSL_HkdfExtract and SSL_HkdfExpandLabel implement the functions from TLS,
* using the version and ciphersuite to set parameters. This allows callers to
* use these TLS functions as a KDF. This is only supported for TLS 1.3.
*
* SSL_HkdfExtract produces a key with a mechanism that is suitable for input to
* SSL_HkdfExpandLabel (and SSL_HkdfExpandLabelWithMech). */
#define SSL_HkdfExtract(version, cipherSuite, salt, ikm, keyp) \
SSL_EXPERIMENTAL_API("SSL_HkdfExtract", \
(PRUint16 _version, PRUint16 _cipherSuite, \
PK11SymKey * _salt, PK11SymKey * _ikm, \
PK11SymKey * *_keyp), \
(version, cipherSuite, salt, ikm, keyp))
/* SSL_HkdfExpandLabel produces a key with a mechanism that is suitable for
* input to SSL_HkdfExpandLabel or SSL_MakeAead. */
#define SSL_HkdfExpandLabel(version, cipherSuite, prk, \
hsHash, hsHashLen, label, labelLen, keyp) \
SSL_EXPERIMENTAL_API("SSL_HkdfExpandLabel", \
(PRUint16 _version, PRUint16 _cipherSuite, \
PK11SymKey * _prk, \
const PRUint8 *_hsHash, unsigned int _hsHashLen, \
const char *_label, unsigned int _labelLen, \
PK11SymKey **_keyp), \
(version, cipherSuite, prk, \
hsHash, hsHashLen, label, labelLen, keyp))
/* SSL_HkdfExpandLabelWithMech uses the KDF from the selected TLS version and
* cipher suite, as with the other calls, but the provided mechanism and key
* size. This allows the key to be used more widely. */
#define SSL_HkdfExpandLabelWithMech(version, cipherSuite, prk, \
hsHash, hsHashLen, label, labelLen, \
mech, keySize, keyp) \
SSL_EXPERIMENTAL_API("SSL_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), \
(version, cipherSuite, prk, \
hsHash, hsHashLen, label, labelLen, \
mech, keySize, keyp))
/* Deprecated experimental APIs */
#define SSL_UseAltServerHelloType(fd, enable) SSL_DEPRECATED_EXPERIMENTAL_API
+60 -10
View File
@@ -272,6 +272,7 @@ typedef struct sslOptionsStr {
unsigned int enableDtlsShortHeader : 1;
unsigned int enableHelloDowngradeCheck : 1;
unsigned int enableV2CompatibleHello : 1;
unsigned int enablePostHandshakeAuth : 1;
} sslOptions;
typedef enum { sslHandshakingUndetermined = 0,
@@ -622,8 +623,6 @@ typedef struct SSL3HandshakeStateStr {
unsigned long msg_len;
PRBool isResuming; /* we are resuming (not used in TLS 1.3) */
PRBool sendingSCSV; /* instead of empty RI */
sslBuffer msgState; /* current state for handshake messages*/
/* protected by recvBufLock */
/* The session ticket received in a NewSessionTicket message is temporarily
* stored in newSessionTicket until the handshake is finished; then it is
@@ -744,10 +743,10 @@ struct ssl3StateStr {
* update is initiated locally. */
PRBool peerRequestedKeyUpdate;
/* Internal callback for when we do a cipher suite change. Used for
* debugging in TLS 1.3. This can only be set by non-public functions. */
sslCipherSpecChangedFunc changedCipherSpecFunc;
void *changedCipherSpecArg;
/* This is true after the server requests client certificate;
* false after the client certificate is received. Used by the
* server. */
PRBool clientCertRequested;
CERTCertificate *clientCertificate; /* used by client */
SECKEYPrivateKey *clientPrivateKey; /* used by client */
@@ -994,6 +993,10 @@ struct sslSocketStr {
PRCList extensionHooks;
SSLResumptionTokenCallback resumptionTokenCallback;
void *resumptionTokenContext;
SSLSecretCallback secretCallback;
void *secretCallbackArg;
SSLRecordWriteCallback recordWriteCallback;
void *recordWriteCallbackArg;
PRIntervalTime rTimeout; /* timeout for NSPR I/O */
PRIntervalTime wTimeout; /* timeout for NSPR I/O */
@@ -1174,7 +1177,7 @@ extern SECStatus ssl_SaveWriteData(sslSocket *ss,
const void *p, unsigned int l);
extern SECStatus ssl_BeginClientHandshake(sslSocket *ss);
extern SECStatus ssl_BeginServerHandshake(sslSocket *ss);
extern int ssl_Do1stHandshake(sslSocket *ss);
extern SECStatus ssl_Do1stHandshake(sslSocket *ss);
extern SECStatus ssl3_InitPendingCipherSpecs(sslSocket *ss, PK11SymKey *secret,
PRBool derive);
@@ -1206,9 +1209,9 @@ extern SECStatus ssl_CipherPrefSetDefault(PRInt32 which, PRBool enabled);
extern SECStatus ssl3_ConstrainRangeByPolicy(void);
extern SECStatus ssl3_InitState(sslSocket *ss);
extern SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen,
int maxOutputLen, const unsigned char *input,
int inputLen);
extern SECStatus Null_Cipher(void *ctx, unsigned char *output, unsigned int *outputLen,
unsigned int maxOutputLen, const unsigned char *input,
unsigned int inputLen);
extern void ssl3_RestartHandshakeHashes(sslSocket *ss);
extern SECStatus ssl3_UpdateHandshakeHashes(sslSocket *ss,
const unsigned char *b,
@@ -1660,6 +1663,8 @@ SECStatus ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid,
const ssl3CipherSuiteDef *ssl_LookupCipherSuiteDef(ssl3CipherSuite suite);
const ssl3CipherSuiteCfg *ssl_LookupCipherSuiteCfg(ssl3CipherSuite suite,
const ssl3CipherSuiteCfg *suites);
PRBool ssl3_CipherSuiteAllowedForVersionRange(ssl3CipherSuite cipherSuite,
const SSLVersionRange *vrange);
SECStatus ssl3_SelectServerCert(sslSocket *ss);
SECStatus ssl_PickSignatureScheme(sslSocket *ss,
@@ -1729,6 +1734,14 @@ SECStatus ssl_DecodeResumptionToken(sslSessionID *sid, const PRUint8 *encodedTic
PRUint32 encodedTicketLen);
PRBool ssl_IsResumptionTokenUsable(sslSocket *ss, sslSessionID *sid);
/* unwrap helper function to handle the case where the wrapKey doesn't wind
* * up in the correct token for the master secret */
PK11SymKey *ssl_unwrapSymKey(PK11SymKey *wrapKey,
CK_MECHANISM_TYPE wrapType, SECItem *param,
SECItem *wrappedKey,
CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
int keySize, CK_FLAGS keyFlags, void *pinArg);
/* Remove when stable. */
SECStatus SSLExp_SetResumptionTokenCallback(PRFileDesc *fd,
@@ -1742,8 +1755,45 @@ SECStatus SSLExp_GetResumptionTokenInfo(const PRUint8 *tokenData, unsigned int t
SECStatus SSLExp_DestroyResumptionTokenInfo(SSLResumptionTokenInfo *token);
SECStatus SSLExp_SecretCallback(PRFileDesc *fd, SSLSecretCallback cb,
void *arg);
SECStatus SSLExp_RecordLayerWriteCallback(PRFileDesc *fd,
SSLRecordWriteCallback write,
void *arg);
SECStatus SSLExp_RecordLayerData(PRFileDesc *fd, PRUint16 epoch,
SSLContentType contentType,
const PRUint8 *data, unsigned int len);
SECStatus SSLExp_GetCurrentEpoch(PRFileDesc *fd, PRUint16 *readEpoch,
PRUint16 *writeEpoch);
#define SSLResumptionTokenVersion 2
SECStatus SSLExp_MakeAead(PRUint16 version, PRUint16 cipherSuite, PK11SymKey *secret,
const char *labelPrefix, unsigned int labelPrefixLen,
SSLAeadContext **ctx);
SECStatus SSLExp_DestroyAead(SSLAeadContext *ctx);
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);
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);
SECStatus SSLExp_HkdfExtract(PRUint16 version, PRUint16 cipherSuite,
PK11SymKey *salt, PK11SymKey *ikm, PK11SymKey **keyp);
SECStatus SSLExp_HkdfExpandLabel(PRUint16 version, PRUint16 cipherSuite, PK11SymKey *prk,
const PRUint8 *hsHash, unsigned int hsHashLen,
const char *label, unsigned int labelLen,
PK11SymKey **key);
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);
SEC_END_PROTOS
#if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS)
+72 -71
View File
@@ -150,6 +150,7 @@ SSL_GetPreliminaryChannelInfo(PRFileDesc *fd,
} else {
inf.maxEarlyDataSize = 0;
}
inf.zeroRttCipherSuite = ss->ssl3.hs.zeroRttSuite;
memcpy(info, &inf, inf.length);
return SECSuccess;
@@ -234,89 +235,89 @@ SSL_GetPreliminaryChannelInfo(PRFileDesc *fd,
static const SSLCipherSuiteInfo suiteInfo[] = {
/* <------ Cipher suite --------------------> <auth> <KEA> <bulk cipher> <MAC> <FIPS> */
{ 0, CS_(TLS_AES_128_GCM_SHA256), S_ANY, K_ANY, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_ANY },
{ 0, CS_(TLS_CHACHA20_POLY1305_SHA256), S_ANY, K_ANY, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_ANY },
{ 0, CS_(TLS_AES_256_GCM_SHA384), S_ANY, K_ANY, C_AESGCM, B_256, M_AEAD_128, F_NFIPS_STD, A_ANY },
{ 0, CS_(TLS_AES_128_GCM_SHA256), S_ANY, K_ANY, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_ANY, ssl_hash_sha256 },
{ 0, CS_(TLS_CHACHA20_POLY1305_SHA256), S_ANY, K_ANY, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_ANY, ssl_hash_sha256 },
{ 0, CS_(TLS_AES_256_GCM_SHA384), S_ANY, K_ANY, C_AESGCM, B_256, M_AEAD_128, F_NFIPS_STD, A_ANY, ssl_hash_sha384 },
{ 0, CS(RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_RSA, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_RSAD },
{ 0, CS(DHE_RSA_WITH_CHACHA20_POLY1305_SHA256), S_RSA, K_DHE, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_RSAS },
{ 0, CS(RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_RSA, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_RSAD, ssl_hash_sha256 },
{ 0, CS(DHE_RSA_WITH_CHACHA20_POLY1305_SHA256), S_RSA, K_DHE, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_RSAS, ssl_hash_sha256 },
{ 0, CS(DHE_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_256, M_SHA, F_NFIPS_STD, A_RSAS },
{ 0, CS(DHE_DSS_WITH_CAMELLIA_256_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_256, M_SHA, F_NFIPS_STD, A_DSA },
{ 0, CS(DHE_RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_DHE, C_AES, B_256, M_SHA256, F_FIPS_STD, A_RSAS },
{ 0, CS(DHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_DHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_RSAS },
{ 0, CS(DHE_DSS_WITH_AES_256_CBC_SHA), S_DSA, K_DHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_DSA },
{ 0, CS(DHE_DSS_WITH_AES_256_CBC_SHA256), S_DSA, K_DHE, C_AES, B_256, M_SHA256, F_FIPS_STD, A_DSA },
{ 0, CS(RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_256, M_SHA, F_NFIPS_STD, A_RSAD },
{ 0, CS(RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_RSA, C_AES, B_256, M_SHA256, F_FIPS_STD, A_RSAD },
{ 0, CS(RSA_WITH_AES_256_CBC_SHA), S_RSA, K_RSA, C_AES, B_256, M_SHA, F_FIPS_STD, A_RSAD },
{ 0, CS(DHE_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_256, M_SHA, F_NFIPS_STD, A_RSAS, ssl_hash_none },
{ 0, CS(DHE_DSS_WITH_CAMELLIA_256_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_256, M_SHA, F_NFIPS_STD, A_DSA, ssl_hash_none },
{ 0, CS(DHE_RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_DHE, C_AES, B_256, M_SHA256, F_FIPS_STD, A_RSAS, ssl_hash_sha256 },
{ 0, CS(DHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_DHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_RSAS, ssl_hash_none },
{ 0, CS(DHE_DSS_WITH_AES_256_CBC_SHA), S_DSA, K_DHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_DSA, ssl_hash_none },
{ 0, CS(DHE_DSS_WITH_AES_256_CBC_SHA256), S_DSA, K_DHE, C_AES, B_256, M_SHA256, F_FIPS_STD, A_DSA, ssl_hash_sha256 },
{ 0, CS(RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_256, M_SHA, F_NFIPS_STD, A_RSAD, ssl_hash_none },
{ 0, CS(RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_RSA, C_AES, B_256, M_SHA256, F_FIPS_STD, A_RSAD, ssl_hash_sha256 },
{ 0, CS(RSA_WITH_AES_256_CBC_SHA), S_RSA, K_RSA, C_AES, B_256, M_SHA, F_FIPS_STD, A_RSAD, ssl_hash_none },
{ 0, CS(DHE_RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_128, M_SHA, F_NFIPS_STD, A_RSAS },
{ 0, CS(DHE_DSS_WITH_CAMELLIA_128_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_128, M_SHA, F_NFIPS_STD, A_DSA },
{ 0, CS(DHE_DSS_WITH_RC4_128_SHA), S_DSA, K_DHE, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_DSA },
{ 0, CS(DHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_DHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_RSAS },
{ 0, CS(DHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_RSAS },
{ 0, CS(DHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_DHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_RSAS },
{ 0, CS(DHE_DSS_WITH_AES_128_GCM_SHA256), S_DSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_DSA },
{ 0, CS(DHE_DSS_WITH_AES_128_CBC_SHA), S_DSA, K_DHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_DSA },
{ 0, CS(DHE_DSS_WITH_AES_128_CBC_SHA256), S_DSA, K_DHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_DSA },
{ 0, CS(RSA_WITH_SEED_CBC_SHA), S_RSA, K_RSA, C_SEED, B_128, M_SHA, F_FIPS_STD, A_RSAD },
{ 0, CS(RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_128, M_SHA, F_NFIPS_STD, A_RSAD },
{ 0, CS(RSA_WITH_RC4_128_SHA), S_RSA, K_RSA, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_RSAD },
{ 0, CS(RSA_WITH_RC4_128_MD5), S_RSA, K_RSA, C_RC4, B_128, M_MD5, F_NFIPS_STD, A_RSAD },
{ 0, CS(RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_RSA, C_AES, B_128, M_SHA256, F_FIPS_STD, A_RSAD },
{ 0, CS(RSA_WITH_AES_128_CBC_SHA), S_RSA, K_RSA, C_AES, B_128, M_SHA, F_FIPS_STD, A_RSAD },
{ 0, CS(DHE_RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_128, M_SHA, F_NFIPS_STD, A_RSAS, ssl_hash_none },
{ 0, CS(DHE_DSS_WITH_CAMELLIA_128_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_128, M_SHA, F_NFIPS_STD, A_DSA, ssl_hash_none },
{ 0, CS(DHE_DSS_WITH_RC4_128_SHA), S_DSA, K_DHE, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_DSA, ssl_hash_none },
{ 0, CS(DHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_DHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_RSAS, ssl_hash_sha256 },
{ 0, CS(DHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_RSAS, ssl_hash_sha256 },
{ 0, CS(DHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_DHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_RSAS, ssl_hash_none },
{ 0, CS(DHE_DSS_WITH_AES_128_GCM_SHA256), S_DSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_DSA, ssl_hash_sha256 },
{ 0, CS(DHE_DSS_WITH_AES_128_CBC_SHA), S_DSA, K_DHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_DSA, ssl_hash_none },
{ 0, CS(DHE_DSS_WITH_AES_128_CBC_SHA256), S_DSA, K_DHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_DSA, ssl_hash_sha256 },
{ 0, CS(RSA_WITH_SEED_CBC_SHA), S_RSA, K_RSA, C_SEED, B_128, M_SHA, F_FIPS_STD, A_RSAD, ssl_hash_none },
{ 0, CS(RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_128, M_SHA, F_NFIPS_STD, A_RSAD, ssl_hash_none },
{ 0, CS(RSA_WITH_RC4_128_SHA), S_RSA, K_RSA, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_RSAD, ssl_hash_none },
{ 0, CS(RSA_WITH_RC4_128_MD5), S_RSA, K_RSA, C_RC4, B_128, M_MD5, F_NFIPS_STD, A_RSAD, ssl_hash_none },
{ 0, CS(RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_RSA, C_AES, B_128, M_SHA256, F_FIPS_STD, A_RSAD, ssl_hash_sha256 },
{ 0, CS(RSA_WITH_AES_128_CBC_SHA), S_RSA, K_RSA, C_AES, B_128, M_SHA, F_FIPS_STD, A_RSAD, ssl_hash_none },
{ 0, CS(DHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_DHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_RSAS },
{ 0, CS(DHE_DSS_WITH_3DES_EDE_CBC_SHA), S_DSA, K_DHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_DSA },
{ 0, CS(RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_RSA, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_RSAD },
{ 0, CS(DHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_DHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_RSAS, ssl_hash_none },
{ 0, CS(DHE_DSS_WITH_3DES_EDE_CBC_SHA), S_DSA, K_DHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_DSA, ssl_hash_none },
{ 0, CS(RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_RSA, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_RSAD, ssl_hash_none },
{ 0, CS(DHE_RSA_WITH_DES_CBC_SHA), S_RSA, K_DHE, C_DES, B_DES, M_SHA, F_NFIPS_STD, A_RSAS },
{ 0, CS(DHE_DSS_WITH_DES_CBC_SHA), S_DSA, K_DHE, C_DES, B_DES, M_SHA, F_NFIPS_STD, A_DSA },
{ 0, CS(RSA_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, F_NFIPS_STD, A_RSAD },
{ 0, CS(DHE_RSA_WITH_DES_CBC_SHA), S_RSA, K_DHE, C_DES, B_DES, M_SHA, F_NFIPS_STD, A_RSAS, ssl_hash_none },
{ 0, CS(DHE_DSS_WITH_DES_CBC_SHA), S_DSA, K_DHE, C_DES, B_DES, M_SHA, F_NFIPS_STD, A_DSA, ssl_hash_none },
{ 0, CS(RSA_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, F_NFIPS_STD, A_RSAD, ssl_hash_none },
{ 0, CS(RSA_WITH_NULL_SHA256), S_RSA, K_RSA, C_NULL, B_0, M_SHA256, F_EXPORT, A_RSAD },
{ 0, CS(RSA_WITH_NULL_SHA), S_RSA, K_RSA, C_NULL, B_0, M_SHA, F_EXPORT, A_RSAD },
{ 0, CS(RSA_WITH_NULL_MD5), S_RSA, K_RSA, C_NULL, B_0, M_MD5, F_EXPORT, A_RSAD },
{ 0, CS(RSA_WITH_NULL_SHA256), S_RSA, K_RSA, C_NULL, B_0, M_SHA256, F_EXPORT, A_RSAD, ssl_hash_sha256 },
{ 0, CS(RSA_WITH_NULL_SHA), S_RSA, K_RSA, C_NULL, B_0, M_SHA, F_EXPORT, A_RSAD, ssl_hash_none },
{ 0, CS(RSA_WITH_NULL_MD5), S_RSA, K_RSA, C_NULL, B_0, M_MD5, F_EXPORT, A_RSAD, ssl_hash_none },
/* ECC cipher suites */
{ 0, CS(ECDHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_RSAS },
{ 0, CS(ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), S_ECDSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_ECDSA },
{ 0, CS(ECDH_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDH, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_ECDH_E },
{ 0, CS(ECDH_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDH, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_ECDH_E },
{ 0, CS(ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDH, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_ECDH_E },
{ 0, CS(ECDH_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_128, M_SHA, F_FIPS_STD, A_ECDH_E },
{ 0, CS(ECDH_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_256, M_SHA, F_FIPS_STD, A_ECDH_E },
{ 0, CS(ECDHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_RSAS, ssl_hash_sha256 },
{ 0, CS(ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), S_ECDSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_ECDSA, ssl_hash_sha256 },
{ 0, CS(ECDH_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDH, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_ECDH_E, ssl_hash_none },
{ 0, CS(ECDH_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDH, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_ECDH_E, ssl_hash_none },
{ 0, CS(ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDH, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_ECDH_E, ssl_hash_none },
{ 0, CS(ECDH_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_128, M_SHA, F_FIPS_STD, A_ECDH_E, ssl_hash_none },
{ 0, CS(ECDH_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_256, M_SHA, F_FIPS_STD, A_ECDH_E, ssl_hash_none },
{ 0, CS(ECDHE_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDHE, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_ECDSA },
{ 0, CS(ECDHE_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDHE, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_ECDSA },
{ 0, CS(ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_ECDSA },
{ 0, CS(ECDHE_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_ECDSA },
{ 0, CS(ECDHE_ECDSA_WITH_AES_128_CBC_SHA256), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_ECDSA },
{ 0, CS(ECDHE_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_ECDSA },
{ 0, CS(ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), S_ECDSA, K_ECDHE, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_ECDSA },
{ 0, CS(ECDHE_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDHE, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_ECDSA, ssl_hash_none },
{ 0, CS(ECDHE_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDHE, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_ECDSA, ssl_hash_none },
{ 0, CS(ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_ECDSA, ssl_hash_none },
{ 0, CS(ECDHE_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_ECDSA, ssl_hash_none },
{ 0, CS(ECDHE_ECDSA_WITH_AES_128_CBC_SHA256), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_ECDSA, ssl_hash_sha256 },
{ 0, CS(ECDHE_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_ECDSA, ssl_hash_none },
{ 0, CS(ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), S_ECDSA, K_ECDHE, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_ECDSA, ssl_hash_sha256 },
{ 0, CS(ECDH_RSA_WITH_NULL_SHA), S_RSA, K_ECDH, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_ECDH_R },
{ 0, CS(ECDH_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDH, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_ECDH_R },
{ 0, CS(ECDH_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDH, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_ECDH_R },
{ 0, CS(ECDH_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDH, C_AES, B_128, M_SHA, F_FIPS_STD, A_ECDH_R },
{ 0, CS(ECDH_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDH, C_AES, B_256, M_SHA, F_FIPS_STD, A_ECDH_R },
{ 0, CS(ECDH_RSA_WITH_NULL_SHA), S_RSA, K_ECDH, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_ECDH_R, ssl_hash_none },
{ 0, CS(ECDH_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDH, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_ECDH_R, ssl_hash_none },
{ 0, CS(ECDH_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDH, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_ECDH_R, ssl_hash_none },
{ 0, CS(ECDH_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDH, C_AES, B_128, M_SHA, F_FIPS_STD, A_ECDH_R, ssl_hash_none },
{ 0, CS(ECDH_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDH, C_AES, B_256, M_SHA, F_FIPS_STD, A_ECDH_R, ssl_hash_none },
{ 0, CS(ECDHE_RSA_WITH_NULL_SHA), S_RSA, K_ECDHE, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_RSAS },
{ 0, CS(ECDHE_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDHE, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_RSAS },
{ 0, CS(ECDHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_RSAS },
{ 0, CS(ECDHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_RSAS },
{ 0, CS(ECDHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_ECDHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_RSAS },
{ 0, CS(ECDHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_RSAS },
{ 0, CS(ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), S_RSA, K_ECDHE, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_RSAS },
{ 0, CS(ECDHE_RSA_WITH_AES_256_CBC_SHA384), S_RSA, K_ECDHE, C_AES, B_256, M_SHA384, F_FIPS_STD, A_RSAS },
{ 0, CS(ECDHE_ECDSA_WITH_AES_256_CBC_SHA384), S_ECDSA, K_ECDHE, C_AES, B_256, M_SHA384, F_FIPS_STD, A_ECDSA },
{ 0, CS(ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), S_ECDSA, K_ECDHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_ECDSA },
{ 0, CS(ECDHE_RSA_WITH_AES_256_GCM_SHA384), S_RSA, K_ECDHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_RSAS },
{ 0, CS(ECDHE_RSA_WITH_NULL_SHA), S_RSA, K_ECDHE, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_RSAS, ssl_hash_none },
{ 0, CS(ECDHE_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDHE, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_RSAS, ssl_hash_none },
{ 0, CS(ECDHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_RSAS, ssl_hash_none },
{ 0, CS(ECDHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_RSAS, ssl_hash_none },
{ 0, CS(ECDHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_ECDHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_RSAS, ssl_hash_sha256 },
{ 0, CS(ECDHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_RSAS, ssl_hash_none },
{ 0, CS(ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), S_RSA, K_ECDHE, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_RSAS, ssl_hash_sha256 },
{ 0, CS(ECDHE_RSA_WITH_AES_256_CBC_SHA384), S_RSA, K_ECDHE, C_AES, B_256, M_SHA384, F_FIPS_STD, A_RSAS, ssl_hash_sha384 },
{ 0, CS(ECDHE_ECDSA_WITH_AES_256_CBC_SHA384), S_ECDSA, K_ECDHE, C_AES, B_256, M_SHA384, F_FIPS_STD, A_ECDSA, ssl_hash_sha384 },
{ 0, CS(ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), S_ECDSA, K_ECDHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_ECDSA, ssl_hash_sha384 },
{ 0, CS(ECDHE_RSA_WITH_AES_256_GCM_SHA384), S_RSA, K_ECDHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_RSAS, ssl_hash_sha384 },
{ 0, CS(DHE_DSS_WITH_AES_256_GCM_SHA384), S_DSA, K_DHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_DSA },
{ 0, CS(DHE_RSA_WITH_AES_256_GCM_SHA384), S_RSA, K_DHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_RSAS },
{ 0, CS(RSA_WITH_AES_256_GCM_SHA384), S_RSA, K_RSA, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_RSAD },
{ 0, CS(DHE_DSS_WITH_AES_256_GCM_SHA384), S_DSA, K_DHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_DSA, ssl_hash_sha384 },
{ 0, CS(DHE_RSA_WITH_AES_256_GCM_SHA384), S_RSA, K_DHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_RSAS, ssl_hash_sha384 },
{ 0, CS(RSA_WITH_AES_256_GCM_SHA384), S_RSA, K_RSA, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_RSAD, ssl_hash_sha384 },
};
#define NUM_SUITEINFOS ((sizeof suiteInfo) / (sizeof suiteInfo[0]))

Some files were not shown because too many files have changed in this diff Show More