openssl 2.1.2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +35 -45
  3. data/History.md +232 -0
  4. data/README.md +2 -2
  5. data/ext/openssl/extconf.rb +61 -46
  6. data/ext/openssl/openssl_missing.c +0 -66
  7. data/ext/openssl/openssl_missing.h +60 -44
  8. data/ext/openssl/ossl.c +112 -66
  9. data/ext/openssl/ossl.h +28 -11
  10. data/ext/openssl/ossl_asn1.c +42 -5
  11. data/ext/openssl/ossl_bn.c +276 -146
  12. data/ext/openssl/ossl_bn.h +2 -1
  13. data/ext/openssl/ossl_cipher.c +38 -29
  14. data/ext/openssl/ossl_config.c +412 -41
  15. data/ext/openssl/ossl_config.h +4 -7
  16. data/ext/openssl/ossl_digest.c +31 -62
  17. data/ext/openssl/ossl_engine.c +18 -27
  18. data/ext/openssl/ossl_hmac.c +52 -145
  19. data/ext/openssl/ossl_kdf.c +11 -19
  20. data/ext/openssl/ossl_ns_spki.c +1 -1
  21. data/ext/openssl/ossl_ocsp.c +9 -62
  22. data/ext/openssl/ossl_ocsp.h +3 -3
  23. data/ext/openssl/ossl_pkcs12.c +21 -3
  24. data/ext/openssl/ossl_pkcs7.c +45 -78
  25. data/ext/openssl/ossl_pkcs7.h +16 -0
  26. data/ext/openssl/ossl_pkey.c +1255 -178
  27. data/ext/openssl/ossl_pkey.h +40 -77
  28. data/ext/openssl/ossl_pkey_dh.c +125 -335
  29. data/ext/openssl/ossl_pkey_dsa.c +93 -398
  30. data/ext/openssl/ossl_pkey_ec.c +155 -318
  31. data/ext/openssl/ossl_pkey_rsa.c +105 -484
  32. data/ext/openssl/ossl_rand.c +2 -40
  33. data/ext/openssl/ossl_ssl.c +395 -364
  34. data/ext/openssl/ossl_ssl_session.c +24 -29
  35. data/ext/openssl/ossl_ts.c +1539 -0
  36. data/ext/openssl/ossl_ts.h +16 -0
  37. data/ext/openssl/ossl_x509.c +86 -1
  38. data/ext/openssl/ossl_x509cert.c +166 -10
  39. data/ext/openssl/ossl_x509crl.c +10 -7
  40. data/ext/openssl/ossl_x509ext.c +15 -2
  41. data/ext/openssl/ossl_x509name.c +16 -5
  42. data/ext/openssl/ossl_x509req.c +10 -7
  43. data/ext/openssl/ossl_x509store.c +193 -92
  44. data/lib/openssl/bn.rb +1 -1
  45. data/lib/openssl/buffering.rb +42 -17
  46. data/lib/openssl/cipher.rb +1 -1
  47. data/lib/openssl/digest.rb +10 -12
  48. data/lib/openssl/hmac.rb +78 -0
  49. data/lib/openssl/marshal.rb +30 -0
  50. data/lib/openssl/pkcs5.rb +1 -1
  51. data/lib/openssl/pkey.rb +435 -1
  52. data/lib/openssl/ssl.rb +53 -14
  53. data/lib/openssl/version.rb +5 -0
  54. data/lib/openssl/x509.rb +177 -1
  55. data/lib/openssl.rb +24 -9
  56. metadata +13 -69
  57. data/ext/openssl/deprecation.rb +0 -23
  58. data/ext/openssl/ossl_version.h +0 -15
  59. data/ext/openssl/ruby_missing.h +0 -24
  60. data/lib/openssl/config.rb +0 -474
@@ -63,7 +63,7 @@ ossl_evp_get_digestbyname(VALUE obj)
63
63
 
64
64
  GetDigest(obj, ctx);
65
65
 
66
- md = EVP_MD_CTX_md(ctx);
66
+ md = EVP_MD_CTX_get0_md(ctx);
67
67
  }
68
68
 
69
69
  return md;
@@ -176,7 +176,7 @@ ossl_digest_reset(VALUE self)
176
176
  EVP_MD_CTX *ctx;
177
177
 
178
178
  GetDigest(self, ctx);
