diff options
author | Martin Thomson <martin.thomson@gmail.com> | 2018-08-15 12:56:12 +1000 |
---|---|---|
committer | Martin Thomson <martin.thomson@gmail.com> | 2018-08-15 12:56:12 +1000 |
commit | 62a0a8ecbec00412349fed423496368e6aeca470 (patch) | |
tree | 52c326804b975b428a9b530904f381e66bf8cdb5 | |
parent | 218053ef9a6e7bf0d2e1f71efe404aead08221f7 (diff) | |
download | nss-hg-62a0a8ecbec00412349fed423496368e6aeca470.tar.gz |
Bug 1482747 - Options for controlling signature scheme in tstclnt/selfserv, r=franziskus
-rw-r--r-- | cmd/lib/secutil.c | 116 | ||||
-rw-r--r-- | cmd/lib/secutil.h | 4 | ||||
-rw-r--r-- | cmd/selfserv/selfserv.c | 33 | ||||
-rw-r--r-- | cmd/tstclnt/tstclnt.c | 85 |
4 files changed, 210 insertions, 28 deletions
diff --git a/cmd/lib/secutil.c b/cmd/lib/secutil.c index 6be2df432..97c7f750a 100644 --- a/cmd/lib/secutil.c +++ b/cmd/lib/secutil.c @@ -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/cmd/lib/secutil.h b/cmd/lib/secutil.h index fe07aca60..ed3372c14 100644 --- a/cmd/lib/secutil.h +++ b/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/cmd/selfserv/selfserv.c b/cmd/selfserv/selfserv.c index c372ec9b8..9e632419f 100644 --- a/cmd/selfserv/selfserv.c +++ b/cmd/selfserv/selfserv.c @@ -165,9 +165,8 @@ PrintUsageHeader(const char *progName) " [-f password_file] [-L [seconds]] [-M maxProcs] [-P dbprefix]\n" " [-V [min-version]:[max-version]] [-a sni_name]\n" " [ T <good|revoked|unknown|badsig|corrupted|none|ocsp>] [-A ca]\n" - " [-C SSLCacheEntries] [-S dsa_nickname] -Q [-I groups]" - " [-e ec_nickname]" - "\n" + " [-C SSLCacheEntries] [-S dsa_nickname] [-Q]\n" + " [-I groups] [-J signatureschemes] [-e ec_nickname]\n" " -U [0|1] -H [0|1|2] -W [0|1]\n" "\n", progName); @@ -228,6 +227,13 @@ PrintParameterUsage() "-I comma separated list of enabled groups for TLS key exchange.\n" " The following values are valid:\n" " P256, P384, P521, x25519, FF2048, FF3072, FF4096, FF6144, FF8192\n" + "-J comma separated list of enabled signature schemes in preference order.\n" + " The following values are valid:\n" + " rsa_pkcs1_sha1, rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha512,\n" + " ecdsa_sha1, ecdsa_secp256r1_sha256, ecdsa_secp384r1_sha384,\n" + " ecdsa_secp521r1_sha512,\n" + " rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512,\n" + " rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512,\n" "-Z enable 0-RTT (for TLS 1.3; also use -u)\n", stderr); } @@ -802,6 +808,8 @@ PRBool zeroRTT = PR_FALSE; PRBool enableALPN = PR_FALSE; SSLNamedGroup *enabledGroups = NULL; unsigned int enabledGroupsCount = 0; +const SSLSignatureScheme *enabledSigSchemes = NULL; +unsigned int enabledSigSchemeCount = 0; static char *virtServerNameArray[MAX_VIRT_SERVER_NAME_ARRAY_INDEX]; static int virtServerNameIndex = 1; @@ -1970,6 +1978,13 @@ server_main( } } + if (enabledSigSchemes) { + rv = SSL_SignatureSchemePrefSet(model_sock, enabledSigSchemes, enabledSigSchemeCount); + if (rv < 0) { + errExit("SSL_SignatureSchemePrefSet failed"); + } + } + /* This cipher is not on by default. The Acceptance test * would like it to be. Turn this cipher on. */ @@ -2216,7 +2231,7 @@ main(int argc, char **argv) ** XXX: 'B', 'E', 'q', and 'x' were used in the past but removed ** in 3.28, please leave some time before resuing those. */ optstate = PL_CreateOptState(argc, argv, - "2:A:C:DGH:I:L:M:NP:QRS:T:U:V:W:YZa:bc:d:e:f:g:hi:jk:lmn:op:rst:uvw:yz"); + "2:A:C:DGH:I:J:L:M:NP:QRS:T:U:V:W:YZa:bc:d:e:f:g:hi:jk:lmn:op:rst:uvw:yz"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { ++optionsFound; switch (optstate->option) { @@ -2451,6 +2466,16 @@ main(int argc, char **argv) } break; + case 'J': + rv = parseSigSchemeList(optstate->value, &enabledSigSchemes, &enabledSigSchemeCount); + if (rv != SECSuccess) { + PL_DestroyOptState(optstate); + fprintf(stderr, "Bad signature scheme specified.\n"); + fprintf(stderr, "Run '%s -h' for usage information.\n", progName); + exit(5); + } + break; + default: case '?': fprintf(stderr, "Unrecognized or bad option specified.\n"); diff --git a/cmd/tstclnt/tstclnt.c b/cmd/tstclnt/tstclnt.c index 6f5a43146..97c49f9a1 100644 --- a/cmd/tstclnt/tstclnt.c +++ b/cmd/tstclnt/tstclnt.c @@ -106,6 +106,45 @@ secuPWData pwdata = { PW_NONE, 0 }; SSLNamedGroup *enabledGroups = NULL; unsigned int enabledGroupsCount = 0; +const SSLSignatureScheme *enabledSigSchemes = NULL; +unsigned int enabledSigSchemeCount = 0; + +const char * +signatureSchemeName(SSLSignatureScheme scheme) +{ + switch (scheme) { +#define strcase(x) \ + case ssl_sig_##x: \ + return #x + strcase(none); + strcase(rsa_pkcs1_sha1); + strcase(rsa_pkcs1_sha256); + strcase(rsa_pkcs1_sha384); + strcase(rsa_pkcs1_sha512); + strcase(ecdsa_sha1); + strcase(ecdsa_secp256r1_sha256); + strcase(ecdsa_secp384r1_sha384); + strcase(ecdsa_secp521r1_sha512); + strcase(rsa_pss_rsae_sha256); + strcase(rsa_pss_rsae_sha384); + strcase(rsa_pss_rsae_sha512); + strcase(ed25519); + strcase(ed448); + strcase(rsa_pss_pss_sha256); + strcase(rsa_pss_pss_sha384); + strcase(rsa_pss_pss_sha512); + strcase(dsa_sha1); + strcase(dsa_sha256); + strcase(dsa_sha384); + strcase(dsa_sha512); +#undef strcase + case ssl_sig_rsa_pkcs1_sha1md5: + return "RSA PKCS#1 SHA1+MD5"; + default: + break; + } + return "Unknown Scheme"; +} void printSecurityInfo(PRFileDesc *fd) @@ -132,11 +171,13 @@ printSecurityInfo(PRFileDesc *fd) suite.macBits, suite.macAlgorithmName); FPRINTF(stderr, "tstclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n" - " Compression: %s, Extended Master Secret: %s\n", + " Compression: %s, Extended Master Secret: %s\n" + " Signature Scheme: %s\n", channel.authKeyBits, suite.authAlgorithmName, channel.keaKeyBits, suite.keaTypeName, channel.compressionMethodName, - channel.extendedMasterSecretUsed ? "Yes" : "No"); + channel.extendedMasterSecretUsed ? "Yes" : "No", + signatureSchemeName(channel.signatureScheme)); } } cert = SSL_RevealCert(fd); @@ -178,11 +219,12 @@ PrintUsageHeader() { fprintf(stderr, "Usage: %s -h host [-a 1st_hs_name ] [-a 2nd_hs_name ] [-p port]\n" - "[-D | -d certdir] [-C] [-b | -R root-module] \n" - "[-n nickname] [-Bafosvx] [-c ciphers] [-Y] [-Z]\n" - "[-V [min-version]:[max-version]] [-K] [-T] [-U]\n" - "[-r N] [-w passwd] [-W pwfile] [-q [-t seconds]] [-I groups]\n" - "[-A requestfile] [-L totalconnections] [-P {client,server}] [-Q]\n" + " [-D | -d certdir] [-C] [-b | -R root-module] \n" + " [-n nickname] [-Bafosvx] [-c ciphers] [-Y] [-Z]\n" + " [-V [min-version]:[max-version]] [-K] [-T] [-U]\n" + " [-r N] [-w passwd] [-W pwfile] [-q [-t seconds]]\n" + " [-I groups] [-J signatureschemes]\n" + " [-A requestfile] [-L totalconnections] [-P {client,server}] [-Q]\n" "\n", progName); } @@ -255,6 +297,15 @@ PrintParameterUsage() "%-20s The following values are valid:\n" "%-20s P256, P384, P521, x25519, FF2048, FF3072, FF4096, FF6144, FF8192\n", "-I", "", ""); + fprintf(stderr, "%-20s Comma separated list of signature schemes in preference order.\n" + "%-20s The following values are valid:\n" + "%-20s rsa_pkcs1_sha1, rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha512,\n" + "%-20s ecdsa_sha1, ecdsa_secp256r1_sha256, ecdsa_secp384r1_sha384,\n" + "%-20s ecdsa_secp521r1_sha512,\n" + "%-20s rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512,\n" + "%-20s rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512,\n" + "%-20s dsa_sha1, dsa_sha256, dsa_sha384, dsa_sha512\n", + "-J", "", "", "", "", "", "", ""); fprintf(stderr, "%-20s Enable alternative TLS 1.3 handshake\n", "-X alt-server-hello"); fprintf(stderr, "%-20s Use DTLS\n", "-P {client, server}"); fprintf(stderr, "%-20s Exit after handshake\n", "-Q"); @@ -1374,6 +1425,15 @@ run() } } + if (enabledSigSchemes) { + rv = SSL_SignatureSchemePrefSet(s, enabledSigSchemes, enabledSigSchemeCount); + if (rv < 0) { + SECU_PrintError(progName, "SSL_SignatureSchemePrefSet failed"); + error = 1; + goto done; + } + } + serverCertAuth.dbHandle = CERT_GetDefaultCertDB(); SSL_AuthCertificateHook(s, ownAuthCertificate, &serverCertAuth); @@ -1631,7 +1691,7 @@ main(int argc, char **argv) /* XXX: 'B' was used in the past but removed in 3.28, * please leave some time before resuing it. */ optstate = PL_CreateOptState(argc, argv, - "46A:CDFGHI:KL:M:OP:QR:STUV:W:X:YZa:bc:d:fgh:m:n:op:qr:st:uvw:z"); + "46A:CDFGHI:J:KL:M:OP:QR:STUV:W:X:YZa:bc:d:fgh:m:n:op:qr:st:uvw:z"); while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch (optstate->option) { case '?': @@ -1862,6 +1922,15 @@ main(int argc, char **argv) Usage(); } break; + + case 'J': + rv = parseSigSchemeList(optstate->value, &enabledSigSchemes, &enabledSigSchemeCount); + if (rv != SECSuccess) { + PL_DestroyOptState(optstate); + fprintf(stderr, "Bad signature scheme specified.\n"); + Usage(); + } + break; } } PL_DestroyOptState(optstate); |