Implement AES-ECB and CBC mode

This is also a huge rewrite to the GCM code to make it block cipher independent.

The AES-ECB code is basically a combination of the previous AES block cipher encryption code with new code for AES decryption.
This commit is contained in:
Ariel Abreu 2021-01-10 15:22:00 -05:00
parent 3fb5fb5389
commit 970348c1b6
No known key found for this signature in database
GPG Key ID: BB20848279B910AC
20 changed files with 1330 additions and 900 deletions

View File

@ -57,12 +57,19 @@ set(corecrypto_sources
src/ccec_points.c
src/ccn_extra.c
src/cczp_extra.c
src/ccaes_extra.c
src/ccgcm.c
src/ccsrp.c
src/ccwrap_priv.c
src/cc_priv.c
src/ccec25519.c
src/cccbc.c
src/ccccm.c
src/cccfb.c
src/cccfb8.c
src/ccctr.c
src/ccofb.c
src/ccxts.c
src/ccckg.c
)
if (DARLING)

View File

@ -253,7 +253,7 @@ int ccmode_ctr_init(const struct ccmode_ctr *ctr, ccctr_ctx *ctx,
size_t rawkey_len, const void *rawkey, const void *iv);
int ccmode_ctr_crypt(ccctr_ctx *ctx, size_t nbytes,
const void *in, void *out);
int ccmode_ctr_setctr(ccctr_ctx* ctx, ccctr_ctx *, const void* iv);
int ccmode_ctr_setctr(const struct ccmode_ctr *ctr, ccctr_ctx *ctx, const void* iv);
struct _ccmode_ctr_key {
const struct ccmode_ecb *ecb;

View File

@ -106,7 +106,7 @@ struct ccmode_ctr {
int (*init)(const struct ccmode_ctr *ctr, ccctr_ctx *ctx,
size_t key_len, const void *key, const void *iv);
int (*ctr)(ccctr_ctx *ctx, size_t nbytes, const void *in, void *out);
int (*setctr)(ccctr_ctx* ctx, ccctr_ctx *, const void* iv);
int (*setctr)(const struct ccmode_ctr *ctr, ccctr_ctx *ctx, const void* iv);
const void *custom;
};

View File

@ -0,0 +1,164 @@
#ifndef _CC_PRIVATE_CC128_H_
#define _CC_PRIVATE_CC128_H_
//
// 128-bit arithmetic
//
// TODO: take advantadge of native architecture support for 128-bit integers when available
//
#include <stdint.h>
#include <stdbool.h>
#include <corecrypto/cc.h>
#include <corecrypto/cc_priv.h>
// little endian representation of a 128-bit integer
typedef struct {
uint8_t bytes[16];
} cc128_t;
// note that this is a literal but *not* a constant
#define CC128_LITERAL16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
((cc128_t) { .bytes = { 0x ## p, 0x ## o, 0x ## n, 0x ## m, 0x ## l, 0x ## k, 0x ## j, 0x ## i, 0x ## h, 0x ## g, 0x ## f, 0x ## e, 0x ## d, 0x ## c, 0x ## b, 0x ## a, }, })
#define CC128_LITERAL15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) \
CC128_LITERAL16(0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
#define CC128_LITERAL14(a, b, c, d, e, f, g, h, i, j, k, l, m, n) \
CC128_LITERAL15(0, a, b, c, d, e, f, g, h, i, j, k, l, m, n)
#define CC128_LITERAL13(a, b, c, d, e, f, g, h, i, j, k, l, m) \
CC128_LITERAL14(0, a, b, c, d, e, f, g, h, i, j, k, l, m)
#define CC128_LITERAL12(a, b, c, d, e, f, g, h, i, j, k, l) \
CC128_LITERAL13(0, a, b, c, d, e, f, g, h, i, j, k, l)
#define CC128_LITERAL11(a, b, c, d, e, f, g, h, i, j, k) \
CC128_LITERAL12(0, a, b, c, d, e, f, g, h, i, j, k)
#define CC128_LITERAL10(a, b, c, d, e, f, g, h, i, j) \
CC128_LITERAL11(0, a, b, c, d, e, f, g, h, i, j)
#define CC128_LITERAL9(a, b, c, d, e, f, g, h, i) \
CC128_LITERAL10(0, a, b, c, d, e, f, g, h, i)
#define CC128_LITERAL8(a, b, c, d, e, f, g, h) \
CC128_LITERAL9(0, a, b, c, d, e, f, g, h)
#define CC128_LITERAL7(a, b, c, d, e, f, g) \
CC128_LITERAL8(0, a, b, c, d, e, f, g)
#define CC128_LITERAL6(a, b, c, d, e, f) \
CC128_LITERAL7(0, a, b, c, d, e, f)
#define CC128_LITERAL5(a, b, c, d, e) \
CC128_LITERAL6(0, a, b, c, d, e)
#define CC128_LITERAL4(a, b, c, d) \
CC128_LITERAL5(0, a, b, c, d)
#define CC128_LITERAL3(a, b, c) \
CC128_LITERAL4(0, a, b, c)
#define CC128_LITERAL2(a, b) \
CC128_LITERAL3(0, a, b)
#define CC128_LITERAL1(a) \
CC128_LITERAL2(0, a)
#define CC128_ZERO ((cc128_t) {0})
CC_INLINE
bool cc128_bit(const cc128_t* a, uint8_t bit_index) {
return (a->bytes[bit_index / 8] >> (bit_index % 8)) & 1;
};
CC_INLINE
void cc128_xor(const cc128_t* a, const cc128_t* b, cc128_t* output) {
cc_xor(sizeof(cc128_t), output, a, b);
};
CC_INLINE
void cc128_shift_right_once(const cc128_t* a, cc128_t* output) {
for (uint8_t i = 0; i < 15; ++i)
output->bytes[i] = ((a->bytes[i + 1] & 1) << 7) | (a->bytes[i] >> 1);
output->bytes[15] = a->bytes[15] >> 1;
};
CC_INLINE
void cc128_mul(const cc128_t* a, const cc128_t* b, cc128_t* output) {
cc128_t z = {0};
cc128_t v = *b;
for (uint8_t i = 128; i > 0; --i) {
if (cc128_bit(a, i - 1)) {
cc128_xor(&z, &v, &z);
}
bool lsb_v = cc128_bit(&v, 0);
cc128_shift_right_once(&v, &v);
if (lsb_v)
v.bytes[15] ^= 0xe1;
}
*output = z;
};
/**
* Increments the least significant word (32 bits) of the given block by 1.
*/
CC_INLINE
void cc128_lsw_increment(const cc128_t* a, cc128_t* output) {
uint32_t lsw = 0;
CC_LOAD32_LE(lsw, a->bytes);
++lsw;
CC_STORE32_LE(lsw, output->bytes);
cc_copy(12, &output->bytes[4], &a->bytes[4]);
};
/**
* Loads 128 bits from the given input buffer as a big-endian integer.
* If there aren't enough bits available (i.e. input_length * 8 is less than 16),
* the output will be padded with trailing zeros.
*/
CC_INLINE
void cc128_load_be(size_t input_length, const void* input, cc128_t* output) {
const uint8_t* real_input = input;
size_t limit = input_length < 16 ? input_length : 16;
for (size_t i = 0; i < limit; ++i)
output->bytes[15 - i] = real_input[i];
for (size_t i = limit; i < 16; ++i)
output->bytes[15 - i] = 0;
};
/**
* Stores 128 bits into the given output buffer as a big-endian integer.
* If there isn't enough space to store all 128 bits (i.e. output_length * 8 is less than 16),
* the output will be truncated to the most significant bits that fit in the output buffer.
*/
CC_INLINE
void cc128_store_be(const cc128_t* input, size_t output_length, void* output) {
uint8_t* real_output = output;
size_t limit = output_length < 16 ? output_length : 16;
for (size_t i = 0; i < limit; ++i)
real_output[i] = input->bytes[15 - i];
};
/**
* Stores the least significant given number of bits from the input block into the output block.
* The input and output blocks MUST NOT overlap.
*/
CC_INLINE
void cc128_lsbits(const cc128_t* restrict input, uint8_t bits, cc128_t* restrict output) {
*output = CC128_ZERO;
uint8_t bytes = (bits + 7) / 8;
for (uint8_t i = 0; i < bytes; ++i)
output->bytes[i] = input->bytes[i];
uint8_t final_byte_bits = bits % 8;
output->bytes[bytes - 1] &= (0xff << (8 - final_byte_bits)) >> (8 - final_byte_bits);
};
/**
* Stores the most significant given number of bits from the input block into the output block.
* The input and output blocks MUST NOT overlap.
*/
CC_INLINE
void cc128_msbits(const cc128_t* restrict input, uint8_t bits, cc128_t* restrict output) {
*output = CC128_ZERO;
uint8_t bytes = (bits + 7) / 8;
uint8_t diff = 16 - bytes;
for (uint8_t i = 0; i < bytes; ++i)
output->bytes[i] = input->bytes[i + diff];
uint8_t final_byte_bits = bits % 8;
output->bytes[bytes - 1] &= (0xff << (8 - final_byte_bits)) >> (8 - final_byte_bits);
};
#endif // _CC_PRIVATE_CC128_H_

View File

@ -1,349 +0,0 @@
#ifndef CC_PRIVATE_CCAES_EXTRA_H
#define CC_PRIVATE_CCAES_EXTRA_H
#include <corecrypto/cc.h>
#include <stdbool.h>
//
// ~~~typedefs~~~
//
// little endian representation of a 128-bit block
typedef struct {
uint8_t block[16];
} ccaes_block_128_t;
typedef struct {
uint8_t bytes[4][4];
} ccaes_state_t;
typedef struct {
uint8_t bytes[4];
} ccaes_word_t;
// `key` is a big-endian array
typedef ccaes_block_128_t (*ccaes_block_cipher_function_t)(const ccaes_block_128_t input, const size_t key_len, const uint8_t* const key);
//
// ~~~constants~~~
//
static const uint8_t ccaes_s_box[16][16] = {
{ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, },
{ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, },
{ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, },
{ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, },
{ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, },
{ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, },
{ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, },
{ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, },
{ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, },
{ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, },
{ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, },
{ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, },
{ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, },
{ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, },
{ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, },
{ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, },
};
static const uint8_t ccaes_round_constant[] = {
0x01,
0x02,
0x04,
0x08,
0x10,
0x20,
0x40,
0x80,
0x1b,
0x36,
};
//
// ~~~function declarations~~~
//
// `key` is a big-endian array
ccaes_block_128_t ccaes_block_cipher(const ccaes_block_128_t input, const size_t key_len, const uint8_t* const key);
//
// ~~~inline functions~~~
//
CC_INLINE
void ccaes_sub_bytes(const size_t len, const uint8_t* const in, uint8_t* const out) {
for (size_t i = 0; i < len; ++i)
out[i] = ccaes_s_box[(in[i] & 0xf0) >> 4][in[i] & 0x0f];
};
CC_INLINE
ccaes_state_t ccaes_shift_rows(const ccaes_state_t state) {
return (ccaes_state_t) {
.bytes = {
{ state.bytes[0][0], state.bytes[0][1], state.bytes[0][2], state.bytes[0][3], },
{ state.bytes[1][1], state.bytes[1][2], state.bytes[1][3], state.bytes[1][0], },
{ state.bytes[2][2], state.bytes[2][3], state.bytes[2][0], state.bytes[2][1], },
{ state.bytes[3][3], state.bytes[3][0], state.bytes[3][1], state.bytes[3][2], },
},
};
};
CC_INLINE
ccaes_state_t ccaes_mix_columns(const ccaes_state_t state) {
// https://en.wikipedia.org/wiki/Rijndael_MixColumns#Implementation_example
ccaes_state_t result = {0};
// hopefully the compiler is smart enough to unroll this loop
for (uint8_t i = 0; i < 4; ++i) {
uint8_t b[4] = {0};
for (uint8_t j = 0; j < 4; ++j) {
uint8_t h = state.bytes[j][i] & 0x80;
b[j] = state.bytes[j][i] << 1;
if (h)
b[j] ^= 0x1b;
}
result.bytes[0][i] = b[0] ^ state.bytes[3][i] ^ state.bytes[2][i] ^ b[1] ^ state.bytes[1][i];
result.bytes[1][i] = b[1] ^ state.bytes[0][i] ^ state.bytes[3][i] ^ b[2] ^ state.bytes[2][i];
result.bytes[2][i] = b[2] ^ state.bytes[1][i] ^ state.bytes[0][i] ^ b[3] ^ state.bytes[3][i];
result.bytes[3][i] = b[3] ^ state.bytes[2][i] ^ state.bytes[1][i] ^ b[0] ^ state.bytes[0][i];
}
return result;
};
CC_INLINE
ccaes_state_t ccaes_add_round_key(const ccaes_state_t state, const ccaes_word_t* const round_key) {
return (ccaes_state_t) {
.bytes = {
{ (state.bytes[0][0] ^ round_key[0].bytes[0]), (state.bytes[0][1] ^ round_key[1].bytes[0]), (state.bytes[0][2] ^ round_key[2].bytes[0]), (state.bytes[0][3] ^ round_key[3].bytes[0]), },
{ (state.bytes[1][0] ^ round_key[0].bytes[1]), (state.bytes[1][1] ^ round_key[1].bytes[1]), (state.bytes[1][2] ^ round_key[2].bytes[1]), (state.bytes[1][3] ^ round_key[3].bytes[1]), },
{ (state.bytes[2][0] ^ round_key[0].bytes[2]), (state.bytes[2][1] ^ round_key[1].bytes[2]), (state.bytes[2][2] ^ round_key[2].bytes[2]), (state.bytes[2][3] ^ round_key[3].bytes[2]), },
{ (state.bytes[3][0] ^ round_key[0].bytes[3]), (state.bytes[3][1] ^ round_key[1].bytes[3]), (state.bytes[3][2] ^ round_key[2].bytes[3]), (state.bytes[3][3] ^ round_key[3].bytes[3]), },
},
};
};
CC_INLINE
ccaes_state_t ccaes_read_state(const size_t len, const uint8_t* const data) {
ccaes_state_t result = {0};
for (size_t i = 0; i < len && i < 16; ++i)
result.bytes[i / 4][i % 4] = data[i];
return result;
};
CC_INLINE
void ccaes_write_state(const ccaes_state_t state, const size_t len, uint8_t* const out) {
for (size_t i = 0; i < len && i < 16; ++i)
out[i] = state.bytes[i / 4][i % 4];
};
CC_INLINE
void ccaes_read_column(ccaes_state_t* const state, const size_t column, const uint8_t* const data) {
for (size_t i = 0; i < 4; ++i)
state->bytes[i][column] = data[i];
};
CC_INLINE
void ccaes_write_column(const ccaes_state_t state, const size_t column, uint8_t* const out) {
for (size_t i = 0; i < 4; ++i)
out[i] = state.bytes[i][column];
};
CC_INLINE
size_t ccaes_round_count(const size_t key_len) {
if (key_len == 16)
return 10;
if (key_len == 24)
return 12;
if (key_len == 32)
return 14;
return 0;
};
CC_INLINE
ccaes_word_t ccaes_rot_word(const ccaes_word_t word) {
return (ccaes_word_t) {
.bytes = { word.bytes[1], word.bytes[2], word.bytes[3], word.bytes[0] },
};
};
CC_INLINE
ccaes_word_t ccaes_xor_word(const ccaes_word_t x, const ccaes_word_t y) {
return (ccaes_word_t) {
.bytes = { x.bytes[0] ^ y.bytes[0], x.bytes[1] ^ y.bytes[1], x.bytes[2] ^ y.bytes[2], x.bytes[3] ^ y.bytes[3] },
};
};
// get the bit at the specified 0-based index
CC_INLINE
bool ccaes_bit_128(const ccaes_block_128_t block, const uint8_t index) {
return (block.block[index / 8] >> (index % 8)) & 1;
};
CC_INLINE
ccaes_block_128_t ccaes_xor_128(const ccaes_block_128_t x, const ccaes_block_128_t y) {
return (ccaes_block_128_t) {
.block = {
x.block[ 0] ^ y.block[ 0],
x.block[ 1] ^ y.block[ 1],
x.block[ 2] ^ y.block[ 2],
x.block[ 3] ^ y.block[ 3],
x.block[ 4] ^ y.block[ 4],
x.block[ 5] ^ y.block[ 5],
x.block[ 6] ^ y.block[ 6],
x.block[ 7] ^ y.block[ 7],
x.block[ 8] ^ y.block[ 8],
x.block[ 9] ^ y.block[ 9],
x.block[10] ^ y.block[10],
x.block[11] ^ y.block[11],
x.block[12] ^ y.block[12],
x.block[13] ^ y.block[13],
x.block[14] ^ y.block[14],
x.block[15] ^ y.block[15],
},
};
};
// shift right by a single bit (i.e. `>> 1`)
CC_INLINE
ccaes_block_128_t ccaes_shift_right_128(const ccaes_block_128_t block) {
ccaes_block_128_t result = {0};
for (uint8_t i = 0; i < 15; ++i)
result.block[i] = (block.block[i] >> 1) | ((block.block[i + 1] & 1) << 7);
result.block[15] = block.block[15] >> 1;
return result;
};
CC_INLINE
ccaes_block_128_t ccaes_most_significant_bits_128(const ccaes_block_128_t block, const uint8_t bits) {
const uint8_t bytes = (bits + 7) / 8;
ccaes_block_128_t result = {0};
const uint8_t diff = 16 - bytes;
for (uint8_t i = 0; i < bytes; ++i)
result.block[i] = block.block[i + diff];
const uint8_t final_byte_bits = bits % 8;
result.block[bytes - 1] &= (0xff << (8 - final_byte_bits)) >> (8 - final_byte_bits);
return result;
};
CC_INLINE
ccaes_block_128_t ccaes_least_significant_bits_128(const ccaes_block_128_t block, const uint8_t bits) {
ccaes_block_128_t result = {0};
const uint8_t bytes = (bits + 7) / 8;
for (uint8_t i = 0; i < bytes; ++i)
result.block[i] = block.block[i];
const uint8_t final_byte_bits = bits % 8;
result.block[bytes - 1] &= (0xff << (8 - final_byte_bits)) >> (8 - final_byte_bits);
return result;
};
// increment the least significant `bits` number of bits of `block`
CC_INLINE
ccaes_block_128_t ccaes_increment_128(const ccaes_block_128_t block, const uint8_t bits) {
ccaes_block_128_t result = block;
const uint8_t bytes = (bits + 7) / 8;
uint8_t carry = 1;
for (uint8_t i = 0; i < bytes - 1; ++i) {
const uint8_t sum = result.block[i] + carry;
carry = (sum < result.block[i]) ? 1 : 0;
result.block[i] = sum;
}
const uint8_t final_byte_bits = bits - ((bytes - 1) * 8);
const uint8_t mask = (0xff << (8 - final_byte_bits)) >> (8 - final_byte_bits);
result.block[bytes - 1] = (result.block[bytes - 1] & ~mask) | ((result.block[bytes - 1] + carry) & mask);
return result;
};
CC_INLINE
ccaes_block_128_t ccaes_multiply_128(const ccaes_block_128_t x, const ccaes_block_128_t y) {
ccaes_block_128_t z = {0};
ccaes_block_128_t v = y;
for (uint8_t i = 128; i > 0; --i) {
if (ccaes_bit_128(x, i - 1))
z = ccaes_xor_128(z, v);
const bool lsb_v = ccaes_bit_128(v, 0);
v = ccaes_shift_right_128(v);
if (lsb_v)
v.block[15] ^= 0xe1;
}
return z;
};
CC_INLINE
ccaes_block_128_t ccaes_power_128(const ccaes_block_128_t block, const size_t power) {
if (power == 0) {
return (ccaes_block_128_t) {
.block = {
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
},
};
}
ccaes_block_128_t result = block;
for (size_t i = 0; i < power - 1; ++i)
result = ccaes_multiply_128(result, block);
return result;
};
// creates a 128-bit block from the leading bytes of `data`,
// regardless of whether `data` actually has 128-bits of data available
//
// (assumes that `data` is big-endian)
//
// this could actually be named `ccaes_read_block_128`
CC_INLINE
ccaes_block_128_t ccaes_normalize_128(const size_t len, const uint8_t* const data) {
ccaes_block_128_t result = {0};
for (size_t i = 0; i < len && i < 16; ++i)
result.block[15 - i] = data[i];
return result;
};
// writes the given block to the output array in big-endian byte order
CC_INLINE
void ccaes_write_block_128(ccaes_block_128_t block, const size_t out_len, uint8_t* const out) {
for (size_t i = 0; i < out_len && i < 16; ++i)
out[i] = block.block[15 - i];
};
#endif // CC_PRIVATE_CCAES_EXTRA_H

View File

@ -1,82 +0,0 @@
#ifndef CC_PRIVATE_CCGCM_H
#define CC_PRIVATE_CCGCM_H
#include <corecrypto/private/ccaes_extra.h>
#include <corecrypto/ccmode_impl.h>
//
// ~~~constants~~~
//
#define CCGCM_MODE_INITIALIZE 0
#define CCGCM_MODE_IV 1
#define CCGCM_MODE_AAD 2
#define CCGCM_MODE_CIPHERTEXT 3
#define CCGCM_MODE_FINALIZE 4
//
// ~~~typedefs~~~
//
typedef struct {
// true if decrypting, false if encrypting
bool decrypting;
// initialize, IV, AAD, ciphertext, or finalize mode
uint8_t mode;
size_t key_len;
const uint8_t* key;
size_t total_iv_length;
size_t total_cipher_length;
size_t total_aad_length;
uint8_t current_iv[12];
// hash subkey
ccaes_block_128_t hash_subkey;
// initial counter block
ccaes_block_128_t initial_cb;
// cumulative hash block
ccaes_block_128_t hash;
// most recent block of data (IV, AAD, or ciphertext, depending on which mode we're in)
ccaes_block_128_t cache;
// current counter block
// (used for ciphertext generation)
ccaes_block_128_t cb;
// cached result of processing the current counter block with the block cipher function
ccaes_block_128_t processed_cb;
} ccgcm_state;
//
// ~~~function declarations~~~
//
// input_len should be a multiple of 16, otherwise you may receive unexpected results!
// (however the function will not error if it is not, you will simply receive possibly
// erroneous results)
ccaes_block_128_t ccgcm_ghash_128(const ccaes_block_128_t hash_subkey, const size_t input_len, const uint8_t* const input);
int ccgcm_gctr_128(const ccaes_block_cipher_function_t block_cipher_function, const size_t key_len, const uint8_t* const key, const ccaes_block_128_t icb, const size_t input_len, const uint8_t* const input, uint8_t* const output);
int ccgcm_internal_init(const struct ccmode_gcm* gcm, ccgcm_ctx* ctx, size_t key_len, const void* key);
int ccgcm_internal_set_iv(ccgcm_ctx* ctx, size_t iv_size, const void* iv);
int ccgcm_internal_gmac(ccgcm_ctx* ctx, size_t nbytes, const void* in);
int ccgcm_internal_gcm(ccgcm_ctx* ctx, size_t nbytes, const void* in, void* out);
int ccgcm_internal_finalize(ccgcm_ctx* key, size_t tag_size, void* tag);
int ccgcm_internal_reset(ccgcm_ctx* ctx);
void ccgcm_process_iv(ccgcm_state* ctx);
#endif // CC_PRIVATE_CCGCM_H

View File

@ -0,0 +1,15 @@
#ifndef CC_PRIVATE_CCSTUBS_H
#define CC_PRIVATE_CCSTUBS_H
#include <stdio.h>
#include <corecrypto/cc_error.h>
#define CC_STUB(return_value) \
printf("DARLING CORECRYPTO STUB: %s\n", __FUNCTION__); \
return return_value;
#define CC_STUB_VOID() CC_STUB(;)
#define CC_STUB_ERR() CC_STUB(CCERR_INTERNAL)
#endif // CC_PRIVATE_CCSTUBS_H

View File

@ -1,102 +1,491 @@
#include <corecrypto/ccaes.h>
#include <corecrypto/private/ccgcm.h>
#include <corecrypto/ccmode_factory.h>
#include <corecrypto/cc_error.h>
#include <corecrypto/private/ccstubs.h>
#include <stdio.h>
static const struct ccmode_gcm ccaes_gcm_encrypt = {
.size = sizeof(ccgcm_state),
.encdec = CCMODE_GCM_ENCRYPTOR,
typedef struct {
uint8_t bytes[4][4];
} ccaes_state_t;
typedef struct {
uint8_t bytes[4];
} ccaes_word_t;
CCMODE_GCM_FACTORY(aes, encrypt);
CCMODE_GCM_FACTORY(aes, decrypt);
CCMODE_CBC_FACTORY(aes, encrypt);
CCMODE_CBC_FACTORY(aes, decrypt);
CCMODE_CFB_FACTORY(aes, cfb, encrypt);
CCMODE_CFB_FACTORY(aes, cfb, decrypt);
CCMODE_CFB_FACTORY(aes, cfb8, encrypt);
CCMODE_CFB_FACTORY(aes, cfb8, decrypt);
CCMODE_XTS_FACTORY(aes, encrypt);
CCMODE_XTS_FACTORY(aes, decrypt);
CCMODE_CCM_FACTORY(aes, encrypt);
CCMODE_CCM_FACTORY(aes, decrypt);
CCMODE_CTR_FACTORY(aes);
CCMODE_OFB_FACTORY(aes);
static int ccaes_ecb_init(const struct ccmode_ecb* info, ccecb_ctx* ctx, size_t key_size, const void* key);
static int ccaes_ecb_encrypt(const ccecb_ctx* ctx, size_t block_count, const void* in, void* out);
static int ccaes_ecb_decrypt(const ccecb_ctx* ctx, size_t block_count, const void* in, void* out);
struct the_real_ccecb_ctx {
uint8_t round_count;
// allocate enough space for the maximum number of round keys
ccaes_word_t round_keys[4 * 15];
};
static const struct ccmode_ecb ccaes_ecb_encrypt_info = {
.block_size = 16,
.init = ccgcm_internal_init,
.set_iv = ccgcm_internal_set_iv,
.gmac = ccgcm_internal_gmac,
.gcm = ccgcm_internal_gcm,
.finalize = ccgcm_internal_finalize,
.reset = ccgcm_internal_reset,
.custom = NULL,
.size = sizeof(struct the_real_ccecb_ctx),
.init = ccaes_ecb_init,
.ecb = ccaes_ecb_encrypt,
};
static const struct ccmode_gcm ccaes_gcm_decrypt = {
.size = sizeof(ccgcm_state),
.encdec = CCMODE_GCM_DECRYPTOR,
static const struct ccmode_ecb ccaes_ecb_decrypt_info = {
.block_size = 16,
.init = ccgcm_internal_init,
.set_iv = ccgcm_internal_set_iv,
.gmac = ccgcm_internal_gmac,
.gcm = ccgcm_internal_gcm,
.finalize = ccgcm_internal_finalize,
.reset = ccgcm_internal_reset,
.custom = NULL,
.size = sizeof(struct the_real_ccecb_ctx),
.init = ccaes_ecb_init,
.ecb = ccaes_ecb_decrypt,
};
const struct ccmode_ecb *ccaes_ecb_encrypt_mode(void) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
}
const struct ccmode_cbc *ccaes_cbc_encrypt_mode(void) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
}
const struct ccmode_cfb *ccaes_cfb_encrypt_mode(void) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
}
const struct ccmode_cfb8 *ccaes_cfb8_encrypt_mode(void) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
}
const struct ccmode_xts *ccaes_xts_encrypt_mode(void) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
}
const struct ccmode_gcm* ccaes_gcm_encrypt_mode(void) {
return &ccaes_gcm_encrypt;
const struct ccmode_ecb* ccaes_ecb_encrypt_mode(void) {
return &ccaes_ecb_encrypt_info;
};
const struct ccmode_ccm *ccaes_ccm_encrypt_mode(void) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
}
const struct ccmode_ecb *ccaes_ecb_decrypt_mode(void) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
}
const struct ccmode_cbc *ccaes_cbc_decrypt_mode(void) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
}
const struct ccmode_cfb *ccaes_cfb_decrypt_mode(void) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
}
const struct ccmode_cfb8 *ccaes_cfb8_decrypt_mode(void) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
}
const struct ccmode_xts *ccaes_xts_decrypt_mode(void) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
}
const struct ccmode_gcm* ccaes_gcm_decrypt_mode(void) {
return &ccaes_gcm_decrypt;
const struct ccmode_ecb* ccaes_ecb_decrypt_mode(void) {
return &ccaes_ecb_decrypt_info;
};
const struct ccmode_ccm *ccaes_ccm_decrypt_mode(void) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
}
static const uint8_t ccaes_s_box[] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
};
const struct ccmode_ctr *ccaes_ctr_crypt_mode(void) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
}
static const uint8_t ccaes_s_box_inverse[] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
};
const struct ccmode_ofb *ccaes_ofb_crypt_mode(void) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
}
static const uint8_t gmul_2[] = {
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,
0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25,
0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45,
0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,
0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5,
};
const struct ccmode_siv *ccaes_siv_encrypt_mode(void) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
}
static const uint8_t gmul_3[] = {
0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41,
0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1,
0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1,
0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1,
0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81,
0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a,
0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba,
0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea,
0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda,
0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a,
0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a,
0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a,
};
const struct ccmode_siv *ccaes_siv_decrypt_mode(void) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
}
static const uint8_t gmul_9[] = {
0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7,
0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc,
0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01,
0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91,
0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a,
0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa,
0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b,
0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b,
0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0,
0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30,
0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,
0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,
0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46,
};
static const uint8_t gmul_11[] = {
0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69,
0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9,
0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12,
0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2,
0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f,
0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f,
0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4,
0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54,
0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e,
0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e,
0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5,
0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55,
0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68,
0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8,
0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3,
};
static const uint8_t gmul_13[] = {
0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b,
0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b,
0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0,
0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20,
0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26,
0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6,
0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d,
0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d,
0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91,
0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41,
0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a,
0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa,
0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc,
0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c,
0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97,
};
static const uint8_t gmul_14[] = {
0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a,
0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba,
0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81,
0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61,
0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7,
0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17,
0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c,
0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc,
0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b,
0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb,
0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0,
0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20,
0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6,
0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56,
0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d,
};
static const uint8_t ccaes_round_constant[] = {
0x01,
0x02,
0x04,
0x08,
0x10,
0x20,
0x40,
0x80,
0x1b,
0x36,
};
CC_INLINE
size_t ccaes_round_count(const size_t key_len) {
if (key_len == 16)
return 10;
if (key_len == 24)
return 12;
if (key_len == 32)
return 14;
return 0;
};
CC_INLINE
ccaes_word_t ccaes_rot_word(const ccaes_word_t word) {
return (ccaes_word_t) {
.bytes = { word.bytes[1], word.bytes[2], word.bytes[3], word.bytes[0] },
};
};
CC_INLINE
ccaes_word_t ccaes_xor_word(const ccaes_word_t x, const ccaes_word_t y) {
return (ccaes_word_t) {
.bytes = { x.bytes[0] ^ y.bytes[0], x.bytes[1] ^ y.bytes[1], x.bytes[2] ^ y.bytes[2], x.bytes[3] ^ y.bytes[3] },
};
};
CC_INLINE
void ccaes_sub_bytes(const size_t len, const uint8_t* const in, uint8_t* const out) {
for (size_t i = 0; i < len; ++i)
out[i] = ccaes_s_box[in[i]];
};
CC_INLINE
void ccaes_sub_bytes_inverse(const size_t len, const uint8_t* const in, uint8_t* const out) {
for (size_t i = 0; i < len; ++i)
out[i] = ccaes_s_box_inverse[in[i]];
};
CC_INLINE
void ccaes_shift_rows(ccaes_state_t* state) {
// i = current row index AND number of times to shift left
for (uint8_t i = 0; i < 4; ++i) {
// shifter: shifts the row left once each iteration
for (uint8_t j = 0; j < i; ++j) {
uint8_t tmp = state->bytes[i][0];
state->bytes[i][0] = state->bytes[i][1];
state->bytes[i][1] = state->bytes[i][2];
state->bytes[i][2] = state->bytes[i][3];
state->bytes[i][3] = tmp;
}
}
};
CC_INLINE
void ccaes_shift_rows_inverse(ccaes_state_t* state) {
// i = current row index AND number of times to shift right
for (uint8_t i = 0; i < 4; ++i) {
// shifter: shifts the row right once each iteration
for (uint8_t j = 0; j < i; ++j) {
uint8_t tmp = state->bytes[i][3];
state->bytes[i][3] = state->bytes[i][2];
state->bytes[i][2] = state->bytes[i][1];
state->bytes[i][1] = state->bytes[i][0];
state->bytes[i][0] = tmp;
}
}
};
CC_INLINE
void ccaes_mix_columns(ccaes_state_t* state) {
// https://en.wikipedia.org/wiki/Rijndael_MixColumns#Implementation_example
ccaes_state_t result = {0};
// hopefully the compiler is smart enough to unroll this loop
for (uint8_t i = 0; i < 4; ++i) {
#define GF1(index) (state->bytes[index][i])
#define GF2(index) (gmul_2[GF1(index)])
#define GF3(index) (gmul_3[GF1(index)])
result.bytes[0][i] = GF2(0) ^ GF3(1) ^ GF1(2) ^ GF1(3);
result.bytes[1][i] = GF1(0) ^ GF2(1) ^ GF3(2) ^ GF1(3);
result.bytes[2][i] = GF1(0) ^ GF1(1) ^ GF2(2) ^ GF3(3);
result.bytes[3][i] = GF3(0) ^ GF1(1) ^ GF1(2) ^ GF2(3);
#undef GF1
#undef GF2
#undef GF3
}
*state = result;
};
CC_INLINE
void ccaes_mix_columns_inverse(ccaes_state_t* state) {
// https://en.wikipedia.org/wiki/Rijndael_MixColumns#InverseMixColumns
ccaes_state_t result = {0};
for (uint8_t i = 0; i < 4; ++i) {
#define GF1(index) (state->bytes[index][i])
#define GF2(index) (gmul_2[GF1(index)])
#define GF9(index) (gmul_9[GF1(index)])
#define GF11(index) (gmul_11[GF1(index)])
#define GF13(index) (gmul_13[GF1(index)])
#define GF14(index) (gmul_14[GF1(index)])
result.bytes[0][i] = GF14(0) ^ GF11(1) ^ GF13(2) ^ GF9(3);
result.bytes[1][i] = GF9(0) ^ GF14(1) ^ GF11(2) ^ GF13(3);
result.bytes[2][i] = GF13(0) ^ GF9(1) ^ GF14(2) ^ GF11(3);
result.bytes[3][i] = GF11(0) ^ GF13(1) ^ GF9(2) ^ GF14(3);
#undef GF1
#undef GF2
#undef GF9
#undef GF11
#undef GF13
#undef GF14
}
*state = result;
};
CC_INLINE
void ccaes_add_round_key(ccaes_state_t* state, const ccaes_word_t* const round_key) {
for (uint8_t i = 0; i < 4; ++i)
for (uint8_t j = 0; j < 4; ++j)
state->bytes[j][i] ^= round_key[i].bytes[j];
};
CC_INLINE
int ccaes_expand_key(const size_t key_len, const uint8_t* const key, ccaes_word_t* const expanded_keys) {
const size_t Nr = ccaes_round_count(key_len);
const size_t Nk = key_len / 4;
ccaes_word_t tmp = {0};
for (size_t i = 0; i < Nk; ++i)
expanded_keys[i] = (ccaes_word_t) { .bytes = { key[4 * i], key[4 * i + 1], key[4 * i + 2], key[4 * i + 3], }, };
for (size_t i = Nk; i < 4 * (Nr + 1); ++i) {
tmp = expanded_keys[i - 1];
if (i % Nk == 0) {
tmp = ccaes_rot_word(tmp);
ccaes_sub_bytes(4, tmp.bytes, tmp.bytes);
tmp.bytes[0] ^= ccaes_round_constant[(i / Nk) - 1];
} else if (Nk > 6 && i % Nk == 4) {
ccaes_sub_bytes(4, tmp.bytes, tmp.bytes);
}
expanded_keys[i] = ccaes_xor_word(expanded_keys[i - Nk], tmp);
}
return 0;
};
static int ccaes_ecb_init(const struct ccmode_ecb* info, ccecb_ctx* _ctx, size_t key_size, const void* key) {
int status = CCERR_OK;
struct the_real_ccecb_ctx* ctx = (struct the_real_ccecb_ctx*)_ctx;
// validate the key size and determine round count
ctx->round_count = ccaes_round_count(key_size);
if (ctx->round_count == 0)
return CCERR_PARAMETER; // i'm guessing that's the right error code
// initialize the context by performing key expansion
status = ccaes_expand_key(key_size, key, (ccaes_word_t*)ctx->round_keys);
return status;
};
static int ccaes_ecb_encrypt(const ccecb_ctx* _ctx, size_t block_count, const void* in, void* out) {
const uint8_t* input = in;
uint8_t* output = out;
struct the_real_ccecb_ctx* ctx = (struct the_real_ccecb_ctx*)_ctx;
for (size_t block_index = 0; block_index < block_count; ++block_index) {
ccaes_state_t state = {
.bytes = {
{ input[ 0], input[ 4], input[ 8], input[12], },
{ input[ 1], input[ 5], input[ 9], input[13], },
{ input[ 2], input[ 6], input[10], input[14], },
{ input[ 3], input[ 7], input[11], input[15], },
},
};
ccaes_add_round_key(&state, &ctx->round_keys[0]);
for (uint8_t round = 1; round < ctx->round_count; ++round) {
ccaes_sub_bytes(16, (const uint8_t*)state.bytes, (uint8_t*)state.bytes);
ccaes_shift_rows(&state);
ccaes_mix_columns(&state);
ccaes_add_round_key(&state, &ctx->round_keys[4 * round]);
}
ccaes_sub_bytes(16, (const uint8_t*)state.bytes, (uint8_t*)state.bytes);
ccaes_shift_rows(&state);
ccaes_add_round_key(&state, &ctx->round_keys[4 * ctx->round_count]);
for (uint8_t i = 0; i < 4; ++i)
for (uint8_t j = 0; j < 4; ++j)
output[(i * 4) + j] = state.bytes[j][i];
input += 16;
output += 16;
}
return CCERR_OK;
};
static int ccaes_ecb_decrypt(const ccecb_ctx* _ctx, size_t block_count, const void* in, void* out) {
const uint8_t* input = in;
uint8_t* output = out;
struct the_real_ccecb_ctx* ctx = (struct the_real_ccecb_ctx*)_ctx;
for (size_t block_index = 0; block_index < block_count; ++block_index) {
ccaes_state_t state = {
.bytes = {
{ input[ 0], input[ 4], input[ 8], input[12], },
{ input[ 1], input[ 5], input[ 9], input[13], },
{ input[ 2], input[ 6], input[10], input[14], },
{ input[ 3], input[ 7], input[11], input[15], },
},
};
ccaes_add_round_key(&state, &ctx->round_keys[4 * ctx->round_count]);
ccaes_shift_rows_inverse(&state);
ccaes_sub_bytes_inverse(16, (const uint8_t*)state.bytes, (uint8_t*)state.bytes);
for (uint8_t round = ctx->round_count - 1; round >= 1; --round) {
ccaes_add_round_key(&state, &ctx->round_keys[4 * round]);
ccaes_mix_columns_inverse(&state);
ccaes_shift_rows_inverse(&state);
ccaes_sub_bytes_inverse(16, (const uint8_t*)state.bytes, (uint8_t*)state.bytes);
}
ccaes_add_round_key(&state, &ctx->round_keys[0]);
for (uint8_t i = 0; i < 4; ++i)
for (uint8_t j = 0; j < 4; ++j)
output[(i * 4) + j] = state.bytes[j][i];
input += 16;
output += 16;
}
return CCERR_OK;
};
const struct ccmode_siv* ccaes_siv_encrypt_mode(void) {
CC_STUB(NULL);
};
const struct ccmode_siv* ccaes_siv_decrypt_mode(void) {
CC_STUB(NULL);
};

