OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
pk7_lib.c
Go to the documentation of this file.
1 /* crypto/pkcs7/pk7_lib.c */
2 /* Copyright (C) 1995-1998 Eric Young ([email protected])
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young ([email protected]).
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 ([email protected]).
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 ([email protected])"
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 ([email protected])"
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 #include "asn1_locl.h"
64 
65 long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg)
66  {
67  int nid;
68  long ret;
69 
70  nid=OBJ_obj2nid(p7->type);
71 
72  switch (cmd)
73  {
75  if (nid == NID_pkcs7_signed)
76  {
77  ret=p7->detached=(int)larg;
78  if (ret && PKCS7_type_is_data(p7->d.sign->contents))
79  {
81  os=p7->d.sign->contents->d.data;
82  ASN1_OCTET_STRING_free(os);
83  p7->d.sign->contents->d.data = NULL;
84  }
85  }
86  else
87  {
89  ret=0;
90  }
91  break;
93  if (nid == NID_pkcs7_signed)
94  {
95  if(!p7->d.sign || !p7->d.sign->contents->d.ptr)
96  ret = 1;
97  else ret = 0;
98 
99  p7->detached = ret;
100  }
101  else
102  {
104  ret=0;
105  }
106 
107  break;
108  default:
110  ret=0;
111  }
112  return(ret);
113  }
114 
116  {
117  PKCS7 *ret=NULL;
118 
119  if ((ret=PKCS7_new()) == NULL) goto err;
120  if (!PKCS7_set_type(ret,type)) goto err;
121  if (!PKCS7_set_content(p7,ret)) goto err;
122 
123  return(1);
124 err:
125  if (ret != NULL) PKCS7_free(ret);
126  return(0);
127  }
128 
129 int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data)
130  {
131  int i;
132 
133  i=OBJ_obj2nid(p7->type);
134  switch (i)
135  {
136  case NID_pkcs7_signed:
137  if (p7->d.sign->contents != NULL)
138  PKCS7_free(p7->d.sign->contents);
139  p7->d.sign->contents=p7_data;
140  break;
141  case NID_pkcs7_digest:
142  if (p7->d.digest->contents != NULL)
143  PKCS7_free(p7->d.digest->contents);
144  p7->d.digest->contents=p7_data;
145  break;
146  case NID_pkcs7_data:
147  case NID_pkcs7_enveloped:
149  case NID_pkcs7_encrypted:
150  default:
152  goto err;
153  }
154  return(1);
155 err:
156  return(0);
157  }
158 
159 int PKCS7_set_type(PKCS7 *p7, int type)
160  {
161  ASN1_OBJECT *obj;
162 
163  /*PKCS7_content_free(p7);*/
164  obj=OBJ_nid2obj(type); /* will not fail */
165 
166  switch (type)
167  {
168  case NID_pkcs7_signed:
169  p7->type=obj;
170  if ((p7->d.sign=PKCS7_SIGNED_new()) == NULL)
171  goto err;
172  if (!ASN1_INTEGER_set(p7->d.sign->version,1))
173  {
174  PKCS7_SIGNED_free(p7->d.sign);
175  p7->d.sign=NULL;
176  goto err;
177  }
178  break;
179  case NID_pkcs7_data:
180  p7->type=obj;
181  if ((p7->d.data=M_ASN1_OCTET_STRING_new()) == NULL)
182  goto err;
183  break;
185  p7->type=obj;
186  if ((p7->d.signed_and_enveloped=PKCS7_SIGN_ENVELOPE_new())
187  == NULL) goto err;
190  goto err;
193  break;
194  case NID_pkcs7_enveloped:
195  p7->type=obj;
196  if ((p7->d.enveloped=PKCS7_ENVELOPE_new())
197  == NULL) goto err;
198  if (!ASN1_INTEGER_set(p7->d.enveloped->version,0))
199  goto err;
202  break;
203  case NID_pkcs7_encrypted:
204  p7->type=obj;
205  if ((p7->d.encrypted=PKCS7_ENCRYPT_new())
206  == NULL) goto err;
207  if (!ASN1_INTEGER_set(p7->d.encrypted->version,0))
208  goto err;
211  break;
212 
213  case NID_pkcs7_digest:
214  p7->type=obj;
215  if ((p7->d.digest=PKCS7_DIGEST_new())
216  == NULL) goto err;
217  if (!ASN1_INTEGER_set(p7->d.digest->version,0))
218  goto err;
219  break;
220  default:
222  goto err;
223  }
224  return(1);
225 err:
226  return(0);
227  }
228 
230  {
231  p7->type = OBJ_nid2obj(type);
232  p7->d.other = other;
233  return 1;
234  }
235 
237  {
238  int i,j,nid;
239  X509_ALGOR *alg;
240  STACK_OF(PKCS7_SIGNER_INFO) *signer_sk;
241  STACK_OF(X509_ALGOR) *md_sk;
242 
243  i=OBJ_obj2nid(p7->type);
244  switch (i)
245  {
246  case NID_pkcs7_signed:
247  signer_sk= p7->d.sign->signer_info;
248  md_sk= p7->d.sign->md_algs;
249  break;
251  signer_sk= p7->d.signed_and_enveloped->signer_info;
252  md_sk= p7->d.signed_and_enveloped->md_algs;
253  break;
254  default:
256  return(0);
257  }
258 
259  nid=OBJ_obj2nid(psi->digest_alg->algorithm);
260 
261  /* If the digest is not currently listed, add it */
262  j=0;
263  for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
264  {
265  alg=sk_X509_ALGOR_value(md_sk,i);
266  if (OBJ_obj2nid(alg->algorithm) == nid)
267  {
268  j=1;
269  break;
270  }
271  }
272  if (!j) /* we need to add another algorithm */
273  {
274  if(!(alg=X509_ALGOR_new())
275  || !(alg->parameter = ASN1_TYPE_new()))
276  {
277  X509_ALGOR_free(alg);
279  return(0);
280  }
281  alg->algorithm=OBJ_nid2obj(nid);
282  alg->parameter->type = V_ASN1_NULL;
283  if (!sk_X509_ALGOR_push(md_sk,alg))
284  {
285  X509_ALGOR_free(alg);
286  return 0;
287  }
288  }
289 
290  if (!sk_PKCS7_SIGNER_INFO_push(signer_sk,psi))
291  return 0;
292  return(1);
293  }
294 
296  {
297  int i;
298  STACK_OF(X509) **sk;
299 
300  i=OBJ_obj2nid(p7->type);
301  switch (i)
302  {
303  case NID_pkcs7_signed:
304  sk= &(p7->d.sign->cert);
305  break;
307  sk= &(p7->d.signed_and_enveloped->cert);
308  break;
309  default:
311  return(0);
312  }
313 
314  if (*sk == NULL)
315  *sk=sk_X509_new_null();
316  if (*sk == NULL)
317  {
319  return 0;
320  }
322  if (!sk_X509_push(*sk,x509))
323  {
324  X509_free(x509);
325  return 0;
326  }
327  return(1);
328  }
329 
331  {
332  int i;
333  STACK_OF(X509_CRL) **sk;
334 
335  i=OBJ_obj2nid(p7->type);
336  switch (i)
337  {
338  case NID_pkcs7_signed:
339  sk= &(p7->d.sign->crl);
340  break;
342  sk= &(p7->d.signed_and_enveloped->crl);
343  break;
344  default:
346  return(0);
347  }
348 
349  if (*sk == NULL)
350  *sk=sk_X509_CRL_new_null();
351  if (*sk == NULL)
352  {
354  return 0;
355  }
356 
358  if (!sk_X509_CRL_push(*sk,crl))
359  {
360  X509_CRL_free(crl);
361  return 0;
362  }
363  return(1);
364  }
365 
367  const EVP_MD *dgst)
368  {
369  int ret;
370 
371  /* We now need to add another PKCS7_SIGNER_INFO entry */
372  if (!ASN1_INTEGER_set(p7i->version,1))
373  goto err;
375  X509_get_issuer_name(x509)))
376  goto err;
377 
378  /* because ASN1_INTEGER_set is used to set a 'long' we will do
379  * things the ugly way. */
381  if (!(p7i->issuer_and_serial->serial=
383  goto err;
384 
385  /* lets keep the pkey around for a while */
387  p7i->pkey=pkey;
388 
389  /* Set the algorithms */
390 
392  V_ASN1_NULL, NULL);
393 
394  if (pkey->ameth && pkey->ameth->pkey_ctrl)
395  {
396  ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_SIGN,
397  0, p7i);
398  if (ret > 0)
399  return 1;
400  if (ret != -2)
401  {
404  return 0;
405  }
406  }
409 err:
410  return 0;
411  }
412 
414  const EVP_MD *dgst)
415  {
416  PKCS7_SIGNER_INFO *si = NULL;
417 
418  if (dgst == NULL)
419  {
420  int def_nid;
421  if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0)
422  goto err;
423  dgst = EVP_get_digestbynid(def_nid);
424  if (dgst == NULL)
425  {
428  goto err;
429  }
430  }
431 
432  if ((si=PKCS7_SIGNER_INFO_new()) == NULL) goto err;
433  if (!PKCS7_SIGNER_INFO_set(si,x509,pkey,dgst)) goto err;
434  if (!PKCS7_add_signer(p7,si)) goto err;
435  return(si);
436 err:
437  if (si)
438  PKCS7_SIGNER_INFO_free(si);
439  return(NULL);
440  }
441 
442 int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md)
443  {
444  if (PKCS7_type_is_digest(p7))
445  {
446  if(!(p7->d.digest->md->parameter = ASN1_TYPE_new()))
447  {
449  return 0;
450  }
451  p7->d.digest->md->parameter->type = V_ASN1_NULL;
452  p7->d.digest->md->algorithm = OBJ_nid2obj(EVP_MD_nid(md));
453  return 1;
454  }
455 
457  return 1;
458  }
459 
460 STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7)
461  {
462  if (PKCS7_type_is_signed(p7))
463  {
464  return(p7->d.sign->signer_info);
465  }
467  {
468  return(p7->d.signed_and_enveloped->signer_info);
469  }
470  else
471  return(NULL);
472  }
473 
475  X509_ALGOR **pdig, X509_ALGOR **psig)
476  {
477  if (pk)
478  *pk = si->pkey;
479  if (pdig)
480  *pdig = si->digest_alg;
481  if (psig)
482  *psig = si->digest_enc_alg;
483  }
484 
486  {
487  if (penc)
488  *penc = ri->key_enc_algor;
489  }
490 
492  {
493  PKCS7_RECIP_INFO *ri;
494 
495  if ((ri=PKCS7_RECIP_INFO_new()) == NULL) goto err;
496  if (!PKCS7_RECIP_INFO_set(ri,x509)) goto err;
497  if (!PKCS7_add_recipient_info(p7,ri)) goto err;
498  return ri;
499 err:
500  if (ri)
501  PKCS7_RECIP_INFO_free(ri);
502  return NULL;
503  }
504 
506  {
507  int i;
509 
510  i=OBJ_obj2nid(p7->type);
511  switch (i)
512  {
514  sk= p7->d.signed_and_enveloped->recipientinfo;
515  break;
516  case NID_pkcs7_enveloped:
517  sk= p7->d.enveloped->recipientinfo;
518  break;
519  default:
521  return(0);
522  }
523 
524  if (!sk_PKCS7_RECIP_INFO_push(sk,ri))
525  return 0;
526  return(1);
527  }
528 
530  {
531  int ret;
532  EVP_PKEY *pkey = NULL;
533  if (!ASN1_INTEGER_set(p7i->version,0))
534  return 0;
536  X509_get_issuer_name(x509)))
537  return 0;
538 
540  if (!(p7i->issuer_and_serial->serial=
542  return 0;
543 
544  pkey = X509_get_pubkey(x509);
545 
546  if (!pkey || !pkey->ameth || !pkey->ameth->pkey_ctrl)
547  {
550  goto err;
551  }
552 
553  ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_ENCRYPT,
554  0, p7i);
555  if (ret == -2)
556  {
559  goto err;
560  }
561  if (ret <= 0)
562  {
565  goto err;
566  }
567 
568  EVP_PKEY_free(pkey);
569 
571  p7i->cert=x509;
572 
573  return 1;
574 
575  err:
576  if (pkey)
577  EVP_PKEY_free(pkey);
578  return 0;
579  }
580 
582  {
583  if (PKCS7_type_is_signed(p7))
584  return(X509_find_by_issuer_and_serial(p7->d.sign->cert,
586  si->issuer_and_serial->serial));
587  else
588  return(NULL);
589  }
590 
591 int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher)
592  {
593  int i;
594  PKCS7_ENC_CONTENT *ec;
595 
596  i=OBJ_obj2nid(p7->type);
597  switch (i)
598  {
601  break;
602  case NID_pkcs7_enveloped:
603  ec=p7->d.enveloped->enc_data;
604  break;
605  default:
607  return(0);
608  }
609 
610  /* Check cipher OID exists and has data in it*/
611  i = EVP_CIPHER_type(cipher);
612  if(i == NID_undef) {
614  return(0);
615  }
616 
617  ec->cipher = cipher;
618  return 1;
619  }
620 
621 int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7)
622  {
623  ASN1_OCTET_STRING *os = NULL;
624 
625  switch (OBJ_obj2nid(p7->type))
626  {
627  case NID_pkcs7_data:
628  os = p7->d.data;
629  break;
630 
633  if (os == NULL)
634  {
637  }
638  break;
639 
640  case NID_pkcs7_enveloped:
641  os = p7->d.enveloped->enc_data->enc_data;
642  if (os == NULL)
643  {
645  p7->d.enveloped->enc_data->enc_data=os;
646  }
647  break;
648 
649  case NID_pkcs7_signed:
650  os=p7->d.sign->contents->d.data;
651  break;
652 
653  default:
654  os = NULL;
655  break;
656  }
657 
658  if (os == NULL)
659  return 0;
660 
662  *boundary = &os->data;
663 
664  return 1;
665  }