Skip to content
Snippets Groups Projects
Commit b2f86518 authored by Mark Haines's avatar Mark Haines
Browse files

Finish and test crypto primitives

parent 44d0c092
No related branches found
No related tags found
No related merge requests found
......@@ -19,7 +19,7 @@ Curve25519KeyPair generate_key(
);
const std::size_t CURVE25519_SHARED_SECRET_LENGTH = 16;
const std::size_t CURVE25519_SHARED_SECRET_LENGTH = 32;
void curve25519_shared_secret(
......@@ -68,6 +68,12 @@ void aes_decrypt_cbc(
);
void sha256(
std::uint8_t const * input, std::size_t input_length,
std::uint8_t * output
);
const std::size_t HMAC_SHA256_OUTPUT_LENGTH = 32;
......
......@@ -19,7 +19,8 @@ namespace {
static const std::uint8_t CURVE25519_BASEPOINT[32] = {9};
static const std::size_t AES_BLOCK_LENGTH = 16;
static const std::size_t SHA256_BLOCK_LENGTH = 32;
static const std::size_t SHA256_HASH_LENGTH = 32;
static const std::size_t SHA256_BLOCK_LENGTH = 64;
static const std::uint8_t HKDF_DEFAULT_SALT[32] = {};
template<std::size_t block_size>
......@@ -37,13 +38,13 @@ inline static void hmac_sha256_key(
std::uint8_t const * input_key, std::size_t input_key_length,
std::uint8_t * hmac_key
) {
std::memset(hmac_key, 0, SHA256_BLOCK_LENGTH);
if (input_key_length > SHA256_BLOCK_LENGTH) {
::SHA256_CTX context;
::sha256_init(&context);
::sha256_update(&context, input_key, input_key_length);
::sha256_final(&context, hmac_key);
} else {
std::memset(hmac_key, 0, SHA256_BLOCK_LENGTH);
std::memcpy(hmac_key, input_key, input_key_length);
}
}
......@@ -56,7 +57,7 @@ inline void hmac_sha256_init(
std::uint8_t i_pad[SHA256_BLOCK_LENGTH];
std::memcpy(i_pad, hmac_key, SHA256_BLOCK_LENGTH);
for (std::size_t i = 0; i < SHA256_BLOCK_LENGTH; ++i) {
i_pad[i] ^= 0x5C;
i_pad[i] ^= 0x36;
}
::sha256_init(context);
::sha256_update(context, i_pad, SHA256_BLOCK_LENGTH);
......@@ -69,16 +70,15 @@ inline void hmac_sha256_final(
std::uint8_t const * hmac_key,
std::uint8_t * output
) {
std::uint8_t o_pad[SHA256_BLOCK_LENGTH];
std::uint8_t o_pad[SHA256_BLOCK_LENGTH + SHA256_HASH_LENGTH];
std::memcpy(o_pad, hmac_key, SHA256_BLOCK_LENGTH);
for (std::size_t i = 0; i < SHA256_BLOCK_LENGTH; ++i) {
o_pad[i] ^= 0x36;
o_pad[i] ^= 0x5C;
}
::sha256_final(context, o_pad + SHA256_BLOCK_LENGTH);
::SHA256_CTX final_context;
::sha256_init(&final_context);
::sha256_update(&final_context, o_pad, SHA256_BLOCK_LENGTH);
::sha256_final(context, o_pad);
::sha256_update(&final_context, o_pad, SHA256_BLOCK_LENGTH);
::sha256_update(&final_context, o_pad, sizeof(o_pad));
::sha256_final(&final_context, output);
std::memset(o_pad, 0, sizeof(o_pad));
}
......@@ -167,6 +167,16 @@ void axolotl::aes_decrypt_cbc(
}
void axolotl::sha256(
std::uint8_t const * input, std::size_t input_length,
std::uint8_t * output
) {
::SHA256_CTX context;
::sha256_init(&context);
::sha256_update(&context, input, input_length);
::sha256_final(&context, output);
}
void axolotl::hmac_sha256(
std::uint8_t const * key, std::size_t key_length,
std::uint8_t const * input, std::size_t input_length,
......@@ -184,14 +194,13 @@ void axolotl::hmac_sha256(
void axolotl::hkdf_sha256(
std::uint8_t const * input, std::size_t input_length,
std::uint8_t const * info, std::size_t info_length,
std::uint8_t const * salt, std::size_t salt_length,
std::uint8_t const * info, std::size_t info_length,
std::uint8_t * output, std::size_t output_length
) {
::SHA256_CTX context;
std::uint8_t extract_key[SHA256_BLOCK_LENGTH];
std::uint8_t expand_key[SHA256_BLOCK_LENGTH];
std::uint8_t step_result[SHA256_BLOCK_LENGTH];
std::uint8_t hmac_key[SHA256_BLOCK_LENGTH];
std::uint8_t step_result[SHA256_HASH_LENGTH];
std::size_t bytes_remaining = output_length;
std::uint8_t iteration = 1;
if (!salt) {
......@@ -199,25 +208,27 @@ void axolotl::hkdf_sha256(
salt_length = sizeof(HKDF_DEFAULT_SALT);
}
/* Expand */
hmac_sha256_key(salt, salt_length, extract_key);
hmac_sha256_init(&context, extract_key);
hmac_sha256_key(salt, salt_length, hmac_key);
hmac_sha256_init(&context, hmac_key);
::sha256_update(&context, input, input_length);
hmac_sha256_final(&context, extract_key, expand_key);
hmac_sha256_final(&context, hmac_key, step_result);
hmac_sha256_key(step_result, SHA256_HASH_LENGTH, hmac_key);
/* Extract */
hmac_sha256_init(&context, expand_key);
hmac_sha256_init(&context, hmac_key);
::sha256_update(&context, info, info_length);
::sha256_update(&context, &iteration, 1);
hmac_sha256_final(&context, expand_key, step_result);
while (bytes_remaining > SHA256_BLOCK_LENGTH) {
std::memcpy(output, step_result, SHA256_BLOCK_LENGTH);
output += SHA256_BLOCK_LENGTH;
bytes_remaining -= SHA256_BLOCK_LENGTH;
hmac_sha256_final(&context, hmac_key, step_result);
while (bytes_remaining > SHA256_HASH_LENGTH) {
std::memcpy(output, step_result, SHA256_HASH_LENGTH);
output += SHA256_HASH_LENGTH;
bytes_remaining -= SHA256_HASH_LENGTH;
iteration ++;
hmac_sha256_init(&context, expand_key);
::sha256_update(&context, step_result, SHA256_BLOCK_LENGTH);
hmac_sha256_init(&context, hmac_key);
::sha256_update(&context, step_result, SHA256_HASH_LENGTH);
::sha256_update(&context, info, info_length);
::sha256_update(&context, &iteration, 1);
hmac_sha256_final(&context, expand_key, step_result);
hmac_sha256_final(&context, hmac_key, step_result);
}
std::memcpy(output, step_result, bytes_remaining);
}
......@@ -36,7 +36,137 @@ void assert_equals(
int main() {
{ /* Curve25529 Test Case 1 */
TEST_CASE = "Curve25529 Test Case 1";
std::uint8_t alice_private[32] = {
0x77, 0x07, 0x6D, 0x0A, 0x73, 0x18, 0xA5, 0x7D,
0x3C, 0x16, 0xC1, 0x72, 0x51, 0xB2, 0x66, 0x45,
0xDF, 0x4C, 0x2F, 0x87, 0xEB, 0xC0, 0x99, 0x2A,
0xB1, 0x77, 0xFB, 0xA5, 0x1D, 0xB9, 0x2C, 0x2A
};
std::uint8_t alice_public[32] = {
0x85, 0x20, 0xF0, 0x09, 0x89, 0x30, 0xA7, 0x54,
0x74, 0x8B, 0x7D, 0xDC, 0xB4, 0x3E, 0xF7, 0x5A,
0x0D, 0xBF, 0x3A, 0x0D, 0x26, 0x38, 0x1A, 0xF4,
0xEB, 0xA4, 0xA9, 0x8E, 0xAA, 0x9B, 0x4E, 0x6A
};
std::uint8_t bob_private[32] = {
0x5D, 0xAB, 0x08, 0x7E, 0x62, 0x4A, 0x8A, 0x4B,
0x79, 0xE1, 0x7F, 0x8B, 0x83, 0x80, 0x0E, 0xE6,
0x6F, 0x3B, 0xB1, 0x29, 0x26, 0x18, 0xB6, 0xFD,
0x1C, 0x2F, 0x8B, 0x27, 0xFF, 0x88, 0xE0, 0xEB
};
std::uint8_t bob_public[32] = {
0xDE, 0x9E, 0xDB, 0x7D, 0x7B, 0x7D, 0xC1, 0xB4,
0xD3, 0x5B, 0x61, 0xC2, 0xEC, 0xE4, 0x35, 0x37,
0x3F, 0x83, 0x43, 0xC8, 0x5B, 0x78, 0x67, 0x4D,
0xAD, 0xFC, 0x7E, 0x14, 0x6F, 0x88, 0x2B, 0x4F
};
std::uint8_t expected_agreement[32] = {
0x4A, 0x5D, 0x9D, 0x5B, 0xA4, 0xCE, 0x2D, 0xE1,
0x72, 0x8E, 0x3B, 0xF4, 0x80, 0x35, 0x0F, 0x25,
0xE0, 0x7E, 0x21, 0xC9, 0x47, 0xD1, 0x9E, 0x33,
0x76, 0xF0, 0x9B, 0x3C, 0x1E, 0x16, 0x17, 0x42
};
axolotl::Curve25519KeyPair alice_pair = axolotl::generate_key(alice_private);
assert_equals(alice_private, alice_pair.private_key, 32);
assert_equals(alice_public, alice_pair.public_key, 32);
axolotl::Curve25519KeyPair bob_pair = axolotl::generate_key(bob_private);
assert_equals(bob_private, bob_pair.private_key, 32);
assert_equals(bob_public, bob_pair.public_key, 32);
std::uint8_t actual_agreement[axolotl::CURVE25519_SHARED_SECRET_LENGTH] = {};
axolotl::curve25519_shared_secret(alice_pair, bob_pair, actual_agreement);
assert_equals(expected_agreement, actual_agreement, 32);
axolotl::curve25519_shared_secret(bob_pair, alice_pair, actual_agreement);
assert_equals(expected_agreement, actual_agreement, 32);
} /* Curve25529 Test Case 1 */
{ /* AES Test Case 1 */
TEST_CASE = "AES Test Case 1";
axolotl::Aes256Key key = {};
axolotl::Aes256Iv iv = {};
std::uint8_t input[32] = {};
std::uint8_t expected[32] = {
0xDC, 0x95, 0xC0, 0x78, 0xA2, 0x40, 0x89, 0x89,
0xAD, 0x48, 0xA2, 0x14, 0x92, 0x84, 0x20, 0x87,
0x08, 0xC3, 0x74, 0x84, 0x8C, 0x22, 0x82, 0x33,
0xC2, 0xB3, 0x4F, 0x33, 0x2B, 0xD2, 0xE9, 0xD3
};
std::uint8_t actual[32] = {};
axolotl::aes_encrypt_cbc(key, iv, input, sizeof(input), actual);
assert_equals(expected, actual, 32);
axolotl::aes_decrypt_cbc(key, iv, expected, sizeof(expected), actual);
assert_equals(input, actual, 32);
} /* AES Test Case 1 */
{ /* SHA 256 Test Case 1 */
TEST_CASE = "SHA 256 Test Case 1";
std::uint8_t input[0] = {};
std::uint8_t expected[32] = {
0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14,
0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24,
0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C,
0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55
};
std::uint8_t actual[32];
axolotl::sha256(input, sizeof(input), actual);
assert_equals(expected, actual, 32);
} /* SHA 256 Test Case 1 */
{ /* HMAC Test Case 1 */
TEST_CASE = "HMAC Test Case 1";
std::uint8_t input[0] = {};
std::uint8_t expected[32] = {
0xb6, 0x13, 0x67, 0x9a, 0x08, 0x14, 0xd9, 0xec,
0x77, 0x2f, 0x95, 0xd7, 0x78, 0xc3, 0x5f, 0xc5,
0xff, 0x16, 0x97, 0xc4, 0x93, 0x71, 0x56, 0x53,
0xc6, 0xc7, 0x12, 0x14, 0x42, 0x92, 0xc5, 0xad
};
std::uint8_t actual[32];
axolotl::hmac_sha256(input, sizeof(input), input, sizeof(input), actual);
assert_equals(expected, actual, 32);
} /* HMAC Test Case 1 */
{ /* HDKF Test Case 1 */
......@@ -68,8 +198,8 @@ std::uint8_t hmac_expected_output[32] = {
std::uint8_t hmac_actual_output[32] = {};
axolotl::hmac_sha256(
salt, 0 * sizeof(salt),
input, 0 * sizeof(input),
salt, sizeof(salt),
input, sizeof(input),
hmac_actual_output
);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment