diff --git a/src/modules/_Crypto/rsa.c b/src/modules/_Crypto/rsa.c
index 99ee9c4a10ba898a81ba7c5a10b938cdb2958680..aaf4051ca410b3e57b26423ae9373391a19d84f0 100644
--- a/src/modules/_Crypto/rsa.c
+++ b/src/modules/_Crypto/rsa.c
@@ -1,5 +1,5 @@
 /*
- * $Id: rsa.c,v 1.3 2000/01/27 21:16:27 grubba Exp $
+ * $Id: rsa.c,v 1.4 2000/01/31 20:09:00 grubba Exp $
  *
  * Glue to RSA BSAFE's RSA implementation.
  *
@@ -28,16 +28,63 @@
 
 #include <bsafe.h>
 
-RCSID("$Id: rsa.c,v 1.3 2000/01/27 21:16:27 grubba Exp $");
+RCSID("$Id: rsa.c,v 1.4 2000/01/31 20:09:00 grubba Exp $");
 
 struct pike_rsa_data
 {
   B_ALGORITHM_OBJ cipher;
   B_KEY_OBJ key;
+  unsigned int flags;
+  struct pike_string *n;	/* modulo */
+  struct pike_string *e;	/* public exponent */
+  struct pike_string *d;	/* private exponent (if known) */
 };
 
 #define THIS ((struct pike_rsa_data *)(fp->current_storage))
 
+/*
+ * RSA memory handling glue code.
+ */
+
+void T_free(POINTER block)
+{
+  free(block);
+}
+
+POINTER T_malloc(unsigned int len)
+{
+  return malloc(len);
+}
+
+int T_memcmp(POINTER firstBlock, POINTER secondBlock, unsigned int len)
+{
+  return MEMCMP(firstBlock, secondBlock, len);
+}
+
+void T_memcpy(POINTER output, POINTER input, unsigned int len)
+{
+  MEMCPY(output, input, len);
+}
+
+void T_memmove(POINTER output, POINTER input, unsigned int len)
+{
+  MEMMOVE(output, input, len);
+}
+
+void T_memset(POINTER output, int value, unsigned int len)
+{
+  MEMSET(output, value, len);
+}
+
+POINTER T_realloc(POINTER block, unsigned int len)
+{
+  return realloc(block, len);
+}
+
+/*
+ * Object init/exit code.
+ */
+
 static void init_pike_rsa(struct object *o)
 {
   int code;
@@ -54,6 +101,15 @@ static void init_pike_rsa(struct object *o)
 
 static void exit_pike_rsa(struct object *o)
 {
+  if (THIS->n) {
+    free_string(THIS->n);
+  }
+  if (THIS->e) {
+    free_string(THIS->e);
+  }
+  if (THIS->d) {
+    free_string(THIS->d);
+  }
   if (THIS->cipher) {
     B_DestroyAlgorithmObject(&(THIS->cipher));
   }
@@ -63,6 +119,10 @@ static void exit_pike_rsa(struct object *o)
   MEMSET(THIS, 0, sizeof(struct pike_rsa_data));
 }
 
+/*
+ * Public functions
+ */
+
 /* object set_public_key(bignum modulo, bignum pub) */
 static void f_set_public_key(INT32 args)
 {
@@ -74,6 +134,15 @@ static void f_set_public_key(INT32 args)
 
   get_all_args("set_public_key", args, "%o%o", &modulo, &pub);
 
+  if (THIS->n) {
+    free_string(THIS->n);
+    THIS->n = NULL;
+  }
+  if (THIS->e) {
+    free_string(THIS->e);
+    THIS->e = NULL;
+  }
+
   push_int(256);
   apply(modulo, "digits", 1);
 
@@ -82,8 +151,13 @@ static void f_set_public_key(INT32 args)
     error("Unexpected return value from modulo->digits().\n");
   }
 
-  key_info.modulus.data = sp[-1].u.string->str;
-  key_info.modulus.len = sp[-1].u.string->len;
+  if (sp[-1].u.string->len < 12) {
+    error("Too small modulo.\n");
+  }
+
+  copy_shared_string(THIS->n, sp[-1].u.string);
+
+  pop_stack();
 
   push_int(256);
   apply(pub, "digits", 1);
@@ -93,14 +167,9 @@ static void f_set_public_key(INT32 args)
     error("Unexpected return value from pub->digits().\n");
   }
 
-  key_info.exponent.data = sp[-1].u.string->str;
-  key_info.exponent.len = sp[-1].u.string->len;
+  copy_shared_string(THIS->e, sp[-1].u.string);
 
-  if ((code = B_SetKeyInfo(THIS->key, KI_RSAPublic, (POINTER)&key_info))) {
-    error("Failed to set public key.\n");
-  }
-  
-  pop_n_elems(args + 2);
+  pop_n_elems(args + 1);
   ref_push_object(fp->current_object);
 }
 
@@ -115,19 +184,11 @@ static void f_set_private_key(INT32 args)
 
   get_all_args("set_private_key", args, "%o%a", &priv, &extra);
 
-#if 0
-  push_int(256);
-  apply(pub, "digits", 1);
-
-  if ((sp[-1].type != T_STRING) || (!sp[-1].u.string) ||
-      (sp[-1].u.string->size_shift)) {
-    error("Unexpected return value from pub->digits().\n");
+  if (THIS->d) {
+    free_string(THIS->d);
+    THIS->d = NULL;
   }
 
-  key_info.modulus.data = sp[-1].u.string->str;
-  key_info.modulus.len = sp[-1].u.string->len;
-#endif /* 0 */
-
   push_int(256);
   apply(priv, "digits", 1);
 
@@ -136,115 +197,181 @@ static void f_set_private_key(INT32 args)
     error("Unexpected return value from priv->digits().\n");
   }
 
