| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 1 | /* | 
| Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 2 |  * | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 3 |  * rsa.c | 
| Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 4 |  * | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 5 |  * Author: Tatu Ylonen <ylo@cs.hut.fi> | 
| Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 6 |  * | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 7 |  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 
 | 8 |  *                    All rights reserved | 
| Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 9 |  * | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 10 |  * Created: Fri Mar  3 22:07:06 1995 ylo | 
| Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 11 |  * | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 12 |  * Description of the RSA algorithm can be found e.g. from the following sources: | 
| Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 13 |  * | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 14 |  *   Bruce Schneier: Applied Cryptography.  John Wiley & Sons, 1994. | 
| Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 15 |  * | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 16 |  *   Jennifer Seberry and Josed Pieprzyk: Cryptography: An Introduction to | 
 | 17 |  *   Computer Security.  Prentice-Hall, 1989. | 
| Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 18 |  * | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 19 |  *   Man Young Rhee: Cryptography and Secure Data Communications.  McGraw-Hill, | 
 | 20 |  *   1994. | 
| Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 21 |  * | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 22 |  *   R. Rivest, A. Shamir, and L. M. Adleman: Cryptographic Communications | 
 | 23 |  *   System and Method.  US Patent 4,405,829, 1983. | 
| Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 24 |  * | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 25 |  *   Hans Riesel: Prime Numbers and Computer Methods for Factorization. | 
 | 26 |  *   Birkhauser, 1994. | 
| Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 27 |  * | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 28 |  *   The RSA Frequently Asked Questions document by RSA Data Security, Inc., 1995. | 
| Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 29 |  * | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 30 |  *   RSA in 3 lines of perl by Adam Back <aba@atlax.ex.ac.uk>, 1995, as included | 
 | 31 |  *   below: | 
| Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 32 |  * | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 33 |  *     [gone - had to be deleted - what a pity] | 
| Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 34 |  * | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 35 | */ | 
 | 36 |  | 
 | 37 | #include "includes.h" | 
| Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 38 | RCSID("$Id: rsa.c,v 1.14 2000/04/16 01:18:45 damien Exp $"); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 39 |  | 
 | 40 | #include "rsa.h" | 
 | 41 | #include "ssh.h" | 
 | 42 | #include "xmalloc.h" | 
| Damien Miller | 040f383 | 2000-04-03 14:50:43 +1000 | [diff] [blame] | 43 | #include "entropy.h" | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 44 |  | 
 | 45 | int rsa_verbose = 1; | 
 | 46 |  | 
 | 47 | int | 
 | 48 | rsa_alive() | 
 | 49 | { | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 50 | 	RSA *key; | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 51 |  | 
| Damien Miller | fac99cd | 2000-03-05 16:10:45 +1100 | [diff] [blame] | 52 | 	seed_rng(); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 53 | 	key = RSA_generate_key(32, 3, NULL, NULL); | 
 | 54 | 	if (key == NULL) | 
 | 55 | 		return (0); | 
 | 56 | 	RSA_free(key); | 
 | 57 | 	return (1); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 58 | } | 
 | 59 |  | 
