Commit 8f5c2474 authored by Nina Satragno's avatar Nina Satragno Committed by Commit Bot

[fido] Large blob encryption & decryption

Implement encrypting and decrypting large blobs, and add a test for
updating blobs which exercises the new code path.

Bug: 1114875
Change-Id: Ief91f642fa5ccc34f7ef2d00c90467fbcb90bc5e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2415218
Commit-Queue: Nina Satragno <nsatragno@chromium.org>
Auto-Submit: Nina Satragno <nsatragno@chromium.org>
Reviewed-by: default avatarMartin Kreichgauer <martinkr@google.com>
Cr-Commit-Position: refs/heads/master@{#808134}
parent 1fd148fc
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "device/fido/test_callback_receiver.h" #include "device/fido/test_callback_receiver.h"
#include "device/fido/virtual_ctap2_device.h" #include "device/fido/virtual_ctap2_device.h"
#include "device/fido/virtual_fido_device.h" #include "device/fido/virtual_fido_device.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace device { namespace device {
...@@ -27,8 +28,11 @@ using ReadCallback = device::test::StatusAndValueCallbackReceiver< ...@@ -27,8 +28,11 @@ using ReadCallback = device::test::StatusAndValueCallbackReceiver<
CtapDeviceResponseCode, CtapDeviceResponseCode,
base::Optional<std::vector<std::pair<LargeBlobKey, std::vector<uint8_t>>>>>; base::Optional<std::vector<std::pair<LargeBlobKey, std::vector<uint8_t>>>>>;
constexpr LargeBlobKey kDummyKey = {{0x01}}; constexpr LargeBlobKey kDummyKey1 = {{0x01}};
constexpr std::array<uint8_t, 4> kSmallBlob = {'l', 'u', 'm', 'a'}; constexpr LargeBlobKey kDummyKey2 = {{0x02}};
constexpr std::array<uint8_t, 4> kSmallBlob1 = {'r', 'o', 's', 'a'};
constexpr std::array<uint8_t, 4> kSmallBlob2 = {'l', 'u', 'm', 'a'};
constexpr std::array<uint8_t, 4> kSmallBlob3 = {'s', 't', 'a', 'r'};
constexpr size_t kMaxStorageSize = 4096; constexpr size_t kMaxStorageSize = 4096;
class FidoDeviceAuthenticatorTest : public testing::Test { class FidoDeviceAuthenticatorTest : public testing::Test {
...@@ -66,7 +70,7 @@ class FidoDeviceAuthenticatorTest : public testing::Test { ...@@ -66,7 +70,7 @@ class FidoDeviceAuthenticatorTest : public testing::Test {
TEST_F(FidoDeviceAuthenticatorTest, TestReadEmptyLargeBlob) { TEST_F(FidoDeviceAuthenticatorTest, TestReadEmptyLargeBlob) {
ReadCallback callback; ReadCallback callback;
authenticator_->ReadLargeBlob({kDummyKey}, base::nullopt, authenticator_->ReadLargeBlob({kDummyKey1}, base::nullopt,
callback.callback()); callback.callback());
callback.WaitForCallback(); callback.WaitForCallback();
...@@ -77,7 +81,7 @@ TEST_F(FidoDeviceAuthenticatorTest, TestReadEmptyLargeBlob) { ...@@ -77,7 +81,7 @@ TEST_F(FidoDeviceAuthenticatorTest, TestReadEmptyLargeBlob) {
TEST_F(FidoDeviceAuthenticatorTest, TestReadInvalidLargeBlob) { TEST_F(FidoDeviceAuthenticatorTest, TestReadInvalidLargeBlob) {
authenticator_state_->large_blob[0] += 1; authenticator_state_->large_blob[0] += 1;
ReadCallback callback; ReadCallback callback;
authenticator_->ReadLargeBlob({kDummyKey}, base::nullopt, authenticator_->ReadLargeBlob({kDummyKey1}, base::nullopt,
callback.callback()); callback.callback());
callback.WaitForCallback(); callback.WaitForCallback();
...@@ -88,23 +92,24 @@ TEST_F(FidoDeviceAuthenticatorTest, TestReadInvalidLargeBlob) { ...@@ -88,23 +92,24 @@ TEST_F(FidoDeviceAuthenticatorTest, TestReadInvalidLargeBlob) {
// Test reading and writing a blob that fits in a single fragment. // Test reading and writing a blob that fits in a single fragment.
TEST_F(FidoDeviceAuthenticatorTest, TestWriteSmallBlob) { TEST_F(FidoDeviceAuthenticatorTest, TestWriteSmallBlob) {
std::vector<uint8_t> small_blob = fido_parsing_utils::Materialize(kSmallBlob); std::vector<uint8_t> small_blob =
fido_parsing_utils::Materialize(kSmallBlob1);
WriteCallback write_callback; WriteCallback write_callback;
authenticator_->WriteLargeBlob(small_blob, {kDummyKey}, base::nullopt, authenticator_->WriteLargeBlob(small_blob, {kDummyKey1}, base::nullopt,
write_callback.callback()); write_callback.callback());
write_callback.WaitForCallback(); write_callback.WaitForCallback();
ASSERT_EQ(CtapDeviceResponseCode::kSuccess, write_callback.value()); ASSERT_EQ(CtapDeviceResponseCode::kSuccess, write_callback.value());
ReadCallback read_callback; ReadCallback read_callback;
authenticator_->ReadLargeBlob({kDummyKey}, base::nullopt, authenticator_->ReadLargeBlob({kDummyKey1}, base::nullopt,
read_callback.callback()); read_callback.callback());
read_callback.WaitForCallback(); read_callback.WaitForCallback();
ASSERT_EQ(CtapDeviceResponseCode::kSuccess, read_callback.status()); ASSERT_EQ(CtapDeviceResponseCode::kSuccess, read_callback.status());
auto large_blob_array = read_callback.value(); auto large_blob_array = read_callback.value();
ASSERT_TRUE(large_blob_array); ASSERT_TRUE(large_blob_array);
ASSERT_EQ(1u, large_blob_array->size()); ASSERT_EQ(1u, large_blob_array->size());
EXPECT_EQ(kDummyKey, large_blob_array->at(0).first); EXPECT_EQ(kDummyKey1, large_blob_array->at(0).first);
EXPECT_EQ(small_blob, large_blob_array->at(0).second); EXPECT_EQ(small_blob, large_blob_array->at(0).second);
} }
...@@ -117,24 +122,63 @@ TEST_F(FidoDeviceAuthenticatorTest, TestWriteLargeBlob) { ...@@ -117,24 +122,63 @@ TEST_F(FidoDeviceAuthenticatorTest, TestWriteLargeBlob) {
} }
WriteCallback write_callback; WriteCallback write_callback;
authenticator_->WriteLargeBlob(large_blob, {kDummyKey}, base::nullopt, authenticator_->WriteLargeBlob(large_blob, {kDummyKey1}, base::nullopt,
write_callback.callback()); write_callback.callback());
write_callback.WaitForCallback(); write_callback.WaitForCallback();
ASSERT_EQ(CtapDeviceResponseCode::kSuccess, write_callback.value()); ASSERT_EQ(CtapDeviceResponseCode::kSuccess, write_callback.value());
ReadCallback read_callback; ReadCallback read_callback;
authenticator_->ReadLargeBlob({kDummyKey}, base::nullopt, authenticator_->ReadLargeBlob({kDummyKey1}, base::nullopt,
read_callback.callback()); read_callback.callback());
read_callback.WaitForCallback(); read_callback.WaitForCallback();
ASSERT_EQ(CtapDeviceResponseCode::kSuccess, read_callback.status()); ASSERT_EQ(CtapDeviceResponseCode::kSuccess, read_callback.status());
auto large_blob_array = read_callback.value(); auto large_blob_array = read_callback.value();
ASSERT_TRUE(large_blob_array); ASSERT_TRUE(large_blob_array);
ASSERT_EQ(1u, large_blob_array->size()); ASSERT_EQ(1u, large_blob_array->size());
EXPECT_EQ(kDummyKey, large_blob_array->at(0).first); EXPECT_EQ(kDummyKey1, large_blob_array->at(0).first);
EXPECT_EQ(large_blob, large_blob_array->at(0).second); EXPECT_EQ(large_blob, large_blob_array->at(0).second);
} }
// Test updating a large blob in an array with multiple entries corresponding to
// other keys.
TEST_F(FidoDeviceAuthenticatorTest, TestUpdateLargeBlob) {
WriteCallback write_callback1;
authenticator_->WriteLargeBlob(fido_parsing_utils::Materialize(kSmallBlob1),
{kDummyKey1}, base::nullopt,
write_callback1.callback());
write_callback1.WaitForCallback();
ASSERT_EQ(CtapDeviceResponseCode::kSuccess, write_callback1.value());
WriteCallback write_callback2;
std::vector<uint8_t> small_blob2 =
fido_parsing_utils::Materialize(kSmallBlob2);
authenticator_->WriteLargeBlob(small_blob2, {kDummyKey2}, base::nullopt,
write_callback2.callback());
write_callback2.WaitForCallback();
ASSERT_EQ(CtapDeviceResponseCode::kSuccess, write_callback2.value());
// Update the first entry.
WriteCallback write_callback3;
std::vector<uint8_t> small_blob3 =
fido_parsing_utils::Materialize(kSmallBlob3);
authenticator_->WriteLargeBlob(small_blob3, {kDummyKey1}, base::nullopt,
write_callback3.callback());
write_callback3.WaitForCallback();
ASSERT_EQ(CtapDeviceResponseCode::kSuccess, write_callback3.value());
ReadCallback read_callback;
authenticator_->ReadLargeBlob({kDummyKey1, kDummyKey2}, base::nullopt,
read_callback.callback());
read_callback.WaitForCallback();
ASSERT_EQ(CtapDeviceResponseCode::kSuccess, read_callback.status());
auto large_blob_array = read_callback.value();
ASSERT_TRUE(large_blob_array);
EXPECT_THAT(*large_blob_array, testing::UnorderedElementsAre(
std::make_pair(kDummyKey1, small_blob3),
std::make_pair(kDummyKey2, small_blob2)));
}
} // namespace } // namespace
} // namespace device } // namespace device
...@@ -139,6 +139,17 @@ bool CopyCBORBytestring(std::array<uint8_t, N>* out, ...@@ -139,6 +139,17 @@ bool CopyCBORBytestring(std::array<uint8_t, N>* out,
return ExtractArray(bytestring, /*pos=*/0, out); return ExtractArray(bytestring, /*pos=*/0, out);
} }
constexpr std::array<uint8_t, 4> Uint32LittleEndian(uint32_t value) {
return {value & 0xFF, value >> 8 & 0xFF, value >> 16 & 0xFF,
value >> 24 & 0xFF};
}
constexpr std::array<uint8_t, 8> Uint64LittleEndian(uint64_t value) {
return {value & 0xFF, value >> 8 & 0xFF, value >> 16 & 0xFF,
value >> 24 & 0xFF, value >> 32 & 0xFF, value >> 40 & 0xFF,
value >> 48 & 0xFF, value >> 56 & 0xFF};
}
} // namespace fido_parsing_utils } // namespace fido_parsing_utils
} // namespace device } // namespace device
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#include "base/containers/span.h" #include "base/containers/span.h"
#include "components/cbor/reader.h" #include "components/cbor/reader.h"
#include "components/cbor/writer.h" #include "components/cbor/writer.h"
#include "crypto/aead.h"
#include "crypto/random.h"
#include "crypto/sha2.h" #include "crypto/sha2.h"
#include "device/fido/fido_parsing_utils.h" #include "device/fido/fido_parsing_utils.h"
#include "device/fido/pin.h" #include "device/fido/pin.h"
...@@ -15,6 +17,21 @@ namespace device { ...@@ -15,6 +17,21 @@ namespace device {
namespace { namespace {
// The number of bytes the large blob validation hash is truncated to. // The number of bytes the large blob validation hash is truncated to.
constexpr size_t kTruncatedHashBytes = 16; constexpr size_t kTruncatedHashBytes = 16;
constexpr std::array<uint8_t, 4> kLargeBlobADPrefix = {'b', 'l', 'o', 'b'};
constexpr size_t kAssociatedDataLength = kLargeBlobADPrefix.size() + 8;
std::array<uint8_t, kAssociatedDataLength> GenerateLargeBlobAdditionalData(
size_t size) {
std::array<uint8_t, kAssociatedDataLength> additional_data;
const std::array<uint8_t, 8>& size_array =
fido_parsing_utils::Uint64LittleEndian(size);
std::copy(kLargeBlobADPrefix.begin(), kLargeBlobADPrefix.end(),
additional_data.begin());
std::copy(size_array.begin(), size_array.end(),
additional_data.begin() + kLargeBlobADPrefix.size());
return additional_data;
}
} // namespace } // namespace
LargeBlobArrayFragment::LargeBlobArrayFragment(const std::vector<uint8_t> bytes, LargeBlobArrayFragment::LargeBlobArrayFragment(const std::vector<uint8_t> bytes,
...@@ -150,7 +167,8 @@ base::Optional<LargeBlobData> LargeBlobData::Parse(const cbor::Value& value) { ...@@ -150,7 +167,8 @@ base::Optional<LargeBlobData> LargeBlobData::Parse(const cbor::Value& value) {
} }
auto nonce_it = auto nonce_it =
map.find(cbor::Value(static_cast<int>(LargeBlobDataKeys::kNonce))); map.find(cbor::Value(static_cast<int>(LargeBlobDataKeys::kNonce)));
if (nonce_it == map.end() || !nonce_it->second.is_bytestring()) { if (nonce_it == map.end() || !nonce_it->second.is_bytestring() ||
nonce_it->second.GetBytestring().size() != kLargeBlobArrayNonceLength) {
return base::nullopt; return base::nullopt;
} }
auto orig_size_it = auto orig_size_it =
...@@ -159,21 +177,25 @@ base::Optional<LargeBlobData> LargeBlobData::Parse(const cbor::Value& value) { ...@@ -159,21 +177,25 @@ base::Optional<LargeBlobData> LargeBlobData::Parse(const cbor::Value& value) {
return base::nullopt; return base::nullopt;
} }
return LargeBlobData(ciphertext_it->second.GetBytestring(), return LargeBlobData(ciphertext_it->second.GetBytestring(),
nonce_it->second.GetBytestring(), base::make_span<kLargeBlobArrayNonceLength>(
nonce_it->second.GetBytestring()),
orig_size_it->second.GetUnsigned()); orig_size_it->second.GetUnsigned());
} }
LargeBlobData::LargeBlobData(std::vector<uint8_t> ciphertext, LargeBlobData::LargeBlobData(
std::vector<uint8_t> nonce, std::vector<uint8_t> ciphertext,
int64_t orig_size) base::span<const uint8_t, kLargeBlobArrayNonceLength> nonce,
: ciphertext_(std::move(ciphertext)), int64_t orig_size)
nonce_(std::move(nonce)), : ciphertext_(std::move(ciphertext)), orig_size_(std::move(orig_size)) {
orig_size_(std::move(orig_size)) {} std::copy(nonce.begin(), nonce.end(), nonce_.begin());
}
LargeBlobData::LargeBlobData(LargeBlobKey key, std::vector<uint8_t> blob) { LargeBlobData::LargeBlobData(LargeBlobKey key, std::vector<uint8_t> blob) {
// TODO(nsatragno): implement encrypting the data. For now, just store and
// return the blob as plaintext.
orig_size_ = blob.size(); orig_size_ = blob.size();
ciphertext_ = blob; crypto::Aead aead(crypto::Aead::AeadAlgorithm::AES_256_GCM);
aead.Init(key);
crypto::RandBytes(nonce_);
ciphertext_ =
aead.Seal(blob, nonce_, GenerateLargeBlobAdditionalData(orig_size_));
} }
LargeBlobData::LargeBlobData(LargeBlobData&&) = default; LargeBlobData::LargeBlobData(LargeBlobData&&) = default;
LargeBlobData& LargeBlobData::operator=(LargeBlobData&&) = default; LargeBlobData& LargeBlobData::operator=(LargeBlobData&&) = default;
...@@ -186,9 +208,10 @@ bool LargeBlobData::operator==(const LargeBlobData& other) const { ...@@ -186,9 +208,10 @@ bool LargeBlobData::operator==(const LargeBlobData& other) const {
base::Optional<std::vector<uint8_t>> LargeBlobData::Decrypt( base::Optional<std::vector<uint8_t>> LargeBlobData::Decrypt(
LargeBlobKey key) const { LargeBlobKey key) const {
// TODO(nsatragno): implement decrypting the data. For now, store and return crypto::Aead aead(crypto::Aead::AeadAlgorithm::AES_256_GCM);
// the blob as plaintext. aead.Init(key);
return ciphertext_; return aead.Open(ciphertext_, nonce_,
GenerateLargeBlobAdditionalData(orig_size_));
} }
cbor::Value::MapValue LargeBlobData::AsCBOR() const { cbor::Value::MapValue LargeBlobData::AsCBOR() const {
......
...@@ -47,6 +47,7 @@ using LargeBlobKey = std::array<uint8_t, kLargeBlobKeyLength>; ...@@ -47,6 +47,7 @@ using LargeBlobKey = std::array<uint8_t, kLargeBlobKeyLength>;
constexpr size_t kLargeBlobDefaultMaxFragmentLength = 960; constexpr size_t kLargeBlobDefaultMaxFragmentLength = 960;
constexpr size_t kLargeBlobReadEncodingOverhead = 64; constexpr size_t kLargeBlobReadEncodingOverhead = 64;
constexpr size_t kLargeBlobArrayNonceLength = 12;
struct COMPONENT_EXPORT(DEVICE_FIDO) LargeBlobArrayFragment { struct COMPONENT_EXPORT(DEVICE_FIDO) LargeBlobArrayFragment {
LargeBlobArrayFragment(std::vector<uint8_t> bytes, size_t offset); LargeBlobArrayFragment(std::vector<uint8_t> bytes, size_t offset);
...@@ -130,10 +131,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) LargeBlobData { ...@@ -130,10 +131,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) LargeBlobData {
private: private:
LargeBlobData(std::vector<uint8_t> ciphertext, LargeBlobData(std::vector<uint8_t> ciphertext,
std::vector<uint8_t> nonce, base::span<const uint8_t, kLargeBlobArrayNonceLength> nonce,
int64_t orig_size); int64_t orig_size);
std::vector<uint8_t> ciphertext_; std::vector<uint8_t> ciphertext_;
std::vector<uint8_t> nonce_; std::array<uint8_t, kLargeBlobArrayNonceLength> nonce_;
int64_t orig_size_; int64_t orig_size_;
}; };
......
...@@ -27,10 +27,11 @@ const std::array<uint8_t, 17> kInvalidLargeBlobArray = { ...@@ -27,10 +27,11 @@ const std::array<uint8_t, 17> kInvalidLargeBlobArray = {
// An "valid" CBOR large blob array with two entries. The first entry is not a // An "valid" CBOR large blob array with two entries. The first entry is not a
// valid large blob map structure. The second entry is valid. // valid large blob map structure. The second entry is valid.
const std::array<uint8_t, 35> kValidLargeBlobArray = { const std::array<uint8_t, 45> kValidLargeBlobArray = {
0x82, 0xA2, 0x02, 0x42, 0x11, 0x11, 0x03, 0x02, 0xA3, 0x01, 0x42, 0x22, 0x82, 0xA2, 0x02, 0x42, 0x11, 0x11, 0x03, 0x02, 0xA3, 0x01, 0x42, 0x22,
0x22, 0x02, 0x42, 0x33, 0x33, 0x03, 0x02, 0x53, 0x5b, 0xaa, 0xd2, 0x7a, 0x22, 0x02, 0x4C, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x26, 0x68, 0x34, 0x9e, 0xc3, 0x90, 0xd3, 0x9a, 0x1c, 0x0a, 0xae}; 0x30, 0x31, 0x32, 0x03, 0x02, 0x9b, 0x33, 0x75, 0x6c, 0x0a, 0x84, 0xdf,
0x32, 0xcc, 0xd0, 0xc8, 0x96, 0xea, 0xa7, 0x99, 0x13};
TEST_F(FidoLargeBlobTest, VerifyLargeBlobArrayIntegrityValid) { TEST_F(FidoLargeBlobTest, VerifyLargeBlobArrayIntegrityValid) {
std::vector<uint8_t> large_blob_array = std::vector<uint8_t> large_blob_array =
...@@ -113,7 +114,7 @@ TEST_F(FidoLargeBlobTest, LargeBlobArrayWriter_PopUnevenly) { ...@@ -113,7 +114,7 @@ TEST_F(FidoLargeBlobTest, LargeBlobArrayWriter_PopUnevenly) {
// Test popping the large blob array in a fragment size that evenly divides the // Test popping the large blob array in a fragment size that evenly divides the
// length of the array. // length of the array.
TEST_F(FidoLargeBlobTest, LargeBlobArrayFragments_PopEvenly) { TEST_F(FidoLargeBlobTest, LargeBlobArrayFragments_PopEvenly) {
const size_t fragment_size = 7; const size_t fragment_size = 9;
const size_t expected_fragments = kValidLargeBlobArray.size() / fragment_size; const size_t expected_fragments = kValidLargeBlobArray.size() / fragment_size;
size_t fragments = 0; size_t fragments = 0;
ASSERT_EQ(0u, kValidLargeBlobArray.size() % fragment_size); ASSERT_EQ(0u, kValidLargeBlobArray.size() % fragment_size);
......
...@@ -70,11 +70,6 @@ constexpr uint8_t kSupportedPermissionsMask = ...@@ -70,11 +70,6 @@ constexpr uint8_t kSupportedPermissionsMask =
static_cast<uint8_t>(pin::Permissions::kCredentialManagement) | static_cast<uint8_t>(pin::Permissions::kCredentialManagement) |
static_cast<uint8_t>(pin::Permissions::kBioEnrollment); static_cast<uint8_t>(pin::Permissions::kBioEnrollment);
constexpr std::array<uint8_t, 4> Uint32LittleEndian(int64_t value) {
return {value & 0xFF, value >> 8 & 0xFF, value >> 16 & 0xFF,
value >> 24 & 0xFF};
}
struct PinUvAuthTokenPermissions { struct PinUvAuthTokenPermissions {
uint8_t permissions; uint8_t permissions;
base::Optional<std::string> rp_id; base::Optional<std::string> rp_id;
...@@ -2199,7 +2194,7 @@ CtapDeviceResponseCode VirtualCtap2Device::OnLargeBlobs( ...@@ -2199,7 +2194,7 @@ CtapDeviceResponseCode VirtualCtap2Device::OnLargeBlobs(
if (offset_it == request_map.end() || !offset_it->second.is_unsigned()) { if (offset_it == request_map.end() || !offset_it->second.is_unsigned()) {
return CtapDeviceResponseCode::kCtap1ErrInvalidParameter; return CtapDeviceResponseCode::kCtap1ErrInvalidParameter;
} }
const size_t offset = offset_it->second.GetUnsigned(); const uint64_t offset = offset_it->second.GetUnsigned();
const auto get_it = request_map.find( const auto get_it = request_map.find(
cbor::Value(static_cast<uint8_t>(LargeBlobsRequestKey::kGet))); cbor::Value(static_cast<uint8_t>(LargeBlobsRequestKey::kGet)));
...@@ -2221,7 +2216,7 @@ CtapDeviceResponseCode VirtualCtap2Device::OnLargeBlobs( ...@@ -2221,7 +2216,7 @@ CtapDeviceResponseCode VirtualCtap2Device::OnLargeBlobs(
if (length_it != request_map.end()) { if (length_it != request_map.end()) {
return CtapDeviceResponseCode::kCtap1ErrInvalidParameter; return CtapDeviceResponseCode::kCtap1ErrInvalidParameter;
} }
const size_t get = get_it->second.GetUnsigned(); const uint64_t get = get_it->second.GetUnsigned();
if (get > max_fragment_length) { if (get > max_fragment_length) {
return CtapDeviceResponseCode::kCtap1ErrInvalidLength; return CtapDeviceResponseCode::kCtap1ErrInvalidLength;
} }
...@@ -2246,7 +2241,7 @@ CtapDeviceResponseCode VirtualCtap2Device::OnLargeBlobs( ...@@ -2246,7 +2241,7 @@ CtapDeviceResponseCode VirtualCtap2Device::OnLargeBlobs(
if (length_it == request_map.end() || !length_it->second.is_unsigned()) { if (length_it == request_map.end() || !length_it->second.is_unsigned()) {
return CtapDeviceResponseCode::kCtap1ErrInvalidParameter; return CtapDeviceResponseCode::kCtap1ErrInvalidParameter;
} }
const size_t length = length_it->second.GetUnsigned(); const uint64_t length = length_it->second.GetUnsigned();
if (length > config_.available_large_blob_storage) { if (length > config_.available_large_blob_storage) {
return CtapDeviceResponseCode::kCtap2ErrLargeBlobStorageFull; return CtapDeviceResponseCode::kCtap2ErrLargeBlobStorageFull;
} }
...@@ -2302,7 +2297,7 @@ CtapDeviceResponseCode VirtualCtap2Device::OnLargeBlobs( ...@@ -2302,7 +2297,7 @@ CtapDeviceResponseCode VirtualCtap2Device::OnLargeBlobs(
kPinUvAuthTokenSafetyPadding.begin(), kPinUvAuthTokenSafetyPadding.begin(),
kPinUvAuthTokenSafetyPadding.end()); kPinUvAuthTokenSafetyPadding.end());
pinauth_bytes.insert(pinauth_bytes.end(), {0x0c, 0x00}); pinauth_bytes.insert(pinauth_bytes.end(), {0x0c, 0x00});
auto offset_vec = Uint32LittleEndian(offset); auto offset_vec = fido_parsing_utils::Uint32LittleEndian(offset);
pinauth_bytes.insert(pinauth_bytes.end(), offset_vec.begin(), pinauth_bytes.insert(pinauth_bytes.end(), offset_vec.begin(),
offset_vec.end()); offset_vec.end());
pinauth_bytes.insert(pinauth_bytes.end(), set.begin(), set.end()); pinauth_bytes.insert(pinauth_bytes.end(), set.begin(), set.end());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment