]> andersk Git - openssh.git/blob - key.c
Up ver
[openssh.git] / key.c
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"
36 #include <openssl/rsa.h>
37 #include <openssl/dsa.h>
38 #include <openssl/evp.h>
39 #include "xmalloc.h"
40 #include "key.h"
41 #include "dsa.h"
42 #include "uuencode.h"
43
44 #define SSH_DSS "ssh-dss"
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;
54         k->dsa = NULL;
55         k->rsa = NULL;
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:
118                 fatal("key_equal: bad key type %d", a->type);
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];
134         unsigned char *blob = NULL;
135         int len = 0;
136         int nlen, elen;
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;
143                 blob = xmalloc(len);
144                 BN_bn2bin(k->rsa->n, blob);
145                 BN_bn2bin(k->rsa->e, blob + nlen);
146                 break;
147         case KEY_DSA:
148                 dsa_make_key_blob(k, &blob, &len);
149                 break;
150         default:
151                 fatal("key_fingerprint: bad key type %d", k->type);
152                 break;
153         }
154         if (blob != NULL) {
155                 unsigned char d[16];
156                 EVP_MD_CTX md;
157                 EVP_DigestInit(&md, EVP_md5());
158                 EVP_DigestUpdate(&md, blob, len);
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]);
163                 memset(blob, 0, len);
164                 xfree(blob);
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 }
224 unsigned int
225 key_read(Key *ret, char **cpp)
226 {
227         Key *k;
228         unsigned int bits = 0;
229         char *cp;
230         int len, n;
231         unsigned char *blob;
232
233         cp = *cpp;
234
235         switch(ret->type) {
236         case KEY_RSA:
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';
242                 if (bits == 0)
243                         return 0;
244                 *cpp = cp;
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:
252                 if (strncmp(cp, SSH_DSS " ", 7) != 0)
253                         return 0;
254                 cp += 7;
255                 len = 2*strlen(cp);
256                 blob = xmalloc(len);
257                 n = uudecode(cp, blob, len);
258                 if (n < 0) {
259                         error("uudecode %s failed", cp);
260                         return 0;
261                 }
262                 k = dsa_key_from_blob(blob, n);
263                 if (k == NULL)
264                          return 0;
265                 xfree(blob);
266                 if (ret->dsa != NULL)
267                         DSA_free(ret->dsa);
268                 ret->dsa = k->dsa;
269                 k->dsa = NULL;
270                 key_free(k);
271                 bits = BN_num_bits(ret->dsa->p);
272                 cp = strchr(cp, '=');
273                 if (cp == NULL)
274                         return 0;
275                 *cpp = cp + 1;
276                 break;
277         default:
278                 fatal("key_read: bad key type: %d", ret->type);
279                 break;
280         }
281         return bits;
282 }
283 int
284 key_write(Key *key, FILE *f)
285 {
286         int success = 0;
287         unsigned int bits = 0;
288
289         if (key->type == KEY_RSA && key->rsa != NULL) {
290                 /* size of modulus 'n' */
291                 bits = BN_num_bits(key->rsa->n);
292                 fprintf(f, "%u", bits);
293                 if (write_bignum(f, key->rsa->e) &&
294                     write_bignum(f, key->rsa->n)) {
295                         success = 1;
296                 } else {
297                         error("key_write: failed for RSA key");
298                 }
299         } else if (key->type == KEY_DSA && key->dsa != NULL) {
300                 int len, n;
301                 unsigned char *blob, *uu;
302                 dsa_make_key_blob(key, &blob, &len);
303                 uu = xmalloc(2*len);
304                 n = uuencode(blob, len, uu, 2*len);
305                 if (n > 0) {
306                         fprintf(f, "%s %s", SSH_DSS, uu);
307                         success = 1;
308                 }
309                 xfree(blob);
310                 xfree(uu);
311         }
312         return success;
313 }
314 char *
315 key_type(Key *k)
316 {
317         switch (k->type) {
318         case KEY_RSA:
319                 return "RSA";
320                 break;
321         case KEY_DSA:
322                 return "DSA";
323                 break;
324         }
325         return "unknown";
326 }
This page took 0.056799 seconds and 5 git commands to generate.