key.c 65.1 KB
Newer Older
1
/* $OpenBSD: key.c,v 1.115 2014/01/09 23:20:00 djm Exp $ */
Damien Miller's avatar
Damien Miller committed
2
/*
3 4 5 6 7 8 9 10 11 12
 * read_bignum():
 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
 *
 * As far as I am concerned, the code I have written for this software
 * can be used freely for any purpose.  Any derived versions of this
 * software must be clearly marked as such, and if the derived work is
 * incompatible with the protocol description in the RFC file, it must be
 * called by a name other than "ssh" or "Secure Shell".
 *
 *
13
 * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
14
 * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.
Damien Miller's avatar
Damien Miller committed
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
36

Damien Miller's avatar
Damien Miller committed
37
#include "includes.h"
38

39
#include <sys/param.h>
40 41
#include <sys/types.h>

42 43
#include "crypto_api.h"

Damien Miller's avatar
Damien Miller committed
44
#include <openssl/evp.h>
45
#include <openbsd-compat/openssl-compat.h>
46

47
#include <stdarg.h>
48
#include <stdio.h>
49 50
#include <string.h>

Damien Miller's avatar
Damien Miller committed
51 52
#include "xmalloc.h"
#include "key.h"
53
#include "rsa.h"
54
#include "uuencode.h"
55
#include "buffer.h"
56
#include "log.h"
57
#include "misc.h"
Damien Miller's avatar
Damien Miller committed
58
#include "ssh2.h"
59
#include "digest.h"
Damien Miller's avatar
Damien Miller committed
60

61
static int to_blob(const Key *, u_char **, u_int *, int);
62
static Key *key_from_blob2(const u_char *, u_int, int);
63

Damien Miller's avatar
Damien Miller committed
64 65 66 67 68 69 70
static struct KeyCert *
cert_new(void)
{
	struct KeyCert *cert;

	cert = xcalloc(1, sizeof(*cert));
	buffer_init(&cert->certblob);
71 72
	buffer_init(&cert->critical);
	buffer_init(&cert->extensions);
Damien Miller's avatar
Damien Miller committed
73 74 75 76 77
	cert->key_id = NULL;
	cert->principals = NULL;
	cert->signature_key = NULL;
	return cert;
}
Damien Miller's avatar
Damien Miller committed
78 79 80 81 82 83 84

Key *
key_new(int type)
{
	Key *k;
	RSA *rsa;
	DSA *dsa;
85
	k = xcalloc(1, sizeof(*k));
Damien Miller's avatar
Damien Miller committed
86
	k->type = type;
87 88
	k->ecdsa = NULL;
	k->ecdsa_nid = -1;
89 90
	k->dsa = NULL;
	k->rsa = NULL;
Damien Miller's avatar
Damien Miller committed
91
	k->cert = NULL;
92 93
	k->ed25519_sk = NULL;
	k->ed25519_pk = NULL;
Damien Miller's avatar
Damien Miller committed
94
	switch (k->type) {
95
	case KEY_RSA1:
Damien Miller's avatar
Damien Miller committed
96
	case KEY_RSA:
97
	case KEY_RSA_CERT_V00:
Damien Miller's avatar
Damien Miller committed
98
	case KEY_RSA_CERT:
99 100 101 102 103 104
		if ((rsa = RSA_new()) == NULL)
			fatal("key_new: RSA_new failed");
		if ((rsa->n = BN_new()) == NULL)
			fatal("key_new: BN_new failed");
		if ((rsa->e = BN_new()) == NULL)
			fatal("key_new: BN_new failed");
Damien Miller's avatar
Damien Miller committed
105 106 107
		k->rsa = rsa;
		break;
	case KEY_DSA:
108
	case KEY_DSA_CERT_V00:
Damien Miller's avatar
Damien Miller committed
109
	case KEY_DSA_CERT:
110 111 112 113 114 115 116 117 118 119
		if ((dsa = DSA_new()) == NULL)
			fatal("key_new: DSA_new failed");
		if ((dsa->p = BN_new()) == NULL)
			fatal("key_new: BN_new failed");
		if ((dsa->q = BN_new()) == NULL)
			fatal("key_new: BN_new failed");
		if ((dsa->g = BN_new()) == NULL)
			fatal("key_new: BN_new failed");
		if ((dsa->pub_key = BN_new()) == NULL)
			fatal("key_new: BN_new failed");
Damien Miller's avatar
Damien Miller committed
120 121
		k->dsa = dsa;
		break;
122
#ifdef OPENSSL_HAS_ECC
123 124 125 126
	case KEY_ECDSA:
	case KEY_ECDSA_CERT:
		/* Cannot do anything until we know the group */
		break;
127
#endif
128 129 130 131
	case KEY_ED25519:
	case KEY_ED25519_CERT:
		/* no need to prealloc */
		break;
132
	case KEY_UNSPEC:
Damien Miller's avatar
Damien Miller committed
133 134 135 136 137
		break;
	default:
		fatal("key_new: bad key type %d", k->type);
		break;
	}
Damien Miller's avatar
Damien Miller committed
138 139 140 141

	if (key_is_cert(k))
		k->cert = cert_new();

Damien Miller's avatar
Damien Miller committed
142 143
	return k;
}
144

Damien Miller's avatar
Damien Miller committed
145 146
void
key_add_private(Key *k)
147 148 149 150
{
	switch (k->type) {
	case KEY_RSA1:
	case KEY_RSA:
151
	case KEY_RSA_CERT_V00:
Damien Miller's avatar
Damien Miller committed
152
	case KEY_RSA_CERT:
153 154 155 156 157 158 159 160 161 162 163 164
		if ((k->rsa->d = BN_new()) == NULL)
			fatal("key_new_private: BN_new failed");
		if ((k->rsa->iqmp = BN_new()) == NULL)
			fatal("key_new_private: BN_new failed");
		if ((k->rsa->q = BN_new()) == NULL)
			fatal("key_new_private: BN_new failed");
		if ((k->rsa->p = BN_new()) == NULL)
			fatal("key_new_private: BN_new failed");
		if ((k->rsa->dmq1 = BN_new()) == NULL)
			fatal("key_new_private: BN_new failed");
		if ((k->rsa->dmp1 = BN_new()) == NULL)
			fatal("key_new_private: BN_new failed");
165 166
		break;
	case KEY_DSA:
167
	case KEY_DSA_CERT_V00:
Damien Miller's avatar
Damien Miller committed
168
	case KEY_DSA_CERT:
169 170
		if ((k->dsa->priv_key = BN_new()) == NULL)
			fatal("key_new_private: BN_new failed");
171
		break;
172 173 174 175
	case KEY_ECDSA:
	case KEY_ECDSA_CERT:
		/* Cannot do anything until we know the group */
		break;
176 177 178 179
	case KEY_ED25519:
	case KEY_ED25519_CERT:
		/* no need to prealloc */
		break;
180 181 182 183 184
	case KEY_UNSPEC:
		break;
	default:
		break;
	}
Damien Miller's avatar
Damien Miller committed
185 186 187 188 189 190 191 192
}

