~ubuntu-branches/ubuntu/hardy/openssl/hardy-security

« back to all changes in this revision

Viewing changes to crypto/pkcs7/pk7_lib.c

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Martin
  • Date: 2004-05-24 17:02:29 UTC
  • Revision ID: james.westby@ubuntu.com-20040524170229-ixlo08bbbly0xied
Tags: upstream-0.9.7d
ImportĀ upstreamĀ versionĀ 0.9.7d

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* crypto/pkcs7/pk7_lib.c */
 
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
 
3
 * All rights reserved.
 
4
 *
 
5
 * This package is an SSL implementation written
 
6
 * by Eric Young (eay@cryptsoft.com).
 
7
 * The implementation was written so as to conform with Netscapes SSL.
 
8
 * 
 
9
 * This library is free for commercial and non-commercial use as long as
 
10
 * the following conditions are aheared to.  The following conditions
 
11
 * apply to all code found in this distribution, be it the RC4, RSA,
 
12
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
 
13
 * included with this distribution is covered by the same copyright terms
 
14
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
 
15
 * 
 
16
 * Copyright remains Eric Young's, and as such any Copyright notices in
 
17
 * the code are not to be removed.
 
18
 * If this package is used in a product, Eric Young should be given attribution
 
19
 * as the author of the parts of the library used.
 
20
 * This can be in the form of a textual message at program startup or
 
21
 * in documentation (online or textual) provided with the package.
 
22
 * 
 
23
 * Redistribution and use in source and binary forms, with or without
 
24
 * modification, are permitted provided that the following conditions
 
25
 * are met:
 
26
 * 1. Redistributions of source code must retain the copyright
 
27
 *    notice, this list of conditions and the following disclaimer.
 
28
 * 2. Redistributions in binary form must reproduce the above copyright
 
29
 *    notice, this list of conditions and the following disclaimer in the
 
30
 *    documentation and/or other materials provided with the distribution.
 
31
 * 3. All advertising materials mentioning features or use of this software
 
32
 *    must display the following acknowledgement:
 
33
 *    "This product includes cryptographic software written by
 
34
 *     Eric Young (eay@cryptsoft.com)"
 
35
 *    The word 'cryptographic' can be left out if the rouines from the library
 
36
 *    being used are not cryptographic related :-).
 
37
 * 4. If you include any Windows specific code (or a derivative thereof) from 
 
38
 *    the apps directory (application code) you must include an acknowledgement:
 
39
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
 
40
 * 
 
41
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
 
42
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
44
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 
45
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
46
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
47
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
49
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
50
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
51
 * SUCH DAMAGE.
 
52
 * 
 
53
 * The licence and distribution terms for any publically available version or
 
54
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 
55
 * copied and put under another distribution licence
 
56
 * [including the GNU Public Licence.]
 
57
 */
 
58
 
 
59
#include <stdio.h>
 
60
#include "cryptlib.h"
 
61
#include <openssl/objects.h>
 
62
#include <openssl/x509.h>
 
63
 
 
64
long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg)
 
65
        {
 
66
        int nid;
 
67
        long ret;
 
68
 
 
69
        nid=OBJ_obj2nid(p7->type);
 
70
 
 
71
        switch (cmd)
 
72
                {
 
73
        case PKCS7_OP_SET_DETACHED_SIGNATURE:
 
74
                if (nid == NID_pkcs7_signed)
 
75
                        {
 
76
                        ret=p7->detached=(int)larg;
 
77
                        if (ret && PKCS7_type_is_data(p7->d.sign->contents))
 
78
                                        {
 
79
                                        ASN1_OCTET_STRING *os;
 
80
                                        os=p7->d.sign->contents->d.data;
 
81
                                        ASN1_OCTET_STRING_free(os);
 
82
                                        p7->d.sign->contents->d.data = NULL;
 
83
                                        }
 
84
                        }
 
85
                else
 
86
                        {
 
87
                        PKCS7err(PKCS7_F_PKCS7_CTRL,PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE);
 
88
                        ret=0;
 
89
                        }
 
90
                break;
 
91
        case PKCS7_OP_GET_DETACHED_SIGNATURE:
 
92
                if (nid == NID_pkcs7_signed)
 
93
                        {
 
94
                        if(!p7->d.sign  || !p7->d.sign->contents->d.ptr)
 
95
                                ret = 1;
 
96
                        else ret = 0;
 
97
                                
 
98
                        p7->detached = ret;
 
99
                        }
 
100
                else
 
101
                        {
 
102
                        PKCS7err(PKCS7_F_PKCS7_CTRL,PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE);
 
103
                        ret=0;
 
104
                        }
 
105
                        
 
106
                break;
 
107
        default:
 
108
                PKCS7err(PKCS7_F_PKCS7_CTRL,PKCS7_R_UNKNOWN_OPERATION);
 
109
                ret=0;
 
110
                }
 
111
        return(ret);
 
112
        }
 
