Ruby 2.0.0p353(2013-11-22revision43784)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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