Key *
key_new_private(int type)
{
	Key *k = key_new(type);

	key_add_private(k);
193 194
	return k;
}
195

Damien Miller's avatar
Damien Miller committed
196 197 198 199 200 201
static void
cert_free(struct KeyCert *cert)
{
	u_int i;

	buffer_free(&cert->certblob);
202 203
	buffer_free(&cert->critical);
	buffer_free(&cert->extensions);
204
	free(cert->key_id);
Damien Miller's avatar
Damien Miller committed
205
	for (i = 0; i < cert->nprincipals; i++)
206 207
		free(cert->principals[i]);
	free(cert->principals);
Damien Miller's avatar
Damien Miller committed
208 209
	if (cert->signature_key != NULL)
		key_free(cert->signature_key);
210
	free(cert);
Damien Miller's avatar
Damien Miller committed
211 212
}

Damien Miller's avatar
Damien Miller committed
213 214 215
void
key_free(Key *k)
{
216
	if (k == NULL)
217
		fatal("key_free: key is NULL");
Damien Miller's avatar
Damien Miller committed
218
	switch (k->type) {
219
	case KEY_RSA1:
Damien Miller's avatar
Damien Miller committed
220
	case KEY_RSA:
221
	case KEY_RSA_CERT_V00:
Damien Miller's avatar
Damien Miller committed
222
	case KEY_RSA_CERT:
Damien Miller's avatar
Damien Miller committed
223 224 225 226 227
		if (k->rsa != NULL)
			RSA_free(k->rsa);
		k->rsa = NULL;
		break;
	case KEY_DSA:
228
	case KEY_DSA_CERT_V00:
Damien Miller's avatar
Damien Miller committed
229
	case KEY_DSA_CERT:
Damien Miller's avatar
Damien Miller committed
230 231 232 233
		if (k->dsa != NULL)
			DSA_free(k->dsa);
		k->dsa = NULL;
		break;
234
#ifdef OPENSSL_HAS_ECC
235 236 237 238 239 240
	case KEY_ECDSA:
	case KEY_ECDSA_CERT:
		if (k->ecdsa != NULL)
			EC_KEY_free(k->ecdsa);
		k->ecdsa = NULL;
		break;
241
#endif
242 243 244 245 246 247 248 249 250 251 252 253 254
	case KEY_ED25519:
	case KEY_ED25519_CERT:
		if (k->ed25519_pk) {
			memset(k->ed25519_pk, 0, ED25519_PK_SZ);
			free(k->ed25519_pk);
			k->ed25519_pk = NULL;
		}
		if (k->ed25519_sk) {
			memset(k->ed25519_sk, 0, ED25519_SK_SZ);
			free(k->ed25519_sk);
			k->ed25519_sk = NULL;
		}
		break;
255 256
	case KEY_UNSPEC:
		break;
Damien Miller's avatar
Damien Miller committed
257 258 259 260
	default:
		fatal("key_free: bad key type %d", k->type);
		break;
	}
Damien Miller's avatar
Damien Miller committed
261 262 263 264 265 266
	if (key_is_cert(k)) {
		if (k->cert != NULL)
			cert_free(k->cert);
		k->cert = NULL;
	}

267
	free(k);
Damien Miller's avatar
Damien Miller committed
268
}
269

Damien Miller's avatar
Damien Miller committed
270 271 272 273 274 275 276 277 278
static int
cert_compare(struct KeyCert *a, struct KeyCert *b)
{
	if (a == NULL && b == NULL)
		return 1;
	if (a == NULL || b == NULL)
		return 0;
	if (buffer_len(&a->certblob) != buffer_len(&b->certblob))
		return 0;
279
	if (timingsafe_bcmp(buffer_ptr(&a->certblob), buffer_ptr(&b->certblob),
Damien Miller's avatar
Damien Miller committed
280 281 282 283 284 285 286 287 288
	    buffer_len(&a->certblob)) != 0)
		return 0;
	return 1;
}

/*
 * Compare public portions of key only, allowing comparisons between
 * certificates and plain keys too.
 */
Damien Miller's avatar
Damien Miller committed
289
int
Damien Miller's avatar
Damien Miller committed
290
key_equal_public(const Key *a, const Key *b)
Damien Miller's avatar
Damien Miller committed
291
{
292
#ifdef OPENSSL_HAS_ECC
293
	BN_CTX *bnctx;
294
#endif
295

Damien Miller's avatar
Damien Miller committed
296 297
	if (a == NULL || b == NULL ||
	    key_type_plain(a->type) != key_type_plain(b->type))
Damien Miller's avatar
Damien Miller committed
298
		return 0;
Damien Miller's avatar
Damien Miller committed
299

Damien Miller's avatar
Damien Miller committed
300
	switch (a->type) {
301
	case KEY_RSA1:
302
	case KEY_RSA_CERT_V00:
Damien Miller's avatar
Damien Miller committed
303
	case KEY_RSA_CERT:
Damien Miller's avatar
Damien Miller committed
304 305 306 307
	case KEY_RSA:
		return a->rsa != NULL && b->rsa != NULL &&
		    BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
		    BN_cmp(a->rsa->n, b->rsa->n) == 0;
308
	case KEY_DSA_CERT_V00:
Damien Miller's avatar
Damien Miller committed
309
	case KEY_DSA_CERT:
Damien Miller's avatar
Damien Miller committed
310 311 312 313 314 315
	case KEY_DSA:
		return a->dsa != NULL && b->dsa != NULL &&
		    BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
		    BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
		    BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
		    BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
316
#ifdef OPENSSL_HAS_ECC
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
	case KEY_ECDSA_CERT:
	case KEY_ECDSA:
		if (a->ecdsa == NULL || b->ecdsa == NULL ||
		    EC_KEY_get0_public_key(a->ecdsa) == NULL ||
		    EC_KEY_get0_public_key(b->ecdsa) == NULL)
			return 0;
		if ((bnctx = BN_CTX_new()) == NULL)
			fatal("%s: BN_CTX_new failed", __func__);
		if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa),
		    EC_KEY_get0_group(b->ecdsa), bnctx) != 0 ||
		    EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa),
		    EC_KEY_get0_public_key(a->ecdsa),
		    EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) {
			BN_CTX_free(bnctx);
			return 0;
		}
		BN_CTX_free(bnctx);
		return 1;
