key.c revision 60576
158582Skris/*
258582Skris * Copyright (c) 2000 Markus Friedl.  All rights reserved.
358582Skris *
458582Skris * Redistribution and use in source and binary forms, with or without
558582Skris * modification, are permitted provided that the following conditions
658582Skris * are met:
758582Skris * 1. Redistributions of source code must retain the above copyright
858582Skris *    notice, this list of conditions and the following disclaimer.
958582Skris * 2. Redistributions in binary form must reproduce the above copyright
1058582Skris *    notice, this list of conditions and the following disclaimer in the
1158582Skris *    documentation and/or other materials provided with the distribution.
1258582Skris * 3. All advertising materials mentioning features or use of this software
1358582Skris *    must display the following acknowledgement:
1458582Skris *      This product includes software developed by Markus Friedl.
1558582Skris * 4. The name of the author may not be used to endorse or promote products
1658582Skris *    derived from this software without specific prior written permission.
1758582Skris *
1858582Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1958582Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2058582Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2158582Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2258582Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2358582Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2458582Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2558582Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2658582Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2758582Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2858592Skris *
2958592Skris * $FreeBSD: head/crypto/openssh/key.c 60576 2000-05-15 05:24:25Z kris $
3058582Skris */
3158582Skris/*
3258582Skris * read_bignum():
3358582Skris * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
3458582Skris */
3558582Skris
3658582Skris#include "includes.h"
3758582Skris#include "ssh.h"
3858592Skris#include <openssl/rsa.h>
3958592Skris#include <openssl/dsa.h>
4058592Skris#include <openssl/evp.h>
4158582Skris#include "xmalloc.h"
4258582Skris#include "key.h"
4360576Skris#include "dsa.h"
4460576Skris#include "uuencode.h"
4558582Skris
4660576Skris#define SSH_DSS "ssh-dss"
4760576Skris
4858582SkrisKey *
4958582Skriskey_new(int type)
5058582Skris{
5158582Skris	Key *k;
5258582Skris	RSA *rsa;
5358582Skris	DSA *dsa;
5458582Skris	k = xmalloc(sizeof(*k));
5558582Skris	k->type = type;
5660576Skris	k->dsa = NULL;
5760576Skris	k->rsa = NULL;
5858582Skris	switch (k->type) {
5958582Skris	case KEY_RSA:
6058582Skris		rsa = RSA_new();
6158582Skris		rsa->n = BN_new();
6258582Skris		rsa->e = BN_new();
6358582Skris		k->rsa = rsa;
6458582Skris		break;
6558582Skris	case KEY_DSA:
6658582Skris		dsa = DSA_new();
6758582Skris		dsa->p = BN_new();
6858582Skris		dsa->q = BN_new();
6958582Skris		dsa->g = BN_new();
7058582Skris		dsa->pub_key = BN_new();
7158582Skris		k->dsa = dsa;
7258582Skris		break;
7358582Skris	case KEY_EMPTY:
7458582Skris		break;
7558582Skris	default:
7658582Skris		fatal("key_new: bad key type %d", k->type);
7758582Skris		break;
7858582Skris	}
7958582Skris	return k;
8058582Skris}
8158582Skrisvoid
8258582Skriskey_free(Key *k)
8358582Skris{
8458582Skris	switch (k->type) {
8558582Skris	case KEY_RSA:
8658582Skris		if (k->rsa != NULL)
8758582Skris			RSA_free(k->rsa);
8858582Skris		k->rsa = NULL;
8958582Skris		break;
9058582Skris	case KEY_DSA:
9158582Skris		if (k->dsa != NULL)
9258582Skris			DSA_free(k->dsa);
9358582Skris		k->dsa = NULL;
9458582Skris		break;
9558582Skris	default:
9658582Skris		fatal("key_free: bad key type %d", k->type);
9758582Skris		break;
9858582Skris	}
9958582Skris	xfree(k);
10058582Skris}
10158582Skrisint
10258582Skriskey_equal(Key *a, Key *b)
10358582Skris{
10458582Skris	if (a == NULL || b == NULL || a->type != b->type)
10558582Skris		return 0;
10658582Skris	switch (a->type) {
10758582Skris	case KEY_RSA:
10858582Skris		return a->rsa != NULL && b->rsa != NULL &&
10958582Skris		    BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
11058582Skris		    BN_cmp(a->rsa->n, b->rsa->n) == 0;
11158582Skris		break;
11258582Skris	case KEY_DSA:
11358582Skris		return a->dsa != NULL && b->dsa != NULL &&
11458582Skris		    BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
11558582Skris		    BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
11658582Skris		    BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
11758582Skris		    BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
11858582Skris		break;
11958582Skris	default:
12060576Skris		fatal("key_equal: bad key type %d", a->type);
12158582Skris		break;
12258582Skris	}
12358582Skris	return 0;
12458582Skris}
12558582Skris
12658582Skris#define FPRINT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
12758582Skris
12858582Skris/*
12958582Skris * Generate key fingerprint in ascii format.
13058582Skris * Based on ideas and code from Bjoern Groenvall <bg@sics.se>
13158582Skris */
13258582Skrischar *
13358582Skriskey_fingerprint(Key *k)
13458582Skris{
13558582Skris	static char retval[80];
13660576Skris	unsigned char *blob = NULL;
13758582Skris	int len = 0;
13860576Skris	int nlen, elen;
13958582Skris
14058582Skris	switch (k->type) {
14158582Skris	case KEY_RSA:
14258582Skris		nlen = BN_num_bytes(k->rsa->n);
14358582Skris		elen = BN_num_bytes(k->rsa->e);
14458582Skris		len = nlen + elen;
14560576Skris		blob = xmalloc(len);
14660576Skris		BN_bn2bin(k->rsa->n, blob);
14760576Skris		BN_bn2bin(k->rsa->e, blob + nlen);
14858582Skris		break;
14958582Skris	case KEY_DSA:
15060576Skris		dsa_make_key_blob(k, &blob, &len);
15158582Skris		break;
15258582Skris	default:
15358582Skris		fatal("key_fingerprint: bad key type %d", k->type);
15458582Skris		break;
15558582Skris	}
15660576Skris	if (blob != NULL) {
15758582Skris		unsigned char d[16];
15858582Skris		EVP_MD_CTX md;
15958582Skris		EVP_DigestInit(&md, EVP_md5());
16060576Skris		EVP_DigestUpdate(&md, blob, len);
16158582Skris		EVP_DigestFinal(&md, d, NULL);
16258582Skris		snprintf(retval, sizeof(retval), FPRINT,
16358582Skris		    d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
16458582Skris		    d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
16560576Skris		memset(blob, 0, len);
16660576Skris		xfree(blob);
16758582Skris	}
16858582Skris	return retval;
16958582Skris}
17058582Skris
17158582Skris/*
17258582Skris * Reads a multiple-precision integer in decimal from the buffer, and advances
17358582Skris * the pointer.  The integer must already be initialized.  This function is
17458582Skris * permitted to modify the buffer.  This leaves *cpp to point just beyond the
17558582Skris * last processed (and maybe modified) character.  Note that this may modify
17658582Skris * the buffer containing the number.
17758582Skris */
17858582Skrisint
17958582Skrisread_bignum(char **cpp, BIGNUM * value)
18058582Skris{
18158582Skris	char *cp = *cpp;
18258582Skris	int old;
18358582Skris
18458582Skris	/* Skip any leading whitespace. */
18558582Skris	for (; *cp == ' ' || *cp == '\t'; cp++)
18658582Skris		;
18758582Skris
18858582Skris	/* Check that it begins with a decimal digit. */
18958582Skris	if (*cp < '0' || *cp > '9')
19058582Skris		return 0;
19158582Skris
19258582Skris	/* Save starting position. */
19358582Skris	*cpp = cp;
19458582Skris
19558582Skris	/* Move forward until all decimal digits skipped. */
19658582Skris	for (; *cp >= '0' && *cp <= '9'; cp++)
19758582Skris		;
19858582Skris
19958582Skris	/* Save the old terminating character, and replace it by \0. */
20058582Skris	old = *cp;
20158582Skris	*cp = 0;
20258582Skris
20358582Skris	/* Parse the number. */
20458582Skris	if (BN_dec2bn(&value, *cpp) == 0)
20558582Skris		return 0;
20658582Skris
20758582Skris	/* Restore old terminating character. */
20858582Skris	*cp = old;
20958582Skris
21058582Skris	/* Move beyond the number and return success. */
21158582Skris	*cpp = cp;
21258582Skris	return 1;
21358582Skris}
21458582Skrisint
21558582Skriswrite_bignum(FILE *f, BIGNUM *num)
21658582Skris{
21758582Skris	char *buf = BN_bn2dec(num);
21858582Skris	if (buf == NULL) {
21958582Skris		error("write_bignum: BN_bn2dec() failed");
22058582Skris		return 0;
22158582Skris	}
22258582Skris	fprintf(f, " %s", buf);
22358582Skris	free(buf);
22458582Skris	return 1;
22558582Skris}
22660576Skrisunsigned int
22760576Skriskey_read(Key *ret, char **cpp)
22858582Skris{
22960576Skris	Key *k;
23060576Skris	unsigned int bits = 0;
23160576Skris	char *cp;
23260576Skris	int len, n;
23360576Skris	unsigned char *blob;
23460576Skris
23560576Skris	cp = *cpp;
23660576Skris
23758582Skris	switch(ret->type) {
23858582Skris	case KEY_RSA:
23960576Skris		/* Get number of bits. */
24060576Skris		if (*cp < '0' || *cp > '9')
24160576Skris			return 0;	/* Bad bit count... */
24260576Skris		for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
24360576Skris			bits = 10 * bits + *cp - '0';
24458582Skris		if (bits == 0)
24558582Skris			return 0;
24660576Skris		*cpp = cp;
24758582Skris		/* Get public exponent, public modulus. */
24858582Skris		if (!read_bignum(cpp, ret->rsa->e))
24958582Skris			return 0;
25058582Skris		if (!read_bignum(cpp, ret->rsa->n))
25158582Skris			return 0;
25258582Skris		break;
25358582Skris	case KEY_DSA:
25460576Skris		if (strncmp(cp, SSH_DSS " ", 7) != 0)
25558582Skris			return 0;
25660576Skris		cp += 7;
25760576Skris		len = 2*strlen(cp);
25860576Skris		blob = xmalloc(len);
25960576Skris		n = uudecode(cp, blob, len);
26060576Skris		if (n < 0) {
26160576Skris			error("uudecode %s failed", cp);
26258582Skris			return 0;
26360576Skris		}
26460576Skris		k = dsa_key_from_blob(blob, n);
26560576Skris		if (k == NULL)
26660576Skris			 return 0;
26760576Skris		xfree(blob);
26860576Skris		if (ret->dsa != NULL)
26960576Skris			DSA_free(ret->dsa);
27060576Skris		ret->dsa = k->dsa;
27160576Skris		k->dsa = NULL;
27260576Skris		key_free(k);
27360576Skris		bits = BN_num_bits(ret->dsa->p);
27460576Skris		cp = strchr(cp, '=');
27560576Skris		if (cp == NULL)
27658582Skris			return 0;
27760576Skris		*cpp = cp + 1;
27858582Skris		break;
27958582Skris	default:
28060576Skris		fatal("key_read: bad key type: %d", ret->type);
28158582Skris		break;
28258582Skris	}
28360576Skris	return bits;
28458582Skris}
28558582Skrisint
28658582Skriskey_write(Key *key, FILE *f)
28758582Skris{
28858582Skris	int success = 0;
28958582Skris	unsigned int bits = 0;
29058582Skris
29158582Skris	if (key->type == KEY_RSA && key->rsa != NULL) {
29258582Skris		/* size of modulus 'n' */
29358582Skris		bits = BN_num_bits(key->rsa->n);
29458582Skris		fprintf(f, "%u", bits);
29558582Skris		if (write_bignum(f, key->rsa->e) &&
29658582Skris		    write_bignum(f, key->rsa->n)) {
29758582Skris			success = 1;
29858582Skris		} else {
29958582Skris			error("key_write: failed for RSA key");
30058582Skris		}
30158582Skris	} else if (key->type == KEY_DSA && key->dsa != NULL) {
30260576Skris		int len, n;
30360576Skris		unsigned char *blob, *uu;
30460576Skris		dsa_make_key_blob(key, &blob, &len);
30560576Skris		uu = xmalloc(2*len);
30660576Skris		n = uuencode(blob, len, uu, 2*len);
30760576Skris		if (n > 0) {
30860576Skris			fprintf(f, "%s %s", SSH_DSS, uu);
30958582Skris			success = 1;
31058582Skris		}
31160576Skris		xfree(blob);
31260576Skris		xfree(uu);
31358582Skris	}
31458582Skris	return success;
31558582Skris}
31660576Skrischar *
31760576Skriskey_type(Key *k)
31860576Skris{
31960576Skris	switch (k->type) {
32060576Skris	case KEY_RSA:
32160576Skris		return "RSA";
32260576Skris		break;
32360576Skris	case KEY_DSA:
32460576Skris		return "DSA";
32560576Skris		break;
32660576Skris	}
32760576Skris	return "unknown";
32860576Skris}
329