179
- if (EVP_DigestInit_ex(ctx, EVP_MD_CTX_md(ctx), NULL) != 1) {
179
+ if (EVP_DigestInit_ex(ctx, EVP_MD_CTX_get0_md(ctx), NULL) != 1) {
180
180
  ossl_raise(eDigestError, "Digest initialization failed.");
181
181
  }
182
182
 
@@ -192,7 +192,7 @@ ossl_digest_reset(VALUE self)
192
192
  * be passed individually to the Digest instance.
193
193
  *
194
194
  * === Example
195
- * digest = OpenSSL::Digest::SHA256.new
195
+ * digest = OpenSSL::Digest.new('SHA256')
196
196
  * digest.update('First input')
197
197
  * digest << 'Second input' # equivalent to digest.update('Second input')
198
198
  * result = digest.digest
@@ -248,7 +248,7 @@ ossl_digest_finish(int argc, VALUE *argv, VALUE self)
248
248
  * Returns the sn of this Digest algorithm.
249
249
  *
250
250
  * === Example
251
- * digest = OpenSSL::Digest::SHA512.new
251
+ * digest = OpenSSL::Digest.new('SHA512')
252
252
  * puts digest.name # => SHA512
253
253
  *
254
254
  */
@@ -259,7 +259,7 @@ ossl_digest_name(VALUE self)
259
259
 
260
260
  GetDigest(self, ctx);
261
261
 
262
- return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx)));
262
+ return rb_str_new_cstr(EVP_MD_name(EVP_MD_CTX_get0_md(ctx)));
263
263
  }
264
264
 
265
265
  /*
@@ -270,7 +270,7 @@ ossl_digest_name(VALUE self)
270
270
  * final message digest result.
271
271
  *
272
272
  * === Example
273
- * digest = OpenSSL::Digest::SHA1.new
273
+ * digest = OpenSSL::Digest.new('SHA1')
274
274
  * puts digest.digest_length # => 20
275
275
  *
276
276
  */
@@ -294,7 +294,7 @@ ossl_digest_size(VALUE self)
294
294
  * consecutively.
295
295
  *
296
296
  * === Example
297
- * digest = OpenSSL::Digest::SHA1.new
297
+ * digest = OpenSSL::Digest.new('SHA1')
298
298
  * puts digest.block_length # => 64
299
299
  */
300
300
  static VALUE
@@ -313,8 +313,6 @@ ossl_digest_block_length(VALUE self)
313
313
  void
314
314
  Init_ossl_digest(void)