335
#endif /* OPENSSL_HAS_ECC */
336 337 338 339
	case KEY_ED25519:
	case KEY_ED25519_CERT:
		return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&
		    memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;
Damien Miller's avatar
Damien Miller committed
340
	default:
341
		fatal("key_equal: bad key type %d", a->type);
Damien Miller's avatar
Damien Miller committed
342
	}
343
	/* NOTREACHED */
Damien Miller's avatar
Damien Miller committed
344 345
}

Damien Miller's avatar
Damien Miller committed
346 347 348 349 350 351 352 353 354 355 356 357
int
key_equal(const Key *a, const Key *b)
{
	if (a == NULL || b == NULL || a->type != b->type)
		return 0;
	if (key_is_cert(a)) {
		if (!cert_compare(a->cert, b->cert))
			return 0;
	}
	return key_equal_public(a, b);
}

358
u_char*
359 360
key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
    u_int *dgst_raw_length)
Damien Miller's avatar
Damien Miller committed
361
{
362
	u_char *blob = NULL;
363
	u_char *retval = NULL;
364
	u_int len = 0;
365
	int nlen, elen, hash_alg = -1;
Damien Miller's avatar
Damien Miller committed
366

367 368
	*dgst_raw_length = 0;

369
	/* XXX switch to DIGEST_* directly? */
370 371
	switch (dgst_type) {
	case SSH_FP_MD5:
372
		hash_alg = SSH_DIGEST_MD5;
373 374
		break;
	case SSH_FP_SHA1:
375
		hash_alg = SSH_DIGEST_SHA1;
376
		break;
377
	case SSH_FP_SHA256:
378
		hash_alg = SSH_DIGEST_SHA256;
379
		break;
380
	default:
381
		fatal("%s: bad digest type %d", __func__, dgst_type);
382
	}
Damien Miller's avatar
Damien Miller committed
383
	switch (k->type) {
384
	case KEY_RSA1:
Damien Miller's avatar
Damien Miller committed
385 386 387
		nlen = BN_num_bytes(k->rsa->n);
		elen = BN_num_bytes(k->rsa->e);
		len = nlen + elen;
388 389 390
		blob = xmalloc(len);
		BN_bn2bin(k->rsa->n, blob);
		BN_bn2bin(k->rsa->e, blob + nlen);
Damien Miller's avatar
Damien Miller committed
391 392
		break;
	case KEY_DSA:
393
	case KEY_ECDSA:
394
	case KEY_RSA:
395
	case KEY_ED25519:
396 397
		key_to_blob(k, &blob, &len);
		break;
398 399
	case KEY_DSA_CERT_V00:
	case KEY_RSA_CERT_V00:
Damien Miller's avatar
Damien Miller committed
400
	case KEY_DSA_CERT:
401
	case KEY_ECDSA_CERT:
Damien Miller's avatar
Damien Miller committed
402
	case KEY_RSA_CERT:
403
	case KEY_ED25519_CERT:
Damien Miller's avatar
Damien Miller committed
404
		/* We want a fingerprint of the _key_ not of the cert */
405
		to_blob(k, &blob, &len, 1);
Damien Miller's avatar
Damien Miller committed
406
		break;
407 408
	case KEY_UNSPEC:
		return retval;
Damien Miller's avatar
Damien Miller committed
409
	default:
410
		fatal("%s: bad key type %d", __func__, k->type);
Damien Miller's avatar
Damien Miller committed
411 412
		break;
	}
413
	if (blob != NULL) {
414 415 416 417
		retval = xmalloc(SSH_DIGEST_MAX_LENGTH);
		if ((ssh_digest_memory(hash_alg, blob, len,
		    retval, SSH_DIGEST_MAX_LENGTH)) != 0)
			fatal("%s: digest_memory failed", __func__);
418
		memset(blob, 0, len);
419
		free(blob);
420
		*dgst_raw_length = ssh_digest_bytes(hash_alg);
421
	} else {
422
		fatal("%s: blob is null", __func__);
Damien Miller's avatar
Damien Miller committed
423 424 425 426
	}
	return retval;
}

427 428
static char *
key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len)
429 430
{
	char *retval;
431
	u_int i;
432

433
	retval = xcalloc(1, dgst_raw_len * 3 + 1);
434
	for (i = 0; i < dgst_raw_len; i++) {
435 436
		char hex[4];
		snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
437
		strlcat(retval, hex, dgst_raw_len * 3 + 1);
438
	}
439 440

	/* Remove the trailing ':' character */
441 442 443 444
	retval[(dgst_raw_len * 3) - 1] = '\0';
	return retval;
}

445 446
static char *
key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len)
447 448 449 450
{
	char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
	char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
	    'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
451
	u_int i, j = 0, rounds, seed = 1;
452 453 454
	char *retval;

	rounds = (dgst_raw_len / 2) + 1;
455
	retval = xcalloc((rounds * 6), sizeof(char));
456 457
	retval[j++] = 'x';
	for (i = 0; i < rounds; i++) {
458
		u_int idx0, idx1, idx2, idx3, idx4;
459 460
		if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
			idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
461
			    seed) % 6;
462 463
			idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
			idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
464
			    (seed / 6)) % 6;
465 466 467 468 469 470 471 472 473
			retval[j++] = vowels[idx0];
			retval[j++] = consonants[idx1];
			retval[j++] = vowels[idx2];
			if ((i + 1) < rounds) {
				idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
				idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
				retval[j++] = consonants[idx3];
				retval[j++] = '-';
				retval[j++] = consonants[idx4];
474
				seed = ((seed * 5) +
475 476
				    ((((u_int)(dgst_raw[2 * i])) * 7) +
				    ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
477 478 479 480 481
			}
		} else {
			idx0 = seed % 6;
			idx1 = 16;
			idx2 = seed / 6;
482 483 484
			retval[j++] = vowels[idx0];
			retval[j++] = consonants[idx1];
			retval[j++] = vowels[idx2];
485 486
		}
	}
