• 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 

Generated on Thu Sep 8 2011 03:50:35 for Ruby by  doxygen 1.7.1