mac.c revision 92555
1106424Sroberto/*
2106424Sroberto * Copyright (c) 2001 Markus Friedl.  All rights reserved.
3132451Sroberto *
4106424Sroberto * Redistribution and use in source and binary forms, with or without
5106424Sroberto * modification, are permitted provided that the following conditions
6182007Sroberto * are met:
7106424Sroberto * 1. Redistributions of source code must retain the above copyright
8106424Sroberto *    notice, this list of conditions and the following disclaimer.
9106424Sroberto * 2. Redistributions in binary form must reproduce the above copyright
10106424Sroberto *    notice, this list of conditions and the following disclaimer in the
11182007Sroberto *    documentation and/or other materials provided with the distribution.
12132451Sroberto *
13106424Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14106424Sroberto * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15106424Sroberto * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16106424Sroberto * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17106424Sroberto * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18106424Sroberto * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19106424Sroberto * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20106424Sroberto * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21106424Sroberto * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22106424Sroberto * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23106424Sroberto */
24106424Sroberto
25106424Sroberto#include "includes.h"
26106424SrobertoRCSID("$OpenBSD: mac.c,v 1.4 2002/01/25 22:07:40 markus Exp $");
27106424Sroberto
28106424Sroberto#include <openssl/hmac.h>
29106424Sroberto
30106424Sroberto#include "xmalloc.h"
31106424Sroberto#include "getput.h"
32106424Sroberto#include "log.h"
33106424Sroberto#include "cipher.h"
34106424Sroberto#include "kex.h"
35106424Sroberto#include "mac.h"
36106424Sroberto
37106424Srobertostruct {
38106424Sroberto	char		*name;
39106424Sroberto	EVP_MD *	(*mdfunc)(void);
40106424Sroberto	int		truncatebits;	/* truncate digest if != 0 */
41106424Sroberto} macs[] = {
42182007Sroberto	{ "hmac-sha1",			EVP_sha1, 0, },
43182007Sroberto	{ "hmac-sha1-96",		EVP_sha1, 96 },
44182007Sroberto	{ "hmac-md5",			EVP_md5, 0 },
45182007Sroberto	{ "hmac-md5-96",		EVP_md5, 96 },
46182007Sroberto	{ "hmac-ripemd160",		EVP_ripemd160, 0 },
47106424Sroberto	{ "hmac-ripemd160@openssh.com",	EVP_ripemd160, 0 },
48106424Sroberto	{ NULL,				NULL, 0 }
49106424Sroberto};
50106424Sroberto
51106424Srobertoint
52106424Srobertomac_init(Mac *mac, char *name)
53106424Sroberto{
54106424Sroberto	int i;
55106424Sroberto	for (i = 0; macs[i].name; i++) {
56106424Sroberto		if (strcmp(name, macs[i].name) == 0) {
57106424Sroberto			if (mac != NULL) {
58106424Sroberto				mac->md = (*macs[i].mdfunc)();
59106424Sroberto				mac->key_len = mac->mac_len = EVP_MD_size(mac->md);
60106424Sroberto				if (macs[i].truncatebits != 0)
61106424Sroberto					mac->mac_len = macs[i].truncatebits/8;
62106424Sroberto			}
63132451Sroberto			debug2("mac_init: found %s", name);
64182007Sroberto			return (0);
65182007Sroberto		}
66182007Sroberto	}
67182007Sroberto	debug2("mac_init: unknown %s", name);
68182007Sroberto	return (-1);
69182007Sroberto}
70182007Sroberto
71182007Srobertou_char *
72182007Srobertomac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen)
73182007Sroberto{
74182007Sroberto	HMAC_CTX c;
75132451Sroberto	static u_char m[EVP_MAX_MD_SIZE];
76132451Sroberto	u_char b[4];
77132451Sroberto
78132451Sroberto	if (mac->key == NULL)
79132451Sroberto		fatal("mac_compute: no key");
80132451Sroberto	if (mac->mac_len > sizeof(m))
81132451Sroberto		fatal("mac_compute: mac too long");
82132451Sroberto	HMAC_Init(&c, mac->key, mac->key_len, mac->md);
83132451Sroberto	PUT_32BIT(b, seqno);
84132451Sroberto	HMAC_Update(&c, b, sizeof(b));
85132451Sroberto	HMAC_Update(&c, data, datalen);
86132451Sroberto	HMAC_Final(&c, m, NULL);
87132451Sroberto	HMAC_cleanup(&c);
88132451Sroberto	return (m);
89132451Sroberto}
90182007Sroberto
91132451Sroberto/* XXX copied from ciphers_valid */
92132451Sroberto#define	MAC_SEP	","
93106424Srobertoint
94106424Srobertomac_valid(const char *names)
95106424Sroberto{
96106424Sroberto	char *maclist, *cp, *p;
97106424Sroberto
98106424Sroberto	if (names == NULL || strcmp(names, "") == 0)
99106424Sroberto		return (0);
100106424Sroberto	maclist = cp = xstrdup(names);
101106424Sroberto	for ((p = strsep(&cp, MAC_SEP)); p && *p != '\0';
102106424Sroberto	    (p = strsep(&cp, MAC_SEP))) {
103106424Sroberto		if (mac_init(NULL, p) < 0) {
104106424Sroberto			debug("bad mac %s [%s]", p, names);
105106424Sroberto			xfree(maclist);
106106424Sroberto			return (0);
107106424Sroberto		} else {
108106424Sroberto			debug3("mac ok: %s [%s]", p, names);
109106424Sroberto		}
110106424Sroberto	}
111106424Sroberto	debug3("macs ok: [%s]", names);
112182007Sroberto	xfree(maclist);
113132451Sroberto	return (1);
114182007Sroberto}
115182007Sroberto