Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 /* 00002 * $Id: ossl_hmac.c 32609 2011-07-22 04:11:38Z emboss $ 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(ctx, RSTRING_PTR(key), RSTRING_LENINT(key), 00074 GetDigestPtr(digest)); 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 * (int)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(ctx, NULL, 0, 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_LENINT(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_LENINT(key), 00224 (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len); 00225 if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * (int)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 00240 mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */ 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