summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Thomson <martin.thomson@gmail.com>2018-08-15 12:56:12 +1000
committerMartin Thomson <martin.thomson@gmail.com>2018-08-15 12:56:12 +1000
commit62a0a8ecbec00412349fed423496368e6aeca470 (patch)
tree52c326804b975b428a9b530904f381e66bf8cdb5
parent218053ef9a6e7bf0d2e1f71efe404aead08221f7 (diff)
downloadnss-hg-62a0a8ecbec00412349fed423496368e6aeca470.tar.gz
Bug 1482747 - Options for controlling signature scheme in tstclnt/selfserv, r=franziskus
-rw-r--r--cmd/lib/secutil.c116
-rw-r--r--cmd/lib/secutil.h4
-rw-r--r--cmd/selfserv/selfserv.c33
-rw-r--r--cmd/tstclnt/tstclnt.c85
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);