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.
20 #include "silcincludes.h"
21 #include "silcpkcs1.h"
23 /* Minimum padding in block */
24 #define SILC_PKCS1_MIN_PADDING 8
26 /* Encodes PKCS#1 data block from the `data' according to the block type
27 indicated by `bt'. When encoding signatures the `bt' must be
28 SILC_PKCS1_BT_PRV1 and when encoding encryption blocks the `bt' must
29 be SILC_PKCS1_BT_PUB. The encoded data is copied into the `dest_data'
30 buffer which is size of `dest_data_size'. If the `dest_data' is not
31 able to hold the encoded block this returns FALSE. The `rng' must be
32 set when `bt' is SILC_PKCS1_BT_PUB. This function returns TRUE on
35 bool silc_pkcs1_encode(SilcPkcs1BlockType bt,
36 const unsigned char *data,
38 unsigned char *dest_data,
39 SilcUInt32 dest_data_size,
45 SILC_LOG_DEBUG(("PKCS#1 encoding, bt %d", bt));
47 if (!data || !dest_data ||
48 dest_data_size < 3 || dest_data_size < data_len) {
49 SILC_LOG_DEBUG(("Data to be encoded is too long"));
55 dest_data[1] = (unsigned char)bt;
57 padlen = (SilcInt32)dest_data_size - (SilcInt32)data_len - 3;
58 if (padlen < SILC_PKCS1_MIN_PADDING) {
59 SILC_LOG_DEBUG(("Data to be encoded is too long"));
63 /* Encode according to block type */
65 case SILC_PKCS1_BT_PRV0:
66 case SILC_PKCS1_BT_PRV1:
68 memset(dest_data + 2, bt == SILC_PKCS1_BT_PRV1 ? 0xff : 0x00, padlen);
71 case SILC_PKCS1_BT_PUB:
74 /* It is guaranteed this routine does not return zero byte. */
76 for (i = 2; i < padlen; i++)
77 dest_data[i] = silc_rng_get_byte_fast(rng);
79 for (i = 2; i < padlen; i++)
80 dest_data[i] = silc_rng_global_get_byte_fast();
85 dest_data[padlen + 2] = 0x00;
86 memcpy(dest_data + padlen + 3, data, data_len);
91 /* Decodes the PKCS#1 encoded block according to the block type `bt'.
92 When verifying signatures the `bt' must be SILC_PKCS1_BT_PRV1 and
93 when decrypting it must be SILC_PKCS1_BT_PUB. This copies the
94 decoded data into `dest_data' which is size of `dest_data_size'. If
95 the deocded block does not fit to `dest_data' this returns FALSE.
96 Returns TRUE on success. */
98 bool silc_pkcs1_decode(SilcPkcs1BlockType bt,
99 const unsigned char *data,
101 unsigned char *dest_data,
102 SilcUInt32 dest_data_size,
103 SilcUInt32 *dest_len)
107 SILC_LOG_DEBUG(("PKCS#1 decoding, bt %d", bt));
110 if (!data || !dest_data || dest_data_size < 3 ||
111 data[0] != 0x00 || data[1] != (unsigned char)bt) {
112 SILC_LOG_DEBUG(("Malformed block"));
116 /* Decode according to block type */
118 case SILC_PKCS1_BT_PRV0:
122 case SILC_PKCS1_BT_PRV1:
124 for (i = 2; i < data_len; i++)
129 case SILC_PKCS1_BT_PUB:
131 for (i = 2; i < data_len; i++)
138 if (data[i++] != 0x00) {
139 SILC_LOG_DEBUG(("Malformed block"));
142 if (i - 1 < SILC_PKCS1_MIN_PADDING) {
143 SILC_LOG_DEBUG(("Malformed block"));
146 if (dest_data_size < data_len - i) {
147 SILC_LOG_DEBUG(("Destination buffer too small"));
152 memcpy(dest_data, data + i, data_len - i);
154 /* Return data length */
156 *dest_len = data_len - i;