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) (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 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
00390
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
00406
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);
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);
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);
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);
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);
00743 x509 = GetX509CertPtr(cert);
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);
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
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);
00857 x509 = GetX509CertPtr(cert);
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
00903
00904
00905
00906
00907 return Qnil;
00908 }
00909
00910
00911
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);
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
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