2 * rsa.c RSA Public and Private key generation functions,
3 * RSA encrypt and decrypt functions.
5 * Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 * Copyright (C) 1997 - 2000 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; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * Created: Sat Mar 1 13:26:45 1997 pekka
21 * RSA public key cryptographic algorithm used in this distribution is:
28 * Public key exponent:
29 * e relatively prime to (p-1) * (q-1)
30 * Private key exponent:
31 * d = e ^ -1 mod ((p-1) * (q-1))
38 * This code is based on SSH's (Secure Shell), PGP's (Pretty Good Privacy)
39 * and RSAREF Toolkit's RSA source codes. They all were a big help for me.
41 * I also suggest reading Bruce Schneier's; Applied Cryptography, Second
42 * Edition, John Wiley & Sons, Inc. 1996. This book deals about RSA and
43 * everything else too about cryptography.
47 #include "silcincludes.h"
51 * SILC PKCS API for RSA
54 /* Generates RSA key pair. */
56 SILC_PKCS_API_INIT(rsa)
58 unsigned int prime_bits = keylen / 2;
61 printf("Generating RSA Public and Private keys, might take a while...\n");
68 printf("Finding p: ");
69 silc_math_gen_prime(&p, prime_bits, TRUE);
71 printf("\nFinding q: ");
72 silc_math_gen_prime(&q, prime_bits, TRUE);
74 if ((silc_mp_cmp(&p, &q)) == 0) {
75 printf("\nFound equal primes, not good, retrying...\n");
79 /* If p is smaller than q, switch them */
80 if ((silc_mp_cmp(&p, &q)) > 0) {
84 silc_mp_set(&hlp, &p);
86 silc_mp_set(&q, &hlp);
91 /* Generate the actual keys */
92 rsa_generate_keys((RsaKey *)context, keylen, &p, &q);
97 printf("\nKeys generated succesfully.\n");
102 SILC_PKCS_API_CLEAR_KEYS(rsa)
104 rsa_clear_keys((RsaKey *)context);
107 /* Returns SILC style encoded RSA public key. */
109 SILC_PKCS_API_GET_PUBLIC_KEY(rsa)
111 RsaKey *key = (RsaKey *)context;
112 unsigned char *e, *n, *ret;
113 unsigned short e_len, n_len;
114 unsigned char tmp[2];
116 e_len = silc_mp_sizeinbase(&key->e, 16);
117 n_len = silc_mp_sizeinbase(&key->n, 16);
118 e = silc_calloc(e_len + 1, sizeof(unsigned char));
119 n = silc_calloc(n_len + 1, sizeof(unsigned char));
120 silc_mp_get_str(e, 16, &key->e);
121 silc_mp_get_str(n, 16, &key->n);
123 *ret_len = e_len + 2 + n_len + 2;
124 ret = silc_calloc(*ret_len, sizeof(unsigned char));
126 /* Put the length of the e. */
132 memcpy(ret + 2, e, e_len);
134 /* Put the length of the n. */
137 memcpy(ret + 2 + e_len, tmp, 2);
140 memcpy(ret + 2 + e_len + 2, n, n_len);
150 /* Returns SILC style encoded RSA private key. Public key is always
151 returned in private key as well. Public keys are often derived
152 directly from private key. */
154 SILC_PKCS_API_GET_PRIVATE_KEY(rsa)
156 RsaKey *key = (RsaKey *)context;
157 unsigned char *e, *n, *d, *ret;
158 unsigned short e_len, n_len, d_len;
159 unsigned char tmp[2];
161 e_len = silc_mp_sizeinbase(&key->e, 16);
162 n_len = silc_mp_sizeinbase(&key->n, 16);
163 d_len = silc_mp_sizeinbase(&key->d, 16);
164 e = silc_calloc(e_len + 1, sizeof(unsigned char));
165 n = silc_calloc(n_len + 1, sizeof(unsigned char));
166 d = silc_calloc(d_len + 1, sizeof(unsigned char));
167 silc_mp_get_str(e, 16, &key->e);
168 silc_mp_get_str(n, 16, &key->n);
169 silc_mp_get_str(d, 16, &key->d);
171 *ret_len = e_len + 2 + n_len + 2 + d_len + 2;
172 ret = silc_calloc(*ret_len, sizeof(unsigned char));
174 /* Put the length of the e. */
180 memcpy(ret + 2, e, e_len);
182 /* Put the length of the n. */
185 memcpy(ret + 2 + e_len, tmp, 2);
188 memcpy(ret + 2 + e_len + 2, n, n_len);
190 /* Put the length of the d. */
193 memcpy(ret + 2 + e_len + 2 + n_len, tmp, 2);
196 memcpy(ret + 2 + e_len + 2 + n_len + 2, d, d_len);
210 SILC_PKCS_API_SET_PUBLIC_KEY(rsa)
212 RsaKey *key = (RsaKey *)context;
213 unsigned char *e, *n, tmp[2];
214 unsigned short e_len, n_len;
216 silc_mp_init(&key->e);
217 silc_mp_init(&key->n);
219 memcpy(tmp, key_data, 2);
220 e_len = ((unsigned int)tmp[0] << 8) | ((unsigned int)tmp[1]);
221 if (e_len > key_len) {
222 silc_mp_clear(&key->e);
223 silc_mp_clear(&key->n);
227 e = silc_calloc(e_len + 1, sizeof(unsigned char));
228 memcpy(e, key_data + 2, e_len);
229 silc_mp_set_str(&key->e, e, 16);
231 memcpy(tmp, key_data + 2 + e_len, 2);
232 n_len = ((unsigned int)tmp[0] << 8) | ((unsigned int)tmp[1]);
233 if (e_len + n_len > key_len) {
236 silc_mp_clear(&key->e);
237 silc_mp_clear(&key->n);
241 n = silc_calloc(n_len + 1, sizeof(unsigned char));
242 memcpy(n, key_data + 2 + e_len + 2, n_len);
243 silc_mp_set_str(&key->n, n, 16);
253 /* Set private key. This derives the public key from the private
254 key and sets the public key as well. Public key should not be set
255 already and should not be set after setting private key. */
257 SILC_PKCS_API_SET_PRIVATE_KEY(rsa)
259 RsaKey *key = (RsaKey *)context;
260 unsigned char *e, *n, *d, tmp[2];
261 unsigned short e_len, n_len, d_len;
263 silc_mp_init(&key->e);
264 silc_mp_init(&key->n);
265 silc_mp_init(&key->d);
267 memcpy(tmp, key_data, 2);
268 e_len = ((unsigned int)tmp[0] << 8) | ((unsigned int)tmp[1]);
269 if (e_len > key_len) {
270 silc_mp_clear(&key->e);
271 silc_mp_clear(&key->n);
275 e = silc_calloc(e_len + 1, sizeof(unsigned char));
276 memcpy(e, key_data + 2, e_len);
277 silc_mp_set_str(&key->e, e, 16);
279 memcpy(tmp, key_data + 2 + e_len, 2);
280 n_len = ((unsigned int)tmp[0] << 8) | ((unsigned int)tmp[1]);
281 if (e_len + n_len > key_len) {
284 silc_mp_clear(&key->e);
285 silc_mp_clear(&key->n);
289 n = silc_calloc(n_len + 1, sizeof(unsigned char));
290 memcpy(n, key_data + 2 + e_len + 2, n_len);
291 silc_mp_set_str(&key->n, n, 16);
293 memcpy(tmp, key_data + 2 + e_len + 2 + n_len, 2);
294 d_len = ((unsigned int)tmp[0] << 8) | ((unsigned int)tmp[1]);
295 if (e_len + n_len + d_len > key_len) {
300 silc_mp_clear(&key->e);
301 silc_mp_clear(&key->n);
305 d = silc_calloc(d_len + 1, sizeof(unsigned char));
306 memcpy(d, key_data + 2 + e_len + 2 + n_len + 2, d_len);
307 silc_mp_set_str(&key->d, d, 16);
319 SILC_PKCS_API_CONTEXT_LEN(rsa)
321 return sizeof(RsaKey);
324 SILC_PKCS_API_DATA_CONTEXT_LEN(rsa)
326 return sizeof(RsaDataContext);
329 SILC_PKCS_API_SET_ARG(rsa)
331 RsaDataContext *data_ctx = (RsaDataContext *)data_context;
358 SILC_PKCS_API_ENCRYPT(rsa)
360 RsaKey *key = (RsaKey *)context;
365 silc_mp_init_set_ui(&mp_tmp, 0);
366 silc_mp_init_set_ui(&mp_dst, 0);
368 /* Format the data into MP int */
369 for (i = 0; i < src_len; i++) {
370 silc_mp_mul_2exp(&mp_tmp, &mp_tmp, 8);
371 silc_mp_add_ui(&mp_tmp, &mp_tmp, src[i]);
374 silc_mp_out_str(stderr, 16, &mp_tmp);
377 rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->e, &key->n);
379 fprintf(stderr, "\n");
380 silc_mp_out_str(stderr, 16, &mp_dst);
382 tmplen = (1024 + 7) / 8;
384 /* Format the MP int back into data */
385 for (i = tmplen; i > 0; i--) {
386 dst[i - 1] = (unsigned char)(silc_mp_get_ui(&mp_dst) & 0xff);
387 silc_mp_fdiv_q_2exp(&mp_dst, &mp_dst, 8);
391 silc_mp_clear(&mp_tmp);
392 silc_mp_clear(&mp_dst);
397 SILC_PKCS_API_DECRYPT(rsa)
399 RsaKey *key = (RsaKey *)context;
404 silc_mp_init_set_ui(&mp_tmp, 0);
405 silc_mp_init_set_ui(&mp_dst, 0);
407 /* Format the data into MP int */
408 for (i = 0; i < src_len; i++) {
409 silc_mp_mul_2exp(&mp_tmp, &mp_tmp, 8);
410 silc_mp_add_ui(&mp_tmp, &mp_tmp, src[i]);
413 silc_mp_out_str(stderr, 16, &mp_tmp);
416 rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
418 fprintf(stderr, "\n");
419 silc_mp_out_str(stderr, 16, &mp_dst);
421 tmplen = (1024 + 7) / 8;
423 /* Format the MP int back into data */
424 for (i = tmplen; i > 0; i--) {
425 dst[i - 1] = (unsigned char)(silc_mp_get_ui(&mp_dst) & 0xff);
426 silc_mp_fdiv_q_2exp(&mp_dst, &mp_dst, 8);
430 silc_mp_clear(&mp_tmp);
431 silc_mp_clear(&mp_dst);
436 SILC_PKCS_API_SIGN(rsa)
438 RsaKey *key = (RsaKey *)context;
443 silc_mp_init_set_ui(&mp_tmp, 0);
444 silc_mp_init_set_ui(&mp_dst, 0);
446 /* Format the data into MP int */
447 for (i = 0; i < src_len; i++) {
448 silc_mp_mul_2exp(&mp_tmp, &mp_tmp, 8);
449 silc_mp_add_ui(&mp_tmp, &mp_tmp, src[i]);
453 rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
455 tmplen = (1024 + 7) / 8;
457 /* Format the MP int back into data */
458 for (i = tmplen; i > 0; i--) {
459 dst[i - 1] = (unsigned char)(silc_mp_get_ui(&mp_dst) & 0xff);
460 silc_mp_fdiv_q_2exp(&mp_dst, &mp_dst, 8);
464 silc_mp_clear(&mp_tmp);
465 silc_mp_clear(&mp_dst);
470 SILC_PKCS_API_VERIFY(rsa)
472 RsaKey *key = (RsaKey *)context;
474 SilcInt mp_tmp, mp_tmp2;
477 silc_mp_init_set_ui(&mp_tmp, 0);
478 silc_mp_init_set_ui(&mp_tmp2, 0);
479 silc_mp_init_set_ui(&mp_dst, 0);
481 /* Format the signature into MP int */
482 for (i = 0; i < signature_len; i++) {
483 silc_mp_mul_2exp(&mp_tmp2, &mp_tmp2, 8);
484 silc_mp_add_ui(&mp_tmp2, &mp_tmp2, signature[i]);
488 rsa_en_de_crypt(&mp_dst, &mp_tmp2, &key->e, &key->n);
490 /* Format the data into MP int */
491 for (i = 0; i < data_len; i++) {
492 silc_mp_mul_2exp(&mp_tmp, &mp_tmp, 8);
493 silc_mp_add_ui(&mp_tmp, &mp_tmp, data[i]);
499 if ((silc_mp_cmp(&mp_tmp, &mp_dst)) != 0)
502 silc_mp_clear(&mp_tmp);
503 silc_mp_clear(&mp_tmp2);
504 silc_mp_clear(&mp_dst);
509 /* Generates RSA public and private keys. Primes p and q that are used
510 to compute the modulus n has to be generated before calling this. They
511 are then sent as argument for the function. */
513 void rsa_generate_keys(RsaKey *key, unsigned int bits,
514 SilcInt *p, SilcInt *q)
520 /* Initialize variables */
521 silc_mp_init(&key->p);
522 silc_mp_init(&key->q);
523 silc_mp_init(&key->n);
524 silc_mp_init(&key->e);
525 silc_mp_init(&key->d);
533 silc_mp_set(&key->p, p);
534 silc_mp_set(&key->q, q);
536 /* Compute modulus, n = p * q */
537 silc_mp_mul(&key->n, &key->p, &key->q);
539 /* phi = (p - 1) * (q - 1) */
540 silc_mp_sub_ui(&pm1, &key->p, 1);
541 silc_mp_sub_ui(&qm1, &key->q, 1);
542 silc_mp_mul(&phi, &pm1, &qm1);
544 /* Set e, the public exponent. We try to use same public exponent
545 for all keys. Also, to make encryption faster we use small
547 silc_mp_set_ui(&key->e, 127);
549 /* See if e is relatively prime to phi. gcd == greates common divisor,
550 if gcd equals 1 they are relatively prime. */
551 silc_mp_gcd(&hlp, &key->e, &phi);
552 if((silc_mp_cmp_ui(&hlp, 1)) > 0) {
553 silc_mp_add_ui(&key->e, &key->e, 2);
557 /* Find d, the private exponent. First we do phi / 2, to get it a
559 silc_mp_div_ui(&dq, &phi, 2);
560 silc_mp_modinv(&key->d, &key->e, &dq);
569 /* Clears whole key structure. */
571 void rsa_clear_keys(RsaKey *key)
574 silc_mp_clear(&key->p);
575 silc_mp_clear(&key->q);
576 silc_mp_clear(&key->n);
577 silc_mp_clear(&key->e);
578 silc_mp_clear(&key->d);
581 /* RSA encrypt/decrypt function. cm = ciphertext or plaintext,
582 mc = plaintext or ciphertext, expo = public or private exponent,
585 Encrypt: c = m ^ e mod n,
586 Decrypt: m = c ^ d mod n
589 void rsa_en_de_crypt(SilcInt *cm, SilcInt *mc,
590 SilcInt *expo, SilcInt *modu)
592 silc_mp_powm(cm, mc, expo, modu);