]> andersk Git - openssh.git/blob - key.c
- Reduce diff against OpenBSD source
[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
42 Key *
43 key_new(int type)
44 {
45         Key *k;
46         RSA *rsa;
47         DSA *dsa;
48         k = xmalloc(sizeof(*k));
49         k->type = type;
50         switch (k->type) {
51         case KEY_RSA:
52                 rsa = RSA_new();
53                 rsa->n = BN_new();
54                 rsa->e = BN_new();
55                 k->rsa = rsa;
56                 break;
57         case KEY_DSA:
58                 dsa = DSA_new();
59                 dsa->p = BN_new();
60                 dsa->q = BN_new();
61                 dsa->g = BN_new();
62                 dsa->pub_key = BN_new();
63                 k->dsa = dsa;
64                 break;
65         case KEY_EMPTY:
66                 k->dsa = NULL;
67                 k->rsa = NULL;
68                 break;
69         default:
70                 fatal("key_new: bad key type %d", k->type);
71                 break;
72         }
73         return k;
74 }
75 void
76 key_free(Key *k)
77 {
78         switch (k->type) {
79         case KEY_RSA:
80                 if (k->rsa != NULL)
81                         RSA_free(k->rsa);
82                 k->rsa = NULL;
83                 break;
84         case KEY_DSA:
85                 if (k->dsa != NULL)
86                         DSA_free(k->dsa);
87                 k->dsa = NULL;
88                 break;
89         default:
90                 fatal("key_free: bad key type %d", k->type);
91                 break;
92         }
93         xfree(k);
94 }
95 int
96 key_equal(Key *a, Key *b)
97 {
98         if (a == NULL || b == NULL || a->type != b->type)
99                 return 0;
100         switch (a->type) {
101         case KEY_RSA:
102                 return a->rsa != NULL && b->rsa != NULL &&
103                     BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
104                     BN_cmp(a->rsa->n, b->rsa->n) == 0;
105                 break;
106         case KEY_DSA:
107                 return a->dsa != NULL && b->dsa != NULL &&
108                     BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
109                     BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
110                     BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
111                     BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
112                 break;
113         default:
114                 fatal("key_free: bad key type %d", a->type);
115                 break;
116         }
117         return 0;
118 }
119
120 #define FPRINT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
121
122 /*
123  * Generate key fingerprint in ascii format.
124  * Based on ideas and code from Bjoern Groenvall <bg@sics.se>
125  */
126 char *
127 key_fingerprint(Key *k)
128 {
129         static char retval[80];
130         unsigned char *buf = NULL;
131         int len = 0;
132         int nlen, elen, plen, qlen, glen, publen;
133
134         switch (k->type) {
135         case KEY_RSA:
136                 nlen = BN_num_bytes(k->rsa->n);
137                 elen = BN_num_bytes(k->rsa->e);
138                 len = nlen + elen;
139                 buf = xmalloc(len);
140                 BN_bn2bin(k->rsa->n, buf);
141                 BN_bn2bin(k->rsa->e, buf + nlen);
142                 break;
143         case KEY_DSA:
144                 plen = BN_num_bytes(k->dsa->p);
145                 qlen = BN_num_bytes(k->dsa->q);
146                 glen = BN_num_bytes(k->dsa->g);
147                 publen = BN_num_bytes(k->dsa->pub_key);
148                 len = qlen + qlen + glen + publen;
149                 buf = xmalloc(len);
150                 BN_bn2bin(k->dsa->p, buf);
151                 BN_bn2bin(k->dsa->q, buf + plen);
152                 BN_bn2bin(k->dsa->g, buf + plen + qlen);
153                 BN_bn2bin(k->dsa->pub_key , buf + plen + qlen + glen);
154                 break;
155         default:
156                 fatal("key_fingerprint: bad key type %d", k->type);
157                 break;
158         }
159         if (buf != NULL) {
160                 unsigned char d[16];
161                 EVP_MD_CTX md;
162                 EVP_DigestInit(&md, EVP_md5());
163                 EVP_DigestUpdate(&md, buf, len);
164                 EVP_DigestFinal(&md, d, NULL);
165                 snprintf(retval, sizeof(retval), FPRINT,
166                     d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
167                     d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
168                 memset(buf, 0, len);
169                 xfree(buf);
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 int
230 key_read(Key *ret, unsigned int bits, char **cpp)
231 {
232         switch(ret->type) {
233         case KEY_RSA:
234                 if (bits == 0)
235                         return 0;
236                 /* Get public exponent, public modulus. */
237                 if (!read_bignum(cpp, ret->rsa->e))
238                         return 0;
239                 if (!read_bignum(cpp, ret->rsa->n))
240                         return 0;
241                 break;
242         case KEY_DSA:
243                 if (bits != 0)
244                         return 0;
245                 if (!read_bignum(cpp, ret->dsa->p))
246                         return 0;
247                 if (!read_bignum(cpp, ret->dsa->q))
248                         return 0;
249                 if (!read_bignum(cpp, ret->dsa->g))
250                         return 0;
251                 if (!read_bignum(cpp, ret->dsa->pub_key))
252                         return 0;
253                 break;
254         default:
255                 fatal("bad key type: %d", ret->type);
256                 break;
257         }
258         return 1;
259 }
260 int
261 key_write(Key *key, FILE *f)
262 {
263         int success = 0;
264         unsigned int bits = 0;
265
266         if (key->type == KEY_RSA && key->rsa != NULL) {
267                 /* size of modulus 'n' */
268                 bits = BN_num_bits(key->rsa->n);
269                 fprintf(f, "%u", bits);
270                 if (write_bignum(f, key->rsa->e) &&
271                     write_bignum(f, key->rsa->n)) {
272                         success = 1;
273                 } else {
274                         error("key_write: failed for RSA key");
275                 }
276         } else if (key->type == KEY_DSA && key->dsa != NULL) {
277                 /* bits == 0 means DSA key */
278                 bits = 0;
279                 fprintf(f, "%u", bits);
280                 if (write_bignum(f, key->dsa->p) &&
281                     write_bignum(f, key->dsa->q) &&
282                     write_bignum(f, key->dsa->g) &&
283                     write_bignum(f, key->dsa->pub_key)) {
284                         success = 1;
285                 } else {
286                         error("key_write: failed for DSA key");
287                 }
288         }
289         return success;
290 }
This page took 0.36113 seconds and 5 git commands to generate.