00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00030
00031 VALUE cHMAC;
00032 VALUE eHMACError;
00033
00034
00035
00036
00037
00038
00039
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
00063
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
00096
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
00128
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
00148
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
00174
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
00190
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
00209
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
00235
00236 void
00237 Init_ossl_hmac()
00238 {
00239 #if 0
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
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
00271