diff options
Diffstat (limited to 'security/nss/cmd/signver')
-rw-r--r-- | security/nss/cmd/signver/Makefile | 43 | ||||
-rwxr-xr-x | security/nss/cmd/signver/examples/1/form.pl | 22 | ||||
-rw-r--r-- | security/nss/cmd/signver/examples/1/signedForm.html | 55 | ||||
-rw-r--r-- | security/nss/cmd/signver/examples/1/signedForm.nt.html | 55 | ||||
-rwxr-xr-x | security/nss/cmd/signver/examples/1/signedForm.pl | 60 | ||||
-rw-r--r-- | security/nss/cmd/signver/manifest.mn | 24 | ||||
-rw-r--r-- | security/nss/cmd/signver/pk7print.c | 907 | ||||
-rw-r--r-- | security/nss/cmd/signver/signver.c | 313 | ||||
-rw-r--r-- | security/nss/cmd/signver/signver.gyp | 26 |
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 |