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