blob: 5cc4132c011f256d9f78f00b411f990a71881237 [file] [log] [blame]
Damien Millerc51a5ab2011-10-18 16:06:14 +11001/* $OpenBSD: key.c,v 1.98 2011/10/18 04:58:26 djm Exp $ */
Damien Miller450a7a12000-03-26 13:04:51 +10002/*
Damien Millere4340be2000-09-16 13:29:08 +11003 * read_bignum():
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 *
6 * As far as I am concerned, the code I have written for this software
7 * can be used freely for any purpose. Any derived versions of this
8 * software must be clearly marked as such, and if the derived work is
9 * incompatible with the protocol description in the RFC file, it must be
10 * called by a name other than "ssh" or "Secure Shell".
11 *
12 *
Ben Lindstrom44697232001-07-04 03:32:30 +000013 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
Darren Tucker0f0ef0a2008-06-13 08:58:05 +100014 * Copyright (c) 2008 Alexander von Gernler. All rights reserved.
Damien Miller450a7a12000-03-26 13:04:51 +100015 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
Damien Miller450a7a12000-03-26 13:04:51 +100024 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
Damien Millerd7834352006-08-05 12:39:39 +100036
Damien Miller450a7a12000-03-26 13:04:51 +100037#include "includes.h"
Ben Lindstrom226cfa02001-01-22 05:34:40 +000038
Darren Tucker9c16ac92008-06-13 04:40:35 +100039#include <sys/param.h>
Damien Millerd7834352006-08-05 12:39:39 +100040#include <sys/types.h>
41
Damien Miller450a7a12000-03-26 13:04:51 +100042#include <openssl/evp.h>
Darren Tucker3d295a62008-02-28 19:22:04 +110043#include <openbsd-compat/openssl-compat.h>
Ben Lindstrom226cfa02001-01-22 05:34:40 +000044
Damien Millerded319c2006-09-01 15:38:36 +100045#include <stdarg.h>
Damien Millera7a73ee2006-08-05 11:37:59 +100046#include <stdio.h>
Damien Millere3476ed2006-07-24 14:13:33 +100047#include <string.h>
48
Damien Miller450a7a12000-03-26 13:04:51 +100049#include "xmalloc.h"
50#include "key.h"
Damien Miller0bc1bd82000-11-13 22:57:25 +110051#include "rsa.h"
Damien Millereba71ba2000-04-29 23:57:08 +100052#include "uuencode.h"
Damien Miller0bc1bd82000-11-13 22:57:25 +110053#include "buffer.h"
Ben Lindstrom226cfa02001-01-22 05:34:40 +000054#include "log.h"
Damien Miller8a0268f2010-07-16 13:57:51 +100055#include "misc.h"
Damien Miller0a80ca12010-02-27 07:55:05 +110056#include "ssh2.h"
57
58static struct KeyCert *
59cert_new(void)
60{
61 struct KeyCert *cert;
62
63 cert = xcalloc(1, sizeof(*cert));
64 buffer_init(&cert->certblob);
Damien Miller4e270b02010-04-16 15:56:21 +100065 buffer_init(&cert->critical);
66 buffer_init(&cert->extensions);
Damien Miller0a80ca12010-02-27 07:55:05 +110067 cert->key_id = NULL;
68 cert->principals = NULL;
69 cert->signature_key = NULL;
70 return cert;
71}
Damien Miller450a7a12000-03-26 13:04:51 +100072
73Key *
74key_new(int type)
75{
76 Key *k;
77 RSA *rsa;
78 DSA *dsa;
Damien Miller07d86be2006-03-26 14:19:21 +110079 k = xcalloc(1, sizeof(*k));
Damien Miller450a7a12000-03-26 13:04:51 +100080 k->type = type;
Damien Millereb8b60e2010-08-31 22:41:14 +100081 k->ecdsa = NULL;
82 k->ecdsa_nid = -1;
Damien Millereba71ba2000-04-29 23:57:08 +100083 k->dsa = NULL;
84 k->rsa = NULL;
Damien Miller0a80ca12010-02-27 07:55:05 +110085 k->cert = NULL;
Damien Miller450a7a12000-03-26 13:04:51 +100086 switch (k->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +110087 case KEY_RSA1:
Damien Miller450a7a12000-03-26 13:04:51 +100088 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +100089 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +110090 case KEY_RSA_CERT:
Damien Millerda755162002-01-22 23:09:22 +110091 if ((rsa = RSA_new()) == NULL)
92 fatal("key_new: RSA_new failed");
93 if ((rsa->n = BN_new()) == NULL)
94 fatal("key_new: BN_new failed");
95 if ((rsa->e = BN_new()) == NULL)
96 fatal("key_new: BN_new failed");
Damien Miller450a7a12000-03-26 13:04:51 +100097 k->rsa = rsa;
98 break;
99 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000100 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100101 case KEY_DSA_CERT:
Damien Millerda755162002-01-22 23:09:22 +1100102 if ((dsa = DSA_new()) == NULL)
103 fatal("key_new: DSA_new failed");
104 if ((dsa->p = BN_new()) == NULL)
105 fatal("key_new: BN_new failed");
106 if ((dsa->q = BN_new()) == NULL)
107 fatal("key_new: BN_new failed");
108 if ((dsa->g = BN_new()) == NULL)
109 fatal("key_new: BN_new failed");
110 if ((dsa->pub_key = BN_new()) == NULL)
111 fatal("key_new: BN_new failed");
Damien Miller450a7a12000-03-26 13:04:51 +1000112 k->dsa = dsa;
113 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000114#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000115 case KEY_ECDSA:
116 case KEY_ECDSA_CERT:
117 /* Cannot do anything until we know the group */
118 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000119#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +1100120 case KEY_UNSPEC:
Damien Miller450a7a12000-03-26 13:04:51 +1000121 break;
122 default:
123 fatal("key_new: bad key type %d", k->type);
124 break;
125 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100126
127 if (key_is_cert(k))
128 k->cert = cert_new();
129
Damien Miller450a7a12000-03-26 13:04:51 +1000130 return k;
131}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000132
Damien Miller0a80ca12010-02-27 07:55:05 +1100133void
134key_add_private(Key *k)
Damien Miller0bc1bd82000-11-13 22:57:25 +1100135{
Damien Miller0bc1bd82000-11-13 22:57:25 +1100136 switch (k->type) {
137 case KEY_RSA1:
138 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000139 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100140 case KEY_RSA_CERT:
Damien Millerda755162002-01-22 23:09:22 +1100141 if ((k->rsa->d = BN_new()) == NULL)
142 fatal("key_new_private: BN_new failed");
143 if ((k->rsa->iqmp = BN_new()) == NULL)
144 fatal("key_new_private: BN_new failed");
145 if ((k->rsa->q = BN_new()) == NULL)
146 fatal("key_new_private: BN_new failed");
147 if ((k->rsa->p = BN_new()) == NULL)
148 fatal("key_new_private: BN_new failed");
149 if ((k->rsa->dmq1 = BN_new()) == NULL)
150 fatal("key_new_private: BN_new failed");
151 if ((k->rsa->dmp1 = BN_new()) == NULL)
152 fatal("key_new_private: BN_new failed");
Damien Miller0bc1bd82000-11-13 22:57:25 +1100153 break;
154 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000155 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100156 case KEY_DSA_CERT:
Damien Millerda755162002-01-22 23:09:22 +1100157 if ((k->dsa->priv_key = BN_new()) == NULL)
158 fatal("key_new_private: BN_new failed");
Damien Miller0bc1bd82000-11-13 22:57:25 +1100159 break;
Damien Millereb8b60e2010-08-31 22:41:14 +1000160 case KEY_ECDSA:
161 case KEY_ECDSA_CERT:
162 /* Cannot do anything until we know the group */
163 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100164 case KEY_UNSPEC:
165 break;
166 default:
167 break;
168 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100169}
170
171Key *
172key_new_private(int type)
173{
174 Key *k = key_new(type);
175
176 key_add_private(k);
Damien Miller0bc1bd82000-11-13 22:57:25 +1100177 return k;
178}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000179
Damien Miller0a80ca12010-02-27 07:55:05 +1100180static void
181cert_free(struct KeyCert *cert)
182{
183 u_int i;
184
185 buffer_free(&cert->certblob);
Damien Miller4e270b02010-04-16 15:56:21 +1000186 buffer_free(&cert->critical);
187 buffer_free(&cert->extensions);
Damien Miller0a80ca12010-02-27 07:55:05 +1100188 if (cert->key_id != NULL)
189 xfree(cert->key_id);
190 for (i = 0; i < cert->nprincipals; i++)
191 xfree(cert->principals[i]);
192 if (cert->principals != NULL)
193 xfree(cert->principals);
194 if (cert->signature_key != NULL)
195 key_free(cert->signature_key);
196}
197
Damien Miller450a7a12000-03-26 13:04:51 +1000198void
199key_free(Key *k)
200{
Damien Miller429fcc22006-03-26 14:02:16 +1100201 if (k == NULL)
Damien Millerbbaad772006-03-26 14:03:03 +1100202 fatal("key_free: key is NULL");
Damien Miller450a7a12000-03-26 13:04:51 +1000203 switch (k->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100204 case KEY_RSA1:
Damien Miller450a7a12000-03-26 13:04:51 +1000205 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000206 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100207 case KEY_RSA_CERT:
Damien Miller450a7a12000-03-26 13:04:51 +1000208 if (k->rsa != NULL)
209 RSA_free(k->rsa);
210 k->rsa = NULL;
211 break;
212 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000213 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100214 case KEY_DSA_CERT:
Damien Miller450a7a12000-03-26 13:04:51 +1000215 if (k->dsa != NULL)
216 DSA_free(k->dsa);
217 k->dsa = NULL;
218 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000219#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000220 case KEY_ECDSA:
221 case KEY_ECDSA_CERT:
222 if (k->ecdsa != NULL)
223 EC_KEY_free(k->ecdsa);
224 k->ecdsa = NULL;
225 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000226#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +1100227 case KEY_UNSPEC:
228 break;
Damien Miller450a7a12000-03-26 13:04:51 +1000229 default:
230 fatal("key_free: bad key type %d", k->type);
231 break;
232 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100233 if (key_is_cert(k)) {
234 if (k->cert != NULL)
235 cert_free(k->cert);
236 k->cert = NULL;
237 }
238
Damien Miller450a7a12000-03-26 13:04:51 +1000239 xfree(k);
240}
Damien Millerf58b58c2003-11-17 21:18:23 +1100241
Damien Miller0a80ca12010-02-27 07:55:05 +1100242static int
243cert_compare(struct KeyCert *a, struct KeyCert *b)
Damien Miller450a7a12000-03-26 13:04:51 +1000244{
Damien Miller0a80ca12010-02-27 07:55:05 +1100245 if (a == NULL && b == NULL)
246 return 1;
247 if (a == NULL || b == NULL)
Damien Miller450a7a12000-03-26 13:04:51 +1000248 return 0;
Damien Miller0a80ca12010-02-27 07:55:05 +1100249 if (buffer_len(&a->certblob) != buffer_len(&b->certblob))
250 return 0;
Damien Millerea1651c2010-07-16 13:58:37 +1000251 if (timingsafe_bcmp(buffer_ptr(&a->certblob), buffer_ptr(&b->certblob),
Damien Miller0a80ca12010-02-27 07:55:05 +1100252 buffer_len(&a->certblob)) != 0)
253 return 0;
254 return 1;
255}
256
257/*
258 * Compare public portions of key only, allowing comparisons between
259 * certificates and plain keys too.
260 */
261int
262key_equal_public(const Key *a, const Key *b)
263{
Darren Tucker8ccb7392010-09-10 12:28:24 +1000264#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000265 BN_CTX *bnctx;
Darren Tucker8ccb7392010-09-10 12:28:24 +1000266#endif
Damien Millereb8b60e2010-08-31 22:41:14 +1000267
Damien Miller0a80ca12010-02-27 07:55:05 +1100268 if (a == NULL || b == NULL ||
269 key_type_plain(a->type) != key_type_plain(b->type))
270 return 0;
271
Damien Miller450a7a12000-03-26 13:04:51 +1000272 switch (a->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100273 case KEY_RSA1:
Damien Miller4e270b02010-04-16 15:56:21 +1000274 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100275 case KEY_RSA_CERT:
Damien Miller450a7a12000-03-26 13:04:51 +1000276 case KEY_RSA:
277 return a->rsa != NULL && b->rsa != NULL &&
278 BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
279 BN_cmp(a->rsa->n, b->rsa->n) == 0;
Damien Miller4e270b02010-04-16 15:56:21 +1000280 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100281 case KEY_DSA_CERT:
Damien Miller450a7a12000-03-26 13:04:51 +1000282 case KEY_DSA:
283 return a->dsa != NULL && b->dsa != NULL &&
284 BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
285 BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
286 BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
287 BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
Damien Miller6af914a2010-09-10 11:39:26 +1000288#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000289 case KEY_ECDSA_CERT:
290 case KEY_ECDSA:
291 if (a->ecdsa == NULL || b->ecdsa == NULL ||
292 EC_KEY_get0_public_key(a->ecdsa) == NULL ||
293 EC_KEY_get0_public_key(b->ecdsa) == NULL)
294 return 0;
295 if ((bnctx = BN_CTX_new()) == NULL)
296 fatal("%s: BN_CTX_new failed", __func__);
297 if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa),
298 EC_KEY_get0_group(b->ecdsa), bnctx) != 0 ||
299 EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa),
300 EC_KEY_get0_public_key(a->ecdsa),
301 EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) {
302 BN_CTX_free(bnctx);
303 return 0;
304 }
305 BN_CTX_free(bnctx);
306 return 1;
Damien Miller6af914a2010-09-10 11:39:26 +1000307#endif /* OPENSSL_HAS_ECC */
Damien Miller450a7a12000-03-26 13:04:51 +1000308 default:
Damien Millereba71ba2000-04-29 23:57:08 +1000309 fatal("key_equal: bad key type %d", a->type);
Damien Miller450a7a12000-03-26 13:04:51 +1000310 }
Damien Miller87dd5f22008-07-11 17:35:09 +1000311 /* NOTREACHED */
Damien Miller450a7a12000-03-26 13:04:51 +1000312}
313
Damien Miller0a80ca12010-02-27 07:55:05 +1100314int
315key_equal(const Key *a, const Key *b)
316{
317 if (a == NULL || b == NULL || a->type != b->type)
318 return 0;
319 if (key_is_cert(a)) {
320 if (!cert_compare(a->cert, b->cert))
321 return 0;
322 }
323 return key_equal_public(a, b);
324}
325
Damien Miller37876e92003-05-15 10:19:46 +1000326u_char*
Damien Miller0a80ca12010-02-27 07:55:05 +1100327key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length)
Damien Miller450a7a12000-03-26 13:04:51 +1000328{
Ben Lindstrom80cb27d2002-03-05 01:33:36 +0000329 const EVP_MD *md = NULL;
Ben Lindstromf0b48532001-03-12 02:59:31 +0000330 EVP_MD_CTX ctx;
Ben Lindstrom46c16222000-12-22 01:43:59 +0000331 u_char *blob = NULL;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000332 u_char *retval = NULL;
Ben Lindstrom90fd8142002-02-26 18:09:42 +0000333 u_int len = 0;
Damien Miller0a80ca12010-02-27 07:55:05 +1100334 int nlen, elen, otype;
Damien Miller450a7a12000-03-26 13:04:51 +1000335
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000336 *dgst_raw_length = 0;
337
Ben Lindstromf0b48532001-03-12 02:59:31 +0000338 switch (dgst_type) {
339 case SSH_FP_MD5:
340 md = EVP_md5();
341 break;
342 case SSH_FP_SHA1:
343 md = EVP_sha1();
344 break;
345 default:
346 fatal("key_fingerprint_raw: bad digest type %d",
347 dgst_type);
348 }
Damien Miller450a7a12000-03-26 13:04:51 +1000349 switch (k->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100350 case KEY_RSA1:
Damien Miller450a7a12000-03-26 13:04:51 +1000351 nlen = BN_num_bytes(k->rsa->n);
352 elen = BN_num_bytes(k->rsa->e);
353 len = nlen + elen;
Damien Millereba71ba2000-04-29 23:57:08 +1000354 blob = xmalloc(len);
355 BN_bn2bin(k->rsa->n, blob);
356 BN_bn2bin(k->rsa->e, blob + nlen);
Damien Miller450a7a12000-03-26 13:04:51 +1000357 break;
358 case KEY_DSA:
Damien Millereb8b60e2010-08-31 22:41:14 +1000359 case KEY_ECDSA:
Damien Miller0bc1bd82000-11-13 22:57:25 +1100360 case KEY_RSA:
361 key_to_blob(k, &blob, &len);
362 break;
Damien Miller4e270b02010-04-16 15:56:21 +1000363 case KEY_DSA_CERT_V00:
364 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100365 case KEY_DSA_CERT:
Damien Millereb8b60e2010-08-31 22:41:14 +1000366 case KEY_ECDSA_CERT:
Damien Miller0a80ca12010-02-27 07:55:05 +1100367 case KEY_RSA_CERT:
368 /* We want a fingerprint of the _key_ not of the cert */
369 otype = k->type;
370 k->type = key_type_plain(k->type);
371 key_to_blob(k, &blob, &len);
372 k->type = otype;
373 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100374 case KEY_UNSPEC:
375 return retval;
Damien Miller450a7a12000-03-26 13:04:51 +1000376 default:
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000377 fatal("key_fingerprint_raw: bad key type %d", k->type);
Damien Miller450a7a12000-03-26 13:04:51 +1000378 break;
379 }
Damien Millereba71ba2000-04-29 23:57:08 +1000380 if (blob != NULL) {
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000381 retval = xmalloc(EVP_MAX_MD_SIZE);
Damien Miller6536c7d2000-06-22 21:32:31 +1000382 EVP_DigestInit(&ctx, md);
383 EVP_DigestUpdate(&ctx, blob, len);
Damien Miller3672e4b2002-02-05 11:54:07 +1100384 EVP_DigestFinal(&ctx, retval, dgst_raw_length);
Damien Millereba71ba2000-04-29 23:57:08 +1000385 memset(blob, 0, len);
386 xfree(blob);
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000387 } else {
388 fatal("key_fingerprint_raw: blob is null");
Damien Miller450a7a12000-03-26 13:04:51 +1000389 }
390 return retval;
391}
392
Ben Lindstroma962c2f2002-07-04 00:14:17 +0000393static char *
394key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len)
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000395{
396 char *retval;
Damien Millereccb9de2005-06-17 12:59:34 +1000397 u_int i;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000398
Damien Miller07d86be2006-03-26 14:19:21 +1100399 retval = xcalloc(1, dgst_raw_len * 3 + 1);
Damien Miller9f0f5c62001-12-21 14:45:46 +1100400 for (i = 0; i < dgst_raw_len; i++) {
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000401 char hex[4];
402 snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
Darren Tucker29588612003-07-14 17:28:34 +1000403 strlcat(retval, hex, dgst_raw_len * 3 + 1);
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000404 }
Darren Tucker29588612003-07-14 17:28:34 +1000405
406 /* Remove the trailing ':' character */
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000407 retval[(dgst_raw_len * 3) - 1] = '\0';
408 return retval;
409}
410
Ben Lindstroma962c2f2002-07-04 00:14:17 +0000411static char *
412key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len)
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000413{
414 char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
415 char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
416 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000417 u_int i, j = 0, rounds, seed = 1;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000418 char *retval;
419
420 rounds = (dgst_raw_len / 2) + 1;
Damien Miller07d86be2006-03-26 14:19:21 +1100421 retval = xcalloc((rounds * 6), sizeof(char));
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000422 retval[j++] = 'x';
423 for (i = 0; i < rounds; i++) {
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000424 u_int idx0, idx1, idx2, idx3, idx4;
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000425 if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
426 idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000427 seed) % 6;
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000428 idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
429 idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000430 (seed / 6)) % 6;
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000431 retval[j++] = vowels[idx0];
432 retval[j++] = consonants[idx1];
433 retval[j++] = vowels[idx2];
434 if ((i + 1) < rounds) {
435 idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
436 idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
437 retval[j++] = consonants[idx3];
438 retval[j++] = '-';
439 retval[j++] = consonants[idx4];
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000440 seed = ((seed * 5) +
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000441 ((((u_int)(dgst_raw[2 * i])) * 7) +
442 ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000443 }
444 } else {
445 idx0 = seed % 6;
446 idx1 = 16;
447 idx2 = seed / 6;
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000448 retval[j++] = vowels[idx0];
449 retval[j++] = consonants[idx1];
450 retval[j++] = vowels[idx2];
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000451 }
452 }
Ben Lindstromcbe3ad22001-03-11 20:06:59 +0000453 retval[j++] = 'x';
454 retval[j++] = '\0';
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000455 return retval;
456}
457
Darren Tucker9c16ac92008-06-13 04:40:35 +1000458/*
459 * Draw an ASCII-Art representing the fingerprint so human brain can
460 * profit from its built-in pattern recognition ability.
461 * This technique is called "random art" and can be found in some
462 * scientific publications like this original paper:
463 *
464 * "Hash Visualization: a New Technique to improve Real-World Security",
465 * Perrig A. and Song D., 1999, International Workshop on Cryptographic
466 * Techniques and E-Commerce (CrypTEC '99)
467 * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
468 *
469 * The subject came up in a talk by Dan Kaminsky, too.
470 *
471 * If you see the picture is different, the key is different.
472 * If the picture looks the same, you still know nothing.
473 *
474 * The algorithm used here is a worm crawling over a discrete plane,
475 * leaving a trace (augmenting the field) everywhere it goes.
476 * Movement is taken from dgst_raw 2bit-wise. Bumping into walls
477 * makes the respective movement vector be ignored for this turn.
478 * Graphs are not unambiguous, because circles in graphs can be
479 * walked in either direction.
480 */
Darren Tucker987ac842008-06-13 04:54:40 +1000481
482/*
483 * Field sizes for the random art. Have to be odd, so the starting point
484 * can be in the exact middle of the picture, and FLDBASE should be >=8 .
485 * Else pictures would be too dense, and drawing the frame would
486 * fail, too, because the key type would not fit in anymore.
487 */
488#define FLDBASE 8
489#define FLDSIZE_Y (FLDBASE + 1)
490#define FLDSIZE_X (FLDBASE * 2 + 1)
Darren Tucker9c16ac92008-06-13 04:40:35 +1000491static char *
Darren Tucker987ac842008-06-13 04:54:40 +1000492key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k)
Darren Tucker9c16ac92008-06-13 04:40:35 +1000493{
494 /*
495 * Chars to be used after each other every time the worm
496 * intersects with itself. Matter of taste.
497 */
Darren Tucker4b3b9772008-06-13 04:55:10 +1000498 char *augmentation_string = " .o+=*BOX@%&#/^SE";
Darren Tucker9c16ac92008-06-13 04:40:35 +1000499 char *retval, *p;
Darren Tucker014d76f2008-06-13 04:43:51 +1000500 u_char field[FLDSIZE_X][FLDSIZE_Y];
Darren Tucker9c16ac92008-06-13 04:40:35 +1000501 u_int i, b;
502 int x, y;
Darren Tuckerd32b28a2008-06-13 04:45:50 +1000503 size_t len = strlen(augmentation_string) - 1;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000504
505 retval = xcalloc(1, (FLDSIZE_X + 3) * (FLDSIZE_Y + 2));
506
507 /* initialize field */
Darren Tucker014d76f2008-06-13 04:43:51 +1000508 memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
Darren Tucker9c16ac92008-06-13 04:40:35 +1000509 x = FLDSIZE_X / 2;
510 y = FLDSIZE_Y / 2;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000511
512 /* process raw key */
513 for (i = 0; i < dgst_raw_len; i++) {
514 int input;
515 /* each byte conveys four 2-bit move commands */
516 input = dgst_raw[i];
517 for (b = 0; b < 4; b++) {
518 /* evaluate 2 bit, rest is shifted later */
519 x += (input & 0x1) ? 1 : -1;
520 y += (input & 0x2) ? 1 : -1;
521
522 /* assure we are still in bounds */
523 x = MAX(x, 0);
524 y = MAX(y, 0);
525 x = MIN(x, FLDSIZE_X - 1);
526 y = MIN(y, FLDSIZE_Y - 1);
527
528 /* augment the field */
Damien Millerc6aadd92008-11-03 19:16:20 +1100529 if (field[x][y] < len - 2)
530 field[x][y]++;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000531 input = input >> 2;
532 }
533 }
Darren Tucker4b3b9772008-06-13 04:55:10 +1000534
535 /* mark starting point and end point*/
536 field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
537 field[x][y] = len;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000538
539 /* fill in retval */
Damien Miller007132a2008-06-29 22:45:37 +1000540 snprintf(retval, FLDSIZE_X, "+--[%4s %4u]", key_type(k), key_size(k));
Darren Tucker987ac842008-06-13 04:54:40 +1000541 p = strchr(retval, '\0');
Darren Tucker9c16ac92008-06-13 04:40:35 +1000542
543 /* output upper border */
Damien Miller007132a2008-06-29 22:45:37 +1000544 for (i = p - retval - 1; i < FLDSIZE_X; i++)
Darren Tucker9c16ac92008-06-13 04:40:35 +1000545 *p++ = '-';
546 *p++ = '+';
547 *p++ = '\n';
548
549 /* output content */
550 for (y = 0; y < FLDSIZE_Y; y++) {
551 *p++ = '|';
552 for (x = 0; x < FLDSIZE_X; x++)
Darren Tuckerd32b28a2008-06-13 04:45:50 +1000553 *p++ = augmentation_string[MIN(field[x][y], len)];
Darren Tucker9c16ac92008-06-13 04:40:35 +1000554 *p++ = '|';
555 *p++ = '\n';
556 }
557
558 /* output lower border */
559 *p++ = '+';
560 for (i = 0; i < FLDSIZE_X; i++)
561 *p++ = '-';
562 *p++ = '+';
563
564 return retval;
565}
566
Ben Lindstroma962c2f2002-07-04 00:14:17 +0000567char *
Damien Miller0a80ca12010-02-27 07:55:05 +1100568key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000569{
Ben Lindstroma3700052001-04-05 23:26:32 +0000570 char *retval = NULL;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000571 u_char *dgst_raw;
Damien Miller3672e4b2002-02-05 11:54:07 +1100572 u_int dgst_raw_len;
Damien Miller9f0f5c62001-12-21 14:45:46 +1100573
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000574 dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len);
575 if (!dgst_raw)
Ben Lindstromcfccef92001-03-13 04:57:58 +0000576 fatal("key_fingerprint: null from key_fingerprint_raw()");
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +0000577 switch (dgst_rep) {
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000578 case SSH_FP_HEX:
579 retval = key_fingerprint_hex(dgst_raw, dgst_raw_len);
580 break;
581 case SSH_FP_BUBBLEBABBLE:
582 retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
583 break;
Darren Tucker9c16ac92008-06-13 04:40:35 +1000584 case SSH_FP_RANDOMART:
Darren Tucker987ac842008-06-13 04:54:40 +1000585 retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k);
Darren Tucker9c16ac92008-06-13 04:40:35 +1000586 break;
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000587 default:
Damien Miller2f54ada2008-11-03 19:24:16 +1100588 fatal("key_fingerprint: bad digest representation %d",
Ben Lindstrom96e8ea62001-03-11 20:03:44 +0000589 dgst_rep);
590 break;
591 }
592 memset(dgst_raw, 0, dgst_raw_len);
593 xfree(dgst_raw);
594 return retval;
595}
596
Damien Miller450a7a12000-03-26 13:04:51 +1000597/*
598 * Reads a multiple-precision integer in decimal from the buffer, and advances
599 * the pointer. The integer must already be initialized. This function is
600 * permitted to modify the buffer. This leaves *cpp to point just beyond the
601 * last processed (and maybe modified) character. Note that this may modify
602 * the buffer containing the number.
603 */
Ben Lindstrombba81212001-06-25 05:01:22 +0000604static int
Damien Miller450a7a12000-03-26 13:04:51 +1000605read_bignum(char **cpp, BIGNUM * value)
606{
607 char *cp = *cpp;
608 int old;
609
610 /* Skip any leading whitespace. */
611 for (; *cp == ' ' || *cp == '\t'; cp++)
612 ;
613
614 /* Check that it begins with a decimal digit. */
615 if (*cp < '0' || *cp > '9')
616 return 0;
617
618 /* Save starting position. */
619 *cpp = cp;
620
621 /* Move forward until all decimal digits skipped. */
622 for (; *cp >= '0' && *cp <= '9'; cp++)
623 ;
624
625 /* Save the old terminating character, and replace it by \0. */
626 old = *cp;
627 *cp = 0;
628
629 /* Parse the number. */
630 if (BN_dec2bn(&value, *cpp) == 0)
631 return 0;
632
633 /* Restore old terminating character. */
634 *cp = old;
635
636 /* Move beyond the number and return success. */
637 *cpp = cp;
638 return 1;
639}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000640
Ben Lindstrombba81212001-06-25 05:01:22 +0000641static int
Damien Miller450a7a12000-03-26 13:04:51 +1000642write_bignum(FILE *f, BIGNUM *num)
643{
644 char *buf = BN_bn2dec(num);
645 if (buf == NULL) {
646 error("write_bignum: BN_bn2dec() failed");
647 return 0;
648 }
649 fprintf(f, " %s", buf);
Damien Milleraf3030f2001-10-10 15:00:49 +1000650 OPENSSL_free(buf);
Damien Miller450a7a12000-03-26 13:04:51 +1000651 return 1;
652}
Damien Miller0bc1bd82000-11-13 22:57:25 +1100653
Ben Lindstrom309f3d12001-09-20 00:55:53 +0000654/* returns 1 ok, -1 error */
Damien Miller0bc1bd82000-11-13 22:57:25 +1100655int
Damien Millereba71ba2000-04-29 23:57:08 +1000656key_read(Key *ret, char **cpp)
Damien Miller450a7a12000-03-26 13:04:51 +1000657{
Damien Millereba71ba2000-04-29 23:57:08 +1000658 Key *k;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100659 int success = -1;
660 char *cp, *space;
Darren Tucker8ccb7392010-09-10 12:28:24 +1000661 int len, n, type;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100662 u_int bits;
Ben Lindstrom46c16222000-12-22 01:43:59 +0000663 u_char *blob;
Darren Tucker8ccb7392010-09-10 12:28:24 +1000664#ifdef OPENSSL_HAS_ECC
665 int curve_nid = -1;
666#endif
Damien Millereba71ba2000-04-29 23:57:08 +1000667
668 cp = *cpp;
669
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +0000670 switch (ret->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100671 case KEY_RSA1:
Damien Millereba71ba2000-04-29 23:57:08 +1000672 /* Get number of bits. */
673 if (*cp < '0' || *cp > '9')
Damien Miller0bc1bd82000-11-13 22:57:25 +1100674 return -1; /* Bad bit count... */
Damien Millereba71ba2000-04-29 23:57:08 +1000675 for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
676 bits = 10 * bits + *cp - '0';
Damien Miller450a7a12000-03-26 13:04:51 +1000677 if (bits == 0)
Damien Miller0bc1bd82000-11-13 22:57:25 +1100678 return -1;
Damien Millereba71ba2000-04-29 23:57:08 +1000679 *cpp = cp;
Damien Miller450a7a12000-03-26 13:04:51 +1000680 /* Get public exponent, public modulus. */
681 if (!read_bignum(cpp, ret->rsa->e))
Damien Miller0bc1bd82000-11-13 22:57:25 +1100682 return -1;
Damien Miller450a7a12000-03-26 13:04:51 +1000683 if (!read_bignum(cpp, ret->rsa->n))
Damien Miller0bc1bd82000-11-13 22:57:25 +1100684 return -1;
Darren Tucker561724f2010-01-13 22:43:05 +1100685 /* validate the claimed number of bits */
686 if ((u_int)BN_num_bits(ret->rsa->n) != bits) {
687 verbose("key_read: claimed key size %d does not match "
688 "actual %d", bits, BN_num_bits(ret->rsa->n));
689 return -1;
690 }
Damien Miller0bc1bd82000-11-13 22:57:25 +1100691 success = 1;
Damien Miller450a7a12000-03-26 13:04:51 +1000692 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100693 case KEY_UNSPEC:
694 case KEY_RSA:
Damien Miller450a7a12000-03-26 13:04:51 +1000695 case KEY_DSA:
Damien Millereb8b60e2010-08-31 22:41:14 +1000696 case KEY_ECDSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000697 case KEY_DSA_CERT_V00:
698 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100699 case KEY_DSA_CERT:
Damien Millereb8b60e2010-08-31 22:41:14 +1000700 case KEY_ECDSA_CERT:
Damien Miller0a80ca12010-02-27 07:55:05 +1100701 case KEY_RSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +1100702 space = strchr(cp, ' ');
703 if (space == NULL) {
Damien Miller386f1f32003-02-24 11:54:57 +1100704 debug3("key_read: missing whitespace");
Damien Miller0bc1bd82000-11-13 22:57:25 +1100705 return -1;
706 }
707 *space = '\0';
708 type = key_type_from_name(cp);
Damien Miller6af914a2010-09-10 11:39:26 +1000709#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000710 if (key_type_plain(type) == KEY_ECDSA &&
711 (curve_nid = key_ecdsa_nid_from_name(cp)) == -1) {
712 debug("key_read: invalid curve");
713 return -1;
714 }
Damien Miller6af914a2010-09-10 11:39:26 +1000715#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +1100716 *space = ' ';
717 if (type == KEY_UNSPEC) {
Damien Miller386f1f32003-02-24 11:54:57 +1100718 debug3("key_read: missing keytype");
Damien Miller0bc1bd82000-11-13 22:57:25 +1100719 return -1;
720 }
721 cp = space+1;
722 if (*cp == '\0') {
723 debug3("key_read: short string");
724 return -1;
725 }
726 if (ret->type == KEY_UNSPEC) {
727 ret->type = type;
728 } else if (ret->type != type) {
729 /* is a key, but different type */
730 debug3("key_read: type mismatch");
Ben Lindstrom309f3d12001-09-20 00:55:53 +0000731 return -1;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100732 }
Damien Millereba71ba2000-04-29 23:57:08 +1000733 len = 2*strlen(cp);
734 blob = xmalloc(len);
735 n = uudecode(cp, blob, len);
Damien Millere247cc42000-05-07 12:03:14 +1000736 if (n < 0) {
Damien Millerb1715dc2000-05-30 13:44:51 +1000737 error("key_read: uudecode %s failed", cp);
Ben Lindstrom4cbc1812001-12-06 16:41:41 +0000738 xfree(blob);
Damien Miller0bc1bd82000-11-13 22:57:25 +1100739 return -1;
Damien Millere247cc42000-05-07 12:03:14 +1000740 }
Darren Tucker502d3842003-06-28 12:38:01 +1000741 k = key_from_blob(blob, (u_int)n);
Ben Lindstrom4cbc1812001-12-06 16:41:41 +0000742 xfree(blob);
Damien Millerb1715dc2000-05-30 13:44:51 +1000743 if (k == NULL) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100744 error("key_read: key_from_blob %s failed", cp);
745 return -1;
Damien Millerb1715dc2000-05-30 13:44:51 +1000746 }
Damien Miller0bc1bd82000-11-13 22:57:25 +1100747 if (k->type != type) {
748 error("key_read: type mismatch: encoding error");
749 key_free(k);
750 return -1;
751 }
Damien Miller6af914a2010-09-10 11:39:26 +1000752#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000753 if (key_type_plain(type) == KEY_ECDSA &&
754 curve_nid != k->ecdsa_nid) {
755 error("key_read: type mismatch: EC curve mismatch");
756 key_free(k);
757 return -1;
758 }
Damien Miller6af914a2010-09-10 11:39:26 +1000759#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +1100760/*XXXX*/
Damien Miller0a80ca12010-02-27 07:55:05 +1100761 if (key_is_cert(ret)) {
762 if (!key_is_cert(k)) {
763 error("key_read: loaded key is not a cert");
764 key_free(k);
765 return -1;
766 }
767 if (ret->cert != NULL)
768 cert_free(ret->cert);
769 ret->cert = k->cert;
770 k->cert = NULL;
771 }
772 if (key_type_plain(ret->type) == KEY_RSA) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100773 if (ret->rsa != NULL)
774 RSA_free(ret->rsa);
775 ret->rsa = k->rsa;
776 k->rsa = NULL;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100777#ifdef DEBUG_PK
778 RSA_print_fp(stderr, ret->rsa, 8);
779#endif
Damien Miller0a80ca12010-02-27 07:55:05 +1100780 }
781 if (key_type_plain(ret->type) == KEY_DSA) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100782 if (ret->dsa != NULL)
783 DSA_free(ret->dsa);
784 ret->dsa = k->dsa;
785 k->dsa = NULL;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100786#ifdef DEBUG_PK
787 DSA_print_fp(stderr, ret->dsa, 8);
788#endif
789 }
Damien Miller6af914a2010-09-10 11:39:26 +1000790#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000791 if (key_type_plain(ret->type) == KEY_ECDSA) {
792 if (ret->ecdsa != NULL)
793 EC_KEY_free(ret->ecdsa);
794 ret->ecdsa = k->ecdsa;
795 ret->ecdsa_nid = k->ecdsa_nid;
796 k->ecdsa = NULL;
797 k->ecdsa_nid = -1;
798#ifdef DEBUG_PK
799 key_dump_ec_key(ret->ecdsa);
800#endif
801 }
Damien Miller6af914a2010-09-10 11:39:26 +1000802#endif
Damien Miller0a80ca12010-02-27 07:55:05 +1100803 success = 1;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100804/*XXXX*/
Ben Lindstrom4cbc1812001-12-06 16:41:41 +0000805 key_free(k);
Damien Miller0bc1bd82000-11-13 22:57:25 +1100806 if (success != 1)
807 break;
Damien Millerb1715dc2000-05-30 13:44:51 +1000808 /* advance cp: skip whitespace and data */
809 while (*cp == ' ' || *cp == '\t')
810 cp++;
811 while (*cp != '\0' && *cp != ' ' && *cp != '\t')
812 cp++;
813 *cpp = cp;
Damien Miller450a7a12000-03-26 13:04:51 +1000814 break;
815 default:
Damien Millereba71ba2000-04-29 23:57:08 +1000816 fatal("key_read: bad key type: %d", ret->type);
Damien Miller450a7a12000-03-26 13:04:51 +1000817 break;
818 }
Damien Miller0bc1bd82000-11-13 22:57:25 +1100819 return success;
Damien Miller450a7a12000-03-26 13:04:51 +1000820}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000821
Damien Miller450a7a12000-03-26 13:04:51 +1000822int
Damien Millerf58b58c2003-11-17 21:18:23 +1100823key_write(const Key *key, FILE *f)
Damien Miller450a7a12000-03-26 13:04:51 +1000824{
Ben Lindstrom90fd8142002-02-26 18:09:42 +0000825 int n, success = 0;
826 u_int len, bits = 0;
Damien Millera10f5612002-09-12 09:49:15 +1000827 u_char *blob;
828 char *uu;
Damien Miller450a7a12000-03-26 13:04:51 +1000829
Damien Miller0a80ca12010-02-27 07:55:05 +1100830 if (key_is_cert(key)) {
831 if (key->cert == NULL) {
832 error("%s: no cert data", __func__);
833 return 0;
834 }
835 if (buffer_len(&key->cert->certblob) == 0) {
836 error("%s: no signed certificate blob", __func__);
837 return 0;
838 }
839 }
840
841 switch (key->type) {
842 case KEY_RSA1:
843 if (key->rsa == NULL)
844 return 0;
Damien Miller450a7a12000-03-26 13:04:51 +1000845 /* size of modulus 'n' */
846 bits = BN_num_bits(key->rsa->n);
847 fprintf(f, "%u", bits);
848 if (write_bignum(f, key->rsa->e) &&
Damien Miller0a80ca12010-02-27 07:55:05 +1100849 write_bignum(f, key->rsa->n))
850 return 1;
851 error("key_write: failed for RSA key");
852 return 0;
853 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000854 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100855 case KEY_DSA_CERT:
856 if (key->dsa == NULL)
857 return 0;
858 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000859#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000860 case KEY_ECDSA:
861 case KEY_ECDSA_CERT:
862 if (key->ecdsa == NULL)
863 return 0;
864 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000865#endif
Damien Miller0a80ca12010-02-27 07:55:05 +1100866 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000867 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100868 case KEY_RSA_CERT:
869 if (key->rsa == NULL)
870 return 0;
871 break;
872 default:
873 return 0;
Damien Miller450a7a12000-03-26 13:04:51 +1000874 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100875
876 key_to_blob(key, &blob, &len);
877 uu = xmalloc(2*len);
878 n = uuencode(blob, len, uu, 2*len);
879 if (n > 0) {
880 fprintf(f, "%s %s", key_ssh_name(key), uu);
881 success = 1;
882 }
883 xfree(blob);
884 xfree(uu);
885
Damien Miller450a7a12000-03-26 13:04:51 +1000886 return success;
887}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000888
Damien Millerf58b58c2003-11-17 21:18:23 +1100889const char *
890key_type(const Key *k)
Damien Millere247cc42000-05-07 12:03:14 +1000891{
892 switch (k->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100893 case KEY_RSA1:
894 return "RSA1";
Damien Millere247cc42000-05-07 12:03:14 +1000895 case KEY_RSA:
896 return "RSA";
Damien Millere247cc42000-05-07 12:03:14 +1000897 case KEY_DSA:
898 return "DSA";
Damien Miller6af914a2010-09-10 11:39:26 +1000899#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000900 case KEY_ECDSA:
901 return "ECDSA";
Damien Miller6af914a2010-09-10 11:39:26 +1000902#endif
Damien Miller4e270b02010-04-16 15:56:21 +1000903 case KEY_RSA_CERT_V00:
904 return "RSA-CERT-V00";
905 case KEY_DSA_CERT_V00:
906 return "DSA-CERT-V00";
Damien Miller0a80ca12010-02-27 07:55:05 +1100907 case KEY_RSA_CERT:
908 return "RSA-CERT";
909 case KEY_DSA_CERT:
910 return "DSA-CERT";
Damien Miller6af914a2010-09-10 11:39:26 +1000911#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000912 case KEY_ECDSA_CERT:
913 return "ECDSA-CERT";
Damien Miller6af914a2010-09-10 11:39:26 +1000914#endif
Damien Millere247cc42000-05-07 12:03:14 +1000915 }
916 return "unknown";
917}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000918
Damien Millerf58b58c2003-11-17 21:18:23 +1100919const char *
Damien Miller1cfbfaf2010-03-22 05:58:24 +1100920key_cert_type(const Key *k)
921{
922 switch (k->cert->type) {
923 case SSH2_CERT_TYPE_USER:
924 return "user";
925 case SSH2_CERT_TYPE_HOST:
926 return "host";
927 default:
928 return "unknown";
929 }
930}
931
Damien Millereb8b60e2010-08-31 22:41:14 +1000932static const char *
933key_ssh_name_from_type_nid(int type, int nid)
Damien Miller0bc1bd82000-11-13 22:57:25 +1100934{
Damien Millereb8b60e2010-08-31 22:41:14 +1000935 switch (type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100936 case KEY_RSA:
937 return "ssh-rsa";
Damien Miller0bc1bd82000-11-13 22:57:25 +1100938 case KEY_DSA:
939 return "ssh-dss";
Damien Miller4e270b02010-04-16 15:56:21 +1000940 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100941 return "ssh-rsa-cert-v00@openssh.com";
Damien Miller4e270b02010-04-16 15:56:21 +1000942 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100943 return "ssh-dss-cert-v00@openssh.com";
Damien Miller4e270b02010-04-16 15:56:21 +1000944 case KEY_RSA_CERT:
945 return "ssh-rsa-cert-v01@openssh.com";
946 case KEY_DSA_CERT:
947 return "ssh-dss-cert-v01@openssh.com";
Damien Miller6af914a2010-09-10 11:39:26 +1000948#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +1000949 case KEY_ECDSA:
950 switch (nid) {
951 case NID_X9_62_prime256v1:
952 return "ecdsa-sha2-nistp256";
953 case NID_secp384r1:
954 return "ecdsa-sha2-nistp384";
955 case NID_secp521r1:
956 return "ecdsa-sha2-nistp521";
957 default:
958 break;
959 }
960 break;
961 case KEY_ECDSA_CERT:
962 switch (nid) {
963 case NID_X9_62_prime256v1:
964 return "ecdsa-sha2-nistp256-cert-v01@openssh.com";
965 case NID_secp384r1:
966 return "ecdsa-sha2-nistp384-cert-v01@openssh.com";
967 case NID_secp521r1:
968 return "ecdsa-sha2-nistp521-cert-v01@openssh.com";
969 default:
970 break;
971 }
972 break;
Damien Miller6af914a2010-09-10 11:39:26 +1000973#endif /* OPENSSL_HAS_ECC */
Damien Miller0bc1bd82000-11-13 22:57:25 +1100974 }
975 return "ssh-unknown";
976}
Ben Lindstrom836f0e92002-06-23 21:21:30 +0000977
Damien Millereb8b60e2010-08-31 22:41:14 +1000978const char *
979key_ssh_name(const Key *k)
980{
981 return key_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
982}
983
984const char *
985key_ssh_name_plain(const Key *k)
986{
987 return key_ssh_name_from_type_nid(key_type_plain(k->type),
988 k->ecdsa_nid);
989}
990
Damien Miller0bc1bd82000-11-13 22:57:25 +1100991u_int
Damien Millerf58b58c2003-11-17 21:18:23 +1100992key_size(const Key *k)
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +0000993{
Damien Millerad833b32000-08-23 10:46:23 +1000994 switch (k->type) {
Damien Miller0bc1bd82000-11-13 22:57:25 +1100995 case KEY_RSA1:
Damien Millerad833b32000-08-23 10:46:23 +1000996 case KEY_RSA:
Damien Miller4e270b02010-04-16 15:56:21 +1000997 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +1100998 case KEY_RSA_CERT:
Damien Millerad833b32000-08-23 10:46:23 +1000999 return BN_num_bits(k->rsa->n);
Damien Millerad833b32000-08-23 10:46:23 +10001000 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +10001001 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001002 case KEY_DSA_CERT:
Damien Millerad833b32000-08-23 10:46:23 +10001003 return BN_num_bits(k->dsa->p);
Damien Miller6af914a2010-09-10 11:39:26 +10001004#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001005 case KEY_ECDSA:
1006 case KEY_ECDSA_CERT:
Damien Miller041ab7c2010-09-10 11:23:34 +10001007 return key_curve_nid_to_bits(k->ecdsa_nid);
Damien Miller6af914a2010-09-10 11:39:26 +10001008#endif
Damien Millerad833b32000-08-23 10:46:23 +10001009 }
1010 return 0;
1011}
Damien Miller0bc1bd82000-11-13 22:57:25 +11001012
Ben Lindstrombba81212001-06-25 05:01:22 +00001013static RSA *
Ben Lindstrom46c16222000-12-22 01:43:59 +00001014rsa_generate_private_key(u_int bits)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001015{
Damien Miller4499f4c2010-11-20 15:15:49 +11001016 RSA *private = RSA_new();
1017 BIGNUM *f4 = BN_new();
Damien Miller69b72032006-03-26 14:02:35 +11001018
Kevin Stevesef4eea92001-02-05 12:42:17 +00001019 if (private == NULL)
Damien Miller4499f4c2010-11-20 15:15:49 +11001020 fatal("%s: RSA_new failed", __func__);
1021 if (f4 == NULL)
1022 fatal("%s: BN_new failed", __func__);
1023 if (!BN_set_word(f4, RSA_F4))
1024 fatal("%s: BN_new failed", __func__);
1025 if (!RSA_generate_key_ex(private, bits, f4, NULL))
1026 fatal("%s: key generation failed.", __func__);
1027 BN_free(f4);
Kevin Stevesef4eea92001-02-05 12:42:17 +00001028 return private;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001029}
1030
Ben Lindstrombba81212001-06-25 05:01:22 +00001031static DSA*
Ben Lindstrom46c16222000-12-22 01:43:59 +00001032dsa_generate_private_key(u_int bits)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001033{
Damien Miller4499f4c2010-11-20 15:15:49 +11001034 DSA *private = DSA_new();
Damien Miller69b72032006-03-26 14:02:35 +11001035
Damien Miller0bc1bd82000-11-13 22:57:25 +11001036 if (private == NULL)
Damien Miller4499f4c2010-11-20 15:15:49 +11001037 fatal("%s: DSA_new failed", __func__);
1038 if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL,
1039 NULL, NULL))
1040 fatal("%s: DSA_generate_parameters failed", __func__);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001041 if (!DSA_generate_key(private))
Damien Miller4499f4c2010-11-20 15:15:49 +11001042 fatal("%s: DSA_generate_key failed.", __func__);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001043 return private;
1044}
1045
Damien Millereb8b60e2010-08-31 22:41:14 +10001046int
1047key_ecdsa_bits_to_nid(int bits)
1048{
1049 switch (bits) {
Damien Miller6af914a2010-09-10 11:39:26 +10001050#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001051 case 256:
1052 return NID_X9_62_prime256v1;
1053 case 384:
1054 return NID_secp384r1;
1055 case 521:
1056 return NID_secp521r1;
Damien Miller6af914a2010-09-10 11:39:26 +10001057#endif
Damien Millereb8b60e2010-08-31 22:41:14 +10001058 default:
1059 return -1;
1060 }
1061}
1062
Damien Miller6af914a2010-09-10 11:39:26 +10001063#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001064int
Damien Millerb472a902010-11-05 10:19:49 +11001065key_ecdsa_key_to_nid(EC_KEY *k)
Damien Millereb8b60e2010-08-31 22:41:14 +10001066{
1067 EC_GROUP *eg;
1068 int nids[] = {
1069 NID_X9_62_prime256v1,
1070 NID_secp384r1,
1071 NID_secp521r1,
1072 -1
1073 };
Damien Millerb472a902010-11-05 10:19:49 +11001074 int nid;
Damien Millereb8b60e2010-08-31 22:41:14 +10001075 u_int i;
1076 BN_CTX *bnctx;
Damien Millerb472a902010-11-05 10:19:49 +11001077 const EC_GROUP *g = EC_KEY_get0_group(k);
Damien Millereb8b60e2010-08-31 22:41:14 +10001078
Damien Millerb472a902010-11-05 10:19:49 +11001079 /*
1080 * The group may be stored in a ASN.1 encoded private key in one of two
1081 * ways: as a "named group", which is reconstituted by ASN.1 object ID
1082 * or explicit group parameters encoded into the key blob. Only the
1083 * "named group" case sets the group NID for us, but we can figure
1084 * it out for the other case by comparing against all the groups that
1085 * are supported.
1086 */
1087 if ((nid = EC_GROUP_get_curve_name(g)) > 0)
1088 return nid;
Damien Millereb8b60e2010-08-31 22:41:14 +10001089 if ((bnctx = BN_CTX_new()) == NULL)
1090 fatal("%s: BN_CTX_new() failed", __func__);
1091 for (i = 0; nids[i] != -1; i++) {
1092 if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL)
1093 fatal("%s: EC_GROUP_new_by_curve_name failed",
1094 __func__);
Damien Millerb472a902010-11-05 10:19:49 +11001095 if (EC_GROUP_cmp(g, eg, bnctx) == 0)
Damien Millereb8b60e2010-08-31 22:41:14 +10001096 break;
Damien Millereb8b60e2010-08-31 22:41:14 +10001097 EC_GROUP_free(eg);
1098 }
1099 BN_CTX_free(bnctx);
1100 debug3("%s: nid = %d", __func__, nids[i]);
Damien Millerb472a902010-11-05 10:19:49 +11001101 if (nids[i] != -1) {
1102 /* Use the group with the NID attached */
1103 EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
1104 if (EC_KEY_set_group(k, eg) != 1)
1105 fatal("%s: EC_KEY_set_group", __func__);
1106 }
Damien Millereb8b60e2010-08-31 22:41:14 +10001107 return nids[i];
1108}
1109
1110static EC_KEY*
1111ecdsa_generate_private_key(u_int bits, int *nid)
1112{
1113 EC_KEY *private;
1114
1115 if ((*nid = key_ecdsa_bits_to_nid(bits)) == -1)
1116 fatal("%s: invalid key length", __func__);
1117 if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL)
1118 fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
1119 if (EC_KEY_generate_key(private) != 1)
1120 fatal("%s: EC_KEY_generate_key failed", __func__);
Damien Millerb472a902010-11-05 10:19:49 +11001121 EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE);
Damien Millereb8b60e2010-08-31 22:41:14 +10001122 return private;
1123}
Damien Miller6af914a2010-09-10 11:39:26 +10001124#endif /* OPENSSL_HAS_ECC */
Damien Millereb8b60e2010-08-31 22:41:14 +10001125
Damien Miller0bc1bd82000-11-13 22:57:25 +11001126Key *
Ben Lindstrom46c16222000-12-22 01:43:59 +00001127key_generate(int type, u_int bits)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001128{
1129 Key *k = key_new(KEY_UNSPEC);
1130 switch (type) {
Kevin Stevesef4eea92001-02-05 12:42:17 +00001131 case KEY_DSA:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001132 k->dsa = dsa_generate_private_key(bits);
1133 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001134#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001135 case KEY_ECDSA:
1136 k->ecdsa = ecdsa_generate_private_key(bits, &k->ecdsa_nid);
1137 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001138#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +11001139 case KEY_RSA:
1140 case KEY_RSA1:
1141 k->rsa = rsa_generate_private_key(bits);
1142 break;
Damien Miller4e270b02010-04-16 15:56:21 +10001143 case KEY_RSA_CERT_V00:
1144 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001145 case KEY_RSA_CERT:
1146 case KEY_DSA_CERT:
1147 fatal("key_generate: cert keys cannot be generated directly");
Damien Miller0bc1bd82000-11-13 22:57:25 +11001148 default:
Kevin Stevesef4eea92001-02-05 12:42:17 +00001149 fatal("key_generate: unknown type %d", type);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001150 }
Kevin Stevesef4eea92001-02-05 12:42:17 +00001151 k->type = type;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001152 return k;
1153}
1154
Damien Miller0a80ca12010-02-27 07:55:05 +11001155void
1156key_cert_copy(const Key *from_key, struct Key *to_key)
1157{
1158 u_int i;
1159 const struct KeyCert *from;
1160 struct KeyCert *to;
1161
1162 if (to_key->cert != NULL) {
1163 cert_free(to_key->cert);
1164 to_key->cert = NULL;
1165 }
1166
1167 if ((from = from_key->cert) == NULL)
1168 return;
1169
1170 to = to_key->cert = cert_new();
1171
1172 buffer_append(&to->certblob, buffer_ptr(&from->certblob),
1173 buffer_len(&from->certblob));
1174
Damien Miller4e270b02010-04-16 15:56:21 +10001175 buffer_append(&to->critical,
1176 buffer_ptr(&from->critical), buffer_len(&from->critical));
1177 buffer_append(&to->extensions,
1178 buffer_ptr(&from->extensions), buffer_len(&from->extensions));
Damien Miller0a80ca12010-02-27 07:55:05 +11001179
Damien Miller4e270b02010-04-16 15:56:21 +10001180 to->serial = from->serial;
Damien Miller0a80ca12010-02-27 07:55:05 +11001181 to->type = from->type;
1182 to->key_id = from->key_id == NULL ? NULL : xstrdup(from->key_id);
1183 to->valid_after = from->valid_after;
1184 to->valid_before = from->valid_before;
1185 to->signature_key = from->signature_key == NULL ?
1186 NULL : key_from_private(from->signature_key);
1187
1188 to->nprincipals = from->nprincipals;
1189 if (to->nprincipals > CERT_MAX_PRINCIPALS)
1190 fatal("%s: nprincipals (%u) > CERT_MAX_PRINCIPALS (%u)",
1191 __func__, to->nprincipals, CERT_MAX_PRINCIPALS);
1192 if (to->nprincipals > 0) {
1193 to->principals = xcalloc(from->nprincipals,
1194 sizeof(*to->principals));
1195 for (i = 0; i < to->nprincipals; i++)
1196 to->principals[i] = xstrdup(from->principals[i]);
1197 }
1198}
1199
Damien Miller0bc1bd82000-11-13 22:57:25 +11001200Key *
Damien Millerf58b58c2003-11-17 21:18:23 +11001201key_from_private(const Key *k)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001202{
1203 Key *n = NULL;
1204 switch (k->type) {
Kevin Stevesef4eea92001-02-05 12:42:17 +00001205 case KEY_DSA:
Damien Miller4e270b02010-04-16 15:56:21 +10001206 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001207 case KEY_DSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001208 n = key_new(k->type);
Darren Tucker0bc85572006-11-07 23:14:41 +11001209 if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
1210 (BN_copy(n->dsa->q, k->dsa->q) == NULL) ||
1211 (BN_copy(n->dsa->g, k->dsa->g) == NULL) ||
1212 (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL))
1213 fatal("key_from_private: BN_copy failed");
Damien Miller0bc1bd82000-11-13 22:57:25 +11001214 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001215#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001216 case KEY_ECDSA:
1217 case KEY_ECDSA_CERT:
1218 n = key_new(k->type);
1219 n->ecdsa_nid = k->ecdsa_nid;
1220 if ((n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL)
1221 fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
1222 if (EC_KEY_set_public_key(n->ecdsa,
1223 EC_KEY_get0_public_key(k->ecdsa)) != 1)
1224 fatal("%s: EC_KEY_set_public_key failed", __func__);
1225 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001226#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +11001227 case KEY_RSA:
1228 case KEY_RSA1:
Damien Miller4e270b02010-04-16 15:56:21 +10001229 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001230 case KEY_RSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001231 n = key_new(k->type);
Darren Tucker0bc85572006-11-07 23:14:41 +11001232 if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
1233 (BN_copy(n->rsa->e, k->rsa->e) == NULL))
1234 fatal("key_from_private: BN_copy failed");
Damien Miller0bc1bd82000-11-13 22:57:25 +11001235 break;
1236 default:
Kevin Stevesef4eea92001-02-05 12:42:17 +00001237 fatal("key_from_private: unknown type %d", k->type);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001238 break;
1239 }
Damien Miller0a80ca12010-02-27 07:55:05 +11001240 if (key_is_cert(k))
1241 key_cert_copy(k, n);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001242 return n;
1243}
1244
1245int
1246key_type_from_name(char *name)
1247{
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001248 if (strcmp(name, "rsa1") == 0) {
Damien Miller0bc1bd82000-11-13 22:57:25 +11001249 return KEY_RSA1;
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001250 } else if (strcmp(name, "rsa") == 0) {
Damien Miller0bc1bd82000-11-13 22:57:25 +11001251 return KEY_RSA;
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001252 } else if (strcmp(name, "dsa") == 0) {
Damien Miller0bc1bd82000-11-13 22:57:25 +11001253 return KEY_DSA;
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001254 } else if (strcmp(name, "ssh-rsa") == 0) {
Damien Miller0bc1bd82000-11-13 22:57:25 +11001255 return KEY_RSA;
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001256 } else if (strcmp(name, "ssh-dss") == 0) {
Damien Miller0bc1bd82000-11-13 22:57:25 +11001257 return KEY_DSA;
Damien Miller6af914a2010-09-10 11:39:26 +10001258#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001259 } else if (strcmp(name, "ecdsa") == 0 ||
1260 strcmp(name, "ecdsa-sha2-nistp256") == 0 ||
1261 strcmp(name, "ecdsa-sha2-nistp384") == 0 ||
1262 strcmp(name, "ecdsa-sha2-nistp521") == 0) {
1263 return KEY_ECDSA;
Damien Miller6af914a2010-09-10 11:39:26 +10001264#endif
Damien Miller0a80ca12010-02-27 07:55:05 +11001265 } else if (strcmp(name, "ssh-rsa-cert-v00@openssh.com") == 0) {
Damien Miller4e270b02010-04-16 15:56:21 +10001266 return KEY_RSA_CERT_V00;
Damien Miller0a80ca12010-02-27 07:55:05 +11001267 } else if (strcmp(name, "ssh-dss-cert-v00@openssh.com") == 0) {
Damien Miller4e270b02010-04-16 15:56:21 +10001268 return KEY_DSA_CERT_V00;
1269 } else if (strcmp(name, "ssh-rsa-cert-v01@openssh.com") == 0) {
1270 return KEY_RSA_CERT;
1271 } else if (strcmp(name, "ssh-dss-cert-v01@openssh.com") == 0) {
Damien Miller0a80ca12010-02-27 07:55:05 +11001272 return KEY_DSA_CERT;
Damien Miller6af914a2010-09-10 11:39:26 +10001273#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001274 } else if (strcmp(name, "ecdsa-sha2-nistp256-cert-v01@openssh.com") == 0 ||
1275 strcmp(name, "ecdsa-sha2-nistp384-cert-v01@openssh.com") == 0 ||
Damien Miller6af914a2010-09-10 11:39:26 +10001276 strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) {
Damien Millereb8b60e2010-08-31 22:41:14 +10001277 return KEY_ECDSA_CERT;
Damien Miller6af914a2010-09-10 11:39:26 +10001278#endif
1279 }
Damien Millereb8b60e2010-08-31 22:41:14 +10001280
Ben Lindstromb54873a2001-03-11 20:01:55 +00001281 debug2("key_type_from_name: unknown key type '%s'", name);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001282 return KEY_UNSPEC;
1283}
1284
Ben Lindstrom982dbbc2001-04-17 18:11:36 +00001285int
Damien Millereb8b60e2010-08-31 22:41:14 +10001286key_ecdsa_nid_from_name(const char *name)
1287{
Damien Miller6af914a2010-09-10 11:39:26 +10001288#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001289 if (strcmp(name, "ecdsa-sha2-nistp256") == 0 ||
1290 strcmp(name, "ecdsa-sha2-nistp256-cert-v01@openssh.com") == 0)
1291 return NID_X9_62_prime256v1;
1292 if (strcmp(name, "ecdsa-sha2-nistp384") == 0 ||
1293 strcmp(name, "ecdsa-sha2-nistp384-cert-v01@openssh.com") == 0)
1294 return NID_secp384r1;
1295 if (strcmp(name, "ecdsa-sha2-nistp521") == 0 ||
1296 strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0)
1297 return NID_secp521r1;
Damien Miller6af914a2010-09-10 11:39:26 +10001298#endif /* OPENSSL_HAS_ECC */
Damien Millereb8b60e2010-08-31 22:41:14 +10001299
1300 debug2("%s: unknown/non-ECDSA key type '%s'", __func__, name);
1301 return -1;
1302}
1303
1304int
Ben Lindstrom982dbbc2001-04-17 18:11:36 +00001305key_names_valid2(const char *names)
1306{
1307 char *s, *cp, *p;
1308
1309 if (names == NULL || strcmp(names, "") == 0)
1310 return 0;
1311 s = cp = xstrdup(names);
1312 for ((p = strsep(&cp, ",")); p && *p != '\0';
Damien Miller9f0f5c62001-12-21 14:45:46 +11001313 (p = strsep(&cp, ","))) {
Ben Lindstrom982dbbc2001-04-17 18:11:36 +00001314 switch (key_type_from_name(p)) {
1315 case KEY_RSA1:
1316 case KEY_UNSPEC:
1317 xfree(s);
1318 return 0;
1319 }
1320 }
1321 debug3("key names ok: [%s]", names);
1322 xfree(s);
1323 return 1;
1324}
1325
Damien Miller0a80ca12010-02-27 07:55:05 +11001326static int
1327cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)
1328{
Damien Miller4e270b02010-04-16 15:56:21 +10001329 u_char *principals, *critical, *exts, *sig_key, *sig;
1330 u_int signed_len, plen, clen, sklen, slen, kidlen, elen;
Damien Miller0a80ca12010-02-27 07:55:05 +11001331 Buffer tmp;
1332 char *principal;
1333 int ret = -1;
Damien Miller4e270b02010-04-16 15:56:21 +10001334 int v00 = key->type == KEY_DSA_CERT_V00 ||
1335 key->type == KEY_RSA_CERT_V00;
Damien Miller0a80ca12010-02-27 07:55:05 +11001336
1337 buffer_init(&tmp);
1338
1339 /* Copy the entire key blob for verification and later serialisation */
1340 buffer_append(&key->cert->certblob, blob, blen);
1341
Damien Miller4e270b02010-04-16 15:56:21 +10001342 elen = 0; /* Not touched for v00 certs */
1343 principals = exts = critical = sig_key = sig = NULL;
1344 if ((!v00 && buffer_get_int64_ret(&key->cert->serial, b) != 0) ||
1345 buffer_get_int_ret(&key->cert->type, b) != 0 ||
Damien Millerda108ec2010-08-31 22:36:39 +10001346 (key->cert->key_id = buffer_get_cstring_ret(b, &kidlen)) == NULL ||
Damien Miller0a80ca12010-02-27 07:55:05 +11001347 (principals = buffer_get_string_ret(b, &plen)) == NULL ||
1348 buffer_get_int64_ret(&key->cert->valid_after, b) != 0 ||
1349 buffer_get_int64_ret(&key->cert->valid_before, b) != 0 ||
Damien Miller4e270b02010-04-16 15:56:21 +10001350 (critical = buffer_get_string_ret(b, &clen)) == NULL ||
1351 (!v00 && (exts = buffer_get_string_ret(b, &elen)) == NULL) ||
1352 (v00 && buffer_get_string_ptr_ret(b, NULL) == NULL) || /* nonce */
1353 buffer_get_string_ptr_ret(b, NULL) == NULL || /* reserved */
Damien Miller0a80ca12010-02-27 07:55:05 +11001354 (sig_key = buffer_get_string_ret(b, &sklen)) == NULL) {
1355 error("%s: parse error", __func__);
1356 goto out;
1357 }
1358
1359 /* Signature is left in the buffer so we can calculate this length */
1360 signed_len = buffer_len(&key->cert->certblob) - buffer_len(b);
1361
1362 if ((sig = buffer_get_string_ret(b, &slen)) == NULL) {
1363 error("%s: parse error", __func__);
1364 goto out;
1365 }
1366
1367 if (key->cert->type != SSH2_CERT_TYPE_USER &&
1368 key->cert->type != SSH2_CERT_TYPE_HOST) {
1369 error("Unknown certificate type %u", key->cert->type);
1370 goto out;
1371 }
1372
1373 buffer_append(&tmp, principals, plen);
1374 while (buffer_len(&tmp) > 0) {
1375 if (key->cert->nprincipals >= CERT_MAX_PRINCIPALS) {
Damien Miller41396572010-03-04 21:51:11 +11001376 error("%s: Too many principals", __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001377 goto out;
1378 }
Damien Millerda108ec2010-08-31 22:36:39 +10001379 if ((principal = buffer_get_cstring_ret(&tmp, &plen)) == NULL) {
Damien Miller41396572010-03-04 21:51:11 +11001380 error("%s: Principals data invalid", __func__);
1381 goto out;
1382 }
Damien Miller0a80ca12010-02-27 07:55:05 +11001383 key->cert->principals = xrealloc(key->cert->principals,
1384 key->cert->nprincipals + 1, sizeof(*key->cert->principals));
1385 key->cert->principals[key->cert->nprincipals++] = principal;
1386 }
1387
1388 buffer_clear(&tmp);
1389
Damien Miller4e270b02010-04-16 15:56:21 +10001390 buffer_append(&key->cert->critical, critical, clen);
1391 buffer_append(&tmp, critical, clen);
Damien Miller0a80ca12010-02-27 07:55:05 +11001392 /* validate structure */
1393 while (buffer_len(&tmp) != 0) {
Damien Miller2befbad2010-03-04 21:52:18 +11001394 if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||
1395 buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {
Damien Miller4e270b02010-04-16 15:56:21 +10001396 error("%s: critical option data invalid", __func__);
1397 goto out;
1398 }
1399 }
1400 buffer_clear(&tmp);
1401
1402 buffer_append(&key->cert->extensions, exts, elen);
1403 buffer_append(&tmp, exts, elen);
1404 /* validate structure */
1405 while (buffer_len(&tmp) != 0) {
1406 if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||
1407 buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {
1408 error("%s: extension data invalid", __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001409 goto out;
1410 }
1411 }
1412 buffer_clear(&tmp);
1413
1414 if ((key->cert->signature_key = key_from_blob(sig_key,
1415 sklen)) == NULL) {
Damien Miller41396572010-03-04 21:51:11 +11001416 error("%s: Signature key invalid", __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001417 goto out;
1418 }
1419 if (key->cert->signature_key->type != KEY_RSA &&
Damien Millereb8b60e2010-08-31 22:41:14 +10001420 key->cert->signature_key->type != KEY_DSA &&
1421 key->cert->signature_key->type != KEY_ECDSA) {
Damien Miller41396572010-03-04 21:51:11 +11001422 error("%s: Invalid signature key type %s (%d)", __func__,
Damien Miller0a80ca12010-02-27 07:55:05 +11001423 key_type(key->cert->signature_key),
1424 key->cert->signature_key->type);
1425 goto out;
1426 }
1427
1428 switch (key_verify(key->cert->signature_key, sig, slen,
1429 buffer_ptr(&key->cert->certblob), signed_len)) {
1430 case 1:
Damien Miller41396572010-03-04 21:51:11 +11001431 ret = 0;
Damien Miller0a80ca12010-02-27 07:55:05 +11001432 break; /* Good signature */
1433 case 0:
Damien Miller41396572010-03-04 21:51:11 +11001434 error("%s: Invalid signature on certificate", __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001435 goto out;
1436 case -1:
Damien Miller41396572010-03-04 21:51:11 +11001437 error("%s: Certificate signature verification failed",
1438 __func__);
Damien Miller0a80ca12010-02-27 07:55:05 +11001439 goto out;
1440 }
1441
Damien Miller0a80ca12010-02-27 07:55:05 +11001442 out:
1443 buffer_free(&tmp);
1444 if (principals != NULL)
1445 xfree(principals);
Damien Miller4e270b02010-04-16 15:56:21 +10001446 if (critical != NULL)
1447 xfree(critical);
1448 if (exts != NULL)
1449 xfree(exts);
Damien Miller0a80ca12010-02-27 07:55:05 +11001450 if (sig_key != NULL)
1451 xfree(sig_key);
1452 if (sig != NULL)
1453 xfree(sig);
1454 return ret;
1455}
1456
Damien Miller0bc1bd82000-11-13 22:57:25 +11001457Key *
Damien Millerf58b58c2003-11-17 21:18:23 +11001458key_from_blob(const u_char *blob, u_int blen)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001459{
1460 Buffer b;
Darren Tucker8ccb7392010-09-10 12:28:24 +10001461 int rlen, type;
Damien Millereb8b60e2010-08-31 22:41:14 +10001462 char *ktype = NULL, *curve = NULL;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001463 Key *key = NULL;
Damien Miller6af914a2010-09-10 11:39:26 +10001464#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001465 EC_POINT *q = NULL;
Darren Tucker8ccb7392010-09-10 12:28:24 +10001466 int nid = -1;
Damien Miller6af914a2010-09-10 11:39:26 +10001467#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +11001468
1469#ifdef DEBUG_PK
1470 dump_base64(stderr, blob, blen);
1471#endif
1472 buffer_init(&b);
1473 buffer_append(&b, blob, blen);
Damien Millerda108ec2010-08-31 22:36:39 +10001474 if ((ktype = buffer_get_cstring_ret(&b, NULL)) == NULL) {
Darren Tucker08d04fa2004-11-05 20:42:28 +11001475 error("key_from_blob: can't read key type");
1476 goto out;
1477 }
1478
Damien Miller0bc1bd82000-11-13 22:57:25 +11001479 type = key_type_from_name(ktype);
Damien Miller6af914a2010-09-10 11:39:26 +10001480#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001481 if (key_type_plain(type) == KEY_ECDSA)
1482 nid = key_ecdsa_nid_from_name(ktype);
Damien Miller6af914a2010-09-10 11:39:26 +10001483#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +11001484
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001485 switch (type) {
Damien Miller0a80ca12010-02-27 07:55:05 +11001486 case KEY_RSA_CERT:
Damien Miller4e270b02010-04-16 15:56:21 +10001487 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1488 /* FALLTHROUGH */
1489 case KEY_RSA:
1490 case KEY_RSA_CERT_V00:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001491 key = key_new(type);
Darren Tucker08d04fa2004-11-05 20:42:28 +11001492 if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 ||
1493 buffer_get_bignum2_ret(&b, key->rsa->n) == -1) {
1494 error("key_from_blob: can't read rsa key");
Damien Miller0a80ca12010-02-27 07:55:05 +11001495 badkey:
Darren Tucker08d04fa2004-11-05 20:42:28 +11001496 key_free(key);
1497 key = NULL;
1498 goto out;
1499 }
Damien Miller0bc1bd82000-11-13 22:57:25 +11001500#ifdef DEBUG_PK
1501 RSA_print_fp(stderr, key->rsa, 8);
1502#endif
1503 break;
Damien Miller0a80ca12010-02-27 07:55:05 +11001504 case KEY_DSA_CERT:
Damien Miller4e270b02010-04-16 15:56:21 +10001505 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1506 /* FALLTHROUGH */
1507 case KEY_DSA:
1508 case KEY_DSA_CERT_V00:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001509 key = key_new(type);
Darren Tucker08d04fa2004-11-05 20:42:28 +11001510 if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 ||
1511 buffer_get_bignum2_ret(&b, key->dsa->q) == -1 ||
1512 buffer_get_bignum2_ret(&b, key->dsa->g) == -1 ||
1513 buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) {
1514 error("key_from_blob: can't read dsa key");
Damien Miller0a80ca12010-02-27 07:55:05 +11001515 goto badkey;
Darren Tucker08d04fa2004-11-05 20:42:28 +11001516 }
Damien Miller0bc1bd82000-11-13 22:57:25 +11001517#ifdef DEBUG_PK
1518 DSA_print_fp(stderr, key->dsa, 8);
1519#endif
1520 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001521#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001522 case KEY_ECDSA_CERT:
1523 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1524 /* FALLTHROUGH */
1525 case KEY_ECDSA:
1526 key = key_new(type);
1527 key->ecdsa_nid = nid;
1528 if ((curve = buffer_get_string_ret(&b, NULL)) == NULL) {
1529 error("key_from_blob: can't read ecdsa curve");
1530 goto badkey;
1531 }
1532 if (key->ecdsa_nid != key_curve_name_to_nid(curve)) {
1533 error("key_from_blob: ecdsa curve doesn't match type");
1534 goto badkey;
1535 }
1536 if (key->ecdsa != NULL)
1537 EC_KEY_free(key->ecdsa);
1538 if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
1539 == NULL)
1540 fatal("key_from_blob: EC_KEY_new_by_curve_name failed");
1541 if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL)
1542 fatal("key_from_blob: EC_POINT_new failed");
1543 if (buffer_get_ecpoint_ret(&b, EC_KEY_get0_group(key->ecdsa),
1544 q) == -1) {
1545 error("key_from_blob: can't read ecdsa key point");
1546 goto badkey;
1547 }
1548 if (key_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
1549 q) != 0)
1550 goto badkey;
1551 if (EC_KEY_set_public_key(key->ecdsa, q) != 1)
1552 fatal("key_from_blob: EC_KEY_set_public_key failed");
1553#ifdef DEBUG_PK
1554 key_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
1555#endif
1556 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001557#endif /* OPENSSL_HAS_ECC */
Damien Miller0bc1bd82000-11-13 22:57:25 +11001558 case KEY_UNSPEC:
1559 key = key_new(type);
1560 break;
1561 default:
1562 error("key_from_blob: cannot handle type %s", ktype);
Darren Tucker08d04fa2004-11-05 20:42:28 +11001563 goto out;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001564 }
Damien Miller0a80ca12010-02-27 07:55:05 +11001565 if (key_is_cert(key) && cert_parse(&b, key, blob, blen) == -1) {
1566 error("key_from_blob: can't parse cert data");
1567 goto badkey;
1568 }
Damien Miller0bc1bd82000-11-13 22:57:25 +11001569 rlen = buffer_len(&b);
1570 if (key != NULL && rlen != 0)
1571 error("key_from_blob: remaining bytes in key blob %d", rlen);
Darren Tucker08d04fa2004-11-05 20:42:28 +11001572 out:
1573 if (ktype != NULL)
1574 xfree(ktype);
Damien Millereb8b60e2010-08-31 22:41:14 +10001575 if (curve != NULL)
1576 xfree(curve);
Damien Miller6af914a2010-09-10 11:39:26 +10001577#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001578 if (q != NULL)
1579 EC_POINT_free(q);
Damien Miller6af914a2010-09-10 11:39:26 +10001580#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +11001581 buffer_free(&b);
1582 return key;
1583}
1584
1585int
Damien Millerf58b58c2003-11-17 21:18:23 +11001586key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001587{
1588 Buffer b;
1589 int len;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001590
1591 if (key == NULL) {
1592 error("key_to_blob: key == NULL");
1593 return 0;
1594 }
1595 buffer_init(&b);
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001596 switch (key->type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001597 case KEY_DSA_CERT_V00:
1598 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001599 case KEY_DSA_CERT:
Damien Millereb8b60e2010-08-31 22:41:14 +10001600 case KEY_ECDSA_CERT:
Damien Miller0a80ca12010-02-27 07:55:05 +11001601 case KEY_RSA_CERT:
1602 /* Use the existing blob */
1603 buffer_append(&b, buffer_ptr(&key->cert->certblob),
1604 buffer_len(&key->cert->certblob));
1605 break;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001606 case KEY_DSA:
1607 buffer_put_cstring(&b, key_ssh_name(key));
1608 buffer_put_bignum2(&b, key->dsa->p);
1609 buffer_put_bignum2(&b, key->dsa->q);
1610 buffer_put_bignum2(&b, key->dsa->g);
1611 buffer_put_bignum2(&b, key->dsa->pub_key);
1612 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001613#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001614 case KEY_ECDSA:
1615 buffer_put_cstring(&b, key_ssh_name(key));
1616 buffer_put_cstring(&b, key_curve_nid_to_name(key->ecdsa_nid));
1617 buffer_put_ecpoint(&b, EC_KEY_get0_group(key->ecdsa),
1618 EC_KEY_get0_public_key(key->ecdsa));
1619 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001620#endif
Damien Miller0bc1bd82000-11-13 22:57:25 +11001621 case KEY_RSA:
1622 buffer_put_cstring(&b, key_ssh_name(key));
Damien Miller0bc1bd82000-11-13 22:57:25 +11001623 buffer_put_bignum2(&b, key->rsa->e);
Ben Lindstrombf555ba2001-01-18 02:04:35 +00001624 buffer_put_bignum2(&b, key->rsa->n);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001625 break;
1626 default:
Ben Lindstrom99a30f12001-09-18 05:49:14 +00001627 error("key_to_blob: unsupported key type %d", key->type);
1628 buffer_free(&b);
1629 return 0;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001630 }
1631 len = buffer_len(&b);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001632 if (lenp != NULL)
1633 *lenp = len;
Ben Lindstrom2bf759c2002-07-07 22:13:31 +00001634 if (blobp != NULL) {
1635 *blobp = xmalloc(len);
1636 memcpy(*blobp, buffer_ptr(&b), len);
1637 }
1638 memset(buffer_ptr(&b), 0, len);
1639 buffer_free(&b);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001640 return len;
1641}
1642
1643int
1644key_sign(
Damien Millerf58b58c2003-11-17 21:18:23 +11001645 const Key *key,
Ben Lindstrom90fd8142002-02-26 18:09:42 +00001646 u_char **sigp, u_int *lenp,
Damien Millerf58b58c2003-11-17 21:18:23 +11001647 const u_char *data, u_int datalen)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001648{
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001649 switch (key->type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001650 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001651 case KEY_DSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001652 case KEY_DSA:
1653 return ssh_dss_sign(key, sigp, lenp, data, datalen);
Damien Miller6af914a2010-09-10 11:39:26 +10001654#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001655 case KEY_ECDSA_CERT:
1656 case KEY_ECDSA:
1657 return ssh_ecdsa_sign(key, sigp, lenp, data, datalen);
Damien Miller6af914a2010-09-10 11:39:26 +10001658#endif
Damien Miller4e270b02010-04-16 15:56:21 +10001659 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001660 case KEY_RSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001661 case KEY_RSA:
1662 return ssh_rsa_sign(key, sigp, lenp, data, datalen);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001663 default:
Darren Tucker5cb30ad2004-08-12 22:40:24 +10001664 error("key_sign: invalid key type %d", key->type);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001665 return -1;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001666 }
1667}
1668
Ben Lindstrom01fff0c2002-06-06 20:54:07 +00001669/*
1670 * key_verify returns 1 for a correct signature, 0 for an incorrect signature
1671 * and -1 on error.
1672 */
Damien Miller0bc1bd82000-11-13 22:57:25 +11001673int
1674key_verify(
Damien Millerf58b58c2003-11-17 21:18:23 +11001675 const Key *key,
1676 const u_char *signature, u_int signaturelen,
1677 const u_char *data, u_int datalen)
Damien Miller0bc1bd82000-11-13 22:57:25 +11001678{
Ben Lindstrom5363aee2001-06-25 04:42:20 +00001679 if (signaturelen == 0)
1680 return -1;
1681
Ben Lindstrom1c37c6a2001-12-06 18:00:18 +00001682 switch (key->type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001683 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001684 case KEY_DSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001685 case KEY_DSA:
1686 return ssh_dss_verify(key, signature, signaturelen, data, datalen);
Damien Miller6af914a2010-09-10 11:39:26 +10001687#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001688 case KEY_ECDSA_CERT:
1689 case KEY_ECDSA:
1690 return ssh_ecdsa_verify(key, signature, signaturelen, data, datalen);
Damien Miller6af914a2010-09-10 11:39:26 +10001691#endif
Damien Miller4e270b02010-04-16 15:56:21 +10001692 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001693 case KEY_RSA_CERT:
Damien Miller0bc1bd82000-11-13 22:57:25 +11001694 case KEY_RSA:
1695 return ssh_rsa_verify(key, signature, signaturelen, data, datalen);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001696 default:
Darren Tucker5cb30ad2004-08-12 22:40:24 +10001697 error("key_verify: invalid key type %d", key->type);
Damien Miller0bc1bd82000-11-13 22:57:25 +11001698 return -1;
Damien Miller0bc1bd82000-11-13 22:57:25 +11001699 }
1700}
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001701
1702/* Converts a private to a public key */
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001703Key *
Damien Millerf58b58c2003-11-17 21:18:23 +11001704key_demote(const Key *k)
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001705{
1706 Key *pk;
Ben Lindstrom6328ab32002-03-22 02:54:23 +00001707
Damien Miller07d86be2006-03-26 14:19:21 +11001708 pk = xcalloc(1, sizeof(*pk));
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001709 pk->type = k->type;
1710 pk->flags = k->flags;
Damien Millereb8b60e2010-08-31 22:41:14 +10001711 pk->ecdsa_nid = k->ecdsa_nid;
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001712 pk->dsa = NULL;
Damien Millereb8b60e2010-08-31 22:41:14 +10001713 pk->ecdsa = NULL;
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001714 pk->rsa = NULL;
1715
1716 switch (k->type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001717 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001718 case KEY_RSA_CERT:
1719 key_cert_copy(k, pk);
1720 /* FALLTHROUGH */
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001721 case KEY_RSA1:
1722 case KEY_RSA:
1723 if ((pk->rsa = RSA_new()) == NULL)
1724 fatal("key_demote: RSA_new failed");
1725 if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL)
1726 fatal("key_demote: BN_dup failed");
1727 if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL)
1728 fatal("key_demote: BN_dup failed");
1729 break;
Damien Miller4e270b02010-04-16 15:56:21 +10001730 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001731 case KEY_DSA_CERT:
1732 key_cert_copy(k, pk);
1733 /* FALLTHROUGH */
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001734 case KEY_DSA:
1735 if ((pk->dsa = DSA_new()) == NULL)
1736 fatal("key_demote: DSA_new failed");
1737 if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL)
1738 fatal("key_demote: BN_dup failed");
1739 if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL)
1740 fatal("key_demote: BN_dup failed");
1741 if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL)
1742 fatal("key_demote: BN_dup failed");
1743 if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL)
1744 fatal("key_demote: BN_dup failed");
1745 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001746#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001747 case KEY_ECDSA_CERT:
1748 key_cert_copy(k, pk);
1749 /* FALLTHROUGH */
1750 case KEY_ECDSA:
1751 if ((pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid)) == NULL)
1752 fatal("key_demote: EC_KEY_new_by_curve_name failed");
1753 if (EC_KEY_set_public_key(pk->ecdsa,
1754 EC_KEY_get0_public_key(k->ecdsa)) != 1)
1755 fatal("key_demote: EC_KEY_set_public_key failed");
1756 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001757#endif
Ben Lindstroma674e8d2002-03-22 01:45:53 +00001758 default:
1759 fatal("key_free: bad key type %d", k->type);
1760 break;
1761 }
1762
1763 return (pk);
1764}
Damien Miller0a80ca12010-02-27 07:55:05 +11001765
1766int
1767key_is_cert(const Key *k)
1768{
Damien Miller4e270b02010-04-16 15:56:21 +10001769 if (k == NULL)
1770 return 0;
1771 switch (k->type) {
1772 case KEY_RSA_CERT_V00:
1773 case KEY_DSA_CERT_V00:
1774 case KEY_RSA_CERT:
1775 case KEY_DSA_CERT:
Damien Millereb8b60e2010-08-31 22:41:14 +10001776 case KEY_ECDSA_CERT:
Damien Miller4e270b02010-04-16 15:56:21 +10001777 return 1;
1778 default:
1779 return 0;
1780 }
Damien Miller0a80ca12010-02-27 07:55:05 +11001781}
1782
1783/* Return the cert-less equivalent to a certified key type */
1784int
1785key_type_plain(int type)
1786{
1787 switch (type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001788 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001789 case KEY_RSA_CERT:
1790 return KEY_RSA;
Damien Miller4e270b02010-04-16 15:56:21 +10001791 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001792 case KEY_DSA_CERT:
1793 return KEY_DSA;
Damien Millereb8b60e2010-08-31 22:41:14 +10001794 case KEY_ECDSA_CERT:
1795 return KEY_ECDSA;
Damien Miller0a80ca12010-02-27 07:55:05 +11001796 default:
1797 return type;
1798 }
1799}
1800
1801/* Convert a KEY_RSA or KEY_DSA to their _CERT equivalent */
1802int
Damien Miller4e270b02010-04-16 15:56:21 +10001803key_to_certified(Key *k, int legacy)
Damien Miller0a80ca12010-02-27 07:55:05 +11001804{
1805 switch (k->type) {
1806 case KEY_RSA:
1807 k->cert = cert_new();
Damien Miller4e270b02010-04-16 15:56:21 +10001808 k->type = legacy ? KEY_RSA_CERT_V00 : KEY_RSA_CERT;
Damien Miller0a80ca12010-02-27 07:55:05 +11001809 return 0;
1810 case KEY_DSA:
1811 k->cert = cert_new();
Damien Miller4e270b02010-04-16 15:56:21 +10001812 k->type = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT;
Damien Miller0a80ca12010-02-27 07:55:05 +11001813 return 0;
Damien Millereb8b60e2010-08-31 22:41:14 +10001814 case KEY_ECDSA:
Damien Miller8f639fe2011-05-20 19:03:08 +10001815 if (legacy)
1816 fatal("%s: legacy ECDSA certificates are not supported",
1817 __func__);
Damien Millereb8b60e2010-08-31 22:41:14 +10001818 k->cert = cert_new();
1819 k->type = KEY_ECDSA_CERT;
1820 return 0;
Damien Miller0a80ca12010-02-27 07:55:05 +11001821 default:
1822 error("%s: key has incorrect type %s", __func__, key_type(k));
1823 return -1;
1824 }
1825}
1826
1827/* Convert a KEY_RSA_CERT or KEY_DSA_CERT to their raw key equivalent */
1828int
1829key_drop_cert(Key *k)
1830{
1831 switch (k->type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001832 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001833 case KEY_RSA_CERT:
1834 cert_free(k->cert);
1835 k->type = KEY_RSA;
1836 return 0;
Damien Miller4e270b02010-04-16 15:56:21 +10001837 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001838 case KEY_DSA_CERT:
1839 cert_free(k->cert);
1840 k->type = KEY_DSA;
1841 return 0;
Damien Millereb8b60e2010-08-31 22:41:14 +10001842 case KEY_ECDSA_CERT:
1843 cert_free(k->cert);
1844 k->type = KEY_ECDSA;
1845 return 0;
Damien Miller0a80ca12010-02-27 07:55:05 +11001846 default:
1847 error("%s: key has incorrect type %s", __func__, key_type(k));
1848 return -1;
1849 }
1850}
1851
Damien Millereb8b60e2010-08-31 22:41:14 +10001852/*
1853 * Sign a KEY_RSA_CERT, KEY_DSA_CERT or KEY_ECDSA_CERT, (re-)generating
1854 * the signed certblob
1855 */
Damien Miller0a80ca12010-02-27 07:55:05 +11001856int
1857key_certify(Key *k, Key *ca)
1858{
1859 Buffer principals;
1860 u_char *ca_blob, *sig_blob, nonce[32];
1861 u_int i, ca_len, sig_len;
1862
1863 if (k->cert == NULL) {
1864 error("%s: key lacks cert info", __func__);
1865 return -1;
1866 }
1867
1868 if (!key_is_cert(k)) {
1869 error("%s: certificate has unknown type %d", __func__,
1870 k->cert->type);
1871 return -1;
1872 }
1873
Damien Millereb8b60e2010-08-31 22:41:14 +10001874 if (ca->type != KEY_RSA && ca->type != KEY_DSA &&
1875 ca->type != KEY_ECDSA) {
Damien Miller0a80ca12010-02-27 07:55:05 +11001876 error("%s: CA key has unsupported type %s", __func__,
1877 key_type(ca));
1878 return -1;
1879 }
1880
1881 key_to_blob(ca, &ca_blob, &ca_len);
1882
1883 buffer_clear(&k->cert->certblob);
1884 buffer_put_cstring(&k->cert->certblob, key_ssh_name(k));
1885
Damien Miller4e270b02010-04-16 15:56:21 +10001886 /* -v01 certs put nonce first */
Damien Miller0a5f0122011-02-04 11:47:01 +11001887 arc4random_buf(&nonce, sizeof(nonce));
1888 if (!key_cert_is_legacy(k))
Damien Miller4e270b02010-04-16 15:56:21 +10001889 buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
Damien Miller4e270b02010-04-16 15:56:21 +10001890
Damien Miller0a80ca12010-02-27 07:55:05 +11001891 switch (k->type) {
Damien Miller4e270b02010-04-16 15:56:21 +10001892 case KEY_DSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001893 case KEY_DSA_CERT:
1894 buffer_put_bignum2(&k->cert->certblob, k->dsa->p);
1895 buffer_put_bignum2(&k->cert->certblob, k->dsa->q);
1896 buffer_put_bignum2(&k->cert->certblob, k->dsa->g);
1897 buffer_put_bignum2(&k->cert->certblob, k->dsa->pub_key);
1898 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001899#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10001900 case KEY_ECDSA_CERT:
1901 buffer_put_cstring(&k->cert->certblob,
1902 key_curve_nid_to_name(k->ecdsa_nid));
1903 buffer_put_ecpoint(&k->cert->certblob,
1904 EC_KEY_get0_group(k->ecdsa),
1905 EC_KEY_get0_public_key(k->ecdsa));
1906 break;
Damien Miller6af914a2010-09-10 11:39:26 +10001907#endif
Damien Miller4e270b02010-04-16 15:56:21 +10001908 case KEY_RSA_CERT_V00:
Damien Miller0a80ca12010-02-27 07:55:05 +11001909 case KEY_RSA_CERT:
1910 buffer_put_bignum2(&k->cert->certblob, k->rsa->e);
1911 buffer_put_bignum2(&k->cert->certblob, k->rsa->n);
1912 break;
1913 default:
1914 error("%s: key has incorrect type %s", __func__, key_type(k));
1915 buffer_clear(&k->cert->certblob);
1916 xfree(ca_blob);
1917 return -1;
1918 }
1919
Damien Miller4e270b02010-04-16 15:56:21 +10001920 /* -v01 certs have a serial number next */
Damien Millereb8b60e2010-08-31 22:41:14 +10001921 if (!key_cert_is_legacy(k))
Damien Miller4e270b02010-04-16 15:56:21 +10001922 buffer_put_int64(&k->cert->certblob, k->cert->serial);
1923
Damien Miller0a80ca12010-02-27 07:55:05 +11001924 buffer_put_int(&k->cert->certblob, k->cert->type);
1925 buffer_put_cstring(&k->cert->certblob, k->cert->key_id);
1926
1927 buffer_init(&principals);
1928 for (i = 0; i < k->cert->nprincipals; i++)
1929 buffer_put_cstring(&principals, k->cert->principals[i]);
1930 buffer_put_string(&k->cert->certblob, buffer_ptr(&principals),
1931 buffer_len(&principals));
1932 buffer_free(&principals);
1933
1934 buffer_put_int64(&k->cert->certblob, k->cert->valid_after);
1935 buffer_put_int64(&k->cert->certblob, k->cert->valid_before);
1936 buffer_put_string(&k->cert->certblob,
Damien Miller4e270b02010-04-16 15:56:21 +10001937 buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical));
Damien Miller0a80ca12010-02-27 07:55:05 +11001938
Damien Miller4e270b02010-04-16 15:56:21 +10001939 /* -v01 certs have non-critical options here */
Damien Millereb8b60e2010-08-31 22:41:14 +10001940 if (!key_cert_is_legacy(k)) {
Damien Miller4e270b02010-04-16 15:56:21 +10001941 buffer_put_string(&k->cert->certblob,
1942 buffer_ptr(&k->cert->extensions),
1943 buffer_len(&k->cert->extensions));
1944 }
1945
1946 /* -v00 certs put the nonce at the end */
Damien Millereb8b60e2010-08-31 22:41:14 +10001947 if (key_cert_is_legacy(k))
Damien Miller4e270b02010-04-16 15:56:21 +10001948 buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
1949
Damien Miller0a80ca12010-02-27 07:55:05 +11001950 buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */
1951 buffer_put_string(&k->cert->certblob, ca_blob, ca_len);
1952 xfree(ca_blob);
1953
1954 /* Sign the whole mess */
1955 if (key_sign(ca, &sig_blob, &sig_len, buffer_ptr(&k->cert->certblob),
1956 buffer_len(&k->cert->certblob)) != 0) {
1957 error("%s: signature operation failed", __func__);
1958 buffer_clear(&k->cert->certblob);
1959 return -1;
1960 }
1961 /* Append signature and we are done */
1962 buffer_put_string(&k->cert->certblob, sig_blob, sig_len);
1963 xfree(sig_blob);
1964
1965 return 0;
1966}
1967
1968int
1969key_cert_check_authority(const Key *k, int want_host, int require_principal,
1970 const char *name, const char **reason)
1971{
1972 u_int i, principal_matches;
1973 time_t now = time(NULL);
1974
1975 if (want_host) {
1976 if (k->cert->type != SSH2_CERT_TYPE_HOST) {
1977 *reason = "Certificate invalid: not a host certificate";
1978 return -1;
1979 }
1980 } else {
1981 if (k->cert->type != SSH2_CERT_TYPE_USER) {
1982 *reason = "Certificate invalid: not a user certificate";
1983 return -1;
1984 }
1985 }
1986 if (now < 0) {
1987 error("%s: system clock lies before epoch", __func__);
1988 *reason = "Certificate invalid: not yet valid";
1989 return -1;
1990 }
1991 if ((u_int64_t)now < k->cert->valid_after) {
1992 *reason = "Certificate invalid: not yet valid";
1993 return -1;
1994 }
1995 if ((u_int64_t)now >= k->cert->valid_before) {
1996 *reason = "Certificate invalid: expired";
1997 return -1;
1998 }
1999 if (k->cert->nprincipals == 0) {
2000 if (require_principal) {
2001 *reason = "Certificate lacks principal list";
2002 return -1;
2003 }
Damien Miller30da3442010-05-10 11:58:03 +10002004 } else if (name != NULL) {
Damien Miller0a80ca12010-02-27 07:55:05 +11002005 principal_matches = 0;
2006 for (i = 0; i < k->cert->nprincipals; i++) {
2007 if (strcmp(name, k->cert->principals[i]) == 0) {
2008 principal_matches = 1;
2009 break;
2010 }
2011 }
2012 if (!principal_matches) {
2013 *reason = "Certificate invalid: name is not a listed "
2014 "principal";
2015 return -1;
2016 }
2017 }
2018 return 0;
2019}
Damien Miller4e270b02010-04-16 15:56:21 +10002020
2021int
2022key_cert_is_legacy(Key *k)
2023{
2024 switch (k->type) {
2025 case KEY_DSA_CERT_V00:
2026 case KEY_RSA_CERT_V00:
2027 return 1;
2028 default:
2029 return 0;
2030 }
2031}
Damien Millereb8b60e2010-08-31 22:41:14 +10002032
Damien Miller041ab7c2010-09-10 11:23:34 +10002033/* XXX: these are really begging for a table-driven approach */
Damien Millereb8b60e2010-08-31 22:41:14 +10002034int
2035key_curve_name_to_nid(const char *name)
2036{
Damien Miller6af914a2010-09-10 11:39:26 +10002037#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10002038 if (strcmp(name, "nistp256") == 0)
2039 return NID_X9_62_prime256v1;
2040 else if (strcmp(name, "nistp384") == 0)
2041 return NID_secp384r1;
2042 else if (strcmp(name, "nistp521") == 0)
2043 return NID_secp521r1;
Damien Miller6af914a2010-09-10 11:39:26 +10002044#endif
Damien Millereb8b60e2010-08-31 22:41:14 +10002045
2046 debug("%s: unsupported EC curve name \"%.100s\"", __func__, name);
2047 return -1;
2048}
2049
Damien Miller041ab7c2010-09-10 11:23:34 +10002050u_int
2051key_curve_nid_to_bits(int nid)
2052{
2053 switch (nid) {
Damien Miller6af914a2010-09-10 11:39:26 +10002054#ifdef OPENSSL_HAS_ECC
Damien Miller041ab7c2010-09-10 11:23:34 +10002055 case NID_X9_62_prime256v1:
2056 return 256;
2057 case NID_secp384r1:
2058 return 384;
2059 case NID_secp521r1:
2060 return 521;
Damien Miller6af914a2010-09-10 11:39:26 +10002061#endif
Damien Miller041ab7c2010-09-10 11:23:34 +10002062 default:
2063 error("%s: unsupported EC curve nid %d", __func__, nid);
2064 return 0;
2065 }
2066}
2067
Damien Millereb8b60e2010-08-31 22:41:14 +10002068const char *
2069key_curve_nid_to_name(int nid)
2070{
Damien Miller6af914a2010-09-10 11:39:26 +10002071#ifdef OPENSSL_HAS_ECC
Damien Millereb8b60e2010-08-31 22:41:14 +10002072 if (nid == NID_X9_62_prime256v1)
2073 return "nistp256";
2074 else if (nid == NID_secp384r1)
2075 return "nistp384";
2076 else if (nid == NID_secp521r1)
2077 return "nistp521";
Damien Miller6af914a2010-09-10 11:39:26 +10002078#endif
Damien Millereb8b60e2010-08-31 22:41:14 +10002079 error("%s: unsupported EC curve nid %d", __func__, nid);
2080 return NULL;
2081}
2082
Damien Miller6af914a2010-09-10 11:39:26 +10002083#ifdef OPENSSL_HAS_ECC
Damien Miller041ab7c2010-09-10 11:23:34 +10002084const EVP_MD *
2085key_ec_nid_to_evpmd(int nid)
2086{
2087 int kbits = key_curve_nid_to_bits(nid);
2088
2089 if (kbits == 0)
2090 fatal("%s: invalid nid %d", __func__, nid);
2091 /* RFC5656 section 6.2.1 */
2092 if (kbits <= 256)
2093 return EVP_sha256();
2094 else if (kbits <= 384)
2095 return EVP_sha384();
2096 else
2097 return EVP_sha512();
2098}
2099
Damien Millereb8b60e2010-08-31 22:41:14 +10002100int
2101key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
2102{
2103 BN_CTX *bnctx;
2104 EC_POINT *nq = NULL;
2105 BIGNUM *order, *x, *y, *tmp;
2106 int ret = -1;
2107
2108 if ((bnctx = BN_CTX_new()) == NULL)
2109 fatal("%s: BN_CTX_new failed", __func__);
2110 BN_CTX_start(bnctx);
2111
2112 /*
2113 * We shouldn't ever hit this case because bignum_get_ecpoint()
2114 * refuses to load GF2m points.
2115 */
2116 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
2117 NID_X9_62_prime_field) {
2118 error("%s: group is not a prime field", __func__);
2119 goto out;
2120 }
2121
2122 /* Q != infinity */
2123 if (EC_POINT_is_at_infinity(group, public)) {
2124 error("%s: received degenerate public key (infinity)",
2125 __func__);
2126 goto out;
2127 }
2128
2129 if ((x = BN_CTX_get(bnctx)) == NULL ||
2130 (y = BN_CTX_get(bnctx)) == NULL ||
2131 (order = BN_CTX_get(bnctx)) == NULL ||
2132 (tmp = BN_CTX_get(bnctx)) == NULL)
2133 fatal("%s: BN_CTX_get failed", __func__);
2134
2135 /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
2136 if (EC_GROUP_get_order(group, order, bnctx) != 1)
2137 fatal("%s: EC_GROUP_get_order failed", __func__);
2138 if (EC_POINT_get_affine_coordinates_GFp(group, public,
2139 x, y, bnctx) != 1)
2140 fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__);
2141 if (BN_num_bits(x) <= BN_num_bits(order) / 2) {
2142 error("%s: public key x coordinate too small: "
2143 "bits(x) = %d, bits(order)/2 = %d", __func__,
2144 BN_num_bits(x), BN_num_bits(order) / 2);
2145 goto out;
2146 }
2147 if (BN_num_bits(y) <= BN_num_bits(order) / 2) {
2148 error("%s: public key y coordinate too small: "
2149 "bits(y) = %d, bits(order)/2 = %d", __func__,
2150 BN_num_bits(x), BN_num_bits(order) / 2);
2151 goto out;
2152 }
2153
2154 /* nQ == infinity (n == order of subgroup) */
2155 if ((nq = EC_POINT_new(group)) == NULL)
2156 fatal("%s: BN_CTX_tmp failed", __func__);
2157 if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1)
2158 fatal("%s: EC_GROUP_mul failed", __func__);
2159 if (EC_POINT_is_at_infinity(group, nq) != 1) {
2160 error("%s: received degenerate public key (nQ != infinity)",
2161 __func__);
2162 goto out;
2163 }
2164
2165 /* x < order - 1, y < order - 1 */
2166 if (!BN_sub(tmp, order, BN_value_one()))
2167 fatal("%s: BN_sub failed", __func__);
2168 if (BN_cmp(x, tmp) >= 0) {
2169 error("%s: public key x coordinate >= group order - 1",
2170 __func__);
2171 goto out;
2172 }
2173 if (BN_cmp(y, tmp) >= 0) {
2174 error("%s: public key y coordinate >= group order - 1",
2175 __func__);
2176 goto out;
2177 }
2178 ret = 0;
2179 out:
2180 BN_CTX_free(bnctx);
2181 EC_POINT_free(nq);
2182 return ret;
2183}
2184
2185int
2186key_ec_validate_private(const EC_KEY *key)
2187{
2188 BN_CTX *bnctx;
2189 BIGNUM *order, *tmp;
2190 int ret = -1;
2191
2192 if ((bnctx = BN_CTX_new()) == NULL)
2193 fatal("%s: BN_CTX_new failed", __func__);
2194 BN_CTX_start(bnctx);
2195
2196 if ((order = BN_CTX_get(bnctx)) == NULL ||
2197 (tmp = BN_CTX_get(bnctx)) == NULL)
2198 fatal("%s: BN_CTX_get failed", __func__);
2199
2200 /* log2(private) > log2(order)/2 */
2201 if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1)
2202 fatal("%s: EC_GROUP_get_order failed", __func__);
2203 if (BN_num_bits(EC_KEY_get0_private_key(key)) <=
2204 BN_num_bits(order) / 2) {
2205 error("%s: private key too small: "
2206 "bits(y) = %d, bits(order)/2 = %d", __func__,
2207 BN_num_bits(EC_KEY_get0_private_key(key)),
2208 BN_num_bits(order) / 2);
2209 goto out;
2210 }
2211
2212 /* private < order - 1 */
2213 if (!BN_sub(tmp, order, BN_value_one()))
2214 fatal("%s: BN_sub failed", __func__);
2215 if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0) {
2216 error("%s: private key >= group order - 1", __func__);
2217 goto out;
2218 }
2219 ret = 0;
2220 out:
2221 BN_CTX_free(bnctx);
2222 return ret;
2223}
2224
2225#if defined(DEBUG_KEXECDH) || defined(DEBUG_PK)
2226void
2227key_dump_ec_point(const EC_GROUP *group, const EC_POINT *point)
2228{
2229 BIGNUM *x, *y;
2230 BN_CTX *bnctx;
2231
2232 if (point == NULL) {
2233 fputs("point=(NULL)\n", stderr);
2234 return;
2235 }
2236 if ((bnctx = BN_CTX_new()) == NULL)
2237 fatal("%s: BN_CTX_new failed", __func__);
2238 BN_CTX_start(bnctx);
2239 if ((x = BN_CTX_get(bnctx)) == NULL || (y = BN_CTX_get(bnctx)) == NULL)
2240 fatal("%s: BN_CTX_get failed", __func__);
2241 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
2242 NID_X9_62_prime_field)
2243 fatal("%s: group is not a prime field", __func__);
2244 if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, bnctx) != 1)
2245 fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__);
2246 fputs("x=", stderr);
2247 BN_print_fp(stderr, x);
2248 fputs("\ny=", stderr);
2249 BN_print_fp(stderr, y);
2250 fputs("\n", stderr);
2251 BN_CTX_free(bnctx);
2252}
2253
2254void
2255key_dump_ec_key(const EC_KEY *key)
2256{
2257 const BIGNUM *exponent;
2258
2259 key_dump_ec_point(EC_KEY_get0_group(key), EC_KEY_get0_public_key(key));
2260 fputs("exponent=", stderr);
2261 if ((exponent = EC_KEY_get0_private_key(key)) == NULL)
2262 fputs("(NULL)", stderr);
2263 else
2264 BN_print_fp(stderr, EC_KEY_get0_private_key(key));
2265 fputs("\n", stderr);
2266}
2267#endif /* defined(DEBUG_KEXECDH) || defined(DEBUG_PK) */
Damien Miller6af914a2010-09-10 11:39:26 +10002268#endif /* OPENSSL_HAS_ECC */