315
315
  {
316
- rb_require("digest");
317
-
318
316
  #if 0
319
317
  mOSSL = rb_define_module("OpenSSL");
320
318
  eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
@@ -348,54 +346,19 @@ Init_ossl_digest(void)
348
346
  * the integrity of a signed document, it suffices to re-compute the hash
349
347
  * and verify that it is equal to that in the signature.
350
348
  *
351
- * Among the supported message digest algorithms are:
352
- * * SHA, SHA1, SHA224, SHA256, SHA384 and SHA512
353
- * * MD2, MD4, MDC2 and MD5
354
- * * RIPEMD160
355
- * * DSS, DSS1 (Pseudo algorithms to be used for DSA signatures. DSS is
356
- * equal to SHA and DSS1 is equal to SHA1)
349
+ * You can get a list of all digest algorithms supported on your system by
350
+ * running this command in your terminal:
357
351
  *
358
- * For each of these algorithms, there is a sub-class of Digest that
359
- * can be instantiated as simply as e.g.
352
+ * openssl list -digest-algorithms
360
353
  *
361
- * digest = OpenSSL::Digest::SHA1.new
354
+ * Among the OpenSSL 1.1.1 supported message digest algorithms are:
355
+ * * SHA224, SHA256, SHA384, SHA512, SHA512-224 and SHA512-256
356
+ * * SHA3-224, SHA3-256, SHA3-384 and SHA3-512
357
+ * * BLAKE2s256 and BLAKE2b512
362
358
  *
363
- * === Mapping between Digest class and sn/ln
359
+ * Each of these algorithms can be instantiated using the name:
364
360
  *
365
- * The sn (short names) and ln (long names) are defined in
366
- * <openssl/object.h> and <openssl/obj_mac.h>. They are textual
367
- * representations of ASN.1 OBJECT IDENTIFIERs. Each supported digest
368
- * algorithm has an OBJECT IDENTIFIER associated to it and those again
369
- * have short/long names assigned to them.
370
- * E.g. the OBJECT IDENTIFIER for SHA-1 is 1.3.14.3.2.26 and its
371
- * sn is "SHA1" and its ln is "sha1".
372
- * ==== MD2
373
- * * sn: MD2
374
- * * ln: md2
375
- * ==== MD4
376
- * * sn: MD4
377
- * * ln: md4
378
- * ==== MD5
379
- * * sn: MD5
380
- * * ln: md5
381
- * ==== SHA
382
- * * sn: SHA
383
- * * ln: SHA
384
- * ==== SHA-1
385
- * * sn: SHA1
386
- * * ln: sha1
387
- * ==== SHA-224
388
- * * sn: SHA224
389
- * * ln: sha224
390
- * ==== SHA-256
391
- * * sn: SHA256
392
- * * ln: sha256
393
- * ==== SHA-384
394
- * * sn: SHA384
395
- * * ln: sha384
396
- * ==== SHA-512
397
- * * sn: SHA512
398
- * * ln: sha512
361
+ * digest = OpenSSL::Digest.new('SHA256')
399
362
  *
400
363
  * "Breaking" a message digest algorithm means defying its one-way
401
364
  * function characteristics, i.e. producing a collision or finding a way
@@ -407,16 +370,16 @@ Init_ossl_digest(void)
407
370
  *
408
371
  * === Hashing a file
409
372
  *
410
- * data = File.read('document')
411
- * sha256 = OpenSSL::Digest::SHA256.new
373
+ * data = File.binread('document')
374
+ * sha256 = OpenSSL::Digest.new('SHA256')
412
375
  * digest = sha256.digest(data)
413
376
  *
414
377
  * === Hashing several pieces of data at once
415
378
  *
416
- * data1 = File.read('file1')
417
- * data2 = File.read('file2')
418
- * data3 = File.read('file3')
419
- * sha256 = OpenSSL::Digest::SHA256.new
379
+ * data1 = File.binread('file1')
380
+ * data2 = File.binread('file2')
381
+ * data3 = File.binread('file3')
382
+ * sha256 = OpenSSL::Digest.new('SHA256')
420
383
  * sha256 << data1
421
384
  * sha256 << data2
422
385
  * sha256 << data3
@@ -424,15 +387,21 @@ Init_ossl_digest(void)
424
387
  *
425
388
  * === Reuse a Digest instance
426
389
  *
427
- * data1 = File.read('file1')
428
- * sha256 = OpenSSL::Digest::SHA256.new
390
+ * data1 = File.binread('file1')
391
+ * sha256 = OpenSSL::Digest.new('SHA256')
429
392
  * digest1 = sha256.digest(data1)
430
393
  *
431
- * data2 = File.read('file2')
394
+ * data2 = File.binread('file2')
432
395
  * sha256.reset
433
396
  * digest2 = sha256.digest(data2)
434
397
  *
435
398
  */
399
+
400
+ /*
401
+ * Digest::Class is defined by the digest library. rb_require() cannot be
402
+ * used here because it bypasses RubyGems.
403
+ */
404
+ rb_funcall(Qnil, rb_intern_const("require"), 1, rb_str_new_cstr("digest"));
436
405
  cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class"));
437
406
  /* Document-class: OpenSSL::Digest::DigestError
438
407
  *
@@ -9,7 +9,8 @@
9
9
  */
10
10
  #include "ossl.h"
11
11
 
12
- #if !defined(OPENSSL_NO_ENGINE)
12
+ #ifdef OSSL_USE_ENGINE
13
+ # include <openssl/engine.h>
13
14
 
14
15
  #define NewEngine(klass) \
15
16
  TypedData_Wrap_Struct((klass), &ossl_engine_type, 0)
@@ -93,9 +94,6 @@ static const rb_data_type_t ossl_engine_type = {
93
94
  static VALUE
94
95
  ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
95
96
  {
96
- #if !defined(HAVE_ENGINE_LOAD_BUILTIN_ENGINES)
97
- return Qnil;
98
- #else
99
97
  VALUE name;
100
98
 
101
99
  rb_scan_args(argc, argv, "01", &name);
@@ -104,60 +102,53 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
104
102
  return Qtrue;
105
103
  }
106
104
  StringValueCStr(name);
107
- #ifndef OPENSSL_NO_STATIC_ENGINE
108
- #if HAVE_ENGINE_LOAD_DYNAMIC
105
+ #ifdef HAVE_ENGINE_LOAD_DYNAMIC
109
106
  OSSL_ENGINE_LOAD_IF_MATCH(dynamic, DYNAMIC);
110
107
  #endif
111
- #if HAVE_ENGINE_LOAD_4758CCA
108
+ #ifndef OPENSSL_NO_STATIC_ENGINE
109
+ #ifdef HAVE_ENGINE_LOAD_4758CCA
112
110
  OSSL_ENGINE_LOAD_IF_MATCH(4758cca, 4758CCA);
113
111
  #endif
114
- #if HAVE_ENGINE_LOAD_AEP
112
+ #ifdef HAVE_ENGINE_LOAD_AEP
115
113
  OSSL_ENGINE_LOAD_IF_MATCH(aep, AEP);
116
114
  #endif
117
- #if HAVE_ENGINE_LOAD_ATALLA
115
+ #ifdef HAVE_ENGINE_LOAD_ATALLA
118
116
  OSSL_ENGINE_LOAD_IF_MATCH(atalla, ATALLA);
119
117
  #endif
120
- #if HAVE_ENGINE_LOAD_CHIL
118
+ #ifdef HAVE_ENGINE_LOAD_CHIL
121
119
  OSSL_ENGINE_LOAD_IF_MATCH(chil, CHIL);
122
120
  #endif
123
- #if HAVE_ENGINE_LOAD_CSWIFT
121
+ #ifdef HAVE_ENGINE_LOAD_CSWIFT
124
122
  OSSL_ENGINE_LOAD_IF_MATCH(cswift, CSWIFT);
125
123
  #endif
126
- #if HAVE_ENGINE_LOAD_NURON
124
+ #ifdef HAVE_ENGINE_LOAD_NURON
127
125
  OSSL_ENGINE_LOAD_IF_MATCH(nuron, NURON);
128
126
  #endif
129
- #if HAVE_ENGINE_LOAD_SUREWARE
127
+ #ifdef HAVE_ENGINE_LOAD_SUREWARE
130
128
  OSSL_ENGINE_LOAD_IF_MATCH(sureware, SUREWARE);
131
129
  #endif
132
- #if HAVE_ENGINE_LOAD_UBSEC
130
+ #ifdef HAVE_ENGINE_LOAD_UBSEC
133
131
  OSSL_ENGINE_LOAD_IF_MATCH(ubsec, UBSEC);
134
132
  #endif
135
- #if HAVE_ENGINE_LOAD_PADLOCK
133
+ #ifdef HAVE_ENGINE_LOAD_PADLOCK
136
134
  OSSL_ENGINE_LOAD_IF_MATCH(padlock, PADLOCK);
137
135
  #endif
138
- #if HAVE_ENGINE_LOAD_CAPI
136
+ #ifdef HAVE_ENGINE_LOAD_CAPI
139
137
  OSSL_ENGINE_LOAD_IF_MATCH(capi, CAPI);
140
138
  #endif
141
- #if HAVE_ENGINE_LOAD_GMP
139
+ #ifdef HAVE_ENGINE_LOAD_GMP
142
140
  OSSL_ENGINE_LOAD_IF_MATCH(gmp, GMP);
143
141
  #endif
144
- #if HAVE_ENGINE_LOAD_GOST
142
+ #ifdef HAVE_ENGINE_LOAD_GOST
145
143
  OSSL_ENGINE_LOAD_IF_MATCH(gost, GOST);
146
144
  #endif
147
- #if HAVE_ENGINE_LOAD_CRYPTODEV
148
- OSSL_ENGINE_LOAD_IF_MATCH(cryptodev, CRYPTODEV);
149
- #endif
150
- #if HAVE_ENGINE_LOAD_AESNI
151
- OSSL_ENGINE_LOAD_IF_MATCH(aesni, AESNI);
152
145
  #endif
153
- #endif
154
- #ifdef HAVE_ENGINE_LOAD_OPENBSD_DEV_CRYPTO
155
- OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto, OPENBSD_DEV_CRYPTO);
146
+ #ifdef HAVE_ENGINE_LOAD_CRYPTODEV
147
+ OSSL_ENGINE_LOAD_IF_MATCH(cryptodev, CRYPTODEV);
156
148
  #endif
157
149
  OSSL_ENGINE_LOAD_IF_MATCH(openssl, OPENSSL);
158
150
  rb_warning("no such builtin loader for `%"PRIsVALUE"'", name);
159
151
  return Qnil;
160
- #endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
161
152
  }
