diff --git a/security/nss.symbols b/security/nss.symbols index d983866de..89560e916 100644 --- a/security/nss.symbols +++ b/security/nss.symbols @@ -726,6 +726,8 @@ VFY_VerifyDataWithAlgorithmID VFY_VerifyDigestDirect _SGN_VerifyPKCS1DigestInfo __PK11_SetCertificateNickname +PK11_GetSlotFromPrivateKey +CERT_GetCertKeyType # These symbols are not used by Firefox itself, but are used by Java's security # libraries, which in turn are used by Java applets/plugins/etc. Provide them # to make Java code happy. diff --git a/security/nss/.hgtags b/security/nss/.hgtags index 0cd78b512..0c93729f8 100644 --- a/security/nss/.hgtags +++ b/security/nss/.hgtags @@ -1593,10 +1593,3 @@ d36a5c8225914f92c12f8e182d83f5b4727d327b NSS_3_27_BETA2 32c9bbad265504522441f601333f0b89861a15d1 NSS_3_34_BETA1 f9e336b12cb424b2e4693feef52c3dc6825a7dea NSS_3_36_BETA1 3570602e28126ef329de0b66829c1d7100206a55 NSS_3_36_BETA2 -de23060d51552a0364dcdaf816d6ae6e00cfc8aa NSS_3_36_BETA3 -33317adf00d6bc6c3e3499e4b32fca6b899c4b77 NSS_3_36_RTM -fa159fd618ea5541f8de61fbf7a64cab8f4c8ded NSS_3_36_1_BETA1 -a6bb8ed73bc124fc5f25bc4178d9e4e7339d2084 NSS_3_36_1_RTM -2251be26fa214eba03f47600d914cd0ab2ab8a30 NSS_3_36_2_RTM -197e03b510a05b9675e4b78eed3661598205020d NSS_3_36_3_RTM -4f54ef76a3278370fafb9861a91dbf5241bbbe0b NSS_3_36_4_RTM diff --git a/security/nss/automation/abi-check/expected-report-libnss3.so.txt b/security/nss/automation/abi-check/expected-report-libnss3.so.txt index e69de29bb..16b496424 100644 --- a/security/nss/automation/abi-check/expected-report-libnss3.so.txt +++ b/security/nss/automation/abi-check/expected-report-libnss3.so.txt @@ -0,0 +1,5 @@ + +1 Added function: + + 'function KeyType CERT_GetCertKeyType(const CERTSubjectPublicKeyInfo*)' {CERT_GetCertKeyType@@NSS_3.39} + 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..06d2389db 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,5 @@ + +1 Added function: + + 'function char* NSSUTIL_AddNSSFlagToModuleSpec(char*, char*)' {NSSUTIL_AddNSSFlagToModuleSpec@@NSSUTIL_3.39} + 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..453b85f97 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_38_BRANCH diff --git a/security/nss/automation/release/nspr-version.txt b/security/nss/automation/release/nspr-version.txt index 701680d2c..102def16d 100644 --- a/security/nss/automation/release/nspr-version.txt +++ b/security/nss/automation/release/nspr-version.txt @@ -1,4 +1,4 @@ -4.19 +4.20 # The first line of this file must contain the human readable NSPR # version number, which is the minimum required version of NSPR 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 # 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 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/docker/setup.sh b/security/nss/automation/taskcluster/docker/setup.sh index 7b90b2e69..772d7355d 100644 --- a/security/nss/automation/taskcluster/docker/setup.sh +++ b/security/nss/automation/taskcluster/docker/setup.sh @@ -22,6 +22,7 @@ apt_packages+=('locales') apt_packages+=('ninja-build') apt_packages+=('pkg-config') apt_packages+=('zlib1g-dev') +apt_packages+=('cmake') # 32-bit builds apt_packages+=('lib32z1-dev') diff --git a/security/nss/automation/taskcluster/graph/src/extend.js b/security/nss/automation/taskcluster/graph/src/extend.js index ee9ac9b74..37e716d9b 100644 --- a/security/nss/automation/taskcluster/graph/src/extend.js +++ b/security/nss/automation/taskcluster/graph/src/extend.js @@ -928,6 +928,9 @@ function scheduleTests(task_build, task_cert, test_base) { queue.scheduleTask(merge(no_cert_base, { name: "SDR tests", symbol: "SDR", tests: "sdr" })); + queue.scheduleTask(merge(no_cert_base, { + name: "Policy tests", symbol: "Policy", tests: "policy" + })); // Schedule tests that need certificates. let cert_base = merge(test_base, {parent: task_cert}); @@ -995,13 +998,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 +1095,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..92cf9bb00 100644 --- a/security/nss/automation/taskcluster/graph/src/try_syntax.js +++ b/security/nss/automation/taskcluster/graph/src/try_syntax.js @@ -37,7 +37,7 @@ function parseOptions(opts) { let aliases = {"gtests": "gtest"}; let allUnitTests = ["bogo", "crmf", "chains", "cipher", "db", "ec", "fips", "gtest", "interop", "lowhash", "merge", "sdr", "smime", "tools", - "ssl", "mpi", "scert", "spki"]; + "ssl", "mpi", "scert", "spki", "policy"]; let unittests = intersect(opts.unittests.split(/\s*,\s*/).map(t => { return aliases[t] || t; }), allUnitTests); @@ -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..5ecf1e71a 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,41 +856,59 @@ 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", "rsaOaep" }; #define MAX_CKA_ID_BIN_LEN 20 #define MAX_CKA_ID_STR_LEN 40 +/* output human readable key ID in buffer, which should have at least + * MAX_CKA_ID_STR_LEN + 3 octets (quotations and a null terminator) */ +static void +formatPrivateKeyID(SECKEYPrivateKey *privkey, char *buffer) +{ + SECItem *ckaID; + + ckaID = PK11_GetLowLevelKeyIDForPrivateKey(privkey); + if (!ckaID) { + strcpy(buffer, "(no CKA_ID)"); + } else if (ItemIsPrintableASCII(ckaID)) { + int len = PR_MIN(MAX_CKA_ID_STR_LEN, ckaID->len); + buffer[0] = '"'; + memcpy(buffer + 1, ckaID->data, len); + buffer[1 + len] = '"'; + buffer[2 + len] = '\0'; + } else { + /* print ckaid in hex */ + SECItem idItem = *ckaID; + if (idItem.len > MAX_CKA_ID_BIN_LEN) + idItem.len = MAX_CKA_ID_BIN_LEN; + SECItemToHex(&idItem, buffer); + } + SECITEM_ZfreeItem(ckaID, PR_TRUE); +} + /* print key number, key ID (in hex or ASCII), key label (nickname) */ static SECStatus PrintKey(PRFileDesc *out, const char *nickName, int count, SECKEYPrivateKey *key, void *pwarg) { - SECItem *ckaID; char ckaIDbuf[MAX_CKA_ID_STR_LEN + 4]; + CERTCertificate *cert; + KeyType keyType; pwarg = NULL; - ckaID = PK11_GetLowLevelKeyIDForPrivateKey(key); - if (!ckaID) { - strcpy(ckaIDbuf, "(no CKA_ID)"); - } else if (ItemIsPrintableASCII(ckaID)) { - int len = PR_MIN(MAX_CKA_ID_STR_LEN, ckaID->len); - ckaIDbuf[0] = '"'; - memcpy(ckaIDbuf + 1, ckaID->data, len); - ckaIDbuf[1 + len] = '"'; - ckaIDbuf[2 + len] = '\0'; - } else { - /* print ckaid in hex */ - SECItem idItem = *ckaID; - if (idItem.len > MAX_CKA_ID_BIN_LEN) - idItem.len = MAX_CKA_ID_BIN_LEN; - SECItemToHex(&idItem, ckaIDbuf); - } + formatPrivateKeyID(key, ckaIDbuf); + cert = PK11_GetCertFromPrivateKey(key); + if (cert) { + keyType = CERT_GetCertKeyType(&cert->subjectPublicKeyInfo); + CERT_DestroyCertificate(cert); + } else { + keyType = key->keyType; + } PR_fprintf(out, "<%2d> %-8.8s %-42.42s %s\n", count, - keyTypeName[key->keyType], ckaIDbuf, nickName); - SECITEM_ZfreeItem(ckaID, PR_TRUE); + keyTypeName[keyType], ckaIDbuf, nickName); return SECSuccess; } @@ -991,7 +1020,7 @@ ListKeys(PK11SlotInfo *slot, const char *nickName, int index, } static SECStatus -DeleteKey(char *nickname, secuPWData *pwdata) +DeleteCertAndKey(char *nickname, secuPWData *pwdata) { SECStatus rv; CERTCertificate *cert; @@ -999,7 +1028,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)); @@ -1020,6 +1049,61 @@ DeleteKey(char *nickname, secuPWData *pwdata) return rv; } +static SECKEYPrivateKey * +findPrivateKeyByID(PK11SlotInfo *slot, const char *ckaID, secuPWData *pwarg) +{ + PORTCheapArenaPool arena; + SECItem ckaIDItem = { 0 }; + SECKEYPrivateKey *privkey = NULL; + SECStatus rv; + + if (PK11_NeedLogin(slot)) { + rv = PK11_Authenticate(slot, PR_TRUE, pwarg); + if (rv != SECSuccess) { + SECU_PrintError(progName, "could not authenticate to token %s.", + PK11_GetTokenName(slot)); + return NULL; + } + } + + if (0 == PL_strncasecmp("0x", ckaID, 2)) { + ckaID += 2; /* skip leading "0x" */ + } + PORT_InitCheapArena(&arena, DER_DEFAULT_CHUNKSIZE); + if (SECU_HexString2SECItem(&arena.arena, &ckaIDItem, ckaID)) { + privkey = PK11_FindKeyByKeyID(slot, &ckaIDItem, pwarg); + } + PORT_DestroyCheapArena(&arena); + return privkey; +} + +static SECStatus +DeleteKey(SECKEYPrivateKey *privkey, secuPWData *pwarg) +{ + SECStatus rv; + PK11SlotInfo *slot; + + slot = PK11_GetSlotFromPrivateKey(privkey); + if (PK11_NeedLogin(slot)) { + rv = PK11_Authenticate(slot, PR_TRUE, pwarg); + if (rv != SECSuccess) { + SECU_PrintError(progName, "could not authenticate to token %s.", + PK11_GetTokenName(slot)); + return SECFailure; + } + } + + rv = PK11_DeleteTokenPrivateKey(privkey, PR_TRUE); + if (rv != SECSuccess) { + char ckaIDbuf[MAX_CKA_ID_STR_LEN + 4]; + formatPrivateKeyID(privkey, ckaIDbuf); + SECU_PrintError("problem deleting private key \"%s\"\n", ckaIDbuf); + } + + PK11_FreeSlot(slot); + return rv; +} + /* * L i s t M o d u l e s * @@ -1066,7 +1150,7 @@ PrintBuildFlags() } static void -PrintSyntax(char *progName) +PrintSyntax() { #define FPS fprintf(stderr, FPS "Type %s -H for more detailed descriptions\n", progName); @@ -1089,7 +1173,9 @@ PrintSyntax(char *progName) "\t\t [-d certdir] [-P dbprefix]\n", progName); FPS "\t%s -E -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n", progName); - FPS "\t%s -F -n nickname [-d certdir] [-P dbprefix]\n", + FPS "\t%s -F -n cert-name [-d certdir] [-P dbprefix]\n", + progName); + FPS "\t%s -F -k key-id [-d certdir] [-P dbprefix]\n", progName); FPS "\t%s -G -n key-name [-h token-name] [-k rsa] [-g key-size] [-y exp]\n" "\t\t [-f pwfile] [-z noisefile] [-d certdir] [-P dbprefix]\n", progName); @@ -1115,7 +1201,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", @@ -1377,6 +1465,8 @@ luF(enum usage_level ul, const char *command) return; FPS "%-20s The nickname of the key to delete\n", " -n cert-name"); + FPS "%-20s The key id of the key to delete, obtained using -K\n", + " -k key-id"); FPS "%-20s Cert database directory (default is ~/.netscape)\n", " -d certdir"); FPS "%-20s Cert & Key database prefix\n", @@ -1542,6 +1632,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 +1652,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 +1930,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 +1958,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 -d \n\n" "Valid commands:\n", progName, progName); - LongUsage(progName, usage_selected, NULL); + LongUsage(usage_selected, NULL); PR_fprintf(PR_STDERR, "\n" "%s -H : Print available options for the given command\n" "%s -H : Print complete help output of all commands and options\n" @@ -2269,10 +2361,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 +2378,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 +2394,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 +2590,7 @@ enum certutilOpts { opt_NewNickname, opt_Pss, opt_PssSign, + opt_SimpleSelfSigned, opt_Help }; @@ -2623,6 +2715,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 +2785,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 +2808,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 +2916,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 +2925,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 +3009,7 @@ certutil_main(int argc, char **argv, PRBool initialize) return 255; } if (commandsEntered == 0) { - Usage(progName); + Usage(); } if (certutil.commands[cmd_ListCerts].activated || @@ -2928,10 +3021,9 @@ certutil_main(int argc, char **argv, PRBool initialize) readOnly = !certutil.options[opt_RW].activated; } - /* -A, -D, -F, -M, -S, -V, and all require -n */ + /* -A, -D, -M, -S, -V, and all require -n */ if ((certutil.commands[cmd_AddCert].activated || certutil.commands[cmd_DeleteCert].activated || - certutil.commands[cmd_DeleteKey].activated || certutil.commands[cmd_DumpChain].activated || certutil.commands[cmd_ModifyCertTrust].activated || certutil.commands[cmd_CreateAndAddCert].activated || @@ -3018,6 +3110,16 @@ certutil_main(int argc, char **argv, PRBool initialize) return 255; } + /* Delete needs a nickname or a key ID */ + if (certutil.commands[cmd_DeleteKey].activated && + !(certutil.options[opt_Nickname].activated || keysource)) { + PR_fprintf(PR_STDERR, + "%s -%c: specify a nickname (-n) or\n" + " a key ID (-k).\n", + commandToRun, progName); + return 255; + } + /* Upgrade/Merge needs a source database and a upgrade id. */ if (certutil.commands[cmd_UpgradeMerge].activated && !(certutil.options[opt_SourceDir].activated && @@ -3124,6 +3226,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 +3454,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 */ @@ -3377,7 +3482,19 @@ certutil_main(int argc, char **argv, PRBool initialize) } /* Delete key (-F) */ if (certutil.commands[cmd_DeleteKey].activated) { - rv = DeleteKey(name, &pwdata); + if (certutil.options[opt_Nickname].activated) { + rv = DeleteCertAndKey(name, &pwdata); + } else { + privkey = findPrivateKeyByID(slot, keysource, &pwdata); + if (!privkey) { + SECU_PrintError(progName, "%s is not a key-id", keysource); + rv = SECFailure; + } else { + rv = DeleteKey(privkey, &pwdata); + /* already destroyed by PK11_DeleteTokenPrivateKey */ + privkey = NULL; + } + } goto shutdown; } /* Modify trust attribute for cert (-M) */ @@ -3444,37 +3561,58 @@ 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); - return SECFailure; - } } - privkey = PK11_FindKeyByDERCert(slot, keycert, &pwdata); - if (privkey) - pubkey = CERT_ExtractPublicKey(keycert); + + if (keycert) { + privkey = PK11_FindKeyByDERCert(slot, keycert, &pwdata); + } else { + /* Interpret keysource as CKA_ID */ + privkey = findPrivateKeyByID(slot, keysource, &pwdata); + } + + if (!privkey) { + SECU_PrintError( + progName, + "%s is neither a key-type nor a nickname nor a key-id", keysource); + return SECFailure; + } + + 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 +3675,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/fipstest/fipstest.c b/security/nss/cmd/fipstest/fipstest.c index 061f3dde0..5d00b3070 100644 --- a/security/nss/cmd/fipstest/fipstest.c +++ b/security/nss/cmd/fipstest/fipstest.c @@ -2335,6 +2335,34 @@ sha_get_hashType(int hashbits) return hashType; } +HASH_HashType +hash_string_to_hashType(const char *src) +{ + HASH_HashType shaAlg = HASH_AlgNULL; + if (strncmp(src, "SHA-1", 5) == 0) { + shaAlg = HASH_AlgSHA1; + } else if (strncmp(src, "SHA-224", 7) == 0) { + shaAlg = HASH_AlgSHA224; + } else if (strncmp(src, "SHA-256", 7) == 0) { + shaAlg = HASH_AlgSHA256; + } else if (strncmp(src, "SHA-384", 7) == 0) { + shaAlg = HASH_AlgSHA384; + } else if (strncmp(src, "SHA-512", 7) == 0) { + shaAlg = HASH_AlgSHA512; + } else if (strncmp(src, "SHA1", 4) == 0) { + shaAlg = HASH_AlgSHA1; + } else if (strncmp(src, "SHA224", 6) == 0) { + shaAlg = HASH_AlgSHA224; + } else if (strncmp(src, "SHA256", 6) == 0) { + shaAlg = HASH_AlgSHA256; + } else if (strncmp(src, "SHA384", 6) == 0) { + shaAlg = HASH_AlgSHA384; + } else if (strncmp(src, "SHA512", 6) == 0) { + shaAlg = HASH_AlgSHA512; + } + return shaAlg; +} + /* * Perform the ECDSA Key Pair Generation Test. * @@ -2628,17 +2656,8 @@ ecdsa_siggen_test(char *reqfn) *dst = '\0'; src++; /* skip the comma */ /* set the SHA Algorithm */ - if (strncmp(src, "SHA-1", 5) == 0) { - shaAlg = HASH_AlgSHA1; - } else if (strncmp(src, "SHA-224", 7) == 0) { - shaAlg = HASH_AlgSHA224; - } else if (strncmp(src, "SHA-256", 7) == 0) { - shaAlg = HASH_AlgSHA256; - } else if (strncmp(src, "SHA-384", 7) == 0) { - shaAlg = HASH_AlgSHA384; - } else if (strncmp(src, "SHA-512", 7) == 0) { - shaAlg = HASH_AlgSHA512; - } else { + shaAlg = hash_string_to_hashType(src); + if (shaAlg == HASH_AlgNULL) { fprintf(ecdsaresp, "ERROR: Unable to find SHAAlg type"); goto loser; } @@ -2798,17 +2817,8 @@ ecdsa_sigver_test(char *reqfn) *dst = '\0'; src++; /* skip the comma */ /* set the SHA Algorithm */ - if (strncmp(src, "SHA-1", 5) == 0) { - shaAlg = HASH_AlgSHA1; - } else if (strncmp(src, "SHA-224", 7) == 0) { - shaAlg = HASH_AlgSHA224; - } else if (strncmp(src, "SHA-256", 7) == 0) { - shaAlg = HASH_AlgSHA256; - } else if (strncmp(src, "SHA-384", 7) == 0) { - shaAlg = HASH_AlgSHA384; - } else if (strncmp(src, "SHA-512", 7) == 0) { - shaAlg = HASH_AlgSHA512; - } else { + shaAlg = hash_string_to_hashType(src); + if (shaAlg == HASH_AlgNULL) { fprintf(ecdsaresp, "ERROR: Unable to find SHAAlg type"); goto loser; } @@ -2956,6 +2966,932 @@ loser: fclose(ecdsareq); } +/* + * Perform the ECDH Functional Test. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ +#define MAX_ECC_PARAMS 256 +void +ecdh_functional(char *reqfn, PRBool response) +{ + char buf[256]; /* holds one line from the input REQUEST file. + * needs to be large enough to hold the longest + * line "Qx = <144 hex digits>\n". + */ + FILE *ecdhreq; /* input stream from the REQUEST file */ + FILE *ecdhresp; /* output stream to the RESPONSE file */ + char curve[16]; /* "nistxddd" */ + unsigned char hashBuf[HASH_LENGTH_MAX]; + ECParams *ecparams[MAX_ECC_PARAMS] = { NULL }; + ECPrivateKey *ecpriv = NULL; + ECParams *current_ecparams = NULL; + SECItem pubkey; + SECItem ZZ; + unsigned int i; + unsigned int len = 0; + unsigned int uit_len = 0; + int current_curve = -1; + HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */ + + ecdhreq = fopen(reqfn, "r"); + ecdhresp = stdout; + strcpy(curve, "nist"); + pubkey.data = NULL; + while (fgets(buf, sizeof buf, ecdhreq) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') { + fputs(buf, ecdhresp); + continue; + } + if (buf[0] == '[') { + /* [Ex] */ + if (buf[1] == 'E' && buf[3] == ']') { + current_curve = buf[2] - 'A'; + fputs(buf, ecdhresp); + continue; + } + /* [Curve selected: x-nnn */ + if (strncmp(buf, "[Curve ", 7) == 0) { + const char *src; + char *dst; + SECItem *encodedparams; + + if ((current_curve < 0) || (current_curve > MAX_ECC_PARAMS)) { + fprintf(stderr, "No curve type defined\n"); + goto loser; + } + + src = &buf[1]; + /* skip passed the colon */ + while (*src && *src != ':') + src++; + if (*src != ':') { + fprintf(stderr, + "No colon in curve selected statement\n%s", buf); + goto loser; + } + src++; + /* skip to the first non-space */ + while (*src && *src == ' ') + src++; + dst = &curve[4]; + *dst++ = tolower(*src); + src += 2; /* skip the hyphen */ + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst = '\0'; + if (ecparams[current_curve] != NULL) { + PORT_FreeArena(ecparams[current_curve]->arena, PR_FALSE); + ecparams[current_curve] = NULL; + } + encodedparams = getECParams(curve); + if (encodedparams == NULL) { + fprintf(stderr, "Unknown curve %s.", curve); + goto loser; + } + if (EC_DecodeParams(encodedparams, &ecparams[current_curve]) != SECSuccess) { + fprintf(stderr, "Curve %s not supported.\n", curve); + goto loser; + } + SECITEM_FreeItem(encodedparams, PR_TRUE); + fputs(buf, ecdhresp); + continue; + } + /* [Ex - SHAxxx] */ + if (buf[1] == 'E' && buf[3] == ' ') { + const char *src; + current_curve = buf[2] - 'A'; + if ((current_curve < 0) || (current_curve > 256)) { + fprintf(stderr, "bad curve type defined (%c)\n", buf[2]); + goto loser; + } + current_ecparams = ecparams[current_curve]; + if (current_ecparams == NULL) { + fprintf(stderr, "no curve defined for type %c defined\n", + buf[2]); + goto loser; + } + /* skip passed the colon */ + src = &buf[1]; + while (*src && *src != '-') + src++; + if (*src != '-') { + fprintf(stderr, + "No data in curve selected statement\n%s", buf); + goto loser; + } + src++; + /* skip to the first non-space */ + while (*src && *src == ' ') + src++; + hash = hash_string_to_hashType(src); + if (hash == HASH_AlgNULL) { + fprintf(ecdhresp, "ERROR: Unable to find SHAAlg type"); + goto loser; + } + fputs(buf, ecdhresp); + continue; + } + fputs(buf, ecdhresp); + continue; + } + /* COUNT = ... */ + if (strncmp(buf, "COUNT", 5) == 0) { + fputs(buf, ecdhresp); + if (current_ecparams == NULL) { + fprintf(stderr, "no curve defined for type %c defined\n", + buf[2]); + goto loser; + } + len = (current_ecparams->fieldID.size + 7) >> 3; + if (pubkey.data != NULL) { + PORT_Free(pubkey.data); + pubkey.data = NULL; + } + SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(current_ecparams)); + if (pubkey.data == NULL) { + goto loser; + } + pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED; + continue; + } + /* QeCAVSx = ... */ + if (strncmp(buf, "QeCAVSx", 7) == 0) { + fputs(buf, ecdhresp); + i = 7; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + from_hex_str(&pubkey.data[1], len, &buf[i]); + continue; + } + /* QeCAVSy = ... */ + if (strncmp(buf, "QeCAVSy", 7) == 0) { + fputs(buf, ecdhresp); + i = 7; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + from_hex_str(&pubkey.data[1 + len], len, &buf[i]); + if (current_ecparams == NULL) { + fprintf(stderr, "no curve defined\n"); + goto loser; + } + /* validate CAVS public key */ + if (EC_ValidatePublicKey(current_ecparams, &pubkey) != SECSuccess) { + fprintf(stderr, "BAD key detected\n"); + goto loser; + } + + /* generate ECC key pair */ + if (EC_NewKey(current_ecparams, &ecpriv) != SECSuccess) { + fprintf(stderr, "Failed to generate new key\n"); + goto loser; + } + /* validate UIT generated public key */ + if (EC_ValidatePublicKey(current_ecparams, &ecpriv->publicValue) != + SECSuccess) { + fprintf(stderr, "generate key did not validate\n"); + goto loser; + } + /* output UIT public key */ + uit_len = ecpriv->publicValue.len; + if (uit_len % 2 == 0) { + fprintf(stderr, "generate key had invalid public value len\n"); + goto loser; + } + uit_len = (uit_len - 1) / 2; + if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) { + fprintf(stderr, "generate key was compressed\n"); + goto loser; + } + fputs("QeIUTx = ", ecdhresp); + to_hex_str(buf, &ecpriv->publicValue.data[1], uit_len); + fputs(buf, ecdhresp); + fputc('\n', ecdhresp); + fputs("QeIUTy = ", ecdhresp); + to_hex_str(buf, &ecpriv->publicValue.data[1 + uit_len], uit_len); + fputs(buf, ecdhresp); + fputc('\n', ecdhresp); + /* ECDH */ + if (ECDH_Derive(&pubkey, current_ecparams, &ecpriv->privateValue, + PR_FALSE, &ZZ) != SECSuccess) { + fprintf(stderr, "Derive failed\n"); + goto loser; + } + /* output hash of ZZ */ + if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) { + fprintf(stderr, "hash of derived key failed\n"); + goto loser; + } + SECITEM_FreeItem(&ZZ, PR_FALSE); + fputs("HashZZ = ", ecdhresp); + to_hex_str(buf, hashBuf, fips_hashLen(hash)); + fputs(buf, ecdhresp); + fputc('\n', ecdhresp); + fputc('\n', ecdhresp); + PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE); + ecpriv = NULL; + continue; + } + } +loser: + if (ecpriv != NULL) { + PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE); + } + for (i = 0; i < MAX_ECC_PARAMS; i++) { + if (ecparams[i] != NULL) { + PORT_FreeArena(ecparams[i]->arena, PR_FALSE); + ecparams[i] = NULL; + } + } + if (pubkey.data != NULL) { + PORT_Free(pubkey.data); + } + fclose(ecdhreq); +} + +#define MATCH_OPENSSL 1 +/* + * Perform the ECDH Validity Test. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ +void +ecdh_verify(char *reqfn, PRBool response) +{ + char buf[256]; /* holds one line from the input REQUEST file. + * needs to be large enough to hold the longest + * line "Qx = <144 hex digits>\n". + */ + FILE *ecdhreq; /* input stream from the REQUEST file */ + FILE *ecdhresp; /* output stream to the RESPONSE file */ + char curve[16]; /* "nistxddd" */ + unsigned char hashBuf[HASH_LENGTH_MAX]; + unsigned char cavsHashBuf[HASH_LENGTH_MAX]; + unsigned char private_data[MAX_ECKEY_LEN]; + ECParams *ecparams[MAX_ECC_PARAMS] = { NULL }; + ECParams *current_ecparams = NULL; + SECItem pubkey; + SECItem ZZ; + SECItem private_value; + unsigned int i; + unsigned int len = 0; + int current_curve = -1; + HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */ + + ecdhreq = fopen(reqfn, "r"); + ecdhresp = stdout; + strcpy(curve, "nist"); + pubkey.data = NULL; + while (fgets(buf, sizeof buf, ecdhreq) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') { + fputs(buf, ecdhresp); + continue; + } + if (buf[0] == '[') { + /* [Ex] */ + if (buf[1] == 'E' && buf[3] == ']') { + current_curve = buf[2] - 'A'; + fputs(buf, ecdhresp); + continue; + } + /* [Curve selected: x-nnn */ + if (strncmp(buf, "[Curve ", 7) == 0) { + const char *src; + char *dst; + SECItem *encodedparams; + + if ((current_curve < 0) || (current_curve > MAX_ECC_PARAMS)) { + fprintf(stderr, "No curve type defined\n"); + goto loser; + } + + src = &buf[1]; + /* skip passed the colon */ + while (*src && *src != ':') + src++; + if (*src != ':') { + fprintf(stderr, + "No colon in curve selected statement\n%s", buf); + goto loser; + } + src++; + /* skip to the first non-space */ + while (*src && *src == ' ') + src++; + dst = &curve[4]; + *dst++ = tolower(*src); + src += 2; /* skip the hyphen */ + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst = '\0'; + if (ecparams[current_curve] != NULL) { + PORT_FreeArena(ecparams[current_curve]->arena, PR_FALSE); + ecparams[current_curve] = NULL; + } + encodedparams = getECParams(curve); + if (encodedparams == NULL) { + fprintf(stderr, "Unknown curve %s.\n", curve); + goto loser; + } + if (EC_DecodeParams(encodedparams, &ecparams[current_curve]) != SECSuccess) { + fprintf(stderr, "Curve %s not supported.\n", curve); + goto loser; + } + SECITEM_FreeItem(encodedparams, PR_TRUE); + fputs(buf, ecdhresp); + continue; + } + /* [Ex - SHAxxx] */ + if (buf[1] == 'E' && buf[3] == ' ') { + const char *src; + current_curve = buf[2] - 'A'; + if ((current_curve < 0) || (current_curve > 256)) { + fprintf(stderr, "bad curve type defined (%c)\n", buf[2]); + goto loser; + } + current_ecparams = ecparams[current_curve]; + if (current_ecparams == NULL) { + fprintf(stderr, "no curve defined for type %c defined\n", + buf[2]); + goto loser; + } + /* skip passed the colon */ + src = &buf[1]; + while (*src && *src != '-') + src++; + if (*src != '-') { + fprintf(stderr, + "No data in curve selected statement\n%s", buf); + goto loser; + } + src++; + /* skip to the first non-space */ + while (*src && *src == ' ') + src++; + hash = hash_string_to_hashType(src); + if (hash == HASH_AlgNULL) { + fprintf(ecdhresp, "ERROR: Unable to find SHAAlg type"); + goto loser; + } + fputs(buf, ecdhresp); + continue; + } + fputs(buf, ecdhresp); + continue; + } + /* COUNT = ... */ + if (strncmp(buf, "COUNT", 5) == 0) { + fputs(buf, ecdhresp); + if (current_ecparams == NULL) { + fprintf(stderr, "no curve defined for type %c defined\n", + buf[2]); + goto loser; + } + len = (current_ecparams->fieldID.size + 7) >> 3; + if (pubkey.data != NULL) { + PORT_Free(pubkey.data); + pubkey.data = NULL; + } + SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(current_ecparams)); + if (pubkey.data == NULL) { + goto loser; + } + pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED; + continue; + } + /* QeCAVSx = ... */ + if (strncmp(buf, "QeCAVSx", 7) == 0) { + fputs(buf, ecdhresp); + i = 7; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + from_hex_str(&pubkey.data[1], len, &buf[i]); + continue; + } + /* QeCAVSy = ... */ + if (strncmp(buf, "QeCAVSy", 7) == 0) { + fputs(buf, ecdhresp); + i = 7; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + from_hex_str(&pubkey.data[1 + len], len, &buf[i]); + continue; + } + if (strncmp(buf, "deIUT", 5) == 0) { + fputs(buf, ecdhresp); + i = 5; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + from_hex_str(private_data, len, &buf[i]); + private_value.data = private_data; + private_value.len = len; + continue; + } + if (strncmp(buf, "QeIUTx", 6) == 0) { + fputs(buf, ecdhresp); + continue; + } + if (strncmp(buf, "QeIUTy", 6) == 0) { + fputs(buf, ecdhresp); + continue; + } + if (strncmp(buf, "CAVSHashZZ", 10) == 0) { + fputs(buf, ecdhresp); + i = 10; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + from_hex_str(cavsHashBuf, fips_hashLen(hash), &buf[i]); + if (current_ecparams == NULL) { + fprintf(stderr, "no curve defined for type defined\n"); + goto loser; + } + /* validate CAVS public key */ + if (EC_ValidatePublicKey(current_ecparams, &pubkey) != SECSuccess) { +#ifdef MATCH_OPENSSL + fprintf(ecdhresp, "Result = F\n"); +#else + fprintf(ecdhresp, "Result = F # key didn't validate\n"); +#endif + continue; + } + + /* ECDH */ + if (ECDH_Derive(&pubkey, current_ecparams, &private_value, + PR_FALSE, &ZZ) != SECSuccess) { + fprintf(stderr, "Derive failed\n"); + goto loser; + } +/* output ZZ */ +#ifndef MATCH_OPENSSL + fputs("Z = ", ecdhresp); + to_hex_str(buf, ZZ.data, ZZ.len); + fputs(buf, ecdhresp); + fputc('\n', ecdhresp); +#endif + + if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) { + fprintf(stderr, "hash of derived key failed\n"); + goto loser; + } + SECITEM_FreeItem(&ZZ, PR_FALSE); +#ifndef MATCH_NIST + fputs("IUTHashZZ = ", ecdhresp); + to_hex_str(buf, hashBuf, fips_hashLen(hash)); + fputs(buf, ecdhresp); + fputc('\n', ecdhresp); +#endif + if (memcmp(hashBuf, cavsHashBuf, fips_hashLen(hash)) != 0) { +#ifdef MATCH_OPENSSL + fprintf(ecdhresp, "Result = F\n"); +#else + fprintf(ecdhresp, "Result = F # hash doesn't match\n"); +#endif + } else { + fprintf(ecdhresp, "Result = P\n"); + } +#ifndef MATCH_OPENSSL + fputc('\n', ecdhresp); +#endif + continue; + } + } +loser: + for (i = 0; i < MAX_ECC_PARAMS; i++) { + if (ecparams[i] != NULL) { + PORT_FreeArena(ecparams[i]->arena, PR_FALSE); + ecparams[i] = NULL; + } + } + if (pubkey.data != NULL) { + PORT_Free(pubkey.data); + } + fclose(ecdhreq); +} + +/* + * Perform the DH Functional Test. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ +#define MAX_ECC_PARAMS 256 +void +dh_functional(char *reqfn, PRBool response) +{ + char buf[1024]; /* holds one line from the input REQUEST file. + * needs to be large enough to hold the longest + * line "YephCAVS = <512 hex digits>\n". + */ + FILE *dhreq; /* input stream from the REQUEST file */ + FILE *dhresp; /* output stream to the RESPONSE file */ + unsigned char hashBuf[HASH_LENGTH_MAX]; + DSAPrivateKey *dsapriv = NULL; + PQGParams pqg = { 0 }; + unsigned char pubkeydata[DSA_MAX_P_BITS / 8]; + SECItem pubkey; + SECItem ZZ; + unsigned int i, j; + unsigned int pgySize; + HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */ + + dhreq = fopen(reqfn, "r"); + dhresp = stdout; + while (fgets(buf, sizeof buf, dhreq) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') { + fputs(buf, dhresp); + continue; + } + if (buf[0] == '[') { + /* [Fx - SHAxxx] */ + if (buf[1] == 'F' && buf[3] == ' ') { + const char *src; + /* skip passed the colon */ + src = &buf[1]; + while (*src && *src != '-') + src++; + if (*src != '-') { + fprintf(stderr, "No hash specified\n%s", buf); + goto loser; + } + src++; + /* skip to the first non-space */ + while (*src && *src == ' ') + src++; + hash = hash_string_to_hashType(src); + if (hash == HASH_AlgNULL) { + fprintf(dhresp, "ERROR: Unable to find SHAAlg type"); + goto loser; + } + /* clear the PQG parameters */ + if (pqg.prime.data) { /* P */ + SECITEM_ZfreeItem(&pqg.prime, PR_FALSE); + } + if (pqg.subPrime.data) { /* Q */ + SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE); + } + if (pqg.base.data) { /* G */ + SECITEM_ZfreeItem(&pqg.base, PR_FALSE); + } + pgySize = DSA_MAX_P_BITS / 8; /* change if more key sizes are supported in CAVS */ + SECITEM_AllocItem(NULL, &pqg.prime, pgySize); + SECITEM_AllocItem(NULL, &pqg.base, pgySize); + pqg.prime.len = pqg.base.len = pgySize; + + /* set q to the max allows */ + SECITEM_AllocItem(NULL, &pqg.subPrime, DSA_MAX_Q_BITS / 8); + pqg.subPrime.len = DSA_MAX_Q_BITS / 8; + fputs(buf, dhresp); + continue; + } + fputs(buf, dhresp); + continue; + } + if (buf[0] == 'P') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j = 0; j < pqg.prime.len; i += 2, j++) { + if (!isxdigit(buf[i])) { + pqg.prime.len = j; + break; + } + hex_to_byteval(&buf[i], &pqg.prime.data[j]); + } + + fputs(buf, dhresp); + continue; + } + + /* Q = ... */ + if (buf[0] == 'Q') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j = 0; j < pqg.subPrime.len; i += 2, j++) { + if (!isxdigit(buf[i])) { + pqg.subPrime.len = j; + break; + } + hex_to_byteval(&buf[i], &pqg.subPrime.data[j]); + } + + fputs(buf, dhresp); + continue; + } + + /* G = ... */ + if (buf[0] == 'G') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j = 0; j < pqg.base.len; i += 2, j++) { + if (!isxdigit(buf[i])) { + pqg.base.len = j; + break; + } + hex_to_byteval(&buf[i], &pqg.base.data[j]); + } + + fputs(buf, dhresp); + continue; + } + + /* COUNT = ... */ + if (strncmp(buf, "COUNT", 5) == 0) { + fputs(buf, dhresp); + continue; + } + + /* YephemCAVS = ... */ + if (strncmp(buf, "YephemCAVS", 10) == 0) { + fputs(buf, dhresp); + i = 10; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + from_hex_str(pubkeydata, pqg.prime.len, &buf[i]); + pubkey.data = pubkeydata; + pubkey.len = pqg.prime.len; + + /* generate FCC key pair, nist uses pqg rather then pg, + * so use DSA to generate the key */ + if (DSA_NewKey(&pqg, &dsapriv) != SECSuccess) { + fprintf(stderr, "Failed to generate new key\n"); + goto loser; + } + fputs("XephemIUT = ", dhresp); + to_hex_str(buf, dsapriv->privateValue.data, dsapriv->privateValue.len); + fputs(buf, dhresp); + fputc('\n', dhresp); + fputs("YephemIUT = ", dhresp); + to_hex_str(buf, dsapriv->publicValue.data, dsapriv->publicValue.len); + fputs(buf, dhresp); + fputc('\n', dhresp); + /* DH */ + if (DH_Derive(&pubkey, &pqg.prime, &dsapriv->privateValue, + &ZZ, pqg.prime.len) != SECSuccess) { + fprintf(stderr, "Derive failed\n"); + goto loser; + } + /* output hash of ZZ */ + if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) { + fprintf(stderr, "hash of derived key failed\n"); + goto loser; + } + SECITEM_FreeItem(&ZZ, PR_FALSE); + fputs("HashZZ = ", dhresp); + to_hex_str(buf, hashBuf, fips_hashLen(hash)); + fputs(buf, dhresp); + fputc('\n', dhresp); + fputc('\n', dhresp); + PORT_FreeArena(dsapriv->params.arena, PR_TRUE); + dsapriv = NULL; + continue; + } + } +loser: + if (dsapriv != NULL) { + PORT_FreeArena(dsapriv->params.arena, PR_TRUE); + } + fclose(dhreq); +} + +#define MATCH_OPENSSL 1 +/* + * Perform the DH Validity Test. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ +void +dh_verify(char *reqfn, PRBool response) +{ + char buf[1024]; /* holds one line from the input REQUEST file. + * needs to be large enough to hold the longest + * line "YephCAVS = <512 hex digits>\n". + */ + FILE *dhreq; /* input stream from the REQUEST file */ + FILE *dhresp; /* output stream to the RESPONSE file */ + unsigned char hashBuf[HASH_LENGTH_MAX]; + unsigned char cavsHashBuf[HASH_LENGTH_MAX]; + PQGParams pqg = { 0 }; + unsigned char pubkeydata[DSA_MAX_P_BITS / 8]; + unsigned char privkeydata[DSA_MAX_P_BITS / 8]; + SECItem pubkey; + SECItem privkey; + SECItem ZZ; + unsigned int i, j; + unsigned int pgySize; + HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */ + + dhreq = fopen(reqfn, "r"); + dhresp = stdout; + while (fgets(buf, sizeof buf, dhreq) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') { + fputs(buf, dhresp); + continue; + } + if (buf[0] == '[') { + /* [Fx - SHAxxx] */ + if (buf[1] == 'F' && buf[3] == ' ') { + const char *src; + /* skip passed the colon */ + src = &buf[1]; + while (*src && *src != '-') + src++; + if (*src != '-') { + fprintf(stderr, "No hash specified\n%s", buf); + goto loser; + } + src++; + /* skip to the first non-space */ + while (*src && *src == ' ') + src++; + hash = hash_string_to_hashType(src); + if (hash == HASH_AlgNULL) { + fprintf(dhresp, "ERROR: Unable to find SHAAlg type"); + goto loser; + } + /* clear the PQG parameters */ + if (pqg.prime.data) { /* P */ + SECITEM_ZfreeItem(&pqg.prime, PR_FALSE); + } + if (pqg.subPrime.data) { /* Q */ + SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE); + } + if (pqg.base.data) { /* G */ + SECITEM_ZfreeItem(&pqg.base, PR_FALSE); + } + pgySize = DSA_MAX_P_BITS / 8; /* change if more key sizes are supported in CAVS */ + SECITEM_AllocItem(NULL, &pqg.prime, pgySize); + SECITEM_AllocItem(NULL, &pqg.base, pgySize); + pqg.prime.len = pqg.base.len = pgySize; + + /* set q to the max allows */ + SECITEM_AllocItem(NULL, &pqg.subPrime, DSA_MAX_Q_BITS / 8); + pqg.subPrime.len = DSA_MAX_Q_BITS / 8; + fputs(buf, dhresp); + continue; + } + fputs(buf, dhresp); + continue; + } + if (buf[0] == 'P') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j = 0; j < pqg.prime.len; i += 2, j++) { + if (!isxdigit(buf[i])) { + pqg.prime.len = j; + break; + } + hex_to_byteval(&buf[i], &pqg.prime.data[j]); + } + + fputs(buf, dhresp); + continue; + } + + /* Q = ... */ + if (buf[0] == 'Q') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j = 0; j < pqg.subPrime.len; i += 2, j++) { + if (!isxdigit(buf[i])) { + pqg.subPrime.len = j; + break; + } + hex_to_byteval(&buf[i], &pqg.subPrime.data[j]); + } + + fputs(buf, dhresp); + continue; + } + + /* G = ... */ + if (buf[0] == 'G') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j = 0; j < pqg.base.len; i += 2, j++) { + if (!isxdigit(buf[i])) { + pqg.base.len = j; + break; + } + hex_to_byteval(&buf[i], &pqg.base.data[j]); + } + + fputs(buf, dhresp); + continue; + } + + /* COUNT = ... */ + if (strncmp(buf, "COUNT", 5) == 0) { + fputs(buf, dhresp); + continue; + } + + /* YephemCAVS = ... */ + if (strncmp(buf, "YephemCAVS", 10) == 0) { + fputs(buf, dhresp); + i = 10; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + from_hex_str(pubkeydata, pqg.prime.len, &buf[i]); + pubkey.data = pubkeydata; + pubkey.len = pqg.prime.len; + continue; + } + /* XephemUIT = ... */ + if (strncmp(buf, "XephemIUT", 9) == 0) { + fputs(buf, dhresp); + i = 9; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + from_hex_str(privkeydata, pqg.subPrime.len, &buf[i]); + privkey.data = privkeydata; + privkey.len = pqg.subPrime.len; + continue; + } + /* YephemUIT = ... */ + if (strncmp(buf, "YephemIUT", 9) == 0) { + fputs(buf, dhresp); + continue; + } + /* CAVSHashZZ = ... */ + if (strncmp(buf, "CAVSHashZZ", 10) == 0) { + fputs(buf, dhresp); + i = 10; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + from_hex_str(cavsHashBuf, fips_hashLen(hash), &buf[i]); + /* do the DH operation*/ + if (DH_Derive(&pubkey, &pqg.prime, &privkey, + &ZZ, pqg.prime.len) != SECSuccess) { + fprintf(stderr, "Derive failed\n"); + goto loser; + } +/* output ZZ */ +#ifndef MATCH_OPENSSL + fputs("Z = ", dhresp); + to_hex_str(buf, ZZ.data, ZZ.len); + fputs(buf, dhresp); + fputc('\n', dhresp); +#endif + if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) { + fprintf(stderr, "hash of derived key failed\n"); + goto loser; + } + SECITEM_FreeItem(&ZZ, PR_FALSE); +#ifndef MATCH_NIST_ + fputs("IUTHashZZ = ", dhresp); + to_hex_str(buf, hashBuf, fips_hashLen(hash)); + fputs(buf, dhresp); + fputc('\n', dhresp); +#endif + if (memcmp(hashBuf, cavsHashBuf, fips_hashLen(hash)) != 0) { + fprintf(dhresp, "Result = F\n"); + } else { + fprintf(dhresp, "Result = P\n"); + } +#ifndef MATCH_OPENSSL + fputc('\n', dhresp); +#endif + continue; + } + } +loser: + fclose(dhreq); +} + PRBool isblankline(char *b) { @@ -5342,17 +6278,8 @@ rsa_siggen_test(char *reqfn) i++; } /* set the SHA Algorithm */ - if (strncmp(&buf[i], "SHA1", 4) == 0) { - shaAlg = HASH_AlgSHA1; - } else if (strncmp(&buf[i], "SHA224", 6) == 0) { - shaAlg = HASH_AlgSHA224; - } else if (strncmp(&buf[i], "SHA256", 6) == 0) { - shaAlg = HASH_AlgSHA256; - } else if (strncmp(&buf[i], "SHA384", 6) == 0) { - shaAlg = HASH_AlgSHA384; - } else if (strncmp(&buf[i], "SHA512", 6) == 0) { - shaAlg = HASH_AlgSHA512; - } else { + shaAlg = hash_string_to_hashType(&buf[i]); + if (shaAlg == HASH_AlgNULL) { fprintf(rsaresp, "ERROR: Unable to find SHAAlg type"); goto loser; } @@ -5537,17 +6464,8 @@ rsa_sigver_test(char *reqfn) i++; } /* set the SHA Algorithm */ - if (strncmp(&buf[i], "SHA1", 4) == 0) { - shaAlg = HASH_AlgSHA1; - } else if (strncmp(&buf[i], "SHA224", 6) == 0) { - shaAlg = HASH_AlgSHA224; - } else if (strncmp(&buf[i], "SHA256", 6) == 0) { - shaAlg = HASH_AlgSHA256; - } else if (strncmp(&buf[i], "SHA384", 6) == 0) { - shaAlg = HASH_AlgSHA384; - } else if (strncmp(&buf[i], "SHA512", 6) == 0) { - shaAlg = HASH_AlgSHA512; - } else { + shaAlg = hash_string_to_hashType(&buf[i]); + if (shaAlg == HASH_AlgNULL) { fprintf(rsaresp, "ERROR: Unable to find SHAAlg type"); goto loser; } @@ -6108,6 +7026,34 @@ main(int argc, char **argv) ecdsa_sigver_test(argv[3]); } /*************/ + /* ECDH */ + /*************/ + } else if (strcmp(argv[1], "ecdh") == 0) { + /* argv[2]={init|resp}-{func|verify} argv[3]=.req */ + if (strcmp(argv[2], "init-func") == 0) { + ecdh_functional(argv[3], 0); + } else if (strcmp(argv[2], "resp-func") == 0) { + ecdh_functional(argv[3], 1); + } else if (strcmp(argv[2], "init-verify") == 0) { + ecdh_verify(argv[3], 0); + } else if (strcmp(argv[2], "resp-verify") == 0) { + ecdh_verify(argv[3], 1); + } + /*************/ + /* DH */ + /*************/ + } else if (strcmp(argv[1], "dh") == 0) { + /* argv[2]={init|resp}-{func|verify} argv[3]=.req */ + if (strcmp(argv[2], "init-func") == 0) { + dh_functional(argv[3], 0); + } else if (strcmp(argv[2], "resp-func") == 0) { + dh_functional(argv[3], 1); + } else if (strcmp(argv[2], "init-verify") == 0) { + dh_verify(argv[3], 0); + } else if (strcmp(argv[2], "resp-verify") == 0) { + dh_verify(argv[3], 1); + } + /*************/ /* RNG */ /*************/ } else if (strcmp(argv[1], "rng") == 0) { diff --git a/security/nss/cmd/fipstest/kas.sh b/security/nss/cmd/fipstest/kas.sh new file mode 100644 index 000000000..9aa5387a8 --- /dev/null +++ b/security/nss/cmd/fipstest/kas.sh @@ -0,0 +1,84 @@ +#!/bin/sh +# +# 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/. +# +# A Bourne shell script for running the NIST DSA Validation System +# +# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment +# variables appropriately so that the fipstest command and the NSPR and NSS +# shared libraries/DLLs are on the search path. Then run this script in the +# directory where the REQUEST (.req) files reside. The script generates the +# RESPONSE (.rsp) files in the same directory. +BASEDIR=${1-.} +TESTDIR=${BASEDIR}/KAS +COMMAND=${2-run} +REQDIR=${TESTDIR}/req +RSPDIR=${TESTDIR}/resp + + +# +if [ ${COMMAND} = "verify" ]; then +# +# need verify for KAS tests + +# verify generated keys +# name=KeyPair +# echo ">>>>> $name" +# fipstest dsa keyver ${RSPDIR}/$name.rsp | grep ^Result.=.F +# verify generated pqg values +# name=PQGGen +# echo ">>>>> $name" +# fipstest dsa pqgver ${RSPDIR}/$name.rsp | grep ^Result.=.F +# verify PQGVer with known answer +# sh ./validate1.sh ${TESTDIR} PQGVer.req ' ' '-e /^Result.=.F/s;.(.*);; -e /^Result.=.P/s;.(.*);;' +# verify signatures +# name=SigGen +# echo ">>>>> $name" +# fipstest dsa sigver ${RSPDIR}/$name.rsp | grep ^Result.=.F +# verify SigVer with known answer +# sh ./validate1.sh ${TESTDIR} SigVer.req ' ' '-e /^X.=/d -e /^Result.=.F/s;.(.*);;' + exit 0 +fi + +request=KASFunctionTest_ECCEphemeralUnified_NOKC_ZZOnly_init.req +response=`echo $request | sed -e "s/req/rsp/"` +echo $request $response +fipstest ecdh init-func ${REQDIR}/$request > ${RSPDIR}/$response + +request=KASFunctionTest_ECCEphemeralUnified_NOKC_ZZOnly_resp.req +response=`echo $request | sed -e "s/req/rsp/"` +echo $request $response +fipstest ecdh resp-func ${REQDIR}/$request > ${RSPDIR}/$response + +request=KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_init.req +response=`echo $request | sed -e "s/req/rsp/"` +echo $request $response +fipstest ecdh init-verify ${REQDIR}/$request > ${RSPDIR}/$response + +request=KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_resp.req +response=`echo $request | sed -e "s/req/rsp/"` +echo $request $response +fipstest ecdh resp-verify ${REQDIR}/$request > ${RSPDIR}/$response + +request=KASFunctionTest_FFCEphem_NOKC_ZZOnly_init.req +response=`echo $request | sed -e "s/req/rsp/"` +echo $request $response +fipstest dh init-func ${REQDIR}/$request > ${RSPDIR}/$response + +request=KASFunctionTest_FFCEphem_NOKC_ZZOnly_resp.req +response=`echo $request | sed -e "s/req/rsp/"` +echo $request $response +fipstest dh resp-func ${REQDIR}/$request > ${RSPDIR}/$response + +request=KASValidityTest_FFCEphem_NOKC_ZZOnly_init.req +response=`echo $request | sed -e "s/req/rsp/"` +echo $request $response +fipstest dh init-verify ${REQDIR}/$request > ${RSPDIR}/$response + +request=KASValidityTest_FFCEphem_NOKC_ZZOnly_resp.req +response=`echo $request | sed -e "s/req/rsp/"` +echo $request $response +fipstest dh resp-verify ${REQDIR}/$request > ${RSPDIR}/$response + diff --git a/security/nss/cmd/fipstest/runtest.sh b/security/nss/cmd/fipstest/runtest.sh index 5f8e66a08..fcb16348b 100644 --- a/security/nss/cmd/fipstest/runtest.sh +++ b/security/nss/cmd/fipstest/runtest.sh @@ -6,7 +6,7 @@ # TESTDIR=${1-.} COMMAND=${2-run} -TESTS="aes aesgcm dsa ecdsa hmac tls rng rsa sha tdea" +TESTS="aes aesgcm dsa ecdsa hmac kas tls rng rsa sha tdea" for i in $TESTS do echo "********************Running $i tests" 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..97c7f750a 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); @@ -3799,7 +3799,7 @@ SECU_ParseSSLVersionRangeString(const char *input, return SECSuccess; } -SSLNamedGroup +static SSLNamedGroup groupNameToNamedGroup(char *name) { if (PL_strlen(name) == 4) { @@ -3837,6 +3837,23 @@ groupNameToNamedGroup(char *name) return ssl_grp_none; } +static SECStatus +countItems(const char *arg, unsigned int *numItems) +{ + char *str = PORT_Strdup(arg); + if (!str) { + return SECFailure; + } + char *p = strtok(str, ","); + while (p) { + ++(*numItems); + p = strtok(NULL, ","); + } + PORT_Free(str); + str = NULL; + return SECSuccess; +} + SECStatus parseGroupList(const char *arg, SSLNamedGroup **enabledGroups, unsigned int *enabledGroupsCount) @@ -3847,21 +3864,12 @@ parseGroupList(const char *arg, SSLNamedGroup **enabledGroups, unsigned int numValues = 0; unsigned int count = 0; - /* Count the number of groups. */ - str = PORT_Strdup(arg); - if (!str) { + if (countItems(arg, &numValues) != SECSuccess) { return SECFailure; } - p = strtok(str, ","); - while (p) { - ++numValues; - p = strtok(NULL, ","); - } - PORT_Free(str); - str = NULL; groups = PORT_ZNewArray(SSLNamedGroup, numValues); if (!groups) { - goto done; + return SECFailure; } /* Get group names. */ @@ -3881,9 +3889,7 @@ parseGroupList(const char *arg, SSLNamedGroup **enabledGroups, } done: - if (str) { - PORT_Free(str); - } + PORT_Free(str); if (!count) { PORT_Free(groups); return SECFailure; @@ -3893,3 +3899,83 @@ done: *enabledGroups = groups; return SECSuccess; } + +SSLSignatureScheme +schemeNameToScheme(const char *name) +{ +#define compareScheme(x) \ + do { \ + if (!PORT_Strncmp(name, #x, PORT_Strlen(#x))) { \ + return ssl_sig_##x; \ + } \ + } while (0) + + compareScheme(rsa_pkcs1_sha1); + compareScheme(rsa_pkcs1_sha256); + compareScheme(rsa_pkcs1_sha384); + compareScheme(rsa_pkcs1_sha512); + compareScheme(ecdsa_sha1); + compareScheme(ecdsa_secp256r1_sha256); + compareScheme(ecdsa_secp384r1_sha384); + compareScheme(ecdsa_secp521r1_sha512); + compareScheme(rsa_pss_rsae_sha256); + compareScheme(rsa_pss_rsae_sha384); + compareScheme(rsa_pss_rsae_sha512); + compareScheme(ed25519); + compareScheme(ed448); + compareScheme(rsa_pss_pss_sha256); + compareScheme(rsa_pss_pss_sha384); + compareScheme(rsa_pss_pss_sha512); + compareScheme(dsa_sha1); + compareScheme(dsa_sha256); + compareScheme(dsa_sha384); + compareScheme(dsa_sha512); + +#undef compareScheme + + return ssl_sig_none; +} + +SECStatus +parseSigSchemeList(const char *arg, const SSLSignatureScheme **enabledSigSchemes, + unsigned int *enabledSigSchemeCount) +{ + SSLSignatureScheme *schemes; + unsigned int numValues = 0; + unsigned int count = 0; + + if (countItems(arg, &numValues) != SECSuccess) { + return SECFailure; + } + schemes = PORT_ZNewArray(SSLSignatureScheme, numValues); + if (!schemes) { + return SECFailure; + } + + /* Get group names. */ + char *str = PORT_Strdup(arg); + if (!str) { + goto done; + } + char *p = strtok(str, ","); + while (p) { + SSLSignatureScheme scheme = schemeNameToScheme(p); + if (scheme == ssl_sig_none) { + count = 0; + goto done; + } + schemes[count++] = scheme; + p = strtok(NULL, ","); + } + +done: + PORT_Free(str); + if (!count) { + PORT_Free(schemes); + return SECFailure; + } + + *enabledSigSchemeCount = count; + *enabledSigSchemes = schemes; + return SECSuccess; +} diff --git a/security/nss/cmd/lib/secutil.h b/security/nss/cmd/lib/secutil.h index fe07aca60..ed3372c14 100644 --- a/security/nss/cmd/lib/secutil.h +++ b/security/nss/cmd/lib/secutil.h @@ -406,7 +406,9 @@ SECU_ParseSSLVersionRangeString(const char *input, SECStatus parseGroupList(const char *arg, SSLNamedGroup **enabledGroups, unsigned int *enabledGroupsCount); -SSLNamedGroup groupNameToNamedGroup(char *name); +SECStatus parseSigSchemeList(const char *arg, + const SSLSignatureScheme **enabledSigSchemes, + unsigned int *enabledSigSchemeCount); /* * 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/manifest.mn b/security/nss/cmd/manifest.mn index 567c6bb9d..be53d3c4e 100644 --- a/security/nss/cmd/manifest.mn +++ b/security/nss/cmd/manifest.mn @@ -47,6 +47,7 @@ NSS_SRCDIRS = \ listsuites \ makepqg \ multinit \ + nss-policy-check \ ocspclnt \ ocspresp \ oidcalc \ 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/nss-policy-check/Makefile b/security/nss/cmd/nss-policy-check/Makefile new file mode 100644 index 000000000..6e1d4ecdf --- /dev/null +++ b/security/nss/cmd/nss-policy-check/Makefile @@ -0,0 +1,47 @@ +#! gmake +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +include ../platlibs.mk + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + +include ../platrules.mk + diff --git a/security/nss/cmd/nss-policy-check/manifest.mn b/security/nss/cmd/nss-policy-check/manifest.mn new file mode 100644 index 000000000..8fb9abf00 --- /dev/null +++ b/security/nss/cmd/nss-policy-check/manifest.mn @@ -0,0 +1,15 @@ +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +CORE_DEPTH = ../.. + +MODULE = nss + +CSRCS = nss-policy-check.c + +REQUIRES = seccmd + +PROGRAM = nss-policy-check + diff --git a/security/nss/cmd/nss-policy-check/nss-policy-check.c b/security/nss/cmd/nss-policy-check/nss-policy-check.c new file mode 100644 index 000000000..b83003874 --- /dev/null +++ b/security/nss/cmd/nss-policy-check/nss-policy-check.c @@ -0,0 +1,206 @@ +/* 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 program can be used to check the validity of a NSS crypto policy + * configuration file, specified using a config= line. + * + * Exit codes: + * failure: 2 + * warning: 1 + * success: 0 + */ + +#include +#include +#include +#include "utilparst.h" +#include "nss.h" +#include "secport.h" +#include "secutil.h" +#include "secmod.h" +#include "ssl.h" +#include "prenv.h" + +const char *sWarn = "WARN"; +const char *sInfo = "INFO"; + +void +get_tls_info(SSLProtocolVariant protocolVariant, const char *display) +{ + SSLVersionRange vrange_supported, vrange_enabled; + unsigned num_enabled = 0; + PRBool failed = PR_FALSE; + + /* We assume SSL v2 is inactive, and therefore SSL_VersionRangeGetDefault + * gives complete information. */ + if ((SSL_VersionRangeGetSupported(protocolVariant, &vrange_supported) != SECSuccess) || + (SSL_VersionRangeGetDefault(protocolVariant, &vrange_enabled) != SECSuccess) || + !vrange_enabled.min || + !vrange_enabled.max || + vrange_enabled.max < vrange_supported.min || + vrange_enabled.min > vrange_supported.max) { + failed = PR_TRUE; + } else { + if (vrange_enabled.min < vrange_supported.min) { + vrange_enabled.min = vrange_supported.min; + } + if (vrange_enabled.max > vrange_supported.max) { + vrange_enabled.max = vrange_supported.max; + } + if (vrange_enabled.min > vrange_enabled.max) { + failed = PR_TRUE; + } + } + if (failed) { + num_enabled = 0; + } else { + num_enabled = vrange_enabled.max - vrange_enabled.min + 1; + } + fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-%s-VERSIONS: %u\n", + num_enabled ? sInfo : sWarn, display, num_enabled); + if (!num_enabled) { + PR_SetEnv("NSS_POLICY_WARN=1"); + } +} + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +int +main(int argc, char **argv) +{ + const PRUint16 *cipherSuites = SSL_ImplementedCiphers; + int i; + SECStatus rv; + SECMODModule *module = NULL; + char path[PATH_MAX]; + const char *filename; + char moduleSpec[1024 + PATH_MAX]; + unsigned num_enabled = 0; + int result = 0; + int fullPathLen; + + if (argc != 2) { + fprintf(stderr, "Syntax: nss-policy-check \n"); + result = 2; + goto loser_no_shutdown; + } + + fullPathLen = strlen(argv[1]); + + if (!fullPathLen || PR_Access(argv[1], PR_ACCESS_READ_OK) != PR_SUCCESS) { + fprintf(stderr, "Error: cannot read file %s\n", argv[1]); + result = 2; + goto loser_no_shutdown; + } + + if (fullPathLen >= PATH_MAX) { + fprintf(stderr, "Error: filename parameter is too long\n"); + result = 2; + goto loser_no_shutdown; + } + + path[0] = 0; + filename = argv[1] + fullPathLen - 1; + while ((filename > argv[1]) && (*filename != NSSUTIL_PATH_SEPARATOR[0])) { + filename--; + } + + if (filename == argv[1]) { + PORT_Strcpy(path, "."); + } else { + filename++; /* Go past the path separator. */ + PORT_Strncat(path, argv[1], (filename - argv[1])); + } + + PR_SetEnv("NSS_IGNORE_SYSTEM_POLICY=1"); + rv = NSS_NoDB_Init(NULL); + if (rv != SECSuccess) { + fprintf(stderr, "NSS_Init failed: %s\n", PORT_ErrorToString(PR_GetError())); + result = 2; + goto loser_no_shutdown; + } + + PR_SetEnv("NSS_POLICY_LOADED=0"); + PR_SetEnv("NSS_POLICY_FAIL=0"); + PR_SetEnv("NSS_POLICY_WARN=0"); + + sprintf(moduleSpec, + "name=\"Policy File\" " + "parameters=\"configdir='sql:%s' " + "secmod='%s' " + "flags=readOnly,noCertDB,forceSecmodChoice,forceOpen\" " + "NSS=\"flags=internal,moduleDB,skipFirst,moduleDBOnly,critical,printPolicyFeedback\"", + path, filename); + + module = SECMOD_LoadModule(moduleSpec, NULL, PR_TRUE); + if (!module || !module->loaded || atoi(PR_GetEnvSecure("NSS_POLICY_LOADED")) != 1) { + fprintf(stderr, "Error: failed to load policy file\n"); + result = 2; + goto loser; + } + + rv = SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE); + if (rv != SECSuccess) { + fprintf(stderr, "enable SSL_SECURITY failed: %s\n", PORT_ErrorToString(PR_GetError())); + result = 2; + goto loser; + } + + for (i = 0; i < SSL_NumImplementedCiphers; i++) { + PRUint16 suite = cipherSuites[i]; + PRBool enabled; + SSLCipherSuiteInfo info; + + rv = SSL_CipherPrefGetDefault(suite, &enabled); + if (rv != SECSuccess) { + fprintf(stderr, + "SSL_CipherPrefGetDefault didn't like value 0x%04x (i = %d): %s\n", + suite, i, PORT_ErrorToString(PR_GetError())); + continue; + } + rv = SSL_GetCipherSuiteInfo(suite, &info, (int)(sizeof info)); + if (rv != SECSuccess) { + fprintf(stderr, + "SSL_GetCipherSuiteInfo didn't like value 0x%04x (i = %d): %s\n", + suite, i, PORT_ErrorToString(PR_GetError())); + continue; + } + if (enabled) { + ++num_enabled; + fprintf(stderr, "NSS-POLICY-INFO: ciphersuite %s is enabled\n", info.cipherSuiteName); + } + } + fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-CIPHERSUITES: %u\n", num_enabled ? sInfo : sWarn, num_enabled); + if (!num_enabled) { + PR_SetEnv("NSS_POLICY_WARN=1"); + } + + get_tls_info(ssl_variant_stream, "TLS"); + get_tls_info(ssl_variant_datagram, "DTLS"); + + if (atoi(PR_GetEnvSecure("NSS_POLICY_FAIL")) != 0) { + result = 2; + } else if (atoi(PR_GetEnvSecure("NSS_POLICY_WARN")) != 0) { + result = 1; + } + +loser: + if (module) { + SECMOD_DestroyModule(module); + } + rv = NSS_Shutdown(); + if (rv != SECSuccess) { + fprintf(stderr, "NSS_Shutdown failed: %s\n", PORT_ErrorToString(PR_GetError())); + result = 2; + } +loser_no_shutdown: + if (result == 2) { + fprintf(stderr, "NSS-POLICY-FAIL\n"); + } else if (result == 1) { + fprintf(stderr, "NSS-POLICY-WARN\n"); + } + return result; +} diff --git a/security/nss/cmd/nss-policy-check/nss-policy-check.gyp b/security/nss/cmd/nss-policy-check/nss-policy-check.gyp new file mode 100644 index 000000000..877a5bc06 --- /dev/null +++ b/security/nss/cmd/nss-policy-check/nss-policy-check.gyp @@ -0,0 +1,24 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +{ + 'includes': [ + '../../coreconf/config.gypi', + '../../cmd/platlibs.gypi' + ], + 'targets': [ + { + 'target_name': 'nss-policy-check', + 'type': 'executable', + 'sources': [ + 'nss-policy-check.c' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports' + ] + } + ], + 'variables': { + 'module': 'nss' + } +} \ No newline at end of file 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 ]\n", - program_name); + progname); PR_fprintf(pr_stderr, "\t%s -P [-d ]\n", - program_name); + progname); PR_fprintf(pr_stderr, "\t%s -r [-a] [-L] [-s ] [-d ]\n", - program_name); + progname); PR_fprintf(pr_stderr, "\t%s -R [-a] [-l ] [-s ] [-d ]\n", - program_name); + progname); PR_fprintf(pr_stderr, "\t%s -S [-a] [-l -t ]\n", - program_name); + progname); PR_fprintf(pr_stderr, "\t\t [-s ] [-w