Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# ext/openssl/ossl_digest.c

Go to the documentation of this file.

    00001 /*
    00002  * $Id: ossl_digest.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 #include "ossl.h"
    00012
    00013 #define GetDigest(obj, ctx) do { \
    00014     Data_Get_Struct(obj, EVP_MD_CTX, ctx); \
    00015     if (!ctx) { \
    00016         ossl_raise(rb_eRuntimeError, "Digest CTX wasn't initialized!"); \
    00017     } \
    00018 } while (0)
    00019 #define SafeGetDigest(obj, ctx) do { \
    00020     OSSL_Check_Kind(obj, cDigest); \
    00021     GetDigest(obj, ctx); \
    00022 } while (0)
    00023
    00024 /*
    00025  * Classes
    00026  */
    00027 VALUE cDigest;
    00028 VALUE eDigestError;
    00029
    00030 static VALUE ossl_digest_alloc(VALUE klass);
    00031
    00032 /*
    00033  * Public
    00034  */
    00035 const EVP_MD *
    00036 GetDigestPtr(VALUE obj)
    00037 {
    00038     const EVP_MD *md;
    00039
    00040     if (TYPE(obj) == T_STRING) {
    00041         const char *name = StringValueCStr(obj);
    00042
    00043         md = EVP_get_digestbyname(name);
    00044         if (!md)
    00045             ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%s).", name);
    00046     } else {
    00047         EVP_MD_CTX *ctx;
    00048
    00049         SafeGetDigest(obj, ctx);
    00050
    00051         md = EVP_MD_CTX_md(ctx);
    00052     }
    00053
    00054     return md;
    00055 }
    00056
    00057 VALUE
    00058 ossl_digest_new(const EVP_MD *md)
    00059 {
    00060     VALUE ret;
    00061     EVP_MD_CTX *ctx;
    00062
    00063     ret = ossl_digest_alloc(cDigest);
    00064     GetDigest(ret, ctx);
    00065     EVP_DigestInit_ex(ctx, md, NULL);
    00066
    00067     return ret;
    00068 }
    00069
    00070 /*
    00071  * Private
    00072  */
    00073 static VALUE
    00074 ossl_digest_alloc(VALUE klass)
    00075 {
    00076     EVP_MD_CTX *ctx;
    00077     VALUE obj;
    00078
    00079     ctx = EVP_MD_CTX_create();
    00080     if (ctx == NULL)
    00081         ossl_raise(rb_eRuntimeError, "EVP_MD_CTX_create() failed");
    00082     obj = Data_Wrap_Struct(klass, 0, EVP_MD_CTX_destroy, ctx);
    00083
    00084     return obj;
    00085 }
    00086
    00087 VALUE ossl_digest_update(VALUE, VALUE);
    00088
    00089 /*
    00090  *  call-seq:
    00091  *     Digest.new(string) -> digest
    00092  *
    00093  */
    00094 static VALUE
    00095 ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
    00096 {
    00097     EVP_MD_CTX *ctx;
    00098     const EVP_MD *md;
    00099     VALUE type, data;
    00100
    00101     rb_scan_args(argc, argv, "11", &type, &data);
    00102     md = GetDigestPtr(type);
    00103     if (!NIL_P(data)) StringValue(data);
    00104
    00105     GetDigest(self, ctx);
    00106     EVP_DigestInit_ex(ctx, md, NULL);
    00107
    00108     if (!NIL_P(data)) return ossl_digest_update(self, data);
    00109     return self;
    00110 }
    00111
    00112 static VALUE
    00113 ossl_digest_copy(VALUE self, VALUE other)
    00114 {
    00115     EVP_MD_CTX *ctx1, *ctx2;
    00116
    00117     rb_check_frozen(self);
    00118     if (self == other) return self;
    00119
    00120     GetDigest(self, ctx1);
    00121     SafeGetDigest(other, ctx2);
    00122
    00123     if (!EVP_MD_CTX_copy(ctx1, ctx2)) {
    00124         ossl_raise(eDigestError, NULL);
    00125     }
    00126     return self;
    00127 }
    00128
    00129 /*
    00130  *  call-seq:
    00131  *     digest.reset -> self
    00132  *
    00133  */
    00134 static VALUE
    00135 ossl_digest_reset(VALUE self)
    00136 {
    00137     EVP_MD_CTX *ctx;
    00138
    00139     GetDigest(self, ctx);
    00140     EVP_DigestInit_ex(ctx, EVP_MD_CTX_md(ctx), NULL);
    00141
    00142     return self;
    00143 }
    00144
    00145 /*
    00146  *  call-seq:
    00147  *     digest.update(string) -> aString
    00148  *
    00149  */
    00150 VALUE
    00151 ossl_digest_update(VALUE self, VALUE data)
    00152 {
    00153     EVP_MD_CTX *ctx;
    00154
    00155     StringValue(data);
    00156     GetDigest(self, ctx);
    00157     EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data));
    00158
    00159     return self;
    00160 }
    00161
    00162 /*
    00163  *  call-seq:
    00164  *      digest.finish -> aString
    00165  *
    00166  */
    00167 static VALUE
    00168 ossl_digest_finish(int argc, VALUE *argv, VALUE self)
    00169 {
    00170     EVP_MD_CTX *ctx;
    00171     VALUE str;
    00172
    00173     rb_scan_args(argc, argv, "01", &str);
    00174
    00175     GetDigest(self, ctx);
    00176
    00177     if (NIL_P(str)) {
    00178         str = rb_str_new(NULL, EVP_MD_CTX_size(ctx));
    00179     } else {
    00180         StringValue(str);
    00181         rb_str_resize(str, EVP_MD_CTX_size(ctx));
    00182     }
    00183
    00184     EVP_DigestFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), NULL);
    00185
    00186     return str;
    00187 }
    00188
    00189 /*
    00190  *  call-seq:
    00191  *      digest.name -> string
    00192  *
    00193  */
    00194 static VALUE
    00195 ossl_digest_name(VALUE self)
    00196 {
    00197     EVP_MD_CTX *ctx;
    00198
    00199     GetDigest(self, ctx);
    00200
    00201     return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx)));
    00202 }
    00203
    00204 /*
    00205  *  call-seq:
    00206  *      digest.digest_size -> integer
    00207  *
    00208  *  Returns the output size of the digest.
    00209  */
    00210 static VALUE
    00211 ossl_digest_size(VALUE self)
    00212 {
    00213     EVP_MD_CTX *ctx;
    00214
    00215     GetDigest(self, ctx);
    00216
    00217     return INT2NUM(EVP_MD_CTX_size(ctx));
    00218 }
    00219
    00220 static VALUE
    00221 ossl_digest_block_length(VALUE self)
    00222 {
    00223     EVP_MD_CTX *ctx;
    00224
    00225     GetDigest(self, ctx);
    00226
    00227     return INT2NUM(EVP_MD_CTX_block_size(ctx));
    00228 }
    00229
    00230 /*
    00231  * INIT
    00232  */
    00233 void
    00234 Init_ossl_digest()
    00235 {
    00236     rb_require("digest");
    00237
    00238 #if 0 /* let rdoc know about mOSSL */
    00239     mOSSL = rb_define_module("OpenSSL");
    00240 #endif
    00241
    00242     cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class"));
    00243     eDigestError = rb_define_class_under(cDigest, "DigestError", eOSSLError);
    00244
    00245     rb_define_alloc_func(cDigest, ossl_digest_alloc);
    00246
    00247     rb_define_method(cDigest, "initialize", ossl_digest_initialize, -1);
    00248     rb_define_copy_func(cDigest, ossl_digest_copy);
    00249     rb_define_method(cDigest, "reset", ossl_digest_reset, 0);
    00250     rb_define_method(cDigest, "update", ossl_digest_update, 1);
    00251     rb_define_alias(cDigest, "<<", "update");
    00252     rb_define_private_method(cDigest, "finish", ossl_digest_finish, -1);
    00253     rb_define_method(cDigest, "digest_length", ossl_digest_size, 0);
    00254     rb_define_method(cDigest, "block_length", ossl_digest_block_length, 0);
    00255
    00256     rb_define_method(cDigest, "name", ossl_digest_name, 0);
    00257 }
    00258