162
153
 
163
154
  /*
@@ -7,14 +7,12 @@
7
7
  * This program is licensed under the same licence as Ruby.
8
8
  * (See the file 'LICENCE'.)
9
9
  */
10
- #if !defined(OPENSSL_NO_HMAC)
11
-
12
10
  #include "ossl.h"
13
11
 
14
12
  #define NewHMAC(klass) \
15
13
  TypedData_Wrap_Struct((klass), &ossl_hmac_type, 0)
16
14
  #define GetHMAC(obj, ctx) do { \
17
- TypedData_Get_Struct((obj), HMAC_CTX, &ossl_hmac_type, (ctx)); \
15
+ TypedData_Get_Struct((obj), EVP_MD_CTX, &ossl_hmac_type, (ctx)); \
18
16
  if (!(ctx)) { \
19
17
  ossl_raise(rb_eRuntimeError, "HMAC wasn't initialized"); \
20
18
  } \
@@ -36,7 +34,7 @@ VALUE eHMACError;
36
34
  static void
37
35
  ossl_hmac_free(void *ctx)
38
36
  {
39
- HMAC_CTX_free(ctx);
37
+ EVP_MD_CTX_free(ctx);
40
38
  }
41
39
 
42
40
  static const rb_data_type_t ossl_hmac_type = {
@@ -51,12 +49,12 @@ static VALUE
51
49
  ossl_hmac_alloc(VALUE klass)
52
50
  {
53
51
  VALUE obj;
54
- HMAC_CTX *ctx;
52
+ EVP_MD_CTX *ctx;
55
53
 
56
54
  obj = NewHMAC(klass);
57
- ctx = HMAC_CTX_new();
55
+ ctx = EVP_MD_CTX_new();
58
56
  if (!ctx)
59
- ossl_raise(eHMACError, NULL);
57
+ ossl_raise(eHMACError, "EVP_MD_CTX");
60
58
  RTYPEDDATA_DATA(obj) = ctx;
61
59
 
62
60
  return obj;
@@ -76,37 +74,41 @@ ossl_hmac_alloc(VALUE klass)
76
74
  * === Example
77
75
  *
78
76
  * key = 'key'
79
- * digest = OpenSSL::Digest.new('sha1')
80
- * instance = OpenSSL::HMAC.new(key, digest)
77
+ * instance = OpenSSL::HMAC.new(key, 'SHA1')
81
78
  * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
82
79
  * instance.class
83
80
  * #=> OpenSSL::HMAC
84
81
  *
85
82
  * === A note about comparisons
86
83
  *
87
- * Two instances won't be equal when they're compared, even if they have the
88
- * same value. Use #to_s or #hexdigest to return the authentication code that
89
- * the instance represents. For example:
84
+ * Two instances can be securely compared with #== in constant time:
90
85
  *
91
- * other_instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1'))
92
- * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
93
- * instance
94
- * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
95
- * instance == other_instance
96
- * #=> false
97
- * instance.to_s == other_instance.to_s
98
- * #=> true
86
+ * other_instance = OpenSSL::HMAC.new('key', 'SHA1')
87
+ * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
88
+ * instance == other_instance
89
+ * #=> true
99
90
  *
100
91
  */
101
92
  static VALUE
102
93
  ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
103
94
  {
104
- HMAC_CTX *ctx;
95
+ EVP_MD_CTX *ctx;
96
+ EVP_PKEY *pkey;
105
97
 
106
- StringValue(key);
107
98
  GetHMAC(self, ctx);
108
- HMAC_Init_ex(ctx, RSTRING_PTR(key), RSTRING_LENINT(key),
109
- ossl_evp_get_digestbyname(digest), NULL);
99
+ StringValue(key);
100
+ pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL,
101
+ (unsigned char *)RSTRING_PTR(key),
102
+ RSTRING_LENINT(key));
103
+ if (!pkey)
104
+ ossl_raise(eHMACError, "EVP_PKEY_new_mac_key");
105
+ if (EVP_DigestSignInit(ctx, NULL, ossl_evp_get_digestbyname(digest),
106
+ NULL, pkey) != 1) {
107
+ EVP_PKEY_free(pkey);
108
+ ossl_raise(eHMACError, "EVP_DigestSignInit");
109
+ }
110
+ /* Decrement reference counter; EVP_MD_CTX still keeps it */
111
+ EVP_PKEY_free(pkey);
110
112
 
111
113
  return self;
112
114
  }
@@ -114,16 +116,15 @@ ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
114
116
  static VALUE
115
117
  ossl_hmac_copy(VALUE self, VALUE other)
116
118
  {
117
- HMAC_CTX *ctx1, *ctx2;
119
+ EVP_MD_CTX *ctx1, *ctx2;
118
120
 
119
121
  rb_check_frozen(self);
120
122
  if (self == other) return self;
121
123
 
122
124
  GetHMAC(self, ctx1);
123
125
  GetHMAC(other, ctx2);
124
-
125
- if (!HMAC_CTX_copy(ctx1, ctx2))
126
- ossl_raise(eHMACError, "HMAC_CTX_copy");
126
+ if (EVP_MD_CTX_copy(ctx1, ctx2) != 1)
127
+ ossl_raise(eHMACError, "EVP_MD_CTX_copy");
127
128
  return self;
128
129
  }
129
130
 
@@ -148,33 +149,16 @@ ossl_hmac_copy(VALUE self, VALUE other)
148
149
  static VALUE
149
150
  ossl_hmac_update(VALUE self, VALUE data)
150
151
  {
151
- HMAC_CTX *ctx;
152
+ EVP_MD_CTX *ctx;
152
153
 
153
154
  StringValue(data);
154
155
  GetHMAC(self, ctx);
155
- HMAC_Update(ctx, (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data));
156
+ if (EVP_DigestSignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1)
157
+ ossl_raise(eHMACError, "EVP_DigestSignUpdate");
156
158
 
157
159
  return self;
158
160
  }
159
161
 
160
- static void
161
- hmac_final(HMAC_CTX *ctx, unsigned char *buf, unsigned int *buf_len)
162
- {
163
- HMAC_CTX *final;
164
-
165
- final = HMAC_CTX_new();
166
- if (!final)
167
- ossl_raise(eHMACError, "HMAC_CTX_new");
168
-
169
- if (!HMAC_CTX_copy(final, ctx)) {
170
- HMAC_CTX_free(final);
171
- ossl_raise(eHMACError, "HMAC_CTX_copy");
172
- }
173
-
174
- HMAC_Final(final, buf, buf_len);
175
- HMAC_CTX_free(final);
176
- }
177
-
178
162
  /*
179
163
  * call-seq:
180
164
  * hmac.digest -> string
@@ -182,7 +166,7 @@ hmac_final(HMAC_CTX *ctx, unsigned char *buf, unsigned int *buf_len)
182
166
  * Returns the authentication code an instance represents as a binary string.
183
167
  *
184
168
  * === Example
185
- * instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1'))
169
+ * instance = OpenSSL::HMAC.new('key', 'SHA1')
186
170
  * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
187
171
  * instance.digest
188
172
  * #=> "\xF4+\xB0\xEE\xB0\x18\xEB\xBDE\x97\xAEr\x13q\x1E\xC6\a`\x84?"
@@ -190,15 +174,16 @@ hmac_final(HMAC_CTX *ctx, unsigned char *buf, unsigned int *buf_len)
190
174
  static VALUE
191
175
  ossl_hmac_digest(VALUE self)
192
176
  {
193
- HMAC_CTX *ctx;
194
- unsigned int buf_len;
177
+ EVP_MD_CTX *ctx;
178
+ size_t buf_len = EVP_MAX_MD_SIZE;
195
179
  VALUE ret;
196
180
 
197
181
  GetHMAC(self, ctx);
198
182
  ret = rb_str_new(NULL, EVP_MAX_MD_SIZE);
199
- hmac_final(ctx, (unsigned char *)RSTRING_PTR(ret), &buf_len);
200
- assert(buf_len <= EVP_MAX_MD_SIZE);
201
- rb_str_set_len(ret, buf_len);
183
+ if (EVP_DigestSignFinal(ctx, (unsigned char *)RSTRING_PTR(ret),
184
+ &buf_len) != 1)
185
+ ossl_raise(eHMACError, "EVP_DigestSignFinal");
186
+ rb_str_set_len(ret, (long)buf_len);
202
187
 
203
188
  return ret;
204
189
  }
@@ -213,13 +198,14 @@ ossl_hmac_digest(VALUE self)
213
198
  static VALUE
214
199
  ossl_hmac_hexdigest(VALUE self)
215
200
  {
216
- HMAC_CTX *ctx;
201
+ EVP_MD_CTX *ctx;
217
202
  unsigned char buf[EVP_MAX_MD_SIZE];
218
- unsigned int buf_len;
203
+ size_t buf_len = EVP_MAX_MD_SIZE;
219
204
  VALUE ret;
220
205
 
221
206
  GetHMAC(self, ctx);
222
- hmac_final(ctx, buf, &buf_len);
207
+ if (EVP_DigestSignFinal(ctx, buf, &buf_len) != 1)
208
+ ossl_raise(eHMACError, "EVP_DigestSignFinal");
223
209
  ret = rb_str_new(NULL, buf_len * 2);
224
210
  ossl_bin2hex(buf, RSTRING_PTR(ret), buf_len);
225
211
 
@@ -236,7 +222,7 @@ ossl_hmac_hexdigest(VALUE self)
236
222
  * === Example
237
223
  *
238
224
  * data = "The quick brown fox jumps over the lazy dog"
239
- * instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1'))
225
+ * instance = OpenSSL::HMAC.new('key', 'SHA1')
240
226
  * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
241
227
  *
242
228
  * instance.update(data)
@@ -248,84 +234,17 @@ ossl_hmac_hexdigest(VALUE self)
248
234
  static VALUE
249
235
  ossl_hmac_reset(VALUE self)
250
236
  {
251
- HMAC_CTX *ctx;
237
+ EVP_MD_CTX *ctx;
238
+ EVP_PKEY *pkey;
252
239
 
253
240
  GetHMAC(self, ctx);
254
- HMAC_Init_ex(ctx, NULL, 0, NULL, NULL);
241
+ pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx));
242
+ if (EVP_DigestSignInit(ctx, NULL, EVP_MD_CTX_get0_md(ctx), NULL, pkey) != 1)
243
+ ossl_raise(eHMACError, "EVP_DigestSignInit");
255
244
 
256
245
  return self;
257
246
  }
258
247
 
259
- /*
260
- * call-seq:
261
- * HMAC.digest(digest, key, data) -> aString
262
- *
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.
266
- *
267
- * === Example
268
- *
269
- * key = 'key'
270
- * data = 'The quick brown fox jumps over the lazy dog'
271
- *
272
- * hmac = OpenSSL::HMAC.digest('sha1', key, data)
273
- * #=> "\xDE|\x9B\x85\xB8\xB7\x8A\xA6\xBC\x8Az6\xF7\n\x90p\x1C\x9D\xB4\xD9"
274
- *
275
- */
276
- static VALUE
277
- ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
278
- {
279
- unsigned char *buf;
280
- unsigned int buf_len;
281
-
282
- StringValue(key);
283
- StringValue(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);
287
-
288
- return rb_str_new((const char *)buf, buf_len);
289
- }
290
-
291
- /*
292
- * call-seq:
293
- * HMAC.hexdigest(digest, key, data) -> aString
294
- *
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.
298
- *
299
- * === Example
300
- *
301
- * key = 'key'
302
- * data = 'The quick brown fox jumps over the lazy dog'
303
- *
304
- * hmac = OpenSSL::HMAC.hexdigest('sha1', key, data)
305
- * #=> "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"
306
- *
307
- */
308
- static VALUE
309
- ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
310
- {
311
- unsigned char buf[EVP_MAX_MD_SIZE];
312
- unsigned int buf_len;
313
- VALUE ret;
314
-
315
- StringValue(key);
316
- StringValue(data);
317
-
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))
321
- ossl_raise(eHMACError, "HMAC");
322
-
323
- ret = rb_str_new(NULL, buf_len * 2);
324
- ossl_bin2hex(buf, RSTRING_PTR(ret), buf_len);
325
-
326
- return ret;
327
- }
328
-
329
248
  /*
330
249
  * INIT
331
250
  */
