Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Linux AES Driver for Zynq Ultrascale+ MPSoC & Versal

...

The Zynq UltraScale+ MPSoC includes an AES-GCM engine for symmetric key encryption and decryption. It is an symmetric algorithm. 
This block uses AES-GCM algorithm to encrypt or decrypt the provided data. It requires a key of size 256 bits and initialization vector(IV) of size 96 bits.
This driver is supported for ZynqMP and Versal.

HW IP Features

  • Supports Symmetric key algorithm.

Features supported in driver

  • Supports Symmetric key algorithm.


PLM Configuration

For Versal, in order to use this driver, the BSP of PLM must be configured to enable XSECURE_NONSECURE_IPI_ACCESS macro in XilSecure library.

This configuration in PLM shall be deprecated and removed in 2023.2 release. 

Kernel Configuration

For ZynqMP, the ZynqMP AES driver and the userspace interface for AEAD algorithms are enabled by default. So there is no need for kernel configuration.

...

Code Block
themeMidnight
root@xilinx-zcu102-2019_1:/run/media/mmcblk0# ./Enc
Data Out:
edaae826b6b416bbd2815879692058f16df1133c7222d549141dcfef0faf01afd6433f9dc6bb7d3207d4a531cdf5e6ebf596bd4a0c3d430313ce88e2b9e16c086e633d24
GCM TAG:
b52b80cd5117afb47b116d4a8f89cf75
Input:
1234567808f070b030d0509010e060a020c0408000a5de08d85898a5a5fedca10134abcdef12345678900987654321123487654124456679874309713627463801ad1056root@xilinx-zcu102-2019_1:/run/media/mmcblk0# ./Dec
Data Out:
1234567808f070b030d0509010e060a020c0408000a5de08d85898a5a5fedca10134abcdef12345678900987654321123487654124456679874309713627463801ad1056

Please note as the data provided in user space will be located in virtual space, linux driver before handing off to ATF converts the data buffers to physical address.

Userspace examples for Versal

...

Code Block
languagecpp
themeMidnight
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/if_alg.h>
#include <linux/socket.h>
#include <string.h>

#ifndef SOL_ALG
#define SOL_ALG 279
#endif


#define KEY_SIZE        32
#define AAD_SIZE	16
#define IV_SIZE         12
#define GCM_TAG_SIZE    16
#define DATA_SIZE	68

#define VERSAL_AES_USER_KEY_0 12