View File

@ -1,86 +0,0 @@
#include <corecrypto/private/ccaes_extra.h>
#include <string.h>
CC_INLINE
int ccaes_expand_key(const size_t key_len, const uint8_t* const key, ccaes_word_t* const expanded_keys) {
const size_t Nr = ccaes_round_count(key_len);
const size_t Nk = key_len / 4;
ccaes_word_t tmp = {0};
for (size_t i = 0; i < Nk; ++i)
expanded_keys[i] = (ccaes_word_t) { .bytes = { key[4 * i], key[4 * i + 1], key[4 * i + 2], key[4 * i + 3], }, };
for (size_t i = Nk; i < 4 * (Nr + 1); ++i) {
tmp = expanded_keys[i - 1];
if (i % Nk == 0) {
tmp = ccaes_rot_word(tmp);
ccaes_sub_bytes(4, tmp.bytes, tmp.bytes);
tmp.bytes[0] ^= ccaes_round_constant[(i / Nk) - 1];
} else if (Nk > 6 && i % Nk == 4) {
ccaes_sub_bytes(4, tmp.bytes, tmp.bytes);
}
expanded_keys[i] = ccaes_xor_word(expanded_keys[i - Nk], tmp);
}
return 0;
};
ccaes_block_128_t ccaes_block_cipher(const ccaes_block_128_t input, const size_t key_len, const uint8_t* const key) {
if (key_len != 16 && key_len != 24 && key_len != 32)
return (ccaes_block_128_t) {0};
const size_t Nr = ccaes_round_count(key_len);
ccaes_word_t expanded_keys[4 * (Nr + 1)];
memset(expanded_keys, 0, sizeof expanded_keys);
ccaes_expand_key(key_len, key, expanded_keys);
ccaes_state_t state = {
.bytes = {
{ input.block[15], input.block[11], input.block[ 7], input.block[ 3], },
{ input.block[14], input.block[10], input.block[ 6], input.block[ 2], },
{ input.block[13], input.block[ 9], input.block[ 5], input.block[ 1], },
{ input.block[12], input.block[ 8], input.block[ 4], input.block[ 0], },
},
};
state = ccaes_add_round_key(state, &expanded_keys[0]);
for (size_t round = 1; round < Nr; ++round) {
ccaes_sub_bytes(16, (const uint8_t*)state.bytes, (uint8_t*)state.bytes);
state = ccaes_shift_rows(state);
state = ccaes_mix_columns(state);
state = ccaes_add_round_key(state, &expanded_keys[4 * round]);
}
ccaes_sub_bytes(16, (const uint8_t*)state.bytes, (uint8_t*)state.bytes);
state = ccaes_shift_rows(state);
state = ccaes_add_round_key(state, &expanded_keys[4 * Nr]);
return (ccaes_block_128_t) {
.block = {
state.bytes[3][3],
state.bytes[2][3],
state.bytes[1][3],
state.bytes[0][3],
state.bytes[3][2],
state.bytes[2][2],
state.bytes[1][2],
state.bytes[0][2],
state.bytes[3][1],
state.bytes[2][1],
state.bytes[1][1],
state.bytes[0][1],
state.bytes[3][0],
state.bytes[2][0],
state.bytes[1][0],
state.bytes[0][0],
},
};
};