@@ -356,11 +275,10 @@ Init_ossl_hmac(void)
356
275
  *
357
276
  * === HMAC-SHA256 using incremental interface
358
277
  *
359
- * data1 = File.read("file1")
360
- * data2 = File.read("file2")
278
+ * data1 = File.binread("file1")
279
+ * data2 = File.binread("file2")
361
280
  * key = "key"
362
- * digest = OpenSSL::Digest::SHA256.new
363
- * hmac = OpenSSL::HMAC.new(key, digest)
281
+ * hmac = OpenSSL::HMAC.new(key, 'SHA256')
364
282
  * hmac << data1
365
283
  * hmac << data2
366
284
  * mac = hmac.digest
@@ -370,8 +288,6 @@ Init_ossl_hmac(void)
370
288
  cHMAC = rb_define_class_under(mOSSL, "HMAC", rb_cObject);
371
289
 
372
290
  rb_define_alloc_func(cHMAC, ossl_hmac_alloc);
373
- rb_define_singleton_method(cHMAC, "digest", ossl_hmac_s_digest, 3);
374
- rb_define_singleton_method(cHMAC, "hexdigest", ossl_hmac_s_hexdigest, 3);
375
291
 
376
292
  rb_define_method(cHMAC, "initialize", ossl_hmac_initialize, 2);
