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.

Files changed (60) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +28 -69
  3. data/README.md +1 -1
  4. data/ext/openssl/deprecation.rb +0 -3
  5. data/ext/openssl/extconf.rb +8 -52
  6. data/ext/openssl/openssl_missing.c +0 -67
  7. data/ext/openssl/openssl_missing.h +3 -50
  8. data/ext/openssl/ossl.c +81 -74
  9. data/ext/openssl/ossl.h +14 -27
  10. data/ext/openssl/ossl_asn1.c +287 -374
  11. data/ext/openssl/ossl_asn1.h +0 -4
  12. data/ext/openssl/ossl_bio.c +5 -20
  13. data/ext/openssl/ossl_bio.h +0 -2
  14. data/ext/openssl/ossl_bn.c +70 -28
  15. data/ext/openssl/ossl_cipher.c +18 -42
  16. data/ext/openssl/ossl_cipher.h +1 -1
  17. data/ext/openssl/ossl_digest.c +8 -12
  18. data/ext/openssl/ossl_digest.h +1 -1
  19. data/ext/openssl/ossl_engine.c +47 -47
  20. data/ext/openssl/ossl_hmac.c +19 -22
  21. data/ext/openssl/ossl_kdf.c +221 -0
  22. data/ext/openssl/ossl_kdf.h +6 -0
  23. data/ext/openssl/ossl_ns_spki.c +17 -21
  24. data/ext/openssl/ossl_ocsp.c +85 -80
  25. data/ext/openssl/ossl_pkcs12.c +15 -21
  26. data/ext/openssl/ossl_pkcs7.c +8 -21
  27. data/ext/openssl/ossl_pkey.c +24 -48
  28. data/ext/openssl/ossl_pkey.h +1 -6
  29. data/ext/openssl/ossl_pkey_dh.c +11 -11
  30. data/ext/openssl/ossl_pkey_dsa.c +16 -22
  31. data/ext/openssl/ossl_pkey_ec.c +43 -56
  32. data/ext/openssl/ossl_pkey_rsa.c +19 -19
  33. data/ext/openssl/ossl_rand.c +12 -12
  34. data/ext/openssl/ossl_ssl.c +291 -243
  35. data/ext/openssl/ossl_ssl.h +0 -5
  36. data/ext/openssl/ossl_ssl_session.c +7 -9
  37. data/ext/openssl/ossl_version.h +1 -1
  38. data/ext/openssl/ossl_x509.c +0 -15
  39. data/ext/openssl/ossl_x509.h +0 -7
  40. data/ext/openssl/ossl_x509attr.c +3 -7
  41. data/ext/openssl/ossl_x509cert.c +17 -54
  42. data/ext/openssl/ossl_x509crl.c +15 -25
  43. data/ext/openssl/ossl_x509ext.c +9 -14
  44. data/ext/openssl/ossl_x509name.c +76 -41
  45. data/ext/openssl/ossl_x509req.c +10 -47
  46. data/ext/openssl/ossl_x509revoked.c +8 -8
  47. data/ext/openssl/ossl_x509store.c +15 -45
  48. data/ext/openssl/ruby_missing.h +2 -13
  49. data/lib/openssl.rb +1 -0
  50. data/lib/openssl/bn.rb +2 -1
  51. data/lib/openssl/buffering.rb +24 -23
  52. data/lib/openssl/config.rb +12 -11
  53. data/lib/openssl/digest.rb +3 -6
  54. data/lib/openssl/pkcs5.rb +22 -0
  55. data/lib/openssl/pkey.rb +0 -41
  56. data/lib/openssl/ssl.rb +118 -16
  57. data/lib/openssl/x509.rb +7 -1
  58. metadata +8 -7
  59. data/ext/openssl/ossl_pkcs5.c +0 -180
  60. data/ext/openssl/ossl_pkcs5.h +0 -6
@@ -13,7 +13,7 @@
13
13
  extern VALUE cCipher;
14
14
  extern VALUE eCipherError;
15
15
 
16
- const EVP_CIPHER *GetCipherPtr(VALUE);
16
+ const EVP_CIPHER *ossl_evp_get_cipherbyname(VALUE);
17
17
  VALUE ossl_cipher_new(const EVP_CIPHER *);
18
18
  void Init_ossl_cipher(void);
19
19
 
@@ -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
- GetDigestPtr(VALUE obj)
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
- SafeGetDigest(obj, ctx);
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 +string+, which is either the ln
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 +data+ (a +String+) is given, it is used as the initial input to the
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 equal to
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 = GetDigestPtr(type);
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
- SafeGetDigest(other, ctx2);
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
- rb_define_copy_func(cDigest, ossl_digest_copy);
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");
@@ -13,7 +13,7 @@
13
13
  extern VALUE cDigest;