67
src/cccbc.c Normal file
View File

@ -0,0 +1,67 @@
#include <corecrypto/ccmode_factory.h>
int ccmode_cbc_init(const struct ccmode_cbc* cbc, cccbc_ctx* _ctx, size_t rawkey_len, const void* rawkey) {
int status = CCERR_OK;
struct _ccmode_cbc_key* ctx = (struct _ccmode_cbc_key*)_ctx;
ctx->ecb = cbc->custom;
ccecb_ctx* ecb_ctx = (ccecb_ctx*)((char*)ctx->u + ccn_sizeof_size(ctx->ecb->block_size));
if ((status = ctx->ecb->init(ctx->ecb, ecb_ctx, rawkey_len, rawkey)) != CCERR_OK)
goto out;
// `_ccmode_cbc_key` includes space for a single block in the context, which i *think* is supposed to be scratch space.
cc_zero(ccn_sizeof_size(ctx->ecb->block_size), ctx->u);
out:
return status;
};
int ccmode_cbc_encrypt(const cccbc_ctx* _ctx, cccbc_iv* _iv, size_t nblocks, const void* in, void* out) {
int status = CCERR_OK;
struct _ccmode_cbc_key* ctx = (struct _ccmode_cbc_key*)_ctx;
ccecb_ctx* ecb_ctx = (ccecb_ctx*)((char*)ctx->u + ccn_sizeof_size(ctx->ecb->block_size));
const uint8_t* input = in;
uint8_t* output = out;
uint8_t* scratch_space = (uint8_t*)ctx->u;
uint8_t* iv = (uint8_t*)_iv;
for (size_t i = 0; i < nblocks; ++i) {
cc_xor(ctx->ecb->block_size, scratch_space, input, iv);
if ((status = ctx->ecb->ecb(ecb_ctx, 1, scratch_space, output)) != CCERR_OK)
goto out;
cc_copy(ctx->ecb->block_size, iv, output);
input += ctx->ecb->block_size;
output += ctx->ecb->block_size;
}
out:
return status;
};
int ccmode_cbc_decrypt(const cccbc_ctx* _ctx, cccbc_iv* _iv, size_t nblocks, const void* in, void* out) {
int status = CCERR_OK;
struct _ccmode_cbc_key* ctx = (struct _ccmode_cbc_key*)_ctx;
ccecb_ctx* ecb_ctx = (ccecb_ctx*)((char*)ctx->u + ccn_sizeof_size(ctx->ecb->block_size));
const uint8_t* input = in;
uint8_t* output = out;
uint8_t* scratch_space = (uint8_t*)ctx->u;
uint8_t* iv = (uint8_t*)_iv;
for (size_t i = 0; i < nblocks; ++i) {
if ((status = ctx->ecb->ecb(ecb_ctx, 1, input, scratch_space)) != CCERR_OK)
goto out;
cc_xor(ctx->ecb->block_size, output, scratch_space, iv);
cc_copy(ctx->ecb->block_size, iv, input);
input += ctx->ecb->block_size;
output += ctx->ecb->block_size;
}
out:
return status;
};

