rubysl-openssl 2.10 → 2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +5 -5
  2. data/ext/rubysl/openssl/deprecation.rb +7 -3
  3. data/ext/rubysl/openssl/extconf.rb +148 -103
  4. data/ext/rubysl/openssl/openssl_missing.c +94 -275
  5. data/ext/rubysl/openssl/openssl_missing.h +167 -98
  6. data/ext/rubysl/openssl/ossl.c +266 -212
  7. data/ext/rubysl/openssl/ossl.h +27 -89
  8. data/ext/rubysl/openssl/ossl_asn1.c +157 -221
  9. data/ext/rubysl/openssl/ossl_asn1.h +11 -3
  10. data/ext/rubysl/openssl/ossl_bio.c +10 -40
  11. data/ext/rubysl/openssl/ossl_bio.h +1 -2
  12. data/ext/rubysl/openssl/ossl_bn.c +144 -100
  13. data/ext/rubysl/openssl/ossl_bn.h +3 -1
  14. data/ext/rubysl/openssl/ossl_cipher.c +270 -195
  15. data/ext/rubysl/openssl/ossl_config.c +7 -1
  16. data/ext/rubysl/openssl/ossl_config.h +0 -1
  17. data/ext/rubysl/openssl/ossl_digest.c +40 -29
  18. data/ext/rubysl/openssl/ossl_engine.c +23 -62
  19. data/ext/rubysl/openssl/ossl_hmac.c +82 -55
  20. data/ext/rubysl/openssl/ossl_ns_spki.c +22 -22
  21. data/ext/rubysl/openssl/ossl_ocsp.c +894 -144
  22. data/ext/rubysl/openssl/ossl_ocsp.h +1 -1
  23. data/ext/rubysl/openssl/ossl_pkcs12.c +47 -19
  24. data/ext/rubysl/openssl/ossl_pkcs5.c +7 -15
  25. data/ext/rubysl/openssl/ossl_pkcs7.c +38 -15
  26. data/ext/rubysl/openssl/ossl_pkey.c +151 -99
  27. data/ext/rubysl/openssl/ossl_pkey.h +123 -29
  28. data/ext/rubysl/openssl/ossl_pkey_dh.c +143 -92
  29. data/ext/rubysl/openssl/ossl_pkey_dsa.c +149 -104
  30. data/ext/rubysl/openssl/ossl_pkey_ec.c +646 -524
  31. data/ext/rubysl/openssl/ossl_pkey_rsa.c +180 -121
  32. data/ext/rubysl/openssl/ossl_rand.c +25 -21
  33. data/ext/rubysl/openssl/ossl_ssl.c +795 -413
  34. data/ext/rubysl/openssl/ossl_ssl.h +3 -0
  35. data/ext/rubysl/openssl/ossl_ssl_session.c +83 -77
  36. data/ext/rubysl/openssl/ossl_version.h +1 -1
  37. data/ext/rubysl/openssl/ossl_x509.c +92 -8
  38. data/ext/rubysl/openssl/ossl_x509.h +14 -5
  39. data/ext/rubysl/openssl/ossl_x509attr.c +77 -41
  40. data/ext/rubysl/openssl/ossl_x509cert.c +45 -46
  41. data/ext/rubysl/openssl/ossl_x509crl.c +51 -57
  42. data/ext/rubysl/openssl/ossl_x509ext.c +39 -33
  43. data/ext/rubysl/openssl/ossl_x509name.c +68 -45
  44. data/ext/rubysl/openssl/ossl_x509req.c +32 -38
  45. data/ext/rubysl/openssl/ossl_x509revoked.c +43 -9
  46. data/ext/rubysl/openssl/ossl_x509store.c +309 -104
  47. data/ext/rubysl/openssl/ruby_missing.h +8 -6
  48. data/lib/openssl/buffering.rb +11 -5
  49. data/lib/openssl/cipher.rb +23 -15
  50. data/lib/openssl/digest.rb +7 -10
  51. data/lib/openssl/pkey.rb +15 -8
  52. data/lib/openssl/ssl.rb +81 -105
  53. data/lib/rubysl/openssl.rb +1 -4
  54. data/lib/rubysl/openssl/version.rb +1 -1
  55. metadata +3 -4
@@ -41,7 +41,7 @@ DupConfigPtr(VALUE obj)
41
41
 
