1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
38 * p7verify -- A command to do a verification of a *detached* pkcs7 signature.
40 * $Id: p7verify.c,v 1.10 2008/08/08 23:47:57 julien.pierre.boogz%sun.com Exp $
50 #include "sechash.h" /* for HASH_GetHashObject() */
60 #if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4))
61 extern int fread(char *, size_t, size_t, FILE*);
62 extern int fprintf(FILE *, char *, ...);
67 AlgorithmToHashType(SECAlgorithmID
*digestAlgorithms
)
72 tag
= SECOID_GetAlgorithmTag(digestAlgorithms
);
82 fprintf(stderr
, "should never get here\n");
88 DigestFile(unsigned char *digest
, unsigned int *len
, unsigned int maxLen
,
89 FILE *inFile
, HASH_HashType hashType
)
92 unsigned char ibuf
[4096];
93 const SECHashObject
*hashObj
;
96 hashObj
= HASH_GetHashObject(hashType
);
98 hashcx
= (* hashObj
->create
)();
102 (* hashObj
->begin
)(hashcx
);
105 if (feof(inFile
)) break;
106 nb
= fread(ibuf
, 1, sizeof(ibuf
), inFile
);
107 if (nb
!= sizeof(ibuf
)) {
109 if (ferror(inFile
)) {
110 PORT_SetError(SEC_ERROR_IO
);
111 (* hashObj
->destroy
)(hashcx
, PR_TRUE
);
118 (* hashObj
->update
)(hashcx
, ibuf
, nb
);
121 (* hashObj
->end
)(hashcx
, digest
, len
, maxLen
);
122 (* hashObj
->destroy
)(hashcx
, PR_TRUE
);
129 Usage(char *progName
)
132 "Usage: %s -c content -s signature [-d dbdir] [-u certusage]\n",
134 fprintf(stderr
, "%-20s content file that was signed\n",
136 fprintf(stderr
, "%-20s file containing signature for that content\n",
139 "%-20s Key/Cert database directory (default is ~/.netscape)\n",
141 fprintf(stderr
, "%-20s Define the type of certificate usage (default is certUsageEmailSigner)\n",
143 fprintf(stderr
, "%-25s 0 - certUsageSSLClient\n", " ");
144 fprintf(stderr
, "%-25s 1 - certUsageSSLServer\n", " ");
145 fprintf(stderr
, "%-25s 2 - certUsageSSLServerWithStepUp\n", " ");
146 fprintf(stderr
, "%-25s 3 - certUsageSSLCA\n", " ");
147 fprintf(stderr
, "%-25s 4 - certUsageEmailSigner\n", " ");
148 fprintf(stderr
, "%-25s 5 - certUsageEmailRecipient\n", " ");
149 fprintf(stderr
, "%-25s 6 - certUsageObjectSigner\n", " ");
150 fprintf(stderr
, "%-25s 7 - certUsageUserCertImport\n", " ");
151 fprintf(stderr
, "%-25s 8 - certUsageVerifyCA\n", " ");
152 fprintf(stderr
, "%-25s 9 - certUsageProtectedObjectSigner\n", " ");
153 fprintf(stderr
, "%-25s 10 - certUsageStatusResponder\n", " ");
154 fprintf(stderr
, "%-25s 11 - certUsageAnyCA\n", " ");
160 HashDecodeAndVerify(FILE *out
, FILE *content
, PRFileDesc
*signature
,
161 SECCertUsage usage
, char *progName
)
164 SEC_PKCS7ContentInfo
*cinfo
;
165 SEC_PKCS7SignedData
*signedData
;
166 HASH_HashType digestType
;
168 unsigned char buffer
[32];
170 if (SECU_ReadDERFromFile(&derdata
, signature
, PR_FALSE
) != SECSuccess
) {
171 SECU_PrintError(progName
, "error reading signature file");
175 cinfo
= SEC_PKCS7DecodeItem(&derdata
, NULL
, NULL
, NULL
, NULL
,
180 if (! SEC_PKCS7ContentIsSigned(cinfo
)) {
181 fprintf (out
, "Signature file is pkcs7 data, but not signed.\n");
185 signedData
= cinfo
->content
.signedData
;
187 /* assume that there is only one digest algorithm for now */
188 digestType
= AlgorithmToHashType(signedData
->digestAlgorithms
[0]);
189 if (digestType
== HASH_AlgNULL
) {
190 fprintf (out
, "Invalid hash algorithmID\n");
194 digest
.data
= buffer
;
195 if (DigestFile (digest
.data
, &digest
.len
, 32, content
, digestType
)) {
196 SECU_PrintError (progName
, "problem computing message digest");
200 fprintf(out
, "Signature is ");
201 if (SEC_PKCS7VerifyDetachedSignature (cinfo
, usage
, &digest
, digestType
,
203 fprintf(out
, "valid.\n");
205 fprintf(out
, "invalid (Reason: %s).\n",
206 SECU_Strerror(PORT_GetError()));
208 SEC_PKCS7DestroyContentInfo(cinfo
);
214 main(int argc
, char **argv
)
217 FILE *contentFile
, *outFile
;
218 PRFileDesc
*signatureFile
;
219 SECCertUsage certUsage
= certUsageEmailSigner
;
220 PLOptState
*optstate
;
224 progName
= strrchr(argv
[0], '/');
225 progName
= progName
? progName
+1 : argv
[0];
228 signatureFile
= NULL
;
232 * Parse command line arguments
234 optstate
= PL_CreateOptState(argc
, argv
, "c:d:o:s:u:");
235 while ((status
= PL_GetNextOpt(optstate
)) == PL_OPT_OK
) {
236 switch (optstate
->option
) {
242 contentFile
= fopen(optstate
->value
, "r");
244 fprintf(stderr
, "%s: unable to open \"%s\" for reading\n",
245 progName
, optstate
->value
);
251 SECU_ConfigDirectory(optstate
->value
);
255 outFile
= fopen(optstate
->value
, "w");
257 fprintf(stderr
, "%s: unable to open \"%s\" for writing\n",
258 progName
, optstate
->value
);
264 signatureFile
= PR_Open(optstate
->value
, PR_RDONLY
, 0);
265 if (!signatureFile
) {
266 fprintf(stderr
, "%s: unable to open \"%s\" for reading\n",
267 progName
, optstate
->value
);
275 usageType
= atoi (strdup(optstate
->value
));
276 if (usageType
< certUsageSSLClient
|| usageType
> certUsageAnyCA
)
278 certUsage
= (SECCertUsage
)usageType
;
285 if (!contentFile
) Usage (progName
);
286 if (!signatureFile
) Usage (progName
);
287 if (!outFile
) outFile
= stdout
;
289 /* Call the NSS initialization routines */
290 PR_Init(PR_SYSTEM_THREAD
, PR_PRIORITY_NORMAL
, 1);
291 rv
= NSS_Init(SECU_ConfigDirectory(NULL
));
292 if (rv
!= SECSuccess
) {
293 SECU_PrintPRandOSError(progName
);
297 if (HashDecodeAndVerify(outFile
, contentFile
, signatureFile
,
298 certUsage
, progName
)) {
299 SECU_PrintError(progName
, "problem decoding/verifying signature");
303 if (NSS_Shutdown() != SECSuccess
) {