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];
259 if (modulusLen < 2 + 1)
265 case RSA_BlockPrivate0:
267 res = (unsigned char *) silc_malloc(modulusLen);
268 memcpy(res, data, modulusLen);
271 case RSA_BlockPrivate:
272 for (i = 0; i < modulusLen; i++) {
273 if (*dp++ != RSA_BLOCK_PRIVATE_PAD_OCTET)
278 len = modulusLen - (dp - data);
279 res = (unsigned char *) silc_malloc(len);
283 memcpy(res, dp, len);
286 case RSA_BlockPublic:
287 for (i = 0; i < modulusLen; i++) {
288 if (*dp++ == RSA_BLOCK_AFTER_PAD_OCTET)
293 len = modulusLen - (dp - data);
294 res = (unsigned char *) silc_malloc(len);
298 memcpy(res, dp, len);
311 * SILC PKCS API for PKCS #1
313 * Note all the other PKCS API functions are used from the rsa.c.
314 * See the definitions in rsa.c and in silcpkcs.c.
317 SILC_PKCS_API_ENCRYPT(pkcs1)
319 RsaKey *key = (RsaKey *)context;
322 unsigned char *padded;
323 SilcUInt32 padded_len, len = (key->bits + 7) / 8;
326 if (!RSA_FormatBlock(&padded, &padded_len, len,
327 RSA_BlockPublic, src, src_len))
330 silc_mp_init(&mp_tmp);
331 silc_mp_init(&mp_dst);
334 silc_mp_bin2mp(padded, padded_len, &mp_tmp);
337 rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->e, &key->n);
340 silc_mp_mp2bin_noalloc(&mp_dst, dst, len);
343 memset(padded, 0, padded_len);
345 silc_mp_uninit(&mp_tmp);
346 silc_mp_uninit(&mp_dst);
351 SILC_PKCS_API_DECRYPT(pkcs1)
353 RsaKey *key = (RsaKey *)context;
356 unsigned char *padded, *unpadded;
357 SilcUInt32 padded_len;
359 silc_mp_init(&mp_tmp);
360 silc_mp_init(&mp_dst);
363 silc_mp_bin2mp(src, src_len, &mp_tmp);
366 rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
369 padded = silc_mp_mp2bin(&mp_dst, (key->bits + 7) / 8, &padded_len);
372 unpadded = RSA_DecodeOneBlock(padded, padded_len, 0,
373 RSA_BlockPublic, &padded_len);
375 memset(padded, 0, padded_len);
377 silc_mp_uninit(&mp_tmp);
378 silc_mp_uninit(&mp_dst);
382 /* Copy to destination */
383 memcpy(dst, unpadded, padded_len);
384 *dst_len = padded_len;
386 memset(padded, 0, padded_len);
387 memset(unpadded, 0, padded_len);
390 silc_mp_uninit(&mp_tmp);
391 silc_mp_uninit(&mp_dst);
396 SILC_PKCS_API_SIGN(pkcs1)
398 RsaKey *key = (RsaKey *)context;
401 unsigned char *padded;
402 SilcUInt32 padded_len;
403 SilcUInt32 len = (key->bits + 7) / 8;
406 if (!RSA_FormatBlock(&padded, &padded_len, len, RSA_BlockPrivate,
410 silc_mp_init(&mp_tmp);
411 silc_mp_init(&mp_dst);
414 silc_mp_bin2mp(padded, len, &mp_tmp);
417 rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
420 silc_mp_mp2bin_noalloc(&mp_dst, dst, len);
423 memset(padded, 0, padded_len);
425 silc_mp_uninit(&mp_tmp);
426 silc_mp_uninit(&mp_dst);
431 SILC_PKCS_API_VERIFY(pkcs1)
433 RsaKey *key = (RsaKey *)context;
437 unsigned char *verify, *unpadded;
438 SilcUInt32 verify_len, len = (key->bits + 7) / 8;
440 silc_mp_init(&mp_tmp2);
441 silc_mp_init(&mp_dst);
443 /* Format the signature into MP int */
444 silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
447 rsa_en_de_crypt(&mp_dst, &mp_tmp2, &key->e, &key->n);
450 verify = silc_mp_mp2bin(&mp_dst, len, &verify_len);
453 unpadded = RSA_DecodeOneBlock(verify, len, 0,
454 RSA_BlockPrivate, &verify_len);
456 memset(verify, 0, verify_len);
458 silc_mp_uninit(&mp_tmp2);
459 silc_mp_uninit(&mp_dst);
464 if (memcmp(data, unpadded, verify_len))
467 memset(verify, 0, verify_len);
468 memset(unpadded, 0, verify_len);
471 silc_mp_uninit(&mp_tmp2);
472 silc_mp_uninit(&mp_dst);