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