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 https://opensource.org/licenses/CDDL-1.0. 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/zfs_context.h> 27 #include <modes/modes.h> 28 #include <aes/aes_impl.h> 29 30 /* Copy a 16-byte AES block from "in" to "out" */ 31 void 32 aes_copy_block(uint8_t *in, uint8_t *out) 33 { 34 if (IS_P2ALIGNED2(in, out, sizeof (uint32_t))) { 35 /* LINTED: pointer alignment */ 36 *(uint32_t *)&out[0] = *(uint32_t *)&in[0]; 37 /* LINTED: pointer alignment */ 38 *(uint32_t *)&out[4] = *(uint32_t *)&in[4]; 39 /* LINTED: pointer alignment */ 40 *(uint32_t *)&out[8] = *(uint32_t *)&in[8]; 41 /* LINTED: pointer alignment */ 42 *(uint32_t *)&out[12] = *(uint32_t *)&in[12]; 43 } else { 44 AES_COPY_BLOCK(in, out); 45 } 46 } 47 48 49 /* XOR a 16-byte AES block of data into dst */ 50 void 51 aes_xor_block(uint8_t *data, uint8_t *dst) 52 { 53 if (IS_P2ALIGNED2(dst, data, sizeof (uint32_t))) { 54 /* LINTED: pointer alignment */ 55 *(uint32_t *)&dst[0] ^= *(uint32_t *)&data[0]; 56 /* LINTED: pointer alignment */ 57 *(uint32_t *)&dst[4] ^= *(uint32_t *)&data[4]; 58 /* LINTED: pointer alignment */ 59 *(uint32_t *)&dst[8] ^= *(uint32_t *)&data[8]; 60 /* LINTED: pointer alignment */ 61 *(uint32_t *)&dst[12] ^= *(uint32_t *)&data[12]; 62 } else { 63 AES_XOR_BLOCK(data, dst); 64 } 65 } 66 67 68 /* 69 * Encrypt multiple blocks of data according to mode. 70 */ 71 int 72 aes_encrypt_contiguous_blocks(void *ctx, char *data, size_t length, 73 crypto_data_t *out) 74 { 75 aes_ctx_t *aes_ctx = ctx; 76 int rv; 77 78 if (aes_ctx->ac_flags & CTR_MODE) { 79 rv = ctr_mode_contiguous_blocks(ctx, data, length, out, 80 AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block); 81 } else if (aes_ctx->ac_flags & CCM_MODE) { 82 rv = ccm_mode_encrypt_contiguous_blocks(ctx, data, length, 83 out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, 84 aes_xor_block); 85 } else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) { 86 rv = gcm_mode_encrypt_contiguous_blocks(ctx, data, length, 87 out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, 88 aes_xor_block); 89 } else if (aes_ctx->ac_flags & CBC_MODE) { 90 rv = cbc_encrypt_contiguous_blocks(ctx, 91 data, length, out, AES_BLOCK_LEN, aes_encrypt_block, 92 aes_copy_block, aes_xor_block); 93 } else { 94 rv = ecb_cipher_contiguous_blocks(ctx, data, length, out, 95 AES_BLOCK_LEN, aes_encrypt_block); 96 } 97 return (rv); 98 } 99 100 101 /* 102 * Decrypt multiple blocks of data according to mode. 103 */ 104 int 105 aes_decrypt_contiguous_blocks(void *ctx, char *data, size_t length, 106 crypto_data_t *out) 107 { 108 aes_ctx_t *aes_ctx = ctx; 109 int rv; 110 111 if (aes_ctx->ac_flags & CTR_MODE) { 112 rv = ctr_mode_contiguous_blocks(ctx, data, length, out, 113 AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block); 114 if (rv == CRYPTO_DATA_LEN_RANGE) 115 rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE; 116 } else if (aes_ctx->ac_flags & CCM_MODE) { 117 rv = ccm_mode_decrypt_contiguous_blocks(ctx, data, length, 118 out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, 119 aes_xor_block); 120 } else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) { 121 rv = gcm_mode_decrypt_contiguous_blocks(ctx, data, length, 122 out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, 123 aes_xor_block); 124 } else if (aes_ctx->ac_flags & CBC_MODE) { 125 rv = cbc_decrypt_contiguous_blocks(ctx, data, length, out, 126 AES_BLOCK_LEN, aes_decrypt_block, aes_copy_block, 127 aes_xor_block); 128 } else { 129 rv = ecb_cipher_contiguous_blocks(ctx, data, length, out, 130 AES_BLOCK_LEN, aes_decrypt_block); 131 if (rv == CRYPTO_DATA_LEN_RANGE) 132 rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE; 133 } 134 return (rv); 135 } 136