openssl 2.0.9 → 2.1.0.beta1
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 +5 -5
- data/History.md +28 -69
- data/README.md +1 -1
- data/ext/openssl/deprecation.rb +0 -3
- data/ext/openssl/extconf.rb +8 -52
- data/ext/openssl/openssl_missing.c +0 -67
- data/ext/openssl/openssl_missing.h +3 -50
- data/ext/openssl/ossl.c +81 -74
- data/ext/openssl/ossl.h +14 -27
- data/ext/openssl/ossl_asn1.c +287 -374
- data/ext/openssl/ossl_asn1.h +0 -4
- data/ext/openssl/ossl_bio.c +5 -20
- data/ext/openssl/ossl_bio.h +0 -2
- data/ext/openssl/ossl_bn.c +70 -28
- data/ext/openssl/ossl_cipher.c +18 -42
- data/ext/openssl/ossl_cipher.h +1 -1
- data/ext/openssl/ossl_digest.c +8 -12
- data/ext/openssl/ossl_digest.h +1 -1
- data/ext/openssl/ossl_engine.c +47 -47
- data/ext/openssl/ossl_hmac.c +19 -22
- data/ext/openssl/ossl_kdf.c +221 -0
- data/ext/openssl/ossl_kdf.h +6 -0
- data/ext/openssl/ossl_ns_spki.c +17 -21
- data/ext/openssl/ossl_ocsp.c +85 -80
- data/ext/openssl/ossl_pkcs12.c +15 -21
- data/ext/openssl/ossl_pkcs7.c +8 -21
- data/ext/openssl/ossl_pkey.c +24 -48
- data/ext/openssl/ossl_pkey.h +1 -6
- data/ext/openssl/ossl_pkey_dh.c +11 -11
- data/ext/openssl/ossl_pkey_dsa.c +16 -22
- data/ext/openssl/ossl_pkey_ec.c +43 -56
- data/ext/openssl/ossl_pkey_rsa.c +19 -19
- data/ext/openssl/ossl_rand.c +12 -12
- data/ext/openssl/ossl_ssl.c +291 -243
- data/ext/openssl/ossl_ssl.h +0 -5
- data/ext/openssl/ossl_ssl_session.c +7 -9
- data/ext/openssl/ossl_version.h +1 -1
- data/ext/openssl/ossl_x509.c +0 -15
- data/ext/openssl/ossl_x509.h +0 -7
- data/ext/openssl/ossl_x509attr.c +3 -7
- data/ext/openssl/ossl_x509cert.c +17 -54
- data/ext/openssl/ossl_x509crl.c +15 -25
- data/ext/openssl/ossl_x509ext.c +9 -14
- data/ext/openssl/ossl_x509name.c +76 -41
- data/ext/openssl/ossl_x509req.c +10 -47
- data/ext/openssl/ossl_x509revoked.c +8 -8
- data/ext/openssl/ossl_x509store.c +15 -45
- data/ext/openssl/ruby_missing.h +2 -13
- data/lib/openssl.rb +1 -0
- data/lib/openssl/bn.rb +2 -1
- data/lib/openssl/buffering.rb +24 -23
- data/lib/openssl/config.rb +12 -11
- data/lib/openssl/digest.rb +3 -6
- data/lib/openssl/pkcs5.rb +22 -0
- data/lib/openssl/pkey.rb +0 -41
- data/lib/openssl/ssl.rb +118 -16
- data/lib/openssl/x509.rb +7 -1
- metadata +8 -7
- data/ext/openssl/ossl_pkcs5.c +0 -180
- data/ext/openssl/ossl_pkcs5.h +0 -6
data/ext/openssl/ossl_cipher.h
CHANGED
data/ext/openssl/ossl_digest.c
CHANGED
@@ -15,10 +15,6 @@
|
|
15
15
|
ossl_raise(rb_eRuntimeError, "Digest CTX wasn't initialized!"); \
|
16
16
|
} \
|
17
17
|
} while (0)
|
18
|
-
#define SafeGetDigest(obj, ctx) do { \
|
19
|
-
OSSL_Check_Kind((obj), cDigest); \
|
20
|
-
GetDigest((obj), (ctx)); \
|
21
|
-
} while (0)
|
22
18
|
|
23
19
|
/*
|
24
20
|
* Classes
|
@@ -46,7 +42,7 @@ static const rb_data_type_t ossl_digest_type = {
|
|
46
42
|
* Public
|
47
43
|
*/
|
48
44
|
const EVP_MD *
|
49
|
-
|
45
|
+
ossl_evp_get_digestbyname(VALUE obj)
|
50
46
|
{
|
51
47
|
const EVP_MD *md;
|
52
48
|
ASN1_OBJECT *oid = NULL;
|
@@ -65,7 +61,7 @@ GetDigestPtr(VALUE obj)
|
|
65
61
|
} else {
|
66
62
|
EVP_MD_CTX *ctx;
|
67
63
|
|
68
|
-
|
64
|
+
GetDigest(obj, ctx);
|
69
65
|
|
70
66
|
md = EVP_MD_CTX_md(ctx);
|
71
67
|
}
|
@@ -106,15 +102,15 @@ VALUE ossl_digest_update(VALUE, VALUE);
|
|
106
102
|
* call-seq:
|
107
103
|
* Digest.new(string [, data]) -> Digest
|
108
104
|
*
|
109
|
-
* Creates a Digest instance based on
|
105
|
+
* Creates a Digest instance based on _string_, which is either the ln
|
110
106
|
* (long name) or sn (short name) of a supported digest algorithm.
|
111
107
|
*
|
112
|
-
* If
|
108
|
+
* If _data_ (a String) is given, it is used as the initial input to the
|
113
109
|
* Digest instance, i.e.
|
114
110
|
*
|
115
111
|
* digest = OpenSSL::Digest.new('sha256', 'digestdata')
|
116
112
|
*
|
117
|
-
* is
|
113
|
+
* is equivalent to
|
118
114
|
*
|
119
115
|
* digest = OpenSSL::Digest.new('sha256')
|
120
116
|
* digest.update('digestdata')
|
@@ -127,7 +123,7 @@ ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
|
|
127
123
|
VALUE type, data;
|
128
124
|
|
129
125
|
rb_scan_args(argc, argv, "11", &type, &data);
|
130
|
-
md =
|
126
|
+
md = ossl_evp_get_digestbyname(type);
|
131
127
|
if (!NIL_P(data)) StringValue(data);
|
132
128
|
|
133
129
|
TypedData_Get_Struct(self, EVP_MD_CTX, &ossl_digest_type, ctx);
|
@@ -158,7 +154,7 @@ ossl_digest_copy(VALUE self, VALUE other)
|
|
158
154
|
if (!ctx1)
|
159
155
|
ossl_raise(eDigestError, "EVP_MD_CTX_new");
|
160
156
|
}
|
161
|
-
|
157
|
+
GetDigest(other, ctx2);
|
162
158
|
|
163
159
|
if (!EVP_MD_CTX_copy(ctx1, ctx2)) {
|
164
160
|
ossl_raise(eDigestError, NULL);
|
@@ -448,7 +444,7 @@ Init_ossl_digest(void)
|
|
448
444
|
rb_define_alloc_func(cDigest, ossl_digest_alloc);
|
449
445
|
|
450
446
|
rb_define_method(cDigest, "initialize", ossl_digest_initialize, -1);
|
451
|
-
|
447
|
+
rb_define_method(cDigest, "initialize_copy", ossl_digest_copy, 1);
|
452
448
|
rb_define_method(cDigest, "reset", ossl_digest_reset, 0);
|
453
449
|
rb_define_method(cDigest, "update", ossl_digest_update, 1);
|
454
450
|
rb_define_alias(cDigest, "<<", "update");
|
data/ext/openssl/ossl_digest.h
CHANGED
data/ext/openssl/ossl_engine.c
CHANGED
@@ -25,10 +25,6 @@
|
|
25
25
|
ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \
|
26
26
|
} \
|
27
27
|
} while (0)
|
28
|
-
#define SafeGetEngine(obj, engine) do { \
|
29
|
-
OSSL_Check_Kind((obj), cEngine); \
|
30
|
-
GetPKCS7((obj), (engine)); \
|
31
|
-
} while (0)
|
32
28
|
|
33
29
|
/*
|
34
30
|
* Classes
|
@@ -72,14 +68,13 @@ static const rb_data_type_t ossl_engine_type = {
|
|
72
68
|
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
73
69
|
};
|
74
70
|
|
75
|
-
/*
|
76
|
-
*
|
71
|
+
/*
|
77
72
|
* call-seq:
|
78
|
-
*
|
73
|
+
* OpenSSL::Engine.load(name = nil)
|
79
74
|
*
|
80
|
-
* This method loads engines. If
|
81
|
-
* loaded. Otherwise, the given
|
82
|
-
* your runtime, and returns true. If
|
75
|
+
* This method loads engines. If _name_ is nil, then all builtin engines are
|
76
|
+
* loaded. Otherwise, the given _name_, as a String, is loaded if available to
|
77
|
+
* your runtime, and returns true. If _name_ is not found, then nil is
|
83
78
|
* returned.
|
84
79
|
*
|
85
80
|
*/
|
@@ -153,9 +148,9 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
|
|
153
148
|
#endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
|
154
149
|
}
|
155
150
|
|
156
|
-
/*
|
151
|
+
/*
|
157
152
|
* call-seq:
|
158
|
-
*
|
153
|
+
* OpenSSL::Engine.cleanup
|
159
154
|
*
|
160
155
|
* It is only necessary to run cleanup when engines are loaded via
|
161
156
|
* OpenSSL::Engine.load. However, running cleanup before exit is recommended.
|
@@ -169,7 +164,9 @@ ossl_engine_s_cleanup(VALUE self)
|
|
169
164
|
return Qnil;
|
170
165
|
}
|
171
166
|
|
172
|
-
/*
|
167
|
+
/*
|
168
|
+
* call-seq:
|
169
|
+
* OpenSSL::Engine.engines -> [engine, ...]
|
173
170
|
*
|
174
171
|
* Returns an array of currently loaded engines.
|
175
172
|
*/
|
@@ -193,17 +190,16 @@ ossl_engine_s_engines(VALUE klass)
|
|
193
190
|
return ary;
|
194
191
|
}
|
195
192
|
|
196
|
-
/*
|
197
|
-
*
|
193
|
+
/*
|
198
194
|
* call-seq:
|
199
|
-
*
|
195
|
+
* OpenSSL::Engine.by_id(name) -> engine
|
200
196
|
*
|
201
|
-
*
|
197
|
+
* Fetches the engine as specified by the _id_ String.
|
202
198
|
*
|
203
199
|
* OpenSSL::Engine.by_id("openssl")
|
204
200
|
* => #<OpenSSL::Engine id="openssl" name="Software engine support">
|
205
201
|
*
|
206
|
-
* See OpenSSL::Engine.engines for the currently loaded engines
|
202
|
+
* See OpenSSL::Engine.engines for the currently loaded engines.
|
207
203
|
*/
|
208
204
|
static VALUE
|
209
205
|
ossl_engine_s_by_id(VALUE klass, VALUE id)
|
@@ -227,9 +223,11 @@ ossl_engine_s_by_id(VALUE klass, VALUE id)
|
|
227
223
|
return obj;
|
228
224
|
}
|
229
225
|
|
230
|
-
/*
|
226
|
+
/*
|
227
|
+
* call-seq:
|
228
|
+
* engine.id -> string
|
231
229
|
*
|
232
|
-
*
|
230
|
+
* Gets the id for this engine.
|
233
231
|
*
|
234
232
|
* OpenSSL::Engine.load
|
235
233
|
* OpenSSL::Engine.engines #=> [#<OpenSSL::Engine#>, ...]
|
@@ -244,9 +242,11 @@ ossl_engine_get_id(VALUE self)
|
|
244
242
|
return rb_str_new2(ENGINE_get_id(e));
|
245
243
|
}
|
246
244
|
|
247
|
-
/*
|
245
|
+
/*
|
246
|
+
* call-seq:
|
247
|
+
* engine.name -> string
|
248
248
|
*
|
249
|
-
* Get the descriptive name for this engine
|
249
|
+
* Get the descriptive name for this engine.
|
250
250
|
*
|
251
251
|
* OpenSSL::Engine.load
|
252
252
|
* OpenSSL::Engine.engines #=> [#<OpenSSL::Engine#>, ...]
|
@@ -262,7 +262,9 @@ ossl_engine_get_name(VALUE self)
|
|
262
262
|
return rb_str_new2(ENGINE_get_name(e));
|
263
263
|
}
|
264
264
|
|
265
|
-
/*
|
265
|
+
/*
|
266
|
+
* call-seq:
|
267
|
+
* engine.finish -> nil
|
266
268
|
*
|
267
269
|
* Releases all internal structural references for this engine.
|
268
270
|
*
|
@@ -279,13 +281,12 @@ ossl_engine_finish(VALUE self)
|
|
279
281
|
return Qnil;
|
280
282
|
}
|
281
283
|
|
282
|
-
/*
|
283
|
-
*
|
284
|
+
/*
|
284
285
|
* call-seq:
|
285
286
|
* engine.cipher(name) -> OpenSSL::Cipher
|
286
287
|
*
|
287
|
-
*
|
288
|
-
* engine.
|
288
|
+
* Returns a new instance of OpenSSL::Cipher by _name_, if it is available in
|
289
|
+
* this engine.
|
289
290
|
*
|
290
291
|
* An EngineError will be raised if the cipher is unavailable.
|
291
292
|
*
|
@@ -312,12 +313,11 @@ ossl_engine_get_cipher(VALUE self, VALUE name)
|
|
312
313
|
return ossl_cipher_new(ciph);
|
313
314
|
}
|
314
315
|
|
315
|
-
/*
|
316
|
-
*
|
316
|
+
/*
|
317
317
|
* call-seq:
|
318
318
|
* engine.digest(name) -> OpenSSL::Digest
|
319
319
|
*
|
320
|
-
*
|
320
|
+
* Returns a new instance of OpenSSL::Digest by _name_.
|
321
321
|
*
|
322
322
|
* Will raise an EngineError if the digest is unavailable.
|
323
323
|
*
|
@@ -345,12 +345,11 @@ ossl_engine_get_digest(VALUE self, VALUE name)
|
|
345
345
|
return ossl_digest_new(md);
|
346
346
|
}
|
347
347
|
|
348
|
-
/*
|
349
|
-
*
|
348
|
+
/*
|
350
349
|
* call-seq:
|
351
350
|
* engine.load_private_key(id = nil, data = nil) -> OpenSSL::PKey
|
352
351
|
*
|
353
|
-
* Loads the given private key by
|
352
|
+
* Loads the given private key identified by _id_ and _data_.
|
354
353
|
*
|
355
354
|
* An EngineError is raised of the OpenSSL::PKey is unavailable.
|
356
355
|
*
|
@@ -375,12 +374,11 @@ ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self)
|
|
375
374
|
return obj;
|
376
375
|
}
|
377
376
|
|
378
|
-
/*
|
379
|
-
*
|
377
|
+
/*
|
380
378
|
* call-seq:
|
381
379
|
* engine.load_public_key(id = nil, data = nil) -> OpenSSL::PKey
|
382
380
|
*
|
383
|
-
* Loads the given
|
381
|
+
* Loads the given public key identified by _id_ and _data_.
|
384
382
|
*
|
385
383
|
* An EngineError is raised of the OpenSSL::PKey is unavailable.
|
386
384
|
*
|
@@ -403,16 +401,15 @@ ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self)
|
|
403
401
|
return ossl_pkey_new(pkey);
|
404
402
|
}
|
405
403
|
|
406
|
-
/*
|
407
|
-
*
|
404
|
+
/*
|
408
405
|
* call-seq:
|
409
406
|
* engine.set_default(flag)
|
410
407
|
*
|
411
|
-
* Set the defaults for this engine with the given
|
408
|
+
* Set the defaults for this engine with the given _flag_.
|
412
409
|
*
|
413
410
|
* These flags are used to control combinations of algorithm methods.
|
414
411
|
*
|
415
|
-
*
|
412
|
+
* _flag_ can be one of the following, other flags are available depending on
|
416
413
|
* your OS.
|
417
414
|
*
|
418
415
|
* [All flags] 0xFFFF
|
@@ -432,14 +429,13 @@ ossl_engine_set_default(VALUE self, VALUE flag)
|
|
432
429
|
return Qtrue;
|
433
430
|
}
|
434
431
|
|
435
|
-
/*
|
436
|
-
*
|
432
|
+
/*
|
437
433
|
* call-seq:
|
438
434
|
* engine.ctrl_cmd(command, value = nil) -> engine
|
439
435
|
*
|
440
|
-
*
|
436
|
+
* Sends the given _command_ to this engine.
|
441
437
|
*
|
442
|
-
* Raises an EngineError if the
|
438
|
+
* Raises an EngineError if the command fails.
|
443
439
|
*/
|
444
440
|
static VALUE
|
445
441
|
ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self)
|
@@ -469,7 +465,9 @@ ossl_engine_cmd_flag_to_name(int flag)
|
|
469
465
|
}
|
470
466
|
}
|
471
467
|
|
472
|
-
/*
|
468
|
+
/*
|
469
|
+
* call-seq:
|
470
|
+
* engine.cmds -> [["name", "description", "flags"], ...]
|
473
471
|
*
|
474
472
|
* Returns an array of command definitions for the current engine
|
475
473
|
*/
|
@@ -495,9 +493,11 @@ ossl_engine_get_cmds(VALUE self)
|
|
495
493
|
return ary;
|
496
494
|
}
|
497
495
|
|
498
|
-
/*
|
496
|
+
/*
|
497
|
+
* call-seq:
|
498
|
+
* engine.inspect -> string
|
499
499
|
*
|
500
|
-
* Pretty
|
500
|
+
* Pretty prints this engine.
|
501
501
|
*/
|
502
502
|
static VALUE
|
503
503
|
ossl_engine_inspect(VALUE self)
|
data/ext/openssl/ossl_hmac.c
CHANGED
@@ -19,10 +19,6 @@
|
|
19
19
|
ossl_raise(rb_eRuntimeError, "HMAC wasn't initialized"); \
|
20
20
|
} \
|
21
21
|
} while (0)
|
22
|
-
#define SafeGetHMAC(obj, ctx) do { \
|
23
|
-
OSSL_Check_Kind((obj), cHMAC); \
|
24
|
-
GetHMAC((obj), (ctx)); \
|
25
|
-
} while (0)
|
26
22
|
|
27
23
|
/*
|
28
24
|
* Classes
|
@@ -110,7 +106,7 @@ ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
|
|
110
106
|
StringValue(key);
|
111
107
|
GetHMAC(self, ctx);
|
112
108
|
HMAC_Init_ex(ctx, RSTRING_PTR(key), RSTRING_LENINT(key),
|
113
|
-
|
109
|
+
ossl_evp_get_digestbyname(digest), NULL);
|
114
110
|
|
115
111
|
return self;
|
116
112
|
}
|
@@ -124,7 +120,7 @@ ossl_hmac_copy(VALUE self, VALUE other)
|
|
124
120
|
if (self == other) return self;
|
125
121
|
|
126
122
|
GetHMAC(self, ctx1);
|
127
|
-
|
123
|
+
GetHMAC(other, ctx2);
|
128
124
|
|
129
125
|
if (!HMAC_CTX_copy(ctx1, ctx2))
|
130
126
|
ossl_raise(eHMACError, "HMAC_CTX_copy");
|
@@ -135,7 +131,7 @@ ossl_hmac_copy(VALUE self, VALUE other)
|
|
135
131
|
* call-seq:
|
136
132
|
* hmac.update(string) -> self
|
137
133
|
*
|
138
|
-
* Returns
|
134
|
+
* Returns _hmac_ updated with the message to be authenticated.
|
139
135
|
* Can be called repeatedly with chunks of the message.
|
140
136
|
*
|
141
137
|
* === Example
|
@@ -234,7 +230,7 @@ ossl_hmac_hexdigest(VALUE self)
|
|
234
230
|
* call-seq:
|
235
231
|
* hmac.reset -> self
|
236
232
|
*
|
237
|
-
* Returns
|
233
|
+
* Returns _hmac_ as it was when it was first initialized, with all processed
|
238
234
|
* data cleared from it.
|
239
235
|
*
|
240
236
|
* === Example
|
@@ -264,16 +260,16 @@ ossl_hmac_reset(VALUE self)
|
|
264
260
|
* call-seq:
|
265
261
|
* HMAC.digest(digest, key, data) -> aString
|
266
262
|
*
|
267
|
-
* Returns the authentication code as a binary string. The
|
268
|
-
*
|
263
|
+
* Returns the authentication code as a binary string. The _digest_ parameter
|
264
|
+
* specifies the digest algorithm to use. This may be a String representing
|
265
|
+
* the algorithm name or an instance of OpenSSL::Digest.
|
269
266
|
*
|
270
267
|
* === Example
|
271
268
|
*
|
272
269
|
* key = 'key'
|
273
270
|
* data = 'The quick brown fox jumps over the lazy dog'
|
274
|
-
* digest = OpenSSL::Digest.new('sha1')
|
275
271
|
*
|
276
|
-
* hmac = OpenSSL::HMAC.digest(
|
272
|
+
* hmac = OpenSSL::HMAC.digest('sha1', key, data)
|
277
273
|
* #=> "\xDE|\x9B\x85\xB8\xB7\x8A\xA6\xBC\x8Az6\xF7\n\x90p\x1C\x9D\xB4\xD9"
|
278
274
|
*
|
279
275
|
*/
|
@@ -285,8 +281,9 @@ ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
|
|
285
281
|
|
286
282
|
StringValue(key);
|
287
283
|
StringValue(data);
|
288
|
-
buf = HMAC(
|
289
|
-
(unsigned char *)RSTRING_PTR(data),
|
284
|
+
buf = HMAC(ossl_evp_get_digestbyname(digest), RSTRING_PTR(key),
|
285
|
+
RSTRING_LENINT(key), (unsigned char *)RSTRING_PTR(data),
|
286
|
+
RSTRING_LEN(data), NULL, &buf_len);
|
290
287
|
|
291
288
|
return rb_str_new((const char *)buf, buf_len);
|
292
289
|
}
|
@@ -295,16 +292,16 @@ ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
|
|
295
292
|
* call-seq:
|
296
293
|
* HMAC.hexdigest(digest, key, data) -> aString
|
297
294
|
*
|
298
|
-
* Returns the authentication code as a hex-encoded string. The
|
299
|
-
* parameter
|
295
|
+
* Returns the authentication code as a hex-encoded string. The _digest_
|
296
|
+
* parameter specifies the digest algorithm to use. This may be a String
|
297
|
+
* representing the algorithm name or an instance of OpenSSL::Digest.
|
300
298
|
*
|
301
299
|
* === Example
|
302
300
|
*
|
303
301
|
* key = 'key'
|
304
302
|
* data = 'The quick brown fox jumps over the lazy dog'
|
305
|
-
* digest = OpenSSL::Digest.new('sha1')
|
306
303
|
*
|
307
|
-
* hmac = OpenSSL::HMAC.hexdigest(
|
304
|
+
* hmac = OpenSSL::HMAC.hexdigest('sha1', key, data)
|
308
305
|
* #=> "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"
|
309
306
|
*
|
310
307
|
*/
|
@@ -318,9 +315,9 @@ ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
|
|
318
315
|
StringValue(key);
|
319
316
|
StringValue(data);
|
320
317
|
|
321
|
-
if (!HMAC(
|
322
|
-
(unsigned char *)RSTRING_PTR(data),
|
323
|
-
buf, &buf_len))
|
318
|
+
if (!HMAC(ossl_evp_get_digestbyname(digest), RSTRING_PTR(key),
|
319
|
+
RSTRING_LENINT(key), (unsigned char *)RSTRING_PTR(data),
|
320
|
+
RSTRING_LEN(data), buf, &buf_len))
|
324
321
|
ossl_raise(eHMACError, "HMAC");
|
325
322
|
|
326
323
|
ret = rb_str_new(NULL, buf_len * 2);
|
@@ -377,7 +374,7 @@ Init_ossl_hmac(void)
|
|
377
374
|
rb_define_singleton_method(cHMAC, "hexdigest", ossl_hmac_s_hexdigest, 3);
|
378
375
|
|
379
376
|
rb_define_method(cHMAC, "initialize", ossl_hmac_initialize, 2);
|
380
|
-
|
377
|
+
rb_define_method(cHMAC, "initialize_copy", ossl_hmac_copy, 1);
|
381
378
|
|
382
379
|
rb_define_method(cHMAC, "reset", ossl_hmac_reset, 0);
|
383
380
|
rb_define_method(cHMAC, "update", ossl_hmac_update, 1);
|
@@ -0,0 +1,221 @@
|
|
1
|
+
/*
|
2
|
+
* Ruby/OpenSSL Project
|
3
|
+
* Copyright (C) 2007, 2017 Ruby/OpenSSL Project Authors
|
4
|
+
*/
|
5
|
+
#include "ossl.h"
|
6
|
+
|
7
|
+
static VALUE mKDF, eKDF;
|
8
|
+
|
9
|
+
/*
|
10
|
+
* call-seq:
|
11
|
+
* KDF.pbkdf2_hmac(pass, salt:, iterations:, length:, hash:) -> aString
|
12
|
+
*
|
13
|
+
* PKCS #5 PBKDF2 (Password-Based Key Derivation Function 2) in combination
|
14
|
+
* with HMAC. Takes _pass_, _salt_ and _iterations_, and then derives a key
|
15
|
+
* of _length_ bytes.
|
16
|
+
*
|
17
|
+
* For more information about PBKDF2, see RFC 2898 Section 5.2
|
18
|
+
* (https://tools.ietf.org/html/rfc2898#section-5.2).
|
19
|
+
*
|
20
|
+
* === Parameters
|
21
|
+
* pass :: The passphrase.
|
22
|
+
* salt :: The salt. Salts prevent attacks based on dictionaries of common
|
23
|
+
* passwords and attacks based on rainbow tables. It is a public
|
24
|
+
* value that can be safely stored along with the password (e.g.
|
25
|
+
* if the derived value is used for password storage).
|
26
|
+
* iterations :: The iteration count. This provides the ability to tune the
|
27
|
+
* algorithm. It is better to use the highest count possible for
|
28
|
+
* the maximum resistance to brute-force attacks.
|
29
|
+
* length :: The desired length of the derived key in octets.
|
30
|
+
* hash :: The hash algorithm used with HMAC for the PRF. May be a String
|
31
|
+
* representing the algorithm name, or an instance of
|
32
|
+
* OpenSSL::Digest.
|
33
|
+
*/
|
34
|
+
static VALUE
|
35
|
+
kdf_pbkdf2_hmac(int argc, VALUE *argv, VALUE self)
|
36
|
+
{
|
37
|
+
VALUE pass, salt, opts, kwargs[4], str;
|
38
|
+
static ID kwargs_ids[4];
|
39
|
+
int iters, len;
|
40
|
+
const EVP_MD *md;
|
41
|
+
|
42
|
+
if (!kwargs_ids[0]) {
|
43
|
+
kwargs_ids[0] = rb_intern_const("salt");
|
44
|
+
kwargs_ids[1] = rb_intern_const("iterations");
|
45
|
+
kwargs_ids[2] = rb_intern_const("length");
|
46
|
+
kwargs_ids[3] = rb_intern_const("hash");
|
47
|
+
}
|
48
|
+
rb_scan_args(argc, argv, "1:", &pass, &opts);
|
49
|
+
rb_get_kwargs(opts, kwargs_ids, 4, 0, kwargs);
|
50
|
+
|
51
|
+
StringValue(pass);
|
52
|
+
salt = StringValue(kwargs[0]);
|
53
|
+
iters = NUM2INT(kwargs[1]);
|
54
|
+
len = NUM2INT(kwargs[2]);
|
55
|
+
md = ossl_evp_get_digestbyname(kwargs[3]);
|
56
|
+
|
57
|
+
str = rb_str_new(0, len);
|
58
|
+
if (!PKCS5_PBKDF2_HMAC(RSTRING_PTR(pass), RSTRING_LENINT(pass),
|
59
|
+
(unsigned char *)RSTRING_PTR(salt),
|
60
|
+
RSTRING_LENINT(salt), iters, md, len,
|
61
|
+
(unsigned char *)RSTRING_PTR(str)))
|
62
|
+
ossl_raise(eKDF, "PKCS5_PBKDF2_HMAC");
|
63
|
+
|
64
|
+
return str;
|
65
|
+
}
|
66
|
+
|
67
|
+
#if defined(HAVE_EVP_PBE_SCRYPT)
|
68
|
+
/*
|
69
|
+
* call-seq:
|
70
|
+
* KDF.scrypt(pass, salt:, N:, r:, p:, length:) -> aString
|
71
|
+
*
|
72
|
+
* Derives a key from _pass_ using given parameters with the scrypt
|
73
|
+
* password-based key derivation function. The result can be used for password
|
74
|
+
* storage.
|
75
|
+
*
|
76
|
+
* scrypt is designed to be memory-hard and more secure against brute-force
|
77
|
+
* attacks using custom hardwares than alternative KDFs such as PBKDF2 or
|
78
|
+
* bcrypt.
|
79
|
+
*
|
80
|
+
* The keyword arguments _N_, _r_ and _p_ can be used to tune scrypt. RFC 7914
|
81
|
+
* (published on 2016-08, https://tools.ietf.org/html/rfc7914#section-2) states
|
82
|
+
* that using values r=8 and p=1 appears to yield good results.
|
83
|
+
*
|
84
|
+
* See RFC 7914 (https://tools.ietf.org/html/rfc7914) for more information.
|
85
|
+
*
|
86
|
+
* === Parameters
|
87
|
+
* pass :: Passphrase.
|
88
|
+
* salt :: Salt.
|
89
|
+
* N :: CPU/memory cost parameter. This must be a power of 2.
|
90
|
+
* r :: Block size parameter.
|
91
|
+
* p :: Parallelization parameter.
|
92
|
+
* length :: Length in octets of the derived key.
|
93
|
+
*
|
94
|
+
* === Example
|
95
|
+
* pass = "password"
|
96
|
+
* salt = SecureRandom.random_bytes(16)
|
97
|
+
* dk = OpenSSL::KDF.scrypt(pass, salt: salt, N: 2**14, r: 8, p: 1, length: 32)
|
98
|
+
* p dk #=> "\xDA\xE4\xE2...\x7F\xA1\x01T"
|
99
|
+
*/
|
100
|
+
static VALUE
|
101
|
+
kdf_scrypt(int argc, VALUE *argv, VALUE self)
|
102
|
+
{
|
103
|
+
VALUE pass, salt, opts, kwargs[5], str;
|
104
|
+
static ID kwargs_ids[5];
|
105
|
+
size_t len;
|
106
|
+
uint64_t N, r, p, maxmem;
|
107
|
+
|
108
|
+
if (!kwargs_ids[0]) {
|
109
|
+
kwargs_ids[0] = rb_intern_const("salt");
|
110
|
+
kwargs_ids[1] = rb_intern_const("N");
|
111
|
+
kwargs_ids[2] = rb_intern_const("r");
|
112
|
+
kwargs_ids[3] = rb_intern_const("p");
|
113
|
+
kwargs_ids[4] = rb_intern_const("length");
|
114
|
+
}
|
115
|
+
rb_scan_args(argc, argv, "1:", &pass, &opts);
|
116
|
+
rb_get_kwargs(opts, kwargs_ids, 5, 0, kwargs);
|
117
|
+
|
118
|
+
StringValue(pass);
|
119
|
+
salt = StringValue(kwargs[0]);
|
120
|
+
N = NUM2UINT64T(kwargs[1]);
|
121
|
+
r = NUM2UINT64T(kwargs[2]);
|
122
|
+
p = NUM2UINT64T(kwargs[3]);
|
123
|
+
len = NUM2LONG(kwargs[4]);
|
124
|
+
/*
|
125
|
+
* OpenSSL uses 32MB by default (if zero is specified), which is too small.
|
126
|
+
* Let's not limit memory consumption but just let malloc() fail inside
|
127
|
+
* OpenSSL. The amount is controllable by other parameters.
|
128
|
+
*/
|
129
|
+
maxmem = SIZE_MAX;
|
130
|
+
|
131
|
+
str = rb_str_new(0, len);
|
132
|
+
if (!EVP_PBE_scrypt(RSTRING_PTR(pass), RSTRING_LEN(pass),
|
133
|
+
(unsigned char *)RSTRING_PTR(salt), RSTRING_LEN(salt),
|
134
|
+
N, r, p, maxmem, (unsigned char *)RSTRING_PTR(str), len))
|
135
|
+
ossl_raise(eKDF, "EVP_PBE_scrypt");
|
136
|
+
|
137
|
+
return str;
|
138
|
+
}
|
139
|
+
#endif
|
140
|
+
|
141
|
+
void
|
142
|
+
Init_ossl_kdf(void)
|
143
|
+
{
|
144
|
+
#if 0
|
145
|
+
mOSSL = rb_define_module("OpenSSL");
|
146
|
+
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
|
147
|
+
#endif
|
148
|
+
|
149
|
+
/*
|
150
|
+
* Document-module: OpenSSL::KDF
|
151
|
+
*
|
152
|
+
* Provides functionality of various KDFs (key derivation function).
|
153
|
+
*
|
154
|
+
* KDF is typically used for securely deriving arbitrary length symmetric
|
155
|
+
* keys to be used with an OpenSSL::Cipher from passwords. Another use case
|
156
|
+
* is for storing passwords: Due to the ability to tweak the effort of
|
157
|
+
* computation by increasing the iteration count, computation can be slowed
|
158
|
+
* down artificially in order to render possible attacks infeasible.
|
159
|
+
*
|
160
|
+
* Currently, OpenSSL::KDF provides implementations for the following KDF:
|
161
|
+
*
|
162
|
+
* * PKCS #5 PBKDF2 (Password-Based Key Derivation Function 2) in
|
163
|
+
* combination with HMAC
|
164
|
+
* * scrypt
|
165
|
+
*
|
166
|
+
* == Examples
|
167
|
+
* === Generating a 128 bit key for a Cipher (e.g. AES)
|
168
|
+
* pass = "secret"
|
169
|
+
* salt = OpenSSL::Random.random_bytes(16)
|
170
|
+
* iter = 20_000
|
171
|
+
* key_len = 16
|
172
|
+
* key = OpenSSL::KDF.pbkdf2_hmac(pass, salt: salt, iterations: iter,
|
173
|
+
* length: key_len, hash: "sha1")
|
174
|
+
*
|
175
|
+
* === Storing Passwords
|
176
|
+
* pass = "secret"
|
177
|
+
* # store this with the generated value
|
178
|
+
* salt = OpenSSL::Random.random_bytes(16)
|
179
|
+
* iter = 20_000
|
180
|
+
* hash = OpenSSL::Digest::SHA256.new
|
181
|
+
* len = hash.digest_length
|
182
|
+
* # the final value to be stored
|
183
|
+
* value = OpenSSL::KDF.pbkdf2_hmac(pass, salt: salt, iterations: iter,
|
184
|
+
* length: len, hash: hash)
|
185
|
+
*
|
186
|
+
* == Important Note on Checking Passwords
|
187
|
+
* When comparing passwords provided by the user with previously stored
|
188
|
+
* values, a common mistake made is comparing the two values using "==".
|
189
|
+
* Typically, "==" short-circuits on evaluation, and is therefore
|
190
|
+
* vulnerable to timing attacks. The proper way is to use a method that
|
191
|
+
* always takes the same amount of time when comparing two values, thus
|
192
|
+
* not leaking any information to potential attackers. To compare two
|
193
|
+
* values, the following could be used:
|
194
|
+
*
|
195
|
+
* def eql_time_cmp(a, b)
|
196
|
+
* unless a.length == b.length
|
197
|
+
* return false
|
198
|
+
* end
|
199
|
+
* cmp = b.bytes
|
200
|
+
* result = 0
|
201
|
+
* a.bytes.each_with_index {|c,i|
|
202
|
+
* result |= c ^ cmp[i]
|
203
|
+
* }
|
204
|
+
* result == 0
|
205
|
+
* end
|
206
|
+
*
|
207
|
+
* Please note that the premature return in case of differing lengths
|
208
|
+
* typically does not leak valuable information - when using PBKDF2, the
|
209
|
+
* length of the values to be compared is of fixed size.
|
210
|
+
*/
|
211
|
+
mKDF = rb_define_module_under(mOSSL, "KDF");
|
212
|
+
/*
|
213
|
+
* Generic exception class raised if an error occurs in OpenSSL::KDF module.
|
214
|
+
*/
|
215
|
+
eKDF = rb_define_class_under(mKDF, "KDFError", eOSSLError);
|
216
|
+
|
217
|
+
rb_define_module_function(mKDF, "pbkdf2_hmac", kdf_pbkdf2_hmac, -1);
|
218
|
+
#if defined(HAVE_EVP_PBE_SCRYPT)
|
219
|
+
rb_define_module_function(mKDF, "scrypt", kdf_scrypt, -1);
|
220
|
+
#endif
|
221
|
+
}
|