rubysl-openssl 2.10 → 2.11

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