154034eb2SDan OpenSolaris Anderson /* 254034eb2SDan OpenSolaris Anderson * CDDL HEADER START 354034eb2SDan OpenSolaris Anderson * 454034eb2SDan OpenSolaris Anderson * The contents of this file are subject to the terms of the 554034eb2SDan OpenSolaris Anderson * Common Development and Distribution License (the "License"). 654034eb2SDan OpenSolaris Anderson * You may not use this file except in compliance with the License. 754034eb2SDan OpenSolaris Anderson * 854034eb2SDan OpenSolaris Anderson * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 954034eb2SDan OpenSolaris Anderson * or http://www.opensolaris.org/os/licensing. 1054034eb2SDan OpenSolaris Anderson * See the License for the specific language governing permissions 1154034eb2SDan OpenSolaris Anderson * and limitations under the License. 1254034eb2SDan OpenSolaris Anderson * 1354034eb2SDan OpenSolaris Anderson * When distributing Covered Code, include this CDDL HEADER in each 1454034eb2SDan OpenSolaris Anderson * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1554034eb2SDan OpenSolaris Anderson * If applicable, add the following below this CDDL HEADER, with the 1654034eb2SDan OpenSolaris Anderson * fields enclosed by brackets "[]" replaced with your own identifying 1754034eb2SDan OpenSolaris Anderson * information: Portions Copyright [yyyy] [name of copyright owner] 1854034eb2SDan OpenSolaris Anderson * 1954034eb2SDan OpenSolaris Anderson * CDDL HEADER END 2054034eb2SDan OpenSolaris Anderson */ 2154034eb2SDan OpenSolaris Anderson /* 2254034eb2SDan OpenSolaris Anderson * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2354034eb2SDan OpenSolaris Anderson * Use is subject to license terms. 24*fb261280SJason King * Copyright 2018, Joyent, Inc. 2554034eb2SDan OpenSolaris Anderson */ 2654034eb2SDan OpenSolaris Anderson 2754034eb2SDan OpenSolaris Anderson #include <sys/types.h> 2854034eb2SDan OpenSolaris Anderson #include <sys/sysmacros.h> 2954034eb2SDan OpenSolaris Anderson #include <modes/modes.h> 3054034eb2SDan OpenSolaris Anderson #include "aes_impl.h" 3154034eb2SDan OpenSolaris Anderson #ifndef _KERNEL 3254034eb2SDan OpenSolaris Anderson #include <stdlib.h> 3354034eb2SDan OpenSolaris Anderson #endif /* !_KERNEL */ 3454034eb2SDan OpenSolaris Anderson 3554034eb2SDan OpenSolaris Anderson 3654034eb2SDan OpenSolaris Anderson /* Copy a 16-byte AES block from "in" to "out" */ 3754034eb2SDan OpenSolaris Anderson void 3854034eb2SDan OpenSolaris Anderson aes_copy_block(uint8_t *in, uint8_t *out) 3954034eb2SDan OpenSolaris Anderson { 4054034eb2SDan OpenSolaris Anderson if (IS_P2ALIGNED2(in, out, sizeof (uint32_t))) { 4154034eb2SDan OpenSolaris Anderson /* LINTED: pointer alignment */ 4254034eb2SDan OpenSolaris Anderson *(uint32_t *)&out[0] = *(uint32_t *)&in[0]; 4354034eb2SDan OpenSolaris Anderson /* LINTED: pointer alignment */ 4454034eb2SDan OpenSolaris Anderson *(uint32_t *)&out[4] = *(uint32_t *)&in[4]; 4554034eb2SDan OpenSolaris Anderson /* LINTED: pointer alignment */ 4654034eb2SDan OpenSolaris Anderson *(uint32_t *)&out[8] = *(uint32_t *)&in[8]; 4754034eb2SDan OpenSolaris Anderson /* LINTED: pointer alignment */ 4854034eb2SDan OpenSolaris Anderson *(uint32_t *)&out[12] = *(uint32_t *)&in[12]; 4954034eb2SDan OpenSolaris Anderson } else { 5054034eb2SDan OpenSolaris Anderson AES_COPY_BLOCK(in, out); 5154034eb2SDan OpenSolaris Anderson } 5254034eb2SDan OpenSolaris Anderson } 5354034eb2SDan OpenSolaris Anderson 54*fb261280SJason King /* 55*fb261280SJason King * Copy a 16-byte AES block in 64-bit chunks if the input address is aligned 56*fb261280SJason King * to 64-bits 57*fb261280SJason King */ 58*fb261280SJason King void 59*fb261280SJason King aes_copy_block64(uint8_t *in, uint64_t *out) 60*fb261280SJason King { 61*fb261280SJason King if (IS_P2ALIGNED(in, sizeof (uint64_t))) { 62*fb261280SJason King /* LINTED: pointer alignment */ 63*fb261280SJason King out[0] = *(uint64_t *)&in[0]; 64*fb261280SJason King /* LINTED: pointer alignment */ 65*fb261280SJason King out[1] = *(uint64_t *)&in[8]; 66*fb261280SJason King } else { 67*fb261280SJason King uint8_t *iv8 = (uint8_t *)&out[0]; 68*fb261280SJason King 69*fb261280SJason King AES_COPY_BLOCK(in, iv8); 70*fb261280SJason King } 71*fb261280SJason King } 7254034eb2SDan OpenSolaris Anderson 7354034eb2SDan OpenSolaris Anderson /* XOR a 16-byte AES block of data into dst */ 7454034eb2SDan OpenSolaris Anderson void 7554034eb2SDan OpenSolaris Anderson aes_xor_block(uint8_t *data, uint8_t *dst) 7654034eb2SDan OpenSolaris Anderson { 7754034eb2SDan OpenSolaris Anderson if (IS_P2ALIGNED2(dst, data, sizeof (uint32_t))) { 7854034eb2SDan OpenSolaris Anderson /* LINTED: pointer alignment */ 7954034eb2SDan OpenSolaris Anderson *(uint32_t *)&dst[0] ^= *(uint32_t *)&data[0]; 8054034eb2SDan OpenSolaris Anderson /* LINTED: pointer alignment */ 8154034eb2SDan OpenSolaris Anderson *(uint32_t *)&dst[4] ^= *(uint32_t *)&data[4]; 8254034eb2SDan OpenSolaris Anderson /* LINTED: pointer alignment */ 8354034eb2SDan OpenSolaris Anderson *(uint32_t *)&dst[8] ^= *(uint32_t *)&data[8]; 8454034eb2SDan OpenSolaris Anderson /* LINTED: pointer alignment */ 8554034eb2SDan OpenSolaris Anderson *(uint32_t *)&dst[12] ^= *(uint32_t *)&data[12]; 8654034eb2SDan OpenSolaris Anderson } else { 8754034eb2SDan OpenSolaris Anderson AES_XOR_BLOCK(data, dst); 8854034eb2SDan OpenSolaris Anderson } 8954034eb2SDan OpenSolaris Anderson } 9054034eb2SDan OpenSolaris Anderson 9154034eb2SDan OpenSolaris Anderson 9254034eb2SDan OpenSolaris Anderson /* 9354034eb2SDan OpenSolaris Anderson * Encrypt multiple blocks of data according to mode. 9454034eb2SDan OpenSolaris Anderson */ 9554034eb2SDan OpenSolaris Anderson int 9654034eb2SDan OpenSolaris Anderson aes_encrypt_contiguous_blocks(void *ctx, char *data, size_t length, 9754034eb2SDan OpenSolaris Anderson crypto_data_t *out) 9854034eb2SDan OpenSolaris Anderson { 9954034eb2SDan OpenSolaris Anderson aes_ctx_t *aes_ctx = ctx; 10054034eb2SDan OpenSolaris Anderson int rv; 10154034eb2SDan OpenSolaris Anderson 10254034eb2SDan OpenSolaris Anderson if (aes_ctx->ac_flags & CTR_MODE) { 10354034eb2SDan OpenSolaris Anderson rv = ctr_mode_contiguous_blocks(ctx, data, length, out, 10454034eb2SDan OpenSolaris Anderson AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block); 10554034eb2SDan OpenSolaris Anderson } else if (aes_ctx->ac_flags & CCM_MODE) { 10654034eb2SDan OpenSolaris Anderson rv = ccm_mode_encrypt_contiguous_blocks(ctx, data, length, 10754034eb2SDan OpenSolaris Anderson out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, 10854034eb2SDan OpenSolaris Anderson aes_xor_block); 10954034eb2SDan OpenSolaris Anderson } else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) { 11054034eb2SDan OpenSolaris Anderson rv = gcm_mode_encrypt_contiguous_blocks(ctx, data, length, 11154034eb2SDan OpenSolaris Anderson out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, 11254034eb2SDan OpenSolaris Anderson aes_xor_block); 113cd964fceSMatt Barden } else if (aes_ctx->ac_flags & (CBC_MODE|CMAC_MODE)) { 11454034eb2SDan OpenSolaris Anderson rv = cbc_encrypt_contiguous_blocks(ctx, 11554034eb2SDan OpenSolaris Anderson data, length, out, AES_BLOCK_LEN, aes_encrypt_block, 11654034eb2SDan OpenSolaris Anderson aes_copy_block, aes_xor_block); 11754034eb2SDan OpenSolaris Anderson } else { 11854034eb2SDan OpenSolaris Anderson rv = ecb_cipher_contiguous_blocks(ctx, data, length, out, 11954034eb2SDan OpenSolaris Anderson AES_BLOCK_LEN, aes_encrypt_block); 12054034eb2SDan OpenSolaris Anderson } 12154034eb2SDan OpenSolaris Anderson return (rv); 12254034eb2SDan OpenSolaris Anderson } 12354034eb2SDan OpenSolaris Anderson 12454034eb2SDan OpenSolaris Anderson 12554034eb2SDan OpenSolaris Anderson /* 12654034eb2SDan OpenSolaris Anderson * Decrypt multiple blocks of data according to mode. 12754034eb2SDan OpenSolaris Anderson */ 12854034eb2SDan OpenSolaris Anderson int 12954034eb2SDan OpenSolaris Anderson aes_decrypt_contiguous_blocks(void *ctx, char *data, size_t length, 13054034eb2SDan OpenSolaris Anderson crypto_data_t *out) 13154034eb2SDan OpenSolaris Anderson { 13254034eb2SDan OpenSolaris Anderson aes_ctx_t *aes_ctx = ctx; 13354034eb2SDan OpenSolaris Anderson int rv; 13454034eb2SDan OpenSolaris Anderson 13554034eb2SDan OpenSolaris Anderson if (aes_ctx->ac_flags & CTR_MODE) { 13654034eb2SDan OpenSolaris Anderson rv = ctr_mode_contiguous_blocks(ctx, data, length, out, 13754034eb2SDan OpenSolaris Anderson AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block); 13854034eb2SDan OpenSolaris Anderson if (rv == CRYPTO_DATA_LEN_RANGE) 13954034eb2SDan OpenSolaris Anderson rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE; 14054034eb2SDan OpenSolaris Anderson } else if (aes_ctx->ac_flags & CCM_MODE) { 14154034eb2SDan OpenSolaris Anderson rv = ccm_mode_decrypt_contiguous_blocks(ctx, data, length, 14254034eb2SDan OpenSolaris Anderson out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, 14354034eb2SDan OpenSolaris Anderson aes_xor_block); 14454034eb2SDan OpenSolaris Anderson } else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) { 14554034eb2SDan OpenSolaris Anderson rv = gcm_mode_decrypt_contiguous_blocks(ctx, data, length, 14654034eb2SDan OpenSolaris Anderson out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, 14754034eb2SDan OpenSolaris Anderson aes_xor_block); 14854034eb2SDan OpenSolaris Anderson } else if (aes_ctx->ac_flags & CBC_MODE) { 14954034eb2SDan OpenSolaris Anderson rv = cbc_decrypt_contiguous_blocks(ctx, data, length, out, 15054034eb2SDan OpenSolaris Anderson AES_BLOCK_LEN, aes_decrypt_block, aes_copy_block, 15154034eb2SDan OpenSolaris Anderson aes_xor_block); 15254034eb2SDan OpenSolaris Anderson } else { 15354034eb2SDan OpenSolaris Anderson rv = ecb_cipher_contiguous_blocks(ctx, data, length, out, 15454034eb2SDan OpenSolaris Anderson AES_BLOCK_LEN, aes_decrypt_block); 15554034eb2SDan OpenSolaris Anderson if (rv == CRYPTO_DATA_LEN_RANGE) 15654034eb2SDan OpenSolaris Anderson rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE; 15754034eb2SDan OpenSolaris Anderson } 15854034eb2SDan OpenSolaris Anderson return (rv); 15954034eb2SDan OpenSolaris Anderson } 160