14
14
  extern VALUE eDigestError;
15
15
 
16
- const EVP_MD *GetDigestPtr(VALUE);
16
+ const EVP_MD *ossl_evp_get_digestbyname(VALUE);
17
17
  VALUE ossl_digest_new(const EVP_MD *);
18
18
  void Init_ossl_digest(void);
19
19
 
@@ -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
- /* Document-method: OpenSSL::Engine.load
76
- *
71
+ /*
77
72
  * call-seq:
78
- * load(enginename = nil)
73
+ * OpenSSL::Engine.load(name = nil)
79
74
  *
80
- * This method loads engines. If +name+ is nil, then all builtin engines are
81
- * loaded. Otherwise, the given +name+, as a string, is loaded if available to
82
- * your runtime, and returns true. If +name+ is not found, then nil is
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
- /* Document-method: OpenSSL::Engine.cleanup
151
+ /*
157
152
  * call-seq:
158
- * OpenSSL::Engine.cleanup
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
- /* Document-method: OpenSSL::Engine.engines
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
- /* Document-method: OpenSSL::Engine.by_id
197
- *
193
+ /*
198
194
  * call-seq:
199
- * by_id(name) -> engine
195
+ * OpenSSL::Engine.by_id(name) -> engine
200
196
  *
201
- * Fetch the engine as specified by the +id+ String
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
- /* Document-method: OpenSSL::Engine#id
226
+ /*
227
+ * call-seq:
228
+ * engine.id -> string
231
229
  *
232
- * Get the id for this engine
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
- /* Document-method: OpenSSL::Engine#name
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
- /* Document-method: OpenSSL::Engine#finish
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
- /* Document-method: OpenSSL::Engine#cipher
283
- *
284
+ /*
284
285
  * call-seq:
285
286
  * engine.cipher(name) -> OpenSSL::Cipher
286
287
  *
287
- * This returns an OpenSSL::Cipher by +name+, if it is available in this
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
- /* Document-method: OpenSSL::Engine#digest
316
- *
316
+ /*
317
317
  * call-seq:
318
318
  * engine.digest(name) -> OpenSSL::Digest
319
319
  *
320
- * This returns an OpenSSL::Digest by +name+.
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
- /* Document-method: OpenSSL::Engine#load_private_key
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 +id+ and +data+.
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
- /* Document-method: OpenSSL::Engine#load_public_key
379
- *
377
+ /*
380
378
  * call-seq:
381
379
  * engine.load_public_key(id = nil, data = nil) -> OpenSSL::PKey
382
380
  *
383
- * Loads the given private key by +id+ and +data+.
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
- /* Document-method: OpenSSL::Engine#set_default
407
- *
404
+ /*
408
405
  * call-seq:
409
406
  * engine.set_default(flag)
410
407
  *
411
- * Set the defaults for this engine with the given +flag+.
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
- * +flag+ can be one of the following, other flags are available depending on
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
- /* Document-method: OpenSSL::Engine#ctrl_cmd
436
- *
432
+ /*
437
433
  * call-seq:
438
434
  * engine.ctrl_cmd(command, value = nil) -> engine
439
435
  *
440
- * Send the given +command+ to this engine.
436
+ * Sends the given _command_ to this engine.
441
437
  *
442
- * Raises an EngineError if the +command+ fails.
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
- /* Document-method: OpenSSL::Engine#cmds
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
- /* Document-method: OpenSSL::Engine#inspect
496
+ /*
497
+ * call-seq:
498
+ * engine.inspect -> string
499
499
  *
500
- * Pretty print this engine
500
+ * Pretty prints this engine.
501
501
  */
502
502
  static VALUE
503
503
  ossl_engine_inspect(VALUE self)
@@ -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
- GetDigestPtr(digest), NULL);
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
- SafeGetHMAC(other, ctx2);
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 +self+ updated with the message to be authenticated.
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 +self+ as it was when it was first initialized, with all processed
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 +digest+ parameter
268
- * must be an instance of OpenSSL::Digest.
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(digest, key, data)
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(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LENINT(key),
289
- (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len);
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 +digest+
299
- * parameter must be an instance of OpenSSL::Digest.
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(digest, key, data)
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(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LENINT(key),
322
- (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(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
- rb_define_copy_func(cHMAC, ossl_hmac_copy);
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
+ }