Fix pairing aes_128_gcm key initialization.
Bug: 150719467 Test: atest adb_pairing_auth_test Test: check 'adb pair' command on all three platforms work Change-Id: Idfc64fe7bed2d09f4da9d2f7df70f9d6ae4e8fa3
This commit is contained in:
parent
5eb308766e
commit
aed3408f47
7 changed files with 69 additions and 356 deletions
|
@ -19,7 +19,6 @@
|
|||
#include <android-base/endian.h>
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hkdf.h>
|
||||
#include <openssl/rand.h>
|
||||
|
@ -28,155 +27,64 @@ namespace adb {
|
|||
namespace pairing {
|
||||
|
||||
namespace {
|
||||
static const size_t kHkdfKeyLength = 256;
|
||||
|
||||
struct Header {
|
||||
uint32_t payload;
|
||||
uint8_t iv[AES_128_GCM_IV_SIZE];
|
||||
uint8_t tag[AES_128_GCM_TAG_SIZE];
|
||||
} __attribute__((packed));
|
||||
// Size of AES-128-GCM key, in bytes
|
||||
static constexpr size_t kHkdfKeyLength = 16;
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
const EVP_CIPHER* Aes128Gcm::cipher_ = EVP_aes_128_gcm();
|
||||
|
||||
Aes128Gcm::Aes128Gcm(const uint8_t* key_material, size_t key_material_len) {
|
||||
CHECK(key_material);
|
||||
CHECK_NE(key_material_len, 0ul);
|
||||
context_.reset(EVP_CIPHER_CTX_new());
|
||||
CHECK(context_.get());
|
||||
|
||||
// Start with a random number for our counter
|
||||
CHECK_EQ(RAND_bytes(counter_.data(), counter_.size()), 1);
|
||||
|
||||
uint8_t key[kHkdfKeyLength] = {};
|
||||
uint8_t salt[64] = "this is the salt";
|
||||
uint8_t info[64] = "this is the info";
|
||||
CHECK_EQ(HKDF(key, sizeof(key), EVP_sha256(), key_material, key_material_len, salt,
|
||||
sizeof(salt), info, sizeof(info)),
|
||||
uint8_t key[kHkdfKeyLength];
|
||||
uint8_t info[] = "adb pairing_auth aes-128-gcm key";
|
||||
CHECK_EQ(HKDF(key, sizeof(key), EVP_sha256(), key_material, key_material_len, nullptr, 0, info,
|
||||
sizeof(info) - 1),
|
||||
1);
|
||||
CHECK_EQ(AES_set_encrypt_key(key, sizeof(key), &aes_key_), 0);
|
||||
CHECK(EVP_AEAD_CTX_init(context_.get(), EVP_aead_aes_128_gcm(), key, sizeof(key),
|
||||
EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
|
||||
}
|
||||
|
||||
int Aes128Gcm::Encrypt(const uint8_t* in, size_t in_len, uint8_t* out, size_t out_len) {
|
||||
if (out_len < EncryptedSize(in_len)) {
|
||||
LOG(ERROR) << "out buffer size (sz=" << out_len
|
||||
<< ") not big enough (sz=" << EncryptedSize(in_len) << ")";
|
||||
return -1;
|
||||
}
|
||||
auto& header = *reinterpret_cast<Header*>(out);
|
||||
// Place the IV in the header
|
||||
memcpy(header.iv, counter_.data(), counter_.size());
|
||||
int status = EVP_EncryptInit_ex(context_.get(), cipher_, nullptr,
|
||||
reinterpret_cast<const uint8_t*>(&aes_key_), counter_.data());
|
||||
counter_.Increase();
|
||||
if (status != 1) {
|
||||
return -1;
|
||||
std::optional<size_t> Aes128Gcm::Encrypt(const uint8_t* in, size_t in_len, uint8_t* out,
|
||||
size_t out_len) {
|
||||
std::vector<uint8_t> nonce(EVP_AEAD_nonce_length(EVP_AEAD_CTX_aead(context_.get())), 0);
|
||||
memcpy(nonce.data(), &enc_sequence_, sizeof(enc_sequence_));
|
||||
size_t written_sz;
|
||||
if (!EVP_AEAD_CTX_seal(context_.get(), out, &written_sz, out_len, nonce.data(), nonce.size(),
|
||||
in, in_len, nullptr, 0)) {
|
||||
LOG(ERROR) << "Failed to encrypt (in_len=" << in_len << ", out_len=" << out_len
|
||||
<< ", out_len_needed=" << EncryptedSize(in_len) << ")";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
int cipherLen = 0;
|
||||
out += sizeof(header);
|
||||
status = EVP_EncryptUpdate(context_.get(), out, &cipherLen, in, in_len);
|
||||
if (status != 1 || cipherLen < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Padding is enabled by default, so EVP_EncryptFinal_ex will pad any
|
||||
// remaining partial data up to the block size.
|
||||
int padding = 0;
|
||||
status = EVP_EncryptFinal_ex(context_.get(), out + cipherLen, &padding);
|
||||
if (status != 1 || padding < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Place the tag in the header
|
||||
status = EVP_CIPHER_CTX_ctrl(context_.get(), EVP_CTRL_GCM_GET_TAG, sizeof(header.tag),
|
||||
header.tag);
|
||||
if (status != 1) {
|
||||
return -1;
|
||||
}
|
||||
// Place the payload size in the header
|
||||
uint32_t totalLen = sizeof(header) + cipherLen + padding;
|
||||
header.payload = htonl(static_cast<uint32_t>(cipherLen) + static_cast<uint32_t>(padding));
|
||||
return totalLen;
|
||||
++enc_sequence_;
|
||||
return written_sz;
|
||||
}
|
||||
|
||||
int Aes128Gcm::Decrypt(const uint8_t* in, size_t in_len, uint8_t* out, size_t out_len) {
|
||||
if (in_len < sizeof(Header)) {
|
||||
return 0;
|
||||
}
|
||||
if (out_len < DecryptedSize(in, in_len)) {
|
||||
return 0;
|
||||
}
|
||||
const auto& header = *reinterpret_cast<const Header*>(in);
|
||||
uint32_t payload = ntohl(header.payload);
|
||||
uint32_t expected_inlen = sizeof(Header) + payload;
|
||||
if (in_len < expected_inlen) {
|
||||
// Not enough data available
|
||||
return 0;
|
||||
}
|
||||
// Initialized with expected IV from header
|
||||
int status = EVP_DecryptInit_ex(context_.get(), cipher_, nullptr,
|
||||
reinterpret_cast<const uint8_t*>(&aes_key_), header.iv);
|
||||
if (status != 1) {
|
||||
return -1;
|
||||
std::optional<size_t> Aes128Gcm::Decrypt(const uint8_t* in, size_t in_len, uint8_t* out,
|
||||
size_t out_len) {
|
||||
std::vector<uint8_t> nonce(EVP_AEAD_nonce_length(EVP_AEAD_CTX_aead(context_.get())), 0);
|
||||
memcpy(nonce.data(), &dec_sequence_, sizeof(dec_sequence_));
|
||||
size_t written_sz;
|
||||
if (!EVP_AEAD_CTX_open(context_.get(), out, &written_sz, out_len, nonce.data(), nonce.size(),
|
||||
in, in_len, nullptr, 0)) {
|
||||
LOG(ERROR) << "Failed to decrypt (in_len=" << in_len << ", out_len=" << out_len
|
||||
<< ", out_len_needed=" << DecryptedSize(in_len) << ")";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
int decrypted_len = 0;
|
||||
status = EVP_DecryptUpdate(context_.get(), out, &decrypted_len, in + sizeof(header), payload);
|
||||
if (status != 1 || decrypted_len < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set expected tag from header
|
||||
status = EVP_CIPHER_CTX_ctrl(context_.get(), EVP_CTRL_GCM_SET_TAG, sizeof(header.tag),
|
||||
const_cast<uint8_t*>(header.tag));
|
||||
if (status != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// This is the padding. It can be ignored.
|
||||
int len = 0;
|
||||
status = EVP_DecryptFinal_ex(context_.get(), out + decrypted_len, &len);
|
||||
if (status != 1) {
|
||||
LOG(ERROR) << "EVP_DecryptFinal_ex failed. Tag mismatch";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Return the length without the padding.
|
||||
return decrypted_len;
|
||||
++dec_sequence_;
|
||||
return written_sz;
|
||||
}
|
||||
|
||||
size_t Aes128Gcm::EncryptedSize(size_t size) {
|
||||
// We need to account for block alignment of the encrypted data.
|
||||
// According to openssl.org/docs/man1.0.2/man3/EVP_EncryptUpdate.html,
|
||||
// "The amount of data written depends on the block alignment of the
|
||||
// encrypted data ..."
|
||||
// ".. the amount of data written may be anything from zero bytes to
|
||||
// (inl + cipher_block_size - 1) ..."
|
||||
const size_t cipher_block_size = EVP_CIPHER_block_size(cipher_);
|
||||
size_t padding = cipher_block_size - (size % cipher_block_size);
|
||||
if (padding != cipher_block_size) {
|
||||
size += padding;
|
||||
}
|
||||
return size + sizeof(Header);
|
||||
// https://commondatastorage.googleapis.com/chromium-boringssl-docs/aead.h.html#EVP_AEAD_CTX_seal
|
||||
return size + EVP_AEAD_max_overhead(EVP_AEAD_CTX_aead(context_.get()));
|
||||
}
|
||||
|
||||
size_t Aes128Gcm::DecryptedSize(const uint8_t* encrypted_data, size_t encrypted_size) {
|
||||
if (encrypted_size < sizeof(Header)) {
|
||||
// Not enough data yet
|
||||
return 0;
|
||||
}
|
||||
auto header = reinterpret_cast<const Header*>(encrypted_data);
|
||||
uint32_t payload = ntohl(header->payload);
|
||||
size_t total_size = payload + sizeof(Header);
|
||||
if (encrypted_size < total_size) {
|
||||
// There's enough data for the header but not enough data for the
|
||||
// payload. Indicate that there's not enough data for now.
|
||||
return 0;
|
||||
}
|
||||
return payload;
|
||||
size_t Aes128Gcm::DecryptedSize(size_t size) {
|
||||
// https://commondatastorage.googleapis.com/chromium-boringssl-docs/aead.h.html#EVP_AEAD_CTX_open
|
||||
return size;
|
||||
}
|
||||
|
||||
} // namespace pairing
|
||||
|
|
|
@ -16,17 +16,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/cipher.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "adb/pairing/counter.h"
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
// This is the default size of the initialization vector (iv) for AES-128-GCM
|
||||
#define AES_128_GCM_IV_SIZE 12
|
||||
// This is the full tag size for AES-128-GCM
|
||||
#define AES_128_GCM_TAG_SIZE 16
|
||||
#include <openssl/aead.h>
|
||||
|
||||
namespace adb {
|
||||
namespace pairing {
|
||||
|
@ -42,7 +37,7 @@ class Aes128Gcm {
|
|||
// suitable for decryption with this class.
|
||||
// The method returns the number of bytes placed in |out| on success and a
|
||||
// negative value if an error occurs.
|
||||
int Encrypt(const uint8_t* in, size_t in_len, uint8_t* out, size_t out_len);
|
||||
std::optional<size_t> Encrypt(const uint8_t* in, size_t in_len, uint8_t* out, size_t out_len);
|
||||
// Decrypt a block of data in |in| of length |in_len|, this consumes all data
|
||||
// in |in_len| bytes of data. The decrypted output is placed in the |out|
|
||||
// buffer of length |out_len|. On successful decryption the number of bytes in
|
||||
|
@ -50,22 +45,18 @@ class Aes128Gcm {
|
|||
// The method returns the number of bytes consumed from the |in| buffer. If
|
||||
// there is not enough data available in |in| the method returns zero. If
|
||||
// an error occurs the method returns a negative value.
|
||||
int Decrypt(const uint8_t* in, size_t in_len, uint8_t* out, size_t out_len);
|
||||
std::optional<size_t> Decrypt(const uint8_t* in, size_t in_len, uint8_t* out, size_t out_len);
|
||||
|
||||
// Return a safe amount of buffer storage needed to encrypt |size| bytes.
|
||||
size_t EncryptedSize(size_t size);
|
||||
// Return a safe amount of buffer storage needed to decrypt the encrypted
|
||||
// data in |encrypted_data| which is of length |encrypted_size|. Returns 0 if
|
||||
// there is not enough data available to determine the required size.
|
||||
size_t DecryptedSize(const uint8_t* encrypted_data, size_t encrypted_size);
|
||||
|
||||
static const EVP_CIPHER* cipher_;
|
||||
// Return a safe amount of buffer storage needed to decrypt |size| bytes.
|
||||
size_t DecryptedSize(size_t size);
|
||||
|
||||
private:
|
||||
bssl::UniquePtr<EVP_CIPHER_CTX> context_;
|
||||
AES_KEY aes_key_;
|
||||
// We're going to use this counter for our iv so that it never repeats
|
||||
Counter<AES_128_GCM_IV_SIZE> counter_;
|
||||
bssl::ScopedEVP_AEAD_CTX context_;
|
||||
// Sequence numbers to use as nonces in the encryption scheme
|
||||
uint64_t dec_sequence_ = 0;
|
||||
uint64_t enc_sequence_ = 0;
|
||||
};
|
||||
|
||||
} // namespace pairing
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace adb {
|
||||
namespace pairing {
|
||||
|
||||
template <size_t N>
|
||||
class Counter {
|
||||
public:
|
||||
void Increase() {
|
||||
for (size_t i = sizeof(counter_) - 1; i < sizeof(counter_); --i) {
|
||||
if (++counter_[i] != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* data() { return counter_; }
|
||||
const uint8_t* data() const { return counter_; }
|
||||
|
||||
constexpr size_t size() const { return sizeof(counter_); }
|
||||
|
||||
uint8_t& operator[](size_t index) { return counter_[index]; }
|
||||
const uint8_t& operator[](size_t index) const { return counter_[index]; }
|
||||
|
||||
private:
|
||||
uint8_t counter_[N];
|
||||
};
|
||||
|
||||
} // namespace pairing
|
||||
} // namespace adb
|
|
@ -75,8 +75,8 @@ struct PairingAuthCtx {
|
|||
// Returns a safe buffer size for encrypting a buffer of size |len|.
|
||||
size_t SafeEncryptedSize(size_t len);
|
||||
|
||||
// Returns a safe buffer size for decrypting a buffer |buf|.
|
||||
size_t SafeDecryptedSize(const Data& buf);
|
||||
// Returns a safe buffer size for decrypting a buffer of size |len|.
|
||||
size_t SafeDecryptedSize(size_t len);
|
||||
|
||||
private:
|
||||
Data our_msg_;
|
||||
|
@ -167,12 +167,12 @@ PairingAuthCtx::Data PairingAuthCtx::Encrypt(const PairingAuthCtx::Data& data) {
|
|||
|
||||
// Determine the size for the encrypted data based on the raw data.
|
||||
Data encrypted(cipher_->EncryptedSize(data.size()));
|
||||
int bytes = cipher_->Encrypt(data.data(), data.size(), encrypted.data(), encrypted.size());
|
||||
if (bytes < 0) {
|
||||
auto out_size = cipher_->Encrypt(data.data(), data.size(), encrypted.data(), encrypted.size());
|
||||
if (!out_size.has_value() || *out_size == 0) {
|
||||
LOG(ERROR) << "Unable to encrypt data";
|
||||
return Data();
|
||||
}
|
||||
encrypted.resize(bytes);
|
||||
encrypted.resize(*out_size);
|
||||
|
||||
return encrypted;
|
||||
}
|
||||
|
@ -182,14 +182,14 @@ PairingAuthCtx::Data PairingAuthCtx::Decrypt(const PairingAuthCtx::Data& data) {
|
|||
CHECK(!data.empty());
|
||||
|
||||
// Determine the size for the decrypted data based on the raw data.
|
||||
Data decrypted(cipher_->DecryptedSize(data.data(), data.size()));
|
||||
Data decrypted(cipher_->DecryptedSize(data.size()));
|
||||
size_t decrypted_size = decrypted.size();
|
||||
int bytes = cipher_->Decrypt(data.data(), data.size(), decrypted.data(), decrypted_size);
|
||||
if (bytes <= 0) {
|
||||
auto out_size = cipher_->Decrypt(data.data(), data.size(), decrypted.data(), decrypted_size);
|
||||
if (!out_size.has_value() || *out_size == 0) {
|
||||
LOG(ERROR) << "Unable to decrypt data";
|
||||
return Data();
|
||||
}
|
||||
decrypted.resize(bytes);
|
||||
decrypted.resize(*out_size);
|
||||
|
||||
return decrypted;
|
||||
}
|
||||
|
@ -199,9 +199,9 @@ size_t PairingAuthCtx::SafeEncryptedSize(size_t len) {
|
|||
return cipher_->EncryptedSize(len);
|
||||
}
|
||||
|
||||
size_t PairingAuthCtx::SafeDecryptedSize(const PairingAuthCtx::Data& buf) {
|
||||
size_t PairingAuthCtx::SafeDecryptedSize(size_t len) {
|
||||
CHECK(cipher_);
|
||||
return cipher_->DecryptedSize(buf.data(), buf.size());
|
||||
return cipher_->DecryptedSize(len);
|
||||
}
|
||||
|
||||
PairingAuthCtx* pairing_auth_server_new(const uint8_t* pswd, size_t len) {
|
||||
|
@ -271,8 +271,8 @@ size_t pairing_auth_safe_decrypted_size(PairingAuthCtx* ctx, const uint8_t* buf,
|
|||
CHECK(ctx);
|
||||
CHECK(buf);
|
||||
CHECK_GT(len, 0U);
|
||||
std::vector<uint8_t> p(buf, buf + len);
|
||||
return ctx->SafeDecryptedSize(p);
|
||||
// We no longer need buf for EVP_AEAD
|
||||
return ctx->SafeDecryptedSize(len);
|
||||
}
|
||||
|
||||
bool pairing_auth_decrypt(PairingAuthCtx* ctx, const uint8_t* inbuf, size_t inlen, uint8_t* outbuf,
|
||||
|
|
|
@ -18,7 +18,6 @@ cc_test {
|
|||
name: "adb_pairing_auth_test",
|
||||
srcs: [
|
||||
"aes_128_gcm_test.cpp",
|
||||
"counter_test.cpp",
|
||||
"pairing_auth_test.cpp",
|
||||
],
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ TEST(Aes128GcmTest, encrypt_decrypt) {
|
|||
const uint8_t msg[] = "alice and bob, sitting in a binary tree";
|
||||
uint8_t material[256];
|
||||
uint8_t encrypted[1024];
|
||||
uint8_t out_buf[1024];
|
||||
uint8_t out_buf[1024] = {};
|
||||
|
||||
RAND_bytes(material, sizeof(material));
|
||||
Aes128Gcm alice(material, sizeof(material));
|
||||
|
@ -47,82 +47,16 @@ TEST(Aes128GcmTest, encrypt_decrypt) {
|
|||
;
|
||||
|
||||
ASSERT_GE(alice.EncryptedSize(sizeof(msg)), sizeof(msg));
|
||||
int encrypted_size = alice.Encrypt(msg, sizeof(msg), encrypted, sizeof(encrypted));
|
||||
ASSERT_GT(encrypted_size, 0);
|
||||
auto encrypted_size = alice.Encrypt(msg, sizeof(msg), encrypted, sizeof(encrypted));
|
||||
ASSERT_TRUE(encrypted_size.has_value());
|
||||
ASSERT_GT(*encrypted_size, 0);
|
||||
size_t out_size = sizeof(out_buf);
|
||||
ASSERT_GE(bob.DecryptedSize(encrypted, sizeof(encrypted)), sizeof(msg));
|
||||
int decrypted_size = bob.Decrypt(encrypted, sizeof(encrypted), out_buf, out_size);
|
||||
ASSERT_EQ(sizeof(msg), decrypted_size);
|
||||
memset(out_buf + decrypted_size, 0, sizeof(out_buf) - decrypted_size);
|
||||
ASSERT_GE(bob.DecryptedSize(*encrypted_size), sizeof(msg));
|
||||
auto decrypted_size = bob.Decrypt(encrypted, *encrypted_size, out_buf, out_size);
|
||||
ASSERT_TRUE(decrypted_size.has_value());
|
||||
ASSERT_EQ(sizeof(msg), *decrypted_size);
|
||||
ASSERT_STREQ(reinterpret_cast<const char*>(msg), reinterpret_cast<const char*>(out_buf));
|
||||
}
|
||||
|
||||
TEST(Aes128GcmTest, padding) {
|
||||
// Test with block-align data as well as unaligned data.
|
||||
const size_t cipher_block_size = EVP_CIPHER_block_size(Aes128Gcm::cipher_);
|
||||
uint8_t material[256];
|
||||
RAND_bytes(material, sizeof(material));
|
||||
Aes128Gcm alice(material, sizeof(material));
|
||||
Aes128Gcm bob(material, sizeof(material));
|
||||
;
|
||||
std::vector<uint8_t> msg;
|
||||
std::vector<uint8_t> encrypted;
|
||||
std::vector<uint8_t> decrypted;
|
||||
|
||||
// Test with aligned data
|
||||
{
|
||||
msg.resize(cipher_block_size);
|
||||
RAND_bytes(msg.data(), msg.size());
|
||||
|
||||
// encrypt
|
||||
size_t safe_encrypted_sz = alice.EncryptedSize(msg.size());
|
||||
ASSERT_GE(safe_encrypted_sz, msg.size());
|
||||
encrypted.resize(safe_encrypted_sz);
|
||||
int encrypted_size =
|
||||
alice.Encrypt(msg.data(), msg.size(), encrypted.data(), encrypted.size());
|
||||
ASSERT_GT(encrypted_size, 0);
|
||||
ASSERT_LE(encrypted_size, safe_encrypted_sz);
|
||||
encrypted.resize(encrypted_size);
|
||||
|
||||
// decrypt
|
||||
size_t safe_decrypted_size = bob.DecryptedSize(encrypted.data(), encrypted.size());
|
||||
ASSERT_GE(safe_decrypted_size, msg.size());
|
||||
decrypted.resize(safe_decrypted_size);
|
||||
int decrypted_size =
|
||||
bob.Decrypt(encrypted.data(), encrypted.size(), decrypted.data(), decrypted.size());
|
||||
ASSERT_GT(decrypted_size, 0);
|
||||
ASSERT_LE(decrypted_size, safe_decrypted_size);
|
||||
ASSERT_EQ(msg.size(), decrypted_size);
|
||||
ASSERT_EQ(memcmp(msg.data(), decrypted.data(), decrypted.size()), 0);
|
||||
}
|
||||
|
||||
// Test with unaligned data
|
||||
{
|
||||
msg.resize(cipher_block_size + 1);
|
||||
RAND_bytes(msg.data(), msg.size());
|
||||
|
||||
// encrypt
|
||||
size_t safe_encrypted_sz = alice.EncryptedSize(msg.size());
|
||||
ASSERT_GE(safe_encrypted_sz, msg.size());
|
||||
encrypted.resize(safe_encrypted_sz);
|
||||
int encrypted_size =
|
||||
alice.Encrypt(msg.data(), msg.size(), encrypted.data(), encrypted.size());
|
||||
ASSERT_GT(encrypted_size, 0);
|
||||
ASSERT_LE(encrypted_size, safe_encrypted_sz);
|
||||
encrypted.resize(encrypted_size);
|
||||
|
||||
// decrypt
|
||||
size_t safe_decrypted_size = bob.DecryptedSize(encrypted.data(), encrypted.size());
|
||||
ASSERT_GE(safe_decrypted_size, msg.size());
|
||||
decrypted.resize(safe_decrypted_size);
|
||||
int decrypted_size =
|
||||
bob.Decrypt(encrypted.data(), encrypted.size(), decrypted.data(), decrypted.size());
|
||||
ASSERT_GT(decrypted_size, 0);
|
||||
ASSERT_LE(decrypted_size, safe_decrypted_size);
|
||||
ASSERT_EQ(msg.size(), decrypted_size);
|
||||
ASSERT_EQ(memcmp(msg.data(), decrypted.data(), decrypted.size()), 0);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pairing
|
||||
} // namespace adb
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <adb/pairing/counter.h>
|
||||
|
||||
namespace adb {
|
||||
namespace pairing {
|
||||
|
||||
static constexpr size_t kTestCounterSize = 13;
|
||||
static const uint8_t kZeroes[64] = {0};
|
||||
|
||||
TEST(AdbCounterTest, size_match) {
|
||||
Counter<kTestCounterSize> counter;
|
||||
ASSERT_EQ(kTestCounterSize, counter.size());
|
||||
}
|
||||
|
||||
TEST(AdbCounterTest, Increase) {
|
||||
Counter<kTestCounterSize> counter;
|
||||
memset(counter.data(), 0, counter.size());
|
||||
counter.Increase();
|
||||
EXPECT_EQ(1, counter[counter.size() - 1]);
|
||||
EXPECT_EQ(0, memcmp(counter.data(), kZeroes, counter.size() - 1));
|
||||
}
|
||||
|
||||
TEST(AdbCounterTest, rollover_first_byte) {
|
||||
Counter<kTestCounterSize> counter;
|
||||
memset(counter.data(), 0, counter.size());
|
||||
counter[counter.size() - 1] = 0xFF;
|
||||
counter.Increase();
|
||||
EXPECT_EQ(0, counter[counter.size() - 1]);
|
||||
EXPECT_EQ(1, counter[counter.size() - 2]);
|
||||
EXPECT_EQ(0, memcmp(counter.data(), kZeroes, counter.size() - 2));
|
||||
}
|
||||
|
||||
TEST(AdbCounterTest, multiple_rollover) {
|
||||
Counter<kTestCounterSize> counter;
|
||||
memset(counter.data(), 0xFF, counter.size());
|
||||
memset(counter.data(), 0, counter.size() - 3);
|
||||
counter.Increase();
|
||||
EXPECT_EQ(0, counter[counter.size() - 5]);
|
||||
EXPECT_EQ(1, counter[counter.size() - 4]);
|
||||
EXPECT_EQ(0, counter[counter.size() - 3]);
|
||||
EXPECT_EQ(0, counter[counter.size() - 2]);
|
||||
EXPECT_EQ(0, counter[counter.size() - 1]);
|
||||
}
|
||||
|
||||
TEST(AdbCounterTest, full_rollover) {
|
||||
Counter<kTestCounterSize> counter;
|
||||
memset(counter.data(), 0xFF, counter.size());
|
||||
counter.Increase();
|
||||
EXPECT_EQ(0, memcmp(counter.data(), kZeroes, counter.size()));
|
||||
}
|
||||
|
||||
} // namespace pairing
|
||||
} // namespace adb
|
Loading…
Reference in a new issue