diff options
author | Michal Rokos <m.rokos@sh.cvut.cz> | 2002-06-04 18:11:45 +0000 |
---|---|---|
committer | Michal Rokos <m.rokos@sh.cvut.cz> | 2002-06-04 18:11:45 +0000 |
commit | c210118d5e1b776837c8e2f72ab85fbfba350960 (patch) | |
tree | 98be4f6f81e53428d16877d880b3de99721fa2ff /ossl_cipher.c | |
parent | b9a8ebf667b3b6dd3bdc3dad91f71ac83ac9d594 (diff) | |
download | ruby-openssl-history-c210118d5e1b776837c8e2f72ab85fbfba350960.tar.gz |
Cipher moved to Factory style
Diffstat (limited to 'ossl_cipher.c')
-rw-r--r-- | ossl_cipher.c | 556 |
1 files changed, 59 insertions, 497 deletions
diff --git a/ossl_cipher.c b/ossl_cipher.c index 38e0d7c..3a43d01 100644 --- a/ossl_cipher.c +++ b/ossl_cipher.c @@ -14,44 +14,27 @@ #define GetCipher(obj, ciphp) Data_Get_Struct(obj, ossl_cipher, ciphp) /* - * Constants - */ -/* BASIC TYPES */ -#define UNSPEC 0x0000 -#define ECB 0x1000 -#define CFB 0x2000 -#define OFB 0x4000 -#define CBC 0x8000 -#define EDE 0x0001 -#define EDE3 0x0002 -#define BIT40 0x0028 /*== 40*/ -#define BIT64 0x0040 /*== 64*/ -#define BIT128 0x0080 /*== 128*/ -#define BIT192 0x00C0 /*== 192*/ -#define BIT256 0x0100 /*== 256*/ - -/* * Classes */ VALUE mCipher; VALUE cCipher; VALUE eCipherError; -VALUE cDES, cRC4, cIdea, cRC2, cBlowFish, cCast5, cRC5, cAES; /* * Struct */ typedef struct ossl_cipher_st { - int nid; - EVP_CIPHER_CTX *ctx; + int init; /* HACK - not to coredump when calling 'update' without previous en/decrypt */ + const EVP_CIPHER *cipher; + EVP_CIPHER_CTX ctx; } ossl_cipher; static void ossl_cipher_free(ossl_cipher *ciphp) { if (ciphp) { - if (ciphp->ctx) OPENSSL_free(ciphp->ctx); - ciphp->ctx = NULL; + EVP_CIPHER_CTX_cleanup(&ciphp->ctx); + ciphp->cipher = NULL; free(ciphp); } } @@ -59,57 +42,62 @@ ossl_cipher_free(ossl_cipher *ciphp) /* * PUBLIC */ -int -ossl_cipher_get_NID(VALUE obj) -{ - ossl_cipher *ciphp = NULL; - - OSSL_Check_Type(obj, cCipher); - - GetCipher(obj, ciphp); - - return ciphp->nid; /*EVP_CIPHER_CTX_nid(ciphp->ctx);*/ -} - const EVP_CIPHER * ossl_cipher_get_EVP_CIPHER(VALUE obj) { ossl_cipher *ciphp = NULL; - OSSL_Check_Type(obj, cCipher); + OSSL_Check_Kind(obj, cCipher); GetCipher(obj, ciphp); - return EVP_get_cipherbynid(ciphp->nid); /*EVP_CIPHER_CTX_cipher(ciphp->ctx);*/ + return ciphp->cipher; /*EVP_CIPHER_CTX_cipher(ciphp->ctx);*/ } /* * PRIVATE */ static VALUE -ossl_cipher_s_new(int argc, VALUE *argv, VALUE klass) +ossl_cipher_s_allocate(VALUE klass) { ossl_cipher *ciphp = NULL; VALUE obj; - if (klass == cCipher) - rb_raise(rb_eNotImpError, "cannot do Cipher::Cipher.new - it is an abstract class"); - MakeCipher(obj, klass, ciphp); +/* + * NOT NEEDED IF STATIC if (!(ciphp->ctx = OPENSSL_malloc(sizeof(EVP_CIPHER_CTX)))) { OSSL_Raise(eCipherError, ""); } - rb_obj_call_init(obj, argc, argv); + */ + ciphp->init = Qfalse; + ciphp->cipher = NULL; return obj; } static VALUE +ossl_cipher_initialize(VALUE self, VALUE str) +{ + ossl_cipher *ciphp = NULL; + char *c_name = NULL; + + GetCipher(self, ciphp); + + c_name = StringValuePtr(str); + + if (!(ciphp->cipher = EVP_get_cipherbyname(c_name))) { + rb_raise(rb_eRuntimeError, "Unsupported cipher algorithm (%s).", c_name); + } + + return self; +} + +static VALUE ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self) { ossl_cipher *ciphp = NULL; - const EVP_CIPHER *cipher = NULL; unsigned char iv[EVP_MAX_IV_LENGTH], key[EVP_MAX_KEY_LENGTH]; VALUE pass, init_v; @@ -139,14 +127,15 @@ ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self) } else memcpy(iv, RSTRING(init_v)->ptr, sizeof(iv)); } - EVP_CIPHER_CTX_init(ciphp->ctx); + EVP_CIPHER_CTX_init(&ciphp->ctx); - cipher = EVP_get_cipherbynid(ciphp->nid); - EVP_BytesToKey(cipher, EVP_md5(), iv, RSTRING(pass)->ptr, RSTRING(pass)->len, 1, key, NULL); + EVP_BytesToKey(ciphp->cipher, EVP_md5(), iv, RSTRING(pass)->ptr, RSTRING(pass)->len, 1, key, NULL); - if (!EVP_EncryptInit(ciphp->ctx, cipher, key, iv)) { + if (!EVP_EncryptInit(&ciphp->ctx, ciphp->cipher, key, iv)) { OSSL_Raise(eCipherError, ""); } + ciphp->init = Qtrue; + return self; } @@ -154,7 +143,6 @@ static VALUE ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self) { ossl_cipher *ciphp = NULL; - const EVP_CIPHER *cipher = NULL; unsigned char iv[EVP_MAX_IV_LENGTH], key[EVP_MAX_KEY_LENGTH]; VALUE pass, init_v; @@ -178,17 +166,17 @@ ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self) } else memcpy(iv, RSTRING(init_v)->ptr, EVP_MAX_IV_LENGTH); } - EVP_CIPHER_CTX_init(ciphp->ctx); + EVP_CIPHER_CTX_init(&ciphp->ctx); - cipher = EVP_get_cipherbynid(ciphp->nid); - - /*if (!load_iv((unsigned char **)&header,&(cipher->iv[0]),8)) return(0); * cipher = CIPHER_INFO */ + /*if (!load_iv((unsigned char **)&header,&(ciphp->cipher->iv[0]),8)) return(0); * cipher = CIPHER_INFO */ - EVP_BytesToKey(cipher, EVP_md5(), iv, RSTRING(pass)->ptr, RSTRING(pass)->len, 1, key, NULL); + EVP_BytesToKey(ciphp->cipher, EVP_md5(), iv, RSTRING(pass)->ptr, RSTRING(pass)->len, 1, key, NULL); - if (!EVP_DecryptInit(ciphp->ctx, cipher, key, iv)) { + if (!EVP_DecryptInit(&ciphp->ctx, ciphp->cipher, key, iv)) { OSSL_Raise(eCipherError, ""); } + ciphp->init = Qtrue; + return self; } @@ -202,18 +190,21 @@ ossl_cipher_update(VALUE self, VALUE data) GetCipher(self, ciphp); + if (ciphp->init != Qtrue) { + rb_raise(eCipherError, "Don't call 'update' without preceding 'en/decrypt'."); + } + data = rb_String(data); in = RSTRING(data)->ptr; in_len = RSTRING(data)->len; - if (!(out = OPENSSL_malloc(in_len + EVP_CIPHER_CTX_block_size(ciphp->ctx)))) { + if (!(out = OPENSSL_malloc(in_len + EVP_CIPHER_CTX_block_size(&ciphp->ctx)))) { OSSL_Raise(eCipherError, ""); } - if (!EVP_CipherUpdate(ciphp->ctx, out, &out_len, in, in_len)) { + if (!EVP_CipherUpdate(&ciphp->ctx, out, &out_len, in, in_len)) { OPENSSL_free(out); OSSL_Raise(eCipherError, ""); } - str = rb_str_new(out, out_len); OPENSSL_free(out); @@ -221,7 +212,7 @@ ossl_cipher_update(VALUE self, VALUE data) } static VALUE -ossl_cipher_cipher(VALUE self) +ossl_cipher_final(VALUE self) { ossl_cipher *ciphp = NULL; @@ -231,369 +222,20 @@ ossl_cipher_cipher(VALUE self) GetCipher(self, ciphp); - if (!(out = OPENSSL_malloc(EVP_CIPHER_CTX_block_size(ciphp->ctx)))) { + if (!(out = OPENSSL_malloc(EVP_CIPHER_CTX_block_size(&ciphp->ctx)))) { OSSL_Raise(eCipherError, ""); } - if (!EVP_CipherFinal(ciphp->ctx, out, &out_len)) { + if (!EVP_CipherFinal(&ciphp->ctx, out, &out_len)) { OPENSSL_free(out); OSSL_Raise(eCipherError, ""); } + EVP_CIPHER_CTX_cleanup(&ciphp->ctx); str = rb_str_new(out, out_len); OPENSSL_free(out); - - return str; -} - -/* - * DES - */ -static VALUE -ossl_des_initialize(int argc, VALUE *argv, VALUE self) -{ - ossl_cipher *ciphp = NULL; - int spec = 0, nid = 0; - VALUE mode, type; + ciphp->init = Qfalse; - GetCipher(self, ciphp); - - if (rb_scan_args(argc, argv, "11", &mode, &type) == 2) - spec = FIX2INT(mode) + FIX2INT(type); - else - spec = FIX2INT(mode); - - switch (spec) { - case ECB: - nid = NID_des_ecb; - break; -/* - * NO LONGER SUPPORTED IN OPENSSL - case EDE: - nid = NID_des_ede; - break; - case EDE3: - nid = NID_des_ede3; - break; - */ - case CFB: - nid = NID_des_cfb64; - break; - case EDE+CFB: - nid = NID_des_ede_cfb64; - break; - case EDE3+CFB: - nid = NID_des_ede3_cfb64; - break; - case OFB: - nid = NID_des_ofb64; - break; - case EDE+OFB: - nid = NID_des_ede_ofb64; - break; - case EDE3+OFB: - nid = NID_des_ede3_ofb64; - break; - case CBC: - nid = NID_des_cbc; - break; - case EDE+CBC: - nid = NID_des_ede_cbc; - break; - case EDE3+CBC: - nid = NID_des_ede3_cbc; - break; - default: - rb_raise(rb_eTypeError, "unsupported combination of modes"); - } - ciphp->nid = nid; - - return self; -} - -/* - * RC4 - */ -static VALUE -ossl_rc4_initialize(int argc, VALUE *argv, VALUE self) -{ - ossl_cipher *ciphp = NULL; - int spec = 0, nid = 0; - VALUE mode; - - GetCipher(self, ciphp); - - if (rb_scan_args(argc, argv, "01", &mode) == 1) - spec = FIX2INT(mode); - - switch (spec) { - case UNSPEC: - nid = NID_rc4; - break; - case BIT40: - nid = NID_rc4_40; - break; - default: - rb_raise(rb_eTypeError, "unsupported combination of modes"); - } - ciphp->nid = nid; - - return self; -} - -/* - * Idea - */ -static VALUE -ossl_idea_initialize(int argc, VALUE *argv, VALUE self) -{ - ossl_cipher *ciphp = NULL; - int spec = 0, nid = 0; - VALUE mode; - - GetCipher(self, ciphp); - - rb_scan_args(argc, argv, "10", &mode); - spec = FIX2INT(mode); - - switch (spec) { - case ECB: - nid = NID_idea_ecb; - break; - case CFB: - nid = NID_idea_cfb64; - break; - case OFB: - nid = NID_idea_ofb64; - break; - case CBC: - nid = NID_idea_cbc; - break; - default: - rb_raise(rb_eTypeError, "unsupported combination of modes"); - } - ciphp->nid = nid; - - return self; -} - -/* - * RC2 - */ -static VALUE -ossl_rc2_initialize(int argc, VALUE *argv, VALUE self) -{ - ossl_cipher *ciphp = NULL; - int spec = 0, nid = 0; - VALUE mode, type; - - GetCipher(self, ciphp); - - if (rb_scan_args(argc, argv, "11", &mode, &type) == 2) - spec = FIX2INT(mode) + FIX2INT(type); - else - spec = FIX2INT(mode); - - switch (spec) { - case ECB: - nid = NID_rc2_ecb; - break; - case CBC: - nid = NID_rc2_cbc; - break; - case BIT40+CBC: - nid = NID_rc2_40_cbc; - break; - case BIT64+CBC: - nid = NID_rc2_64_cbc; - break; - case CFB: - nid = NID_rc2_cfb64; - break; - case OFB: - nid = NID_rc2_ofb64; - break; - default: - rb_raise(rb_eTypeError, "unsupported combination of modes"); - } - ciphp->nid = nid; - - return self; -} - -/* - * BlowFish - */ -static VALUE -ossl_bf_initialize(int argc, VALUE *argv, VALUE self) -{ - ossl_cipher *ciphp = NULL; - int spec = 0, nid = 0; - VALUE mode; - - GetCipher(self, ciphp); - - rb_scan_args(argc, argv, "10", &mode); - spec = FIX2INT(mode); - - switch (spec) { - case ECB: - nid = NID_bf_ecb; - break; - case CFB: - nid = NID_bf_cfb64; - break; - case OFB: - nid = NID_bf_ofb64; - break; - case CBC: - nid = NID_bf_cbc; - break; - default: - rb_raise(rb_eTypeError, "unsupported combination of modes"); - } - ciphp->nid = nid; - - return self; -} - -/* - * Cast5 - */ -static VALUE -ossl_cast5_initialize(int argc, VALUE *argv, VALUE self) -{ - ossl_cipher *ciphp = NULL; - int spec = 0, nid = 0; - VALUE mode; - - GetCipher(self, ciphp); - - rb_scan_args(argc, argv, "10", &mode); - spec = FIX2INT(mode); - - switch (spec) { - case ECB: - nid = NID_cast5_ecb; - break; - case CFB: - nid = NID_cast5_cfb64; - break; - case OFB: - nid = NID_cast5_ofb64; - break; - case CBC: - nid = NID_cast5_cbc; - break; - default: - rb_raise(rb_eTypeError, "unsupported combination of modes"); - } - ciphp->nid = nid; - - return self; -} - -/* - * RC5 - */ -static VALUE -ossl_rc5_initialize(int argc, VALUE *argv, VALUE self) -{ - ossl_cipher *ciphp = NULL; - int spec = 0, nid = 0; - VALUE mode; - - GetCipher(self, ciphp); - - rb_scan_args(argc, argv, "10", &mode); - spec = FIX2INT(mode); - - switch (spec) { - case ECB: - nid = NID_rc5_ecb; - break; - case CFB: - nid = NID_rc5_cfb64; - break; - case OFB: - nid = NID_rc5_ofb64; - break; - case CBC: - nid = NID_rc5_cbc; - break; - default: - rb_raise(rb_eTypeError, "unsupported combination of modes"); - } - ciphp->nid = nid; - - return self; -} - -#if OPENSSL_VERSION_NUMBER >= 0x00907000L /* DEV version of OpenSSL has AES */ -/* - * AES - */ -static VALUE -ossl_aes_initialize(int argc, VALUE *argv, VALUE self) -{ - ossl_cipher *ciphp = NULL; - int spec = 0, nid = 0; - VALUE mode, type; - - GetCipher(self, ciphp); - - rb_scan_args(argc, argv, "20", &mode, &type); - spec = FIX2INT(mode) + FIX2INT(type); - - switch (spec) { - case BIT128+ECB: - nid = NID_aes_128_ecb; - break; - /* - case BIT128+CFB: - nid = NID_aes_128_cfb; - break; - case BIT128+OFB: - nid = NID_aes_128_ofb; - break; - */ - case BIT128+CBC: - nid = NID_aes_128_cbc; - break; - case BIT192+ECB: - nid = NID_aes_192_ecb; - break; - /* - case BIT192+CFB: - nid = NID_aes_192_cfb; - break; - case BIT192+OFB: - nid = NID_aes_192_ofb; - break; - */ - case BIT192+CBC: - nid = NID_aes_192_cbc; - break; - case BIT256+ECB: - nid = NID_aes_256_ecb; - break; - /* - case BIT256+CFB: - nid = NID_aes_256_cfb; - break; - case BIT256+OFB: - nid = NID_aes_256_ofb; - break; - */ - case BIT256+CBC: - nid = NID_aes_256_cbc; - break; - default: - rb_raise(rb_eTypeError, "unsupported combination of modes"); - } - ciphp->nid = nid; - - return self; + return str; } -#endif /* OPENSSL_VERSION_NUMBER */ /* * INIT @@ -606,96 +248,16 @@ Init_ossl_cipher(void) eCipherError = rb_define_class_under(mOSSL, "CipherError", eOSSLError); cCipher = rb_define_class_under(mCipher, "Cipher", rb_cObject); - rb_define_singleton_method(cCipher, "new", ossl_cipher_s_new, -1); - /*"initialize"*/ + + rb_define_singleton_method(cCipher, "allocate", ossl_cipher_s_allocate, 0); + rb_define_method(cCipher, "initialize", ossl_cipher_initialize, 1); + rb_enable_super(cCipher, "initialize"); + rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, -1); rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, -1); rb_define_method(cCipher, "update", ossl_cipher_update, 1); rb_define_alias(cCipher, "<<", "update"); - rb_define_method(cCipher, "cipher", ossl_cipher_cipher, 0); - -/* - * Constants - */ -#define DefCipherConst(x) rb_define_const(mOSSL, #x, INT2FIX(x)) - - DefCipherConst(ECB); - DefCipherConst(EDE); - DefCipherConst(EDE3); - DefCipherConst(CFB); - DefCipherConst(OFB); - DefCipherConst(CBC); - DefCipherConst(BIT40); - DefCipherConst(BIT64); - DefCipherConst(BIT128); - DefCipherConst(BIT192); - DefCipherConst(BIT256); - -/* - * automation for classes creation and initialize method binding - */ -#define DefCipher(name, func) \ - c##name = rb_define_class_under(mOSSL, #name, cCipher); \ - rb_define_method(c##name, "initialize", ossl_##func##_initialize, -1) - -/* - * create classes and bind initialize method - */ -#if !defined(OPENSSL_NO_DES) - DefCipher(DES, des); -#else -# warning >>> OpenSSL is compiled without DES support <<< - rb_warning("OpenSSL is compiled without DES support"); -#endif /* NO_DES */ - -#if !defined(OPENSSL_NO_RC2) - DefCipher(RC2, rc2); -#else -# warning >>> OpenSSL is compiled without RC2 support <<< - rb_warning("OpenSSL is compiled without RC2 support"); -#endif /* NO_RC2 */ - -#if !defined(OPENSSL_NO_RC4) - DefCipher(RC4, rc4); -#else -# warning >>> OpenSSL is compiled without RC4 support <<< - rb_warning("OpenSSL is compiled without RC4 support"); -#endif /* NO_RC4 */ - -#if !defined(OPENSSL_NO_RC5) - DefCipher(RC5, rc5); -#else -# warning >>> OpenSSL is compiled without RC5 support <<< - rb_warning("OpenSSL is compiled without RC5 support"); -#endif /* NO_RC5 */ - -#if !defined(OPENSSL_NO_BF) - DefCipher(BlowFish, bf); -#else -# warning >>> OpenSSL is compiled without BF support <<< - rb_warning("OpenSSL is compiled without BlowFish support"); -#endif /* NO_BF */ - -#if !defined(OPENSSL_NO_CAST) - DefCipher(Cast5, cast5); -#else -# warning >>> OpenSSL is compiled without CAST support <<< - rb_warning("OpenSSL is compiled without Cast5 support"); -#endif /* NO_CAST */ - -#if !defined(OPENSSL_NO_IDEA) - DefCipher(Idea, idea); -#else -# warning >>> OpenSSL is compiled without IDEA support <<< - rb_warning("OpenSSL is compiled without Idea support"); -#endif /* NO_IDEA */ - -#if !defined(OPENSSL_NO_AES) - DefCipher(AES, aes); -#else -# warning >>> OpenSSL is compiled without AES support <<< - rb_warning("OpenSSL is compiled without AES support"); -#endif /* NO_AES */ + rb_define_method(cCipher, "final", ossl_cipher_final, 0); } /* Init_ossl_cipher */ |