Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# ext/openssl/ossl_hmac.c

Go to the documentation of this file.

    00001 /*
    00002  * $Id: ossl_hmac.c 27440 2010-04-22 08:21:01Z nobu $
    00003  * 'OpenSSL for Ruby' project
    00004  * Copyright (C) 2001-2002  Michal Rokos <m.rokos@sh.cvut.cz>
    00005  * All rights reserved.
    00006  */
    00007 /*
    00008  * This program is licenced under the same licence as Ruby.
    00009  * (See the file 'LICENCE'.)
    00010  */
    00011 #if !defined(OPENSSL_NO_HMAC)
    00012
    00013 #include "ossl.h"
    00014
    00015 #define MakeHMAC(obj, klass, ctx) \
    00016     obj = Data_Make_Struct(klass, HMAC_CTX, 0, ossl_hmac_free, ctx)
    00017 #define GetHMAC(obj, ctx) do { \
    00018     Data_Get_Struct(obj, HMAC_CTX, ctx); \
    00019     if (!ctx) { \
    00020         ossl_raise(rb_eRuntimeError, "HMAC wasn't initialized"); \
    00021     } \
    00022 } while (0)
    00023 #define SafeGetHMAC(obj, ctx) do { \
    00024     OSSL_Check_Kind(obj, cHMAC); \
    00025     GetHMAC(obj, ctx); \
    00026 } while (0)
    00027
    00028 /*
    00029  * Classes
    00030  */
    00031 VALUE cHMAC;
    00032 VALUE eHMACError;
    00033
    00034 /*
    00035  * Public
    00036  */
    00037
    00038 /*
    00039  * Private
    00040  */
    00041 static void
    00042 ossl_hmac_free(HMAC_CTX *ctx)
    00043 {
    00044     HMAC_CTX_cleanup(ctx);
    00045     ruby_xfree(ctx);
    00046 }
    00047
    00048 static VALUE
    00049 ossl_hmac_alloc(VALUE klass)
    00050 {
    00051     HMAC_CTX *ctx;
    00052     VALUE obj;
    00053
    00054     MakeHMAC(obj, klass, ctx);
    00055     HMAC_CTX_init(ctx);
    00056
    00057     return obj;
    00058 }
    00059
    00060
    00061 /*
    00062  *  call-seq:
    00063  *     HMAC.new(key, digest) -> hmac
    00064  *
    00065  */
    00066 static VALUE
    00067 ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
    00068 {
    00069     HMAC_CTX *ctx;
    00070
    00071     StringValue(key);
    00072     GetHMAC(self, ctx);
    00073     HMAC_Init_ex(ctx, RSTRING_PTR(key), RSTRING_LEN(key),
    00074                  GetDigestPtr(digest), NULL);
    00075
    00076     return self;
    00077 }
    00078
    00079 static VALUE
    00080 ossl_hmac_copy(VALUE self, VALUE other)
    00081 {
    00082     HMAC_CTX *ctx1, *ctx2;
    00083
    00084     rb_check_frozen(self);
    00085     if (self == other) return self;
    00086
    00087     GetHMAC(self, ctx1);
    00088     SafeGetHMAC(other, ctx2);
    00089
    00090     HMAC_CTX_copy(ctx1, ctx2);
    00091     return self;
    00092 }
    00093
    00094 /*
    00095  *  call-seq:
    00096  *     hmac.update(string) -> self
    00097  *
    00098  */
    00099 static VALUE
    00100 ossl_hmac_update(VALUE self, VALUE data)
    00101 {
    00102     HMAC_CTX *ctx;
    00103
    00104     StringValue(data);
    00105     GetHMAC(self, ctx);
    00106     HMAC_Update(ctx, (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data));
    00107
    00108     return self;
    00109 }
    00110
    00111 static void
    00112 hmac_final(HMAC_CTX *ctx, unsigned char **buf, unsigned int *buf_len)
    00113 {
    00114     HMAC_CTX final;
    00115
    00116     HMAC_CTX_copy(&final, ctx);
    00117     if (!(*buf = OPENSSL_malloc(HMAC_size(&final)))) {
    00118         HMAC_CTX_cleanup(&final);
    00119         OSSL_Debug("Allocating %d mem", HMAC_size(&final));
    00120         ossl_raise(eHMACError, "Cannot allocate memory for hmac");
    00121     }
    00122     HMAC_Final(&final, *buf, buf_len);
    00123     HMAC_CTX_cleanup(&final);
    00124 }
    00125
    00126 /*
    00127  *  call-seq:
    00128  *     hmac.digest -> aString
    00129  *
    00130  */
    00131 static VALUE
    00132 ossl_hmac_digest(VALUE self)
    00133 {
    00134     HMAC_CTX *ctx;
    00135     unsigned char *buf;
    00136     unsigned int buf_len;
    00137     VALUE digest;
    00138
    00139     GetHMAC(self, ctx);
    00140     hmac_final(ctx, &buf, &buf_len);
    00141     digest = ossl_buf2str((char *)buf, buf_len);
    00142
    00143     return digest;
    00144 }
    00145
    00146 /*
    00147  *  call-seq:
    00148  *     hmac.hexdigest -> aString
    00149  *
    00150  */
    00151 static VALUE
    00152 ossl_hmac_hexdigest(VALUE self)
    00153 {
    00154     HMAC_CTX *ctx;
    00155     unsigned char *buf;
    00156     char *hexbuf;
    00157     unsigned int buf_len;
    00158     VALUE hexdigest;
    00159
    00160     GetHMAC(self, ctx);
    00161     hmac_final(ctx, &buf, &buf_len);
    00162     if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) {
    00163         OPENSSL_free(buf);
    00164         ossl_raise(eHMACError, "Memory alloc error");
    00165     }
    00166     OPENSSL_free(buf);
    00167     hexdigest = ossl_buf2str(hexbuf, 2 * buf_len);
    00168
    00169     return hexdigest;
    00170 }
    00171
    00172 /*
    00173  *  call-seq:
    00174  *     hmac.reset -> self
    00175  *
    00176  */
    00177 static VALUE
    00178 ossl_hmac_reset(VALUE self)
    00179 {
    00180     HMAC_CTX *ctx;
    00181
    00182     GetHMAC(self, ctx);
    00183     HMAC_Init_ex(ctx, NULL, 0, NULL, NULL);
    00184
    00185     return self;
    00186 }
    00187
    00188 /*
    00189  *  call-seq:
    00190  *     HMAC.digest(digest, key, data) -> aString
    00191  *
    00192  */
    00193 static VALUE
    00194 ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
    00195 {
    00196     unsigned char *buf;
    00197     unsigned int buf_len;
    00198
    00199     StringValue(key);
    00200     StringValue(data);
    00201     buf = HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LEN(key),
    00202                (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len);
    00203
    00204     return rb_str_new((const char *)buf, buf_len);
    00205 }
    00206
    00207 /*
    00208  *  call-seq:
    00209  *     HMAC.digest(digest, key, data) -> aString
    00210  *
    00211  */
    00212 static VALUE
    00213 ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
    00214 {
    00215     unsigned char *buf;
    00216     char *hexbuf;
    00217     unsigned int buf_len;
    00218     VALUE hexdigest;
    00219
    00220     StringValue(key);
    00221     StringValue(data);
    00222
    00223     buf = HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LEN(key),
    00224                (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len);
    00225     if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) {
    00226         ossl_raise(eHMACError, "Cannot convert buf to hexbuf");
    00227     }
    00228     hexdigest = ossl_buf2str(hexbuf, 2 * buf_len);
    00229
    00230     return hexdigest;
    00231 }
    00232
    00233 /*
    00234  * INIT
    00235  */
    00236 void
    00237 Init_ossl_hmac()
    00238 {
    00239 #if 0 /* let rdoc know about mOSSL */
    00240     mOSSL = rb_define_module("OpenSSL");
    00241 #endif
    00242
    00243     eHMACError = rb_define_class_under(mOSSL, "HMACError", eOSSLError);
    00244
    00245     cHMAC = rb_define_class_under(mOSSL, "HMAC", rb_cObject);
    00246
    00247     rb_define_alloc_func(cHMAC, ossl_hmac_alloc);
    00248     rb_define_singleton_method(cHMAC, "digest", ossl_hmac_s_digest, 3);
    00249     rb_define_singleton_method(cHMAC, "hexdigest", ossl_hmac_s_hexdigest, 3);
    00250
    00251     rb_define_method(cHMAC, "initialize", ossl_hmac_initialize, 2);
    00252     rb_define_copy_func(cHMAC, ossl_hmac_copy);
    00253
    00254     rb_define_method(cHMAC, "reset", ossl_hmac_reset, 0);
    00255     rb_define_method(cHMAC, "update", ossl_hmac_update, 1);
    00256     rb_define_alias(cHMAC, "<<", "update");
    00257     rb_define_method(cHMAC, "digest", ossl_hmac_digest, 0);
    00258     rb_define_method(cHMAC, "hexdigest", ossl_hmac_hexdigest, 0);
    00259     rb_define_alias(cHMAC, "inspect", "hexdigest");
    00260     rb_define_alias(cHMAC, "to_s", "hexdigest");
    00261 }
    00262
    00263 #else /* NO_HMAC */
    00264 #  warning >>> OpenSSL is compiled without HMAC support <<<
    00265 void
    00266 Init_ossl_hmac()
    00267 {
    00268     rb_warning("HMAC will NOT be avaible: OpenSSL is compiled without HMAC.");
    00269 }
    00270 #endif /* NO_HMAC */
    00271