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*2f9f8a9bSJason King  * Copyright 2019 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
aes_copy_block(uint8_t * in,uint8_t * out)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 
54fb261280SJason King /*
55fb261280SJason King  * Copy a 16-byte AES block in 64-bit chunks if the input address is aligned
56fb261280SJason King  * to 64-bits
57fb261280SJason King  */
58fb261280SJason King void
aes_copy_block64(uint8_t * in,uint64_t * out)59fb261280SJason King aes_copy_block64(uint8_t *in, uint64_t *out)
60fb261280SJason King {
61fb261280SJason King 	if (IS_P2ALIGNED(in, sizeof (uint64_t))) {
62fb261280SJason King 		/* LINTED: pointer alignment */
63fb261280SJason King 		out[0] = *(uint64_t *)&in[0];
64fb261280SJason King 		/* LINTED: pointer alignment */
65fb261280SJason King 		out[1] = *(uint64_t *)&in[8];
66fb261280SJason King 	} else {
67fb261280SJason King 		uint8_t *iv8 = (uint8_t *)&out[0];
68fb261280SJason King 
69fb261280SJason King 		AES_COPY_BLOCK(in, iv8);
70fb261280SJason King 	}
71fb261280SJason King }
7254034eb2SDan OpenSolaris Anderson 
7354034eb2SDan OpenSolaris Anderson /* XOR a 16-byte AES block of data into dst */
7454034eb2SDan OpenSolaris Anderson void
aes_xor_block(uint8_t * data,uint8_t * dst)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
aes_encrypt_contiguous_blocks(void * ctx,char * data,size_t length,crypto_data_t * out)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,
104*2f9f8a9bSJason King 		    AES_BLOCK_LEN, aes_encrypt_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
aes_decrypt_contiguous_blocks(void * ctx,char * data,size_t length,crypto_data_t * out)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,
137*2f9f8a9bSJason King 		    AES_BLOCK_LEN, aes_encrypt_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