00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00073
00074 VALUE cPKCS7;
00075 VALUE cPKCS7Signer;
00076 VALUE cPKCS7Recipient;
00077 VALUE ePKCS7Error;
00078
00079
00080
00081
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
00137
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
00161
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
00196
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);
00212 pkey = GetPrivPKeyPtr(key);
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
00239
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);
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
00304
00305
00306
00307
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
00395
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
00411
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);
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);
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);
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);
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);
00748 x509 = GetX509CertPtr(cert);
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);
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
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);
00862 x509 = GetX509CertPtr(cert);
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
00908
00909
00910
00911
00912 return Qnil;
00913 }
00914
00915
00916
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);
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
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