add tiny AES library (for future LLA use);

3.5-maint
Bryan Biedenkapp 2 years ago
parent 0ebd3f7c79
commit 1eb24608a0

@ -26,15 +26,6 @@
#*/
cmake_minimum_required(VERSION 3.16.0)
#
## dvmtest source/header files
#
file(GLOB dvmtests_SRC
"tests/nulltest.cpp"
"tests/edac/*.cpp"
"tests/p25/*.cpp"
)
option(ENABLE_TESTS "Enable compilation of test suite" off)
message(CHECK_START "Enable compilation of test suite")
if (ENABLE_TESTS)

@ -0,0 +1,768 @@
/**
* Digital Voice Modem - Host Software
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / Host Software
*
*/
//
// Based on code from the C++ AES project. (https://github.com/SergeyBel/AES)
// Licensed under the MIT License (https://opensource.org/license/MIT)
//
/*
* Copyright (C) 2019 SergeyBel
* Copyright (C) 2023 Bryan Biedenkapp N2PLL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "Defines.h"
#include "AESCrypto.h"
using namespace crypto;
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stdexcept>
#include <string>
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
const uint8_t SBOX[16][16] = {
{ 0x63U, 0x7cU, 0x77U, 0x7bU, 0xf2U, 0x6bU, 0x6fU, 0xc5U, 0x30U, 0x01U, 0x67U, 0x2bU, 0xfeU, 0xd7U, 0xabU, 0x76U },
{ 0xcaU, 0x82U, 0xc9U, 0x7dU, 0xfaU, 0x59U, 0x47U, 0xf0U, 0xadU, 0xd4U, 0xa2U, 0xafU, 0x9cU, 0xa4U, 0x72U, 0xc0U },
{ 0xb7U, 0xfdU, 0x93U, 0x26U, 0x36U, 0x3fU, 0xf7U, 0xccU, 0x34U, 0xa5U, 0xe5U, 0xf1U, 0x71U, 0xd8U, 0x31U, 0x15U },
{ 0x04U, 0xc7U, 0x23U, 0xc3U, 0x18U, 0x96U, 0x05U, 0x9aU, 0x07U, 0x12U, 0x80U, 0xe2U, 0xebU, 0x27U, 0xb2U, 0x75U },
{ 0x09U, 0x83U, 0x2cU, 0x1aU, 0x1bU, 0x6eU, 0x5aU, 0xa0U, 0x52U, 0x3bU, 0xd6U, 0xb3U, 0x29U, 0xe3U, 0x2fU, 0x84U },
{ 0x53U, 0xd1U, 0x00U, 0xedU, 0x20U, 0xfcU, 0xb1U, 0x5bU, 0x6aU, 0xcbU, 0xbeU, 0x39U, 0x4aU, 0x4cU, 0x58U, 0xcfU },
{ 0xd0U, 0xefU, 0xaaU, 0xfbU, 0x43U, 0x4dU, 0x33U, 0x85U, 0x45U, 0xf9U, 0x02U, 0x7fU, 0x50U, 0x3cU, 0x9fU, 0xa8U },
{ 0x51U, 0xa3U, 0x40U, 0x8fU, 0x92U, 0x9dU, 0x38U, 0xf5U, 0xbcU, 0xb6U, 0xdaU, 0x21U, 0x10U, 0xffU, 0xf3U, 0xd2U },
{ 0xcdU, 0x0cU, 0x13U, 0xecU, 0x5fU, 0x97U, 0x44U, 0x17U, 0xc4U, 0xa7U, 0x7eU, 0x3dU, 0x64U, 0x5dU, 0x19U, 0x73U },
{ 0x60U, 0x81U, 0x4fU, 0xdcU, 0x22U, 0x2aU, 0x90U, 0x88U, 0x46U, 0xeeU, 0xb8U, 0x14U, 0xdeU, 0x5eU, 0x0bU, 0xdbU },
{ 0xe0U, 0x32U, 0x3aU, 0x0aU, 0x49U, 0x06U, 0x24U, 0x5cU, 0xc2U, 0xd3U, 0xacU, 0x62U, 0x91U, 0x95U, 0xe4U, 0x79U },
{ 0xe7U, 0xc8U, 0x37U, 0x6dU, 0x8dU, 0xd5U, 0x4eU, 0xa9U, 0x6cU, 0x56U, 0xf4U, 0xeaU, 0x65U, 0x7aU, 0xaeU, 0x08U },
{ 0xbaU, 0x78U, 0x25U, 0x2eU, 0x1cU, 0xa6U, 0xb4U, 0xc6U, 0xe8U, 0xddU, 0x74U, 0x1fU, 0x4bU, 0xbdU, 0x8bU, 0x8aU },
{ 0x70U, 0x3eU, 0xb5U, 0x66U, 0x48U, 0x03U, 0xf6U, 0x0eU, 0x61U, 0x35U, 0x57U, 0xb9U, 0x86U, 0xc1U, 0x1dU, 0x9eU },
{ 0xe1U, 0xf8U, 0x98U, 0x11U, 0x69U, 0xd9U, 0x8eU, 0x94U, 0x9bU, 0x1eU, 0x87U, 0xe9U, 0xceU, 0x55U, 0x28U, 0xdfU },
{ 0x8cU, 0xa1U, 0x89U, 0x0dU, 0xbfU, 0xe6U, 0x42U, 0x68U, 0x41U, 0x99U, 0x2dU, 0x0fU, 0xb0U, 0x54U, 0xbbU, 0x16U }
};
const uint8_t INV_SBOX[16][16] = {
{ 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU },
{ 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU },
{ 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU },
{ 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U },
{ 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U },
{ 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U },
{ 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U },
{ 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU },
{ 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U },
{ 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU },
{ 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU },
{ 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U },
{ 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU },
{ 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU },
{ 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U },
{ 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU }
};
// Galois Multiplication lookup tables
static const uint8_t GF_MUL_TABLE[15][256] = {
{},
{},
// mul 2
{
0x00U, 0x02U, 0x04U, 0x06U, 0x08U, 0x0aU, 0x0cU, 0x0eU, 0x10U, 0x12U, 0x14U, 0x16U,
0x18U, 0x1aU, 0x1cU, 0x1eU, 0x20U, 0x22U, 0x24U, 0x26U, 0x28U, 0x2aU, 0x2cU, 0x2eU,
0x30U, 0x32U, 0x34U, 0x36U, 0x38U, 0x3aU, 0x3cU, 0x3eU, 0x40U, 0x42U, 0x44U, 0x46U,
0x48U, 0x4aU, 0x4cU, 0x4eU, 0x50U, 0x52U, 0x54U, 0x56U, 0x58U, 0x5aU, 0x5cU, 0x5eU,
0x60U, 0x62U, 0x64U, 0x66U, 0x68U, 0x6aU, 0x6cU, 0x6eU, 0x70U, 0x72U, 0x74U, 0x76U,
0x78U, 0x7aU, 0x7cU, 0x7eU, 0x80U, 0x82U, 0x84U, 0x86U, 0x88U, 0x8aU, 0x8cU, 0x8eU,
0x90U, 0x92U, 0x94U, 0x96U, 0x98U, 0x9aU, 0x9cU, 0x9eU, 0xa0U, 0xa2U, 0xa4U, 0xa6U,
0xa8U, 0xaaU, 0xacU, 0xaeU, 0xb0U, 0xb2U, 0xb4U, 0xb6U, 0xb8U, 0xbaU, 0xbcU, 0xbeU,
0xc0U, 0xc2U, 0xc4U, 0xc6U, 0xc8U, 0xcaU, 0xccU, 0xceU, 0xd0U, 0xd2U, 0xd4U, 0xd6U,
0xd8U, 0xdaU, 0xdcU, 0xdeU, 0xe0U, 0xe2U, 0xe4U, 0xe6U, 0xe8U, 0xeaU, 0xecU, 0xeeU,
0xf0U, 0xf2U, 0xf4U, 0xf6U, 0xf8U, 0xfaU, 0xfcU, 0xfeU, 0x1bU, 0x19U, 0x1fU, 0x1dU,
0x13U, 0x11U, 0x17U, 0x15U, 0x0bU, 0x09U, 0x0fU, 0x0dU, 0x03U, 0x01U, 0x07U, 0x05U,
0x3bU, 0x39U, 0x3fU, 0x3dU, 0x33U, 0x31U, 0x37U, 0x35U, 0x2bU, 0x29U, 0x2fU, 0x2dU,
0x23U, 0x21U, 0x27U, 0x25U, 0x5bU, 0x59U, 0x5fU, 0x5dU, 0x53U, 0x51U, 0x57U, 0x55U,
0x4bU, 0x49U, 0x4fU, 0x4dU, 0x43U, 0x41U, 0x47U, 0x45U, 0x7bU, 0x79U, 0x7fU, 0x7dU,
0x73U, 0x71U, 0x77U, 0x75U, 0x6bU, 0x69U, 0x6fU, 0x6dU, 0x63U, 0x61U, 0x67U, 0x65U,
0x9bU, 0x99U, 0x9fU, 0x9dU, 0x93U, 0x91U, 0x97U, 0x95U, 0x8bU, 0x89U, 0x8fU, 0x8dU,
0x83U, 0x81U, 0x87U, 0x85U, 0xbbU, 0xb9U, 0xbfU, 0xbdU, 0xb3U, 0xb1U, 0xb7U, 0xb5U,
0xabU, 0xa9U, 0xafU, 0xadU, 0xa3U, 0xa1U, 0xa7U, 0xa5U, 0xdbU, 0xd9U, 0xdfU, 0xddU,
0xd3U, 0xd1U, 0xd7U, 0xd5U, 0xcbU, 0xc9U, 0xcfU, 0xcdU, 0xc3U, 0xc1U, 0xc7U, 0xc5U,
0xfbU, 0xf9U, 0xffU, 0xfdU, 0xf3U, 0xf1U, 0xf7U, 0xf5U, 0xebU, 0xe9U, 0xefU, 0xedU,
0xe3U, 0xe1U, 0xe7U, 0xe5U
},
// mul 3
{
0x00U, 0x03U, 0x06U, 0x05U, 0x0cU, 0x0fU, 0x0aU, 0x09U, 0x18U, 0x1bU, 0x1eU, 0x1dU,
0x14U, 0x17U, 0x12U, 0x11U, 0x30U, 0x33U, 0x36U, 0x35U, 0x3cU, 0x3fU, 0x3aU, 0x39U,
0x28U, 0x2bU, 0x2eU, 0x2dU, 0x24U, 0x27U, 0x22U, 0x21U, 0x60U, 0x63U, 0x66U, 0x65U,
0x6cU, 0x6fU, 0x6aU, 0x69U, 0x78U, 0x7bU, 0x7eU, 0x7dU, 0x74U, 0x77U, 0x72U, 0x71U,
0x50U, 0x53U, 0x56U, 0x55U, 0x5cU, 0x5fU, 0x5aU, 0x59U, 0x48U, 0x4bU, 0x4eU, 0x4dU,
0x44U, 0x47U, 0x42U, 0x41U, 0xc0U, 0xc3U, 0xc6U, 0xc5U, 0xccU, 0xcfU, 0xcaU, 0xc9U,
0xd8U, 0xdbU, 0xdeU, 0xddU, 0xd4U, 0xd7U, 0xd2U, 0xd1U, 0xf0U, 0xf3U, 0xf6U, 0xf5U,
0xfcU, 0xffU, 0xfaU, 0xf9U, 0xe8U, 0xebU, 0xeeU, 0xedU, 0xe4U, 0xe7U, 0xe2U, 0xe1U,
0xa0U, 0xa3U, 0xa6U, 0xa5U, 0xacU, 0xafU, 0xaaU, 0xa9U, 0xb8U, 0xbbU, 0xbeU, 0xbdU,
0xb4U, 0xb7U, 0xb2U, 0xb1U, 0x90U, 0x93U, 0x96U, 0x95U, 0x9cU, 0x9fU, 0x9aU, 0x99U,
0x88U, 0x8bU, 0x8eU, 0x8dU, 0x84U, 0x87U, 0x82U, 0x81U, 0x9bU, 0x98U, 0x9dU, 0x9eU,
0x97U, 0x94U, 0x91U, 0x92U, 0x83U, 0x80U, 0x85U, 0x86U, 0x8fU, 0x8cU, 0x89U, 0x8aU,
0xabU, 0xa8U, 0xadU, 0xaeU, 0xa7U, 0xa4U, 0xa1U, 0xa2U, 0xb3U, 0xb0U, 0xb5U, 0xb6U,
0xbfU, 0xbcU, 0xb9U, 0xbaU, 0xfbU, 0xf8U, 0xfdU, 0xfeU, 0xf7U, 0xf4U, 0xf1U, 0xf2U,
0xe3U, 0xe0U, 0xe5U, 0xe6U, 0xefU, 0xecU, 0xe9U, 0xeaU, 0xcbU, 0xc8U, 0xcdU, 0xceU,
0xc7U, 0xc4U, 0xc1U, 0xc2U, 0xd3U, 0xd0U, 0xd5U, 0xd6U, 0xdfU, 0xdcU, 0xd9U, 0xdaU,
0x5bU, 0x58U, 0x5dU, 0x5eU, 0x57U, 0x54U, 0x51U, 0x52U, 0x43U, 0x40U, 0x45U, 0x46U,
0x4fU, 0x4cU, 0x49U, 0x4aU, 0x6bU, 0x68U, 0x6dU, 0x6eU, 0x67U, 0x64U, 0x61U, 0x62U,
0x73U, 0x70U, 0x75U, 0x76U, 0x7fU, 0x7cU, 0x79U, 0x7aU, 0x3bU, 0x38U, 0x3dU, 0x3eU,
0x37U, 0x34U, 0x31U, 0x32U, 0x23U, 0x20U, 0x25U, 0x26U, 0x2fU, 0x2cU, 0x29U, 0x2aU,
0x0bU, 0x08U, 0x0dU, 0x0eU, 0x07U, 0x04U, 0x01U, 0x02U, 0x13U, 0x10U, 0x15U, 0x16U,
0x1fU, 0x1cU, 0x19U, 0x1aU
},
{},
{},
{},
{},
{},
// mul 9
{
0x00U, 0x09U, 0x12U, 0x1bU, 0x24U, 0x2dU, 0x36U, 0x3fU, 0x48U, 0x41U, 0x5aU, 0x53U,
0x6cU, 0x65U, 0x7eU, 0x77U, 0x90U, 0x99U, 0x82U, 0x8bU, 0xb4U, 0xbdU, 0xa6U, 0xafU,
0xd8U, 0xd1U, 0xcaU, 0xc3U, 0xfcU, 0xf5U, 0xeeU, 0xe7U, 0x3bU, 0x32U, 0x29U, 0x20U,
0x1fU, 0x16U, 0x0dU, 0x04U, 0x73U, 0x7aU, 0x61U, 0x68U, 0x57U, 0x5eU, 0x45U, 0x4cU,
0xabU, 0xa2U, 0xb9U, 0xb0U, 0x8fU, 0x86U, 0x9dU, 0x94U, 0xe3U, 0xeaU, 0xf1U, 0xf8U,
0xc7U, 0xceU, 0xd5U, 0xdcU, 0x76U, 0x7fU, 0x64U, 0x6dU, 0x52U, 0x5bU, 0x40U, 0x49U,
0x3eU, 0x37U, 0x2cU, 0x25U, 0x1aU, 0x13U, 0x08U, 0x01U, 0xe6U, 0xefU, 0xf4U, 0xfdU,
0xc2U, 0xcbU, 0xd0U, 0xd9U, 0xaeU, 0xa7U, 0xbcU, 0xb5U, 0x8aU, 0x83U, 0x98U, 0x91U,
0x4dU, 0x44U, 0x5fU, 0x56U, 0x69U, 0x60U, 0x7bU, 0x72U, 0x05U, 0x0cU, 0x17U, 0x1eU,
0x21U, 0x28U, 0x33U, 0x3aU, 0xddU, 0xd4U, 0xcfU, 0xc6U, 0xf9U, 0xf0U, 0xebU, 0xe2U,
0x95U, 0x9cU, 0x87U, 0x8eU, 0xb1U, 0xb8U, 0xa3U, 0xaaU, 0xecU, 0xe5U, 0xfeU, 0xf7U,
0xc8U, 0xc1U, 0xdaU, 0xd3U, 0xa4U, 0xadU, 0xb6U, 0xbfU, 0x80U, 0x89U, 0x92U, 0x9bU,
0x7cU, 0x75U, 0x6eU, 0x67U, 0x58U, 0x51U, 0x4aU, 0x43U, 0x34U, 0x3dU, 0x26U, 0x2fU,
0x10U, 0x19U, 0x02U, 0x0bU, 0xd7U, 0xdeU, 0xc5U, 0xccU, 0xf3U, 0xfaU, 0xe1U, 0xe8U,
0x9fU, 0x96U, 0x8dU, 0x84U, 0xbbU, 0xb2U, 0xa9U, 0xa0U, 0x47U, 0x4eU, 0x55U, 0x5cU,
0x63U, 0x6aU, 0x71U, 0x78U, 0x0fU, 0x06U, 0x1dU, 0x14U, 0x2bU, 0x22U, 0x39U, 0x30U,
0x9aU, 0x93U, 0x88U, 0x81U, 0xbeU, 0xb7U, 0xacU, 0xa5U, 0xd2U, 0xdbU, 0xc0U, 0xc9U,
0xf6U, 0xffU, 0xe4U, 0xedU, 0x0aU, 0x03U, 0x18U, 0x11U, 0x2eU, 0x27U, 0x3cU, 0x35U,
0x42U, 0x4bU, 0x50U, 0x59U, 0x66U, 0x6fU, 0x74U, 0x7dU, 0xa1U, 0xa8U, 0xb3U, 0xbaU,
0x85U, 0x8cU, 0x97U, 0x9eU, 0xe9U, 0xe0U, 0xfbU, 0xf2U, 0xcdU, 0xc4U, 0xdfU, 0xd6U,
0x31U, 0x38U, 0x23U, 0x2aU, 0x15U, 0x1cU, 0x07U, 0x0eU, 0x79U, 0x70U, 0x6bU, 0x62U,
0x5dU, 0x54U, 0x4fU, 0x46U
},
{},
// mul 11
{
0x00U, 0x0bU, 0x16U, 0x1dU, 0x2cU, 0x27U, 0x3aU, 0x31U, 0x58U, 0x53U, 0x4eU, 0x45U,
0x74U, 0x7fU, 0x62U, 0x69U, 0xb0U, 0xbbU, 0xa6U, 0xadU, 0x9cU, 0x97U, 0x8aU, 0x81U,
0xe8U, 0xe3U, 0xfeU, 0xf5U, 0xc4U, 0xcfU, 0xd2U, 0xd9U, 0x7bU, 0x70U, 0x6dU, 0x66U,
0x57U, 0x5cU, 0x41U, 0x4aU, 0x23U, 0x28U, 0x35U, 0x3eU, 0x0fU, 0x04U, 0x19U, 0x12U,
0xcbU, 0xc0U, 0xddU, 0xd6U, 0xe7U, 0xecU, 0xf1U, 0xfaU, 0x93U, 0x98U, 0x85U, 0x8eU,
0xbfU, 0xb4U, 0xa9U, 0xa2U, 0xf6U, 0xfdU, 0xe0U, 0xebU, 0xdaU, 0xd1U, 0xccU, 0xc7U,
0xaeU, 0xa5U, 0xb8U, 0xb3U, 0x82U, 0x89U, 0x94U, 0x9fU, 0x46U, 0x4dU, 0x50U, 0x5bU,
0x6aU, 0x61U, 0x7cU, 0x77U, 0x1eU, 0x15U, 0x08U, 0x03U, 0x32U, 0x39U, 0x24U, 0x2fU,
0x8dU, 0x86U, 0x9bU, 0x90U, 0xa1U, 0xaaU, 0xb7U, 0xbcU, 0xd5U, 0xdeU, 0xc3U, 0xc8U,
0xf9U, 0xf2U, 0xefU, 0xe4U, 0x3dU, 0x36U, 0x2bU, 0x20U, 0x11U, 0x1aU, 0x07U, 0x0cU,
0x65U, 0x6eU, 0x73U, 0x78U, 0x49U, 0x42U, 0x5fU, 0x54U, 0xf7U, 0xfcU, 0xe1U, 0xeaU,
0xdbU, 0xd0U, 0xcdU, 0xc6U, 0xafU, 0xa4U, 0xb9U, 0xb2U, 0x83U, 0x88U, 0x95U, 0x9eU,
0x47U, 0x4cU, 0x51U, 0x5aU, 0x6bU, 0x60U, 0x7dU, 0x76U, 0x1fU, 0x14U, 0x09U, 0x02U,
0x33U, 0x38U, 0x25U, 0x2eU, 0x8cU, 0x87U, 0x9aU, 0x91U, 0xa0U, 0xabU, 0xb6U, 0xbdU,
0xd4U, 0xdfU, 0xc2U, 0xc9U, 0xf8U, 0xf3U, 0xeeU, 0xe5U, 0x3cU, 0x37U, 0x2aU, 0x21U,
0x10U, 0x1bU, 0x06U, 0x0dU, 0x64U, 0x6fU, 0x72U, 0x79U, 0x48U, 0x43U, 0x5eU, 0x55U,
0x01U, 0x0aU, 0x17U, 0x1cU, 0x2dU, 0x26U, 0x3bU, 0x30U, 0x59U, 0x52U, 0x4fU, 0x44U,
0x75U, 0x7eU, 0x63U, 0x68U, 0xb1U, 0xbaU, 0xa7U, 0xacU, 0x9dU, 0x96U, 0x8bU, 0x80U,
0xe9U, 0xe2U, 0xffU, 0xf4U, 0xc5U, 0xceU, 0xd3U, 0xd8U, 0x7aU, 0x71U, 0x6cU, 0x67U,
0x56U, 0x5dU, 0x40U, 0x4bU, 0x22U, 0x29U, 0x34U, 0x3fU, 0x0eU, 0x05U, 0x18U, 0x13U,
0xcaU, 0xc1U, 0xdcU, 0xd7U, 0xe6U, 0xedU, 0xf0U, 0xfbU, 0x92U, 0x99U, 0x84U, 0x8fU,
0xbeU, 0xb5U, 0xa8U, 0xa3U
},
{},
// mul 13
{
0x00U, 0x0dU, 0x1aU, 0x17U, 0x34U, 0x39U, 0x2eU, 0x23U, 0x68U, 0x65U, 0x72U, 0x7fU,
0x5cU, 0x51U, 0x46U, 0x4bU, 0xd0U, 0xddU, 0xcaU, 0xc7U, 0xe4U, 0xe9U, 0xfeU, 0xf3U,
0xb8U, 0xb5U, 0xa2U, 0xafU, 0x8cU, 0x81U, 0x96U, 0x9bU, 0xbbU, 0xb6U, 0xa1U, 0xacU,
0x8fU, 0x82U, 0x95U, 0x98U, 0xd3U, 0xdeU, 0xc9U, 0xc4U, 0xe7U, 0xeaU, 0xfdU, 0xf0U,
0x6bU, 0x66U, 0x71U, 0x7cU, 0x5fU, 0x52U, 0x45U, 0x48U, 0x03U, 0x0eU, 0x19U, 0x14U,
0x37U, 0x3aU, 0x2dU, 0x20U, 0x6dU, 0x60U, 0x77U, 0x7aU, 0x59U, 0x54U, 0x43U, 0x4eU,
0x05U, 0x08U, 0x1fU, 0x12U, 0x31U, 0x3cU, 0x2bU, 0x26U, 0xbdU, 0xb0U, 0xa7U, 0xaaU,
0x89U, 0x84U, 0x93U, 0x9eU, 0xd5U, 0xd8U, 0xcfU, 0xc2U, 0xe1U, 0xecU, 0xfbU, 0xf6U,
0xd6U, 0xdbU, 0xccU, 0xc1U, 0xe2U, 0xefU, 0xf8U, 0xf5U, 0xbeU, 0xb3U, 0xa4U, 0xa9U,
0x8aU, 0x87U, 0x90U, 0x9dU, 0x06U, 0x0bU, 0x1cU, 0x11U, 0x32U, 0x3fU, 0x28U, 0x25U,
0x6eU, 0x63U, 0x74U, 0x79U, 0x5aU, 0x57U, 0x40U, 0x4dU, 0xdaU, 0xd7U, 0xc0U, 0xcdU,
0xeeU, 0xe3U, 0xf4U, 0xf9U, 0xb2U, 0xbfU, 0xa8U, 0xa5U, 0x86U, 0x8bU, 0x9cU, 0x91U,
0x0aU, 0x07U, 0x10U, 0x1dU, 0x3eU, 0x33U, 0x24U, 0x29U, 0x62U, 0x6fU, 0x78U, 0x75U,
0x56U, 0x5bU, 0x4cU, 0x41U, 0x61U, 0x6cU, 0x7bU, 0x76U, 0x55U, 0x58U, 0x4fU, 0x42U,
0x09U, 0x04U, 0x13U, 0x1eU, 0x3dU, 0x30U, 0x27U, 0x2aU, 0xb1U, 0xbcU, 0xabU, 0xa6U,
0x85U, 0x88U, 0x9fU, 0x92U, 0xd9U, 0xd4U, 0xc3U, 0xceU, 0xedU, 0xe0U, 0xf7U, 0xfaU,
0xb7U, 0xbaU, 0xadU, 0xa0U, 0x83U, 0x8eU, 0x99U, 0x94U, 0xdfU, 0xd2U, 0xc5U, 0xc8U,
0xebU, 0xe6U, 0xf1U, 0xfcU, 0x67U, 0x6aU, 0x7dU, 0x70U, 0x53U, 0x5eU, 0x49U, 0x44U,
0x0fU, 0x02U, 0x15U, 0x18U, 0x3bU, 0x36U, 0x21U, 0x2cU, 0x0cU, 0x01U, 0x16U, 0x1bU,
0x38U, 0x35U, 0x22U, 0x2fU, 0x64U, 0x69U, 0x7eU, 0x73U, 0x50U, 0x5dU, 0x4aU, 0x47U,
0xdcU, 0xd1U, 0xc6U, 0xcbU, 0xe8U, 0xe5U, 0xf2U, 0xffU, 0xb4U, 0xb9U, 0xaeU, 0xa3U,
0x80U, 0x8dU, 0x9aU, 0x97U
},
// mul 14
{
0x00U, 0x0eU, 0x1cU, 0x12U, 0x38U, 0x36U, 0x24U, 0x2aU, 0x70U, 0x7eU, 0x6cU, 0x62U,
0x48U, 0x46U, 0x54U, 0x5aU, 0xe0U, 0xeeU, 0xfcU, 0xf2U, 0xd8U, 0xd6U, 0xc4U, 0xcaU,
0x90U, 0x9eU, 0x8cU, 0x82U, 0xa8U, 0xa6U, 0xb4U, 0xbaU, 0xdbU, 0xd5U, 0xc7U, 0xc9U,
0xe3U, 0xedU, 0xffU, 0xf1U, 0xabU, 0xa5U, 0xb7U, 0xb9U, 0x93U, 0x9dU, 0x8fU, 0x81U,
0x3bU, 0x35U, 0x27U, 0x29U, 0x03U, 0x0dU, 0x1fU, 0x11U, 0x4bU, 0x45U, 0x57U, 0x59U,
0x73U, 0x7dU, 0x6fU, 0x61U, 0xadU, 0xa3U, 0xb1U, 0xbfU, 0x95U, 0x9bU, 0x89U, 0x87U,
0xddU, 0xd3U, 0xc1U, 0xcfU, 0xe5U, 0xebU, 0xf9U, 0xf7U, 0x4dU, 0x43U, 0x51U, 0x5fU,
0x75U, 0x7bU, 0x69U, 0x67U, 0x3dU, 0x33U, 0x21U, 0x2fU, 0x05U, 0x0bU, 0x19U, 0x17U,
0x76U, 0x78U, 0x6aU, 0x64U, 0x4eU, 0x40U, 0x52U, 0x5cU, 0x06U, 0x08U, 0x1aU, 0x14U,
0x3eU, 0x30U, 0x22U, 0x2cU, 0x96U, 0x98U, 0x8aU, 0x84U, 0xaeU, 0xa0U, 0xb2U, 0xbcU,
0xe6U, 0xe8U, 0xfaU, 0xf4U, 0xdeU, 0xd0U, 0xc2U, 0xccU, 0x41U, 0x4fU, 0x5dU, 0x53U,
0x79U, 0x77U, 0x65U, 0x6bU, 0x31U, 0x3fU, 0x2dU, 0x23U, 0x09U, 0x07U, 0x15U, 0x1bU,
0xa1U, 0xafU, 0xbdU, 0xb3U, 0x99U, 0x97U, 0x85U, 0x8bU, 0xd1U, 0xdfU, 0xcdU, 0xc3U,
0xe9U, 0xe7U, 0xf5U, 0xfbU, 0x9aU, 0x94U, 0x86U, 0x88U, 0xa2U, 0xacU, 0xbeU, 0xb0U,
0xeaU, 0xe4U, 0xf6U, 0xf8U, 0xd2U, 0xdcU, 0xceU, 0xc0U, 0x7aU, 0x74U, 0x66U, 0x68U,
0x42U, 0x4cU, 0x5eU, 0x50U, 0x0aU, 0x04U, 0x16U, 0x18U, 0x32U, 0x3cU, 0x2eU, 0x20U,
0xecU, 0xe2U, 0xf0U, 0xfeU, 0xd4U, 0xdaU, 0xc8U, 0xc6U, 0x9cU, 0x92U, 0x80U, 0x8eU,
0xa4U, 0xaaU, 0xb8U, 0xb6U, 0x0cU, 0x02U, 0x10U, 0x1eU, 0x34U, 0x3aU, 0x28U, 0x26U,
0x7cU, 0x72U, 0x60U, 0x6eU, 0x44U, 0x4aU, 0x58U, 0x56U, 0x37U, 0x39U, 0x2bU, 0x25U,
0x0fU, 0x01U, 0x13U, 0x1dU, 0x47U, 0x49U, 0x5bU, 0x55U, 0x7fU, 0x71U, 0x63U, 0x6dU,
0xd7U, 0xd9U, 0xcbU, 0xc5U, 0xefU, 0xe1U, 0xf3U, 0xfdU, 0xa7U, 0xa9U, 0xbbU, 0xb5U,
0x9fU, 0x91U, 0x83U, 0x8dU
}
};
// Circulant MDS matrix
static const uint8_t CMDS[4][4] = { {2, 3, 1, 1}, {1, 2, 3, 1}, {1, 1, 2, 3}, {3, 1, 1, 2} };
// Inverse circulant MDS matrix
static const uint8_t INV_CMDS[4][4] = { {14, 11, 13, 9}, {9, 14, 11, 13}, {13, 9, 14, 11}, {11, 13, 9, 14} };
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the AES class.
/// </summary>
AES::AES(const AESKeyLength keyLength) {
switch (keyLength) {
case AESKeyLength::AES_128:
this->m_Nk = 4;
this->m_Nr = 10;
break;
case AESKeyLength::AES_192:
this->m_Nk = 6;
this->m_Nr = 12;
break;
case AESKeyLength::AES_256:
this->m_Nk = 8;
this->m_Nr = 14;
break;
}
}
/// <summary>
///
/// </summary>
/// <param name="in"></param>
/// <param name="inLen"></param>
/// <param name="key"></param>
/// <returns></returns>
uint8_t* AES::encryptECB(const uint8_t in[], uint32_t inLen, const uint8_t key[])
{
if (inLen % m_blockBytesLen != 0) {
throw std::length_error("Plaintext length must be divisible by " + std::to_string(m_blockBytesLen));
}
uint8_t* out = new uint8_t[inLen];
uint8_t* roundKeys = new uint8_t[4 * AES_NB * (m_Nr + 1)];
keyExpansion(key, roundKeys);
for (uint32_t i = 0; i < inLen; i += m_blockBytesLen) {
encryptBlock(in + i, out + i, roundKeys);
}
delete[] roundKeys;
return out;
}
/// <summary>
///
/// </summary>
/// <param name="in"></param>
/// <param name="inLen"></param>
/// <param name="key"></param>
/// <returns></returns>
uint8_t* AES::decryptECB(const uint8_t in[], uint32_t inLen, const uint8_t key[])
{
if (inLen % m_blockBytesLen != 0) {
throw std::length_error("Plaintext length must be divisible by " + std::to_string(m_blockBytesLen));
}
uint8_t* out = new uint8_t[inLen];
uint8_t* roundKeys = new uint8_t[4 * AES_NB * (m_Nr + 1)];
keyExpansion(key, roundKeys);
for (uint32_t i = 0; i < inLen; i += m_blockBytesLen) {
decryptBlock(in + i, out + i, roundKeys);
}
delete[] roundKeys;
return out;
}
/// <summary>
///
/// </summary>
/// <param name="in"></param>
/// <param name="inLen"></param>
/// <param name="key"></param>
/// <param name="iv"></param>
/// <returns></returns>
uint8_t* AES::encryptCBC(const uint8_t in[], uint32_t inLen, const uint8_t key[], const uint8_t* iv)
{
if (inLen % m_blockBytesLen != 0) {
throw std::length_error("Plaintext length must be divisible by " + std::to_string(m_blockBytesLen));
}
uint8_t* out = new uint8_t[inLen];
uint8_t block[m_blockBytesLen];
uint8_t* roundKeys = new uint8_t[4 * AES_NB * (m_Nr + 1)];
keyExpansion(key, roundKeys);
memcpy(block, iv, m_blockBytesLen);
for (uint32_t i = 0; i < inLen; i += m_blockBytesLen) {
xorBlocks(block, in + i, block, m_blockBytesLen);
encryptBlock(block, out + i, roundKeys);
memcpy(block, out + i, m_blockBytesLen);
}
delete[] roundKeys;
return out;
}
/// <summary>
///
/// </summary>
/// <param name="in"></param>
/// <param name="inLen"></param>
/// <param name="key"></param>
/// <param name="iv"></param>
/// <returns></returns>
uint8_t *AES::decryptCBC(const uint8_t in[], uint32_t inLen, const uint8_t key[], const uint8_t *iv)
{
if (inLen % m_blockBytesLen != 0) {
throw std::length_error("Plaintext length must be divisible by " + std::to_string(m_blockBytesLen));
}
uint8_t* out = new uint8_t[inLen];
uint8_t block[m_blockBytesLen];
uint8_t* roundKeys = new uint8_t[4 * AES_NB * (m_Nr + 1)];
keyExpansion(key, roundKeys);
memcpy(block, iv, m_blockBytesLen);
for (uint32_t i = 0; i < inLen; i += m_blockBytesLen) {
decryptBlock(in + i, out + i, roundKeys);
xorBlocks(block, out + i, out + i, m_blockBytesLen);
memcpy(block, in + i, m_blockBytesLen);
}
delete[] roundKeys;
return out;
}
/// <summary>
///
/// </summary>
/// <param name="in"></param>
/// <param name="inLen"></param>
/// <param name="key"></param>
/// <param name="iv"></param>
/// <returns></returns>
uint8_t *AES::encryptCFB(const uint8_t in[], uint32_t inLen, const uint8_t key[], const uint8_t *iv)
{
if (inLen % m_blockBytesLen != 0) {
throw std::length_error("Plaintext length must be divisible by " + std::to_string(m_blockBytesLen));
}
uint8_t* out = new uint8_t[inLen];
uint8_t block[m_blockBytesLen];
uint8_t encryptedBlock[m_blockBytesLen];
uint8_t* roundKeys = new uint8_t[4 * AES_NB * (m_Nr + 1)];
keyExpansion(key, roundKeys);
memcpy(block, iv, m_blockBytesLen);
for (uint32_t i = 0; i < inLen; i += m_blockBytesLen) {
encryptBlock(block, encryptedBlock, roundKeys);
xorBlocks(in + i, encryptedBlock, out + i, m_blockBytesLen);
memcpy(block, out + i, m_blockBytesLen);
}
delete[] roundKeys;
return out;
}
/// <summary>
///
/// </summary>
/// <param name="in"></param>
/// <param name="inLen"></param>
/// <param name="key"></param>
/// <param name="iv"></param>
/// <returns></returns>
uint8_t *AES::decryptCFB(const uint8_t in[], uint32_t inLen, const uint8_t key[], const uint8_t *iv)
{
if (inLen % m_blockBytesLen != 0) {
throw std::length_error("Plaintext length must be divisible by " + std::to_string(m_blockBytesLen));
}
uint8_t* out = new uint8_t[inLen];
uint8_t block[m_blockBytesLen];
uint8_t encryptedBlock[m_blockBytesLen];
uint8_t* roundKeys = new uint8_t[4 * AES_NB * (m_Nr + 1)];
keyExpansion(key, roundKeys);
memcpy(block, iv, m_blockBytesLen);
for (uint32_t i = 0; i < inLen; i += m_blockBytesLen) {
encryptBlock(block, encryptedBlock, roundKeys);
xorBlocks(in + i, encryptedBlock, out + i, m_blockBytesLen);
memcpy(block, in + i, m_blockBytesLen);
}
delete[] roundKeys;
return out;
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
///
/// </summary>
/// <param name="state"></param>
void AES::subBytes(uint8_t state[4][AES_NB]) {
uint8_t t;
for (uint32_t i = 0; i < 4; i++) {
for (uint32_t j = 0; j < AES_NB; j++) {
t = state[i][j];
state[i][j] = SBOX[t / 16][t % 16];
}
}
}
/// <summary>
///
/// </summary>
/// <param name="state"></param>
void AES::invSubBytes(uint8_t state[4][AES_NB])
{
uint8_t t;
for (uint32_t i = 0; i < 4; i++) {
for (uint32_t j = 0; j < AES_NB; j++) {
t = state[i][j];
state[i][j] = INV_SBOX[t / 16][t % 16];
}
}
}
/// <summary>
/// Shift row i on n positions.
/// </summary>
/// <param name="state"></param>
/// <param name="i"></param>
/// <param name="n"></param>
void AES::shiftRow(uint8_t state[4][AES_NB], uint32_t i, uint32_t n)
{
uint8_t tmp[AES_NB];
for (uint32_t j = 0; j < AES_NB; j++) {
tmp[j] = state[i][(j + n) % AES_NB];
}
memcpy(state[i], tmp, AES_NB * sizeof(uint8_t));
}
/// <summary>
///
/// </summary>
/// <param name="state"></param>
void AES::shiftRows(uint8_t state[4][AES_NB])
{
shiftRow(state, 1, 1);
shiftRow(state, 2, 2);
shiftRow(state, 3, 3);
}
/// <summary>
///
/// </summary>
/// <param name="state"></param>
void AES::invShiftRows(uint8_t state[4][AES_NB])
{
shiftRow(state, 1, AES_NB - 1);
shiftRow(state, 2, AES_NB - 2);
shiftRow(state, 3, AES_NB - 3);
}
/// <summary>
///
/// </summary>
/// <param name="state"></param>
void AES::mixColumns(uint8_t state[4][AES_NB]) {
uint8_t tempState[4][AES_NB];
for (size_t i = 0; i < 4; ++i) {
memset(tempState[i], 0, 4);
}
for (size_t i = 0; i < 4; ++i) {
for (size_t k = 0; k < 4; ++k) {
for (size_t j = 0; j < 4; ++j) {
if (CMDS[i][k] == 1)
tempState[i][j] ^= state[k][j];
else
tempState[i][j] ^= GF_MUL_TABLE[CMDS[i][k]][state[k][j]];
}
}
}
for (size_t i = 0; i < 4; ++i) {
memcpy(state[i], tempState[i], 4);
}
}
/// <summary>
///
/// </summary>
/// <param name="state"></param>
void AES::invMixColumns(uint8_t state[4][AES_NB]) {
uint8_t tempState[4][AES_NB];
for (size_t i = 0; i < 4; ++i) {
memset(tempState[i], 0, 4);
}
for (size_t i = 0; i < 4; ++i) {
for (size_t k = 0; k < 4; ++k) {
for (size_t j = 0; j < 4; ++j) {
tempState[i][j] ^= GF_MUL_TABLE[INV_CMDS[i][k]][state[k][j]];
}
}
}
for (size_t i = 0; i < 4; ++i) {
memcpy(state[i], tempState[i], 4);
}
}
/// <summary>
///
/// </summary>
/// <param name="state"></param>
/// <param name="key"></param>
void AES::addRoundKey(uint8_t state[4][AES_NB], uint8_t* key)
{
for (uint32_t i = 0; i < 4; i++) {
for (uint32_t j = 0; j < AES_NB; j++) {
state[i][j] = state[i][j] ^ key[i + 4 * j];
}
}
}
/// <summary>
///
/// </summary>
/// <param name="a"></param>
void AES::subWord(uint8_t* a)
{
for (uint32_t i = 0; i < 4; i++) {
a[i] = SBOX[a[i] / 16][a[i] % 16];
}
}
/// <summary>
///
/// </summary>
/// <param name="a"></param>
void AES::rotWord(uint8_t* a)
{
uint8_t c = a[0];
a[0] = a[1];
a[1] = a[2];
a[2] = a[3];
a[3] = c;
}
/// <summary>
///
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="c"></param>
void AES::xorWords(uint8_t* a, uint8_t* b, uint8_t* c)
{
for (uint32_t i = 0; i < 4; i++) {
c[i] = a[i] ^ b[i];
}
}
/// <summary>
///
/// </summary>
/// <param name="a"></param>
/// <param name="n"></param>
void AES::rcon(uint8_t *a, uint32_t n)
{
uint8_t c = 1;
for (uint32_t i = 0; i < n - 1; i++) {
c = xtime(c);
}
a[0] = c;
a[1] = a[2] = a[3] = 0;
}
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="w"></param>
void AES::keyExpansion(const uint8_t key[], uint8_t w[]) {
uint8_t temp[4], rcon[4];
uint32_t i = 0;
while (i < 4 * m_Nk) {
w[i] = key[i];
i++;
}
i = 4 * m_Nk;
while (i < 4 * AES_NB * (m_Nr + 1)) {
temp[0] = w[i - 4 + 0];
temp[1] = w[i - 4 + 1];
temp[2] = w[i - 4 + 2];
temp[3] = w[i - 4 + 3];
if (i / 4 % m_Nk == 0) {
rotWord(temp);
subWord(temp);
this->rcon(rcon, i / (m_Nk * 4));
xorWords(temp, rcon, temp);
} else if (m_Nk > 6 && i / 4 % m_Nk == 4) {
subWord(temp);
}
w[i + 0] = w[i - 4 * m_Nk] ^ temp[0];
w[i + 1] = w[i + 1 - 4 * m_Nk] ^ temp[1];
w[i + 2] = w[i + 2 - 4 * m_Nk] ^ temp[2];
w[i + 3] = w[i + 3 - 4 * m_Nk] ^ temp[3];
i += 4;
}
}
/// <summary>
///
/// </summary>
/// <param name="in"></param>
/// <param name="out"></param>
/// <param name="roundKeys"></param>
void AES::encryptBlock(const uint8_t in[], uint8_t out[], uint8_t* roundKeys)
{
uint8_t state[4][AES_NB];
for (uint32_t i = 0; i < 4; i++) {
for (uint32_t j = 0; j < AES_NB; j++) {
state[i][j] = in[i + 4 * j];
}
}
addRoundKey(state, roundKeys);
for (uint32_t round = 1; round <= m_Nr - 1; round++) {
subBytes(state);
shiftRows(state);
mixColumns(state);
addRoundKey(state, roundKeys + round * 4 * AES_NB);
}
subBytes(state);
shiftRows(state);
addRoundKey(state, roundKeys + m_Nr * 4 * AES_NB);
for (uint32_t i = 0; i < 4; i++) {
for (uint32_t j = 0; j < AES_NB; j++) {
out[i + 4 * j] = state[i][j];
}
}
}
/// <summary>
///
/// </summary>
/// <param name="in"></param>
/// <param name="out"></param>
/// <param name="roundKeys"></param>
void AES::decryptBlock(const uint8_t in[], uint8_t out[], uint8_t* roundKeys)
{
uint8_t state[4][AES_NB];
for (uint32_t i = 0; i < 4; i++) {
for (uint32_t j = 0; j < AES_NB; j++) {
state[i][j] = in[i + 4 * j];
}
}
addRoundKey(state, roundKeys + m_Nr * 4 * AES_NB);
for (uint32_t round = m_Nr - 1; round >= 1; round--) {
invSubBytes(state);
invShiftRows(state);
addRoundKey(state, roundKeys + round * 4 * AES_NB);
invMixColumns(state);
}
invSubBytes(state);
invShiftRows(state);
addRoundKey(state, roundKeys);
for (uint32_t i = 0; i < 4; i++) {
for (uint32_t j = 0; j < AES_NB; j++) {
out[i + 4 * j] = state[i][j];
}
}
}
/// <summary>
///
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="c"></param>
/// <param name="len"></param>
void AES::xorBlocks(const uint8_t *a, const uint8_t *b, uint8_t *c, uint32_t len)
{
for (uint32_t i = 0; i < len; i++) {
c[i] = a[i] ^ b[i];
}
}

@ -0,0 +1,104 @@
/**
* Digital Voice Modem - Host Software
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / Host Software
*
*/
//
// Based on code from the C++ AES project. (https://github.com/SergeyBel/AES)
// Licensed under the MIT License (https://opensource.org/license/MIT)
//
/*
* Copyright (C) 2019 SergeyBel
* Copyright (C) 2023 Bryan Biedenkapp N2PLL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#if !defined(__AES_CRYPTO_H__)
#define __AES_CRYPTO_H__
#include "Defines.h"
namespace crypto
{
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
const uint8_t AES_NB = 4;
/**
* AES Key Length
*/
enum class AESKeyLength { AES_128, AES_192, AES_256 };
// ---------------------------------------------------------------------------
// Class Declaration
// Implements the AES encryption algorithm.
// ---------------------------------------------------------------------------
class HOST_SW_API AES {
public:
/// <summary>Initializes a new instance of the AES class.</summary>
explicit AES(const AESKeyLength keyLength = AESKeyLength::AES_256);
uint8_t* encryptECB(const uint8_t in[], uint32_t inLen, const uint8_t key[]);
uint8_t* decryptECB(const uint8_t in[], uint32_t inLen, const uint8_t key[]);
uint8_t* encryptCBC(const uint8_t in[], uint32_t inLen, const uint8_t key[], const uint8_t* iv);
uint8_t* decryptCBC(const uint8_t in[], uint32_t inLen, const uint8_t key[], const uint8_t* iv);
uint8_t* encryptCFB(const uint8_t in[], uint32_t inLen, const uint8_t key[], const uint8_t* iv);
uint8_t* decryptCFB(const uint8_t in[], uint32_t inLen, const uint8_t key[], const uint8_t* iv);
private:
static constexpr uint32_t m_blockBytesLen = 4 * AES_NB * sizeof(uint8_t);
uint32_t m_Nk;
uint32_t m_Nr;
void subBytes(uint8_t state[4][AES_NB]);
void invSubBytes(uint8_t state[4][AES_NB]);
void shiftRow(uint8_t state[4][AES_NB], uint32_t i, uint32_t n); // shift row i on n positions
void shiftRows(uint8_t state[4][AES_NB]);
void invShiftRows(uint8_t state[4][AES_NB]);
uint8_t xtime(uint8_t b) { return (b << 1) ^ (((b >> 7) & 1) * 0x1bU); }
void mixColumns(uint8_t state[4][AES_NB]);
void invMixColumns(uint8_t state[4][AES_NB]);
void addRoundKey(uint8_t state[4][AES_NB], uint8_t* key);
void subWord(uint8_t* a);
void rotWord(uint8_t* a);
void xorWords(uint8_t* a, uint8_t* b, uint8_t* c);
void rcon(uint8_t* a, uint32_t n);
void keyExpansion(const uint8_t key[], uint8_t w[]);
void encryptBlock(const uint8_t in[], uint8_t out[], uint8_t* roundKeys);
void decryptBlock(const uint8_t in[], uint8_t out[], uint8_t* roundKeys);
void xorBlocks(const uint8_t* a, const uint8_t* b, uint8_t* c, uint32_t len);
};
} // namespace crypto
#endif // __AES_CRYPTO_H__

