Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

ossl_hmac.c
Go to the documentation of this file.
1 /*
2 * $Id: ossl_hmac.c 42416 2013-08-06 23:32:42Z zzak $
3 * 'OpenSSL for Ruby' project
4 * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
5 * All rights reserved.
6 */
7 /*
8 * This program is licenced under the same licence as Ruby.
9 * (See the file 'LICENCE'.)
10 */
11 #if !defined(OPENSSL_NO_HMAC)
12
13 #include "ossl.h"
14
15 #define MakeHMAC(obj, klass, ctx) \
16 (obj) = Data_Make_Struct((klass), HMAC_CTX, 0, ossl_hmac_free, (ctx))
17 #define GetHMAC(obj, ctx) do { \
18 Data_Get_Struct((obj), HMAC_CTX, (ctx)); \
19 if (!(ctx)) { \
20 ossl_raise(rb_eRuntimeError, "HMAC wasn't initialized"); \
21 } \
22 } while (0)
23 #define SafeGetHMAC(obj, ctx) do { \
24 OSSL_Check_Kind((obj), cHMAC); \
25 GetHMAC((obj), (ctx)); \
26 } while (0)
27
28 /*
29 * Classes
30 */
31 VALUE cHMAC;
32 VALUE eHMACError;
33
34 /*
35 * Public
36 */
37
38 /*
39 * Private
40 */
41 static void
42 ossl_hmac_free(HMAC_CTX *ctx)
43 {
44 HMAC_CTX_cleanup(ctx);
45 ruby_xfree(ctx);
46 }
47
48 static VALUE
49 ossl_hmac_alloc(VALUE klass)
50 {
51 HMAC_CTX *ctx;
52 VALUE obj;
53
54 MakeHMAC(obj, klass, ctx);
55 HMAC_CTX_init(ctx);
56
57 return obj;
58 }
59
60
61 /*
62 * call-seq:
63 * HMAC.new(key, digest) -> hmac
64 *
65 * Returns an instance of OpenSSL::HMAC set with the key and digest
66 * algorithm to be used. The instance represents the initial state of
67 * the message authentication code before any data has been processed.
68 * To process data with it, use the instance method #update with your
69 * data as an argument.
70 *
71 * === Example
72 *
73 * key = 'key'
74 * digest = OpenSSL::Digest.new('sha1')
75 * instance = OpenSSL::HMAC.new(key, digest)
76 * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
77 * instance.class
78 * #=> OpenSSL::HMAC
79 *
80 * === A note about comparisons
81 *
82 * Two instances won't be equal when they're compared, even if they have the
83 * same value. Use #to_s or #hexdigest to return the authentication code that
84 * the instance represents. For example:
85 *
86 * other_instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1'))
87 * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
88 * instance
89 * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
90 * instance == other_instance
91 * #=> false
92 * instance.to_s == other_instance.to_s
93 * #=> true
94 *
95 */
96 static VALUE
97 ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
98 {
99 HMAC_CTX *ctx;
100
101 StringValue(key);
102 GetHMAC(self, ctx);
103 HMAC_Init(ctx, RSTRING_PTR(key), RSTRING_LENINT(key),
104 GetDigestPtr(digest));
105
106 return self;
107 }
108
109 static VALUE
110 ossl_hmac_copy(VALUE self, VALUE other)
111 {
112 HMAC_CTX *ctx1, *ctx2;
113
114 rb_check_frozen(self);
115 if (self == other) return self;
116
117 GetHMAC(self, ctx1);
118 SafeGetHMAC(other, ctx2);
119
120 HMAC_CTX_copy(ctx1, ctx2);
121 return self;
122 }
123
124 /*
125 * call-seq:
126 * hmac.update(string) -> self
127 *
128 * Returns +self+ updated with the message to be authenticated.
129 * Can be called repeatedly with chunks of the message.
130 *
131 * === Example
132 *
133 * first_chunk = 'The quick brown fox jumps '
134 * second_chunk = 'over the lazy dog'
135 *
136 * instance.update(first_chunk)
137 * #=> 5b9a8038a65d571076d97fe783989e52278a492a
138 * instance.update(second_chunk)
139 * #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9
140 *
141 */
142 static VALUE
143 ossl_hmac_update(VALUE self, VALUE data)
144 {
145 HMAC_CTX *ctx;
146
147 StringValue(data);
148 GetHMAC(self, ctx);
149 HMAC_Update(ctx, (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data));
150
151 return self;
152 }
153
154 static void
155 hmac_final(HMAC_CTX *ctx, unsigned char **buf, unsigned int *buf_len)
156 {
157 HMAC_CTX final;
158
159 HMAC_CTX_copy(&final, ctx);
160 if (!(*buf = OPENSSL_malloc(HMAC_size(&final)))) {
161 HMAC_CTX_cleanup(&final);
162 OSSL_Debug("Allocating %d mem", HMAC_size(&final));
163 ossl_raise(eHMACError, "Cannot allocate memory for hmac");
164 }
165 HMAC_Final(&final, *buf, buf_len);
166 HMAC_CTX_cleanup(&final);
167 }
168
169 /*
170 * call-seq:
171 * hmac.digest -> string
172 *
173 * Returns the authentication code an instance represents as a binary string.
174 *
175 * === Example
176 *
177 * instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1'))
178 * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
179 * instance.digest
180 * #=> "\xF4+\xB0\xEE\xB0\x18\xEB\xBDE\x97\xAEr\x13q\x1E\xC6\a`\x84?"
181 *
182 */
183 static VALUE
184 ossl_hmac_digest(VALUE self)
185 {
186 HMAC_CTX *ctx;
187 unsigned char *buf;
188 unsigned int buf_len;
189 VALUE digest;
190
191 GetHMAC(self, ctx);
192 hmac_final(ctx, &buf, &buf_len);
193 digest = ossl_buf2str((char *)buf, buf_len);
194
195 return digest;
196 }
197
198 /*
199 * call-seq:
200 * hmac.hexdigest -> string
201 *
202 * Returns the authentication code an instance represents as a hex-encoded
203 * string.
204 *
205 */
206 static VALUE
207 ossl_hmac_hexdigest(VALUE self)
208 {
209 HMAC_CTX *ctx;
210 unsigned char *buf;
211 char *hexbuf;
212 unsigned int buf_len;
213 VALUE hexdigest;
214
215 GetHMAC(self, ctx);
216 hmac_final(ctx, &buf, &buf_len);
217 if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * (int)buf_len) {
218 OPENSSL_free(buf);
219 ossl_raise(eHMACError, "Memory alloc error");
220 }
221 OPENSSL_free(buf);
222 hexdigest = ossl_buf2str(hexbuf, 2 * buf_len);
223
224 return hexdigest;
225 }
226
227 /*
228 * call-seq:
229 * hmac.reset -> self
230 *
231 * Returns +self+ as it was when it was first initialized, with all processed
232 * data cleared from it.
233 *
234 * === Example
235 *
236 * data = "The quick brown fox jumps over the lazy dog"
237 * instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1'))
238 * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
239 *
240 * instance.update(data)
241 * #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9
242 * instance.reset
243 * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
244 *
245 */
246 static VALUE
247 ossl_hmac_reset(VALUE self)
248 {
249 HMAC_CTX *ctx;
250
251 GetHMAC(self, ctx);
252 HMAC_Init(ctx, NULL, 0, NULL);
253
254 return self;
255 }
256
257 /*
258 * call-seq:
259 * HMAC.digest(digest, key, data) -> aString
260 *
261 * Returns the authentication code as a binary string. The +digest+ parameter
262 * must be an instance of OpenSSL::Digest.
263 *
264 * === Example
265 *
266 * key = 'key'
267 * data = 'The quick brown fox jumps over the lazy dog'
268 * digest = OpenSSL::Digest.new('sha1')
269 *
270 * hmac = OpenSSL::HMAC.digest(digest, key, data)
271 * #=> "\xDE|\x9B\x85\xB8\xB7\x8A\xA6\xBC\x8Az6\xF7\n\x90p\x1C\x9D\xB4\xD9"
272 *
273 */
274 static VALUE
275 ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
276 {
277 unsigned char *buf;
278 unsigned int buf_len;
279
280 StringValue(key);
281 StringValue(data);
282 buf = HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LENINT(key),
283 (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len);
284
285 return rb_str_new((const char *)buf, buf_len);
286 }
287
288 /*
289 * call-seq:
290 * HMAC.hexdigest(digest, key, data) -> aString
291 *
292 * Returns the authentication code as a hex-encoded string. The +digest+
293 * parameter must be an instance of OpenSSL::Digest.
294 *
295 * === Example
296 *
297 * key = 'key'
298 * data = 'The quick brown fox jumps over the lazy dog'
299 * digest = OpenSSL::Digest.new('sha1')
300 *
301 * hmac = OpenSSL::HMAC.hexdigest(digest, key, data)
302 * #=> "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"
303 *
304 */
305 static VALUE
306 ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
307 {
308 unsigned char *buf;
309 char *hexbuf;
310 unsigned int buf_len;
311 VALUE hexdigest;
312
313 StringValue(key);
314 StringValue(data);
315
316 buf = HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LENINT(key),
317 (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len);
318 if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * (int)buf_len) {
319 ossl_raise(eHMACError, "Cannot convert buf to hexbuf");
320 }
321 hexdigest = ossl_buf2str(hexbuf, 2 * buf_len);
322
323 return hexdigest;
324 }
325
326 /*
327 * INIT
328 */
329 void
330 Init_ossl_hmac()
331 {
332 #if 0
333 /* :nodoc: */
334 mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
335 #endif
336
337 eHMACError = rb_define_class_under(mOSSL, "HMACError", eOSSLError);
338
339 cHMAC = rb_define_class_under(mOSSL, "HMAC", rb_cObject);
340
341 rb_define_alloc_func(cHMAC, ossl_hmac_alloc);
342 rb_define_singleton_method(cHMAC, "digest", ossl_hmac_s_digest, 3);
343 rb_define_singleton_method(cHMAC, "hexdigest", ossl_hmac_s_hexdigest, 3);
344
345 rb_define_method(cHMAC, "initialize", ossl_hmac_initialize, 2);
346 rb_define_copy_func(cHMAC, ossl_hmac_copy);
347
348 rb_define_method(cHMAC, "reset", ossl_hmac_reset, 0);
349 rb_define_method(cHMAC, "update", ossl_hmac_update, 1);
350 rb_define_alias(cHMAC, "<<", "update");
351 rb_define_method(cHMAC, "digest", ossl_hmac_digest, 0);
352 rb_define_method(cHMAC, "hexdigest", ossl_hmac_hexdigest, 0);
353 rb_define_alias(cHMAC, "inspect", "hexdigest");
354 rb_define_alias(cHMAC, "to_s", "hexdigest");
355 }
356
357 #else /* NO_HMAC */
358 # warning >>> OpenSSL is compiled without HMAC support <<<
359 void
360 Init_ossl_hmac()
361 {
362 rb_warning("HMAC will NOT be avaible: OpenSSL is compiled without HMAC.");
363 }
364 #endif /* NO_HMAC */
GetHMAC
#define GetHMAC(obj, ctx)
Definition: ossl_hmac.c:17
mOSSL
VALUE mOSSL
Definition: ossl.c:259
cHMAC
VALUE cHMAC
Definition: ossl_hmac.c:31
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1655
ossl_hmac_free
static void ossl_hmac_free(HMAC_CTX *ctx)
Definition: ossl_hmac.c:42
ossl_hmac_initialize
static VALUE ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
Definition: ossl_hmac.c:97
MakeHMAC
#define MakeHMAC(obj, klass, ctx)
Definition: ossl_hmac.c:15
HMAC_CTX_copy
void HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in)
Definition: openssl_missing.c:26
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:676
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
Init_ossl_hmac
void Init_ossl_hmac()
Definition: ossl_hmac.c:330
eHMACError
VALUE eHMACError
Definition: ossl_hmac.c:32
rb_define_copy_func
#define rb_define_copy_func(klass, func)
Definition: ruby_missing.h:14
ossl_hmac_digest
static VALUE ossl_hmac_digest(VALUE self)
Definition: ossl_hmac.c:184
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1553
GetDigestPtr
const EVP_MD * GetDigestPtr(VALUE obj)
Definition: ossl_digest.c:36
eOSSLError
VALUE eOSSLError
Definition: ossl.c:264
ossl_hmac_alloc
static VALUE ossl_hmac_alloc(VALUE klass)
Definition: ossl_hmac.c:49
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1697
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:841
SafeGetHMAC
#define SafeGetHMAC(obj, ctx)
Definition: ossl_hmac.c:23
ruby_xfree
void ruby_xfree(void *x)
Definition: gc.c:6242
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
ossl_hmac_hexdigest
static VALUE ossl_hmac_hexdigest(VALUE self)
Definition: ossl_hmac.c:207
VALUE
unsigned long VALUE
Definition: ruby.h:88
OSSL_Debug
#define OSSL_Debug
Definition: ossl.h:211
HMAC_CTX_init
void HMAC_CTX_init(HMAC_CTX *ctx)
Definition: openssl_missing.c:95
ossl_hmac_update
static VALUE ossl_hmac_update(VALUE self, VALUE data)
Definition: ossl_hmac.c:143
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:845
ossl_hmac_copy
static VALUE ossl_hmac_copy(VALUE self, VALUE other)
Definition: ossl_hmac.c:110
ossl_hmac_reset
static VALUE ossl_hmac_reset(VALUE self)
Definition: ossl_hmac.c:247
key
uint8_t key[16]
Definition: random.c:1250
ossl_buf2str
VALUE ossl_buf2str(char *buf, int len)
Definition: ossl.c:134
ossl_raise
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:333
ossl_hmac_s_digest
static VALUE ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
Definition: ossl_hmac.c:275
hmac_final
static void hmac_final(HMAC_CTX *ctx, unsigned char **buf, unsigned int *buf_len)
Definition: ossl_hmac.c:155
ossl.h
rb_warning
void rb_warning(const char *fmt,...)
Definition: error.c:236
RSTRING_LENINT
#define RSTRING_LENINT(str)
Definition: ruby.h:853
rb_check_frozen
#define rb_check_frozen(obj)
Definition: intern.h:277
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:746
NULL
#define NULL
Definition: _sdbm.c:103
ossl_hmac_s_hexdigest
static VALUE ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
Definition: ossl_hmac.c:306
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1488
HMAC_CTX_cleanup
void HMAC_CTX_cleanup(HMAC_CTX *ctx)
Definition: openssl_missing.c:105
string2hex
int string2hex(const unsigned char *buf, int buf_len, char **hexbuf, int *hexbuf_len)
Definition: ossl.c:18
StringValue
#define StringValue(v)
Definition: ruby.h:539
rb_str_new
VALUE rb_str_new(const char *, long)
Definition: string.c:534