30
src/ccccm.c Normal file
View File

@ -0,0 +1,30 @@
#include <corecrypto/ccmode_factory.h>
#include <corecrypto/private/ccstubs.h>
int ccmode_ccm_init(const struct ccmode_ccm* ccm, ccccm_ctx* _ctx, size_t rawkey_len, const void* rawkey) {
CC_STUB_ERR();
};
int ccmode_ccm_set_iv(ccccm_ctx* _ctx, ccccm_nonce* _nonce_ctx, size_t nonce_len, const void* nonce, size_t mac_size, size_t auth_len, size_t data_len) {
CC_STUB_ERR();
};
int ccmode_ccm_cbcmac(ccccm_ctx* _ctx, ccccm_nonce* _nonce_ctx, size_t nbytes, const void* in) {
CC_STUB_ERR();
};
int ccmode_ccm_decrypt(ccccm_ctx *_ctx, ccccm_nonce* _nonce_ctx, size_t nbytes, const void* in, void* out) {
CC_STUB_ERR();
};
int ccmode_ccm_encrypt(ccccm_ctx *_ctx, ccccm_nonce* _nonce_ctx, size_t nbytes, const void* in, void* out) {
CC_STUB_ERR();
};
int ccmode_ccm_finalize(ccccm_ctx* _ctx, ccccm_nonce* _nonce_ctx, void* mac) {
CC_STUB_ERR();
};
int ccmode_ccm_reset(ccccm_ctx* _ctx, ccccm_nonce* _nonce_ctx) {
CC_STUB_ERR();
};