@ -37,6 +37,8 @@
using namespace modem;
using namespace lookups;
#if !defined(CATCH2_TEST_COMPILATION)
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
@ -1053,3 +1055,5 @@ void HostCal::printStatus()
getStatus();
}
#endif // !defined(CATCH2_TEST_COMPILATION)

@ -38,6 +38,8 @@
#include <string>
#if !defined(CATCH2_TEST_COMPILATION)
// ---------------------------------------------------------------------------
// Class Declaration
// This class implements the interactive calibration mode.
@ -80,4 +82,6 @@ private:
void printStatus();
};
#endif // !defined(CATCH2_TEST_COMPILATION)
#endif // __HOST_CAL_H__

@ -51,6 +51,8 @@ using namespace lookups;
#include <unistd.h>
#if !defined(CATCH2_TEST_COMPILATION)
#if defined(ENABLE_SETUP_TUI)
#include "host/setup/SetupApplication.h"
#include "host/setup/SetupMainWnd.h"
@ -2298,3 +2300,5 @@ uint8_t HostSetup::countErrs(uint8_t a, uint8_t b)
}
return cnt;
}
#endif // !defined(CATCH2_TEST_COMPILATION)

@ -37,6 +37,8 @@
#include <string>
#if !defined(CATCH2_TEST_COMPILATION)
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
@ -246,4 +248,6 @@ protected:
uint8_t countErrs(uint8_t a, uint8_t b);
};
#endif // !defined(CATCH2_TEST_COMPILATION)
#endif // __HOST_SETUP_H__

