zig_example 0.2.0 → 0.3.1

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