mac.c revision 92555
1193267Sjkim/*
2193267Sjkim * Copyright (c) 2001 Markus Friedl.  All rights reserved.
3193267Sjkim *
4193267Sjkim * Redistribution and use in source and binary forms, with or without
5193267Sjkim * modification, are permitted provided that the following conditions
6193267Sjkim * are met:
7193267Sjkim * 1. Redistributions of source code must retain the above copyright
8193267Sjkim *    notice, this list of conditions and the following disclaimer.
9193267Sjkim * 2. Redistributions in binary form must reproduce the above copyright
10193267Sjkim *    notice, this list of conditions and the following disclaimer in the
11193267Sjkim *    documentation and/or other materials provided with the distribution.
12193267Sjkim *
13193267Sjkim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14193267Sjkim * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15193267Sjkim * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16193267Sjkim * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17193267Sjkim * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18193267Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19193267Sjkim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20193267Sjkim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21193267Sjkim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22193267Sjkim * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23193267Sjkim */
24193267Sjkim
25193267Sjkim#include "includes.h"
26193267SjkimRCSID("$OpenBSD: mac.c,v 1.4 2002/01/25 22:07:40 markus Exp $");
27193267Sjkim
28193267Sjkim#include <openssl/hmac.h>
29193267Sjkim
30193267Sjkim#include "xmalloc.h"
31193267Sjkim#include "getput.h"
32193267Sjkim#include "log.h"
33193267Sjkim#include "cipher.h"
34193267Sjkim#include "kex.h"
35193267Sjkim#include "mac.h"
36193267Sjkim
37193267Sjkimstruct {
38193267Sjkim	char		*name;
39193267Sjkim	EVP_MD *	(*mdfunc)(void);
40193267Sjkim	int		truncatebits;	/* truncate digest if != 0 */
41193267Sjkim} macs[] = {
42193267Sjkim	{ "hmac-sha1",			EVP_sha1, 0, },
43193267Sjkim	{ "hmac-sha1-96",		EVP_sha1, 96 },
44193267Sjkim	{ "hmac-md5",			EVP_md5, 0 },
45193267Sjkim	{ "hmac-md5-96",		EVP_md5, 96 },
46193267Sjkim	{ "hmac-ripemd160",		EVP_ripemd160, 0 },
47193267Sjkim	{ "hmac-ripemd160@openssh.com",	EVP_ripemd160, 0 },
48193267Sjkim	{ NULL,				NULL, 0 }
49193267Sjkim};
50193267Sjkim
51193267Sjkimint
52193267Sjkimmac_init(Mac *mac, char *name)
53193267Sjkim{
54193267Sjkim	int i;
55193267Sjkim	for (i = 0; macs[i].name; i++) {
56193267Sjkim		if (strcmp(name, macs[i].name) == 0) {
57193267Sjkim			if (mac != NULL) {
58193267Sjkim				mac->md = (*macs[i].mdfunc)();
59193267Sjkim				mac->key_len = mac->mac_len = EVP_MD_size(mac->md);
60193267Sjkim				if (macs[i].truncatebits != 0)
61193267Sjkim					mac->mac_len = macs[i].truncatebits/8;
62193267Sjkim			}
63193267Sjkim			debug2("mac_init: found %s", name);
64193267Sjkim			return (0);
65193267Sjkim		}
66193267Sjkim	}
67193267Sjkim	debug2("mac_init: unknown %s", name);
68193267Sjkim	return (-1);
69193267Sjkim}
70193267Sjkim
71193267Sjkimu_char *
72193267Sjkimmac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen)
73193267Sjkim{
74193267Sjkim	HMAC_CTX c;
75193267Sjkim	static u_char m[EVP_MAX_MD_SIZE];
76193267Sjkim	u_char b[4];
77193267Sjkim
78193267Sjkim	if (mac->key == NULL)
79193267Sjkim		fatal("mac_compute: no key");
80193267Sjkim	if (mac->mac_len > sizeof(m))
81193267Sjkim		fatal("mac_compute: mac too long");
82193267Sjkim	HMAC_Init(&c, mac->key, mac->key_len, mac->md);
83193267Sjkim	PUT_32BIT(b, seqno);
84193267Sjkim	HMAC_Update(&c, b, sizeof(b));
85193267Sjkim	HMAC_Update(&c, data, datalen);
86193267Sjkim	HMAC_Final(&c, m, NULL);
87193267Sjkim	HMAC_cleanup(&c);
88193267Sjkim	return (m);
89193267Sjkim}
90193267Sjkim
91193267Sjkim/* XXX copied from ciphers_valid */
92193267Sjkim#define	MAC_SEP	","
93193267Sjkimint
94193267Sjkimmac_valid(const char *names)
95193267Sjkim{
96193267Sjkim	char *maclist, *cp, *p;
97193267Sjkim
98193267Sjkim	if (names == NULL || strcmp(names, "") == 0)
99193267Sjkim		return (0);
100193267Sjkim	maclist = cp = xstrdup(names);
101193267Sjkim	for ((p = strsep(&cp, MAC_SEP)); p && *p != '\0';
102193267Sjkim	    (p = strsep(&cp, MAC_SEP))) {
103193267Sjkim		if (mac_init(NULL, p) < 0) {
104193267Sjkim			debug("bad mac %s [%s]", p, names);
105193267Sjkim			xfree(maclist);
106193267Sjkim			return (0);
107193267Sjkim		} else {
108193267Sjkim			debug3("mac ok: %s [%s]", p, names);
109193267Sjkim		}
110193267Sjkim	}
111193267Sjkim	debug3("macs ok: [%s]", names);
112193267Sjkim	xfree(maclist);
113193267Sjkim	return (1);
114193267Sjkim}
115193267Sjkim