+/* $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.
*/
/*
*/
#include "silcincludes.h"
+#include "rsa_internal.h"
+#include "rsa.h"
#define RSA_BLOCK_MIN_PAD_LEN 8
#define RSA_BLOCK_FIRST_OCTET 0x00
* 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;
* Blocks intended for public-key operation.
*/
case RSA_BlockPublic:
-
/*
* 0x00 || BT || Pad || 0x00 || ActualData
* 1 1 padLen 1 data_len
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;
}
}
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
*/
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;
*/
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;
+ dp += 2;
+
switch (blockType) {
case RSA_BlockPrivate0:
/* Ignored */
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) {
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) {
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);
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);
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,
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;
}
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;
}
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);
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;
}
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;
}