|
Ruby 1.9.2p290(2011-07-09revision32553)
|
00001 /* 00002 * $Id: ossl_pkcs7.c 27440 2010-04-22 08:21:01Z nobu $ 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) (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 DATA_PTR(self) = pkcs; 00322 if (!p7) { 00323 (void)BIO_reset(in); 00324 p7 = d2i_PKCS7_bio(in, &pkcs); 00325 DATA_PTR(self) = pkcs; 00326 } 00327 BIO_free(in); 00328 ossl_pkcs7_set_data(self, Qnil); 00329 ossl_pkcs7_set_err_string(self, Qnil); 00330 00331 return self; 00332 } 00333 00334 static VALUE 00335 ossl_pkcs7_copy(VALUE self, VALUE other) 00336 { 00337 PKCS7 *a, *b, *pkcs7; 00338 00339 rb_check_frozen(self); 00340 if (self == other) return self; 00341 00342 GetPKCS7(self, a); 00343 SafeGetPKCS7(other, b); 00344 00345 pkcs7 = PKCS7_dup(b); 00346 if (!pkcs7) { 00347 ossl_raise(ePKCS7Error, NULL); 00348 } 00349 DATA_PTR(self) = pkcs7; 00350 PKCS7_free(a); 00351 00352 return self; 00353 } 00354 00355 static int 00356 ossl_pkcs7_sym2typeid(VALUE sym) 00357 { 00358 int i, ret = Qnil; 00359 const char *s; 00360 00361 static struct { 00362 const char *name; 00363 int nid; 00364 } p7_type_tab[] = { 00365 { "signed", NID_pkcs7_signed }, 00366 { "data", NID_pkcs7_data }, 00367 { "signedAndEnveloped", NID_pkcs7_signedAndEnveloped }, 00368 { "enveloped", NID_pkcs7_enveloped }, 00369 { "encrypted", NID_pkcs7_encrypted }, 00370 { "digest", NID_pkcs7_digest }, 00371 { NULL, 0 }, 00372 }; 00373 00374 if(TYPE(sym) == T_SYMBOL) s = rb_id2name(SYM2ID(sym)); 00375 else s = StringValuePtr(sym); 00376 for(i = 0; i < numberof(p7_type_tab); i++){ 00377 if(p7_type_tab[i].name == NULL) 00378 ossl_raise(ePKCS7Error, "unknown type \"%s\"", s); 00379 if(strcmp(p7_type_tab[i].name, s) == 0){ 00380 ret = p7_type_tab[i].nid; 00381 break; 00382 } 00383 } 00384 00385 return ret; 00386 } 00387 00388 /* 00389 * call-seq: 00390 * pkcs7.type = type => type 00391 */ 00392 static VALUE 00393 ossl_pkcs7_set_type(VALUE self, VALUE type) 00394 { 00395 PKCS7 *p7; 00396 00397 GetPKCS7(self, p7); 00398 if(!PKCS7_set_type(p7, ossl_pkcs7_sym2typeid(type))) 00399 ossl_raise(ePKCS7Error, NULL); 00400 00401 return type; 00402 } 00403 00404 /* 00405 * call-seq: 00406 * pkcs7.type => string or nil 00407 */ 00408 static VALUE 00409 ossl_pkcs7_get_type(VALUE self) 00410 { 00411 PKCS7 *p7; 00412 00413 GetPKCS7(self, p7); 00414 if(PKCS7_type_is_signed(p7)) 00415 return ID2SYM(rb_intern("signed")); 00416 if(PKCS7_type_is_encrypted(p7)) 00417 return ID2SYM(rb_intern("encrypted")); 00418 if(PKCS7_type_is_enveloped(p7)) 00419 return ID2SYM(rb_intern("enveloped")); 00420 if(PKCS7_type_is_signedAndEnveloped(p7)) 00421 return ID2SYM(rb_intern("signedAndEnveloped")); 00422 if(PKCS7_type_is_data(p7)) 00423 return ID2SYM(rb_intern("data")); 00424 return Qnil; 00425 } 00426 00427 static VALUE 00428 ossl_pkcs7_set_detached(VALUE self, VALUE flag) 00429 { 00430 PKCS7 *p7; 00431 00432 GetPKCS7(self, p7); 00433 if(flag != Qtrue && flag != Qfalse) 00434 ossl_raise(ePKCS7Error, "must specify a boolean"); 00435 if(!PKCS7_set_detached(p7, flag == Qtrue ? 1 : 0)) 00436 ossl_raise(ePKCS7Error, NULL); 00437 00438 return flag; 00439 } 00440 00441 static VALUE 00442 ossl_pkcs7_get_detached(VALUE self) 00443 { 00444 PKCS7 *p7; 00445 GetPKCS7(self, p7); 00446 return PKCS7_get_detached(p7) ? Qtrue : Qfalse; 00447 } 00448 00449 static VALUE 00450 ossl_pkcs7_detached_p(VALUE self) 00451 { 00452 PKCS7 *p7; 00453 GetPKCS7(self, p7); 00454 return PKCS7_is_detached(p7) ? Qtrue : Qfalse; 00455 } 00456 00457 static VALUE 00458 ossl_pkcs7_set_cipher(VALUE self, VALUE cipher) 00459 { 00460 PKCS7 *pkcs7; 00461 00462 GetPKCS7(self, pkcs7); 00463 if (!PKCS7_set_cipher(pkcs7, GetCipherPtr(cipher))) { 00464 ossl_raise(ePKCS7Error, NULL); 00465 } 00466 00467 return cipher; 00468 } 00469 00470 static VALUE 00471 ossl_pkcs7_add_signer(VALUE self, VALUE signer) 00472 { 00473 PKCS7 *pkcs7; 00474 PKCS7_SIGNER_INFO *p7si; 00475 00476 p7si = DupPKCS7SignerPtr(signer); /* NEED TO DUP */ 00477 GetPKCS7(self, pkcs7); 00478 if (!PKCS7_add_signer(pkcs7, p7si)) { 00479 PKCS7_SIGNER_INFO_free(p7si); 00480 ossl_raise(ePKCS7Error, "Could not add signer."); 00481 } 00482 if (PKCS7_type_is_signed(pkcs7)){ 00483 PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType, 00484 V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data)); 00485 } 00486 00487 return self; 00488 } 00489 00490 static VALUE 00491 ossl_pkcs7_get_signer(VALUE self) 00492 { 00493 PKCS7 *pkcs7; 00494 STACK_OF(PKCS7_SIGNER_INFO) *sk; 00495 PKCS7_SIGNER_INFO *si; 00496 int num, i; 00497 VALUE ary; 00498 00499 GetPKCS7(self, pkcs7); 00500 if (!(sk = PKCS7_get_signer_info(pkcs7))) { 00501 OSSL_Debug("OpenSSL::PKCS7#get_signer_info == NULL!"); 00502 return rb_ary_new(); 00503 } 00504 if ((num = sk_PKCS7_SIGNER_INFO_num(sk)) < 0) { 00505 ossl_raise(ePKCS7Error, "Negative number of signers!"); 00506 } 00507 ary = rb_ary_new2(num); 00508 for (i=0; i<num; i++) { 00509 si = sk_PKCS7_SIGNER_INFO_value(sk, i); 00510 rb_ary_push(ary, ossl_pkcs7si_new(si)); 00511 } 00512 00513 return ary; 00514 } 00515 00516 static VALUE 00517 ossl_pkcs7_add_recipient(VALUE self, VALUE recip) 00518 { 00519 PKCS7 *pkcs7; 00520 PKCS7_RECIP_INFO *ri; 00521 00522 ri = DupPKCS7RecipientPtr(recip); /* NEED TO DUP */ 00523 GetPKCS7(self, pkcs7); 00524 if (!PKCS7_add_recipient_info(pkcs7, ri)) { 00525 PKCS7_RECIP_INFO_free(ri); 00526 ossl_raise(ePKCS7Error, "Could not add recipient."); 00527 } 00528 00529 return self; 00530 } 00531 00532 static VALUE 00533 ossl_pkcs7_get_recipient(VALUE self) 00534 { 00535 PKCS7 *pkcs7; 00536 STACK_OF(PKCS7_RECIP_INFO) *sk; 00537 PKCS7_RECIP_INFO *si; 00538 int num, i; 00539 VALUE ary; 00540 00541 GetPKCS7(self, pkcs7); 00542 if (PKCS7_type_is_enveloped(pkcs7)) 00543 sk = pkcs7->d.enveloped->recipientinfo; 00544 else if (PKCS7_type_is_signedAndEnveloped(pkcs7)) 00545 sk = pkcs7->d.signed_and_enveloped->recipientinfo; 00546 else sk = NULL; 00547 if (!sk) return rb_ary_new(); 00548 if ((num = sk_PKCS7_RECIP_INFO_num(sk)) < 0) { 00549 ossl_raise(ePKCS7Error, "Negative number of recipient!"); 00550 } 00551 ary = rb_ary_new2(num); 00552 for (i=0; i<num; i++) { 00553 si = sk_PKCS7_RECIP_INFO_value(sk, i); 00554 rb_ary_push(ary, ossl_pkcs7ri_new(si)); 00555 } 00556 00557 return ary; 00558 } 00559 00560 static VALUE 00561 ossl_pkcs7_add_certificate(VALUE self, VALUE cert) 00562 { 00563 PKCS7 *pkcs7; 00564 X509 *x509; 00565 00566 GetPKCS7(self, pkcs7); 00567 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ 00568 if (!PKCS7_add_certificate(pkcs7, x509)){ 00569 ossl_raise(ePKCS7Error, NULL); 00570 } 00571 00572 return self; 00573 } 00574 00575 static STACK_OF(X509) * 00576 pkcs7_get_certs(VALUE self) 00577 { 00578 PKCS7 *pkcs7; 00579 STACK_OF(X509) *certs; 00580 int i; 00581 00582 GetPKCS7(self, pkcs7); 00583 i = OBJ_obj2nid(pkcs7->type); 00584 switch(i){ 00585 case NID_pkcs7_signed: 00586 certs = pkcs7->d.sign->cert; 00587 break; 00588 case NID_pkcs7_signedAndEnveloped: 00589 certs = pkcs7->d.signed_and_enveloped->cert; 00590 break; 00591 default: 00592 certs = NULL; 00593 } 00594 00595 return certs; 00596 } 00597 00598 static STACK_OF(X509_CRL) * 00599 pkcs7_get_crls(VALUE self) 00600 { 00601 PKCS7 *pkcs7; 00602 STACK_OF(X509_CRL) *crls; 00603 int i; 00604 00605 GetPKCS7(self, pkcs7); 00606 i = OBJ_obj2nid(pkcs7->type); 00607 switch(i){ 00608 case NID_pkcs7_signed: 00609 crls = pkcs7->d.sign->crl; 00610 break; 00611 case NID_pkcs7_signedAndEnveloped: 00612 crls = pkcs7->d.signed_and_enveloped->crl; 00613 break; 00614 default: 00615 crls = NULL; 00616 } 00617 00618 return crls; 00619 } 00620 00621 static VALUE 00622 ossl_pkcs7_set_certs_i(VALUE i, VALUE arg) 00623 { 00624 return ossl_pkcs7_add_certificate(arg, i); 00625 } 00626 00627 static VALUE 00628 ossl_pkcs7_set_certificates(VALUE self, VALUE ary) 00629 { 00630 STACK_OF(X509) *certs; 00631 X509 *cert; 00632 00633 certs = pkcs7_get_certs(self); 00634 while((cert = sk_X509_pop(certs))) X509_free(cert); 00635 rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_certs_i, self); 00636 00637 return ary; 00638 } 00639 00640 static VALUE 00641 ossl_pkcs7_get_certificates(VALUE self) 00642 { 00643 return ossl_x509_sk2ary(pkcs7_get_certs(self)); 00644 } 00645 00646 static VALUE 00647 ossl_pkcs7_add_crl(VALUE self, VALUE crl) 00648 { 00649 PKCS7 *pkcs7; 00650 X509_CRL *x509crl; 00651 00652 GetPKCS7(self, pkcs7); /* NO DUP needed! */ 00653 x509crl = GetX509CRLPtr(crl); 00654 if (!PKCS7_add_crl(pkcs7, x509crl)) { 00655 ossl_raise(ePKCS7Error, NULL); 00656 } 00657 00658 return self; 00659 } 00660 00661 static VALUE 00662 ossl_pkcs7_set_crls_i(VALUE i, VALUE arg) 00663 { 00664 return ossl_pkcs7_add_crl(arg, i); 00665 } 00666 00667 static VALUE 00668 ossl_pkcs7_set_crls(VALUE self, VALUE ary) 00669 { 00670 STACK_OF(X509_CRL) *crls; 00671 X509_CRL *crl; 00672 00673 crls = pkcs7_get_crls(self); 00674 while((crl = sk_X509_CRL_pop(crls))) X509_CRL_free(crl); 00675 rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_crls_i, self); 00676 00677 return ary; 00678 } 00679 00680 static VALUE 00681 ossl_pkcs7_get_crls(VALUE self) 00682 { 00683 return ossl_x509crl_sk2ary(pkcs7_get_crls(self)); 00684 } 00685 00686 static VALUE 00687 ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self) 00688 { 00689 VALUE certs, store, indata, flags; 00690 STACK_OF(X509) *x509s; 00691 X509_STORE *x509st; 00692 int flg, ok, status = 0; 00693 BIO *in, *out; 00694 PKCS7 *p7; 00695 VALUE data; 00696 const char *msg; 00697 00698 rb_scan_args(argc, argv, "22", &certs, &store, &indata, &flags); 00699 flg = NIL_P(flags) ? 0 : NUM2INT(flags); 00700 if(NIL_P(indata)) indata = ossl_pkcs7_get_data(self); 00701 in = NIL_P(indata) ? NULL : ossl_obj2bio(indata); 00702 if(NIL_P(certs)) x509s = NULL; 00703 else{ 00704 x509s = ossl_protect_x509_ary2sk(certs, &status); 00705 if(status){ 00706 BIO_free(in); 00707 rb_jump_tag(status); 00708 } 00709 } 00710 x509st = GetX509StorePtr(store); 00711 GetPKCS7(self, p7); 00712 if(!(out = BIO_new(BIO_s_mem()))){ 00713 BIO_free(in); 00714 sk_X509_pop_free(x509s, X509_free); 00715 ossl_raise(ePKCS7Error, NULL); 00716 } 00717 ok = PKCS7_verify(p7, x509s, x509st, in, out, flg); 00718 BIO_free(in); 00719 if (ok < 0) ossl_raise(ePKCS7Error, NULL); 00720 msg = ERR_reason_error_string(ERR_get_error()); 00721 ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil); 00722 ERR_clear_error(); 00723 data = ossl_membio2str(out); 00724 ossl_pkcs7_set_data(self, data); 00725 sk_X509_pop_free(x509s, X509_free); 00726 00727 return (ok == 1) ? Qtrue : Qfalse; 00728 } 00729 00730 static VALUE 00731 ossl_pkcs7_decrypt(int argc, VALUE *argv, VALUE self) 00732 { 00733 VALUE pkey, cert, flags; 00734 EVP_PKEY *key; 00735 X509 *x509; 00736 int flg; 00737 PKCS7 *p7; 00738 BIO *out; 00739 VALUE str; 00740 00741 rb_scan_args(argc, argv, "21", &pkey, &cert, &flags); 00742 key = GetPrivPKeyPtr(pkey); /* NO NEED TO DUP */ 00743 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ 00744 flg = NIL_P(flags) ? 0 : NUM2INT(flags); 00745 GetPKCS7(self, p7); 00746 if(!(out = BIO_new(BIO_s_mem()))) 00747 ossl_raise(ePKCS7Error, NULL); 00748 if(!PKCS7_decrypt(p7, key, x509, out, flg)){ 00749 BIO_free(out); 00750 ossl_raise(ePKCS7Error, NULL); 00751 } 00752 str = ossl_membio2str(out); /* out will be free */ 00753 00754 return str; 00755 } 00756 00757 static VALUE 00758 ossl_pkcs7_add_data(VALUE self, VALUE data) 00759 { 00760 PKCS7 *pkcs7; 00761 BIO *out, *in; 00762 char buf[4096]; 00763 int len; 00764 00765 in = ossl_obj2bio(data); 00766 GetPKCS7(self, pkcs7); 00767 if(PKCS7_type_is_signed(pkcs7)){ 00768 if(!PKCS7_content_new(pkcs7, NID_pkcs7_data)) 00769 ossl_raise(ePKCS7Error, NULL); 00770 } 00771 if(!(out = PKCS7_dataInit(pkcs7, NULL))) goto err; 00772 for(;;){ 00773 if((len = BIO_read(in, buf, sizeof(buf))) <= 0) 00774 break; 00775 if(BIO_write(out, buf, len) != len) 00776 goto err; 00777 } 00778 if(!PKCS7_dataFinal(pkcs7, out)) goto err; 00779 ossl_pkcs7_set_data(self, Qnil); 00780 00781 err: 00782 BIO_free(out); 00783 BIO_free(in); 00784 if(ERR_peek_error()){ 00785 ossl_raise(ePKCS7Error, NULL); 00786 } 00787 00788 return data; 00789 } 00790 00791 static VALUE 00792 ossl_pkcs7_to_der(VALUE self) 00793 { 00794 PKCS7 *pkcs7; 00795 VALUE str; 00796 long len; 00797 unsigned char *p; 00798 00799 GetPKCS7(self, pkcs7); 00800 if((len = i2d_PKCS7(pkcs7, NULL)) <= 0) 00801 ossl_raise(ePKCS7Error, NULL); 00802 str = rb_str_new(0, len); 00803 p = (unsigned char *)RSTRING_PTR(str); 00804 if(i2d_PKCS7(pkcs7, &p) <= 0) 00805 ossl_raise(ePKCS7Error, NULL); 00806 ossl_str_adjust(str, p); 00807 00808 return str; 00809 } 00810 00811 static VALUE 00812 ossl_pkcs7_to_pem(VALUE self) 00813 { 00814 PKCS7 *pkcs7; 00815 BIO *out; 00816 VALUE str; 00817 00818 GetPKCS7(self, pkcs7); 00819 if (!(out = BIO_new(BIO_s_mem()))) { 00820 ossl_raise(ePKCS7Error, NULL); 00821 } 00822 if (!PEM_write_bio_PKCS7(out, pkcs7)) { 00823 BIO_free(out); 00824 ossl_raise(ePKCS7Error, NULL); 00825 } 00826 str = ossl_membio2str(out); 00827 00828 return str; 00829 } 00830 00831 /* 00832 * SIGNER INFO 00833 */ 00834 static VALUE 00835 ossl_pkcs7si_alloc(VALUE klass) 00836 { 00837 PKCS7_SIGNER_INFO *p7si; 00838 VALUE obj; 00839 00840 if (!(p7si = PKCS7_SIGNER_INFO_new())) { 00841 ossl_raise(ePKCS7Error, NULL); 00842 } 00843 WrapPKCS7si(klass, obj, p7si); 00844 00845 return obj; 00846 } 00847 00848 static VALUE 00849 ossl_pkcs7si_initialize(VALUE self, VALUE cert, VALUE key, VALUE digest) 00850 { 00851 PKCS7_SIGNER_INFO *p7si; 00852 EVP_PKEY *pkey; 00853 X509 *x509; 00854 const EVP_MD *md; 00855 00856 pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ 00857 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ 00858 md = GetDigestPtr(digest); 00859 GetPKCS7si(self, p7si); 00860 if (!(PKCS7_SIGNER_INFO_set(p7si, x509, pkey, (EVP_MD*)md))) { 00861 ossl_raise(ePKCS7Error, NULL); 00862 } 00863 00864 return self; 00865 } 00866 00867 static VALUE 00868 ossl_pkcs7si_get_issuer(VALUE self) 00869 { 00870 PKCS7_SIGNER_INFO *p7si; 00871 00872 GetPKCS7si(self, p7si); 00873 00874 return ossl_x509name_new(p7si->issuer_and_serial->issuer); 00875 } 00876 00877 static VALUE 00878 ossl_pkcs7si_get_serial(VALUE self) 00879 { 00880 PKCS7_SIGNER_INFO *p7si; 00881 00882 GetPKCS7si(self, p7si); 00883 00884 return asn1integer_to_num(p7si->issuer_and_serial->serial); 00885 } 00886 00887 static VALUE 00888 ossl_pkcs7si_get_signed_time(VALUE self) 00889 { 00890 PKCS7_SIGNER_INFO *p7si; 00891 ASN1_TYPE *asn1obj; 00892 00893 GetPKCS7si(self, p7si); 00894 00895 if (!(asn1obj = PKCS7_get_signed_attribute(p7si, NID_pkcs9_signingTime))) { 00896 ossl_raise(ePKCS7Error, NULL); 00897 } 00898 if (asn1obj->type == V_ASN1_UTCTIME) { 00899 return asn1time_to_time(asn1obj->value.utctime); 00900 } 00901 /* 00902 * OR 00903 * ossl_raise(ePKCS7Error, "..."); 00904 * ? 00905 */ 00906 00907 return Qnil; 00908 } 00909 00910 /* 00911 * RECIPIENT INFO 00912 */ 00913 static VALUE 00914 ossl_pkcs7ri_alloc(VALUE klass) 00915 { 00916 PKCS7_RECIP_INFO *p7ri; 00917 VALUE obj; 00918 00919 if (!(p7ri = PKCS7_RECIP_INFO_new())) { 00920 ossl_raise(ePKCS7Error, NULL); 00921 } 00922 WrapPKCS7ri(klass, obj, p7ri); 00923 00924 return obj; 00925 } 00926 00927 static VALUE 00928 ossl_pkcs7ri_initialize(VALUE self, VALUE cert) 00929 { 00930 PKCS7_RECIP_INFO *p7ri; 00931 X509 *x509; 00932 00933 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ 00934 GetPKCS7ri(self, p7ri); 00935 if (!PKCS7_RECIP_INFO_set(p7ri, x509)) { 00936 ossl_raise(ePKCS7Error, NULL); 00937 } 00938 00939 return self; 00940 } 00941 00942 static VALUE 00943 ossl_pkcs7ri_get_issuer(VALUE self) 00944 { 00945 PKCS7_RECIP_INFO *p7ri; 00946 00947 GetPKCS7ri(self, p7ri); 00948 00949 return ossl_x509name_new(p7ri->issuer_and_serial->issuer); 00950 } 00951 00952 static VALUE 00953 ossl_pkcs7ri_get_serial(VALUE self) 00954 { 00955 PKCS7_RECIP_INFO *p7ri; 00956 00957 GetPKCS7ri(self, p7ri); 00958 00959 return asn1integer_to_num(p7ri->issuer_and_serial->serial); 00960 } 00961 00962 static VALUE 00963 ossl_pkcs7ri_get_enc_key(VALUE self) 00964 { 00965 PKCS7_RECIP_INFO *p7ri; 00966 00967 GetPKCS7ri(self, p7ri); 00968 00969 return asn1str_to_str(p7ri->enc_key); 00970 } 00971 00972 /* 00973 * INIT 00974 */ 00975 void 00976 Init_ossl_pkcs7() 00977 { 00978 cPKCS7 = rb_define_class_under(mOSSL, "PKCS7", rb_cObject); 00979 ePKCS7Error = rb_define_class_under(cPKCS7, "PKCS7Error", eOSSLError); 00980 rb_define_singleton_method(cPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1); 00981 rb_define_singleton_method(cPKCS7, "write_smime", ossl_pkcs7_s_write_smime, -1); 00982 rb_define_singleton_method(cPKCS7, "sign", ossl_pkcs7_s_sign, -1); 00983 rb_define_singleton_method(cPKCS7, "encrypt", ossl_pkcs7_s_encrypt, -1); 00984 rb_attr(cPKCS7, rb_intern("data"), 1, 0, Qfalse); 00985 rb_attr(cPKCS7, rb_intern("error_string"), 1, 1, Qfalse); 00986 rb_define_alloc_func(cPKCS7, ossl_pkcs7_alloc); 00987 rb_define_copy_func(cPKCS7, ossl_pkcs7_copy); 00988 rb_define_method(cPKCS7, "initialize", ossl_pkcs7_initialize, -1); 00989 rb_define_method(cPKCS7, "type=", ossl_pkcs7_set_type, 1); 00990 rb_define_method(cPKCS7, "type", ossl_pkcs7_get_type, 0); 00991 rb_define_method(cPKCS7, "detached=", ossl_pkcs7_set_detached, 1); 00992 rb_define_method(cPKCS7, "detached", ossl_pkcs7_get_detached, 0); 00993 rb_define_method(cPKCS7, "detached?", ossl_pkcs7_detached_p, 0); 00994 rb_define_method(cPKCS7, "cipher=", ossl_pkcs7_set_cipher, 1); 00995 rb_define_method(cPKCS7, "add_signer", ossl_pkcs7_add_signer, 1); 00996 rb_define_method(cPKCS7, "signers", ossl_pkcs7_get_signer, 0); 00997 rb_define_method(cPKCS7, "add_recipient", ossl_pkcs7_add_recipient, 1); 00998 rb_define_method(cPKCS7, "recipients", ossl_pkcs7_get_recipient, 0); 00999 rb_define_method(cPKCS7, "add_certificate", ossl_pkcs7_add_certificate, 1); 01000 rb_define_method(cPKCS7, "certificates=", ossl_pkcs7_set_certificates, 1); 01001 rb_define_method(cPKCS7, "certificates", ossl_pkcs7_get_certificates, 0); 01002 rb_define_method(cPKCS7, "add_crl", ossl_pkcs7_add_crl, 1); 01003 rb_define_method(cPKCS7, "crls=", ossl_pkcs7_set_crls, 1); 01004 rb_define_method(cPKCS7, "crls", ossl_pkcs7_get_crls, 0); 01005 rb_define_method(cPKCS7, "add_data", ossl_pkcs7_add_data, 1); 01006 rb_define_alias(cPKCS7, "data=", "add_data"); 01007 rb_define_method(cPKCS7, "verify", ossl_pkcs7_verify, -1); 01008 rb_define_method(cPKCS7, "decrypt", ossl_pkcs7_decrypt, -1); 01009 rb_define_method(cPKCS7, "to_pem", ossl_pkcs7_to_pem, 0); 01010 rb_define_alias(cPKCS7, "to_s", "to_pem"); 01011 rb_define_method(cPKCS7, "to_der", ossl_pkcs7_to_der, 0); 01012 01013 cPKCS7Signer = rb_define_class_under(cPKCS7, "SignerInfo", rb_cObject); 01014 rb_define_const(cPKCS7, "Signer", cPKCS7Signer); 01015 rb_define_alloc_func(cPKCS7Signer, ossl_pkcs7si_alloc); 01016 rb_define_method(cPKCS7Signer, "initialize", ossl_pkcs7si_initialize,3); 01017 rb_define_method(cPKCS7Signer, "issuer", ossl_pkcs7si_get_issuer, 0); 01018 rb_define_alias(cPKCS7Signer, "name", "issuer"); 01019 rb_define_method(cPKCS7Signer, "serial", ossl_pkcs7si_get_serial,0); 01020 rb_define_method(cPKCS7Signer,"signed_time",ossl_pkcs7si_get_signed_time,0); 01021 01022 cPKCS7Recipient = rb_define_class_under(cPKCS7,"RecipientInfo",rb_cObject); 01023 rb_define_alloc_func(cPKCS7Recipient, ossl_pkcs7ri_alloc); 01024 rb_define_method(cPKCS7Recipient, "initialize", ossl_pkcs7ri_initialize,1); 01025 rb_define_method(cPKCS7Recipient, "issuer", ossl_pkcs7ri_get_issuer,0); 01026 rb_define_method(cPKCS7Recipient, "serial", ossl_pkcs7ri_get_serial,0); 01027 rb_define_method(cPKCS7Recipient, "enc_key", ossl_pkcs7ri_get_enc_key,0); 01028 01029 #define DefPKCS7Const(x) rb_define_const(cPKCS7, #x, INT2NUM(PKCS7_##x)) 01030 01031 DefPKCS7Const(TEXT); 01032 DefPKCS7Const(NOCERTS); 01033 DefPKCS7Const(NOSIGS); 01034 DefPKCS7Const(NOCHAIN); 01035 DefPKCS7Const(NOINTERN); 01036 DefPKCS7Const(NOVERIFY); 01037 DefPKCS7Const(DETACHED); 01038 DefPKCS7Const(BINARY); 01039 DefPKCS7Const(NOATTR); 01040 DefPKCS7Const(NOSMIMECAP); 01041 } 01042
1.7.3