blob: d56910a23a1b55f67f04a79bc0132f9db6f09737 [file] [log] [blame]
// Copyright 2018 The Fuchsia 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 "peridot/bin/ledger/encryption/primitives/encrypt.h"
#include <openssl/aead.h>
#include <zircon/syscalls.h>
namespace encryption {
bool AES128GCMSIVEncrypt(rng::Random* random, fxl::StringView key,
fxl::StringView data, std::string* output) {
if (key.size() != 16) {
return false;
}
const EVP_AEAD* algorithm = EVP_aead_aes_128_gcm_siv();
const size_t kNonceOffset = 0;
const size_t kNonceSize = EVP_AEAD_nonce_length(algorithm);
const size_t kTagOffset = kNonceOffset + kNonceSize;
const size_t kTagSize = EVP_AEAD_max_tag_len(algorithm);
const size_t kEncryptedDataOffset = kTagOffset + kTagSize;
bssl::ScopedEVP_AEAD_CTX ctx;
if (!EVP_AEAD_CTX_init_with_direction(
ctx.get(), algorithm, reinterpret_cast<const uint8_t*>(key.data()),
key.size(), EVP_AEAD_DEFAULT_TAG_LENGTH, evp_aead_seal)) {
return false;
}
std::string result;
result.resize(kEncryptedDataOffset + data.size() +
EVP_AEAD_max_overhead(algorithm));
uint8_t* result_as_int8_ptr = reinterpret_cast<uint8_t*>(&result[0]);
// Generate seed.
random->Draw(&result[0], EVP_AEAD_nonce_length(algorithm));
size_t out_len;
if (EVP_AEAD_CTX_seal(
ctx.get(), &result_as_int8_ptr[kEncryptedDataOffset], &out_len,
data.size() + EVP_AEAD_max_overhead(algorithm),
&result_as_int8_ptr[kNonceOffset], kNonceSize,
reinterpret_cast<const uint8_t*>(data.data()), data.size(),
&result_as_int8_ptr[kTagOffset], kTagSize) == 0) {
return false;
}
result.resize(kEncryptedDataOffset + out_len);
output->swap(result);
return true;
}
bool AES128GCMSIVDecrypt(fxl::StringView key, fxl::StringView encrypted_data,
std::string* output) {
if (key.size() != 16) {
return false;
}
const EVP_AEAD* algorithm = EVP_aead_aes_128_gcm_siv();
const size_t kNonceOffset = 0;
const size_t kNonceSize = EVP_AEAD_nonce_length(algorithm);
const size_t kTagOffset = kNonceOffset + kNonceSize;
const size_t kTagSize = EVP_AEAD_max_tag_len(algorithm);
const size_t kEncryptedDataOffset = kTagOffset + kTagSize;
if (encrypted_data.size() < kEncryptedDataOffset) {
return false;
}
const size_t kEncryptedDataSize =
encrypted_data.size() - kEncryptedDataOffset;
bssl::ScopedEVP_AEAD_CTX ctx;
if (!EVP_AEAD_CTX_init_with_direction(
ctx.get(), algorithm, reinterpret_cast<const uint8_t*>(key.data()),
key.size(), EVP_AEAD_DEFAULT_TAG_LENGTH, evp_aead_open)) {
return false;
}
const uint8_t* encrypted_data_as_uint8_ptr =
reinterpret_cast<const uint8_t*>(encrypted_data.data());
std::string result;
result.resize(kEncryptedDataSize);
size_t out_len;
if (EVP_AEAD_CTX_open(
ctx.get(), reinterpret_cast<uint8_t*>(&result[0]), &out_len,
result.size(), &encrypted_data_as_uint8_ptr[kNonceOffset], kNonceSize,
&encrypted_data_as_uint8_ptr[kEncryptedDataOffset],
kEncryptedDataSize, &encrypted_data_as_uint8_ptr[kTagOffset],
kTagSize) == 0) {
return false;
}
result.resize(out_len);
output->swap(result);
return true;
}
} // namespace encryption