Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add and implement mojo interface to generate an uid for EcheApp
Use curve25519 to create a key pair and store in PrefServices, this key pair can be used for digital signatures so that other endpoints can verify signatures coming from the endpoint that owns the UID. We use the public key as an UID for now. Bug: b/180990062 Test: chromeos_components_unittests Change-Id: I1bc022d45f14fd186f83b056f91e0e975534efbd Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2781095 Commit-Queue: Guanru Lee <guanrulee@chromium.org> Reviewed-by: Nasko Oskov <nasko@chromium.org> Reviewed-by: David Benjamin <davidben@chromium.org> Reviewed-by: Dominic Battré <battre@chromium.org> Reviewed-by: Daniel Nishi <dhnishi@chromium.org> Reviewed-by: calamity <calamity@chromium.org> Cr-Commit-Position: refs/heads/master@{#879710}
- Loading branch information
Guanru Lee
authored and
Chromium LUCI CQ
committed
May 6, 2021
1 parent
7397ec9
commit bdca2e6
Showing
15 changed files
with
329 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
// Copyright 2021 The Chromium 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 "chromeos/components/eche_app_ui/eche_uid_provider.h" | ||
#include <base/base64.h> | ||
#include <openssl/base64.h> | ||
#include <cstring> | ||
#include "base/check.h" | ||
#include "chromeos/components/multidevice/logging/logging.h" | ||
#include "components/prefs/pref_service.h" | ||
#include "crypto/random.h" | ||
|
||
namespace chromeos { | ||
namespace eche_app { | ||
|
||
const char kEcheAppSeedPref[] = "cros.echeapp.seed"; | ||
const size_t kSeedSizeInByte = 32; | ||
|
||
EcheUidProvider::EcheUidProvider(PrefService* pref_service) | ||
: pref_service_(pref_service) {} | ||
|
||
EcheUidProvider::~EcheUidProvider() = default; | ||
|
||
void EcheUidProvider::GetUid( | ||
base::OnceCallback<void(const std::string&)> callback) { | ||
if (!uid_.empty()) { | ||
std::move(callback).Run(uid_); | ||
return; | ||
} | ||
uint8_t public_key[ED25519_PUBLIC_KEY_LEN]; | ||
uint8_t private_key[ED25519_PRIVATE_KEY_LEN]; | ||
std::string pref_seed = pref_service_->GetString(kEcheAppSeedPref); | ||
if (pref_seed.empty()) { | ||
GenerateKeyPair(public_key, private_key); | ||
} else { | ||
base::Optional<std::vector<uint8_t>> result = | ||
ConvertStringToBinary(pref_seed, kSeedSizeInByte); | ||
if (!result) { | ||
PA_LOG(WARNING) << "Invalid encoded string, regenerate the keypair."; | ||
GenerateKeyPair(public_key, private_key); | ||
} else { | ||
DCHECK_EQ(kSeedSizeInByte, result->size()); | ||
ED25519_keypair_from_seed(public_key, private_key, result->data()); | ||
} | ||
} | ||
uid_ = ConvertBinaryToString(public_key); | ||
std::move(callback).Run(uid_); | ||
} | ||
|
||
void EcheUidProvider::GenerateKeyPair( | ||
uint8_t public_key[ED25519_PUBLIC_KEY_LEN], | ||
uint8_t private_key[ED25519_PRIVATE_KEY_LEN]) { | ||
ED25519_keypair(public_key, private_key); | ||
// Store the seed (what RFC8032 calls a private key), which is the | ||
// first 32 bytes of what BoringSSL calls the private key. | ||
pref_service_->SetString( | ||
kEcheAppSeedPref, | ||
ConvertBinaryToString(base::make_span(private_key, kSeedSizeInByte))); | ||
} | ||
|
||
base::Optional<std::vector<uint8_t>> EcheUidProvider::ConvertStringToBinary( | ||
base::StringPiece str, | ||
size_t expected_len) { | ||
std::vector<uint8_t> decoded_data(str.size()); | ||
size_t decoded_data_len = 0; | ||
if (!EVP_DecodeBase64( | ||
decoded_data.data(), &decoded_data_len, decoded_data.size(), | ||
reinterpret_cast<const uint8_t*>(str.data()), str.size())) { | ||
PA_LOG(ERROR) << "Attempting to decode string failed."; | ||
return base::nullopt; | ||
} | ||
if (decoded_data_len != expected_len) { | ||
PA_LOG(ERROR) << "Expected length is not match."; | ||
return base::nullopt; | ||
} | ||
decoded_data.resize(decoded_data_len); | ||
return decoded_data; | ||
} | ||
|
||
std::string EcheUidProvider::ConvertBinaryToString( | ||
base::span<const uint8_t> src) { | ||
// Use a constant-time implementation of base64 in BoringSSL instead of | ||
// base::Base64Encode. | ||
size_t encoded_data_len; | ||
CHECK(EVP_EncodedLength(&encoded_data_len, src.size()) == 1); | ||
std::vector<uint8_t> encoded_data(encoded_data_len); | ||
size_t encoded_block_len = | ||
EVP_EncodeBlock(encoded_data.data(), src.data(), src.size()); | ||
// The return value of EVP_EncodeBlock is not the same with the result of | ||
// EVP_EncodedLength, we save the real size of EVP_EncodeBlock to string, not | ||
// the size of buffer. | ||
return std::string(reinterpret_cast<const char*>(encoded_data.data()), | ||
encoded_block_len); | ||
} | ||
|
||
void EcheUidProvider::Bind( | ||
mojo::PendingReceiver<mojom::UidGenerator> receiver) { | ||
uid_receiver_.reset(); | ||
uid_receiver_.Bind(std::move(receiver)); | ||
} | ||
|
||
} // namespace eche_app | ||
} // namespace chromeos |
Oops, something went wrong.