/* * 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 "adb/tls/adb_ca_list.h" #include #include #include #include #include #include namespace adb { namespace tls { namespace { // CA issuer identifier to distinguished embedded keys. Also has version // information appended to the end of the string (e.g. "AdbKey-0"). static constexpr int kAdbKeyIdentifierNid = NID_organizationName; static constexpr char kAdbKeyIdentifierV0[] = "AdbKey-0"; // Where we store the actual data static constexpr int kAdbKeyValueNid = NID_commonName; // TODO: Remove this once X509_NAME_add_entry_by_NID is fixed to use const unsigned char* // https://boringssl-review.googlesource.com/c/boringssl/+/39764 int X509_NAME_add_entry_by_NID_const(X509_NAME* name, int nid, int type, const unsigned char* bytes, int len, int loc, int set) { return X509_NAME_add_entry_by_NID(name, nid, type, const_cast(bytes), len, loc, set); } bool IsHexDigit(char c) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); } // Wrapper around X509_NAME_get_text_by_NID that first calculates the size // of the string. Returns empty string on failure. std::optional GetX509NameTextByNid(X509_NAME* name, int nid) { // |len| is the len of the text excluding the final null int len = X509_NAME_get_text_by_NID(name, nid, nullptr, -1); if (len <= 0) { return std::nullopt; } // Include the space for the final null byte std::vector buf(len + 1, '\0'); CHECK(X509_NAME_get_text_by_NID(name, nid, buf.data(), buf.size())); return std::make_optional(std::string(buf.data())); } } // namespace // Takes an encoded public key and generates a X509_NAME that can be used in // TlsConnection::SetClientCAList(), to allow the client to figure out which of // its keys it should try to use in the TLS handshake. bssl::UniquePtr CreateCAIssuerFromEncodedKey(std::string_view key) { // "O=AdbKey-0;CN=;" CHECK(!key.empty()); std::string identifier = kAdbKeyIdentifierV0; bssl::UniquePtr name(X509_NAME_new()); CHECK(X509_NAME_add_entry_by_NID_const(name.get(), kAdbKeyIdentifierNid, MBSTRING_ASC, reinterpret_cast(identifier.data()), identifier.size(), -1, 0)); CHECK(X509_NAME_add_entry_by_NID_const(name.get(), kAdbKeyValueNid, MBSTRING_ASC, reinterpret_cast(key.data()), key.size(), -1, 0)); return name; } // Parses a CA issuer and returns the encoded key, if any. std::optional ParseEncodedKeyFromCAIssuer(X509_NAME* issuer) { CHECK(issuer); auto buf = GetX509NameTextByNid(issuer, kAdbKeyIdentifierNid); if (!buf) { return std::nullopt; } // Check for supported versions if (*buf == kAdbKeyIdentifierV0) { return GetX509NameTextByNid(issuer, kAdbKeyValueNid); } return std::nullopt; } std::string SHA256BitsToHexString(std::string_view sha256) { CHECK_EQ(sha256.size(), static_cast(SHA256_DIGEST_LENGTH)); std::stringstream ss; auto* u8 = reinterpret_cast(sha256.data()); ss << std::uppercase << std::setfill('0') << std::hex; // Convert to hex-string representation for (size_t i = 0; i < SHA256_DIGEST_LENGTH; ++i) { // Need to cast to something bigger than one byte, or // stringstream will interpret it as a char value. ss << std::setw(2) << static_cast(u8[i]); } return ss.str(); } std::optional SHA256HexStringToBits(std::string_view sha256_str) { if (sha256_str.size() != SHA256_DIGEST_LENGTH * 2) { return std::nullopt; } std::string result; for (size_t i = 0; i < SHA256_DIGEST_LENGTH; ++i) { auto bytestr = std::string(sha256_str.substr(i * 2, 2)); if (!IsHexDigit(bytestr[0]) || !IsHexDigit(bytestr[1])) { LOG(ERROR) << "SHA256 string has invalid non-hex chars"; return std::nullopt; } result += static_cast(std::stol(bytestr, nullptr, 16)); } return result; } } // namespace tls } // namespace adb