Merged silc_1_0_branch to trunk.
[silc.git] / lib / silccrypt / pkcs1.c
index c3136f58eef0d4b39e9d625279dd07e429120a97..98963739d8565565e05cb5624b4f41107449e0c6 100644 (file)
@@ -1,13 +1,15 @@
+/* $Id$ */
 /* 
    PKCS #1 RSA wrapper.
 
-   Heavily modified to work under SILC, code that is not needed in SILC has
-   been removed for good, and some code was fixed and changed.
+   Heavily modified to work under SILC, rewrote all interfaces, code that
+   is not needed in SILC has been removed for good, and some code was fixed
+   and changed.
 
    For example, RSA_DecodeOneBlock was not used at all by Mozilla, however,
-   I took this code in to use after doing some fixing.  Also, OAEP is removed
-   totally for now.  I'm not sure whether OAEP could be used in the future
-   with SILC but not for now.
+   I took this code in to use after doing some fixing (it had some bugs).  
+   Also, OAEP is removed totally for now.  I'm not sure whether OAEP could
+   be used in the future with SILC but not for now.
 
    This file also implements partial SILC PKCS API for RSA with PKCS #1.
    It is partial because all the other functions but encrypt, decrypt,
    Hence, the encoding is always in PKCS #1 version 1.5 format.
 
    Any questions and comments regarding this modified version should be
-   sent to priikone@poseidon.pspt.fi.
+   sent to priikone@silcnet.org.
 
    References: ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc,
                ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1.asc,
               and RFC 2437.
 
-   Copyright notice: All code, including the SILC PKCS API code that is
-   not part of the Mozilla code, falls under the same license found attached
-   to this file, below.
+   Copyright notice: All code in this file, including the SILC PKCS API
+   code that is not part of the Mozilla code, falls under the same license
+   (MPL or GPL) found attached to this file, below.
 */
 
 /*
@@ -75,6 +77,8 @@
  */
 
 #include "silcincludes.h"
+#include "rsa_internal.h"
+#include "rsa.h"
 
 #define RSA_BLOCK_MIN_PAD_LEN          8
 #define RSA_BLOCK_FIRST_OCTET          0x00
@@ -101,8 +105,8 @@ typedef enum {
  * the rules defined in PKCS #1.
  */
 static unsigned char *
-RSA_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType,
-                  unsigned char *data, unsigned int data_len)
+RSA_FormatOneBlock(SilcUInt32 modulusLen, RSA_BlockType blockType,
+                  unsigned char *data, SilcUInt32 data_len)
 {
     unsigned char *block;
     unsigned char *bp;
@@ -150,7 +154,6 @@ RSA_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType,
        * Blocks intended for public-key operation.
        */
       case RSA_BlockPublic:
-
        /*
         * 0x00 || BT || Pad || 0x00 || ActualData
         *   1      1   padLen    1      data_len
@@ -161,17 +164,15 @@ RSA_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType,
        for (i = 0; i < padLen; i++) {
            /* Pad with non-zero random data. */
            do {
-               RNG_GenerateGlobalRandomBytes(bp + i, 1);
+             bp[i] = silc_rng_global_get_byte();
            } while (bp[i] == RSA_BLOCK_AFTER_PAD_OCTET);
        }
        bp += padLen;
        *bp++ = RSA_BLOCK_AFTER_PAD_OCTET;
        memcpy(bp, data, data_len);
-
        break;
 
       default:
-       assert(0);
        silc_free(block);
        return NULL;
     }
@@ -180,10 +181,10 @@ RSA_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType,
 }
 
 static int
