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