@ -24,6 +24,16 @@
#* along with this program; if not, write to the Free Software
#* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#*/
#
## dvmtest source/header files
#
file(GLOB dvmtests_SRC
"tests/nulltest.cpp"
"tests/crypto/*.cpp"
"tests/edac/*.cpp"
"tests/p25/*.cpp"
)
#
## dvmtest project
#

@ -0,0 +1,97 @@
/**
* Digital Voice Modem - Host Software (Test Suite)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / Host Software / Test Suite
*
*/
/*
* Copyright (C) 2023 Bryan Biedenkapp N2PLL
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Defines.h"
#include "AESCrypto.h"
#include "Log.h"
#include "Utils.h"
using namespace crypto;
#include <catch2/catch_test_macros.hpp>
#include <stdlib.h>
#include <time.h>
TEST_CASE("AES", "[LLA AM1 Test]") {
SECTION("LLA_AM1_Test") {
bool failed = false;
INFO("AES P25 LLA AM1 Test");
/*
** TIA-102.AACE-A 6.6 AM1 Sample
*/
srand((unsigned int)time(NULL));
// key (K)
uint8_t K[16] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
};
// result KS
uint8_t resultKS[16] =
{
0x05, 0x24, 0x30, 0xBD, 0xAF, 0x39, 0xE8, 0x2F,
0xD0, 0xDD, 0xD6, 0x98, 0xC0, 0x2F, 0xB0, 0x36
};
// RS
uint8_t RS[10] =
{
0x38, 0xAE, 0xC8, 0x29, 0x33, 0xB1, 0x7F, 0x80,
0x24, 0x9D
};
// expand RS to 16 bytes
uint8_t expandedRS[16];
for (uint32_t i = 0; i < 16U; i++)
expandedRS[i] = 0x00U;
for (uint32_t i = 0; i < 10U; i++)
expandedRS[i] = RS[i];
Utils::dump(2U, "LLA_AM1_Test, Expanded RS", expandedRS, 16);
// perform crypto
AES* aes = new AES(AESKeyLength::AES_128);
uint8_t* KS = aes->encryptECB(expandedRS, 16 * sizeof(uint8_t), K);
Utils::dump(2U, "LLA_AM1_Test, Const Result", resultKS, 16);
Utils::dump(2U, "LLA_AM1_Test, Result", KS, 16);
for (uint32_t i = 0; i < 16U; i++) {
if (KS[i] != resultKS[i]) {
::LogDebug("T", "LLA_AM1_Test, INVALID AT IDX %d\n", i);
failed = true;
}
}
delete aes;
REQUIRE(failed==false);
}
}

