From beb3b3c33082427a2026078a7a5e3693b144ad5e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?=
 <grubba@grubba.org>
Date: Mon, 11 Nov 1996 15:22:08 +0100
Subject: [PATCH] Implemented according to the new "standard".

Rev: src/modules/_Crypto/cbc.c:1.1
---
 .gitattributes            |   1 +
 src/modules/_Crypto/cbc.c | 318 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 319 insertions(+)
 create mode 100644 src/modules/_Crypto/cbc.c

diff --git a/.gitattributes b/.gitattributes
index fb6d2e7f43..e1a8d41a88 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -8,6 +8,7 @@ testfont binary
 # Files containing CVS ids follow.
 # Remove the corresponding line before committing
 # changes to these files.
+/src/modules/_Crypto/cbc.c foreign_ident
 /src/modules/_Crypto/crypto.c foreign_ident
 /src/modules/_Crypto/crypto.h foreign_ident
 /src/modules/_Crypto/des.c foreign_ident
diff --git a/src/modules/_Crypto/cbc.c b/src/modules/_Crypto/cbc.c
new file mode 100644
index 0000000000..c89e1da924
--- /dev/null
+++ b/src/modules/_Crypto/cbc.c
@@ -0,0 +1,318 @@
+/*
+ * $Id: cbc.c,v 1.1 1996/11/11 14:22:08 grubba Exp $
+ *
+ * CBC (Cipher Block Chaining Mode) crypto module for Pike.
+ *
+ * /precompiled/crypto/cbc
+ *
+ * Henrik Grubbström 1996-11-10
+ */
+
+/*
+ * Includes
+ */
+
+/* From the Pike distribution */
+#include "global.h"
+#include "stralloc.h"
+#include "interpret.h"
+#include "svalue.h"
+#include "constants.h"
+#include "macros.h"
+#include "threads.h"
+#include "object.h"
+#include "stralloc.h"
+#include "interpret.h"
+#include "builtin_functions.h"
+
+/* Module specific includes */
+#include "precompiled_crypto.h"
+
+/*
+ * Globals
+ */
+
+static struct program *pike_cbc_program;
+
+/*
+ * Functions
+ */
+
+static void init_pike_cbc(struct object *o)
+{
+  memset(PIKE_CBC, 0, sizeof(struct pike_cbc));
+}
+
+static void exit_pike_cbc(struct object *o)
+{
+  if (PIKE_CBC->object) {
+    free_object(PIKE_CBC->object);
+  }
+  if (PIKE_CBC->iv) {
+    MEMSET(PIKE_CBC->iv, 0, PIKE_CBC->block_size);
+    free(PIKE_CBC->iv);
+  }
+  memset(PIKE_CBC, 0, sizeof(struct pike_cbc));
+}
+
+INLINE static void cbc_encrypt_step(const unsigned char *source,
+				    unsigned char *dest)
+{
+  INT32 block_size = PIKE_CBC->block_size;
+  INT32 i;
+  
+  for (i=0; i < block_size; i++) {
+    PIKE_CBC->iv[i] ^= source[i];
+  }
+
+  push_string(make_shared_binary_string((char *)PIKE_CBC->iv, block_size));
+  safe_apply(PIKE_CBC->object, "crypt_block", 1);
+
+  if (sp[-1].type != T_STRING) {
+    error("cbc->encrypt(): Expected string from crypt_block()\n");
+  }
+  if (sp[-1].u.string->len != block_size) {
+    error("cbc->encrypt(): Bad string length %d returned from crypt_block()\n",
+	  sp[-1].u.string->len);
+  }
+  MEMCPY(PIKE_CBC->iv, sp[-1].u.string->str, block_size);
+  MEMCPY(dest, sp[-1].u.string->str, block_size);
+  pop_stack();
+}
+
+INLINE static void cbc_decrypt_step(const unsigned char *source,
+				    unsigned char *dest)
+{
+  INT32 block_size = PIKE_CBC->block_size;
+  INT32 i;
+  
+  push_string(make_shared_binary_string((const char *)source, block_size));
+  safe_apply(PIKE_CBC->object, "crypt_block", 1);
+
+  if (sp[-1].type != T_STRING) {
+    error("cbc->decrypt(): Expected string from crypt_block()\n");
+  }
+  if (sp[-1].u.string->len != block_size) {
+    error("cbc->decrypt(): Bad string length %d returned from crypt_block()\n",
+	  sp[-1].u.string->len);
+  }
+
+  for (i=0; i < block_size; i++) {
+    dest[i] = PIKE_CBC->iv[i] ^ sp[-1].u.string->str[i];
+  }
+
+  pop_stack();
+  MEMCPY(PIKE_CBC->iv, source, block_size);
+}
+
+/*
+ * efuns and the like
+ */
+
+/* void create(program|object, ...) */
+static void f_create(INT32 args)
+{
+  if (args < 1) {
+    error("Too few arguments to cbc->create()\n");
+  }
+  if ((sp[-args].type != T_PROGRAM) &&
+      (sp[-args].type != T_OBJECT)) {
+    error("Bad argument 1 to cbc->create()\n");
+  }
+  if (sp[-args].type == T_PROGRAM) {
+    PIKE_CBC->object = clone(sp[-args].u.program, args-1);
+  } else {
+    if (args != 1) {
+      error("Too many arguments to cbc->create()\n");
+    }
+    PIKE_CBC->object = sp[-args].u.object;
+    PIKE_CBC->object->refs++;
+  }
+  pop_stack(); /* Just one element left on the stack in both cases */
+
+  assert_is_crypto_module(PIKE_CBC->object);
+
+  safe_apply(PIKE_CBC->object, "query_block_size", 0);
+
+  if (sp[-1].type != T_INT) {
+    error("cbc->create(): query_block_size() didn't return an int\n");
+  }
+  PIKE_CBC->block_size = sp[-1].u.integer;
+
+  pop_stack();
+
+  if ((!PIKE_CBC->block_size) ||
+      (PIKE_CBC->block_size > 4096)) {
+    error("cbc->create(): Bad block size %d\n", PIKE_CBC->block_size);
+  }
+
+  PIKE_CBC->iv = (unsigned char *)xalloc(PIKE_CBC->block_size);
+  MEMSET(PIKE_CBC->iv, 0, PIKE_CBC->block_size);
+}
+
+/* int query_block_size(void) */
+static void f_query_block_size(INT32 args)
+{
+  pop_n_elems(args);
+  push_int(PIKE_CBC->block_size);
+}
+
+/* int query_key_length(void) */
+static void f_query_key_length(INT32 args)
+{
+  safe_apply(PIKE_CBC->object, "query_key_length", args);
+}
+
+/* void set_encrypt_key(INT32 args) */
+static void f_set_encrypt_key(INT32 args)
+{
+  if (PIKE_CBC->block_size) {
+    MEMSET(PIKE_CBC->iv, 0, PIKE_CBC->block_size);
+  } else {
+    error("cbc->set_encrypt_key(): Object has not been created yet\n");
+  }
+  PIKE_CBC->mode = 0;
+  safe_apply(PIKE_CBC->object, "set_encrypt_key", args);
+}
+
+/* void set_decrypt_key(INT32 args) */
+static void f_set_decrypt_key(INT32 args)
+{
+  if (PIKE_CBC->block_size) {
+    MEMSET(PIKE_CBC->iv, 0, PIKE_CBC->block_size);
+  } else {
+    error("cbc->set_decrypt_key(): Object has not been created yet\n");
+  }
+  PIKE_CBC->mode = 1;
+  safe_apply(PIKE_CBC->object, "set_decrypt_key", args);
+}
+
+/* string encrypt_block(string) */
+static void f_encrypt_block(INT32 args)
+{
+  unsigned char *result;
+  INT32 offset = 0;
+
+  if (args != 1) {
+    error("Wrong number of arguments to cbc->encrypt_block()\n");
+  }
+  if (sp[-1].type != T_STRING) {
+    error("Bad argument 1 to cbc->encrypt_block()\n");
+  }
+  if (sp[-1].u.string->len % PIKE_CBC->block_size) {
+    error("Bad length of argument 1 to cbc->encrypt_block()\n");
+  }
+  if (!(result = alloca(sp[-1].u.string->len))) {
+    error("cbc->encrypt_block(): Out of memory\n");
+  }
+
+  while (offset < sp[-1].u.string->len) {
+
+    cbc_encrypt_step((const unsigned char *)sp[-1].u.string->str + offset,
+		     result + offset);
+    offset += PIKE_CBC->block_size;
+  }
+
+  pop_n_elems(args);
+
+  push_string(make_shared_binary_string((char *)result, offset));
+  MEMSET(result, 0, offset);
+}
+
+/* string decrypt_block(string) */
+static void f_decrypt_block(INT32 args)
+{
+  unsigned char *result;
+  INT32 offset = 0;
+
+  if (args != 1) {
+    error("Wrong number of arguments to cbc->decrypt_block()\n");
+  }
+  if (sp[-1].type != T_STRING) {
+    error("Bad argument 1 to cbc->decrypt_block()\n");
+  }
+  if (sp[-1].u.string->len & PIKE_CBC->block_size) {
+    error("Bad length of argument 1 to cbc->decrypt_block()\n");
+  }
+  if (!(result = alloca(sp[-1].u.string->len))) {
+    error("cbc->cbc_decrypt(): Out of memory\n");
+  }
+
+  while (offset < sp[-1].u.string->len) {
+
+    cbc_decrypt_step((const unsigned char *)sp[-1].u.string->str + offset,
+		     result + offset);
+    offset += PIKE_CBC->block_size;
+  }
+
+  pop_n_elems(args);
+
+  push_string(make_shared_binary_string((char *)result, offset));
+  MEMSET(result, 0, offset);
+}
+
+/* string crypt_block(string) */
+static void f_crypt_block(INT32 args)
+{
+  if (PIKE_CBC->mode) {
+    f_decrypt_block(args);
+  } else {
+    f_encrypt_block(args);
+  }
+}
+
+/*
+ * Module linkage
+ */
+
+void init_cbc_efuns(void)
+{
+  /* add_efun()s */
+}
+
+void init_cbc_programs(void)
+{
+  /*
+   * start_new_program();
+   *
+   * add_storage();
+   *
+   * add_function();
+   * add_function();
+   * ...
+   *
+   * set_init_callback();
+   * set_exit_callback();
+   *
+   * program = end_c_program();
+   * program->refs++;
+   *
+   */
+
+  start_new_program();
+  add_storage(sizeof(struct pike_cbc));
+
+  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_encrypt_key", f_set_encrypt_key, "function(string:void)", OPT_SIDE_EFFECT);
+  add_function("set_decrypt_key", f_set_decrypt_key, "function(string:void)", OPT_SIDE_EFFECT);
+  add_function("crypt_block", f_crypt_block, "function(string:string)", OPT_EXTERNAL_DEPEND);
+  add_function("encrypt_block", f_encrypt_block, "function(string:string)", OPT_EXTERNAL_DEPEND);
+  add_function("decrypt_block", f_decrypt_block, "function(string:string)", OPT_EXTERNAL_DEPEND);
+
+  set_init_callback(init_pike_cbc);
+  set_exit_callback(exit_pike_cbc);
+
+  pike_cbc_program = end_c_program("/precompiled/crypto/cbc");
+  pike_cbc_program->refs++;
+}
+
+void exit_cbc(void)
+{
+  /* free_program()s */
+  free_program(pike_cbc_program);
+}
+
-- 
GitLab