blob: e8fc5b1b835e1edf5afcca39713ea0b5a5f2d0f3 [file] [log] [blame]
Damien Miller1f0311c2014-05-15 14:24:09 +10001/* $OpenBSD: key.c,v 1.117 2014/04/29 18:01:49 markus 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 Miller5be9d9e2013-12-07 11:24:01 +110042#include "crypto_api.h"
43
Damien Miller450a7a12000-03-26 13:04:51 +100044#include <openssl/evp.h>
Darren Tucker3d295a62008-02-28 19:22:04 +110045#include <openbsd-compat/openssl-compat.h>
Ben Lindstrom226cfa02001-01-22 05:34:40 +000046
Damien Millerded319c2006-09-01 15:38:36 +100047#include <stdarg.h>
Damien Millera7a73ee2006-08-05 11:37:59 +100048#include <stdio.h>
Damien Millere3476ed2006-07-24 14:13:33 +100049#include <string.h>
50
Damien Miller450a7a12000-03-26 13:04:51 +100051#include "xmalloc.h"
52#include "key.h"
Damien Miller0bc1bd82000-11-13 22:57:25 +110053#include "rsa.h"
Damien Millereba71ba2000-04-29 23:57:08 +100054#include "uuencode.h"
Damien Miller0bc1bd82000-11-13 22:57:25 +110055#include "buffer.h"
Ben Lindstrom226cfa02001-01-22 05:34:40 +000056#include "log.h"
Damien Miller8a0268f2010-07-16 13:57:51 +100057#include "misc.h"
Damien Miller0a80ca12010-02-27 07:55:05 +110058#include "ssh2.h"
Damien Millerb3051d02014-01-10 10:58:53 +110059#include "digest.h"
Damien Miller0a80ca12010-02-27 07:55:05 +110060
Damien Millerf3747bf2013-01-18 11:44:04 +110061static int to_blob(const Key *, u_char **, u_int *, int);
Damien Miller4a3a9d42013-10-30 22:19:47 +110062static Key *key_from_blob2(const u_char *, u_int, int);
Damien Millerf3747bf2013-01-18 11:44:04 +110063
Damien Miller0a80ca12010-02-27 07:55:05 +110064static struct KeyCert *
65cert_new(void)
66{
67 struct KeyCert *cert;
68
69 cert = xcalloc(1, sizeof(*cert));
70 buffer_init(&cert->certblob);
Damien Miller4e270b02010-04-16 15:56:21 +100071 buffer_init(&cert->critical);
72 buffer_init(&cert->extensions);
Damien Miller0a80ca12010-02-27 07:55:05 +110073 cert->key_id = NULL;
74 cert->principals = NULL;
75 cert->signature_key = NULL;
76 return cert;
77}
Damien Miller450a7a12000-03-26 13:04:51 +100078
79Key *
80key_new(int type)
81{
82 Key *k;
Damien Miller1f0311c2014-05-15 14:24:09 +100083#ifdef WITH_OPENSSL
Damien Miller450a7a12000-03-26 13:04:51 +100084 RSA *rsa;
85 DSA *dsa;
Damien Miller1f0311c2014-05-15 14:24:09 +100086#endif
87
Damien Miller07d86be2006-03-26 14:19:21 +110088 k = xcalloc(1, sizeof(*k));
Damien Miller450a7a12000-03-26 13:04:51 +100089 k->type = type;
Damien Millereb8b60e2010-08-31 22:41:14 +100090 k->ecdsa = NULL;
91 k->ecdsa_nid = -1;
Damien Millereba71ba2000-04-29 23:57:08 +100092 k->dsa = NULL;
93 k->rsa = NULL;
Damien Miller0a80ca12010-02-27 07:55:05 +110094 k->cert = NULL;
Damien Miller5be9d9e2013-12-07 11:24:01 +110095 k->ed25519_sk = NULL;
96 k->ed25519_pk = NULL;
Damien Miller450a7a12000-03-26 13:04:51 +100097 switch (k->type) {
Damien Miller1f0311c2014-05-15 14:24:09 +100098#ifdef WITH_OPENSSL
Damien Miller0bc1bd82000-11-13 22:57:25 +110099 case KEY_RSA1:
Damien Miller450a7a12000-03-26 13:04:51 +1000100 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000101 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100102 case KEY_RSA_CERT:
Damien Millerda755162002-01-22 23:09:22 +1100103 if ((rsa = RSA_new()) == NULL)
104 fatal("key_new: RSA_new failed");
105 if ((rsa->n = BN_new()) == NULL)
106 fatal("key_new: BN_new failed");
107 if ((rsa->e = BN_new()) == NULL)
108 fatal("key_new: BN_new failed");
Damien Miller450a7a12000-03-26 13:04:51 +1000109 k->rsa = rsa;
110 break;
111 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000112 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100113 case KEY_DSA_CERT:
Damien Millerda755162002-01-22 23:09:22 +1100114 if ((dsa = DSA_new()) == NULL)
115 fatal("key_new: DSA_new failed");
116 if ((dsa->p = BN_new()) == NULL)
117 fatal("key_new: BN_new failed");
118 if ((dsa->q = BN_new()) == NULL)
119 fatal("key_new: BN_new failed");
120 if ((dsa->g = BN_new()) == NULL)
121 fatal("key_new: BN_new failed");
122 if ((dsa->pub_key = BN_new()) == NULL)
123 fatal("key_new: BN_new failed");
Damien Miller450a7a12000-03-26 13:04:51 +1000124 k->dsa = dsa;
125 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000126#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000127 case KEY_ECDSA:
128 case KEY_ECDSA_CERT:
129 /* Cannot do anything until we know the group */
130 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000131#endif
Damien Miller1f0311c2014-05-15 14:24:09 +1000132#endif
Damien Miller5be9d9e2013-12-07 11:24:01 +1100133 case KEY_ED25519:
134 case KEY_ED25519_CERT:
135 /* no need to prealloc */
136 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100137 case KEY_UNSPEC:
Damien Miller450a7a12000-03-26 13:04:51 +1000138 break;
139 default:
140 fatal("key_new: bad key type %d", k->type);
141 break;
142 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100143
144 if (key_is_cert(k))
145 k->cert = cert_new();
146
Damien Miller450a7a12000-03-26 13:04:51 +1000147 return k;
148}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000149
Damien Miller0a80ca12010-02-27 07:55:05 +1100150void
151key_add_private(Key *k)
Damien Miller0bc1bd82000-11-13 22:57:25 +1100152{
Damien Miller0bc1bd82000-11-13 22:57:25 +1100153 switch (k->type) {
Damien Miller1f0311c2014-05-15 14:24:09 +1000154#ifdef WITH_OPENSSL
Damien Miller0bc1bd82000-11-13 22:57:25 +1100155 case KEY_RSA1:
156 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000157 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100158 case KEY_RSA_CERT:
Damien Millerda755162002-01-22 23:09:22 +1100159 if ((k->rsa->d = BN_new()) == NULL)
160 fatal("key_new_private: BN_new failed");
161 if ((k->rsa->iqmp = BN_new()) == NULL)
162 fatal("key_new_private: BN_new failed");
163 if ((k->rsa->q = BN_new()) == NULL)
164 fatal("key_new_private: BN_new failed");
165 if ((k->rsa->p = BN_new()) == NULL)
166 fatal("key_new_private: BN_new failed");
167 if ((k->rsa->dmq1 = BN_new()) == NULL)
168 fatal("key_new_private: BN_new failed");
169 if ((k->rsa->dmp1 = BN_new()) == NULL)
170 fatal("key_new_private: BN_new failed");
Damien Miller0bc1bd82000-11-13 22:57:25 +1100171 break;
172 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000173 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100174 case KEY_DSA_CERT:
Damien Millerda755162002-01-22 23:09:22 +1100175 if ((k->dsa->priv_key = BN_new()) == NULL)
176 fatal("key_new_private: BN_new failed");
Damien Miller0bc1bd82000-11-13 22:57:25 +1100177 break;
Damien Millereb8b60e2010-08-31 22:41:14 +1000178 case KEY_ECDSA:
179 case KEY_ECDSA_CERT:
180 /* Cannot do anything until we know the group */
181 break;
Damien Miller1f0311c2014-05-15 14:24:09 +1000182#endif
Damien Miller5be9d9e2013-12-07 11:24:01 +1100183 case KEY_ED25519:
184 case KEY_ED25519_CERT:
185 /* no need to prealloc */
186 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100187 case KEY_UNSPEC:
188 break;
189 default:
190 break;
191 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100192}
193
194Key *
195key_new_private(int type)
196{
197 Key *k = key_new(type);
198
199 key_add_private(k);
Damien Miller0bc1bd82000-11-13 22:57:25 +1100200 return k;
201}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000202
Damien Miller0a80ca12010-02-27 07:55:05 +1100203static void
204cert_free(struct KeyCert *cert)
205{
206 u_int i;
207
208 buffer_free(&cert->certblob);
Damien Miller4e270b02010-04-16 15:56:21 +1000209 buffer_free(&cert->critical);
210 buffer_free(&cert->extensions);
Darren Tuckera627d422013-06-02 07:31:17 +1000211 free(cert->key_id);
Damien Miller0a80ca12010-02-27 07:55:05 +1100212 for (i = 0; i < cert->nprincipals; i++)
Darren Tuckera627d422013-06-02 07:31:17 +1000213 free(cert->principals[i]);
214 free(cert->principals);
Damien Miller0a80ca12010-02-27 07:55:05 +1100215 if (cert->signature_key != NULL)
216 key_free(cert->signature_key);
Darren Tuckera627d422013-06-02 07:31:17 +1000217 free(cert);
Damien Miller0a80ca12010-02-27 07:55:05 +1100218}
219
Damien Miller450a7a12000-03-26 13:04:51 +1000220void
221key_free(Key *k)
222{
Damien Miller429fcc22006-03-26 14:02:16 +1100223 if (k == NULL)
Damien Millerbbaad772006-03-26 14:03:03 +1100224 fatal("key_free: key is NULL");
Damien Miller450a7a12000-03-26 13:04:51 +1000225 switch (k->type) {
Damien Miller1f0311c2014-05-15 14:24:09 +1000226#ifdef WITH_OPENSSL
Damien Miller0bc1bd82000-11-13 22:57:25 +1100227 case KEY_RSA1:
Damien Miller450a7a12000-03-26 13:04:51 +1000228 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000229 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100230 case KEY_RSA_CERT:
Damien Miller450a7a12000-03-26 13:04:51 +1000231 if (k->rsa != NULL)
232 RSA_free(k->rsa);
233 k->rsa = NULL;
234 break;
235 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000236 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100237 case KEY_DSA_CERT:
Damien Miller450a7a12000-03-26 13:04:51 +1000238 if (k->dsa != NULL)
239 DSA_free(k->dsa);
240 k->dsa = NULL;
241 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000242#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000243 case KEY_ECDSA:
244 case KEY_ECDSA_CERT:
245 if (k->ecdsa != NULL)
246 EC_KEY_free(k->ecdsa);
247 k->ecdsa = NULL;
248 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000249#endif
Damien Miller5be9d9e2013-12-07 11:24:01 +1100250 case KEY_ED25519:
251 case KEY_ED25519_CERT:
252 if (k->ed25519_pk) {
Damien Millera5103f42014-02-04 11:20:14 +1100253 explicit_bzero(k->ed25519_pk, ED25519_PK_SZ);
Damien Miller5be9d9e2013-12-07 11:24:01 +1100254 free(k->ed25519_pk);
255 k->ed25519_pk = NULL;
256 }
257 if (k->ed25519_sk) {
Damien Millera5103f42014-02-04 11:20:14 +1100258 explicit_bzero(k->ed25519_sk, ED25519_SK_SZ);
Damien Miller5be9d9e2013-12-07 11:24:01 +1100259 free(k->ed25519_sk);
260 k->ed25519_sk = NULL;
261 }
262 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100263 case KEY_UNSPEC:
264 break;
Damien Miller450a7a12000-03-26 13:04:51 +1000265 default:
266 fatal("key_free: bad key type %d", k->type);
267 break;
268 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100269 if (key_is_cert(k)) {
270 if (k->cert != NULL)
271 cert_free(k->cert);
272 k->cert = NULL;
273 }
274
Darren Tuckera627d422013-06-02 07:31:17 +1000275 free(k);
Damien Miller450a7a12000-03-26 13:04:51 +1000276}
Damien Millerf58b58c2003-11-17 21:18:23 +1100277
Damien Miller0a80ca12010-02-27 07:55:05 +1100278static int
279cert_compare(struct KeyCert *a, struct KeyCert *b)
Damien Miller450a7a12000-03-26 13:04:51 +1000280{
Damien Miller0a80ca12010-02-27 07:55:05 +1100281 if (a == NULL && b == NULL)
282 return 1;
283 if (a == NULL || b == NULL)
Damien Miller450a7a12000-03-26 13:04:51 +1000284 return 0;
Damien Miller0a80ca12010-02-27 07:55:05 +1100285 if (buffer_len(&a->certblob) != buffer_len(&b->certblob))
286 return 0;
Damien Millerea1651c2010-07-16 13:58:37 +1000287 if (timingsafe_bcmp(buffer_ptr(&a->certblob), buffer_ptr(&b->certblob),
Damien Miller0a80ca12010-02-27 07:55:05 +1100288 buffer_len(&a->certblob)) != 0)
289 return 0;
290 return 1;
291}
292
293/*
294 * Compare public portions of key only, allowing comparisons between
295 * certificates and plain keys too.
296 */
297int
298key_equal_public(const Key *a, const Key *b)
299{
Damien Miller1f0311c2014-05-15 14:24:09 +1000300#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
Damien Millereb8b60e2010-08-31 22:41:14 +1000301 BN_CTX *bnctx;
Darren Tucker8ccb7392010-09-10 12:28:24 +1000302#endif
Damien Millereb8b60e2010-08-31 22:41:14 +1000303
Damien Miller0a80ca12010-02-27 07:55:05 +1100304 if (a == NULL || b == NULL ||
305 key_type_plain(a->type) != key_type_plain(b->type))
306 return 0;
307
Damien Miller450a7a12000-03-26 13:04:51 +1000308 switch (a->type) {
Damien Miller1f0311c2014-05-15 14:24:09 +1000309#ifdef WITH_OPENSSL
Damien Miller0bc1bd82000-11-13 22:57:25 +1100310 case KEY_RSA1:
Damien Miller4e270b02010-04-16 15:56:21 +1000311 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100312 case KEY_RSA_CERT:
Damien Miller450a7a12000-03-26 13:04:51 +1000313 case KEY_RSA:
314 return a->rsa != NULL && b->rsa != NULL &&
315 BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
316 BN_cmp(a->rsa->n, b->rsa->n) == 0;
Damien Miller4e270b02010-04-16 15:56:21 +1000317 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100318 case KEY_DSA_CERT:
Damien Miller450a7a12000-03-26 13:04:51 +1000319 case KEY_DSA:
320 return a->dsa != NULL && b->dsa != NULL &&
321 BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
322 BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
323 BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
324 BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
Damien Miller6af914a2010-09-10 11:39:26 +1000325#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000326 case KEY_ECDSA_CERT:
327 case KEY_ECDSA:
328 if (a->ecdsa == NULL || b->ecdsa == NULL ||
329 EC_KEY_get0_public_key(a->ecdsa) == NULL ||
330 EC_KEY_get0_public_key(b->ecdsa) == NULL)
331 return 0;
332 if ((bnctx = BN_CTX_new()) == NULL)
333 fatal("%s: BN_CTX_new failed", __func__);
334 if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa),
335 EC_KEY_get0_group(b->ecdsa), bnctx) != 0 ||
336 EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa),
337 EC_KEY_get0_public_key(a->ecdsa),
338 EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) {
339 BN_CTX_free(bnctx);
340 return 0;
341 }
342 BN_CTX_free(bnctx);
343 return 1;
Damien Miller6af914a2010-09-10 11:39:26 +1000344#endif /* OPENSSL_HAS_ECC */
Damien Miller1f0311c2014-05-15 14:24:09 +1000345#endif /* WITH_OPENSSL */
Damien Miller5be9d9e2013-12-07 11:24:01 +1100346 case KEY_ED25519:
347 case KEY_ED25519_CERT:
348 return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&
349 memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;
Damien Miller450a7a12000-03-26 13:04:51 +1000350 default:
Damien Millereba71ba2000-04-29 23:57:08 +1000351 fatal("key_equal: bad key type %d", a->type);
Damien Miller450a7a12000-03-26 13:04:51 +1000352 }
Damien Miller87dd5f22008-07-11 17:35:09 +1000353 /* NOTREACHED */
Damien Miller450a7a12000-03-26 13:04:51 +1000354}
355
Damien Miller0a80ca12010-02-27 07:55:05 +1100356int
357key_equal(const Key *a, const Key *b)
358{
359 if (a == NULL || b == NULL || a->type != b->type)
360 return 0;
361 if (key_is_cert(a)) {
362 if (!cert_compare(a->cert, b->cert))
363 return 0;
364 }
365 return key_equal_public(a, b);
366}
367
Damien Miller37876e92003-05-15 10:19:46 +1000368u_char*
Damien Millerf3747bf2013-01-18 11:44:04 +1100369key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
370 u_int *dgst_raw_length)
Damien Miller450a7a12000-03-26 13:04:51 +1000371{
Ben Lindstrom46c16222000-12-22 01:43:59 +0000372 u_char *blob = NULL;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000373 u_char *retval = NULL;
Ben Lindstrom90fd8142002-02-26 18:09:42 +0000374 u_int len = 0;
Damien Miller1f0311c2014-05-15 14:24:09 +1000375 int hash_alg = -1;
376#ifdef WITH_OPENSSL
377 int nlen, elen;
378#endif
Damien Miller450a7a12000-03-26 13:04:51 +1000379
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000380 *dgst_raw_length = 0;
381
Damien Millerb3051d02014-01-10 10:58:53 +1100382 /* XXX switch to DIGEST_* directly? */
Ben Lindstromf0b48532001-03-12 02:59:31 +0000383 switch (dgst_type) {
384 case SSH_FP_MD5:
Damien Millerb3051d02014-01-10 10:58:53 +1100385 hash_alg = SSH_DIGEST_MD5;
Ben Lindstromf0b48532001-03-12 02:59:31 +0000386 break;
387 case SSH_FP_SHA1:
Damien Millerb3051d02014-01-10 10:58:53 +1100388 hash_alg = SSH_DIGEST_SHA1;
Ben Lindstromf0b48532001-03-12 02:59:31 +0000389 break;
Damien Miller3bde12a2012-06-20 21:51:11 +1000390 case SSH_FP_SHA256:
Damien Millerb3051d02014-01-10 10:58:53 +1100391 hash_alg = SSH_DIGEST_SHA256;
Damien Miller3bde12a2012-06-20 21:51:11 +1000392 break;
Ben Lindstromf0b48532001-03-12 02:59:31 +0000393 default:
Damien Millerb3051d02014-01-10 10:58:53 +1100394 fatal("%s: bad digest type %d", __func__, dgst_type);
Ben Lindstromf0b48532001-03-12 02:59:31 +0000395 }
Damien Miller450a7a12000-03-26 13:04:51 +1000396 switch (k->type) {
Damien Miller1f0311c2014-05-15 14:24:09 +1000397#ifdef WITH_OPENSSL
Damien Miller0bc1bd82000-11-13 22:57:25 +1100398 case KEY_RSA1:
Damien Miller450a7a12000-03-26 13:04:51 +1000399 nlen = BN_num_bytes(k->rsa->n);
400 elen = BN_num_bytes(k->rsa->e);
401 len = nlen + elen;
Damien Millereba71ba2000-04-29 23:57:08 +1000402 blob = xmalloc(len);
403 BN_bn2bin(k->rsa->n, blob);
404 BN_bn2bin(k->rsa->e, blob + nlen);
Damien Miller450a7a12000-03-26 13:04:51 +1000405 break;
406 case KEY_DSA:
Damien Millereb8b60e2010-08-31 22:41:14 +1000407 case KEY_ECDSA:
Damien Miller0bc1bd82000-11-13 22:57:25 +1100408 case KEY_RSA:
Damien Miller1f0311c2014-05-15 14:24:09 +1000409#endif
Damien Miller5be9d9e2013-12-07 11:24:01 +1100410 case KEY_ED25519:
Damien Miller0bc1bd82000-11-13 22:57:25 +1100411 key_to_blob(k, &blob, &len);
412 break;
Damien Miller1f0311c2014-05-15 14:24:09 +1000413#ifdef WITH_OPENSSL
Damien Miller4e270b02010-04-16 15:56:21 +1000414 case KEY_DSA_CERT_V00:
415 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100416 case KEY_DSA_CERT:
Damien Millereb8b60e2010-08-31 22:41:14 +1000417 case KEY_ECDSA_CERT:
Damien Miller0a80ca12010-02-27 07:55:05 +1100418 case KEY_RSA_CERT:
Damien Miller1f0311c2014-05-15 14:24:09 +1000419#endif
Damien Miller5be9d9e2013-12-07 11:24:01 +1100420 case KEY_ED25519_CERT:
Damien Miller0a80ca12010-02-27 07:55:05 +1100421 /* We want a fingerprint of the _key_ not of the cert */
Damien Millerf3747bf2013-01-18 11:44:04 +1100422 to_blob(k, &blob, &len, 1);
Damien Miller0a80ca12010-02-27 07:55:05 +1100423 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100424 case KEY_UNSPEC:
425 return retval;
Damien Miller450a7a12000-03-26 13:04:51 +1000426 default:
Damien Millerb3051d02014-01-10 10:58:53 +1100427 fatal("%s: bad key type %d", __func__, k->type);
Damien Miller450a7a12000-03-26 13:04:51 +1000428 break;
429 }
Damien Millereba71ba2000-04-29 23:57:08 +1000430 if (blob != NULL) {
Damien Millerb3051d02014-01-10 10:58:53 +1100431 retval = xmalloc(SSH_DIGEST_MAX_LENGTH);
432 if ((ssh_digest_memory(hash_alg, blob, len,
433 retval, SSH_DIGEST_MAX_LENGTH)) != 0)
434 fatal("%s: digest_memory failed", __func__);
Damien Millera5103f42014-02-04 11:20:14 +1100435 explicit_bzero(blob, len);
Darren Tuckera627d422013-06-02 07:31:17 +1000436 free(blob);
Damien Millerb3051d02014-01-10 10:58:53 +1100437 *dgst_raw_length = ssh_digest_bytes(hash_alg);
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000438 } else {
Damien Millerb3051d02014-01-10 10:58:53 +1100439 fatal("%s: blob is null", __func__);
Damien Miller450a7a12000-03-26 13:04:51 +1000440 }
441 return retval;
442}
443
Ben Lindstroma962c2f2002-07-04 00:14:17 +0000444static char *
445key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len)
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000446{
447 char *retval;
Damien Millereccb9de2005-06-17 12:59:34 +1000448 u_int i;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000449
Damien Miller07d86be2006-03-26 14:19:21 +1100450 retval = xcalloc(1, dgst_raw_len * 3 + 1);
Damien Miller9f0f5c62001-12-21 14:45:46 +1100451 for (i = 0; i < dgst_raw_len; i++) {
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000452 char hex[4];
453 snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
Darren Tucker29588612003-07-14 17:28:34 +1000454 strlcat(retval, hex, dgst_raw_len * 3 + 1);
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000455 }
Darren Tucker29588612003-07-14 17:28:34 +1000456
457 /* Remove the trailing ':' character */
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000458 retval[(dgst_raw_len * 3) - 1] = '\0';
459 return retval;
460}
461
Ben Lindstroma962c2f2002-07-04 00:14:17 +0000462static char *
463key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len)
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000464{
465 char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
466 char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
467 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000468 u_int i, j = 0, rounds, seed = 1;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000469 char *retval;
470
471 rounds = (dgst_raw_len / 2) + 1;
Damien Miller07d86be2006-03-26 14:19:21 +1100472 retval = xcalloc((rounds * 6), sizeof(char));
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000473 retval[j++] = 'x';
474 for (i = 0; i < rounds; i++) {
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000475 u_int idx0, idx1, idx2, idx3, idx4;
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000476 if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
477 idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000478 seed) % 6;
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000479 idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
480 idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000481 (seed / 6)) % 6;
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000482 retval[j++] = vowels[idx0];
483 retval[j++] = consonants[idx1];
484 retval[j++] = vowels[idx2];
485 if ((i + 1) < rounds) {
486 idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
487 idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
488 retval[j++] = consonants[idx3];
489 retval[j++] = '-';
490 retval[j++] = consonants[idx4];
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000491 seed = ((seed * 5) +
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000492 ((((u_int)(dgst_raw[2 * i])) * 7) +
493 ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000494 }
495 } else {
496 idx0 = seed % 6;
497 idx1 = 16;
498 idx2 = seed / 6;
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000499 retval[j++] = vowels[idx0];
500 retval[j++] = consonants[idx1];
501 retval[j++] = vowels[idx2];
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000502 }
503 }
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000504 retval[j++] = 'x';
505 retval[j++] = '\0';
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000506 return retval;
507}
508
Darren Tucker9c16ac92008-06-13 04:40:35 +1000509/*
510 * Draw an ASCII-Art representing the fingerprint so human brain can
511 * profit from its built-in pattern recognition ability.
512 * This technique is called "random art" and can be found in some
513 * scientific publications like this original paper:
514 *
515 * "Hash Visualization: a New Technique to improve Real-World Security",
516 * Perrig A. and Song D., 1999, International Workshop on Cryptographic
517 * Techniques and E-Commerce (CrypTEC '99)
518 * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
519 *
520 * The subject came up in a talk by Dan Kaminsky, too.
521 *
522 * If you see the picture is different, the key is different.
523 * If the picture looks the same, you still know nothing.
524 *
525 * The algorithm used here is a worm crawling over a discrete plane,
526 * leaving a trace (augmenting the field) everywhere it goes.
527 * Movement is taken from dgst_raw 2bit-wise. Bumping into walls
528 * makes the respective movement vector be ignored for this turn.
529 * Graphs are not unambiguous, because circles in graphs can be
530 * walked in either direction.
531 */
Darren Tucker987ac842008-06-13 04:54:40 +1000532
533/*
534 * Field sizes for the random art. Have to be odd, so the starting point
535 * can be in the exact middle of the picture, and FLDBASE should be >=8 .
536 * Else pictures would be too dense, and drawing the frame would
537 * fail, too, because the key type would not fit in anymore.
538 */
539#define FLDBASE 8
540#define FLDSIZE_Y (FLDBASE + 1)
541#define FLDSIZE_X (FLDBASE * 2 + 1)
Darren Tucker9c16ac92008-06-13 04:40:35 +1000542static char *
Darren Tucker987ac842008-06-13 04:54:40 +1000543key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k)
Darren Tucker9c16ac92008-06-13 04:40:35 +1000544{
545 /*
546 * Chars to be used after each other every time the worm
547 * intersects with itself. Matter of taste.
548 */
Darren Tucker4b3b9772008-06-13 04:55:10 +1000549 char *augmentation_string = " .o+=*BOX@%&#/^SE";
Darren Tucker9c16ac92008-06-13 04:40:35 +1000550 char *retval, *p;
Darren Tucker014d76f2008-06-13 04:43:51 +1000551 u_char field[FLDSIZE_X][FLDSIZE_Y];
Darren Tucker9c16ac92008-06-13 04:40:35 +1000552 u_int i, b;
553 int x, y;
Darren Tuckerd32b28a2008-06-13 04:45:50 +1000554 size_t len = strlen(augmentation_string) - 1;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000555
556 retval = xcalloc(1, (FLDSIZE_X + 3) * (FLDSIZE_Y + 2));
557
558 /* initialize field */
Darren Tucker014d76f2008-06-13 04:43:51 +1000559 memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
Darren Tucker9c16ac92008-06-13 04:40:35 +1000560 x = FLDSIZE_X / 2;
561 y = FLDSIZE_Y / 2;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000562
563 /* process raw key */
564 for (i = 0; i < dgst_raw_len; i++) {
565 int input;
566 /* each byte conveys four 2-bit move commands */
567 input = dgst_raw[i];
568 for (b = 0; b < 4; b++) {
569 /* evaluate 2 bit, rest is shifted later */
570 x += (input & 0x1) ? 1 : -1;
571 y += (input & 0x2) ? 1 : -1;
572
573 /* assure we are still in bounds */
574 x = MAX(x, 0);
575 y = MAX(y, 0);
576 x = MIN(x, FLDSIZE_X - 1);
577 y = MIN(y, FLDSIZE_Y - 1);
578
579 /* augment the field */
Damien Millerc6aadd92008-11-03 19:16:20 +1100580 if (field[x][y] < len - 2)
581 field[x][y]++;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000582 input = input >> 2;
583 }
584 }
Darren Tucker4b3b9772008-06-13 04:55:10 +1000585
586 /* mark starting point and end point*/
587 field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
588 field[x][y] = len;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000589
590 /* fill in retval */
Damien Miller007132a2008-06-29 22:45:37 +1000591 snprintf(retval, FLDSIZE_X, "+--[%4s %4u]", key_type(k), key_size(k));
Darren Tucker987ac842008-06-13 04:54:40 +1000592 p = strchr(retval, '\0');
Darren Tucker9c16ac92008-06-13 04:40:35 +1000593
594 /* output upper border */
Damien Miller007132a2008-06-29 22:45:37 +1000595 for (i = p - retval - 1; i < FLDSIZE_X; i++)
Darren Tucker9c16ac92008-06-13 04:40:35 +1000596 *p++ = '-';
597 *p++ = '+';
598 *p++ = '\n';
599
600 /* output content */
601 for (y = 0; y < FLDSIZE_Y; y++) {
602 *p++ = '|';
603 for (x = 0; x < FLDSIZE_X; x++)
Darren Tuckerd32b28a2008-06-13 04:45:50 +1000604 *p++ = augmentation_string[MIN(field[x][y], len)];
Darren Tucker9c16ac92008-06-13 04:40:35 +1000605 *p++ = '|';
606 *p++ = '\n';
607 }
608
609 /* output lower border */
610 *p++ = '+';
611 for (i = 0; i < FLDSIZE_X; i++)
612 *p++ = '-';
613 *p++ = '+';
614
615 return retval;
616}
617
Ben Lindstroma962c2f2002-07-04 00:14:17 +0000618char *
Darren Tucker0acca372013-06-02 07:41:51 +1000619key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000620{
Ben Lindstroma3700052001-04-05 23:26:32 +0000621 char *retval = NULL;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000622 u_char *dgst_raw;
Damien Miller3672e4b2002-02-05 11:54:07 +1100623 u_int dgst_raw_len;
Damien Miller9f0f5c62001-12-21 14:45:46 +1100624
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000625 dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len);
626 if (!dgst_raw)
Ben Lindstromcfccef92001-03-13 04:57:58 +0000627 fatal("key_fingerprint: null from key_fingerprint_raw()");
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +0000628 switch (dgst_rep) {
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000629 case SSH_FP_HEX:
630 retval = key_fingerprint_hex(dgst_raw, dgst_raw_len);
631 break;
632 case SSH_FP_BUBBLEBABBLE:
633 retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
634 break;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000635 case SSH_FP_RANDOMART:
Darren Tucker987ac842008-06-13 04:54:40 +1000636 retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k);
Darren Tucker9c16ac92008-06-13 04:40:35 +1000637 break;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000638 default:
Damien Miller2f54ada2008-11-03 19:24:16 +1100639 fatal("key_fingerprint: bad digest representation %d",
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000640 dgst_rep);
641 break;
642 }
Damien Millera5103f42014-02-04 11:20:14 +1100643 explicit_bzero(dgst_raw, dgst_raw_len);
Darren Tuckera627d422013-06-02 07:31:17 +1000644 free(dgst_raw);
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000645 return retval;
646}
647
Damien Miller1f0311c2014-05-15 14:24:09 +1000648#ifdef WITH_SSH1
Damien Miller450a7a12000-03-26 13:04:51 +1000649/*
650 * Reads a multiple-precision integer in decimal from the buffer, and advances
651 * the pointer. The integer must already be initialized. This function is
652 * permitted to modify the buffer. This leaves *cpp to point just beyond the
653 * last processed (and maybe modified) character. Note that this may modify
654 * the buffer containing the number.
655 */
Ben Lindstrombba81212001-06-25 05:01:22 +0000656static int
Damien Miller450a7a12000-03-26 13:04:51 +1000657read_bignum(char **cpp, BIGNUM * value)
658{
659 char *cp = *cpp;
660 int old;
661
662 /* Skip any leading whitespace. */
663 for (; *cp == ' ' || *cp == '\t'; cp++)
664 ;
665
666 /* Check that it begins with a decimal digit. */
667 if (*cp < '0' || *cp > '9')
668 return 0;
669
670 /* Save starting position. */
671 *cpp = cp;
672
673 /* Move forward until all decimal digits skipped. */
674 for (; *cp >= '0' && *cp <= '9'; cp++)
675 ;
676
677 /* Save the old terminating character, and replace it by \0. */
678 old = *cp;
679 *cp = 0;
680
681 /* Parse the number. */
682 if (BN_dec2bn(&value, *cpp) == 0)
683 return 0;
684
685 /* Restore old terminating character. */
686 *cp = old;
687
688 /* Move beyond the number and return success. */
689 *cpp = cp;
690 return 1;
691}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000692
Ben Lindstrombba81212001-06-25 05:01:22 +0000693static int
Damien Miller450a7a12000-03-26 13:04:51 +1000694write_bignum(FILE *f, BIGNUM *num)
695{
696 char *buf = BN_bn2dec(num);
697 if (buf == NULL) {
698 error("write_bignum: BN_bn2dec() failed");
699 return 0;
700 }
701 fprintf(f, " %s", buf);
Damien Milleraf3030f2001-10-10 15:00:49 +1000702 OPENSSL_free(buf);
Damien Miller450a7a12000-03-26 13:04:51 +1000703 return 1;
704}
Damien Miller1f0311c2014-05-15 14:24:09 +1000705#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +1100706
Ben Lindstrom309f3d12001-09-20 00:55:53 +0000707/* returns 1 ok, -1 error */
Damien Miller0bc1bd82000-11-13 22:57:25 +1100708int
Damien Millereba71ba2000-04-29 23:57:08 +1000709key_read(Key *ret, char **cpp)
Damien Miller450a7a12000-03-26 13:04:51 +1000710{
Damien Millereba71ba2000-04-29 23:57:08 +1000711 Key *k;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100712 int success = -1;
713 char *cp, *space;
Darren Tucker8ccb7392010-09-10 12:28:24 +1000714 int len, n, type;
Ben Lindstrom46c16222000-12-22 01:43:59 +0000715 u_char *blob;
Damien Miller1f0311c2014-05-15 14:24:09 +1000716#ifdef WITH_SSH1
717 u_int bits;
718#endif
Darren Tucker8ccb7392010-09-10 12:28:24 +1000719#ifdef OPENSSL_HAS_ECC
720 int curve_nid = -1;
721#endif
Damien Millereba71ba2000-04-29 23:57:08 +1000722
723 cp = *cpp;
724
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +0000725 switch (ret->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100726 case KEY_RSA1:
Damien Miller1f0311c2014-05-15 14:24:09 +1000727#ifdef WITH_SSH1
Damien Millereba71ba2000-04-29 23:57:08 +1000728 /* Get number of bits. */
729 if (*cp < '0' || *cp > '9')
Damien Miller0bc1bd82000-11-13 22:57:25 +1100730 return -1; /* Bad bit count... */
Damien Millereba71ba2000-04-29 23:57:08 +1000731 for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
732 bits = 10 * bits + *cp - '0';
Damien Miller450a7a12000-03-26 13:04:51 +1000733 if (bits == 0)
Damien Miller0bc1bd82000-11-13 22:57:25 +1100734 return -1;
Damien Millereba71ba2000-04-29 23:57:08 +1000735 *cpp = cp;
Damien Miller450a7a12000-03-26 13:04:51 +1000736 /* Get public exponent, public modulus. */
737 if (!read_bignum(cpp, ret->rsa->e))
Damien Miller0bc1bd82000-11-13 22:57:25 +1100738 return -1;
Damien Miller450a7a12000-03-26 13:04:51 +1000739 if (!read_bignum(cpp, ret->rsa->n))
Damien Miller0bc1bd82000-11-13 22:57:25 +1100740 return -1;
Darren Tucker561724f2010-01-13 22:43:05 +1100741 /* validate the claimed number of bits */
742 if ((u_int)BN_num_bits(ret->rsa->n) != bits) {
743 verbose("key_read: claimed key size %d does not match "
744 "actual %d", bits, BN_num_bits(ret->rsa->n));
745 return -1;
746 }
Damien Miller0bc1bd82000-11-13 22:57:25 +1100747 success = 1;
Damien Miller1f0311c2014-05-15 14:24:09 +1000748#endif
Damien Miller450a7a12000-03-26 13:04:51 +1000749 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100750 case KEY_UNSPEC:
751 case KEY_RSA:
Damien Miller450a7a12000-03-26 13:04:51 +1000752 case KEY_DSA:
Damien Millereb8b60e2010-08-31 22:41:14 +1000753 case KEY_ECDSA:
Damien Miller5be9d9e2013-12-07 11:24:01 +1100754 case KEY_ED25519:
Damien Miller4e270b02010-04-16 15:56:21 +1000755 case KEY_DSA_CERT_V00:
756 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100757 case KEY_DSA_CERT:
Damien Millereb8b60e2010-08-31 22:41:14 +1000758 case KEY_ECDSA_CERT:
Damien Miller0a80ca12010-02-27 07:55:05 +1100759 case KEY_RSA_CERT:
Damien Miller5be9d9e2013-12-07 11:24:01 +1100760 case KEY_ED25519_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +1100761 space = strchr(cp, ' ');
762 if (space == NULL) {
Damien Miller386f1f32003-02-24 11:54:57 +1100763 debug3("key_read: missing whitespace");
Damien Miller0bc1bd82000-11-13 22:57:25 +1100764 return -1;
765 }
766 *space = '\0';
767 type = key_type_from_name(cp);
Damien Miller6af914a2010-09-10 11:39:26 +1000768#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000769 if (key_type_plain(type) == KEY_ECDSA &&
770 (curve_nid = key_ecdsa_nid_from_name(cp)) == -1) {
771 debug("key_read: invalid curve");
772 return -1;
773 }
Damien Miller6af914a2010-09-10 11:39:26 +1000774#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +1100775 *space = ' ';
776 if (type == KEY_UNSPEC) {
Damien Miller386f1f32003-02-24 11:54:57 +1100777 debug3("key_read: missing keytype");
Damien Miller0bc1bd82000-11-13 22:57:25 +1100778 return -1;
779 }
780 cp = space+1;
781 if (*cp == '\0') {
782 debug3("key_read: short string");
783 return -1;
784 }
785 if (ret->type == KEY_UNSPEC) {
786 ret->type = type;
787 } else if (ret->type != type) {
788 /* is a key, but different type */
789 debug3("key_read: type mismatch");
Ben Lindstrom309f3d12001-09-20 00:55:53 +0000790 return -1;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100791 }
Damien Millereba71ba2000-04-29 23:57:08 +1000792 len = 2*strlen(cp);
793 blob = xmalloc(len);
794 n = uudecode(cp, blob, len);
Damien Millere247cc42000-05-07 12:03:14 +1000795 if (n < 0) {
Damien Millerb1715dc2000-05-30 13:44:51 +1000796 error("key_read: uudecode %s failed", cp);
Darren Tuckera627d422013-06-02 07:31:17 +1000797 free(blob);
Damien Miller0bc1bd82000-11-13 22:57:25 +1100798 return -1;
Damien Millere247cc42000-05-07 12:03:14 +1000799 }
Darren Tucker502d3842003-06-28 12:38:01 +1000800 k = key_from_blob(blob, (u_int)n);
Darren Tuckera627d422013-06-02 07:31:17 +1000801 free(blob);
Damien Millerb1715dc2000-05-30 13:44:51 +1000802 if (k == NULL) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100803 error("key_read: key_from_blob %s failed", cp);
804 return -1;
Damien Millerb1715dc2000-05-30 13:44:51 +1000805 }
Damien Miller0bc1bd82000-11-13 22:57:25 +1100806 if (k->type != type) {
807 error("key_read: type mismatch: encoding error");
808 key_free(k);
809 return -1;
810 }
Damien Miller6af914a2010-09-10 11:39:26 +1000811#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000812 if (key_type_plain(type) == KEY_ECDSA &&
813 curve_nid != k->ecdsa_nid) {
814 error("key_read: type mismatch: EC curve mismatch");
815 key_free(k);
816 return -1;
817 }
Damien Miller6af914a2010-09-10 11:39:26 +1000818#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +1100819/*XXXX*/
Damien Miller0a80ca12010-02-27 07:55:05 +1100820 if (key_is_cert(ret)) {
821 if (!key_is_cert(k)) {
822 error("key_read: loaded key is not a cert");
823 key_free(k);
824 return -1;
825 }
826 if (ret->cert != NULL)
827 cert_free(ret->cert);
828 ret->cert = k->cert;
829 k->cert = NULL;
830 }
Damien Miller1f0311c2014-05-15 14:24:09 +1000831#ifdef WITH_OPENSSL
Damien Miller0a80ca12010-02-27 07:55:05 +1100832 if (key_type_plain(ret->type) == KEY_RSA) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100833 if (ret->rsa != NULL)
834 RSA_free(ret->rsa);
835 ret->rsa = k->rsa;
836 k->rsa = NULL;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100837#ifdef DEBUG_PK
838 RSA_print_fp(stderr, ret->rsa, 8);
839#endif
Damien Miller0a80ca12010-02-27 07:55:05 +1100840 }
841 if (key_type_plain(ret->type) == KEY_DSA) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100842 if (ret->dsa != NULL)
843 DSA_free(ret->dsa);
844 ret->dsa = k->dsa;
845 k->dsa = NULL;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100846#ifdef DEBUG_PK
847 DSA_print_fp(stderr, ret->dsa, 8);
848#endif
849 }
Damien Miller6af914a2010-09-10 11:39:26 +1000850#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000851 if (key_type_plain(ret->type) == KEY_ECDSA) {
852 if (ret->ecdsa != NULL)
853 EC_KEY_free(ret->ecdsa);
854 ret->ecdsa = k->ecdsa;
855 ret->ecdsa_nid = k->ecdsa_nid;
856 k->ecdsa = NULL;
857 k->ecdsa_nid = -1;
858#ifdef DEBUG_PK
859 key_dump_ec_key(ret->ecdsa);
860#endif
861 }
Damien Miller6af914a2010-09-10 11:39:26 +1000862#endif
Damien Miller1f0311c2014-05-15 14:24:09 +1000863#endif
Damien Miller5be9d9e2013-12-07 11:24:01 +1100864 if (key_type_plain(ret->type) == KEY_ED25519) {
865 free(ret->ed25519_pk);
866 ret->ed25519_pk = k->ed25519_pk;
867 k->ed25519_pk = NULL;
868#ifdef DEBUG_PK
869 /* XXX */
870#endif
871 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100872 success = 1;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100873/*XXXX*/
Ben Lindstrom4cbc1812001-12-06 16:41:41 +0000874 key_free(k);
Damien Miller0bc1bd82000-11-13 22:57:25 +1100875 if (success != 1)
876 break;
Damien Millerb1715dc2000-05-30 13:44:51 +1000877 /* advance cp: skip whitespace and data */
878 while (*cp == ' ' || *cp == '\t')
879 cp++;
880 while (*cp != '\0' && *cp != ' ' && *cp != '\t')
881 cp++;
882 *cpp = cp;
Damien Miller450a7a12000-03-26 13:04:51 +1000883 break;
884 default:
Damien Millereba71ba2000-04-29 23:57:08 +1000885 fatal("key_read: bad key type: %d", ret->type);
Damien Miller450a7a12000-03-26 13:04:51 +1000886 break;
887 }
Damien Miller0bc1bd82000-11-13 22:57:25 +1100888 return success;
Damien Miller450a7a12000-03-26 13:04:51 +1000889}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000890
Damien Miller450a7a12000-03-26 13:04:51 +1000891int
Damien Millerf58b58c2003-11-17 21:18:23 +1100892key_write(const Key *key, FILE *f)
Damien Miller450a7a12000-03-26 13:04:51 +1000893{
Ben Lindstrom90fd8142002-02-26 18:09:42 +0000894 int n, success = 0;
Damien Miller1f0311c2014-05-15 14:24:09 +1000895#ifdef WITH_SSH1
896 u_int bits = 0;
897#endif
898 u_int len;
Damien Millera10f5612002-09-12 09:49:15 +1000899 u_char *blob;
900 char *uu;
Damien Miller450a7a12000-03-26 13:04:51 +1000901
Damien Miller0a80ca12010-02-27 07:55:05 +1100902 if (key_is_cert(key)) {
903 if (key->cert == NULL) {
904 error("%s: no cert data", __func__);
905 return 0;
906 }
907 if (buffer_len(&key->cert->certblob) == 0) {
908 error("%s: no signed certificate blob", __func__);
909 return 0;
910 }
911 }
912
913 switch (key->type) {
Damien Miller1f0311c2014-05-15 14:24:09 +1000914#ifdef WITH_SSH1
Damien Miller0a80ca12010-02-27 07:55:05 +1100915 case KEY_RSA1:
916 if (key->rsa == NULL)
917 return 0;
Damien Miller450a7a12000-03-26 13:04:51 +1000918 /* size of modulus 'n' */
919 bits = BN_num_bits(key->rsa->n);
920 fprintf(f, "%u", bits);
921 if (write_bignum(f, key->rsa->e) &&
Damien Miller0a80ca12010-02-27 07:55:05 +1100922 write_bignum(f, key->rsa->n))
923 return 1;
924 error("key_write: failed for RSA key");
925 return 0;
Damien Miller1f0311c2014-05-15 14:24:09 +1000926#endif
927#ifdef WITH_OPENSSL
Damien Miller0a80ca12010-02-27 07:55:05 +1100928 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000929 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100930 case KEY_DSA_CERT:
931 if (key->dsa == NULL)
932 return 0;
933 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000934#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000935 case KEY_ECDSA:
936 case KEY_ECDSA_CERT:
937 if (key->ecdsa == NULL)
938 return 0;
939 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000940#endif
Damien Miller0a80ca12010-02-27 07:55:05 +1100941 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000942 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100943 case KEY_RSA_CERT:
944 if (key->rsa == NULL)
945 return 0;
946 break;
Damien Miller1f0311c2014-05-15 14:24:09 +1000947#endif
948 case KEY_ED25519:
949 case KEY_ED25519_CERT:
950 if (key->ed25519_pk == NULL)
951 return 0;
952 break;
Damien Miller0a80ca12010-02-27 07:55:05 +1100953 default:
954 return 0;
Damien Miller450a7a12000-03-26 13:04:51 +1000955 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100956
957 key_to_blob(key, &blob, &len);
958 uu = xmalloc(2*len);
959 n = uuencode(blob, len, uu, 2*len);
960 if (n > 0) {
961 fprintf(f, "%s %s", key_ssh_name(key), uu);
962 success = 1;
963 }
Darren Tuckera627d422013-06-02 07:31:17 +1000964 free(blob);
965 free(uu);
Damien Miller0a80ca12010-02-27 07:55:05 +1100966
Damien Miller450a7a12000-03-26 13:04:51 +1000967 return success;
968}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000969
Damien Millerf58b58c2003-11-17 21:18:23 +1100970const char *
Damien Miller1cfbfaf2010-03-22 05:58:24 +1100971key_cert_type(const Key *k)
972{
973 switch (k->cert->type) {
974 case SSH2_CERT_TYPE_USER:
975 return "user";
976 case SSH2_CERT_TYPE_HOST:
977 return "host";
978 default:
979 return "unknown";
980 }
981}
982
Damien Millerea111192013-04-23 19:24:32 +1000983struct keytype {
984 char *name;
985 char *shortname;
986 int type;
987 int nid;
988 int cert;
989};
990static const struct keytype keytypes[] = {
Damien Miller1f0311c2014-05-15 14:24:09 +1000991#ifdef WITH_OPENSSL
992#ifdef WITH_SSH1
Damien Millerea111192013-04-23 19:24:32 +1000993 { NULL, "RSA1", KEY_RSA1, 0, 0 },
Damien Miller1f0311c2014-05-15 14:24:09 +1000994#endif
Damien Millerea111192013-04-23 19:24:32 +1000995 { "ssh-rsa", "RSA", KEY_RSA, 0, 0 },
996 { "ssh-dss", "DSA", KEY_DSA, 0, 0 },
997#ifdef OPENSSL_HAS_ECC
998 { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 },
999 { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 },
Darren Tucker37bcef52013-11-09 18:39:25 +11001000# ifdef OPENSSL_HAS_NISTP521
Damien Millerea111192013-04-23 19:24:32 +10001001 { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 },
Darren Tucker37bcef52013-11-09 18:39:25 +11001002# endif
Damien Millerea111192013-04-23 19:24:32 +10001003#endif /* OPENSSL_HAS_ECC */
1004 { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1 },
1005 { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1 },
1006#ifdef OPENSSL_HAS_ECC
1007 { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT",
1008 KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1 },
1009 { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT",
1010 KEY_ECDSA_CERT, NID_secp384r1, 1 },
Darren Tucker37bcef52013-11-09 18:39:25 +11001011# ifdef OPENSSL_HAS_NISTP521
Damien Millerea111192013-04-23 19:24:32 +10001012 { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT",
1013 KEY_ECDSA_CERT, NID_secp521r1, 1 },
Darren Tucker37bcef52013-11-09 18:39:25 +11001014# endif
Damien Millerea111192013-04-23 19:24:32 +10001015#endif /* OPENSSL_HAS_ECC */
1016 { "ssh-rsa-cert-v00@openssh.com", "RSA-CERT-V00",
1017 KEY_RSA_CERT_V00, 0, 1 },
1018 { "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00",
1019 KEY_DSA_CERT_V00, 0, 1 },
Damien Miller1f0311c2014-05-15 14:24:09 +10001020#endif
1021 { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0 },
Damien Miller5be9d9e2013-12-07 11:24:01 +11001022 { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",
1023 KEY_ED25519_CERT, 0, 1 },
Damien Millerea111192013-04-23 19:24:32 +10001024 { NULL, NULL, -1, -1, 0 }
1025};
1026
1027const char *
1028key_type(const Key *k)
1029{
1030 const struct keytype *kt;
1031
1032 for (kt = keytypes; kt->type != -1; kt++) {
1033 if (kt->type == k->type)
1034 return kt->shortname;
1035 }
1036 return "unknown";
1037}
1038
Damien Millereb8b60e2010-08-31 22:41:14 +10001039static const char *
1040key_ssh_name_from_type_nid(int type, int nid)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001041{
Damien Millerea111192013-04-23 19:24:32 +10001042 const struct keytype *kt;
1043
1044 for (kt = keytypes; kt->type != -1; kt++) {
1045 if (kt->type == type && (kt->nid == 0 || kt->nid == nid))
1046 return kt->name;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001047 }
1048 return "ssh-unknown";
1049}
Ben Lindstrom836f0e92002-06-23 21:21:30 +00001050
Damien Millereb8b60e2010-08-31 22:41:14 +10001051const char *
1052key_ssh_name(const Key *k)
1053{
1054 return key_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
1055}
1056
1057const char *
1058key_ssh_name_plain(const Key *k)
1059{
1060 return key_ssh_name_from_type_nid(key_type_plain(k->type),
1061 k->ecdsa_nid);
1062}
1063
Damien Millerea111192013-04-23 19:24:32 +10001064int
1065key_type_from_name(char *name)
1066{
1067 const struct keytype *kt;
1068
1069 for (kt = keytypes; kt->type != -1; kt++) {
1070 /* Only allow shortname matches for plain key types */
1071 if ((kt->name != NULL && strcmp(name, kt->name) == 0) ||
1072 (!kt->cert && strcasecmp(kt->shortname, name) == 0))
1073 return kt->type;
1074 }
1075 debug2("key_type_from_name: unknown key type '%s'", name);
1076 return KEY_UNSPEC;
1077}
1078
1079int
1080key_ecdsa_nid_from_name(const char *name)
1081{
1082 const struct keytype *kt;
1083
1084 for (kt = keytypes; kt->type != -1; kt++) {
1085 if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT)
1086 continue;
1087 if (kt->name != NULL && strcmp(name, kt->name) == 0)
1088 return kt->nid;
1089 }
1090 debug2("%s: unknown/non-ECDSA key type '%s'", __func__, name);
1091 return -1;
1092}
1093
1094char *
Damien Miller5be9d9e2013-12-07 11:24:01 +11001095key_alg_list(int certs_only, int plain_only)
Damien Millerea111192013-04-23 19:24:32 +10001096{
1097 char *ret = NULL;
1098 size_t nlen, rlen = 0;
1099 const struct keytype *kt;
1100
1101 for (kt = keytypes; kt->type != -1; kt++) {
1102 if (kt->name == NULL)
1103 continue;
Damien Miller5be9d9e2013-12-07 11:24:01 +11001104 if ((certs_only && !kt->cert) || (plain_only && kt->cert))
1105 continue;
Damien Millerea111192013-04-23 19:24:32 +10001106 if (ret != NULL)
1107 ret[rlen++] = '\n';
1108 nlen = strlen(kt->name);
1109 ret = xrealloc(ret, 1, rlen + nlen + 2);
1110 memcpy(ret + rlen, kt->name, nlen + 1);
1111 rlen += nlen;
1112 }
1113 return ret;
1114}
1115
Damien Miller4a3a9d42013-10-30 22:19:47 +11001116int
1117key_type_is_cert(int type)
1118{
1119 const struct keytype *kt;
1120
1121 for (kt = keytypes; kt->type != -1; kt++) {
1122 if (kt->type == type)
1123 return kt->cert;
1124 }
1125 return 0;
1126}
1127
Damien Miller29ace1c2013-12-29 17:49:31 +11001128static int
1129key_type_is_valid_ca(int type)
1130{
1131 switch (type) {
1132 case KEY_RSA:
1133 case KEY_DSA:
1134 case KEY_ECDSA:
1135 case KEY_ED25519:
1136 return 1;
1137 default:
1138 return 0;
1139 }
1140}
1141
Damien Miller0bc1bd82000-11-13 22:57:25 +11001142u_int
Damien Millerf58b58c2003-11-17 21:18:23 +11001143key_size(const Key *k)
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001144{
Damien Millerad833b32000-08-23 10:46:23 +10001145 switch (k->type) {
Damien Miller1f0311c2014-05-15 14:24:09 +10001146#ifdef WITH_OPENSSL
Damien Miller0bc1bd82000-11-13 22:57:25 +11001147 case KEY_RSA1:
Damien Millerad833b32000-08-23 10:46:23 +10001148 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +10001149 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001150 case KEY_RSA_CERT:
Damien Millerad833b32000-08-23 10:46:23 +10001151 return BN_num_bits(k->rsa->n);
Damien Millerad833b32000-08-23 10:46:23 +10001152 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +10001153 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001154 case KEY_DSA_CERT:
Damien Millerad833b32000-08-23 10:46:23 +10001155 return BN_num_bits(k->dsa->p);
Damien Miller6af914a2010-09-10 11:39:26 +10001156#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001157 case KEY_ECDSA:
1158 case KEY_ECDSA_CERT:
Damien Miller041ab7c2010-09-10 11:23:34 +10001159 return key_curve_nid_to_bits(k->ecdsa_nid);
Damien Miller6af914a2010-09-10 11:39:26 +10001160#endif
Damien Miller1f0311c2014-05-15 14:24:09 +10001161#endif
1162 case KEY_ED25519:
1163 return 256; /* XXX */
Damien Millerad833b32000-08-23 10:46:23 +10001164 }
1165 return 0;
1166}
Damien Miller0bc1bd82000-11-13 22:57:25 +11001167
Damien Miller1f0311c2014-05-15 14:24:09 +10001168#ifdef WITH_OPENSSL
Ben Lindstrombba81212001-06-25 05:01:22 +00001169static RSA *
Ben Lindstrom46c16222000-12-22 01:43:59 +00001170rsa_generate_private_key(u_int bits)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001171{
Damien Miller4499f4c2010-11-20 15:15:49 +11001172 RSA *private = RSA_new();
1173 BIGNUM *f4 = BN_new();
Damien Miller69b72032006-03-26 14:02:35 +11001174
Kevin Stevesef4eea92001-02-05 12:42:17 +00001175 if (private == NULL)
Damien Miller4499f4c2010-11-20 15:15:49 +11001176 fatal("%s: RSA_new failed", __func__);
1177 if (f4 == NULL)
1178 fatal("%s: BN_new failed", __func__);
1179 if (!BN_set_word(f4, RSA_F4))
1180 fatal("%s: BN_new failed", __func__);
1181 if (!RSA_generate_key_ex(private, bits, f4, NULL))
1182 fatal("%s: key generation failed.", __func__);
1183 BN_free(f4);
Kevin Stevesef4eea92001-02-05 12:42:17 +00001184 return private;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001185}
1186
Ben Lindstrombba81212001-06-25 05:01:22 +00001187static DSA*
Ben Lindstrom46c16222000-12-22 01:43:59 +00001188dsa_generate_private_key(u_int bits)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001189{
Damien Miller4499f4c2010-11-20 15:15:49 +11001190 DSA *private = DSA_new();
Damien Miller69b72032006-03-26 14:02:35 +11001191
Damien Miller0bc1bd82000-11-13 22:57:25 +11001192 if (private == NULL)
Damien Miller4499f4c2010-11-20 15:15:49 +11001193 fatal("%s: DSA_new failed", __func__);
1194 if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL,
1195 NULL, NULL))
1196 fatal("%s: DSA_generate_parameters failed", __func__);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001197 if (!DSA_generate_key(private))
Damien Miller4499f4c2010-11-20 15:15:49 +11001198 fatal("%s: DSA_generate_key failed.", __func__);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001199 return private;
1200}
1201
Damien Millereb8b60e2010-08-31 22:41:14 +10001202int
1203key_ecdsa_bits_to_nid(int bits)
1204{
1205 switch (bits) {
Damien Miller6af914a2010-09-10 11:39:26 +10001206#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001207 case 256:
1208 return NID_X9_62_prime256v1;
1209 case 384:
1210 return NID_secp384r1;
Darren Tucker2c894302013-11-10 12:38:42 +11001211# ifdef OPENSSL_HAS_NISTP521
Damien Millereb8b60e2010-08-31 22:41:14 +10001212 case 521:
1213 return NID_secp521r1;
Darren Tucker37bcef52013-11-09 18:39:25 +11001214# endif
Damien Miller6af914a2010-09-10 11:39:26 +10001215#endif
Damien Millereb8b60e2010-08-31 22:41:14 +10001216 default:
1217 return -1;
1218 }
1219}
1220
Damien Miller6af914a2010-09-10 11:39:26 +10001221#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001222int
Damien Millerb472a902010-11-05 10:19:49 +11001223key_ecdsa_key_to_nid(EC_KEY *k)
Damien Millereb8b60e2010-08-31 22:41:14 +10001224{
1225 EC_GROUP *eg;
1226 int nids[] = {
1227 NID_X9_62_prime256v1,
1228 NID_secp384r1,
Darren Tucker37bcef52013-11-09 18:39:25 +11001229# ifdef OPENSSL_HAS_NISTP521
Damien Millereb8b60e2010-08-31 22:41:14 +10001230 NID_secp521r1,
Darren Tucker37bcef52013-11-09 18:39:25 +11001231# endif
Damien Millereb8b60e2010-08-31 22:41:14 +10001232 -1
1233 };
Damien Millerb472a902010-11-05 10:19:49 +11001234 int nid;
Damien Millereb8b60e2010-08-31 22:41:14 +10001235 u_int i;
1236 BN_CTX *bnctx;
Damien Millerb472a902010-11-05 10:19:49 +11001237 const EC_GROUP *g = EC_KEY_get0_group(k);
Damien Millereb8b60e2010-08-31 22:41:14 +10001238
Damien Millerb472a902010-11-05 10:19:49 +11001239 /*
1240 * The group may be stored in a ASN.1 encoded private key in one of two
1241 * ways: as a "named group", which is reconstituted by ASN.1 object ID
1242 * or explicit group parameters encoded into the key blob. Only the
1243 * "named group" case sets the group NID for us, but we can figure
1244 * it out for the other case by comparing against all the groups that
1245 * are supported.
1246 */
1247 if ((nid = EC_GROUP_get_curve_name(g)) > 0)
1248 return nid;
Damien Millereb8b60e2010-08-31 22:41:14 +10001249 if ((bnctx = BN_CTX_new()) == NULL)
1250 fatal("%s: BN_CTX_new() failed", __func__);
1251 for (i = 0; nids[i] != -1; i++) {
1252 if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL)
1253 fatal("%s: EC_GROUP_new_by_curve_name failed",
1254 __func__);
Damien Millerb472a902010-11-05 10:19:49 +11001255 if (EC_GROUP_cmp(g, eg, bnctx) == 0)
Damien Millereb8b60e2010-08-31 22:41:14 +10001256 break;
Damien Millereb8b60e2010-08-31 22:41:14 +10001257 EC_GROUP_free(eg);
1258 }
1259 BN_CTX_free(bnctx);
1260 debug3("%s: nid = %d", __func__, nids[i]);
Damien Millerb472a902010-11-05 10:19:49 +11001261 if (nids[i] != -1) {
1262 /* Use the group with the NID attached */
1263 EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
1264 if (EC_KEY_set_group(k, eg) != 1)
1265 fatal("%s: EC_KEY_set_group", __func__);
1266 }
Damien Millereb8b60e2010-08-31 22:41:14 +10001267 return nids[i];
1268}
1269
1270static EC_KEY*
1271ecdsa_generate_private_key(u_int bits, int *nid)
1272{
1273 EC_KEY *private;
1274
1275 if ((*nid = key_ecdsa_bits_to_nid(bits)) == -1)
1276 fatal("%s: invalid key length", __func__);
1277 if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL)
1278 fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
1279 if (EC_KEY_generate_key(private) != 1)
1280 fatal("%s: EC_KEY_generate_key failed", __func__);
Damien Millerb472a902010-11-05 10:19:49 +11001281 EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE);
Damien Millereb8b60e2010-08-31 22:41:14 +10001282 return private;
1283}
Damien Miller6af914a2010-09-10 11:39:26 +10001284#endif /* OPENSSL_HAS_ECC */
Damien Miller1f0311c2014-05-15 14:24:09 +10001285#endif /* WITH_OPENSSL */
Damien Millereb8b60e2010-08-31 22:41:14 +10001286
Damien Miller0bc1bd82000-11-13 22:57:25 +11001287Key *
Ben Lindstrom46c16222000-12-22 01:43:59 +00001288key_generate(int type, u_int bits)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001289{
1290 Key *k = key_new(KEY_UNSPEC);
1291 switch (type) {
Damien Miller1f0311c2014-05-15 14:24:09 +10001292#ifdef WITH_OPENSSL
Kevin Stevesef4eea92001-02-05 12:42:17 +00001293 case KEY_DSA:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001294 k->dsa = dsa_generate_private_key(bits);
1295 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001296#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001297 case KEY_ECDSA:
1298 k->ecdsa = ecdsa_generate_private_key(bits, &k->ecdsa_nid);
1299 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001300#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +11001301 case KEY_RSA:
1302 case KEY_RSA1:
1303 k->rsa = rsa_generate_private_key(bits);
1304 break;
Damien Miller1f0311c2014-05-15 14:24:09 +10001305#endif
Damien Miller4e270b02010-04-16 15:56:21 +10001306 case KEY_RSA_CERT_V00:
1307 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001308 case KEY_RSA_CERT:
1309 case KEY_DSA_CERT:
1310 fatal("key_generate: cert keys cannot be generated directly");
Damien Miller1f0311c2014-05-15 14:24:09 +10001311#endif
1312 case KEY_ED25519:
1313 k->ed25519_pk = xmalloc(ED25519_PK_SZ);
1314 k->ed25519_sk = xmalloc(ED25519_SK_SZ);
1315 crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk);
1316 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001317 default:
Kevin Stevesef4eea92001-02-05 12:42:17 +00001318 fatal("key_generate: unknown type %d", type);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001319 }
Kevin Stevesef4eea92001-02-05 12:42:17 +00001320 k->type = type;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001321 return k;
1322}
1323
Damien Miller0a80ca12010-02-27 07:55:05 +11001324void
1325key_cert_copy(const Key *from_key, struct Key *to_key)
1326{
1327 u_int i;
1328 const struct KeyCert *from;
1329 struct KeyCert *to;
1330
1331 if (to_key->cert != NULL) {
1332 cert_free(to_key->cert);
1333 to_key->cert = NULL;
1334 }
1335
1336 if ((from = from_key->cert) == NULL)
1337 return;
1338
1339 to = to_key->cert = cert_new();
1340
1341 buffer_append(&to->certblob, buffer_ptr(&from->certblob),
1342 buffer_len(&from->certblob));
1343
Damien Miller4e270b02010-04-16 15:56:21 +10001344 buffer_append(&to->critical,
1345 buffer_ptr(&from->critical), buffer_len(&from->critical));
1346 buffer_append(&to->extensions,
1347 buffer_ptr(&from->extensions), buffer_len(&from->extensions));
Damien Miller0a80ca12010-02-27 07:55:05 +11001348
Damien Miller4e270b02010-04-16 15:56:21 +10001349 to->serial = from->serial;
Damien Miller0a80ca12010-02-27 07:55:05 +11001350 to->type = from->type;
1351 to->key_id = from->key_id == NULL ? NULL : xstrdup(from->key_id);
1352 to->valid_after = from->valid_after;
1353 to->valid_before = from->valid_before;
1354 to->signature_key = from->signature_key == NULL ?
1355 NULL : key_from_private(from->signature_key);
1356
1357 to->nprincipals = from->nprincipals;
1358 if (to->nprincipals > CERT_MAX_PRINCIPALS)
1359 fatal("%s: nprincipals (%u) > CERT_MAX_PRINCIPALS (%u)",
1360 __func__, to->nprincipals, CERT_MAX_PRINCIPALS);
1361 if (to->nprincipals > 0) {
1362 to->principals = xcalloc(from->nprincipals,
1363 sizeof(*to->principals));
1364 for (i = 0; i < to->nprincipals; i++)
1365 to->principals[i] = xstrdup(from->principals[i]);
1366 }
1367}
1368
Damien Miller0bc1bd82000-11-13 22:57:25 +11001369Key *
Damien Millerf58b58c2003-11-17 21:18:23 +11001370key_from_private(const Key *k)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001371{
1372 Key *n = NULL;
1373 switch (k->type) {
Damien Miller1f0311c2014-05-15 14:24:09 +10001374#ifdef WITH_OPENSSL
Kevin Stevesef4eea92001-02-05 12:42:17 +00001375 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +10001376 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001377 case KEY_DSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001378 n = key_new(k->type);
Darren Tucker0bc85572006-11-07 23:14:41 +11001379 if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
1380 (BN_copy(n->dsa->q, k->dsa->q) == NULL) ||
1381 (BN_copy(n->dsa->g, k->dsa->g) == NULL) ||
1382 (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL))
1383 fatal("key_from_private: BN_copy failed");
Damien Miller0bc1bd82000-11-13 22:57:25 +11001384 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001385#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001386 case KEY_ECDSA:
1387 case KEY_ECDSA_CERT:
1388 n = key_new(k->type);
1389 n->ecdsa_nid = k->ecdsa_nid;
1390 if ((n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL)
1391 fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
1392 if (EC_KEY_set_public_key(n->ecdsa,
1393 EC_KEY_get0_public_key(k->ecdsa)) != 1)
1394 fatal("%s: EC_KEY_set_public_key failed", __func__);
1395 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001396#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +11001397 case KEY_RSA:
1398 case KEY_RSA1:
Damien Miller4e270b02010-04-16 15:56:21 +10001399 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001400 case KEY_RSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001401 n = key_new(k->type);
Darren Tucker0bc85572006-11-07 23:14:41 +11001402 if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
1403 (BN_copy(n->rsa->e, k->rsa->e) == NULL))
1404 fatal("key_from_private: BN_copy failed");
Damien Miller0bc1bd82000-11-13 22:57:25 +11001405 break;
Damien Miller1f0311c2014-05-15 14:24:09 +10001406#endif
Damien Miller5be9d9e2013-12-07 11:24:01 +11001407 case KEY_ED25519:
1408 case KEY_ED25519_CERT:
1409 n = key_new(k->type);
1410 if (k->ed25519_pk != NULL) {
1411 n->ed25519_pk = xmalloc(ED25519_PK_SZ);
1412 memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
1413 }
1414 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001415 default:
Kevin Stevesef4eea92001-02-05 12:42:17 +00001416 fatal("key_from_private: unknown type %d", k->type);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001417 break;
1418 }
Damien Miller0a80ca12010-02-27 07:55:05 +11001419 if (key_is_cert(k))
1420 key_cert_copy(k, n);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001421 return n;
1422}
1423
1424int
Ben Lindstrom982dbbc2001-04-17 18:11:36 +00001425key_names_valid2(const char *names)
1426{
1427 char *s, *cp, *p;
1428
1429 if (names == NULL || strcmp(names, "") == 0)
1430 return 0;
1431 s = cp = xstrdup(names);
1432 for ((p = strsep(&cp, ",")); p && *p != '\0';
Damien Miller9f0f5c62001-12-21 14:45:46 +11001433 (p = strsep(&cp, ","))) {
Ben Lindstrom982dbbc2001-04-17 18:11:36 +00001434 switch (key_type_from_name(p)) {
1435 case KEY_RSA1:
1436 case KEY_UNSPEC:
Darren Tuckera627d422013-06-02 07:31:17 +10001437 free(s);
Ben Lindstrom982dbbc2001-04-17 18:11:36 +00001438 return 0;
1439 }
1440 }
1441 debug3("key names ok: [%s]", names);
Darren Tuckera627d422013-06-02 07:31:17 +10001442 free(s);
Ben Lindstrom982dbbc2001-04-17 18:11:36 +00001443 return 1;
1444}
1445
Damien Miller0a80ca12010-02-27 07:55:05 +11001446static int
1447cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)
1448{
Damien Miller4e270b02010-04-16 15:56:21 +10001449 u_char *principals, *critical, *exts, *sig_key, *sig;
1450 u_int signed_len, plen, clen, sklen, slen, kidlen, elen;
Damien Miller0a80ca12010-02-27 07:55:05 +11001451 Buffer tmp;
1452 char *principal;
1453 int ret = -1;
Damien Miller4e270b02010-04-16 15:56:21 +10001454 int v00 = key->type == KEY_DSA_CERT_V00 ||
1455 key->type == KEY_RSA_CERT_V00;
Damien Miller0a80ca12010-02-27 07:55:05 +11001456
1457 buffer_init(&tmp);
1458
1459 /* Copy the entire key blob for verification and later serialisation */
1460 buffer_append(&key->cert->certblob, blob, blen);
1461
Damien Miller4e270b02010-04-16 15:56:21 +10001462 elen = 0; /* Not touched for v00 certs */
1463 principals = exts = critical = sig_key = sig = NULL;
1464 if ((!v00 && buffer_get_int64_ret(&key->cert->serial, b) != 0) ||
1465 buffer_get_int_ret(&key->cert->type, b) != 0 ||
Damien Millerda108ec2010-08-31 22:36:39 +10001466 (key->cert->key_id = buffer_get_cstring_ret(b, &kidlen)) == NULL ||
Damien Miller0a80ca12010-02-27 07:55:05 +11001467 (principals = buffer_get_string_ret(b, &plen)) == NULL ||
1468 buffer_get_int64_ret(&key->cert->valid_after, b) != 0 ||
1469 buffer_get_int64_ret(&key->cert->valid_before, b) != 0 ||
Damien Miller4e270b02010-04-16 15:56:21 +10001470 (critical = buffer_get_string_ret(b, &clen)) == NULL ||
1471 (!v00 && (exts = buffer_get_string_ret(b, &elen)) == NULL) ||
1472 (v00 && buffer_get_string_ptr_ret(b, NULL) == NULL) || /* nonce */
1473 buffer_get_string_ptr_ret(b, NULL) == NULL || /* reserved */
Damien Miller0a80ca12010-02-27 07:55:05 +11001474 (sig_key = buffer_get_string_ret(b, &sklen)) == NULL) {
1475 error("%s: parse error", __func__);
1476 goto out;
1477 }
1478
1479 /* Signature is left in the buffer so we can calculate this length */
1480 signed_len = buffer_len(&key->cert->certblob) - buffer_len(b);
1481
1482 if ((sig = buffer_get_string_ret(b, &slen)) == NULL) {
1483 error("%s: parse error", __func__);
1484 goto out;
1485 }
1486
1487 if (key->cert->type != SSH2_CERT_TYPE_USER &&
1488 key->cert->type != SSH2_CERT_TYPE_HOST) {
1489 error("Unknown certificate type %u", key->cert->type);
1490 goto out;
1491 }
1492
1493 buffer_append(&tmp, principals, plen);
1494 while (buffer_len(&tmp) > 0) {
1495 if (key->cert->nprincipals >= CERT_MAX_PRINCIPALS) {
Damien Miller41396572010-03-04 21:51:11 +11001496 error("%s: Too many principals", __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001497 goto out;
1498 }
Damien Millerda108ec2010-08-31 22:36:39 +10001499 if ((principal = buffer_get_cstring_ret(&tmp, &plen)) == NULL) {
Damien Miller41396572010-03-04 21:51:11 +11001500 error("%s: Principals data invalid", __func__);
1501 goto out;
1502 }
Damien Miller0a80ca12010-02-27 07:55:05 +11001503 key->cert->principals = xrealloc(key->cert->principals,
1504 key->cert->nprincipals + 1, sizeof(*key->cert->principals));
1505 key->cert->principals[key->cert->nprincipals++] = principal;
1506 }
1507
1508 buffer_clear(&tmp);
1509
Damien Miller4e270b02010-04-16 15:56:21 +10001510 buffer_append(&key->cert->critical, critical, clen);
1511 buffer_append(&tmp, critical, clen);
Damien Miller0a80ca12010-02-27 07:55:05 +11001512 /* validate structure */
1513 while (buffer_len(&tmp) != 0) {
Damien Miller2befbad2010-03-04 21:52:18 +11001514 if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||
1515 buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {
Damien Miller4e270b02010-04-16 15:56:21 +10001516 error("%s: critical option data invalid", __func__);
1517 goto out;
1518 }
1519 }
1520 buffer_clear(&tmp);
1521
1522 buffer_append(&key->cert->extensions, exts, elen);
1523 buffer_append(&tmp, exts, elen);
1524 /* validate structure */
1525 while (buffer_len(&tmp) != 0) {
1526 if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||
1527 buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {
1528 error("%s: extension data invalid", __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001529 goto out;
1530 }
1531 }
1532 buffer_clear(&tmp);
1533
Damien Miller4a3a9d42013-10-30 22:19:47 +11001534 if ((key->cert->signature_key = key_from_blob2(sig_key, sklen, 0))
1535 == NULL) {
Damien Miller41396572010-03-04 21:51:11 +11001536 error("%s: Signature key invalid", __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001537 goto out;
1538 }
Damien Miller29ace1c2013-12-29 17:49:31 +11001539 if (!key_type_is_valid_ca(key->cert->signature_key->type)) {
Damien Miller41396572010-03-04 21:51:11 +11001540 error("%s: Invalid signature key type %s (%d)", __func__,
Damien Miller0a80ca12010-02-27 07:55:05 +11001541 key_type(key->cert->signature_key),
1542 key->cert->signature_key->type);
1543 goto out;
1544 }
1545
1546 switch (key_verify(key->cert->signature_key, sig, slen,
1547 buffer_ptr(&key->cert->certblob), signed_len)) {
1548 case 1:
Damien Miller41396572010-03-04 21:51:11 +11001549 ret = 0;
Damien Miller0a80ca12010-02-27 07:55:05 +11001550 break; /* Good signature */
1551 case 0:
Damien Miller41396572010-03-04 21:51:11 +11001552 error("%s: Invalid signature on certificate", __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001553 goto out;
1554 case -1:
Damien Miller41396572010-03-04 21:51:11 +11001555 error("%s: Certificate signature verification failed",
1556 __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001557 goto out;
1558 }
1559
Damien Miller0a80ca12010-02-27 07:55:05 +11001560 out:
1561 buffer_free(&tmp);
Darren Tuckera627d422013-06-02 07:31:17 +10001562 free(principals);
1563 free(critical);
1564 free(exts);
1565 free(sig_key);
1566 free(sig);
Damien Miller0a80ca12010-02-27 07:55:05 +11001567 return ret;
1568}
1569
Damien Miller4a3a9d42013-10-30 22:19:47 +11001570static Key *
1571key_from_blob2(const u_char *blob, u_int blen, int allow_cert)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001572{
1573 Buffer b;
Darren Tucker8ccb7392010-09-10 12:28:24 +10001574 int rlen, type;
Damien Miller5be9d9e2013-12-07 11:24:01 +11001575 u_int len;
Damien Millereb8b60e2010-08-31 22:41:14 +10001576 char *ktype = NULL, *curve = NULL;
Damien Miller5be9d9e2013-12-07 11:24:01 +11001577 u_char *pk = NULL;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001578 Key *key = NULL;
Damien Miller6af914a2010-09-10 11:39:26 +10001579#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001580 EC_POINT *q = NULL;
Darren Tucker8ccb7392010-09-10 12:28:24 +10001581 int nid = -1;
Damien Miller6af914a2010-09-10 11:39:26 +10001582#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +11001583
1584#ifdef DEBUG_PK
1585 dump_base64(stderr, blob, blen);
1586#endif
1587 buffer_init(&b);
1588 buffer_append(&b, blob, blen);
Damien Millerda108ec2010-08-31 22:36:39 +10001589 if ((ktype = buffer_get_cstring_ret(&b, NULL)) == NULL) {
Darren Tucker08d04fa2004-11-05 20:42:28 +11001590 error("key_from_blob: can't read key type");
1591 goto out;
1592 }
1593
Damien Miller0bc1bd82000-11-13 22:57:25 +11001594 type = key_type_from_name(ktype);
Damien Miller6af914a2010-09-10 11:39:26 +10001595#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001596 if (key_type_plain(type) == KEY_ECDSA)
1597 nid = key_ecdsa_nid_from_name(ktype);
Damien Miller6af914a2010-09-10 11:39:26 +10001598#endif
Damien Miller4a3a9d42013-10-30 22:19:47 +11001599 if (!allow_cert && key_type_is_cert(type)) {
1600 error("key_from_blob: certificate not allowed in this context");
1601 goto out;
1602 }
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001603 switch (type) {
Damien Miller1f0311c2014-05-15 14:24:09 +10001604#ifdef WITH_OPENSSL
Damien Miller0a80ca12010-02-27 07:55:05 +11001605 case KEY_RSA_CERT:
Damien Miller4e270b02010-04-16 15:56:21 +10001606 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1607 /* FALLTHROUGH */
1608 case KEY_RSA:
1609 case KEY_RSA_CERT_V00:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001610 key = key_new(type);
Darren Tucker08d04fa2004-11-05 20:42:28 +11001611 if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 ||
1612 buffer_get_bignum2_ret(&b, key->rsa->n) == -1) {
1613 error("key_from_blob: can't read rsa key");
Damien Miller1f0311c2014-05-15 14:24:09 +10001614 goto badkey;
Darren Tucker08d04fa2004-11-05 20:42:28 +11001615 }
Damien Miller0bc1bd82000-11-13 22:57:25 +11001616#ifdef DEBUG_PK
1617 RSA_print_fp(stderr, key->rsa, 8);
1618#endif
1619 break;
Damien Miller0a80ca12010-02-27 07:55:05 +11001620 case KEY_DSA_CERT:
Damien Miller4e270b02010-04-16 15:56:21 +10001621 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1622 /* FALLTHROUGH */
1623 case KEY_DSA:
1624 case KEY_DSA_CERT_V00:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001625 key = key_new(type);
Darren Tucker08d04fa2004-11-05 20:42:28 +11001626 if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 ||
1627 buffer_get_bignum2_ret(&b, key->dsa->q) == -1 ||
1628 buffer_get_bignum2_ret(&b, key->dsa->g) == -1 ||
1629 buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) {
1630 error("key_from_blob: can't read dsa key");
Damien Miller0a80ca12010-02-27 07:55:05 +11001631 goto badkey;
Darren Tucker08d04fa2004-11-05 20:42:28 +11001632 }
Damien Miller0bc1bd82000-11-13 22:57:25 +11001633#ifdef DEBUG_PK
1634 DSA_print_fp(stderr, key->dsa, 8);
1635#endif
1636 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001637#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001638 case KEY_ECDSA_CERT:
1639 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1640 /* FALLTHROUGH */
1641 case KEY_ECDSA:
1642 key = key_new(type);
1643 key->ecdsa_nid = nid;
1644 if ((curve = buffer_get_string_ret(&b, NULL)) == NULL) {
1645 error("key_from_blob: can't read ecdsa curve");
1646 goto badkey;
1647 }
1648 if (key->ecdsa_nid != key_curve_name_to_nid(curve)) {
1649 error("key_from_blob: ecdsa curve doesn't match type");
1650 goto badkey;
1651 }
1652 if (key->ecdsa != NULL)
1653 EC_KEY_free(key->ecdsa);
1654 if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
1655 == NULL)
1656 fatal("key_from_blob: EC_KEY_new_by_curve_name failed");
1657 if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL)
1658 fatal("key_from_blob: EC_POINT_new failed");
1659 if (buffer_get_ecpoint_ret(&b, EC_KEY_get0_group(key->ecdsa),
1660 q) == -1) {
1661 error("key_from_blob: can't read ecdsa key point");
1662 goto badkey;
1663 }
1664 if (key_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
1665 q) != 0)
1666 goto badkey;
1667 if (EC_KEY_set_public_key(key->ecdsa, q) != 1)
1668 fatal("key_from_blob: EC_KEY_set_public_key failed");
1669#ifdef DEBUG_PK
1670 key_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
1671#endif
1672 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001673#endif /* OPENSSL_HAS_ECC */
Damien Miller5be9d9e2013-12-07 11:24:01 +11001674 case KEY_ED25519_CERT:
1675 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1676 /* FALLTHROUGH */
1677 case KEY_ED25519:
1678 if ((pk = buffer_get_string_ret(&b, &len)) == NULL) {
1679 error("key_from_blob: can't read ed25519 key");
1680 goto badkey;
1681 }
1682 if (len != ED25519_PK_SZ) {
1683 error("key_from_blob: ed25519 len %d != %d",
1684 len, ED25519_PK_SZ);
1685 goto badkey;
1686 }
1687 key = key_new(type);
1688 key->ed25519_pk = pk;
1689 pk = NULL;
1690 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001691 case KEY_UNSPEC:
1692 key = key_new(type);
1693 break;
1694 default:
1695 error("key_from_blob: cannot handle type %s", ktype);
Darren Tucker08d04fa2004-11-05 20:42:28 +11001696 goto out;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001697 }
Damien Miller0a80ca12010-02-27 07:55:05 +11001698 if (key_is_cert(key) && cert_parse(&b, key, blob, blen) == -1) {
1699 error("key_from_blob: can't parse cert data");
1700 goto badkey;
1701 }
Damien Miller0bc1bd82000-11-13 22:57:25 +11001702 rlen = buffer_len(&b);
1703 if (key != NULL && rlen != 0)
1704 error("key_from_blob: remaining bytes in key blob %d", rlen);
Darren Tucker08d04fa2004-11-05 20:42:28 +11001705 out:
Darren Tuckera627d422013-06-02 07:31:17 +10001706 free(ktype);
1707 free(curve);
Damien Miller5be9d9e2013-12-07 11:24:01 +11001708 free(pk);
Damien Miller6af914a2010-09-10 11:39:26 +10001709#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001710 if (q != NULL)
1711 EC_POINT_free(q);
Damien Miller6af914a2010-09-10 11:39:26 +10001712#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +11001713 buffer_free(&b);
1714 return key;
Damien Miller1f0311c2014-05-15 14:24:09 +10001715
1716 badkey:
1717 key_free(key);
1718 key = NULL;
1719 goto out;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001720}
1721
Damien Miller4a3a9d42013-10-30 22:19:47 +11001722Key *
1723key_from_blob(const u_char *blob, u_int blen)
1724{
1725 return key_from_blob2(blob, blen, 1);
1726}
1727
Damien Millerf3747bf2013-01-18 11:44:04 +11001728static int
1729to_blob(const Key *key, u_char **blobp, u_int *lenp, int force_plain)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001730{
1731 Buffer b;
Damien Millerf3747bf2013-01-18 11:44:04 +11001732 int len, type;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001733
Damien Millerf7e8a872013-12-05 10:25:51 +11001734 if (blobp != NULL)
1735 *blobp = NULL;
1736 if (lenp != NULL)
1737 *lenp = 0;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001738 if (key == NULL) {
1739 error("key_to_blob: key == NULL");
1740 return 0;
1741 }
1742 buffer_init(&b);
Damien Millerf3747bf2013-01-18 11:44:04 +11001743 type = force_plain ? key_type_plain(key->type) : key->type;
1744 switch (type) {
Damien Miller1f0311c2014-05-15 14:24:09 +10001745#ifdef WITH_OPENSSL
Damien Miller4e270b02010-04-16 15:56:21 +10001746 case KEY_DSA_CERT_V00:
1747 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001748 case KEY_DSA_CERT:
Damien Millereb8b60e2010-08-31 22:41:14 +10001749 case KEY_ECDSA_CERT:
Damien Miller0a80ca12010-02-27 07:55:05 +11001750 case KEY_RSA_CERT:
Damien Miller1f0311c2014-05-15 14:24:09 +10001751#endif
Damien Miller5be9d9e2013-12-07 11:24:01 +11001752 case KEY_ED25519_CERT:
Damien Miller0a80ca12010-02-27 07:55:05 +11001753 /* Use the existing blob */
1754 buffer_append(&b, buffer_ptr(&key->cert->certblob),
1755 buffer_len(&key->cert->certblob));
1756 break;
Damien Miller1f0311c2014-05-15 14:24:09 +10001757#ifdef WITH_OPENSSL
Damien Miller0bc1bd82000-11-13 22:57:25 +11001758 case KEY_DSA:
Damien Millerf3747bf2013-01-18 11:44:04 +11001759 buffer_put_cstring(&b,
1760 key_ssh_name_from_type_nid(type, key->ecdsa_nid));
Damien Miller0bc1bd82000-11-13 22:57:25 +11001761 buffer_put_bignum2(&b, key->dsa->p);
1762 buffer_put_bignum2(&b, key->dsa->q);
1763 buffer_put_bignum2(&b, key->dsa->g);
1764 buffer_put_bignum2(&b, key->dsa->pub_key);
1765 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001766#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001767 case KEY_ECDSA:
Damien Millerf3747bf2013-01-18 11:44:04 +11001768 buffer_put_cstring(&b,
1769 key_ssh_name_from_type_nid(type, key->ecdsa_nid));
Damien Millereb8b60e2010-08-31 22:41:14 +10001770 buffer_put_cstring(&b, key_curve_nid_to_name(key->ecdsa_nid));
1771 buffer_put_ecpoint(&b, EC_KEY_get0_group(key->ecdsa),
1772 EC_KEY_get0_public_key(key->ecdsa));
1773 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001774#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +11001775 case KEY_RSA:
Damien Millerf3747bf2013-01-18 11:44:04 +11001776 buffer_put_cstring(&b,
1777 key_ssh_name_from_type_nid(type, key->ecdsa_nid));
Damien Miller0bc1bd82000-11-13 22:57:25 +11001778 buffer_put_bignum2(&b, key->rsa->e);
Ben Lindstrombf555ba2001-01-18 02:04:35 +00001779 buffer_put_bignum2(&b, key->rsa->n);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001780 break;
Damien Miller1f0311c2014-05-15 14:24:09 +10001781#endif
Damien Miller5be9d9e2013-12-07 11:24:01 +11001782 case KEY_ED25519:
1783 buffer_put_cstring(&b,
1784 key_ssh_name_from_type_nid(type, key->ecdsa_nid));
1785 buffer_put_string(&b, key->ed25519_pk, ED25519_PK_SZ);
1786 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001787 default:
Ben Lindstrom99a30f12001-09-18 05:49:14 +00001788 error("key_to_blob: unsupported key type %d", key->type);
1789 buffer_free(&b);
1790 return 0;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001791 }
1792 len = buffer_len(&b);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001793 if (lenp != NULL)
1794 *lenp = len;
Ben Lindstrom2bf759c2002-07-07 22:13:31 +00001795 if (blobp != NULL) {
1796 *blobp = xmalloc(len);
1797 memcpy(*blobp, buffer_ptr(&b), len);
1798 }
Damien Millera5103f42014-02-04 11:20:14 +11001799 explicit_bzero(buffer_ptr(&b), len);
Ben Lindstrom2bf759c2002-07-07 22:13:31 +00001800 buffer_free(&b);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001801 return len;
1802}
1803
1804int
Damien Millerf3747bf2013-01-18 11:44:04 +11001805key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
1806{
1807 return to_blob(key, blobp, lenp, 0);
1808}
1809
1810int
Damien Miller0bc1bd82000-11-13 22:57:25 +11001811key_sign(
Damien Millerf58b58c2003-11-17 21:18:23 +11001812 const Key *key,
Ben Lindstrom90fd8142002-02-26 18:09:42 +00001813 u_char **sigp, u_int *lenp,
Damien Millerf58b58c2003-11-17 21:18:23 +11001814 const u_char *data, u_int datalen)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001815{
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001816 switch (key->type) {
Damien Miller1f0311c2014-05-15 14:24:09 +10001817#ifdef WITH_OPENSSL
Damien Miller4e270b02010-04-16 15:56:21 +10001818 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001819 case KEY_DSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001820 case KEY_DSA:
1821 return ssh_dss_sign(key, sigp, lenp, data, datalen);
Damien Miller6af914a2010-09-10 11:39:26 +10001822#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001823 case KEY_ECDSA_CERT:
1824 case KEY_ECDSA:
1825 return ssh_ecdsa_sign(key, sigp, lenp, data, datalen);
Damien Miller6af914a2010-09-10 11:39:26 +10001826#endif
Damien Miller4e270b02010-04-16 15:56:21 +10001827 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001828 case KEY_RSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001829 case KEY_RSA:
1830 return ssh_rsa_sign(key, sigp, lenp, data, datalen);
Damien Miller1f0311c2014-05-15 14:24:09 +10001831#endif
Damien Miller5be9d9e2013-12-07 11:24:01 +11001832 case KEY_ED25519:
1833 case KEY_ED25519_CERT:
1834 return ssh_ed25519_sign(key, sigp, lenp, data, datalen);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001835 default:
Darren Tucker5cb30ad2004-08-12 22:40:24 +10001836 error("key_sign: invalid key type %d", key->type);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001837 return -1;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001838 }
1839}
1840
Ben Lindstrom01fff0c2002-06-06 20:54:07 +00001841/*
1842 * key_verify returns 1 for a correct signature, 0 for an incorrect signature
1843 * and -1 on error.
1844 */
Damien Miller0bc1bd82000-11-13 22:57:25 +11001845int
1846key_verify(
Damien Millerf58b58c2003-11-17 21:18:23 +11001847 const Key *key,
1848 const u_char *signature, u_int signaturelen,
1849 const u_char *data, u_int datalen)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001850{
Ben Lindstrom5363aee2001-06-25 04:42:20 +00001851 if (signaturelen == 0)
1852 return -1;
1853
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001854 switch (key->type) {
Damien Miller1f0311c2014-05-15 14:24:09 +10001855#ifdef WITH_OPENSSL
Damien Miller4e270b02010-04-16 15:56:21 +10001856 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001857 case KEY_DSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001858 case KEY_DSA:
1859 return ssh_dss_verify(key, signature, signaturelen, data, datalen);
Damien Miller6af914a2010-09-10 11:39:26 +10001860#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001861 case KEY_ECDSA_CERT:
1862 case KEY_ECDSA:
1863 return ssh_ecdsa_verify(key, signature, signaturelen, data, datalen);
Damien Miller6af914a2010-09-10 11:39:26 +10001864#endif
Damien Miller4e270b02010-04-16 15:56:21 +10001865 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001866 case KEY_RSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001867 case KEY_RSA:
1868 return ssh_rsa_verify(key, signature, signaturelen, data, datalen);
Damien Miller1f0311c2014-05-15 14:24:09 +10001869#endif
Damien Miller5be9d9e2013-12-07 11:24:01 +11001870 case KEY_ED25519:
1871 case KEY_ED25519_CERT:
1872 return ssh_ed25519_verify(key, signature, signaturelen, data, datalen);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001873 default:
Darren Tucker5cb30ad2004-08-12 22:40:24 +10001874 error("key_verify: invalid key type %d", key->type);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001875 return -1;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001876 }
1877}
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001878
1879/* Converts a private to a public key */
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001880Key *
Damien Millerf58b58c2003-11-17 21:18:23 +11001881key_demote(const Key *k)
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001882{
1883 Key *pk;
Ben Lindstrom6328ab32002-03-22 02:54:23 +00001884
Damien Miller07d86be2006-03-26 14:19:21 +11001885 pk = xcalloc(1, sizeof(*pk));
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001886 pk->type = k->type;
1887 pk->flags = k->flags;
Damien Millereb8b60e2010-08-31 22:41:14 +10001888 pk->ecdsa_nid = k->ecdsa_nid;
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001889 pk->dsa = NULL;
Damien Millereb8b60e2010-08-31 22:41:14 +10001890 pk->ecdsa = NULL;
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001891 pk->rsa = NULL;
Damien Miller5be9d9e2013-12-07 11:24:01 +11001892 pk->ed25519_pk = NULL;
1893 pk->ed25519_sk = NULL;
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001894
1895 switch (k->type) {
Damien Miller1f0311c2014-05-15 14:24:09 +10001896#ifdef WITH_OPENSSL
Damien Miller4e270b02010-04-16 15:56:21 +10001897 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001898 case KEY_RSA_CERT:
1899 key_cert_copy(k, pk);
1900 /* FALLTHROUGH */
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001901 case KEY_RSA1:
1902 case KEY_RSA:
1903 if ((pk->rsa = RSA_new()) == NULL)
1904 fatal("key_demote: RSA_new failed");
1905 if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL)
1906 fatal("key_demote: BN_dup failed");
1907 if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL)
1908 fatal("key_demote: BN_dup failed");
1909 break;
Damien Miller4e270b02010-04-16 15:56:21 +10001910 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001911 case KEY_DSA_CERT:
1912 key_cert_copy(k, pk);
1913 /* FALLTHROUGH */
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001914 case KEY_DSA:
1915 if ((pk->dsa = DSA_new()) == NULL)
1916 fatal("key_demote: DSA_new failed");
1917 if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL)
1918 fatal("key_demote: BN_dup failed");
1919 if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL)
1920 fatal("key_demote: BN_dup failed");
1921 if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL)
1922 fatal("key_demote: BN_dup failed");
1923 if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL)
1924 fatal("key_demote: BN_dup failed");
1925 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001926#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001927 case KEY_ECDSA_CERT:
1928 key_cert_copy(k, pk);
1929 /* FALLTHROUGH */
1930 case KEY_ECDSA:
1931 if ((pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid)) == NULL)
1932 fatal("key_demote: EC_KEY_new_by_curve_name failed");
1933 if (EC_KEY_set_public_key(pk->ecdsa,
1934 EC_KEY_get0_public_key(k->ecdsa)) != 1)
1935 fatal("key_demote: EC_KEY_set_public_key failed");
1936 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001937#endif
Damien Miller5be9d9e2013-12-07 11:24:01 +11001938 case KEY_ED25519_CERT:
1939 key_cert_copy(k, pk);
1940 /* FALLTHROUGH */
1941 case KEY_ED25519:
1942 if (k->ed25519_pk != NULL) {
1943 pk->ed25519_pk = xmalloc(ED25519_PK_SZ);
1944 memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
1945 }
1946 break;
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001947 default:
Damien Miller5be9d9e2013-12-07 11:24:01 +11001948 fatal("key_demote: bad key type %d", k->type);
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001949 break;
1950 }
1951
1952 return (pk);
1953}
Damien Miller0a80ca12010-02-27 07:55:05 +11001954
1955int
1956key_is_cert(const Key *k)
1957{
Damien Miller4e270b02010-04-16 15:56:21 +10001958 if (k == NULL)
1959 return 0;
Damien Miller4a3a9d42013-10-30 22:19:47 +11001960 return key_type_is_cert(k->type);
Damien Miller0a80ca12010-02-27 07:55:05 +11001961}
1962
1963/* Return the cert-less equivalent to a certified key type */
1964int
1965key_type_plain(int type)
1966{
1967 switch (type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001968 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001969 case KEY_RSA_CERT:
1970 return KEY_RSA;
Damien Miller4e270b02010-04-16 15:56:21 +10001971 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001972 case KEY_DSA_CERT:
1973 return KEY_DSA;
Damien Millereb8b60e2010-08-31 22:41:14 +10001974 case KEY_ECDSA_CERT:
1975 return KEY_ECDSA;
Damien Miller5be9d9e2013-12-07 11:24:01 +11001976 case KEY_ED25519_CERT:
1977 return KEY_ED25519;
Damien Miller0a80ca12010-02-27 07:55:05 +11001978 default:
1979 return type;
1980 }
1981}
1982
Damien Miller5baeacf2013-12-29 17:48:55 +11001983/* Convert a plain key to their _CERT equivalent */
Damien Miller0a80ca12010-02-27 07:55:05 +11001984int
Damien Miller4e270b02010-04-16 15:56:21 +10001985key_to_certified(Key *k, int legacy)
Damien Miller0a80ca12010-02-27 07:55:05 +11001986{
1987 switch (k->type) {
1988 case KEY_RSA:
1989 k->cert = cert_new();
Damien Miller4e270b02010-04-16 15:56:21 +10001990 k->type = legacy ? KEY_RSA_CERT_V00 : KEY_RSA_CERT;
Damien Miller0a80ca12010-02-27 07:55:05 +11001991 return 0;
1992 case KEY_DSA:
1993 k->cert = cert_new();
Damien Miller4e270b02010-04-16 15:56:21 +10001994 k->type = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT;
Damien Miller0a80ca12010-02-27 07:55:05 +11001995 return 0;
Damien Millereb8b60e2010-08-31 22:41:14 +10001996 case KEY_ECDSA:
Damien Miller8f639fe2011-05-20 19:03:08 +10001997 if (legacy)
1998 fatal("%s: legacy ECDSA certificates are not supported",
1999 __func__);
Damien Millereb8b60e2010-08-31 22:41:14 +10002000 k->cert = cert_new();
2001 k->type = KEY_ECDSA_CERT;
2002 return 0;
Damien Miller5be9d9e2013-12-07 11:24:01 +11002003 case KEY_ED25519:
2004 if (legacy)
2005 fatal("%s: legacy ED25519 certificates are not "
2006 "supported", __func__);
2007 k->cert = cert_new();
2008 k->type = KEY_ED25519_CERT;
2009 return 0;
Damien Miller0a80ca12010-02-27 07:55:05 +11002010 default:
2011 error("%s: key has incorrect type %s", __func__, key_type(k));
2012 return -1;
2013 }
2014}
2015
Damien Miller9de4fcd2013-12-29 17:49:13 +11002016/* Convert a certificate to its raw key equivalent */
Damien Miller0a80ca12010-02-27 07:55:05 +11002017int
2018key_drop_cert(Key *k)
2019{
Damien Miller5be9d9e2013-12-07 11:24:01 +11002020 if (!key_type_is_cert(k->type)) {
Damien Miller0a80ca12010-02-27 07:55:05 +11002021 error("%s: key has incorrect type %s", __func__, key_type(k));
2022 return -1;
2023 }
Damien Miller5be9d9e2013-12-07 11:24:01 +11002024 cert_free(k->cert);
Damien Millerca570a52013-12-07 11:29:09 +11002025 k->cert = NULL;
Damien Miller5be9d9e2013-12-07 11:24:01 +11002026 k->type = key_type_plain(k->type);
2027 return 0;
Damien Miller0a80ca12010-02-27 07:55:05 +11002028}
2029
Damien Miller5be9d9e2013-12-07 11:24:01 +11002030/* Sign a certified key, (re-)generating the signed certblob. */
Damien Miller0a80ca12010-02-27 07:55:05 +11002031int
2032key_certify(Key *k, Key *ca)
2033{
2034 Buffer principals;
2035 u_char *ca_blob, *sig_blob, nonce[32];
2036 u_int i, ca_len, sig_len;
2037
2038 if (k->cert == NULL) {
2039 error("%s: key lacks cert info", __func__);
2040 return -1;
2041 }
2042
2043 if (!key_is_cert(k)) {
2044 error("%s: certificate has unknown type %d", __func__,
2045 k->cert->type);
2046 return -1;
2047 }
2048
Damien Miller29ace1c2013-12-29 17:49:31 +11002049 if (!key_type_is_valid_ca(ca->type)) {
Damien Miller0a80ca12010-02-27 07:55:05 +11002050 error("%s: CA key has unsupported type %s", __func__,
2051 key_type(ca));
2052 return -1;
2053 }
2054
2055 key_to_blob(ca, &ca_blob, &ca_len);
2056
2057 buffer_clear(&k->cert->certblob);
2058 buffer_put_cstring(&k->cert->certblob, key_ssh_name(k));
2059
Damien Miller4e270b02010-04-16 15:56:21 +10002060 /* -v01 certs put nonce first */
Damien Miller0a5f0122011-02-04 11:47:01 +11002061 arc4random_buf(&nonce, sizeof(nonce));
2062 if (!key_cert_is_legacy(k))
Damien Miller4e270b02010-04-16 15:56:21 +10002063 buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
Damien Miller4e270b02010-04-16 15:56:21 +10002064
Damien Millerbcd00ab2013-12-07 10:41:55 +11002065 /* XXX this substantially duplicates to_blob(); refactor */
Damien Miller0a80ca12010-02-27 07:55:05 +11002066 switch (k->type) {
Damien Miller1f0311c2014-05-15 14:24:09 +10002067#ifdef WITH_OPENSSL
Damien Miller4e270b02010-04-16 15:56:21 +10002068 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11002069 case KEY_DSA_CERT:
2070 buffer_put_bignum2(&k->cert->certblob, k->dsa->p);
2071 buffer_put_bignum2(&k->cert->certblob, k->dsa->q);
2072 buffer_put_bignum2(&k->cert->certblob, k->dsa->g);
2073 buffer_put_bignum2(&k->cert->certblob, k->dsa->pub_key);
2074 break;
Damien Miller6af914a2010-09-10 11:39:26 +10002075#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10002076 case KEY_ECDSA_CERT:
2077 buffer_put_cstring(&k->cert->certblob,
2078 key_curve_nid_to_name(k->ecdsa_nid));
2079 buffer_put_ecpoint(&k->cert->certblob,
2080 EC_KEY_get0_group(k->ecdsa),
2081 EC_KEY_get0_public_key(k->ecdsa));
2082 break;
Damien Miller6af914a2010-09-10 11:39:26 +10002083#endif
Damien Miller4e270b02010-04-16 15:56:21 +10002084 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11002085 case KEY_RSA_CERT:
2086 buffer_put_bignum2(&k->cert->certblob, k->rsa->e);
2087 buffer_put_bignum2(&k->cert->certblob, k->rsa->n);
2088 break;
Damien Miller1f0311c2014-05-15 14:24:09 +10002089#endif
Damien Miller5be9d9e2013-12-07 11:24:01 +11002090 case KEY_ED25519_CERT:
2091 buffer_put_string(&k->cert->certblob,
2092 k->ed25519_pk, ED25519_PK_SZ);
2093 break;
Damien Miller0a80ca12010-02-27 07:55:05 +11002094 default:
2095 error("%s: key has incorrect type %s", __func__, key_type(k));
2096 buffer_clear(&k->cert->certblob);
Darren Tuckera627d422013-06-02 07:31:17 +10002097 free(ca_blob);
Damien Miller0a80ca12010-02-27 07:55:05 +11002098 return -1;
2099 }
2100
Damien Miller4e270b02010-04-16 15:56:21 +10002101 /* -v01 certs have a serial number next */
Damien Millereb8b60e2010-08-31 22:41:14 +10002102 if (!key_cert_is_legacy(k))
Damien Miller4e270b02010-04-16 15:56:21 +10002103 buffer_put_int64(&k->cert->certblob, k->cert->serial);
2104
Damien Miller0a80ca12010-02-27 07:55:05 +11002105 buffer_put_int(&k->cert->certblob, k->cert->type);
2106 buffer_put_cstring(&k->cert->certblob, k->cert->key_id);
2107
2108 buffer_init(&principals);
2109 for (i = 0; i < k->cert->nprincipals; i++)
2110 buffer_put_cstring(&principals, k->cert->principals[i]);
2111 buffer_put_string(&k->cert->certblob, buffer_ptr(&principals),
2112 buffer_len(&principals));
2113 buffer_free(&principals);
2114
2115 buffer_put_int64(&k->cert->certblob, k->cert->valid_after);
2116 buffer_put_int64(&k->cert->certblob, k->cert->valid_before);
2117 buffer_put_string(&k->cert->certblob,
Damien Miller4e270b02010-04-16 15:56:21 +10002118 buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical));
Damien Miller0a80ca12010-02-27 07:55:05 +11002119
Damien Miller4e270b02010-04-16 15:56:21 +10002120 /* -v01 certs have non-critical options here */
Damien Millereb8b60e2010-08-31 22:41:14 +10002121 if (!key_cert_is_legacy(k)) {
Damien Miller4e270b02010-04-16 15:56:21 +10002122 buffer_put_string(&k->cert->certblob,
2123 buffer_ptr(&k->cert->extensions),
2124 buffer_len(&k->cert->extensions));
2125 }
2126
2127 /* -v00 certs put the nonce at the end */
Damien Millereb8b60e2010-08-31 22:41:14 +10002128 if (key_cert_is_legacy(k))
Damien Miller4e270b02010-04-16 15:56:21 +10002129 buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
2130
Damien Miller0a80ca12010-02-27 07:55:05 +11002131 buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */
2132 buffer_put_string(&k->cert->certblob, ca_blob, ca_len);
Darren Tuckera627d422013-06-02 07:31:17 +10002133 free(ca_blob);
Damien Miller0a80ca12010-02-27 07:55:05 +11002134
2135 /* Sign the whole mess */
2136 if (key_sign(ca, &sig_blob, &sig_len, buffer_ptr(&k->cert->certblob),
2137 buffer_len(&k->cert->certblob)) != 0) {
2138 error("%s: signature operation failed", __func__);
2139 buffer_clear(&k->cert->certblob);
2140 return -1;
2141 }
2142 /* Append signature and we are done */
2143 buffer_put_string(&k->cert->certblob, sig_blob, sig_len);
Darren Tuckera627d422013-06-02 07:31:17 +10002144 free(sig_blob);
Damien Miller0a80ca12010-02-27 07:55:05 +11002145
2146 return 0;
2147}
2148
2149int
2150key_cert_check_authority(const Key *k, int want_host, int require_principal,
2151 const char *name, const char **reason)
2152{
2153 u_int i, principal_matches;
2154 time_t now = time(NULL);
2155
2156 if (want_host) {
2157 if (k->cert->type != SSH2_CERT_TYPE_HOST) {
2158 *reason = "Certificate invalid: not a host certificate";
2159 return -1;
2160 }
2161 } else {
2162 if (k->cert->type != SSH2_CERT_TYPE_USER) {
2163 *reason = "Certificate invalid: not a user certificate";
2164 return -1;
2165 }
2166 }
2167 if (now < 0) {
2168 error("%s: system clock lies before epoch", __func__);
2169 *reason = "Certificate invalid: not yet valid";
2170 return -1;
2171 }
2172 if ((u_int64_t)now < k->cert->valid_after) {
2173 *reason = "Certificate invalid: not yet valid";
2174 return -1;
2175 }
2176 if ((u_int64_t)now >= k->cert->valid_before) {
2177 *reason = "Certificate invalid: expired";
2178 return -1;
2179 }
2180 if (k->cert->nprincipals == 0) {
2181 if (require_principal) {
2182 *reason = "Certificate lacks principal list";
2183 return -1;
2184 }
Damien Miller30da3442010-05-10 11:58:03 +10002185 } else if (name != NULL) {
Damien Miller0a80ca12010-02-27 07:55:05 +11002186 principal_matches = 0;
2187 for (i = 0; i < k->cert->nprincipals; i++) {
2188 if (strcmp(name, k->cert->principals[i]) == 0) {
2189 principal_matches = 1;
2190 break;
2191 }
2192 }
2193 if (!principal_matches) {
2194 *reason = "Certificate invalid: name is not a listed "
2195 "principal";
2196 return -1;
2197 }
2198 }
2199 return 0;
2200}
Damien Miller4e270b02010-04-16 15:56:21 +10002201
2202int
Damien Millerf3747bf2013-01-18 11:44:04 +11002203key_cert_is_legacy(const Key *k)
Damien Miller4e270b02010-04-16 15:56:21 +10002204{
2205 switch (k->type) {
2206 case KEY_DSA_CERT_V00:
2207 case KEY_RSA_CERT_V00:
2208 return 1;
2209 default:
2210 return 0;
2211 }
2212}
Damien Millereb8b60e2010-08-31 22:41:14 +10002213
Damien Miller1f0311c2014-05-15 14:24:09 +10002214#ifdef WITH_OPENSSL
Damien Miller041ab7c2010-09-10 11:23:34 +10002215/* XXX: these are really begging for a table-driven approach */
Damien Millereb8b60e2010-08-31 22:41:14 +10002216int
2217key_curve_name_to_nid(const char *name)
2218{
Damien Miller6af914a2010-09-10 11:39:26 +10002219#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10002220 if (strcmp(name, "nistp256") == 0)
2221 return NID_X9_62_prime256v1;
2222 else if (strcmp(name, "nistp384") == 0)
2223 return NID_secp384r1;
Darren Tucker37bcef52013-11-09 18:39:25 +11002224# ifdef OPENSSL_HAS_NISTP521
Damien Millereb8b60e2010-08-31 22:41:14 +10002225 else if (strcmp(name, "nistp521") == 0)
2226 return NID_secp521r1;
Darren Tucker37bcef52013-11-09 18:39:25 +11002227# endif
Damien Miller6af914a2010-09-10 11:39:26 +10002228#endif
Damien Millereb8b60e2010-08-31 22:41:14 +10002229
2230 debug("%s: unsupported EC curve name \"%.100s\"", __func__, name);
2231 return -1;
2232}
2233
Damien Miller041ab7c2010-09-10 11:23:34 +10002234u_int
2235key_curve_nid_to_bits(int nid)
2236{
2237 switch (nid) {
Damien Miller6af914a2010-09-10 11:39:26 +10002238#ifdef OPENSSL_HAS_ECC
Damien Miller041ab7c2010-09-10 11:23:34 +10002239 case NID_X9_62_prime256v1:
2240 return 256;
2241 case NID_secp384r1:
2242 return 384;
Darren Tucker2c894302013-11-10 12:38:42 +11002243# ifdef OPENSSL_HAS_NISTP521
Damien Miller041ab7c2010-09-10 11:23:34 +10002244 case NID_secp521r1:
2245 return 521;
Darren Tucker37bcef52013-11-09 18:39:25 +11002246# endif
Damien Miller6af914a2010-09-10 11:39:26 +10002247#endif
Damien Miller041ab7c2010-09-10 11:23:34 +10002248 default:
2249 error("%s: unsupported EC curve nid %d", __func__, nid);
2250 return 0;
2251 }
2252}
2253
Damien Millereb8b60e2010-08-31 22:41:14 +10002254const char *
2255key_curve_nid_to_name(int nid)
2256{
Damien Miller6af914a2010-09-10 11:39:26 +10002257#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10002258 if (nid == NID_X9_62_prime256v1)
2259 return "nistp256";
2260 else if (nid == NID_secp384r1)
2261 return "nistp384";
Darren Tucker37bcef52013-11-09 18:39:25 +11002262# ifdef OPENSSL_HAS_NISTP521
Damien Millereb8b60e2010-08-31 22:41:14 +10002263 else if (nid == NID_secp521r1)
2264 return "nistp521";
Darren Tucker37bcef52013-11-09 18:39:25 +11002265# endif
Damien Miller6af914a2010-09-10 11:39:26 +10002266#endif
Damien Millereb8b60e2010-08-31 22:41:14 +10002267 error("%s: unsupported EC curve nid %d", __func__, nid);
2268 return NULL;
2269}
2270
Damien Miller6af914a2010-09-10 11:39:26 +10002271#ifdef OPENSSL_HAS_ECC
Damien Millerb3051d02014-01-10 10:58:53 +11002272int
2273key_ec_nid_to_hash_alg(int nid)
Damien Miller041ab7c2010-09-10 11:23:34 +10002274{
2275 int kbits = key_curve_nid_to_bits(nid);
2276
2277 if (kbits == 0)
2278 fatal("%s: invalid nid %d", __func__, nid);
2279 /* RFC5656 section 6.2.1 */
2280 if (kbits <= 256)
Damien Millerb3051d02014-01-10 10:58:53 +11002281 return SSH_DIGEST_SHA256;
Damien Miller041ab7c2010-09-10 11:23:34 +10002282 else if (kbits <= 384)
Damien Millerb3051d02014-01-10 10:58:53 +11002283 return SSH_DIGEST_SHA384;
Damien Miller041ab7c2010-09-10 11:23:34 +10002284 else
Damien Millerb3051d02014-01-10 10:58:53 +11002285 return SSH_DIGEST_SHA512;
Damien Miller041ab7c2010-09-10 11:23:34 +10002286}
2287
Damien Millereb8b60e2010-08-31 22:41:14 +10002288int
2289key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
2290{
2291 BN_CTX *bnctx;
2292 EC_POINT *nq = NULL;
2293 BIGNUM *order, *x, *y, *tmp;
2294 int ret = -1;
2295
2296 if ((bnctx = BN_CTX_new()) == NULL)
2297 fatal("%s: BN_CTX_new failed", __func__);
2298 BN_CTX_start(bnctx);
2299
2300 /*
2301 * We shouldn't ever hit this case because bignum_get_ecpoint()
2302 * refuses to load GF2m points.
2303 */
2304 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
2305 NID_X9_62_prime_field) {
2306 error("%s: group is not a prime field", __func__);
2307 goto out;
2308 }
2309
2310 /* Q != infinity */
2311 if (EC_POINT_is_at_infinity(group, public)) {
2312 error("%s: received degenerate public key (infinity)",
2313 __func__);
2314 goto out;
2315 }
2316
2317 if ((x = BN_CTX_get(bnctx)) == NULL ||
2318 (y = BN_CTX_get(bnctx)) == NULL ||
2319 (order = BN_CTX_get(bnctx)) == NULL ||
2320 (tmp = BN_CTX_get(bnctx)) == NULL)
2321 fatal("%s: BN_CTX_get failed", __func__);
2322
2323 /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
2324 if (EC_GROUP_get_order(group, order, bnctx) != 1)
2325 fatal("%s: EC_GROUP_get_order failed", __func__);
2326 if (EC_POINT_get_affine_coordinates_GFp(group, public,
2327 x, y, bnctx) != 1)
2328 fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__);
2329 if (BN_num_bits(x) <= BN_num_bits(order) / 2) {
2330 error("%s: public key x coordinate too small: "
2331 "bits(x) = %d, bits(order)/2 = %d", __func__,
2332 BN_num_bits(x), BN_num_bits(order) / 2);
2333 goto out;
2334 }
2335 if (BN_num_bits(y) <= BN_num_bits(order) / 2) {
2336 error("%s: public key y coordinate too small: "
2337 "bits(y) = %d, bits(order)/2 = %d", __func__,
2338 BN_num_bits(x), BN_num_bits(order) / 2);
2339 goto out;
2340 }
2341
2342 /* nQ == infinity (n == order of subgroup) */
2343 if ((nq = EC_POINT_new(group)) == NULL)
2344 fatal("%s: BN_CTX_tmp failed", __func__);
2345 if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1)
2346 fatal("%s: EC_GROUP_mul failed", __func__);
2347 if (EC_POINT_is_at_infinity(group, nq) != 1) {
2348 error("%s: received degenerate public key (nQ != infinity)",
2349 __func__);
2350 goto out;
2351 }
2352
2353 /* x < order - 1, y < order - 1 */
2354 if (!BN_sub(tmp, order, BN_value_one()))
2355 fatal("%s: BN_sub failed", __func__);
2356 if (BN_cmp(x, tmp) >= 0) {
2357 error("%s: public key x coordinate >= group order - 1",
2358 __func__);
2359 goto out;
2360 }
2361 if (BN_cmp(y, tmp) >= 0) {
2362 error("%s: public key y coordinate >= group order - 1",
2363 __func__);
2364 goto out;
2365 }
2366 ret = 0;
2367 out:
2368 BN_CTX_free(bnctx);
2369 EC_POINT_free(nq);
2370 return ret;
2371}
2372
2373int
2374key_ec_validate_private(const EC_KEY *key)
2375{
2376 BN_CTX *bnctx;
2377 BIGNUM *order, *tmp;
2378 int ret = -1;
2379
2380 if ((bnctx = BN_CTX_new()) == NULL)
2381 fatal("%s: BN_CTX_new failed", __func__);
2382 BN_CTX_start(bnctx);
2383
2384 if ((order = BN_CTX_get(bnctx)) == NULL ||
2385 (tmp = BN_CTX_get(bnctx)) == NULL)
2386 fatal("%s: BN_CTX_get failed", __func__);
2387
2388 /* log2(private) > log2(order)/2 */
2389 if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1)
2390 fatal("%s: EC_GROUP_get_order failed", __func__);
2391 if (BN_num_bits(EC_KEY_get0_private_key(key)) <=
2392 BN_num_bits(order) / 2) {
2393 error("%s: private key too small: "
2394 "bits(y) = %d, bits(order)/2 = %d", __func__,
2395 BN_num_bits(EC_KEY_get0_private_key(key)),
2396 BN_num_bits(order) / 2);
2397 goto out;
2398 }
2399
2400 /* private < order - 1 */
2401 if (!BN_sub(tmp, order, BN_value_one()))
2402 fatal("%s: BN_sub failed", __func__);
2403 if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0) {
2404 error("%s: private key >= group order - 1", __func__);
2405 goto out;
2406 }
2407 ret = 0;
2408 out:
2409 BN_CTX_free(bnctx);
2410 return ret;
2411}
Damien Miller1f0311c2014-05-15 14:24:09 +10002412#endif
Damien Millereb8b60e2010-08-31 22:41:14 +10002413
2414#if defined(DEBUG_KEXECDH) || defined(DEBUG_PK)
2415void
2416key_dump_ec_point(const EC_GROUP *group, const EC_POINT *point)
2417{
2418 BIGNUM *x, *y;
2419 BN_CTX *bnctx;
2420
2421 if (point == NULL) {
2422 fputs("point=(NULL)\n", stderr);
2423 return;
2424 }
2425 if ((bnctx = BN_CTX_new()) == NULL)
2426 fatal("%s: BN_CTX_new failed", __func__);
2427 BN_CTX_start(bnctx);
2428 if ((x = BN_CTX_get(bnctx)) == NULL || (y = BN_CTX_get(bnctx)) == NULL)
2429 fatal("%s: BN_CTX_get failed", __func__);
2430 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
2431 NID_X9_62_prime_field)
2432 fatal("%s: group is not a prime field", __func__);
2433 if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, bnctx) != 1)
2434 fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__);
2435 fputs("x=", stderr);
2436 BN_print_fp(stderr, x);
2437 fputs("\ny=", stderr);
2438 BN_print_fp(stderr, y);
2439 fputs("\n", stderr);
2440 BN_CTX_free(bnctx);
2441}
2442
2443void
2444key_dump_ec_key(const EC_KEY *key)
2445{
2446 const BIGNUM *exponent;
2447
2448 key_dump_ec_point(EC_KEY_get0_group(key), EC_KEY_get0_public_key(key));
2449 fputs("exponent=", stderr);
2450 if ((exponent = EC_KEY_get0_private_key(key)) == NULL)
2451 fputs("(NULL)", stderr);
2452 else
2453 BN_print_fp(stderr, EC_KEY_get0_private_key(key));
2454 fputs("\n", stderr);
2455}
2456#endif /* defined(DEBUG_KEXECDH) || defined(DEBUG_PK) */
Damien Miller6af914a2010-09-10 11:39:26 +10002457#endif /* OPENSSL_HAS_ECC */
Damien Millerf0e90602013-12-07 10:40:26 +11002458
2459void
2460key_private_serialize(const Key *key, Buffer *b)
2461{
2462 buffer_put_cstring(b, key_ssh_name(key));
2463 switch (key->type) {
Damien Miller1f0311c2014-05-15 14:24:09 +10002464#ifdef WITH_OPENSSL
Damien Millerf0e90602013-12-07 10:40:26 +11002465 case KEY_RSA:
2466 buffer_put_bignum2(b, key->rsa->n);
2467 buffer_put_bignum2(b, key->rsa->e);
2468 buffer_put_bignum2(b, key->rsa->d);
2469 buffer_put_bignum2(b, key->rsa->iqmp);
2470 buffer_put_bignum2(b, key->rsa->p);
2471 buffer_put_bignum2(b, key->rsa->q);
2472 break;
2473 case KEY_RSA_CERT_V00:
2474 case KEY_RSA_CERT:
2475 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
2476 fatal("%s: no cert/certblob", __func__);
2477 buffer_put_string(b, buffer_ptr(&key->cert->certblob),
2478 buffer_len(&key->cert->certblob));
2479 buffer_put_bignum2(b, key->rsa->d);
2480 buffer_put_bignum2(b, key->rsa->iqmp);
2481 buffer_put_bignum2(b, key->rsa->p);
2482 buffer_put_bignum2(b, key->rsa->q);
2483 break;
2484 case KEY_DSA:
2485 buffer_put_bignum2(b, key->dsa->p);
2486 buffer_put_bignum2(b, key->dsa->q);
2487 buffer_put_bignum2(b, key->dsa->g);
2488 buffer_put_bignum2(b, key->dsa->pub_key);
2489 buffer_put_bignum2(b, key->dsa->priv_key);
2490 break;
2491 case KEY_DSA_CERT_V00:
2492 case KEY_DSA_CERT:
2493 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
2494 fatal("%s: no cert/certblob", __func__);
2495 buffer_put_string(b, buffer_ptr(&key->cert->certblob),
2496 buffer_len(&key->cert->certblob));
2497 buffer_put_bignum2(b, key->dsa->priv_key);
2498 break;
2499#ifdef OPENSSL_HAS_ECC
2500 case KEY_ECDSA:
2501 buffer_put_cstring(b, key_curve_nid_to_name(key->ecdsa_nid));
2502 buffer_put_ecpoint(b, EC_KEY_get0_group(key->ecdsa),
2503 EC_KEY_get0_public_key(key->ecdsa));
2504 buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa));
2505 break;
2506 case KEY_ECDSA_CERT:
2507 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
2508 fatal("%s: no cert/certblob", __func__);
2509 buffer_put_string(b, buffer_ptr(&key->cert->certblob),
2510 buffer_len(&key->cert->certblob));
2511 buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa));
2512 break;
2513#endif /* OPENSSL_HAS_ECC */
Damien Miller5be9d9e2013-12-07 11:24:01 +11002514 case KEY_ED25519:
2515 buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ);
2516 buffer_put_string(b, key->ed25519_sk, ED25519_SK_SZ);
2517 break;
Damien Miller1f0311c2014-05-15 14:24:09 +10002518#endif
2519#endif
Damien Miller5be9d9e2013-12-07 11:24:01 +11002520 case KEY_ED25519_CERT:
2521 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
2522 fatal("%s: no cert/certblob", __func__);
2523 buffer_put_string(b, buffer_ptr(&key->cert->certblob),
2524 buffer_len(&key->cert->certblob));
2525 buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ);
2526 buffer_put_string(b, key->ed25519_sk, ED25519_SK_SZ);
2527 break;
Damien Millerf0e90602013-12-07 10:40:26 +11002528 }
2529}
2530
2531Key *
2532key_private_deserialize(Buffer *blob)
2533{
2534 char *type_name;
2535 Key *k = NULL;
2536 u_char *cert;
Damien Miller5be9d9e2013-12-07 11:24:01 +11002537 u_int len, pklen, sklen;
Damien Millerf0e90602013-12-07 10:40:26 +11002538 int type;
Damien Miller1f0311c2014-05-15 14:24:09 +10002539#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
Damien Millerf0e90602013-12-07 10:40:26 +11002540 char *curve;
2541 BIGNUM *exponent;
2542 EC_POINT *q;
2543#endif
2544
2545 type_name = buffer_get_string(blob, NULL);
2546 type = key_type_from_name(type_name);
2547 switch (type) {
Damien Miller1f0311c2014-05-15 14:24:09 +10002548#ifdef WITH_OPENSSL
Damien Millerf0e90602013-12-07 10:40:26 +11002549 case KEY_DSA:
2550 k = key_new_private(type);
2551 buffer_get_bignum2(blob, k->dsa->p);
2552 buffer_get_bignum2(blob, k->dsa->q);
2553 buffer_get_bignum2(blob, k->dsa->g);
2554 buffer_get_bignum2(blob, k->dsa->pub_key);
2555 buffer_get_bignum2(blob, k->dsa->priv_key);
2556 break;
2557 case KEY_DSA_CERT_V00:
2558 case KEY_DSA_CERT:
2559 cert = buffer_get_string(blob, &len);
2560 if ((k = key_from_blob(cert, len)) == NULL)
2561 fatal("Certificate parse failed");
2562 free(cert);
2563 key_add_private(k);
2564 buffer_get_bignum2(blob, k->dsa->priv_key);
2565 break;
2566#ifdef OPENSSL_HAS_ECC
2567 case KEY_ECDSA:
2568 k = key_new_private(type);
2569 k->ecdsa_nid = key_ecdsa_nid_from_name(type_name);
2570 curve = buffer_get_string(blob, NULL);
2571 if (k->ecdsa_nid != key_curve_name_to_nid(curve))
2572 fatal("%s: curve names mismatch", __func__);
2573 free(curve);
2574 k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
2575 if (k->ecdsa == NULL)
2576 fatal("%s: EC_KEY_new_by_curve_name failed",
2577 __func__);
2578 q = EC_POINT_new(EC_KEY_get0_group(k->ecdsa));
2579 if (q == NULL)
2580 fatal("%s: BN_new failed", __func__);
2581 if ((exponent = BN_new()) == NULL)
2582 fatal("%s: BN_new failed", __func__);
2583 buffer_get_ecpoint(blob,
2584 EC_KEY_get0_group(k->ecdsa), q);
2585 buffer_get_bignum2(blob, exponent);
2586 if (EC_KEY_set_public_key(k->ecdsa, q) != 1)
2587 fatal("%s: EC_KEY_set_public_key failed",
2588 __func__);
2589 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1)
2590 fatal("%s: EC_KEY_set_private_key failed",
2591 __func__);
2592 if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
2593 EC_KEY_get0_public_key(k->ecdsa)) != 0)
2594 fatal("%s: bad ECDSA public key", __func__);
2595 if (key_ec_validate_private(k->ecdsa) != 0)
2596 fatal("%s: bad ECDSA private key", __func__);
2597 BN_clear_free(exponent);
2598 EC_POINT_free(q);
2599 break;
2600 case KEY_ECDSA_CERT:
2601 cert = buffer_get_string(blob, &len);
2602 if ((k = key_from_blob(cert, len)) == NULL)
2603 fatal("Certificate parse failed");
2604 free(cert);
2605 key_add_private(k);
2606 if ((exponent = BN_new()) == NULL)
2607 fatal("%s: BN_new failed", __func__);
2608 buffer_get_bignum2(blob, exponent);
2609 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1)
2610 fatal("%s: EC_KEY_set_private_key failed",
2611 __func__);
2612 if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
2613 EC_KEY_get0_public_key(k->ecdsa)) != 0 ||
2614 key_ec_validate_private(k->ecdsa) != 0)
2615 fatal("%s: bad ECDSA key", __func__);
2616 BN_clear_free(exponent);
2617 break;
2618#endif
2619 case KEY_RSA:
2620 k = key_new_private(type);
2621 buffer_get_bignum2(blob, k->rsa->n);
2622 buffer_get_bignum2(blob, k->rsa->e);
2623 buffer_get_bignum2(blob, k->rsa->d);
2624 buffer_get_bignum2(blob, k->rsa->iqmp);
2625 buffer_get_bignum2(blob, k->rsa->p);
2626 buffer_get_bignum2(blob, k->rsa->q);
2627
2628 /* Generate additional parameters */
2629 rsa_generate_additional_parameters(k->rsa);
2630 break;
2631 case KEY_RSA_CERT_V00:
2632 case KEY_RSA_CERT:
2633 cert = buffer_get_string(blob, &len);
2634 if ((k = key_from_blob(cert, len)) == NULL)
2635 fatal("Certificate parse failed");
2636 free(cert);
2637 key_add_private(k);
2638 buffer_get_bignum2(blob, k->rsa->d);
2639 buffer_get_bignum2(blob, k->rsa->iqmp);
2640 buffer_get_bignum2(blob, k->rsa->p);
2641 buffer_get_bignum2(blob, k->rsa->q);
2642 break;
Damien Miller1f0311c2014-05-15 14:24:09 +10002643#endif
2644#endif
Damien Miller5be9d9e2013-12-07 11:24:01 +11002645 case KEY_ED25519:
2646 k = key_new_private(type);
2647 k->ed25519_pk = buffer_get_string(blob, &pklen);
2648 k->ed25519_sk = buffer_get_string(blob, &sklen);
2649 if (pklen != ED25519_PK_SZ)
2650 fatal("%s: ed25519 pklen %d != %d",
2651 __func__, pklen, ED25519_PK_SZ);
2652 if (sklen != ED25519_SK_SZ)
2653 fatal("%s: ed25519 sklen %d != %d",
2654 __func__, sklen, ED25519_SK_SZ);
2655 break;
2656 case KEY_ED25519_CERT:
2657 cert = buffer_get_string(blob, &len);
2658 if ((k = key_from_blob(cert, len)) == NULL)
2659 fatal("Certificate parse failed");
2660 free(cert);
2661 key_add_private(k);
2662 k->ed25519_pk = buffer_get_string(blob, &pklen);
2663 k->ed25519_sk = buffer_get_string(blob, &sklen);
2664 if (pklen != ED25519_PK_SZ)
2665 fatal("%s: ed25519 pklen %d != %d",
2666 __func__, pklen, ED25519_PK_SZ);
2667 if (sklen != ED25519_SK_SZ)
2668 fatal("%s: ed25519 sklen %d != %d",
2669 __func__, sklen, ED25519_SK_SZ);
2670 break;
Damien Millerf0e90602013-12-07 10:40:26 +11002671 default:
2672 free(type_name);
2673 buffer_clear(blob);
2674 return NULL;
2675 }
2676 free(type_name);
2677
2678 /* enable blinding */
2679 switch (k->type) {
Damien Miller1f0311c2014-05-15 14:24:09 +10002680#ifdef WITH_OPENSSL
Damien Millerf0e90602013-12-07 10:40:26 +11002681 case KEY_RSA:
2682 case KEY_RSA_CERT_V00:
2683 case KEY_RSA_CERT:
2684 case KEY_RSA1:
2685 if (RSA_blinding_on(k->rsa, NULL) != 1) {
2686 error("%s: RSA_blinding_on failed", __func__);
2687 key_free(k);
2688 return NULL;
2689 }
2690 break;
Damien Miller1f0311c2014-05-15 14:24:09 +10002691#endif
Damien Millerf0e90602013-12-07 10:40:26 +11002692 }
2693 return k;
2694}