Deleted Added
full compact
key.c (60576) key.c (61203)
1/*
2 * Copyright (c) 2000 Markus Friedl. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by Markus Friedl.
15 * 4. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
1/*
2 * Copyright (c) 2000 Markus Friedl. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by Markus Friedl.
15 * 4. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * $FreeBSD: head/crypto/openssh/key.c 60576 2000-05-15 05:24:25Z kris $
29 * $FreeBSD: head/crypto/openssh/key.c 61203 2000-06-03 07:31:44Z kris $
30 */
31/*
32 * read_bignum():
33 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
34 */
35
36#include "includes.h"
37#include "ssh.h"
38#include <openssl/rsa.h>
39#include <openssl/dsa.h>
40#include <openssl/evp.h>
41#include "xmalloc.h"
42#include "key.h"
43#include "dsa.h"
44#include "uuencode.h"
45
46#define SSH_DSS "ssh-dss"
47
48Key *
49key_new(int type)
50{
51 Key *k;
52 RSA *rsa;
53 DSA *dsa;
54 k = xmalloc(sizeof(*k));
55 k->type = type;
56 k->dsa = NULL;
57 k->rsa = NULL;
58 switch (k->type) {
59 case KEY_RSA:
60 rsa = RSA_new();
61 rsa->n = BN_new();
62 rsa->e = BN_new();
63 k->rsa = rsa;
64 break;
65 case KEY_DSA:
66 dsa = DSA_new();
67 dsa->p = BN_new();
68 dsa->q = BN_new();
69 dsa->g = BN_new();
70 dsa->pub_key = BN_new();
71 k->dsa = dsa;
72 break;
73 case KEY_EMPTY:
74 break;
75 default:
76 fatal("key_new: bad key type %d", k->type);
77 break;
78 }
79 return k;
80}
81void
82key_free(Key *k)
83{
84 switch (k->type) {
85 case KEY_RSA:
86 if (k->rsa != NULL)
87 RSA_free(k->rsa);
88 k->rsa = NULL;
89 break;
90 case KEY_DSA:
91 if (k->dsa != NULL)
92 DSA_free(k->dsa);
93 k->dsa = NULL;
94 break;
95 default:
96 fatal("key_free: bad key type %d", k->type);
97 break;
98 }
99 xfree(k);
100}
101int
102key_equal(Key *a, Key *b)
103{
104 if (a == NULL || b == NULL || a->type != b->type)
105 return 0;
106 switch (a->type) {
107 case KEY_RSA:
108 return a->rsa != NULL && b->rsa != NULL &&
109 BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
110 BN_cmp(a->rsa->n, b->rsa->n) == 0;
111 break;
112 case KEY_DSA:
113 return a->dsa != NULL && b->dsa != NULL &&
114 BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
115 BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
116 BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
117 BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
118 break;
119 default:
120 fatal("key_equal: bad key type %d", a->type);
121 break;
122 }
123 return 0;
124}
125
126#define FPRINT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
127
128/*
129 * Generate key fingerprint in ascii format.
130 * Based on ideas and code from Bjoern Groenvall <bg@sics.se>
131 */
132char *
133key_fingerprint(Key *k)
134{
135 static char retval[80];
136 unsigned char *blob = NULL;
137 int len = 0;
138 int nlen, elen;
139
140 switch (k->type) {
141 case KEY_RSA:
142 nlen = BN_num_bytes(k->rsa->n);
143 elen = BN_num_bytes(k->rsa->e);
144 len = nlen + elen;
145 blob = xmalloc(len);
146 BN_bn2bin(k->rsa->n, blob);
147 BN_bn2bin(k->rsa->e, blob + nlen);
148 break;
149 case KEY_DSA:
150 dsa_make_key_blob(k, &blob, &len);
151 break;
152 default:
153 fatal("key_fingerprint: bad key type %d", k->type);
154 break;
155 }
156 if (blob != NULL) {
157 unsigned char d[16];
158 EVP_MD_CTX md;
159 EVP_DigestInit(&md, EVP_md5());
160 EVP_DigestUpdate(&md, blob, len);
161 EVP_DigestFinal(&md, d, NULL);
162 snprintf(retval, sizeof(retval), FPRINT,
163 d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
164 d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
165 memset(blob, 0, len);
166 xfree(blob);
167 }
168 return retval;
169}
170
171/*
172 * Reads a multiple-precision integer in decimal from the buffer, and advances
173 * the pointer. The integer must already be initialized. This function is
174 * permitted to modify the buffer. This leaves *cpp to point just beyond the
175 * last processed (and maybe modified) character. Note that this may modify
176 * the buffer containing the number.
177 */
178int
179read_bignum(char **cpp, BIGNUM * value)
180{
181 char *cp = *cpp;
182 int old;
183
184 /* Skip any leading whitespace. */
185 for (; *cp == ' ' || *cp == '\t'; cp++)
186 ;
187
188 /* Check that it begins with a decimal digit. */
189 if (*cp < '0' || *cp > '9')
190 return 0;
191
192 /* Save starting position. */
193 *cpp = cp;
194
195 /* Move forward until all decimal digits skipped. */
196 for (; *cp >= '0' && *cp <= '9'; cp++)
197 ;
198
199 /* Save the old terminating character, and replace it by \0. */
200 old = *cp;
201 *cp = 0;
202
203 /* Parse the number. */
204 if (BN_dec2bn(&value, *cpp) == 0)
205 return 0;
206
207 /* Restore old terminating character. */
208 *cp = old;
209
210 /* Move beyond the number and return success. */
211 *cpp = cp;
212 return 1;
213}
214int
215write_bignum(FILE *f, BIGNUM *num)
216{
217 char *buf = BN_bn2dec(num);
218 if (buf == NULL) {
219 error("write_bignum: BN_bn2dec() failed");
220 return 0;
221 }
222 fprintf(f, " %s", buf);
223 free(buf);
224 return 1;
225}
226unsigned int
227key_read(Key *ret, char **cpp)
228{
229 Key *k;
230 unsigned int bits = 0;
231 char *cp;
232 int len, n;
233 unsigned char *blob;
234
235 cp = *cpp;
236
237 switch(ret->type) {
238 case KEY_RSA:
239 /* Get number of bits. */
240 if (*cp < '0' || *cp > '9')
241 return 0; /* Bad bit count... */
242 for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
243 bits = 10 * bits + *cp - '0';
244 if (bits == 0)
245 return 0;
246 *cpp = cp;
247 /* Get public exponent, public modulus. */
248 if (!read_bignum(cpp, ret->rsa->e))
249 return 0;
250 if (!read_bignum(cpp, ret->rsa->n))
251 return 0;
252 break;
253 case KEY_DSA:
254 if (strncmp(cp, SSH_DSS " ", 7) != 0)
255 return 0;
256 cp += 7;
257 len = 2*strlen(cp);
258 blob = xmalloc(len);
259 n = uudecode(cp, blob, len);
260 if (n < 0) {
30 */
31/*
32 * read_bignum():
33 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
34 */
35
36#include "includes.h"
37#include "ssh.h"
38#include <openssl/rsa.h>
39#include <openssl/dsa.h>
40#include <openssl/evp.h>
41#include "xmalloc.h"
42#include "key.h"
43#include "dsa.h"
44#include "uuencode.h"
45
46#define SSH_DSS "ssh-dss"
47
48Key *
49key_new(int type)
50{
51 Key *k;
52 RSA *rsa;
53 DSA *dsa;
54 k = xmalloc(sizeof(*k));
55 k->type = type;
56 k->dsa = NULL;
57 k->rsa = NULL;
58 switch (k->type) {
59 case KEY_RSA:
60 rsa = RSA_new();
61 rsa->n = BN_new();
62 rsa->e = BN_new();
63 k->rsa = rsa;
64 break;
65 case KEY_DSA:
66 dsa = DSA_new();
67 dsa->p = BN_new();
68 dsa->q = BN_new();
69 dsa->g = BN_new();
70 dsa->pub_key = BN_new();
71 k->dsa = dsa;
72 break;
73 case KEY_EMPTY:
74 break;
75 default:
76 fatal("key_new: bad key type %d", k->type);
77 break;
78 }
79 return k;
80}
81void
82key_free(Key *k)
83{
84 switch (k->type) {
85 case KEY_RSA:
86 if (k->rsa != NULL)
87 RSA_free(k->rsa);
88 k->rsa = NULL;
89 break;
90 case KEY_DSA:
91 if (k->dsa != NULL)
92 DSA_free(k->dsa);
93 k->dsa = NULL;
94 break;
95 default:
96 fatal("key_free: bad key type %d", k->type);
97 break;
98 }
99 xfree(k);
100}
101int
102key_equal(Key *a, Key *b)
103{
104 if (a == NULL || b == NULL || a->type != b->type)
105 return 0;
106 switch (a->type) {
107 case KEY_RSA:
108 return a->rsa != NULL && b->rsa != NULL &&
109 BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
110 BN_cmp(a->rsa->n, b->rsa->n) == 0;
111 break;
112 case KEY_DSA:
113 return a->dsa != NULL && b->dsa != NULL &&
114 BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
115 BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
116 BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
117 BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
118 break;
119 default:
120 fatal("key_equal: bad key type %d", a->type);
121 break;
122 }
123 return 0;
124}
125
126#define FPRINT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
127
128/*
129 * Generate key fingerprint in ascii format.
130 * Based on ideas and code from Bjoern Groenvall <bg@sics.se>
131 */
132char *
133key_fingerprint(Key *k)
134{
135 static char retval[80];
136 unsigned char *blob = NULL;
137 int len = 0;
138 int nlen, elen;
139
140 switch (k->type) {
141 case KEY_RSA:
142 nlen = BN_num_bytes(k->rsa->n);
143 elen = BN_num_bytes(k->rsa->e);
144 len = nlen + elen;
145 blob = xmalloc(len);
146 BN_bn2bin(k->rsa->n, blob);
147 BN_bn2bin(k->rsa->e, blob + nlen);
148 break;
149 case KEY_DSA:
150 dsa_make_key_blob(k, &blob, &len);
151 break;
152 default:
153 fatal("key_fingerprint: bad key type %d", k->type);
154 break;
155 }
156 if (blob != NULL) {
157 unsigned char d[16];
158 EVP_MD_CTX md;
159 EVP_DigestInit(&md, EVP_md5());
160 EVP_DigestUpdate(&md, blob, len);
161 EVP_DigestFinal(&md, d, NULL);
162 snprintf(retval, sizeof(retval), FPRINT,
163 d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
164 d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
165 memset(blob, 0, len);
166 xfree(blob);
167 }
168 return retval;
169}
170
171/*
172 * Reads a multiple-precision integer in decimal from the buffer, and advances
173 * the pointer. The integer must already be initialized. This function is
174 * permitted to modify the buffer. This leaves *cpp to point just beyond the
175 * last processed (and maybe modified) character. Note that this may modify
176 * the buffer containing the number.
177 */
178int
179read_bignum(char **cpp, BIGNUM * value)
180{
181 char *cp = *cpp;
182 int old;
183
184 /* Skip any leading whitespace. */
185 for (; *cp == ' ' || *cp == '\t'; cp++)
186 ;
187
188 /* Check that it begins with a decimal digit. */
189 if (*cp < '0' || *cp > '9')
190 return 0;
191
192 /* Save starting position. */
193 *cpp = cp;
194
195 /* Move forward until all decimal digits skipped. */
196 for (; *cp >= '0' && *cp <= '9'; cp++)
197 ;
198
199 /* Save the old terminating character, and replace it by \0. */
200 old = *cp;
201 *cp = 0;
202
203 /* Parse the number. */
204 if (BN_dec2bn(&value, *cpp) == 0)
205 return 0;
206
207 /* Restore old terminating character. */
208 *cp = old;
209
210 /* Move beyond the number and return success. */
211 *cpp = cp;
212 return 1;
213}
214int
215write_bignum(FILE *f, BIGNUM *num)
216{
217 char *buf = BN_bn2dec(num);
218 if (buf == NULL) {
219 error("write_bignum: BN_bn2dec() failed");
220 return 0;
221 }
222 fprintf(f, " %s", buf);
223 free(buf);
224 return 1;
225}
226unsigned int
227key_read(Key *ret, char **cpp)
228{
229 Key *k;
230 unsigned int bits = 0;
231 char *cp;
232 int len, n;
233 unsigned char *blob;
234
235 cp = *cpp;
236
237 switch(ret->type) {
238 case KEY_RSA:
239 /* Get number of bits. */
240 if (*cp < '0' || *cp > '9')
241 return 0; /* Bad bit count... */
242 for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
243 bits = 10 * bits + *cp - '0';
244 if (bits == 0)
245 return 0;
246 *cpp = cp;
247 /* Get public exponent, public modulus. */
248 if (!read_bignum(cpp, ret->rsa->e))
249 return 0;
250 if (!read_bignum(cpp, ret->rsa->n))
251 return 0;
252 break;
253 case KEY_DSA:
254 if (strncmp(cp, SSH_DSS " ", 7) != 0)
255 return 0;
256 cp += 7;
257 len = 2*strlen(cp);
258 blob = xmalloc(len);
259 n = uudecode(cp, blob, len);
260 if (n < 0) {
261 error("uudecode %s failed", cp);
261 error("key_read: uudecode %s failed", cp);
262 return 0;
263 }
264 k = dsa_key_from_blob(blob, n);
262 return 0;
263 }
264 k = dsa_key_from_blob(blob, n);
265 if (k == NULL)
266 return 0;
265 if (k == NULL) {
266 error("key_read: dsa_key_from_blob %s failed", cp);
267 return 0;
268 }
267 xfree(blob);
268 if (ret->dsa != NULL)
269 DSA_free(ret->dsa);
270 ret->dsa = k->dsa;
271 k->dsa = NULL;
272 key_free(k);
273 bits = BN_num_bits(ret->dsa->p);
269 xfree(blob);
270 if (ret->dsa != NULL)
271 DSA_free(ret->dsa);
272 ret->dsa = k->dsa;
273 k->dsa = NULL;
274 key_free(k);
275 bits = BN_num_bits(ret->dsa->p);
274 cp = strchr(cp, '=');
275 if (cp == NULL)
276 return 0;
277 *cpp = cp + 1;
276 /* advance cp: skip whitespace and data */
277 while (*cp == ' ' || *cp == '\t')
278 cp++;
279 while (*cp != '\0' && *cp != ' ' && *cp != '\t')
280 cp++;
281 *cpp = cp;
278 break;
279 default:
280 fatal("key_read: bad key type: %d", ret->type);
281 break;
282 }
283 return bits;
284}
285int
286key_write(Key *key, FILE *f)
287{
288 int success = 0;
289 unsigned int bits = 0;
290
291 if (key->type == KEY_RSA && key->rsa != NULL) {
292 /* size of modulus 'n' */
293 bits = BN_num_bits(key->rsa->n);
294 fprintf(f, "%u", bits);
295 if (write_bignum(f, key->rsa->e) &&
296 write_bignum(f, key->rsa->n)) {
297 success = 1;
298 } else {
299 error("key_write: failed for RSA key");
300 }
301 } else if (key->type == KEY_DSA && key->dsa != NULL) {
302 int len, n;
303 unsigned char *blob, *uu;
304 dsa_make_key_blob(key, &blob, &len);
305 uu = xmalloc(2*len);
306 n = uuencode(blob, len, uu, 2*len);
307 if (n > 0) {
308 fprintf(f, "%s %s", SSH_DSS, uu);
309 success = 1;
310 }
311 xfree(blob);
312 xfree(uu);
313 }
314 return success;
315}
316char *
317key_type(Key *k)
318{
319 switch (k->type) {
320 case KEY_RSA:
321 return "RSA";
322 break;
323 case KEY_DSA:
324 return "DSA";
325 break;
326 }
327 return "unknown";
328}
282 break;
283 default:
284 fatal("key_read: bad key type: %d", ret->type);
285 break;
286 }
287 return bits;
288}
289int
290key_write(Key *key, FILE *f)
291{
292 int success = 0;
293 unsigned int bits = 0;
294
295 if (key->type == KEY_RSA && key->rsa != NULL) {
296 /* size of modulus 'n' */
297 bits = BN_num_bits(key->rsa->n);
298 fprintf(f, "%u", bits);
299 if (write_bignum(f, key->rsa->e) &&
300 write_bignum(f, key->rsa->n)) {
301 success = 1;
302 } else {
303 error("key_write: failed for RSA key");
304 }
305 } else if (key->type == KEY_DSA && key->dsa != NULL) {
306 int len, n;
307 unsigned char *blob, *uu;
308 dsa_make_key_blob(key, &blob, &len);
309 uu = xmalloc(2*len);
310 n = uuencode(blob, len, uu, 2*len);
311 if (n > 0) {
312 fprintf(f, "%s %s", SSH_DSS, uu);
313 success = 1;
314 }
315 xfree(blob);
316 xfree(uu);
317 }
318 return success;
319}
320char *
321key_type(Key *k)
322{
323 switch (k->type) {
324 case KEY_RSA:
325 return "RSA";
326 break;
327 case KEY_DSA:
328 return "DSA";
329 break;
330 }
331 return "unknown";
332}