@ -0,0 +1,99 @@
/**
* Digital Voice Modem - Host Software (Test Suite)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / Host Software / Test Suite
*
*/
/*
* Copyright (C) 2023 Bryan Biedenkapp N2PLL
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Defines.h"
#include "AESCrypto.h"
#include "Log.h"
#include "Utils.h"
using namespace crypto;
#include <catch2/catch_test_macros.hpp>
#include <stdlib.h>
#include <time.h>
TEST_CASE("AES", "[LLA AM2 Test]") {
SECTION("LLA_AM2_Test") {
bool failed = false;
INFO("AES P25 LLA AM2 Test");
/*
** TIA-102.AACE-A 6.6 AM2 Sample
*/
srand((unsigned int)time(NULL));
// key (KS)
uint8_t KS[16] =
{
0x05, 0x24, 0x30, 0xBD, 0xAF, 0x39, 0xE8, 0x2F,
0xD0, 0xDD, 0xD6, 0x98, 0xC0, 0x2F, 0xB0, 0x36
};
// RES1
uint8_t resultRES1[4] =
{
0x3E, 0x00, 0xFA, 0xA8
};
// RAND1
uint8_t RAND1[5] =
{
0x4D, 0x92, 0x5A, 0xF6, 0x08
};
// expand RAND1 to 16 bytes
uint8_t expandedRAND1[16];
for (uint32_t i = 0; i < 16U; i++)
expandedRAND1[i] = 0x00U;
for (uint32_t i = 0; i < 5U; i++)
expandedRAND1[i] = RAND1[i];
// perform crypto
AES* aes = new AES(AESKeyLength::AES_128);
uint8_t* aesOut = aes->encryptECB(expandedRAND1, 16 * sizeof(uint8_t), KS);
// reduce AES output
uint8_t RES1[4];
for (uint32_t i = 0; i < 4U; i++)
RES1[i] = aesOut[i];
Utils::dump(2U, "LLA_AM2_Test, Const Result", resultRES1, 4);
Utils::dump(2U, "LLA_AM2_Test, AES Out", aesOut, 16);
Utils::dump(2U, "LLA_AM2_Test, Result", RES1, 4);
for (uint32_t i = 0; i < 4U; i++) {
if (RES1[i] != resultRES1[i]) {
::LogDebug("T", "LLA_AM2_Test, INVALID AT IDX %d\n", i);
failed = true;
}
}
delete aes;
REQUIRE(failed==false);
}
}