42
42
  OSSL_Check_Kind(obj, cConfig);
43
43
  str = rb_funcall(obj, rb_intern("to_s"), 0);
44
- bio = ossl_obj2bio(str);
44
+ bio = ossl_obj2bio(&str);
45
45
  conf = NCONF_new(NULL);
46
46
  if(!conf){
47
47
  BIO_free(bio);
@@ -72,6 +72,12 @@ void
72
72
  Init_ossl_config(void)
73
73
  {
74
74
  char *default_config_file;
75
+
76
+ #if 0
77
+ mOSSL = rb_define_module("OpenSSL");
78
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
79
+ #endif
80
+
75
81
  eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError);
76
82
  cConfig = rb_define_class_under(mOSSL, "Config", rb_cObject);
77
83
 
@@ -13,7 +13,6 @@
13
13
  extern VALUE cConfig;
14
14
  extern VALUE eConfigError;
15
15
 
16
- CONF* GetConfigPtr(VALUE obj);
17
16
  CONF* DupConfigPtr(VALUE obj);
18
17
  void Init_ossl_config(void);
19
18
 
@@ -61,7 +61,7 @@ GetDigestPtr(VALUE obj)
61
61
  ASN1_OBJECT_free(oid);
62
62
  }
63
63
  if(!md)
64
- ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%s).", name);
64
+ ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%"PRIsVALUE").", obj);
65
65
  } else {
66
66
  EVP_MD_CTX *ctx;
67
67
 
@@ -80,10 +80,13 @@ ossl_digest_new(const EVP_MD *md)
80
80
  EVP_MD_CTX *ctx;
81
81
 
82
82
  ret = ossl_digest_alloc(cDigest);
83
- GetDigest(ret, ctx);
84
- if (EVP_DigestInit_ex(ctx, md, NULL) != 1) {
85
- ossl_raise(eDigestError, "Digest initialization failed.");
86
- }
83
+ ctx = EVP_MD_CTX_new();
84
+ if (!ctx)
85
+ ossl_raise(eDigestError, "EVP_MD_CTX_new");
86
+ RTYPEDDATA_DATA(ret) = ctx;
87
+
88
+ if (!EVP_DigestInit_ex(ctx, md, NULL))
89
+ ossl_raise(eDigestError, "Digest initialization failed");
87
90
 
88
91
  return ret;
89
92
  }
@@ -94,13 +97,7 @@ ossl_digest_new(const EVP_MD *md)
94
97
  static VALUE
95
98
  ossl_digest_alloc(VALUE klass)
96
99
  {
97
- VALUE obj = TypedData_Wrap_Struct(klass, &ossl_digest_type, 0);
98
- EVP_MD_CTX *ctx = EVP_MD_CTX_create();
99
- if (ctx == NULL)
100
- ossl_raise(rb_eRuntimeError, "EVP_MD_CTX_create() failed");
101
- RTYPEDDATA_DATA(obj) = ctx;
102
-
103
- return obj;
100
+ return TypedData_Wrap_Struct(klass, &ossl_digest_type, 0);
104
101
  }
105
102
 
106
103
  VALUE ossl_digest_update(VALUE, VALUE);
@@ -111,17 +108,16 @@ VALUE ossl_digest_update(VALUE, VALUE);
111
108
  *
112
109
  * Creates a Digest instance based on +string+, which is either the ln
113
110
  * (long name) or sn (short name) of a supported digest algorithm.
111
+ *
114
112
  * If +data+ (a +String+) is given, it is used as the initial input to the
115
113
  * Digest instance, i.e.
114
+ *
116
115
  * digest = OpenSSL::Digest.new('sha256', 'digestdata')
116
+ *
117
117
  * is equal to
118
+ *
118
119
  * digest = OpenSSL::Digest.new('sha256')
119
120
  * digest.update('digestdata')
120
- *
121
- * === Example
122
- * digest = OpenSSL::Digest.new('sha1')
123
- *
124
- *
125
121
  */
126
122
  static VALUE
127
123
  ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
@@ -134,11 +130,16 @@ ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
134
130
  md = GetDigestPtr(type);
135
131
  if (!NIL_P(data)) StringValue(data);
136
132
 
