1/* 2 * $Id: ossl_pkcs7.c 35167 2012-03-29 01:27:17Z emboss $ 3 * 'OpenSSL for Ruby' project 4 * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> 5 * All rights reserved. 6 */ 7/* 8 * This program is licenced under the same licence as Ruby. 9 * (See the file 'LICENCE'.) 10 */ 11#include "ossl.h" 12 13#define WrapPKCS7(klass, obj, pkcs7) do { \ 14 if (!(pkcs7)) { \ 15 ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \ 16 } \ 17 (obj) = Data_Wrap_Struct((klass), 0, PKCS7_free, (pkcs7)); \ 18} while (0) 19#define GetPKCS7(obj, pkcs7) do { \ 20 Data_Get_Struct((obj), PKCS7, (pkcs7)); \ 21 if (!(pkcs7)) { \ 22 ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \ 23 } \ 24} while (0) 25#define SafeGetPKCS7(obj, pkcs7) do { \ 26 OSSL_Check_Kind((obj), cPKCS7); \ 27 GetPKCS7((obj), (pkcs7)); \ 28} while (0) 29 30#define WrapPKCS7si(klass, obj, p7si) do { \ 31 if (!(p7si)) { \ 32 ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \ 33 } \ 34 (obj) = Data_Wrap_Struct((klass), 0, PKCS7_SIGNER_INFO_free, (p7si)); \ 35} while (0) 36#define GetPKCS7si(obj, p7si) do { \ 37 Data_Get_Struct((obj), PKCS7_SIGNER_INFO, (p7si)); \ 38 if (!(p7si)) { \ 39 ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \ 40 } \ 41} while (0) 42#define SafeGetPKCS7si(obj, p7si) do { \ 43 OSSL_Check_Kind((obj), cPKCS7Signer); \ 44 GetPKCS7si((obj), (p7si)); \ 45} while (0) 46 47#define WrapPKCS7ri(klass, obj, p7ri) do { \ 48 if (!(p7ri)) { \ 49 ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \ 50 } \ 51 (obj) = Data_Wrap_Struct((klass), 0, PKCS7_RECIP_INFO_free, (p7ri)); \ 52} while (0) 53#define GetPKCS7ri(obj, p7ri) do { \ 54 Data_Get_Struct((obj), PKCS7_RECIP_INFO, (p7ri)); \ 55 if (!(p7ri)) { \ 56 ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \ 57 } \ 58} while (0) 59#define SafeGetPKCS7ri(obj, p7ri) do { \ 60 OSSL_Check_Kind((obj), cPKCS7Recipient); \ 61 GetPKCS7ri((obj), (p7ri)); \ 62} while (0) 63 64#define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0])) 65 66#define ossl_pkcs7_set_data(o,v) rb_iv_set((o), "@data", (v)) 67#define ossl_pkcs7_get_data(o) rb_iv_get((o), "@data") 68#define ossl_pkcs7_set_err_string(o,v) rb_iv_set((o), "@error_string", (v)) 69#define ossl_pkcs7_get_err_string(o) rb_iv_get((o), "@error_string") 70 71/* 72 * Classes 73 */ 74VALUE cPKCS7; 75VALUE cPKCS7Signer; 76VALUE cPKCS7Recipient; 77VALUE ePKCS7Error; 78 79/* 80 * Public 81 * (MADE PRIVATE UNTIL SOMEBODY WILL NEED THEM) 82 */ 83static VALUE 84ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si) 85{ 86 PKCS7_SIGNER_INFO *pkcs7; 87 VALUE obj; 88 89 pkcs7 = p7si ? PKCS7_SIGNER_INFO_dup(p7si) : PKCS7_SIGNER_INFO_new(); 90 if (!pkcs7) ossl_raise(ePKCS7Error, NULL); 91 WrapPKCS7si(cPKCS7Signer, obj, pkcs7); 92 93 return obj; 94} 95 96static PKCS7_SIGNER_INFO * 97DupPKCS7SignerPtr(VALUE obj) 98{ 99 PKCS7_SIGNER_INFO *p7si, *pkcs7; 100 101 SafeGetPKCS7si(obj, p7si); 102 if (!(pkcs7 = PKCS7_SIGNER_INFO_dup(p7si))) { 103 ossl_raise(ePKCS7Error, NULL); 104 } 105 106 return pkcs7; 107} 108 109static VALUE 110ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri) 111{ 112 PKCS7_RECIP_INFO *pkcs7; 113 VALUE obj; 114 115 pkcs7 = p7ri ? PKCS7_RECIP_INFO_dup(p7ri) : PKCS7_RECIP_INFO_new(); 116 if (!pkcs7) ossl_raise(ePKCS7Error, NULL); 117 WrapPKCS7ri(cPKCS7Recipient, obj, pkcs7); 118 119 return obj; 120} 121 122static PKCS7_RECIP_INFO * 123DupPKCS7RecipientPtr(VALUE obj) 124{ 125 PKCS7_RECIP_INFO *p7ri, *pkcs7; 126 127 SafeGetPKCS7ri(obj, p7ri); 128 if (!(pkcs7 = PKCS7_RECIP_INFO_dup(p7ri))) { 129 ossl_raise(ePKCS7Error, NULL); 130 } 131 132 return pkcs7; 133} 134 135/* 136 * call-seq: 137 * PKCS7.read_smime(string) => pkcs7 138 */ 139static VALUE 140ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg) 141{ 142 BIO *in, *out; 143 PKCS7 *pkcs7; 144 VALUE ret, data; 145 146 in = ossl_obj2bio(arg); 147 out = NULL; 148 pkcs7 = SMIME_read_PKCS7(in, &out); 149 BIO_free(in); 150 if(!pkcs7) ossl_raise(ePKCS7Error, NULL); 151 data = out ? ossl_membio2str(out) : Qnil; 152 WrapPKCS7(cPKCS7, ret, pkcs7); 153 ossl_pkcs7_set_data(ret, data); 154 ossl_pkcs7_set_err_string(ret, Qnil); 155 156 return ret; 157} 158 159/* 160 * call-seq: 161 * PKCS7.write_smime(pkcs7 [, data [, flags]]) => string 162 */ 163static VALUE 164ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass) 165{ 166 VALUE pkcs7, data, flags; 167 BIO *out, *in; 168 PKCS7 *p7; 169 VALUE str; 170 int flg; 171 172 rb_scan_args(argc, argv, "12", &pkcs7, &data, &flags); 173 flg = NIL_P(flags) ? 0 : NUM2INT(flags); 174 if(NIL_P(data)) data = ossl_pkcs7_get_data(pkcs7); 175 SafeGetPKCS7(pkcs7, p7); 176 if(!NIL_P(data) && PKCS7_is_detached(p7)) 177 flg |= PKCS7_DETACHED; 178 in = NIL_P(data) ? NULL : ossl_obj2bio(data); 179 if(!(out = BIO_new(BIO_s_mem()))){ 180 BIO_free(in); 181 ossl_raise(ePKCS7Error, NULL); 182 } 183 if(!SMIME_write_PKCS7(out, p7, in, flg)){ 184 BIO_free(out); 185 BIO_free(in); 186 ossl_raise(ePKCS7Error, NULL); 187 } 188 BIO_free(in); 189 str = ossl_membio2str(out); 190 191 return str; 192} 193 194/* 195 * call-seq: 196 * PKCS7.sign(cert, key, data, [, certs [, flags]]) => pkcs7 197 */ 198static VALUE 199ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass) 200{ 201 VALUE cert, key, data, certs, flags; 202 X509 *x509; 203 EVP_PKEY *pkey; 204 BIO *in; 205 STACK_OF(X509) *x509s; 206 int flg, status = 0; 207 PKCS7 *pkcs7; 208 VALUE ret; 209 210 rb_scan_args(argc, argv, "32", &cert, &key, &data, &certs, &flags); 211 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ 212 pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ 213 flg = NIL_P(flags) ? 0 : NUM2INT(flags); 214 in = ossl_obj2bio(data); 215 if(NIL_P(certs)) x509s = NULL; 216 else{ 217 x509s = ossl_protect_x509_ary2sk(certs, &status); 218 if(status){ 219 BIO_free(in); 220 rb_jump_tag(status); 221 } 222 } 223 if(!(pkcs7 = PKCS7_sign(x509, pkey, x509s, in, flg))){ 224 BIO_free(in); 225 sk_X509_pop_free(x509s, X509_free); 226 ossl_raise(ePKCS7Error, NULL); 227 } 228 WrapPKCS7(cPKCS7, ret, pkcs7); 229 ossl_pkcs7_set_data(ret, data); 230 ossl_pkcs7_set_err_string(ret, Qnil); 231 BIO_free(in); 232 sk_X509_pop_free(x509s, X509_free); 233 234 return ret; 235} 236 237/* 238 * call-seq: 239 * PKCS7.encrypt(certs, data, [, cipher [, flags]]) => pkcs7 240 */ 241static VALUE 242ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass) 243{ 244 VALUE certs, data, cipher, flags; 245 STACK_OF(X509) *x509s; 246 BIO *in; 247 const EVP_CIPHER *ciph; 248 int flg, status = 0; 249 VALUE ret; 250 PKCS7 *p7; 251 252 rb_scan_args(argc, argv, "22", &certs, &data, &cipher, &flags); 253 if(NIL_P(cipher)){ 254#if !defined(OPENSSL_NO_RC2) 255 ciph = EVP_rc2_40_cbc(); 256#elif !defined(OPENSSL_NO_DES) 257 ciph = EVP_des_ede3_cbc(); 258#elif !defined(OPENSSL_NO_RC2) 259 ciph = EVP_rc2_40_cbc(); 260#elif !defined(OPENSSL_NO_AES) 261 ciph = EVP_EVP_aes_128_cbc(); 262#else 263 ossl_raise(ePKCS7Error, "Must specify cipher"); 264#endif 265 266 } 267 else ciph = GetCipherPtr(cipher); /* NO NEED TO DUP */ 268 flg = NIL_P(flags) ? 0 : NUM2INT(flags); 269 in = ossl_obj2bio(data); 270 x509s = ossl_protect_x509_ary2sk(certs, &status); 271 if(status){ 272 BIO_free(in); 273 rb_jump_tag(status); 274 } 275 if(!(p7 = PKCS7_encrypt(x509s, in, (EVP_CIPHER*)ciph, flg))){ 276 BIO_free(in); 277 sk_X509_pop_free(x509s, X509_free); 278 ossl_raise(ePKCS7Error, NULL); 279 } 280 BIO_free(in); 281 WrapPKCS7(cPKCS7, ret, p7); 282 ossl_pkcs7_set_data(ret, data); 283 sk_X509_pop_free(x509s, X509_free); 284 285 return ret; 286} 287 288static VALUE 289ossl_pkcs7_alloc(VALUE klass) 290{ 291 PKCS7 *pkcs7; 292 VALUE obj; 293 294 if (!(pkcs7 = PKCS7_new())) { 295 ossl_raise(ePKCS7Error, NULL); 296 } 297 WrapPKCS7(klass, obj, pkcs7); 298 299 return obj; 300} 301 302/* 303 * call-seq: 304 * PKCS7.new => pkcs7 305 * PKCS7.new(string) => pkcs7 306 * 307 * Many methods in this class aren't documented. 308 */ 309static VALUE 310ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self) 311{ 312 PKCS7 *p7, *pkcs = DATA_PTR(self); 313 BIO *in; 314 VALUE arg; 315 316 if(rb_scan_args(argc, argv, "01", &arg) == 0) 317 return self; 318 arg = ossl_to_der_if_possible(arg); 319 in = ossl_obj2bio(arg); 320 p7 = PEM_read_bio_PKCS7(in, &pkcs, NULL, NULL); 321 if (!p7) { 322 OSSL_BIO_reset(in); 323 p7 = d2i_PKCS7_bio(in, &pkcs); 324 if (!p7) { 325 BIO_free(in); 326 PKCS7_free(pkcs); 327 DATA_PTR(self) = NULL; 328 ossl_raise(rb_eArgError, "Could not parse the PKCS7"); 329 } 330 } 331 DATA_PTR(self) = pkcs; 332 BIO_free(in); 333 ossl_pkcs7_set_data(self, Qnil); 334 ossl_pkcs7_set_err_string(self, Qnil); 335 336 return self; 337} 338 339static VALUE 340ossl_pkcs7_copy(VALUE self, VALUE other) 341{ 342 PKCS7 *a, *b, *pkcs7; 343 344 rb_check_frozen(self); 345 if (self == other) return self; 346 347 GetPKCS7(self, a); 348 SafeGetPKCS7(other, b); 349 350 pkcs7 = PKCS7_dup(b); 351 if (!pkcs7) { 352 ossl_raise(ePKCS7Error, NULL); 353 } 354 DATA_PTR(self) = pkcs7; 355 PKCS7_free(a); 356 357 return self; 358} 359 360static int 361ossl_pkcs7_sym2typeid(VALUE sym) 362{ 363 int i, ret = Qnil; 364 const char *s; 365 366 static struct { 367 const char *name; 368 int nid; 369 } p7_type_tab[] = { 370 { "signed", NID_pkcs7_signed }, 371 { "data", NID_pkcs7_data }, 372 { "signedAndEnveloped", NID_pkcs7_signedAndEnveloped }, 373 { "enveloped", NID_pkcs7_enveloped }, 374 { "encrypted", NID_pkcs7_encrypted }, 375 { "digest", NID_pkcs7_digest }, 376 { NULL, 0 }, 377 }; 378 379 if(TYPE(sym) == T_SYMBOL) s = rb_id2name(SYM2ID(sym)); 380 else s = StringValuePtr(sym); 381 for(i = 0; i < numberof(p7_type_tab); i++){ 382 if(p7_type_tab[i].name == NULL) 383 ossl_raise(ePKCS7Error, "unknown type \"%s\"", s); 384 if(strcmp(p7_type_tab[i].name, s) == 0){ 385 ret = p7_type_tab[i].nid; 386 break; 387 } 388 } 389 390 return ret; 391} 392 393/* 394 * call-seq: 395 * pkcs7.type = type => type 396 */ 397static VALUE 398ossl_pkcs7_set_type(VALUE self, VALUE type) 399{ 400 PKCS7 *p7; 401 402 GetPKCS7(self, p7); 403 if(!PKCS7_set_type(p7, ossl_pkcs7_sym2typeid(type))) 404 ossl_raise(ePKCS7Error, NULL); 405 406 return type; 407} 408 409/* 410 * call-seq: 411 * pkcs7.type => string or nil 412 */ 413static VALUE 414ossl_pkcs7_get_type(VALUE self) 415{ 416 PKCS7 *p7; 417 418 GetPKCS7(self, p7); 419 if(PKCS7_type_is_signed(p7)) 420 return ID2SYM(rb_intern("signed")); 421 if(PKCS7_type_is_encrypted(p7)) 422 return ID2SYM(rb_intern("encrypted")); 423 if(PKCS7_type_is_enveloped(p7)) 424 return ID2SYM(rb_intern("enveloped")); 425 if(PKCS7_type_is_signedAndEnveloped(p7)) 426 return ID2SYM(rb_intern("signedAndEnveloped")); 427 if(PKCS7_type_is_data(p7)) 428 return ID2SYM(rb_intern("data")); 429 return Qnil; 430} 431 432static VALUE 433ossl_pkcs7_set_detached(VALUE self, VALUE flag) 434{ 435 PKCS7 *p7; 436 437 GetPKCS7(self, p7); 438 if(flag != Qtrue && flag != Qfalse) 439 ossl_raise(ePKCS7Error, "must specify a boolean"); 440 if(!PKCS7_set_detached(p7, flag == Qtrue ? 1 : 0)) 441 ossl_raise(ePKCS7Error, NULL); 442 443 return flag; 444} 445 446static VALUE 447ossl_pkcs7_get_detached(VALUE self) 448{ 449 PKCS7 *p7; 450 GetPKCS7(self, p7); 451 return PKCS7_get_detached(p7) ? Qtrue : Qfalse; 452} 453 454static VALUE 455ossl_pkcs7_detached_p(VALUE self) 456{ 457 PKCS7 *p7; 458 GetPKCS7(self, p7); 459 return PKCS7_is_detached(p7) ? Qtrue : Qfalse; 460} 461 462static VALUE 463ossl_pkcs7_set_cipher(VALUE self, VALUE cipher) 464{ 465 PKCS7 *pkcs7; 466 467 GetPKCS7(self, pkcs7); 468 if (!PKCS7_set_cipher(pkcs7, GetCipherPtr(cipher))) { 469 ossl_raise(ePKCS7Error, NULL); 470 } 471 472 return cipher; 473} 474 475static VALUE 476ossl_pkcs7_add_signer(VALUE self, VALUE signer) 477{ 478 PKCS7 *pkcs7; 479 PKCS7_SIGNER_INFO *p7si; 480 481 p7si = DupPKCS7SignerPtr(signer); /* NEED TO DUP */ 482 GetPKCS7(self, pkcs7); 483 if (!PKCS7_add_signer(pkcs7, p7si)) { 484 PKCS7_SIGNER_INFO_free(p7si); 485 ossl_raise(ePKCS7Error, "Could not add signer."); 486 } 487 if (PKCS7_type_is_signed(pkcs7)){ 488 PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType, 489 V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data)); 490 } 491 492 return self; 493} 494 495static VALUE 496ossl_pkcs7_get_signer(VALUE self) 497{ 498 PKCS7 *pkcs7; 499 STACK_OF(PKCS7_SIGNER_INFO) *sk; 500 PKCS7_SIGNER_INFO *si; 501 int num, i; 502 VALUE ary; 503 504 GetPKCS7(self, pkcs7); 505 if (!(sk = PKCS7_get_signer_info(pkcs7))) { 506 OSSL_Debug("OpenSSL::PKCS7#get_signer_info == NULL!"); 507 return rb_ary_new(); 508 } 509 if ((num = sk_PKCS7_SIGNER_INFO_num(sk)) < 0) { 510 ossl_raise(ePKCS7Error, "Negative number of signers!"); 511 } 512 ary = rb_ary_new2(num); 513 for (i=0; i<num; i++) { 514 si = sk_PKCS7_SIGNER_INFO_value(sk, i); 515 rb_ary_push(ary, ossl_pkcs7si_new(si)); 516 } 517 518 return ary; 519} 520 521static VALUE 522ossl_pkcs7_add_recipient(VALUE self, VALUE recip) 523{ 524 PKCS7 *pkcs7; 525 PKCS7_RECIP_INFO *ri; 526 527 ri = DupPKCS7RecipientPtr(recip); /* NEED TO DUP */ 528 GetPKCS7(self, pkcs7); 529 if (!PKCS7_add_recipient_info(pkcs7, ri)) { 530 PKCS7_RECIP_INFO_free(ri); 531 ossl_raise(ePKCS7Error, "Could not add recipient."); 532 } 533 534 return self; 535} 536 537static VALUE 538ossl_pkcs7_get_recipient(VALUE self) 539{ 540 PKCS7 *pkcs7; 541 STACK_OF(PKCS7_RECIP_INFO) *sk; 542 PKCS7_RECIP_INFO *si; 543 int num, i; 544 VALUE ary; 545 546 GetPKCS7(self, pkcs7); 547 if (PKCS7_type_is_enveloped(pkcs7)) 548 sk = pkcs7->d.enveloped->recipientinfo; 549 else if (PKCS7_type_is_signedAndEnveloped(pkcs7)) 550 sk = pkcs7->d.signed_and_enveloped->recipientinfo; 551 else sk = NULL; 552 if (!sk) return rb_ary_new(); 553 if ((num = sk_PKCS7_RECIP_INFO_num(sk)) < 0) { 554 ossl_raise(ePKCS7Error, "Negative number of recipient!"); 555 } 556 ary = rb_ary_new2(num); 557 for (i=0; i<num; i++) { 558 si = sk_PKCS7_RECIP_INFO_value(sk, i); 559 rb_ary_push(ary, ossl_pkcs7ri_new(si)); 560 } 561 562 return ary; 563} 564 565static VALUE 566ossl_pkcs7_add_certificate(VALUE self, VALUE cert) 567{ 568 PKCS7 *pkcs7; 569 X509 *x509; 570 571 GetPKCS7(self, pkcs7); 572 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ 573 if (!PKCS7_add_certificate(pkcs7, x509)){ 574 ossl_raise(ePKCS7Error, NULL); 575 } 576 577 return self; 578} 579 580static STACK_OF(X509) * 581pkcs7_get_certs(VALUE self) 582{ 583 PKCS7 *pkcs7; 584 STACK_OF(X509) *certs; 585 int i; 586 587 GetPKCS7(self, pkcs7); 588 i = OBJ_obj2nid(pkcs7->type); 589 switch(i){ 590 case NID_pkcs7_signed: 591 certs = pkcs7->d.sign->cert; 592 break; 593 case NID_pkcs7_signedAndEnveloped: 594 certs = pkcs7->d.signed_and_enveloped->cert; 595 break; 596 default: 597 certs = NULL; 598 } 599 600 return certs; 601} 602 603static STACK_OF(X509_CRL) * 604pkcs7_get_crls(VALUE self) 605{ 606 PKCS7 *pkcs7; 607 STACK_OF(X509_CRL) *crls; 608 int i; 609 610 GetPKCS7(self, pkcs7); 611 i = OBJ_obj2nid(pkcs7->type); 612 switch(i){ 613 case NID_pkcs7_signed: 614 crls = pkcs7->d.sign->crl; 615 break; 616 case NID_pkcs7_signedAndEnveloped: 617 crls = pkcs7->d.signed_and_enveloped->crl; 618 break; 619 default: 620 crls = NULL; 621 } 622 623 return crls; 624} 625 626static VALUE 627ossl_pkcs7_set_certs_i(VALUE i, VALUE arg) 628{ 629 return ossl_pkcs7_add_certificate(arg, i); 630} 631 632static VALUE 633ossl_pkcs7_set_certificates(VALUE self, VALUE ary) 634{ 635 STACK_OF(X509) *certs; 636 X509 *cert; 637 638 certs = pkcs7_get_certs(self); 639 while((cert = sk_X509_pop(certs))) X509_free(cert); 640 rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_certs_i, self); 641 642 return ary; 643} 644 645static VALUE 646ossl_pkcs7_get_certificates(VALUE self) 647{ 648 return ossl_x509_sk2ary(pkcs7_get_certs(self)); 649} 650 651static VALUE 652ossl_pkcs7_add_crl(VALUE self, VALUE crl) 653{ 654 PKCS7 *pkcs7; 655 X509_CRL *x509crl; 656 657 GetPKCS7(self, pkcs7); /* NO DUP needed! */ 658 x509crl = GetX509CRLPtr(crl); 659 if (!PKCS7_add_crl(pkcs7, x509crl)) { 660 ossl_raise(ePKCS7Error, NULL); 661 } 662 663 return self; 664} 665 666static VALUE 667ossl_pkcs7_set_crls_i(VALUE i, VALUE arg) 668{ 669 return ossl_pkcs7_add_crl(arg, i); 670} 671 672static VALUE 673ossl_pkcs7_set_crls(VALUE self, VALUE ary) 674{ 675 STACK_OF(X509_CRL) *crls; 676 X509_CRL *crl; 677 678 crls = pkcs7_get_crls(self); 679 while((crl = sk_X509_CRL_pop(crls))) X509_CRL_free(crl); 680 rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_crls_i, self); 681 682 return ary; 683} 684 685static VALUE 686ossl_pkcs7_get_crls(VALUE self) 687{ 688 return ossl_x509crl_sk2ary(pkcs7_get_crls(self)); 689} 690 691static VALUE 692ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self) 693{ 694 VALUE certs, store, indata, flags; 695 STACK_OF(X509) *x509s; 696 X509_STORE *x509st; 697 int flg, ok, status = 0; 698 BIO *in, *out; 699 PKCS7 *p7; 700 VALUE data; 701 const char *msg; 702 703 rb_scan_args(argc, argv, "22", &certs, &store, &indata, &flags); 704 flg = NIL_P(flags) ? 0 : NUM2INT(flags); 705 if(NIL_P(indata)) indata = ossl_pkcs7_get_data(self); 706 in = NIL_P(indata) ? NULL : ossl_obj2bio(indata); 707 if(NIL_P(certs)) x509s = NULL; 708 else{ 709 x509s = ossl_protect_x509_ary2sk(certs, &status); 710 if(status){ 711 BIO_free(in); 712 rb_jump_tag(status); 713 } 714 } 715 x509st = GetX509StorePtr(store); 716 GetPKCS7(self, p7); 717 if(!(out = BIO_new(BIO_s_mem()))){ 718 BIO_free(in); 719 sk_X509_pop_free(x509s, X509_free); 720 ossl_raise(ePKCS7Error, NULL); 721 } 722 ok = PKCS7_verify(p7, x509s, x509st, in, out, flg); 723 BIO_free(in); 724 if (ok < 0) ossl_raise(ePKCS7Error, NULL); 725 msg = ERR_reason_error_string(ERR_get_error()); 726 ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil); 727 ERR_clear_error(); 728 data = ossl_membio2str(out); 729 ossl_pkcs7_set_data(self, data); 730 sk_X509_pop_free(x509s, X509_free); 731 732 return (ok == 1) ? Qtrue : Qfalse; 733} 734 735static VALUE 736ossl_pkcs7_decrypt(int argc, VALUE *argv, VALUE self) 737{ 738 VALUE pkey, cert, flags; 739 EVP_PKEY *key; 740 X509 *x509; 741 int flg; 742 PKCS7 *p7; 743 BIO *out; 744 VALUE str; 745 746 rb_scan_args(argc, argv, "21", &pkey, &cert, &flags); 747 key = GetPrivPKeyPtr(pkey); /* NO NEED TO DUP */ 748 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ 749 flg = NIL_P(flags) ? 0 : NUM2INT(flags); 750 GetPKCS7(self, p7); 751 if(!(out = BIO_new(BIO_s_mem()))) 752 ossl_raise(ePKCS7Error, NULL); 753 if(!PKCS7_decrypt(p7, key, x509, out, flg)){ 754 BIO_free(out); 755 ossl_raise(ePKCS7Error, NULL); 756 } 757 str = ossl_membio2str(out); /* out will be free */ 758 759 return str; 760} 761 762static VALUE 763ossl_pkcs7_add_data(VALUE self, VALUE data) 764{ 765 PKCS7 *pkcs7; 766 BIO *out, *in; 767 char buf[4096]; 768 int len; 769 770 in = ossl_obj2bio(data); 771 GetPKCS7(self, pkcs7); 772 if(PKCS7_type_is_signed(pkcs7)){ 773 if(!PKCS7_content_new(pkcs7, NID_pkcs7_data)) 774 ossl_raise(ePKCS7Error, NULL); 775 } 776 if(!(out = PKCS7_dataInit(pkcs7, NULL))) goto err; 777 for(;;){ 778 if((len = BIO_read(in, buf, sizeof(buf))) <= 0) 779 break; 780 if(BIO_write(out, buf, len) != len) 781 goto err; 782 } 783 if(!PKCS7_dataFinal(pkcs7, out)) goto err; 784 ossl_pkcs7_set_data(self, Qnil); 785 786 err: 787 BIO_free(out); 788 BIO_free(in); 789 if(ERR_peek_error()){ 790 ossl_raise(ePKCS7Error, NULL); 791 } 792 793 return data; 794} 795 796static VALUE 797ossl_pkcs7_to_der(VALUE self) 798{ 799 PKCS7 *pkcs7; 800 VALUE str; 801 long len; 802 unsigned char *p; 803 804 GetPKCS7(self, pkcs7); 805 if((len = i2d_PKCS7(pkcs7, NULL)) <= 0) 806 ossl_raise(ePKCS7Error, NULL); 807 str = rb_str_new(0, len); 808 p = (unsigned char *)RSTRING_PTR(str); 809 if(i2d_PKCS7(pkcs7, &p) <= 0) 810 ossl_raise(ePKCS7Error, NULL); 811 ossl_str_adjust(str, p); 812 813 return str; 814} 815 816static VALUE 817ossl_pkcs7_to_pem(VALUE self) 818{ 819 PKCS7 *pkcs7; 820 BIO *out; 821 VALUE str; 822 823 GetPKCS7(self, pkcs7); 824 if (!(out = BIO_new(BIO_s_mem()))) { 825 ossl_raise(ePKCS7Error, NULL); 826 } 827 if (!PEM_write_bio_PKCS7(out, pkcs7)) { 828 BIO_free(out); 829 ossl_raise(ePKCS7Error, NULL); 830 } 831 str = ossl_membio2str(out); 832 833 return str; 834} 835 836/* 837 * SIGNER INFO 838 */ 839static VALUE 840ossl_pkcs7si_alloc(VALUE klass) 841{ 842 PKCS7_SIGNER_INFO *p7si; 843 VALUE obj; 844 845 if (!(p7si = PKCS7_SIGNER_INFO_new())) { 846 ossl_raise(ePKCS7Error, NULL); 847 } 848 WrapPKCS7si(klass, obj, p7si); 849 850 return obj; 851} 852 853static VALUE 854ossl_pkcs7si_initialize(VALUE self, VALUE cert, VALUE key, VALUE digest) 855{ 856 PKCS7_SIGNER_INFO *p7si; 857 EVP_PKEY *pkey; 858 X509 *x509; 859 const EVP_MD *md; 860 861 pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ 862 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ 863 md = GetDigestPtr(digest); 864 GetPKCS7si(self, p7si); 865 if (!(PKCS7_SIGNER_INFO_set(p7si, x509, pkey, (EVP_MD*)md))) { 866 ossl_raise(ePKCS7Error, NULL); 867 } 868 869 return self; 870} 871 872static VALUE 873ossl_pkcs7si_get_issuer(VALUE self) 874{ 875 PKCS7_SIGNER_INFO *p7si; 876 877 GetPKCS7si(self, p7si); 878 879 return ossl_x509name_new(p7si->issuer_and_serial->issuer); 880} 881 882static VALUE 883ossl_pkcs7si_get_serial(VALUE self) 884{ 885 PKCS7_SIGNER_INFO *p7si; 886 887 GetPKCS7si(self, p7si); 888 889 return asn1integer_to_num(p7si->issuer_and_serial->serial); 890} 891 892static VALUE 893ossl_pkcs7si_get_signed_time(VALUE self) 894{ 895 PKCS7_SIGNER_INFO *p7si; 896 ASN1_TYPE *asn1obj; 897 898 GetPKCS7si(self, p7si); 899 900 if (!(asn1obj = PKCS7_get_signed_attribute(p7si, NID_pkcs9_signingTime))) { 901 ossl_raise(ePKCS7Error, NULL); 902 } 903 if (asn1obj->type == V_ASN1_UTCTIME) { 904 return asn1time_to_time(asn1obj->value.utctime); 905 } 906 /* 907 * OR 908 * ossl_raise(ePKCS7Error, "..."); 909 * ? 910 */ 911 912 return Qnil; 913} 914 915/* 916 * RECIPIENT INFO 917 */ 918static VALUE 919ossl_pkcs7ri_alloc(VALUE klass) 920{ 921 PKCS7_RECIP_INFO *p7ri; 922 VALUE obj; 923 924 if (!(p7ri = PKCS7_RECIP_INFO_new())) { 925 ossl_raise(ePKCS7Error, NULL); 926 } 927 WrapPKCS7ri(klass, obj, p7ri); 928 929 return obj; 930} 931 932static VALUE 933ossl_pkcs7ri_initialize(VALUE self, VALUE cert) 934{ 935 PKCS7_RECIP_INFO *p7ri; 936 X509 *x509; 937 938 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ 939 GetPKCS7ri(self, p7ri); 940 if (!PKCS7_RECIP_INFO_set(p7ri, x509)) { 941 ossl_raise(ePKCS7Error, NULL); 942 } 943 944 return self; 945} 946 947static VALUE 948ossl_pkcs7ri_get_issuer(VALUE self) 949{ 950 PKCS7_RECIP_INFO *p7ri; 951 952 GetPKCS7ri(self, p7ri); 953 954 return ossl_x509name_new(p7ri->issuer_and_serial->issuer); 955} 956 957static VALUE 958ossl_pkcs7ri_get_serial(VALUE self) 959{ 960 PKCS7_RECIP_INFO *p7ri; 961 962 GetPKCS7ri(self, p7ri); 963 964 return asn1integer_to_num(p7ri->issuer_and_serial->serial); 965} 966 967static VALUE 968ossl_pkcs7ri_get_enc_key(VALUE self) 969{ 970 PKCS7_RECIP_INFO *p7ri; 971 972 GetPKCS7ri(self, p7ri); 973 974 return asn1str_to_str(p7ri->enc_key); 975} 976 977/* 978 * INIT 979 */ 980void 981Init_ossl_pkcs7() 982{ 983 cPKCS7 = rb_define_class_under(mOSSL, "PKCS7", rb_cObject); 984 ePKCS7Error = rb_define_class_under(cPKCS7, "PKCS7Error", eOSSLError); 985 rb_define_singleton_method(cPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1); 986 rb_define_singleton_method(cPKCS7, "write_smime", ossl_pkcs7_s_write_smime, -1); 987 rb_define_singleton_method(cPKCS7, "sign", ossl_pkcs7_s_sign, -1); 988 rb_define_singleton_method(cPKCS7, "encrypt", ossl_pkcs7_s_encrypt, -1); 989 rb_attr(cPKCS7, rb_intern("data"), 1, 0, Qfalse); 990 rb_attr(cPKCS7, rb_intern("error_string"), 1, 1, Qfalse); 991 rb_define_alloc_func(cPKCS7, ossl_pkcs7_alloc); 992 rb_define_copy_func(cPKCS7, ossl_pkcs7_copy); 993 rb_define_method(cPKCS7, "initialize", ossl_pkcs7_initialize, -1); 994 rb_define_method(cPKCS7, "type=", ossl_pkcs7_set_type, 1); 995 rb_define_method(cPKCS7, "type", ossl_pkcs7_get_type, 0); 996 rb_define_method(cPKCS7, "detached=", ossl_pkcs7_set_detached, 1); 997 rb_define_method(cPKCS7, "detached", ossl_pkcs7_get_detached, 0); 998 rb_define_method(cPKCS7, "detached?", ossl_pkcs7_detached_p, 0); 999 rb_define_method(cPKCS7, "cipher=", ossl_pkcs7_set_cipher, 1); 1000 rb_define_method(cPKCS7, "add_signer", ossl_pkcs7_add_signer, 1); 1001 rb_define_method(cPKCS7, "signers", ossl_pkcs7_get_signer, 0); 1002 rb_define_method(cPKCS7, "add_recipient", ossl_pkcs7_add_recipient, 1); 1003 rb_define_method(cPKCS7, "recipients", ossl_pkcs7_get_recipient, 0); 1004 rb_define_method(cPKCS7, "add_certificate", ossl_pkcs7_add_certificate, 1); 1005 rb_define_method(cPKCS7, "certificates=", ossl_pkcs7_set_certificates, 1); 1006 rb_define_method(cPKCS7, "certificates", ossl_pkcs7_get_certificates, 0); 1007 rb_define_method(cPKCS7, "add_crl", ossl_pkcs7_add_crl, 1); 1008 rb_define_method(cPKCS7, "crls=", ossl_pkcs7_set_crls, 1); 1009 rb_define_method(cPKCS7, "crls", ossl_pkcs7_get_crls, 0); 1010 rb_define_method(cPKCS7, "add_data", ossl_pkcs7_add_data, 1); 1011 rb_define_alias(cPKCS7, "data=", "add_data"); 1012 rb_define_method(cPKCS7, "verify", ossl_pkcs7_verify, -1); 1013 rb_define_method(cPKCS7, "decrypt", ossl_pkcs7_decrypt, -1); 1014 rb_define_method(cPKCS7, "to_pem", ossl_pkcs7_to_pem, 0); 1015 rb_define_alias(cPKCS7, "to_s", "to_pem"); 1016 rb_define_method(cPKCS7, "to_der", ossl_pkcs7_to_der, 0); 1017 1018 cPKCS7Signer = rb_define_class_under(cPKCS7, "SignerInfo", rb_cObject); 1019 rb_define_const(cPKCS7, "Signer", cPKCS7Signer); 1020 rb_define_alloc_func(cPKCS7Signer, ossl_pkcs7si_alloc); 1021 rb_define_method(cPKCS7Signer, "initialize", ossl_pkcs7si_initialize,3); 1022 rb_define_method(cPKCS7Signer, "issuer", ossl_pkcs7si_get_issuer, 0); 1023 rb_define_alias(cPKCS7Signer, "name", "issuer"); 1024 rb_define_method(cPKCS7Signer, "serial", ossl_pkcs7si_get_serial,0); 1025 rb_define_method(cPKCS7Signer,"signed_time",ossl_pkcs7si_get_signed_time,0); 1026 1027 cPKCS7Recipient = rb_define_class_under(cPKCS7,"RecipientInfo",rb_cObject); 1028 rb_define_alloc_func(cPKCS7Recipient, ossl_pkcs7ri_alloc); 1029 rb_define_method(cPKCS7Recipient, "initialize", ossl_pkcs7ri_initialize,1); 1030 rb_define_method(cPKCS7Recipient, "issuer", ossl_pkcs7ri_get_issuer,0); 1031 rb_define_method(cPKCS7Recipient, "serial", ossl_pkcs7ri_get_serial,0); 1032 rb_define_method(cPKCS7Recipient, "enc_key", ossl_pkcs7ri_get_enc_key,0); 1033 1034#define DefPKCS7Const(x) rb_define_const(cPKCS7, #x, INT2NUM(PKCS7_##x)) 1035 1036 DefPKCS7Const(TEXT); 1037 DefPKCS7Const(NOCERTS); 1038 DefPKCS7Const(NOSIGS); 1039 DefPKCS7Const(NOCHAIN); 1040 DefPKCS7Const(NOINTERN); 1041 DefPKCS7Const(NOVERIFY); 1042 DefPKCS7Const(DETACHED); 1043 DefPKCS7Const(BINARY); 1044 DefPKCS7Const(NOATTR); 1045 DefPKCS7Const(NOSMIMECAP); 1046} 1047