487 488
	retval[j++] = 'x';
	retval[j++] = '\0';
489 490 491
	return retval;
}

492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
/*
 * Draw an ASCII-Art representing the fingerprint so human brain can
 * profit from its built-in pattern recognition ability.
 * This technique is called "random art" and can be found in some
 * scientific publications like this original paper:
 *
 * "Hash Visualization: a New Technique to improve Real-World Security",
 * Perrig A. and Song D., 1999, International Workshop on Cryptographic
 * Techniques and E-Commerce (CrypTEC '99)
 * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
 *
 * The subject came up in a talk by Dan Kaminsky, too.
 *
 * If you see the picture is different, the key is different.
 * If the picture looks the same, you still know nothing.
 *
 * The algorithm used here is a worm crawling over a discrete plane,
 * leaving a trace (augmenting the field) everywhere it goes.
 * Movement is taken from dgst_raw 2bit-wise.  Bumping into walls
 * makes the respective movement vector be ignored for this turn.
 * Graphs are not unambiguous, because circles in graphs can be
 * walked in either direction.
 */
515 516 517 518 519 520 521 522 523 524

/*
 * Field sizes for the random art.  Have to be odd, so the starting point
 * can be in the exact middle of the picture, and FLDBASE should be >=8 .
 * Else pictures would be too dense, and drawing the frame would
 * fail, too, because the key type would not fit in anymore.
 */
#define	FLDBASE		8
#define	FLDSIZE_Y	(FLDBASE + 1)
#define	FLDSIZE_X	(FLDBASE * 2 + 1)
525
static char *
526
key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k)
527 528 529 530 531
{
	/*
	 * Chars to be used after each other every time the worm
	 * intersects with itself.  Matter of taste.
	 */
532
	char	*augmentation_string = " .o+=*BOX@%&#/^SE";
533
	char	*retval, *p;
534
	u_char	 field[FLDSIZE_X][FLDSIZE_Y];
535 536
	u_int	 i, b;
	int	 x, y;
537
	size_t	 len = strlen(augmentation_string) - 1;
538 539 540 541

	retval = xcalloc(1, (FLDSIZE_X + 3) * (FLDSIZE_Y + 2));

	/* initialize field */
542
	memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562
	x = FLDSIZE_X / 2;
	y = FLDSIZE_Y / 2;

	/* process raw key */
	for (i = 0; i < dgst_raw_len; i++) {
		int input;
		/* each byte conveys four 2-bit move commands */
		input = dgst_raw[i];
		for (b = 0; b < 4; b++) {
			/* evaluate 2 bit, rest is shifted later */
			x += (input & 0x1) ? 1 : -1;
			y += (input & 0x2) ? 1 : -1;

			/* assure we are still in bounds */
			x = MAX(x, 0);
			y = MAX(y, 0);
			x = MIN(x, FLDSIZE_X - 1);
			y = MIN(y, FLDSIZE_Y - 1);

			/* augment the field */
563 564
			if (field[x][y] < len - 2)
				field[x][y]++;
565 566 567
			input = input >> 2;
		}
	}
568 569 570 571

	/* mark starting point and end point*/
	field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
	field[x][y] = len;
572 573

	/* fill in retval */
574
	snprintf(retval, FLDSIZE_X, "+--[%4s %4u]", key_type(k), key_size(k));
575
	p = strchr(retval, '\0');
576 577

	/* output upper border */
578
	for (i = p - retval - 1; i < FLDSIZE_X; i++)
579 580 581 582 583 584 585 586
		*p++ = '-';
	*p++ = '+';
	*p++ = '\n';

	/* output content */
	for (y = 0; y < FLDSIZE_Y; y++) {
		*p++ = '|';
		for (x = 0; x < FLDSIZE_X; x++)
587
			*p++ = augmentation_string[MIN(field[x][y], len)];
588 589 590 591 592 593 594 595 596 597 598 599 600
		*p++ = '|';
		*p++ = '\n';
	}

	/* output lower border */
	*p++ = '+';
	for (i = 0; i < FLDSIZE_X; i++)
		*p++ = '-';
	*p++ = '+';

	return retval;
}

601
char *
602
key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
603
{
604
	char *retval = NULL;
605
	u_char *dgst_raw;
606
	u_int dgst_raw_len;
607

608 609
	dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len);
	if (!dgst_raw)
Ben Lindstrom's avatar
Ben Lindstrom committed
610
		fatal("key_fingerprint: null from key_fingerprint_raw()");
611
	switch (dgst_rep) {
612 613 614 615 616 617
	case SSH_FP_HEX:
		retval = key_fingerprint_hex(dgst_raw, dgst_raw_len);
		break;
	case SSH_FP_BUBBLEBABBLE:
		retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
		break;
618
	case SSH_FP_RANDOMART:
619
		retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k);
620
		break;
621
	default:
622
		fatal("key_fingerprint: bad digest representation %d",
623 624 625 626
		    dgst_rep);
		break;
	}
	memset(dgst_raw, 0, dgst_raw_len);
627
	free(dgst_raw);
628 629 630
	return retval;
}

Damien Miller's avatar
Damien Miller committed
631 632 633 634 635 636 637
/*
 * Reads a multiple-precision integer in decimal from the buffer, and advances
 * the pointer.  The integer must already be initialized.  This function is
 * permitted to modify the buffer.  This leaves *cpp to point just beyond the
 * last processed (and maybe modified) character.  Note that this may modify
 * the buffer containing the number.
 */
638
static int
Damien Miller's avatar
Damien Miller committed
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673
read_bignum(char **cpp, BIGNUM * value)
{
	char *cp = *cpp;
	int old;

	/* Skip any leading whitespace. */
	for (; *cp == ' ' || *cp == '\t'; cp++)
		;

	/* Check that it begins with a decimal digit. */
	if (*cp < '0' || *cp > '9')
		return 0;

	/* Save starting position. */
	*cpp = cp;

	/* Move forward until all decimal digits skipped. */
	for (; *cp >= '0' && *cp <= '9'; cp++)
		;

	/* Save the old terminating character, and replace it by \0. */
	old = *cp;
	*cp = 0;

	/* Parse the number. */
	if (BN_dec2bn(&value, *cpp) == 0)
		return 0;

	/* Restore old terminating character. */
	*cp = old;

	/* Move beyond the number and return success. */
	*cpp = cp;
	return 1;
}
674

