from SILC distributions.
-Sun Nov 9 20:44:56 EET 200 Pekka Riikonen <priikone@silcnet.org>
+Mon Nov 10 13:03:46 EET 2003 Pekka Riikonen <priikone@silcnet.org>
+
+ * Rewrote the PKCS#1 routines. Added lib/silccrypt/silcpkcs1.[ch].
+
+ * The SILC RNG is now gauranteed to return non-zero random
+ values. Affected files are lib/silccrypt/silcrng.[ch].
+
+Sun Nov 9 20:44:56 EET 2003 Pekka Riikonen <priikone@silcnet.org>
* Fixed nickname formatting when changing only case of the
nickname. Affected file lib/silcclient/idlist.c.
#include "silchmac.h"
#include "silcrng.h"
#include "silcpkcs.h"
+#include "silcpkcs1.h"
/* More SILC util library includes */
#include "silcmutex.h"
@LINK=silcrng.html:SILC RNG Interface
@LINK=silccipher.html:SILC Cipher API
@LINK=silcpkcs.html:SILC PKCS API
+@LINK=silcpkcs1.html:SILC PKCS#1 API
@LINK=silchash.html:SILC Hash Interface
@LINK=silchmac.html:SILC HMAC Interface
-->
<br /><br />
@LINKS@
-
#
# Makefile.am
#
-# Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+# Author: Pekka Riikonen <priikone@silcnet.org>
#
-# Copyright (C) 2000 Pekka Riikonen
+# Copyright (C) 2000 2003 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
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
+# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
silchmac.c \
silcrng.c \
silcpkcs.c \
- pkcs1.c
+ silcpkcs1.c
if SILC_LIBTOOLFIX
# Tell libtool to compile silccrypt as shared since silcsim will need it.
LTFLAGS = --libtool-enable-shared
else
-LTFLAGS =
+LTFLAGS =
endif
CFLAGS = $(LTFLAGS)
ciphers.h \
md5.h \
none.h \
- pkcs1.h \
rc5.h \
rsa.h \
sha1.h \
silchmac.h \
silcpkcs.h \
silcrng.h \
+ silcpkcs1.h \
twofish.h
endif
+++ /dev/null
-/* $Id$ */
-/*
- PKCS #1 RSA wrapper.
-
- 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 (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,
- 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@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 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.
-*/
-
-/*
- * PKCS#1 encoding and decoding functions.
- * This file is believed to contain no code licensed from other parties.
- *
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1994-2000 Netscape Communications Corporation. All
- * Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- *
- * $Id$
- */
-
-#include "silcincludes.h"
-#include "rsa_internal.h"
-#include "rsa.h"
-
-#define RSA_BLOCK_MIN_PAD_LEN 8
-#define RSA_BLOCK_FIRST_OCTET 0x00
-#define RSA_BLOCK_PRIVATE0_PAD_OCTET 0x00
-#define RSA_BLOCK_PRIVATE_PAD_OCTET 0xff
-#define RSA_BLOCK_AFTER_PAD_OCTET 0x00
-
-/*
- * RSA block types
- *
- * The actual values are important -- they are fixed, *not* arbitrary.
- * The explicit value assignments are not needed (because C would give
- * us those same values anyway) but are included as a reminder...
- */
-typedef enum {
- RSA_BlockPrivate0 = 0, /* unused, really */
- RSA_BlockPrivate = 1, /* pad for a private-key operation */
- RSA_BlockPublic = 2, /* pad for a public-key operation */
- RSA_BlockTotal
-} RSA_BlockType;
-
-/*
- * Format one block of data for public/private key encryption using
- * the rules defined in PKCS #1.
- */
-static unsigned char *
-RSA_FormatOneBlock(SilcUInt32 modulusLen, RSA_BlockType blockType,
- unsigned char *data, SilcUInt32 data_len)
-{
- unsigned char *block;
- unsigned char *bp;
- int padLen;
- int i;
-
- block = (unsigned char *) silc_malloc(modulusLen);
- if (block == NULL)
- return NULL;
-
- bp = block;
-
- /*
- * All RSA blocks start with two octets:
- * 0x00 || BlockType
- */
- *bp++ = RSA_BLOCK_FIRST_OCTET;
- *bp++ = (unsigned char) blockType;
-
- switch (blockType) {
-
- /*
- * Blocks intended for private-key operation.
- */
- case RSA_BlockPrivate0: /* essentially unused */
- case RSA_BlockPrivate: /* preferred method */
- /*
- * 0x00 || BT || Pad || 0x00 || ActualData
- * 1 1 padLen 1 data_len
- * Pad is either all 0x00 or all 0xff bytes, depending on blockType.
- */
- padLen = modulusLen - data_len - 3;
- assert(padLen >= RSA_BLOCK_MIN_PAD_LEN);
- memset(bp,
- blockType == RSA_BlockPrivate0
- ? RSA_BLOCK_PRIVATE0_PAD_OCTET
- : RSA_BLOCK_PRIVATE_PAD_OCTET,
- padLen);
- bp += padLen;
- *bp++ = RSA_BLOCK_AFTER_PAD_OCTET;
- memcpy(bp, data, data_len);
- break;
-
- /*
- * Blocks intended for public-key operation.
- */
- case RSA_BlockPublic:
- /*
- * 0x00 || BT || Pad || 0x00 || ActualData
- * 1 1 padLen 1 data_len
- * Pad is all non-zero random bytes.
- */
- padLen = modulusLen - data_len - 3;
- assert(padLen >= RSA_BLOCK_MIN_PAD_LEN);
- for (i = 0; i < padLen; i++) {
- /* Pad with non-zero random data. */
- do {
- 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:
- silc_free(block);
- return NULL;
- }
-
- return block;
-}
-
-static int
-RSA_FormatBlock(unsigned char **result, SilcUInt32 *result_len,
- SilcUInt32 modulusLen,
- RSA_BlockType blockType, unsigned char *data,
- SilcUInt32 data_len)
-{
- /*
- * XXX For now assume that the data length fits in a single
- * XXX encryption block; the ASSERTs below force this.
- * XXX To fix it, each case will have to loop over chunks whose
- * XXX lengths satisfy the assertions, until all data is handled.
- * XXX (Unless RSA has more to say about how to handle data
- * XXX which does not fit in a single encryption block?)
- * XXX And I do not know what the result is supposed to be,
- * XXX so the interface to this function may need to change
- * XXX to allow for returning multiple blocks, if they are
- * XXX not wanted simply concatenated one after the other.
- */
-
- switch (blockType) {
- case RSA_BlockPrivate0:
- case RSA_BlockPrivate:
- case RSA_BlockPublic:
- /*
- * 0x00 || BT || Pad || 0x00 || ActualData
- *
- * The "3" below is the first octet + the second octet + the 0x00
- * octet that always comes just before the ActualData.
- */
- assert(data_len <= (modulusLen - (3 + RSA_BLOCK_MIN_PAD_LEN)));
-
- *result = RSA_FormatOneBlock(modulusLen, blockType, data, data_len);
- if (result == NULL) {
- *result_len = 0;
- return FALSE;
- }
- *result_len = modulusLen;
-
- break;
-
- default:
- *result = NULL;
- *result_len = 0;
- return FALSE;
- }
-
- return TRUE;
-}
-
-/*
- * Takes a formatted block and returns the data part.
- * (This is the inverse of RSA_FormatOneBlock().)
- * In some formats the start of the data is ambiguous;
- * if it is non-zero, expectedLen will disambiguate.
- *
- */
-unsigned char *
-RSA_DecodeOneBlock(unsigned char *data,
- SilcUInt32 modulusLen,
- SilcUInt32 expectedLen,
- RSA_BlockType bt,
- SilcUInt32 *pResultLen)
-{
- RSA_BlockType blockType;
- unsigned char *dp, *res;
- SilcUInt32 i, len = 0;
-
- dp = data;
- if (dp[0] != RSA_BLOCK_FIRST_OCTET) {
- return NULL;
- }
-
- blockType = (RSA_BlockType)dp[1];
- if (blockType != bt)
- return NULL;
-
- if (modulusLen < 2 + 1)
- return NULL;
-
- dp += 2;
-
- switch (blockType) {
- case RSA_BlockPrivate0:
- /* Ignored */
- res = (unsigned char *) silc_malloc(modulusLen);
- memcpy(res, data, modulusLen);
- break;
-
- case RSA_BlockPrivate:
- for (i = 0; i < modulusLen; i++) {
- if (*dp++ != RSA_BLOCK_PRIVATE_PAD_OCTET)
- break;
- }
- if (i == modulusLen)
- return NULL;
- len = modulusLen - (dp - data);
- res = (unsigned char *) silc_malloc(len);
- if (res == NULL) {
- return NULL;
- }
- memcpy(res, dp, len);
- break;
-
- case RSA_BlockPublic:
- for (i = 0; i < modulusLen; i++) {
- if (*dp++ == RSA_BLOCK_AFTER_PAD_OCTET)
- break;
- }
- if (i == modulusLen)
- return NULL;
- len = modulusLen - (dp - data);
- res = (unsigned char *) silc_malloc(len);
- if (res == NULL) {
- return NULL;
- }
- memcpy(res, dp, len);
- break;
-
- default:
- return NULL;
- }
-
- if (pResultLen)
- *pResultLen = len;
- return res;
-}
-
-/*
- * SILC PKCS API for PKCS #1
- *
- * Note all the other PKCS API functions are used from the rsa.c.
- * See the definitions in rsa.c and in silcpkcs.c.
- */
-
-SILC_PKCS_API_ENCRYPT(pkcs1)
-{
- RsaKey *key = (RsaKey *)context;
- SilcMPInt mp_tmp;
- SilcMPInt mp_dst;
- unsigned char *padded;
- SilcUInt32 padded_len, len = (key->bits + 7) / 8;
-
- /* Pad data */
- if (!RSA_FormatBlock(&padded, &padded_len, len,
- RSA_BlockPublic, src, src_len))
- return FALSE;
-
- silc_mp_init(&mp_tmp);
- silc_mp_init(&mp_dst);
-
- /* Data to MP */
- silc_mp_bin2mp(padded, padded_len, &mp_tmp);
-
- /* Encrypt */
- rsa_public_operation(key, &mp_tmp, &mp_dst);
-
- /* MP to data */
- silc_mp_mp2bin_noalloc(&mp_dst, dst, len);
- *dst_len = len;
-
- memset(padded, 0, padded_len);
- silc_free(padded);
- silc_mp_uninit(&mp_tmp);
- silc_mp_uninit(&mp_dst);
-
- return TRUE;
-}
-
-SILC_PKCS_API_DECRYPT(pkcs1)
-{
- RsaKey *key = (RsaKey *)context;
- SilcMPInt mp_tmp;
- SilcMPInt mp_dst;
- unsigned char *padded, *unpadded;
- SilcUInt32 padded_len;
-
- silc_mp_init(&mp_tmp);
- silc_mp_init(&mp_dst);
-
- /* Data to MP */
- silc_mp_bin2mp(src, src_len, &mp_tmp);
-
- /* Decrypt */
- rsa_private_operation(key, &mp_tmp, &mp_dst);
-
- /* MP to data */
- padded = silc_mp_mp2bin(&mp_dst, (key->bits + 7) / 8, &padded_len);
-
- /* Unpad data */
- unpadded = RSA_DecodeOneBlock(padded, padded_len, 0,
- RSA_BlockPublic, &padded_len);
- if (!unpadded) {
- memset(padded, 0, padded_len);
- silc_free(padded);
- silc_mp_uninit(&mp_tmp);
- silc_mp_uninit(&mp_dst);
- return FALSE;
- }
-
- /* Copy to destination */
- memcpy(dst, unpadded, padded_len);
- *dst_len = padded_len;
-
- memset(padded, 0, padded_len);
- memset(unpadded, 0, padded_len);
- silc_free(padded);
- silc_free(unpadded);
- silc_mp_uninit(&mp_tmp);
- silc_mp_uninit(&mp_dst);
-
- return TRUE;
-}
-
-SILC_PKCS_API_SIGN(pkcs1)
-{
- RsaKey *key = (RsaKey *)context;
- SilcMPInt mp_tmp;
- SilcMPInt mp_dst;
- unsigned char *padded;
- SilcUInt32 padded_len;
- SilcUInt32 len = (key->bits + 7) / 8;
-
- /* Pad data */
- if (!RSA_FormatBlock(&padded, &padded_len, len, RSA_BlockPrivate,
- src, src_len))
- return FALSE;
-
- silc_mp_init(&mp_tmp);
- silc_mp_init(&mp_dst);
-
- /* Data to MP */
- silc_mp_bin2mp(padded, len, &mp_tmp);
-
- /* Sign */
- rsa_private_operation(key, &mp_tmp, &mp_dst);
-
- /* MP to data */
- silc_mp_mp2bin_noalloc(&mp_dst, dst, len);
- *dst_len = len;
-
- memset(padded, 0, padded_len);
- silc_free(padded);
- silc_mp_uninit(&mp_tmp);
- silc_mp_uninit(&mp_dst);
-
- return TRUE;
-}
-
-SILC_PKCS_API_VERIFY(pkcs1)
-{
- RsaKey *key = (RsaKey *)context;
- int ret = TRUE;
- SilcMPInt mp_tmp2;
- SilcMPInt mp_dst;
- unsigned char *verify, *unpadded;
- SilcUInt32 verify_len, len = (key->bits + 7) / 8;
-
- silc_mp_init(&mp_tmp2);
- silc_mp_init(&mp_dst);
-
- /* Format the signature into MP int */
- silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
-
- /* Verify */
- rsa_public_operation(key, &mp_tmp2, &mp_dst);
-
- /* MP to data */
- verify = silc_mp_mp2bin(&mp_dst, len, &verify_len);
-
- /* Unpad data */
- unpadded = RSA_DecodeOneBlock(verify, len, 0,
- RSA_BlockPrivate, &verify_len);
- if (!unpadded) {
- memset(verify, 0, verify_len);
- silc_free(verify);
- silc_mp_uninit(&mp_tmp2);
- silc_mp_uninit(&mp_dst);
- return FALSE;
- }
-
- /* Compare */
- if (memcmp(data, unpadded, verify_len))
- ret = FALSE;
-
- memset(verify, 0, verify_len);
- memset(unpadded, 0, verify_len);
- silc_free(verify);
- silc_free(unpadded);
- silc_mp_uninit(&mp_tmp2);
- silc_mp_uninit(&mp_dst);
-
- return ret;
-}
+++ /dev/null
-/*
-
- pkcs1.h
-
- Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
-
- Copyright (C) 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
-*/
-#ifndef PKCS1_H
-#define PKCS1_H
-
-/*
- * SILC PKCS API for PKCS #1
- *
- * Note all the other PKCS API functions are used from the rsa.c.
- * See the definitions in rsa.c and in silcpkcs.c.
- */
-
-SILC_PKCS_API_ENCRYPT(pkcs1);
-SILC_PKCS_API_DECRYPT(pkcs1);
-SILC_PKCS_API_SIGN(pkcs1);
-SILC_PKCS_API_VERIFY(pkcs1);
-
-#endif
return sizeof(RsaKey);
}
+/* Raw RSA routines */
+
SILC_PKCS_API_ENCRYPT(rsa)
{
RsaKey *key = (RsaKey *)context;
return ret;
}
+
+/* PKCS#1 RSA routines */
+
+SILC_PKCS_API_ENCRYPT(pkcs1)
+{
+ RsaKey *key = (RsaKey *)context;
+ SilcMPInt mp_tmp;
+ SilcMPInt mp_dst;
+ unsigned char padded[2048 + 1];
+ SilcUInt32 len = (key->bits + 7) / 8;
+
+ if (sizeof(padded) < len)
+ return FALSE;
+
+ /* Pad data */
+ if (!silc_pkcs1_encode(SILC_PKCS1_BT_PUB, src, src_len,
+ padded, len, NULL))
+ return FALSE;
+
+ silc_mp_init(&mp_tmp);
+ silc_mp_init(&mp_dst);
+
+ /* Data to MP */
+ silc_mp_bin2mp(padded, len, &mp_tmp);
+
+ /* Encrypt */
+ rsa_public_operation(key, &mp_tmp, &mp_dst);
+
+ /* MP to data */
+ silc_mp_mp2bin_noalloc(&mp_dst, dst, len);
+ *dst_len = len;
+
+ memset(padded, 0, sizeof(padded));
+ silc_mp_uninit(&mp_tmp);
+ silc_mp_uninit(&mp_dst);
+
+ return TRUE;
+}
+
+SILC_PKCS_API_DECRYPT(pkcs1)
+{
+ RsaKey *key = (RsaKey *)context;
+ SilcMPInt mp_tmp;
+ SilcMPInt mp_dst;
+ unsigned char *padded, unpadded[2048 + 1];
+ SilcUInt32 padded_len;
+
+ silc_mp_init(&mp_tmp);
+ silc_mp_init(&mp_dst);
+
+ /* Data to MP */
+ silc_mp_bin2mp(src, src_len, &mp_tmp);
+
+ /* Decrypt */
+ rsa_private_operation(key, &mp_tmp, &mp_dst);
+
+ /* MP to data */
+ padded = silc_mp_mp2bin(&mp_dst, (key->bits + 7) / 8, &padded_len);
+
+ /* Unpad data */
+ if (!silc_pkcs1_decode(SILC_PKCS1_BT_PUB, padded, padded_len,
+ unpadded, sizeof(unpadded), dst_len)) {
+ memset(padded, 0, padded_len);
+ silc_free(padded);
+ silc_mp_uninit(&mp_tmp);
+ silc_mp_uninit(&mp_dst);
+ return FALSE;
+ }
+
+ /* Copy to destination */
+ memcpy(dst, unpadded, *dst_len);
+
+ memset(padded, 0, padded_len);
+ memset(unpadded, 0, sizeof(unpadded));
+ silc_free(padded);
+ silc_mp_uninit(&mp_tmp);
+ silc_mp_uninit(&mp_dst);
+
+ return TRUE;
+}
+
+SILC_PKCS_API_SIGN(pkcs1)
+{
+ RsaKey *key = (RsaKey *)context;
+ SilcMPInt mp_tmp;
+ SilcMPInt mp_dst;
+ unsigned char padded[2048 + 1];
+ SilcUInt32 len = (key->bits + 7) / 8;
+
+ if (sizeof(padded) < len)
+ return FALSE;
+
+ /* Pad data */
+ if (!silc_pkcs1_encode(SILC_PKCS1_BT_PRV1, src, src_len,
+ padded, len, NULL))
+ return FALSE;
+
+ silc_mp_init(&mp_tmp);
+ silc_mp_init(&mp_dst);
+
+ /* Data to MP */
+ silc_mp_bin2mp(padded, len, &mp_tmp);
+
+ /* Sign */
+ rsa_private_operation(key, &mp_tmp, &mp_dst);
+
+ /* MP to data */
+ silc_mp_mp2bin_noalloc(&mp_dst, dst, len);
+ *dst_len = len;
+
+ memset(padded, 0, sizeof(padded));
+ silc_mp_uninit(&mp_tmp);
+ silc_mp_uninit(&mp_dst);
+
+ return TRUE;
+}
+
+SILC_PKCS_API_VERIFY(pkcs1)
+{
+ RsaKey *key = (RsaKey *)context;
+ int ret = TRUE;
+ SilcMPInt mp_tmp2;
+ SilcMPInt mp_dst;
+ unsigned char *verify, unpadded[2048 + 1];
+ SilcUInt32 verify_len, len = (key->bits + 7) / 8;
+
+ silc_mp_init(&mp_tmp2);
+ silc_mp_init(&mp_dst);
+
+ /* Format the signature into MP int */
+ silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
+
+ /* Verify */
+ rsa_public_operation(key, &mp_tmp2, &mp_dst);
+
+ /* MP to data */
+ verify = silc_mp_mp2bin(&mp_dst, len, &verify_len);
+
+ /* Unpad data */
+ if (!silc_pkcs1_decode(SILC_PKCS1_BT_PRV1, verify, verify_len,
+ unpadded, sizeof(unpadded), &len)) {
+ memset(verify, 0, verify_len);
+ silc_free(verify);
+ silc_mp_uninit(&mp_tmp2);
+ silc_mp_uninit(&mp_dst);
+ return FALSE;
+ }
+
+ /* Compare */
+ if (memcmp(data, unpadded, len))
+ ret = FALSE;
+
+ memset(verify, 0, verify_len);
+ memset(unpadded, 0, sizeof(unpadded));
+ silc_free(verify);
+ silc_mp_uninit(&mp_tmp2);
+ silc_mp_uninit(&mp_dst);
+
+ return ret;
+}
+
/* Generates RSA public and private keys. Primes p and q that are used
to compute the modulus n has to be generated before calling this. They
are then sent as argument for the function. */
rsa.h
- Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+ Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2000 Pekka Riikonen
+ Copyright (C) 1997 - 2003 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
+ the Free Software Foundation; version 2 of the License.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
SILC_PKCS_API_SIGN(rsa);
SILC_PKCS_API_VERIFY(rsa);
+SILC_PKCS_API_ENCRYPT(pkcs1);
+SILC_PKCS_API_DECRYPT(pkcs1);
+SILC_PKCS_API_SIGN(pkcs1);
+SILC_PKCS_API_VERIFY(pkcs1);
+
#endif
#include "silcincludes.h"
#include "rsa.h"
-#include "pkcs1.h"
/* The main SILC PKCS structure. */
struct SilcPKCSStruct {
--- /dev/null
+/*
+
+ silcpkcs1.c
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2003 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
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#include "silcincludes.h"
+#include "silcpkcs1.h"
+
+/* Encodes PKCS#1 data block from the `data' according to the block type
+ indicated by `bt'. When encoding signatures the `bt' must be
+ SILC_PKCS1_BT_PRV1 and when encoding encryption blocks the `bt' must
+ be SILC_PKCS1_BT_PUB. The encoded data is copied into the `dest_data'
+ buffer which is size of `dest_data_size'. If the `dest_data' is not
+ able to hold the encoded block this returns FALSE. The `rng' must be
+ set when `bt' is SILC_PKCS1_BT_PUB. This function returns TRUE on
+ success. */
+
+bool silc_pkcs1_encode(SilcPkcs1BlockType bt,
+ const unsigned char *data,
+ SilcUInt32 data_len,
+ unsigned char *dest_data,
+ SilcUInt32 dest_data_size,
+ SilcRng rng)
+{
+ SilcInt32 padlen;
+ int i;
+
+ SILC_LOG_DEBUG(("PKCS#1 encoding, bt %d", bt));
+
+ if (!data || !dest_data ||
+ dest_data_size < 3 || dest_data_size < data_len) {
+ SILC_LOG_DEBUG(("Data to be encoded is too long"));
+ return FALSE;
+ }
+
+ /* Start of block */
+ dest_data[0] = 0x00;
+ dest_data[1] = (unsigned char)bt;
+
+ padlen = (SilcInt32)dest_data_size - (SilcInt32)data_len - 3;
+ if (padlen < 8) {
+ SILC_LOG_DEBUG(("Data to be encoded is too long"));
+ return FALSE;
+ }
+
+ /* Encode according to block type */
+ switch (bt) {
+ case SILC_PKCS1_BT_PRV0:
+ case SILC_PKCS1_BT_PRV1:
+ /* Signature */
+ memset(dest_data + 2, bt == SILC_PKCS1_BT_PRV1 ? 0xff : 0x00, padlen);
+ break;
+
+ case SILC_PKCS1_BT_PUB:
+ /* Encryption */
+ for (i = 2; i < padlen; i++) {
+ /* It is guaranteed this routine does not return zero byte. */
+ if (rng)
+ dest_data[i] = silc_rng_get_byte_fast(rng);
+ else
+ dest_data[i] = silc_rng_global_get_byte_fast();
+ }
+
+ break;
+ }
+
+ /* Copy the data */
+ dest_data[padlen + 2] = 0x00;
+ memcpy(dest_data + padlen + 3, data, data_len);
+
+ return TRUE;
+}
+
+/* Decodes the PKCS#1 encoded block according to the block type `bt'.
+ When verifying signatures the `bt' must be SILC_PKCS1_BT_PRV1 and
+ when decrypting it must be SILC_PKCS1_BT_PUB. This copies the
+ decoded data into `dest_data' which is size of `dest_data_size'. If
+ the deocded block does not fit to `dest_data' this returns FALSE.
+ Returns TRUE on success. */
+
+bool silc_pkcs1_decode(SilcPkcs1BlockType bt,
+ const unsigned char *data,
+ SilcUInt32 data_len,
+ unsigned char *dest_data,
+ SilcUInt32 dest_data_size,
+ SilcUInt32 *dest_len)
+{
+ int i = 0;
+
+ SILC_LOG_DEBUG(("PKCS#1 decoding, bt %d", bt));
+
+ /* Sanity checks */
+ if (!data || !dest_data || dest_data_size < 3 ||
+ data[0] != 0x00 || data[1] != (unsigned char)bt) {
+ SILC_LOG_DEBUG(("Malformed block"));
+ return FALSE;
+ }
+
+ /* Decode according to block type */
+ switch (bt) {
+ case SILC_PKCS1_BT_PRV0:
+ /* Do nothing */
+ break;
+
+ case SILC_PKCS1_BT_PRV1:
+ /* Verification */
+ for (i = 2; i < data_len; i++)
+ if (data[i] != 0xff)
+ break;
+ break;
+
+ case SILC_PKCS1_BT_PUB:
+ /* Decryption */
+ for (i = 2; i < data_len; i++)
+ if (data[i] == 0x00)
+ break;
+ break;
+ }
+
+ /* Sanity checks */
+ if (data[i] != 0x00 || i < 10 - 2)
+ return FALSE;
+ i++;
+ if (dest_data_size < data_len - i)
+ return FALSE;
+
+ /* Copy the data */
+ memcpy(dest_data, data + i, data_len - i);
+
+ /* Return data length */
+ if (dest_len)
+ *dest_len = data_len - i;
+
+ return TRUE;
+}
--- /dev/null
+/*
+
+ silcpkcs1.h
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2003 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
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+/****h* silccrypt/SILC PKCS1 Interface
+ *
+ * DESCRIPTION
+ *
+ * This interface implements the PKCS#1 standard block encoding and decoding
+ * routines. It is used as part of RSA implementation to perform PKCS#1
+ * RSA operations. The routines encode and decode the data for RSA operations
+ * such as digital signatures and their verification, and encryption and
+ * decryption.
+ *
+ ***/
+
+#ifndef SILCPKCS1_H
+#define SILCPKCS1_H
+
+/****d* silccrypt/SilcPKCS1API/SilcPkcs1BlockType
+ *
+ * NAME
+ *
+ * typedef enum { ... } SilcPkcs1BlockType
+ *
+ * DESCRIPTION
+ *
+ * Defines the PKCS#1 block types that define how the blcok is encoded
+ * for different RSA operations.
+ *
+ * SOURCE
+ */
+typedef enum {
+ SILC_PKCS1_BT_PRV0 = 0x00, /* Private key BT 0 */
+ SILC_PKCS1_BT_PRV1 = 0x01, /* Private key BT 1 (use this always) */
+ SILC_PKCS1_BT_PUB = 0x02, /* Public key BT */
+} SilcPkcs1BlockType;
+/***/
+
+/****f* silccrypt/SilcPKCS1API/silc_pkcs1_encode
+ *
+ * SYNOPSIS
+ *
+ * bool silc_pkcs1_encode(SilcPkcs1BlockType bt,
+ * const unsigned char *data,
+ * SilcUInt32 data_len,
+ * unsigned char *dest_data,
+ * SilcUInt32 dest_data_size,
+ * SilcRng rng);
+ *
+ * DESCRIPTION
+ *
+ * Encodes PKCS#1 data block from the `data' according to the block type
+ * indicated by `bt'. When encoding signatures the `bt' must be
+ * SILC_PKCS1_BT_PRV1 and when encoding encryption blocks the `bt' must
+ * be SILC_PKCS1_BT_PUB. The encoded data is copied into the `dest_data'
+ * buffer which is size of `dest_data_size'. If the `dest_data' is not
+ * able to hold the encoded block this returns FALSE. Usually the
+ * `dest_data_size' is set to the RSA key length value as it is the
+ * length of one block. The `rng' should be set when `bt' is set to
+ * SILC_PKCS1_BT_PUB. If `rng' is NULL global RNG is used. This
+ * function returns TRUE on success.
+ *
+ ***/
+bool silc_pkcs1_encode(SilcPkcs1BlockType bt,
+ const unsigned char *data,
+ SilcUInt32 data_len,
+ unsigned char *dest_data,
+ SilcUInt32 dest_data_size,
+ SilcRng rng);
+
+/****f* silccrypt/SilcPKCS1API/silc_pkcs1_decode
+ *
+ * SYNOPSIS
+ *
+ * bool silc_pkcs1_decode(SilcPkcs1BlockType bt,
+ * const unsigned char *data,
+ * SilcUInt32 data_len,
+ * unsigned char *dest_data,
+ * SilcUInt32 dest_data_size,
+ * SilcUInt32 *dest_len);
+ *
+ * DESCRIPTION
+ *
+ * Decodes the PKCS#1 encoded block according to the block type `bt'.
+ * When verifying signatures the `bt' must be SILC_PKCS1_BT_PRV1 and
+ * when decrypting it must be SILC_PKCS1_BT_PUB. This copies the
+ * decoded data into `dest_data' which is size of `dest_data_size'. If
+ * the deocded block does not fit to `dest_data' this returns FALSE.
+ * Returns the decoded length into `dest_len'.
+ *
+ ***/
+bool silc_pkcs1_decode(SilcPkcs1BlockType bt,
+ const unsigned char *data,
+ SilcUInt32 data_len,
+ unsigned char *dest_data,
+ SilcUInt32 dest_data_size,
+ SilcUInt32 *dest_len);
+
+#endif /* SILCPKCS1_H */