mirror of
https://github.com/darlinghq/darling-corecrypto.git
synced 2024-11-23 12:19:44 +00:00
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:
parent
3fb5fb5389
commit
970348c1b6
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
164
include/corecrypto/private/cc128.h
Normal file
164
include/corecrypto/private/cc128.h
Normal 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_
|
@ -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
|
@ -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
|
15
include/corecrypto/private/ccstubs.h
Normal file
15
include/corecrypto/private/ccstubs.h
Normal 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
|
557
src/ccaes.c
557
src/ccaes.c
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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
67
src/cccbc.c
Normal 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
30
src/ccccm.c
Normal 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
14
src/cccfb.c
Normal 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
14
src/cccfb8.c
Normal 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
38
src/ccckg.c
Normal 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
14
src/ccctr.c
Normal 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();
|
||||
};
|
635
src/ccgcm.c
635
src/ccgcm.c
@ -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();
|
||||
};
|
||||
|
121
src/ccmode.c
121
src/ccmode.c
@ -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);
|
||||
};
|
||||
|
@ -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
9
src/ccofb.c
Normal 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
18
src/ccxts.c
Normal 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();
|
||||
};
|
Loading…
Reference in New Issue
Block a user