From 11dbedfaad4a9a9521ece2198a8dc491678b1902 Mon Sep 17 00:00:00 2001 From: shyouhei Date: Wed, 29 Aug 2007 04:06:12 +0000 Subject: add tag v1_8_6_5001 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/tags/v1_8_6_5001@13304 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ruby_1_8_6/ext/openssl/ossl_digest.c | 298 +++++++++++++++++++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 ruby_1_8_6/ext/openssl/ossl_digest.c (limited to 'ruby_1_8_6/ext/openssl/ossl_digest.c') diff --git a/ruby_1_8_6/ext/openssl/ossl_digest.c b/ruby_1_8_6/ext/openssl/ossl_digest.c new file mode 100644 index 0000000000..4096b097a2 --- /dev/null +++ b/ruby_1_8_6/ext/openssl/ossl_digest.c @@ -0,0 +1,298 @@ +/* + * $Id$ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +#define GetDigest(obj, ctx) do { \ + Data_Get_Struct(obj, EVP_MD_CTX, ctx); \ + if (!ctx) { \ + ossl_raise(rb_eRuntimeError, "Digest CTX wasn't initialized!"); \ + } \ +} while (0) +#define SafeGetDigest(obj, ctx) do { \ + OSSL_Check_Kind(obj, cDigest); \ + GetDigest(obj, ctx); \ +} while (0) + +/* + * Classes + */ +VALUE mDigest; +VALUE cDigest; +VALUE eDigestError; + +static VALUE ossl_digest_alloc(VALUE klass); + +/* + * Public + */ +const EVP_MD * +GetDigestPtr(VALUE obj) +{ + EVP_MD_CTX *ctx; + + SafeGetDigest(obj, ctx); + + return EVP_MD_CTX_md(ctx); /*== ctx->digest*/ +} + +VALUE +ossl_digest_new(const EVP_MD *md) +{ + VALUE ret; + EVP_MD_CTX *ctx; + + ret = ossl_digest_alloc(cDigest); + GetDigest(ret, ctx); + EVP_MD_CTX_init(ctx); + EVP_DigestInit_ex(ctx, md, NULL); + + return ret; +} + +/* + * Private + */ +static VALUE +ossl_digest_alloc(VALUE klass) +{ + EVP_MD_CTX *ctx; + VALUE obj; + + ctx = EVP_MD_CTX_create(); + if (ctx == NULL) + ossl_raise(rb_eRuntimeError, "EVP_MD_CTX_create() failed"); + EVP_MD_CTX_init(ctx); + obj = Data_Wrap_Struct(klass, 0, EVP_MD_CTX_destroy, ctx); + + return obj; +} + +VALUE ossl_digest_update(VALUE, VALUE); + +static VALUE +ossl_digest_initialize(int argc, VALUE *argv, VALUE self) +{ + EVP_MD_CTX *ctx; + const EVP_MD *md; + char *name; + VALUE type, data; + + rb_scan_args(argc, argv, "11", &type, &data); + StringValue(type); + if (!NIL_P(data)) StringValue(data); + name = StringValuePtr(type); + + md = EVP_get_digestbyname(name); + if (!md) { + ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%s).", name); + } + GetDigest(self, ctx); + EVP_DigestInit_ex(ctx, md, NULL); + + if (!NIL_P(data)) return ossl_digest_update(self, data); + return self; +} + +static VALUE +ossl_digest_copy(VALUE self, VALUE other) +{ + EVP_MD_CTX *ctx1, *ctx2; + + rb_check_frozen(self); + if (self == other) return self; + + GetDigest(self, ctx1); + SafeGetDigest(other, ctx2); + + if (!EVP_MD_CTX_copy(ctx1, ctx2)) { + ossl_raise(eDigestError, NULL); + } + return self; +} + +static VALUE +ossl_digest_reset(VALUE self) +{ + EVP_MD_CTX *ctx; + + GetDigest(self, ctx); + EVP_DigestInit_ex(ctx, EVP_MD_CTX_md(ctx), NULL); + + return self; +} + +VALUE +ossl_digest_update(VALUE self, VALUE data) +{ + EVP_MD_CTX *ctx; + + StringValue(data); + GetDigest(self, ctx); + EVP_DigestUpdate(ctx, RSTRING(data)->ptr, RSTRING(data)->len); + + return self; +} + +static void +digest_final(EVP_MD_CTX *ctx, char **buf, int *buf_len) +{ + EVP_MD_CTX final; + + if (!EVP_MD_CTX_copy(&final, ctx)) { + ossl_raise(eDigestError, NULL); + } + if (!(*buf = OPENSSL_malloc(EVP_MD_CTX_size(&final)))) { + EVP_MD_CTX_cleanup(&final); + ossl_raise(eDigestError, "Cannot allocate mem for digest"); + } + EVP_DigestFinal_ex(&final, *buf, buf_len); + EVP_MD_CTX_cleanup(&final); +} + +static VALUE +ossl_digest_digest(VALUE self) +{ + EVP_MD_CTX *ctx; + char *buf; + int buf_len; + VALUE digest; + + GetDigest(self, ctx); + digest_final(ctx, &buf, &buf_len); + digest = ossl_buf2str(buf, buf_len); + + return digest; +} + +static VALUE +ossl_digest_hexdigest(VALUE self) +{ + EVP_MD_CTX *ctx; + char *buf, *hexbuf; + int buf_len; + VALUE hexdigest; + + GetDigest(self, ctx); + digest_final(ctx, &buf, &buf_len); + if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) { + OPENSSL_free(buf); + ossl_raise(eDigestError, "Memory alloc error"); + } + OPENSSL_free(buf); + hexdigest = ossl_buf2str(hexbuf, 2 * buf_len); + + return hexdigest; +} + +static VALUE +ossl_digest_s_digest(VALUE klass, VALUE str, VALUE data) +{ + VALUE obj = rb_class_new_instance(1, &str, klass); + + ossl_digest_update(obj, data); + + return ossl_digest_digest(obj); +} + +static VALUE +ossl_digest_s_hexdigest(VALUE klass, VALUE str, VALUE data) +{ + VALUE obj = rb_class_new_instance(1, &str, klass); + + ossl_digest_update(obj, data); + + return ossl_digest_hexdigest(obj); +} + +static VALUE +ossl_digest_equal(VALUE self, VALUE other) +{ + EVP_MD_CTX *ctx; + VALUE str1, str2; + + if (rb_obj_is_kind_of(other, cDigest) == Qtrue) { + str2 = ossl_digest_digest(other); + } else { + StringValue(other); + str2 = other; + } + GetDigest(self, ctx); + if (RSTRING(str2)->len == EVP_MD_CTX_size(ctx)) { + str1 = ossl_digest_digest(self); + } else { + str1 = ossl_digest_hexdigest(self); + } + if (RSTRING(str1)->len == RSTRING(str2)->len + && rb_str_cmp(str1, str2) == 0) { + return Qtrue; + } + + return Qfalse; +} + +static VALUE +ossl_digest_name(VALUE self) +{ + EVP_MD_CTX *ctx; + + GetDigest(self, ctx); + + return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx))); +} + +static VALUE +ossl_digest_size(VALUE self) +{ + EVP_MD_CTX *ctx; + + GetDigest(self, ctx); + + return INT2NUM(EVP_MD_CTX_size(ctx)); +} + +/* + * INIT + */ +void +Init_ossl_digest() +{ +#if 0 /* let rdoc know about mOSSL */ + mOSSL = rb_define_module("OpenSSL"); +#endif + + mDigest = rb_define_module_under(mOSSL, "Digest"); + + eDigestError = rb_define_class_under(mDigest, "DigestError", eOSSLError); + + cDigest = rb_define_class_under(mDigest, "Digest", rb_cObject); + + rb_define_alloc_func(cDigest, ossl_digest_alloc); + rb_define_singleton_method(cDigest, "digest", ossl_digest_s_digest, 2); + rb_define_singleton_method(cDigest, "hexdigest", ossl_digest_s_hexdigest, 2); + + rb_define_method(cDigest, "initialize", ossl_digest_initialize, -1); + rb_define_method(cDigest, "reset", ossl_digest_reset, 0); + + rb_define_copy_func(cDigest, ossl_digest_copy); + + rb_define_method(cDigest, "digest", ossl_digest_digest, 0); + rb_define_method(cDigest, "hexdigest", ossl_digest_hexdigest, 0); + rb_define_alias(cDigest, "inspect", "hexdigest"); + rb_define_alias(cDigest, "to_s", "hexdigest"); + + rb_define_method(cDigest, "update", ossl_digest_update, 1); + rb_define_alias(cDigest, "<<", "update"); + + rb_define_method(cDigest, "==", ossl_digest_equal, 1); + + rb_define_method(cDigest, "name", ossl_digest_name, 0); + rb_define_method(cDigest, "size", ossl_digest_size, 0); +} -- cgit v1.2.3