diff --git a/include/olm/crypto.h b/include/olm/crypto.h new file mode 100644 index 0000000..1357834 --- /dev/null +++ b/include/olm/crypto.h @@ -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 +#include + +#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_ */ diff --git a/include/olm/crypto.hh b/include/olm/crypto.hh index 7a05f8d..64e8f7d 100644 --- a/include/olm/crypto.hh +++ b/include/olm/crypto.hh @@ -18,6 +18,11 @@ #include #include +// 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 { 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 #endif /* OLM_CRYPTO_HH_ */ diff --git a/src/cipher.cpp b/src/cipher.cpp index 7bb11b8..a550312 100644 --- a/src/cipher.cpp +++ b/src/cipher.cpp @@ -36,7 +36,7 @@ static void derive_keys( DerivedKeys & keys ) { std::uint8_t derived_secrets[2 * olm::KEY_LENGTH + olm::IV_LENGTH]; - olm::hkdf_sha256( + crypto_hkdf_sha256( key, key_length, nullptr, 0, kdf_info, kdf_info_length, @@ -83,7 +83,7 @@ std::size_t olm::CipherAesSha256::encrypt( return std::size_t(-1); } 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); @@ -91,7 +91,7 @@ std::size_t olm::CipherAesSha256::encrypt( 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 ); @@ -115,11 +115,11 @@ std::size_t olm::CipherAesSha256::decrypt( std::uint8_t * plaintext, std::size_t max_plaintext_length ) const { 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); - olm::hmac_sha256( + crypto_hmac_sha256( keys.mac_key, olm::KEY_LENGTH, input, input_length - MAC_LENGTH, mac ); diff --git a/src/crypto.cpp b/src/crypto.cpp index ffe2661..175b323 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -85,7 +85,7 @@ inline static void hmac_sha256_final( std::uint8_t const * hmac_key, 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); for (std::size_t i = 0; i < SHA256_BLOCK_LENGTH; ++i) { 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 * 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 * input, std::size_t input_length, 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 * salt, std::size_t salt_length, std::uint8_t const * info, std::size_t info_length, @@ -291,7 +291,7 @@ void olm::hkdf_sha256( ) { ::SHA256_CTX context; 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::uint8_t iteration = 1; if (!salt) { @@ -303,20 +303,20 @@ void olm::hkdf_sha256( hmac_sha256_init(&context, hmac_key); ::sha256_update(&context, input, input_length); 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 */ hmac_sha256_init(&context, hmac_key); ::sha256_update(&context, info, info_length); ::sha256_update(&context, &iteration, 1); hmac_sha256_final(&context, hmac_key, step_result); - while (bytes_remaining > olm::SHA256_OUTPUT_LENGTH) { - std::memcpy(output, step_result, olm::SHA256_OUTPUT_LENGTH); - output += olm::SHA256_OUTPUT_LENGTH; - bytes_remaining -= olm::SHA256_OUTPUT_LENGTH; + while (bytes_remaining > SHA256_OUTPUT_LENGTH) { + std::memcpy(output, step_result, SHA256_OUTPUT_LENGTH); + output += SHA256_OUTPUT_LENGTH; + bytes_remaining -= SHA256_OUTPUT_LENGTH; iteration ++; 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, &iteration, 1); hmac_sha256_final(&context, hmac_key, step_result); diff --git a/src/ratchet.cpp b/src/ratchet.cpp index b04099f..8b1f30b 100644 --- a/src/ratchet.cpp +++ b/src/ratchet.cpp @@ -50,7 +50,7 @@ static void create_chain_key( olm::SharedKey secret; olm::curve25519_shared_secret(our_key, their_key, secret); std::uint8_t derived_secrets[2 * olm::KEY_LENGTH]; - olm::hkdf_sha256( + crypto_hkdf_sha256( secret, sizeof(secret), root_key, sizeof(root_key), info.ratchet_info, info.ratchet_info_length, @@ -70,7 +70,7 @@ static void advance_chain_key( olm::ChainKey const & chain_key, olm::ChainKey & new_chain_key ) { - olm::hmac_sha256( + crypto_hmac_sha256( chain_key.key, sizeof(chain_key.key), CHAIN_KEY_SEED, sizeof(CHAIN_KEY_SEED), new_chain_key.key @@ -84,7 +84,7 @@ static void create_message_keys( olm::ChainKey const & chain_key, olm::KdfInfo const & info, olm::MessageKey & message_key) { - olm::hmac_sha256( + crypto_hmac_sha256( chain_key.key, sizeof(chain_key.key), MESSAGE_KEY_SEED, sizeof(MESSAGE_KEY_SEED), message_key.key @@ -195,7 +195,7 @@ void olm::Ratchet::initialise_as_bob( olm::Curve25519PublicKey const & their_ratchet_key ) { std::uint8_t derived_secrets[2 * olm::KEY_LENGTH]; - olm::hkdf_sha256( + crypto_hkdf_sha256( shared_secret, shared_secret_length, nullptr, 0, 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 ) { std::uint8_t derived_secrets[2 * olm::KEY_LENGTH]; - olm::hkdf_sha256( + crypto_hkdf_sha256( shared_secret, shared_secret_length, nullptr, 0, kdf_info.root_info, kdf_info.root_info_length, diff --git a/src/session.cpp b/src/session.cpp index 86ba63b..85c958c 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -192,7 +192,7 @@ std::size_t olm::Session::new_inbound_session( 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_base_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(); } diff --git a/src/utility.cpp b/src/utility.cpp index bc51cff..2217778 100644 --- a/src/utility.cpp +++ b/src/utility.cpp @@ -23,7 +23,7 @@ olm::Utility::Utility( 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; return std::size_t(-1); } - olm::sha256(input, input_length, output); - return olm::SHA256_OUTPUT_LENGTH; + crypto_sha256(input, input_length, output); + return SHA256_OUTPUT_LENGTH; } diff --git a/tests/test_crypto.cpp b/tests/test_crypto.cpp index 4606c52..e86f3ab 100644 --- a/tests/test_crypto.cpp +++ b/tests/test_crypto.cpp @@ -186,7 +186,7 @@ std::uint8_t expected[32] = { std::uint8_t actual[32]; -olm::sha256(input, sizeof(input), actual); +crypto_sha256(input, sizeof(input), actual); assert_equals(expected, actual, 32); @@ -207,7 +207,7 @@ std::uint8_t expected[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); @@ -242,7 +242,7 @@ std::uint8_t hmac_expected_output[32] = { std::uint8_t hmac_actual_output[32] = {}; -olm::hmac_sha256( +crypto_hmac_sha256( salt, sizeof(salt), input, sizeof(input), hmac_actual_output @@ -261,7 +261,7 @@ std::uint8_t hkdf_expected_output[42] = { std::uint8_t hkdf_actual_output[42] = {}; -olm::hkdf_sha256( +crypto_hkdf_sha256( input, sizeof(input), salt, sizeof(salt), info, sizeof(info),