message_encrypter.cc 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/encrypted_messages/message_encrypter.h"
  5. #include "base/logging.h"
  6. #include "base/strings/string_piece.h"
  7. #include "components/encrypted_messages/encrypted_message.pb.h"
  8. #include "crypto/aead.h"
  9. #include "crypto/hkdf.h"
  10. #include "crypto/random.h"
  11. #include "third_party/boringssl/src/include/openssl/curve25519.h"
  12. namespace encrypted_messages {
  13. namespace {
  14. bool GetHkdfSubkeySecret(size_t subkey_length,
  15. const uint8_t* private_key,
  16. const uint8_t* public_key,
  17. base::StringPiece hkdf_label,
  18. std::string* secret) {
  19. uint8_t shared_secret[X25519_SHARED_KEY_LEN];
  20. if (!X25519(shared_secret, private_key, public_key))
  21. return false;
  22. base::StringPiece hkdf_input(reinterpret_cast<char*>(shared_secret),
  23. sizeof(shared_secret));
  24. *secret = crypto::HkdfSha256(hkdf_input, "", hkdf_label, subkey_length);
  25. return true;
  26. }
  27. } // namespace
  28. bool EncryptSerializedMessage(const uint8_t* server_public_key,
  29. uint32_t server_public_key_version,
  30. base::StringPiece hkdf_label,
  31. const std::string& message,
  32. EncryptedMessage* encrypted_message) {
  33. // Generate an ephemeral key pair to generate a shared secret.
  34. uint8_t public_key[X25519_PUBLIC_VALUE_LEN];
  35. uint8_t private_key[X25519_PRIVATE_KEY_LEN];
  36. crypto::RandBytes(private_key, sizeof(private_key));
  37. X25519_public_from_private(public_key, private_key);
  38. crypto::Aead aead(crypto::Aead::AES_128_CTR_HMAC_SHA256);
  39. std::string key;
  40. if (!GetHkdfSubkeySecret(aead.KeyLength(), private_key,
  41. reinterpret_cast<const uint8_t*>(server_public_key),
  42. hkdf_label, &key)) {
  43. LOG(ERROR) << "Error getting subkey secret.";
  44. return false;
  45. }
  46. aead.Init(&key);
  47. // Use an all-zero nonce because the key is random per-message.
  48. std::string nonce(aead.NonceLength(), '\0');
  49. std::string ciphertext;
  50. if (!aead.Seal(message, nonce, std::string(), &ciphertext)) {
  51. LOG(ERROR) << "Error sealing message.";
  52. return false;
  53. }
  54. encrypted_message->set_encrypted_message(ciphertext);
  55. encrypted_message->set_server_public_key_version(server_public_key_version);
  56. encrypted_message->set_client_public_key(reinterpret_cast<char*>(public_key),
  57. sizeof(public_key));
  58. encrypted_message->set_algorithm(
  59. EncryptedMessage::AEAD_ECDH_AES_128_CTR_HMAC_SHA256);
  60. return true;
  61. }
  62. // Used only by tests.
  63. bool DecryptMessageForTesting(const uint8_t server_private_key[32],
  64. base::StringPiece hkdf_label,
  65. const EncryptedMessage& encrypted_message,
  66. std::string* decrypted_serialized_message) {
  67. crypto::Aead aead(crypto::Aead::AES_128_CTR_HMAC_SHA256);
  68. std::string key;
  69. if (!GetHkdfSubkeySecret(aead.KeyLength(), server_private_key,
  70. reinterpret_cast<const uint8_t*>(
  71. encrypted_message.client_public_key().data()),
  72. hkdf_label, &key)) {
  73. LOG(ERROR) << "Error getting subkey secret.";
  74. return false;
  75. }
  76. aead.Init(&key);
  77. // Use an all-zero nonce because the key is random per-message.
  78. std::string nonce(aead.NonceLength(), 0);
  79. return aead.Open(encrypted_message.encrypted_message(), nonce, std::string(),
  80. decrypted_serialized_message);
  81. }
  82. } // namespace encrypted_messages