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
* p7sign -- A command to create a *detached* pkcs7 signature (over a given
41
* $Id: p7sign.c,v 1.10 2004/10/07 04:10:52 julien.pierre.bugs%sun.com Exp $
50
#include "sechash.h" /* for HASH_GetHashObject() */
61
#if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4))
62
extern int fread(char *, size_t, size_t, FILE*);
63
extern int fwrite(char *, size_t, size_t, FILE*);
64
extern int fprintf(FILE *, char *, ...);
67
char* KeyDbPassword = 0;
70
char* MyPK11PasswordFunc (PK11SlotInfo *slot, PRBool retry, void* arg)
76
ret = PL_strdup (KeyDbPassword);
85
"Usage: %s -k keyname [-d keydir] [-i input] [-o output]\n",
87
fprintf(stderr, "%-20s Nickname of key to use for signature\n",
89
fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
91
fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
93
fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
95
fprintf(stderr, "%-20s Encapsulate content in signature message\n",
97
fprintf(stderr, "%-20s Password to the key databse\n", "-p");
102
SignOut(void *arg, const char *buf, unsigned long len)
107
fwrite (buf, len, 1, out);
111
CreateDigest(SECItem *data, char *digestdata, unsigned int *len, unsigned int maxlen)
113
const SECHashObject *hashObj;
116
/* XXX probably want to extend interface to allow other hash algorithms */
117
hashObj = HASH_GetHashObject(HASH_AlgSHA1);
119
hashcx = (* hashObj->create)();
123
(* hashObj->begin)(hashcx);
124
(* hashObj->update)(hashcx, data->data, data->len);
125
(* hashObj->end)(hashcx, (unsigned char *)digestdata, len, maxlen);
126
(* hashObj->destroy)(hashcx, PR_TRUE);
131
SignFile(FILE *outFile, PRFileDesc *inFile, CERTCertificate *cert,
136
SECItem digest, data2sign;
137
SEC_PKCS7ContentInfo *cinfo;
140
if (outFile == NULL || inFile == NULL || cert == NULL)
143
/* suck the file in */
144
if (SECU_ReadDERFromFile(&data2sign, inFile, PR_FALSE) != SECSuccess)
148
/* unfortunately, we must create the digest ourselves */
149
/* SEC_PKCS7CreateSignedData should have a flag to not include */
150
/* the content for non-encapsulated content at encode time, but */
151
/* should always compute the hash itself */
152
if (CreateDigest(&data2sign, digestdata, &len, 32) < 0)
154
digest.data = (unsigned char *)digestdata;
158
/* XXX Need a better way to handle that usage stuff! */
159
cinfo = SEC_PKCS7CreateSignedData (cert, certUsageEmailSigner, NULL,
161
encapsulated ? NULL : &digest,
167
SEC_PKCS7SetContent(cinfo, (char *)data2sign.data, data2sign.len);
170
rv = SEC_PKCS7IncludeCertChain (cinfo, NULL);
171
if (rv != SECSuccess) {
172
SEC_PKCS7DestroyContentInfo (cinfo);
176
rv = SEC_PKCS7Encode (cinfo, SignOut, outFile, NULL,
179
SEC_PKCS7DestroyContentInfo (cinfo);
181
if (rv != SECSuccess)
188
main(int argc, char **argv)
194
CERTCertDBHandle *certHandle;
195
CERTCertificate *cert;
196
PRBool encapsulated = PR_FALSE;
197
PLOptState *optstate;
201
progName = strrchr(argv[0], '/');
202
progName = progName ? progName+1 : argv[0];
209
* Parse command line arguments
211
optstate = PL_CreateOptState(argc, argv, "ed:k:i:o:p:");
212
while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
213
switch (optstate->option) {
219
/* create a message with the signed content encapsulated */
220
encapsulated = PR_TRUE;
224
SECU_ConfigDirectory(optstate->value);
228
inFile = PR_Open(optstate->value, PR_RDONLY, 0);
230
fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
231
progName, optstate->value);
237
keyName = strdup(optstate->value);
241
outFile = fopen(optstate->value, "w");
243
fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
244
progName, optstate->value);
249
KeyDbPassword = strdup (optstate->value);
254
if (!keyName) Usage(progName);
256
if (!inFile) inFile = PR_STDIN;
257
if (!outFile) outFile = stdout;
259
/* Call the initialization routines */
260
PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
261
rv = NSS_Init(SECU_ConfigDirectory(NULL));
262
if (rv != SECSuccess) {
263
SECU_PrintPRandOSError(progName);
267
PK11_SetPasswordFunc (MyPK11PasswordFunc);
269
/* open cert database */
270
certHandle = CERT_GetDefaultCertDB();
271
if (certHandle == NULL) {
276
cert = CERT_FindCertByNickname(certHandle, keyName);
278
SECU_PrintError(progName,
279
"the corresponding cert for key \"%s\" does not exist",
284
if (SignFile(outFile, inFile, cert, encapsulated)) {
285
SECU_PrintError(progName, "problem signing data");
289
if (NSS_Shutdown() != SECSuccess) {