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,1899 @@
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
+ static const rb_data_type_t ossl_ec_group_type;
24
+ static const rb_data_type_t ossl_ec_point_type;
25
+
26
+ #define GetPKeyEC(obj, pkey) do { \
27
+ GetPKey((obj), (pkey)); \
28
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) { \
29
+ ossl_raise(rb_eRuntimeError, "THIS IS NOT A EC PKEY!"); \
30
+ } \
31
+ } while (0)
32
+
33
+ #define SafeGet_ec_group(obj, group) do { \
34
+ OSSL_Check_Kind((obj), cEC_GROUP); \
35
+ TypedData_Get_Struct((obj), ossl_ec_group, &ossl_ec_group_type, (group)); \
36
+ } while(0)
37
+
38
+ #define Get_EC_KEY(obj, key) do { \
39
+ EVP_PKEY *pkey; \
40
+ GetPKeyEC((obj), pkey); \
41
+ (key) = EVP_PKEY_get0_EC_KEY(pkey); \
42
+ } while(0)
43
+
44
+ #define Require_EC_KEY(obj, key) do { \
45
+ Get_EC_KEY((obj), (key)); \
46
+ if ((key) == NULL) \
47
+ ossl_raise(eECError, "EC_KEY is not initialized"); \
48
+ } while(0)
49
+
50
+ #define SafeRequire_EC_KEY(obj, key) do { \
51
+ OSSL_Check_Kind((obj), cEC); \
52
+ Require_EC_KEY((obj), (key)); \
53
+ } while (0)
54
+
55
+ #define Get_EC_GROUP(obj, g) do { \
56
+ ossl_ec_group *ec_group; \
57
+ TypedData_Get_Struct((obj), ossl_ec_group, &ossl_ec_group_type, ec_group); \
58
+ if (ec_group == NULL) \
59
+ ossl_raise(eEC_GROUP, "missing ossl_ec_group structure"); \
60
+ (g) = ec_group->group; \
61
+ } while(0)
62
+
63
+ #define Require_EC_GROUP(obj, group) do { \
64
+ Get_EC_GROUP((obj), (group)); \
65
+ if ((group) == NULL) \
66
+ ossl_raise(eEC_GROUP, "EC_GROUP is not initialized"); \
67
+ } while(0)
68
+
69
+ #define SafeRequire_EC_GROUP(obj, group) do { \
70
+ OSSL_Check_Kind((obj), cEC_GROUP); \
71
+ Require_EC_GROUP((obj), (group)); \
72
+ } while(0)
73
+
74
+ #define Get_EC_POINT(obj, p) do { \
75
+ ossl_ec_point *ec_point; \
76
+ TypedData_Get_Struct((obj), ossl_ec_point, &ossl_ec_point_type, ec_point); \
77
+ if (ec_point == NULL) \
78
+ ossl_raise(eEC_POINT, "missing ossl_ec_point structure"); \
79
+ (p) = ec_point->point; \
80
+ } while(0)
81
+
82
+ #define Require_EC_POINT(obj, point) do { \
83
+ Get_EC_POINT((obj), (point)); \
84
+ if ((point) == NULL) \
85
+ ossl_raise(eEC_POINT, "EC_POINT is not initialized"); \
86
+ } while(0)
87
+
88
+ #define SafeRequire_EC_POINT(obj, point) do { \
89
+ OSSL_Check_Kind((obj), cEC_POINT); \
90
+ Require_EC_POINT((obj), (point)); \
91
+ } while(0)
92
+
93
+ VALUE cEC;
94
+ VALUE eECError;
95
+ VALUE cEC_GROUP;
96
+ VALUE eEC_GROUP;
97
+ VALUE cEC_POINT;
98
+ VALUE eEC_POINT;
99
+
100
+ static ID s_GFp;
101
+ static ID s_GFp_simple;
102
+ static ID s_GFp_mont;
103
+ static ID s_GFp_nist;
104
+ static ID s_GF2m;
105
+ static ID s_GF2m_simple;
106
+
107
+ static ID ID_uncompressed;
108
+ static ID ID_compressed;
109
+ static ID ID_hybrid;
110
+
111
+ static ID id_i_group, id_i_key;
112
+
113
+ static VALUE ec_instance(VALUE klass, EC_KEY *ec)
114
+ {
115
+ EVP_PKEY *pkey;
116
+ VALUE obj;
117
+
118
+ if (!ec) {
119
+ return Qfalse;
120
+ }
121
+ obj = NewPKey(klass);
122
+ if (!(pkey = EVP_PKEY_new())) {
123
+ return Qfalse;
124
+ }
125
+ if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
126
+ EVP_PKEY_free(pkey);
127
+ return Qfalse;
128
+ }
129
+ SetPKey(obj, pkey);
130
+
131
+ return obj;
132
+ }
133
+
134
+ VALUE ossl_ec_new(EVP_PKEY *pkey)
135
+ {
136
+ VALUE obj;
137
+
138
+ if (!pkey) {
139
+ obj = ec_instance(cEC, EC_KEY_new());
140
+ } else {
141
+ obj = NewPKey(cEC);
142
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) {
143
+ ossl_raise(rb_eTypeError, "Not a EC key!");
144
+ }
145
+ SetPKey(obj, pkey);
146
+ }
147
+ if (obj == Qfalse) {
148
+ ossl_raise(eECError, NULL);
149
+ }
150
+
151
+ return obj;
152
+ }
153
+
154
+ /*
155
+ * Creates a new EC_KEY on the EC group obj. arg can be an EC::Group or a String
156
+ * representing an OID.
157
+ */
158
+ static EC_KEY *
159
+ ec_key_new_from_group(VALUE arg)
160
+ {
161
+ EC_KEY *ec;
162
+
163
+ if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
164
+ EC_GROUP *group;
165
+
166
+ SafeRequire_EC_GROUP(arg, group);
167
+
168
+ if (!(ec = EC_KEY_new()))
169
+ ossl_raise(eECError, NULL);
170
+
171
+ if (!EC_KEY_set_group(ec, group)) {
172
+ EC_KEY_free(ec);
173
+ ossl_raise(eECError, NULL);
174
+ }
175
+ } else {
176
+ int nid = OBJ_sn2nid(StringValueCStr(arg));
177
+
178
+ if (nid == NID_undef)
179
+ ossl_raise(eECError, "invalid curve name");
180
+
181
+ if (!(ec = EC_KEY_new_by_curve_name(nid)))
182
+ ossl_raise(eECError, NULL);
183
+
184
+ EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
185
+ EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
186
+ }
187
+
188
+ return ec;
189
+ }
190
+
191
+ /*
192
+ * call-seq:
193
+ * EC.generate(ec_group) -> ec
194
+ * EC.generate(string) -> ec
195
+ *
196
+ * Creates a new EC instance with a new random private and public key.
197
+ */
198
+ static VALUE
199
+ ossl_ec_key_s_generate(VALUE klass, VALUE arg)
200
+ {
201
+ EC_KEY *ec;
202
+ VALUE obj;
203
+
204
+ ec = ec_key_new_from_group(arg);
205
+
206
+ obj = ec_instance(klass, ec);
207
+ if (obj == Qfalse) {
208
+ EC_KEY_free(ec);
209
+ ossl_raise(eECError, NULL);
210
+ }
211
+
212
+ if (!EC_KEY_generate_key(ec))
213
+ ossl_raise(eECError, "EC_KEY_generate_key");
214
+
215
+ return obj;
216
+ }
217
+
218
+ /*
219
+ * call-seq:
220
+ * OpenSSL::PKey::EC.new
221
+ * OpenSSL::PKey::EC.new(ec_key)
222
+ * OpenSSL::PKey::EC.new(ec_group)
223
+ * OpenSSL::PKey::EC.new("secp112r1")
224
+ * OpenSSL::PKey::EC.new(pem_string [, pwd])
225
+ * OpenSSL::PKey::EC.new(der_string)
226
+ *
227
+ * Creates a new EC object from given arguments.
228
+ */
229
+ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
230
+ {
231
+ EVP_PKEY *pkey;
232
+ EC_KEY *ec;
233
+ VALUE arg, pass;
234
+
235
+ GetPKey(self, pkey);
236
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
237
+ ossl_raise(eECError, "EC_KEY already initialized");
238
+
239
+ rb_scan_args(argc, argv, "02", &arg, &pass);
240
+
241
+ if (NIL_P(arg)) {
242
+ if (!(ec = EC_KEY_new()))
243
+ ossl_raise(eECError, NULL);
244
+ } else if (rb_obj_is_kind_of(arg, cEC)) {
245
+ EC_KEY *other_ec = NULL;
246
+
247
+ SafeRequire_EC_KEY(arg, other_ec);
248
+ if (!(ec = EC_KEY_dup(other_ec)))
249
+ ossl_raise(eECError, NULL);
250
+ } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
251
+ ec = ec_key_new_from_group(arg);
252
+ } else {
253
+ BIO *in;
254
+
255
+ pass = ossl_pem_passwd_value(pass);
256
+ in = ossl_obj2bio(arg);
257
+
258
+ ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass);
259
+ if (!ec) {
260
+ OSSL_BIO_reset(in);
261
+ ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, (void *)pass);
262
+ }
263
+ if (!ec) {
264
+ OSSL_BIO_reset(in);
265
+ ec = d2i_ECPrivateKey_bio(in, NULL);
266
+ }
267
+ if (!ec) {
268
+ OSSL_BIO_reset(in);
269
+ ec = d2i_EC_PUBKEY_bio(in, NULL);
270
+ }
271
+ BIO_free(in);
272
+
273
+ if (!ec) {
274
+ ossl_clear_error();
275
+ ec = ec_key_new_from_group(arg);
276
+ }
277
+ }
278
+
279
+ if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
280
+ EC_KEY_free(ec);
281
+ ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
282
+ }
283
+
284
+ rb_ivar_set(self, id_i_group, Qnil);
285
+
286
+ return self;
287
+ }
288
+
289
+ static VALUE
290
+ ossl_ec_key_initialize_copy(VALUE self, VALUE other)
291
+ {
292
+ EVP_PKEY *pkey;
293
+ EC_KEY *ec, *ec_new;
294
+
295
+ GetPKey(self, pkey);
296
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
297
+ ossl_raise(eECError, "EC already initialized");
298
+ SafeRequire_EC_KEY(other, ec);
299
+
300
+ ec_new = EC_KEY_dup(ec);
301
+ if (!ec_new)
302
+ ossl_raise(eECError, "EC_KEY_dup");
303
+ if (!EVP_PKEY_assign_EC_KEY(pkey, ec_new)) {
304
+ EC_KEY_free(ec_new);
305
+ ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
306
+ }
307
+ rb_ivar_set(self, id_i_group, Qnil); /* EC_KEY_dup() also copies the EC_GROUP */
308
+
309
+ return self;
310
+ }
311
+
312
+ /*
313
+ * call-seq:
314
+ * key.group => group
315
+ *
316
+ * Returns a constant <code>OpenSSL::EC::Group</code> that is tied to the key.
317
+ * Modifying the returned group can make the key invalid.
318
+ */
319
+ static VALUE ossl_ec_key_get_group(VALUE self)
320
+ {
321
+ VALUE group_v;
322
+ EC_KEY *ec;
323
+ ossl_ec_group *ec_group;
324
+ EC_GROUP *group;
325
+
326
+ Require_EC_KEY(self, ec);
327
+
328
+ group_v = rb_attr_get(self, id_i_group);
329
+ if (!NIL_P(group_v))
330
+ return group_v;
331
+
332
+ if ((group = (EC_GROUP *)EC_KEY_get0_group(ec)) != NULL) {
333
+ group_v = rb_obj_alloc(cEC_GROUP);
334
+ SafeGet_ec_group(group_v, ec_group);
335
+ ec_group->group = group;
336
+ ec_group->dont_free = 1;
337
+ rb_ivar_set(group_v, id_i_key, self);
338
+ rb_ivar_set(self, id_i_group, group_v);
339
+ return group_v;
340
+ }
341
+
342
+ return Qnil;
343
+ }
344
+
345
+ /*
346
+ * call-seq:
347
+ * key.group = group => group
348
+ *
349
+ * Returns the same object passed, not the group object associated with the key.
350
+ * If you wish to access the group object tied to the key call key.group after setting
351
+ * the group.
352
+ *
353
+ * Setting the group will immediately destroy any previously assigned group object.
354
+ * The group is internally copied by OpenSSL. Modifying the original group after
355
+ * assignment will not effect the internal key structure.
356
+ * (your changes may be lost). BE CAREFUL.
357
+ *
358
+ * EC_KEY_set_group calls EC_GROUP_free(key->group) then EC_GROUP_dup(), not EC_GROUP_copy.
359
+ * This documentation is accurate for OpenSSL 0.9.8b.
360
+ */
361
+ static VALUE ossl_ec_key_set_group(VALUE self, VALUE group_v)
362
+ {
363
+ VALUE old_group_v;
364
+ EC_KEY *ec;
365
+ EC_GROUP *group;
366
+
367
+ Require_EC_KEY(self, ec);
368
+ SafeRequire_EC_GROUP(group_v, group);
369
+
370
+ old_group_v = rb_attr_get(self, id_i_group);
371
+ if (!NIL_P(old_group_v)) {
372
+ ossl_ec_group *old_ec_group;
373
+ SafeGet_ec_group(old_group_v, old_ec_group);
374
+
375
+ old_ec_group->group = NULL;
376
+ old_ec_group->dont_free = 0;
377
+ rb_ivar_set(old_group_v, id_i_key, Qnil);
378
+ }
379
+
380
+ rb_ivar_set(self, id_i_group, Qnil);
381
+
382
+ if (EC_KEY_set_group(ec, group) != 1)
383
+ ossl_raise(eECError, "EC_KEY_set_group");
384
+
385
+ return group_v;
386
+ }
387
+
388
+ /*
389
+ * call-seq:
390
+ * key.private_key => OpenSSL::BN
391
+ *
392
+ * See the OpenSSL documentation for EC_KEY_get0_private_key()
393
+ */
394
+ static VALUE ossl_ec_key_get_private_key(VALUE self)
395
+ {
396
+ EC_KEY *ec;
397
+ const BIGNUM *bn;
398
+
399
+ Require_EC_KEY(self, ec);
400
+
401
+ if ((bn = EC_KEY_get0_private_key(ec)) == NULL)
402
+ return Qnil;
403
+
404
+ return ossl_bn_new(bn);
405
+ }
406
+
407
+ /*
408
+ * call-seq:
409
+ * key.private_key = openssl_bn
410
+ *
411
+ * See the OpenSSL documentation for EC_KEY_set_private_key()
412
+ */
413
+ static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key)
414
+ {
415
+ EC_KEY *ec;
416
+ BIGNUM *bn = NULL;
417
+
418
+ Require_EC_KEY(self, ec);
419
+ if (!NIL_P(private_key))
420
+ bn = GetBNPtr(private_key);
421
+
422
+ switch (EC_KEY_set_private_key(ec, bn)) {
423
+ case 1:
424
+ break;
425
+ case 0:
426
+ if (bn == NULL)
427
+ break;
428
+ default:
429
+ ossl_raise(eECError, "EC_KEY_set_private_key");
430
+ }
431
+
432
+ return private_key;
433
+ }
434
+
435
+
436
+ static VALUE ossl_ec_point_dup(const EC_POINT *point, VALUE group_v)
437
+ {
438
+ VALUE obj;
439
+ const EC_GROUP *group;
440
+ ossl_ec_point *new_point;
441
+
442
+ obj = rb_obj_alloc(cEC_POINT);
443
+ TypedData_Get_Struct(obj, ossl_ec_point, &ossl_ec_point_type, new_point);
444
+
445
+ SafeRequire_EC_GROUP(group_v, group);
446
+
447
+ new_point->point = EC_POINT_dup(point, group);
448
+ if (new_point->point == NULL)
449
+ ossl_raise(eEC_POINT, "EC_POINT_dup");
450
+ rb_ivar_set(obj, id_i_group, group_v);
451
+
452
+ return obj;
453
+ }
454
+
455
+ /*
456
+ * call-seq:
457
+ * key.public_key => OpenSSL::PKey::EC::Point
458
+ *
459
+ * See the OpenSSL documentation for EC_KEY_get0_public_key()
460
+ */
461
+ static VALUE ossl_ec_key_get_public_key(VALUE self)
462
+ {
463
+ EC_KEY *ec;
464
+ const EC_POINT *point;
465
+ VALUE group;
466
+
467
+ Require_EC_KEY(self, ec);
468
+
469
+ if ((point = EC_KEY_get0_public_key(ec)) == NULL)
470
+ return Qnil;
471
+
472
+ group = rb_funcall(self, rb_intern("group"), 0);
473
+ if (NIL_P(group))
474
+ ossl_raise(eECError, "EC_KEY_get0_get0_group (has public_key but no group???");
475
+
476
+ return ossl_ec_point_dup(point, group);
477
+ }
478
+
479
+ /*
480
+ * call-seq:
481
+ * key.public_key = ec_point
482
+ *
483
+ * See the OpenSSL documentation for EC_KEY_set_public_key()
484
+ */
485
+ static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
486
+ {
487
+ EC_KEY *ec;
488
+ EC_POINT *point = NULL;
489
+
490
+ Require_EC_KEY(self, ec);
491
+ if (!NIL_P(public_key))
492
+ SafeRequire_EC_POINT(public_key, point);
493
+
494
+ switch (EC_KEY_set_public_key(ec, point)) {
495
+ case 1:
496
+ break;
497
+ case 0:
498
+ if (point == NULL)
499
+ break;
500
+ default:
501
+ ossl_raise(eECError, "EC_KEY_set_public_key");
502
+ }
503
+
504
+ return public_key;
505
+ }
506
+
507
+ /*
508
+ * call-seq:
509
+ * key.public? => true or false
510
+ *
511
+ * Returns whether this EC instance has a public key. The public key
512
+ * (EC::Point) can be retrieved with EC#public_key.
513
+ */
514
+ static VALUE ossl_ec_key_is_public(VALUE self)
515
+ {
516
+ EC_KEY *ec;
517
+
518
+ Require_EC_KEY(self, ec);
519
+
520
+ return EC_KEY_get0_public_key(ec) ? Qtrue : Qfalse;
521
+ }
522
+
523
+ /*
524
+ * call-seq:
525
+ * key.private? => true or false
526
+ *
527
+ * Returns whether this EC instance has a private key. The private key (BN) can
528
+ * be retrieved with EC#private_key.
529
+ */
530
+ static VALUE ossl_ec_key_is_private(VALUE self)
531
+ {
532
+ EC_KEY *ec;
533
+
534
+ Require_EC_KEY(self, ec);
535
+
536
+ return EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse;
537
+ }
538
+
539
+ static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int format)
540
+ {
541
+ EC_KEY *ec;
542
+ BIO *out;
543
+ int i = -1;
544
+ int private = 0;
545
+ VALUE str;
546
+ const EVP_CIPHER *cipher = NULL;
547
+
548
+ Require_EC_KEY(self, ec);
549
+
550
+ if (EC_KEY_get0_public_key(ec) == NULL)
551
+ ossl_raise(eECError, "can't export - no public key set");
552
+
553
+ if (EC_KEY_check_key(ec) != 1)
554
+ ossl_raise(eECError, "can't export - EC_KEY_check_key failed");
555
+
556
+ if (EC_KEY_get0_private_key(ec))
557
+ private = 1;
558
+
559
+ if (!NIL_P(ciph)) {
560
+ cipher = GetCipherPtr(ciph);
561
+ pass = ossl_pem_passwd_value(pass);
562
+ }
563
+
564
+ if (!(out = BIO_new(BIO_s_mem())))
565
+ ossl_raise(eECError, "BIO_new(BIO_s_mem())");
566
+
567
+ switch(format) {
568
+ case EXPORT_PEM:
569
+ if (private) {
570
+ i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, ossl_pem_passwd_cb, (void *)pass);
571
+ } else {
572
+ i = PEM_write_bio_EC_PUBKEY(out, ec);
573
+ }
574
+
575
+ break;
576
+ case EXPORT_DER:
577
+ if (private) {
578
+ i = i2d_ECPrivateKey_bio(out, ec);
579
+ } else {
580
+ i = i2d_EC_PUBKEY_bio(out, ec);
581
+ }
582
+
583
+ break;
584
+ default:
585
+ BIO_free(out);
586
+ ossl_raise(rb_eRuntimeError, "unknown format (internal error)");
587
+ }
588
+
589
+ if (i != 1) {
590
+ BIO_free(out);
591
+ ossl_raise(eECError, "outlen=%d", i);
592
+ }
593
+
594
+ str = ossl_membio2str(out);
595
+
596
+ return str;
597
+ }
598
+
599
+ /*
600
+ * call-seq:
601
+ * key.export([cipher, pass_phrase]) => String
602
+ * key.to_pem([cipher, pass_phrase]) => String
603
+ *
604
+ * Outputs the EC key in PEM encoding. If +cipher+ and +pass_phrase+ are given
605
+ * they will be used to encrypt the key. +cipher+ must be an OpenSSL::Cipher
606
+ * instance. Note that encryption will only be effective for a private key,
607
+ * public keys will always be encoded in plain text.
608
+ */
609
+ static VALUE ossl_ec_key_export(int argc, VALUE *argv, VALUE self)
610
+ {
611
+ VALUE cipher, passwd;
612
+ rb_scan_args(argc, argv, "02", &cipher, &passwd);
613
+ return ossl_ec_key_to_string(self, cipher, passwd, EXPORT_PEM);
614
+ }
615
+
616
+ /*
617
+ * call-seq:
618
+ * key.to_der => String
619
+ *
620
+ * See the OpenSSL documentation for i2d_ECPrivateKey_bio()
621
+ */
622
+ static VALUE ossl_ec_key_to_der(VALUE self)
623
+ {
624
+ return ossl_ec_key_to_string(self, Qnil, Qnil, EXPORT_DER);
625
+ }
626
+
627
+ /*
628
+ * call-seq:
629
+ * key.to_text => String
630
+ *
631
+ * See the OpenSSL documentation for EC_KEY_print()
632
+ */
633
+ static VALUE ossl_ec_key_to_text(VALUE self)
634
+ {
635
+ EC_KEY *ec;
636
+ BIO *out;
637
+ VALUE str;
638
+
639
+ Require_EC_KEY(self, ec);
640
+ if (!(out = BIO_new(BIO_s_mem()))) {
641
+ ossl_raise(eECError, "BIO_new(BIO_s_mem())");
642
+ }
643
+ if (!EC_KEY_print(out, ec, 0)) {
644
+ BIO_free(out);
645
+ ossl_raise(eECError, "EC_KEY_print");
646
+ }
647
+ str = ossl_membio2str(out);
648
+
649
+ return str;
650
+ }
651
+
652
+ /*
653
+ * call-seq:
654
+ * key.generate_key! => self
655
+ *
656
+ * Generates a new random private and public key.
657
+ *
658
+ * See also the OpenSSL documentation for EC_KEY_generate_key()
659
+ *
660
+ * === Example
661
+ * ec = OpenSSL::PKey::EC.new("prime256v1")
662
+ * p ec.private_key # => nil
663
+ * ec.generate_key!
664
+ * p ec.private_key # => #<OpenSSL::BN XXXXXX>
665
+ */
666
+ static VALUE ossl_ec_key_generate_key(VALUE self)
667
+ {
668
+ EC_KEY *ec;
669
+
670
+ Require_EC_KEY(self, ec);
671
+
672
+ if (EC_KEY_generate_key(ec) != 1)
673
+ ossl_raise(eECError, "EC_KEY_generate_key");
674
+
675
+ return self;
676
+ }
677
+
678
+ /*
679
+ * call-seq:
680
+ * key.check_key => true
681
+ *
682
+ * Raises an exception if the key is invalid.
683
+ *
684
+ * See the OpenSSL documentation for EC_KEY_check_key()
685
+ */
686
+ static VALUE ossl_ec_key_check_key(VALUE self)
687
+ {
688
+ EC_KEY *ec;
689
+
690
+ Require_EC_KEY(self, ec);
691
+
692
+ if (EC_KEY_check_key(ec) != 1)
693
+ ossl_raise(eECError, "EC_KEY_check_key");
694
+
695
+ return Qtrue;
696
+ }
697
+
698
+ /*
699
+ * call-seq:
700
+ * key.dh_compute_key(pubkey) => String
701
+ *
702
+ * See the OpenSSL documentation for ECDH_compute_key()
703
+ */
704
+ static VALUE ossl_ec_key_dh_compute_key(VALUE self, VALUE pubkey)
705
+ {
706
+ EC_KEY *ec;
707
+ EC_POINT *point;
708
+ int buf_len;
709
+ VALUE str;
710
+
711
+ Require_EC_KEY(self, ec);
712
+ SafeRequire_EC_POINT(pubkey, point);
713
+
714
+ /* BUG: need a way to figure out the maximum string size */
715
+ buf_len = 1024;
716
+ str = rb_str_new(0, buf_len);
717
+ /* BUG: take KDF as a block */
718
+ buf_len = ECDH_compute_key(RSTRING_PTR(str), buf_len, point, ec, NULL);
719
+ if (buf_len < 0)
720
+ ossl_raise(eECError, "ECDH_compute_key");
721
+
722
+ rb_str_resize(str, buf_len);
723
+
724
+ return str;
725
+ }
726
+
727
+ /* sign_setup */
728
+
729
+ /*
730
+ * call-seq:
731
+ * key.dsa_sign_asn1(data) => String
732
+ *
733
+ * See the OpenSSL documentation for ECDSA_sign()
734
+ */
735
+ static VALUE ossl_ec_key_dsa_sign_asn1(VALUE self, VALUE data)
736
+ {
737
+ EC_KEY *ec;
738
+ unsigned int buf_len;
739
+ VALUE str;
740
+
741
+ Require_EC_KEY(self, ec);
742
+ StringValue(data);
743
+
744
+ if (EC_KEY_get0_private_key(ec) == NULL)
745
+ ossl_raise(eECError, "Private EC key needed!");
746
+
747
+ str = rb_str_new(0, ECDSA_size(ec) + 16);
748
+ if (ECDSA_sign(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(str), &buf_len, ec) != 1)
749
+ ossl_raise(eECError, "ECDSA_sign");
750
+
751
+ rb_str_resize(str, buf_len);
752
+
753
+ return str;
754
+ }
755
+
756
+ /*
757
+ * call-seq:
758
+ * key.dsa_verify_asn1(data, sig) => true or false
759
+ *
760
+ * See the OpenSSL documentation for ECDSA_verify()
761
+ */
762
+ static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig)
763
+ {
764
+ EC_KEY *ec;
765
+
766
+ Require_EC_KEY(self, ec);
767
+ StringValue(data);
768
+ StringValue(sig);
769
+
770
+ switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(sig), (int)RSTRING_LEN(sig), ec)) {
771
+ case 1: return Qtrue;
772
+ case 0: return Qfalse;
773
+ default: break;
774
+ }
775
+
776
+ ossl_raise(eECError, "ECDSA_verify");
777
+
778
+ UNREACHABLE;
779
+ }
780
+
781
+ static void ossl_ec_group_free(void *ptr)
782
+ {
783
+ ossl_ec_group *ec_group = ptr;
784
+ if (!ec_group->dont_free && ec_group->group)
785
+ EC_GROUP_clear_free(ec_group->group);
786
+ ruby_xfree(ec_group);
787
+ }
788
+
789
+ static const rb_data_type_t ossl_ec_group_type = {
790
+ "OpenSSL/ec_group",
791
+ {
792
+ 0, ossl_ec_group_free,
793
+ },
794
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
795
+ };
796
+
797
+ static VALUE ossl_ec_group_alloc(VALUE klass)
798
+ {
799
+ ossl_ec_group *ec_group;
800
+ VALUE obj;
801
+
802
+ obj = TypedData_Make_Struct(klass, ossl_ec_group, &ossl_ec_group_type, ec_group);
803
+
804
+ return obj;
805
+ }
806
+
807
+ /*
808
+ * call-seq:
809
+ * OpenSSL::PKey::EC::Group.new(ec_group)
810
+ * OpenSSL::PKey::EC::Group.new(pem_or_der_encoded)
811
+ * OpenSSL::PKey::EC::Group.new(ec_method)
812
+ * OpenSSL::PKey::EC::Group.new(:GFp, bignum_p, bignum_a, bignum_b)
813
+ * OpenSSL::PKey::EC::Group.new(:GF2m, bignum_p, bignum_a, bignum_b)
814
+ *
815
+ * Creates a new EC::Group object.
816
+ *
817
+ * +ec_method+ is a symbol that represents an EC_METHOD. Currently the following
818
+ * are supported:
819
+ *
820
+ * * :GFp_simple
821
+ * * :GFp_mont
822
+ * * :GFp_nist
823
+ * * :GF2m_simple
824
+ *
825
+ * If the first argument is :GFp or :GF2m, creates a new curve with given
826
+ * parameters.
827
+ */
828
+ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
829
+ {
830
+ VALUE arg1, arg2, arg3, arg4;
831
+ ossl_ec_group *ec_group;
832
+ EC_GROUP *group = NULL;
833
+
834
+ TypedData_Get_Struct(self, ossl_ec_group, &ossl_ec_group_type, ec_group);
835
+ if (ec_group->group != NULL)
836
+ ossl_raise(rb_eRuntimeError, "EC_GROUP is already initialized");
837
+
838
+ switch (rb_scan_args(argc, argv, "13", &arg1, &arg2, &arg3, &arg4)) {
839
+ case 1:
840
+ if (SYMBOL_P(arg1)) {
841
+ const EC_METHOD *method = NULL;
842
+ ID id = SYM2ID(arg1);
843
+
844
+ if (id == s_GFp_simple) {
845
+ method = EC_GFp_simple_method();
846
+ } else if (id == s_GFp_mont) {
847
+ method = EC_GFp_mont_method();
848
+ } else if (id == s_GFp_nist) {
849
+ method = EC_GFp_nist_method();
850
+ #if !defined(OPENSSL_NO_EC2M)
851
+ } else if (id == s_GF2m_simple) {
852
+ method = EC_GF2m_simple_method();
853
+ #endif
854
+ }
855
+
856
+ if (method) {
857
+ if ((group = EC_GROUP_new(method)) == NULL)
858
+ ossl_raise(eEC_GROUP, "EC_GROUP_new");
859
+ } else {
860
+ ossl_raise(rb_eArgError, "unknown symbol, must be :GFp_simple, :GFp_mont, :GFp_nist or :GF2m_simple");
861
+ }
862
+ } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
863
+ const EC_GROUP *arg1_group;
864
+
865
+ SafeRequire_EC_GROUP(arg1, arg1_group);
866
+ if ((group = EC_GROUP_dup(arg1_group)) == NULL)
867
+ ossl_raise(eEC_GROUP, "EC_GROUP_dup");
868
+ } else {
869
+ BIO *in = ossl_obj2bio(arg1);
870
+
871
+ group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
872
+ if (!group) {
873
+ OSSL_BIO_reset(in);
874
+ group = d2i_ECPKParameters_bio(in, NULL);
875
+ }
876
+
877
+ BIO_free(in);
878
+
879
+ if (!group) {
880
+ const char *name = StringValueCStr(arg1);
881
+ int nid = OBJ_sn2nid(name);
882
+
883
+ ossl_clear_error(); /* ignore errors in d2i_ECPKParameters_bio() */
884
+ if (nid == NID_undef)
885
+ ossl_raise(eEC_GROUP, "unknown curve name (%"PRIsVALUE")", arg1);
886
+
887
+ group = EC_GROUP_new_by_curve_name(nid);
888
+ if (group == NULL)
889
+ ossl_raise(eEC_GROUP, "unable to create curve (%"PRIsVALUE")", arg1);
890
+
891
+ EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
892
+ EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
893
+ }
894
+ }
895
+
896
+ break;
897
+ case 4:
898
+ if (SYMBOL_P(arg1)) {
899
+ ID id = SYM2ID(arg1);
900
+ EC_GROUP *(*new_curve)(const BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *) = NULL;
901
+ const BIGNUM *p = GetBNPtr(arg2);
902
+ const BIGNUM *a = GetBNPtr(arg3);
903
+ const BIGNUM *b = GetBNPtr(arg4);
904
+
905
+ if (id == s_GFp) {
906
+ new_curve = EC_GROUP_new_curve_GFp;
907
+ #if !defined(OPENSSL_NO_EC2M)
908
+ } else if (id == s_GF2m) {
909
+ new_curve = EC_GROUP_new_curve_GF2m;
910
+ #endif
911
+ } else {
912
+ ossl_raise(rb_eArgError, "unknown symbol, must be :GFp or :GF2m");
913
+ }
914
+
915
+ if ((group = new_curve(p, a, b, ossl_bn_ctx)) == NULL)
916
+ ossl_raise(eEC_GROUP, "EC_GROUP_new_by_GF*");
917
+ } else {
918
+ ossl_raise(rb_eArgError, "unknown argument, must be :GFp or :GF2m");
919
+ }
920
+
921
+ break;
922
+ default:
923
+ ossl_raise(rb_eArgError, "wrong number of arguments");
924
+ }
925
+
926
+ if (group == NULL)
927
+ ossl_raise(eEC_GROUP, "");
928
+
929
+ ec_group->group = group;
930
+
931
+ return self;
932
+ }
933
+
934
+ static VALUE
935
+ ossl_ec_group_initialize_copy(VALUE self, VALUE other)
936
+ {
937
+ ossl_ec_group *ec_group;
938
+ EC_GROUP *orig;
939
+
940
+ TypedData_Get_Struct(self, ossl_ec_group, &ossl_ec_group_type, ec_group);
941
+ if (ec_group->group)
942
+ ossl_raise(eEC_GROUP, "EC::Group already initialized");
943
+ SafeRequire_EC_GROUP(other, orig);
944
+
945
+ ec_group->group = EC_GROUP_dup(orig);
946
+ if (!ec_group->group)
947
+ ossl_raise(eEC_GROUP, "EC_GROUP_dup");
948
+
949
+ rb_ivar_set(self, id_i_key, Qnil);
950
+
951
+ return self;
952
+ }
953
+
954
+ /*
955
+ * call-seq:
956
+ * group1.eql?(group2) => true | false
957
+ * group1 == group2 => true | false
958
+ *
959
+ * Returns true if the two groups use the same curve and have the same
960
+ * parameters, false otherwise.
961
+ */
962
+ static VALUE ossl_ec_group_eql(VALUE a, VALUE b)
963
+ {
964
+ EC_GROUP *group1 = NULL, *group2 = NULL;
965
+
966
+ Require_EC_GROUP(a, group1);
967
+ SafeRequire_EC_GROUP(b, group2);
968
+
969
+ if (EC_GROUP_cmp(group1, group2, ossl_bn_ctx) == 1)
970
+ return Qfalse;
971
+
972
+ return Qtrue;
973
+ }
974
+
975
+ /*
976
+ * call-seq:
977
+ * group.generator => ec_point
978
+ *
979
+ * Returns the generator of the group.
980
+ *
981
+ * See the OpenSSL documentation for EC_GROUP_get0_generator()
982
+ */
983
+ static VALUE ossl_ec_group_get_generator(VALUE self)
984
+ {
985
+ VALUE point_obj;
986
+ EC_GROUP *group = NULL;
987
+
988
+ Require_EC_GROUP(self, group);
989
+
990
+ point_obj = ossl_ec_point_dup(EC_GROUP_get0_generator(group), self);
991
+
992
+ return point_obj;
993
+ }
994
+
995
+ /*
996
+ * call-seq:
997
+ * group.set_generator(generator, order, cofactor) => self
998
+ *
999
+ * Sets the curve parameters. +generator+ must be an instance of EC::Point that
1000
+ * is on the curve. +order+ and +cofactor+ are integers.
1001
+ *
1002
+ * See the OpenSSL documentation for EC_GROUP_set_generator()
1003
+ */
1004
+ static VALUE ossl_ec_group_set_generator(VALUE self, VALUE generator, VALUE order, VALUE cofactor)
1005
+ {
1006
+ EC_GROUP *group = NULL;
1007
+ const EC_POINT *point;
1008
+ const BIGNUM *o, *co;
1009
+
1010
+ Require_EC_GROUP(self, group);
1011
+ SafeRequire_EC_POINT(generator, point);
1012
+ o = GetBNPtr(order);
1013
+ co = GetBNPtr(cofactor);
1014
+
1015
+ if (EC_GROUP_set_generator(group, point, o, co) != 1)
1016
+ ossl_raise(eEC_GROUP, "EC_GROUP_set_generator");
1017
+
1018
+ return self;
1019
+ }
1020
+
1021
+ /*
1022
+ * call-seq:
1023
+ * group.get_order => order_bn
1024
+ *
1025
+ * Returns the order of the group.
1026
+ *
1027
+ * See the OpenSSL documentation for EC_GROUP_get_order()
1028
+ */
1029
+ static VALUE ossl_ec_group_get_order(VALUE self)
1030
+ {
1031
+ VALUE bn_obj;
1032
+ BIGNUM *bn;
1033
+ EC_GROUP *group = NULL;
1034
+
1035
+ Require_EC_GROUP(self, group);
1036
+
1037
+ bn_obj = ossl_bn_new(NULL);
1038
+ bn = GetBNPtr(bn_obj);
1039
+
1040
+ if (EC_GROUP_get_order(group, bn, ossl_bn_ctx) != 1)
1041
+ ossl_raise(eEC_GROUP, "EC_GROUP_get_order");
1042
+
1043
+ return bn_obj;
1044
+ }
1045
+
1046
+ /*
1047
+ * call-seq:
1048
+ * group.get_cofactor => cofactor_bn
1049
+ *
1050
+ * Returns the cofactor of the group.
1051
+ *
1052
+ * See the OpenSSL documentation for EC_GROUP_get_cofactor()
1053
+ */
1054
+ static VALUE ossl_ec_group_get_cofactor(VALUE self)
1055
+ {
1056
+ VALUE bn_obj;
1057
+ BIGNUM *bn;
1058
+ EC_GROUP *group = NULL;
1059
+
1060
+ Require_EC_GROUP(self, group);
1061
+
1062
+ bn_obj = ossl_bn_new(NULL);
1063
+ bn = GetBNPtr(bn_obj);
1064
+
1065
+ if (EC_GROUP_get_cofactor(group, bn, ossl_bn_ctx) != 1)
1066
+ ossl_raise(eEC_GROUP, "EC_GROUP_get_cofactor");
1067
+
1068
+ return bn_obj;
1069
+ }
1070
+
1071
+ /*
1072
+ * call-seq:
1073
+ * group.curve_name => String
1074
+ *
1075
+ * Returns the curve name (sn).
1076
+ *
1077
+ * See the OpenSSL documentation for EC_GROUP_get_curve_name()
1078
+ */
1079
+ static VALUE ossl_ec_group_get_curve_name(VALUE self)
1080
+ {
1081
+ EC_GROUP *group = NULL;
1082
+ int nid;
1083
+
1084
+ Get_EC_GROUP(self, group);
1085
+ if (group == NULL)
1086
+ return Qnil;
1087
+
1088
+ nid = EC_GROUP_get_curve_name(group);
1089
+
1090
+ /* BUG: an nid or asn1 object should be returned, maybe. */
1091
+ return rb_str_new2(OBJ_nid2sn(nid));
1092
+ }
1093
+
1094
+ /*
1095
+ * call-seq:
1096
+ * EC.builtin_curves => [[sn, comment], ...]
1097
+ *
1098
+ * Obtains a list of all predefined curves by the OpenSSL. Curve names are
1099
+ * returned as sn.
1100
+ *
1101
+ * See the OpenSSL documentation for EC_get_builtin_curves().
1102
+ */
1103
+ static VALUE ossl_s_builtin_curves(VALUE self)
1104
+ {
1105
+ EC_builtin_curve *curves = NULL;
1106
+ int n;
1107
+ int crv_len = rb_long2int(EC_get_builtin_curves(NULL, 0));
1108
+ VALUE ary, ret;
1109
+
1110
+ curves = ALLOCA_N(EC_builtin_curve, crv_len);
1111
+ if (curves == NULL)
1112
+ return Qnil;
1113
+ if (!EC_get_builtin_curves(curves, crv_len))
1114
+ ossl_raise(rb_eRuntimeError, "EC_get_builtin_curves");
1115
+
1116
+ ret = rb_ary_new2(crv_len);
1117
+
1118
+ for (n = 0; n < crv_len; n++) {
1119
+ const char *sname = OBJ_nid2sn(curves[n].nid);
1120
+ const char *comment = curves[n].comment;
1121
+
1122
+ ary = rb_ary_new2(2);
1123
+ rb_ary_push(ary, rb_str_new2(sname));
1124
+ rb_ary_push(ary, comment ? rb_str_new2(comment) : Qnil);
1125
+ rb_ary_push(ret, ary);
1126
+ }
1127
+
1128
+ return ret;
1129
+ }
1130
+
1131
+ /*
1132
+ * call-seq:
1133
+ * group.asn1_flag -> Integer
1134
+ *
1135
+ * Returns the flags set on the group.
1136
+ *
1137
+ * See also #asn1_flag=.
1138
+ */
1139
+ static VALUE ossl_ec_group_get_asn1_flag(VALUE self)
1140
+ {
1141
+ EC_GROUP *group = NULL;
1142
+ int flag;
1143
+
1144
+ Require_EC_GROUP(self, group);
1145
+
1146
+ flag = EC_GROUP_get_asn1_flag(group);
1147
+
1148
+ return INT2NUM(flag);
1149
+ }
1150
+
1151
+ /*
1152
+ * call-seq:
1153
+ * group.asn1_flag = flags
1154
+ *
1155
+ * Sets flags on the group. The flag value is used to determine how to encode
1156
+ * the group: encode explicit parameters or named curve using an OID.
1157
+ *
1158
+ * The flag value can be either of:
1159
+ *
1160
+ * * EC::NAMED_CURVE
1161
+ * * EC::EXPLICIT_CURVE
1162
+ *
1163
+ * See the OpenSSL documentation for EC_GROUP_set_asn1_flag().
1164
+ */
1165
+ static VALUE ossl_ec_group_set_asn1_flag(VALUE self, VALUE flag_v)
1166
+ {
1167
+ EC_GROUP *group = NULL;
1168
+
1169
+ Require_EC_GROUP(self, group);
1170
+
1171
+ EC_GROUP_set_asn1_flag(group, NUM2INT(flag_v));
1172
+
1173
+ return flag_v;
1174
+ }
1175
+
1176
+ /*
1177
+ * call-seq:
1178
+ * group.point_conversion_form -> Symbol
1179
+ *
1180
+ * Returns the form how EC::Point data is encoded as ASN.1.
1181
+ *
1182
+ * See also #point_conversion_form=.
1183
+ */
1184
+ static VALUE ossl_ec_group_get_point_conversion_form(VALUE self)
1185
+ {
1186
+ EC_GROUP *group = NULL;
1187
+ point_conversion_form_t form;
1188
+ VALUE ret;
1189
+
1190
+ Require_EC_GROUP(self, group);
1191
+
1192
+ form = EC_GROUP_get_point_conversion_form(group);
1193
+
1194
+ switch (form) {
1195
+ case POINT_CONVERSION_UNCOMPRESSED: ret = ID_uncompressed; break;
1196
+ case POINT_CONVERSION_COMPRESSED: ret = ID_compressed; break;
1197
+ case POINT_CONVERSION_HYBRID: ret = ID_hybrid; break;
1198
+ default: ossl_raise(eEC_GROUP, "unsupported point conversion form: %d, this module should be updated", form);
1199
+ }
1200
+
1201
+ return ID2SYM(ret);
1202
+ }
1203
+
1204
+ /*
1205
+ * call-seq:
1206
+ * group.point_conversion_form = form
1207
+ *
1208
+ * Sets the form how EC::Point data is encoded as ASN.1 as defined in X9.62.
1209
+ *
1210
+ * +format+ can be one of these:
1211
+ *
1212
+ * :compressed::
1213
+ * Encoded as z||x, where z is an octet indicating which solution of the
1214
+ * equation y is. z will be 0x02 or 0x03.
1215
+ * :uncompressed::
1216
+ * Encoded as z||x||y, where z is an octet 0x04.
1217
+ * :hybrid::
1218
+ * Encodes as z||x||y, where z is an octet indicating which solution of the
1219
+ * equation y is. z will be 0x06 or 0x07.
1220
+ *
1221
+ * See the OpenSSL documentation for EC_GROUP_set_point_conversion_form()
1222
+ */
1223
+ static VALUE ossl_ec_group_set_point_conversion_form(VALUE self, VALUE form_v)
1224
+ {
1225
+ EC_GROUP *group = NULL;
1226
+ point_conversion_form_t form;
1227
+ ID form_id = SYM2ID(form_v);
1228
+
1229
+ Require_EC_GROUP(self, group);
1230
+
1231
+ if (form_id == ID_uncompressed) {
1232
+ form = POINT_CONVERSION_UNCOMPRESSED;
1233
+ } else if (form_id == ID_compressed) {
1234
+ form = POINT_CONVERSION_COMPRESSED;
1235
+ } else if (form_id == ID_hybrid) {
1236
+ form = POINT_CONVERSION_HYBRID;
1237
+ } else {
1238
+ ossl_raise(rb_eArgError, "form must be :compressed, :uncompressed, or :hybrid");
1239
+ }
1240
+
1241
+ EC_GROUP_set_point_conversion_form(group, form);
1242
+
1243
+ return form_v;
1244
+ }
1245
+
1246
+ /*
1247
+ * call-seq:
1248
+ * group.seed => String or nil
1249
+ *
1250
+ * See the OpenSSL documentation for EC_GROUP_get0_seed()
1251
+ */
1252
+ static VALUE ossl_ec_group_get_seed(VALUE self)
1253
+ {
1254
+ EC_GROUP *group = NULL;
1255
+ size_t seed_len;
1256
+
1257
+ Require_EC_GROUP(self, group);
1258
+
1259
+ seed_len = EC_GROUP_get_seed_len(group);
1260
+
1261
+ if (seed_len == 0)
1262
+ return Qnil;
1263
+
1264
+ return rb_str_new((const char *)EC_GROUP_get0_seed(group), seed_len);
1265
+ }
1266
+
1267
+ /*
1268
+ * call-seq:
1269
+ * group.seed = seed => seed
1270
+ *
1271
+ * See the OpenSSL documentation for EC_GROUP_set_seed()
1272
+ */
1273
+ static VALUE ossl_ec_group_set_seed(VALUE self, VALUE seed)
1274
+ {
1275
+ EC_GROUP *group = NULL;
1276
+
1277
+ Require_EC_GROUP(self, group);
1278
+ StringValue(seed);
1279
+
1280
+ if (EC_GROUP_set_seed(group, (unsigned char *)RSTRING_PTR(seed), RSTRING_LEN(seed)) != (size_t)RSTRING_LEN(seed))
1281
+ ossl_raise(eEC_GROUP, "EC_GROUP_set_seed");
1282
+
1283
+ return seed;
1284
+ }
1285
+
1286
+ /* get/set curve GFp, GF2m */
1287
+
1288
+ /*
1289
+ * call-seq:
1290
+ * group.degree => Fixnum
1291
+ *
1292
+ * See the OpenSSL documentation for EC_GROUP_get_degree()
1293
+ */
1294
+ static VALUE ossl_ec_group_get_degree(VALUE self)
1295
+ {
1296
+ EC_GROUP *group = NULL;
1297
+
1298
+ Require_EC_GROUP(self, group);
1299
+
1300
+ return INT2NUM(EC_GROUP_get_degree(group));
1301
+ }
1302
+
1303
+ static VALUE ossl_ec_group_to_string(VALUE self, int format)
1304
+ {
1305
+ EC_GROUP *group;
1306
+ BIO *out;
1307
+ int i = -1;
1308
+ VALUE str;
1309
+
1310
+ Get_EC_GROUP(self, group);
1311
+
1312
+ if (!(out = BIO_new(BIO_s_mem())))
1313
+ ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())");
1314
+
1315
+ switch(format) {
1316
+ case EXPORT_PEM:
1317
+ i = PEM_write_bio_ECPKParameters(out, group);
1318
+ break;
1319
+ case EXPORT_DER:
1320
+ i = i2d_ECPKParameters_bio(out, group);
1321
+ break;
1322
+ default:
1323
+ BIO_free(out);
1324
+ ossl_raise(rb_eRuntimeError, "unknown format (internal error)");
1325
+ }
1326
+
1327
+ if (i != 1) {
1328
+ BIO_free(out);
1329
+ ossl_raise(eECError, NULL);
1330
+ }
1331
+
1332
+ str = ossl_membio2str(out);
1333
+
1334
+ return str;
1335
+ }
1336
+
1337
+ /*
1338
+ * call-seq:
1339
+ * group.to_pem => String
1340
+ *
1341
+ * See the OpenSSL documentation for PEM_write_bio_ECPKParameters()
1342
+ */
1343
+ static VALUE ossl_ec_group_to_pem(VALUE self)
1344
+ {
1345
+ return ossl_ec_group_to_string(self, EXPORT_PEM);
1346
+ }
1347
+
1348
+ /*
1349
+ * call-seq:
1350
+ * group.to_der => String
1351
+ *
1352
+ * See the OpenSSL documentation for i2d_ECPKParameters_bio()
1353
+ */
1354
+ static VALUE ossl_ec_group_to_der(VALUE self)
1355
+ {
1356
+ return ossl_ec_group_to_string(self, EXPORT_DER);
1357
+ }
1358
+
1359
+ /*
1360
+ * call-seq:
1361
+ * group.to_text => String
1362
+ *
1363
+ * See the OpenSSL documentation for ECPKParameters_print()
1364
+ */
1365
+ static VALUE ossl_ec_group_to_text(VALUE self)
1366
+ {
1367
+ EC_GROUP *group;
1368
+ BIO *out;
1369
+ VALUE str;
1370
+
1371
+ Require_EC_GROUP(self, group);
1372
+ if (!(out = BIO_new(BIO_s_mem()))) {
1373
+ ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())");
1374
+ }
1375
+ if (!ECPKParameters_print(out, group, 0)) {
1376
+ BIO_free(out);
1377
+ ossl_raise(eEC_GROUP, NULL);
1378
+ }
1379
+ str = ossl_membio2str(out);
1380
+
1381
+ return str;
1382
+ }
1383
+
1384
+
1385
+ static void ossl_ec_point_free(void *ptr)
1386
+ {
1387
+ ossl_ec_point *ec_point = ptr;
1388
+ if (!ec_point->dont_free && ec_point->point)
1389
+ EC_POINT_clear_free(ec_point->point);
1390
+ ruby_xfree(ec_point);
1391
+ }
1392
+
1393
+ static const rb_data_type_t ossl_ec_point_type = {
1394
+ "OpenSSL/ec_point",
1395
+ {
1396
+ 0, ossl_ec_point_free,
1397
+ },
1398
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
1399
+ };
1400
+
1401
+ static VALUE ossl_ec_point_alloc(VALUE klass)
1402
+ {
1403
+ ossl_ec_point *ec_point;
1404
+ VALUE obj;
1405
+
1406
+ obj = TypedData_Make_Struct(klass, ossl_ec_point, &ossl_ec_point_type, ec_point);
1407
+
1408
+ return obj;
1409
+ }
1410
+
1411
+ /*
1412
+ * call-seq:
1413
+ * OpenSSL::PKey::EC::Point.new(point)
1414
+ * OpenSSL::PKey::EC::Point.new(group)
1415
+ * OpenSSL::PKey::EC::Point.new(group, bn)
1416
+ *
1417
+ * See the OpenSSL documentation for EC_POINT_*
1418
+ */
1419
+ static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
1420
+ {
1421
+ ossl_ec_point *ec_point;
1422
+ EC_POINT *point = NULL;
1423
+ VALUE arg1, arg2;
1424
+ VALUE group_v = Qnil;
1425
+ const EC_GROUP *group = NULL;
1426
+
1427
+ TypedData_Get_Struct(self, ossl_ec_point, &ossl_ec_point_type, ec_point);
1428
+ if (ec_point->point)
1429
+ ossl_raise(eEC_POINT, "EC_POINT already initialized");
1430
+
1431
+ switch (rb_scan_args(argc, argv, "11", &arg1, &arg2)) {
1432
+ case 1:
1433
+ if (rb_obj_is_kind_of(arg1, cEC_POINT)) {
1434
+ const EC_POINT *arg_point;
1435
+
1436
+ group_v = rb_attr_get(arg1, id_i_group);
1437
+ SafeRequire_EC_GROUP(group_v, group);
1438
+ SafeRequire_EC_POINT(arg1, arg_point);
1439
+
1440
+ point = EC_POINT_dup(arg_point, group);
1441
+ } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
1442
+ group_v = arg1;
1443
+ SafeRequire_EC_GROUP(group_v, group);
1444
+
1445
+ point = EC_POINT_new(group);
1446
+ } else {
1447
+ ossl_raise(eEC_POINT, "wrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group");
1448
+ }
1449
+
1450
+ break;
1451
+ case 2:
1452
+ if (!rb_obj_is_kind_of(arg1, cEC_GROUP))
1453
+ ossl_raise(rb_eArgError, "1st argument must be OpenSSL::PKey::EC::Group");
1454
+ group_v = arg1;
1455
+ SafeRequire_EC_GROUP(group_v, group);
1456
+
1457
+ if (rb_obj_is_kind_of(arg2, cBN)) {
1458
+ const BIGNUM *bn = GetBNPtr(arg2);
1459
+
1460
+ point = EC_POINT_bn2point(group, bn, NULL, ossl_bn_ctx);
1461
+ } else {
1462
+ BIO *in = ossl_obj2bio(arg1);
1463
+
1464
+ /* BUG: finish me */
1465
+
1466
+ BIO_free(in);
1467
+
1468
+ if (point == NULL) {
1469
+ ossl_raise(eEC_POINT, "unknown type for 2nd arg");
1470
+ }
1471
+ }
1472
+ break;
1473
+ default:
1474
+ ossl_raise(rb_eArgError, "wrong number of arguments");
1475
+ }
1476
+
1477
+ if (point == NULL)
1478
+ ossl_raise(eEC_POINT, NULL);
1479
+
1480
+ if (NIL_P(group_v))
1481
+ ossl_raise(rb_eRuntimeError, "missing group (internal error)");
1482
+
1483
+ ec_point->point = point;
1484
+
1485
+ rb_ivar_set(self, id_i_group, group_v);
1486
+
1487
+ return self;
1488
+ }
1489
+
1490
+ static VALUE
1491
+ ossl_ec_point_initialize_copy(VALUE self, VALUE other)
1492
+ {
1493
+ ossl_ec_point *ec_point;
1494
+ EC_POINT *orig;
1495
+ EC_GROUP *group;
1496
+ VALUE group_v;
1497
+
1498
+ TypedData_Get_Struct(self, ossl_ec_point, &ossl_ec_point_type, ec_point);
1499
+ if (ec_point->point)
1500
+ ossl_raise(eEC_POINT, "EC::Point already initialized");
1501
+ SafeRequire_EC_POINT(other, orig);
1502
+
1503
+ group_v = rb_obj_dup(rb_attr_get(other, id_i_group));
1504
+ SafeRequire_EC_GROUP(group_v, group);
1505
+
1506
+ ec_point->point = EC_POINT_dup(orig, group);
1507
+ if (!ec_point->point)
1508
+ ossl_raise(eEC_POINT, "EC_POINT_dup");
1509
+ rb_ivar_set(self, id_i_key, Qnil);
1510
+ rb_ivar_set(self, id_i_group, group_v);
1511
+
1512
+ return self;
1513
+ }
1514
+
1515
+ /*
1516
+ * call-seq:
1517
+ * point1.eql?(point2) => true | false
1518
+ * point1 == point2 => true | false
1519
+ */
1520
+ static VALUE ossl_ec_point_eql(VALUE a, VALUE b)
1521
+ {
1522
+ EC_POINT *point1, *point2;
1523
+ VALUE group_v1 = rb_attr_get(a, id_i_group);
1524
+ VALUE group_v2 = rb_attr_get(b, id_i_group);
1525
+ const EC_GROUP *group;
1526
+
1527
+ if (ossl_ec_group_eql(group_v1, group_v2) == Qfalse)
1528
+ return Qfalse;
1529
+
1530
+ Require_EC_POINT(a, point1);
1531
+ SafeRequire_EC_POINT(b, point2);
1532
+ SafeRequire_EC_GROUP(group_v1, group);
1533
+
1534
+ if (EC_POINT_cmp(group, point1, point2, ossl_bn_ctx) == 1)
1535
+ return Qfalse;
1536
+
1537
+ return Qtrue;
1538
+ }
1539
+
1540
+ /*
1541
+ * call-seq:
1542
+ * point.infinity? => true | false
1543
+ */
1544
+ static VALUE ossl_ec_point_is_at_infinity(VALUE self)
1545
+ {
1546
+ EC_POINT *point;
1547
+ VALUE group_v = rb_attr_get(self, id_i_group);
1548
+ const EC_GROUP *group;
1549
+
1550
+ Require_EC_POINT(self, point);
1551
+ SafeRequire_EC_GROUP(group_v, group);
1552
+
1553
+ switch (EC_POINT_is_at_infinity(group, point)) {
1554
+ case 1: return Qtrue;
1555
+ case 0: return Qfalse;
1556
+ default: ossl_raise(cEC_POINT, "EC_POINT_is_at_infinity");
1557
+ }
1558
+
1559
+ UNREACHABLE;
1560
+ }
1561
+
1562
+ /*
1563
+ * call-seq:
1564
+ * point.on_curve? => true | false
1565
+ */
1566
+ static VALUE ossl_ec_point_is_on_curve(VALUE self)
1567
+ {
1568
+ EC_POINT *point;
1569
+ VALUE group_v = rb_attr_get(self, id_i_group);
1570
+ const EC_GROUP *group;
1571
+
1572
+ Require_EC_POINT(self, point);
1573
+ SafeRequire_EC_GROUP(group_v, group);
1574
+
1575
+ switch (EC_POINT_is_on_curve(group, point, ossl_bn_ctx)) {
1576
+ case 1: return Qtrue;
1577
+ case 0: return Qfalse;
1578
+ default: ossl_raise(cEC_POINT, "EC_POINT_is_on_curve");
1579
+ }
1580
+
1581
+ UNREACHABLE;
1582
+ }
1583
+
1584
+ /*
1585
+ * call-seq:
1586
+ * point.make_affine! => self
1587
+ */
1588
+ static VALUE ossl_ec_point_make_affine(VALUE self)
1589
+ {
1590
+ EC_POINT *point;
1591
+ VALUE group_v = rb_attr_get(self, id_i_group);
1592
+ const EC_GROUP *group;
1593
+
1594
+ Require_EC_POINT(self, point);
1595
+ SafeRequire_EC_GROUP(group_v, group);
1596
+
1597
+ if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1)
1598
+ ossl_raise(cEC_POINT, "EC_POINT_make_affine");
1599
+
1600
+ return self;
1601
+ }
1602
+
1603
+ /*
1604
+ * call-seq:
1605
+ * point.invert! => self
1606
+ */
1607
+ static VALUE ossl_ec_point_invert(VALUE self)
1608
+ {
1609
+ EC_POINT *point;
1610
+ VALUE group_v = rb_attr_get(self, id_i_group);
1611
+ const EC_GROUP *group;
1612
+
1613
+ Require_EC_POINT(self, point);
1614
+ SafeRequire_EC_GROUP(group_v, group);
1615
+
1616
+ if (EC_POINT_invert(group, point, ossl_bn_ctx) != 1)
1617
+ ossl_raise(cEC_POINT, "EC_POINT_invert");
1618
+
1619
+ return self;
1620
+ }
1621
+
1622
+ /*
1623
+ * call-seq:
1624
+ * point.set_to_infinity! => self
1625
+ */
1626
+ static VALUE ossl_ec_point_set_to_infinity(VALUE self)
1627
+ {
1628
+ EC_POINT *point;
1629
+ VALUE group_v = rb_attr_get(self, id_i_group);
1630
+ const EC_GROUP *group;
1631
+
1632
+ Require_EC_POINT(self, point);
1633
+ SafeRequire_EC_GROUP(group_v, group);
1634
+
1635
+ if (EC_POINT_set_to_infinity(group, point) != 1)
1636
+ ossl_raise(cEC_POINT, "EC_POINT_set_to_infinity");
1637
+
1638
+ return self;
1639
+ }
1640
+
1641
+ /*
1642
+ * call-seq:
1643
+ * point.to_bn => OpenSSL::BN
1644
+ *
1645
+ * See the OpenSSL documentation for EC_POINT_point2bn()
1646
+ */
1647
+ static VALUE ossl_ec_point_to_bn(VALUE self)
1648
+ {
1649
+ EC_POINT *point;
1650
+ VALUE bn_obj;
1651
+ VALUE group_v = rb_attr_get(self, id_i_group);
1652
+ const EC_GROUP *group;
1653
+ point_conversion_form_t form;
1654
+ BIGNUM *bn;
1655
+
1656
+ Require_EC_POINT(self, point);
1657
+ SafeRequire_EC_GROUP(group_v, group);
1658
+
1659
+ form = EC_GROUP_get_point_conversion_form(group);
1660
+
1661
+ bn_obj = rb_obj_alloc(cBN);
1662
+ bn = GetBNPtr(bn_obj);
1663
+
1664
+ if (EC_POINT_point2bn(group, point, form, bn, ossl_bn_ctx) == NULL)
1665
+ ossl_raise(eEC_POINT, "EC_POINT_point2bn");
1666
+
1667
+ return bn_obj;
1668
+ }
1669
+
1670
+ /*
1671
+ * call-seq:
1672
+ * point.mul(bn1 [, bn2]) => point
1673
+ * point.mul(bns, points [, bn2]) => point
1674
+ *
1675
+ * Performs elliptic curve point multiplication.
1676
+ *
1677
+ * The first form calculates <tt>bn1 * point + bn2 * G</tt>, where +G+ is the
1678
+ * generator of the group of +point+. +bn2+ may be ommitted, and in that case,
1679
+ * the result is just <tt>bn1 * point</tt>.
1680
+ *
1681
+ * The second form calculates <tt>bns[0] * point + bns[1] * points[0] + ...
1682
+ * + bns[-1] * points[-1] + bn2 * G</tt>. +bn2+ may be ommitted. +bns+ must be
1683
+ * an array of OpenSSL::BN. +points+ must be an array of
1684
+ * OpenSSL::PKey::EC::Point. Please note that <tt>points[0]</tt> is not
1685
+ * multiplied by <tt>bns[0]</tt>, but <tt>bns[1]</tt>.
1686
+ */
1687
+ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
1688
+ {
1689
+ EC_POINT *point_self, *point_result;
1690
+ const EC_GROUP *group;
1691
+ VALUE group_v = rb_attr_get(self, id_i_group);
1692
+ VALUE arg1, arg2, arg3, result;
1693
+ const BIGNUM *bn_g = NULL;
1694
+
1695
+ Require_EC_POINT(self, point_self);
1696
+ SafeRequire_EC_GROUP(group_v, group);
1697
+
1698
+ result = rb_obj_alloc(cEC_POINT);
1699
+ ossl_ec_point_initialize(1, &group_v, result);
1700
+ Require_EC_POINT(result, point_result);
1701
+
1702
+ rb_scan_args(argc, argv, "12", &arg1, &arg2, &arg3);
1703
+ if (!RB_TYPE_P(arg1, T_ARRAY)) {
1704
+ BIGNUM *bn = GetBNPtr(arg1);
1705
+
1706
+ if (!NIL_P(arg2))
1707
+ bn_g = GetBNPtr(arg2);
1708
+ if (EC_POINT_mul(group, point_result, bn_g, point_self, bn, ossl_bn_ctx) != 1)
1709
+ ossl_raise(eEC_POINT, NULL);
1710
+ } else {
1711
+ /*
1712
+ * bignums | arg1[0] | arg1[1] | arg1[2] | ...
1713
+ * points | self | arg2[0] | arg2[1] | ...
1714
+ */
1715
+ long i, num;
1716
+ VALUE tmp_p, tmp_b;
1717
+ const EC_POINT **points;
1718
+ const BIGNUM **bignums;
1719
+
1720
+ Check_Type(arg1, T_ARRAY);
1721
+ Check_Type(arg2, T_ARRAY);
1722
+ if (RARRAY_LEN(arg1) != RARRAY_LEN(arg2) + 1) /* arg2 must be 1 larger */
1723
+ ossl_raise(rb_eArgError, "bns must be 1 longer than points; see the documentation");
1724
+
1725
+ num = RARRAY_LEN(arg1);
1726
+ bignums = ALLOCV_N(const BIGNUM *, tmp_b, num);
1727
+ for (i = 0; i < num; i++)
1728
+ bignums[i] = GetBNPtr(RARRAY_AREF(arg1, i));
1729
+
1730
+ points = ALLOCV_N(const EC_POINT *, tmp_p, num);
1731
+ points[0] = point_self; /* self */
1732
+ for (i = 0; i < num - 1; i++)
1733
+ SafeRequire_EC_POINT(RARRAY_AREF(arg2, i), points[i + 1]);
1734
+
1735
+ if (!NIL_P(arg3))
1736
+ bn_g = GetBNPtr(arg3);
1737
+
1738
+ if (EC_POINTs_mul(group, point_result, bn_g, num, points, bignums, ossl_bn_ctx) != 1) {
1739
+ ALLOCV_END(tmp_b);
1740
+ ALLOCV_END(tmp_p);
1741
+ ossl_raise(eEC_POINT, NULL);
1742
+ }
1743
+
1744
+ ALLOCV_END(tmp_b);
1745
+ ALLOCV_END(tmp_p);
1746
+ }
1747
+
1748
+ return result;
1749
+ }
1750
+
1751
+ void Init_ossl_ec(void)
1752
+ {
1753
+ #if 0
1754
+ mPKey = rb_define_module_under(mOSSL, "PKey");
1755
+ cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
1756
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
1757
+ ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
1758
+ #endif
1759
+
1760
+ eECError = rb_define_class_under(mPKey, "ECError", ePKeyError);
1761
+
1762
+ /*
1763
+ * Document-class: OpenSSL::PKey::EC
1764
+ *
1765
+ * OpenSSL::PKey::EC provides access to Elliptic Curve Digital Signature
1766
+ * Algorithm (ECDSA) and Elliptic Curve Diffie-Hellman (ECDH).
1767
+ *
1768
+ * === Key exchange
1769
+ * ec1 = OpenSSL::PKey::EC.generate("prime256v1")
1770
+ * ec2 = OpenSSL::PKey::EC.generate("prime256v1")
1771
+ * # ec1 and ec2 have own private key respectively
1772
+ * shared_key1 = ec1.dh_compute_key(ec2.public_key)
1773
+ * shared_key2 = ec2.dh_compute_key(ec1.public_key)
1774
+ *
1775
+ * p shared_key1 == shared_key2 #=> true
1776
+ */
1777
+ cEC = rb_define_class_under(mPKey, "EC", cPKey);
1778
+ cEC_GROUP = rb_define_class_under(cEC, "Group", rb_cObject);
1779
+ cEC_POINT = rb_define_class_under(cEC, "Point", rb_cObject);
1780
+ eEC_GROUP = rb_define_class_under(cEC_GROUP, "Error", eOSSLError);
1781
+ eEC_POINT = rb_define_class_under(cEC_POINT, "Error", eOSSLError);
1782
+
1783
+ s_GFp = rb_intern("GFp");
1784
+ s_GF2m = rb_intern("GF2m");
1785
+ s_GFp_simple = rb_intern("GFp_simple");
1786
+ s_GFp_mont = rb_intern("GFp_mont");
1787
+ s_GFp_nist = rb_intern("GFp_nist");
1788
+ s_GF2m_simple = rb_intern("GF2m_simple");
1789
+
1790
+ ID_uncompressed = rb_intern("uncompressed");
1791
+ ID_compressed = rb_intern("compressed");
1792
+ ID_hybrid = rb_intern("hybrid");
1793
+
1794
+ rb_define_const(cEC, "NAMED_CURVE", INT2NUM(OPENSSL_EC_NAMED_CURVE));
1795
+ #if defined(OPENSSL_EC_EXPLICIT_CURVE)
1796
+ rb_define_const(cEC, "EXPLICIT_CURVE", INT2NUM(OPENSSL_EC_EXPLICIT_CURVE));
1797
+ #endif
1798
+
1799
+ rb_define_singleton_method(cEC, "builtin_curves", ossl_s_builtin_curves, 0);
1800
+
1801
+ rb_define_singleton_method(cEC, "generate", ossl_ec_key_s_generate, 1);
1802
+ rb_define_method(cEC, "initialize", ossl_ec_key_initialize, -1);
1803
+ rb_define_copy_func(cEC, ossl_ec_key_initialize_copy);
1804
+ /* copy/dup/cmp */
1805
+
1806
+ rb_define_method(cEC, "group", ossl_ec_key_get_group, 0);
1807
+ rb_define_method(cEC, "group=", ossl_ec_key_set_group, 1);
1808
+ rb_define_method(cEC, "private_key", ossl_ec_key_get_private_key, 0);
1809
+ rb_define_method(cEC, "private_key=", ossl_ec_key_set_private_key, 1);
1810
+ rb_define_method(cEC, "public_key", ossl_ec_key_get_public_key, 0);
1811
+ rb_define_method(cEC, "public_key=", ossl_ec_key_set_public_key, 1);
1812
+ rb_define_method(cEC, "private?", ossl_ec_key_is_private, 0);
1813
+ rb_define_method(cEC, "public?", ossl_ec_key_is_public, 0);
1814
+ rb_define_alias(cEC, "private_key?", "private?");
1815
+ rb_define_alias(cEC, "public_key?", "public?");
1816
+ /* rb_define_method(cEC, "", ossl_ec_key_get_, 0);
1817
+ rb_define_method(cEC, "=", ossl_ec_key_set_ 1);
1818
+ set/get enc_flags
1819
+ set/get _conv_from
1820
+ set/get asn1_flag (can use ruby to call self.group.asn1_flag)
1821
+ set/get precompute_mult
1822
+ */
1823
+ rb_define_method(cEC, "generate_key!", ossl_ec_key_generate_key, 0);
1824
+ rb_define_alias(cEC, "generate_key", "generate_key!");
1825
+ rb_define_method(cEC, "check_key", ossl_ec_key_check_key, 0);
1826
+
1827
+ rb_define_method(cEC, "dh_compute_key", ossl_ec_key_dh_compute_key, 1);
1828
+ rb_define_method(cEC, "dsa_sign_asn1", ossl_ec_key_dsa_sign_asn1, 1);
1829
+ rb_define_method(cEC, "dsa_verify_asn1", ossl_ec_key_dsa_verify_asn1, 2);
1830
+ /* do_sign/do_verify */
1831
+
1832
+ rb_define_method(cEC, "export", ossl_ec_key_export, -1);
1833
+ rb_define_alias(cEC, "to_pem", "export");
1834
+ rb_define_method(cEC, "to_der", ossl_ec_key_to_der, 0);
1835
+ rb_define_method(cEC, "to_text", ossl_ec_key_to_text, 0);
1836
+
1837
+
1838
+ rb_define_alloc_func(cEC_GROUP, ossl_ec_group_alloc);
1839
+ rb_define_method(cEC_GROUP, "initialize", ossl_ec_group_initialize, -1);
1840
+ rb_define_copy_func(cEC_GROUP, ossl_ec_group_initialize_copy);
1841
+ rb_define_method(cEC_GROUP, "eql?", ossl_ec_group_eql, 1);
1842
+ rb_define_alias(cEC_GROUP, "==", "eql?");
1843
+ /* copy/dup/cmp */
1844
+
1845
+ rb_define_method(cEC_GROUP, "generator", ossl_ec_group_get_generator, 0);
1846
+ rb_define_method(cEC_GROUP, "set_generator", ossl_ec_group_set_generator, 3);
1847
+ rb_define_method(cEC_GROUP, "order", ossl_ec_group_get_order, 0);
1848
+ rb_define_method(cEC_GROUP, "cofactor", ossl_ec_group_get_cofactor, 0);
1849
+
1850
+ rb_define_method(cEC_GROUP, "curve_name", ossl_ec_group_get_curve_name, 0);
1851
+ /* rb_define_method(cEC_GROUP, "curve_name=", ossl_ec_group_set_curve_name, 1); */
1852
+
1853
+ rb_define_method(cEC_GROUP, "asn1_flag", ossl_ec_group_get_asn1_flag, 0);
1854
+ rb_define_method(cEC_GROUP, "asn1_flag=", ossl_ec_group_set_asn1_flag, 1);
1855
+
1856
+ rb_define_method(cEC_GROUP, "point_conversion_form", ossl_ec_group_get_point_conversion_form, 0);
1857
+ rb_define_method(cEC_GROUP, "point_conversion_form=", ossl_ec_group_set_point_conversion_form, 1);
1858
+
1859
+ rb_define_method(cEC_GROUP, "seed", ossl_ec_group_get_seed, 0);
1860
+ rb_define_method(cEC_GROUP, "seed=", ossl_ec_group_set_seed, 1);
1861
+
1862
+ /* get/set GFp, GF2m */
1863
+
1864
+ rb_define_method(cEC_GROUP, "degree", ossl_ec_group_get_degree, 0);
1865
+
1866
+ /* check* */
1867
+
1868
+
1869
+ rb_define_method(cEC_GROUP, "to_pem", ossl_ec_group_to_pem, 0);
1870
+ rb_define_method(cEC_GROUP, "to_der", ossl_ec_group_to_der, 0);
1871
+ rb_define_method(cEC_GROUP, "to_text", ossl_ec_group_to_text, 0);
1872
+
1873
+
1874
+ rb_define_alloc_func(cEC_POINT, ossl_ec_point_alloc);
1875
+ rb_define_method(cEC_POINT, "initialize", ossl_ec_point_initialize, -1);
1876
+ rb_define_copy_func(cEC_POINT, ossl_ec_point_initialize_copy);
1877
+ rb_attr(cEC_POINT, rb_intern("group"), 1, 0, 0);
1878
+ rb_define_method(cEC_POINT, "eql?", ossl_ec_point_eql, 1);
1879
+ rb_define_alias(cEC_POINT, "==", "eql?");
1880
+
1881
+ rb_define_method(cEC_POINT, "infinity?", ossl_ec_point_is_at_infinity, 0);
1882
+ rb_define_method(cEC_POINT, "on_curve?", ossl_ec_point_is_on_curve, 0);
1883
+ rb_define_method(cEC_POINT, "make_affine!", ossl_ec_point_make_affine, 0);
1884
+ rb_define_method(cEC_POINT, "invert!", ossl_ec_point_invert, 0);
1885
+ rb_define_method(cEC_POINT, "set_to_infinity!", ossl_ec_point_set_to_infinity, 0);
1886
+ /* all the other methods */
1887
+
1888
+ rb_define_method(cEC_POINT, "to_bn", ossl_ec_point_to_bn, 0);
1889
+ rb_define_method(cEC_POINT, "mul", ossl_ec_point_mul, -1);
1890
+
1891
+ id_i_group = rb_intern("@group");
1892
+ id_i_key = rb_intern("@key");
1893
+ }
1894
+
1895
+ #else /* defined NO_EC */
1896
+ void Init_ossl_ec(void)
1897
+ {
1898
+ }
1899
+ #endif /* NO_EC */