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 485