mac.c revision 98675
176259Sgreen/* 276259Sgreen * Copyright (c) 2001 Markus Friedl. All rights reserved. 376259Sgreen * 476259Sgreen * Redistribution and use in source and binary forms, with or without 576259Sgreen * modification, are permitted provided that the following conditions 676259Sgreen * are met: 776259Sgreen * 1. Redistributions of source code must retain the above copyright 876259Sgreen * notice, this list of conditions and the following disclaimer. 976259Sgreen * 2. Redistributions in binary form must reproduce the above copyright 1076259Sgreen * notice, this list of conditions and the following disclaimer in the 1176259Sgreen * documentation and/or other materials provided with the distribution. 1276259Sgreen * 1376259Sgreen * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1476259Sgreen * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1576259Sgreen * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1676259Sgreen * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1776259Sgreen * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1876259Sgreen * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1976259Sgreen * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2076259Sgreen * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2176259Sgreen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2276259Sgreen * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2376259Sgreen */ 2476259Sgreen 2576259Sgreen#include "includes.h" 2698675SdesRCSID("$OpenBSD: mac.c,v 1.5 2002/05/16 22:02:50 markus Exp $"); 2776259Sgreen 2876259Sgreen#include <openssl/hmac.h> 2976259Sgreen 3076259Sgreen#include "xmalloc.h" 3176259Sgreen#include "getput.h" 3276259Sgreen#include "log.h" 3376259Sgreen#include "cipher.h" 3476259Sgreen#include "kex.h" 3576259Sgreen#include "mac.h" 3676259Sgreen 3776259Sgreenstruct { 3876259Sgreen char *name; 3998675Sdes const EVP_MD * (*mdfunc)(void); 4076259Sgreen int truncatebits; /* truncate digest if != 0 */ 4176259Sgreen} macs[] = { 4276259Sgreen { "hmac-sha1", EVP_sha1, 0, }, 4376259Sgreen { "hmac-sha1-96", EVP_sha1, 96 }, 4476259Sgreen { "hmac-md5", EVP_md5, 0 }, 4576259Sgreen { "hmac-md5-96", EVP_md5, 96 }, 4676259Sgreen { "hmac-ripemd160", EVP_ripemd160, 0 }, 4776259Sgreen { "hmac-ripemd160@openssh.com", EVP_ripemd160, 0 }, 4876259Sgreen { NULL, NULL, 0 } 4976259Sgreen}; 5076259Sgreen 5176259Sgreenint 5276259Sgreenmac_init(Mac *mac, char *name) 5376259Sgreen{ 5476259Sgreen int i; 5576259Sgreen for (i = 0; macs[i].name; i++) { 5676259Sgreen if (strcmp(name, macs[i].name) == 0) { 5776259Sgreen if (mac != NULL) { 5876259Sgreen mac->md = (*macs[i].mdfunc)(); 5992555Sdes mac->key_len = mac->mac_len = EVP_MD_size(mac->md); 6076259Sgreen if (macs[i].truncatebits != 0) 6176259Sgreen mac->mac_len = macs[i].truncatebits/8; 6276259Sgreen } 6376259Sgreen debug2("mac_init: found %s", name); 6476259Sgreen return (0); 6576259Sgreen } 6676259Sgreen } 6776259Sgreen debug2("mac_init: unknown %s", name); 6876259Sgreen return (-1); 6976259Sgreen} 7076259Sgreen 7176259Sgreenu_char * 7276259Sgreenmac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen) 7376259Sgreen{ 7476259Sgreen HMAC_CTX c; 7576259Sgreen static u_char m[EVP_MAX_MD_SIZE]; 7676259Sgreen u_char b[4]; 7776259Sgreen 7876259Sgreen if (mac->key == NULL) 7976259Sgreen fatal("mac_compute: no key"); 8076259Sgreen if (mac->mac_len > sizeof(m)) 8176259Sgreen fatal("mac_compute: mac too long"); 8276259Sgreen HMAC_Init(&c, mac->key, mac->key_len, mac->md); 8376259Sgreen PUT_32BIT(b, seqno); 8476259Sgreen HMAC_Update(&c, b, sizeof(b)); 8576259Sgreen HMAC_Update(&c, data, datalen); 8676259Sgreen HMAC_Final(&c, m, NULL); 8776259Sgreen HMAC_cleanup(&c); 8876259Sgreen return (m); 8976259Sgreen} 9076259Sgreen 9176259Sgreen/* XXX copied from ciphers_valid */ 9276259Sgreen#define MAC_SEP "," 9376259Sgreenint 9476259Sgreenmac_valid(const char *names) 9576259Sgreen{ 9676259Sgreen char *maclist, *cp, *p; 9776259Sgreen 9876259Sgreen if (names == NULL || strcmp(names, "") == 0) 9976259Sgreen return (0); 10076259Sgreen maclist = cp = xstrdup(names); 10176259Sgreen for ((p = strsep(&cp, MAC_SEP)); p && *p != '\0'; 10292555Sdes (p = strsep(&cp, MAC_SEP))) { 10376259Sgreen if (mac_init(NULL, p) < 0) { 10476259Sgreen debug("bad mac %s [%s]", p, names); 10576259Sgreen xfree(maclist); 10676259Sgreen return (0); 10776259Sgreen } else { 10876259Sgreen debug3("mac ok: %s [%s]", p, names); 10976259Sgreen } 11076259Sgreen } 11176259Sgreen debug3("macs ok: [%s]", names); 11276259Sgreen xfree(maclist); 11376259Sgreen return (1); 11476259Sgreen} 115