137
- GetDigest(self, ctx);
138
- if (EVP_DigestInit_ex(ctx, md, NULL) != 1) {
139
- ossl_raise(eDigestError, "Digest initialization failed.");
133
+ TypedData_Get_Struct(self, EVP_MD_CTX, &ossl_digest_type, ctx);
134
+ if (!ctx) {
135
+ RTYPEDDATA_DATA(self) = ctx = EVP_MD_CTX_new();
136
+ if (!ctx)
137
+ ossl_raise(eDigestError, "EVP_MD_CTX_new");
140
138
  }
141
139
 
140
+ if (!EVP_DigestInit_ex(ctx, md, NULL))
141
+ ossl_raise(eDigestError, "Digest initialization failed");
142
+
142
143
  if (!NIL_P(data)) return ossl_digest_update(self, data);
143
144
  return self;
144
145
  }
@@ -151,7 +152,12 @@ ossl_digest_copy(VALUE self, VALUE other)
151
152
  rb_check_frozen(self);
152
153
  if (self == other) return self;
153
154
 
154
- GetDigest(self, ctx1);
155
+ TypedData_Get_Struct(self, EVP_MD_CTX, &ossl_digest_type, ctx1);
156
+ if (!ctx1) {
157
+ RTYPEDDATA_DATA(self) = ctx1 = EVP_MD_CTX_new();
158
+ if (!ctx1)
159
+ ossl_raise(eDigestError, "EVP_MD_CTX_new");
160
+ }
155
161
  SafeGetDigest(other, ctx2);
156
162
 
157
163
  if (!EVP_MD_CTX_copy(ctx1, ctx2)) {
@@ -203,7 +209,9 @@ ossl_digest_update(VALUE self, VALUE data)
203
209
 
204
210
  StringValue(data);
205
211
  GetDigest(self, ctx);
206
- EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data));
212
+
213
+ if (!EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)))
214
+ ossl_raise(eDigestError, "EVP_DigestUpdate");
207
215
 
208
216
  return self;
209
217
  }
@@ -218,19 +226,21 @@ ossl_digest_finish(int argc, VALUE *argv, VALUE self)
218
226
  {
219
227
  EVP_MD_CTX *ctx;
220
228
  VALUE str;
221
-
222
- rb_scan_args(argc, argv, "01", &str);
229
+ int out_len;
223
230
 
224
231
  GetDigest(self, ctx);
232
+ rb_scan_args(argc, argv, "01", &str);
233
+ out_len = EVP_MD_CTX_size(ctx);
225
234
 
226
235
  if (NIL_P(str)) {
227
- str = rb_str_new(NULL, EVP_MD_CTX_size(ctx));
236
+ str = rb_str_new(NULL, out_len);
228
237
  } else {
229
238
  StringValue(str);
230
- rb_str_resize(str, EVP_MD_CTX_size(ctx));
239
+ rb_str_resize(str, out_len);
231
240
  }
232
241
 
233
- EVP_DigestFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), NULL);
242
+ if (!EVP_DigestFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), NULL))
243
+ ossl_raise(eDigestError, "EVP_DigestFinal_ex");
234
244
 
235
245
  return str;
236
246
  }
@@ -239,7 +249,7 @@ ossl_digest_finish(int argc, VALUE *argv, VALUE self)
239
249
  * call-seq:
240
250
  * digest.name -> string
241
251
  *
242
- * Returns the sn of this Digest instance.
252
+ * Returns the sn of this Digest algorithm.
243
253
  *
244
254
  * === Example
245
255
  * digest = OpenSSL::Digest::SHA512.new
@@ -310,7 +320,8 @@ Init_ossl_digest(void)
310
320
  rb_require("digest");
311
321
 
312
322
  #if 0
313
- mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
323
+ mOSSL = rb_define_module("OpenSSL");
324
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
314
325
  #endif
315
326
 
316
327
  /* Document-class: OpenSSL::Digest
@@ -9,7 +9,7 @@
9
9
  */
10
10
  #include "ossl.h"
11
11
 
12
- #if defined(OSSL_ENGINE_ENABLED)
12
+ #if !defined(OPENSSL_NO_ENGINE)
13
13
 
14
14
  #define NewEngine(klass) \
15
15
  TypedData_Wrap_Struct((klass), &ossl_engine_type, 0)
@@ -96,7 +96,7 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
96
96
  ENGINE_load_builtin_engines();
97
97
  return Qtrue;
98
98
  }
