| /* |
| * 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 |