esp-idf/components/mbedtls/test_apps/main/test_aes.c
Mahavir Jain f7a01d8f90
aes: fix DMA descriptor calculation for the alignment case
The number of the DMA descriptors allocated for certain length (e.g.,
8176) were not sufficient (off by 1 error). This used to result in the
dynamic memory corruption as the region was modified beyond the
allocated range.

This change fixes the DMA descriptor calculation part and allocates
sufficient DMA descriptors based on the data length alignment considerations.

Test has also been added to cover the specific scenario in the CI.

Closes https://github.com/espressif/esp-idf/issues/11310
2023-05-31 14:19:58 +05:30

1589 lines
62 KiB
C

/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* mbedTLS AES test
*/
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <esp_system.h>
#include "mbedtls/aes.h"
#include "mbedtls/gcm.h"
#include "unity.h"
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "esp_heap_caps.h"
#include "test_utils.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_memory_utils.h"
#include "soc/lldesc.h"
static const uint8_t key_256[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
};
static const uint8_t iv[] = {
0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09,
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
};
/* Cipher produced via this Python:
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
def as_c_array(byte_arr):
hex_str = ''
for idx, byte in enumerate(byte_arr):
hex_str += "0x{:02x}, ".format(byte)
bytes_per_line = 8
if idx % bytes_per_line == bytes_per_line - 1:
hex_str += '\n'
return hex_str
key = bytearray(range(32))
iv = bytearray(range(16, 0, -1))
print("Key: \n{}".format(as_c_array(key)))
print("IV: \n{}".format(as_c_array(iv)))
# Replace CTR with desired mode
cipher = Cipher(algorithms.AES(key), modes.CTR(iv), backend=default_backend())
encryptor = cipher.encryptor()
input_len = 1000
plain = b'\x3A'*input_len
print(as_c_array(plain))
ct = encryptor.update(plain) + encryptor.finalize()
print("Chipertext: {}".format(as_c_array(ct)))
*/
TEST_CASE("mbedtls CBC AES-256 test", "[aes]")
{
const unsigned SZ = 1600;
mbedtls_aes_context ctx;
uint8_t nonce[16];
const uint8_t expected_cipher_end[] = {
0x3e, 0x68, 0x8a, 0x02, 0xe6, 0xf2, 0x6a, 0x9e,
0x9b, 0xb2, 0xc0, 0xc4, 0x63, 0x63, 0xd9, 0x25,
0x51, 0xdc, 0xc2, 0x71, 0x96, 0xb3, 0xe5, 0xcd,
0xbd, 0x0e, 0xf2, 0xef, 0xa9, 0xab, 0xab, 0x2d,
};
memcpy(nonce, iv, 16);
// allocate internal memory
uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(decryptedtext);
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key_256, 256);
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
// Encrypt
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, SZ, nonce, plaintext, chipertext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32);
// Decrypt
memcpy(nonce, iv, 16);
mbedtls_aes_setkey_dec(&ctx, key_256, 256);
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, SZ, nonce, chipertext, decryptedtext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
mbedtls_aes_free(&ctx);
free(plaintext);
free(chipertext);
free(decryptedtext);
}
TEST_CASE("mbedtls CBC AES-256 DMA buffer align test", "[aes]")
{
#define ALIGN_DOWN(val, align) ((val) & ~((align) - 1))
// Size is taken considering the maximum DMA buffer size
const unsigned SZ = ALIGN_DOWN((2*LLDESC_MAX_NUM_PER_DESC), 16);
mbedtls_aes_context ctx;
uint8_t nonce[16];
const uint8_t expected_cipher_end[] = {
0x9e, 0xcb, 0x1d, 0x24, 0x01, 0xc8, 0x3f, 0xba,
0xde, 0x76, 0xea, 0x9c, 0xf3, 0x64, 0x23, 0x19,
0x8c, 0x67, 0xd4, 0x1a, 0xd1, 0xe0, 0xbf, 0xc3,
0xd2, 0xb8, 0x40, 0x95, 0x89, 0x41, 0x09, 0xdb,
};
memcpy(nonce, iv, 16);
// allocate internal memory
uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(decryptedtext);
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key_256, 256);
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
// Encrypt
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, SZ, nonce, plaintext, chipertext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32);
// Decrypt
memcpy(nonce, iv, 16);
mbedtls_aes_setkey_dec(&ctx, key_256, 256);
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, SZ, nonce, chipertext, decryptedtext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
mbedtls_aes_free(&ctx);
free(plaintext);
free(chipertext);
free(decryptedtext);
}
TEST_CASE("mbedtls CTR AES-256 test", "[aes]")
{
const unsigned SZ = 1000;
mbedtls_aes_context ctx;
uint8_t nonce[16];
uint8_t stream_block[16];
size_t nc_off = 0;
const uint8_t expected_cipher_end[] = {
0xd4, 0xdc, 0x4f, 0x8f, 0xfe, 0x86, 0xee, 0xb5,
0x14, 0x7f, 0xba, 0x30, 0x25, 0xa6, 0x7f, 0x6c,
0xb5, 0x73, 0xaf, 0x90, 0xd7, 0xff, 0x36, 0xba,
0x2b, 0x1d, 0xec, 0xb9, 0x38, 0xfa, 0x0d, 0xeb,
};
memcpy(nonce, iv, 16);
// allocate internal memory
uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(decryptedtext);
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key_256, 256);
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
// Encrypt
mbedtls_aes_crypt_ctr(&ctx, SZ, &nc_off, nonce, stream_block, plaintext, chipertext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32);
// Decrypt
nc_off = 0;
memcpy(nonce, iv, 16);
mbedtls_aes_crypt_ctr(&ctx, SZ, &nc_off, nonce, stream_block, chipertext, decryptedtext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
mbedtls_aes_free(&ctx);
free(plaintext);
free(chipertext);
free(decryptedtext);
}
TEST_CASE("mbedtls OFB AES-256 test", "[aes]")
{
const unsigned SZ = 1000;
mbedtls_aes_context ctx;
uint8_t nonce[16];
size_t nc_off = 0;
const uint8_t expected_cipher_end[] = {
0xca, 0xc3, 0x05, 0x77, 0xae, 0xb9, 0x38, 0xd6,
0x03, 0x0a, 0xad, 0x90, 0x6e, 0xdd, 0xf3, 0x9a,
0x41, 0x4d, 0x71, 0x30, 0x04, 0x9f, 0xd3, 0x53,
0xb7, 0x5e, 0xb4, 0xfd, 0x93, 0xf8, 0x31, 0x6a,
};
memcpy(nonce, iv, 16);
// allocate internal memory
uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(decryptedtext);
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key_256, 256);
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
// Encrypt
mbedtls_aes_crypt_ofb(&ctx, SZ, &nc_off, nonce, plaintext, chipertext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32);
// Decrypt
nc_off = 0;
memcpy(nonce, iv, 16);
mbedtls_aes_crypt_ofb(&ctx, SZ, &nc_off, nonce, chipertext, decryptedtext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
mbedtls_aes_free(&ctx);
free(plaintext);
free(chipertext);
free(decryptedtext);
}
TEST_CASE("mbedtls CFB-8 AES-256 test", "[aes]")
{
const unsigned SZ = 1000;
mbedtls_aes_context ctx;
uint8_t nonce[16];
const uint8_t expected_cipher_end[] = {
0x69, 0xdc, 0x1d, 0x8a, 0x0b, 0x9e, 0xbc, 0x84,
0x29, 0xa2, 0x04, 0xb6, 0x91, 0x6b, 0xb2, 0x83,
0x13, 0x23, 0x54, 0xcb, 0xf9, 0x6d, 0xcc, 0x53,
0x04, 0x59, 0xd1, 0xc9, 0xff, 0xab, 0xe2, 0x37,
};
memcpy(nonce, iv, 16);
// allocate internal memory
uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(decryptedtext);
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key_256, 256);
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
// Encrypt
mbedtls_aes_crypt_cfb8(&ctx, MBEDTLS_AES_ENCRYPT, SZ, nonce, plaintext, chipertext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32);
// Decrypt
memcpy(nonce, iv, 16);
mbedtls_aes_crypt_cfb8(&ctx, MBEDTLS_AES_DECRYPT, SZ, nonce, chipertext, decryptedtext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
mbedtls_aes_free(&ctx);
free(plaintext);
free(chipertext);
free(decryptedtext);
}
TEST_CASE("mbedtls CFB-128 AES-256 test", "[aes]")
{
const unsigned SZ = 1000;
mbedtls_aes_context ctx;
uint8_t nonce[16];
size_t nc_off = 0;
const uint8_t expected_cipher_end[] = {
0xf3, 0x64, 0x20, 0xa1, 0x70, 0x2a, 0xd9, 0x3f,
0xb7, 0x48, 0x8c, 0x2c, 0x1f, 0x65, 0x53, 0xc2,
0xac, 0xfd, 0x82, 0xe5, 0x31, 0x24, 0x1f, 0x30,
0xaf, 0xcc, 0x8d, 0xb3, 0xf3, 0x63, 0xe1, 0xa0,
};
memcpy(nonce, iv, 16);
// allocate internal memory
uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(decryptedtext);
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key_256, 256);
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
// Encrypt
mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_ENCRYPT, SZ, &nc_off, nonce, plaintext, chipertext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32);
// Decrypt
nc_off = 0;
memcpy(nonce, iv, 16);
mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_DECRYPT, SZ, &nc_off, nonce, chipertext, decryptedtext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
mbedtls_aes_free(&ctx);
free(plaintext);
free(chipertext);
free(decryptedtext);
}
static void aes_ctr_stream_test(void)
{
const unsigned SZ = 100;
mbedtls_aes_context ctx;
uint8_t nonce[16];
uint8_t key[16];
uint8_t stream_block[16];
/* Cipher produced via this Python:
import os, binascii
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
key = b'\x44' * 16
nonce = b'\xee' * 16
cipher = Cipher(algorithms.AES(key), modes.CTR(nonce), backend=default_backend())
encryptor = cipher.encryptor()
ct = encryptor.update(b'\xaa' * 100) + encryptor.finalize()
ct_arr = ""
for idx, b in enumerate(ct):
if idx % 8 == 0:
ct_arr += '\n'
ct_arr += "0x{}, ".format(binascii.hexlify(b))
print(ct_arr)
*/
const uint8_t expected_cipher[] = {
0xc5, 0x78, 0xa7, 0xb4, 0xf3, 0xb9, 0xcb, 0x8b,
0x09, 0xe0, 0xd6, 0x89, 0x14, 0x6a, 0x19, 0x09,
0xde, 0xaf, 0x37, 0x19, 0x32, 0x4d, 0xca, 0xf6,
0xff, 0x6e, 0xd2, 0x5d, 0x87, 0x51, 0xaa, 0x8c,
0x1c, 0xe3, 0x3b, 0xbb, 0x18, 0xf5, 0xa0, 0x1b,
0xdc, 0x29, 0x52, 0x63, 0xf6, 0x5d, 0x49, 0x85,
0x29, 0xf1, 0xf0, 0x69, 0x8f, 0xa6, 0x9f, 0x38,
0x5c, 0xdd, 0x26, 0xf8, 0x9d, 0x40, 0xa1, 0xff,
0x52, 0x46, 0xe1, 0x72, 0x70, 0x39, 0x73, 0xff,
0xd0, 0x5e, 0xe5, 0x3f, 0xc5, 0xed, 0x5c, 0x18,
0xa7, 0x84, 0xd8, 0xdf, 0x9d, 0xb5, 0x06, 0xb1,
0xa7, 0xcf, 0x2e, 0x7a, 0x51, 0xfc, 0x44, 0xc5,
0xb9, 0x5f, 0x22, 0x47,
};
memset(nonce, 0xEE, 16);
memset(key, 0x44, 16);
// allocate internal memory
uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(decryptedtext);
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key, 128);
memset(plaintext, 0xAA, SZ);
/* Test that all the end results are the same
no matter how many bytes we encrypt each call
*/
for (int bytes_to_process = 1; bytes_to_process < SZ; bytes_to_process++) {
ESP_LOGD("test", "bytes_to_process %d", bytes_to_process);
memset(nonce, 0xEE, 16);
memset(chipertext, 0x0, SZ);
memset(decryptedtext, 0x0, SZ);
size_t offset = 0;
// Encrypt
for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) {
// Limit length of last call to avoid exceeding buffer size
size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process;
mbedtls_aes_crypt_ctr(&ctx, length, &offset, nonce,
stream_block, plaintext + idx, chipertext + idx );
}
ESP_LOG_BUFFER_HEXDUMP("expected", expected_cipher, SZ, ESP_LOG_DEBUG);
ESP_LOG_BUFFER_HEXDUMP("actual ", chipertext, SZ, ESP_LOG_DEBUG);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, chipertext, SZ);
// Decrypt
memset(nonce, 0xEE, 16);
memset(decryptedtext, 0x22, SZ);
offset = 0;
for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) {
// Limit length of last call to avoid exceeding buffer size
size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process;
mbedtls_aes_crypt_ctr(&ctx, length, &offset, nonce,
stream_block, chipertext + idx, decryptedtext + idx );
}
ESP_LOG_BUFFER_HEXDUMP("decrypted", decryptedtext, SZ, ESP_LOG_DEBUG);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
}
mbedtls_aes_free(&ctx);
free(plaintext);
free(chipertext);
free(decryptedtext);
}
TEST_CASE("mbedtls CTR stream test", "[aes]")
{
aes_ctr_stream_test();
}
TEST_CASE("mbedtls OFB stream test", "[aes]")
{
const unsigned SZ = 100;
mbedtls_aes_context ctx;
uint8_t iv[16];
uint8_t key[16];
/* Cipher produced via this Python:
import os, binascii
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
key = b'\x44' * 16
iv = b'\xee' * 16
cipher = Cipher(algorithms.AES(key), modes.OFB(iv), backend=default_backend())
encryptor = cipher.encryptor()
ct = encryptor.update(b'\xaa' * 100) + encryptor.finalize()
ct_arr = ""
for idx, b in enumerate(ct):
if idx % 8 == 0:
ct_arr += '\n'
ct_arr += "0x{}, ".format(binascii.hexlify(b))
print(ct_arr)
*/
const uint8_t expected_cipher[] = {
0xc5, 0x78, 0xa7, 0xb4, 0xf3, 0xb9, 0xcb, 0x8b,
0x09, 0xe0, 0xd6, 0x89, 0x14, 0x6a, 0x19, 0x09,
0x0a, 0x33, 0x8b, 0xab, 0x82, 0xcb, 0x20, 0x8f,
0x74, 0x2a, 0x6c, 0xb3, 0xc6, 0xe8, 0x18, 0x89,
0x09, 0xb6, 0xaf, 0x20, 0xcd, 0xea, 0x74, 0x14,
0x48, 0x61, 0xe8, 0x4d, 0x50, 0x12, 0x9f, 0x5e,
0xb8, 0x10, 0x53, 0x3b, 0x74, 0xd9, 0xd0, 0x95,
0x13, 0xdc, 0x14, 0xcf, 0x0c, 0xa1, 0x90, 0xfd,
0xa2, 0x58, 0x12, 0xb2, 0x00, 0x2c, 0x5b, 0x7a,
0x2a, 0x76, 0x80, 0x20, 0x82, 0x39, 0xa2, 0x21,
0xf8, 0x7a, 0xec, 0xae, 0x82, 0x6a, 0x5c, 0xd3,
0x04, 0xd9, 0xbd, 0xe4, 0x53, 0xc9, 0xdf, 0x67,
0xaa, 0x5c, 0xaf, 0xa6,
};
memset(key, 0x44, 16);
// allocate internal memory
uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(decryptedtext);
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key, 128);
memset(plaintext, 0xAA, SZ);
/* Test that all the end results are the same
no matter how many bytes we encrypt each call
*/
for (int bytes_to_process = 1; bytes_to_process < SZ; bytes_to_process++) {
ESP_LOGD("test", "bytes_to_process %d", bytes_to_process);
// Encrypt
memset(iv, 0xEE, 16);
size_t offset = 0;
for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) {
// Limit length of last call to avoid exceeding buffer size
size_t length = ( (idx + bytes_to_process) > SZ) ? (SZ - idx) : bytes_to_process;
mbedtls_aes_crypt_ofb(&ctx, length, &offset, iv, plaintext + idx, chipertext + idx);
}
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, chipertext, SZ);
// Decrypt
memset(iv, 0xEE, 16);
memset(decryptedtext, 0x22, SZ);
offset = 0;
for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) {
// Limit length of last call to avoid exceeding buffer size
size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process;
mbedtls_aes_crypt_ofb(&ctx, length, &offset, iv, chipertext + idx, decryptedtext + idx);
}
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
}
mbedtls_aes_free(&ctx);
free(plaintext);
free(chipertext);
free(decryptedtext);
}
TEST_CASE("mbedtls CFB8 stream test", "[aes]")
{
const unsigned SZ = 32;
mbedtls_aes_context ctx;
uint8_t iv[16];
uint8_t key[16];
/* Cipher produced via this Python:
import os, binascii
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
key = b'\x44' * 16
iv = b'\xee' * 16
cipher = Cipher(algorithms.AES(key), modes.CFB8(iv), backend=default_backend())
encryptor = cipher.encryptor()
ct = encryptor.update(b'\xaa' * 100) + encryptor.finalize()
ct_arr = ""
for idx, b in enumerate(ct):
if idx % 8 == 0:
ct_arr += '\n'
ct_arr += "0x{}, ".format(binascii.hexlify(b))
print(ct_arr)
*/
const uint8_t expected_cipher[] = {
0xc5, 0x2f, 0xb0, 0x9b, 0x94, 0x9c, 0xa4, 0x5c,
0x0f, 0x4d, 0xa1, 0x9d, 0xd1, 0x19, 0xfc, 0x04,
0xe2, 0x7f, 0x04, 0x82, 0x6a, 0xa3, 0x61, 0xbb,
0x07, 0x6f, 0xac, 0xb9, 0xdf, 0x00, 0xf9, 0xa8,
0xc4, 0xbe, 0x9d, 0x4d, 0xd9, 0x42, 0x8a, 0x83,
0x12, 0x8b, 0xeb, 0xd7, 0x88, 0x70, 0x8a, 0xed,
0x46, 0x81, 0x5b, 0x4c, 0x14, 0x67, 0xe0, 0xfb,
0xab, 0x34, 0x90, 0x85, 0x24, 0xd2, 0x6b, 0x64,
0xdf, 0x1d, 0x04, 0xfd, 0x69, 0xf6, 0x30, 0xbe,
0xa6, 0xac, 0x0b, 0x54, 0x25, 0x24, 0x67, 0xd6,
0x09, 0xb1, 0x8f, 0x91, 0x63, 0xbd, 0xdf, 0xa1,
0x8a, 0xa3, 0x2e, 0xeb, 0x15, 0x7d, 0xe5, 0x37,
0xe5, 0x5a, 0x9f, 0xa5,
};
memset(key, 0x44, 16);
// allocate internal memory
uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(decryptedtext);
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key, 128);
memset(plaintext, 0xAA, SZ);
/* Test that all the end results are the same
no matter how many bytes we encrypt each call
*/
for (int bytes_to_process = 1; bytes_to_process < SZ; bytes_to_process++) {
memset(iv, 0xEE, 16);
for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) {
// Limit length of last call to avoid exceeding buffer size
size_t length = ( (idx + bytes_to_process) > SZ) ? (SZ - idx) : bytes_to_process;
mbedtls_aes_crypt_cfb8(&ctx, MBEDTLS_AES_ENCRYPT, length, iv, plaintext + idx, chipertext + idx);
}
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, chipertext, SZ);
memset(iv, 0xEE, 16);
for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) {
// Limit length of last call to avoid exceeding buffer size
size_t length = ( (idx + bytes_to_process) > SZ) ? (SZ - idx) : bytes_to_process;
mbedtls_aes_crypt_cfb8(&ctx, MBEDTLS_AES_DECRYPT, length, iv, chipertext + idx, decryptedtext + idx);
}
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
}
mbedtls_aes_free(&ctx);
free(plaintext);
free(chipertext);
free(decryptedtext);
}
TEST_CASE("mbedtls CFB128 stream test", "[aes]")
{
const unsigned SZ = 32;
mbedtls_aes_context ctx;
uint8_t iv[16];
uint8_t key[16];
/* Cipher produced via this Python:
import os, binascii
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
key = b'\x44' * 16
iv = b'\xee' * 16
cipher = Cipher(algorithms.AES(key), modes.CFB(iv), backend=default_backend())
encryptor = cipher.encryptor()
ct = encryptor.update(b'\xaa' * 100) + encryptor.finalize()
ct_arr = ""
for idx, b in enumerate(ct):
if idx % 8 == 0:
ct_arr += '\n'
ct_arr += "0x{}, ".format(binascii.hexlify(b))
print(ct_arr)
*/
const uint8_t expected_cipher[] = {
0xc5, 0x78, 0xa7, 0xb4, 0xf3, 0xb9, 0xcb, 0x8b,
0x09, 0xe0, 0xd6, 0x89, 0x14, 0x6a, 0x19, 0x09,
0xf9, 0x08, 0x7e, 0xe1, 0x92, 0x8a, 0x7c, 0xa4,
0x25, 0xa5, 0xa7, 0x43, 0x24, 0x8d, 0x85, 0x3e,
0x99, 0x28, 0xeb, 0x36, 0x59, 0x74, 0x69, 0x0e,
0x09, 0x9f, 0x4e, 0xc0, 0x6d, 0xc3, 0x2b, 0x80,
0x01, 0xad, 0xa1, 0x0c, 0x99, 0x90, 0x8b, 0x07,
0xd6, 0x00, 0xf0, 0x32, 0xd7, 0x6b, 0xa1, 0xf1,
0x4d, 0x14, 0xd0, 0x28, 0xde, 0x64, 0x23, 0x71,
0xf4, 0x23, 0x61, 0x12, 0x71, 0xbe, 0x03, 0x74,
0x99, 0x81, 0x9d, 0x65, 0x48, 0xd9, 0xd4, 0x67,
0xd1, 0x31, 0xe8, 0x44, 0x27, 0x17, 0xd4, 0x2d,
0x3d, 0x59, 0xf7, 0xd3,
};
memset(key, 0x44, 16);
// allocate internal memory
uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(decryptedtext);
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key, 128);
memset(plaintext, 0xAA, SZ);
/* Test that all the end results are the same
no matter how many bytes we encrypt each call
*/
//for (int bytes_to_process = 1; bytes_to_process < SZ; bytes_to_process++) {
int bytes_to_process = 17;
size_t offset = 0;
memset(iv, 0xEE, 16);
for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) {
// Limit length of last call to avoid exceeding buffer size
size_t length = ( (idx + bytes_to_process) > SZ) ? (SZ - idx) : bytes_to_process;
mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_ENCRYPT, length, &offset, iv, plaintext + idx, chipertext + idx);
}
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, chipertext, SZ);
offset = 0;
memset(iv, 0xEE, 16);
for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) {
// Limit length of last call to avoid exceeding buffer size
size_t length = ( (idx + bytes_to_process) > SZ) ? (SZ - idx) : bytes_to_process;
mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_DECRYPT, length, &offset, iv, chipertext + idx, decryptedtext + idx);
}
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
mbedtls_aes_free(&ctx);
free(plaintext);
free(chipertext);
free(decryptedtext);
}
/* Cipher produced via this Python:
import os, binascii
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
key = b'\x44' * 16
nonce = b'\xee' * 16
cipher = Cipher(algorithms.AES(key), modes.CTR(nonce), backend=default_backend())
encryptor = cipher.encryptor()
ct = encryptor.update(b'\xaa' * 100) + encryptor.finalize()
ct_arr = ""
for idx, b in enumerate(ct):
if idx % 8 == 0:
ct_arr += '\n'
ct_arr += "0x{}, ".format(binascii.hexlify(b))
print(ct_arr)
*/
/* Test the case where the input and output buffers point to the same location */
TEST_CASE("mbedtls CTR, input buf = output buf", "[aes]")
{
const unsigned SZ = 1000;
mbedtls_aes_context ctx;
uint8_t nonce[16];
uint8_t stream_block[16];
size_t nc_off = 0;
const uint8_t expected_cipher_end[] = {
0xd4, 0xdc, 0x4f, 0x8f, 0xfe, 0x86, 0xee, 0xb5,
0x14, 0x7f, 0xba, 0x30, 0x25, 0xa6, 0x7f, 0x6c,
0xb5, 0x73, 0xaf, 0x90, 0xd7, 0xff, 0x36, 0xba,
0x2b, 0x1d, 0xec, 0xb9, 0x38, 0xfa, 0x0d, 0xeb,
};
memcpy(nonce, iv, 16);
// allocate internal memory
uint8_t *buf = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buf);
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key_256, 256);
memset(buf, 0x3A, SZ);
// Encrypt
mbedtls_aes_crypt_ctr(&ctx, SZ, &nc_off, nonce, stream_block, buf, buf);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, buf + SZ - 32, 32);
// Decrypt
nc_off = 0;
memcpy(nonce, iv, 16);
mbedtls_aes_crypt_ctr(&ctx, SZ, &nc_off, nonce, stream_block, buf, buf);
for (int i = 0; i < SZ; i++) {
TEST_ASSERT_EQUAL_HEX8(0x3A, buf[i]);
}
mbedtls_aes_free(&ctx);
free(buf);
}
TEST_CASE("mbedtls OFB, chained DMA descriptors", "[aes]")
{
// Max bytes in a single DMA descriptor is 4095
const unsigned SZ = 6000;
mbedtls_aes_context ctx;
uint8_t nonce[16];
size_t nc_off = 0;
const uint8_t expected_cipher_end[] = {
0xfe, 0xfa, 0xc9, 0x26, 0xb5, 0xc9, 0xea, 0xb0,
0xdd, 0x1e, 0xe7, 0x0e, 0xfa, 0x5b, 0x4b, 0x94,
0xaa, 0x5f, 0x60, 0x1e, 0xb2, 0x19, 0x3c, 0x2e,
0xf6, 0x73, 0x56, 0x9f, 0xa7, 0xd5, 0xb7, 0x21,
};
memcpy(nonce, iv, 16);
// allocate internal memory
uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(decryptedtext);
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key_256, 256);
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
// Encrypt
mbedtls_aes_crypt_ofb(&ctx, SZ, &nc_off, nonce, plaintext, chipertext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32);
// Decrypt
nc_off = 0;
memcpy(nonce, iv, 16);
mbedtls_aes_crypt_ofb(&ctx, SZ, &nc_off, nonce, chipertext, decryptedtext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
mbedtls_aes_free(&ctx);
free(plaintext);
free(chipertext);
free(decryptedtext);
}
const uint8_t expected_cipher_ctr_end[] = {
0x93, 0xca, 0xe0, 0x44, 0x96, 0x6d, 0xcb, 0xb2,
0xcf, 0x8a, 0x8d, 0x73, 0x8c, 0x6b, 0xfa, 0x4d,
0xd6, 0xc4, 0x18, 0x49, 0xdd, 0xc6, 0xbf, 0xc2,
0xb9, 0xf0, 0x09, 0x69, 0x45, 0x42, 0xc6, 0x05,
};
void aes_ctr_alignment_test(uint32_t input_buf_caps, uint32_t output_buf_caps)
{
mbedtls_aes_context ctx;
uint8_t nonce[16];
uint8_t key[16];
uint8_t stream_block[16];
size_t SZ = 32*200;
size_t ALIGNMENT_SIZE_BYTES = 64;
memset(nonce, 0x2F, 16);
memset(key, 0x1E, 16);
// allocate memory according the requested caps
uint8_t *chipertext = heap_caps_malloc(SZ + ALIGNMENT_SIZE_BYTES, output_buf_caps);
uint8_t *plaintext = heap_caps_malloc(SZ + ALIGNMENT_SIZE_BYTES, input_buf_caps);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(decryptedtext);
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key, 128);
memset(plaintext, 0x26, SZ + ALIGNMENT_SIZE_BYTES);
size_t offset;
/* Shift buffers and test for all different misalignments */
for (int i = 0; i < ALIGNMENT_SIZE_BYTES; i++ ) {
// Encrypt with input buffer in external ram
offset = 0;
memset(nonce, 0x2F, 16);
mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, plaintext + i, chipertext + i);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_ctr_end, chipertext + i + SZ - 32, 32);
// Decrypt
offset = 0;
memset(nonce, 0x2F, 16);
// Decrypt with input buffer in instruction memory, the crypto DMA can't access this
mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, chipertext + i, decryptedtext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
}
mbedtls_aes_free(&ctx);
free(plaintext);
free(chipertext);
free(decryptedtext);
}
TEST_CASE("mbedtls AES internal mem alignment tests", "[aes]")
{
uint32_t internal_dma_caps = MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL;
aes_ctr_alignment_test(internal_dma_caps, internal_dma_caps);
}
#ifdef CONFIG_SPIRAM_USE_MALLOC
void aes_psram_one_buf_ctr_test(void)
{
mbedtls_aes_context ctx;
uint8_t nonce[16];
uint8_t key[16];
uint8_t stream_block[16];
size_t SZ = 32*200;
size_t ALIGNMENT_SIZE_BYTES = 32;
memset(nonce, 0x2F, 16);
memset(key, 0x1E, 16);
// allocate external memory
uint8_t *buf = heap_caps_malloc(SZ + ALIGNMENT_SIZE_BYTES, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
TEST_ASSERT_NOT_NULL(buf);
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key, 128);
memset(buf, 0x26, SZ + ALIGNMENT_SIZE_BYTES);
size_t offset;
/* Shift buffers and test for all different misalignments */
for (int i = 0; i < ALIGNMENT_SIZE_BYTES; i++ ) {
// Encrypt with input buffer in external ram
offset = 0;
memset(buf, 0x26, SZ + ALIGNMENT_SIZE_BYTES);
memset(nonce, 0x2F, 16);
mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, buf + i, buf + i);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_ctr_end, buf + i + SZ - 32, 32);
// Decrypt
offset = 0;
memset(nonce, 0x2F, 16);
// Decrypt with input buffer in instruction memory, the crypto DMA can't access this
mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, buf + i, buf);
TEST_ASSERT_EACH_EQUAL_HEX8(0x26, buf + i, SZ - i);
}
mbedtls_aes_free(&ctx);
free(buf);
}
const uint8_t long_input[] = {
0xf7, 0xe6, 0x6b, 0x8d, 0x2e, 0xbf, 0x88, 0xd6,
0xb0, 0x77, 0xdf, 0x72, 0xbf, 0xa8, 0x0, 0x55,
0xd5, 0xd1, 0x49, 0xa3, 0x2c, 0xc, 0xfe, 0xdb,
0x17, 0x37, 0xa4, 0x1d, 0x70, 0x6b, 0x99, 0xf5,
0x9e, 0x6, 0xad, 0x6c, 0xe0, 0x3b, 0xfa, 0x50,
0x28, 0xb2, 0x62, 0xf2, 0x99, 0x3a, 0xcc, 0xe4,
0x86, 0x5f, 0x1, 0xf8, 0x69, 0xd7, 0xf5, 0xb2,
0x8a, 0x5f, 0x5c, 0x38, 0x9f, 0x8a, 0xb8, 0x8c,
0xea, 0x6, 0xe1, 0x68, 0xff, 0xaf, 0x5d, 0xd9,
0x1f, 0xa5, 0x5c, 0x8c, 0x52, 0xa1, 0x5f, 0x45,
0x55, 0xcb, 0x76, 0x59, 0x8f, 0xfe, 0x36, 0xd0,
0x85, 0x1f, 0x8, 0x90, 0x6f, 0x62, 0xb1, 0x1a,
0xde, 0x75, 0xab, 0x90, 0xb7, 0x75, 0xe9, 0xa0,
0xa9, 0xb0, 0xac, 0x61, 0x5, 0x6d, 0x9a, 0xe3,
0x3b, 0x43, 0x61, 0x13, 0x8c, 0x3a, 0xa0, 0xaa,
0x91, 0xea, 0x3e, 0xe1, 0x87, 0x35, 0xff, 0x90,
0xe2, 0x43, 0xa3, 0x70, 0x57, 0x65, 0x2d, 0xa2,
0x65, 0xe6, 0xde, 0xb0, 0x52, 0x85, 0x5b, 0xb8,
0x3, 0x8, 0x63, 0x8b, 0xa1, 0xc2, 0xe1, 0x35,
0x2e, 0xba, 0xe0, 0x84, 0x56, 0x52, 0x5f, 0x12,
0xd3, 0x22, 0x8d, 0xa5, 0xbb, 0xe1, 0xd3, 0xfc,
0x18, 0x1c, 0x90, 0x3b, 0x79, 0xe, 0xab, 0x2d,
0x5e, 0xb0, 0x7, 0xbb, 0x46, 0x73, 0x1d, 0x35,
0xd9, 0xc5, 0xa7, 0x87, 0x80, 0xf7, 0xee, 0x29,
0xb5, 0x17, 0xf3, 0xaf, 0x30, 0xe5, 0x19, 0x50,
0xf9, 0x5d, 0x2b, 0xc3, 0xc0, 0xda, 0x8f, 0xca,
0x3c, 0x4d, 0xd5, 0xd7, 0x6c, 0xd2, 0x36, 0xa4,
0x22, 0x8, 0x66, 0x48, 0x31, 0xb4, 0x3d, 0xc2,
0xf6, 0x6b, 0xce, 0xf0, 0x12, 0xe4, 0x38, 0x5c,
0xd8, 0x71, 0xea, 0x30, 0x52, 0xdf, 0x34, 0x62,
0xdc, 0xb4, 0x30, 0xe, 0x74, 0xc, 0x5, 0x14,
0xf, 0x47, 0x25, 0x5, 0x72, 0xc9, 0x14, 0x7c,
0x1f, 0x6e, 0xdb, 0x6f, 0x83, 0x6, 0xa0, 0xb2,
0x7f, 0x29, 0xe6, 0xb6, 0xe3, 0x11, 0x23, 0x4b,
0x68, 0x92, 0xa, 0x49, 0xb5, 0x9d, 0x5d, 0x39,
0x90, 0xff, 0x9, 0xa0, 0xa, 0x69, 0x6b, 0x2,
0x18, 0xfb, 0xca, 0x5a, 0x91, 0x1a, 0xd9, 0x19,
0x6b, 0xd4, 0x92, 0xd3, 0xd9, 0x7, 0xce, 0xcb,
0xc7, 0xf3, 0xa1, 0x33, 0xcd, 0xa9, 0xb1, 0x44,
0x8c, 0x93, 0xcd, 0xac, 0xc1, 0x44, 0x12, 0x48,
0x95, 0x3, 0xdf, 0xc, 0x2f, 0xfc, 0x34, 0x8d,
0x3, 0xde, 0xc1, 0xed, 0xdc, 0xf0, 0xfa, 0xa5,
0xb2, 0x62, 0xcd, 0xa2, 0xbf, 0xf7, 0x7e, 0x47,
0xb6, 0xcc, 0xe4, 0xa6, 0x4e, 0x51, 0xc6, 0x34,
0xee, 0x83, 0x21, 0xb7, 0xc2, 0xe3, 0x13, 0x92,
0xfc, 0xc9, 0x6, 0x6b, 0x91, 0x76, 0x7b, 0x2e,
0x1e, 0xa2, 0xe0, 0x17, 0xab, 0x10, 0xfa, 0xac,
0xd1, 0x2, 0x33, 0xb0, 0xd3, 0x3d, 0xb9, 0xce,
0xea, 0xe9, 0x93, 0x5c, 0x98, 0x14, 0x0, 0xc6,
0x2c, 0xa6, 0xdb, 0x1f, 0xdc, 0x76, 0xfb, 0xeb,
0x9d, 0x55, 0xa6, 0x5f, 0xd5, 0x8e, 0x13, 0x39,
0x88, 0x58, 0xff, 0xe8, 0xb4, 0x98, 0x9e, 0x4b,
0xe7, 0x46, 0xdc, 0x7a, 0x68, 0x5b, 0xa8, 0xc2,
0xe5, 0xa9, 0x50, 0xe2, 0x8, 0x31, 0x6, 0x3e,
0x8e, 0xaf, 0x80, 0x24, 0x4e, 0xbd, 0x73, 0x6d,
0xd9, 0x4b, 0xb4, 0x3e, 0x84, 0x5e, 0x31, 0x8e,
0xf7, 0xa8, 0x9b, 0x5e, 0x2c, 0xd5, 0xe9, 0x7c,
0xca, 0xca, 0xfa, 0x8e, 0x87, 0xbf, 0xf5, 0xa3,
0x2f, 0x73, 0x2f, 0xc0, 0x5f, 0x46, 0xf4, 0x2,
0xfd, 0xd1, 0x23, 0x6f, 0xc2, 0xc1, 0xc0, 0x86,
0x62, 0x43, 0xc3, 0x44, 0x3b, 0x2c, 0x3d, 0xc2,
0xd5, 0xe0, 0x2, 0xae, 0x1, 0x5a, 0x9, 0x89,
0x52, 0x34, 0xdf, 0xb1, 0x6c, 0x2b, 0x85, 0x77,
0xa5, 0x83, 0xe3, 0xa5, 0x50, 0x13, 0x2f, 0xf3,
0xa6, 0x83, 0x60, 0x33, 0xba, 0xd5, 0xd2, 0x96,
0x8a, 0xcd, 0xee, 0xfa, 0x76, 0x2a, 0x63, 0xec,
0x41, 0x3a, 0xf3, 0xe5, 0x9e, 0x1d, 0x5e, 0x46,
0x8, 0xd7, 0xe2, 0x3a, 0x25, 0x6f, 0x37, 0x7e,
0x0, 0x2d, 0x3d, 0x1b, 0x86, 0xf4, 0xbe, 0x0,
0x3c, 0xda, 0x82, 0x4a, 0xa3, 0x8, 0x2a, 0x38,
0x95, 0xe, 0x38, 0xf8, 0x18, 0x6c, 0x42, 0x6f,
0x30, 0x19, 0x8e, 0x22, 0xf6, 0xb7, 0x18, 0xb7,
0x93, 0xd, 0x54, 0x72, 0x4, 0x64, 0xc1, 0x19,
0x76, 0x6e, 0xfc, 0x9e, 0xb0, 0x7c, 0x20, 0x37,
0xb0, 0xcb, 0x82, 0x3a, 0x20, 0x1d, 0x12, 0x44,
0xbf, 0x44, 0xc4, 0x4d, 0x33, 0x7e, 0x7b, 0xeb,
0xd8, 0xb8, 0xa1, 0x75, 0x9e, 0x47, 0x99, 0x64,
0x92, 0xd3, 0x21, 0x1d, 0x72, 0x63, 0xc7, 0xb3,
0x3d, 0xfc, 0xb9, 0x4, 0x65, 0x18, 0x94, 0xcc,
0x20, 0xfe, 0x6f, 0x66, 0x36, 0xba, 0x36, 0x2a,
0x7, 0xf0, 0x5e, 0x8a, 0xf2, 0x7, 0x1e, 0x9e,
0x47, 0x2a, 0xc3, 0x7d, 0x7a, 0x20, 0x3c, 0x30,
0x6f, 0xbe, 0x43, 0x5e, 0x71, 0x6f, 0xd, 0xb8,
0x3d, 0x1d, 0x3e, 0x18, 0x65, 0x62, 0x75, 0xe8,
0x34, 0xfd, 0x72, 0xbb, 0xd9, 0x3f, 0xf0, 0xa2,
0x55, 0xee, 0x91, 0x12, 0x88, 0xda, 0x7, 0x3d,
0x44, 0x88, 0x70, 0x1f, 0xe0, 0xbe, 0x4b, 0x88,
0xa8, 0x8e, 0x28, 0x7, 0x73, 0xfd, 0x3f, 0xff,
0x3e, 0xb2, 0xb5, 0xdb, 0x18, 0x48, 0x9e, 0x73,
0x6e, 0xd7, 0x24, 0xa9, 0x25, 0xdb, 0x4, 0xe0,
0xe0, 0xf4, 0x45, 0xc0, 0x1b, 0x82, 0xdf, 0x4e,
0x48, 0x60, 0x85, 0x9c, 0xd8, 0x90, 0x32, 0xca,
0x4b, 0xf9, 0xb4, 0xb8, 0xe1, 0xfe, 0xd2, 0xe0,
0xb2, 0xd6, 0xb8, 0x19, 0x38, 0x34, 0x17, 0x8d,
0x5e, 0xdf, 0xf4, 0xf1, 0xac, 0x2c, 0x88, 0x7f,
0x54, 0xbc, 0xf1, 0x39, 0xf2, 0xaf, 0x5a, 0xff,
0xa7, 0x96, 0x0, 0xf0, 0x27, 0x79, 0x27, 0x2e,
0x9c, 0xf1, 0x4b, 0xa3, 0xad, 0xdc, 0x8a, 0x2c,
0x9, 0x4c, 0xd3, 0xcd, 0xd0, 0x2d, 0xb1, 0xec,
0x4d, 0x68, 0x40, 0xb8, 0xc5, 0x5, 0xfa, 0xb2,
0x61, 0xb8, 0x31, 0x5, 0xea, 0xb8, 0xa3, 0x34,
0xa8, 0x8b, 0x3, 0x5b, 0x22, 0x93, 0xba, 0x91,
0x33, 0x3f, 0x8b, 0x5e, 0xed, 0x86, 0x23, 0x95,
0xbc, 0x9e, 0xdf, 0xa9, 0x8c, 0xca, 0xb9, 0x97,
0x9b, 0xc5, 0xca, 0xf4, 0xff, 0x4d, 0x62, 0x52,
0x1c, 0xd3, 0x4c, 0x42, 0xbf, 0x8a, 0x25, 0x47,
0xc7, 0x9, 0x4e, 0xe0, 0xb1, 0x72, 0x7d, 0x2,
0x8f, 0xca, 0x4f, 0x4, 0xc8, 0x74, 0x82, 0x8e,
0x53, 0xfd, 0xa1, 0x37, 0xda, 0x29, 0x5c, 0xa3,
0x83, 0xe9, 0xa8, 0xd8, 0x25, 0x27, 0xfe, 0xf7,
0x41, 0xc4, 0xb0, 0xee, 0x1d, 0x89, 0x1c, 0xe7,
0xef, 0x86, 0x68, 0xd8, 0x87, 0x4c, 0x4f, 0x49,
0xeb, 0xbc, 0xb3, 0x81, 0xa7, 0xf4, 0xb4, 0x9b,
0xc1, 0x52, 0x93, 0x7e, 0xdf, 0x75, 0x75, 0xfc,
0x45, 0xb2, 0x86, 0xa9, 0x50, 0xb5, 0xa3, 0xf7,
0x61, 0x60, 0xe4, 0x13, 0x99, 0xc0, 0xf8, 0x49,
0x7b, 0x61, 0x8b, 0xa8, 0xfa, 0x77, 0x0, 0xe4,
0x6, 0x9a, 0xc5, 0x51, 0xe4, 0xeb, 0xaf, 0x5f,
0xb9, 0x5c, 0x74, 0xc8, 0xf8, 0x3e, 0x62, 0x26,
0xe, 0xe5, 0x85, 0xca, 0x49, 0xa0, 0x2f, 0xf7,
0x7, 0x99, 0x3e, 0x5c, 0xe0, 0x72, 0xfa, 0xd4,
0x80, 0x2e, 0xd6, 0x40, 0x6, 0xde, 0x5f, 0xc5,
0xc5, 0x1, 0xd, 0xbf, 0xdb, 0xb6, 0xb3, 0x92,
0x76, 0xb3, 0x3f, 0x3d, 0x5d, 0x1, 0x23, 0xb8,
0xa, 0xcb, 0x80, 0x17, 0x31, 0x19, 0xc7, 0x64,
0x69, 0xf1, 0x99, 0x53, 0xe5, 0xf2, 0x9f, 0x9d,
0x3c, 0xda, 0xcb, 0xa6, 0x94, 0x94, 0x44, 0xd3,
0xc6, 0x8b, 0xb5, 0xae, 0x45, 0x25, 0xef, 0x2a,
0x24, 0x1, 0x3a, 0xf6, 0xf, 0xe, 0xcb, 0x10,
0xc4, 0xe0, 0xf4, 0x3d, 0xf4, 0xf5, 0xea, 0x9b,
0xd1, 0x16, 0x1b, 0x62, 0x11, 0x3e, 0x20, 0x3a,
0x68, 0xc8, 0xf0, 0xe, 0x55, 0xbe, 0x51, 0x4d,
0xbe, 0x1f, 0x4f, 0xda, 0x84, 0xda, 0xc4, 0x9e,
0x24, 0xd7, 0x46, 0x82, 0x56, 0x4e, 0x61, 0x63,
0xda, 0x18, 0xea, 0xc6, 0xc3, 0x21, 0x89, 0x18,
0xe, 0x87, 0xb7, 0x91, 0xfe, 0x8d, 0xe, 0xac,
0x75, 0x58, 0xe5, 0x9f, 0x1f, 0x93, 0xa6, 0x49,
0x24, 0xa2, 0xc6, 0xe8, 0x9d, 0x9c, 0x6d, 0xc1,
0xf, 0xfc, 0xe3, 0x57, 0xd3, 0xc2, 0x10, 0x91,
0x9a, 0xa8, 0xaa, 0xd7, 0xf, 0xaa, 0x75, 0x90,
0x4a, 0x10, 0xef, 0xb6, 0xdd, 0x6c, 0xd5, 0x1a,
0xe3, 0xbb, 0xe0, 0x64, 0x44, 0xc, 0x59, 0xa1,
0xef, 0x3, 0x52, 0xac, 0xa4, 0x85, 0x3e, 0x40,
0xee, 0x5c, 0xef, 0xcf, 0xb1, 0xaa, 0x88, 0xe5,
0x56, 0xb8, 0xcd, 0x87, 0xc7, 0xc6, 0xd3, 0xb4,
0x85, 0x8f, 0x2a, 0xc9, 0xcd, 0x8a, 0x8b, 0x25,
0x12, 0x71, 0x76, 0xc9, 0xaa, 0x62, 0x75, 0x80,
0x6e, 0xa3, 0xf9, 0xa5, 0xfc, 0x90, 0xac, 0x28,
0x13, 0x82, 0xbb, 0x5d, 0xa6, 0x93, 0x47, 0xd4,
0xf, 0x3b, 0x19, 0xf6, 0x81, 0xdb, 0x55, 0xb0,
0x47, 0x75, 0x63, 0x93, 0xb4, 0xdd, 0xf0, 0xaf,
0xb7, 0x44, 0xcb, 0x7, 0x7b, 0x35, 0xc5, 0xe4,
0x45, 0xfe, 0xbb, 0x11, 0x1a, 0x90, 0x96, 0x3a,
0x7, 0x2a, 0xef, 0x9c, 0xc, 0xae, 0x38, 0x26,
0xef, 0xc2, 0xc3, 0x53, 0xfa, 0x54, 0xcf, 0x6f,
0xf7, 0xa, 0xea, 0x19, 0xa8, 0xf, 0xbd, 0xa7,
0x3f, 0xcd, 0x38, 0x2c, 0xf3, 0x97, 0xfb, 0xdb,
0xcb, 0xc5, 0x83, 0x80, 0x91, 0x3d, 0xc7, 0x29,
0x67, 0x16, 0xa5, 0xd1, 0x41, 0xd0, 0xa1, 0x9b,
0xde, 0x13, 0x83, 0x12, 0x36, 0x75, 0x81, 0x71,
0x6b, 0xbc, 0x72, 0xcb, 0x37, 0x4, 0x6, 0x7c,
0x3a, 0x22, 0x2b, 0xa, 0x11, 0xd3, 0x33, 0x8f,
0x3, 0x54, 0x8e, 0x79, 0xb6, 0x36, 0x93, 0x92,
0xb8, 0xf, 0x24, 0x4a, 0xd3, 0xd5, 0x27, 0x66,
0xd1, 0xde, 0xe3, 0xaa, 0x4b, 0x2a, 0xe9, 0x22,
0x9b, 0xbf, 0x6e, 0x9a, 0xf7, 0xa, 0x2f, 0x24,
0x13, 0xd5, 0xd5, 0xbb, 0xa3, 0xba, 0x8f, 0xfc,
0x28, 0xa8, 0xbe, 0xe6, 0x9f, 0xea, 0xed, 0xb1,
0xba, 0xaf, 0xf, 0x1c, 0x1e, 0x51, 0xf8, 0xd7,
0x1b, 0xa5, 0xa6, 0x63, 0x40, 0x6e, 0x3f, 0xa2,
0x57, 0x6f, 0x57, 0xe4, 0x27, 0xc2, 0x3c, 0x33,
0xc6, 0x9c, 0x24, 0xd0, 0x53, 0xc4, 0xfc, 0xed,
0x8e, 0x1d, 0xf, 0xc3, 0x86, 0x9, 0x3d, 0x1d,
0xc2, 0xdb, 0x24, 0x1a, 0x65, 0xf4, 0x30, 0xa5,
0xc, 0x48, 0x37, 0xc5, 0x53, 0x35, 0x3b, 0xab,
0xd, 0x96, 0x30, 0xd7, 0x1d, 0x66, 0x18, 0xc2,
0x47, 0x3a, 0xef, 0xbe, 0x2e, 0xe4, 0x54, 0x9d,
0xc4, 0xa5, 0xb9, 0xb3, 0x4c, 0x12, 0x73, 0x35,
0xf0, 0x7, 0xe, 0x36, 0x88, 0xb2, 0x4b, 0x29,
0xb, 0x4e, 0x84, 0x11, 0xaa, 0x9a, 0x3e, 0xb1,
0xd7, 0xec, 0xfb, 0x7f, 0x10, 0x70, 0x1f, 0x26,
0xf0, 0x27, 0x46, 0x5d, 0x4, 0x51, 0x97, 0x29,
0xb4, 0x66, 0x39, 0x1, 0x82, 0x47, 0xd8, 0x5f,
0xa9, 0xb3, 0xa1, 0xb8, 0xde, 0x1, 0xe1, 0xc4,
0x47, 0xc5, 0xe8, 0xe6, 0xbb, 0xc0, 0xb6, 0x41,
0x55, 0x10, 0x79, 0xa8, 0xd0, 0xd, 0x1, 0x56,
0x29, 0x6c, 0xa5, 0x96, 0x87, 0x59, 0x4b, 0xd,
0xc8, 0x3, 0x5, 0xaa, 0xa9, 0x6a, 0xb1, 0x10,
0xbc, 0x1, 0x68, 0xd3, 0xa5, 0x52, 0x41, 0xe1,
0x1f, 0x53, 0x7, 0xc6, 0xad, 0xb8, 0xc4, 0xf0,
0x28, 0xe9, 0x3, 0x3a, 0xee, 0xce, 0x2c, 0xe2,
0xb0, 0xda, 0x78, 0x3d, 0x37, 0x7, 0x2d, 0x1f,
0xf1, 0x47, 0x81, 0x4, 0x67, 0x6e, 0xd, 0xa1,
0x2b, 0x4, 0xe8, 0xd9, 0xf4, 0xaf, 0x35, 0xca,
0xa5, 0xd1, 0xe3, 0xec, 0xc5, 0x82, 0x50, 0x99,
0x9a, 0xee, 0xea, 0x53, 0x41, 0x86, 0x97, 0x44,
0xeb, 0x58, 0x43, 0x47, 0xe7, 0xa0, 0xd3, 0x28,
0xfc, 0xe7, 0x13, 0x8b, 0x56, 0xe3, 0xdb, 0xa9,
0xcd, 0x9, 0xc8, 0x7, 0x11, 0xeb, 0xbf, 0xac,
0x76, 0x72, 0x60, 0xaf, 0x9c, 0xba, 0x8a, 0x64,
0xfb, 0xf4, 0xab, 0x27, 0x29, 0xe7, 0xec, 0x69,
0x21, 0xcb, 0x5b, 0x79, 0x56, 0x10, 0xc1, 0x8,
0xd5, 0x5d, 0x93, 0xb1, 0x70, 0x88, 0xf2, 0x19,
0x41, 0xc6, 0xc2, 0x84, 0xdd, 0xf0, 0xb3, 0x40,
0x12, 0x71, 0x24, 0x54, 0xc4, 0x5e, 0xfb, 0x5f,
0x47, 0x8c, 0xa9, 0x4, 0x5a, 0xd5, 0x61, 0x19,
0xb5, 0x7f, 0xc9, 0xbd, 0x87, 0xb2, 0xcd, 0x57,
0x99, 0x50, 0x67, 0x1d, 0xb0, 0x1d, 0x82, 0xdd,
0xef, 0x32, 0x38, 0xb9, 0xc7, 0x86, 0xb4, 0xd2,
0xd6, 0xe1, 0x33, 0xb2, 0xdb, 0x5e, 0xc2, 0xa3,
0x49, 0xa6, 0x5f, 0x79, 0x32, 0x50, 0x41, 0x5b,
0xd7, 0x87, 0x74, 0xf5, 0xc9, 0x9c, 0x78, 0xb7,
0xb, 0x1f, 0x72, 0xba, 0xd9, 0x3a, 0x4d, 0x18,
0x45, 0x1d, 0xad, 0xef, 0xc4, 0xdc, 0x30, 0xe8,
0x2, 0xb1, 0x7f, 0x6c, 0x8f, 0xaa, 0xd0, 0x40,
0x17, 0xe, 0x58, 0x93, 0x42, 0x49, 0x63, 0x77,
0x48, 0x55, 0x90, 0x2f, 0x7c, 0x3b, 0xee, 0x3c,
0xac, 0xd, 0xd8, 0x72, 0x23, 0xd7, 0xa5, 0x6e,
0xb0, 0xd2, 0x91, 0x25, 0x60, 0x9a, 0x52, 0xab,
0xbd, 0x63, 0xce, 0xba, 0xda, 0xb1, 0xd7, 0xc7,
0x3d, 0x21, 0x4e, 0x9c, 0x5a, 0x1e, 0x8d, 0xf4,
0xa, 0xdb, 0xd9, 0xf, 0x20, 0x7e, 0xfb, 0xbf,
0x36, 0x9c, 0x4f, 0xbd, 0xf7, 0xdb, 0x5b, 0xa2,
0x6, 0xb2, 0x0, 0xe2, 0xa2, 0x9e, 0x4e, 0x19,
0xd4, 0x69, 0xa9, 0x51, 0x69, 0x8b, 0xf5, 0xe1,
0xad, 0x89, 0x8, 0xc5, 0x4f, 0xac, 0x1b, 0x7d,
0xe7, 0xa, 0x9, 0x7d, 0x34, 0xf5, 0x3f, 0x46,
0x80, 0xb9, 0xb9, 0x45, 0x58, 0xcd, 0x6c, 0xb5,
0x5f, 0x60, 0xeb, 0x5a, 0xe3, 0xa3, 0x8, 0x5e,
0xb1, 0xc4, 0x73, 0xc5, 0xa5, 0x67, 0x56, 0xd3,
0xc6, 0x8a, 0x55, 0x6b, 0xd7, 0xd7, 0xc, 0x20,
0xe6, 0xc, 0x73, 0x8, 0x2, 0x4b, 0xfb, 0xdd,
0x4d, 0x4e, 0xa8, 0xb8, 0xd8, 0x4b, 0x53, 0x2f,
0xc2, 0xfb, 0x5d, 0xa1, 0x6a, 0x16, 0x6b, 0xe,
0xf1, 0xa1, 0xa5, 0x5b, 0xdf, 0x9c, 0x23, 0xb5,
0x94, 0x9c, 0xae, 0x7b, 0xbe, 0x42, 0xb5, 0x79,
0x80, 0xc3, 0x43, 0x41, 0xa4, 0x1b, 0x18, 0xfc,
0x52, 0xcf, 0x43, 0xc5, 0x80, 0x7b, 0xbd, 0xc1,
0x20, 0x5e, 0x65, 0xec, 0xc5, 0xfc, 0x3, 0xec,
0x8f, 0x61, 0x66, 0xf5, 0x15, 0x67, 0xc8, 0xb6,
0xef, 0x9a, 0xba, 0xb7, 0xcb, 0x2c, 0xac, 0x1b,
0x50, 0xda, 0xb6, 0x29, 0xa4, 0x37, 0xe9, 0x96,
0xa0, 0x7, 0x7d, 0x49, 0xa6, 0xce, 0xf3, 0xf0,
0x19, 0xdf, 0x61, 0xc7, 0xa4, 0x7b, 0x5a, 0xd4,
0x99, 0xb2, 0x64, 0xe7, 0xd1, 0x6b, 0x7f, 0xe8,
0xb8, 0xd3, 0x89, 0xee, 0x96, 0xc0, 0xed, 0x5d,
0x7e, 0x48, 0x2, 0xd2, 0x25, 0xd0, 0x5, 0xef,
0x93, 0x72, 0x7c, 0x8c, 0xbd, 0x6e, 0x49, 0xd3,
0x38, 0x46, 0x1c, 0xff, 0x28, 0x4e, 0x1b, 0xad,
0x39, 0x2f, 0x65, 0x26, 0xe2, 0x70, 0x3d, 0xb8,
0x7a, 0xd3, 0x38, 0x38, 0xfc, 0x3a, 0x67, 0x78,
0xdb, 0x9, 0xcb, 0xbf, 0xc9, 0xe1, 0xee, 0x69,
0x2b, 0xd, 0xb1, 0x79, 0x13, 0xd0, 0xa5, 0x75,
0x6, 0x8, 0x79, 0xa7, 0x7c, 0xc, 0xe7, 0x1b,
0x9c, 0x36, 0x64, 0xbe, 0x20, 0x65, 0xa2, 0xd4,
0xd9, 0xc, 0x68, 0xe, 0x88, 0x2b, 0x93, 0x60,
0xf1, 0xa5, 0x82, 0xc5, 0x4d, 0x2b, 0x7d, 0x73,
0xe9, 0x13, 0x8c, 0xc1, 0x8, 0xbd, 0x21, 0x65,
0x77, 0x2f, 0x34, 0xb1, 0x97, 0x9f, 0xd8, 0x55,
0xcf, 0x75, 0xc2, 0xf2, 0x41, 0x68, 0xc1, 0x9c,
0x1c, 0xd7, 0x23, 0xbf, 0x83, 0x2a, 0x9, 0x66,
0xce, 0x8f, 0xd2, 0x12, 0x79, 0x93, 0xef, 0x8,
0x9b, 0xeb, 0x2f, 0xc, 0xe4, 0x5b, 0x71, 0x1a,
0xef, 0x11, 0x65, 0xd8, 0x6d, 0x8c, 0x59, 0x53,
0x70, 0x1d, 0xb5, 0x81, 0xff, 0xc0, 0x7d, 0x87,
0xa5, 0x21, 0x5d, 0x9f, 0x63, 0xb2, 0xe7, 0xe9,
0xd0, 0x49, 0x41, 0xc7, 0x3c, 0xe1, 0x2b, 0xb1,
0xac, 0x15, 0xcd, 0xb0, 0xa8, 0xdc, 0xae, 0x3b,
0xef, 0x32, 0x98, 0x8c, 0xc7, 0x40, 0xa6, 0x81,
0x1, 0xa1, 0x7d, 0x89, 0x46, 0x99, 0x91, 0x24,
0xce, 0xb2, 0x70, 0x82, 0x92, 0xf3, 0x60, 0x66,
0x34, 0x6, 0x37, 0xad, 0x5c, 0xed, 0xc3, 0x27,
0x68, 0x8c, 0x56, 0xe7, 0xf, 0x73, 0x5c, 0x7e,
0x9e, 0xd0, 0x8c, 0x99, 0x5a, 0xb1, 0x15, 0x98,
0xbb, 0x79, 0x9f, 0xd1, 0x69, 0xce, 0x76, 0x5,
0xcb, 0x8e, 0x18, 0xb3, 0x84, 0x65, 0xa9, 0x2,
0xbc, 0x43, 0x8b, 0x7e, 0xe9, 0xe2, 0xe6, 0x74,
0x31, 0x8d, 0xe7, 0xa2, 0x42, 0x8f, 0xca, 0x38,
0x59, 0x85, 0x25, 0x47, 0xd2, 0x86, 0x47, 0x9,
0xc2, 0x11, 0x2, 0x91, 0xe6, 0xf3, 0x47, 0xc2,
0x9c, 0x28, 0x2f, 0xbb, 0xac, 0xde, 0x9f, 0xd,
0xc2, 0x96, 0x4f, 0x43, 0xca, 0x32, 0xed, 0x34,
0xba, 0xad, 0xef, 0xbe, 0x68, 0xc7, 0xa2, 0x83,
0xaf, 0xe, 0xd3, 0x72, 0x52, 0xd1, 0x76, 0x3d,
0x9a, 0x98, 0x39, 0xf4, 0x3e, 0x14, 0x27, 0xff,
0xb2, 0x37, 0x23, 0xc5, 0x6d, 0x66, 0xef, 0xaa,
0xfe, 0xe7, 0xe4, 0x86, 0xa1, 0xe, 0x4e, 0x36,
0x64, 0xb1, 0x67, 0xf, 0x94, 0x6f, 0x77, 0xd5,
0xec, 0xe2, 0x5e, 0xc8, 0xe3, 0x64, 0x29, 0x92,
0xd, 0x20, 0x34, 0x9f, 0x19, 0x6e, 0x85, 0xf8,
0x48, 0x78, 0xb0, 0xf, 0x42, 0xb2, 0x8c, 0xea,
0xc2, 0x4d, 0xd3, 0x23, 0xb, 0x4d, 0x20, 0x33,
0xc7, 0x46, 0x0, 0x45, 0x37, 0xc6, 0xcb, 0xd0,
0xec, 0x11, 0xc6, 0x74, 0x91, 0x7d, 0x6b, 0x54,
0x56, 0x10, 0x8d, 0xd0, 0xce, 0xe8, 0x57, 0x3b,
0x83, 0xd8, 0x25, 0x51, 0x79, 0x48, 0xa, 0xa5,
0xc3, 0xe4, 0x65, 0x33, 0xb2, 0x89, 0xa6, 0x4c,
0xe8, 0xc8, 0x9e, 0xce, 0xea, 0x2a, 0x55, 0x40,
0xfc, 0x26, 0x29, 0xd4, 0x2d, 0x7e, 0xe1, 0xb1,
0x4d, 0x65, 0x1, 0xe9, 0x98, 0xc9, 0xf4, 0x69,
0x10, 0xd9, 0xa3, 0xf9, 0x34, 0xaf, 0x3c, 0x34,
0x64, 0x23, 0xde, 0xb8, 0x1c, 0x33, 0x18, 0x74,
0x67, 0xb4, 0x4a, 0x71, 0xa6, 0x89, 0x2, 0xfe,
0xf7, 0xf1, 0x32, 0xc7, 0x98, 0xad, 0xe5, 0x10,
0x98, 0x3c, 0x6c, 0xaf, 0x1f, 0x13, 0x3d, 0xcc,
0xfc, 0x3b, 0x67, 0x33, 0x34, 0xc9, 0x31, 0xcd,
0x3f, 0xd, 0x3c, 0x5a, 0xb6, 0xc2, 0x8, 0xea,
0xe2, 0xae, 0xdd, 0xfc, 0x6f, 0xca, 0xb5, 0x67,
0x11, 0xce, 0xd5, 0xda, 0x3a, 0x8b, 0x7, 0xf2,
0xc0, 0x9e, 0x78, 0x18, 0x92, 0x9f, 0x64, 0x26,
0x9f, 0x66, 0x62, 0x66, 0xa1, 0x7e, 0x3, 0xf5,
0xb9, 0xe6, 0x74, 0x20, 0x88, 0xb7, 0x7e, 0x62,
0x7a, 0x33, 0x21, 0x9, 0x9c, 0x91, 0x3b, 0x62,
0x9, 0x46, 0xd3, 0xd1, 0x1f, 0xc5, 0x3a, 0x8f,
0x69, 0x27, 0x2c, 0x7b, 0xec, 0xda, 0x79, 0xf1,
0xc9, 0xe9, 0x98, 0xd0, 0xa, 0xc9, 0xf6, 0x37,
0x28, 0xf8, 0xfc, 0xe, 0xdc, 0xf, 0xe9, 0x23,
0xf6, 0x84, 0x25, 0x96, 0x2c, 0x24, 0x14, 0xd7,
0xe2, 0x5e, 0x1c, 0x56, 0x7f, 0x99, 0x98, 0x62,
0x76, 0xcc, 0x84, 0x44, 0xd6, 0xb9, 0x47, 0x2b,
0x52, 0xfb, 0x42, 0x40, 0xf3, 0x63, 0xaf, 0xd4,
0x10, 0x5, 0xf9, 0x3b, 0xc8, 0x53, 0xa9, 0x45,
0xa4, 0x50, 0x41, 0x83, 0xe8, 0x4a, 0x9, 0xb6,
0xf1, 0x77, 0x70, 0xe3, 0x61, 0x30, 0xd8, 0x90,
0x49, 0x52, 0x4b, 0x4a, 0xf2, 0x66, 0x84, 0xaf,
0x71, 0x1, 0x40, 0x66, 0xf6, 0x3, 0xc9, 0x23,
0xb1, 0x1a, 0xc1, 0xb2, 0xf7, 0x35, 0x1a, 0xc9,
0x3a, 0x75, 0xb1, 0xa7, 0x4, 0xff, 0x69, 0xa,
0x90, 0x58, 0xd4, 0xf4, 0x16, 0x79, 0xe1, 0xae,
0x39, 0x9d, 0xbb, 0x32, 0x6b, 0x3, 0xe2, 0xf5,
0x73, 0x83, 0x7e, 0x3c, 0xf8, 0x29, 0xab, 0xcc,
0xdc, 0xf0, 0x13, 0xdb, 0x86, 0x28, 0x88, 0x8e,
0xde, 0x6a, 0x29, 0xf1, 0xea, 0x0, 0x83, 0x97,
0x1, 0x32, 0x5f, 0xaa, 0x5b, 0x1b, 0xe4, 0x87,
0xec, 0x90, 0x45, 0xc7, 0xc5, 0x6c, 0x11, 0x83,
0x95, 0xab, 0xdd, 0x71, 0x69, 0x24, 0xc, 0x5c,
0xc0, 0xf3, 0xc1, 0xb0, 0x5e, 0x1, 0x5e, 0x4,
0xa1, 0x6e, 0x6e, 0x7d, 0x3f, 0x6f, 0xbd, 0x5d,
0x9, 0x8f, 0x23, 0x53, 0x74, 0x4b, 0xa9, 0x53,
0xd2, 0x10, 0xa1, 0xc0, 0x8e, 0x18, 0xa, 0x2f,
0x88, 0x8d, 0x4b, 0xf8, 0xc2, 0x3d, 0xeb, 0x34,
0x23, 0xa, 0x80, 0xc, 0x69, 0x21, 0x3, 0xc1,
0x6f, 0xbe, 0xdf, 0xf6, 0x2c, 0x27, 0x77, 0xa2,
0xc5, 0x5c, 0x9, 0x54, 0x5d, 0x4a, 0x4c, 0xb,
0x6b, 0xb5, 0x88, 0x11, 0x42, 0x62, 0x39, 0x89,
0x9e, 0x36, 0xd3, 0x91, 0xf6, 0x70, 0x18, 0x35,
0x79, 0xaf, 0x73, 0xf3, 0x0, 0x75, 0x5a, 0xa3,
0xce, 0xf1, 0x42, 0x80, 0x19, 0x5e, 0x42, 0x56,
0x53, 0x85, 0xbb, 0xf4, 0x29, 0xac, 0x84, 0x1d,
0x97, 0x1, 0x1c, 0xc4, 0x58, 0xcb, 0x33, 0xc4,
0xdc, 0x1e, 0x59, 0x8f, 0x48, 0xa9, 0x59, 0xfd,
0xaf, 0xa3, 0x5c, 0x19, 0x17, 0x6b, 0x46, 0x2d,
0xab, 0x44, 0xa3, 0xcc, 0x1a, 0xaa, 0x23, 0x4e,
0x58, 0x37, 0x7b, 0x11, 0x14, 0xc2, 0xf1, 0xc9,
0x58, 0x99, 0xd3, 0x3c, 0xec, 0xb9, 0xbe, 0x17,
0x3c, 0x8d, 0x1c, 0x87, 0x9d, 0xe1, 0xb9, 0xad,
0x68, 0x36, 0xd5, 0xfc, 0x24, 0x9b, 0x34, 0x5,
0x26, 0xac, 0x15, 0x9f, 0xd6, 0x70, 0x74, 0x6c,
0x72, 0xf, 0x6, 0x6, 0x5a, 0xc, 0xc0, 0x78,
0x47, 0x8e, 0xcf, 0xf2, 0xce, 0x8, 0xe2, 0xa4,
0xc6, 0x7d, 0x2d, 0x70, 0x14, 0xe2, 0xc6, 0xfc,
0x63, 0x7a, 0x42, 0x8c, 0x45, 0xae, 0xe8, 0x3b,
0x30, 0x48, 0xda, 0x3e, 0x14, 0xb5, 0x8b, 0x10,
0xae, 0x56, 0xbd, 0x17, 0xdf, 0xcb, 0x63, 0xf5,
0xb, 0x2b, 0xd7, 0x34, 0x7c, 0x96, 0x43, 0xe9,
0x17, 0xd4, 0x53, 0x2b, 0x4e, 0xba, 0x61, 0x57,
0x92, 0xdb, 0xe8, 0x37, 0xf4, 0xa3, 0x59, 0x88,
0x74, 0xc2, 0x3c, 0x5d, 0x54, 0x30, 0xb9, 0x6,
0xbe, 0x75, 0x13, 0xe8, 0xf2, 0xe8, 0xcb, 0x45,
0x73, 0x70, 0xaf, 0x94, 0xe6, 0xc5, 0xb0, 0xdf,
0xd2, 0xd5, 0x57, 0x97, 0x7c, 0x97, 0xde, 0x55,
0xaf, 0xbb, 0xed, 0x19, 0x35, 0x17, 0xf4, 0x23,
0x38, 0x9c, 0xce, 0x37, 0xfe, 0xd8, 0x4e, 0xd8,
0x99, 0xba, 0x33, 0x22, 0xf2, 0xeb, 0xab, 0x97,
0xee, 0x9d, 0xab, 0x67, 0x95, 0x35, 0xdf, 0xc8,
0xb6, 0xa0, 0xf, 0x15, 0x51, 0xa9, 0x76, 0x15,
0xdd, 0xbd, 0xac, 0x12, 0xce, 0x51, 0xde, 0x68,
0x15, 0xaf, 0x27, 0xcf, 0xd1, 0xba, 0x7c, 0x17,
0xef, 0xbf, 0xbb, 0xc0, 0x6e, 0x58, 0x73, 0xf6,
0x57, 0xe1, 0x8d, 0xb0, 0x9a, 0x5a, 0x9, 0x19,
0xef, 0xdd, 0x4, 0xe1, 0x76, 0x94, 0x31, 0xd7,
0x26, 0x9f, 0x9c, 0x27, 0xc4, 0x2b, 0x4b, 0xf6,
0x3b, 0xa1, 0x8c, 0xf4, 0x21, 0xde, 0x39, 0x14,
0x5a, 0x54, 0xac, 0x95, 0x2f, 0xa0, 0x60, 0x53,
0x87, 0x5b, 0x71, 0x92, 0xae, 0xf9, 0x6c, 0x62,
0x76, 0x7e, 0x91, 0x11, 0xa6, 0xf4, 0xf2, 0xa8,
0xdf, 0xc1, 0xf6, 0x3a, 0xdb, 0x34, 0x96, 0x9,
0x71, 0xb4, 0x4, 0xfa, 0xd4, 0x3, 0x46, 0x16,
0x78, 0x41, 0x42, 0x7d, 0x15, 0x68, 0x63, 0x55,
0x23, 0x4, 0x46, 0x5d, 0xe1, 0xd8, 0xe7, 0x5f,
0x55, 0x39, 0xd2, 0x45, 0xb2, 0x0, 0x35, 0xde,
0xd8, 0x9d, 0xc7, 0x3a, 0x8f, 0x37, 0x7e, 0xe5,
0x9e, 0xcf, 0xd1, 0x6a, 0x22, 0xe1, 0x51, 0xb2,
0xe6, 0x99, 0x3e, 0x83, 0xeb, 0x34, 0x9d, 0x34,
0x7, 0x1c, 0xbe, 0x91, 0x69, 0x9e, 0xaa, 0xcb,
0x86, 0xd2, 0xb6, 0xed, 0xa5, 0x4, 0xf9, 0x7d,
0xf8, 0xba, 0x2a, 0x27, 0x38, 0xe1, 0xaa, 0x22,
0x94, 0x46, 0x1f, 0x1b, 0xcf, 0xc4, 0x78, 0x88,
0x3d, 0x50, 0x83, 0x30, 0x61, 0x87, 0xb6, 0x38,
0x5b, 0x4f, 0x5a, 0x3, 0x2d, 0x5d, 0xa6, 0x33,
0x38, 0xe7, 0x8b, 0x60, 0x1, 0x8e, 0xde, 0x69,
0x8e, 0x4d, 0x60, 0x24, 0x3b, 0x47, 0x4b, 0x56,
0xea, 0xf9, 0xc8, 0xfa, 0x2d, 0x65, 0x7b, 0xad,
0xee, 0xe4, 0x91, 0x20, 0x6f, 0x64, 0x6e, 0x81,
0x69, 0xda, 0xf5, 0x3c, 0x3d, 0xff, 0x4c, 0xe9,
0x9b, 0x4d, 0xa8, 0x67, 0x9e, 0x67, 0x7f, 0x84,
0xdb, 0x7a, 0xb7, 0x24, 0x32, 0xa0, 0x80, 0x16,
0x55, 0x2d, 0x1d, 0xc1, 0x3a, 0x19, 0xd3, 0x17,
0x74, 0x8e, 0x2a, 0x5c, 0xf6, 0x71, 0xf7, 0x25,
0x3a, 0x54, 0x28, 0xef, 0x50, 0x78, 0x14, 0x5,
0x49, 0x8a, 0xbb, 0x71, 0xb2, 0xed, 0xa2, 0x5b,
0xff, 0x2, 0xe, 0xd8, 0x1a, 0x8b, 0x3c, 0xcc,
0x58, 0x27, 0x71, 0x2d, 0xb, 0x11, 0x9f, 0x6,
0xc3, 0xfd, 0x37, 0x19, 0xdb, 0xec, 0xa5, 0x4b,
0x93, 0x81, 0xb6, 0xff, 0xd4, 0xf5, 0x7b, 0xf5,
0x49, 0x5b, 0x95, 0x9, 0xa4, 0xca, 0xa5, 0x33,
0x9a, 0xfc, 0x97, 0xec, 0x7b, 0xb, 0xb9, 0x2e,
0x3b, 0x9d, 0x52, 0xc2, 0xa2, 0x9, 0xc8, 0xbf,
0x39, 0x16, 0xce, 0x42, 0x3, 0x4b, 0xe3, 0xfc,
0xfd, 0xc, 0x37, 0x96, 0x10, 0x36, 0xad, 0x44,
0xda, 0xc5, 0x58, 0x3e, 0x78, 0x52, 0xa1, 0x65,
0xed, 0x89, 0xe7, 0xea, 0xbf, 0xa8, 0x6a, 0xf2,
0xa7, 0x8e, 0x9d, 0x1, 0x25, 0x83, 0x57, 0x5f,
0x51, 0xe6, 0xe1, 0xa4, 0x4f, 0xf6, 0x81, 0xd7,
0xe6, 0x98, 0x29, 0x98, 0x58, 0xfe, 0xda, 0x45,
0xab, 0x38, 0x6, 0x91, 0x97, 0xb7, 0xa3, 0x4f,
0x93, 0x8d, 0x8a, 0x8b, 0x5, 0xe9, 0x5, 0x98,
0x3b, 0xc4, 0xb7, 0xe1, 0x68, 0x58, 0xa0, 0x3b,
0x99, 0xea, 0x8a, 0xa9, 0xfb, 0x55, 0xe2, 0xc7,
0x1d, 0x87, 0x3, 0x40, 0x24, 0x13, 0x28, 0x6a,
0x34, 0x8a, 0xff, 0x62, 0x91, 0xb8, 0x7d, 0x28,
0x1a, 0xd2, 0xfc, 0x4e, 0xa3, 0xda, 0x66, 0x69,
0x15, 0xc0, 0xda, 0x15, 0x3e, 0x67, 0x12, 0x95,
0x6, 0x1b, 0xf4, 0x60, 0xe4, 0x39, 0x82, 0xe9,
0x2e, 0xbe, 0xab, 0x8c, 0x2c, 0x6e, 0xd6, 0x40,
0x91, 0xc0, 0x68, 0xf7, 0xa2, 0x41, 0xd0, 0xa8,
0x7, 0xab, 0x13, 0x34, 0x16, 0xf4, 0x73, 0x4f,
0x1d, 0x21, 0x1a, 0x7d, 0xad, 0x43, 0x12, 0xf,
0xb7, 0xfe, 0xa3, 0x81, 0xe9, 0xb5, 0x2d, 0xd3,
0xa, 0x29, 0xb5, 0x32, 0xcb, 0x49, 0x6f, 0x1,
0x90, 0x45, 0x62, 0xca, 0x1b, 0x66, 0x39, 0x88,
0x1c, 0xee, 0x30, 0xa8, 0xb5, 0x37, 0xd0, 0xfa,
0x46, 0x52, 0x16, 0x30, 0x17, 0xcf, 0x88, 0xd0,
0x4, 0x5d, 0xde, 0x5e, 0x4f, 0xe7, 0xa9, 0xbf,
0x3c, 0x29, 0x3a, 0x63, 0x67, 0x23, 0xb3, 0x7c,
0x51, 0x17, 0xfe, 0x8d, 0xdb, 0xc8, 0x8d, 0x70,
0xe9, 0x6f, 0x56, 0xe5, 0x44, 0xb2, 0x94, 0xeb,
0x47, 0xca, 0x3a, 0xdc, 0xe3, 0x33, 0x87, 0x9c,
0xe8, 0x89, 0x4b, 0x41, 0xb8, 0xb3, 0x69, 0xb0,
0x7f, 0xc8, 0xc7, 0x74, 0xf5, 0xcb, 0x20, 0xad,
0xea, 0xbb, 0x3d, 0x11, 0xc6, 0xc0, 0xd2, 0x88,
0x8b, 0x16, 0xee, 0x62, 0x5a, 0x4d, 0x32, 0xe7,
0x48, 0xae, 0xab, 0x5e, 0xc2, 0x83, 0xc4, 0xfc,
0xd1, 0xb9, 0x71, 0xf2, 0x9, 0x7f, 0xdc, 0xbc,
0x28, 0x74, 0xa0, 0x37, 0xa9, 0x5b, 0x6c, 0x7c,
0x9b, 0x61, 0x94, 0x88, 0xf7, 0x40, 0x84, 0x75,
0xa5, 0x50, 0xab, 0xb0, 0x92, 0x66, 0x10, 0x66,
0xf6, 0xec, 0x6b, 0x5e, 0x31, 0x9b, 0xc4, 0xfa,
0x95, 0x8b, 0xe7, 0xd4, 0xba, 0x81, 0xd2, 0x85,
0x30, 0x4, 0x8b, 0x3d, 0xfa, 0x8a, 0x8f, 0x9b,
0x54, 0x6a, 0x4d, 0x35, 0xa2, 0xe9, 0x58, 0x95,
0xe3, 0xd1, 0x71, 0xcd, 0x3a, 0x54, 0xae, 0xd9,
0x5c, 0x83, 0xd, 0x15, 0x64, 0x66, 0xee, 0x39,
0xa1, 0x85, 0xe2, 0x28, 0xf5, 0x66, 0x5f, 0xec,
0x39, 0x70, 0x96, 0x2c, 0x72, 0x9e, 0x57, 0xfd,
0x57, 0x27, 0xb7, 0xda, 0x79, 0x39, 0xd8, 0x3b,
0x2e, 0xa3, 0xb0, 0xde, 0xbf, 0x60, 0xb6, 0x42,
0x78, 0x9d, 0x8f, 0xe8, 0x1c, 0x7c, 0x45, 0x72,
0x3, 0xc4, 0xd5, 0x81, 0xf6, 0xe6, 0x9, 0x29,
0x1e, 0xcd, 0xf3, 0xe, 0xd6, 0x65, 0xee, 0x6d,
0x90, 0x17, 0x95, 0x20, 0x54, 0xf1, 0xd, 0x2f,
0xa0, 0xac, 0xe3, 0x4b, 0xfc, 0xa4, 0xdc, 0xab,
0x9d, 0x9e, 0x32, 0x63, 0x72, 0xd1, 0xb4, 0xef,
0xf1, 0x83, 0xa7, 0xd7, 0x2b, 0x1a, 0x9a, 0x9e,
0xfa, 0x1e, 0xb, 0x2b, 0xdc, 0x7b, 0x87, 0x96,
0xf, 0xdb, 0x75, 0xb9, 0x6, 0x2b, 0xd3, 0x95,
0xc5, 0xb3, 0x9, 0x53, 0x94, 0x54, 0x1f, 0xd0,
0x75, 0x5a, 0x36, 0x6a, 0x7c, 0x82, 0xdb, 0xb1,
0xa2, 0x17, 0xbc, 0xeb, 0x1f, 0xfa, 0x34, 0x3d,
0xee, 0x68, 0xee, 0x93, 0x33, 0xfb, 0xcb, 0xd2,
0xa3, 0xd1, 0x24, 0x5e, 0xf4, 0x9, 0xbe, 0x5a,
0x68, 0x9e, 0x3e, 0xd4, 0x81, 0xcd, 0xa3, 0x1e,
0x2, 0x13, 0xb4, 0x79, 0x94, 0xc9, 0xb2, 0xde,
0x56, 0xf1, 0x7b, 0x2f, 0xe2, 0x56, 0xe1, 0x10,
0xf4, 0x73, 0x2d, 0xc9, 0xca, 0x4d, 0x5f, 0x11,
0x9e, 0xd6, 0x3c, 0x73, 0x12, 0x57, 0xe9, 0x14,
0xe0, 0x8d, 0xdd, 0x4b, 0x8a, 0xbb, 0xb3, 0x78,
0xbe, 0x16, 0x94, 0x93, 0x51, 0x33, 0x7a, 0xa5,
0x41, 0x14, 0x60, 0x82, 0x94, 0x67, 0x70, 0xea,
0xe6, 0x3, 0x7f, 0xc5, 0xa0, 0x20, 0x15, 0x88,
0x53, 0xe3, 0x7e, 0x16, 0x52, 0xe4, 0xca, 0xa0,
0x6f, 0xb9, 0x68, 0x4e, 0x30, 0xb9, 0x8c, 0xe6,
0x9c, 0x5e, 0xc2, 0x93, 0xf9, 0xe1, 0x41, 0x4b,
0x18, 0x42, 0x6f, 0x8f, 0x96, 0x3d, 0x2b, 0x28,
0xd5, 0x53, 0x62, 0xdd, 0x6b, 0xd0, 0xf8, 0x2e,
0xa6, 0x97, 0xe5, 0x87, 0xc5, 0xf6, 0x96, 0x7b,
0xc4, 0x3e, 0x84, 0xc9, 0xf6, 0x34, 0x63, 0x46,
0xe1, 0x10, 0xa5, 0x91, 0x6b, 0xff, 0x10, 0x3f,
0x50, 0x2e, 0xd7, 0x39, 0x12, 0x7a, 0x15, 0x85,
0xed, 0x99, 0xdb, 0x9b, 0x99, 0x6b, 0xfa, 0xfa,
0x93, 0x7, 0x44, 0xbe, 0xbe, 0x60, 0x23, 0xc1,
0xec, 0x5c, 0xf6, 0x93, 0x38, 0xf9, 0x89, 0x0,
0xc5, 0x5f, 0x5b, 0xe2, 0x9d, 0x2b, 0xea, 0x6b,
0x2e, 0xee, 0xb7, 0x4a, 0x4e, 0x8d, 0xd0, 0x35,
0xe9, 0xc1, 0x5, 0x2b, 0x83, 0xb7, 0x72, 0x25,
0xbb, 0xbe, 0xe8, 0x15, 0xf4, 0x74, 0x69, 0x69,
0x67, 0x8c, 0x5c, 0x31, 0x79, 0x78, 0x2e, 0x43,
0x83, 0xd1, 0xdd, 0x9, 0xc3, 0xa1, 0x0, 0x13,
0x31, 0x4b, 0x86, 0xce, 0xee, 0xd7, 0xec, 0xb1,
0x2c, 0x38, 0x46, 0x68, 0x62, 0xd9, 0x84, 0xdb,
0x24, 0x62, 0x82, 0xc, 0x12, 0xb7, 0x4f, 0x86,
0x54, 0x18, 0xc6, 0xd7, 0x94, 0x8b, 0xf2, 0x4c,
0x17, 0x98, 0xaa, 0xe0,
};
const uint8_t expected_cipher_long_input_end[] = {
0x05, 0x95, 0x58, 0x7b, 0xb4, 0x60, 0x15,
0x32, 0x9f, 0x38, 0xcc, 0x98, 0x1b, 0xbe, 0x10, 0xa5, 0x06, 0x67, 0xae, 0x38,
0xbd, 0x7d, 0xb5, 0xcd, 0x58, 0x32, 0xdd, 0x9e,
0x6a, 0xde, 0xe3, 0x53,
};
void aes_ext_flash_ctr_test(uint32_t output_buf_caps)
{
mbedtls_aes_context ctx;
uint8_t nonce[16];
uint8_t key[16];
uint8_t stream_block[16];
size_t SZ = sizeof(long_input);
memset(nonce, 0x2F, 16);
memset(key, 0x1E, 16);
uint8_t *chipertext = heap_caps_malloc(SZ, output_buf_caps);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(decryptedtext);
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key, 128);
size_t offset;
// Encrypt with input buffer in external flash
offset = 0;
memset(nonce, 0x2F, 16);
mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, long_input, chipertext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_long_input_end, chipertext + SZ - 32, 32);
// Decrypt
offset = 0;
memset(nonce, 0x2F, 16);
// Decrypt with input buffer in external flash, the crypto DMA can't access this
mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, chipertext, decryptedtext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(long_input, decryptedtext, SZ);
mbedtls_aes_free(&ctx);
free(chipertext);
free(decryptedtext);
}
/* Tests how crypto DMA handles data in external memory */
TEST_CASE("mbedtls AES PSRAM tests", "[aes]")
{
aes_ctr_alignment_test(MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
aes_ctr_alignment_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
aes_ctr_alignment_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
aes_psram_one_buf_ctr_test();
}
/* Tests how crypto DMA handles data from external flash */
TEST_CASE("mbedtls AES external flash tests", "[aes]")
{
aes_ext_flash_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
aes_ext_flash_ctr_test(MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
}
#endif // CONFIG_SPIRAM_USE_MALLOC
static SemaphoreHandle_t done_sem;
static void __attribute__((unused)) aes_ctr_stream_test_task(void *pv)
{
aes_ctr_stream_test();
xSemaphoreGive(done_sem);
vTaskDelete(NULL);
}
#if CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK
TEST_CASE("mbedtls AES stack in RTC RAM", "[mbedtls]")
{
done_sem = xSemaphoreCreateBinary();
static StaticTask_t rtc_task;
size_t STACK_SIZE = 3072;
uint8_t *rtc_stack = heap_caps_calloc(STACK_SIZE, 1, MALLOC_CAP_RTCRAM);
TEST_ASSERT(esp_ptr_in_rtc_dram_fast(rtc_stack));
TEST_ASSERT_NOT_NULL(xTaskCreateStatic(aes_ctr_stream_test_task, "aes_ctr_task", STACK_SIZE, NULL,
3, rtc_stack, &rtc_task));
TEST_ASSERT_TRUE(xSemaphoreTake(done_sem, 10000 / portTICK_PERIOD_MS));
/* Give task time to cleanup before freeing stack */
vTaskDelay(1000 / portTICK_PERIOD_MS);
free(rtc_stack);
vSemaphoreDelete(done_sem);
}
#endif //CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK
#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY && CONFIG_SPIRAM_USE_MALLOC
TEST_CASE("mbedtls AES stack in PSRAM", "[mbedtls]")
{
done_sem = xSemaphoreCreateBinary();
static StaticTask_t psram_task;
size_t STACK_SIZE = 3072;
uint8_t *psram_stack = heap_caps_calloc(STACK_SIZE, 1, MALLOC_CAP_SPIRAM);
TEST_ASSERT(esp_ptr_external_ram(psram_stack));
TEST_ASSERT_NOT_NULL(xTaskCreateStatic(aes_ctr_stream_test_task, "aes_ctr_task", STACK_SIZE, NULL,
3, psram_stack, &psram_task));
TEST_ASSERT_TRUE(xSemaphoreTake(done_sem, 10000 / portTICK_PERIOD_MS));
/* Give task time to cleanup before freeing stack */
vTaskDelay(1000 / portTICK_PERIOD_MS);
free(psram_stack);
vSemaphoreDelete(done_sem);
}
#endif //CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY && CONFIG_SPIRAM_USE_MALLOC