377
293
  rb_define_method(cHMAC, "initialize_copy", ossl_hmac_copy, 1);
@@ -384,12 +300,3 @@ Init_ossl_hmac(void)
384
300
  rb_define_alias(cHMAC, "inspect", "hexdigest");
385
301
  rb_define_alias(cHMAC, "to_s", "hexdigest");
386
302
  }
387
-
388
- #else /* NO_HMAC */
389
- # warning >>> OpenSSL is compiled without HMAC support <<<
390
- void
391
- Init_ossl_hmac(void)
392
- {
393
- rb_warning("HMAC is not available: OpenSSL is compiled without HMAC.");
394
- }
395
- #endif /* NO_HMAC */
@@ -163,6 +163,14 @@ kdf_scrypt(int argc, VALUE *argv, VALUE self)
163
163
  * HashLen is the length of the hash function output in octets.
164
164
  * _hash_::
165
165
  * The hash function.
166
+ *
167
+ * === Example
168
+ * # The values from https://datatracker.ietf.org/doc/html/rfc5869#appendix-A.1
169
+ * ikm = ["0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"].pack("H*")
170
+ * salt = ["000102030405060708090a0b0c"].pack("H*")
171
+ * info = ["f0f1f2f3f4f5f6f7f8f9"].pack("H*")
172
+ * p OpenSSL::KDF.hkdf(ikm, salt: salt, info: info, length: 42, hash: "SHA256").unpack1("H*")
173
+ * # => "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"
166
174
  */