99
- StringValue(name);
99
+ StringValueCStr(name);
100
100
  #ifndef OPENSSL_NO_STATIC_ENGINE
101
101
  #if HAVE_ENGINE_LOAD_DYNAMIC
102
102
  OSSL_ENGINE_LOAD_IF_MATCH(dynamic);
@@ -148,7 +148,7 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
148
148
  OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto);
149
149
  #endif
150
150
  OSSL_ENGINE_LOAD_IF_MATCH(openssl);
151
- rb_warning("no such builtin loader for `%s'", RSTRING_PTR(name));
151
+ rb_warning("no such builtin loader for `%"PRIsVALUE"'", name);
152
152
  return Qnil;
153
153
  #endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
154
154
  }
@@ -160,14 +160,12 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
160
160
  * It is only necessary to run cleanup when engines are loaded via
161
161
  * OpenSSL::Engine.load. However, running cleanup before exit is recommended.
162
162
  *
163
- * See also, https://www.openssl.org/docs/crypto/engine.html
163
+ * Note that this is needed and works only in OpenSSL < 1.1.0.
164
164
  */
165
165
  static VALUE
166
166
  ossl_engine_s_cleanup(VALUE self)
167
167
  {
168
- #if defined(HAVE_ENGINE_CLEANUP)
169
168
  ENGINE_cleanup();
170
- #endif
171
169
  return Qnil;
172
170
  }
173
171
 
@@ -213,7 +211,7 @@ ossl_engine_s_by_id(VALUE klass, VALUE id)
213
211
  ENGINE *e;
214
212
  VALUE obj;
215
213
 
216
- StringValue(id);
214
+ StringValueCStr(id);
217
215
  ossl_engine_s_load(1, &id, klass);
218
216
  obj = NewEngine(klass);
219
217
  if(!(e = ENGINE_by_id(RSTRING_PTR(id))))
@@ -224,22 +222,7 @@ ossl_engine_s_by_id(VALUE klass, VALUE id)
224
222
  ossl_raise(eEngineError, NULL);
225
223
  ENGINE_ctrl(e, ENGINE_CTRL_SET_PASSWORD_CALLBACK,
226
224
  0, NULL, (void(*)(void))ossl_pem_passwd_cb);
227
- ERR_clear_error();
228
-
229
- return obj;
230
- }
231
-
232
- static VALUE
233
- ossl_engine_s_alloc(VALUE klass)
234
- {
235
- ENGINE *e;
236
- VALUE obj;
237
-
238
- obj = NewEngine(klass);
239
- if (!(e = ENGINE_new())) {
240
- ossl_raise(eEngineError, NULL);
241
- }
242
- SetEngine(obj, e);
225
+ ossl_clear_error();
243
226
 
244
227
  return obj;
245
228
  }
@@ -296,7 +279,6 @@ ossl_engine_finish(VALUE self)
296
279
  return Qnil;
297
280
  }
298
281
 
