rubysl-openssl 0.0.1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +0 -1
  3. data/.travis.yml +7 -0
  4. data/README.md +2 -2
  5. data/Rakefile +0 -1
  6. data/ext/rubysl/openssl/extconf.h +50 -0
  7. data/ext/rubysl/openssl/extconf.rb +144 -0
  8. data/ext/rubysl/openssl/openssl_missing.c +343 -0
  9. data/ext/rubysl/openssl/openssl_missing.h +191 -0
  10. data/ext/rubysl/openssl/ossl.c +552 -0
  11. data/ext/rubysl/openssl/ossl.h +233 -0
  12. data/ext/rubysl/openssl/ossl_asn1.c +1160 -0
  13. data/ext/rubysl/openssl/ossl_asn1.h +59 -0
  14. data/ext/rubysl/openssl/ossl_bio.c +86 -0
  15. data/ext/rubysl/openssl/ossl_bio.h +21 -0
  16. data/ext/rubysl/openssl/ossl_bn.c +852 -0
  17. data/ext/rubysl/openssl/ossl_bn.h +25 -0
  18. data/ext/rubysl/openssl/ossl_cipher.c +569 -0
  19. data/ext/rubysl/openssl/ossl_cipher.h +22 -0
  20. data/ext/rubysl/openssl/ossl_config.c +75 -0
  21. data/ext/rubysl/openssl/ossl_config.h +22 -0
  22. data/ext/rubysl/openssl/ossl_digest.c +259 -0
  23. data/ext/rubysl/openssl/ossl_digest.h +22 -0
  24. data/ext/rubysl/openssl/ossl_engine.c +411 -0
  25. data/ext/rubysl/openssl/ossl_engine.h +20 -0
  26. data/ext/rubysl/openssl/ossl_hmac.c +268 -0
  27. data/ext/rubysl/openssl/ossl_hmac.h +19 -0
  28. data/ext/rubysl/openssl/ossl_ns_spki.c +257 -0
  29. data/ext/rubysl/openssl/ossl_ns_spki.h +21 -0
  30. data/ext/rubysl/openssl/ossl_ocsp.c +769 -0
  31. data/ext/rubysl/openssl/ossl_ocsp.h +24 -0
  32. data/ext/rubysl/openssl/ossl_pkcs12.c +210 -0
  33. data/ext/rubysl/openssl/ossl_pkcs12.h +15 -0
  34. data/ext/rubysl/openssl/ossl_pkcs5.c +99 -0
  35. data/ext/rubysl/openssl/ossl_pkcs5.h +6 -0
  36. data/ext/rubysl/openssl/ossl_pkcs7.c +1039 -0
  37. data/ext/rubysl/openssl/ossl_pkcs7.h +22 -0
  38. data/ext/rubysl/openssl/ossl_pkey.c +240 -0
  39. data/ext/rubysl/openssl/ossl_pkey.h +141 -0
  40. data/ext/rubysl/openssl/ossl_pkey_dh.c +532 -0
  41. data/ext/rubysl/openssl/ossl_pkey_dsa.c +484 -0
  42. data/ext/rubysl/openssl/ossl_pkey_ec.c +1593 -0
  43. data/ext/rubysl/openssl/ossl_pkey_rsa.c +593 -0
  44. data/ext/rubysl/openssl/ossl_rand.c +202 -0
  45. data/ext/rubysl/openssl/ossl_rand.h +20 -0
  46. data/ext/rubysl/openssl/ossl_ssl.c +1484 -0
  47. data/ext/rubysl/openssl/ossl_ssl.h +36 -0
  48. data/ext/rubysl/openssl/ossl_ssl_session.c +307 -0
  49. data/ext/rubysl/openssl/ossl_version.h +16 -0
  50. data/ext/rubysl/openssl/ossl_x509.c +104 -0
  51. data/ext/rubysl/openssl/ossl_x509.h +114 -0
  52. data/ext/rubysl/openssl/ossl_x509attr.c +274 -0
  53. data/ext/rubysl/openssl/ossl_x509cert.c +764 -0
  54. data/ext/rubysl/openssl/ossl_x509crl.c +535 -0
  55. data/ext/rubysl/openssl/ossl_x509ext.c +458 -0
  56. data/ext/rubysl/openssl/ossl_x509name.c +399 -0
  57. data/ext/rubysl/openssl/ossl_x509req.c +466 -0
  58. data/ext/rubysl/openssl/ossl_x509revoked.c +229 -0
  59. data/ext/rubysl/openssl/ossl_x509store.c +625 -0
  60. data/ext/rubysl/openssl/ruby_missing.h +41 -0
  61. data/lib/openssl.rb +1 -0
  62. data/lib/openssl/bn.rb +35 -0
  63. data/lib/openssl/buffering.rb +241 -0
  64. data/lib/openssl/cipher.rb +65 -0
  65. data/lib/openssl/config.rb +316 -0
  66. data/lib/openssl/digest.rb +61 -0
  67. data/lib/openssl/net/ftptls.rb +53 -0
  68. data/lib/openssl/net/telnets.rb +251 -0
  69. data/lib/openssl/pkcs7.rb +25 -0
  70. data/lib/openssl/ssl-internal.rb +187 -0
  71. data/lib/openssl/ssl.rb +1 -0
  72. data/lib/openssl/x509-internal.rb +153 -0
  73. data/lib/openssl/x509.rb +1 -0
  74. data/lib/rubysl/openssl.rb +28 -0
  75. data/lib/rubysl/openssl/version.rb +5 -0
  76. data/rubysl-openssl.gemspec +19 -18
  77. data/spec/cipher_spec.rb +16 -0
  78. data/spec/config/freeze_spec.rb +17 -0
  79. data/spec/hmac/digest_spec.rb +15 -0
  80. data/spec/hmac/hexdigest_spec.rb +15 -0
  81. data/spec/random/pseudo_bytes_spec.rb +5 -0
  82. data/spec/random/random_bytes_spec.rb +5 -0
  83. data/spec/random/shared/random_bytes.rb +28 -0
  84. data/spec/shared/constants.rb +11 -0
  85. data/spec/x509/name/parse_spec.rb +47 -0
  86. metadata +153 -89
  87. data/lib/rubysl-openssl.rb +0 -7
  88. data/lib/rubysl-openssl/version.rb +0 -5
