• 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 

Generated on Wed Sep 8 2010 21:54:05 for Ruby by  doxygen 1.7.1