1181467Sphilip/*- 2181467Sphilip * Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3181467Sphilip * All rights reserved. 4181467Sphilip * 5181467Sphilip * Redistribution and use in source and binary forms, with or without 6181467Sphilip * modification, are permitted provided that the following conditions 7181467Sphilip * are met: 8181467Sphilip * 1. Redistributions of source code must retain the above copyright 9181467Sphilip * notice, this list of conditions and the following disclaimer. 10181467Sphilip * 2. Redistributions in binary form must reproduce the above copyright 11181467Sphilip * notice, this list of conditions and the following disclaimer in the 12181467Sphilip * documentation and/or other materials provided with the distribution. 13181467Sphilip * 14181467Sphilip * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15181467Sphilip * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16181467Sphilip * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17181467Sphilip * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18181467Sphilip * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19181467Sphilip * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20181467Sphilip * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21181467Sphilip * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22181467Sphilip * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23181467Sphilip * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24181467Sphilip * SUCH DAMAGE. 25181467Sphilip */ 26181467Sphilip 27181467Sphilip#include <sys/cdefs.h> 28181467Sphilip__FBSDID("$FreeBSD: releng/10.2/sys/dev/glxsb/glxsb_hash.c 181593 2008-08-11 08:41:08Z pjd $"); 29181467Sphilip 30181467Sphilip#include <sys/param.h> 31181467Sphilip#include <sys/systm.h> 32181467Sphilip#include <sys/malloc.h> 33181467Sphilip 34181467Sphilip#include <opencrypto/cryptosoft.h> /* for hmac_ipad_buffer and hmac_opad_buffer */ 35181467Sphilip#include <opencrypto/xform.h> 36181467Sphilip 37181467Sphilip#include "glxsb.h" 38181467Sphilip 39181467Sphilip/* 40181467Sphilip * Implementation notes. 41181467Sphilip * 42181467Sphilip * The Geode LX Security Block provides AES-128-CBC acceleration. 43181467Sphilip * We implement all HMAC algorithms provided by crypto(9) framework so glxsb can work 44181467Sphilip * with ipsec(4) 45181467Sphilip * 46181467Sphilip * This code was stolen from crypto/via/padlock_hash.c 47181467Sphilip */ 48181467Sphilip 49181467SphilipMALLOC_DECLARE(M_GLXSB); 50181467Sphilip 51181467Sphilipstatic void 52181467Sphilipglxsb_hash_key_setup(struct glxsb_session *ses, caddr_t key, int klen) 53181467Sphilip{ 54181467Sphilip struct auth_hash *axf; 55181467Sphilip int i; 56181467Sphilip 57181467Sphilip klen /= 8; 58181467Sphilip axf = ses->ses_axf; 59181467Sphilip 60181467Sphilip for (i = 0; i < klen; i++) 61181467Sphilip key[i] ^= HMAC_IPAD_VAL; 62181467Sphilip 63181467Sphilip axf->Init(ses->ses_ictx); 64181467Sphilip axf->Update(ses->ses_ictx, key, klen); 65181467Sphilip axf->Update(ses->ses_ictx, hmac_ipad_buffer, axf->blocksize - klen); 66181467Sphilip 67181467Sphilip for (i = 0; i < klen; i++) 68181467Sphilip key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); 69181467Sphilip 70181467Sphilip axf->Init(ses->ses_octx); 71181467Sphilip axf->Update(ses->ses_octx, key, klen); 72181467Sphilip axf->Update(ses->ses_octx, hmac_opad_buffer, axf->blocksize - klen); 73181467Sphilip 74181467Sphilip for (i = 0; i < klen; i++) 75181467Sphilip key[i] ^= HMAC_OPAD_VAL; 76181467Sphilip} 77181467Sphilip 78181467Sphilip/* 79181467Sphilip * Compute keyed-hash authenticator. 80181467Sphilip */ 81181467Sphilipstatic int 82181467Sphilipglxsb_authcompute(struct glxsb_session *ses, struct cryptodesc *crd, 83181467Sphilip caddr_t buf, int flags) 84181467Sphilip{ 85181467Sphilip u_char hash[HASH_MAX_LEN]; 86181467Sphilip struct auth_hash *axf; 87181467Sphilip union authctx ctx; 88181467Sphilip int error; 89181467Sphilip 90181467Sphilip axf = ses->ses_axf; 91181467Sphilip bcopy(ses->ses_ictx, &ctx, axf->ctxsize); 92181467Sphilip error = crypto_apply(flags, buf, crd->crd_skip, crd->crd_len, 93181467Sphilip (int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx); 94181593Spjd if (error != 0) 95181467Sphilip return (error); 96181467Sphilip axf->Final(hash, &ctx); 97181467Sphilip 98181467Sphilip bcopy(ses->ses_octx, &ctx, axf->ctxsize); 99181467Sphilip axf->Update(&ctx, hash, axf->hashsize); 100181467Sphilip axf->Final(hash, &ctx); 101181467Sphilip 102181467Sphilip /* Inject the authentication data */ 103181467Sphilip crypto_copyback(flags, buf, crd->crd_inject, 104181467Sphilip ses->ses_mlen == 0 ? axf->hashsize : ses->ses_mlen, hash); 105181467Sphilip return (0); 106181467Sphilip} 107181467Sphilip 108181467Sphilipint 109181467Sphilipglxsb_hash_setup(struct glxsb_session *ses, struct cryptoini *macini) 110181467Sphilip{ 111181467Sphilip 112181467Sphilip ses->ses_mlen = macini->cri_mlen; 113181467Sphilip 114181467Sphilip /* Find software structure which describes HMAC algorithm. */ 115181467Sphilip switch (macini->cri_alg) { 116181467Sphilip case CRYPTO_NULL_HMAC: 117181467Sphilip ses->ses_axf = &auth_hash_null; 118181467Sphilip break; 119181467Sphilip case CRYPTO_MD5_HMAC: 120181467Sphilip ses->ses_axf = &auth_hash_hmac_md5; 121181467Sphilip break; 122181467Sphilip case CRYPTO_SHA1_HMAC: 123181467Sphilip ses->ses_axf = &auth_hash_hmac_sha1; 124181467Sphilip break; 125181467Sphilip case CRYPTO_RIPEMD160_HMAC: 126181467Sphilip ses->ses_axf = &auth_hash_hmac_ripemd_160; 127181467Sphilip break; 128181467Sphilip case CRYPTO_SHA2_256_HMAC: 129181467Sphilip ses->ses_axf = &auth_hash_hmac_sha2_256; 130181467Sphilip break; 131181467Sphilip case CRYPTO_SHA2_384_HMAC: 132181467Sphilip ses->ses_axf = &auth_hash_hmac_sha2_384; 133181467Sphilip break; 134181467Sphilip case CRYPTO_SHA2_512_HMAC: 135181467Sphilip ses->ses_axf = &auth_hash_hmac_sha2_512; 136181467Sphilip break; 137181467Sphilip } 138181467Sphilip 139181467Sphilip /* Allocate memory for HMAC inner and outer contexts. */ 140181467Sphilip ses->ses_ictx = malloc(ses->ses_axf->ctxsize, M_GLXSB, 141181467Sphilip M_ZERO | M_NOWAIT); 142181467Sphilip ses->ses_octx = malloc(ses->ses_axf->ctxsize, M_GLXSB, 143181467Sphilip M_ZERO | M_NOWAIT); 144181467Sphilip if (ses->ses_ictx == NULL || ses->ses_octx == NULL) 145181467Sphilip return (ENOMEM); 146181467Sphilip 147181467Sphilip /* Setup key if given. */ 148181467Sphilip if (macini->cri_key != NULL) { 149181467Sphilip glxsb_hash_key_setup(ses, macini->cri_key, 150181467Sphilip macini->cri_klen); 151181467Sphilip } 152181467Sphilip return (0); 153181467Sphilip} 154181467Sphilip 155181467Sphilipint 156181467Sphilipglxsb_hash_process(struct glxsb_session *ses, struct cryptodesc *maccrd, 157181467Sphilip struct cryptop *crp) 158181467Sphilip{ 159181467Sphilip int error; 160181467Sphilip 161181467Sphilip if ((maccrd->crd_flags & CRD_F_KEY_EXPLICIT) != 0) 162181467Sphilip glxsb_hash_key_setup(ses, maccrd->crd_key, maccrd->crd_klen); 163181467Sphilip 164181467Sphilip error = glxsb_authcompute(ses, maccrd, crp->crp_buf, crp->crp_flags); 165181467Sphilip return (error); 166181467Sphilip} 167181467Sphilip 168181467Sphilipvoid 169181467Sphilipglxsb_hash_free(struct glxsb_session *ses) 170181467Sphilip{ 171181467Sphilip 172181467Sphilip if (ses->ses_ictx != NULL) { 173181467Sphilip bzero(ses->ses_ictx, ses->ses_axf->ctxsize); 174181467Sphilip free(ses->ses_ictx, M_GLXSB); 175181467Sphilip ses->ses_ictx = NULL; 176181467Sphilip } 177181467Sphilip if (ses->ses_octx != NULL) { 178181467Sphilip bzero(ses->ses_octx, ses->ses_axf->ctxsize); 179181467Sphilip free(ses->ses_octx, M_GLXSB); 180181467Sphilip ses->ses_octx = NULL; 181181467Sphilip } 182181467Sphilip} 183