Ruby  2.0.0p648(2015-12-16revision53162)
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  */
32 
33 /*
34  * Public functions
35  */
36 
37 /*
38  * Private functions
39  */
40 static VALUE
42 {
43  NETSCAPE_SPKI *spki;
44  VALUE obj;
45 
46  if (!(spki = NETSCAPE_SPKI_new())) {
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
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)))) {
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
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)
102  str = rb_str_new(0, len);
103  p = (unsigned char *)RSTRING_PTR(str);
104  if (i2d_NETSCAPE_SPKI(spki, &p) <= 0)
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
119 {
120  NETSCAPE_SPKI *spki;
121  char *data;
122  VALUE str;
123 
124  GetSPKI(self, spki);
125  if (!(data = NETSCAPE_SPKI_b64_encode(spki))) {
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
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()))) {
151  }
152  if (!NETSCAPE_SPKI_print(out, spki)) {
153  BIO_free(out);
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
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 */
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
197 {
198  NETSCAPE_SPKI *spki;
199 
200  GetSPKI(self, spki);
201  if (!NETSCAPE_SPKI_set_pubkey(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */
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
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
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))) {
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
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)) {
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
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:
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
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 
372 
374 
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);
383  rb_define_method(cSPKI, "public_key=", ossl_spki_set_public_key, 1);
385  rb_define_method(cSPKI, "verify", ossl_spki_verify, 1);
388 }
389 
VALUE mOSSL
Definition: ossl.c:259
size_t strlen(const char *)
#define WrapSPKI(klass, obj, spki)
Definition: ossl_ns_spki.c:13
VALUE eSPKIError
Definition: ossl_ns_spki.c:31
#define Qtrue
Definition: ruby.h:434
EVP_PKEY * GetPrivPKeyPtr(VALUE obj)
Definition: ossl_pkey.c:184
#define ossl_str_adjust(str, p)
Definition: ossl.h:138
static VALUE ossl_spki_print(VALUE self)
Definition: ossl_ns_spki.c:141
static VALUE ossl_spki_set_public_key(VALUE self, VALUE key)
Definition: ossl_ns_spki.c:196
#define rb_long2int(n)
Definition: ruby.h:325
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:534
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
#define DATA_PTR(dta)
Definition: ruby.h:985
static VALUE ossl_spki_get_challenge(VALUE self)
Definition: ossl_ns_spki.c:215
VALUE ossl_pkey_new(EVP_PKEY *pkey)
Definition: ossl_pkey.c:76
Win32OLEIDispatch * p
Definition: win32ole.c:786
static VALUE ossl_spki_to_der(VALUE self)
Definition: ossl_ns_spki.c:92
VALUE eX509CertError
Definition: ossl_x509cert.c:34
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1426
static VALUE ossl_spki_get_public_key(VALUE self)
Definition: ossl_ns_spki.c:171
const EVP_MD * GetDigestPtr(VALUE obj)
Definition: ossl_digest.c:36
VALUE eOSSLError
Definition: ossl.c:264
int argc
Definition: ruby.c:130
#define Qfalse
Definition: ruby.h:433
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1539
#define RSTRING_LEN(str)
Definition: ruby.h:862
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1570
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
#define Qnil
Definition: ruby.h:435
unsigned long VALUE
Definition: ruby.h:104
#define OSSL_Debug
Definition: ossl.h:211
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:626
#define RSTRING_PTR(str)
Definition: ruby.h:866
static VALUE ossl_spki_set_challenge(VALUE self, VALUE str)
Definition: ossl_ns_spki.c:240
static VALUE ossl_spki_alloc(VALUE klass)
Definition: ossl_ns_spki.c:41
static VALUE ossl_spki_sign(VALUE self, VALUE key, VALUE digest)
Definition: ossl_ns_spki.c:268
uint8_t key[16]
Definition: random.c:1370
VALUE ossl_buf2str(char *buf, int len)
Definition: ossl.c:134
VALUE mNetscape
Definition: ossl_ns_spki.c:29
static VALUE ossl_spki_to_pem(VALUE self)
Definition: ossl_ns_spki.c:118
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:333
EVP_PKEY * GetPKeyPtr(VALUE obj)
Definition: ossl_pkey.c:174
void Init_ossl_ns_spki()
Definition: ossl_ns_spki.c:363
static VALUE ossl_spki_verify(VALUE self, VALUE key)
Definition: ossl_ns_spki.c:295
#define RSTRING_LENINT(str)
Definition: ruby.h:874
VALUE rb_define_module(const char *name)
Definition: class.c:606
static VALUE ossl_spki_initialize(int argc, VALUE *argv, VALUE self)
Definition: ossl_ns_spki.c:62
#define NULL
Definition: _sdbm.c:102
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
#define GetSPKI(obj, spki)
Definition: ossl_ns_spki.c:19
VALUE cSPKI
Definition: ossl_ns_spki.c:30
char ** argv
Definition: ruby.c:131
#define StringValue(v)
Definition: ruby.h:546
VALUE rb_str_new(const char *, long)
Definition: string.c:425