14
src/cccfb.c Normal file
View File

@ -0,0 +1,14 @@
#include <corecrypto/ccmode_factory.h>
#include <corecrypto/private/ccstubs.h>
int ccmode_cfb_init(const struct ccmode_cfb* cfb, cccfb_ctx* _ctx, size_t rawkey_len, const void* rawkey, const void* iv) {
CC_STUB_ERR();
};
int ccmode_cfb_decrypt(cccfb_ctx* _ctx, size_t nbytes, const void* in, void* out) {
CC_STUB_ERR();
};
int ccmode_cfb_encrypt(cccfb_ctx* _ctx, size_t nbytes, const void* in, void* out) {
CC_STUB_ERR();
};

14
src/cccfb8.c Normal file
View File

@ -0,0 +1,14 @@
#include <corecrypto/ccmode_factory.h>
#include <corecrypto/private/ccstubs.h>
int ccmode_cfb8_init(const struct ccmode_cfb8* cfb8, cccfb8_ctx* _ctx, size_t rawkey_len, const void* rawkey, const void* iv) {
CC_STUB_ERR();
};
int ccmode_cfb8_decrypt(cccfb8_ctx* _ctx, size_t nbytes, const void* in, void* out) {
CC_STUB_ERR();
};
int ccmode_cfb8_encrypt(cccfb8_ctx* _ctx, size_t nbytes, const void* in, void* out) {
CC_STUB_ERR();
};

38
src/ccckg.c Normal file
View File

@ -0,0 +1,38 @@
#include <corecrypto/ccckg.h>
#include <corecrypto/private/ccstubs.h>
size_t ccckg_sizeof_commitment(ccec_const_cp_t cp, const struct ccdigest_info* digest_info) {
CC_STUB(0);
};
size_t ccckg_sizeof_share(ccec_const_cp_t cp, const struct ccdigest_info* digest_info) {
CC_STUB(0);
};
size_t ccckg_sizeof_opening(ccec_const_cp_t cp, const struct ccdigest_info* digest_info) {
CC_STUB(0);
};
size_t ccckg_sizeof_ctx(ccec_const_cp_t cp, const struct ccdigest_info* digest_info) {
CC_STUB(0);
};
int ccckg_init(ccckg_ctx_t ctx, ccec_const_cp_t cp, const struct ccdigest_info* digest_info, struct ccrng_state* rng) {
CC_STUB_ERR();
};
int ccckg_contributor_commit(ccckg_ctx_t ctx, size_t commitment_length, void* commitment) {
CC_STUB_ERR();
};
int ccckg_contributor_finish(ccckg_ctx_t ctx, size_t share_length, const void* share, size_t opening_length, void* opening, ccec_pub_ctx_t ec_pub, size_t shared_key_length, void* shared_key) {
CC_STUB_ERR();
};
int ccckg_owner_finish(ccckg_ctx_t ctx, size_t opening_length, const void* opening, ccec_full_ctx_t ec_full, size_t shared_key_length, void* shared_key) {
CC_STUB_ERR();
};
int ccckg_owner_generate_share(ccckg_ctx_t ctx, size_t commitment_length, const void* commitment, size_t share_length, void* share) {
CC_STUB_ERR();
};

14
src/ccctr.c Normal file
View File

@ -0,0 +1,14 @@
#include <corecrypto/ccmode_factory.h>
#include <corecrypto/private/ccstubs.h>
int ccmode_ctr_init(const struct ccmode_ctr* ctr, ccctr_ctx* _ctx, size_t rawkey_len, const void* rawkey, const void* iv) {
CC_STUB_ERR();
};
int ccmode_ctr_crypt(ccctr_ctx* ctx, size_t nbytes, const void* in, void* out) {
CC_STUB_ERR();
};
int ccmode_ctr_setctr(const struct ccmode_ctr* ctr, ccctr_ctx* ctx, const void* iv) {
CC_STUB_ERR();
};

View File

