summaryrefslogtreecommitdiffstats
path: root/security/nss/cmd/signver
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--security/nss/cmd/signver/Makefile43
-rwxr-xr-xsecurity/nss/cmd/signver/examples/1/form.pl22
-rw-r--r--security/nss/cmd/signver/examples/1/signedForm.html55
-rw-r--r--security/nss/cmd/signver/examples/1/signedForm.nt.html55
-rwxr-xr-xsecurity/nss/cmd/signver/examples/1/signedForm.pl60
-rw-r--r--security/nss/cmd/signver/manifest.mn24
-rw-r--r--security/nss/cmd/signver/pk7print.c907
-rw-r--r--security/nss/cmd/signver/signver.c313
-rw-r--r--security/nss/cmd/signver/signver.gyp26
9 files changed, 1505 insertions, 0 deletions
diff --git a/security/nss/cmd/signver/Makefile b/security/nss/cmd/signver/Makefile
new file mode 100644
index 0000000000..fc8358d5ad
--- /dev/null
+++ b/security/nss/cmd/signver/Makefile
@@ -0,0 +1,43 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
diff --git a/security/nss/cmd/signver/examples/1/form.pl b/security/nss/cmd/signver/examples/1/form.pl
new file mode 100755
index 0000000000..f2cfddc691
--- /dev/null
+++ b/security/nss/cmd/signver/examples/1/form.pl
@@ -0,0 +1,22 @@
+#! /usr/bin/perl
+# 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/.
+
+
+print "Content-type: text/html\n\n";
+print "<B>Server Name:</B> ", $ENV{'SERVER_NAME'}, "<BR>", "\n";
+print "<B>Server Port:</B> ", $ENV{'SERVER_PORT'}, "<BR>", "\n";
+print "<B>Server Software:</B> ", $ENV{'SERVER_SOFTWARE'}, "<BR>", "\n";
+print "<B>Server Protocol:</B> ", $ENV{'SERVER_PROTOCOL'}, "<BR>", "\n";
+print "<B>CGI Revision:</B> ", $ENV{'GATEWAY_INTERFACE'}, "<BR>", "\n";
+print "<B>Browser:</B> ", $ENV{'HTTP_USER_AGENT'}, "<BR>", "\n";
+print "<B>Remote Address:</B> ", $ENV{'REMOTE_ADDR'}, "<BR>", "\n";
+print "<B>Remote Host:</B> ", $ENV{'REMOTE_HOST'}, "<BR>", "\n";
+print "<B>Remote User:</B> ", $ENV{'REMOTE_USER'}, "<BR>", "\n";
+print "You typed:\n";
+
+while( $_ = <STDIN>) {
+ print "$_";
+}
+
diff --git a/security/nss/cmd/signver/examples/1/signedForm.html b/security/nss/cmd/signver/examples/1/signedForm.html
new file mode 100644
index 0000000000..ac48e3f1e6
--- /dev/null
+++ b/security/nss/cmd/signver/examples/1/signedForm.html
@@ -0,0 +1,55 @@
+<html>
+<!-- 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/. -->
+<head>
+<title>Form to sign</title>
+<script language="javascript">
+<!--
+function submitSigned(form){
+ var signature = "";
+ var dataToSign = "";
+ var i;
+
+ form.action='signedForm.pl';
+ for (i = 0; i < form.length; i++)
+ if (form.elements[i].type == "text")
+ dataToSign += form.elements[i].value;
+
+ // alert("Data to sign:\n" + dataToSign);
+ signature = crypto.signText(dataToSign, "ask");
+ /* alert("You cannot see this alert");
+ alert("Data signature:\n" + signature); */
+
+ if (signature != "error:userCancel") {
+ for (i = 0; i < form.length; i++) {
+ if (form.elements[i].type == "hidden") {
+ if (form.elements[i].name == "dataToSign")
+ form.elements[i].value = dataToSign;
+ if (form.elements[i].name == "dataSignature")
+ form.elements[i].value = signature;
+ }
+ }
+ form.submit();
+ }
+}
+//-->
+</script>
+</head>
+
+<body>
+<form method=post Action="form.pl">
+<input type=hidden size=30 name=dataSignature>
+<input type=hidden size=30 name=dataToSign>
+<input type=text size=30 name=p>
+<BR>
+<input type=text size=30 name=q>
+<BR>
+<input type=text size=30 name=r>
+<BR>
+<input type=submit value="Submit Data">
+<input type=button value="Sign and Submit Data" onclick=submitSigned(this.form)>
+<input type=reset value=Reset>
+</form>
+</body>
+</html>
diff --git a/security/nss/cmd/signver/examples/1/signedForm.nt.html b/security/nss/cmd/signver/examples/1/signedForm.nt.html
new file mode 100644
index 0000000000..1a126d2ff9
--- /dev/null
+++ b/security/nss/cmd/signver/examples/1/signedForm.nt.html
@@ -0,0 +1,55 @@
+<html>
+<!-- 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/. -->
+<head>
+<title>Form to sign</title>
+<script language="javascript">
+<!--
+function submitSigned(form){
+ var signature = "";
+ var dataToSign = "";
+ var i;
+
+ form.action='cgi-bin/signedForm.pl';
+ for (i = 0; i < form.length; i++)
+ if (form.elements[i].type == "text")
+ dataToSign += form.elements[i].value;
+
+ // alert("Data to sign:\n" + dataToSign);
+ signature = crypto.signText(dataToSign, "ask");
+ /* alert("You cannot see this alert");
+ alert("Data signature:\n" + signature); */
+
+ if (signature != "error:userCancel") {
+ for (i = 0; i < form.length; i++) {
+ if (form.elements[i].type == "hidden") {
+ if (form.elements[i].name == "dataToSign")
+ form.elements[i].value = dataToSign;
+ if (form.elements[i].name == "dataSignature")
+ form.elements[i].value = signature;
+ }
+ }
+ form.submit();
+ }
+}
+//-->
+</script>
+</head>
+
+<body>
+<form method=post Action="cgi-bin/form.pl">
+<input type=hidden size=30 name=dataSignature>
+<input type=hidden size=30 name=dataToSign>
+<input type=text size=30 name=p>
+<BR>
+<input type=text size=30 name=q>
+<BR>
+<input type=text size=30 name=r>
+<BR>
+<input type=submit value="Submit Data">
+<input type=button value="Sign and Submit Data" onclick=submitSigned(this.form)>
+<input type=reset value=Reset>
+</form>
+</body>
+</html>
diff --git a/security/nss/cmd/signver/examples/1/signedForm.pl b/security/nss/cmd/signver/examples/1/signedForm.pl
new file mode 100755
index 0000000000..847814c90a
--- /dev/null
+++ b/security/nss/cmd/signver/examples/1/signedForm.pl
@@ -0,0 +1,60 @@
+#! /usr/bin/perl
+# 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/.
+
+
+
+sub decode {
+ read (STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
+ @pairs = split(/&/, $buffer);
+ foreach $pair (@pairs)
+ {
+ ($name, $value) = split(/=/, $pair);
+ $value =~tr/+/ /;
+ $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
+ $FORM{$name} = $value;
+# print "name=$name value=$value<BR>\n";
+ }
+}
+
+print "Content-type: text/html\n\n";
+
+&decode();
+
+$dataSignature = $FORM{'dataSignature'};
+$dataToSign = $FORM{'dataToSign'};
+
+unlink("signature");
+open(FILE1,">signature") || die("Cannot open file for writing\n");
+
+print FILE1 "$dataSignature";
+
+close(FILE1);
+
+
+unlink("data");
+open(FILE2,">data") || die("Cannot open file for writing\n");
+
+print FILE2 "$dataToSign";
+
+close(FILE2);
+
+
+print "<BR><B>Signed Data:</B><BR>", "$dataToSign", "<BR>";
+
+print "<BR><b>Verification Info:</b><BR>";
+
+$verInfo = `./signver -D . -s signature -d data -v`;
+print "<font color=red><b>$verInfo</b></font><BR>";
+
+print "<BR><B>Signature Data:</B><BR>", "$dataSignature", "<BR>";
+
+print "<BR><b>Signature Info:</b><BR>";
+
+foreach $line (`./signver -s signature -A`) {
+ print "$line<BR>\n";
+}
+
+print "<b>End of Info</b><BR>";
+
diff --git a/security/nss/cmd/signver/manifest.mn b/security/nss/cmd/signver/manifest.mn
new file mode 100644
index 0000000000..7a1de149f9
--- /dev/null
+++ b/security/nss/cmd/signver/manifest.mn
@@ -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/.
+
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+CSRCS = signver.c \
+ pk7print.c \
+ $(NULL)
+
+REQUIRES = dbm seccmd
+
+PROGRAM = signver
+
+PACKAGE_FILES = README.txt signedForm.html signedForm.pl form.pl
+ifeq ($(subst /,_,$(shell uname -s)),WINNT)
+PACKAGE_FILES += signedForm.nt.pl signver.exe
+else
+PACKAGE_FILES += signver
+endif
+
+ARCHIVE_NAME = signver
diff --git a/security/nss/cmd/signver/pk7print.c b/security/nss/cmd/signver/pk7print.c
new file mode 100644
index 0000000000..d8dbe09a7b
--- /dev/null
+++ b/security/nss/cmd/signver/pk7print.c
@@ -0,0 +1,907 @@
+/* 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/. */
+
+/*
+** secutil.c - various functions used by security stuff
+**
+*/
+
+/* pkcs #7 -related functions */
+
+#include "secutil.h"
+#include "secpkcs7.h"
+#include "secoid.h"
+#include <sys/stat.h>
+#include <stdarg.h>
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#endif
+
+/* for SEC_TraverseNames */
+#include "cert.h"
+#include "prtypes.h"
+#include "prtime.h"
+
+#include "prlong.h"
+#include "secmod.h"
+#include "pk11func.h"
+#include "prerror.h"
+
+/*
+** PKCS7 Support
+*/
+
+/* forward declaration */
+int
+sv_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, char *);
+
+void
+sv_PrintAsHex(FILE *out, SECItem *data, char *m)
+{
+ unsigned i;
+
+ if (m)
+ fprintf(out, "%s", m);
+
+ for (i = 0; i < data->len; i++) {
+ if (i < data->len - 1) {
+ fprintf(out, "%02x:", data->data[i]);
+ } else {
+ fprintf(out, "%02x\n", data->data[i]);
+ break;
+ }
+ }
+}
+
+void
+sv_PrintInteger(FILE *out, SECItem *i, char *m)
+{
+ int iv;
+
+ if (i->len > 4) {
+ sv_PrintAsHex(out, i, m);
+ } else {
+ iv = DER_GetInteger(i);
+ fprintf(out, "%s%d (0x%x)\n", m, iv, iv);
+ }
+}
+
+int
+sv_PrintTime(FILE *out, SECItem *t, char *m)
+{
+ PRExplodedTime printableTime;
+ PRTime time;
+ char *timeString;
+ int rv;
+
+ rv = DER_DecodeTimeChoice(&time, t);
+ if (rv)
+ return rv;
+
+ /* Convert to local time */
+ PR_ExplodeTime(time, PR_LocalTimeParameters, &printableTime);
+
+ timeString = (char *)PORT_Alloc(256);
+
+ if (timeString) {
+ if (PR_FormatTime(timeString, 256, "%a %b %d %H:%M:%S %Y", &printableTime)) {
+ fprintf(out, "%s%s\n", m, timeString);
+ }
+ PORT_Free(timeString);
+ return 0;
+ }
+ return SECFailure;
+}
+
+int
+sv_PrintValidity(FILE *out, CERTValidity *v, char *m)
+{
+ int rv;
+
+ fprintf(out, "%s", m);
+ rv = sv_PrintTime(out, &v->notBefore, "notBefore=");
+ if (rv)
+ return rv;
+ fprintf(out, "%s", m);
+ sv_PrintTime(out, &v->notAfter, "notAfter=");
+ return rv;
+}
+
+void
+sv_PrintObjectID(FILE *out, SECItem *oid, char *m)
+{
+ const char *name;
+ SECOidData *oiddata;
+
+ oiddata = SECOID_FindOID(oid);
+ if (oiddata == NULL) {
+ sv_PrintAsHex(out, oid, m);
+ return;
+ }
+ name = oiddata->desc;
+
+ if (m != NULL)
+ fprintf(out, "%s", m);
+ fprintf(out, "%s\n", name);
+}
+
+void
+sv_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m)
+{
+ sv_PrintObjectID(out, &a->algorithm, m);
+
+ if ((a->parameters.len != 2) ||
+ (PORT_Memcmp(a->parameters.data, "\005\000", 2) != 0)) {
+ /* Print args to algorithm */
+ sv_PrintAsHex(out, &a->parameters, "Args=");
+ }
+}
+
+void
+sv_PrintAttribute(FILE *out, SEC_PKCS7Attribute *attr, char *m)
+{
+ SECItem *value;
+ int i;
+ char om[100];
+
+ fprintf(out, "%s", m);
+
+ /*
+ * XXX Make this smarter; look at the type field and then decode
+ * and print the value(s) appropriately!
+ */
+ sv_PrintObjectID(out, &(attr->type), "type=");
+ if (attr->values != NULL) {
+ i = 0;
+ while ((value = attr->values[i]) != NULL) {
+ snprintf(om, sizeof(om), "%svalue[%d]=%s", m, i++, attr->encoded ? "(encoded)" : "");
+ if (attr->encoded || attr->typeTag == NULL) {
+ sv_PrintAsHex(out, value, om);
+ } else {
+ switch (attr->typeTag->offset) {
+ default:
+ sv_PrintAsHex(out, value, om);
+ break;
+ case SEC_OID_PKCS9_CONTENT_TYPE:
+ sv_PrintObjectID(out, value, om);
+ break;
+ case SEC_OID_PKCS9_SIGNING_TIME:
+ sv_PrintTime(out, value, om);
+ break;
+ }
+ }
+ }
+ }
+}
+
+void
+sv_PrintName(FILE *out, CERTName *name, char *msg)
+{
+ char *str;
+
+ str = CERT_NameToAscii(name);
+ fprintf(out, "%s%s\n", msg, str);
+ PORT_Free(str);
+}
+
+#if 0
+/*
+** secu_PrintPKCS7EncContent
+** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
+*/
+void
+secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
+ char *m, int level)
+{
+ if (src->contentTypeTag == NULL)
+ src->contentTypeTag = SECOID_FindOID(&(src->contentType));
+
+ secu_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ secu_Indent(out, level + 1);
+ fprintf(out, "Content Type: %s\n",
+ (src->contentTypeTag != NULL) ? src->contentTypeTag->desc
+ : "Unknown");
+ sv_PrintAlgorithmID(out, &(src->contentEncAlg),
+ "Content Encryption Algorithm");
+ sv_PrintAsHex(out, &(src->encContent),
+ "Encrypted Content", level+1);
+}
+
+/*
+** secu_PrintRecipientInfo
+** Prints a PKCS7RecipientInfo type
+*/
+void
+secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info, char *m,
+ int level)
+{
+ secu_Indent(out, level); fprintf(out, "%s:\n", m);
+ sv_PrintInteger(out, &(info->version), "Version");
+
+ sv_PrintName(out, &(info->issuerAndSN->issuer), "Issuer");
+ sv_PrintInteger(out, &(info->issuerAndSN->serialNumber),
+ "Serial Number");
+
+ /* Parse and display encrypted key */
+ sv_PrintAlgorithmID(out, &(info->keyEncAlg),
+ "Key Encryption Algorithm");
+ sv_PrintAsHex(out, &(info->encKey), "Encrypted Key", level + 1);
+}
+#endif
+
+/*
+** secu_PrintSignerInfo
+** Prints a PKCS7SingerInfo type
+*/
+void
+sv_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info, char *m)
+{
+ SEC_PKCS7Attribute *attr;
+ int iv;
+
+ fprintf(out, "%s", m);
+ sv_PrintInteger(out, &(info->version), "version=");
+
+ fprintf(out, "%s", m);
+ sv_PrintName(out, &(info->issuerAndSN->issuer), "issuerName=");
+ fprintf(out, "%s", m);
+ sv_PrintInteger(out, &(info->issuerAndSN->serialNumber),
+ "serialNumber=");
+
+ fprintf(out, "%s", m);
+ sv_PrintAlgorithmID(out, &(info->digestAlg), "digestAlgorithm=");
+
+ if (info->authAttr != NULL) {
+ char mm[120];
+
+ iv = 0;
+ while (info->authAttr[iv] != NULL)
+ iv++;
+ fprintf(out, "%sauthenticatedAttributes=%d\n", m, iv);
+ iv = 0;
+ while ((attr = info->authAttr[iv]) != NULL) {
+ snprintf(mm, sizeof(mm), "%sattribute[%d].", m, iv++);
+ sv_PrintAttribute(out, attr, mm);
+ }
+ }
+
+ /* Parse and display signature */
+ fprintf(out, "%s", m);
+ sv_PrintAlgorithmID(out, &(info->digestEncAlg), "digestEncryptionAlgorithm=");
+ fprintf(out, "%s", m);
+ sv_PrintAsHex(out, &(info->encDigest), "encryptedDigest=");
+
+ if (info->unAuthAttr != NULL) {
+ char mm[120];
+
+ iv = 0;
+ while (info->unAuthAttr[iv] != NULL)
+ iv++;
+ fprintf(out, "%sunauthenticatedAttributes=%d\n", m, iv);
+ iv = 0;
+ while ((attr = info->unAuthAttr[iv]) != NULL) {
+ snprintf(mm, sizeof(mm), "%sattribute[%d].", m, iv++);
+ sv_PrintAttribute(out, attr, mm);
+ }
+ }
+}
+
+void
+sv_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m)
+{
+ fprintf(out, "%s", m);
+ sv_PrintInteger(out, &pk->u.rsa.modulus, "modulus=");
+ fprintf(out, "%s", m);
+ sv_PrintInteger(out, &pk->u.rsa.publicExponent, "exponent=");
+}
+
+void
+sv_PrintDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m)
+{
+ fprintf(out, "%s", m);
+ sv_PrintInteger(out, &pk->u.dsa.params.prime, "prime=");
+ fprintf(out, "%s", m);
+ sv_PrintInteger(out, &pk->u.dsa.params.subPrime, "subprime=");
+ fprintf(out, "%s", m);
+ sv_PrintInteger(out, &pk->u.dsa.params.base, "base=");
+ fprintf(out, "%s", m);
+ sv_PrintInteger(out, &pk->u.dsa.publicValue, "publicValue=");
+}
+
+void
+sv_PrintECDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m)
+{
+ SECItem curve = { siBuffer, NULL, 0 };
+ if ((pk->u.ec.DEREncodedParams.len > 2) &&
+ (pk->u.ec.DEREncodedParams.data[0] == 0x06)) {
+ /* strip to just the oid for the curve */
+ curve.len = pk->u.ec.DEREncodedParams.data[1];
+ curve.data = pk->u.ec.DEREncodedParams.data + 2;
+ /* don't overflow the buffer */
+ curve.len = PR_MIN(curve.len, pk->u.ec.DEREncodedParams.len - 2);
+ fprintf(out, "%s", m);
+ sv_PrintObjectID(out, &curve, "curve=");
+ }
+ fprintf(out, "%s", m);
+ sv_PrintInteger(out, &pk->u.ec.publicValue, "publicValue=");
+}
+
+int
+sv_PrintSubjectPublicKeyInfo(FILE *out, PLArenaPool *arena,
+ CERTSubjectPublicKeyInfo *i, char *msg)
+{
+ SECKEYPublicKey pk;
+ int rv;
+ char mm[200];
+
+ snprintf(mm, sizeof(mm), "%s.publicKeyAlgorithm=", msg);
+ sv_PrintAlgorithmID(out, &i->algorithm, mm);
+
+ DER_ConvertBitString(&i->subjectPublicKey);
+ switch (SECOID_FindOIDTag(&i->algorithm.algorithm)) {
+ case SEC_OID_PKCS1_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
+ rv = SEC_ASN1DecodeItem(arena, &pk,
+ SEC_ASN1_GET(SECKEY_RSAPublicKeyTemplate),
+ &i->subjectPublicKey);
+ if (rv)
+ return rv;
+ snprintf(mm, sizeof(mm), "%s.rsaPublicKey.", msg);
+ sv_PrintRSAPublicKey(out, &pk, mm);
+ break;
+ case SEC_OID_ANSIX9_DSA_SIGNATURE:
+ rv = SEC_ASN1DecodeItem(arena, &pk,
+ SEC_ASN1_GET(SECKEY_DSAPublicKeyTemplate),
+ &i->subjectPublicKey);
+ if (rv)
+ return rv;
+#ifdef notdef
+ /* SECKEY_PQGParamsTemplate is not yet exported form NSS */
+ rv = SEC_ASN1DecodeItem(arena, &pk.u.dsa.params,
+ SEC_ASN1_GET(SECKEY_PQGParamsTemplate),
+ &i->algorithm.parameters);
+ if (rv)
+ return rv;
+#endif
+ snprintf(mm, sizeof(mm), "%s.dsaPublicKey.", msg);
+ sv_PrintDSAPublicKey(out, &pk, mm);
+ break;
+ case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
+ rv = SECITEM_CopyItem(arena, &pk.u.ec.DEREncodedParams,
+ &i->algorithm.parameters);
+ if (rv)
+ return rv;
+ rv = SECITEM_CopyItem(arena, &pk.u.ec.publicValue,
+ &i->subjectPublicKey);
+ if (rv)
+ return rv;
+ snprintf(mm, sizeof(mm), "%s.ecdsaPublicKey.", msg);
+ sv_PrintECDSAPublicKey(out, &pk, mm);
+ break;
+ default:
+ fprintf(out, "%s=bad SPKI algorithm type\n", msg);
+ return 0;
+ }
+
+ return 0;
+}
+
+SECStatus
+sv_PrintInvalidDateExten(FILE *out, SECItem *value, char *msg)
+{
+ SECItem decodedValue;
+ SECStatus rv;
+ PRTime invalidTime;
+ char *formattedTime = NULL;
+
+ decodedValue.data = NULL;
+ rv = SEC_ASN1DecodeItem(NULL, &decodedValue,
+ SEC_ASN1_GET(SEC_GeneralizedTimeTemplate),
+ value);
+ if (rv == SECSuccess) {
+ rv = DER_GeneralizedTimeToTime(&invalidTime, &decodedValue);
+ if (rv == SECSuccess) {
+ formattedTime = CERT_GenTime2FormattedAscii(invalidTime, "%a %b %d %H:%M:%S %Y");
+ fprintf(out, "%s: %s\n", msg, formattedTime);
+ PORT_Free(formattedTime);
+ }
+ }
+ PORT_Free(decodedValue.data);
+
+ return (rv);
+}
+
+int
+sv_PrintExtensions(FILE *out, CERTCertExtension **extensions, char *msg)
+{
+ SECOidTag oidTag;
+
+ if (extensions) {
+
+ while (*extensions) {
+ SECItem *tmpitem;
+
+ fprintf(out, "%sname=", msg);
+
+ tmpitem = &(*extensions)->id;
+ sv_PrintObjectID(out, tmpitem, NULL);
+
+ tmpitem = &(*extensions)->critical;
+ if (tmpitem->len)
+ fprintf(out, "%scritical=%s\n", msg,
+ (tmpitem->data && tmpitem->data[0]) ? "True" : "False");
+
+ oidTag = SECOID_FindOIDTag(&((*extensions)->id));
+
+ fprintf(out, "%s", msg);
+ tmpitem = &((*extensions)->value);
+ if (oidTag == SEC_OID_X509_INVALID_DATE)
+ sv_PrintInvalidDateExten(out, tmpitem, "invalidExt");
+ else
+ sv_PrintAsHex(out, tmpitem, "data=");
+
+ /*fprintf(out, "\n");*/
+ extensions++;
+ }
+ }
+
+ return 0;
+}
+
+/* callers of this function must make sure that the CERTSignedCrl
+ from which they are extracting the CERTCrl has been fully-decoded.
+ Otherwise it will not have the entries even though the CRL may have
+ some */
+void
+sv_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m)
+{
+ CERTCrlEntry *entry;
+ int iv;
+ char om[100];
+
+ fprintf(out, "%s", m);
+ sv_PrintAlgorithmID(out, &(crl->signatureAlg), "signatureAlgorithm=");
+ fprintf(out, "%s", m);
+ sv_PrintName(out, &(crl->name), "name=");
+ fprintf(out, "%s", m);
+ sv_PrintTime(out, &(crl->lastUpdate), "lastUpdate=");
+ fprintf(out, "%s", m);
+ sv_PrintTime(out, &(crl->nextUpdate), "nextUpdate=");
+
+ if (crl->entries != NULL) {
+ iv = 0;
+ while ((entry = crl->entries[iv]) != NULL) {
+ fprintf(out, "%sentry[%d].", m, iv);
+ sv_PrintInteger(out, &(entry->serialNumber), "serialNumber=");
+ fprintf(out, "%sentry[%d].", m, iv);
+ sv_PrintTime(out, &(entry->revocationDate), "revocationDate=");
+ snprintf(om, sizeof(om), "%sentry[%d].signedCRLEntriesExtensions.", m, iv++);
+ sv_PrintExtensions(out, entry->extensions, om);
+ }
+ }
+ snprintf(om, sizeof(om), "%ssignedCRLEntriesExtensions.", m);
+ sv_PrintExtensions(out, crl->extensions, om);
+}
+
+int
+sv_PrintCertificate(FILE *out, SECItem *der, char *m, int level)
+{
+ PLArenaPool *arena = NULL;
+ CERTCertificate *c;
+ int rv;
+ int iv;
+ char mm[200];
+
+ /* Decode certificate */
+ c = (CERTCertificate *)PORT_ZAlloc(sizeof(CERTCertificate));
+ if (!c)
+ return PORT_GetError();
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena)
+ return SEC_ERROR_NO_MEMORY;
+
+ rv = SEC_ASN1DecodeItem(arena, c, SEC_ASN1_GET(CERT_CertificateTemplate),
+ der);
+ if (rv) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+ }
+
+ /* Pretty print it out */
+ iv = DER_GetInteger(&c->version);
+ fprintf(out, "%sversion=%d (0x%x)\n", m, iv + 1, iv);
+ snprintf(mm, sizeof(mm), "%sserialNumber=", m);
+ sv_PrintInteger(out, &c->serialNumber, mm);
+ snprintf(mm, sizeof(mm), "%ssignatureAlgorithm=", m);
+ sv_PrintAlgorithmID(out, &c->signature, mm);
+ snprintf(mm, sizeof(mm), "%sissuerName=", m);
+ sv_PrintName(out, &c->issuer, mm);
+ snprintf(mm, sizeof(mm), "%svalidity.", m);
+ sv_PrintValidity(out, &c->validity, mm);
+ snprintf(mm, sizeof(mm), "%ssubject=", m);
+ sv_PrintName(out, &c->subject, mm);
+ snprintf(mm, sizeof(mm), "%ssubjectPublicKeyInfo", m);
+ rv = sv_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo, mm);
+ if (rv) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+ }
+ snprintf(mm, sizeof(mm), "%ssignedExtensions.", m);
+ sv_PrintExtensions(out, c->extensions, mm);
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return 0;
+}
+
+int
+sv_PrintSignedData(FILE *out, SECItem *der, char *m, SECU_PPFunc inner)
+{
+ PLArenaPool *arena = NULL;
+ CERTSignedData *sd;
+ int rv;
+
+ /* Strip off the signature */
+ sd = (CERTSignedData *)PORT_ZAlloc(sizeof(CERTSignedData));
+ if (!sd)
+ return PORT_GetError();
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena)
+ return SEC_ERROR_NO_MEMORY;
+
+ rv = SEC_ASN1DecodeItem(arena, sd, SEC_ASN1_GET(CERT_SignedDataTemplate),
+ der);
+ if (rv) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+ }
+
+ /* fprintf(out, "%s:\n", m); */
+ PORT_Strcat(m, "data.");
+
+ rv = (*inner)(out, &sd->data, m, 0);
+ if (rv) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+ }
+
+ m[PORT_Strlen(m) - 5] = 0;
+ fprintf(out, "%s", m);
+ sv_PrintAlgorithmID(out, &sd->signatureAlgorithm, "signatureAlgorithm=");
+ DER_ConvertBitString(&sd->signature);
+ fprintf(out, "%s", m);
+ sv_PrintAsHex(out, &sd->signature, "signature=");
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return 0;
+}
+
+/*
+** secu_PrintPKCS7Signed
+** Pretty print a PKCS7 signed data type (up to version 1).
+*/
+int
+sv_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src)
+{
+ SECAlgorithmID *digAlg; /* digest algorithms */
+ SECItem *aCert; /* certificate */
+ CERTSignedCrl *aCrl; /* certificate revocation list */
+ SEC_PKCS7SignerInfo *sigInfo; /* signer information */
+ int rv, iv;
+ char om[120];
+
+ sv_PrintInteger(out, &(src->version), "pkcs7.version=");
+
+ /* Parse and list digest algorithms (if any) */
+ if (src->digestAlgorithms != NULL) {
+ iv = 0;
+ while (src->digestAlgorithms[iv] != NULL)
+ iv++;
+ fprintf(out, "pkcs7.digestAlgorithmListLength=%d\n", iv);
+ iv = 0;
+ while ((digAlg = src->digestAlgorithms[iv]) != NULL) {
+ snprintf(om, sizeof(om), "pkcs7.digestAlgorithm[%d]=", iv++);
+ sv_PrintAlgorithmID(out, digAlg, om);
+ }
+ }
+
+ /* Now for the content */
+ rv = sv_PrintPKCS7ContentInfo(out, &(src->contentInfo),
+ "pkcs7.contentInformation=");
+ if (rv != 0)
+ return rv;
+
+ /* Parse and list certificates (if any) */
+ if (src->rawCerts != NULL) {
+ iv = 0;
+ while (src->rawCerts[iv] != NULL)
+ iv++;
+ fprintf(out, "pkcs7.certificateListLength=%d\n", iv);
+
+ iv = 0;
+ while ((aCert = src->rawCerts[iv]) != NULL) {
+ snprintf(om, sizeof(om), "certificate[%d].", iv++);
+ rv = sv_PrintSignedData(out, aCert, om, sv_PrintCertificate);
+ if (rv)
+ return rv;
+ }
+ }
+
+ /* Parse and list CRL's (if any) */
+ if (src->crls != NULL) {
+ iv = 0;
+ while (src->crls[iv] != NULL)
+ iv++;
+ fprintf(out, "pkcs7.signedRevocationLists=%d\n", iv);
+ iv = 0;
+ while ((aCrl = src->crls[iv]) != NULL) {
+ snprintf(om, sizeof(om), "signedRevocationList[%d].", iv);
+ fprintf(out, "%s", om);
+ sv_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
+ "signatureAlgorithm=");
+ DER_ConvertBitString(&aCrl->signatureWrap.signature);
+ fprintf(out, "%s", om);
+ sv_PrintAsHex(out, &aCrl->signatureWrap.signature, "signature=");
+ snprintf(om, sizeof(om), "certificateRevocationList[%d].", iv);
+ sv_PrintCRLInfo(out, &aCrl->crl, om);
+ iv++;
+ }
+ }
+
+ /* Parse and list signatures (if any) */
+ if (src->signerInfos != NULL) {
+ iv = 0;
+ while (src->signerInfos[iv] != NULL)
+ iv++;
+ fprintf(out, "pkcs7.signerInformationListLength=%d\n", iv);
+ iv = 0;
+ while ((sigInfo = src->signerInfos[iv]) != NULL) {
+ snprintf(om, sizeof(om), "signerInformation[%d].", iv++);
+ sv_PrintSignerInfo(out, sigInfo, om);
+ }
+ }
+
+ return 0;
+}
+
+#if 0
+/*
+** secu_PrintPKCS7Enveloped
+** Pretty print a PKCS7 enveloped data type (up to version 1).
+*/
+void
+secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
+ char *m, int level)
+{
+ SEC_PKCS7RecipientInfo *recInfo; /* pointer for signer information */
+ int iv;
+ char om[100];
+
+ secu_Indent(out, level); fprintf(out, "%s:\n", m);
+ sv_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ /* Parse and list recipients (this is not optional) */
+ if (src->recipientInfos != NULL) {
+ secu_Indent(out, level + 1);
+ fprintf(out, "Recipient Information List:\n");
+ iv = 0;
+ while ((recInfo = src->recipientInfos[iv++]) != NULL) {
+ snprintf(om, sizeof(om), "Recipient Information (%x)", iv);
+ secu_PrintRecipientInfo(out, recInfo, om, level + 2);
+ }
+ }
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+}
+
+/*
+** secu_PrintPKCS7SignedEnveloped
+** Pretty print a PKCS7 singed and enveloped data type (up to version 1).
+*/
+int
+secu_PrintPKCS7SignedAndEnveloped(FILE *out,
+ SEC_PKCS7SignedAndEnvelopedData *src,
+ char *m, int level)
+{
+ SECAlgorithmID *digAlg; /* pointer for digest algorithms */
+ SECItem *aCert; /* pointer for certificate */
+ CERTSignedCrl *aCrl; /* pointer for certificate revocation list */
+ SEC_PKCS7SignerInfo *sigInfo; /* pointer for signer information */
+ SEC_PKCS7RecipientInfo *recInfo; /* pointer for recipient information */
+ int rv, iv;
+ char om[100];
+
+ secu_Indent(out, level); fprintf(out, "%s:\n", m);
+ sv_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ /* Parse and list recipients (this is not optional) */
+ if (src->recipientInfos != NULL) {
+ secu_Indent(out, level + 1);
+ fprintf(out, "Recipient Information List:\n");
+ iv = 0;
+ while ((recInfo = src->recipientInfos[iv++]) != NULL) {
+ snprintf(om, sizeof(om), "Recipient Information (%x)", iv);
+ secu_PrintRecipientInfo(out, recInfo, om, level + 2);
+ }
+ }
+
+ /* Parse and list digest algorithms (if any) */
+ if (src->digestAlgorithms != NULL) {
+ secu_Indent(out, level + 1); fprintf(out, "Digest Algorithm List:\n");
+ iv = 0;
+ while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
+ snprintf(om, sizeof(om), "Digest Algorithm (%x)", iv);
+ sv_PrintAlgorithmID(out, digAlg, om);
+ }
+ }
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+
+ /* Parse and list certificates (if any) */
+ if (src->rawCerts != NULL) {
+ secu_Indent(out, level + 1); fprintf(out, "Certificate List:\n");
+ iv = 0;
+ while ((aCert = src->rawCerts[iv++]) != NULL) {
+ snprintf(om, sizeof(om), "Certificate (%x)", iv);
+ rv = SECU_PrintSignedData(out, aCert, om, level + 2,
+ SECU_PrintCertificate);
+ if (rv)
+ return rv;
+ }
+ }
+
+ /* Parse and list CRL's (if any) */
+ if (src->crls != NULL) {
+ secu_Indent(out, level + 1);
+ fprintf(out, "Signed Revocation Lists:\n");
+ iv = 0;
+ while ((aCrl = src->crls[iv++]) != NULL) {
+ snprintf(om, sizeof(om), "Signed Revocation List (%x)", iv);
+ secu_Indent(out, level + 2); fprintf(out, "%s:\n", om);
+ sv_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
+ "Signature Algorithm");
+ DER_ConvertBitString(&aCrl->signatureWrap.signature);
+ sv_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
+ level+3);
+ SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
+ level + 3);
+ }
+ }
+
+ /* Parse and list signatures (if any) */
+ if (src->signerInfos != NULL) {
+ secu_Indent(out, level + 1);
+ fprintf(out, "Signer Information List:\n");
+ iv = 0;
+ while ((sigInfo = src->signerInfos[iv++]) != NULL) {
+ snprintf(om, sizeof(om), "Signer Information (%x)", iv);
+ secu_PrintSignerInfo(out, sigInfo, om, level + 2);
+ }
+ }
+
+ return 0;
+}
+
+/*
+** secu_PrintPKCS7Encrypted
+** Pretty print a PKCS7 encrypted data type (up to version 1).
+*/
+void
+secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src,
+ char *m, int level)
+{
+ secu_Indent(out, level); fprintf(out, "%s:\n", m);
+ sv_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+}
+
+/*
+** secu_PrintPKCS7Digested
+** Pretty print a PKCS7 digested data type (up to version 1).
+*/
+void
+sv_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src)
+{
+ secu_Indent(out, level); fprintf(out, "%s:\n", m);
+ sv_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ sv_PrintAlgorithmID(out, &src->digestAlg, "Digest Algorithm");
+ sv_PrintPKCS7ContentInfo(out, &src->contentInfo, "Content Information",
+ level + 1);
+ sv_PrintAsHex(out, &src->digest, "Digest", level + 1);
+}
+
+#endif
+
+/*
+** secu_PrintPKCS7ContentInfo
+** Takes a SEC_PKCS7ContentInfo type and sends the contents to the
+** appropriate function
+*/
+int
+sv_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src, char *m)
+{
+ const char *desc;
+ SECOidTag kind;
+ int rv;
+
+ if (src->contentTypeTag == NULL)
+ src->contentTypeTag = SECOID_FindOID(&(src->contentType));
+
+ if (src->contentTypeTag == NULL) {
+ desc = "Unknown";
+ kind = SEC_OID_PKCS7_DATA;
+ } else {
+ desc = src->contentTypeTag->desc;
+ kind = src->contentTypeTag->offset;
+ }
+
+ fprintf(out, "%s%s\n", m, desc);
+
+ if (src->content.data == NULL) {
+ fprintf(out, "pkcs7.data=<no content>\n");
+ return 0;
+ }
+
+ rv = 0;
+ switch (kind) {
+ case SEC_OID_PKCS7_SIGNED_DATA: /* Signed Data */
+ rv = sv_PrintPKCS7Signed(out, src->content.signedData);
+ break;
+
+ case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */
+ fprintf(out, "pkcs7EnvelopedData=<unsupported>\n");
+ /*sv_PrintPKCS7Enveloped(out, src->content.envelopedData);*/
+ break;
+
+ case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */
+ fprintf(out, "pkcs7SignedEnvelopedData=<unsupported>\n");
+ /*rv = sv_PrintPKCS7SignedAndEnveloped(out,
+ src->content.signedAndEnvelopedData);*/
+ break;
+
+ case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */
+ fprintf(out, "pkcs7DigestedData=<unsupported>\n");
+ /*sv_PrintPKCS7Digested(out, src->content.digestedData);*/
+ break;
+
+ case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */
+ fprintf(out, "pkcs7EncryptedData=<unsupported>\n");
+ /*sv_PrintPKCS7Encrypted(out, src->content.encryptedData);*/
+ break;
+
+ default:
+ fprintf(out, "pkcs7UnknownData=<unsupported>\n");
+ /*sv_PrintAsHex(out, src->content.data);*/
+ break;
+ }
+
+ return rv;
+}
+
+int
+SV_PrintPKCS7ContentInfo(FILE *out, SECItem *der)
+{
+ SEC_PKCS7ContentInfo *cinfo;
+ int rv = -1;
+
+ cinfo = SEC_PKCS7DecodeItem(der, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ if (cinfo != NULL) {
+ rv = sv_PrintPKCS7ContentInfo(out, cinfo, "pkcs7.contentInfo=");
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ }
+
+ return rv;
+}
+/*
+** End of PKCS7 functions
+*/
diff --git a/security/nss/cmd/signver/signver.c b/security/nss/cmd/signver/signver.c
new file mode 100644
index 0000000000..8b122bde05
--- /dev/null
+++ b/security/nss/cmd/signver/signver.c
@@ -0,0 +1,313 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "secutil.h"
+#include "secmod.h"
+#include "cert.h"
+#include "secoid.h"
+#include "nss.h"
+
+/* NSPR 2.0 header files */
+#include "prinit.h"
+#include "prprf.h"
+#include "prsystem.h"
+#include "prmem.h"
+/* Portable layer header files */
+#include "plstr.h"
+#include "sechash.h" /* for HASH_GetHashObject() */
+
+static PRBool debugInfo;
+static PRBool verbose;
+static PRBool doVerify;
+static PRBool displayAll;
+
+static const char *const usageInfo[] = {
+ "signver - verify a detached PKCS7 signature - Version " NSS_VERSION,
+ "Commands:",
+ " -A display all information from pkcs #7",
+ " -V verify the signed object and display result",
+ "Options:",
+ " -a signature file is ASCII",
+ " -d certdir directory containing cert database",
+ " -i dataFileName input file containing signed data (default stdin)",
+ " -o outputFileName output file name, default stdout",
+ " -s signatureFileName input file for signature (default stdin)",
+ " -v display verbose reason for failure"
+};
+static int nUsageInfo = sizeof(usageInfo) / sizeof(char *);
+
+extern int SV_PrintPKCS7ContentInfo(FILE *, SECItem *);
+
+static void
+Usage(char *progName, FILE *outFile)
+{
+ int i;
+ fprintf(outFile, "Usage: %s [ commands ] options\n", progName);
+ for (i = 0; i < nUsageInfo; i++)
+ fprintf(outFile, "%s\n", usageInfo[i]);
+ exit(-1);
+}
+
+static HASH_HashType
+AlgorithmToHashType(SECAlgorithmID *digestAlgorithms)
+{
+ SECOidTag tag = SECOID_GetAlgorithmTag(digestAlgorithms);
+ HASH_HashType hash = HASH_GetHashTypeByOidTag(tag);
+ return hash;
+}
+
+static SECStatus
+DigestContent(SECItem *digest, SECItem *content, HASH_HashType hashType)
+{
+ unsigned int maxLen = digest->len;
+ unsigned int len = HASH_ResultLen(hashType);
+ SECStatus rv;
+
+ if (len > maxLen) {
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+ return SECFailure;
+ }
+
+ rv = HASH_HashBuf(hashType, digest->data, content->data, content->len);
+ if (rv == SECSuccess)
+ digest->len = len;
+ return rv;
+}
+
+enum {
+ cmd_DisplayAllPCKS7Info = 0,
+ cmd_VerifySignedObj
+};
+
+enum {
+ opt_ASCII,
+ opt_CertDir,
+ opt_InputDataFile,
+ opt_OutputFile,
+ opt_InputSigFile,
+ opt_PrintWhyFailure,
+ opt_DebugInfo
+};
+
+static secuCommandFlag signver_commands[] = {
+ { /* cmd_DisplayAllPCKS7Info*/ 'A', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_VerifySignedObj */ 'V', PR_FALSE, 0, PR_FALSE }
+};
+
+static secuCommandFlag signver_options[] = {
+ { /* opt_ASCII */ 'a', PR_FALSE, 0, PR_FALSE },
+ { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE },
+ { /* opt_InputDataFile */ 'i', PR_TRUE, 0, PR_FALSE },
+ { /* opt_OutputFile */ 'o', PR_TRUE, 0, PR_FALSE },
+ { /* opt_InputSigFile */ 's', PR_TRUE, 0, PR_FALSE },
+ { /* opt_PrintWhyFailure */ 'v', PR_FALSE, 0, PR_FALSE },
+ { /* opt_DebugInfo */ 0, PR_FALSE, 0, PR_FALSE, "debug" }
+};
+
+int
+main(int argc, char **argv)
+{
+ PRFileDesc *contentFile = NULL;
+ PRFileDesc *signFile = PR_STDIN;
+ FILE *outFile = stdout;
+ char *progName;
+ SECStatus rv;
+ int result = 1;
+ SECItem pkcs7der, content;
+ secuCommand signver;
+
+ pkcs7der.data = NULL;
+ content.data = NULL;
+
+ signver.numCommands = sizeof(signver_commands) / sizeof(secuCommandFlag);
+ signver.numOptions = sizeof(signver_options) / sizeof(secuCommandFlag);
+ signver.commands = signver_commands;
+ signver.options = signver_options;
+
+#ifdef XP_PC
+ progName = strrchr(argv[0], '\\');
+#else
+ progName = strrchr(argv[0], '/');
+#endif
+ progName = progName ? progName + 1 : argv[0];
+
+ rv = SECU_ParseCommandLine(argc, argv, progName, &signver);
+ if (SECSuccess != rv) {
+ Usage(progName, outFile);
+ }
+ debugInfo = signver.options[opt_DebugInfo].activated;
+ verbose = signver.options[opt_PrintWhyFailure].activated;
+ doVerify = signver.commands[cmd_VerifySignedObj].activated;
+ displayAll = signver.commands[cmd_DisplayAllPCKS7Info].activated;
+ if (!doVerify && !displayAll)
+ doVerify = PR_TRUE;
+
+ /* Set the certdb directory (default is ~/.netscape) */
+ rv = NSS_Init(SECU_ConfigDirectory(signver.options[opt_CertDir].arg));
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return result;
+ }
+ /* below here, goto cleanup */
+ SECU_RegisterDynamicOids();
+
+ /* Open the input content file. */
+ if (signver.options[opt_InputDataFile].activated &&
+ signver.options[opt_InputDataFile].arg) {
+ if (PL_strcmp("-", signver.options[opt_InputDataFile].arg)) {
+ contentFile = PR_Open(signver.options[opt_InputDataFile].arg,
+ PR_RDONLY, 0);
+ if (!contentFile) {
+ PR_fprintf(PR_STDERR,
+ "%s: unable to open \"%s\" for reading.\n",
+ progName, signver.options[opt_InputDataFile].arg);
+ goto cleanup;
+ }
+ } else
+ contentFile = PR_STDIN;
+ }
+
+ /* Open the input signature file. */
+ if (signver.options[opt_InputSigFile].activated &&
+ signver.options[opt_InputSigFile].arg) {
+ if (PL_strcmp("-", signver.options[opt_InputSigFile].arg)) {
+ signFile = PR_Open(signver.options[opt_InputSigFile].arg,
+ PR_RDONLY, 0);
+ if (!signFile) {
+ PR_fprintf(PR_STDERR,
+ "%s: unable to open \"%s\" for reading.\n",
+ progName, signver.options[opt_InputSigFile].arg);
+ goto cleanup;
+ }
+ }
+ }
+
+ if (contentFile == PR_STDIN && signFile == PR_STDIN && doVerify) {
+ PR_fprintf(PR_STDERR,
+ "%s: cannot read both content and signature from standard input\n",
+ progName);
+ goto cleanup;
+ }
+
+ /* Open|Create the output file. */
+ if (signver.options[opt_OutputFile].activated) {
+ outFile = fopen(signver.options[opt_OutputFile].arg, "w");
+ if (!outFile) {
+ PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for writing.\n",
+ progName, signver.options[opt_OutputFile].arg);
+ goto cleanup;
+ }
+ }
+
+ /* read in the input files' contents */
+ rv = SECU_ReadDERFromFile(&pkcs7der, signFile,
+ signver.options[opt_ASCII].activated, PR_FALSE);
+ if (signFile != PR_STDIN)
+ PR_Close(signFile);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "problem reading PKCS7 input");
+ goto cleanup;
+ }
+ if (contentFile) {
+ rv = SECU_FileToItem(&content, contentFile);
+ if (contentFile != PR_STDIN)
+ PR_Close(contentFile);
+ if (rv != SECSuccess)
+ content.data = NULL;
+ }
+
+ /* Signature Verification */
+ if (doVerify) {
+ SEC_PKCS7ContentInfo *cinfo;
+ SEC_PKCS7SignedData *signedData;
+ HASH_HashType digestType;
+ PRBool contentIsSigned;
+
+ cinfo = SEC_PKCS7DecodeItem(&pkcs7der, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ if (cinfo == NULL) {
+ PR_fprintf(PR_STDERR, "Unable to decode PKCS7 data\n");
+ goto cleanup;
+ }
+ /* below here, goto done */
+
+ contentIsSigned = SEC_PKCS7ContentIsSigned(cinfo);
+ if (debugInfo) {
+ PR_fprintf(PR_STDERR, "Content is%s encrypted.\n",
+ SEC_PKCS7ContentIsEncrypted(cinfo) ? "" : " not");
+ }
+ if (debugInfo || !contentIsSigned) {
+ PR_fprintf(PR_STDERR, "Content is%s signed.\n",
+ contentIsSigned ? "" : " not");
+ }
+
+ if (!contentIsSigned)
+ goto done;
+
+ signedData = cinfo->content.signedData;
+
+ /* assume that there is only one digest algorithm for now */
+ digestType = AlgorithmToHashType(signedData->digestAlgorithms[0]);
+ if (digestType == HASH_AlgNULL) {
+ PR_fprintf(PR_STDERR, "Invalid hash algorithmID\n");
+ goto done;
+ }
+ if (content.data) {
+ SECCertUsage usage = certUsageEmailSigner;
+ SECItem digest;
+ unsigned char digestBuffer[HASH_LENGTH_MAX];
+
+ if (debugInfo)
+ PR_fprintf(PR_STDERR, "contentToVerify=%s\n", content.data);
+
+ digest.data = digestBuffer;
+ digest.len = sizeof digestBuffer;
+
+ if (DigestContent(&digest, &content, digestType)) {
+ SECU_PrintError(progName, "Message digest computation failure");
+ goto done;
+ }
+
+ if (debugInfo) {
+ unsigned int i;
+ PR_fprintf(PR_STDERR, "Data Digest=:");
+ for (i = 0; i < digest.len; i++)
+ PR_fprintf(PR_STDERR, "%02x:", digest.data[i]);
+ PR_fprintf(PR_STDERR, "\n");
+ }
+
+ fprintf(outFile, "signatureValid=");
+ PORT_SetError(0);
+ if (SEC_PKCS7VerifyDetachedSignature(cinfo, usage,
+ &digest, digestType, PR_FALSE)) {
+ fprintf(outFile, "yes");
+ } else {
+ fprintf(outFile, "no");
+ if (verbose) {
+ fprintf(outFile, ":%s",
+ SECU_Strerror(PORT_GetError()));
+ }
+ }
+ fprintf(outFile, "\n");
+ result = 0;
+ }
+ done:
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ }
+
+ if (displayAll) {
+ if (SV_PrintPKCS7ContentInfo(outFile, &pkcs7der))
+ result = 1;
+ }
+
+cleanup:
+ SECITEM_FreeItem(&pkcs7der, PR_FALSE);
+ SECITEM_FreeItem(&content, PR_FALSE);
+
+ if (NSS_Shutdown() != SECSuccess) {
+ result = 1;
+ }
+
+ return result;
+}
diff --git a/security/nss/cmd/signver/signver.gyp b/security/nss/cmd/signver/signver.gyp
new file mode 100644
index 0000000000..9aeb504591
--- /dev/null
+++ b/security/nss/cmd/signver/signver.gyp
@@ -0,0 +1,26 @@
+# 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': 'signver',
+ 'type': 'executable',
+ 'sources': [
+ 'pk7print.c',
+ 'signver.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file