675
static int
Damien Miller's avatar
Damien Miller committed
676 677 678 679 680 681 682 683
write_bignum(FILE *f, BIGNUM *num)
{
	char *buf = BN_bn2dec(num);
	if (buf == NULL) {
		error("write_bignum: BN_bn2dec() failed");
		return 0;
	}
	fprintf(f, " %s", buf);
684
	OPENSSL_free(buf);
Damien Miller's avatar
Damien Miller committed
685 686
	return 1;
}
687

688
/* returns 1 ok, -1 error */
689
int
690
key_read(Key *ret, char **cpp)
Damien Miller's avatar
Damien Miller committed
691
{
692
	Key *k;
693 694
	int success = -1;
	char *cp, *space;
695
	int len, n, type;
696
	u_int bits;
697
	u_char *blob;
698 699 700
#ifdef OPENSSL_HAS_ECC
	int curve_nid = -1;
#endif
701 702 703

	cp = *cpp;

704
	switch (ret->type) {
705
	case KEY_RSA1:
706 707
		/* Get number of bits. */
		if (*cp < '0' || *cp > '9')
708
			return -1;	/* Bad bit count... */
709 710
		for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
			bits = 10 * bits + *cp - '0';
Damien Miller's avatar
Damien Miller committed
711
		if (bits == 0)
712
			return -1;
713
		*cpp = cp;
Damien Miller's avatar
Damien Miller committed
714 715
		/* Get public exponent, public modulus. */
		if (!read_bignum(cpp, ret->rsa->e))
716
			return -1;
Damien Miller's avatar
Damien Miller committed
717
		if (!read_bignum(cpp, ret->rsa->n))
718
			return -1;
719 720 721 722 723 724
		/* validate the claimed number of bits */
		if ((u_int)BN_num_bits(ret->rsa->n) != bits) {
			verbose("key_read: claimed key size %d does not match "
			   "actual %d", bits, BN_num_bits(ret->rsa->n));
			return -1;
		}
725
		success = 1;
Damien Miller's avatar
Damien Miller committed
726
		break;
727 728
	case KEY_UNSPEC:
	case KEY_RSA:
Damien Miller's avatar
Damien Miller committed
729
	case KEY_DSA:
730
	case KEY_ECDSA:
731
	case KEY_ED25519:
732 733
	case KEY_DSA_CERT_V00:
	case KEY_RSA_CERT_V00:
Damien Miller's avatar
Damien Miller committed
734
	case KEY_DSA_CERT:
735
	case KEY_ECDSA_CERT:
Damien Miller's avatar
Damien Miller committed
736
	case KEY_RSA_CERT:
737
	case KEY_ED25519_CERT:
738 739
		space = strchr(cp, ' ');
		if (space == NULL) {
740
			debug3("key_read: missing whitespace");
741 742 743 744
			return -1;
		}
		*space = '\0';
		type = key_type_from_name(cp);
745
#ifdef OPENSSL_HAS_ECC
746 747 748 749 750
		if (key_type_plain(type) == KEY_ECDSA &&
		    (curve_nid = key_ecdsa_nid_from_name(cp)) == -1) {
			debug("key_read: invalid curve");
			return -1;
		}
751
#endif
752 753
		*space = ' ';
		if (type == KEY_UNSPEC) {
754
			debug3("key_read: missing keytype");
755 756 757 758 759 760 761 762 763 764 765 766
			return -1;
		}
		cp = space+1;
		if (*cp == '\0') {
			debug3("key_read: short string");
			return -1;
		}
		if (ret->type == KEY_UNSPEC) {
			ret->type = type;
		} else if (ret->type != type) {
			/* is a key, but different type */
			debug3("key_read: type mismatch");
767
			return -1;
768
		}
769 770 771
		len = 2*strlen(cp);
		blob = xmalloc(len);
		n = uudecode(cp, blob, len);
772
		if (n < 0) {
773
			error("key_read: uudecode %s failed", cp);
774
			free(blob);
775
			return -1;
776
		}
777
		k = key_from_blob(blob, (u_int)n);
778
		free(blob);
779
		if (k == NULL) {
780 781
			error("key_read: key_from_blob %s failed", cp);
			return -1;
782
		}
783 784 785 786 787
		if (k->type != type) {
			error("key_read: type mismatch: encoding error");
			key_free(k);
			return -1;
		}
788
#ifdef OPENSSL_HAS_ECC
789 790 791 792 793 794
		if (key_type_plain(type) == KEY_ECDSA &&
		    curve_nid != k->ecdsa_nid) {
			error("key_read: type mismatch: EC curve mismatch");
			key_free(k);
			return -1;
		}
795
#endif
796
/*XXXX*/
Damien Miller's avatar
Damien Miller committed
797 798 799 800 801 802 803 804 805 806 807 808
		if (key_is_cert(ret)) {
			if (!key_is_cert(k)) {
				error("key_read: loaded key is not a cert");
				key_free(k);
				return -1;
			}
			if (ret->cert != NULL)
				cert_free(ret->cert);
			ret->cert = k->cert;
			k->cert = NULL;
		}
		if (key_type_plain(ret->type) == KEY_RSA) {
809 810 811 812 813 814 815
			if (ret->rsa != NULL)
				RSA_free(ret->rsa);
			ret->rsa = k->rsa;
			k->rsa = NULL;
#ifdef DEBUG_PK
			RSA_print_fp(stderr, ret->rsa, 8);
#endif
Damien Miller's avatar
Damien Miller committed
816 817
		}
		if (key_type_plain(ret->type) == KEY_DSA) {
818 819 820 821 822 823
			if (ret->dsa != NULL)
				DSA_free(ret->dsa);
			ret->dsa = k->dsa;
			k->dsa = NULL;
#ifdef DEBUG_PK
			DSA_print_fp(stderr, ret->dsa, 8);
824 825
#endif
		}
826
#ifdef OPENSSL_HAS_ECC
827 828 829 830 831 832 833 834 835
		if (key_type_plain(ret->type) == KEY_ECDSA) {
			if (ret->ecdsa != NULL)
				EC_KEY_free(ret->ecdsa);
			ret->ecdsa = k->ecdsa;
			ret->ecdsa_nid = k->ecdsa_nid;
			k->ecdsa = NULL;
			k->ecdsa_nid = -1;
#ifdef DEBUG_PK
			key_dump_ec_key(ret->ecdsa);
836 837
#endif
		}
838
#endif
839 840 841 842 843 844 845 846
		if (key_type_plain(ret->type) == KEY_ED25519) {
			free(ret->ed25519_pk);
			ret->ed25519_pk = k->ed25519_pk;
			k->ed25519_pk = NULL;
#ifdef DEBUG_PK
			/* XXX */
#endif
		}
Damien Miller's avatar
Damien Miller committed
847
		success = 1;
848
/*XXXX*/
849
		key_free(k);
850 851
		if (success != 1)
			break;
852 853 854 855 856 857
		/* advance cp: skip whitespace and data */
		while (*cp == ' ' || *cp == '\t')
			cp++;
		while (*cp != '\0' && *cp != ' ' && *cp != '\t')
			cp++;
		*cpp = cp;
Damien Miller's avatar
Damien Miller committed
858 859
		break;
	default:
860
		fatal("key_read: bad key type: %d", ret->type);
Damien Miller's avatar
Damien Miller committed
861 862
		break;
	}
863
	return success;
Damien Miller's avatar
Damien Miller committed
864
}
865

