1*54034eb2SDan OpenSolaris Anderson /* 2*54034eb2SDan OpenSolaris Anderson * CDDL HEADER START 3*54034eb2SDan OpenSolaris Anderson * 4*54034eb2SDan OpenSolaris Anderson * The contents of this file are subject to the terms of the 5*54034eb2SDan OpenSolaris Anderson * Common Development and Distribution License (the "License"). 6*54034eb2SDan OpenSolaris Anderson * You may not use this file except in compliance with the License. 7*54034eb2SDan OpenSolaris Anderson * 8*54034eb2SDan OpenSolaris Anderson * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*54034eb2SDan OpenSolaris Anderson * or http://www.opensolaris.org/os/licensing. 10*54034eb2SDan OpenSolaris Anderson * See the License for the specific language governing permissions 11*54034eb2SDan OpenSolaris Anderson * and limitations under the License. 12*54034eb2SDan OpenSolaris Anderson * 13*54034eb2SDan OpenSolaris Anderson * When distributing Covered Code, include this CDDL HEADER in each 14*54034eb2SDan OpenSolaris Anderson * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*54034eb2SDan OpenSolaris Anderson * If applicable, add the following below this CDDL HEADER, with the 16*54034eb2SDan OpenSolaris Anderson * fields enclosed by brackets "[]" replaced with your own identifying 17*54034eb2SDan OpenSolaris Anderson * information: Portions Copyright [yyyy] [name of copyright owner] 18*54034eb2SDan OpenSolaris Anderson * 19*54034eb2SDan OpenSolaris Anderson * CDDL HEADER END 20*54034eb2SDan OpenSolaris Anderson */ 21*54034eb2SDan OpenSolaris Anderson /* 22*54034eb2SDan OpenSolaris Anderson * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23*54034eb2SDan OpenSolaris Anderson * Use is subject to license terms. 24*54034eb2SDan OpenSolaris Anderson */ 25*54034eb2SDan OpenSolaris Anderson 26*54034eb2SDan OpenSolaris Anderson #include <sys/types.h> 27*54034eb2SDan OpenSolaris Anderson #include <sys/sysmacros.h> 28*54034eb2SDan OpenSolaris Anderson #include <modes/modes.h> 29*54034eb2SDan OpenSolaris Anderson #include "aes_impl.h" 30*54034eb2SDan OpenSolaris Anderson #ifndef _KERNEL 31*54034eb2SDan OpenSolaris Anderson #include <stdlib.h> 32*54034eb2SDan OpenSolaris Anderson #endif /* !_KERNEL */ 33*54034eb2SDan OpenSolaris Anderson 34*54034eb2SDan OpenSolaris Anderson 35*54034eb2SDan OpenSolaris Anderson /* Copy a 16-byte AES block from "in" to "out" */ 36*54034eb2SDan OpenSolaris Anderson void 37*54034eb2SDan OpenSolaris Anderson aes_copy_block(uint8_t *in, uint8_t *out) 38*54034eb2SDan OpenSolaris Anderson { 39*54034eb2SDan OpenSolaris Anderson if (IS_P2ALIGNED2(in, out, sizeof (uint32_t))) { 40*54034eb2SDan OpenSolaris Anderson /* LINTED: pointer alignment */ 41*54034eb2SDan OpenSolaris Anderson *(uint32_t *)&out[0] = *(uint32_t *)&in[0]; 42*54034eb2SDan OpenSolaris Anderson /* LINTED: pointer alignment */ 43*54034eb2SDan OpenSolaris Anderson *(uint32_t *)&out[4] = *(uint32_t *)&in[4]; 44*54034eb2SDan OpenSolaris Anderson /* LINTED: pointer alignment */ 45*54034eb2SDan OpenSolaris Anderson *(uint32_t *)&out[8] = *(uint32_t *)&in[8]; 46*54034eb2SDan OpenSolaris Anderson /* LINTED: pointer alignment */ 47*54034eb2SDan OpenSolaris Anderson *(uint32_t *)&out[12] = *(uint32_t *)&in[12]; 48*54034eb2SDan OpenSolaris Anderson } else { 49*54034eb2SDan OpenSolaris Anderson AES_COPY_BLOCK(in, out); 50*54034eb2SDan OpenSolaris Anderson } 51*54034eb2SDan OpenSolaris Anderson } 52*54034eb2SDan OpenSolaris Anderson 53*54034eb2SDan OpenSolaris Anderson 54*54034eb2SDan OpenSolaris Anderson /* XOR a 16-byte AES block of data into dst */ 55*54034eb2SDan OpenSolaris Anderson void 56*54034eb2SDan OpenSolaris Anderson aes_xor_block(uint8_t *data, uint8_t *dst) 57*54034eb2SDan OpenSolaris Anderson { 58*54034eb2SDan OpenSolaris Anderson if (IS_P2ALIGNED2(dst, data, sizeof (uint32_t))) { 59*54034eb2SDan OpenSolaris Anderson /* LINTED: pointer alignment */ 60*54034eb2SDan OpenSolaris Anderson *(uint32_t *)&dst[0] ^= *(uint32_t *)&data[0]; 61*54034eb2SDan OpenSolaris Anderson /* LINTED: pointer alignment */ 62*54034eb2SDan OpenSolaris Anderson *(uint32_t *)&dst[4] ^= *(uint32_t *)&data[4]; 63*54034eb2SDan OpenSolaris Anderson /* LINTED: pointer alignment */ 64*54034eb2SDan OpenSolaris Anderson *(uint32_t *)&dst[8] ^= *(uint32_t *)&data[8]; 65*54034eb2SDan OpenSolaris Anderson /* LINTED: pointer alignment */ 66*54034eb2SDan OpenSolaris Anderson *(uint32_t *)&dst[12] ^= *(uint32_t *)&data[12]; 67*54034eb2SDan OpenSolaris Anderson } else { 68*54034eb2SDan OpenSolaris Anderson AES_XOR_BLOCK(data, dst); 69*54034eb2SDan OpenSolaris Anderson } 70*54034eb2SDan OpenSolaris Anderson } 71*54034eb2SDan OpenSolaris Anderson 72*54034eb2SDan OpenSolaris Anderson 73*54034eb2SDan OpenSolaris Anderson /* 74*54034eb2SDan OpenSolaris Anderson * Encrypt multiple blocks of data according to mode. 75*54034eb2SDan OpenSolaris Anderson */ 76*54034eb2SDan OpenSolaris Anderson int 77*54034eb2SDan OpenSolaris Anderson aes_encrypt_contiguous_blocks(void *ctx, char *data, size_t length, 78*54034eb2SDan OpenSolaris Anderson crypto_data_t *out) 79*54034eb2SDan OpenSolaris Anderson { 80*54034eb2SDan OpenSolaris Anderson aes_ctx_t *aes_ctx = ctx; 81*54034eb2SDan OpenSolaris Anderson int rv; 82*54034eb2SDan OpenSolaris Anderson 83*54034eb2SDan OpenSolaris Anderson if (aes_ctx->ac_flags & CTR_MODE) { 84*54034eb2SDan OpenSolaris Anderson rv = ctr_mode_contiguous_blocks(ctx, data, length, out, 85*54034eb2SDan OpenSolaris Anderson AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block); 86*54034eb2SDan OpenSolaris Anderson #ifdef _KERNEL 87*54034eb2SDan OpenSolaris Anderson } else if (aes_ctx->ac_flags & CCM_MODE) { 88*54034eb2SDan OpenSolaris Anderson rv = ccm_mode_encrypt_contiguous_blocks(ctx, data, length, 89*54034eb2SDan OpenSolaris Anderson out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, 90*54034eb2SDan OpenSolaris Anderson aes_xor_block); 91*54034eb2SDan OpenSolaris Anderson } else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) { 92*54034eb2SDan OpenSolaris Anderson rv = gcm_mode_encrypt_contiguous_blocks(ctx, data, length, 93*54034eb2SDan OpenSolaris Anderson out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, 94*54034eb2SDan OpenSolaris Anderson aes_xor_block); 95*54034eb2SDan OpenSolaris Anderson #endif 96*54034eb2SDan OpenSolaris Anderson } else if (aes_ctx->ac_flags & CBC_MODE) { 97*54034eb2SDan OpenSolaris Anderson rv = cbc_encrypt_contiguous_blocks(ctx, 98*54034eb2SDan OpenSolaris Anderson data, length, out, AES_BLOCK_LEN, aes_encrypt_block, 99*54034eb2SDan OpenSolaris Anderson aes_copy_block, aes_xor_block); 100*54034eb2SDan OpenSolaris Anderson } else { 101*54034eb2SDan OpenSolaris Anderson rv = ecb_cipher_contiguous_blocks(ctx, data, length, out, 102*54034eb2SDan OpenSolaris Anderson AES_BLOCK_LEN, aes_encrypt_block); 103*54034eb2SDan OpenSolaris Anderson } 104*54034eb2SDan OpenSolaris Anderson return (rv); 105*54034eb2SDan OpenSolaris Anderson } 106*54034eb2SDan OpenSolaris Anderson 107*54034eb2SDan OpenSolaris Anderson 108*54034eb2SDan OpenSolaris Anderson /* 109*54034eb2SDan OpenSolaris Anderson * Decrypt multiple blocks of data according to mode. 110*54034eb2SDan OpenSolaris Anderson */ 111*54034eb2SDan OpenSolaris Anderson int 112*54034eb2SDan OpenSolaris Anderson aes_decrypt_contiguous_blocks(void *ctx, char *data, size_t length, 113*54034eb2SDan OpenSolaris Anderson crypto_data_t *out) 114*54034eb2SDan OpenSolaris Anderson { 115*54034eb2SDan OpenSolaris Anderson aes_ctx_t *aes_ctx = ctx; 116*54034eb2SDan OpenSolaris Anderson int rv; 117*54034eb2SDan OpenSolaris Anderson 118*54034eb2SDan OpenSolaris Anderson if (aes_ctx->ac_flags & CTR_MODE) { 119*54034eb2SDan OpenSolaris Anderson rv = ctr_mode_contiguous_blocks(ctx, data, length, out, 120*54034eb2SDan OpenSolaris Anderson AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block); 121*54034eb2SDan OpenSolaris Anderson if (rv == CRYPTO_DATA_LEN_RANGE) 122*54034eb2SDan OpenSolaris Anderson rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE; 123*54034eb2SDan OpenSolaris Anderson #ifdef _KERNEL 124*54034eb2SDan OpenSolaris Anderson } else if (aes_ctx->ac_flags & CCM_MODE) { 125*54034eb2SDan OpenSolaris Anderson rv = ccm_mode_decrypt_contiguous_blocks(ctx, data, length, 126*54034eb2SDan OpenSolaris Anderson out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, 127*54034eb2SDan OpenSolaris Anderson aes_xor_block); 128*54034eb2SDan OpenSolaris Anderson } else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) { 129*54034eb2SDan OpenSolaris Anderson rv = gcm_mode_decrypt_contiguous_blocks(ctx, data, length, 130*54034eb2SDan OpenSolaris Anderson out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, 131*54034eb2SDan OpenSolaris Anderson aes_xor_block); 132*54034eb2SDan OpenSolaris Anderson #endif 133*54034eb2SDan OpenSolaris Anderson } else if (aes_ctx->ac_flags & CBC_MODE) { 134*54034eb2SDan OpenSolaris Anderson rv = cbc_decrypt_contiguous_blocks(ctx, data, length, out, 135*54034eb2SDan OpenSolaris Anderson AES_BLOCK_LEN, aes_decrypt_block, aes_copy_block, 136*54034eb2SDan OpenSolaris Anderson aes_xor_block); 137*54034eb2SDan OpenSolaris Anderson } else { 138*54034eb2SDan OpenSolaris Anderson rv = ecb_cipher_contiguous_blocks(ctx, data, length, out, 139*54034eb2SDan OpenSolaris Anderson AES_BLOCK_LEN, aes_decrypt_block); 140*54034eb2SDan OpenSolaris Anderson if (rv == CRYPTO_DATA_LEN_RANGE) 141*54034eb2SDan OpenSolaris Anderson rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE; 142*54034eb2SDan OpenSolaris Anderson } 143*54034eb2SDan OpenSolaris Anderson return (rv); 144*54034eb2SDan OpenSolaris Anderson } 145