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 & CCM_MODE) { 79 rv = ccm_mode_encrypt_contiguous_blocks(ctx, data, length, 80 out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, 81 aes_xor_block); 82 } else if (aes_ctx->ac_flags & GCM_MODE) { 83 rv = gcm_mode_encrypt_contiguous_blocks(ctx, data, length, 84 out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, 85 aes_xor_block); 86 } 87 else 88 __builtin_unreachable(); 89 return (rv); 90 } 91 92 93 /* 94 * Decrypt multiple blocks of data according to mode. 95 */ 96 int 97 aes_decrypt_contiguous_blocks(void *ctx, char *data, size_t length, 98 crypto_data_t *out) 99 { 100 aes_ctx_t *aes_ctx = ctx; 101 int rv; 102 103 if (aes_ctx->ac_flags & CCM_MODE) { 104 rv = ccm_mode_decrypt_contiguous_blocks(ctx, data, length, 105 out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, 106 aes_xor_block); 107 } else if (aes_ctx->ac_flags & GCM_MODE) { 108 rv = gcm_mode_decrypt_contiguous_blocks(ctx, data, length, 109 out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, 110 aes_xor_block); 111 } else 112 __builtin_unreachable(); 113 return (rv); 114 } 115