11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: key.c,v 1.97 2011/05/17 07:13:31 djm Exp $ */
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * read_bignum():
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * As far as I am concerned, the code I have written for this software
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * can be used freely for any purpose.  Any derived versions of this
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * software must be clearly marked as such, and if the derived work is
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * incompatible with the protocol description in the RFC file, it must be
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * called by a name other than "ssh" or "Secure Shell".
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Redistribution and use in source and binary forms, with or without
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * modification, are permitted provided that the following conditions
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * are met:
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 1. Redistributions of source code must retain the above copyright
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer.
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 2. Redistributions in binary form must reproduce the above copyright
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer in the
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    documentation and/or other materials provided with the distribution.
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/param.h>
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <openssl/evp.h>
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <openbsd-compat/openssl-compat.h>
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h>
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdio.h>
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h"
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "key.h"
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "rsa.h"
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "uuencode.h"
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h"
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h"
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "misc.h"
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh2.h"
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic struct KeyCert *
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcert_new(void)
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct KeyCert *cert;
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	cert = xcalloc(1, sizeof(*cert));
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&cert->certblob);
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&cert->critical);
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&cert->extensions);
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	cert->key_id = NULL;
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	cert->principals = NULL;
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	cert->signature_key = NULL;
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return cert;
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodKey *
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_new(int type)
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *k;
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	RSA *rsa;
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	DSA *dsa;
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	k = xcalloc(1, sizeof(*k));
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	k->type = type;
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	k->ecdsa = NULL;
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	k->ecdsa_nid = -1;
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	k->dsa = NULL;
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	k->rsa = NULL;
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	k->cert = NULL;
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (k->type) {
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA1:
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((rsa = RSA_new()) == NULL)
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_new: RSA_new failed");
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((rsa->n = BN_new()) == NULL)
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_new: BN_new failed");
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((rsa->e = BN_new()) == NULL)
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_new: BN_new failed");
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->rsa = rsa;
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((dsa = DSA_new()) == NULL)
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_new: DSA_new failed");
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((dsa->p = BN_new()) == NULL)
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_new: BN_new failed");
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((dsa->q = BN_new()) == NULL)
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_new: BN_new failed");
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((dsa->g = BN_new()) == NULL)
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_new: BN_new failed");
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((dsa->pub_key = BN_new()) == NULL)
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_new: BN_new failed");
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->dsa = dsa;
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Cannot do anything until we know the group */
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_UNSPEC:
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("key_new: bad key type %d", k->type);
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key_is_cert(k))
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->cert = cert_new();
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return k;
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_add_private(Key *k)
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (k->type) {
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA1:
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((k->rsa->d = BN_new()) == NULL)
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_new_private: BN_new failed");
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((k->rsa->iqmp = BN_new()) == NULL)
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_new_private: BN_new failed");
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((k->rsa->q = BN_new()) == NULL)
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_new_private: BN_new failed");
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((k->rsa->p = BN_new()) == NULL)
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_new_private: BN_new failed");
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((k->rsa->dmq1 = BN_new()) == NULL)
1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_new_private: BN_new failed");
1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((k->rsa->dmp1 = BN_new()) == NULL)
1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_new_private: BN_new failed");
1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((k->dsa->priv_key = BN_new()) == NULL)
1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_new_private: BN_new failed");
1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Cannot do anything until we know the group */
1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_UNSPEC:
1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodKey *
1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_new_private(int type)
1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *k = key_new(type);
1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	key_add_private(k);
1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return k;
1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcert_free(struct KeyCert *cert)
1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i;
1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&cert->certblob);
1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&cert->critical);
1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&cert->extensions);
1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (cert->key_id != NULL)
1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(cert->key_id);
1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < cert->nprincipals; i++)
1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(cert->principals[i]);
1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (cert->principals != NULL)
1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(cert->principals);
1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (cert->signature_key != NULL)
1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key_free(cert->signature_key);
1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_free(Key *k)
2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (k == NULL)
2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("key_free: key is NULL");
2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (k->type) {
2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA1:
2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (k->rsa != NULL)
2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			RSA_free(k->rsa);
2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->rsa = NULL;
2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (k->dsa != NULL)
2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			DSA_free(k->dsa);
2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->dsa = NULL;
2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (k->ecdsa != NULL)
2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			EC_KEY_free(k->ecdsa);
2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->ecdsa = NULL;
2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_UNSPEC:
2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("key_free: bad key type %d", k->type);
2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key_is_cert(k)) {
2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (k->cert != NULL)
2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			cert_free(k->cert);
2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->cert = NULL;
2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(k);
2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcert_compare(struct KeyCert *a, struct KeyCert *b)
2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (a == NULL && b == NULL)
2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 1;
2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (a == NULL || b == NULL)
2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (buffer_len(&a->certblob) != buffer_len(&b->certblob))
2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (timingsafe_bcmp(buffer_ptr(&a->certblob), buffer_ptr(&b->certblob),
2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buffer_len(&a->certblob)) != 0)
2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Compare public portions of key only, allowing comparisons between
2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * certificates and plain keys too.
2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_equal_public(const Key *a, const Key *b)
2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BN_CTX *bnctx;
2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (a == NULL || b == NULL ||
2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    key_type_plain(a->type) != key_type_plain(b->type))
2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (a->type) {
2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA1:
2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return a->rsa != NULL && b->rsa != NULL &&
2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    BN_cmp(a->rsa->n, b->rsa->n) == 0;
2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return a->dsa != NULL && b->dsa != NULL &&
2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (a->ecdsa == NULL || b->ecdsa == NULL ||
2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    EC_KEY_get0_public_key(a->ecdsa) == NULL ||
2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    EC_KEY_get0_public_key(b->ecdsa) == NULL)
2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((bnctx = BN_CTX_new()) == NULL)
2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("%s: BN_CTX_new failed", __func__);
2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa),
2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    EC_KEY_get0_group(b->ecdsa), bnctx) != 0 ||
2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa),
3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    EC_KEY_get0_public_key(a->ecdsa),
3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) {
3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			BN_CTX_free(bnctx);
3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		BN_CTX_free(bnctx);
3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 1;
3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* OPENSSL_HAS_ECC */
3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("key_equal: bad key type %d", a->type);
3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* NOTREACHED */
3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_equal(const Key *a, const Key *b)
3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (a == NULL || b == NULL || a->type != b->type)
3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
3191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key_is_cert(a)) {
3201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!cert_compare(a->cert, b->cert))
3211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
3221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return key_equal_public(a, b);
3241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodu_char*
3271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length)
3281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const EVP_MD *md = NULL;
3301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	EVP_MD_CTX ctx;
3311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *blob = NULL;
3321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *retval = NULL;
3331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int len = 0;
3341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int nlen, elen, otype;
3351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*dgst_raw_length = 0;
3371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (dgst_type) {
3391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH_FP_MD5:
3401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		md = EVP_md5();
3411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
3421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH_FP_SHA1:
3431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		md = EVP_sha1();
3441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
3451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
3461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("key_fingerprint_raw: bad digest type %d",
3471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    dgst_type);
3481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (k->type) {
3501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA1:
3511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		nlen = BN_num_bytes(k->rsa->n);
3521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		elen = BN_num_bytes(k->rsa->e);
3531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		len = nlen + elen;
3541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		blob = xmalloc(len);
3551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		BN_bn2bin(k->rsa->n, blob);
3561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		BN_bn2bin(k->rsa->e, blob + nlen);
3571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
3581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
3591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
3601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
3611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key_to_blob(k, &blob, &len);
3621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
3631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
3641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
3651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
3661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
3671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
3681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* We want a fingerprint of the _key_ not of the cert */
3691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		otype = k->type;
3701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->type = key_type_plain(k->type);
3711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key_to_blob(k, &blob, &len);
3721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->type = otype;
3731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
3741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_UNSPEC:
3751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return retval;
3761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
3771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("key_fingerprint_raw: bad key type %d", k->type);
3781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
3791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (blob != NULL) {
3811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		retval = xmalloc(EVP_MAX_MD_SIZE);
3821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		EVP_DigestInit(&ctx, md);
3831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		EVP_DigestUpdate(&ctx, blob, len);
3841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		EVP_DigestFinal(&ctx, retval, dgst_raw_length);
3851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		memset(blob, 0, len);
3861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(blob);
3871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
3881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("key_fingerprint_raw: blob is null");
3891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return retval;
3911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *
3941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len)
3951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *retval;
3971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i;
3981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	retval = xcalloc(1, dgst_raw_len * 3 + 1);
4001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < dgst_raw_len; i++) {
4011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		char hex[4];
4021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
4031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		strlcat(retval, hex, dgst_raw_len * 3 + 1);
4041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Remove the trailing ':' character */
4071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	retval[(dgst_raw_len * 3) - 1] = '\0';
4081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return retval;
4091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *
4121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len)
4131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
4151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
4161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
4171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i, j = 0, rounds, seed = 1;
4181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *retval;
4191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	rounds = (dgst_raw_len / 2) + 1;
4211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	retval = xcalloc((rounds * 6), sizeof(char));
4221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	retval[j++] = 'x';
4231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < rounds; i++) {
4241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		u_int idx0, idx1, idx2, idx3, idx4;
4251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
4261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
4271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    seed) % 6;
4281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
4291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
4301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    (seed / 6)) % 6;
4311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			retval[j++] = vowels[idx0];
4321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			retval[j++] = consonants[idx1];
4331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			retval[j++] = vowels[idx2];
4341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if ((i + 1) < rounds) {
4351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
4361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
4371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				retval[j++] = consonants[idx3];
4381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				retval[j++] = '-';
4391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				retval[j++] = consonants[idx4];
4401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				seed = ((seed * 5) +
4411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    ((((u_int)(dgst_raw[2 * i])) * 7) +
4421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
4431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
4441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
4451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			idx0 = seed % 6;
4461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			idx1 = 16;
4471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			idx2 = seed / 6;
4481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			retval[j++] = vowels[idx0];
4491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			retval[j++] = consonants[idx1];
4501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			retval[j++] = vowels[idx2];
4511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	retval[j++] = 'x';
4541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	retval[j++] = '\0';
4551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return retval;
4561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
4591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Draw an ASCII-Art representing the fingerprint so human brain can
4601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * profit from its built-in pattern recognition ability.
4611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * This technique is called "random art" and can be found in some
4621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * scientific publications like this original paper:
4631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
4641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * "Hash Visualization: a New Technique to improve Real-World Security",
4651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Perrig A. and Song D., 1999, International Workshop on Cryptographic
4661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Techniques and E-Commerce (CrypTEC '99)
4671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
4681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
4691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * The subject came up in a talk by Dan Kaminsky, too.
4701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
4711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * If you see the picture is different, the key is different.
4721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * If the picture looks the same, you still know nothing.
4731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
4741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * The algorithm used here is a worm crawling over a discrete plane,
4751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * leaving a trace (augmenting the field) everywhere it goes.
4761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Movement is taken from dgst_raw 2bit-wise.  Bumping into walls
4771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * makes the respective movement vector be ignored for this turn.
4781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Graphs are not unambiguous, because circles in graphs can be
4791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * walked in either direction.
4801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
4811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
4831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Field sizes for the random art.  Have to be odd, so the starting point
4841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * can be in the exact middle of the picture, and FLDBASE should be >=8 .
4851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Else pictures would be too dense, and drawing the frame would
4861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * fail, too, because the key type would not fit in anymore.
4871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
4881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define	FLDBASE		8
4891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define	FLDSIZE_Y	(FLDBASE + 1)
4901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define	FLDSIZE_X	(FLDBASE * 2 + 1)
4911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *
4921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k)
4931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
4951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Chars to be used after each other every time the worm
4961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * intersects with itself.  Matter of taste.
4971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
4981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char	*augmentation_string = " .o+=*BOX@%&#/^SE";
4991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char	*retval, *p;
5001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char	 field[FLDSIZE_X][FLDSIZE_Y];
5011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int	 i, b;
5021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int	 x, y;
5031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	size_t	 len = strlen(augmentation_string) - 1;
5041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	retval = xcalloc(1, (FLDSIZE_X + 3) * (FLDSIZE_Y + 2));
5061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* initialize field */
5081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
5091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	x = FLDSIZE_X / 2;
5101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	y = FLDSIZE_Y / 2;
5111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* process raw key */
5131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < dgst_raw_len; i++) {
5141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		int input;
5151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* each byte conveys four 2-bit move commands */
5161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		input = dgst_raw[i];
5171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (b = 0; b < 4; b++) {
5181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* evaluate 2 bit, rest is shifted later */
5191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			x += (input & 0x1) ? 1 : -1;
5201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			y += (input & 0x2) ? 1 : -1;
5211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* assure we are still in bounds */
5231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			x = MAX(x, 0);
5241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			y = MAX(y, 0);
5251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			x = MIN(x, FLDSIZE_X - 1);
5261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			y = MIN(y, FLDSIZE_Y - 1);
5271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* augment the field */
5291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (field[x][y] < len - 2)
5301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				field[x][y]++;
5311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			input = input >> 2;
5321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
5331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* mark starting point and end point*/
5361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
5371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	field[x][y] = len;
5381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* fill in retval */
5401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	snprintf(retval, FLDSIZE_X, "+--[%4s %4u]", key_type(k), key_size(k));
5411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p = strchr(retval, '\0');
5421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* output upper border */
5441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = p - retval - 1; i < FLDSIZE_X; i++)
5451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*p++ = '-';
5461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*p++ = '+';
5471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*p++ = '\n';
5481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* output content */
5501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (y = 0; y < FLDSIZE_Y; y++) {
5511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*p++ = '|';
5521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (x = 0; x < FLDSIZE_X; x++)
5531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*p++ = augmentation_string[MIN(field[x][y], len)];
5541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*p++ = '|';
5551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*p++ = '\n';
5561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* output lower border */
5591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*p++ = '+';
5601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < FLDSIZE_X; i++)
5611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*p++ = '-';
5621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*p++ = '+';
5631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return retval;
5651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar *
5681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
5691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
5701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *retval = NULL;
5711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *dgst_raw;
5721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int dgst_raw_len;
5731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len);
5751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!dgst_raw)
5761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("key_fingerprint: null from key_fingerprint_raw()");
5771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (dgst_rep) {
5781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH_FP_HEX:
5791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		retval = key_fingerprint_hex(dgst_raw, dgst_raw_len);
5801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
5811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH_FP_BUBBLEBABBLE:
5821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
5831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
5841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH_FP_RANDOMART:
5851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k);
5861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
5871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
5881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("key_fingerprint: bad digest representation %d",
5891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    dgst_rep);
5901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
5911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(dgst_raw, 0, dgst_raw_len);
5931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(dgst_raw);
5941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return retval;
5951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
5981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Reads a multiple-precision integer in decimal from the buffer, and advances
5991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * the pointer.  The integer must already be initialized.  This function is
6001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * permitted to modify the buffer.  This leaves *cpp to point just beyond the
6011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * last processed (and maybe modified) character.  Note that this may modify
6021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * the buffer containing the number.
6031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
6041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
6051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodread_bignum(char **cpp, BIGNUM * value)
6061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *cp = *cpp;
6081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int old;
6091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Skip any leading whitespace. */
6111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (; *cp == ' ' || *cp == '\t'; cp++)
6121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		;
6131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Check that it begins with a decimal digit. */
6151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*cp < '0' || *cp > '9')
6161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
6171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Save starting position. */
6191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*cpp = cp;
6201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Move forward until all decimal digits skipped. */
6221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (; *cp >= '0' && *cp <= '9'; cp++)
6231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		;
6241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Save the old terminating character, and replace it by \0. */
6261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	old = *cp;
6271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*cp = 0;
6281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Parse the number. */
6301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (BN_dec2bn(&value, *cpp) == 0)
6311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
6321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Restore old terminating character. */
6341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*cp = old;
6351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Move beyond the number and return success. */
6371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*cpp = cp;
6381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
6391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
6421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodwrite_bignum(FILE *f, BIGNUM *num)
6431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *buf = BN_bn2dec(num);
6451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (buf == NULL) {
6461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("write_bignum: BN_bn2dec() failed");
6471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
6481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fprintf(f, " %s", buf);
6501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	OPENSSL_free(buf);
6511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
6521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* returns 1 ok, -1 error */
6551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
6561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_read(Key *ret, char **cpp)
6571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *k;
6591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int success = -1;
6601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *cp, *space;
6611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int len, n, type;
6621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int bits;
6631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *blob;
6641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
6651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int curve_nid = -1;
6661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
6671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	cp = *cpp;
6691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (ret->type) {
6711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA1:
6721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Get number of bits. */
6731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*cp < '0' || *cp > '9')
6741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;	/* Bad bit count... */
6751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
6761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			bits = 10 * bits + *cp - '0';
6771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (bits == 0)
6781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
6791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*cpp = cp;
6801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Get public exponent, public modulus. */
6811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!read_bignum(cpp, ret->rsa->e))
6821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
6831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!read_bignum(cpp, ret->rsa->n))
6841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
6851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* validate the claimed number of bits */
6861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((u_int)BN_num_bits(ret->rsa->n) != bits) {
6871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			verbose("key_read: claimed key size %d does not match "
6881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			   "actual %d", bits, BN_num_bits(ret->rsa->n));
6891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
6901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
6911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		success = 1;
6921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
6931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_UNSPEC:
6941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
6951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
6961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
6971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
6981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
6991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
7001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
7011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
7021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		space = strchr(cp, ' ');
7031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (space == NULL) {
7041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug3("key_read: missing whitespace");
7051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
7061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*space = '\0';
7081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		type = key_type_from_name(cp);
7091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
7101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key_type_plain(type) == KEY_ECDSA &&
7111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (curve_nid = key_ecdsa_nid_from_name(cp)) == -1) {
7121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("key_read: invalid curve");
7131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
7141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
7161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*space = ' ';
7171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (type == KEY_UNSPEC) {
7181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug3("key_read: missing keytype");
7191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
7201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cp = space+1;
7221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*cp == '\0') {
7231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug3("key_read: short string");
7241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
7251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (ret->type == KEY_UNSPEC) {
7271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ret->type = type;
7281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (ret->type != type) {
7291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* is a key, but different type */
7301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug3("key_read: type mismatch");
7311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
7321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		len = 2*strlen(cp);
7341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		blob = xmalloc(len);
7351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		n = uudecode(cp, blob, len);
7361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (n < 0) {
7371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("key_read: uudecode %s failed", cp);
7381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(blob);
7391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
7401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k = key_from_blob(blob, (u_int)n);
7421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(blob);
7431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (k == NULL) {
7441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("key_read: key_from_blob %s failed", cp);
7451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
7461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (k->type != type) {
7481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("key_read: type mismatch: encoding error");
7491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			key_free(k);
7501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
7511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
7531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key_type_plain(type) == KEY_ECDSA &&
7541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    curve_nid != k->ecdsa_nid) {
7551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("key_read: type mismatch: EC curve mismatch");
7561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			key_free(k);
7571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
7581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
7601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*XXXX*/
7611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key_is_cert(ret)) {
7621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (!key_is_cert(k)) {
7631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				error("key_read: loaded key is not a cert");
7641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				key_free(k);
7651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				return -1;
7661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
7671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (ret->cert != NULL)
7681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				cert_free(ret->cert);
7691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ret->cert = k->cert;
7701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			k->cert = NULL;
7711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key_type_plain(ret->type) == KEY_RSA) {
7731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (ret->rsa != NULL)
7741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				RSA_free(ret->rsa);
7751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ret->rsa = k->rsa;
7761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			k->rsa = NULL;
7771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_PK
7781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			RSA_print_fp(stderr, ret->rsa, 8);
7791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
7801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key_type_plain(ret->type) == KEY_DSA) {
7821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (ret->dsa != NULL)
7831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				DSA_free(ret->dsa);
7841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ret->dsa = k->dsa;
7851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			k->dsa = NULL;
7861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_PK
7871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			DSA_print_fp(stderr, ret->dsa, 8);
7881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
7891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
7911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key_type_plain(ret->type) == KEY_ECDSA) {
7921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (ret->ecdsa != NULL)
7931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				EC_KEY_free(ret->ecdsa);
7941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ret->ecdsa = k->ecdsa;
7951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ret->ecdsa_nid = k->ecdsa_nid;
7961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			k->ecdsa = NULL;
7971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			k->ecdsa_nid = -1;
7981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_PK
7991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			key_dump_ec_key(ret->ecdsa);
8001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
8011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
8021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
8031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		success = 1;
8041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*XXXX*/
8051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key_free(k);
8061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (success != 1)
8071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
8081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* advance cp: skip whitespace and data */
8091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		while (*cp == ' ' || *cp == '\t')
8101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			cp++;
8111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		while (*cp != '\0' && *cp != ' ' && *cp != '\t')
8121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			cp++;
8131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*cpp = cp;
8141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
8161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("key_read: bad key type: %d", ret->type);
8171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return success;
8201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
8231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_write(const Key *key, FILE *f)
8241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int n, success = 0;
8261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int len, bits = 0;
8271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *blob;
8281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *uu;
8291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key_is_cert(key)) {
8311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key->cert == NULL) {
8321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("%s: no cert data", __func__);
8331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
8341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
8351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (buffer_len(&key->cert->certblob) == 0) {
8361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("%s: no signed certificate blob", __func__);
8371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
8381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
8391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (key->type) {
8421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA1:
8431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key->rsa == NULL)
8441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
8451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* size of modulus 'n' */
8461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		bits = BN_num_bits(key->rsa->n);
8471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fprintf(f, "%u", bits);
8481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (write_bignum(f, key->rsa->e) &&
8491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    write_bignum(f, key->rsa->n))
8501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 1;
8511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("key_write: failed for RSA key");
8521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
8531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
8541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
8551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
8561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key->dsa == NULL)
8571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
8581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
8601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
8611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
8621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key->ecdsa == NULL)
8631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
8641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
8661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
8671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
8681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
8691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key->rsa == NULL)
8701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
8711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
8731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
8741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	key_to_blob(key, &blob, &len);
8771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	uu = xmalloc(2*len);
8781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	n = uuencode(blob, len, uu, 2*len);
8791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (n > 0) {
8801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fprintf(f, "%s %s", key_ssh_name(key), uu);
8811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		success = 1;
8821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(blob);
8841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(uu);
8851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return success;
8871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodconst char *
8901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_type(const Key *k)
8911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (k->type) {
8931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA1:
8941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "RSA1";
8951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
8961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "RSA";
8971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
8981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "DSA";
8991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
9001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
9011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "ECDSA";
9021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
9031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
9041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "RSA-CERT-V00";
9051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
9061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "DSA-CERT-V00";
9071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
9081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "RSA-CERT";
9091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
9101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "DSA-CERT";
9111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
9121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
9131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "ECDSA-CERT";
9141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
9151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return "unknown";
9171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodconst char *
9201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_cert_type(const Key *k)
9211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (k->cert->type) {
9231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH2_CERT_TYPE_USER:
9241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "user";
9251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH2_CERT_TYPE_HOST:
9261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "host";
9271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
9281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "unknown";
9291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic const char *
9331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_ssh_name_from_type_nid(int type, int nid)
9341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (type) {
9361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
9371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "ssh-rsa";
9381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
9391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "ssh-dss";
9401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
9411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "ssh-rsa-cert-v00@openssh.com";
9421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
9431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "ssh-dss-cert-v00@openssh.com";
9441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
9451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "ssh-rsa-cert-v01@openssh.com";
9461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
9471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "ssh-dss-cert-v01@openssh.com";
9481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
9491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
9501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (nid) {
9511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case NID_X9_62_prime256v1:
9521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return "ecdsa-sha2-nistp256";
9531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case NID_secp384r1:
9541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return "ecdsa-sha2-nistp384";
9551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case NID_secp521r1:
9561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return "ecdsa-sha2-nistp521";
9571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
9581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
9591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
9601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
9611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
9621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (nid) {
9631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case NID_X9_62_prime256v1:
9641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return "ecdsa-sha2-nistp256-cert-v01@openssh.com";
9651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case NID_secp384r1:
9661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return "ecdsa-sha2-nistp384-cert-v01@openssh.com";
9671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case NID_secp521r1:
9681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return "ecdsa-sha2-nistp521-cert-v01@openssh.com";
9691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
9701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
9711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
9721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
9731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* OPENSSL_HAS_ECC */
9741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return "ssh-unknown";
9761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodconst char *
9791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_ssh_name(const Key *k)
9801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return key_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
9821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodconst char *
9851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_ssh_name_plain(const Key *k)
9861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return key_ssh_name_from_type_nid(key_type_plain(k->type),
9881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    k->ecdsa_nid);
9891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodu_int
9921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_size(const Key *k)
9931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (k->type) {
9951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA1:
9961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
9971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
9981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
9991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return BN_num_bits(k->rsa->n);
10001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
10011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
10021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
10031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return BN_num_bits(k->dsa->p);
10041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
10051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
10061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
10071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return key_curve_nid_to_bits(k->ecdsa_nid);
10081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
10091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
10101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
10111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic RSA *
10141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodrsa_generate_private_key(u_int bits)
10151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	RSA *private = RSA_new();
10171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BIGNUM *f4 = BN_new();
10181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (private == NULL)
10201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: RSA_new failed", __func__);
10211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (f4 == NULL)
10221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_new failed", __func__);
10231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!BN_set_word(f4, RSA_F4))
10241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_new failed", __func__);
10251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!RSA_generate_key_ex(private, bits, f4, NULL))
10261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: key generation failed.", __func__);
10271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BN_free(f4);
10281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return private;
10291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic DSA*
10321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddsa_generate_private_key(u_int bits)
10331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	DSA *private = DSA_new();
10351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (private == NULL)
10371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: DSA_new failed", __func__);
10381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL,
10391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    NULL, NULL))
10401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: DSA_generate_parameters failed", __func__);
10411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!DSA_generate_key(private))
10421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: DSA_generate_key failed.", __func__);
10431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return private;
10441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
10471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_ecdsa_bits_to_nid(int bits)
10481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (bits) {
10501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
10511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case 256:
10521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NID_X9_62_prime256v1;
10531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case 384:
10541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NID_secp384r1;
10551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case 521:
10561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NID_secp521r1;
10571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
10581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
10591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
10601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
10611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
10641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
10651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_ecdsa_key_to_nid(EC_KEY *k)
10661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	EC_GROUP *eg;
10681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int nids[] = {
10691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		NID_X9_62_prime256v1,
10701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		NID_secp384r1,
10711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		NID_secp521r1,
10721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		-1
10731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	};
10741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int nid;
10751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i;
10761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BN_CTX *bnctx;
10771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const EC_GROUP *g = EC_KEY_get0_group(k);
10781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
10801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * The group may be stored in a ASN.1 encoded private key in one of two
10811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * ways: as a "named group", which is reconstituted by ASN.1 object ID
10821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * or explicit group parameters encoded into the key blob. Only the
10831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * "named group" case sets the group NID for us, but we can figure
10841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * it out for the other case by comparing against all the groups that
10851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * are supported.
10861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
10871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((nid = EC_GROUP_get_curve_name(g)) > 0)
10881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return nid;
10891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((bnctx = BN_CTX_new()) == NULL)
10901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_CTX_new() failed", __func__);
10911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; nids[i] != -1; i++) {
10921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL)
10931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("%s: EC_GROUP_new_by_curve_name failed",
10941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    __func__);
10951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (EC_GROUP_cmp(g, eg, bnctx) == 0)
10961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
10971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		EC_GROUP_free(eg);
10981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
10991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BN_CTX_free(bnctx);
11001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("%s: nid = %d", __func__, nids[i]);
11011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (nids[i] != -1) {
11021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Use the group with the NID attached */
11031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
11041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (EC_KEY_set_group(k, eg) != 1)
11051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("%s: EC_KEY_set_group", __func__);
11061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
11071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return nids[i];
11081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
11091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic EC_KEY*
11111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodecdsa_generate_private_key(u_int bits, int *nid)
11121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
11131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	EC_KEY *private;
11141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((*nid = key_ecdsa_bits_to_nid(bits)) == -1)
11161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: invalid key length", __func__);
11171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL)
11181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
11191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (EC_KEY_generate_key(private) != 1)
11201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: EC_KEY_generate_key failed", __func__);
11211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE);
11221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return private;
11231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
11241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* OPENSSL_HAS_ECC */
11251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11261305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodKey *
11271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_generate(int type, u_int bits)
11281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
11291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *k = key_new(KEY_UNSPEC);
11301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (type) {
11311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
11321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->dsa = dsa_generate_private_key(bits);
11331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
11341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
11351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
11361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->ecdsa = ecdsa_generate_private_key(bits, &k->ecdsa_nid);
11371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
11381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
11391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
11401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA1:
11411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->rsa = rsa_generate_private_key(bits);
11421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
11431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
11441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
11451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
11461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
11471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("key_generate: cert keys cannot be generated directly");
11481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
11491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("key_generate: unknown type %d", type);
11501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
11511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	k->type = type;
11521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return k;
11531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
11541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
11561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_cert_copy(const Key *from_key, struct Key *to_key)
11571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
11581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i;
11591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const struct KeyCert *from;
11601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct KeyCert *to;
11611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (to_key->cert != NULL) {
11631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cert_free(to_key->cert);
11641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		to_key->cert = NULL;
11651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
11661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((from = from_key->cert) == NULL)
11681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
11691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	to = to_key->cert = cert_new();
11711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&to->certblob, buffer_ptr(&from->certblob),
11731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buffer_len(&from->certblob));
11741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&to->critical,
11761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buffer_ptr(&from->critical), buffer_len(&from->critical));
11771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&to->extensions,
11781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buffer_ptr(&from->extensions), buffer_len(&from->extensions));
11791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	to->serial = from->serial;
11811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	to->type = from->type;
11821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	to->key_id = from->key_id == NULL ? NULL : xstrdup(from->key_id);
11831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	to->valid_after = from->valid_after;
11841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	to->valid_before = from->valid_before;
11851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	to->signature_key = from->signature_key == NULL ?
11861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    NULL : key_from_private(from->signature_key);
11871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	to->nprincipals = from->nprincipals;
11891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (to->nprincipals > CERT_MAX_PRINCIPALS)
11901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: nprincipals (%u) > CERT_MAX_PRINCIPALS (%u)",
11911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    __func__, to->nprincipals, CERT_MAX_PRINCIPALS);
11921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (to->nprincipals > 0) {
11931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		to->principals = xcalloc(from->nprincipals,
11941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    sizeof(*to->principals));
11951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (i = 0; i < to->nprincipals; i++)
11961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			to->principals[i] = xstrdup(from->principals[i]);
11971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
11981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
11991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12001305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodKey *
12011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_from_private(const Key *k)
12021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
12031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *n = NULL;
12041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (k->type) {
12051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
12061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
12071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
12081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		n = key_new(k->type);
12091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
12101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (BN_copy(n->dsa->q, k->dsa->q) == NULL) ||
12111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (BN_copy(n->dsa->g, k->dsa->g) == NULL) ||
12121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL))
12131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_from_private: BN_copy failed");
12141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
12151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
12161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
12171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
12181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		n = key_new(k->type);
12191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		n->ecdsa_nid = k->ecdsa_nid;
12201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL)
12211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
12221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (EC_KEY_set_public_key(n->ecdsa,
12231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    EC_KEY_get0_public_key(k->ecdsa)) != 1)
12241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("%s: EC_KEY_set_public_key failed", __func__);
12251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
12261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
12271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
12281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA1:
12291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
12301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
12311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		n = key_new(k->type);
12321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
12331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (BN_copy(n->rsa->e, k->rsa->e) == NULL))
12341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_from_private: BN_copy failed");
12351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
12361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
12371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("key_from_private: unknown type %d", k->type);
12381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
12391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key_is_cert(k))
12411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key_cert_copy(k, n);
12421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return n;
12431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
12441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
12461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_type_from_name(char *name)
12471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
12481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (strcmp(name, "rsa1") == 0) {
12491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return KEY_RSA1;
12501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (strcmp(name, "rsa") == 0) {
12511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return KEY_RSA;
12521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (strcmp(name, "dsa") == 0) {
12531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return KEY_DSA;
12541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (strcmp(name, "ssh-rsa") == 0) {
12551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return KEY_RSA;
12561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (strcmp(name, "ssh-dss") == 0) {
12571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return KEY_DSA;
12581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
12591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (strcmp(name, "ecdsa") == 0 ||
12601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    strcmp(name, "ecdsa-sha2-nistp256") == 0 ||
12611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    strcmp(name, "ecdsa-sha2-nistp384") == 0 ||
12621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    strcmp(name, "ecdsa-sha2-nistp521") == 0) {
12631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return KEY_ECDSA;
12641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
12651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (strcmp(name, "ssh-rsa-cert-v00@openssh.com") == 0) {
12661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return KEY_RSA_CERT_V00;
12671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (strcmp(name, "ssh-dss-cert-v00@openssh.com") == 0) {
12681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return KEY_DSA_CERT_V00;
12691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (strcmp(name, "ssh-rsa-cert-v01@openssh.com") == 0) {
12701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return KEY_RSA_CERT;
12711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (strcmp(name, "ssh-dss-cert-v01@openssh.com") == 0) {
12721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return KEY_DSA_CERT;
12731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
12741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (strcmp(name, "ecdsa-sha2-nistp256-cert-v01@openssh.com") == 0 ||
12751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    strcmp(name, "ecdsa-sha2-nistp384-cert-v01@openssh.com") == 0 ||
12761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) {
12771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return KEY_ECDSA_CERT;
12781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
12791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("key_type_from_name: unknown key type '%s'", name);
12821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return KEY_UNSPEC;
12831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
12841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
12861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_ecdsa_nid_from_name(const char *name)
12871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
12881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
12891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (strcmp(name, "ecdsa-sha2-nistp256") == 0 ||
12901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    strcmp(name, "ecdsa-sha2-nistp256-cert-v01@openssh.com") == 0)
12911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NID_X9_62_prime256v1;
12921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (strcmp(name, "ecdsa-sha2-nistp384") == 0 ||
12931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    strcmp(name, "ecdsa-sha2-nistp384-cert-v01@openssh.com") == 0)
12941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NID_secp384r1;
12951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (strcmp(name, "ecdsa-sha2-nistp521") == 0 ||
12961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0)
12971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NID_secp521r1;
12981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* OPENSSL_HAS_ECC */
12991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("%s: unknown/non-ECDSA key type '%s'", __func__, name);
13011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return -1;
13021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
13031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
13051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_names_valid2(const char *names)
13061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
13071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *s, *cp, *p;
13081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (names == NULL || strcmp(names, "") == 0)
13101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
13111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s = cp = xstrdup(names);
13121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for ((p = strsep(&cp, ",")); p && *p != '\0';
13131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (p = strsep(&cp, ","))) {
13141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (key_type_from_name(p)) {
13151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case KEY_RSA1:
13161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case KEY_UNSPEC:
13171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(s);
13181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
13191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
13201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
13211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("key names ok: [%s]", names);
13221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(s);
13231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
13241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
13251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
13271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)
13281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
13291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *principals, *critical, *exts, *sig_key, *sig;
13301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int signed_len, plen, clen, sklen, slen, kidlen, elen;
13311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer tmp;
13321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *principal;
13331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int ret = -1;
13341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int v00 = key->type == KEY_DSA_CERT_V00 ||
13351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    key->type == KEY_RSA_CERT_V00;
13361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&tmp);
13381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Copy the entire key blob for verification and later serialisation */
13401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&key->cert->certblob, blob, blen);
13411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	elen = 0; /* Not touched for v00 certs */
13431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	principals = exts = critical = sig_key = sig = NULL;
13441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((!v00 && buffer_get_int64_ret(&key->cert->serial, b) != 0) ||
13451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buffer_get_int_ret(&key->cert->type, b) != 0 ||
13461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (key->cert->key_id = buffer_get_cstring_ret(b, &kidlen)) == NULL ||
13471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (principals = buffer_get_string_ret(b, &plen)) == NULL ||
13481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buffer_get_int64_ret(&key->cert->valid_after, b) != 0 ||
13491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buffer_get_int64_ret(&key->cert->valid_before, b) != 0 ||
13501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (critical = buffer_get_string_ret(b, &clen)) == NULL ||
13511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (!v00 && (exts = buffer_get_string_ret(b, &elen)) == NULL) ||
13521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (v00 && buffer_get_string_ptr_ret(b, NULL) == NULL) || /* nonce */
13531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buffer_get_string_ptr_ret(b, NULL) == NULL || /* reserved */
13541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (sig_key = buffer_get_string_ret(b, &sklen)) == NULL) {
13551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: parse error", __func__);
13561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
13571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
13581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (kidlen != strlen(key->cert->key_id)) {
13601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: key ID contains \\0 character", __func__);
13611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
13621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
13631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Signature is left in the buffer so we can calculate this length */
13651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	signed_len = buffer_len(&key->cert->certblob) - buffer_len(b);
13661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((sig = buffer_get_string_ret(b, &slen)) == NULL) {
13681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: parse error", __func__);
13691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
13701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
13711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key->cert->type != SSH2_CERT_TYPE_USER &&
13731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    key->cert->type != SSH2_CERT_TYPE_HOST) {
13741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("Unknown certificate type %u", key->cert->type);
13751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
13761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
13771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&tmp, principals, plen);
13791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (buffer_len(&tmp) > 0) {
13801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key->cert->nprincipals >= CERT_MAX_PRINCIPALS) {
13811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("%s: Too many principals", __func__);
13821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto out;
13831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
13841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((principal = buffer_get_cstring_ret(&tmp, &plen)) == NULL) {
13851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("%s: Principals data invalid", __func__);
13861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto out;
13871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
13881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key->cert->principals = xrealloc(key->cert->principals,
13891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    key->cert->nprincipals + 1, sizeof(*key->cert->principals));
13901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key->cert->principals[key->cert->nprincipals++] = principal;
13911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
13921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_clear(&tmp);
13941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&key->cert->critical, critical, clen);
13961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&tmp, critical, clen);
13971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* validate structure */
13981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (buffer_len(&tmp) != 0) {
13991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||
14001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {
14011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("%s: critical option data invalid", __func__);
14021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto out;
14031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
14041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
14051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_clear(&tmp);
14061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&key->cert->extensions, exts, elen);
14081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&tmp, exts, elen);
14091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* validate structure */
14101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (buffer_len(&tmp) != 0) {
14111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||
14121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {
14131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("%s: extension data invalid", __func__);
14141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto out;
14151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
14161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
14171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_clear(&tmp);
14181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((key->cert->signature_key = key_from_blob(sig_key,
14201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    sklen)) == NULL) {
14211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: Signature key invalid", __func__);
14221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
14231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
14241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key->cert->signature_key->type != KEY_RSA &&
14251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    key->cert->signature_key->type != KEY_DSA &&
14261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    key->cert->signature_key->type != KEY_ECDSA) {
14271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: Invalid signature key type %s (%d)", __func__,
14281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    key_type(key->cert->signature_key),
14291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    key->cert->signature_key->type);
14301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
14311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
14321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (key_verify(key->cert->signature_key, sig, slen,
14341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buffer_ptr(&key->cert->certblob), signed_len)) {
14351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case 1:
14361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ret = 0;
14371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break; /* Good signature */
14381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case 0:
14391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: Invalid signature on certificate", __func__);
14401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
14411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case -1:
14421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: Certificate signature verification failed",
14431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    __func__);
14441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
14451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
14461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood out:
14481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&tmp);
14491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (principals != NULL)
14501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(principals);
14511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (critical != NULL)
14521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(critical);
14531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (exts != NULL)
14541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(exts);
14551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sig_key != NULL)
14561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(sig_key);
14571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sig != NULL)
14581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(sig);
14591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return ret;
14601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
14611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14621305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodKey *
14631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_from_blob(const u_char *blob, u_int blen)
14641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
14651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer b;
14661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int rlen, type;
14671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *ktype = NULL, *curve = NULL;
14681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *key = NULL;
14691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
14701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	EC_POINT *q = NULL;
14711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int nid = -1;
14721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
14731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_PK
14751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dump_base64(stderr, blob, blen);
14761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
14771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&b);
14781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&b, blob, blen);
14791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((ktype = buffer_get_cstring_ret(&b, NULL)) == NULL) {
14801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("key_from_blob: can't read key type");
14811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
14821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
14831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	type = key_type_from_name(ktype);
14851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
14861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key_type_plain(type) == KEY_ECDSA)
14871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		nid = key_ecdsa_nid_from_name(ktype);
14881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
14891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (type) {
14911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
14921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		(void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
14931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* FALLTHROUGH */
14941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
14951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
14961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key = key_new(type);
14971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 ||
14981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_get_bignum2_ret(&b, key->rsa->n) == -1) {
14991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("key_from_blob: can't read rsa key");
15001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood badkey:
15011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			key_free(key);
15021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			key = NULL;
15031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto out;
15041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
15051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_PK
15061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		RSA_print_fp(stderr, key->rsa, 8);
15071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
15081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
15091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
15101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		(void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
15111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* FALLTHROUGH */
15121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
15131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
15141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key = key_new(type);
15151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 ||
15161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_get_bignum2_ret(&b, key->dsa->q) == -1 ||
15171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_get_bignum2_ret(&b, key->dsa->g) == -1 ||
15181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) {
15191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("key_from_blob: can't read dsa key");
15201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto badkey;
15211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
15221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_PK
15231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		DSA_print_fp(stderr, key->dsa, 8);
15241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
15251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
15261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
15271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
15281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		(void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
15291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* FALLTHROUGH */
15301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
15311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key = key_new(type);
15321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key->ecdsa_nid = nid;
15331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((curve = buffer_get_string_ret(&b, NULL)) == NULL) {
15341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("key_from_blob: can't read ecdsa curve");
15351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto badkey;
15361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
15371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key->ecdsa_nid != key_curve_name_to_nid(curve)) {
15381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("key_from_blob: ecdsa curve doesn't match type");
15391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto badkey;
15401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
15411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key->ecdsa != NULL)
15421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			EC_KEY_free(key->ecdsa);
15431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
15441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    == NULL)
15451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_from_blob: EC_KEY_new_by_curve_name failed");
15461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL)
15471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_from_blob: EC_POINT_new failed");
15481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (buffer_get_ecpoint_ret(&b, EC_KEY_get0_group(key->ecdsa),
15491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    q) == -1) {
15501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("key_from_blob: can't read ecdsa key point");
15511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto badkey;
15521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
15531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
15541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    q) != 0)
15551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto badkey;
15561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (EC_KEY_set_public_key(key->ecdsa, q) != 1)
15571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_from_blob: EC_KEY_set_public_key failed");
15581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_PK
15591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
15601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
15611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
15621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* OPENSSL_HAS_ECC */
15631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_UNSPEC:
15641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key = key_new(type);
15651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
15661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
15671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("key_from_blob: cannot handle type %s", ktype);
15681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
15691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
15701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key_is_cert(key) && cert_parse(&b, key, blob, blen) == -1) {
15711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("key_from_blob: can't parse cert data");
15721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto badkey;
15731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
15741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	rlen = buffer_len(&b);
15751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key != NULL && rlen != 0)
15761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("key_from_blob: remaining bytes in key blob %d", rlen);
15771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood out:
15781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ktype != NULL)
15791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(ktype);
15801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (curve != NULL)
15811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(curve);
15821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
15831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (q != NULL)
15841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		EC_POINT_free(q);
15851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
15861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&b);
15871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return key;
15881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
15891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
15911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_to_blob(const Key *key, u_char **blobp, u_int *lenp)
15921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
15931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer b;
15941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int len;
15951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key == NULL) {
15971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("key_to_blob: key == NULL");
15981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
15991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&b);
16011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (key->type) {
16021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
16031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
16041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
16051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
16061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
16071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Use the existing blob */
16081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_append(&b, buffer_ptr(&key->cert->certblob),
16091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_len(&key->cert->certblob));
16101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
16111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
16121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_cstring(&b, key_ssh_name(key));
16131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_bignum2(&b, key->dsa->p);
16141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_bignum2(&b, key->dsa->q);
16151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_bignum2(&b, key->dsa->g);
16161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_bignum2(&b, key->dsa->pub_key);
16171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
16181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
16191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
16201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_cstring(&b, key_ssh_name(key));
16211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_cstring(&b, key_curve_nid_to_name(key->ecdsa_nid));
16221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_ecpoint(&b, EC_KEY_get0_group(key->ecdsa),
16231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    EC_KEY_get0_public_key(key->ecdsa));
16241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
16251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
16261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
16271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_cstring(&b, key_ssh_name(key));
16281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_bignum2(&b, key->rsa->e);
16291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_bignum2(&b, key->rsa->n);
16301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
16311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
16321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("key_to_blob: unsupported key type %d", key->type);
16331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_free(&b);
16341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
16351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	len = buffer_len(&b);
16371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (lenp != NULL)
16381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*lenp = len;
16391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (blobp != NULL) {
16401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*blobp = xmalloc(len);
16411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		memcpy(*blobp, buffer_ptr(&b), len);
16421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(buffer_ptr(&b), 0, len);
16441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&b);
16451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return len;
16461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
16471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
16491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_sign(
16501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    const Key *key,
16511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    u_char **sigp, u_int *lenp,
16521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    const u_char *data, u_int datalen)
16531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
16541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (key->type) {
16551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
16561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
16571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
16581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return ssh_dss_sign(key, sigp, lenp, data, datalen);
16591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
16601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
16611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
16621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return ssh_ecdsa_sign(key, sigp, lenp, data, datalen);
16631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
16641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
16651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
16661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
16671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return ssh_rsa_sign(key, sigp, lenp, data, datalen);
16681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
16691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("key_sign: invalid key type %d", key->type);
16701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
16711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
16731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
16751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * key_verify returns 1 for a correct signature, 0 for an incorrect signature
16761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * and -1 on error.
16771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
16781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
16791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_verify(
16801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    const Key *key,
16811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    const u_char *signature, u_int signaturelen,
16821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    const u_char *data, u_int datalen)
16831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
16841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (signaturelen == 0)
16851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
16861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (key->type) {
16881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
16891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
16901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
16911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return ssh_dss_verify(key, signature, signaturelen, data, datalen);
16921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
16931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
16941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
16951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return ssh_ecdsa_verify(key, signature, signaturelen, data, datalen);
16961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
16971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
16981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
16991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
17001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return ssh_rsa_verify(key, signature, signaturelen, data, datalen);
17011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
17021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("key_verify: invalid key type %d", key->type);
17031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
17041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
17051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
17061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Converts a private to a public key */
17081305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodKey *
17091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_demote(const Key *k)
17101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
17111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *pk;
17121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pk = xcalloc(1, sizeof(*pk));
17141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pk->type = k->type;
17151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pk->flags = k->flags;
17161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pk->ecdsa_nid = k->ecdsa_nid;
17171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pk->dsa = NULL;
17181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pk->ecdsa = NULL;
17191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pk->rsa = NULL;
17201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (k->type) {
17221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
17231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
17241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key_cert_copy(k, pk);
17251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* FALLTHROUGH */
17261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA1:
17271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
17281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((pk->rsa = RSA_new()) == NULL)
17291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_demote: RSA_new failed");
17301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL)
17311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_demote: BN_dup failed");
17321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL)
17331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_demote: BN_dup failed");
17341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
17351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
17361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
17371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key_cert_copy(k, pk);
17381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* FALLTHROUGH */
17391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
17401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((pk->dsa = DSA_new()) == NULL)
17411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_demote: DSA_new failed");
17421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL)
17431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_demote: BN_dup failed");
17441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL)
17451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_demote: BN_dup failed");
17461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL)
17471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_demote: BN_dup failed");
17481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL)
17491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_demote: BN_dup failed");
17501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
17511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
17521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
17531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key_cert_copy(k, pk);
17541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* FALLTHROUGH */
17551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
17561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid)) == NULL)
17571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_demote: EC_KEY_new_by_curve_name failed");
17581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (EC_KEY_set_public_key(pk->ecdsa,
17591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    EC_KEY_get0_public_key(k->ecdsa)) != 1)
17601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("key_demote: EC_KEY_set_public_key failed");
17611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
17621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
17631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
17641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("key_free: bad key type %d", k->type);
17651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
17661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
17671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (pk);
17691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
17701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
17721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_is_cert(const Key *k)
17731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
17741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (k == NULL)
17751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
17761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (k->type) {
17771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
17781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
17791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
17801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
17811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
17821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 1;
17831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
17841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
17851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
17861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
17871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Return the cert-less equivalent to a certified key type */
17891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
17901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_type_plain(int type)
17911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
17921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (type) {
17931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
17941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
17951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return KEY_RSA;
17961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
17971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
17981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return KEY_DSA;
17991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
18001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return KEY_ECDSA;
18011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
18021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return type;
18031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
18041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
18051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Convert a KEY_RSA or KEY_DSA to their _CERT equivalent */
18071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
18081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_to_certified(Key *k, int legacy)
18091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
18101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (k->type) {
18111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
18121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->cert = cert_new();
18131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->type = legacy ? KEY_RSA_CERT_V00 : KEY_RSA_CERT;
18141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
18151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
18161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->cert = cert_new();
18171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->type = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT;
18181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
18191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
18201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (legacy)
18211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("%s: legacy ECDSA certificates are not supported",
18221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    __func__);
18231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->cert = cert_new();
18241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->type = KEY_ECDSA_CERT;
18251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
18261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
18271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: key has incorrect type %s", __func__, key_type(k));
18281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
18291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
18301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
18311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Convert a KEY_RSA_CERT or KEY_DSA_CERT to their raw key equivalent */
18331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
18341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_drop_cert(Key *k)
18351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
18361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (k->type) {
18371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
18381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
18391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cert_free(k->cert);
18401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->type = KEY_RSA;
18411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
18421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
18431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
18441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cert_free(k->cert);
18451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->type = KEY_DSA;
18461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
18471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
18481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cert_free(k->cert);
18491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k->type = KEY_ECDSA;
18501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
18511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
18521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: key has incorrect type %s", __func__, key_type(k));
18531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
18541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
18551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
18561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
18581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Sign a KEY_RSA_CERT, KEY_DSA_CERT or KEY_ECDSA_CERT, (re-)generating
18591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * the signed certblob
18601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
18611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
18621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_certify(Key *k, Key *ca)
18631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
18641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer principals;
18651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *ca_blob, *sig_blob, nonce[32];
18661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i, ca_len, sig_len;
18671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (k->cert == NULL) {
18691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: key lacks cert info", __func__);
18701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
18711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
18721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!key_is_cert(k)) {
18741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: certificate has unknown type %d", __func__,
18751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    k->cert->type);
18761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
18771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
18781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ca->type != KEY_RSA && ca->type != KEY_DSA &&
18801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    ca->type != KEY_ECDSA) {
18811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: CA key has unsupported type %s", __func__,
18821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    key_type(ca));
18831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
18841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
18851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	key_to_blob(ca, &ca_blob, &ca_len);
18871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_clear(&k->cert->certblob);
18891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_cstring(&k->cert->certblob, key_ssh_name(k));
18901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* -v01 certs put nonce first */
18921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	arc4random_buf(&nonce, sizeof(nonce));
18931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!key_cert_is_legacy(k))
18941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
18951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (k->type) {
18971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
18981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT:
18991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_bignum2(&k->cert->certblob, k->dsa->p);
19001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_bignum2(&k->cert->certblob, k->dsa->q);
19011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_bignum2(&k->cert->certblob, k->dsa->g);
19021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_bignum2(&k->cert->certblob, k->dsa->pub_key);
19031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
19041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
19051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA_CERT:
19061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_cstring(&k->cert->certblob,
19071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    key_curve_nid_to_name(k->ecdsa_nid));
19081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_ecpoint(&k->cert->certblob,
19091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    EC_KEY_get0_group(k->ecdsa),
19101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    EC_KEY_get0_public_key(k->ecdsa));
19111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
19121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
19131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
19141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
19151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_bignum2(&k->cert->certblob, k->rsa->e);
19161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_bignum2(&k->cert->certblob, k->rsa->n);
19171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
19181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
19191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: key has incorrect type %s", __func__, key_type(k));
19201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_clear(&k->cert->certblob);
19211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(ca_blob);
19221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
19231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
19241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* -v01 certs have a serial number next */
19261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!key_cert_is_legacy(k))
19271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_int64(&k->cert->certblob, k->cert->serial);
19281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int(&k->cert->certblob, k->cert->type);
19301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_cstring(&k->cert->certblob, k->cert->key_id);
19311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&principals);
19331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < k->cert->nprincipals; i++)
19341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_cstring(&principals, k->cert->principals[i]);
19351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_string(&k->cert->certblob, buffer_ptr(&principals),
19361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buffer_len(&principals));
19371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&principals);
19381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int64(&k->cert->certblob, k->cert->valid_after);
19401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int64(&k->cert->certblob, k->cert->valid_before);
19411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_string(&k->cert->certblob,
19421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical));
19431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* -v01 certs have non-critical options here */
19451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!key_cert_is_legacy(k)) {
19461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_string(&k->cert->certblob,
19471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_ptr(&k->cert->extensions),
19481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_len(&k->cert->extensions));
19491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
19501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* -v00 certs put the nonce at the end */
19521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key_cert_is_legacy(k))
19531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
19541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */
19561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_string(&k->cert->certblob, ca_blob, ca_len);
19571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(ca_blob);
19581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Sign the whole mess */
19601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key_sign(ca, &sig_blob, &sig_len, buffer_ptr(&k->cert->certblob),
19611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buffer_len(&k->cert->certblob)) != 0) {
19621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: signature operation failed", __func__);
19631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_clear(&k->cert->certblob);
19641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
19651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
19661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Append signature and we are done */
19671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_string(&k->cert->certblob, sig_blob, sig_len);
19681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(sig_blob);
19691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
19711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
19721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
19741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_cert_check_authority(const Key *k, int want_host, int require_principal,
19751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    const char *name, const char **reason)
19761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
19771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i, principal_matches;
19781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	time_t now = time(NULL);
19791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (want_host) {
19811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (k->cert->type != SSH2_CERT_TYPE_HOST) {
19821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*reason = "Certificate invalid: not a host certificate";
19831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
19841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
19851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
19861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (k->cert->type != SSH2_CERT_TYPE_USER) {
19871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*reason = "Certificate invalid: not a user certificate";
19881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
19891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
19901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
19911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (now < 0) {
19921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: system clock lies before epoch", __func__);
19931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*reason = "Certificate invalid: not yet valid";
19941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
19951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
19961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((u_int64_t)now < k->cert->valid_after) {
19971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*reason = "Certificate invalid: not yet valid";
19981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
19991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
20001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((u_int64_t)now >= k->cert->valid_before) {
20011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*reason = "Certificate invalid: expired";
20021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
20031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
20041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (k->cert->nprincipals == 0) {
20051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (require_principal) {
20061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*reason = "Certificate lacks principal list";
20071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
20081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
20091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (name != NULL) {
20101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		principal_matches = 0;
20111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (i = 0; i < k->cert->nprincipals; i++) {
20121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (strcmp(name, k->cert->principals[i]) == 0) {
20131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				principal_matches = 1;
20141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
20151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
20161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
20171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!principal_matches) {
20181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*reason = "Certificate invalid: name is not a listed "
20191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "principal";
20201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
20211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
20221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
20231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
20241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
20251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
20271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_cert_is_legacy(Key *k)
20281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
20291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (k->type) {
20301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA_CERT_V00:
20311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
20321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 1;
20331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
20341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
20351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
20361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
20371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* XXX: these are really begging for a table-driven approach */
20391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
20401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_curve_name_to_nid(const char *name)
20411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
20421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
20431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (strcmp(name, "nistp256") == 0)
20441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NID_X9_62_prime256v1;
20451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else if (strcmp(name, "nistp384") == 0)
20461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NID_secp384r1;
20471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else if (strcmp(name, "nistp521") == 0)
20481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NID_secp521r1;
20491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
20501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("%s: unsupported EC curve name \"%.100s\"", __func__, name);
20521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return -1;
20531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
20541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodu_int
20561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_curve_nid_to_bits(int nid)
20571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
20581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (nid) {
20591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
20601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case NID_X9_62_prime256v1:
20611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 256;
20621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case NID_secp384r1:
20631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 384;
20641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case NID_secp521r1:
20651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 521;
20661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
20671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
20681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: unsupported EC curve nid %d", __func__, nid);
20691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
20701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
20711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
20721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodconst char *
20741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_curve_nid_to_name(int nid)
20751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
20761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
20771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (nid == NID_X9_62_prime256v1)
20781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "nistp256";
20791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else if (nid == NID_secp384r1)
20801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "nistp384";
20811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else if (nid == NID_secp521r1)
20821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return "nistp521";
20831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
20841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	error("%s: unsupported EC curve nid %d", __func__, nid);
20851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return NULL;
20861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
20871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
20891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodconst EVP_MD *
20901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_ec_nid_to_evpmd(int nid)
20911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
20921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int kbits = key_curve_nid_to_bits(nid);
20931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (kbits == 0)
20951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: invalid nid %d", __func__, nid);
20961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* RFC5656 section 6.2.1 */
20971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (kbits <= 256)
20981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return EVP_sha256();
20991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else if (kbits <= 384)
21001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return EVP_sha384();
21011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
21021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return EVP_sha512();
21031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
21041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
21061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
21071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
21081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BN_CTX *bnctx;
21091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	EC_POINT *nq = NULL;
21101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BIGNUM *order, *x, *y, *tmp;
21111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int ret = -1;
21121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((bnctx = BN_CTX_new()) == NULL)
21141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_CTX_new failed", __func__);
21151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BN_CTX_start(bnctx);
21161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
21181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * We shouldn't ever hit this case because bignum_get_ecpoint()
21191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * refuses to load GF2m points.
21201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
21211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
21221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    NID_X9_62_prime_field) {
21231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: group is not a prime field", __func__);
21241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
21251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
21261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Q != infinity */
21281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (EC_POINT_is_at_infinity(group, public)) {
21291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: received degenerate public key (infinity)",
21301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    __func__);
21311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
21321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
21331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((x = BN_CTX_get(bnctx)) == NULL ||
21351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (y = BN_CTX_get(bnctx)) == NULL ||
21361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (order = BN_CTX_get(bnctx)) == NULL ||
21371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (tmp = BN_CTX_get(bnctx)) == NULL)
21381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_CTX_get failed", __func__);
21391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
21411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (EC_GROUP_get_order(group, order, bnctx) != 1)
21421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: EC_GROUP_get_order failed", __func__);
21431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (EC_POINT_get_affine_coordinates_GFp(group, public,
21441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    x, y, bnctx) != 1)
21451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__);
21461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (BN_num_bits(x) <= BN_num_bits(order) / 2) {
21471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: public key x coordinate too small: "
21481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "bits(x) = %d, bits(order)/2 = %d", __func__,
21491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    BN_num_bits(x), BN_num_bits(order) / 2);
21501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
21511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
21521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (BN_num_bits(y) <= BN_num_bits(order) / 2) {
21531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: public key y coordinate too small: "
21541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "bits(y) = %d, bits(order)/2 = %d", __func__,
21551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    BN_num_bits(x), BN_num_bits(order) / 2);
21561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
21571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
21581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* nQ == infinity (n == order of subgroup) */
21601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((nq = EC_POINT_new(group)) == NULL)
21611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_CTX_tmp failed", __func__);
21621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1)
21631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: EC_GROUP_mul failed", __func__);
21641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (EC_POINT_is_at_infinity(group, nq) != 1) {
21651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: received degenerate public key (nQ != infinity)",
21661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    __func__);
21671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
21681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
21691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* x < order - 1, y < order - 1 */
21711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!BN_sub(tmp, order, BN_value_one()))
21721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_sub failed", __func__);
21731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (BN_cmp(x, tmp) >= 0) {
21741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: public key x coordinate >= group order - 1",
21751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    __func__);
21761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
21771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
21781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (BN_cmp(y, tmp) >= 0) {
21791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: public key y coordinate >= group order - 1",
21801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    __func__);
21811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
21821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
21831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ret = 0;
21841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood out:
21851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BN_CTX_free(bnctx);
21861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	EC_POINT_free(nq);
21871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return ret;
21881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
21891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
21911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_ec_validate_private(const EC_KEY *key)
21921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
21931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BN_CTX *bnctx;
21941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BIGNUM *order, *tmp;
21951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int ret = -1;
21961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((bnctx = BN_CTX_new()) == NULL)
21981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_CTX_new failed", __func__);
21991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BN_CTX_start(bnctx);
22001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
22011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((order = BN_CTX_get(bnctx)) == NULL ||
22021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (tmp = BN_CTX_get(bnctx)) == NULL)
22031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_CTX_get failed", __func__);
22041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
22051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* log2(private) > log2(order)/2 */
22061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1)
22071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: EC_GROUP_get_order failed", __func__);
22081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (BN_num_bits(EC_KEY_get0_private_key(key)) <=
22091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    BN_num_bits(order) / 2) {
22101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: private key too small: "
22111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "bits(y) = %d, bits(order)/2 = %d", __func__,
22121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    BN_num_bits(EC_KEY_get0_private_key(key)),
22131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    BN_num_bits(order) / 2);
22141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
22151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
22161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
22171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* private < order - 1 */
22181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!BN_sub(tmp, order, BN_value_one()))
22191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_sub failed", __func__);
22201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0) {
22211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: private key >= group order - 1", __func__);
22221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
22231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
22241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ret = 0;
22251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood out:
22261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BN_CTX_free(bnctx);
22271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return ret;
22281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
22291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
22301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if defined(DEBUG_KEXECDH) || defined(DEBUG_PK)
22311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
22321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_dump_ec_point(const EC_GROUP *group, const EC_POINT *point)
22331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
22341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BIGNUM *x, *y;
22351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BN_CTX *bnctx;
22361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
22371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (point == NULL) {
22381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fputs("point=(NULL)\n", stderr);
22391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
22401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
22411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((bnctx = BN_CTX_new()) == NULL)
22421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_CTX_new failed", __func__);
22431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BN_CTX_start(bnctx);
22441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((x = BN_CTX_get(bnctx)) == NULL || (y = BN_CTX_get(bnctx)) == NULL)
22451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_CTX_get failed", __func__);
22461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
22471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    NID_X9_62_prime_field)
22481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: group is not a prime field", __func__);
22491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, bnctx) != 1)
22501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__);
22511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fputs("x=", stderr);
22521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BN_print_fp(stderr, x);
22531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fputs("\ny=", stderr);
22541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BN_print_fp(stderr, y);
22551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fputs("\n", stderr);
22561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BN_CTX_free(bnctx);
22571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
22581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
22591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
22601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_dump_ec_key(const EC_KEY *key)
22611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
22621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const BIGNUM *exponent;
22631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
22641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	key_dump_ec_point(EC_KEY_get0_group(key), EC_KEY_get0_public_key(key));
22651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fputs("exponent=", stderr);
22661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((exponent = EC_KEY_get0_private_key(key)) == NULL)
22671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fputs("(NULL)", stderr);
22681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
22691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		BN_print_fp(stderr, EC_KEY_get0_private_key(key));
22701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fputs("\n", stderr);
22711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
22721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* defined(DEBUG_KEXECDH) || defined(DEBUG_PK) */
22731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* OPENSSL_HAS_ECC */
2274