Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

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