You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
769 lines
30 KiB
769 lines
30 KiB
/**
|
|
* 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];
|
|
}
|
|
}
|