openssl-custom 2.2.2

Sign up to get free protection for your applications and to get access to all the features.
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 */