rubysl-openssl 2.10 → 2.11

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