299
- #if defined(HAVE_ENGINE_GET_CIPHER)
300
282
  /* Document-method: OpenSSL::Engine#cipher
301
283
  *
302
284
  * call-seq:
@@ -305,7 +287,7 @@ ossl_engine_finish(VALUE self)
305
287
  * This returns an OpenSSL::Cipher by +name+, if it is available in this
306
288
  * engine.
307
289
  *
308
- * A EngineError will be raised if the cipher is unavailable.
290
+ * An EngineError will be raised if the cipher is unavailable.
309
291
  *
310
292
  * e = OpenSSL::Engine.by_id("openssl")
311
293
  * => #<OpenSSL::Engine id="openssl" name="Software engine support">
@@ -318,12 +300,10 @@ ossl_engine_get_cipher(VALUE self, VALUE name)
318
300
  {
319
301
  ENGINE *e;
320
302
  const EVP_CIPHER *ciph, *tmp;
321
- char *s;
322
303
  int nid;
323
304
 
324
- s = StringValuePtr(name);
325
- tmp = EVP_get_cipherbyname(s);
326
- if(!tmp) ossl_raise(eEngineError, "no such cipher `%s'", s);
305
+ tmp = EVP_get_cipherbyname(StringValueCStr(name));
306
+ if(!tmp) ossl_raise(eEngineError, "no such cipher `%"PRIsVALUE"'", name);
327
307
  nid = EVP_CIPHER_nid(tmp);
328
308
  GetEngine(self, e);
329
309
  ciph = ENGINE_get_cipher(e, nid);
@@ -331,11 +311,7 @@ ossl_engine_get_cipher(VALUE self, VALUE name)
331
311
 
332
312
  return ossl_cipher_new(ciph);
333
313
  }
334
- #else
335
- #define ossl_engine_get_cipher rb_f_notimplement
336
- #endif
337
314
 
338
- #if defined(HAVE_ENGINE_GET_DIGEST)
339
315
  /* Document-method: OpenSSL::Engine#digest
340
316
  *
341
317
  * call-seq:
@@ -357,12 +333,10 @@ ossl_engine_get_digest(VALUE self, VALUE name)
357
333
  {
358
334
  ENGINE *e;
359
335
  const EVP_MD *md, *tmp;
360
- char *s;
361
336
  int nid;
362
337
 
363
- s = StringValuePtr(name);
364
- tmp = EVP_get_digestbyname(s);
365
- if(!tmp) ossl_raise(eEngineError, "no such digest `%s'", s);
338
+ tmp = EVP_get_digestbyname(StringValueCStr(name));
339
+ if(!tmp) ossl_raise(eEngineError, "no such digest `%"PRIsVALUE"'", name);
366
340
  nid = EVP_MD_nid(tmp);
367
341
  GetEngine(self, e);
368
342
  md = ENGINE_get_digest(e, nid);
@@ -370,9 +344,6 @@ ossl_engine_get_digest(VALUE self, VALUE name)
370
344
 
371
345
  return ossl_digest_new(md);
372
346
  }
373
- #else
374
- #define ossl_engine_get_digest rb_f_notimplement
375
- #endif
376
347
 
377
348
  /* Document-method: OpenSSL::Engine#load_private_key
378
349
  *
@@ -393,14 +364,10 @@ ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self)
393
364
  char *sid, *sdata;
394
365
 
395
366
  rb_scan_args(argc, argv, "02", &id, &data);
396
- sid = NIL_P(id) ? NULL : StringValuePtr(id);
397
- sdata = NIL_P(data) ? NULL : StringValuePtr(data);
367
+ sid = NIL_P(id) ? NULL : StringValueCStr(id);
368
+ sdata = NIL_P(data) ? NULL : StringValueCStr(data);
398
369
  GetEngine(self, e);
399
- #if OPENSSL_VERSION_NUMBER < 0x00907000L
400
- pkey = ENGINE_load_private_key(e, sid, sdata);
401
- #else
402
370
  pkey = ENGINE_load_private_key(e, sid, NULL, sdata);
403
- #endif
404
371
  if (!pkey) ossl_raise(eEngineError, NULL);
405
372
  obj = ossl_pkey_new(pkey);
406
373
  OSSL_PKEY_SET_PRIVATE(obj);
@@ -427,14 +394,10 @@ ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self)
427
394
  char *sid, *sdata;
428
395
 
429
396
  rb_scan_args(argc, argv, "02", &id, &data);
430
- sid = NIL_P(id) ? NULL : StringValuePtr(id);
431
- sdata = NIL_P(data) ? NULL : StringValuePtr(data);
397
+ sid = NIL_P(id) ? NULL : StringValueCStr(id);
398
+ sdata = NIL_P(data) ? NULL : StringValueCStr(data);
432
399
  GetEngine(self, e);
433
- #if OPENSSL_VERSION_NUMBER < 0x00907000L
434
- pkey = ENGINE_load_public_key(e, sid, sdata);
435
- #else
436
400
  pkey = ENGINE_load_public_key(e, sid, NULL, sdata);
437
- #endif
438
401
  if (!pkey) ossl_raise(eEngineError, NULL);
439
402
 
440
403
  return ossl_pkey_new(pkey);
@@ -487,10 +450,8 @@ ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self)
487
450
 
488
451
  GetEngine(self, e);
489
452
  rb_scan_args(argc, argv, "11", &cmd, &val);
490
- StringValue(cmd);
491
- if (!NIL_P(val)) StringValue(val);
492
- ret = ENGINE_ctrl_cmd_string(e, RSTRING_PTR(cmd),
493
- NIL_P(val) ? NULL : RSTRING_PTR(val), 0);
453
+ ret = ENGINE_ctrl_cmd_string(e, StringValueCStr(cmd),
454
+ NIL_P(val) ? NULL : StringValueCStr(val), 0);
494
455
  if (!ret) ossl_raise(eEngineError, NULL);
495
456
 
496
457
  return self;
@@ -553,15 +514,19 @@ ossl_engine_inspect(VALUE self)
553
514
  void
554
515
  Init_ossl_engine(void)
555
516
  {
517
+ #if 0
518
+ mOSSL = rb_define_module("OpenSSL");
519
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
520
+ #endif
521
+
556
522
  cEngine = rb_define_class_under(mOSSL, "Engine", rb_cObject);
557
523
  eEngineError = rb_define_class_under(cEngine, "EngineError", eOSSLError);
558
524
 
559
- rb_define_alloc_func(cEngine, ossl_engine_s_alloc);
525
+ rb_undef_alloc_func(cEngine);
560
526
  rb_define_singleton_method(cEngine, "load", ossl_engine_s_load, -1);
561
527
  rb_define_singleton_method(cEngine, "cleanup", ossl_engine_s_cleanup, 0);
562
528
  rb_define_singleton_method(cEngine, "engines", ossl_engine_s_engines, 0);
563
529
  rb_define_singleton_method(cEngine, "by_id", ossl_engine_s_by_id, 1);
564
- rb_undef_method(CLASS_OF(cEngine), "new");
565
530
 
566
531
  rb_define_method(cEngine, "id", ossl_engine_get_id, 0);
567
532
  rb_define_method(cEngine, "name", ossl_engine_get_name, 0);
@@ -585,12 +550,8 @@ Init_ossl_engine(void)
585
550
  #ifdef ENGINE_METHOD_BN_MOD_EXP_CRT
586
551
  DefEngineConst(METHOD_BN_MOD_EXP_CRT);
587
552
  #endif
588
- #ifdef ENGINE_METHOD_CIPHERS
589
553
  DefEngineConst(METHOD_CIPHERS);
590
- #endif
591
- #ifdef ENGINE_METHOD_DIGESTS
592
554
  DefEngineConst(METHOD_DIGESTS);
593
- #endif
594
555
  DefEngineConst(METHOD_ALL);
595
556
  DefEngineConst(METHOD_NONE);
596
557
  }
@@ -11,8 +11,8 @@
11
11
 
12
12
  #include "ossl.h"
13
13
 
14
- #define MakeHMAC(obj, klass, ctx) \
15
- (obj) = TypedData_Make_Struct((klass), HMAC_CTX, &ossl_hmac_type, (ctx))
14
+ #define NewHMAC(klass) \
15
+ TypedData_Wrap_Struct((klass), &ossl_hmac_type, 0)
16
16
  #define GetHMAC(obj, ctx) do { \
17
17
  TypedData_Get_Struct((obj), HMAC_CTX, &ossl_hmac_type, (ctx)); \
18
18
  if (!(ctx)) { \
@@ -40,8 +40,7 @@ VALUE eHMACError;
40
40
  static void
41
41
  ossl_hmac_free(void *ctx)
42
42
  {
43
- HMAC_CTX_cleanup(ctx);
44
- ruby_xfree(ctx);
43
+ HMAC_CTX_free(ctx);
45
44
  }
46
45
 
47
46
  static const rb_data_type_t ossl_hmac_type = {
@@ -55,11 +54,14 @@ static const rb_data_type_t ossl_hmac_type = {
55
54
  static VALUE
56
55
  ossl_hmac_alloc(VALUE klass)
57
56
  {
58
- HMAC_CTX *ctx;
59
57
  VALUE obj;
58
+ HMAC_CTX *ctx;
60
59
 
61
- MakeHMAC(obj, klass, ctx);
62
- HMAC_CTX_init(ctx);
60
+ obj = NewHMAC(klass);
61
+ ctx = HMAC_CTX_new();
62
+ if (!ctx)
63
+ ossl_raise(eHMACError, NULL);
64
+ RTYPEDDATA_DATA(obj) = ctx;
63
65
 
64
66
  return obj;
65
67
  }
@@ -107,8 +109,8 @@ ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
107
109
 
108
110
  StringValue(key);
109
111
  GetHMAC(self, ctx);
110
- HMAC_Init(ctx, RSTRING_PTR(key), RSTRING_LENINT(key),
111
- GetDigestPtr(digest));
112
+ HMAC_Init_ex(ctx, RSTRING_PTR(key), RSTRING_LENINT(key),
113
+ GetDigestPtr(digest), NULL);
112
114
 
113
115
  return self;
114
116
  }
@@ -124,7 +126,8 @@ ossl_hmac_copy(VALUE self, VALUE other)
124
126
  GetHMAC(self, ctx1);
125
127
  SafeGetHMAC(other, ctx2);
126
128
 
127
- HMAC_CTX_copy(ctx1, ctx2);
129
+ if (!HMAC_CTX_copy(ctx1, ctx2))
130
+ ossl_raise(eHMACError, "HMAC_CTX_copy");
128
131
  return self;
129
132
  }
130
133
 
@@ -159,18 +162,21 @@ ossl_hmac_update(VALUE self, VALUE data)
159
162
  }
160
163
 
161
164
  static void
162
- hmac_final(HMAC_CTX *ctx, unsigned char **buf, unsigned int *buf_len)
165
+ hmac_final(HMAC_CTX *ctx, unsigned char *buf, unsigned int *buf_len)
163
166
  {
164
- HMAC_CTX final;
167
+ HMAC_CTX *final;
165
168
 
166
- HMAC_CTX_copy(&final, ctx);
167
- if (!(*buf = OPENSSL_malloc(HMAC_size(&final)))) {
168
- HMAC_CTX_cleanup(&final);
169
- OSSL_Debug("Allocating %d mem", HMAC_size(&final));
170
- ossl_raise(eHMACError, "Cannot allocate memory for hmac");
169
+ final = HMAC_CTX_new();
170
+ if (!final)
171
+ ossl_raise(eHMACError, "HMAC_CTX_new");
172
+
173
+ if (!HMAC_CTX_copy(final, ctx)) {
174
+ HMAC_CTX_free(final);
175
+ ossl_raise(eHMACError, "HMAC_CTX_copy");
171
176
  }
172
- HMAC_Final(&final, *buf, buf_len);
173
- HMAC_CTX_cleanup(&final);
177
+
178
+ HMAC_Final(final, buf, buf_len);
179
+ HMAC_CTX_free(final);
174
180
  }
175
181
 
176
182
  /*
@@ -180,26 +186,25 @@ hmac_final(HMAC_CTX *ctx, unsigned char **buf, unsigned int *buf_len)
180
186
  * Returns the authentication code an instance represents as a binary string.
181
187
  *
182
188
  * === Example
183
- *
184
- * instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1'))
185
- * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
186
- * instance.digest
187
- * #=> "\xF4+\xB0\xEE\xB0\x18\xEB\xBDE\x97\xAEr\x13q\x1E\xC6\a`\x84?"
188
- *
189
+ * instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1'))
190
+ * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
191
+ * instance.digest
192
+ * #=> "\xF4+\xB0\xEE\xB0\x18\xEB\xBDE\x97\xAEr\x13q\x1E\xC6\a`\x84?"
189
193
  */
