1 /*- 2 * Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/malloc.h> 33 34 #include <opencrypto/cryptosoft.h> /* for hmac_ipad_buffer and hmac_opad_buffer */ 35 #include <opencrypto/xform.h> 36 37 #include "glxsb.h" 38 39 /* 40 * Implementation notes. 41 * 42 * The Geode LX Security Block provides AES-128-CBC acceleration. 43 * We implement all HMAC algorithms provided by crypto(9) framework so glxsb can work 44 * with ipsec(4) 45 * 46 * This code was stolen from crypto/via/padlock_hash.c 47 */ 48 49 MALLOC_DECLARE(M_GLXSB); 50 51 static void 52 glxsb_hash_key_setup(struct glxsb_session *ses, caddr_t key, int klen) 53 { 54 struct auth_hash *axf; 55 int i; 56 57 klen /= 8; 58 axf = ses->ses_axf; 59 60 for (i = 0; i < klen; i++) 61 key[i] ^= HMAC_IPAD_VAL; 62 63 axf->Init(ses->ses_ictx); 64 axf->Update(ses->ses_ictx, key, klen); 65 axf->Update(ses->ses_ictx, hmac_ipad_buffer, axf->blocksize - klen); 66 67 for (i = 0; i < klen; i++) 68 key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); 69 70 axf->Init(ses->ses_octx); 71 axf->Update(ses->ses_octx, key, klen); 72 axf->Update(ses->ses_octx, hmac_opad_buffer, axf->blocksize - klen); 73 74 for (i = 0; i < klen; i++) 75 key[i] ^= HMAC_OPAD_VAL; 76 } 77 78 /* 79 * Compute keyed-hash authenticator. 80 */ 81 static int 82 glxsb_authcompute(struct glxsb_session *ses, struct cryptodesc *crd, 83 caddr_t buf, int flags) 84 { 85 u_char hash[HASH_MAX_LEN]; 86 struct auth_hash *axf; 87 union authctx ctx; 88 int error; 89 90 axf = ses->ses_axf; 91 bcopy(ses->ses_ictx, &ctx, axf->ctxsize); 92 error = crypto_apply(flags, buf, crd->crd_skip, crd->crd_len, 93 (int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx); 94 if (error != 0) 95 return (error); 96 axf->Final(hash, &ctx); 97 98 bcopy(ses->ses_octx, &ctx, axf->ctxsize); 99 axf->Update(&ctx, hash, axf->hashsize); 100 axf->Final(hash, &ctx); 101 102 /* Inject the authentication data */ 103 crypto_copyback(flags, buf, crd->crd_inject, 104 ses->ses_mlen == 0 ? axf->hashsize : ses->ses_mlen, hash); 105 return (0); 106 } 107 108 int 109 glxsb_hash_setup(struct glxsb_session *ses, struct cryptoini *macini) 110 { 111 112 ses->ses_mlen = macini->cri_mlen; 113 114 /* Find software structure which describes HMAC algorithm. */ 115 switch (macini->cri_alg) { 116 case CRYPTO_NULL_HMAC: 117 ses->ses_axf = &auth_hash_null; 118 break; 119 case CRYPTO_MD5_HMAC: 120 ses->ses_axf = &auth_hash_hmac_md5; 121 break; 122 case CRYPTO_SHA1_HMAC: 123 ses->ses_axf = &auth_hash_hmac_sha1; 124 break; 125 case CRYPTO_RIPEMD160_HMAC: 126 ses->ses_axf = &auth_hash_hmac_ripemd_160; 127 break; 128 case CRYPTO_SHA2_256_HMAC: 129 ses->ses_axf = &auth_hash_hmac_sha2_256; 130 break; 131 case CRYPTO_SHA2_384_HMAC: 132 ses->ses_axf = &auth_hash_hmac_sha2_384; 133 break; 134 case CRYPTO_SHA2_512_HMAC: 135 ses->ses_axf = &auth_hash_hmac_sha2_512; 136 break; 137 } 138 139 /* Allocate memory for HMAC inner and outer contexts. */ 140 ses->ses_ictx = malloc(ses->ses_axf->ctxsize, M_GLXSB, 141 M_ZERO | M_NOWAIT); 142 ses->ses_octx = malloc(ses->ses_axf->ctxsize, M_GLXSB, 143 M_ZERO | M_NOWAIT); 144 if (ses->ses_ictx == NULL || ses->ses_octx == NULL) 145 return (ENOMEM); 146 147 /* Setup key if given. */ 148 if (macini->cri_key != NULL) { 149 glxsb_hash_key_setup(ses, macini->cri_key, 150 macini->cri_klen); 151 } 152 return (0); 153 } 154 155 int 156 glxsb_hash_process(struct glxsb_session *ses, struct cryptodesc *maccrd, 157 struct cryptop *crp) 158 { 159 int error; 160 161 if ((maccrd->crd_flags & CRD_F_KEY_EXPLICIT) != 0) 162 glxsb_hash_key_setup(ses, maccrd->crd_key, maccrd->crd_klen); 163 164 error = glxsb_authcompute(ses, maccrd, crp->crp_buf, crp->crp_flags); 165 return (error); 166 } 167 168 void 169 glxsb_hash_free(struct glxsb_session *ses) 170 { 171 172 if (ses->ses_ictx != NULL) { 173 bzero(ses->ses_ictx, ses->ses_axf->ctxsize); 174 free(ses->ses_ictx, M_GLXSB); 175 ses->ses_ictx = NULL; 176 } 177 if (ses->ses_octx != NULL) { 178 bzero(ses->ses_octx, ses->ses_axf->ctxsize); 179 free(ses->ses_octx, M_GLXSB); 180 ses->ses_octx = NULL; 181 } 182 } 183