Files
bootloader/apps/elftosb/common/aes128_key_wrap_unwrap.c
László Monda e6c1fce5b4 Add KBOOT.
2016-08-10 01:45:15 +02:00

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
////////////////////////////////////////////////////////////////////////////////