~ubuntu-branches/ubuntu/trusty/xulrunner/trusty

« back to all changes in this revision

Viewing changes to security/nss-fips/cmd/p7sign/p7sign.c

  • Committer: Bazaar Package Importer
  • Author(s): Devid Antonio Filoni
  • Date: 2008-08-25 13:04:18 UTC
  • mfrom: (1.1.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20080825130418-ck1i2ms384tzb9m0
Tags: 1.8.1.16+nobinonly-0ubuntu1
* New upstream release (taken from upstream CVS), LP: #254618.
* Fix MFSA 2008-35, MFSA 2008-34, MFSA 2008-33, MFSA 2008-32, MFSA 2008-31,
  MFSA 2008-30, MFSA 2008-29, MFSA 2008-28, MFSA 2008-27, MFSA 2008-25,
  MFSA 2008-24, MFSA 2008-23, MFSA 2008-22, MFSA 2008-21, MFSA 2008-26 also
  known as CVE-2008-2933, CVE-2008-2785, CVE-2008-2811, CVE-2008-2810,
  CVE-2008-2809, CVE-2008-2808, CVE-2008-2807, CVE-2008-2806, CVE-2008-2805,
  CVE-2008-2803, CVE-2008-2802, CVE-2008-2801, CVE-2008-2800, CVE-2008-2798.
* Drop 89_bz419350_attachment_306066 patch, merged upstream.
* Bump Standards-Version to 3.8.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ***** BEGIN LICENSE BLOCK *****
 
2
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
3
 *
 
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/
 
8
 *
 
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
 
12
 * License.
 
13
 *
 
14
 * The Original Code is the Netscape security libraries.
 
15
 *
 
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.
 
20
 *
 
21
 * Contributor(s):
 
22
 *
 
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.
 
34
 *
 
35
 * ***** END LICENSE BLOCK ***** */
 
36
 
 
37
/*
 
38
 * p7sign -- A command to create a *detached* pkcs7 signature (over a given
 
39
 * input file).
 
40
 *
 
41
 * $Id: p7sign.c,v 1.10 2004/10/07 04:10:52 julien.pierre.bugs%sun.com Exp $
 
42
 */
 
43
 
 
44
#include "nspr.h"
 
45
#include "plgetopt.h"
 
46
#include "secutil.h"
 
47
#include "secpkcs7.h"
 
48
#include "cert.h"
 
49
#include "certdb.h"
 
50
#include "sechash.h"    /* for HASH_GetHashObject() */
 
51
#include "nss.h"
 
52
#include "pk11func.h"
 
53
 
 
54
#if defined(XP_UNIX)
 
55
#include <unistd.h>
 
56
#endif
 
57
 
 
58
#include <stdio.h>
 
59
#include <string.h>
 
60
 
 
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 *, ...);
 
65
#endif
 
66
 
 
67
char* KeyDbPassword = 0;
 
68
 
 
69
 
 
70
char* MyPK11PasswordFunc (PK11SlotInfo *slot, PRBool retry, void* arg)
 
71
{
 
72
    char *ret=0;
 
73
 
 
74
    if (retry == PR_TRUE)
 
75
        return NULL;
 
76
    ret = PL_strdup (KeyDbPassword);
 
77
    return ret;
 
78
}
 
79
 
 
80
 
 
81
static void
 
82
Usage(char *progName)
 
83
{
 
84
    fprintf(stderr,
 
85
            "Usage:  %s -k keyname [-d keydir] [-i input] [-o output]\n",
 
86
            progName);
 
87
    fprintf(stderr, "%-20s Nickname of key to use for signature\n",
 
88
            "-k keyname");
 
89
    fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
 
90
            "-d keydir");
 
91
    fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
 
92
            "-i input");
 
93
    fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
 
94
            "-o output");
 
95
    fprintf(stderr, "%-20s Encapsulate content in signature message\n",
 
96
            "-e");
 
97
    fprintf(stderr, "%-20s Password to the key databse\n", "-p");
 
98
    exit(-1);
 
99
}
 
100
 
 
101
static void
 
102
SignOut(void *arg, const char *buf, unsigned long len)
 
103
{
 
104
   FILE *out;
 
105
 
 
106
   out = (FILE*) arg; 
 
107
   fwrite (buf, len, 1, out);
 
108
}
 
109
 
 
110
static int
 
111
CreateDigest(SECItem *data, char *digestdata, unsigned int *len, unsigned int maxlen)
 
112
{
 
113
    const SECHashObject *hashObj;
 
114
    void *hashcx;
 
115
 
 
116
    /* XXX probably want to extend interface to allow other hash algorithms */
 
117
    hashObj = HASH_GetHashObject(HASH_AlgSHA1);
 
118
 
 
119
    hashcx = (* hashObj->create)();
 
120
    if (hashcx == NULL)
 
121
        return -1;
 
122
 
 
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);
 
127
    return 0;
 
128
}
 
129
 
 
130
static int
 
131
SignFile(FILE *outFile, PRFileDesc *inFile, CERTCertificate *cert, 
 
132
         PRBool encapsulated)
 