int main(void)
{
	int len = AAD_SIZE + DATA_SIZE + GCM_TAG_SIZE;
	int opfd;
	int tfmfd;
	struct sockaddr_alg sa = {
		.salg_family = AF_ALG,
		.salg_type = "aead",
		.salg_name = "gcm(aes)"
	};
	struct msghdr msg = {};
	struct cmsghdr *cmsg;
	char cbuf[CMSG_SPACE(4) + CMSG_SPACE(1024) + CMSG_SPACE(1024)] = {0};
	char buf[len];
	struct af_alg_iv *iv;
	struct iovec iov;
	int i;


	__u8 key[] = {
		0xF8, 0x78, 0xB8, 0x38, 0xD8, 0x58, 0x98, 0x18, 0xE8, 0x68, 0xA8, 0x28, 0xC8, 0x48,
		0x88, 0x08, 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20,
		0xC0, 0x40, 0x80, 0x00
	};
	__u8 key_type[] = {VERSAL_AES_USER_KEY_0};


	__u8 usr_iv[] = {
		0xD2, 0x45, 0x0E, 0x07, 0xEA, 0x5D, 0xE0, 0x42, 0x6C, 0x0F, 0xA1, 0x33
	};
	__u8 input[] = {
		/* First1bytes are AAD data */
		0x67, 0xe2, 0x1c, 0xf3, 0xcb, 0x29, 0xe0, 0xdc,
		0xbc, 0x4d, 0x8b, 0x1d, 0x0c, 0xc5, 0x33, 0x4b,
		/* Cipher text  */
		0xed, 0xaa, 0xe8, 0x26, 0xb6, 0xb4, 0x16, 0xbb, 0xd2, 0x81, 0x58, 0x79, 0x69, 0x20, 0x58, 0xf1, 0x6d, 0xf1, 0x13, 0x3c, 0x72,
		0x22, 0xd5, 0x49, 0x14, 0x1d, 0xcf, 0xef, 0x0f, 0xaf, 0x01, 0xaf, 0xd6, 0x43, 0x3f, 0x9d, 0xc6, 0xbb, 0x7d, 0x32, 0x07, 0xd4,
		0xa5, 0x31, 0xcd, 0xf5, 0xe6, 0xeb, 0xf5, 0x96, 0xbd, 0x4a, 0x0c, 0x3d, 0x43, 0x03, 0x13, 0xce, 0x88, 0xe2, 0xb9, 0xe1, 0x6c,
		0x08, 0x6e, 0x63, 0x3d, 0x24,

		/* GCM TAG */
		0xec, 0x5a, 0xfd, 0x6b, 0x11, 0x8c, 0xff, 0x14, 0xfb, 0x63, 0x16, 0x75, 0xa5, 0x84, 0x0b, 0x4c

	};



	tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
	printf("BIND \n");
	bind(tfmfd, (struct sockaddr *)&sa, sizeof(sa));
	printf("SET KEY \n");
	setsockopt(tfmfd, SOL_ALG, ALG_SET_KEY, key, KEY_SIZE);
	printf("SET auth size \n");
	setsockopt(tfmfd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, 16);
	printf("ACCEPT \n");
	opfd = accept(tfmfd, NULL, 0);
	msg.msg_control = cbuf;
	msg.msg_controllen = sizeof(cbuf);
	printf("SET OP \n");
	cmsg = CMSG_FIRSTHDR(&msg);
	cmsg->cmsg_level = SOL_ALG;
	cmsg->cmsg_type = ALG_SET_OP;
	cmsg->cmsg_len = CMSG_LEN(4);
	*(__u32 *)CMSG_DATA(cmsg) = ALG_OP_DECRYPT;
	printf("SET IV \n");
	cmsg = CMSG_NXTHDR(&msg, cmsg);
	cmsg->cmsg_level = SOL_ALG;
	cmsg->cmsg_type = ALG_SET_IV;
	cmsg->cmsg_len = CMSG_LEN(1024);
	iv = (void *)CMSG_DATA(cmsg);
	iv->ivlen = IV_SIZE;
	memcpy(iv->iv, usr_iv, IV_SIZE);

	cmsg = CMSG_NXTHDR(&msg, cmsg);
	cmsg->cmsg_level = SOL_ALG;
	cmsg->cmsg_type = ALG_SET_AEAD_ASSOCLEN;
	cmsg->cmsg_len = CMSG_LEN(1024);

	iv = (void *)CMSG_DATA(cmsg);
	iv->ivlen = AAD_SIZE;

	iov.iov_base = input;
	iov.iov_len = len;
	printf("SET INPUT \n");
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	printf("SEND MSG \n");
	sendmsg(opfd, &msg, 0);
	printf("READ \n");
	read(opfd, buf, len - GCM_TAG_SIZE);

	close(opfd);
	printf("CLOSE OPFD \n");
	close(tfmfd);
	printf("CLOSE TFMFD \n");

	printf("Data Out:\r\n");
	for (i = AAD_SIZE; i < len - GCM_TAG_SIZE; i++) {
		printf("%02x", (unsigned char)buf[i]);
	}
	printf("\n");

	return 0;
}

Mainline status

Change Log

2018.3 

Summary 

  • crypto: zynqmp-aes: Adds zynqmp-aes driver

Commits

Initial commit

  • c7e7089 crypto: synqmp-aes: Adds zynqmp-aes driver 

Bug fixes 

  • 6c6033a crypto: zynqmp-aes: Fix for segfault seen with large sets of data
  • c1a602d crypto: zynqmp-aes: Adds an error code for zynqmp-aes driver

2023.1

  • Userspace interface for AEAD algorithms(CONFIG_CRYPTO_USER_API_AEAD) and the driver(CONFIG_CRYPTO_DEV_ZYNQMP_AES) are enabled by default in the xilinx_defconfig and xilinx_zynqmp_defconfig
  • Existing driver is replaced with new driver written using aead framework
  • Added support for Versal

Related Links

Driver Code : https://github.com/Xilinx/linux-xlnx/blob/master/drivers/crypto/xilinx/zynqmp-aes-gcm.c

...