openssl-custom 2.2.2

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