5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2003 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
22 #include "silcpkcs1.h"
24 /* Minimum padding in block */
25 #define SILC_PKCS1_MIN_PADDING 8
27 /* Encodes PKCS#1 data block from the `data' according to the block type
28 indicated by `bt'. When encoding signatures the `bt' must be
29 SILC_PKCS1_BT_PRV1 and when encoding encryption blocks the `bt' must
30 be SILC_PKCS1_BT_PUB. The encoded data is copied into the `dest_data'
31 buffer which is size of `dest_data_size'. If the `dest_data' is not
32 able to hold the encoded block this returns FALSE. The `rng' must be
33 set when `bt' is SILC_PKCS1_BT_PUB. This function returns TRUE on
36 SilcBool silc_pkcs1_encode(SilcPkcs1BlockType bt,
37 const unsigned char *data,
39 unsigned char *dest_data,
40 SilcUInt32 dest_data_size,
46 SILC_LOG_DEBUG(("PKCS#1 encoding, bt %d", bt));
48 if (!data || !dest_data ||
49 dest_data_size < 3 || dest_data_size < data_len) {
50 SILC_LOG_DEBUG(("Data to be encoded is too long"));
56 dest_data[1] = (unsigned char)bt;
58 padlen = (SilcInt32)dest_data_size - (SilcInt32)data_len - 3;
59 if (padlen < SILC_PKCS1_MIN_PADDING) {
60 SILC_LOG_DEBUG(("Data to be encoded is too long"));
64 /* Encode according to block type */
66 case SILC_PKCS1_BT_PRV0:
67 case SILC_PKCS1_BT_PRV1:
69 memset(dest_data + 2, bt == SILC_PKCS1_BT_PRV1 ? 0xff : 0x00, padlen);
72 case SILC_PKCS1_BT_PUB:
75 /* It is guaranteed this routine does not return zero byte. */
77 for (i = 2; i < padlen; i++)
78 dest_data[i] = silc_rng_get_byte_fast(rng);
80 for (i = 2; i < padlen; i++)
81 dest_data[i] = silc_rng_global_get_byte_fast();
86 dest_data[padlen + 2] = 0x00;
87 memcpy(dest_data + padlen + 3, data, data_len);
92 /* Decodes the PKCS#1 encoded block according to the block type `bt'.
93 When verifying signatures the `bt' must be SILC_PKCS1_BT_PRV1 and
94 when decrypting it must be SILC_PKCS1_BT_PUB. This copies the
95 decoded data into `dest_data' which is size of `dest_data_size'. If
96 the deocded block does not fit to `dest_data' this returns FALSE.
97 Returns TRUE on success. */
99 SilcBool silc_pkcs1_decode(SilcPkcs1BlockType bt,
100 const unsigned char *data,
102 unsigned char *dest_data,
103 SilcUInt32 dest_data_size,
104 SilcUInt32 *dest_len)
108 SILC_LOG_DEBUG(("PKCS#1 decoding, bt %d", bt));
111 if (!data || !dest_data || dest_data_size < 3 ||
112 data[0] != 0x00 || data[1] != (unsigned char)bt) {
113 SILC_LOG_DEBUG(("Malformed block"));
117 /* Decode according to block type */
119 case SILC_PKCS1_BT_PRV0:
123 case SILC_PKCS1_BT_PRV1:
125 for (i = 2; i < data_len; i++)
130 case SILC_PKCS1_BT_PUB:
132 for (i = 2; i < data_len; i++)
139 if (data[i++] != 0x00) {
140 SILC_LOG_DEBUG(("Malformed block"));
143 if (i - 1 < SILC_PKCS1_MIN_PADDING) {
144 SILC_LOG_DEBUG(("Malformed block"));
147 if (dest_data_size < data_len - i) {
148 SILC_LOG_DEBUG(("Destination buffer too small"));
153 memcpy(dest_data, data + i, data_len - i);
155 /* Return data length */
157 *dest_len = data_len - i;