Annotation of src/usr.bin/ssh/key.c, Revision 1.5
1.1 markus 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: /*
30: * read_bignum():
31: * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
32: */
33:
34: #include "includes.h"
35: #include "ssh.h"
1.2 markus 36: #include <openssl/rsa.h>
37: #include <openssl/dsa.h>
38: #include <openssl/evp.h>
1.1 markus 39: #include "xmalloc.h"
40: #include "key.h"
1.3 markus 41: #include "dsa.h"
42: #include "uuencode.h"
43:
44: #define SSH_DSS "ssh-dss"
1.1 markus 45:
46: Key *
47: key_new(int type)
48: {
49: Key *k;
50: RSA *rsa;
51: DSA *dsa;
52: k = xmalloc(sizeof(*k));
53: k->type = type;
1.3 markus 54: k->dsa = NULL;
55: k->rsa = NULL;
1.1 markus 56: switch (k->type) {
57: case KEY_RSA:
58: rsa = RSA_new();
59: rsa->n = BN_new();
60: rsa->e = BN_new();
61: k->rsa = rsa;
62: break;
63: case KEY_DSA:
64: dsa = DSA_new();
65: dsa->p = BN_new();
66: dsa->q = BN_new();
67: dsa->g = BN_new();
68: dsa->pub_key = BN_new();
69: k->dsa = dsa;
70: break;
71: case KEY_EMPTY:
72: break;
73: default:
74: fatal("key_new: bad key type %d", k->type);
75: break;
76: }
77: return k;
78: }
79: void
80: key_free(Key *k)
81: {
82: switch (k->type) {
83: case KEY_RSA:
84: if (k->rsa != NULL)
85: RSA_free(k->rsa);
86: k->rsa = NULL;
87: break;
88: case KEY_DSA:
89: if (k->dsa != NULL)
90: DSA_free(k->dsa);
91: k->dsa = NULL;
92: break;
93: default:
94: fatal("key_free: bad key type %d", k->type);
95: break;
96: }
97: xfree(k);
98: }
99: int
100: key_equal(Key *a, Key *b)
101: {
102: if (a == NULL || b == NULL || a->type != b->type)
103: return 0;
104: switch (a->type) {
105: case KEY_RSA:
106: return a->rsa != NULL && b->rsa != NULL &&
107: BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
108: BN_cmp(a->rsa->n, b->rsa->n) == 0;
109: break;
110: case KEY_DSA:
111: return a->dsa != NULL && b->dsa != NULL &&
112: BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
113: BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
114: BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
115: BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
116: break;
117: default:
1.3 markus 118: fatal("key_equal: bad key type %d", a->type);
1.1 markus 119: break;
120: }
121: return 0;
122: }
123:
124: #define FPRINT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
125:
126: /*
127: * Generate key fingerprint in ascii format.
128: * Based on ideas and code from Bjoern Groenvall <bg@sics.se>
129: */
130: char *
131: key_fingerprint(Key *k)
132: {
133: static char retval[80];
1.3 markus 134: unsigned char *blob = NULL;
1.1 markus 135: int len = 0;
1.3 markus 136: int nlen, elen;
1.1 markus 137:
138: switch (k->type) {
139: case KEY_RSA:
140: nlen = BN_num_bytes(k->rsa->n);
141: elen = BN_num_bytes(k->rsa->e);
142: len = nlen + elen;
1.3 markus 143: blob = xmalloc(len);
144: BN_bn2bin(k->rsa->n, blob);
145: BN_bn2bin(k->rsa->e, blob + nlen);
1.1 markus 146: break;
147: case KEY_DSA:
1.3 markus 148: dsa_make_key_blob(k, &blob, &len);
1.1 markus 149: break;
150: default:
151: fatal("key_fingerprint: bad key type %d", k->type);
152: break;
153: }
1.3 markus 154: if (blob != NULL) {
1.1 markus 155: unsigned char d[16];
156: EVP_MD_CTX md;
157: EVP_DigestInit(&md, EVP_md5());
1.3 markus 158: EVP_DigestUpdate(&md, blob, len);
1.1 markus 159: EVP_DigestFinal(&md, d, NULL);
160: snprintf(retval, sizeof(retval), FPRINT,
161: d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
162: d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
1.3 markus 163: memset(blob, 0, len);
164: xfree(blob);
1.1 markus 165: }
166: return retval;
167: }
168:
169: /*
170: * Reads a multiple-precision integer in decimal from the buffer, and advances
171: * the pointer. The integer must already be initialized. This function is
172: * permitted to modify the buffer. This leaves *cpp to point just beyond the
173: * last processed (and maybe modified) character. Note that this may modify
174: * the buffer containing the number.
175: */
176: int
177: read_bignum(char **cpp, BIGNUM * value)
178: {
179: char *cp = *cpp;
180: int old;
181:
182: /* Skip any leading whitespace. */
183: for (; *cp == ' ' || *cp == '\t'; cp++)
184: ;
185:
186: /* Check that it begins with a decimal digit. */
187: if (*cp < '0' || *cp > '9')
188: return 0;
189:
190: /* Save starting position. */
191: *cpp = cp;
192:
193: /* Move forward until all decimal digits skipped. */
194: for (; *cp >= '0' && *cp <= '9'; cp++)
195: ;
196:
197: /* Save the old terminating character, and replace it by \0. */
198: old = *cp;
199: *cp = 0;
200:
201: /* Parse the number. */
202: if (BN_dec2bn(&value, *cpp) == 0)
203: return 0;
204:
205: /* Restore old terminating character. */
206: *cp = old;
207:
208: /* Move beyond the number and return success. */
209: *cpp = cp;
210: return 1;
211: }
212: int
213: write_bignum(FILE *f, BIGNUM *num)
214: {
215: char *buf = BN_bn2dec(num);
216: if (buf == NULL) {
217: error("write_bignum: BN_bn2dec() failed");
218: return 0;
219: }
220: fprintf(f, " %s", buf);
221: free(buf);
222: return 1;
223: }
1.3 markus 224: unsigned int
225: key_read(Key *ret, char **cpp)
1.1 markus 226: {
1.3 markus 227: Key *k;
228: unsigned int bits = 0;
229: char *cp;
230: int len, n;
231: unsigned char *blob;
232:
233: cp = *cpp;
234:
1.1 markus 235: switch(ret->type) {
236: case KEY_RSA:
1.3 markus 237: /* Get number of bits. */
238: if (*cp < '0' || *cp > '9')
239: return 0; /* Bad bit count... */
240: for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
241: bits = 10 * bits + *cp - '0';
1.1 markus 242: if (bits == 0)
243: return 0;
1.3 markus 244: *cpp = cp;
1.1 markus 245: /* Get public exponent, public modulus. */
246: if (!read_bignum(cpp, ret->rsa->e))
247: return 0;
248: if (!read_bignum(cpp, ret->rsa->n))
249: return 0;
250: break;
251: case KEY_DSA:
1.3 markus 252: if (strncmp(cp, SSH_DSS " ", 7) != 0)
1.1 markus 253: return 0;
1.3 markus 254: cp += 7;
255: len = 2*strlen(cp);
256: blob = xmalloc(len);
257: n = uudecode(cp, blob, len);
258: k = dsa_key_from_blob(blob, n);
259: if (k == NULL)
260: return 0;
261: xfree(blob);
262: if (ret->dsa != NULL)
263: DSA_free(ret->dsa);
264: ret->dsa = k->dsa;
265: k->dsa = NULL;
266: key_free(k);
267: bits = BN_num_bits(ret->dsa->p);
268: cp = strchr(cp, '=');
269: if (cp == NULL)
1.1 markus 270: return 0;
1.3 markus 271: *cpp = cp + 1;
1.1 markus 272: break;
273: default:
1.3 markus 274: fatal("key_read: bad key type: %d", ret->type);
1.1 markus 275: break;
276: }
1.3 markus 277: return bits;
1.1 markus 278: }
279: int
280: key_write(Key *key, FILE *f)
281: {
282: int success = 0;
283: unsigned int bits = 0;
284:
285: if (key->type == KEY_RSA && key->rsa != NULL) {
286: /* size of modulus 'n' */
287: bits = BN_num_bits(key->rsa->n);
288: fprintf(f, "%u", bits);
289: if (write_bignum(f, key->rsa->e) &&
290: write_bignum(f, key->rsa->n)) {
291: success = 1;
292: } else {
293: error("key_write: failed for RSA key");
294: }
295: } else if (key->type == KEY_DSA && key->dsa != NULL) {
1.3 markus 296: int len, n;
297: unsigned char *blob, *uu;
298: dsa_make_key_blob(key, &blob, &len);
299: uu = xmalloc(2*len);
1.5 ! markus 300: n = uuencode(blob, len, uu, 2*len);
! 301: if (n > 0) {
! 302: fprintf(f, "%s %s", SSH_DSS, uu);
! 303: success = 1;
! 304: }
1.3 markus 305: xfree(blob);
306: xfree(uu);
1.1 markus 307: }
308: return success;
309: }
1.4 markus 310: char *
311: key_type(Key *k)
312: {
313: switch (k->type) {
314: case KEY_RSA:
315: return "RSA";
316: break;
317: case KEY_DSA:
318: return "DSA";
319: break;
320: }
321: return "unknown";
322: }