blob: 842280a9f66b12a351c6f79f1360f6b0dade0d1a [file] [log] [blame]
Damien Millereb8b60e2010-08-31 22:41:14 +10001/* $OpenBSD: key.c,v 1.92 2010/08/31 11:54:45 djm Exp $ */
Damien Miller450a7a12000-03-26 13:04:51 +10002/*
Damien Millere4340be2000-09-16 13:29:08 +11003 * read_bignum():
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 *
6 * As far as I am concerned, the code I have written for this software
7 * can be used freely for any purpose. Any derived versions of this
8 * software must be clearly marked as such, and if the derived work is
9 * incompatible with the protocol description in the RFC file, it must be
10 * called by a name other than "ssh" or "Secure Shell".
11 *
12 *
Ben Lindstrom44697232001-07-04 03:32:30 +000013 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
Darren Tucker0f0ef0a2008-06-13 08:58:05 +100014 * Copyright (c) 2008 Alexander von Gernler. All rights reserved.
Damien Miller450a7a12000-03-26 13:04:51 +100015 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
Damien Miller450a7a12000-03-26 13:04:51 +100024 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
Damien Millerd7834352006-08-05 12:39:39 +100036
Damien Miller450a7a12000-03-26 13:04:51 +100037#include "includes.h"
Ben Lindstrom226cfa02001-01-22 05:34:40 +000038
Darren Tucker9c16ac92008-06-13 04:40:35 +100039#include <sys/param.h>
Damien Millerd7834352006-08-05 12:39:39 +100040#include <sys/types.h>
41
Damien Miller450a7a12000-03-26 13:04:51 +100042#include <openssl/evp.h>
Darren Tucker3d295a62008-02-28 19:22:04 +110043#include <openbsd-compat/openssl-compat.h>
Ben Lindstrom226cfa02001-01-22 05:34:40 +000044
Damien Millerded319c2006-09-01 15:38:36 +100045#include <stdarg.h>
Damien Millera7a73ee2006-08-05 11:37:59 +100046#include <stdio.h>
Damien Millere3476ed2006-07-24 14:13:33 +100047#include <string.h>
48
Damien Miller450a7a12000-03-26 13:04:51 +100049#include "xmalloc.h"
50#include "key.h"
Damien Miller0bc1bd82000-11-13 22:57:25 +110051#include "rsa.h"
Damien Millereba71ba2000-04-29 23:57:08 +100052#include "uuencode.h"
Damien Miller0bc1bd82000-11-13 22:57:25 +110053#include "buffer.h"
Ben Lindstrom226cfa02001-01-22 05:34:40 +000054#include "log.h"
Damien Miller8a0268f2010-07-16 13:57:51 +100055#include "misc.h"
Damien Miller0a80ca12010-02-27 07:55:05 +110056#include "ssh2.h"
57
58static struct KeyCert *
59cert_new(void)
60{
61 struct KeyCert *cert;
62
63 cert = xcalloc(1, sizeof(*cert));
64 buffer_init(&cert->certblob);
Damien Miller4e270b02010-04-16 15:56:21 +100065 buffer_init(&cert->critical);
66 buffer_init(&cert->extensions);
Damien Miller0a80ca12010-02-27 07:55:05 +110067 cert->key_id = NULL;
68 cert->principals = NULL;
69 cert->signature_key = NULL;
70 return cert;
71}
Damien Miller450a7a12000-03-26 13:04:51 +100072
73Key *
74key_new(int type)
75{
76 Key *k;
77 RSA *rsa;
78 DSA *dsa;
Damien Miller07d86be2006-03-26 14:19:21 +110079 k = xcalloc(1, sizeof(*k));
Damien Miller450a7a12000-03-26 13:04:51 +100080 k->type = type;
Damien Millereb8b60e2010-08-31 22:41:14 +100081 k->ecdsa = NULL;
82 k->ecdsa_nid = -1;
Damien Millereba71ba2000-04-29 23:57:08 +100083 k->dsa = NULL;
84 k->rsa = NULL;
Damien Miller0a80ca12010-02-27 07:55:05 +110085 k->cert = NULL;
Damien Miller450a7a12000-03-26 13:04:51 +100086 switch (k->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +110087 case KEY_RSA1:
Damien Miller450a7a12000-03-26 13:04:51 +100088 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +100089 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +110090 case KEY_RSA_CERT:
Damien Millerda755162002-01-22 23:09:22 +110091 if ((rsa = RSA_new()) == NULL)
92 fatal("key_new: RSA_new failed");
93 if ((rsa->n = BN_new()) == NULL)
94 fatal("key_new: BN_new failed");
95 if ((rsa->e = BN_new()) == NULL)
96 fatal("key_new: BN_new failed");
Damien Miller450a7a12000-03-26 13:04:51 +100097 k->rsa = rsa;
98 break;
99 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000100 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100101 case KEY_DSA_CERT:
Damien Millerda755162002-01-22 23:09:22 +1100102 if ((dsa = DSA_new()) == NULL)
103 fatal("key_new: DSA_new failed");
104 if ((dsa->p = BN_new()) == NULL)
105 fatal("key_new: BN_new failed");
106 if ((dsa->q = BN_new()) == NULL)
107 fatal("key_new: BN_new failed");
108 if ((dsa->g = BN_new()) == NULL)
109 fatal("key_new: BN_new failed");
110 if ((dsa->pub_key = BN_new()) == NULL)
111 fatal("key_new: BN_new failed");
Damien Miller450a7a12000-03-26 13:04:51 +1000112 k->dsa = dsa;
113 break;
Damien Millereb8b60e2010-08-31 22:41:14 +1000114 case KEY_ECDSA:
115 case KEY_ECDSA_CERT:
116 /* Cannot do anything until we know the group */
117 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100118 case KEY_UNSPEC:
Damien Miller450a7a12000-03-26 13:04:51 +1000119 break;
120 default:
121 fatal("key_new: bad key type %d", k->type);
122 break;
123 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100124
125 if (key_is_cert(k))
126 k->cert = cert_new();
127
Damien Miller450a7a12000-03-26 13:04:51 +1000128 return k;
129}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000130
Damien Miller0a80ca12010-02-27 07:55:05 +1100131void
132key_add_private(Key *k)
Damien Miller0bc1bd82000-11-13 22:57:25 +1100133{
Damien Miller0bc1bd82000-11-13 22:57:25 +1100134 switch (k->type) {
135 case KEY_RSA1:
136 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000137 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100138 case KEY_RSA_CERT:
Damien Millerda755162002-01-22 23:09:22 +1100139 if ((k->rsa->d = BN_new()) == NULL)
140 fatal("key_new_private: BN_new failed");
141 if ((k->rsa->iqmp = BN_new()) == NULL)
142 fatal("key_new_private: BN_new failed");
143 if ((k->rsa->q = BN_new()) == NULL)
144 fatal("key_new_private: BN_new failed");
145 if ((k->rsa->p = BN_new()) == NULL)
146 fatal("key_new_private: BN_new failed");
147 if ((k->rsa->dmq1 = BN_new()) == NULL)
148 fatal("key_new_private: BN_new failed");
149 if ((k->rsa->dmp1 = BN_new()) == NULL)
150 fatal("key_new_private: BN_new failed");
Damien Miller0bc1bd82000-11-13 22:57:25 +1100151 break;
152 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000153 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100154 case KEY_DSA_CERT:
Damien Millerda755162002-01-22 23:09:22 +1100155 if ((k->dsa->priv_key = BN_new()) == NULL)
156 fatal("key_new_private: BN_new failed");
Damien Miller0bc1bd82000-11-13 22:57:25 +1100157 break;
Damien Millereb8b60e2010-08-31 22:41:14 +1000158 case KEY_ECDSA:
159 case KEY_ECDSA_CERT:
160 /* Cannot do anything until we know the group */
161 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100162 case KEY_UNSPEC:
163 break;
164 default:
165 break;
166 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100167}
168
169Key *
170key_new_private(int type)
171{
172 Key *k = key_new(type);
173
174 key_add_private(k);
Damien Miller0bc1bd82000-11-13 22:57:25 +1100175 return k;
176}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000177
Damien Miller0a80ca12010-02-27 07:55:05 +1100178static void
179cert_free(struct KeyCert *cert)
180{
181 u_int i;
182
183 buffer_free(&cert->certblob);
Damien Miller4e270b02010-04-16 15:56:21 +1000184 buffer_free(&cert->critical);
185 buffer_free(&cert->extensions);
Damien Miller0a80ca12010-02-27 07:55:05 +1100186 if (cert->key_id != NULL)
187 xfree(cert->key_id);
188 for (i = 0; i < cert->nprincipals; i++)
189 xfree(cert->principals[i]);
190 if (cert->principals != NULL)
191 xfree(cert->principals);
192 if (cert->signature_key != NULL)
193 key_free(cert->signature_key);
194}
195
Damien Miller450a7a12000-03-26 13:04:51 +1000196void
197key_free(Key *k)
198{
Damien Miller429fcc22006-03-26 14:02:16 +1100199 if (k == NULL)
Damien Millerbbaad772006-03-26 14:03:03 +1100200 fatal("key_free: key is NULL");
Damien Miller450a7a12000-03-26 13:04:51 +1000201 switch (k->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100202 case KEY_RSA1:
Damien Miller450a7a12000-03-26 13:04:51 +1000203 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000204 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100205 case KEY_RSA_CERT:
Damien Miller450a7a12000-03-26 13:04:51 +1000206 if (k->rsa != NULL)
207 RSA_free(k->rsa);
208 k->rsa = NULL;
209 break;
210 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000211 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100212 case KEY_DSA_CERT:
Damien Miller450a7a12000-03-26 13:04:51 +1000213 if (k->dsa != NULL)
214 DSA_free(k->dsa);
215 k->dsa = NULL;
216 break;
Damien Millereb8b60e2010-08-31 22:41:14 +1000217 case KEY_ECDSA:
218 case KEY_ECDSA_CERT:
219 if (k->ecdsa != NULL)
220 EC_KEY_free(k->ecdsa);
221 k->ecdsa = NULL;
222 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100223 case KEY_UNSPEC:
224 break;
Damien Miller450a7a12000-03-26 13:04:51 +1000225 default:
226 fatal("key_free: bad key type %d", k->type);
227 break;
228 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100229 if (key_is_cert(k)) {
230 if (k->cert != NULL)
231 cert_free(k->cert);
232 k->cert = NULL;
233 }
234
Damien Miller450a7a12000-03-26 13:04:51 +1000235 xfree(k);
236}
Damien Millerf58b58c2003-11-17 21:18:23 +1100237
Damien Miller0a80ca12010-02-27 07:55:05 +1100238static int
239cert_compare(struct KeyCert *a, struct KeyCert *b)
Damien Miller450a7a12000-03-26 13:04:51 +1000240{
Damien Miller0a80ca12010-02-27 07:55:05 +1100241 if (a == NULL && b == NULL)
242 return 1;
243 if (a == NULL || b == NULL)
Damien Miller450a7a12000-03-26 13:04:51 +1000244 return 0;
Damien Miller0a80ca12010-02-27 07:55:05 +1100245 if (buffer_len(&a->certblob) != buffer_len(&b->certblob))
246 return 0;
Damien Millerea1651c2010-07-16 13:58:37 +1000247 if (timingsafe_bcmp(buffer_ptr(&a->certblob), buffer_ptr(&b->certblob),
Damien Miller0a80ca12010-02-27 07:55:05 +1100248 buffer_len(&a->certblob)) != 0)
249 return 0;
250 return 1;
251}
252
253/*
254 * Compare public portions of key only, allowing comparisons between
255 * certificates and plain keys too.
256 */
257int
258key_equal_public(const Key *a, const Key *b)
259{
Damien Millereb8b60e2010-08-31 22:41:14 +1000260 BN_CTX *bnctx;
261
Damien Miller0a80ca12010-02-27 07:55:05 +1100262 if (a == NULL || b == NULL ||
263 key_type_plain(a->type) != key_type_plain(b->type))
264 return 0;
265
Damien Miller450a7a12000-03-26 13:04:51 +1000266 switch (a->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100267 case KEY_RSA1:
Damien Miller4e270b02010-04-16 15:56:21 +1000268 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100269 case KEY_RSA_CERT:
Damien Miller450a7a12000-03-26 13:04:51 +1000270 case KEY_RSA:
271 return a->rsa != NULL && b->rsa != NULL &&
272 BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
273 BN_cmp(a->rsa->n, b->rsa->n) == 0;
Damien Miller4e270b02010-04-16 15:56:21 +1000274 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100275 case KEY_DSA_CERT:
Damien Miller450a7a12000-03-26 13:04:51 +1000276 case KEY_DSA:
277 return a->dsa != NULL && b->dsa != NULL &&
278 BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
279 BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
280 BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
281 BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
Damien Millereb8b60e2010-08-31 22:41:14 +1000282 case KEY_ECDSA_CERT:
283 case KEY_ECDSA:
284 if (a->ecdsa == NULL || b->ecdsa == NULL ||
285 EC_KEY_get0_public_key(a->ecdsa) == NULL ||
286 EC_KEY_get0_public_key(b->ecdsa) == NULL)
287 return 0;
288 if ((bnctx = BN_CTX_new()) == NULL)
289 fatal("%s: BN_CTX_new failed", __func__);
290 if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa),
291 EC_KEY_get0_group(b->ecdsa), bnctx) != 0 ||
292 EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa),
293 EC_KEY_get0_public_key(a->ecdsa),
294 EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) {
295 BN_CTX_free(bnctx);
296 return 0;
297 }
298 BN_CTX_free(bnctx);
299 return 1;
Damien Miller450a7a12000-03-26 13:04:51 +1000300 default:
Damien Millereba71ba2000-04-29 23:57:08 +1000301 fatal("key_equal: bad key type %d", a->type);
Damien Miller450a7a12000-03-26 13:04:51 +1000302 }
Damien Miller87dd5f22008-07-11 17:35:09 +1000303 /* NOTREACHED */
Damien Miller450a7a12000-03-26 13:04:51 +1000304}
305
Damien Miller0a80ca12010-02-27 07:55:05 +1100306int
307key_equal(const Key *a, const Key *b)
308{
309 if (a == NULL || b == NULL || a->type != b->type)
310 return 0;
311 if (key_is_cert(a)) {
312 if (!cert_compare(a->cert, b->cert))
313 return 0;
314 }
315 return key_equal_public(a, b);
316}
317
Damien Miller37876e92003-05-15 10:19:46 +1000318u_char*
Damien Miller0a80ca12010-02-27 07:55:05 +1100319key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length)
Damien Miller450a7a12000-03-26 13:04:51 +1000320{
Ben Lindstrom80cb27d2002-03-05 01:33:36 +0000321 const EVP_MD *md = NULL;
Ben Lindstromf0b48532001-03-12 02:59:31 +0000322 EVP_MD_CTX ctx;
Ben Lindstrom46c16222000-12-22 01:43:59 +0000323 u_char *blob = NULL;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000324 u_char *retval = NULL;
Ben Lindstrom90fd8142002-02-26 18:09:42 +0000325 u_int len = 0;
Damien Miller0a80ca12010-02-27 07:55:05 +1100326 int nlen, elen, otype;
Damien Miller450a7a12000-03-26 13:04:51 +1000327
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000328 *dgst_raw_length = 0;
329
Ben Lindstromf0b48532001-03-12 02:59:31 +0000330 switch (dgst_type) {
331 case SSH_FP_MD5:
332 md = EVP_md5();
333 break;
334 case SSH_FP_SHA1:
335 md = EVP_sha1();
336 break;
337 default:
338 fatal("key_fingerprint_raw: bad digest type %d",
339 dgst_type);
340 }
Damien Miller450a7a12000-03-26 13:04:51 +1000341 switch (k->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100342 case KEY_RSA1:
Damien Miller450a7a12000-03-26 13:04:51 +1000343 nlen = BN_num_bytes(k->rsa->n);
344 elen = BN_num_bytes(k->rsa->e);
345 len = nlen + elen;
Damien Millereba71ba2000-04-29 23:57:08 +1000346 blob = xmalloc(len);
347 BN_bn2bin(k->rsa->n, blob);
348 BN_bn2bin(k->rsa->e, blob + nlen);
Damien Miller450a7a12000-03-26 13:04:51 +1000349 break;
350 case KEY_DSA:
Damien Millereb8b60e2010-08-31 22:41:14 +1000351 case KEY_ECDSA:
Damien Miller0bc1bd82000-11-13 22:57:25 +1100352 case KEY_RSA:
353 key_to_blob(k, &blob, &len);
354 break;
Damien Miller4e270b02010-04-16 15:56:21 +1000355 case KEY_DSA_CERT_V00:
356 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100357 case KEY_DSA_CERT:
Damien Millereb8b60e2010-08-31 22:41:14 +1000358 case KEY_ECDSA_CERT:
Damien Miller0a80ca12010-02-27 07:55:05 +1100359 case KEY_RSA_CERT:
360 /* We want a fingerprint of the _key_ not of the cert */
361 otype = k->type;
362 k->type = key_type_plain(k->type);
363 key_to_blob(k, &blob, &len);
364 k->type = otype;
365 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100366 case KEY_UNSPEC:
367 return retval;
Damien Miller450a7a12000-03-26 13:04:51 +1000368 default:
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000369 fatal("key_fingerprint_raw: bad key type %d", k->type);
Damien Miller450a7a12000-03-26 13:04:51 +1000370 break;
371 }
Damien Millereba71ba2000-04-29 23:57:08 +1000372 if (blob != NULL) {
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000373 retval = xmalloc(EVP_MAX_MD_SIZE);
Damien Miller6536c7d2000-06-22 21:32:31 +1000374 EVP_DigestInit(&ctx, md);
375 EVP_DigestUpdate(&ctx, blob, len);
Damien Miller3672e4b2002-02-05 11:54:07 +1100376 EVP_DigestFinal(&ctx, retval, dgst_raw_length);
Damien Millereba71ba2000-04-29 23:57:08 +1000377 memset(blob, 0, len);
378 xfree(blob);
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000379 } else {
380 fatal("key_fingerprint_raw: blob is null");
Damien Miller450a7a12000-03-26 13:04:51 +1000381 }
382 return retval;
383}
384
Ben Lindstroma962c2f2002-07-04 00:14:17 +0000385static char *
386key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len)
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000387{
388 char *retval;
Damien Millereccb9de2005-06-17 12:59:34 +1000389 u_int i;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000390
Damien Miller07d86be2006-03-26 14:19:21 +1100391 retval = xcalloc(1, dgst_raw_len * 3 + 1);
Damien Miller9f0f5c62001-12-21 14:45:46 +1100392 for (i = 0; i < dgst_raw_len; i++) {
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000393 char hex[4];
394 snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
Darren Tucker29588612003-07-14 17:28:34 +1000395 strlcat(retval, hex, dgst_raw_len * 3 + 1);
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000396 }
Darren Tucker29588612003-07-14 17:28:34 +1000397
398 /* Remove the trailing ':' character */
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000399 retval[(dgst_raw_len * 3) - 1] = '\0';
400 return retval;
401}
402
Ben Lindstroma962c2f2002-07-04 00:14:17 +0000403static char *
404key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len)
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000405{
406 char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
407 char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
408 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000409 u_int i, j = 0, rounds, seed = 1;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000410 char *retval;
411
412 rounds = (dgst_raw_len / 2) + 1;
Damien Miller07d86be2006-03-26 14:19:21 +1100413 retval = xcalloc((rounds * 6), sizeof(char));
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000414 retval[j++] = 'x';
415 for (i = 0; i < rounds; i++) {
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000416 u_int idx0, idx1, idx2, idx3, idx4;
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000417 if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
418 idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000419 seed) % 6;
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000420 idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
421 idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000422 (seed / 6)) % 6;
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000423 retval[j++] = vowels[idx0];
424 retval[j++] = consonants[idx1];
425 retval[j++] = vowels[idx2];
426 if ((i + 1) < rounds) {
427 idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
428 idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
429 retval[j++] = consonants[idx3];
430 retval[j++] = '-';
431 retval[j++] = consonants[idx4];
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000432 seed = ((seed * 5) +
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000433 ((((u_int)(dgst_raw[2 * i])) * 7) +
434 ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000435 }
436 } else {
437 idx0 = seed % 6;
438 idx1 = 16;
439 idx2 = seed / 6;
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000440 retval[j++] = vowels[idx0];
441 retval[j++] = consonants[idx1];
442 retval[j++] = vowels[idx2];
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000443 }
444 }
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000445 retval[j++] = 'x';
446 retval[j++] = '\0';
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000447 return retval;
448}
449
Darren Tucker9c16ac92008-06-13 04:40:35 +1000450/*
451 * Draw an ASCII-Art representing the fingerprint so human brain can
452 * profit from its built-in pattern recognition ability.
453 * This technique is called "random art" and can be found in some
454 * scientific publications like this original paper:
455 *
456 * "Hash Visualization: a New Technique to improve Real-World Security",
457 * Perrig A. and Song D., 1999, International Workshop on Cryptographic
458 * Techniques and E-Commerce (CrypTEC '99)
459 * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
460 *
461 * The subject came up in a talk by Dan Kaminsky, too.
462 *
463 * If you see the picture is different, the key is different.
464 * If the picture looks the same, you still know nothing.
465 *
466 * The algorithm used here is a worm crawling over a discrete plane,
467 * leaving a trace (augmenting the field) everywhere it goes.
468 * Movement is taken from dgst_raw 2bit-wise. Bumping into walls
469 * makes the respective movement vector be ignored for this turn.
470 * Graphs are not unambiguous, because circles in graphs can be
471 * walked in either direction.
472 */
Darren Tucker987ac842008-06-13 04:54:40 +1000473
474/*
475 * Field sizes for the random art. Have to be odd, so the starting point
476 * can be in the exact middle of the picture, and FLDBASE should be >=8 .
477 * Else pictures would be too dense, and drawing the frame would
478 * fail, too, because the key type would not fit in anymore.
479 */
480#define FLDBASE 8
481#define FLDSIZE_Y (FLDBASE + 1)
482#define FLDSIZE_X (FLDBASE * 2 + 1)
Darren Tucker9c16ac92008-06-13 04:40:35 +1000483static char *
Darren Tucker987ac842008-06-13 04:54:40 +1000484key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k)
Darren Tucker9c16ac92008-06-13 04:40:35 +1000485{
486 /*
487 * Chars to be used after each other every time the worm
488 * intersects with itself. Matter of taste.
489 */
Darren Tucker4b3b9772008-06-13 04:55:10 +1000490 char *augmentation_string = " .o+=*BOX@%&#/^SE";
Darren Tucker9c16ac92008-06-13 04:40:35 +1000491 char *retval, *p;
Darren Tucker014d76f2008-06-13 04:43:51 +1000492 u_char field[FLDSIZE_X][FLDSIZE_Y];
Darren Tucker9c16ac92008-06-13 04:40:35 +1000493 u_int i, b;
494 int x, y;
Darren Tuckerd32b28a2008-06-13 04:45:50 +1000495 size_t len = strlen(augmentation_string) - 1;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000496
497 retval = xcalloc(1, (FLDSIZE_X + 3) * (FLDSIZE_Y + 2));
498
499 /* initialize field */
Darren Tucker014d76f2008-06-13 04:43:51 +1000500 memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
Darren Tucker9c16ac92008-06-13 04:40:35 +1000501 x = FLDSIZE_X / 2;
502 y = FLDSIZE_Y / 2;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000503
504 /* process raw key */
505 for (i = 0; i < dgst_raw_len; i++) {
506 int input;
507 /* each byte conveys four 2-bit move commands */
508 input = dgst_raw[i];
509 for (b = 0; b < 4; b++) {
510 /* evaluate 2 bit, rest is shifted later */
511 x += (input & 0x1) ? 1 : -1;
512 y += (input & 0x2) ? 1 : -1;
513
514 /* assure we are still in bounds */
515 x = MAX(x, 0);
516 y = MAX(y, 0);
517 x = MIN(x, FLDSIZE_X - 1);
518 y = MIN(y, FLDSIZE_Y - 1);
519
520 /* augment the field */
Damien Millerc6aadd92008-11-03 19:16:20 +1100521 if (field[x][y] < len - 2)
522 field[x][y]++;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000523 input = input >> 2;
524 }
525 }
Darren Tucker4b3b9772008-06-13 04:55:10 +1000526
527 /* mark starting point and end point*/
528 field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
529 field[x][y] = len;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000530
531 /* fill in retval */
Damien Miller007132a2008-06-29 22:45:37 +1000532 snprintf(retval, FLDSIZE_X, "+--[%4s %4u]", key_type(k), key_size(k));
Darren Tucker987ac842008-06-13 04:54:40 +1000533 p = strchr(retval, '\0');
Darren Tucker9c16ac92008-06-13 04:40:35 +1000534
535 /* output upper border */
Damien Miller007132a2008-06-29 22:45:37 +1000536 for (i = p - retval - 1; i < FLDSIZE_X; i++)
Darren Tucker9c16ac92008-06-13 04:40:35 +1000537 *p++ = '-';
538 *p++ = '+';
539 *p++ = '\n';
540
541 /* output content */
542 for (y = 0; y < FLDSIZE_Y; y++) {
543 *p++ = '|';
544 for (x = 0; x < FLDSIZE_X; x++)
Darren Tuckerd32b28a2008-06-13 04:45:50 +1000545 *p++ = augmentation_string[MIN(field[x][y], len)];
Darren Tucker9c16ac92008-06-13 04:40:35 +1000546 *p++ = '|';
547 *p++ = '\n';
548 }
549
550 /* output lower border */
551 *p++ = '+';
552 for (i = 0; i < FLDSIZE_X; i++)
553 *p++ = '-';
554 *p++ = '+';
555
556 return retval;
557}
558
Ben Lindstroma962c2f2002-07-04 00:14:17 +0000559char *
Damien Miller0a80ca12010-02-27 07:55:05 +1100560key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000561{
Ben Lindstroma3700052001-04-05 23:26:32 +0000562 char *retval = NULL;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000563 u_char *dgst_raw;
Damien Miller3672e4b2002-02-05 11:54:07 +1100564 u_int dgst_raw_len;
Damien Miller9f0f5c62001-12-21 14:45:46 +1100565
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000566 dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len);
567 if (!dgst_raw)
Ben Lindstromcfccef92001-03-13 04:57:58 +0000568 fatal("key_fingerprint: null from key_fingerprint_raw()");
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +0000569 switch (dgst_rep) {
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000570 case SSH_FP_HEX:
571 retval = key_fingerprint_hex(dgst_raw, dgst_raw_len);
572 break;
573 case SSH_FP_BUBBLEBABBLE:
574 retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
575 break;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000576 case SSH_FP_RANDOMART:
Darren Tucker987ac842008-06-13 04:54:40 +1000577 retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k);
Darren Tucker9c16ac92008-06-13 04:40:35 +1000578 break;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000579 default:
Damien Miller2f54ada2008-11-03 19:24:16 +1100580 fatal("key_fingerprint: bad digest representation %d",
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000581 dgst_rep);
582 break;
583 }
584 memset(dgst_raw, 0, dgst_raw_len);
585 xfree(dgst_raw);
586 return retval;
587}
588
Damien Miller450a7a12000-03-26 13:04:51 +1000589/*
590 * Reads a multiple-precision integer in decimal from the buffer, and advances
591 * the pointer. The integer must already be initialized. This function is
592 * permitted to modify the buffer. This leaves *cpp to point just beyond the
593 * last processed (and maybe modified) character. Note that this may modify
594 * the buffer containing the number.
595 */
Ben Lindstrombba81212001-06-25 05:01:22 +0000596static int
Damien Miller450a7a12000-03-26 13:04:51 +1000597read_bignum(char **cpp, BIGNUM * value)
598{
599 char *cp = *cpp;
600 int old;
601
602 /* Skip any leading whitespace. */
603 for (; *cp == ' ' || *cp == '\t'; cp++)
604 ;
605
606 /* Check that it begins with a decimal digit. */
607 if (*cp < '0' || *cp > '9')
608 return 0;
609
610 /* Save starting position. */
611 *cpp = cp;
612
613 /* Move forward until all decimal digits skipped. */
614 for (; *cp >= '0' && *cp <= '9'; cp++)
615 ;
616
617 /* Save the old terminating character, and replace it by \0. */
618 old = *cp;
619 *cp = 0;
620
621 /* Parse the number. */
622 if (BN_dec2bn(&value, *cpp) == 0)
623 return 0;
624
625 /* Restore old terminating character. */
626 *cp = old;
627
628 /* Move beyond the number and return success. */
629 *cpp = cp;
630 return 1;
631}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000632
Ben Lindstrombba81212001-06-25 05:01:22 +0000633static int
Damien Miller450a7a12000-03-26 13:04:51 +1000634write_bignum(FILE *f, BIGNUM *num)
635{
636 char *buf = BN_bn2dec(num);
637 if (buf == NULL) {
638 error("write_bignum: BN_bn2dec() failed");
639 return 0;
640 }
641 fprintf(f, " %s", buf);
Damien Milleraf3030f2001-10-10 15:00:49 +1000642 OPENSSL_free(buf);
Damien Miller450a7a12000-03-26 13:04:51 +1000643 return 1;
644}
Damien Miller0bc1bd82000-11-13 22:57:25 +1100645
Ben Lindstrom309f3d12001-09-20 00:55:53 +0000646/* returns 1 ok, -1 error */
Damien Miller0bc1bd82000-11-13 22:57:25 +1100647int
Damien Millereba71ba2000-04-29 23:57:08 +1000648key_read(Key *ret, char **cpp)
Damien Miller450a7a12000-03-26 13:04:51 +1000649{
Damien Millereba71ba2000-04-29 23:57:08 +1000650 Key *k;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100651 int success = -1;
652 char *cp, *space;
Damien Millereb8b60e2010-08-31 22:41:14 +1000653 int len, n, type, curve_nid = -1;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100654 u_int bits;
Ben Lindstrom46c16222000-12-22 01:43:59 +0000655 u_char *blob;
Damien Millereba71ba2000-04-29 23:57:08 +1000656
657 cp = *cpp;
658
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +0000659 switch (ret->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100660 case KEY_RSA1:
Damien Millereba71ba2000-04-29 23:57:08 +1000661 /* Get number of bits. */
662 if (*cp < '0' || *cp > '9')
Damien Miller0bc1bd82000-11-13 22:57:25 +1100663 return -1; /* Bad bit count... */
Damien Millereba71ba2000-04-29 23:57:08 +1000664 for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
665 bits = 10 * bits + *cp - '0';
Damien Miller450a7a12000-03-26 13:04:51 +1000666 if (bits == 0)
Damien Miller0bc1bd82000-11-13 22:57:25 +1100667 return -1;
Damien Millereba71ba2000-04-29 23:57:08 +1000668 *cpp = cp;
Damien Miller450a7a12000-03-26 13:04:51 +1000669 /* Get public exponent, public modulus. */
670 if (!read_bignum(cpp, ret->rsa->e))
Damien Miller0bc1bd82000-11-13 22:57:25 +1100671 return -1;
Damien Miller450a7a12000-03-26 13:04:51 +1000672 if (!read_bignum(cpp, ret->rsa->n))
Damien Miller0bc1bd82000-11-13 22:57:25 +1100673 return -1;
Darren Tucker561724f2010-01-13 22:43:05 +1100674 /* validate the claimed number of bits */
675 if ((u_int)BN_num_bits(ret->rsa->n) != bits) {
676 verbose("key_read: claimed key size %d does not match "
677 "actual %d", bits, BN_num_bits(ret->rsa->n));
678 return -1;
679 }
Damien Miller0bc1bd82000-11-13 22:57:25 +1100680 success = 1;
Damien Miller450a7a12000-03-26 13:04:51 +1000681 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100682 case KEY_UNSPEC:
683 case KEY_RSA:
Damien Miller450a7a12000-03-26 13:04:51 +1000684 case KEY_DSA:
Damien Millereb8b60e2010-08-31 22:41:14 +1000685 case KEY_ECDSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000686 case KEY_DSA_CERT_V00:
687 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100688 case KEY_DSA_CERT:
Damien Millereb8b60e2010-08-31 22:41:14 +1000689 case KEY_ECDSA_CERT:
Damien Miller0a80ca12010-02-27 07:55:05 +1100690 case KEY_RSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +1100691 space = strchr(cp, ' ');
692 if (space == NULL) {
Damien Miller386f1f32003-02-24 11:54:57 +1100693 debug3("key_read: missing whitespace");
Damien Miller0bc1bd82000-11-13 22:57:25 +1100694 return -1;
695 }
696 *space = '\0';
697 type = key_type_from_name(cp);
Damien Millereb8b60e2010-08-31 22:41:14 +1000698 if (key_type_plain(type) == KEY_ECDSA &&
699 (curve_nid = key_ecdsa_nid_from_name(cp)) == -1) {
700 debug("key_read: invalid curve");
701 return -1;
702 }
Damien Miller0bc1bd82000-11-13 22:57:25 +1100703 *space = ' ';
704 if (type == KEY_UNSPEC) {
Damien Miller386f1f32003-02-24 11:54:57 +1100705 debug3("key_read: missing keytype");
Damien Miller0bc1bd82000-11-13 22:57:25 +1100706 return -1;
707 }
708 cp = space+1;
709 if (*cp == '\0') {
710 debug3("key_read: short string");
711 return -1;
712 }
713 if (ret->type == KEY_UNSPEC) {
714 ret->type = type;
715 } else if (ret->type != type) {
716 /* is a key, but different type */
717 debug3("key_read: type mismatch");
Ben Lindstrom309f3d12001-09-20 00:55:53 +0000718 return -1;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100719 }
Damien Millereba71ba2000-04-29 23:57:08 +1000720 len = 2*strlen(cp);
721 blob = xmalloc(len);
722 n = uudecode(cp, blob, len);
Damien Millere247cc42000-05-07 12:03:14 +1000723 if (n < 0) {
Damien Millerb1715dc2000-05-30 13:44:51 +1000724 error("key_read: uudecode %s failed", cp);
Ben Lindstrom4cbc1812001-12-06 16:41:41 +0000725 xfree(blob);
Damien Miller0bc1bd82000-11-13 22:57:25 +1100726 return -1;
Damien Millere247cc42000-05-07 12:03:14 +1000727 }
Darren Tucker502d3842003-06-28 12:38:01 +1000728 k = key_from_blob(blob, (u_int)n);
Ben Lindstrom4cbc1812001-12-06 16:41:41 +0000729 xfree(blob);
Damien Millerb1715dc2000-05-30 13:44:51 +1000730 if (k == NULL) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100731 error("key_read: key_from_blob %s failed", cp);
732 return -1;
Damien Millerb1715dc2000-05-30 13:44:51 +1000733 }
Damien Miller0bc1bd82000-11-13 22:57:25 +1100734 if (k->type != type) {
735 error("key_read: type mismatch: encoding error");
736 key_free(k);
737 return -1;
738 }
Damien Millereb8b60e2010-08-31 22:41:14 +1000739 if (key_type_plain(type) == KEY_ECDSA &&
740 curve_nid != k->ecdsa_nid) {
741 error("key_read: type mismatch: EC curve mismatch");
742 key_free(k);
743 return -1;
744 }
Damien Miller0bc1bd82000-11-13 22:57:25 +1100745/*XXXX*/
Damien Miller0a80ca12010-02-27 07:55:05 +1100746 if (key_is_cert(ret)) {
747 if (!key_is_cert(k)) {
748 error("key_read: loaded key is not a cert");
749 key_free(k);
750 return -1;
751 }
752 if (ret->cert != NULL)
753 cert_free(ret->cert);
754 ret->cert = k->cert;
755 k->cert = NULL;
756 }
757 if (key_type_plain(ret->type) == KEY_RSA) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100758 if (ret->rsa != NULL)
759 RSA_free(ret->rsa);
760 ret->rsa = k->rsa;
761 k->rsa = NULL;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100762#ifdef DEBUG_PK
763 RSA_print_fp(stderr, ret->rsa, 8);
764#endif
Damien Miller0a80ca12010-02-27 07:55:05 +1100765 }
766 if (key_type_plain(ret->type) == KEY_DSA) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100767 if (ret->dsa != NULL)
768 DSA_free(ret->dsa);
769 ret->dsa = k->dsa;
770 k->dsa = NULL;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100771#ifdef DEBUG_PK
772 DSA_print_fp(stderr, ret->dsa, 8);
773#endif
774 }
Damien Millereb8b60e2010-08-31 22:41:14 +1000775 if (key_type_plain(ret->type) == KEY_ECDSA) {
776 if (ret->ecdsa != NULL)
777 EC_KEY_free(ret->ecdsa);
778 ret->ecdsa = k->ecdsa;
779 ret->ecdsa_nid = k->ecdsa_nid;
780 k->ecdsa = NULL;
781 k->ecdsa_nid = -1;
782#ifdef DEBUG_PK
783 key_dump_ec_key(ret->ecdsa);
784#endif
785 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100786 success = 1;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100787/*XXXX*/
Ben Lindstrom4cbc1812001-12-06 16:41:41 +0000788 key_free(k);
Damien Miller0bc1bd82000-11-13 22:57:25 +1100789 if (success != 1)
790 break;
Damien Millerb1715dc2000-05-30 13:44:51 +1000791 /* advance cp: skip whitespace and data */
792 while (*cp == ' ' || *cp == '\t')
793 cp++;
794 while (*cp != '\0' && *cp != ' ' && *cp != '\t')
795 cp++;
796 *cpp = cp;
Damien Miller450a7a12000-03-26 13:04:51 +1000797 break;
798 default:
Damien Millereba71ba2000-04-29 23:57:08 +1000799 fatal("key_read: bad key type: %d", ret->type);
Damien Miller450a7a12000-03-26 13:04:51 +1000800 break;
801 }
Damien Miller0bc1bd82000-11-13 22:57:25 +1100802 return success;
Damien Miller450a7a12000-03-26 13:04:51 +1000803}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000804
Damien Miller450a7a12000-03-26 13:04:51 +1000805int
Damien Millerf58b58c2003-11-17 21:18:23 +1100806key_write(const Key *key, FILE *f)
Damien Miller450a7a12000-03-26 13:04:51 +1000807{
Ben Lindstrom90fd8142002-02-26 18:09:42 +0000808 int n, success = 0;
809 u_int len, bits = 0;
Damien Millera10f5612002-09-12 09:49:15 +1000810 u_char *blob;
811 char *uu;
Damien Miller450a7a12000-03-26 13:04:51 +1000812
Damien Miller0a80ca12010-02-27 07:55:05 +1100813 if (key_is_cert(key)) {
814 if (key->cert == NULL) {
815 error("%s: no cert data", __func__);
816 return 0;
817 }
818 if (buffer_len(&key->cert->certblob) == 0) {
819 error("%s: no signed certificate blob", __func__);
820 return 0;
821 }
822 }
823
824 switch (key->type) {
825 case KEY_RSA1:
826 if (key->rsa == NULL)
827 return 0;
Damien Miller450a7a12000-03-26 13:04:51 +1000828 /* size of modulus 'n' */
829 bits = BN_num_bits(key->rsa->n);
830 fprintf(f, "%u", bits);
831 if (write_bignum(f, key->rsa->e) &&
Damien Miller0a80ca12010-02-27 07:55:05 +1100832 write_bignum(f, key->rsa->n))
833 return 1;
834 error("key_write: failed for RSA key");
835 return 0;
836 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000837 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100838 case KEY_DSA_CERT:
839 if (key->dsa == NULL)
840 return 0;
841 break;
Damien Millereb8b60e2010-08-31 22:41:14 +1000842 case KEY_ECDSA:
843 case KEY_ECDSA_CERT:
844 if (key->ecdsa == NULL)
845 return 0;
846 break;
Damien Miller0a80ca12010-02-27 07:55:05 +1100847 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000848 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100849 case KEY_RSA_CERT:
850 if (key->rsa == NULL)
851 return 0;
852 break;
853 default:
854 return 0;
Damien Miller450a7a12000-03-26 13:04:51 +1000855 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100856
857 key_to_blob(key, &blob, &len);
858 uu = xmalloc(2*len);
859 n = uuencode(blob, len, uu, 2*len);
860 if (n > 0) {
861 fprintf(f, "%s %s", key_ssh_name(key), uu);
862 success = 1;
863 }
864 xfree(blob);
865 xfree(uu);
866
Damien Miller450a7a12000-03-26 13:04:51 +1000867 return success;
868}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000869
Damien Millerf58b58c2003-11-17 21:18:23 +1100870const char *
871key_type(const Key *k)
Damien Millere247cc42000-05-07 12:03:14 +1000872{
873 switch (k->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100874 case KEY_RSA1:
875 return "RSA1";
Damien Millere247cc42000-05-07 12:03:14 +1000876 case KEY_RSA:
877 return "RSA";
Damien Millere247cc42000-05-07 12:03:14 +1000878 case KEY_DSA:
879 return "DSA";
Damien Millereb8b60e2010-08-31 22:41:14 +1000880 case KEY_ECDSA:
881 return "ECDSA";
Damien Miller4e270b02010-04-16 15:56:21 +1000882 case KEY_RSA_CERT_V00:
883 return "RSA-CERT-V00";
884 case KEY_DSA_CERT_V00:
885 return "DSA-CERT-V00";
Damien Miller0a80ca12010-02-27 07:55:05 +1100886 case KEY_RSA_CERT:
887 return "RSA-CERT";
888 case KEY_DSA_CERT:
889 return "DSA-CERT";
Damien Millereb8b60e2010-08-31 22:41:14 +1000890 case KEY_ECDSA_CERT:
891 return "ECDSA-CERT";
Damien Millere247cc42000-05-07 12:03:14 +1000892 }
893 return "unknown";
894}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000895
Damien Millerf58b58c2003-11-17 21:18:23 +1100896const char *
Damien Miller1cfbfaf2010-03-22 05:58:24 +1100897key_cert_type(const Key *k)
898{
899 switch (k->cert->type) {
900 case SSH2_CERT_TYPE_USER:
901 return "user";
902 case SSH2_CERT_TYPE_HOST:
903 return "host";
904 default:
905 return "unknown";
906 }
907}
908
Damien Millereb8b60e2010-08-31 22:41:14 +1000909static const char *
910key_ssh_name_from_type_nid(int type, int nid)
Damien Miller0bc1bd82000-11-13 22:57:25 +1100911{
Damien Millereb8b60e2010-08-31 22:41:14 +1000912 switch (type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100913 case KEY_RSA:
914 return "ssh-rsa";
Damien Miller0bc1bd82000-11-13 22:57:25 +1100915 case KEY_DSA:
916 return "ssh-dss";
Damien Miller4e270b02010-04-16 15:56:21 +1000917 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100918 return "ssh-rsa-cert-v00@openssh.com";
Damien Miller4e270b02010-04-16 15:56:21 +1000919 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100920 return "ssh-dss-cert-v00@openssh.com";
Damien Miller4e270b02010-04-16 15:56:21 +1000921 case KEY_RSA_CERT:
922 return "ssh-rsa-cert-v01@openssh.com";
923 case KEY_DSA_CERT:
924 return "ssh-dss-cert-v01@openssh.com";
Damien Millereb8b60e2010-08-31 22:41:14 +1000925 case KEY_ECDSA:
926 switch (nid) {
927 case NID_X9_62_prime256v1:
928 return "ecdsa-sha2-nistp256";
929 case NID_secp384r1:
930 return "ecdsa-sha2-nistp384";
931 case NID_secp521r1:
932 return "ecdsa-sha2-nistp521";
933 default:
934 break;
935 }
936 break;
937 case KEY_ECDSA_CERT:
938 switch (nid) {
939 case NID_X9_62_prime256v1:
940 return "ecdsa-sha2-nistp256-cert-v01@openssh.com";
941 case NID_secp384r1:
942 return "ecdsa-sha2-nistp384-cert-v01@openssh.com";
943 case NID_secp521r1:
944 return "ecdsa-sha2-nistp521-cert-v01@openssh.com";
945 default:
946 break;
947 }
948 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100949 }
950 return "ssh-unknown";
951}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000952
Damien Millereb8b60e2010-08-31 22:41:14 +1000953const char *
954key_ssh_name(const Key *k)
955{
956 return key_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
957}
958
959const char *
960key_ssh_name_plain(const Key *k)
961{
962 return key_ssh_name_from_type_nid(key_type_plain(k->type),
963 k->ecdsa_nid);
964}
965
Damien Miller0bc1bd82000-11-13 22:57:25 +1100966u_int
Damien Millerf58b58c2003-11-17 21:18:23 +1100967key_size(const Key *k)
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +0000968{
Damien Millerad833b32000-08-23 10:46:23 +1000969 switch (k->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100970 case KEY_RSA1:
Damien Millerad833b32000-08-23 10:46:23 +1000971 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000972 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100973 case KEY_RSA_CERT:
Damien Millerad833b32000-08-23 10:46:23 +1000974 return BN_num_bits(k->rsa->n);
Damien Millerad833b32000-08-23 10:46:23 +1000975 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000976 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100977 case KEY_DSA_CERT:
Damien Millerad833b32000-08-23 10:46:23 +1000978 return BN_num_bits(k->dsa->p);
Damien Millereb8b60e2010-08-31 22:41:14 +1000979 case KEY_ECDSA:
980 case KEY_ECDSA_CERT:
981 switch (k->ecdsa_nid) {
982 case NID_X9_62_prime256v1:
983 return 256;
984 case NID_secp384r1:
985 return 384;
986 case NID_secp521r1:
987 return 521;
988 default:
989 break;
990 }
991 break;
Damien Millerad833b32000-08-23 10:46:23 +1000992 }
993 return 0;
994}
Damien Miller0bc1bd82000-11-13 22:57:25 +1100995
Ben Lindstrombba81212001-06-25 05:01:22 +0000996static RSA *
Ben Lindstrom46c16222000-12-22 01:43:59 +0000997rsa_generate_private_key(u_int bits)
Damien Miller0bc1bd82000-11-13 22:57:25 +1100998{
Kevin Stevesef4eea92001-02-05 12:42:17 +0000999 RSA *private;
Damien Miller69b72032006-03-26 14:02:35 +11001000
Darren Tucker57e0d012010-01-08 18:52:27 +11001001 private = RSA_generate_key(bits, RSA_F4, NULL, NULL);
Kevin Stevesef4eea92001-02-05 12:42:17 +00001002 if (private == NULL)
1003 fatal("rsa_generate_private_key: key generation failed.");
1004 return private;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001005}
1006
Ben Lindstrombba81212001-06-25 05:01:22 +00001007static DSA*
Ben Lindstrom46c16222000-12-22 01:43:59 +00001008dsa_generate_private_key(u_int bits)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001009{
1010 DSA *private = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
Damien Miller69b72032006-03-26 14:02:35 +11001011
Damien Miller0bc1bd82000-11-13 22:57:25 +11001012 if (private == NULL)
1013 fatal("dsa_generate_private_key: DSA_generate_parameters failed");
1014 if (!DSA_generate_key(private))
Kevin Stevesef4eea92001-02-05 12:42:17 +00001015 fatal("dsa_generate_private_key: DSA_generate_key failed.");
1016 if (private == NULL)
1017 fatal("dsa_generate_private_key: NULL.");
Damien Miller0bc1bd82000-11-13 22:57:25 +11001018 return private;
1019}
1020
Damien Millereb8b60e2010-08-31 22:41:14 +10001021int
1022key_ecdsa_bits_to_nid(int bits)
1023{
1024 switch (bits) {
1025 case 256:
1026 return NID_X9_62_prime256v1;
1027 case 384:
1028 return NID_secp384r1;
1029 case 521:
1030 return NID_secp521r1;
1031 default:
1032 return -1;
1033 }
1034}
1035
1036/*
1037 * This is horrid, but OpenSSL's PEM_read_PrivateKey seems not to restore
1038 * the EC_GROUP nid when loading a key...
1039 */
1040int
1041key_ecdsa_group_to_nid(const EC_GROUP *g)
1042{
1043 EC_GROUP *eg;
1044 int nids[] = {
1045 NID_X9_62_prime256v1,
1046 NID_secp384r1,
1047 NID_secp521r1,
1048 -1
1049 };
1050 u_int i;
1051 BN_CTX *bnctx;
1052
1053 if ((bnctx = BN_CTX_new()) == NULL)
1054 fatal("%s: BN_CTX_new() failed", __func__);
1055 for (i = 0; nids[i] != -1; i++) {
1056 if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL)
1057 fatal("%s: EC_GROUP_new_by_curve_name failed",
1058 __func__);
1059 if (EC_GROUP_cmp(g, eg, bnctx) == 0) {
1060 EC_GROUP_free(eg);
1061 break;
1062 }
1063 EC_GROUP_free(eg);
1064 }
1065 BN_CTX_free(bnctx);
1066 debug3("%s: nid = %d", __func__, nids[i]);
1067 return nids[i];
1068}
1069
1070static EC_KEY*
1071ecdsa_generate_private_key(u_int bits, int *nid)
1072{
1073 EC_KEY *private;
1074
1075 if ((*nid = key_ecdsa_bits_to_nid(bits)) == -1)
1076 fatal("%s: invalid key length", __func__);
1077 if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL)
1078 fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
1079 if (EC_KEY_generate_key(private) != 1)
1080 fatal("%s: EC_KEY_generate_key failed", __func__);
1081 return private;
1082}
1083
Damien Miller0bc1bd82000-11-13 22:57:25 +11001084Key *
Ben Lindstrom46c16222000-12-22 01:43:59 +00001085key_generate(int type, u_int bits)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001086{
1087 Key *k = key_new(KEY_UNSPEC);
1088 switch (type) {
Kevin Stevesef4eea92001-02-05 12:42:17 +00001089 case KEY_DSA:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001090 k->dsa = dsa_generate_private_key(bits);
1091 break;
Damien Millereb8b60e2010-08-31 22:41:14 +10001092 case KEY_ECDSA:
1093 k->ecdsa = ecdsa_generate_private_key(bits, &k->ecdsa_nid);
1094 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001095 case KEY_RSA:
1096 case KEY_RSA1:
1097 k->rsa = rsa_generate_private_key(bits);
1098 break;
Damien Miller4e270b02010-04-16 15:56:21 +10001099 case KEY_RSA_CERT_V00:
1100 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001101 case KEY_RSA_CERT:
1102 case KEY_DSA_CERT:
1103 fatal("key_generate: cert keys cannot be generated directly");
Damien Miller0bc1bd82000-11-13 22:57:25 +11001104 default:
Kevin Stevesef4eea92001-02-05 12:42:17 +00001105 fatal("key_generate: unknown type %d", type);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001106 }
Kevin Stevesef4eea92001-02-05 12:42:17 +00001107 k->type = type;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001108 return k;
1109}
1110
Damien Miller0a80ca12010-02-27 07:55:05 +11001111void
1112key_cert_copy(const Key *from_key, struct Key *to_key)
1113{
1114 u_int i;
1115 const struct KeyCert *from;
1116 struct KeyCert *to;
1117
1118 if (to_key->cert != NULL) {
1119 cert_free(to_key->cert);
1120 to_key->cert = NULL;
1121 }
1122
1123 if ((from = from_key->cert) == NULL)
1124 return;
1125
1126 to = to_key->cert = cert_new();
1127
1128 buffer_append(&to->certblob, buffer_ptr(&from->certblob),
1129 buffer_len(&from->certblob));
1130
Damien Miller4e270b02010-04-16 15:56:21 +10001131 buffer_append(&to->critical,
1132 buffer_ptr(&from->critical), buffer_len(&from->critical));
1133 buffer_append(&to->extensions,
1134 buffer_ptr(&from->extensions), buffer_len(&from->extensions));
Damien Miller0a80ca12010-02-27 07:55:05 +11001135
Damien Miller4e270b02010-04-16 15:56:21 +10001136 to->serial = from->serial;
Damien Miller0a80ca12010-02-27 07:55:05 +11001137 to->type = from->type;
1138 to->key_id = from->key_id == NULL ? NULL : xstrdup(from->key_id);
1139 to->valid_after = from->valid_after;
1140 to->valid_before = from->valid_before;
1141 to->signature_key = from->signature_key == NULL ?
1142 NULL : key_from_private(from->signature_key);
1143
1144 to->nprincipals = from->nprincipals;
1145 if (to->nprincipals > CERT_MAX_PRINCIPALS)
1146 fatal("%s: nprincipals (%u) > CERT_MAX_PRINCIPALS (%u)",
1147 __func__, to->nprincipals, CERT_MAX_PRINCIPALS);
1148 if (to->nprincipals > 0) {
1149 to->principals = xcalloc(from->nprincipals,
1150 sizeof(*to->principals));
1151 for (i = 0; i < to->nprincipals; i++)
1152 to->principals[i] = xstrdup(from->principals[i]);
1153 }
1154}
1155
Damien Miller0bc1bd82000-11-13 22:57:25 +11001156Key *
Damien Millerf58b58c2003-11-17 21:18:23 +11001157key_from_private(const Key *k)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001158{
1159 Key *n = NULL;
1160 switch (k->type) {
Kevin Stevesef4eea92001-02-05 12:42:17 +00001161 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +10001162 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001163 case KEY_DSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001164 n = key_new(k->type);
Darren Tucker0bc85572006-11-07 23:14:41 +11001165 if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
1166 (BN_copy(n->dsa->q, k->dsa->q) == NULL) ||
1167 (BN_copy(n->dsa->g, k->dsa->g) == NULL) ||
1168 (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL))
1169 fatal("key_from_private: BN_copy failed");
Damien Miller0bc1bd82000-11-13 22:57:25 +11001170 break;
Damien Millereb8b60e2010-08-31 22:41:14 +10001171 case KEY_ECDSA:
1172 case KEY_ECDSA_CERT:
1173 n = key_new(k->type);
1174 n->ecdsa_nid = k->ecdsa_nid;
1175 if ((n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL)
1176 fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
1177 if (EC_KEY_set_public_key(n->ecdsa,
1178 EC_KEY_get0_public_key(k->ecdsa)) != 1)
1179 fatal("%s: EC_KEY_set_public_key failed", __func__);
1180 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001181 case KEY_RSA:
1182 case KEY_RSA1:
Damien Miller4e270b02010-04-16 15:56:21 +10001183 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001184 case KEY_RSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001185 n = key_new(k->type);
Darren Tucker0bc85572006-11-07 23:14:41 +11001186 if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
1187 (BN_copy(n->rsa->e, k->rsa->e) == NULL))
1188 fatal("key_from_private: BN_copy failed");
Damien Miller0bc1bd82000-11-13 22:57:25 +11001189 break;
1190 default:
Kevin Stevesef4eea92001-02-05 12:42:17 +00001191 fatal("key_from_private: unknown type %d", k->type);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001192 break;
1193 }
Damien Miller0a80ca12010-02-27 07:55:05 +11001194 if (key_is_cert(k))
1195 key_cert_copy(k, n);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001196 return n;
1197}
1198
1199int
1200key_type_from_name(char *name)
1201{
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001202 if (strcmp(name, "rsa1") == 0) {
Damien Miller0bc1bd82000-11-13 22:57:25 +11001203 return KEY_RSA1;
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001204 } else if (strcmp(name, "rsa") == 0) {
Damien Miller0bc1bd82000-11-13 22:57:25 +11001205 return KEY_RSA;
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001206 } else if (strcmp(name, "dsa") == 0) {
Damien Miller0bc1bd82000-11-13 22:57:25 +11001207 return KEY_DSA;
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001208 } else if (strcmp(name, "ssh-rsa") == 0) {
Damien Miller0bc1bd82000-11-13 22:57:25 +11001209 return KEY_RSA;
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001210 } else if (strcmp(name, "ssh-dss") == 0) {
Damien Miller0bc1bd82000-11-13 22:57:25 +11001211 return KEY_DSA;
Damien Millereb8b60e2010-08-31 22:41:14 +10001212 } else if (strcmp(name, "ecdsa") == 0 ||
1213 strcmp(name, "ecdsa-sha2-nistp256") == 0 ||
1214 strcmp(name, "ecdsa-sha2-nistp384") == 0 ||
1215 strcmp(name, "ecdsa-sha2-nistp521") == 0) {
1216 return KEY_ECDSA;
Damien Miller0a80ca12010-02-27 07:55:05 +11001217 } else if (strcmp(name, "ssh-rsa-cert-v00@openssh.com") == 0) {
Damien Miller4e270b02010-04-16 15:56:21 +10001218 return KEY_RSA_CERT_V00;
Damien Miller0a80ca12010-02-27 07:55:05 +11001219 } else if (strcmp(name, "ssh-dss-cert-v00@openssh.com") == 0) {
Damien Miller4e270b02010-04-16 15:56:21 +10001220 return KEY_DSA_CERT_V00;
1221 } else if (strcmp(name, "ssh-rsa-cert-v01@openssh.com") == 0) {
1222 return KEY_RSA_CERT;
1223 } else if (strcmp(name, "ssh-dss-cert-v01@openssh.com") == 0) {
Damien Miller0a80ca12010-02-27 07:55:05 +11001224 return KEY_DSA_CERT;
Damien Millereb8b60e2010-08-31 22:41:14 +10001225 } else if (strcmp(name, "ecdsa-sha2-nistp256-cert-v01@openssh.com") == 0 ||
1226 strcmp(name, "ecdsa-sha2-nistp384-cert-v01@openssh.com") == 0 ||
1227 strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0)
1228 return KEY_ECDSA_CERT;
1229
Ben Lindstromb54873a2001-03-11 20:01:55 +00001230 debug2("key_type_from_name: unknown key type '%s'", name);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001231 return KEY_UNSPEC;
1232}
1233
Ben Lindstrom982dbbc2001-04-17 18:11:36 +00001234int
Damien Millereb8b60e2010-08-31 22:41:14 +10001235key_ecdsa_nid_from_name(const char *name)
1236{
1237 if (strcmp(name, "ecdsa-sha2-nistp256") == 0 ||
1238 strcmp(name, "ecdsa-sha2-nistp256-cert-v01@openssh.com") == 0)
1239 return NID_X9_62_prime256v1;
1240 if (strcmp(name, "ecdsa-sha2-nistp384") == 0 ||
1241 strcmp(name, "ecdsa-sha2-nistp384-cert-v01@openssh.com") == 0)
1242 return NID_secp384r1;
1243 if (strcmp(name, "ecdsa-sha2-nistp521") == 0 ||
1244 strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0)
1245 return NID_secp521r1;
1246
1247 debug2("%s: unknown/non-ECDSA key type '%s'", __func__, name);
1248 return -1;
1249}
1250
1251int
Ben Lindstrom982dbbc2001-04-17 18:11:36 +00001252key_names_valid2(const char *names)
1253{
1254 char *s, *cp, *p;
1255
1256 if (names == NULL || strcmp(names, "") == 0)
1257 return 0;
1258 s = cp = xstrdup(names);
1259 for ((p = strsep(&cp, ",")); p && *p != '\0';
Damien Miller9f0f5c62001-12-21 14:45:46 +11001260 (p = strsep(&cp, ","))) {
Ben Lindstrom982dbbc2001-04-17 18:11:36 +00001261 switch (key_type_from_name(p)) {
1262 case KEY_RSA1:
1263 case KEY_UNSPEC:
1264 xfree(s);
1265 return 0;
1266 }
1267 }
1268 debug3("key names ok: [%s]", names);
1269 xfree(s);
1270 return 1;
1271}
1272
Damien Miller0a80ca12010-02-27 07:55:05 +11001273static int
1274cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)
1275{
Damien Miller4e270b02010-04-16 15:56:21 +10001276 u_char *principals, *critical, *exts, *sig_key, *sig;
1277 u_int signed_len, plen, clen, sklen, slen, kidlen, elen;
Damien Miller0a80ca12010-02-27 07:55:05 +11001278 Buffer tmp;
1279 char *principal;
1280 int ret = -1;
Damien Miller4e270b02010-04-16 15:56:21 +10001281 int v00 = key->type == KEY_DSA_CERT_V00 ||
1282 key->type == KEY_RSA_CERT_V00;
Damien Miller0a80ca12010-02-27 07:55:05 +11001283
1284 buffer_init(&tmp);
1285
1286 /* Copy the entire key blob for verification and later serialisation */
1287 buffer_append(&key->cert->certblob, blob, blen);
1288
Damien Miller4e270b02010-04-16 15:56:21 +10001289 elen = 0; /* Not touched for v00 certs */
1290 principals = exts = critical = sig_key = sig = NULL;
1291 if ((!v00 && buffer_get_int64_ret(&key->cert->serial, b) != 0) ||
1292 buffer_get_int_ret(&key->cert->type, b) != 0 ||
Damien Millerda108ec2010-08-31 22:36:39 +10001293 (key->cert->key_id = buffer_get_cstring_ret(b, &kidlen)) == NULL ||
Damien Miller0a80ca12010-02-27 07:55:05 +11001294 (principals = buffer_get_string_ret(b, &plen)) == NULL ||
1295 buffer_get_int64_ret(&key->cert->valid_after, b) != 0 ||
1296 buffer_get_int64_ret(&key->cert->valid_before, b) != 0 ||
Damien Miller4e270b02010-04-16 15:56:21 +10001297 (critical = buffer_get_string_ret(b, &clen)) == NULL ||
1298 (!v00 && (exts = buffer_get_string_ret(b, &elen)) == NULL) ||
1299 (v00 && buffer_get_string_ptr_ret(b, NULL) == NULL) || /* nonce */
1300 buffer_get_string_ptr_ret(b, NULL) == NULL || /* reserved */
Damien Miller0a80ca12010-02-27 07:55:05 +11001301 (sig_key = buffer_get_string_ret(b, &sklen)) == NULL) {
1302 error("%s: parse error", __func__);
1303 goto out;
1304 }
1305
Damien Miller41396572010-03-04 21:51:11 +11001306 if (kidlen != strlen(key->cert->key_id)) {
1307 error("%s: key ID contains \\0 character", __func__);
1308 goto out;
1309 }
1310
Damien Miller0a80ca12010-02-27 07:55:05 +11001311 /* Signature is left in the buffer so we can calculate this length */
1312 signed_len = buffer_len(&key->cert->certblob) - buffer_len(b);
1313
1314 if ((sig = buffer_get_string_ret(b, &slen)) == NULL) {
1315 error("%s: parse error", __func__);
1316 goto out;
1317 }
1318
1319 if (key->cert->type != SSH2_CERT_TYPE_USER &&
1320 key->cert->type != SSH2_CERT_TYPE_HOST) {
1321 error("Unknown certificate type %u", key->cert->type);
1322 goto out;
1323 }
1324
1325 buffer_append(&tmp, principals, plen);
1326 while (buffer_len(&tmp) > 0) {
1327 if (key->cert->nprincipals >= CERT_MAX_PRINCIPALS) {
Damien Miller41396572010-03-04 21:51:11 +11001328 error("%s: Too many principals", __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001329 goto out;
1330 }
Damien Millerda108ec2010-08-31 22:36:39 +10001331 if ((principal = buffer_get_cstring_ret(&tmp, &plen)) == NULL) {
Damien Miller41396572010-03-04 21:51:11 +11001332 error("%s: Principals data invalid", __func__);
1333 goto out;
1334 }
Damien Miller0a80ca12010-02-27 07:55:05 +11001335 key->cert->principals = xrealloc(key->cert->principals,
1336 key->cert->nprincipals + 1, sizeof(*key->cert->principals));
1337 key->cert->principals[key->cert->nprincipals++] = principal;
1338 }
1339
1340 buffer_clear(&tmp);
1341
Damien Miller4e270b02010-04-16 15:56:21 +10001342 buffer_append(&key->cert->critical, critical, clen);
1343 buffer_append(&tmp, critical, clen);
Damien Miller0a80ca12010-02-27 07:55:05 +11001344 /* validate structure */
1345 while (buffer_len(&tmp) != 0) {
Damien Miller2befbad2010-03-04 21:52:18 +11001346 if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||
1347 buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {
Damien Miller4e270b02010-04-16 15:56:21 +10001348 error("%s: critical option data invalid", __func__);
1349 goto out;
1350 }
1351 }
1352 buffer_clear(&tmp);
1353
1354 buffer_append(&key->cert->extensions, exts, elen);
1355 buffer_append(&tmp, exts, elen);
1356 /* validate structure */
1357 while (buffer_len(&tmp) != 0) {
1358 if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||
1359 buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {
1360 error("%s: extension data invalid", __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001361 goto out;
1362 }
1363 }
1364 buffer_clear(&tmp);
1365
1366 if ((key->cert->signature_key = key_from_blob(sig_key,
1367 sklen)) == NULL) {
Damien Miller41396572010-03-04 21:51:11 +11001368 error("%s: Signature key invalid", __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001369 goto out;
1370 }
1371 if (key->cert->signature_key->type != KEY_RSA &&
Damien Millereb8b60e2010-08-31 22:41:14 +10001372 key->cert->signature_key->type != KEY_DSA &&
1373 key->cert->signature_key->type != KEY_ECDSA) {
Damien Miller41396572010-03-04 21:51:11 +11001374 error("%s: Invalid signature key type %s (%d)", __func__,
Damien Miller0a80ca12010-02-27 07:55:05 +11001375 key_type(key->cert->signature_key),
1376 key->cert->signature_key->type);
1377 goto out;
1378 }
1379
1380 switch (key_verify(key->cert->signature_key, sig, slen,
1381 buffer_ptr(&key->cert->certblob), signed_len)) {
1382 case 1:
Damien Miller41396572010-03-04 21:51:11 +11001383 ret = 0;
Damien Miller0a80ca12010-02-27 07:55:05 +11001384 break; /* Good signature */
1385 case 0:
Damien Miller41396572010-03-04 21:51:11 +11001386 error("%s: Invalid signature on certificate", __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001387 goto out;
1388 case -1:
Damien Miller41396572010-03-04 21:51:11 +11001389 error("%s: Certificate signature verification failed",
1390 __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001391 goto out;
1392 }
1393
Damien Miller0a80ca12010-02-27 07:55:05 +11001394 out:
1395 buffer_free(&tmp);
1396 if (principals != NULL)
1397 xfree(principals);
Damien Miller4e270b02010-04-16 15:56:21 +10001398 if (critical != NULL)
1399 xfree(critical);
1400 if (exts != NULL)
1401 xfree(exts);
Damien Miller0a80ca12010-02-27 07:55:05 +11001402 if (sig_key != NULL)
1403 xfree(sig_key);
1404 if (sig != NULL)
1405 xfree(sig);
1406 return ret;
1407}
1408
Damien Miller0bc1bd82000-11-13 22:57:25 +11001409Key *
Damien Millerf58b58c2003-11-17 21:18:23 +11001410key_from_blob(const u_char *blob, u_int blen)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001411{
1412 Buffer b;
Damien Millereb8b60e2010-08-31 22:41:14 +10001413 int rlen, type, nid = -1;
1414 char *ktype = NULL, *curve = NULL;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001415 Key *key = NULL;
Damien Millereb8b60e2010-08-31 22:41:14 +10001416 EC_POINT *q = NULL;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001417
1418#ifdef DEBUG_PK
1419 dump_base64(stderr, blob, blen);
1420#endif
1421 buffer_init(&b);
1422 buffer_append(&b, blob, blen);
Damien Millerda108ec2010-08-31 22:36:39 +10001423 if ((ktype = buffer_get_cstring_ret(&b, NULL)) == NULL) {
Darren Tucker08d04fa2004-11-05 20:42:28 +11001424 error("key_from_blob: can't read key type");
1425 goto out;
1426 }
1427
Damien Miller0bc1bd82000-11-13 22:57:25 +11001428 type = key_type_from_name(ktype);
Damien Millereb8b60e2010-08-31 22:41:14 +10001429 if (key_type_plain(type) == KEY_ECDSA)
1430 nid = key_ecdsa_nid_from_name(ktype);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001431
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001432 switch (type) {
Damien Miller0a80ca12010-02-27 07:55:05 +11001433 case KEY_RSA_CERT:
Damien Miller4e270b02010-04-16 15:56:21 +10001434 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1435 /* FALLTHROUGH */
1436 case KEY_RSA:
1437 case KEY_RSA_CERT_V00:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001438 key = key_new(type);
Darren Tucker08d04fa2004-11-05 20:42:28 +11001439 if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 ||
1440 buffer_get_bignum2_ret(&b, key->rsa->n) == -1) {
1441 error("key_from_blob: can't read rsa key");
Damien Miller0a80ca12010-02-27 07:55:05 +11001442 badkey:
Darren Tucker08d04fa2004-11-05 20:42:28 +11001443 key_free(key);
1444 key = NULL;
1445 goto out;
1446 }
Damien Miller0bc1bd82000-11-13 22:57:25 +11001447#ifdef DEBUG_PK
1448 RSA_print_fp(stderr, key->rsa, 8);
1449#endif
1450 break;
Damien Miller0a80ca12010-02-27 07:55:05 +11001451 case KEY_DSA_CERT:
Damien Miller4e270b02010-04-16 15:56:21 +10001452 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1453 /* FALLTHROUGH */
1454 case KEY_DSA:
1455 case KEY_DSA_CERT_V00:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001456 key = key_new(type);
Darren Tucker08d04fa2004-11-05 20:42:28 +11001457 if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 ||
1458 buffer_get_bignum2_ret(&b, key->dsa->q) == -1 ||
1459 buffer_get_bignum2_ret(&b, key->dsa->g) == -1 ||
1460 buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) {
1461 error("key_from_blob: can't read dsa key");
Damien Miller0a80ca12010-02-27 07:55:05 +11001462 goto badkey;
Darren Tucker08d04fa2004-11-05 20:42:28 +11001463 }
Damien Miller0bc1bd82000-11-13 22:57:25 +11001464#ifdef DEBUG_PK
1465 DSA_print_fp(stderr, key->dsa, 8);
1466#endif
1467 break;
Damien Millereb8b60e2010-08-31 22:41:14 +10001468 case KEY_ECDSA_CERT:
1469 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1470 /* FALLTHROUGH */
1471 case KEY_ECDSA:
1472 key = key_new(type);
1473 key->ecdsa_nid = nid;
1474 if ((curve = buffer_get_string_ret(&b, NULL)) == NULL) {
1475 error("key_from_blob: can't read ecdsa curve");
1476 goto badkey;
1477 }
1478 if (key->ecdsa_nid != key_curve_name_to_nid(curve)) {
1479 error("key_from_blob: ecdsa curve doesn't match type");
1480 goto badkey;
1481 }
1482 if (key->ecdsa != NULL)
1483 EC_KEY_free(key->ecdsa);
1484 if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
1485 == NULL)
1486 fatal("key_from_blob: EC_KEY_new_by_curve_name failed");
1487 if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL)
1488 fatal("key_from_blob: EC_POINT_new failed");
1489 if (buffer_get_ecpoint_ret(&b, EC_KEY_get0_group(key->ecdsa),
1490 q) == -1) {
1491 error("key_from_blob: can't read ecdsa key point");
1492 goto badkey;
1493 }
1494 if (key_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
1495 q) != 0)
1496 goto badkey;
1497 if (EC_KEY_set_public_key(key->ecdsa, q) != 1)
1498 fatal("key_from_blob: EC_KEY_set_public_key failed");
1499#ifdef DEBUG_PK
1500 key_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
1501#endif
1502 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001503 case KEY_UNSPEC:
1504 key = key_new(type);
1505 break;
1506 default:
1507 error("key_from_blob: cannot handle type %s", ktype);
Darren Tucker08d04fa2004-11-05 20:42:28 +11001508 goto out;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001509 }
Damien Miller0a80ca12010-02-27 07:55:05 +11001510 if (key_is_cert(key) && cert_parse(&b, key, blob, blen) == -1) {
1511 error("key_from_blob: can't parse cert data");
1512 goto badkey;
1513 }
Damien Miller0bc1bd82000-11-13 22:57:25 +11001514 rlen = buffer_len(&b);
1515 if (key != NULL && rlen != 0)
1516 error("key_from_blob: remaining bytes in key blob %d", rlen);
Darren Tucker08d04fa2004-11-05 20:42:28 +11001517 out:
1518 if (ktype != NULL)
1519 xfree(ktype);
Damien Millereb8b60e2010-08-31 22:41:14 +10001520 if (curve != NULL)
1521 xfree(curve);
1522 if (q != NULL)
1523 EC_POINT_free(q);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001524 buffer_free(&b);
1525 return key;
1526}
1527
1528int
Damien Millerf58b58c2003-11-17 21:18:23 +11001529key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001530{
1531 Buffer b;
1532 int len;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001533
1534 if (key == NULL) {
1535 error("key_to_blob: key == NULL");
1536 return 0;
1537 }
1538 buffer_init(&b);
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001539 switch (key->type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001540 case KEY_DSA_CERT_V00:
1541 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001542 case KEY_DSA_CERT:
Damien Millereb8b60e2010-08-31 22:41:14 +10001543 case KEY_ECDSA_CERT:
Damien Miller0a80ca12010-02-27 07:55:05 +11001544 case KEY_RSA_CERT:
1545 /* Use the existing blob */
1546 buffer_append(&b, buffer_ptr(&key->cert->certblob),
1547 buffer_len(&key->cert->certblob));
1548 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001549 case KEY_DSA:
1550 buffer_put_cstring(&b, key_ssh_name(key));
1551 buffer_put_bignum2(&b, key->dsa->p);
1552 buffer_put_bignum2(&b, key->dsa->q);
1553 buffer_put_bignum2(&b, key->dsa->g);
1554 buffer_put_bignum2(&b, key->dsa->pub_key);
1555 break;
Damien Millereb8b60e2010-08-31 22:41:14 +10001556 case KEY_ECDSA:
1557 buffer_put_cstring(&b, key_ssh_name(key));
1558 buffer_put_cstring(&b, key_curve_nid_to_name(key->ecdsa_nid));
1559 buffer_put_ecpoint(&b, EC_KEY_get0_group(key->ecdsa),
1560 EC_KEY_get0_public_key(key->ecdsa));
1561 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001562 case KEY_RSA:
1563 buffer_put_cstring(&b, key_ssh_name(key));
Damien Miller0bc1bd82000-11-13 22:57:25 +11001564 buffer_put_bignum2(&b, key->rsa->e);
Ben Lindstrombf555ba2001-01-18 02:04:35 +00001565 buffer_put_bignum2(&b, key->rsa->n);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001566 break;
1567 default:
Ben Lindstrom99a30f12001-09-18 05:49:14 +00001568 error("key_to_blob: unsupported key type %d", key->type);
1569 buffer_free(&b);
1570 return 0;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001571 }
1572 len = buffer_len(&b);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001573 if (lenp != NULL)
1574 *lenp = len;
Ben Lindstrom2bf759c2002-07-07 22:13:31 +00001575 if (blobp != NULL) {
1576 *blobp = xmalloc(len);
1577 memcpy(*blobp, buffer_ptr(&b), len);
1578 }
1579 memset(buffer_ptr(&b), 0, len);
1580 buffer_free(&b);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001581 return len;
1582}
1583
1584int
1585key_sign(
Damien Millerf58b58c2003-11-17 21:18:23 +11001586 const Key *key,
Ben Lindstrom90fd8142002-02-26 18:09:42 +00001587 u_char **sigp, u_int *lenp,
Damien Millerf58b58c2003-11-17 21:18:23 +11001588 const u_char *data, u_int datalen)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001589{
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001590 switch (key->type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001591 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001592 case KEY_DSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001593 case KEY_DSA:
1594 return ssh_dss_sign(key, sigp, lenp, data, datalen);
Damien Millereb8b60e2010-08-31 22:41:14 +10001595 case KEY_ECDSA_CERT:
1596 case KEY_ECDSA:
1597 return ssh_ecdsa_sign(key, sigp, lenp, data, datalen);
Damien Miller4e270b02010-04-16 15:56:21 +10001598 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001599 case KEY_RSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001600 case KEY_RSA:
1601 return ssh_rsa_sign(key, sigp, lenp, data, datalen);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001602 default:
Darren Tucker5cb30ad2004-08-12 22:40:24 +10001603 error("key_sign: invalid key type %d", key->type);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001604 return -1;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001605 }
1606}
1607
Ben Lindstrom01fff0c2002-06-06 20:54:07 +00001608/*
1609 * key_verify returns 1 for a correct signature, 0 for an incorrect signature
1610 * and -1 on error.
1611 */
Damien Miller0bc1bd82000-11-13 22:57:25 +11001612int
1613key_verify(
Damien Millerf58b58c2003-11-17 21:18:23 +11001614 const Key *key,
1615 const u_char *signature, u_int signaturelen,
1616 const u_char *data, u_int datalen)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001617{
Ben Lindstrom5363aee2001-06-25 04:42:20 +00001618 if (signaturelen == 0)
1619 return -1;
1620
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001621 switch (key->type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001622 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001623 case KEY_DSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001624 case KEY_DSA:
1625 return ssh_dss_verify(key, signature, signaturelen, data, datalen);
Damien Millereb8b60e2010-08-31 22:41:14 +10001626 case KEY_ECDSA_CERT:
1627 case KEY_ECDSA:
1628 return ssh_ecdsa_verify(key, signature, signaturelen, data, datalen);
Damien Miller4e270b02010-04-16 15:56:21 +10001629 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001630 case KEY_RSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001631 case KEY_RSA:
1632 return ssh_rsa_verify(key, signature, signaturelen, data, datalen);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001633 default:
Darren Tucker5cb30ad2004-08-12 22:40:24 +10001634 error("key_verify: invalid key type %d", key->type);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001635 return -1;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001636 }
1637}
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001638
1639/* Converts a private to a public key */
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001640Key *
Damien Millerf58b58c2003-11-17 21:18:23 +11001641key_demote(const Key *k)
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001642{
1643 Key *pk;
Ben Lindstrom6328ab32002-03-22 02:54:23 +00001644
Damien Miller07d86be2006-03-26 14:19:21 +11001645 pk = xcalloc(1, sizeof(*pk));
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001646 pk->type = k->type;
1647 pk->flags = k->flags;
Damien Millereb8b60e2010-08-31 22:41:14 +10001648 pk->ecdsa_nid = k->ecdsa_nid;
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001649 pk->dsa = NULL;
Damien Millereb8b60e2010-08-31 22:41:14 +10001650 pk->ecdsa = NULL;
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001651 pk->rsa = NULL;
1652
1653 switch (k->type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001654 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001655 case KEY_RSA_CERT:
1656 key_cert_copy(k, pk);
1657 /* FALLTHROUGH */
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001658 case KEY_RSA1:
1659 case KEY_RSA:
1660 if ((pk->rsa = RSA_new()) == NULL)
1661 fatal("key_demote: RSA_new failed");
1662 if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL)
1663 fatal("key_demote: BN_dup failed");
1664 if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL)
1665 fatal("key_demote: BN_dup failed");
1666 break;
Damien Miller4e270b02010-04-16 15:56:21 +10001667 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001668 case KEY_DSA_CERT:
1669 key_cert_copy(k, pk);
1670 /* FALLTHROUGH */
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001671 case KEY_DSA:
1672 if ((pk->dsa = DSA_new()) == NULL)
1673 fatal("key_demote: DSA_new failed");
1674 if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL)
1675 fatal("key_demote: BN_dup failed");
1676 if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL)
1677 fatal("key_demote: BN_dup failed");
1678 if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL)
1679 fatal("key_demote: BN_dup failed");
1680 if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL)
1681 fatal("key_demote: BN_dup failed");
1682 break;
Damien Millereb8b60e2010-08-31 22:41:14 +10001683 case KEY_ECDSA_CERT:
1684 key_cert_copy(k, pk);
1685 /* FALLTHROUGH */
1686 case KEY_ECDSA:
1687 if ((pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid)) == NULL)
1688 fatal("key_demote: EC_KEY_new_by_curve_name failed");
1689 if (EC_KEY_set_public_key(pk->ecdsa,
1690 EC_KEY_get0_public_key(k->ecdsa)) != 1)
1691 fatal("key_demote: EC_KEY_set_public_key failed");
1692 break;
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001693 default:
1694 fatal("key_free: bad key type %d", k->type);
1695 break;
1696 }
1697
1698 return (pk);
1699}
Damien Miller0a80ca12010-02-27 07:55:05 +11001700
1701int
1702key_is_cert(const Key *k)
1703{
Damien Miller4e270b02010-04-16 15:56:21 +10001704 if (k == NULL)
1705 return 0;
1706 switch (k->type) {
1707 case KEY_RSA_CERT_V00:
1708 case KEY_DSA_CERT_V00:
1709 case KEY_RSA_CERT:
1710 case KEY_DSA_CERT:
Damien Millereb8b60e2010-08-31 22:41:14 +10001711 case KEY_ECDSA_CERT:
Damien Miller4e270b02010-04-16 15:56:21 +10001712 return 1;
1713 default:
1714 return 0;
1715 }
Damien Miller0a80ca12010-02-27 07:55:05 +11001716}
1717
1718/* Return the cert-less equivalent to a certified key type */
1719int
1720key_type_plain(int type)
1721{
1722 switch (type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001723 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001724 case KEY_RSA_CERT:
1725 return KEY_RSA;
Damien Miller4e270b02010-04-16 15:56:21 +10001726 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001727 case KEY_DSA_CERT:
1728 return KEY_DSA;
Damien Millereb8b60e2010-08-31 22:41:14 +10001729 case KEY_ECDSA_CERT:
1730 return KEY_ECDSA;
Damien Miller0a80ca12010-02-27 07:55:05 +11001731 default:
1732 return type;
1733 }
1734}
1735
1736/* Convert a KEY_RSA or KEY_DSA to their _CERT equivalent */
1737int
Damien Miller4e270b02010-04-16 15:56:21 +10001738key_to_certified(Key *k, int legacy)
Damien Miller0a80ca12010-02-27 07:55:05 +11001739{
1740 switch (k->type) {
1741 case KEY_RSA:
1742 k->cert = cert_new();
Damien Miller4e270b02010-04-16 15:56:21 +10001743 k->type = legacy ? KEY_RSA_CERT_V00 : KEY_RSA_CERT;
Damien Miller0a80ca12010-02-27 07:55:05 +11001744 return 0;
1745 case KEY_DSA:
1746 k->cert = cert_new();
Damien Miller4e270b02010-04-16 15:56:21 +10001747 k->type = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT;
Damien Miller0a80ca12010-02-27 07:55:05 +11001748 return 0;
Damien Millereb8b60e2010-08-31 22:41:14 +10001749 case KEY_ECDSA:
1750 k->cert = cert_new();
1751 k->type = KEY_ECDSA_CERT;
1752 return 0;
Damien Miller0a80ca12010-02-27 07:55:05 +11001753 default:
1754 error("%s: key has incorrect type %s", __func__, key_type(k));
1755 return -1;
1756 }
1757}
1758
1759/* Convert a KEY_RSA_CERT or KEY_DSA_CERT to their raw key equivalent */
1760int
1761key_drop_cert(Key *k)
1762{
1763 switch (k->type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001764 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001765 case KEY_RSA_CERT:
1766 cert_free(k->cert);
1767 k->type = KEY_RSA;
1768 return 0;
Damien Miller4e270b02010-04-16 15:56:21 +10001769 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001770 case KEY_DSA_CERT:
1771 cert_free(k->cert);
1772 k->type = KEY_DSA;
1773 return 0;
Damien Millereb8b60e2010-08-31 22:41:14 +10001774 case KEY_ECDSA_CERT:
1775 cert_free(k->cert);
1776 k->type = KEY_ECDSA;
1777 return 0;
Damien Miller0a80ca12010-02-27 07:55:05 +11001778 default:
1779 error("%s: key has incorrect type %s", __func__, key_type(k));
1780 return -1;
1781 }
1782}
1783
Damien Millereb8b60e2010-08-31 22:41:14 +10001784/*
1785 * Sign a KEY_RSA_CERT, KEY_DSA_CERT or KEY_ECDSA_CERT, (re-)generating
1786 * the signed certblob
1787 */
Damien Miller0a80ca12010-02-27 07:55:05 +11001788int
1789key_certify(Key *k, Key *ca)
1790{
1791 Buffer principals;
1792 u_char *ca_blob, *sig_blob, nonce[32];
1793 u_int i, ca_len, sig_len;
1794
1795 if (k->cert == NULL) {
1796 error("%s: key lacks cert info", __func__);
1797 return -1;
1798 }
1799
1800 if (!key_is_cert(k)) {
1801 error("%s: certificate has unknown type %d", __func__,
1802 k->cert->type);
1803 return -1;
1804 }
1805
Damien Millereb8b60e2010-08-31 22:41:14 +10001806 if (ca->type != KEY_RSA && ca->type != KEY_DSA &&
1807 ca->type != KEY_ECDSA) {
Damien Miller0a80ca12010-02-27 07:55:05 +11001808 error("%s: CA key has unsupported type %s", __func__,
1809 key_type(ca));
1810 return -1;
1811 }
1812
1813 key_to_blob(ca, &ca_blob, &ca_len);
1814
1815 buffer_clear(&k->cert->certblob);
1816 buffer_put_cstring(&k->cert->certblob, key_ssh_name(k));
1817
Damien Miller4e270b02010-04-16 15:56:21 +10001818 /* -v01 certs put nonce first */
Damien Millereb8b60e2010-08-31 22:41:14 +10001819 if (!key_cert_is_legacy(k)) {
Damien Miller4e270b02010-04-16 15:56:21 +10001820 arc4random_buf(&nonce, sizeof(nonce));
1821 buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
1822 }
1823
Damien Miller0a80ca12010-02-27 07:55:05 +11001824 switch (k->type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001825 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001826 case KEY_DSA_CERT:
1827 buffer_put_bignum2(&k->cert->certblob, k->dsa->p);
1828 buffer_put_bignum2(&k->cert->certblob, k->dsa->q);
1829 buffer_put_bignum2(&k->cert->certblob, k->dsa->g);
1830 buffer_put_bignum2(&k->cert->certblob, k->dsa->pub_key);
1831 break;
Damien Millereb8b60e2010-08-31 22:41:14 +10001832 case KEY_ECDSA_CERT:
1833 buffer_put_cstring(&k->cert->certblob,
1834 key_curve_nid_to_name(k->ecdsa_nid));
1835 buffer_put_ecpoint(&k->cert->certblob,
1836 EC_KEY_get0_group(k->ecdsa),
1837 EC_KEY_get0_public_key(k->ecdsa));
1838 break;
Damien Miller4e270b02010-04-16 15:56:21 +10001839 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001840 case KEY_RSA_CERT:
1841 buffer_put_bignum2(&k->cert->certblob, k->rsa->e);
1842 buffer_put_bignum2(&k->cert->certblob, k->rsa->n);
1843 break;
1844 default:
1845 error("%s: key has incorrect type %s", __func__, key_type(k));
1846 buffer_clear(&k->cert->certblob);
1847 xfree(ca_blob);
1848 return -1;
1849 }
1850
Damien Miller4e270b02010-04-16 15:56:21 +10001851 /* -v01 certs have a serial number next */
Damien Millereb8b60e2010-08-31 22:41:14 +10001852 if (!key_cert_is_legacy(k))
Damien Miller4e270b02010-04-16 15:56:21 +10001853 buffer_put_int64(&k->cert->certblob, k->cert->serial);
1854
Damien Miller0a80ca12010-02-27 07:55:05 +11001855 buffer_put_int(&k->cert->certblob, k->cert->type);
1856 buffer_put_cstring(&k->cert->certblob, k->cert->key_id);
1857
1858 buffer_init(&principals);
1859 for (i = 0; i < k->cert->nprincipals; i++)
1860 buffer_put_cstring(&principals, k->cert->principals[i]);
1861 buffer_put_string(&k->cert->certblob, buffer_ptr(&principals),
1862 buffer_len(&principals));
1863 buffer_free(&principals);
1864
1865 buffer_put_int64(&k->cert->certblob, k->cert->valid_after);
1866 buffer_put_int64(&k->cert->certblob, k->cert->valid_before);
1867 buffer_put_string(&k->cert->certblob,
Damien Miller4e270b02010-04-16 15:56:21 +10001868 buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical));
Damien Miller0a80ca12010-02-27 07:55:05 +11001869
Damien Miller4e270b02010-04-16 15:56:21 +10001870 /* -v01 certs have non-critical options here */
Damien Millereb8b60e2010-08-31 22:41:14 +10001871 if (!key_cert_is_legacy(k)) {
Damien Miller4e270b02010-04-16 15:56:21 +10001872 buffer_put_string(&k->cert->certblob,
1873 buffer_ptr(&k->cert->extensions),
1874 buffer_len(&k->cert->extensions));
1875 }
1876
1877 /* -v00 certs put the nonce at the end */
Damien Millereb8b60e2010-08-31 22:41:14 +10001878 if (key_cert_is_legacy(k))
Damien Miller4e270b02010-04-16 15:56:21 +10001879 buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
1880
Damien Miller0a80ca12010-02-27 07:55:05 +11001881 buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */
1882 buffer_put_string(&k->cert->certblob, ca_blob, ca_len);
1883 xfree(ca_blob);
1884
1885 /* Sign the whole mess */
1886 if (key_sign(ca, &sig_blob, &sig_len, buffer_ptr(&k->cert->certblob),
1887 buffer_len(&k->cert->certblob)) != 0) {
1888 error("%s: signature operation failed", __func__);
1889 buffer_clear(&k->cert->certblob);
1890 return -1;
1891 }
1892 /* Append signature and we are done */
1893 buffer_put_string(&k->cert->certblob, sig_blob, sig_len);
1894 xfree(sig_blob);
1895
1896 return 0;
1897}
1898
1899int
1900key_cert_check_authority(const Key *k, int want_host, int require_principal,
1901 const char *name, const char **reason)
1902{
1903 u_int i, principal_matches;
1904 time_t now = time(NULL);
1905
1906 if (want_host) {
1907 if (k->cert->type != SSH2_CERT_TYPE_HOST) {
1908 *reason = "Certificate invalid: not a host certificate";
1909 return -1;
1910 }
1911 } else {
1912 if (k->cert->type != SSH2_CERT_TYPE_USER) {
1913 *reason = "Certificate invalid: not a user certificate";
1914 return -1;
1915 }
1916 }
1917 if (now < 0) {
1918 error("%s: system clock lies before epoch", __func__);
1919 *reason = "Certificate invalid: not yet valid";
1920 return -1;
1921 }
1922 if ((u_int64_t)now < k->cert->valid_after) {
1923 *reason = "Certificate invalid: not yet valid";
1924 return -1;
1925 }
1926 if ((u_int64_t)now >= k->cert->valid_before) {
1927 *reason = "Certificate invalid: expired";
1928 return -1;
1929 }
1930 if (k->cert->nprincipals == 0) {
1931 if (require_principal) {
1932 *reason = "Certificate lacks principal list";
1933 return -1;
1934 }
Damien Miller30da3442010-05-10 11:58:03 +10001935 } else if (name != NULL) {
Damien Miller0a80ca12010-02-27 07:55:05 +11001936 principal_matches = 0;
1937 for (i = 0; i < k->cert->nprincipals; i++) {
1938 if (strcmp(name, k->cert->principals[i]) == 0) {
1939 principal_matches = 1;
1940 break;
1941 }
1942 }
1943 if (!principal_matches) {
1944 *reason = "Certificate invalid: name is not a listed "
1945 "principal";
1946 return -1;
1947 }
1948 }
1949 return 0;
1950}
Damien Miller4e270b02010-04-16 15:56:21 +10001951
1952int
1953key_cert_is_legacy(Key *k)
1954{
1955 switch (k->type) {
1956 case KEY_DSA_CERT_V00:
1957 case KEY_RSA_CERT_V00:
1958 return 1;
1959 default:
1960 return 0;
1961 }
1962}
Damien Millereb8b60e2010-08-31 22:41:14 +10001963
1964int
1965key_curve_name_to_nid(const char *name)
1966{
1967 if (strcmp(name, "nistp256") == 0)
1968 return NID_X9_62_prime256v1;
1969 else if (strcmp(name, "nistp384") == 0)
1970 return NID_secp384r1;
1971 else if (strcmp(name, "nistp521") == 0)
1972 return NID_secp521r1;
1973
1974 debug("%s: unsupported EC curve name \"%.100s\"", __func__, name);
1975 return -1;
1976}
1977
1978const char *
1979key_curve_nid_to_name(int nid)
1980{
1981 if (nid == NID_X9_62_prime256v1)
1982 return "nistp256";
1983 else if (nid == NID_secp384r1)
1984 return "nistp384";
1985 else if (nid == NID_secp521r1)
1986 return "nistp521";
1987
1988 error("%s: unsupported EC curve nid %d", __func__, nid);
1989 return NULL;
1990}
1991
1992int
1993key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
1994{
1995 BN_CTX *bnctx;
1996 EC_POINT *nq = NULL;
1997 BIGNUM *order, *x, *y, *tmp;
1998 int ret = -1;
1999
2000 if ((bnctx = BN_CTX_new()) == NULL)
2001 fatal("%s: BN_CTX_new failed", __func__);
2002 BN_CTX_start(bnctx);
2003
2004 /*
2005 * We shouldn't ever hit this case because bignum_get_ecpoint()
2006 * refuses to load GF2m points.
2007 */
2008 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
2009 NID_X9_62_prime_field) {
2010 error("%s: group is not a prime field", __func__);
2011 goto out;
2012 }
2013
2014 /* Q != infinity */
2015 if (EC_POINT_is_at_infinity(group, public)) {
2016 error("%s: received degenerate public key (infinity)",
2017 __func__);
2018 goto out;
2019 }
2020
2021 if ((x = BN_CTX_get(bnctx)) == NULL ||
2022 (y = BN_CTX_get(bnctx)) == NULL ||
2023 (order = BN_CTX_get(bnctx)) == NULL ||
2024 (tmp = BN_CTX_get(bnctx)) == NULL)
2025 fatal("%s: BN_CTX_get failed", __func__);
2026
2027 /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
2028 if (EC_GROUP_get_order(group, order, bnctx) != 1)
2029 fatal("%s: EC_GROUP_get_order failed", __func__);
2030 if (EC_POINT_get_affine_coordinates_GFp(group, public,
2031 x, y, bnctx) != 1)
2032 fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__);
2033 if (BN_num_bits(x) <= BN_num_bits(order) / 2) {
2034 error("%s: public key x coordinate too small: "
2035 "bits(x) = %d, bits(order)/2 = %d", __func__,
2036 BN_num_bits(x), BN_num_bits(order) / 2);
2037 goto out;
2038 }
2039 if (BN_num_bits(y) <= BN_num_bits(order) / 2) {
2040 error("%s: public key y coordinate too small: "
2041 "bits(y) = %d, bits(order)/2 = %d", __func__,
2042 BN_num_bits(x), BN_num_bits(order) / 2);
2043 goto out;
2044 }
2045
2046 /* nQ == infinity (n == order of subgroup) */
2047 if ((nq = EC_POINT_new(group)) == NULL)
2048 fatal("%s: BN_CTX_tmp failed", __func__);
2049 if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1)
2050 fatal("%s: EC_GROUP_mul failed", __func__);
2051 if (EC_POINT_is_at_infinity(group, nq) != 1) {
2052 error("%s: received degenerate public key (nQ != infinity)",
2053 __func__);
2054 goto out;
2055 }
2056
2057 /* x < order - 1, y < order - 1 */
2058 if (!BN_sub(tmp, order, BN_value_one()))
2059 fatal("%s: BN_sub failed", __func__);
2060 if (BN_cmp(x, tmp) >= 0) {
2061 error("%s: public key x coordinate >= group order - 1",
2062 __func__);
2063 goto out;
2064 }
2065 if (BN_cmp(y, tmp) >= 0) {
2066 error("%s: public key y coordinate >= group order - 1",
2067 __func__);
2068 goto out;
2069 }
2070 ret = 0;
2071 out:
2072 BN_CTX_free(bnctx);
2073 EC_POINT_free(nq);
2074 return ret;
2075}
2076
2077int
2078key_ec_validate_private(const EC_KEY *key)
2079{
2080 BN_CTX *bnctx;
2081 BIGNUM *order, *tmp;
2082 int ret = -1;
2083
2084 if ((bnctx = BN_CTX_new()) == NULL)
2085 fatal("%s: BN_CTX_new failed", __func__);
2086 BN_CTX_start(bnctx);
2087
2088 if ((order = BN_CTX_get(bnctx)) == NULL ||
2089 (tmp = BN_CTX_get(bnctx)) == NULL)
2090 fatal("%s: BN_CTX_get failed", __func__);
2091
2092 /* log2(private) > log2(order)/2 */
2093 if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1)
2094 fatal("%s: EC_GROUP_get_order failed", __func__);
2095 if (BN_num_bits(EC_KEY_get0_private_key(key)) <=
2096 BN_num_bits(order) / 2) {
2097 error("%s: private key too small: "
2098 "bits(y) = %d, bits(order)/2 = %d", __func__,
2099 BN_num_bits(EC_KEY_get0_private_key(key)),
2100 BN_num_bits(order) / 2);
2101 goto out;
2102 }
2103
2104 /* private < order - 1 */
2105 if (!BN_sub(tmp, order, BN_value_one()))
2106 fatal("%s: BN_sub failed", __func__);
2107 if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0) {
2108 error("%s: private key >= group order - 1", __func__);
2109 goto out;
2110 }
2111 ret = 0;
2112 out:
2113 BN_CTX_free(bnctx);
2114 return ret;
2115}
2116
2117#if defined(DEBUG_KEXECDH) || defined(DEBUG_PK)
2118void
2119key_dump_ec_point(const EC_GROUP *group, const EC_POINT *point)
2120{
2121 BIGNUM *x, *y;
2122 BN_CTX *bnctx;
2123
2124 if (point == NULL) {
2125 fputs("point=(NULL)\n", stderr);
2126 return;
2127 }
2128 if ((bnctx = BN_CTX_new()) == NULL)
2129 fatal("%s: BN_CTX_new failed", __func__);
2130 BN_CTX_start(bnctx);
2131 if ((x = BN_CTX_get(bnctx)) == NULL || (y = BN_CTX_get(bnctx)) == NULL)
2132 fatal("%s: BN_CTX_get failed", __func__);
2133 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
2134 NID_X9_62_prime_field)
2135 fatal("%s: group is not a prime field", __func__);
2136 if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, bnctx) != 1)
2137 fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__);
2138 fputs("x=", stderr);
2139 BN_print_fp(stderr, x);
2140 fputs("\ny=", stderr);
2141 BN_print_fp(stderr, y);
2142 fputs("\n", stderr);
2143 BN_CTX_free(bnctx);
2144}
2145
2146void
2147key_dump_ec_key(const EC_KEY *key)
2148{
2149 const BIGNUM *exponent;
2150
2151 key_dump_ec_point(EC_KEY_get0_group(key), EC_KEY_get0_public_key(key));
2152 fputs("exponent=", stderr);
2153 if ((exponent = EC_KEY_get0_private_key(key)) == NULL)
2154 fputs("(NULL)", stderr);
2155 else
2156 BN_print_fp(stderr, EC_KEY_get0_private_key(key));
2157 fputs("\n", stderr);
2158}
2159#endif /* defined(DEBUG_KEXECDH) || defined(DEBUG_PK) */
2160