blob: b8c60cb2cfcbb59a43e5e48d640ed7def393711d [file] [log] [blame]
Darren Tuckercaf00102013-05-16 20:26:18 +10001/* $OpenBSD: key.c,v 1.102 2013/05/10 04:08:01 djm Exp $ */
Damien Miller450a7a12000-03-26 13:04:51 +10002/*
Damien Millere4340be2000-09-16 13:29:08 +11003 * read_bignum():
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 *
6 * As far as I am concerned, the code I have written for this software
7 * can be used freely for any purpose. Any derived versions of this
8 * software must be clearly marked as such, and if the derived work is
9 * incompatible with the protocol description in the RFC file, it must be
10 * called by a name other than "ssh" or "Secure Shell".
11 *
12 *
Ben Lindstrom44697232001-07-04 03:32:30 +000013 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
Darren Tucker0f0ef0a2008-06-13 08:58:05 +100014 * Copyright (c) 2008 Alexander von Gernler. All rights reserved.
Damien Miller450a7a12000-03-26 13:04:51 +100015 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
Damien Miller450a7a12000-03-26 13:04:51 +100024 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
Damien Millerd7834352006-08-05 12:39:39 +100036
Damien Miller450a7a12000-03-26 13:04:51 +100037#include "includes.h"
Ben Lindstrom226cfa02001-01-22 05:34:40 +000038
Darren Tucker9c16ac92008-06-13 04:40:35 +100039#include <sys/param.h>
Damien Millerd7834352006-08-05 12:39:39 +100040#include <sys/types.h>
41
Damien Miller450a7a12000-03-26 13:04:51 +100042#include <openssl/evp.h>
Darren Tucker3d295a62008-02-28 19:22:04 +110043#include <openbsd-compat/openssl-compat.h>
Ben Lindstrom226cfa02001-01-22 05:34:40 +000044
Damien Millerded319c2006-09-01 15:38:36 +100045#include <stdarg.h>
Damien Millera7a73ee2006-08-05 11:37:59 +100046#include <stdio.h>
Damien Millere3476ed2006-07-24 14:13:33 +100047#include <string.h>
48
Damien Miller450a7a12000-03-26 13:04:51 +100049#include "xmalloc.h"
50#include "key.h"
Damien Miller0bc1bd82000-11-13 22:57:25 +110051#include "rsa.h"
Damien Millereba71ba2000-04-29 23:57:08 +100052#include "uuencode.h"
Damien Miller0bc1bd82000-11-13 22:57:25 +110053#include "buffer.h"
Ben Lindstrom226cfa02001-01-22 05:34:40 +000054#include "log.h"
Damien Miller8a0268f2010-07-16 13:57:51 +100055#include "misc.h"
Damien Miller0a80ca12010-02-27 07:55:05 +110056#include "ssh2.h"
57
Damien Millerf3747bf2013-01-18 11:44:04 +110058static int to_blob(const Key *, u_char **, u_int *, int);
59
Damien Miller0a80ca12010-02-27 07:55:05 +110060static struct KeyCert *
61cert_new(void)
62{
63 struct KeyCert *cert;
64
65 cert = xcalloc(1, sizeof(*cert));
66 buffer_init(&cert->certblob);
Damien Miller4e270b02010-04-16 15:56:21 +100067 buffer_init(&cert->critical);
68 buffer_init(&cert->extensions);
Damien Miller0a80ca12010-02-27 07:55:05 +110069 cert->key_id = NULL;
70 cert->principals = NULL;
71 cert->signature_key = NULL;
72 return cert;
73}
Damien Miller450a7a12000-03-26 13:04:51 +100074
75Key *
76key_new(int type)
77{
78 Key *k;
79 RSA *rsa;
80 DSA *dsa;
Damien Miller07d86be2006-03-26 14:19:21 +110081 k = xcalloc(1, sizeof(*k));
Damien Miller450a7a12000-03-26 13:04:51 +100082 k->type = type;
Damien Millereb8b60e2010-08-31 22:41:14 +100083 k->ecdsa = NULL;
84 k->ecdsa_nid = -1;
Damien Millereba71ba2000-04-29 23:57:08 +100085 k->dsa = NULL;
86 k->rsa = NULL;
Damien Miller0a80ca12010-02-27 07:55:05 +110087 k->cert = NULL;
Damien Miller450a7a12000-03-26 13:04:51 +100088 switch (k->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +110089 case KEY_RSA1:
Damien Miller450a7a12000-03-26 13:04:51 +100090 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +100091 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +110092 case KEY_RSA_CERT:
Damien Millerda755162002-01-22 23:09:22 +110093 if ((rsa = RSA_new()) == NULL)
94 fatal("key_new: RSA_new failed");
95 if ((rsa->n = BN_new()) == NULL)
96 fatal("key_new: BN_new failed");
97 if ((rsa->e = BN_new()) == NULL)
98 fatal("key_new: BN_new failed");
Damien Miller450a7a12000-03-26 13:04:51 +100099 k->rsa = rsa;
100 break;
101 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000102 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100103 case KEY_DSA_CERT:
Damien Millerda755162002-01-22 23:09:22 +1100104 if ((dsa = DSA_new()) == NULL)
105 fatal("key_new: DSA_new failed");
106 if ((dsa->p = BN_new()) == NULL)
107 fatal("key_new: BN_new failed");
108 if ((dsa->q = BN_new()) == NULL)
109 fatal("key_new: BN_new failed");
110 if ((dsa->g = BN_new()) == NULL)
111 fatal("key_new: BN_new failed");
112 if ((dsa->pub_key = BN_new()) == NULL)
113 fatal("key_new: BN_new failed");
Damien Miller450a7a12000-03-26 13:04:51 +1000114 k->dsa = dsa;
115 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000116#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000117 case KEY_ECDSA:
118 case KEY_ECDSA_CERT:
119 /* Cannot do anything until we know the group */
120 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000121#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +1100122 case KEY_UNSPEC:
Damien Miller450a7a12000-03-26 13:04:51 +1000123 break;
124 default:
125 fatal("key_new: bad key type %d", k->type);
126 break;
127 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100128
129 if (key_is_cert(k))
130 k->cert = cert_new();
131
Damien Miller450a7a12000-03-26 13:04:51 +1000132 return k;
133}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000134
Damien Miller0a80ca12010-02-27 07:55:05 +1100135void
136key_add_private(Key *k)
Damien Miller0bc1bd82000-11-13 22:57:25 +1100137{
Damien Miller0bc1bd82000-11-13 22:57:25 +1100138 switch (k->type) {
139 case KEY_RSA1:
140 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000141 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100142 case KEY_RSA_CERT:
Damien Millerda755162002-01-22 23:09:22 +1100143 if ((k->rsa->d = BN_new()) == NULL)
144 fatal("key_new_private: BN_new failed");
145 if ((k->rsa->iqmp = BN_new()) == NULL)
146 fatal("key_new_private: BN_new failed");
147 if ((k->rsa->q = BN_new()) == NULL)
148 fatal("key_new_private: BN_new failed");
149 if ((k->rsa->p = BN_new()) == NULL)
150 fatal("key_new_private: BN_new failed");
151 if ((k->rsa->dmq1 = BN_new()) == NULL)
152 fatal("key_new_private: BN_new failed");
153 if ((k->rsa->dmp1 = BN_new()) == NULL)
154 fatal("key_new_private: BN_new failed");
Damien Miller0bc1bd82000-11-13 22:57:25 +1100155 break;
156 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000157 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100158 case KEY_DSA_CERT:
Damien Millerda755162002-01-22 23:09:22 +1100159 if ((k->dsa->priv_key = BN_new()) == NULL)
160 fatal("key_new_private: BN_new failed");
Damien Miller0bc1bd82000-11-13 22:57:25 +1100161 break;
Damien Millereb8b60e2010-08-31 22:41:14 +1000162 case KEY_ECDSA:
163 case KEY_ECDSA_CERT:
164 /* Cannot do anything until we know the group */
165 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100166 case KEY_UNSPEC:
167 break;
168 default:
169 break;
170 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100171}
172
173Key *
174key_new_private(int type)
175{
176 Key *k = key_new(type);
177
178 key_add_private(k);
Damien Miller0bc1bd82000-11-13 22:57:25 +1100179 return k;
180}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000181
Damien Miller0a80ca12010-02-27 07:55:05 +1100182static void
183cert_free(struct KeyCert *cert)
184{
185 u_int i;
186
187 buffer_free(&cert->certblob);
Damien Miller4e270b02010-04-16 15:56:21 +1000188 buffer_free(&cert->critical);
189 buffer_free(&cert->extensions);
Damien Miller0a80ca12010-02-27 07:55:05 +1100190 if (cert->key_id != NULL)
191 xfree(cert->key_id);
192 for (i = 0; i < cert->nprincipals; i++)
193 xfree(cert->principals[i]);
194 if (cert->principals != NULL)
195 xfree(cert->principals);
196 if (cert->signature_key != NULL)
197 key_free(cert->signature_key);
Darren Tuckercaf00102013-05-16 20:26:18 +1000198 xfree(cert);
Damien Miller0a80ca12010-02-27 07:55:05 +1100199}
200
Damien Miller450a7a12000-03-26 13:04:51 +1000201void
202key_free(Key *k)
203{
Damien Miller429fcc22006-03-26 14:02:16 +1100204 if (k == NULL)
Damien Millerbbaad772006-03-26 14:03:03 +1100205 fatal("key_free: key is NULL");
Damien Miller450a7a12000-03-26 13:04:51 +1000206 switch (k->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100207 case KEY_RSA1:
Damien Miller450a7a12000-03-26 13:04:51 +1000208 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000209 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100210 case KEY_RSA_CERT:
Damien Miller450a7a12000-03-26 13:04:51 +1000211 if (k->rsa != NULL)
212 RSA_free(k->rsa);
213 k->rsa = NULL;
214 break;
215 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000216 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100217 case KEY_DSA_CERT:
Damien Miller450a7a12000-03-26 13:04:51 +1000218 if (k->dsa != NULL)
219 DSA_free(k->dsa);
220 k->dsa = NULL;
221 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000222#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000223 case KEY_ECDSA:
224 case KEY_ECDSA_CERT:
225 if (k->ecdsa != NULL)
226 EC_KEY_free(k->ecdsa);
227 k->ecdsa = NULL;
228 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000229#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +1100230 case KEY_UNSPEC:
231 break;
Damien Miller450a7a12000-03-26 13:04:51 +1000232 default:
233 fatal("key_free: bad key type %d", k->type);
234 break;
235 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100236 if (key_is_cert(k)) {
237 if (k->cert != NULL)
238 cert_free(k->cert);
239 k->cert = NULL;
240 }
241
Damien Miller450a7a12000-03-26 13:04:51 +1000242 xfree(k);
243}
Damien Millerf58b58c2003-11-17 21:18:23 +1100244
Damien Miller0a80ca12010-02-27 07:55:05 +1100245static int
246cert_compare(struct KeyCert *a, struct KeyCert *b)
Damien Miller450a7a12000-03-26 13:04:51 +1000247{
Damien Miller0a80ca12010-02-27 07:55:05 +1100248 if (a == NULL && b == NULL)
249 return 1;
250 if (a == NULL || b == NULL)
Damien Miller450a7a12000-03-26 13:04:51 +1000251 return 0;
Damien Miller0a80ca12010-02-27 07:55:05 +1100252 if (buffer_len(&a->certblob) != buffer_len(&b->certblob))
253 return 0;
Damien Millerea1651c2010-07-16 13:58:37 +1000254 if (timingsafe_bcmp(buffer_ptr(&a->certblob), buffer_ptr(&b->certblob),
Damien Miller0a80ca12010-02-27 07:55:05 +1100255 buffer_len(&a->certblob)) != 0)
256 return 0;
257 return 1;
258}
259
260/*
261 * Compare public portions of key only, allowing comparisons between
262 * certificates and plain keys too.
263 */
264int
265key_equal_public(const Key *a, const Key *b)
266{
Darren Tucker8ccb7392010-09-10 12:28:24 +1000267#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000268 BN_CTX *bnctx;
Darren Tucker8ccb7392010-09-10 12:28:24 +1000269#endif
Damien Millereb8b60e2010-08-31 22:41:14 +1000270
Damien Miller0a80ca12010-02-27 07:55:05 +1100271 if (a == NULL || b == NULL ||
272 key_type_plain(a->type) != key_type_plain(b->type))
273 return 0;
274
Damien Miller450a7a12000-03-26 13:04:51 +1000275 switch (a->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100276 case KEY_RSA1:
Damien Miller4e270b02010-04-16 15:56:21 +1000277 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100278 case KEY_RSA_CERT:
Damien Miller450a7a12000-03-26 13:04:51 +1000279 case KEY_RSA:
280 return a->rsa != NULL && b->rsa != NULL &&
281 BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
282 BN_cmp(a->rsa->n, b->rsa->n) == 0;
Damien Miller4e270b02010-04-16 15:56:21 +1000283 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100284 case KEY_DSA_CERT:
Damien Miller450a7a12000-03-26 13:04:51 +1000285 case KEY_DSA:
286 return a->dsa != NULL && b->dsa != NULL &&
287 BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
288 BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
289 BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
290 BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
Damien Miller6af914a2010-09-10 11:39:26 +1000291#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000292 case KEY_ECDSA_CERT:
293 case KEY_ECDSA:
294 if (a->ecdsa == NULL || b->ecdsa == NULL ||
295 EC_KEY_get0_public_key(a->ecdsa) == NULL ||
296 EC_KEY_get0_public_key(b->ecdsa) == NULL)
297 return 0;
298 if ((bnctx = BN_CTX_new()) == NULL)
299 fatal("%s: BN_CTX_new failed", __func__);
300 if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa),
301 EC_KEY_get0_group(b->ecdsa), bnctx) != 0 ||
302 EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa),
303 EC_KEY_get0_public_key(a->ecdsa),
304 EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) {
305 BN_CTX_free(bnctx);
306 return 0;
307 }
308 BN_CTX_free(bnctx);
309 return 1;
Damien Miller6af914a2010-09-10 11:39:26 +1000310#endif /* OPENSSL_HAS_ECC */
Damien Miller450a7a12000-03-26 13:04:51 +1000311 default:
Damien Millereba71ba2000-04-29 23:57:08 +1000312 fatal("key_equal: bad key type %d", a->type);
Damien Miller450a7a12000-03-26 13:04:51 +1000313 }
Damien Miller87dd5f22008-07-11 17:35:09 +1000314 /* NOTREACHED */
Damien Miller450a7a12000-03-26 13:04:51 +1000315}
316
Damien Miller0a80ca12010-02-27 07:55:05 +1100317int
318key_equal(const Key *a, const Key *b)
319{
320 if (a == NULL || b == NULL || a->type != b->type)
321 return 0;
322 if (key_is_cert(a)) {
323 if (!cert_compare(a->cert, b->cert))
324 return 0;
325 }
326 return key_equal_public(a, b);
327}
328
Damien Miller37876e92003-05-15 10:19:46 +1000329u_char*
Damien Millerf3747bf2013-01-18 11:44:04 +1100330key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
331 u_int *dgst_raw_length)
Damien Miller450a7a12000-03-26 13:04:51 +1000332{
Ben Lindstrom80cb27d2002-03-05 01:33:36 +0000333 const EVP_MD *md = NULL;
Ben Lindstromf0b48532001-03-12 02:59:31 +0000334 EVP_MD_CTX ctx;
Ben Lindstrom46c16222000-12-22 01:43:59 +0000335 u_char *blob = NULL;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000336 u_char *retval = NULL;
Ben Lindstrom90fd8142002-02-26 18:09:42 +0000337 u_int len = 0;
Damien Millerf3747bf2013-01-18 11:44:04 +1100338 int nlen, elen;
Damien Miller450a7a12000-03-26 13:04:51 +1000339
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000340 *dgst_raw_length = 0;
341
Ben Lindstromf0b48532001-03-12 02:59:31 +0000342 switch (dgst_type) {
343 case SSH_FP_MD5:
344 md = EVP_md5();
345 break;
346 case SSH_FP_SHA1:
347 md = EVP_sha1();
348 break;
Darren Tucker14a9d252012-06-30 20:05:02 +1000349#ifdef HAVE_EVP_SHA256
Damien Miller3bde12a2012-06-20 21:51:11 +1000350 case SSH_FP_SHA256:
351 md = EVP_sha256();
352 break;
Darren Tucker14a9d252012-06-30 20:05:02 +1000353#endif
Ben Lindstromf0b48532001-03-12 02:59:31 +0000354 default:
355 fatal("key_fingerprint_raw: bad digest type %d",
356 dgst_type);
357 }
Damien Miller450a7a12000-03-26 13:04:51 +1000358 switch (k->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100359 case KEY_RSA1:
Damien Miller450a7a12000-03-26 13:04:51 +1000360 nlen = BN_num_bytes(k->rsa->n);
361 elen = BN_num_bytes(k->rsa->e);
362 len = nlen + elen;
Damien Millereba71ba2000-04-29 23:57:08 +1000363 blob = xmalloc(len);
364 BN_bn2bin(k->rsa->n, blob);
365 BN_bn2bin(k->rsa->e, blob + nlen);
Damien Miller450a7a12000-03-26 13:04:51 +1000366 break;
367 case KEY_DSA:
Damien Millereb8b60e2010-08-31 22:41:14 +1000368 case KEY_ECDSA:
Damien Miller0bc1bd82000-11-13 22:57:25 +1100369 case KEY_RSA:
370 key_to_blob(k, &blob, &len);
371 break;
Damien Miller4e270b02010-04-16 15:56:21 +1000372 case KEY_DSA_CERT_V00:
373 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100374 case KEY_DSA_CERT:
Damien Millereb8b60e2010-08-31 22:41:14 +1000375 case KEY_ECDSA_CERT:
Damien Miller0a80ca12010-02-27 07:55:05 +1100376 case KEY_RSA_CERT:
377 /* We want a fingerprint of the _key_ not of the cert */
Damien Millerf3747bf2013-01-18 11:44:04 +1100378 to_blob(k, &blob, &len, 1);
Damien Miller0a80ca12010-02-27 07:55:05 +1100379 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100380 case KEY_UNSPEC:
381 return retval;
Damien Miller450a7a12000-03-26 13:04:51 +1000382 default:
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000383 fatal("key_fingerprint_raw: bad key type %d", k->type);
Damien Miller450a7a12000-03-26 13:04:51 +1000384 break;
385 }
Damien Millereba71ba2000-04-29 23:57:08 +1000386 if (blob != NULL) {
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000387 retval = xmalloc(EVP_MAX_MD_SIZE);
Damien Miller6536c7d2000-06-22 21:32:31 +1000388 EVP_DigestInit(&ctx, md);
389 EVP_DigestUpdate(&ctx, blob, len);
Damien Miller3672e4b2002-02-05 11:54:07 +1100390 EVP_DigestFinal(&ctx, retval, dgst_raw_length);
Damien Millereba71ba2000-04-29 23:57:08 +1000391 memset(blob, 0, len);
392 xfree(blob);
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000393 } else {
394 fatal("key_fingerprint_raw: blob is null");
Damien Miller450a7a12000-03-26 13:04:51 +1000395 }
396 return retval;
397}
398
Ben Lindstroma962c2f2002-07-04 00:14:17 +0000399static char *
400key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len)
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000401{
402 char *retval;
Damien Millereccb9de2005-06-17 12:59:34 +1000403 u_int i;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000404
Damien Miller07d86be2006-03-26 14:19:21 +1100405 retval = xcalloc(1, dgst_raw_len * 3 + 1);
Damien Miller9f0f5c62001-12-21 14:45:46 +1100406 for (i = 0; i < dgst_raw_len; i++) {
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000407 char hex[4];
408 snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
Darren Tucker29588612003-07-14 17:28:34 +1000409 strlcat(retval, hex, dgst_raw_len * 3 + 1);
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000410 }
Darren Tucker29588612003-07-14 17:28:34 +1000411
412 /* Remove the trailing ':' character */
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000413 retval[(dgst_raw_len * 3) - 1] = '\0';
414 return retval;
415}
416
Ben Lindstroma962c2f2002-07-04 00:14:17 +0000417static char *
418key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len)
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000419{
420 char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
421 char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
422 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000423 u_int i, j = 0, rounds, seed = 1;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000424 char *retval;
425
426 rounds = (dgst_raw_len / 2) + 1;
Damien Miller07d86be2006-03-26 14:19:21 +1100427 retval = xcalloc((rounds * 6), sizeof(char));
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000428 retval[j++] = 'x';
429 for (i = 0; i < rounds; i++) {
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000430 u_int idx0, idx1, idx2, idx3, idx4;
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000431 if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
432 idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000433 seed) % 6;
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000434 idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
435 idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000436 (seed / 6)) % 6;
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000437 retval[j++] = vowels[idx0];
438 retval[j++] = consonants[idx1];
439 retval[j++] = vowels[idx2];
440 if ((i + 1) < rounds) {
441 idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
442 idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
443 retval[j++] = consonants[idx3];
444 retval[j++] = '-';
445 retval[j++] = consonants[idx4];
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000446 seed = ((seed * 5) +
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000447 ((((u_int)(dgst_raw[2 * i])) * 7) +
448 ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000449 }
450 } else {
451 idx0 = seed % 6;
452 idx1 = 16;
453 idx2 = seed / 6;
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000454 retval[j++] = vowels[idx0];
455 retval[j++] = consonants[idx1];
456 retval[j++] = vowels[idx2];
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000457 }
458 }
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000459 retval[j++] = 'x';
460 retval[j++] = '\0';
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000461 return retval;
462}
463
Darren Tucker9c16ac92008-06-13 04:40:35 +1000464/*
465 * Draw an ASCII-Art representing the fingerprint so human brain can
466 * profit from its built-in pattern recognition ability.
467 * This technique is called "random art" and can be found in some
468 * scientific publications like this original paper:
469 *
470 * "Hash Visualization: a New Technique to improve Real-World Security",
471 * Perrig A. and Song D., 1999, International Workshop on Cryptographic
472 * Techniques and E-Commerce (CrypTEC '99)
473 * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
474 *
475 * The subject came up in a talk by Dan Kaminsky, too.
476 *
477 * If you see the picture is different, the key is different.
478 * If the picture looks the same, you still know nothing.
479 *
480 * The algorithm used here is a worm crawling over a discrete plane,
481 * leaving a trace (augmenting the field) everywhere it goes.
482 * Movement is taken from dgst_raw 2bit-wise. Bumping into walls
483 * makes the respective movement vector be ignored for this turn.
484 * Graphs are not unambiguous, because circles in graphs can be
485 * walked in either direction.
486 */
Darren Tucker987ac842008-06-13 04:54:40 +1000487
488/*
489 * Field sizes for the random art. Have to be odd, so the starting point
490 * can be in the exact middle of the picture, and FLDBASE should be >=8 .
491 * Else pictures would be too dense, and drawing the frame would
492 * fail, too, because the key type would not fit in anymore.
493 */
494#define FLDBASE 8
495#define FLDSIZE_Y (FLDBASE + 1)
496#define FLDSIZE_X (FLDBASE * 2 + 1)
Darren Tucker9c16ac92008-06-13 04:40:35 +1000497static char *
Darren Tucker987ac842008-06-13 04:54:40 +1000498key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k)
Darren Tucker9c16ac92008-06-13 04:40:35 +1000499{
500 /*
501 * Chars to be used after each other every time the worm
502 * intersects with itself. Matter of taste.
503 */
Darren Tucker4b3b9772008-06-13 04:55:10 +1000504 char *augmentation_string = " .o+=*BOX@%&#/^SE";
Darren Tucker9c16ac92008-06-13 04:40:35 +1000505 char *retval, *p;
Darren Tucker014d76f2008-06-13 04:43:51 +1000506 u_char field[FLDSIZE_X][FLDSIZE_Y];
Darren Tucker9c16ac92008-06-13 04:40:35 +1000507 u_int i, b;
508 int x, y;
Darren Tuckerd32b28a2008-06-13 04:45:50 +1000509 size_t len = strlen(augmentation_string) - 1;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000510
511 retval = xcalloc(1, (FLDSIZE_X + 3) * (FLDSIZE_Y + 2));
512
513 /* initialize field */
Darren Tucker014d76f2008-06-13 04:43:51 +1000514 memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
Darren Tucker9c16ac92008-06-13 04:40:35 +1000515 x = FLDSIZE_X / 2;
516 y = FLDSIZE_Y / 2;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000517
518 /* process raw key */
519 for (i = 0; i < dgst_raw_len; i++) {
520 int input;
521 /* each byte conveys four 2-bit move commands */
522 input = dgst_raw[i];
523 for (b = 0; b < 4; b++) {
524 /* evaluate 2 bit, rest is shifted later */
525 x += (input & 0x1) ? 1 : -1;
526 y += (input & 0x2) ? 1 : -1;
527
528 /* assure we are still in bounds */
529 x = MAX(x, 0);
530 y = MAX(y, 0);
531 x = MIN(x, FLDSIZE_X - 1);
532 y = MIN(y, FLDSIZE_Y - 1);
533
534 /* augment the field */
Damien Millerc6aadd92008-11-03 19:16:20 +1100535 if (field[x][y] < len - 2)
536 field[x][y]++;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000537 input = input >> 2;
538 }
539 }
Darren Tucker4b3b9772008-06-13 04:55:10 +1000540
541 /* mark starting point and end point*/
542 field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
543 field[x][y] = len;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000544
545 /* fill in retval */
Damien Miller007132a2008-06-29 22:45:37 +1000546 snprintf(retval, FLDSIZE_X, "+--[%4s %4u]", key_type(k), key_size(k));
Darren Tucker987ac842008-06-13 04:54:40 +1000547 p = strchr(retval, '\0');
Darren Tucker9c16ac92008-06-13 04:40:35 +1000548
549 /* output upper border */
Damien Miller007132a2008-06-29 22:45:37 +1000550 for (i = p - retval - 1; i < FLDSIZE_X; i++)
Darren Tucker9c16ac92008-06-13 04:40:35 +1000551 *p++ = '-';
552 *p++ = '+';
553 *p++ = '\n';
554
555 /* output content */
556 for (y = 0; y < FLDSIZE_Y; y++) {
557 *p++ = '|';
558 for (x = 0; x < FLDSIZE_X; x++)
Darren Tuckerd32b28a2008-06-13 04:45:50 +1000559 *p++ = augmentation_string[MIN(field[x][y], len)];
Darren Tucker9c16ac92008-06-13 04:40:35 +1000560 *p++ = '|';
561 *p++ = '\n';
562 }
563
564 /* output lower border */
565 *p++ = '+';
566 for (i = 0; i < FLDSIZE_X; i++)
567 *p++ = '-';
568 *p++ = '+';
569
570 return retval;
571}
572
Ben Lindstroma962c2f2002-07-04 00:14:17 +0000573char *
Damien Miller0a80ca12010-02-27 07:55:05 +1100574key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000575{
Ben Lindstroma3700052001-04-05 23:26:32 +0000576 char *retval = NULL;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000577 u_char *dgst_raw;
Damien Miller3672e4b2002-02-05 11:54:07 +1100578 u_int dgst_raw_len;
Damien Miller9f0f5c62001-12-21 14:45:46 +1100579
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000580 dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len);
581 if (!dgst_raw)
Ben Lindstromcfccef92001-03-13 04:57:58 +0000582 fatal("key_fingerprint: null from key_fingerprint_raw()");
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +0000583 switch (dgst_rep) {
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000584 case SSH_FP_HEX:
585 retval = key_fingerprint_hex(dgst_raw, dgst_raw_len);
586 break;
587 case SSH_FP_BUBBLEBABBLE:
588 retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
589 break;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000590 case SSH_FP_RANDOMART:
Darren Tucker987ac842008-06-13 04:54:40 +1000591 retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k);
Darren Tucker9c16ac92008-06-13 04:40:35 +1000592 break;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000593 default:
Damien Miller2f54ada2008-11-03 19:24:16 +1100594 fatal("key_fingerprint: bad digest representation %d",
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000595 dgst_rep);
596 break;
597 }
598 memset(dgst_raw, 0, dgst_raw_len);
599 xfree(dgst_raw);
600 return retval;
601}
602
Damien Miller450a7a12000-03-26 13:04:51 +1000603/*
604 * Reads a multiple-precision integer in decimal from the buffer, and advances
605 * the pointer. The integer must already be initialized. This function is
606 * permitted to modify the buffer. This leaves *cpp to point just beyond the
607 * last processed (and maybe modified) character. Note that this may modify
608 * the buffer containing the number.
609 */
Ben Lindstrombba81212001-06-25 05:01:22 +0000610static int
Damien Miller450a7a12000-03-26 13:04:51 +1000611read_bignum(char **cpp, BIGNUM * value)
612{
613 char *cp = *cpp;
614 int old;
615
616 /* Skip any leading whitespace. */
617 for (; *cp == ' ' || *cp == '\t'; cp++)
618 ;
619
620 /* Check that it begins with a decimal digit. */
621 if (*cp < '0' || *cp > '9')
622 return 0;
623
624 /* Save starting position. */
625 *cpp = cp;
626
627 /* Move forward until all decimal digits skipped. */
628 for (; *cp >= '0' && *cp <= '9'; cp++)
629 ;
630
631 /* Save the old terminating character, and replace it by \0. */
632 old = *cp;
633 *cp = 0;
634
635 /* Parse the number. */
636 if (BN_dec2bn(&value, *cpp) == 0)
637 return 0;
638
639 /* Restore old terminating character. */
640 *cp = old;
641
642 /* Move beyond the number and return success. */
643 *cpp = cp;
644 return 1;
645}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000646
Ben Lindstrombba81212001-06-25 05:01:22 +0000647static int
Damien Miller450a7a12000-03-26 13:04:51 +1000648write_bignum(FILE *f, BIGNUM *num)
649{
650 char *buf = BN_bn2dec(num);
651 if (buf == NULL) {
652 error("write_bignum: BN_bn2dec() failed");
653 return 0;
654 }
655 fprintf(f, " %s", buf);
Damien Milleraf3030f2001-10-10 15:00:49 +1000656 OPENSSL_free(buf);
Damien Miller450a7a12000-03-26 13:04:51 +1000657 return 1;
658}
Damien Miller0bc1bd82000-11-13 22:57:25 +1100659
Ben Lindstrom309f3d12001-09-20 00:55:53 +0000660/* returns 1 ok, -1 error */
Damien Miller0bc1bd82000-11-13 22:57:25 +1100661int
Damien Millereba71ba2000-04-29 23:57:08 +1000662key_read(Key *ret, char **cpp)
Damien Miller450a7a12000-03-26 13:04:51 +1000663{
Damien Millereba71ba2000-04-29 23:57:08 +1000664 Key *k;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100665 int success = -1;
666 char *cp, *space;
Darren Tucker8ccb7392010-09-10 12:28:24 +1000667 int len, n, type;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100668 u_int bits;
Ben Lindstrom46c16222000-12-22 01:43:59 +0000669 u_char *blob;
Darren Tucker8ccb7392010-09-10 12:28:24 +1000670#ifdef OPENSSL_HAS_ECC
671 int curve_nid = -1;
672#endif
Damien Millereba71ba2000-04-29 23:57:08 +1000673
674 cp = *cpp;
675
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +0000676 switch (ret->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100677 case KEY_RSA1:
Damien Millereba71ba2000-04-29 23:57:08 +1000678 /* Get number of bits. */
679 if (*cp < '0' || *cp > '9')
Damien Miller0bc1bd82000-11-13 22:57:25 +1100680 return -1; /* Bad bit count... */
Damien Millereba71ba2000-04-29 23:57:08 +1000681 for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
682 bits = 10 * bits + *cp - '0';
Damien Miller450a7a12000-03-26 13:04:51 +1000683 if (bits == 0)
Damien Miller0bc1bd82000-11-13 22:57:25 +1100684 return -1;
Damien Millereba71ba2000-04-29 23:57:08 +1000685 *cpp = cp;
Damien Miller450a7a12000-03-26 13:04:51 +1000686 /* Get public exponent, public modulus. */
687 if (!read_bignum(cpp, ret->rsa->e))
Damien Miller0bc1bd82000-11-13 22:57:25 +1100688 return -1;
Damien Miller450a7a12000-03-26 13:04:51 +1000689 if (!read_bignum(cpp, ret->rsa->n))
Damien Miller0bc1bd82000-11-13 22:57:25 +1100690 return -1;
Darren Tucker561724f2010-01-13 22:43:05 +1100691 /* validate the claimed number of bits */
692 if ((u_int)BN_num_bits(ret->rsa->n) != bits) {
693 verbose("key_read: claimed key size %d does not match "
694 "actual %d", bits, BN_num_bits(ret->rsa->n));
695 return -1;
696 }
Damien Miller0bc1bd82000-11-13 22:57:25 +1100697 success = 1;
Damien Miller450a7a12000-03-26 13:04:51 +1000698 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100699 case KEY_UNSPEC:
700 case KEY_RSA:
Damien Miller450a7a12000-03-26 13:04:51 +1000701 case KEY_DSA:
Damien Millereb8b60e2010-08-31 22:41:14 +1000702 case KEY_ECDSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000703 case KEY_DSA_CERT_V00:
704 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100705 case KEY_DSA_CERT:
Damien Millereb8b60e2010-08-31 22:41:14 +1000706 case KEY_ECDSA_CERT:
Damien Miller0a80ca12010-02-27 07:55:05 +1100707 case KEY_RSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +1100708 space = strchr(cp, ' ');
709 if (space == NULL) {
Damien Miller386f1f32003-02-24 11:54:57 +1100710 debug3("key_read: missing whitespace");
Damien Miller0bc1bd82000-11-13 22:57:25 +1100711 return -1;
712 }
713 *space = '\0';
714 type = key_type_from_name(cp);
Damien Miller6af914a2010-09-10 11:39:26 +1000715#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000716 if (key_type_plain(type) == KEY_ECDSA &&
717 (curve_nid = key_ecdsa_nid_from_name(cp)) == -1) {
718 debug("key_read: invalid curve");
719 return -1;
720 }
Damien Miller6af914a2010-09-10 11:39:26 +1000721#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +1100722 *space = ' ';
723 if (type == KEY_UNSPEC) {
Damien Miller386f1f32003-02-24 11:54:57 +1100724 debug3("key_read: missing keytype");
Damien Miller0bc1bd82000-11-13 22:57:25 +1100725 return -1;
726 }
727 cp = space+1;
728 if (*cp == '\0') {
729 debug3("key_read: short string");
730 return -1;
731 }
732 if (ret->type == KEY_UNSPEC) {
733 ret->type = type;
734 } else if (ret->type != type) {
735 /* is a key, but different type */
736 debug3("key_read: type mismatch");
Ben Lindstrom309f3d12001-09-20 00:55:53 +0000737 return -1;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100738 }
Damien Millereba71ba2000-04-29 23:57:08 +1000739 len = 2*strlen(cp);
740 blob = xmalloc(len);
741 n = uudecode(cp, blob, len);
Damien Millere247cc42000-05-07 12:03:14 +1000742 if (n < 0) {
Damien Millerb1715dc2000-05-30 13:44:51 +1000743 error("key_read: uudecode %s failed", cp);
Ben Lindstrom4cbc1812001-12-06 16:41:41 +0000744 xfree(blob);
Damien Miller0bc1bd82000-11-13 22:57:25 +1100745 return -1;
Damien Millere247cc42000-05-07 12:03:14 +1000746 }
Darren Tucker502d3842003-06-28 12:38:01 +1000747 k = key_from_blob(blob, (u_int)n);
Ben Lindstrom4cbc1812001-12-06 16:41:41 +0000748 xfree(blob);
Damien Millerb1715dc2000-05-30 13:44:51 +1000749 if (k == NULL) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100750 error("key_read: key_from_blob %s failed", cp);
751 return -1;
Damien Millerb1715dc2000-05-30 13:44:51 +1000752 }
Damien Miller0bc1bd82000-11-13 22:57:25 +1100753 if (k->type != type) {
754 error("key_read: type mismatch: encoding error");
755 key_free(k);
756 return -1;
757 }
Damien Miller6af914a2010-09-10 11:39:26 +1000758#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000759 if (key_type_plain(type) == KEY_ECDSA &&
760 curve_nid != k->ecdsa_nid) {
761 error("key_read: type mismatch: EC curve mismatch");
762 key_free(k);
763 return -1;
764 }
Damien Miller6af914a2010-09-10 11:39:26 +1000765#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +1100766/*XXXX*/
Damien Miller0a80ca12010-02-27 07:55:05 +1100767 if (key_is_cert(ret)) {
768 if (!key_is_cert(k)) {
769 error("key_read: loaded key is not a cert");
770 key_free(k);
771 return -1;
772 }
773 if (ret->cert != NULL)
774 cert_free(ret->cert);
775 ret->cert = k->cert;
776 k->cert = NULL;
777 }
778 if (key_type_plain(ret->type) == KEY_RSA) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100779 if (ret->rsa != NULL)
780 RSA_free(ret->rsa);
781 ret->rsa = k->rsa;
782 k->rsa = NULL;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100783#ifdef DEBUG_PK
784 RSA_print_fp(stderr, ret->rsa, 8);
785#endif
Damien Miller0a80ca12010-02-27 07:55:05 +1100786 }
787 if (key_type_plain(ret->type) == KEY_DSA) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100788 if (ret->dsa != NULL)
789 DSA_free(ret->dsa);
790 ret->dsa = k->dsa;
791 k->dsa = NULL;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100792#ifdef DEBUG_PK
793 DSA_print_fp(stderr, ret->dsa, 8);
794#endif
795 }
Damien Miller6af914a2010-09-10 11:39:26 +1000796#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000797 if (key_type_plain(ret->type) == KEY_ECDSA) {
798 if (ret->ecdsa != NULL)
799 EC_KEY_free(ret->ecdsa);
800 ret->ecdsa = k->ecdsa;
801 ret->ecdsa_nid = k->ecdsa_nid;
802 k->ecdsa = NULL;
803 k->ecdsa_nid = -1;
804#ifdef DEBUG_PK
805 key_dump_ec_key(ret->ecdsa);
806#endif
807 }
Damien Miller6af914a2010-09-10 11:39:26 +1000808#endif
Damien Miller0a80ca12010-02-27 07:55:05 +1100809 success = 1;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100810/*XXXX*/
Ben Lindstrom4cbc1812001-12-06 16:41:41 +0000811 key_free(k);
Damien Miller0bc1bd82000-11-13 22:57:25 +1100812 if (success != 1)
813 break;
Damien Millerb1715dc2000-05-30 13:44:51 +1000814 /* advance cp: skip whitespace and data */
815 while (*cp == ' ' || *cp == '\t')
816 cp++;
817 while (*cp != '\0' && *cp != ' ' && *cp != '\t')
818 cp++;
819 *cpp = cp;
Damien Miller450a7a12000-03-26 13:04:51 +1000820 break;
821 default:
Damien Millereba71ba2000-04-29 23:57:08 +1000822 fatal("key_read: bad key type: %d", ret->type);
Damien Miller450a7a12000-03-26 13:04:51 +1000823 break;
824 }
Damien Miller0bc1bd82000-11-13 22:57:25 +1100825 return success;
Damien Miller450a7a12000-03-26 13:04:51 +1000826}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000827
Damien Miller450a7a12000-03-26 13:04:51 +1000828int
Damien Millerf58b58c2003-11-17 21:18:23 +1100829key_write(const Key *key, FILE *f)
Damien Miller450a7a12000-03-26 13:04:51 +1000830{
Ben Lindstrom90fd8142002-02-26 18:09:42 +0000831 int n, success = 0;
832 u_int len, bits = 0;
Damien Millera10f5612002-09-12 09:49:15 +1000833 u_char *blob;
834 char *uu;
Damien Miller450a7a12000-03-26 13:04:51 +1000835
Damien Miller0a80ca12010-02-27 07:55:05 +1100836 if (key_is_cert(key)) {
837 if (key->cert == NULL) {
838 error("%s: no cert data", __func__);
839 return 0;
840 }
841 if (buffer_len(&key->cert->certblob) == 0) {
842 error("%s: no signed certificate blob", __func__);
843 return 0;
844 }
845 }
846
847 switch (key->type) {
848 case KEY_RSA1:
849 if (key->rsa == NULL)
850 return 0;
Damien Miller450a7a12000-03-26 13:04:51 +1000851 /* size of modulus 'n' */
852 bits = BN_num_bits(key->rsa->n);
853 fprintf(f, "%u", bits);
854 if (write_bignum(f, key->rsa->e) &&
Damien Miller0a80ca12010-02-27 07:55:05 +1100855 write_bignum(f, key->rsa->n))
856 return 1;
857 error("key_write: failed for RSA key");
858 return 0;
859 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000860 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100861 case KEY_DSA_CERT:
862 if (key->dsa == NULL)
863 return 0;
864 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000865#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000866 case KEY_ECDSA:
867 case KEY_ECDSA_CERT:
868 if (key->ecdsa == NULL)
869 return 0;
870 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000871#endif
Damien Miller0a80ca12010-02-27 07:55:05 +1100872 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000873 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100874 case KEY_RSA_CERT:
875 if (key->rsa == NULL)
876 return 0;
877 break;
878 default:
879 return 0;
Damien Miller450a7a12000-03-26 13:04:51 +1000880 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100881
882 key_to_blob(key, &blob, &len);
883 uu = xmalloc(2*len);
884 n = uuencode(blob, len, uu, 2*len);
885 if (n > 0) {
886 fprintf(f, "%s %s", key_ssh_name(key), uu);
887 success = 1;
888 }
889 xfree(blob);
890 xfree(uu);
891
Damien Miller450a7a12000-03-26 13:04:51 +1000892 return success;
893}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000894
Damien Millerf58b58c2003-11-17 21:18:23 +1100895const char *
Damien Miller1cfbfaf2010-03-22 05:58:24 +1100896key_cert_type(const Key *k)
897{
898 switch (k->cert->type) {
899 case SSH2_CERT_TYPE_USER:
900 return "user";
901 case SSH2_CERT_TYPE_HOST:
902 return "host";
903 default:
904 return "unknown";
905 }
906}
907
Damien Millerea111192013-04-23 19:24:32 +1000908struct keytype {
909 char *name;
910 char *shortname;
911 int type;
912 int nid;
913 int cert;
914};
915static const struct keytype keytypes[] = {
916 { NULL, "RSA1", KEY_RSA1, 0, 0 },
917 { "ssh-rsa", "RSA", KEY_RSA, 0, 0 },
918 { "ssh-dss", "DSA", KEY_DSA, 0, 0 },
919#ifdef OPENSSL_HAS_ECC
920 { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 },
921 { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 },
922 { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 },
923#endif /* OPENSSL_HAS_ECC */
924 { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1 },
925 { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1 },
926#ifdef OPENSSL_HAS_ECC
927 { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT",
928 KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1 },
929 { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT",
930 KEY_ECDSA_CERT, NID_secp384r1, 1 },
931 { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT",
932 KEY_ECDSA_CERT, NID_secp521r1, 1 },
933#endif /* OPENSSL_HAS_ECC */
934 { "ssh-rsa-cert-v00@openssh.com", "RSA-CERT-V00",
935 KEY_RSA_CERT_V00, 0, 1 },
936 { "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00",
937 KEY_DSA_CERT_V00, 0, 1 },
938 { NULL, NULL, -1, -1, 0 }
939};
940
941const char *
942key_type(const Key *k)
943{
944 const struct keytype *kt;
945
946 for (kt = keytypes; kt->type != -1; kt++) {
947 if (kt->type == k->type)
948 return kt->shortname;
949 }
950 return "unknown";
951}
952
Damien Millereb8b60e2010-08-31 22:41:14 +1000953static const char *
954key_ssh_name_from_type_nid(int type, int nid)
Damien Miller0bc1bd82000-11-13 22:57:25 +1100955{
Damien Millerea111192013-04-23 19:24:32 +1000956 const struct keytype *kt;
957
958 for (kt = keytypes; kt->type != -1; kt++) {
959 if (kt->type == type && (kt->nid == 0 || kt->nid == nid))
960 return kt->name;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100961 }
962 return "ssh-unknown";
963}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000964
Damien Millereb8b60e2010-08-31 22:41:14 +1000965const char *
966key_ssh_name(const Key *k)
967{
968 return key_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
969}
970
971const char *
972key_ssh_name_plain(const Key *k)
973{
974 return key_ssh_name_from_type_nid(key_type_plain(k->type),
975 k->ecdsa_nid);
976}
977
Damien Millerea111192013-04-23 19:24:32 +1000978int
979key_type_from_name(char *name)
980{
981 const struct keytype *kt;
982
983 for (kt = keytypes; kt->type != -1; kt++) {
984 /* Only allow shortname matches for plain key types */
985 if ((kt->name != NULL && strcmp(name, kt->name) == 0) ||
986 (!kt->cert && strcasecmp(kt->shortname, name) == 0))
987 return kt->type;
988 }
989 debug2("key_type_from_name: unknown key type '%s'", name);
990 return KEY_UNSPEC;
991}
992
993int
994key_ecdsa_nid_from_name(const char *name)
995{
996 const struct keytype *kt;
997
998 for (kt = keytypes; kt->type != -1; kt++) {
999 if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT)
1000 continue;
1001 if (kt->name != NULL && strcmp(name, kt->name) == 0)
1002 return kt->nid;
1003 }
1004 debug2("%s: unknown/non-ECDSA key type '%s'", __func__, name);
1005 return -1;
1006}
1007
1008char *
1009key_alg_list(void)
1010{
1011 char *ret = NULL;
1012 size_t nlen, rlen = 0;
1013 const struct keytype *kt;
1014
1015 for (kt = keytypes; kt->type != -1; kt++) {
1016 if (kt->name == NULL)
1017 continue;
1018 if (ret != NULL)
1019 ret[rlen++] = '\n';
1020 nlen = strlen(kt->name);
1021 ret = xrealloc(ret, 1, rlen + nlen + 2);
1022 memcpy(ret + rlen, kt->name, nlen + 1);
1023 rlen += nlen;
1024 }
1025 return ret;
1026}
1027
Damien Miller0bc1bd82000-11-13 22:57:25 +11001028u_int
Damien Millerf58b58c2003-11-17 21:18:23 +11001029key_size(const Key *k)
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001030{
Damien Millerad833b32000-08-23 10:46:23 +10001031 switch (k->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +11001032 case KEY_RSA1:
Damien Millerad833b32000-08-23 10:46:23 +10001033 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +10001034 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001035 case KEY_RSA_CERT:
Damien Millerad833b32000-08-23 10:46:23 +10001036 return BN_num_bits(k->rsa->n);
Damien Millerad833b32000-08-23 10:46:23 +10001037 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +10001038 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001039 case KEY_DSA_CERT:
Damien Millerad833b32000-08-23 10:46:23 +10001040 return BN_num_bits(k->dsa->p);
Damien Miller6af914a2010-09-10 11:39:26 +10001041#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001042 case KEY_ECDSA:
1043 case KEY_ECDSA_CERT:
Damien Miller041ab7c2010-09-10 11:23:34 +10001044 return key_curve_nid_to_bits(k->ecdsa_nid);
Damien Miller6af914a2010-09-10 11:39:26 +10001045#endif
Damien Millerad833b32000-08-23 10:46:23 +10001046 }
1047 return 0;
1048}
Damien Miller0bc1bd82000-11-13 22:57:25 +11001049
Ben Lindstrombba81212001-06-25 05:01:22 +00001050static RSA *
Ben Lindstrom46c16222000-12-22 01:43:59 +00001051rsa_generate_private_key(u_int bits)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001052{
Damien Miller4499f4c2010-11-20 15:15:49 +11001053 RSA *private = RSA_new();
1054 BIGNUM *f4 = BN_new();
Damien Miller69b72032006-03-26 14:02:35 +11001055
Kevin Stevesef4eea92001-02-05 12:42:17 +00001056 if (private == NULL)
Damien Miller4499f4c2010-11-20 15:15:49 +11001057 fatal("%s: RSA_new failed", __func__);
1058 if (f4 == NULL)
1059 fatal("%s: BN_new failed", __func__);
1060 if (!BN_set_word(f4, RSA_F4))
1061 fatal("%s: BN_new failed", __func__);
1062 if (!RSA_generate_key_ex(private, bits, f4, NULL))
1063 fatal("%s: key generation failed.", __func__);
1064 BN_free(f4);
Kevin Stevesef4eea92001-02-05 12:42:17 +00001065 return private;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001066}
1067
Ben Lindstrombba81212001-06-25 05:01:22 +00001068static DSA*
Ben Lindstrom46c16222000-12-22 01:43:59 +00001069dsa_generate_private_key(u_int bits)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001070{
Damien Miller4499f4c2010-11-20 15:15:49 +11001071 DSA *private = DSA_new();
Damien Miller69b72032006-03-26 14:02:35 +11001072
Damien Miller0bc1bd82000-11-13 22:57:25 +11001073 if (private == NULL)
Damien Miller4499f4c2010-11-20 15:15:49 +11001074 fatal("%s: DSA_new failed", __func__);
1075 if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL,
1076 NULL, NULL))
1077 fatal("%s: DSA_generate_parameters failed", __func__);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001078 if (!DSA_generate_key(private))
Damien Miller4499f4c2010-11-20 15:15:49 +11001079 fatal("%s: DSA_generate_key failed.", __func__);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001080 return private;
1081}
1082
Damien Millereb8b60e2010-08-31 22:41:14 +10001083int
1084key_ecdsa_bits_to_nid(int bits)
1085{
1086 switch (bits) {
Damien Miller6af914a2010-09-10 11:39:26 +10001087#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001088 case 256:
1089 return NID_X9_62_prime256v1;
1090 case 384:
1091 return NID_secp384r1;
1092 case 521:
1093 return NID_secp521r1;
Damien Miller6af914a2010-09-10 11:39:26 +10001094#endif
Damien Millereb8b60e2010-08-31 22:41:14 +10001095 default:
1096 return -1;
1097 }
1098}
1099
Damien Miller6af914a2010-09-10 11:39:26 +10001100#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001101int
Damien Millerb472a902010-11-05 10:19:49 +11001102key_ecdsa_key_to_nid(EC_KEY *k)
Damien Millereb8b60e2010-08-31 22:41:14 +10001103{
1104 EC_GROUP *eg;
1105 int nids[] = {
1106 NID_X9_62_prime256v1,
1107 NID_secp384r1,
1108 NID_secp521r1,
1109 -1
1110 };
Damien Millerb472a902010-11-05 10:19:49 +11001111 int nid;
Damien Millereb8b60e2010-08-31 22:41:14 +10001112 u_int i;
1113 BN_CTX *bnctx;
Damien Millerb472a902010-11-05 10:19:49 +11001114 const EC_GROUP *g = EC_KEY_get0_group(k);
Damien Millereb8b60e2010-08-31 22:41:14 +10001115
Damien Millerb472a902010-11-05 10:19:49 +11001116 /*
1117 * The group may be stored in a ASN.1 encoded private key in one of two
1118 * ways: as a "named group", which is reconstituted by ASN.1 object ID
1119 * or explicit group parameters encoded into the key blob. Only the
1120 * "named group" case sets the group NID for us, but we can figure
1121 * it out for the other case by comparing against all the groups that
1122 * are supported.
1123 */
1124 if ((nid = EC_GROUP_get_curve_name(g)) > 0)
1125 return nid;
Damien Millereb8b60e2010-08-31 22:41:14 +10001126 if ((bnctx = BN_CTX_new()) == NULL)
1127 fatal("%s: BN_CTX_new() failed", __func__);
1128 for (i = 0; nids[i] != -1; i++) {
1129 if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL)
1130 fatal("%s: EC_GROUP_new_by_curve_name failed",
1131 __func__);
Damien Millerb472a902010-11-05 10:19:49 +11001132 if (EC_GROUP_cmp(g, eg, bnctx) == 0)
Damien Millereb8b60e2010-08-31 22:41:14 +10001133 break;
Damien Millereb8b60e2010-08-31 22:41:14 +10001134 EC_GROUP_free(eg);
1135 }
1136 BN_CTX_free(bnctx);
1137 debug3("%s: nid = %d", __func__, nids[i]);
Damien Millerb472a902010-11-05 10:19:49 +11001138 if (nids[i] != -1) {
1139 /* Use the group with the NID attached */
1140 EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
1141 if (EC_KEY_set_group(k, eg) != 1)
1142 fatal("%s: EC_KEY_set_group", __func__);
1143 }
Damien Millereb8b60e2010-08-31 22:41:14 +10001144 return nids[i];
1145}
1146
1147static EC_KEY*
1148ecdsa_generate_private_key(u_int bits, int *nid)
1149{
1150 EC_KEY *private;
1151
1152 if ((*nid = key_ecdsa_bits_to_nid(bits)) == -1)
1153 fatal("%s: invalid key length", __func__);
1154 if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL)
1155 fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
1156 if (EC_KEY_generate_key(private) != 1)
1157 fatal("%s: EC_KEY_generate_key failed", __func__);
Damien Millerb472a902010-11-05 10:19:49 +11001158 EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE);
Damien Millereb8b60e2010-08-31 22:41:14 +10001159 return private;
1160}
Damien Miller6af914a2010-09-10 11:39:26 +10001161#endif /* OPENSSL_HAS_ECC */
Damien Millereb8b60e2010-08-31 22:41:14 +10001162
Damien Miller0bc1bd82000-11-13 22:57:25 +11001163Key *
Ben Lindstrom46c16222000-12-22 01:43:59 +00001164key_generate(int type, u_int bits)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001165{
1166 Key *k = key_new(KEY_UNSPEC);
1167 switch (type) {
Kevin Stevesef4eea92001-02-05 12:42:17 +00001168 case KEY_DSA:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001169 k->dsa = dsa_generate_private_key(bits);
1170 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001171#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001172 case KEY_ECDSA:
1173 k->ecdsa = ecdsa_generate_private_key(bits, &k->ecdsa_nid);
1174 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001175#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +11001176 case KEY_RSA:
1177 case KEY_RSA1:
1178 k->rsa = rsa_generate_private_key(bits);
1179 break;
Damien Miller4e270b02010-04-16 15:56:21 +10001180 case KEY_RSA_CERT_V00:
1181 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001182 case KEY_RSA_CERT:
1183 case KEY_DSA_CERT:
1184 fatal("key_generate: cert keys cannot be generated directly");
Damien Miller0bc1bd82000-11-13 22:57:25 +11001185 default:
Kevin Stevesef4eea92001-02-05 12:42:17 +00001186 fatal("key_generate: unknown type %d", type);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001187 }
Kevin Stevesef4eea92001-02-05 12:42:17 +00001188 k->type = type;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001189 return k;
1190}
1191
Damien Miller0a80ca12010-02-27 07:55:05 +11001192void
1193key_cert_copy(const Key *from_key, struct Key *to_key)
1194{
1195 u_int i;
1196 const struct KeyCert *from;
1197 struct KeyCert *to;
1198
1199 if (to_key->cert != NULL) {
1200 cert_free(to_key->cert);
1201 to_key->cert = NULL;
1202 }
1203
1204 if ((from = from_key->cert) == NULL)
1205 return;
1206
1207 to = to_key->cert = cert_new();
1208
1209 buffer_append(&to->certblob, buffer_ptr(&from->certblob),
1210 buffer_len(&from->certblob));
1211
Damien Miller4e270b02010-04-16 15:56:21 +10001212 buffer_append(&to->critical,
1213 buffer_ptr(&from->critical), buffer_len(&from->critical));
1214 buffer_append(&to->extensions,
1215 buffer_ptr(&from->extensions), buffer_len(&from->extensions));
Damien Miller0a80ca12010-02-27 07:55:05 +11001216
Damien Miller4e270b02010-04-16 15:56:21 +10001217 to->serial = from->serial;
Damien Miller0a80ca12010-02-27 07:55:05 +11001218 to->type = from->type;
1219 to->key_id = from->key_id == NULL ? NULL : xstrdup(from->key_id);
1220 to->valid_after = from->valid_after;
1221 to->valid_before = from->valid_before;
1222 to->signature_key = from->signature_key == NULL ?
1223 NULL : key_from_private(from->signature_key);
1224
1225 to->nprincipals = from->nprincipals;
1226 if (to->nprincipals > CERT_MAX_PRINCIPALS)
1227 fatal("%s: nprincipals (%u) > CERT_MAX_PRINCIPALS (%u)",
1228 __func__, to->nprincipals, CERT_MAX_PRINCIPALS);
1229 if (to->nprincipals > 0) {
1230 to->principals = xcalloc(from->nprincipals,
1231 sizeof(*to->principals));
1232 for (i = 0; i < to->nprincipals; i++)
1233 to->principals[i] = xstrdup(from->principals[i]);
1234 }
1235}
1236
Damien Miller0bc1bd82000-11-13 22:57:25 +11001237Key *
Damien Millerf58b58c2003-11-17 21:18:23 +11001238key_from_private(const Key *k)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001239{
1240 Key *n = NULL;
1241 switch (k->type) {
Kevin Stevesef4eea92001-02-05 12:42:17 +00001242 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +10001243 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001244 case KEY_DSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001245 n = key_new(k->type);
Darren Tucker0bc85572006-11-07 23:14:41 +11001246 if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
1247 (BN_copy(n->dsa->q, k->dsa->q) == NULL) ||
1248 (BN_copy(n->dsa->g, k->dsa->g) == NULL) ||
1249 (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL))
1250 fatal("key_from_private: BN_copy failed");
Damien Miller0bc1bd82000-11-13 22:57:25 +11001251 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001252#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001253 case KEY_ECDSA:
1254 case KEY_ECDSA_CERT:
1255 n = key_new(k->type);
1256 n->ecdsa_nid = k->ecdsa_nid;
1257 if ((n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL)
1258 fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
1259 if (EC_KEY_set_public_key(n->ecdsa,
1260 EC_KEY_get0_public_key(k->ecdsa)) != 1)
1261 fatal("%s: EC_KEY_set_public_key failed", __func__);
1262 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001263#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +11001264 case KEY_RSA:
1265 case KEY_RSA1:
Damien Miller4e270b02010-04-16 15:56:21 +10001266 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001267 case KEY_RSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001268 n = key_new(k->type);
Darren Tucker0bc85572006-11-07 23:14:41 +11001269 if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
1270 (BN_copy(n->rsa->e, k->rsa->e) == NULL))
1271 fatal("key_from_private: BN_copy failed");
Damien Miller0bc1bd82000-11-13 22:57:25 +11001272 break;
1273 default:
Kevin Stevesef4eea92001-02-05 12:42:17 +00001274 fatal("key_from_private: unknown type %d", k->type);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001275 break;
1276 }
Damien Miller0a80ca12010-02-27 07:55:05 +11001277 if (key_is_cert(k))
1278 key_cert_copy(k, n);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001279 return n;
1280}
1281
1282int
Ben Lindstrom982dbbc2001-04-17 18:11:36 +00001283key_names_valid2(const char *names)
1284{
1285 char *s, *cp, *p;
1286
1287 if (names == NULL || strcmp(names, "") == 0)
1288 return 0;
1289 s = cp = xstrdup(names);
1290 for ((p = strsep(&cp, ",")); p && *p != '\0';
Damien Miller9f0f5c62001-12-21 14:45:46 +11001291 (p = strsep(&cp, ","))) {
Ben Lindstrom982dbbc2001-04-17 18:11:36 +00001292 switch (key_type_from_name(p)) {
1293 case KEY_RSA1:
1294 case KEY_UNSPEC:
1295 xfree(s);
1296 return 0;
1297 }
1298 }
1299 debug3("key names ok: [%s]", names);
1300 xfree(s);
1301 return 1;
1302}
1303
Damien Miller0a80ca12010-02-27 07:55:05 +11001304static int
1305cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)
1306{
Damien Miller4e270b02010-04-16 15:56:21 +10001307 u_char *principals, *critical, *exts, *sig_key, *sig;
1308 u_int signed_len, plen, clen, sklen, slen, kidlen, elen;
Damien Miller0a80ca12010-02-27 07:55:05 +11001309 Buffer tmp;
1310 char *principal;
1311 int ret = -1;
Damien Miller4e270b02010-04-16 15:56:21 +10001312 int v00 = key->type == KEY_DSA_CERT_V00 ||
1313 key->type == KEY_RSA_CERT_V00;
Damien Miller0a80ca12010-02-27 07:55:05 +11001314
1315 buffer_init(&tmp);
1316
1317 /* Copy the entire key blob for verification and later serialisation */
1318 buffer_append(&key->cert->certblob, blob, blen);
1319
Damien Miller4e270b02010-04-16 15:56:21 +10001320 elen = 0; /* Not touched for v00 certs */
1321 principals = exts = critical = sig_key = sig = NULL;
1322 if ((!v00 && buffer_get_int64_ret(&key->cert->serial, b) != 0) ||
1323 buffer_get_int_ret(&key->cert->type, b) != 0 ||
Damien Millerda108ec2010-08-31 22:36:39 +10001324 (key->cert->key_id = buffer_get_cstring_ret(b, &kidlen)) == NULL ||
Damien Miller0a80ca12010-02-27 07:55:05 +11001325 (principals = buffer_get_string_ret(b, &plen)) == NULL ||
1326 buffer_get_int64_ret(&key->cert->valid_after, b) != 0 ||
1327 buffer_get_int64_ret(&key->cert->valid_before, b) != 0 ||
Damien Miller4e270b02010-04-16 15:56:21 +10001328 (critical = buffer_get_string_ret(b, &clen)) == NULL ||
1329 (!v00 && (exts = buffer_get_string_ret(b, &elen)) == NULL) ||
1330 (v00 && buffer_get_string_ptr_ret(b, NULL) == NULL) || /* nonce */
1331 buffer_get_string_ptr_ret(b, NULL) == NULL || /* reserved */
Damien Miller0a80ca12010-02-27 07:55:05 +11001332 (sig_key = buffer_get_string_ret(b, &sklen)) == NULL) {
1333 error("%s: parse error", __func__);
1334 goto out;
1335 }
1336
1337 /* Signature is left in the buffer so we can calculate this length */
1338 signed_len = buffer_len(&key->cert->certblob) - buffer_len(b);
1339
1340 if ((sig = buffer_get_string_ret(b, &slen)) == NULL) {
1341 error("%s: parse error", __func__);
1342 goto out;
1343 }
1344
1345 if (key->cert->type != SSH2_CERT_TYPE_USER &&
1346 key->cert->type != SSH2_CERT_TYPE_HOST) {
1347 error("Unknown certificate type %u", key->cert->type);
1348 goto out;
1349 }
1350
1351 buffer_append(&tmp, principals, plen);
1352 while (buffer_len(&tmp) > 0) {
1353 if (key->cert->nprincipals >= CERT_MAX_PRINCIPALS) {
Damien Miller41396572010-03-04 21:51:11 +11001354 error("%s: Too many principals", __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001355 goto out;
1356 }
Damien Millerda108ec2010-08-31 22:36:39 +10001357 if ((principal = buffer_get_cstring_ret(&tmp, &plen)) == NULL) {
Damien Miller41396572010-03-04 21:51:11 +11001358 error("%s: Principals data invalid", __func__);
1359 goto out;
1360 }
Damien Miller0a80ca12010-02-27 07:55:05 +11001361 key->cert->principals = xrealloc(key->cert->principals,
1362 key->cert->nprincipals + 1, sizeof(*key->cert->principals));
1363 key->cert->principals[key->cert->nprincipals++] = principal;
1364 }
1365
1366 buffer_clear(&tmp);
1367
Damien Miller4e270b02010-04-16 15:56:21 +10001368 buffer_append(&key->cert->critical, critical, clen);
1369 buffer_append(&tmp, critical, clen);
Damien Miller0a80ca12010-02-27 07:55:05 +11001370 /* validate structure */
1371 while (buffer_len(&tmp) != 0) {
Damien Miller2befbad2010-03-04 21:52:18 +11001372 if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||
1373 buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {
Damien Miller4e270b02010-04-16 15:56:21 +10001374 error("%s: critical option data invalid", __func__);
1375 goto out;
1376 }
1377 }
1378 buffer_clear(&tmp);
1379
1380 buffer_append(&key->cert->extensions, exts, elen);
1381 buffer_append(&tmp, exts, elen);
1382 /* validate structure */
1383 while (buffer_len(&tmp) != 0) {
1384 if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||
1385 buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {
1386 error("%s: extension data invalid", __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001387 goto out;
1388 }
1389 }
1390 buffer_clear(&tmp);
1391
1392 if ((key->cert->signature_key = key_from_blob(sig_key,
1393 sklen)) == NULL) {
Damien Miller41396572010-03-04 21:51:11 +11001394 error("%s: Signature key invalid", __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001395 goto out;
1396 }
1397 if (key->cert->signature_key->type != KEY_RSA &&
Damien Millereb8b60e2010-08-31 22:41:14 +10001398 key->cert->signature_key->type != KEY_DSA &&
1399 key->cert->signature_key->type != KEY_ECDSA) {
Damien Miller41396572010-03-04 21:51:11 +11001400 error("%s: Invalid signature key type %s (%d)", __func__,
Damien Miller0a80ca12010-02-27 07:55:05 +11001401 key_type(key->cert->signature_key),
1402 key->cert->signature_key->type);
1403 goto out;
1404 }
1405
1406 switch (key_verify(key->cert->signature_key, sig, slen,
1407 buffer_ptr(&key->cert->certblob), signed_len)) {
1408 case 1:
Damien Miller41396572010-03-04 21:51:11 +11001409 ret = 0;
Damien Miller0a80ca12010-02-27 07:55:05 +11001410 break; /* Good signature */
1411 case 0:
Damien Miller41396572010-03-04 21:51:11 +11001412 error("%s: Invalid signature on certificate", __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001413 goto out;
1414 case -1:
Damien Miller41396572010-03-04 21:51:11 +11001415 error("%s: Certificate signature verification failed",
1416 __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001417 goto out;
1418 }
1419
Damien Miller0a80ca12010-02-27 07:55:05 +11001420 out:
1421 buffer_free(&tmp);
1422 if (principals != NULL)
1423 xfree(principals);
Damien Miller4e270b02010-04-16 15:56:21 +10001424 if (critical != NULL)
1425 xfree(critical);
1426 if (exts != NULL)
1427 xfree(exts);
Damien Miller0a80ca12010-02-27 07:55:05 +11001428 if (sig_key != NULL)
1429 xfree(sig_key);
1430 if (sig != NULL)
1431 xfree(sig);
1432 return ret;
1433}
1434
Damien Miller0bc1bd82000-11-13 22:57:25 +11001435Key *
Damien Millerf58b58c2003-11-17 21:18:23 +11001436key_from_blob(const u_char *blob, u_int blen)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001437{
1438 Buffer b;
Darren Tucker8ccb7392010-09-10 12:28:24 +10001439 int rlen, type;
Damien Millereb8b60e2010-08-31 22:41:14 +10001440 char *ktype = NULL, *curve = NULL;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001441 Key *key = NULL;
Damien Miller6af914a2010-09-10 11:39:26 +10001442#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001443 EC_POINT *q = NULL;
Darren Tucker8ccb7392010-09-10 12:28:24 +10001444 int nid = -1;
Damien Miller6af914a2010-09-10 11:39:26 +10001445#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +11001446
1447#ifdef DEBUG_PK
1448 dump_base64(stderr, blob, blen);
1449#endif
1450 buffer_init(&b);
1451 buffer_append(&b, blob, blen);
Damien Millerda108ec2010-08-31 22:36:39 +10001452 if ((ktype = buffer_get_cstring_ret(&b, NULL)) == NULL) {
Darren Tucker08d04fa2004-11-05 20:42:28 +11001453 error("key_from_blob: can't read key type");
1454 goto out;
1455 }
1456
Damien Miller0bc1bd82000-11-13 22:57:25 +11001457 type = key_type_from_name(ktype);
Damien Miller6af914a2010-09-10 11:39:26 +10001458#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001459 if (key_type_plain(type) == KEY_ECDSA)
1460 nid = key_ecdsa_nid_from_name(ktype);
Damien Miller6af914a2010-09-10 11:39:26 +10001461#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +11001462
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001463 switch (type) {
Damien Miller0a80ca12010-02-27 07:55:05 +11001464 case KEY_RSA_CERT:
Damien Miller4e270b02010-04-16 15:56:21 +10001465 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1466 /* FALLTHROUGH */
1467 case KEY_RSA:
1468 case KEY_RSA_CERT_V00:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001469 key = key_new(type);
Darren Tucker08d04fa2004-11-05 20:42:28 +11001470 if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 ||
1471 buffer_get_bignum2_ret(&b, key->rsa->n) == -1) {
1472 error("key_from_blob: can't read rsa key");
Damien Miller0a80ca12010-02-27 07:55:05 +11001473 badkey:
Darren Tucker08d04fa2004-11-05 20:42:28 +11001474 key_free(key);
1475 key = NULL;
1476 goto out;
1477 }
Damien Miller0bc1bd82000-11-13 22:57:25 +11001478#ifdef DEBUG_PK
1479 RSA_print_fp(stderr, key->rsa, 8);
1480#endif
1481 break;
Damien Miller0a80ca12010-02-27 07:55:05 +11001482 case KEY_DSA_CERT:
Damien Miller4e270b02010-04-16 15:56:21 +10001483 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1484 /* FALLTHROUGH */
1485 case KEY_DSA:
1486 case KEY_DSA_CERT_V00:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001487 key = key_new(type);
Darren Tucker08d04fa2004-11-05 20:42:28 +11001488 if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 ||
1489 buffer_get_bignum2_ret(&b, key->dsa->q) == -1 ||
1490 buffer_get_bignum2_ret(&b, key->dsa->g) == -1 ||
1491 buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) {
1492 error("key_from_blob: can't read dsa key");
Damien Miller0a80ca12010-02-27 07:55:05 +11001493 goto badkey;
Darren Tucker08d04fa2004-11-05 20:42:28 +11001494 }
Damien Miller0bc1bd82000-11-13 22:57:25 +11001495#ifdef DEBUG_PK
1496 DSA_print_fp(stderr, key->dsa, 8);
1497#endif
1498 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001499#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001500 case KEY_ECDSA_CERT:
1501 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1502 /* FALLTHROUGH */
1503 case KEY_ECDSA:
1504 key = key_new(type);
1505 key->ecdsa_nid = nid;
1506 if ((curve = buffer_get_string_ret(&b, NULL)) == NULL) {
1507 error("key_from_blob: can't read ecdsa curve");
1508 goto badkey;
1509 }
1510 if (key->ecdsa_nid != key_curve_name_to_nid(curve)) {
1511 error("key_from_blob: ecdsa curve doesn't match type");
1512 goto badkey;
1513 }
1514 if (key->ecdsa != NULL)
1515 EC_KEY_free(key->ecdsa);
1516 if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
1517 == NULL)
1518 fatal("key_from_blob: EC_KEY_new_by_curve_name failed");
1519 if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL)
1520 fatal("key_from_blob: EC_POINT_new failed");
1521 if (buffer_get_ecpoint_ret(&b, EC_KEY_get0_group(key->ecdsa),
1522 q) == -1) {
1523 error("key_from_blob: can't read ecdsa key point");
1524 goto badkey;
1525 }
1526 if (key_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
1527 q) != 0)
1528 goto badkey;
1529 if (EC_KEY_set_public_key(key->ecdsa, q) != 1)
1530 fatal("key_from_blob: EC_KEY_set_public_key failed");
1531#ifdef DEBUG_PK
1532 key_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
1533#endif
1534 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001535#endif /* OPENSSL_HAS_ECC */
Damien Miller0bc1bd82000-11-13 22:57:25 +11001536 case KEY_UNSPEC:
1537 key = key_new(type);
1538 break;
1539 default:
1540 error("key_from_blob: cannot handle type %s", ktype);
Darren Tucker08d04fa2004-11-05 20:42:28 +11001541 goto out;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001542 }
Damien Miller0a80ca12010-02-27 07:55:05 +11001543 if (key_is_cert(key) && cert_parse(&b, key, blob, blen) == -1) {
1544 error("key_from_blob: can't parse cert data");
1545 goto badkey;
1546 }
Damien Miller0bc1bd82000-11-13 22:57:25 +11001547 rlen = buffer_len(&b);
1548 if (key != NULL && rlen != 0)
1549 error("key_from_blob: remaining bytes in key blob %d", rlen);
Darren Tucker08d04fa2004-11-05 20:42:28 +11001550 out:
1551 if (ktype != NULL)
1552 xfree(ktype);
Damien Millereb8b60e2010-08-31 22:41:14 +10001553 if (curve != NULL)
1554 xfree(curve);
Damien Miller6af914a2010-09-10 11:39:26 +10001555#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001556 if (q != NULL)
1557 EC_POINT_free(q);
Damien Miller6af914a2010-09-10 11:39:26 +10001558#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +11001559 buffer_free(&b);
1560 return key;
1561}
1562
Damien Millerf3747bf2013-01-18 11:44:04 +11001563static int
1564to_blob(const Key *key, u_char **blobp, u_int *lenp, int force_plain)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001565{
1566 Buffer b;
Damien Millerf3747bf2013-01-18 11:44:04 +11001567 int len, type;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001568
1569 if (key == NULL) {
1570 error("key_to_blob: key == NULL");
1571 return 0;
1572 }
1573 buffer_init(&b);
Damien Millerf3747bf2013-01-18 11:44:04 +11001574 type = force_plain ? key_type_plain(key->type) : key->type;
1575 switch (type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001576 case KEY_DSA_CERT_V00:
1577 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001578 case KEY_DSA_CERT:
Damien Millereb8b60e2010-08-31 22:41:14 +10001579 case KEY_ECDSA_CERT:
Damien Miller0a80ca12010-02-27 07:55:05 +11001580 case KEY_RSA_CERT:
1581 /* Use the existing blob */
1582 buffer_append(&b, buffer_ptr(&key->cert->certblob),
1583 buffer_len(&key->cert->certblob));
1584 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001585 case KEY_DSA:
Damien Millerf3747bf2013-01-18 11:44:04 +11001586 buffer_put_cstring(&b,
1587 key_ssh_name_from_type_nid(type, key->ecdsa_nid));
Damien Miller0bc1bd82000-11-13 22:57:25 +11001588 buffer_put_bignum2(&b, key->dsa->p);
1589 buffer_put_bignum2(&b, key->dsa->q);
1590 buffer_put_bignum2(&b, key->dsa->g);
1591 buffer_put_bignum2(&b, key->dsa->pub_key);
1592 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001593#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001594 case KEY_ECDSA:
Damien Millerf3747bf2013-01-18 11:44:04 +11001595 buffer_put_cstring(&b,
1596 key_ssh_name_from_type_nid(type, key->ecdsa_nid));
Damien Millereb8b60e2010-08-31 22:41:14 +10001597 buffer_put_cstring(&b, key_curve_nid_to_name(key->ecdsa_nid));
1598 buffer_put_ecpoint(&b, EC_KEY_get0_group(key->ecdsa),
1599 EC_KEY_get0_public_key(key->ecdsa));
1600 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001601#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +11001602 case KEY_RSA:
Damien Millerf3747bf2013-01-18 11:44:04 +11001603 buffer_put_cstring(&b,
1604 key_ssh_name_from_type_nid(type, key->ecdsa_nid));
Damien Miller0bc1bd82000-11-13 22:57:25 +11001605 buffer_put_bignum2(&b, key->rsa->e);
Ben Lindstrombf555ba2001-01-18 02:04:35 +00001606 buffer_put_bignum2(&b, key->rsa->n);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001607 break;
1608 default:
Ben Lindstrom99a30f12001-09-18 05:49:14 +00001609 error("key_to_blob: unsupported key type %d", key->type);
1610 buffer_free(&b);
1611 return 0;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001612 }
1613 len = buffer_len(&b);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001614 if (lenp != NULL)
1615 *lenp = len;
Ben Lindstrom2bf759c2002-07-07 22:13:31 +00001616 if (blobp != NULL) {
1617 *blobp = xmalloc(len);
1618 memcpy(*blobp, buffer_ptr(&b), len);
1619 }
1620 memset(buffer_ptr(&b), 0, len);
1621 buffer_free(&b);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001622 return len;
1623}
1624
1625int
Damien Millerf3747bf2013-01-18 11:44:04 +11001626key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
1627{
1628 return to_blob(key, blobp, lenp, 0);
1629}
1630
1631int
Damien Miller0bc1bd82000-11-13 22:57:25 +11001632key_sign(
Damien Millerf58b58c2003-11-17 21:18:23 +11001633 const Key *key,
Ben Lindstrom90fd8142002-02-26 18:09:42 +00001634 u_char **sigp, u_int *lenp,
Damien Millerf58b58c2003-11-17 21:18:23 +11001635 const u_char *data, u_int datalen)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001636{
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001637 switch (key->type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001638 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001639 case KEY_DSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001640 case KEY_DSA:
1641 return ssh_dss_sign(key, sigp, lenp, data, datalen);
Damien Miller6af914a2010-09-10 11:39:26 +10001642#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001643 case KEY_ECDSA_CERT:
1644 case KEY_ECDSA:
1645 return ssh_ecdsa_sign(key, sigp, lenp, data, datalen);
Damien Miller6af914a2010-09-10 11:39:26 +10001646#endif
Damien Miller4e270b02010-04-16 15:56:21 +10001647 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001648 case KEY_RSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001649 case KEY_RSA:
1650 return ssh_rsa_sign(key, sigp, lenp, data, datalen);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001651 default:
Darren Tucker5cb30ad2004-08-12 22:40:24 +10001652 error("key_sign: invalid key type %d", key->type);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001653 return -1;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001654 }
1655}
1656
Ben Lindstrom01fff0c2002-06-06 20:54:07 +00001657/*
1658 * key_verify returns 1 for a correct signature, 0 for an incorrect signature
1659 * and -1 on error.
1660 */
Damien Miller0bc1bd82000-11-13 22:57:25 +11001661int
1662key_verify(
Damien Millerf58b58c2003-11-17 21:18:23 +11001663 const Key *key,
1664 const u_char *signature, u_int signaturelen,
1665 const u_char *data, u_int datalen)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001666{
Ben Lindstrom5363aee2001-06-25 04:42:20 +00001667 if (signaturelen == 0)
1668 return -1;
1669
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001670 switch (key->type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001671 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001672 case KEY_DSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001673 case KEY_DSA:
1674 return ssh_dss_verify(key, signature, signaturelen, data, datalen);
Damien Miller6af914a2010-09-10 11:39:26 +10001675#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001676 case KEY_ECDSA_CERT:
1677 case KEY_ECDSA:
1678 return ssh_ecdsa_verify(key, signature, signaturelen, data, datalen);
Damien Miller6af914a2010-09-10 11:39:26 +10001679#endif
Damien Miller4e270b02010-04-16 15:56:21 +10001680 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001681 case KEY_RSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001682 case KEY_RSA:
1683 return ssh_rsa_verify(key, signature, signaturelen, data, datalen);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001684 default:
Darren Tucker5cb30ad2004-08-12 22:40:24 +10001685 error("key_verify: invalid key type %d", key->type);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001686 return -1;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001687 }
1688}
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001689
1690/* Converts a private to a public key */
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001691Key *
Damien Millerf58b58c2003-11-17 21:18:23 +11001692key_demote(const Key *k)
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001693{
1694 Key *pk;
Ben Lindstrom6328ab32002-03-22 02:54:23 +00001695
Damien Miller07d86be2006-03-26 14:19:21 +11001696 pk = xcalloc(1, sizeof(*pk));
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001697 pk->type = k->type;
1698 pk->flags = k->flags;
Damien Millereb8b60e2010-08-31 22:41:14 +10001699 pk->ecdsa_nid = k->ecdsa_nid;
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001700 pk->dsa = NULL;
Damien Millereb8b60e2010-08-31 22:41:14 +10001701 pk->ecdsa = NULL;
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001702 pk->rsa = NULL;
1703
1704 switch (k->type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001705 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001706 case KEY_RSA_CERT:
1707 key_cert_copy(k, pk);
1708 /* FALLTHROUGH */
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001709 case KEY_RSA1:
1710 case KEY_RSA:
1711 if ((pk->rsa = RSA_new()) == NULL)
1712 fatal("key_demote: RSA_new failed");
1713 if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL)
1714 fatal("key_demote: BN_dup failed");
1715 if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL)
1716 fatal("key_demote: BN_dup failed");
1717 break;
Damien Miller4e270b02010-04-16 15:56:21 +10001718 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001719 case KEY_DSA_CERT:
1720 key_cert_copy(k, pk);
1721 /* FALLTHROUGH */
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001722 case KEY_DSA:
1723 if ((pk->dsa = DSA_new()) == NULL)
1724 fatal("key_demote: DSA_new failed");
1725 if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL)
1726 fatal("key_demote: BN_dup failed");
1727 if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL)
1728 fatal("key_demote: BN_dup failed");
1729 if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL)
1730 fatal("key_demote: BN_dup failed");
1731 if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL)
1732 fatal("key_demote: BN_dup failed");
1733 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001734#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001735 case KEY_ECDSA_CERT:
1736 key_cert_copy(k, pk);
1737 /* FALLTHROUGH */
1738 case KEY_ECDSA:
1739 if ((pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid)) == NULL)
1740 fatal("key_demote: EC_KEY_new_by_curve_name failed");
1741 if (EC_KEY_set_public_key(pk->ecdsa,
1742 EC_KEY_get0_public_key(k->ecdsa)) != 1)
1743 fatal("key_demote: EC_KEY_set_public_key failed");
1744 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001745#endif
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001746 default:
1747 fatal("key_free: bad key type %d", k->type);
1748 break;
1749 }
1750
1751 return (pk);
1752}
Damien Miller0a80ca12010-02-27 07:55:05 +11001753
1754int
1755key_is_cert(const Key *k)
1756{
Damien Miller4e270b02010-04-16 15:56:21 +10001757 if (k == NULL)
1758 return 0;
1759 switch (k->type) {
1760 case KEY_RSA_CERT_V00:
1761 case KEY_DSA_CERT_V00:
1762 case KEY_RSA_CERT:
1763 case KEY_DSA_CERT:
Damien Millereb8b60e2010-08-31 22:41:14 +10001764 case KEY_ECDSA_CERT:
Damien Miller4e270b02010-04-16 15:56:21 +10001765 return 1;
1766 default:
1767 return 0;
1768 }
Damien Miller0a80ca12010-02-27 07:55:05 +11001769}
1770
1771/* Return the cert-less equivalent to a certified key type */
1772int
1773key_type_plain(int type)
1774{
1775 switch (type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001776 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001777 case KEY_RSA_CERT:
1778 return KEY_RSA;
Damien Miller4e270b02010-04-16 15:56:21 +10001779 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001780 case KEY_DSA_CERT:
1781 return KEY_DSA;
Damien Millereb8b60e2010-08-31 22:41:14 +10001782 case KEY_ECDSA_CERT:
1783 return KEY_ECDSA;
Damien Miller0a80ca12010-02-27 07:55:05 +11001784 default:
1785 return type;
1786 }
1787}
1788
1789/* Convert a KEY_RSA or KEY_DSA to their _CERT equivalent */
1790int
Damien Miller4e270b02010-04-16 15:56:21 +10001791key_to_certified(Key *k, int legacy)
Damien Miller0a80ca12010-02-27 07:55:05 +11001792{
1793 switch (k->type) {
1794 case KEY_RSA:
1795 k->cert = cert_new();
Damien Miller4e270b02010-04-16 15:56:21 +10001796 k->type = legacy ? KEY_RSA_CERT_V00 : KEY_RSA_CERT;
Damien Miller0a80ca12010-02-27 07:55:05 +11001797 return 0;
1798 case KEY_DSA:
1799 k->cert = cert_new();
Damien Miller4e270b02010-04-16 15:56:21 +10001800 k->type = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT;
Damien Miller0a80ca12010-02-27 07:55:05 +11001801 return 0;
Damien Millereb8b60e2010-08-31 22:41:14 +10001802 case KEY_ECDSA:
Damien Miller8f639fe2011-05-20 19:03:08 +10001803 if (legacy)
1804 fatal("%s: legacy ECDSA certificates are not supported",
1805 __func__);
Damien Millereb8b60e2010-08-31 22:41:14 +10001806 k->cert = cert_new();
1807 k->type = KEY_ECDSA_CERT;
1808 return 0;
Damien Miller0a80ca12010-02-27 07:55:05 +11001809 default:
1810 error("%s: key has incorrect type %s", __func__, key_type(k));
1811 return -1;
1812 }
1813}
1814
1815/* Convert a KEY_RSA_CERT or KEY_DSA_CERT to their raw key equivalent */
1816int
1817key_drop_cert(Key *k)
1818{
1819 switch (k->type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001820 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001821 case KEY_RSA_CERT:
1822 cert_free(k->cert);
1823 k->type = KEY_RSA;
1824 return 0;
Damien Miller4e270b02010-04-16 15:56:21 +10001825 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001826 case KEY_DSA_CERT:
1827 cert_free(k->cert);
1828 k->type = KEY_DSA;
1829 return 0;
Damien Millereb8b60e2010-08-31 22:41:14 +10001830 case KEY_ECDSA_CERT:
1831 cert_free(k->cert);
1832 k->type = KEY_ECDSA;
1833 return 0;
Damien Miller0a80ca12010-02-27 07:55:05 +11001834 default:
1835 error("%s: key has incorrect type %s", __func__, key_type(k));
1836 return -1;
1837 }
1838}
1839
Damien Millereb8b60e2010-08-31 22:41:14 +10001840/*
1841 * Sign a KEY_RSA_CERT, KEY_DSA_CERT or KEY_ECDSA_CERT, (re-)generating
1842 * the signed certblob
1843 */
Damien Miller0a80ca12010-02-27 07:55:05 +11001844int
1845key_certify(Key *k, Key *ca)
1846{
1847 Buffer principals;
1848 u_char *ca_blob, *sig_blob, nonce[32];
1849 u_int i, ca_len, sig_len;
1850
1851 if (k->cert == NULL) {
1852 error("%s: key lacks cert info", __func__);
1853 return -1;
1854 }
1855
1856 if (!key_is_cert(k)) {
1857 error("%s: certificate has unknown type %d", __func__,
1858 k->cert->type);
1859 return -1;
1860 }
1861
Damien Millereb8b60e2010-08-31 22:41:14 +10001862 if (ca->type != KEY_RSA && ca->type != KEY_DSA &&
1863 ca->type != KEY_ECDSA) {
Damien Miller0a80ca12010-02-27 07:55:05 +11001864 error("%s: CA key has unsupported type %s", __func__,
1865 key_type(ca));
1866 return -1;
1867 }
1868
1869 key_to_blob(ca, &ca_blob, &ca_len);
1870
1871 buffer_clear(&k->cert->certblob);
1872 buffer_put_cstring(&k->cert->certblob, key_ssh_name(k));
1873
Damien Miller4e270b02010-04-16 15:56:21 +10001874 /* -v01 certs put nonce first */
Damien Miller0a5f0122011-02-04 11:47:01 +11001875 arc4random_buf(&nonce, sizeof(nonce));
1876 if (!key_cert_is_legacy(k))
Damien Miller4e270b02010-04-16 15:56:21 +10001877 buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
Damien Miller4e270b02010-04-16 15:56:21 +10001878
Damien Miller0a80ca12010-02-27 07:55:05 +11001879 switch (k->type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001880 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001881 case KEY_DSA_CERT:
1882 buffer_put_bignum2(&k->cert->certblob, k->dsa->p);
1883 buffer_put_bignum2(&k->cert->certblob, k->dsa->q);
1884 buffer_put_bignum2(&k->cert->certblob, k->dsa->g);
1885 buffer_put_bignum2(&k->cert->certblob, k->dsa->pub_key);
1886 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001887#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001888 case KEY_ECDSA_CERT:
1889 buffer_put_cstring(&k->cert->certblob,
1890 key_curve_nid_to_name(k->ecdsa_nid));
1891 buffer_put_ecpoint(&k->cert->certblob,
1892 EC_KEY_get0_group(k->ecdsa),
1893 EC_KEY_get0_public_key(k->ecdsa));
1894 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001895#endif
Damien Miller4e270b02010-04-16 15:56:21 +10001896 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001897 case KEY_RSA_CERT:
1898 buffer_put_bignum2(&k->cert->certblob, k->rsa->e);
1899 buffer_put_bignum2(&k->cert->certblob, k->rsa->n);
1900 break;
1901 default:
1902 error("%s: key has incorrect type %s", __func__, key_type(k));
1903 buffer_clear(&k->cert->certblob);
1904 xfree(ca_blob);
1905 return -1;
1906 }
1907
Damien Miller4e270b02010-04-16 15:56:21 +10001908 /* -v01 certs have a serial number next */
Damien Millereb8b60e2010-08-31 22:41:14 +10001909 if (!key_cert_is_legacy(k))
Damien Miller4e270b02010-04-16 15:56:21 +10001910 buffer_put_int64(&k->cert->certblob, k->cert->serial);
1911
Damien Miller0a80ca12010-02-27 07:55:05 +11001912 buffer_put_int(&k->cert->certblob, k->cert->type);
1913 buffer_put_cstring(&k->cert->certblob, k->cert->key_id);
1914
1915 buffer_init(&principals);
1916 for (i = 0; i < k->cert->nprincipals; i++)
1917 buffer_put_cstring(&principals, k->cert->principals[i]);
1918 buffer_put_string(&k->cert->certblob, buffer_ptr(&principals),
1919 buffer_len(&principals));
1920 buffer_free(&principals);
1921
1922 buffer_put_int64(&k->cert->certblob, k->cert->valid_after);
1923 buffer_put_int64(&k->cert->certblob, k->cert->valid_before);
1924 buffer_put_string(&k->cert->certblob,
Damien Miller4e270b02010-04-16 15:56:21 +10001925 buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical));
Damien Miller0a80ca12010-02-27 07:55:05 +11001926
Damien Miller4e270b02010-04-16 15:56:21 +10001927 /* -v01 certs have non-critical options here */
Damien Millereb8b60e2010-08-31 22:41:14 +10001928 if (!key_cert_is_legacy(k)) {
Damien Miller4e270b02010-04-16 15:56:21 +10001929 buffer_put_string(&k->cert->certblob,
1930 buffer_ptr(&k->cert->extensions),
1931 buffer_len(&k->cert->extensions));
1932 }
1933
1934 /* -v00 certs put the nonce at the end */
Damien Millereb8b60e2010-08-31 22:41:14 +10001935 if (key_cert_is_legacy(k))
Damien Miller4e270b02010-04-16 15:56:21 +10001936 buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
1937
Damien Miller0a80ca12010-02-27 07:55:05 +11001938 buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */
1939 buffer_put_string(&k->cert->certblob, ca_blob, ca_len);
1940 xfree(ca_blob);
1941
1942 /* Sign the whole mess */
1943 if (key_sign(ca, &sig_blob, &sig_len, buffer_ptr(&k->cert->certblob),
1944 buffer_len(&k->cert->certblob)) != 0) {
1945 error("%s: signature operation failed", __func__);
1946 buffer_clear(&k->cert->certblob);
1947 return -1;
1948 }
1949 /* Append signature and we are done */
1950 buffer_put_string(&k->cert->certblob, sig_blob, sig_len);
1951 xfree(sig_blob);
1952
1953 return 0;
1954}
1955
1956int
1957key_cert_check_authority(const Key *k, int want_host, int require_principal,
1958 const char *name, const char **reason)
1959{
1960 u_int i, principal_matches;
1961 time_t now = time(NULL);
1962
1963 if (want_host) {
1964 if (k->cert->type != SSH2_CERT_TYPE_HOST) {
1965 *reason = "Certificate invalid: not a host certificate";
1966 return -1;
1967 }
1968 } else {
1969 if (k->cert->type != SSH2_CERT_TYPE_USER) {
1970 *reason = "Certificate invalid: not a user certificate";
1971 return -1;
1972 }
1973 }
1974 if (now < 0) {
1975 error("%s: system clock lies before epoch", __func__);
1976 *reason = "Certificate invalid: not yet valid";
1977 return -1;
1978 }
1979 if ((u_int64_t)now < k->cert->valid_after) {
1980 *reason = "Certificate invalid: not yet valid";
1981 return -1;
1982 }
1983 if ((u_int64_t)now >= k->cert->valid_before) {
1984 *reason = "Certificate invalid: expired";
1985 return -1;
1986 }
1987 if (k->cert->nprincipals == 0) {
1988 if (require_principal) {
1989 *reason = "Certificate lacks principal list";
1990 return -1;
1991 }
Damien Miller30da3442010-05-10 11:58:03 +10001992 } else if (name != NULL) {
Damien Miller0a80ca12010-02-27 07:55:05 +11001993 principal_matches = 0;
1994 for (i = 0; i < k->cert->nprincipals; i++) {
1995 if (strcmp(name, k->cert->principals[i]) == 0) {
1996 principal_matches = 1;
1997 break;
1998 }
1999 }
2000 if (!principal_matches) {
2001 *reason = "Certificate invalid: name is not a listed "
2002 "principal";
2003 return -1;
2004 }
2005 }
2006 return 0;
2007}
Damien Miller4e270b02010-04-16 15:56:21 +10002008
2009int
Damien Millerf3747bf2013-01-18 11:44:04 +11002010key_cert_is_legacy(const Key *k)
Damien Miller4e270b02010-04-16 15:56:21 +10002011{
2012 switch (k->type) {
2013 case KEY_DSA_CERT_V00:
2014 case KEY_RSA_CERT_V00:
2015 return 1;
2016 default:
2017 return 0;
2018 }
2019}
Damien Millereb8b60e2010-08-31 22:41:14 +10002020
Damien Miller041ab7c2010-09-10 11:23:34 +10002021/* XXX: these are really begging for a table-driven approach */
Damien Millereb8b60e2010-08-31 22:41:14 +10002022int
2023key_curve_name_to_nid(const char *name)
2024{
Damien Miller6af914a2010-09-10 11:39:26 +10002025#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10002026 if (strcmp(name, "nistp256") == 0)
2027 return NID_X9_62_prime256v1;
2028 else if (strcmp(name, "nistp384") == 0)
2029 return NID_secp384r1;
2030 else if (strcmp(name, "nistp521") == 0)
2031 return NID_secp521r1;
Damien Miller6af914a2010-09-10 11:39:26 +10002032#endif
Damien Millereb8b60e2010-08-31 22:41:14 +10002033
2034 debug("%s: unsupported EC curve name \"%.100s\"", __func__, name);
2035 return -1;
2036}
2037
Damien Miller041ab7c2010-09-10 11:23:34 +10002038u_int
2039key_curve_nid_to_bits(int nid)
2040{
2041 switch (nid) {
Damien Miller6af914a2010-09-10 11:39:26 +10002042#ifdef OPENSSL_HAS_ECC
Damien Miller041ab7c2010-09-10 11:23:34 +10002043 case NID_X9_62_prime256v1:
2044 return 256;
2045 case NID_secp384r1:
2046 return 384;
2047 case NID_secp521r1:
2048 return 521;
Damien Miller6af914a2010-09-10 11:39:26 +10002049#endif
Damien Miller041ab7c2010-09-10 11:23:34 +10002050 default:
2051 error("%s: unsupported EC curve nid %d", __func__, nid);
2052 return 0;
2053 }
2054}
2055
Damien Millereb8b60e2010-08-31 22:41:14 +10002056const char *
2057key_curve_nid_to_name(int nid)
2058{
Damien Miller6af914a2010-09-10 11:39:26 +10002059#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10002060 if (nid == NID_X9_62_prime256v1)
2061 return "nistp256";
2062 else if (nid == NID_secp384r1)
2063 return "nistp384";
2064 else if (nid == NID_secp521r1)
2065 return "nistp521";
Damien Miller6af914a2010-09-10 11:39:26 +10002066#endif
Damien Millereb8b60e2010-08-31 22:41:14 +10002067 error("%s: unsupported EC curve nid %d", __func__, nid);
2068 return NULL;
2069}
2070
Damien Miller6af914a2010-09-10 11:39:26 +10002071#ifdef OPENSSL_HAS_ECC
Damien Miller041ab7c2010-09-10 11:23:34 +10002072const EVP_MD *
2073key_ec_nid_to_evpmd(int nid)
2074{
2075 int kbits = key_curve_nid_to_bits(nid);
2076
2077 if (kbits == 0)
2078 fatal("%s: invalid nid %d", __func__, nid);
2079 /* RFC5656 section 6.2.1 */
2080 if (kbits <= 256)
2081 return EVP_sha256();
2082 else if (kbits <= 384)
2083 return EVP_sha384();
2084 else
2085 return EVP_sha512();
2086}
2087
Damien Millereb8b60e2010-08-31 22:41:14 +10002088int
2089key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
2090{
2091 BN_CTX *bnctx;
2092 EC_POINT *nq = NULL;
2093 BIGNUM *order, *x, *y, *tmp;
2094 int ret = -1;
2095
2096 if ((bnctx = BN_CTX_new()) == NULL)
2097 fatal("%s: BN_CTX_new failed", __func__);
2098 BN_CTX_start(bnctx);
2099
2100 /*
2101 * We shouldn't ever hit this case because bignum_get_ecpoint()
2102 * refuses to load GF2m points.
2103 */
2104 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
2105 NID_X9_62_prime_field) {
2106 error("%s: group is not a prime field", __func__);
2107 goto out;
2108 }
2109
2110 /* Q != infinity */
2111 if (EC_POINT_is_at_infinity(group, public)) {
2112 error("%s: received degenerate public key (infinity)",
2113 __func__);
2114 goto out;
2115 }
2116
2117 if ((x = BN_CTX_get(bnctx)) == NULL ||
2118 (y = BN_CTX_get(bnctx)) == NULL ||
2119 (order = BN_CTX_get(bnctx)) == NULL ||
2120 (tmp = BN_CTX_get(bnctx)) == NULL)
2121 fatal("%s: BN_CTX_get failed", __func__);
2122
2123 /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
2124 if (EC_GROUP_get_order(group, order, bnctx) != 1)
2125 fatal("%s: EC_GROUP_get_order failed", __func__);
2126 if (EC_POINT_get_affine_coordinates_GFp(group, public,
2127 x, y, bnctx) != 1)
2128 fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__);
2129 if (BN_num_bits(x) <= BN_num_bits(order) / 2) {
2130 error("%s: public key x coordinate too small: "
2131 "bits(x) = %d, bits(order)/2 = %d", __func__,
2132 BN_num_bits(x), BN_num_bits(order) / 2);
2133 goto out;
2134 }
2135 if (BN_num_bits(y) <= BN_num_bits(order) / 2) {
2136 error("%s: public key y coordinate too small: "
2137 "bits(y) = %d, bits(order)/2 = %d", __func__,
2138 BN_num_bits(x), BN_num_bits(order) / 2);
2139 goto out;
2140 }
2141
2142 /* nQ == infinity (n == order of subgroup) */
2143 if ((nq = EC_POINT_new(group)) == NULL)
2144 fatal("%s: BN_CTX_tmp failed", __func__);
2145 if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1)
2146 fatal("%s: EC_GROUP_mul failed", __func__);
2147 if (EC_POINT_is_at_infinity(group, nq) != 1) {
2148 error("%s: received degenerate public key (nQ != infinity)",
2149 __func__);
2150 goto out;
2151 }
2152
2153 /* x < order - 1, y < order - 1 */
2154 if (!BN_sub(tmp, order, BN_value_one()))
2155 fatal("%s: BN_sub failed", __func__);
2156 if (BN_cmp(x, tmp) >= 0) {
2157 error("%s: public key x coordinate >= group order - 1",
2158 __func__);
2159 goto out;
2160 }
2161 if (BN_cmp(y, tmp) >= 0) {
2162 error("%s: public key y coordinate >= group order - 1",
2163 __func__);
2164 goto out;
2165 }
2166 ret = 0;
2167 out:
2168 BN_CTX_free(bnctx);
2169 EC_POINT_free(nq);
2170 return ret;
2171}
2172
2173int
2174key_ec_validate_private(const EC_KEY *key)
2175{
2176 BN_CTX *bnctx;
2177 BIGNUM *order, *tmp;
2178 int ret = -1;
2179
2180 if ((bnctx = BN_CTX_new()) == NULL)
2181 fatal("%s: BN_CTX_new failed", __func__);
2182 BN_CTX_start(bnctx);
2183
2184 if ((order = BN_CTX_get(bnctx)) == NULL ||
2185 (tmp = BN_CTX_get(bnctx)) == NULL)
2186 fatal("%s: BN_CTX_get failed", __func__);
2187
2188 /* log2(private) > log2(order)/2 */
2189 if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1)
2190 fatal("%s: EC_GROUP_get_order failed", __func__);
2191 if (BN_num_bits(EC_KEY_get0_private_key(key)) <=
2192 BN_num_bits(order) / 2) {
2193 error("%s: private key too small: "
2194 "bits(y) = %d, bits(order)/2 = %d", __func__,
2195 BN_num_bits(EC_KEY_get0_private_key(key)),
2196 BN_num_bits(order) / 2);
2197 goto out;
2198 }
2199
2200 /* private < order - 1 */
2201 if (!BN_sub(tmp, order, BN_value_one()))
2202 fatal("%s: BN_sub failed", __func__);
2203 if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0) {
2204 error("%s: private key >= group order - 1", __func__);
2205 goto out;
2206 }
2207 ret = 0;
2208 out:
2209 BN_CTX_free(bnctx);
2210 return ret;
2211}
2212
2213#if defined(DEBUG_KEXECDH) || defined(DEBUG_PK)
2214void
2215key_dump_ec_point(const EC_GROUP *group, const EC_POINT *point)
2216{
2217 BIGNUM *x, *y;
2218 BN_CTX *bnctx;
2219
2220 if (point == NULL) {
2221 fputs("point=(NULL)\n", stderr);
2222 return;
2223 }
2224 if ((bnctx = BN_CTX_new()) == NULL)
2225 fatal("%s: BN_CTX_new failed", __func__);
2226 BN_CTX_start(bnctx);
2227 if ((x = BN_CTX_get(bnctx)) == NULL || (y = BN_CTX_get(bnctx)) == NULL)
2228 fatal("%s: BN_CTX_get failed", __func__);
2229 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
2230 NID_X9_62_prime_field)
2231 fatal("%s: group is not a prime field", __func__);
2232 if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, bnctx) != 1)
2233 fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__);
2234 fputs("x=", stderr);
2235 BN_print_fp(stderr, x);
2236 fputs("\ny=", stderr);
2237 BN_print_fp(stderr, y);
2238 fputs("\n", stderr);
2239 BN_CTX_free(bnctx);
2240}
2241
2242void
2243key_dump_ec_key(const EC_KEY *key)
2244{
2245 const BIGNUM *exponent;
2246
2247 key_dump_ec_point(EC_KEY_get0_group(key), EC_KEY_get0_public_key(key));
2248 fputs("exponent=", stderr);
2249 if ((exponent = EC_KEY_get0_private_key(key)) == NULL)
2250 fputs("(NULL)", stderr);
2251 else
2252 BN_print_fp(stderr, EC_KEY_get0_private_key(key));
2253 fputs("\n", stderr);
2254}
2255#endif /* defined(DEBUG_KEXECDH) || defined(DEBUG_PK) */
Damien Miller6af914a2010-09-10 11:39:26 +10002256#endif /* OPENSSL_HAS_ECC */