5 Heavily modified to work under SILC, rewrote all interfaces, code that
6 is not needed in SILC has been removed for good, and some code was fixed
9 For example, RSA_DecodeOneBlock was not used at all by Mozilla, however,
10 I took this code in to use after doing some fixing (it had some bugs).
11 Also, OAEP is removed totally for now. I'm not sure whether OAEP could
12 be used in the future with SILC but not for now.
14 This file also implements partial SILC PKCS API for RSA with PKCS #1.
15 It is partial because all the other functions but encrypt, decrypt,
16 sign and verify are common.
20 The mandatory PKCS #1 implementation in SILC must be compliant to either
21 PKCS #1 version 1.5 or PKCS #1 version 2 with the following notes:
22 The signature encoding is always in same format as the encryption
23 encoding regardles of the PKCS #1 version. The signature with
24 appendix (with hash algorithm OID in the data) must not be used
25 in the SILC. Rationale for this is that there is no binding between
26 the PKCS #1 OIDs and the hash algorithms used in the SILC protocol.
27 Hence, the encoding is always in PKCS #1 version 1.5 format.
29 Any questions and comments regarding this modified version should be
30 sent to priikone@silcnet.org.
32 References: ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc,
33 ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1.asc,
36 Copyright notice: All code in this file, including the SILC PKCS API
37 code that is not part of the Mozilla code, falls under the same license
38 (MPL or GPL) found attached to this file, below.
42 * PKCS#1 encoding and decoding functions.
43 * This file is believed to contain no code licensed from other parties.
45 * The contents of this file are subject to the Mozilla Public
46 * License Version 1.1 (the "License"); you may not use this file
47 * except in compliance with the License. You may obtain a copy of
48 * the License at http://www.mozilla.org/MPL/
50 * Software distributed under the License is distributed on an "AS
51 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
52 * implied. See the License for the specific language governing
53 * rights and limitations under the License.
55 * The Original Code is the Netscape security libraries.
57 * The Initial Developer of the Original Code is Netscape
58 * Communications Corporation. Portions created by Netscape are
59 * Copyright (C) 1994-2000 Netscape Communications Corporation. All
64 * Alternatively, the contents of this file may be used under the
65 * terms of the GNU General Public License Version 2 or later (the
66 * "GPL"), in which case the provisions of the GPL are applicable
67 * instead of those above. If you wish to allow use of your
68 * version of this file only under the terms of the GPL and not to
69 * allow others to use your version of this file under the MPL,
70 * indicate your decision by deleting the provisions above and
71 * replace them with the notice and other provisions required by
72 * the GPL. If you do not delete the provisions above, a recipient
73 * may use your version of this file under either the MPL or the
79 #include "silcincludes.h"
80 #include "rsa_internal.h"
83 #define RSA_BLOCK_MIN_PAD_LEN 8
84 #define RSA_BLOCK_FIRST_OCTET 0x00
85 #define RSA_BLOCK_PRIVATE0_PAD_OCTET 0x00
86 #define RSA_BLOCK_PRIVATE_PAD_OCTET 0xff
87 #define RSA_BLOCK_AFTER_PAD_OCTET 0x00
92 * The actual values are important -- they are fixed, *not* arbitrary.
93 * The explicit value assignments are not needed (because C would give
94 * us those same values anyway) but are included as a reminder...
97 RSA_BlockPrivate0 = 0, /* unused, really */
98 RSA_BlockPrivate = 1, /* pad for a private-key operation */
99 RSA_BlockPublic = 2, /* pad for a public-key operation */
104 * Format one block of data for public/private key encryption using
105 * the rules defined in PKCS #1.
107 static unsigned char *
108 RSA_FormatOneBlock(SilcUInt32 modulusLen, RSA_BlockType blockType,
109 unsigned char *data, SilcUInt32 data_len)
111 unsigned char *block;
116 block = (unsigned char *) silc_malloc(modulusLen);
123 * All RSA blocks start with two octets:
126 *bp++ = RSA_BLOCK_FIRST_OCTET;
127 *bp++ = (unsigned char) blockType;
132 * Blocks intended for private-key operation.
134 case RSA_BlockPrivate0: /* essentially unused */
135 case RSA_BlockPrivate: /* preferred method */
137 * 0x00 || BT || Pad || 0x00 || ActualData
138 * 1 1 padLen 1 data_len
139 * Pad is either all 0x00 or all 0xff bytes, depending on blockType.
141 padLen = modulusLen - data_len - 3;
142 assert(padLen >= RSA_BLOCK_MIN_PAD_LEN);
144 blockType == RSA_BlockPrivate0
145 ? RSA_BLOCK_PRIVATE0_PAD_OCTET
146 : RSA_BLOCK_PRIVATE_PAD_OCTET,
149 *bp++ = RSA_BLOCK_AFTER_PAD_OCTET;
150 memcpy(bp, data, data_len);
154 * Blocks intended for public-key operation.
156 case RSA_BlockPublic:
158 * 0x00 || BT || Pad || 0x00 || ActualData
159 * 1 1 padLen 1 data_len
160 * Pad is all non-zero random bytes.
162 padLen = modulusLen - data_len - 3;
163 assert(padLen >= RSA_BLOCK_MIN_PAD_LEN);
164 for (i = 0; i < padLen; i++) {
165 /* Pad with non-zero random data. */
167 bp[i] = silc_rng_global_get_byte();
168 } while (bp[i] == RSA_BLOCK_AFTER_PAD_OCTET);
171 *bp++ = RSA_BLOCK_AFTER_PAD_OCTET;
172 memcpy(bp, data, data_len);
184 RSA_FormatBlock(unsigned char **result, SilcUInt32 *result_len,
185 SilcUInt32 modulusLen,
186 RSA_BlockType blockType, unsigned char *data,
190 * XXX For now assume that the data length fits in a single
191 * XXX encryption block; the ASSERTs below force this.
192 * XXX To fix it, each case will have to loop over chunks whose
193 * XXX lengths satisfy the assertions, until all data is handled.
194 * XXX (Unless RSA has more to say about how to handle data
195 * XXX which does not fit in a single encryption block?)
196 * XXX And I do not know what the result is supposed to be,
197 * XXX so the interface to this function may need to change
198 * XXX to allow for returning multiple blocks, if they are
199 * XXX not wanted simply concatenated one after the other.
203 case RSA_BlockPrivate0:
204 case RSA_BlockPrivate:
205 case RSA_BlockPublic:
207 * 0x00 || BT || Pad || 0x00 || ActualData
209 * The "3" below is the first octet + the second octet + the 0x00
210 * octet that always comes just before the ActualData.
212 assert(data_len <= (modulusLen - (3 + RSA_BLOCK_MIN_PAD_LEN)));
214 *result = RSA_FormatOneBlock(modulusLen, blockType, data, data_len);
215 if (result == NULL) {
219 *result_len = modulusLen;
233 * Takes a formatted block and returns the data part.
234 * (This is the inverse of RSA_FormatOneBlock().)
235 * In some formats the start of the data is ambiguous;
236 * if it is non-zero, expectedLen will disambiguate.
240 RSA_DecodeOneBlock(unsigned char *data,
241 SilcUInt32 modulusLen,
242 SilcUInt32 expectedLen,
244 SilcUInt32 *pResultLen)
246 RSA_BlockType blockType;
247 unsigned char *dp, *res;
248 SilcUInt32 i, len = 0;
251 if (dp[0] != RSA_BLOCK_FIRST_OCTET) {
255 blockType = (RSA_BlockType)dp[1];
262 case RSA_BlockPrivate0:
264 res = (unsigned char *) silc_malloc(modulusLen);
265 memcpy(res, data, modulusLen);
268 case RSA_BlockPrivate:
269 for (i = 0; i < modulusLen; i++) {
270 if (*dp++ != RSA_BLOCK_PRIVATE_PAD_OCTET)
275 len = modulusLen - (dp - data);
276 res = (unsigned char *) silc_malloc(len);
280 memcpy(res, dp, len);
283 case RSA_BlockPublic:
284 for (i = 0; i < modulusLen; i++) {
285 if (*dp++ == RSA_BLOCK_AFTER_PAD_OCTET)
290 len = modulusLen - (dp - data);
291 res = (unsigned char *) silc_malloc(len);
295 memcpy(res, dp, len);
308 * SILC PKCS API for PKCS #1
310 * Note all the other PKCS API functions are used from the rsa.c.
311 * See the definitions in rsa.c and in silcpkcs.c.
314 SILC_PKCS_API_ENCRYPT(pkcs1)
316 RsaKey *key = (RsaKey *)context;
319 unsigned char *padded;
320 SilcUInt32 padded_len, len = key->bits / 8;
323 if (!RSA_FormatBlock(&padded, &padded_len, len,
324 RSA_BlockPublic, src, src_len))
327 silc_mp_init(&mp_tmp);
328 silc_mp_init(&mp_dst);
329 silc_mp_set_ui(&mp_tmp, 0);
330 silc_mp_set_ui(&mp_dst, 0);
333 silc_mp_bin2mp(padded, padded_len, &mp_tmp);
336 rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->e, &key->n);
339 silc_mp_mp2bin_noalloc(&mp_dst, dst, len);
342 memset(padded, 0, padded_len);
344 silc_mp_uninit(&mp_tmp);
345 silc_mp_uninit(&mp_dst);
350 SILC_PKCS_API_DECRYPT(pkcs1)
352 RsaKey *key = (RsaKey *)context;
355 unsigned char *padded, *unpadded;
356 SilcUInt32 padded_len;
358 silc_mp_init(&mp_tmp);
359 silc_mp_init(&mp_dst);
360 silc_mp_set_ui(&mp_tmp, 0);
361 silc_mp_set_ui(&mp_dst, 0);
364 silc_mp_bin2mp(src, src_len, &mp_tmp);
367 rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
370 padded = silc_mp_mp2bin(&mp_dst, key->bits / 8, &padded_len);
373 unpadded = RSA_DecodeOneBlock(padded, padded_len, 0,
374 RSA_BlockPublic, &padded_len);
376 memset(padded, 0, padded_len);
378 silc_mp_uninit(&mp_tmp);
379 silc_mp_uninit(&mp_dst);
383 /* Copy to destination */
384 memcpy(dst, unpadded, padded_len);
385 *dst_len = padded_len;
387 memset(padded, 0, padded_len);
388 memset(unpadded, 0, padded_len);
391 silc_mp_uninit(&mp_tmp);
392 silc_mp_uninit(&mp_dst);
397 SILC_PKCS_API_SIGN(pkcs1)
399 RsaKey *key = (RsaKey *)context;
402 unsigned char *padded;
403 SilcUInt32 padded_len;
404 SilcUInt32 len = key->bits / 8;
407 if (!RSA_FormatBlock(&padded, &padded_len, len, RSA_BlockPrivate,
411 silc_mp_init(&mp_tmp);
412 silc_mp_init(&mp_dst);
413 silc_mp_set_ui(&mp_tmp, 0);
414 silc_mp_set_ui(&mp_dst, 0);
417 silc_mp_bin2mp(padded, len, &mp_tmp);
420 rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
423 silc_mp_mp2bin_noalloc(&mp_dst, dst, len);
426 memset(padded, 0, padded_len);
428 silc_mp_uninit(&mp_tmp);
429 silc_mp_uninit(&mp_dst);
434 SILC_PKCS_API_VERIFY(pkcs1)
436 RsaKey *key = (RsaKey *)context;
440 unsigned char *verify, *unpadded;
441 SilcUInt32 verify_len, len = key->bits / 8;
443 silc_mp_init(&mp_tmp2);
444 silc_mp_init(&mp_dst);
445 silc_mp_set_ui(&mp_tmp2, 0);
446 silc_mp_set_ui(&mp_dst, 0);
448 /* Format the signature into MP int */
449 silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
452 rsa_en_de_crypt(&mp_dst, &mp_tmp2, &key->e, &key->n);
455 verify = silc_mp_mp2bin(&mp_dst, len, &verify_len);
458 unpadded = RSA_DecodeOneBlock(verify, len, 0,
459 RSA_BlockPrivate, &verify_len);
461 memset(verify, 0, verify_len);
463 silc_mp_uninit(&mp_tmp2);
464 silc_mp_uninit(&mp_dst);
469 if (memcmp(data, unpadded, verify_len))
472 memset(verify, 0, verify_len);
473 memset(unpadded, 0, verify_len);
476 silc_mp_uninit(&mp_tmp2);
477 silc_mp_uninit(&mp_dst);