pk7_lib.c revision 55714
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 64long 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 } 78 else 79 { 80 PKCS7err(PKCS7_F_PKCS7_CTRL,PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE); 81 ret=0; 82 } 83 break; 84 case PKCS7_OP_GET_DETACHED_SIGNATURE: 85 if (nid == NID_pkcs7_signed) 86 { 87 ret=p7->detached; 88 } 89 else 90 { 91 PKCS7err(PKCS7_F_PKCS7_CTRL,PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE); 92 ret=0; 93 } 94 95 break; 96 default: 97 PKCS7err(PKCS7_F_PKCS7_CTRL,PKCS7_R_UNKNOWN_OPERATION); 98 ret=0; 99 } 100 return(ret); 101 } 102 103int PKCS7_content_new(PKCS7 *p7, int type) 104 { 105 PKCS7 *ret=NULL; 106 107 if ((ret=PKCS7_new()) == NULL) goto err; 108 if (!PKCS7_set_type(ret,type)) goto err; 109 if (!PKCS7_set_content(p7,ret)) goto err; 110 111 return(1); 112err: 113 if (ret != NULL) PKCS7_free(ret); 114 return(0); 115 } 116 117int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data) 118 { 119 int i; 120 121 i=OBJ_obj2nid(p7->type); 122 switch (i) 123 { 124 case NID_pkcs7_signed: 125 if (p7->d.sign->contents != NULL) 126 PKCS7_content_free(p7->d.sign->contents); 127 p7->d.sign->contents=p7_data; 128 break; 129 case NID_pkcs7_digest: 130 case NID_pkcs7_data: 131 case NID_pkcs7_enveloped: 132 case NID_pkcs7_signedAndEnveloped: 133 case NID_pkcs7_encrypted: 134 default: 135 PKCS7err(PKCS7_F_PKCS7_SET_CONTENT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 136 goto err; 137 } 138 return(1); 139err: 140 return(0); 141 } 142 143int PKCS7_set_type(PKCS7 *p7, int type) 144 { 145 ASN1_OBJECT *obj; 146 147 PKCS7_content_free(p7); 148 obj=OBJ_nid2obj(type); /* will not fail */ 149 150 switch (type) 151 { 152 case NID_pkcs7_signed: 153 p7->type=obj; 154 if ((p7->d.sign=PKCS7_SIGNED_new()) == NULL) 155 goto err; 156 ASN1_INTEGER_set(p7->d.sign->version,1); 157 break; 158 case NID_pkcs7_data: 159 p7->type=obj; 160 if ((p7->d.data=ASN1_OCTET_STRING_new()) == NULL) 161 goto err; 162 break; 163 case NID_pkcs7_signedAndEnveloped: 164 p7->type=obj; 165 if ((p7->d.signed_and_enveloped=PKCS7_SIGN_ENVELOPE_new()) 166 == NULL) goto err; 167 ASN1_INTEGER_set(p7->d.signed_and_enveloped->version,1); 168/* p7->d.signed_and_enveloped->enc_data->content_type= 169 OBJ_nid2obj(NID_pkcs7_encrypted);*/ 170 171 break; 172 case NID_pkcs7_enveloped: 173 p7->type=obj; 174 if ((p7->d.enveloped=PKCS7_ENVELOPE_new()) 175 == NULL) goto err; 176 ASN1_INTEGER_set(p7->d.enveloped->version,0); 177 break; 178 case NID_pkcs7_digest: 179 case NID_pkcs7_encrypted: 180 default: 181 PKCS7err(PKCS7_F_PKCS7_SET_TYPE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 182 goto err; 183 } 184 return(1); 185err: 186 return(0); 187 } 188 189int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi) 190 { 191 int i,j,nid; 192 X509_ALGOR *alg; 193 STACK_OF(PKCS7_SIGNER_INFO) *signer_sk; 194 STACK_OF(X509_ALGOR) *md_sk; 195 196 i=OBJ_obj2nid(p7->type); 197 switch (i) 198 { 199 case NID_pkcs7_signed: 200 signer_sk= p7->d.sign->signer_info; 201 md_sk= p7->d.sign->md_algs; 202 break; 203 case NID_pkcs7_signedAndEnveloped: 204 signer_sk= p7->d.signed_and_enveloped->signer_info; 205 md_sk= p7->d.signed_and_enveloped->md_algs; 206 break; 207 default: 208 PKCS7err(PKCS7_F_PKCS7_ADD_SIGNER,PKCS7_R_WRONG_CONTENT_TYPE); 209 return(0); 210 } 211 212 nid=OBJ_obj2nid(psi->digest_alg->algorithm); 213 214 /* If the digest is not currently listed, add it */ 215 j=0; 216 for (i=0; i<sk_X509_ALGOR_num(md_sk); i++) 217 { 218 alg=sk_X509_ALGOR_value(md_sk,i); 219 if (OBJ_obj2nid(alg->algorithm) == nid) 220 { 221 j=1; 222 break; 223 } 224 } 225 if (!j) /* we need to add another algorithm */ 226 { 227 alg=X509_ALGOR_new(); 228 alg->algorithm=OBJ_nid2obj(nid); 229 sk_X509_ALGOR_push(md_sk,alg); 230 } 231 232 sk_PKCS7_SIGNER_INFO_push(signer_sk,psi); 233 return(1); 234 } 235 236int PKCS7_add_certificate(PKCS7 *p7, X509 *x509) 237 { 238 int i; 239 STACK_OF(X509) **sk; 240 241 i=OBJ_obj2nid(p7->type); 242 switch (i) 243 { 244 case NID_pkcs7_signed: 245 sk= &(p7->d.sign->cert); 246 break; 247 case NID_pkcs7_signedAndEnveloped: 248 sk= &(p7->d.signed_and_enveloped->cert); 249 break; 250 default: 251 PKCS7err(PKCS7_F_PKCS7_ADD_CERTIFICATE,PKCS7_R_WRONG_CONTENT_TYPE); 252 return(0); 253 } 254 255 if (*sk == NULL) 256 *sk=sk_X509_new_null(); 257 CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509); 258 sk_X509_push(*sk,x509); 259 return(1); 260 } 261 262int PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl) 263 { 264 int i; 265 STACK_OF(X509_CRL) **sk; 266 267 i=OBJ_obj2nid(p7->type); 268 switch (i) 269 { 270 case NID_pkcs7_signed: 271 sk= &(p7->d.sign->crl); 272 break; 273 case NID_pkcs7_signedAndEnveloped: 274 sk= &(p7->d.signed_and_enveloped->crl); 275 break; 276 default: 277 PKCS7err(PKCS7_F_PKCS7_ADD_CRL,PKCS7_R_WRONG_CONTENT_TYPE); 278 return(0); 279 } 280 281 if (*sk == NULL) 282 *sk=sk_X509_CRL_new_null(); 283 284 CRYPTO_add(&crl->references,1,CRYPTO_LOCK_X509_CRL); 285 sk_X509_CRL_push(*sk,crl); 286 return(1); 287 } 288 289int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, 290 EVP_MD *dgst) 291 { 292 /* We now need to add another PKCS7_SIGNER_INFO entry */ 293 ASN1_INTEGER_set(p7i->version,1); 294 X509_NAME_set(&p7i->issuer_and_serial->issuer, 295 X509_get_issuer_name(x509)); 296 297 /* because ASN1_INTEGER_set is used to set a 'long' we will do 298 * things the ugly way. */ 299 ASN1_INTEGER_free(p7i->issuer_and_serial->serial); 300 p7i->issuer_and_serial->serial= 301 ASN1_INTEGER_dup(X509_get_serialNumber(x509)); 302 303 /* lets keep the pkey around for a while */ 304 CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY); 305 p7i->pkey=pkey; 306 307 /* Set the algorithms */ 308 if (pkey->type == EVP_PKEY_DSA) 309 p7i->digest_alg->algorithm=OBJ_nid2obj(NID_sha1); 310 else 311 p7i->digest_alg->algorithm=OBJ_nid2obj(EVP_MD_type(dgst)); 312 313 if (p7i->digest_alg->parameter != NULL) 314 ASN1_TYPE_free(p7i->digest_alg->parameter); 315 if ((p7i->digest_alg->parameter=ASN1_TYPE_new()) == NULL) 316 goto err; 317 p7i->digest_alg->parameter->type=V_ASN1_NULL; 318 319 p7i->digest_enc_alg->algorithm=OBJ_nid2obj(EVP_PKEY_type(pkey->type)); 320 321 if (p7i->digest_enc_alg->parameter != NULL) 322 ASN1_TYPE_free(p7i->digest_enc_alg->parameter); 323 if ((p7i->digest_enc_alg->parameter=ASN1_TYPE_new()) == NULL) 324 goto err; 325 p7i->digest_enc_alg->parameter->type=V_ASN1_NULL; 326 327 return(1); 328err: 329 return(0); 330 } 331 332PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey, 333 EVP_MD *dgst) 334 { 335 PKCS7_SIGNER_INFO *si; 336 337 if ((si=PKCS7_SIGNER_INFO_new()) == NULL) goto err; 338 if (!PKCS7_SIGNER_INFO_set(si,x509,pkey,dgst)) goto err; 339 if (!PKCS7_add_signer(p7,si)) goto err; 340 return(si); 341err: 342 return(NULL); 343 } 344 345STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7) 346 { 347 if (PKCS7_type_is_signed(p7)) 348 { 349 return(p7->d.sign->signer_info); 350 } 351 else if (PKCS7_type_is_signedAndEnveloped(p7)) 352 { 353 return(p7->d.signed_and_enveloped->signer_info); 354 } 355 else 356 return(NULL); 357 } 358 359PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509) 360 { 361 PKCS7_RECIP_INFO *ri; 362 363 if ((ri=PKCS7_RECIP_INFO_new()) == NULL) goto err; 364 if (!PKCS7_RECIP_INFO_set(ri,x509)) goto err; 365 if (!PKCS7_add_recipient_info(p7,ri)) goto err; 366 return(ri); 367err: 368 return(NULL); 369 } 370 371int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri) 372 { 373 int i; 374 STACK_OF(PKCS7_RECIP_INFO) *sk; 375 376 i=OBJ_obj2nid(p7->type); 377 switch (i) 378 { 379 case NID_pkcs7_signedAndEnveloped: 380 sk= p7->d.signed_and_enveloped->recipientinfo; 381 break; 382 case NID_pkcs7_enveloped: 383 sk= p7->d.enveloped->recipientinfo; 384 break; 385 default: 386 PKCS7err(PKCS7_F_PKCS7_ADD_RECIPIENT_INFO,PKCS7_R_WRONG_CONTENT_TYPE); 387 return(0); 388 } 389 390 sk_PKCS7_RECIP_INFO_push(sk,ri); 391 return(1); 392 } 393 394int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509) 395 { 396 ASN1_INTEGER_set(p7i->version,0); 397 X509_NAME_set(&p7i->issuer_and_serial->issuer, 398 X509_get_issuer_name(x509)); 399 400 ASN1_INTEGER_free(p7i->issuer_and_serial->serial); 401 p7i->issuer_and_serial->serial= 402 ASN1_INTEGER_dup(X509_get_serialNumber(x509)); 403 404 X509_ALGOR_free(p7i->key_enc_algor); 405 p7i->key_enc_algor=(X509_ALGOR *)ASN1_dup(i2d_X509_ALGOR, 406 (char *(*)())d2i_X509_ALGOR, 407 (char *)x509->cert_info->key->algor); 408 409 CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509); 410 p7i->cert=x509; 411 412 return(1); 413 } 414 415X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si) 416 { 417 if (PKCS7_type_is_signed(p7)) 418 return(X509_find_by_issuer_and_serial(p7->d.sign->cert, 419 si->issuer_and_serial->issuer, 420 si->issuer_and_serial->serial)); 421 else 422 return(NULL); 423 } 424 425int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher) 426 { 427 int i; 428 PKCS7_ENC_CONTENT *ec; 429 430 i=OBJ_obj2nid(p7->type); 431 switch (i) 432 { 433 case NID_pkcs7_signedAndEnveloped: 434 ec=p7->d.signed_and_enveloped->enc_data; 435 break; 436 case NID_pkcs7_enveloped: 437 ec=p7->d.enveloped->enc_data; 438 break; 439 default: 440 PKCS7err(PKCS7_F_PKCS7_SET_CIPHER,PKCS7_R_WRONG_CONTENT_TYPE); 441 return(0); 442 } 443 444 /* Setup cipher OID */ 445 446 ec->cipher = cipher; 447 return 1; 448 } 449 450