131 lines
3.9 KiB
C++
131 lines
3.9 KiB
C++
/*
|
|
* Copyright 2021, 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 "host/libs/confui/sign.h"
|
|
|
|
#include <openssl/hmac.h>
|
|
#include <openssl/sha.h>
|
|
|
|
#include <string>
|
|
|
|
#include <android-base/logging.h>
|
|
|
|
#include "common/libs/confui/confui.h"
|
|
#include "common/libs/fs/shared_fd.h"
|
|
#include "common/libs/security/confui_sign.h"
|
|
#include "host/commands/kernel_log_monitor/utils.h"
|
|
#include "host/libs/config/cuttlefish_config.h"
|
|
#include "host/libs/confui/sign_utils.h"
|
|
|
|
namespace cuttlefish {
|
|
namespace confui {
|
|
namespace {
|
|
std::string GetSecureEnvSocketPath() {
|
|
auto config = cuttlefish::CuttlefishConfig::Get();
|
|
CHECK(config) << "Config must not be null";
|
|
auto instance = config->ForDefaultInstance();
|
|
return instance.PerInstanceInternalPath("confui_sign.sock");
|
|
}
|
|
|
|
/**
|
|
* the secure_env signing server may be on slightly later than
|
|
* confirmation UI host/webRTC process.
|
|
*/
|
|
SharedFD ConnectToSecureEnv() {
|
|
auto socket_path = GetSecureEnvSocketPath();
|
|
SharedFD socket_to_secure_env =
|
|
SharedFD::SocketLocalClient(socket_path, false, SOCK_STREAM);
|
|
return socket_to_secure_env;
|
|
}
|
|
} // end of namespace
|
|
|
|
class HMacImplementation {
|
|
public:
|
|
static std::optional<support::hmac_t> hmac256(
|
|
const support::auth_token_key_t& key,
|
|
std::initializer_list<support::ByteBufferProxy> buffers);
|
|
};
|
|
|
|
std::optional<support::hmac_t> HMacImplementation::hmac256(
|
|
const support::auth_token_key_t& key,
|
|
std::initializer_list<support::ByteBufferProxy> buffers) {
|
|
HMAC_CTX hmacCtx;
|
|
HMAC_CTX_init(&hmacCtx);
|
|
if (!HMAC_Init_ex(&hmacCtx, key.data(), key.size(), EVP_sha256(), nullptr)) {
|
|
return {};
|
|
}
|
|
for (auto& buffer : buffers) {
|
|
if (!HMAC_Update(&hmacCtx, buffer.data(), buffer.size())) {
|
|
return {};
|
|
}
|
|
}
|
|
support::hmac_t result;
|
|
if (!HMAC_Final(&hmacCtx, result.data(), nullptr)) {
|
|
return {};
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The test key is 32byte word with all bytes set to TestKeyBits::BYTE.
|
|
*/
|
|
enum class TestKeyBits : uint8_t {
|
|
BYTE = 165 /* 0xA5 */,
|
|
};
|
|
|
|
std::optional<std::vector<std::uint8_t>> TestSign(
|
|
const std::vector<std::uint8_t>& message) {
|
|
// the same as userConfirm()
|
|
using namespace support;
|
|
auth_token_key_t key;
|
|
key.fill(static_cast<std::uint8_t>(TestKeyBits::BYTE));
|
|
using HMacer = HMacImplementation;
|
|
auto confirm_signed_opt =
|
|
HMacer::hmac256(key, {"confirmation token", message});
|
|
if (!confirm_signed_opt) {
|
|
return std::nullopt;
|
|
}
|
|
auto confirm_signed = confirm_signed_opt.value();
|
|
return {
|
|
std::vector<std::uint8_t>(confirm_signed.begin(), confirm_signed.end())};
|
|
}
|
|
|
|
std::optional<std::vector<std::uint8_t>> Sign(
|
|
const std::vector<std::uint8_t>& message) {
|
|
SharedFD socket_to_secure_env = ConnectToSecureEnv();
|
|
if (!socket_to_secure_env->IsOpen()) {
|
|
ConfUiLog(ERROR) << "Failed to connect to secure_env signing server.";
|
|
return std::nullopt;
|
|
}
|
|
ConfUiSignRequester sign_client(socket_to_secure_env);
|
|
// request signature
|
|
sign_client.Request(message);
|
|
auto response_opt = sign_client.Receive();
|
|
if (!response_opt) {
|
|
ConfUiLog(ERROR) << "Received nullopt";
|
|
return std::nullopt;
|
|
}
|
|
// respond should be either error code or the signature
|
|
auto response = std::move(response_opt.value());
|
|
if (response.error_ != SignMessageError::kOk) {
|
|
ConfUiLog(ERROR) << "Response was received with non-OK error code";
|
|
return std::nullopt;
|
|
}
|
|
return {response.payload_};
|
|
}
|
|
} // namespace confui
|
|
} // end of namespace cuttlefish
|