~ubuntu-branches/ubuntu/lucid/seamonkey/lucid-security

« back to all changes in this revision

Viewing changes to security/nss-fips/lib/smime/cmsutil.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabien Tassin
  • Date: 2008-07-29 21:29:02 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20080729212902-spm9kpvchp9udwbw
Tags: 1.1.11+nobinonly-0ubuntu1
* New security upstream release: 1.1.11 (LP: #218534)
  Fixes USN-602-1, USN-619-1, USN-623-1 and USN-629-1
* Refresh diverged patch:
  - update debian/patches/80_security_build.patch
* Fix FTBFS with missing -lfontconfig
  - add debian/patches/11_fix_ftbfs_with_fontconfig.patch
  - update debian/patches/series
* Build with default gcc (hardy: 4.2, intrepid: 4.3)
  - update debian/rules
  - update debian/control

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
 *   Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
 
23
 *
 
24
 * Alternatively, the contents of this file may be used under the terms of
 
25
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
26
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
27
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
28
 * of those above. If you wish to allow use of your version of this file only
 
29
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
30
 * use your version of this file under the terms of the MPL, indicate your
 
31
 * decision by deleting the provisions above and replace them with the notice
 
32
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
33
 * the provisions above, a recipient may use your version of this file under
 
34
 * the terms of any one of the MPL, the GPL or the LGPL.
 
35
 *
 
36
 * ***** END LICENSE BLOCK ***** */
 
37
 
 
38
/*
 
39
 * CMS miscellaneous utility functions.
 
40
 *
 
41
 * $Id: cmsutil.c,v 1.13.2.1 2006/01/21 19:01:34 rrelyea%redhat.com Exp $
 
42
 */
 
43
 
 
44
#include "nssrenam.h"
 
45
 
 
46
#include "cmslocal.h"
 
47
 
 
48
#include "cert.h"
 
49
#include "key.h"
 
50
#include "secasn1.h"
 
51
#include "secitem.h"
 
52
#include "secoid.h"
 
53
#include "pk11func.h"
 
54
#include "secerr.h"
 
55
#include "sechash.h"
 
56
 
 
57
/*
 
58
 * NSS_CMSArray_SortByDER - sort array of objects by objects' DER encoding
 
59
 *
 
60
 * make sure that the order of the objects guarantees valid DER (which must be
 
61
 * in lexigraphically ascending order for a SET OF); if reordering is necessary it
 
62
 * will be done in place (in objs).
 
63
 */
 
64
SECStatus
 
65
NSS_CMSArray_SortByDER(void **objs, const SEC_ASN1Template *objtemplate, void **objs2)
 
66
{
 
67
    PRArenaPool *poolp;
 
68
    int num_objs;
 
69
    SECItem **enc_objs;
 
70
    SECStatus rv = SECFailure;
 
71
    int i;
 
72
 
 
73
    if (objs == NULL)                                   /* already sorted */
 
74
        return SECSuccess;
 
75
 
 
76
    num_objs = NSS_CMSArray_Count((void **)objs);
 
77
    if (num_objs == 0 || num_objs == 1)         /* already sorted. */
 
78
        return SECSuccess;
 
79
 
 
80
    poolp = PORT_NewArena (1024);       /* arena for temporaries */
 
81
    if (poolp == NULL)
 
82
        return SECFailure;              /* no memory; nothing we can do... */
 
83
 
 
84
    /*
 
85
     * Allocate arrays to hold the individual encodings which we will use
 
86
     * for comparisons and the reordered attributes as they are sorted.
 
87
     */
 
88
    enc_objs = (SECItem **)PORT_ArenaZAlloc(poolp, (num_objs + 1) * sizeof(SECItem *));
 
89
    if (enc_objs == NULL)
 
90
        goto loser;
 
91
 
 
92
    /* DER encode each individual object. */
 
93
    for (i = 0; i < num_objs; i++) {
 
94
        enc_objs[i] = SEC_ASN1EncodeItem(poolp, NULL, objs[i], objtemplate);
 
95
        if (enc_objs[i] == NULL)
 
96
            goto loser;
 
97
    }
 
98
    enc_objs[num_objs] = NULL;
 
99
 
 
100
    /* now compare and sort objs by the order of enc_objs */
 
101
    NSS_CMSArray_Sort((void **)enc_objs, NSS_CMSUtil_DERCompare, objs, objs2);
 
102
 
 
103
    rv = SECSuccess;
 
104
 
 
105
loser:
 
106
    PORT_FreeArena (poolp, PR_FALSE);
 
107
    return rv;
 
108
}
 
109
 
 
110
/*
 
111
 * NSS_CMSUtil_DERCompare - for use with NSS_CMSArray_Sort to
 
112
 *  sort arrays of SECItems containing DER
 
113
 */
 
114
int
 
115
NSS_CMSUtil_DERCompare(void *a, void *b)
 
116
{
 
117
    SECItem *der1 = (SECItem *)a;
 
118
    SECItem *der2 = (SECItem *)b;
 
119
    unsigned int j;
 
120
 
 
121
    /*
 
122
     * Find the lowest (lexigraphically) encoding.  One that is
 
123
     * shorter than all the rest is known to be "less" because each
 
124
     * attribute is of the same type (a SEQUENCE) and so thus the
 
125
     * first octet of each is the same, and the second octet is
 
126
     * the length (or the length of the length with the high bit
 
127
     * set, followed by the length, which also works out to always
 
128
     * order the shorter first).  Two (or more) that have the
 
129
     * same length need to be compared byte by byte until a mismatch
 
130
     * is found.
 
131
     */
 
132
    if (der1->len != der2->len)
 
133
        return (der1->len < der2->len) ? -1 : 1;
 
134
 
 
135
    for (j = 0; j < der1->len; j++) {
 
136
        if (der1->data[j] == der2->data[j])
 
137
            continue;
 
138
        return (der1->data[j] < der2->data[j]) ? -1 : 1;
 
139
    }
 
140
    return 0;
 
141
}
 
142
 
 
143
/*
 
144
 * NSS_CMSAlgArray_GetIndexByAlgID - find a specific algorithm in an array of 
 
145
 * algorithms.
 
146
 *
 
147
 * algorithmArray - array of algorithm IDs
 
148
 * algid - algorithmid of algorithm to pick
 
149
 *
 
150
 * Returns:
 
151
 *  An integer containing the index of the algorithm in the array or -1 if 
 
152
 *  algorithm was not found.
 
153
 */
 
154
int
 
155
NSS_CMSAlgArray_GetIndexByAlgID(SECAlgorithmID **algorithmArray, SECAlgorithmID *algid)
 
156
{
 
157
    int i;
 
158
 
 
159
    if (algorithmArray == NULL || algorithmArray[0] == NULL)
 
160
        return -1;
 
161
 
 
162
    for (i = 0; algorithmArray[i] != NULL; i++) {
 
163
        if (SECOID_CompareAlgorithmID(algorithmArray[i], algid) == SECEqual)
 
164
            break;      /* bingo */
 
165
    }
 
166
 
 
167
    if (algorithmArray[i] == NULL)
 
168
        return -1;      /* not found */
 
169
 
 
170
    return i;
 
171
}
 
172
 
 
173
/*
 
174
 * NSS_CMSAlgArray_GetIndexByAlgTag - find a specific algorithm in an array of 
 
175
 * algorithms.
 
176
 *
 
177
 * algorithmArray - array of algorithm IDs
 
178
 * algtag - algorithm tag of algorithm to pick
 
179
 *
 
180
 * Returns:
 
181
 *  An integer containing the index of the algorithm in the array or -1 if 
 
182
 *  algorithm was not found.
 
183
 */
 
184
int
 
185
NSS_CMSAlgArray_GetIndexByAlgTag(SECAlgorithmID **algorithmArray, 
 
186
                                 SECOidTag algtag)
 
187
{
 
188
    SECOidData *algid;
 
189
    int i = -1;
 
190
 
 
191
    if (algorithmArray == NULL || algorithmArray[0] == NULL)
 
192
        return i;
 
193
 
 
194
#ifdef ORDER_N_SQUARED
 
195
    for (i = 0; algorithmArray[i] != NULL; i++) {
 
196
        algid = SECOID_FindOID(&(algorithmArray[i]->algorithm));
 
197
        if (algid->offset == algtag)
 
198
            break;      /* bingo */
 
199
    }
 
200
#else
 
201
    algid = SECOID_FindOIDByTag(algtag);
 
202
    if (!algid) 
 
203
        return i;
 
204
    for (i = 0; algorithmArray[i] != NULL; i++) {
 
205
        if (SECITEM_ItemsAreEqual(&algorithmArray[i]->algorithm, &algid->oid))
 
206
            break;      /* bingo */
 
207
    }
 
208
#endif
 
209
 
 
210
    if (algorithmArray[i] == NULL)
 
211
        return -1;      /* not found */
 
212
 
 
213
    return i;
 
214
}
 
215
 
 
216
const SECHashObject *
 
217
NSS_CMSUtil_GetHashObjByAlgID(SECAlgorithmID *algid)
 
218
{
 
219
    SECOidTag oidTag = SECOID_FindOIDTag(&(algid->algorithm));
 
220
    const SECHashObject *digobj = HASH_GetHashObjectByOidTag(oidTag);
 
221
 
 
222
    return digobj;
 
223
}
 
224
 
 
225
/*
 
226
 * XXX I would *really* like to not have to do this, but the current
 
227
 * signing interface gives me little choice.
 
228
 */
 
229
SECOidTag
 
230
NSS_CMSUtil_MakeSignatureAlgorithm(SECOidTag hashalg, SECOidTag encalg)
 
231
{
 
232
    switch (encalg) {
 
233
      case SEC_OID_PKCS1_RSA_ENCRYPTION:
 
234
        switch (hashalg) {
 
235
          case SEC_OID_MD2:
 
236
            return SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
 
237
          case SEC_OID_MD5:
 
238
            return SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
 
239
          case SEC_OID_SHA1:
 
240
            return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
 
241
          case SEC_OID_SHA256:
 
242
            return SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
 
243
          case SEC_OID_SHA384:
 
244
            return SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
 
245
          case SEC_OID_SHA512:
 
246
            return SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
 
247
          default:
 
248
            return SEC_OID_UNKNOWN;
 
249
        }
 
250
      case SEC_OID_ANSIX9_DSA_SIGNATURE:
 
251
      case SEC_OID_MISSI_KEA_DSS:
 
252
      case SEC_OID_MISSI_DSS:
 
253
        switch (hashalg) {
 
254
          case SEC_OID_SHA1:
 
255
            return SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
 
256
          default:
 
257
            return SEC_OID_UNKNOWN;
 
258
        }
 
259
      case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
 
260
        switch (hashalg) {
 
261
          case SEC_OID_SHA1:
 
262
            return SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE;
 
263
          case SEC_OID_SHA256:
 
264
            return SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE;
 
265
          case SEC_OID_SHA384:
 
266
            return SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE;
 
267
          case SEC_OID_SHA512:
 
268
            return SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE;
 
269
          default:
 
270
            return SEC_OID_UNKNOWN;
 
271
        }
 
272
      default:
 
273
        break;
 
274
    }
 
275
 
 
276
    return encalg;              /* maybe it is already the right algid */
 
277
}
 
278
 
 
279
const SEC_ASN1Template *
 
280
NSS_CMSUtil_GetTemplateByTypeTag(SECOidTag type)
 
281
{
 
282
    const SEC_ASN1Template *template;
 
283
    extern const SEC_ASN1Template NSSCMSSignedDataTemplate[];
 
284
    extern const SEC_ASN1Template NSSCMSEnvelopedDataTemplate[];
 
285
    extern const SEC_ASN1Template NSSCMSEncryptedDataTemplate[];
 
286
    extern const SEC_ASN1Template NSSCMSDigestedDataTemplate[];
 
287
 
 
288
    switch (type) {
 
289
    case SEC_OID_PKCS7_SIGNED_DATA:
 
290
        template = NSSCMSSignedDataTemplate;
 
291
        break;
 
292
    case SEC_OID_PKCS7_ENVELOPED_DATA:
 
293
        template = NSSCMSEnvelopedDataTemplate;
 
294
        break;
 
295
    case SEC_OID_PKCS7_ENCRYPTED_DATA:
 
296
        template = NSSCMSEncryptedDataTemplate;
 
297
        break;
 
298
    case SEC_OID_PKCS7_DIGESTED_DATA:
 
299
        template = NSSCMSDigestedDataTemplate;
 
300
        break;
 
301
    default:
 
302
    case SEC_OID_PKCS7_DATA:
 
303
        template = NULL;
 
304
        break;
 
305
    }
 
306
    return template;
 
307
}
 
308
 
 
309
size_t
 
310
NSS_CMSUtil_GetSizeByTypeTag(SECOidTag type)
 
311
{
 
312
    size_t size;
 
313
 
 
314
    switch (type) {
 
315
    case SEC_OID_PKCS7_SIGNED_DATA:
 
316
        size = sizeof(NSSCMSSignedData);
 
317
        break;
 
318
    case SEC_OID_PKCS7_ENVELOPED_DATA:
 
319
        size = sizeof(NSSCMSEnvelopedData);
 
320
        break;
 
321
    case SEC_OID_PKCS7_ENCRYPTED_DATA:
 
322
        size = sizeof(NSSCMSEncryptedData);
 
323
        break;
 
324
    case SEC_OID_PKCS7_DIGESTED_DATA:
 
325
        size = sizeof(NSSCMSDigestedData);
 
326
        break;
 
327
    default:
 
328
    case SEC_OID_PKCS7_DATA:
 
329
        size = 0;
 
330
        break;
 
331
    }
 
332
    return size;
 
333
}
 
334
 
 
335
NSSCMSContentInfo *
 
336
NSS_CMSContent_GetContentInfo(void *msg, SECOidTag type)
 
337
{
 
338
    NSSCMSContent c;
 
339
    NSSCMSContentInfo *cinfo = NULL;
 
340
 
 
341
    if (!msg)
 
342
        return cinfo;
 
343
    c.pointer = msg;
 
344
    switch (type) {
 
345
    case SEC_OID_PKCS7_SIGNED_DATA:
 
346
        cinfo = &(c.signedData->contentInfo);
 
347
        break;
 
348
    case SEC_OID_PKCS7_ENVELOPED_DATA:
 
349
        cinfo = &(c.envelopedData->contentInfo);
 
350
        break;
 
351
    case SEC_OID_PKCS7_ENCRYPTED_DATA:
 
352
        cinfo = &(c.encryptedData->contentInfo);
 
353
        break;
 
354
    case SEC_OID_PKCS7_DIGESTED_DATA:
 
355
        cinfo = &(c.digestedData->contentInfo);
 
356
        break;
 
357
    default:
 
358
        cinfo = NULL;
 
359
    }
 
360
    return cinfo;
 
361
}
 
362
 
 
363
const char *
 
364
NSS_CMSUtil_VerificationStatusToString(NSSCMSVerificationStatus vs)
 
365
{
 
366
    switch (vs) {
 
367
    case NSSCMSVS_Unverified:                   return "Unverified";
 
368
    case NSSCMSVS_GoodSignature:                return "GoodSignature";
 
369
    case NSSCMSVS_BadSignature:                 return "BadSignature";
 
370
    case NSSCMSVS_DigestMismatch:               return "DigestMismatch";
 
371
    case NSSCMSVS_SigningCertNotFound:          return "SigningCertNotFound";
 
372
    case NSSCMSVS_SigningCertNotTrusted:        return "SigningCertNotTrusted";
 
373
    case NSSCMSVS_SignatureAlgorithmUnknown:    return "SignatureAlgorithmUnknown";
 
374
    case NSSCMSVS_SignatureAlgorithmUnsupported: return "SignatureAlgorithmUnsupported";
 
375
    case NSSCMSVS_MalformedSignature:           return "MalformedSignature";
 
376
    case NSSCMSVS_ProcessingError:              return "ProcessingError";
 
377
    default:                                    return "Unknown";
 
378
    }
 
379
}
 
380
 
 
381
SECStatus
 
382
NSS_CMSDEREncode(NSSCMSMessage *cmsg, SECItem *input, SECItem *derOut, 
 
383
                 PLArenaPool *arena)
 
384
{
 
385
    NSSCMSEncoderContext *ecx;
 
386
    SECStatus rv = SECSuccess;
 
387
    if (!cmsg || !derOut || !arena) {
 
388
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
389
        return SECFailure;
 
390
    }
 
391
    ecx = NSS_CMSEncoder_Start(cmsg, 0, 0, derOut, arena, 0, 0, 0, 0, 0, 0);
 
392
    if (!ecx) {
 
393
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
 
394
        return SECFailure;
 
395
    }
 
396
    if (input) {
 
397
        rv = NSS_CMSEncoder_Update(ecx, (const char*)input->data, input->len);
 
398
        if (rv) {
 
399
            PORT_SetError(SEC_ERROR_BAD_DATA);
 
400
        }
 
401
    }
 
402
    rv |= NSS_CMSEncoder_Finish(ecx);
 
403
    if (rv) {
 
404
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
 
405
    }
 
406
    return rv;
 
407
}