-RSA_FormatBlock(unsigned char **result, unsigned int *result_len,
-               unsigned modulusLen,
+RSA_FormatBlock(unsigned char **result, SilcUInt32 *result_len,
+               SilcUInt32 modulusLen,
                RSA_BlockType blockType, unsigned char *data,
-               unsigned int data_len)
+               SilcUInt32 data_len)
 {
     /*
      * XXX For now assume that the data length fits in a single
@@ -210,7 +211,7 @@ RSA_FormatBlock(unsigned char **result, unsigned int *result_len,
         */
        assert(data_len <= (modulusLen - (3 + RSA_BLOCK_MIN_PAD_LEN)));
 
-       *result = RSA_FormatOneBlock(modulusLen, blockType, data);
+       *result = RSA_FormatOneBlock(modulusLen, blockType, data, data_len);
        if (result == NULL) {
            *result_len = 0;
            return FALSE;
@@ -237,24 +238,29 @@ RSA_FormatBlock(unsigned char **result, unsigned int *result_len,
  */
 unsigned char *
 RSA_DecodeOneBlock(unsigned char *data,
-                  unsigned int modulusLen,
-                  unsigned int expectedLen,
+                  SilcUInt32 modulusLen,
+                  SilcUInt32 expectedLen,
                   RSA_BlockType bt,
-                  unsigned int *pResultLen)
+                  SilcUInt32 *pResultLen)
 {
     RSA_BlockType blockType;
     unsigned char *dp, *res;
-    unsigned int i, len;
+    SilcUInt32 i, len = 0;
 
     dp = data;
-    if (*dp++ != RSA_BLOCK_FIRST_OCTET) {
+    if (dp[0] != RSA_BLOCK_FIRST_OCTET) {
        return NULL;
     }
 
-    blockType = (RSA_BlockType)*dp++;
+    blockType = (RSA_BlockType)dp[1];
     if (blockType != bt)
       return NULL;
 
+    if (modulusLen < 2 + 1)
+      return NULL;
+
+    dp += 2;
+
     switch (blockType) {
       case RSA_BlockPrivate0:
        /* Ignored */
@@ -267,10 +273,8 @@ RSA_DecodeOneBlock(unsigned char *data,
            if (*dp++ != RSA_BLOCK_PRIVATE_PAD_OCTET)
                break;
        }
-       if ((i == modulusLen) || (*dp != RSA_BLOCK_AFTER_PAD_OCTET)) {
+       if (i == modulusLen)
            return NULL;
-       }
-       dp++;
        len = modulusLen - (dp - data);
        res = (unsigned char *) silc_malloc(len);
        if (res == NULL) {
@@ -284,10 +288,8 @@ RSA_DecodeOneBlock(unsigned char *data,
            if (*dp++ == RSA_BLOCK_AFTER_PAD_OCTET)
                break;
        }
-       if (i == modulusLen) {
+       if (i == modulusLen)
            return NULL;
-       }
-       dp++;
        len = modulusLen - (dp - data);
        res = (unsigned char *) silc_malloc(len);
        if (res == NULL) {
@@ -315,19 +317,18 @@ RSA_DecodeOneBlock(unsigned char *data,
 SILC_PKCS_API_ENCRYPT(pkcs1)
 {
   RsaKey *key = (RsaKey *)context;
-  int i, ret = TRUE;
-  SilcInt mp_tmp;
-  SilcInt mp_dst;
+  SilcMPInt mp_tmp;
+  SilcMPInt mp_dst;
   unsigned char *padded;
-  unsigned int padded_len;
+  SilcUInt32 padded_len, len = (key->bits + 7) / 8;
 
   /* Pad data */
-  if (!RSA_FormatBlock(&padded, &padded_len, key->bits / 8,
+  if (!RSA_FormatBlock(&padded, &padded_len, len,
                       RSA_BlockPublic, src, src_len))
     return FALSE;
 
-  silc_mp_init_set_ui(&mp_tmp, 0);
-  silc_mp_init_set_ui(&mp_dst, 0);
+  silc_mp_init(&mp_tmp);
+  silc_mp_init(&mp_dst);
 
   /* Data to MP */
   silc_mp_bin2mp(padded, padded_len, &mp_tmp);
@@ -336,28 +337,27 @@ SILC_PKCS_API_ENCRYPT(pkcs1)
   rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->e, &key->n);
   
   /* MP to data */
-  if (!silc_mp_mp2bin_noalloc(&mp_dst, dst, key->bits / 8, dst_len))
-    ret = FALSE;
+  silc_mp_mp2bin_noalloc(&mp_dst, dst, len);
+  *dst_len = len;
 
   memset(padded, 0, padded_len);
   silc_free(padded);
-  silc_mp_clear(&mp_tmp);
-  silc_mp_clear(&mp_dst);
+  silc_mp_uninit(&mp_tmp);
+  silc_mp_uninit(&mp_dst);
 
-  return ret;
+  return TRUE;
 }
 
 SILC_PKCS_API_DECRYPT(pkcs1)
 {
   RsaKey *key = (RsaKey *)context;
-  int i, tmplen;
-  SilcInt mp_tmp;
-  SilcInt mp_dst;
+  SilcMPInt mp_tmp;
+  SilcMPInt mp_dst;
   unsigned char *padded, *unpadded;
-  unsigned int padded_len;
+  SilcUInt32 padded_len;
 
-  silc_mp_init_set_ui(&mp_tmp, 0);
-  silc_mp_init_set_ui(&mp_dst, 0);
+  silc_mp_init(&mp_tmp);
+  silc_mp_init(&mp_dst);
 
   /* Data to MP */
   silc_mp_bin2mp(src, src_len, &mp_tmp);
@@ -366,7 +366,7 @@ SILC_PKCS_API_DECRYPT(pkcs1)
   rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
 
   /* MP to data */
-  padded = silc_mp_mp2bin(&mp_dst, &padded_len);
+  padded = silc_mp_mp2bin(&mp_dst, (key->bits + 7) / 8, &padded_len);
 
   /* Unpad data */
   unpadded = RSA_DecodeOneBlock(padded, padded_len, 0, 
@@ -374,8 +374,8 @@ SILC_PKCS_API_DECRYPT(pkcs1)
   if (!unpadded) {
     memset(padded, 0, padded_len);
     silc_free(padded);
-    silc_mp_clear(&mp_tmp);
-    silc_mp_clear(&mp_dst);
+    silc_mp_uninit(&mp_tmp);
+    silc_mp_uninit(&mp_dst);
     return FALSE;
   }
 
@@ -387,8 +387,8 @@ SILC_PKCS_API_DECRYPT(pkcs1)
   memset(unpadded, 0, padded_len);
   silc_free(padded);
   silc_free(unpadded);
-  silc_mp_clear(&mp_tmp);
-  silc_mp_clear(&mp_dst);
+  silc_mp_uninit(&mp_tmp);
+  silc_mp_uninit(&mp_dst);
 
   return TRUE;
 }
@@ -396,49 +396,49 @@ SILC_PKCS_API_DECRYPT(pkcs1)
 SILC_PKCS_API_SIGN(pkcs1)
 {
   RsaKey *key = (RsaKey *)context;
-  int i, ret = TRUE;
-  SilcInt mp_tmp;
-  SilcInt mp_dst;
+  SilcMPInt mp_tmp;
+  SilcMPInt mp_dst;
   unsigned char *padded;
-  unsigned int padded_len;
+  SilcUInt32 padded_len;
+  SilcUInt32 len = (key->bits + 7) / 8;
 
   /* Pad data */
-  if (!RSA_FormatBlock(&padded, &padded_len, key->bits / 8,
-                      RSA_BlockPrivate, src, src_len))
+  if (!RSA_FormatBlock(&padded, &padded_len, len, RSA_BlockPrivate, 
+                      src, src_len))
     return FALSE;
 
-  silc_mp_init_set_ui(&mp_tmp, 0);
-  silc_mp_init_set_ui(&mp_dst, 0);
+  silc_mp_init(&mp_tmp);
+  silc_mp_init(&mp_dst);
 
   /* Data to MP */
-  silc_mp_bin2mp(padded, padded_len, &mp_tmp);
+  silc_mp_bin2mp(padded, len, &mp_tmp);
 
   /* Sign */
   rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
   
   /* MP to data */
-  if (!silc_mp_mp2bin_noalloc(&mp_dst, dst, key->bits / 8, dst_len))
-    ret = FALSE;
+  silc_mp_mp2bin_noalloc(&mp_dst, dst, len);
+  *dst_len = len;
 
   memset(padded, 0, padded_len);
   silc_free(padded);
-  silc_mp_clear(&mp_tmp);
-  silc_mp_clear(&mp_dst);
+  silc_mp_uninit(&mp_tmp);
+  silc_mp_uninit(&mp_dst);
 
-  return ret;
+  return TRUE;
 }
 
 SILC_PKCS_API_VERIFY(pkcs1)
 {
   RsaKey *key = (RsaKey *)context;
-  int i, ret = TRUE;
-  SilcInt mp_tmp, mp_tmp2;
-  SilcInt mp_dst;
-  unsigned char *verify, unpadded;
-  unsigned int verify_len;
+  int ret = TRUE;
+  SilcMPInt mp_tmp2;
+  SilcMPInt mp_dst;
+  unsigned char *verify, *unpadded;
+  SilcUInt32 verify_len, len = (key->bits + 7) / 8;
 
-  silc_mp_init_set_ui(&mp_tmp2, 0);
-  silc_mp_init_set_ui(&mp_dst, 0);
+  silc_mp_init(&mp_tmp2);
+  silc_mp_init(&mp_dst);
 
   /* Format the signature into MP int */
   silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
@@ -447,16 +447,16 @@ SILC_PKCS_API_VERIFY(pkcs1)
   rsa_en_de_crypt(&mp_dst, &mp_tmp2, &key->e, &key->n);
 
   /* MP to data */
-  verify = silc_mp_mp2bin(&mp_dst, &verify_len);
+  verify = silc_mp_mp2bin(&mp_dst, len, &verify_len);
 
   /* Unpad data */
-  unpadded = RSA_DecodeOneBlock(verify, verify_len, 0, 
+  unpadded = RSA_DecodeOneBlock(verify, len, 0, 
                                RSA_BlockPrivate, &verify_len);
   if (!unpadded) {
     memset(verify, 0, verify_len);
     silc_free(verify);
-    silc_mp_clear(&mp_tmp2);
-    silc_mp_clear(&mp_dst);
+    silc_mp_uninit(&mp_tmp2);
+    silc_mp_uninit(&mp_dst);
     return FALSE;
   }
 
@@ -468,8 +468,8 @@ SILC_PKCS_API_VERIFY(pkcs1)
   memset(unpadded, 0, verify_len);
   silc_free(verify);
   silc_free(unpadded);
-  silc_mp_clear(&mp_tmp2);
-  silc_mp_clear(&mp_dst);
+  silc_mp_uninit(&mp_tmp2);
+  silc_mp_uninit(&mp_dst);
 
   return ret;
 }