Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# ext/openssl/ossl_pkcs7.c

Go to the documentation of this file.

    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