Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

260 lines (208 sloc) 5.131 kb
/*
* $Id: ossl_digest.c 25189 2009-10-02 12:04:37Z akr $
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* 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 cDigest;
VALUE eDigestError;
static VALUE ossl_digest_alloc(VALUE klass, SEL sel);
/*
* Public
*/
const EVP_MD *
GetDigestPtr(VALUE obj)
{
const EVP_MD *md;
if (TYPE(obj) == T_STRING) {
const char *name = StringValueCStr(obj);
md = EVP_get_digestbyname(name);
if (!md)
ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%s).", name);
} else {
EVP_MD_CTX *ctx;
SafeGetDigest(obj, ctx);
md = EVP_MD_CTX_md(ctx);
}
return md;
}
VALUE
ossl_digest_new(const EVP_MD *md)
{
VALUE ret;
EVP_MD_CTX *ctx;
ret = ossl_digest_alloc(cDigest, 0);
GetDigest(ret, ctx);
EVP_DigestInit_ex(ctx, md, NULL);
return ret;
}
/*
* Private
*/
static VALUE
ossl_digest_alloc(VALUE klass, SEL sel)
{
EVP_MD_CTX *ctx;
VALUE obj;
ctx = EVP_MD_CTX_create();
if (ctx == NULL)
ossl_raise(rb_eRuntimeError, "EVP_MD_CTX_create() failed");
obj = Data_Wrap_Struct(klass, 0, EVP_MD_CTX_destroy, ctx);
return obj;
}
VALUE ossl_digest_update(VALUE, SEL, VALUE);
/*
* call-seq:
* Digest.new(string) -> digest
*
*/
static VALUE
ossl_digest_initialize(VALUE self, SEL sel, int argc, VALUE *argv)
{
EVP_MD_CTX *ctx;
const EVP_MD *md;
VALUE type, data;
rb_scan_args(argc, argv, "11", &type, &data);
md = GetDigestPtr(type);
if (!NIL_P(data)) StringValue(data);
GetDigest(self, ctx);
EVP_DigestInit_ex(ctx, md, NULL);
if (!NIL_P(data)) return ossl_digest_update(self, 0, data);
return self;
}
static VALUE
ossl_digest_copy(VALUE self, SEL sel, 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;
}
/*
* call-seq:
* digest.reset -> self
*
*/
static VALUE
ossl_digest_reset(VALUE self, SEL sel)
{
EVP_MD_CTX *ctx;
GetDigest(self, ctx);
EVP_DigestInit_ex(ctx, EVP_MD_CTX_md(ctx), NULL);
return self;
}
/*
* call-seq:
* digest.update(string) -> aString
*
*/
VALUE
ossl_digest_update(VALUE self, SEL sel, VALUE data)
{
EVP_MD_CTX *ctx;
StringValue(data);
GetDigest(self, ctx);
EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data));
return self;
}
/*
* call-seq:
* digest.finish -> aString
*
*/
static VALUE
ossl_digest_finish(VALUE self, SEL sel, int argc, VALUE *argv)
{
EVP_MD_CTX *ctx;
VALUE str;
rb_scan_args(argc, argv, "01", &str);
GetDigest(self, ctx);
if (NIL_P(str)) {
str = rb_bstr_new();
}
else {
StringValue(str);
str = rb_str_bstr(str);
}
rb_bstr_resize(str, EVP_MD_CTX_size(ctx));
EVP_DigestFinal_ex(ctx, rb_bstr_bytes(str), NULL);
return str;
}
/*
* call-seq:
* digest.name -> string
*
*/
static VALUE
ossl_digest_name(VALUE self, SEL sel)
{
EVP_MD_CTX *ctx;
GetDigest(self, ctx);
return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx)));
}
/*
* call-seq:
* digest.digest_size -> integer
*
* Returns the output size of the digest.
*/
static VALUE
ossl_digest_size(VALUE self, SEL sel)
{
EVP_MD_CTX *ctx;
GetDigest(self, ctx);
return INT2NUM(EVP_MD_CTX_size(ctx));
}
static VALUE
ossl_digest_block_length(VALUE self, SEL sel)
{
EVP_MD_CTX *ctx;
GetDigest(self, ctx);
return INT2NUM(EVP_MD_CTX_block_size(ctx));
}
/*
* INIT
*/
void
Init_ossl_digest()
{
rb_require("digest");
#if 0 /* let rdoc know about mOSSL */
mOSSL = rb_define_module("OpenSSL");
#endif
cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class"));
eDigestError = rb_define_class_under(cDigest, "DigestError", eOSSLError);
rb_objc_define_method(*(VALUE *)cDigest, "alloc", ossl_digest_alloc, 0);
rb_objc_define_method(cDigest, "initialize", ossl_digest_initialize, -1);
rb_define_copy_func(cDigest, ossl_digest_copy);
rb_objc_define_method(cDigest, "reset", ossl_digest_reset, 0);
rb_objc_define_method(cDigest, "update", ossl_digest_update, 1);
rb_define_alias(cDigest, "<<", "update");
rb_objc_define_private_method(cDigest, "finish", ossl_digest_finish, -1);
rb_objc_define_method(cDigest, "digest_length", ossl_digest_size, 0);
rb_objc_define_method(cDigest, "block_length", ossl_digest_block_length, 0);
rb_objc_define_method(cDigest, "name", ossl_digest_name, 0);
}
Jump to Line
Something went wrong with that request. Please try again.