Damien Miller's avatar
Damien Miller committed
866
int
867
key_write(const Key *key, FILE *f)
Damien Miller's avatar
Damien Miller committed
868
{
869 870
	int n, success = 0;
	u_int len, bits = 0;
871 872
	u_char *blob;
	char *uu;
Damien Miller's avatar
Damien Miller committed
873

Damien Miller's avatar
Damien Miller committed
874 875 876 877 878 879 880 881 882 883 884 885 886 887 888
	if (key_is_cert(key)) {
		if (key->cert == NULL) {
			error("%s: no cert data", __func__);
			return 0;
		}
		if (buffer_len(&key->cert->certblob) == 0) {
			error("%s: no signed certificate blob", __func__);
			return 0;
		}
	}

	switch (key->type) {
	case KEY_RSA1:
		if (key->rsa == NULL)
			return 0;
Damien Miller's avatar
Damien Miller committed
889 890 891 892
		/* size of modulus 'n' */
		bits = BN_num_bits(key->rsa->n);
		fprintf(f, "%u", bits);
		if (write_bignum(f, key->rsa->e) &&
Damien Miller's avatar
Damien Miller committed
893 894 895 896 897
		    write_bignum(f, key->rsa->n))
			return 1;
		error("key_write: failed for RSA key");
		return 0;
	case KEY_DSA:
898
	case KEY_DSA_CERT_V00:
Damien Miller's avatar
Damien Miller committed
899 900 901 902
	case KEY_DSA_CERT:
		if (key->dsa == NULL)
			return 0;
		break;
903
#ifdef OPENSSL_HAS_ECC
904 905 906 907 908
	case KEY_ECDSA:
	case KEY_ECDSA_CERT:
		if (key->ecdsa == NULL)
			return 0;
		break;
909
#endif
910 911 912 913 914
	case KEY_ED25519:
	case KEY_ED25519_CERT:
		if (key->ed25519_pk == NULL)
			return 0;
		break;
Damien Miller's avatar
Damien Miller committed
915
	case KEY_RSA:
916
	case KEY_RSA_CERT_V00:
Damien Miller's avatar
Damien Miller committed
917 918 919 920 921 922
	case KEY_RSA_CERT:
		if (key->rsa == NULL)
			return 0;
		break;
	default:
		return 0;
Damien Miller's avatar
Damien Miller committed
923
	}
Damien Miller's avatar
Damien Miller committed
924 925 926 927 928 929 930 931

	key_to_blob(key, &blob, &len);
	uu = xmalloc(2*len);
	n = uuencode(blob, len, uu, 2*len);
	if (n > 0) {
		fprintf(f, "%s %s", key_ssh_name(key), uu);
		success = 1;
	}
932 933
	free(blob);
	free(uu);
Damien Miller's avatar
Damien Miller committed
934

Damien Miller's avatar
Damien Miller committed
935 936
	return success;
}
937

938 939 940 941 942 943 944 945 946 947 948 949 950
const char *
key_cert_type(const Key *k)
{
	switch (k->cert->type) {
	case SSH2_CERT_TYPE_USER:
		return "user";
	case SSH2_CERT_TYPE_HOST:
		return "host";
	default:
		return "unknown";
	}
}