@ -0,0 +1,104 @@
/**
* Digital Voice Modem - Host Software (Test Suite)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / Host Software / Test Suite
*
*/
/*
* Copyright (C) 2023 Bryan Biedenkapp N2PLL
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Defines.h"
#include "AESCrypto.h"
#include "Log.h"
#include "Utils.h"
using namespace crypto;
#include <catch2/catch_test_macros.hpp>
#include <stdlib.h>
#include <time.h>
TEST_CASE("AES", "[LLA AM3 Test]") {
SECTION("LLA_AM3_Test") {
bool failed = false;
INFO("AES P25 LLA AM3 Test");
/*
** TIA-102.AACE-A 6.6 AM3 Sample
*/
srand((unsigned int)time(NULL));
// key (K)
uint8_t K[16] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
};
// result KS
uint8_t resultKS[16] =
{
0x69, 0xD5, 0xDC, 0x08, 0x02, 0x3C, 0x46, 0x52,
0xCC, 0x71, 0xD5, 0xCD, 0x1E, 0x74, 0xE1, 0x04
};
// RS
uint8_t RS[10] =
{
0x38, 0xAE, 0xC8, 0x29, 0x33, 0xB1, 0x7F, 0x80,
0x24, 0x9D
};
// expand RS to 16 bytes
uint8_t expandedRS[16];
for (uint32_t i = 0; i < 16U; i++)
expandedRS[i] = 0x00U;
for (uint32_t i = 0; i < 10U; i++)
expandedRS[i] = RS[i];
Utils::dump(2U, "LLA_AM3_Test, Expanded RS", expandedRS, 16);
// complement RS
uint8_t complementRS[16];
for (uint32_t i = 0; i < 16U; i++)
complementRS[i] = ~expandedRS[i];
Utils::dump(2U, "LLA_AM3_Test, Complement RS", complementRS, 16);
// perform crypto
AES* aes = new AES(AESKeyLength::AES_128);
uint8_t* KS = aes->encryptECB(complementRS, 16 * sizeof(uint8_t), K);
Utils::dump(2U, "LLA_AM3_Test, Const Result", resultKS, 16);
Utils::dump(2U, "LLA_AM3_Test, Result", KS, 16);
for (uint32_t i = 0; i < 16U; i++) {
if (KS[i] != resultKS[i]) {
::LogDebug("T", "LLA_AM3_Test, INVALID AT IDX %d\n", i);
failed = true;
}
}
delete aes;
REQUIRE(failed==false);
}
}