190
194
  static VALUE
191
195
  ossl_hmac_digest(VALUE self)
192
196
  {
193
197
  HMAC_CTX *ctx;
194
- unsigned char *buf;
195
198
  unsigned int buf_len;
196
- VALUE digest;
199
+ VALUE ret;
197
200
 
198
201
  GetHMAC(self, ctx);
199
- hmac_final(ctx, &buf, &buf_len);
200
- digest = ossl_buf2str((char *)buf, buf_len);
202
+ ret = rb_str_new(NULL, EVP_MAX_MD_SIZE);
203
+ hmac_final(ctx, (unsigned char *)RSTRING_PTR(ret), &buf_len);
204
+ assert(buf_len <= EVP_MAX_MD_SIZE);
205
+ rb_str_set_len(ret, buf_len);
201
206
 
202
- return digest;
207
+ return ret;
203
208
  }
204
209
 
205
210
  /*
@@ -208,27 +213,21 @@ ossl_hmac_digest(VALUE self)
208
213
  *
209
214
  * Returns the authentication code an instance represents as a hex-encoded
210
215
  * string.
211
- *
212
216
  */
213
217
  static VALUE
214
218
  ossl_hmac_hexdigest(VALUE self)
215
219
  {
216
220
  HMAC_CTX *ctx;
217
- unsigned char *buf;
218
- char *hexbuf;
221
+ unsigned char buf[EVP_MAX_MD_SIZE];
219
222
  unsigned int buf_len;
220
- VALUE hexdigest;
223
+ VALUE ret;
221
224
 
222
225
  GetHMAC(self, ctx);
223
- hmac_final(ctx, &buf, &buf_len);
224
- if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * (int)buf_len) {
225
- OPENSSL_free(buf);
226
- ossl_raise(eHMACError, "Memory alloc error");
227
- }
228
- OPENSSL_free(buf);
229
- hexdigest = ossl_buf2str(hexbuf, 2 * buf_len);
226
+ hmac_final(ctx, buf, &buf_len);
227
+ ret = rb_str_new(NULL, buf_len * 2);
228
+ ossl_bin2hex(buf, RSTRING_PTR(ret), buf_len);
230
229
 