951 952 953 954 955 956 957 958 959 960 961
struct keytype {
	char *name;
	char *shortname;
	int type;
	int nid;
	int cert;
};
static const struct keytype keytypes[] = {
	{ NULL, "RSA1", KEY_RSA1, 0, 0 },
	{ "ssh-rsa", "RSA", KEY_RSA, 0, 0 },
	{ "ssh-dss", "DSA", KEY_DSA, 0, 0 },
962
	{ "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0 },
963 964 965
#ifdef OPENSSL_HAS_ECC
	{ "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 },
	{ "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 },
966
# ifdef OPENSSL_HAS_NISTP521
967
	{ "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 },
968
# endif
969 970 971 972 973 974 975 976
#endif /* OPENSSL_HAS_ECC */
	{ "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1 },
	{ "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1 },
#ifdef OPENSSL_HAS_ECC
	{ "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT",
	    KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1 },
	{ "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT",
	    KEY_ECDSA_CERT, NID_secp384r1, 1 },
977
# ifdef OPENSSL_HAS_NISTP521
978 979
	{ "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT",
	    KEY_ECDSA_CERT, NID_secp521r1, 1 },
980
# endif
981 982 983 984 985
#endif /* OPENSSL_HAS_ECC */
	{ "ssh-rsa-cert-v00@openssh.com", "RSA-CERT-V00",
	    KEY_RSA_CERT_V00, 0, 1 },
	{ "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00",
	    KEY_DSA_CERT_V00, 0, 1 },
986 987
	{ "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",
	    KEY_ED25519_CERT, 0, 1 },
988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002
	{ NULL, NULL, -1, -1, 0 }
};

const char *
key_type(const Key *k)
{
	const struct keytype *kt;

	for (kt = keytypes; kt->type != -1; kt++) {
		if (kt->type == k->type)
			return kt->shortname;
	}
	return "unknown";
}

1003 1004
static const char *
key_ssh_name_from_type_nid(int type, int nid)
1005
{
1006 1007 1008 1009 1010
	const struct keytype *kt;

	for (kt = keytypes; kt->type != -1; kt++) {
		if (kt->type == type && (kt->nid == 0 || kt->nid == nid))
			return kt->name;
1011 1012 1013
	}
	return "ssh-unknown";
}
1014

1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
const char *
key_ssh_name(const Key *k)
{
	return key_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
}

const char *
key_ssh_name_plain(const Key *k)
{
	return key_ssh_name_from_type_nid(key_type_plain(k->type),
	    k->ecdsa_nid);
}

1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058
int
key_type_from_name(char *name)
{
	const struct keytype *kt;

	for (kt = keytypes; kt->type != -1; kt++) {
		/* Only allow shortname matches for plain key types */
		if ((kt->name != NULL && strcmp(name, kt->name) == 0) ||
		    (!kt->cert && strcasecmp(kt->shortname, name) == 0))
			return kt->type;
	}
	debug2("key_type_from_name: unknown key type '%s'", name);
	return KEY_UNSPEC;
}

int
key_ecdsa_nid_from_name(const char *name)
{
	const struct keytype *kt;

	for (kt = keytypes; kt->type != -1; kt++) {
		if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT)
			continue;
		if (kt->name != NULL && strcmp(name, kt->name) == 0)
			return kt->nid;
	}
	debug2("%s: unknown/non-ECDSA key type '%s'", __func__, name);
	return -1;
}

char *
1059
key_alg_list(int certs_only, int plain_only)
1060 1061 1062 1063 1064 1065 1066 1067
{
	char *ret = NULL;
	size_t nlen, rlen = 0;
	const struct keytype *kt;

	for (kt = keytypes; kt->type != -1; kt++) {
		if (kt->name == NULL)
			continue;
1068 1069
		if ((certs_only && !kt->cert) || (plain_only && kt->cert))
			continue;
1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
		if (ret != NULL)
			ret[rlen++] = '\n';
		nlen = strlen(kt->name);
		ret = xrealloc(ret, 1, rlen + nlen + 2);
		memcpy(ret + rlen, kt->name, nlen + 1);
		rlen += nlen;
	}
	return ret;
}

1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091
int
key_type_is_cert(int type)
{
	const struct keytype *kt;

	for (kt = keytypes; kt->type != -1; kt++) {
		if (kt->type == type)
			return kt->cert;
	}
	return 0;
}

1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
static int
key_type_is_valid_ca(int type)
{
	switch (type) {
	case KEY_RSA:
	case KEY_DSA:
	case KEY_ECDSA:
	case KEY_ED25519:
		return 1;
	default:
		return 0;
	}
}

1106
u_int
1107
key_size(const Key *k)
1108
{
1109
	switch (k->type) {
1110
	case KEY_RSA1:
1111
	case KEY_RSA:
1112
	case KEY_RSA_CERT_V00:
Damien Miller's avatar
Damien Miller committed
1113
	case KEY_RSA_CERT:
1114 1115
		return BN_num_bits(k->rsa->n);
	case KEY_DSA:
1116
	case KEY_DSA_CERT_V00:
Damien Miller's avatar
Damien Miller committed
1117
	case KEY_DSA_CERT:
1118
		return BN_num_bits(k->dsa->p);
1119 1120
	case KEY_ED25519:
		return 256;	/* XXX */
1121
#ifdef OPENSSL_HAS_ECC
1122 1123
	case KEY_ECDSA:
	case KEY_ECDSA_CERT:
1124
		return key_curve_nid_to_bits(k->ecdsa_nid);
1125
#endif
1126 1127 1128
	}
	return 0;
}
1129

1130
static RSA *
1131
rsa_generate_private_key(u_int bits)
1132
{
1133 1134
	RSA *private = RSA_new();
	BIGNUM *f4 = BN_new();
1135

1136
	if (private == NULL)
1137 1138 1139 1140 1141 1142 1143 1144
		fatal("%s: RSA_new failed", __func__);
	if (f4 == NULL)
		fatal("%s: BN_new failed", __func__);
	if (!BN_set_word(f4, RSA_F4))
		fatal("%s: BN_new failed", __func__);
	if (!RSA_generate_key_ex(private, bits, f4, NULL))
		fatal("%s: key generation failed.", __func__);
	BN_free(f4);
1145
	return private;
1146 1147
}

1148
static DSA*
1149
dsa_generate_private_key(u_int bits)
1150
{
1151
	DSA *private = DSA_new();
1152

1153
	if (private == NULL)
1154 1155 1156 1157
		fatal("%s: DSA_new failed", __func__);
	if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL,
	    NULL, NULL))
		fatal("%s: DSA_generate_parameters failed", __func__);
1158
	if (!DSA_generate_key(private))
1159
		fatal("%s: DSA_generate_key failed.", __func__);
1160 1161 1162
	return private;
}

1163 1164 1165 1166
int
key_ecdsa_bits_to_nid(int bits)
{
	switch (bits) {
1167
#ifdef OPENSSL_HAS_ECC
1168 1169 1170 1171
	case 256:
		return NID_X9_62_prime256v1;
	case 384:
		return NID_secp384r1;
1172
# ifdef OPENSSL_HAS_NISTP521
1173 1174
	case 521:
		return NID_secp521r1;
1175
# endif
1176
#endif
1177 1178 1179 1180 1181
	default:
		return -1;
	}
}

1182
#ifdef OPENSSL_HAS_ECC
1183
int
1184
key_ecdsa_key_to_nid(EC_KEY *k)
1185 1186 1187 1188 1189
{
	EC_GROUP *eg;
	int nids[] = {
		NID_X9_62_prime256v1,
		NID_secp384r1,
1190
# ifdef OPENSSL_HAS_NISTP521
1191
		NID_secp521r1,
1192
# endif
1193 1194
		-1
	};
1195
	int nid;
1196 1197
	u_int i;
	BN_CTX *bnctx;
1198
	const EC_GROUP *g = EC_KEY_get0_group(k);
1199

1200 1201 1202 1203 1204 1205 1206 1207 1208 1209
	/*
	 * The group may be stored in a ASN.1 encoded private key in one of two
	 * ways: as a "named group", which is reconstituted by ASN.1 object ID
	 * or explicit group parameters encoded into the key blob. Only the
	 * "named group" case sets the group NID for us, but we can figure
	 * it out for the other case by comparing against all the groups that
	 * are supported.
	 */
	if ((nid = EC_GROUP_get_curve_name(g)) > 0)
		return nid;
1210 1211 1212 1213 1214 1215
	if ((bnctx = BN_CTX_new()) == NULL)
		fatal("%s: BN_CTX_new() failed", __func__);
	for (i = 0; nids[i] != -1; i++) {
		if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL)
			fatal("%s: EC_GROUP_new_by_curve_name failed",
			    __func__);
1216
		if (EC_GROUP_cmp(g, eg, bnctx) == 0)
1217 1218 1219 1220 1221
			break;
		EC_GROUP_free(eg);
	}
	BN_CTX_free(bnctx);
	debug3("%s: nid = %d", __func__, nids[i]);
1222 1223 1224 1225 1226 1227
	if (nids[i] != -1) {
		/* Use the group with the NID attached */
		EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
		if (EC_KEY_set_group(k, eg) != 1)
			fatal("%s: EC_KEY_set_group", __func__);
	}
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241
	return nids[i];
}

static EC_KEY*
ecdsa_generate_private_key(u_int bits, int *nid)
{
	EC_KEY *private;

	if ((*nid = key_ecdsa_bits_to_nid(bits)) == -1)
		fatal("%s: invalid key length", __func__);
	if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL)
		fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
	if (EC_KEY_generate_key(private) != 1)
		fatal("%s: EC_KEY_generate_key failed", __func__);
1242
	EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE);
1243 1244
	return private;
}
1245
#endif /* OPENSSL_HAS_ECC */
1246

