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,672 @@
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
+ #if !defined(OPENSSL_NO_DSA)
13
+
14
+ #define GetPKeyDSA(obj, pkey) do { \
15
+ GetPKey((obj), (pkey)); \
16
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DSA) { /* PARANOIA? */ \
17
+ ossl_raise(rb_eRuntimeError, "THIS IS NOT A DSA!"); \
18
+ } \
19
+ } while (0)
20
+ #define GetDSA(obj, dsa) do { \
21
+ EVP_PKEY *_pkey; \
22
+ GetPKeyDSA((obj), _pkey); \
23
+ (dsa) = EVP_PKEY_get0_DSA(_pkey); \
24
+ } while (0)
25
+
26
+ static inline int
27
+ DSA_HAS_PRIVATE(DSA *dsa)
28
+ {
29
+ const BIGNUM *bn;
30
+ DSA_get0_key(dsa, NULL, &bn);
31
+ return !!bn;
32
+ }
33
+
34
+ static inline int
35
+ DSA_PRIVATE(VALUE obj, DSA *dsa)
36
+ {
37
+ return DSA_HAS_PRIVATE(dsa) || OSSL_PKEY_IS_PRIVATE(obj);
38
+ }
39
+
40
+ /*
41
+ * Classes
42
+ */
43
+ VALUE cDSA;
44
+ VALUE eDSAError;
45
+
46
+ /*
47
+ * Public
48
+ */
49
+ static VALUE
50
+ dsa_instance(VALUE klass, DSA *dsa)
51
+ {
52
+ EVP_PKEY *pkey;
53
+ VALUE obj;
54
+
55
+ if (!dsa) {
56
+ return Qfalse;
57
+ }
58
+ obj = NewPKey(klass);
59
+ if (!(pkey = EVP_PKEY_new())) {
60
+ return Qfalse;
61
+ }
62
+ if (!EVP_PKEY_assign_DSA(pkey, dsa)) {
63
+ EVP_PKEY_free(pkey);
64
+ return Qfalse;
65
+ }
66
+ SetPKey(obj, pkey);
67
+
68
+ return obj;
69
+ }
70
+
71
+ VALUE
72
+ ossl_dsa_new(EVP_PKEY *pkey)
73
+ {
74
+ VALUE obj;
75
+
76
+ if (!pkey) {
77
+ obj = dsa_instance(cDSA, DSA_new());
78
+ } else {
79
+ obj = NewPKey(cDSA);
80
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DSA) {
81
+ ossl_raise(rb_eTypeError, "Not a DSA key!");
82
+ }
83
+ SetPKey(obj, pkey);
84
+ }
85
+ if (obj == Qfalse) {
86
+ ossl_raise(eDSAError, NULL);
87
+ }
88
+
89
+ return obj;
90
+ }
91
+
92
+ /*
93
+ * Private
94
+ */
95
+ struct dsa_blocking_gen_arg {
96
+ DSA *dsa;
97
+ int size;
98
+ int *counter;
99
+ unsigned long *h;
100
+ BN_GENCB *cb;
101
+ int result;
102
+ };
103
+
104
+ static void *
105
+ dsa_blocking_gen(void *arg)
106
+ {
107
+ struct dsa_blocking_gen_arg *gen = (struct dsa_blocking_gen_arg *)arg;
108
+ gen->result = DSA_generate_parameters_ex(gen->dsa, gen->size, NULL, 0,
109
+ gen->counter, gen->h, gen->cb);
110
+ return 0;
111
+ }
112
+
113
+ static DSA *
114
+ dsa_generate(int size)
115
+ {
116
+ struct ossl_generate_cb_arg cb_arg = { 0 };
117
+ struct dsa_blocking_gen_arg gen_arg;
118
+ DSA *dsa = DSA_new();
119
+ BN_GENCB *cb = BN_GENCB_new();
120
+ int counter;
121
+ unsigned long h;
122
+
123
+ if (!dsa || !cb) {
124
+ DSA_free(dsa);
125
+ BN_GENCB_free(cb);
126
+ return NULL;
127
+ }
128
+
129
+ if (rb_block_given_p())
130
+ cb_arg.yield = 1;
131
+ BN_GENCB_set(cb, ossl_generate_cb_2, &cb_arg);
132
+ gen_arg.dsa = dsa;
133
+ gen_arg.size = size;
134
+ gen_arg.counter = &counter;
135
+ gen_arg.h = &h;
136
+ gen_arg.cb = cb;
137
+ if (cb_arg.yield == 1) {
138
+ /* we cannot release GVL when callback proc is supplied */
139
+ dsa_blocking_gen(&gen_arg);
140
+ } else {
141
+ /* there's a chance to unblock */
142
+ rb_thread_call_without_gvl(dsa_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg);
143
+ }
144
+
145
+ BN_GENCB_free(cb);
146
+ if (!gen_arg.result) {
147
+ DSA_free(dsa);
148
+ if (cb_arg.state) {
149
+ /* Clear OpenSSL error queue before re-raising. By the way, the
150
+ * documentation of DSA_generate_parameters_ex() says the error code
151
+ * can be obtained by ERR_get_error(), but the default
152
+ * implementation, dsa_builtin_paramgen() doesn't put any error... */
153
+ ossl_clear_error();
154
+ rb_jump_tag(cb_arg.state);
155
+ }
156
+ return NULL;
157
+ }
158
+
159
+ if (!DSA_generate_key(dsa)) {
160
+ DSA_free(dsa);
161
+ return NULL;
162
+ }
163
+
164
+ return dsa;
165
+ }
166
+
167
+ /*
168
+ * call-seq:
169
+ * DSA.generate(size) -> dsa
170
+ *
171
+ * Creates a new DSA instance by generating a private/public key pair
172
+ * from scratch.
173
+ *
174
+ * === Parameters
175
+ * * +size+ is an integer representing the desired key size.
176
+ *
177
+ */
178
+ static VALUE
179
+ ossl_dsa_s_generate(VALUE klass, VALUE size)
180
+ {
181
+ DSA *dsa = dsa_generate(NUM2INT(size)); /* err handled by dsa_instance */
182
+ VALUE obj = dsa_instance(klass, dsa);
183
+
184
+ if (obj == Qfalse) {
185
+ DSA_free(dsa);
186
+ ossl_raise(eDSAError, NULL);
187
+ }
188
+
189
+ return obj;
190
+ }
191
+
192
+ /*
193
+ * call-seq:
194
+ * DSA.new -> dsa
195
+ * DSA.new(size) -> dsa
196
+ * DSA.new(string [, pass]) -> dsa
197
+ *
198
+ * Creates a new DSA instance by reading an existing key from +string+.
199
+ *
200
+ * === Parameters
201
+ * * +size+ is an integer representing the desired key size.
202
+ * * +string+ contains a DER or PEM encoded key.
203
+ * * +pass+ is a string that contains an optional password.
204
+ *
205
+ * === Examples
206
+ * DSA.new -> dsa
207
+ * DSA.new(1024) -> dsa
208
+ * DSA.new(File.read('dsa.pem')) -> dsa
209
+ * DSA.new(File.read('dsa.pem'), 'mypassword') -> dsa
210
+ *
211
+ */
212
+ static VALUE
213
+ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
214
+ {
215
+ EVP_PKEY *pkey;
216
+ DSA *dsa;
217
+ BIO *in;
218
+ VALUE arg, pass;
219
+
220
+ GetPKey(self, pkey);
221
+ if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
222
+ dsa = DSA_new();
223
+ }
224
+ else if (RB_INTEGER_TYPE_P(arg)) {
225
+ if (!(dsa = dsa_generate(NUM2INT(arg)))) {
226
+ ossl_raise(eDSAError, NULL);
227
+ }
228
+ }
229
+ else {
230
+ pass = ossl_pem_passwd_value(pass);
231
+ arg = ossl_to_der_if_possible(arg);
232
+ in = ossl_obj2bio(arg);
233
+ dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass);
234
+ if (!dsa) {
235
+ OSSL_BIO_reset(in);
236
+ dsa = PEM_read_bio_DSA_PUBKEY(in, NULL, NULL, NULL);
237
+ }
238
+ if (!dsa) {
239
+ OSSL_BIO_reset(in);
240
+ dsa = d2i_DSAPrivateKey_bio(in, NULL);
241
+ }
242
+ if (!dsa) {
243
+ OSSL_BIO_reset(in);
244
+ dsa = d2i_DSA_PUBKEY_bio(in, NULL);
245
+ }
246
+ if (!dsa) {
247
+ OSSL_BIO_reset(in);
248
+ #define PEM_read_bio_DSAPublicKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
249
+ (d2i_of_void *)d2i_DSAPublicKey, PEM_STRING_DSA_PUBLIC, (bp), (void **)(x), (cb), (u))
250
+ dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL);
251
+ #undef PEM_read_bio_DSAPublicKey
252
+ }
253
+ BIO_free(in);
254
+ if (!dsa) {
255
+ ossl_clear_error();
256
+ ossl_raise(eDSAError, "Neither PUB key nor PRIV key");
257
+ }
258
+ }
259
+ if (!EVP_PKEY_assign_DSA(pkey, dsa)) {
260
+ DSA_free(dsa);
261
+ ossl_raise(eDSAError, NULL);
262
+ }
263
+
264
+ return self;
265
+ }
266
+
267
+ static VALUE
268
+ ossl_dsa_initialize_copy(VALUE self, VALUE other)
269
+ {
270
+ EVP_PKEY *pkey;
271
+ DSA *dsa, *dsa_new;
272
+
273
+ GetPKey(self, pkey);
274
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
275
+ ossl_raise(eDSAError, "DSA already initialized");
276
+ GetDSA(other, dsa);
277
+
278
+ dsa_new = ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey, (d2i_of_void *)d2i_DSAPrivateKey, (char *)dsa);
279
+ if (!dsa_new)
280
+ ossl_raise(eDSAError, "ASN1_dup");
281
+
282
+ EVP_PKEY_assign_DSA(pkey, dsa_new);
283
+
284
+ return self;
285
+ }
286
+
287
+ /*
288
+ * call-seq:
289
+ * dsa.public? -> true | false
290
+ *
291
+ * Indicates whether this DSA instance has a public key associated with it or
292
+ * not. The public key may be retrieved with DSA#public_key.
293
+ */
294
+ static VALUE
295
+ ossl_dsa_is_public(VALUE self)
296
+ {
297
+ DSA *dsa;
298
+ const BIGNUM *bn;
299
+
300
+ GetDSA(self, dsa);
301
+ DSA_get0_key(dsa, &bn, NULL);
302
+
303
+ return bn ? Qtrue : Qfalse;
304
+ }
305
+
306
+ /*
307
+ * call-seq:
308
+ * dsa.private? -> true | false
309
+ *
310
+ * Indicates whether this DSA instance has a private key associated with it or
311
+ * not. The private key may be retrieved with DSA#private_key.
312
+ */
313
+ static VALUE
314
+ ossl_dsa_is_private(VALUE self)
315
+ {
316
+ DSA *dsa;
317
+
318
+ GetDSA(self, dsa);
319
+
320
+ return DSA_PRIVATE(self, dsa) ? Qtrue : Qfalse;
321
+ }
322
+
323
+ /*
324
+ * call-seq:
325
+ * dsa.export([cipher, password]) -> aString
326
+ * dsa.to_pem([cipher, password]) -> aString
327
+ * dsa.to_s([cipher, password]) -> aString
328
+ *
329
+ * Encodes this DSA to its PEM encoding.
330
+ *
331
+ * === Parameters
332
+ * * +cipher+ is an OpenSSL::Cipher.
333
+ * * +password+ is a string containing your password.
334
+ *
335
+ * === Examples
336
+ * DSA.to_pem -> aString
337
+ * DSA.to_pem(cipher, 'mypassword') -> aString
338
+ *
339
+ */
340
+ static VALUE
341
+ ossl_dsa_export(int argc, VALUE *argv, VALUE self)
342
+ {
343
+ DSA *dsa;
344
+ BIO *out;
345
+ const EVP_CIPHER *ciph = NULL;
346
+ VALUE cipher, pass, str;
347
+
348
+ GetDSA(self, dsa);
349
+ rb_scan_args(argc, argv, "02", &cipher, &pass);
350
+ if (!NIL_P(cipher)) {
351
+ ciph = GetCipherPtr(cipher);
352
+ pass = ossl_pem_passwd_value(pass);
353
+ }
354
+ if (!(out = BIO_new(BIO_s_mem()))) {
355
+ ossl_raise(eDSAError, NULL);
356
+ }
357
+ if (DSA_HAS_PRIVATE(dsa)) {
358
+ if (!PEM_write_bio_DSAPrivateKey(out, dsa, ciph, NULL, 0,
359
+ ossl_pem_passwd_cb, (void *)pass)){
360
+ BIO_free(out);
361
+ ossl_raise(eDSAError, NULL);
362
+ }
363
+ } else {
364
+ if (!PEM_write_bio_DSA_PUBKEY(out, dsa)) {
365
+ BIO_free(out);
366
+ ossl_raise(eDSAError, NULL);
367
+ }
368
+ }
369
+ str = ossl_membio2str(out);
370
+
371
+ return str;
372
+ }
373
+
374
+ /*
375
+ * call-seq:
376
+ * dsa.to_der -> aString
377
+ *
378
+ * Encodes this DSA to its DER encoding.
379
+ *
380
+ */
381
+ static VALUE
382
+ ossl_dsa_to_der(VALUE self)
383
+ {
384
+ DSA *dsa;
385
+ int (*i2d_func)(DSA *, unsigned char **);
386
+ unsigned char *p;
387
+ long len;
388
+ VALUE str;
389
+
390
+ GetDSA(self, dsa);
391
+ if(DSA_HAS_PRIVATE(dsa))
392
+ i2d_func = (int (*)(DSA *,unsigned char **))i2d_DSAPrivateKey;
393
+ else
394
+ i2d_func = i2d_DSA_PUBKEY;
395
+ if((len = i2d_func(dsa, NULL)) <= 0)
396
+ ossl_raise(eDSAError, NULL);
397
+ str = rb_str_new(0, len);
398
+ p = (unsigned char *)RSTRING_PTR(str);
399
+ if(i2d_func(dsa, &p) < 0)
400
+ ossl_raise(eDSAError, NULL);
401
+ ossl_str_adjust(str, p);
402
+
403
+ return str;
404
+ }
405
+
406
+
407
+ /*
408
+ * call-seq:
409
+ * dsa.params -> hash
410
+ *
411
+ * Stores all parameters of key to the hash
412
+ * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
413
+ * Don't use :-)) (I's up to you)
414
+ */
415
+ static VALUE
416
+ ossl_dsa_get_params(VALUE self)
417
+ {
418
+ DSA *dsa;
419
+ VALUE hash;
420
+ const BIGNUM *p, *q, *g, *pub_key, *priv_key;
421
+
422
+ GetDSA(self, dsa);
423
+ DSA_get0_pqg(dsa, &p, &q, &g);
424
+ DSA_get0_key(dsa, &pub_key, &priv_key);
425
+
426
+ hash = rb_hash_new();
427
+ rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(p));
428
+ rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(q));
429
+ rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(g));
430
+ rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pub_key));
431
+ rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(priv_key));
432
+
433
+ return hash;
434
+ }
435
+
436
+ /*
437
+ * call-seq:
438
+ * dsa.to_text -> aString
439
+ *
440
+ * Prints all parameters of key to buffer
441
+ * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
442
+ * Don't use :-)) (I's up to you)
443
+ */
444
+ static VALUE
445
+ ossl_dsa_to_text(VALUE self)
446
+ {
447
+ DSA *dsa;
448
+ BIO *out;
449
+ VALUE str;
450
+
451
+ GetDSA(self, dsa);
452
+ if (!(out = BIO_new(BIO_s_mem()))) {
453
+ ossl_raise(eDSAError, NULL);
454
+ }
455
+ if (!DSA_print(out, dsa, 0)) { /* offset = 0 */
456
+ BIO_free(out);
457
+ ossl_raise(eDSAError, NULL);
458
+ }
459
+ str = ossl_membio2str(out);
460
+
461
+ return str;
462
+ }
463
+
464
+ /*
465
+ * call-seq:
466
+ * dsa.public_key -> aDSA
467
+ *
468
+ * Returns a new DSA instance that carries just the public key information.
469
+ * If the current instance has also private key information, this will no
470
+ * longer be present in the new instance. This feature is helpful for
471
+ * publishing the public key information without leaking any of the private
472
+ * information.
473
+ *
474
+ * === Example
475
+ * dsa = OpenSSL::PKey::DSA.new(2048) # has public and private information
476
+ * pub_key = dsa.public_key # has only the public part available
477
+ * pub_key_der = pub_key.to_der # it's safe to publish this
478
+ *
479
+ *
480
+ */
481
+ static VALUE
482
+ ossl_dsa_to_public_key(VALUE self)
483
+ {
484
+ EVP_PKEY *pkey;
485
+ DSA *dsa;
486
+ VALUE obj;
487
+
488
+ GetPKeyDSA(self, pkey);
489
+ /* err check performed by dsa_instance */
490
+ #define DSAPublicKey_dup(dsa) (DSA *)ASN1_dup( \
491
+ (i2d_of_void *)i2d_DSAPublicKey, (d2i_of_void *)d2i_DSAPublicKey, (char *)(dsa))
492
+ dsa = DSAPublicKey_dup(EVP_PKEY_get0_DSA(pkey));
493
+ #undef DSAPublicKey_dup
494
+ obj = dsa_instance(CLASS_OF(self), dsa);
495
+ if (obj == Qfalse) {
496
+ DSA_free(dsa);
497
+ ossl_raise(eDSAError, NULL);
498
+ }
499
+ return obj;
500
+ }
501
+
502
+ #define ossl_dsa_buf_size(dsa) (DSA_size(dsa) + 16)
503
+
504
+ /*
505
+ * call-seq:
506
+ * dsa.syssign(string) -> aString
507
+ *
508
+ * Computes and returns the DSA signature of +string+, where +string+ is
509
+ * expected to be an already-computed message digest of the original input
510
+ * data. The signature is issued using the private key of this DSA instance.
511
+ *
512
+ * === Parameters
513
+ * * +string+ is a message digest of the original input data to be signed
514
+ *
515
+ * === Example
516
+ * dsa = OpenSSL::PKey::DSA.new(2048)
517
+ * doc = "Sign me"
518
+ * digest = OpenSSL::Digest::SHA1.digest(doc)
519
+ * sig = dsa.syssign(digest)
520
+ *
521
+ *
522
+ */
523
+ static VALUE
524
+ ossl_dsa_sign(VALUE self, VALUE data)
525
+ {
526
+ DSA *dsa;
527
+ const BIGNUM *dsa_q;
528
+ unsigned int buf_len;
529
+ VALUE str;
530
+
531
+ GetDSA(self, dsa);
532
+ DSA_get0_pqg(dsa, NULL, &dsa_q, NULL);
533
+ if (!dsa_q)
534
+ ossl_raise(eDSAError, "incomplete DSA");
535
+ if (!DSA_PRIVATE(self, dsa))
536
+ ossl_raise(eDSAError, "Private DSA key needed!");
537
+ StringValue(data);
538
+ str = rb_str_new(0, ossl_dsa_buf_size(dsa));
539
+ if (!DSA_sign(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data),
540
+ (unsigned char *)RSTRING_PTR(str),
541
+ &buf_len, dsa)) { /* type is ignored (0) */
542
+ ossl_raise(eDSAError, NULL);
543
+ }
544
+ rb_str_set_len(str, buf_len);
545
+
546
+ return str;
547
+ }
548
+
549
+ /*
550
+ * call-seq:
551
+ * dsa.sysverify(digest, sig) -> true | false
552
+ *
553
+ * Verifies whether the signature is valid given the message digest input. It
554
+ * does so by validating +sig+ using the public key of this DSA instance.
555
+ *
556
+ * === Parameters
557
+ * * +digest+ is a message digest of the original input data to be signed
558
+ * * +sig+ is a DSA signature value
559
+ *
560
+ * === Example
561
+ * dsa = OpenSSL::PKey::DSA.new(2048)
562
+ * doc = "Sign me"
563
+ * digest = OpenSSL::Digest::SHA1.digest(doc)
564
+ * sig = dsa.syssign(digest)
565
+ * puts dsa.sysverify(digest, sig) # => true
566
+ *
567
+ */
568
+ static VALUE
569
+ ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
570
+ {
571
+ DSA *dsa;
572
+ int ret;
573
+
574
+ GetDSA(self, dsa);
575
+ StringValue(digest);
576
+ StringValue(sig);
577
+ /* type is ignored (0) */
578
+ ret = DSA_verify(0, (unsigned char *)RSTRING_PTR(digest), RSTRING_LENINT(digest),
579
+ (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), dsa);
580
+ if (ret < 0) {
581
+ ossl_raise(eDSAError, NULL);
582
+ }
583
+ else if (ret == 1) {
584
+ return Qtrue;
585
+ }
586
+
587
+ return Qfalse;
588
+ }
589
+
590
+ /*
591
+ * Document-method: OpenSSL::PKey::DSA#set_pqg
592
+ * call-seq:
593
+ * dsa.set_pqg(p, q, g) -> self
594
+ *
595
+ * Sets +p+, +q+, +g+ for the DSA instance.
596
+ */
597
+ OSSL_PKEY_BN_DEF3(dsa, DSA, pqg, p, q, g)
598
+ /*
599
+ * Document-method: OpenSSL::PKey::DSA#set_key
600
+ * call-seq:
601
+ * dsa.set_key(pub_key, priv_key) -> self
602
+ *
603
+ * Sets +pub_key+ and +priv_key+ for the DSA instance. +priv_key+ may be nil.
604
+ */
605
+ OSSL_PKEY_BN_DEF2(dsa, DSA, key, pub_key, priv_key)
606
+
607
+ /*
608
+ * INIT
609
+ */
610
+ void
611
+ Init_ossl_dsa(void)
612
+ {
613
+ #if 0
614
+ mPKey = rb_define_module_under(mOSSL, "PKey");
615
+ cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
616
+ ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
617
+ #endif
618
+
619
+ /* Document-class: OpenSSL::PKey::DSAError
620
+ *
621
+ * Generic exception that is raised if an operation on a DSA PKey
622
+ * fails unexpectedly or in case an instantiation of an instance of DSA
623
+ * fails due to non-conformant input data.
624
+ */
625
+ eDSAError = rb_define_class_under(mPKey, "DSAError", ePKeyError);
626
+
627
+ /* Document-class: OpenSSL::PKey::DSA
628
+ *
629
+ * DSA, the Digital Signature Algorithm, is specified in NIST's
630
+ * FIPS 186-3. It is an asymmetric public key algorithm that may be used
631
+ * similar to e.g. RSA.
632
+ * Please note that for OpenSSL versions prior to 1.0.0 the digest
633
+ * algorithms OpenSSL::Digest::DSS (equivalent to SHA) or
634
+ * OpenSSL::Digest::DSS1 (equivalent to SHA-1) must be used for issuing
635
+ * signatures with a DSA key using OpenSSL::PKey#sign.
636
+ * Starting with OpenSSL 1.0.0, digest algorithms are no longer restricted,
637
+ * any Digest may be used for signing.
638
+ */
639
+ cDSA = rb_define_class_under(mPKey, "DSA", cPKey);
640
+
641
+ rb_define_singleton_method(cDSA, "generate", ossl_dsa_s_generate, 1);
642
+ rb_define_method(cDSA, "initialize", ossl_dsa_initialize, -1);
643
+ rb_define_copy_func(cDSA, ossl_dsa_initialize_copy);
644
+
645
+ rb_define_method(cDSA, "public?", ossl_dsa_is_public, 0);
646
+ rb_define_method(cDSA, "private?", ossl_dsa_is_private, 0);
647
+ rb_define_method(cDSA, "to_text", ossl_dsa_to_text, 0);
648
+ rb_define_method(cDSA, "export", ossl_dsa_export, -1);
649
+ rb_define_alias(cDSA, "to_pem", "export");
650
+ rb_define_alias(cDSA, "to_s", "export");
651
+ rb_define_method(cDSA, "to_der", ossl_dsa_to_der, 0);
652
+ rb_define_method(cDSA, "public_key", ossl_dsa_to_public_key, 0);
653
+ rb_define_method(cDSA, "syssign", ossl_dsa_sign, 1);
654
+ rb_define_method(cDSA, "sysverify", ossl_dsa_verify, 2);
655
+
656
+ DEF_OSSL_PKEY_BN(cDSA, dsa, p);
657
+ DEF_OSSL_PKEY_BN(cDSA, dsa, q);
658
+ DEF_OSSL_PKEY_BN(cDSA, dsa, g);
659
+ DEF_OSSL_PKEY_BN(cDSA, dsa, pub_key);
660
+ DEF_OSSL_PKEY_BN(cDSA, dsa, priv_key);
661
+ rb_define_method(cDSA, "set_pqg", ossl_dsa_set_pqg, 3);
662
+ rb_define_method(cDSA, "set_key", ossl_dsa_set_key, 2);
663
+
664
+ rb_define_method(cDSA, "params", ossl_dsa_get_params, 0);
665
+ }
666
+
667
+ #else /* defined NO_DSA */
668
+ void
669
+ Init_ossl_dsa(void)
670
+ {
671
+ }
672
+ #endif /* NO_DSA */