Give SHA256 functions C bindings

This commit is contained in:
Richard van der Hoff 2016-05-13 12:56:23 +01:00
parent 4f1bb49d20
commit e533b0dc8e
8 changed files with 100 additions and 62 deletions

65
include/olm/crypto.h Normal file
View file

@ -0,0 +1,65 @@
/* Copyright 2015 OpenMarket Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* C-compatible crpyto utility functions. At some point all of crypto.hh will
* move here.
*/
#ifndef OLM_CRYPTO_H_
#define OLM_CRYPTO_H_
#include <stdint.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
const size_t SHA256_OUTPUT_LENGTH = 32;
/** Computes SHA-256 of the input. The output buffer must be a least 32
* bytes long. */
void crypto_sha256(
uint8_t const * input, size_t input_length,
uint8_t * output
);
/** HMAC: Keyed-Hashing for Message Authentication
* http://tools.ietf.org/html/rfc2104
* Computes HMAC-SHA-256 of the input for the key. The output buffer must
* be at least 32 bytes long. */
void crypto_hmac_sha256(
uint8_t const * key, size_t key_length,
uint8_t const * input, size_t input_length,
uint8_t * output
);
/** HMAC-based Key Derivation Function (HKDF)
* https://tools.ietf.org/html/rfc5869
* Derives key material from the input bytes. */
void crypto_hkdf_sha256(
uint8_t const * input, size_t input_length,
uint8_t const * info, size_t info_length,
uint8_t const * salt, size_t salt_length,
uint8_t * output, size_t output_length
);
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* OLM_CRYPTO_H_ */

View file

@ -18,6 +18,11 @@
#include <cstdint> #include <cstdint>
#include <cstddef> #include <cstddef>
// eventually all of this needs to move into crypto.h, and everything should
// use that. For now, include crypto.h here.
#include "olm/crypto.h"
namespace olm { namespace olm {
static const std::size_t KEY_LENGTH = 32; static const std::size_t KEY_LENGTH = 32;
@ -142,38 +147,6 @@ std::size_t aes_decrypt_cbc(
); );
/** Computes SHA-256 of the input. The output buffer must be a least 32
* bytes long. */
void sha256(
std::uint8_t const * input, std::size_t input_length,
std::uint8_t * output
);
const std::size_t SHA256_OUTPUT_LENGTH = 32;
/** HMAC: Keyed-Hashing for Message Authentication
* http://tools.ietf.org/html/rfc2104
* Computes HMAC-SHA-256 of the input for the key. The output buffer must
* be at least 32 bytes long. */
void hmac_sha256(
std::uint8_t const * key, std::size_t key_length,
std::uint8_t const * input, std::size_t input_length,
std::uint8_t * output
);
/** HMAC-based Key Derivation Function (HKDF)
* https://tools.ietf.org/html/rfc5869
* Derives key material from the input bytes. */
void 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 * output, std::size_t output_length
);
} // namespace olm } // namespace olm
#endif /* OLM_CRYPTO_HH_ */ #endif /* OLM_CRYPTO_HH_ */

View file