@ -1,37 +1,299 @@
#include <corecrypto/private/ccgcm.h>
#include <corecrypto/private/cc128.h>
#include <corecrypto/ccmode_factory.h>
#include <corecrypto/private/ccstubs.h>
#include <corecrypto/ccmode.h>
#include <string.h>
#include <stdio.h>
// `input` is assumed to be in normal byte order (big-endian; most significant byte at lowest address)
ccaes_block_128_t ccgcm_ghash_128(const ccaes_block_128_t hash_subkey, const size_t input_len, const uint8_t* const input) {
const size_t m = (input_len + 15) / 16;
ccaes_block_128_t y = {0};
#define CCGCM_MODE_INITIALIZE 0
#define CCGCM_MODE_IV 1
#define CCGCM_MODE_AAD 2
#define CCGCM_MODE_CIPHERTEXT 3
#define CCGCM_MODE_FINALIZE 4
for (size_t i = 0; i < m; ++i) {
const ccaes_block_128_t x = ccaes_normalize_128(input_len - (i * 16), input + (i * 16));
y = ccaes_multiply_128(ccaes_xor_128(y, x), hash_subkey);
#define CTX_U_BUFFER(index) ((uint8_t*)ctx->u + (index * ccn_sizeof_size(ctx->ecb->block_size)))
#define CTX_U_BLOCK(index) ((cc128_t*)CTX_U_BUFFER(index))
CC_INLINE
int perform_block_cipher(struct _ccmode_gcm_key* ctx, const cc128_t* input, cc128_t* output) {
int status = CCERR_OK;
uint8_t* temp = CTX_U_BUFFER(4);
cc128_store_be(input, 16, temp);
if ((status = ctx->ecb->ecb(ctx->ecb_key, 1, temp, temp)) != CCERR_OK)
goto out;
cc128_load_be(16, temp, output);
out:
return status;
};
int ccmode_gcm_init(const struct ccmode_gcm* gcm, ccgcm_ctx* _ctx, size_t rawkey_len, const void* rawkey) {
int status = CCERR_OK;
struct _ccmode_gcm_key* ctx = (struct _ccmode_gcm_key*)_ctx;
cc128_t* hash_subkey = (cc128_t*)ctx->H;
ctx->ecb = gcm->custom;
ctx->ecb_key = ctx->u + (5 * ccn_sizeof_size(ctx->ecb->block_size));
if ((status = ctx->ecb->init(ctx->ecb, ctx->ecb_key, rawkey_len, rawkey)) != CCERR_OK)
goto out;
ctx->encdec = gcm->encdec;
ctx->flags = 0;
ctx->buf_nbytes = 0;
ctx->aad_nbytes = 0;
ctx->text_nbytes = 0;
ctx->state = CCGCM_MODE_INITIALIZE;
cc_zero(5 * ccn_sizeof_size(ctx->ecb->block_size), CTX_U_BUFFER(0));
cc_zero(sizeof(ctx->H), ctx->H);
cc_zero(sizeof(ctx->X), ctx->X);
cc_zero(sizeof(ctx->Y), ctx->Y);
cc_zero(sizeof(ctx->Y_0), ctx->Y_0);
cc_zero(sizeof(ctx->buf), ctx->buf);
if ((status = perform_block_cipher(ctx, hash_subkey, hash_subkey)) != CCERR_OK)
goto out;
out:
return status;
};
int ccmode_gcm_set_iv(ccgcm_ctx* _ctx, size_t iv_size, const void* iv) {
int status = CCERR_OK;
struct _ccmode_gcm_key* ctx = (struct _ccmode_gcm_key*)_ctx;
cc128_t* initial_cb = (cc128_t*)ctx->Y_0;
cc128_t* hash_subkey = (cc128_t*)ctx->H;
cc128_t* cache = (cc128_t*)ctx->buf;
const uint8_t* iv_buf = iv;
if (ctx->state == CCGCM_MODE_INITIALIZE)
ctx->state = CCGCM_MODE_IV;
if (ctx->state != CCGCM_MODE_IV)
return CCMODE_INVALID_CALL_SEQUENCE;
for (size_t i = 0; i < iv_size; ++i) {
// `aad_nbytes` is used as the IV length when we're in IV mode
const size_t current_block_index = 15 - (ctx->aad_nbytes % 16);
cache->bytes[current_block_index] = iv_buf[i];
if (current_block_index == 0) {
cc128_xor(initial_cb, cache, initial_cb);
cc128_mul(initial_cb, hash_subkey, initial_cb);
cc_zero(16, cache->bytes);
}
++ctx->aad_nbytes;
}
return y;
return status;
};
CC_INLINE
int ccgcm_process_iv(struct _ccmode_gcm_key* ctx) {
int status = CCERR_OK;
uint8_t* current_iv = CTX_U_BUFFER(0);
cc128_t* initial_cb = (cc128_t*)ctx->Y_0;
cc128_t* hash_subkey = (cc128_t*)ctx->H;
cc128_t* cache = (cc128_t*)ctx->buf;
cc128_t* cb = (cc128_t*)ctx->Y;
cc128_t* processed_cb = CTX_U_BLOCK(1);
if (ctx->aad_nbytes == 12) {
// we only do this when IV is 12 bytes because the only time
// the IV is incremented for reuse is when it's set through
// `ccgcm_init_with_iv`
for (size_t i = 0; i < 12; ++i)
current_iv[i] = cache->bytes[15 - i];
cache->bytes[0] = 1;
cc_copy(16, initial_cb->bytes, cache->bytes);
} else {
if (ctx->aad_nbytes % 16 != 0) {
cc128_xor(initial_cb, cache, initial_cb);
cc128_mul(initial_cb, hash_subkey, initial_cb);
cc_zero(16, cache->bytes);
}
const size_t iv_bits = ctx->aad_nbytes * 8;
for (size_t i = 0; i < sizeof(size_t); ++i)
cache->bytes[i] = (iv_bits >> (i * 8)) & 0xff;
cc128_xor(initial_cb, cache, initial_cb);
cc128_mul(initial_cb, hash_subkey, initial_cb);
}
cc_zero(16, cache->bytes);
cc128_lsw_increment(initial_cb, cb);
if ((status = perform_block_cipher(ctx, cb, processed_cb)) != CCERR_OK)
return status;
ctx->aad_nbytes = 0;
return status;
};
int ccmode_gcm_aad(ccgcm_ctx* _ctx, size_t buf_len, const void* in) {
int status = CCERR_OK;
struct _ccmode_gcm_key* ctx = (struct _ccmode_gcm_key*)_ctx;
const uint8_t* in_buf = in;
cc128_t* cache = (cc128_t*)ctx->buf;
cc128_t* hash = (cc128_t*)ctx->X;
cc128_t* hash_subkey = (cc128_t*)ctx->H;
if (ctx->state == CCGCM_MODE_IV) {
if ((status = ccgcm_process_iv(ctx)) != CCERR_OK)
goto out;
ctx->state = CCGCM_MODE_AAD;
}
if (ctx->state != CCGCM_MODE_AAD)
return CCMODE_INVALID_CALL_SEQUENCE;
for (size_t i = 0; i < buf_len; ++i) {
const size_t current_block_index = 15 - (ctx->aad_nbytes % 16);
cache->bytes[current_block_index] = in_buf[i];
if (current_block_index == 0) {
cc128_xor(hash, cache, hash);
cc128_mul(hash, hash_subkey, hash);
cc_zero(16, cache->bytes);
}
++ctx->aad_nbytes;
}
out:
return status;
};
CC_INLINE
int ccgcm_process_aad(struct _ccmode_gcm_key* ctx) {
cc128_t* cache = (cc128_t*)ctx->buf;
cc128_t* hash = (cc128_t*)ctx->X;
cc128_t* hash_subkey = (cc128_t*)ctx->H;
if (ctx->aad_nbytes % 16 != 0) {
cc128_xor(hash, cache, hash);
cc128_mul(hash, hash_subkey, hash);
cc_zero(16, cache->bytes);
}
return CCERR_OK;
};
int ccmode_gcm_encrypt(ccgcm_ctx* _ctx, size_t buf_len, const void* in, void* out) {
int status = CCERR_OK;
struct _ccmode_gcm_key* ctx = (struct _ccmode_gcm_key*)_ctx;
const uint8_t* in_buf = in;
uint8_t* out_buf = out;
bool decrypting = ctx->encdec == CCMODE_GCM_DECRYPTOR;
cc128_t* cache = (cc128_t*)ctx->buf;
cc128_t* hash = (cc128_t*)ctx->X;
cc128_t* hash_subkey = (cc128_t*)ctx->H;
cc128_t* cb = (cc128_t*)ctx->Y;
cc128_t* processed_cb = CTX_U_BLOCK(1);
if (ctx->state == CCGCM_MODE_IV) {
if ((status = ccgcm_process_iv(ctx)) != CCERR_OK)
return status;
ctx->state = CCGCM_MODE_AAD;
}
if (ctx->state == CCGCM_MODE_AAD) {
if ((status = ccgcm_process_aad(ctx)) != CCERR_OK)
return status;
ctx->state = CCGCM_MODE_CIPHERTEXT;
}
if (ctx->state != CCGCM_MODE_CIPHERTEXT)
return CCMODE_INVALID_CALL_SEQUENCE;
for (size_t i = 0; i < buf_len; ++i) {
const size_t current_block_index = 15 - (ctx->text_nbytes % 16);
if (decrypting) {
cache->bytes[current_block_index] = in_buf[i];
}
out_buf[i] = in_buf[i] ^ processed_cb->bytes[current_block_index];
if (!decrypting) {
cache->bytes[current_block_index] = out_buf[i];
}
if (current_block_index == 0) {
cc128_xor(hash, cache, hash);
cc128_mul(hash, hash_subkey, hash);
cc_zero(16, cache->bytes);
}
++ctx->text_nbytes;
if (ctx->text_nbytes % 16 == 0) {
cc128_lsw_increment(cb, cb);
if ((status = perform_block_cipher(ctx, cb, processed_cb)) != CCERR_OK)
return status;
}
}
return status;
};
int ccmode_gcm_decrypt(ccgcm_ctx* _ctx, size_t nbytes, const void* in, void* out) {
return ccmode_gcm_encrypt(_ctx, nbytes, in, out);
};
CC_INLINE
int ccgcm_process_ciphertext(struct _ccmode_gcm_key* ctx) {
cc128_t* cache = (cc128_t*)ctx->buf;
cc128_t* hash = (cc128_t*)ctx->X;
cc128_t* hash_subkey = (cc128_t*)ctx->H;
if (ctx->text_nbytes % 16 != 0) {
cc128_xor(hash, cache, hash);
cc128_mul(hash, hash_subkey, hash);
cc_zero(16, cache->bytes);
}
return CCERR_OK;
};
// `input` is assumed to be in normal byte order (big-endian; most significant byte at lowest address)
// `output` is in the same order as `input`
int ccgcm_gctr_128(const ccaes_block_cipher_function_t block_cipher_function, const size_t key_len, const uint8_t* const key, const ccaes_block_128_t icb, const size_t input_len, const uint8_t* const input, uint8_t* const output) {
CC_INLINE
int ccgcm_gctr_128(struct _ccmode_gcm_key* ctx, const size_t input_len, const uint8_t* const input, uint8_t* const output) {
if (input_len == 0)
return 0;
return CCERR_OK;
int status = CCERR_OK;
const size_t n = (input_len + 15) / 16;
ccaes_block_128_t cb = icb;
cc128_t* cache = (cc128_t*)ctx->buf;
cc128_t* hash = (cc128_t*)ctx->X;
cc128_t* hash_subkey = (cc128_t*)ctx->H;
cc128_t* cb = (cc128_t*)ctx->Y;
cc128_t* processed_cb = CTX_U_BLOCK(1);
cc128_t* temp = CTX_U_BLOCK(4);
cc128_t* initial_cb = (cc128_t*)ctx->Y_0;
size_t current_len = input_len;
const uint8_t* current_input = input;
uint8_t* current_output = output;
for (size_t i = 0; i < n - 1; ++i) {
const ccaes_block_128_t x = ccaes_normalize_128(current_len, current_input);
const ccaes_block_128_t y = ccaes_xor_128(x, block_cipher_function(cb, key_len, key));
ccaes_write_block_128(y, current_len, current_output);
cc_copy(16, cb->bytes, initial_cb->bytes);
cb = ccaes_increment_128(cb, 32);
for (size_t i = 0; i < n - 1; ++i) {
cc128_load_be(current_len, current_input, cache);
if ((status = perform_block_cipher(ctx, cb, processed_cb)) != CCERR_OK)
return status;
cc128_xor(cache, processed_cb, cache);
cc128_store_be(cache, current_len, current_output);
cc128_lsw_increment(cb, cb);
current_len -= 16;
current_input += 16;
@ -39,264 +301,145 @@ int ccgcm_gctr_128(const ccaes_block_cipher_function_t block_cipher_function, co
}
const size_t final_block_bytes = input_len - ((n - 1) * 8);
const ccaes_block_128_t final_block = ccaes_normalize_128(current_len, current_input);
const ccaes_block_128_t final_y = ccaes_xor_128(final_block, ccaes_most_significant_bits_128(block_cipher_function(cb, key_len, key), final_block_bytes * 8));
ccaes_write_block_128(final_y, current_len, current_output);
cc128_load_be(current_len, current_input, cache);
return 0;
if ((status = perform_block_cipher(ctx, cb, processed_cb)) != CCERR_OK)
return status;
cc128_msbits(processed_cb, final_block_bytes * 8, temp);
cc128_xor(cache, temp, cache);
cc128_store_be(cache, current_len, current_output);
return status;
};
//
// ~~~actual AES-GCM implementation~~~
//
int ccmode_gcm_finalize(ccgcm_ctx* _ctx, size_t tag_size, void* tag) {
int status = CCERR_OK;
struct _ccmode_gcm_key* ctx = (struct _ccmode_gcm_key*)_ctx;
cc128_t* cache = (cc128_t*)ctx->buf;
cc128_t* hash = (cc128_t*)ctx->X;
cc128_t* hash_subkey = (cc128_t*)ctx->H;
uint8_t* hash_buf = CTX_U_BUFFER(2);
uint8_t* result_buf = CTX_U_BUFFER(3);
int ccgcm_internal_init(const struct ccmode_gcm* gcm, ccgcm_ctx* ctx, size_t key_len, const void* key) {
ccgcm_state* state = (ccgcm_state*)ctx;
// our block cipher function only accepts 128-bit, 192-bit, or 256-bit keys
if (key_len != 16 && key_len != 24 && key_len != 32)
return -1;
*state = (ccgcm_state) {0};
state->decrypting = gcm->encdec == CCMODE_GCM_DECRYPTOR;
state->mode = CCGCM_MODE_INITIALIZE;
state->key = key;
state->key_len = key_len;
state->hash_subkey = ccaes_block_cipher((ccaes_block_128_t){0}, state->key_len, state->key);
return 0;
};
void ccgcm_process_iv(ccgcm_state* state) {
if (state->total_iv_length == 12) {
// we only do this when IV is 12 bytes because the only time
// the IV is incremented for reuse is when it's set through
// `ccgcm_init_with_iv`
for (size_t i = 0; i < 12; ++i)
state->current_iv[i] = state->cache.block[15 - i];
state->cache.block[0] = 1;
state->initial_cb = state->cache;
} else {
if (state->total_iv_length % 16 != 0) {
state->initial_cb = ccaes_multiply_128(ccaes_xor_128(state->initial_cb, state->cache), state->hash_subkey);
state->cache = (ccaes_block_128_t) {0};
}
const size_t iv_bits = state->total_iv_length * 8;
ccaes_block_128_t length_block = {0};
for (size_t i = 0; i < sizeof(size_t); ++i)
length_block.block[i] = (iv_bits >> (i * 8)) & 0xff;
state->initial_cb = ccaes_multiply_128(ccaes_xor_128(state->initial_cb, length_block), state->hash_subkey);
if (ctx->state == CCGCM_MODE_IV) {
if ((status = ccgcm_process_iv(ctx)) != CCERR_OK)
return status;
ctx->state = CCGCM_MODE_AAD;
}
state->cache = (ccaes_block_128_t) {0};
if (ctx->state == CCGCM_MODE_AAD) {
if ((status = ccgcm_process_aad(ctx)) != CCERR_OK)
return status;
ctx->state = CCGCM_MODE_CIPHERTEXT;
}
state->cb = ccaes_increment_128(state->initial_cb, 32);
state->processed_cb = ccaes_block_cipher(state->cb, state->key_len, state->key);
};
if (ctx->state == CCGCM_MODE_CIPHERTEXT) {
if ((status = ccgcm_process_ciphertext(ctx)) != CCERR_OK)
return status;
ctx->state = CCGCM_MODE_FINALIZE;
}
int ccgcm_internal_set_iv(ccgcm_ctx* ctx, size_t iv_size, const void* iv) {
ccgcm_state* state = (ccgcm_state*)ctx;
const uint8_t* iv_buf = iv;
if (state->mode == CCGCM_MODE_INITIALIZE)
state->mode = CCGCM_MODE_IV;
if (state->mode != CCGCM_MODE_IV)
if (ctx->state != CCGCM_MODE_FINALIZE)
return CCMODE_INVALID_CALL_SEQUENCE;
for (size_t i = 0; i < iv_size; ++i) {
const size_t current_block_index = 15 - (state->total_iv_length % 16);
state->cache.block[current_block_index] = iv_buf[i];
if (current_block_index == 0) {
state->initial_cb = ccaes_multiply_128(ccaes_xor_128(state->initial_cb, state->cache), state->hash_subkey);
state->cache = (ccaes_block_128_t) {0};
}
++state->total_iv_length;
}
return 0;
};
CC_INLINE
void ccgcm_process_aad(ccgcm_state* state) {
if (state->total_aad_length % 16 != 0) {
state->hash = ccaes_multiply_128(ccaes_xor_128(state->hash, state->cache), state->hash_subkey);
state->cache = (ccaes_block_128_t) {0};
}
};
int ccgcm_internal_gmac(ccgcm_ctx* ctx, size_t buf_len, const void* in) {
ccgcm_state* state = (ccgcm_state*)ctx;
const uint8_t* in_buf = in;
if (state->mode == CCGCM_MODE_IV) {
ccgcm_process_iv(state);
state->mode = CCGCM_MODE_AAD;
}
if (state->mode != CCGCM_MODE_AAD)
return CCMODE_INVALID_CALL_SEQUENCE;
for (size_t i = 0; i < buf_len; ++i) {
const size_t current_block_index = 15 - (state->total_aad_length % 16);
state->cache.block[current_block_index] = in_buf[i];
if (current_block_index == 0) {
state->hash = ccaes_multiply_128(ccaes_xor_128(state->hash, state->cache), state->hash_subkey);
state->cache = (ccaes_block_128_t) {0};
}
++state->total_aad_length;
}
return 0;
};
CC_INLINE
void ccgcm_process_ciphertext(ccgcm_state* state) {
if (state->total_cipher_length % 16 != 0) {
state->hash = ccaes_multiply_128(ccaes_xor_128(state->hash, state->cache), state->hash_subkey);
state->cache = (ccaes_block_128_t) {0};
}
};
int ccgcm_internal_gcm(ccgcm_ctx* ctx, size_t buf_len, const void* in, void* out) {
ccgcm_state* state = (ccgcm_state*)ctx;
const uint8_t* in_buf = in;
uint8_t* out_buf = out;
if (state->mode == CCGCM_MODE_IV) {
ccgcm_process_iv(state);
state->mode = CCGCM_MODE_AAD;
}
if (state->mode == CCGCM_MODE_AAD) {
ccgcm_process_aad(state);
state->mode = CCGCM_MODE_CIPHERTEXT;
}
if (state->mode != CCGCM_MODE_CIPHERTEXT)
return CCMODE_INVALID_CALL_SEQUENCE;
for (size_t i = 0; i < buf_len; ++i) {
const size_t current_block_index = 15 - (state->total_cipher_length % 16);
out_buf[i] = in_buf[i] ^ state->processed_cb.block[current_block_index];
const uint8_t cipher_byte = state->decrypting ? in_buf[i] : out_buf[i];
state->cache.block[current_block_index] = cipher_byte;
if (current_block_index == 0) {
state->hash = ccaes_multiply_128(ccaes_xor_128(state->hash, state->cache), state->hash_subkey);
state->cache = (ccaes_block_128_t) {0};
}
++state->total_cipher_length;
if (state->total_cipher_length % 16 == 0) {
state->cb = ccaes_increment_128(state->cb, 32);
state->processed_cb = ccaes_block_cipher(state->cb, state->key_len, state->key);
}
}
return 0;
};
int ccgcm_internal_finalize(ccgcm_ctx* ctx, size_t tag_size, void* tag) {
ccgcm_state* state = (ccgcm_state*)ctx;
if (state->mode == CCGCM_MODE_IV) {
ccgcm_process_iv(state);
state->mode = CCGCM_MODE_AAD;
}
if (state->mode == CCGCM_MODE_AAD) {
ccgcm_process_aad(state);
state->mode = CCGCM_MODE_CIPHERTEXT;
}
if (state->mode == CCGCM_MODE_CIPHERTEXT) {
ccgcm_process_ciphertext(state);
state->mode = CCGCM_MODE_FINALIZE;
}
if (state->mode != CCGCM_MODE_FINALIZE)
return CCMODE_INVALID_CALL_SEQUENCE;
const size_t aad_bits = state->total_aad_length * 8;
const size_t cipher_bits = state->total_cipher_length * 8;
const size_t aad_bits = ctx->aad_nbytes * 8;
const size_t cipher_bits = ctx->text_nbytes * 8;
uint8_t* tag_buf = tag;
ccaes_block_128_t length_block = {0};
for (size_t i = 0; i < sizeof(size_t); ++i)
cache->bytes[8 + i] = (aad_bits >> (i * 8)) & 0xff;
for (size_t i = 0; i < sizeof(size_t); ++i)
length_block.block[8 + i] = (aad_bits >> (i * 8)) & 0xff;
cache->bytes[i] = (cipher_bits >> (i * 8)) & 0xff;
for (size_t i = 0; i < sizeof(size_t); ++i)
length_block.block[i] = (cipher_bits >> (i * 8)) & 0xff;
cc128_xor(hash, cache, hash);
cc128_mul(hash, hash_subkey, hash);
state->hash = ccaes_multiply_128(ccaes_xor_128(state->hash, length_block), state->hash_subkey);
cc128_store_be(hash, 16, hash_buf);
cc_zero(16, result_buf);
const uint8_t hash_buf[16] = {
state->hash.block[15],
state->hash.block[14],
state->hash.block[13],
state->hash.block[12],
state->hash.block[11],
state->hash.block[10],
state->hash.block[ 9],
state->hash.block[ 8],
state->hash.block[ 7],
state->hash.block[ 6],
state->hash.block[ 5],
state->hash.block[ 4],
state->hash.block[ 3],
state->hash.block[ 2],
state->hash.block[ 1],
state->hash.block[ 0],
};
ccgcm_gctr_128(ctx, 16, hash_buf, result_buf);
uint8_t result_buf[16] = {0};
ccgcm_gctr_128(ccaes_block_cipher, state->key_len, state->key, state->initial_cb, sizeof hash_buf, hash_buf, result_buf);
if (ctx->encdec == CCMODE_GCM_DECRYPTOR)
status = cc_cmp_safe(tag_size < 16 ? tag_size : 16, tag_buf, result_buf) == 0 ? CCERR_OK : CCMODE_INTEGRITY_FAILURE;
for (size_t i = 0; i < 16 && i < tag_size; ++i)
tag_buf[i] = result_buf[i];
return status;
};
int ccmode_gcm_reset(ccgcm_ctx* _ctx) {
struct _ccmode_gcm_key* ctx = (struct _ccmode_gcm_key*)_ctx;
// *don't* zero the ECB key (it's preserved across resets)
//cc_zero(ccn_sizeof_size(ctx->ecb->size), ctx->ecb_key);
ctx->buf_nbytes = 0;
ctx->aad_nbytes = 0;
ctx->text_nbytes = 0;
ctx->state = CCGCM_MODE_INITIALIZE;
// skip the first block because that contains the current IV (which is preserved across resets)
cc_zero(4 * ccn_sizeof_size(ctx->ecb->block_size), CTX_U_BUFFER(1));
// *don't* zero the hash subkey (it's preserved across resets)
//cc_zero(sizeof(ctx->H), ctx->H);
cc_zero(sizeof(ctx->X), ctx->X);
cc_zero(sizeof(ctx->Y), ctx->Y);
cc_zero(sizeof(ctx->Y_0), ctx->Y_0);
cc_zero(sizeof(ctx->buf), ctx->buf);
return CCERR_OK;
};
int ccgcm_init_with_iv(const struct ccmode_gcm* mode, ccgcm_ctx* ctx, size_t key_nbytes, const void* key, const void* iv) {
int status = CCERR_OK;
if ((status = ccgcm_init(mode, ctx, key_nbytes, key)) != CCERR_OK)
return status;
if ((status = ccgcm_set_iv(mode, ctx, 12, iv)) != CCERR_OK)
return status;
return 0;
};
int ccgcm_internal_reset(ccgcm_ctx* ctx) {
ccgcm_state* state = (ccgcm_state*)ctx;
int ccgcm_inc_iv(const struct ccmode_gcm* mode, ccgcm_ctx* _ctx, void* iv) {
uint8_t* iv_buf = iv;
struct _ccmode_gcm_key* ctx = (struct _ccmode_gcm_key*)_ctx;
cc128_t* cache = (cc128_t*)ctx->buf;
uint8_t* current_iv = CTX_U_BUFFER(0);
ccgcm_state new_state = {
.decrypting = state->decrypting,
.mode = CCGCM_MODE_INITIALIZE,
.key_len = state->key_len,
.key = state->key,
// aggregate initialization automatically zeroes all other members
};
cc_zero(16, cache->bytes);
memcpy(new_state.current_iv, state->current_iv, sizeof state->current_iv);
memcpy(new_state.hash_subkey.block, state->hash_subkey.block, sizeof state->hash_subkey);
for (size_t i = 0; i < 12; ++i)
cache->bytes[15 - i] = current_iv[i];
*state = new_state;
for (size_t i = 0; i < 8; ++i) {
cache->bytes[4 + i] += 1;
if (cache->bytes[4 + i] != 0)
break;
}
ctx->aad_nbytes = 12;
ccgcm_process_iv(ctx);
memcpy(iv_buf, current_iv, 12);
return 0;
};
int ccgcm_set_iv_legacy(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t iv_nbytes, const void *iv) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
};
int ccgcm_one_shot(const struct ccmode_gcm* mode, size_t key_len, const void* key, size_t iv_len, const void* iv, size_t adata_len, const void* adata, size_t nbytes, const void* in, void* out, size_t tag_len, void* tag) {
CC_STUB_ERR();
};
int ccgcm_one_shot_legacy(const struct ccmode_gcm* mode, size_t key_len, const void* key, size_t iv_len, const void* iv, size_t adata_len, const void* adata, size_t nbytes, const void* in, void* out, size_t tag_len, void* tag) {
CC_STUB_ERR();
};

View File

@ -1,55 +1,80 @@
#include <corecrypto/ccmode.h>
#include <corecrypto/private/ccgcm.h>
#include <stdio.h>
#include <corecrypto/ccmode_factory.h>
int ccgcm_one_shot(const struct ccmode_gcm *mode,
size_t key_len, const void *key,
size_t iv_len, const void *iv,
size_t adata_len, const void *adata,
size_t nbytes, const void *in, void *out,
size_t tag_len, void *tag) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
}
int ccgcm_one_shot_legacy(const struct ccmode_gcm *mode,
size_t key_len, const void *key,
size_t iv_len, const void *iv,
size_t adata_len, const void *adata,
size_t nbytes, const void *in, void *out,
size_t tag_len, void *tag) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
}
int ccgcm_init_with_iv(const struct ccmode_gcm* mode, ccgcm_ctx* ctx, size_t key_nbytes, const void* key, const void* iv) {
ccgcm_init(mode, ctx, key_nbytes, key);
ccgcm_set_iv(mode, ctx, 12, iv);
return 0;
void ccmode_factory_cbc_encrypt(struct ccmode_cbc* cbc, const struct ccmode_ecb* ecb) {
*cbc = (struct ccmode_cbc) CCMODE_FACTORY_CBC_ENCRYPT(ecb);
};
int ccgcm_inc_iv(const struct ccmode_gcm* mode, ccgcm_ctx* ctx, void* iv) {
uint8_t* iv_buf = iv;
ccgcm_state* state = (ccgcm_state*)ctx;
state->cache = (ccaes_block_128_t) {0};
for (size_t i = 0; i < 12; ++i)
state->cache.block[15 - i] = state->current_iv[i];
for (size_t i = 0; i < 8; ++i) {
state->cache.block[4 + i] += 1;
if (state->cache.block[4 + i] != 0)
break;
}
state->total_iv_length = 12;
ccgcm_process_iv(state);
memcpy(iv_buf, state->current_iv, 12);
return 0;
void ccmode_factory_cbc_decrypt(struct ccmode_cbc* cbc, const struct ccmode_ecb* ecb) {
*cbc = (struct ccmode_cbc) CCMODE_FACTORY_CBC_DECRYPT(ecb);
};
int ccgcm_set_iv_legacy(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t iv_nbytes, const void *iv) {
printf("DARLING CRYPTO STUB: %s\n", __PRETTY_FUNCTION__);
void ccmode_factory_gcm_encrypt(struct ccmode_gcm* gcm, const struct ccmode_ecb* ecb_encrypt) {
*gcm = (struct ccmode_gcm) {
.size = sizeof(struct _ccmode_gcm_key) + GCM_ECB_KEY_SIZE(ecb_encrypt),
.encdec = CCMODE_GCM_ENCRYPTOR,
.block_size = 1,
.init = ccmode_gcm_init,
.set_iv = ccmode_gcm_set_iv,
.gmac = ccmode_gcm_aad,
.gcm = ccmode_gcm_encrypt,
.finalize = ccmode_gcm_finalize,
.reset = ccmode_gcm_reset,
.custom = ecb_encrypt,
};
};
void ccmode_factory_gcm_decrypt(struct ccmode_gcm* gcm, const struct ccmode_ecb* ecb_encrypt) {
*gcm = (struct ccmode_gcm) {
.size = sizeof(struct _ccmode_gcm_key) + GCM_ECB_KEY_SIZE(ecb_encrypt),
.encdec = CCMODE_GCM_DECRYPTOR,
.block_size = 1,
.init = ccmode_gcm_init,
.set_iv = ccmode_gcm_set_iv,
.gmac = ccmode_gcm_aad,
.gcm = ccmode_gcm_decrypt,
.finalize = ccmode_gcm_finalize,
.reset = ccmode_gcm_reset,
.custom = ecb_encrypt,
};
};
void ccmode_factory_cfb_encrypt(struct ccmode_cfb* cfb, const struct ccmode_ecb* ecb) {
*cfb = (struct ccmode_cfb) CCMODE_FACTORY_CFB_ENCRYPT(ecb);
};
void ccmode_factory_cfb_decrypt(struct ccmode_cfb* cfb, const struct ccmode_ecb* ecb) {
*cfb = (struct ccmode_cfb) CCMODE_FACTORY_CFB_DECRYPT(ecb);
};
void ccmode_factory_cfb8_encrypt(struct ccmode_cfb8* cfb8, const struct ccmode_ecb* ecb) {
*cfb8 = (struct ccmode_cfb8) CCMODE_FACTORY_CFB8_ENCRYPT(ecb);
};
void ccmode_factory_cfb8_decrypt(struct ccmode_cfb8* cfb8, const struct ccmode_ecb* ecb) {
*cfb8 = (struct ccmode_cfb8) CCMODE_FACTORY_CFB8_DECRYPT(ecb);
};
void ccmode_factory_ctr_crypt(struct ccmode_ctr* ctr, const struct ccmode_ecb* ecb_encrypt) {
*ctr = (struct ccmode_ctr) CCMODE_FACTORY_CTR_CRYPT(ecb_encrypt);
};
void ccmode_factory_ccm_encrypt(struct ccmode_ccm* ccm, const struct ccmode_ecb* ecb_encrypt) {
*ccm = (struct ccmode_ccm) CCMODE_FACTORY_CCM_ENCRYPT(ecb_encrypt);
};
void ccmode_factory_ccm_decrypt(struct ccmode_ccm* ccm, const struct ccmode_ecb* ecb_encrypt) {
*ccm = (struct ccmode_ccm) CCMODE_FACTORY_CCM_DECRYPT(ecb_encrypt);
};
void ccmode_factory_ofb_crypt(struct ccmode_ofb* ofb, const struct ccmode_ecb* ecb) {
*ofb = (struct ccmode_ofb) CCMODE_FACTORY_OFB_CRYPT(ecb);
};
void ccmode_factory_xts_encrypt(struct ccmode_xts* xts, const struct ccmode_ecb* ecb, const struct ccmode_ecb* ecb_encrypt) {
*xts = (struct ccmode_xts) CCMODE_FACTORY_XTS_ENCRYPT(ecb, ecb_encrypt);
};
void ccmode_factory_xts_decrypt(struct ccmode_xts* xts, const struct ccmode_ecb* ecb, const struct ccmode_ecb* ecb_encrypt) {
*xts = (struct ccmode_xts) CCMODE_FACTORY_XTS_DECRYPT(ecb, ecb_encrypt);
};

View File

@ -501,10 +501,10 @@ void ccn_zero_multi(cc_size n, cc_unit *r, ...) {
void ccn_print(cc_size n, const cc_unit *s) {
printf("size: %zu\n", n);
for (int i = 0; i < n; i++)
for (cc_size i = 0; i < n; i++)
{
#if CCN_UNIT_SIZE == 8
printf("%llx\n", s[i]);
printf("%llx\n", (unsigned long long)s[i]);
#elif CCN_UNIT_SIZE == 4
printf("%x\n", s[i]);
#endif

9
src/ccofb.c Normal file
View File

@ -0,0 +1,9 @@
#include <corecrypto/ccmode_factory.h>
#include <corecrypto/private/ccstubs.h>
int ccmode_ofb_init(const struct ccmode_ofb* ofb, ccofb_ctx* _ctx, size_t rawkey_len, const void* rawkey, const void* iv) {
CC_STUB_ERR();
};
int ccmode_ofb_crypt(ccofb_ctx* _ctx, size_t nbytes, const void* in, void* out) {
CC_STUB_ERR();
};

18
src/ccxts.c Normal file
View File

@ -0,0 +1,18 @@
#include <corecrypto/ccmode_factory.h>
#include <corecrypto/private/ccstubs.h>
int ccmode_xts_init(const struct ccmode_xts* xts, ccxts_ctx* _ctx, size_t key_nbytes, const void* data_key, const void* tweak_key) {
CC_STUB_ERR();
};
void ccmode_xts_key_sched(const struct ccmode_xts* xts, ccxts_ctx* _ctx, size_t key_nbytes, const void* data_key, const void* tweak_key) {
CC_STUB_VOID();
};
void* ccmode_xts_crypt(const ccxts_ctx* _ctx, ccxts_tweak* tweak, size_t nblocks, const void* in, void* out) {
CC_STUB(NULL);
};
int ccmode_xts_set_tweak(const ccxts_ctx* _ctx, ccxts_tweak* tweak, const void* iv) {
CC_STUB_ERR();
};