mirror of
https://github.com/roytam1/mozilla45esr.git
synced 2026-05-29 17:38:37 +00:00
nss: update nss to hg rev e5e10a46b9ad with vc2013 hackfix
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
+2036
-626
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*$/);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ NSS_SRCDIRS = \
|
||||
p7sign \
|
||||
p7verify \
|
||||
pk12util \
|
||||
pk11importtest \
|
||||
pk11ectest \
|
||||
pk11gcmtest \
|
||||
pk11mode \
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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__
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ struct ScopedMaybeDelete {
|
||||
SCOPED(SECAlgorithmID);
|
||||
SCOPED(SECItem);
|
||||
SCOPED(PK11URI);
|
||||
SCOPED(PLArenaPool);
|
||||
|
||||
#undef SCOPED
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 <emaldona@redhat.com>, Deon Lackey <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>
|
||||
@@ -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 \
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -24,6 +24,7 @@ NSS_SRCDIRS = \
|
||||
cryptohi_gtest \
|
||||
der_gtest \
|
||||
pk11_gtest \
|
||||
smime_gtest \
|
||||
softoken_gtest \
|
||||
ssl_gtest \
|
||||
$(SYSINIT_GTEST) \
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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_, ¶m, out, &uoutlen, maxlen, in, inlen);
|
||||
} else {
|
||||
rv = PK11_Encrypt(key_, mech_, ¶m, 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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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'
|
||||
],
|
||||
}],
|
||||
],
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -1145,3 +1145,9 @@ HASH_GetHashOidTagByHashType;
|
||||
;+ local:
|
||||
;+ *;
|
||||
;+};
|
||||
;+NSS_3.44 { # NSS 3.44 release
|
||||
;+ global:
|
||||
CERT_GetCertificateDer;
|
||||
;+ local:
|
||||
;+ *;
|
||||
;+};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -55,6 +55,7 @@ CSRCS = \
|
||||
tls13replay.c \
|
||||
sslcert.c \
|
||||
sslgrp.c \
|
||||
sslprimitive.c \
|
||||
tls13esni.c \
|
||||
$(NULL)
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
'sslinit.c',
|
||||
'sslmutex.c',
|
||||
'sslnonce.c',
|
||||
'sslprimitive.c',
|
||||
'sslreveal.c',
|
||||
'sslsecur.c',
|
||||
'sslsnce.c',
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user