231
- return hexdigest;
230
+ return ret;
232
231
  }
233
232
 
234
233
  /*
@@ -256,7 +255,7 @@ ossl_hmac_reset(VALUE self)
256
255
  HMAC_CTX *ctx;
257
256
 
258
257
  GetHMAC(self, ctx);
259
- HMAC_Init(ctx, NULL, 0, NULL);
258
+ HMAC_Init_ex(ctx, NULL, 0, NULL, NULL);
260
259
 
261
260
  return self;
262
261
  }
@@ -312,22 +311,22 @@ ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
312
311
  static VALUE
313
312
  ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
314
313
  {
315
- unsigned char *buf;
316
- char *hexbuf;
314
+ unsigned char buf[EVP_MAX_MD_SIZE];
317
315
  unsigned int buf_len;
318
- VALUE hexdigest;
316
+ VALUE ret;
319
317
 
320
318
  StringValue(key);
321
319
  StringValue(data);
322
320
 
323
- buf = HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LENINT(key),
324
- (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len);
325
- if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * (int)buf_len) {
326
- ossl_raise(eHMACError, "Cannot convert buf to hexbuf");
327
- }
328
- hexdigest = ossl_buf2str(hexbuf, 2 * buf_len);
321
+ if (!HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LENINT(key),
322
+ (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data),
323
+ buf, &buf_len))
324
+ ossl_raise(eHMACError, "HMAC");
325
+
326
+ ret = rb_str_new(NULL, buf_len * 2);
327
+ ossl_bin2hex(buf, RSTRING_PTR(ret), buf_len);
329
328
 
330
- return hexdigest;
329
+ return ret;
331
330
  }
332
331
 
333
332
  /*
@@ -337,10 +336,38 @@ void
337
336
  Init_ossl_hmac(void)
338
337
  {
339
338
  #if 0
340
- /* :nodoc: */
341
- mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
339
+ mOSSL = rb_define_module("OpenSSL");
340
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
342
341
  #endif