113
 
 
114
int PKCS7_content_new(PKCS7 *p7, int type)
 
115
        {
 
116
        PKCS7 *ret=NULL;
 
117
 
 
118
        if ((ret=PKCS7_new()) == NULL) goto err;
 
119
        if (!PKCS7_set_type(ret,type)) goto err;
 
120
        if (!PKCS7_set_content(p7,ret)) goto err;
 
121
 
 
122
        return(1);
 
123
err:
 
124
        if (ret != NULL) PKCS7_free(ret);
 
125
        return(0);
 
126
        }
 
127
 
 
128
int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data)
 
129
        {
 
130
        int i;
 
131
 
 
132
        i=OBJ_obj2nid(p7->type);
 
133
        switch (i)
 
134
                {
 
135
        case NID_pkcs7_signed:
 
136
                if (p7->d.sign->contents != NULL)
 
137
                        PKCS7_free(p7->d.sign->contents);
 
138
                p7->d.sign->contents=p7_data;
 
139
                break;
 
140
        case NID_pkcs7_digest:
 
141
        case NID_pkcs7_data:
 
142
        case NID_pkcs7_enveloped:
 
143
        case NID_pkcs7_signedAndEnveloped:
 
144
        case NID_pkcs7_encrypted:
 
145
        default:
 
146
                PKCS7err(PKCS7_F_PKCS7_SET_CONTENT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
 
147
                goto err;
 
148
                }
 
149
        return(1);
 
150
err:
 
151
        return(0);
 
152
        }
 
153
 
 
154
int PKCS7_set_type(PKCS7 *p7, int type)
 
155
        {
 
156
        ASN1_OBJECT *obj;
 
157
 
 
158
        /*PKCS7_content_free(p7);*/
 
159
        obj=OBJ_nid2obj(type); /* will not fail */
 
160
 
 
161
        switch (type)
 
162
                {
 
163
        case NID_pkcs7_signed:
 
164
                p7->type=obj;
 
165
                if ((p7->d.sign=PKCS7_SIGNED_new()) == NULL)
 
166
                        goto err;
 
167
                ASN1_INTEGER_set(p7->d.sign->version,1);
 
168
                break;
 
169
        case NID_pkcs7_data:
 
170
                p7->type=obj;
 
171
                if ((p7->d.data=M_ASN1_OCTET_STRING_new()) == NULL)
 
172
                        goto err;
 
173
                break;
 
174
        case NID_pkcs7_signedAndEnveloped:
 
175
                p7->type=obj;
 
176
                if ((p7->d.signed_and_enveloped=PKCS7_SIGN_ENVELOPE_new())
 
177
                        == NULL) goto err;
 
178
                ASN1_INTEGER_set(p7->d.signed_and_enveloped->version,1);
 
179
                p7->d.signed_and_enveloped->enc_data->content_type
 
180
                                                = OBJ_nid2obj(NID_pkcs7_data);
 
181
                break;
 
182
        case NID_pkcs7_enveloped:
 
183
                p7->type=obj;
 
184
                if ((p7->d.enveloped=PKCS7_ENVELOPE_new())
 
185
                        == NULL) goto err;
 
186
                ASN1_INTEGER_set(p7->d.enveloped->version,0);
 
187
                p7->d.enveloped->enc_data->content_type
 
188
                                                = OBJ_nid2obj(NID_pkcs7_data);
 
189
                break;
 
190
        case NID_pkcs7_encrypted:
 
191
                p7->type=obj;
 
192
                if ((p7->d.encrypted=PKCS7_ENCRYPT_new())
 
193
                        == NULL) goto err;
 
194
                ASN1_INTEGER_set(p7->d.encrypted->version,0);
 
195
                p7->d.encrypted->enc_data->content_type
 
196
                                                = OBJ_nid2obj(NID_pkcs7_data);
 
197
                break;
 
198
 
 
199
        case NID_pkcs7_digest:
 
200
        default:
 
201
                PKCS7err(PKCS7_F_PKCS7_SET_TYPE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
 
202
                goto err;
 
203
                }
 
204
        return(1);
 
205
err:
 
206
        return(0);
 
207
        }
 
208
 
 
209
int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi)
 
210
        {
 
211
        int i,j,nid;
 
212
        X509_ALGOR *alg;
 
213
        STACK_OF(PKCS7_SIGNER_INFO) *signer_sk;
 
214
        STACK_OF(X509_ALGOR) *md_sk;
 
215
 
 
216
        i=OBJ_obj2nid(p7->type);
 
217
        switch (i)
 
218
                {
 
219
        case NID_pkcs7_signed:
 
220
                signer_sk=      p7->d.sign->signer_info;
 
221
                md_sk=          p7->d.sign->md_algs;
 
222
                break;
 
223
        case NID_pkcs7_signedAndEnveloped:
 
224
                signer_sk=      p7->d.signed_and_enveloped->signer_info;
 
225
                md_sk=          p7->d.signed_and_enveloped->md_algs;
 
226
                break;
 
227
        default:
 
228
                PKCS7err(PKCS7_F_PKCS7_ADD_SIGNER,PKCS7_R_WRONG_CONTENT_TYPE);
 
229
                return(0);
 
230
                }
 
231
 
 
232
        nid=OBJ_obj2nid(psi->digest_alg->algorithm);
 
233
 
 
234
        /* If the digest is not currently listed, add it */
 
235
        j=0;
 
236
        for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
 
237
                {
 
238
                alg=sk_X509_ALGOR_value(md_sk,i);
 
239
                if (OBJ_obj2nid(alg->algorithm) == nid)
 
240
                        {
 
241
                        j=1;
 
242
                        break;
 
243
                        }
 
244
                }
 
245
        if (!j) /* we need to add another algorithm */
 
246
                {
 
247
                if(!(alg=X509_ALGOR_new())
 
248
                        || !(alg->parameter = ASN1_TYPE_new())) {
 
249
                        PKCS7err(PKCS7_F_PKCS7_ADD_SIGNER,ERR_R_MALLOC_FAILURE);
 
250
                        return(0);
 
251
                }
 
252
                alg->algorithm=OBJ_nid2obj(nid);
 
253
                alg->parameter->type = V_ASN1_NULL;
 
254
                sk_X509_ALGOR_push(md_sk,alg);
 
255
                }
 
256
 
 
257
        sk_PKCS7_SIGNER_INFO_push(signer_sk,psi);
 
258
        return(1);
 
259
        }
 
260
 
 
261
int PKCS7_add_certificate(PKCS7 *p7, X509 *x509)
 
262
        {
 
263
        int i;
 
264
        STACK_OF(X509) **sk;
 
265
 
 
266
        i=OBJ_obj2nid(p7->type);
 
267
        switch (i)
 
268
                {
 
269
        case NID_pkcs7_signed:
 
270
                sk= &(p7->d.sign->cert);
 
271
                break;
 
272
        case NID_pkcs7_signedAndEnveloped:
 
273
                sk= &(p7->d.signed_and_enveloped->cert);
 
274
                break;
 
275
        default:
 
276
                PKCS7err(PKCS7_F_PKCS7_ADD_CERTIFICATE,PKCS7_R_WRONG_CONTENT_TYPE);
 
277
                return(0);
 
278
                }
 
279
 
 
280
        if (*sk == NULL)
 
281
                *sk=sk_X509_new_null();
 
282
        CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509);
 
283
        sk_X509_push(*sk,x509);
 
284
        return(1);
 
285
        }
 
