• Main Page
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

ext/openssl/ossl_pkcs12.c

Go to the documentation of this file.
00001 /*
00002  * This program is licenced under the same licence as Ruby.
00003  * (See the file 'LICENCE'.)
00004  * $Id: ossl_pkcs12.c 27437 2010-04-22 08:04:13Z nobu $
00005  */
00006 #include "ossl.h"
00007 
00008 #define WrapPKCS12(klass, obj, p12) do { \
00009     if(!p12) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
00010     obj = Data_Wrap_Struct(klass, 0, PKCS12_free, p12); \
00011 } while (0)
00012 
00013 #define GetPKCS12(obj, p12) do { \
00014     Data_Get_Struct(obj, PKCS12, p12); \
00015     if(!p12) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
00016 } while (0)
00017 
00018 #define SafeGetPKCS12(obj, p12) do { \
00019     OSSL_Check_Kind(obj, cPKCS12); \
00020     GetPKCS12(obj, p12); \
00021 } while (0)
00022 
00023 #define ossl_pkcs12_set_key(o,v)      rb_iv_set((o), "@key", (v))
00024 #define ossl_pkcs12_set_cert(o,v)     rb_iv_set((o), "@certificate", (v))
00025 #define ossl_pkcs12_set_ca_certs(o,v) rb_iv_set((o), "@ca_certs", (v))
00026 #define ossl_pkcs12_get_key(o)        rb_iv_get((o), "@key")
00027 #define ossl_pkcs12_get_cert(o)       rb_iv_get((o), "@certificate")
00028 #define ossl_pkcs12_get_ca_certs(o)   rb_iv_get((o), "@ca_certs")
00029 
00030 /*
00031  * Classes
00032  */
00033 VALUE cPKCS12;
00034 VALUE ePKCS12Error;
00035 
00036 /*
00037  * Private
00038  */
00039 static VALUE
00040 ossl_pkcs12_s_allocate(VALUE klass)
00041 {
00042     PKCS12 *p12;
00043     VALUE obj;
00044 
00045     if(!(p12 = PKCS12_new())) ossl_raise(ePKCS12Error, NULL);
00046     WrapPKCS12(klass, obj, p12);
00047 
00048     return obj;
00049 }
00050 
00051 /*
00052  * call-seq:
00053  *    PKCS12.create(pass, name, key, cert [, ca, [, key_pbe [, cert_pbe [, key_iter [, mac_iter [, keytype]]]]]])
00054  *
00055  * === Parameters
00056  * * +pass+ - string
00057  * * +name+ - A string describing the key.
00058  * * +key+ - Any PKey.
00059  * * +cert+ - A X509::Certificate.
00060  * * * The public_key portion of the certificate must contain a valid public key.
00061  * * * The not_before and not_after fields must be filled in.
00062  * * +ca+ - An optional array of X509::Certificate's.
00063  * * +key_pbe+ - string
00064  * * +cert_pbe+ - string
00065  * * +key_iter+ - integer
00066  * * +mac_iter+ - integer
00067  * * +keytype+ - An integer representing an MSIE specific extension.
00068  *
00069  * Any optional arguments may be supplied as nil to preserve the OpenSSL defaults.
00070  *
00071  * See the OpenSSL documentation for PKCS12_create().
00072  */
00073 static VALUE
00074 ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
00075 {
00076     VALUE pass, name, pkey, cert, ca, key_nid, cert_nid, key_iter, mac_iter, keytype;
00077     VALUE obj;
00078     char *passphrase, *friendlyname;
00079     EVP_PKEY *key;
00080     X509 *x509;
00081     STACK_OF(X509) *x509s;
00082     int nkey = 0, ncert = 0, kiter = 0, miter = 0, ktype = 0;
00083     PKCS12 *p12;
00084 
00085     rb_scan_args(argc, argv, "46", &pass, &name, &pkey, &cert, &ca, &key_nid, &cert_nid, &key_iter, &mac_iter, &keytype);
00086     passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass);
00087     friendlyname = NIL_P(name) ? NULL : StringValuePtr(name);
00088     key = GetPKeyPtr(pkey);
00089     x509 = GetX509CertPtr(cert);
00090     x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca);
00091 /* TODO: make a VALUE to nid function */
00092     if (!NIL_P(key_nid)) {
00093         if ((nkey = OBJ_txt2nid(StringValuePtr(key_nid))) == NID_undef)
00094             rb_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(key_nid));
00095     }
00096     if (!NIL_P(cert_nid)) {
00097         if ((ncert = OBJ_txt2nid(StringValuePtr(cert_nid))) == NID_undef)
00098             rb_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(cert_nid));
00099     }
00100     if (!NIL_P(key_iter))
00101         kiter = NUM2INT(key_iter);
00102     if (!NIL_P(mac_iter))
00103         miter = NUM2INT(mac_iter);
00104     if (!NIL_P(keytype))
00105         ktype = NUM2INT(keytype);
00106 
00107     p12 = PKCS12_create(passphrase, friendlyname, key, x509, x509s,
00108                         nkey, ncert, kiter, miter, ktype);
00109     sk_X509_pop_free(x509s, X509_free);
00110     if(!p12) ossl_raise(ePKCS12Error, NULL);
00111     WrapPKCS12(cPKCS12, obj, p12);
00112 
00113     ossl_pkcs12_set_key(obj, pkey);
00114     ossl_pkcs12_set_cert(obj, cert);
00115     ossl_pkcs12_set_ca_certs(obj, ca);
00116 
00117     return obj;
00118 }
00119 
00120 /*
00121  * call-seq:
00122  *    PKCS12.new -> pkcs12
00123  *    PKCS12.new(str) -> pkcs12
00124  *    PKCS12.new(str, pass) -> pkcs12
00125  *
00126  * === Parameters
00127  * * +str+ - Must be a DER encoded PKCS12 string.
00128  * * +pass+ - string
00129  */
00130 static VALUE
00131 ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
00132 {
00133     BIO *in;
00134     VALUE arg, pass, pkey, cert, ca;
00135     char *passphrase;
00136     EVP_PKEY *key;
00137     X509 *x509;
00138     STACK_OF(X509) *x509s = NULL;
00139     int st = 0;
00140     PKCS12 *pkcs = DATA_PTR(self);
00141 
00142     if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) return self;
00143     passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass);
00144     in = ossl_obj2bio(arg);
00145     d2i_PKCS12_bio(in, &pkcs);
00146     DATA_PTR(self) = pkcs;
00147     BIO_free(in);
00148 
00149     pkey = cert = ca = Qnil;
00150     if(!PKCS12_parse(pkcs, passphrase, &key, &x509, &x509s))
00151         ossl_raise(ePKCS12Error, "PKCS12_parse");
00152     pkey = rb_protect((VALUE(*)_((VALUE)))ossl_pkey_new, (VALUE)key,
00153                       &st); /* NO DUP */
00154     if(st) goto err;
00155     cert = rb_protect((VALUE(*)_((VALUE)))ossl_x509_new, (VALUE)x509, &st);
00156     if(st) goto err;
00157     if(x509s){
00158         ca =
00159             rb_protect((VALUE(*)_((VALUE)))ossl_x509_sk2ary, (VALUE)x509s, &st);
00160         if(st) goto err;
00161     }
00162 
00163   err:
00164     X509_free(x509);
00165     sk_X509_pop_free(x509s, X509_free);
00166     ossl_pkcs12_set_key(self, pkey);
00167     ossl_pkcs12_set_cert(self, cert);
00168     ossl_pkcs12_set_ca_certs(self, ca);
00169     if(st) rb_jump_tag(st);
00170 
00171     return self;
00172 }
00173 
00174 static VALUE
00175 ossl_pkcs12_to_der(VALUE self)
00176 {
00177     PKCS12 *p12;
00178     VALUE str;
00179     long len;
00180     unsigned char *p;
00181 
00182     GetPKCS12(self, p12);
00183     if((len = i2d_PKCS12(p12, NULL)) <= 0)
00184         ossl_raise(ePKCS12Error, NULL);
00185     str = rb_str_new(0, len);
00186     p = (unsigned char *)RSTRING_PTR(str);
00187     if(i2d_PKCS12(p12, &p) <= 0)
00188         ossl_raise(ePKCS12Error, NULL);
00189     ossl_str_adjust(str, p);
00190 
00191     return str;
00192 }
00193 
00194 void
00195 Init_ossl_pkcs12()
00196 {
00197     /*
00198      * Defines a file format commonly used to store private keys with
00199      * accompanying public key certificates, protected with a password-based
00200      * symmetric key.
00201      */
00202     cPKCS12 = rb_define_class_under(mOSSL, "PKCS12", rb_cObject);
00203     ePKCS12Error = rb_define_class_under(cPKCS12, "PKCS12Error", eOSSLError);
00204     rb_define_singleton_method(cPKCS12, "create", ossl_pkcs12_s_create, -1);
00205 
00206     rb_define_alloc_func(cPKCS12, ossl_pkcs12_s_allocate);
00207     rb_attr(cPKCS12, rb_intern("key"), 1, 0, Qfalse);
00208     rb_attr(cPKCS12, rb_intern("certificate"), 1, 0, Qfalse);
00209     rb_attr(cPKCS12, rb_intern("ca_certs"), 1, 0, Qfalse);
00210     rb_define_method(cPKCS12, "initialize", ossl_pkcs12_initialize, -1);
00211     rb_define_method(cPKCS12, "to_der", ossl_pkcs12_to_der, 0);
00212 }
00213 

Generated on Thu Sep 8 2011 03:50:35 for Ruby by  doxygen 1.7.1