| Damien Miller | 5428f64 | 1999-11-25 11:54:57 +1100 | [diff] [blame] | 60 | /* | 
| Damien Miller | fdb5f13 | 1999-12-17 14:02:47 +1100 | [diff] [blame] | 61 |  * Key generation progress meter callback | 
 | 62 |  */ | 
 | 63 | void | 
 | 64 | keygen_progress(int p, int n, void *arg) | 
 | 65 | { | 
 | 66 | 	const char progress_chars[] = ".o+O?"; | 
 | 67 |  | 
 | 68 | 	if ((p < 0) || (p > (sizeof(progress_chars) - 2))) | 
| Damien Miller | f07390e | 2000-01-29 20:40:22 +1100 | [diff] [blame] | 69 | 		p = sizeof(progress_chars) - 2; | 
| Damien Miller | fdb5f13 | 1999-12-17 14:02:47 +1100 | [diff] [blame] | 70 |  | 
| Damien Miller | f07390e | 2000-01-29 20:40:22 +1100 | [diff] [blame] | 71 | 	putchar(progress_chars[p]); | 
| Damien Miller | fdb5f13 | 1999-12-17 14:02:47 +1100 | [diff] [blame] | 72 | 	fflush(stdout); | 
 | 73 | } | 
 | 74 |  | 
 | 75 | /* | 
| Damien Miller | 5428f64 | 1999-11-25 11:54:57 +1100 | [diff] [blame] | 76 |  * Generates RSA public and private keys.  This initializes the data | 
 | 77 |  * structures; they should be freed with rsa_clear_private_key and | 
 | 78 |  * rsa_clear_public_key. | 
 | 79 |  */ | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 80 |  | 
 | 81 | void | 
 | 82 | rsa_generate_key(RSA *prv, RSA *pub, unsigned int bits) | 
 | 83 | { | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 84 | 	RSA *key; | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 85 |  | 
| Damien Miller | f07390e | 2000-01-29 20:40:22 +1100 | [diff] [blame] | 86 | 	seed_rng(); | 
 | 87 | 	 | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 88 | 	if (rsa_verbose) { | 
 | 89 | 		printf("Generating RSA keys:  "); | 
 | 90 | 		fflush(stdout); | 
| Damien Miller | fdb5f13 | 1999-12-17 14:02:47 +1100 | [diff] [blame] | 91 | 		key = RSA_generate_key(bits, 35, keygen_progress, NULL); | 
 | 92 | 		printf("\n"); | 
 | 93 | 	} else { | 
 | 94 | 		key = RSA_generate_key(bits, 35, NULL, NULL); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 95 | 	} | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 96 | 	if (key == NULL) | 
 | 97 | 		fatal("rsa_generate_key: key generation failed."); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 98 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 99 | 	/* Copy public key parameters */ | 
 | 100 | 	pub->n = BN_new(); | 
 | 101 | 	BN_copy(pub->n, key->n); | 
 | 102 | 	pub->e = BN_new(); | 
 | 103 | 	BN_copy(pub->e, key->e); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 104 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 105 | 	/* Copy private key parameters */ | 
 | 106 | 	prv->n = BN_new(); | 
 | 107 | 	BN_copy(prv->n, key->n); | 
 | 108 | 	prv->e = BN_new(); | 
 | 109 | 	BN_copy(prv->e, key->e); | 
 | 110 | 	prv->d = BN_new(); | 
 | 111 | 	BN_copy(prv->d, key->d); | 
 | 112 | 	prv->p = BN_new(); | 
 | 113 | 	BN_copy(prv->p, key->p); | 
 | 114 | 	prv->q = BN_new(); | 
 | 115 | 	BN_copy(prv->q, key->q); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 116 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 117 | 	prv->dmp1 = BN_new(); | 
 | 118 | 	BN_copy(prv->dmp1, key->dmp1); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 119 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 120 | 	prv->dmq1 = BN_new(); | 
 | 121 | 	BN_copy(prv->dmq1, key->dmq1); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 122 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 123 | 	prv->iqmp = BN_new(); | 
 | 124 | 	BN_copy(prv->iqmp, key->iqmp); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 125 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 126 | 	RSA_free(key); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 127 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 128 | 	if (rsa_verbose) | 
 | 129 | 		printf("Key generation complete.\n"); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 130 | } | 
 | 131 |  | 
 | 132 | void | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 133 | rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key) | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 134 | { | 
| Damien Miller | 7684ee1 | 2000-03-17 23:40:15 +1100 | [diff] [blame] | 135 | 	unsigned char *inbuf, *outbuf; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 136 | 	int len, ilen, olen; | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 137 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 138 | 	if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e)) | 
 | 139 | 		fatal("rsa_public_encrypt() exponent too small or not odd"); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 140 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 141 | 	olen = BN_num_bytes(key->n); | 
 | 142 | 	outbuf = xmalloc(olen); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 143 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 144 | 	ilen = BN_num_bytes(in); | 
 | 145 | 	inbuf = xmalloc(ilen); | 
 | 146 | 	BN_bn2bin(in, inbuf); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 147 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 148 | 	if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key, | 
| Damien Miller | 98c7ad6 | 2000-03-09 21:27:49 +1100 | [diff] [blame] | 149 | 	    RSA_PKCS1_PADDING)) <= 0) | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 150 | 		fatal("rsa_public_encrypt() failed"); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 151 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 152 | 	BN_bin2bn(outbuf, len, out); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 153 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 154 | 	memset(outbuf, 0, olen); | 
 | 155 | 	memset(inbuf, 0, ilen); | 
 | 156 | 	xfree(outbuf); | 
 | 157 | 	xfree(inbuf); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 158 | } | 
 | 159 |  | 
 | 160 | void | 
 | 161 | rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key) | 
 | 162 | { | 
| Damien Miller | 7684ee1 | 2000-03-17 23:40:15 +1100 | [diff] [blame] | 163 | 	unsigned char *inbuf, *outbuf; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 164 | 	int len, ilen, olen; | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 165 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 166 | 	olen = BN_num_bytes(key->n); | 
 | 167 | 	outbuf = xmalloc(olen); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 168 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 169 | 	ilen = BN_num_bytes(in); | 
 | 170 | 	inbuf = xmalloc(ilen); | 
 | 171 | 	BN_bn2bin(in, inbuf); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 172 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 173 | 	if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key, | 
| Damien Miller | 98c7ad6 | 2000-03-09 21:27:49 +1100 | [diff] [blame] | 174 | 	    RSA_PKCS1_PADDING)) <= 0) | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 175 | 		fatal("rsa_private_decrypt() failed"); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 176 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 177 | 	BN_bin2bn(outbuf, len, out); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 178 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 179 | 	memset(outbuf, 0, olen); | 
 | 180 | 	memset(inbuf, 0, ilen); | 
 | 181 | 	xfree(outbuf); | 
 | 182 | 	xfree(inbuf); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 183 | } | 
 | 184 |  | 
 | 185 | /* Set whether to output verbose messages during key generation. */ | 
 | 186 |  | 
 | 187 | void | 
 | 188 | rsa_set_verbose(int verbose) | 
 | 189 | { | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 190 | 	rsa_verbose = verbose; | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 191 | } |