@ -0,0 +1,99 @@
/**
* Digital Voice Modem - Host Software (Test Suite)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / Host Software / Test Suite
*
*/
/*
* Copyright (C) 2023 Bryan Biedenkapp N2PLL
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Defines.h"
#include "AESCrypto.h"
#include "Log.h"
#include "Utils.h"
using namespace crypto;
#include <catch2/catch_test_macros.hpp>
#include <stdlib.h>
#include <time.h>
TEST_CASE("AES", "[LLA AM4 Test]") {
SECTION("LLA_AM4_Test") {
bool failed = false;
INFO("AES P25 LLA AM4 Test");
/*
** TIA-102.AACE-A 6.6 AM4 Sample
*/
srand((unsigned int)time(NULL));
// key (KS)
uint8_t KS[16] =
{
0x69, 0xD5, 0xDC, 0x08, 0x02, 0x3C, 0x46, 0x52,
0xCC, 0x71, 0xD5, 0xCD, 0x1E, 0x74, 0xE1, 0x04
};
// RES2
uint8_t resultRES2[4] =
{
0xB3, 0xAD, 0x16, 0xE1
};
// RAND2
uint8_t RAND2[5] =
{
0x6E, 0x78, 0x4F, 0x75, 0xBD
};
// expand RAND2 to 16 bytes
uint8_t expandedRAND2[16];
for (uint32_t i = 0; i < 16U; i++)
expandedRAND2[i] = 0x00U;
for (uint32_t i = 0; i < 5U; i++)
expandedRAND2[i] = RAND2[i];
// perform crypto
AES* aes = new AES(AESKeyLength::AES_128);
uint8_t* aesOut = aes->encryptECB(expandedRAND2, 16 * sizeof(uint8_t), KS);
// reduce AES output
uint8_t RES2[4];
for (uint32_t i = 0; i < 4U; i++)
RES2[i] = aesOut[i];
Utils::dump(2U, "LLA_AM4_Test, Const Result", resultRES2, 4);
Utils::dump(2U, "LLA_AM4_Test, AES Out", aesOut, 16);
Utils::dump(2U, "LLA_AM4_Test, Result", RES2, 4);
for (uint32_t i = 0; i < 4U; i++) {
if (RES2[i] != resultRES2[i]) {
::LogDebug("T", "LLA_AM4_Test, INVALID AT IDX %d\n", i);
failed = true;
}
}
delete aes;
REQUIRE(failed==false);
}
}
Loading…
Cancel
Save

Powered by TurnKey Linux.