Skip to content

Commit

Permalink
Add error messages to HPKE
Browse files Browse the repository at this point in the history
Bug: 345867252
Change-Id: I591a06ca76a34bbf64ef7d0846080baa53901d17
  • Loading branch information
ipetr0v committed Jun 27, 2024
1 parent 8e38fbd commit a011478
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 22 deletions.
4 changes: 2 additions & 2 deletions cc/crypto/encryptor_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ TEST(EncryptorTest,
auto server_decryption_result = server_encryptor.Decrypt(*client_ciphertext);
EXPECT_FALSE(server_decryption_result.ok());
EXPECT_EQ(server_decryption_result.status().code(),
absl::StatusCode::kAborted);
absl::StatusCode::kInvalidArgument);
EXPECT_THAT(server_decryption_result.status().message(),
StrEq("Unable to decrypt message"));
StrEq("Unable to decrypt message: code=101, reason=BAD_DECRYPT"));
}

} // namespace
Expand Down
29 changes: 19 additions & 10 deletions cc/crypto/hpke/recipient_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ absl::Status ValidateKeys(std::vector<uint8_t>& public_key_bytes,
/* kem= */ EVP_hpke_x25519_hkdf_sha256(),
/* priv_key= */ private_key_bytes.data(),
/* priv_key_len= */ private_key_bytes.size())) {
return absl::AbortedError("Failed to generate HPKE keys for validation");
return absl::InvalidArgumentError(GetLastErrorWithPrefix(
"Failed to generate HPKE keys from input for validation"));
}

std::vector<uint8_t> verified_public_key_bytes(public_key_bytes.size());
Expand All @@ -67,11 +68,13 @@ absl::Status ValidateKeys(std::vector<uint8_t>& public_key_bytes,
/* out= */ verified_public_key_bytes.data(),
/* out_len= */ &verfied_public_key_size,
/* max_out= */ verified_public_key_bytes.size())) {
return absl::AbortedError("Failed to get public key");
return absl::InvalidArgumentError(
GetLastErrorWithPrefix("Failed to get public key"));
}

if (public_key_bytes != verified_public_key_bytes) {
return absl::InvalidArgumentError("Public key does not match private key");
return absl::InvalidArgumentError(
"Public key does not correspond to the private key");
}
return absl::OkStatus();
}
Expand All @@ -85,7 +88,8 @@ absl::StatusOr<std::unique_ptr<RecipientContext>> RecipientContext::Deserialize(
/* key_len= */ session_keys.request_key().size(),
/* tag_len= */ 0));
if (request_aead_context == nullptr) {
return absl::AbortedError("Unable to deserialize request AEAD context");
return absl::InternalError(
GetLastErrorWithPrefix("Unable to deserialize request AEAD context"));
}