167
175
  static VALUE
168
176
  kdf_hkdf(int argc, VALUE *argv, VALUE self)
@@ -272,7 +280,7 @@ Init_ossl_kdf(void)
272
280
  * # store this with the generated value
273
281
  * salt = OpenSSL::Random.random_bytes(16)
274
282
  * iter = 20_000
275
- * hash = OpenSSL::Digest::SHA256.new
283
+ * hash = OpenSSL::Digest.new('SHA256')
276
284
  * len = hash.digest_length
277
285
  * # the final value to be stored
278
286
  * value = OpenSSL::KDF.pbkdf2_hmac(pass, salt: salt, iterations: iter,
@@ -284,24 +292,8 @@ Init_ossl_kdf(void)
284
292
  * Typically, "==" short-circuits on evaluation, and is therefore
285
293
  * vulnerable to timing attacks. The proper way is to use a method that
286
294
  * always takes the same amount of time when comparing two values, thus
287
- * not leaking any information to potential attackers. To compare two
288
- * values, the following could be used:
289
- *
290
- * def eql_time_cmp(a, b)
291
- * unless a.length == b.length
292
- * return false
293
- * end
294
- * cmp = b.bytes
295
- * result = 0
296
- * a.bytes.each_with_index {|c,i|
297
- * result |= c ^ cmp[i]
298
- * }
299
- * result == 0
300
- * end
301
- *
302
- * Please note that the premature return in case of differing lengths
303
- * typically does not leak valuable information - when using PBKDF2, the
304
- * length of the values to be compared is of fixed size.
295
+ * not leaking any information to potential attackers. To do this, use
296
+ * +OpenSSL.fixed_length_secure_compare+.
305
297
  */
306
298
  mKDF = rb_define_module_under(mOSSL, "KDF");
307
299
  /*
@@ -350,7 +350,7 @@ ossl_spki_verify(VALUE self, VALUE key)
350
350
  * spki = OpenSSL::Netscape::SPKI.new
351
351
  * spki.challenge = "RandomChallenge"
352
352
  * spki.public_key = key.public_key
353
- * spki.sign(key, OpenSSL::Digest::SHA256.new)
353
+ * spki.sign(key, OpenSSL::Digest.new('SHA256'))
354
354
  * #send a request containing this to a server generating a certificate
355
355
  * === Verifying an SPKI request
356
356
  * request = #...