Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 /* 00002 * $Id: ossl_pkcs7.c 35167 2012-03-29 01:27:17Z emboss $ 00003 * 'OpenSSL for Ruby' project 00004 * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> 00005 * All rights reserved. 00006 */ 00007 /* 00008 * This program is licenced under the same licence as Ruby. 00009 * (See the file 'LICENCE'.) 00010 */ 00011 #include "ossl.h" 00012 00013 #define WrapPKCS7(klass, obj, pkcs7) do { \ 00014 if (!(pkcs7)) { \ 00015 ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \ 00016 } \ 00017 (obj) = Data_Wrap_Struct((klass), 0, PKCS7_free, (pkcs7)); \ 00018 } while (0) 00019 #define GetPKCS7(obj, pkcs7) do { \ 00020 Data_Get_Struct((obj), PKCS7, (pkcs7)); \ 00021 if (!(pkcs7)) { \ 00022 ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \ 00023 } \ 00024 } while (0) 00025 #define SafeGetPKCS7(obj, pkcs7) do { \ 00026 OSSL_Check_Kind((obj), cPKCS7); \ 00027 GetPKCS7((obj), (pkcs7)); \ 00028 } while (0) 00029 00030 #define WrapPKCS7si(klass, obj, p7si) do { \ 00031 if (!(p7si)) { \ 00032 ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \ 00033 } \ 00034 (obj) = Data_Wrap_Struct((klass), 0, PKCS7_SIGNER_INFO_free, (p7si)); \ 00035 } while (0) 00036 #define GetPKCS7si(obj, p7si) do { \ 00037 Data_Get_Struct((obj), PKCS7_SIGNER_INFO, (p7si)); \ 00038 if (!(p7si)) { \ 00039 ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \ 00040 } \ 00041 } while (0) 00042 #define SafeGetPKCS7si(obj, p7si) do { \ 00043 OSSL_Check_Kind((obj), cPKCS7Signer); \ 00044 GetPKCS7si((obj), (p7si)); \ 00045 } while (0) 00046 00047 #define WrapPKCS7ri(klass, obj, p7ri) do { \ 00048 if (!(p7ri)) { \ 00049 ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \ 00050 } \ 00051 (obj) = Data_Wrap_Struct((klass), 0, PKCS7_RECIP_INFO_free, (p7ri)); \ 00052 } while (0) 00053 #define GetPKCS7ri(obj, p7ri) do { \ 00054 Data_Get_Struct((obj), PKCS7_RECIP_INFO, (p7ri)); \ 00055 if (!(p7ri)) { \ 00056 ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \ 00057 } \ 00058 } while (0) 00059 #define SafeGetPKCS7ri(obj, p7ri) do { \ 00060 OSSL_Check_Kind((obj), cPKCS7Recipient); \ 00061 GetPKCS7ri((obj), (p7ri)); \ 00062 } while (0) 00063 00064 #define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0])) 00065 00066 #define ossl_pkcs7_set_data(o,v) rb_iv_set((o), "@data", (v)) 00067 #define ossl_pkcs7_get_data(o) rb_iv_get((o), "@data") 00068 #define ossl_pkcs7_set_err_string(o,v) rb_iv_set((o), "@error_string", (v)) 00069 #define ossl_pkcs7_get_err_string(o) rb_iv_get((o), "@error_string") 00070 00071 /* 00072 * Classes 00073 */ 00074 VALUE cPKCS7; 00075 VALUE cPKCS7Signer; 00076 VALUE cPKCS7Recipient; 00077 VALUE ePKCS7Error; 00078 00079 /* 00080 * Public 00081 * (MADE PRIVATE UNTIL SOMEBODY WILL NEED THEM) 00082 */ 00083 static VALUE 00084 ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si) 00085 { 00086 PKCS7_SIGNER_INFO *pkcs7; 00087 VALUE obj; 00088 00089 pkcs7 = p7si ? PKCS7_SIGNER_INFO_dup(p7si) : PKCS7_SIGNER_INFO_new(); 00090 if (!pkcs7) ossl_raise(ePKCS7Error, NULL); 00091 WrapPKCS7si(cPKCS7Signer, obj, pkcs7); 00092 00093 return obj; 00094 } 00095 00096 static PKCS7_SIGNER_INFO * 00097 DupPKCS7SignerPtr(VALUE obj) 00098 { 00099 PKCS7_SIGNER_INFO *p7si, *pkcs7; 00100 00101 SafeGetPKCS7si(obj, p7si); 00102 if (!(pkcs7 = PKCS7_SIGNER_INFO_dup(p7si))) { 00103 ossl_raise(ePKCS7Error, NULL); 00104 } 00105 00106 return pkcs7; 00107 } 00108 00109 static VALUE 00110 ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri) 00111 { 00112 PKCS7_RECIP_INFO *pkcs7; 00113 VALUE obj; 00114 00115 pkcs7 = p7ri ? PKCS7_RECIP_INFO_dup(p7ri) : PKCS7_RECIP_INFO_new(); 00116 if (!pkcs7) ossl_raise(ePKCS7Error, NULL); 00117 WrapPKCS7ri(cPKCS7Recipient, obj, pkcs7); 00118 00119 return obj; 00120 } 00121 00122 static PKCS7_RECIP_INFO * 00123 DupPKCS7RecipientPtr(VALUE obj) 00124 { 00125 PKCS7_RECIP_INFO *p7ri, *pkcs7; 00126 00127 SafeGetPKCS7ri(obj, p7ri); 00128 if (!(pkcs7 = PKCS7_RECIP_INFO_dup(p7ri))) { 00129 ossl_raise(ePKCS7Error, NULL); 00130 } 00131 00132 return pkcs7; 00133 } 00134 00135 /* 00136 * call-seq: 00137 * PKCS7.read_smime(string) => pkcs7 00138 */ 00139 static VALUE 00140 ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg) 00141 { 00142 BIO *in, *out; 00143 PKCS7 *pkcs7; 00144 VALUE ret, data; 00145 00146 in = ossl_obj2bio(arg); 00147 out = NULL; 00148 pkcs7 = SMIME_read_PKCS7(in, &out); 00149 BIO_free(in); 00150 if(!pkcs7) ossl_raise(ePKCS7Error, NULL); 00151 data = out ? ossl_membio2str(out) : Qnil; 00152 WrapPKCS7(cPKCS7, ret, pkcs7); 00153 ossl_pkcs7_set_data(ret, data); 00154 ossl_pkcs7_set_err_string(ret, Qnil); 00155 00156 return ret; 00157 } 00158 00159 /* 00160 * call-seq: 00161 * PKCS7.write_smime(pkcs7 [, data [, flags]]) => string 00162 */ 00163 static VALUE 00164 ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass) 00165 { 00166 VALUE pkcs7, data, flags; 00167 BIO *out, *in; 00168 PKCS7 *p7; 00169 VALUE str; 00170 int flg; 00171 00172 rb_scan_args(argc, argv, "12", &pkcs7, &data, &flags); 00173 flg = NIL_P(flags) ? 0 : NUM2INT(flags); 00174 if(NIL_P(data)) data = ossl_pkcs7_get_data(pkcs7); 00175 SafeGetPKCS7(pkcs7, p7); 00176 if(!NIL_P(data) && PKCS7_is_detached(p7)) 00177 flg |= PKCS7_DETACHED; 00178 in = NIL_P(data) ? NULL : ossl_obj2bio(data); 00179 if(!(out = BIO_new(BIO_s_mem()))){ 00180 BIO_free(in); 00181 ossl_raise(ePKCS7Error, NULL); 00182 } 00183 if(!SMIME_write_PKCS7(out, p7, in, flg)){ 00184 BIO_free(out); 00185 BIO_free(in); 00186 ossl_raise(ePKCS7Error, NULL); 00187 } 00188 BIO_free(in); 00189 str = ossl_membio2str(out); 00190 00191 return str; 00192 } 00193 00194 /* 00195 * call-seq: 00196 * PKCS7.sign(cert, key, data, [, certs [, flags]]) => pkcs7 00197 */ 00198 static VALUE 00199 ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass) 00200 { 00201 VALUE cert, key, data, certs, flags; 00202 X509 *x509; 00203 EVP_PKEY *pkey; 00204 BIO *in; 00205 STACK_OF(X509) *x509s; 00206 int flg, status = 0; 00207 PKCS7 *pkcs7; 00208 VALUE ret; 00209 00210 rb_scan_args(argc, argv, "32", &cert, &key, &data, &certs, &flags); 00211 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ 00212 pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ 00213 flg = NIL_P(flags) ? 0 : NUM2INT(flags); 00214 in = ossl_obj2bio(data); 00215 if(NIL_P(certs)) x509s = NULL; 00216 else{ 00217 x509s = ossl_protect_x509_ary2sk(certs, &status); 00218 if(status){ 00219 BIO_free(in); 00220 rb_jump_tag(status); 00221 } 00222 } 00223 if(!(pkcs7 = PKCS7_sign(x509, pkey, x509s, in, flg))){ 00224 BIO_free(in); 00225 sk_X509_pop_free(x509s, X509_free); 00226 ossl_raise(ePKCS7Error, NULL); 00227 } 00228 WrapPKCS7(cPKCS7, ret, pkcs7); 00229 ossl_pkcs7_set_data(ret, data); 00230 ossl_pkcs7_set_err_string(ret, Qnil); 00231 BIO_free(in); 00232 sk_X509_pop_free(x509s, X509_free); 00233 00234 return ret; 00235 } 00236 00237 /* 00238 * call-seq: 00239 * PKCS7.encrypt(certs, data, [, cipher [, flags]]) => pkcs7 00240 */ 00241 static VALUE 00242 ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass) 00243 { 00244 VALUE certs, data, cipher, flags; 00245 STACK_OF(X509) *x509s; 00246 BIO *in; 00247 const EVP_CIPHER *ciph; 00248 int flg, status = 0; 00249 VALUE ret; 00250 PKCS7 *p7; 00251 00252 rb_scan_args(argc, argv, "22", &certs, &data, &cipher, &flags); 00253 if(NIL_P(cipher)){ 00254 #if !defined(OPENSSL_NO_RC2) 00255 ciph = EVP_rc2_40_cbc(); 00256 #elif !defined(OPENSSL_NO_DES) 00257 ciph = EVP_des_ede3_cbc(); 00258 #elif !defined(OPENSSL_NO_RC2) 00259 ciph = EVP_rc2_40_cbc(); 00260 #elif !defined(OPENSSL_NO_AES) 00261 ciph = EVP_EVP_aes_128_cbc(); 00262 #else 00263 ossl_raise(ePKCS7Error, "Must specify cipher"); 00264 #endif 00265 00266 } 00267 else ciph = GetCipherPtr(cipher); /* NO NEED TO DUP */ 00268 flg = NIL_P(flags) ? 0 : NUM2INT(flags); 00269 in = ossl_obj2bio(data); 00270 x509s = ossl_protect_x509_ary2sk(certs, &status); 00271 if(status){ 00272 BIO_free(in); 00273 rb_jump_tag(status); 00274 } 00275 if(!(p7 = PKCS7_encrypt(x509s, in, (EVP_CIPHER*)ciph, flg))){ 00276 BIO_free(in); 00277 sk_X509_pop_free(x509s, X509_free); 00278 ossl_raise(ePKCS7Error, NULL); 00279 } 00280 BIO_free(in); 00281 WrapPKCS7(cPKCS7, ret, p7); 00282 ossl_pkcs7_set_data(ret, data); 00283 sk_X509_pop_free(x509s, X509_free); 00284 00285 return ret; 00286 } 00287 00288 static VALUE 00289 ossl_pkcs7_alloc(VALUE klass) 00290 { 00291 PKCS7 *pkcs7; 00292 VALUE obj; 00293 00294 if (!(pkcs7 = PKCS7_new())) { 00295 ossl_raise(ePKCS7Error, NULL); 00296 } 00297 WrapPKCS7(klass, obj, pkcs7); 00298 00299 return obj; 00300 } 00301 00302 /* 00303 * call-seq: 00304 * PKCS7.new => pkcs7 00305 * PKCS7.new(string) => pkcs7 00306 * 00307 * Many methods in this class aren't documented. 00308 */ 00309 static VALUE 00310 ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self) 00311 { 00312 PKCS7 *p7, *pkcs = DATA_PTR(self); 00313 BIO *in; 00314 VALUE arg; 00315 00316 if(rb_scan_args(argc, argv, "01", &arg) == 0) 00317 return self; 00318 arg = ossl_to_der_if_possible(arg); 00319 in = ossl_obj2bio(arg); 00320 p7 = PEM_read_bio_PKCS7(in, &pkcs, NULL, NULL); 00321 if (!p7) { 00322 OSSL_BIO_reset(in); 00323 p7 = d2i_PKCS7_bio(in, &pkcs); 00324 if (!p7) { 00325 BIO_free(in); 00326 PKCS7_free(pkcs); 00327 DATA_PTR(self) = NULL; 00328 ossl_raise(rb_eArgError, "Could not parse the PKCS7"); 00329 } 00330 } 00331 DATA_PTR(self) = pkcs; 00332 BIO_free(in); 00333 ossl_pkcs7_set_data(self, Qnil); 00334 ossl_pkcs7_set_err_string(self, Qnil); 00335 00336 return self; 00337 } 00338 00339 static VALUE 00340 ossl_pkcs7_copy(VALUE self, VALUE other) 00341 { 00342 PKCS7 *a, *b, *pkcs7; 00343 00344 rb_check_frozen(self); 00345 if (self == other) return self; 00346 00347 GetPKCS7(self, a); 00348 SafeGetPKCS7(other, b); 00349 00350 pkcs7 = PKCS7_dup(b); 00351 if (!pkcs7) { 00352 ossl_raise(ePKCS7Error, NULL); 00353 } 00354 DATA_PTR(self) = pkcs7; 00355 PKCS7_free(a); 00356 00357 return self; 00358 } 00359 00360 static int 00361 ossl_pkcs7_sym2typeid(VALUE sym) 00362 { 00363 int i, ret = Qnil; 00364 const char *s; 00365 00366 static struct { 00367 const char *name; 00368 int nid; 00369 } p7_type_tab[] = { 00370 { "signed", NID_pkcs7_signed }, 00371 { "data", NID_pkcs7_data }, 00372 { "signedAndEnveloped", NID_pkcs7_signedAndEnveloped }, 00373 { "enveloped", NID_pkcs7_enveloped }, 00374 { "encrypted", NID_pkcs7_encrypted }, 00375 { "digest", NID_pkcs7_digest }, 00376 { NULL, 0 }, 00377 }; 00378 00379 if(TYPE(sym) == T_SYMBOL) s = rb_id2name(SYM2ID(sym)); 00380 else s = StringValuePtr(sym); 00381 for(i = 0; i < numberof(p7_type_tab); i++){ 00382 if(p7_type_tab[i].name == NULL) 00383 ossl_raise(ePKCS7Error, "unknown type \"%s\"", s); 00384 if(strcmp(p7_type_tab[i].name, s) == 0){ 00385 ret = p7_type_tab[i].nid; 00386 break; 00387 } 00388 } 00389 00390 return ret; 00391 } 00392 00393 /* 00394 * call-seq: 00395 * pkcs7.type = type => type 00396 */ 00397 static VALUE 00398 ossl_pkcs7_set_type(VALUE self, VALUE type) 00399 { 00400 PKCS7 *p7; 00401 00402 GetPKCS7(self, p7); 00403 if(!PKCS7_set_type(p7, ossl_pkcs7_sym2typeid(type))) 00404 ossl_raise(ePKCS7Error, NULL); 00405 00406 return type; 00407 } 00408 00409 /* 00410 * call-seq: 00411 * pkcs7.type => string or nil 00412 */ 00413 static VALUE 00414 ossl_pkcs7_get_type(VALUE self) 00415 { 00416 PKCS7 *p7; 00417 00418 GetPKCS7(self, p7); 00419 if(PKCS7_type_is_signed(p7)) 00420 return ID2SYM(rb_intern("signed")); 00421 if(PKCS7_type_is_encrypted(p7)) 00422 return ID2SYM(rb_intern("encrypted")); 00423 if(PKCS7_type_is_enveloped(p7)) 00424 return ID2SYM(rb_intern("enveloped")); 00425 if(PKCS7_type_is_signedAndEnveloped(p7)) 00426 return ID2SYM(rb_intern("signedAndEnveloped")); 00427 if(PKCS7_type_is_data(p7)) 00428 return ID2SYM(rb_intern("data")); 00429 return Qnil; 00430 } 00431 00432 static VALUE 00433 ossl_pkcs7_set_detached(VALUE self, VALUE flag) 00434 { 00435 PKCS7 *p7; 00436 00437 GetPKCS7(self, p7); 00438 if(flag != Qtrue && flag != Qfalse) 00439 ossl_raise(ePKCS7Error, "must specify a boolean"); 00440 if(!PKCS7_set_detached(p7, flag == Qtrue ? 1 : 0)) 00441 ossl_raise(ePKCS7Error, NULL); 00442 00443 return flag; 00444 } 00445 00446 static VALUE 00447 ossl_pkcs7_get_detached(VALUE self) 00448 { 00449 PKCS7 *p7; 00450 GetPKCS7(self, p7); 00451 return PKCS7_get_detached(p7) ? Qtrue : Qfalse; 00452 } 00453 00454 static VALUE 00455 ossl_pkcs7_detached_p(VALUE self) 00456 { 00457 PKCS7 *p7; 00458 GetPKCS7(self, p7); 00459 return PKCS7_is_detached(p7) ? Qtrue : Qfalse; 00460 } 00461 00462 static VALUE 00463 ossl_pkcs7_set_cipher(VALUE self, VALUE cipher) 00464 { 00465 PKCS7 *pkcs7; 00466 00467 GetPKCS7(self, pkcs7); 00468 if (!PKCS7_set_cipher(pkcs7, GetCipherPtr(cipher))) { 00469 ossl_raise(ePKCS7Error, NULL); 00470 } 00471 00472 return cipher; 00473 } 00474 00475 static VALUE 00476 ossl_pkcs7_add_signer(VALUE self, VALUE signer) 00477 { 00478 PKCS7 *pkcs7; 00479 PKCS7_SIGNER_INFO *p7si; 00480 00481 p7si = DupPKCS7SignerPtr(signer); /* NEED TO DUP */ 00482 GetPKCS7(self, pkcs7); 00483 if (!PKCS7_add_signer(pkcs7, p7si)) { 00484 PKCS7_SIGNER_INFO_free(p7si); 00485 ossl_raise(ePKCS7Error, "Could not add signer."); 00486 } 00487 if (PKCS7_type_is_signed(pkcs7)){ 00488 PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType, 00489 V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data)); 00490 } 00491 00492 return self; 00493 } 00494 00495 static VALUE 00496 ossl_pkcs7_get_signer(VALUE self) 00497 { 00498 PKCS7 *pkcs7; 00499 STACK_OF(PKCS7_SIGNER_INFO) *sk; 00500 PKCS7_SIGNER_INFO *si; 00501 int num, i; 00502 VALUE ary; 00503 00504 GetPKCS7(self, pkcs7); 00505 if (!(sk = PKCS7_get_signer_info(pkcs7))) { 00506 OSSL_Debug("OpenSSL::PKCS7#get_signer_info == NULL!"); 00507 return rb_ary_new(); 00508 } 00509 if ((num = sk_PKCS7_SIGNER_INFO_num(sk)) < 0) { 00510 ossl_raise(ePKCS7Error, "Negative number of signers!"); 00511 } 00512 ary = rb_ary_new2(num); 00513 for (i=0; i<num; i++) { 00514 si = sk_PKCS7_SIGNER_INFO_value(sk, i); 00515 rb_ary_push(ary, ossl_pkcs7si_new(si)); 00516 } 00517 00518 return ary; 00519 } 00520 00521 static VALUE 00522 ossl_pkcs7_add_recipient(VALUE self, VALUE recip) 00523 { 00524 PKCS7 *pkcs7; 00525 PKCS7_RECIP_INFO *ri; 00526 00527 ri = DupPKCS7RecipientPtr(recip); /* NEED TO DUP */ 00528 GetPKCS7(self, pkcs7); 00529 if (!PKCS7_add_recipient_info(pkcs7, ri)) { 00530 PKCS7_RECIP_INFO_free(ri); 00531 ossl_raise(ePKCS7Error, "Could not add recipient."); 00532 } 00533 00534 return self; 00535 } 00536 00537 static VALUE 00538 ossl_pkcs7_get_recipient(VALUE self) 00539 { 00540 PKCS7 *pkcs7; 00541 STACK_OF(PKCS7_RECIP_INFO) *sk; 00542 PKCS7_RECIP_INFO *si; 00543 int num, i; 00544 VALUE ary; 00545 00546 GetPKCS7(self, pkcs7); 00547 if (PKCS7_type_is_enveloped(pkcs7)) 00548 sk = pkcs7->d.enveloped->recipientinfo; 00549 else if (PKCS7_type_is_signedAndEnveloped(pkcs7)) 00550 sk = pkcs7->d.signed_and_enveloped->recipientinfo; 00551 else sk = NULL; 00552 if (!sk) return rb_ary_new(); 00553 if ((num = sk_PKCS7_RECIP_INFO_num(sk)) < 0) { 00554 ossl_raise(ePKCS7Error, "Negative number of recipient!"); 00555 } 00556 ary = rb_ary_new2(num); 00557 for (i=0; i<num; i++) { 00558 si = sk_PKCS7_RECIP_INFO_value(sk, i); 00559 rb_ary_push(ary, ossl_pkcs7ri_new(si)); 00560 } 00561 00562 return ary; 00563 } 00564 00565 static VALUE 00566 ossl_pkcs7_add_certificate(VALUE self, VALUE cert) 00567 { 00568 PKCS7 *pkcs7; 00569 X509 *x509; 00570 00571 GetPKCS7(self, pkcs7); 00572 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ 00573 if (!PKCS7_add_certificate(pkcs7, x509)){ 00574 ossl_raise(ePKCS7Error, NULL); 00575 } 00576 00577 return self; 00578 } 00579 00580 static STACK_OF(X509) * 00581 pkcs7_get_certs(VALUE self) 00582 { 00583 PKCS7 *pkcs7; 00584 STACK_OF(X509) *certs; 00585 int i; 00586 00587 GetPKCS7(self, pkcs7); 00588 i = OBJ_obj2nid(pkcs7->type); 00589 switch(i){ 00590 case NID_pkcs7_signed: 00591 certs = pkcs7->d.sign->cert; 00592 break; 00593 case NID_pkcs7_signedAndEnveloped: 00594 certs = pkcs7->d.signed_and_enveloped->cert; 00595 break; 00596 default: 00597 certs = NULL; 00598 } 00599 00600 return certs; 00601 } 00602 00603 static STACK_OF(X509_CRL) * 00604 pkcs7_get_crls(VALUE self) 00605 { 00606 PKCS7 *pkcs7; 00607 STACK_OF(X509_CRL) *crls; 00608 int i; 00609 00610 GetPKCS7(self, pkcs7); 00611 i = OBJ_obj2nid(pkcs7->type); 00612 switch(i){ 00613 case NID_pkcs7_signed: 00614 crls = pkcs7->d.sign->crl; 00615 break; 00616 case NID_pkcs7_signedAndEnveloped: 00617 crls = pkcs7->d.signed_and_enveloped->crl; 00618 break; 00619 default: 00620 crls = NULL; 00621 } 00622 00623 return crls; 00624 } 00625 00626 static VALUE 00627 ossl_pkcs7_set_certs_i(VALUE i, VALUE arg) 00628 { 00629 return ossl_pkcs7_add_certificate(arg, i); 00630 } 00631 00632 static VALUE 00633 ossl_pkcs7_set_certificates(VALUE self, VALUE ary) 00634 { 00635 STACK_OF(X509) *certs; 00636 X509 *cert; 00637 00638 certs = pkcs7_get_certs(self); 00639 while((cert = sk_X509_pop(certs))) X509_free(cert); 00640 rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_certs_i, self); 00641 00642 return ary; 00643 } 00644 00645 static VALUE 00646 ossl_pkcs7_get_certificates(VALUE self) 00647 { 00648 return ossl_x509_sk2ary(pkcs7_get_certs(self)); 00649 } 00650 00651 static VALUE 00652 ossl_pkcs7_add_crl(VALUE self, VALUE crl) 00653 { 00654 PKCS7 *pkcs7; 00655 X509_CRL *x509crl; 00656 00657 GetPKCS7(self, pkcs7); /* NO DUP needed! */ 00658 x509crl = GetX509CRLPtr(crl); 00659 if (!PKCS7_add_crl(pkcs7, x509crl)) { 00660 ossl_raise(ePKCS7Error, NULL); 00661 } 00662 00663 return self; 00664 } 00665 00666 static VALUE 00667 ossl_pkcs7_set_crls_i(VALUE i, VALUE arg) 00668 { 00669 return ossl_pkcs7_add_crl(arg, i); 00670 } 00671 00672 static VALUE 00673 ossl_pkcs7_set_crls(VALUE self, VALUE ary) 00674 { 00675 STACK_OF(X509_CRL) *crls; 00676 X509_CRL *crl; 00677 00678 crls = pkcs7_get_crls(self); 00679 while((crl = sk_X509_CRL_pop(crls))) X509_CRL_free(crl); 00680 rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_crls_i, self); 00681 00682 return ary; 00683 } 00684 00685 static VALUE 00686 ossl_pkcs7_get_crls(VALUE self) 00687 { 00688 return ossl_x509crl_sk2ary(pkcs7_get_crls(self)); 00689 } 00690 00691 static VALUE 00692 ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self) 00693 { 00694 VALUE certs, store, indata, flags; 00695 STACK_OF(X509) *x509s; 00696 X509_STORE *x509st; 00697 int flg, ok, status = 0; 00698 BIO *in, *out; 00699 PKCS7 *p7; 00700 VALUE data; 00701 const char *msg; 00702 00703 rb_scan_args(argc, argv, "22", &certs, &store, &indata, &flags); 00704 flg = NIL_P(flags) ? 0 : NUM2INT(flags); 00705 if(NIL_P(indata)) indata = ossl_pkcs7_get_data(self); 00706 in = NIL_P(indata) ? NULL : ossl_obj2bio(indata); 00707 if(NIL_P(certs)) x509s = NULL; 00708 else{ 00709 x509s = ossl_protect_x509_ary2sk(certs, &status); 00710 if(status){ 00711 BIO_free(in); 00712 rb_jump_tag(status); 00713 } 00714 } 00715 x509st = GetX509StorePtr(store); 00716 GetPKCS7(self, p7); 00717 if(!(out = BIO_new(BIO_s_mem()))){ 00718 BIO_free(in); 00719 sk_X509_pop_free(x509s, X509_free); 00720 ossl_raise(ePKCS7Error, NULL); 00721 } 00722 ok = PKCS7_verify(p7, x509s, x509st, in, out, flg); 00723 BIO_free(in); 00724 if (ok < 0) ossl_raise(ePKCS7Error, NULL); 00725 msg = ERR_reason_error_string(ERR_get_error()); 00726 ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil); 00727 ERR_clear_error(); 00728 data = ossl_membio2str(out); 00729 ossl_pkcs7_set_data(self, data); 00730 sk_X509_pop_free(x509s, X509_free); 00731 00732 return (ok == 1) ? Qtrue : Qfalse; 00733 } 00734 00735 static VALUE 00736 ossl_pkcs7_decrypt(int argc, VALUE *argv, VALUE self) 00737 { 00738 VALUE pkey, cert, flags; 00739 EVP_PKEY *key; 00740 X509 *x509; 00741 int flg; 00742 PKCS7 *p7; 00743 BIO *out; 00744 VALUE str; 00745 00746 rb_scan_args(argc, argv, "21", &pkey, &cert, &flags); 00747 key = GetPrivPKeyPtr(pkey); /* NO NEED TO DUP */ 00748 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ 00749 flg = NIL_P(flags) ? 0 : NUM2INT(flags); 00750 GetPKCS7(self, p7); 00751 if(!(out = BIO_new(BIO_s_mem()))) 00752 ossl_raise(ePKCS7Error, NULL); 00753 if(!PKCS7_decrypt(p7, key, x509, out, flg)){ 00754 BIO_free(out); 00755 ossl_raise(ePKCS7Error, NULL); 00756 } 00757 str = ossl_membio2str(out); /* out will be free */ 00758 00759 return str; 00760 } 00761 00762 static VALUE 00763 ossl_pkcs7_add_data(VALUE self, VALUE data) 00764 { 00765 PKCS7 *pkcs7; 00766 BIO *out, *in; 00767 char buf[4096]; 00768 int len; 00769 00770 in = ossl_obj2bio(data); 00771 GetPKCS7(self, pkcs7); 00772 if(PKCS7_type_is_signed(pkcs7)){ 00773 if(!PKCS7_content_new(pkcs7, NID_pkcs7_data)) 00774 ossl_raise(ePKCS7Error, NULL); 00775 } 00776 if(!(out = PKCS7_dataInit(pkcs7, NULL))) goto err; 00777 for(;;){ 00778 if((len = BIO_read(in, buf, sizeof(buf))) <= 0) 00779 break; 00780 if(BIO_write(out, buf, len) != len) 00781 goto err; 00782 } 00783 if(!PKCS7_dataFinal(pkcs7, out)) goto err; 00784 ossl_pkcs7_set_data(self, Qnil); 00785 00786 err: 00787 BIO_free(out); 00788 BIO_free(in); 00789 if(ERR_peek_error()){ 00790 ossl_raise(ePKCS7Error, NULL); 00791 } 00792 00793 return data; 00794 } 00795 00796 static VALUE 00797 ossl_pkcs7_to_der(VALUE self) 00798 { 00799 PKCS7 *pkcs7; 00800 VALUE str; 00801 long len; 00802 unsigned char *p; 00803 00804 GetPKCS7(self, pkcs7); 00805 if((len = i2d_PKCS7(pkcs7, NULL)) <= 0) 00806 ossl_raise(ePKCS7Error, NULL); 00807 str = rb_str_new(0, len); 00808 p = (unsigned char *)RSTRING_PTR(str); 00809 if(i2d_PKCS7(pkcs7, &p) <= 0) 00810 ossl_raise(ePKCS7Error, NULL); 00811 ossl_str_adjust(str, p); 00812 00813 return str; 00814 } 00815 00816 static VALUE 00817 ossl_pkcs7_to_pem(VALUE self) 00818 { 00819 PKCS7 *pkcs7; 00820 BIO *out; 00821 VALUE str; 00822 00823 GetPKCS7(self, pkcs7); 00824 if (!(out = BIO_new(BIO_s_mem()))) { 00825 ossl_raise(ePKCS7Error, NULL); 00826 } 00827 if (!PEM_write_bio_PKCS7(out, pkcs7)) { 00828 BIO_free(out); 00829 ossl_raise(ePKCS7Error, NULL); 00830 } 00831 str = ossl_membio2str(out); 00832 00833 return str; 00834 } 00835 00836 /* 00837 * SIGNER INFO 00838 */ 00839 static VALUE 00840 ossl_pkcs7si_alloc(VALUE klass) 00841 { 00842 PKCS7_SIGNER_INFO *p7si; 00843 VALUE obj; 00844 00845 if (!(p7si = PKCS7_SIGNER_INFO_new())) { 00846 ossl_raise(ePKCS7Error, NULL); 00847 } 00848 WrapPKCS7si(klass, obj, p7si); 00849 00850 return obj; 00851 } 00852 00853 static VALUE 00854 ossl_pkcs7si_initialize(VALUE self, VALUE cert, VALUE key, VALUE digest) 00855 { 00856 PKCS7_SIGNER_INFO *p7si; 00857 EVP_PKEY *pkey; 00858 X509 *x509; 00859 const EVP_MD *md; 00860 00861 pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ 00862 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ 00863 md = GetDigestPtr(digest); 00864 GetPKCS7si(self, p7si); 00865 if (!(PKCS7_SIGNER_INFO_set(p7si, x509, pkey, (EVP_MD*)md))) { 00866 ossl_raise(ePKCS7Error, NULL); 00867 } 00868 00869 return self; 00870 } 00871 00872 static VALUE 00873 ossl_pkcs7si_get_issuer(VALUE self) 00874 { 00875 PKCS7_SIGNER_INFO *p7si; 00876 00877 GetPKCS7si(self, p7si); 00878 00879 return ossl_x509name_new(p7si->issuer_and_serial->issuer); 00880 } 00881 00882 static VALUE 00883 ossl_pkcs7si_get_serial(VALUE self) 00884 { 00885 PKCS7_SIGNER_INFO *p7si; 00886 00887 GetPKCS7si(self, p7si); 00888 00889 return asn1integer_to_num(p7si->issuer_and_serial->serial); 00890 } 00891 00892 static VALUE 00893 ossl_pkcs7si_get_signed_time(VALUE self) 00894 { 00895 PKCS7_SIGNER_INFO *p7si; 00896 ASN1_TYPE *asn1obj; 00897 00898 GetPKCS7si(self, p7si); 00899 00900 if (!(asn1obj = PKCS7_get_signed_attribute(p7si, NID_pkcs9_signingTime))) { 00901 ossl_raise(ePKCS7Error, NULL); 00902 } 00903 if (asn1obj->type == V_ASN1_UTCTIME) { 00904 return asn1time_to_time(asn1obj->value.utctime); 00905 } 00906 /* 00907 * OR 00908 * ossl_raise(ePKCS7Error, "..."); 00909 * ? 00910 */ 00911 00912 return Qnil; 00913 } 00914 00915 /* 00916 * RECIPIENT INFO 00917 */ 00918 static VALUE 00919 ossl_pkcs7ri_alloc(VALUE klass) 00920 { 00921 PKCS7_RECIP_INFO *p7ri; 00922 VALUE obj; 00923 00924 if (!(p7ri = PKCS7_RECIP_INFO_new())) { 00925 ossl_raise(ePKCS7Error, NULL); 00926 } 00927 WrapPKCS7ri(klass, obj, p7ri); 00928 00929 return obj; 00930 } 00931 00932 static VALUE 00933 ossl_pkcs7ri_initialize(VALUE self, VALUE cert) 00934 { 00935 PKCS7_RECIP_INFO *p7ri; 00936 X509 *x509; 00937 00938 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ 00939 GetPKCS7ri(self, p7ri); 00940 if (!PKCS7_RECIP_INFO_set(p7ri, x509)) { 00941 ossl_raise(ePKCS7Error, NULL); 00942 } 00943 00944 return self; 00945 } 00946 00947 static VALUE 00948 ossl_pkcs7ri_get_issuer(VALUE self) 00949 { 00950 PKCS7_RECIP_INFO *p7ri; 00951 00952 GetPKCS7ri(self, p7ri); 00953 00954 return ossl_x509name_new(p7ri->issuer_and_serial->issuer); 00955 } 00956 00957 static VALUE 00958 ossl_pkcs7ri_get_serial(VALUE self) 00959 { 00960 PKCS7_RECIP_INFO *p7ri; 00961 00962 GetPKCS7ri(self, p7ri); 00963 00964 return asn1integer_to_num(p7ri->issuer_and_serial->serial); 00965 } 00966 00967 static VALUE 00968 ossl_pkcs7ri_get_enc_key(VALUE self) 00969 { 00970 PKCS7_RECIP_INFO *p7ri; 00971 00972 GetPKCS7ri(self, p7ri); 00973 00974 return asn1str_to_str(p7ri->enc_key); 00975 } 00976 00977 /* 00978 * INIT 00979 */ 00980 void 00981 Init_ossl_pkcs7() 00982 { 00983 cPKCS7 = rb_define_class_under(mOSSL, "PKCS7", rb_cObject); 00984 ePKCS7Error = rb_define_class_under(cPKCS7, "PKCS7Error", eOSSLError); 00985 rb_define_singleton_method(cPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1); 00986 rb_define_singleton_method(cPKCS7, "write_smime", ossl_pkcs7_s_write_smime, -1); 00987 rb_define_singleton_method(cPKCS7, "sign", ossl_pkcs7_s_sign, -1); 00988 rb_define_singleton_method(cPKCS7, "encrypt", ossl_pkcs7_s_encrypt, -1); 00989 rb_attr(cPKCS7, rb_intern("data"), 1, 0, Qfalse); 00990 rb_attr(cPKCS7, rb_intern("error_string"), 1, 1, Qfalse); 00991 rb_define_alloc_func(cPKCS7, ossl_pkcs7_alloc); 00992 rb_define_copy_func(cPKCS7, ossl_pkcs7_copy); 00993 rb_define_method(cPKCS7, "initialize", ossl_pkcs7_initialize, -1); 00994 rb_define_method(cPKCS7, "type=", ossl_pkcs7_set_type, 1); 00995 rb_define_method(cPKCS7, "type", ossl_pkcs7_get_type, 0); 00996 rb_define_method(cPKCS7, "detached=", ossl_pkcs7_set_detached, 1); 00997 rb_define_method(cPKCS7, "detached", ossl_pkcs7_get_detached, 0); 00998 rb_define_method(cPKCS7, "detached?", ossl_pkcs7_detached_p, 0); 00999 rb_define_method(cPKCS7, "cipher=", ossl_pkcs7_set_cipher, 1); 01000 rb_define_method(cPKCS7, "add_signer", ossl_pkcs7_add_signer, 1); 01001 rb_define_method(cPKCS7, "signers", ossl_pkcs7_get_signer, 0); 01002 rb_define_method(cPKCS7, "add_recipient", ossl_pkcs7_add_recipient, 1); 01003 rb_define_method(cPKCS7, "recipients", ossl_pkcs7_get_recipient, 0); 01004 rb_define_method(cPKCS7, "add_certificate", ossl_pkcs7_add_certificate, 1); 01005 rb_define_method(cPKCS7, "certificates=", ossl_pkcs7_set_certificates, 1); 01006 rb_define_method(cPKCS7, "certificates", ossl_pkcs7_get_certificates, 0); 01007 rb_define_method(cPKCS7, "add_crl", ossl_pkcs7_add_crl, 1); 01008 rb_define_method(cPKCS7, "crls=", ossl_pkcs7_set_crls, 1); 01009 rb_define_method(cPKCS7, "crls", ossl_pkcs7_get_crls, 0); 01010 rb_define_method(cPKCS7, "add_data", ossl_pkcs7_add_data, 1); 01011 rb_define_alias(cPKCS7, "data=", "add_data"); 01012 rb_define_method(cPKCS7, "verify", ossl_pkcs7_verify, -1); 01013 rb_define_method(cPKCS7, "decrypt", ossl_pkcs7_decrypt, -1); 01014 rb_define_method(cPKCS7, "to_pem", ossl_pkcs7_to_pem, 0); 01015 rb_define_alias(cPKCS7, "to_s", "to_pem"); 01016 rb_define_method(cPKCS7, "to_der", ossl_pkcs7_to_der, 0); 01017 01018 cPKCS7Signer = rb_define_class_under(cPKCS7, "SignerInfo", rb_cObject); 01019 rb_define_const(cPKCS7, "Signer", cPKCS7Signer); 01020 rb_define_alloc_func(cPKCS7Signer, ossl_pkcs7si_alloc); 01021 rb_define_method(cPKCS7Signer, "initialize", ossl_pkcs7si_initialize,3); 01022 rb_define_method(cPKCS7Signer, "issuer", ossl_pkcs7si_get_issuer, 0); 01023 rb_define_alias(cPKCS7Signer, "name", "issuer"); 01024 rb_define_method(cPKCS7Signer, "serial", ossl_pkcs7si_get_serial,0); 01025 rb_define_method(cPKCS7Signer,"signed_time",ossl_pkcs7si_get_signed_time,0); 01026 01027 cPKCS7Recipient = rb_define_class_under(cPKCS7,"RecipientInfo",rb_cObject); 01028 rb_define_alloc_func(cPKCS7Recipient, ossl_pkcs7ri_alloc); 01029 rb_define_method(cPKCS7Recipient, "initialize", ossl_pkcs7ri_initialize,1); 01030 rb_define_method(cPKCS7Recipient, "issuer", ossl_pkcs7ri_get_issuer,0); 01031 rb_define_method(cPKCS7Recipient, "serial", ossl_pkcs7ri_get_serial,0); 01032 rb_define_method(cPKCS7Recipient, "enc_key", ossl_pkcs7ri_get_enc_key,0); 01033 01034 #define DefPKCS7Const(x) rb_define_const(cPKCS7, #x, INT2NUM(PKCS7_##x)) 01035 01036 DefPKCS7Const(TEXT); 01037 DefPKCS7Const(NOCERTS); 01038 DefPKCS7Const(NOSIGS); 01039 DefPKCS7Const(NOCHAIN); 01040 DefPKCS7Const(NOINTERN); 01041 DefPKCS7Const(NOVERIFY); 01042 DefPKCS7Const(DETACHED); 01043 DefPKCS7Const(BINARY); 01044 DefPKCS7Const(NOATTR); 01045 DefPKCS7Const(NOSMIMECAP); 01046 } 01047