@ -36,7 +36,7 @@ static void derive_keys(
DerivedKeys & keys DerivedKeys & keys
) { ) {
std::uint8_t derived_secrets[2 * olm::KEY_LENGTH + olm::IV_LENGTH]; std::uint8_t derived_secrets[2 * olm::KEY_LENGTH + olm::IV_LENGTH];
olm::hkdf_sha256( crypto_hkdf_sha256(
key, key_length, key, key_length,
nullptr, 0, nullptr, 0,
kdf_info, kdf_info_length, kdf_info, kdf_info_length,
@ -83,7 +83,7 @@ std::size_t olm::CipherAesSha256::encrypt(
return std::size_t(-1); return std::size_t(-1);
} }
struct DerivedKeys keys; struct DerivedKeys keys;
std::uint8_t mac[olm::SHA256_OUTPUT_LENGTH]; std::uint8_t mac[SHA256_OUTPUT_LENGTH];
derive_keys(kdf_info, kdf_info_length, key, key_length, keys); derive_keys(kdf_info, kdf_info_length, key, key_length, keys);
@ -91,7 +91,7 @@ std::size_t olm::CipherAesSha256::encrypt(
keys.aes_key, keys.aes_iv, plaintext, plaintext_length, ciphertext keys.aes_key, keys.aes_iv, plaintext, plaintext_length, ciphertext
); );
olm::hmac_sha256( crypto_hmac_sha256(
keys.mac_key, olm::KEY_LENGTH, output, output_length - MAC_LENGTH, mac keys.mac_key, olm::KEY_LENGTH, output, output_length - MAC_LENGTH, mac
); );
@ -115,11 +115,11 @@ std::size_t olm::CipherAesSha256::decrypt(
std::uint8_t * plaintext, std::size_t max_plaintext_length std::uint8_t * plaintext, std::size_t max_plaintext_length
) const { ) const {
DerivedKeys keys; DerivedKeys keys;
std::uint8_t mac[olm::SHA256_OUTPUT_LENGTH]; std::uint8_t mac[SHA256_OUTPUT_LENGTH];
derive_keys(kdf_info, kdf_info_length, key, key_length, keys); derive_keys(kdf_info, kdf_info_length, key, key_length, keys);
olm::hmac_sha256( crypto_hmac_sha256(
keys.mac_key, olm::KEY_LENGTH, input, input_length - MAC_LENGTH, mac keys.mac_key, olm::KEY_LENGTH, input, input_length - MAC_LENGTH, mac
); );

View file

@ -85,7 +85,7 @@ inline static void hmac_sha256_final(
std::uint8_t const * hmac_key, std::uint8_t const * hmac_key,
std::uint8_t * output std::uint8_t * output
) { ) {
std::uint8_t o_pad[SHA256_BLOCK_LENGTH + olm::SHA256_OUTPUT_LENGTH]; std::uint8_t o_pad[SHA256_BLOCK_LENGTH + SHA256_OUTPUT_LENGTH];
std::memcpy(o_pad, hmac_key, SHA256_BLOCK_LENGTH); std::memcpy(o_pad, hmac_key, SHA256_BLOCK_LENGTH);
for (std::size_t i = 0; i < SHA256_BLOCK_LENGTH; ++i) { for (std::size_t i = 0; i < SHA256_BLOCK_LENGTH; ++i) {
o_pad[i] ^= 0x5C; o_pad[i] ^= 0x5C;
@ -255,7 +255,7 @@ std::size_t olm::aes_decrypt_cbc(
} }
void olm::sha256( void crypto_sha256(
std::uint8_t const * input, std::size_t input_length, std::uint8_t const * input, std::size_t input_length,
std::uint8_t * output std::uint8_t * output
) { ) {
@ -267,7 +267,7 @@ void olm::sha256(
} }
void olm::hmac_sha256( void crypto_hmac_sha256(
std::uint8_t const * key, std::size_t key_length, std::uint8_t const * key, std::size_t key_length,
std::uint8_t const * input, std::size_t input_length, std::uint8_t const * input, std::size_t input_length,
std::uint8_t * output std::uint8_t * output
@ -283,7 +283,7 @@ void olm::hmac_sha256(
} }
void olm::hkdf_sha256( void crypto_hkdf_sha256(
std::uint8_t const * input, std::size_t input_length, std::uint8_t const * input, std::size_t input_length,
std::uint8_t const * salt, std::size_t salt_length, std::uint8_t const * salt, std::size_t salt_length,
std::uint8_t const * info, std::size_t info_length, std::uint8_t const * info, std::size_t info_length,
@ -291,7 +291,7 @@ void olm::hkdf_sha256(
) { ) {
::SHA256_CTX context; ::SHA256_CTX context;
std::uint8_t hmac_key[SHA256_BLOCK_LENGTH]; std::uint8_t hmac_key[SHA256_BLOCK_LENGTH];
std::uint8_t step_result[olm::SHA256_OUTPUT_LENGTH]; std::uint8_t step_result[SHA256_OUTPUT_LENGTH];
std::size_t bytes_remaining = output_length; std::size_t bytes_remaining = output_length;
std::uint8_t iteration = 1; std::uint8_t iteration = 1;
if (!salt) { if (!salt) {
@ -303,20 +303,20 @@ void olm::hkdf_sha256(
hmac_sha256_init(&context, hmac_key); hmac_sha256_init(&context, hmac_key);
::sha256_update(&context, input, input_length); ::sha256_update(&context, input, input_length);
hmac_sha256_final(&context, hmac_key, step_result); hmac_sha256_final(&context, hmac_key, step_result);
hmac_sha256_key(step_result, olm::SHA256_OUTPUT_LENGTH, hmac_key); hmac_sha256_key(step_result, SHA256_OUTPUT_LENGTH, hmac_key);
/* Expand */ /* Expand */
hmac_sha256_init(&context, hmac_key); hmac_sha256_init(&context, hmac_key);
::sha256_update(&context, info, info_length); ::sha256_update(&context, info, info_length);
::sha256_update(&context, &iteration, 1); ::sha256_update(&context, &iteration, 1);
hmac_sha256_final(&context, hmac_key, step_result); hmac_sha256_final(&context, hmac_key, step_result);
while (bytes_remaining > olm::SHA256_OUTPUT_LENGTH) { while (bytes_remaining > SHA256_OUTPUT_LENGTH) {
std::memcpy(output, step_result, olm::SHA256_OUTPUT_LENGTH); std::memcpy(output, step_result, SHA256_OUTPUT_LENGTH);
output += olm::SHA256_OUTPUT_LENGTH; output += SHA256_OUTPUT_LENGTH;
bytes_remaining -= olm::SHA256_OUTPUT_LENGTH; bytes_remaining -= SHA256_OUTPUT_LENGTH;
iteration ++; iteration ++;
hmac_sha256_init(&context, hmac_key); hmac_sha256_init(&context, hmac_key);
::sha256_update(&context, step_result, olm::SHA256_OUTPUT_LENGTH); ::sha256_update(&context, step_result, SHA256_OUTPUT_LENGTH);
::sha256_update(&context, info, info_length); ::sha256_update(&context, info, info_length);
::sha256_update(&context, &iteration, 1); ::sha256_update(&context, &iteration, 1);
hmac_sha256_final(&context, hmac_key, step_result); hmac_sha256_final(&context, hmac_key, step_result);

View file

@ -50,7 +50,7 @@ static void create_chain_key(
olm::SharedKey secret; olm::SharedKey secret;
olm::curve25519_shared_secret(our_key, their_key, secret); olm::curve25519_shared_secret(our_key, their_key, secret);
std::uint8_t derived_secrets[2 * olm::KEY_LENGTH]; std::uint8_t derived_secrets[2 * olm::KEY_LENGTH];
olm::hkdf_sha256( crypto_hkdf_sha256(
secret, sizeof(secret), secret, sizeof(secret),
root_key, sizeof(root_key), root_key, sizeof(root_key),
info.ratchet_info, info.ratchet_info_length, info.ratchet_info, info.ratchet_info_length,
@ -70,7 +70,7 @@ static void advance_chain_key(
olm::ChainKey const & chain_key, olm::ChainKey const & chain_key,
olm::ChainKey & new_chain_key olm::ChainKey & new_chain_key
) { ) {
olm::hmac_sha256( crypto_hmac_sha256(
chain_key.key, sizeof(chain_key.key), chain_key.key, sizeof(chain_key.key),
CHAIN_KEY_SEED, sizeof(CHAIN_KEY_SEED), CHAIN_KEY_SEED, sizeof(CHAIN_KEY_SEED),
new_chain_key.key new_chain_key.key
@ -84,7 +84,7 @@ static void create_message_keys(
olm::ChainKey const & chain_key, olm::ChainKey const & chain_key,
olm::KdfInfo const & info, olm::KdfInfo const & info,
olm::MessageKey & message_key) { olm::MessageKey & message_key) {
olm::hmac_sha256( crypto_hmac_sha256(
chain_key.key, sizeof(chain_key.key), chain_key.key, sizeof(chain_key.key),
MESSAGE_KEY_SEED, sizeof(MESSAGE_KEY_SEED), MESSAGE_KEY_SEED, sizeof(MESSAGE_KEY_SEED),
message_key.key message_key.key
@ -195,7 +195,7 @@ void olm::Ratchet::initialise_as_bob(
olm::Curve25519PublicKey const & their_ratchet_key olm::Curve25519PublicKey const & their_ratchet_key
) { ) {
std::uint8_t derived_secrets[2 * olm::KEY_LENGTH]; std::uint8_t derived_secrets[2 * olm::KEY_LENGTH];
olm::hkdf_sha256( crypto_hkdf_sha256(
shared_secret, shared_secret_length, shared_secret, shared_secret_length,
nullptr, 0, nullptr, 0,
kdf_info.root_info, kdf_info.root_info_length, kdf_info.root_info, kdf_info.root_info_length,
@ -217,7 +217,7 @@ void olm::Ratchet::initialise_as_alice(
olm::Curve25519KeyPair const & our_ratchet_key olm::Curve25519KeyPair const & our_ratchet_key
) { ) {
std::uint8_t derived_secrets[2 * olm::KEY_LENGTH]; std::uint8_t derived_secrets[2 * olm::KEY_LENGTH];
olm::hkdf_sha256( crypto_hkdf_sha256(
shared_secret, shared_secret_length, shared_secret, shared_secret_length,
nullptr, 0, nullptr, 0,
kdf_info.root_info, kdf_info.root_info_length, kdf_info.root_info, kdf_info.root_info_length,

View file

@ -192,7 +192,7 @@ std::size_t olm::Session::new_inbound_session(
std::size_t olm::Session::session_id_length() { std::size_t olm::Session::session_id_length() {
return olm::SHA256_OUTPUT_LENGTH; return SHA256_OUTPUT_LENGTH;
} }
@ -208,7 +208,7 @@ std::size_t olm::Session::session_id(
pos = olm::store_array(pos, alice_identity_key.public_key); pos = olm::store_array(pos, alice_identity_key.public_key);
pos = olm::store_array(pos, alice_base_key.public_key); pos = olm::store_array(pos, alice_base_key.public_key);
pos = olm::store_array(pos, bob_one_time_key.public_key); pos = olm::store_array(pos, bob_one_time_key.public_key);
olm::sha256(tmp, sizeof(tmp), id); crypto_sha256(tmp, sizeof(tmp), id);
return session_id_length(); return session_id_length();
} }

View file

@ -23,7 +23,7 @@ olm::Utility::Utility(
size_t olm::Utility::sha256_length() { size_t olm::Utility::sha256_length() {
return olm::SHA256_OUTPUT_LENGTH; return SHA256_OUTPUT_LENGTH;
} }
@ -35,8 +35,8 @@ size_t olm::Utility::sha256(
last_error = olm::ErrorCode::OUTPUT_BUFFER_TOO_SMALL; last_error = olm::ErrorCode::OUTPUT_BUFFER_TOO_SMALL;
return std::size_t(-1); return std::size_t(-1);
} }
olm::sha256(input, input_length, output); crypto_sha256(input, input_length, output);
return olm::SHA256_OUTPUT_LENGTH; return SHA256_OUTPUT_LENGTH;
} }

View file

@ -186,7 +186,7 @@ std::uint8_t expected[32] = {
std::uint8_t actual[32]; std::uint8_t actual[32];
olm::sha256(input, sizeof(input), actual); crypto_sha256(input, sizeof(input), actual);
assert_equals(expected, actual, 32); assert_equals(expected, actual, 32);
@ -207,7 +207,7 @@ std::uint8_t expected[32] = {
std::uint8_t actual[32]; std::uint8_t actual[32];
olm::hmac_sha256(input, sizeof(input), input, sizeof(input), actual); crypto_hmac_sha256(input, sizeof(input), input, sizeof(input), actual);
assert_equals(expected, actual, 32); assert_equals(expected, actual, 32);
@ -242,7 +242,7 @@ std::uint8_t hmac_expected_output[32] = {
std::uint8_t hmac_actual_output[32] = {}; std::uint8_t hmac_actual_output[32] = {};
olm::hmac_sha256( crypto_hmac_sha256(
salt, sizeof(salt), salt, sizeof(salt),
input, sizeof(input), input, sizeof(input),
hmac_actual_output hmac_actual_output
@ -261,7 +261,7 @@ std::uint8_t hkdf_expected_output[42] = {
std::uint8_t hkdf_actual_output[42] = {}; std::uint8_t hkdf_actual_output[42] = {};
olm::hkdf_sha256( crypto_hkdf_sha256(
input, sizeof(input), input, sizeof(input),
salt, sizeof(salt), salt, sizeof(salt),
info, sizeof(info), info, sizeof(info),