mac.c revision 126274
165793Smsmith/*
265793Smsmith * Copyright (c) 2001 Markus Friedl.  All rights reserved.
381082Sscottl *
465793Smsmith * Redistribution and use in source and binary forms, with or without
581082Sscottl * modification, are permitted provided that the following conditions
665793Smsmith * are met:
765793Smsmith * 1. Redistributions of source code must retain the above copyright
865793Smsmith *    notice, this list of conditions and the following disclaimer.
965793Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1065793Smsmith *    notice, this list of conditions and the following disclaimer in the
1165793Smsmith *    documentation and/or other materials provided with the distribution.
1265793Smsmith *
1365793Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1465793Smsmith * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1565793Smsmith * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1665793Smsmith * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1765793Smsmith * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1865793Smsmith * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1965793Smsmith * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2065793Smsmith * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2165793Smsmith * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2265793Smsmith * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2365793Smsmith */
2465793Smsmith
2565793Smsmith#include "includes.h"
2665793SmsmithRCSID("$OpenBSD: mac.c,v 1.6 2003/09/18 13:02:21 miod Exp $");
2765793Smsmith
2865793Smsmith#include <openssl/hmac.h>
2965793Smsmith
30119418Sobrien#include "xmalloc.h"
31119418Sobrien#include "getput.h"
32119418Sobrien#include "log.h"
3381151Sscottl#include "cipher.h"
3481151Sscottl#include "kex.h"
3565793Smsmith#include "mac.h"
3665793Smsmith
3765793Smsmithstruct {
38129879Sphk	char		*name;
3981154Sscottl	const EVP_MD *	(*mdfunc)(void);
4065793Smsmith	int		truncatebits;	/* truncate digest if != 0 */
4165793Smsmith} macs[] = {
4265793Smsmith	{ "hmac-sha1",			EVP_sha1, 0, },
4365793Smsmith	{ "hmac-sha1-96",		EVP_sha1, 96 },
4465793Smsmith	{ "hmac-md5",			EVP_md5, 0 },
4582527Sscottl	{ "hmac-md5-96",		EVP_md5, 96 },
4682527Sscottl	{ "hmac-ripemd160",		EVP_ripemd160, 0 },
4782527Sscottl	{ "hmac-ripemd160@openssh.com",	EVP_ripemd160, 0 },
4882527Sscottl	{ NULL,				NULL, 0 }
4965793Smsmith};
5065793Smsmith
5165793Smsmithint
5265793Smsmithmac_init(Mac *mac, char *name)
5370393Smsmith{
5465793Smsmith	int i;
5565793Smsmith	for (i = 0; macs[i].name; i++) {
5665793Smsmith		if (strcmp(name, macs[i].name) == 0) {
5765793Smsmith			if (mac != NULL) {
5865793Smsmith				mac->md = (*macs[i].mdfunc)();
5965793Smsmith				mac->key_len = mac->mac_len = EVP_MD_size(mac->md);
6065793Smsmith				if (macs[i].truncatebits != 0)
6165793Smsmith					mac->mac_len = macs[i].truncatebits/8;
6265793Smsmith			}
6365793Smsmith			debug2("mac_init: found %s", name);
6465793Smsmith			return (0);
6565793Smsmith		}
66111525Sscottl	}
67111525Sscottl	debug2("mac_init: unknown %s", name);
68111525Sscottl	return (-1);
69111220Sphk}
7065793Smsmith
7189112Smsmithu_char *
7265793Smsmithmac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen)
7365793Smsmith{
7483114Sscottl	HMAC_CTX c;
7583114Sscottl	static u_char m[EVP_MAX_MD_SIZE];
7683114Sscottl	u_char b[4];
7783114Sscottl
7865793Smsmith	if (mac->key == NULL)
7965793Smsmith		fatal("mac_compute: no key");
8065793Smsmith	if ((u_int)mac->mac_len > sizeof(m))
8183114Sscottl		fatal("mac_compute: mac too long");
8283114Sscottl	HMAC_Init(&c, mac->key, mac->key_len, mac->md);
8383114Sscottl	PUT_32BIT(b, seqno);
8465793Smsmith	HMAC_Update(&c, b, sizeof(b));
8565793Smsmith	HMAC_Update(&c, data, datalen);
8695350Sscottl	HMAC_Final(&c, m, NULL);
8795350Sscottl	HMAC_cleanup(&c);
8865793Smsmith	return (m);
8965793Smsmith}
9081154Sscottl
9195350Sscottl/* XXX copied from ciphers_valid */
9281154Sscottl#define	MAC_SEP	","
9381154Sscottlint
9481154Sscottlmac_valid(const char *names)
95121307Ssilby{
9682527Sscottl	char *maclist, *cp, *p;
9781154Sscottl
9883114Sscottl	if (names == NULL || strcmp(names, "") == 0)
9965793Smsmith		return (0);
10065793Smsmith	maclist = cp = xstrdup(names);
10165793Smsmith	for ((p = strsep(&cp, MAC_SEP)); p && *p != '\0';
10265793Smsmith	    (p = strsep(&cp, MAC_SEP))) {
10365793Smsmith		if (mac_init(NULL, p) < 0) {
10465793Smsmith			debug("bad mac %s [%s]", p, names);
105111525Sscottl			xfree(maclist);
10665793Smsmith			return (0);
10783114Sscottl		} else {
10865793Smsmith			debug3("mac ok: %s [%s]", p, names);
10983114Sscottl		}
11083114Sscottl	}
111111525Sscottl	debug3("macs ok: [%s]", names);
11265793Smsmith	xfree(maclist);
113109088Sscottl	return (1);
114109088Sscottl}
11583114Sscottl