286
 
 
287
int PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl)
 
288
        {
 
289
        int i;
 
290
        STACK_OF(X509_CRL) **sk;
 
291
 
 
292
        i=OBJ_obj2nid(p7->type);
 
293
        switch (i)
 
294
                {
 
295
        case NID_pkcs7_signed:
 
296
                sk= &(p7->d.sign->crl);
 
297
                break;
 
298
        case NID_pkcs7_signedAndEnveloped:
 
299
                sk= &(p7->d.signed_and_enveloped->crl);
 
300
                break;
 
301
        default:
 
302
                PKCS7err(PKCS7_F_PKCS7_ADD_CRL,PKCS7_R_WRONG_CONTENT_TYPE);
 
303
                return(0);
 
304
                }
 
305
 
 
306
        if (*sk == NULL)
 
307
                *sk=sk_X509_CRL_new_null();
 
308
 
 
309
        CRYPTO_add(&crl->references,1,CRYPTO_LOCK_X509_CRL);
 
310
        sk_X509_CRL_push(*sk,crl);
 
311
        return(1);
 
312
        }
 
313
 
 
314
int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey,
 
315
             const EVP_MD *dgst)
 
316
        {
 
317
        char is_dsa;
 
318
        if (pkey->type == EVP_PKEY_DSA) is_dsa = 1;
 
319
        else is_dsa = 0;
 
320
        /* We now need to add another PKCS7_SIGNER_INFO entry */
 
321
        ASN1_INTEGER_set(p7i->version,1);
 
322
        X509_NAME_set(&p7i->issuer_and_serial->issuer,
 
323
                X509_get_issuer_name(x509));
 
324
 
 
325
        /* because ASN1_INTEGER_set is used to set a 'long' we will do
 
326
         * things the ugly way. */
 
327
        M_ASN1_INTEGER_free(p7i->issuer_and_serial->serial);
 
328
        p7i->issuer_and_serial->serial=
 
329
                M_ASN1_INTEGER_dup(X509_get_serialNumber(x509));
 
330
 
 
331
        /* lets keep the pkey around for a while */
 
332
        CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
 
333
        p7i->pkey=pkey;
 
334
 
 
335
        /* Set the algorithms */
 
336
        if (is_dsa) p7i->digest_alg->algorithm=OBJ_nid2obj(NID_sha1);
 
337
        else    
 
338
                p7i->digest_alg->algorithm=OBJ_nid2obj(EVP_MD_type(dgst));
 
339
 
 
340
        if (p7i->digest_alg->parameter != NULL)
 
341
                ASN1_TYPE_free(p7i->digest_alg->parameter);
 
342
        if ((p7i->digest_alg->parameter=ASN1_TYPE_new()) == NULL)
 
343
                goto err;
 
344
        p7i->digest_alg->parameter->type=V_ASN1_NULL;
 
345
 
 
346
        p7i->digest_enc_alg->algorithm=OBJ_nid2obj(EVP_PKEY_type(pkey->type));
 
347
 
 
348
        if (p7i->digest_enc_alg->parameter != NULL)
 
349
                ASN1_TYPE_free(p7i->digest_enc_alg->parameter);
 
350
        if(is_dsa) p7i->digest_enc_alg->parameter = NULL;
 
351
        else {
 
352
                if (!(p7i->digest_enc_alg->parameter=ASN1_TYPE_new()))
 
353
                        goto err;
 
354
                p7i->digest_enc_alg->parameter->type=V_ASN1_NULL;
 
355
        }
 
356
 
 
357
        return(1);
 
358
err:
 
359
        return(0);
 
360
        }
 
