Ruby 2.0.0p247(2013-06-27revision41674)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

ossl_pkcs12.c
Go to the documentation of this file.
1 /*
2 * This program is licenced under the same licence as Ruby.
3 * (See the file 'LICENCE'.)
4 * $Id: ossl_pkcs12.c 32199 2011-06-22 08:41:08Z emboss $
5 */
6 #include "ossl.h"
7
8 #define WrapPKCS12(klass, obj, p12) do { \
9 if(!(p12)) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
10 (obj) = Data_Wrap_Struct((klass), 0, PKCS12_free, (p12)); \
11 } while (0)
12
13 #define GetPKCS12(obj, p12) do { \
14 Data_Get_Struct((obj), PKCS12, (p12)); \
15 if(!(p12)) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
16 } while (0)
17
18 #define SafeGetPKCS12(obj, p12) do { \
19 OSSL_Check_Kind((obj), cPKCS12); \
20 GetPKCS12((obj), (p12)); \
21 } while (0)
22
23 #define ossl_pkcs12_set_key(o,v) rb_iv_set((o), "@key", (v))
24 #define ossl_pkcs12_set_cert(o,v) rb_iv_set((o), "@certificate", (v))
25 #define ossl_pkcs12_set_ca_certs(o,v) rb_iv_set((o), "@ca_certs", (v))
26 #define ossl_pkcs12_get_key(o) rb_iv_get((o), "@key")
27 #define ossl_pkcs12_get_cert(o) rb_iv_get((o), "@certificate")
28 #define ossl_pkcs12_get_ca_certs(o) rb_iv_get((o), "@ca_certs")
29
30 /*
31 * Classes
32 */
33 VALUE cPKCS12;
34 VALUE ePKCS12Error;
35
36 /*
37 * Private
38 */
39 static VALUE
40 ossl_pkcs12_s_allocate(VALUE klass)
41 {
42 PKCS12 *p12;
43 VALUE obj;
44
45 if(!(p12 = PKCS12_new())) ossl_raise(ePKCS12Error, NULL);
46 WrapPKCS12(klass, obj, p12);
47
48 return obj;
49 }
50
51 /*
52 * call-seq:
53 * PKCS12.create(pass, name, key, cert [, ca, [, key_pbe [, cert_pbe [, key_iter [, mac_iter [, keytype]]]]]])
54 *
55 * === Parameters
56 * * +pass+ - string
57 * * +name+ - A string describing the key.
58 * * +key+ - Any PKey.
59 * * +cert+ - A X509::Certificate.
60 * * * The public_key portion of the certificate must contain a valid public key.
61 * * * The not_before and not_after fields must be filled in.
62 * * +ca+ - An optional array of X509::Certificate's.
63 * * +key_pbe+ - string
64 * * +cert_pbe+ - string
65 * * +key_iter+ - integer
66 * * +mac_iter+ - integer
67 * * +keytype+ - An integer representing an MSIE specific extension.
68 *
69 * Any optional arguments may be supplied as nil to preserve the OpenSSL defaults.
70 *
71 * See the OpenSSL documentation for PKCS12_create().
72 */
73 static VALUE
74 ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
75 {
76 VALUE pass, name, pkey, cert, ca, key_nid, cert_nid, key_iter, mac_iter, keytype;
77 VALUE obj;
78 char *passphrase, *friendlyname;
79 EVP_PKEY *key;
80 X509 *x509;
81 STACK_OF(X509) *x509s;
82 int nkey = 0, ncert = 0, kiter = 0, miter = 0, ktype = 0;
83 PKCS12 *p12;
84
85 rb_scan_args(argc, argv, "46", &pass, &name, &pkey, &cert, &ca, &key_nid, &cert_nid, &key_iter, &mac_iter, &keytype);
86 passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass);
87 friendlyname = NIL_P(name) ? NULL : StringValuePtr(name);
88 key = GetPKeyPtr(pkey);
89 x509 = GetX509CertPtr(cert);
90 x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca);
91 /* TODO: make a VALUE to nid function */
92 if (!NIL_P(key_nid)) {
93 if ((nkey = OBJ_txt2nid(StringValuePtr(key_nid))) == NID_undef)
94 ossl_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(key_nid));
95 }
96 if (!NIL_P(cert_nid)) {
97 if ((ncert = OBJ_txt2nid(StringValuePtr(cert_nid))) == NID_undef)
98 ossl_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(cert_nid));
99 }
100 if (!NIL_P(key_iter))
101 kiter = NUM2INT(key_iter);
102 if (!NIL_P(mac_iter))
103 miter = NUM2INT(mac_iter);
104 if (!NIL_P(keytype))
105 ktype = NUM2INT(keytype);
106
107 p12 = PKCS12_create(passphrase, friendlyname, key, x509, x509s,
108 nkey, ncert, kiter, miter, ktype);
109 sk_X509_pop_free(x509s, X509_free);
110 if(!p12) ossl_raise(ePKCS12Error, NULL);
111 WrapPKCS12(cPKCS12, obj, p12);
112
113 ossl_pkcs12_set_key(obj, pkey);
114 ossl_pkcs12_set_cert(obj, cert);
115 ossl_pkcs12_set_ca_certs(obj, ca);
116
117 return obj;
118 }
119
120 /*
121 * call-seq:
122 * PKCS12.new -> pkcs12
123 * PKCS12.new(str) -> pkcs12
124 * PKCS12.new(str, pass) -> pkcs12
125 *
126 * === Parameters
127 * * +str+ - Must be a DER encoded PKCS12 string.
128 * * +pass+ - string
129 */
130 static VALUE
131 ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
132 {
133 BIO *in;
134 VALUE arg, pass, pkey, cert, ca;
135 char *passphrase;
136 EVP_PKEY *key;
137 X509 *x509;
138 STACK_OF(X509) *x509s = NULL;
139 int st = 0;
140 PKCS12 *pkcs = DATA_PTR(self);
141
142 if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) return self;
143 passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass);
144 in = ossl_obj2bio(arg);
145 d2i_PKCS12_bio(in, &pkcs);
146 DATA_PTR(self) = pkcs;
147 BIO_free(in);
148
149 pkey = cert = ca = Qnil;
150 if(!PKCS12_parse(pkcs, passphrase, &key, &x509, &x509s))
151 ossl_raise(ePKCS12Error, "PKCS12_parse");
152 pkey = rb_protect((VALUE(*)_((VALUE)))ossl_pkey_new, (VALUE)key,
153 &st); /* NO DUP */
154 if(st) goto err;
155 cert = rb_protect((VALUE(*)_((VALUE)))ossl_x509_new, (VALUE)x509, &st);
156 if(st) goto err;
157 if(x509s){
158 ca =
159 rb_protect((VALUE(*)_((VALUE)))ossl_x509_sk2ary, (VALUE)x509s, &st);
160 if(st) goto err;
161 }
162
163 err:
164 X509_free(x509);
165 sk_X509_pop_free(x509s, X509_free);
166 ossl_pkcs12_set_key(self, pkey);
167 ossl_pkcs12_set_cert(self, cert);
168 ossl_pkcs12_set_ca_certs(self, ca);
169 if(st) rb_jump_tag(st);
170
171 return self;
172 }
173
174 static VALUE
175 ossl_pkcs12_to_der(VALUE self)
176 {
177 PKCS12 *p12;
178 VALUE str;
179 long len;
180 unsigned char *p;
181
182 GetPKCS12(self, p12);
183 if((len = i2d_PKCS12(p12, NULL)) <= 0)
184 ossl_raise(ePKCS12Error, NULL);
185 str = rb_str_new(0, len);
186 p = (unsigned char *)RSTRING_PTR(str);
187 if(i2d_PKCS12(p12, &p) <= 0)
188 ossl_raise(ePKCS12Error, NULL);
189 ossl_str_adjust(str, p);
190
191 return str;
192 }
193
194 void
195 Init_ossl_pkcs12()
196 {
197 /*
198 * Defines a file format commonly used to store private keys with
199 * accompanying public key certificates, protected with a password-based
200 * symmetric key.
201 */
202 cPKCS12 = rb_define_class_under(mOSSL, "PKCS12", rb_cObject);
203 ePKCS12Error = rb_define_class_under(cPKCS12, "PKCS12Error", eOSSLError);
204 rb_define_singleton_method(cPKCS12, "create", ossl_pkcs12_s_create, -1);
205
206 rb_define_alloc_func(cPKCS12, ossl_pkcs12_s_allocate);
207 rb_attr(cPKCS12, rb_intern("key"), 1, 0, Qfalse);
208 rb_attr(cPKCS12, rb_intern("certificate"), 1, 0, Qfalse);
209 rb_attr(cPKCS12, rb_intern("ca_certs"), 1, 0, Qfalse);
210 rb_define_method(cPKCS12, "initialize", ossl_pkcs12_initialize, -1);
211 rb_define_method(cPKCS12, "to_der", ossl_pkcs12_to_der, 0);
212 }
213