]> andersk Git - openssh.git/blob - key.c
be38a88f5e6c4ef7cc312fa75defb319298cf36d
[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 /*
125  * Generate key fingerprint in ascii format.
126  * Based on ideas and code from Bjoern Groenvall <bg@sics.se>
127  */
128 char *
129 key_fingerprint(Key *k)
130 {
131         static char retval[(EVP_MAX_MD_SIZE+1)*3];
132         unsigned char *blob = NULL;
133         int len = 0;
134         int nlen, elen;
135
136         switch (k->type) {
137         case KEY_RSA:
138                 nlen = BN_num_bytes(k->rsa->n);
139                 elen = BN_num_bytes(k->rsa->e);
140                 len = nlen + elen;
141                 blob = xmalloc(len);
142                 BN_bn2bin(k->rsa->n, blob);
143                 BN_bn2bin(k->rsa->e, blob + nlen);
144                 break;
145         case KEY_DSA:
146                 dsa_make_key_blob(k, &blob, &len);
147                 break;
148         default:
149                 fatal("key_fingerprint: bad key type %d", k->type);
150                 break;
151         }
152         retval[0] = '\0';
153
154         if (blob != NULL) {
155                 int i;
156                 unsigned char digest[EVP_MAX_MD_SIZE];
157                 EVP_MD *md = EVP_md5();
158                 EVP_MD_CTX ctx;
159                 EVP_DigestInit(&ctx, md);
160                 EVP_DigestUpdate(&ctx, blob, len);
161                 EVP_DigestFinal(&ctx, digest, NULL);
162                 for(i = 0; i < md->md_size; i++) {
163                         char hex[4];
164                         snprintf(hex, sizeof(hex), "%02x:", digest[i]);
165                         strlcat(retval, hex, sizeof(retval));
166                 }
167                 retval[strlen(retval) - 1] = '\0';
168                 memset(blob, 0, len);
169                 xfree(blob);
170         }
171         return retval;
172 }
173
174 /*
175  * Reads a multiple-precision integer in decimal from the buffer, and advances
176  * the pointer.  The integer must already be initialized.  This function is
177  * permitted to modify the buffer.  This leaves *cpp to point just beyond the
178  * last processed (and maybe modified) character.  Note that this may modify
179  * the buffer containing the number.
180  */
181 int
182 read_bignum(char **cpp, BIGNUM * value)
183 {
184         char *cp = *cpp;
185         int old;
186
187         /* Skip any leading whitespace. */
188         for (; *cp == ' ' || *cp == '\t'; cp++)
189                 ;
190
191         /* Check that it begins with a decimal digit. */
192         if (*cp < '0' || *cp > '9')
193                 return 0;
194
195         /* Save starting position. */
196         *cpp = cp;
197
198         /* Move forward until all decimal digits skipped. */
199         for (; *cp >= '0' && *cp <= '9'; cp++)
200                 ;
201
202         /* Save the old terminating character, and replace it by \0. */
203         old = *cp;
204         *cp = 0;
205
206         /* Parse the number. */
207         if (BN_dec2bn(&value, *cpp) == 0)
208                 return 0;
209
210         /* Restore old terminating character. */
211         *cp = old;
212
213         /* Move beyond the number and return success. */
214         *cpp = cp;
215         return 1;
216 }
217 int
218 write_bignum(FILE *f, BIGNUM *num)
219 {
220         char *buf = BN_bn2dec(num);
221         if (buf == NULL) {
222                 error("write_bignum: BN_bn2dec() failed");
223                 return 0;
224         }
225         fprintf(f, " %s", buf);
226         free(buf);
227         return 1;
228 }
229 unsigned int
230 key_read(Key *ret, char **cpp)
231 {
232         Key *k;
233         unsigned int bits = 0;
234         char *cp;
235         int len, n;
236         unsigned char *blob;
237
238         cp = *cpp;
239
240         switch(ret->type) {
241         case KEY_RSA:
242                 /* Get number of bits. */
243                 if (*cp < '0' || *cp > '9')
244                         return 0;       /* Bad bit count... */
245                 for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
246                         bits = 10 * bits + *cp - '0';
247                 if (bits == 0)
248                         return 0;
249                 *cpp = cp;
250                 /* Get public exponent, public modulus. */
251                 if (!read_bignum(cpp, ret->rsa->e))
252                         return 0;
253                 if (!read_bignum(cpp, ret->rsa->n))
254                         return 0;
255                 break;
256         case KEY_DSA:
257                 if (strncmp(cp, SSH_DSS " ", 7) != 0)
258                         return 0;
259                 cp += 7;
260                 len = 2*strlen(cp);
261                 blob = xmalloc(len);
262                 n = uudecode(cp, blob, len);
263                 if (n < 0) {
264                         error("key_read: uudecode %s failed", cp);
265                         return 0;
266                 }
267                 k = dsa_key_from_blob(blob, n);
268                 if (k == NULL) {
269                         error("key_read: dsa_key_from_blob %s failed", cp);
270                         return 0;
271                 }
272                 xfree(blob);
273                 if (ret->dsa != NULL)
274                         DSA_free(ret->dsa);
275                 ret->dsa = k->dsa;
276                 k->dsa = NULL;
277                 key_free(k);
278                 bits = BN_num_bits(ret->dsa->p);
279                 /* advance cp: skip whitespace and data */
280                 while (*cp == ' ' || *cp == '\t')
281                         cp++;
282                 while (*cp != '\0' && *cp != ' ' && *cp != '\t')
283                         cp++;
284                 *cpp = cp;
285                 break;
286         default:
287                 fatal("key_read: bad key type: %d", ret->type);
288                 break;
289         }
290         return bits;
291 }
292 int
293 key_write(Key *key, FILE *f)
294 {
295         int success = 0;
296         unsigned int bits = 0;
297
298         if (key->type == KEY_RSA && key->rsa != NULL) {
299                 /* size of modulus 'n' */
300                 bits = BN_num_bits(key->rsa->n);
301                 fprintf(f, "%u", bits);
302                 if (write_bignum(f, key->rsa->e) &&
303                     write_bignum(f, key->rsa->n)) {
304                         success = 1;
305                 } else {
306                         error("key_write: failed for RSA key");
307                 }
308         } else if (key->type == KEY_DSA && key->dsa != NULL) {
309                 int len, n;
310                 unsigned char *blob, *uu;
311                 dsa_make_key_blob(key, &blob, &len);
312                 uu = xmalloc(2*len);
313                 n = uuencode(blob, len, uu, 2*len);
314                 if (n > 0) {
315                         fprintf(f, "%s %s", SSH_DSS, uu);
316                         success = 1;
317                 }
318                 xfree(blob);
319                 xfree(uu);
320         }
321         return success;
322 }
323 char *
324 key_type(Key *k)
325 {
326         switch (k->type) {
327         case KEY_RSA:
328                 return "RSA";
329                 break;
330         case KEY_DSA:
331                 return "DSA";
332                 break;
333         }
334         return "unknown";
335 }
This page took 0.049866 seconds and 3 git commands to generate.