Ruby 2.0.0p353(2013-11-22revision43784)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

ossl_ns_spki.c
Go to the documentation of this file.
1 /*
2 * $Id: ossl_ns_spki.c 33497 2011-10-20 17:22:09Z emboss $
3 * 'OpenSSL for Ruby' project
4 * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
5 * All rights reserved.
6 */
7 /*
8 * This program is licenced under the same licence as Ruby.
9 * (See the file 'LICENCE'.)
10 */
11 #include "ossl.h"
12
13 #define WrapSPKI(klass, obj, spki) do { \
14 if (!(spki)) { \
15 ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \
16 } \
17 (obj) = Data_Wrap_Struct((klass), 0, NETSCAPE_SPKI_free, (spki)); \
18 } while (0)
19 #define GetSPKI(obj, spki) do { \
20 Data_Get_Struct((obj), NETSCAPE_SPKI, (spki)); \
21 if (!(spki)) { \
22 ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \
23 } \
24 } while (0)
25
26 /*
27 * Classes
28 */
29 VALUE mNetscape;
30 VALUE cSPKI;
31 VALUE eSPKIError;
32
33 /*
34 * Public functions
35 */
36
37 /*
38 * Private functions
39 */
40 static VALUE
41 ossl_spki_alloc(VALUE klass)
42 {
43 NETSCAPE_SPKI *spki;
44 VALUE obj;
45
46 if (!(spki = NETSCAPE_SPKI_new())) {
47 ossl_raise(eSPKIError, NULL);
48 }
49 WrapSPKI(klass, obj, spki);
50
51 return obj;
52 }
53
54 /*
55 * call-seq:
56 * SPKI.new([request]) => spki
57 *
58 * === Parameters
59 * * +request+ - optional raw request, either in PEM or DER format.
60 */
61 static VALUE
62 ossl_spki_initialize(int argc, VALUE *argv, VALUE self)
63 {
64 NETSCAPE_SPKI *spki;
65 VALUE buffer;
66 const unsigned char *p;
67
68 if (rb_scan_args(argc, argv, "01", &buffer) == 0) {
69 return self;
70 }
71 StringValue(buffer);
72 if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING_PTR(buffer), -1))) {
73 p = (unsigned char *)RSTRING_PTR(buffer);
74 if (!(spki = d2i_NETSCAPE_SPKI(NULL, &p, RSTRING_LEN(buffer)))) {
75 ossl_raise(eSPKIError, NULL);
76 }
77 }
78 NETSCAPE_SPKI_free(DATA_PTR(self));
79 DATA_PTR(self) = spki;
80 ERR_clear_error();
81
82 return self;
83 }
84
85 /*
86 * call-seq:
87 * spki.to_der => DER-encoded string
88 *
89 * Returns the DER encoding of this SPKI.
90 */
91 static VALUE
92 ossl_spki_to_der(VALUE self)
93 {
94 NETSCAPE_SPKI *spki;
95 VALUE str;
96 long len;
97 unsigned char *p;
98
99 GetSPKI(self, spki);
100 if ((len = i2d_NETSCAPE_SPKI(spki, NULL)) <= 0)
101 ossl_raise(eX509CertError, NULL);
102 str = rb_str_new(0, len);
103 p = (unsigned char *)RSTRING_PTR(str);
104 if (i2d_NETSCAPE_SPKI(spki, &p) <= 0)
105 ossl_raise(eX509CertError, NULL);
106 ossl_str_adjust(str, p);
107
108 return str;
109 }
110
111 /*
112 * call-seq:
113 * spki.to_pem => PEM-encoded string
114 *
115 * Returns the PEM encoding of this SPKI.
116 */
117 static VALUE
118 ossl_spki_to_pem(VALUE self)
119 {
120 NETSCAPE_SPKI *spki;
121 char *data;
122 VALUE str;
123
124 GetSPKI(self, spki);
125 if (!(data = NETSCAPE_SPKI_b64_encode(spki))) {
126 ossl_raise(eSPKIError, NULL);
127 }
128 str = ossl_buf2str(data, rb_long2int(strlen(data)));
129
130 return str;
131 }
132
133 /*
134 * call-seq:
135 * spki.to_text => string
136 *
137 * Returns a textual representation of this SPKI, useful for debugging
138 * purposes.
139 */
140 static VALUE
141 ossl_spki_print(VALUE self)
142 {
143 NETSCAPE_SPKI *spki;
144 BIO *out;
145 BUF_MEM *buf;
146 VALUE str;
147
148 GetSPKI(self, spki);
149 if (!(out = BIO_new(BIO_s_mem()))) {
150 ossl_raise(eSPKIError, NULL);
151 }
152 if (!NETSCAPE_SPKI_print(out, spki)) {
153 BIO_free(out);
154 ossl_raise(eSPKIError, NULL);
155 }
156 BIO_get_mem_ptr(out, &buf);
157 str = rb_str_new(buf->data, buf->length);
158 BIO_free(out);
159
160 return str;
161 }
162
163 /*
164 * call-seq:
165 * spki.public_key => pkey
166 *
167 * Returns the public key associated with the SPKI, an instance of
168 * OpenSSL::PKey.
169 */
170 static VALUE
171 ossl_spki_get_public_key(VALUE self)
172 {
173 NETSCAPE_SPKI *spki;
174 EVP_PKEY *pkey;
175
176 GetSPKI(self, spki);
177 if (!(pkey = NETSCAPE_SPKI_get_pubkey(spki))) { /* adds an reference */
178 ossl_raise(eSPKIError, NULL);
179 }
180
181 return ossl_pkey_new(pkey); /* NO DUP - OK */
182 }
183
184 /*
185 * call-seq:
186 * spki.public_key = pub => pkey
187 *
188 * === Parameters
189 * * +pub+ - the public key to be set for this instance
190 *
191 * Sets the public key to be associated with the SPKI, an instance of
192 * OpenSSL::PKey. This should be the public key corresponding to the
193 * private key used for signing the SPKI.
194 */
195 static VALUE
196 ossl_spki_set_public_key(VALUE self, VALUE key)
197 {
198 NETSCAPE_SPKI *spki;
199
200 GetSPKI(self, spki);
201 if (!NETSCAPE_SPKI_set_pubkey(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */
202 ossl_raise(eSPKIError, NULL);
203 }
204
205 return key;
206 }
207
208 /*
209 * call-seq:
210 * spki.challenge => string
211 *
212 * Returns the challenge string associated with this SPKI.
213 */
214 static VALUE
215 ossl_spki_get_challenge(VALUE self)
216 {
217 NETSCAPE_SPKI *spki;
218
219 GetSPKI(self, spki);
220 if (spki->spkac->challenge->length <= 0) {
221 OSSL_Debug("Challenge.length <= 0?");
222 return rb_str_new(0, 0);
223 }
224
225 return rb_str_new((const char *)spki->spkac->challenge->data,
226 spki->spkac->challenge->length);
227 }
228
229 /*
230 * call-seq:
231 * spki.challenge = str => string
232 *
233 * === Parameters
234 * * +str+ - the challenge string to be set for this instance
235 *
236 * Sets the challenge to be associated with the SPKI. May be used by the
237 * server, e.g. to prevent replay.
238 */
239 static VALUE
240 ossl_spki_set_challenge(VALUE self, VALUE str)
241 {
242 NETSCAPE_SPKI *spki;
243
244 StringValue(str);
245 GetSPKI(self, spki);
246 if (!ASN1_STRING_set(spki->spkac->challenge, RSTRING_PTR(str),
247 RSTRING_LENINT(str))) {
248 ossl_raise(eSPKIError, NULL);
249 }
250
251 return str;
252 }
253
254 /*
255 * call-seq:
256 * spki.sign(key, digest) => spki
257 *
258 * === Parameters
259 * * +key+ - the private key to be used for signing this instance
260 * * +digest+ - the digest to be used for signing this instance
261 *
262 * To sign an SPKI, the private key corresponding to the public key set
263 * for this instance should be used, in addition to a digest algorithm in
264 * the form of an OpenSSL::Digest. The private key should be an instance of
265 * OpenSSL::PKey.
266 */
267 static VALUE
268 ossl_spki_sign(VALUE self, VALUE key, VALUE digest)
269 {
270 NETSCAPE_SPKI *spki;
271 EVP_PKEY *pkey;
272 const EVP_MD *md;
273
274 pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
275 md = GetDigestPtr(digest);
276 GetSPKI(self, spki);
277 if (!NETSCAPE_SPKI_sign(spki, pkey, md)) {
278 ossl_raise(eSPKIError, NULL);
279 }
280
281 return self;
282 }
283
284 /*
285 * call-seq:
286 * spki.verify(key) => boolean
287 *
288 * === Parameters
289 * * +key+ - the public key to be used for verifying the SPKI signature
290 *
291 * Returns +true+ if the signature is valid, +false+ otherwise. To verify an
292 * SPKI, the public key contained within the SPKI should be used.
293 */
294 static VALUE
295 ossl_spki_verify(VALUE self, VALUE key)
296 {
297 NETSCAPE_SPKI *spki;
298
299 GetSPKI(self, spki);
300 switch (NETSCAPE_SPKI_verify(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */
301 case 0:
302 return Qfalse;
303 case 1:
304 return Qtrue;
305 default:
306 ossl_raise(eSPKIError, NULL);
307 }
308 return Qnil; /* dummy */
309 }
310
311 /* Document-class: OpenSSL::Netscape::SPKI
312 *
313 * A Simple Public Key Infrastructure implementation (pronounced "spookey").
314 * The structure is defined as
315 * PublicKeyAndChallenge ::= SEQUENCE {
316 * spki SubjectPublicKeyInfo,
317 * challenge IA5STRING
318 * }
319 *
320 * SignedPublicKeyAndChallenge ::= SEQUENCE {
321 * publicKeyAndChallenge PublicKeyAndChallenge,
322 * signatureAlgorithm AlgorithmIdentifier,
323 * signature BIT STRING
324 * }
325 * where the definitions of SubjectPublicKeyInfo and AlgorithmIdentifier can
326 * be found in RFC5280. SPKI is typically used in browsers for generating
327 * a public/private key pair and a subsequent certificate request, using
328 * the HTML <keygen> element.
329 *
330 * == Examples
331 *
332 * === Creating an SPKI
333 * key = OpenSSL::PKey::RSA.new 2048
334 * spki = OpenSSL::Netscape::SPKI.new
335 * spki.challenge = "RandomChallenge"
336 * spki.public_key = key.public_key
337 * spki.sign(key, OpenSSL::Digest::SHA256.new)
338 * #send a request containing this to a server generating a certificate
339 * === Verifiying an SPKI request
340 * request = #...
341 * spki = OpenSSL::Netscape::SPKI.new request
342 * unless spki.verify(spki.public_key)
343 * # signature is invalid
344 * end
345 * #proceed
346 */
347
348 /* Document-module: OpenSSL::Netscape
349 *
350 * OpenSSL::Netscape is a namespace for SPKI (Simple Public Key
351 * Infrastructure) which implements Signed Public Key and Challenge.
352 * See {RFC 2692}[http://tools.ietf.org/html/rfc2692] and {RFC
353 * 2693}[http://tools.ietf.org/html/rfc2692] for details.
354 */
355
356 /* Document-class: OpenSSL::Netscape::SPKIError
357 *
358 * Generic Exception class that is raised if an error occurs during an
359 * operation on an instance of OpenSSL::Netscape::SPKI.
360 */
361
362 void
363 Init_ossl_ns_spki()
364 {
365 #if 0
366 mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
367 #endif
368
369 mNetscape = rb_define_module_under(mOSSL, "Netscape");
370
371 eSPKIError = rb_define_class_under(mNetscape, "SPKIError", eOSSLError);
372
373 cSPKI = rb_define_class_under(mNetscape, "SPKI", rb_cObject);
374
375 rb_define_alloc_func(cSPKI, ossl_spki_alloc);
376 rb_define_method(cSPKI, "initialize", ossl_spki_initialize, -1);
377
378 rb_define_method(cSPKI, "to_der", ossl_spki_to_der, 0);
379 rb_define_method(cSPKI, "to_pem", ossl_spki_to_pem, 0);
380 rb_define_alias(cSPKI, "to_s", "to_pem");
381 rb_define_method(cSPKI, "to_text", ossl_spki_print, 0);
382 rb_define_method(cSPKI, "public_key", ossl_spki_get_public_key, 0);
383 rb_define_method(cSPKI, "public_key=", ossl_spki_set_public_key, 1);
384 rb_define_method(cSPKI, "sign", ossl_spki_sign, 2);
385 rb_define_method(cSPKI, "verify", ossl_spki_verify, 1);
386 rb_define_method(cSPKI, "challenge", ossl_spki_get_challenge, 0);
387 rb_define_method(cSPKI, "challenge=", ossl_spki_set_challenge, 1);
388 }
389
data
VALUE data
Definition: tcltklib.c:3368
mOSSL
VALUE mOSSL
Definition: ossl.c:259
strlen
size_t strlen(const char *)
p
Win32OLEIDispatch * p
Definition: win32ole.c:786
WrapSPKI
#define WrapSPKI(klass, obj, spki)
Definition: ossl_ns_spki.c:13
out
C_block * out
Definition: crypt.c:308
eSPKIError
VALUE eSPKIError
Definition: ossl_ns_spki.c:31
GetPrivPKeyPtr
EVP_PKEY * GetPrivPKeyPtr(VALUE obj)
Definition: ossl_pkey.c:184
ossl_str_adjust
#define ossl_str_adjust(str, p)
Definition: ossl.h:138
ossl_spki_print
static VALUE ossl_spki_print(VALUE self)
Definition: ossl_ns_spki.c:141
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
ossl_spki_set_public_key
static VALUE ossl_spki_set_public_key(VALUE self, VALUE key)
Definition: ossl_ns_spki.c:196
RSTRING_PTR
#define RSTRING_PTR(str)
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:545
Qtrue
return Qtrue
Definition: tcltklib.c:9610
ossl_spki_get_challenge
static VALUE ossl_spki_get_challenge(VALUE self)
Definition: ossl_ns_spki.c:215
ossl_pkey_new
VALUE ossl_pkey_new(EVP_PKEY *pkey)
Definition: ossl_pkey.c:76
ossl_spki_to_der
static VALUE ossl_spki_to_der(VALUE self)
Definition: ossl_ns_spki.c:92
Qfalse
return Qfalse
Definition: tcltklib.c:6779
Qnil
#define Qnil
Definition: tcltklib.c:1896
eX509CertError
VALUE eX509CertError
Definition: ossl_x509cert.c:34
str
static VALUE char * str
Definition: tcltklib.c:3547
ossl_spki_get_public_key
static VALUE ossl_spki_get_public_key(VALUE self)
Definition: ossl_ns_spki.c:171
GetDigestPtr
const EVP_MD * GetDigestPtr(VALUE obj)
Definition: ossl_digest.c:36
obj
static VALUE VALUE obj
Definition: tcltklib.c:3158
RSTRING_LEN
#define RSTRING_LEN(str)
eOSSLError
VALUE eOSSLError
Definition: ossl.c:264
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
key
static int VALUE key
Definition: tkutil.c:265
rb_long2int
#define rb_long2int(n)
argv
VALUE * argv
Definition: tcltklib.c:1971
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1539
StringValue
#define StringValue(v)
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1570
argc
int argc
Definition: tcltklib.c:1970
OSSL_Debug
#define OSSL_Debug
Definition: ossl.h:211
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:637
ossl_spki_set_challenge
static VALUE ossl_spki_set_challenge(VALUE self, VALUE str)
Definition: ossl_ns_spki.c:240
ossl_spki_alloc
static VALUE ossl_spki_alloc(VALUE klass)
Definition: ossl_ns_spki.c:41
DATA_PTR
DATA_PTR(self)
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ripper.y:1426
ossl_spki_sign
static VALUE ossl_spki_sign(VALUE self, VALUE key, VALUE digest)
Definition: ossl_ns_spki.c:268
ossl_buf2str
VALUE ossl_buf2str(char *buf, int len)
Definition: ossl.c:134
mNetscape
VALUE mNetscape
Definition: ossl_ns_spki.c:29
klass
klass
Definition: tcltklib.c:3504
ossl_spki_to_pem
static VALUE ossl_spki_to_pem(VALUE self)
Definition: ossl_ns_spki.c:118
ossl_raise
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:328
GetPKeyPtr
EVP_PKEY * GetPKeyPtr(VALUE obj)
Definition: ossl_pkey.c:174
Init_ossl_ns_spki
void Init_ossl_ns_spki()
Definition: ossl_ns_spki.c:363
RSTRING_LENINT
#define RSTRING_LENINT(str)
rb_str_new
VALUE rb_str_new(const char *, long)
Definition: string.c:425
ossl_spki_verify
static VALUE ossl_spki_verify(VALUE self, VALUE key)
Definition: ossl_ns_spki.c:295
ossl.h
VALUE
unsigned long VALUE
Definition: ripper.y:104
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:617
ossl_spki_initialize
static VALUE ossl_spki_initialize(int argc, VALUE *argv, VALUE self)
Definition: ossl_ns_spki.c:62
NULL
#define NULL
Definition: _sdbm.c:103
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
GetSPKI
#define GetSPKI(obj, spki)
Definition: ossl_ns_spki.c:19
cSPKI
VALUE cSPKI
Definition: ossl_ns_spki.c:30
len
size_t len
Definition: tcltklib.c:3568