rubysl-openssl 2.10 → 2.11

Sign up to get free protection for your applications and to get access to all the features.
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);