123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- // Copyright 2017 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/encrypted_messages/message_encrypter.h"
- #include "base/logging.h"
- #include "base/strings/string_piece.h"
- #include "components/encrypted_messages/encrypted_message.pb.h"
- #include "crypto/aead.h"
- #include "crypto/hkdf.h"
- #include "crypto/random.h"
- #include "third_party/boringssl/src/include/openssl/curve25519.h"
- namespace encrypted_messages {
- namespace {
- bool GetHkdfSubkeySecret(size_t subkey_length,
- const uint8_t* private_key,
- const uint8_t* public_key,
- base::StringPiece hkdf_label,
- std::string* secret) {
- uint8_t shared_secret[X25519_SHARED_KEY_LEN];
- if (!X25519(shared_secret, private_key, public_key))
- return false;
- base::StringPiece hkdf_input(reinterpret_cast<char*>(shared_secret),
- sizeof(shared_secret));
- *secret = crypto::HkdfSha256(hkdf_input, "", hkdf_label, subkey_length);
- return true;
- }
- } // namespace
- bool EncryptSerializedMessage(const uint8_t* server_public_key,
- uint32_t server_public_key_version,
- base::StringPiece hkdf_label,
- const std::string& message,
- EncryptedMessage* encrypted_message) {
- // Generate an ephemeral key pair to generate a shared secret.
- uint8_t public_key[X25519_PUBLIC_VALUE_LEN];
- uint8_t private_key[X25519_PRIVATE_KEY_LEN];
- crypto::RandBytes(private_key, sizeof(private_key));
- X25519_public_from_private(public_key, private_key);
- crypto::Aead aead(crypto::Aead::AES_128_CTR_HMAC_SHA256);
- std::string key;
- if (!GetHkdfSubkeySecret(aead.KeyLength(), private_key,
- reinterpret_cast<const uint8_t*>(server_public_key),
- hkdf_label, &key)) {
- LOG(ERROR) << "Error getting subkey secret.";
- return false;
- }
- aead.Init(&key);
- // Use an all-zero nonce because the key is random per-message.
- std::string nonce(aead.NonceLength(), '\0');
- std::string ciphertext;
- if (!aead.Seal(message, nonce, std::string(), &ciphertext)) {
- LOG(ERROR) << "Error sealing message.";
- return false;
- }
- encrypted_message->set_encrypted_message(ciphertext);
- encrypted_message->set_server_public_key_version(server_public_key_version);
- encrypted_message->set_client_public_key(reinterpret_cast<char*>(public_key),
- sizeof(public_key));
- encrypted_message->set_algorithm(
- EncryptedMessage::AEAD_ECDH_AES_128_CTR_HMAC_SHA256);
- return true;
- }
- // Used only by tests.
- bool DecryptMessageForTesting(const uint8_t server_private_key[32],
- base::StringPiece hkdf_label,
- const EncryptedMessage& encrypted_message,
- std::string* decrypted_serialized_message) {
- crypto::Aead aead(crypto::Aead::AES_128_CTR_HMAC_SHA256);
- std::string key;
- if (!GetHkdfSubkeySecret(aead.KeyLength(), server_private_key,
- reinterpret_cast<const uint8_t*>(
- encrypted_message.client_public_key().data()),
- hkdf_label, &key)) {
- LOG(ERROR) << "Error getting subkey secret.";
- return false;
- }
- aead.Init(&key);
- // Use an all-zero nonce because the key is random per-message.
- std::string nonce(aead.NonceLength(), 0);
- return aead.Open(encrypted_message.encrypted_message(), nonce, std::string(),
- decrypted_serialized_message);
- }
- } // namespace encrypted_messages
|