@@ -0,0 +1,1593 @@
1
+ /*
2
+ * Copyright (C) 2006-2007 Technorama Ltd. <oss-ruby@technorama.net>
3
+ */
4
+
5
+ #include "ossl.h"
6
+
7
+ #if !defined(OPENSSL_NO_EC) && (OPENSSL_VERSION_NUMBER >= 0x0090802fL)
8
+
9
+ typedef struct {
10
+ EC_GROUP *group;
11
+ int dont_free;
12
+ } ossl_ec_group;
13
+
14
+ typedef struct {
15
+ EC_POINT *point;
16
+ int dont_free;
17
+ } ossl_ec_point;
18
+
19
+
20
+ #define EXPORT_PEM 0
21
+ #define EXPORT_DER 1
22
+
23
+
24
+ #define GetPKeyEC(obj, pkey) do { \
25
+ GetPKey(obj, pkey); \
26
+ if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) { \
27
+ ossl_raise(rb_eRuntimeError, "THIS IS NOT A EC PKEY!"); \
28
+ } \
29
+ } while (0)
30
+
31
+ #define SafeGet_ec_group(obj, group) do { \
32
+ OSSL_Check_Kind(obj, cEC_GROUP); \
33
+ Data_Get_Struct(obj, ossl_ec_group, group); \
34
+ } while(0)
35
+
36
+ #define Get_EC_KEY(obj, key) do { \
37
+ EVP_PKEY *pkey; \
38
+ GetPKeyEC(obj, pkey); \
39
+ key = pkey->pkey.ec; \
40
+ } while(0)
41
+
42
+ #define Require_EC_KEY(obj, key) do { \
43
+ Get_EC_KEY(obj, key); \
44
+ if (key == NULL) \
45
+ rb_raise(eECError, "EC_KEY is not initialized"); \
46
+ } while(0)
47
+
48
+ #define SafeRequire_EC_KEY(obj, key) do { \
49
+ OSSL_Check_Kind(obj, cEC); \
50
+ Require_EC_KEY(obj, key); \
51
+ } while (0)
52
+
53
+ #define Get_EC_GROUP(obj, g) do { \
54
+ ossl_ec_group *ec_group; \
55
+ Data_Get_Struct(obj, ossl_ec_group, ec_group); \
56
+ if (ec_group == NULL) \
57
+ rb_raise(eEC_GROUP, "missing ossl_ec_group structure"); \
58
+ g = ec_group->group; \
59
+ } while(0)
60
+
61
+ #define Require_EC_GROUP(obj, group) do { \
62
+ Get_EC_GROUP(obj, group); \
63
+ if (group == NULL) \
64
+ rb_raise(eEC_GROUP, "EC_GROUP is not initialized"); \
65
+ } while(0)
66
+
67
+ #define SafeRequire_EC_GROUP(obj, group) do { \
68
+ OSSL_Check_Kind(obj, cEC_GROUP); \
69
+ Require_EC_GROUP(obj, group); \
70
+ } while(0)
71
+
72
+ #define Get_EC_POINT(obj, p) do { \
73
+ ossl_ec_point *ec_point; \
74
+ Data_Get_Struct(obj, ossl_ec_point, ec_point); \
75
+ if (ec_point == NULL) \
76
+ rb_raise(eEC_POINT, "missing ossl_ec_point structure"); \
77
+ p = ec_point->point; \
78
+ } while(0)
79
+
80
+ #define Require_EC_POINT(obj, point) do { \
81
+ Get_EC_POINT(obj, point); \
82
+ if (point == NULL) \
83
+ rb_raise(eEC_POINT, "EC_POINT is not initialized"); \
84
+ } while(0)
85
+
86
+ #define SafeRequire_EC_POINT(obj, point) do { \
87
+ OSSL_Check_Kind(obj, cEC_POINT); \
88
+ Require_EC_POINT(obj, point); \
89
+ } while(0)
90
+
91
+ VALUE cEC;
92
+ VALUE eECError;
93
+ VALUE cEC_GROUP;
94
+ VALUE eEC_GROUP;
95
+ VALUE cEC_POINT;
96
+ VALUE eEC_POINT;
97
+
98
+ static ID s_GFp;
99
+ static ID s_GFp_simple;
100
+ static ID s_GFp_mont;
101
+ static ID s_GFp_nist;
102
+ static ID s_GF2m;
103
+ static ID s_GF2m_simple;
104
+
105
+ static ID ID_uncompressed;
106
+ static ID ID_compressed;
107
+ static ID ID_hybrid;
108
+
109
+ static VALUE ec_instance(VALUE klass, EC_KEY *ec)
110
+ {
111
+ EVP_PKEY *pkey;
112
+ VALUE obj;
113
+
114
+ if (!ec) {
115
+ return Qfalse;
116
+ }
117
+ if (!(pkey = EVP_PKEY_new())) {
118
+ return Qfalse;
119
+ }
120
+ if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
121
+ EVP_PKEY_free(pkey);
122
+ return Qfalse;
123
+ }
124
+ WrapPKey(klass, obj, pkey);
125
+
126
+ return obj;
127
+ }
128
+
129
+ VALUE ossl_ec_new(EVP_PKEY *pkey)
130
+ {
131
+ VALUE obj;
132
+
133
+ if (!pkey) {
134
+ obj = ec_instance(cEC, EC_KEY_new());
135
+ } else {
136
+ if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) {
137
+ ossl_raise(rb_eTypeError, "Not a EC key!");
138
+ }
139
+ WrapPKey(cEC, obj, pkey);
140
+ }
141
+ if (obj == Qfalse) {
142
+ ossl_raise(eECError, NULL);
143
+ }
144
+
145
+ return obj;
146
+ }
147
+
148
+
149
+ /* call-seq:
150
+ * OpenSSL::PKey::EC.new()
151
+ * OpenSSL::PKey::EC.new(ec_key)
152
+ * OpenSSL::PKey::EC.new(ec_group)
153
+ * OpenSSL::PKey::EC.new("secp112r1")
154
+ * OpenSSL::PKey::EC.new(pem_string)
155
+ * OpenSSL::PKey::EC.new(der_string)
156
+ *
157
+ * See the OpenSSL documentation for:
158
+ * EC_KEY_*
159
+ */
160
+ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
161
+ {
162
+ EVP_PKEY *pkey;
163
+ EC_KEY *ec = NULL;
164
+ VALUE arg, pass;
165
+ VALUE group = Qnil;
166
+
167
+ GetPKey(self, pkey);
168
+ if (pkey->pkey.ec)
169
+ rb_raise(eECError, "EC_KEY already initialized");
170
+
171
+ rb_scan_args(argc, argv, "02", &arg, &pass);
172
+
173
+ if (NIL_P(arg)) {
174
+ ec = EC_KEY_new();
175
+ } else {
176
+ if (rb_obj_is_kind_of(arg, cEC)) {
177
+ EC_KEY *other_ec = NULL;
178
+
179
+ SafeRequire_EC_KEY(arg, other_ec);
180
+ ec = EC_KEY_dup(other_ec);
181
+ } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
182
+ ec = EC_KEY_new();
183
+ group = arg;
184
+ } else {
185
+ BIO *in = ossl_obj2bio(arg);
186
+
187
+ ec = PEM_read_bio_ECPrivateKey(in, NULL, NULL, NULL);
188
+ if (!ec) {
189
+ BIO_reset(in);
190
+ ec = PEM_read_bio_EC_PUBKEY(in, NULL, NULL, NULL);
191
+ }
192
+ if (!ec) {
193
+ BIO_reset(in);
194
+ ec = d2i_ECPrivateKey_bio(in, NULL);
195
+ }
196
+ if (!ec) {
197
+ BIO_reset(in);
198
+ ec = d2i_EC_PUBKEY_bio(in, NULL);
199
+ }
200
+
201
+ BIO_free(in);
202
+
203
+ if (ec == NULL) {
204
+ const char *name = STR2CSTR(arg);
205
+ int nid = OBJ_sn2nid(name);
206
+
207
+ if (nid == NID_undef)
208
+ ossl_raise(eECError, "unknown curve name (%s)\n", name);
209
+
210
+ if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL)
211
+ ossl_raise(eECError, "unable to create curve (%s)\n", name);
212
+
213
+ EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
214
+ EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
215
+ }
216
+ }
217
+ }
218
+
219
+ if (ec == NULL)
220
+ ossl_raise(eECError, NULL);
221
+
222
+ if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
223
+ EC_KEY_free(ec);
224
+ ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
225
+ }
226
+
227
+ rb_iv_set(self, "@group", Qnil);
228
+
229
+ if (!NIL_P(group))
230
+ rb_funcall(self, rb_intern("group="), 1, arg);
231
+
232
+ return self;
233
+ }
234
+
235
+ /*
236
+ * call-seq:
237
+ * key.group => group
238
+ *
239
+ * Returns a constant <code>OpenSSL::EC::Group</code> that is tied to the key.
240
+ * Modifying the returned group can make the key invalid.
241
+ */
242
+ static VALUE ossl_ec_key_get_group(VALUE self)
243
+ {
244
+ VALUE group_v;
245
+ EC_KEY *ec;
246
+ ossl_ec_group *ec_group;
247
+ EC_GROUP *group;
248
+
249
+ Require_EC_KEY(self, ec);
250
+
251
+ group_v = rb_iv_get(self, "@group");
252
+ if (!NIL_P(group_v))
253
+ return group_v;
254
+
255
+ if ((group = (EC_GROUP *)EC_KEY_get0_group(ec)) != NULL) {
256
+ group_v = rb_obj_alloc(cEC_GROUP);
257
+ SafeGet_ec_group(group_v, ec_group);
258
+ ec_group->group = group;
259
+ ec_group->dont_free = 1;
260
+ rb_iv_set(group_v, "@key", self);
261
+ rb_iv_set(self, "@group", group_v);
262
+ return group_v;
263
+ }
264
+
265
+ return Qnil;
266
+ }
267
+
268
+ /*
269
+ * call-seq:
270
+ * key.group = group => group
271
+ *
272
+ * Returns the same object passed, not the group object associated with the key.
273
+ * If you wish to access the group object tied to the key call key.group after setting
274
+ * the group.
275
+ *
276
+ * Setting the group will immediately destroy any previously assigned group object.
277
+ * The group is internally copied by OpenSSL. Modifying the original group after
278
+ * assignment will not effect the internal key structure.
279
+ * (your changes may be lost). BE CAREFUL.
280
+ *
281
+ * EC_KEY_set_group calls EC_GROUP_free(key->group) then EC_GROUP_dup(), not EC_GROUP_copy.
282
+ * This documentation is accurate for OpenSSL 0.9.8b.
283
+ */
284
+ static VALUE ossl_ec_key_set_group(VALUE self, VALUE group_v)
285
+ {
286
+ VALUE old_group_v;
287
+ EC_KEY *ec;
288
+ EC_GROUP *group;
289
+
290
+ Require_EC_KEY(self, ec);
291
+ SafeRequire_EC_GROUP(group_v, group);
292
+
293
+ old_group_v = rb_iv_get(self, "@group");
294
+ if (!NIL_P(old_group_v)) {
295
+ ossl_ec_group *old_ec_group;
296
+ SafeGet_ec_group(old_group_v, old_ec_group);
297
+
298
+ old_ec_group->group = NULL;
299
+ old_ec_group->dont_free = 0;
300
+ rb_iv_set(old_group_v, "@key", Qnil);
301
+ }
302
+
303
+ rb_iv_set(self, "@group", Qnil);
304
+
305
+ if (EC_KEY_set_group(ec, group) != 1)
306
+ ossl_raise(eECError, "EC_KEY_set_group");
307
+
308
+ return group_v;
309
+ }
310
+
311
+ /*
312
+ * call-seq:
313
+ * key.private_key => OpenSSL::BN
314
+ *
315
+ * See the OpenSSL documentation for EC_KEY_get0_private_key()
316
+ */
317
+ static VALUE ossl_ec_key_get_private_key(VALUE self)
318
+ {
319
+ EC_KEY *ec;
320
+ const BIGNUM *bn;
321
+
322
+ Require_EC_KEY(self, ec);
323
+
324
+ if ((bn = EC_KEY_get0_private_key(ec)) == NULL)
325
+ return Qnil;
326
+
327
+ return ossl_bn_new(bn);
328
+ }
329
+
330
+ /*
331
+ * call-seq:
332
+ * key.private_key = openssl_bn
333
+ *
334
+ * See the OpenSSL documentation for EC_KEY_set_private_key()
335
+ */
336
+ static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key)
337
+ {
338
+ EC_KEY *ec;
339
+ BIGNUM *bn = NULL;
340
+
341
+ Require_EC_KEY(self, ec);
342
+ if (!NIL_P(private_key))
343
+ bn = GetBNPtr(private_key);
344
+
345
+ switch (EC_KEY_set_private_key(ec, bn)) {
346
+ case 1:
347
+ break;
348
+ case 0:
349
+ if (bn == NULL)
350
+ break;
351
+ default:
352
+ ossl_raise(eECError, "EC_KEY_set_private_key");
353
+ }
354
+
355
+ return private_key;
356
+ }
357
+
358
+
359
+ static VALUE ossl_ec_point_dup(const EC_POINT *point, VALUE group_v)
360
+ {
361
+ VALUE obj;
362
+ const EC_GROUP *group;
363
+ ossl_ec_point *new_point;
364
+
365
+ obj = rb_obj_alloc(cEC_POINT);
366
+ Data_Get_Struct(obj, ossl_ec_point, new_point);
367
+
368
+ SafeRequire_EC_GROUP(group_v, group);
369
+
370
+ new_point->point = EC_POINT_dup(point, group);
371
+ if (new_point->point == NULL)
372
+ ossl_raise(eEC_POINT, "EC_POINT_dup");
373
+ rb_iv_set(obj, "@group", group_v);
374
+
375
+ return obj;
376
+ }
377
+
378
+ /*
379
+ * call-seq:
380
+ * key.public_key => OpenSSL::PKey::EC::Point
381
+ *
382
+ * See the OpenSSL documentation for EC_KEY_get0_public_key()
383
+ */
384
+ static VALUE ossl_ec_key_get_public_key(VALUE self)
385
+ {
386
+ EC_KEY *ec;
387
+ const EC_POINT *point;
388
+ VALUE group;
389
+
390
+ Require_EC_KEY(self, ec);
391
+
392
+ if ((point = EC_KEY_get0_public_key(ec)) == NULL)
393
+ return Qnil;
394
+
395
+ group = rb_funcall(self, rb_intern("group"), 0);
396
+ if (NIL_P(group))
397
+ ossl_raise(eECError, "EC_KEY_get0_get0_group (has public_key but no group???");
398
+
399
+ return ossl_ec_point_dup(point, group);
400
+ }
401
+
402
+ /*
403
+ * call-seq:
404
+ * key.public_key = ec_point
405
+ *
406
+ * See the OpenSSL documentation for EC_KEY_set_public_key()
407
+ */
408
+ static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
409
+ {
410
+ EC_KEY *ec;
411
+ EC_POINT *point = NULL;
412
+
413
+ Require_EC_KEY(self, ec);
414
+ if (!NIL_P(public_key))
415
+ SafeRequire_EC_POINT(public_key, point);
416
+
417
+ switch (EC_KEY_set_public_key(ec, point)) {
418
+ case 1:
419
+ break;
420
+ case 0:
421
+ if (point == NULL)
422
+ break;
423
+ default:
424
+ ossl_raise(eECError, "EC_KEY_set_public_key");
425
+ }
426
+
427
+ return public_key;
428
+ }
429
+
430
+ /*
431
+ * call-seq:
432
+ * key.public_key? => true or false
433
+ *
434
+ * Both public_key? and private_key? may return false at the same time unlike other PKey classes.
435
+ */
436
+ static VALUE ossl_ec_key_is_public_key(VALUE self)
437
+ {
438
+ EC_KEY *ec;
439
+
440
+ Require_EC_KEY(self, ec);
441
+
442
+ return (EC_KEY_get0_public_key(ec) ? Qtrue : Qfalse);
443
+ }
444
+
445
+ /*
446
+ * call-seq:
447
+ * key.private_key? => true or false
448
+ *
449
+ * Both public_key? and private_key? may return false at the same time unlike other PKey classes.
450
+ */
451
+ static VALUE ossl_ec_key_is_private_key(VALUE self)
452
+ {
453
+ EC_KEY *ec;
454
+
455
+ Require_EC_KEY(self, ec);
456
+
457
+ return (EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse);
458
+ }
459
+
460
+ static VALUE ossl_ec_key_to_string(VALUE self, int format)
461
+ {
462
+ EC_KEY *ec;
463
+ BIO *out;
464
+ int i = -1;
465
+ int private = 0;
466
+ #if 0 /* unused now */
467
+ EVP_CIPHER *cipher = NULL;
468
+ char *password = NULL;
469
+ #endif
470
+ VALUE str;
471
+
472
+ Require_EC_KEY(self, ec);
473
+
474
+ if (EC_KEY_get0_public_key(ec) == NULL)
475
+ rb_raise(eECError, "can't export - no public key set");
476
+
477
+ if (EC_KEY_check_key(ec) != 1)
478
+ ossl_raise(eECError, "can't export - EC_KEY_check_key failed");
479
+
480
+ if (EC_KEY_get0_private_key(ec))
481
+ private = 1;
482
+
483
+ if (!(out = BIO_new(BIO_s_mem())))
484
+ ossl_raise(eECError, "BIO_new(BIO_s_mem())");
485
+
486
+ switch(format) {
487
+ case EXPORT_PEM:
488
+ if (private) {
489
+ #if 0 /* unused now */
490
+ if (cipher || password)
491
+ /* BUG: finish cipher/password key export */
492
+ rb_notimplement();
493
+ i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, NULL, password);
494
+ #endif
495
+ i = PEM_write_bio_ECPrivateKey(out, ec, NULL, NULL, 0, NULL, NULL);
496
+ } else {
497
+ #if 0 /* unused now */
498
+ if (cipher || password)
499
+ rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
500
+ #endif
501
+
502
+ i = PEM_write_bio_EC_PUBKEY(out, ec);
503
+ }
504
+
505
+ break;
506
+ case EXPORT_DER:
507
+ if (private) {
508
+ #if 0 /* unused now */
509
+ if (cipher || password)
510
+ rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
511
+ #endif
512
+
513
+ i = i2d_ECPrivateKey_bio(out, ec);
514
+ } else {
515
+ #if 0 /* unused now */
516
+ if (cipher || password)
517
+ rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
518
+ #endif
519
+
520
+ i = i2d_EC_PUBKEY_bio(out, ec);
521
+ }
522
+
523
+ break;
524
+ default:
525
+ BIO_free(out);
526
+ rb_raise(rb_eRuntimeError, "unknown format (internal error)");
527
+ }
528
+
529
+ if (i != 1) {
530
+ BIO_free(out);
531
+ ossl_raise(eECError, "outlen=%d", i);
532
+ }
533
+
534
+ str = ossl_membio2str(out);
535
+
536
+ return str;
537
+ }
538
+
539
+ /*
540
+ * call-seq:
541
+ * key.to_pem => String
542
+ *
543
+ * See the OpenSSL documentation for PEM_write_bio_ECPrivateKey()
544
+ */
545
+ static VALUE ossl_ec_key_to_pem(VALUE self)
546
+ {
547
+ return ossl_ec_key_to_string(self, EXPORT_PEM);
548
+ }
549
+
550
+ /*
551
+ * call-seq:
552
+ * key.to_der => String
553
+ *
554
+ * See the OpenSSL documentation for i2d_ECPrivateKey_bio()
555
+ */
556
+ static VALUE ossl_ec_key_to_der(VALUE self)
557
+ {
558
+ return ossl_ec_key_to_string(self, EXPORT_DER);
559
+ }
560
+
561
+ /*
562
+ * call-seq:
563
+ * key.to_text => String
564
+ *
565
+ * See the OpenSSL documentation for EC_KEY_print()
566
+ */
567
+ static VALUE ossl_ec_key_to_text(VALUE self)
568
+ {
569
+ EC_KEY *ec;
570
+ BIO *out;
571
+ VALUE str;
572
+
573
+ Require_EC_KEY(self, ec);
574
+ if (!(out = BIO_new(BIO_s_mem()))) {
575
+ ossl_raise(eECError, "BIO_new(BIO_s_mem())");
576
+ }
577
+ if (!EC_KEY_print(out, ec, 0)) {
578
+ BIO_free(out);
579
+ ossl_raise(eECError, "EC_KEY_print");
580
+ }
581
+ str = ossl_membio2str(out);
582
+
583
+ return str;
584
+ }
585
+
586
+ /*
587
+ * call-seq:
588
+ * key.generate_key => self
589
+ *
590
+ * See the OpenSSL documentation for EC_KEY_generate_key()
591
+ */
592
+ static VALUE ossl_ec_key_generate_key(VALUE self)
593
+ {
594
+ EC_KEY *ec;
595
+
596
+ Require_EC_KEY(self, ec);
597
+
598
+ if (EC_KEY_generate_key(ec) != 1)
599
+ ossl_raise(eECError, "EC_KEY_generate_key");
600
+
601
+ return self;
602
+ }
603
+
604
+ /*
605
+ * call-seq:
606
+ * key.check_key => true
607
+ *
608
+ * Raises an exception if the key is invalid.
609
+ *
610
+ * See the OpenSSL documentation for EC_KEY_check_key()
611
+ */
612
+ static VALUE ossl_ec_key_check_key(VALUE self)
613
+ {
614
+ EC_KEY *ec;
615
+
616
+ Require_EC_KEY(self, ec);
617
+
618
+ if (EC_KEY_check_key(ec) != 1)
619
+ ossl_raise(eECError, "EC_KEY_check_key");
620
+
621
+ return Qtrue;
622
+ }
623
+
624
+ /*
625
+ * call-seq:
626
+ * key.dh_compute_key(pubkey) => String
627
+ *
628
+ * See the OpenSSL documentation for ECDH_compute_key()
629
+ */
630
+ static VALUE ossl_ec_key_dh_compute_key(VALUE self, VALUE pubkey)
631
+ {
632
+ EC_KEY *ec;
633
+ EC_POINT *point;
634
+ int buf_len;
635
+ VALUE str;
636
+
637
+ Require_EC_KEY(self, ec);
638
+ SafeRequire_EC_POINT(pubkey, point);
639
+
640
+ /* BUG: need a way to figure out the maximum string size */
641
+ buf_len = 1024;
642
+ str = rb_str_new(0, buf_len);
643
+ /* BUG: take KDF as a block */
644
+ buf_len = ECDH_compute_key(RSTRING_PTR(str), buf_len, point, ec, NULL);
645
+ if (buf_len < 0)
646
+ ossl_raise(eECError, "ECDH_compute_key");
647
+
648
+ rb_str_resize(str, buf_len);
649
+
650
+ return str;
651
+ }
652
+
653
+ /* sign_setup */
654
+
655
+ /*
656
+ * call-seq:
657
+ * key.dsa_sign_asn1(data) => String
658
+ *
659
+ * See the OpenSSL documentation for ECDSA_sign()
660
+ */
661
+ static VALUE ossl_ec_key_dsa_sign_asn1(VALUE self, VALUE data)
662
+ {
663
+ EC_KEY *ec;
664
+ unsigned int buf_len;
665
+ VALUE str;
666
+
667
+ Require_EC_KEY(self, ec);
668
+ StringValue(data);
669
+
670
+ if (EC_KEY_get0_private_key(ec) == NULL)
671
+ ossl_raise(eECError, "Private EC key needed!");
672
+
673
+ str = rb_str_new(0, ECDSA_size(ec) + 16);
674
+ if (ECDSA_sign(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LEN(data), (unsigned char *) RSTRING_PTR(str), &buf_len, ec) != 1)
675
+ ossl_raise(eECError, "ECDSA_sign");
676
+
677
+ rb_str_resize(str, buf_len);
678
+
679
+ return str;
680
+ }
681
+
682
+ /*
683
+ * call-seq:
684
+ * key.dsa_verify_asn1(data, sig) => true or false
685
+ *
686
+ * See the OpenSSL documentation for ECDSA_verify()
687
+ */
688
+ static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig)
689
+ {
690
+ EC_KEY *ec;
691
+
692
+ Require_EC_KEY(self, ec);
693
+ StringValue(data);
694
+ StringValue(sig);
695
+
696
+ switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LEN(data), (unsigned char *) RSTRING_PTR(sig), RSTRING_LEN(sig), ec)) {
697
+ case 1: return Qtrue;
698
+ case 0: return Qfalse;
699
+ default: break;
700
+ }
701
+
702
+ ossl_raise(eECError, "ECDSA_verify");
703
+ }
704
+
705
+ static void ossl_ec_group_free(ossl_ec_group *ec_group)
706
+ {
707
+ if (!ec_group->dont_free && ec_group->group)
708
+ EC_GROUP_clear_free(ec_group->group);
709
+ ruby_xfree(ec_group);
710
+ }
711
+
712
+ static VALUE ossl_ec_group_alloc(VALUE klass)
713
+ {
714
+ ossl_ec_group *ec_group;
715
+ VALUE obj;
716
+
717
+ obj = Data_Make_Struct(klass, ossl_ec_group, 0, ossl_ec_group_free, ec_group);
718
+
719
+ return obj;
720
+ }
721
+
722
+ /* call-seq:
723
+ * OpenSSL::PKey::EC::Group.new("secp112r1")
724
+ * OpenSSL::PKey::EC::Group.new(ec_group)
725
+ * OpenSSL::PKey::EC::Group.new(pem_string)
726
+ * OpenSSL::PKey::EC::Group.new(der_string)
727
+ * OpenSSL::PKey::EC::Group.new(pem_file)
728
+ * OpenSSL::PKey::EC::Group.new(der_file)
729
+ * OpenSSL::PKey::EC::Group.new(:GFp_simple)
730
+ * OpenSSL::PKey::EC::Group.new(:GFp_mult)
731
+ * OpenSSL::PKey::EC::Group.new(:GFp_nist)
732
+ * OpenSSL::PKey::EC::Group.new(:GF2m_simple)
733
+ * OpenSSL::PKey::EC::Group.new(:GFp, bignum_p, bignum_a, bignum_b)
734
+ * OpenSSL::PKey::EC::Group.new(:GF2m, bignum_p, bignum_a, bignum_b)
735
+ *
736
+ * See the OpenSSL documentation for EC_GROUP_*
737
+ */
738
+ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
739
+ {
740
+ VALUE arg1, arg2, arg3, arg4;
741
+ ossl_ec_group *ec_group;
742
+ EC_GROUP *group = NULL;
743
+
744
+ Data_Get_Struct(self, ossl_ec_group, ec_group);
745
+ if (ec_group->group != NULL)
746
+ rb_raise(rb_eRuntimeError, "EC_GROUP is already initialized");
747
+
748
+ switch (rb_scan_args(argc, argv, "13", &arg1, &arg2, &arg3, &arg4)) {
749
+ case 1:
750
+ if (SYMBOL_P(arg1)) {
751
+ const EC_METHOD *method = NULL;
752
+ ID id = SYM2ID(arg1);
753
+
754
+ if (id == s_GFp_simple) {
755
+ method = EC_GFp_simple_method();
756
+ } else if (id == s_GFp_mont) {
757
+ method = EC_GFp_mont_method();
758
+ } else if (id == s_GFp_nist) {
759
+ method = EC_GFp_nist_method();
760
+ } else if (id == s_GF2m_simple) {
761
+ method = EC_GF2m_simple_method();
762
+ }
763
+
764
+ if (method) {
765
+ if ((group = EC_GROUP_new(method)) == NULL)
766
+ ossl_raise(eEC_GROUP, "EC_GROUP_new");
767
+ } else {
768
+ rb_raise(rb_eArgError, "unknown symbol, must be :GFp_simple, :GFp_mont, :GFp_nist or :GF2m_simple");
769
+ }
770
+ } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
771
+ const EC_GROUP *arg1_group;
772
+
773
+ SafeRequire_EC_GROUP(arg1, arg1_group);
774
+ if ((group = EC_GROUP_dup(arg1_group)) == NULL)
775
+ ossl_raise(eEC_GROUP, "EC_GROUP_dup");
776
+ } else {
777
+ BIO *in = ossl_obj2bio(arg1);
778
+
779
+ group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
780
+ if (!group) {
781
+ BIO_reset(in);
782
+ group = d2i_ECPKParameters_bio(in, NULL);
783
+ }
784
+
785
+ BIO_free(in);
786
+
787
+ if (!group) {
788
+ const char *name = STR2CSTR(arg1);
789
+ int nid = OBJ_sn2nid(name);
790
+
791
+ if (nid == NID_undef)
792
+ ossl_raise(eEC_GROUP, "unknown curve name (%s)", name);
793
+
794
+ group = EC_GROUP_new_by_curve_name(nid);
795
+ if (group == NULL)
796
+ ossl_raise(eEC_GROUP, "unable to create curve (%s)", name);
797
+
798
+ EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
799
+ EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
800
+ }
801
+ }
802
+
803
+ break;
804
+ case 4:
805
+ if (SYMBOL_P(arg1)) {
806
+ ID id = SYM2ID(arg1);
807
+ EC_GROUP *(*new_curve)(const BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *) = NULL;
808
+ const BIGNUM *p = GetBNPtr(arg2);
809
+ const BIGNUM *a = GetBNPtr(arg3);
810
+ const BIGNUM *b = GetBNPtr(arg4);
811
+
812
+ if (id == s_GFp) {
813
+ new_curve = EC_GROUP_new_curve_GFp;
814
+ } else if (id == s_GF2m) {
815
+ new_curve = EC_GROUP_new_curve_GF2m;
816
+ } else {
817
+ rb_raise(rb_eArgError, "unknown symbol, must be :GFp or :GF2m");
818
+ }
819
+
820
+ if ((group = new_curve(p, a, b, ossl_bn_ctx)) == NULL)
821
+ ossl_raise(eEC_GROUP, "EC_GROUP_new_by_GF*");
822
+ } else {
823
+ rb_raise(rb_eArgError, "unknown argument, must be :GFp or :GF2m");
824
+ }
825
+
826
+ break;
827
+ default:
828
+ rb_raise(rb_eArgError, "wrong number of arguments");
829
+ }
830
+
831
+ if (group == NULL)
832
+ ossl_raise(eEC_GROUP, "");
833
+
834
+ ec_group->group = group;
835
+
836
+ return self;
837
+ }
838
+
839
+ /* call-seq:
840
+ * group1 == group2 => true | false
841
+ *
842
+ */
843
+ static VALUE ossl_ec_group_eql(VALUE a, VALUE b)
844
+ {
845
+ EC_GROUP *group1 = NULL, *group2 = NULL;
846
+
847
+ Require_EC_GROUP(a, group1);
848
+ SafeRequire_EC_GROUP(b, group2);
849
+
850
+ if (EC_GROUP_cmp(group1, group2, ossl_bn_ctx) == 1)
851
+ return Qfalse;
852
+
853
+ return Qtrue;
854
+ }
855
+
856
+ /* call-seq:
857
+ * group.generator => ec_point
858
+ *
859
+ * See the OpenSSL documentation for EC_GROUP_get0_generator()
860
+ */
861
+ static VALUE ossl_ec_group_get_generator(VALUE self)
862
+ {
863
+ VALUE point_obj;
864
+ EC_GROUP *group = NULL;
865
+
866
+ Require_EC_GROUP(self, group);
867
+
868
+ point_obj = ossl_ec_point_dup(EC_GROUP_get0_generator(group), self);
869
+
870
+ return point_obj;
871
+ }
872
+
873
+ /* call-seq:
874
+ * group.set_generator(generator, order, cofactor) => self
875
+ *
876
+ * See the OpenSSL documentation for EC_GROUP_set_generator()
877
+ */
878
+ static VALUE ossl_ec_group_set_generator(VALUE self, VALUE generator, VALUE order, VALUE cofactor)
879
+ {
880
+ EC_GROUP *group = NULL;
881
+ const EC_POINT *point;
882
+ const BIGNUM *o, *co;
883
+
884
+ Require_EC_GROUP(self, group);
885
+ SafeRequire_EC_POINT(generator, point);
886
+ o = GetBNPtr(order);
887
+ co = GetBNPtr(cofactor);
888
+
889
+ if (EC_GROUP_set_generator(group, point, o, co) != 1)
890
+ ossl_raise(eEC_GROUP, "EC_GROUP_set_generator");
891
+
892
+ return self;
893
+ }
894
+
895
+ /* call-seq:
896
+ * group.get_order => order_bn
897
+ *
898
+ * See the OpenSSL documentation for EC_GROUP_get_order()
899
+ */
900
+ static VALUE ossl_ec_group_get_order(VALUE self)
901
+ {
902
+ VALUE bn_obj;
903
+ BIGNUM *bn;
904
+ EC_GROUP *group = NULL;
905
+
906
+ Require_EC_GROUP(self, group);
907
+
908
+ bn_obj = ossl_bn_new(NULL);
909
+ bn = GetBNPtr(bn_obj);
910
+
911
+ if (EC_GROUP_get_order(group, bn, ossl_bn_ctx) != 1)
912
+ ossl_raise(eEC_GROUP, "EC_GROUP_get_order");
913
+
914
+ return bn_obj;
915
+ }
916
+
917
+ /* call-seq:
918
+ * group.get_cofactor => cofactor_bn
919
+ *
920
+ * See the OpenSSL documentation for EC_GROUP_get_cofactor()
921
+ */
922
+ static VALUE ossl_ec_group_get_cofactor(VALUE self)
923
+ {
924
+ VALUE bn_obj;
925
+ BIGNUM *bn;
926
+ EC_GROUP *group = NULL;
927
+
928
+ Require_EC_GROUP(self, group);
929
+
930
+ bn_obj = ossl_bn_new(NULL);
931
+ bn = GetBNPtr(bn_obj);
932
+
933
+ if (EC_GROUP_get_cofactor(group, bn, ossl_bn_ctx) != 1)
934
+ ossl_raise(eEC_GROUP, "EC_GROUP_get_cofactor");
935
+
936
+ return bn_obj;
937
+ }
938
+
939
+ /* call-seq:
940
+ * group.curve_name => String
941
+ *
942
+ * See the OpenSSL documentation for EC_GROUP_get_curve_name()
943
+ */
944
+ static VALUE ossl_ec_group_get_curve_name(VALUE self)
945
+ {
946
+ EC_GROUP *group = NULL;
947
+ int nid;
948
+
949
+ Get_EC_GROUP(self, group);
950
+ if (group == NULL)
951
+ return Qnil;
952
+
953
+ nid = EC_GROUP_get_curve_name(group);
954
+
955
+ /* BUG: an nid or asn1 object should be returned, maybe. */
956
+ return rb_str_new2(OBJ_nid2sn(nid));
957
+ }
958
+
959
+ /* call-seq:
960
+ * EC.builtin_curves => [[name, comment], ...]
961
+ *
962
+ * See the OpenSSL documentation for EC_builtin_curves()
963
+ */
964
+ static VALUE ossl_s_builtin_curves(VALUE self)
965
+ {
966
+ EC_builtin_curve *curves = NULL;
967
+ int n;
968
+ int crv_len = EC_get_builtin_curves(NULL, 0);
969
+ VALUE ary, ret;
970
+
971
+ curves = ALLOCA_N(EC_builtin_curve, crv_len);
972
+ if (curves == NULL)
973
+ return Qnil;
974
+ if (!EC_get_builtin_curves(curves, crv_len))
975
+ ossl_raise(rb_eRuntimeError, "EC_get_builtin_curves");
976
+
977
+ ret = rb_ary_new2(crv_len);
978
+
979
+ for (n = 0; n < crv_len; n++) {
980
+ const char *sname = OBJ_nid2sn(curves[n].nid);
981
+ const char *comment = curves[n].comment;
982
+
983
+ ary = rb_ary_new2(2);
984
+ rb_ary_push(ary, rb_str_new2(sname));
985
+ rb_ary_push(ary, comment ? rb_str_new2(comment) : Qnil);
986
+ rb_ary_push(ret, ary);
987
+ }
988
+
989
+ return ret;
990
+ }
991
+
992
+ /* call-seq:
993
+ * group.asn1_flag => Fixnum
994
+ *
995
+ * See the OpenSSL documentation for EC_GROUP_get_asn1_flag()
996
+ */
997
+ static VALUE ossl_ec_group_get_asn1_flag(VALUE self)
998
+ {
999
+ EC_GROUP *group = NULL;
1000
+ int flag;
1001
+
1002
+ Require_EC_GROUP(self, group);
1003
+
1004
+ flag = EC_GROUP_get_asn1_flag(group);
1005
+
1006
+ return INT2FIX(flag);
1007
+ }
1008
+
1009
+ /* call-seq:
1010
+ * group.asn1_flag = Fixnum => Fixnum
1011
+ *
1012
+ * See the OpenSSL documentation for EC_GROUP_set_asn1_flag()
1013
+ */
1014
+ static VALUE ossl_ec_group_set_asn1_flag(VALUE self, VALUE flag_v)
1015
+ {
1016
+ EC_GROUP *group = NULL;
1017
+
1018
+ Require_EC_GROUP(self, group);
1019
+
1020
+ EC_GROUP_set_asn1_flag(group, NUM2INT(flag_v));
1021
+
1022
+ return flag_v;
1023
+ }
1024
+
1025
+ /* call-seq:
1026
+ * group.point_conversion_form => :uncompressed | :compressed | :hybrid
1027
+ *
1028
+ * See the OpenSSL documentation for EC_GROUP_get_point_conversion_form()
1029
+ */
1030
+ static VALUE ossl_ec_group_get_point_conversion_form(VALUE self)
1031
+ {
1032
+ EC_GROUP *group = NULL;
1033
+ point_conversion_form_t form;
1034
+ VALUE ret;
1035
+
1036
+ Require_EC_GROUP(self, group);
1037
+
1038
+ form = EC_GROUP_get_point_conversion_form(group);
1039
+
1040
+ switch (form) {
1041
+ case POINT_CONVERSION_UNCOMPRESSED: ret = ID_uncompressed; break;
1042
+ case POINT_CONVERSION_COMPRESSED: ret = ID_compressed; break;
1043
+ case POINT_CONVERSION_HYBRID: ret = ID_hybrid; break;
1044
+ default: rb_raise(eEC_GROUP, "unsupported point conversion form: %d, this module should be updated", form);
1045
+ }
1046
+
1047
+ return ID2SYM(ret);
1048
+ }
1049
+
1050
+ /* call-seq:
1051
+ * group.point_conversion_form = form => form
1052
+ *
1053
+ * See the OpenSSL documentation for EC_GROUP_set_point_conversion_form()
1054
+ */
1055
+ static VALUE ossl_ec_group_set_point_conversion_form(VALUE self, VALUE form_v)
1056
+ {
1057
+ EC_GROUP *group = NULL;
1058
+ point_conversion_form_t form;
1059
+ ID form_id = SYM2ID(form_v);
1060
+
1061
+ Require_EC_GROUP(self, group);
1062
+
1063
+ if (form_id == ID_uncompressed) {
1064
+ form = POINT_CONVERSION_UNCOMPRESSED;
1065
+ } else if (form_id == ID_compressed) {
1066
+ form = POINT_CONVERSION_COMPRESSED;
1067
+ } else if (form_id == ID_hybrid) {
1068
+ form = POINT_CONVERSION_HYBRID;
1069
+ } else {
1070
+ rb_raise(rb_eArgError, "form must be :compressed, :uncompressed, or :hybrid");
1071
+ }
1072
+
1073
+ EC_GROUP_set_point_conversion_form(group, form);
1074
+
1075
+ return form_v;
1076
+ }
1077
+
1078
+ /* call-seq:
1079
+ * group.seed => String or nil
1080
+ *
1081
+ * See the OpenSSL documentation for EC_GROUP_get0_seed()
1082
+ */
1083
+ static VALUE ossl_ec_group_get_seed(VALUE self)
1084
+ {
1085
+ EC_GROUP *group = NULL;
1086
+ size_t seed_len;
1087
+
1088
+ Require_EC_GROUP(self, group);
1089
+
1090
+ seed_len = EC_GROUP_get_seed_len(group);
1091
+
1092
+ if (seed_len == 0)
1093
+ return Qnil;
1094
+
1095
+ return rb_str_new(EC_GROUP_get0_seed(group), seed_len);
1096
+ }
1097
+
1098
+ /* call-seq:
1099
+ * group.seed = seed => seed
1100
+ *
1101
+ * See the OpenSSL documentation for EC_GROUP_set_seed()
1102
+ */
1103
+ static VALUE ossl_ec_group_set_seed(VALUE self, VALUE seed)
1104
+ {
1105
+ EC_GROUP *group = NULL;
1106
+
1107
+ Require_EC_GROUP(self, group);
1108
+ StringValue(seed);
1109
+
1110
+ if (EC_GROUP_set_seed(group, RSTRING_PTR(seed), RSTRING_LEN(seed)) != RSTRING_LEN(seed))
1111
+ ossl_raise(eEC_GROUP, "EC_GROUP_set_seed");
1112
+
1113
+ return seed;
1114
+ }
1115
+
1116
+ /* get/set curve GFp, GF2m */
1117
+
1118
+ /* call-seq:
1119
+ * group.degree => Fixnum
1120
+ *
1121
+ * See the OpenSSL documentation for EC_GROUP_get_degree()
1122
+ */
1123
+ static VALUE ossl_ec_group_get_degree(VALUE self)
1124
+ {
1125
+ EC_GROUP *group = NULL;
1126
+
1127
+ Require_EC_GROUP(self, group);
1128
+
1129
+ return INT2NUM(EC_GROUP_get_degree(group));
1130
+ }
1131
+
1132
+ static VALUE ossl_ec_group_to_string(VALUE self, int format)
1133
+ {
1134
+ EC_GROUP *group;
1135
+ BIO *out;
1136
+ int i = -1;
1137
+ VALUE str;
1138
+
1139
+ Get_EC_GROUP(self, group);
1140
+
1141
+ if (!(out = BIO_new(BIO_s_mem())))
1142
+ ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())");
1143
+
1144
+ switch(format) {
1145
+ case EXPORT_PEM:
1146
+ i = PEM_write_bio_ECPKParameters(out, group);
1147
+ break;
1148
+ case EXPORT_DER:
1149
+ i = i2d_ECPKParameters_bio(out, group);
1150
+ break;
1151
+ default:
1152
+ BIO_free(out);
1153
+ rb_raise(rb_eRuntimeError, "unknown format (internal error)");
1154
+ }
1155
+
1156
+ if (i != 1) {
1157
+ BIO_free(out);
1158
+ ossl_raise(eECError, NULL);
1159
+ }
1160
+
1161
+ str = ossl_membio2str(out);
1162
+
1163
+ return str;
1164
+ }
1165
+
1166
+ /* call-seq:
1167
+ * group.to_pem => String
1168
+ *
1169
+ * See the OpenSSL documentation for PEM_write_bio_ECPKParameters()
1170
+ */
1171
+ static VALUE ossl_ec_group_to_pem(VALUE self)
1172
+ {
1173
+ return ossl_ec_group_to_string(self, EXPORT_PEM);
1174
+ }
1175
+
1176
+ /* call-seq:
1177
+ * group.to_der => String
1178
+ *
1179
+ * See the OpenSSL documentation for i2d_ECPKParameters_bio()
1180
+ */
1181
+ static VALUE ossl_ec_group_to_der(VALUE self)
1182
+ {
1183
+ return ossl_ec_group_to_string(self, EXPORT_DER);
1184
+ }
1185
+
1186
+ /* call-seq:
1187
+ * group.to_text => String
1188
+ *
1189
+ * See the OpenSSL documentation for ECPKParameters_print()
1190
+ */
1191
+ static VALUE ossl_ec_group_to_text(VALUE self)
1192
+ {
1193
+ EC_GROUP *group;
1194
+ BIO *out;
1195
+ VALUE str;
1196
+
1197
+ Require_EC_GROUP(self, group);
1198
+ if (!(out = BIO_new(BIO_s_mem()))) {
1199
+ ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())");
1200
+ }
1201
+ if (!ECPKParameters_print(out, group, 0)) {
1202
+ BIO_free(out);
1203
+ ossl_raise(eEC_GROUP, NULL);
1204
+ }
1205
+ str = ossl_membio2str(out);
1206
+
1207
+ return str;
1208
+ }
1209
+
1210
+
1211
+ static void ossl_ec_point_free(ossl_ec_point *ec_point)
1212
+ {
1213
+ if (!ec_point->dont_free && ec_point->point)
1214
+ EC_POINT_clear_free(ec_point->point);
1215
+ ruby_xfree(ec_point);
1216
+ }
1217
+
1218
+ static VALUE ossl_ec_point_alloc(VALUE klass)
1219
+ {
1220
+ ossl_ec_point *ec_point;
1221
+ VALUE obj;
1222
+
1223
+ obj = Data_Make_Struct(klass, ossl_ec_point, 0, ossl_ec_point_free, ec_point);
1224
+
1225
+ return obj;
1226
+ }
1227
+
1228
+ /*
1229
+ * call-seq:
1230
+ * OpenSSL::PKey::EC::Point.new(point)
1231
+ * OpenSSL::PKey::EC::Point.new(group)
1232
+ * OpenSSL::PKey::EC::Point.new(group, bn)
1233
+ *
1234
+ * See the OpenSSL documentation for EC_POINT_*
1235
+ */
1236
+ static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
1237
+ {
1238
+ ossl_ec_point *ec_point;
1239
+ EC_POINT *point = NULL;
1240
+ VALUE arg1, arg2;
1241
+ VALUE group_v = Qnil;
1242
+ const EC_GROUP *group = NULL;
1243
+
1244
+ Data_Get_Struct(self, ossl_ec_point, ec_point);
1245
+ if (ec_point->point)
1246
+ rb_raise(eEC_POINT, "EC_POINT already initialized");
1247
+
1248
+ switch (rb_scan_args(argc, argv, "11", &arg1, &arg2)) {
1249
+ case 1:
1250
+ if (rb_obj_is_kind_of(arg1, cEC_POINT)) {
1251
+ const EC_POINT *arg_point;
1252
+
1253
+ group_v = rb_iv_get(arg1, "@group");
1254
+ SafeRequire_EC_GROUP(group_v, group);
1255
+ SafeRequire_EC_POINT(arg1, arg_point);
1256
+
1257
+ point = EC_POINT_dup(arg_point, group);
1258
+ } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
1259
+ group_v = arg1;
1260
+ SafeRequire_EC_GROUP(group_v, group);
1261
+
1262
+ point = EC_POINT_new(group);
1263
+ } else {
1264
+ rb_raise(eEC_POINT, "wrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group");
1265
+ }
1266
+
1267
+ break;
1268
+ case 2:
1269
+ if (!rb_obj_is_kind_of(arg1, cEC_GROUP))
1270
+ rb_raise(rb_eArgError, "1st argument must be OpenSSL::PKey::EC::Group");
1271
+ group_v = arg1;
1272
+ SafeRequire_EC_GROUP(group_v, group);
1273
+
1274
+ if (rb_obj_is_kind_of(arg2, cBN)) {
1275
+ const BIGNUM *bn = GetBNPtr(arg2);
1276
+
1277
+ point = EC_POINT_bn2point(group, bn, NULL, ossl_bn_ctx);
1278
+ } else {
1279
+ BIO *in = ossl_obj2bio(arg1);
1280
+
1281
+ /* BUG: finish me */
1282
+
1283
+ BIO_free(in);
1284
+
1285
+ if (point == NULL) {
1286
+ ossl_raise(eEC_POINT, "unknown type for 2nd arg");
1287
+ }
1288
+ }
1289
+ break;
1290
+ default:
1291
+ rb_raise(rb_eArgError, "wrong number of arguments");
1292
+ }
1293
+
1294
+ if (point == NULL)
1295
+ ossl_raise(eEC_POINT, NULL);
1296
+
1297
+ if (NIL_P(group_v))
1298
+ rb_raise(rb_eRuntimeError, "missing group (internal error)");
1299
+
1300
+ ec_point->point = point;
1301
+
1302
+ rb_iv_set(self, "@group", group_v);
1303
+
1304
+ return self;
1305
+ }
1306
+
1307
+ /*
1308
+ * call-seq:
1309
+ * point1 == point2 => true | false
1310
+ *
1311
+ */
1312
+ static VALUE ossl_ec_point_eql(VALUE a, VALUE b)
1313
+ {
1314
+ EC_POINT *point1, *point2;
1315
+ VALUE group_v1 = rb_iv_get(a, "@group");
1316
+ VALUE group_v2 = rb_iv_get(b, "@group");
1317
+ const EC_GROUP *group;
1318
+
1319
+ if (ossl_ec_group_eql(group_v1, group_v2) == Qfalse)
1320
+ return Qfalse;
1321
+
1322
+ Require_EC_POINT(a, point1);
1323
+ SafeRequire_EC_POINT(b, point2);
1324
+ SafeRequire_EC_GROUP(group_v1, group);
1325
+
1326
+ if (EC_POINT_cmp(group, point1, point2, ossl_bn_ctx) == 1)
1327
+ return Qfalse;
1328
+
1329
+ return Qtrue;
1330
+ }
1331
+
1332
+ /*
1333
+ * call-seq:
1334
+ * point.infinity? => true | false
1335
+ *
1336
+ */
1337
+ static VALUE ossl_ec_point_is_at_infinity(VALUE self)
1338
+ {
1339
+ EC_POINT *point;
1340
+ VALUE group_v = rb_iv_get(self, "@group");
1341
+ const EC_GROUP *group;
1342
+
1343
+ Require_EC_POINT(self, point);
1344
+ SafeRequire_EC_GROUP(group_v, group);
1345
+
1346
+ switch (EC_POINT_is_at_infinity(group, point)) {
1347
+ case 1: return Qtrue;
1348
+ case 0: return Qfalse;
1349
+ default: ossl_raise(cEC_POINT, "EC_POINT_is_at_infinity");
1350
+ }
1351
+ }
1352
+
1353
+ /*
1354
+ * call-seq:
1355
+ * point.on_curve? => true | false
1356
+ *
1357
+ */
1358
+ static VALUE ossl_ec_point_is_on_curve(VALUE self)
1359
+ {
1360
+ EC_POINT *point;
1361
+ VALUE group_v = rb_iv_get(self, "@group");
1362
+ const EC_GROUP *group;
1363
+
1364
+ Require_EC_POINT(self, point);
1365
+ SafeRequire_EC_GROUP(group_v, group);
1366
+
1367
+ switch (EC_POINT_is_on_curve(group, point, ossl_bn_ctx)) {
1368
+ case 1: return Qtrue;
1369
+ case 0: return Qfalse;
1370
+ default: ossl_raise(cEC_POINT, "EC_POINT_is_on_curve");
1371
+ }
1372
+ }
1373
+
1374
+ /*
1375
+ * call-seq:
1376
+ * point.make_affine! => self
1377
+ *
1378
+ */
1379
+ static VALUE ossl_ec_point_make_affine(VALUE self)
1380
+ {
1381
+ EC_POINT *point;
1382
+ VALUE group_v = rb_iv_get(self, "@group");
1383
+ const EC_GROUP *group;
1384
+
1385
+ Require_EC_POINT(self, point);
1386
+ SafeRequire_EC_GROUP(group_v, group);
1387
+
1388
+ if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1)
1389
+ ossl_raise(cEC_POINT, "EC_POINT_make_affine");
1390
+
1391
+ return self;
1392
+ }
1393
+
1394
+ /*
1395
+ * call-seq:
1396
+ * point.invert! => self
1397
+ *
1398
+ */
1399
+ static VALUE ossl_ec_point_invert(VALUE self)
1400
+ {
1401
+ EC_POINT *point;
1402
+ VALUE group_v = rb_iv_get(self, "@group");
1403
+ const EC_GROUP *group;
1404
+
1405
+ Require_EC_POINT(self, point);
1406
+ SafeRequire_EC_GROUP(group_v, group);
1407
+
1408
+ if (EC_POINT_invert(group, point, ossl_bn_ctx) != 1)
1409
+ ossl_raise(cEC_POINT, "EC_POINT_invert");
1410
+
1411
+ return self;
1412
+ }
1413
+
1414
+ /*
1415
+ * call-seq:
1416
+ * point.set_to_infinity! => self
1417
+ *
1418
+ */
1419
+ static VALUE ossl_ec_point_set_to_infinity(VALUE self)
1420
+ {
1421
+ EC_POINT *point;
1422
+ VALUE group_v = rb_iv_get(self, "@group");
1423
+ const EC_GROUP *group;
1424
+
1425
+ Require_EC_POINT(self, point);
1426
+ SafeRequire_EC_GROUP(group_v, group);
1427
+
1428
+ if (EC_POINT_set_to_infinity(group, point) != 1)
1429
+ ossl_raise(cEC_POINT, "EC_POINT_set_to_infinity");
1430
+
1431
+ return self;
1432
+ }
1433
+
1434
+ /*
1435
+ * call-seq:
1436
+ * point.to_bn => OpenSSL::BN
1437
+ *
1438
+ * See the OpenSSL documentation for EC_POINT_point2bn()
1439
+ */
1440
+ static VALUE ossl_ec_point_to_bn(VALUE self)
1441
+ {
1442
+ EC_POINT *point;
1443
+ VALUE bn_obj;
1444
+ VALUE group_v = rb_iv_get(self, "@group");
1445
+ const EC_GROUP *group;
1446
+ point_conversion_form_t form;
1447
+ BIGNUM *bn;
1448
+
1449
+ Require_EC_POINT(self, point);
1450
+ SafeRequire_EC_GROUP(group_v, group);
1451
+
1452
+ form = EC_GROUP_get_point_conversion_form(group);
1453
+
1454
+ bn_obj = rb_obj_alloc(cBN);
1455
+ bn = GetBNPtr(bn_obj);
1456
+
1457
+ if (EC_POINT_point2bn(group, point, form, bn, ossl_bn_ctx) == NULL)
1458
+ ossl_raise(eEC_POINT, "EC_POINT_point2bn");
1459
+
1460
+ return bn_obj;
1461
+ }
1462
+
1463
+ static void no_copy(VALUE klass)
1464
+ {
1465
+ rb_undef_method(klass, "copy");
1466
+ rb_undef_method(klass, "clone");
1467
+ rb_undef_method(klass, "dup");
1468
+ rb_undef_method(klass, "initialize_copy");
1469
+ }
1470
+
1471
+ void Init_ossl_ec()
1472
+ {
1473
+ #ifdef DONT_NEED_RDOC_WORKAROUND
1474
+ mOSSL = rb_define_module("OpenSSL");
1475
+ mPKey = rb_define_module_under(mOSSL, "PKey");
1476
+ #endif
1477
+
1478
+ eECError = rb_define_class_under(mPKey, "ECError", ePKeyError);
1479
+
1480
+ cEC = rb_define_class_under(mPKey, "EC", cPKey);
1481
+ cEC_GROUP = rb_define_class_under(cEC, "Group", rb_cObject);
1482
+ cEC_POINT = rb_define_class_under(cEC, "Point", rb_cObject);
1483
+ eEC_GROUP = rb_define_class_under(cEC_GROUP, "Error", eOSSLError);
1484
+ eEC_POINT = rb_define_class_under(cEC_POINT, "Error", eOSSLError);
1485
+
1486
+ s_GFp = rb_intern("GFp");
1487
+ s_GF2m = rb_intern("GF2m");
1488
+ s_GFp_simple = rb_intern("GFp_simple");
1489
+ s_GFp_mont = rb_intern("GFp_mont");
1490
+ s_GFp_nist = rb_intern("GFp_nist");
1491
+ s_GF2m_simple = rb_intern("GF2m_simple");
1492
+
1493
+ ID_uncompressed = rb_intern("uncompressed");
1494
+ ID_compressed = rb_intern("compressed");
1495
+ ID_hybrid = rb_intern("hybrid");
1496
+
1497
+ #ifdef OPENSSL_EC_NAMED_CURVE
1498
+ rb_define_const(cEC, "NAMED_CURVE", ULONG2NUM(OPENSSL_EC_NAMED_CURVE));
1499
+ #endif
1500
+
1501
+ rb_define_singleton_method(cEC, "builtin_curves", ossl_s_builtin_curves, 0);
1502
+
1503
+ rb_define_method(cEC, "initialize", ossl_ec_key_initialize, -1);
1504
+ /* copy/dup/cmp */
1505
+
1506
+ rb_define_method(cEC, "group", ossl_ec_key_get_group, 0);
1507
+ rb_define_method(cEC, "group=", ossl_ec_key_set_group, 1);
1508
+ rb_define_method(cEC, "private_key", ossl_ec_key_get_private_key, 0);
1509
+ rb_define_method(cEC, "private_key=", ossl_ec_key_set_private_key, 1);
1510
+ rb_define_method(cEC, "public_key", ossl_ec_key_get_public_key, 0);
1511
+ rb_define_method(cEC, "public_key=", ossl_ec_key_set_public_key, 1);
1512
+ rb_define_method(cEC, "private_key?", ossl_ec_key_is_private_key, 0);
1513
+ rb_define_method(cEC, "public_key?", ossl_ec_key_is_public_key, 0);
1514
+ /* rb_define_method(cEC, "", ossl_ec_key_get_, 0);
1515
+ rb_define_method(cEC, "=", ossl_ec_key_set_ 1);
1516
+ set/get enc_flags
1517
+ set/get _conv_from
1518
+ set/get asn1_flag (can use ruby to call self.group.asn1_flag)
1519
+ set/get precompute_mult
1520
+ */
1521
+ rb_define_method(cEC, "generate_key", ossl_ec_key_generate_key, 0);
1522
+ rb_define_method(cEC, "check_key", ossl_ec_key_check_key, 0);
1523
+
1524
+ rb_define_method(cEC, "dh_compute_key", ossl_ec_key_dh_compute_key, 1);
1525
+ rb_define_method(cEC, "dsa_sign_asn1", ossl_ec_key_dsa_sign_asn1, 1);
1526
+ rb_define_method(cEC, "dsa_verify_asn1", ossl_ec_key_dsa_verify_asn1, 2);
1527
+ /* do_sign/do_verify */
1528
+
1529
+ rb_define_method(cEC, "to_pem", ossl_ec_key_to_pem, 0);
1530
+ rb_define_method(cEC, "to_der", ossl_ec_key_to_der, 0);
1531
+ rb_define_method(cEC, "to_text", ossl_ec_key_to_text, 0);
1532
+
1533
+
1534
+ rb_define_alloc_func(cEC_GROUP, ossl_ec_group_alloc);
1535
+ rb_define_method(cEC_GROUP, "initialize", ossl_ec_group_initialize, -1);
1536
+ rb_define_method(cEC_GROUP, "eql?", ossl_ec_group_eql, 1);
1537
+ rb_define_alias(cEC_GROUP, "==", "eql?");
1538
+ /* copy/dup/cmp */
1539
+
1540
+ rb_define_method(cEC_GROUP, "generator", ossl_ec_group_get_generator, 0);
1541
+ rb_define_method(cEC_GROUP, "set_generator", ossl_ec_group_set_generator, 3);
1542
+ rb_define_method(cEC_GROUP, "order", ossl_ec_group_get_order, 0);
1543
+ rb_define_method(cEC_GROUP, "cofactor", ossl_ec_group_get_cofactor, 0);
1544
+
1545
+ rb_define_method(cEC_GROUP, "curve_name", ossl_ec_group_get_curve_name, 0);
1546
+ /* rb_define_method(cEC_GROUP, "curve_name=", ossl_ec_group_set_curve_name, 1); */
1547
+
1548
+ rb_define_method(cEC_GROUP, "asn1_flag", ossl_ec_group_get_asn1_flag, 0);
1549
+ rb_define_method(cEC_GROUP, "asn1_flag=", ossl_ec_group_set_asn1_flag, 1);
1550
+
1551
+ rb_define_method(cEC_GROUP, "point_conversion_form", ossl_ec_group_get_point_conversion_form, 0);
1552
+ rb_define_method(cEC_GROUP, "point_conversion_form=", ossl_ec_group_set_point_conversion_form, 1);
1553
+
1554
+ rb_define_method(cEC_GROUP, "seed", ossl_ec_group_get_seed, 0);
1555
+ rb_define_method(cEC_GROUP, "seed=", ossl_ec_group_set_seed, 1);
1556
+
1557
+ /* get/set GFp, GF2m */
1558
+
1559
+ rb_define_method(cEC_GROUP, "degree", ossl_ec_group_get_degree, 0);
1560
+
1561
+ /* check* */
1562
+
1563
+
1564
+ rb_define_method(cEC_GROUP, "to_pem", ossl_ec_group_to_pem, 0);
1565
+ rb_define_method(cEC_GROUP, "to_der", ossl_ec_group_to_der, 0);
1566
+ rb_define_method(cEC_GROUP, "to_text", ossl_ec_group_to_text, 0);
1567
+
1568
+
1569
+ rb_define_alloc_func(cEC_POINT, ossl_ec_point_alloc);
1570
+ rb_define_method(cEC_POINT, "initialize", ossl_ec_point_initialize, -1);
1571
+ rb_attr(cEC_POINT, rb_intern("group"), 1, 0, 0);
1572
+ rb_define_method(cEC_POINT, "eql?", ossl_ec_point_eql, 1);
1573
+ rb_define_alias(cEC_POINT, "==", "eql?");
1574
+
1575
+ rb_define_method(cEC_POINT, "infinity?", ossl_ec_point_is_at_infinity, 0);
1576
+ rb_define_method(cEC_POINT, "on_curve?", ossl_ec_point_is_on_curve, 0);
1577
+ rb_define_method(cEC_POINT, "make_affine!", ossl_ec_point_make_affine, 0);
1578
+ rb_define_method(cEC_POINT, "invert!", ossl_ec_point_invert, 0);
1579
+ rb_define_method(cEC_POINT, "set_to_infinity!", ossl_ec_point_set_to_infinity, 0);
1580
+ /* all the other methods */
1581
+
1582
+ rb_define_method(cEC_POINT, "to_bn", ossl_ec_point_to_bn, 0);
1583
+
1584
+ no_copy(cEC);
1585
+ no_copy(cEC_GROUP);
1586
+ no_copy(cEC_POINT);
1587
+ }
1588
+
1589
+ #else /* defined NO_EC */
1590
+ void Init_ossl_ec()
1591
+ {
1592
+ }
1593
+ #endif /* NO_EC */