From bf207b17c9fd2016f73bfdaa8bf2472e890b5c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?= <grubba@grubba.org> Date: Thu, 7 Nov 1996 20:29:04 +0100 Subject: [PATCH] Added the generic /precompiled/crypto module. Rev: src/modules/_Crypto/crypto.c:1.2 Rev: src/modules/_Crypto/crypto.doc:1.1 Rev: src/modules/_Crypto/crypto_submodule.doc:1.1 --- src/modules/_Crypto/crypto.c | 317 ++++++++++++++++++++++- src/modules/_Crypto/crypto.doc | 18 ++ src/modules/_Crypto/crypto_submodule.doc | 9 + 3 files changed, 343 insertions(+), 1 deletion(-) create mode 100644 src/modules/_Crypto/crypto.doc create mode 100644 src/modules/_Crypto/crypto_submodule.doc diff --git a/src/modules/_Crypto/crypto.c b/src/modules/_Crypto/crypto.c index 6735237ed4..238998e552 100644 --- a/src/modules/_Crypto/crypto.c +++ b/src/modules/_Crypto/crypto.c @@ -1,5 +1,5 @@ /* - * $Id: crypto.c,v 1.1.1.1 1996/11/05 15:10:09 grubba Exp $ + * $Id: crypto.c,v 1.2 1996/11/07 19:29:02 grubba Exp $ * * A pike module for getting access to some common cryptos. * @@ -39,10 +39,64 @@ * Globals */ +static const char *crypto_functions[] = { + "query_block_size", + "query_key_length", + "set_key", + "encrypt", + "decrypt", + NULL +}; + +static struct program *pike_crypto_program; + /* * Functions */ +static void init_pike_crypto(struct object *o) +{ + memset(PIKE_CRYPTO, 0, sizeof(struct pike_crypto)); +} + +static void exit_pike_crypto(struct object *o) +{ + if (PIKE_CRYPTO->object) { + free_object(PIKE_CRYPTO->object); + } + if (PIKE_CRYPTO->iv) { + MEMSET(PIKE_CRYPTO->iv, 0, PIKE_CRYPTO->block_size); + free(PIKE_CRYPTO->iv); + } + if (PIKE_CRYPTO->overflow) { + MEMSET(PIKE_CRYPTO->overflow, 0, PIKE_CRYPTO->block_size); + free(PIKE_CRYPTO->overflow); + } + memset(PIKE_CRYPTO, 0, sizeof(struct pike_crypto)); +} + +static void check_functions(struct object *o, const char **requiered) +{ + struct program *p; + + if (!o) { + error("/precompiled/crypto: internal error -- no object\n"); + } + if (!requiered) { + return; + } + + p = o->prog; + + while (*requiered) { + if (!find_identifier(*requiered, p)) { + error("/precompiled/crypto: Object is missing identifier \"%s\"\n", + *requiered); + } + requiered++; + } +} + /* * efuns and the like */ @@ -127,6 +181,245 @@ static void f_hex_to_string(INT32 args) sp[-1].u.string->refs++; } +/* + * /precompiled/crypto + */ + +/* void create(program|object, ...) */ +static void f_create(INT32 args) +{ + if (args < 1) { + error("Too few arguments to crypto->create()\n"); + } + if ((sp[-args].type != T_PROGRAM) && + (sp[-args].type != T_OBJECT)) { + error("Bad argument 1 to crypto->create()\n"); + } + if (sp[-args].type == T_PROGRAM) { + PIKE_CRYPTO->object = clone(sp[-args].u.program, args-1); + } else { + if (args != 1) { + error("Too many arguments to crypto->create()\n"); + } + PIKE_CRYPTO->object = sp[-args].u.object; + PIKE_CRYPTO->object->refs++; + } + pop_stack(); /* Just one element left on the stack in both cases */ + + check_functions(PIKE_CRYPTO->object, crypto_functions); + + safe_apply(PIKE_CRYPTO->object, "query_block_size", 0); + + if (sp[-1].type != T_INT) { + error("crypto->create(): query_block_size() didn't return an int\n"); + } + PIKE_CRYPTO->block_size = sp[-1].u.integer; + + pop_stack(); + + if ((!PIKE_CRYPTO->block_size) || + (PIKE_CRYPTO->block_size > 4096)) { + error("crypto->create(): Bad block size %d\n", PIKE_CRYPTO->block_size); + } + + PIKE_CRYPTO->iv = (unsigned char *)xalloc(PIKE_CRYPTO->block_size); + PIKE_CRYPTO->overflow = (unsigned char *)xalloc(PIKE_CRYPTO->block_size); + PIKE_CRYPTO->overflow_len = 0; + MEMSET(PIKE_CRYPTO->iv, 0, PIKE_CRYPTO->block_size); + MEMSET(PIKE_CRYPTO->overflow, 0, PIKE_CRYPTO->block_size); +} + +/* int query_block_size(void) */ +static void f_query_block_size(INT32 args) +{ + pop_n_elems(args); + push_int(PIKE_CRYPTO->block_size); +} + +/* int query_key_length(void) */ +static void f_query_key_length(INT32 args) +{ + safe_apply(PIKE_CRYPTO->object, "query_key_length", args); +} + +/* void set_key(INT32 args) */ +static void f_set_key(INT32 args) +{ + if (PIKE_CRYPTO->block_size) { + MEMSET(PIKE_CRYPTO->iv, 0, PIKE_CRYPTO->block_size); + MEMSET(PIKE_CRYPTO->overflow, 0, PIKE_CRYPTO->block_size); + } else { + error("crypto->set_key(): Object has not been created yet\n"); + } + safe_apply(PIKE_CRYPTO->object, "set_key", args); +} + +/* string encrypt(string) */ +static void f_encrypt(INT32 args) +{ + safe_apply(PIKE_CRYPTO->object, "encrypt", args); +} + +/* string decrypt(string) */ +static void f_decrypt(INT32 args) +{ + safe_apply(PIKE_CRYPTO->object, "decrypt", args); +} + +/* string ecb_encrypt(string) */ +static void f_ecb_encrypt(INT32 args) +{ + unsigned char *result; + INT32 roffset = 0; + INT32 soffset = 0; + + if (args != 1) { + error("Wrong number of arguments to crypto->ecb_encrypt()\n"); + } + if (sp[-1].type != T_STRING) { + error("Bad argument 1 to crypto->ecb_encrypt()\n"); + } + if (!(result = alloca(sp[-1].u.string->len + PIKE_CRYPTO->block_size))) { + error("crypto->ecb_encrypt(): Out of memory\n"); + } + if (PIKE_CRYPTO->overflow_len) { + if (sp[-1].u.string->len >= + (PIKE_CRYPTO->block_size - PIKE_CRYPTO->overflow_len)) { + MEMCPY(PIKE_CRYPTO->overflow + PIKE_CRYPTO->overflow_len, + sp[-1].u.string->str, + (PIKE_CRYPTO->block_size - PIKE_CRYPTO->overflow_len)); + soffset += (PIKE_CRYPTO->block_size - PIKE_CRYPTO->overflow_len); + PIKE_CRYPTO->overflow_len = 0; + push_string(make_shared_binary_string((char *)PIKE_CRYPTO->overflow, + PIKE_CRYPTO->block_size)); + safe_apply(PIKE_CRYPTO->object, "encrypt", 1); + if (sp[-1].type != T_STRING) { + error("crypto->ecb_encrypt(): encrypt() did not return string\n"); + } + if (sp[-1].u.string->len != PIKE_CRYPTO->block_size) { + error("crypto->ecb_encrypt(): Unexpected string length %d\n", + sp[-1].u.string->len); + } + + MEMCPY(result + roffset, sp[-1].u.string->str, PIKE_CRYPTO->block_size); + roffset += PIKE_CRYPTO->block_size; + pop_stack(); + MEMSET(PIKE_CRYPTO->overflow, 0, PIKE_CRYPTO->block_size); + } else { + MEMCPY(PIKE_CRYPTO->overflow + PIKE_CRYPTO->overflow_len, + sp[-1].u.string->str, sp[-1].u.string->len); + PIKE_CRYPTO->overflow_len += sp[-1].u.string->len; + pop_n_elems(args); + push_string(make_shared_binary_string("", 0)); + return; + } + } + + while (soffset + PIKE_CRYPTO->block_size <= sp[-1].u.string->len) { + push_string(make_shared_binary_string(sp[-1].u.string->str + soffset, + PIKE_CRYPTO->block_size)); + soffset += PIKE_CRYPTO->block_size; + safe_apply(PIKE_CRYPTO->object, "encrypt", 1); + if (sp[-1].type != T_STRING) { + error("crypto->ecb_encrypt(): encrypt() did not return string\n"); + } + if (sp[-1].u.string->len != PIKE_CRYPTO->block_size) { + error("crypto->ecb_encrypt(): Unexpected string length %d\n", + sp[-1].u.string->len); + } + + MEMCPY(result + roffset, sp[-1].u.string->str, PIKE_CRYPTO->block_size); + roffset += PIKE_CRYPTO->block_size; + pop_stack(); + } + + if (soffset < sp[-1].u.string->len) { + MEMCPY(PIKE_CRYPTO->overflow, sp[-1].u.string->str + soffset, + sp[-1].u.string->len - soffset); + PIKE_CRYPTO->overflow_len = sp[-1].u.string->len - soffset; + } + + push_string(make_shared_binary_string((char *)result, roffset)); + MEMSET(result, 0, roffset); +} + +/* string ecb_decrypt(string) */ +static void f_ecb_decrypt(INT32 args) +{ + unsigned char *result; + INT32 roffset = 0; + INT32 soffset = 0; + + if (args != 1) { + error("Wrong number of arguments to crypto->ecb_decrypt()\n"); + } + if (sp[-1].type != T_STRING) { + error("Bad argument 1 to crypto->ecb_decrypt()\n"); + } + if (!(result = alloca(sp[-1].u.string->len + PIKE_CRYPTO->block_size))) { + error("crypto->ecb_decrypt(): Out of memory\n"); + } + if (PIKE_CRYPTO->overflow_len) { + if (sp[-1].u.string->len >= + (PIKE_CRYPTO->block_size - PIKE_CRYPTO->overflow_len)) { + MEMCPY(PIKE_CRYPTO->overflow + PIKE_CRYPTO->overflow_len, + sp[-1].u.string->str, + (PIKE_CRYPTO->block_size - PIKE_CRYPTO->overflow_len)); + soffset += (PIKE_CRYPTO->block_size - PIKE_CRYPTO->overflow_len); + PIKE_CRYPTO->overflow_len = 0; + push_string(make_shared_binary_string((char *)PIKE_CRYPTO->overflow, + PIKE_CRYPTO->block_size)); + safe_apply(PIKE_CRYPTO->object, "decrypt", 1); + if (sp[-1].type != T_STRING) { + error("crypto->ecb_decrypt(): decrypt() did not return string\n"); + } + if (sp[-1].u.string->len != PIKE_CRYPTO->block_size) { + error("crypto->ecb_decrypt(): Unexpected string length %d\n", + sp[-1].u.string->len); + } + + MEMCPY(result + roffset, sp[-1].u.string->str, PIKE_CRYPTO->block_size); + roffset += PIKE_CRYPTO->block_size; + pop_stack(); + MEMSET(PIKE_CRYPTO->overflow, 0, PIKE_CRYPTO->block_size); + } else { + MEMCPY(PIKE_CRYPTO->overflow + PIKE_CRYPTO->overflow_len, + sp[-1].u.string->str, sp[-1].u.string->len); + PIKE_CRYPTO->overflow_len += sp[-1].u.string->len; + pop_n_elems(args); + push_string(make_shared_binary_string("", 0)); + return; + } + } + + while (soffset + PIKE_CRYPTO->block_size <= sp[-1].u.string->len) { + push_string(make_shared_binary_string(sp[-1].u.string->str + soffset, + PIKE_CRYPTO->block_size)); + soffset += PIKE_CRYPTO->block_size; + safe_apply(PIKE_CRYPTO->object, "decrypt", 1); + if (sp[-1].type != T_STRING) { + error("crypto->ecb_decrypt(): decrypt() did not return string\n"); + } + if (sp[-1].u.string->len != PIKE_CRYPTO->block_size) { + error("crypto->ecb_decrypt(): Unexpected string length %d\n", + sp[-1].u.string->len); + } + + MEMCPY(result + roffset, sp[-1].u.string->str, PIKE_CRYPTO->block_size); + roffset += PIKE_CRYPTO->block_size; + pop_stack(); + } + + if (soffset < sp[-1].u.string->len) { + MEMCPY(PIKE_CRYPTO->overflow, sp[-1].u.string->str + soffset, + sp[-1].u.string->len - soffset); + PIKE_CRYPTO->overflow_len = sp[-1].u.string->len - soffset; + } + + push_string(make_shared_binary_string((char *)result, roffset)); + MEMSET(result, 0, roffset); +} + /* * Module linkage */ @@ -162,6 +455,28 @@ void init_module_programs(void) * program->refs++; * */ + + start_new_program(); + add_storage(sizeof(struct pike_crypto)); + + add_function("create", f_create, "function(program|object:void)", OPT_EXTERNAL_DEPEND); + + add_function("query_block_size", f_query_block_size, "function(void:int)", OPT_TRY_OPTIMIZE); + add_function("query_key_length", f_query_key_length, "function(void:int)", OPT_TRY_OPTIMIZE); + + add_function("set_key", f_set_key, "function(string:void)", OPT_SIDE_EFFECT); + add_function("encrypt", f_encrypt, "function(string:string)", OPT_EXTERNAL_DEPEND); + add_function("decrypt", f_decrypt, "function(string:string)", OPT_EXTERNAL_DEPEND); + + add_function("ecb_encrypt", f_ecb_encrypt, "function(string:string)", OPT_EXTERNAL_DEPEND); + add_function("ecb_decrypt", f_ecb_decrypt, "function(string:string)", OPT_EXTERNAL_DEPEND); + + set_init_callback(init_pike_crypto); + set_exit_callback(exit_pike_crypto); + + pike_crypto_program = end_c_program("/precompiled/crypto"); + pike_crypto_program->refs++; + init_md2_programs(); init_md5_programs(); init_idea_programs(); diff --git a/src/modules/_Crypto/crypto.doc b/src/modules/_Crypto/crypto.doc new file mode 100644 index 0000000000..87888b7f82 --- /dev/null +++ b/src/modules/_Crypto/crypto.doc @@ -0,0 +1,18 @@ +In essence the /precompiled/crypto program will do a restricted inherit +of the sub-module given to create(). + +string create(program|object); /* Encrypt using this sub-module */ +int query_block_size(void); /* Returns the size of the crypt block */ +int query_key_length(void); /* Returns the minimum key length */ +void set_key(string); /* Sets the encryption/decryption key, and + resets the state */ +string encrypt(string); /* Encrypt the block with the current key */ +string decrypt(string); /* Decrypt the block with the current key */ +string ecb_encrypt(string); /* Encrypt the string, using the + Electronic CookBook method */ +string ecb_decrypt(string); /* Decrypt the string, using the + Electronic CookBook method */ +string cbc_encrypt(string); /* Encrypt the string, using the + Cipher Block Chaining method */ +string cbc_decrypt(string); /* Decrypt the string, using the + Cipher Block Chaining method */ \ No newline at end of file diff --git a/src/modules/_Crypto/crypto_submodule.doc b/src/modules/_Crypto/crypto_submodule.doc new file mode 100644 index 0000000000..0496644d12 --- /dev/null +++ b/src/modules/_Crypto/crypto_submodule.doc @@ -0,0 +1,9 @@ +A block crypto sub-module needs to implement the following Pike-functions to +support encryption/decryption: + +int query_block_size(void); /* Returns the size of the crypt block */ +int query_key_length(void); /* Returns the minimum key length */ +void set_key(string); /* Sets the encryption/decryption key */ +string encrypt(string); /* Encrypt the block with the current key */ +string decrypt(string); /* Decrypt the block with the current key */ + -- GitLab