133
{
 
134
    char digestdata[32];
 
135
    unsigned int len;
 
136
    SECItem digest, data2sign;
 
137
    SEC_PKCS7ContentInfo *cinfo;
 
138
    SECStatus rv;
 
139
 
 
140
    if (outFile == NULL || inFile == NULL || cert == NULL)
 
141
        return -1;
 
142
 
 
143
    /* suck the file in */
 
144
        if (SECU_ReadDERFromFile(&data2sign, inFile, PR_FALSE) != SECSuccess)
 
145
        return -1;
 
146
 
 
147
    if (!encapsulated) {
 
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)
 
153
            return -1;
 
154
        digest.data = (unsigned char *)digestdata;
 
155
        digest.len = len;
 
156
    }
 
157
 
 
158
    /* XXX Need a better way to handle that usage stuff! */
 
159
    cinfo = SEC_PKCS7CreateSignedData (cert, certUsageEmailSigner, NULL,
 
160
                                       SEC_OID_SHA1,
 
161
                                       encapsulated ? NULL : &digest,
 
162
                                       NULL, NULL);
 
163
    if (cinfo == NULL)
 
164
        return -1;
 
165
 
 
166
    if (encapsulated) {
 
167
        SEC_PKCS7SetContent(cinfo, (char *)data2sign.data, data2sign.len);
 
168
    }
 
169
 
 
170
    rv = SEC_PKCS7IncludeCertChain (cinfo, NULL);
 
171
    if (rv != SECSuccess) {
 
172
        SEC_PKCS7DestroyContentInfo (cinfo);
 
173
        return -1;
 
174
    }
 
175
 
 
176
    rv = SEC_PKCS7Encode (cinfo, SignOut, outFile, NULL,
 
177
                          NULL, NULL);
 
178
 
 
179
    SEC_PKCS7DestroyContentInfo (cinfo);
 
180
 
 
181
    if (rv != SECSuccess)
 
182
        return -1;
 
183
 
 
184
    return 0;
 
185
}
 
186
 
 
187
int
 
188
main(int argc, char **argv)
 
189
{
 
190
    char *progName;
 
191
    FILE *outFile;
 
192
    PRFileDesc *inFile;
 
193
    char *keyName;
 
194
    CERTCertDBHandle *certHandle;
 
195
    CERTCertificate *cert;
 
196
    PRBool encapsulated = PR_FALSE;
 
197
    PLOptState *optstate;
 
198
    PLOptStatus status;
 
199
    SECStatus rv;
 
200
 
 
201
    progName = strrchr(argv[0], '/');
 
202
    progName = progName ? progName+1 : argv[0];
 
203
 
 
204
    inFile = NULL;
 
205
    outFile = NULL;
 
206
    keyName = NULL;
 
207
 
 
208
    /*
 
209
     * Parse command line arguments
 
210
     */
 
211
    optstate = PL_CreateOptState(argc, argv, "ed:k:i:o:p:");
 
212
    while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
 
213
        switch (optstate->option) {
 
214
          case '?':
 
215
            Usage(progName);
 
216
            break;
 
217
 
 
218
          case 'e':
 
219
            /* create a message with the signed content encapsulated */
 
220
            encapsulated = PR_TRUE;
 
221
            break;
 
222
 
 
223
          case 'd':
 
224
            SECU_ConfigDirectory(optstate->value);
 
225
            break;
 
226
 
 
227
          case 'i':
 
228
            inFile = PR_Open(optstate->value, PR_RDONLY, 0);
 
229
            if (!inFile) {
 
230
                fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
 
231
                        progName, optstate->value);
 
232
                return -1;
 
233
            }
 
234
            break;
 
235
 
 
236
          case 'k':
 
237
            keyName = strdup(optstate->value);
 
238
            break;
 
239
 
 
240
          case 'o':
 
241
            outFile = fopen(optstate->value, "w");
 
242
            if (!outFile) {
 
243
                fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
 
244
                        progName, optstate->value);
 
245
                return -1;
 
246
            }
 
247
            break;
 
248
          case 'p':
 
249
            KeyDbPassword = strdup (optstate->value);
 
250
            break;
 
251
        }
 
252
    }
 
253
 
 
254
    if (!keyName) Usage(progName);
 
255
 
 
256
    if (!inFile) inFile = PR_STDIN;
 
257
    if (!outFile) outFile = stdout;
 
258
 
 
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);
 
264
        return -1;
 
265
    }
 
266
 
 
267
    PK11_SetPasswordFunc (MyPK11PasswordFunc);
 
268
 
 
269
    /* open cert database */
 
270
    certHandle = CERT_GetDefaultCertDB();
 
271
    if (certHandle == NULL) {
 
272
        return -1;
 
273
    }
 
274
 
 
275
    /* find cert */
 
276
    cert = CERT_FindCertByNickname(certHandle, keyName);
 
277
    if (cert == NULL) {
 
278
        SECU_PrintError(progName,
 
279
                        "the corresponding cert for key \"%s\" does not exist",
 
280
                        keyName);
 
281
        return -1;
 
282
    }
 
283
 
 
284
    if (SignFile(outFile, inFile, cert, encapsulated)) {
 
285
        SECU_PrintError(progName, "problem signing data");
 
286
        return -1;
 
287
    }
 
288
 
 
289
    if (NSS_Shutdown() != SECSuccess) {
 
290
        exit(1);
 
291
    }
 
292
 
 
293
    return 0;
 
294
}