-  key_info.exponent.data = sp[-1].u.string->str;
-  key_info.exponent.len = sp[-1].u.string->len;
+  copy_shared_string(THIS->d, sp[-1].u.string);
 
-  if ((code = B_SetKeyInfo(THIS->key, KI_RSAPrivate, (POINTER)&key_info))) {
-    error("Failed to set public key.\n");
-  }
-  
-  pop_n_elems(args + 2);
+  /* FIXME: extra is currently ignored */
+
+  pop_n_elems(args + 1);
   ref_push_object(fp->current_object);
 }
 
+/* int query_blocksize() */
 static void f_query_blocksize(INT32 args)
 {
+  if (!THIS->n) {
+    error("Public key has not been set.\n");
+  }
+
   pop_n_elems(args);
-  push_int(0);
+  push_int(THIS->n->len - 3);
 }
 
+/* bignum rsa_pad(string message, int type, mixed|void random) */
 static void f_rsa_pad(INT32 args)
 {
+  error("Not yet implemented.\n");
   pop_n_elems(args);
   push_int(0);
 }
 
+/* string rsa_unpad(bignum block, int type) */
 static void f_rsa_unpad(INT32 args)
 {
-  pop_n_elems(args);
-  push_int(0);
+  struct object *block = NULL;
+  INT32 type;
+  int i;
+  struct pike_string *res;
+
+  get_all_args("rsa_unpad", args, "%o%i", &block, &type);
+
+  push_int(256);
+  apply(block, "digits", 1);
+
+  if ((sp[-1].type != T_STRING) || (!sp[-1].u.string) ||
+      (sp[-1].u.string->size_shift)) {
+    error("Unexpected return value from block->digits().\n");
+  }
+
+  if (!THIS->n) {
+    error("Public key has not been set.\n");
+  }
+
+  if (((i = strlen(sp[-1].u.string->str)) < 9) ||
+      (sp[-1].u.string->len != THIS->n->len - 1) ||
+      (sp[-1].u.string->str[0] != type)) {
+    pop_n_elems(args + 1);
+    push_int(0);
+    return;
+  }
+
+  res = make_shared_binary_string(sp[-1].u.string->str + i + 1,
+				  sp[-1].u.string->len - i - 1);
+
+  pop_n_elems(args + 1);
+  push_string(res);
 }
 
+/* object raw_sign(string digest) */
 static void f_raw_sign(INT32 args)
 {
+  error("Not yet implemented.\n");
   pop_n_elems(args);
   push_int(0);
 }
 
+/* int raw_verify(string digest, object s) */
 static void f_raw_verify(INT32 args)
 {
+  error("Not yet implemented.\n");
   pop_n_elems(args);
   push_int(0);
 }
 
+/* object sign(string message, program h, mixed|void r) */
 static void f_sign(INT32 args)
 {
+  error("Not yet implemented.\n");
   pop_n_elems(args);
   push_int(0);
 }
 
+/* int verify(string msg, program h, object sign) */
 static void f_verify(INT32 args)
 {
+  error("Not yet implemented.\n");
   pop_n_elems(args);
   push_int(0);
 }
 
+/* string sha_sign(string message, mixed|void r) */
 static void f_sha_sign(INT32 args)
 {
+  error("Not yet implemented.\n");
   pop_n_elems(args);
   push_int(0);
 }
 
+/* int sha_verify(string message, string signature) */
 static void f_sha_verify(INT32 args)
 {
+  error("Not yet implemented.\n");
   pop_n_elems(args);
   push_int(0);
 }
 
+/* object generate_key(int bits, function|void r) */
 static void f_generate_key(INT32 args)
 {
+  error("Not yet implemented.\n");
   pop_n_elems(args);
   push_int(0);
 }
 
+/* string encrypt(string s, mixed|void r) */
 static void f_encrypt(INT32 args)
 {
+  error("Not yet implemented.\n");
   pop_n_elems(args);
   push_int(0);
 }
 
+/* string decrypt(string s) */
 static void f_decrypt(INT32 args)
 {
+  error("Not yet implemented.\n");
   pop_n_elems(args);
   push_int(0);
 }
 
+/* object set_encrypt_key(array(bignum) key) */
 static void f_set_encrypt_key(INT32 args)
 {
+  error("Not yet implemented.\n");
   pop_n_elems(args);
   push_int(0);
 }
 
+/* object set_decrypt_key(array(bignum) key) */
 static void f_set_decrypt_key(INT32 args)
 {
+  error("Not yet implemented.\n");
   pop_n_elems(args);
   push_int(0);
 }
 
+/* string crypt_block(string s) */
 static void f_crypt_block(INT32 args)
 {
+  error("Not yet implemented.\n");
   pop_n_elems(args);
   push_int(0);
 }
 
+/* int rsa_size() */
 static void f_rsa_size(INT32 args)
 {
+  if (!THIS->n) {
+    error("Public key has not been set.\n");
+  }
+
   pop_n_elems(args);
-  push_int(0);
+  push_int(THIS->n->len);
 }
 
+/* int public_key_equal (object rsa) */
 static void f_public_key_equal(INT32 args)
 {
+  error("Not yet implemented.\n");
   pop_n_elems(args);
   push_int(0);
 }