openssl 2.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of openssl might be problematic. Click here for more details.

Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/BSDL +22 -0
  3. data/CONTRIBUTING.md +130 -0
  4. data/History.md +118 -0
  5. data/LICENSE.txt +56 -0
  6. data/README.md +70 -0
  7. data/ext/openssl/deprecation.rb +26 -0
  8. data/ext/openssl/extconf.rb +158 -0
  9. data/ext/openssl/openssl_missing.c +173 -0
  10. data/ext/openssl/openssl_missing.h +244 -0
  11. data/ext/openssl/ossl.c +1201 -0
  12. data/ext/openssl/ossl.h +222 -0
  13. data/ext/openssl/ossl_asn1.c +1992 -0
  14. data/ext/openssl/ossl_asn1.h +66 -0
  15. data/ext/openssl/ossl_bio.c +87 -0
  16. data/ext/openssl/ossl_bio.h +19 -0
  17. data/ext/openssl/ossl_bn.c +1153 -0
  18. data/ext/openssl/ossl_bn.h +23 -0
  19. data/ext/openssl/ossl_cipher.c +1085 -0
  20. data/ext/openssl/ossl_cipher.h +20 -0
  21. data/ext/openssl/ossl_config.c +89 -0
  22. data/ext/openssl/ossl_config.h +19 -0
  23. data/ext/openssl/ossl_digest.c +453 -0
  24. data/ext/openssl/ossl_digest.h +20 -0
  25. data/ext/openssl/ossl_engine.c +580 -0
  26. data/ext/openssl/ossl_engine.h +19 -0
  27. data/ext/openssl/ossl_hmac.c +398 -0
  28. data/ext/openssl/ossl_hmac.h +18 -0
  29. data/ext/openssl/ossl_ns_spki.c +406 -0
  30. data/ext/openssl/ossl_ns_spki.h +19 -0
  31. data/ext/openssl/ossl_ocsp.c +2013 -0
  32. data/ext/openssl/ossl_ocsp.h +23 -0
  33. data/ext/openssl/ossl_pkcs12.c +259 -0
  34. data/ext/openssl/ossl_pkcs12.h +13 -0
  35. data/ext/openssl/ossl_pkcs5.c +180 -0
  36. data/ext/openssl/ossl_pkcs5.h +6 -0
  37. data/ext/openssl/ossl_pkcs7.c +1125 -0
  38. data/ext/openssl/ossl_pkcs7.h +20 -0
  39. data/ext/openssl/ossl_pkey.c +435 -0
  40. data/ext/openssl/ossl_pkey.h +245 -0
  41. data/ext/openssl/ossl_pkey_dh.c +650 -0
  42. data/ext/openssl/ossl_pkey_dsa.c +672 -0
  43. data/ext/openssl/ossl_pkey_ec.c +1899 -0
  44. data/ext/openssl/ossl_pkey_rsa.c +768 -0
  45. data/ext/openssl/ossl_rand.c +238 -0
  46. data/ext/openssl/ossl_rand.h +18 -0
  47. data/ext/openssl/ossl_ssl.c +2679 -0
  48. data/ext/openssl/ossl_ssl.h +41 -0
  49. data/ext/openssl/ossl_ssl_session.c +352 -0
  50. data/ext/openssl/ossl_version.h +15 -0
  51. data/ext/openssl/ossl_x509.c +186 -0
  52. data/ext/openssl/ossl_x509.h +119 -0
  53. data/ext/openssl/ossl_x509attr.c +328 -0
  54. data/ext/openssl/ossl_x509cert.c +860 -0
  55. data/ext/openssl/ossl_x509crl.c +565 -0
  56. data/ext/openssl/ossl_x509ext.c +480 -0
  57. data/ext/openssl/ossl_x509name.c +547 -0
  58. data/ext/openssl/ossl_x509req.c +492 -0
  59. data/ext/openssl/ossl_x509revoked.c +279 -0
  60. data/ext/openssl/ossl_x509store.c +846 -0
  61. data/ext/openssl/ruby_missing.h +32 -0
  62. data/lib/openssl.rb +21 -0
  63. data/lib/openssl/bn.rb +39 -0
  64. data/lib/openssl/buffering.rb +451 -0
  65. data/lib/openssl/cipher.rb +67 -0
  66. data/lib/openssl/config.rb +473 -0
  67. data/lib/openssl/digest.rb +78 -0
  68. data/lib/openssl/pkey.rb +44 -0
  69. data/lib/openssl/ssl.rb +416 -0
  70. data/lib/openssl/x509.rb +176 -0
  71. metadata +178 -0
