key.c revision 58582
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.
2858582Skris */
2958582Skris/*
3058582Skris * read_bignum():
3158582Skris * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
3258582Skris */
3358582Skris
3458582Skris#include "includes.h"
3558582Skris#include "ssh.h"
3658582Skris#include <ssl/rsa.h>
3758582Skris#include <ssl/dsa.h>
3858582Skris#include <ssl/evp.h>
3958582Skris#include "xmalloc.h"
4058582Skris#include "key.h"
4158582Skris
4258582SkrisKey *
4358582Skriskey_new(int type)
4458582Skris{
4558582Skris	Key *k;
4658582Skris	RSA *rsa;
4758582Skris	DSA *dsa;
4858582Skris	k = xmalloc(sizeof(*k));
4958582Skris	k->type = type;
5058582Skris	switch (k->type) {
5158582Skris	case KEY_RSA:
5258582Skris		rsa = RSA_new();
5358582Skris		rsa->n = BN_new();
5458582Skris		rsa->e = BN_new();
5558582Skris		k->rsa = rsa;
5658582Skris		break;
5758582Skris	case KEY_DSA:
5858582Skris		dsa = DSA_new();
5958582Skris		dsa->p = BN_new();
6058582Skris		dsa->q = BN_new();
6158582Skris		dsa->g = BN_new();
6258582Skris		dsa->pub_key = BN_new();
6358582Skris		k->dsa = dsa;
6458582Skris		break;
6558582Skris	case KEY_EMPTY:
6658582Skris		k->dsa = NULL;
6758582Skris		k->rsa = NULL;
6858582Skris		break;
6958582Skris	default:
7058582Skris		fatal("key_new: bad key type %d", k->type);
7158582Skris		break;
7258582Skris	}
7358582Skris	return k;
7458582Skris}
7558582Skrisvoid
7658582Skriskey_free(Key *k)
7758582Skris{
7858582Skris	switch (k->type) {
7958582Skris	case KEY_RSA:
8058582Skris		if (k->rsa != NULL)
8158582Skris			RSA_free(k->rsa);
8258582Skris		k->rsa = NULL;
8358582Skris		break;
8458582Skris	case KEY_DSA:
8558582Skris		if (k->dsa != NULL)
8658582Skris			DSA_free(k->dsa);
8758582Skris		k->dsa = NULL;
8858582Skris		break;
8958582Skris	default:
9058582Skris		fatal("key_free: bad key type %d", k->type);
9158582Skris		break;
9258582Skris	}
9358582Skris	xfree(k);
9458582Skris}
9558582Skrisint
9658582Skriskey_equal(Key *a, Key *b)
9758582Skris{
9858582Skris	if (a == NULL || b == NULL || a->type != b->type)
9958582Skris		return 0;
10058582Skris	switch (a->type) {
10158582Skris	case KEY_RSA:
10258582Skris		return a->rsa != NULL && b->rsa != NULL &&
10358582Skris		    BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
10458582Skris		    BN_cmp(a->rsa->n, b->rsa->n) == 0;
10558582Skris		break;
10658582Skris	case KEY_DSA:
10758582Skris		return a->dsa != NULL && b->dsa != NULL &&
10858582Skris		    BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
10958582Skris		    BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
11058582Skris		    BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
11158582Skris		    BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
11258582Skris		break;
11358582Skris	default:
11458582Skris		fatal("key_free: bad key type %d", a->type);
11558582Skris		break;
11658582Skris	}
11758582Skris	return 0;
11858582Skris}
11958582Skris
12058582Skris#define FPRINT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
12158582Skris
12258582Skris/*
12358582Skris * Generate key fingerprint in ascii format.
12458582Skris * Based on ideas and code from Bjoern Groenvall <bg@sics.se>
12558582Skris */
12658582Skrischar *
12758582Skriskey_fingerprint(Key *k)
12858582Skris{
12958582Skris	static char retval[80];
13058582Skris	unsigned char *buf = NULL;
13158582Skris	int len = 0;
13258582Skris	int nlen, elen, plen, qlen, glen, publen;
13358582Skris
13458582Skris	switch (k->type) {
13558582Skris	case KEY_RSA:
13658582Skris		nlen = BN_num_bytes(k->rsa->n);
13758582Skris		elen = BN_num_bytes(k->rsa->e);
13858582Skris		len = nlen + elen;
13958582Skris		buf = xmalloc(len);
14058582Skris		BN_bn2bin(k->rsa->n, buf);
14158582Skris		BN_bn2bin(k->rsa->e, buf + nlen);
14258582Skris		break;
14358582Skris	case KEY_DSA:
14458582Skris		plen = BN_num_bytes(k->dsa->p);
14558582Skris		qlen = BN_num_bytes(k->dsa->q);
14658582Skris		glen = BN_num_bytes(k->dsa->g);
14758582Skris		publen = BN_num_bytes(k->dsa->pub_key);
14858582Skris		len = qlen + qlen + glen + publen;
14958582Skris		buf = xmalloc(len);
15058582Skris		BN_bn2bin(k->dsa->p, buf);
15158582Skris		BN_bn2bin(k->dsa->q, buf + plen);
15258582Skris		BN_bn2bin(k->dsa->g, buf + plen + qlen);
15358582Skris		BN_bn2bin(k->dsa->pub_key , buf + plen + qlen + glen);
15458582Skris		break;
15558582Skris	default:
15658582Skris		fatal("key_fingerprint: bad key type %d", k->type);
15758582Skris		break;
15858582Skris	}
15958582Skris	if (buf != NULL) {
16058582Skris		unsigned char d[16];
16158582Skris		EVP_MD_CTX md;
16258582Skris		EVP_DigestInit(&md, EVP_md5());
16358582Skris		EVP_DigestUpdate(&md, buf, len);
16458582Skris		EVP_DigestFinal(&md, d, NULL);
16558582Skris		snprintf(retval, sizeof(retval), FPRINT,
16658582Skris		    d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
16758582Skris		    d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
16858582Skris		memset(buf, 0, len);
16958582Skris		xfree(buf);
17058582Skris	}
17158582Skris	return retval;
17258582Skris}
17358582Skris
17458582Skris/*
17558582Skris * Reads a multiple-precision integer in decimal from the buffer, and advances
17658582Skris * the pointer.  The integer must already be initialized.  This function is
17758582Skris * permitted to modify the buffer.  This leaves *cpp to point just beyond the
17858582Skris * last processed (and maybe modified) character.  Note that this may modify
17958582Skris * the buffer containing the number.
18058582Skris */
18158582Skrisint
18258582Skrisread_bignum(char **cpp, BIGNUM * value)
18358582Skris{
18458582Skris	char *cp = *cpp;
18558582Skris	int old;
18658582Skris
18758582Skris	/* Skip any leading whitespace. */
18858582Skris	for (; *cp == ' ' || *cp == '\t'; cp++)
18958582Skris		;
19058582Skris
19158582Skris	/* Check that it begins with a decimal digit. */
19258582Skris	if (*cp < '0' || *cp > '9')
19358582Skris		return 0;
19458582Skris
19558582Skris	/* Save starting position. */
19658582Skris	*cpp = cp;
19758582Skris
19858582Skris	/* Move forward until all decimal digits skipped. */
19958582Skris	for (; *cp >= '0' && *cp <= '9'; cp++)
20058582Skris		;
20158582Skris
20258582Skris	/* Save the old terminating character, and replace it by \0. */
20358582Skris	old = *cp;
20458582Skris	*cp = 0;
20558582Skris
20658582Skris	/* Parse the number. */
20758582Skris	if (BN_dec2bn(&value, *cpp) == 0)
20858582Skris		return 0;
20958582Skris
21058582Skris	/* Restore old terminating character. */
21158582Skris	*cp = old;
21258582Skris
21358582Skris	/* Move beyond the number and return success. */
21458582Skris	*cpp = cp;
21558582Skris	return 1;
21658582Skris}
21758582Skrisint
21858582Skriswrite_bignum(FILE *f, BIGNUM *num)
21958582Skris{
22058582Skris	char *buf = BN_bn2dec(num);
22158582Skris	if (buf == NULL) {
22258582Skris		error("write_bignum: BN_bn2dec() failed");
22358582Skris		return 0;
22458582Skris	}
22558582Skris	fprintf(f, " %s", buf);
22658582Skris	free(buf);
22758582Skris	return 1;
22858582Skris}
22958582Skrisint
23058582Skriskey_read(Key *ret, unsigned int bits, char **cpp)
23158582Skris{
23258582Skris	switch(ret->type) {
23358582Skris	case KEY_RSA:
23458582Skris		if (bits == 0)
23558582Skris			return 0;
23658582Skris		/* Get public exponent, public modulus. */
23758582Skris		if (!read_bignum(cpp, ret->rsa->e))
23858582Skris			return 0;
23958582Skris		if (!read_bignum(cpp, ret->rsa->n))
24058582Skris			return 0;
24158582Skris		break;
24258582Skris	case KEY_DSA:
24358582Skris		if (bits != 0)
24458582Skris			return 0;
24558582Skris		if (!read_bignum(cpp, ret->dsa->p))
24658582Skris			return 0;
24758582Skris		if (!read_bignum(cpp, ret->dsa->q))
24858582Skris			return 0;
24958582Skris		if (!read_bignum(cpp, ret->dsa->g))
25058582Skris			return 0;
25158582Skris		if (!read_bignum(cpp, ret->dsa->pub_key))
25258582Skris			return 0;
25358582Skris		break;
25458582Skris	default:
25558582Skris		fatal("bad key type: %d", ret->type);
25658582Skris		break;
25758582Skris	}
25858582Skris	return 1;
25958582Skris}
26058582Skrisint
26158582Skriskey_write(Key *key, FILE *f)
26258582Skris{
26358582Skris	int success = 0;
26458582Skris	unsigned int bits = 0;
26558582Skris
26658582Skris	if (key->type == KEY_RSA && key->rsa != NULL) {
26758582Skris		/* size of modulus 'n' */
26858582Skris		bits = BN_num_bits(key->rsa->n);
26958582Skris		fprintf(f, "%u", bits);
27058582Skris		if (write_bignum(f, key->rsa->e) &&
27158582Skris		    write_bignum(f, key->rsa->n)) {
27258582Skris			success = 1;
27358582Skris		} else {
27458582Skris			error("key_write: failed for RSA key");
27558582Skris		}
27658582Skris	} else if (key->type == KEY_DSA && key->dsa != NULL) {
27758582Skris		/* bits == 0 means DSA key */
27858582Skris		bits = 0;
27958582Skris		fprintf(f, "%u", bits);
28058582Skris		if (write_bignum(f, key->dsa->p) &&
28158582Skris		    write_bignum(f, key->dsa->q) &&
28258582Skris		    write_bignum(f, key->dsa->g) &&
28358582Skris		    write_bignum(f, key->dsa->pub_key)) {
28458582Skris			success = 1;
28558582Skris		} else {
28658582Skris			error("key_write: failed for DSA key");
28758582Skris		}
28858582Skris	}
28958582Skris	return success;
29058582Skris}
291