1247
Key *
1248
key_generate(int type, u_int bits)
1249 1250 1251
{
	Key *k = key_new(KEY_UNSPEC);
	switch (type) {
1252
	case KEY_DSA:
1253 1254
		k->dsa = dsa_generate_private_key(bits);
		break;
1255
#ifdef OPENSSL_HAS_ECC
1256 1257 1258
	case KEY_ECDSA:
		k->ecdsa = ecdsa_generate_private_key(bits, &k->ecdsa_nid);
		break;
1259
#endif
1260 1261 1262 1263
	case KEY_RSA:
	case KEY_RSA1:
		k->rsa = rsa_generate_private_key(bits);
		break;
1264 1265 1266 1267 1268
	case KEY_ED25519:
		k->ed25519_pk = xmalloc(ED25519_PK_SZ);
		k->ed25519_sk = xmalloc(ED25519_SK_SZ);
		crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk);
		break;
1269 1270
	case KEY_RSA_CERT_V00:
	case KEY_DSA_CERT_V00:
Damien Miller's avatar
Damien Miller committed
1271 1272 1273
	case KEY_RSA_CERT:
	case KEY_DSA_CERT:
		fatal("key_generate: cert keys cannot be generated directly");
1274
	default:
1275
		fatal("key_generate: unknown type %d", type);
1276
	}
1277
	k->type = type;
1278 1279 1280
	return k;
}

Damien Miller's avatar
Damien Miller committed
1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300
void
key_cert_copy(const Key *from_key, struct Key *to_key)
{
	u_int i;
	const struct KeyCert *from;
	struct KeyCert *to;

	if (to_key->cert != NULL) {
		cert_free(to_key->cert);
		to_key->cert = NULL;
	}

	if ((from = from_key->cert) == NULL)
		return;

	to = to_key->cert = cert_new();

	buffer_append(&to->certblob, buffer_ptr(&from->certblob),
	    buffer_len(&from->certblob));

1301 1302 1303 1304
	buffer_append(&to->critical,
	    buffer_ptr(&from->critical), buffer_len(&from->critical));
	buffer_append(&to->extensions,
	    buffer_ptr(&from->extensions), buffer_len(&from->extensions));
Damien Miller's avatar
Damien Miller committed
1305

1306
	to->serial = from->serial;
Damien Miller's avatar
Damien Miller committed
1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325
	to->type = from->type;
	to->key_id = from->key_id == NULL ? NULL : xstrdup(from->key_id);
	to->valid_after = from->valid_after;
	to->valid_before = from->valid_before;
	to->signature_key = from->signature_key == NULL ?
	    NULL : key_from_private(from->signature_key);

	to->nprincipals = from->nprincipals;
	if (to->nprincipals > CERT_MAX_PRINCIPALS)
		fatal("%s: nprincipals (%u) > CERT_MAX_PRINCIPALS (%u)",
		    __func__, to->nprincipals, CERT_MAX_PRINCIPALS);
	if (to->nprincipals > 0) {
		to->principals = xcalloc(from->nprincipals,
		    sizeof(*to->principals));
		for (i = 0; i < to->nprincipals; i++)
			to->principals[i] = xstrdup(from->principals[i]);
	}
}

1326
Key *
1327
key_from_private(const Key *k)
1328 1329 1330
{
	Key *n = NULL;
	switch (k->type) {
1331
	case KEY_DSA:
1332
	case KEY_DSA_CERT_V00:
Damien Miller's avatar
Damien Miller committed
1333
	case KEY_DSA_CERT:
1334
		n = key_new(k->type);
1335 1336 1337 1338 1339
		if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
		    (BN_copy(n->dsa->q, k->dsa->q) == NULL) ||
		    (BN_copy(n->dsa->g, k->dsa->g) == NULL) ||
		    (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL))
			fatal("key_from_private: BN_copy failed");
1340
		break;
1341
#ifdef OPENSSL_HAS_ECC
1342 1343 1344 1345 1346 1347 1348 1349 1350 1351
	case KEY_ECDSA:
	case KEY_ECDSA_CERT:
		n = key_new(k->type);
		n->ecdsa_nid = k->ecdsa_nid;
		if ((n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL)
			fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
		if (EC_KEY_set_public_key(n->ecdsa,
		    EC_KEY_get0_public_key(k->ecdsa)) != 1)
			fatal("%s: EC_KEY_set_public_key failed", __func__);
		break;
1352
#endif
1353 1354
	case KEY_RSA:
	case KEY_RSA1: