Ruby 1.9.2p136(2010-12-25revision30365)

- 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