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 int 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 int 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 int 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]);
222 e = silc_calloc(e_len + 1, sizeof(unsigned char));
223 memcpy(e, key_data + 2, e_len);
224 silc_mp_set_str(&key->e, e, 16);
226 memcpy(tmp, key_data + 2 + e_len, 2);
227 n_len = ((unsigned int)tmp[0] << 8) | ((unsigned int)tmp[1]);
229 n = silc_calloc(n_len + 1, sizeof(unsigned char));
230 memcpy(n, key_data + 2 + e_len + 2, n_len);
231 silc_mp_set_str(&key->n, n, 16);
241 /* Set private key. This derives the public key from the private
242 key and sets the public key as well. Public key should not be set
243 already and should not be set after setting private key. */
245 SILC_PKCS_API_SET_PRIVATE_KEY(rsa)
247 RsaKey *key = (RsaKey *)context;
248 unsigned char *e, *n, *d, tmp[2];
249 unsigned int e_len, n_len, d_len;
251 silc_mp_init(&key->e);
252 silc_mp_init(&key->n);
253 silc_mp_init(&key->d);
255 memcpy(tmp, key_data, 2);
256 e_len = ((unsigned int)tmp[0] << 8) | ((unsigned int)tmp[1]);
258 e = silc_calloc(e_len + 1, sizeof(unsigned char));
259 memcpy(e, key_data + 2, e_len);
260 silc_mp_set_str(&key->e, e, 16);
262 memcpy(tmp, key_data + 2 + e_len, 2);
263 n_len = ((unsigned int)tmp[0] << 8) | ((unsigned int)tmp[1]);
265 n = silc_calloc(n_len + 1, sizeof(unsigned char));
266 memcpy(n, key_data + 2 + e_len + 2, n_len);
267 silc_mp_set_str(&key->n, n, 16);
269 memcpy(tmp, key_data + 2 + e_len + 2 + n_len, 2);
270 d_len = ((unsigned int)tmp[0] << 8) | ((unsigned int)tmp[1]);
272 d = silc_calloc(d_len + 1, sizeof(unsigned char));
273 memcpy(d, key_data + 2 + e_len + 2 + n_len + 2, d_len);
274 silc_mp_set_str(&key->d, d, 16);
286 SILC_PKCS_API_CONTEXT_LEN(rsa)
288 return sizeof(RsaKey);
291 SILC_PKCS_API_DATA_CONTEXT_LEN(rsa)
293 return sizeof(RsaDataContext);
296 SILC_PKCS_API_SET_ARG(rsa)
298 RsaDataContext *data_ctx = (RsaDataContext *)data_context;
325 SILC_PKCS_API_ENCRYPT(rsa)
327 RsaKey *key = (RsaKey *)context;
332 silc_mp_init_set_ui(&mp_tmp, 0);
333 silc_mp_init_set_ui(&mp_dst, 0);
335 /* Format the data into MP int */
336 for (i = 0; i < src_len; i++) {
337 silc_mp_mul_2exp(&mp_tmp, &mp_tmp, 8);
338 silc_mp_add_ui(&mp_tmp, &mp_tmp, src[i]);
341 silc_mp_out_str(stderr, 16, &mp_tmp);
344 rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->e, &key->n);
346 fprintf(stderr, "\n");
347 silc_mp_out_str(stderr, 16, &mp_dst);
349 tmplen = (1024 + 7) / 8;
351 /* Format the MP int back into data */
352 for (i = tmplen; i > 0; i--) {
353 dst[i - 1] = (unsigned char)(silc_mp_get_ui(&mp_dst) & 0xff);
354 silc_mp_fdiv_q_2exp(&mp_dst, &mp_dst, 8);
358 silc_mp_clear(&mp_tmp);
359 silc_mp_clear(&mp_dst);
364 SILC_PKCS_API_DECRYPT(rsa)
366 RsaKey *key = (RsaKey *)context;
371 silc_mp_init_set_ui(&mp_tmp, 0);
372 silc_mp_init_set_ui(&mp_dst, 0);
374 /* Format the data into MP int */
375 for (i = 0; i < src_len; i++) {
376 silc_mp_mul_2exp(&mp_tmp, &mp_tmp, 8);
377 silc_mp_add_ui(&mp_tmp, &mp_tmp, src[i]);
380 silc_mp_out_str(stderr, 16, &mp_tmp);
383 rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
385 fprintf(stderr, "\n");
386 silc_mp_out_str(stderr, 16, &mp_dst);
388 tmplen = (1024 + 7) / 8;
390 /* Format the MP int back into data */
391 for (i = tmplen; i > 0; i--) {
392 dst[i - 1] = (unsigned char)(silc_mp_get_ui(&mp_dst) & 0xff);
393 silc_mp_fdiv_q_2exp(&mp_dst, &mp_dst, 8);
397 silc_mp_clear(&mp_tmp);
398 silc_mp_clear(&mp_dst);
403 SILC_PKCS_API_SIGN(rsa)
405 RsaKey *key = (RsaKey *)context;
410 silc_mp_init_set_ui(&mp_tmp, 0);
411 silc_mp_init_set_ui(&mp_dst, 0);
413 /* Format the data into MP int */
414 for (i = 0; i < src_len; i++) {
415 silc_mp_mul_2exp(&mp_tmp, &mp_tmp, 8);
416 silc_mp_add_ui(&mp_tmp, &mp_tmp, src[i]);
420 rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
422 tmplen = (1024 + 7) / 8;
424 /* Format the MP int back into data */
425 for (i = tmplen; i > 0; i--) {
426 dst[i - 1] = (unsigned char)(silc_mp_get_ui(&mp_dst) & 0xff);
427 silc_mp_fdiv_q_2exp(&mp_dst, &mp_dst, 8);
431 silc_mp_clear(&mp_tmp);
432 silc_mp_clear(&mp_dst);
437 SILC_PKCS_API_VERIFY(rsa)
439 RsaKey *key = (RsaKey *)context;
441 SilcInt mp_tmp, mp_tmp2;
444 silc_mp_init_set_ui(&mp_tmp, 0);
445 silc_mp_init_set_ui(&mp_tmp2, 0);
446 silc_mp_init_set_ui(&mp_dst, 0);
448 /* Format the signature into MP int */
449 for (i = 0; i < signature_len; i++) {
450 silc_mp_mul_2exp(&mp_tmp2, &mp_tmp2, 8);
451 silc_mp_add_ui(&mp_tmp2, &mp_tmp2, signature[i]);
455 rsa_en_de_crypt(&mp_dst, &mp_tmp2, &key->e, &key->n);
457 /* Format the data into MP int */
458 for (i = 0; i < data_len; i++) {
459 silc_mp_mul_2exp(&mp_tmp, &mp_tmp, 8);
460 silc_mp_add_ui(&mp_tmp, &mp_tmp, data[i]);
466 if ((silc_mp_cmp(&mp_tmp, &mp_dst)) != 0)
469 silc_mp_clear(&mp_tmp);
470 silc_mp_clear(&mp_tmp2);
471 silc_mp_clear(&mp_dst);
476 /* Generates RSA public and private keys. Primes p and q that are used
477 to compute the modulus n has to be generated before calling this. They
478 are then sent as argument for the function. */
480 void rsa_generate_keys(RsaKey *key, unsigned int bits,
481 SilcInt *p, SilcInt *q)
487 /* Initialize variables */
488 silc_mp_init(&key->p);
489 silc_mp_init(&key->q);
490 silc_mp_init(&key->n);
491 silc_mp_init(&key->e);
492 silc_mp_init(&key->d);
500 silc_mp_set(&key->p, p);
501 silc_mp_set(&key->q, q);
503 /* Compute modulus, n = p * q */
504 silc_mp_mul(&key->n, &key->p, &key->q);
506 /* phi = (p - 1) * (q - 1) */
507 silc_mp_sub_ui(&pm1, &key->p, 1);
508 silc_mp_sub_ui(&qm1, &key->q, 1);
509 silc_mp_mul(&phi, &pm1, &qm1);
511 /* Set e, the public exponent. We try to use same public exponent
512 for all keys. Also, to make encryption faster we use small
514 silc_mp_set_ui(&key->e, 127);
516 /* See if e is relatively prime to phi. gcd == greates common divisor,
517 if gcd equals 1 they are relatively prime. */
518 silc_mp_gcd(&hlp, &key->e, &phi);
519 if((silc_mp_cmp_ui(&hlp, 1)) > 0) {
520 silc_mp_add_ui(&key->e, &key->e, 2);
524 /* Find d, the private exponent. First we do phi / 2, to get it a
526 silc_mp_div_ui(&dq, &phi, 2);
527 silc_mp_modinv(&key->d, &key->e, &dq);
536 /* Clears whole key structure. */
538 void rsa_clear_keys(RsaKey *key)
541 silc_mp_clear(&key->p);
542 silc_mp_clear(&key->q);
543 silc_mp_clear(&key->n);
544 silc_mp_clear(&key->e);
545 silc_mp_clear(&key->d);
548 /* RSA encrypt/decrypt function. cm = ciphertext or plaintext,
549 mc = plaintext or ciphertext, expo = public or private exponent,
552 Encrypt: c = m ^ e mod n,
553 Decrypt: m = c ^ d mod n
556 void rsa_en_de_crypt(SilcInt *cm, SilcInt *mc,
557 SilcInt *expo, SilcInt *modu)
559 silc_mp_powm(cm, mc, expo, modu);