361
 
 
362
PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey,
 
363
             const EVP_MD *dgst)
 
364
        {
 
365
        PKCS7_SIGNER_INFO *si;
 
366
 
 
367
        if ((si=PKCS7_SIGNER_INFO_new()) == NULL) goto err;
 
368
        if (!PKCS7_SIGNER_INFO_set(si,x509,pkey,dgst)) goto err;
 
369
        if (!PKCS7_add_signer(p7,si)) goto err;
 
370
        return(si);
 
371
err:
 
372
        return(NULL);
 
373
        }
 
374
 
 
375
STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7)
 
376
        {
 
377
        if (PKCS7_type_is_signed(p7))
 
378
                {
 
379
                return(p7->d.sign->signer_info);
 
380
                }
 
381
        else if (PKCS7_type_is_signedAndEnveloped(p7))
 
382
                {
 
383
                return(p7->d.signed_and_enveloped->signer_info);
 
384
                }
 
385
        else
 
386
                return(NULL);
 
387
        }
 
388
 
 
389
PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509)
 
390
        {
 
391
        PKCS7_RECIP_INFO *ri;
 
392
 
 
393
        if ((ri=PKCS7_RECIP_INFO_new()) == NULL) goto err;
 
394
        if (!PKCS7_RECIP_INFO_set(ri,x509)) goto err;
 
395
        if (!PKCS7_add_recipient_info(p7,ri)) goto err;
 
396
        return(ri);
 
397
err:
 
398
        return(NULL);
 
399
        }
 