@@ -0,0 +1,19 @@
1
+ /*
2
+ * 'OpenSSL for Ruby' project
3
+ * Copyright (C) 2003 Michal Rokos <m.rokos@sh.cvut.cz>
4
+ * Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
5
+ * All rights reserved.
6
+ */
7
+ /*
8
+ * This program is licensed under the same licence as Ruby.
9
+ * (See the file 'LICENCE'.)
10
+ */
11
+ #if !defined(OSSL_ENGINE_H)
12
+ #define OSSL_ENGINE_H
13
+
14
+ extern VALUE cEngine;
15
+ extern VALUE eEngineError;
16
+
17
+ void Init_ossl_engine(void);
18
+
19
+ #endif /* OSSL_ENGINE_H */
@@ -0,0 +1,398 @@
1
+ /*
2
+ * 'OpenSSL for Ruby' project
3
+ * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
4
+ * All rights reserved.
5
+ */
6
+ /*
7
+ * This program is licensed under the same licence as Ruby.
8
+ * (See the file 'LICENCE'.)
9
+ */
10
+ #if !defined(OPENSSL_NO_HMAC)
11
+
12
+ #include "ossl.h"
13
+
14
+ #define NewHMAC(klass) \
15
+ TypedData_Wrap_Struct((klass), &ossl_hmac_type, 0)
16
+ #define GetHMAC(obj, ctx) do { \
17
+ TypedData_Get_Struct((obj), HMAC_CTX, &ossl_hmac_type, (ctx)); \
18
+ if (!(ctx)) { \
19
+ ossl_raise(rb_eRuntimeError, "HMAC wasn't initialized"); \
20
+ } \
21
+ } while (0)
22
+ #define SafeGetHMAC(obj, ctx) do { \
23
+ OSSL_Check_Kind((obj), cHMAC); \
24
+ GetHMAC((obj), (ctx)); \
25
+ } while (0)
26
+
27
+ /*
28
+ * Classes
29
+ */
30
+ VALUE cHMAC;
31
+ VALUE eHMACError;
32
+
33
+ /*
34
+ * Public
35
+ */
36
+
37
+ /*
38
+ * Private
39
+ */
40
+ static void
41
+ ossl_hmac_free(void *ctx)
42
+ {
43
+ HMAC_CTX_free(ctx);
44
+ }
45
+
46
+ static const rb_data_type_t ossl_hmac_type = {
47
+ "OpenSSL/HMAC",
48
+ {
49
+ 0, ossl_hmac_free,
50
+ },
51
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
52
+ };
53
+
54
+ static VALUE
55
+ ossl_hmac_alloc(VALUE klass)
56
+ {
57
+ VALUE obj;
58
+ HMAC_CTX *ctx;
59
+
60
+ obj = NewHMAC(klass);
61
+ ctx = HMAC_CTX_new();
62
+ if (!ctx)
63
+ ossl_raise(eHMACError, NULL);
64
+ RTYPEDDATA_DATA(obj) = ctx;
65
+
66
+ return obj;
67
+ }
68
+
69
+
70
+ /*
71
+ * call-seq:
72
+ * HMAC.new(key, digest) -> hmac
73
+ *
74
+ * Returns an instance of OpenSSL::HMAC set with the key and digest
75
+ * algorithm to be used. The instance represents the initial state of
76
+ * the message authentication code before any data has been processed.
77
+ * To process data with it, use the instance method #update with your
78
+ * data as an argument.
79
+ *
80
+ * === Example
81
+ *
82
+ * key = 'key'
83
+ * digest = OpenSSL::Digest.new('sha1')
84
+ * instance = OpenSSL::HMAC.new(key, digest)
85
+ * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
86
+ * instance.class
87
+ * #=> OpenSSL::HMAC
88
+ *
89
+ * === A note about comparisons
90
+ *
91
+ * Two instances won't be equal when they're compared, even if they have the
92
+ * same value. Use #to_s or #hexdigest to return the authentication code that
93
+ * the instance represents. For example:
94
+ *
95
+ * other_instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1'))
96
+ * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
97
+ * instance
98
+ * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
99
+ * instance == other_instance
100
+ * #=> false
101
+ * instance.to_s == other_instance.to_s
102
+ * #=> true
103
+ *
104
+ */
105
+ static VALUE
106
+ ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
107
+ {
108
+ HMAC_CTX *ctx;
109
+
110
+ StringValue(key);
111
+ GetHMAC(self, ctx);
112
+ HMAC_Init_ex(ctx, RSTRING_PTR(key), RSTRING_LENINT(key),
113
+ GetDigestPtr(digest), NULL);
114
+
115
+ return self;
116
+ }
117
+
118
+ static VALUE
119
+ ossl_hmac_copy(VALUE self, VALUE other)
120
+ {
121
+ HMAC_CTX *ctx1, *ctx2;
122
+
123
+ rb_check_frozen(self);
124
+ if (self == other) return self;
125
+
126
+ GetHMAC(self, ctx1);
127
+ SafeGetHMAC(other, ctx2);
128
+
129
+ if (!HMAC_CTX_copy(ctx1, ctx2))
130
+ ossl_raise(eHMACError, "HMAC_CTX_copy");
131
+ return self;
132
+ }
133
+
134
+ /*
135
+ * call-seq:
136
+ * hmac.update(string) -> self
137
+ *
138
+ * Returns +self+ updated with the message to be authenticated.
139
+ * Can be called repeatedly with chunks of the message.
140
+ *
141
+ * === Example
142
+ *
143
+ * first_chunk = 'The quick brown fox jumps '
144
+ * second_chunk = 'over the lazy dog'
145
+ *
146
+ * instance.update(first_chunk)
147
+ * #=> 5b9a8038a65d571076d97fe783989e52278a492a
148
+ * instance.update(second_chunk)
149
+ * #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9
150
+ *
151
+ */
152
+ static VALUE
153
+ ossl_hmac_update(VALUE self, VALUE data)
154
+ {
155
+ HMAC_CTX *ctx;
156
+
157
+ StringValue(data);
158
+ GetHMAC(self, ctx);
159
+ HMAC_Update(ctx, (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data));
160
+
161
+ return self;
162
+ }
163
+
164
+ static void
165
+ hmac_final(HMAC_CTX *ctx, unsigned char *buf, unsigned int *buf_len)
166
+ {
167
+ HMAC_CTX *final;
168
+
169
+ final = HMAC_CTX_new();
170
+ if (!final)
171
+ ossl_raise(eHMACError, "HMAC_CTX_new");
172
+
173
+ if (!HMAC_CTX_copy(final, ctx)) {
174
+ HMAC_CTX_free(final);
175
+ ossl_raise(eHMACError, "HMAC_CTX_copy");
176
+ }
177
+
178
+ HMAC_Final(final, buf, buf_len);
179
+ HMAC_CTX_free(final);
180
+ }
181
+
182
+ /*
183
+ * call-seq:
184
+ * hmac.digest -> string
185
+ *
186
+ * Returns the authentication code an instance represents as a binary string.
187
+ *
188
+ * === Example
189
+ * instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1'))
190
+ * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
191
+ * instance.digest
192
+ * #=> "\xF4+\xB0\xEE\xB0\x18\xEB\xBDE\x97\xAEr\x13q\x1E\xC6\a`\x84?"
193
+ */
194
+ static VALUE
195
+ ossl_hmac_digest(VALUE self)
196
+ {
197
+ HMAC_CTX *ctx;
198
+ unsigned int buf_len;
199
+ VALUE ret;
200
+
201
+ GetHMAC(self, ctx);
202
+ ret = rb_str_new(NULL, EVP_MAX_MD_SIZE);
203
+ hmac_final(ctx, (unsigned char *)RSTRING_PTR(ret), &buf_len);
204
+ assert(buf_len <= EVP_MAX_MD_SIZE);
205
+ rb_str_set_len(ret, buf_len);
206
+
207
+ return ret;
208
+ }
209
+
210
+ /*
211
+ * call-seq:
212
+ * hmac.hexdigest -> string
213
+ *
214
+ * Returns the authentication code an instance represents as a hex-encoded
215
+ * string.
216
+ */
217
+ static VALUE
218
+ ossl_hmac_hexdigest(VALUE self)
219
+ {
220
+ HMAC_CTX *ctx;
221
+ unsigned char buf[EVP_MAX_MD_SIZE];
222
+ unsigned int buf_len;
223
+ VALUE ret;
224
+
225
+ GetHMAC(self, ctx);
226
+ hmac_final(ctx, buf, &buf_len);
227
+ ret = rb_str_new(NULL, buf_len * 2);
228
+ ossl_bin2hex(buf, RSTRING_PTR(ret), buf_len);
229
+
230
+ return ret;
231
+ }
232
+
233
+ /*
234
+ * call-seq:
235
+ * hmac.reset -> self
236
+ *
237
+ * Returns +self+ as it was when it was first initialized, with all processed
238
+ * data cleared from it.
239
+ *
240
+ * === Example
241
+ *
242
+ * data = "The quick brown fox jumps over the lazy dog"
243
+ * instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1'))
244
+ * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
245
+ *
246
+ * instance.update(data)
247
+ * #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9
248
+ * instance.reset
249
+ * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
250
+ *
251
+ */
252
+ static VALUE
253
+ ossl_hmac_reset(VALUE self)
254
+ {
255
+ HMAC_CTX *ctx;
256
+
257
+ GetHMAC(self, ctx);
258
+ HMAC_Init_ex(ctx, NULL, 0, NULL, NULL);
259
+
260
+ return self;
261
+ }
262
+
263
+ /*
264
+ * call-seq:
265
+ * HMAC.digest(digest, key, data) -> aString
266
+ *
267
+ * Returns the authentication code as a binary string. The +digest+ parameter
268
+ * must be an instance of OpenSSL::Digest.
269
+ *
270
+ * === Example
271
+ *
272
+ * key = 'key'
273
+ * data = 'The quick brown fox jumps over the lazy dog'
274
+ * digest = OpenSSL::Digest.new('sha1')
275
+ *
276
+ * hmac = OpenSSL::HMAC.digest(digest, key, data)
277
+ * #=> "\xDE|\x9B\x85\xB8\xB7\x8A\xA6\xBC\x8Az6\xF7\n\x90p\x1C\x9D\xB4\xD9"
278
+ *
279
+ */
280
+ static VALUE
281
+ ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
282
+ {
283
+ unsigned char *buf;
284
+ unsigned int buf_len;
285
+
286
+ StringValue(key);
287
+ StringValue(data);
288
+ buf = HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LENINT(key),
289
+ (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len);
290
+
291
+ return rb_str_new((const char *)buf, buf_len);
292
+ }
293
+
294
+ /*
295
+ * call-seq:
296
+ * HMAC.hexdigest(digest, key, data) -> aString
297
+ *
298
+ * Returns the authentication code as a hex-encoded string. The +digest+
299
+ * parameter must be an instance of OpenSSL::Digest.
300
+ *
301
+ * === Example
302
+ *
303
+ * key = 'key'
304
+ * data = 'The quick brown fox jumps over the lazy dog'
305
+ * digest = OpenSSL::Digest.new('sha1')
306
+ *
307
+ * hmac = OpenSSL::HMAC.hexdigest(digest, key, data)
308
+ * #=> "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"
309
+ *
310
+ */
311
+ static VALUE
312
+ ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
313
+ {
314
+ unsigned char buf[EVP_MAX_MD_SIZE];
315
+ unsigned int buf_len;
316
+ VALUE ret;
317
+
318
+ StringValue(key);
319
+ StringValue(data);
320
+
321
+ if (!HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LENINT(key),
322
+ (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data),
323
+ buf, &buf_len))
324
+ ossl_raise(eHMACError, "HMAC");
325
+
326
+ ret = rb_str_new(NULL, buf_len * 2);
327
+ ossl_bin2hex(buf, RSTRING_PTR(ret), buf_len);
328
+
329
+ return ret;
330
+ }
331
+
332
+ /*
333
+ * INIT
334
+ */
335
+ void
336
+ Init_ossl_hmac(void)
337
+ {
338
+ #if 0
339
+ mOSSL = rb_define_module("OpenSSL");
340
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
341
+ #endif
342
+
343
+ /*
344
+ * Document-class: OpenSSL::HMAC
345
+ *
346
+ * OpenSSL::HMAC allows computing Hash-based Message Authentication Code
347
+ * (HMAC). It is a type of message authentication code (MAC) involving a
348
+ * hash function in combination with a key. HMAC can be used to verify the
349
+ * integrity of a message as well as the authenticity.
350
+ *
351
+ * OpenSSL::HMAC has a similar interface to OpenSSL::Digest.
352
+ *
353
+ * === HMAC-SHA256 using one-shot interface
354
+ *
355
+ * key = "key"
356
+ * data = "message-to-be-authenticated"
357
+ * mac = OpenSSL::HMAC.hexdigest("SHA256", key, data)
358
+ * #=> "cddb0db23f469c8bf072b21fd837149bd6ace9ab771cceef14c9e517cc93282e"
359
+ *
360
+ * === HMAC-SHA256 using incremental interface
361
+ *
362
+ * data1 = File.read("file1")
363
+ * data2 = File.read("file2")
364
+ * key = "key"
365
+ * digest = OpenSSL::Digest::SHA256.new
366
+ * hmac = OpenSSL::HMAC.new(key, digest)
367
+ * hmac << data1
368
+ * hmac << data2
369
+ * mac = hmac.digest
370
+ */
371
+ eHMACError = rb_define_class_under(mOSSL, "HMACError", eOSSLError);
372
+
373
+ cHMAC = rb_define_class_under(mOSSL, "HMAC", rb_cObject);
374
+
375
+ rb_define_alloc_func(cHMAC, ossl_hmac_alloc);
376
+ rb_define_singleton_method(cHMAC, "digest", ossl_hmac_s_digest, 3);
377
+ rb_define_singleton_method(cHMAC, "hexdigest", ossl_hmac_s_hexdigest, 3);
378
+
379
+ rb_define_method(cHMAC, "initialize", ossl_hmac_initialize, 2);
380
+ rb_define_copy_func(cHMAC, ossl_hmac_copy);
381
+
382
+ rb_define_method(cHMAC, "reset", ossl_hmac_reset, 0);
383
+ rb_define_method(cHMAC, "update", ossl_hmac_update, 1);
384
+ rb_define_alias(cHMAC, "<<", "update");
385
+ rb_define_method(cHMAC, "digest", ossl_hmac_digest, 0);
386
+ rb_define_method(cHMAC, "hexdigest", ossl_hmac_hexdigest, 0);
387
+ rb_define_alias(cHMAC, "inspect", "hexdigest");
388
+ rb_define_alias(cHMAC, "to_s", "hexdigest");
389
+ }
390
+
391
+ #else /* NO_HMAC */
392
+ # warning >>> OpenSSL is compiled without HMAC support <<<
393
+ void
394
+ Init_ossl_hmac(void)
395
+ {
396
+ rb_warning("HMAC is not available: OpenSSL is compiled without HMAC.");
397
+ }
398
+ #endif /* NO_HMAC */
@@ -0,0 +1,18 @@
1
+ /*
2
+ * 'OpenSSL for Ruby' project
3
+ * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
4
+ * All rights reserved.
5
+ */
6
+ /*
7
+ * This program is licensed under the same licence as Ruby.
8
+ * (See the file 'LICENCE'.)
9
+ */
10
+ #if !defined(_OSSL_HMAC_H_)
11
+ #define _OSSL_HMAC_H_
12
+
13
+ extern VALUE cHMAC;
14
+ extern VALUE eHMACError;
15
+
16
+ void Init_ossl_hmac(void);
17
+
18
+ #endif /* _OSSL_HMAC_H_ */
@@ -0,0 +1,406 @@
1
+ /*
2
+ * 'OpenSSL for Ruby' project
3
+ * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
4
+ * All rights reserved.
5
+ */
6
+ /*
7
+ * This program is licensed under the same licence as Ruby.
8
+ * (See the file 'LICENCE'.)
9
+ */
10
+ #include "ossl.h"
11
+
12
+ #define NewSPKI(klass) \
13
+ TypedData_Wrap_Struct((klass), &ossl_netscape_spki_type, 0)
14
+ #define SetSPKI(obj, spki) do { \
15
+ if (!(spki)) { \
16
+ ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \
17
+ } \
18
+ RTYPEDDATA_DATA(obj) = (spki); \
19
+ } while (0)
20
+ #define GetSPKI(obj, spki) do { \
21
+ TypedData_Get_Struct((obj), NETSCAPE_SPKI, &ossl_netscape_spki_type, (spki)); \
22
+ if (!(spki)) { \
23
+ ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \
24
+ } \
25
+ } while (0)
26
+
27
+ /*
28
+ * Classes
29
+ */
30
+ VALUE mNetscape;
31
+ VALUE cSPKI;
32
+ VALUE eSPKIError;
33
+
34
+ /*
35
+ * Public functions
36
+ */
37
+
38
+ /*
39
+ * Private functions
40
+ */
41
+
42
+ static void
43
+ ossl_netscape_spki_free(void *spki)
44
+ {
45
+ NETSCAPE_SPKI_free(spki);
46
+ }
47
+
48
+ static const rb_data_type_t ossl_netscape_spki_type = {
49
+ "OpenSSL/NETSCAPE_SPKI",
50
+ {
51
+ 0, ossl_netscape_spki_free,
52
+ },
53
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
54
+ };
55
+
56
+ static VALUE
57
+ ossl_spki_alloc(VALUE klass)
58
+ {
59
+ NETSCAPE_SPKI *spki;
60
+ VALUE obj;
61
+
62
+ obj = NewSPKI(klass);
63
+ if (!(spki = NETSCAPE_SPKI_new())) {
64
+ ossl_raise(eSPKIError, NULL);
65
+ }
66
+ SetSPKI(obj, spki);
67
+
68
+ return obj;
69
+ }
70
+
71
+ /*
72
+ * call-seq:
73
+ * SPKI.new([request]) => spki
74
+ *
75
+ * === Parameters
76
+ * * +request+ - optional raw request, either in PEM or DER format.
77
+ */
78
+ static VALUE
79
+ ossl_spki_initialize(int argc, VALUE *argv, VALUE self)
80
+ {
81
+ NETSCAPE_SPKI *spki;
82
+ VALUE buffer;
83
+ const unsigned char *p;
84
+
85
+ if (rb_scan_args(argc, argv, "01", &buffer) == 0) {
86
+ return self;
87
+ }
88
+ StringValue(buffer);
89
+ if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING_PTR(buffer), RSTRING_LENINT(buffer)))) {
90
+ ossl_clear_error();
91
+ p = (unsigned char *)RSTRING_PTR(buffer);
92
+ if (!(spki = d2i_NETSCAPE_SPKI(NULL, &p, RSTRING_LEN(buffer)))) {
93
+ ossl_raise(eSPKIError, NULL);
94
+ }
95
+ }
96
+ NETSCAPE_SPKI_free(DATA_PTR(self));
97
+ SetSPKI(self, spki);
98
+
99
+ return self;
100
+ }
101
+
102
+ /*
103
+ * call-seq:
104
+ * spki.to_der => DER-encoded string
105
+ *
106
+ * Returns the DER encoding of this SPKI.
107
+ */
108
+ static VALUE
109
+ ossl_spki_to_der(VALUE self)
110
+ {
111
+ NETSCAPE_SPKI *spki;
112
+ VALUE str;
113
+ long len;
114
+ unsigned char *p;
115
+
116
+ GetSPKI(self, spki);
117
+ if ((len = i2d_NETSCAPE_SPKI(spki, NULL)) <= 0)
118
+ ossl_raise(eX509CertError, NULL);
119
+ str = rb_str_new(0, len);
120
+ p = (unsigned char *)RSTRING_PTR(str);
121
+ if (i2d_NETSCAPE_SPKI(spki, &p) <= 0)
122
+ ossl_raise(eX509CertError, NULL);
123
+ ossl_str_adjust(str, p);
124
+
125
+ return str;
126
+ }
127
+
128
+ /*
129
+ * call-seq:
130
+ * spki.to_pem => PEM-encoded string
131
+ *
132
+ * Returns the PEM encoding of this SPKI.
133
+ */
134
+ static VALUE
135
+ ossl_spki_to_pem(VALUE self)
136
+ {
137
+ NETSCAPE_SPKI *spki;
138
+ char *data;
139
+ VALUE str;
140
+
141
+ GetSPKI(self, spki);
142
+ if (!(data = NETSCAPE_SPKI_b64_encode(spki))) {
143
+ ossl_raise(eSPKIError, NULL);
144
+ }
145
+ str = ossl_buf2str(data, rb_long2int(strlen(data)));
146
+
147
+ return str;
148
+ }
149
+
150
+ /*
151
+ * call-seq:
152
+ * spki.to_text => string
153
+ *
154
+ * Returns a textual representation of this SPKI, useful for debugging
155
+ * purposes.
156
+ */
157
+ static VALUE
158
+ ossl_spki_print(VALUE self)
159
+ {
160
+ NETSCAPE_SPKI *spki;
161
+ BIO *out;
162
+ BUF_MEM *buf;
163
+ VALUE str;
164
+
165
+ GetSPKI(self, spki);
166
+ if (!(out = BIO_new(BIO_s_mem()))) {
167
+ ossl_raise(eSPKIError, NULL);
168
+ }
169
+ if (!NETSCAPE_SPKI_print(out, spki)) {
170
+ BIO_free(out);
171
+ ossl_raise(eSPKIError, NULL);
172
+ }
173
+ BIO_get_mem_ptr(out, &buf);
174
+ str = rb_str_new(buf->data, buf->length);
175
+ BIO_free(out);
176
+
177
+ return str;
178
+ }
179
+
180
+ /*
181
+ * call-seq:
182
+ * spki.public_key => pkey
183
+ *
184
+ * Returns the public key associated with the SPKI, an instance of
185
+ * OpenSSL::PKey.
186
+ */
187
+ static VALUE
188
+ ossl_spki_get_public_key(VALUE self)
189
+ {
190
+ NETSCAPE_SPKI *spki;
191
+ EVP_PKEY *pkey;
192
+
193
+ GetSPKI(self, spki);
194
+ if (!(pkey = NETSCAPE_SPKI_get_pubkey(spki))) { /* adds an reference */
195
+ ossl_raise(eSPKIError, NULL);
196
+ }
197
+
198
+ return ossl_pkey_new(pkey); /* NO DUP - OK */
199
+ }
200
+
201
+ /*
202
+ * call-seq:
203
+ * spki.public_key = pub => pkey
204
+ *
205
+ * === Parameters
206
+ * * +pub+ - the public key to be set for this instance
207
+ *
208
+ * Sets the public key to be associated with the SPKI, an instance of
209
+ * OpenSSL::PKey. This should be the public key corresponding to the
210
+ * private key used for signing the SPKI.
211
+ */
212
+ static VALUE
213
+ ossl_spki_set_public_key(VALUE self, VALUE key)
214
+ {
215
+ NETSCAPE_SPKI *spki;
216
+
217
+ GetSPKI(self, spki);
218
+ if (!NETSCAPE_SPKI_set_pubkey(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */
219
+ ossl_raise(eSPKIError, NULL);
220
+ }
221
+
222
+ return key;
223
+ }
224
+
225
+ /*
226
+ * call-seq:
227
+ * spki.challenge => string
228
+ *
229
+ * Returns the challenge string associated with this SPKI.
230
+ */
231
+ static VALUE
232
+ ossl_spki_get_challenge(VALUE self)
233
+ {
234
+ NETSCAPE_SPKI *spki;
235
+
236
+ GetSPKI(self, spki);
237
+ if (spki->spkac->challenge->length <= 0) {
238
+ OSSL_Debug("Challenge.length <= 0?");
239
+ return rb_str_new(0, 0);
240
+ }
241
+
242
+ return rb_str_new((const char *)spki->spkac->challenge->data,
243
+ spki->spkac->challenge->length);
244
+ }
245
+
246
+ /*
247
+ * call-seq:
248
+ * spki.challenge = str => string
249
+ *
250
+ * === Parameters
251
+ * * +str+ - the challenge string to be set for this instance
252
+ *
253
+ * Sets the challenge to be associated with the SPKI. May be used by the
254
+ * server, e.g. to prevent replay.
255
+ */
256
+ static VALUE
257
+ ossl_spki_set_challenge(VALUE self, VALUE str)
258
+ {
259
+ NETSCAPE_SPKI *spki;
260
+
261
+ StringValue(str);
262
+ GetSPKI(self, spki);
263
+ if (!ASN1_STRING_set(spki->spkac->challenge, RSTRING_PTR(str),
264
+ RSTRING_LENINT(str))) {
265
+ ossl_raise(eSPKIError, NULL);
266
+ }
267
+
268
+ return str;
269
+ }
270
+
271
+ /*
272
+ * call-seq:
273
+ * spki.sign(key, digest) => spki
274
+ *
275
+ * === Parameters
276
+ * * +key+ - the private key to be used for signing this instance
277
+ * * +digest+ - the digest to be used for signing this instance
278
+ *
279
+ * To sign an SPKI, the private key corresponding to the public key set
280
+ * for this instance should be used, in addition to a digest algorithm in
281
+ * the form of an OpenSSL::Digest. The private key should be an instance of
282
+ * OpenSSL::PKey.
283
+ */
284
+ static VALUE
285
+ ossl_spki_sign(VALUE self, VALUE key, VALUE digest)
286
+ {
287
+ NETSCAPE_SPKI *spki;
288
+ EVP_PKEY *pkey;
289
+ const EVP_MD *md;
290
+
291
+ pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
292
+ md = GetDigestPtr(digest);
293
+ GetSPKI(self, spki);
294
+ if (!NETSCAPE_SPKI_sign(spki, pkey, md)) {
295
+ ossl_raise(eSPKIError, NULL);
296
+ }
297
+
298
+ return self;
299
+ }
300
+
301
+ /*
302
+ * call-seq:
303
+ * spki.verify(key) => boolean
304
+ *
305
+ * === Parameters
306
+ * * +key+ - the public key to be used for verifying the SPKI signature
307
+ *
308
+ * Returns +true+ if the signature is valid, +false+ otherwise. To verify an
309
+ * SPKI, the public key contained within the SPKI should be used.
310
+ */
311
+ static VALUE
312
+ ossl_spki_verify(VALUE self, VALUE key)
313
+ {
314
+ NETSCAPE_SPKI *spki;
315
+
316
+ GetSPKI(self, spki);
317
+ switch (NETSCAPE_SPKI_verify(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */
318
+ case 0:
319
+ return Qfalse;
320
+ case 1:
321
+ return Qtrue;
322
+ default:
323
+ ossl_raise(eSPKIError, NULL);
324
+ }
325
+ return Qnil; /* dummy */
326
+ }
327
+
328
+ /* Document-class: OpenSSL::Netscape::SPKI
329
+ *
330
+ * A Simple Public Key Infrastructure implementation (pronounced "spookey").
331
+ * The structure is defined as
332
+ * PublicKeyAndChallenge ::= SEQUENCE {
333
+ * spki SubjectPublicKeyInfo,
334
+ * challenge IA5STRING
335
+ * }
336
+ *
337
+ * SignedPublicKeyAndChallenge ::= SEQUENCE {
338
+ * publicKeyAndChallenge PublicKeyAndChallenge,
339
+ * signatureAlgorithm AlgorithmIdentifier,
340
+ * signature BIT STRING
341
+ * }
342
+ * where the definitions of SubjectPublicKeyInfo and AlgorithmIdentifier can
343
+ * be found in RFC5280. SPKI is typically used in browsers for generating
344
+ * a public/private key pair and a subsequent certificate request, using
345
+ * the HTML <keygen> element.
346
+ *
347
+ * == Examples
348
+ *
349
+ * === Creating an SPKI
350
+ * key = OpenSSL::PKey::RSA.new 2048
351
+ * spki = OpenSSL::Netscape::SPKI.new
352
+ * spki.challenge = "RandomChallenge"
353
+ * spki.public_key = key.public_key
354
+ * spki.sign(key, OpenSSL::Digest::SHA256.new)
355
+ * #send a request containing this to a server generating a certificate
356
+ * === Verifiying an SPKI request
357
+ * request = #...
358
+ * spki = OpenSSL::Netscape::SPKI.new request
359
+ * unless spki.verify(spki.public_key)
360
+ * # signature is invalid
361
+ * end
362
+ * #proceed
363
+ */
364
+
365
+ /* Document-module: OpenSSL::Netscape
366
+ *
367
+ * OpenSSL::Netscape is a namespace for SPKI (Simple Public Key
368
+ * Infrastructure) which implements Signed Public Key and Challenge.
369
+ * See {RFC 2692}[http://tools.ietf.org/html/rfc2692] and {RFC
370
+ * 2693}[http://tools.ietf.org/html/rfc2692] for details.
371
+ */
372
+
373
+ /* Document-class: OpenSSL::Netscape::SPKIError
374
+ *
375
+ * Generic Exception class that is raised if an error occurs during an
376
+ * operation on an instance of OpenSSL::Netscape::SPKI.
377
+ */
378
+
379
+ void
380
+ Init_ossl_ns_spki(void)
381
+ {
382
+ #if 0
383
+ mOSSL = rb_define_module("OpenSSL");
384
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
385
+ #endif
386
+
387
+ mNetscape = rb_define_module_under(mOSSL, "Netscape");
388
+
389
+ eSPKIError = rb_define_class_under(mNetscape, "SPKIError", eOSSLError);
390
+
391
+ cSPKI = rb_define_class_under(mNetscape, "SPKI", rb_cObject);
392
+
393
+ rb_define_alloc_func(cSPKI, ossl_spki_alloc);
394
+ rb_define_method(cSPKI, "initialize", ossl_spki_initialize, -1);
395
+
396
+ rb_define_method(cSPKI, "to_der", ossl_spki_to_der, 0);
397
+ rb_define_method(cSPKI, "to_pem", ossl_spki_to_pem, 0);
398
+ rb_define_alias(cSPKI, "to_s", "to_pem");
399
+ rb_define_method(cSPKI, "to_text", ossl_spki_print, 0);
400
+ rb_define_method(cSPKI, "public_key", ossl_spki_get_public_key, 0);
401
+ rb_define_method(cSPKI, "public_key=", ossl_spki_set_public_key, 1);
402
+ rb_define_method(cSPKI, "sign", ossl_spki_sign, 2);
403
+ rb_define_method(cSPKI, "verify", ossl_spki_verify, 1);
404
+ rb_define_method(cSPKI, "challenge", ossl_spki_get_challenge, 0);
405
+ rb_define_method(cSPKI, "challenge=", ossl_spki_set_challenge, 1);
406
+ }