aesni_wrap.c revision 210409
1210409Skib/*- 2210409Skib * Copyright (c) 2010 Konstantin Belousov <kib@FreeBSD.org> 3210409Skib * All rights reserved. 4210409Skib * 5210409Skib * Redistribution and use in source and binary forms, with or without 6210409Skib * modification, are permitted provided that the following conditions 7210409Skib * are met: 8210409Skib * 1. Redistributions of source code must retain the above copyright 9210409Skib * notice, this list of conditions and the following disclaimer. 10210409Skib * 2. Redistributions in binary form must reproduce the above copyright 11210409Skib * notice, this list of conditions and the following disclaimer in the 12210409Skib * documentation and/or other materials provided with the distribution. 13210409Skib * 14210409Skib * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15210409Skib * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16210409Skib * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17210409Skib * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18210409Skib * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19210409Skib * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20210409Skib * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21210409Skib * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22210409Skib * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23210409Skib * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24210409Skib * SUCH DAMAGE. 25210409Skib */ 26210409Skib 27210409Skib#include <sys/cdefs.h> 28210409Skib__FBSDID("$FreeBSD: head/sys/crypto/aesni/aesni_wrap.c 210409 2010-07-23 11:00:46Z kib $"); 29210409Skib 30210409Skib#include <sys/param.h> 31210409Skib#include <sys/libkern.h> 32210409Skib#include <sys/malloc.h> 33210409Skib#include <sys/proc.h> 34210409Skib#include <sys/systm.h> 35210409Skib#include <crypto/aesni/aesni.h> 36210409Skib 37210409SkibMALLOC_DECLARE(M_AESNI); 38210409Skib 39210409Skib#ifdef DEBUG 40210409Skibstatic void 41210409Skibps_len(const char *string, const uint8_t *data, int length) 42210409Skib{ 43210409Skib int i; 44210409Skib 45210409Skib printf("%-12s[0x", string); 46210409Skib for(i = 0; i < length; i++) { 47210409Skib if (i % AES_BLOCK_LEN == 0 && i > 0) 48210409Skib printf("+"); 49210409Skib printf("%02x", data[i]); 50210409Skib } 51210409Skib printf("]\n"); 52210409Skib} 53210409Skib#endif 54210409Skib 55210409Skibvoid 56210409Skibaesni_encrypt_cbc(int rounds, const void *key_schedule, size_t len, 57210409Skib const uint8_t *from, uint8_t *to, const uint8_t iv[AES_BLOCK_LEN]) 58210409Skib{ 59210409Skib const uint8_t *ivp; 60210409Skib size_t i; 61210409Skib 62210409Skib#ifdef DEBUG 63210409Skib ps_len("AES CBC encrypt iv:", iv, AES_BLOCK_LEN); 64210409Skib ps_len("from:", from, len); 65210409Skib#endif 66210409Skib 67210409Skib len /= AES_BLOCK_LEN; 68210409Skib ivp = iv; 69210409Skib for (i = 0; i < len; i++) { 70210409Skib aesni_enc(rounds - 1, key_schedule, from, to, ivp); 71210409Skib ivp = to; 72210409Skib from += AES_BLOCK_LEN; 73210409Skib to += AES_BLOCK_LEN; 74210409Skib } 75210409Skib#ifdef DEBUG 76210409Skib ps_len("to:", to - len * AES_BLOCK_LEN, len * AES_BLOCK_LEN); 77210409Skib#endif 78210409Skib} 79210409Skib 80210409Skibvoid 81210409Skibaesni_encrypt_ecb(int rounds, const void *key_schedule, size_t len, 82210409Skib const uint8_t from[AES_BLOCK_LEN], uint8_t to[AES_BLOCK_LEN]) 83210409Skib{ 84210409Skib size_t i; 85210409Skib 86210409Skib len /= AES_BLOCK_LEN; 87210409Skib for (i = 0; i < len; i++) { 88210409Skib aesni_enc(rounds - 1, key_schedule, from, to, NULL); 89210409Skib from += AES_BLOCK_LEN; 90210409Skib to += AES_BLOCK_LEN; 91210409Skib } 92210409Skib} 93210409Skib 94210409Skibvoid 95210409Skibaesni_decrypt_ecb(int rounds, const void *key_schedule, size_t len, 96210409Skib const uint8_t from[AES_BLOCK_LEN], uint8_t to[AES_BLOCK_LEN]) 97210409Skib{ 98210409Skib size_t i; 99210409Skib 100210409Skib len /= AES_BLOCK_LEN; 101210409Skib for (i = 0; i < len; i++) { 102210409Skib aesni_dec(rounds - 1, key_schedule, from, to, NULL); 103210409Skib from += AES_BLOCK_LEN; 104210409Skib to += AES_BLOCK_LEN; 105210409Skib } 106210409Skib} 107210409Skib 108210409Skibint 109210409Skibaesni_cipher_setup(struct aesni_session *ses, struct cryptoini *encini) 110210409Skib{ 111210409Skib struct thread *td; 112210409Skib int error; 113210409Skib 114210409Skib switch (encini->cri_klen) { 115210409Skib case 128: 116210409Skib ses->rounds = AES128_ROUNDS; 117210409Skib break; 118210409Skib case 192: 119210409Skib ses->rounds = AES192_ROUNDS; 120210409Skib break; 121210409Skib case 256: 122210409Skib ses->rounds = AES256_ROUNDS; 123210409Skib break; 124210409Skib default: 125210409Skib return (EINVAL); 126210409Skib } 127210409Skib 128210409Skib td = curthread; 129210409Skib error = fpu_kern_enter(td, &ses->fpu_ctx, FPU_KERN_NORMAL); 130210409Skib if (error == 0) { 131210409Skib aesni_set_enckey(encini->cri_key, ses->enc_schedule, 132210409Skib ses->rounds); 133210409Skib aesni_set_deckey(ses->enc_schedule, ses->dec_schedule, 134210409Skib ses->rounds); 135210409Skib arc4rand(ses->iv, sizeof(ses->iv), 0); 136210409Skib fpu_kern_leave(td, &ses->fpu_ctx); 137210409Skib } 138210409Skib return (error); 139210409Skib} 140210409Skib 141210409Skibint 142210409Skibaesni_cipher_process(struct aesni_session *ses, struct cryptodesc *enccrd, 143210409Skib struct cryptop *crp) 144210409Skib{ 145210409Skib struct thread *td; 146210409Skib uint8_t *buf; 147210409Skib int error, allocated; 148210409Skib 149210409Skib buf = aesni_cipher_alloc(enccrd, crp, &allocated); 150210409Skib if (buf == NULL) { 151210409Skib error = ENOMEM; 152210409Skib goto out; 153210409Skib } 154210409Skib 155210409Skib td = curthread; 156210409Skib error = fpu_kern_enter(td, &ses->fpu_ctx, FPU_KERN_NORMAL); 157210409Skib if (error != 0) 158210409Skib goto out1; 159210409Skib 160210409Skib if ((enccrd->crd_flags & CRD_F_ENCRYPT) != 0) { 161210409Skib if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0) 162210409Skib bcopy(enccrd->crd_iv, ses->iv, AES_BLOCK_LEN); 163210409Skib 164210409Skib if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) 165210409Skib crypto_copyback(crp->crp_flags, crp->crp_buf, 166210409Skib enccrd->crd_inject, AES_BLOCK_LEN, ses->iv); 167210409Skib 168210409Skib aesni_encrypt_cbc(ses->rounds, ses->enc_schedule, 169210409Skib enccrd->crd_len, buf, buf, ses->iv); 170210409Skib } else { 171210409Skib if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0) 172210409Skib bcopy(enccrd->crd_iv, ses->iv, AES_BLOCK_LEN); 173210409Skib else 174210409Skib crypto_copydata(crp->crp_flags, crp->crp_buf, 175210409Skib enccrd->crd_inject, AES_BLOCK_LEN, ses->iv); 176210409Skib aesni_decrypt_cbc(ses->rounds, ses->dec_schedule, 177210409Skib enccrd->crd_len, buf, ses->iv); 178210409Skib } 179210409Skib fpu_kern_leave(td, &ses->fpu_ctx); 180210409Skib if (allocated) 181210409Skib crypto_copyback(crp->crp_flags, crp->crp_buf, enccrd->crd_skip, 182210409Skib enccrd->crd_len, buf); 183210409Skib if ((enccrd->crd_flags & CRD_F_ENCRYPT) != 0) 184210409Skib crypto_copydata(crp->crp_flags, crp->crp_buf, 185210409Skib enccrd->crd_skip + enccrd->crd_len - AES_BLOCK_LEN, 186210409Skib AES_BLOCK_LEN, ses->iv); 187210409Skib out1: 188210409Skib if (allocated) { 189210409Skib bzero(buf, enccrd->crd_len); 190210409Skib free(buf, M_AESNI); 191210409Skib } 192210409Skib out: 193210409Skib return (error); 194210409Skib} 195