From: Pekka Riikonen Date: Tue, 20 Feb 2001 15:49:36 +0000 (+0000) Subject: updates. X-Git-Tag: SILC.0.1~201 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=04f41c4481381e8e7c1e685a4edb6be6ec5d2c66 updates. --- diff --git a/CHANGES b/CHANGES index 9edaaa5a..faaa44cb 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,19 @@ +Tue Feb 20 14:14:14 EET 2001 Pekka Riikonen + + * The RSA key length is now save to the RsaKey context in the + key generation process in lib/silccrypt/rsa.c. The key length + is now used to figure out the maximum size of the block allowed + to be encrypted/signed. + + * Added silc_mp_mp2bin_noalloc into lib/silcmath/mpbin.[ch]. It + is equivalent to the silc_mp_mp2bin but does not allocate any + memory. + + * Changed silc_mp_mp2bin API to take length argument. If it is + non-zero then the buffer is allocated that large. If zero, then + the size is approximated using silc_mp_sizeinbase, which however + is not relieable. + Mon Feb 19 19:59:28 EET 2001 Pekka Riikonen * The client entry's userinfo pointer must be always valid. diff --git a/apps/silc/clientutil.c b/apps/silc/clientutil.c index 210f50b0..22e84bdc 100644 --- a/apps/silc/clientutil.c +++ b/apps/silc/clientutil.c @@ -435,7 +435,7 @@ New pair of keys will be created. Please, answer to following questions.\n\ rng = silc_rng_alloc(); silc_rng_init(rng); - silc_math_primegen_init(); + silc_rng_global_init(rng); if (!public_key) { memset(line, 0, sizeof(line)); @@ -490,7 +490,6 @@ New pair of keys will be created. Please, answer to following questions.\n\ memset(key, 0, sizeof(key_len)); silc_free(key); - silc_math_primegen_uninit(); silc_rng_free(rng); silc_pkcs_free(pkcs); diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 0d351bc0..a41add7d 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -96,7 +96,6 @@ void silc_server_free(SilcServer server) if (server->pending_commands) silc_dlist_uninit(server->pending_commands); - silc_math_primegen_uninit(); /* XXX */ silc_free(server); } } @@ -140,7 +139,7 @@ int silc_server_init(SilcServer server) /* Initialize random number generator for the server. */ server->rng = silc_rng_alloc(); silc_rng_init(server->rng); - silc_math_primegen_init(); /* XXX */ + silc_rng_global_init(server->rng); /* Initialize hash functions for server to use */ silc_hash_alloc("md5", &server->md5hash); @@ -701,7 +700,8 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second) if (ctx->dest_id) silc_free(ctx->dest_id); silc_free(ctx); - sock->protocol = NULL; + if (sock) + sock->protocol = NULL; silc_server_disconnect_remote(server, sock, "Server closed connection: " "Key exchange failed"); return; diff --git a/apps/silcd/testi2.conf b/apps/silcd/testi2.conf index 35f54730..fe6247a1 100644 --- a/apps/silcd/testi2.conf +++ b/apps/silcd/testi2.conf @@ -19,10 +19,10 @@ nobody:nobody Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi [ServerInfo] -lassi.kuo.fi.ssh.com:212.146.8.245:Kuopio, Finland:1334 +lassi.kuo.fi.ssh.com:10.2.1.7:Kuopio, Finland:1334 [ListenPort] -212.146.8.245:212.146.8.245:1334 +10.2.1.7:10.2.1.7:1334 [Logging] infologfile:silcd2.log:10000 @@ -43,10 +43,10 @@ errorlogfile:silcd2.log:10000 [AdminConnection] [ServerConnection] -212.146.8.245:passwd:priikone:1333:1:1 +10.2.1.7:passwd:priikone:1333:1:1 [RouterConnection] -212.146.8.245:passwd:priikone:1335:1:1:0 +10.2.1.7:passwd:priikone:1335:1:1:0 [DenyConnection] [RedirectClient] diff --git a/lib/silccrypt/Makefile.am b/lib/silccrypt/Makefile.am index a1441d19..66a9fbe0 100644 --- a/lib/silccrypt/Makefile.am +++ b/lib/silccrypt/Makefile.am @@ -35,7 +35,8 @@ libsilccrypt_a_SOURCES = \ silchash.c \ silchmac.c \ silcrng.c \ - silcpkcs.c + silcpkcs.c \ + pkcs1.c EXTRA_DIST = *.h diff --git a/lib/silccrypt/pkcs1.c b/lib/silccrypt/pkcs1.c index c3136f58..2ba6f3ef 100644 --- a/lib/silccrypt/pkcs1.c +++ b/lib/silccrypt/pkcs1.c @@ -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, @@ -32,8 +34,8 @@ 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. + not part of the Mozilla code, falls under the same license (MPL or GPL) + found attached to this file, below. */ /* @@ -75,6 +77,7 @@ */ #include "silcincludes.h" +#include "rsa.h" #define RSA_BLOCK_MIN_PAD_LEN 8 #define RSA_BLOCK_FIRST_OCTET 0x00 @@ -101,7 +104,7 @@ typedef enum { * the rules defined in PKCS #1. */ static unsigned char * -RSA_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType, +RSA_FormatOneBlock(unsigned int modulusLen, RSA_BlockType blockType, unsigned char *data, unsigned int data_len) { unsigned char *block; @@ -150,7 +153,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 +163,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); + silc_rng_global_get_byte(bp + i); } 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; } @@ -181,7 +181,7 @@ RSA_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType, static int RSA_FormatBlock(unsigned char **result, unsigned int *result_len, - unsigned modulusLen, + unsigned int modulusLen, RSA_BlockType blockType, unsigned char *data, unsigned int data_len) { @@ -210,7 +210,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; @@ -244,17 +244,19 @@ RSA_DecodeOneBlock(unsigned char *data, { RSA_BlockType blockType; unsigned char *dp, *res; - unsigned int i, len; + unsigned int 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 */ @@ -267,10 +269,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 +284,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,14 +313,13 @@ RSA_DecodeOneBlock(unsigned char *data, SILC_PKCS_API_ENCRYPT(pkcs1) { RsaKey *key = (RsaKey *)context; - int i, ret = TRUE; SilcInt mp_tmp; SilcInt mp_dst; unsigned char *padded; - unsigned int padded_len; + unsigned int padded_len, len = key->bits / 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; @@ -336,21 +333,20 @@ 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); - return ret; + return TRUE; } SILC_PKCS_API_DECRYPT(pkcs1) { RsaKey *key = (RsaKey *)context; - int i, tmplen; SilcInt mp_tmp; SilcInt mp_dst; unsigned char *padded, *unpadded; @@ -366,7 +362,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 / 8, &padded_len); /* Unpad data */ unpadded = RSA_DecodeOneBlock(padded, padded_len, 0, @@ -396,46 +392,46 @@ SILC_PKCS_API_DECRYPT(pkcs1) SILC_PKCS_API_SIGN(pkcs1) { RsaKey *key = (RsaKey *)context; - int i, ret = TRUE; SilcInt mp_tmp; SilcInt mp_dst; unsigned char *padded; unsigned int padded_len; + unsigned int len = key->bits / 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); /* 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); - return ret; + return TRUE; } SILC_PKCS_API_VERIFY(pkcs1) { RsaKey *key = (RsaKey *)context; - int i, ret = TRUE; - SilcInt mp_tmp, mp_tmp2; + int ret = TRUE; + SilcInt mp_tmp2; SilcInt mp_dst; - unsigned char *verify, unpadded; - unsigned int verify_len; + unsigned char *verify, *unpadded; + unsigned int verify_len, len = key->bits / 8; silc_mp_init_set_ui(&mp_tmp2, 0); silc_mp_init_set_ui(&mp_dst, 0); @@ -447,10 +443,10 @@ 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); diff --git a/lib/silccrypt/pkcs1.h b/lib/silccrypt/pkcs1.h index 7ed3e97d..38937aee 100644 --- a/lib/silccrypt/pkcs1.h +++ b/lib/silccrypt/pkcs1.h @@ -20,40 +20,6 @@ #ifndef PKCS1_H #define PKCS1_H -/* - 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. - - 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. - - This file also implements partial SILC PKCS API for RSA with PKCS #1. - It is partial because all the other functions but encrypt, decrypt, - sign and verify are common. - - Note: - - The mandatory PKCS #1 implementation in SILC must be compliant to either - PKCS #1 version 1.5 or PKCS #1 version 2 with the following notes: - The signature encoding is always in same format as the encryption - encoding regardles of the PKCS #1 version. The signature with - appendix (with hash algorithm OID in the data) must not be used - in the SILC. Rationale for this is that there is no binding between - the PKCS #1 OIDs and the hash algorithms used in the SILC protocol. - 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. - - References: ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc, - ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1.asc, - and RFC 2437. -*/ - /* * SILC PKCS API for PKCS #1 * diff --git a/lib/silccrypt/rsa.c b/lib/silccrypt/rsa.c index c65283e7..4fd1dc1b 100644 --- a/lib/silccrypt/rsa.c +++ b/lib/silccrypt/rsa.c @@ -54,6 +54,12 @@ try to find the smallest possible d by doing modinv(e, lcm(phi)) instead of modinv(e, phi). Note: this is not security fix but optimization. + o Tue Feb 20 13:58:58 EET 2001 Pekka + + Set key->bits in rsa_generate_key. It is the modulus length in bits. + The `tmplen' in encrypt, decrypt, sign and verify PKCS API functions + is now calculated by (key->bits + 7) / 8. It is the length of one block. + */ #include "silcincludes.h" @@ -125,8 +131,8 @@ SILC_PKCS_API_GET_PUBLIC_KEY(rsa) unsigned int e_len, n_len; unsigned char tmp[4]; - e = silc_mp_mp2bin(&key->e, &e_len); - n = silc_mp_mp2bin(&key->n, &n_len); + e = silc_mp_mp2bin(&key->e, 0, &e_len); + n = silc_mp_mp2bin(&key->n, key->bits / 8, &n_len); *ret_len = e_len + 4 + n_len + 4; ret = silc_calloc(*ret_len, sizeof(unsigned char)); @@ -164,9 +170,9 @@ SILC_PKCS_API_GET_PRIVATE_KEY(rsa) unsigned int e_len, n_len, d_len; unsigned char tmp[4]; - e = silc_mp_mp2bin(&key->e, &e_len); - n = silc_mp_mp2bin(&key->n, &n_len); - d = silc_mp_mp2bin(&key->d, &d_len); + e = silc_mp_mp2bin(&key->e, 0, &e_len); + n = silc_mp_mp2bin(&key->n, key->bits / 8, &n_len); + d = silc_mp_mp2bin(&key->d, 0, &d_len); *ret_len = e_len + 4 + n_len + 4 + d_len + 4; ret = silc_calloc(*ret_len, sizeof(unsigned char)); @@ -233,6 +239,8 @@ SILC_PKCS_API_SET_PUBLIC_KEY(rsa) silc_mp_bin2mp(key_data + 4 + e_len + 4, n_len, &key->n); + key->bits = n_len * 8; + return TRUE; } @@ -280,6 +288,8 @@ SILC_PKCS_API_SET_PRIVATE_KEY(rsa) silc_mp_bin2mp(key_data + 4 + e_len + 4 + n_len + 4, d_len, &key->d); + key->bits = n_len * 8; + return TRUE; } @@ -341,7 +351,7 @@ SILC_PKCS_API_ENCRYPT(rsa) /* Encrypt */ rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->e, &key->n); - tmplen = (1024 + 7) / 8; + tmplen = (key->bits + 7) / 8; /* Format the MP int back into data */ for (i = tmplen; i > 0; i--) { @@ -375,7 +385,7 @@ SILC_PKCS_API_DECRYPT(rsa) /* Decrypt */ rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n); - tmplen = (1024 + 7) / 8; + tmplen = (key->bits + 7) / 8; /* Format the MP int back into data */ for (i = tmplen; i > 0; i--) { @@ -409,7 +419,7 @@ SILC_PKCS_API_SIGN(rsa) /* Sign */ rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n); - tmplen = (1024 + 7) / 8; + tmplen = (key->bits + 7) / 8; /* Format the MP int back into data */ for (i = tmplen; i > 0; i--) { @@ -487,6 +497,9 @@ void rsa_generate_keys(RsaKey *key, unsigned int bits, silc_mp_init(&pm1); silc_mp_init(&qm1); + /* Set modulus length */ + key->bits = bits; + /* Set the primes */ silc_mp_set(&key->p, p); silc_mp_set(&key->q, q); diff --git a/lib/silccrypt/silcpkcs.c b/lib/silccrypt/silcpkcs.c index 74870ec8..c193fc87 100644 --- a/lib/silccrypt/silcpkcs.c +++ b/lib/silccrypt/silcpkcs.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2000 Pekka Riikonen + Copyright (C) 1997 - 2001 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,12 +22,25 @@ #include "silcincludes.h" #include "rsa.h" +#include "pkcs1.h" /* List of all PKCS's in SILC. PKCS's don't support SIM's thus only static declarations are possible. XXX: I hope this to change real soon. */ SilcPKCSObject silc_pkcs_list[] = { + /* RSA with PKCS #1 (Uses directly routines from Raw RSA operations) */ + /* + { "rsa", &silc_rsa_data_context, + silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key, + silc_rsa_get_private_key, silc_rsa_set_public_key, + silc_rsa_set_private_key, silc_rsa_context_len, + silc_rsa_data_context_len, silc_rsa_set_arg, + silc_pkcs1_encrypt, silc_pkcs1_decrypt, + silc_pkcs1_sign, silc_pkcs1_verify }, + */ + + /* Raw RSA operations */ { "rsa", &silc_rsa_data_context, silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key, silc_rsa_get_private_key, silc_rsa_set_public_key, diff --git a/lib/silccrypt/silcpkcs.h b/lib/silccrypt/silcpkcs.h index 8183b3ac..c726cfa8 100644 --- a/lib/silccrypt/silcpkcs.h +++ b/lib/silccrypt/silcpkcs.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2000 Pekka Riikonen + Copyright (C) 1997 - 2001 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/silccrypt/silcrng.c b/lib/silccrypt/silcrng.c index 9da70dd9..742cb59a 100644 --- a/lib/silccrypt/silcrng.c +++ b/lib/silccrypt/silcrng.c @@ -31,6 +31,16 @@ #undef SILC_RNG_DEBUG /* #define SILC_RNG_DEBUG */ +static unsigned int silc_rng_get_position(SilcRng rng); +static void silc_rng_stir_pool(SilcRng rng); +static void silc_rng_xor(SilcRng rng, unsigned int val, unsigned int pos); +static void silc_rng_add_noise(SilcRng rng, unsigned char *buffer, + unsigned int len); +static void silc_rng_exec_command(SilcRng rng, char *command); +static void silc_rng_get_hard_noise(SilcRng rng); +static void silc_rng_get_medium_noise(SilcRng rng); +static void silc_rng_get_soft_noise(SilcRng rng); + /* SILC SilcRng State context. @@ -167,7 +177,7 @@ void silc_rng_init(SilcRng rng) /* This function gets 'soft' noise from environment. */ -void silc_rng_get_soft_noise(SilcRng rng) +static void silc_rng_get_soft_noise(SilcRng rng) { struct tms ptime; @@ -203,7 +213,7 @@ void silc_rng_get_soft_noise(SilcRng rng) /* This function gets noise from different commands */ -void silc_rng_get_medium_noise(SilcRng rng) +static void silc_rng_get_medium_noise(SilcRng rng) { silc_rng_exec_command(rng, "ps -lefaww 2> /dev/null"); silc_rng_exec_command(rng, "ls -afiln 2> /dev/null"); @@ -218,7 +228,7 @@ void silc_rng_get_medium_noise(SilcRng rng) /* This function gets 'hard' noise from environment. This tries to get the noise from /dev/random if available. */ -void silc_rng_get_hard_noise(SilcRng rng) +static void silc_rng_get_hard_noise(SilcRng rng) { char buf[32]; int fd, len, i; @@ -244,7 +254,7 @@ void silc_rng_get_hard_noise(SilcRng rng) /* Execs command and gets noise from its output */ -void silc_rng_exec_command(SilcRng rng, char *command) +static void silc_rng_exec_command(SilcRng rng, char *command) { char buf[2048]; FILE *fd; @@ -277,8 +287,8 @@ void silc_rng_exec_command(SilcRng rng, char *command) /* This function adds the contents of the buffer as noise into random pool. After adding the noise the pool is stirred. */ -void silc_rng_add_noise(SilcRng rng, unsigned char *buffer, - unsigned int len) +static void silc_rng_add_noise(SilcRng rng, unsigned char *buffer, + unsigned int len) { unsigned int i, pos; @@ -297,7 +307,7 @@ void silc_rng_add_noise(SilcRng rng, unsigned char *buffer, /* XOR's data into the pool */ -void silc_rng_xor(SilcRng rng, unsigned int val, unsigned int pos) +static void silc_rng_xor(SilcRng rng, unsigned int val, unsigned int pos) { assert(rng != NULL); rng->pool[pos] ^= val + val; @@ -306,7 +316,7 @@ void silc_rng_xor(SilcRng rng, unsigned int val, unsigned int pos) /* This function stirs the random pool by encrypting buffer in CFB (cipher feedback) mode with SHA1 algorithm. */ -void silc_rng_stir_pool(SilcRng rng) +static void silc_rng_stir_pool(SilcRng rng) { int i; unsigned long iv[5]; @@ -343,7 +353,7 @@ void silc_rng_stir_pool(SilcRng rng) /* Returns next position where data is fetched from the pool or put to the pool. */ -unsigned int silc_rng_get_position(SilcRng rng) +static unsigned int silc_rng_get_position(SilcRng rng) { SilcRngState next; unsigned int pos; @@ -430,3 +440,62 @@ unsigned char *silc_rng_get_rn_data(SilcRng rng, unsigned int len) return data; } + +/* Global RNG. This is global RNG that application can initialize so + that any part of code anywhere can use RNG without having to allocate + new RNG object everytime. If this is not initialized then these routines + will fail. Note: currently in SILC applications always initialize this. */ + +SilcRng global_rng = NULL; + +/* Initialize global RNG. If `rng' is provided it is set as the global + RNG object (it can be allocated by the application for example). */ + +int silc_rng_global_init(SilcRng rng) +{ + if (rng) + global_rng = rng; + else + global_rng = silc_rng_alloc(); + + return TRUE; +} + +/* Uninitialize global RNG */ + +int silc_rng_global_uninit() +{ + if (global_rng) { + silc_rng_free(global_rng); + global_rng = NULL; + } + + return TRUE; +} + +/* These are analogous to the functions above. */ + +unsigned char silc_rng_global_get_byte() +{ + return global_rng ? silc_rng_get_byte(global_rng) : 0; +} + +unsigned short silc_rng_global_get_rn16() +{ + return global_rng ? silc_rng_get_rn16(global_rng) : 0; +} + +unsigned int silc_rng_global_get_rn32() +{ + return global_rng ? silc_rng_get_rn32(global_rng) : 0; +} + +unsigned char *silc_rng_global_get_rn_string(unsigned int len) +{ + return global_rng ? silc_rng_get_rn_string(global_rng, len) : NULL; +} + +unsigned char *silc_rng_global_get_rn_data(unsigned int len) +{ + return global_rng ? silc_rng_get_rn_data(global_rng, len) : NULL; +} diff --git a/lib/silccrypt/silcrng.h b/lib/silccrypt/silcrng.h index 7dfc2d78..40084bc1 100644 --- a/lib/silccrypt/silcrng.h +++ b/lib/silccrypt/silcrng.h @@ -34,19 +34,18 @@ typedef struct SilcRngObjectStruct *SilcRng; SilcRng silc_rng_alloc(); void silc_rng_free(SilcRng rng); void silc_rng_init(SilcRng rng); -void silc_rng_get_soft_noise(SilcRng rng); -void silc_rng_get_medium_noise(SilcRng rng); -void silc_rng_get_hard_noise(SilcRng rng); -void silc_rng_exec_command(SilcRng rng, char *command); -void silc_rng_add_noise(SilcRng rng, unsigned char *buffer, - unsigned int len); -void silc_rng_xor(SilcRng rng, unsigned int val, unsigned int pos); -void silc_rng_stir_pool(SilcRng rng); -unsigned int silc_rng_get_position(SilcRng rng); unsigned char silc_rng_get_byte(SilcRng rng); unsigned short silc_rng_get_rn16(SilcRng rng); unsigned int silc_rng_get_rn32(SilcRng rng); unsigned char *silc_rng_get_rn_string(SilcRng rng, unsigned int len); unsigned char *silc_rng_get_rn_data(SilcRng rng, unsigned int len); +int silc_rng_global_init(SilcRng rng); +int silc_rng_global_uninit(); +unsigned char silc_rng_global_get_byte(); +unsigned short silc_rng_global_get_rn16(); +unsigned int silc_rng_global_get_rn32(); +unsigned char *silc_rng_global_get_rn_string(unsigned int len); +unsigned char *silc_rng_global_get_rn_data(unsigned int len); + #endif diff --git a/lib/silcmath/mpbin.c b/lib/silcmath/mpbin.c index 6e0e6ead..8b598aa1 100644 --- a/lib/silcmath/mpbin.c +++ b/lib/silcmath/mpbin.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2000 Pekka Riikonen + Copyright (C) 2000 - 2001 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,18 +22,20 @@ #include "silcincludes.h" /* Encodes MP integer into binary data. Returns allocated data that - must be free'd by the caller. */ + must be free'd by the caller. If `len' is provided the destination + buffer is allocated that large. If zero then the size is approximated. */ -unsigned char *silc_mp_mp2bin(SilcInt *val, unsigned int *ret_len) +unsigned char *silc_mp_mp2bin(SilcInt *val, unsigned int len, + unsigned int *ret_len) { int i; unsigned int size; unsigned char *ret; SilcInt tmp; - size = (silc_mp_sizeinbase(val, 2) + 7) / 8; + size = (len ? len : ((silc_mp_sizeinbase(val, 2) + 7) / 8)); ret = silc_calloc(size, sizeof(*ret)); - + silc_mp_init_set(&tmp, val); for (i = size; i > 0; i--) { @@ -49,6 +51,27 @@ unsigned char *silc_mp_mp2bin(SilcInt *val, unsigned int *ret_len) return ret; } +/* Samve as above but does not allocate any memory. The encoded data is + returned into `dst' and it's length to the `ret_len'. If `dst_len is + non-zero then the destination buffer is assumbed to be that large. */ + +void silc_mp_mp2bin_noalloc(SilcInt *val, unsigned char *dst, + unsigned int dst_len) +{ + int i; + unsigned int size = dst_len; + SilcInt tmp; + + silc_mp_init_set(&tmp, val); + + for (i = size; i > 0; i--) { + dst[i - 1] = (unsigned char)(silc_mp_get_ui(&tmp) & 0xff); + silc_mp_fdiv_q_2exp(&tmp, &tmp, 8); + } + + silc_mp_clear(&tmp); +} + /* Decodes binary data into MP integer. The integer sent as argument must be initialized. */ diff --git a/lib/silcmath/mpbin.h b/lib/silcmath/mpbin.h index 41ebf12b..f32f19a3 100644 --- a/lib/silcmath/mpbin.h +++ b/lib/silcmath/mpbin.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2000 Pekka Riikonen + Copyright (C) 2000 - 2001 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,7 +21,10 @@ #ifndef MPBIN_H #define MPBIN_H -unsigned char *silc_mp_mp2bin(SilcInt *val, unsigned int *ret_len); +unsigned char *silc_mp_mp2bin(SilcInt *val, unsigned int len, + unsigned int *ret_len); +void silc_mp_mp2bin_noalloc(SilcInt *val, unsigned char *dst, + unsigned int dst_len); void silc_mp_bin2mp(unsigned char *data, unsigned int len, SilcInt *ret); #endif diff --git a/lib/silcmath/silcprimegen.c b/lib/silcmath/silcprimegen.c index b86a6aad..decb9538 100644 --- a/lib/silcmath/silcprimegen.c +++ b/lib/silcmath/silcprimegen.c @@ -22,12 +22,6 @@ #include "silcincludes.h" -/* XXX This must be temporary solution!! yucky! */ -/* Global random pool used for all prime generation. All primes generated - in SILC uses this same pool. Before primes can be generated one must - call silc_math_primegen_init. */ -static SilcRng primegen_rng; - /* Fixed primetable for small prime division. We use this primetable to test if possible prime is divisible any of these. Primetable is NULL @@ -208,9 +202,6 @@ int silc_math_gen_prime(SilcInt *prime, unsigned int bits, int verbose) unsigned int *spmods; SilcInt r, base, tmp, tmp2, oprime; - /* XXX */ - assert(primegen_rng != NULL); - silc_mp_init(&r); silc_mp_init_set_ui(&base, 2); silc_mp_init(&tmp); @@ -220,7 +211,7 @@ int silc_math_gen_prime(SilcInt *prime, unsigned int bits, int verbose) SILC_LOG_DEBUG(("Generating new prime")); /* Get random number */ - numbuf = silc_rng_get_rn_string(primegen_rng, (bits / 8)); + numbuf = silc_rng_global_get_rn_string((bits / 8)); if (!numbuf) return FALSE; @@ -348,24 +339,3 @@ int silc_math_prime_test(SilcInt *p) /* Number is probably a prime */ return TRUE; } - -/* XXX This must temporary solution!! */ -/* Initializes the random pool used to generated primes */ - -void silc_math_primegen_init() -{ - SILC_LOG_DEBUG(("Start")); - - if (primegen_rng == NULL) { - primegen_rng = silc_rng_alloc(); - silc_rng_init(primegen_rng); - } -} - -/* XXX This must temporary solution!! */ -/* Uninitializes random pool */ - -void silc_math_primegen_uninit() -{ - silc_rng_free(primegen_rng); -} diff --git a/lib/silcske/payload.c b/lib/silcske/payload.c index c491f29e..d0526135 100644 --- a/lib/silcske/payload.c +++ b/lib/silcske/payload.c @@ -282,7 +282,7 @@ SilcSKEStatus silc_ske_payload_one_encode(SilcSKE ske, return SILC_SKE_STATUS_ERROR; /* Encode the integer into binary data */ - e_str = silc_mp_mp2bin(&payload->e, &e_len); + e_str = silc_mp_mp2bin(&payload->e, 0, &e_len); if (!e_str) return SILC_SKE_STATUS_ERROR; @@ -421,7 +421,7 @@ SilcSKEStatus silc_ske_payload_two_encode(SilcSKE ske, return SILC_SKE_STATUS_ERROR; /* Encode the integer into HEX string */ - f_str = silc_mp_mp2bin(&payload->f, &f_len); + f_str = silc_mp_mp2bin(&payload->f, 0, &f_len); /* Allocate channel payload buffer. The length of the buffer is 2 + 2 + public key + 2 + f + 2 + signature. */ diff --git a/lib/silcske/silcske.c b/lib/silcske/silcske.c index bc84849f..c8de900e 100644 --- a/lib/silcske/silcske.c +++ b/lib/silcske/silcske.c @@ -1161,9 +1161,9 @@ SilcSKEStatus silc_ske_make_hash(SilcSKE ske, SILC_LOG_DEBUG(("Start")); - e = silc_mp_mp2bin(&ske->ke1_payload->e, &e_len); - f = silc_mp_mp2bin(&ske->ke2_payload->f, &f_len); - KEY = silc_mp_mp2bin(ske->KEY, &KEY_len); + e = silc_mp_mp2bin(&ske->ke1_payload->e, 0, &e_len); + f = silc_mp_mp2bin(&ske->ke2_payload->f, 0, &f_len); + KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len); buf = silc_buffer_alloc(ske->start_payload_copy->len + ske->pk_len + e_len + f_len + KEY_len); @@ -1226,7 +1226,7 @@ SilcSKEStatus silc_ske_process_key_material(SilcSKE ske, SILC_LOG_DEBUG(("Start")); /* Encode KEY to binary data */ - tmpbuf = silc_mp_mp2bin(ske->KEY, &klen); + tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen); buf = silc_buffer_alloc(1 + klen + hash_len); silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));