162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Minimal library implementation of GCM
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2022 Google LLC
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/module.h>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <crypto/algapi.h>
1162306a36Sopenharmony_ci#include <crypto/gcm.h>
1262306a36Sopenharmony_ci#include <crypto/ghash.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <asm/irqflags.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_cistatic void aesgcm_encrypt_block(const struct crypto_aes_ctx *ctx, void *dst,
1762306a36Sopenharmony_ci				 const void *src)
1862306a36Sopenharmony_ci{
1962306a36Sopenharmony_ci	unsigned long flags;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	/*
2262306a36Sopenharmony_ci	 * In AES-GCM, both the GHASH key derivation and the CTR mode
2362306a36Sopenharmony_ci	 * encryption operate on known plaintext, making them susceptible to
2462306a36Sopenharmony_ci	 * timing attacks on the encryption key. The AES library already
2562306a36Sopenharmony_ci	 * mitigates this risk to some extent by pulling the entire S-box into
2662306a36Sopenharmony_ci	 * the caches before doing any substitutions, but this strategy is more
2762306a36Sopenharmony_ci	 * effective when running with interrupts disabled.
2862306a36Sopenharmony_ci	 */
2962306a36Sopenharmony_ci	local_irq_save(flags);
3062306a36Sopenharmony_ci	aes_encrypt(ctx, dst, src);
3162306a36Sopenharmony_ci	local_irq_restore(flags);
3262306a36Sopenharmony_ci}
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/**
3562306a36Sopenharmony_ci * aesgcm_expandkey - Expands the AES and GHASH keys for the AES-GCM key
3662306a36Sopenharmony_ci *		      schedule
3762306a36Sopenharmony_ci *
3862306a36Sopenharmony_ci * @ctx:	The data structure that will hold the AES-GCM key schedule
3962306a36Sopenharmony_ci * @key:	The AES encryption input key
4062306a36Sopenharmony_ci * @keysize:	The length in bytes of the input key
4162306a36Sopenharmony_ci * @authsize:	The size in bytes of the GCM authentication tag
4262306a36Sopenharmony_ci *
4362306a36Sopenharmony_ci * Returns: 0 on success, or -EINVAL if @keysize or @authsize contain values
4462306a36Sopenharmony_ci * that are not permitted by the GCM specification.
4562306a36Sopenharmony_ci */
4662306a36Sopenharmony_ciint aesgcm_expandkey(struct aesgcm_ctx *ctx, const u8 *key,
4762306a36Sopenharmony_ci		     unsigned int keysize, unsigned int authsize)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	u8 kin[AES_BLOCK_SIZE] = {};
5062306a36Sopenharmony_ci	int ret;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	ret = crypto_gcm_check_authsize(authsize) ?:
5362306a36Sopenharmony_ci	      aes_expandkey(&ctx->aes_ctx, key, keysize);
5462306a36Sopenharmony_ci	if (ret)
5562306a36Sopenharmony_ci		return ret;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	ctx->authsize = authsize;
5862306a36Sopenharmony_ci	aesgcm_encrypt_block(&ctx->aes_ctx, &ctx->ghash_key, kin);
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	return 0;
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ciEXPORT_SYMBOL(aesgcm_expandkey);
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistatic void aesgcm_ghash(be128 *ghash, const be128 *key, const void *src,
6562306a36Sopenharmony_ci			 int len)
6662306a36Sopenharmony_ci{
6762306a36Sopenharmony_ci	while (len > 0) {
6862306a36Sopenharmony_ci		crypto_xor((u8 *)ghash, src, min(len, GHASH_BLOCK_SIZE));
6962306a36Sopenharmony_ci		gf128mul_lle(ghash, key);
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci		src += GHASH_BLOCK_SIZE;
7262306a36Sopenharmony_ci		len -= GHASH_BLOCK_SIZE;
7362306a36Sopenharmony_ci	}
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistatic void aesgcm_mac(const struct aesgcm_ctx *ctx, const u8 *src, int src_len,
7762306a36Sopenharmony_ci		       const u8 *assoc, int assoc_len, __be32 *ctr, u8 *authtag)
7862306a36Sopenharmony_ci{
7962306a36Sopenharmony_ci	be128 tail = { cpu_to_be64(assoc_len * 8), cpu_to_be64(src_len * 8) };
8062306a36Sopenharmony_ci	u8 buf[AES_BLOCK_SIZE];
8162306a36Sopenharmony_ci	be128 ghash = {};
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	aesgcm_ghash(&ghash, &ctx->ghash_key, assoc, assoc_len);
8462306a36Sopenharmony_ci	aesgcm_ghash(&ghash, &ctx->ghash_key, src, src_len);
8562306a36Sopenharmony_ci	aesgcm_ghash(&ghash, &ctx->ghash_key, &tail, sizeof(tail));
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	ctr[3] = cpu_to_be32(1);
8862306a36Sopenharmony_ci	aesgcm_encrypt_block(&ctx->aes_ctx, buf, ctr);
8962306a36Sopenharmony_ci	crypto_xor_cpy(authtag, buf, (u8 *)&ghash, ctx->authsize);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	memzero_explicit(&ghash, sizeof(ghash));
9262306a36Sopenharmony_ci	memzero_explicit(buf, sizeof(buf));
9362306a36Sopenharmony_ci}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cistatic void aesgcm_crypt(const struct aesgcm_ctx *ctx, u8 *dst, const u8 *src,
9662306a36Sopenharmony_ci			 int len, __be32 *ctr)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	u8 buf[AES_BLOCK_SIZE];
9962306a36Sopenharmony_ci	unsigned int n = 2;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	while (len > 0) {
10262306a36Sopenharmony_ci		/*
10362306a36Sopenharmony_ci		 * The counter increment below must not result in overflow or
10462306a36Sopenharmony_ci		 * carry into the next 32-bit word, as this could result in
10562306a36Sopenharmony_ci		 * inadvertent IV reuse, which must be avoided at all cost for
10662306a36Sopenharmony_ci		 * stream ciphers such as AES-CTR. Given the range of 'int
10762306a36Sopenharmony_ci		 * len', this cannot happen, so no explicit test is necessary.
10862306a36Sopenharmony_ci		 */
10962306a36Sopenharmony_ci		ctr[3] = cpu_to_be32(n++);
11062306a36Sopenharmony_ci		aesgcm_encrypt_block(&ctx->aes_ctx, buf, ctr);
11162306a36Sopenharmony_ci		crypto_xor_cpy(dst, src, buf, min(len, AES_BLOCK_SIZE));
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci		dst += AES_BLOCK_SIZE;
11462306a36Sopenharmony_ci		src += AES_BLOCK_SIZE;
11562306a36Sopenharmony_ci		len -= AES_BLOCK_SIZE;
11662306a36Sopenharmony_ci	}
11762306a36Sopenharmony_ci	memzero_explicit(buf, sizeof(buf));
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci/**
12162306a36Sopenharmony_ci * aesgcm_encrypt - Perform AES-GCM encryption on a block of data
12262306a36Sopenharmony_ci *
12362306a36Sopenharmony_ci * @ctx:	The AES-GCM key schedule
12462306a36Sopenharmony_ci * @dst:	Pointer to the ciphertext output buffer
12562306a36Sopenharmony_ci * @src:	Pointer the plaintext (may equal @dst for encryption in place)
12662306a36Sopenharmony_ci * @crypt_len:	The size in bytes of the plaintext and ciphertext.
12762306a36Sopenharmony_ci * @assoc:	Pointer to the associated data,
12862306a36Sopenharmony_ci * @assoc_len:	The size in bytes of the associated data
12962306a36Sopenharmony_ci * @iv:		The initialization vector (IV) to use for this block of data
13062306a36Sopenharmony_ci *		(must be 12 bytes in size as per the GCM spec recommendation)
13162306a36Sopenharmony_ci * @authtag:	The address of the buffer in memory where the authentication
13262306a36Sopenharmony_ci *		tag should be stored. The buffer is assumed to have space for
13362306a36Sopenharmony_ci *		@ctx->authsize bytes.
13462306a36Sopenharmony_ci */
13562306a36Sopenharmony_civoid aesgcm_encrypt(const struct aesgcm_ctx *ctx, u8 *dst, const u8 *src,
13662306a36Sopenharmony_ci		    int crypt_len, const u8 *assoc, int assoc_len,
13762306a36Sopenharmony_ci		    const u8 iv[GCM_AES_IV_SIZE], u8 *authtag)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	__be32 ctr[4];
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	memcpy(ctr, iv, GCM_AES_IV_SIZE);
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	aesgcm_crypt(ctx, dst, src, crypt_len, ctr);
14462306a36Sopenharmony_ci	aesgcm_mac(ctx, dst, crypt_len, assoc, assoc_len, ctr, authtag);
14562306a36Sopenharmony_ci}
14662306a36Sopenharmony_ciEXPORT_SYMBOL(aesgcm_encrypt);
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci/**
14962306a36Sopenharmony_ci * aesgcm_decrypt - Perform AES-GCM decryption on a block of data
15062306a36Sopenharmony_ci *
15162306a36Sopenharmony_ci * @ctx:	The AES-GCM key schedule
15262306a36Sopenharmony_ci * @dst:	Pointer to the plaintext output buffer
15362306a36Sopenharmony_ci * @src:	Pointer the ciphertext (may equal @dst for decryption in place)
15462306a36Sopenharmony_ci * @crypt_len:	The size in bytes of the plaintext and ciphertext.
15562306a36Sopenharmony_ci * @assoc:	Pointer to the associated data,
15662306a36Sopenharmony_ci * @assoc_len:	The size in bytes of the associated data
15762306a36Sopenharmony_ci * @iv:		The initialization vector (IV) to use for this block of data
15862306a36Sopenharmony_ci *		(must be 12 bytes in size as per the GCM spec recommendation)
15962306a36Sopenharmony_ci * @authtag:	The address of the buffer in memory where the authentication
16062306a36Sopenharmony_ci *		tag is stored.
16162306a36Sopenharmony_ci *
16262306a36Sopenharmony_ci * Returns: true on success, or false if the ciphertext failed authentication.
16362306a36Sopenharmony_ci * On failure, no plaintext will be returned.
16462306a36Sopenharmony_ci */
16562306a36Sopenharmony_cibool __must_check aesgcm_decrypt(const struct aesgcm_ctx *ctx, u8 *dst,
16662306a36Sopenharmony_ci				 const u8 *src, int crypt_len, const u8 *assoc,
16762306a36Sopenharmony_ci				 int assoc_len, const u8 iv[GCM_AES_IV_SIZE],
16862306a36Sopenharmony_ci				 const u8 *authtag)
16962306a36Sopenharmony_ci{
17062306a36Sopenharmony_ci	u8 tagbuf[AES_BLOCK_SIZE];
17162306a36Sopenharmony_ci	__be32 ctr[4];
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	memcpy(ctr, iv, GCM_AES_IV_SIZE);
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	aesgcm_mac(ctx, src, crypt_len, assoc, assoc_len, ctr, tagbuf);
17662306a36Sopenharmony_ci	if (crypto_memneq(authtag, tagbuf, ctx->authsize)) {
17762306a36Sopenharmony_ci		memzero_explicit(tagbuf, sizeof(tagbuf));
17862306a36Sopenharmony_ci		return false;
17962306a36Sopenharmony_ci	}
18062306a36Sopenharmony_ci	aesgcm_crypt(ctx, dst, src, crypt_len, ctr);
18162306a36Sopenharmony_ci	return true;
18262306a36Sopenharmony_ci}
18362306a36Sopenharmony_ciEXPORT_SYMBOL(aesgcm_decrypt);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ciMODULE_DESCRIPTION("Generic AES-GCM library");
18662306a36Sopenharmony_ciMODULE_AUTHOR("Ard Biesheuvel <ardb@kernel.org>");
18762306a36Sopenharmony_ciMODULE_LICENSE("GPL");
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci#ifndef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci/*
19262306a36Sopenharmony_ci * Test code below. Vectors taken from crypto/testmgr.h
19362306a36Sopenharmony_ci */
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_cistatic const u8 __initconst ctext0[16] =
19662306a36Sopenharmony_ci	"\x58\xe2\xfc\xce\xfa\x7e\x30\x61"
19762306a36Sopenharmony_ci	"\x36\x7f\x1d\x57\xa4\xe7\x45\x5a";
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_cistatic const u8 __initconst ptext1[16];
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cistatic const u8 __initconst ctext1[32] =
20262306a36Sopenharmony_ci	"\x03\x88\xda\xce\x60\xb6\xa3\x92"
20362306a36Sopenharmony_ci	"\xf3\x28\xc2\xb9\x71\xb2\xfe\x78"
20462306a36Sopenharmony_ci	"\xab\x6e\x47\xd4\x2c\xec\x13\xbd"
20562306a36Sopenharmony_ci	"\xf5\x3a\x67\xb2\x12\x57\xbd\xdf";
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_cistatic const u8 __initconst ptext2[64] =
20862306a36Sopenharmony_ci	"\xd9\x31\x32\x25\xf8\x84\x06\xe5"
20962306a36Sopenharmony_ci	"\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
21062306a36Sopenharmony_ci	"\x86\xa7\xa9\x53\x15\x34\xf7\xda"
21162306a36Sopenharmony_ci	"\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
21262306a36Sopenharmony_ci	"\x1c\x3c\x0c\x95\x95\x68\x09\x53"
21362306a36Sopenharmony_ci	"\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
21462306a36Sopenharmony_ci	"\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
21562306a36Sopenharmony_ci	"\xba\x63\x7b\x39\x1a\xaf\xd2\x55";
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_cistatic const u8 __initconst ctext2[80] =
21862306a36Sopenharmony_ci	"\x42\x83\x1e\xc2\x21\x77\x74\x24"
21962306a36Sopenharmony_ci	"\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
22062306a36Sopenharmony_ci	"\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0"
22162306a36Sopenharmony_ci	"\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
22262306a36Sopenharmony_ci	"\x21\xd5\x14\xb2\x54\x66\x93\x1c"
22362306a36Sopenharmony_ci	"\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
22462306a36Sopenharmony_ci	"\x1b\xa3\x0b\x39\x6a\x0a\xac\x97"
22562306a36Sopenharmony_ci	"\x3d\x58\xe0\x91\x47\x3f\x59\x85"
22662306a36Sopenharmony_ci	"\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6"
22762306a36Sopenharmony_ci	"\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4";
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_cistatic const u8 __initconst ptext3[60] =
23062306a36Sopenharmony_ci	"\xd9\x31\x32\x25\xf8\x84\x06\xe5"
23162306a36Sopenharmony_ci	"\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
23262306a36Sopenharmony_ci	"\x86\xa7\xa9\x53\x15\x34\xf7\xda"
23362306a36Sopenharmony_ci	"\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
23462306a36Sopenharmony_ci	"\x1c\x3c\x0c\x95\x95\x68\x09\x53"
23562306a36Sopenharmony_ci	"\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
23662306a36Sopenharmony_ci	"\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
23762306a36Sopenharmony_ci	"\xba\x63\x7b\x39";
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_cistatic const u8 __initconst ctext3[76] =
24062306a36Sopenharmony_ci	"\x42\x83\x1e\xc2\x21\x77\x74\x24"
24162306a36Sopenharmony_ci	"\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
24262306a36Sopenharmony_ci	"\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0"
24362306a36Sopenharmony_ci	"\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
24462306a36Sopenharmony_ci	"\x21\xd5\x14\xb2\x54\x66\x93\x1c"
24562306a36Sopenharmony_ci	"\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
24662306a36Sopenharmony_ci	"\x1b\xa3\x0b\x39\x6a\x0a\xac\x97"
24762306a36Sopenharmony_ci	"\x3d\x58\xe0\x91"
24862306a36Sopenharmony_ci	"\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb"
24962306a36Sopenharmony_ci	"\x94\xfa\xe9\x5a\xe7\x12\x1a\x47";
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_cistatic const u8 __initconst ctext4[16] =
25262306a36Sopenharmony_ci	"\xcd\x33\xb2\x8a\xc7\x73\xf7\x4b"
25362306a36Sopenharmony_ci	"\xa0\x0e\xd1\xf3\x12\x57\x24\x35";
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_cistatic const u8 __initconst ctext5[32] =
25662306a36Sopenharmony_ci	"\x98\xe7\x24\x7c\x07\xf0\xfe\x41"
25762306a36Sopenharmony_ci	"\x1c\x26\x7e\x43\x84\xb0\xf6\x00"
25862306a36Sopenharmony_ci	"\x2f\xf5\x8d\x80\x03\x39\x27\xab"
25962306a36Sopenharmony_ci	"\x8e\xf4\xd4\x58\x75\x14\xf0\xfb";
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_cistatic const u8 __initconst ptext6[64] =
26262306a36Sopenharmony_ci	"\xd9\x31\x32\x25\xf8\x84\x06\xe5"
26362306a36Sopenharmony_ci	"\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
26462306a36Sopenharmony_ci	"\x86\xa7\xa9\x53\x15\x34\xf7\xda"
26562306a36Sopenharmony_ci	"\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
26662306a36Sopenharmony_ci	"\x1c\x3c\x0c\x95\x95\x68\x09\x53"
26762306a36Sopenharmony_ci	"\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
26862306a36Sopenharmony_ci	"\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
26962306a36Sopenharmony_ci	"\xba\x63\x7b\x39\x1a\xaf\xd2\x55";
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_cistatic const u8 __initconst ctext6[80] =
27262306a36Sopenharmony_ci	"\x39\x80\xca\x0b\x3c\x00\xe8\x41"
27362306a36Sopenharmony_ci	"\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
27462306a36Sopenharmony_ci	"\x85\x9e\x1c\xea\xa6\xef\xd9\x84"
27562306a36Sopenharmony_ci	"\x62\x85\x93\xb4\x0c\xa1\xe1\x9c"
27662306a36Sopenharmony_ci	"\x7d\x77\x3d\x00\xc1\x44\xc5\x25"
27762306a36Sopenharmony_ci	"\xac\x61\x9d\x18\xc8\x4a\x3f\x47"
27862306a36Sopenharmony_ci	"\x18\xe2\x44\x8b\x2f\xe3\x24\xd9"
27962306a36Sopenharmony_ci	"\xcc\xda\x27\x10\xac\xad\xe2\x56"
28062306a36Sopenharmony_ci	"\x99\x24\xa7\xc8\x58\x73\x36\xbf"
28162306a36Sopenharmony_ci	"\xb1\x18\x02\x4d\xb8\x67\x4a\x14";
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_cistatic const u8 __initconst ctext7[16] =
28462306a36Sopenharmony_ci	"\x53\x0f\x8a\xfb\xc7\x45\x36\xb9"
28562306a36Sopenharmony_ci	"\xa9\x63\xb4\xf1\xc4\xcb\x73\x8b";
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_cistatic const u8 __initconst ctext8[32] =
28862306a36Sopenharmony_ci	"\xce\xa7\x40\x3d\x4d\x60\x6b\x6e"
28962306a36Sopenharmony_ci	"\x07\x4e\xc5\xd3\xba\xf3\x9d\x18"
29062306a36Sopenharmony_ci	"\xd0\xd1\xc8\xa7\x99\x99\x6b\xf0"
29162306a36Sopenharmony_ci	"\x26\x5b\x98\xb5\xd4\x8a\xb9\x19";
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_cistatic const u8 __initconst ptext9[64] =
29462306a36Sopenharmony_ci	"\xd9\x31\x32\x25\xf8\x84\x06\xe5"
29562306a36Sopenharmony_ci	"\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
29662306a36Sopenharmony_ci	"\x86\xa7\xa9\x53\x15\x34\xf7\xda"
29762306a36Sopenharmony_ci	"\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
29862306a36Sopenharmony_ci	"\x1c\x3c\x0c\x95\x95\x68\x09\x53"
29962306a36Sopenharmony_ci	"\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
30062306a36Sopenharmony_ci	"\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
30162306a36Sopenharmony_ci	"\xba\x63\x7b\x39\x1a\xaf\xd2\x55";
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_cistatic const u8 __initconst ctext9[80] =
30462306a36Sopenharmony_ci	"\x52\x2d\xc1\xf0\x99\x56\x7d\x07"
30562306a36Sopenharmony_ci	"\xf4\x7f\x37\xa3\x2a\x84\x42\x7d"
30662306a36Sopenharmony_ci	"\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9"
30762306a36Sopenharmony_ci	"\x75\x98\xa2\xbd\x25\x55\xd1\xaa"
30862306a36Sopenharmony_ci	"\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d"
30962306a36Sopenharmony_ci	"\xa7\xb0\x8b\x10\x56\x82\x88\x38"
31062306a36Sopenharmony_ci	"\xc5\xf6\x1e\x63\x93\xba\x7a\x0a"
31162306a36Sopenharmony_ci	"\xbc\xc9\xf6\x62\x89\x80\x15\xad"
31262306a36Sopenharmony_ci	"\xb0\x94\xda\xc5\xd9\x34\x71\xbd"
31362306a36Sopenharmony_ci	"\xec\x1a\x50\x22\x70\xe3\xcc\x6c";
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_cistatic const u8 __initconst ptext10[60] =
31662306a36Sopenharmony_ci	"\xd9\x31\x32\x25\xf8\x84\x06\xe5"
31762306a36Sopenharmony_ci	"\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
31862306a36Sopenharmony_ci	"\x86\xa7\xa9\x53\x15\x34\xf7\xda"
31962306a36Sopenharmony_ci	"\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
32062306a36Sopenharmony_ci	"\x1c\x3c\x0c\x95\x95\x68\x09\x53"
32162306a36Sopenharmony_ci	"\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
32262306a36Sopenharmony_ci	"\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
32362306a36Sopenharmony_ci	"\xba\x63\x7b\x39";
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_cistatic const u8 __initconst ctext10[76] =
32662306a36Sopenharmony_ci	"\x52\x2d\xc1\xf0\x99\x56\x7d\x07"
32762306a36Sopenharmony_ci	"\xf4\x7f\x37\xa3\x2a\x84\x42\x7d"
32862306a36Sopenharmony_ci	"\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9"
32962306a36Sopenharmony_ci	"\x75\x98\xa2\xbd\x25\x55\xd1\xaa"
33062306a36Sopenharmony_ci	"\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d"
33162306a36Sopenharmony_ci	"\xa7\xb0\x8b\x10\x56\x82\x88\x38"
33262306a36Sopenharmony_ci	"\xc5\xf6\x1e\x63\x93\xba\x7a\x0a"
33362306a36Sopenharmony_ci	"\xbc\xc9\xf6\x62"
33462306a36Sopenharmony_ci	"\x76\xfc\x6e\xce\x0f\x4e\x17\x68"
33562306a36Sopenharmony_ci	"\xcd\xdf\x88\x53\xbb\x2d\x55\x1b";
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_cistatic const u8 __initconst ptext11[60] =
33862306a36Sopenharmony_ci	"\xd9\x31\x32\x25\xf8\x84\x06\xe5"
33962306a36Sopenharmony_ci	"\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
34062306a36Sopenharmony_ci	"\x86\xa7\xa9\x53\x15\x34\xf7\xda"
34162306a36Sopenharmony_ci	"\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
34262306a36Sopenharmony_ci	"\x1c\x3c\x0c\x95\x95\x68\x09\x53"
34362306a36Sopenharmony_ci	"\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
34462306a36Sopenharmony_ci	"\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
34562306a36Sopenharmony_ci	"\xba\x63\x7b\x39";
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_cistatic const u8 __initconst ctext11[76] =
34862306a36Sopenharmony_ci	"\x39\x80\xca\x0b\x3c\x00\xe8\x41"
34962306a36Sopenharmony_ci	"\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
35062306a36Sopenharmony_ci	"\x85\x9e\x1c\xea\xa6\xef\xd9\x84"
35162306a36Sopenharmony_ci	"\x62\x85\x93\xb4\x0c\xa1\xe1\x9c"
35262306a36Sopenharmony_ci	"\x7d\x77\x3d\x00\xc1\x44\xc5\x25"
35362306a36Sopenharmony_ci	"\xac\x61\x9d\x18\xc8\x4a\x3f\x47"
35462306a36Sopenharmony_ci	"\x18\xe2\x44\x8b\x2f\xe3\x24\xd9"
35562306a36Sopenharmony_ci	"\xcc\xda\x27\x10"
35662306a36Sopenharmony_ci	"\x25\x19\x49\x8e\x80\xf1\x47\x8f"
35762306a36Sopenharmony_ci	"\x37\xba\x55\xbd\x6d\x27\x61\x8c";
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_cistatic const u8 __initconst ptext12[719] =
36062306a36Sopenharmony_ci	"\x42\xc1\xcc\x08\x48\x6f\x41\x3f"
36162306a36Sopenharmony_ci	"\x2f\x11\x66\x8b\x2a\x16\xf0\xe0"
36262306a36Sopenharmony_ci	"\x58\x83\xf0\xc3\x70\x14\xc0\x5b"
36362306a36Sopenharmony_ci	"\x3f\xec\x1d\x25\x3c\x51\xd2\x03"
36462306a36Sopenharmony_ci	"\xcf\x59\x74\x1f\xb2\x85\xb4\x07"
36562306a36Sopenharmony_ci	"\xc6\x6a\x63\x39\x8a\x5b\xde\xcb"
36662306a36Sopenharmony_ci	"\xaf\x08\x44\xbd\x6f\x91\x15\xe1"
36762306a36Sopenharmony_ci	"\xf5\x7a\x6e\x18\xbd\xdd\x61\x50"
36862306a36Sopenharmony_ci	"\x59\xa9\x97\xab\xbb\x0e\x74\x5c"
36962306a36Sopenharmony_ci	"\x00\xa4\x43\x54\x04\x54\x9b\x3b"
37062306a36Sopenharmony_ci	"\x77\xec\xfd\x5c\xa6\xe8\x7b\x08"
37162306a36Sopenharmony_ci	"\xae\xe6\x10\x3f\x32\x65\xd1\xfc"
37262306a36Sopenharmony_ci	"\xa4\x1d\x2c\x31\xfb\x33\x7a\xb3"
37362306a36Sopenharmony_ci	"\x35\x23\xf4\x20\x41\xd4\xad\x82"
37462306a36Sopenharmony_ci	"\x8b\xa4\xad\x96\x1c\x20\x53\xbe"
37562306a36Sopenharmony_ci	"\x0e\xa6\xf4\xdc\x78\x49\x3e\x72"
37662306a36Sopenharmony_ci	"\xb1\xa9\xb5\x83\xcb\x08\x54\xb7"
37762306a36Sopenharmony_ci	"\xad\x49\x3a\xae\x98\xce\xa6\x66"
37862306a36Sopenharmony_ci	"\x10\x30\x90\x8c\x55\x83\xd7\x7c"
37962306a36Sopenharmony_ci	"\x8b\xe6\x53\xde\xd2\x6e\x18\x21"
38062306a36Sopenharmony_ci	"\x01\x52\xd1\x9f\x9d\xbb\x9c\x73"
38162306a36Sopenharmony_ci	"\x57\xcc\x89\x09\x75\x9b\x78\x70"
38262306a36Sopenharmony_ci	"\xed\x26\x97\x4d\xb4\xe4\x0c\xa5"
38362306a36Sopenharmony_ci	"\xfa\x70\x04\x70\xc6\x96\x1c\x7d"
38462306a36Sopenharmony_ci	"\x54\x41\x77\xa8\xe3\xb0\x7e\x96"
38562306a36Sopenharmony_ci	"\x82\xd9\xec\xa2\x87\x68\x55\xf9"
38662306a36Sopenharmony_ci	"\x8f\x9e\x73\x43\x47\x6a\x08\x36"
38762306a36Sopenharmony_ci	"\x93\x67\xa8\x2d\xde\xac\x41\xa9"
38862306a36Sopenharmony_ci	"\x5c\x4d\x73\x97\x0f\x70\x68\xfa"
38962306a36Sopenharmony_ci	"\x56\x4d\x00\xc2\x3b\x1f\xc8\xb9"
39062306a36Sopenharmony_ci	"\x78\x1f\x51\x07\xe3\x9a\x13\x4e"
39162306a36Sopenharmony_ci	"\xed\x2b\x2e\xa3\xf7\x44\xb2\xe7"
39262306a36Sopenharmony_ci	"\xab\x19\x37\xd9\xba\x76\x5e\xd2"
39362306a36Sopenharmony_ci	"\xf2\x53\x15\x17\x4c\x6b\x16\x9f"
39462306a36Sopenharmony_ci	"\x02\x66\x49\xca\x7c\x91\x05\xf2"
39562306a36Sopenharmony_ci	"\x45\x36\x1e\xf5\x77\xad\x1f\x46"
39662306a36Sopenharmony_ci	"\xa8\x13\xfb\x63\xb6\x08\x99\x63"
39762306a36Sopenharmony_ci	"\x82\xa2\xed\xb3\xac\xdf\x43\x19"
39862306a36Sopenharmony_ci	"\x45\xea\x78\x73\xd9\xb7\x39\x11"
39962306a36Sopenharmony_ci	"\xa3\x13\x7c\xf8\x3f\xf7\xad\x81"
40062306a36Sopenharmony_ci	"\x48\x2f\xa9\x5c\x5f\xa0\xf0\x79"
40162306a36Sopenharmony_ci	"\xa4\x47\x7d\x80\x20\x26\xfd\x63"
40262306a36Sopenharmony_ci	"\x0a\xc7\x7e\x6d\x75\x47\xff\x76"
40362306a36Sopenharmony_ci	"\x66\x2e\x8a\x6c\x81\x35\xaf\x0b"
40462306a36Sopenharmony_ci	"\x2e\x6a\x49\x60\xc1\x10\xe1\xe1"
40562306a36Sopenharmony_ci	"\x54\x03\xa4\x09\x0c\x37\x7a\x15"
40662306a36Sopenharmony_ci	"\x23\x27\x5b\x8b\x4b\xa5\x64\x97"
40762306a36Sopenharmony_ci	"\xae\x4a\x50\x73\x1f\x66\x1c\x5c"
40862306a36Sopenharmony_ci	"\x03\x25\x3c\x8d\x48\x58\x71\x34"
40962306a36Sopenharmony_ci	"\x0e\xec\x4e\x55\x1a\x03\x6a\xe5"
41062306a36Sopenharmony_ci	"\xb6\x19\x2b\x84\x2a\x20\xd1\xea"
41162306a36Sopenharmony_ci	"\x80\x6f\x96\x0e\x05\x62\xc7\x78"
41262306a36Sopenharmony_ci	"\x87\x79\x60\x38\x46\xb4\x25\x57"
41362306a36Sopenharmony_ci	"\x6e\x16\x63\xf8\xad\x6e\xd7\x42"
41462306a36Sopenharmony_ci	"\x69\xe1\x88\xef\x6e\xd5\xb4\x9a"
41562306a36Sopenharmony_ci	"\x3c\x78\x6c\x3b\xe5\xa0\x1d\x22"
41662306a36Sopenharmony_ci	"\x86\x5c\x74\x3a\xeb\x24\x26\xc7"
41762306a36Sopenharmony_ci	"\x09\xfc\x91\x96\x47\x87\x4f\x1a"
41862306a36Sopenharmony_ci	"\xd6\x6b\x2c\x18\x47\xc0\xb8\x24"
41962306a36Sopenharmony_ci	"\xa8\x5a\x4a\x9e\xcb\x03\xe7\x2a"
42062306a36Sopenharmony_ci	"\x09\xe6\x4d\x9c\x6d\x86\x60\xf5"
42162306a36Sopenharmony_ci	"\x2f\x48\x69\x37\x9f\xf2\xd2\xcb"
42262306a36Sopenharmony_ci	"\x0e\x5a\xdd\x6e\x8a\xfb\x6a\xfe"
42362306a36Sopenharmony_ci	"\x0b\x63\xde\x87\x42\x79\x8a\x68"
42462306a36Sopenharmony_ci	"\x51\x28\x9b\x7a\xeb\xaf\xb8\x2f"
42562306a36Sopenharmony_ci	"\x9d\xd1\xc7\x45\x90\x08\xc9\x83"
42662306a36Sopenharmony_ci	"\xe9\x83\x84\xcb\x28\x69\x09\x69"
42762306a36Sopenharmony_ci	"\xce\x99\x46\x00\x54\xcb\xd8\x38"
42862306a36Sopenharmony_ci	"\xf9\x53\x4a\xbf\x31\xce\x57\x15"
42962306a36Sopenharmony_ci	"\x33\xfa\x96\x04\x33\x42\xe3\xc0"
43062306a36Sopenharmony_ci	"\xb7\x54\x4a\x65\x7a\x7c\x02\xe6"
43162306a36Sopenharmony_ci	"\x19\x95\xd0\x0e\x82\x07\x63\xf9"
43262306a36Sopenharmony_ci	"\xe1\x2b\x2a\xfc\x55\x92\x52\xc9"
43362306a36Sopenharmony_ci	"\xb5\x9f\x23\x28\x60\xe7\x20\x51"
43462306a36Sopenharmony_ci	"\x10\xd3\xed\x6d\x9b\xab\xb8\xe2"
43562306a36Sopenharmony_ci	"\x5d\x9a\x34\xb3\xbe\x9c\x64\xcb"
43662306a36Sopenharmony_ci	"\x78\xc6\x91\x22\x40\x91\x80\xbe"
43762306a36Sopenharmony_ci	"\xd7\x78\x5c\x0e\x0a\xdc\x08\xe9"
43862306a36Sopenharmony_ci	"\x67\x10\xa4\x83\x98\x79\x23\xe7"
43962306a36Sopenharmony_ci	"\x92\xda\xa9\x22\x16\xb1\xe7\x78"
44062306a36Sopenharmony_ci	"\xa3\x1c\x6c\x8f\x35\x7c\x4d\x37"
44162306a36Sopenharmony_ci	"\x2f\x6e\x0b\x50\x5c\x34\xb9\xf9"
44262306a36Sopenharmony_ci	"\xe6\x3d\x91\x0d\x32\x95\xaa\x3d"
44362306a36Sopenharmony_ci	"\x48\x11\x06\xbb\x2d\xf2\x63\x88"
44462306a36Sopenharmony_ci	"\x3f\x73\x09\xe2\x45\x56\x31\x51"
44562306a36Sopenharmony_ci	"\xfa\x5e\x4e\x62\xf7\x90\xf9\xa9"
44662306a36Sopenharmony_ci	"\x7d\x7b\x1b\xb1\xc8\x26\x6e\x66"
44762306a36Sopenharmony_ci	"\xf6\x90\x9a\x7f\xf2\x57\xcc\x23"
44862306a36Sopenharmony_ci	"\x59\xfa\xfa\xaa\x44\x04\x01\xa7"
44962306a36Sopenharmony_ci	"\xa4\x78\xdb\x74\x3d\x8b\xb5";
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_cistatic const u8 __initconst ctext12[735] =
45262306a36Sopenharmony_ci	"\x84\x0b\xdb\xd5\xb7\xa8\xfe\x20"
45362306a36Sopenharmony_ci	"\xbb\xb1\x12\x7f\x41\xea\xb3\xc0"
45462306a36Sopenharmony_ci	"\xa2\xb4\x37\x19\x11\x58\xb6\x0b"
45562306a36Sopenharmony_ci	"\x4c\x1d\x38\x05\x54\xd1\x16\x73"
45662306a36Sopenharmony_ci	"\x8e\x1c\x20\x90\xa2\x9a\xb7\x74"
45762306a36Sopenharmony_ci	"\x47\xe6\xd8\xfc\x18\x3a\xb4\xea"
45862306a36Sopenharmony_ci	"\xd5\x16\x5a\x2c\x53\x01\x46\xb3"
45962306a36Sopenharmony_ci	"\x18\x33\x74\x6c\x50\xf2\xe8\xc0"
46062306a36Sopenharmony_ci	"\x73\xda\x60\x22\xeb\xe3\xe5\x9b"
46162306a36Sopenharmony_ci	"\x20\x93\x6c\x4b\x37\x99\xb8\x23"
46262306a36Sopenharmony_ci	"\x3b\x4e\xac\xe8\x5b\xe8\x0f\xb7"
46362306a36Sopenharmony_ci	"\xc3\x8f\xfb\x4a\x37\xd9\x39\x95"
46462306a36Sopenharmony_ci	"\x34\xf1\xdb\x8f\x71\xd9\xc7\x0b"
46562306a36Sopenharmony_ci	"\x02\xf1\x63\xfc\x9b\xfc\xc5\xab"
46662306a36Sopenharmony_ci	"\xb9\x14\x13\x21\xdf\xce\xaa\x88"
46762306a36Sopenharmony_ci	"\x44\x30\x1e\xce\x26\x01\x92\xf8"
46862306a36Sopenharmony_ci	"\x9f\x00\x4b\x0c\x4b\xf7\x5f\xe0"
46962306a36Sopenharmony_ci	"\x89\xca\x94\x66\x11\x21\x97\xca"
47062306a36Sopenharmony_ci	"\x3e\x83\x74\x2d\xdb\x4d\x11\xeb"
47162306a36Sopenharmony_ci	"\x97\xc2\x14\xff\x9e\x1e\xa0\x6b"
47262306a36Sopenharmony_ci	"\x08\xb4\x31\x2b\x85\xc6\x85\x6c"
47362306a36Sopenharmony_ci	"\x90\xec\x39\xc0\xec\xb3\xb5\x4e"
47462306a36Sopenharmony_ci	"\xf3\x9c\xe7\x83\x3a\x77\x0a\xf4"
47562306a36Sopenharmony_ci	"\x56\xfe\xce\x18\x33\x6d\x0b\x2d"
47662306a36Sopenharmony_ci	"\x33\xda\xc8\x05\x5c\xb4\x09\x2a"
47762306a36Sopenharmony_ci	"\xde\x6b\x52\x98\x01\xef\x36\x3d"
47862306a36Sopenharmony_ci	"\xbd\xf9\x8f\xa8\x3e\xaa\xcd\xd1"
47962306a36Sopenharmony_ci	"\x01\x2d\x42\x49\xc3\xb6\x84\xbb"
48062306a36Sopenharmony_ci	"\x48\x96\xe0\x90\x93\x6c\x48\x64"
48162306a36Sopenharmony_ci	"\xd4\xfa\x7f\x93\x2c\xa6\x21\xc8"
48262306a36Sopenharmony_ci	"\x7a\x23\x7b\xaa\x20\x56\x12\xae"
48362306a36Sopenharmony_ci	"\x16\x9d\x94\x0f\x54\xa1\xec\xca"
48462306a36Sopenharmony_ci	"\x51\x4e\xf2\x39\xf4\xf8\x5f\x04"
48562306a36Sopenharmony_ci	"\x5a\x0d\xbf\xf5\x83\xa1\x15\xe1"
48662306a36Sopenharmony_ci	"\xf5\x3c\xd8\x62\xa3\xed\x47\x89"
48762306a36Sopenharmony_ci	"\x85\x4c\xe5\xdb\xac\x9e\x17\x1d"
48862306a36Sopenharmony_ci	"\x0c\x09\xe3\x3e\x39\x5b\x4d\x74"
48962306a36Sopenharmony_ci	"\x0e\xf5\x34\xee\x70\x11\x4c\xfd"
49062306a36Sopenharmony_ci	"\xdb\x34\xb1\xb5\x10\x3f\x73\xb7"
49162306a36Sopenharmony_ci	"\xf5\xfa\xed\xb0\x1f\xa5\xcd\x3c"
49262306a36Sopenharmony_ci	"\x8d\x35\x83\xd4\x11\x44\x6e\x6c"
49362306a36Sopenharmony_ci	"\x5b\xe0\x0e\x69\xa5\x39\xe5\xbb"
49462306a36Sopenharmony_ci	"\xa9\x57\x24\x37\xe6\x1f\xdd\xcf"
49562306a36Sopenharmony_ci	"\x16\x2a\x13\xf9\x6a\x2d\x90\xa0"
49662306a36Sopenharmony_ci	"\x03\x60\x7a\xed\x69\xd5\x00\x8b"
49762306a36Sopenharmony_ci	"\x7e\x4f\xcb\xb9\xfa\x91\xb9\x37"
49862306a36Sopenharmony_ci	"\xc1\x26\xce\x90\x97\x22\x64\x64"
49962306a36Sopenharmony_ci	"\xc1\x72\x43\x1b\xf6\xac\xc1\x54"
50062306a36Sopenharmony_ci	"\x8a\x10\x9c\xdd\x8d\xd5\x8e\xb2"
50162306a36Sopenharmony_ci	"\xe4\x85\xda\xe0\x20\x5f\xf4\xb4"
50262306a36Sopenharmony_ci	"\x15\xb5\xa0\x8d\x12\x74\x49\x23"
50362306a36Sopenharmony_ci	"\x3a\xdf\x4a\xd3\xf0\x3b\x89\xeb"
50462306a36Sopenharmony_ci	"\xf8\xcc\x62\x7b\xfb\x93\x07\x41"
50562306a36Sopenharmony_ci	"\x61\x26\x94\x58\x70\xa6\x3c\xe4"
50662306a36Sopenharmony_ci	"\xff\x58\xc4\x13\x3d\xcb\x36\x6b"
50762306a36Sopenharmony_ci	"\x32\xe5\xb2\x6d\x03\x74\x6f\x76"
50862306a36Sopenharmony_ci	"\x93\x77\xde\x48\xc4\xfa\x30\x4a"
50962306a36Sopenharmony_ci	"\xda\x49\x80\x77\x0f\x1c\xbe\x11"
51062306a36Sopenharmony_ci	"\xc8\x48\xb1\xe5\xbb\xf2\x8a\xe1"
51162306a36Sopenharmony_ci	"\x96\x2f\x9f\xd1\x8e\x8a\x5c\xe2"
51262306a36Sopenharmony_ci	"\xf7\xd7\xd8\x54\xf3\x3f\xc4\x91"
51362306a36Sopenharmony_ci	"\xb8\xfb\x86\xdc\x46\x24\x91\x60"
51462306a36Sopenharmony_ci	"\x6c\x2f\xc9\x41\x37\x51\x49\x54"
51562306a36Sopenharmony_ci	"\x09\x81\x21\xf3\x03\x9f\x2b\xe3"
51662306a36Sopenharmony_ci	"\x1f\x39\x63\xaf\xf4\xd7\x53\x60"
51762306a36Sopenharmony_ci	"\xa7\xc7\x54\xf9\xee\xb1\xb1\x7d"
51862306a36Sopenharmony_ci	"\x75\x54\x65\x93\xfe\xb1\x68\x6b"
51962306a36Sopenharmony_ci	"\x57\x02\xf9\xbb\x0e\xf9\xf8\xbf"
52062306a36Sopenharmony_ci	"\x01\x12\x27\xb4\xfe\xe4\x79\x7a"
52162306a36Sopenharmony_ci	"\x40\x5b\x51\x4b\xdf\x38\xec\xb1"
52262306a36Sopenharmony_ci	"\x6a\x56\xff\x35\x4d\x42\x33\xaa"
52362306a36Sopenharmony_ci	"\x6f\x1b\xe4\xdc\xe0\xdb\x85\x35"
52462306a36Sopenharmony_ci	"\x62\x10\xd4\xec\xeb\xc5\x7e\x45"
52562306a36Sopenharmony_ci	"\x1c\x6f\x17\xca\x3b\x8e\x2d\x66"
52662306a36Sopenharmony_ci	"\x4f\x4b\x36\x56\xcd\x1b\x59\xaa"
52762306a36Sopenharmony_ci	"\xd2\x9b\x17\xb9\x58\xdf\x7b\x64"
52862306a36Sopenharmony_ci	"\x8a\xff\x3b\x9c\xa6\xb5\x48\x9e"
52962306a36Sopenharmony_ci	"\xaa\xe2\x5d\x09\x71\x32\x5f\xb6"
53062306a36Sopenharmony_ci	"\x29\xbe\xe7\xc7\x52\x7e\x91\x82"
53162306a36Sopenharmony_ci	"\x6b\x6d\x33\xe1\x34\x06\x36\x21"
53262306a36Sopenharmony_ci	"\x5e\xbe\x1e\x2f\x3e\xc1\xfb\xea"
53362306a36Sopenharmony_ci	"\x49\x2c\xb5\xca\xf7\xb0\x37\xea"
53462306a36Sopenharmony_ci	"\x1f\xed\x10\x04\xd9\x48\x0d\x1a"
53562306a36Sopenharmony_ci	"\x1c\xfb\xe7\x84\x0e\x83\x53\x74"
53662306a36Sopenharmony_ci	"\xc7\x65\xe2\x5c\xe5\xba\x73\x4c"
53762306a36Sopenharmony_ci	"\x0e\xe1\xb5\x11\x45\x61\x43\x46"
53862306a36Sopenharmony_ci	"\xaa\x25\x8f\xbd\x85\x08\xfa\x4c"
53962306a36Sopenharmony_ci	"\x15\xc1\xc0\xd8\xf5\xdc\x16\xbb"
54062306a36Sopenharmony_ci	"\x7b\x1d\xe3\x87\x57\xa7\x2a\x1d"
54162306a36Sopenharmony_ci	"\x38\x58\x9e\x8a\x43\xdc\x57"
54262306a36Sopenharmony_ci	"\xd1\x81\x7d\x2b\xe9\xff\x99\x3a"
54362306a36Sopenharmony_ci	"\x4b\x24\x52\x58\x55\xe1\x49\x14";
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_cistatic struct {
54662306a36Sopenharmony_ci	const u8	*ptext;
54762306a36Sopenharmony_ci	const u8	*ctext;
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	u8		key[AES_MAX_KEY_SIZE];
55062306a36Sopenharmony_ci	u8		iv[GCM_AES_IV_SIZE];
55162306a36Sopenharmony_ci	u8		assoc[20];
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	int		klen;
55462306a36Sopenharmony_ci	int		clen;
55562306a36Sopenharmony_ci	int		plen;
55662306a36Sopenharmony_ci	int		alen;
55762306a36Sopenharmony_ci} const aesgcm_tv[] __initconst = {
55862306a36Sopenharmony_ci	{ /* From McGrew & Viega - http://citeseer.ist.psu.edu/656989.html */
55962306a36Sopenharmony_ci		.klen	= 16,
56062306a36Sopenharmony_ci		.ctext	= ctext0,
56162306a36Sopenharmony_ci		.clen	= sizeof(ctext0),
56262306a36Sopenharmony_ci	}, {
56362306a36Sopenharmony_ci		.klen	= 16,
56462306a36Sopenharmony_ci		.ptext	= ptext1,
56562306a36Sopenharmony_ci		.plen	= sizeof(ptext1),
56662306a36Sopenharmony_ci		.ctext	= ctext1,
56762306a36Sopenharmony_ci		.clen	= sizeof(ctext1),
56862306a36Sopenharmony_ci	}, {
56962306a36Sopenharmony_ci		.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
57062306a36Sopenharmony_ci			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
57162306a36Sopenharmony_ci		.klen	= 16,
57262306a36Sopenharmony_ci		.iv	= "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
57362306a36Sopenharmony_ci			  "\xde\xca\xf8\x88",
57462306a36Sopenharmony_ci		.ptext	= ptext2,
57562306a36Sopenharmony_ci		.plen	= sizeof(ptext2),
57662306a36Sopenharmony_ci		.ctext	= ctext2,
57762306a36Sopenharmony_ci		.clen	= sizeof(ctext2),
57862306a36Sopenharmony_ci	}, {
57962306a36Sopenharmony_ci		.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
58062306a36Sopenharmony_ci			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
58162306a36Sopenharmony_ci		.klen	= 16,
58262306a36Sopenharmony_ci		.iv	= "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
58362306a36Sopenharmony_ci			  "\xde\xca\xf8\x88",
58462306a36Sopenharmony_ci		.ptext	= ptext3,
58562306a36Sopenharmony_ci		.plen	= sizeof(ptext3),
58662306a36Sopenharmony_ci		.assoc	= "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
58762306a36Sopenharmony_ci			  "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
58862306a36Sopenharmony_ci			  "\xab\xad\xda\xd2",
58962306a36Sopenharmony_ci		.alen	= 20,
59062306a36Sopenharmony_ci		.ctext	= ctext3,
59162306a36Sopenharmony_ci		.clen	= sizeof(ctext3),
59262306a36Sopenharmony_ci	}, {
59362306a36Sopenharmony_ci		.klen	= 24,
59462306a36Sopenharmony_ci		.ctext	= ctext4,
59562306a36Sopenharmony_ci		.clen	= sizeof(ctext4),
59662306a36Sopenharmony_ci	}, {
59762306a36Sopenharmony_ci		.klen	= 24,
59862306a36Sopenharmony_ci		.ptext	= ptext1,
59962306a36Sopenharmony_ci		.plen	= sizeof(ptext1),
60062306a36Sopenharmony_ci		.ctext	= ctext5,
60162306a36Sopenharmony_ci		.clen	= sizeof(ctext5),
60262306a36Sopenharmony_ci	}, {
60362306a36Sopenharmony_ci		.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
60462306a36Sopenharmony_ci			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
60562306a36Sopenharmony_ci			  "\xfe\xff\xe9\x92\x86\x65\x73\x1c",
60662306a36Sopenharmony_ci		.klen	= 24,
60762306a36Sopenharmony_ci		.iv	= "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
60862306a36Sopenharmony_ci			  "\xde\xca\xf8\x88",
60962306a36Sopenharmony_ci		.ptext	= ptext6,
61062306a36Sopenharmony_ci		.plen	= sizeof(ptext6),
61162306a36Sopenharmony_ci		.ctext	= ctext6,
61262306a36Sopenharmony_ci		.clen	= sizeof(ctext6),
61362306a36Sopenharmony_ci	}, {
61462306a36Sopenharmony_ci		.klen	= 32,
61562306a36Sopenharmony_ci		.ctext	= ctext7,
61662306a36Sopenharmony_ci		.clen	= sizeof(ctext7),
61762306a36Sopenharmony_ci	}, {
61862306a36Sopenharmony_ci		.klen	= 32,
61962306a36Sopenharmony_ci		.ptext	= ptext1,
62062306a36Sopenharmony_ci		.plen	= sizeof(ptext1),
62162306a36Sopenharmony_ci		.ctext	= ctext8,
62262306a36Sopenharmony_ci		.clen	= sizeof(ctext8),
62362306a36Sopenharmony_ci	}, {
62462306a36Sopenharmony_ci		.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
62562306a36Sopenharmony_ci			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
62662306a36Sopenharmony_ci			  "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
62762306a36Sopenharmony_ci			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
62862306a36Sopenharmony_ci		.klen	= 32,
62962306a36Sopenharmony_ci		.iv	= "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
63062306a36Sopenharmony_ci			  "\xde\xca\xf8\x88",
63162306a36Sopenharmony_ci		.ptext	= ptext9,
63262306a36Sopenharmony_ci		.plen	= sizeof(ptext9),
63362306a36Sopenharmony_ci		.ctext	= ctext9,
63462306a36Sopenharmony_ci		.clen	= sizeof(ctext9),
63562306a36Sopenharmony_ci	}, {
63662306a36Sopenharmony_ci		.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
63762306a36Sopenharmony_ci			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
63862306a36Sopenharmony_ci			  "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
63962306a36Sopenharmony_ci			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
64062306a36Sopenharmony_ci		.klen	= 32,
64162306a36Sopenharmony_ci		.iv	= "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
64262306a36Sopenharmony_ci			  "\xde\xca\xf8\x88",
64362306a36Sopenharmony_ci		.ptext	= ptext10,
64462306a36Sopenharmony_ci		.plen	= sizeof(ptext10),
64562306a36Sopenharmony_ci		.assoc	= "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
64662306a36Sopenharmony_ci			  "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
64762306a36Sopenharmony_ci			  "\xab\xad\xda\xd2",
64862306a36Sopenharmony_ci		.alen	= 20,
64962306a36Sopenharmony_ci		.ctext	= ctext10,
65062306a36Sopenharmony_ci		.clen	= sizeof(ctext10),
65162306a36Sopenharmony_ci	}, {
65262306a36Sopenharmony_ci		.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
65362306a36Sopenharmony_ci			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
65462306a36Sopenharmony_ci			  "\xfe\xff\xe9\x92\x86\x65\x73\x1c",
65562306a36Sopenharmony_ci		.klen	= 24,
65662306a36Sopenharmony_ci		.iv	= "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
65762306a36Sopenharmony_ci			  "\xde\xca\xf8\x88",
65862306a36Sopenharmony_ci		.ptext	= ptext11,
65962306a36Sopenharmony_ci		.plen	= sizeof(ptext11),
66062306a36Sopenharmony_ci		.assoc	= "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
66162306a36Sopenharmony_ci			  "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
66262306a36Sopenharmony_ci			  "\xab\xad\xda\xd2",
66362306a36Sopenharmony_ci		.alen	= 20,
66462306a36Sopenharmony_ci		.ctext	= ctext11,
66562306a36Sopenharmony_ci		.clen	= sizeof(ctext11),
66662306a36Sopenharmony_ci	}, {
66762306a36Sopenharmony_ci		.key	= "\x62\x35\xf8\x95\xfc\xa5\xeb\xf6"
66862306a36Sopenharmony_ci			  "\x0e\x92\x12\x04\xd3\xa1\x3f\x2e"
66962306a36Sopenharmony_ci			  "\x8b\x32\xcf\xe7\x44\xed\x13\x59"
67062306a36Sopenharmony_ci			  "\x04\x38\x77\xb0\xb9\xad\xb4\x38",
67162306a36Sopenharmony_ci		.klen	= 32,
67262306a36Sopenharmony_ci		.iv	= "\x00\xff\xff\xff\xff\x00\x00\xff"
67362306a36Sopenharmony_ci			  "\xff\xff\x00\xff",
67462306a36Sopenharmony_ci		.ptext	= ptext12,
67562306a36Sopenharmony_ci		.plen	= sizeof(ptext12),
67662306a36Sopenharmony_ci		.ctext	= ctext12,
67762306a36Sopenharmony_ci		.clen	= sizeof(ctext12),
67862306a36Sopenharmony_ci	}
67962306a36Sopenharmony_ci};
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_cistatic int __init libaesgcm_init(void)
68262306a36Sopenharmony_ci{
68362306a36Sopenharmony_ci	for (int i = 0; i < ARRAY_SIZE(aesgcm_tv); i++) {
68462306a36Sopenharmony_ci		u8 tagbuf[AES_BLOCK_SIZE];
68562306a36Sopenharmony_ci		int plen = aesgcm_tv[i].plen;
68662306a36Sopenharmony_ci		struct aesgcm_ctx ctx;
68762306a36Sopenharmony_ci		u8 buf[sizeof(ptext12)];
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci		if (aesgcm_expandkey(&ctx, aesgcm_tv[i].key, aesgcm_tv[i].klen,
69062306a36Sopenharmony_ci				     aesgcm_tv[i].clen - plen)) {
69162306a36Sopenharmony_ci			pr_err("aesgcm_expandkey() failed on vector %d\n", i);
69262306a36Sopenharmony_ci			return -ENODEV;
69362306a36Sopenharmony_ci		}
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci		if (!aesgcm_decrypt(&ctx, buf, aesgcm_tv[i].ctext, plen,
69662306a36Sopenharmony_ci				    aesgcm_tv[i].assoc, aesgcm_tv[i].alen,
69762306a36Sopenharmony_ci				    aesgcm_tv[i].iv, aesgcm_tv[i].ctext + plen)
69862306a36Sopenharmony_ci		    || memcmp(buf, aesgcm_tv[i].ptext, plen)) {
69962306a36Sopenharmony_ci			pr_err("aesgcm_decrypt() #1 failed on vector %d\n", i);
70062306a36Sopenharmony_ci			return -ENODEV;
70162306a36Sopenharmony_ci		}
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci		/* encrypt in place */
70462306a36Sopenharmony_ci		aesgcm_encrypt(&ctx, buf, buf, plen, aesgcm_tv[i].assoc,
70562306a36Sopenharmony_ci			       aesgcm_tv[i].alen, aesgcm_tv[i].iv, tagbuf);
70662306a36Sopenharmony_ci		if (memcmp(buf, aesgcm_tv[i].ctext, plen)) {
70762306a36Sopenharmony_ci			pr_err("aesgcm_encrypt() failed on vector %d\n", i);
70862306a36Sopenharmony_ci			return -ENODEV;
70962306a36Sopenharmony_ci		}
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci		/* decrypt in place */
71262306a36Sopenharmony_ci		if (!aesgcm_decrypt(&ctx, buf, buf, plen, aesgcm_tv[i].assoc,
71362306a36Sopenharmony_ci				    aesgcm_tv[i].alen, aesgcm_tv[i].iv, tagbuf)
71462306a36Sopenharmony_ci		    || memcmp(buf, aesgcm_tv[i].ptext, plen)) {
71562306a36Sopenharmony_ci			pr_err("aesgcm_decrypt() #2 failed on vector %d\n", i);
71662306a36Sopenharmony_ci			return -ENODEV;
71762306a36Sopenharmony_ci		}
71862306a36Sopenharmony_ci	}
71962306a36Sopenharmony_ci	return 0;
72062306a36Sopenharmony_ci}
72162306a36Sopenharmony_cimodule_init(libaesgcm_init);
72262306a36Sopenharmony_ci
72362306a36Sopenharmony_cistatic void __exit libaesgcm_exit(void)
72462306a36Sopenharmony_ci{
72562306a36Sopenharmony_ci}
72662306a36Sopenharmony_cimodule_exit(libaesgcm_exit);
72762306a36Sopenharmony_ci#endif
728