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