400
 
 
401
int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri)
 
402
        {
 
403
        int i;
 
404
        STACK_OF(PKCS7_RECIP_INFO) *sk;
 
405
 
 
406
        i=OBJ_obj2nid(p7->type);
 
407
        switch (i)
 
408
                {
 
409
        case NID_pkcs7_signedAndEnveloped:
 
410
                sk=     p7->d.signed_and_enveloped->recipientinfo;
 
411
                break;
 
412
        case NID_pkcs7_enveloped:
 
413
                sk=     p7->d.enveloped->recipientinfo;
 
414
                break;
 
415
        default:
 
416
                PKCS7err(PKCS7_F_PKCS7_ADD_RECIPIENT_INFO,PKCS7_R_WRONG_CONTENT_TYPE);
 
417
                return(0);
 
418
                }
 
419
 
 
420
        sk_PKCS7_RECIP_INFO_push(sk,ri);
 
421
        return(1);
 
422
        }
 
423
 
 
424
int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509)
 
425
        {
 
426
        ASN1_INTEGER_set(p7i->version,0);
 
427
        X509_NAME_set(&p7i->issuer_and_serial->issuer,
 
428
                X509_get_issuer_name(x509));
 
429
 
 
430
        M_ASN1_INTEGER_free(p7i->issuer_and_serial->serial);
 
431
        p7i->issuer_and_serial->serial=
 
432
                M_ASN1_INTEGER_dup(X509_get_serialNumber(x509));
 
433
 
 
434
        X509_ALGOR_free(p7i->key_enc_algor);
 
435
        p7i->key_enc_algor= X509_ALGOR_dup(x509->cert_info->key->algor);
 
436
 
 
437
        CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509);
 
438
        p7i->cert=x509;
 
439
 
 
440
        return(1);
 
441
        }
 
442
 
 
443
X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si)
 
444
        {
 
445
        if (PKCS7_type_is_signed(p7))
 
446
                return(X509_find_by_issuer_and_serial(p7->d.sign->cert,
 
447
                        si->issuer_and_serial->issuer,
 
448
                        si->issuer_and_serial->serial));
 
449
        else
 
450
                return(NULL);
 
451
        }
 
452
 
 
453
int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher)
 
454
        {
 
455
        int i;
 
456
        ASN1_OBJECT *objtmp;
 
457
        PKCS7_ENC_CONTENT *ec;
 
458
 
 
459
        i=OBJ_obj2nid(p7->type);
 
460
        switch (i)
 
461
                {
 
462
        case NID_pkcs7_signedAndEnveloped:
 
463
                ec=p7->d.signed_and_enveloped->enc_data;
 
464
                break;
 
465
        case NID_pkcs7_enveloped:
 
466
                ec=p7->d.enveloped->enc_data;
 
467
                break;
 
468
        default:
 
469
                PKCS7err(PKCS7_F_PKCS7_SET_CIPHER,PKCS7_R_WRONG_CONTENT_TYPE);
 
470
                return(0);
 
471
                }
 
472
 
 
473
        /* Check cipher OID exists and has data in it*/
 
474
        i = EVP_CIPHER_type(cipher);
 
475
        if(i == NID_undef) {
 
476
                PKCS7err(PKCS7_F_PKCS7_SET_CIPHER,PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
 
477
                return(0);
 
478
        }
 
479
        objtmp = OBJ_nid2obj(i);
 
480
 
 
481
        ec->cipher = cipher;
 
482
        return 1;
 
483
        }
 
484