parent
0ebd3f7c79
commit
1eb24608a0
@ -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__
|
||||||
@ -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…
Reference in new issue