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 #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                 {
  74         case PKCS7_OP_SET_DETACHED_SIGNATURE:
  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                                         {
  80                                         ASN1_OCTET_STRING *os;
  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                         {
  88                         PKCS7err(PKCS7_F_PKCS7_CTRL,PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE);
  89                         ret=0;
  90                         }
  91                 break;
  92         case PKCS7_OP_GET_DETACHED_SIGNATURE:
  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                         {
 103                         PKCS7err(PKCS7_F_PKCS7_CTRL,PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE);
 104                         ret=0;
 105                         }
 106 
 107                 break;
 108         default:
 109                 PKCS7err(PKCS7_F_PKCS7_CTRL,PKCS7_R_UNKNOWN_OPERATION);
 110                 ret=0;
 111                 }
 112         return(ret);
 113         }
 114 
 115 int PKCS7_content_new(PKCS7 *p7, int type)
 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:
 148         case NID_pkcs7_signedAndEnveloped:
 149         case NID_pkcs7_encrypted:
 150         default:
 151                 PKCS7err(PKCS7_F_PKCS7_SET_CONTENT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
 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;
 184         case NID_pkcs7_signedAndEnveloped:
 185                 p7->type=obj;
 186                 if ((p7->d.signed_and_enveloped=PKCS7_SIGN_ENVELOPE_new())
 187                         == NULL) goto err;
 188                 ASN1_INTEGER_set(p7->d.signed_and_enveloped->version,1);
 189                 if (!ASN1_INTEGER_set(p7->d.signed_and_enveloped->version,1))
 190                         goto err;
 191                 p7->d.signed_and_enveloped->enc_data->content_type
 192                                                 = OBJ_nid2obj(NID_pkcs7_data);
 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;
 200                 p7->d.enveloped->enc_data->content_type
 201                                                 = OBJ_nid2obj(NID_pkcs7_data);
 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;
 209                 p7->d.encrypted->enc_data->content_type
 210                                                 = OBJ_nid2obj(NID_pkcs7_data);
 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:
 221                 PKCS7err(PKCS7_F_PKCS7_SET_TYPE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
 222                 goto err;
 223                 }
 224         return(1);
 225 err:
 226         return(0);
 227         }
 228 
 229 int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other)
 230         {
 231         p7->type = OBJ_nid2obj(type);
 232         p7->d.other = other;
 233         return 1;
 234         }
 235 
 236 int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi)
 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;
 250         case NID_pkcs7_signedAndEnveloped:
 251                 signer_sk=      p7->d.signed_and_enveloped->signer_info;
 252                 md_sk=          p7->d.signed_and_enveloped->md_algs;
 253                 break;
 254         default:
 255                 PKCS7err(PKCS7_F_PKCS7_ADD_SIGNER,PKCS7_R_WRONG_CONTENT_TYPE);
 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);
 278                         PKCS7err(PKCS7_F_PKCS7_ADD_SIGNER,ERR_R_MALLOC_FAILURE);
 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 
 295 int PKCS7_add_certificate(PKCS7 *p7, X509 *x509)
 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;
 306         case NID_pkcs7_signedAndEnveloped:
 307                 sk= &(p7->d.signed_and_enveloped->cert);
 308                 break;
 309         default:
 310                 PKCS7err(PKCS7_F_PKCS7_ADD_CERTIFICATE,PKCS7_R_WRONG_CONTENT_TYPE);
 311                 return(0);
 312                 }
 313 
 314         if (*sk == NULL)
 315                 *sk=sk_X509_new_null();
 316         if (*sk == NULL)
 317                 {
 318                 PKCS7err(PKCS7_F_PKCS7_ADD_CERTIFICATE, ERR_R_MALLOC_FAILURE);
 319                 return 0;
 320                 }
 321         CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509);
 322         if (!sk_X509_push(*sk,x509))
 323                 {
 324                 X509_free(x509);
 325                 return 0;
 326                 }
 327         return(1);
 328         }
 329 
 330 int PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl)
 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;
 341         case NID_pkcs7_signedAndEnveloped:
 342                 sk= &(p7->d.signed_and_enveloped->crl);
 343                 break;
 344         default:
 345                 PKCS7err(PKCS7_F_PKCS7_ADD_CRL,PKCS7_R_WRONG_CONTENT_TYPE);
 346                 return(0);
 347                 }
 348 
 349         if (*sk == NULL)
 350                 *sk=sk_X509_CRL_new_null();
 351         if (*sk == NULL)
 352                 {
 353                 PKCS7err(PKCS7_F_PKCS7_ADD_CRL,ERR_R_MALLOC_FAILURE);
 354                 return 0;
 355                 }
 356 
 357         CRYPTO_add(&crl->references,1,CRYPTO_LOCK_X509_CRL);
 358         if (!sk_X509_CRL_push(*sk,crl))
 359                 {
 360                 X509_CRL_free(crl);
 361                 return 0;
 362                 }
 363         return(1);
 364         }
 365 
 366 int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey,
 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;
 374         if (!X509_NAME_set(&p7i->issuer_and_serial->issuer,
 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. */
 380         M_ASN1_INTEGER_free(p7i->issuer_and_serial->serial);
 381         if (!(p7i->issuer_and_serial->serial=
 382                         M_ASN1_INTEGER_dup(X509_get_serialNumber(x509))))
 383                 goto err;
 384 
 385         /* lets keep the pkey around for a while */
 386         CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
 387         p7i->pkey=pkey;
 388 
 389         /* Set the algorithms */
 390 
 391         X509_ALGOR_set0(p7i->digest_alg, OBJ_nid2obj(EVP_MD_type(dgst)),
 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                         {
 402                         PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SET,
 403                                         PKCS7_R_SIGNING_CTRL_FAILURE);
 404                         return 0;
 405                         }
 406                 }
 407         PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SET,
 408                         PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
 409 err:
 410         return 0;
 411         }
 412 
 413 PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey,
 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                         {
 426                         PKCS7err(PKCS7_F_PKCS7_ADD_SIGNATURE,
 427                                                 PKCS7_R_NO_DEFAULT_DIGEST);
 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                         {
 448                         PKCS7err(PKCS7_F_PKCS7_SET_DIGEST,ERR_R_MALLOC_FAILURE);
 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 
 456         PKCS7err(PKCS7_F_PKCS7_SET_DIGEST,PKCS7_R_WRONG_CONTENT_TYPE);
 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                 }
 466         else if (PKCS7_type_is_signedAndEnveloped(p7))
 467                 {
 468                 return(p7->d.signed_and_enveloped->signer_info);
 469                 }
 470         else
 471                 return(NULL);
 472         }
 473 
 474 void PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO *si, EVP_PKEY **pk,
 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 
 485 void PKCS7_RECIP_INFO_get0_alg(PKCS7_RECIP_INFO *ri, X509_ALGOR **penc)
 486         {
 487         if (penc)
 488                 *penc = ri->key_enc_algor;
 489         }
 490 
 491 PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509)
 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 
 505 int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri)
 506         {
 507         int i;
 508         STACK_OF(PKCS7_RECIP_INFO) *sk;
 509 
 510         i=OBJ_obj2nid(p7->type);
 511         switch (i)
 512                 {
 513         case NID_pkcs7_signedAndEnveloped:
 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:
 520                 PKCS7err(PKCS7_F_PKCS7_ADD_RECIPIENT_INFO,PKCS7_R_WRONG_CONTENT_TYPE);
 521                 return(0);
 522                 }
 523 
 524         if (!sk_PKCS7_RECIP_INFO_push(sk,ri))
 525                 return 0;
 526         return(1);
 527         }
 528 
 529 int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509)
 530         {
 531         int ret;
 532         EVP_PKEY *pkey = NULL;
 533         if (!ASN1_INTEGER_set(p7i->version,0))
 534                 return 0;
 535         if (!X509_NAME_set(&p7i->issuer_and_serial->issuer,
 536                 X509_get_issuer_name(x509)))
 537                 return 0;
 538 
 539         M_ASN1_INTEGER_free(p7i->issuer_and_serial->serial);
 540         if (!(p7i->issuer_and_serial->serial=
 541                 M_ASN1_INTEGER_dup(X509_get_serialNumber(x509))))
 542                 return 0;
 543 
 544         pkey = X509_get_pubkey(x509);
 545 
 546         if (!pkey || !pkey->ameth || !pkey->ameth->pkey_ctrl)
 547                 {
 548                 PKCS7err(PKCS7_F_PKCS7_RECIP_INFO_SET,
 549                         PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
 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                 {
 557                 PKCS7err(PKCS7_F_PKCS7_RECIP_INFO_SET,
 558                         PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
 559                 goto err;
 560                 }
 561         if (ret <= 0)
 562                 {
 563                 PKCS7err(PKCS7_F_PKCS7_RECIP_INFO_SET,
 564                                 PKCS7_R_ENCRYPTION_CTRL_FAILURE);
 565                 goto err;
 566                 }
 567 
 568         EVP_PKEY_free(pkey);
 569 
 570         CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509);
 571         p7i->cert=x509;
 572 
 573         return 1;
 574 
 575         err:
 576         if (pkey)
 577                 EVP_PKEY_free(pkey);
 578         return 0;
 579         }
 580 
 581 X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si)
 582         {
 583         if (PKCS7_type_is_signed(p7))
 584                 return(X509_find_by_issuer_and_serial(p7->d.sign->cert,
 585                         si->issuer_and_serial->issuer,
 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                 {
 599         case NID_pkcs7_signedAndEnveloped:
 600                 ec=p7->d.signed_and_enveloped->enc_data;
 601                 break;
 602         case NID_pkcs7_enveloped:
 603                 ec=p7->d.enveloped->enc_data;
 604                 break;
 605         default:
 606                 PKCS7err(PKCS7_F_PKCS7_SET_CIPHER,PKCS7_R_WRONG_CONTENT_TYPE);
 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) {
 613                 PKCS7err(PKCS7_F_PKCS7_SET_CIPHER,PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
 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 
 631                 case NID_pkcs7_signedAndEnveloped:
 632                 os = p7->d.signed_and_enveloped->enc_data->enc_data;
 633                 if (os == NULL)
 634                         {
 635                         os=M_ASN1_OCTET_STRING_new();
 636                         p7->d.signed_and_enveloped->enc_data->enc_data=os;
 637                         }
 638                 break;
 639 
 640                 case NID_pkcs7_enveloped:
 641                 os = p7->d.enveloped->enc_data->enc_data;
 642                 if (os == NULL)
 643                         {
 644                         os=M_ASN1_OCTET_STRING_new();
 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 
 661         os->flags |= ASN1_STRING_FLAG_NDEF;
 662         *boundary = &os->data;
 663 
 664         return 1;
 665         }