310 lines
11 KiB
C
310 lines
11 KiB
C
/*
|
|
* Copyright (c) 2014, Freescale Semiconductor, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted provided that the following conditions are met:
|
|
*
|
|
* o Redistributions of source code must retain the above copyright notice, this list
|
|
* of conditions and the following disclaimer.
|
|
*
|
|
* o Redistributions in binary form must reproduce the above copyright notice, this
|
|
* list of conditions and the following disclaimer in the documentation and/or
|
|
* other materials provided with the distribution.
|
|
*
|
|
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
|
* contributors may be used to endorse or promote products derived from this
|
|
* software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#define BOOTLOADER_HOST
|
|
|
|
#include "aes128_key_wrap_unwrap.h"
|
|
#if !defined(BOOTLOADER_HOST)
|
|
#include "security/aes_security.h"
|
|
#endif
|
|
|
|
#if defined(BOOTLOADER_HOST)
|
|
// From bytes_aes.c.
|
|
extern void Cipher(unsigned char cin[], unsigned int w[], int nr, unsigned char cout[]);
|
|
extern void InvCipher(unsigned char cin[], unsigned int w[], int nr, unsigned char cout[]);
|
|
#endif
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Definitions
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//! @brief number of 64-bit data blocks
|
|
#define N 5
|
|
|
|
//! @brief 64-bit initialization vector
|
|
static const unsigned char iv[8] = { 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6 };
|
|
//! @brief 64-bit integrity check register
|
|
static unsigned char a[8];
|
|
//! @brief 8-bit array of 64-bit registers
|
|
static unsigned char r[8 * (N + 1)];
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Code
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// See aes128_key_wrap_unwrap.h for documentation on this function.
|
|
void do_aes128_key_wrap(const unsigned char plaintext[],
|
|
unsigned char wrapped_ciphertext[],
|
|
unsigned int expanded_kek[])
|
|
{
|
|
unsigned int i, j; // loop counters
|
|
unsigned char in[16]; // 128-bit temporary plaintext input vector
|
|
|
|
// step 1: initialize the byte-sized data variables
|
|
// set A = IV
|
|
// for i = 1 to n
|
|
// R[i] = P[i]
|
|
|
|
a[0] = iv[0];
|
|
a[1] = iv[1];
|
|
a[2] = iv[2];
|
|
a[3] = iv[3];
|
|
a[4] = iv[4];
|
|
a[5] = iv[5];
|
|
a[6] = iv[6];
|
|
a[7] = iv[7];
|
|
|
|
for (i = 1; i <= N; i++)
|
|
{
|
|
r[8 * i + 0] = plaintext[8 * (i - 1) + 0];
|
|
r[8 * i + 1] = plaintext[8 * (i - 1) + 1];
|
|
r[8 * i + 2] = plaintext[8 * (i - 1) + 2];
|
|
r[8 * i + 3] = plaintext[8 * (i - 1) + 3];
|
|
r[8 * i + 4] = plaintext[8 * (i - 1) + 4];
|
|
r[8 * i + 5] = plaintext[8 * (i - 1) + 5];
|
|
r[8 * i + 6] = plaintext[8 * (i - 1) + 6];
|
|
r[8 * i + 7] = plaintext[8 * (i - 1) + 7];
|
|
}
|
|
|
|
// step 2: calculate intermediate values
|
|
// for j = 0 to 5
|
|
// for i = 1 to n
|
|
// B = AES(K, A | R[i])
|
|
// A = MSB(64, B) ^ (n*j)+i
|
|
// R[i] = LSB(64, B)
|
|
|
|
for (j = 0; j <= 5; j++)
|
|
{
|
|
for (i = 1; i <= N; i++)
|
|
{
|
|
in[0] = a[0];
|
|
in[1] = a[1];
|
|
in[2] = a[2];
|
|
in[3] = a[3];
|
|
in[4] = a[4];
|
|
in[5] = a[5];
|
|
in[6] = a[6];
|
|
in[7] = a[7];
|
|
|
|
in[8] = r[8 * i + 0];
|
|
in[9] = r[8 * i + 1];
|
|
in[10] = r[8 * i + 2];
|
|
in[11] = r[8 * i + 3];
|
|
in[12] = r[8 * i + 4];
|
|
in[13] = r[8 * i + 5];
|
|
in[14] = r[8 * i + 6];
|
|
in[15] = r[8 * i + 7];
|
|
|
|
#if defined BOOTLOADER_HOST
|
|
Cipher(in, expanded_kek, 10, in); // perform aes128 encryption
|
|
#else
|
|
aes_encrypt((unsigned int *)in, expanded_kek, (unsigned int *)in);
|
|
#endif // BOOTLOADER_HOST
|
|
|
|
a[0] = in[0];
|
|
a[1] = in[1];
|
|
a[2] = in[2];
|
|
a[3] = in[3];
|
|
a[4] = in[4];
|
|
a[5] = in[5];
|
|
a[6] = in[6];
|
|
a[7] = in[7] ^ ((N * j) + i);
|
|
|
|
r[8 * i + 0] = in[8];
|
|
r[8 * i + 1] = in[9];
|
|
r[8 * i + 2] = in[10];
|
|
r[8 * i + 3] = in[11];
|
|
r[8 * i + 4] = in[12];
|
|
r[8 * i + 5] = in[13];
|
|
r[8 * i + 6] = in[14];
|
|
r[8 * i + 7] = in[15];
|
|
} // end for (i)
|
|
} // end for (j)
|
|
|
|
// step 3: output the results
|
|
// set C[0] = A
|
|
// for i = 1 to n
|
|
// C[i] = R[i]
|
|
|
|
wrapped_ciphertext[0] = a[0];
|
|
wrapped_ciphertext[1] = a[1];
|
|
wrapped_ciphertext[2] = a[2];
|
|
wrapped_ciphertext[3] = a[3];
|
|
wrapped_ciphertext[4] = a[4];
|
|
wrapped_ciphertext[5] = a[5];
|
|
wrapped_ciphertext[6] = a[6];
|
|
wrapped_ciphertext[7] = a[7];
|
|
|
|
for (i = 1; i <= N; i++)
|
|
{
|
|
wrapped_ciphertext[8 * i + 0] = r[8 * i + 0];
|
|
wrapped_ciphertext[8 * i + 1] = r[8 * i + 1];
|
|
wrapped_ciphertext[8 * i + 2] = r[8 * i + 2];
|
|
wrapped_ciphertext[8 * i + 3] = r[8 * i + 3];
|
|
wrapped_ciphertext[8 * i + 4] = r[8 * i + 4];
|
|
wrapped_ciphertext[8 * i + 5] = r[8 * i + 5];
|
|
wrapped_ciphertext[8 * i + 6] = r[8 * i + 6];
|
|
wrapped_ciphertext[8 * i + 7] = r[8 * i + 7];
|
|
}
|
|
}
|
|
|
|
//******************************************************************************
|
|
//******************************************************************************
|
|
|
|
// See aes128_key_wrap_unwrap.h for documentation on this function.
|
|
unsigned int do_aes128_key_unwrap(const unsigned char wrapped_ciphertext[],
|
|
unsigned char unwrapped_plaintext[],
|
|
unsigned int expanded_kek[])
|
|
{
|
|
signed int i, j; // loop counters
|
|
unsigned char in[16]; // 128-bit temporary ciphertext input vector
|
|
|
|
// step 1: initialize variables
|
|
// set A = C[0]
|
|
// for i = 1 to n
|
|
// R[i] = C[i]
|
|
|
|
a[0] = wrapped_ciphertext[0];
|
|
a[1] = wrapped_ciphertext[1];
|
|
a[2] = wrapped_ciphertext[2];
|
|
a[3] = wrapped_ciphertext[3];
|
|
a[4] = wrapped_ciphertext[4];
|
|
a[5] = wrapped_ciphertext[5];
|
|
a[6] = wrapped_ciphertext[6];
|
|
a[7] = wrapped_ciphertext[7];
|
|
|
|
for (i = 1; i <= N; i++)
|
|
{
|
|
r[8 * i + 0] = wrapped_ciphertext[8 * i + 0];
|
|
r[8 * i + 1] = wrapped_ciphertext[8 * i + 1];
|
|
r[8 * i + 2] = wrapped_ciphertext[8 * i + 2];
|
|
r[8 * i + 3] = wrapped_ciphertext[8 * i + 3];
|
|
r[8 * i + 4] = wrapped_ciphertext[8 * i + 4];
|
|
r[8 * i + 5] = wrapped_ciphertext[8 * i + 5];
|
|
r[8 * i + 6] = wrapped_ciphertext[8 * i + 6];
|
|
r[8 * i + 7] = wrapped_ciphertext[8 * i + 7];
|
|
}
|
|
|
|
// step 2: calculate intermediate values
|
|
// for j = 5 to 0
|
|
// for i = n to 1
|
|
// B = AES-1(K, (A ^ (n*j+i) | R[i])
|
|
// A = MSB(64, B)
|
|
// R[i] = LSB(64, B)
|
|
|
|
for (j = 5; j >= 0; j--)
|
|
{
|
|
for (i = N; i >= 1; i--)
|
|
{
|
|
in[0] = a[0];
|
|
in[1] = a[1];
|
|
in[2] = a[2];
|
|
in[3] = a[3];
|
|
in[4] = a[4];
|
|
in[5] = a[5];
|
|
in[6] = a[6];
|
|
in[7] = a[7] ^ ((N * j) + i);
|
|
|
|
in[8] = r[8 * i + 0];
|
|
in[9] = r[8 * i + 1];
|
|
in[10] = r[8 * i + 2];
|
|
in[11] = r[8 * i + 3];
|
|
in[12] = r[8 * i + 4];
|
|
in[13] = r[8 * i + 5];
|
|
in[14] = r[8 * i + 6];
|
|
in[15] = r[8 * i + 7];
|
|
|
|
#if defined BOOTLOADER_HOST
|
|
InvCipher(in, expanded_kek, 10, in); // perform aes128 decryption
|
|
#else
|
|
// TODO aes_decrypt reverses bytes(?)
|
|
aes_decrypt((unsigned int *)in, expanded_kek, (unsigned int *)in);
|
|
#endif // BOOTLOADER_HOST
|
|
|
|
a[0] = in[0];
|
|
a[1] = in[1];
|
|
a[2] = in[2];
|
|
a[3] = in[3];
|
|
a[4] = in[4];
|
|
a[5] = in[5];
|
|
a[6] = in[6];
|
|
a[7] = in[7];
|
|
|
|
r[8 * i + 0] = in[8];
|
|
r[8 * i + 1] = in[9];
|
|
r[8 * i + 2] = in[10];
|
|
r[8 * i + 3] = in[11];
|
|
r[8 * i + 4] = in[12];
|
|
r[8 * i + 5] = in[13];
|
|
r[8 * i + 6] = in[14];
|
|
r[8 * i + 7] = in[15];
|
|
} // end for (i)
|
|
} // end for (j)
|
|
|
|
// step 3: output the results
|
|
// if A == IV
|
|
// then
|
|
// for i = 1 to n
|
|
// P[i] = R[i]
|
|
// else
|
|
// return an error
|
|
|
|
unwrapped_plaintext[0] = a[0];
|
|
unwrapped_plaintext[1] = a[1];
|
|
unwrapped_plaintext[2] = a[2];
|
|
unwrapped_plaintext[3] = a[3];
|
|
unwrapped_plaintext[4] = a[4];
|
|
unwrapped_plaintext[5] = a[5];
|
|
unwrapped_plaintext[6] = a[6];
|
|
unwrapped_plaintext[7] = a[7];
|
|
|
|
for (i = 1; i <= N; i++)
|
|
{
|
|
unwrapped_plaintext[8 * i + 0] = r[8 * i + 0];
|
|
unwrapped_plaintext[8 * i + 1] = r[8 * i + 1];
|
|
unwrapped_plaintext[8 * i + 2] = r[8 * i + 2];
|
|
unwrapped_plaintext[8 * i + 3] = r[8 * i + 3];
|
|
unwrapped_plaintext[8 * i + 4] = r[8 * i + 4];
|
|
unwrapped_plaintext[8 * i + 5] = r[8 * i + 5];
|
|
unwrapped_plaintext[8 * i + 6] = r[8 * i + 6];
|
|
unwrapped_plaintext[8 * i + 7] = r[8 * i + 7];
|
|
}
|
|
|
|
if ((unwrapped_plaintext[0] == iv[0]) && (unwrapped_plaintext[1] == iv[1]) && (unwrapped_plaintext[2] == iv[2]) &&
|
|
(unwrapped_plaintext[3] == iv[3]) && (unwrapped_plaintext[4] == iv[4]) && (unwrapped_plaintext[5] == iv[5]) &&
|
|
(unwrapped_plaintext[6] == iv[6]) && (unwrapped_plaintext[7] == iv[7]))
|
|
return 0; // error-free exit
|
|
else
|
|
return -1; // error exit
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// EOF
|
|
////////////////////////////////////////////////////////////////////////////////
|