343
342
 
343
+ /*
344
+ * Document-class: OpenSSL::HMAC
345
+ *
346
+ * OpenSSL::HMAC allows computing Hash-based Message Authentication Code
347
+ * (HMAC). It is a type of message authentication code (MAC) involving a
348
+ * hash function in combination with a key. HMAC can be used to verify the
349
+ * integrity of a message as well as the authenticity.
350
+ *
351
+ * OpenSSL::HMAC has a similar interface to OpenSSL::Digest.
352
+ *
353
+ * === HMAC-SHA256 using one-shot interface
354
+ *
355
+ * key = "key"
356
+ * data = "message-to-be-authenticated"
357
+ * mac = OpenSSL::HMAC.hexdigest("SHA256", key, data)
358
+ * #=> "cddb0db23f469c8bf072b21fd837149bd6ace9ab771cceef14c9e517cc93282e"
359
+ *
360
+ * === HMAC-SHA256 using incremental interface
361
+ *
362
+ * data1 = File.read("file1")
363
+ * data2 = File.read("file2")
364
+ * key = "key"
365
+ * digest = OpenSSL::Digest::SHA256.new
366
+ * hmac = OpenSSL::HMAC.new(key, digest)
367
+ * hmac << data1
368
+ * hmac << data2
369
+ * mac = hmac.digest
370
+ */
344
371
  eHMACError = rb_define_class_under(mOSSL, "HMACError", eOSSLError);
345
372
 
346
373
  cHMAC = rb_define_class_under(mOSSL, "HMAC", rb_cObject);