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,8 +74,7 @@ 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
@@ -86,7 +83,7 @@ ossl_hmac_alloc(VALUE klass)
86
83
*
87
84
* Two instances can be securely compared with #== in constant time:
88
85
*
89
- * other_instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1') )
86
+ * other_instance = OpenSSL::HMAC.new('key', 'SHA1' )
90
87
* #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
91
88
* instance == other_instance
92
89
* #=> true
@@ -95,29 +92,39 @@ ossl_hmac_alloc(VALUE klass)
95
92
static VALUE
96
93
ossl_hmac_initialize (VALUE self , VALUE key , VALUE digest )
97
94
{
98
- HMAC_CTX * ctx ;
95
+ EVP_MD_CTX * ctx ;
96
+ EVP_PKEY * pkey ;
99
97
100
- StringValue (key );
101
98
GetHMAC (self , ctx );
102
- HMAC_Init_ex (ctx , RSTRING_PTR (key ), RSTRING_LENINT (key ),
103
- 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 );
104
112
105
113
return self ;
106
114
}
107
115
108
116
static VALUE
109
117
ossl_hmac_copy (VALUE self , VALUE other )
110
118
{
111
- HMAC_CTX * ctx1 , * ctx2 ;
119
+ EVP_MD_CTX * ctx1 , * ctx2 ;
112
120
113
121
rb_check_frozen (self );
114
122
if (self == other ) return self ;
115
123
116
124
GetHMAC (self , ctx1 );
117
125
GetHMAC (other , ctx2 );
118
-
119
- if (!HMAC_CTX_copy (ctx1 , ctx2 ))
120
- ossl_raise (eHMACError , "HMAC_CTX_copy" );
126
+ if (EVP_MD_CTX_copy (ctx1 , ctx2 ) != 1 )
127
+ ossl_raise (eHMACError , "EVP_MD_CTX_copy" );
121
128
return self ;
122
129
}
123
130
@@ -142,57 +149,41 @@ ossl_hmac_copy(VALUE self, VALUE other)
142
149
static VALUE
143
150
ossl_hmac_update (VALUE self , VALUE data )
144
151
{
145
- HMAC_CTX * ctx ;
152
+ EVP_MD_CTX * ctx ;
146
153
147
154
StringValue (data );
148
155
GetHMAC (self , ctx );
149
- 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" );
150
158
151
159
return self ;
152
160
}
153
161
154
- static void
155
- hmac_final (HMAC_CTX * ctx , unsigned char * buf , unsigned int * buf_len )
156
- {
157
- HMAC_CTX * final ;
158
-
159
- final = HMAC_CTX_new ();
160
- if (!final )
161
- ossl_raise (eHMACError , "HMAC_CTX_new" );
162
-
163
- if (!HMAC_CTX_copy (final , ctx )) {
164
- HMAC_CTX_free (final );
165
- ossl_raise (eHMACError , "HMAC_CTX_copy" );
166
- }
167
-
168
- HMAC_Final (final , buf , buf_len );
169
- HMAC_CTX_free (final );
170
- }
171
-
172
162
/*
173
163
* call-seq:
174
164
* hmac.digest -> string
175
165
*
176
166
* Returns the authentication code an instance represents as a binary string.
177
167
*
178
168
* === Example
179
- * instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1') )
169
+ * instance = OpenSSL::HMAC.new('key', 'SHA1' )
180
170
* #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
181
171
* instance.digest
182
172
* #=> "\xF4+\xB0\xEE\xB0\x18\xEB\xBDE\x97\xAEr\x13q\x1E\xC6\a`\x84?"
183
173
*/
184
174
static VALUE
185
175
ossl_hmac_digest (VALUE self )
186
176
{
187
- HMAC_CTX * ctx ;
188
- unsigned int buf_len ;
177
+ EVP_MD_CTX * ctx ;
178
+ size_t buf_len ;
189
179
VALUE ret ;
190
180
191
181
GetHMAC (self , ctx );
192
182
ret = rb_str_new (NULL , EVP_MAX_MD_SIZE );
193
- hmac_final (ctx , (unsigned char * )RSTRING_PTR (ret ), & buf_len );
194
- assert (buf_len <= EVP_MAX_MD_SIZE );
195
- 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 );
196
187
197
188
return ret ;
198
189
}
@@ -207,13 +198,14 @@ ossl_hmac_digest(VALUE self)
207
198
static VALUE
208
199
ossl_hmac_hexdigest (VALUE self )
209
200
{
210
- HMAC_CTX * ctx ;
201
+ EVP_MD_CTX * ctx ;
211
202
unsigned char buf [EVP_MAX_MD_SIZE ];
212
- unsigned int buf_len ;
203
+ size_t buf_len ;
213
204
VALUE ret ;
214
205
215
206
GetHMAC (self , ctx );
216
- hmac_final (ctx , buf , & buf_len );
207
+ if (EVP_DigestSignFinal (ctx , buf , & buf_len ) != 1 )
208
+ ossl_raise (eHMACError , "EVP_DigestSignFinal" );
217
209
ret = rb_str_new (NULL , buf_len * 2 );
218
210
ossl_bin2hex (buf , RSTRING_PTR (ret ), buf_len );
219
211
@@ -230,7 +222,7 @@ ossl_hmac_hexdigest(VALUE self)
230
222
* === Example
231
223
*
232
224
* data = "The quick brown fox jumps over the lazy dog"
233
- * instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1') )
225
+ * instance = OpenSSL::HMAC.new('key', 'SHA1' )
234
226
* #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
235
227
*
236
228
* instance.update(data)
@@ -242,84 +234,17 @@ ossl_hmac_hexdigest(VALUE self)
242
234
static VALUE
243
235
ossl_hmac_reset (VALUE self )
244
236
{
245
- HMAC_CTX * ctx ;
237
+ EVP_MD_CTX * ctx ;
238
+ EVP_PKEY * pkey ;
246
239
247
240
GetHMAC (self , ctx );
248
- HMAC_Init_ex (ctx , NULL , 0 , NULL , NULL );
241
+ pkey = EVP_PKEY_CTX_get0_pkey (EVP_MD_CTX_pkey_ctx (ctx ));
242
+ if (EVP_DigestSignInit (ctx , NULL , EVP_MD_CTX_md (ctx ), NULL , pkey ) != 1 )
243
+ ossl_raise (eHMACError , "EVP_DigestSignInit" );
249
244
250
245
return self ;
251
246
}
252
247
253
- /*
254
- * call-seq:
255
- * HMAC.digest(digest, key, data) -> aString
256
- *
257
- * Returns the authentication code as a binary string. The _digest_ parameter
258
- * specifies the digest algorithm to use. This may be a String representing
259
- * the algorithm name or an instance of OpenSSL::Digest.
260
- *
261
- * === Example
262
- *
263
- * key = 'key'
264
- * data = 'The quick brown fox jumps over the lazy dog'
265
- *
266
- * hmac = OpenSSL::HMAC.digest('sha1', key, data)
267
- * #=> "\xDE|\x9B\x85\xB8\xB7\x8A\xA6\xBC\x8Az6\xF7\n\x90p\x1C\x9D\xB4\xD9"
268
- *
269
- */
270
- static VALUE
271
- ossl_hmac_s_digest (VALUE klass , VALUE digest , VALUE key , VALUE data )
272
- {
273
- unsigned char * buf ;
274
- unsigned int buf_len ;
275
-
276
- StringValue (key );
277
- StringValue (data );
278
- buf = HMAC (ossl_evp_get_digestbyname (digest ), RSTRING_PTR (key ),
279
- RSTRING_LENINT (key ), (unsigned char * )RSTRING_PTR (data ),
280
- RSTRING_LEN (data ), NULL , & buf_len );
281
-
282
- return rb_str_new ((const char * )buf , buf_len );
283
- }
284
-
285
- /*
286
- * call-seq:
287
- * HMAC.hexdigest(digest, key, data) -> aString
288
- *
289
- * Returns the authentication code as a hex-encoded string. The _digest_
290
- * parameter specifies the digest algorithm to use. This may be a String
291
- * representing the algorithm name or an instance of OpenSSL::Digest.
292
- *
293
- * === Example
294
- *
295
- * key = 'key'
296
- * data = 'The quick brown fox jumps over the lazy dog'
297
- *
298
- * hmac = OpenSSL::HMAC.hexdigest('sha1', key, data)
299
- * #=> "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"
300
- *
301
- */
302
- static VALUE
303
- ossl_hmac_s_hexdigest (VALUE klass , VALUE digest , VALUE key , VALUE data )
304
- {
305
- unsigned char buf [EVP_MAX_MD_SIZE ];
306
- unsigned int buf_len ;
307
- VALUE ret ;
308
-
309
- StringValue (key );
310
- StringValue (data );
311
-
312
- if (!HMAC (ossl_evp_get_digestbyname (digest ), RSTRING_PTR (key ),
313
- RSTRING_LENINT (key ), (unsigned char * )RSTRING_PTR (data ),
314
- RSTRING_LEN (data ), buf , & buf_len ))
315
- ossl_raise (eHMACError , "HMAC" );
316
-
317
- ret = rb_str_new (NULL , buf_len * 2 );
318
- ossl_bin2hex (buf , RSTRING_PTR (ret ), buf_len );
319
-
320
- return ret ;
321
- }
322
-
323
248
/*
324
249
* INIT
325
250
*/
@@ -353,8 +278,7 @@ Init_ossl_hmac(void)
353
278
* data1 = File.binread("file1")
354
279
* data2 = File.binread("file2")
355
280
* key = "key"
356
- * digest = OpenSSL::Digest.new('SHA256')
357
- * hmac = OpenSSL::HMAC.new(key, digest)
281
+ * hmac = OpenSSL::HMAC.new(key, 'SHA256')
358
282
* hmac << data1
359
283
* hmac << data2
360
284
* mac = hmac.digest
@@ -364,8 +288,6 @@ Init_ossl_hmac(void)
364
288
cHMAC = rb_define_class_under (mOSSL , "HMAC" , rb_cObject );
365
289
366
290
rb_define_alloc_func (cHMAC , ossl_hmac_alloc );
367
- rb_define_singleton_method (cHMAC , "digest" , ossl_hmac_s_digest , 3 );
368
- rb_define_singleton_method (cHMAC , "hexdigest" , ossl_hmac_s_hexdigest , 3 );
369
291
370
292
rb_define_method (cHMAC , "initialize" , ossl_hmac_initialize , 2 );
371
293
rb_define_method (cHMAC , "initialize_copy" , ossl_hmac_copy , 1 );
@@ -378,12 +300,3 @@ Init_ossl_hmac(void)
378
300
rb_define_alias (cHMAC , "inspect" , "hexdigest" );
379
301
rb_define_alias (cHMAC , "to_s" , "hexdigest" );
380
302
}
381
-
382
- #else /* NO_HMAC */
383
- # warning >>> OpenSSL is compiled without HMAC support <<<
384
- void
385
- Init_ossl_hmac (void )
386
- {
387
- rb_warning ("HMAC is not available: OpenSSL is compiled without HMAC." );
388
- }
389
- #endif /* NO_HMAC */
0 commit comments