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