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