std::unique_ptr<EVP_AEAD_CTX> response_aead_context(EVP_AEAD_CTX_new(
Expand All @@ -94,7 +98,8 @@ absl::StatusOr<std::unique_ptr<RecipientContext>> RecipientContext::Deserialize(
/* key_len= */ session_keys.response_key().size(),
/* tag_len= */ 0));
if (response_aead_context == nullptr) {
return absl::AbortedError("Unable to deserialize response AEAD context");
return absl::InternalError(
GetLastErrorWithPrefix("Unable to deserialize response AEAD context"));
}

return std::make_unique<RecipientContext>(
Expand Down Expand Up @@ -154,7 +159,7 @@ absl::StatusOr<std::unique_ptr<RecipientContext>> SetupBaseRecipient(

std::unique_ptr<EVP_HPKE_CTX> hpke_recipient_context(EVP_HPKE_CTX_new());
if (hpke_recipient_context == nullptr) {
return absl::AbortedError("Unable to generate HPKE recipient context");
return absl::InternalError("Unable to generate HPKE recipient context");
}

if (!EVP_HPKE_CTX_setup_recipient(
Expand All @@ -166,7 +171,8 @@ absl::StatusOr<std::unique_ptr<RecipientContext>> SetupBaseRecipient(
/* enc_len= */ encap_public_key_bytes.size(),
/* info= */ info_bytes.data(),
/* info_len= */ info_bytes.size())) {
return absl::AbortedError("Unable to setup recipient context");
return absl::InvalidArgumentError(
GetLastErrorWithPrefix("Unable to setup recipient context"));
}

// Configure recipient request context.
Expand Down Expand Up @@ -205,7 +211,8 @@ absl::StatusOr<KeyPair> KeyPair::Generate() {
if (!EVP_HPKE_KEY_generate(
/* key= */ recipient_keys.get(),
/* kem= */ EVP_hpke_x25519_hkdf_sha256())) {
return absl::AbortedError("Failed to generate HPKE keys");
return absl::InternalError(
GetLastErrorWithPrefix("Failed to generate HPKE keys"));
}

std::vector<uint8_t> public_key_bytes(EVP_HPKE_MAX_PUBLIC_KEY_LENGTH);
Expand All @@ -215,7 +222,8 @@ absl::StatusOr<KeyPair> KeyPair::Generate() {
/* out= */ public_key_bytes.data(),
/* out_len= */ &public_key_bytes_len,
/* max_out= */ public_key_bytes.size())) {
return absl::AbortedError("Failed to retrieve public key");
return absl::InternalError(
GetLastErrorWithPrefix("Failed to retrieve public key"));
}
public_key_bytes.resize(public_key_bytes_len);

Expand All @@ -226,7 +234,8 @@ absl::StatusOr<KeyPair> KeyPair::Generate() {
/* out= */ private_key_bytes.data(),
/* out_len= */ &private_key_bytes_len,
/* max_out= */ private_key_bytes.size())) {
return absl::AbortedError("Failed to retrieve private key");
return absl::InternalError(
GetLastErrorWithPrefix("Failed to retrieve private key"));
}
private_key_bytes.resize(private_key_bytes_len);

Expand Down
3 changes: 2 additions & 1 deletion cc/crypto/hpke/recipient_context_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,8 @@ TEST_F(RecipientContextTest, RecipientRequestContextOpenFailure) {
(*recipient_context)
->Open(*nonce, edited_ciphertext, associated_data_request_);
EXPECT_FALSE(received_plaintext.ok());
EXPECT_EQ(received_plaintext.status().code(), absl::StatusCode::kAborted);
EXPECT_EQ(received_plaintext.status().code(),
absl::StatusCode::kInvalidArgument);
}

TEST_F(RecipientContextTest, RecipientResponseContextSealSuccess) {
Expand Down
5 changes: 3 additions & 2 deletions cc/crypto/hpke/sender_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ absl::StatusOr<std::unique_ptr<SenderContext>> SetupBaseSender(

std::unique_ptr<EVP_HPKE_CTX> hpke_sender_context(EVP_HPKE_CTX_new());
if (hpke_sender_context == nullptr) {
return absl::AbortedError("Unable to generate HPKE sender context");
return absl::InternalError("Unable to generate HPKE sender context");
}

if (!EVP_HPKE_CTX_setup_sender(
Expand All @@ -92,7 +92,8 @@ absl::StatusOr<std::unique_ptr<SenderContext>> SetupBaseSender(
/* peer_public_key_len= */ recipient_public_key_bytes.size(),
/* info= */ info_bytes.data(),
/* info_len= */ info_bytes.size())) {
return absl::AbortedError("Unable to setup sender context");
return absl::InvalidArgumentError(
GetLastErrorWithPrefix("Unable to setup sender context"));
}
encap_public_key_info.key_bytes.resize(encap_public_key_info.key_size);

Expand Down
6 changes: 4 additions & 2 deletions cc/crypto/hpke/sender_context_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,8 @@ TEST_F(SenderContextTest, SenderOpensEncryptedMessageFailureNoncesNotAligned) {
auto decyphered_message = sender_context.Open(
default_nonce_bytes_, ciphertext, associated_data_response_);
EXPECT_FALSE(decyphered_message.ok());
EXPECT_EQ(decyphered_message.status().code(), absl::StatusCode::kAborted);
EXPECT_EQ(decyphered_message.status().code(),
absl::StatusCode::kInvalidArgument);

// Cleanup the lingering context.
EVP_AEAD_CTX_free(response_aead_context_send.release());
Expand Down Expand Up @@ -267,7 +268,8 @@ TEST_F(SenderContextTest,
auto decyphered_message = sender_context.Open(
default_nonce_bytes_, ciphertext, different_associated_data);
EXPECT_FALSE(decyphered_message.ok());
EXPECT_EQ(decyphered_message.status().code(), absl::StatusCode::kAborted);
EXPECT_EQ(decyphered_message.status().code(),
absl::StatusCode::kInvalidArgument);

// Cleanup the lingering context.
EVP_AEAD_CTX_free(response_aead_context_send.release());
Expand Down
23 changes: 18 additions & 5 deletions cc/crypto/hpke/utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "openssl/aead.h"
#include "openssl/err.h"
#include "openssl/hpke.h"
#include "openssl/rand.h"

Expand All @@ -49,7 +50,7 @@ absl::StatusOr<std::unique_ptr<EVP_AEAD_CTX>> GetContext(
/* secret_len= */ key.size(),
/* context= */ key_context_bytes.data(),
/* context_len= */ key_context_bytes.size())) {
return absl::AbortedError("Unable to export key");
return absl::InternalError(GetLastErrorWithPrefix("Unable to export key"));
}

std::unique_ptr<EVP_AEAD_CTX> aead_context(EVP_AEAD_CTX_new(
Expand All @@ -59,7 +60,8 @@ absl::StatusOr<std::unique_ptr<EVP_AEAD_CTX>> GetContext(
/* tag_len= */ 0));

if (aead_context == nullptr) {
return absl::AbortedError("Unable to generate AEAD context");
return absl::InternalError(
GetLastErrorWithPrefix("Unable to generate AEAD context"));
}

return std::move(aead_context);
Expand All @@ -68,7 +70,8 @@ absl::StatusOr<std::unique_ptr<EVP_AEAD_CTX>> GetContext(
absl::StatusOr<std::vector<uint8_t>> GenerateRandomNonce() {
std::vector<uint8_t> nonce(kAeadNonceSizeBytes);
if (!RAND_bytes(nonce.data(), nonce.size())) {
return absl::AbortedError("Unable to generate random nonce");
return absl::InternalError(
GetLastErrorWithPrefix("Unable to generate random nonce"));
}
return nonce;
}
Expand Down Expand Up @@ -101,7 +104,8 @@ absl::StatusOr<std::string> AeadSeal(const EVP_AEAD_CTX* context,
/* in_len= */ plaintext_bytes.size(),
/* ad= */ associated_data_bytes.data(),
/* ad_len= */ associated_data_bytes.size())) {
return absl::AbortedError("Unable to encrypt message");
return absl::InvalidArgumentError(
GetLastErrorWithPrefix("Unable to encrypt message"));
}
ciphertext_bytes.resize(ciphertext_bytes_len);
std::string ciphertext(ciphertext_bytes.begin(), ciphertext_bytes.end());
Expand Down Expand Up @@ -134,11 +138,20 @@ absl::StatusOr<std::string> AeadOpen(const EVP_AEAD_CTX* context,
/* in_len= */ ciphertext_bytes.size(),
/* ad= */ associated_data_bytes.data(),
/* ad_len= */ associated_data_bytes.size())) {
return absl::AbortedError("Unable to decrypt message");
return absl::InvalidArgumentError(
GetLastErrorWithPrefix("Unable to decrypt message"));
}
plaintext_bytes.resize(plaintext_bytes_size);
std::string plaintext(plaintext_bytes.begin(), plaintext_bytes.end());
return plaintext;
}

// Gets latest from the OpenSSL error queue and return it's corresponding reason
// string with a `prefix`.
std::string GetLastErrorWithPrefix(absl::string_view prefix) {
int error = ERR_peek_last_error();
return absl::StrFormat("%s: code=%d, reason=%s", prefix,
ERR_GET_REASON(error), ERR_reason_error_string(error));
}

} // namespace oak::crypto
3 changes: 3 additions & 0 deletions cc/crypto/hpke/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "openssl/aead.h"
#include "openssl/err.h"
#include "openssl/hpke.h"

namespace oak::crypto {
Expand Down Expand Up @@ -71,5 +72,7 @@ absl::StatusOr<std::string> AeadOpen(const EVP_AEAD_CTX* context,
absl::string_view ciphertext,
absl::string_view associated_data);

std::string GetLastErrorWithPrefix(absl::string_view prefix);

} // namespace oak::crypto
#endif // CC_CRYPTO_HPKE_CONSTANTS_H_

0 comments on commit a011478

Please sign in to comment.