diff options
author | wolfbeast <mcwerewolf@gmail.com> | 2018-08-14 07:52:35 +0200 |
---|---|---|
committer | wolfbeast <mcwerewolf@gmail.com> | 2018-08-14 16:42:52 +0200 |
commit | ab1060037931158d3a8bf4c8f9f6cb4dbfe916e9 (patch) | |
tree | 5e4677e52b9a349602f04135a44b3000c8baa97b /security/nss | |
parent | f44e99950fc25d16a3cdaffe26dadf7b58a9d38c (diff) | |
download | UXP-ab1060037931158d3a8bf4c8f9f6cb4dbfe916e9.tar UXP-ab1060037931158d3a8bf4c8f9f6cb4dbfe916e9.tar.gz UXP-ab1060037931158d3a8bf4c8f9f6cb4dbfe916e9.tar.lz UXP-ab1060037931158d3a8bf4c8f9f6cb4dbfe916e9.tar.xz UXP-ab1060037931158d3a8bf4c8f9f6cb4dbfe916e9.zip |
Update NSS to 3.38
- Added HACL*Poly1305 32-bit (INRIA/Microsoft)
- Updated to final TLS 1.3 draft version (28)
- Removed TLS 1.3 prerelease draft limit check
- Removed NPN code
- Enabled dev/urandom-only RNG on Linux with NSS_SEED_ONLY_DEV_URANDOM for non-standard environments
- Fixed several bugs with TLS 1.3 negotiation
- Updated internal certificate store
- Added support for the TLS Record Size Limit Extension.
- Fixed CVE-2018-0495
- Various security fixes in the ASN.1 code.
Diffstat (limited to 'security/nss')
195 files changed, 4861 insertions, 7139 deletions
diff --git a/security/nss/TAG-INFO b/security/nss/TAG-INFO index 1d96321b3..a004fa449 100644 --- a/security/nss/TAG-INFO +++ b/security/nss/TAG-INFO @@ -1 +1 @@ -NSS_3_36_4_RTM +NSS_3_38_RTM diff --git a/security/nss/automation/abi-check/expected-report-libnssutil3.so.txt b/security/nss/automation/abi-check/expected-report-libnssutil3.so.txt index e69de29bb..efc7d6d67 100644 --- a/security/nss/automation/abi-check/expected-report-libnssutil3.so.txt +++ b/security/nss/automation/abi-check/expected-report-libnssutil3.so.txt @@ -0,0 +1,4 @@ + +1 Added function: + + 'function SECStatus SECITEM_MakeItem(PLArenaPool*, SECItem*, unsigned char*, unsigned int)' {SECITEM_MakeItem@@NSSUTIL_3.38} diff --git a/security/nss/automation/abi-check/expected-report-libssl3.so.txt b/security/nss/automation/abi-check/expected-report-libssl3.so.txt index ad818d0aa..e69de29bb 100644 --- a/security/nss/automation/abi-check/expected-report-libssl3.so.txt +++ b/security/nss/automation/abi-check/expected-report-libssl3.so.txt @@ -1,28 +0,0 @@ - -1 function with some indirect sub-type change: - - [C]'function SECStatus SSL_GetChannelInfo(PRFileDesc*, SSLChannelInfo*, PRUintn)' at sslinfo.c:12:1 has some indirect sub-type changes: - parameter 2 of type 'SSLChannelInfo*' has sub-type changes: - in pointed to type 'typedef SSLChannelInfo' at sslt.h:318:1: - underlying type 'struct SSLChannelInfoStr' at sslt.h:251:1 changed: - type size hasn't changed - 1 data member change: - type of 'SSLSignatureScheme SSLChannelInfoStr::signatureScheme' changed: - underlying type 'enum __anonymous_enum__' at sslt.h:115:1 changed: - type size hasn't changed - 3 enumerator deletions: - '__anonymous_enum__::ssl_sig_rsa_pss_sha256' value '2052' - '__anonymous_enum__::ssl_sig_rsa_pss_sha384' value '2053' - '__anonymous_enum__::ssl_sig_rsa_pss_sha512' value '2054' - - 6 enumerator insertions: - '__anonymous_enum__::ssl_sig_rsa_pss_rsae_sha256' value '2052' - '__anonymous_enum__::ssl_sig_rsa_pss_rsae_sha384' value '2053' - '__anonymous_enum__::ssl_sig_rsa_pss_rsae_sha512' value '2054' - '__anonymous_enum__::ssl_sig_rsa_pss_pss_sha256' value '2057' - '__anonymous_enum__::ssl_sig_rsa_pss_pss_sha384' value '2058' - '__anonymous_enum__::ssl_sig_rsa_pss_pss_sha512' value '2059' - - - - diff --git a/security/nss/automation/abi-check/previous-nss-release b/security/nss/automation/abi-check/previous-nss-release index c213ca3f8..c52061e7e 100644 --- a/security/nss/automation/abi-check/previous-nss-release +++ b/security/nss/automation/abi-check/previous-nss-release @@ -1 +1 @@ -NSS_3_35_BRANCH +NSS_3_37_BRANCH diff --git a/security/nss/automation/taskcluster/docker-hacl/Dockerfile b/security/nss/automation/taskcluster/docker-hacl/Dockerfile index 63f9a24e2..50f2be239 100644 --- a/security/nss/automation/taskcluster/docker-hacl/Dockerfile +++ b/security/nss/automation/taskcluster/docker-hacl/Dockerfile @@ -5,11 +5,11 @@ MAINTAINER Franziskus Kiefer <franziskuskiefer@gmail.com> # the original F* formula with Daniel Fabian # Pinned versions of HACL* (F* and KreMLin are pinned as submodules) -ENV haclrepo https://github.com/franziskuskiefer/hacl-star.git +ENV haclrepo https://github.com/mitls/hacl-star.git # Define versions of dependencies -ENV opamv 4.04.2 -ENV haclversion 668d6cf274c33bbe2e951e3a84b73f2b6442a51f +ENV opamv 4.05.0 +ENV haclversion 1da331f9ef30e13269e45ae73bbe4a4bca679ae6 # Install required packages and set versions ADD setup.sh /tmp/setup.sh diff --git a/security/nss/automation/taskcluster/docker-hacl/setup-user.sh b/security/nss/automation/taskcluster/docker-hacl/setup-user.sh index b8accaf58..e2c0b857b 100644 --- a/security/nss/automation/taskcluster/docker-hacl/setup-user.sh +++ b/security/nss/automation/taskcluster/docker-hacl/setup-user.sh @@ -16,7 +16,6 @@ git -C hacl-star checkout ${haclversion} # This caches the extracted c code (pins the HACL* version). All we need to do # on CI now is comparing the code in this docker image with the one in NSS. opam config exec -- make -C hacl-star prepare -j$(nproc) -make -C hacl-star verify-nss -j$(nproc) make -C hacl-star -f Makefile.build snapshots/nss -j$(nproc) KOPTS="-funroll-loops 5" make -C hacl-star/code/curve25519 test -j$(nproc) make -C hacl-star/code/salsa-family test -j$(nproc) diff --git a/security/nss/automation/taskcluster/docker-saw/Dockerfile b/security/nss/automation/taskcluster/docker-saw/Dockerfile index a481ba048..d67787010 100644 --- a/security/nss/automation/taskcluster/docker-saw/Dockerfile +++ b/security/nss/automation/taskcluster/docker-saw/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:latest +FROM ubuntu:16.04 MAINTAINER Tim Taubert <ttaubert@mozilla.com> RUN useradd -d /home/worker -s /bin/bash -m worker diff --git a/security/nss/automation/taskcluster/docker/Dockerfile b/security/nss/automation/taskcluster/docker/Dockerfile index 8a2256d12..b3c2516ba 100644 --- a/security/nss/automation/taskcluster/docker/Dockerfile +++ b/security/nss/automation/taskcluster/docker/Dockerfile @@ -12,9 +12,6 @@ RUN chmod +x /home/worker/bin/* ADD setup.sh /tmp/setup.sh RUN bash /tmp/setup.sh -# Change user. -USER worker - # Env variables. ENV HOME /home/worker ENV SHELL /bin/bash diff --git a/security/nss/automation/taskcluster/graph/src/extend.js b/security/nss/automation/taskcluster/graph/src/extend.js index ee9ac9b74..5305325c5 100644 --- a/security/nss/automation/taskcluster/graph/src/extend.js +++ b/security/nss/automation/taskcluster/graph/src/extend.js @@ -995,13 +995,13 @@ async function scheduleTools() { })); queue.scheduleTask(merge(base, { - symbol: "scan-build-5.0", - name: "scan-build-5.0", - image: LINUX_IMAGE, + symbol: "scan-build", + name: "scan-build", + image: FUZZ_IMAGE, env: { USE_64: "1", - CC: "clang-5.0", - CCC: "clang++-5.0", + CC: "clang", + CCC: "clang++", }, artifacts: { public: { @@ -1092,5 +1092,17 @@ async function scheduleTools() { ] })); + queue.scheduleTask(merge(base, { + symbol: "Coverage", + name: "Coverage", + image: FUZZ_IMAGE, + features: ["allowPtrace"], + command: [ + "/bin/bash", + "-c", + "bin/checkout.sh && nss/automation/taskcluster/scripts/gen_coverage_report.sh" + ] + })); + return queue.submit(); } diff --git a/security/nss/automation/taskcluster/graph/src/try_syntax.js b/security/nss/automation/taskcluster/graph/src/try_syntax.js index 1c06dde13..214793bd5 100644 --- a/security/nss/automation/taskcluster/graph/src/try_syntax.js +++ b/security/nss/automation/taskcluster/graph/src/try_syntax.js @@ -51,7 +51,7 @@ function parseOptions(opts) { } // Parse tools. - let allTools = ["clang-format", "scan-build", "hacl", "saw", "abi"]; + let allTools = ["clang-format", "scan-build", "hacl", "saw", "abi", "coverage"]; let tools = intersect(opts.tools.split(/\s*,\s*/), allTools); // If the given value is "all" run all tools. diff --git a/security/nss/automation/taskcluster/scripts/gen_coverage_report.sh b/security/nss/automation/taskcluster/scripts/gen_coverage_report.sh new file mode 100644 index 000000000..3907c72e8 --- /dev/null +++ b/security/nss/automation/taskcluster/scripts/gen_coverage_report.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +source $(dirname "$0")/tools.sh + +# Clone NSPR. +hg_clone https://hg.mozilla.org/projects/nspr ./nspr default + +out=/home/worker/artifacts +mkdir -p $out + +# Generate coverage report. +cd nss && ./mach coverage --outdir=$out ssl_gtests diff --git a/security/nss/automation/taskcluster/scripts/run_hacl.sh b/security/nss/automation/taskcluster/scripts/run_hacl.sh index 281075eef..6cbda49b4 100644 --- a/security/nss/automation/taskcluster/scripts/run_hacl.sh +++ b/security/nss/automation/taskcluster/scripts/run_hacl.sh @@ -12,8 +12,8 @@ set -e -x -v # The extracted C code from HACL* is already generated and the HACL* tests were # successfully executed. -# Verify Poly1305 (doesn't work in docker image build) -make verify -C ~/hacl-star/code/poly1305 -j$(nproc) +# Verify HACL*. Taskcluster fails when we do this in the image build. +make -C hacl-star verify-nss -j$(nproc) # Add license header to specs spec_files=($(find ~/hacl-star/specs -type f -name '*.fst')) diff --git a/security/nss/automation/taskcluster/scripts/tools.sh b/security/nss/automation/taskcluster/scripts/tools.sh index 46d567e3a..534cb32ce 100644 --- a/security/nss/automation/taskcluster/scripts/tools.sh +++ b/security/nss/automation/taskcluster/scripts/tools.sh @@ -3,11 +3,16 @@ set -v -e -x if [[ $(id -u) -eq 0 ]]; then + # Stupid Docker. It works without sometimes... But not always. + echo "127.0.0.1 localhost.localdomain" >> /etc/hosts + # Drop privileges by re-running this script. # Note: this mangles arguments, better to avoid running scripts as root. exec su worker -c "$0 $*" fi +export PATH="${PATH}:/home/worker/.cargo/bin/:/usr/lib/go-1.6/bin" + # Usage: hg_clone repo dir [revision=@] hg_clone() { repo=$1 diff --git a/security/nss/cmd/bltest/blapitest.c b/security/nss/cmd/bltest/blapitest.c index ca3d6f314..ef8fdd802 100644 --- a/security/nss/cmd/bltest/blapitest.c +++ b/security/nss/cmd/bltest/blapitest.c @@ -3724,7 +3724,7 @@ main(int argc, char **argv) /* test the RSA_PopulatePrivateKey function */ if (bltest.commands[cmd_RSAPopulate].activated) { unsigned int keySize = 1024; - unsigned long exponent = 65537; + unsigned long keyExponent = 65537; int rounds = 1; int ret = -1; @@ -3735,12 +3735,12 @@ main(int argc, char **argv) rounds = PORT_Atoi(bltest.options[opt_Rounds].arg); } if (bltest.options[opt_Exponent].activated) { - exponent = PORT_Atoi(bltest.options[opt_Exponent].arg); + keyExponent = PORT_Atoi(bltest.options[opt_Exponent].arg); } for (i = 0; i < rounds; i++) { printf("Running RSA Populate test round %d\n", i); - ret = doRSAPopulateTest(keySize, exponent); + ret = doRSAPopulateTest(keySize, keyExponent); if (ret != 0) { break; } diff --git a/security/nss/cmd/certutil/certutil.c b/security/nss/cmd/certutil/certutil.c index 20722ae78..dbb93c922 100644 --- a/security/nss/cmd/certutil/certutil.c +++ b/security/nss/cmd/certutil/certutil.c @@ -36,9 +36,11 @@ #include "certdb.h" #include "nss.h" #include "certutil.h" +#include "basicutil.h" +#include "ssl.h" #define MIN_KEY_BITS 512 -/* MAX_KEY_BITS should agree with MAX_RSA_MODULUS in freebl */ +/* MAX_KEY_BITS should agree with RSA_MAX_MODULUS_BITS in freebl */ #define MAX_KEY_BITS 8192 #define DEFAULT_KEY_BITS 2048 @@ -447,7 +449,8 @@ ChangeTrustAttributes(CERTCertDBHandle *handle, PK11SlotInfo *slot, } static SECStatus -DumpChain(CERTCertDBHandle *handle, char *name, PRBool ascii) +DumpChain(CERTCertDBHandle *handle, char *name, PRBool ascii, + PRBool simpleSelfSigned) { CERTCertificate *the_cert; CERTCertificateList *chain; @@ -458,6 +461,14 @@ DumpChain(CERTCertDBHandle *handle, char *name, PRBool ascii) SECU_PrintError(progName, "Could not find: %s\n", name); return SECFailure; } + if (simpleSelfSigned && + SECEqual == SECITEM_CompareItem(&the_cert->derIssuer, + &the_cert->derSubject)) { + printf("\"%s\" [%s]\n\n", the_cert->nickname, the_cert->subjectName); + CERT_DestroyCertificate(the_cert); + return SECSuccess; + } + chain = CERT_CertChainFromCert(the_cert, 0, PR_TRUE); CERT_DestroyCertificate(the_cert); if (!chain) { @@ -782,17 +793,17 @@ ValidateCert(CERTCertDBHandle *handle, char *name, char *date, fprintf(stdout, "%s: certificate is valid\n", progName); GEN_BREAK(SECSuccess) } else { - char *name; + char *nick; CERTVerifyLogNode *node; node = log->head; while (node) { if (node->cert->nickname != NULL) { - name = node->cert->nickname; + nick = node->cert->nickname; } else { - name = node->cert->subjectName; + nick = node->cert->subjectName; } - fprintf(stderr, "%s : %s\n", name, + fprintf(stderr, "%s : %s\n", nick, SECU_Strerror(node->error)); CERT_DestroyCertificate(node->cert); node = node->next; @@ -845,7 +856,7 @@ SECItemToHex(const SECItem *item, char *dst) } static const char *const keyTypeName[] = { - "null", "rsa", "dsa", "fortezza", "dh", "kea", "ec" + "null", "rsa", "dsa", "fortezza", "dh", "kea", "ec", "rsaPss" }; #define MAX_CKA_ID_BIN_LEN 20 @@ -999,7 +1010,7 @@ DeleteKey(char *nickname, secuPWData *pwdata) slot = PK11_GetInternalKeySlot(); if (PK11_NeedLogin(slot)) { - SECStatus rv = PK11_Authenticate(slot, PR_TRUE, pwdata); + rv = PK11_Authenticate(slot, PR_TRUE, pwdata); if (rv != SECSuccess) { SECU_PrintError(progName, "could not authenticate to token %s.", PK11_GetTokenName(slot)); @@ -1066,7 +1077,7 @@ PrintBuildFlags() } static void -PrintSyntax(char *progName) +PrintSyntax() { #define FPS fprintf(stderr, FPS "Type %s -H for more detailed descriptions\n", progName); @@ -1115,7 +1126,9 @@ PrintSyntax(char *progName) FPS "\t%s --build-flags\n", progName); FPS "\t%s -M -n cert-name -t trustargs [-d certdir] [-P dbprefix]\n", progName); - FPS "\t%s -O -n cert-name [-X] [-d certdir] [-a] [-P dbprefix]\n", progName); + FPS "\t%s -O -n cert-name [-X] [-d certdir] [-a] [-P dbprefix]\n" + "\t\t [--simple-self-signed]\n", + progName); FPS "\t%s -R -s subj -o cert-request-file [-d certdir] [-P dbprefix] [-p phone] [-a]\n" "\t\t [-7 emailAddrs] [-k key-type-or-id] [-h token-name] [-f pwfile]\n" "\t\t [-g key-size] [-Z hashAlg]\n", @@ -1542,6 +1555,8 @@ luO(enum usage_level ul, const char *command) " -P dbprefix"); FPS "%-20s force the database to open R/W\n", " -X"); + FPS "%-20s don't search for a chain if issuer name equals subject name\n", + " --simple-self-signed"); FPS "\n"); } @@ -1560,7 +1575,7 @@ luR(enum usage_level ul, const char *command) " -o output-req"); FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n", " -k key-type-or-id"); - FPS "%-20s or nickname of the cert key to use \n", + FPS "%-20s or nickname of the cert key to use, or key id obtained using -K\n", ""); FPS "%-20s Name of token in which to generate key (default is internal)\n", " -h token-name"); @@ -1838,7 +1853,7 @@ luBuildFlags(enum usage_level ul, const char *command) } static void -LongUsage(char *progName, enum usage_level ul, const char *command) +LongUsage(enum usage_level ul, const char *command) { luA(ul, command); luB(ul, command); @@ -1866,14 +1881,14 @@ LongUsage(char *progName, enum usage_level ul, const char *command) } static void -Usage(char *progName) +Usage() { PR_fprintf(PR_STDERR, "%s - Utility to manipulate NSS certificate databases\n\n" "Usage: %s <command> -d <database-directory> <options>\n\n" "Valid commands:\n", progName, progName); - LongUsage(progName, usage_selected, NULL); + LongUsage(usage_selected, NULL); PR_fprintf(PR_STDERR, "\n" "%s -H <command> : Print available options for the given command\n" "%s -H : Print complete help output of all commands and options\n" @@ -2269,10 +2284,10 @@ flagArray opFlagsArray[] = { NAME_SIZE(verify_recover), CKF_VERIFY_RECOVER }, { NAME_SIZE(wrap), CKF_WRAP }, { NAME_SIZE(unwrap), CKF_UNWRAP }, - { NAME_SIZE(derive), CKF_DERIVE }, + { NAME_SIZE(derive), CKF_DERIVE } }; -int opFlagsCount = sizeof(opFlagsArray) / sizeof(flagArray); +int opFlagsCount = PR_ARRAY_SIZE(opFlagsArray); flagArray attrFlagsArray[] = { @@ -2286,14 +2301,13 @@ flagArray attrFlagsArray[] = { NAME_SIZE(insensitive), PK11_ATTR_INSENSITIVE }, { NAME_SIZE(extractable), PK11_ATTR_EXTRACTABLE }, { NAME_SIZE(unextractable), PK11_ATTR_UNEXTRACTABLE } - }; -int attrFlagsCount = sizeof(attrFlagsArray) / sizeof(flagArray); +int attrFlagsCount = PR_ARRAY_SIZE(attrFlagsArray); #define MAX_STRING 30 CK_ULONG -GetFlags(char *flagsString, flagArray *flagArray, int count) +GetFlags(char *flagsString, flagArray *flags, int count) { CK_ULONG flagsValue = strtol(flagsString, NULL, 0); int i; @@ -2303,10 +2317,10 @@ GetFlags(char *flagsString, flagArray *flagArray, int count) } while (*flagsString) { for (i = 0; i < count; i++) { - if (strncmp(flagsString, flagArray[i].name, flagArray[i].nameSize) == + if (strncmp(flagsString, flags[i].name, flags[i].nameSize) == 0) { - flagsValue |= flagArray[i].value; - flagsString += flagArray[i].nameSize; + flagsValue |= flags[i].value; + flagsString += flags[i].nameSize; if (*flagsString != 0) { flagsString++; } @@ -2499,6 +2513,7 @@ enum certutilOpts { opt_NewNickname, opt_Pss, opt_PssSign, + opt_SimpleSelfSigned, opt_Help }; @@ -2623,6 +2638,8 @@ static const secuCommandFlag options_init[] = "pss" }, { /* opt_PssSign */ 0, PR_FALSE, 0, PR_FALSE, "pss-sign" }, + { /* opt_SimpleSelfSigned */ 0, PR_FALSE, 0, PR_FALSE, + "simple-self-signed" }, }; #define NUM_OPTIONS ((sizeof options_init) / (sizeof options_init[0])) @@ -2691,14 +2708,13 @@ certutil_main(int argc, char **argv, PRBool initialize) rv = SECU_ParseCommandLine(argc, argv, progName, &certutil); if (rv != SECSuccess) - Usage(progName); + Usage(); if (certutil.commands[cmd_PrintSyntax].activated) { - PrintSyntax(progName); + PrintSyntax(); } if (certutil.commands[cmd_PrintHelp].activated) { - int i; char buf[2]; const char *command = NULL; for (i = 0; i < max_cmd; i++) { @@ -2715,7 +2731,7 @@ certutil_main(int argc, char **argv, PRBool initialize) break; } } - LongUsage(progName, (command ? usage_selected : usage_all), command); + LongUsage((command ? usage_selected : usage_all), command); exit(1); } @@ -2823,7 +2839,7 @@ certutil_main(int argc, char **argv, PRBool initialize) if (certutil.options[opt_DBPrefix].arg) { certPrefix = certutil.options[opt_DBPrefix].arg; } else { - Usage(progName); + Usage(); } } @@ -2832,7 +2848,7 @@ certutil_main(int argc, char **argv, PRBool initialize) if (certutil.options[opt_SourcePrefix].arg) { srcCertPrefix = certutil.options[opt_SourcePrefix].arg; } else { - Usage(progName); + Usage(); } } @@ -2916,7 +2932,7 @@ certutil_main(int argc, char **argv, PRBool initialize) return 255; } if (commandsEntered == 0) { - Usage(progName); + Usage(); } if (certutil.commands[cmd_ListCerts].activated || @@ -3124,6 +3140,8 @@ certutil_main(int argc, char **argv, PRBool initialize) } initialized = PR_TRUE; SECU_RegisterDynamicOids(); + /* Ensure the SSL error code table has been registered. Bug 1460284. */ + SSL_OptionSetDefault(-1, 0); } certHandle = CERT_GetDefaultCertDB(); @@ -3350,7 +3368,8 @@ certutil_main(int argc, char **argv, PRBool initialize) } if (certutil.commands[cmd_DumpChain].activated) { rv = DumpChain(certHandle, name, - certutil.options[opt_ASCIIForIO].activated); + certutil.options[opt_ASCIIForIO].activated, + certutil.options[opt_SimpleSelfSigned].activated); goto shutdown; } /* XXX needs work */ @@ -3444,37 +3463,80 @@ certutil_main(int argc, char **argv, PRBool initialize) keycert = CERT_FindCertByNicknameOrEmailAddr(certHandle, keysource); if (!keycert) { keycert = PK11_FindCertFromNickname(keysource, NULL); - if (!keycert) { - SECU_PrintError(progName, - "%s is neither a key-type nor a nickname", keysource); + } + + if (keycert) { + privkey = PK11_FindKeyByDERCert(slot, keycert, &pwdata); + } else { + PLArenaPool *arena = NULL; + SECItem keyidItem = { 0 }; + char *keysourcePtr = keysource; + /* Interpret keysource as CKA_ID */ + if (PK11_NeedLogin(slot)) { + rv = PK11_Authenticate(slot, PR_TRUE, &pwdata); + if (rv != SECSuccess) { + SECU_PrintError(progName, "could not authenticate to token %s.", + PK11_GetTokenName(slot)); + return SECFailure; + } + } + if (0 == PL_strncasecmp("0x", keysource, 2)) { + keysourcePtr = keysource + 2; // skip leading "0x" + } + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!arena) { + SECU_PrintError(progName, "unable to allocate arena"); return SECFailure; } + if (SECU_HexString2SECItem(arena, &keyidItem, keysourcePtr)) { + privkey = PK11_FindKeyByKeyID(slot, &keyidItem, &pwdata); + } + PORT_FreeArena(arena, PR_FALSE); + } + + if (!privkey) { + SECU_PrintError( + progName, + "%s is neither a key-type nor a nickname nor a key-id", keysource); + return SECFailure; } - privkey = PK11_FindKeyByDERCert(slot, keycert, &pwdata); - if (privkey) - pubkey = CERT_ExtractPublicKey(keycert); + + pubkey = SECKEY_ConvertToPublicKey(privkey); if (!pubkey) { SECU_PrintError(progName, "Could not get keys from cert %s", keysource); + if (keycert) { + CERT_DestroyCertificate(keycert); + } rv = SECFailure; - CERT_DestroyCertificate(keycert); goto shutdown; } keytype = privkey->keyType; + /* On CertReq for renewal if no subject has been * specified obtain it from the certificate. */ if (certutil.commands[cmd_CertReq].activated && !subject) { - subject = CERT_AsciiToName(keycert->subjectName); - if (!subject) { - SECU_PrintError(progName, - "Could not get subject from certificate %s", keysource); - CERT_DestroyCertificate(keycert); + if (keycert) { + subject = CERT_AsciiToName(keycert->subjectName); + if (!subject) { + SECU_PrintError( + progName, + "Could not get subject from certificate %s", + keysource); + CERT_DestroyCertificate(keycert); + rv = SECFailure; + goto shutdown; + } + } else { + SECU_PrintError(progName, "Subject name not provided"); rv = SECFailure; goto shutdown; } } - CERT_DestroyCertificate(keycert); + if (keycert) { + CERT_DestroyCertificate(keycert); + } } else { privkey = CERTUTIL_GeneratePrivateKey(keytype, slot, keysize, @@ -3537,6 +3599,14 @@ certutil_main(int argc, char **argv, PRBool initialize) } } + if (certutil.options[opt_SimpleSelfSigned].activated && + !certutil.commands[cmd_DumpChain].activated) { + PR_fprintf(PR_STDERR, + "%s -%c: --simple-self-signed only works with -O.\n", + progName, commandToRun); + return 255; + } + /* If we need a list of extensions convert the flags into list format */ if (certutil.commands[cmd_CertReq].activated || certutil.commands[cmd_CreateAndAddCert].activated || diff --git a/security/nss/cmd/crlutil/crlutil.c b/security/nss/cmd/crlutil/crlutil.c index c008ecc01..c5527fc93 100644 --- a/security/nss/cmd/crlutil/crlutil.c +++ b/security/nss/cmd/crlutil/crlutil.c @@ -770,7 +770,7 @@ loser: } static void -Usage(char *progName) +Usage() { fprintf(stderr, "Usage: %s -L [-n nickname] [-d keydir] [-P dbprefix] [-t crlType]\n" @@ -908,7 +908,7 @@ main(int argc, char **argv) while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch (optstate->option) { case '?': - Usage(progName); + Usage(); break; case 'T': @@ -1038,17 +1038,17 @@ main(int argc, char **argv) } if (deleteCRL && !nickName) - Usage(progName); + Usage(); if (importCRL && !inFile) - Usage(progName); + Usage(); if (showFileCRL && !inFile) - Usage(progName); + Usage(); if ((generateCRL && !nickName) || (modifyCRL && !inFile && !nickName)) - Usage(progName); + Usage(); if (!(listCRL || deleteCRL || importCRL || showFileCRL || generateCRL || modifyCRL || test || erase)) - Usage(progName); + Usage(); if (listCRL || showFileCRL) { readonly = PR_TRUE; diff --git a/security/nss/cmd/crmftest/testcrmf.c b/security/nss/cmd/crmftest/testcrmf.c index cbc680b08..1c1359b1b 100644 --- a/security/nss/cmd/crmftest/testcrmf.c +++ b/security/nss/cmd/crmftest/testcrmf.c @@ -577,7 +577,6 @@ Decode(void) printf("WARNING: The DER contained %d messages.\n", numMsgs); } for (i = 0; i < numMsgs; i++) { - SECStatus rv; printf("crmftest: Processing cert request %d\n", i); certReqMsg = CRMF_CertReqMessagesGetCertReqMsgAtIndex(certReqMsgs, i); if (certReqMsg == NULL) { diff --git a/security/nss/cmd/dbtest/dbtest.c b/security/nss/cmd/dbtest/dbtest.c index 9a6a034a6..11713c23f 100644 --- a/security/nss/cmd/dbtest/dbtest.c +++ b/security/nss/cmd/dbtest/dbtest.c @@ -58,7 +58,7 @@ getPassword(PK11SlotInfo *slot, PRBool retry, void *arg) } static void -Usage(const char *progName) +Usage() { printf("Usage: %s [-r] [-f] [-i] [-d dbdir ] \n", progName); @@ -96,7 +96,7 @@ main(int argc, char **argv) switch (optstate->option) { case 'h': default: - Usage(progName); + Usage(); break; case 'r': @@ -122,7 +122,7 @@ main(int argc, char **argv) } PL_DestroyOptState(optstate); if (optstatus == PL_OPT_BAD) - Usage(progName); + Usage(); if (dbDir) { char *tmp = dbDir; @@ -181,7 +181,6 @@ main(int argc, char **argv) ret = SUCCESS; if (doInitTest) { PK11SlotInfo *slot = PK11_GetInternalKeySlot(); - SECStatus rv; int passwordSuccess = 0; int type = CKM_DES3_CBC; SECItem keyid = { 0, NULL, 0 }; diff --git a/security/nss/cmd/httpserv/httpserv.c b/security/nss/cmd/httpserv/httpserv.c index 7cf28c65a..71e2ab88d 100644 --- a/security/nss/cmd/httpserv/httpserv.c +++ b/security/nss/cmd/httpserv/httpserv.c @@ -682,6 +682,7 @@ handle_connection( } if (arena) { PORT_FreeArena(arena, PR_FALSE); + arena = NULL; } if (!request || !request->tbsRequest || !request->tbsRequest->requestList || @@ -753,11 +754,11 @@ handle_connection( { PRTime now = PR_Now(); - PLArenaPool *arena = NULL; CERTOCSPSingleResponse *sr; CERTOCSPSingleResponse **singleResponses; SECItem *ocspResponse; + PORT_Assert(!arena); arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (unknown) { @@ -787,8 +788,8 @@ handle_connection( } else { PR_Write(ssl_sock, outOcspHeader, strlen(outOcspHeader)); PR_Write(ssl_sock, ocspResponse->data, ocspResponse->len); - PORT_FreeArena(arena, PR_FALSE); } + PORT_FreeArena(arena, PR_FALSE); } CERT_DestroyOCSPRequest(request); break; @@ -1357,7 +1358,6 @@ main(int argc, char **argv) caRevoIter = &caRevoInfos->link; do { PRFileDesc *inFile; - int rv = SECFailure; SECItem crlDER; crlDER.data = NULL; @@ -1413,11 +1413,9 @@ main(int argc, char **argv) if (provideOcsp) { if (caRevoInfos) { - PRCList *caRevoIter; - caRevoIter = &caRevoInfos->link; do { - caRevoInfo *revoInfo = (caRevoInfo *)caRevoIter; + revoInfo = (caRevoInfo *)caRevoIter; if (revoInfo->nickname) PORT_Free(revoInfo->nickname); if (revoInfo->crlFilename) diff --git a/security/nss/cmd/lib/secutil.c b/security/nss/cmd/lib/secutil.c index 2b33f8963..6be2df432 100644 --- a/security/nss/cmd/lib/secutil.c +++ b/security/nss/cmd/lib/secutil.c @@ -1528,9 +1528,9 @@ SECU_PrintDumpDerIssuerAndSerial(FILE *out, SECItem *der, char *m, unsigned int i; for (i = 0; i < c->serialNumber.len; ++i) { unsigned char *chardata = (unsigned char *)(c->serialNumber.data); - unsigned char c = *(chardata + i); + unsigned char ch = *(chardata + i); - fprintf(out, "\\x%02x", c); + fprintf(out, "\\x%02x", ch); } fprintf(out, "\" }\n"); } @@ -3137,7 +3137,7 @@ typedef enum { static int secu_PrintSignedDataSigOpt(FILE *out, SECItem *der, const char *m, int level, SECU_PPFunc inner, - SignatureOptionType withSignature) + SignatureOptionType signatureOption) { PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); CERTSignedData *sd; @@ -3164,7 +3164,7 @@ secu_PrintSignedDataSigOpt(FILE *out, SECItem *der, const char *m, } rv = (*inner)(out, &sd->data, "Data", level + 1); - if (withSignature) { + if (signatureOption == withSignature) { SECU_PrintAlgorithmID(out, &sd->signatureAlgorithm, "Signature Algorithm", level + 1); DER_ConvertBitString(&sd->signature); diff --git a/security/nss/cmd/listsuites/listsuites.c b/security/nss/cmd/listsuites/listsuites.c index 8eb2c3553..b49f2d8cf 100644 --- a/security/nss/cmd/listsuites/listsuites.c +++ b/security/nss/cmd/listsuites/listsuites.c @@ -64,9 +64,7 @@ main(int argc, char **argv) /* disable all the SSL3 cipher suites */ for (i = 0; i < SSL_NumImplementedCiphers; i++) { PRUint16 suite = cipherSuites[i]; - SECStatus rv; PRBool enabled; - PRErrorCode err; SSLCipherSuiteInfo info; rv = SSL_CipherPrefGetDefault(suite, &enabled); diff --git a/security/nss/cmd/lowhashtest/lowhashtest.c b/security/nss/cmd/lowhashtest/lowhashtest.c index 29d6ff4fd..fcc06a86e 100644 --- a/security/nss/cmd/lowhashtest/lowhashtest.c +++ b/security/nss/cmd/lowhashtest/lowhashtest.c @@ -390,7 +390,7 @@ testSHA512(NSSLOWInitContext *initCtx) } static void -Usage(char *progName) +Usage() { fprintf(stderr, "Usage: %s [algorithm]\n", progName); @@ -436,7 +436,7 @@ main(int argc, char **argv) rv += testSHA512(initCtx); } else { SECU_PrintError(progName, "Unsupported hash type %s\n", argv[0]); - Usage(progName); + Usage(); } NSSLOW_Shutdown(initCtx); diff --git a/security/nss/cmd/modutil/install-ds.c b/security/nss/cmd/modutil/install-ds.c index 030568762..576839f8f 100644 --- a/security/nss/cmd/modutil/install-ds.c +++ b/security/nss/cmd/modutil/install-ds.c @@ -88,11 +88,11 @@ static const char* errString[] = { static char* PR_Strdup(const char* str); -#define PAD(x) \ - { \ - int i; \ - for (i = 0; i < x; i++) \ - printf(" "); \ +#define PAD(x) \ + { \ + int pad_i; \ + for (pad_i = 0; pad_i < (x); pad_i++) \ + printf(" "); \ } #define PADINC 4 diff --git a/security/nss/cmd/mpitests/mpi-test.c b/security/nss/cmd/mpitests/mpi-test.c index 3a1f5d6c2..b7953b6f6 100644 --- a/security/nss/cmd/mpitests/mpi-test.c +++ b/security/nss/cmd/mpitests/mpi-test.c @@ -375,14 +375,14 @@ void reason(char *fmt, ...); char g_intbuf[4096]; /* buffer for integer comparison */ char a_intbuf[4096]; /* buffer for integer comparison */ int g_verbose = 1; /* print out reasons for failure? */ -int res; - -#define IFOK(x) \ - { \ - if (MP_OKAY > (res = (x))) { \ - reason("test %s failed: error %d\n", #x, res); \ - return 1; \ - } \ + +#define IFOK(x) \ + { \ + int ifok_res = (x); \ + if (MP_OKAY > ifok_res) { \ + reason("test %s failed: error %d\n", #x, ifok_res); \ + return 1; \ + } \ } int diff --git a/security/nss/cmd/ocspclnt/ocspclnt.c b/security/nss/cmd/ocspclnt/ocspclnt.c index afcb7e13f..0927f8ef6 100644 --- a/security/nss/cmd/ocspclnt/ocspclnt.c +++ b/security/nss/cmd/ocspclnt/ocspclnt.c @@ -38,7 +38,7 @@ char *program_name; static void -synopsis(char *program_name) +synopsis(char *progname) { PRFileDesc *pr_stderr; @@ -46,44 +46,44 @@ synopsis(char *program_name) PR_fprintf(pr_stderr, "Usage:"); PR_fprintf(pr_stderr, "\t%s -p [-d <dir>]\n", - program_name); + progname); PR_fprintf(pr_stderr, "\t%s -P [-d <dir>]\n", - program_name); + progname); PR_fprintf(pr_stderr, "\t%s -r <name> [-a] [-L] [-s <name>] [-d <dir>]\n", - program_name); + progname); PR_fprintf(pr_stderr, "\t%s -R <name> [-a] [-l <location>] [-s <name>] [-d <dir>]\n", - program_name); + progname); PR_fprintf(pr_stderr, "\t%s -S <name> [-a] [-l <location> -t <name>]\n", - program_name); + progname); PR_fprintf(pr_stderr, "\t\t [-s <name>] [-w <time>] [-d <dir>]\n"); PR_fprintf(pr_stderr, "\t%s -V <name> [-a] -u <usage> [-l <location> -t <name>]\n", - program_name); + progname); PR_fprintf(pr_stderr, "\t\t [-s <name>] [-w <time>] [-d <dir>]\n"); } static void -short_usage(char *program_name) +short_usage(char *progname) { PR_fprintf(PR_STDERR, "Type %s -H for more detailed descriptions\n", - program_name); - synopsis(program_name); + progname); + synopsis(progname); } static void -long_usage(char *program_name) +long_usage(char *progname) { PRFileDesc *pr_stderr; pr_stderr = PR_STDERR; - synopsis(program_name); + synopsis(progname); PR_fprintf(pr_stderr, "\nCommands (must specify exactly one):\n"); PR_fprintf(pr_stderr, " %-13s Pretty-print a binary request read from stdin\n", diff --git a/security/nss/cmd/ocspresp/ocspresp.c b/security/nss/cmd/ocspresp/ocspresp.c index 632623c97..d18d32e18 100644 --- a/security/nss/cmd/ocspresp/ocspresp.c +++ b/security/nss/cmd/ocspresp/ocspresp.c @@ -194,8 +194,8 @@ main(int argc, char **argv) &obtainedSignerCert, caCert)); #ifdef DEBUG { - SECStatus rv = CERT_GetOCSPStatusForCertID(certHandle, decodedRev, cid, - obtainedSignerCert, now); + rv = CERT_GetOCSPStatusForCertID(certHandle, decodedRev, cid, + obtainedSignerCert, now); PORT_Assert(rv == SECFailure); PORT_Assert(PORT_GetError() == SEC_ERROR_REVOKED_CERTIFICATE); } @@ -211,7 +211,7 @@ main(int argc, char **argv) decodedFail = CERT_DecodeOCSPResponse(encodedFail); #ifdef DEBUG { - SECStatus rv = CERT_GetOCSPResponseStatus(decodedFail); + rv = CERT_GetOCSPResponseStatus(decodedFail); PORT_Assert(rv == SECFailure); PORT_Assert(PORT_GetError() == SEC_ERROR_OCSP_TRY_SERVER_LATER); } diff --git a/security/nss/cmd/pk12util/pk12util.c b/security/nss/cmd/pk12util/pk12util.c index 70454a0d8..5884713e3 100644 --- a/security/nss/cmd/pk12util/pk12util.c +++ b/security/nss/cmd/pk12util/pk12util.c @@ -28,7 +28,7 @@ static PRBool pk12uForceUnicode; PRIntn pk12uErrno = 0; static void -Usage(char *progName) +Usage() { #define FPS PR_fprintf(PR_STDERR, FPS "Usage: %s -i importfile [-d certdir] [-P dbprefix] [-h tokenname]\n", @@ -1020,26 +1020,26 @@ main(int argc, char **argv) rv = SECU_ParseCommandLine(argc, argv, progName, &pk12util); if (rv != SECSuccess) - Usage(progName); + Usage(); pk12_debugging = pk12util.options[opt_Debug].activated; if ((pk12util.options[opt_Import].activated + pk12util.options[opt_Export].activated + pk12util.options[opt_List].activated) != 1) { - Usage(progName); + Usage(); } if (pk12util.options[opt_Export].activated && !pk12util.options[opt_Nickname].activated) { - Usage(progName); + Usage(); } rv = NSS_OptionGet(__NSS_PKCS12_DECODE_FORCE_UNICODE, &forceUnicode); if (rv != SECSuccess) { SECU_PrintError(progName, "Failed to get NSS_PKCS12_DECODE_FORCE_UNICODE option"); - Usage(progName); + Usage(); } pk12uForceUnicode = forceUnicode; @@ -1144,7 +1144,7 @@ main(int argc, char **argv) P12U_ListPKCS12File(import_file, slot, &slotPw, &p12FilePw); } else { - Usage(progName); + Usage(); pk12uErrno = PK12UERR_USAGE; } diff --git a/security/nss/cmd/pk1sign/pk1sign.c b/security/nss/cmd/pk1sign/pk1sign.c index 085aa1659..d5524c149 100644 --- a/security/nss/cmd/pk1sign/pk1sign.c +++ b/security/nss/cmd/pk1sign/pk1sign.c @@ -178,7 +178,7 @@ loser: SECKEY_DestroyPrivateKey(privKey); } if (data) { - PORT_Free(data); + PR_Free(data); } PORT_FreeArena(arena, PR_FALSE); diff --git a/security/nss/cmd/rsaperf/rsaperf.c b/security/nss/cmd/rsaperf/rsaperf.c index 2bb23856e..7762a465b 100644 --- a/security/nss/cmd/rsaperf/rsaperf.c +++ b/security/nss/cmd/rsaperf/rsaperf.c @@ -313,7 +313,7 @@ main(int argc, char **argv) char *slotname = NULL; long keybits = 0; RSAOp fn; - void *rsaKey = NULL; + void *rsaKeyPtr = NULL; PLOptState *optstate; PLOptStatus optstatus; long iters = DEFAULT_ITERS; @@ -464,7 +464,7 @@ main(int argc, char **argv) if (doPub) { /* do public key ops */ fn = (RSAOp)PK11_PublicKeyOp; - rsaKey = (void *)pubHighKey; + rsaKeyPtr = (void *)pubHighKey; kh = PK11_ImportPublicKey(cert->slot, pubHighKey, PR_FALSE); if (CK_INVALID_HANDLE == kh) { @@ -489,7 +489,7 @@ main(int argc, char **argv) fn = (RSAOp)PK11_PrivateKeyOp; keys.privKey = privHighKey; keys.pubKey = pubHighKey; - rsaKey = (void *)&keys; + rsaKeyPtr = (void *)&keys; printf("Using PKCS#11 for RSA decryption with token %s.\n", PK11_GetTokenName(privHighKey->pkcs11Slot)); } @@ -537,13 +537,13 @@ main(int argc, char **argv) if (doPub) { /* do public key operations */ fn = (RSAOp)PK11_PublicKeyOp; - rsaKey = (void *)pubHighKey; + rsaKeyPtr = (void *)pubHighKey; } else { /* do private key operations */ fn = (RSAOp)PK11_PrivateKeyOp; keys.privKey = privHighKey; keys.pubKey = pubHighKey; - rsaKey = (void *)&keys; + rsaKeyPtr = (void *)&keys; } } else @@ -574,7 +574,7 @@ main(int argc, char **argv) pe.data = &pubEx[0]; pe.type = siBuffer; - rsaKey = RSA_NewKey(keybits, &pe); + rsaKeyPtr = RSA_NewKey(keybits, &pe); fprintf(stderr, "Keygen completed.\n"); } else { /* use a hardcoded key */ @@ -589,31 +589,31 @@ main(int argc, char **argv) if (doPub) { /* do public key operations */ fn = (RSAOp)RSA_PublicKeyOp; - if (rsaKey) { + if (rsaKeyPtr) { /* convert the RSAPrivateKey to RSAPublicKey */ pubKeyStr.arena = NULL; - pubKeyStr.modulus = ((RSAPrivateKey *)rsaKey)->modulus; + pubKeyStr.modulus = ((RSAPrivateKey *)rsaKeyPtr)->modulus; pubKeyStr.publicExponent = - ((RSAPrivateKey *)rsaKey)->publicExponent; - rsaKey = &pubKeyStr; + ((RSAPrivateKey *)rsaKeyPtr)->publicExponent; + rsaKeyPtr = &pubKeyStr; } else { /* convert NSSLOWKeyPublicKey to RSAPublicKey */ - rsaKey = (void *)(&pubKey->u.rsa); + rsaKeyPtr = (void *)(&pubKey->u.rsa); } - PORT_Assert(rsaKey); + PORT_Assert(rsaKeyPtr); } else { /* do private key operations */ fn = (RSAOp)RSA_PrivateKeyOp; if (privKey) { /* convert NSSLOWKeyPrivateKey to RSAPrivateKey */ - rsaKey = (void *)(&privKey->u.rsa); + rsaKeyPtr = (void *)(&privKey->u.rsa); } - PORT_Assert(rsaKey); + PORT_Assert(rsaKeyPtr); } } memset(buf, 1, sizeof buf); - rv = fn(rsaKey, buf2, buf); + rv = fn(rsaKeyPtr, buf2, buf); if (rv != SECSuccess) { PRErrorCode errNum; const char *errStr = NULL; @@ -638,7 +638,7 @@ main(int argc, char **argv) runDataArr[i]->fn = fn; runDataArr[i]->buf = buf; runDataArr[i]->doIters = &doIters; - runDataArr[i]->rsaKey = rsaKey; + runDataArr[i]->rsaKey = rsaKeyPtr; runDataArr[i]->seconds = seconds; runDataArr[i]->iters = iters; threadsArr[i] = diff --git a/security/nss/cmd/selfserv/selfserv.c b/security/nss/cmd/selfserv/selfserv.c index fac428e10..c372ec9b8 100644 --- a/security/nss/cmd/selfserv/selfserv.c +++ b/security/nss/cmd/selfserv/selfserv.c @@ -57,7 +57,7 @@ int NumSidCacheEntries = 1024; -static int handle_connection(PRFileDesc *, PRFileDesc *, int); +static int handle_connection(PRFileDesc *, PRFileDesc *); static const char envVarName[] = { SSL_ENV_VAR_NAME }; static const char inheritableSockName[] = { "SELFSERV_LISTEN_SOCKET" }; @@ -509,7 +509,6 @@ typedef struct jobStr { PRCList link; PRFileDesc *tcp_sock; PRFileDesc *model_sock; - int requestCert; } JOB; static PZLock *qLock; /* this lock protects all data immediately below */ @@ -541,7 +540,7 @@ setupJobs(int maxJobs) return SECSuccess; } -typedef int startFn(PRFileDesc *a, PRFileDesc *b, int c); +typedef int startFn(PRFileDesc *a, PRFileDesc *b); typedef enum { rs_idle = 0, rs_running = 1, @@ -550,7 +549,6 @@ typedef enum { rs_idle = 0, typedef struct perThreadStr { PRFileDesc *a; PRFileDesc *b; - int c; int rv; startFn *startFunc; PRThread *prThread; @@ -564,7 +562,7 @@ thread_wrapper(void *arg) { perThread *slot = (perThread *)arg; - slot->rv = (*slot->startFunc)(slot->a, slot->b, slot->c); + slot->rv = (*slot->startFunc)(slot->a, slot->b); /* notify the thread exit handler. */ PZ_Lock(qLock); @@ -575,7 +573,7 @@ thread_wrapper(void *arg) } int -jobLoop(PRFileDesc *a, PRFileDesc *b, int c) +jobLoop(PRFileDesc *a, PRFileDesc *b) { PRCList *myLink = 0; JOB *myJob; @@ -595,8 +593,7 @@ jobLoop(PRFileDesc *a, PRFileDesc *b, int c) /* myJob will be null when stopping is true and jobQ is empty */ if (!myJob) break; - handle_connection(myJob->tcp_sock, myJob->model_sock, - myJob->requestCert); + handle_connection(myJob->tcp_sock, myJob->model_sock); PZ_Lock(qLock); PR_APPEND_LINK(myLink, &freeJobs); PZ_NotifyCondVar(freeListNotEmptyCv); @@ -609,7 +606,6 @@ launch_threads( startFn *startFunc, PRFileDesc *a, PRFileDesc *b, - int c, PRBool local) { int i; @@ -645,7 +641,6 @@ launch_threads( slot->state = rs_running; slot->a = a; slot->b = b; - slot->c = c; slot->startFunc = startFunc; slot->prThread = PR_CreateThread(PR_USER_THREAD, thread_wrapper, slot, PR_PRIORITY_NORMAL, @@ -893,8 +888,7 @@ int /* returns count */ int do_writes( PRFileDesc *ssl_sock, - PRFileDesc *model_sock, - int requestCert) + PRFileDesc *model_sock) { int sent = 0; int count = 0; @@ -925,8 +919,7 @@ do_writes( static int handle_fdx_connection( PRFileDesc *tcp_sock, - PRFileDesc *model_sock, - int requestCert) + PRFileDesc *model_sock) { PRFileDesc *ssl_sock = NULL; SECStatus result; @@ -960,8 +953,7 @@ handle_fdx_connection( lockedVars_AddToCount(&lv, 1); /* Attempt to launch the writer thread. */ - result = launch_thread(do_writes, ssl_sock, (PRFileDesc *)&lv, - requestCert); + result = launch_thread(do_writes, ssl_sock, (PRFileDesc *)&lv); if (result == SECSuccess) do { @@ -1093,7 +1085,7 @@ makeCorruptedOCSPResponse(PLArenaPool *arena) } SECItemArray * -makeSignedOCSPResponse(PLArenaPool *arena, ocspStaplingModeType osm, +makeSignedOCSPResponse(PLArenaPool *arena, CERTCertificate *cert, secuPWData *pwdata) { SECItemArray *result = NULL; @@ -1117,7 +1109,7 @@ makeSignedOCSPResponse(PLArenaPool *arena, ocspStaplingModeType osm, nextUpdate = now + (PRTime)60 * 60 * 24 * PR_USEC_PER_SEC; /* plus 1 day */ - switch (osm) { + switch (ocspStaplingMode) { case osm_good: case osm_badsig: sr = CERT_CreateOCSPSingleResponseGood(arena, cid, now, @@ -1150,7 +1142,7 @@ makeSignedOCSPResponse(PLArenaPool *arena, ocspStaplingModeType osm, singleResponses[1] = NULL; ocspResponse = CERT_CreateEncodedOCSPSuccessResponse(arena, - (osm == osm_badsig) + (ocspStaplingMode == osm_badsig) ? NULL : ca, ocspResponderID_byName, now, singleResponses, @@ -1175,7 +1167,7 @@ makeSignedOCSPResponse(PLArenaPool *arena, ocspStaplingModeType osm, } void -setupCertStatus(PLArenaPool *arena, enum ocspStaplingModeEnum ocspStaplingMode, +setupCertStatus(PLArenaPool *arena, CERTCertificate *cert, int index, secuPWData *pwdata) { if (ocspStaplingMode == osm_random) { @@ -1213,7 +1205,7 @@ setupCertStatus(PLArenaPool *arena, enum ocspStaplingModeEnum ocspStaplingMode, case osm_unknown: case osm_badsig: multiOcspResponses = - makeSignedOCSPResponse(arena, ocspStaplingMode, cert, + makeSignedOCSPResponse(arena, cert, pwdata); break; case osm_corrupted: @@ -1236,10 +1228,7 @@ setupCertStatus(PLArenaPool *arena, enum ocspStaplingModeEnum ocspStaplingMode, } int -handle_connection( - PRFileDesc *tcp_sock, - PRFileDesc *model_sock, - int requestCert) +handle_connection(PRFileDesc *tcp_sock, PRFileDesc *model_sock) { PRFileDesc *ssl_sock = NULL; PRFileDesc *local_file_fd = NULL; @@ -1272,7 +1261,6 @@ handle_connection( VLOG(("selfserv: handle_connection: starting\n")); if (useModelSocket && model_sock) { - SECStatus rv; ssl_sock = SSL_ImportFD(model_sock, tcp_sock); if (!ssl_sock) { errWarn("SSL_ImportFD with model"); @@ -1588,8 +1576,7 @@ sigusr1_handler(int sig) SECStatus do_accepts( PRFileDesc *listen_sock, - PRFileDesc *model_sock, - int requestCert) + PRFileDesc *model_sock) { PRNetAddr addr; PRErrorCode perr; @@ -1659,7 +1646,6 @@ do_accepts( JOB *myJob = (JOB *)myLink; myJob->tcp_sock = tcp_sock; myJob->model_sock = model_sock; - myJob->requestCert = requestCert; } PR_APPEND_LINK(myLink, &jobQ); @@ -1818,7 +1804,6 @@ handshakeCallback(PRFileDesc *fd, void *client_data) void server_main( PRFileDesc *listen_sock, - int requestCert, SECKEYPrivateKey **privKey, CERTCertificate **cert, const char *expectedHostNameVal) @@ -2021,7 +2006,7 @@ server_main( /* end of ssl configuration. */ /* Now, do the accepting, here in the main thread. */ - rv = do_accepts(listen_sock, model_sock, requestCert); + rv = do_accepts(listen_sock, model_sock); terminateWorkerThreads(); @@ -2654,9 +2639,8 @@ main(int argc, char **argv) } } if (cipher > 0) { - SECStatus status; - status = SSL_CipherPrefSetDefault(cipher, SSL_ALLOWED); - if (status != SECSuccess) + rv = SSL_CipherPrefSetDefault(cipher, SSL_ALLOWED); + if (rv != SECSuccess) SECU_PrintError(progName, "SSL_CipherPrefSet()"); } else { fprintf(stderr, @@ -2684,7 +2668,7 @@ main(int argc, char **argv) exit(11); } if (privKey[i]->keyType != ecKey) - setupCertStatus(certStatusArena, ocspStaplingMode, cert[i], i, &pwdata); + setupCertStatus(certStatusArena, cert[i], i, &pwdata); } if (configureWeakDHE > 0) { @@ -2697,7 +2681,7 @@ main(int argc, char **argv) } /* allocate the array of thread slots, and launch the worker threads. */ - rv = launch_threads(&jobLoop, 0, 0, requestCert, useLocalThreads); + rv = launch_threads(&jobLoop, 0, 0, useLocalThreads); if (rv == SECSuccess && logStats) { loggerThread = PR_CreateThread(PR_SYSTEM_THREAD, @@ -2712,7 +2696,7 @@ main(int argc, char **argv) } if (rv == SECSuccess) { - server_main(listen_sock, requestCert, privKey, cert, + server_main(listen_sock, privKey, cert, expectedHostNameVal); } @@ -2731,7 +2715,6 @@ cleanup: } { - int i; for (i = 0; i < certNicknameIndex; i++) { if (cert[i]) { CERT_DestroyCertificate(cert[i]); diff --git a/security/nss/cmd/shlibsign/shlibsign.c b/security/nss/cmd/shlibsign/shlibsign.c index d93fc422d..221d1e67e 100644 --- a/security/nss/cmd/shlibsign/shlibsign.c +++ b/security/nss/cmd/shlibsign/shlibsign.c @@ -148,7 +148,7 @@ writeItem(PRFileDesc *fd, CK_VOID_PTR pValue, return PR_FAILURE; } bytesWritten = PR_Write(fd, pValue, ulValueLen); - if (bytesWritten != ulValueLen) { + if (bytesWritten < 0 || (CK_ULONG)bytesWritten != ulValueLen) { lperror(file); return PR_FAILURE; } diff --git a/security/nss/cmd/signtool/javascript.c b/security/nss/cmd/signtool/javascript.c index ffff2db59..58869aa61 100644 --- a/security/nss/cmd/signtool/javascript.c +++ b/security/nss/cmd/signtool/javascript.c @@ -1300,7 +1300,6 @@ extract_js(char *filename) * Now we have a stream of tags and text. Go through and deal with each. */ for (curitem = head; curitem; curitem = curitem->next) { - TagItem *tagp = NULL; AVPair *pairp = NULL; char *src = NULL, *id = NULL, *codebase = NULL; PRBool hasEventHandler = PR_FALSE; @@ -1669,11 +1668,14 @@ loser: * Returns PR_SUCCESS if the directory is present, PR_FAILURE otherwise. */ static PRStatus -ensureExists(char *base, char *path) +ensureExists(char *basepath, char *path) { char fn[FNSIZE]; PRDir *dir; - sprintf(fn, "%s/%s", base, path); + int c = snprintf(fn, sizeof(fn), "%s/%s", basepath, path); + if (c >= sizeof(fn)) { + return PR_FAILURE; + } /*PR_fprintf(outputFD, "Trying to open directory %s.\n", fn);*/ diff --git a/security/nss/cmd/signtool/sign.c b/security/nss/cmd/signtool/sign.c index 6f8e43946..534530947 100644 --- a/security/nss/cmd/signtool/sign.c +++ b/security/nss/cmd/signtool/sign.c @@ -175,16 +175,16 @@ typedef struct { * */ int -SignAllArc(char *jartree, char *keyName, int javascript, char *metafile, - char *install_script, int optimize, PRBool recurse) +SignAllArc(char *jartree, char *keyName, int javascript, char *metafilename, + char *install_script, int optimize_level, PRBool recurse) { SignArcInfo info; info.keyName = keyName; info.javascript = javascript; - info.metafile = metafile; + info.metafile = metafilename; info.install_script = install_script; - info.optimize = optimize; + info.optimize = optimize_level; return foreach (jartree, "", sign_all_arc_fn, recurse, PR_TRUE /*include dirs*/, (void *)&info); @@ -194,7 +194,7 @@ static int sign_all_arc_fn(char *relpath, char *basedir, char *reldir, char *filename, void *arg) { - char *zipfile = NULL; + char *zipfilename = NULL; char *arc = NULL, *archive = NULL; int retval = 0; SignArcInfo *infop = (SignArcInfo *)arg; @@ -212,8 +212,8 @@ sign_all_arc_fn(char *relpath, char *basedir, char *reldir, char *filename, } archive = PR_smprintf("%s/%s", basedir, relpath); - zipfile = PL_strdup(archive); - arc = PORT_Strrchr(zipfile, '.'); + zipfilename = PL_strdup(archive); + arc = PORT_Strrchr(zipfilename, '.'); if (arc == NULL) { PR_fprintf(errorFD, "%s: Internal failure\n", PROGRAM_NAME); @@ -225,17 +225,17 @@ sign_all_arc_fn(char *relpath, char *basedir, char *reldir, char *filename, PL_strcpy(arc, ".jar"); if (verbosity >= 0) { - PR_fprintf(outputFD, "\nsigning: %s\n", zipfile); + PR_fprintf(outputFD, "\nsigning: %s\n", zipfilename); } - retval = SignArchive(archive, infop->keyName, zipfile, + retval = SignArchive(archive, infop->keyName, zipfilename, infop->javascript, infop->metafile, infop->install_script, infop->optimize, PR_TRUE /* recurse */); } finish: if (archive) PR_Free(archive); - if (zipfile) - PR_Free(zipfile); + if (zipfilename) + PR_Free(zipfilename); return retval; } @@ -707,8 +707,8 @@ SignFile(FILE *outFile, FILE *inFile, CERTCertificate *cert) static int generate_SF_file(char *manifile, char *who) { - FILE *sf; - FILE *mf; + FILE *sfFile; + FILE *mfFile; long r1, r2, r3; char whofile[FNSIZE]; char *buf, *name = NULL; @@ -718,12 +718,12 @@ generate_SF_file(char *manifile, char *who) strcpy(whofile, who); - if ((mf = fopen(manifile, "rb")) == NULL) { + if ((mfFile = fopen(manifile, "rb")) == NULL) { perror(manifile); exit(ERRX); } - if ((sf = fopen(whofile, "wb")) == NULL) { + if ((sfFile = fopen(whofile, "wb")) == NULL) { perror(who); exit(ERRX); } @@ -736,11 +736,11 @@ generate_SF_file(char *manifile, char *who) if (buf == NULL || name == NULL) out_of_memory(); - fprintf(sf, "Signature-Version: 1.0\n"); - fprintf(sf, "Created-By: %s\n", CREATOR); - fprintf(sf, "Comments: %s\n", BREAKAGE); + fprintf(sfFile, "Signature-Version: 1.0\n"); + fprintf(sfFile, "Created-By: %s\n", CREATOR); + fprintf(sfFile, "Comments: %s\n", BREAKAGE); - if (fgets(buf, BUFSIZ, mf) == NULL) { + if (fgets(buf, BUFSIZ, mfFile) == NULL) { PR_fprintf(errorFD, "%s: empty manifest file!\n", PROGRAM_NAME); errorCount++; exit(ERRX); @@ -752,15 +752,15 @@ generate_SF_file(char *manifile, char *who) exit(ERRX); } - fseek(mf, 0L, SEEK_SET); + fseek(mfFile, 0L, SEEK_SET); /* Process blocks of headers, and calculate their hashen */ while (1) { /* Beginning range */ - r1 = ftell(mf); + r1 = ftell(mfFile); - if (fgets(name, BUFSIZ, mf) == NULL) + if (fgets(name, BUFSIZ, mfFile) == NULL) break; line++; @@ -774,46 +774,46 @@ generate_SF_file(char *manifile, char *who) } r2 = r1; - while (fgets(buf, BUFSIZ, mf)) { + while (fgets(buf, BUFSIZ, mfFile)) { if (*buf == 0 || *buf == '\n' || *buf == '\r') break; line++; /* Ending range for hashing */ - r2 = ftell(mf); + r2 = ftell(mfFile); } - r3 = ftell(mf); + r3 = ftell(mfFile); if (r1) { - fprintf(sf, "\n"); - fprintf(sf, "%s", name); + fprintf(sfFile, "\n"); + fprintf(sfFile, "%s", name); } - calculate_MD5_range(mf, r1, r2, &dig); + calculate_MD5_range(mfFile, r1, r2, &dig); if (optimize == 0) { - fprintf(sf, "Digest-Algorithms: MD5 SHA1\n"); + fprintf(sfFile, "Digest-Algorithms: MD5 SHA1\n"); md5 = BTOA_DataToAscii(dig.md5, MD5_LENGTH); - fprintf(sf, "MD5-Digest: %s\n", md5); + fprintf(sfFile, "MD5-Digest: %s\n", md5); PORT_Free(md5); } sha1 = BTOA_DataToAscii(dig.sha1, SHA1_LENGTH); - fprintf(sf, "SHA1-Digest: %s\n", sha1); + fprintf(sfFile, "SHA1-Digest: %s\n", sha1); PORT_Free(sha1); /* restore normalcy after changing offset position */ - fseek(mf, r3, SEEK_SET); + fseek(mfFile, r3, SEEK_SET); } PORT_Free(buf); PORT_Free(name); - fclose(sf); - fclose(mf); + fclose(sfFile); + fclose(mfFile); return 0; } diff --git a/security/nss/cmd/signtool/zip.c b/security/nss/cmd/signtool/zip.c index 35d5f5733..aeb5d6c54 100644 --- a/security/nss/cmd/signtool/zip.c +++ b/security/nss/cmd/signtool/zip.c @@ -129,7 +129,7 @@ handle_zerror(int err, char *msg) * been opened with JzipOpen. */ int -JzipAdd(char *fullname, char *filename, ZIPfile *zipfile, int compression_level) +JzipAdd(char *fullname, char *filename, ZIPfile *zipfile, int lvl) { ZIPentry *entry; PRFileDesc *readfp; @@ -319,7 +319,7 @@ JzipAdd(char *fullname, char *filename, ZIPfile *zipfile, int compression_level) * It causes zlib to leave out its headers and footers, which don't * work in PKZIP files. */ - err = deflateInit2(&zstream, compression_level, Z_DEFLATED, + err = deflateInit2(&zstream, lvl, Z_DEFLATED, -MAX_WBITS, 8 /*default*/, Z_DEFAULT_STRATEGY); if (err != Z_OK) { handle_zerror(err, zstream.msg); diff --git a/security/nss/cmd/smimetools/cmsutil.c b/security/nss/cmd/smimetools/cmsutil.c index fe17f26a4..7106521c1 100644 --- a/security/nss/cmd/smimetools/cmsutil.c +++ b/security/nss/cmd/smimetools/cmsutil.c @@ -68,7 +68,7 @@ DigestFile(PLArenaPool *poolp, SECItem ***digests, SECItem *input, } static void -Usage(char *progName) +Usage(void) { fprintf(stderr, "Usage: %s [-C|-D|-E|-O|-S] [<options>] [-d dbdir] [-u certusage]\n" @@ -280,7 +280,6 @@ decode(FILE *out, SECItem *input, const struct decodeOptionsStr *decodeOptions) ** or might be an invalid message, such as a QA test message ** or a message from an attacker. */ - SECStatus rv; rv = NSS_CMSSignedData_VerifyCertsOnly(sigd, decodeOptions->options->certHandle, decodeOptions->options->certUsage); @@ -1127,7 +1126,7 @@ main(int argc, char **argv) fprintf(stderr, "%s: option -G only supported with option -S.\n", progName); - Usage(progName); + Usage(); exit(1); } signOptions.signingTime = PR_TRUE; @@ -1137,7 +1136,7 @@ main(int argc, char **argv) fprintf(stderr, "%s: option -H only supported with option -S.\n", progName); - Usage(progName); + Usage(); exit(1); } decodeOptions.suppressContent = PR_TRUE; @@ -1167,7 +1166,7 @@ main(int argc, char **argv) fprintf(stderr, "%s: option -N only supported with option -S.\n", progName); - Usage(progName); + Usage(); exit(1); } signOptions.nickname = PORT_Strdup(optstate->value); @@ -1180,7 +1179,7 @@ main(int argc, char **argv) fprintf(stderr, "%s: option -P only supported with option -S.\n", progName); - Usage(progName); + Usage(); exit(1); } signOptions.smimeProfile = PR_TRUE; @@ -1193,7 +1192,7 @@ main(int argc, char **argv) fprintf(stderr, "%s: option -T only supported with option -S.\n", progName); - Usage(progName); + Usage(); exit(1); } signOptions.detached = PR_TRUE; @@ -1203,7 +1202,7 @@ main(int argc, char **argv) fprintf(stderr, "%s: option -Y only supported with option -S.\n", progName); - Usage(progName); + Usage(); exit(1); } signOptions.encryptionKeyPreferenceNick = strdup(optstate->value); @@ -1214,7 +1213,7 @@ main(int argc, char **argv) fprintf(stderr, "%s: option -b only supported with option -D.\n", progName); - Usage(progName); + Usage(); exit(1); } batch = PR_TRUE; @@ -1225,7 +1224,7 @@ main(int argc, char **argv) fprintf(stderr, "%s: option -c only supported with option -D.\n", progName); - Usage(progName); + Usage(); exit(1); } contentFile = PR_Open(optstate->value, PR_RDONLY, 006600); @@ -1261,7 +1260,7 @@ main(int argc, char **argv) fprintf(stderr, "%s: option -h only supported with option -D.\n", progName); - Usage(progName); + Usage(); exit(1); } decodeOptions.headerLevel = atoi(optstate->value); @@ -1288,7 +1287,7 @@ main(int argc, char **argv) fprintf(stderr, "%s: option -k only supported with option -D.\n", progName); - Usage(progName); + Usage(); exit(1); } decodeOptions.keepCerts = PR_TRUE; @@ -1299,7 +1298,7 @@ main(int argc, char **argv) fprintf(stderr, "%s: option -n only supported with option -D.\n", progName); - Usage(progName); + Usage(); exit(1); } decodeOptions.suppressContent = PR_TRUE; @@ -1315,7 +1314,7 @@ main(int argc, char **argv) case 'p': if (!optstate->value) { fprintf(stderr, "%s: option -p must have a value.\n", progName); - Usage(progName); + Usage(); exit(1); } @@ -1325,7 +1324,7 @@ main(int argc, char **argv) case 'f': if (!optstate->value) { fprintf(stderr, "%s: option -f must have a value.\n", progName); - Usage(progName); + Usage(); exit(1); } @@ -1335,7 +1334,7 @@ main(int argc, char **argv) case 'r': if (!optstate->value) { fprintf(stderr, "%s: option -r must have a value.\n", progName); - Usage(progName); + Usage(); exit(1); } envelopeOptions.recipients = ptrarray; @@ -1368,11 +1367,11 @@ main(int argc, char **argv) } } if (status == PL_OPT_BAD) - Usage(progName); + Usage(); PL_DestroyOptState(optstate); if (mode == UNKNOWN) - Usage(progName); + Usage(); if (mode != CERTSONLY && !batch) { rv = SECU_FileToItem(&input, inFile); @@ -1529,7 +1528,7 @@ main(int argc, char **argv) break; default: fprintf(stderr, "One of options -D, -S or -E must be set.\n"); - Usage(progName); + Usage(); exitstatus = 1; } diff --git a/security/nss/cmd/strsclnt/strsclnt.c b/security/nss/cmd/strsclnt/strsclnt.c index 7d259bd0a..bba53efac 100644 --- a/security/nss/cmd/strsclnt/strsclnt.c +++ b/security/nss/cmd/strsclnt/strsclnt.c @@ -137,7 +137,7 @@ SECItem bigBuf; fprintf static void -Usage(const char *progName) +Usage(void) { fprintf(stderr, "Usage: %s [-n nickname] [-p port] [-d dbdir] [-c connections]\n" @@ -260,7 +260,6 @@ void printSecurityInfo(PRFileDesc *fd) { CERTCertificate *cert = NULL; - SSL3Statistics *ssl3stats = SSL_GetStatistics(); SECStatus result; SSLChannelInfo channel; SSLCipherSuiteInfo suite; @@ -1095,7 +1094,6 @@ client_main( while (0 != (ndx = *cipherString)) { const char *startCipher = cipherString++; int cipher = 0; - SECStatus rv; if (ndx == ':') { cipher = hexchar_to_int(*cipherString++); @@ -1353,7 +1351,7 @@ main(int argc, char **argv) enabledVersions, &enabledVersions) != SECSuccess) { fprintf(stderr, "Bad version specified.\n"); - Usage(progName); + Usage(); } break; @@ -1431,27 +1429,27 @@ main(int argc, char **argv) case 0: /* positional parameter */ if (hostName) { - Usage(progName); + Usage(); } hostName = PL_strdup(optstate->value); break; default: case '?': - Usage(progName); + Usage(); break; } } PL_DestroyOptState(optstate); if (!hostName || status == PL_OPT_BAD) - Usage(progName); + Usage(); if (fullhs != NO_FULLHS_PERCENTAGE && (fullhs < 0 || fullhs > 100 || NoReuse)) - Usage(progName); + Usage(); if (port == 0) - Usage(progName); + Usage(); if (fileName) readBigFile(fileName); diff --git a/security/nss/cmd/symkeyutil/symkeyutil.c b/security/nss/cmd/symkeyutil/symkeyutil.c index 444456808..31ab4dda4 100644 --- a/security/nss/cmd/symkeyutil/symkeyutil.c +++ b/security/nss/cmd/symkeyutil/symkeyutil.c @@ -1034,10 +1034,10 @@ main(int argc, char **argv) char *targetName = symKeyUtil.options[opt_TargetToken].arg; PK11SymKey *newKey; PK11SymKey *symKey = FindKey(slot, name, &keyID, &pwdata); - char *keyName = PK11_GetSymKeyNickname(symKey); + char *keyName; if (!symKey) { - char *keyName = keyID.data ? BufToHex(&keyID) : PORT_Strdup(name); + keyName = keyID.data ? BufToHex(&keyID) : PORT_Strdup(name); PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n", progName, keyName, PK11_GetTokenName(slot)); PORT_Free(keyName); @@ -1061,6 +1061,7 @@ main(int argc, char **argv) PR_fprintf(PR_STDERR, "%s: Couldn't move the key \n", progName); goto shutdown; } + keyName = PK11_GetSymKeyNickname(symKey); if (keyName) { rv = PK11_SetSymKeyNickname(newKey, keyName); if (rv != SECSuccess) { diff --git a/security/nss/cmd/tstclnt/tstclnt.c b/security/nss/cmd/tstclnt/tstclnt.c index 1ad99502b..6f5a43146 100644 --- a/security/nss/cmd/tstclnt/tstclnt.c +++ b/security/nss/cmd/tstclnt/tstclnt.c @@ -51,6 +51,7 @@ #define MAX_WAIT_FOR_SERVER 600 #define WAIT_INTERVAL 100 +#define ZERO_RTT_MAX (2 << 16) #define EXIT_CODE_HANDSHAKE_FAILED 254 @@ -99,6 +100,7 @@ int renegotiationsDone = 0; PRBool initializedServerSessionCache = PR_FALSE; static char *progName; +static const char *requestFile; secuPWData pwdata = { PW_NONE, 0 }; @@ -172,7 +174,7 @@ printSecurityInfo(PRFileDesc *fd) } static void -PrintUsageHeader(const char *progName) +PrintUsageHeader() { fprintf(stderr, "Usage: %s -h host [-a 1st_hs_name ] [-a 2nd_hs_name ] [-p port]\n" @@ -186,7 +188,7 @@ PrintUsageHeader(const char *progName) } static void -PrintParameterUsage(void) +PrintParameterUsage() { fprintf(stderr, "%-20s Send different SNI name. 1st_hs_name - at first\n" "%-20s handshake, 2nd_hs_name - at second handshake.\n" @@ -259,17 +261,17 @@ PrintParameterUsage(void) } static void -Usage(const char *progName) +Usage() { - PrintUsageHeader(progName); + PrintUsageHeader(); PrintParameterUsage(); exit(1); } static void -PrintCipherUsage(const char *progName) +PrintCipherUsage() { - PrintUsageHeader(progName); + PrintUsageHeader(); fprintf(stderr, "%-20s Letter(s) chosen from the following list\n", "-c ciphers"); fprintf(stderr, @@ -303,7 +305,7 @@ milliPause(PRUint32 milli) } void -disableAllSSLCiphers(void) +disableAllSSLCiphers() { const PRUint16 *cipherSuites = SSL_GetImplementedCiphers(); int i = SSL_GetNumImplementedCiphers(); @@ -711,12 +713,18 @@ void thread_main(void *arg) { PRFileDesc *ps = (PRFileDesc *)arg; - PRFileDesc *std_in = PR_GetSpecialFD(PR_StandardInput); + PRFileDesc *std_in; int wc, rc; char buf[256]; + if (requestFile) { + std_in = PR_Open(requestFile, PR_RDONLY, 0); + } else { + std_in = PR_GetSpecialFD(PR_StandardInput); + } + #ifdef WIN32 - { + if (!requestFile) { /* Put stdin into O_BINARY mode ** or else incoming \r\n's will become \n's. */ @@ -737,6 +745,9 @@ thread_main(void *arg) wc = PR_Send(ps, buf, rc, 0, maxInterval); } while (wc == rc); PR_Close(ps); + if (requestFile) { + PR_Close(std_in); + } } #endif @@ -844,7 +855,7 @@ separateReqHeader(const PRFileDesc *outFd, const char *buf, const int nb, } else if (((c) >= 'A') && ((c) <= 'F')) { \ i = (c) - 'A' + 10; \ } else { \ - Usage(progName); \ + Usage(); \ } static SECStatus @@ -915,22 +926,22 @@ char *hs1SniHostName = NULL; char *hs2SniHostName = NULL; PRUint16 portno = 443; int override = 0; -char *requestString = NULL; -PRInt32 requestStringLen = 0; -PRBool requestSent = PR_FALSE; PRBool enableZeroRtt = PR_FALSE; +PRUint8 *zeroRttData; +unsigned int zeroRttLen = 0; PRBool enableAltServerHello = PR_FALSE; PRBool useDTLS = PR_FALSE; PRBool actAsServer = PR_FALSE; PRBool stopAfterHandshake = PR_FALSE; PRBool requestToExit = PR_FALSE; char *versionString = NULL; +PRBool handshakeComplete = PR_FALSE; static int -writeBytesToServer(PRFileDesc *s, const char *buf, int nb) +writeBytesToServer(PRFileDesc *s, const PRUint8 *buf, int nb) { SECStatus rv; - const char *bufp = buf; + const PRUint8 *bufp = buf; PRPollDesc pollDesc; pollDesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; @@ -944,12 +955,20 @@ writeBytesToServer(PRFileDesc *s, const char *buf, int nb) if (cc < 0) { PRErrorCode err = PR_GetError(); if (err != PR_WOULD_BLOCK_ERROR) { - SECU_PrintError(progName, - "write to SSL socket failed"); + SECU_PrintError(progName, "write to SSL socket failed"); return 254; } cc = 0; } + FPRINTF(stderr, "%s: %d bytes written\n", progName, cc); + if (enableZeroRtt && !handshakeComplete) { + if (zeroRttLen + cc > ZERO_RTT_MAX) { + SECU_PrintError(progName, "too much early data to save"); + return -1; + } + PORT_Memcpy(zeroRttData + zeroRttLen, bufp, cc); + zeroRttLen += cc; + } bufp += cc; nb -= cc; if (nb <= 0) @@ -969,8 +988,7 @@ writeBytesToServer(PRFileDesc *s, const char *buf, int nb) progName); cc = PR_Poll(&pollDesc, 1, PR_INTERVAL_NO_TIMEOUT); if (cc < 0) { - SECU_PrintError(progName, - "PR_Poll failed"); + SECU_PrintError(progName, "PR_Poll failed"); return -1; } FPRINTF(stderr, @@ -993,7 +1011,7 @@ handshakeCallback(PRFileDesc *fd, void *client_data) SSL_ReHandshake(fd, (renegotiationsToDo < 2)); ++renegotiationsDone; } - if (requestString && requestSent) { + if (zeroRttLen) { /* This data was sent in 0-RTT. */ SSLChannelInfo info; SECStatus rv; @@ -1003,29 +1021,30 @@ handshakeCallback(PRFileDesc *fd, void *client_data) return; if (!info.earlyDataAccepted) { - FPRINTF(stderr, "Early data rejected. Re-sending\n"); - writeBytesToServer(fd, requestString, requestStringLen); + FPRINTF(stderr, "Early data rejected. Re-sending %d bytes\n", + zeroRttLen); + writeBytesToServer(fd, zeroRttData, zeroRttLen); + zeroRttLen = 0; } } if (stopAfterHandshake) { requestToExit = PR_TRUE; } + handshakeComplete = PR_TRUE; } -#define REQUEST_WAITING (requestString && !requestSent) - static SECStatus -installServerCertificate(PRFileDesc *s, char *nickname) +installServerCertificate(PRFileDesc *s, char *nick) { CERTCertificate *cert; SECKEYPrivateKey *privKey = NULL; - if (!nickname) { + if (!nick) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } - cert = PK11_FindCertFromNickname(nickname, &pwdata); + cert = PK11_FindCertFromNickname(nick, &pwdata); if (cert == NULL) { return SECFailure; } @@ -1129,20 +1148,19 @@ connectToServer(PRFileDesc *s, PRPollDesc *pollset) } static int -run(void) +run() { int headerSeparatorPtrnId = 0; int error = 0; SECStatus rv; PRStatus status; PRInt32 filesReady; - int npds; PRFileDesc *s = NULL; PRFileDesc *std_out; - PRPollDesc pollset[2]; + PRPollDesc pollset[2] = { { 0 }, { 0 } }; PRBool wrStarted = PR_FALSE; - requestSent = PR_FALSE; + handshakeComplete = PR_FALSE; /* Create socket */ if (useDTLS) { @@ -1225,19 +1243,18 @@ run(void) cipherString++; } else { if (!isalpha(ndx)) - Usage(progName); + Usage(); ndx = tolower(ndx) - 'a'; if (ndx < PR_ARRAY_SIZE(ssl3CipherSuites)) { cipher = ssl3CipherSuites[ndx]; } } if (cipher > 0) { - SECStatus status; - status = SSL_CipherPrefSet(s, cipher, SSL_ALLOWED); - if (status != SECSuccess) + rv = SSL_CipherPrefSet(s, cipher, SSL_ALLOWED); + if (rv != SECSuccess) SECU_PrintError(progName, "SSL_CipherPrefSet()"); } else { - Usage(progName); + Usage(); } } PORT_Free(cstringSaved); @@ -1394,7 +1411,6 @@ run(void) /* Try to connect to the server */ rv = connectToServer(s, pollset); if (rv != SECSuccess) { - ; error = 1; goto done; } @@ -1406,13 +1422,18 @@ run(void) pollset[SSOCK_FD].in_flags |= (clientSpeaksFirst ? 0 : PR_POLL_READ); else pollset[SSOCK_FD].in_flags |= PR_POLL_READ; - pollset[STDIN_FD].fd = PR_GetSpecialFD(PR_StandardInput); - if (!REQUEST_WAITING) { - pollset[STDIN_FD].in_flags = PR_POLL_READ; - npds = 2; + if (requestFile) { + pollset[STDIN_FD].fd = PR_Open(requestFile, PR_RDONLY, 0); + if (!pollset[STDIN_FD].fd) { + fprintf(stderr, "%s: unable to open input file: %s\n", + progName, requestFile); + error = 1; + goto done; + } } else { - npds = 1; + pollset[STDIN_FD].fd = PR_GetSpecialFD(PR_StandardInput); } + pollset[STDIN_FD].in_flags = PR_POLL_READ; std_out = PR_GetSpecialFD(PR_StandardOutput); #if defined(WIN32) || defined(OS2) @@ -1458,10 +1479,9 @@ run(void) requestToExit = PR_FALSE; FPRINTF(stderr, "%s: ready...\n", progName); while (!requestToExit && - ((pollset[SSOCK_FD].in_flags | pollset[STDIN_FD].in_flags) || - REQUEST_WAITING)) { - char buf[4000]; /* buffer for stdin */ - int nb; /* num bytes read from stdin. */ + (pollset[SSOCK_FD].in_flags || pollset[STDIN_FD].in_flags)) { + PRUint8 buf[4000]; /* buffer for stdin */ + int nb; /* num bytes read from stdin. */ rv = restartHandshakeAfterServerCertIfNeeded(s, &serverCertAuth, override); @@ -1475,7 +1495,8 @@ run(void) pollset[STDIN_FD].out_flags = 0; FPRINTF(stderr, "%s: about to call PR_Poll !\n", progName); - filesReady = PR_Poll(pollset, npds, PR_INTERVAL_NO_TIMEOUT); + filesReady = PR_Poll(pollset, PR_ARRAY_SIZE(pollset), + PR_INTERVAL_NO_TIMEOUT); if (filesReady < 0) { SECU_PrintError(progName, "select failed"); error = 1; @@ -1497,14 +1518,6 @@ run(void) "%s: PR_Poll returned 0x%02x for socket out_flags.\n", progName, pollset[SSOCK_FD].out_flags); } - if (REQUEST_WAITING) { - error = writeBytesToServer(s, requestString, requestStringLen); - if (error) { - goto done; - } - requestSent = PR_TRUE; - pollset[SSOCK_FD].in_flags = PR_POLL_READ; - } if (pollset[STDIN_FD].out_flags & PR_POLL_READ) { /* Read from stdin and write to socket */ nb = PR_Read(pollset[STDIN_FD].fd, buf, sizeof(buf)); @@ -1518,6 +1531,8 @@ run(void) } else if (nb == 0) { /* EOF on stdin, stop polling stdin for read. */ pollset[STDIN_FD].in_flags = 0; + if (actAsServer) + requestToExit = PR_TRUE; } else { error = writeBytesToServer(s, buf, nb); if (error) { @@ -1532,12 +1547,12 @@ run(void) "%s: PR_Poll returned 0x%02x for socket out_flags.\n", progName, pollset[SSOCK_FD].out_flags); } - if ((pollset[SSOCK_FD].out_flags & PR_POLL_READ) || - (pollset[SSOCK_FD].out_flags & PR_POLL_ERR) #ifdef PR_POLL_HUP - || (pollset[SSOCK_FD].out_flags & PR_POLL_HUP) +#define POLL_RECV_FLAGS (PR_POLL_READ | PR_POLL_ERR | PR_POLL_HUP) +#else +#define POLL_RECV_FLAGS (PR_POLL_READ | PR_POLL_ERR) #endif - ) { + if (pollset[SSOCK_FD].out_flags & POLL_RECV_FLAGS) { /* Read from socket and write to stdout */ nb = PR_Recv(pollset[SSOCK_FD].fd, buf, sizeof buf, 0, maxInterval); FPRINTF(stderr, "%s: Read from server %d bytes\n", progName, nb); @@ -1554,7 +1569,7 @@ run(void) if (skipProtoHeader != PR_TRUE || wrStarted == PR_TRUE) { PR_Write(std_out, buf, nb); } else { - separateReqHeader(std_out, buf, nb, &wrStarted, + separateReqHeader(std_out, (char *)buf, nb, &wrStarted, &headerSeparatorPtrnId); } if (verbose) @@ -1568,42 +1583,10 @@ done: if (s) { PR_Close(s); } - - return error; -} - -PRInt32 -ReadFile(const char *filename, char **data) -{ - char *ret = NULL; - char buf[8192]; - unsigned int len = 0; - PRStatus rv; - - PRFileDesc *fd = PR_Open(filename, PR_RDONLY, 0); - if (!fd) - return -1; - - for (;;) { - rv = PR_Read(fd, buf, sizeof(buf)); - if (rv < 0) { - PR_Free(ret); - return rv; - } - - if (!rv) - break; - - ret = PR_Realloc(ret, len + rv); - if (!ret) { - return -1; - } - PORT_Memcpy(ret + len, buf, rv); - len += rv; + if (requestFile && pollset[STDIN_FD].fd) { + PR_Close(pollset[STDIN_FD].fd); } - - *data = ret; - return len; + return error; } int @@ -1653,26 +1636,22 @@ main(int argc, char **argv) switch (optstate->option) { case '?': default: - Usage(progName); + Usage(); break; case '4': allowIPv6 = PR_FALSE; if (!allowIPv4) - Usage(progName); + Usage(); break; case '6': allowIPv4 = PR_FALSE; if (!allowIPv6) - Usage(progName); + Usage(); break; case 'A': - requestStringLen = ReadFile(optstate->value, &requestString); - if (requestStringLen < 0) { - fprintf(stderr, "Couldn't read file %s\n", optstate->value); - exit(1); - } + requestFile = PORT_Strdup(optstate->value); break; case 'C': @@ -1735,7 +1714,7 @@ main(int argc, char **argv) actAsServer = 1; } else { if (strcmp(optstate->value, "client")) { - Usage(progName); + Usage(); } } break; @@ -1768,16 +1747,21 @@ main(int argc, char **argv) if (!strcmp(optstate->value, "alt-server-hello")) { enableAltServerHello = PR_TRUE; } else { - Usage(progName); + Usage(); } break; case 'Y': - PrintCipherUsage(progName); + PrintCipherUsage(); exit(0); break; case 'Z': enableZeroRtt = PR_TRUE; + zeroRttData = PORT_ZAlloc(ZERO_RTT_MAX); + if (!zeroRttData) { + fprintf(stderr, "Unable to allocate buffer for 0-RTT\n"); + exit(1); + } break; case 'a': @@ -1786,7 +1770,7 @@ main(int argc, char **argv) } else if (!hs2SniHostName) { hs2SniHostName = PORT_Strdup(optstate->value); } else { - Usage(progName); + Usage(); } break; @@ -1875,7 +1859,7 @@ main(int argc, char **argv) if (rv != SECSuccess) { PL_DestroyOptState(optstate); fprintf(stderr, "Bad group specified.\n"); - Usage(progName); + Usage(); } break; } @@ -1889,18 +1873,18 @@ main(int argc, char **argv) enabledVersions, &enabledVersions) != SECSuccess) { fprintf(stderr, "Bad version specified.\n"); - Usage(progName); + Usage(); } PORT_Free(versionString); } if (optstatus == PL_OPT_BAD) { - Usage(progName); + Usage(); } if (!host || !portno) { fprintf(stderr, "%s: parameters -h and -p are mandatory\n", progName); - Usage(progName); + Usage(); } if (serverCertAuth.testFreshStatusFromSideChannel && @@ -2060,20 +2044,13 @@ done: PR_Close(s); } - if (hs1SniHostName) { - PORT_Free(hs1SniHostName); - } - if (hs2SniHostName) { - PORT_Free(hs2SniHostName); - } - if (nickname) { - PORT_Free(nickname); - } - if (pwdata.data) { - PORT_Free(pwdata.data); - } + PORT_Free((void *)requestFile); + PORT_Free(hs1SniHostName); + PORT_Free(hs2SniHostName); + PORT_Free(nickname); + PORT_Free(pwdata.data); PORT_Free(host); - PORT_Free(requestString); + PORT_Free(zeroRttData); if (enabledGroups) { PORT_Free(enabledGroups); diff --git a/security/nss/cmd/vfyserv/vfyserv.c b/security/nss/cmd/vfyserv/vfyserv.c index aa648ad8c..4234ecd09 100644 --- a/security/nss/cmd/vfyserv/vfyserv.c +++ b/security/nss/cmd/vfyserv/vfyserv.c @@ -327,9 +327,7 @@ do_connects(void *a, int connection) } void -client_main(unsigned short port, - int connections, - const char *hostName) +client_main(int connections) { int i; SECStatus secStatus; @@ -553,7 +551,7 @@ main(int argc, char **argv) } } - client_main(port, connections, hostName); + client_main(connections); cleanup: if (doOcspCheck) { diff --git a/security/nss/cmd/vfyserv/vfyutil.c b/security/nss/cmd/vfyserv/vfyutil.c index 2f1b53262..d3d8a206e 100644 --- a/security/nss/cmd/vfyserv/vfyutil.c +++ b/security/nss/cmd/vfyserv/vfyutil.c @@ -310,13 +310,13 @@ myHandshakeCallback(PRFileDesc *socket, void *arg) void disableAllSSLCiphers(void) { - const PRUint16 *cipherSuites = SSL_ImplementedCiphers; + const PRUint16 *allSuites = SSL_ImplementedCiphers; int i = SSL_NumImplementedCiphers; SECStatus rv; /* disable all the SSL3 cipher suites */ while (--i >= 0) { - PRUint16 suite = cipherSuites[i]; + PRUint16 suite = allSuites[i]; rv = SSL_CipherPrefSetDefault(suite, PR_FALSE); if (rv != SECSuccess) { fprintf(stderr, diff --git a/security/nss/coreconf/Werror.mk b/security/nss/coreconf/Werror.mk index 69155eb14..a569a497c 100644 --- a/security/nss/coreconf/Werror.mk +++ b/security/nss/coreconf/Werror.mk @@ -48,9 +48,11 @@ ifndef WARNING_CFLAGS else # This tests to see if enabling the warning is possible before # setting an option to disable it. - disable_warning = $(shell $(CC) -x c -E -Werror -W$(1) /dev/null >/dev/null 2>&1 && echo -Wno-$(1)) + set_warning = $(shell $(CC) -x c -E -Werror -W$(1) /dev/null >/dev/null 2>&1 && echo -W$(2)$(1)) + enable_warning = $(call set_warning,$(1),) + disable_warning = $(call set_warning,$(1),no-) - WARNING_CFLAGS = -Wall + WARNING_CFLAGS = -Wall $(call enable_warning,shadow) ifdef CC_IS_CLANG # -Qunused-arguments : clang objects to arguments that it doesn't understand # and fixing this would require rearchitecture diff --git a/security/nss/coreconf/config.mk b/security/nss/coreconf/config.mk index 55d95c30e..b62f6cef4 100644 --- a/security/nss/coreconf/config.mk +++ b/security/nss/coreconf/config.mk @@ -181,6 +181,10 @@ ifndef NSS_FORCE_FIPS DEFINES += -DNSS_NO_INIT_SUPPORT endif +ifdef NSS_SEED_ONLY_DEV_URANDOM +DEFINES += -DSEED_ONLY_DEV_URANDOM +endif + # Avoid building object leak test code for optimized library ifndef BUILD_OPT ifdef PKIX_OBJECT_LEAK_TEST diff --git a/security/nss/coreconf/coreconf.dep b/security/nss/coreconf/coreconf.dep index 5182f7555..590d1bfae 100644 --- a/security/nss/coreconf/coreconf.dep +++ b/security/nss/coreconf/coreconf.dep @@ -10,3 +10,4 @@ */ #error "Do not include this header file." + diff --git a/security/nss/coreconf/nsinstall/pathsub.c b/security/nss/coreconf/nsinstall/pathsub.c index a42a9f30a..c31a946f0 100644 --- a/security/nss/coreconf/nsinstall/pathsub.c +++ b/security/nss/coreconf/nsinstall/pathsub.c @@ -212,7 +212,7 @@ reversepath(char *inpath, char *name, int len, char *outpath) xchdir(".."); } else { cp -= 3; - strncpy(cp, "../", 3); + memcpy(cp, "../", 3); xchdir(buf); } } diff --git a/security/nss/coreconf/werror.py b/security/nss/coreconf/werror.py index c469c4002..0e2d41c63 100644 --- a/security/nss/coreconf/werror.py +++ b/security/nss/coreconf/werror.py @@ -54,7 +54,7 @@ def main(): set_warning(w, 'no-') print('-Qunused-arguments') - # set_warning('shadow') # Bug 1309068 + set_warning('shadow') if __name__ == '__main__': main() diff --git a/security/nss/cpputil/databuffer.cc b/security/nss/cpputil/databuffer.cc index d60ebccb3..1420d76b4 100644 --- a/security/nss/cpputil/databuffer.cc +++ b/security/nss/cpputil/databuffer.cc @@ -18,12 +18,12 @@ namespace nss_test { -void DataBuffer::Assign(const uint8_t* data, size_t len) { - if (data) { - Allocate(len); - memcpy(static_cast<void*>(data_), static_cast<const void*>(data), len); +void DataBuffer::Assign(const uint8_t* d, size_t l) { + if (d) { + Allocate(l); + memcpy(static_cast<void*>(data_), static_cast<const void*>(d), l); } else { - assert(len == 0); + assert(l == 0); data_ = nullptr; len_ = 0; } diff --git a/security/nss/cpputil/databuffer.h b/security/nss/cpputil/databuffer.h index 58e07efe1..5ec035098 100644 --- a/security/nss/cpputil/databuffer.h +++ b/security/nss/cpputil/databuffer.h @@ -17,8 +17,8 @@ namespace nss_test { class DataBuffer { public: DataBuffer() : data_(nullptr), len_(0) {} - DataBuffer(const uint8_t* data, size_t len) : data_(nullptr), len_(0) { - Assign(data, len); + DataBuffer(const uint8_t* d, size_t l) : data_(nullptr), len_(0) { + Assign(d, l); } DataBuffer(const DataBuffer& other) : data_(nullptr), len_(0) { Assign(other); @@ -32,17 +32,17 @@ class DataBuffer { return *this; } - void Allocate(size_t len) { + void Allocate(size_t l) { delete[] data_; - data_ = new uint8_t[len ? len : 1]; // Don't depend on new [0]. - len_ = len; + data_ = new uint8_t[l ? l : 1]; // Don't depend on new [0]. + len_ = l; } - void Truncate(size_t len) { len_ = (std::min)(len_, len); } + void Truncate(size_t l) { len_ = (std::min)(len_, l); } void Assign(const DataBuffer& other) { Assign(other.data(), other.len()); } - void Assign(const uint8_t* data, size_t len); + void Assign(const uint8_t* d, size_t l); // Write will do a new allocation and expand the size of the buffer if needed. // Returns the offset of the end of the write. diff --git a/security/nss/cpputil/scoped_ptrs.h b/security/nss/cpputil/scoped_ptrs.h index 8a0b4f5ab..6ffef4dd3 100644 --- a/security/nss/cpputil/scoped_ptrs.h +++ b/security/nss/cpputil/scoped_ptrs.h @@ -45,6 +45,7 @@ struct ScopedDelete { void operator()(SEC_PKCS12DecoderContext* dcx) { SEC_PKCS12DecoderFinish(dcx); } + void operator()(CERTDistNames* names) { CERT_FreeDistNames(names); } }; template <class T> @@ -78,6 +79,7 @@ SCOPED(PK11Context); SCOPED(PK11GenericObject); SCOPED(SSLResumptionTokenInfo); SCOPED(SEC_PKCS12DecoderContext); +SCOPED(CERTDistNames); #undef SCOPED diff --git a/security/nss/cpputil/tls_parser.cc b/security/nss/cpputil/tls_parser.cc index e4c06aa91..efedd7a65 100644 --- a/security/nss/cpputil/tls_parser.cc +++ b/security/nss/cpputil/tls_parser.cc @@ -46,6 +46,21 @@ bool TlsParser::Read(DataBuffer* val, size_t len) { return true; } +bool TlsParser::ReadFromMark(DataBuffer* val, size_t len, size_t mark) { + auto saved = offset_; + offset_ = mark; + + if (remaining() < len) { + offset_ = saved; + return false; + } + + val->Assign(ptr(), len); + + offset_ = saved; + return true; +} + bool TlsParser::ReadVariable(DataBuffer* val, size_t len_size) { uint32_t len; if (!Read(&len, len_size)) { diff --git a/security/nss/cpputil/tls_parser.h b/security/nss/cpputil/tls_parser.h index 436c11e76..56f562e07 100644 --- a/security/nss/cpputil/tls_parser.h +++ b/security/nss/cpputil/tls_parser.h @@ -123,6 +123,7 @@ class TlsParser { bool Read(uint32_t* val, size_t size); // Reads len bytes into dest buffer, overwriting it. bool Read(DataBuffer* dest, size_t len); + bool ReadFromMark(DataBuffer* val, size_t len, size_t mark); // Reads bytes into dest buffer, overwriting it. The number of bytes is // determined by reading from len_size bytes from the stream first. bool ReadVariable(DataBuffer* dest, size_t len_size); diff --git a/security/nss/fuzz/fuzz.gyp b/security/nss/fuzz/fuzz.gyp index ed1f53d58..69e178319 100644 --- a/security/nss/fuzz/fuzz.gyp +++ b/security/nss/fuzz/fuzz.gyp @@ -44,6 +44,9 @@ # This is a static build of pk11wrap, softoken, and freebl. '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static', ], + 'cflags_cc': [ + '-Wno-error=shadow', + ], 'conditions': [ ['fuzz_oss==0', { 'sources': [ diff --git a/security/nss/fuzz/tls_client_target.cc b/security/nss/fuzz/tls_client_target.cc index e59550984..a5b2a2c5f 100644 --- a/security/nss/fuzz/tls_client_target.cc +++ b/security/nss/fuzz/tls_client_target.cc @@ -87,15 +87,12 @@ static void SetupCallbacks(PRFileDesc* fd, ClientConfig* config) { } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) { - static std::unique_ptr<NSSDatabase> db(new NSSDatabase()); + std::unique_ptr<NSSDatabase> db(new NSSDatabase()); assert(db != nullptr); EnableAllProtocolVersions(); std::unique_ptr<ClientConfig> config(new ClientConfig(data, len)); - // Clear the cache. We never want to resume as we couldn't reproduce that. - SSL_ClearSessionCache(); - // Reset the RNG state. assert(RNG_RandomUpdate(NULL, 0) == SECSuccess); @@ -114,6 +111,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) { SetupCallbacks(ssl_fd, config.get()); DoHandshake(ssl_fd, false); + // Release all SIDs. + SSL_ClearSessionCache(); + return 0; } diff --git a/security/nss/gtests/freebl_gtest/blake2b_unittest.cc b/security/nss/gtests/freebl_gtest/blake2b_unittest.cc index e6b0c1157..ac9cca83f 100644 --- a/security/nss/gtests/freebl_gtest/blake2b_unittest.cc +++ b/security/nss/gtests/freebl_gtest/blake2b_unittest.cc @@ -50,7 +50,7 @@ TEST_P(Blake2BKATUnkeyed, Unkeyed) { TEST_P(Blake2BKATKeyed, Keyed) { std::vector<uint8_t> values(BLAKE2B512_LENGTH); SECStatus rv = BLAKE2B_MAC_HashBuf(values.data(), kat_data.data(), - std::get<0>(GetParam()), key.data(), + std::get<0>(GetParam()), kat_key.data(), BLAKE2B_KEY_SIZE); ASSERT_EQ(SECSuccess, rv); EXPECT_EQ(values, std::get<1>(GetParam())); @@ -139,7 +139,7 @@ TEST_F(Blake2BTests, NullTest) { EXPECT_EQ(std::get<1>(TestcasesUnkeyed[0]), digest); digest = std::vector<uint8_t>(BLAKE2B512_LENGTH); - rv = BLAKE2B_MAC_HashBuf(digest.data(), nullptr, 0, key.data(), + rv = BLAKE2B_MAC_HashBuf(digest.data(), nullptr, 0, kat_key.data(), BLAKE2B_KEY_SIZE); ASSERT_EQ(SECSuccess, rv); EXPECT_EQ(std::get<1>(TestcasesKeyed[0]), digest); diff --git a/security/nss/gtests/freebl_gtest/kat/blake2b_kat.h b/security/nss/gtests/freebl_gtest/kat/blake2b_kat.h index 28921cc94..2d73a4ab5 100644 --- a/security/nss/gtests/freebl_gtest/kat/blake2b_kat.h +++ b/security/nss/gtests/freebl_gtest/kat/blake2b_kat.h @@ -7,7 +7,7 @@ #include <vector> #include <stdint.h> -const std::vector<uint8_t> key = { +const std::vector<uint8_t> kat_key = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, diff --git a/security/nss/gtests/nss_bogo_shim/config.cc b/security/nss/gtests/nss_bogo_shim/config.cc index 2e6f7f775..603bb6029 100644 --- a/security/nss/gtests/nss_bogo_shim/config.cc +++ b/security/nss/gtests/nss_bogo_shim/config.cc @@ -9,26 +9,37 @@ #include <queue> #include <string> -bool ConfigEntryBase::ParseInternal(std::queue<const char *> *args, - std::string *out) { - if (args->empty()) return false; - *out = args->front(); - args->pop(); +bool ConfigEntryBase::ParseInternal(std::queue<const char *> &args, + std::vector<int> &out) { + if (args.empty()) return false; + + char *endptr; + out.push_back(strtol(args.front(), &endptr, 10)); + args.pop(); + + return !*endptr; +} + +bool ConfigEntryBase::ParseInternal(std::queue<const char *> &args, + std::string &out) { + if (args.empty()) return false; + out = args.front(); + args.pop(); return true; } -bool ConfigEntryBase::ParseInternal(std::queue<const char *> *args, int *out) { - if (args->empty()) return false; +bool ConfigEntryBase::ParseInternal(std::queue<const char *> &args, int &out) { + if (args.empty()) return false; char *endptr; - *out = strtol(args->front(), &endptr, 10); - args->pop(); + out = strtol(args.front(), &endptr, 10); + args.pop(); return !*endptr; } -bool ConfigEntryBase::ParseInternal(std::queue<const char *> *args, bool *out) { - *out = true; +bool ConfigEntryBase::ParseInternal(std::queue<const char *> &args, bool &out) { + out = true; return true; } @@ -51,7 +62,7 @@ Config::Status Config::ParseArgs(int argc, char **argv) { if (e == entries_.end()) { return kUnknownFlag; } - if (!e->second->Parse(&args)) return kMalformedArgument; + if (!e->second->Parse(args)) return kMalformedArgument; } return kOK; diff --git a/security/nss/gtests/nss_bogo_shim/config.h b/security/nss/gtests/nss_bogo_shim/config.h index 822df65b3..0e7fb5ed5 100644 --- a/security/nss/gtests/nss_bogo_shim/config.h +++ b/security/nss/gtests/nss_bogo_shim/config.h @@ -23,18 +23,19 @@ // Abstract base class for a given config flag. class ConfigEntryBase { public: - ConfigEntryBase(const std::string& name, const std::string& type) - : name_(name), type_(type) {} + ConfigEntryBase(const std::string& nm, const std::string& typ) + : name_(nm), type_(typ) {} virtual ~ConfigEntryBase() {} const std::string& type() const { return type_; } - virtual bool Parse(std::queue<const char*>* args) = 0; + virtual bool Parse(std::queue<const char*>& args) = 0; protected: - bool ParseInternal(std::queue<const char*>* args, std::string* out); - bool ParseInternal(std::queue<const char*>* args, int* out); - bool ParseInternal(std::queue<const char*>* args, bool* out); + bool ParseInternal(std::queue<const char*>& args, std::vector<int>& out); + bool ParseInternal(std::queue<const char*>& args, std::string& out); + bool ParseInternal(std::queue<const char*>& args, int& out); + bool ParseInternal(std::queue<const char*>& args, bool& out); const std::string name_; const std::string type_; @@ -48,8 +49,8 @@ class ConfigEntry : public ConfigEntryBase { : ConfigEntryBase(name, typeid(T).name()), value_(init) {} T get() const { return value_; } - bool Parse(std::queue<const char*>* args) { - return ParseInternal(args, &value_); + bool Parse(std::queue<const char*>& args) { + return ParseInternal(args, value_); } private: diff --git a/security/nss/gtests/nss_bogo_shim/config.json b/security/nss/gtests/nss_bogo_shim/config.json index 03f875466..6dc155bef 100644 --- a/security/nss/gtests/nss_bogo_shim/config.json +++ b/security/nss/gtests/nss_bogo_shim/config.json @@ -1,69 +1,16 @@ { "DisabledTests": { "### These tests break whenever we rev versions, so just leave them here for easy uncommenting":"", - "SendWarningAlerts-Pass":"BoringSSL updated", - "SendBogusAlertType":"BoringSSL updated", - "SendEmptyRecords-Pass":"BoringSSL updated", - "ExtraCompressionMethods-TLS12":"BoringSSL updated", - "SendSNIWarningAlert":"BoringSSL updated", - "NoNullCompression-TLS12":"BoringSSL updated", - "InvalidCompressionMethod":"BoringSSL updated", - "SupportTicketsWithSessionID":"BoringSSL updated", - "NoSharedCipher":"BoringSSL updated", - "ServerHelloBogusCipher":"BoringSSL updated", - "ClientHelloVersionTooHigh":"BoringSSL updated", - "ServerAuth-SignatureType":"BoringSSL updated", - "ECDSACurveMismatch-Verify-TLS12":"BoringSSL updated", - "UnknownExtension-Client":"BoringSSL updated", - "UnofferedExtension-Client":"BoringSSL updated", - "SendClientVersion-RSA":"BoringSSL updated", - "SupportedCurves-ServerHello-TLS12":"BoringSSL updated", - "Basic-Client*Sync":"BoringSSL updated", - "Resume-Client-CipherMismatch":"BoringSSL updated", - "ClientAuth-SignatureType":"BoringSSL updated", - "Agree-Digest-Default":"BoringSSL updated", - "Basic-Server*Sync":"BoringSSL updated", - "ClientAuth-*-Sync":"BoringSSL updated", - "RSA-PSS-Default*":"BoringSSL updated", - "Renegotiate-Server-NoExt*":"BoringSSL updated", - "Downgrade-TLS12*":"BoringSSL updated", - "MaxCBCPadding":"BoringSSL updated", - "UnknownCipher":"BoringSSL updated", - "LargeMessage":"BoringSSL updated", - "NoCommonCurves":"BoringSSL updated", - "UnknownCurve":"BoringSSL updated", - "SessionTicketsDisabled*":"BoringSSL updated", - "BadFinished-*":"BoringSSL updated", - "ServerSkipCertificateVerify":"BoringSSL updated", - "*VersionTolerance":"BoringSSL updated", - "ConflictingVersionNegotiation*":"BoringSSL updated", - "Ed25519DefaultDisable*":"BoringSSL updated", - "*SHA1-Fallback*":"BoringSSL updated", - "ExtendedMasterSecret-NoToNo*":"BoringSSL updated", - "ServerNameExtensionClientMissing*":"BoringSSL updated", - "NoClientCertificate*":"BoringSSL updated", - "ServerCipherFilter*":"BoringSSL updated", - "*FallbackSCSV*":"BoringSSL updated", - "LooseInitialRecordVersion*":"BoringSSL updated", - "ALPNClient*":"BoringSSL updated", - "MinimumVersion*":"BoringSSL updated", - "VersionNegotiation*":"BoringSSL updated", - "*Client-ClientAuth*":"BoringSSL updated", - "*Server-ClientAuth*":"BoringSSL updated", - "NoExtendedMasterSecret*":"BoringSSL updated", - "PointFormat*":"BoringSSL updated", - "*Sync-SplitHandshakeRecords*":"BoringSSL updated", - "*Sync-PackHandshakeFlight*":"BoringSSL updated", - "TicketSessionIDLength*":"BoringSSL updated", - "*LargeRecord*":"BoringSSL updated", - "WrongMessageType-NewSessionTicket":"BoringSSL updated", - "WrongMessageType*Certificate*":"BoringSSL updated", - "WrongMessageType*Client*":"BoringSSL updated", - "WrongMessageType*Server*":"BoringSSL updated", - "WrongMessageType*DTLS":"BoringSSL updated", - "GarbageCertificate*":"BoringSSL updated", - "EmptyExtensions*":"BoringSSL updated", - "*OmitExtensions*":"BoringSSL updated", + "ServerBogusVersion":"Check that SH.legacy_version=TLS12 when the server picks TLS 1.3 (Bug 1443761)", + "DummyPQPadding-Server*":"Boring is testing a dummy PQ padding extension", + "VerifyPreferences-Enforced":"NSS sends alerts in response to errors in protected handshake messages in the clear", + "Draft-Downgrade-Server":"Boring implements a draft downgrade sentinel used for measurements.", + "FilterExtraAlgorithms":"NSS doesn't allow sending unsupported signature algorithms", + "SendBogusAlertType":"Unexpected TLS alerts should abort connections (Bug 1438263)", + "VerifyPreferences-Ed25519":"Add Ed25519 support (Bug 1325335)", + "Ed25519DefaultDisable*":"Add Ed25519 support (Bug 1325335)", + "ServerCipherFilter*":"Add Ed25519 support (Bug 1325335)", + "GarbageCertificate*":"Send bad_certificate alert when certificate parsing fails (Bug 1441565)", "SupportedVersionSelection-TLS12":"Should maybe reject TLS 1.2 in SH.supported_versions (Bug 1438266)", "*TLS13*":"(NSS=19, BoGo=18)", "*HelloRetryRequest*":"(NSS=19, BoGo=18)", @@ -108,7 +55,6 @@ "WrongMessageType-TLS13-ServerCertificateVerify":"nss updated/broken", "WrongMessageType-TLS13-ServerCertificate":"nss updated/broken", "WrongMessageType-TLS13-ServerFinished":"nss updated/broken", - "EncryptedExtensionsWithKeyShare":"nss updated/broken", "EmptyEncryptedExtensions":"nss updated/broken", "TrailingMessageData-*": "Bug 1304575", "DuplicateKeyShares":"Bug 1304578", diff --git a/security/nss/gtests/nss_bogo_shim/nss_bogo_shim.cc b/security/nss/gtests/nss_bogo_shim/nss_bogo_shim.cc index e12714e8d..72dbd5771 100644 --- a/security/nss/gtests/nss_bogo_shim/nss_bogo_shim.cc +++ b/security/nss/gtests/nss_bogo_shim/nss_bogo_shim.cc @@ -5,6 +5,7 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "config.h" +#include <algorithm> #include <cstdlib> #include <iostream> #include <memory> @@ -90,9 +91,14 @@ class TestAgent { PRStatus prv; PRNetAddr addr; - prv = PR_StringToNetAddr("127.0.0.1", &addr); + // Try IPv6 first. + prv = PR_StringToNetAddr("::1", &addr); if (prv != PR_SUCCESS) { - return false; + // If that fails, try IPv4. + prv = PR_StringToNetAddr("127.0.0.1", &addr); + if (prv != PR_SUCCESS) { + return false; + } } addr.inet.port = PR_htons(cfg_.get<int>("port")); @@ -256,7 +262,11 @@ class TestAgent { } bool SetupOptions() { - SECStatus rv = SSL_OptionSet(ssl_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE); + SECStatus rv = + SSL_OptionSet(ssl_fd_, SSL_ENABLE_TLS13_COMPAT_MODE, PR_TRUE); + if (rv != SECSuccess) return false; + + rv = SSL_OptionSet(ssl_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE); if (rv != SECSuccess) return false; SSLVersionRange vrange; @@ -287,6 +297,26 @@ class TestAgent { if (rv != SECSuccess) return false; } + // Set supported signature schemes. + auto sign_prefs = cfg_.get<std::vector<int>>("signing-prefs"); + auto verify_prefs = cfg_.get<std::vector<int>>("verify-prefs"); + if (sign_prefs.empty()) { + sign_prefs = verify_prefs; + } else if (!verify_prefs.empty()) { + return false; // Both shouldn't be set. + } + if (!sign_prefs.empty()) { + std::vector<SSLSignatureScheme> sig_schemes; + std::transform( + sign_prefs.begin(), sign_prefs.end(), std::back_inserter(sig_schemes), + [](int scheme) { return static_cast<SSLSignatureScheme>(scheme); }); + + rv = SSL_SignatureSchemePrefSet( + ssl_fd_, sig_schemes.data(), + static_cast<unsigned int>(sig_schemes.size())); + if (rv != SECSuccess) return false; + } + if (cfg_.get<bool>("fallback-scsv")) { rv = SSL_OptionSet(ssl_fd_, SSL_ENABLE_FALLBACK_SCSV, PR_TRUE); if (rv != SECSuccess) return false; @@ -410,7 +440,7 @@ class TestAgent { size_t left = sizeof(block); while (left) { - int32_t rv = PR_Read(ssl_fd_, block, left); + rv = PR_Read(ssl_fd_, block, left); if (rv < 0) { std::cerr << "Failure reading\n"; return SECFailure; @@ -481,6 +511,24 @@ class TestAgent { } } + auto sig_alg = cfg_.get<int>("expect-peer-signature-algorithm"); + if (sig_alg) { + SSLChannelInfo info; + rv = SSL_GetChannelInfo(ssl_fd_, &info, sizeof(info)); + if (rv != SECSuccess) { + PRErrorCode err = PR_GetError(); + std::cerr << "SSL_GetChannelInfo failed with error=" << FormatError(err) + << std::endl; + return SECFailure; + } + + auto expected = static_cast<SSLSignatureScheme>(sig_alg); + if (info.signatureScheme != expected) { + std::cerr << "Unexpected signature scheme" << std::endl; + return SECFailure; + } + } + return SECSuccess; } @@ -513,6 +561,9 @@ std::unique_ptr<const Config> ReadConfig(int argc, char** argv) { cfg->AddEntry<bool>("verify-peer", false); cfg->AddEntry<std::string>("advertise-alpn", ""); cfg->AddEntry<std::string>("expect-alpn", ""); + cfg->AddEntry<std::vector<int>>("signing-prefs", std::vector<int>()); + cfg->AddEntry<std::vector<int>>("verify-prefs", std::vector<int>()); + cfg->AddEntry<int>("expect-peer-signature-algorithm", 0); auto rv = cfg->ParseArgs(argc, argv); switch (rv) { diff --git a/security/nss/gtests/pk11_gtest/pk11_signature_test.h b/security/nss/gtests/pk11_gtest/pk11_signature_test.h index b14104371..8a12171a0 100644 --- a/security/nss/gtests/pk11_gtest/pk11_signature_test.h +++ b/security/nss/gtests/pk11_gtest/pk11_signature_test.h @@ -25,8 +25,8 @@ struct Pkcs11SignatureTestParams { class Pk11SignatureTest : public ::testing::Test { protected: - Pk11SignatureTest(CK_MECHANISM_TYPE mechanism, SECOidTag hash_oid) - : mechanism_(mechanism), hash_oid_(hash_oid) {} + Pk11SignatureTest(CK_MECHANISM_TYPE mech, SECOidTag hash_oid) + : mechanism_(mech), hash_oid_(hash_oid) {} virtual const SECItem* parameters() const { return nullptr; } CK_MECHANISM_TYPE mechanism() const { return mechanism_; } diff --git a/security/nss/gtests/ssl_gtest/libssl_internals.c b/security/nss/gtests/ssl_gtest/libssl_internals.c index 17b4ffe49..e43113de4 100644 --- a/security/nss/gtests/ssl_gtest/libssl_internals.c +++ b/security/nss/gtests/ssl_gtest/libssl_internals.c @@ -237,22 +237,23 @@ SECStatus SSLInt_AdvanceReadSeqNum(PRFileDesc *fd, PRUint64 to) { if (!ss) { return SECFailure; } - if (to >= RECORD_SEQ_MAX) { + if (to > RECORD_SEQ_MAX) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } ssl_GetSpecWriteLock(ss); spec = ss->ssl3.crSpec; - spec->seqNum = to; + spec->nextSeqNum = to; /* For DTLS, we need to fix the record sequence number. For this, we can just * scrub the entire structure on the assumption that the new sequence number * is far enough past the last received sequence number. */ - if (spec->seqNum <= spec->recvdRecords.right + DTLS_RECVD_RECORDS_WINDOW) { + if (spec->nextSeqNum <= + spec->recvdRecords.right + DTLS_RECVD_RECORDS_WINDOW) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } - dtls_RecordSetRecvd(&spec->recvdRecords, spec->seqNum); + dtls_RecordSetRecvd(&spec->recvdRecords, spec->nextSeqNum - 1); ssl_ReleaseSpecWriteLock(ss); return SECSuccess; @@ -270,7 +271,7 @@ SECStatus SSLInt_AdvanceWriteSeqNum(PRFileDesc *fd, PRUint64 to) { return SECFailure; } ssl_GetSpecWriteLock(ss); - ss->ssl3.cwSpec->seqNum = to; + ss->ssl3.cwSpec->nextSeqNum = to; ssl_ReleaseSpecWriteLock(ss); return SECSuccess; } @@ -284,7 +285,7 @@ SECStatus SSLInt_AdvanceWriteSeqByAWindow(PRFileDesc *fd, PRInt32 extra) { return SECFailure; } ssl_GetSpecReadLock(ss); - to = ss->ssl3.cwSpec->seqNum + DTLS_RECVD_RECORDS_WINDOW + extra; + to = ss->ssl3.cwSpec->nextSeqNum + DTLS_RECVD_RECORDS_WINDOW + extra; ssl_ReleaseSpecReadLock(ss); return SSLInt_AdvanceWriteSeqNum(fd, to); } diff --git a/security/nss/gtests/ssl_gtest/manifest.mn b/security/nss/gtests/ssl_gtest/manifest.mn index 5d893bab3..8547e56d1 100644 --- a/security/nss/gtests/ssl_gtest/manifest.mn +++ b/security/nss/gtests/ssl_gtest/manifest.mn @@ -36,6 +36,7 @@ CPPSRCS = \ ssl_loopback_unittest.cc \ ssl_misc_unittest.cc \ ssl_record_unittest.cc \ + ssl_recordsize_unittest.cc \ ssl_resumption_unittest.cc \ ssl_renegotiation_unittest.cc \ ssl_skip_unittest.cc \ diff --git a/security/nss/gtests/ssl_gtest/rsa8193.h b/security/nss/gtests/ssl_gtest/rsa8193.h new file mode 100644 index 000000000..626516389 --- /dev/null +++ b/security/nss/gtests/ssl_gtest/rsa8193.h @@ -0,0 +1,209 @@ +/* -*- 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/. */ + +// openssl req -nodes -x509 -newkey rsa:8193 -out cert.pem -days 365 +static const uint8_t rsa8193[] = { + 0x30, 0x82, 0x09, 0x61, 0x30, 0x82, 0x05, 0x48, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x09, 0x00, 0xaf, 0xff, 0x37, 0x91, 0x3e, 0x44, 0xae, 0x57, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x0b, 0x05, 0x00, 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, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x35, 0x31, 0x37, + 0x30, 0x39, 0x34, 0x32, 0x32, 0x39, 0x5a, 0x17, 0x0d, 0x31, 0x39, 0x30, + 0x35, 0x31, 0x37, 0x30, 0x39, 0x34, 0x32, 0x32, 0x39, 0x5a, 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, 0x30, 0x82, 0x04, + 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x04, 0x0f, 0x00, 0x30, 0x82, 0x04, + 0x0a, 0x02, 0x82, 0x04, 0x01, 0x01, 0x77, 0xd6, 0xa9, 0x93, 0x4e, 0x15, + 0xb5, 0x67, 0x70, 0x8e, 0xc3, 0x77, 0x4f, 0xc9, 0x8a, 0x06, 0xd9, 0xb9, + 0xa6, 0x41, 0xb8, 0xfa, 0x4a, 0x13, 0x26, 0xdc, 0x2b, 0xc5, 0x82, 0xa0, + 0x74, 0x8c, 0x1e, 0xe9, 0xc0, 0x70, 0x15, 0x56, 0xec, 0x1f, 0x7e, 0x91, + 0x6e, 0x31, 0x42, 0x8b, 0xd5, 0xe2, 0x0e, 0x9c, 0xeb, 0xff, 0xbc, 0xf9, + 0x42, 0xd3, 0xb9, 0x1c, 0x5e, 0x46, 0x80, 0x90, 0x5f, 0xe1, 0x59, 0x22, + 0x13, 0x71, 0xd3, 0xd6, 0x66, 0x7a, 0xe0, 0x56, 0x04, 0x10, 0x59, 0x01, + 0xb3, 0xb6, 0xd2, 0xc7, 0xa7, 0x3b, 0xbc, 0xe6, 0x38, 0x44, 0xd5, 0x71, + 0x66, 0x1d, 0xb2, 0x63, 0x2f, 0xa9, 0x5e, 0x80, 0x92, 0x3c, 0x21, 0x0e, + 0xe1, 0xda, 0xd6, 0x1d, 0xcb, 0xce, 0xac, 0xe1, 0x5f, 0x97, 0x45, 0x8f, + 0xc1, 0x64, 0x16, 0xa6, 0x88, 0x2a, 0x36, 0x4a, 0x76, 0x64, 0x8f, 0x83, + 0x7a, 0x1d, 0xd8, 0x91, 0x90, 0x7b, 0x58, 0xb8, 0x1c, 0x7f, 0x56, 0x57, + 0x35, 0xfb, 0xf3, 0x1a, 0xcb, 0x7c, 0x66, 0x66, 0x04, 0x95, 0xee, 0x3a, + 0x80, 0xf0, 0xd4, 0x12, 0x3a, 0x7e, 0x7e, 0x5e, 0xb8, 0x55, 0x29, 0x23, + 0x06, 0xd3, 0x85, 0x0c, 0x99, 0x91, 0x42, 0xee, 0x5a, 0x30, 0x7f, 0x52, + 0x20, 0xb3, 0xe2, 0xe7, 0x39, 0x69, 0xb6, 0xfc, 0x42, 0x1e, 0x98, 0xd3, + 0x31, 0xa2, 0xfa, 0x81, 0x52, 0x69, 0x6d, 0x23, 0xf8, 0xc4, 0xc3, 0x3c, + 0x9b, 0x48, 0x75, 0xa8, 0xc7, 0xe7, 0x61, 0x81, 0x1f, 0xf7, 0xce, 0x10, + 0xaa, 0x13, 0xcb, 0x6e, 0x19, 0xc0, 0x4f, 0x6f, 0x90, 0xa8, 0x41, 0xea, + 0x49, 0xdf, 0xe4, 0xef, 0x84, 0x54, 0xb5, 0x37, 0xaf, 0x12, 0x75, 0x1a, + 0x11, 0x4b, 0x58, 0x7f, 0x63, 0x22, 0x33, 0xb1, 0xc8, 0x4d, 0xf2, 0x41, + 0x10, 0xbc, 0x37, 0xb5, 0xd5, 0xb2, 0x21, 0x32, 0x35, 0x9d, 0xf3, 0x8d, + 0xab, 0x66, 0x9d, 0x19, 0x12, 0x71, 0x45, 0xb3, 0x82, 0x5a, 0x5c, 0xff, + 0x2d, 0xcf, 0xf4, 0x5b, 0x56, 0xb8, 0x08, 0xb3, 0xd2, 0x43, 0x8c, 0xac, + 0xd2, 0xf8, 0xcc, 0x6d, 0x90, 0x97, 0xff, 0x12, 0x74, 0x97, 0xf8, 0xa4, + 0xe3, 0x95, 0xae, 0x92, 0xdc, 0x7e, 0x9d, 0x2b, 0xb4, 0x94, 0xc3, 0x8d, + 0x80, 0xe7, 0x77, 0x5c, 0x5b, 0xbb, 0x43, 0xdc, 0xa6, 0xe9, 0xbe, 0x20, + 0xcc, 0x9d, 0x8e, 0xa4, 0x2b, 0xf2, 0x72, 0xdc, 0x44, 0x61, 0x0f, 0xad, + 0x1a, 0x5e, 0xa5, 0x48, 0xe4, 0x42, 0xc5, 0xe4, 0xf1, 0x6d, 0x33, 0xdb, + 0xb2, 0x1b, 0x9f, 0xb2, 0xff, 0x18, 0x0e, 0x62, 0x35, 0x99, 0xed, 0x22, + 0x19, 0x4a, 0x5e, 0xb3, 0x3c, 0x07, 0x8f, 0x6e, 0x22, 0x5b, 0x16, 0x4a, + 0x9f, 0xef, 0xf3, 0xe7, 0xd6, 0x48, 0xe1, 0xb4, 0x3b, 0xab, 0x1b, 0x9e, + 0x53, 0xd7, 0x1b, 0xd9, 0x2d, 0x51, 0x8f, 0xe4, 0x1c, 0xab, 0xdd, 0xb9, + 0xe2, 0xee, 0xe4, 0xdd, 0x60, 0x04, 0x86, 0x6b, 0x4e, 0x7a, 0xc8, 0x09, + 0x51, 0xd1, 0x9b, 0x36, 0x9a, 0x36, 0x7f, 0xe8, 0x6b, 0x09, 0x6c, 0xee, + 0xad, 0x3a, 0x2f, 0xa8, 0x63, 0x92, 0x23, 0x2f, 0x7e, 0x00, 0xe2, 0xd1, + 0xbb, 0xd9, 0x5b, 0x5b, 0xfa, 0x4b, 0x83, 0x00, 0x19, 0x28, 0xfb, 0x7e, + 0xfe, 0x58, 0xab, 0xb7, 0x33, 0x45, 0x8f, 0x75, 0x9a, 0x54, 0x3d, 0x77, + 0x06, 0x75, 0x61, 0x4f, 0x5c, 0x93, 0xa0, 0xf9, 0xe8, 0xcf, 0xf6, 0x04, + 0x14, 0xda, 0x1b, 0x2e, 0x79, 0x35, 0xb8, 0xb4, 0xfa, 0x08, 0x27, 0x9a, + 0x03, 0x70, 0x78, 0x97, 0x8f, 0xae, 0x2e, 0xd5, 0x1c, 0xe0, 0x4d, 0x91, + 0x3a, 0xfe, 0x1a, 0x64, 0xd8, 0x49, 0xdf, 0x6c, 0x66, 0xac, 0xc9, 0x57, + 0x06, 0x72, 0xc0, 0xc0, 0x09, 0x71, 0x6a, 0xd0, 0xb0, 0x7d, 0x35, 0x3f, + 0x53, 0x17, 0x49, 0x38, 0x92, 0x22, 0x55, 0xf6, 0x58, 0x56, 0xa2, 0x42, + 0x77, 0x94, 0xb7, 0x28, 0x0a, 0xa0, 0xd2, 0xda, 0x25, 0xc1, 0xcc, 0x52, + 0x51, 0xd6, 0xba, 0x18, 0x0f, 0x0d, 0xe3, 0x7d, 0xd1, 0xda, 0xd9, 0x0c, + 0x5e, 0x3a, 0xca, 0xe9, 0xf1, 0xf5, 0x65, 0xfc, 0xc3, 0x99, 0x72, 0x25, + 0xf2, 0xc0, 0xa1, 0x8c, 0x43, 0x9d, 0xb2, 0xc9, 0xb1, 0x1a, 0x24, 0x34, + 0x57, 0xd8, 0xa7, 0x52, 0xa3, 0x39, 0x6e, 0x0b, 0xec, 0xbd, 0x5e, 0xc9, + 0x1f, 0x74, 0xed, 0xae, 0xe6, 0x4e, 0x49, 0xe8, 0x87, 0x3e, 0x46, 0x0d, + 0x40, 0x30, 0xda, 0x9d, 0xcf, 0xf5, 0x03, 0x1f, 0x38, 0x29, 0x3b, 0x66, + 0xe5, 0xc0, 0x89, 0x4c, 0xfc, 0x09, 0x62, 0x37, 0x01, 0xf9, 0x01, 0xab, + 0x8d, 0x53, 0x9c, 0x36, 0x5d, 0x36, 0x66, 0x8d, 0x87, 0xf4, 0xab, 0x37, + 0xb7, 0xf7, 0xe3, 0xdf, 0xc1, 0x52, 0xc0, 0x1d, 0x09, 0x92, 0x21, 0x47, + 0x49, 0x9a, 0x19, 0x38, 0x05, 0x62, 0xf3, 0x47, 0x80, 0x89, 0x1e, 0x70, + 0xa1, 0x57, 0xb7, 0x72, 0xd0, 0x41, 0x7a, 0x5c, 0x6a, 0x13, 0x8b, 0x6c, + 0xda, 0xdf, 0x6b, 0x01, 0x15, 0x20, 0xfa, 0xc8, 0x67, 0xee, 0xb2, 0x13, + 0xd8, 0x5f, 0x84, 0x30, 0x44, 0x8e, 0xf9, 0x2a, 0xae, 0x17, 0x53, 0x49, + 0xaa, 0x34, 0x31, 0x12, 0x31, 0xec, 0xf3, 0x25, 0x27, 0x53, 0x6b, 0xb5, + 0x63, 0xa6, 0xbc, 0xf1, 0x77, 0xd4, 0xb4, 0x77, 0xd1, 0xee, 0xad, 0x62, + 0x9d, 0x2c, 0x2e, 0x11, 0x0a, 0xd1, 0x87, 0xfe, 0xef, 0x77, 0x0e, 0xd1, + 0x38, 0xfe, 0xcc, 0x88, 0xaa, 0x1c, 0x06, 0x93, 0x25, 0x56, 0xfe, 0x0c, + 0x52, 0xe9, 0x7f, 0x4c, 0x3b, 0x2a, 0xfb, 0x40, 0x62, 0x29, 0x0a, 0x1d, + 0x58, 0x78, 0x8b, 0x09, 0x25, 0xaa, 0xc6, 0x8f, 0x66, 0x8f, 0xd1, 0x93, + 0x5a, 0xd6, 0x68, 0x35, 0x69, 0x13, 0x5d, 0x42, 0x35, 0x95, 0xcb, 0xc4, + 0xec, 0x17, 0x92, 0x96, 0xcb, 0x4a, 0xb9, 0x8f, 0xe5, 0xc4, 0x4a, 0xe7, + 0x54, 0x52, 0x4c, 0x64, 0x06, 0xac, 0x2f, 0x13, 0x32, 0x02, 0x47, 0x13, + 0x5c, 0xa2, 0x66, 0xdc, 0x36, 0x0c, 0x4f, 0xbb, 0x89, 0x58, 0x85, 0x16, + 0xf1, 0xf1, 0xff, 0xd2, 0x86, 0x54, 0x29, 0xb3, 0x7e, 0x2a, 0xbd, 0xf9, + 0x53, 0x8c, 0xa0, 0x60, 0x60, 0xb2, 0x90, 0x7f, 0x3a, 0x11, 0x5f, 0x2a, + 0x50, 0x74, 0x2a, 0xd1, 0x68, 0x78, 0xdb, 0x31, 0x1b, 0x8b, 0xee, 0xee, + 0x18, 0x97, 0xf3, 0x50, 0x84, 0xc1, 0x8f, 0xe1, 0xc6, 0x01, 0xb4, 0x16, + 0x65, 0x25, 0x0c, 0x03, 0xab, 0xed, 0x4f, 0xd6, 0xe6, 0x16, 0x23, 0xcc, + 0x42, 0x93, 0xff, 0xfa, 0x92, 0x63, 0x33, 0x9e, 0x36, 0xb0, 0xdc, 0x9a, + 0xb6, 0xaa, 0xd7, 0x48, 0xfe, 0x27, 0x01, 0xcf, 0x67, 0xc0, 0x75, 0xa0, + 0x86, 0x9a, 0xec, 0xa7, 0x2e, 0xb8, 0x7b, 0x00, 0x7f, 0xd4, 0xe3, 0xb3, + 0xfc, 0x48, 0xab, 0x50, 0x20, 0xd4, 0x0d, 0x58, 0x26, 0xc0, 0x3c, 0x09, + 0x0b, 0x80, 0x9e, 0xaf, 0x14, 0x3c, 0x0c, 0x6e, 0x69, 0xbc, 0x6c, 0x4e, + 0x50, 0x33, 0xb0, 0x07, 0x64, 0x6e, 0x77, 0x96, 0xc2, 0xe6, 0x3b, 0xd7, + 0xfe, 0xdc, 0xa4, 0x2f, 0x18, 0x5b, 0x53, 0xe5, 0xdd, 0xb6, 0xce, 0xeb, + 0x16, 0xb4, 0x25, 0xc6, 0xcb, 0xf2, 0x65, 0x3c, 0x4f, 0x94, 0xa5, 0x11, + 0x18, 0xeb, 0x7b, 0x62, 0x1d, 0xd5, 0x02, 0x35, 0x76, 0xf6, 0xb5, 0x20, + 0x27, 0x21, 0x9b, 0xab, 0xf4, 0xb6, 0x8f, 0x1a, 0x70, 0x1d, 0x12, 0xe3, + 0xb9, 0x8e, 0x29, 0x52, 0x25, 0xf4, 0xba, 0xb4, 0x25, 0x2c, 0x91, 0x11, + 0xf2, 0xae, 0x7b, 0xbe, 0xb6, 0x67, 0xd6, 0x08, 0xf8, 0x6f, 0xe7, 0xb0, + 0x16, 0xc5, 0xf6, 0xd5, 0xfb, 0x07, 0x71, 0x5b, 0x0e, 0xe1, 0x02, 0x03, + 0x01, 0x00, 0x01, 0xa3, 0x53, 0x30, 0x51, 0x30, 0x1d, 0x06, 0x03, 0x55, + 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xaa, 0xe7, 0x7f, 0xcf, 0xf8, 0xb4, + 0xe0, 0x8d, 0x39, 0x9a, 0x1d, 0x4f, 0x86, 0xa2, 0xac, 0x56, 0x32, 0xd9, + 0x58, 0xe3, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, + 0x16, 0x80, 0x14, 0xaa, 0xe7, 0x7f, 0xcf, 0xf8, 0xb4, 0xe0, 0x8d, 0x39, + 0x9a, 0x1d, 0x4f, 0x86, 0xa2, 0xac, 0x56, 0x32, 0xd9, 0x58, 0xe3, 0x30, + 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x04, 0x02, 0x00, + 0x00, 0x0a, 0x0a, 0x81, 0xb5, 0x2e, 0xac, 0x52, 0xab, 0x0f, 0xeb, 0xad, + 0x96, 0xd6, 0xd6, 0x59, 0x8f, 0x55, 0x15, 0x56, 0x70, 0xda, 0xd5, 0x75, + 0x47, 0x12, 0x9a, 0x0e, 0xd1, 0x65, 0x68, 0xe0, 0x51, 0x89, 0x59, 0xcc, + 0xe3, 0x5a, 0x1b, 0x85, 0x14, 0xa3, 0x1d, 0x9b, 0x3f, 0xd1, 0xa4, 0x42, + 0xb0, 0x89, 0x12, 0x93, 0xd3, 0x54, 0x19, 0x04, 0xa2, 0xaf, 0xaa, 0x60, + 0xca, 0x03, 0xc2, 0xae, 0x62, 0x8c, 0xb6, 0x31, 0x03, 0xd6, 0xa5, 0xf3, + 0x5e, 0x8d, 0x5c, 0x69, 0x4c, 0x7d, 0x81, 0x49, 0x20, 0x25, 0x41, 0xa4, + 0x2a, 0x95, 0x87, 0x36, 0xa3, 0x9b, 0x9e, 0x9f, 0xed, 0x85, 0xf3, 0xb1, + 0xf1, 0xe9, 0x1b, 0xbb, 0xe3, 0xbc, 0x3b, 0x11, 0x36, 0xca, 0xb9, 0x5f, + 0xee, 0x64, 0xde, 0x2a, 0x99, 0x27, 0x91, 0xc0, 0x54, 0x9e, 0x7a, 0xd4, + 0x89, 0x8c, 0xa0, 0xe3, 0xfd, 0x44, 0x6f, 0x02, 0x38, 0x3c, 0xee, 0x52, + 0x48, 0x1b, 0xd4, 0x25, 0x2b, 0xcb, 0x8e, 0xa8, 0x1b, 0x09, 0xd6, 0x30, + 0x51, 0x15, 0x6c, 0x5c, 0x03, 0x76, 0xad, 0x64, 0x45, 0x50, 0xa2, 0xe1, + 0x3c, 0x5a, 0x67, 0x87, 0xff, 0x8c, 0xed, 0x9a, 0x8d, 0x04, 0xc1, 0xac, + 0xf9, 0xca, 0xf5, 0x2a, 0x05, 0x9c, 0xdd, 0x78, 0xce, 0x99, 0x78, 0x7b, + 0xcd, 0x43, 0x10, 0x40, 0xf7, 0xb5, 0x27, 0x12, 0xec, 0xe9, 0xb2, 0x3f, + 0xf4, 0x5d, 0xd9, 0xbb, 0xf8, 0xc4, 0xc9, 0xa4, 0x46, 0x20, 0x41, 0x7f, + 0xeb, 0x79, 0xb0, 0x51, 0x8c, 0xf7, 0xc3, 0x2c, 0x16, 0xfe, 0x42, 0x59, + 0x77, 0xfe, 0x53, 0xfe, 0x19, 0x57, 0x58, 0x44, 0x6d, 0x12, 0xe2, 0x95, + 0xd0, 0xd3, 0x5a, 0xb5, 0x2d, 0xe5, 0x7e, 0xb4, 0xb3, 0xa9, 0xcc, 0x7d, + 0x53, 0x77, 0x81, 0x01, 0x0f, 0x0a, 0xf6, 0x86, 0x3c, 0x7d, 0xb5, 0x2c, + 0xbf, 0x62, 0xc3, 0xf5, 0x38, 0x89, 0x13, 0x84, 0x1f, 0x44, 0x2d, 0x87, + 0x5c, 0x23, 0x9e, 0x05, 0x62, 0x56, 0x3d, 0x71, 0x4d, 0xd0, 0xe3, 0x15, + 0xe9, 0x09, 0x9c, 0x1a, 0xc0, 0x9a, 0x19, 0x8b, 0x9c, 0xe9, 0xae, 0xde, + 0x62, 0x05, 0x23, 0xe2, 0xd0, 0x3f, 0xf5, 0xef, 0x04, 0x96, 0x4c, 0x87, + 0x34, 0x2f, 0xd5, 0x90, 0xde, 0xbf, 0x4b, 0x56, 0x12, 0x5f, 0xc6, 0xdc, + 0xa4, 0x1c, 0xc4, 0x53, 0x0c, 0xf9, 0xb4, 0xe4, 0x2c, 0xe7, 0x48, 0xbd, + 0xb1, 0xac, 0xf1, 0xc1, 0x8d, 0x53, 0x47, 0x84, 0xc0, 0x78, 0x0a, 0x5e, + 0xc2, 0x16, 0xff, 0xef, 0x97, 0x5b, 0x33, 0x85, 0x92, 0xcd, 0xd4, 0xbb, + 0x64, 0xee, 0xed, 0x17, 0x18, 0x43, 0x32, 0x99, 0x32, 0x36, 0x25, 0xf4, + 0x21, 0x3c, 0x2f, 0x55, 0xdc, 0x16, 0x06, 0x4d, 0x86, 0xa3, 0xa9, 0x34, + 0x22, 0xd5, 0xc3, 0xc8, 0x64, 0x3c, 0x4e, 0x3a, 0x69, 0xbd, 0xcf, 0xd7, + 0xee, 0x3f, 0x0d, 0x15, 0xeb, 0xfb, 0xbd, 0x91, 0x7f, 0xef, 0x48, 0xec, + 0x86, 0xb2, 0x78, 0xf7, 0x53, 0x90, 0x38, 0xb5, 0x04, 0x9c, 0xb7, 0xd7, + 0x9e, 0xaa, 0x15, 0xf7, 0xcd, 0xc2, 0x17, 0xd5, 0x8f, 0x82, 0x98, 0xa3, + 0xaf, 0x59, 0xf1, 0x71, 0xda, 0x6e, 0xaf, 0x97, 0x6d, 0x77, 0x72, 0xfd, + 0xa8, 0x80, 0x25, 0xce, 0x46, 0x04, 0x6e, 0x40, 0x15, 0x24, 0xc0, 0xf9, + 0xbf, 0x13, 0x16, 0x72, 0xcb, 0xb7, 0x10, 0xc7, 0x0a, 0xd6, 0x66, 0x96, + 0x5b, 0x27, 0x4d, 0x66, 0xc4, 0x2f, 0x21, 0x90, 0x9f, 0x8c, 0x24, 0xa0, + 0x0e, 0xa2, 0x89, 0x92, 0xd2, 0x44, 0x63, 0x06, 0xb2, 0xab, 0x07, 0x26, + 0xde, 0x03, 0x1d, 0xdb, 0x2a, 0x42, 0x5b, 0x4c, 0xf6, 0xfe, 0x53, 0xfa, + 0x80, 0x45, 0x8d, 0x75, 0xf6, 0x0e, 0x1d, 0xcc, 0x4c, 0x3b, 0xb0, 0x80, + 0x6d, 0x4c, 0xed, 0x7c, 0xe0, 0xd2, 0xe7, 0x62, 0x59, 0xb1, 0x5a, 0x5d, + 0x3a, 0xec, 0x86, 0x04, 0xfe, 0x26, 0xd1, 0x18, 0xed, 0x56, 0x7d, 0x67, + 0x56, 0x24, 0x6d, 0x7c, 0x6e, 0x8f, 0xc8, 0xa0, 0xba, 0x42, 0x0a, 0x33, + 0x38, 0x7a, 0x09, 0x03, 0xc2, 0xbf, 0x9b, 0x01, 0xdd, 0x03, 0x5a, 0xba, + 0x76, 0x04, 0xb1, 0xc3, 0x40, 0x23, 0x53, 0xbd, 0x64, 0x4e, 0x0f, 0xe7, + 0xc3, 0x4e, 0x48, 0xea, 0x19, 0x2b, 0x1c, 0xe4, 0x3d, 0x93, 0xd8, 0xf6, + 0xfb, 0xda, 0x3d, 0xeb, 0xed, 0xc2, 0xbd, 0x14, 0x57, 0x40, 0xde, 0xd1, + 0x74, 0x54, 0x1b, 0xa8, 0x39, 0xda, 0x73, 0x56, 0xd4, 0xbe, 0xab, 0xec, + 0xc7, 0x17, 0x4f, 0x91, 0xb6, 0xf6, 0xcb, 0x24, 0xc6, 0x1c, 0x07, 0xc4, + 0xf3, 0xd0, 0x5e, 0x8d, 0xfa, 0x44, 0x98, 0x5c, 0x87, 0x36, 0x75, 0xb6, + 0xa5, 0x31, 0xaa, 0xab, 0x7d, 0x38, 0x66, 0xb3, 0x18, 0x58, 0x65, 0x97, + 0x06, 0xfd, 0x61, 0x81, 0x71, 0xc5, 0x17, 0x8b, 0x19, 0x03, 0xc8, 0x58, + 0xec, 0x05, 0xca, 0x7b, 0x0f, 0xec, 0x9d, 0xb4, 0xbc, 0xa3, 0x20, 0x2e, + 0xf8, 0xe4, 0xb1, 0x82, 0xdc, 0x5a, 0xd2, 0x92, 0x9c, 0x43, 0x5d, 0x16, + 0x5b, 0x90, 0x80, 0xe4, 0xfb, 0x6e, 0x24, 0x6b, 0x8c, 0x1a, 0x35, 0xab, + 0xbd, 0x77, 0x7f, 0xf9, 0x61, 0x80, 0xa5, 0xab, 0xa3, 0x39, 0xc2, 0xc9, + 0x69, 0x3c, 0xfc, 0xb3, 0x9a, 0x05, 0x45, 0x03, 0x88, 0x8f, 0x8e, 0x23, + 0xf2, 0x0c, 0x4c, 0x54, 0xb9, 0x40, 0x3a, 0x31, 0x1a, 0x22, 0x67, 0x43, + 0x4a, 0x3e, 0xa0, 0x8c, 0x2d, 0x4d, 0x4f, 0xfc, 0xb5, 0x9b, 0x1f, 0xe1, + 0xef, 0x02, 0x54, 0xab, 0x8d, 0x75, 0x4d, 0x93, 0xba, 0x76, 0xe1, 0xbc, + 0x42, 0x7f, 0x6c, 0xcb, 0xf5, 0x47, 0xd6, 0x8a, 0xac, 0x5d, 0xe9, 0xbb, + 0x3a, 0x65, 0x2c, 0x81, 0xe5, 0xff, 0x27, 0x7e, 0x60, 0x64, 0x80, 0x42, + 0x8d, 0x36, 0x6b, 0x07, 0x76, 0x6a, 0xf1, 0xdf, 0x96, 0x17, 0x93, 0x21, + 0x5d, 0xe4, 0x6c, 0xce, 0x1c, 0xb9, 0x82, 0x45, 0x05, 0x61, 0xe2, 0x41, + 0x96, 0x03, 0x7d, 0x10, 0x8b, 0x3e, 0xc7, 0xe5, 0xcf, 0x08, 0xeb, 0x81, + 0xd3, 0x82, 0x1b, 0x04, 0x96, 0x93, 0x5a, 0xe2, 0x8c, 0x8e, 0x50, 0x33, + 0xf6, 0xf9, 0xf0, 0xfb, 0xb1, 0xd7, 0xc6, 0x97, 0xaa, 0xef, 0x0b, 0x87, + 0xe1, 0x34, 0x97, 0x78, 0x2e, 0x7c, 0x46, 0x11, 0xd5, 0x3c, 0xec, 0x38, + 0x70, 0x59, 0x14, 0x65, 0x4d, 0x0e, 0xd1, 0xeb, 0x49, 0xb3, 0x99, 0x6f, + 0x87, 0xf1, 0x79, 0x21, 0xd9, 0x5c, 0x37, 0xb2, 0xfe, 0xc4, 0x7a, 0xc1, + 0x67, 0xbd, 0x02, 0xfc, 0x02, 0xab, 0x2f, 0xf5, 0x0f, 0xa7, 0xae, 0x90, + 0xc2, 0xaf, 0xdb, 0xd1, 0x96, 0xb2, 0x92, 0x5a, 0xfb, 0xca, 0x28, 0x74, + 0x17, 0xed, 0xda, 0x2c, 0x9f, 0xb4, 0x2d, 0xf5, 0x71, 0x20, 0x64, 0x2d, + 0x44, 0xe5, 0xa3, 0xa0, 0x94, 0x6f, 0x20, 0xb3, 0x73, 0x96, 0x40, 0x06, + 0x9b, 0x25, 0x47, 0x4b, 0xe0, 0x63, 0x91, 0xd9, 0xda, 0xf3, 0xc3, 0xe5, + 0x3a, 0x3c, 0xb7, 0x5f, 0xab, 0x1e, 0x51, 0x17, 0x4f, 0xec, 0xc1, 0x6d, + 0x82, 0x79, 0x8e, 0xba, 0x7c, 0x47, 0x8e, 0x99, 0x00, 0x17, 0x9e, 0xda, + 0x10, 0x42, 0x70, 0x25, 0x42, 0x84, 0xc8, 0xb1, 0x95, 0x56, 0xb2, 0x08, + 0xa0, 0x4f, 0xdc, 0xcd, 0x9e, 0x31, 0x4b, 0x0c, 0x0b, 0x03, 0x5d, 0x2c, + 0x26, 0xbc, 0xa9, 0x4b, 0x19, 0xdf, 0x90, 0x01, 0x9a, 0xe0, 0x06, 0x05, + 0x13, 0x34, 0x9d, 0x34, 0xb8, 0xef, 0x13, 0x3a, 0x20, 0xf5, 0x74, 0x02, + 0x70, 0x3b, 0x41, 0x60, 0x1f, 0x5e, 0x76, 0x0a, 0xb1, 0x17, 0xd5, 0xcf, + 0x79, 0xef, 0xf7, 0xab, 0xe7, 0xd6, 0x0f, 0xad, 0x85, 0x2c, 0x52, 0x67, + 0xb5, 0xa0, 0x4a, 0xfd, 0xaf};
\ No newline at end of file diff --git a/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc index 08781af71..28fdc6631 100644 --- a/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc @@ -345,8 +345,8 @@ TEST_P(TlsConnectTls13, TestTls13ZeroRttNoAlpnClient) { TEST_P(TlsConnectTls13, TestTls13ZeroRttAlpnChangeBoth) { EnableAlpn(); SetupForZeroRtt(); - static const uint8_t alpn[] = {0x01, 0x62}; // "b" - EnableAlpn(alpn, sizeof(alpn)); + static const std::vector<uint8_t> alpn({0x01, 0x62}); // "b" + EnableAlpn(alpn); client_->Set0RttEnabled(true); server_->Set0RttEnabled(true); ExpectResumption(RESUME_TICKET); diff --git a/security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc index f0c57e8b1..6be3b61f8 100644 --- a/security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc @@ -8,9 +8,6 @@ #include "sslerr.h" #include "sslproto.h" -// This is an internal header, used to get TLS_1_3_DRAFT_VERSION. -#include "ssl3prot.h" - #include <memory> #include "databuffer.h" @@ -21,7 +18,6 @@ namespace nss_test { -static const uint8_t kD13 = TLS_1_3_DRAFT_VERSION; // This is a 1-RTT ClientHello with ECDHE. const static uint8_t kCannedTls13ClientHello[] = { 0x01, 0x00, 0x00, 0xcf, 0x03, 0x03, 0x6c, 0xb3, 0x46, 0x81, 0xc8, 0x1a, @@ -42,16 +38,7 @@ const static uint8_t kCannedTls13ClientHello[] = { 0x1e, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x02, 0x03, 0x08, 0x04, 0x08, 0x05, 0x08, 0x06, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x02, 0x01, 0x04, 0x02, 0x05, 0x02, 0x06, 0x02, 0x02, 0x02}; - -const static uint8_t kCannedTls13ServerHello[] = { - 0x03, 0x03, 0x9c, 0xbc, 0x14, 0x9b, 0x0e, 0x2e, 0xfa, 0x0d, 0xf3, - 0xf0, 0x5c, 0x70, 0x7a, 0xe0, 0xd1, 0x9b, 0x3e, 0x5a, 0x44, 0x6b, - 0xdf, 0xe5, 0xc2, 0x28, 0x64, 0xf7, 0x00, 0xc1, 0x9c, 0x08, 0x76, - 0x08, 0x00, 0x13, 0x01, 0x00, 0x00, 0x2e, 0x00, 0x33, 0x00, 0x24, - 0x00, 0x1d, 0x00, 0x20, 0xc2, 0xcf, 0x23, 0x17, 0x64, 0x23, 0x03, - 0xf0, 0xfb, 0x45, 0x98, 0x26, 0xd1, 0x65, 0x24, 0xa1, 0x6c, 0xa9, - 0x80, 0x8f, 0x2c, 0xac, 0x0a, 0xea, 0x53, 0x3a, 0xcb, 0xe3, 0x08, - 0x84, 0xae, 0x19, 0x00, 0x2b, 0x00, 0x02, 0x7f, kD13}; +static const size_t kFirstFragmentSize = 20; static const char *k0RttData = "ABCDEF"; TEST_P(TlsAgentTest, EarlyFinished) { @@ -74,8 +61,9 @@ TEST_P(TlsAgentTestClient13, CannedHello) { DataBuffer buffer; EnsureInit(); DataBuffer server_hello; - MakeHandshakeMessage(kTlsHandshakeServerHello, kCannedTls13ServerHello, - sizeof(kCannedTls13ServerHello), &server_hello); + auto sh = MakeCannedTls13ServerHello(); + MakeHandshakeMessage(kTlsHandshakeServerHello, sh.data(), sh.len(), + &server_hello); MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3, server_hello.data(), server_hello.len(), &buffer); ProcessMessage(buffer, TlsAgent::STATE_CONNECTING); @@ -83,8 +71,9 @@ TEST_P(TlsAgentTestClient13, CannedHello) { TEST_P(TlsAgentTestClient13, EncryptedExtensionsInClear) { DataBuffer server_hello; - MakeHandshakeMessage(kTlsHandshakeServerHello, kCannedTls13ServerHello, - sizeof(kCannedTls13ServerHello), &server_hello); + auto sh = MakeCannedTls13ServerHello(); + MakeHandshakeMessage(kTlsHandshakeServerHello, sh.data(), sh.len(), + &server_hello); DataBuffer encrypted_extensions; MakeHandshakeMessage(kTlsHandshakeEncryptedExtensions, nullptr, 0, &encrypted_extensions, 1); @@ -100,19 +89,21 @@ TEST_P(TlsAgentTestClient13, EncryptedExtensionsInClear) { TEST_F(TlsAgentStreamTestClient, EncryptedExtensionsInClearTwoPieces) { DataBuffer server_hello; - MakeHandshakeMessage(kTlsHandshakeServerHello, kCannedTls13ServerHello, - sizeof(kCannedTls13ServerHello), &server_hello); + auto sh = MakeCannedTls13ServerHello(); + MakeHandshakeMessage(kTlsHandshakeServerHello, sh.data(), sh.len(), + &server_hello); DataBuffer encrypted_extensions; MakeHandshakeMessage(kTlsHandshakeEncryptedExtensions, nullptr, 0, &encrypted_extensions, 1); server_hello.Append(encrypted_extensions); DataBuffer buffer; MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3, - server_hello.data(), 20, &buffer); + server_hello.data(), kFirstFragmentSize, &buffer); DataBuffer buffer2; MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3, - server_hello.data() + 20, server_hello.len() - 20, &buffer2); + server_hello.data() + kFirstFragmentSize, + server_hello.len() - kFirstFragmentSize, &buffer2); EnsureInit(); agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_3, @@ -124,15 +115,15 @@ TEST_F(TlsAgentStreamTestClient, EncryptedExtensionsInClearTwoPieces) { } TEST_F(TlsAgentDgramTestClient, EncryptedExtensionsInClearTwoPieces) { + auto sh = MakeCannedTls13ServerHello(); DataBuffer server_hello_frag1; - MakeHandshakeMessageFragment( - kTlsHandshakeServerHello, kCannedTls13ServerHello, - sizeof(kCannedTls13ServerHello), &server_hello_frag1, 0, 0, 20); + MakeHandshakeMessageFragment(kTlsHandshakeServerHello, sh.data(), sh.len(), + &server_hello_frag1, 0, 0, kFirstFragmentSize); DataBuffer server_hello_frag2; - MakeHandshakeMessageFragment( - kTlsHandshakeServerHello, kCannedTls13ServerHello + 20, - sizeof(kCannedTls13ServerHello), &server_hello_frag2, 0, 20, - sizeof(kCannedTls13ServerHello) - 20); + MakeHandshakeMessageFragment(kTlsHandshakeServerHello, + sh.data() + kFirstFragmentSize, sh.len(), + &server_hello_frag2, 0, kFirstFragmentSize, + sh.len() - kFirstFragmentSize); DataBuffer encrypted_extensions; MakeHandshakeMessage(kTlsHandshakeEncryptedExtensions, nullptr, 0, &encrypted_extensions, 1); @@ -154,6 +145,35 @@ TEST_F(TlsAgentDgramTestClient, EncryptedExtensionsInClearTwoPieces) { SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); } +TEST_F(TlsAgentDgramTestClient, AckWithBogusLengthField) { + EnsureInit(); + // Length doesn't match + const uint8_t ackBuf[] = {0x00, 0x08, 0x00}; + DataBuffer record; + MakeRecord(variant_, kTlsAckType, SSL_LIBRARY_VERSION_TLS_1_2, ackBuf, + sizeof(ackBuf), &record, 0); + agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_3, + SSL_LIBRARY_VERSION_TLS_1_3); + ExpectAlert(kTlsAlertDecodeError); + ProcessMessage(record, TlsAgent::STATE_ERROR, + SSL_ERROR_RX_MALFORMED_DTLS_ACK); +} + +TEST_F(TlsAgentDgramTestClient, AckWithNonEvenLength) { + EnsureInit(); + // Length isn't a multiple of 8 + const uint8_t ackBuf[] = {0x00, 0x01, 0x00}; + DataBuffer record; + MakeRecord(variant_, kTlsAckType, SSL_LIBRARY_VERSION_TLS_1_2, ackBuf, + sizeof(ackBuf), &record, 0); + agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_3, + SSL_LIBRARY_VERSION_TLS_1_3); + // Because we haven't negotiated the version, + // ssl3_DecodeError() sends an older (pre-TLS error). + ExpectAlert(kTlsAlertIllegalParameter); + ProcessMessage(record, TlsAgent::STATE_ERROR, SSL_ERROR_BAD_SERVER); +} + TEST_F(TlsAgentStreamTestClient, Set0RttOptionThenWrite) { EnsureInit(); agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1, diff --git a/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc index 7f2b2840d..e2a30e6bc 100644 --- a/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc @@ -155,8 +155,8 @@ TEST_P(TlsConnectTls12, ClientAuthBigRsaCheckSigAlg) { class TlsZeroCertificateRequestSigAlgsFilter : public TlsHandshakeFilter { public: - TlsZeroCertificateRequestSigAlgsFilter(const std::shared_ptr<TlsAgent>& agent) - : TlsHandshakeFilter(agent, {kTlsHandshakeCertificateRequest}) {} + TlsZeroCertificateRequestSigAlgsFilter(const std::shared_ptr<TlsAgent>& a) + : TlsHandshakeFilter(a, {kTlsHandshakeCertificateRequest}) {} virtual PacketFilter::Action FilterHandshake( const TlsHandshakeFilter::HandshakeHeader& header, const DataBuffer& input, DataBuffer* output) { @@ -366,6 +366,50 @@ TEST_P(TlsConnectTls12, SignatureAlgorithmDrop) { server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); } +// Replaces the signature scheme in a TLS 1.3 CertificateVerify message. +class TlsReplaceSignatureSchemeFilter : public TlsHandshakeFilter { + public: + TlsReplaceSignatureSchemeFilter(const std::shared_ptr<TlsAgent>& a, + SSLSignatureScheme scheme) + : TlsHandshakeFilter(a, {kTlsHandshakeCertificateVerify}), + scheme_(scheme) { + EnableDecryption(); + } + + protected: + virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, + const DataBuffer& input, + DataBuffer* output) { + *output = input; + output->Write(0, scheme_, 2); + return CHANGE; + } + + private: + SSLSignatureScheme scheme_; +}; + +TEST_P(TlsConnectTls13, UnsupportedSignatureSchemeAlert) { + EnsureTlsSetup(); + MakeTlsFilter<TlsReplaceSignatureSchemeFilter>(server_, ssl_sig_none); + + ConnectExpectAlert(client_, kTlsAlertIllegalParameter); + server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); + client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CERT_VERIFY); +} + +TEST_P(TlsConnectTls13, InconsistentSignatureSchemeAlert) { + EnsureTlsSetup(); + + // This won't work because we use an RSA cert by default. + MakeTlsFilter<TlsReplaceSignatureSchemeFilter>( + server_, ssl_sig_ecdsa_secp256r1_sha256); + + ConnectExpectAlert(client_, kTlsAlertIllegalParameter); + server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); + client_->CheckErrorCode(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM); +} + TEST_P(TlsConnectTls12Plus, RequestClientAuthWithSha384) { server_->SetSignatureSchemes(SignatureSchemeRsaSha384, PR_ARRAY_SIZE(SignatureSchemeRsaSha384)); diff --git a/security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc index fa2238be7..ec289bdd6 100644 --- a/security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc @@ -166,8 +166,8 @@ class TlsCipherSuiteTestBase : public TlsConnectTestBase { case ssl_calg_seed: break; } - EXPECT_TRUE(false) << "No limit for " << csinfo_.cipherSuiteName; - return 1ULL < 48; + ADD_FAILURE() << "No limit for " << csinfo_.cipherSuiteName; + return 0; } uint64_t last_safe_write() const { @@ -246,12 +246,13 @@ TEST_P(TlsCipherSuiteTest, ReadLimit) { client_->SendData(10, 10); server_->ReadBytes(); // This should be OK. + server_->ReadBytes(); // Read twice to flush any 1,N-1 record splitting. } else { // In TLS 1.3, reading or writing triggers a KeyUpdate. That would mean // that the sequence numbers would reset and we wouldn't hit the limit. So - // we move the sequence number to one less than the limit directly and don't - // test sending and receiving just before the limit. - uint64_t last = record_limit() - 1; + // move the sequence number to the limit directly and don't test sending and + // receiving just before the limit. + uint64_t last = record_limit(); EXPECT_EQ(SECSuccess, SSLInt_AdvanceReadSeqNum(server_->ssl_fd(), last)); } diff --git a/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc index c2f582a93..5be62e506 100644 --- a/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc @@ -68,6 +68,7 @@ static const uint16_t kManyExtensions[] = { ssl_next_proto_nego_xtn, ssl_renegotiation_info_xtn, ssl_tls13_short_header_xtn, + ssl_record_size_limit_xtn, 1, 0xffff}; // The list here includes all extensions we expect to use (SSL_MAX_EXTENSIONS), diff --git a/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc index cdafa7a84..b99461632 100644 --- a/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc @@ -103,8 +103,8 @@ TEST_P(TlsConnectGenericPre13, ConnectFfdheServer) { class TlsDheServerKeyExchangeDamager : public TlsHandshakeFilter { public: - TlsDheServerKeyExchangeDamager(const std::shared_ptr<TlsAgent>& agent) - : TlsHandshakeFilter(agent, {kTlsHandshakeServerKeyExchange}) {} + TlsDheServerKeyExchangeDamager(const std::shared_ptr<TlsAgent>& a) + : TlsHandshakeFilter(a, {kTlsHandshakeServerKeyExchange}) {} virtual PacketFilter::Action FilterHandshake( const TlsHandshakeFilter::HandshakeHeader& header, const DataBuffer& input, DataBuffer* output) { @@ -141,9 +141,9 @@ class TlsDheSkeChangeY : public TlsHandshakeFilter { kYZeroPad }; - TlsDheSkeChangeY(const std::shared_ptr<TlsAgent>& agent, - uint8_t handshake_type, ChangeYTo change) - : TlsHandshakeFilter(agent, {handshake_type}), change_Y_(change) {} + TlsDheSkeChangeY(const std::shared_ptr<TlsAgent>& a, uint8_t handshake_type, + ChangeYTo change) + : TlsHandshakeFilter(a, {handshake_type}), change_Y_(change) {} protected: void ChangeY(const DataBuffer& input, DataBuffer* output, size_t offset, @@ -208,9 +208,9 @@ class TlsDheSkeChangeY : public TlsHandshakeFilter { class TlsDheSkeChangeYServer : public TlsDheSkeChangeY { public: - TlsDheSkeChangeYServer(const std::shared_ptr<TlsAgent>& agent, - ChangeYTo change, bool modify) - : TlsDheSkeChangeY(agent, kTlsHandshakeServerKeyExchange, change), + TlsDheSkeChangeYServer(const std::shared_ptr<TlsAgent>& a, ChangeYTo change, + bool modify) + : TlsDheSkeChangeY(a, kTlsHandshakeServerKeyExchange, change), modify_(modify), p_() {} @@ -247,9 +247,9 @@ class TlsDheSkeChangeYServer : public TlsDheSkeChangeY { class TlsDheSkeChangeYClient : public TlsDheSkeChangeY { public: TlsDheSkeChangeYClient( - const std::shared_ptr<TlsAgent>& agent, ChangeYTo change, + const std::shared_ptr<TlsAgent>& a, ChangeYTo change, std::shared_ptr<const TlsDheSkeChangeYServer> server_filter) - : TlsDheSkeChangeY(agent, kTlsHandshakeClientKeyExchange, change), + : TlsDheSkeChangeY(a, kTlsHandshakeClientKeyExchange, change), server_filter_(server_filter) {} protected: @@ -357,8 +357,8 @@ INSTANTIATE_TEST_CASE_P( class TlsDheSkeMakePEven : public TlsHandshakeFilter { public: - TlsDheSkeMakePEven(const std::shared_ptr<TlsAgent>& agent) - : TlsHandshakeFilter(agent, {kTlsHandshakeServerKeyExchange}) {} + TlsDheSkeMakePEven(const std::shared_ptr<TlsAgent>& a) + : TlsHandshakeFilter(a, {kTlsHandshakeServerKeyExchange}) {} virtual PacketFilter::Action FilterHandshake( const TlsHandshakeFilter::HandshakeHeader& header, @@ -390,8 +390,8 @@ TEST_P(TlsConnectGenericPre13, MakeDhePEven) { class TlsDheSkeZeroPadP : public TlsHandshakeFilter { public: - TlsDheSkeZeroPadP(const std::shared_ptr<TlsAgent>& agent) - : TlsHandshakeFilter(agent, {kTlsHandshakeServerKeyExchange}) {} + TlsDheSkeZeroPadP(const std::shared_ptr<TlsAgent>& a) + : TlsHandshakeFilter(a, {kTlsHandshakeServerKeyExchange}) {} virtual PacketFilter::Action FilterHandshake( const TlsHandshakeFilter::HandshakeHeader& header, @@ -475,6 +475,45 @@ TEST_P(TlsConnectTls13, NamedGroupMismatch13) { client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); } +// Replace the key share in the server key exchange message with one that's +// larger than 8192 bits. +class TooLongDHEServerKEXFilter : public TlsHandshakeFilter { + public: + TooLongDHEServerKEXFilter(const std::shared_ptr<TlsAgent>& server) + : TlsHandshakeFilter(server, {kTlsHandshakeServerKeyExchange}) {} + + protected: + virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, + const DataBuffer& input, + DataBuffer* output) { + // Replace the server key exchange message very large DH shares that are + // not supported by NSS. + const uint32_t share_len = 0x401; + const uint8_t zero_share[share_len] = {0x80}; + size_t offset = 0; + // Write dh_p. + offset = output->Write(offset, share_len, 2); + offset = output->Write(offset, zero_share, share_len); + // Write dh_g. + offset = output->Write(offset, share_len, 2); + offset = output->Write(offset, zero_share, share_len); + // Write dh_Y. + offset = output->Write(offset, share_len, 2); + offset = output->Write(offset, zero_share, share_len); + + return CHANGE; + } +}; + +TEST_P(TlsConnectGenericPre13, TooBigDHGroup) { + EnableOnlyDheCiphers(); + MakeTlsFilter<TooLongDHEServerKEXFilter>(server_); + client_->SetOption(SSL_REQUIRE_DH_NAMED_GROUPS, PR_FALSE); + ConnectExpectAlert(client_, kTlsAlertIllegalParameter); + server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); + client_->CheckErrorCode(SSL_ERROR_DH_KEY_TOO_LONG); +} + // Even though the client doesn't have DHE groups enabled the server assumes it // does. The client requires named groups and thus does not accept FF3072 as // custom group in contrast to the previous test. @@ -546,9 +585,9 @@ TEST_P(TlsConnectTls13, ResumeFfdhe) { class TlsDheSkeChangeSignature : public TlsHandshakeFilter { public: - TlsDheSkeChangeSignature(const std::shared_ptr<TlsAgent>& agent, - uint16_t version, const uint8_t* data, size_t len) - : TlsHandshakeFilter(agent, {kTlsHandshakeServerKeyExchange}), + TlsDheSkeChangeSignature(const std::shared_ptr<TlsAgent>& a, uint16_t version, + const uint8_t* data, size_t len) + : TlsHandshakeFilter(a, {kTlsHandshakeServerKeyExchange}), version_(version), data_(data), len_(len) {} diff --git a/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc index ee8906deb..e5b52ff06 100644 --- a/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc @@ -66,7 +66,8 @@ TEST_P(TlsConnectDatagramPre13, DropServerSecondFlightThrice) { Connect(); } -class TlsDropDatagram13 : public TlsConnectDatagram13 { +class TlsDropDatagram13 : public TlsConnectDatagram13, + public ::testing::WithParamInterface<bool> { public: TlsDropDatagram13() : client_filters_(), @@ -77,6 +78,9 @@ class TlsDropDatagram13 : public TlsConnectDatagram13 { void SetUp() override { TlsConnectDatagram13::SetUp(); ConfigureSessionCache(RESUME_NONE, RESUME_NONE); + int short_header = GetParam() ? PR_TRUE : PR_FALSE; + client_->SetOption(SSL_ENABLE_DTLS_SHORT_HEADER, short_header); + server_->SetOption(SSL_ENABLE_DTLS_SHORT_HEADER, short_header); SetFilters(); } @@ -138,10 +142,13 @@ class TlsDropDatagram13 : public TlsConnectDatagram13 { void CheckAcks(const DropAckChain& chain, size_t index, std::vector<uint64_t> acks) { const DataBuffer& buf = chain.ack_->record(index).buffer; - size_t offset = 0; + size_t offset = 2; + uint64_t len; - EXPECT_EQ(acks.size() * 8, buf.len()); - if ((acks.size() * 8) != buf.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)); @@ -186,7 +193,7 @@ class TlsDropDatagram13 : public TlsConnectDatagram13 { // to the client upon receiving the client Finished. // Dropping complete first and second flights does not produce // ACKs -TEST_F(TlsDropDatagram13, DropClientFirstFlightOnce) { +TEST_P(TlsDropDatagram13, DropClientFirstFlightOnce) { client_filters_.drop_->Reset({0}); StartConnect(); client_->Handshake(); @@ -195,7 +202,7 @@ TEST_F(TlsDropDatagram13, DropClientFirstFlightOnce) { CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); } -TEST_F(TlsDropDatagram13, DropServerFirstFlightOnce) { +TEST_P(TlsDropDatagram13, DropServerFirstFlightOnce) { server_filters_.drop_->Reset(0xff); StartConnect(); client_->Handshake(); @@ -209,7 +216,7 @@ TEST_F(TlsDropDatagram13, DropServerFirstFlightOnce) { // Dropping the server's first record also does not produce // an ACK because the next record is ignored. // TODO(ekr@rtfm.com): We should generate an empty ACK. -TEST_F(TlsDropDatagram13, DropServerFirstRecordOnce) { +TEST_P(TlsDropDatagram13, DropServerFirstRecordOnce) { server_filters_.drop_->Reset({0}); StartConnect(); client_->Handshake(); @@ -221,7 +228,7 @@ TEST_F(TlsDropDatagram13, DropServerFirstRecordOnce) { // Dropping the second packet of the server's flight should // produce an ACK. -TEST_F(TlsDropDatagram13, DropServerSecondRecordOnce) { +TEST_P(TlsDropDatagram13, DropServerSecondRecordOnce) { server_filters_.drop_->Reset({1}); StartConnect(); client_->Handshake(); @@ -235,7 +242,7 @@ TEST_F(TlsDropDatagram13, DropServerSecondRecordOnce) { // Drop the server ACK and verify that the client retransmits // the ClientHello. -TEST_F(TlsDropDatagram13, DropServerAckOnce) { +TEST_P(TlsDropDatagram13, DropServerAckOnce) { StartConnect(); client_->Handshake(); server_->Handshake(); @@ -263,7 +270,7 @@ TEST_F(TlsDropDatagram13, DropServerAckOnce) { } // Drop the client certificate verify. -TEST_F(TlsDropDatagram13, DropClientCertVerify) { +TEST_P(TlsDropDatagram13, DropClientCertVerify) { StartConnect(); client_->SetupClientAuth(); server_->RequestClientAuth(true); @@ -284,7 +291,7 @@ TEST_F(TlsDropDatagram13, DropClientCertVerify) { } // Shrink the MTU down so that certs get split and drop the first piece. -TEST_F(TlsDropDatagram13, DropFirstHalfOfServerCertificate) { +TEST_P(TlsDropDatagram13, DropFirstHalfOfServerCertificate) { server_filters_.drop_->Reset({2}); StartConnect(); ShrinkPostServerHelloMtu(); @@ -311,7 +318,7 @@ TEST_F(TlsDropDatagram13, DropFirstHalfOfServerCertificate) { } // Shrink the MTU down so that certs get split and drop the second piece. -TEST_F(TlsDropDatagram13, DropSecondHalfOfServerCertificate) { +TEST_P(TlsDropDatagram13, DropSecondHalfOfServerCertificate) { server_filters_.drop_->Reset({3}); StartConnect(); ShrinkPostServerHelloMtu(); @@ -524,11 +531,11 @@ class TlsFragmentationAndRecoveryTest : public TlsDropDatagram13 { size_t cert_len_; }; -TEST_F(TlsFragmentationAndRecoveryTest, DropFirstHalf) { RunTest(0); } +TEST_P(TlsFragmentationAndRecoveryTest, DropFirstHalf) { RunTest(0); } -TEST_F(TlsFragmentationAndRecoveryTest, DropSecondHalf) { RunTest(1); } +TEST_P(TlsFragmentationAndRecoveryTest, DropSecondHalf) { RunTest(1); } -TEST_F(TlsDropDatagram13, NoDropsDuringZeroRtt) { +TEST_P(TlsDropDatagram13, NoDropsDuringZeroRtt) { SetupForZeroRtt(); SetFilters(); std::cerr << "Starting second handshake" << std::endl; @@ -546,7 +553,7 @@ TEST_F(TlsDropDatagram13, NoDropsDuringZeroRtt) { 0x0002000000000000ULL}); // Finished } -TEST_F(TlsDropDatagram13, DropEEDuringZeroRtt) { +TEST_P(TlsDropDatagram13, DropEEDuringZeroRtt) { SetupForZeroRtt(); SetFilters(); std::cerr << "Starting second handshake" << std::endl; @@ -591,7 +598,7 @@ class TlsReorderDatagram13 : public TlsDropDatagram13 { // Reorder the server records so that EE comes at the end // of the flight and will still produce an ACK. -TEST_F(TlsDropDatagram13, ReorderServerEE) { +TEST_P(TlsDropDatagram13, ReorderServerEE) { server_filters_.drop_->Reset({1}); StartConnect(); client_->Handshake(); @@ -647,7 +654,7 @@ class TlsSendCipherSpecCapturer { std::vector<std::shared_ptr<TlsCipherSpec>> send_cipher_specs_; }; -TEST_F(TlsDropDatagram13, SendOutOfOrderAppWithHandshakeKey) { +TEST_P(TlsDropDatagram13, SendOutOfOrderAppWithHandshakeKey) { StartConnect(); TlsSendCipherSpecCapturer capturer(client_); client_->Handshake(); @@ -662,9 +669,9 @@ TEST_F(TlsDropDatagram13, SendOutOfOrderAppWithHandshakeKey) { auto spec = capturer.spec(0); ASSERT_NE(nullptr, spec.get()); ASSERT_EQ(2, spec->epoch()); - ASSERT_TRUE(client_->SendEncryptedRecord( - spec, SSL_LIBRARY_VERSION_DTLS_1_2_WIRE, 0x0002000000000002, - kTlsApplicationDataType, DataBuffer(buf, sizeof(buf)))); + ASSERT_TRUE(client_->SendEncryptedRecord(spec, 0x0002000000000002, + kTlsApplicationDataType, + DataBuffer(buf, sizeof(buf)))); // Now have the server consume the bogus message. server_->ExpectSendAlert(illegal_parameter, kTlsAlertFatal); @@ -673,7 +680,7 @@ TEST_F(TlsDropDatagram13, SendOutOfOrderAppWithHandshakeKey) { EXPECT_EQ(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE, PORT_GetError()); } -TEST_F(TlsDropDatagram13, SendOutOfOrderHsNonsenseWithHandshakeKey) { +TEST_P(TlsDropDatagram13, SendOutOfOrderHsNonsenseWithHandshakeKey) { StartConnect(); TlsSendCipherSpecCapturer capturer(client_); client_->Handshake(); @@ -688,9 +695,9 @@ TEST_F(TlsDropDatagram13, SendOutOfOrderHsNonsenseWithHandshakeKey) { auto spec = capturer.spec(0); ASSERT_NE(nullptr, spec.get()); ASSERT_EQ(2, spec->epoch()); - ASSERT_TRUE(client_->SendEncryptedRecord( - spec, SSL_LIBRARY_VERSION_DTLS_1_2_WIRE, 0x0002000000000002, - kTlsHandshakeType, DataBuffer(buf, sizeof(buf)))); + ASSERT_TRUE(client_->SendEncryptedRecord(spec, 0x0002000000000002, + kTlsHandshakeType, + DataBuffer(buf, sizeof(buf)))); server_->Handshake(); EXPECT_EQ(2UL, server_filters_.ack_->count()); // The server acknowledges client Finished twice. @@ -700,7 +707,7 @@ TEST_F(TlsDropDatagram13, SendOutOfOrderHsNonsenseWithHandshakeKey) { // Shrink the MTU down so that certs get split and then swap the first and // second pieces of the server certificate. -TEST_F(TlsReorderDatagram13, ReorderServerCertificate) { +TEST_P(TlsReorderDatagram13, ReorderServerCertificate) { StartConnect(); ShrinkPostServerHelloMtu(); client_->Handshake(); @@ -722,7 +729,7 @@ TEST_F(TlsReorderDatagram13, ReorderServerCertificate) { CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); } -TEST_F(TlsReorderDatagram13, DataAfterEOEDDuringZeroRtt) { +TEST_P(TlsReorderDatagram13, DataAfterEOEDDuringZeroRtt) { SetupForZeroRtt(); SetFilters(); std::cerr << "Starting second handshake" << std::endl; @@ -761,7 +768,7 @@ TEST_F(TlsReorderDatagram13, DataAfterEOEDDuringZeroRtt) { EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()); } -TEST_F(TlsReorderDatagram13, DataAfterFinDuringZeroRtt) { +TEST_P(TlsReorderDatagram13, DataAfterFinDuringZeroRtt) { SetupForZeroRtt(); SetFilters(); std::cerr << "Starting second handshake" << std::endl; @@ -812,12 +819,17 @@ static void GetCipherAndLimit(uint16_t version, uint16_t* cipher, *cipher = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256; *limit = (1ULL << 48) - 1; } else { + // This test probably isn't especially useful for TLS 1.3, which has a much + // shorter sequence number encoding. That space can probably be searched in + // a reasonable amount of time. *cipher = TLS_CHACHA20_POLY1305_SHA256; - *limit = (1ULL << 48) - 1; + // Assume that we are starting with an expected sequence number of 0. + *limit = (1ULL << 29) - 1; } } // This simulates a huge number of drops on one side. +// See Bug 12965514 where a large gap was handled very inefficiently. TEST_P(TlsConnectDatagram, MissLotsOfPackets) { uint16_t cipher; uint64_t limit; @@ -834,6 +846,17 @@ TEST_P(TlsConnectDatagram, MissLotsOfPackets) { SendReceive(); } +// Send a sequence number of 0xfffffffd and it should be interpreted as that +// (and not -3 or UINT64_MAX - 2). +TEST_F(TlsConnectDatagram13, UnderflowSequenceNumber) { + Connect(); + // This is only valid if short headers are disabled. + client_->SetOption(SSL_ENABLE_DTLS_SHORT_HEADER, PR_FALSE); + EXPECT_EQ(SECSuccess, + SSLInt_AdvanceWriteSeqNum(client_->ssl_fd(), (1ULL << 30) - 3)); + SendReceive(); +} + class TlsConnectDatagram12Plus : public TlsConnectDatagram { public: TlsConnectDatagram12Plus() : TlsConnectDatagram() {} @@ -861,9 +884,54 @@ TEST_P(TlsConnectDatagram12Plus, MissAWindowAndOne) { SendReceive(); } +// This filter replaces the first record it sees with junk application data. +class TlsReplaceFirstRecordWithJunk : public TlsRecordFilter { + public: + TlsReplaceFirstRecordWithJunk(const std::shared_ptr<TlsAgent>& a) + : TlsRecordFilter(a), replaced_(false) {} + + protected: + PacketFilter::Action FilterRecord(const TlsRecordHeader& header, + const DataBuffer& record, size_t* offset, + DataBuffer* output) override { + if (replaced_) { + return KEEP; + } + replaced_ = true; + TlsRecordHeader out_header(header.variant(), header.version(), + kTlsApplicationDataType, + header.sequence_number()); + + static const uint8_t junk[] = {1, 2, 3, 4}; + *offset = out_header.Write(output, *offset, DataBuffer(junk, sizeof(junk))); + return CHANGE; + } + + private: + bool replaced_; +}; + +// DTLS needs to discard application_data that it receives prior to handshake +// completion, not generate an error. +TEST_P(TlsConnectDatagram, ReplaceFirstServerRecordWithApplicationData) { + MakeTlsFilter<TlsReplaceFirstRecordWithJunk>(server_); + Connect(); +} + +TEST_P(TlsConnectDatagram, ReplaceFirstClientRecordWithApplicationData) { + MakeTlsFilter<TlsReplaceFirstRecordWithJunk>(client_); + Connect(); +} + INSTANTIATE_TEST_CASE_P(Datagram12Plus, TlsConnectDatagram12Plus, TlsConnectTestBase::kTlsV12Plus); INSTANTIATE_TEST_CASE_P(DatagramPre13, TlsConnectDatagramPre13, TlsConnectTestBase::kTlsV11V12); +INSTANTIATE_TEST_CASE_P(DatagramDrop13, TlsDropDatagram13, + ::testing::Values(true, false)); +INSTANTIATE_TEST_CASE_P(DatagramReorder13, TlsReorderDatagram13, + ::testing::Values(true, false)); +INSTANTIATE_TEST_CASE_P(DatagramFragment13, TlsFragmentationAndRecoveryTest, + ::testing::Values(true, false)); } // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc index 3c7cd2ecf..12c6e8516 100644 --- a/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc @@ -192,8 +192,8 @@ TEST_P(TlsConnectGenericPre13, P384PriorityFromModelSocket) { class TlsKeyExchangeGroupCapture : public TlsHandshakeFilter { public: - TlsKeyExchangeGroupCapture(const std::shared_ptr<TlsAgent> &agent) - : TlsHandshakeFilter(agent, {kTlsHandshakeServerKeyExchange}), + TlsKeyExchangeGroupCapture(const std::shared_ptr<TlsAgent> &a) + : TlsHandshakeFilter(a, {kTlsHandshakeServerKeyExchange}), group_(ssl_grp_none) {} SSLNamedGroup group() const { return group_; } @@ -559,6 +559,113 @@ TEST_P(TlsConnectGenericPre13, ConnectECDHEmptyClientPoint) { server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH); } +// Damage ECParams/ECPoint of a SKE. +class ECCServerKEXDamager : public TlsHandshakeFilter { + public: + ECCServerKEXDamager(const std::shared_ptr<TlsAgent> &server, ECType ec_type, + SSLNamedGroup named_curve) + : TlsHandshakeFilter(server, {kTlsHandshakeServerKeyExchange}), + ec_type_(ec_type), + named_curve_(named_curve) {} + + protected: + virtual PacketFilter::Action FilterHandshake(const HandshakeHeader &header, + const DataBuffer &input, + DataBuffer *output) { + size_t offset = 0; + output->Allocate(5); + offset = output->Write(offset, ec_type_, 1); + offset = output->Write(offset, named_curve_, 2); + // Write a point with fmt != EC_POINT_FORM_UNCOMPRESSED. + offset = output->Write(offset, 1U, 1); + (void)output->Write(offset, 0x02, 1); // EC_POINT_FORM_COMPRESSED_Y0 + return CHANGE; + } + + private: + ECType ec_type_; + SSLNamedGroup named_curve_; +}; + +TEST_P(TlsConnectGenericPre13, ConnectUnsupportedCurveType) { + EnsureTlsSetup(); + client_->DisableAllCiphers(); + client_->EnableCiphersByKeyExchange(ssl_kea_ecdh); + + MakeTlsFilter<ECCServerKEXDamager>(server_, ec_type_explicitPrime, + ssl_grp_none); + ConnectExpectAlert(client_, kTlsAlertHandshakeFailure); + client_->CheckErrorCode(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); +} + +TEST_P(TlsConnectGenericPre13, ConnectUnsupportedCurve) { + EnsureTlsSetup(); + client_->DisableAllCiphers(); + client_->EnableCiphersByKeyExchange(ssl_kea_ecdh); + + MakeTlsFilter<ECCServerKEXDamager>(server_, ec_type_named, + ssl_grp_ffdhe_2048); + ConnectExpectAlert(client_, kTlsAlertHandshakeFailure); + client_->CheckErrorCode(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); +} + +TEST_P(TlsConnectGenericPre13, ConnectUnsupportedPointFormat) { + EnsureTlsSetup(); + client_->DisableAllCiphers(); + client_->EnableCiphersByKeyExchange(ssl_kea_ecdh); + + MakeTlsFilter<ECCServerKEXDamager>(server_, ec_type_named, + ssl_grp_ec_secp256r1); + ConnectExpectAlert(client_, kTlsAlertHandshakeFailure); + client_->CheckErrorCode(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM); +} + +// Replace SignatureAndHashAlgorithm of a SKE. +class ECCServerKEXSigAlgReplacer : public TlsHandshakeFilter { + public: + ECCServerKEXSigAlgReplacer(const std::shared_ptr<TlsAgent> &server, + SSLSignatureScheme sig_scheme) + : TlsHandshakeFilter(server, {kTlsHandshakeServerKeyExchange}), + sig_scheme_(sig_scheme) {} + + protected: + virtual PacketFilter::Action FilterHandshake(const HandshakeHeader &header, + const DataBuffer &input, + DataBuffer *output) { + *output = input; + + uint32_t point_len; + EXPECT_TRUE(output->Read(3, 1, &point_len)); + output->Write(4 + point_len, sig_scheme_, 2); + + return CHANGE; + } + + private: + SSLSignatureScheme sig_scheme_; +}; + +TEST_P(TlsConnectTls12, ConnectUnsupportedSigAlg) { + EnsureTlsSetup(); + client_->DisableAllCiphers(); + client_->EnableCiphersByKeyExchange(ssl_kea_ecdh); + + MakeTlsFilter<ECCServerKEXSigAlgReplacer>(server_, ssl_sig_none); + ConnectExpectAlert(client_, kTlsAlertIllegalParameter); + client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM); +} + +TEST_P(TlsConnectTls12, ConnectIncorrectSigAlg) { + EnsureTlsSetup(); + client_->DisableAllCiphers(); + client_->EnableCiphersByKeyExchange(ssl_kea_ecdh); + + MakeTlsFilter<ECCServerKEXSigAlgReplacer>(server_, + ssl_sig_ecdsa_secp256r1_sha256); + ConnectExpectAlert(client_, kTlsAlertIllegalParameter); + client_->CheckErrorCode(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM); +} + INSTANTIATE_TEST_CASE_P(KeyExchangeTest, TlsKeyExchangeTest, ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, TlsConnectTestBase::kTlsV11Plus)); diff --git a/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc index 0453dabdb..6965e9ca7 100644 --- a/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc @@ -19,9 +19,9 @@ namespace nss_test { class TlsExtensionTruncator : public TlsExtensionFilter { public: - TlsExtensionTruncator(const std::shared_ptr<TlsAgent>& agent, - uint16_t extension, size_t length) - : TlsExtensionFilter(agent), extension_(extension), length_(length) {} + TlsExtensionTruncator(const std::shared_ptr<TlsAgent>& a, uint16_t extension, + size_t length) + : TlsExtensionFilter(a), extension_(extension), length_(length) {} virtual PacketFilter::Action FilterExtension(uint16_t extension_type, const DataBuffer& input, DataBuffer* output) { @@ -43,9 +43,9 @@ class TlsExtensionTruncator : public TlsExtensionFilter { class TlsExtensionDamager : public TlsExtensionFilter { public: - TlsExtensionDamager(const std::shared_ptr<TlsAgent>& agent, - uint16_t extension, size_t index) - : TlsExtensionFilter(agent), extension_(extension), index_(index) {} + TlsExtensionDamager(const std::shared_ptr<TlsAgent>& a, uint16_t extension, + size_t index) + : TlsExtensionFilter(a), extension_(extension), index_(index) {} virtual PacketFilter::Action FilterExtension(uint16_t extension_type, const DataBuffer& input, DataBuffer* output) { @@ -65,11 +65,9 @@ class TlsExtensionDamager : public TlsExtensionFilter { class TlsExtensionAppender : public TlsHandshakeFilter { public: - TlsExtensionAppender(const std::shared_ptr<TlsAgent>& agent, + TlsExtensionAppender(const std::shared_ptr<TlsAgent>& a, uint8_t handshake_type, uint16_t ext, DataBuffer& data) - : TlsHandshakeFilter(agent, {handshake_type}), - extension_(ext), - data_(data) {} + : TlsHandshakeFilter(a, {handshake_type}), extension_(ext), data_(data) {} virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, const DataBuffer& input, @@ -323,7 +321,15 @@ TEST_P(TlsExtensionTestGeneric, AlpnMissingValue) { TEST_P(TlsExtensionTestGeneric, AlpnZeroLength) { EnableAlpn(); - const uint8_t val[] = {0x01, 0x61, 0x00}; + const uint8_t val[] = {0x00, 0x03, 0x01, 0x61, 0x00}; + DataBuffer extension(val, sizeof(val)); + ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>( + client_, ssl_app_layer_protocol_xtn, extension)); +} + +TEST_P(TlsExtensionTestGeneric, AlpnLengthOverflow) { + EnableAlpn(); + const uint8_t val[] = {0x00, 0x03, 0x01, 0x61, 0x01}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>( client_, ssl_app_layer_protocol_xtn, extension)); @@ -628,12 +634,9 @@ typedef std::function<void(TlsPreSharedKeyReplacer*)> class TlsPreSharedKeyReplacer : public TlsExtensionFilter { public: - TlsPreSharedKeyReplacer(const std::shared_ptr<TlsAgent>& agent, + TlsPreSharedKeyReplacer(const std::shared_ptr<TlsAgent>& a, TlsPreSharedKeyReplacerFunc function) - : TlsExtensionFilter(agent), - identities_(), - binders_(), - function_(function) {} + : TlsExtensionFilter(a), identities_(), binders_(), function_(function) {} static size_t CopyAndMaybeReplace(TlsParser* parser, size_t size, const std::unique_ptr<DataBuffer>& replace, diff --git a/security/nss/gtests/ssl_gtest/ssl_fragment_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_fragment_unittest.cc index f4940bf28..92947c2c7 100644 --- a/security/nss/gtests/ssl_gtest/ssl_fragment_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_fragment_unittest.cc @@ -20,14 +20,16 @@ namespace nss_test { // This class cuts every unencrypted handshake record into two parts. class RecordFragmenter : public PacketFilter { public: - RecordFragmenter() : sequence_number_(0), splitting_(true) {} + RecordFragmenter(bool is_dtls13) + : is_dtls13_(is_dtls13), sequence_number_(0), splitting_(true) {} private: class HandshakeSplitter { public: - HandshakeSplitter(const DataBuffer& input, DataBuffer* output, - uint64_t* sequence_number) - : input_(input), + HandshakeSplitter(bool is_dtls13, const DataBuffer& input, + DataBuffer* output, uint64_t* sequence_number) + : is_dtls13_(is_dtls13), + input_(input), output_(output), cursor_(0), sequence_number_(sequence_number) {} @@ -35,9 +37,9 @@ class RecordFragmenter : public PacketFilter { private: void WriteRecord(TlsRecordHeader& record_header, DataBuffer& record_fragment) { - TlsRecordHeader fragment_header(record_header.version(), - record_header.content_type(), - *sequence_number_); + TlsRecordHeader fragment_header( + record_header.variant(), record_header.version(), + record_header.content_type(), *sequence_number_); ++*sequence_number_; if (::g_ssl_gtest_verbose) { std::cerr << "Fragment: " << fragment_header << ' ' << record_fragment @@ -88,7 +90,7 @@ class RecordFragmenter : public PacketFilter { while (parser.remaining()) { TlsRecordHeader header; DataBuffer record; - if (!header.Parse(0, &parser, &record)) { + if (!header.Parse(is_dtls13_, 0, &parser, &record)) { ADD_FAILURE() << "bad record header"; return false; } @@ -118,6 +120,7 @@ class RecordFragmenter : public PacketFilter { } private: + bool is_dtls13_; const DataBuffer& input_; DataBuffer* output_; size_t cursor_; @@ -132,7 +135,7 @@ class RecordFragmenter : public PacketFilter { } output->Allocate(input.len()); - HandshakeSplitter splitter(input, output, &sequence_number_); + HandshakeSplitter splitter(is_dtls13_, input, output, &sequence_number_); if (!splitter.Split()) { // If splitting fails, we obviously reached encrypted packets. // Stop splitting from that point onward. @@ -144,18 +147,21 @@ class RecordFragmenter : public PacketFilter { } private: + bool is_dtls13_; uint64_t sequence_number_; bool splitting_; }; TEST_P(TlsConnectDatagram, FragmentClientPackets) { - client_->SetFilter(std::make_shared<RecordFragmenter>()); + bool is_dtls13 = version_ >= SSL_LIBRARY_VERSION_TLS_1_3; + client_->SetFilter(std::make_shared<RecordFragmenter>(is_dtls13)); Connect(); SendReceive(); } TEST_P(TlsConnectDatagram, FragmentServerPackets) { - server_->SetFilter(std::make_shared<RecordFragmenter>()); + bool is_dtls13 = version_ >= SSL_LIBRARY_VERSION_TLS_1_3; + server_->SetFilter(std::make_shared<RecordFragmenter>(is_dtls13)); Connect(); SendReceive(); } diff --git a/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc index 99448321c..f0afc9118 100644 --- a/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc @@ -27,8 +27,8 @@ class TlsFuzzTest : public ::testing::Test {}; // Record the application data stream. class TlsApplicationDataRecorder : public TlsRecordFilter { public: - TlsApplicationDataRecorder(const std::shared_ptr<TlsAgent>& agent) - : TlsRecordFilter(agent), buffer_() {} + TlsApplicationDataRecorder(const std::shared_ptr<TlsAgent>& a) + : TlsRecordFilter(a), buffer_() {} virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header, const DataBuffer& input, diff --git a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp index e2a8d830a..17677713d 100644 --- a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp +++ b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp @@ -37,6 +37,7 @@ 'ssl_loopback_unittest.cc', 'ssl_misc_unittest.cc', 'ssl_record_unittest.cc', + 'ssl_recordsize_unittest.cc', 'ssl_resumption_unittest.cc', 'ssl_renegotiation_unittest.cc', 'ssl_skip_unittest.cc', diff --git a/security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc index 05ae87034..77b335e86 100644 --- a/security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc @@ -69,8 +69,8 @@ TEST_P(TlsConnectTls13, HelloRetryRequestAbortsZeroRtt) { // handshake packets, this will break. class CorrectMessageSeqAfterHrrFilter : public TlsRecordFilter { public: - CorrectMessageSeqAfterHrrFilter(const std::shared_ptr<TlsAgent>& agent) - : TlsRecordFilter(agent) {} + CorrectMessageSeqAfterHrrFilter(const std::shared_ptr<TlsAgent>& a) + : TlsRecordFilter(a) {} protected: PacketFilter::Action FilterRecord(const TlsRecordHeader& header, @@ -81,8 +81,9 @@ class CorrectMessageSeqAfterHrrFilter : public TlsRecordFilter { } DataBuffer buffer(record); - TlsRecordHeader new_header = {header.version(), header.content_type(), - header.sequence_number() + 1}; + TlsRecordHeader new_header(header.variant(), header.version(), + header.content_type(), + header.sequence_number() + 1); // Correct message_seq. buffer.Write(4, 1U, 2); @@ -151,8 +152,8 @@ TEST_P(TlsConnectTls13, SecondClientHelloRejectEarlyDataXtn) { class KeyShareReplayer : public TlsExtensionFilter { public: - KeyShareReplayer(const std::shared_ptr<TlsAgent>& agent) - : TlsExtensionFilter(agent) {} + KeyShareReplayer(const std::shared_ptr<TlsAgent>& a) + : TlsExtensionFilter(a) {} virtual PacketFilter::Action FilterExtension(uint16_t extension_type, const DataBuffer& input, @@ -567,6 +568,28 @@ void TriggerHelloRetryRequest(std::shared_ptr<TlsAgent>& client, client->Handshake(); server->Handshake(); EXPECT_EQ(1U, cb_called); + // Stop the callback from being called in future handshakes. + EXPECT_EQ(SECSuccess, + SSL_HelloRetryRequestCallback(server->ssl_fd(), nullptr, nullptr)); +} + +TEST_P(TlsConnectTls13, VersionNumbersAfterRetry) { + ConfigureSelfEncrypt(); + EnsureTlsSetup(); + auto r = MakeTlsFilter<TlsRecordRecorder>(client_); + TriggerHelloRetryRequest(client_, server_); + Handshake(); + ASSERT_GT(r->count(), 1UL); + auto ch1 = r->record(0); + if (ch1.header.is_dtls()) { + ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, ch1.header.version()); + } else { + ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, ch1.header.version()); + } + auto ch2 = r->record(1); + ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, ch2.header.version()); + + CheckConnected(); } TEST_P(TlsConnectTls13, RetryStateless) { @@ -577,6 +600,7 @@ TEST_P(TlsConnectTls13, RetryStateless) { MakeNewServer(); Handshake(); + CheckConnected(); SendReceive(); } @@ -593,6 +617,68 @@ TEST_P(TlsConnectTls13, RetryStatefulDropCookie) { server_->CheckErrorCode(SSL_ERROR_MISSING_COOKIE_EXTENSION); } +class TruncateHrrCookie : public TlsExtensionFilter { + public: + TruncateHrrCookie(const std::shared_ptr<TlsAgent>& a) + : TlsExtensionFilter(a) {} + virtual PacketFilter::Action FilterExtension(uint16_t extension_type, + const DataBuffer& input, + DataBuffer* output) { + if (extension_type != ssl_tls13_cookie_xtn) { + return KEEP; + } + + // Claim a zero-length cookie. + output->Allocate(2); + output->Write(0, static_cast<uint32_t>(0), 2); + return CHANGE; + } +}; + +TEST_P(TlsConnectTls13, RetryCookieEmpty) { + ConfigureSelfEncrypt(); + EnsureTlsSetup(); + + TriggerHelloRetryRequest(client_, server_); + MakeTlsFilter<TruncateHrrCookie>(client_); + + ExpectAlert(server_, kTlsAlertHandshakeFailure); + Handshake(); + client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); + server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); +} + +class AddJunkToCookie : public TlsExtensionFilter { + public: + AddJunkToCookie(const std::shared_ptr<TlsAgent>& a) : TlsExtensionFilter(a) {} + virtual PacketFilter::Action FilterExtension(uint16_t extension_type, + const DataBuffer& input, + DataBuffer* output) { + if (extension_type != ssl_tls13_cookie_xtn) { + return KEEP; + } + + *output = input; + // Add junk after the cookie. + static const uint8_t junk[2] = {1, 2}; + output->Append(DataBuffer(junk, sizeof(junk))); + return CHANGE; + } +}; + +TEST_P(TlsConnectTls13, RetryCookieWithExtras) { + ConfigureSelfEncrypt(); + EnsureTlsSetup(); + + TriggerHelloRetryRequest(client_, server_); + MakeTlsFilter<AddJunkToCookie>(client_); + + ExpectAlert(server_, kTlsAlertHandshakeFailure); + Handshake(); + client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); + server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); +} + // Stream only because DTLS drops bad packets. TEST_F(TlsConnectStreamTls13, RetryStatelessDamageFirstClientHello) { ConfigureSelfEncrypt(); @@ -907,7 +993,10 @@ class HelloRetryRequestAgentTest : public TlsAgentTestClient { hrr_data.Allocate(len + 6); size_t i = 0; - i = hrr_data.Write(i, 0x0303, 2); + i = hrr_data.Write(i, variant_ == ssl_variant_datagram + ? SSL_LIBRARY_VERSION_DTLS_1_2_WIRE + : SSL_LIBRARY_VERSION_TLS_1_2, + 2); i = hrr_data.Write(i, ssl_hello_retry_random, sizeof(ssl_hello_retry_random)); i = hrr_data.Write(i, static_cast<uint32_t>(0), 1); // session_id @@ -973,6 +1062,39 @@ TEST_P(HelloRetryRequestAgentTest, HandleNoopHelloRetryRequest) { SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST); } +class ReplaceRandom : public TlsHandshakeFilter { + public: + ReplaceRandom(const std::shared_ptr<TlsAgent>& a, const DataBuffer& r) + : TlsHandshakeFilter(a, {kTlsHandshakeServerHello}), random_(r) {} + + PacketFilter::Action FilterHandshake(const HandshakeHeader& header, + const DataBuffer& input, + DataBuffer* output) override { + output->Assign(input); + output->Write(2, random_); + return CHANGE; + } + + private: + DataBuffer random_; +}; + +// Make sure that the TLS 1.3 special value for the ServerHello.random +// is rejected by earlier versions. +TEST_P(TlsConnectStreamPre13, HrrRandomOnTls10) { + static const uint8_t hrr_random[] = { + 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE, 0x1D, 0x8C, + 0x02, 0x1E, 0x65, 0xB8, 0x91, 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, + 0x8C, 0x5E, 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C}; + + EnsureTlsSetup(); + MakeTlsFilter<ReplaceRandom>(server_, + DataBuffer(hrr_random, sizeof(hrr_random))); + ConnectExpectAlert(client_, kTlsAlertIllegalParameter); + client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); + server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); +} + INSTANTIATE_TEST_CASE_P(HelloRetryRequestAgentTests, HelloRetryRequestAgentTest, ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, TlsConnectTestBase::kTlsV13)); diff --git a/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc index f1b78f52f..5adbd9dc7 100644 --- a/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc @@ -56,8 +56,8 @@ TEST_P(TlsConnectGeneric, CipherSuiteMismatch) { class TlsAlertRecorder : public TlsRecordFilter { public: - TlsAlertRecorder(const std::shared_ptr<TlsAgent>& agent) - : TlsRecordFilter(agent), level_(255), description_(255) {} + TlsAlertRecorder(const std::shared_ptr<TlsAgent>& a) + : TlsRecordFilter(a), level_(255), description_(255) {} PacketFilter::Action FilterRecord(const TlsRecordHeader& header, const DataBuffer& input, @@ -87,9 +87,9 @@ class TlsAlertRecorder : public TlsRecordFilter { class HelloTruncator : public TlsHandshakeFilter { public: - HelloTruncator(const std::shared_ptr<TlsAgent>& agent) + HelloTruncator(const std::shared_ptr<TlsAgent>& a) : TlsHandshakeFilter( - agent, {kTlsHandshakeClientHello, kTlsHandshakeServerHello}) {} + a, {kTlsHandshakeClientHello, kTlsHandshakeServerHello}) {} PacketFilter::Action FilterHandshake(const HandshakeHeader& header, const DataBuffer& input, DataBuffer* output) override { @@ -149,6 +149,27 @@ TEST_P(TlsConnectGeneric, ConnectAlpn) { CheckAlpn("a"); } +TEST_P(TlsConnectGeneric, ConnectAlpnPriorityA) { + // "alpn" "npn" + // alpn is the fallback here. npn has the highest priority and should be + // picked. + const std::vector<uint8_t> alpn = {0x04, 0x61, 0x6c, 0x70, 0x6e, + 0x03, 0x6e, 0x70, 0x6e}; + EnableAlpn(alpn); + Connect(); + CheckAlpn("npn"); +} + +TEST_P(TlsConnectGeneric, ConnectAlpnPriorityB) { + // "alpn" "npn" "http" + // npn has the highest priority and should be picked. + const std::vector<uint8_t> alpn = {0x04, 0x61, 0x6c, 0x70, 0x6e, 0x03, 0x6e, + 0x70, 0x6e, 0x04, 0x68, 0x74, 0x74, 0x70}; + EnableAlpn(alpn); + Connect(); + CheckAlpn("npn"); +} + TEST_P(TlsConnectGeneric, ConnectAlpnClone) { EnsureModelSockets(); client_model_->EnableAlpn(alpn_dummy_val_, sizeof(alpn_dummy_val_)); @@ -157,6 +178,33 @@ TEST_P(TlsConnectGeneric, ConnectAlpnClone) { CheckAlpn("a"); } +TEST_P(TlsConnectGeneric, ConnectAlpnWithCustomCallbackA) { + // "ab" "alpn" + const std::vector<uint8_t> client_alpn = {0x02, 0x61, 0x62, 0x04, + 0x61, 0x6c, 0x70, 0x6e}; + EnableAlpnWithCallback(client_alpn, "alpn"); + Connect(); + CheckAlpn("alpn"); +} + +TEST_P(TlsConnectGeneric, ConnectAlpnWithCustomCallbackB) { + // "ab" "alpn" + const std::vector<uint8_t> client_alpn = {0x02, 0x61, 0x62, 0x04, + 0x61, 0x6c, 0x70, 0x6e}; + EnableAlpnWithCallback(client_alpn, "ab"); + Connect(); + CheckAlpn("ab"); +} + +TEST_P(TlsConnectGeneric, ConnectAlpnWithCustomCallbackC) { + // "cd" "npn" "alpn" + const std::vector<uint8_t> client_alpn = {0x02, 0x63, 0x64, 0x03, 0x6e, 0x70, + 0x6e, 0x04, 0x61, 0x6c, 0x70, 0x6e}; + EnableAlpnWithCallback(client_alpn, "npn"); + Connect(); + CheckAlpn("npn"); +} + TEST_P(TlsConnectDatagram, ConnectSrtp) { EnableSrtp(); Connect(); @@ -171,8 +219,8 @@ TEST_P(TlsConnectGeneric, ConnectSendReceive) { class SaveTlsRecord : public TlsRecordFilter { public: - SaveTlsRecord(const std::shared_ptr<TlsAgent>& agent, size_t index) - : TlsRecordFilter(agent), index_(index), count_(0), contents_() {} + SaveTlsRecord(const std::shared_ptr<TlsAgent>& a, size_t index) + : TlsRecordFilter(a), index_(index), count_(0), contents_() {} const DataBuffer& contents() const { return contents_; } @@ -227,8 +275,8 @@ TEST_F(TlsConnectStreamTls13, DecryptRecordServer) { class DropTlsRecord : public TlsRecordFilter { public: - DropTlsRecord(const std::shared_ptr<TlsAgent>& agent, size_t index) - : TlsRecordFilter(agent), index_(index), count_(0) {} + DropTlsRecord(const std::shared_ptr<TlsAgent>& a, size_t index) + : TlsRecordFilter(a), index_(index), count_(0) {} protected: PacketFilter::Action FilterRecord(const TlsRecordHeader& header, @@ -373,8 +421,8 @@ TEST_P(TlsHolddownTest, TestDtlsHolddownExpiryResumption) { class TlsPreCCSHeaderInjector : public TlsRecordFilter { public: - TlsPreCCSHeaderInjector(const std::shared_ptr<TlsAgent>& agent) - : TlsRecordFilter(agent) {} + TlsPreCCSHeaderInjector(const std::shared_ptr<TlsAgent>& a) + : TlsRecordFilter(a) {} virtual PacketFilter::Action FilterRecord( const TlsRecordHeader& record_header, const DataBuffer& input, size_t* offset, DataBuffer* output) override { @@ -383,7 +431,8 @@ class TlsPreCCSHeaderInjector : public TlsRecordFilter { std::cerr << "Injecting Finished header before CCS\n"; const uint8_t hhdr[] = {kTlsHandshakeFinished, 0x00, 0x00, 0x0c}; DataBuffer hhdr_buf(hhdr, sizeof(hhdr)); - TlsRecordHeader nhdr(record_header.version(), kTlsHandshakeType, 0); + TlsRecordHeader nhdr(record_header.variant(), record_header.version(), + kTlsHandshakeType, 0); *offset = nhdr.Write(output, *offset, hhdr_buf); *offset = record_header.Write(output, *offset, input); return CHANGE; diff --git a/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc index 3b8727850..53b11c61a 100644 --- a/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc @@ -103,16 +103,14 @@ TEST_P(TlsPaddingTest, LastByteOfPadWrong) { class RecordReplacer : public TlsRecordFilter { public: - RecordReplacer(const std::shared_ptr<TlsAgent>& agent, size_t size) - : TlsRecordFilter(agent), enabled_(false), size_(size) {} + RecordReplacer(const std::shared_ptr<TlsAgent>& a, size_t size) + : TlsRecordFilter(a), size_(size) { + Disable(); + } PacketFilter::Action FilterRecord(const TlsRecordHeader& header, const DataBuffer& data, DataBuffer* changed) override { - if (!enabled_) { - return KEEP; - } - EXPECT_EQ(kTlsApplicationDataType, header.content_type()); changed->Allocate(size_); @@ -120,17 +118,33 @@ class RecordReplacer : public TlsRecordFilter { changed->data()[i] = i & 0xff; } - enabled_ = false; + Disable(); return CHANGE; } - void Enable() { enabled_ = true; } - private: - bool enabled_; size_t size_; }; +TEST_P(TlsConnectStream, BadRecordMac) { + EnsureTlsSetup(); + Connect(); + client_->SetFilter(std::make_shared<TlsRecordLastByteDamager>(client_)); + ExpectAlert(server_, kTlsAlertBadRecordMac); + client_->SendData(10); + + // Read from the client, get error. + uint8_t buf[10]; + PRInt32 rv = PR_Read(server_->ssl_fd(), buf, sizeof(buf)); + EXPECT_GT(0, rv); + EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, PORT_GetError()); + + // Read the server alert. + rv = PR_Read(client_->ssl_fd(), buf, sizeof(buf)); + EXPECT_GT(0, rv); + EXPECT_EQ(SSL_ERROR_BAD_MAC_ALERT, PORT_GetError()); +} + TEST_F(TlsConnectStreamTls13, LargeRecord) { EnsureTlsSetup(); @@ -168,6 +182,29 @@ TEST_F(TlsConnectStreamTls13, TooLargeRecord) { EXPECT_EQ(SSL_ERROR_RECORD_OVERFLOW_ALERT, PORT_GetError()); } +class ShortHeaderChecker : public PacketFilter { + public: + PacketFilter::Action Filter(const DataBuffer& input, DataBuffer* output) { + // The first octet should be 0b001xxxxx. + EXPECT_EQ(1, input.data()[0] >> 5); + return KEEP; + } +}; + +TEST_F(TlsConnectDatagram13, ShortHeadersClient) { + Connect(); + client_->SetOption(SSL_ENABLE_DTLS_SHORT_HEADER, PR_TRUE); + client_->SetFilter(std::make_shared<ShortHeaderChecker>()); + SendReceive(); +} + +TEST_F(TlsConnectDatagram13, ShortHeadersServer) { + Connect(); + server_->SetOption(SSL_ENABLE_DTLS_SHORT_HEADER, PR_TRUE); + server_->SetFilter(std::make_shared<ShortHeaderChecker>()); + SendReceive(); +} + const static size_t kContentSizesArr[] = { 1, kMacSize - 1, kMacSize, 30, 31, 32, 36, 256, 257, 287, 288}; diff --git a/security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc new file mode 100644 index 000000000..00651aec5 --- /dev/null +++ b/security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc @@ -0,0 +1,431 @@ +/* -*- 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" + +#include "gtest_utils.h" +#include "scoped_ptrs.h" +#include "tls_connect.h" +#include "tls_filter.h" +#include "tls_parser.h" + +namespace nss_test { + +// This class tracks the maximum size of record that was sent, both cleartext +// and plain. It only tracks records that have an outer type of +// application_data. In TLS 1.3, this includes handshake messages. +class TlsRecordMaximum : public TlsRecordFilter { + public: + TlsRecordMaximum(const std::shared_ptr<TlsAgent>& a) + : TlsRecordFilter(a), max_ciphertext_(0), max_plaintext_(0) {} + + size_t max_ciphertext() const { return max_ciphertext_; } + size_t max_plaintext() const { return max_plaintext_; } + + protected: + PacketFilter::Action FilterRecord(const TlsRecordHeader& header, + const DataBuffer& record, size_t* offset, + DataBuffer* output) override { + std::cerr << "max: " << record << std::endl; + // Ignore unprotected packets. + if (header.content_type() != kTlsApplicationDataType) { + return KEEP; + } + + max_ciphertext_ = (std::max)(max_ciphertext_, record.len()); + return TlsRecordFilter::FilterRecord(header, record, offset, output); + } + + PacketFilter::Action FilterRecord(const TlsRecordHeader& header, + const DataBuffer& data, + DataBuffer* changed) override { + max_plaintext_ = (std::max)(max_plaintext_, data.len()); + return KEEP; + } + + private: + size_t max_ciphertext_; + size_t max_plaintext_; +}; + +void CheckRecordSizes(const std::shared_ptr<TlsAgent>& agent, + const std::shared_ptr<TlsRecordMaximum>& record_max, + size_t config) { + uint16_t cipher_suite; + ASSERT_TRUE(agent->cipher_suite(&cipher_suite)); + + size_t expansion; + size_t iv; + switch (cipher_suite) { + case TLS_AES_128_GCM_SHA256: + case TLS_AES_256_GCM_SHA384: + case TLS_CHACHA20_POLY1305_SHA256: + expansion = 16; + iv = 0; + break; + + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + expansion = 16; + iv = 8; + break; + + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + // Expansion is 20 for the MAC. Maximum block padding is 16. Maximum + // padding is added when the input plus the MAC is an exact multiple of + // the block size. + expansion = 20 + 16 - ((config + 20) % 16); + iv = 16; + break; + + default: + ADD_FAILURE() << "No expansion set for ciphersuite " + << agent->cipher_suite_name(); + return; + } + + switch (agent->version()) { + case SSL_LIBRARY_VERSION_TLS_1_3: + EXPECT_EQ(0U, iv) << "No IV for TLS 1.3"; + // We only have decryption in TLS 1.3. + EXPECT_EQ(config - 1, record_max->max_plaintext()) + << "bad plaintext length for " << agent->role_str(); + break; + + case SSL_LIBRARY_VERSION_TLS_1_2: + case SSL_LIBRARY_VERSION_TLS_1_1: + expansion += iv; + break; + + case SSL_LIBRARY_VERSION_TLS_1_0: + break; + + default: + ADD_FAILURE() << "Unexpected version " << agent->version(); + return; + } + + EXPECT_EQ(config + expansion, record_max->max_ciphertext()) + << "bad ciphertext length for " << agent->role_str(); +} + +TEST_P(TlsConnectGeneric, RecordSizeMaximum) { + uint16_t max_record_size = + (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) ? 16385 : 16384; + size_t send_size = (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) + ? max_record_size + : max_record_size + 1; + + EnsureTlsSetup(); + auto client_max = MakeTlsFilter<TlsRecordMaximum>(client_); + client_max->EnableDecryption(); + auto server_max = MakeTlsFilter<TlsRecordMaximum>(server_); + server_max->EnableDecryption(); + + Connect(); + client_->SendData(send_size, send_size); + server_->SendData(send_size, send_size); + server_->ReadBytes(send_size); + client_->ReadBytes(send_size); + + CheckRecordSizes(client_, client_max, max_record_size); + CheckRecordSizes(server_, server_max, max_record_size); +} + +TEST_P(TlsConnectGeneric, RecordSizeMinimumClient) { + EnsureTlsSetup(); + auto server_max = MakeTlsFilter<TlsRecordMaximum>(server_); + server_max->EnableDecryption(); + + client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64); + Connect(); + SendReceive(127); // Big enough for one record, allowing for 1+N splitting. + + CheckRecordSizes(server_, server_max, 64); +} + +TEST_P(TlsConnectGeneric, RecordSizeMinimumServer) { + EnsureTlsSetup(); + auto client_max = MakeTlsFilter<TlsRecordMaximum>(client_); + client_max->EnableDecryption(); + + server_->SetOption(SSL_RECORD_SIZE_LIMIT, 64); + Connect(); + SendReceive(127); + + CheckRecordSizes(client_, client_max, 64); +} + +TEST_P(TlsConnectGeneric, RecordSizeAsymmetric) { + EnsureTlsSetup(); + auto client_max = MakeTlsFilter<TlsRecordMaximum>(client_); + client_max->EnableDecryption(); + auto server_max = MakeTlsFilter<TlsRecordMaximum>(server_); + server_max->EnableDecryption(); + + client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64); + server_->SetOption(SSL_RECORD_SIZE_LIMIT, 100); + Connect(); + SendReceive(127); + + CheckRecordSizes(client_, client_max, 100); + CheckRecordSizes(server_, server_max, 64); +} + +// This just modifies the encrypted payload so to include a few extra zeros. +class TlsRecordExpander : public TlsRecordFilter { + public: + TlsRecordExpander(const std::shared_ptr<TlsAgent>& a, size_t expansion) + : TlsRecordFilter(a), expansion_(expansion) {} + + protected: + virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header, + const DataBuffer& data, + DataBuffer* changed) { + if (header.content_type() != kTlsApplicationDataType) { + return KEEP; + } + changed->Allocate(data.len() + expansion_); + changed->Write(0, data.data(), data.len()); + return CHANGE; + } + + private: + size_t expansion_; +}; + +// Tweak the plaintext of server records so that they exceed the client's limit. +TEST_P(TlsConnectTls13, RecordSizePlaintextExceed) { + EnsureTlsSetup(); + auto server_expand = MakeTlsFilter<TlsRecordExpander>(server_, 1); + server_expand->EnableDecryption(); + + client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64); + Connect(); + + server_->SendData(100); + + client_->ExpectReadWriteError(); + ExpectAlert(client_, kTlsAlertRecordOverflow); + client_->ReadBytes(100); + EXPECT_EQ(SSL_ERROR_RX_RECORD_TOO_LONG, client_->error_code()); + + // Consume the alert at the server. + server_->Handshake(); + server_->CheckErrorCode(SSL_ERROR_RECORD_OVERFLOW_ALERT); +} + +// Tweak the ciphertext of server records so that they greatly exceed the limit. +// This requires a much larger expansion than for plaintext to trigger the +// guard, which runs before decryption (current allowance is 304 octets). +TEST_P(TlsConnectTls13, RecordSizeCiphertextExceed) { + EnsureTlsSetup(); + + client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64); + Connect(); + + auto server_expand = MakeTlsFilter<TlsRecordExpander>(server_, 320); + server_->SendData(100); + + client_->ExpectReadWriteError(); + ExpectAlert(client_, kTlsAlertRecordOverflow); + client_->ReadBytes(100); + EXPECT_EQ(SSL_ERROR_RX_RECORD_TOO_LONG, client_->error_code()); + + // Consume the alert at the server. + server_->Handshake(); + server_->CheckErrorCode(SSL_ERROR_RECORD_OVERFLOW_ALERT); +} + +// This indiscriminately adds padding to application data records. +class TlsRecordPadder : public TlsRecordFilter { + public: + TlsRecordPadder(const std::shared_ptr<TlsAgent>& a, size_t padding) + : TlsRecordFilter(a), padding_(padding) {} + + protected: + PacketFilter::Action FilterRecord(const TlsRecordHeader& header, + const DataBuffer& record, size_t* offset, + DataBuffer* output) override { + if (header.content_type() != kTlsApplicationDataType) { + return KEEP; + } + + uint8_t inner_content_type; + DataBuffer plaintext; + if (!Unprotect(header, record, &inner_content_type, &plaintext)) { + return KEEP; + } + + if (inner_content_type != kTlsApplicationDataType) { + return KEEP; + } + + DataBuffer ciphertext; + bool ok = + Protect(header, inner_content_type, plaintext, &ciphertext, padding_); + EXPECT_TRUE(ok); + if (!ok) { + return KEEP; + } + *offset = header.Write(output, *offset, ciphertext); + return CHANGE; + } + + private: + size_t padding_; +}; + +TEST_P(TlsConnectTls13, RecordSizeExceedPad) { + EnsureTlsSetup(); + auto server_max = std::make_shared<TlsRecordMaximum>(server_); + auto server_expand = std::make_shared<TlsRecordPadder>(server_, 1); + server_->SetFilter(std::make_shared<ChainedPacketFilter>( + ChainedPacketFilterInit({server_max, server_expand}))); + server_expand->EnableDecryption(); + + client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64); + Connect(); + + server_->SendData(100); + + client_->ExpectReadWriteError(); + ExpectAlert(client_, kTlsAlertRecordOverflow); + client_->ReadBytes(100); + EXPECT_EQ(SSL_ERROR_RX_RECORD_TOO_LONG, client_->error_code()); + + // Consume the alert at the server. + server_->Handshake(); + server_->CheckErrorCode(SSL_ERROR_RECORD_OVERFLOW_ALERT); +} + +TEST_P(TlsConnectGeneric, RecordSizeBadValues) { + EnsureTlsSetup(); + EXPECT_EQ(SECFailure, + SSL_OptionSet(client_->ssl_fd(), SSL_RECORD_SIZE_LIMIT, 63)); + EXPECT_EQ(SECFailure, + SSL_OptionSet(client_->ssl_fd(), SSL_RECORD_SIZE_LIMIT, -1)); + EXPECT_EQ(SECFailure, + SSL_OptionSet(server_->ssl_fd(), SSL_RECORD_SIZE_LIMIT, 16386)); + Connect(); +} + +TEST_P(TlsConnectGeneric, RecordSizeGetValues) { + EnsureTlsSetup(); + int v; + EXPECT_EQ(SECSuccess, + SSL_OptionGet(client_->ssl_fd(), SSL_RECORD_SIZE_LIMIT, &v)); + EXPECT_EQ(16385, v); + client_->SetOption(SSL_RECORD_SIZE_LIMIT, 300); + EXPECT_EQ(SECSuccess, + SSL_OptionGet(client_->ssl_fd(), SSL_RECORD_SIZE_LIMIT, &v)); + EXPECT_EQ(300, v); + Connect(); +} + +// The value of the extension is capped by the maximum version of the client. +TEST_P(TlsConnectGeneric, RecordSizeCapExtensionClient) { + EnsureTlsSetup(); + client_->SetOption(SSL_RECORD_SIZE_LIMIT, 16385); + auto capture = + MakeTlsFilter<TlsExtensionCapture>(client_, ssl_record_size_limit_xtn); + capture->EnableDecryption(); + Connect(); + + uint64_t val = 0; + EXPECT_TRUE(capture->extension().Read(0, 2, &val)); + if (version_ < SSL_LIBRARY_VERSION_TLS_1_3) { + EXPECT_EQ(16384U, val) << "Extension should be capped"; + } else { + EXPECT_EQ(16385U, val); + } +} + +// The value of the extension is capped by the maximum version of the server. +TEST_P(TlsConnectGeneric, RecordSizeCapExtensionServer) { + EnsureTlsSetup(); + server_->SetOption(SSL_RECORD_SIZE_LIMIT, 16385); + auto capture = + MakeTlsFilter<TlsExtensionCapture>(server_, ssl_record_size_limit_xtn); + capture->EnableDecryption(); + Connect(); + + uint64_t val = 0; + EXPECT_TRUE(capture->extension().Read(0, 2, &val)); + if (version_ < SSL_LIBRARY_VERSION_TLS_1_3) { + EXPECT_EQ(16384U, val) << "Extension should be capped"; + } else { + EXPECT_EQ(16385U, val); + } +} + +// Damage the client extension and the handshake fails, but the server +// doesn't generate a validation error. +TEST_P(TlsConnectGenericPre13, RecordSizeClientExtensionInvalid) { + EnsureTlsSetup(); + client_->SetOption(SSL_RECORD_SIZE_LIMIT, 1000); + static const uint8_t v[] = {0xf4, 0x1f}; + MakeTlsFilter<TlsExtensionReplacer>(client_, ssl_record_size_limit_xtn, + DataBuffer(v, sizeof(v))); + ConnectExpectAlert(server_, kTlsAlertDecryptError); +} + +// Special handling for TLS 1.3, where the alert isn't read. +TEST_F(TlsConnectStreamTls13, RecordSizeClientExtensionInvalid) { + EnsureTlsSetup(); + client_->SetOption(SSL_RECORD_SIZE_LIMIT, 1000); + static const uint8_t v[] = {0xf4, 0x1f}; + MakeTlsFilter<TlsExtensionReplacer>(client_, ssl_record_size_limit_xtn, + DataBuffer(v, sizeof(v))); + client_->ExpectSendAlert(kTlsAlertBadRecordMac); + server_->ExpectSendAlert(kTlsAlertBadRecordMac); + ConnectExpectFail(); +} + +TEST_P(TlsConnectGeneric, RecordSizeServerExtensionInvalid) { + EnsureTlsSetup(); + server_->SetOption(SSL_RECORD_SIZE_LIMIT, 1000); + static const uint8_t v[] = {0xf4, 0x1f}; + auto replace = MakeTlsFilter<TlsExtensionReplacer>( + server_, ssl_record_size_limit_xtn, DataBuffer(v, sizeof(v))); + replace->EnableDecryption(); + ConnectExpectAlert(client_, kTlsAlertIllegalParameter); +} + +class RecordSizeDefaultsTest : public ::testing::Test { + public: + void SetUp() { + EXPECT_EQ(SECSuccess, + SSL_OptionGetDefault(SSL_RECORD_SIZE_LIMIT, &default_)); + } + void TearDown() { + // Make sure to restore the default value at the end. + EXPECT_EQ(SECSuccess, + SSL_OptionSetDefault(SSL_RECORD_SIZE_LIMIT, default_)); + } + + private: + PRIntn default_ = 0; +}; + +TEST_F(RecordSizeDefaultsTest, RecordSizeBadValues) { + EXPECT_EQ(SECFailure, SSL_OptionSetDefault(SSL_RECORD_SIZE_LIMIT, 63)); + EXPECT_EQ(SECFailure, SSL_OptionSetDefault(SSL_RECORD_SIZE_LIMIT, -1)); + EXPECT_EQ(SECFailure, SSL_OptionSetDefault(SSL_RECORD_SIZE_LIMIT, 16386)); +} + +TEST_F(RecordSizeDefaultsTest, RecordSizeGetValue) { + int v; + EXPECT_EQ(SECSuccess, SSL_OptionGetDefault(SSL_RECORD_SIZE_LIMIT, &v)); + EXPECT_EQ(16385, v); + EXPECT_EQ(SECSuccess, SSL_OptionSetDefault(SSL_RECORD_SIZE_LIMIT, 3000)); + EXPECT_EQ(SECSuccess, SSL_OptionGetDefault(SSL_RECORD_SIZE_LIMIT, &v)); + EXPECT_EQ(3000, v); +} + +} // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc index eb78c0585..2cc98a327 100644 --- a/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc @@ -484,10 +484,8 @@ TEST_P(TlsConnectStream, TestResumptionOverrideCipher) { class SelectedVersionReplacer : public TlsHandshakeFilter { public: - SelectedVersionReplacer(const std::shared_ptr<TlsAgent>& agent, - uint16_t version) - : TlsHandshakeFilter(agent, {kTlsHandshakeServerHello}), - version_(version) {} + SelectedVersionReplacer(const std::shared_ptr<TlsAgent>& a, uint16_t version) + : TlsHandshakeFilter(a, {kTlsHandshakeServerHello}), version_(version) {} protected: PacketFilter::Action FilterHandshake(const HandshakeHeader& header, diff --git a/security/nss/gtests/ssl_gtest/ssl_skip_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_skip_unittest.cc index e4a9e5aed..9ef19653b 100644 --- a/security/nss/gtests/ssl_gtest/ssl_skip_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_skip_unittest.cc @@ -22,11 +22,9 @@ namespace nss_test { class TlsHandshakeSkipFilter : public TlsRecordFilter { public: // A TLS record filter that skips handshake messages of the identified type. - TlsHandshakeSkipFilter(const std::shared_ptr<TlsAgent>& agent, + TlsHandshakeSkipFilter(const std::shared_ptr<TlsAgent>& a, uint8_t handshake_type) - : TlsRecordFilter(agent), - handshake_type_(handshake_type), - skipped_(false) {} + : TlsRecordFilter(a), handshake_type_(handshake_type), skipped_(false) {} protected: // Takes a record; if it is a handshake record, it removes the first handshake diff --git a/security/nss/gtests/ssl_gtest/ssl_staticrsa_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_staticrsa_unittest.cc index e5fccc12b..ff4091b9a 100644 --- a/security/nss/gtests/ssl_gtest/ssl_staticrsa_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_staticrsa_unittest.cc @@ -21,6 +21,7 @@ extern "C" { #include "tls_connect.h" #include "tls_filter.h" #include "tls_parser.h" +#include "rsa8193.h" namespace nss_test { @@ -100,4 +101,39 @@ TEST_P(TlsConnectStreamPre13, Connect(); } +// Replace the server certificate with one that uses 8193-bit RSA. +class TooLargeRSACertFilter : public TlsHandshakeFilter { + public: + TooLargeRSACertFilter(const std::shared_ptr<TlsAgent> &server) + : TlsHandshakeFilter(server, {kTlsHandshakeCertificate}) {} + + protected: + virtual PacketFilter::Action FilterHandshake(const HandshakeHeader &header, + const DataBuffer &input, + DataBuffer *output) { + const uint32_t cert_len = sizeof(rsa8193); + const uint32_t outer_len = cert_len + 3; + size_t offset = 0; + offset = output->Write(offset, outer_len, 3); + offset = output->Write(offset, cert_len, 3); + offset = output->Write(offset, rsa8193, cert_len); + + return CHANGE; + } +}; + +TEST_P(TlsConnectGenericPre13, TooLargeRSAKeyInCert) { + EnableOnlyStaticRsaCiphers(); + MakeTlsFilter<TooLargeRSACertFilter>(server_); + ConnectExpectAlert(client_, kTlsAlertIllegalParameter); + client_->CheckErrorCode(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); + server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); +} + +TEST_P(TlsConnectGeneric, ServerAuthBiggestRsa) { + Reset(TlsAgent::kRsa8192); + Connect(); + CheckKeys(); +} + } // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc index f5ccf096b..42f1065f6 100644 --- a/security/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc @@ -214,6 +214,98 @@ TEST_F(Tls13CompatTest, EnabledHrrZeroRtt) { CheckForCompatHandshake(); } +class TlsSessionIDEchoFilter : public TlsHandshakeFilter { + public: + TlsSessionIDEchoFilter(const std::shared_ptr<TlsAgent>& a) + : TlsHandshakeFilter( + a, {kTlsHandshakeClientHello, kTlsHandshakeServerHello}) {} + + protected: + virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, + const DataBuffer& input, + DataBuffer* output) { + TlsParser parser(input); + + // Skip version + random. + EXPECT_TRUE(parser.Skip(2 + 32)); + + // Capture CH.legacy_session_id. + if (header.handshake_type() == kTlsHandshakeClientHello) { + EXPECT_TRUE(parser.ReadVariable(&sid_, 1)); + return KEEP; + } + + // Check that server sends one too. + uint32_t sid_len = 0; + EXPECT_TRUE(parser.Read(&sid_len, 1)); + EXPECT_EQ(sid_len, sid_.len()); + + // Echo the one we captured. + *output = input; + output->Write(parser.consumed(), sid_.data(), sid_.len()); + + return CHANGE; + } + + private: + DataBuffer sid_; +}; + +TEST_F(TlsConnectTest, EchoTLS13CompatibilitySessionID) { + ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID); + + client_->SetOption(SSL_ENABLE_TLS13_COMPAT_MODE, PR_TRUE); + + client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, + SSL_LIBRARY_VERSION_TLS_1_3); + + server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, + SSL_LIBRARY_VERSION_TLS_1_2); + + server_->SetFilter(MakeTlsFilter<TlsSessionIDEchoFilter>(client_)); + ConnectExpectAlert(client_, kTlsAlertIllegalParameter); + + client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); + server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); +} + +class TlsSessionIDInjectFilter : public TlsHandshakeFilter { + public: + TlsSessionIDInjectFilter(const std::shared_ptr<TlsAgent>& a) + : TlsHandshakeFilter(a, {kTlsHandshakeServerHello}) {} + + protected: + virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, + const DataBuffer& input, + DataBuffer* output) { + TlsParser parser(input); + + // Skip version + random. + EXPECT_TRUE(parser.Skip(2 + 32)); + + *output = input; + + // Inject a Session ID. + const uint8_t fake_sid[SSL3_SESSIONID_BYTES] = {0xff}; + output->Write(parser.consumed(), sizeof(fake_sid), 1); + output->Splice(fake_sid, sizeof(fake_sid), parser.consumed() + 1, 0); + + return CHANGE; + } +}; + +TEST_F(TlsConnectTest, TLS13NonCompatModeSessionID) { + ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); + + MakeTlsFilter<TlsSessionIDInjectFilter>(server_); + client_->ExpectSendAlert(kTlsAlertIllegalParameter); + server_->ExpectSendAlert(kTlsAlertBadRecordMac); + ConnectExpectFail(); + + client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); + server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); +} + static const uint8_t kCannedCcs[] = { kTlsChangeCipherSpecType, SSL_LIBRARY_VERSION_TLS_1_2 >> 8, diff --git a/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc index 7f3c4a896..09d7801e9 100644 --- a/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc @@ -50,12 +50,12 @@ inline std::ostream& operator<<(std::ostream& stream, class VersionRangeWithLabel { public: - VersionRangeWithLabel(const std::string& label, const SSLVersionRange& vr) - : label_(label), vr_(vr) {} - VersionRangeWithLabel(const std::string& label, uint16_t min, uint16_t max) - : label_(label) { - vr_.min = min; - vr_.max = max; + VersionRangeWithLabel(const std::string& txt, const SSLVersionRange& vr) + : label_(txt), vr_(vr) {} + VersionRangeWithLabel(const std::string& txt, uint16_t start, uint16_t end) + : label_(txt) { + vr_.min = start; + vr_.max = end; } VersionRangeWithLabel(const std::string& label) : label_(label) { vr_.min = vr_.max = SSL_LIBRARY_VERSION_NONE; diff --git a/security/nss/gtests/ssl_gtest/test_io.cc b/security/nss/gtests/ssl_gtest/test_io.cc index 728217851..d76b3526c 100644 --- a/security/nss/gtests/ssl_gtest/test_io.cc +++ b/security/nss/gtests/ssl_gtest/test_io.cc @@ -99,8 +99,8 @@ int32_t DummyPrSocket::Write(PRFileDesc *f, const void *buf, int32_t length) { return -1; } - auto peer = peer_.lock(); - if (!peer) { + auto dst = peer_.lock(); + if (!dst) { PR_SetError(PR_IO_ERROR, 0); return -1; } @@ -116,14 +116,14 @@ int32_t DummyPrSocket::Write(PRFileDesc *f, const void *buf, int32_t length) { case PacketFilter::CHANGE: LOG("Original packet: " << packet); LOG("Filtered packet: " << filtered); - peer->PacketReceived(filtered); + dst->PacketReceived(filtered); break; case PacketFilter::DROP: LOG("Droppped packet: " << packet); break; case PacketFilter::KEEP: LOGV("Packet: " << packet); - peer->PacketReceived(packet); + dst->PacketReceived(packet); break; } // libssl can't handle it if this reports something other than the length diff --git a/security/nss/gtests/ssl_gtest/test_io.h b/security/nss/gtests/ssl_gtest/test_io.h index dbeb6b9d4..8327373ce 100644 --- a/security/nss/gtests/ssl_gtest/test_io.h +++ b/security/nss/gtests/ssl_gtest/test_io.h @@ -59,9 +59,9 @@ class PacketFilter { class DummyPrSocket : public DummyIOLayerMethods { public: - DummyPrSocket(const std::string& name, SSLProtocolVariant variant) + DummyPrSocket(const std::string& name, SSLProtocolVariant var) : name_(name), - variant_(variant), + variant_(var), peer_(), input_(), filter_(nullptr), @@ -73,7 +73,7 @@ class DummyPrSocket : public DummyIOLayerMethods { ScopedPRFileDesc CreateFD(); std::weak_ptr<DummyPrSocket>& peer() { return peer_; } - void SetPeer(const std::shared_ptr<DummyPrSocket>& peer) { peer_ = peer; } + void SetPeer(const std::shared_ptr<DummyPrSocket>& p) { peer_ = p; } void SetPacketFilter(const std::shared_ptr<PacketFilter>& filter) { filter_ = filter; } diff --git a/security/nss/gtests/ssl_gtest/tls_agent.cc b/security/nss/gtests/ssl_gtest/tls_agent.cc index 2f71caedb..9bed1ce1b 100644 --- a/security/nss/gtests/ssl_gtest/tls_agent.cc +++ b/security/nss/gtests/ssl_gtest/tls_agent.cc @@ -33,6 +33,7 @@ const char* TlsAgent::states[] = {"INIT", "CONNECTING", "CONNECTED", "ERROR"}; const std::string TlsAgent::kClient = "client"; // both sign and encrypt const std::string TlsAgent::kRsa2048 = "rsa2048"; // bigger +const std::string TlsAgent::kRsa8192 = "rsa8192"; // biggest allowed const std::string TlsAgent::kServerRsa = "rsa"; // both sign and encrypt const std::string TlsAgent::kServerRsaSign = "rsa_sign"; const std::string TlsAgent::kServerRsaPss = "rsa_pss"; @@ -44,13 +45,22 @@ const std::string TlsAgent::kServerEcdhRsa = "ecdh_rsa"; const std::string TlsAgent::kServerEcdhEcdsa = "ecdh_ecdsa"; const std::string TlsAgent::kServerDsa = "dsa"; -TlsAgent::TlsAgent(const std::string& name, Role role, - SSLProtocolVariant variant) - : name_(name), - variant_(variant), - role_(role), +static const uint8_t kCannedTls13ServerHello[] = { + 0x03, 0x03, 0x9c, 0xbc, 0x14, 0x9b, 0x0e, 0x2e, 0xfa, 0x0d, 0xf3, + 0xf0, 0x5c, 0x70, 0x7a, 0xe0, 0xd1, 0x9b, 0x3e, 0x5a, 0x44, 0x6b, + 0xdf, 0xe5, 0xc2, 0x28, 0x64, 0xf7, 0x00, 0xc1, 0x9c, 0x08, 0x76, + 0x08, 0x00, 0x13, 0x01, 0x00, 0x00, 0x2e, 0x00, 0x33, 0x00, 0x24, + 0x00, 0x1d, 0x00, 0x20, 0xc2, 0xcf, 0x23, 0x17, 0x64, 0x23, 0x03, + 0xf0, 0xfb, 0x45, 0x98, 0x26, 0xd1, 0x65, 0x24, 0xa1, 0x6c, 0xa9, + 0x80, 0x8f, 0x2c, 0xac, 0x0a, 0xea, 0x53, 0x3a, 0xcb, 0xe3, 0x08, + 0x84, 0xae, 0x19, 0x00, 0x2b, 0x00, 0x02, 0x7f, kD13}; + +TlsAgent::TlsAgent(const std::string& nm, Role rl, SSLProtocolVariant var) + : name_(nm), + variant_(var), + role_(rl), server_key_bits_(0), - adapter_(new DummyPrSocket(role_str(), variant)), + adapter_(new DummyPrSocket(role_str(), var)), ssl_fd_(nullptr), state_(STATE_INIT), timer_handle_(nullptr), @@ -103,11 +113,11 @@ TlsAgent::~TlsAgent() { } } -void TlsAgent::SetState(State state) { - if (state_ == state) return; +void TlsAgent::SetState(State s) { + if (state_ == s) return; - LOG("Changing state from " << state_ << " to " << state); - state_ = state; + LOG("Changing state from " << state_ << " to " << s); + state_ = s; } /*static*/ bool TlsAgent::LoadCertificate(const std::string& name, @@ -124,11 +134,11 @@ void TlsAgent::SetState(State state) { return true; } -bool TlsAgent::ConfigServerCert(const std::string& name, bool updateKeyBits, +bool TlsAgent::ConfigServerCert(const std::string& id, bool updateKeyBits, const SSLExtraServerCertData* serverCertData) { ScopedCERTCertificate cert; ScopedSECKEYPrivateKey priv; - if (!TlsAgent::LoadCertificate(name, &cert, &priv)) { + if (!TlsAgent::LoadCertificate(id, &cert, &priv)) { return false; } @@ -175,6 +185,10 @@ bool TlsAgent::EnsureTlsSetup(PRFileDesc* modelSocket) { if (rv != SECSuccess) return false; } + ScopedCERTCertList anchors(CERT_NewCertList()); + rv = SSL_SetTrustAnchors(ssl_fd(), anchors.get()); + if (rv != SECSuccess) return false; + if (role_ == SERVER) { EXPECT_TRUE(ConfigServerCert(name_, true)); @@ -182,10 +196,6 @@ bool TlsAgent::EnsureTlsSetup(PRFileDesc* modelSocket) { EXPECT_EQ(SECSuccess, rv); if (rv != SECSuccess) return false; - ScopedCERTCertList anchors(CERT_NewCertList()); - rv = SSL_SetTrustAnchors(ssl_fd(), anchors.get()); - if (rv != SECSuccess) return false; - rv = SSL_SetMaxEarlyDataSize(ssl_fd(), 1024); EXPECT_EQ(SECSuccess, rv); if (rv != SECSuccess) return false; @@ -246,6 +256,17 @@ void TlsAgent::SetupClientAuth() { reinterpret_cast<void*>(this))); } +void CheckCertReqAgainstDefaultCAs(const CERTDistNames* caNames) { + ScopedCERTDistNames expected(CERT_GetSSLCACerts(nullptr)); + + ASSERT_EQ(expected->nnames, caNames->nnames); + + for (size_t i = 0; i < static_cast<size_t>(expected->nnames); ++i) { + EXPECT_EQ(SECEqual, + SECITEM_CompareItem(&(expected->names[i]), &(caNames->names[i]))); + } +} + SECStatus TlsAgent::GetClientAuthDataHook(void* self, PRFileDesc* fd, CERTDistNames* caNames, CERTCertificate** clientCert, @@ -254,6 +275,9 @@ SECStatus TlsAgent::GetClientAuthDataHook(void* self, PRFileDesc* fd, ScopedCERTCertificate peerCert(SSL_PeerCertificate(agent->ssl_fd())); EXPECT_TRUE(peerCert) << "Client should be able to see the server cert"; + // See bug 1457716 + // CheckCertReqAgainstDefaultCAs(caNames); + ScopedCERTCertificate cert; ScopedSECKEYPrivateKey priv; if (!TlsAgent::LoadCertificate(agent->name(), &cert, &priv)) { @@ -282,8 +306,8 @@ bool TlsAgent::GetPeerChainLength(size_t* count) { return true; } -void TlsAgent::CheckCipherSuite(uint16_t cipher_suite) { - EXPECT_EQ(csinfo_.cipherSuite, cipher_suite); +void TlsAgent::CheckCipherSuite(uint16_t suite) { + EXPECT_EQ(csinfo_.cipherSuite, suite); } void TlsAgent::RequestClientAuth(bool requireAuth) { @@ -442,9 +466,7 @@ void TlsAgent::GetVersionRange(uint16_t* minver, uint16_t* maxver) { *maxver = vrange_.max; } -void TlsAgent::SetExpectedVersion(uint16_t version) { - expected_version_ = version; -} +void TlsAgent::SetExpectedVersion(uint16_t ver) { expected_version_ = ver; } void TlsAgent::SetServerKeyBits(uint16_t bits) { server_key_bits_ = bits; } @@ -491,10 +513,10 @@ void TlsAgent::SetSignatureSchemes(const SSLSignatureScheme* schemes, EXPECT_EQ(i, configuredCount) << "schemes in use were all set"; } -void TlsAgent::CheckKEA(SSLKEAType kea_type, SSLNamedGroup kea_group, +void TlsAgent::CheckKEA(SSLKEAType kea, SSLNamedGroup kea_group, size_t kea_size) const { EXPECT_EQ(STATE_CONNECTED, state_); - EXPECT_EQ(kea_type, info_.keaType); + EXPECT_EQ(kea, info_.keaType); if (kea_size == 0) { switch (kea_group) { case ssl_grp_ec_curve25519: @@ -515,7 +537,7 @@ void TlsAgent::CheckKEA(SSLKEAType kea_type, SSLNamedGroup kea_group, case ssl_grp_ffdhe_custom: break; default: - if (kea_type == ssl_kea_rsa) { + if (kea == ssl_kea_rsa) { kea_size = server_key_bits_; } else { EXPECT_TRUE(false) << "need to update group sizes"; @@ -534,13 +556,13 @@ void TlsAgent::CheckOriginalKEA(SSLNamedGroup kea_group) const { } } -void TlsAgent::CheckAuthType(SSLAuthType auth_type, +void TlsAgent::CheckAuthType(SSLAuthType auth, SSLSignatureScheme sig_scheme) const { EXPECT_EQ(STATE_CONNECTED, state_); - EXPECT_EQ(auth_type, info_.authType); + EXPECT_EQ(auth, info_.authType); EXPECT_EQ(server_key_bits_, info_.authKeyBits); if (expected_version_ < SSL_LIBRARY_VERSION_TLS_1_2) { - switch (auth_type) { + switch (auth) { case ssl_auth_rsa_sign: sig_scheme = ssl_sig_rsa_pkcs1_sha1md5; break; @@ -558,9 +580,8 @@ void TlsAgent::CheckAuthType(SSLAuthType auth_type, } // Check authAlgorithm, which is the old value for authType. This is a second - // switch - // statement because default label is different. - switch (auth_type) { + // switch statement because default label is different. + switch (auth) { case ssl_auth_rsa_sign: EXPECT_EQ(ssl_auth_rsa_decrypt, csinfo_.authAlgorithm) << "authAlgorithm for RSA is always decrypt"; @@ -574,7 +595,7 @@ void TlsAgent::CheckAuthType(SSLAuthType auth_type, << "authAlgorithm for ECDH_ECDSA is ECDSA (i.e., wrong)"; break; default: - EXPECT_EQ(auth_type, csinfo_.authAlgorithm) + EXPECT_EQ(auth, csinfo_.authAlgorithm) << "authAlgorithm is (usually) the same as authType"; break; } @@ -593,22 +614,20 @@ void TlsAgent::ExpectResumption() { expect_resumption_ = true; } void TlsAgent::EnableAlpn(const uint8_t* val, size_t len) { EXPECT_TRUE(EnsureTlsSetup()); - - SetOption(SSL_ENABLE_ALPN, PR_TRUE); EXPECT_EQ(SECSuccess, SSL_SetNextProtoNego(ssl_fd(), val, len)); } void TlsAgent::CheckAlpn(SSLNextProtoState expected_state, const std::string& expected) const { - SSLNextProtoState state; + SSLNextProtoState alpn_state; char chosen[10]; unsigned int chosen_len; - SECStatus rv = SSL_GetNextProto(ssl_fd(), &state, + SECStatus rv = SSL_GetNextProto(ssl_fd(), &alpn_state, reinterpret_cast<unsigned char*>(chosen), &chosen_len, sizeof(chosen)); EXPECT_EQ(SECSuccess, rv); - EXPECT_EQ(expected_state, state); - if (state == SSL_NEXT_PROTO_NO_SUPPORT) { + EXPECT_EQ(expected_state, alpn_state); + if (alpn_state == SSL_NEXT_PROTO_NO_SUPPORT) { EXPECT_EQ("", expected); } else { EXPECT_NE("", expected); @@ -840,10 +859,10 @@ void TlsAgent::CheckSecretsDestroyed() { ASSERT_EQ(PR_TRUE, SSLInt_CheckSecretsDestroyed(ssl_fd())); } -void TlsAgent::SetDowngradeCheckVersion(uint16_t version) { +void TlsAgent::SetDowngradeCheckVersion(uint16_t ver) { ASSERT_TRUE(EnsureTlsSetup()); - SECStatus rv = SSL_SetDowngradeCheckVersion(ssl_fd(), version); + SECStatus rv = SSL_SetDowngradeCheckVersion(ssl_fd(), ver); ASSERT_EQ(SECSuccess, rv); } @@ -920,9 +939,9 @@ static bool ErrorIsNonFatal(PRErrorCode code) { } void TlsAgent::SendData(size_t bytes, size_t blocksize) { - uint8_t block[4096]; + uint8_t block[16385]; // One larger than the maximum record size. - ASSERT_LT(blocksize, sizeof(block)); + ASSERT_LE(blocksize, sizeof(block)); while (bytes) { size_t tosend = std::min(blocksize, bytes); @@ -951,12 +970,13 @@ void TlsAgent::SendBuffer(const DataBuffer& buf) { } bool TlsAgent::SendEncryptedRecord(const std::shared_ptr<TlsCipherSpec>& spec, - uint16_t wireVersion, uint64_t seq, - uint8_t ct, const DataBuffer& buf) { - LOGV("Writing " << buf.len() << " bytes"); - // Ensure we are a TLS 1.3 cipher agent. + uint64_t seq, uint8_t ct, + const DataBuffer& buf) { + LOGV("Encrypting " << buf.len() << " bytes"); + // Ensure that we are doing TLS 1.3. EXPECT_GE(expected_version_, SSL_LIBRARY_VERSION_TLS_1_3); - TlsRecordHeader header(wireVersion, kTlsApplicationDataType, seq); + TlsRecordHeader header(variant_, expected_version_, kTlsApplicationDataType, + seq); DataBuffer padded = buf; padded.Write(padded.len(), ct, 1); DataBuffer ciphertext; @@ -1078,15 +1098,20 @@ void TlsAgentTestBase::ProcessMessage(const DataBuffer& buffer, void TlsAgentTestBase::MakeRecord(SSLProtocolVariant variant, uint8_t type, uint16_t version, const uint8_t* buf, size_t len, DataBuffer* out, - uint64_t seq_num) { + uint64_t sequence_number) { size_t index = 0; index = out->Write(index, type, 1); if (variant == ssl_variant_stream) { index = out->Write(index, version, 2); + } else if (version >= SSL_LIBRARY_VERSION_TLS_1_3 && + type == kTlsApplicationDataType) { + uint32_t epoch = (sequence_number >> 48) & 0x3; + uint32_t seqno = sequence_number & ((1ULL << 30) - 1); + index = out->Write(index, (epoch << 30) | seqno, 4); } else { index = out->Write(index, TlsVersionToDtlsVersion(version), 2); - index = out->Write(index, seq_num >> 32, 4); - index = out->Write(index, seq_num & PR_UINT32_MAX, 4); + index = out->Write(index, sequence_number >> 32, 4); + index = out->Write(index, sequence_number & PR_UINT32_MAX, 4); } index = out->Write(index, len, 2); out->Write(index, buf, len); @@ -1144,4 +1169,12 @@ void TlsAgentTestBase::MakeTrivialHandshakeRecord(uint8_t hs_type, } } +DataBuffer TlsAgentTestBase::MakeCannedTls13ServerHello() { + DataBuffer sh(kCannedTls13ServerHello, sizeof(kCannedTls13ServerHello)); + if (variant_ == ssl_variant_datagram) { + sh.Write(0, SSL_LIBRARY_VERSION_DTLS_1_2_WIRE, 2); + } + return sh; +} + } // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/tls_agent.h b/security/nss/gtests/ssl_gtest/tls_agent.h index 6cd6d5073..a93d0c6ee 100644 --- a/security/nss/gtests/ssl_gtest/tls_agent.h +++ b/security/nss/gtests/ssl_gtest/tls_agent.h @@ -10,6 +10,9 @@ #include "prio.h" #include "ssl.h" +// This is an internal header, used to get TLS_1_3_DRAFT_VERSION. +#include "ssl3prot.h" + #include <functional> #include <iostream> @@ -57,6 +60,8 @@ typedef std::function<int32_t(TlsAgent* agent, const SECItem* srvNameArr, PRUint32 srvNameArrSize)> SniCallbackFunction; +static const uint8_t kD13 = TLS_1_3_DRAFT_VERSION; + class TlsAgent : public PollTarget { public: enum Role { CLIENT, SERVER }; @@ -64,6 +69,7 @@ class TlsAgent : public PollTarget { static const std::string kClient; // the client key is sign only static const std::string kRsa2048; // bigger sign and encrypt for either + static const std::string kRsa8192; // biggest sign and encrypt for either static const std::string kServerRsa; // both sign and encrypt static const std::string kServerRsaSign; static const std::string kServerRsaPss; @@ -143,8 +149,7 @@ class TlsAgent : public PollTarget { void SendData(size_t bytes, size_t blocksize = 1024); void SendBuffer(const DataBuffer& buf); bool SendEncryptedRecord(const std::shared_ptr<TlsCipherSpec>& spec, - uint16_t wireVersion, uint64_t seq, uint8_t ct, - const DataBuffer& buf); + uint64_t seq, uint8_t ct, const DataBuffer& buf); // Send data directly to the underlying socket, skipping the TLS layer. void SendDirect(const DataBuffer& buf); void SendRecordDirect(const TlsRecord& record); @@ -209,10 +214,10 @@ class TlsAgent : public PollTarget { return info_.protocolVersion; } - bool cipher_suite(uint16_t* cipher_suite) const { + bool cipher_suite(uint16_t* suite) const { if (state_ != STATE_CONNECTED) return false; - *cipher_suite = info_.cipherSuite; + *suite = info_.cipherSuite; return true; } @@ -227,17 +232,17 @@ class TlsAgent : public PollTarget { info_.sessionID + info_.sessionIDLength); } - bool auth_type(SSLAuthType* auth_type) const { + bool auth_type(SSLAuthType* a) const { if (state_ != STATE_CONNECTED) return false; - *auth_type = info_.authType; + *a = info_.authType; return true; } - bool kea_type(SSLKEAType* kea_type) const { + bool kea_type(SSLKEAType* k) const { if (state_ != STATE_CONNECTED) return false; - *kea_type = info_.keaType; + *k = info_.keaType; return true; } @@ -264,6 +269,8 @@ class TlsAgent : public PollTarget { void ExpectReceiveAlert(uint8_t alert, uint8_t level = 0); void ExpectSendAlert(uint8_t alert, uint8_t level = 0); + std::string alpn_value_to_use_ = ""; + private: const static char* states[]; @@ -443,6 +450,7 @@ class TlsAgentTestBase : public ::testing::Test { size_t hs_len, DataBuffer* out, uint64_t seq_num, uint32_t fragment_offset, uint32_t fragment_length) const; + DataBuffer MakeCannedTls13ServerHello(); static void MakeTrivialHandshakeRecord(uint8_t hs_type, size_t hs_len, DataBuffer* out); static inline TlsAgent::Role ToRole(const std::string& str) { diff --git a/security/nss/gtests/ssl_gtest/tls_connect.cc b/security/nss/gtests/ssl_gtest/tls_connect.cc index 8567b392f..68f6d21e9 100644 --- a/security/nss/gtests/ssl_gtest/tls_connect.cc +++ b/security/nss/gtests/ssl_gtest/tls_connect.cc @@ -571,14 +571,57 @@ void TlsConnectTestBase::CheckResumption(SessionResumptionMode expected) { } } +static SECStatus NextProtoCallbackServer(void* arg, PRFileDesc* fd, + const unsigned char* protos, + unsigned int protos_len, + unsigned char* protoOut, + unsigned int* protoOutLen, + unsigned int protoMaxLen) { + EXPECT_EQ(protoMaxLen, 255U); + TlsAgent* agent = reinterpret_cast<TlsAgent*>(arg); + // Check that agent->alpn_value_to_use_ is in protos. + if (protos_len < 1) { + return SECFailure; + } + for (size_t i = 0; i < protos_len;) { + size_t l = protos[i]; + EXPECT_LT(i + l, protos_len); + if (i + l >= protos_len) { + return SECFailure; + } + std::string protos_s(reinterpret_cast<const char*>(protos + i + 1), l); + if (protos_s == agent->alpn_value_to_use_) { + size_t s_len = agent->alpn_value_to_use_.size(); + EXPECT_LE(s_len, 255U); + memcpy(protoOut, &agent->alpn_value_to_use_[0], s_len); + *protoOutLen = s_len; + return SECSuccess; + } + i += l + 1; + } + return SECFailure; +} + void TlsConnectTestBase::EnableAlpn() { client_->EnableAlpn(alpn_dummy_val_, sizeof(alpn_dummy_val_)); server_->EnableAlpn(alpn_dummy_val_, sizeof(alpn_dummy_val_)); } -void TlsConnectTestBase::EnableAlpn(const uint8_t* val, size_t len) { - client_->EnableAlpn(val, len); - server_->EnableAlpn(val, len); +void TlsConnectTestBase::EnableAlpnWithCallback( + const std::vector<uint8_t>& client_vals, std::string server_choice) { + EnsureTlsSetup(); + server_->alpn_value_to_use_ = server_choice; + EXPECT_EQ(SECSuccess, + SSL_SetNextProtoNego(client_->ssl_fd(), client_vals.data(), + client_vals.size())); + SECStatus rv = SSL_SetNextProtoCallback( + server_->ssl_fd(), NextProtoCallbackServer, server_.get()); + EXPECT_EQ(SECSuccess, rv); +} + +void TlsConnectTestBase::EnableAlpn(const std::vector<uint8_t>& vals) { + client_->EnableAlpn(vals.data(), vals.size()); + server_->EnableAlpn(vals.data(), vals.size()); } void TlsConnectTestBase::EnsureModelSockets() { diff --git a/security/nss/gtests/ssl_gtest/tls_connect.h b/security/nss/gtests/ssl_gtest/tls_connect.h index 7dffe7f8a..000494501 100644 --- a/security/nss/gtests/ssl_gtest/tls_connect.h +++ b/security/nss/gtests/ssl_gtest/tls_connect.h @@ -110,7 +110,9 @@ class TlsConnectTestBase : public ::testing::Test { void ConfigureSessionCache(SessionResumptionMode client, SessionResumptionMode server); void EnableAlpn(); - void EnableAlpn(const uint8_t* val, size_t len); + void EnableAlpnWithCallback(const std::vector<uint8_t>& client, + std::string server_choice); + void EnableAlpn(const std::vector<uint8_t>& vals); void EnsureModelSockets(); void CheckAlpn(const std::string& val); void EnableSrtp(); diff --git a/security/nss/gtests/ssl_gtest/tls_filter.cc b/security/nss/gtests/ssl_gtest/tls_filter.cc index d34b13bcb..aa03cba70 100644 --- a/security/nss/gtests/ssl_gtest/tls_filter.cc +++ b/security/nss/gtests/ssl_gtest/tls_filter.cc @@ -30,11 +30,9 @@ void TlsVersioned::WriteStream(std::ostream& stream) const { case SSL_LIBRARY_VERSION_TLS_1_0: stream << "1.0"; break; - case SSL_LIBRARY_VERSION_DTLS_1_0_WIRE: case SSL_LIBRARY_VERSION_TLS_1_1: stream << (is_dtls() ? "1.0" : "1.1"); break; - case SSL_LIBRARY_VERSION_DTLS_1_2_WIRE: case SSL_LIBRARY_VERSION_TLS_1_2: stream << "1.2"; break; @@ -67,8 +65,14 @@ void TlsRecordFilter::CipherSpecChanged(void* arg, PRBool sending, return; } - self->in_sequence_number_ = 0; - self->out_sequence_number_ = 0; + 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; + } + 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( @@ -77,33 +81,59 @@ void TlsRecordFilter::CipherSpecChanged(void* arg, PRBool sending, EXPECT_EQ(true, ret); } +bool TlsRecordFilter::is_dtls13() const { + if (agent()->variant() != ssl_variant_datagram) { + return false; + } + if (agent()->state() == TlsAgent::STATE_CONNECTED) { + return agent()->version() >= SSL_LIBRARY_VERSION_TLS_1_3; + } + SSLPreliminaryChannelInfo info; + EXPECT_EQ(SECSuccess, SSL_GetPreliminaryChannelInfo(agent()->ssl_fd(), &info, + sizeof(info))); + return (info.protocolVersion >= SSL_LIBRARY_VERSION_TLS_1_3) || + info.canSendEarlyData; +} + PacketFilter::Action TlsRecordFilter::Filter(const DataBuffer& input, DataBuffer* output) { + // Disable during shutdown. + if (!agent()) { + return KEEP; + } + bool changed = false; size_t offset = 0U; - output->Allocate(input.len()); + output->Allocate(input.len()); TlsParser parser(input); while (parser.remaining()) { TlsRecordHeader header; DataBuffer record; - if (!header.Parse(in_sequence_number_, &parser, &record)) { + if (!header.Parse(is_dtls13(), in_sequence_number_, &parser, &record)) { ADD_FAILURE() << "not a valid record"; return KEEP; } - // Track the sequence number, which is necessary for stream mode (the - // sequence number is in the header for datagram). + // 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 + // 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 AND packets were dropped from the - // older epoch, we will not correctly re-encrypt records in the old epoch to - // update their sequence numbers. - if (cipher_spec_ && header.content_type() == kTlsApplicationDataType) { - ++in_sequence_number_; + // 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() == kTlsApplicationDataType) { + in_sequence_number_ = + (std::max)(in_sequence_number_, header.sequence_number() + 1); } if (FilterRecord(header, record, &offset, output) != KEEP) { @@ -131,11 +161,14 @@ PacketFilter::Action TlsRecordFilter::FilterRecord( DataBuffer plaintext; if (!Unprotect(header, record, &inner_content_type, &plaintext)) { + if (g_ssl_gtest_verbose) { + std::cerr << "unprotect failed: " << header << ":" << record << std::endl; + } return KEEP; } - TlsRecordHeader real_header = {header.version(), inner_content_type, - header.sequence_number()}; + TlsRecordHeader real_header(header.variant(), header.version(), + inner_content_type, header.sequence_number()); PacketFilter::Action action = FilterRecord(real_header, plaintext, &filtered); // In stream mode, even if something doesn't change we need to re-encrypt if @@ -166,8 +199,8 @@ PacketFilter::Action TlsRecordFilter::FilterRecord( } else { seq_num = out_sequence_number_++; } - TlsRecordHeader out_header = {header.version(), header.content_type(), - seq_num}; + TlsRecordHeader out_header(header.variant(), header.version(), + header.content_type(), seq_num); DataBuffer ciphertext; bool rv = Protect(out_header, inner_content_type, filtered, &ciphertext); @@ -179,20 +212,119 @@ PacketFilter::Action TlsRecordFilter::FilterRecord( return CHANGE; } -bool TlsRecordHeader::Parse(uint64_t sequence_number, TlsParser* parser, +size_t TlsRecordHeader::header_length() const { + // If we have a header, return it's length. + if (header_.len()) { + return header_.len(); + } + + // Otherwise make a dummy header and return the length. + DataBuffer buf; + return WriteHeader(&buf, 0, 0); +} + +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; + // 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)); + // 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)) { + seq_no -= 1ULL << partial_bits; + } + return seq_no; +} + +// Determine the full epoch and sequence number from an expected and raw value. +// The expected and output values are packed as they are in DTLS 1.2 and +// earlier: with 16 bits of epoch and 48 bits of sequence number. +uint64_t TlsRecordHeader::ParseSequenceNumber(uint64_t expected, uint32_t raw, + size_t seq_no_bits, + size_t epoch_bits) { + uint64_t epoch_mask = (1ULL << epoch_bits) - 1; + uint64_t epoch = RecoverSequenceNumber( + expected >> 48, (raw >> seq_no_bits) & epoch_mask, epoch_bits); + if (epoch > (expected >> 48)) { + // If the epoch has changed, reset the expected sequence number. + expected = 0; + } else { + // Otherwise, retain just the sequence number part. + expected &= (1ULL << 48) - 1; + } + uint64_t seq_no_mask = (1ULL << seq_no_bits) - 1; + uint64_t seq_no = + RecoverSequenceNumber(expected, raw & seq_no_mask, seq_no_bits); + return (epoch << 48) | seq_no; +} + +bool TlsRecordHeader::Parse(bool is_dtls13, uint64_t seqno, TlsParser* parser, DataBuffer* body) { + auto mark = parser->consumed(); + if (!parser->Read(&content_type_)) { return false; } - uint32_t version; - if (!parser->Read(&version, 2)) { + if (is_dtls13) { + variant_ = ssl_variant_datagram; + version_ = SSL_LIBRARY_VERSION_TLS_1_3; + +#ifndef UNSAFE_FUZZER_MODE + // Deal with the 7 octet header. + if (content_type_ == kTlsApplicationDataType) { + uint32_t tmp; + if (!parser->Read(&tmp, 4)) { + return false; + } + sequence_number_ = ParseSequenceNumber(seqno, tmp, 30, 2); + if (!parser->ReadFromMark(&header_, parser->consumed() + 2 - mark, + mark)) { + return false; + } + return parser->ReadVariable(body, 2); + } + + // The short, 2 octet header. + if ((content_type_ & 0xe0) == 0x20) { + uint32_t tmp; + if (!parser->Read(&tmp, 1)) { + return false; + } + // Need to use the low 5 bits of the first octet too. + tmp |= (content_type_ & 0x1f) << 8; + content_type_ = kTlsApplicationDataType; + sequence_number_ = ParseSequenceNumber(seqno, tmp, 12, 1); + + if (!parser->ReadFromMark(&header_, parser->consumed() - mark, mark)) { + return false; + } + return parser->Read(body, parser->remaining()); + } + + // The full 13 octet header can only be used for a few types. + EXPECT_TRUE(content_type_ == kTlsAlertType || + content_type_ == kTlsHandshakeType || + content_type_ == kTlsAckType); +#endif + } + + uint32_t ver; + if (!parser->Read(&ver, 2)) { return false; } - version_ = version; + if (!is_dtls13) { + variant_ = IsDtls(ver) ? ssl_variant_datagram : ssl_variant_stream; + } + version_ = NormalizeTlsVersion(ver); - // If this is DTLS, overwrite the sequence number. - if (IsDtls(version)) { + if (is_dtls()) { + // If this is DTLS, read the sequence number. uint32_t tmp; if (!parser->Read(&tmp, 4)) { return false; @@ -203,21 +335,40 @@ bool TlsRecordHeader::Parse(uint64_t sequence_number, TlsParser* parser, } sequence_number_ |= static_cast<uint64_t>(tmp); } else { - sequence_number_ = sequence_number; + sequence_number_ = seqno; + } + if (!parser->ReadFromMark(&header_, parser->consumed() + 2 - mark, mark)) { + return false; } return parser->ReadVariable(body, 2); } -size_t TlsRecordHeader::Write(DataBuffer* buffer, size_t offset, - const DataBuffer& body) const { +size_t TlsRecordHeader::WriteHeader(DataBuffer* buffer, size_t offset, + size_t body_len) const { offset = buffer->Write(offset, content_type_, 1); - offset = buffer->Write(offset, version_, 2); - if (is_dtls()) { - // write epoch (2 octet), and seqnum (6 octet) - offset = buffer->Write(offset, sequence_number_ >> 32, 4); - offset = buffer->Write(offset, sequence_number_ & 0xffffffff, 4); + if (is_dtls() && version_ >= SSL_LIBRARY_VERSION_TLS_1_3 && + content_type() == kTlsApplicationDataType) { + // application_data records in TLS 1.3 have a different header format. + // Always use the long header here for simplicity. + uint32_t e = (sequence_number_ >> 48) & 0x3; + uint32_t seqno = sequence_number_ & ((1ULL << 30) - 1); + offset = buffer->Write(offset, (e << 30) | seqno, 4); + } else { + uint16_t v = is_dtls() ? TlsVersionToDtlsVersion(version_) : version_; + offset = buffer->Write(offset, v, 2); + if (is_dtls()) { + // write epoch (2 octet), and seqnum (6 octet) + offset = buffer->Write(offset, sequence_number_ >> 32, 4); + offset = buffer->Write(offset, sequence_number_ & 0xffffffff, 4); + } } - offset = buffer->Write(offset, body.len(), 2); + offset = buffer->Write(offset, body_len, 2); + return offset; +} + +size_t TlsRecordHeader::Write(DataBuffer* buffer, size_t offset, + const DataBuffer& body) const { + offset = WriteHeader(buffer, offset, body.len()); offset = buffer->Write(offset, body); return offset; } @@ -259,7 +410,7 @@ bool TlsRecordFilter::Unprotect(const TlsRecordHeader& header, bool TlsRecordFilter::Protect(const TlsRecordHeader& header, uint8_t inner_content_type, const DataBuffer& plaintext, - DataBuffer* ciphertext) { + DataBuffer* ciphertext, size_t padding) { if (!cipher_spec_ || header.content_type() != kTlsApplicationDataType) { *ciphertext = plaintext; return true; @@ -267,8 +418,10 @@ bool TlsRecordFilter::Protect(const TlsRecordHeader& header, if (g_ssl_gtest_verbose) { std::cerr << "protect: " << header.sequence_number() << std::endl; } - DataBuffer padded = plaintext; - padded.Write(padded.len(), inner_content_type, 1); + 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); } @@ -406,6 +559,7 @@ bool TlsHandshakeFilter::HandshakeHeader::Parse( const DataBuffer& preceding_fragment, DataBuffer* body, bool* complete) { *complete = false; + variant_ = record_header.variant(); version_ = record_header.version(); if (!parser->Read(&handshake_type_)) { return false; // malformed @@ -487,10 +641,10 @@ PacketFilter::Action TlsConversationRecorder::FilterRecord( return KEEP; } -PacketFilter::Action TlsHeaderRecorder::FilterRecord( - const TlsRecordHeader& header, const DataBuffer& input, - DataBuffer* output) { - headers_.push_back(header); +PacketFilter::Action TlsHeaderRecorder::FilterRecord(const TlsRecordHeader& hdr, + const DataBuffer& input, + DataBuffer* output) { + headers_.push_back(hdr); return KEEP; } diff --git a/security/nss/gtests/ssl_gtest/tls_filter.h b/security/nss/gtests/ssl_gtest/tls_filter.h index 1bbe190ab..effda4aa0 100644 --- a/security/nss/gtests/ssl_gtest/tls_filter.h +++ b/security/nss/gtests/ssl_gtest/tls_filter.h @@ -11,7 +11,7 @@ #include <memory> #include <set> #include <vector> - +#include "sslt.h" #include "test_io.h" #include "tls_agent.h" #include "tls_parser.h" @@ -27,43 +27,57 @@ class TlsCipherSpec; class TlsVersioned { public: - TlsVersioned() : version_(0) {} - explicit TlsVersioned(uint16_t version) : version_(version) {} + TlsVersioned() : variant_(ssl_variant_stream), version_(0) {} + TlsVersioned(SSLProtocolVariant var, uint16_t ver) + : variant_(var), version_(ver) {} - bool is_dtls() const { return IsDtls(version_); } + bool is_dtls() const { return variant_ == ssl_variant_datagram; } + SSLProtocolVariant variant() const { return variant_; } uint16_t version() const { return version_; } void WriteStream(std::ostream& stream) const; protected: + SSLProtocolVariant variant_; uint16_t version_; }; class TlsRecordHeader : public TlsVersioned { public: - TlsRecordHeader() : TlsVersioned(), content_type_(0), sequence_number_(0) {} - TlsRecordHeader(uint16_t version, uint8_t content_type, - uint64_t sequence_number) - : TlsVersioned(version), - content_type_(content_type), - sequence_number_(sequence_number) {} + TlsRecordHeader() + : TlsVersioned(), content_type_(0), sequence_number_(0), header_() {} + TlsRecordHeader(SSLProtocolVariant var, uint16_t ver, uint8_t ct, + uint64_t seqno) + : TlsVersioned(var, ver), + content_type_(ct), + sequence_number_(seqno), + header_() {} uint8_t content_type() const { return content_type_; } uint64_t sequence_number() const { return sequence_number_; } uint16_t epoch() const { return static_cast<uint16_t>(sequence_number_ >> 48); } - size_t header_length() const { return is_dtls() ? 13 : 5; } + size_t header_length() const; + const DataBuffer& header() const { return header_; } // Parse the header; return true if successful; body in an outparam if OK. - bool Parse(uint64_t sequence_number, TlsParser* parser, DataBuffer* body); + bool Parse(bool is_dtls13, uint64_t sequence_number, TlsParser* parser, + DataBuffer* body); // Write the header and body to a buffer at the given offset. // Return the offset of the end of the write. size_t Write(DataBuffer* buffer, size_t offset, const DataBuffer& body) const; + size_t WriteHeader(DataBuffer* buffer, size_t offset, size_t body_len) const; private: + static uint64_t RecoverSequenceNumber(uint64_t expected, uint32_t partial, + size_t partial_bits); + static uint64_t ParseSequenceNumber(uint64_t expected, uint32_t raw, + size_t seq_no_bits, size_t epoch_bits); + uint8_t content_type_; uint64_t sequence_number_; + DataBuffer header_; }; struct TlsRecord { @@ -83,8 +97,8 @@ 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>& agent) - : agent_(agent), + TlsRecordFilter(const std::shared_ptr<TlsAgent>& a) + : agent_(a), count_(0), cipher_spec_(), dropped_record_(false), @@ -106,7 +120,8 @@ class TlsRecordFilter : public PacketFilter { 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); + const DataBuffer& plaintext, DataBuffer* ciphertext, + size_t padding = 0); protected: // There are two filter functions which can be overriden. Both are @@ -130,6 +145,8 @@ class TlsRecordFilter : public PacketFilter { return KEEP; } + bool is_dtls13() const; + private: static void CipherSpecChanged(void* arg, PRBool sending, ssl3CipherSpec* newSpec); @@ -183,13 +200,11 @@ inline std::ostream& operator<<(std::ostream& stream, // records and that they don't span records or anything crazy like that. class TlsHandshakeFilter : public TlsRecordFilter { public: - TlsHandshakeFilter(const std::shared_ptr<TlsAgent>& agent) - : TlsRecordFilter(agent), handshake_types_(), preceding_fragment_() {} - TlsHandshakeFilter(const std::shared_ptr<TlsAgent>& agent, + TlsHandshakeFilter(const std::shared_ptr<TlsAgent>& a) + : TlsRecordFilter(a), handshake_types_(), preceding_fragment_() {} + TlsHandshakeFilter(const std::shared_ptr<TlsAgent>& a, const std::set<uint8_t>& types) - : TlsRecordFilter(agent), - handshake_types_(types), - preceding_fragment_() {} + : TlsRecordFilter(a), handshake_types_(types), preceding_fragment_() {} // This filter can be set to be selective based on handshake message type. If // this function isn't used (or the set is empty), then all handshake messages @@ -243,12 +258,12 @@ class TlsHandshakeFilter : public TlsRecordFilter { // Make a copy of the first instance of a handshake message. class TlsHandshakeRecorder : public TlsHandshakeFilter { public: - TlsHandshakeRecorder(const std::shared_ptr<TlsAgent>& agent, + TlsHandshakeRecorder(const std::shared_ptr<TlsAgent>& a, uint8_t handshake_type) - : TlsHandshakeFilter(agent, {handshake_type}), buffer_() {} - TlsHandshakeRecorder(const std::shared_ptr<TlsAgent>& agent, + : TlsHandshakeFilter(a, {handshake_type}), buffer_() {} + TlsHandshakeRecorder(const std::shared_ptr<TlsAgent>& a, const std::set<uint8_t>& handshake_types) - : TlsHandshakeFilter(agent, handshake_types), buffer_() {} + : TlsHandshakeFilter(a, handshake_types), buffer_() {} virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, const DataBuffer& input, @@ -265,10 +280,10 @@ class TlsHandshakeRecorder : public TlsHandshakeFilter { // Replace all instances of a handshake message. class TlsInspectorReplaceHandshakeMessage : public TlsHandshakeFilter { public: - TlsInspectorReplaceHandshakeMessage(const std::shared_ptr<TlsAgent>& agent, + TlsInspectorReplaceHandshakeMessage(const std::shared_ptr<TlsAgent>& a, uint8_t handshake_type, const DataBuffer& replacement) - : TlsHandshakeFilter(agent, {handshake_type}), buffer_(replacement) {} + : TlsHandshakeFilter(a, {handshake_type}), buffer_(replacement) {} virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, const DataBuffer& input, @@ -281,10 +296,10 @@ class TlsInspectorReplaceHandshakeMessage : public TlsHandshakeFilter { // Make a copy of each record of a given type. class TlsRecordRecorder : public TlsRecordFilter { public: - TlsRecordRecorder(const std::shared_ptr<TlsAgent>& agent, uint8_t ct) - : TlsRecordFilter(agent), filter_(true), ct_(ct), records_() {} - TlsRecordRecorder(const std::shared_ptr<TlsAgent>& agent) - : TlsRecordFilter(agent), + TlsRecordRecorder(const std::shared_ptr<TlsAgent>& a, uint8_t ct) + : TlsRecordFilter(a), filter_(true), ct_(ct), records_() {} + TlsRecordRecorder(const std::shared_ptr<TlsAgent>& a) + : TlsRecordFilter(a), filter_(false), ct_(content_handshake), // dummy (<optional> is C++14) records_() {} @@ -306,9 +321,9 @@ class TlsRecordRecorder : public TlsRecordFilter { // Make a copy of the complete conversation. class TlsConversationRecorder : public TlsRecordFilter { public: - TlsConversationRecorder(const std::shared_ptr<TlsAgent>& agent, + TlsConversationRecorder(const std::shared_ptr<TlsAgent>& a, DataBuffer& buffer) - : TlsRecordFilter(agent), buffer_(buffer) {} + : TlsRecordFilter(a), buffer_(buffer) {} virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header, const DataBuffer& input, @@ -321,8 +336,7 @@ class TlsConversationRecorder : public TlsRecordFilter { // Make a copy of the records class TlsHeaderRecorder : public TlsRecordFilter { public: - TlsHeaderRecorder(const std::shared_ptr<TlsAgent>& agent) - : TlsRecordFilter(agent) {} + TlsHeaderRecorder(const std::shared_ptr<TlsAgent>& a) : TlsRecordFilter(a) {} virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header, const DataBuffer& input, DataBuffer* output); @@ -359,15 +373,15 @@ typedef std::function<bool(TlsParser* parser, const TlsVersioned& header)> class TlsExtensionFilter : public TlsHandshakeFilter { public: - TlsExtensionFilter(const std::shared_ptr<TlsAgent>& agent) - : TlsHandshakeFilter(agent, + TlsExtensionFilter(const std::shared_ptr<TlsAgent>& a) + : TlsHandshakeFilter(a, {kTlsHandshakeClientHello, kTlsHandshakeServerHello, kTlsHandshakeHelloRetryRequest, kTlsHandshakeEncryptedExtensions}) {} - TlsExtensionFilter(const std::shared_ptr<TlsAgent>& agent, + TlsExtensionFilter(const std::shared_ptr<TlsAgent>& a, const std::set<uint8_t>& types) - : TlsHandshakeFilter(agent, types) {} + : TlsHandshakeFilter(a, types) {} static bool FindExtensions(TlsParser* parser, const HandshakeHeader& header); @@ -388,9 +402,9 @@ class TlsExtensionFilter : public TlsHandshakeFilter { class TlsExtensionCapture : public TlsExtensionFilter { public: - TlsExtensionCapture(const std::shared_ptr<TlsAgent>& agent, uint16_t ext, + TlsExtensionCapture(const std::shared_ptr<TlsAgent>& a, uint16_t ext, bool last = false) - : TlsExtensionFilter(agent), + : TlsExtensionFilter(a), extension_(ext), captured_(false), last_(last), @@ -413,9 +427,9 @@ class TlsExtensionCapture : public TlsExtensionFilter { class TlsExtensionReplacer : public TlsExtensionFilter { public: - TlsExtensionReplacer(const std::shared_ptr<TlsAgent>& agent, - uint16_t extension, const DataBuffer& data) - : TlsExtensionFilter(agent), extension_(extension), data_(data) {} + TlsExtensionReplacer(const std::shared_ptr<TlsAgent>& a, uint16_t extension, + const DataBuffer& data) + : TlsExtensionFilter(a), extension_(extension), data_(data) {} PacketFilter::Action FilterExtension(uint16_t extension_type, const DataBuffer& input, DataBuffer* output) override; @@ -427,9 +441,8 @@ class TlsExtensionReplacer : public TlsExtensionFilter { class TlsExtensionDropper : public TlsExtensionFilter { public: - TlsExtensionDropper(const std::shared_ptr<TlsAgent>& agent, - uint16_t extension) - : TlsExtensionFilter(agent), extension_(extension) {} + TlsExtensionDropper(const std::shared_ptr<TlsAgent>& a, uint16_t extension) + : TlsExtensionFilter(a), extension_(extension) {} PacketFilter::Action FilterExtension(uint16_t extension_type, const DataBuffer&, DataBuffer*) override; @@ -439,9 +452,9 @@ class TlsExtensionDropper : public TlsExtensionFilter { class TlsExtensionInjector : public TlsHandshakeFilter { public: - TlsExtensionInjector(const std::shared_ptr<TlsAgent>& agent, uint16_t ext, + TlsExtensionInjector(const std::shared_ptr<TlsAgent>& a, uint16_t ext, const DataBuffer& data) - : TlsHandshakeFilter(agent), extension_(ext), data_(data) {} + : TlsHandshakeFilter(a), extension_(ext), data_(data) {} protected: PacketFilter::Action FilterHandshake(const HandshakeHeader& header, @@ -453,7 +466,6 @@ class TlsExtensionInjector : public TlsHandshakeFilter { const DataBuffer data_; }; -class TlsAgent; typedef std::function<void(void)> VoidFunction; class AfterRecordN : public TlsRecordFilter { @@ -495,6 +507,22 @@ class TlsClientHelloVersionChanger : public TlsHandshakeFilter { std::weak_ptr<TlsAgent> server_; }; +// Damage a record. +class TlsRecordLastByteDamager : public TlsRecordFilter { + public: + TlsRecordLastByteDamager(const std::shared_ptr<TlsAgent>& a) + : TlsRecordFilter(a) {} + + protected: + PacketFilter::Action FilterRecord(const TlsRecordHeader& header, + const DataBuffer& data, + DataBuffer* changed) override { + *changed = data; + changed->data()[changed->len() - 1]++; + return CHANGE; + } +}; + // This class selectively drops complete writes. This relies on the fact that // writes in libssl are on record boundaries. class SelectiveDropFilter : public PacketFilter { @@ -515,16 +543,16 @@ class SelectiveDropFilter : public PacketFilter { // datagram, we just drop one. class SelectiveRecordDropFilter : public TlsRecordFilter { public: - SelectiveRecordDropFilter(const std::shared_ptr<TlsAgent>& agent, + SelectiveRecordDropFilter(const std::shared_ptr<TlsAgent>& a, uint32_t pattern, bool enabled = true) - : TlsRecordFilter(agent), pattern_(pattern), counter_(0) { + : TlsRecordFilter(a), pattern_(pattern), counter_(0) { if (!enabled) { Disable(); } } - SelectiveRecordDropFilter(const std::shared_ptr<TlsAgent>& agent, + SelectiveRecordDropFilter(const std::shared_ptr<TlsAgent>& a, std::initializer_list<size_t> records) - : SelectiveRecordDropFilter(agent, ToPattern(records), true) {} + : SelectiveRecordDropFilter(a, ToPattern(records), true) {} void Reset(uint32_t pattern) { counter_ = 0; @@ -551,10 +579,9 @@ class SelectiveRecordDropFilter : public TlsRecordFilter { // Set the version number in the ClientHello. class TlsClientHelloVersionSetter : public TlsHandshakeFilter { public: - TlsClientHelloVersionSetter(const std::shared_ptr<TlsAgent>& agent, + TlsClientHelloVersionSetter(const std::shared_ptr<TlsAgent>& a, uint16_t version) - : TlsHandshakeFilter(agent, {kTlsHandshakeClientHello}), - version_(version) {} + : TlsHandshakeFilter(a, {kTlsHandshakeClientHello}), version_(version) {} virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, const DataBuffer& input, @@ -567,8 +594,8 @@ class TlsClientHelloVersionSetter : public TlsHandshakeFilter { // Damages the last byte of a handshake message. class TlsLastByteDamager : public TlsHandshakeFilter { public: - TlsLastByteDamager(const std::shared_ptr<TlsAgent>& agent, uint8_t type) - : TlsHandshakeFilter(agent), type_(type) {} + TlsLastByteDamager(const std::shared_ptr<TlsAgent>& a, uint8_t type) + : TlsHandshakeFilter(a), type_(type) {} PacketFilter::Action FilterHandshake( const TlsHandshakeFilter::HandshakeHeader& header, const DataBuffer& input, DataBuffer* output) override { @@ -588,9 +615,9 @@ class TlsLastByteDamager : public TlsHandshakeFilter { class SelectedCipherSuiteReplacer : public TlsHandshakeFilter { public: - SelectedCipherSuiteReplacer(const std::shared_ptr<TlsAgent>& agent, + SelectedCipherSuiteReplacer(const std::shared_ptr<TlsAgent>& a, uint16_t suite) - : TlsHandshakeFilter(agent, {kTlsHandshakeServerHello}), + : TlsHandshakeFilter(a, {kTlsHandshakeServerHello}), cipher_suite_(suite) {} protected: diff --git a/security/nss/gtests/ssl_gtest/tls_protect.cc b/security/nss/gtests/ssl_gtest/tls_protect.cc index 6c945f66e..c715a36a6 100644 --- a/security/nss/gtests/ssl_gtest/tls_protect.cc +++ b/security/nss/gtests/ssl_gtest/tls_protect.cc @@ -54,17 +54,17 @@ bool AeadCipher::AeadInner(bool decrypt, void *params, size_t param_length, return rv == SECSuccess; } -bool AeadCipherAesGcm::Aead(bool decrypt, uint64_t seq, const uint8_t *in, - size_t inlen, uint8_t *out, size_t *outlen, - size_t maxlen) { +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 = NULL; - aeadParams.ulAADLen = 0; + aeadParams.pAAD = const_cast<uint8_t *>(hdr); + aeadParams.ulAADLen = hdr_len; aeadParams.ulTagBits = 128; FormatNonce(seq, nonce); @@ -72,7 +72,8 @@ bool AeadCipherAesGcm::Aead(bool decrypt, uint64_t seq, const uint8_t *in, in, inlen, out, outlen, maxlen); } -bool AeadCipherChacha20Poly1305::Aead(bool decrypt, uint64_t seq, +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) { @@ -82,8 +83,8 @@ bool AeadCipherChacha20Poly1305::Aead(bool decrypt, uint64_t seq, memset(&aeadParams, 0, sizeof(aeadParams)); aeadParams.pNonce = nonce; aeadParams.ulNonceLen = sizeof(nonce); - aeadParams.pAAD = NULL; - aeadParams.ulAADLen = 0; + aeadParams.pAAD = const_cast<uint8_t *>(hdr); + aeadParams.ulAADLen = hdr_len; aeadParams.ulTagLen = 16; FormatNonce(seq, nonce); @@ -91,9 +92,9 @@ bool AeadCipherChacha20Poly1305::Aead(bool decrypt, uint64_t seq, in, inlen, out, outlen, maxlen); } -bool TlsCipherSpec::Init(uint16_t epoch, SSLCipherAlgorithm cipher, +bool TlsCipherSpec::Init(uint16_t epoc, SSLCipherAlgorithm cipher, PK11SymKey *key, const uint8_t *iv) { - epoch_ = epoch; + epoch_ = epoc; switch (cipher) { case ssl_calg_aes_gcm: aead_.reset(new AeadCipherAesGcm()); @@ -114,10 +115,12 @@ bool TlsCipherSpec::Unprotect(const TlsRecordHeader &header, // Make space. plaintext->Allocate(ciphertext.len()); + auto header_bytes = header.header(); size_t len; bool ret = - aead_->Aead(true, header.sequence_number(), ciphertext.data(), - ciphertext.len(), plaintext->data(), &len, plaintext->len()); + 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; plaintext->Truncate(len); @@ -133,9 +136,13 @@ bool TlsCipherSpec::Protect(const TlsRecordHeader &header, ciphertext->Allocate(plaintext.len() + 32); // Room for any plausible auth tag size_t len; + + DataBuffer header_bytes; + (void)header.WriteHeader(&header_bytes, 0, plaintext.len() + 16); bool ret = - aead_->Aead(false, header.sequence_number(), plaintext.data(), - plaintext.len(), ciphertext->data(), &len, ciphertext->len()); + 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; ciphertext->Truncate(len); diff --git a/security/nss/gtests/ssl_gtest/tls_protect.h b/security/nss/gtests/ssl_gtest/tls_protect.h index 93ffd6322..6f129a4eb 100644 --- a/security/nss/gtests/ssl_gtest/tls_protect.h +++ b/security/nss/gtests/ssl_gtest/tls_protect.h @@ -23,8 +23,9 @@ class AeadCipher { virtual ~AeadCipher(); bool Init(PK11SymKey *key, const uint8_t *iv); - virtual bool Aead(bool decrypt, uint64_t seq, const uint8_t *in, size_t inlen, - uint8_t *out, size_t *outlen, size_t maxlen) = 0; + 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); @@ -42,8 +43,9 @@ class AeadCipherChacha20Poly1305 : public AeadCipher { AeadCipherChacha20Poly1305() : AeadCipher(CKM_NSS_CHACHA20_POLY1305) {} protected: - bool Aead(bool decrypt, uint64_t seq, const uint8_t *in, size_t inlen, - uint8_t *out, size_t *outlen, size_t maxlen); + 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 { @@ -51,8 +53,9 @@ class AeadCipherAesGcm : public AeadCipher { AeadCipherAesGcm() : AeadCipher(CKM_AES_GCM) {} protected: - bool Aead(bool decrypt, uint64_t seq, const uint8_t *in, size_t inlen, - uint8_t *out, size_t *outlen, size_t maxlen); + 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 diff --git a/security/nss/lib/certdb/crl.c b/security/nss/lib/certdb/crl.c index d1c48dfba..63adcad46 100644 --- a/security/nss/lib/certdb/crl.c +++ b/security/nss/lib/certdb/crl.c @@ -898,13 +898,13 @@ static PLHashAllocOps preAllocOps = { PreAllocTable, PreFreeTable, /* destructor for PreAllocator object */ void -PreAllocator_Destroy(PreAllocator* PreAllocator) +PreAllocator_Destroy(PreAllocator* allocator) { - if (!PreAllocator) { + if (!allocator) { return; } - if (PreAllocator->arena) { - PORT_FreeArena(PreAllocator->arena, PR_TRUE); + if (allocator->arena) { + PORT_FreeArena(allocator->arena, PR_TRUE); } } diff --git a/security/nss/lib/ckfw/Makefile b/security/nss/lib/ckfw/Makefile index 484dbb511..2902bef48 100644 --- a/security/nss/lib/ckfw/Makefile +++ b/security/nss/lib/ckfw/Makefile @@ -33,7 +33,3 @@ ifdef NSS_BUILD_CAPI DIRS += capi endif endif - -#ifeq ($(OS_ARCH), Darwin) -#DIRS += nssmkey -#endif diff --git a/security/nss/lib/ckfw/builtins/certdata.txt b/security/nss/lib/ckfw/builtins/certdata.txt index 5d2baf3a5..d291f28a5 100644 --- a/security/nss/lib/ckfw/builtins/certdata.txt +++ b/security/nss/lib/ckfw/builtins/certdata.txt @@ -7241,163 +7241,6 @@ CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE # -# Certificate "TC TrustCenter Class 3 CA II" -# -# Issuer: CN=TC TrustCenter Class 3 CA II,OU=TC TrustCenter Class 3 CA,O=TC TrustCenter GmbH,C=DE -# Serial Number:4a:47:00:01:00:02:e5:a0:5d:d6:3f:00:51:bf -# Subject: CN=TC TrustCenter Class 3 CA II,OU=TC TrustCenter Class 3 CA,O=TC TrustCenter GmbH,C=DE -# Not Valid Before: Thu Jan 12 14:41:57 2006 -# Not Valid After : Wed Dec 31 22:59:59 2025 -# Fingerprint (MD5): 56:5F:AA:80:61:12:17:F6:67:21:E6:2B:6D:61:56:8E -# Fingerprint (SHA1): 80:25:EF:F4:6E:70:C8:D4:72:24:65:84:FE:40:3B:8A:8D:6A:DB:F5 -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 "TC TrustCenter Class 3 CA II" -CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 -CKA_SUBJECT MULTILINE_OCTAL -\060\166\061\013\060\011\006\003\125\004\006\023\002\104\105\061 -\034\060\032\006\003\125\004\012\023\023\124\103\040\124\162\165 -\163\164\103\145\156\164\145\162\040\107\155\142\110\061\042\060 -\040\006\003\125\004\013\023\031\124\103\040\124\162\165\163\164 -\103\145\156\164\145\162\040\103\154\141\163\163\040\063\040\103 -\101\061\045\060\043\006\003\125\004\003\023\034\124\103\040\124 -\162\165\163\164\103\145\156\164\145\162\040\103\154\141\163\163 -\040\063\040\103\101\040\111\111 -END -CKA_ID UTF8 "0" -CKA_ISSUER MULTILINE_OCTAL -\060\166\061\013\060\011\006\003\125\004\006\023\002\104\105\061 -\034\060\032\006\003\125\004\012\023\023\124\103\040\124\162\165 -\163\164\103\145\156\164\145\162\040\107\155\142\110\061\042\060 -\040\006\003\125\004\013\023\031\124\103\040\124\162\165\163\164 -\103\145\156\164\145\162\040\103\154\141\163\163\040\063\040\103 -\101\061\045\060\043\006\003\125\004\003\023\034\124\103\040\124 -\162\165\163\164\103\145\156\164\145\162\040\103\154\141\163\163 -\040\063\040\103\101\040\111\111 -END -CKA_SERIAL_NUMBER MULTILINE_OCTAL -\002\016\112\107\000\001\000\002\345\240\135\326\077\000\121\277 -END -CKA_VALUE MULTILINE_OCTAL -\060\202\004\252\060\202\003\222\240\003\002\001\002\002\016\112 -\107\000\001\000\002\345\240\135\326\077\000\121\277\060\015\006 -\011\052\206\110\206\367\015\001\001\005\005\000\060\166\061\013 -\060\011\006\003\125\004\006\023\002\104\105\061\034\060\032\006 -\003\125\004\012\023\023\124\103\040\124\162\165\163\164\103\145 -\156\164\145\162\040\107\155\142\110\061\042\060\040\006\003\125 -\004\013\023\031\124\103\040\124\162\165\163\164\103\145\156\164 -\145\162\040\103\154\141\163\163\040\063\040\103\101\061\045\060 -\043\006\003\125\004\003\023\034\124\103\040\124\162\165\163\164 -\103\145\156\164\145\162\040\103\154\141\163\163\040\063\040\103 -\101\040\111\111\060\036\027\015\060\066\060\061\061\062\061\064 -\064\061\065\067\132\027\015\062\065\061\062\063\061\062\062\065 -\071\065\071\132\060\166\061\013\060\011\006\003\125\004\006\023 -\002\104\105\061\034\060\032\006\003\125\004\012\023\023\124\103 -\040\124\162\165\163\164\103\145\156\164\145\162\040\107\155\142 -\110\061\042\060\040\006\003\125\004\013\023\031\124\103\040\124 -\162\165\163\164\103\145\156\164\145\162\040\103\154\141\163\163 -\040\063\040\103\101\061\045\060\043\006\003\125\004\003\023\034 -\124\103\040\124\162\165\163\164\103\145\156\164\145\162\040\103 -\154\141\163\163\040\063\040\103\101\040\111\111\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\264\340\273 -\121\273\071\134\213\004\305\114\171\034\043\206\061\020\143\103 -\125\047\077\306\105\307\244\075\354\011\015\032\036\040\302\126 -\036\336\033\067\007\060\042\057\157\361\006\361\253\255\326\310 -\253\141\243\057\103\304\260\262\055\374\303\226\151\173\176\212 -\344\314\300\071\022\220\102\140\311\314\065\150\356\332\137\220 -\126\137\315\034\115\133\130\111\353\016\001\117\144\372\054\074 -\211\130\330\057\056\342\260\150\351\042\073\165\211\326\104\032 -\145\362\033\227\046\035\050\155\254\350\275\131\035\053\044\366 -\326\204\003\146\210\044\000\170\140\361\370\253\376\002\262\153 -\373\042\373\065\346\026\321\255\366\056\022\344\372\065\152\345 -\031\271\135\333\073\036\032\373\323\377\025\024\010\330\011\152 -\272\105\235\024\171\140\175\257\100\212\007\163\263\223\226\323 -\164\064\215\072\067\051\336\134\354\365\356\056\061\302\040\334 -\276\361\117\177\043\122\331\133\342\144\331\234\252\007\010\265 -\105\275\321\320\061\301\253\124\237\251\322\303\142\140\003\361 -\273\071\112\222\112\075\012\271\235\305\240\376\067\002\003\001 -\000\001\243\202\001\064\060\202\001\060\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\035\006\003\125 -\035\016\004\026\004\024\324\242\374\237\263\303\330\003\323\127 -\134\007\244\320\044\247\300\362\000\324\060\201\355\006\003\125 -\035\037\004\201\345\060\201\342\060\201\337\240\201\334\240\201 -\331\206\065\150\164\164\160\072\057\057\167\167\167\056\164\162 -\165\163\164\143\145\156\164\145\162\056\144\145\057\143\162\154 -\057\166\062\057\164\143\137\143\154\141\163\163\137\063\137\143 -\141\137\111\111\056\143\162\154\206\201\237\154\144\141\160\072 -\057\057\167\167\167\056\164\162\165\163\164\143\145\156\164\145 -\162\056\144\145\057\103\116\075\124\103\045\062\060\124\162\165 -\163\164\103\145\156\164\145\162\045\062\060\103\154\141\163\163 -\045\062\060\063\045\062\060\103\101\045\062\060\111\111\054\117 -\075\124\103\045\062\060\124\162\165\163\164\103\145\156\164\145 -\162\045\062\060\107\155\142\110\054\117\125\075\162\157\157\164 -\143\145\162\164\163\054\104\103\075\164\162\165\163\164\143\145 -\156\164\145\162\054\104\103\075\144\145\077\143\145\162\164\151 -\146\151\143\141\164\145\122\145\166\157\143\141\164\151\157\156 -\114\151\163\164\077\142\141\163\145\077\060\015\006\011\052\206 -\110\206\367\015\001\001\005\005\000\003\202\001\001\000\066\140 -\344\160\367\006\040\103\331\043\032\102\362\370\243\262\271\115 -\212\264\363\302\232\125\061\174\304\073\147\232\264\337\115\016 -\212\223\112\027\213\033\215\312\211\341\317\072\036\254\035\361 -\234\062\264\216\131\166\242\101\205\045\067\240\023\320\365\174 -\116\325\352\226\342\156\162\301\273\052\376\154\156\370\221\230 -\106\374\311\033\127\133\352\310\032\073\077\260\121\230\074\007 -\332\054\131\001\332\213\104\350\341\164\375\247\150\335\124\272 -\203\106\354\310\106\265\370\257\227\300\073\011\034\217\316\162 -\226\075\063\126\160\274\226\313\330\325\175\040\232\203\237\032 -\334\071\361\305\162\243\021\003\375\073\102\122\051\333\350\001 -\367\233\136\214\326\215\206\116\031\372\274\034\276\305\041\245 -\207\236\170\056\066\333\011\161\243\162\064\370\154\343\006\011 -\362\136\126\245\323\335\230\372\324\346\006\364\360\266\040\143 -\113\352\051\275\252\202\146\036\373\201\252\247\067\255\023\030 -\346\222\303\201\301\063\273\210\036\241\347\342\264\275\061\154 -\016\121\075\157\373\226\126\200\342\066\027\321\334\344 -END -CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE - -# Trust for Certificate "TC TrustCenter Class 3 CA II" -# Issuer: CN=TC TrustCenter Class 3 CA II,OU=TC TrustCenter Class 3 CA,O=TC TrustCenter GmbH,C=DE -# Serial Number:4a:47:00:01:00:02:e5:a0:5d:d6:3f:00:51:bf -# Subject: CN=TC TrustCenter Class 3 CA II,OU=TC TrustCenter Class 3 CA,O=TC TrustCenter GmbH,C=DE -# Not Valid Before: Thu Jan 12 14:41:57 2006 -# Not Valid After : Wed Dec 31 22:59:59 2025 -# Fingerprint (MD5): 56:5F:AA:80:61:12:17:F6:67:21:E6:2B:6D:61:56:8E -# Fingerprint (SHA1): 80:25:EF:F4:6E:70:C8:D4:72:24:65:84:FE:40:3B:8A:8D:6A:DB:F5 -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 "TC TrustCenter Class 3 CA II" -CKA_CERT_SHA1_HASH MULTILINE_OCTAL -\200\045\357\364\156\160\310\324\162\044\145\204\376\100\073\212 -\215\152\333\365 -END -CKA_CERT_MD5_HASH MULTILINE_OCTAL -\126\137\252\200\141\022\027\366\147\041\346\053\155\141\126\216 -END -CKA_ISSUER MULTILINE_OCTAL -\060\166\061\013\060\011\006\003\125\004\006\023\002\104\105\061 -\034\060\032\006\003\125\004\012\023\023\124\103\040\124\162\165 -\163\164\103\145\156\164\145\162\040\107\155\142\110\061\042\060 -\040\006\003\125\004\013\023\031\124\103\040\124\162\165\163\164 -\103\145\156\164\145\162\040\103\154\141\163\163\040\063\040\103 -\101\061\045\060\043\006\003\125\004\003\023\034\124\103\040\124 -\162\165\163\164\103\145\156\164\145\162\040\103\154\141\163\163 -\040\063\040\103\101\040\111\111 -END -CKA_SERIAL_NUMBER MULTILINE_OCTAL -\002\016\112\107\000\001\000\002\345\240\135\326\077\000\121\277 -END -CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -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 "Deutsche Telekom Root CA 2" # # Issuer: CN=Deutsche Telekom Root CA 2,OU=T-TeleSec Trust Center,O=Deutsche Telekom AG,C=DE @@ -17883,155 +17726,6 @@ CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE # -# Certificate "S-TRUST Universal Root CA" -# -# Issuer: CN=S-TRUST Universal Root CA,OU=S-TRUST Certification Services,O=Deutscher Sparkassen Verlag GmbH,C=DE -# Serial Number:60:56:c5:4b:23:40:5b:64:d4:ed:25:da:d9:d6:1e:1e -# Subject: CN=S-TRUST Universal Root CA,OU=S-TRUST Certification Services,O=Deutscher Sparkassen Verlag GmbH,C=DE -# Not Valid Before: Tue Oct 22 00:00:00 2013 -# Not Valid After : Thu Oct 21 23:59:59 2038 -# Fingerprint (SHA-256): D8:0F:EF:91:0A:E3:F1:04:72:3B:04:5C:EC:2D:01:9F:44:1C:E6:21:3A:DF:15:67:91:E7:0C:17:90:11:0A:31 -# Fingerprint (SHA1): 1B:3D:11:14:EA:7A:0F:95:58:54:41:95:BF:6B:25:82:AB:40:CE:9A -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 "S-TRUST Universal Root CA" -CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 -CKA_SUBJECT MULTILINE_OCTAL -\060\201\205\061\013\060\011\006\003\125\004\006\023\002\104\105 -\061\051\060\047\006\003\125\004\012\023\040\104\145\165\164\163 -\143\150\145\162\040\123\160\141\162\153\141\163\163\145\156\040 -\126\145\162\154\141\147\040\107\155\142\110\061\047\060\045\006 -\003\125\004\013\023\036\123\055\124\122\125\123\124\040\103\145 -\162\164\151\146\151\143\141\164\151\157\156\040\123\145\162\166 -\151\143\145\163\061\042\060\040\006\003\125\004\003\023\031\123 -\055\124\122\125\123\124\040\125\156\151\166\145\162\163\141\154 -\040\122\157\157\164\040\103\101 -END -CKA_ID UTF8 "0" -CKA_ISSUER MULTILINE_OCTAL -\060\201\205\061\013\060\011\006\003\125\004\006\023\002\104\105 -\061\051\060\047\006\003\125\004\012\023\040\104\145\165\164\163 -\143\150\145\162\040\123\160\141\162\153\141\163\163\145\156\040 -\126\145\162\154\141\147\040\107\155\142\110\061\047\060\045\006 -\003\125\004\013\023\036\123\055\124\122\125\123\124\040\103\145 -\162\164\151\146\151\143\141\164\151\157\156\040\123\145\162\166 -\151\143\145\163\061\042\060\040\006\003\125\004\003\023\031\123 -\055\124\122\125\123\124\040\125\156\151\166\145\162\163\141\154 -\040\122\157\157\164\040\103\101 -END -CKA_SERIAL_NUMBER MULTILINE_OCTAL -\002\020\140\126\305\113\043\100\133\144\324\355\045\332\331\326 -\036\036 -END -CKA_VALUE MULTILINE_OCTAL -\060\202\003\330\060\202\002\300\240\003\002\001\002\002\020\140 -\126\305\113\043\100\133\144\324\355\045\332\331\326\036\036\060 -\015\006\011\052\206\110\206\367\015\001\001\013\005\000\060\201 -\205\061\013\060\011\006\003\125\004\006\023\002\104\105\061\051 -\060\047\006\003\125\004\012\023\040\104\145\165\164\163\143\150 -\145\162\040\123\160\141\162\153\141\163\163\145\156\040\126\145 -\162\154\141\147\040\107\155\142\110\061\047\060\045\006\003\125 -\004\013\023\036\123\055\124\122\125\123\124\040\103\145\162\164 -\151\146\151\143\141\164\151\157\156\040\123\145\162\166\151\143 -\145\163\061\042\060\040\006\003\125\004\003\023\031\123\055\124 -\122\125\123\124\040\125\156\151\166\145\162\163\141\154\040\122 -\157\157\164\040\103\101\060\036\027\015\061\063\061\060\062\062 -\060\060\060\060\060\060\132\027\015\063\070\061\060\062\061\062 -\063\065\071\065\071\132\060\201\205\061\013\060\011\006\003\125 -\004\006\023\002\104\105\061\051\060\047\006\003\125\004\012\023 -\040\104\145\165\164\163\143\150\145\162\040\123\160\141\162\153 -\141\163\163\145\156\040\126\145\162\154\141\147\040\107\155\142 -\110\061\047\060\045\006\003\125\004\013\023\036\123\055\124\122 -\125\123\124\040\103\145\162\164\151\146\151\143\141\164\151\157 -\156\040\123\145\162\166\151\143\145\163\061\042\060\040\006\003 -\125\004\003\023\031\123\055\124\122\125\123\124\040\125\156\151 -\166\145\162\163\141\154\040\122\157\157\164\040\103\101\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\250 -\343\013\337\021\067\205\202\232\265\154\146\174\141\077\300\107 -\032\035\106\343\260\125\144\345\270\202\071\050\007\176\027\377 -\364\233\212\360\221\201\352\070\077\041\170\154\110\354\153\057 -\242\323\212\162\262\247\327\331\352\177\264\300\111\153\060\045 -\211\214\353\267\325\100\141\230\342\334\074\040\222\315\145\112 -\162\237\032\216\214\372\045\025\277\363\041\203\050\015\213\257 -\131\021\202\103\134\233\115\045\121\177\130\030\143\140\073\263 -\265\212\213\130\143\067\110\110\220\104\302\100\335\135\367\103 -\151\051\230\134\022\145\136\253\220\222\113\146\337\325\165\022 -\123\124\030\246\336\212\326\273\127\003\071\131\231\030\005\014 -\371\375\025\306\220\144\106\027\202\327\302\112\101\075\375\000 -\276\127\162\030\224\167\033\123\132\211\001\366\063\162\016\223 -\072\334\350\036\375\005\005\326\274\163\340\210\334\253\117\354 -\265\030\206\117\171\204\016\110\052\146\052\335\062\310\170\145 -\310\013\235\130\001\005\161\355\201\365\150\027\156\313\015\264 -\113\330\241\354\256\070\353\034\130\057\241\145\003\064\057\002 -\003\001\000\001\243\102\060\100\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\035\006\003\125\035\016 -\004\026\004\024\232\175\327\353\353\177\124\230\105\051\264\040 -\253\155\013\226\043\031\244\302\060\015\006\011\052\206\110\206 -\367\015\001\001\013\005\000\003\202\001\001\000\116\226\022\333 -\176\167\136\222\047\236\041\027\030\202\166\330\077\274\245\011 -\004\146\210\211\255\333\125\263\063\152\306\145\304\217\115\363 -\062\066\334\171\004\226\251\167\062\321\227\365\030\153\214\272 -\355\316\021\320\104\307\222\361\264\104\216\355\210\122\110\236 -\325\375\131\370\243\036\121\373\001\122\345\137\345\172\335\252 -\044\117\042\213\335\166\106\366\245\240\017\065\330\312\017\230 -\271\060\135\040\157\302\201\036\275\275\300\376\025\323\070\052 -\011\223\230\047\033\223\173\320\053\064\136\150\245\025\117\321 -\122\303\240\312\240\203\105\035\365\365\267\131\163\135\131\001 -\217\252\302\107\057\024\161\325\051\343\020\265\107\223\045\314 -\043\051\332\267\162\330\221\324\354\033\110\212\042\344\301\052 -\367\072\150\223\237\105\031\156\103\267\314\376\270\221\232\141 -\032\066\151\143\144\222\050\363\157\141\222\205\023\237\311\007 -\054\213\127\334\353\236\171\325\302\336\010\325\124\262\127\116 -\052\062\215\241\342\072\321\020\040\042\071\175\064\105\157\161 -\073\303\035\374\377\262\117\250\342\366\060\036 -END -CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE - -# Trust for "S-TRUST Universal Root CA" -# Issuer: CN=S-TRUST Universal Root CA,OU=S-TRUST Certification Services,O=Deutscher Sparkassen Verlag GmbH,C=DE -# Serial Number:60:56:c5:4b:23:40:5b:64:d4:ed:25:da:d9:d6:1e:1e -# Subject: CN=S-TRUST Universal Root CA,OU=S-TRUST Certification Services,O=Deutscher Sparkassen Verlag GmbH,C=DE -# Not Valid Before: Tue Oct 22 00:00:00 2013 -# Not Valid After : Thu Oct 21 23:59:59 2038 -# Fingerprint (SHA-256): D8:0F:EF:91:0A:E3:F1:04:72:3B:04:5C:EC:2D:01:9F:44:1C:E6:21:3A:DF:15:67:91:E7:0C:17:90:11:0A:31 -# Fingerprint (SHA1): 1B:3D:11:14:EA:7A:0F:95:58:54:41:95:BF:6B:25:82:AB:40:CE:9A -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 "S-TRUST Universal Root CA" -CKA_CERT_SHA1_HASH MULTILINE_OCTAL -\033\075\021\024\352\172\017\225\130\124\101\225\277\153\045\202 -\253\100\316\232 -END -CKA_CERT_MD5_HASH MULTILINE_OCTAL -\130\366\101\001\256\365\133\121\231\116\134\041\350\117\324\146 -END -CKA_ISSUER MULTILINE_OCTAL -\060\201\205\061\013\060\011\006\003\125\004\006\023\002\104\105 -\061\051\060\047\006\003\125\004\012\023\040\104\145\165\164\163 -\143\150\145\162\040\123\160\141\162\153\141\163\163\145\156\040 -\126\145\162\154\141\147\040\107\155\142\110\061\047\060\045\006 -\003\125\004\013\023\036\123\055\124\122\125\123\124\040\103\145 -\162\164\151\146\151\143\141\164\151\157\156\040\123\145\162\166 -\151\143\145\163\061\042\060\040\006\003\125\004\003\023\031\123 -\055\124\122\125\123\124\040\125\156\151\166\145\162\163\141\154 -\040\122\157\157\164\040\103\101 -END -CKA_SERIAL_NUMBER MULTILINE_OCTAL -\002\020\140\126\305\113\043\100\133\144\324\355\045\332\331\326 -\036\036 -END -CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -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 "Entrust Root Certification Authority - G2" # # Issuer: CN=Entrust Root Certification Authority - G2,OU="(c) 2009 Entrust, Inc. - for authorized use only",OU=See www.entrust.net/legal-terms,O="Entrust, Inc.",C=US @@ -18509,167 +18203,6 @@ CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE # -# Certificate "TÃœRKTRUST Elektronik Sertifika Hizmet SaÄŸlayıcısı H5" -# -# Issuer: CN=T..RKTRUST Elektronik Sertifika Hizmet Sa..lay..c..s.. H5,O=T..RKTRUST Bilgi ..leti..im ve Bili..im G..venli..i Hizmetleri A....,L=Ankara,C=TR -# Serial Number:00:8e:17:fe:24:20:81 -# Subject: CN=T..RKTRUST Elektronik Sertifika Hizmet Sa..lay..c..s.. H5,O=T..RKTRUST Bilgi ..leti..im ve Bili..im G..venli..i Hizmetleri A....,L=Ankara,C=TR -# Not Valid Before: Tue Apr 30 08:07:01 2013 -# Not Valid After : Fri Apr 28 08:07:01 2023 -# Fingerprint (SHA-256): 49:35:1B:90:34:44:C1:85:CC:DC:5C:69:3D:24:D8:55:5C:B2:08:D6:A8:14:13:07:69:9F:4A:F0:63:19:9D:78 -# Fingerprint (SHA1): C4:18:F6:4D:46:D1:DF:00:3D:27:30:13:72:43:A9:12:11:C6:75:FB -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 "TÃœRKTRUST Elektronik Sertifika Hizmet SaÄŸlayıcısı H5" -CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 -CKA_SUBJECT MULTILINE_OCTAL -\060\201\261\061\013\060\011\006\003\125\004\006\023\002\124\122 -\061\017\060\015\006\003\125\004\007\014\006\101\156\153\141\162 -\141\061\115\060\113\006\003\125\004\012\014\104\124\303\234\122 -\113\124\122\125\123\124\040\102\151\154\147\151\040\304\260\154 -\145\164\151\305\237\151\155\040\166\145\040\102\151\154\151\305 -\237\151\155\040\107\303\274\166\145\156\154\151\304\237\151\040 -\110\151\172\155\145\164\154\145\162\151\040\101\056\305\236\056 -\061\102\060\100\006\003\125\004\003\014\071\124\303\234\122\113 -\124\122\125\123\124\040\105\154\145\153\164\162\157\156\151\153 -\040\123\145\162\164\151\146\151\153\141\040\110\151\172\155\145 -\164\040\123\141\304\237\154\141\171\304\261\143\304\261\163\304 -\261\040\110\065 -END -CKA_ID UTF8 "0" -CKA_ISSUER MULTILINE_OCTAL -\060\201\261\061\013\060\011\006\003\125\004\006\023\002\124\122 -\061\017\060\015\006\003\125\004\007\014\006\101\156\153\141\162 -\141\061\115\060\113\006\003\125\004\012\014\104\124\303\234\122 -\113\124\122\125\123\124\040\102\151\154\147\151\040\304\260\154 -\145\164\151\305\237\151\155\040\166\145\040\102\151\154\151\305 -\237\151\155\040\107\303\274\166\145\156\154\151\304\237\151\040 -\110\151\172\155\145\164\154\145\162\151\040\101\056\305\236\056 -\061\102\060\100\006\003\125\004\003\014\071\124\303\234\122\113 -\124\122\125\123\124\040\105\154\145\153\164\162\157\156\151\153 -\040\123\145\162\164\151\146\151\153\141\040\110\151\172\155\145 -\164\040\123\141\304\237\154\141\171\304\261\143\304\261\163\304 -\261\040\110\065 -END -CKA_SERIAL_NUMBER MULTILINE_OCTAL -\002\007\000\216\027\376\044\040\201 -END -CKA_VALUE MULTILINE_OCTAL -\060\202\004\047\060\202\003\017\240\003\002\001\002\002\007\000 -\216\027\376\044\040\201\060\015\006\011\052\206\110\206\367\015 -\001\001\013\005\000\060\201\261\061\013\060\011\006\003\125\004 -\006\023\002\124\122\061\017\060\015\006\003\125\004\007\014\006 -\101\156\153\141\162\141\061\115\060\113\006\003\125\004\012\014 -\104\124\303\234\122\113\124\122\125\123\124\040\102\151\154\147 -\151\040\304\260\154\145\164\151\305\237\151\155\040\166\145\040 -\102\151\154\151\305\237\151\155\040\107\303\274\166\145\156\154 -\151\304\237\151\040\110\151\172\155\145\164\154\145\162\151\040 -\101\056\305\236\056\061\102\060\100\006\003\125\004\003\014\071 -\124\303\234\122\113\124\122\125\123\124\040\105\154\145\153\164 -\162\157\156\151\153\040\123\145\162\164\151\146\151\153\141\040 -\110\151\172\155\145\164\040\123\141\304\237\154\141\171\304\261 -\143\304\261\163\304\261\040\110\065\060\036\027\015\061\063\060 -\064\063\060\060\070\060\067\060\061\132\027\015\062\063\060\064 -\062\070\060\070\060\067\060\061\132\060\201\261\061\013\060\011 -\006\003\125\004\006\023\002\124\122\061\017\060\015\006\003\125 -\004\007\014\006\101\156\153\141\162\141\061\115\060\113\006\003 -\125\004\012\014\104\124\303\234\122\113\124\122\125\123\124\040 -\102\151\154\147\151\040\304\260\154\145\164\151\305\237\151\155 -\040\166\145\040\102\151\154\151\305\237\151\155\040\107\303\274 -\166\145\156\154\151\304\237\151\040\110\151\172\155\145\164\154 -\145\162\151\040\101\056\305\236\056\061\102\060\100\006\003\125 -\004\003\014\071\124\303\234\122\113\124\122\125\123\124\040\105 -\154\145\153\164\162\157\156\151\153\040\123\145\162\164\151\146 -\151\153\141\040\110\151\172\155\145\164\040\123\141\304\237\154 -\141\171\304\261\143\304\261\163\304\261\040\110\065\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\244\045 -\031\341\145\236\353\110\041\120\112\010\345\021\360\132\272\046 -\377\203\131\316\104\052\057\376\341\316\140\003\374\215\003\245 -\355\377\153\250\272\314\064\006\237\131\065\366\354\054\273\235 -\373\215\122\151\343\234\047\020\123\363\244\002\305\247\371\021 -\032\151\165\156\303\035\213\321\230\215\223\207\247\161\227\015 -\041\307\231\371\122\323\054\143\135\125\274\350\037\001\110\271 -\140\376\102\112\366\310\200\256\315\146\172\236\105\212\150\167 -\342\110\150\237\242\332\361\341\301\020\237\353\074\051\201\247 -\341\062\010\324\240\005\261\214\373\215\226\000\016\076\045\337 -\123\206\042\073\374\364\275\363\011\176\167\354\206\353\017\063 -\345\103\117\364\124\165\155\051\231\056\146\132\103\337\313\134 -\312\310\345\070\361\176\073\065\235\017\364\305\132\241\314\363 -\040\200\044\323\127\354\025\272\165\045\233\350\144\113\263\064 -\204\357\004\270\366\311\154\252\002\076\266\125\342\062\067\137 -\374\146\227\137\315\326\236\307\040\277\115\306\254\077\165\137 -\034\355\062\234\174\151\000\151\221\343\043\030\123\351\002\003 -\001\000\001\243\102\060\100\060\035\006\003\125\035\016\004\026 -\004\024\126\231\007\036\323\254\014\151\144\264\014\120\107\336 -\103\054\276\040\300\373\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\236\105\166\173\027 -\110\062\362\070\213\051\275\356\226\112\116\201\030\261\121\107 -\040\315\320\144\261\016\311\331\001\331\011\316\310\231\334\150 -\045\023\324\134\362\243\350\004\376\162\011\307\013\252\035\045 -\125\176\226\232\127\267\272\305\021\172\031\346\247\176\075\205 -\016\365\371\056\051\057\347\371\154\130\026\127\120\045\366\076 -\056\076\252\355\167\161\252\252\231\226\106\012\256\216\354\052 -\121\026\260\136\315\352\147\004\034\130\060\365\140\212\275\246 -\275\115\345\226\264\374\102\211\001\153\366\160\310\120\071\014 -\055\325\146\331\310\322\263\062\267\033\031\155\313\063\371\337 -\245\346\025\204\067\360\302\362\145\226\222\220\167\360\255\364 -\220\351\021\170\327\223\211\300\075\013\272\051\364\350\231\235 -\162\216\355\235\057\356\222\175\241\361\377\135\272\063\140\205 -\142\376\007\002\241\204\126\106\276\226\012\232\023\327\041\114 -\267\174\007\237\116\116\077\221\164\373\047\235\021\314\335\346 -\261\312\161\115\023\027\071\046\305\051\041\053\223\051\152\226 -\372\253\101\341\113\266\065\013\300\233\025 -END -CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE - -# Trust for "TÃœRKTRUST Elektronik Sertifika Hizmet SaÄŸlayıcısı H5" -# Issuer: CN=T..RKTRUST Elektronik Sertifika Hizmet Sa..lay..c..s.. H5,O=T..RKTRUST Bilgi ..leti..im ve Bili..im G..venli..i Hizmetleri A....,L=Ankara,C=TR -# Serial Number:00:8e:17:fe:24:20:81 -# Subject: CN=T..RKTRUST Elektronik Sertifika Hizmet Sa..lay..c..s.. H5,O=T..RKTRUST Bilgi ..leti..im ve Bili..im G..venli..i Hizmetleri A....,L=Ankara,C=TR -# Not Valid Before: Tue Apr 30 08:07:01 2013 -# Not Valid After : Fri Apr 28 08:07:01 2023 -# Fingerprint (SHA-256): 49:35:1B:90:34:44:C1:85:CC:DC:5C:69:3D:24:D8:55:5C:B2:08:D6:A8:14:13:07:69:9F:4A:F0:63:19:9D:78 -# Fingerprint (SHA1): C4:18:F6:4D:46:D1:DF:00:3D:27:30:13:72:43:A9:12:11:C6:75:FB -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 "TÃœRKTRUST Elektronik Sertifika Hizmet SaÄŸlayıcısı H5" -CKA_CERT_SHA1_HASH MULTILINE_OCTAL -\304\030\366\115\106\321\337\000\075\047\060\023\162\103\251\022 -\021\306\165\373 -END -CKA_CERT_MD5_HASH MULTILINE_OCTAL -\332\160\216\360\042\337\223\046\366\137\237\323\025\006\122\116 -END -CKA_ISSUER MULTILINE_OCTAL -\060\201\261\061\013\060\011\006\003\125\004\006\023\002\124\122 -\061\017\060\015\006\003\125\004\007\014\006\101\156\153\141\162 -\141\061\115\060\113\006\003\125\004\012\014\104\124\303\234\122 -\113\124\122\125\123\124\040\102\151\154\147\151\040\304\260\154 -\145\164\151\305\237\151\155\040\166\145\040\102\151\154\151\305 -\237\151\155\040\107\303\274\166\145\156\154\151\304\237\151\040 -\110\151\172\155\145\164\154\145\162\151\040\101\056\305\236\056 -\061\102\060\100\006\003\125\004\003\014\071\124\303\234\122\113 -\124\122\125\123\124\040\105\154\145\153\164\162\157\156\151\153 -\040\123\145\162\164\151\146\151\153\141\040\110\151\172\155\145 -\164\040\123\141\304\237\154\141\171\304\261\143\304\261\163\304 -\261\040\110\065 -END -CKA_SERIAL_NUMBER MULTILINE_OCTAL -\002\007\000\216\027\376\044\040\201 -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 - -# # Certificate "Certinomis - Root CA" # # Issuer: CN=Certinomis - Root CA,OU=0002 433998903,O=Certinomis,C=FR diff --git a/security/nss/lib/ckfw/builtins/nssckbi.h b/security/nss/lib/ckfw/builtins/nssckbi.h index 0189369b1..d40c8080e 100644 --- a/security/nss/lib/ckfw/builtins/nssckbi.h +++ b/security/nss/lib/ckfw/builtins/nssckbi.h @@ -32,7 +32,7 @@ * - whenever possible, if older branches require a modification to the * list, these changes should be made on the main line of development (trunk), * and the older branches should update to the most recent list. - * + * * - ODD minor version numbers are reserved to indicate a snapshot that has * deviated from the main line of development, e.g. if it was necessary * to modify the list on a stable branch. @@ -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 22 -#define NSS_BUILTINS_LIBRARY_VERSION "2.22" +#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 24 +#define NSS_BUILTINS_LIBRARY_VERSION "2.24" /* These version numbers detail the semantic changes to the ckfw engine. */ #define NSS_BUILTINS_HARDWARE_VERSION_MAJOR 1 diff --git a/security/nss/lib/ckfw/nssmkey/Makefile b/security/nss/lib/ckfw/nssmkey/Makefile deleted file mode 100644 index e630e84b0..000000000 --- a/security/nss/lib/ckfw/nssmkey/Makefile +++ /dev/null @@ -1,72 +0,0 @@ -# -# 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 manifest.mn -include $(CORE_DEPTH)/coreconf/config.mk -include config.mk - -EXTRA_LIBS = \ - $(DIST)/lib/$(LIB_PREFIX)nssckfw.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)secutil.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)nssb.$(LIB_SUFFIX) \ - $(NULL) - -# can't do this in manifest.mn because OS_TARGET isn't defined there. -ifeq (,$(filter-out WIN%,$(OS_TARGET))) - -ifdef NS_USE_GCC -EXTRA_LIBS += \ - -L$(NSPR_LIB_DIR) \ - -lplc4 \ - -lplds4 \ - -lnspr4 \ - $(NULL) -else -EXTRA_SHARED_LIBS += \ - $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \ - $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \ - $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \ - $(NULL) -endif # NS_USE_GCC -else - -EXTRA_LIBS += \ - -L$(NSPR_LIB_DIR) \ - -lplc4 \ - -lplds4 \ - -lnspr4 \ - -framework Security \ - -framework CoreServices \ - $(NULL) -endif - - -include $(CORE_DEPTH)/coreconf/rules.mk - -# Generate certdata.c. -generate: - perl certdata.perl < certdata.txt - -# This'll need some help from a build person. - - -ifeq ($(OS_TARGET)$(OS_RELEASE), AIX4.1) -DSO_LDOPTS = -bM:SRE -bh:4 -bnoentry -EXTRA_DSO_LDOPTS = -lc -MKSHLIB = xlC $(DSO_LDOPTS) - -$(SHARED_LIBRARY): $(OBJS) - @$(MAKE_OBJDIR) - rm -f $@ - $(MKSHLIB) -o $@ $(OBJS) $(EXTRA_LIBS) $(EXTRA_DSO_LDOPTS) - chmod +x $@ - -endif - -ifeq ($(OS_TARGET)$(OS_RELEASE), AIX4.2) -LD += -G -endif - - diff --git a/security/nss/lib/ckfw/nssmkey/README b/security/nss/lib/ckfw/nssmkey/README deleted file mode 100644 index c060d9c3c..000000000 --- a/security/nss/lib/ckfw/nssmkey/README +++ /dev/null @@ -1,21 +0,0 @@ -This Cryptoki module provides acces to certs and keys stored in -Macintosh key Ring. - -- It does not yet export PKCS #12 keys. To get this to work should be - implemented using exporting the key object in PKCS #8 wrapped format. - PSM work needs to happen before this can be completed. -- It does not import or export CA Root trust from the mac keychain. -- It does not handle S/MIME objects (pkcs #7 in mac keychain terms?). -- The AuthRoots don't show up on the default list. -- Only RSA keys are supported currently. - -There are a number of things that have not been tested that other PKCS #11 -apps may need: -- reading Modulus and Public Exponents from private keys and public keys. -- storing public keys. -- setting attributes other than CKA_ID and CKA_LABEL. - -Other TODOs: -- Check for and plug memory leaks. -- Need to map mac errors into something more intellegible than - CKR_GENERAL_ERROR. diff --git a/security/nss/lib/ckfw/nssmkey/ckmk.h b/security/nss/lib/ckfw/nssmkey/ckmk.h deleted file mode 100644 index 4f3ab82d7..000000000 --- a/security/nss/lib/ckfw/nssmkey/ckmk.h +++ /dev/null @@ -1,182 +0,0 @@ -/* 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 CKMK_H -#define CKMK_H 1 - -#include <Security/SecKeychainSearch.h> -#include <Security/SecKeychainItem.h> -#include <Security/SecKeychain.h> -#include <Security/cssmtype.h> -#include <Security/cssmapi.h> -#include <Security/SecKey.h> -#include <Security/SecCertificate.h> - -#define NTO - -#include "nssckmdt.h" -#include "nssckfw.h" -/* - * I'm including this for access to the arena functions. - * Looks like we should publish that API. - */ -#ifndef BASE_H -#include "base.h" -#endif /* BASE_H */ -/* - * This is where the Netscape extensions live, at least for now. - */ -#ifndef CKT_H -#include "ckt.h" -#endif /* CKT_H */ - -/* - * statically defined raw objects. Allows us to data description objects - * to this PKCS #11 module. - */ -struct ckmkRawObjectStr { - CK_ULONG n; - const CK_ATTRIBUTE_TYPE *types; - const NSSItem *items; -}; -typedef struct ckmkRawObjectStr ckmkRawObject; - -/* - * Key/Cert Items - */ -struct ckmkItemObjectStr { - SecKeychainItemRef itemRef; - SecItemClass itemClass; - PRBool hasID; - NSSItem modify; - NSSItem private; - NSSItem encrypt; - NSSItem decrypt; - NSSItem derive; - NSSItem sign; - NSSItem signRecover; - NSSItem verify; - NSSItem verifyRecover; - NSSItem wrap; - NSSItem unwrap; - NSSItem label; - NSSItem subject; - NSSItem issuer; - NSSItem serial; - NSSItem derCert; - NSSItem id; - NSSItem modulus; - NSSItem exponent; - NSSItem privateExponent; - NSSItem prime1; - NSSItem prime2; - NSSItem exponent1; - NSSItem exponent2; - NSSItem coefficient; -}; -typedef struct ckmkItemObjectStr ckmkItemObject; - -typedef enum { - ckmkRaw, - ckmkItem, -} ckmkObjectType; - -/* - * all the various types of objects are abstracted away in cobject and - * cfind as ckmkInternalObjects. - */ -struct ckmkInternalObjectStr { - ckmkObjectType type; - union { - ckmkRawObject raw; - ckmkItemObject item; - } u; - CK_OBJECT_CLASS objClass; - NSSItem hashKey; - unsigned char hashKeyData[128]; - NSSCKMDObject mdObject; -}; -typedef struct ckmkInternalObjectStr ckmkInternalObject; - -/* our raw object data array */ -NSS_EXTERN_DATA ckmkInternalObject nss_ckmk_data[]; -NSS_EXTERN_DATA const PRUint32 nss_ckmk_nObjects; - -NSS_EXTERN_DATA const CK_VERSION nss_ckmk_CryptokiVersion; -NSS_EXTERN_DATA const NSSUTF8 *nss_ckmk_ManufacturerID; -NSS_EXTERN_DATA const NSSUTF8 *nss_ckmk_LibraryDescription; -NSS_EXTERN_DATA const CK_VERSION nss_ckmk_LibraryVersion; -NSS_EXTERN_DATA const NSSUTF8 *nss_ckmk_SlotDescription; -NSS_EXTERN_DATA const CK_VERSION nss_ckmk_HardwareVersion; -NSS_EXTERN_DATA const CK_VERSION nss_ckmk_FirmwareVersion; -NSS_EXTERN_DATA const NSSUTF8 *nss_ckmk_TokenLabel; -NSS_EXTERN_DATA const NSSUTF8 *nss_ckmk_TokenModel; -NSS_EXTERN_DATA const NSSUTF8 *nss_ckmk_TokenSerialNumber; - -NSS_EXTERN_DATA const NSSCKMDInstance nss_ckmk_mdInstance; -NSS_EXTERN_DATA const NSSCKMDSlot nss_ckmk_mdSlot; -NSS_EXTERN_DATA const NSSCKMDToken nss_ckmk_mdToken; -NSS_EXTERN_DATA const NSSCKMDMechanism nss_ckmk_mdMechanismRSA; - -NSS_EXTERN NSSCKMDSession * -nss_ckmk_CreateSession( - NSSCKFWSession *fwSession, - CK_RV *pError); - -NSS_EXTERN NSSCKMDFindObjects * -nss_ckmk_FindObjectsInit( - NSSCKFWSession *fwSession, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulAttributeCount, - CK_RV *pError); - -/* - * Object Utilities - */ -NSS_EXTERN NSSCKMDObject * -nss_ckmk_CreateMDObject( - NSSArena *arena, - ckmkInternalObject *io, - CK_RV *pError); - -NSS_EXTERN NSSCKMDObject * -nss_ckmk_CreateObject( - NSSCKFWSession *fwSession, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulAttributeCount, - CK_RV *pError); - -NSS_EXTERN const NSSItem * -nss_ckmk_FetchAttribute( - ckmkInternalObject *io, - CK_ATTRIBUTE_TYPE type, - CK_RV *pError); - -NSS_EXTERN void -nss_ckmk_DestroyInternalObject( - ckmkInternalObject *io); - -unsigned char * -nss_ckmk_DERUnwrap( - unsigned char *src, - int size, - int *outSize, - unsigned char **next); - -CK_ULONG -nss_ckmk_GetULongAttribute( - CK_ATTRIBUTE_TYPE type, - CK_ATTRIBUTE *template, - CK_ULONG templateSize, - CK_RV *pError); - -#define NSS_CKMK_ARRAY_SIZE(x) ((sizeof(x)) / (sizeof((x)[0]))) - -#ifdef DEBUG -#define CKMK_MACERR(str, err) cssmPerror(str, err) -#else -#define CKMK_MACERR(str, err) -#endif - -#endif diff --git a/security/nss/lib/ckfw/nssmkey/ckmkver.c b/security/nss/lib/ckfw/nssmkey/ckmkver.c deleted file mode 100644 index 2b99f1e22..000000000 --- a/security/nss/lib/ckfw/nssmkey/ckmkver.c +++ /dev/null @@ -1,17 +0,0 @@ -/* 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/. */ -/* Library identity and versioning */ - -#include "nssmkey.h" - -#if defined(DEBUG) -#define _DEBUG_STRING " (debug)" -#else -#define _DEBUG_STRING "" -#endif - -/* - * Version information - */ -const char __nss_ckmk_version[] = "Version: NSS Access to the MAC OS X Key Ring " NSS_CKMK_LIBRARY_VERSION _DEBUG_STRING; diff --git a/security/nss/lib/ckfw/nssmkey/config.mk b/security/nss/lib/ckfw/nssmkey/config.mk deleted file mode 100644 index 709691067..000000000 --- a/security/nss/lib/ckfw/nssmkey/config.mk +++ /dev/null @@ -1,24 +0,0 @@ -# -# 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/. - -ifdef BUILD_IDG -DEFINES += -DNSSDEBUG -endif - -ifdef NS_USE_CKFW_TRACE -DEFINES += -DTRACE -endif - -# -# Override TARGETS variable so that only static libraries -# are specifed as dependencies within rules.mk. -# - -TARGETS = $(LIBRARY) -SHARED_LIBRARY = -IMPORT_LIBRARY = -PROGRAM = - - diff --git a/security/nss/lib/ckfw/nssmkey/manchor.c b/security/nss/lib/ckfw/nssmkey/manchor.c deleted file mode 100644 index 3b8bc2dbb..000000000 --- a/security/nss/lib/ckfw/nssmkey/manchor.c +++ /dev/null @@ -1,17 +0,0 @@ -/* 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/. */ - -/* - * nssmkey/manchor.c - * - * This file "anchors" the actual cryptoki entry points in this module's - * shared library, which is required for dynamic loading. See the - * comments in nssck.api for more information. - */ - -#include "ckmk.h" - -#define MODULE_NAME ckmk -#define INSTANCE_NAME (NSSCKMDInstance *)&nss_ckmk_mdInstance -#include "nssck.api" diff --git a/security/nss/lib/ckfw/nssmkey/manifest.mn b/security/nss/lib/ckfw/nssmkey/manifest.mn deleted file mode 100644 index 036d9bc3f..000000000 --- a/security/nss/lib/ckfw/nssmkey/manifest.mn +++ /dev/null @@ -1,33 +0,0 @@ -# -# 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 -MAPFILE = $(OBJDIR)/nssmkey.def - -EXPORTS = \ - nssmkey.h \ - $(NULL) - -CSRCS = \ - manchor.c \ - mconstants.c \ - mfind.c \ - minst.c \ - mobject.c \ - mrsa.c \ - msession.c \ - mslot.c \ - mtoken.c \ - ckmkver.c \ - staticobj.c \ - $(NULL) - -REQUIRES = nspr - -LIBRARY_NAME = nssmkey - -#EXTRA_SHARED_LIBS = -L$(DIST)/lib -lnssckfw -lnssb -lplc4 -lplds4 diff --git a/security/nss/lib/ckfw/nssmkey/mconstants.c b/security/nss/lib/ckfw/nssmkey/mconstants.c deleted file mode 100644 index c26298ada..000000000 --- a/security/nss/lib/ckfw/nssmkey/mconstants.c +++ /dev/null @@ -1,61 +0,0 @@ -/* 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/. */ - -/* - * nssmkey/constants.c - * - * Identification and other constants, all collected here in one place. - */ - -#ifndef NSSBASET_H -#include "nssbaset.h" -#endif /* NSSBASET_H */ - -#ifndef NSSCKT_H -#include "nssckt.h" -#endif /* NSSCKT_H */ - -#include "nssmkey.h" - -NSS_IMPLEMENT_DATA const CK_VERSION - nss_ckmk_CryptokiVersion = { - NSS_CKMK_CRYPTOKI_VERSION_MAJOR, - NSS_CKMK_CRYPTOKI_VERSION_MINOR - }; - -NSS_IMPLEMENT_DATA const NSSUTF8 * - nss_ckmk_ManufacturerID = (NSSUTF8 *)"Mozilla Foundation"; - -NSS_IMPLEMENT_DATA const NSSUTF8 * - nss_ckmk_LibraryDescription = (NSSUTF8 *)"NSS Access to Mac OS X Key Ring"; - -NSS_IMPLEMENT_DATA const CK_VERSION - nss_ckmk_LibraryVersion = { - NSS_CKMK_LIBRARY_VERSION_MAJOR, - NSS_CKMK_LIBRARY_VERSION_MINOR - }; - -NSS_IMPLEMENT_DATA const NSSUTF8 * - nss_ckmk_SlotDescription = (NSSUTF8 *)"Mac OS X Key Ring"; - -NSS_IMPLEMENT_DATA const CK_VERSION - nss_ckmk_HardwareVersion = { - NSS_CKMK_HARDWARE_VERSION_MAJOR, - NSS_CKMK_HARDWARE_VERSION_MINOR - }; - -NSS_IMPLEMENT_DATA const CK_VERSION - nss_ckmk_FirmwareVersion = { - NSS_CKMK_FIRMWARE_VERSION_MAJOR, - NSS_CKMK_FIRMWARE_VERSION_MINOR - }; - -NSS_IMPLEMENT_DATA const NSSUTF8 * - nss_ckmk_TokenLabel = (NSSUTF8 *)"Mac OS X Key Ring"; - -NSS_IMPLEMENT_DATA const NSSUTF8 * - nss_ckmk_TokenModel = (NSSUTF8 *)"1"; - -NSS_IMPLEMENT_DATA const NSSUTF8 * - nss_ckmk_TokenSerialNumber = (NSSUTF8 *)"1"; diff --git a/security/nss/lib/ckfw/nssmkey/mfind.c b/security/nss/lib/ckfw/nssmkey/mfind.c deleted file mode 100644 index d193a8de7..000000000 --- a/security/nss/lib/ckfw/nssmkey/mfind.c +++ /dev/null @@ -1,352 +0,0 @@ -/* 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 CKMK_H -#include "ckmk.h" -#endif /* CKMK_H */ - -/* - * nssmkey/mfind.c - * - * This file implements the NSSCKMDFindObjects object for the - * "nssmkey" cryptoki module. - */ - -struct ckmkFOStr { - NSSArena *arena; - CK_ULONG n; - CK_ULONG i; - ckmkInternalObject **objs; -}; - -static void -ckmk_mdFindObjects_Final( - NSSCKMDFindObjects *mdFindObjects, - NSSCKFWFindObjects *fwFindObjects, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance) -{ - struct ckmkFOStr *fo = (struct ckmkFOStr *)mdFindObjects->etc; - NSSArena *arena = fo->arena; - PRUint32 i; - - /* walk down an free the unused 'objs' */ - for (i = fo->i; i < fo->n; i++) { - nss_ckmk_DestroyInternalObject(fo->objs[i]); - } - - nss_ZFreeIf(fo->objs); - nss_ZFreeIf(fo); - nss_ZFreeIf(mdFindObjects); - if ((NSSArena *)NULL != arena) { - NSSArena_Destroy(arena); - } - - return; -} - -static NSSCKMDObject * -ckmk_mdFindObjects_Next( - NSSCKMDFindObjects *mdFindObjects, - NSSCKFWFindObjects *fwFindObjects, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - NSSArena *arena, - CK_RV *pError) -{ - struct ckmkFOStr *fo = (struct ckmkFOStr *)mdFindObjects->etc; - ckmkInternalObject *io; - - if (fo->i == fo->n) { - *pError = CKR_OK; - return (NSSCKMDObject *)NULL; - } - - io = fo->objs[fo->i]; - fo->i++; - - return nss_ckmk_CreateMDObject(arena, io, pError); -} - -static CK_BBOOL -ckmk_attrmatch( - CK_ATTRIBUTE_PTR a, - ckmkInternalObject *o) -{ - PRBool prb; - const NSSItem *b; - CK_RV error; - - b = nss_ckmk_FetchAttribute(o, a->type, &error); - if (b == NULL) { - return CK_FALSE; - } - - if (a->ulValueLen != b->size) { - /* match a decoded serial number */ - if ((a->type == CKA_SERIAL_NUMBER) && (a->ulValueLen < b->size)) { - int len; - unsigned char *data; - - data = nss_ckmk_DERUnwrap(b->data, b->size, &len, NULL); - if ((len == a->ulValueLen) && - nsslibc_memequal(a->pValue, data, len, (PRStatus *)NULL)) { - return CK_TRUE; - } - } - return CK_FALSE; - } - - prb = nsslibc_memequal(a->pValue, b->data, b->size, (PRStatus *)NULL); - - if (PR_TRUE == prb) { - return CK_TRUE; - } else { - return CK_FALSE; - } -} - -static CK_BBOOL -ckmk_match( - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulAttributeCount, - ckmkInternalObject *o) -{ - CK_ULONG i; - - for (i = 0; i < ulAttributeCount; i++) { - if (CK_FALSE == ckmk_attrmatch(&pTemplate[i], o)) { - return CK_FALSE; - } - } - - /* Every attribute passed */ - return CK_TRUE; -} - -#define CKMK_ITEM_CHUNK 20 - -#define PUT_OBJECT(obj, err, size, count, list) \ - { \ - if (count >= size) { \ - (list) = (list) ? nss_ZREALLOCARRAY(list, ckmkInternalObject *, \ - ((size) + \ - CKMK_ITEM_CHUNK)) \ - : nss_ZNEWARRAY(NULL, ckmkInternalObject *, \ - ((size) + \ - CKMK_ITEM_CHUNK)); \ - if ((ckmkInternalObject **)NULL == list) { \ - err = CKR_HOST_MEMORY; \ - goto loser; \ - } \ - (size) += CKMK_ITEM_CHUNK; \ - } \ - (list)[count] = (obj); \ - count++; \ - } - -/* find all the certs that represent the appropriate object (cert, priv key, or - * pub key) in the cert store. - */ -static PRUint32 -collect_class( - CK_OBJECT_CLASS objClass, - SecItemClass itemClass, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulAttributeCount, - ckmkInternalObject ***listp, - PRUint32 *sizep, - PRUint32 count, - CK_RV *pError) -{ - ckmkInternalObject *next = NULL; - SecKeychainSearchRef searchRef = 0; - SecKeychainItemRef itemRef = 0; - OSStatus error; - - /* future, build the attribute list based on the template - * so we can refine the search */ - error = SecKeychainSearchCreateFromAttributes( - NULL, itemClass, NULL, &searchRef); - - while (noErr == SecKeychainSearchCopyNext(searchRef, &itemRef)) { - /* if we don't have an internal object structure, get one */ - if ((ckmkInternalObject *)NULL == next) { - next = nss_ZNEW(NULL, ckmkInternalObject); - if ((ckmkInternalObject *)NULL == next) { - *pError = CKR_HOST_MEMORY; - goto loser; - } - } - /* fill in the relevant object data */ - next->type = ckmkItem; - next->objClass = objClass; - next->u.item.itemRef = itemRef; - next->u.item.itemClass = itemClass; - - /* see if this is one of the objects we are looking for */ - if (CK_TRUE == ckmk_match(pTemplate, ulAttributeCount, next)) { - /* yes, put it on the list */ - PUT_OBJECT(next, *pError, *sizep, count, *listp); - next = NULL; /* this one is on the list, need to allocate a new one now */ - } else { - /* no , release the current item and clear out the structure for reuse */ - CFRelease(itemRef); - /* don't cache the values we just loaded */ - nsslibc_memset(next, 0, sizeof(*next)); - } - } -loser: - if (searchRef) { - CFRelease(searchRef); - } - nss_ZFreeIf(next); - return count; -} - -static PRUint32 -collect_objects( - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulAttributeCount, - ckmkInternalObject ***listp, - CK_RV *pError) -{ - PRUint32 i; - PRUint32 count = 0; - PRUint32 size = 0; - CK_OBJECT_CLASS objClass; - - /* - * first handle the static build in objects (if any) - */ - for (i = 0; i < nss_ckmk_nObjects; i++) { - ckmkInternalObject *o = (ckmkInternalObject *)&nss_ckmk_data[i]; - - if (CK_TRUE == ckmk_match(pTemplate, ulAttributeCount, o)) { - PUT_OBJECT(o, *pError, size, count, *listp); - } - } - - /* - * now handle the various object types - */ - objClass = nss_ckmk_GetULongAttribute(CKA_CLASS, - pTemplate, ulAttributeCount, pError); - if (CKR_OK != *pError) { - objClass = CK_INVALID_HANDLE; - } - *pError = CKR_OK; - switch (objClass) { - case CKO_CERTIFICATE: - count = collect_class(objClass, kSecCertificateItemClass, - pTemplate, ulAttributeCount, listp, - &size, count, pError); - break; - case CKO_PUBLIC_KEY: - count = collect_class(objClass, CSSM_DL_DB_RECORD_PUBLIC_KEY, - pTemplate, ulAttributeCount, listp, - &size, count, pError); - break; - case CKO_PRIVATE_KEY: - count = collect_class(objClass, CSSM_DL_DB_RECORD_PRIVATE_KEY, - pTemplate, ulAttributeCount, listp, - &size, count, pError); - break; - /* all of them */ - case CK_INVALID_HANDLE: - count = collect_class(CKO_CERTIFICATE, kSecCertificateItemClass, - pTemplate, ulAttributeCount, listp, - &size, count, pError); - count = collect_class(CKO_PUBLIC_KEY, CSSM_DL_DB_RECORD_PUBLIC_KEY, - pTemplate, ulAttributeCount, listp, - &size, count, pError); - count = collect_class(CKO_PUBLIC_KEY, CSSM_DL_DB_RECORD_PRIVATE_KEY, - pTemplate, ulAttributeCount, listp, - &size, count, pError); - break; - default: - break; - } - if (CKR_OK != *pError) { - goto loser; - } - - return count; -loser: - nss_ZFreeIf(*listp); - return 0; -} - -NSS_IMPLEMENT NSSCKMDFindObjects * -nss_ckmk_FindObjectsInit( - NSSCKFWSession *fwSession, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulAttributeCount, - CK_RV *pError) -{ - /* This could be made more efficient. I'm rather rushed. */ - NSSArena *arena; - NSSCKMDFindObjects *rv = (NSSCKMDFindObjects *)NULL; - struct ckmkFOStr *fo = (struct ckmkFOStr *)NULL; - ckmkInternalObject **temp = (ckmkInternalObject **)NULL; - - arena = NSSArena_Create(); - if ((NSSArena *)NULL == arena) { - goto loser; - } - - rv = nss_ZNEW(arena, NSSCKMDFindObjects); - if ((NSSCKMDFindObjects *)NULL == rv) { - *pError = CKR_HOST_MEMORY; - goto loser; - } - - fo = nss_ZNEW(arena, struct ckmkFOStr); - if ((struct ckmkFOStr *)NULL == fo) { - *pError = CKR_HOST_MEMORY; - goto loser; - } - - fo->arena = arena; - /* fo->n and fo->i are already zero */ - - rv->etc = (void *)fo; - rv->Final = ckmk_mdFindObjects_Final; - rv->Next = ckmk_mdFindObjects_Next; - rv->null = (void *)NULL; - - fo->n = collect_objects(pTemplate, ulAttributeCount, &temp, pError); - if (*pError != CKR_OK) { - goto loser; - } - - fo->objs = nss_ZNEWARRAY(arena, ckmkInternalObject *, fo->n); - if ((ckmkInternalObject **)NULL == fo->objs) { - *pError = CKR_HOST_MEMORY; - goto loser; - } - - (void)nsslibc_memcpy(fo->objs, temp, sizeof(ckmkInternalObject *) * fo->n); - nss_ZFreeIf(temp); - temp = (ckmkInternalObject **)NULL; - - return rv; - -loser: - nss_ZFreeIf(temp); - nss_ZFreeIf(fo); - nss_ZFreeIf(rv); - if ((NSSArena *)NULL != arena) { - NSSArena_Destroy(arena); - } - return (NSSCKMDFindObjects *)NULL; -} diff --git a/security/nss/lib/ckfw/nssmkey/minst.c b/security/nss/lib/ckfw/nssmkey/minst.c deleted file mode 100644 index fcb96c652..000000000 --- a/security/nss/lib/ckfw/nssmkey/minst.c +++ /dev/null @@ -1,97 +0,0 @@ -/* 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 "ckmk.h" - -/* - * nssmkey/minstance.c - * - * This file implements the NSSCKMDInstance object for the - * "nssmkey" cryptoki module. - */ - -/* - * NSSCKMDInstance methods - */ - -static CK_ULONG -ckmk_mdInstance_GetNSlots( - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_RV *pError) -{ - return (CK_ULONG)1; -} - -static CK_VERSION -ckmk_mdInstance_GetCryptokiVersion( - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance) -{ - return nss_ckmk_CryptokiVersion; -} - -static NSSUTF8 * -ckmk_mdInstance_GetManufacturerID( - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_RV *pError) -{ - return (NSSUTF8 *)nss_ckmk_ManufacturerID; -} - -static NSSUTF8 * -ckmk_mdInstance_GetLibraryDescription( - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_RV *pError) -{ - return (NSSUTF8 *)nss_ckmk_LibraryDescription; -} - -static CK_VERSION -ckmk_mdInstance_GetLibraryVersion( - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance) -{ - return nss_ckmk_LibraryVersion; -} - -static CK_RV -ckmk_mdInstance_GetSlots( - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - NSSCKMDSlot *slots[]) -{ - slots[0] = (NSSCKMDSlot *)&nss_ckmk_mdSlot; - return CKR_OK; -} - -static CK_BBOOL -ckmk_mdInstance_ModuleHandlesSessionObjects( - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance) -{ - /* we don't want to allow any session object creation, at least - * until we can investigate whether or not we can use those objects - */ - return CK_TRUE; -} - -NSS_IMPLEMENT_DATA const NSSCKMDInstance - nss_ckmk_mdInstance = { - (void *)NULL, /* etc */ - NULL, /* Initialize */ - NULL, /* Finalize */ - ckmk_mdInstance_GetNSlots, - ckmk_mdInstance_GetCryptokiVersion, - ckmk_mdInstance_GetManufacturerID, - ckmk_mdInstance_GetLibraryDescription, - ckmk_mdInstance_GetLibraryVersion, - ckmk_mdInstance_ModuleHandlesSessionObjects, - /*NULL, /* HandleSessionObjects */ - ckmk_mdInstance_GetSlots, - NULL, /* WaitForSlotEvent */ - (void *)NULL /* null terminator */ - }; diff --git a/security/nss/lib/ckfw/nssmkey/mobject.c b/security/nss/lib/ckfw/nssmkey/mobject.c deleted file mode 100644 index b19a8fdbd..000000000 --- a/security/nss/lib/ckfw/nssmkey/mobject.c +++ /dev/null @@ -1,1861 +0,0 @@ -/* 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 "ckmk.h" -#include "nssbase.h" - -#include "secdert.h" /* for DER_INTEGER */ -#include "string.h" - -/* asn1 encoder (to build pkcs#8 blobs) */ -#include <seccomon.h> -#include <secitem.h> -#include <blapit.h> -#include <secoid.h> -#include <secasn1.h> - -/* for importing the keys */ -#include <CoreFoundation/CoreFoundation.h> -#include <security/SecImportExport.h> - -/* - * nssmkey/mobject.c - * - * This file implements the NSSCKMDObject object for the - * "nssmkey" cryptoki module. - */ - -const CK_ATTRIBUTE_TYPE certAttrs[] = { - CKA_CLASS, - CKA_TOKEN, - CKA_PRIVATE, - CKA_MODIFIABLE, - CKA_LABEL, - CKA_CERTIFICATE_TYPE, - CKA_SUBJECT, - CKA_ISSUER, - CKA_SERIAL_NUMBER, - CKA_VALUE -}; -const PRUint32 certAttrsCount = NSS_CKMK_ARRAY_SIZE(certAttrs); - -/* private keys, for now only support RSA */ -const CK_ATTRIBUTE_TYPE privKeyAttrs[] = { - CKA_CLASS, - CKA_TOKEN, - CKA_PRIVATE, - CKA_MODIFIABLE, - CKA_LABEL, - CKA_KEY_TYPE, - CKA_DERIVE, - CKA_LOCAL, - CKA_SUBJECT, - CKA_SENSITIVE, - CKA_DECRYPT, - CKA_SIGN, - CKA_SIGN_RECOVER, - CKA_UNWRAP, - CKA_EXTRACTABLE, - CKA_ALWAYS_SENSITIVE, - CKA_NEVER_EXTRACTABLE, - CKA_MODULUS, - CKA_PUBLIC_EXPONENT, -}; -const PRUint32 privKeyAttrsCount = NSS_CKMK_ARRAY_SIZE(privKeyAttrs); - -/* public keys, for now only support RSA */ -const CK_ATTRIBUTE_TYPE pubKeyAttrs[] = { - CKA_CLASS, - CKA_TOKEN, - CKA_PRIVATE, - CKA_MODIFIABLE, - CKA_LABEL, - CKA_KEY_TYPE, - CKA_DERIVE, - CKA_LOCAL, - CKA_SUBJECT, - CKA_ENCRYPT, - CKA_VERIFY, - CKA_VERIFY_RECOVER, - CKA_WRAP, - CKA_MODULUS, - CKA_PUBLIC_EXPONENT, -}; -const PRUint32 pubKeyAttrsCount = NSS_CKMK_ARRAY_SIZE(pubKeyAttrs); -static const CK_BBOOL ck_true = CK_TRUE; -static const CK_BBOOL ck_false = CK_FALSE; -static const CK_CERTIFICATE_TYPE ckc_x509 = CKC_X_509; -static const CK_KEY_TYPE ckk_rsa = CKK_RSA; -static const CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE; -static const CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY; -static const CK_OBJECT_CLASS cko_public_key = CKO_PUBLIC_KEY; -static const NSSItem ckmk_trueItem = { - (void *)&ck_true, (PRUint32)sizeof(CK_BBOOL) -}; -static const NSSItem ckmk_falseItem = { - (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL) -}; -static const NSSItem ckmk_x509Item = { - (void *)&ckc_x509, (PRUint32)sizeof(CK_CERTIFICATE_TYPE) -}; -static const NSSItem ckmk_rsaItem = { - (void *)&ckk_rsa, (PRUint32)sizeof(CK_KEY_TYPE) -}; -static const NSSItem ckmk_certClassItem = { - (void *)&cko_certificate, (PRUint32)sizeof(CK_OBJECT_CLASS) -}; -static const NSSItem ckmk_privKeyClassItem = { - (void *)&cko_private_key, (PRUint32)sizeof(CK_OBJECT_CLASS) -}; -static const NSSItem ckmk_pubKeyClassItem = { - (void *)&cko_public_key, (PRUint32)sizeof(CK_OBJECT_CLASS) -}; -static const NSSItem ckmk_emptyItem = { - (void *)&ck_true, 0 -}; - -/* - * these are utilities. The chould be moved to a new utilities file. - */ -#ifdef DEBUG -static void -itemdump(char *str, void *data, int size, CK_RV error) -{ - unsigned char *ptr = (unsigned char *)data; - int i; - fprintf(stderr, str); - for (i = 0; i < size; i++) { - fprintf(stderr, "%02x ", (unsigned int)ptr[i]); - } - fprintf(stderr, " (error = %d)\n", (int)error); -} -#endif - -/* - * unwrap a single DER value - * now that we have util linked in, we should probably use - * the ANS1_Decoder for this work... - */ -unsigned char * -nss_ckmk_DERUnwrap( - unsigned char *src, - int size, - int *outSize, - unsigned char **next) -{ - unsigned char *start = src; - unsigned int len = 0; - - /* initialize error condition return values */ - *outSize = 0; - if (next) { - *next = src; - } - - if (size < 2) { - return start; - } - src++; /* skip the tag -- should check it against an expected value! */ - len = (unsigned)*src++; - if (len & 0x80) { - int count = len & 0x7f; - len = 0; - - if (count + 2 > size) { - return start; - } - while (count-- > 0) { - len = (len << 8) | (unsigned)*src++; - } - } - if (len + (src - start) > (unsigned int)size) { - return start; - } - if (next) { - *next = src + len; - } - *outSize = len; - - return src; -} - -/* - * get an attribute from a template. Value is returned in NSS item. - * data for the item is owned by the template. - */ -CK_RV -nss_ckmk_GetAttribute( - CK_ATTRIBUTE_TYPE type, - CK_ATTRIBUTE *template, - CK_ULONG templateSize, - NSSItem *item) -{ - CK_ULONG i; - - for (i = 0; i < templateSize; i++) { - if (template[i].type == type) { - item->data = template[i].pValue; - item->size = template[i].ulValueLen; - return CKR_OK; - } - } - return CKR_TEMPLATE_INCOMPLETE; -} - -/* - * get an attribute which is type CK_ULONG. - */ -CK_ULONG -nss_ckmk_GetULongAttribute( - CK_ATTRIBUTE_TYPE type, - CK_ATTRIBUTE *template, - CK_ULONG templateSize, - CK_RV *pError) -{ - NSSItem item; - - *pError = nss_ckmk_GetAttribute(type, template, templateSize, &item); - if (CKR_OK != *pError) { - return (CK_ULONG)0; - } - if (item.size != sizeof(CK_ULONG)) { - *pError = CKR_ATTRIBUTE_VALUE_INVALID; - return (CK_ULONG)0; - } - return *(CK_ULONG *)item.data; -} - -/* - * get an attribute which is type CK_BBOOL. - */ -CK_BBOOL -nss_ckmk_GetBoolAttribute( - CK_ATTRIBUTE_TYPE type, - CK_ATTRIBUTE *template, - CK_ULONG templateSize, - CK_BBOOL defaultBool) -{ - NSSItem item; - CK_RV error; - - error = nss_ckmk_GetAttribute(type, template, templateSize, &item); - if (CKR_OK != error) { - return defaultBool; - } - if (item.size != sizeof(CK_BBOOL)) { - return defaultBool; - } - return *(CK_BBOOL *)item.data; -} - -/* - * get an attribute as a NULL terminated string. Caller is responsible to - * free the string. - */ -char * -nss_ckmk_GetStringAttribute( - CK_ATTRIBUTE_TYPE type, - CK_ATTRIBUTE *template, - CK_ULONG templateSize, - CK_RV *pError) -{ - NSSItem item; - char *str; - - /* get the attribute */ - *pError = nss_ckmk_GetAttribute(type, template, templateSize, &item); - if (CKR_OK != *pError) { - return (char *)NULL; - } - /* make sure it is null terminated */ - str = nss_ZNEWARRAY(NULL, char, item.size + 1); - if ((char *)NULL == str) { - *pError = CKR_HOST_MEMORY; - return (char *)NULL; - } - - nsslibc_memcpy(str, item.data, item.size); - str[item.size] = 0; - - return str; -} - -/* - * Apple doesn't seem to have a public interface to the DER encoder, - * wip out a quick one for integers only (anything more complicated, - * we should use one of the 3 in lib/util). -- especially since we - * now link with it. - */ -static CK_RV -ckmk_encodeInt(NSSItem *dest, void *src, int srcLen) -{ - int dataLen = srcLen; - int lenLen = 1; - int encLen; - int isSigned = 0; - int offset = 0; - unsigned char *data = NULL; - int i; - - if (*(unsigned char *)src & 0x80) { - dataLen++; - isSigned = 1; - } - - /* calculate the length of the length specifier */ - /* (NOTE: destroys dataLen value) */ - if (dataLen > 0x7f) { - do { - lenLen++; - dataLen >>= 8; - } while (dataLen); - } - - /* calculate our total length */ - dataLen = isSigned + srcLen; - encLen = 1 + lenLen + dataLen; - data = nss_ZNEWARRAY(NULL, unsigned char, encLen); - if ((unsigned char *)NULL == data) { - return CKR_HOST_MEMORY; - } - data[0] = DER_INTEGER; - if (1 == lenLen) { - data[1] = dataLen; - } else { - data[1] = 0x80 + lenLen; - for (i = 0; i < lenLen; i++) { - data[i + 1] = ((dataLen >> ((lenLen - - i - 1) * - 8)) & - 0xff); - } - } - offset = lenLen + 1; - - if (isSigned) { - data[offset++] = 0; - } - nsslibc_memcpy(&data[offset], src, srcLen); - dest->data = data; - dest->size = encLen; - return CKR_OK; -} - -/* - * Get a Keyring attribute. If content is set to true, then we get the - * content, not the attribute. - */ -static CK_RV -ckmk_GetCommonAttribute( - ckmkInternalObject *io, - SecItemAttr itemAttr, - PRBool content, - NSSItem *item, - char *dbString) -{ - SecKeychainAttributeList *attrList = NULL; - SecKeychainAttributeInfo attrInfo; - PRUint32 len = 0; - PRUint32 dataLen = 0; - PRUint32 attrFormat = 0; - void *dataVal = 0; - void *out = NULL; - CK_RV error = CKR_OK; - OSStatus macErr; - - attrInfo.count = 1; - attrInfo.tag = &itemAttr; - attrInfo.format = &attrFormat; - - macErr = SecKeychainItemCopyAttributesAndData(io->u.item.itemRef, - &attrInfo, NULL, &attrList, &len, &out); - if (noErr != macErr) { - CKMK_MACERR(dbString, macErr); - return CKR_ATTRIBUTE_TYPE_INVALID; - } - dataLen = content ? len : attrList->attr->length; - dataVal = content ? out : attrList->attr->data; - - /* Apple's documentation says this value is DER Encoded, but it clearly isn't - * der encode it before we ship it back off to NSS - */ - if (kSecSerialNumberItemAttr == itemAttr) { - error = ckmk_encodeInt(item, dataVal, dataLen); - goto loser; /* logically 'done' if error == CKR_OK */ - } - item->data = nss_ZNEWARRAY(NULL, char, dataLen); - if (NULL == item->data) { - error = CKR_HOST_MEMORY; - goto loser; - } - nsslibc_memcpy(item->data, dataVal, dataLen); - item->size = dataLen; - -loser: - SecKeychainItemFreeAttributesAndData(attrList, out); - return error; -} - -/* - * change an attribute (does not operate on the content). - */ -static CK_RV -ckmk_updateAttribute( - SecKeychainItemRef itemRef, - SecItemAttr itemAttr, - void *data, - PRUint32 len, - char *dbString) -{ - SecKeychainAttributeList attrList; - SecKeychainAttribute attrAttr; - OSStatus macErr; - CK_RV error = CKR_OK; - - attrList.count = 1; - attrList.attr = &attrAttr; - attrAttr.tag = itemAttr; - attrAttr.data = data; - attrAttr.length = len; - macErr = SecKeychainItemModifyAttributesAndData(itemRef, &attrList, 0, NULL); - if (noErr != macErr) { - CKMK_MACERR(dbString, macErr); - error = CKR_ATTRIBUTE_TYPE_INVALID; - } - return error; -} - -/* - * get an attribute (does not operate on the content) - */ -static CK_RV -ckmk_GetDataAttribute( - ckmkInternalObject *io, - SecItemAttr itemAttr, - NSSItem *item, - char *dbString) -{ - return ckmk_GetCommonAttribute(io, itemAttr, PR_FALSE, item, dbString); -} - -/* - * get an attribute we know is a BOOL. - */ -static CK_RV -ckmk_GetBoolAttribute( - ckmkInternalObject *io, - SecItemAttr itemAttr, - NSSItem *item, - char *dbString) -{ - SecKeychainAttribute attr; - SecKeychainAttributeList attrList; - CK_BBOOL *boolp = NULL; - PRUint32 len = 0; - ; - void *out = NULL; - CK_RV error = CKR_OK; - OSStatus macErr; - - attr.tag = itemAttr; - attr.length = 0; - attr.data = NULL; - attrList.count = 1; - attrList.attr = &attr; - - boolp = nss_ZNEW(NULL, CK_BBOOL); - if ((CK_BBOOL *)NULL == boolp) { - error = CKR_HOST_MEMORY; - goto loser; - } - - macErr = SecKeychainItemCopyContent(io->u.item.itemRef, NULL, - &attrList, &len, &out); - if (noErr != macErr) { - CKMK_MACERR(dbString, macErr); - error = CKR_ATTRIBUTE_TYPE_INVALID; - goto loser; - } - if (sizeof(PRUint32) != attr.length) { - error = CKR_ATTRIBUTE_TYPE_INVALID; - goto loser; - } - *boolp = *(PRUint32 *)attr.data ? 1 : 0; - item->data = boolp; - boolp = NULL; - item->size = sizeof(CK_BBOOL); - -loser: - nss_ZFreeIf(boolp); - SecKeychainItemFreeContent(&attrList, out); - return error; -} - -/* - * macros for fetching attributes into a cache and returning the - * appropriate value. These operate inside switch statements - */ -#define CKMK_HANDLE_ITEM(func, io, type, loc, item, error, str) \ - if (0 == (item)->loc.size) { \ - error = func(io, type, &(item)->loc, str); \ - } \ - return (CKR_OK == (error)) ? &(item)->loc : NULL; - -#define CKMK_HANDLE_OPT_ITEM(func, io, type, loc, item, error, str) \ - if (0 == (item)->loc.size) { \ - (void)func(io, type, &(item)->loc, str); \ - } \ - return &(item)->loc; - -#define CKMK_HANDLE_BOOL_ITEM(io, type, loc, item, error, str) \ - CKMK_HANDLE_ITEM(ckmk_GetBoolAttribute, io, type, loc, item, error, str) -#define CKMK_HANDLE_DATA_ITEM(io, type, loc, item, error, str) \ - CKMK_HANDLE_ITEM(ckmk_GetDataAttribute, io, type, loc, item, error, str) -#define CKMK_HANDLE_OPT_DATA_ITEM(io, type, loc, item, error, str) \ - CKMK_HANDLE_OPT_ITEM(ckmk_GetDataAttribute, io, type, loc, item, error, str) - -/* - * fetch the unique identifier for each object type. - */ -static void -ckmk_FetchHashKey( - ckmkInternalObject *io) -{ - NSSItem *key = &io->hashKey; - - if (io->objClass == CKO_CERTIFICATE) { - ckmk_GetCommonAttribute(io, kSecCertEncodingItemAttr, - PR_TRUE, key, "Fetching HashKey (cert)"); - } else { - ckmk_GetCommonAttribute(io, kSecKeyLabel, - PR_FALSE, key, "Fetching HashKey (key)"); - } -} - -/* - * Apple mucks with the actual subject and issuer, so go fetch - * the real ones ourselves. - */ -static void -ckmk_fetchCert( - ckmkInternalObject *io) -{ - CK_RV error; - unsigned char *cert, *next; - int certSize, thisEntrySize; - - error = ckmk_GetCommonAttribute(io, kSecCertEncodingItemAttr, PR_TRUE, - &io->u.item.derCert, "Fetching Value (cert)"); - if (CKR_OK != error) { - return; - } - /* unwrap the cert bundle */ - cert = nss_ckmk_DERUnwrap((unsigned char *)io->u.item.derCert.data, - io->u.item.derCert.size, - &certSize, NULL); - /* unwrap the cert itself */ - /* cert == certdata */ - cert = nss_ckmk_DERUnwrap(cert, certSize, &certSize, NULL); - - /* skip the optional version */ - if ((cert[0] & 0xa0) == 0xa0) { - nss_ckmk_DERUnwrap(cert, certSize, &thisEntrySize, &next); - certSize -= next - cert; - cert = next; - } - /* skip the serial number */ - nss_ckmk_DERUnwrap(cert, certSize, &thisEntrySize, &next); - certSize -= next - cert; - cert = next; - - /* skip the OID */ - nss_ckmk_DERUnwrap(cert, certSize, &thisEntrySize, &next); - certSize -= next - cert; - cert = next; - - /* save the (wrapped) issuer */ - io->u.item.issuer.data = cert; - nss_ckmk_DERUnwrap(cert, certSize, &thisEntrySize, &next); - io->u.item.issuer.size = next - cert; - certSize -= io->u.item.issuer.size; - cert = next; - - /* skip the OID */ - nss_ckmk_DERUnwrap(cert, certSize, &thisEntrySize, &next); - certSize -= next - cert; - cert = next; - - /* save the (wrapped) subject */ - io->u.item.subject.data = cert; - nss_ckmk_DERUnwrap(cert, certSize, &thisEntrySize, &next); - io->u.item.subject.size = next - cert; - certSize -= io->u.item.subject.size; - cert = next; -} - -static void -ckmk_fetchModulus( - ckmkInternalObject *io) -{ - NSSItem item; - PRInt32 modLen; - CK_RV error; - - /* we can't reliably get the modulus for private keys through CSSM (sigh). - * For NSS this is OK because we really only use this to get the modulus - * length (unless we are trying to get a public key from a private keys, - * something CSSM ALSO does not do!). - */ - error = ckmk_GetDataAttribute(io, kSecKeyKeySizeInBits, &item, - "Key Fetch Modulus"); - if (CKR_OK != error) { - return; - } - - modLen = *(PRInt32 *)item.data; - modLen = modLen / 8; /* convert from bits to bytes */ - - nss_ZFreeIf(item.data); - io->u.item.modulus.data = nss_ZNEWARRAY(NULL, char, modLen); - if (NULL == io->u.item.modulus.data) { - return; - } - *(char *)io->u.item.modulus.data = 0x80; /* fake NSS out or it will - * drop the first byte */ - io->u.item.modulus.size = modLen; - return; -} - -const NSSItem * -ckmk_FetchCertAttribute( - ckmkInternalObject *io, - CK_ATTRIBUTE_TYPE type, - CK_RV *pError) -{ - ckmkItemObject *item = &io->u.item; - *pError = CKR_OK; - switch (type) { - case CKA_CLASS: - return &ckmk_certClassItem; - case CKA_TOKEN: - case CKA_MODIFIABLE: - return &ckmk_trueItem; - case CKA_PRIVATE: - return &ckmk_falseItem; - case CKA_CERTIFICATE_TYPE: - return &ckmk_x509Item; - case CKA_LABEL: - CKMK_HANDLE_OPT_DATA_ITEM(io, kSecLabelItemAttr, label, item, *pError, - "Cert:Label attr") - case CKA_SUBJECT: - /* OK, well apple does provide an subject and issuer attribute, but they - * decided to cannonicalize that value. Probably a good move for them, - * but makes it useless for most users of PKCS #11.. Get the real subject - * from the certificate */ - if (0 == item->derCert.size) { - ckmk_fetchCert(io); - } - return &item->subject; - case CKA_ISSUER: - if (0 == item->derCert.size) { - ckmk_fetchCert(io); - } - return &item->issuer; - case CKA_SERIAL_NUMBER: - CKMK_HANDLE_DATA_ITEM(io, kSecSerialNumberItemAttr, serial, item, *pError, - "Cert:Serial Number attr") - case CKA_VALUE: - if (0 == item->derCert.size) { - ckmk_fetchCert(io); - } - return &item->derCert; - case CKA_ID: - CKMK_HANDLE_OPT_DATA_ITEM(io, kSecPublicKeyHashItemAttr, id, item, *pError, - "Cert:ID attr") - default: - *pError = CKR_ATTRIBUTE_TYPE_INVALID; - break; - } - return NULL; -} - -const NSSItem * -ckmk_FetchPubKeyAttribute( - ckmkInternalObject *io, - CK_ATTRIBUTE_TYPE type, - CK_RV *pError) -{ - ckmkItemObject *item = &io->u.item; - *pError = CKR_OK; - - switch (type) { - case CKA_CLASS: - return &ckmk_pubKeyClassItem; - case CKA_TOKEN: - case CKA_LOCAL: - return &ckmk_trueItem; - case CKA_KEY_TYPE: - return &ckmk_rsaItem; - case CKA_LABEL: - CKMK_HANDLE_OPT_DATA_ITEM(io, kSecKeyPrintName, label, item, *pError, - "PubKey:Label attr") - case CKA_ENCRYPT: - CKMK_HANDLE_BOOL_ITEM(io, kSecKeyEncrypt, encrypt, item, *pError, - "PubKey:Encrypt attr") - case CKA_VERIFY: - CKMK_HANDLE_BOOL_ITEM(io, kSecKeyVerify, verify, item, *pError, - "PubKey:Verify attr") - case CKA_VERIFY_RECOVER: - CKMK_HANDLE_BOOL_ITEM(io, kSecKeyVerifyRecover, verifyRecover, - item, *pError, "PubKey:VerifyRecover attr") - case CKA_PRIVATE: - CKMK_HANDLE_BOOL_ITEM(io, kSecKeyPrivate, private, item, *pError, - "PubKey:Private attr") - case CKA_MODIFIABLE: - CKMK_HANDLE_BOOL_ITEM(io, kSecKeyModifiable, modify, item, *pError, - "PubKey:Modify attr") - case CKA_DERIVE: - CKMK_HANDLE_BOOL_ITEM(io, kSecKeyDerive, derive, item, *pError, - "PubKey:Derive attr") - case CKA_WRAP: - CKMK_HANDLE_BOOL_ITEM(io, kSecKeyWrap, wrap, item, *pError, - "PubKey:Wrap attr") - case CKA_SUBJECT: - CKMK_HANDLE_OPT_DATA_ITEM(io, kSecSubjectItemAttr, subject, item, *pError, - "PubKey:Subect attr") - case CKA_MODULUS: - return &ckmk_emptyItem; - case CKA_PUBLIC_EXPONENT: - return &ckmk_emptyItem; - case CKA_ID: - CKMK_HANDLE_OPT_DATA_ITEM(io, kSecKeyLabel, id, item, *pError, - "PubKey:ID attr") - default: - *pError = CKR_ATTRIBUTE_TYPE_INVALID; - break; - } - return NULL; -} - -const NSSItem * -ckmk_FetchPrivKeyAttribute( - ckmkInternalObject *io, - CK_ATTRIBUTE_TYPE type, - CK_RV *pError) -{ - ckmkItemObject *item = &io->u.item; - *pError = CKR_OK; - - switch (type) { - case CKA_CLASS: - return &ckmk_privKeyClassItem; - case CKA_TOKEN: - case CKA_LOCAL: - return &ckmk_trueItem; - case CKA_SENSITIVE: - case CKA_EXTRACTABLE: /* will probably move in the future */ - case CKA_ALWAYS_SENSITIVE: - case CKA_NEVER_EXTRACTABLE: - return &ckmk_falseItem; - case CKA_KEY_TYPE: - return &ckmk_rsaItem; - case CKA_LABEL: - CKMK_HANDLE_OPT_DATA_ITEM(io, kSecKeyPrintName, label, item, *pError, - "PrivateKey:Label attr") - case CKA_DECRYPT: - CKMK_HANDLE_BOOL_ITEM(io, kSecKeyDecrypt, decrypt, item, *pError, - "PrivateKey:Decrypt attr") - case CKA_SIGN: - CKMK_HANDLE_BOOL_ITEM(io, kSecKeySign, sign, item, *pError, - "PrivateKey:Sign attr") - case CKA_SIGN_RECOVER: - CKMK_HANDLE_BOOL_ITEM(io, kSecKeySignRecover, signRecover, item, *pError, - "PrivateKey:Sign Recover attr") - case CKA_PRIVATE: - CKMK_HANDLE_BOOL_ITEM(io, kSecKeyPrivate, private, item, *pError, - "PrivateKey:Private attr") - case CKA_MODIFIABLE: - CKMK_HANDLE_BOOL_ITEM(io, kSecKeyModifiable, modify, item, *pError, - "PrivateKey:Modify attr") - case CKA_DERIVE: - CKMK_HANDLE_BOOL_ITEM(io, kSecKeyDerive, derive, item, *pError, - "PrivateKey:Derive attr") - case CKA_UNWRAP: - CKMK_HANDLE_BOOL_ITEM(io, kSecKeyUnwrap, unwrap, item, *pError, - "PrivateKey:Unwrap attr") - case CKA_SUBJECT: - CKMK_HANDLE_OPT_DATA_ITEM(io, kSecSubjectItemAttr, subject, item, *pError, - "PrivateKey:Subject attr") - case CKA_MODULUS: - if (0 == item->modulus.size) { - ckmk_fetchModulus(io); - } - return &item->modulus; - case CKA_PUBLIC_EXPONENT: - return &ckmk_emptyItem; -#ifdef notdef - /* the following are sensitive attributes. We could implement them for - * sensitive keys using the key export function, but it's better to - * just support wrap through this token. That will more reliably allow us - * to export any private key that is truly exportable. - */ - case CKA_PRIVATE_EXPONENT: - CKMK_HANDLE_DATA_ITEM(io, kSecPrivateExponentItemAttr, privateExponent, - item, *pError) - case CKA_PRIME_1: - CKMK_HANDLE_DATA_ITEM(io, kSecPrime1ItemAttr, prime1, item, *pError) - case CKA_PRIME_2: - CKMK_HANDLE_DATA_ITEM(io, kSecPrime2ItemAttr, prime2, item, *pError) - case CKA_EXPONENT_1: - CKMK_HANDLE_DATA_ITEM(io, kSecExponent1ItemAttr, exponent1, item, *pError) - case CKA_EXPONENT_2: - CKMK_HANDLE_DATA_ITEM(io, kSecExponent2ItemAttr, exponent2, item, *pError) - case CKA_COEFFICIENT: - CKMK_HANDLE_DATA_ITEM(io, kSecCoefficientItemAttr, coefficient, - item, *pError) -#endif - case CKA_ID: - CKMK_HANDLE_OPT_DATA_ITEM(io, kSecKeyLabel, id, item, *pError, - "PrivateKey:ID attr") - default: - *pError = CKR_ATTRIBUTE_TYPE_INVALID; - return NULL; - } -} - -const NSSItem * -nss_ckmk_FetchAttribute( - ckmkInternalObject *io, - CK_ATTRIBUTE_TYPE type, - CK_RV *pError) -{ - CK_ULONG i; - const NSSItem *value = NULL; - - if (io->type == ckmkRaw) { - for (i = 0; i < io->u.raw.n; i++) { - if (type == io->u.raw.types[i]) { - return &io->u.raw.items[i]; - } - } - *pError = CKR_ATTRIBUTE_TYPE_INVALID; - return NULL; - } - /* deal with the common attributes */ - switch (io->objClass) { - case CKO_CERTIFICATE: - value = ckmk_FetchCertAttribute(io, type, pError); - break; - case CKO_PRIVATE_KEY: - value = ckmk_FetchPrivKeyAttribute(io, type, pError); - break; - case CKO_PUBLIC_KEY: - value = ckmk_FetchPubKeyAttribute(io, type, pError); - break; - default: - *pError = CKR_OBJECT_HANDLE_INVALID; - return NULL; - } - -#ifdef DEBUG - if (CKA_ID == type) { - itemdump("id: ", value->data, value->size, *pError); - } -#endif - return value; -} - -static void -ckmk_removeObjectFromHash( - ckmkInternalObject *io); - -/* - * - * These are the MSObject functions we need to implement - * - * Finalize - unneeded (actually we should clean up the hashtables) - * Destroy - * IsTokenObject - CK_TRUE - * GetAttributeCount - * GetAttributeTypes - * GetAttributeSize - * GetAttribute - * SetAttribute - * GetObjectSize - */ - -static CK_RV -ckmk_mdObject_Destroy( - NSSCKMDObject *mdObject, - NSSCKFWObject *fwObject, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance) -{ - ckmkInternalObject *io = (ckmkInternalObject *)mdObject->etc; - OSStatus macErr; - - if (ckmkRaw == io->type) { - /* there is not 'object write protected' error, use the next best thing */ - return CKR_TOKEN_WRITE_PROTECTED; - } - - /* This API is done well. The following 4 lines are the complete apple - * specific part of this implementation */ - macErr = SecKeychainItemDelete(io->u.item.itemRef); - if (noErr != macErr) { - CKMK_MACERR("Delete object", macErr); - } - - /* remove it from the hash */ - ckmk_removeObjectFromHash(io); - - /* free the puppy.. */ - nss_ckmk_DestroyInternalObject(io); - - return CKR_OK; -} - -static CK_BBOOL -ckmk_mdObject_IsTokenObject( - NSSCKMDObject *mdObject, - NSSCKFWObject *fwObject, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance) -{ - return CK_TRUE; -} - -static CK_ULONG -ckmk_mdObject_GetAttributeCount( - NSSCKMDObject *mdObject, - NSSCKFWObject *fwObject, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_RV *pError) -{ - ckmkInternalObject *io = (ckmkInternalObject *)mdObject->etc; - - if (ckmkRaw == io->type) { - return io->u.raw.n; - } - switch (io->objClass) { - case CKO_CERTIFICATE: - return certAttrsCount; - case CKO_PUBLIC_KEY: - return pubKeyAttrsCount; - case CKO_PRIVATE_KEY: - return privKeyAttrsCount; - default: - break; - } - return 0; -} - -static CK_RV -ckmk_mdObject_GetAttributeTypes( - NSSCKMDObject *mdObject, - NSSCKFWObject *fwObject, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_ATTRIBUTE_TYPE_PTR typeArray, - CK_ULONG ulCount) -{ - ckmkInternalObject *io = (ckmkInternalObject *)mdObject->etc; - CK_ULONG i; - CK_RV error = CKR_OK; - const CK_ATTRIBUTE_TYPE *attrs = NULL; - CK_ULONG size = ckmk_mdObject_GetAttributeCount( - mdObject, fwObject, mdSession, fwSession, - mdToken, fwToken, mdInstance, fwInstance, &error); - - if (size != ulCount) { - return CKR_BUFFER_TOO_SMALL; - } - if (io->type == ckmkRaw) { - attrs = io->u.raw.types; - } else - switch (io->objClass) { - case CKO_CERTIFICATE: - attrs = - certAttrs; - break; - case CKO_PUBLIC_KEY: - attrs = - pubKeyAttrs; - break; - case CKO_PRIVATE_KEY: - attrs = - privKeyAttrs; - break; - default: - return CKR_OK; - } - - for (i = 0; i < size; i++) { - typeArray[i] = attrs[i]; - } - - return CKR_OK; -} - -static CK_ULONG -ckmk_mdObject_GetAttributeSize( - NSSCKMDObject *mdObject, - NSSCKFWObject *fwObject, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_ATTRIBUTE_TYPE attribute, - CK_RV *pError) -{ - ckmkInternalObject *io = (ckmkInternalObject *)mdObject->etc; - - const NSSItem *b; - - b = nss_ckmk_FetchAttribute(io, attribute, pError); - - if ((const NSSItem *)NULL == b) { - return 0; - } - return b->size; -} - -static CK_RV -ckmk_mdObject_SetAttribute( - NSSCKMDObject *mdObject, - NSSCKFWObject *fwObject, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_ATTRIBUTE_TYPE attribute, - NSSItem *value) -{ - ckmkInternalObject *io = (ckmkInternalObject *)mdObject->etc; - SecKeychainItemRef itemRef; - - if (io->type == ckmkRaw) { - return CKR_TOKEN_WRITE_PROTECTED; - } - itemRef = io->u.item.itemRef; - - switch (io->objClass) { - case CKO_PRIVATE_KEY: - case CKO_PUBLIC_KEY: - switch (attribute) { - case CKA_ID: - ckmk_updateAttribute(itemRef, kSecKeyLabel, - value->data, value->size, "Set Attr Key ID"); -#ifdef DEBUG - itemdump("key id: ", value->data, value->size, CKR_OK); -#endif - break; - case CKA_LABEL: - ckmk_updateAttribute(itemRef, kSecKeyPrintName, value->data, - value->size, "Set Attr Key Label"); - break; - default: - break; - } - break; - - case CKO_CERTIFICATE: - switch (attribute) { - case CKA_ID: - ckmk_updateAttribute(itemRef, kSecPublicKeyHashItemAttr, - value->data, value->size, "Set Attr Cert ID"); - break; - case CKA_LABEL: - ckmk_updateAttribute(itemRef, kSecLabelItemAttr, value->data, - value->size, "Set Attr Cert Label"); - break; - default: - break; - } - break; - - default: - break; - } - return CKR_OK; -} - -static NSSCKFWItem -ckmk_mdObject_GetAttribute( - NSSCKMDObject *mdObject, - NSSCKFWObject *fwObject, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_ATTRIBUTE_TYPE attribute, - CK_RV *pError) -{ - NSSCKFWItem mdItem; - ckmkInternalObject *io = (ckmkInternalObject *)mdObject->etc; - - mdItem.needsFreeing = PR_FALSE; - mdItem.item = (NSSItem *)nss_ckmk_FetchAttribute(io, attribute, pError); - - return mdItem; -} - -static CK_ULONG -ckmk_mdObject_GetObjectSize( - NSSCKMDObject *mdObject, - NSSCKFWObject *fwObject, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_RV *pError) -{ - CK_ULONG rv = 1; - - /* size is irrelevant to this token */ - return rv; -} - -static const NSSCKMDObject - ckmk_prototype_mdObject = { - (void *)NULL, /* etc */ - NULL, /* Finalize */ - ckmk_mdObject_Destroy, - ckmk_mdObject_IsTokenObject, - ckmk_mdObject_GetAttributeCount, - ckmk_mdObject_GetAttributeTypes, - ckmk_mdObject_GetAttributeSize, - ckmk_mdObject_GetAttribute, - NULL, /* FreeAttribute */ - ckmk_mdObject_SetAttribute, - ckmk_mdObject_GetObjectSize, - (void *)NULL /* null terminator */ - }; - -static nssHash *ckmkInternalObjectHash = NULL; - -NSS_IMPLEMENT NSSCKMDObject * -nss_ckmk_CreateMDObject( - NSSArena *arena, - ckmkInternalObject *io, - CK_RV *pError) -{ - if ((nssHash *)NULL == ckmkInternalObjectHash) { - ckmkInternalObjectHash = nssHash_CreateItem(NULL, 10); - } - if (ckmkItem == io->type) { - /* the hash key, not a cryptographic key */ - NSSItem *key = &io->hashKey; - ckmkInternalObject *old_o = NULL; - - if (key->size == 0) { - ckmk_FetchHashKey(io); - } - old_o = (ckmkInternalObject *) - nssHash_Lookup(ckmkInternalObjectHash, key); - if (!old_o) { - nssHash_Add(ckmkInternalObjectHash, key, io); - } else if (old_o != io) { - nss_ckmk_DestroyInternalObject(io); - io = old_o; - } - } - - if ((void *)NULL == io->mdObject.etc) { - (void)nsslibc_memcpy(&io->mdObject, &ckmk_prototype_mdObject, - sizeof(ckmk_prototype_mdObject)); - io->mdObject.etc = (void *)io; - } - return &io->mdObject; -} - -static void -ckmk_removeObjectFromHash( - ckmkInternalObject *io) -{ - NSSItem *key = &io->hashKey; - - if ((nssHash *)NULL == ckmkInternalObjectHash) { - return; - } - if (key->size == 0) { - ckmk_FetchHashKey(io); - } - nssHash_Remove(ckmkInternalObjectHash, key); - return; -} - -void -nss_ckmk_DestroyInternalObject( - ckmkInternalObject *io) -{ - switch (io->type) { - case ckmkRaw: - return; - case ckmkItem: - nss_ZFreeIf(io->u.item.modify.data); - nss_ZFreeIf(io->u.item.private.data); - nss_ZFreeIf(io->u.item.encrypt.data); - nss_ZFreeIf(io->u.item.decrypt.data); - nss_ZFreeIf(io->u.item.derive.data); - nss_ZFreeIf(io->u.item.sign.data); - nss_ZFreeIf(io->u.item.signRecover.data); - nss_ZFreeIf(io->u.item.verify.data); - nss_ZFreeIf(io->u.item.verifyRecover.data); - nss_ZFreeIf(io->u.item.wrap.data); - nss_ZFreeIf(io->u.item.unwrap.data); - nss_ZFreeIf(io->u.item.label.data); - /*nss_ZFreeIf(io->u.item.subject.data); */ - /*nss_ZFreeIf(io->u.item.issuer.data); */ - nss_ZFreeIf(io->u.item.serial.data); - nss_ZFreeIf(io->u.item.modulus.data); - nss_ZFreeIf(io->u.item.exponent.data); - nss_ZFreeIf(io->u.item.privateExponent.data); - nss_ZFreeIf(io->u.item.prime1.data); - nss_ZFreeIf(io->u.item.prime2.data); - nss_ZFreeIf(io->u.item.exponent1.data); - nss_ZFreeIf(io->u.item.exponent2.data); - nss_ZFreeIf(io->u.item.coefficient.data); - break; - } - nss_ZFreeIf(io); - return; -} - -static ckmkInternalObject * -nss_ckmk_NewInternalObject( - CK_OBJECT_CLASS objClass, - SecKeychainItemRef itemRef, - SecItemClass itemClass, - CK_RV *pError) -{ - ckmkInternalObject *io = nss_ZNEW(NULL, ckmkInternalObject); - - if ((ckmkInternalObject *)NULL == io) { - *pError = CKR_HOST_MEMORY; - return io; - } - io->type = ckmkItem; - io->objClass = objClass; - io->u.item.itemRef = itemRef; - io->u.item.itemClass = itemClass; - return io; -} - -/* - * Apple doesn't alway have a default keyChain set by the OS, use the - * SearchList to try to find one. - */ -static CK_RV -ckmk_GetSafeDefaultKeychain( - SecKeychainRef *keychainRef) -{ - OSStatus macErr; - CFArrayRef searchList = 0; - CK_RV error = CKR_OK; - - macErr = SecKeychainCopyDefault(keychainRef); - if (noErr != macErr) { - int searchCount = 0; - if (errSecNoDefaultKeychain != macErr) { - CKMK_MACERR("Getting default key chain", macErr); - error = CKR_GENERAL_ERROR; - goto loser; - } - /* ok, we don't have a default key chain, find one */ - macErr = SecKeychainCopySearchList(&searchList); - if (noErr != macErr) { - CKMK_MACERR("failed to find a keyring searchList", macErr); - error = CKR_DEVICE_REMOVED; - goto loser; - } - searchCount = CFArrayGetCount(searchList); - if (searchCount < 1) { - error = CKR_DEVICE_REMOVED; - goto loser; - } - *keychainRef = - (SecKeychainRef)CFRetain(CFArrayGetValueAtIndex(searchList, 0)); - if (0 == *keychainRef) { - error = CKR_DEVICE_REMOVED; - goto loser; - } - /* should we set it as default? */ - } -loser: - if (0 != searchList) { - CFRelease(searchList); - } - return error; -} -static ckmkInternalObject * -nss_ckmk_CreateCertificate( - NSSCKFWSession *fwSession, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulAttributeCount, - CK_RV *pError) -{ - NSSItem value; - ckmkInternalObject *io = NULL; - OSStatus macErr; - SecCertificateRef certRef; - SecKeychainItemRef itemRef; - SecKeychainRef keychainRef; - CSSM_DATA certData; - - *pError = nss_ckmk_GetAttribute(CKA_VALUE, pTemplate, - ulAttributeCount, &value); - if (CKR_OK != *pError) { - goto loser; - } - - certData.Data = value.data; - certData.Length = value.size; - macErr = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3, - CSSM_CERT_ENCODING_BER, &certRef); - if (noErr != macErr) { - CKMK_MACERR("Create cert from data Failed", macErr); - *pError = CKR_GENERAL_ERROR; /* need to map macErr */ - goto loser; - } - - *pError = ckmk_GetSafeDefaultKeychain(&keychainRef); - if (CKR_OK != *pError) { - goto loser; - } - - macErr = SecCertificateAddToKeychain(certRef, keychainRef); - itemRef = (SecKeychainItemRef)certRef; - if (errSecDuplicateItem != macErr) { - NSSItem keyID = { NULL, 0 }; - char *nickname = NULL; - CK_RV dummy; - - if (noErr != macErr) { - CKMK_MACERR("Add cert to keychain Failed", macErr); - *pError = CKR_GENERAL_ERROR; /* need to map macErr */ - goto loser; - } - /* these two are optional */ - nickname = nss_ckmk_GetStringAttribute(CKA_LABEL, pTemplate, - ulAttributeCount, &dummy); - /* we've added a new one, update the attributes in the key ring */ - if (nickname) { - ckmk_updateAttribute(itemRef, kSecLabelItemAttr, nickname, - strlen(nickname) + 1, "Modify Cert Label"); - nss_ZFreeIf(nickname); - } - dummy = nss_ckmk_GetAttribute(CKA_ID, pTemplate, - ulAttributeCount, &keyID); - if (CKR_OK == dummy) { - dummy = ckmk_updateAttribute(itemRef, kSecPublicKeyHashItemAttr, - keyID.data, keyID.size, "Modify Cert ID"); - } - } - - io = nss_ckmk_NewInternalObject(CKO_CERTIFICATE, itemRef, - kSecCertificateItemClass, pError); - if ((ckmkInternalObject *)NULL != io) { - itemRef = 0; - } - -loser: - if (0 != itemRef) { - CFRelease(itemRef); - } - if (0 != keychainRef) { - CFRelease(keychainRef); - } - - return io; -} - -/* - * PKCS #8 attributes - */ -struct ckmk_AttributeStr { - SECItem attrType; - SECItem *attrValue; -}; -typedef struct ckmk_AttributeStr ckmk_Attribute; - -/* - ** A PKCS#8 private key info object - */ -struct PrivateKeyInfoStr { - PLArenaPool *arena; - SECItem version; - SECAlgorithmID algorithm; - SECItem privateKey; - ckmk_Attribute **attributes; -}; -typedef struct PrivateKeyInfoStr PrivateKeyInfo; - -const SEC_ASN1Template ckmk_RSAPrivateKeyTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RSAPrivateKey) }, - { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, version) }, - { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, modulus) }, - { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, publicExponent) }, - { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, privateExponent) }, - { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, prime1) }, - { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, prime2) }, - { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent1) }, - { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent2) }, - { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, coefficient) }, - { 0 } -}; - -const SEC_ASN1Template ckmk_AttributeTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(ckmk_Attribute) }, - { SEC_ASN1_OBJECT_ID, offsetof(ckmk_Attribute, attrType) }, - { SEC_ASN1_SET_OF, offsetof(ckmk_Attribute, attrValue), - SEC_AnyTemplate }, - { 0 } -}; - -const SEC_ASN1Template ckmk_SetOfAttributeTemplate[] = { - { SEC_ASN1_SET_OF, 0, ckmk_AttributeTemplate }, -}; - -SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) - -/* ASN1 Templates for new decoder/encoder */ -const SEC_ASN1Template ckmk_PrivateKeyInfoTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PrivateKeyInfo) }, - { SEC_ASN1_INTEGER, offsetof(PrivateKeyInfo, version) }, - { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(PrivateKeyInfo, algorithm), - SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, - { SEC_ASN1_OCTET_STRING, offsetof(PrivateKeyInfo, privateKey) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(PrivateKeyInfo, attributes), ckmk_SetOfAttributeTemplate }, - { 0 } -}; - -#define CKMK_PRIVATE_KEY_INFO_VERSION 0 -static CK_RV -ckmk_CreateRSAKeyBlob( - RSAPrivateKey *lk, - NSSItem *keyBlob) -{ - PrivateKeyInfo *pki = NULL; - PLArenaPool *arena = NULL; - SECOidTag algorithm = SEC_OID_UNKNOWN; - void *dummy; - SECStatus rv; - SECItem *encodedKey = NULL; - CK_RV error = CKR_OK; - - arena = PORT_NewArena(2048); /* XXX different size? */ - if (!arena) { - error = CKR_HOST_MEMORY; - goto loser; - } - - pki = (PrivateKeyInfo *)PORT_ArenaZAlloc(arena, sizeof(PrivateKeyInfo)); - if (!pki) { - error = CKR_HOST_MEMORY; - goto loser; - } - pki->arena = arena; - - dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, - ckmk_RSAPrivateKeyTemplate); - algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; - - if (!dummy) { - error = CKR_DEVICE_ERROR; /* should map NSS SECError */ - goto loser; - } - - rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm, - (SECItem *)NULL); - if (rv != SECSuccess) { - error = CKR_DEVICE_ERROR; /* should map NSS SECError */ - goto loser; - } - - dummy = SEC_ASN1EncodeInteger(arena, &pki->version, - CKMK_PRIVATE_KEY_INFO_VERSION); - if (!dummy) { - error = CKR_DEVICE_ERROR; /* should map NSS SECError */ - goto loser; - } - - encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki, - ckmk_PrivateKeyInfoTemplate); - if (!encodedKey) { - error = CKR_DEVICE_ERROR; - goto loser; - } - - keyBlob->data = nss_ZNEWARRAY(NULL, char, encodedKey->len); - if (NULL == keyBlob->data) { - error = CKR_HOST_MEMORY; - goto loser; - } - nsslibc_memcpy(keyBlob->data, encodedKey->data, encodedKey->len); - keyBlob->size = encodedKey->len; - -loser: - if (arena) { - PORT_FreeArena(arena, PR_TRUE); - } - if (encodedKey) { - SECITEM_FreeItem(encodedKey, PR_TRUE); - } - - return error; -} -/* - * There MUST be a better way to do this. For now, find the key based on the - * default name Apple gives it once we import. - */ -#define IMPORTED_NAME "Imported Private Key" -static CK_RV -ckmk_FindImportedKey( - SecKeychainRef keychainRef, - SecItemClass itemClass, - SecKeychainItemRef *outItemRef) -{ - OSStatus macErr; - SecKeychainSearchRef searchRef = 0; - SecKeychainItemRef newItemRef; - - macErr = SecKeychainSearchCreateFromAttributes(keychainRef, itemClass, - NULL, &searchRef); - if (noErr != macErr) { - CKMK_MACERR("Can't search for Key", macErr); - return CKR_GENERAL_ERROR; - } - while (noErr == SecKeychainSearchCopyNext(searchRef, &newItemRef)) { - SecKeychainAttributeList *attrList = NULL; - SecKeychainAttributeInfo attrInfo; - SecItemAttr itemAttr = kSecKeyPrintName; - PRUint32 attrFormat = 0; - OSStatus macErr; - - attrInfo.count = 1; - attrInfo.tag = &itemAttr; - attrInfo.format = &attrFormat; - - macErr = SecKeychainItemCopyAttributesAndData(newItemRef, - &attrInfo, NULL, &attrList, NULL, NULL); - if (noErr == macErr) { - if (nsslibc_memcmp(attrList->attr->data, IMPORTED_NAME, - attrList->attr->length, NULL) == 0) { - *outItemRef = newItemRef; - CFRelease(searchRef); - SecKeychainItemFreeAttributesAndData(attrList, NULL); - return CKR_OK; - } - SecKeychainItemFreeAttributesAndData(attrList, NULL); - } - CFRelease(newItemRef); - } - CFRelease(searchRef); - return CKR_GENERAL_ERROR; /* we can come up with something better! */ -} - -static ckmkInternalObject * -nss_ckmk_CreatePrivateKey( - NSSCKFWSession *fwSession, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulAttributeCount, - CK_RV *pError) -{ - NSSItem attribute; - RSAPrivateKey lk; - NSSItem keyID; - char *nickname = NULL; - ckmkInternalObject *io = NULL; - CK_KEY_TYPE keyType; - OSStatus macErr; - SecKeychainItemRef itemRef = 0; - NSSItem keyBlob = { NULL, 0 }; - CFDataRef dataRef = 0; - SecExternalFormat inputFormat = kSecFormatBSAFE; - /*SecExternalFormat inputFormat = kSecFormatOpenSSL; */ - SecExternalItemType itemType = kSecItemTypePrivateKey; - SecKeyImportExportParameters keyParams; - SecKeychainRef targetKeychain = 0; - unsigned char zero = 0; - CK_RV error; - - keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; - keyParams.flags = 0; - keyParams.passphrase = 0; - keyParams.alertTitle = 0; - keyParams.alertPrompt = 0; - keyParams.accessRef = 0; /* default */ - keyParams.keyUsage = 0; /* will get filled in */ - keyParams.keyAttributes = CSSM_KEYATTR_PERMANENT; /* will get filled in */ - keyType = nss_ckmk_GetULongAttribute(CKA_KEY_TYPE, pTemplate, ulAttributeCount, pError); - if (CKR_OK != *pError) { - return (ckmkInternalObject *)NULL; - } - if (CKK_RSA != keyType) { - *pError = CKR_ATTRIBUTE_VALUE_INVALID; - return (ckmkInternalObject *)NULL; - } - if (nss_ckmk_GetBoolAttribute(CKA_DECRYPT, - pTemplate, ulAttributeCount, CK_TRUE)) { - keyParams.keyUsage |= CSSM_KEYUSE_DECRYPT; - } - if (nss_ckmk_GetBoolAttribute(CKA_UNWRAP, - pTemplate, ulAttributeCount, CK_TRUE)) { - keyParams.keyUsage |= CSSM_KEYUSE_UNWRAP; - } - if (nss_ckmk_GetBoolAttribute(CKA_SIGN, - pTemplate, ulAttributeCount, CK_TRUE)) { - keyParams.keyUsage |= CSSM_KEYUSE_SIGN; - } - if (nss_ckmk_GetBoolAttribute(CKA_DERIVE, - pTemplate, ulAttributeCount, CK_FALSE)) { - keyParams.keyUsage |= CSSM_KEYUSE_DERIVE; - } - if (nss_ckmk_GetBoolAttribute(CKA_SENSITIVE, - pTemplate, ulAttributeCount, CK_TRUE)) { - keyParams.keyAttributes |= CSSM_KEYATTR_SENSITIVE; - } - if (nss_ckmk_GetBoolAttribute(CKA_EXTRACTABLE, - pTemplate, ulAttributeCount, CK_TRUE)) { - keyParams.keyAttributes |= CSSM_KEYATTR_EXTRACTABLE; - } - - lk.version.type = siUnsignedInteger; - lk.version.data = &zero; - lk.version.len = 1; - - *pError = nss_ckmk_GetAttribute(CKA_MODULUS, pTemplate, - ulAttributeCount, &attribute); - if (CKR_OK != *pError) { - return (ckmkInternalObject *)NULL; - } - lk.modulus.type = siUnsignedInteger; - lk.modulus.data = attribute.data; - lk.modulus.len = attribute.size; - - *pError = nss_ckmk_GetAttribute(CKA_PUBLIC_EXPONENT, pTemplate, - ulAttributeCount, &attribute); - if (CKR_OK != *pError) { - return (ckmkInternalObject *)NULL; - } - lk.publicExponent.type = siUnsignedInteger; - lk.publicExponent.data = attribute.data; - lk.publicExponent.len = attribute.size; - - *pError = nss_ckmk_GetAttribute(CKA_PRIVATE_EXPONENT, pTemplate, - ulAttributeCount, &attribute); - if (CKR_OK != *pError) { - return (ckmkInternalObject *)NULL; - } - lk.privateExponent.type = siUnsignedInteger; - lk.privateExponent.data = attribute.data; - lk.privateExponent.len = attribute.size; - - *pError = nss_ckmk_GetAttribute(CKA_PRIME_1, pTemplate, - ulAttributeCount, &attribute); - if (CKR_OK != *pError) { - return (ckmkInternalObject *)NULL; - } - lk.prime1.type = siUnsignedInteger; - lk.prime1.data = attribute.data; - lk.prime1.len = attribute.size; - - *pError = nss_ckmk_GetAttribute(CKA_PRIME_2, pTemplate, - ulAttributeCount, &attribute); - if (CKR_OK != *pError) { - return (ckmkInternalObject *)NULL; - } - lk.prime2.type = siUnsignedInteger; - lk.prime2.data = attribute.data; - lk.prime2.len = attribute.size; - - *pError = nss_ckmk_GetAttribute(CKA_EXPONENT_1, pTemplate, - ulAttributeCount, &attribute); - if (CKR_OK != *pError) { - return (ckmkInternalObject *)NULL; - } - lk.exponent1.type = siUnsignedInteger; - lk.exponent1.data = attribute.data; - lk.exponent1.len = attribute.size; - - *pError = nss_ckmk_GetAttribute(CKA_EXPONENT_2, pTemplate, - ulAttributeCount, &attribute); - if (CKR_OK != *pError) { - return (ckmkInternalObject *)NULL; - } - lk.exponent2.type = siUnsignedInteger; - lk.exponent2.data = attribute.data; - lk.exponent2.len = attribute.size; - - *pError = nss_ckmk_GetAttribute(CKA_COEFFICIENT, pTemplate, - ulAttributeCount, &attribute); - if (CKR_OK != *pError) { - return (ckmkInternalObject *)NULL; - } - lk.coefficient.type = siUnsignedInteger; - lk.coefficient.data = attribute.data; - lk.coefficient.len = attribute.size; - - /* ASN1 Encode the pkcs8 structure... look at softoken to see how this - * is done... */ - error = ckmk_CreateRSAKeyBlob(&lk, &keyBlob); - if (CKR_OK != error) { - goto loser; - } - - dataRef = CFDataCreate(NULL, (UInt8 *)keyBlob.data, keyBlob.size); - if (0 == dataRef) { - *pError = CKR_HOST_MEMORY; - goto loser; - } - - *pError == ckmk_GetSafeDefaultKeychain(&targetKeychain); - if (CKR_OK != *pError) { - goto loser; - } - - /* the itemArray that is returned is useless. the item does not - * is 'not on the key chain' so none of the modify calls work on it. - * It also has a key that isn't the same key as the one in the actual - * key chain. In short it isn't the item we want, and it gives us zero - * information about the item we want, so don't even bother with it... - */ - macErr = SecKeychainItemImport(dataRef, NULL, &inputFormat, &itemType, 0, - &keyParams, targetKeychain, NULL); - if (noErr != macErr) { - CKMK_MACERR("Import Private Key", macErr); - *pError = CKR_GENERAL_ERROR; - goto loser; - } - - *pError = ckmk_FindImportedKey(targetKeychain, - CSSM_DL_DB_RECORD_PRIVATE_KEY, - &itemRef); - if (CKR_OK != *pError) { -#ifdef DEBUG - fprintf(stderr, "couldn't find key in keychain \n"); -#endif - goto loser; - } - - /* set the CKA_ID and the CKA_LABEL */ - error = nss_ckmk_GetAttribute(CKA_ID, pTemplate, - ulAttributeCount, &keyID); - if (CKR_OK == error) { - error = ckmk_updateAttribute(itemRef, kSecKeyLabel, - keyID.data, keyID.size, "Modify Key ID"); -#ifdef DEBUG - itemdump("key id: ", keyID.data, keyID.size, error); -#endif - } - nickname = nss_ckmk_GetStringAttribute(CKA_LABEL, pTemplate, - ulAttributeCount, &error); - if (nickname) { - ckmk_updateAttribute(itemRef, kSecKeyPrintName, nickname, - strlen(nickname) + 1, "Modify Key Label"); - } else { -#define DEFAULT_NICKNAME "NSS Imported Key" - ckmk_updateAttribute(itemRef, kSecKeyPrintName, DEFAULT_NICKNAME, - sizeof(DEFAULT_NICKNAME), "Modify Key Label"); - } - - io = nss_ckmk_NewInternalObject(CKO_PRIVATE_KEY, itemRef, - CSSM_DL_DB_RECORD_PRIVATE_KEY, pError); - if ((ckmkInternalObject *)NULL == io) { - CFRelease(itemRef); - } - - return io; - -loser: - /* free the key blob */ - if (keyBlob.data) { - nss_ZFreeIf(keyBlob.data); - } - if (0 != targetKeychain) { - CFRelease(targetKeychain); - } - if (0 != dataRef) { - CFRelease(dataRef); - } - return io; -} - -NSS_EXTERN NSSCKMDObject * -nss_ckmk_CreateObject( - NSSCKFWSession *fwSession, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulAttributeCount, - CK_RV *pError) -{ - CK_OBJECT_CLASS objClass; - ckmkInternalObject *io = NULL; - CK_BBOOL isToken; - - /* - * only create token objects - */ - isToken = nss_ckmk_GetBoolAttribute(CKA_TOKEN, pTemplate, - ulAttributeCount, CK_FALSE); - if (!isToken) { - *pError = CKR_ATTRIBUTE_VALUE_INVALID; - return (NSSCKMDObject *)NULL; - } - - /* - * only create keys and certs. - */ - objClass = nss_ckmk_GetULongAttribute(CKA_CLASS, pTemplate, - ulAttributeCount, pError); - if (CKR_OK != *pError) { - return (NSSCKMDObject *)NULL; - } -#ifdef notdef - if (objClass == CKO_PUBLIC_KEY) { - return CKR_OK; /* fake public key creation, happens as a side effect of - * private key creation */ - } -#endif - if (objClass == CKO_CERTIFICATE) { - io = nss_ckmk_CreateCertificate(fwSession, pTemplate, - ulAttributeCount, pError); - } else if (objClass == CKO_PRIVATE_KEY) { - io = nss_ckmk_CreatePrivateKey(fwSession, pTemplate, - ulAttributeCount, pError); - } else { - *pError = CKR_ATTRIBUTE_VALUE_INVALID; - } - - if ((ckmkInternalObject *)NULL == io) { - return (NSSCKMDObject *)NULL; - } - return nss_ckmk_CreateMDObject(NULL, io, pError); -} diff --git a/security/nss/lib/ckfw/nssmkey/mrsa.c b/security/nss/lib/ckfw/nssmkey/mrsa.c deleted file mode 100644 index 00175b47a..000000000 --- a/security/nss/lib/ckfw/nssmkey/mrsa.c +++ /dev/null @@ -1,479 +0,0 @@ -/* 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 "ckmk.h" - -/* Sigh, For all the talk about 'ease of use', apple has hidden the interfaces - * needed to be able to truly use CSSM. These came from their modification - * to NSS's S/MIME code. The following two functions currently are not - * part of the SecKey.h interface. - */ -OSStatus -SecKeyGetCredentials( - SecKeyRef keyRef, - CSSM_ACL_AUTHORIZATION_TAG authTag, - int type, - const CSSM_ACCESS_CREDENTIALS **creds); - -/* this function could be implemented using 'SecKeychainItemCopyKeychain' and - * 'SecKeychainGetCSPHandle' */ -OSStatus -SecKeyGetCSPHandle( - SecKeyRef keyRef, - CSSM_CSP_HANDLE *cspHandle); - -typedef struct ckmkInternalCryptoOperationRSAPrivStr - ckmkInternalCryptoOperationRSAPriv; -struct ckmkInternalCryptoOperationRSAPrivStr { - NSSCKMDCryptoOperation mdOperation; - NSSCKMDMechanism *mdMechanism; - ckmkInternalObject *iKey; - NSSItem *buffer; - CSSM_CC_HANDLE cssmContext; -}; - -typedef enum { - CKMK_DECRYPT, - CKMK_SIGN -} ckmkRSAOpType; - -/* - * ckmk_mdCryptoOperationRSAPriv_Create - */ -static NSSCKMDCryptoOperation * -ckmk_mdCryptoOperationRSAPriv_Create( - const NSSCKMDCryptoOperation *proto, - NSSCKMDMechanism *mdMechanism, - NSSCKMDObject *mdKey, - ckmkRSAOpType type, - CK_RV *pError) -{ - ckmkInternalObject *iKey = (ckmkInternalObject *)mdKey->etc; - const NSSItem *classItem = nss_ckmk_FetchAttribute(iKey, CKA_CLASS, pError); - const NSSItem *keyType = nss_ckmk_FetchAttribute(iKey, CKA_KEY_TYPE, pError); - ckmkInternalCryptoOperationRSAPriv *iOperation; - SecKeyRef privateKey; - OSStatus macErr; - CSSM_RETURN cssmErr; - const CSSM_KEY *cssmKey; - CSSM_CSP_HANDLE cspHandle; - const CSSM_ACCESS_CREDENTIALS *creds = NULL; - CSSM_CC_HANDLE cssmContext; - CSSM_ACL_AUTHORIZATION_TAG authType; - - /* make sure we have the right objects */ - if (((const NSSItem *)NULL == classItem) || - (sizeof(CK_OBJECT_CLASS) != classItem->size) || - (CKO_PRIVATE_KEY != *(CK_OBJECT_CLASS *)classItem->data) || - ((const NSSItem *)NULL == keyType) || - (sizeof(CK_KEY_TYPE) != keyType->size) || - (CKK_RSA != *(CK_KEY_TYPE *)keyType->data)) { - *pError = CKR_KEY_TYPE_INCONSISTENT; - return (NSSCKMDCryptoOperation *)NULL; - } - - privateKey = (SecKeyRef)iKey->u.item.itemRef; - macErr = SecKeyGetCSSMKey(privateKey, &cssmKey); - if (noErr != macErr) { - CKMK_MACERR("Getting CSSM Key", macErr); - *pError = CKR_KEY_HANDLE_INVALID; - return (NSSCKMDCryptoOperation *)NULL; - } - macErr = SecKeyGetCSPHandle(privateKey, &cspHandle); - if (noErr != macErr) { - CKMK_MACERR("Getting CSP for Key", macErr); - *pError = CKR_KEY_HANDLE_INVALID; - return (NSSCKMDCryptoOperation *)NULL; - } - switch (type) { - case CKMK_DECRYPT: - authType = CSSM_ACL_AUTHORIZATION_DECRYPT; - break; - case CKMK_SIGN: - authType = CSSM_ACL_AUTHORIZATION_SIGN; - break; - default: - *pError = CKR_GENERAL_ERROR; -#ifdef DEBUG - fprintf(stderr, "RSAPriv_Create: bad type = %d\n", type); -#endif - return (NSSCKMDCryptoOperation *)NULL; - } - - macErr = SecKeyGetCredentials(privateKey, authType, 0, &creds); - if (noErr != macErr) { - CKMK_MACERR("Getting Credentials for Key", macErr); - *pError = CKR_KEY_HANDLE_INVALID; - return (NSSCKMDCryptoOperation *)NULL; - } - - switch (type) { - case CKMK_DECRYPT: - cssmErr = CSSM_CSP_CreateAsymmetricContext(cspHandle, CSSM_ALGID_RSA, - creds, cssmKey, CSSM_PADDING_PKCS1, &cssmContext); - break; - case CKMK_SIGN: - cssmErr = CSSM_CSP_CreateSignatureContext(cspHandle, CSSM_ALGID_RSA, - creds, cssmKey, &cssmContext); - break; - default: - *pError = CKR_GENERAL_ERROR; -#ifdef DEBUG - fprintf(stderr, "RSAPriv_Create: bad type = %d\n", type); -#endif - return (NSSCKMDCryptoOperation *)NULL; - } - if (noErr != cssmErr) { - CKMK_MACERR("Getting Context for Key", cssmErr); - *pError = CKR_GENERAL_ERROR; - return (NSSCKMDCryptoOperation *)NULL; - } - - iOperation = nss_ZNEW(NULL, ckmkInternalCryptoOperationRSAPriv); - if ((ckmkInternalCryptoOperationRSAPriv *)NULL == iOperation) { - *pError = CKR_HOST_MEMORY; - return (NSSCKMDCryptoOperation *)NULL; - } - iOperation->mdMechanism = mdMechanism; - iOperation->iKey = iKey; - iOperation->cssmContext = cssmContext; - - nsslibc_memcpy(&iOperation->mdOperation, - proto, sizeof(NSSCKMDCryptoOperation)); - iOperation->mdOperation.etc = iOperation; - - return &iOperation->mdOperation; -} - -static void -ckmk_mdCryptoOperationRSAPriv_Destroy( - NSSCKMDCryptoOperation *mdOperation, - NSSCKFWCryptoOperation *fwOperation, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance) -{ - ckmkInternalCryptoOperationRSAPriv *iOperation = - (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc; - - if (iOperation->buffer) { - nssItem_Destroy(iOperation->buffer); - } - if (iOperation->cssmContext) { - CSSM_DeleteContext(iOperation->cssmContext); - } - nss_ZFreeIf(iOperation); - return; -} - -static CK_ULONG -ckmk_mdCryptoOperationRSA_GetFinalLength( - NSSCKMDCryptoOperation *mdOperation, - NSSCKFWCryptoOperation *fwOperation, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_RV *pError) -{ - ckmkInternalCryptoOperationRSAPriv *iOperation = - (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc; - const NSSItem *modulus = - nss_ckmk_FetchAttribute(iOperation->iKey, CKA_MODULUS, pError); - - return modulus->size; -} - -/* - * ckmk_mdCryptoOperationRSADecrypt_GetOperationLength - * we won't know the length until we actually decrypt the - * input block. Since we go to all the work to decrypt the - * the block, we'll save if for when the block is asked for - */ -static CK_ULONG -ckmk_mdCryptoOperationRSADecrypt_GetOperationLength( - NSSCKMDCryptoOperation *mdOperation, - NSSCKFWCryptoOperation *fwOperation, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - const NSSItem *input, - CK_RV *pError) -{ - ckmkInternalCryptoOperationRSAPriv *iOperation = - (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc; - CSSM_DATA cssmInput; - CSSM_DATA cssmOutput = { 0, NULL }; - PRUint32 bytesDecrypted; - CSSM_DATA remainder = { 0, NULL }; - NSSItem output; - CSSM_RETURN cssmErr; - - if (iOperation->buffer) { - return iOperation->buffer->size; - } - - cssmInput.Data = input->data; - cssmInput.Length = input->size; - - cssmErr = CSSM_DecryptData(iOperation->cssmContext, - &cssmInput, 1, &cssmOutput, 1, - &bytesDecrypted, &remainder); - if (CSSM_OK != cssmErr) { - CKMK_MACERR("Decrypt Failed", cssmErr); - *pError = CKR_DATA_INVALID; - return 0; - } - /* we didn't suppy any buffers, so it should all be in remainder */ - output.data = nss_ZNEWARRAY(NULL, char, bytesDecrypted + remainder.Length); - if (NULL == output.data) { - free(cssmOutput.Data); - free(remainder.Data); - *pError = CKR_HOST_MEMORY; - return 0; - } - output.size = bytesDecrypted + remainder.Length; - - if (0 != bytesDecrypted) { - nsslibc_memcpy(output.data, cssmOutput.Data, bytesDecrypted); - free(cssmOutput.Data); - } - if (0 != remainder.Length) { - nsslibc_memcpy(((char *)output.data) + bytesDecrypted, - remainder.Data, remainder.Length); - free(remainder.Data); - } - - iOperation->buffer = nssItem_Duplicate(&output, NULL, NULL); - nss_ZFreeIf(output.data); - if ((NSSItem *)NULL == iOperation->buffer) { - *pError = CKR_HOST_MEMORY; - return 0; - } - - return iOperation->buffer->size; -} - -/* - * ckmk_mdCryptoOperationRSADecrypt_UpdateFinal - * - * NOTE: ckmk_mdCryptoOperationRSADecrypt_GetOperationLength is presumed to - * have been called previously. - */ -static CK_RV -ckmk_mdCryptoOperationRSADecrypt_UpdateFinal( - NSSCKMDCryptoOperation *mdOperation, - NSSCKFWCryptoOperation *fwOperation, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - const NSSItem *input, - NSSItem *output) -{ - ckmkInternalCryptoOperationRSAPriv *iOperation = - (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc; - NSSItem *buffer = iOperation->buffer; - - if ((NSSItem *)NULL == buffer) { - return CKR_GENERAL_ERROR; - } - nsslibc_memcpy(output->data, buffer->data, buffer->size); - output->size = buffer->size; - return CKR_OK; -} - -/* - * ckmk_mdCryptoOperationRSASign_UpdateFinal - * - */ -static CK_RV -ckmk_mdCryptoOperationRSASign_UpdateFinal( - NSSCKMDCryptoOperation *mdOperation, - NSSCKFWCryptoOperation *fwOperation, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - const NSSItem *input, - NSSItem *output) -{ - ckmkInternalCryptoOperationRSAPriv *iOperation = - (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc; - CSSM_DATA cssmInput; - CSSM_DATA cssmOutput = { 0, NULL }; - CSSM_RETURN cssmErr; - - cssmInput.Data = input->data; - cssmInput.Length = input->size; - - cssmErr = CSSM_SignData(iOperation->cssmContext, &cssmInput, 1, - CSSM_ALGID_NONE, &cssmOutput); - if (CSSM_OK != cssmErr) { - CKMK_MACERR("Signed Failed", cssmErr); - return CKR_FUNCTION_FAILED; - } - if (cssmOutput.Length > output->size) { - free(cssmOutput.Data); - return CKR_BUFFER_TOO_SMALL; - } - nsslibc_memcpy(output->data, cssmOutput.Data, cssmOutput.Length); - free(cssmOutput.Data); - output->size = cssmOutput.Length; - - return CKR_OK; -} - -NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation - ckmk_mdCryptoOperationRSADecrypt_proto = { - NULL, /* etc */ - ckmk_mdCryptoOperationRSAPriv_Destroy, - NULL, /* GetFinalLengh - not needed for one shot Decrypt/Encrypt */ - ckmk_mdCryptoOperationRSADecrypt_GetOperationLength, - NULL, /* Final - not needed for one shot operation */ - NULL, /* Update - not needed for one shot operation */ - NULL, /* DigetUpdate - not needed for one shot operation */ - ckmk_mdCryptoOperationRSADecrypt_UpdateFinal, - NULL, /* UpdateCombo - not needed for one shot operation */ - NULL, /* DigetKey - not needed for one shot operation */ - (void *)NULL /* null terminator */ - }; - -NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation - ckmk_mdCryptoOperationRSASign_proto = { - NULL, /* etc */ - ckmk_mdCryptoOperationRSAPriv_Destroy, - ckmk_mdCryptoOperationRSA_GetFinalLength, - NULL, /* GetOperationLengh - not needed for one shot Sign/Verify */ - NULL, /* Final - not needed for one shot operation */ - NULL, /* Update - not needed for one shot operation */ - NULL, /* DigetUpdate - not needed for one shot operation */ - ckmk_mdCryptoOperationRSASign_UpdateFinal, - NULL, /* UpdateCombo - not needed for one shot operation */ - NULL, /* DigetKey - not needed for one shot operation */ - (void *)NULL /* null terminator */ - }; - -/********** NSSCKMDMechansim functions ***********************/ -/* - * ckmk_mdMechanismRSA_Destroy - */ -static void -ckmk_mdMechanismRSA_Destroy( - NSSCKMDMechanism *mdMechanism, - NSSCKFWMechanism *fwMechanism, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance) -{ - nss_ZFreeIf(fwMechanism); -} - -/* - * ckmk_mdMechanismRSA_GetMinKeySize - */ -static CK_ULONG -ckmk_mdMechanismRSA_GetMinKeySize( - NSSCKMDMechanism *mdMechanism, - NSSCKFWMechanism *fwMechanism, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_RV *pError) -{ - return 384; -} - -/* - * ckmk_mdMechanismRSA_GetMaxKeySize - */ -static CK_ULONG -ckmk_mdMechanismRSA_GetMaxKeySize( - NSSCKMDMechanism *mdMechanism, - NSSCKFWMechanism *fwMechanism, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_RV *pError) -{ - return 16384; -} - -/* - * ckmk_mdMechanismRSA_DecryptInit - */ -static NSSCKMDCryptoOperation * -ckmk_mdMechanismRSA_DecryptInit( - NSSCKMDMechanism *mdMechanism, - NSSCKFWMechanism *fwMechanism, - CK_MECHANISM *pMechanism, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - NSSCKMDObject *mdKey, - NSSCKFWObject *fwKey, - CK_RV *pError) -{ - return ckmk_mdCryptoOperationRSAPriv_Create( - &ckmk_mdCryptoOperationRSADecrypt_proto, - mdMechanism, mdKey, CKMK_DECRYPT, pError); -} - -/* - * ckmk_mdMechanismRSA_SignInit - */ -static NSSCKMDCryptoOperation * -ckmk_mdMechanismRSA_SignInit( - NSSCKMDMechanism *mdMechanism, - NSSCKFWMechanism *fwMechanism, - CK_MECHANISM *pMechanism, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - NSSCKMDObject *mdKey, - NSSCKFWObject *fwKey, - CK_RV *pError) -{ - return ckmk_mdCryptoOperationRSAPriv_Create( - &ckmk_mdCryptoOperationRSASign_proto, - mdMechanism, mdKey, CKMK_SIGN, pError); -} - -NSS_IMPLEMENT_DATA const NSSCKMDMechanism - nss_ckmk_mdMechanismRSA = { - (void *)NULL, /* etc */ - ckmk_mdMechanismRSA_Destroy, - ckmk_mdMechanismRSA_GetMinKeySize, - ckmk_mdMechanismRSA_GetMaxKeySize, - NULL, /* GetInHardware - default false */ - NULL, /* EncryptInit - default errs */ - ckmk_mdMechanismRSA_DecryptInit, - NULL, /* DigestInit - default errs*/ - ckmk_mdMechanismRSA_SignInit, - NULL, /* VerifyInit - default errs */ - ckmk_mdMechanismRSA_SignInit, /* SignRecoverInit */ - NULL, /* VerifyRecoverInit - default errs */ - NULL, /* GenerateKey - default errs */ - NULL, /* GenerateKeyPair - default errs */ - NULL, /* GetWrapKeyLength - default errs */ - NULL, /* WrapKey - default errs */ - NULL, /* UnwrapKey - default errs */ - NULL, /* DeriveKey - default errs */ - (void *)NULL /* null terminator */ - }; diff --git a/security/nss/lib/ckfw/nssmkey/msession.c b/security/nss/lib/ckfw/nssmkey/msession.c deleted file mode 100644 index e6a29244a..000000000 --- a/security/nss/lib/ckfw/nssmkey/msession.c +++ /dev/null @@ -1,87 +0,0 @@ -/* 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 "ckmk.h" - -/* - * nssmkey/msession.c - * - * This file implements the NSSCKMDSession object for the - * "nssmkey" cryptoki module. - */ - -static NSSCKMDFindObjects * -ckmk_mdSession_FindObjectsInit( - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulAttributeCount, - CK_RV *pError) -{ - return nss_ckmk_FindObjectsInit(fwSession, pTemplate, ulAttributeCount, pError); -} - -static NSSCKMDObject * -ckmk_mdSession_CreateObject( - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - NSSArena *arena, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulAttributeCount, - CK_RV *pError) -{ - return nss_ckmk_CreateObject(fwSession, pTemplate, ulAttributeCount, pError); -} - -NSS_IMPLEMENT NSSCKMDSession * -nss_ckmk_CreateSession( - NSSCKFWSession *fwSession, - CK_RV *pError) -{ - NSSArena *arena; - NSSCKMDSession *rv; - - arena = NSSCKFWSession_GetArena(fwSession, pError); - if ((NSSArena *)NULL == arena) { - return (NSSCKMDSession *)NULL; - } - - rv = nss_ZNEW(arena, NSSCKMDSession); - if ((NSSCKMDSession *)NULL == rv) { - *pError = CKR_HOST_MEMORY; - return (NSSCKMDSession *)NULL; - } - - /* - * rv was zeroed when allocated, so we only - * need to set the non-zero members. - */ - - rv->etc = (void *)fwSession; - /* rv->Close */ - /* rv->GetDeviceError */ - /* rv->Login */ - /* rv->Logout */ - /* rv->InitPIN */ - /* rv->SetPIN */ - /* rv->GetOperationStateLen */ - /* rv->GetOperationState */ - /* rv->SetOperationState */ - rv->CreateObject = ckmk_mdSession_CreateObject; - /* rv->CopyObject */ - rv->FindObjectsInit = ckmk_mdSession_FindObjectsInit; - /* rv->SeedRandom */ - /* rv->GetRandom */ - /* rv->null */ - - return rv; -} diff --git a/security/nss/lib/ckfw/nssmkey/mslot.c b/security/nss/lib/ckfw/nssmkey/mslot.c deleted file mode 100644 index b2747ff7b..000000000 --- a/security/nss/lib/ckfw/nssmkey/mslot.c +++ /dev/null @@ -1,81 +0,0 @@ -/* 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 "ckmk.h" - -/* - * nssmkey/mslot.c - * - * This file implements the NSSCKMDSlot object for the - * "nssmkey" cryptoki module. - */ - -static NSSUTF8 * -ckmk_mdSlot_GetSlotDescription( - NSSCKMDSlot *mdSlot, - NSSCKFWSlot *fwSlot, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_RV *pError) -{ - return (NSSUTF8 *)nss_ckmk_SlotDescription; -} - -static NSSUTF8 * -ckmk_mdSlot_GetManufacturerID( - NSSCKMDSlot *mdSlot, - NSSCKFWSlot *fwSlot, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_RV *pError) -{ - return (NSSUTF8 *)nss_ckmk_ManufacturerID; -} - -static CK_VERSION -ckmk_mdSlot_GetHardwareVersion( - NSSCKMDSlot *mdSlot, - NSSCKFWSlot *fwSlot, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance) -{ - return nss_ckmk_HardwareVersion; -} - -static CK_VERSION -ckmk_mdSlot_GetFirmwareVersion( - NSSCKMDSlot *mdSlot, - NSSCKFWSlot *fwSlot, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance) -{ - return nss_ckmk_FirmwareVersion; -} - -static NSSCKMDToken * -ckmk_mdSlot_GetToken( - NSSCKMDSlot *mdSlot, - NSSCKFWSlot *fwSlot, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_RV *pError) -{ - return (NSSCKMDToken *)&nss_ckmk_mdToken; -} - -NSS_IMPLEMENT_DATA const NSSCKMDSlot - nss_ckmk_mdSlot = { - (void *)NULL, /* etc */ - NULL, /* Initialize */ - NULL, /* Destroy */ - ckmk_mdSlot_GetSlotDescription, - ckmk_mdSlot_GetManufacturerID, - NULL, /* GetTokenPresent -- defaults to true */ - NULL, /* GetRemovableDevice -- defaults to false */ - NULL, /* GetHardwareSlot -- defaults to false */ - ckmk_mdSlot_GetHardwareVersion, - ckmk_mdSlot_GetFirmwareVersion, - ckmk_mdSlot_GetToken, - (void *)NULL /* null terminator */ - }; diff --git a/security/nss/lib/ckfw/nssmkey/mtoken.c b/security/nss/lib/ckfw/nssmkey/mtoken.c deleted file mode 100644 index e18d61240..000000000 --- a/security/nss/lib/ckfw/nssmkey/mtoken.c +++ /dev/null @@ -1,184 +0,0 @@ -/* 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 "ckmk.h" - -/* - * nssmkey/mtoken.c - * - * This file implements the NSSCKMDToken object for the - * "nssmkey" cryptoki module. - */ - -static NSSUTF8 * -ckmk_mdToken_GetLabel( - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_RV *pError) -{ - return (NSSUTF8 *)nss_ckmk_TokenLabel; -} - -static NSSUTF8 * -ckmk_mdToken_GetManufacturerID( - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_RV *pError) -{ - return (NSSUTF8 *)nss_ckmk_ManufacturerID; -} - -static NSSUTF8 * -ckmk_mdToken_GetModel( - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_RV *pError) -{ - return (NSSUTF8 *)nss_ckmk_TokenModel; -} - -static NSSUTF8 * -ckmk_mdToken_GetSerialNumber( - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_RV *pError) -{ - return (NSSUTF8 *)nss_ckmk_TokenSerialNumber; -} - -static CK_BBOOL -ckmk_mdToken_GetIsWriteProtected( - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance) -{ - return CK_FALSE; -} - -/* fake out Mozilla so we don't try to initialize the token */ -static CK_BBOOL -ckmk_mdToken_GetUserPinInitialized( - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance) -{ - return CK_TRUE; -} - -static CK_VERSION -ckmk_mdToken_GetHardwareVersion( - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance) -{ - return nss_ckmk_HardwareVersion; -} - -static CK_VERSION -ckmk_mdToken_GetFirmwareVersion( - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance) -{ - return nss_ckmk_FirmwareVersion; -} - -static NSSCKMDSession * -ckmk_mdToken_OpenSession( - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - NSSCKFWSession *fwSession, - CK_BBOOL rw, - CK_RV *pError) -{ - return nss_ckmk_CreateSession(fwSession, pError); -} - -static CK_ULONG -ckmk_mdToken_GetMechanismCount( - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance) -{ - return (CK_ULONG)1; -} - -static CK_RV -ckmk_mdToken_GetMechanismTypes( - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_MECHANISM_TYPE types[]) -{ - types[0] = CKM_RSA_PKCS; - return CKR_OK; -} - -static NSSCKMDMechanism * -ckmk_mdToken_GetMechanism( - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_MECHANISM_TYPE which, - CK_RV *pError) -{ - if (which != CKM_RSA_PKCS) { - *pError = CKR_MECHANISM_INVALID; - return (NSSCKMDMechanism *)NULL; - } - return (NSSCKMDMechanism *)&nss_ckmk_mdMechanismRSA; -} - -NSS_IMPLEMENT_DATA const NSSCKMDToken - nss_ckmk_mdToken = { - (void *)NULL, /* etc */ - NULL, /* Setup */ - NULL, /* Invalidate */ - NULL, /* InitToken -- default errs */ - ckmk_mdToken_GetLabel, - ckmk_mdToken_GetManufacturerID, - ckmk_mdToken_GetModel, - ckmk_mdToken_GetSerialNumber, - NULL, /* GetHasRNG -- default is false */ - ckmk_mdToken_GetIsWriteProtected, - NULL, /* GetLoginRequired -- default is false */ - ckmk_mdToken_GetUserPinInitialized, - NULL, /* GetRestoreKeyNotNeeded -- irrelevant */ - NULL, /* GetHasClockOnToken -- default is false */ - NULL, /* GetHasProtectedAuthenticationPath -- default is false */ - NULL, /* GetSupportsDualCryptoOperations -- default is false */ - NULL, /* GetMaxSessionCount -- default is CK_UNAVAILABLE_INFORMATION */ - NULL, /* GetMaxRwSessionCount -- default is CK_UNAVAILABLE_INFORMATION */ - NULL, /* GetMaxPinLen -- irrelevant */ - NULL, /* GetMinPinLen -- irrelevant */ - NULL, /* GetTotalPublicMemory -- default is CK_UNAVAILABLE_INFORMATION */ - NULL, /* GetFreePublicMemory -- default is CK_UNAVAILABLE_INFORMATION */ - NULL, /* GetTotalPrivateMemory -- default is CK_UNAVAILABLE_INFORMATION */ - NULL, /* GetFreePrivateMemory -- default is CK_UNAVAILABLE_INFORMATION */ - ckmk_mdToken_GetHardwareVersion, - ckmk_mdToken_GetFirmwareVersion, - NULL, /* GetUTCTime -- no clock */ - ckmk_mdToken_OpenSession, - ckmk_mdToken_GetMechanismCount, - ckmk_mdToken_GetMechanismTypes, - ckmk_mdToken_GetMechanism, - (void *)NULL /* null terminator */ - }; diff --git a/security/nss/lib/ckfw/nssmkey/nssmkey.def b/security/nss/lib/ckfw/nssmkey/nssmkey.def deleted file mode 100644 index 45d307ff0..000000000 --- a/security/nss/lib/ckfw/nssmkey/nssmkey.def +++ /dev/null @@ -1,26 +0,0 @@ -;+# -;+# 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/. -;+# -;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS -;+# 1. For all unix platforms, the string ";-" means "remove this line" -;+# 2. For all unix platforms, the string " DATA " will be removed from any -;+# line on which it occurs. -;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX. -;+# On AIX, lines containing ";+" will be removed. -;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed. -;+# 5. For all unix platforms, after the above processing has taken place, -;+# all characters after the first ";" on the line will be removed. -;+# And for AIX, the first ";" will also be removed. -;+# This file is passed directly to windows. Since ';' is a comment, all UNIX -;+# directives are hidden behind ";", ";+", and ";-" -;+ -;+NSSMKEY_3.0 { # First release of nssmkey -;+ global: -LIBRARY nssmkey ;- -EXPORTS ;- -C_GetFunctionList; -;+ local: -;+*; -;+}; diff --git a/security/nss/lib/ckfw/nssmkey/nssmkey.h b/security/nss/lib/ckfw/nssmkey/nssmkey.h deleted file mode 100644 index ba58233e6..000000000 --- a/security/nss/lib/ckfw/nssmkey/nssmkey.h +++ /dev/null @@ -1,41 +0,0 @@ -/* 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 NSSMKEY_H -#define NSSMKEY_H - -/* - * NSS CKMK Version numbers. - * - * These are the version numbers for the nssmkey module packaged with - * this release on NSS. To determine the version numbers of the builtin - * module you are using, use the appropriate PKCS #11 calls. - * - * These version numbers detail changes to the PKCS #11 interface. They map - * to the PKCS #11 spec versions. - */ -#define NSS_CKMK_CRYPTOKI_VERSION_MAJOR 2 -#define NSS_CKMK_CRYPTOKI_VERSION_MINOR 20 - -/* These version numbers detail the changes - * to the list of trusted certificates. - * - * NSS_CKMK_LIBRARY_VERSION_MINOR is a CK_BYTE. It's not clear - * whether we may use its full range (0-255) or only 0-99 because - * of the comment in the CK_VERSION type definition. - */ -#define NSS_CKMK_LIBRARY_VERSION_MAJOR 1 -#define NSS_CKMK_LIBRARY_VERSION_MINOR 1 -#define NSS_CKMK_LIBRARY_VERSION "1.1" - -/* These version numbers detail the semantic changes to the ckfw engine. */ -#define NSS_CKMK_HARDWARE_VERSION_MAJOR 1 -#define NSS_CKMK_HARDWARE_VERSION_MINOR 0 - -/* These version numbers detail the semantic changes to ckbi itself - * (new PKCS #11 objects), etc. */ -#define NSS_CKMK_FIRMWARE_VERSION_MAJOR 1 -#define NSS_CKMK_FIRMWARE_VERSION_MINOR 0 - -#endif /* NSSMKEY_H */ diff --git a/security/nss/lib/ckfw/nssmkey/staticobj.c b/security/nss/lib/ckfw/nssmkey/staticobj.c deleted file mode 100644 index 5f3bb7c72..000000000 --- a/security/nss/lib/ckfw/nssmkey/staticobj.c +++ /dev/null @@ -1,36 +0,0 @@ -/* 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 CKMK_H -#include "ckmk.h" -#endif /* CKMK_H */ - -static const CK_TRUST ckt_netscape_valid = CKT_NETSCAPE_VALID; -static const CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE; -static const CK_TRUST ckt_netscape_trusted_delegator = CKT_NETSCAPE_TRUSTED_DELEGATOR; -static const CK_OBJECT_CLASS cko_netscape_trust = CKO_NETSCAPE_TRUST; -static const CK_BBOOL ck_true = CK_TRUE; -static const CK_OBJECT_CLASS cko_data = CKO_DATA; -static const CK_CERTIFICATE_TYPE ckc_x_509 = CKC_X_509; -static const CK_BBOOL ck_false = CK_FALSE; -static const CK_OBJECT_CLASS cko_netscape_builtin_root_list = CKO_NETSCAPE_BUILTIN_ROOT_LIST; - -/* example of a static object */ -static const CK_ATTRIBUTE_TYPE nss_ckmk_types_1[] = { - CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_MODIFIABLE, CKA_LABEL -}; - -static const NSSItem nss_ckmk_items_1[] = { - { (void *)&cko_data, (PRUint32)sizeof(CK_OBJECT_CLASS) }, - { (void *)&ck_true, (PRUint32)sizeof(CK_BBOOL) }, - { (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL) }, - { (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL) }, - { (void *)"Mozilla Mac Key Ring Access", (PRUint32)28 } -}; - -ckmkInternalObject nss_ckmk_data[] = { - { ckmkRaw, { { 5, nss_ckmk_types_1, nss_ckmk_items_1 } }, CKO_DATA, { NULL } }, -}; - -const PRUint32 nss_ckmk_nObjects = 1; diff --git a/security/nss/lib/ckfw/session.c b/security/nss/lib/ckfw/session.c index a3119345c..7efedf403 100644 --- a/security/nss/lib/ckfw/session.c +++ b/security/nss/lib/ckfw/session.c @@ -1419,9 +1419,8 @@ nssCKFWSession_CopyObject( /* use create object */ NSSArena *tmpArena; CK_ATTRIBUTE_PTR newTemplate; - CK_ULONG i, j, n, newLength, k; + CK_ULONG j, n, newLength, k; CK_ATTRIBUTE_TYPE_PTR oldTypes; - NSSCKFWObject *rv; n = nssCKFWObject_GetAttributeCount(fwObject, pError); if ((0 == n) && (CKR_OK != *pError)) { diff --git a/security/nss/lib/dev/devtoken.c b/security/nss/lib/dev/devtoken.c index 0d4c3b5a7..41ffe86da 100644 --- a/security/nss/lib/dev/devtoken.c +++ b/security/nss/lib/dev/devtoken.c @@ -528,7 +528,9 @@ nssToken_ImportCertificate( */ NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize); NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id); - NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname); + if (!rvObject->label && nickname) { + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname); + } NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize); /* reset the mutable attributes on the token */ nssCKObject_SetAttributes(rvObject->handle, diff --git a/security/nss/lib/freebl/Makefile b/security/nss/lib/freebl/Makefile index a4b1a86ae..bff11c7c8 100644 --- a/security/nss/lib/freebl/Makefile +++ b/security/nss/lib/freebl/Makefile @@ -517,13 +517,13 @@ ifndef NSS_DISABLE_CHACHAPOLY ifdef HAVE_INT128_SUPPORT EXTRA_SRCS += Hacl_Poly1305_64.c else - EXTRA_SRCS += poly1305.c + EXTRA_SRCS += Hacl_Poly1305_32.c endif else ifeq ($(CPU_ARCH),aarch64) EXTRA_SRCS += Hacl_Poly1305_64.c else - EXTRA_SRCS += poly1305.c + EXTRA_SRCS += Hacl_Poly1305_32.c endif endif # x86_64 @@ -535,12 +535,16 @@ ifeq (,$(filter-out i386 x386 x86 x86_64 aarch64,$(CPU_ARCH))) # All intel architectures get the 64 bit version # With custom uint128 if necessary (faster than generic 32 bit version). ECL_SRCS += curve25519_64.c - VERIFIED_SRCS += Hacl_Curve25519.c FStar.c + VERIFIED_SRCS += Hacl_Curve25519.c else # All non intel architectures get the generic 32 bit implementation (slow!) ECL_SRCS += curve25519_32.c endif +ifndef HAVE_INT128_SUPPORT + VERIFIED_SRCS += FStar.c +endif + ####################################################################### # (5) Execute "global" rules. (OPTIONAL) # ####################################################################### diff --git a/security/nss/lib/freebl/blake2b.c b/security/nss/lib/freebl/blake2b.c index 4099c67e0..b4a0442c9 100644 --- a/security/nss/lib/freebl/blake2b.c +++ b/security/nss/lib/freebl/blake2b.c @@ -180,7 +180,7 @@ blake2b_Begin(BLAKE2BContext* ctx, uint8_t outlen, const uint8_t* key, return SECSuccess; failure: - PORT_Memset(&ctx, 0, sizeof(ctx)); + PORT_Memset(ctx, 0, sizeof(*ctx)); PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } diff --git a/security/nss/lib/freebl/chacha20poly1305.c b/security/nss/lib/freebl/chacha20poly1305.c index 859d05316..302f0db9e 100644 --- a/security/nss/lib/freebl/chacha20poly1305.c +++ b/security/nss/lib/freebl/chacha20poly1305.c @@ -24,36 +24,60 @@ extern void Hacl_Chacha20_Vec128_chacha20(uint8_t *output, uint8_t *plain, extern void Hacl_Chacha20_chacha20(uint8_t *output, uint8_t *plain, uint32_t len, uint8_t *k, uint8_t *n1, uint32_t ctr); -/* Poly1305Do writes the Poly1305 authenticator of the given additional data - * and ciphertext to |out|. */ #if defined(HAVE_INT128_SUPPORT) && (defined(NSS_X86_OR_X64) || defined(__aarch64__)) /* Use HACL* Poly1305 on 64-bit Intel and ARM */ #include "verified/Hacl_Poly1305_64.h" +#define NSS_POLY1305_64 1 +#define Hacl_Poly1305_update Hacl_Poly1305_64_update +#define Hacl_Poly1305_mk_state Hacl_Poly1305_64_mk_state +#define Hacl_Poly1305_init Hacl_Poly1305_64_init +#define Hacl_Poly1305_finish Hacl_Poly1305_64_finish +typedef Hacl_Impl_Poly1305_64_State_poly1305_state Hacl_Impl_Poly1305_State_poly1305_state; +#else +/* All other platforms get the 32-bit poly1305 HACL* implementation. */ +#include "verified/Hacl_Poly1305_32.h" +#define NSS_POLY1305_32 1 +#define Hacl_Poly1305_update Hacl_Poly1305_32_update +#define Hacl_Poly1305_mk_state Hacl_Poly1305_32_mk_state +#define Hacl_Poly1305_init Hacl_Poly1305_32_init +#define Hacl_Poly1305_finish Hacl_Poly1305_32_finish +typedef Hacl_Impl_Poly1305_32_State_poly1305_state Hacl_Impl_Poly1305_State_poly1305_state; +#endif /* HAVE_INT128_SUPPORT */ static void -Poly1305PadUpdate(Hacl_Impl_Poly1305_64_State_poly1305_state state, +Poly1305PadUpdate(Hacl_Impl_Poly1305_State_poly1305_state state, unsigned char *block, const unsigned char *p, const unsigned int pLen) { unsigned int pRemLen = pLen % 16; - Hacl_Poly1305_64_update(state, (uint8_t *)p, (pLen / 16)); + Hacl_Poly1305_update(state, (uint8_t *)p, (pLen / 16)); if (pRemLen > 0) { memcpy(block, p + (pLen - pRemLen), pRemLen); - Hacl_Poly1305_64_update(state, block, 1); + Hacl_Poly1305_update(state, block, 1); } } +/* Poly1305Do writes the Poly1305 authenticator of the given additional data + * and ciphertext to |out|. */ static void Poly1305Do(unsigned char *out, const unsigned char *ad, unsigned int adLen, const unsigned char *ciphertext, unsigned int ciphertextLen, const unsigned char key[32]) { - uint64_t tmp1[6U] = { 0U }; - Hacl_Impl_Poly1305_64_State_poly1305_state state = - Hacl_Poly1305_64_mk_state(tmp1, tmp1 + 3); +#ifdef NSS_POLY1305_64 + uint64_t stateStack[6U] = { 0U }; + size_t offset = 3; +#elif defined NSS_POLY1305_32 + uint32_t stateStack[10U] = { 0U }; + size_t offset = 5; +#else +#error "This can't happen." +#endif + Hacl_Impl_Poly1305_State_poly1305_state state = + Hacl_Poly1305_mk_state(stateStack, stateStack + offset); unsigned char block[16] = { 0 }; - Hacl_Poly1305_64_init(state, (uint8_t *)key); + Hacl_Poly1305_init(state, (uint8_t *)key); Poly1305PadUpdate(state, block, ad, adLen); memset(block, 0, 16); @@ -68,49 +92,11 @@ Poly1305Do(unsigned char *out, const unsigned char *ad, unsigned int adLen, block[i] = j; } - Hacl_Poly1305_64_update(state, block, 1); - Hacl_Poly1305_64_finish(state, out, (uint8_t *)(key + 16)); + Hacl_Poly1305_update(state, block, 1); + Hacl_Poly1305_finish(state, out, (uint8_t *)(key + 16)); +#undef NSS_POLY1305_64 +#undef NSS_POLY1305_32 } -#else -/* All other platforms get the 32-bit poly1305 reference implementation. */ -#include "poly1305.h" - -static void -Poly1305Do(unsigned char *out, const unsigned char *ad, unsigned int adLen, - const unsigned char *ciphertext, unsigned int ciphertextLen, - const unsigned char key[32]) -{ - poly1305_state state; - unsigned int j; - unsigned char lengthBytes[8]; - static const unsigned char zeros[15]; - unsigned int i; - - Poly1305Init(&state, key); - Poly1305Update(&state, ad, adLen); - if (adLen % 16 > 0) { - Poly1305Update(&state, zeros, 16 - adLen % 16); - } - Poly1305Update(&state, ciphertext, ciphertextLen); - if (ciphertextLen % 16 > 0) { - Poly1305Update(&state, zeros, 16 - ciphertextLen % 16); - } - j = adLen; - for (i = 0; i < sizeof(lengthBytes); i++) { - lengthBytes[i] = j; - j >>= 8; - } - Poly1305Update(&state, lengthBytes, sizeof(lengthBytes)); - j = ciphertextLen; - for (i = 0; i < sizeof(lengthBytes); i++) { - lengthBytes[i] = j; - j >>= 8; - } - Poly1305Update(&state, lengthBytes, sizeof(lengthBytes)); - Poly1305Finish(&state, out); -} - -#endif /* HAVE_INT128_SUPPORT */ #endif /* NSS_DISABLE_CHACHAPOLY */ SECStatus diff --git a/security/nss/lib/freebl/dsa.c b/security/nss/lib/freebl/dsa.c index 9324d306b..aef353967 100644 --- a/security/nss/lib/freebl/dsa.c +++ b/security/nss/lib/freebl/dsa.c @@ -16,14 +16,11 @@ #include "blapi.h" #include "nssilock.h" #include "secitem.h" -#include "blapi.h" +#include "blapit.h" #include "mpi.h" #include "secmpi.h" #include "pqg.h" -/* XXX to be replaced by define in blapit.h */ -#define NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE 2048 - /* * FIPS 186-2 requires result from random output to be reduced mod q when * generating random numbers for DSA. @@ -168,7 +165,7 @@ dsa_NewKeyExtended(const PQGParams *params, const SECItem *seed, return SECFailure; } /* Initialize an arena for the DSA key. */ - arena = PORT_NewArena(NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE); + arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE); if (!arena) { PORT_SetError(SEC_ERROR_NO_MEMORY); return SECFailure; @@ -213,8 +210,9 @@ cleanup: mp_clear(&g); mp_clear(&x); mp_clear(&y); - if (key) + if (key) { PORT_FreeArena(key->params.arena, PR_TRUE); + } if (err) { translate_mpi_error(err); return SECFailure; @@ -321,6 +319,7 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest, mp_int x, k; /* private key & pseudo-random integer */ mp_int r, s; /* tuple (r, s) is signature) */ mp_int t; /* holding tmp values */ + mp_int ar; /* holding blinding values */ mp_err err = MP_OKAY; SECStatus rv = SECSuccess; unsigned int dsa_subprime_len, dsa_signature_len, offset; @@ -364,6 +363,7 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest, MP_DIGITS(&r) = 0; MP_DIGITS(&s) = 0; MP_DIGITS(&t) = 0; + MP_DIGITS(&ar) = 0; CHECK_MPI_OK(mp_init(&p)); CHECK_MPI_OK(mp_init(&q)); CHECK_MPI_OK(mp_init(&g)); @@ -372,6 +372,7 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest, CHECK_MPI_OK(mp_init(&r)); CHECK_MPI_OK(mp_init(&s)); CHECK_MPI_OK(mp_init(&t)); + CHECK_MPI_OK(mp_init(&ar)); /* ** Convert stored PQG and private key into MPI integers. */ @@ -397,14 +398,28 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest, rv = SECFailure; goto cleanup; } - SECITEM_TO_MPINT(t2, &t); /* t <-$ Zq */ + SECITEM_TO_MPINT(t2, &t); /* t <-$ Zq */ + SECITEM_FreeItem(&t2, PR_FALSE); + if (DSA_NewRandom(NULL, &key->params.subPrime, &t2) != SECSuccess) { + PORT_SetError(SEC_ERROR_NEED_RANDOM); + rv = SECFailure; + goto cleanup; + } + SECITEM_TO_MPINT(t2, &ar); /* ar <-$ Zq */ + SECITEM_FreeItem(&t2, PR_FALSE); + + /* Using mp_invmod on k directly would leak bits from k. */ + CHECK_MPI_OK(mp_mul(&k, &ar, &k)); /* k = k * ar */ CHECK_MPI_OK(mp_mulmod(&k, &t, &q, &k)); /* k = k * t mod q */ CHECK_MPI_OK(mp_invmod(&k, &q, &k)); /* k = k**-1 mod q */ CHECK_MPI_OK(mp_mulmod(&k, &t, &q, &k)); /* k = k * t mod q */ SECITEM_TO_MPINT(localDigest, &s); /* s = HASH(M) */ - CHECK_MPI_OK(mp_mulmod(&x, &r, &q, &x)); /* x = x * r mod q */ - CHECK_MPI_OK(mp_addmod(&s, &x, &q, &s)); /* s = s + x mod q */ - CHECK_MPI_OK(mp_mulmod(&s, &k, &q, &s)); /* s = s * k mod q */ + /* To avoid leaking secret bits here the addition is blinded. */ + CHECK_MPI_OK(mp_mul(&x, &ar, &x)); /* x = x * ar */ + CHECK_MPI_OK(mp_mulmod(&x, &r, &q, &x)); /* x = x * r mod q */ + CHECK_MPI_OK(mp_mulmod(&s, &ar, &q, &t)); /* t = s * ar mod q */ + CHECK_MPI_OK(mp_add(&t, &x, &s)); /* s = t + x */ + CHECK_MPI_OK(mp_mulmod(&s, &k, &q, &s)); /* s = s * k mod q */ /* ** verify r != 0 and s != 0 ** mentioned as optional in FIPS 186-1. @@ -438,7 +453,7 @@ cleanup: mp_clear(&r); mp_clear(&s); mp_clear(&t); - SECITEM_FreeItem(&t2, PR_FALSE); + mp_clear(&ar); if (err) { translate_mpi_error(err); rv = SECFailure; diff --git a/security/nss/lib/freebl/ec.c b/security/nss/lib/freebl/ec.c index b28815ade..6468a10d6 100644 --- a/security/nss/lib/freebl/ec.c +++ b/security/nss/lib/freebl/ec.c @@ -653,6 +653,7 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, mp_int r, s; /* tuple (r, s) is the signature */ mp_int t; /* holding tmp values */ mp_int n; + mp_int ar; /* blinding value */ mp_err err = MP_OKAY; ECParams *ecParams = NULL; SECItem kGpoint = { siBuffer, NULL, 0 }; @@ -674,6 +675,7 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, MP_DIGITS(&s) = 0; MP_DIGITS(&n) = 0; MP_DIGITS(&t) = 0; + MP_DIGITS(&ar) = 0; /* Check args */ if (!key || !signature || !digest || !kb || (kblen < 0)) { @@ -700,6 +702,7 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, CHECK_MPI_OK(mp_init(&s)); CHECK_MPI_OK(mp_init(&n)); CHECK_MPI_OK(mp_init(&t)); + CHECK_MPI_OK(mp_init(&ar)); SECITEM_TO_MPINT(ecParams->order, &n); SECITEM_TO_MPINT(key->privateValue, &d); @@ -815,12 +818,25 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, goto cleanup; } CHECK_MPI_OK(mp_read_unsigned_octets(&t, t2, 2 * ecParams->order.len)); /* t <-$ Zn */ - CHECK_MPI_OK(mp_mulmod(&k, &t, &n, &k)); /* k = k * t mod n */ - CHECK_MPI_OK(mp_invmod(&k, &n, &k)); /* k = k**-1 mod n */ - CHECK_MPI_OK(mp_mulmod(&k, &t, &n, &k)); /* k = k * t mod n */ - CHECK_MPI_OK(mp_mulmod(&d, &r, &n, &d)); /* d = d * r mod n */ - CHECK_MPI_OK(mp_addmod(&s, &d, &n, &s)); /* s = s + d mod n */ - CHECK_MPI_OK(mp_mulmod(&s, &k, &n, &s)); /* s = s * k mod n */ + PORT_Memset(t2, 0, 2 * ecParams->order.len); + if (RNG_GenerateGlobalRandomBytes(t2, 2 * ecParams->order.len) != SECSuccess) { + PORT_SetError(SEC_ERROR_NEED_RANDOM); + rv = SECFailure; + goto cleanup; + } + CHECK_MPI_OK(mp_read_unsigned_octets(&ar, t2, 2 * ecParams->order.len)); /* ar <-$ Zn */ + + /* Using mp_invmod on k directly would leak bits from k. */ + CHECK_MPI_OK(mp_mul(&k, &ar, &k)); /* k = k * ar */ + CHECK_MPI_OK(mp_mulmod(&k, &t, &n, &k)); /* k = k * t mod n */ + CHECK_MPI_OK(mp_invmod(&k, &n, &k)); /* k = k**-1 mod n */ + CHECK_MPI_OK(mp_mulmod(&k, &t, &n, &k)); /* k = k * t mod n */ + /* To avoid leaking secret bits here the addition is blinded. */ + CHECK_MPI_OK(mp_mul(&d, &ar, &t)); /* t = d * ar */ + CHECK_MPI_OK(mp_mulmod(&t, &r, &n, &d)); /* d = t * r mod n */ + CHECK_MPI_OK(mp_mulmod(&s, &ar, &n, &t)); /* t = s * ar mod n */ + CHECK_MPI_OK(mp_add(&t, &d, &s)); /* s = t + d */ + CHECK_MPI_OK(mp_mulmod(&s, &k, &n, &s)); /* s = s * k mod n */ #if EC_DEBUG mp_todecimal(&s, mpstr); @@ -858,6 +874,7 @@ cleanup: mp_clear(&s); mp_clear(&n); mp_clear(&t); + mp_clear(&ar); if (t2) { PORT_Free(t2); diff --git a/security/nss/lib/freebl/freebl.gyp b/security/nss/lib/freebl/freebl.gyp index fae56f709..004807483 100644 --- a/security/nss/lib/freebl/freebl.gyp +++ b/security/nss/lib/freebl/freebl.gyp @@ -272,28 +272,15 @@ }, }], [ 'cc_use_gnu_ld==1 and OS=="win" and target_arch=="x64"', { + # mingw x64 'defines': [ 'MP_IS_LITTLE_ENDIAN', - 'NSS_BEVAND_ARCFOUR', - 'MPI_AMD64', - 'MP_ASSEMBLY_MULTIPLY', - 'NSS_USE_COMBA', - 'USE_HW_AES', - 'INTEL_GCM', ], }], - [ 'OS!="win"', { - 'conditions': [ - [ 'target_arch=="x64" or target_arch=="arm64" or target_arch=="aarch64"', { - 'defines': [ - # The Makefile does version-tests on GCC, but we're not doing that here. - 'HAVE_INT128_SUPPORT', - ], - }, { - 'defines': [ - 'KRML_NOUINT128', - ], - }], + [ 'have_int128_support==1', { + 'defines': [ + # The Makefile does version-tests on GCC, but we're not doing that here. + 'HAVE_INT128_SUPPORT', ], }, { 'defines': [ @@ -355,5 +342,18 @@ }, 'variables': { 'module': 'nss', + 'conditions': [ + [ 'OS!="win"', { + 'conditions': [ + [ 'target_arch=="x64" or target_arch=="arm64" or target_arch=="aarch64"', { + 'have_int128_support%': 1, + }, { + 'have_int128_support%': 0, + }], + ], + }, { + 'have_int128_support%': 0, + }], + ], } } diff --git a/security/nss/lib/freebl/freebl_base.gypi b/security/nss/lib/freebl/freebl_base.gypi index ebd1018d8..1372994f4 100644 --- a/security/nss/lib/freebl/freebl_base.gypi +++ b/security/nss/lib/freebl/freebl_base.gypi @@ -59,7 +59,7 @@ 'sha_fast.c', 'shvfy.c', 'sysrand.c', - 'tlsprfalg.c' + 'tlsprfalg.c', ], 'conditions': [ [ 'OS=="linux" or OS=="android"', { @@ -122,6 +122,11 @@ 'intel-gcm-x86-masm.asm', ], }], + [ 'cc_use_gnu_ld==1', { + # mingw + 'sources': [ + ], + }], [ 'cc_is_clang!=1', { # MSVC 'sources': [ @@ -135,7 +140,6 @@ # All intel and 64-bit ARM architectures get the 64 bit version. 'ecl/curve25519_64.c', 'verified/Hacl_Curve25519.c', - 'verified/FStar.c', ], }, { 'sources': [ @@ -167,7 +171,7 @@ }, { # !Windows & !x64 & !arm64 & !aarch64 'sources': [ - 'poly1305.c', + 'verified/Hacl_Poly1305_32.c', ], }], ], @@ -176,7 +180,7 @@ }, { # Windows 'sources': [ - 'poly1305.c', + 'verified/Hacl_Poly1305_32.c', ], }], ], @@ -215,6 +219,9 @@ }], ], }], + [ 'have_int128_support==0', { + 'sources': [ 'verified/FStar.c' ], + }], ], 'ldflags': [ '-Wl,-Bsymbolic' diff --git a/security/nss/lib/freebl/loader.c b/security/nss/lib/freebl/loader.c index fe5e0a668..6d200e6dd 100644 --- a/security/nss/lib/freebl/loader.c +++ b/security/nss/lib/freebl/loader.c @@ -2164,12 +2164,12 @@ BLAKE2B_NewContext(void) } void -BLAKE2B_DestroyContext(BLAKE2BContext *BLAKE2BContext, PRBool freeit) +BLAKE2B_DestroyContext(BLAKE2BContext *ctx, PRBool freeit) { if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) { return; } - (vector->p_BLAKE2B_DestroyContext)(BLAKE2BContext, freeit); + (vector->p_BLAKE2B_DestroyContext)(ctx, freeit); } SECStatus diff --git a/security/nss/lib/freebl/mpi/mpi.c b/security/nss/lib/freebl/mpi/mpi.c index ae404019d..8c893fb5f 100644 --- a/security/nss/lib/freebl/mpi/mpi.c +++ b/security/nss/lib/freebl/mpi/mpi.c @@ -2657,10 +2657,10 @@ mp_toradix(mp_int *mp, char *str, int radix) /* Reverse the digits and sign indicator */ ix = 0; while (ix < pos) { - char tmp = str[ix]; + char tmpc = str[ix]; str[ix] = str[pos]; - str[pos] = tmp; + str[pos] = tmpc; ++ix; --pos; } @@ -3313,13 +3313,14 @@ s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r) /* could check for power of 2 here, but mp_div_d does that. */ if (MP_USED(mp) == 1) { mp_digit n = MP_DIGIT(mp, 0); - mp_digit rem; + mp_digit remdig; q = n / d; - rem = n % d; + remdig = n % d; MP_DIGIT(mp, 0) = q; - if (r) - *r = rem; + if (r) { + *r = remdig; + } return MP_OKAY; } diff --git a/security/nss/lib/freebl/poly1305-donna-x64-sse2-incremental-source.c b/security/nss/lib/freebl/poly1305-donna-x64-sse2-incremental-source.c deleted file mode 100644 index 3c803c167..000000000 --- a/security/nss/lib/freebl/poly1305-donna-x64-sse2-incremental-source.c +++ /dev/null @@ -1,881 +0,0 @@ -/* 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/. */ - -/* This implementation of poly1305 is by Andrew Moon - * (https://github.com/floodyberry/poly1305-donna) and released as public - * domain. It implements SIMD vectorization based on the algorithm described in - * http://cr.yp.to/papers.html#neoncrypto. Unrolled to 2 powers, i.e. 64 byte - * block size. */ - -#include <emmintrin.h> -#include <stdint.h> - -#include "poly1305.h" -#include "blapii.h" - -#define ALIGN(x) __attribute__((aligned(x))) -#define INLINE inline -#define U8TO64_LE(m) (*(uint64_t *)(m)) -#define U8TO32_LE(m) (*(uint32_t *)(m)) -#define U64TO8_LE(m, v) (*(uint64_t *)(m)) = v - -typedef __m128i xmmi; -typedef unsigned __int128 uint128_t; - -static const uint32_t ALIGN(16) poly1305_x64_sse2_message_mask[4] = { (1 << 26) - 1, 0, (1 << 26) - 1, 0 }; -static const uint32_t ALIGN(16) poly1305_x64_sse2_5[4] = { 5, 0, 5, 0 }; -static const uint32_t ALIGN(16) poly1305_x64_sse2_1shl128[4] = { (1 << 24), 0, (1 << 24), 0 }; - -static uint128_t INLINE -add128(uint128_t a, uint128_t b) -{ - return a + b; -} - -static uint128_t INLINE -add128_64(uint128_t a, uint64_t b) -{ - return a + b; -} - -static uint128_t INLINE -mul64x64_128(uint64_t a, uint64_t b) -{ - return (uint128_t)a * b; -} - -static uint64_t INLINE -lo128(uint128_t a) -{ - return (uint64_t)a; -} - -static uint64_t INLINE -shr128(uint128_t v, const int shift) -{ - return (uint64_t)(v >> shift); -} - -static uint64_t INLINE -shr128_pair(uint64_t hi, uint64_t lo, const int shift) -{ - return (uint64_t)((((uint128_t)hi << 64) | lo) >> shift); -} - -typedef struct poly1305_power_t { - union { - xmmi v; - uint64_t u[2]; - uint32_t d[4]; - } R20, R21, R22, R23, R24, S21, S22, S23, S24; -} poly1305_power; - -typedef struct poly1305_state_internal_t { - poly1305_power P[2]; /* 288 bytes, top 32 bit halves unused = 144 bytes of free storage */ - union { - xmmi H[5]; /* 80 bytes */ - uint64_t HH[10]; - }; - /* uint64_t r0,r1,r2; [24 bytes] */ - /* uint64_t pad0,pad1; [16 bytes] */ - uint64_t started; /* 8 bytes */ - uint64_t leftover; /* 8 bytes */ - uint8_t buffer[64]; /* 64 bytes */ -} poly1305_state_internal; /* 448 bytes total + 63 bytes for alignment = 511 bytes raw */ - -static poly1305_state_internal INLINE - * - poly1305_aligned_state(poly1305_state *state) -{ - return (poly1305_state_internal *)(((uint64_t)state + 63) & ~63); -} - -/* copy 0-63 bytes */ -static void INLINE NO_SANITIZE_ALIGNMENT -poly1305_block_copy(uint8_t *dst, const uint8_t *src, size_t bytes) -{ - size_t offset = src - dst; - if (bytes & 32) { - _mm_storeu_si128((xmmi *)(dst + 0), _mm_loadu_si128((xmmi *)(dst + offset + 0))); - _mm_storeu_si128((xmmi *)(dst + 16), _mm_loadu_si128((xmmi *)(dst + offset + 16))); - dst += 32; - } - if (bytes & 16) { - _mm_storeu_si128((xmmi *)dst, _mm_loadu_si128((xmmi *)(dst + offset))); - dst += 16; - } - if (bytes & 8) { - *(uint64_t *)dst = *(uint64_t *)(dst + offset); - dst += 8; - } - if (bytes & 4) { - *(uint32_t *)dst = *(uint32_t *)(dst + offset); - dst += 4; - } - if (bytes & 2) { - *(uint16_t *)dst = *(uint16_t *)(dst + offset); - dst += 2; - } - if (bytes & 1) { - *(uint8_t *)dst = *(uint8_t *)(dst + offset); - } -} - -/* zero 0-15 bytes */ -static void INLINE -poly1305_block_zero(uint8_t *dst, size_t bytes) -{ - if (bytes & 8) { - *(uint64_t *)dst = 0; - dst += 8; - } - if (bytes & 4) { - *(uint32_t *)dst = 0; - dst += 4; - } - if (bytes & 2) { - *(uint16_t *)dst = 0; - dst += 2; - } - if (bytes & 1) { - *(uint8_t *)dst = 0; - } -} - -static size_t INLINE -poly1305_min(size_t a, size_t b) -{ - return (a < b) ? a : b; -} - -void -Poly1305Init(poly1305_state *state, const unsigned char key[32]) -{ - poly1305_state_internal *st = poly1305_aligned_state(state); - poly1305_power *p; - uint64_t r0, r1, r2; - uint64_t t0, t1; - - /* clamp key */ - t0 = U8TO64_LE(key + 0); - t1 = U8TO64_LE(key + 8); - r0 = t0 & 0xffc0fffffff; - t0 >>= 44; - t0 |= t1 << 20; - r1 = t0 & 0xfffffc0ffff; - t1 >>= 24; - r2 = t1 & 0x00ffffffc0f; - - /* store r in un-used space of st->P[1] */ - p = &st->P[1]; - p->R20.d[1] = (uint32_t)(r0); - p->R20.d[3] = (uint32_t)(r0 >> 32); - p->R21.d[1] = (uint32_t)(r1); - p->R21.d[3] = (uint32_t)(r1 >> 32); - p->R22.d[1] = (uint32_t)(r2); - p->R22.d[3] = (uint32_t)(r2 >> 32); - - /* store pad */ - p->R23.d[1] = U8TO32_LE(key + 16); - p->R23.d[3] = U8TO32_LE(key + 20); - p->R24.d[1] = U8TO32_LE(key + 24); - p->R24.d[3] = U8TO32_LE(key + 28); - - /* H = 0 */ - st->H[0] = _mm_setzero_si128(); - st->H[1] = _mm_setzero_si128(); - st->H[2] = _mm_setzero_si128(); - st->H[3] = _mm_setzero_si128(); - st->H[4] = _mm_setzero_si128(); - - st->started = 0; - st->leftover = 0; -} - -static void -poly1305_first_block(poly1305_state_internal *st, const uint8_t *m) -{ - const xmmi MMASK = _mm_load_si128((xmmi *)poly1305_x64_sse2_message_mask); - const xmmi FIVE = _mm_load_si128((xmmi *)poly1305_x64_sse2_5); - const xmmi HIBIT = _mm_load_si128((xmmi *)poly1305_x64_sse2_1shl128); - xmmi T5, T6; - poly1305_power *p; - uint128_t d[3]; - uint64_t r0, r1, r2; - uint64_t r20, r21, r22, s22; - uint64_t pad0, pad1; - uint64_t c; - uint64_t i; - - /* pull out stored info */ - p = &st->P[1]; - - r0 = ((uint64_t)p->R20.d[3] << 32) | (uint64_t)p->R20.d[1]; - r1 = ((uint64_t)p->R21.d[3] << 32) | (uint64_t)p->R21.d[1]; - r2 = ((uint64_t)p->R22.d[3] << 32) | (uint64_t)p->R22.d[1]; - pad0 = ((uint64_t)p->R23.d[3] << 32) | (uint64_t)p->R23.d[1]; - pad1 = ((uint64_t)p->R24.d[3] << 32) | (uint64_t)p->R24.d[1]; - - /* compute powers r^2,r^4 */ - r20 = r0; - r21 = r1; - r22 = r2; - for (i = 0; i < 2; i++) { - s22 = r22 * (5 << 2); - - d[0] = add128(mul64x64_128(r20, r20), mul64x64_128(r21 * 2, s22)); - d[1] = add128(mul64x64_128(r22, s22), mul64x64_128(r20 * 2, r21)); - d[2] = add128(mul64x64_128(r21, r21), mul64x64_128(r22 * 2, r20)); - - r20 = lo128(d[0]) & 0xfffffffffff; - c = shr128(d[0], 44); - d[1] = add128_64(d[1], c); - r21 = lo128(d[1]) & 0xfffffffffff; - c = shr128(d[1], 44); - d[2] = add128_64(d[2], c); - r22 = lo128(d[2]) & 0x3ffffffffff; - c = shr128(d[2], 42); - r20 += c * 5; - c = (r20 >> 44); - r20 = r20 & 0xfffffffffff; - r21 += c; - - p->R20.v = _mm_shuffle_epi32(_mm_cvtsi32_si128((uint32_t)(r20)&0x3ffffff), _MM_SHUFFLE(1, 0, 1, 0)); - p->R21.v = _mm_shuffle_epi32(_mm_cvtsi32_si128((uint32_t)((r20 >> 26) | (r21 << 18)) & 0x3ffffff), _MM_SHUFFLE(1, 0, 1, 0)); - p->R22.v = _mm_shuffle_epi32(_mm_cvtsi32_si128((uint32_t)((r21 >> 8)) & 0x3ffffff), _MM_SHUFFLE(1, 0, 1, 0)); - p->R23.v = _mm_shuffle_epi32(_mm_cvtsi32_si128((uint32_t)((r21 >> 34) | (r22 << 10)) & 0x3ffffff), _MM_SHUFFLE(1, 0, 1, 0)); - p->R24.v = _mm_shuffle_epi32(_mm_cvtsi32_si128((uint32_t)((r22 >> 16))), _MM_SHUFFLE(1, 0, 1, 0)); - p->S21.v = _mm_mul_epu32(p->R21.v, FIVE); - p->S22.v = _mm_mul_epu32(p->R22.v, FIVE); - p->S23.v = _mm_mul_epu32(p->R23.v, FIVE); - p->S24.v = _mm_mul_epu32(p->R24.v, FIVE); - p--; - } - - /* put saved info back */ - p = &st->P[1]; - p->R20.d[1] = (uint32_t)(r0); - p->R20.d[3] = (uint32_t)(r0 >> 32); - p->R21.d[1] = (uint32_t)(r1); - p->R21.d[3] = (uint32_t)(r1 >> 32); - p->R22.d[1] = (uint32_t)(r2); - p->R22.d[3] = (uint32_t)(r2 >> 32); - p->R23.d[1] = (uint32_t)(pad0); - p->R23.d[3] = (uint32_t)(pad0 >> 32); - p->R24.d[1] = (uint32_t)(pad1); - p->R24.d[3] = (uint32_t)(pad1 >> 32); - - /* H = [Mx,My] */ - T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 0)), _mm_loadl_epi64((xmmi *)(m + 16))); - T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 8)), _mm_loadl_epi64((xmmi *)(m + 24))); - st->H[0] = _mm_and_si128(MMASK, T5); - st->H[1] = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26)); - T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12)); - st->H[2] = _mm_and_si128(MMASK, T5); - st->H[3] = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26)); - st->H[4] = _mm_or_si128(_mm_srli_epi64(T6, 40), HIBIT); -} - -static void -poly1305_blocks(poly1305_state_internal *st, const uint8_t *m, size_t bytes) -{ - const xmmi MMASK = _mm_load_si128((xmmi *)poly1305_x64_sse2_message_mask); - const xmmi FIVE = _mm_load_si128((xmmi *)poly1305_x64_sse2_5); - const xmmi HIBIT = _mm_load_si128((xmmi *)poly1305_x64_sse2_1shl128); - - poly1305_power *p; - xmmi H0, H1, H2, H3, H4; - xmmi T0, T1, T2, T3, T4, T5, T6; - xmmi M0, M1, M2, M3, M4; - xmmi C1, C2; - - H0 = st->H[0]; - H1 = st->H[1]; - H2 = st->H[2]; - H3 = st->H[3]; - H4 = st->H[4]; - - while (bytes >= 64) { - /* H *= [r^4,r^4] */ - p = &st->P[0]; - T0 = _mm_mul_epu32(H0, p->R20.v); - T1 = _mm_mul_epu32(H0, p->R21.v); - T2 = _mm_mul_epu32(H0, p->R22.v); - T3 = _mm_mul_epu32(H0, p->R23.v); - T4 = _mm_mul_epu32(H0, p->R24.v); - T5 = _mm_mul_epu32(H1, p->S24.v); - T6 = _mm_mul_epu32(H1, p->R20.v); - T0 = _mm_add_epi64(T0, T5); - T1 = _mm_add_epi64(T1, T6); - T5 = _mm_mul_epu32(H2, p->S23.v); - T6 = _mm_mul_epu32(H2, p->S24.v); - T0 = _mm_add_epi64(T0, T5); - T1 = _mm_add_epi64(T1, T6); - T5 = _mm_mul_epu32(H3, p->S22.v); - T6 = _mm_mul_epu32(H3, p->S23.v); - T0 = _mm_add_epi64(T0, T5); - T1 = _mm_add_epi64(T1, T6); - T5 = _mm_mul_epu32(H4, p->S21.v); - T6 = _mm_mul_epu32(H4, p->S22.v); - T0 = _mm_add_epi64(T0, T5); - T1 = _mm_add_epi64(T1, T6); - T5 = _mm_mul_epu32(H1, p->R21.v); - T6 = _mm_mul_epu32(H1, p->R22.v); - T2 = _mm_add_epi64(T2, T5); - T3 = _mm_add_epi64(T3, T6); - T5 = _mm_mul_epu32(H2, p->R20.v); - T6 = _mm_mul_epu32(H2, p->R21.v); - T2 = _mm_add_epi64(T2, T5); - T3 = _mm_add_epi64(T3, T6); - T5 = _mm_mul_epu32(H3, p->S24.v); - T6 = _mm_mul_epu32(H3, p->R20.v); - T2 = _mm_add_epi64(T2, T5); - T3 = _mm_add_epi64(T3, T6); - T5 = _mm_mul_epu32(H4, p->S23.v); - T6 = _mm_mul_epu32(H4, p->S24.v); - T2 = _mm_add_epi64(T2, T5); - T3 = _mm_add_epi64(T3, T6); - T5 = _mm_mul_epu32(H1, p->R23.v); - T4 = _mm_add_epi64(T4, T5); - T5 = _mm_mul_epu32(H2, p->R22.v); - T4 = _mm_add_epi64(T4, T5); - T5 = _mm_mul_epu32(H3, p->R21.v); - T4 = _mm_add_epi64(T4, T5); - T5 = _mm_mul_epu32(H4, p->R20.v); - T4 = _mm_add_epi64(T4, T5); - - /* H += [Mx,My]*[r^2,r^2] */ - T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 0)), _mm_loadl_epi64((xmmi *)(m + 16))); - T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 8)), _mm_loadl_epi64((xmmi *)(m + 24))); - M0 = _mm_and_si128(MMASK, T5); - M1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26)); - T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12)); - M2 = _mm_and_si128(MMASK, T5); - M3 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26)); - M4 = _mm_or_si128(_mm_srli_epi64(T6, 40), HIBIT); - - p = &st->P[1]; - T5 = _mm_mul_epu32(M0, p->R20.v); - T6 = _mm_mul_epu32(M0, p->R21.v); - T0 = _mm_add_epi64(T0, T5); - T1 = _mm_add_epi64(T1, T6); - T5 = _mm_mul_epu32(M1, p->S24.v); - T6 = _mm_mul_epu32(M1, p->R20.v); - T0 = _mm_add_epi64(T0, T5); - T1 = _mm_add_epi64(T1, T6); - T5 = _mm_mul_epu32(M2, p->S23.v); - T6 = _mm_mul_epu32(M2, p->S24.v); - T0 = _mm_add_epi64(T0, T5); - T1 = _mm_add_epi64(T1, T6); - T5 = _mm_mul_epu32(M3, p->S22.v); - T6 = _mm_mul_epu32(M3, p->S23.v); - T0 = _mm_add_epi64(T0, T5); - T1 = _mm_add_epi64(T1, T6); - T5 = _mm_mul_epu32(M4, p->S21.v); - T6 = _mm_mul_epu32(M4, p->S22.v); - T0 = _mm_add_epi64(T0, T5); - T1 = _mm_add_epi64(T1, T6); - T5 = _mm_mul_epu32(M0, p->R22.v); - T6 = _mm_mul_epu32(M0, p->R23.v); - T2 = _mm_add_epi64(T2, T5); - T3 = _mm_add_epi64(T3, T6); - T5 = _mm_mul_epu32(M1, p->R21.v); - T6 = _mm_mul_epu32(M1, p->R22.v); - T2 = _mm_add_epi64(T2, T5); - T3 = _mm_add_epi64(T3, T6); - T5 = _mm_mul_epu32(M2, p->R20.v); - T6 = _mm_mul_epu32(M2, p->R21.v); - T2 = _mm_add_epi64(T2, T5); - T3 = _mm_add_epi64(T3, T6); - T5 = _mm_mul_epu32(M3, p->S24.v); - T6 = _mm_mul_epu32(M3, p->R20.v); - T2 = _mm_add_epi64(T2, T5); - T3 = _mm_add_epi64(T3, T6); - T5 = _mm_mul_epu32(M4, p->S23.v); - T6 = _mm_mul_epu32(M4, p->S24.v); - T2 = _mm_add_epi64(T2, T5); - T3 = _mm_add_epi64(T3, T6); - T5 = _mm_mul_epu32(M0, p->R24.v); - T4 = _mm_add_epi64(T4, T5); - T5 = _mm_mul_epu32(M1, p->R23.v); - T4 = _mm_add_epi64(T4, T5); - T5 = _mm_mul_epu32(M2, p->R22.v); - T4 = _mm_add_epi64(T4, T5); - T5 = _mm_mul_epu32(M3, p->R21.v); - T4 = _mm_add_epi64(T4, T5); - T5 = _mm_mul_epu32(M4, p->R20.v); - T4 = _mm_add_epi64(T4, T5); - - /* H += [Mx,My] */ - T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 32)), _mm_loadl_epi64((xmmi *)(m + 48))); - T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 40)), _mm_loadl_epi64((xmmi *)(m + 56))); - M0 = _mm_and_si128(MMASK, T5); - M1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26)); - T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12)); - M2 = _mm_and_si128(MMASK, T5); - M3 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26)); - M4 = _mm_or_si128(_mm_srli_epi64(T6, 40), HIBIT); - - T0 = _mm_add_epi64(T0, M0); - T1 = _mm_add_epi64(T1, M1); - T2 = _mm_add_epi64(T2, M2); - T3 = _mm_add_epi64(T3, M3); - T4 = _mm_add_epi64(T4, M4); - - /* reduce */ - C1 = _mm_srli_epi64(T0, 26); - C2 = _mm_srli_epi64(T3, 26); - T0 = _mm_and_si128(T0, MMASK); - T3 = _mm_and_si128(T3, MMASK); - T1 = _mm_add_epi64(T1, C1); - T4 = _mm_add_epi64(T4, C2); - C1 = _mm_srli_epi64(T1, 26); - C2 = _mm_srli_epi64(T4, 26); - T1 = _mm_and_si128(T1, MMASK); - T4 = _mm_and_si128(T4, MMASK); - T2 = _mm_add_epi64(T2, C1); - T0 = _mm_add_epi64(T0, _mm_mul_epu32(C2, FIVE)); - C1 = _mm_srli_epi64(T2, 26); - C2 = _mm_srli_epi64(T0, 26); - T2 = _mm_and_si128(T2, MMASK); - T0 = _mm_and_si128(T0, MMASK); - T3 = _mm_add_epi64(T3, C1); - T1 = _mm_add_epi64(T1, C2); - C1 = _mm_srli_epi64(T3, 26); - T3 = _mm_and_si128(T3, MMASK); - T4 = _mm_add_epi64(T4, C1); - - /* H = (H*[r^4,r^4] + [Mx,My]*[r^2,r^2] + [Mx,My]) */ - H0 = T0; - H1 = T1; - H2 = T2; - H3 = T3; - H4 = T4; - - m += 64; - bytes -= 64; - } - - st->H[0] = H0; - st->H[1] = H1; - st->H[2] = H2; - st->H[3] = H3; - st->H[4] = H4; -} - -static size_t -poly1305_combine(poly1305_state_internal *st, const uint8_t *m, size_t bytes) -{ - const xmmi MMASK = _mm_load_si128((xmmi *)poly1305_x64_sse2_message_mask); - const xmmi HIBIT = _mm_load_si128((xmmi *)poly1305_x64_sse2_1shl128); - const xmmi FIVE = _mm_load_si128((xmmi *)poly1305_x64_sse2_5); - - poly1305_power *p; - xmmi H0, H1, H2, H3, H4; - xmmi M0, M1, M2, M3, M4; - xmmi T0, T1, T2, T3, T4, T5, T6; - xmmi C1, C2; - - uint64_t r0, r1, r2; - uint64_t t0, t1, t2, t3, t4; - uint64_t c; - size_t consumed = 0; - - H0 = st->H[0]; - H1 = st->H[1]; - H2 = st->H[2]; - H3 = st->H[3]; - H4 = st->H[4]; - - /* p = [r^2,r^2] */ - p = &st->P[1]; - - if (bytes >= 32) { - /* H *= [r^2,r^2] */ - T0 = _mm_mul_epu32(H0, p->R20.v); - T1 = _mm_mul_epu32(H0, p->R21.v); - T2 = _mm_mul_epu32(H0, p->R22.v); - T3 = _mm_mul_epu32(H0, p->R23.v); - T4 = _mm_mul_epu32(H0, p->R24.v); - T5 = _mm_mul_epu32(H1, p->S24.v); - T6 = _mm_mul_epu32(H1, p->R20.v); - T0 = _mm_add_epi64(T0, T5); - T1 = _mm_add_epi64(T1, T6); - T5 = _mm_mul_epu32(H2, p->S23.v); - T6 = _mm_mul_epu32(H2, p->S24.v); - T0 = _mm_add_epi64(T0, T5); - T1 = _mm_add_epi64(T1, T6); - T5 = _mm_mul_epu32(H3, p->S22.v); - T6 = _mm_mul_epu32(H3, p->S23.v); - T0 = _mm_add_epi64(T0, T5); - T1 = _mm_add_epi64(T1, T6); - T5 = _mm_mul_epu32(H4, p->S21.v); - T6 = _mm_mul_epu32(H4, p->S22.v); - T0 = _mm_add_epi64(T0, T5); - T1 = _mm_add_epi64(T1, T6); - T5 = _mm_mul_epu32(H1, p->R21.v); - T6 = _mm_mul_epu32(H1, p->R22.v); - T2 = _mm_add_epi64(T2, T5); - T3 = _mm_add_epi64(T3, T6); - T5 = _mm_mul_epu32(H2, p->R20.v); - T6 = _mm_mul_epu32(H2, p->R21.v); - T2 = _mm_add_epi64(T2, T5); - T3 = _mm_add_epi64(T3, T6); - T5 = _mm_mul_epu32(H3, p->S24.v); - T6 = _mm_mul_epu32(H3, p->R20.v); - T2 = _mm_add_epi64(T2, T5); - T3 = _mm_add_epi64(T3, T6); - T5 = _mm_mul_epu32(H4, p->S23.v); - T6 = _mm_mul_epu32(H4, p->S24.v); - T2 = _mm_add_epi64(T2, T5); - T3 = _mm_add_epi64(T3, T6); - T5 = _mm_mul_epu32(H1, p->R23.v); - T4 = _mm_add_epi64(T4, T5); - T5 = _mm_mul_epu32(H2, p->R22.v); - T4 = _mm_add_epi64(T4, T5); - T5 = _mm_mul_epu32(H3, p->R21.v); - T4 = _mm_add_epi64(T4, T5); - T5 = _mm_mul_epu32(H4, p->R20.v); - T4 = _mm_add_epi64(T4, T5); - - /* H += [Mx,My] */ - T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 0)), _mm_loadl_epi64((xmmi *)(m + 16))); - T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 8)), _mm_loadl_epi64((xmmi *)(m + 24))); - M0 = _mm_and_si128(MMASK, T5); - M1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26)); - T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12)); - M2 = _mm_and_si128(MMASK, T5); - M3 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26)); - M4 = _mm_or_si128(_mm_srli_epi64(T6, 40), HIBIT); - - T0 = _mm_add_epi64(T0, M0); - T1 = _mm_add_epi64(T1, M1); - T2 = _mm_add_epi64(T2, M2); - T3 = _mm_add_epi64(T3, M3); - T4 = _mm_add_epi64(T4, M4); - - /* reduce */ - C1 = _mm_srli_epi64(T0, 26); - C2 = _mm_srli_epi64(T3, 26); - T0 = _mm_and_si128(T0, MMASK); - T3 = _mm_and_si128(T3, MMASK); - T1 = _mm_add_epi64(T1, C1); - T4 = _mm_add_epi64(T4, C2); - C1 = _mm_srli_epi64(T1, 26); - C2 = _mm_srli_epi64(T4, 26); - T1 = _mm_and_si128(T1, MMASK); - T4 = _mm_and_si128(T4, MMASK); - T2 = _mm_add_epi64(T2, C1); - T0 = _mm_add_epi64(T0, _mm_mul_epu32(C2, FIVE)); - C1 = _mm_srli_epi64(T2, 26); - C2 = _mm_srli_epi64(T0, 26); - T2 = _mm_and_si128(T2, MMASK); - T0 = _mm_and_si128(T0, MMASK); - T3 = _mm_add_epi64(T3, C1); - T1 = _mm_add_epi64(T1, C2); - C1 = _mm_srli_epi64(T3, 26); - T3 = _mm_and_si128(T3, MMASK); - T4 = _mm_add_epi64(T4, C1); - - /* H = (H*[r^2,r^2] + [Mx,My]) */ - H0 = T0; - H1 = T1; - H2 = T2; - H3 = T3; - H4 = T4; - - consumed = 32; - } - - /* finalize, H *= [r^2,r] */ - r0 = ((uint64_t)p->R20.d[3] << 32) | (uint64_t)p->R20.d[1]; - r1 = ((uint64_t)p->R21.d[3] << 32) | (uint64_t)p->R21.d[1]; - r2 = ((uint64_t)p->R22.d[3] << 32) | (uint64_t)p->R22.d[1]; - - p->R20.d[2] = (uint32_t)(r0)&0x3ffffff; - p->R21.d[2] = (uint32_t)((r0 >> 26) | (r1 << 18)) & 0x3ffffff; - p->R22.d[2] = (uint32_t)((r1 >> 8)) & 0x3ffffff; - p->R23.d[2] = (uint32_t)((r1 >> 34) | (r2 << 10)) & 0x3ffffff; - p->R24.d[2] = (uint32_t)((r2 >> 16)); - p->S21.d[2] = p->R21.d[2] * 5; - p->S22.d[2] = p->R22.d[2] * 5; - p->S23.d[2] = p->R23.d[2] * 5; - p->S24.d[2] = p->R24.d[2] * 5; - - /* H *= [r^2,r] */ - T0 = _mm_mul_epu32(H0, p->R20.v); - T1 = _mm_mul_epu32(H0, p->R21.v); - T2 = _mm_mul_epu32(H0, p->R22.v); - T3 = _mm_mul_epu32(H0, p->R23.v); - T4 = _mm_mul_epu32(H0, p->R24.v); - T5 = _mm_mul_epu32(H1, p->S24.v); - T6 = _mm_mul_epu32(H1, p->R20.v); - T0 = _mm_add_epi64(T0, T5); - T1 = _mm_add_epi64(T1, T6); - T5 = _mm_mul_epu32(H2, p->S23.v); - T6 = _mm_mul_epu32(H2, p->S24.v); - T0 = _mm_add_epi64(T0, T5); - T1 = _mm_add_epi64(T1, T6); - T5 = _mm_mul_epu32(H3, p->S22.v); - T6 = _mm_mul_epu32(H3, p->S23.v); - T0 = _mm_add_epi64(T0, T5); - T1 = _mm_add_epi64(T1, T6); - T5 = _mm_mul_epu32(H4, p->S21.v); - T6 = _mm_mul_epu32(H4, p->S22.v); - T0 = _mm_add_epi64(T0, T5); - T1 = _mm_add_epi64(T1, T6); - T5 = _mm_mul_epu32(H1, p->R21.v); - T6 = _mm_mul_epu32(H1, p->R22.v); - T2 = _mm_add_epi64(T2, T5); - T3 = _mm_add_epi64(T3, T6); - T5 = _mm_mul_epu32(H2, p->R20.v); - T6 = _mm_mul_epu32(H2, p->R21.v); - T2 = _mm_add_epi64(T2, T5); - T3 = _mm_add_epi64(T3, T6); - T5 = _mm_mul_epu32(H3, p->S24.v); - T6 = _mm_mul_epu32(H3, p->R20.v); - T2 = _mm_add_epi64(T2, T5); - T3 = _mm_add_epi64(T3, T6); - T5 = _mm_mul_epu32(H4, p->S23.v); - T6 = _mm_mul_epu32(H4, p->S24.v); - T2 = _mm_add_epi64(T2, T5); - T3 = _mm_add_epi64(T3, T6); - T5 = _mm_mul_epu32(H1, p->R23.v); - T4 = _mm_add_epi64(T4, T5); - T5 = _mm_mul_epu32(H2, p->R22.v); - T4 = _mm_add_epi64(T4, T5); - T5 = _mm_mul_epu32(H3, p->R21.v); - T4 = _mm_add_epi64(T4, T5); - T5 = _mm_mul_epu32(H4, p->R20.v); - T4 = _mm_add_epi64(T4, T5); - - C1 = _mm_srli_epi64(T0, 26); - C2 = _mm_srli_epi64(T3, 26); - T0 = _mm_and_si128(T0, MMASK); - T3 = _mm_and_si128(T3, MMASK); - T1 = _mm_add_epi64(T1, C1); - T4 = _mm_add_epi64(T4, C2); - C1 = _mm_srli_epi64(T1, 26); - C2 = _mm_srli_epi64(T4, 26); - T1 = _mm_and_si128(T1, MMASK); - T4 = _mm_and_si128(T4, MMASK); - T2 = _mm_add_epi64(T2, C1); - T0 = _mm_add_epi64(T0, _mm_mul_epu32(C2, FIVE)); - C1 = _mm_srli_epi64(T2, 26); - C2 = _mm_srli_epi64(T0, 26); - T2 = _mm_and_si128(T2, MMASK); - T0 = _mm_and_si128(T0, MMASK); - T3 = _mm_add_epi64(T3, C1); - T1 = _mm_add_epi64(T1, C2); - C1 = _mm_srli_epi64(T3, 26); - T3 = _mm_and_si128(T3, MMASK); - T4 = _mm_add_epi64(T4, C1); - - /* H = H[0]+H[1] */ - H0 = _mm_add_epi64(T0, _mm_srli_si128(T0, 8)); - H1 = _mm_add_epi64(T1, _mm_srli_si128(T1, 8)); - H2 = _mm_add_epi64(T2, _mm_srli_si128(T2, 8)); - H3 = _mm_add_epi64(T3, _mm_srli_si128(T3, 8)); - H4 = _mm_add_epi64(T4, _mm_srli_si128(T4, 8)); - - t0 = _mm_cvtsi128_si32(H0); - c = (t0 >> 26); - t0 &= 0x3ffffff; - t1 = _mm_cvtsi128_si32(H1) + c; - c = (t1 >> 26); - t1 &= 0x3ffffff; - t2 = _mm_cvtsi128_si32(H2) + c; - c = (t2 >> 26); - t2 &= 0x3ffffff; - t3 = _mm_cvtsi128_si32(H3) + c; - c = (t3 >> 26); - t3 &= 0x3ffffff; - t4 = _mm_cvtsi128_si32(H4) + c; - c = (t4 >> 26); - t4 &= 0x3ffffff; - t0 = t0 + (c * 5); - c = (t0 >> 26); - t0 &= 0x3ffffff; - t1 = t1 + c; - - st->HH[0] = ((t0) | (t1 << 26)) & 0xfffffffffffull; - st->HH[1] = ((t1 >> 18) | (t2 << 8) | (t3 << 34)) & 0xfffffffffffull; - st->HH[2] = ((t3 >> 10) | (t4 << 16)) & 0x3ffffffffffull; - - return consumed; -} - -void -Poly1305Update(poly1305_state *state, const unsigned char *m, size_t bytes) -{ - poly1305_state_internal *st = poly1305_aligned_state(state); - size_t want; - - /* need at least 32 initial bytes to start the accelerated branch */ - if (!st->started) { - if ((st->leftover == 0) && (bytes > 32)) { - poly1305_first_block(st, m); - m += 32; - bytes -= 32; - } else { - want = poly1305_min(32 - st->leftover, bytes); - poly1305_block_copy(st->buffer + st->leftover, m, want); - bytes -= want; - m += want; - st->leftover += want; - if ((st->leftover < 32) || (bytes == 0)) - return; - poly1305_first_block(st, st->buffer); - st->leftover = 0; - } - st->started = 1; - } - - /* handle leftover */ - if (st->leftover) { - want = poly1305_min(64 - st->leftover, bytes); - poly1305_block_copy(st->buffer + st->leftover, m, want); - bytes -= want; - m += want; - st->leftover += want; - if (st->leftover < 64) - return; - poly1305_blocks(st, st->buffer, 64); - st->leftover = 0; - } - - /* process 64 byte blocks */ - if (bytes >= 64) { - want = (bytes & ~63); - poly1305_blocks(st, m, want); - m += want; - bytes -= want; - } - - if (bytes) { - poly1305_block_copy(st->buffer + st->leftover, m, bytes); - st->leftover += bytes; - } -} - -void -Poly1305Finish(poly1305_state *state, unsigned char mac[16]) -{ - poly1305_state_internal *st = poly1305_aligned_state(state); - size_t leftover = st->leftover; - uint8_t *m = st->buffer; - uint128_t d[3]; - uint64_t h0, h1, h2; - uint64_t t0, t1; - uint64_t g0, g1, g2, c, nc; - uint64_t r0, r1, r2, s1, s2; - poly1305_power *p; - - if (st->started) { - size_t consumed = poly1305_combine(st, m, leftover); - leftover -= consumed; - m += consumed; - } - - /* st->HH will either be 0 or have the combined result */ - h0 = st->HH[0]; - h1 = st->HH[1]; - h2 = st->HH[2]; - - p = &st->P[1]; - r0 = ((uint64_t)p->R20.d[3] << 32) | (uint64_t)p->R20.d[1]; - r1 = ((uint64_t)p->R21.d[3] << 32) | (uint64_t)p->R21.d[1]; - r2 = ((uint64_t)p->R22.d[3] << 32) | (uint64_t)p->R22.d[1]; - s1 = r1 * (5 << 2); - s2 = r2 * (5 << 2); - - if (leftover < 16) - goto poly1305_donna_atmost15bytes; - -poly1305_donna_atleast16bytes: - t0 = U8TO64_LE(m + 0); - t1 = U8TO64_LE(m + 8); - h0 += t0 & 0xfffffffffff; - t0 = shr128_pair(t1, t0, 44); - h1 += t0 & 0xfffffffffff; - h2 += (t1 >> 24) | ((uint64_t)1 << 40); - -poly1305_donna_mul: - d[0] = add128(add128(mul64x64_128(h0, r0), mul64x64_128(h1, s2)), mul64x64_128(h2, s1)); - d[1] = add128(add128(mul64x64_128(h0, r1), mul64x64_128(h1, r0)), mul64x64_128(h2, s2)); - d[2] = add128(add128(mul64x64_128(h0, r2), mul64x64_128(h1, r1)), mul64x64_128(h2, r0)); - h0 = lo128(d[0]) & 0xfffffffffff; - c = shr128(d[0], 44); - d[1] = add128_64(d[1], c); - h1 = lo128(d[1]) & 0xfffffffffff; - c = shr128(d[1], 44); - d[2] = add128_64(d[2], c); - h2 = lo128(d[2]) & 0x3ffffffffff; - c = shr128(d[2], 42); - h0 += c * 5; - - m += 16; - leftover -= 16; - if (leftover >= 16) - goto poly1305_donna_atleast16bytes; - -/* final bytes */ -poly1305_donna_atmost15bytes: - if (!leftover) - goto poly1305_donna_finish; - - m[leftover++] = 1; - poly1305_block_zero(m + leftover, 16 - leftover); - leftover = 16; - - t0 = U8TO64_LE(m + 0); - t1 = U8TO64_LE(m + 8); - h0 += t0 & 0xfffffffffff; - t0 = shr128_pair(t1, t0, 44); - h1 += t0 & 0xfffffffffff; - h2 += (t1 >> 24); - - goto poly1305_donna_mul; - -poly1305_donna_finish: - c = (h0 >> 44); - h0 &= 0xfffffffffff; - h1 += c; - c = (h1 >> 44); - h1 &= 0xfffffffffff; - h2 += c; - c = (h2 >> 42); - h2 &= 0x3ffffffffff; - h0 += c * 5; - - g0 = h0 + 5; - c = (g0 >> 44); - g0 &= 0xfffffffffff; - g1 = h1 + c; - c = (g1 >> 44); - g1 &= 0xfffffffffff; - g2 = h2 + c - ((uint64_t)1 << 42); - - c = (g2 >> 63) - 1; - nc = ~c; - h0 = (h0 & nc) | (g0 & c); - h1 = (h1 & nc) | (g1 & c); - h2 = (h2 & nc) | (g2 & c); - - /* pad */ - t0 = ((uint64_t)p->R23.d[3] << 32) | (uint64_t)p->R23.d[1]; - t1 = ((uint64_t)p->R24.d[3] << 32) | (uint64_t)p->R24.d[1]; - h0 += (t0 & 0xfffffffffff); - c = (h0 >> 44); - h0 &= 0xfffffffffff; - t0 = shr128_pair(t1, t0, 44); - h1 += (t0 & 0xfffffffffff) + c; - c = (h1 >> 44); - h1 &= 0xfffffffffff; - t1 = (t1 >> 24); - h2 += (t1) + c; - - U64TO8_LE(mac + 0, ((h0) | (h1 << 44))); - U64TO8_LE(mac + 8, ((h1 >> 20) | (h2 << 24))); -} diff --git a/security/nss/lib/freebl/poly1305.c b/security/nss/lib/freebl/poly1305.c deleted file mode 100644 index eb3e3cd55..000000000 --- a/security/nss/lib/freebl/poly1305.c +++ /dev/null @@ -1,314 +0,0 @@ -/* 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/. */ - -/* This implementation of poly1305 is by Andrew Moon - * (https://github.com/floodyberry/poly1305-donna) and released as public - * domain. */ - -#include <string.h> - -#include "poly1305.h" - -#if defined(_MSC_VER) && _MSC_VER < 1600 -#include "prtypes.h" -typedef PRUint32 uint32_t; -typedef PRUint64 uint64_t; -#else -#include <stdint.h> -#endif - -#if defined(NSS_X86) || defined(NSS_X64) -/* We can assume little-endian. */ -static uint32_t -U8TO32_LE(const unsigned char *m) -{ - uint32_t r; - memcpy(&r, m, sizeof(r)); - return r; -} - -static void -U32TO8_LE(unsigned char *m, uint32_t v) -{ - memcpy(m, &v, sizeof(v)); -} -#else -static uint32_t -U8TO32_LE(const unsigned char *m) -{ - return (uint32_t)m[0] | - (uint32_t)m[1] << 8 | - (uint32_t)m[2] << 16 | - (uint32_t)m[3] << 24; -} - -static void -U32TO8_LE(unsigned char *m, uint32_t v) -{ - m[0] = v; - m[1] = v >> 8; - m[2] = v >> 16; - m[3] = v >> 24; -} -#endif - -static uint64_t -mul32x32_64(uint32_t a, uint32_t b) -{ - return (uint64_t)a * b; -} - -struct poly1305_state_st { - uint32_t r0, r1, r2, r3, r4; - uint32_t s1, s2, s3, s4; - uint32_t h0, h1, h2, h3, h4; - unsigned char buf[16]; - unsigned int buf_used; - unsigned char key[16]; -}; - -/* update updates |state| given some amount of input data. This function may - * only be called with a |len| that is not a multiple of 16 at the end of the - * data. Otherwise the input must be buffered into 16 byte blocks. */ -static void -update(struct poly1305_state_st *state, const unsigned char *in, - size_t len) -{ - uint32_t t0, t1, t2, t3; - uint64_t t[5]; - uint32_t b; - uint64_t c; - size_t j; - unsigned char mp[16]; - - if (len < 16) - goto poly1305_donna_atmost15bytes; - -poly1305_donna_16bytes: - t0 = U8TO32_LE(in); - t1 = U8TO32_LE(in + 4); - t2 = U8TO32_LE(in + 8); - t3 = U8TO32_LE(in + 12); - - in += 16; - len -= 16; - - state->h0 += t0 & 0x3ffffff; - state->h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff; - state->h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff; - state->h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff; - state->h4 += (t3 >> 8) | (1 << 24); - -poly1305_donna_mul: - t[0] = mul32x32_64(state->h0, state->r0) + - mul32x32_64(state->h1, state->s4) + - mul32x32_64(state->h2, state->s3) + - mul32x32_64(state->h3, state->s2) + - mul32x32_64(state->h4, state->s1); - t[1] = mul32x32_64(state->h0, state->r1) + - mul32x32_64(state->h1, state->r0) + - mul32x32_64(state->h2, state->s4) + - mul32x32_64(state->h3, state->s3) + - mul32x32_64(state->h4, state->s2); - t[2] = mul32x32_64(state->h0, state->r2) + - mul32x32_64(state->h1, state->r1) + - mul32x32_64(state->h2, state->r0) + - mul32x32_64(state->h3, state->s4) + - mul32x32_64(state->h4, state->s3); - t[3] = mul32x32_64(state->h0, state->r3) + - mul32x32_64(state->h1, state->r2) + - mul32x32_64(state->h2, state->r1) + - mul32x32_64(state->h3, state->r0) + - mul32x32_64(state->h4, state->s4); - t[4] = mul32x32_64(state->h0, state->r4) + - mul32x32_64(state->h1, state->r3) + - mul32x32_64(state->h2, state->r2) + - mul32x32_64(state->h3, state->r1) + - mul32x32_64(state->h4, state->r0); - - state->h0 = (uint32_t)t[0] & 0x3ffffff; - c = (t[0] >> 26); - t[1] += c; - state->h1 = (uint32_t)t[1] & 0x3ffffff; - b = (uint32_t)(t[1] >> 26); - t[2] += b; - state->h2 = (uint32_t)t[2] & 0x3ffffff; - b = (uint32_t)(t[2] >> 26); - t[3] += b; - state->h3 = (uint32_t)t[3] & 0x3ffffff; - b = (uint32_t)(t[3] >> 26); - t[4] += b; - state->h4 = (uint32_t)t[4] & 0x3ffffff; - b = (uint32_t)(t[4] >> 26); - state->h0 += b * 5; - - if (len >= 16) - goto poly1305_donna_16bytes; - -/* final bytes */ -poly1305_donna_atmost15bytes: - if (!len) - return; - - for (j = 0; j < len; j++) - mp[j] = in[j]; - mp[j++] = 1; - for (; j < 16; j++) - mp[j] = 0; - len = 0; - - t0 = U8TO32_LE(mp + 0); - t1 = U8TO32_LE(mp + 4); - t2 = U8TO32_LE(mp + 8); - t3 = U8TO32_LE(mp + 12); - - state->h0 += t0 & 0x3ffffff; - state->h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff; - state->h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff; - state->h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff; - state->h4 += (t3 >> 8); - - goto poly1305_donna_mul; -} - -void -Poly1305Init(poly1305_state *statep, const unsigned char key[32]) -{ - struct poly1305_state_st *state = (struct poly1305_state_st *)statep; - uint32_t t0, t1, t2, t3; - - t0 = U8TO32_LE(key + 0); - t1 = U8TO32_LE(key + 4); - t2 = U8TO32_LE(key + 8); - t3 = U8TO32_LE(key + 12); - - /* precompute multipliers */ - state->r0 = t0 & 0x3ffffff; - t0 >>= 26; - t0 |= t1 << 6; - state->r1 = t0 & 0x3ffff03; - t1 >>= 20; - t1 |= t2 << 12; - state->r2 = t1 & 0x3ffc0ff; - t2 >>= 14; - t2 |= t3 << 18; - state->r3 = t2 & 0x3f03fff; - t3 >>= 8; - state->r4 = t3 & 0x00fffff; - - state->s1 = state->r1 * 5; - state->s2 = state->r2 * 5; - state->s3 = state->r3 * 5; - state->s4 = state->r4 * 5; - - /* init state */ - state->h0 = 0; - state->h1 = 0; - state->h2 = 0; - state->h3 = 0; - state->h4 = 0; - - state->buf_used = 0; - memcpy(state->key, key + 16, sizeof(state->key)); -} - -void -Poly1305Update(poly1305_state *statep, const unsigned char *in, - size_t in_len) -{ - unsigned int i; - struct poly1305_state_st *state = (struct poly1305_state_st *)statep; - - if (state->buf_used) { - unsigned int todo = 16 - state->buf_used; - if (todo > in_len) - todo = in_len; - for (i = 0; i < todo; i++) - state->buf[state->buf_used + i] = in[i]; - state->buf_used += todo; - in_len -= todo; - in += todo; - - if (state->buf_used == 16) { - update(state, state->buf, 16); - state->buf_used = 0; - } - } - - if (in_len >= 16) { - size_t todo = in_len & ~0xf; - update(state, in, todo); - in += todo; - in_len &= 0xf; - } - - if (in_len) { - for (i = 0; i < in_len; i++) - state->buf[i] = in[i]; - state->buf_used = in_len; - } -} - -void -Poly1305Finish(poly1305_state *statep, unsigned char mac[16]) -{ - struct poly1305_state_st *state = (struct poly1305_state_st *)statep; - uint64_t f0, f1, f2, f3; - uint32_t g0, g1, g2, g3, g4; - uint32_t b, nb; - - if (state->buf_used) - update(state, state->buf, state->buf_used); - - b = state->h0 >> 26; - state->h0 = state->h0 & 0x3ffffff; - state->h1 += b; - b = state->h1 >> 26; - state->h1 = state->h1 & 0x3ffffff; - state->h2 += b; - b = state->h2 >> 26; - state->h2 = state->h2 & 0x3ffffff; - state->h3 += b; - b = state->h3 >> 26; - state->h3 = state->h3 & 0x3ffffff; - state->h4 += b; - b = state->h4 >> 26; - state->h4 = state->h4 & 0x3ffffff; - state->h0 += b * 5; - - g0 = state->h0 + 5; - b = g0 >> 26; - g0 &= 0x3ffffff; - g1 = state->h1 + b; - b = g1 >> 26; - g1 &= 0x3ffffff; - g2 = state->h2 + b; - b = g2 >> 26; - g2 &= 0x3ffffff; - g3 = state->h3 + b; - b = g3 >> 26; - g3 &= 0x3ffffff; - g4 = state->h4 + b - (1 << 26); - - b = (g4 >> 31) - 1; - nb = ~b; - state->h0 = (state->h0 & nb) | (g0 & b); - state->h1 = (state->h1 & nb) | (g1 & b); - state->h2 = (state->h2 & nb) | (g2 & b); - state->h3 = (state->h3 & nb) | (g3 & b); - state->h4 = (state->h4 & nb) | (g4 & b); - - f0 = ((state->h0) | (state->h1 << 26)) + (uint64_t)U8TO32_LE(&state->key[0]); - f1 = ((state->h1 >> 6) | (state->h2 << 20)) + (uint64_t)U8TO32_LE(&state->key[4]); - f2 = ((state->h2 >> 12) | (state->h3 << 14)) + (uint64_t)U8TO32_LE(&state->key[8]); - f3 = ((state->h3 >> 18) | (state->h4 << 8)) + (uint64_t)U8TO32_LE(&state->key[12]); - - U32TO8_LE(&mac[0], (uint32_t)f0); - f1 += (f0 >> 32); - U32TO8_LE(&mac[4], (uint32_t)f1); - f2 += (f1 >> 32); - U32TO8_LE(&mac[8], (uint32_t)f2); - f3 += (f2 >> 32); - U32TO8_LE(&mac[12], (uint32_t)f3); -} diff --git a/security/nss/lib/freebl/poly1305.h b/security/nss/lib/freebl/poly1305.h deleted file mode 100644 index 125f49b3b..000000000 --- a/security/nss/lib/freebl/poly1305.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * poly1305.h - header file for Poly1305 implementation. - * - * 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 FREEBL_POLY1305_H_ -#define FREEBL_POLY1305_H_ - -#include "stddef.h" - -typedef unsigned char poly1305_state[512]; - -/* Poly1305Init sets up |state| so that it can be used to calculate an - * authentication tag with the one-time key |key|. Note that |key| is a - * one-time key and therefore there is no `reset' method because that would - * enable several messages to be authenticated with the same key. */ -extern void Poly1305Init(poly1305_state* state, const unsigned char key[32]); - -/* Poly1305Update processes |in_len| bytes from |in|. It can be called zero or - * more times after poly1305_init. */ -extern void Poly1305Update(poly1305_state* state, const unsigned char* in, - size_t inLen); - -/* Poly1305Finish completes the poly1305 calculation and writes a 16 byte - * authentication tag to |mac|. */ -extern void Poly1305Finish(poly1305_state* state, unsigned char mac[16]); - -#endif /* FREEBL_POLY1305_H_ */ diff --git a/security/nss/lib/freebl/unix_urandom.c b/security/nss/lib/freebl/unix_urandom.c index 25e6ad91c..869a5ed8c 100644 --- a/security/nss/lib/freebl/unix_urandom.c +++ b/security/nss/lib/freebl/unix_urandom.c @@ -4,10 +4,14 @@ #include <fcntl.h> #include <unistd.h> +#include <errno.h> #include "secerr.h" #include "secrng.h" #include "prprf.h" +/* syscall getentropy() is limited to retrieving 256 bytes */ +#define GETENTROPY_MAX_BYTES 256 + void RNG_SystemInfoForRNG(void) { @@ -28,6 +32,35 @@ 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)))) + int result; + + while (fileBytes < maxLen) { + size_t getBytes = maxLen - fileBytes; + if (getBytes > GETENTROPY_MAX_BYTES) { + getBytes = GETENTROPY_MAX_BYTES; + } + result = getentropy(buffer, getBytes); + if (result == 0) { /* success */ + fileBytes += getBytes; + buffer += getBytes; + } else { + break; + } + } + if (fileBytes == maxLen) { /* success */ + return maxLen; + } + /* If we failed with an error other than ENOSYS, it means the destination + * buffer is not writeable. We don't need to try writing to it again. */ + if (errno != ENOSYS) { + PORT_SetError(SEC_ERROR_NEED_RANDOM); + return 0; + } + /* ENOSYS means the kernel doesn't support getentropy()/getrandom(). + * Reset the number of bytes to get and fall back to /dev/urandom. */ + fileBytes = 0; +#endif fd = open("/dev/urandom", O_RDONLY); if (fd < 0) { PORT_SetError(SEC_ERROR_NEED_RANDOM); diff --git a/security/nss/lib/freebl/verified/Hacl_Poly1305_32.c b/security/nss/lib/freebl/verified/Hacl_Poly1305_32.c new file mode 100644 index 000000000..246a41af3 --- /dev/null +++ b/security/nss/lib/freebl/verified/Hacl_Poly1305_32.c @@ -0,0 +1,578 @@ +/* Copyright 2016-2017 INRIA and Microsoft Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Hacl_Poly1305_32.h" + +inline static void +Hacl_Bignum_Modulo_reduce(uint32_t *b) +{ + uint32_t b0 = b[0U]; + b[0U] = (b0 << (uint32_t)2U) + b0; +} + +inline static void +Hacl_Bignum_Modulo_carry_top(uint32_t *b) +{ + uint32_t b4 = b[4U]; + uint32_t b0 = b[0U]; + uint32_t b4_26 = b4 >> (uint32_t)26U; + b[4U] = b4 & (uint32_t)0x3ffffffU; + b[0U] = (b4_26 << (uint32_t)2U) + b4_26 + b0; +} + +inline static void +Hacl_Bignum_Modulo_carry_top_wide(uint64_t *b) +{ + uint64_t b4 = b[4U]; + uint64_t b0 = b[0U]; + uint64_t b4_ = b4 & (uint64_t)(uint32_t)0x3ffffffU; + uint32_t b4_26 = (uint32_t)(b4 >> (uint32_t)26U); + uint64_t b0_ = b0 + (uint64_t)((b4_26 << (uint32_t)2U) + b4_26); + b[4U] = b4_; + b[0U] = b0_; +} + +inline static void +Hacl_Bignum_Fproduct_copy_from_wide_(uint32_t *output, uint64_t *input) +{ + for (uint32_t i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U) { + uint64_t xi = input[i]; + output[i] = (uint32_t)xi; + } +} + +inline static void +Hacl_Bignum_Fproduct_sum_scalar_multiplication_(uint64_t *output, uint32_t *input, uint32_t s) +{ + for (uint32_t i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U) { + uint64_t xi = output[i]; + uint32_t yi = input[i]; + uint64_t x_wide = (uint64_t)yi; + uint64_t y_wide = (uint64_t)s; + output[i] = xi + x_wide * y_wide; + } +} + +inline static void +Hacl_Bignum_Fproduct_carry_wide_(uint64_t *tmp) +{ + for (uint32_t i = (uint32_t)0U; i < (uint32_t)4U; i = i + (uint32_t)1U) { + uint32_t ctr = i; + uint64_t tctr = tmp[ctr]; + uint64_t tctrp1 = tmp[ctr + (uint32_t)1U]; + uint32_t r0 = (uint32_t)tctr & (uint32_t)0x3ffffffU; + uint64_t c = tctr >> (uint32_t)26U; + tmp[ctr] = (uint64_t)r0; + tmp[ctr + (uint32_t)1U] = tctrp1 + c; + } +} + +inline static void +Hacl_Bignum_Fproduct_carry_limb_(uint32_t *tmp) +{ + for (uint32_t i = (uint32_t)0U; i < (uint32_t)4U; i = i + (uint32_t)1U) { + uint32_t ctr = i; + uint32_t tctr = tmp[ctr]; + uint32_t tctrp1 = tmp[ctr + (uint32_t)1U]; + uint32_t r0 = tctr & (uint32_t)0x3ffffffU; + uint32_t c = tctr >> (uint32_t)26U; + tmp[ctr] = r0; + tmp[ctr + (uint32_t)1U] = tctrp1 + c; + } +} + +inline static void +Hacl_Bignum_Fmul_shift_reduce(uint32_t *output) +{ + uint32_t tmp = output[4U]; + for (uint32_t i = (uint32_t)0U; i < (uint32_t)4U; i = i + (uint32_t)1U) { + uint32_t ctr = (uint32_t)5U - i - (uint32_t)1U; + uint32_t z = output[ctr - (uint32_t)1U]; + output[ctr] = z; + } + output[0U] = tmp; + Hacl_Bignum_Modulo_reduce(output); +} + +static void +Hacl_Bignum_Fmul_mul_shift_reduce_(uint64_t *output, uint32_t *input, uint32_t *input2) +{ + for (uint32_t i = (uint32_t)0U; i < (uint32_t)4U; i = i + (uint32_t)1U) { + uint32_t input2i = input2[i]; + Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i); + Hacl_Bignum_Fmul_shift_reduce(input); + } + uint32_t i = (uint32_t)4U; + uint32_t input2i = input2[i]; + Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i); +} + +inline static void +Hacl_Bignum_Fmul_fmul(uint32_t *output, uint32_t *input, uint32_t *input2) +{ + uint32_t tmp[5U] = { 0U }; + memcpy(tmp, input, (uint32_t)5U * sizeof input[0U]); + uint64_t t[5U] = { 0U }; + Hacl_Bignum_Fmul_mul_shift_reduce_(t, tmp, input2); + Hacl_Bignum_Fproduct_carry_wide_(t); + Hacl_Bignum_Modulo_carry_top_wide(t); + Hacl_Bignum_Fproduct_copy_from_wide_(output, t); + uint32_t i0 = output[0U]; + uint32_t i1 = output[1U]; + uint32_t i0_ = i0 & (uint32_t)0x3ffffffU; + uint32_t i1_ = i1 + (i0 >> (uint32_t)26U); + output[0U] = i0_; + output[1U] = i1_; +} + +inline static void +Hacl_Bignum_AddAndMultiply_add_and_multiply(uint32_t *acc, uint32_t *block, uint32_t *r) +{ + for (uint32_t i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U) { + uint32_t xi = acc[i]; + uint32_t yi = block[i]; + acc[i] = xi + yi; + } + Hacl_Bignum_Fmul_fmul(acc, acc, r); +} + +inline static void +Hacl_Impl_Poly1305_32_poly1305_update( + Hacl_Impl_Poly1305_32_State_poly1305_state st, + uint8_t *m) +{ + Hacl_Impl_Poly1305_32_State_poly1305_state scrut0 = st; + uint32_t *h = scrut0.h; + uint32_t *acc = h; + Hacl_Impl_Poly1305_32_State_poly1305_state scrut = st; + uint32_t *r = scrut.r; + uint32_t *r5 = r; + uint32_t tmp[5U] = { 0U }; + uint8_t *s0 = m; + uint8_t *s1 = m + (uint32_t)3U; + uint8_t *s2 = m + (uint32_t)6U; + uint8_t *s3 = m + (uint32_t)9U; + uint8_t *s4 = m + (uint32_t)12U; + uint32_t i0 = load32_le(s0); + uint32_t i1 = load32_le(s1); + uint32_t i2 = load32_le(s2); + uint32_t i3 = load32_le(s3); + uint32_t i4 = load32_le(s4); + uint32_t r0 = i0 & (uint32_t)0x3ffffffU; + uint32_t r1 = i1 >> (uint32_t)2U & (uint32_t)0x3ffffffU; + uint32_t r2 = i2 >> (uint32_t)4U & (uint32_t)0x3ffffffU; + uint32_t r3 = i3 >> (uint32_t)6U & (uint32_t)0x3ffffffU; + uint32_t r4 = i4 >> (uint32_t)8U; + tmp[0U] = r0; + tmp[1U] = r1; + tmp[2U] = r2; + tmp[3U] = r3; + tmp[4U] = r4; + uint32_t b4 = tmp[4U]; + uint32_t b4_ = (uint32_t)0x1000000U | b4; + tmp[4U] = b4_; + Hacl_Bignum_AddAndMultiply_add_and_multiply(acc, tmp, r5); +} + +inline static void +Hacl_Impl_Poly1305_32_poly1305_process_last_block_( + uint8_t *block, + Hacl_Impl_Poly1305_32_State_poly1305_state st, + uint8_t *m, + uint64_t rem_) +{ + uint32_t tmp[5U] = { 0U }; + uint8_t *s0 = block; + uint8_t *s1 = block + (uint32_t)3U; + uint8_t *s2 = block + (uint32_t)6U; + uint8_t *s3 = block + (uint32_t)9U; + uint8_t *s4 = block + (uint32_t)12U; + uint32_t i0 = load32_le(s0); + uint32_t i1 = load32_le(s1); + uint32_t i2 = load32_le(s2); + uint32_t i3 = load32_le(s3); + uint32_t i4 = load32_le(s4); + uint32_t r0 = i0 & (uint32_t)0x3ffffffU; + uint32_t r1 = i1 >> (uint32_t)2U & (uint32_t)0x3ffffffU; + uint32_t r2 = i2 >> (uint32_t)4U & (uint32_t)0x3ffffffU; + uint32_t r3 = i3 >> (uint32_t)6U & (uint32_t)0x3ffffffU; + uint32_t r4 = i4 >> (uint32_t)8U; + tmp[0U] = r0; + tmp[1U] = r1; + tmp[2U] = r2; + tmp[3U] = r3; + tmp[4U] = r4; + Hacl_Impl_Poly1305_32_State_poly1305_state scrut0 = st; + uint32_t *h = scrut0.h; + Hacl_Impl_Poly1305_32_State_poly1305_state scrut = st; + uint32_t *r = scrut.r; + Hacl_Bignum_AddAndMultiply_add_and_multiply(h, tmp, r); +} + +inline static void +Hacl_Impl_Poly1305_32_poly1305_process_last_block( + Hacl_Impl_Poly1305_32_State_poly1305_state st, + uint8_t *m, + uint64_t rem_) +{ + uint8_t zero1 = (uint8_t)0U; + KRML_CHECK_SIZE(zero1, (uint32_t)16U); + uint8_t block[16U]; + for (uint32_t _i = 0U; _i < (uint32_t)16U; ++_i) + block[_i] = zero1; + uint32_t i0 = (uint32_t)rem_; + uint32_t i = (uint32_t)rem_; + memcpy(block, m, i * sizeof m[0U]); + block[i0] = (uint8_t)1U; + Hacl_Impl_Poly1305_32_poly1305_process_last_block_(block, st, m, rem_); +} + +static void +Hacl_Impl_Poly1305_32_poly1305_last_pass(uint32_t *acc) +{ + Hacl_Bignum_Fproduct_carry_limb_(acc); + Hacl_Bignum_Modulo_carry_top(acc); + uint32_t t0 = acc[0U]; + uint32_t t10 = acc[1U]; + uint32_t t20 = acc[2U]; + uint32_t t30 = acc[3U]; + uint32_t t40 = acc[4U]; + uint32_t t1_ = t10 + (t0 >> (uint32_t)26U); + uint32_t mask_261 = (uint32_t)0x3ffffffU; + uint32_t t0_ = t0 & mask_261; + uint32_t t2_ = t20 + (t1_ >> (uint32_t)26U); + uint32_t t1__ = t1_ & mask_261; + uint32_t t3_ = t30 + (t2_ >> (uint32_t)26U); + uint32_t t2__ = t2_ & mask_261; + uint32_t t4_ = t40 + (t3_ >> (uint32_t)26U); + uint32_t t3__ = t3_ & mask_261; + acc[0U] = t0_; + acc[1U] = t1__; + acc[2U] = t2__; + acc[3U] = t3__; + acc[4U] = t4_; + Hacl_Bignum_Modulo_carry_top(acc); + uint32_t t00 = acc[0U]; + uint32_t t1 = acc[1U]; + uint32_t t2 = acc[2U]; + uint32_t t3 = acc[3U]; + uint32_t t4 = acc[4U]; + uint32_t t1_0 = t1 + (t00 >> (uint32_t)26U); + uint32_t t0_0 = t00 & (uint32_t)0x3ffffffU; + uint32_t t2_0 = t2 + (t1_0 >> (uint32_t)26U); + uint32_t t1__0 = t1_0 & (uint32_t)0x3ffffffU; + uint32_t t3_0 = t3 + (t2_0 >> (uint32_t)26U); + uint32_t t2__0 = t2_0 & (uint32_t)0x3ffffffU; + uint32_t t4_0 = t4 + (t3_0 >> (uint32_t)26U); + uint32_t t3__0 = t3_0 & (uint32_t)0x3ffffffU; + acc[0U] = t0_0; + acc[1U] = t1__0; + acc[2U] = t2__0; + acc[3U] = t3__0; + acc[4U] = t4_0; + Hacl_Bignum_Modulo_carry_top(acc); + uint32_t i0 = acc[0U]; + uint32_t i1 = acc[1U]; + uint32_t i0_ = i0 & (uint32_t)0x3ffffffU; + uint32_t i1_ = i1 + (i0 >> (uint32_t)26U); + acc[0U] = i0_; + acc[1U] = i1_; + uint32_t a0 = acc[0U]; + uint32_t a1 = acc[1U]; + uint32_t a2 = acc[2U]; + uint32_t a3 = acc[3U]; + uint32_t a4 = acc[4U]; + uint32_t mask0 = FStar_UInt32_gte_mask(a0, (uint32_t)0x3fffffbU); + uint32_t mask1 = FStar_UInt32_eq_mask(a1, (uint32_t)0x3ffffffU); + uint32_t mask2 = FStar_UInt32_eq_mask(a2, (uint32_t)0x3ffffffU); + uint32_t mask3 = FStar_UInt32_eq_mask(a3, (uint32_t)0x3ffffffU); + uint32_t mask4 = FStar_UInt32_eq_mask(a4, (uint32_t)0x3ffffffU); + uint32_t mask = (((mask0 & mask1) & mask2) & mask3) & mask4; + uint32_t a0_ = a0 - ((uint32_t)0x3fffffbU & mask); + uint32_t a1_ = a1 - ((uint32_t)0x3ffffffU & mask); + uint32_t a2_ = a2 - ((uint32_t)0x3ffffffU & mask); + uint32_t a3_ = a3 - ((uint32_t)0x3ffffffU & mask); + uint32_t a4_ = a4 - ((uint32_t)0x3ffffffU & mask); + acc[0U] = a0_; + acc[1U] = a1_; + acc[2U] = a2_; + acc[3U] = a3_; + acc[4U] = a4_; +} + +static Hacl_Impl_Poly1305_32_State_poly1305_state +Hacl_Impl_Poly1305_32_mk_state(uint32_t *r, uint32_t *h) +{ + return ((Hacl_Impl_Poly1305_32_State_poly1305_state){.r = r, .h = h }); +} + +static void +Hacl_Standalone_Poly1305_32_poly1305_blocks( + Hacl_Impl_Poly1305_32_State_poly1305_state st, + uint8_t *m, + uint64_t len1) +{ + if (!(len1 == (uint64_t)0U)) { + uint8_t *block = m; + uint8_t *tail1 = m + (uint32_t)16U; + Hacl_Impl_Poly1305_32_poly1305_update(st, block); + uint64_t len2 = len1 - (uint64_t)1U; + Hacl_Standalone_Poly1305_32_poly1305_blocks(st, tail1, len2); + } +} + +static void +Hacl_Standalone_Poly1305_32_poly1305_partial( + Hacl_Impl_Poly1305_32_State_poly1305_state st, + uint8_t *input, + uint64_t len1, + uint8_t *kr) +{ + Hacl_Impl_Poly1305_32_State_poly1305_state scrut = st; + uint32_t *r = scrut.r; + uint32_t *x0 = r; + FStar_UInt128_t k1 = load128_le(kr); + FStar_UInt128_t + k_clamped = + FStar_UInt128_logand(k1, + FStar_UInt128_logor(FStar_UInt128_shift_left(FStar_UInt128_uint64_to_uint128((uint64_t)0x0ffffffc0ffffffcU), + (uint32_t)64U), + FStar_UInt128_uint64_to_uint128((uint64_t)0x0ffffffc0fffffffU))); + uint32_t r0 = (uint32_t)FStar_UInt128_uint128_to_uint64(k_clamped) & (uint32_t)0x3ffffffU; + uint32_t + r1 = + (uint32_t)FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(k_clamped, (uint32_t)26U)) & (uint32_t)0x3ffffffU; + uint32_t + r2 = + (uint32_t)FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(k_clamped, (uint32_t)52U)) & (uint32_t)0x3ffffffU; + uint32_t + r3 = + (uint32_t)FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(k_clamped, (uint32_t)78U)) & (uint32_t)0x3ffffffU; + uint32_t + r4 = + (uint32_t)FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(k_clamped, (uint32_t)104U)) & (uint32_t)0x3ffffffU; + x0[0U] = r0; + x0[1U] = r1; + x0[2U] = r2; + x0[3U] = r3; + x0[4U] = r4; + Hacl_Impl_Poly1305_32_State_poly1305_state scrut0 = st; + uint32_t *h = scrut0.h; + uint32_t *x00 = h; + x00[0U] = (uint32_t)0U; + x00[1U] = (uint32_t)0U; + x00[2U] = (uint32_t)0U; + x00[3U] = (uint32_t)0U; + x00[4U] = (uint32_t)0U; + Hacl_Standalone_Poly1305_32_poly1305_blocks(st, input, len1); +} + +static void +Hacl_Standalone_Poly1305_32_poly1305_complete( + Hacl_Impl_Poly1305_32_State_poly1305_state st, + uint8_t *m, + uint64_t len1, + uint8_t *k1) +{ + uint8_t *kr = k1; + uint64_t len16 = len1 >> (uint32_t)4U; + uint64_t rem16 = len1 & (uint64_t)0xfU; + uint8_t *part_input = m; + uint8_t *last_block = m + (uint32_t)((uint64_t)16U * len16); + Hacl_Standalone_Poly1305_32_poly1305_partial(st, part_input, len16, kr); + if (!(rem16 == (uint64_t)0U)) + Hacl_Impl_Poly1305_32_poly1305_process_last_block(st, last_block, rem16); + Hacl_Impl_Poly1305_32_State_poly1305_state scrut = st; + uint32_t *h = scrut.h; + uint32_t *acc = h; + Hacl_Impl_Poly1305_32_poly1305_last_pass(acc); +} + +static void +Hacl_Standalone_Poly1305_32_crypto_onetimeauth_( + uint8_t *output, + uint8_t *input, + uint64_t len1, + uint8_t *k1) +{ + uint32_t buf[10U] = { 0U }; + uint32_t *r = buf; + uint32_t *h = buf + (uint32_t)5U; + Hacl_Impl_Poly1305_32_State_poly1305_state st = Hacl_Impl_Poly1305_32_mk_state(r, h); + uint8_t *key_s = k1 + (uint32_t)16U; + Hacl_Standalone_Poly1305_32_poly1305_complete(st, input, len1, k1); + Hacl_Impl_Poly1305_32_State_poly1305_state scrut = st; + uint32_t *h5 = scrut.h; + uint32_t *acc = h5; + FStar_UInt128_t k_ = load128_le(key_s); + uint32_t h0 = acc[0U]; + uint32_t h1 = acc[1U]; + uint32_t h2 = acc[2U]; + uint32_t h3 = acc[3U]; + uint32_t h4 = acc[4U]; + FStar_UInt128_t + acc_ = + FStar_UInt128_logor(FStar_UInt128_shift_left(FStar_UInt128_uint64_to_uint128((uint64_t)h4), + (uint32_t)104U), + FStar_UInt128_logor(FStar_UInt128_shift_left(FStar_UInt128_uint64_to_uint128((uint64_t)h3), + (uint32_t)78U), + FStar_UInt128_logor(FStar_UInt128_shift_left(FStar_UInt128_uint64_to_uint128((uint64_t)h2), + (uint32_t)52U), + FStar_UInt128_logor(FStar_UInt128_shift_left(FStar_UInt128_uint64_to_uint128((uint64_t)h1), + (uint32_t)26U), + FStar_UInt128_uint64_to_uint128((uint64_t)h0))))); + FStar_UInt128_t mac_ = FStar_UInt128_add_mod(acc_, k_); + store128_le(output, mac_); +} + +static void +Hacl_Standalone_Poly1305_32_crypto_onetimeauth( + uint8_t *output, + uint8_t *input, + uint64_t len1, + uint8_t *k1) +{ + Hacl_Standalone_Poly1305_32_crypto_onetimeauth_(output, input, len1, k1); +} + +void * +Hacl_Poly1305_32_op_String_Access(FStar_Monotonic_HyperStack_mem h, uint8_t *b) +{ + return (void *)(uint8_t)0U; +} + +Hacl_Impl_Poly1305_32_State_poly1305_state +Hacl_Poly1305_32_mk_state(uint32_t *r, uint32_t *acc) +{ + return Hacl_Impl_Poly1305_32_mk_state(r, acc); +} + +void +Hacl_Poly1305_32_init(Hacl_Impl_Poly1305_32_State_poly1305_state st, uint8_t *k1) +{ + Hacl_Impl_Poly1305_32_State_poly1305_state scrut = st; + uint32_t *r = scrut.r; + uint32_t *x0 = r; + FStar_UInt128_t k10 = load128_le(k1); + FStar_UInt128_t + k_clamped = + FStar_UInt128_logand(k10, + FStar_UInt128_logor(FStar_UInt128_shift_left(FStar_UInt128_uint64_to_uint128((uint64_t)0x0ffffffc0ffffffcU), + (uint32_t)64U), + FStar_UInt128_uint64_to_uint128((uint64_t)0x0ffffffc0fffffffU))); + uint32_t r0 = (uint32_t)FStar_UInt128_uint128_to_uint64(k_clamped) & (uint32_t)0x3ffffffU; + uint32_t + r1 = + (uint32_t)FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(k_clamped, (uint32_t)26U)) & (uint32_t)0x3ffffffU; + uint32_t + r2 = + (uint32_t)FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(k_clamped, (uint32_t)52U)) & (uint32_t)0x3ffffffU; + uint32_t + r3 = + (uint32_t)FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(k_clamped, (uint32_t)78U)) & (uint32_t)0x3ffffffU; + uint32_t + r4 = + (uint32_t)FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(k_clamped, (uint32_t)104U)) & (uint32_t)0x3ffffffU; + x0[0U] = r0; + x0[1U] = r1; + x0[2U] = r2; + x0[3U] = r3; + x0[4U] = r4; + Hacl_Impl_Poly1305_32_State_poly1305_state scrut0 = st; + uint32_t *h = scrut0.h; + uint32_t *x00 = h; + x00[0U] = (uint32_t)0U; + x00[1U] = (uint32_t)0U; + x00[2U] = (uint32_t)0U; + x00[3U] = (uint32_t)0U; + x00[4U] = (uint32_t)0U; +} + +void *Hacl_Poly1305_32_empty_log = (void *)(uint8_t)0U; + +void +Hacl_Poly1305_32_update_block(Hacl_Impl_Poly1305_32_State_poly1305_state st, uint8_t *m) +{ + Hacl_Impl_Poly1305_32_poly1305_update(st, m); +} + +void +Hacl_Poly1305_32_update( + Hacl_Impl_Poly1305_32_State_poly1305_state st, + uint8_t *m, + uint32_t len1) +{ + if (!(len1 == (uint32_t)0U)) { + uint8_t *block = m; + uint8_t *m_ = m + (uint32_t)16U; + uint32_t len2 = len1 - (uint32_t)1U; + Hacl_Poly1305_32_update_block(st, block); + Hacl_Poly1305_32_update(st, m_, len2); + } +} + +void +Hacl_Poly1305_32_update_last( + Hacl_Impl_Poly1305_32_State_poly1305_state st, + uint8_t *m, + uint32_t len1) +{ + if (!((uint64_t)len1 == (uint64_t)0U)) + Hacl_Impl_Poly1305_32_poly1305_process_last_block(st, m, (uint64_t)len1); + Hacl_Impl_Poly1305_32_State_poly1305_state scrut = st; + uint32_t *h = scrut.h; + uint32_t *acc = h; + Hacl_Impl_Poly1305_32_poly1305_last_pass(acc); +} + +void +Hacl_Poly1305_32_finish( + Hacl_Impl_Poly1305_32_State_poly1305_state st, + uint8_t *mac, + uint8_t *k1) +{ + Hacl_Impl_Poly1305_32_State_poly1305_state scrut = st; + uint32_t *h = scrut.h; + uint32_t *acc = h; + FStar_UInt128_t k_ = load128_le(k1); + uint32_t h0 = acc[0U]; + uint32_t h1 = acc[1U]; + uint32_t h2 = acc[2U]; + uint32_t h3 = acc[3U]; + uint32_t h4 = acc[4U]; + FStar_UInt128_t + acc_ = + FStar_UInt128_logor(FStar_UInt128_shift_left(FStar_UInt128_uint64_to_uint128((uint64_t)h4), + (uint32_t)104U), + FStar_UInt128_logor(FStar_UInt128_shift_left(FStar_UInt128_uint64_to_uint128((uint64_t)h3), + (uint32_t)78U), + FStar_UInt128_logor(FStar_UInt128_shift_left(FStar_UInt128_uint64_to_uint128((uint64_t)h2), + (uint32_t)52U), + FStar_UInt128_logor(FStar_UInt128_shift_left(FStar_UInt128_uint64_to_uint128((uint64_t)h1), + (uint32_t)26U), + FStar_UInt128_uint64_to_uint128((uint64_t)h0))))); + FStar_UInt128_t mac_ = FStar_UInt128_add_mod(acc_, k_); + store128_le(mac, mac_); +} + +void +Hacl_Poly1305_32_crypto_onetimeauth( + uint8_t *output, + uint8_t *input, + uint64_t len1, + uint8_t *k1) +{ + Hacl_Standalone_Poly1305_32_crypto_onetimeauth(output, input, len1, k1); +} diff --git a/security/nss/lib/freebl/verified/Hacl_Poly1305_32.h b/security/nss/lib/freebl/verified/Hacl_Poly1305_32.h new file mode 100644 index 000000000..4dd070026 --- /dev/null +++ b/security/nss/lib/freebl/verified/Hacl_Poly1305_32.h @@ -0,0 +1,103 @@ +/* Copyright 2016-2017 INRIA and Microsoft Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kremlib.h" +#ifndef __Hacl_Poly1305_32_H +#define __Hacl_Poly1305_32_H + +typedef uint32_t Hacl_Bignum_Constants_limb; + +typedef uint64_t Hacl_Bignum_Constants_wide; + +typedef uint64_t Hacl_Bignum_Wide_t; + +typedef uint32_t Hacl_Bignum_Limb_t; + +typedef void *Hacl_Impl_Poly1305_32_State_log_t; + +typedef uint8_t *Hacl_Impl_Poly1305_32_State_uint8_p; + +typedef uint32_t *Hacl_Impl_Poly1305_32_State_bigint; + +typedef void *Hacl_Impl_Poly1305_32_State_seqelem; + +typedef uint32_t *Hacl_Impl_Poly1305_32_State_elemB; + +typedef uint8_t *Hacl_Impl_Poly1305_32_State_wordB; + +typedef uint8_t *Hacl_Impl_Poly1305_32_State_wordB_16; + +typedef struct +{ + uint32_t *r; + uint32_t *h; +} Hacl_Impl_Poly1305_32_State_poly1305_state; + +typedef void *Hacl_Impl_Poly1305_32_log_t; + +typedef uint32_t *Hacl_Impl_Poly1305_32_bigint; + +typedef uint8_t *Hacl_Impl_Poly1305_32_uint8_p; + +typedef uint32_t *Hacl_Impl_Poly1305_32_elemB; + +typedef uint8_t *Hacl_Impl_Poly1305_32_wordB; + +typedef uint8_t *Hacl_Impl_Poly1305_32_wordB_16; + +typedef uint8_t *Hacl_Poly1305_32_uint8_p; + +typedef uint64_t Hacl_Poly1305_32_uint64_t; + +void *Hacl_Poly1305_32_op_String_Access(FStar_Monotonic_HyperStack_mem h, uint8_t *b); + +typedef uint8_t *Hacl_Poly1305_32_key; + +typedef Hacl_Impl_Poly1305_32_State_poly1305_state Hacl_Poly1305_32_state; + +Hacl_Impl_Poly1305_32_State_poly1305_state +Hacl_Poly1305_32_mk_state(uint32_t *r, uint32_t *acc); + +void Hacl_Poly1305_32_init(Hacl_Impl_Poly1305_32_State_poly1305_state st, uint8_t *k1); + +extern void *Hacl_Poly1305_32_empty_log; + +void Hacl_Poly1305_32_update_block(Hacl_Impl_Poly1305_32_State_poly1305_state st, uint8_t *m); + +void +Hacl_Poly1305_32_update( + Hacl_Impl_Poly1305_32_State_poly1305_state st, + uint8_t *m, + uint32_t len1); + +void +Hacl_Poly1305_32_update_last( + Hacl_Impl_Poly1305_32_State_poly1305_state st, + uint8_t *m, + uint32_t len1); + +void +Hacl_Poly1305_32_finish( + Hacl_Impl_Poly1305_32_State_poly1305_state st, + uint8_t *mac, + uint8_t *k1); + +void +Hacl_Poly1305_32_crypto_onetimeauth( + uint8_t *output, + uint8_t *input, + uint64_t len1, + uint8_t *k1); +#endif diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c index 9954f0ca6..f73b95f68 100644 --- a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c @@ -70,7 +70,7 @@ static const PKIX_UInt32 httpprotocolLen = 5; /* strlen(httpprotocol) */ * The address at which the Boolean state machine flag is stored to * indicate whether processing can continue without further input. * Must be non-NULL. - * "plContext" + * "plCtx" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) @@ -85,7 +85,7 @@ pkix_pl_HttpDefaultClient_HdrCheckComplete( PKIX_PL_HttpDefaultClient *client, PKIX_UInt32 bytesRead, PKIX_Boolean *pKeepGoing, - void *plContext) + void *plCtx) { PKIX_UInt32 alreadyScanned = 0; PKIX_UInt32 comp = 0; @@ -142,7 +142,7 @@ pkix_pl_HttpDefaultClient_HdrCheckComplete( headerLength = (eoh - client->rcvBuf); /* allocate space to copy header (and for the NULL terminator) */ - PKIX_CHECK(PKIX_PL_Malloc(headerLength + 1, (void **)©, plContext), + PKIX_CHECK(PKIX_PL_Malloc(headerLength + 1, (void **)©, plCtx), PKIX_MALLOCFAILED); /* copy header data before we corrupt it (by storing NULLs) */ @@ -301,7 +301,7 @@ pkix_pl_HttpDefaultClient_HdrCheckComplete( if (contentLength > 0) { /* allocate a buffer of size contentLength for the content */ - PKIX_CHECK(PKIX_PL_Malloc(contentLength, (void **)&body, plContext), + PKIX_CHECK(PKIX_PL_Malloc(contentLength, (void **)&body, plCtx), PKIX_MALLOCFAILED); /* copy any remaining bytes in current buffer into new buffer */ @@ -311,7 +311,7 @@ pkix_pl_HttpDefaultClient_HdrCheckComplete( } } - PKIX_CHECK(PKIX_PL_Free(client->rcvBuf, plContext), + PKIX_CHECK(PKIX_PL_Free(client->rcvBuf, plCtx), PKIX_FREEFAILED); client->rcvBuf = body; @@ -340,7 +340,7 @@ cleanup: * "pClient" * The address at which the created HttpDefaultClient is to be stored. * Must be non-NULL. - * "plContext" + * "plCtx" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) @@ -355,7 +355,7 @@ pkix_pl_HttpDefaultClient_Create( const char *host, PRUint16 portnum, PKIX_PL_HttpDefaultClient **pClient, - void *plContext) + void *plCtx) { PKIX_PL_HttpDefaultClient *client = NULL; @@ -367,7 +367,7 @@ pkix_pl_HttpDefaultClient_Create( (PKIX_HTTPDEFAULTCLIENT_TYPE, sizeof (PKIX_PL_HttpDefaultClient), (PKIX_PL_Object **)&client, - plContext), + plCtx), PKIX_COULDNOTCREATEHTTPDEFAULTCLIENTOBJECT); /* Client timeout is overwritten in HttpDefaultClient_RequestCreate @@ -408,10 +408,10 @@ pkix_pl_HttpDefaultClient_Create( client->socket = NULL; /* - * The HttpClient API does not include a plContext argument in its + * The HttpClient API does not include a plCtx argument in its * function calls. Save it here. */ - client->plContext = plContext; + client->plContext = plCtx; *pClient = client; @@ -430,7 +430,7 @@ cleanup: static PKIX_Error * pkix_pl_HttpDefaultClient_Destroy( PKIX_PL_Object *object, - void *plContext) + void *plCtx) { PKIX_PL_HttpDefaultClient *client = NULL; @@ -438,13 +438,13 @@ pkix_pl_HttpDefaultClient_Destroy( PKIX_NULLCHECK_ONE(object); PKIX_CHECK(pkix_CheckType - (object, PKIX_HTTPDEFAULTCLIENT_TYPE, plContext), + (object, PKIX_HTTPDEFAULTCLIENT_TYPE, plCtx), PKIX_OBJECTNOTANHTTPDEFAULTCLIENT); client = (PKIX_PL_HttpDefaultClient *)object; if (client->rcvHeaders) { - PKIX_PL_Free(client->rcvHeaders, plContext); + PKIX_PL_Free(client->rcvHeaders, plCtx); client->rcvHeaders = NULL; } if (client->rcvContentType) { @@ -456,11 +456,11 @@ pkix_pl_HttpDefaultClient_Destroy( client->GETBuf = NULL; } if (client->POSTBuf != NULL) { - PKIX_PL_Free(client->POSTBuf, plContext); + PKIX_PL_Free(client->POSTBuf, plCtx); client->POSTBuf = NULL; } if (client->rcvBuf != NULL) { - PKIX_PL_Free(client->rcvBuf, plContext); + PKIX_PL_Free(client->rcvBuf, plCtx); client->rcvBuf = NULL; } if (client->host) { @@ -493,7 +493,7 @@ cleanup: * thread-safe. */ PKIX_Error * -pkix_pl_HttpDefaultClient_RegisterSelf(void *plContext) +pkix_pl_HttpDefaultClient_RegisterSelf(void *plCtx) { extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; pkix_ClassTable_Entry *entry = @@ -529,7 +529,7 @@ pkix_pl_HttpDefaultClient_RegisterSelf(void *plContext) * The address at which the Boolean state machine flag is stored to * indicate whether processing can continue without further input. * Must be non-NULL. - * "plContext" + * "plCtx" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) @@ -543,7 +543,7 @@ static PKIX_Error * pkix_pl_HttpDefaultClient_ConnectContinue( PKIX_PL_HttpDefaultClient *client, PKIX_Boolean *pKeepGoing, - void *plContext) + void *plCtx) { PRErrorCode status; PKIX_Boolean keepGoing = PKIX_FALSE; @@ -557,7 +557,7 @@ pkix_pl_HttpDefaultClient_ConnectContinue( callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; PKIX_CHECK(callbackList->connectcontinueCallback - (client->socket, &status, plContext), + (client->socket, &status, plCtx), PKIX_SOCKETCONNECTCONTINUEFAILED); if (status == 0) { @@ -595,7 +595,7 @@ cleanup: * "pBytesTransferred" * The address at which the number of bytes sent is stored. Must be * non-NULL. - * "plContext" + * "plCtx" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) @@ -610,7 +610,7 @@ pkix_pl_HttpDefaultClient_Send( PKIX_PL_HttpDefaultClient *client, PKIX_Boolean *pKeepGoing, PKIX_UInt32 *pBytesTransferred, - void *plContext) + void *plCtx) { PKIX_Int32 bytesWritten = 0; PKIX_Int32 lenToWrite = 0; @@ -640,7 +640,7 @@ pkix_pl_HttpDefaultClient_Send( dataToWrite, lenToWrite, &bytesWritten, - plContext), + plCtx), PKIX_SOCKETSENDFAILED); client->rcvBuf = NULL; @@ -690,7 +690,7 @@ cleanup: * "pBytesTransferred" * The address at which the number of bytes sent is stored. Must be * non-NULL. - * "plContext" + * "plCtx" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) @@ -705,7 +705,7 @@ pkix_pl_HttpDefaultClient_SendContinue( PKIX_PL_HttpDefaultClient *client, PKIX_Boolean *pKeepGoing, PKIX_UInt32 *pBytesTransferred, - void *plContext) + void *plCtx) { PKIX_Int32 bytesWritten = 0; PKIX_PL_Socket_Callback *callbackList = NULL; @@ -718,7 +718,7 @@ pkix_pl_HttpDefaultClient_SendContinue( callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; PKIX_CHECK(callbackList->pollCallback - (client->socket, &bytesWritten, NULL, plContext), + (client->socket, &bytesWritten, NULL, plCtx), PKIX_SOCKETPOLLFAILED); /* @@ -752,7 +752,7 @@ cleanup: * The address at which the Boolean state machine flag is stored to * indicate whether processing can continue without further input. * Must be non-NULL. - * "plContext" + * "plCtx" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) @@ -766,7 +766,7 @@ static PKIX_Error * pkix_pl_HttpDefaultClient_RecvHdr( PKIX_PL_HttpDefaultClient *client, PKIX_Boolean *pKeepGoing, - void *plContext) + void *plCtx) { PKIX_UInt32 bytesToRead = 0; PKIX_Int32 bytesRead = 0; @@ -787,7 +787,7 @@ pkix_pl_HttpDefaultClient_RecvHdr( (client->rcvBuf, client->capacity, (void **)&(client->rcvBuf), - plContext), + plCtx), PKIX_REALLOCFAILED); bytesToRead = client->capacity - client->filledupBytes; @@ -799,7 +799,7 @@ pkix_pl_HttpDefaultClient_RecvHdr( (void *)&(client->rcvBuf[client->filledupBytes]), bytesToRead, &bytesRead, - plContext), + plCtx), PKIX_SOCKETRECVFAILED); if (bytesRead > 0) { @@ -808,7 +808,7 @@ pkix_pl_HttpDefaultClient_RecvHdr( PKIX_CHECK( pkix_pl_HttpDefaultClient_HdrCheckComplete(client, bytesRead, pKeepGoing, - plContext), + plCtx), PKIX_HTTPDEFAULTCLIENTHDRCHECKCOMPLETEFAILED); } else { client->connectStatus = HTTP_RECV_HDR_PENDING; @@ -834,7 +834,7 @@ cleanup: * The address at which the Boolean state machine flag is stored to * indicate whether processing can continue without further input. * Must be non-NULL. - * "plContext" + * "plCtx" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) @@ -848,7 +848,7 @@ static PKIX_Error * pkix_pl_HttpDefaultClient_RecvHdrContinue( PKIX_PL_HttpDefaultClient *client, PKIX_Boolean *pKeepGoing, - void *plContext) + void *plCtx) { PKIX_Int32 bytesRead = 0; PKIX_PL_Socket_Callback *callbackList = NULL; @@ -861,14 +861,14 @@ pkix_pl_HttpDefaultClient_RecvHdrContinue( callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; PKIX_CHECK(callbackList->pollCallback - (client->socket, NULL, &bytesRead, plContext), + (client->socket, NULL, &bytesRead, plCtx), PKIX_SOCKETPOLLFAILED); if (bytesRead > 0) { client->filledupBytes += bytesRead; PKIX_CHECK(pkix_pl_HttpDefaultClient_HdrCheckComplete - (client, bytesRead, pKeepGoing, plContext), + (client, bytesRead, pKeepGoing, plCtx), PKIX_HTTPDEFAULTCLIENTHDRCHECKCOMPLETEFAILED); } else { @@ -897,7 +897,7 @@ cleanup: * The address at which the Boolean state machine flag is stored to * indicate whether processing can continue without further input. * Must be non-NULL. - * "plContext" + * "plCtx" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) @@ -911,7 +911,7 @@ static PKIX_Error * pkix_pl_HttpDefaultClient_RecvBody( PKIX_PL_HttpDefaultClient *client, PKIX_Boolean *pKeepGoing, - void *plContext) + void *plCtx) { PKIX_Int32 bytesRead = 0; PKIX_Int32 bytesToRead = 0; @@ -952,7 +952,7 @@ pkix_pl_HttpDefaultClient_RecvBody( client->capacity = newLength; PKIX_CHECK( PKIX_PL_Realloc(client->rcvBuf, newLength, - (void**)&client->rcvBuf, plContext), + (void**)&client->rcvBuf, plCtx), PKIX_REALLOCFAILED); freeBuffSize = client->capacity - client->filledupBytes; @@ -964,7 +964,7 @@ pkix_pl_HttpDefaultClient_RecvBody( /* Use poll callback if waiting on non-blocking IO */ if (client->connectStatus == HTTP_RECV_BODY_PENDING) { PKIX_CHECK(callbackList->pollCallback - (client->socket, NULL, &bytesRead, plContext), + (client->socket, NULL, &bytesRead, plCtx), PKIX_SOCKETPOLLFAILED); } else { PKIX_CHECK(callbackList->recvCallback @@ -972,7 +972,7 @@ pkix_pl_HttpDefaultClient_RecvBody( (void *)&(client->rcvBuf[client->filledupBytes]), bytesToRead, &bytesRead, - plContext), + plCtx), PKIX_SOCKETRECVFAILED); } @@ -1026,7 +1026,7 @@ cleanup: * PARAMETERS: * "client" * The address of the HttpDefaultClient object. Must be non-NULL. - * "plContext" + * "plCtx" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) @@ -1039,7 +1039,7 @@ cleanup: static PKIX_Error * pkix_pl_HttpDefaultClient_Dispatch( PKIX_PL_HttpDefaultClient *client, - void *plContext) + void *plCtx) { PKIX_UInt32 bytesTransferred = 0; PKIX_Boolean keepGoing = PKIX_TRUE; @@ -1051,33 +1051,33 @@ pkix_pl_HttpDefaultClient_Dispatch( switch (client->connectStatus) { case HTTP_CONNECT_PENDING: PKIX_CHECK(pkix_pl_HttpDefaultClient_ConnectContinue - (client, &keepGoing, plContext), + (client, &keepGoing, plCtx), PKIX_HTTPDEFAULTCLIENTCONNECTCONTINUEFAILED); break; case HTTP_CONNECTED: PKIX_CHECK(pkix_pl_HttpDefaultClient_Send - (client, &keepGoing, &bytesTransferred, plContext), + (client, &keepGoing, &bytesTransferred, plCtx), PKIX_HTTPDEFAULTCLIENTSENDFAILED); break; case HTTP_SEND_PENDING: PKIX_CHECK(pkix_pl_HttpDefaultClient_SendContinue - (client, &keepGoing, &bytesTransferred, plContext), + (client, &keepGoing, &bytesTransferred, plCtx), PKIX_HTTPDEFAULTCLIENTSENDCONTINUEFAILED); break; case HTTP_RECV_HDR: PKIX_CHECK(pkix_pl_HttpDefaultClient_RecvHdr - (client, &keepGoing, plContext), + (client, &keepGoing, plCtx), PKIX_HTTPDEFAULTCLIENTRECVHDRFAILED); break; case HTTP_RECV_HDR_PENDING: PKIX_CHECK(pkix_pl_HttpDefaultClient_RecvHdrContinue - (client, &keepGoing, plContext), + (client, &keepGoing, plCtx), PKIX_HTTPDEFAULTCLIENTRECVHDRCONTINUEFAILED); break; case HTTP_RECV_BODY: case HTTP_RECV_BODY_PENDING: PKIX_CHECK(pkix_pl_HttpDefaultClient_RecvBody - (client, &keepGoing, plContext), + (client, &keepGoing, plCtx), PKIX_HTTPDEFAULTCLIENTRECVBODYFAILED); break; case HTTP_ERROR: @@ -1106,7 +1106,7 @@ pkix_pl_HttpDefaultClient_CreateSession( const char *host, PRUint16 portnum, SEC_HTTP_SERVER_SESSION *pSession, - void *plContext) + void *plCtx) { PKIX_PL_HttpDefaultClient *client = NULL; @@ -1115,7 +1115,7 @@ pkix_pl_HttpDefaultClient_CreateSession( PKIX_NULLCHECK_TWO(host, pSession); PKIX_CHECK(pkix_pl_HttpDefaultClient_Create - (host, portnum, &client, plContext), + (host, portnum, &client, plCtx), PKIX_HTTPDEFAULTCLIENTCREATEFAILED); *pSession = (SEC_HTTP_SERVER_SESSION)client; @@ -1130,7 +1130,7 @@ PKIX_Error * pkix_pl_HttpDefaultClient_KeepAliveSession( SEC_HTTP_SERVER_SESSION session, PRPollDesc **pPollDesc, - void *plContext) + void *plCtx) { PKIX_ENTER (HTTPDEFAULTCLIENT, @@ -1140,7 +1140,7 @@ pkix_pl_HttpDefaultClient_KeepAliveSession( PKIX_CHECK(pkix_CheckType ((PKIX_PL_Object *)session, PKIX_HTTPDEFAULTCLIENT_TYPE, - plContext), + plCtx), PKIX_SESSIONNOTANHTTPDEFAULTCLIENT); /* XXX Not implemented */ @@ -1159,7 +1159,7 @@ pkix_pl_HttpDefaultClient_RequestCreate( const char *http_request_method, const PRIntervalTime timeout, SEC_HTTP_REQUEST_SESSION *pRequest, - void *plContext) + void *plCtx) { PKIX_PL_HttpDefaultClient *client = NULL; PKIX_PL_Socket *socket = NULL; @@ -1174,7 +1174,7 @@ pkix_pl_HttpDefaultClient_RequestCreate( PKIX_CHECK(pkix_CheckType ((PKIX_PL_Object *)session, PKIX_HTTPDEFAULTCLIENT_TYPE, - plContext), + plCtx), PKIX_SESSIONNOTANHTTPDEFAULTCLIENT); client = (PKIX_PL_HttpDefaultClient *)session; @@ -1212,7 +1212,7 @@ pkix_pl_HttpDefaultClient_RequestCreate( 2001, /* client->portnum, */ &status, &socket, - plContext), + plCtx), PKIX_HTTPCERTSTOREFINDSOCKETCONNECTIONFAILED); #else PKIX_CHECK(pkix_HttpCertStore_FindSocketConnection @@ -1221,20 +1221,20 @@ pkix_pl_HttpDefaultClient_RequestCreate( client->portnum, &status, &socket, - plContext), + plCtx), PKIX_HTTPCERTSTOREFINDSOCKETCONNECTIONFAILED); #endif client->socket = socket; PKIX_CHECK(pkix_pl_Socket_GetCallbackList - (socket, &callbackList, plContext), + (socket, &callbackList, plCtx), PKIX_SOCKETGETCALLBACKLISTFAILED); client->callbackList = (void *)callbackList; PKIX_CHECK(pkix_pl_Socket_GetPRFileDesc - (socket, &fileDesc, plContext), + (socket, &fileDesc, plCtx), PKIX_SOCKETGETPRFILEDESCFAILED); client->pollDesc.fd = fileDesc; @@ -1264,7 +1264,7 @@ pkix_pl_HttpDefaultClient_SetPostData( const char *http_data, const PRUint32 http_data_len, const char *http_content_type, - void *plContext) + void *plCtx) { PKIX_PL_HttpDefaultClient *client = NULL; @@ -1276,7 +1276,7 @@ pkix_pl_HttpDefaultClient_SetPostData( PKIX_CHECK(pkix_CheckType ((PKIX_PL_Object *)request, PKIX_HTTPDEFAULTCLIENT_TYPE, - plContext), + plCtx), PKIX_REQUESTNOTANHTTPDEFAULTCLIENT); client = (PKIX_PL_HttpDefaultClient *)request; @@ -1307,7 +1307,7 @@ pkix_pl_HttpDefaultClient_TrySendAndReceive( PRUint32 *http_response_data_len, PRPollDesc **pPollDesc, SECStatus *pSECReturn, - void *plContext) + void *plCtx) { PKIX_PL_HttpDefaultClient *client = NULL; PKIX_UInt32 postLen = 0; @@ -1324,7 +1324,7 @@ pkix_pl_HttpDefaultClient_TrySendAndReceive( PKIX_CHECK(pkix_CheckType ((PKIX_PL_Object *)request, PKIX_HTTPDEFAULTCLIENT_TYPE, - plContext), + plCtx), PKIX_REQUESTNOTANHTTPDEFAULTCLIENT); client = (PKIX_PL_HttpDefaultClient *)request; @@ -1380,7 +1380,7 @@ pkix_pl_HttpDefaultClient_TrySendAndReceive( PKIX_CHECK(PKIX_PL_Malloc (client->POSTLen, (void **)&(client->POSTBuf), - plContext), + plCtx), PKIX_MALLOCFAILED); /* copy header into postBuffer */ @@ -1407,7 +1407,7 @@ pkix_pl_HttpDefaultClient_TrySendAndReceive( } /* continue according to state */ - PKIX_CHECK(pkix_pl_HttpDefaultClient_Dispatch(client, plContext), + PKIX_CHECK(pkix_pl_HttpDefaultClient_Dispatch(client, plCtx), PKIX_HTTPDEFAULTCLIENTDISPATCHFAILED); switch (client->connectStatus) { @@ -1478,7 +1478,7 @@ cleanup: PKIX_Error * pkix_pl_HttpDefaultClient_Cancel( SEC_HTTP_REQUEST_SESSION request, - void *plContext) + void *plCtx) { PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_Cancel"); PKIX_NULLCHECK_ONE(request); @@ -1486,7 +1486,7 @@ pkix_pl_HttpDefaultClient_Cancel( PKIX_CHECK(pkix_CheckType ((PKIX_PL_Object *)request, PKIX_HTTPDEFAULTCLIENT_TYPE, - plContext), + plCtx), PKIX_REQUESTNOTANHTTPDEFAULTCLIENT); /* XXX Not implemented */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.c index 9fa8e9260..09b54a2be 100644 --- a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.c +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.c @@ -23,8 +23,8 @@ * PARAMETERS * "method" * The UInt32 value to be stored as the method field of the InfoAccess. - * "generalName" - * The GeneralName to be stored as the generalName field of the InfoAccess. + * "gName" + * The GeneralName to be stored as the gName field of the InfoAccess. * Must be non-NULL. * "pInfoAccess" * Address where the result is stored. Must be non-NULL. @@ -39,7 +39,7 @@ static PKIX_Error * pkix_pl_InfoAccess_Create( PKIX_UInt32 method, - PKIX_PL_GeneralName *generalName, + PKIX_PL_GeneralName *gName, PKIX_PL_InfoAccess **pInfoAccess, void *plContext) { @@ -47,7 +47,7 @@ pkix_pl_InfoAccess_Create( PKIX_PL_InfoAccess *infoAccess = NULL; PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_Create"); - PKIX_NULLCHECK_TWO(generalName, pInfoAccess); + PKIX_NULLCHECK_TWO(gName, pInfoAccess); PKIX_CHECK(PKIX_PL_Object_Alloc (PKIX_INFOACCESS_TYPE, @@ -58,8 +58,8 @@ pkix_pl_InfoAccess_Create( infoAccess->method = method; - PKIX_INCREF(generalName); - infoAccess->location = generalName; + PKIX_INCREF(gName); + infoAccess->location = gName; *pInfoAccess = infoAccess; infoAccess = NULL; @@ -678,7 +678,7 @@ pkix_pl_UnescapeURL( * [binary|<other-type>]]* * * PARAMETERS - * "generalName" + * "gName" * Address of the GeneralName whose LDAPLocation is to be parsed. Must be * non-NULL. * "arena" @@ -700,7 +700,7 @@ pkix_pl_UnescapeURL( */ PKIX_Error * pkix_pl_InfoAccess_ParseLocation( - PKIX_PL_GeneralName *generalName, + PKIX_PL_GeneralName *gName, PLArenaPool *arena, LDAPRequestParams *request, char **pDomainName, @@ -722,9 +722,9 @@ pkix_pl_InfoAccess_ParseLocation( LDAPNameComponent *nameComponent = NULL; PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_ParseLocation"); - PKIX_NULLCHECK_FOUR(generalName, arena, request, pDomainName); + PKIX_NULLCHECK_FOUR(gName, arena, request, pDomainName); - PKIX_TOSTRING(generalName, &locationString, plContext, + PKIX_TOSTRING(gName, &locationString, plContext, PKIX_GENERALNAMETOSTRINGFAILED); PKIX_CHECK(PKIX_PL_String_GetEncoded diff --git a/security/nss/lib/nss/nss.h b/security/nss/lib/nss/nss.h index d62f4957b..efb0827c5 100644 --- a/security/nss/lib/nss/nss.h +++ b/security/nss/lib/nss/nss.h @@ -22,10 +22,10 @@ * The format of the version string should be * "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]" */ -#define NSS_VERSION "3.36.4" _NSS_CUSTOMIZED +#define NSS_VERSION "3.38" _NSS_CUSTOMIZED #define NSS_VMAJOR 3 -#define NSS_VMINOR 36 -#define NSS_VPATCH 4 +#define NSS_VMINOR 38 +#define NSS_VPATCH 0 #define NSS_VBUILD 0 #define NSS_BETA PR_FALSE diff --git a/security/nss/lib/pk11wrap/pk11akey.c b/security/nss/lib/pk11wrap/pk11akey.c index c45901ec3..346e473a9 100644 --- a/security/nss/lib/pk11wrap/pk11akey.c +++ b/security/nss/lib/pk11wrap/pk11akey.c @@ -804,12 +804,30 @@ PK11_MakePrivKey(PK11SlotInfo *slot, KeyType keyType, /* don't know? look it up */ if (keyType == nullKey) { CK_KEY_TYPE pk11Type = CKK_RSA; + SECItem info; pk11Type = PK11_ReadULongAttribute(slot, privID, CKA_KEY_TYPE); isTemp = (PRBool)!PK11_HasAttributeSet(slot, privID, CKA_TOKEN, PR_FALSE); switch (pk11Type) { case CKK_RSA: keyType = rsaKey; + /* determine RSA key type from the CKA_PUBLIC_KEY_INFO if present */ + rv = PK11_ReadAttribute(slot, privID, CKA_PUBLIC_KEY_INFO, NULL, &info); + if (rv == SECSuccess) { + CERTSubjectPublicKeyInfo *spki; + + spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&info); + if (spki) { + SECOidTag tag; + + tag = SECOID_GetAlgorithmTag(&spki->algorithm); + if (tag == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) + keyType = rsaPssKey; + SECKEY_DestroySubjectPublicKeyInfo(spki); + } + SECITEM_FreeItem(&info, PR_FALSE); + } + break; case CKK_DSA: keyType = dsaKey; diff --git a/security/nss/lib/pk11wrap/pk11pars.c b/security/nss/lib/pk11wrap/pk11pars.c index fc30222b3..c165e1ef2 100644 --- a/security/nss/lib/pk11wrap/pk11pars.c +++ b/security/nss/lib/pk11wrap/pk11pars.c @@ -547,16 +547,16 @@ secmod_applyCryptoPolicy(const char *policyString, for (i = 0; i < PR_ARRAY_SIZE(algOptList); i++) { const oidValDef *algOpt = &algOptList[i]; unsigned name_size = algOpt->name_size; - PRBool newValue = PR_FALSE; + PRBool newOption = PR_FALSE; if ((length >= name_size) && (cipher[name_size] == '/')) { - newValue = PR_TRUE; + newOption = PR_TRUE; } - if ((newValue || algOpt->name_size == length) && + if ((newOption || algOpt->name_size == length) && PORT_Strncasecmp(algOpt->name, cipher, name_size) == 0) { PRUint32 value = algOpt->val; PRUint32 enable, disable; - if (newValue) { + if (newOption) { value = secmod_parsePolicyValue(&cipher[name_size] + 1, length - name_size - 1); } diff --git a/security/nss/lib/pkcs12/p12e.c b/security/nss/lib/pkcs12/p12e.c index 4a21d8955..c42c4d2e2 100644 --- a/security/nss/lib/pkcs12/p12e.c +++ b/security/nss/lib/pkcs12/p12e.c @@ -884,7 +884,9 @@ sec_PKCS12AddAttributeToBag(SEC_PKCS12ExportContext *p12ctxt, unsigned int nItems = 0; SECStatus rv; - if (!safeBag || !p12ctxt) { + PORT_Assert(p12ctxt->arena == safeBag->arena); + if (!safeBag || !p12ctxt || p12ctxt->arena != safeBag->arena) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } @@ -1589,6 +1591,7 @@ sec_pkcs12_encoder_start_context(SEC_PKCS12ExportContext *p12exp) params = PK11_CreatePBEParams(salt, &pwd, NSS_PBE_DEFAULT_ITERATION_COUNT); SECITEM_ZfreeItem(salt, PR_TRUE); + salt = NULL; SECITEM_ZfreeItem(&pwd, PR_FALSE); /* get the PBA Mechanism to generate the key */ diff --git a/security/nss/lib/pkcs7/p7decode.c b/security/nss/lib/pkcs7/p7decode.c index 4f17b8e84..ba51955ab 100644 --- a/security/nss/lib/pkcs7/p7decode.c +++ b/security/nss/lib/pkcs7/p7decode.c @@ -1596,7 +1596,6 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo, } else { SECItem *sig; SECItem holder; - SECStatus rv; /* * No authenticated attributes. diff --git a/security/nss/lib/pki/pki3hack.c b/security/nss/lib/pki/pki3hack.c index fb3110a23..fab3a7a02 100644 --- a/security/nss/lib/pki/pki3hack.c +++ b/security/nss/lib/pki/pki3hack.c @@ -1143,8 +1143,8 @@ STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust) (PRBool)(trust->sslFlags & CERTDB_GOVT_APPROVED_CA); if (c->object.cryptoContext != NULL) { /* The cert is in a context, set the trust there */ - NSSCryptoContext *cc = c->object.cryptoContext; - nssrv = nssCryptoContext_ImportTrust(cc, nssTrust); + NSSCryptoContext *cctx = c->object.cryptoContext; + nssrv = nssCryptoContext_ImportTrust(cctx, nssTrust); if (nssrv != PR_SUCCESS) { goto done; } diff --git a/security/nss/lib/smime/cmsrecinfo.c b/security/nss/lib/smime/cmsrecinfo.c index 2efb6b1f2..8cab288d2 100644 --- a/security/nss/lib/smime/cmsrecinfo.c +++ b/security/nss/lib/smime/cmsrecinfo.c @@ -82,7 +82,7 @@ nss_cmsrecipientinfo_create(NSSCMSMessage *cmsg, if (DERinput) { /* decode everything from DER */ SECItem newinput; - SECStatus rv = SECITEM_CopyItem(poolp, &newinput, DERinput); + rv = SECITEM_CopyItem(poolp, &newinput, DERinput); if (SECSuccess != rv) goto loser; rv = SEC_QuickDERDecodeItem(poolp, ri, NSSCMSRecipientInfoTemplate, &newinput); diff --git a/security/nss/lib/softoken/legacydb/pcertdb.c b/security/nss/lib/softoken/legacydb/pcertdb.c index 2e8b650ee..47778190d 100644 --- a/security/nss/lib/softoken/legacydb/pcertdb.c +++ b/security/nss/lib/softoken/legacydb/pcertdb.c @@ -2577,14 +2577,13 @@ ReadDBSubjectEntry(NSSLOWCERTCertDBHandle *handle, SECItem *derSubject) SECItem dbentry; SECStatus rv; + PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE); arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; } - PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE); - entry = (certDBEntrySubject *)PORT_ArenaAlloc(arena, sizeof(certDBEntrySubject)); if (entry == NULL) { diff --git a/security/nss/lib/softoken/lowkey.c b/security/nss/lib/softoken/lowkey.c index 295d55f40..a28a3a55e 100644 --- a/security/nss/lib/softoken/lowkey.c +++ b/security/nss/lib/softoken/lowkey.c @@ -45,6 +45,23 @@ const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = { { 0 } }; +const SEC_ASN1Template nsslowkey_SubjectPublicKeyInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYSubjectPublicKeyInfo) }, + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, + offsetof(NSSLOWKEYSubjectPublicKeyInfo, algorithm), + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, + { SEC_ASN1_BIT_STRING, + offsetof(NSSLOWKEYSubjectPublicKeyInfo, subjectPublicKey) }, + { 0 } +}; + +const SEC_ASN1Template nsslowkey_RSAPublicKeyTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPublicKey) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey, u.rsa.modulus) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey, u.rsa.publicExponent) }, + { 0 } +}; + const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) }, { SEC_ASN1_INTEGER, offsetof(PQGParams, prime) }, @@ -135,6 +152,13 @@ prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) } void +prepare_low_rsa_pub_key_for_asn1(NSSLOWKEYPublicKey *key) +{ + key->u.rsa.modulus.type = siUnsignedInteger; + key->u.rsa.publicExponent.type = siUnsignedInteger; +} + +void prepare_low_pqg_params_for_asn1(PQGParams *params) { params->prime.type = siUnsignedInteger; diff --git a/security/nss/lib/softoken/lowkeyi.h b/security/nss/lib/softoken/lowkeyi.h index f9ba3a75f..e599f01fa 100644 --- a/security/nss/lib/softoken/lowkeyi.h +++ b/security/nss/lib/softoken/lowkeyi.h @@ -27,6 +27,7 @@ extern void prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key); extern void prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key); extern void prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key); extern void prepare_low_ecparams_for_asn1(ECParams *params); +extern void prepare_low_rsa_pub_key_for_asn1(NSSLOWKEYPublicKey *key); /* ** Destroy a private key object. diff --git a/security/nss/lib/softoken/lowkeyti.h b/security/nss/lib/softoken/lowkeyti.h index c048b33e7..7e77592c5 100644 --- a/security/nss/lib/softoken/lowkeyti.h +++ b/security/nss/lib/softoken/lowkeyti.h @@ -25,6 +25,8 @@ extern const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[]; extern const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[]; extern const SEC_ASN1Template nsslowkey_EncryptedPrivateKeyInfoTemplate[]; +extern const SEC_ASN1Template nsslowkey_SubjectPublicKeyInfoTemplate[]; +extern const SEC_ASN1Template nsslowkey_RSAPublicKeyTemplate[]; /* * PKCS #8 attributes @@ -48,6 +50,13 @@ struct NSSLOWKEYPrivateKeyInfoStr { typedef struct NSSLOWKEYPrivateKeyInfoStr NSSLOWKEYPrivateKeyInfo; #define NSSLOWKEY_PRIVATE_KEY_INFO_VERSION 0 /* what we *create* */ +struct NSSLOWKEYSubjectPublicKeyInfoStr { + PLArenaPool *arena; + SECAlgorithmID algorithm; + SECItem subjectPublicKey; +}; +typedef struct NSSLOWKEYSubjectPublicKeyInfoStr NSSLOWKEYSubjectPublicKeyInfo; + typedef enum { NSSLOWKEYNullKey = 0, NSSLOWKEYRSAKey = 1, diff --git a/security/nss/lib/softoken/lowpbe.c b/security/nss/lib/softoken/lowpbe.c index 0a47804bf..4a101c68c 100644 --- a/security/nss/lib/softoken/lowpbe.c +++ b/security/nss/lib/softoken/lowpbe.c @@ -1073,15 +1073,15 @@ sec_pkcs5_rc2(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy, } if (encrypt != PR_FALSE) { - void *dummy; + void *v; - dummy = CBC_PadBuffer(NULL, dup_src->data, - dup_src->len, &dup_src->len, 8 /* RC2_BLOCK_SIZE */); - if (dummy == NULL) { + v = CBC_PadBuffer(NULL, dup_src->data, + dup_src->len, &dup_src->len, 8 /* RC2_BLOCK_SIZE */); + if (v == NULL) { SECITEM_FreeItem(dup_src, PR_TRUE); return NULL; } - dup_src->data = (unsigned char *)dummy; + dup_src->data = (unsigned char *)v; } dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c index 77882a274..34f25a9d0 100644 --- a/security/nss/lib/softoken/pkcs11.c +++ b/security/nss/lib/softoken/pkcs11.c @@ -1343,7 +1343,6 @@ sftk_handleSecretKeyObject(SFTKSession *session, SFTKObject *object, if (sftk_isTrue(object, CKA_TOKEN)) { SFTKSlot *slot = session->slot; SFTKDBHandle *keyHandle = sftk_getKeyDB(slot); - CK_RV crv; if (keyHandle == NULL) { return CKR_TOKEN_WRITE_PROTECTED; @@ -3807,12 +3806,12 @@ NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, PZ_Unlock(slot->slotLock); /* Reset login flags. */ if (ulNewLen == 0) { - PRBool tokenRemoved = PR_FALSE; PZ_Lock(slot->slotLock); slot->isLoggedIn = PR_FALSE; slot->ssoLoggedIn = PR_FALSE; PZ_Unlock(slot->slotLock); + tokenRemoved = PR_FALSE; rv = sftkdb_CheckPassword(handle, "", &tokenRemoved); if (tokenRemoved) { sftk_CloseAllSessions(slot, PR_FALSE); @@ -4422,6 +4421,44 @@ NSC_GetObjectSize(CK_SESSION_HANDLE hSession, return CKR_OK; } +static CK_RV +nsc_GetTokenAttributeValue(SFTKSession *session, CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) +{ + SFTKSlot *slot = sftk_SlotFromSession(session); + SFTKDBHandle *dbHandle = sftk_getDBForTokenObject(slot, hObject); + SFTKDBHandle *keydb = NULL; + CK_RV crv; + + if (dbHandle == NULL) { + return CKR_OBJECT_HANDLE_INVALID; + } + + crv = sftkdb_GetAttributeValue(dbHandle, hObject, pTemplate, ulCount); + + /* make sure we don't export any sensitive information */ + keydb = sftk_getKeyDB(slot); + if (dbHandle == keydb) { + CK_ULONG i; + for (i = 0; i < ulCount; i++) { + if (sftk_isSensitive(pTemplate[i].type, CKO_PRIVATE_KEY)) { + crv = CKR_ATTRIBUTE_SENSITIVE; + if (pTemplate[i].pValue && (pTemplate[i].ulValueLen != -1)) { + PORT_Memset(pTemplate[i].pValue, 0, + pTemplate[i].ulValueLen); + } + pTemplate[i].ulValueLen = -1; + } + } + } + + sftk_freeDB(dbHandle); + if (keydb) { + sftk_freeDB(keydb); + } + return crv; +} + /* NSC_GetAttributeValue obtains the value of one or more object attributes. */ CK_RV NSC_GetAttributeValue(CK_SESSION_HANDLE hSession, @@ -4450,37 +4487,8 @@ NSC_GetAttributeValue(CK_SESSION_HANDLE hSession, /* short circuit everything for token objects */ if (sftk_isToken(hObject)) { - SFTKSlot *slot = sftk_SlotFromSession(session); - SFTKDBHandle *dbHandle = sftk_getDBForTokenObject(slot, hObject); - SFTKDBHandle *keydb = NULL; - - if (dbHandle == NULL) { - sftk_FreeSession(session); - return CKR_OBJECT_HANDLE_INVALID; - } - - crv = sftkdb_GetAttributeValue(dbHandle, hObject, pTemplate, ulCount); - - /* make sure we don't export any sensitive information */ - keydb = sftk_getKeyDB(slot); - if (dbHandle == keydb) { - for (i = 0; i < (int)ulCount; i++) { - if (sftk_isSensitive(pTemplate[i].type, CKO_PRIVATE_KEY)) { - crv = CKR_ATTRIBUTE_SENSITIVE; - if (pTemplate[i].pValue && (pTemplate[i].ulValueLen != -1)) { - PORT_Memset(pTemplate[i].pValue, 0, - pTemplate[i].ulValueLen); - } - pTemplate[i].ulValueLen = -1; - } - } - } - + crv = nsc_GetTokenAttributeValue(session, hObject, pTemplate, ulCount); sftk_FreeSession(session); - sftk_freeDB(dbHandle); - if (keydb) { - sftk_freeDB(keydb); - } return crv; } diff --git a/security/nss/lib/softoken/pkcs11c.c b/security/nss/lib/softoken/pkcs11c.c index d675d7331..385d3c144 100644 --- a/security/nss/lib/softoken/pkcs11c.c +++ b/security/nss/lib/softoken/pkcs11c.c @@ -5324,7 +5324,52 @@ sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp) prepare_low_rsa_priv_key_for_asn1(lk); dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, nsslowkey_RSAPrivateKeyTemplate); - algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; + + /* determine RSA key type from the CKA_PUBLIC_KEY_INFO if present */ + attribute = sftk_FindAttribute(key, CKA_PUBLIC_KEY_INFO); + if (attribute) { + NSSLOWKEYSubjectPublicKeyInfo *publicKeyInfo; + SECItem spki; + + spki.data = attribute->attrib.pValue; + spki.len = attribute->attrib.ulValueLen; + + publicKeyInfo = PORT_ArenaZAlloc(arena, + sizeof(NSSLOWKEYSubjectPublicKeyInfo)); + if (!publicKeyInfo) { + sftk_FreeAttribute(attribute); + *crvp = CKR_HOST_MEMORY; + rv = SECFailure; + goto loser; + } + rv = SEC_QuickDERDecodeItem(arena, publicKeyInfo, + nsslowkey_SubjectPublicKeyInfoTemplate, + &spki); + if (rv != SECSuccess) { + sftk_FreeAttribute(attribute); + *crvp = CKR_KEY_TYPE_INCONSISTENT; + goto loser; + } + algorithm = SECOID_GetAlgorithmTag(&publicKeyInfo->algorithm); + if (algorithm != SEC_OID_PKCS1_RSA_ENCRYPTION && + algorithm != SEC_OID_PKCS1_RSA_PSS_SIGNATURE) { + sftk_FreeAttribute(attribute); + rv = SECFailure; + *crvp = CKR_KEY_TYPE_INCONSISTENT; + goto loser; + } + param = SECITEM_DupItem(&publicKeyInfo->algorithm.parameters); + if (!param) { + sftk_FreeAttribute(attribute); + rv = SECFailure; + *crvp = CKR_HOST_MEMORY; + goto loser; + } + sftk_FreeAttribute(attribute); + } else { + /* default to PKCS #1 */ + algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; + } break; case NSSLOWKEYDSAKey: prepare_low_dsa_priv_key_export_for_asn1(lk); @@ -5803,6 +5848,53 @@ sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki) break; } + if (crv != CKR_OK) { + goto loser; + } + + /* For RSA-PSS, record the original algorithm parameters so + * they can be encrypted altoghether when wrapping */ + if (SECOID_GetAlgorithmTag(&pki->algorithm) == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) { + NSSLOWKEYSubjectPublicKeyInfo spki; + NSSLOWKEYPublicKey pubk; + SECItem *publicKeyInfo; + + memset(&spki, 0, sizeof(NSSLOWKEYSubjectPublicKeyInfo)); + rv = SECOID_CopyAlgorithmID(arena, &spki.algorithm, &pki->algorithm); + if (rv != SECSuccess) { + crv = CKR_HOST_MEMORY; + goto loser; + } + + prepare_low_rsa_pub_key_for_asn1(&pubk); + + rv = SECITEM_CopyItem(arena, &pubk.u.rsa.modulus, &lpk->u.rsa.modulus); + if (rv != SECSuccess) { + crv = CKR_HOST_MEMORY; + goto loser; + } + rv = SECITEM_CopyItem(arena, &pubk.u.rsa.publicExponent, &lpk->u.rsa.publicExponent); + if (rv != SECSuccess) { + crv = CKR_HOST_MEMORY; + goto loser; + } + + if (SEC_ASN1EncodeItem(arena, &spki.subjectPublicKey, + &pubk, nsslowkey_RSAPublicKeyTemplate) == NULL) { + crv = CKR_HOST_MEMORY; + goto loser; + } + + publicKeyInfo = SEC_ASN1EncodeItem(arena, NULL, + &spki, nsslowkey_SubjectPublicKeyInfoTemplate); + if (!publicKeyInfo) { + crv = CKR_HOST_MEMORY; + goto loser; + } + crv = sftk_AddAttributeType(key, CKA_PUBLIC_KEY_INFO, + sftk_item_expand(publicKeyInfo)); + } + loser: if (lpk) { nsslowkey_DestroyPrivateKey(lpk); @@ -7575,13 +7667,13 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession, (const CK_NSS_HKDFParams *)pMechanism->pParameter; const SECHashObject *rawHash; unsigned hashLen; - CK_BYTE buf[HASH_LENGTH_MAX]; + CK_BYTE hashbuf[HASH_LENGTH_MAX]; CK_BYTE *prk; /* psuedo-random key */ CK_ULONG prkLen; CK_BYTE *okm; /* output keying material */ rawHash = HASH_GetRawHashObject(hashType); - if (rawHash == NULL || rawHash->length > sizeof buf) { + if (rawHash == NULL || rawHash->length > sizeof(hashbuf)) { crv = CKR_FUNCTION_FAILED; break; } @@ -7615,7 +7707,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession, saltLen = params->ulSaltLen; if (salt == NULL) { saltLen = hashLen; - salt = buf; + salt = hashbuf; memset(salt, 0, saltLen); } hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS); @@ -7626,10 +7718,10 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession, HMAC_Begin(hmac); HMAC_Update(hmac, (const unsigned char *)att->attrib.pValue, att->attrib.ulValueLen); - HMAC_Finish(hmac, buf, &bufLen, sizeof(buf)); + HMAC_Finish(hmac, hashbuf, &bufLen, sizeof(hashbuf)); HMAC_Destroy(hmac, PR_TRUE); PORT_Assert(bufLen == rawHash->length); - prk = buf; + prk = hashbuf; prkLen = bufLen; } else { /* PRK = base key value */ @@ -7646,24 +7738,24 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession, * key material = T(1) | ... | T(n) */ HMACContext *hmac; - CK_BYTE i; + CK_BYTE bi; unsigned iterations = PR_ROUNDUP(keySize, hashLen) / hashLen; hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS); if (hmac == NULL) { crv = CKR_HOST_MEMORY; break; } - for (i = 1; i <= iterations; ++i) { + for (bi = 1; bi <= iterations; ++bi) { unsigned len; HMAC_Begin(hmac); - if (i > 1) { - HMAC_Update(hmac, key_block + ((i - 2) * hashLen), hashLen); + if (bi > 1) { + HMAC_Update(hmac, key_block + ((bi - 2) * hashLen), hashLen); } if (params->ulInfoLen != 0) { HMAC_Update(hmac, params->pInfo, params->ulInfoLen); } - HMAC_Update(hmac, &i, 1); - HMAC_Finish(hmac, key_block + ((i - 1) * hashLen), &len, + HMAC_Update(hmac, &bi, 1); + HMAC_Finish(hmac, key_block + ((bi - 1) * hashLen), &len, hashLen); PORT_Assert(len == hashLen); } diff --git a/security/nss/lib/softoken/pkcs11u.c b/security/nss/lib/softoken/pkcs11u.c index 27e411759..7b5fe732f 100644 --- a/security/nss/lib/softoken/pkcs11u.c +++ b/security/nss/lib/softoken/pkcs11u.c @@ -1193,7 +1193,7 @@ sftk_DeleteObject(SFTKSession *session, SFTKObject *object) /* Handle Token case */ if (so && so->session) { - SFTKSession *session = so->session; + session = so->session; PZ_Lock(session->objectLock); sftkqueue_delete(&so->sessionList, 0, session->objects, 0); PZ_Unlock(session->objectLock); @@ -1269,7 +1269,7 @@ static const CK_ULONG ecPubKeyAttrsCount = static const CK_ATTRIBUTE_TYPE commonPrivKeyAttrs[] = { CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER, CKA_UNWRAP, CKA_SUBJECT, - CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_NETSCAPE_DB + CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_NETSCAPE_DB, CKA_PUBLIC_KEY_INFO }; static const CK_ULONG commonPrivKeyAttrsCount = sizeof(commonPrivKeyAttrs) / sizeof(commonPrivKeyAttrs[0]); diff --git a/security/nss/lib/softoken/sdb.c b/security/nss/lib/softoken/sdb.c index 96717cb26..fb897d68c 100644 --- a/security/nss/lib/softoken/sdb.c +++ b/security/nss/lib/softoken/sdb.c @@ -37,6 +37,10 @@ #elif defined(XP_UNIX) #include <unistd.h> #endif +#if defined(LINUX) && !defined(ANDROID) +#include <linux/magic.h> +#include <sys/vfs.h> +#endif #include "utilpars.h" #ifdef SQLITE_UNSAFE_THREADS @@ -154,7 +158,8 @@ static const CK_ATTRIBUTE_TYPE known_attributes[] = { CKA_TRUST_EMAIL_PROTECTION, CKA_TRUST_IPSEC_END_SYSTEM, CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER, CKA_TRUST_TIME_STAMPING, CKA_TRUST_STEP_UP_APPROVED, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH, - CKA_NETSCAPE_DB, CKA_NETSCAPE_TRUST, CKA_NSS_OVERRIDE_EXTENSIONS + CKA_NETSCAPE_DB, CKA_NETSCAPE_TRUST, CKA_NSS_OVERRIDE_EXTENSIONS, + CKA_PUBLIC_KEY_INFO }; static int known_attributes_size = sizeof(known_attributes) / @@ -643,13 +648,18 @@ static int sdb_openDB(const char *name, sqlite3 **sqlDB, int flags) { int sqlerr; - /* - * in sqlite3 3.5.0, there is a new open call that allows us - * to specify read only. Most new OS's are still on 3.3.x (including - * NSS's internal version and the version shipped with Firefox). - */ + int openFlags; + *sqlDB = NULL; - sqlerr = sqlite3_open(name, sqlDB); + + if (flags & SDB_RDONLY) { + openFlags = SQLITE_OPEN_READONLY; + } else { + openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + } + + /* Requires SQLite 3.5.0 or newer. */ + sqlerr = sqlite3_open_v2(name, sqlDB, openFlags, NULL); if (sqlerr != SQLITE_OK) { return sqlerr; } @@ -1757,6 +1767,8 @@ sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate, PRIntervalTime now = 0; char *env; PRBool enableCache = PR_FALSE; + PRBool checkFSType = PR_FALSE; + PRBool measureSpeed = PR_FALSE; PRBool create; int flags = inFlags & 0x7; @@ -1917,11 +1929,48 @@ sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate, env = PR_GetEnvSecure("NSS_SDB_USE_CACHE"); - if (!env || PORT_Strcasecmp(env, "no") == 0) { - enableCache = PR_FALSE; + /* Variables enableCache, checkFSType, measureSpeed are PR_FALSE by default, + * which is the expected behavior for NSS_SDB_USE_CACHE="no". + * We don't need to check for "no" here. */ + if (!env) { + /* By default, with no variable set, we avoid expensive measuring for + * most FS types. We start with inexpensive FS type checking, and + * might perform measuring for some types. */ + checkFSType = PR_TRUE; } else if (PORT_Strcasecmp(env, "yes") == 0) { enableCache = PR_TRUE; - } else { + } else if (PORT_Strcasecmp(env, "no") != 0) { /* not "no" => "auto" */ + measureSpeed = PR_TRUE; + } + + if (checkFSType) { +#if defined(LINUX) && !defined(ANDROID) + struct statfs statfs_s; + if (statfs(dbname, &statfs_s) == 0) { + switch (statfs_s.f_type) { + case SMB_SUPER_MAGIC: + case 0xff534d42: /* CIFS_MAGIC_NUMBER */ + case NFS_SUPER_MAGIC: + /* We assume these are slow. */ + enableCache = PR_TRUE; + break; + case CODA_SUPER_MAGIC: + case 0x65735546: /* FUSE_SUPER_MAGIC */ + case NCP_SUPER_MAGIC: + /* It's uncertain if this FS is fast or slow. + * It seems reasonable to perform slow measuring for users + * with questionable FS speed. */ + measureSpeed = PR_TRUE; + break; + case AFS_SUPER_MAGIC: /* Already implements caching. */ + default: + break; + } + } +#endif + } + + if (measureSpeed) { char *tempDir = NULL; PRUint32 tempOps = 0; /* diff --git a/security/nss/lib/softoken/sftkdb.c b/security/nss/lib/softoken/sftkdb.c index 2ae084068..409c910f4 100644 --- a/security/nss/lib/softoken/sftkdb.c +++ b/security/nss/lib/softoken/sftkdb.c @@ -1591,7 +1591,8 @@ static const CK_ATTRIBUTE_TYPE known_attributes[] = { CKA_TRUST_EMAIL_PROTECTION, CKA_TRUST_IPSEC_END_SYSTEM, CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER, CKA_TRUST_TIME_STAMPING, CKA_TRUST_STEP_UP_APPROVED, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH, - CKA_NETSCAPE_DB, CKA_NETSCAPE_TRUST, CKA_NSS_OVERRIDE_EXTENSIONS + CKA_NETSCAPE_DB, CKA_NETSCAPE_TRUST, CKA_NSS_OVERRIDE_EXTENSIONS, + CKA_PUBLIC_KEY_INFO }; static unsigned int known_attributes_size = sizeof(known_attributes) / diff --git a/security/nss/lib/softoken/sftkpars.c b/security/nss/lib/softoken/sftkpars.c index e972fe854..5e96a1c04 100644 --- a/security/nss/lib/softoken/sftkpars.c +++ b/security/nss/lib/softoken/sftkpars.c @@ -162,7 +162,7 @@ sftk_parseParameters(char *param, sftk_parameters *parsed, PRBool isFIPS) } if (parsed->tokens == NULL) { int count = isFIPS ? 1 : 2; - int index = count - 1; + int i = count - 1; sftk_token_parameters *tokens = NULL; tokens = (sftk_token_parameters *) @@ -172,30 +172,30 @@ sftk_parseParameters(char *param, sftk_parameters *parsed, PRBool isFIPS) } parsed->tokens = tokens; parsed->token_count = count; - tokens[index].slotID = isFIPS ? FIPS_SLOT_ID : PRIVATE_KEY_SLOT_ID; - tokens[index].certPrefix = certPrefix; - tokens[index].keyPrefix = keyPrefix; - tokens[index].minPW = minPW ? atoi(minPW) : 0; - tokens[index].readOnly = parsed->readOnly; - tokens[index].noCertDB = parsed->noCertDB; - tokens[index].noKeyDB = parsed->noCertDB; - tokens[index].forceOpen = parsed->forceOpen; - tokens[index].pwRequired = parsed->pwRequired; - tokens[index].optimizeSpace = parsed->optimizeSpace; + tokens[i].slotID = isFIPS ? FIPS_SLOT_ID : PRIVATE_KEY_SLOT_ID; + tokens[i].certPrefix = certPrefix; + tokens[i].keyPrefix = keyPrefix; + tokens[i].minPW = minPW ? atoi(minPW) : 0; + tokens[i].readOnly = parsed->readOnly; + tokens[i].noCertDB = parsed->noCertDB; + tokens[i].noKeyDB = parsed->noCertDB; + tokens[i].forceOpen = parsed->forceOpen; + tokens[i].pwRequired = parsed->pwRequired; + tokens[i].optimizeSpace = parsed->optimizeSpace; tokens[0].optimizeSpace = parsed->optimizeSpace; certPrefix = NULL; keyPrefix = NULL; if (isFIPS) { - tokens[index].tokdes = ftokdes; - tokens[index].updtokdes = pupdtokdes; - tokens[index].slotdes = fslotdes; + tokens[i].tokdes = ftokdes; + tokens[i].updtokdes = pupdtokdes; + tokens[i].slotdes = fslotdes; fslotdes = NULL; ftokdes = NULL; pupdtokdes = NULL; } else { - tokens[index].tokdes = ptokdes; - tokens[index].updtokdes = pupdtokdes; - tokens[index].slotdes = pslotdes; + tokens[i].tokdes = ptokdes; + tokens[i].updtokdes = pupdtokdes; + tokens[i].slotdes = pslotdes; tokens[0].slotID = NETSCAPE_SLOT_ID; tokens[0].tokdes = tokdes; tokens[0].slotdes = slotdes; diff --git a/security/nss/lib/softoken/sftkpwd.c b/security/nss/lib/softoken/sftkpwd.c index e0d2df9ab..9834d3ba0 100644 --- a/security/nss/lib/softoken/sftkpwd.c +++ b/security/nss/lib/softoken/sftkpwd.c @@ -138,12 +138,14 @@ sftkdb_decodeCipherText(SECItem *cipherText, sftkCipherValue *cipherValue) SFTKDBEncryptedDataInfo edi; SECStatus rv; + PORT_Assert(cipherValue); + cipherValue->arena = NULL; + cipherValue->param = NULL; + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { return SECFailure; } - cipherValue->arena = NULL; - cipherValue->param = NULL; rv = SEC_QuickDERDecodeItem(arena, &edi, sftkdb_EncryptedDataInfoTemplate, cipherText); diff --git a/security/nss/lib/softoken/softkver.h b/security/nss/lib/softoken/softkver.h index f760ba21d..827bf2e22 100644 --- a/security/nss/lib/softoken/softkver.h +++ b/security/nss/lib/softoken/softkver.h @@ -17,10 +17,10 @@ * The format of the version string should be * "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]" */ -#define SOFTOKEN_VERSION "3.36.4" SOFTOKEN_ECC_STRING +#define SOFTOKEN_VERSION "3.38" SOFTOKEN_ECC_STRING #define SOFTOKEN_VMAJOR 3 -#define SOFTOKEN_VMINOR 36 -#define SOFTOKEN_VPATCH 4 +#define SOFTOKEN_VMINOR 38 +#define SOFTOKEN_VPATCH 0 #define SOFTOKEN_VBUILD 0 #define SOFTOKEN_BETA PR_FALSE diff --git a/security/nss/lib/ssl/SSLerrs.h b/security/nss/lib/ssl/SSLerrs.h index d3f087544..f01d16583 100644 --- a/security/nss/lib/ssl/SSLerrs.h +++ b/security/nss/lib/ssl/SSLerrs.h @@ -374,7 +374,7 @@ ER3(SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY, (SSL_ERROR_BASE + 115), "SSL received a weak ephemeral Diffie-Hellman key in Server Key Exchange handshake message.") ER3(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID, (SSL_ERROR_BASE + 116), - "SSL received invalid NPN extension data.") + "SSL received invalid ALPN extension data.") ER3(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2, (SSL_ERROR_BASE + 117), "SSL feature not supported for SSL 2.0 connections.") @@ -543,3 +543,12 @@ ER3(SSL_ERROR_TOO_MANY_KEY_UPDATES, (SSL_ERROR_BASE + 171), ER3(SSL_ERROR_HANDSHAKE_FAILED, (SSL_ERROR_BASE + 172), "SSL handshake has already failed. No more operations possible.") + +ER3(SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR, (SSL_ERROR_BASE + 173), + "SSL received an invalid resumption token.") + +ER3(SSL_ERROR_RX_MALFORMED_DTLS_ACK, (SSL_ERROR_BASE + 174), + "SSL received a malformed DTLS ACK") + +ER3(SSL_ERROR_DH_KEY_TOO_LONG, (SSL_ERROR_BASE + 175), + "SSL received a DH key share that's too long (>8192 bit).") diff --git a/security/nss/lib/ssl/dtls13con.c b/security/nss/lib/ssl/dtls13con.c index aba0f62ab..de6cb47ca 100644 --- a/security/nss/lib/ssl/dtls13con.c +++ b/security/nss/lib/ssl/dtls13con.c @@ -11,6 +11,43 @@ #include "sslimpl.h" #include "sslproto.h" +SECStatus +dtls13_InsertCipherTextHeader(const sslSocket *ss, ssl3CipherSpec *cwSpec, + sslBuffer *wrBuf, PRBool *needsLength) +{ + PRUint32 seq; + SECStatus rv; + + /* Avoid using short records for the handshake. We pack multiple records + * into the one datagram for the handshake. */ + if (ss->opt.enableDtlsShortHeader && + cwSpec->epoch != TrafficKeyHandshake) { + *needsLength = PR_FALSE; + /* The short header is comprised of two octets in the form + * 0b001essssssssssss where 'e' is the low bit of the epoch and 's' is + * the low 12 bits of the sequence number. */ + seq = 0x2000 | + (((uint64_t)cwSpec->epoch & 1) << 12) | + (cwSpec->nextSeqNum & 0xfff); + return sslBuffer_AppendNumber(wrBuf, seq, 2); + } + + rv = sslBuffer_AppendNumber(wrBuf, content_application_data, 1); + if (rv != SECSuccess) { + return SECFailure; + } + + /* The epoch and sequence number are encoded on 4 octets, with the epoch + * consuming the first two bits. */ + seq = (((uint64_t)cwSpec->epoch & 3) << 30) | (cwSpec->nextSeqNum & 0x3fffffff); + rv = sslBuffer_AppendNumber(wrBuf, seq, 4); + if (rv != SECSuccess) { + return SECFailure; + } + *needsLength = PR_TRUE; + return SECSuccess; +} + /* DTLS 1.3 Record map for ACK processing. * This represents a single fragment, so a record which includes * multiple fragments will have one entry for each fragment on the @@ -82,10 +119,15 @@ dtls13_SendAck(sslSocket *ss) SECStatus rv = SECSuccess; PRCList *cursor; PRInt32 sent; + unsigned int offset; SSL_TRC(10, ("%d: SSL3[%d]: Sending ACK", SSL_GETPID(), ss->fd)); + rv = sslBuffer_Skip(&buf, 2, &offset); + if (rv != SECSuccess) { + goto loser; + } for (cursor = PR_LIST_HEAD(&ss->ssl3.hs.dtlsRcvdHandshake); cursor != &ss->ssl3.hs.dtlsRcvdHandshake; cursor = PR_NEXT_LINK(cursor)) { @@ -99,6 +141,11 @@ dtls13_SendAck(sslSocket *ss) } } + rv = sslBuffer_InsertLength(&buf, offset, 2); + if (rv != SECSuccess) { + goto loser; + } + ssl_GetXmitBufLock(ss); sent = ssl3_SendRecord(ss, NULL, content_ack, buf.buf, buf.len, 0); @@ -364,6 +411,7 @@ dtls13_HandleAck(sslSocket *ss, sslBuffer *databuf) { PRUint8 *b = databuf->buf; PRUint32 l = databuf->len; + unsigned int length; SECStatus rv; /* Ensure we don't loop. */ @@ -372,10 +420,19 @@ dtls13_HandleAck(sslSocket *ss, sslBuffer *databuf) PORT_Assert(IS_DTLS(ss)); if (!tls13_MaybeTls13(ss)) { tls13_FatalError(ss, SSL_ERROR_RX_UNKNOWN_RECORD_TYPE, illegal_parameter); - return SECSuccess; + return SECFailure; } SSL_TRC(10, ("%d: SSL3[%d]: Handling ACK", SSL_GETPID(), ss->fd)); + rv = ssl3_ConsumeHandshakeNumber(ss, &length, 2, &b, &l); + if (rv != SECSuccess) { + return SECFailure; + } + if (length != l) { + tls13_FatalError(ss, SSL_ERROR_RX_MALFORMED_DTLS_ACK, decode_error); + return SECFailure; + } + while (l > 0) { PRUint64 seq; PRCList *cursor; diff --git a/security/nss/lib/ssl/dtls13con.h b/security/nss/lib/ssl/dtls13con.h index bf14d3bd2..ca48ef363 100644 --- a/security/nss/lib/ssl/dtls13con.h +++ b/security/nss/lib/ssl/dtls13con.h @@ -9,6 +9,10 @@ #ifndef __dtls13con_h_ #define __dtls13con_h_ +SECStatus dtls13_InsertCipherTextHeader(const sslSocket *ss, + ssl3CipherSpec *cwSpec, + sslBuffer *wrBuf, + PRBool *needsLength); SECStatus dtls13_RememberFragment(sslSocket *ss, PRCList *list, PRUint32 sequence, PRUint32 offset, PRUint32 length, DTLSEpoch epoch, diff --git a/security/nss/lib/ssl/dtlscon.c b/security/nss/lib/ssl/dtlscon.c index 2f335f924..a82295c66 100644 --- a/security/nss/lib/ssl/dtlscon.c +++ b/security/nss/lib/ssl/dtlscon.c @@ -724,13 +724,16 @@ dtls_FragmentHandshake(sslSocket *ss, DTLSQueuedMessage *msg) PORT_Assert(end <= contentLen); fragmentLen = PR_MIN(end, contentLen) - fragmentOffset; - /* Reduce to the space remaining in the MTU. Allow for any existing - * messages, record expansion, and the handshake header. */ + /* Limit further by the record size limit. Account for the header. */ + fragmentLen = PR_MIN(fragmentLen, + msg->cwSpec->recordSizeLimit - DTLS_HS_HDR_LEN); + + /* Reduce to the space remaining in the MTU. */ fragmentLen = PR_MIN(fragmentLen, ss->ssl3.mtu - /* MTU estimate. */ - ss->pendingBuf.len - /* Less unsent records. */ + ss->pendingBuf.len - /* Less any unsent records. */ DTLS_MAX_EXPANSION - /* Allow for expansion. */ - DTLS_HS_HDR_LEN); /* + handshake header. */ + DTLS_HS_HDR_LEN); /* And the handshake header. */ PORT_Assert(fragmentLen > 0 || fragmentOffset == 0); /* Make totally sure that we will fit in the buffer. This should be @@ -776,7 +779,7 @@ dtls_FragmentHandshake(sslSocket *ss, DTLSQueuedMessage *msg) rv = dtls13_RememberFragment(ss, &ss->ssl3.hs.dtlsSentHandshake, msgSeq, fragmentOffset, fragmentLen, msg->cwSpec->epoch, - msg->cwSpec->seqNum); + msg->cwSpec->nextSeqNum); if (rv != SECSuccess) { return SECFailure; } @@ -1319,6 +1322,107 @@ DTLS_GetHandshakeTimeout(PRFileDesc *socket, PRIntervalTime *timeout) return SECSuccess; } +PRBool +dtls_IsLongHeader(SSL3ProtocolVersion version, PRUint8 firstOctet) +{ +#ifndef UNSAFE_FUZZER_MODE + return version < SSL_LIBRARY_VERSION_TLS_1_3 || + firstOctet == content_handshake || + firstOctet == content_ack || + firstOctet == content_alert; +#else + return PR_TRUE; +#endif +} + +DTLSEpoch +dtls_ReadEpoch(const ssl3CipherSpec *crSpec, const PRUint8 *hdr) +{ + DTLSEpoch epoch; + DTLSEpoch maxEpoch; + DTLSEpoch partial; + + if (dtls_IsLongHeader(crSpec->version, hdr[0])) { + return ((DTLSEpoch)hdr[3] << 8) | hdr[4]; + } + + /* A lot of how we recover the epoch here will depend on how we plan to + * manage KeyUpdate. In the case that we decide to install a new read spec + * as a KeyUpdate is handled, crSpec will always be the highest epoch we can + * possibly receive. That makes this easier to manage. */ + if ((hdr[0] & 0xe0) == 0x20) { + /* Use crSpec->epoch, or crSpec->epoch - 1 if the last bit differs. */ + if (((hdr[0] >> 4) & 1) == (crSpec->epoch & 1)) { + return crSpec->epoch; + } + return crSpec->epoch - 1; + } + + /* dtls_GatherData should ensure that this works. */ + PORT_Assert(hdr[0] == content_application_data); + + /* This uses the same method as is used to recover the sequence number in + * dtls_ReadSequenceNumber, except that the maximum value is set to the + * current epoch. */ + partial = hdr[1] >> 6; + maxEpoch = PR_MAX(crSpec->epoch, 3); + epoch = (maxEpoch & 0xfffc) | partial; + if (partial > (maxEpoch & 0x03)) { + epoch -= 4; + } + return epoch; +} + +static sslSequenceNumber +dtls_ReadSequenceNumber(const ssl3CipherSpec *spec, const PRUint8 *hdr) +{ + sslSequenceNumber cap; + sslSequenceNumber partial; + sslSequenceNumber seqNum; + sslSequenceNumber mask; + + if (dtls_IsLongHeader(spec->version, hdr[0])) { + static const unsigned int seqNumOffset = 5; /* type, version, epoch */ + static const unsigned int seqNumLength = 6; + sslReader r = SSL_READER(hdr + seqNumOffset, seqNumLength); + (void)sslRead_ReadNumber(&r, seqNumLength, &seqNum); + return seqNum; + } + + /* Only the least significant bits of the sequence number is available here. + * This recovers the value based on the next expected sequence number. + * + * This works by determining the maximum possible sequence number, which is + * half the range of possible values above the expected next value (the + * expected next value is in |spec->seqNum|). Then, the last part of the + * sequence number is replaced. If that causes the value to exceed the + * maximum, subtract an entire range. + */ + if ((hdr[0] & 0xe0) == 0x20) { + /* A 12-bit sequence number. */ + cap = spec->nextSeqNum + (1ULL << 11); + partial = (((sslSequenceNumber)hdr[0] & 0xf) << 8) | + (sslSequenceNumber)hdr[1]; + mask = (1ULL << 12) - 1; + } else { + /* A 30-bit sequence number. */ + cap = spec->nextSeqNum + (1ULL << 29); + partial = (((sslSequenceNumber)hdr[1] & 0x3f) << 24) | + ((sslSequenceNumber)hdr[2] << 16) | + ((sslSequenceNumber)hdr[3] << 8) | + (sslSequenceNumber)hdr[4]; + mask = (1ULL << 30) - 1; + } + seqNum = (cap & ~mask) | partial; + /* The second check prevents the value from underflowing if we get a large + * gap at the start of a connection, where this subtraction would cause the + * sequence number to wrap to near UINT64_MAX. */ + if ((partial > (cap & mask)) && (seqNum > mask)) { + seqNum -= mask + 1; + } + return seqNum; +} + /* * DTLS relevance checks: * Note that this code currently ignores all out-of-epoch packets, @@ -1336,7 +1440,7 @@ dtls_IsRelevant(sslSocket *ss, const ssl3CipherSpec *spec, const SSL3Ciphertext *cText, sslSequenceNumber *seqNumOut) { - sslSequenceNumber seqNum = cText->seq_num & RECORD_SEQ_MASK; + sslSequenceNumber seqNum = dtls_ReadSequenceNumber(spec, cText->hdr); if (dtls_RecordGetRecvd(&spec->recvdRecords, seqNum) != 0) { SSL_TRC(10, ("%d: SSL3[%d]: dtls_IsRelevant, rejecting " "potentially replayed packet", diff --git a/security/nss/lib/ssl/dtlscon.h b/security/nss/lib/ssl/dtlscon.h index d094380f8..45fc069b9 100644 --- a/security/nss/lib/ssl/dtlscon.h +++ b/security/nss/lib/ssl/dtlscon.h @@ -41,8 +41,10 @@ extern SSL3ProtocolVersion dtls_TLSVersionToDTLSVersion(SSL3ProtocolVersion tlsv); extern SSL3ProtocolVersion dtls_DTLSVersionToTLSVersion(SSL3ProtocolVersion dtlsv); +DTLSEpoch dtls_ReadEpoch(const ssl3CipherSpec *crSpec, const PRUint8 *hdr); extern PRBool dtls_IsRelevant(sslSocket *ss, const ssl3CipherSpec *spec, const SSL3Ciphertext *cText, sslSequenceNumber *seqNum); void dtls_ReceivedFirstMessageInFlight(sslSocket *ss); +PRBool dtls_IsLongHeader(SSL3ProtocolVersion version, PRUint8 firstOctet); #endif diff --git a/security/nss/lib/ssl/ssl.h b/security/nss/lib/ssl/ssl.h index 25aabbaa2..ecc4f9506 100644 --- a/security/nss/lib/ssl/ssl.h +++ b/security/nss/lib/ssl/ssl.h @@ -158,23 +158,18 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd); #define SSL_CBC_RANDOM_IV 23 #define SSL_ENABLE_OCSP_STAPLING 24 /* Request OCSP stapling (client) */ -/* SSL_ENABLE_NPN controls whether the NPN extension is enabled for the initial - * handshake when application layer protocol negotiation is used. - * SSL_SetNextProtoCallback or SSL_SetNextProtoNego must be used to control the - * application layer protocol negotiation; otherwise, the NPN extension will - * not be negotiated. SSL_ENABLE_NPN is currently enabled by default but this - * may change in future versions. - */ +/* SSL_ENABLE_NPN is defunct and defaults to false. + * Using this option will not have any effect but won't produce an error. */ #define SSL_ENABLE_NPN 25 /* SSL_ENABLE_ALPN controls whether the ALPN extension is enabled for the * initial handshake when application layer protocol negotiation is used. - * SSL_SetNextProtoNego (not SSL_SetNextProtoCallback) must be used to control - * the application layer protocol negotiation; otherwise, the ALPN extension - * will not be negotiated. ALPN is not negotiated for renegotiation handshakes, - * even though the ALPN specification defines a way to use ALPN during - * renegotiations. SSL_ENABLE_ALPN is currently disabled by default, but this - * may change in future versions. + * SSL_SetNextProtoNego or SSL_SetNextProtoCallback can be used to control + * the application layer protocol negotiation; + * ALPN is not negotiated for renegotiation handshakes, even though the ALPN + * specification defines a way to use ALPN during renegotiations. + * SSL_ENABLE_ALPN is currently enabled by default, but this may change in + * future versions. */ #define SSL_ENABLE_ALPN 26 @@ -248,12 +243,45 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd); */ #define SSL_ENABLE_0RTT_DATA 33 +/* Sets a limit to the size of encrypted records (see + * draft-ietf-tls-record-limit). This is the value that is advertised to peers, + * not a limit on the size of records that will be created. Setting this value + * reduces the size of records that will be received (not sent). + * + * This limit applies to the plaintext, but the records that appear on the wire + * will be bigger. This doesn't include record headers, IVs, block cipher + * padding, and authentication tags or MACs. + * + * NSS always advertises the record size limit extension. If this option is not + * set, the extension will contain the maximum allowed size for the selected TLS + * version (currently this is 16384 or 2^14 for TLS 1.2 and lower and 16385 for + * TLS 1.3). + * + * By default, NSS creates records that are the maximum size possible, using all + * the data that was written by the application. Writes larger than the maximum + * are split into maximum sized records, and any remainder (unless + * SSL_CBC_RANDOM_IV is enabled and active). If a peer advertises a record size + * limit then that value is used instead. + */ +#define SSL_RECORD_SIZE_LIMIT 34 + /* Enables TLS 1.3 compatibility mode. In this mode, the client includes a fake * session ID in the handshake and sends a ChangeCipherSpec. A server will * always use the setting chosen by the client, so the value of this option has * no effect for a server. This setting is ignored for DTLS. */ #define SSL_ENABLE_TLS13_COMPAT_MODE 35 +/* Enables the sending of DTLS records using the short (two octet) record + * header. Only do this if there are 2^10 or fewer packets in flight at a time; + * using this with a larger number of packets in flight could mean that packets + * are dropped if there is reordering. + * + * This applies to TLS 1.3 only. This is not a parameter that is negotiated + * during the TLS handshake. Unlike other socket options, this option can be + * changed after a handshake is complete. + */ +#define SSL_ENABLE_DTLS_SHORT_HEADER 36 + #ifdef SSL_DEPRECATED_FUNCTION /* Old deprecated function names */ SSL_IMPORT SECStatus SSL_Enable(PRFileDesc *fd, int option, PRIntn on); @@ -272,10 +300,10 @@ SSL_IMPORT SECStatus SSL_OptionSetDefault(PRInt32 option, PRIntn val); SSL_IMPORT SECStatus SSL_OptionGetDefault(PRInt32 option, PRIntn *val); SSL_IMPORT SECStatus SSL_CertDBHandleSet(PRFileDesc *fd, CERTCertDBHandle *dbHandle); -/* SSLNextProtoCallback is called during the handshake for the client, when a - * Next Protocol Negotiation (NPN) extension has been received from the server. - * |protos| and |protosLen| define a buffer which contains the server's - * advertisement. This data is guaranteed to be well formed per the NPN spec. +/* SSLNextProtoCallback is called during the handshake for the server, when an + * Application-Layer Protocol Negotiation (ALPN) extension has been received + * from the client. |protos| and |protosLen| define a buffer which contains the + * client's advertisement. * |protoOut| is a buffer provided by the caller, of length 255 (the maximum * allowed by the protocol). On successful return, the protocol to be announced * to the server will be in |protoOut| and its length in |*protoOutLen|. @@ -291,27 +319,24 @@ typedef SECStatus(PR_CALLBACK *SSLNextProtoCallback)( unsigned int *protoOutLen, unsigned int protoMaxOut); -/* SSL_SetNextProtoCallback sets a callback function to handle Next Protocol - * Negotiation. It causes a client to advertise NPN. */ +/* SSL_SetNextProtoCallback sets a callback function to handle ALPN Negotiation. + * It causes a client to advertise ALPN. */ SSL_IMPORT SECStatus SSL_SetNextProtoCallback(PRFileDesc *fd, SSLNextProtoCallback callback, void *arg); /* SSL_SetNextProtoNego can be used as an alternative to - * SSL_SetNextProtoCallback. It also causes a client to advertise NPN and - * installs a default callback function which selects the first supported - * protocol in server-preference order. If no matching protocol is found it - * selects the first supported protocol. + * SSL_SetNextProtoCallback. * - * Using this function also allows the client to transparently support ALPN. + * Using this function allows client and server to transparently support ALPN. * The same set of protocols will be advertised via ALPN and, if the server * uses ALPN to select a protocol, SSL_GetNextProto will return * SSL_NEXT_PROTO_SELECTED as the state. * - * Since NPN uses the first protocol as the fallback protocol, when sending an - * ALPN extension, the first protocol is moved to the end of the list. This - * indicates that the fallback protocol is the least preferred. The other - * protocols should be in preference order. + * Because the predecessor to ALPN, NPN, used the first protocol as the fallback + * protocol, when sending an ALPN extension, the first protocol is moved to the + * end of the list. This indicates that the fallback protocol is the least + * preferred. The other protocols should be in preference order. * * The supported protocols are specified in |data| in wire-format (8-bit * length-prefixed). For example: "\010http/1.1\006spdy/2". */ diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index 2593bbacc..466fc296f 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -990,27 +990,22 @@ ssl_ClientReadVersion(sslSocket *ss, PRUint8 **b, unsigned int *len, if (rv != SECSuccess) { return SECFailure; /* alert has been sent */ } - -#ifdef TLS_1_3_DRAFT_VERSION - if (temp == SSL_LIBRARY_VERSION_TLS_1_3) { - (void)SSL3_SendAlert(ss, alert_fatal, protocol_version); - PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION); - return SECFailure; - } - if (temp == tls13_EncodeDraftVersion(SSL_LIBRARY_VERSION_TLS_1_3)) { - v = SSL_LIBRARY_VERSION_TLS_1_3; - } else { - v = (SSL3ProtocolVersion)temp; - } -#else v = (SSL3ProtocolVersion)temp; -#endif if (IS_DTLS(ss)) { - /* If this fails, we get 0 back and the next check to fails. */ v = dtls_DTLSVersionToTLSVersion(v); + /* Check for failure. */ + if (!v || v > SSL_LIBRARY_VERSION_MAX_SUPPORTED) { + SSL3_SendAlert(ss, alert_fatal, illegal_parameter); + return SECFailure; + } } + /* You can't negotiate TLS 1.3 this way. */ + if (v >= SSL_LIBRARY_VERSION_TLS_1_3) { + SSL3_SendAlert(ss, alert_fatal, illegal_parameter); + return SECFailure; + } *version = v; return SECSuccess; } @@ -1415,7 +1410,7 @@ ssl3_SetupPendingCipherSpec(sslSocket *ss, CipherSpecDirection direction, spec->macDef = ssl_GetMacDef(ss, suiteDef); spec->epoch = prev->epoch + 1; - spec->seqNum = 0; + spec->nextSeqNum = 0; if (IS_DTLS(ss) && direction == CipherSpecRead) { dtls_InitRecvdRecords(&spec->recvdRecords); } @@ -1481,6 +1476,13 @@ ssl3_SetupBothPendingCipherSpecs(sslSocket *ss) goto loser; } + if (ssl3_ExtensionNegotiated(ss, ssl_record_size_limit_xtn)) { + ss->ssl3.prSpec->recordSizeLimit = PR_MIN(MAX_FRAGMENT_LENGTH, + ss->opt.recordSizeLimit); + ss->ssl3.pwSpec->recordSizeLimit = PR_MIN(MAX_FRAGMENT_LENGTH, + ss->xtnData.recordSizeLimit); + } + ssl_ReleaseSpecWriteLock(ss); /*******************************/ return SECSuccess; @@ -2004,6 +2006,7 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec, unsigned int ivLen = 0; unsigned char pseudoHeaderBuf[13]; sslBuffer pseudoHeader = SSL_BUFFER(pseudoHeaderBuf); + int len; if (cwSpec->cipherDef->type == type_block && cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { @@ -2013,29 +2016,32 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec, * record. */ ivLen = cwSpec->cipherDef->iv_size; - if (ivLen > wrBuf->space) { + if (ivLen > SSL_BUFFER_SPACE(wrBuf)) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } - rv = PK11_GenerateRandom(wrBuf->buf, ivLen); + rv = PK11_GenerateRandom(SSL_BUFFER_NEXT(wrBuf), ivLen); if (rv != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE); return rv; } rv = cwSpec->cipher(cwSpec->cipherContext, - wrBuf->buf, /* output */ - (int *)&wrBuf->len, /* outlen */ - ivLen, /* max outlen */ - wrBuf->buf, /* input */ - ivLen); /* input len */ - if (rv != SECSuccess || wrBuf->len != ivLen) { + SSL_BUFFER_NEXT(wrBuf), /* output */ + &len, /* outlen */ + ivLen, /* max outlen */ + SSL_BUFFER_NEXT(wrBuf), /* input */ + ivLen); /* input len */ + if (rv != SECSuccess || len != ivLen) { PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); return SECFailure; } + + rv = sslBuffer_Skip(wrBuf, len, NULL); + PORT_Assert(rv == SECSuccess); /* Can't fail. */ } rv = ssl3_BuildRecordPseudoHeader( - cwSpec->epoch, cwSpec->seqNum, type, + cwSpec->epoch, cwSpec->nextSeqNum, type, cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_0, cwSpec->recordVersion, isDTLS, contentLen, &pseudoHeader); PORT_Assert(rv == SECSuccess); @@ -2043,23 +2049,26 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec, const int nonceLen = cwSpec->cipherDef->explicit_nonce_size; const int tagLen = cwSpec->cipherDef->tag_size; - if (nonceLen + contentLen + tagLen > wrBuf->space) { + if (nonceLen + contentLen + tagLen > SSL_BUFFER_SPACE(wrBuf)) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } rv = cwSpec->aead( &cwSpec->keyMaterial, - PR_FALSE, /* do encrypt */ - wrBuf->buf, /* output */ - (int *)&wrBuf->len, /* out len */ - wrBuf->space, /* max out */ - pIn, contentLen, /* input */ + PR_FALSE, /* do encrypt */ + SSL_BUFFER_NEXT(wrBuf), /* output */ + &len, /* out len */ + SSL_BUFFER_SPACE(wrBuf), /* max out */ + pIn, contentLen, /* input */ SSL_BUFFER_BASE(&pseudoHeader), SSL_BUFFER_LEN(&pseudoHeader)); if (rv != SECSuccess) { PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); return SECFailure; } + + rv = sslBuffer_Skip(wrBuf, len, NULL); + PORT_Assert(rv == SECSuccess); /* Can't fail. */ } else { int blockSize = cwSpec->cipherDef->block_size; @@ -2069,7 +2078,7 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec, rv = ssl3_ComputeRecordMAC(cwSpec, SSL_BUFFER_BASE(&pseudoHeader), SSL_BUFFER_LEN(&pseudoHeader), pIn, contentLen, - wrBuf->buf + ivLen + contentLen, &macLen); + SSL_BUFFER_NEXT(wrBuf) + contentLen, &macLen); if (rv != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); return SECFailure; @@ -2095,7 +2104,7 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec, PORT_Assert((fragLen % blockSize) == 0); /* Pad according to TLS rules (also acceptable to SSL3). */ - pBuf = &wrBuf->buf[ivLen + fragLen - 1]; + pBuf = SSL_BUFFER_NEXT(wrBuf) + fragLen - 1; for (i = padding_length + 1; i > 0; --i) { *pBuf-- = padding_length; } @@ -2112,14 +2121,14 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec, p2Len += oddLen; PORT_Assert((blockSize < 2) || (p2Len % blockSize) == 0); - memmove(wrBuf->buf + ivLen + p1Len, pIn + p1Len, oddLen); + memmove(SSL_BUFFER_NEXT(wrBuf) + p1Len, pIn + p1Len, oddLen); } if (p1Len > 0) { int cipherBytesPart1 = -1; rv = cwSpec->cipher(cwSpec->cipherContext, - wrBuf->buf + ivLen, /* output */ - &cipherBytesPart1, /* actual outlen */ - p1Len, /* max outlen */ + SSL_BUFFER_NEXT(wrBuf), /* output */ + &cipherBytesPart1, /* actual outlen */ + p1Len, /* max outlen */ pIn, p1Len); /* input, and inputlen */ PORT_Assert(rv == SECSuccess && cipherBytesPart1 == (int)p1Len); @@ -2127,22 +2136,24 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec, PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); return SECFailure; } - wrBuf->len += cipherBytesPart1; + rv = sslBuffer_Skip(wrBuf, p1Len, NULL); + PORT_Assert(rv == SECSuccess); } if (p2Len > 0) { int cipherBytesPart2 = -1; rv = cwSpec->cipher(cwSpec->cipherContext, - wrBuf->buf + ivLen + p1Len, + SSL_BUFFER_NEXT(wrBuf), &cipherBytesPart2, /* output and actual outLen */ p2Len, /* max outlen */ - wrBuf->buf + ivLen + p1Len, + SSL_BUFFER_NEXT(wrBuf), p2Len); /* input and inputLen*/ PORT_Assert(rv == SECSuccess && cipherBytesPart2 == (int)p2Len); if (rv != SECSuccess || cipherBytesPart2 != (int)p2Len) { PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); return SECFailure; } - wrBuf->len += cipherBytesPart2; + rv = sslBuffer_Skip(wrBuf, p2Len, NULL); + PORT_Assert(rv == SECSuccess); } } @@ -2150,16 +2161,20 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec, } /* Note: though this can report failure, it shouldn't. */ -static SECStatus +SECStatus ssl_InsertRecordHeader(const sslSocket *ss, ssl3CipherSpec *cwSpec, - SSL3ContentType contentType, unsigned int len, - sslBuffer *wrBuf) + SSL3ContentType contentType, sslBuffer *wrBuf, + PRBool *needsLength) { SECStatus rv; #ifndef UNSAFE_FUZZER_MODE if (cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_3 && - cwSpec->cipherDef->calg != ssl_calg_null) { + cwSpec->epoch > TrafficKeyClearText) { + if (IS_DTLS(ss)) { + return dtls13_InsertCipherTextHeader(ss, cwSpec, wrBuf, + needsLength); + } contentType = content_application_data; } #endif @@ -2177,16 +2192,12 @@ ssl_InsertRecordHeader(const sslSocket *ss, ssl3CipherSpec *cwSpec, if (rv != SECSuccess) { return SECFailure; } - rv = sslBuffer_AppendNumber(wrBuf, cwSpec->seqNum, 6); + rv = sslBuffer_AppendNumber(wrBuf, cwSpec->nextSeqNum, 6); if (rv != SECSuccess) { return SECFailure; } } - rv = sslBuffer_AppendNumber(wrBuf, len, 2); - if (rv != SECSuccess) { - return SECFailure; - } - + *needsLength = PR_TRUE; return SECSuccess; } @@ -2194,66 +2205,67 @@ SECStatus ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, SSL3ContentType type, const PRUint8 *pIn, PRUint32 contentLen, sslBuffer *wrBuf) { - unsigned int headerLen = IS_DTLS(ss) ? DTLS_RECORD_HEADER_LENGTH - : SSL3_RECORD_HEADER_LENGTH; - sslBuffer protBuf = SSL_BUFFER_FIXED(SSL_BUFFER_BASE(wrBuf) + headerLen, - SSL_BUFFER_SPACE(wrBuf) - headerLen); - PRBool isTLS13; + PRBool needsLength; + unsigned int lenOffset; SECStatus rv; PORT_Assert(cwSpec->direction == CipherSpecWrite); PORT_Assert(SSL_BUFFER_LEN(wrBuf) == 0); PORT_Assert(cwSpec->cipherDef->max_records <= RECORD_SEQ_MAX); - if (cwSpec->seqNum >= cwSpec->cipherDef->max_records) { + + if (cwSpec->nextSeqNum >= cwSpec->cipherDef->max_records) { /* We should have automatically updated before here in TLS 1.3. */ PORT_Assert(cwSpec->version < SSL_LIBRARY_VERSION_TLS_1_3); SSL_TRC(3, ("%d: SSL[-]: write sequence number at limit 0x%0llx", - SSL_GETPID(), cwSpec->seqNum)); + SSL_GETPID(), cwSpec->nextSeqNum)); PORT_SetError(SSL_ERROR_TOO_MANY_RECORDS); return SECFailure; } - isTLS13 = (PRBool)(cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_3); + rv = ssl_InsertRecordHeader(ss, cwSpec, type, wrBuf, &needsLength); + if (rv != SECSuccess) { + return SECFailure; + } + if (needsLength) { + rv = sslBuffer_Skip(wrBuf, 2, &lenOffset); + if (rv != SECSuccess) { + return SECFailure; + } + } #ifdef UNSAFE_FUZZER_MODE { int len; - rv = Null_Cipher(NULL, SSL_BUFFER_BASE(&protBuf), &len, - SSL_BUFFER_SPACE(&protBuf), pIn, contentLen); + rv = Null_Cipher(NULL, SSL_BUFFER_NEXT(wrBuf), &len, + SSL_BUFFER_SPACE(wrBuf), pIn, contentLen); if (rv != SECSuccess) { return SECFailure; /* error was set */ } - rv = sslBuffer_Skip(&protBuf, len, NULL); + rv = sslBuffer_Skip(wrBuf, len, NULL); PORT_Assert(rv == SECSuccess); /* Can't fail. */ } #else - if (isTLS13) { - rv = tls13_ProtectRecord(ss, cwSpec, type, pIn, contentLen, &protBuf); + if (cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_3) { + rv = tls13_ProtectRecord(ss, cwSpec, type, pIn, contentLen, wrBuf); } else { rv = ssl3_MACEncryptRecord(cwSpec, ss->sec.isServer, IS_DTLS(ss), type, - pIn, contentLen, &protBuf); + pIn, contentLen, wrBuf); } #endif if (rv != SECSuccess) { return SECFailure; /* error was set */ } - PORT_Assert(protBuf.len <= MAX_FRAGMENT_LENGTH + (isTLS13 ? 256 : 1024)); - - rv = ssl_InsertRecordHeader(ss, cwSpec, type, SSL_BUFFER_LEN(&protBuf), - wrBuf); - if (rv != SECSuccess) { - return SECFailure; - } - - PORT_Assert(SSL_BUFFER_LEN(wrBuf) == headerLen); - rv = sslBuffer_Skip(wrBuf, SSL_BUFFER_LEN(&protBuf), NULL); - if (rv != SECSuccess) { - PORT_Assert(0); /* Can't fail. */ - return SECFailure; + if (needsLength) { + /* Insert the length. */ + rv = sslBuffer_InsertLength(wrBuf, lenOffset, 2); + if (rv != SECSuccess) { + PORT_Assert(0); /* Can't fail. */ + return SECFailure; + } } - ++cwSpec->seqNum; + ++cwSpec->nextSeqNum; return SECSuccess; } @@ -2267,7 +2279,7 @@ ssl_ProtectNextRecord(sslSocket *ss, ssl3CipherSpec *spec, SSL3ContentType type, unsigned int spaceNeeded; SECStatus rv; - contentLen = PR_MIN(nIn, MAX_FRAGMENT_LENGTH); + contentLen = PR_MIN(nIn, spec->recordSizeLimit); spaceNeeded = contentLen + SSL3_BUFFER_FUDGE; if (spec->version >= SSL_LIBRARY_VERSION_TLS_1_1 && spec->cipherDef->type == type_block) { @@ -2291,6 +2303,7 @@ ssl_ProtectNextRecord(sslSocket *ss, ssl3CipherSpec *spec, SSL3ContentType type, *written = contentLen; return SECSuccess; } + /* Process the plain text before sending it. * Returns the number of bytes of plaintext that were successfully sent * plus the number of bytes of plaintext that were copied into the @@ -2368,7 +2381,7 @@ ssl3_SendRecord(sslSocket *ss, rv = ssl_ProtectNextRecord(ss, spec, type, pIn, nIn, &written); ssl_ReleaseSpecReadLock(ss); if (rv != SECSuccess) { - return SECFailure; + goto loser; } PORT_Assert(written > 0); @@ -3034,7 +3047,6 @@ ssl3_SendChangeCipherSpecsInt(sslSocket *ss) return SECFailure; /* error code set by ssl3_SendRecord */ } } else { - SECStatus rv; rv = dtls_QueueMessage(ss, content_change_cipher_spec, &change, 1); if (rv != SECSuccess) { return SECFailure; @@ -5567,13 +5579,20 @@ ssl3_SendRSAClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey) } /* Get the wrapped (encrypted) pre-master secret, enc_pms */ - enc_pms.len = SECKEY_PublicKeyStrength(svrPubKey); + unsigned int svrPubKeyBits = SECKEY_PublicKeyStrengthInBits(svrPubKey); + enc_pms.len = (svrPubKeyBits + 7) / 8; + /* Check that the RSA key isn't larger than 8k bit. */ + if (svrPubKeyBits > SSL_MAX_RSA_KEY_BITS) { + (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter); + ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); + goto loser; + } enc_pms.data = (unsigned char *)PORT_Alloc(enc_pms.len); if (enc_pms.data == NULL) { goto loser; /* err set by PORT_Alloc */ } - /* wrap pre-master secret in server's public key. */ + /* Wrap pre-master secret in server's public key. */ rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, svrPubKey, pms, &enc_pms); if (rv != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); @@ -5676,7 +5695,7 @@ ssl3_SendDHClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey) }; sslEphemeralKeyPair *keyPair = NULL; SECKEYPublicKey *pubKey; - PRUint8 dhData[1026]; /* Enough for the 8192-bit group. */ + PRUint8 dhData[SSL_MAX_DH_KEY_BITS / 8 + 2]; sslBuffer dhBuf = SSL_BUFFER(dhData); PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); @@ -6208,7 +6227,6 @@ ssl3_HandleServerHello(sslSocket *ss, PRUint8 *b, PRUint32 length) SECItem sidBytes = { siBuffer, NULL, 0 }; PRBool isHelloRetry; SSL3AlertDescription desc = illegal_parameter; - TLSExtension *versionExtension; const PRUint8 *savedMsg = b; const PRUint32 savedLength = length; #ifndef TLS_1_3_DRAFT_VERSION @@ -6299,16 +6317,10 @@ ssl3_HandleServerHello(sslSocket *ss, PRUint8 *b, PRUint32 length) } } - /* Update the version based on the extension, as necessary. */ - versionExtension = ssl3_FindExtension(ss, ssl_tls13_supported_versions_xtn); - if (versionExtension) { - rv = ssl_ClientReadVersion(ss, &versionExtension->data.data, - &versionExtension->data.len, - &ss->version); - if (rv != SECSuccess) { - errCode = PORT_GetError(); - goto loser; /* An alert is sent by ssl_ClientReadVersion */ - } + /* Read supported_versions if present. */ + rv = tls13_ClientReadSupportedVersion(ss); + if (rv != SECSuccess) { + goto loser; } PORT_Assert(!SSL_ALL_VERSIONS_DISABLED(&ss->vrange)); @@ -6332,7 +6344,7 @@ ssl3_HandleServerHello(sslSocket *ss, PRUint8 *b, PRUint32 length) /* The server didn't pick 1.3 although we either received a * HelloRetryRequest, or we prepared to send early app data. */ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { - if (ss->ssl3.hs.helloRetry) { + if (isHelloRetry || ss->ssl3.hs.helloRetry) { /* SSL3_SendAlert() will uncache the SID. */ desc = illegal_parameter; errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO; @@ -6393,8 +6405,9 @@ ssl3_HandleServerHello(sslSocket *ss, PRUint8 *b, PRUint32 length) /* Finally, now all the version-related checks have passed. */ ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_version; /* Update the write cipher spec to match the version. But not after - * HelloRetryRequest, because cwSpec might be a 0-RTT cipher spec. */ - if (!ss->firstHsDone && !ss->ssl3.hs.helloRetry) { + * HelloRetryRequest, because cwSpec might be a 0-RTT cipher spec, + * in which case this is a no-op. */ + if (!ss->firstHsDone && !isHelloRetry) { ssl_GetSpecWriteLock(ss); ssl_SetSpecVersions(ss, ss->ssl3.cwSpec); ssl_ReleaseSpecWriteLock(ss); @@ -6729,6 +6742,10 @@ ssl_HandleDHServerKeyExchange(sslSocket *ss, PRUint8 *b, PRUint32 length) errCode = SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY; goto alert_loser; } + if (dh_p_bits > SSL_MAX_DH_KEY_BITS) { + errCode = SSL_ERROR_DH_KEY_TOO_LONG; + goto alert_loser; + } rv = ssl3_ConsumeHandshakeVariable(ss, &dh_g, 2, &b, &length); if (rv != SECSuccess) { goto loser; /* malformed. */ @@ -6938,8 +6955,10 @@ ssl3_ParseCertificateRequestCAs(sslSocket *ss, PRUint8 **b, PRUint32 *length, goto alert_loser; /* malformed */ remaining -= 2; + if (SECITEM_MakeItem(ca_list->arena, &node->name, *b, len) != SECSuccess) { + goto no_mem; + } node->name.len = len; - node->name.data = *b; *b += len; *length -= len; remaining -= len; @@ -6967,7 +6986,6 @@ ssl3_ParseCertificateRequestCAs(sslSocket *ss, PRUint8 **b, PRUint32 *length, return SECSuccess; no_mem: - PORT_SetError(SEC_ERROR_NO_MEMORY); return SECFailure; alert_loser: @@ -7332,10 +7350,6 @@ ssl3_SendClientSecondRound(sslSocket *ss) * certificate to an attacker that does not have a valid cert for the * domain we are connecting to. * - * XXX: We should do the same for the NPN extension, but for that we - * need an option to give the application the ability to leak the NPN - * information to get better performance. - * * During the initial handshake on a connection, we never send/receive * application data until we have authenticated the server's certificate; * i.e. we have fully authenticated the handshake before using the cipher @@ -7409,14 +7423,6 @@ ssl3_SendClientSecondRound(sslSocket *ss) ss->enoughFirstHsDone = PR_TRUE; if (!ss->firstHsDone) { - /* XXX: If the server's certificate hasn't been authenticated by this - * point, then we may be leaking this NPN message to an attacker. - */ - rv = ssl3_SendNextProto(ss); - if (rv != SECSuccess) { - goto loser; /* err code was set. */ - } - if (ss->opt.enableFalseStart) { if (!ss->ssl3.hs.authCertificatePending) { /* When we fix bug 589047, we will need to know whether we are @@ -8879,12 +8885,10 @@ ssl_ConstructServerHello(sslSocket *ss, PRBool helloRetry, SSL3ProtocolVersion version; sslSessionID *sid = ss->sec.ci.sid; - if (IS_DTLS(ss) && ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { - version = dtls_TLSVersionToDTLSVersion(ss->version); - } else { - version = PR_MIN(ss->version, SSL_LIBRARY_VERSION_TLS_1_2); + version = PR_MIN(ss->version, SSL_LIBRARY_VERSION_TLS_1_2); + if (IS_DTLS(ss)) { + version = dtls_TLSVersionToDTLSVersion(version); } - rv = sslBuffer_AppendNumber(messageBuf, version, 2); if (rv != SECSuccess) { return SECFailure; @@ -11404,6 +11408,10 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length, /* Increment the expected sequence number */ ss->ssl3.hs.recvMessageSeq++; } + + /* Taint the message so that it's easier to detect UAFs. */ + PORT_Memset(b, 'N', length); + return rv; } @@ -11738,7 +11746,7 @@ ssl_RemoveTLSCBCPadding(sslBuffer *plaintext, unsigned int macSize) } for (i = 0; i < toCheck; i++) { - unsigned int t = paddingLength - i; + t = paddingLength - i; /* If i <= paddingLength then the MSB of t is zero and mask is * 0xff. Otherwise, mask is 0. */ unsigned char mask = DUPLICATE_MSB_TO_ALL(~t); @@ -11878,6 +11886,7 @@ ssl3_UnprotectRecord(sslSocket *ss, unsigned int good; unsigned int ivLen = 0; SSL3ContentType rType; + SSL3ProtocolVersion rVersion; unsigned int minLength; unsigned int originalLen = 0; PRUint8 headerBuf[13]; @@ -11950,7 +11959,9 @@ ssl3_UnprotectRecord(sslSocket *ss, return SECFailure; } - rType = cText->type; + rType = (SSL3ContentType)cText->hdr[0]; + rVersion = ((SSL3ProtocolVersion)cText->hdr[1] << 8) | + (SSL3ProtocolVersion)cText->hdr[2]; if (cipher_def->type == type_aead) { /* XXX For many AEAD ciphers, the plaintext is shorter than the * ciphertext by a fixed byte count, but it is not true in general. @@ -11960,8 +11971,8 @@ ssl3_UnprotectRecord(sslSocket *ss, cText->buf->len - cipher_def->explicit_nonce_size - cipher_def->tag_size; rv = ssl3_BuildRecordPseudoHeader( - spec->epoch, IS_DTLS(ss) ? cText->seq_num : spec->seqNum, - rType, isTLS, cText->version, IS_DTLS(ss), decryptedLen, &header); + spec->epoch, cText->seqNum, + rType, isTLS, rVersion, IS_DTLS(ss), decryptedLen, &header); PORT_Assert(rv == SECSuccess); rv = spec->aead(&spec->keyMaterial, PR_TRUE, /* do decrypt */ @@ -12008,8 +12019,8 @@ ssl3_UnprotectRecord(sslSocket *ss, /* compute the MAC */ rv = ssl3_BuildRecordPseudoHeader( - spec->epoch, IS_DTLS(ss) ? cText->seq_num : spec->seqNum, - rType, isTLS, cText->version, IS_DTLS(ss), + spec->epoch, cText->seqNum, + rType, isTLS, rVersion, IS_DTLS(ss), plaintext->len - spec->macDef->mac_size, &header); PORT_Assert(rv == SECSuccess); if (cipher_def->type == type_block) { @@ -12059,13 +12070,19 @@ ssl3_UnprotectRecord(sslSocket *ss, return SECSuccess; } -static SECStatus +SECStatus ssl3_HandleNonApplicationData(sslSocket *ss, SSL3ContentType rType, DTLSEpoch epoch, sslSequenceNumber seqNum, sslBuffer *databuf) { SECStatus rv; + /* check for Token Presence */ + if (!ssl3_ClientAuthTokenPresent(ss->sec.ci.sid)) { + PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL); + return SECFailure; + } + ssl_GetSSL3HandshakeLock(ss); /* All the functions called in this switch MUST set error code if @@ -12111,15 +12128,16 @@ ssl3_HandleNonApplicationData(sslSocket *ss, SSL3ContentType rType, * Returns NULL if no appropriate cipher spec is found. */ static ssl3CipherSpec * -ssl3_GetCipherSpec(sslSocket *ss, sslSequenceNumber seq) +ssl3_GetCipherSpec(sslSocket *ss, SSL3Ciphertext *cText) { ssl3CipherSpec *crSpec = ss->ssl3.crSpec; ssl3CipherSpec *newSpec = NULL; - DTLSEpoch epoch = seq >> 48; + DTLSEpoch epoch; if (!IS_DTLS(ss)) { return crSpec; } + epoch = dtls_ReadEpoch(crSpec, cText->hdr); if (crSpec->epoch == epoch) { return crSpec; } @@ -12136,6 +12154,11 @@ ssl3_GetCipherSpec(sslSocket *ss, sslSequenceNumber seq) return NULL; } +/* MAX_EXPANSION is the amount by which a record might plausibly be expanded + * when protected. It's the worst case estimate, so the sum of block cipher + * padding (up to 256 octets) and HMAC (48 octets for SHA-384). */ +#define MAX_EXPANSION (256 + 48) + /* if cText is non-null, then decipher and check the MAC of the * SSL record from cText->buf (typically gs->inbuf) * into databuf (typically gs->buf), and any previous contents of databuf @@ -12159,16 +12182,16 @@ ssl3_GetCipherSpec(sslSocket *ss, sslSequenceNumber seq) * Application Data records. */ SECStatus -ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) +ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText) { SECStatus rv; PRBool isTLS; DTLSEpoch epoch; - sslSequenceNumber seqNum = 0; ssl3CipherSpec *spec = NULL; + PRUint16 recordSizeLimit; PRBool outOfOrderSpec = PR_FALSE; SSL3ContentType rType; - sslBuffer *plaintext; + sslBuffer *plaintext = &ss->gs.buf; SSL3AlertDescription alert = internal_error; PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); @@ -12178,27 +12201,23 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) return SECFailure; } - /* cText is NULL when we're called from ssl3_RestartHandshakeAfterXXX(). - * This implies that databuf holds a previously deciphered SSL Handshake - * message. - */ - if (cText == NULL) { - SSL_DBG(("%d: SSL3[%d]: HandleRecord, resuming handshake", - SSL_GETPID(), ss->fd)); - /* Note that this doesn't pass the epoch and sequence number of the - * record through, which DTLS 1.3 depends on. DTLS doesn't support - * asynchronous certificate validation, so that should be OK. */ - PORT_Assert(!IS_DTLS(ss)); - return ssl3_HandleNonApplicationData(ss, content_handshake, - 0, 0, databuf); + /* Clear out the buffer in case this exits early. Any data then won't be + * processed twice. */ + plaintext->len = 0; + + /* We're waiting for another ClientHello, which will appear unencrypted. + * Use the content type to tell whether this should be discarded. */ + if (ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_hrr && + cText->hdr[0] == content_application_data) { + PORT_Assert(ss->ssl3.hs.ws == wait_client_hello); + return SECSuccess; } ssl_GetSpecReadLock(ss); /******************************************/ - spec = ssl3_GetCipherSpec(ss, cText->seq_num); + spec = ssl3_GetCipherSpec(ss, cText); if (!spec) { PORT_Assert(IS_DTLS(ss)); ssl_ReleaseSpecReadLock(ss); /*****************************/ - databuf->len = 0; /* Needed to ensure data not left around */ return SECSuccess; } if (spec != ss->ssl3.crSpec) { @@ -12209,66 +12228,68 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) } isTLS = (PRBool)(spec->version > SSL_LIBRARY_VERSION_3_0); if (IS_DTLS(ss)) { - if (!dtls_IsRelevant(ss, spec, cText, &seqNum)) { + if (!dtls_IsRelevant(ss, spec, cText, &cText->seqNum)) { ssl_ReleaseSpecReadLock(ss); /*****************************/ - databuf->len = 0; /* Needed to ensure data not left around */ - return SECSuccess; } } else { - seqNum = spec->seqNum + 1; + cText->seqNum = spec->nextSeqNum; } - if (seqNum >= spec->cipherDef->max_records) { + if (cText->seqNum >= spec->cipherDef->max_records) { ssl_ReleaseSpecReadLock(ss); /*****************************/ SSL_TRC(3, ("%d: SSL[%d]: read sequence number at limit 0x%0llx", - SSL_GETPID(), ss->fd, seqNum)); + SSL_GETPID(), ss->fd, cText->seqNum)); PORT_SetError(SSL_ERROR_TOO_MANY_RECORDS); return SECFailure; } - plaintext = databuf; - plaintext->len = 0; /* filled in by Unprotect call below. */ - - /* We're waiting for another ClientHello, which will appear unencrypted. - * Use the content type to tell whether this is should be discarded. - * - * XXX If we decide to remove the content type from encrypted records, this - * will become much more difficult to manage. */ - if (ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_hrr && - cText->type == content_application_data) { + recordSizeLimit = spec->recordSizeLimit; + if (cText->buf->len > recordSizeLimit + MAX_EXPANSION) { ssl_ReleaseSpecReadLock(ss); /*****************************/ - PORT_Assert(ss->ssl3.hs.ws == wait_client_hello); - databuf->len = 0; - return SECSuccess; + SSL3_SendAlert(ss, alert_fatal, record_overflow); + PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG); + return SECFailure; } - if (plaintext->space < MAX_FRAGMENT_LENGTH) { - rv = sslBuffer_Grow(plaintext, MAX_FRAGMENT_LENGTH + 2048); + if (plaintext->space < recordSizeLimit + MAX_EXPANSION) { + rv = sslBuffer_Grow(plaintext, recordSizeLimit + MAX_EXPANSION); if (rv != SECSuccess) { ssl_ReleaseSpecReadLock(ss); /*************************/ SSL_DBG(("%d: SSL3[%d]: HandleRecord, tried to get %d bytes", - SSL_GETPID(), ss->fd, MAX_FRAGMENT_LENGTH + 2048)); + SSL_GETPID(), ss->fd, recordSizeLimit + MAX_EXPANSION)); /* sslBuffer_Grow has set a memory error code. */ /* Perhaps we should send an alert. (but we have no memory!) */ return SECFailure; } } + /* Most record types aside from protected TLS 1.3 records carry the content + * type in the first octet. TLS 1.3 will override this value later. */ + rType = cText->hdr[0]; + /* Encrypted application data records could arrive before the handshake + * completes in DTLS 1.3. These can look like valid TLS 1.2 application_data + * records in epoch 0, which is never valid. Pretend they didn't decrypt. */ + if (spec->epoch == 0 && rType == content_application_data) { + PORT_SetError(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA); + alert = unexpected_message; + rv = SECFailure; + } else { #ifdef UNSAFE_FUZZER_MODE - rv = Null_Cipher(NULL, plaintext->buf, (int *)&plaintext->len, - plaintext->space, cText->buf->buf, cText->buf->len); + rv = Null_Cipher(NULL, plaintext->buf, (int *)&plaintext->len, + plaintext->space, cText->buf->buf, cText->buf->len); #else - /* IMPORTANT: Unprotect functions MUST NOT send alerts - * because we still hold the spec read lock. Instead, if they - * return SECFailure, they set *alert to the alert to be sent. */ - if (spec->version < SSL_LIBRARY_VERSION_TLS_1_3 || - spec->cipherDef->calg == ssl_calg_null) { - /* Unencrypted TLS 1.3 records use the pre-TLS 1.3 format. */ - rv = ssl3_UnprotectRecord(ss, spec, cText, plaintext, &alert); - } else { - rv = tls13_UnprotectRecord(ss, spec, cText, plaintext, &alert); - } + /* IMPORTANT: Unprotect functions MUST NOT send alerts + * because we still hold the spec read lock. Instead, if they + * return SECFailure, they set *alert to the alert to be sent. */ + if (spec->version < SSL_LIBRARY_VERSION_TLS_1_3 || + spec->epoch == 0) { + rv = ssl3_UnprotectRecord(ss, spec, cText, plaintext, &alert); + } else { + rv = tls13_UnprotectRecord(ss, spec, cText, plaintext, &rType, + &alert); + } #endif + } if (rv != SECSuccess) { ssl_ReleaseSpecReadLock(ss); /***************************/ @@ -12276,39 +12297,45 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) SSL_DBG(("%d: SSL3[%d]: decryption failed", SSL_GETPID(), ss->fd)); /* Ensure that we don't process this data again. */ - databuf->len = 0; + plaintext->len = 0; - /* Ignore a CCS if the alternative handshake is negotiated. Note that - * this will fail if the server fails to negotiate the alternative - * handshake type in a 0-RTT session that is resumed from a session that - * did negotiate it. We don't care about that corner case right now. */ + /* Ignore a CCS if compatibility mode is negotiated. Note that this + * will fail if the server fails to negotiate compatibility mode in a + * 0-RTT session that is resumed from a session that did negotiate it. + * We don't care about that corner case right now. */ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 && - cText->type == content_change_cipher_spec && + cText->hdr[0] == content_change_cipher_spec && ss->ssl3.hs.ws != idle_handshake && cText->buf->len == 1 && cText->buf->buf[0] == change_cipher_spec_choice) { /* Ignore the CCS. */ return SECSuccess; } + if (IS_DTLS(ss) || (ss->sec.isServer && ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_trial)) { - /* Silently drop the packet */ + /* Silently drop the packet unless we sent a fatal alert. */ + if (ss->ssl3.fatalAlertSent) { + return SECFailure; + } return SECSuccess; - } else { - int errCode = PORT_GetError(); - SSL3_SendAlert(ss, alert_fatal, alert); - /* Reset the error code in case SSL3_SendAlert called - * PORT_SetError(). */ - PORT_SetError(errCode); - return SECFailure; } + + int errCode = PORT_GetError(); + SSL3_SendAlert(ss, alert_fatal, alert); + /* Reset the error code in case SSL3_SendAlert called + * PORT_SetError(). */ + PORT_SetError(errCode); + return SECFailure; } /* SECSuccess */ - spec->seqNum = PR_MAX(spec->seqNum, seqNum); if (IS_DTLS(ss)) { - dtls_RecordSetRecvd(&spec->recvdRecords, seqNum); + dtls_RecordSetRecvd(&spec->recvdRecords, cText->seqNum); + spec->nextSeqNum = PR_MAX(spec->nextSeqNum, cText->seqNum + 1); + } else { + ++spec->nextSeqNum; } epoch = spec->epoch; @@ -12317,19 +12344,18 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) /* * The decrypted data is now in plaintext. */ - rType = cText->type; /* This must go after decryption because TLS 1.3 - * has encrypted content types. */ /* IMPORTANT: We are in DTLS 1.3 mode and we have processed something * from the wrong epoch. Divert to a divert processing function to make * sure we don't accidentally use the data unsafely. */ if (outOfOrderSpec) { PORT_Assert(IS_DTLS(ss) && ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); - return dtls13_HandleOutOfEpochRecord(ss, spec, rType, databuf); + return dtls13_HandleOutOfEpochRecord(ss, spec, rType, plaintext); } /* Check the length of the plaintext. */ - if (isTLS && databuf->len > MAX_FRAGMENT_LENGTH) { + if (isTLS && plaintext->len > recordSizeLimit) { + plaintext->len = 0; SSL3_SendAlert(ss, alert_fatal, record_overflow); PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG); return SECFailure; @@ -12344,14 +12370,16 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 && ss->sec.isServer && ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) { - return tls13_HandleEarlyApplicationData(ss, databuf); + return tls13_HandleEarlyApplicationData(ss, plaintext); } + plaintext->len = 0; (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); PORT_SetError(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA); return SECFailure; } - return ssl3_HandleNonApplicationData(ss, rType, epoch, seqNum, databuf); + return ssl3_HandleNonApplicationData(ss, rType, epoch, cText->seqNum, + plaintext); } /* diff --git a/security/nss/lib/ssl/ssl3ecc.c b/security/nss/lib/ssl/ssl3ecc.c index 913a14f63..f8b9a9400 100644 --- a/security/nss/lib/ssl/ssl3ecc.c +++ b/security/nss/lib/ssl/ssl3ecc.c @@ -548,12 +548,14 @@ ssl3_HandleECDHServerKeyExchange(sslSocket *ss, PRUint8 *b, PRUint32 length) if (ss->ssl3.prSpec->version == SSL_LIBRARY_VERSION_TLS_1_2) { rv = ssl_ConsumeSignatureScheme(ss, &b, &length, &sigScheme); if (rv != SECSuccess) { - goto loser; /* malformed or unsupported. */ + errCode = PORT_GetError(); + goto alert_loser; /* malformed or unsupported. */ } rv = ssl_CheckSignatureSchemeConsistency(ss, sigScheme, ss->sec.peerCert); if (rv != SECSuccess) { - goto loser; + errCode = PORT_GetError(); + goto alert_loser; } hashAlg = ssl_SignatureSchemeToHashType(sigScheme); } else { diff --git a/security/nss/lib/ssl/ssl3ext.c b/security/nss/lib/ssl/ssl3ext.c index 5a5077998..9b6c719f8 100644 --- a/security/nss/lib/ssl/ssl3ext.c +++ b/security/nss/lib/ssl/ssl3ext.c @@ -39,7 +39,6 @@ static const ssl3ExtensionHandler clientHelloHandlers[] = { { ssl_ec_point_formats_xtn, &ssl3_HandleSupportedPointFormatsXtn }, { ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn }, { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, - { ssl_next_proto_nego_xtn, &ssl3_ServerHandleNextProtoNegoXtn }, { ssl_app_layer_protocol_xtn, &ssl3_ServerHandleAppProtoXtn }, { ssl_use_srtp_xtn, &ssl3_ServerHandleUseSRTPXtn }, { ssl_cert_status_xtn, &ssl3_ServerHandleStatusRequestXtn }, @@ -51,6 +50,7 @@ static const ssl3ExtensionHandler clientHelloHandlers[] = { { ssl_tls13_early_data_xtn, &tls13_ServerHandleEarlyDataXtn }, { ssl_tls13_psk_key_exchange_modes_xtn, &tls13_ServerHandlePskModesXtn }, { ssl_tls13_cookie_xtn, &tls13_ServerHandleCookieXtn }, + { ssl_record_size_limit_xtn, &ssl_HandleRecordSizeLimitXtn }, { 0, NULL } }; @@ -61,7 +61,6 @@ static const ssl3ExtensionHandler serverHelloHandlersTLS[] = { /* TODO: add a handler for ssl_ec_point_formats_xtn */ { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn }, { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, - { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, { ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn }, { ssl_use_srtp_xtn, &ssl3_ClientHandleUseSRTPXtn }, { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, @@ -70,6 +69,7 @@ static const ssl3ExtensionHandler serverHelloHandlersTLS[] = { { ssl_tls13_key_share_xtn, &tls13_ClientHandleKeyShareXtn }, { ssl_tls13_pre_shared_key_xtn, &tls13_ClientHandlePreSharedKeyXtn }, { ssl_tls13_early_data_xtn, &tls13_ClientHandleEarlyDataXtn }, + { ssl_record_size_limit_xtn, &ssl_HandleRecordSizeLimitXtn }, { 0, NULL } }; @@ -122,7 +122,6 @@ static const sslExtensionBuilder clientHelloSendersTLS[] = { ssl_supported_groups_xtn, &ssl_SendSupportedGroupsXtn }, { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn }, { ssl_session_ticket_xtn, &ssl3_ClientSendSessionTicketXtn }, - { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn }, { ssl_app_layer_protocol_xtn, &ssl3_ClientSendAppProtoXtn }, { ssl_use_srtp_xtn, &ssl3_ClientSendUseSRTPXtn }, { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, @@ -137,6 +136,7 @@ static const sslExtensionBuilder clientHelloSendersTLS[] = { ssl_signature_algorithms_xtn, &ssl3_SendSigAlgsXtn }, { ssl_tls13_cookie_xtn, &tls13_ClientSendHrrCookieXtn }, { ssl_tls13_psk_key_exchange_modes_xtn, &tls13_ClientSendPskModesXtn }, + { ssl_record_size_limit_xtn, &ssl_SendRecordSizeLimitXtn }, /* The pre_shared_key extension MUST be last. */ { ssl_tls13_pre_shared_key_xtn, &tls13_ClientSendPreSharedKeyXtn }, { 0, NULL } @@ -183,7 +183,6 @@ static const struct { { ssl_tls13_psk_key_exchange_modes_xtn, ssl_ext_native_only }, { ssl_tls13_ticket_early_data_info_xtn, ssl_ext_native_only }, { ssl_tls13_certificate_authorities_xtn, ssl_ext_native }, - { ssl_next_proto_nego_xtn, ssl_ext_none }, { ssl_renegotiation_info_xtn, ssl_ext_native } }; @@ -681,7 +680,11 @@ ssl_CallCustomExtensionSenders(sslSocket *ss, sslBuffer *buf, } } - sslBuffer_Append(buf, tail.buf, tail.len); + rv = sslBuffer_Append(buf, tail.buf, tail.len); + if (rv != SECSuccess) { + goto loser; /* Code already set. */ + } + sslBuffer_Clear(&tail); return SECSuccess; diff --git a/security/nss/lib/ssl/ssl3ext.h b/security/nss/lib/ssl/ssl3ext.h index d0f75a599..6d77c7459 100644 --- a/security/nss/lib/ssl/ssl3ext.h +++ b/security/nss/lib/ssl/ssl3ext.h @@ -98,6 +98,9 @@ struct TLSExtensionDataStr { /* The application token contains a value that was passed to the client via * a session ticket, or the cookie in a HelloRetryRequest. */ SECItem applicationToken; + + /* The record size limit set by the peer. Our value is kept in ss->opt. */ + PRUint16 recordSizeLimit; }; typedef struct TLSExtensionStr { diff --git a/security/nss/lib/ssl/ssl3exthandle.c b/security/nss/lib/ssl/ssl3exthandle.c index e6388945e..d1f286dc3 100644 --- a/security/nss/lib/ssl/ssl3exthandle.c +++ b/security/nss/lib/ssl/ssl3exthandle.c @@ -242,33 +242,11 @@ ssl_AlpnTagAllowed(const sslSocket *ss, const SECItem *tag) return PR_FALSE; } -/* handle an incoming Next Protocol Negotiation extension. */ -SECStatus -ssl3_ServerHandleNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, - SECItem *data) -{ - PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3); - - if (ss->firstHsDone || data->len != 0) { - /* Clients MUST send an empty NPN extension, if any. */ - PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); - return SECFailure; - } - - xtnData->negotiated[xtnData->numNegotiated++] = ssl_next_proto_nego_xtn; - - /* TODO: server side NPN support would require calling - * ssl3_RegisterServerHelloExtensionSender here in order to echo the - * extension back to the client. */ - - return SECSuccess; -} - -/* ssl3_ValidateNextProtoNego checks that the given block of data is valid: none +/* ssl3_ValidateAppProtocol checks that the given block of data is valid: none * of the lengths may be 0 and the sum of the lengths must equal the length of * the block. */ SECStatus -ssl3_ValidateNextProtoNego(const unsigned char *data, unsigned int length) +ssl3_ValidateAppProtocol(const unsigned char *data, unsigned int length) { unsigned int offset = 0; @@ -286,7 +264,7 @@ ssl3_ValidateNextProtoNego(const unsigned char *data, unsigned int length) return SECSuccess; } -/* protocol selection handler for ALPN (server side) and NPN (client side) */ +/* Protocol selection handler for ALPN. */ static SECStatus ssl3_SelectAppProtocol(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 extension, SECItem *data) @@ -295,7 +273,7 @@ ssl3_SelectAppProtocol(const sslSocket *ss, TLSExtensionData *xtnData, unsigned char resultBuffer[255]; SECItem result = { siBuffer, resultBuffer, 0 }; - rv = ssl3_ValidateNextProtoNego(data->data, data->len); + rv = ssl3_ValidateAppProtocol(data->data, data->len); if (rv != SECSuccess) { ssl3_ExtSendAlert(ss, alert_fatal, decode_error); PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); @@ -303,11 +281,13 @@ ssl3_SelectAppProtocol(const sslSocket *ss, TLSExtensionData *xtnData, } PORT_Assert(ss->nextProtoCallback); - /* For ALPN, the cipher suite isn't selected yet. Note that extensions + /* The cipher suite isn't selected yet. Note that extensions * sometimes affect what cipher suite is selected, e.g., for ECC. */ PORT_Assert((ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all & ~ssl_preinfo_cipher_suite) == (ssl_preinfo_all & ~ssl_preinfo_cipher_suite)); + /* The callback has to make sure that either rv != SECSuccess or that result + * is not set if there is no common protocol. */ rv = ss->nextProtoCallback(ss->nextProtoArg, ss->fd, data->data, data->len, result.data, &result.len, sizeof(resultBuffer)); if (rv != SECSuccess) { @@ -320,21 +300,20 @@ ssl3_SelectAppProtocol(const sslSocket *ss, TLSExtensionData *xtnData, * stack. */ if (result.len > sizeof(resultBuffer)) { PORT_SetError(SEC_ERROR_OUTPUT_LEN); - /* TODO: crash */ + PORT_Assert(PR_FALSE); return SECFailure; } SECITEM_FreeItem(&xtnData->nextProto, PR_FALSE); - if (extension == ssl_app_layer_protocol_xtn && - xtnData->nextProtoState != SSL_NEXT_PROTO_NEGOTIATED) { - /* The callback might say OK, but then it picks a default value - one - * that was not listed. That's OK for NPN, but not ALPN. */ + if (result.len < 1 || !result.data) { + /* Check that we actually got a result. */ ssl3_ExtSendAlert(ss, alert_fatal, no_application_protocol); PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL); return SECFailure; } + xtnData->nextProtoState = SSL_NEXT_PROTO_NEGOTIATED; xtnData->negotiated[xtnData->numNegotiated++] = extension; return SECITEM_CopyItem(NULL, &xtnData->nextProto, &result); } @@ -356,7 +335,7 @@ ssl3_ServerHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, return SECFailure; } - /* Unlike NPN, ALPN has extra redundant length information so that + /* ALPN has extra redundant length information so that * the extension is the same in both ClientHello and ServerHello. */ rv = ssl3_ExtConsumeHandshakeNumber(ss, &count, 2, &data->data, &data->len); if (rv != SECSuccess || count != data->len) { @@ -389,39 +368,6 @@ ssl3_ServerHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, } SECStatus -ssl3_ClientHandleNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, - SECItem *data) -{ - PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3); - PORT_Assert(!ss->firstHsDone); - - if (ssl3_ExtensionNegotiated(ss, ssl_app_layer_protocol_xtn)) { - /* If the server negotiated ALPN then it has already told us what - * protocol to use, so it doesn't make sense for us to try to negotiate - * a different one by sending the NPN handshake message. However, if - * we've negotiated NPN then we're required to send the NPN handshake - * message. Thus, these two extensions cannot both be negotiated on the - * same connection. */ - ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter); - PORT_SetError(SSL_ERROR_BAD_SERVER); - return SECFailure; - } - - /* We should only get this call if we sent the extension, so - * ss->nextProtoCallback needs to be non-NULL. However, it is possible - * that an application erroneously cleared the callback between the time - * we sent the ClientHello and now. */ - if (!ss->nextProtoCallback) { - PORT_Assert(0); - ssl3_ExtSendAlert(ss, alert_fatal, internal_error); - PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK); - return SECFailure; - } - - return ssl3_SelectAppProtocol(ss, xtnData, ssl_next_proto_nego_xtn, data); -} - -SECStatus ssl3_ClientHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, SECItem *data) { @@ -475,19 +421,6 @@ ssl3_ClientHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, } SECStatus -ssl3_ClientSendNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, - sslBuffer *buf, PRBool *added) -{ - /* Renegotiations do not send this extension. */ - if (!ss->opt.enableNPN || !ss->nextProtoCallback || ss->firstHsDone) { - return SECSuccess; - } - - *added = PR_TRUE; - return SECSuccess; -} - -SECStatus ssl3_ClientSendAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, sslBuffer *buf, PRBool *added) { @@ -499,35 +432,15 @@ ssl3_ClientSendAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, return SECSuccess; } - /* NPN requires that the client's fallback protocol is first in the - * list. However, ALPN sends protocols in preference order. So move the - * first protocol to the end of the list. */ - if (len > 0) { /* Each protocol string is prefixed with a single byte length. */ - unsigned int i; - rv = sslBuffer_AppendNumber(buf, len, 2); if (rv != SECSuccess) { return SECFailure; } - - i = ss->opt.nextProtoNego.data[0] + 1; - if (i <= len) { - rv = sslBuffer_Append(buf, &ss->opt.nextProtoNego.data[i], len - i); - if (rv != SECSuccess) { - return SECFailure; - } - rv = sslBuffer_Append(buf, ss->opt.nextProtoNego.data, i); - if (rv != SECSuccess) { - return SECFailure; - } - } else { - /* This seems to be invalid data so we'll send as-is. */ - rv = sslBuffer_Append(buf, ss->opt.nextProtoNego.data, len); - if (rv != SECSuccess) { - return SECFailure; - } + rv = sslBuffer_Append(buf, ss->opt.nextProtoNego.data, len); + if (rv != SECSuccess) { + return SECFailure; } } @@ -1955,3 +1868,67 @@ ssl_HandleSupportedGroupsXtn(const sslSocket *ss, TLSExtensionData *xtnData, return SECSuccess; } + +SECStatus +ssl_HandleRecordSizeLimitXtn(const sslSocket *ss, TLSExtensionData *xtnData, + SECItem *data) +{ + SECStatus rv; + PRUint32 limit; + PRUint32 maxLimit = (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) + ? (MAX_FRAGMENT_LENGTH + 1) + : MAX_FRAGMENT_LENGTH; + + rv = ssl3_ExtConsumeHandshakeNumber(ss, &limit, 2, &data->data, &data->len); + if (rv != SECSuccess) { + return SECFailure; + } + if (data->len != 0 || limit < 64) { + ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter); + PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE); + return SECFailure; + } + + if (ss->sec.isServer) { + rv = ssl3_RegisterExtensionSender(ss, xtnData, ssl_record_size_limit_xtn, + &ssl_SendRecordSizeLimitXtn); + if (rv != SECSuccess) { + return SECFailure; /* error already set. */ + } + } else if (limit > maxLimit) { + /* The client can sensibly check the maximum. */ + ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter); + PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE); + return SECFailure; + } + + /* We can't enforce the maximum on a server. But we do need to ensure + * that we don't apply a limit that is too large. */ + xtnData->recordSizeLimit = PR_MIN(maxLimit, limit); + xtnData->negotiated[xtnData->numNegotiated++] = ssl_record_size_limit_xtn; + return SECSuccess; +} + +SECStatus +ssl_SendRecordSizeLimitXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) +{ + PRUint32 maxLimit; + if (ss->sec.isServer) { + maxLimit = (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) + ? (MAX_FRAGMENT_LENGTH + 1) + : MAX_FRAGMENT_LENGTH; + } else { + maxLimit = (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3) + ? (MAX_FRAGMENT_LENGTH + 1) + : MAX_FRAGMENT_LENGTH; + } + PRUint32 limit = PR_MIN(ss->opt.recordSizeLimit, maxLimit); + SECStatus rv = sslBuffer_AppendNumber(buf, limit, 2); + if (rv != SECSuccess) { + return SECFailure; + } + + *added = PR_TRUE; + return SECSuccess; +} diff --git a/security/nss/lib/ssl/ssl3exthandle.h b/security/nss/lib/ssl/ssl3exthandle.h index b84bd074c..eaf7f0081 100644 --- a/security/nss/lib/ssl/ssl3exthandle.h +++ b/security/nss/lib/ssl/ssl3exthandle.h @@ -119,4 +119,11 @@ SECStatus ssl_SendSupportedGroupsXtn(const sslSocket *ss, SECStatus ssl3_SendSupportedPointFormatsXtn(const sslSocket *ss, TLSExtensionData *xtnData, sslBuffer *buf, PRBool *added); +SECStatus ssl_HandleRecordSizeLimitXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + SECItem *data); +SECStatus ssl_SendRecordSizeLimitXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); + #endif diff --git a/security/nss/lib/ssl/ssl3gthr.c b/security/nss/lib/ssl/ssl3gthr.c index 8b323bb05..5ea7cc249 100644 --- a/security/nss/lib/ssl/ssl3gthr.c +++ b/security/nss/lib/ssl/ssl3gthr.c @@ -158,6 +158,7 @@ ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags, ssl2Gather *ssl2gs) * the length of the following encrypted data, and then * read in the rest of the record into gs->inbuf. */ gs->remainder = (gs->hdr[3] << 8) | gs->hdr[4]; + gs->hdrLen = SSL3_RECORD_HEADER_LENGTH; } else { /* Probably an SSLv2 record header. No need to handle any * security escapes (gs->hdr[0] & 0x40) as we wouldn't get @@ -264,8 +265,9 @@ static int dtls_GatherData(sslSocket *ss, sslGather *gs, int flags) { int nb; - int err; - int rv = 1; + PRUint8 contentType; + unsigned int headerLen; + SECStatus rv; SSL_TRC(30, ("dtls_GatherData")); @@ -285,81 +287,97 @@ dtls_GatherData(sslSocket *ss, sslGather *gs, int flags) ** to 13 (the size of the record header). */ if (gs->dtlsPacket.space < MAX_FRAGMENT_LENGTH + 2048 + 13) { - err = sslBuffer_Grow(&gs->dtlsPacket, - MAX_FRAGMENT_LENGTH + 2048 + 13); - if (err) { /* realloc has set error code to no mem. */ - return err; + rv = sslBuffer_Grow(&gs->dtlsPacket, + MAX_FRAGMENT_LENGTH + 2048 + 13); + if (rv != SECSuccess) { + return -1; /* Code already set. */ } } /* recv() needs to read a full datagram at a time */ nb = ssl_DefRecv(ss, gs->dtlsPacket.buf, gs->dtlsPacket.space, flags); - if (nb > 0) { PRINT_BUF(60, (ss, "raw gather data:", gs->dtlsPacket.buf, nb)); } else if (nb == 0) { /* EOF */ SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd)); - rv = 0; - return rv; + return 0; } else /* if (nb < 0) */ { SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd, PR_GetError())); - rv = SECFailure; - return rv; + return -1; } gs->dtlsPacket.len = nb; } + contentType = gs->dtlsPacket.buf[gs->dtlsPacketOffset]; + if (dtls_IsLongHeader(ss->version, contentType)) { + headerLen = 13; + } else if (contentType == content_application_data) { + headerLen = 7; + } else if ((contentType & 0xe0) == 0x20) { + headerLen = 2; + } else { + SSL_DBG(("%d: SSL3[%d]: invalid first octet (%d) for DTLS", + SSL_GETPID(), ss->fd, contentType)); + PORT_SetError(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE); + gs->dtlsPacketOffset = 0; + gs->dtlsPacket.len = 0; + return -1; + } + /* At this point we should have >=1 complete records lined up in * dtlsPacket. Read off the header. */ - if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < 13) { + if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < headerLen) { SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet " "too short to contain header", SSL_GETPID(), ss->fd)); - PR_SetError(PR_WOULD_BLOCK_ERROR, 0); + PORT_SetError(PR_WOULD_BLOCK_ERROR); gs->dtlsPacketOffset = 0; gs->dtlsPacket.len = 0; - rv = SECFailure; - return rv; + return -1; } - memcpy(gs->hdr, gs->dtlsPacket.buf + gs->dtlsPacketOffset, 13); - gs->dtlsPacketOffset += 13; + memcpy(gs->hdr, SSL_BUFFER_BASE(&gs->dtlsPacket) + gs->dtlsPacketOffset, + headerLen); + gs->hdrLen = headerLen; + gs->dtlsPacketOffset += headerLen; /* Have received SSL3 record header in gs->hdr. */ - gs->remainder = (gs->hdr[11] << 8) | gs->hdr[12]; + if (headerLen == 13) { + gs->remainder = (gs->hdr[11] << 8) | gs->hdr[12]; + } else if (headerLen == 7) { + gs->remainder = (gs->hdr[5] << 8) | gs->hdr[6]; + } else { + PORT_Assert(headerLen == 2); + gs->remainder = gs->dtlsPacket.len - gs->dtlsPacketOffset; + } if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < gs->remainder) { SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet too short " "to contain rest of body", SSL_GETPID(), ss->fd)); - PR_SetError(PR_WOULD_BLOCK_ERROR, 0); + PORT_SetError(PR_WOULD_BLOCK_ERROR); gs->dtlsPacketOffset = 0; gs->dtlsPacket.len = 0; - rv = SECFailure; - return rv; + return -1; } /* OK, we have at least one complete packet, copy into inbuf */ - if (gs->remainder > gs->inbuf.space) { - err = sslBuffer_Grow(&gs->inbuf, gs->remainder); - if (err) { /* realloc has set error code to no mem. */ - return err; - } + gs->inbuf.len = 0; + rv = sslBuffer_Append(&gs->inbuf, + SSL_BUFFER_BASE(&gs->dtlsPacket) + gs->dtlsPacketOffset, + gs->remainder); + if (rv != SECSuccess) { + return -1; /* code already set. */ } - - SSL_TRC(20, ("%d: SSL3[%d]: dtls gathered record type=%d len=%d", - SSL_GETPID(), ss->fd, gs->hdr[0], gs->inbuf.len)); - - memcpy(gs->inbuf.buf, gs->dtlsPacket.buf + gs->dtlsPacketOffset, - gs->remainder); - gs->inbuf.len = gs->remainder; gs->offset = gs->remainder; gs->dtlsPacketOffset += gs->remainder; gs->state = GS_INIT; + SSL_TRC(20, ("%d: SSL3[%d]: dtls gathered record type=%d len=%d", + SSL_GETPID(), ss->fd, contentType, gs->inbuf.len)); return 1; } @@ -442,7 +460,11 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) * We need to process it now before we overwrite it with the next * handshake record. */ - rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf); + SSL_DBG(("%d: SSL3[%d]: resuming handshake", + SSL_GETPID(), ss->fd)); + PORT_Assert(!IS_DTLS(ss)); + rv = ssl3_HandleNonApplicationData(ss, content_handshake, + 0, 0, &ss->gs.buf); } else { /* State for SSLv2 client hello support. */ ssl2Gather ssl2gs = { PR_FALSE, 0 }; @@ -495,20 +517,14 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) * 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.type = (SSL3ContentType)ss->gs.hdr[0]; - cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2]; - - if (IS_DTLS(ss)) { - sslSequenceNumber seq_num; - - /* DTLS sequence number */ - PORT_Memcpy(&seq_num, &ss->gs.hdr[3], sizeof(seq_num)); - cText.seq_num = PR_ntohll(seq_num); - } - + cText.hdr = ss->gs.hdr; + cText.hdrLen = ss->gs.hdrLen; cText.buf = &ss->gs.inbuf; - rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf); + rv = ssl3_HandleRecord(ss, &cText); } } if (rv < 0) { @@ -520,7 +536,6 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) * completing any renegotiation handshake we may be doing. */ PORT_Assert(ss->firstHsDone); - PORT_Assert(cText.type == content_application_data); break; } diff --git a/security/nss/lib/ssl/ssl3prot.h b/security/nss/lib/ssl/ssl3prot.h index d1f46db97..8e6cf2745 100644 --- a/security/nss/lib/ssl/ssl3prot.h +++ b/security/nss/lib/ssl/ssl3prot.h @@ -16,7 +16,7 @@ typedef PRUint16 SSL3ProtocolVersion; /* The TLS 1.3 draft version. Used to avoid negotiating * between incompatible pre-standard TLS 1.3 drafts. * TODO(ekr@rtfm.com): Remove when TLS 1.3 is published. */ -#define TLS_1_3_DRAFT_VERSION 23 +#define TLS_1_3_DRAFT_VERSION 28 typedef PRUint16 ssl3CipherSuite; /* The cipher suites are defined in sslproto.h */ diff --git a/security/nss/lib/ssl/sslcert.c b/security/nss/lib/ssl/sslcert.c index 6cd02e402..1c3ddb0e7 100644 --- a/security/nss/lib/ssl/sslcert.c +++ b/security/nss/lib/ssl/sslcert.c @@ -256,7 +256,8 @@ ssl_PopulateKeyPair(sslServerCert *sc, sslKeyPair *keyPair) /* Get the size of the cert's public key, and remember it. */ sc->serverKeyBits = SECKEY_PublicKeyStrengthInBits(keyPair->pubKey); - if (sc->serverKeyBits == 0) { + if (sc->serverKeyBits == 0 || + (keyType == rsaKey && sc->serverKeyBits > SSL_MAX_RSA_KEY_BITS)) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } diff --git a/security/nss/lib/ssl/sslerr.h b/security/nss/lib/ssl/sslerr.h index b94d0cc62..518a2b887 100644 --- a/security/nss/lib/ssl/sslerr.h +++ b/security/nss/lib/ssl/sslerr.h @@ -262,6 +262,8 @@ typedef enum { SSL_ERROR_TOO_MANY_KEY_UPDATES = (SSL_ERROR_BASE + 171), SSL_ERROR_HANDSHAKE_FAILED = (SSL_ERROR_BASE + 172), SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR = (SSL_ERROR_BASE + 173), + SSL_ERROR_RX_MALFORMED_DTLS_ACK = (SSL_ERROR_BASE + 174), + SSL_ERROR_DH_KEY_TOO_LONG = (SSL_ERROR_BASE + 175), SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */ } SSLErrorCodes; #endif /* NO_SECURITY_ERROR_ENUM */ diff --git a/security/nss/lib/ssl/sslimpl.h b/security/nss/lib/ssl/sslimpl.h index 10d0333d9..a2209e90a 100644 --- a/security/nss/lib/ssl/sslimpl.h +++ b/security/nss/lib/ssl/sslimpl.h @@ -121,6 +121,10 @@ typedef enum { SSLAppOpRead = 0, /* default number of entries in namedGroupPreferences */ #define SSL_NAMED_GROUP_COUNT 31 +/* The maximum DH and RSA bit-length supported. */ +#define SSL_MAX_DH_KEY_BITS 8192 +#define SSL_MAX_RSA_KEY_BITS 8192 + /* Types and names of elliptic curves used in TLS */ typedef enum { ec_type_explicitPrime = 1, /* not supported */ @@ -232,6 +236,7 @@ typedef struct sslOptionsStr { /* If SSL_SetNextProtoNego has been called, then this contains the * list of supported protocols. */ SECItem nextProtoNego; + PRUint16 recordSizeLimit; PRUint32 maxEarlyDataSize; unsigned int useSecurity : 1; @@ -251,7 +256,6 @@ typedef struct sslOptionsStr { unsigned int enableFalseStart : 1; unsigned int cbcRandomIV : 1; unsigned int enableOCSPStapling : 1; - unsigned int enableNPN : 1; unsigned int enableALPN : 1; unsigned int reuseServerECDHEKey : 1; unsigned int enableFallbackSCSV : 1; @@ -261,6 +265,7 @@ typedef struct sslOptionsStr { unsigned int requireDHENamedGroups : 1; unsigned int enable0RttData : 1; unsigned int enableTls13CompatMode : 1; + unsigned int enableDtlsShortHeader : 1; } sslOptions; typedef enum { sslHandshakingUndetermined = 0, @@ -325,9 +330,11 @@ struct sslGatherStr { ** than into buf or inbuf, while in the GS_HEADER state. ** The portion of the SSL record header put here always comes off the wire ** as plaintext, never ciphertext. - ** For SSL3/TLS, the plaintext portion is 5 bytes long. For DTLS it is 13. + ** For SSL3/TLS, the plaintext portion is 5 bytes long. For DTLS it + ** varies based on version and header type. */ unsigned char hdr[13]; + unsigned int hdrLen; /* Buffer for DTLS data read off the wire as a single datagram */ sslBuffer dtlsPacket; @@ -440,7 +447,7 @@ struct sslSessionIDStr { */ SECItem signedCertTimestamps; - /* The NPN/ALPN value negotiated in the original connection. + /* The ALPN value negotiated in the original connection. * Used for TLS 1.3. */ SECItem alpnSelection; @@ -780,9 +787,13 @@ struct ssl3StateStr { #define IS_DTLS(ss) (ss->protocolVariant == ssl_variant_datagram) typedef struct { - SSL3ContentType type; - SSL3ProtocolVersion version; - sslSequenceNumber seq_num; /* DTLS only */ + /* |seqNum| eventually contains the reconstructed sequence number. */ + sslSequenceNumber seqNum; + /* The header of the cipherText. */ + const PRUint8 *hdr; + unsigned int hdrLen; + + /* |buf| is the payload of the ciphertext. */ sslBuffer *buf; } SSL3Ciphertext; @@ -805,7 +816,7 @@ struct ssl3DHParamsStr { }; typedef struct SSLWrappedSymWrappingKeyStr { - PRUint8 wrappedSymmetricWrappingkey[512]; + PRUint8 wrappedSymmetricWrappingkey[SSL_MAX_RSA_KEY_BITS / 8]; CK_MECHANISM_TYPE symWrapMechanism; /* unwrapped symmetric wrapping key uses this mechanism */ CK_MECHANISM_TYPE asymWrapMechanism; @@ -1375,8 +1386,11 @@ SECStatus ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type); /* * input into the SSL3 machinery from the actualy network reading code */ -SECStatus ssl3_HandleRecord( - sslSocket *ss, SSL3Ciphertext *cipher, sslBuffer *out); +SECStatus ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cipher); +SECStatus ssl3_HandleNonApplicationData(sslSocket *ss, SSL3ContentType rType, + DTLSEpoch epoch, + sslSequenceNumber seqNum, + sslBuffer *databuf); SECStatus ssl_RemoveTLSCBCPadding(sslBuffer *plaintext, unsigned int macSize); int ssl3_GatherAppDataRecord(sslSocket *ss, int flags); @@ -1537,8 +1551,8 @@ SECStatus ssl_GetSelfEncryptKeys(sslSocket *ss, unsigned char *keyName, PK11SymKey **encKey, PK11SymKey **macKey); void ssl_ResetSelfEncryptKeys(); -extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char *data, - unsigned int length); +extern SECStatus ssl3_ValidateAppProtocol(const unsigned char *data, + unsigned int length); /* Construct a new NSPR socket for the app to use */ extern PRFileDesc *ssl_NewPRSocket(sslSocket *ss, PRFileDesc *fd); @@ -1636,6 +1650,9 @@ SSLHashType ssl_SignatureSchemeToHashType(SSLSignatureScheme scheme); KeyType ssl_SignatureSchemeToKeyType(SSLSignatureScheme scheme); SECStatus ssl3_SetupCipherSuite(sslSocket *ss, PRBool initHashes); +SECStatus ssl_InsertRecordHeader(const sslSocket *ss, ssl3CipherSpec *cwSpec, + SSL3ContentType contentType, sslBuffer *wrBuf, + PRBool *needsLength); /* Pull in DTLS functions */ #include "dtlscon.h" diff --git a/security/nss/lib/ssl/sslsecur.c b/security/nss/lib/ssl/sslsecur.c index f09ec067c..a1d389214 100644 --- a/security/nss/lib/ssl/sslsecur.c +++ b/security/nss/lib/ssl/sslsecur.c @@ -791,7 +791,7 @@ tls13_CheckKeyUpdate(sslSocket *ss, CipherSpecDirection dir) spec = ss->ssl3.cwSpec; margin = spec->cipherDef->max_records / 4; } - seqNum = spec->seqNum; + seqNum = spec->nextSeqNum; keyUpdate = seqNum > spec->cipherDef->max_records - margin; ssl_ReleaseSpecReadLock(ss); if (!keyUpdate) { @@ -922,21 +922,30 @@ ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags) */ if (!ss->firstHsDone) { PRBool allowEarlySend = PR_FALSE; + PRBool firstClientWrite = PR_FALSE; ssl_Get1stHandshakeLock(ss); - if (ss->opt.enableFalseStart || - (ss->opt.enable0RttData && !ss->sec.isServer)) { + /* The client can sometimes send before the handshake is fully + * complete. In TLS 1.2: false start; in TLS 1.3: 0-RTT. */ + if (!ss->sec.isServer && + (ss->opt.enableFalseStart || ss->opt.enable0RttData)) { ssl_GetSSL3HandshakeLock(ss); - /* The client can sometimes send before the handshake is fully - * complete. In TLS 1.2: false start; in TLS 1.3: 0-RTT. */ zeroRtt = ss->ssl3.hs.zeroRttState == ssl_0rtt_sent || ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted; allowEarlySend = ss->ssl3.hs.canFalseStart || zeroRtt; + firstClientWrite = ss->ssl3.hs.ws == idle_handshake; ssl_ReleaseSSL3HandshakeLock(ss); } if (!allowEarlySend && ss->handshake) { rv = ssl_Do1stHandshake(ss); } + if (firstClientWrite) { + /* Wait until after sending ClientHello and double-check 0-RTT. */ + ssl_GetSSL3HandshakeLock(ss); + zeroRtt = ss->ssl3.hs.zeroRttState == ssl_0rtt_sent || + ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted; + ssl_ReleaseSSL3HandshakeLock(ss); + } ssl_Release1stHandshakeLock(ss); } diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c index e08d5e232..33595ffae 100644 --- a/security/nss/lib/ssl/sslsock.c +++ b/security/nss/lib/ssl/sslsock.c @@ -55,6 +55,7 @@ static const sslSocketOps ssl_secure_ops = { /* SSL. */ static sslOptions ssl_defaults = { .nextProtoNego = { siBuffer, NULL, 0 }, .maxEarlyDataSize = 1 << 16, + .recordSizeLimit = MAX_FRAGMENT_LENGTH + 1, .useSecurity = PR_TRUE, .useSocks = PR_FALSE, .requestCertificate = PR_FALSE, @@ -72,7 +73,6 @@ static sslOptions ssl_defaults = { .enableFalseStart = PR_FALSE, .cbcRandomIV = PR_TRUE, .enableOCSPStapling = PR_FALSE, - .enableNPN = PR_FALSE, .enableALPN = PR_TRUE, .reuseServerECDHEKey = PR_TRUE, .enableFallbackSCSV = PR_FALSE, @@ -81,7 +81,8 @@ static sslOptions ssl_defaults = { .enableSignedCertTimestamps = PR_FALSE, .requireDHENamedGroups = PR_FALSE, .enable0RttData = PR_FALSE, - .enableTls13CompatMode = PR_FALSE + .enableTls13CompatMode = PR_FALSE, + .enableDtlsShortHeader = PR_FALSE }; /* @@ -803,10 +804,23 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRIntn val) ss->opt.enable0RttData = val; break; + case SSL_RECORD_SIZE_LIMIT: + if (val < 64 || val > (MAX_FRAGMENT_LENGTH + 1)) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + rv = SECFailure; + } else { + ss->opt.recordSizeLimit = val; + } + break; + case SSL_ENABLE_TLS13_COMPAT_MODE: ss->opt.enableTls13CompatMode = val; break; + case SSL_ENABLE_DTLS_SHORT_HEADER: + ss->opt.enableDtlsShortHeader = val; + break; + default: PORT_SetError(SEC_ERROR_INVALID_ARGS); rv = SECFailure; @@ -914,7 +928,7 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRIntn *pVal) val = ss->opt.enableOCSPStapling; break; case SSL_ENABLE_NPN: - val = ss->opt.enableNPN; + val = PR_FALSE; break; case SSL_ENABLE_ALPN: val = ss->opt.enableALPN; @@ -940,9 +954,15 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRIntn *pVal) case SSL_ENABLE_0RTT_DATA: val = ss->opt.enable0RttData; break; + case SSL_RECORD_SIZE_LIMIT: + val = ss->opt.recordSizeLimit; + break; case SSL_ENABLE_TLS13_COMPAT_MODE: val = ss->opt.enableTls13CompatMode; break; + case SSL_ENABLE_DTLS_SHORT_HEADER: + val = ss->opt.enableDtlsShortHeader; + break; default: PORT_SetError(SEC_ERROR_INVALID_ARGS); rv = SECFailure; @@ -1037,7 +1057,7 @@ SSL_OptionGetDefault(PRInt32 which, PRIntn *pVal) val = ssl_defaults.enableOCSPStapling; break; case SSL_ENABLE_NPN: - val = ssl_defaults.enableNPN; + val = PR_FALSE; break; case SSL_ENABLE_ALPN: val = ssl_defaults.enableALPN; @@ -1060,9 +1080,15 @@ SSL_OptionGetDefault(PRInt32 which, PRIntn *pVal) case SSL_ENABLE_0RTT_DATA: val = ssl_defaults.enable0RttData; break; + case SSL_RECORD_SIZE_LIMIT: + val = ssl_defaults.recordSizeLimit; + break; case SSL_ENABLE_TLS13_COMPAT_MODE: val = ssl_defaults.enableTls13CompatMode; break; + case SSL_ENABLE_DTLS_SHORT_HEADER: + val = ssl_defaults.enableDtlsShortHeader; + break; default: PORT_SetError(SEC_ERROR_INVALID_ARGS); rv = SECFailure; @@ -1242,10 +1268,22 @@ SSL_OptionSetDefault(PRInt32 which, PRIntn val) ssl_defaults.enable0RttData = val; break; + case SSL_RECORD_SIZE_LIMIT: + if (val < 64 || val > (MAX_FRAGMENT_LENGTH + 1)) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + ssl_defaults.recordSizeLimit = val; + break; + case SSL_ENABLE_TLS13_COMPAT_MODE: ssl_defaults.enableTls13CompatMode = val; break; + case SSL_ENABLE_DTLS_SHORT_HEADER: + ssl_defaults.enableDtlsShortHeader = val; + break; + default: PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; @@ -1895,10 +1933,7 @@ DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd) } /* SSL_SetNextProtoCallback is used to select an application protocol - * for ALPN and NPN. For ALPN, this runs on the server; for NPN it - * runs on the client. */ -/* Note: The ALPN version doesn't allow for the use of a default, setting a - * status of SSL_NEXT_PROTO_NO_OVERLAP is treated as a failure. */ + * for ALPN. */ SECStatus SSL_SetNextProtoCallback(PRFileDesc *fd, SSLNextProtoCallback callback, void *arg) @@ -1919,7 +1954,7 @@ SSL_SetNextProtoCallback(PRFileDesc *fd, SSLNextProtoCallback callback, return SECSuccess; } -/* ssl_NextProtoNegoCallback is set as an ALPN/NPN callback when +/* ssl_NextProtoNegoCallback is set as an ALPN callback when * SSL_SetNextProtoNego is used. */ static SECStatus @@ -1929,7 +1964,6 @@ ssl_NextProtoNegoCallback(void *arg, PRFileDesc *fd, unsigned int protoMaxLen) { unsigned int i, j; - const unsigned char *result; sslSocket *ss = ssl_FindSocket(fd); if (!ss) { @@ -1937,37 +1971,29 @@ ssl_NextProtoNegoCallback(void *arg, PRFileDesc *fd, SSL_GETPID(), fd)); return SECFailure; } + PORT_Assert(protoMaxLen <= 255); + if (protoMaxLen > 255) { + PORT_SetError(SEC_ERROR_OUTPUT_LEN); + return SECFailure; + } - /* For each protocol in server preference, see if we support it. */ - for (i = 0; i < protos_len;) { - for (j = 0; j < ss->opt.nextProtoNego.len;) { + /* For each protocol in client preference, see if we support it. */ + for (j = 0; j < ss->opt.nextProtoNego.len;) { + for (i = 0; i < protos_len;) { if (protos[i] == ss->opt.nextProtoNego.data[j] && PORT_Memcmp(&protos[i + 1], &ss->opt.nextProtoNego.data[j + 1], protos[i]) == 0) { /* We found a match. */ - ss->xtnData.nextProtoState = SSL_NEXT_PROTO_NEGOTIATED; - result = &protos[i]; - goto found; + const unsigned char *result = &protos[i]; + memcpy(protoOut, result + 1, result[0]); + *protoOutLen = result[0]; + return SECSuccess; } - j += 1 + (unsigned int)ss->opt.nextProtoNego.data[j]; + i += 1 + (unsigned int)protos[i]; } - i += 1 + (unsigned int)protos[i]; + j += 1 + (unsigned int)ss->opt.nextProtoNego.data[j]; } - /* The other side supports the extension, and either doesn't have any - * protocols configured, or none of its options match ours. In this case we - * request our favoured protocol. */ - /* This will be treated as a failure for ALPN. */ - ss->xtnData.nextProtoState = SSL_NEXT_PROTO_NO_OVERLAP; - result = ss->opt.nextProtoNego.data; - -found: - if (protoMaxLen < result[0]) { - PORT_SetError(SEC_ERROR_OUTPUT_LEN); - return SECFailure; - } - memcpy(protoOut, result + 1, result[0]); - *protoOutLen = result[0]; return SECSuccess; } @@ -1976,8 +2002,6 @@ SSL_SetNextProtoNego(PRFileDesc *fd, const unsigned char *data, unsigned int length) { sslSocket *ss; - SECStatus rv; - SECItem dataItem = { siBuffer, (unsigned char *)data, length }; ss = ssl_FindSocket(fd); if (!ss) { @@ -1986,17 +2010,22 @@ SSL_SetNextProtoNego(PRFileDesc *fd, const unsigned char *data, return SECFailure; } - if (ssl3_ValidateNextProtoNego(data, length) != SECSuccess) + if (ssl3_ValidateAppProtocol(data, length) != SECSuccess) { return SECFailure; + } + /* NPN required that the client's fallback protocol is first in the + * list. However, ALPN sends protocols in preference order. So move the + * first protocol to the end of the list. */ ssl_GetSSL3HandshakeLock(ss); SECITEM_FreeItem(&ss->opt.nextProtoNego, PR_FALSE); - rv = SECITEM_CopyItem(NULL, &ss->opt.nextProtoNego, &dataItem); + SECITEM_AllocItem(NULL, &ss->opt.nextProtoNego, length); + size_t firstLen = data[0] + 1; + /* firstLen <= length is ensured by ssl3_ValidateAppProtocol. */ + PORT_Memcpy(ss->opt.nextProtoNego.data + (length - firstLen), data, firstLen); + PORT_Memcpy(ss->opt.nextProtoNego.data, data + firstLen, length - firstLen); ssl_ReleaseSSL3HandshakeLock(ss); - if (rv != SECSuccess) - return rv; - return SSL_SetNextProtoCallback(fd, ssl_NextProtoNegoCallback, NULL); } @@ -3034,26 +3063,27 @@ ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *p_out_flags) } else { /* handshaking as server */ new_flags |= PR_POLL_READ; } - } else + } else if (ss->lastWriteBlocked) { /* First handshake is in progress */ - if (ss->lastWriteBlocked) { if (new_flags & PR_POLL_READ) { /* The caller is waiting for data to be received, ** but the initial handshake is blocked on write, or the ** client's first handshake record has not been written. ** The code should select on write, not read. */ - new_flags ^= PR_POLL_READ; /* don't select on read. */ + new_flags &= ~PR_POLL_READ; /* don't select on read. */ new_flags |= PR_POLL_WRITE; /* do select on write. */ } } else if (new_flags & PR_POLL_WRITE) { /* The caller is trying to write, but the handshake is ** blocked waiting for data to read, and the first ** handshake has been sent. So do NOT to poll on write - ** unless we did false start. + ** unless we did false start or we are doing 0-RTT. */ - if (!ss->ssl3.hs.canFalseStart) { - new_flags ^= PR_POLL_WRITE; /* don't select on write. */ + if (!(ss->ssl3.hs.canFalseStart || + ss->ssl3.hs.zeroRttState == ssl_0rtt_sent || + ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted)) { + new_flags &= ~PR_POLL_WRITE; /* don't select on write. */ } new_flags |= PR_POLL_READ; /* do select on read. */ } @@ -3093,6 +3123,9 @@ ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *p_out_flags) } } + SSL_TRC(20, ("%d: SSL[%d]: ssl_Poll flags %x -> %x", + SSL_GETPID(), fd, how_flags, new_flags)); + if (new_flags && (fd->lower->methods->poll != NULL)) { PRInt16 lower_out_flags = 0; PRInt16 lower_new_flags; diff --git a/security/nss/lib/ssl/sslspec.c b/security/nss/lib/ssl/sslspec.c index 26c3eb546..7833eeab6 100644 --- a/security/nss/lib/ssl/sslspec.c +++ b/security/nss/lib/ssl/sslspec.c @@ -143,6 +143,7 @@ ssl_CreateCipherSpec(sslSocket *ss, CipherSpecDirection direction) spec->refCt = 1; spec->version = ss->version; spec->direction = direction; + spec->recordSizeLimit = MAX_FRAGMENT_LENGTH; SSL_TRC(10, ("%d: SSL[%d]: new %s spec %d ct=%d", SSL_GETPID(), ss->fd, SPEC_DIR(spec), spec, spec->refCt)); diff --git a/security/nss/lib/ssl/sslspec.h b/security/nss/lib/ssl/sslspec.h index 729ac1006..b25601755 100644 --- a/security/nss/lib/ssl/sslspec.h +++ b/security/nss/lib/ssl/sslspec.h @@ -162,12 +162,18 @@ struct ssl3CipherSpecStr { DTLSEpoch epoch; const char *phase; - sslSequenceNumber seqNum; + + /* The next sequence number to be sent or received. */ + sslSequenceNumber nextSeqNum; DTLSRecvdRecords recvdRecords; /* The number of 0-RTT bytes that can be sent or received in TLS 1.3. This * will be zero for everything but 0-RTT. */ PRUint32 earlyDataRemaining; + /* The maximum plaintext length. This differs from the configured or + * negotiated value for TLS 1.3; it is reduced by one to account for the + * content type octet. */ + PRUint16 recordSizeLimit; }; typedef void (*sslCipherSpecChangedFunc)(void *arg, diff --git a/security/nss/lib/ssl/sslt.h b/security/nss/lib/ssl/sslt.h index e2b80fb43..bb1bec7a3 100644 --- a/security/nss/lib/ssl/sslt.h +++ b/security/nss/lib/ssl/sslt.h @@ -432,6 +432,7 @@ typedef enum { ssl_signed_cert_timestamp_xtn = 18, ssl_padding_xtn = 21, ssl_extended_master_secret_xtn = 23, + ssl_record_size_limit_xtn = 28, ssl_session_ticket_xtn = 35, /* 40 was used in draft versions of TLS 1.3; it is now reserved. */ ssl_tls13_pre_shared_key_xtn = 41, @@ -454,7 +455,7 @@ typedef enum { /* SSL_MAX_EXTENSIONS includes the maximum number of extensions that are * supported for any single message type. That is, a ClientHello; ServerHello * and TLS 1.3 NewSessionTicket and HelloRetryRequest extensions have fewer. */ -#define SSL_MAX_EXTENSIONS 20 +#define SSL_MAX_EXTENSIONS 21 /* Deprecated */ typedef enum { diff --git a/security/nss/lib/ssl/tls13con.c b/security/nss/lib/ssl/tls13con.c index c06acc83a..4d9170fb0 100644 --- a/security/nss/lib/ssl/tls13con.c +++ b/security/nss/lib/ssl/tls13con.c @@ -792,7 +792,7 @@ tls13_HandleKeyUpdate(sslSocket *ss, PRUint8 *b, unsigned int length) /* Only send an update if we have sent with the current spec. This * prevents us from being forced to crank forward pointlessly. */ ssl_GetSpecReadLock(ss); - sendUpdate = ss->ssl3.cwSpec->seqNum > 0; + sendUpdate = ss->ssl3.cwSpec->nextSeqNum > 0; ssl_ReleaseSpecReadLock(ss); } else { sendUpdate = PR_TRUE; @@ -1620,7 +1620,7 @@ tls13_HandleClientHelloPart2(sslSocket *ss, ssl_GetSpecWriteLock(ss); /* Increase the write sequence number. The read sequence number * will be reset after this to early data or handshake. */ - ss->ssl3.cwSpec->seqNum = 1; + ss->ssl3.cwSpec->nextSeqNum = 1; ssl_ReleaseSpecWriteLock(ss); } @@ -2007,7 +2007,7 @@ tls13_SendHelloRetryRequest(sslSocket *ss, /* We depend on this being exactly one record and one message. */ PORT_Assert(!IS_DTLS(ss) || (ss->ssl3.hs.sendMessageSeq == 1 && - ss->ssl3.cwSpec->seqNum == 1)); + ss->ssl3.cwSpec->nextSeqNum == 1)); ssl_ReleaseXmitBufLock(ss); ss->ssl3.hs.helloRetry = PR_TRUE; @@ -2209,6 +2209,8 @@ tls13_HandleHelloRetryRequest(sslSocket *ss, const PRUint8 *savedMsg, } else { PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_none); } + /* Set the spec version, because we want to send CH now with 0303 */ + tls13_SetSpecRecordVersion(ss, ss->ssl3.cwSpec); /* Extensions must contain more than just supported_versions. This will * ensure that a HelloRetryRequest isn't a no-op: we must have at least two @@ -2248,6 +2250,7 @@ tls13_HandleHelloRetryRequest(sslSocket *ss, const PRUint8 *savedMsg, goto loser; } } + rv = ssl3_SendClientHello(ss, client_hello_retry); if (rv != SECSuccess) { goto loser; @@ -3251,6 +3254,17 @@ tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) } tls13_SetSpecRecordVersion(ss, spec); + + /* The record size limit is reduced by one so that the remainder of the + * record handling code can use the same checks for all versions. */ + if (ssl3_ExtensionNegotiated(ss, ssl_record_size_limit_xtn)) { + spec->recordSizeLimit = ((spec->direction == CipherSpecRead) + ? ss->opt.recordSizeLimit + : ss->xtnData.recordSizeLimit) - + 1; + } else { + spec->recordSizeLimit = MAX_FRAGMENT_LENGTH; + } return SECSuccess; } @@ -3316,7 +3330,7 @@ tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch, return SECFailure; } spec->epoch = epoch; - spec->seqNum = 0; + spec->nextSeqNum = 0; if (IS_DTLS(ss)) { dtls_InitRecvdRecords(&spec->recvdRecords); } @@ -3536,14 +3550,15 @@ tls13_AESGCM(ssl3KeyMaterial *keys, CK_GCM_PARAMS gcmParams; unsigned char nonce[12]; + PORT_Assert(additionalDataLen > 8); memset(&gcmParams, 0, sizeof(gcmParams)); gcmParams.pIv = nonce; gcmParams.ulIvLen = sizeof(nonce); - gcmParams.pAAD = NULL; - gcmParams.ulAADLen = 0; + gcmParams.pAAD = (PRUint8 *)(additionalData + 8); + gcmParams.ulAADLen = additionalDataLen - 8; gcmParams.ulTagBits = 128; /* GCM measures tag length in bits. */ - tls13_WriteNonce(keys, additionalData, additionalDataLen, + tls13_WriteNonce(keys, additionalData, 8, nonce, sizeof(nonce)); return tls13_AEAD(keys, doDecrypt, out, outlen, maxout, in, inlen, CKM_AES_GCM, @@ -3560,14 +3575,15 @@ tls13_ChaCha20Poly1305(ssl3KeyMaterial *keys, PRBool doDecrypt, CK_NSS_AEAD_PARAMS aeadParams; unsigned char nonce[12]; + PORT_Assert(additionalDataLen > 8); memset(&aeadParams, 0, sizeof(aeadParams)); aeadParams.pNonce = nonce; aeadParams.ulNonceLen = sizeof(nonce); - aeadParams.pAAD = NULL; /* No AAD in TLS 1.3. */ - aeadParams.ulAADLen = 0; + aeadParams.pAAD = (PRUint8 *)(additionalData + 8); + aeadParams.ulAADLen = additionalDataLen - 8; aeadParams.ulTagLen = 16; /* The Poly1305 tag is 16 octets. */ - tls13_WriteNonce(keys, additionalData, additionalDataLen, + tls13_WriteNonce(keys, additionalData, 8, nonce, sizeof(nonce)); return tls13_AEAD(keys, doDecrypt, out, outlen, maxout, in, inlen, CKM_NSS_CHACHA20_POLY1305, @@ -3579,7 +3595,7 @@ tls13_HandleEncryptedExtensions(sslSocket *ss, PRUint8 *b, PRUint32 length) { SECStatus rv; PRUint32 innerLength; - SECItem oldNpn = { siBuffer, NULL, 0 }; + SECItem oldAlpn = { siBuffer, NULL, 0 }; PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); @@ -3603,11 +3619,11 @@ tls13_HandleEncryptedExtensions(sslSocket *ss, PRUint8 *b, PRUint32 length) return SECFailure; } - /* If we are doing 0-RTT, then we already have an NPN value. Stash + /* If we are doing 0-RTT, then we already have an ALPN value. Stash * it for comparison. */ if (ss->ssl3.hs.zeroRttState == ssl_0rtt_sent && ss->xtnData.nextProtoState == SSL_NEXT_PROTO_EARLY_VALUE) { - oldNpn = ss->xtnData.nextProto; + oldAlpn = ss->xtnData.nextProto; ss->xtnData.nextProto.data = NULL; ss->xtnData.nextProtoState = SSL_NEXT_PROTO_NO_SUPPORT; } @@ -3627,8 +3643,8 @@ tls13_HandleEncryptedExtensions(sslSocket *ss, PRUint8 *b, PRUint32 length) ss->ssl3.hs.zeroRttState = ssl_0rtt_accepted; /* Check that the server negotiated the same ALPN (if any). */ - if (SECITEM_CompareItem(&oldNpn, &ss->xtnData.nextProto)) { - SECITEM_FreeItem(&oldNpn, PR_FALSE); + if (SECITEM_CompareItem(&oldAlpn, &ss->xtnData.nextProto)) { + SECITEM_FreeItem(&oldAlpn, PR_FALSE); FATAL_ERROR(ss, SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID, illegal_parameter); return SECFailure; @@ -3650,7 +3666,7 @@ tls13_HandleEncryptedExtensions(sslSocket *ss, PRUint8 *b, PRUint32 length) ss->ssl3.hs.zeroRttState == ssl_0rtt_ignored)); } - SECITEM_FreeItem(&oldNpn, PR_FALSE); + SECITEM_FreeItem(&oldAlpn, PR_FALSE); if (ss->ssl3.hs.kea_def->authKeyType == ssl_auth_psk) { TLS13_SET_HS_STATE(ss, wait_finished); } else { @@ -3815,13 +3831,14 @@ tls13_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length) rv = ssl_ConsumeSignatureScheme(ss, &b, &length, &sigScheme); if (rv != SECSuccess) { - PORT_SetError(SSL_ERROR_RX_MALFORMED_CERT_VERIFY); + FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_VERIFY, illegal_parameter); return SECFailure; } rv = ssl_CheckSignatureSchemeConsistency(ss, sigScheme, ss->sec.peerCert); if (rv != SECSuccess) { /* Error set already */ + FATAL_ERROR(ss, PORT_GetError(), illegal_parameter); return SECFailure; } hashAlg = ssl_SignatureSchemeToHashType(sigScheme); @@ -4740,7 +4757,8 @@ static const struct { { ssl_tls13_cookie_xtn, _M2(client_hello, hello_retry_request) }, { ssl_tls13_certificate_authorities_xtn, _M1(certificate_request) }, { ssl_tls13_supported_versions_xtn, _M3(client_hello, server_hello, - hello_retry_request) } + hello_retry_request) }, + { ssl_record_size_limit_xtn, _M2(client_hello, encrypted_extensions) } }; tls13ExtensionStatus @@ -4780,19 +4798,20 @@ tls13_ExtensionStatus(PRUint16 extension, SSLHandshakeType message) #undef _M2 #undef _M3 -/* TLS 1.3 doesn't actually have additional data but the aead function - * signature overloads additional data to carry the record sequence - * number and that's what we put here. The TLS 1.3 AEAD functions - * just use this input as the sequence number and not as additional - * data. */ +/* We cheat a bit on additional data because the AEAD interface + * which doesn't have room for the record number. The AAD we + * format is serialized record number followed by the true AD + * (i.e., the record header) plus the serialized record number. */ static SECStatus -tls13_FormatAdditionalData(sslSocket *ss, PRUint8 *aad, unsigned int length, - DTLSEpoch epoch, sslSequenceNumber seqNum) +tls13_FormatAdditionalData( + sslSocket *ss, + const PRUint8 *header, unsigned int headerLen, + DTLSEpoch epoch, sslSequenceNumber seqNum, + PRUint8 *aad, unsigned int *aadLength, unsigned int maxLength) { SECStatus rv; - sslBuffer buf = SSL_BUFFER_FIXED(aad, length); + sslBuffer buf = SSL_BUFFER_FIXED(aad, maxLength); - PORT_Assert(length == 8); if (IS_DTLS(ss)) { rv = sslBuffer_AppendNumber(&buf, epoch, 2); if (rv != SECSuccess) { @@ -4803,6 +4822,14 @@ tls13_FormatAdditionalData(sslSocket *ss, PRUint8 *aad, unsigned int length, if (rv != SECSuccess) { return SECFailure; } + + rv = sslBuffer_Append(&buf, header, headerLen); + if (rv != SECSuccess) { + return SECFailure; + } + + *aadLength = buf.len; + return SECSuccess; } @@ -4843,43 +4870,68 @@ tls13_ProtectRecord(sslSocket *ss, PORT_Assert(cwSpec->direction == CipherSpecWrite); SSL_TRC(3, ("%d: TLS13[%d]: spec=%d epoch=%d (%s) protect 0x%0llx len=%u", SSL_GETPID(), ss->fd, cwSpec, cwSpec->epoch, cwSpec->phase, - cwSpec->seqNum, contentLen)); + cwSpec->nextSeqNum, contentLen)); - if (contentLen + 1 + tagLen > wrBuf->space) { + if (contentLen + 1 + tagLen > SSL_BUFFER_SPACE(wrBuf)) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } /* Copy the data into the wrBuf. We're going to encrypt in-place * in the AEAD branch anyway */ - PORT_Memcpy(wrBuf->buf, pIn, contentLen); + PORT_Memcpy(SSL_BUFFER_NEXT(wrBuf), pIn, contentLen); if (cipher_def->calg == ssl_calg_null) { /* Shortcut for plaintext */ - wrBuf->len = contentLen; + rv = sslBuffer_Skip(wrBuf, contentLen, NULL); + PORT_Assert(rv == SECSuccess); } else { - PRUint8 aad[8]; + PRUint8 hdr[13]; + sslBuffer buf = SSL_BUFFER_FIXED(hdr, sizeof(hdr)); + PRBool needsLength; + PRUint8 aad[21]; + unsigned int aadLen; + int len; + PORT_Assert(cipher_def->type == type_aead); /* Add the content type at the end. */ - wrBuf->buf[contentLen] = type; + *(SSL_BUFFER_NEXT(wrBuf) + contentLen) = type; - rv = tls13_FormatAdditionalData(ss, aad, sizeof(aad), cwSpec->epoch, - cwSpec->seqNum); + /* Create the header (ugly that we have to do it twice). */ + rv = ssl_InsertRecordHeader(ss, cwSpec, content_application_data, + &buf, &needsLength); + if (rv != SECSuccess) { + return SECFailure; + } + if (needsLength) { + rv = sslBuffer_AppendNumber(&buf, contentLen + 1 + + cwSpec->cipherDef->tag_size, + 2); + if (rv != SECSuccess) { + return SECFailure; + } + } + rv = tls13_FormatAdditionalData(ss, SSL_BUFFER_BASE(&buf), SSL_BUFFER_LEN(&buf), + cwSpec->epoch, cwSpec->nextSeqNum, + aad, &aadLen, sizeof(aad)); if (rv != SECSuccess) { return SECFailure; } rv = cwSpec->aead(&cwSpec->keyMaterial, - PR_FALSE, /* do encrypt */ - wrBuf->buf, /* output */ - (int *)&wrBuf->len, /* out len */ - wrBuf->space, /* max out */ - wrBuf->buf, contentLen + 1, /* input */ - aad, sizeof(aad)); + PR_FALSE, /* do encrypt */ + SSL_BUFFER_NEXT(wrBuf), /* output */ + &len, /* out len */ + SSL_BUFFER_SPACE(wrBuf), /* max out */ + SSL_BUFFER_NEXT(wrBuf), /* input */ + contentLen + 1, /* input len */ + aad, aadLen); if (rv != SECSuccess) { PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); return SECFailure; } + rv = sslBuffer_Skip(wrBuf, len, NULL); + PORT_Assert(rv == SECSuccess); } return SECSuccess; @@ -4897,25 +4949,22 @@ tls13_ProtectRecord(sslSocket *ss, SECStatus tls13_UnprotectRecord(sslSocket *ss, ssl3CipherSpec *spec, - SSL3Ciphertext *cText, sslBuffer *plaintext, + SSL3Ciphertext *cText, + sslBuffer *plaintext, + SSL3ContentType *innerType, SSL3AlertDescription *alert) { const ssl3BulkCipherDef *cipher_def = spec->cipherDef; - sslSequenceNumber seqNum; - PRUint8 aad[8]; + PRUint8 aad[21]; + unsigned int aadLen; SECStatus rv; *alert = bad_record_mac; /* Default alert for most issues. */ PORT_Assert(spec->direction == CipherSpecRead); - if (IS_DTLS(ss)) { - seqNum = cText->seq_num & RECORD_SEQ_MASK; - } else { - seqNum = spec->seqNum; - } SSL_TRC(3, ("%d: TLS13[%d]: spec=%d epoch=%d (%s) unprotect 0x%0llx len=%u", - SSL_GETPID(), ss->fd, spec, spec->epoch, spec->phase, seqNum, - cText->buf->len)); + SSL_GETPID(), ss->fd, spec, spec->epoch, spec->phase, + cText->seqNum, cText->buf->len)); /* We can perform this test in variable time because the record's total * length and the ciphersuite are both public knowledge. */ @@ -4927,28 +4976,38 @@ tls13_UnprotectRecord(sslSocket *ss, return SECFailure; } - /* Verify that the content type is right, even though we overwrite it. */ - if (cText->type != content_application_data) { + /* Verify that the content type is right, even though we overwrite it. + * Also allow the DTLS short header in TLS 1.3. */ + if (!(cText->hdr[0] == content_application_data || + (IS_DTLS(ss) && + ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 && + (cText->hdr[0] & 0xe0) == 0x20))) { SSL_TRC(3, - ("%d: TLS13[%d]: record has invalid exterior content type=%d", - SSL_GETPID(), ss->fd, cText->type)); + ("%d: TLS13[%d]: record has invalid exterior type=%2.2x", + SSL_GETPID(), ss->fd, cText->hdr[0])); /* Do we need a better error here? */ PORT_SetError(SSL_ERROR_BAD_MAC_READ); return SECFailure; } - /* Check the version number in the record. */ - if (cText->version != spec->recordVersion) { - /* Do we need a better error here? */ - SSL_TRC(3, - ("%d: TLS13[%d]: record has bogus version", - SSL_GETPID(), ss->fd)); - return SECFailure; + /* Check the version number in the record. Stream only. */ + if (!IS_DTLS(ss)) { + SSL3ProtocolVersion version = + ((SSL3ProtocolVersion)cText->hdr[1] << 8) | + (SSL3ProtocolVersion)cText->hdr[2]; + if (version != spec->recordVersion) { + /* Do we need a better error here? */ + SSL_TRC(3, ("%d: TLS13[%d]: record has bogus version", + SSL_GETPID(), ss->fd)); + return SECFailure; + } } /* Decrypt */ PORT_Assert(cipher_def->type == type_aead); - rv = tls13_FormatAdditionalData(ss, aad, sizeof(aad), spec->epoch, seqNum); + rv = tls13_FormatAdditionalData(ss, cText->hdr, cText->hdrLen, + spec->epoch, cText->seqNum, + aad, &aadLen, sizeof(aad)); if (rv != SECSuccess) { return SECFailure; } @@ -4959,7 +5018,7 @@ tls13_UnprotectRecord(sslSocket *ss, plaintext->space, /* maxout */ cText->buf->buf, /* in */ cText->buf->len, /* inlen */ - aad, sizeof(aad)); + aad, aadLen); if (rv != SECSuccess) { SSL_TRC(3, ("%d: TLS13[%d]: record has bogus MAC", @@ -4968,6 +5027,16 @@ tls13_UnprotectRecord(sslSocket *ss, return SECFailure; } + /* There is a similar test in ssl3_HandleRecord, but this test is needed to + * account for padding. It's safe to do this here (including the alert), + * because it only confirms that the record exceeded the size limit, which + * is apparent from the size of the ciphertext. */ + if (plaintext->len > spec->recordSizeLimit + 1) { + SSL3_SendAlert(ss, alert_fatal, record_overflow); + PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG); + return SECFailure; + } + /* The record is right-padded with 0s, followed by the true * content type, so read from the right until we receive a * nonzero byte. */ @@ -4977,9 +5046,7 @@ tls13_UnprotectRecord(sslSocket *ss, /* Bogus padding. */ if (plaintext->len < 1) { - SSL_TRC(3, - ("%d: TLS13[%d]: empty record", - SSL_GETPID(), ss->fd, cText->type)); + SSL_TRC(3, ("%d: TLS13[%d]: empty record", SSL_GETPID(), ss->fd)); /* It's safe to report this specifically because it happened * after the MAC has been verified. */ PORT_SetError(SSL_ERROR_BAD_BLOCK_PADDING); @@ -4987,12 +5054,12 @@ tls13_UnprotectRecord(sslSocket *ss, } /* Record the type. */ - cText->type = plaintext->buf[plaintext->len - 1]; + *innerType = (SSL3ContentType)plaintext->buf[plaintext->len - 1]; --plaintext->len; /* Check that we haven't received too much 0-RTT data. */ if (spec->epoch == TrafficKeyEarlyApplicationData && - cText->type == content_application_data) { + *innerType == content_application_data) { if (plaintext->len > spec->earlyDataRemaining) { *alert = unexpected_message; PORT_SetError(SSL_ERROR_TOO_MUCH_EARLY_DATA); @@ -5002,9 +5069,8 @@ tls13_UnprotectRecord(sslSocket *ss, } SSL_TRC(10, - ("%d: TLS13[%d]: %s received record of length=%d type=%d", - SSL_GETPID(), ss->fd, SSL_ROLE(ss), - plaintext->len, cText->type)); + ("%d: TLS13[%d]: %s received record of length=%d, type=%d", + SSL_GETPID(), ss->fd, SSL_ROLE(ss), plaintext->len, *innerType)); return SECSuccess; } @@ -5227,6 +5293,58 @@ tls13_EncodeDraftVersion(SSL3ProtocolVersion version) return (PRUint16)version; } +SECStatus +tls13_ClientReadSupportedVersion(sslSocket *ss) +{ + PRUint32 temp; + SSL3ProtocolVersion v; + TLSExtension *versionExtension; + SECItem it; + SECStatus rv; + + /* Update the version based on the extension, as necessary. */ + versionExtension = ssl3_FindExtension(ss, ssl_tls13_supported_versions_xtn); + if (!versionExtension) { + return SECSuccess; + } + + /* Struct copy so we don't damage the extension. */ + it = versionExtension->data; + + rv = ssl3_ConsumeHandshakeNumber(ss, &temp, 2, &it.data, &it.len); + if (rv != SECSuccess) { + return SECFailure; + } + if (it.len) { + FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_SERVER_HELLO, illegal_parameter); + return SECFailure; + } + v = (SSL3ProtocolVersion)temp; + + /* You cannot negotiate < TLS 1.3 with supported_versions. */ + if (v < SSL_LIBRARY_VERSION_TLS_1_3) { + FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_SERVER_HELLO, illegal_parameter); + return SECFailure; + } + +#ifdef TLS_1_3_DRAFT_VERSION + if (temp == SSL_LIBRARY_VERSION_TLS_1_3) { + FATAL_ERROR(ss, SSL_ERROR_UNSUPPORTED_VERSION, protocol_version); + return SECFailure; + } + if (temp == tls13_EncodeDraftVersion(SSL_LIBRARY_VERSION_TLS_1_3)) { + v = SSL_LIBRARY_VERSION_TLS_1_3; + } else { + v = (SSL3ProtocolVersion)temp; + } +#else + v = (SSL3ProtocolVersion)temp; +#endif + + ss->version = v; + return SECSuccess; +} + /* Pick the highest version we support that is also advertised. */ SECStatus tls13_NegotiateVersion(sslSocket *ss, const TLSExtension *supportedVersions) diff --git a/security/nss/lib/ssl/tls13con.h b/security/nss/lib/ssl/tls13con.h index 1aaffb651..f35b20023 100644 --- a/security/nss/lib/ssl/tls13con.h +++ b/security/nss/lib/ssl/tls13con.h @@ -28,6 +28,7 @@ typedef enum { SECStatus tls13_UnprotectRecord( sslSocket *ss, ssl3CipherSpec *spec, SSL3Ciphertext *cText, sslBuffer *plaintext, + SSL3ContentType *innerType, SSL3AlertDescription *alert); #if defined(WIN32) @@ -101,6 +102,7 @@ PRInt32 tls13_Read0RttData(sslSocket *ss, void *buf, PRInt32 len); SECStatus tls13_HandleEarlyApplicationData(sslSocket *ss, sslBuffer *origBuf); PRBool tls13_ClientAllow0Rtt(const sslSocket *ss, const sslSessionID *sid); PRUint16 tls13_EncodeDraftVersion(SSL3ProtocolVersion version); +SECStatus tls13_ClientReadSupportedVersion(sslSocket *ss); SECStatus tls13_NegotiateVersion(sslSocket *ss, const TLSExtension *supported_versions); diff --git a/security/nss/lib/ssl/tls13exthandle.c b/security/nss/lib/ssl/tls13exthandle.c index 899f23827..1ab8a8e59 100644 --- a/security/nss/lib/ssl/tls13exthandle.c +++ b/security/nss/lib/ssl/tls13exthandle.c @@ -860,12 +860,12 @@ tls13_ServerHandleCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData, } if (xtnData->cookie.len == 0) { - PORT_SetError(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); + PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); return SECFailure; } if (data->len) { - PORT_SetError(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); + PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); return SECFailure; } diff --git a/security/nss/lib/util/nssutil.def b/security/nss/lib/util/nssutil.def index 936455f6e..26e438ba6 100644 --- a/security/nss/lib/util/nssutil.def +++ b/security/nss/lib/util/nssutil.def @@ -322,4 +322,9 @@ _NSSUTIL_UTF8ToWide;- _NSSUTIL_Access;- ;- local: ;- *; -;-}; +;+NSSUTIL_3.38 { # NSS Utilities 3.38 release +;+ global: +SECITEM_MakeItem; +;+ local: +;+ *; +;+}; diff --git a/security/nss/lib/util/nssutil.h b/security/nss/lib/util/nssutil.h index b65d4a0c9..2749abaa1 100644 --- a/security/nss/lib/util/nssutil.h +++ b/security/nss/lib/util/nssutil.h @@ -19,10 +19,10 @@ * The format of the version string should be * "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]" */ -#define NSSUTIL_VERSION "3.36.4" +#define NSSUTIL_VERSION "3.38" #define NSSUTIL_VMAJOR 3 -#define NSSUTIL_VMINOR 36 -#define NSSUTIL_VPATCH 4 +#define NSSUTIL_VMINOR 38 +#define NSSUTIL_VPATCH 0 #define NSSUTIL_VBUILD 0 #define NSSUTIL_BETA PR_FALSE diff --git a/security/nss/lib/util/pkcs11t.h b/security/nss/lib/util/pkcs11t.h index c945f314e..01ff8a572 100644 --- a/security/nss/lib/util/pkcs11t.h +++ b/security/nss/lib/util/pkcs11t.h @@ -466,6 +466,8 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE; #define CKA_EXPONENT_1 0x00000126 #define CKA_EXPONENT_2 0x00000127 #define CKA_COEFFICIENT 0x00000128 +/* CKA_PUBLIC_KEY_INFO is new for v2.40 */ +#define CKA_PUBLIC_KEY_INFO 0x00000129 #define CKA_PRIME 0x00000130 #define CKA_SUBPRIME 0x00000131 #define CKA_BASE 0x00000132 diff --git a/security/nss/lib/util/secasn1d.c b/security/nss/lib/util/secasn1d.c index ccd97481d..ed237ed72 100644 --- a/security/nss/lib/util/secasn1d.c +++ b/security/nss/lib/util/secasn1d.c @@ -2987,7 +2987,9 @@ SEC_ASN1DecoderFinish(SEC_ASN1DecoderContext *cx) * XXX anything else that needs to be finished? */ - PORT_FreeArena(cx->our_pool, PR_TRUE); + if (cx) { + PORT_FreeArena(cx->our_pool, PR_TRUE); + } return rv; } diff --git a/security/nss/lib/util/secitem.c b/security/nss/lib/util/secitem.c index 22c5b1f6e..1e505a9af 100644 --- a/security/nss/lib/util/secitem.c +++ b/security/nss/lib/util/secitem.c @@ -76,6 +76,15 @@ loser: } SECStatus +SECITEM_MakeItem(PLArenaPool *arena, SECItem *dest, unsigned char *data, + unsigned int len) +{ + SECItem it = { siBuffer, data, len }; + + return SECITEM_CopyItem(arena, dest, &it); +} + +SECStatus SECITEM_ReallocItem(PLArenaPool *arena, SECItem *item, unsigned int oldlen, unsigned int newlen) { diff --git a/security/nss/lib/util/secitem.h b/security/nss/lib/util/secitem.h index 5b9d0e174..4fb123938 100644 --- a/security/nss/lib/util/secitem.h +++ b/security/nss/lib/util/secitem.h @@ -35,6 +35,14 @@ SEC_BEGIN_PROTOS extern SECItem *SECITEM_AllocItem(PLArenaPool *arena, SECItem *item, unsigned int len); +/* Allocate and make an item with the requested contents. + * + * We seem to have mostly given up on SECItemType, so the result is + * always siBuffer. + */ +extern SECStatus SECITEM_MakeItem(PLArenaPool *arena, SECItem *dest, + unsigned char *data, unsigned int len); + /* ** This is a legacy function containing bugs. It doesn't update item->len, ** and it has other issues as described in bug 298649 and bug 298938. diff --git a/security/nss/nss-tool/enc/enctool.cc b/security/nss/nss-tool/enc/enctool.cc index b3c0d1dbe..e37e4593a 100644 --- a/security/nss/nss-tool/enc/enctool.cc +++ b/security/nss/nss-tool/enc/enctool.cc @@ -271,7 +271,6 @@ bool EncTool::DoCipher(std::string file_name, std::string out_file, if (file_name.empty()) { std::vector<uint8_t> data = ReadInputData(""); std::vector<uint8_t> out(data.size() + 16); - SECStatus rv; if (encrypt) { rv = PK11_Encrypt(symKey.get(), cipher_mech_, params.get(), out.data(), &outLen, data.size() + 16, data.data(), data.size()); diff --git a/security/nss/tests/all.sh b/security/nss/tests/all.sh index 3a02debef..f8a777fb3 100755 --- a/security/nss/tests/all.sh +++ b/security/nss/tests/all.sh @@ -309,7 +309,7 @@ TESTS=${NSS_TESTS:-$tests} ALL_TESTS=${TESTS} -nss_ssl_tests="crl iopr policy" +nss_ssl_tests="crl iopr policy normal_normal" if [ $NO_INIT_SUPPORT -eq 0 ]; then nss_ssl_tests="$nss_ssl_tests fips_normal normal_fips" fi diff --git a/security/nss/tests/bogo/bogo.sh b/security/nss/tests/bogo/bogo.sh index d1a93bf9b..4fccb845b 100755 --- a/security/nss/tests/bogo/bogo.sh +++ b/security/nss/tests/bogo/bogo.sh @@ -25,7 +25,7 @@ bogo_init() BORING=${BORING:=boringssl} if [ ! -d "$BORING" ]; then git clone -q https://boringssl.googlesource.com/boringssl "$BORING" - git -C "$BORING" checkout -q a513e86c1ebb1383930c9e504bdabcc302a85f30 + git -C "$BORING" checkout -q ec55dc15d3a39e5f1a58bfd79148729f38f6acb4 fi SCRIPTNAME="bogo.sh" @@ -39,11 +39,12 @@ bogo_cleanup() . common/cleanup.sh } -cd "$(dirname "$0")" -SOURCE_DIR="$PWD"/../.. +cd ../ +cwd=$(cd $(dirname $0); pwd -P) +SOURCE_DIR="$cwd"/.. bogo_init (cd "$BORING"/ssl/test/runner; - GOPATH="$PWD" go test -pipe -shim-path "${BINDIR}"/nss_bogo_shim \ + GOPATH="$cwd" go test -pipe -shim-path "${BINDIR}"/nss_bogo_shim \ -loose-errors -allow-unimplemented \ -shim-config "${SOURCE_DIR}/gtests/nss_bogo_shim/config.json") \ 2>bogo.errors | tee bogo.log diff --git a/security/nss/tests/cert/cert.sh b/security/nss/tests/cert/cert.sh index d1a9148a9..34006efd1 100755 --- a/security/nss/tests/cert/cert.sh +++ b/security/nss/tests/cert/cert.sh @@ -1060,6 +1060,25 @@ cert_extended_ssl() # -d "${PROFILEDIR}" -i "${CLIENT_CADIR}/clientCA-ecmixed.ca.cert" \ # 2>&1 + # Check that a repeated import with a different nickname doesn't change the + # nickname of the existing cert (bug 1458518). + # We want to search for the results using grep, to avoid subset matches, + # we'll use one of the longer nicknames for testing. + # (Because "grep -w hostname" matches "grep -w hostname-dsamixed") + MYDBPASS="-d ${PROFILEDIR} -f ${R_PWFILE}" + TESTNAME="Ensure there's exactly one match for ${CERTNAME}-dsamixed" + cert_check_nickname_exists "$MYDBPASS" "${CERTNAME}-dsamixed" 0 1 "${TESTNAME}" + + CU_ACTION="Repeated import of $CERTNAME's mixed DSA Cert with different nickname" + certu -A -n "${CERTNAME}-repeated-dsamixed" -t "u,u,u" -d "${PROFILEDIR}" \ + -f "${R_PWFILE}" -i "${CERTNAME}-dsamixed.cert" 2>&1 + + TESTNAME="Ensure there's still exactly one match for ${CERTNAME}-dsamixed" + cert_check_nickname_exists "$MYDBPASS" "${CERTNAME}-dsamixed" 0 1 "${TESTNAME}" + + TESTNAME="Ensure there's zero matches for ${CERTNAME}-repeated-dsamixed" + cert_check_nickname_exists "$MYDBPASS" "${CERTNAME}-repeated-dsamixed" 0 0 "${TESTNAME}" + echo "Importing all the server's own CA chain into the servers DB" for CA in `find ${SERVER_CADIR} -name "?*.ca.cert"` ; do @@ -1532,6 +1551,37 @@ cert_make_with_param() return 0 } +cert_check_nickname_exists() +{ + MYDIRPASS="$1" + MYCERTNAME="$2" + EXPECT="$3" + EXPECTCOUNT="$4" + MYTESTNAME="$5" + + echo certutil ${MYDIRPASS} -L + ${BINDIR}/certutil ${MYDIRPASS} -L + + RET=$? + if [ "${RET}" -ne "${EXPECT}" ]; then + CERTFAILED=1 + html_failed "${MYTESTNAME} - list" + cert_log "ERROR: ${MYTESTNAME} - list" + return 1 + fi + + LISTCOUNT=`${BINDIR}/certutil ${MYDIRPASS} -L | grep -wc ${MYCERTNAME}` + if [ "${LISTCOUNT}" -ne "${EXPECTCOUNT}" ]; then + CERTFAILED=1 + html_failed "${MYTESTNAME} - list and count" + cert_log "ERROR: ${MYTESTNAME} - list and count failed" + return 1 + fi + + html_passed "${MYTESTNAME}" + return 0 +} + cert_list_and_count_dns() { DIRPASS="$1" @@ -2425,6 +2475,31 @@ EOF RETEXPECTED=0 } +cert_test_orphan_key_reuse() +{ + CU_ACTION="Create orphan key in serverdir" + certu -G -f "${R_PWFILE}" -z ${R_NOISE_FILE} -d ${PROFILEDIR} + # Let's get the key ID of the first orphan key. + # The output of certutil -K (list keys) isn't well formatted. + # The initial <key-number> part may or may not contain white space, which + # makes the use of awk to filter the column unreliable. + # To fix that, we remove the initial <number> field using sed, then select the + # column that contains the key ID. + ORPHAN=`${BINDIR}/certutil -d ${PROFILEDIR} -K -f ${R_PWFILE} | \ + sed 's/^<.*>//g' | grep -w orphan | head -1 | awk '{print $2}'` + CU_ACTION="Create cert request for orphan key" + certu -R -f "${R_PWFILE}" -k ${ORPHAN} -s "CN=orphan" -d ${PROFILEDIR} \ + -o ${SERVERDIR}/orphan.req + # Ensure that creating the request really works by listing it, and check + # if listing was successful. + ${BINDIR}/pp -t certificate-request -i ${SERVERDIR}/orphan.req + RET=$? + if [ "$RET" -ne 0 ]; then + html_failed "Listing cert request for orphan key ($RET)" + cert_log "ERROR: Listing cert request for orphan key failed $RET" + fi +} + ############################## cert_cleanup ############################ # local shell function to finish this script (no exit since it might be # sourced) @@ -2444,6 +2519,7 @@ cert_all_CA cert_test_implicit_db_init cert_extended_ssl cert_ssl +cert_test_orphan_key_reuse cert_smime_client IS_FIPS_DISABLED=`certutil --build-flags |grep -cw NSS_FIPS_DISABLED` if [ $IS_FIPS_DISABLED -ne 0 ]; then diff --git a/security/nss/tests/common/init.sh b/security/nss/tests/common/init.sh index 933551e83..6aa22af8d 100644 --- a/security/nss/tests/common/init.sh +++ b/security/nss/tests/common/init.sh @@ -543,8 +543,8 @@ if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then D_DISTRUST="Distrust.$version" D_RSAPSS="RSAPSS.$version" - # we need relative pathnames of these files abd directories, since our - # tools can't handle the unix style absolut pathnames on cygnus + # we need relative pathnames of these files and directories, since our + # tools can't handle the unix style absolute pathnames on cygnus R_CADIR=../CA R_SERVERDIR=../server @@ -565,6 +565,7 @@ if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then R_NOLOGINDIR=../nologin R_SSLGTESTDIR=../ssl_gtests R_GTESTDIR=../gtests + R_RSAPSSDIR=../rsapss # # profiles are either paths or domains depending on the setting of @@ -581,6 +582,7 @@ if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then P_R_EXT_SERVERDIR=${R_EXT_SERVERDIR} P_R_EXT_CLIENTDIR=${R_EXT_CLIENTDIR} P_R_IMPLICIT_INIT_DIR=${R_IMPLICIT_INIT_DIR} + P_R_RSAPSSDIR=${R_RSAPSSDIR} if [ -n "${MULTIACCESS_DBM}" ]; then P_R_CADIR="multiaccess:${D_CA}" P_R_ALICEDIR="multiaccess:${D_ALICE}" @@ -593,6 +595,7 @@ if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then P_R_EXT_SERVERDIR="multiaccess:${D_EXT_SERVER}" P_R_EXT_CLIENTDIR="multiaccess:${D_EXT_CLIENT}" P_R_IMPLICIT_INIT_DIR="multiaccess:${D_IMPLICIT_INIT}" + P_R_RSAPSSDIR="multiaccess:${D_RSAPSS}" fi R_PWFILE=../tests.pw diff --git a/security/nss/tests/interop/interop.sh b/security/nss/tests/interop/interop.sh index 97c82e0ca..50c8bb3c1 100644 --- a/security/nss/tests/interop/interop.sh +++ b/security/nss/tests/interop/interop.sh @@ -25,7 +25,7 @@ interop_init() INTEROP=${INTEROP:=tls_interop} if [ ! -d "$INTEROP" ]; then git clone -q https://github.com/ttaubert/tls-interop "$INTEROP" - git -C "$INTEROP" checkout -q 07930b791827c1bdb6f4c19ca0aa63850fd59e22 + git -C "$INTEROP" checkout -q d07b28ac32b390dea1c9bcca5c56716247d23e5e fi INTEROP=$(cd "$INTEROP";pwd -P) diff --git a/security/nss/tests/ssl/ssl.sh b/security/nss/tests/ssl/ssl.sh index de867a4bd..9a63bd997 100755 --- a/security/nss/tests/ssl/ssl.sh +++ b/security/nss/tests/ssl/ssl.sh @@ -283,34 +283,30 @@ ssl_cov() echo "${testname}" | grep "EXPORT" > /dev/null EXP=$? - if [ "$ectype" = "ECC" ] ; then - echo "$SCRIPTNAME: skipping $testname (ECC only)" - else - echo "$SCRIPTNAME: running $testname ----------------------------" - VMAX="ssl3" - if [ "$testmax" = "TLS10" ]; then - VMAX="tls1.0" - fi - if [ "$testmax" = "TLS11" ]; then - VMAX="tls1.1" - fi - if [ "$testmax" = "TLS12" ]; then - VMAX="tls1.2" - fi - - echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -c ${param} -V ${VMIN}:${VMAX} ${CLIENT_OPTIONS} \\" - echo " -f -d ${P_R_CLIENTDIR} $verbose -w nss < ${REQUEST_FILE}" - - rm ${TMP}/$HOST.tmp.$$ 2>/dev/null - ${PROFTOOL} ${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} -c ${param} -V ${VMIN}:${VMAX} ${CLIENT_OPTIONS} -f \ - -d ${P_R_CLIENTDIR} $verbose -w nss < ${REQUEST_FILE} \ - >${TMP}/$HOST.tmp.$$ 2>&1 - ret=$? - cat ${TMP}/$HOST.tmp.$$ - rm ${TMP}/$HOST.tmp.$$ 2>/dev/null - html_msg $ret 0 "${testname}" \ - "produced a returncode of $ret, expected is 0" + echo "$SCRIPTNAME: running $testname ----------------------------" + VMAX="ssl3" + if [ "$testmax" = "TLS10" ]; then + VMAX="tls1.0" + fi + if [ "$testmax" = "TLS11" ]; then + VMAX="tls1.1" fi + if [ "$testmax" = "TLS12" ]; then + VMAX="tls1.2" + fi + + echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -c ${param} -V ${VMIN}:${VMAX} ${CLIENT_OPTIONS} \\" + echo " -f -d ${P_R_CLIENTDIR} $verbose -w nss < ${REQUEST_FILE}" + + rm ${TMP}/$HOST.tmp.$$ 2>/dev/null + ${PROFTOOL} ${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} -c ${param} -V ${VMIN}:${VMAX} ${CLIENT_OPTIONS} -f \ + -d ${P_R_CLIENTDIR} $verbose -w nss < ${REQUEST_FILE} \ + >${TMP}/$HOST.tmp.$$ 2>&1 + ret=$? + cat ${TMP}/$HOST.tmp.$$ + rm ${TMP}/$HOST.tmp.$$ 2>/dev/null + html_msg $ret 0 "${testname}" \ + "produced a returncode of $ret, expected is 0" done kill_selfserv @@ -335,8 +331,6 @@ ssl_auth() echo "$SCRIPTNAME: skipping $testname (non-FIPS only)" elif [ "$ectype" = "SNI" -a "$NORM_EXT" = "Extended Test" ] ; then echo "$SCRIPTNAME: skipping $testname for $NORM_EXT" - elif [ "$ectype" = "ECC" ] ; then - echo "$SCRIPTNAME: skipping $testname (ECC only)" else cparam=`echo $cparam | sed -e 's;_; ;g' -e "s/TestUser/$USER_NICKNAME/g" ` if [ "$ectype" = "SNI" ]; then @@ -550,8 +544,6 @@ ssl_stress() if [ "$ectype" = "SNI" -a "$NORM_EXT" = "Extended Test" ] ; then echo "$SCRIPTNAME: skipping $testname for $NORM_EXT" - elif [ "$ectype" = "ECC" ] ; then - echo "$SCRIPTNAME: skipping $testname (ECC only)" elif [ "${CLIENT_MODE}" = "fips" -a "${CAUTH}" -ne 0 ] ; then echo "$SCRIPTNAME: skipping $testname (non-FIPS only)" elif [ "${NOLOGIN}" -eq 0 ] && \ @@ -615,9 +607,7 @@ ssl_crl_ssl() ignore_blank_lines ${SSLAUTH} | \ while read ectype value sparam cparam testname do - if [ "$ectype" = "ECC" ] ; then - echo "$SCRIPTNAME: skipping $testname (ECC only)" - elif [ "$ectype" = "SNI" ]; then + if [ "$ectype" = "SNI" ]; then continue else servarg=`echo $sparam | awk '{r=split($0,a,"-r") - 1;print r;}'` @@ -729,43 +719,39 @@ ssl_policy() do VMIN="ssl3" - if [ "$ectype" = "ECC" ] ; then - echo "$SCRIPTNAME: skipping $testname (ECC only)" - else - echo "$SCRIPTNAME: running $testname ----------------------------" - VMAX="ssl3" - if [ "$testmax" = "TLS10" ]; then - VMAX="tls1.0" - fi - if [ "$testmax" = "TLS11" ]; then - VMAX="tls1.1" - fi - if [ "$testmax" = "TLS12" ]; then - VMAX="tls1.2" - fi + echo "$SCRIPTNAME: running $testname ----------------------------" + VMAX="ssl3" + if [ "$testmax" = "TLS10" ]; then + VMAX="tls1.0" + fi + if [ "$testmax" = "TLS11" ]; then + VMAX="tls1.1" + fi + if [ "$testmax" = "TLS12" ]; then + VMAX="tls1.2" + fi - # load the policy - policy=`echo ${policy} | sed -e 's;_; ;g'` - setup_policy "$policy" ${P_R_CLIENTDIR} + # load the policy + policy=`echo ${policy} | sed -e 's;_; ;g'` + setup_policy "$policy" ${P_R_CLIENTDIR} - echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -c ${param} -V ${VMIN}:${VMAX} ${CLIENT_OPTIONS} \\" - echo " -f -d ${P_R_CLIENTDIR} $verbose -w nss < ${REQUEST_FILE}" + echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -c ${param} -V ${VMIN}:${VMAX} ${CLIENT_OPTIONS} \\" + echo " -f -d ${P_R_CLIENTDIR} $verbose -w nss < ${REQUEST_FILE}" - rm ${TMP}/$HOST.tmp.$$ 2>/dev/null - ${PROFTOOL} ${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} -c ${param} -V ${VMIN}:${VMAX} ${CLIENT_OPTIONS} -f \ - -d ${P_R_CLIENTDIR} $verbose -w nss < ${REQUEST_FILE} \ - >${TMP}/$HOST.tmp.$$ 2>&1 - ret=$? - cat ${TMP}/$HOST.tmp.$$ - rm ${TMP}/$HOST.tmp.$$ 2>/dev/null + rm ${TMP}/$HOST.tmp.$$ 2>/dev/null + ${PROFTOOL} ${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} -c ${param} -V ${VMIN}:${VMAX} ${CLIENT_OPTIONS} -f \ + -d ${P_R_CLIENTDIR} $verbose -w nss < ${REQUEST_FILE} \ + >${TMP}/$HOST.tmp.$$ 2>&1 + ret=$? + cat ${TMP}/$HOST.tmp.$$ + rm ${TMP}/$HOST.tmp.$$ 2>/dev/null - #workaround for bug #402058 - [ $ret -ne 0 ] && ret=1 - [ ${value} -ne 0 ] && value=1 + #workaround for bug #402058 + [ $ret -ne 0 ] && ret=1 + [ ${value} -ne 0 ] && value=1 - html_msg $ret ${value} "${testname}" \ - "produced a returncode of $ret, expected is ${value}" - fi + html_msg $ret ${value} "${testname}" \ + "produced a returncode of $ret, expected is ${value}" done cp ${P_R_CLIENTDIR}/pkcs11.txt.sav ${P_R_CLIENTDIR}/pkcs11.txt @@ -1004,9 +990,7 @@ ssl_crl_cache() while read ectype value sparam cparam testname do [ "$ectype" = "" ] && continue - if [ "$ectype" = "ECC" ] ; then - echo "$SCRIPTNAME: skipping $testname (ECC only)" - elif [ "$ectype" = "SNI" ]; then + if [ "$ectype" = "SNI" ]; then continue else servarg=`echo $sparam | awk '{r=split($0,a,"-r") - 1;print r;}'` diff --git a/security/nss/tests/ssl_gtests/ssl_gtests.sh b/security/nss/tests/ssl_gtests/ssl_gtests.sh index fd678bf59..eef77f16f 100755 --- a/security/nss/tests/ssl_gtests/ssl_gtests.sh +++ b/security/nss/tests/ssl_gtests/ssl_gtests.sh @@ -47,6 +47,7 @@ make_cert() { dsa) type_args='-g 1024' ;; rsa) type_args='-g 1024' ;; rsa2048) type_args='-g 2048';type=rsa ;; + rsa8192) type_args='-g 8192';type=rsa ;; rsapss) type_args='-g 1024 --pss';type=rsa ;; p256) type_args='-q nistp256';type=ec ;; p384) type_args='-q secp384r1';type=ec ;; @@ -83,6 +84,7 @@ ssl_gtest_certs() { make_cert client rsa sign make_cert rsa rsa sign kex make_cert rsa2048 rsa2048 sign kex + make_cert rsa8192 rsa8192 sign kex make_cert rsa_sign rsa sign make_cert rsa_pss rsapss sign make_cert rsa_decrypt rsa kex diff --git a/security/nss/tests/tools/TestRSAPSS.p12 b/security/nss/tests/tools/TestRSAPSS.p12 Binary files differnew file mode 100644 index 000000000..91473891c --- /dev/null +++ b/security/nss/tests/tools/TestRSAPSS.p12 diff --git a/security/nss/tests/tools/tools.sh b/security/nss/tests/tools/tools.sh index 11be23e05..7cf1ef73f 100644 --- a/security/nss/tests/tools/tools.sh +++ b/security/nss/tests/tools/tools.sh @@ -105,6 +105,7 @@ tools_init() mkdir -p ${TOOLSDIR}/data cp ${QADIR}/tools/TestOldCA.p12 ${TOOLSDIR}/data cp ${QADIR}/tools/TestOldAES128CA.p12 ${TOOLSDIR}/data + cp ${QADIR}/tools/TestRSAPSS.p12 ${TOOLSDIR}/data cd ${TOOLSDIR} } @@ -436,6 +437,23 @@ tools_p12_import_old_files() check_tmpfile } +tools_p12_import_rsa_pss_private_key() +{ + echo "$SCRIPTNAME: Importing RSA-PSS private key from PKCS#12 file --------------" + ${BINDIR}/pk12util -i ${TOOLSDIR}/data/TestRSAPSS.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -W '' 2>&1 + ret=$? + html_msg $ret 0 "Importing RSA-PSS private key from PKCS#12 file" + check_tmpfile + + # Check if RSA-PSS identifier is included in the key listing + ${BINDIR}/certutil -d ${P_R_COPYDIR} -K -f ${R_PWFILE} | grep '^<[0-9 ]*> *rsaPss' + ret=$? + html_msg $ret 0 "Listing RSA-PSS private key imported from PKCS#12 file" + check_tmpfile + + return $ret +} + ############################## tools_p12 ############################### # local shell function to test basic functionality of pk12util ######################################################################## @@ -448,6 +466,9 @@ tools_p12() tools_p12_export_with_none_ciphers tools_p12_export_with_invalid_ciphers tools_p12_import_old_files + if [ "${TEST_MODE}" = "SHARED_DB" ] ; then + tools_p12_import_rsa_pss_private_key + fi } ############################## tools_sign ############################## |