Commit 3f958afb authored by Erik Chen's avatar Erik Chen Committed by Chromium LUCI CQ

lacros: Implement platformKeysInternal.getPublicKey.

This CL refactors the ash implementation of
platformKeysInternal.getPublicKey into chromeos::platform_keys. This has
no intended behavior change for ash. This CL hooks up the crosapi
KeystoreService::GetPublicKey by forwarding to the same
chromeos::platform_keys implementation.

Change-Id: I19daa05727353c65ca072e365297c0e51f6d8b85
Bug: 1164523
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2626044Reviewed-by: default avatarNico Weber <thakis@chromium.org>
Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Reviewed-by: default avatarMaksim Ivanov <emaxx@chromium.org>
Reviewed-by: default avatarJames Cook <jamescook@chromium.org>
Reviewed-by: default avatarMichael Ershov <miersh@google.com>
Commit-Queue: Erik Chen <erikchen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#843373}
parent 0fef84b8
...@@ -4518,6 +4518,7 @@ static_library("browser") { ...@@ -4518,6 +4518,7 @@ static_library("browser") {
"//chromeos/components/cdm_factory_daemon:cdm_factory_daemon_browser", "//chromeos/components/cdm_factory_daemon:cdm_factory_daemon_browser",
"//chromeos/components/quick_answers", "//chromeos/components/quick_answers",
"//chromeos/components/sync_wifi", "//chromeos/components/sync_wifi",
"//chromeos/crosapi/cpp",
"//chromeos/crosapi/mojom", "//chromeos/crosapi/mojom",
"//chromeos/dbus", "//chromeos/dbus",
"//chromeos/geolocation", "//chromeos/geolocation",
...@@ -4637,6 +4638,7 @@ static_library("browser") { ...@@ -4637,6 +4638,7 @@ static_library("browser") {
"platform_util_lacros.cc", "platform_util_lacros.cc",
] ]
deps += [ deps += [
"//chromeos/crosapi/cpp",
"//chromeos/crosapi/mojom", "//chromeos/crosapi/mojom",
"//chromeos/lacros", "//chromeos/lacros",
"//chromeos/ui/frame", "//chromeos/ui/frame",
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h"
#include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h"
#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager.h"
#include "chromeos/crosapi/cpp/keystore_service_util.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "net/cert/x509_certificate.h" #include "net/cert/x509_certificate.h"
#include "third_party/boringssl/src/include/openssl/pool.h" #include "third_party/boringssl/src/include/openssl/pool.h"
...@@ -21,6 +22,7 @@ namespace crosapi { ...@@ -21,6 +22,7 @@ namespace crosapi {
using PlatformKeysService = chromeos::platform_keys::PlatformKeysService; using PlatformKeysService = chromeos::platform_keys::PlatformKeysService;
using TokenId = chromeos::platform_keys::TokenId; using TokenId = chromeos::platform_keys::TokenId;
using SigningAlgorithmName = crosapi::mojom::KeystoreSigningAlgorithmName;
namespace { namespace {
...@@ -28,6 +30,8 @@ const char kEnterprisePlatformErrorInvalidX509Cert[] = ...@@ -28,6 +30,8 @@ const char kEnterprisePlatformErrorInvalidX509Cert[] =
"Certificate is not a valid X.509 certificate."; "Certificate is not a valid X.509 certificate.";
const char kUnsupportedKeystoreType[] = "Keystore type is not supported."; const char kUnsupportedKeystoreType[] = "Keystore type is not supported.";
const char kUnsupportedAlgorithmType[] = "Algorithm type is not supported."; const char kUnsupportedAlgorithmType[] = "Algorithm type is not supported.";
const char kErrorAlgorithmNotPermittedByCertificate[] =
"The requested Algorithm is not permitted by the certificate.";
// Converts a binary blob to a certificate. // Converts a binary blob to a certificate.
scoped_refptr<net::X509Certificate> ParseCertificate( scoped_refptr<net::X509Certificate> ParseCertificate(
...@@ -60,6 +64,18 @@ base::Optional<TokenId> KeystoreToToken(mojom::KeystoreType type) { ...@@ -60,6 +64,18 @@ base::Optional<TokenId> KeystoreToToken(mojom::KeystoreType type) {
} }
} }
base::Optional<std::string> StringFromSigningAlgorithmName(
SigningAlgorithmName name) {
switch (name) {
case SigningAlgorithmName::kRsassaPkcs115:
return crosapi::keystore_service_util::kWebCryptoRsassaPkcs1v15;
case SigningAlgorithmName::kEcdsa:
return crosapi::keystore_service_util::kWebCryptoEcdsa;
case SigningAlgorithmName::kUnknown:
return base::nullopt;
}
}
} // namespace } // namespace
KeystoreServiceAsh::KeystoreServiceAsh( KeystoreServiceAsh::KeystoreServiceAsh(
...@@ -216,6 +232,45 @@ void KeystoreServiceAsh::RemoveCertificate( ...@@ -216,6 +232,45 @@ void KeystoreServiceAsh::RemoveCertificate(
std::move(callback))); std::move(callback)));
} }
void KeystoreServiceAsh::GetPublicKey(
const std::vector<uint8_t>& certificate,
mojom::KeystoreSigningAlgorithmName algorithm_name,
GetPublicKeyCallback callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
base::Optional<std::string> name =
StringFromSigningAlgorithmName(algorithm_name);
if (!name) {
std::move(callback).Run(mojom::GetPublicKeyResult::NewErrorMessage(
kErrorAlgorithmNotPermittedByCertificate));
return;
}
chromeos::platform_keys::GetPublicKeyAndAlgorithmOutput output =
chromeos::platform_keys::GetPublicKeyAndAlgorithm(certificate,
name.value());
mojom::GetPublicKeyResultPtr result_ptr = mojom::GetPublicKeyResult::New();
if (output.error.empty()) {
base::Optional<crosapi::mojom::KeystoreSigningAlgorithmPtr>
signing_algorithm =
crosapi::keystore_service_util::SigningAlgorithmFromDictionary(
output.algorithm);
if (signing_algorithm) {
mojom::GetPublicKeySuccessResultPtr success_result_ptr =
mojom::GetPublicKeySuccessResult::New();
success_result_ptr->public_key = std::move(output.public_key);
success_result_ptr->algorithm_properties =
std::move(signing_algorithm.value());
result_ptr->set_success_result(std::move(success_result_ptr));
} else {
result_ptr->set_error_message(kUnsupportedAlgorithmType);
}
} else {
result_ptr->set_error_message(output.error);
}
std::move(callback).Run(std::move(result_ptr));
}
// static // static
void KeystoreServiceAsh::OnGetTokens( void KeystoreServiceAsh::OnGetTokens(
GetKeyStoresCallback callback, GetKeyStoresCallback callback,
......
...@@ -53,6 +53,9 @@ class KeystoreServiceAsh : public mojom::KeystoreService { ...@@ -53,6 +53,9 @@ class KeystoreServiceAsh : public mojom::KeystoreService {
void RemoveCertificate(mojom::KeystoreType keystore, void RemoveCertificate(mojom::KeystoreType keystore,
const std::vector<uint8_t>& certificate, const std::vector<uint8_t>& certificate,
RemoveCertificateCallback callback) override; RemoveCertificateCallback callback) override;
void GetPublicKey(const std::vector<uint8_t>& certificate,
mojom::KeystoreSigningAlgorithmName algorithm_name,
GetPublicKeyCallback callback) override;
private: private:
static void OnGetTokens( static void OnGetTokens(
......
...@@ -9,14 +9,35 @@ ...@@ -9,14 +9,35 @@
#include <string> #include <string>
#include "base/callback.h" #include "base/callback.h"
#include "base/check_op.h"
#include "base/task/task_traits.h" #include "base/task/task_traits.h"
#include "base/task/thread_pool.h" #include "base/task/thread_pool.h"
#include "chromeos/crosapi/cpp/keystore_service_util.h"
#include "net/base/hash_value.h" #include "net/base/hash_value.h"
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "net/cert/x509_certificate.h" #include "net/cert/x509_certificate.h"
namespace { namespace {
const char kErrorAlgorithmNotPermittedByCertificate[] =
"The requested Algorithm is not permitted by the certificate.";
const char kErrorInvalidX509Cert[] =
"Certificate is not a valid X.509 certificate.";
using crosapi::keystore_service_util::kWebCryptoEcdsa;
using crosapi::keystore_service_util::kWebCryptoNamedCurveP256;
using crosapi::keystore_service_util::kWebCryptoRsassaPkcs1v15;
void BuildWebCryptoEcdsaAlgorithmDictionary(
const chromeos::platform_keys::PublicKeyInfo& key_info,
base::DictionaryValue* algorithm) {
CHECK_EQ(net::X509Certificate::kPublicKeyTypeECDSA, key_info.key_type);
algorithm->SetStringKey("name", kWebCryptoEcdsa);
// Only P-256 named curve is supported.
algorithm->SetStringKey("namedCurve", kWebCryptoNamedCurveP256);
}
void IntersectOnWorkerThread(const net::CertificateList& certs1, void IntersectOnWorkerThread(const net::CertificateList& certs1,
const net::CertificateList& certs2, const net::CertificateList& certs2,
net::CertificateList* intersection) { net::CertificateList* intersection) {
...@@ -102,6 +123,96 @@ void IntersectCertificates( ...@@ -102,6 +123,96 @@ void IntersectCertificates(
base::BindOnce(callback, base::Passed(&intersection))); base::BindOnce(callback, base::Passed(&intersection)));
} }
GetPublicKeyAndAlgorithmOutput::GetPublicKeyAndAlgorithmOutput() = default;
GetPublicKeyAndAlgorithmOutput::GetPublicKeyAndAlgorithmOutput(
GetPublicKeyAndAlgorithmOutput&&) = default;
GetPublicKeyAndAlgorithmOutput::~GetPublicKeyAndAlgorithmOutput() = default;
GetPublicKeyAndAlgorithmOutput GetPublicKeyAndAlgorithm(
const std::vector<uint8_t>& possibly_invalid_cert_der,
const std::string& algorithm_name) {
GetPublicKeyAndAlgorithmOutput output;
if (possibly_invalid_cert_der.empty()) {
output.error = kErrorInvalidX509Cert;
return output;
}
// Allow UTF-8 inside PrintableStrings in client certificates. See
// crbug.com/770323 and crbug.com/788655.
net::X509Certificate::UnsafeCreateOptions options;
options.printable_string_is_utf8 = true;
scoped_refptr<net::X509Certificate> cert_x509 =
net::X509Certificate::CreateFromBytesUnsafeOptions(
reinterpret_cast<const char*>(possibly_invalid_cert_der.data()),
possibly_invalid_cert_der.size(), options);
if (!cert_x509) {
output.error = kErrorInvalidX509Cert;
return output;
}
PublicKeyInfo key_info;
key_info.public_key_spki_der =
chromeos::platform_keys::GetSubjectPublicKeyInfo(cert_x509);
if (!chromeos::platform_keys::GetPublicKey(cert_x509, &key_info.key_type,
&key_info.key_size_bits) ||
(key_info.key_type != net::X509Certificate::kPublicKeyTypeRSA &&
key_info.key_type != net::X509Certificate::kPublicKeyTypeECDSA)) {
output.error = StatusToString(Status::kErrorAlgorithmNotSupported);
return output;
}
// Currently, the only supported combinations are:
// 1- A certificate declaring rsaEncryption in the SubjectPublicKeyInfo used
// with the RSASSA-PKCS1-v1.5 algorithm.
// 2- A certificate declaring id-ecPublicKey in the SubjectPublicKeyInfo used
// with the ECDSA algorithm.
if (algorithm_name == kWebCryptoRsassaPkcs1v15) {
if (key_info.key_type != net::X509Certificate::kPublicKeyTypeRSA) {
output.error = kErrorAlgorithmNotPermittedByCertificate;
return output;
}
BuildWebCryptoRSAAlgorithmDictionary(key_info, &output.algorithm);
output.public_key =
std::vector<uint8_t>(key_info.public_key_spki_der.begin(),
key_info.public_key_spki_der.end());
return output;
}
if (algorithm_name == kWebCryptoEcdsa) {
if (key_info.key_type != net::X509Certificate::kPublicKeyTypeECDSA) {
output.error = kErrorAlgorithmNotPermittedByCertificate;
return output;
}
BuildWebCryptoEcdsaAlgorithmDictionary(key_info, &output.algorithm);
output.public_key =
std::vector<uint8_t>(key_info.public_key_spki_der.begin(),
key_info.public_key_spki_der.end());
return output;
}
output.error = kErrorAlgorithmNotPermittedByCertificate;
return output;
}
PublicKeyInfo::PublicKeyInfo() = default;
PublicKeyInfo::~PublicKeyInfo() = default;
void BuildWebCryptoRSAAlgorithmDictionary(const PublicKeyInfo& key_info,
base::DictionaryValue* algorithm) {
CHECK_EQ(net::X509Certificate::kPublicKeyTypeRSA, key_info.key_type);
algorithm->SetStringKey("name", kWebCryptoRsassaPkcs1v15);
algorithm->SetKey("modulusLength",
base::Value(static_cast<int>(key_info.key_size_bits)));
// Equals 65537.
static constexpr uint8_t kDefaultPublicExponent[] = {0x01, 0x00, 0x01};
algorithm->SetKey("publicExponent",
base::Value(base::make_span(kDefaultPublicExponent)));
}
ClientCertificateRequest::ClientCertificateRequest() = default; ClientCertificateRequest::ClientCertificateRequest() = default;
ClientCertificateRequest::ClientCertificateRequest( ClientCertificateRequest::ClientCertificateRequest(
......
...@@ -5,11 +5,14 @@ ...@@ -5,11 +5,14 @@
#ifndef CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_PLATFORM_KEYS_H_ #ifndef CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_PLATFORM_KEYS_H_
#define CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_PLATFORM_KEYS_H_ #define CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_PLATFORM_KEYS_H_
#include <stdint.h>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include "base/callback.h" #include "base/callback.h"
#include "base/values.h"
#include "net/cert/x509_certificate.h" #include "net/cert/x509_certificate.h"
namespace chromeos { namespace chromeos {
...@@ -76,6 +79,45 @@ void IntersectCertificates( ...@@ -76,6 +79,45 @@ void IntersectCertificates(
const base::Callback<void(std::unique_ptr<net::CertificateList>)>& const base::Callback<void(std::unique_ptr<net::CertificateList>)>&
callback); callback);
// The output for GetPublicKeyAndAlgorithm.
struct GetPublicKeyAndAlgorithmOutput {
GetPublicKeyAndAlgorithmOutput();
GetPublicKeyAndAlgorithmOutput(GetPublicKeyAndAlgorithmOutput&&);
~GetPublicKeyAndAlgorithmOutput();
std::string error; // Only set on error.
std::vector<uint8_t> public_key; // Only set on success.
base::DictionaryValue algorithm; // Only set on success.
};
// This is a convenient wrapper around GetPublicKey which also builds a
// WebCrypto algorithm dictionary and performs error checking.
GetPublicKeyAndAlgorithmOutput GetPublicKeyAndAlgorithm(
const std::vector<uint8_t>& possibly_invalid_cert_der,
const std::string& algorithm_name);
struct PublicKeyInfo {
PublicKeyInfo();
~PublicKeyInfo();
// The X.509 Subject Public Key Info of the key in DER encoding.
std::string public_key_spki_der;
// The type of the key.
net::X509Certificate::PublicKeyType key_type =
net::X509Certificate::kPublicKeyTypeUnknown;
// The size of the key in bits.
size_t key_size_bits = 0;
};
// Builds a partial WebCrypto Algorithm object from the parameters available in
// |key_info|, which must be the info of an RSA key. This doesn't include
// sign/hash parameters and thus isn't complete. platform_keys::GetPublicKey()
// enforced the public exponent 65537.
void BuildWebCryptoRSAAlgorithmDictionary(const PublicKeyInfo& key_info,
base::DictionaryValue* algorithm);
// Obtains information about the public key in |certificate|. // Obtains information about the public key in |certificate|.
// If |certificate| contains an RSA key, sets |key_size_bits| to the modulus // If |certificate| contains an RSA key, sets |key_size_bits| to the modulus
// length, and |key_type| to type RSA and returns true. // length, and |key_type| to type RSA and returns true.
......
...@@ -944,7 +944,10 @@ static_library("extensions") { ...@@ -944,7 +944,10 @@ static_library("extensions") {
"api/enterprise_platform_keys/enterprise_platform_keys_api.h", "api/enterprise_platform_keys/enterprise_platform_keys_api.h",
"api/platform_keys/platform_keys_api.h", "api/platform_keys/platform_keys_api.h",
] ]
deps += [ "//chromeos/crosapi/mojom" ] deps += [
"//chromeos/crosapi/cpp",
"//chromeos/crosapi/mojom",
]
if (is_chromeos_lacros) { if (is_chromeos_lacros) {
sources += [ sources += [
"api/enterprise_device_attributes/enterprise_device_attributes_api_lacros.cc", "api/enterprise_device_attributes/enterprise_device_attributes_api_lacros.cc",
......
...@@ -20,12 +20,15 @@ ...@@ -20,12 +20,15 @@
#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/chromeos/platform_keys/platform_keys.h"
#include "chrome/browser/extensions/api/platform_keys/verify_trust_api.h" #include "chrome/browser/extensions/api/platform_keys/verify_trust_api.h"
#include "chrome/common/extensions/api/platform_keys_internal.h" #include "chrome/common/extensions/api/platform_keys_internal.h"
#include "chromeos/crosapi/cpp/keystore_service_util.h"
#include "components/web_modal/web_contents_modal_dialog_manager.h" #include "components/web_modal/web_contents_modal_dialog_manager.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "net/cert/x509_certificate.h" #include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.h" #include "net/cert/x509_util.h"
using PublicKeyInfo = chromeos::platform_keys::PublicKeyInfo;
namespace extensions { namespace extensions {
namespace api_pk = api::platform_keys; namespace api_pk = api::platform_keys;
...@@ -33,53 +36,12 @@ namespace api_pki = api::platform_keys_internal; ...@@ -33,53 +36,12 @@ namespace api_pki = api::platform_keys_internal;
namespace { namespace {
const char kErrorAlgorithmNotPermittedByCertificate[] =
"The requested Algorithm is not permitted by the certificate.";
const char kErrorInteractiveCallFromBackground[] = const char kErrorInteractiveCallFromBackground[] =
"Interactive calls must happen in the context of a browser tab or a " "Interactive calls must happen in the context of a browser tab or a "
"window."; "window.";
const char kWebCryptoEcdsa[] = "ECDSA"; using crosapi::keystore_service_util::kWebCryptoEcdsa;
const char kWebCryptoNamedCurveP256[] = "P-256"; using crosapi::keystore_service_util::kWebCryptoRsassaPkcs1v15;
const char kWebCryptoRSASSA_PKCS1_v1_5[] = "RSASSA-PKCS1-v1_5";
struct PublicKeyInfo {
// The X.509 Subject Public Key Info of the key in DER encoding.
std::string public_key_spki_der;
// The type of the key.
net::X509Certificate::PublicKeyType key_type =
net::X509Certificate::kPublicKeyTypeUnknown;
// The size of the key in bits.
size_t key_size_bits = 0;
};
// Builds a partial WebCrypto Algorithm object from the parameters available in
// |key_info|, which must the info of an RSA key. This doesn't include sign/hash
// parameters and thus isn't complete.
// platform_keys::GetPublicKey() enforced the public exponent 65537.
void BuildWebCryptoRSAAlgorithmDictionary(const PublicKeyInfo& key_info,
base::DictionaryValue* algorithm) {
CHECK_EQ(net::X509Certificate::kPublicKeyTypeRSA, key_info.key_type);
algorithm->SetStringKey("name", kWebCryptoRSASSA_PKCS1_v1_5);
algorithm->SetKey("modulusLength",
base::Value(static_cast<int>(key_info.key_size_bits)));
// Equals 65537.
static constexpr uint8_t kDefaultPublicExponent[] = {0x01, 0x00, 0x01};
algorithm->SetKey("publicExponent",
base::Value(base::make_span(kDefaultPublicExponent)));
}
void BuildWebCryptoEcdsaAlgorithmDictionary(const PublicKeyInfo& key_info,
base::DictionaryValue* algorithm) {
CHECK_EQ(net::X509Certificate::kPublicKeyTypeECDSA, key_info.key_type);
algorithm->SetStringKey("name", kWebCryptoEcdsa);
// Only P-256 named curve is supported.
algorithm->SetStringKey("namedCurve", kWebCryptoNamedCurveP256);
}
const struct NameValuePair { const struct NameValuePair {
const char* const name; const char* const name;
...@@ -133,67 +95,17 @@ PlatformKeysInternalGetPublicKeyFunction::Run() { ...@@ -133,67 +95,17 @@ PlatformKeysInternalGetPublicKeyFunction::Run() {
api_pki::GetPublicKey::Params::Create(*args_)); api_pki::GetPublicKey::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params); EXTENSION_FUNCTION_VALIDATE(params);
const std::vector<uint8_t>& cert_der = params->certificate; chromeos::platform_keys::GetPublicKeyAndAlgorithmOutput output =
if (cert_der.empty()) chromeos::platform_keys::GetPublicKeyAndAlgorithm(params->certificate,
return RespondNow(Error(platform_keys::kErrorInvalidX509Cert)); params->algorithm_name);
// Allow UTF-8 inside PrintableStrings in client certificates. See if (!output.error.empty()) {
// crbug.com/770323 and crbug.com/788655. return RespondNow(Error(output.error));
net::X509Certificate::UnsafeCreateOptions options;
options.printable_string_is_utf8 = true;
scoped_refptr<net::X509Certificate> cert_x509 =
net::X509Certificate::CreateFromBytesUnsafeOptions(
reinterpret_cast<const char*>(cert_der.data()), cert_der.size(),
options);
if (!cert_x509)
return RespondNow(Error(platform_keys::kErrorInvalidX509Cert));
PublicKeyInfo key_info;
key_info.public_key_spki_der =
chromeos::platform_keys::GetSubjectPublicKeyInfo(cert_x509);
if (!chromeos::platform_keys::GetPublicKey(cert_x509, &key_info.key_type,
&key_info.key_size_bits) ||
(key_info.key_type != net::X509Certificate::kPublicKeyTypeRSA &&
key_info.key_type != net::X509Certificate::kPublicKeyTypeECDSA)) {
return RespondNow(Error(StatusToString(
chromeos::platform_keys::Status::kErrorAlgorithmNotSupported)));
}
// Currently, the only supported combinations are:
// 1- A certificate declaring rsaEncryption in the SubjectPublicKeyInfo used
// with the RSASSA-PKCS1-v1.5 algorithm.
// 2- A certificate declaring id-ecPublicKey in the SubjectPublicKeyInfo used
// with the ECDSA algorithm.
if (params->algorithm_name == kWebCryptoRSASSA_PKCS1_v1_5) {
if (key_info.key_type != net::X509Certificate::kPublicKeyTypeRSA) {
return RespondNow(Error(kErrorAlgorithmNotPermittedByCertificate));
}
api_pki::GetPublicKey::Results::Algorithm algorithm;
BuildWebCryptoRSAAlgorithmDictionary(key_info,
&algorithm.additional_properties);
return RespondNow(ArgumentList(api_pki::GetPublicKey::Results::Create(
std::vector<uint8_t>(key_info.public_key_spki_der.begin(),
key_info.public_key_spki_der.end()),
algorithm)));
}
if (params->algorithm_name == kWebCryptoEcdsa) {
if (key_info.key_type != net::X509Certificate::kPublicKeyTypeECDSA) {
return RespondNow(Error(kErrorAlgorithmNotPermittedByCertificate));
} }
api_pki::GetPublicKey::Results::Algorithm algorithm; api_pki::GetPublicKey::Results::Algorithm algorithm;
BuildWebCryptoEcdsaAlgorithmDictionary(key_info, algorithm.additional_properties = std::move(output.algorithm);
&algorithm.additional_properties);
return RespondNow(ArgumentList(api_pki::GetPublicKey::Results::Create( return RespondNow(ArgumentList(api_pki::GetPublicKey::Results::Create(
std::vector<uint8_t>(key_info.public_key_spki_der.begin(), std::move(output.public_key), std::move(algorithm))));
key_info.public_key_spki_der.end()),
algorithm)));
}
return RespondNow(Error(kErrorAlgorithmNotPermittedByCertificate));
} }
PlatformKeysInternalGetPublicKeyBySpkiFunction:: PlatformKeysInternalGetPublicKeyBySpkiFunction::
...@@ -223,14 +135,14 @@ PlatformKeysInternalGetPublicKeyBySpkiFunction::Run() { ...@@ -223,14 +135,14 @@ PlatformKeysInternalGetPublicKeyBySpkiFunction::Run() {
// Currently, the only supported combination is: // Currently, the only supported combination is:
// A SPKI declaring rsaEncryption used with the RSASSA-PKCS1-v1.5 algorithm. // A SPKI declaring rsaEncryption used with the RSASSA-PKCS1-v1.5 algorithm.
if (params->algorithm_name != kWebCryptoRSASSA_PKCS1_v1_5) { if (params->algorithm_name != kWebCryptoRsassaPkcs1v15) {
return RespondNow(Error(StatusToString( return RespondNow(Error(StatusToString(
chromeos::platform_keys::Status::kErrorAlgorithmNotSupported))); chromeos::platform_keys::Status::kErrorAlgorithmNotSupported)));
} }
api_pki::GetPublicKeyBySpki::Results::Algorithm algorithm; api_pki::GetPublicKeyBySpki::Results::Algorithm algorithm;
BuildWebCryptoRSAAlgorithmDictionary(key_info, chromeos::platform_keys::BuildWebCryptoRSAAlgorithmDictionary(
&algorithm.additional_properties); key_info, &algorithm.additional_properties);
return RespondNow(ArgumentList(api_pki::GetPublicKeyBySpki::Results::Create( return RespondNow(ArgumentList(api_pki::GetPublicKeyBySpki::Results::Create(
public_key_spki_der, algorithm))); public_key_spki_der, algorithm)));
...@@ -347,7 +259,7 @@ void PlatformKeysInternalSelectClientCertificatesFunction:: ...@@ -347,7 +259,7 @@ void PlatformKeysInternalSelectClientCertificatesFunction::
result_match.certificate.assign(der_encoded_cert.begin(), result_match.certificate.assign(der_encoded_cert.begin(),
der_encoded_cert.end()); der_encoded_cert.end());
BuildWebCryptoRSAAlgorithmDictionary( chromeos::platform_keys::BuildWebCryptoRSAAlgorithmDictionary(
key_info, &result_match.key_algorithm.additional_properties); key_info, &result_match.key_algorithm.additional_properties);
result_matches.push_back(std::move(result_match)); result_matches.push_back(std::move(result_match));
} }
...@@ -380,7 +292,7 @@ ExtensionFunction::ResponseAction PlatformKeysInternalSignFunction::Run() { ...@@ -380,7 +292,7 @@ ExtensionFunction::ResponseAction PlatformKeysInternalSignFunction::Run() {
if (params->hash_algorithm_name == "none") { if (params->hash_algorithm_name == "none") {
// Signing without digesting is only supported for RSASSA-PKCS1-v1_5. // Signing without digesting is only supported for RSASSA-PKCS1-v1_5.
if (params->algorithm_name != kWebCryptoRSASSA_PKCS1_v1_5) if (params->algorithm_name != kWebCryptoRsassaPkcs1v15)
return RespondNow(Error(StatusToString( return RespondNow(Error(StatusToString(
chromeos::platform_keys::Status::kErrorAlgorithmNotSupported))); chromeos::platform_keys::Status::kErrorAlgorithmNotSupported)));
...@@ -406,7 +318,7 @@ ExtensionFunction::ResponseAction PlatformKeysInternalSignFunction::Run() { ...@@ -406,7 +318,7 @@ ExtensionFunction::ResponseAction PlatformKeysInternalSignFunction::Run() {
} }
chromeos::platform_keys::KeyType key_type; chromeos::platform_keys::KeyType key_type;
if (params->algorithm_name == kWebCryptoRSASSA_PKCS1_v1_5) { if (params->algorithm_name == kWebCryptoRsassaPkcs1v15) {
key_type = chromeos::platform_keys::KeyType::kRsassaPkcs1V15; key_type = chromeos::platform_keys::KeyType::kRsassaPkcs1V15;
} else if (params->algorithm_name == kWebCryptoEcdsa) { } else if (params->algorithm_name == kWebCryptoEcdsa) {
key_type = chromeos::platform_keys::KeyType::kEcdsa; key_type = chromeos::platform_keys::KeyType::kEcdsa;
......
...@@ -4,14 +4,44 @@ ...@@ -4,14 +4,44 @@
#include "chrome/browser/extensions/api/platform_keys/platform_keys_api_lacros.h" #include "chrome/browser/extensions/api/platform_keys/platform_keys_api_lacros.h"
#include "base/optional.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/platform_keys_internal.h"
#include "chromeos/crosapi/cpp/keystore_service_util.h"
#include "chromeos/lacros/lacros_chrome_service_impl.h"
namespace extensions { namespace extensions {
namespace api_pki = api::platform_keys_internal;
using SigningAlgorithmName = crosapi::mojom::KeystoreSigningAlgorithmName;
namespace {
const char kUnsupportedByAsh[] = "Not implemented.";
const char kUnsupportedProfile[] = "Not available.";
const char kErrorAlgorithmNotPermittedByCertificate[] =
"The requested Algorithm is not permitted by the certificate.";
using crosapi::keystore_service_util::kWebCryptoEcdsa;
using crosapi::keystore_service_util::kWebCryptoRsassaPkcs1v15;
base::Optional<SigningAlgorithmName> SigningAlgorithmNameFromString(
const std::string& input) {
if (input == kWebCryptoRsassaPkcs1v15)
return SigningAlgorithmName::kRsassaPkcs115;
if (input == kWebCryptoEcdsa)
return SigningAlgorithmName::kEcdsa;
return base::nullopt;
}
} // namespace
PlatformKeysInternalSelectClientCertificatesFunction:: PlatformKeysInternalSelectClientCertificatesFunction::
~PlatformKeysInternalSelectClientCertificatesFunction() {} ~PlatformKeysInternalSelectClientCertificatesFunction() {}
ExtensionFunction::ResponseAction ExtensionFunction::ResponseAction
PlatformKeysInternalSelectClientCertificatesFunction::Run() { PlatformKeysInternalSelectClientCertificatesFunction::Run() {
return RespondNow(Error("Not implemented.")); return RespondNow(Error(kUnsupportedByAsh));
} }
PlatformKeysInternalGetPublicKeyFunction:: PlatformKeysInternalGetPublicKeyFunction::
...@@ -19,7 +49,58 @@ PlatformKeysInternalGetPublicKeyFunction:: ...@@ -19,7 +49,58 @@ PlatformKeysInternalGetPublicKeyFunction::
ExtensionFunction::ResponseAction ExtensionFunction::ResponseAction
PlatformKeysInternalGetPublicKeyFunction::Run() { PlatformKeysInternalGetPublicKeyFunction::Run() {
return RespondNow(Error("Not implemented.")); std::unique_ptr<api_pki::GetPublicKey::Params> params(
api_pki::GetPublicKey::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
if (chromeos::LacrosChromeServiceImpl::Get()->GetInterfaceVersion(
crosapi::mojom::KeystoreService::Uuid_) < 3) {
return RespondNow(Error(kUnsupportedByAsh));
}
// These APIs are used in security-sensitive contexts. We need to ensure that
// the user for ash is the same as the user for lacros. We do this by
// restricting the API to the default profile, which is guaranteed to be the
// same user.
if (!Profile::FromBrowserContext(browser_context())->IsMainProfile())
return RespondNow(Error(kUnsupportedProfile));
base::Optional<SigningAlgorithmName> algorithm_name =
SigningAlgorithmNameFromString(params->algorithm_name);
if (!algorithm_name) {
return RespondNow(Error(kErrorAlgorithmNotPermittedByCertificate));
}
auto cb = base::BindOnce(
&PlatformKeysInternalGetPublicKeyFunction::OnGetPublicKey, this);
chromeos::LacrosChromeServiceImpl::Get()
->keystore_service_remote()
->GetPublicKey(params->certificate, algorithm_name.value(),
std::move(cb));
return RespondLater();
}
void PlatformKeysInternalGetPublicKeyFunction::OnGetPublicKey(
ResultPtr result) {
using Result = crosapi::mojom::GetPublicKeyResult;
switch (result->which()) {
case Result::Tag::ERROR_MESSAGE:
Respond(Error(result->get_error_message()));
return;
case Result::Tag::SUCCESS_RESULT:
api_pki::GetPublicKey::Results::Algorithm algorithm;
base::Optional<base::DictionaryValue> dict =
crosapi::keystore_service_util::DictionaryFromSigningAlgorithm(
result->get_success_result()->algorithm_properties);
if (!dict) {
Respond(Error(kUnsupportedByAsh));
return;
}
algorithm.additional_properties = std::move(dict.value());
Respond(ArgumentList(api_pki::GetPublicKey::Results::Create(
result->get_success_result()->public_key, std::move(algorithm))));
return;
}
} }
PlatformKeysInternalGetPublicKeyBySpkiFunction:: PlatformKeysInternalGetPublicKeyBySpkiFunction::
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_EXTENSIONS_API_PLATFORM_KEYS_PLATFORM_KEYS_API_LACROS_H_ #ifndef CHROME_BROWSER_EXTENSIONS_API_PLATFORM_KEYS_PLATFORM_KEYS_API_LACROS_H_
#define CHROME_BROWSER_EXTENSIONS_API_PLATFORM_KEYS_PLATFORM_KEYS_API_LACROS_H_ #define CHROME_BROWSER_EXTENSIONS_API_PLATFORM_KEYS_PLATFORM_KEYS_API_LACROS_H_
#include "chromeos/crosapi/mojom/keystore_service.mojom.h"
#include "extensions/browser/extension_function.h" #include "extensions/browser/extension_function.h"
namespace extensions { namespace extensions {
...@@ -24,6 +25,9 @@ class PlatformKeysInternalGetPublicKeyFunction : public ExtensionFunction { ...@@ -24,6 +25,9 @@ class PlatformKeysInternalGetPublicKeyFunction : public ExtensionFunction {
~PlatformKeysInternalGetPublicKeyFunction() override; ~PlatformKeysInternalGetPublicKeyFunction() override;
ResponseAction Run() override; ResponseAction Run() override;
using ResultPtr = crosapi::mojom::GetPublicKeyResultPtr;
void OnGetPublicKey(ResultPtr result_ptr);
DECLARE_EXTENSION_FUNCTION("platformKeysInternal.getPublicKey", DECLARE_EXTENSION_FUNCTION("platformKeysInternal.getPublicKey",
PLATFORMKEYSINTERNAL_GETPUBLICKEY) PLATFORMKEYSINTERNAL_GETPUBLICKEY)
}; };
......
...@@ -155,6 +155,7 @@ test("chromeos_unittests") { ...@@ -155,6 +155,7 @@ test("chromeos_unittests") {
"//build:chromeos_buildflags", "//build:chromeos_buildflags",
"//chromeos/attestation:unit_tests", "//chromeos/attestation:unit_tests",
"//chromeos/audio:unit_tests", "//chromeos/audio:unit_tests",
"//chromeos/crosapi/cpp:unit_tests",
"//chromeos/cryptohome:unit_tests", "//chromeos/cryptohome:unit_tests",
"//chromeos/dbus:test_support", "//chromeos/dbus:test_support",
"//chromeos/dbus:unit_tests", "//chromeos/dbus:unit_tests",
......
...@@ -10,19 +10,42 @@ config("crosapi_implementation") { ...@@ -10,19 +10,42 @@ config("crosapi_implementation") {
component("cpp") { component("cpp") {
output_name = "crosapi_public_cpp" output_name = "crosapi_public_cpp"
sources = [ sources = [
"bitmap.cc",
"bitmap.h",
"bitmap_util.cc", "bitmap_util.cc",
"bitmap_util.h", "bitmap_util.h",
"crosapi_constants.cc", "crosapi_constants.cc",
"crosapi_constants.h", "crosapi_constants.h",
"keystore_service_util.cc",
"keystore_service_util.h",
"scoped_allow_sync_call.cc", "scoped_allow_sync_call.cc",
"scoped_allow_sync_call.h", "scoped_allow_sync_call.h",
] ]
configs += [ ":crosapi_implementation" ] configs += [ ":crosapi_implementation" ]
deps = [ deps = [
"//base", "//base",
"//chromeos/crosapi/mojom",
"//mojo/public/cpp/bindings", "//mojo/public/cpp/bindings",
"//skia", "//skia",
] ]
} }
# chromeos/crosapi/mojom depends on this component.
component("cpp_internal") {
output_name = "crosapi_private_cpp"
sources = [
"bitmap.cc",
"bitmap.h",
]
configs += [ ":crosapi_implementation" ]
deps = [ "//base" ]
}
source_set("unit_tests") {
testonly = true
deps = [
":cpp",
"//base/test:test_support",
"//chromeos/crosapi/mojom",
"//testing/gtest",
]
sources = [ "keystore_service_util_unittest.cc" ]
}
// 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/crosapi/cpp/keystore_service_util.h"
#include "base/numerics/safe_math.h"
#include "base/optional.h"
#include "base/values.h"
#include "chromeos/crosapi/mojom/keystore_service.mojom.h"
namespace crosapi {
namespace keystore_service_util {
const char kWebCryptoEcdsa[] = "ECDSA";
const char kWebCryptoRsassaPkcs1v15[] = "RSASSA-PKCS1-v1_5";
const char kWebCryptoNamedCurveP256[] = "P-256";
// Converts a signing algorithm into a WebCrypto dictionary.
base::Optional<base::DictionaryValue> DictionaryFromSigningAlgorithm(
const crosapi::mojom::KeystoreSigningAlgorithmPtr& algorithm) {
base::DictionaryValue value;
switch (algorithm->which()) {
case crosapi::mojom::KeystoreSigningAlgorithm::Tag::kPkcs115:
value.SetStringKey("name", kWebCryptoRsassaPkcs1v15);
if (!base::IsValueInRangeForNumericType<int>(
algorithm->get_pkcs115()->modulus_length)) {
return base::nullopt;
}
value.SetKey("modulusLength",
base::Value(base::checked_cast<int>(
algorithm->get_pkcs115()->modulus_length)));
if (!algorithm->get_pkcs115()->public_exponent) {
return base::nullopt;
}
value.SetKey(
"publicExponent",
base::Value(algorithm->get_pkcs115()->public_exponent.value()));
break;
case crosapi::mojom::KeystoreSigningAlgorithm::Tag::kEcdsa:
value.SetStringKey("name", kWebCryptoEcdsa);
value.SetStringKey("namedCurve", algorithm->get_ecdsa()->named_curve);
break;
}
return value;
}
base::Optional<crosapi::mojom::KeystoreSigningAlgorithmPtr>
SigningAlgorithmFromDictionary(const base::DictionaryValue& dictionary) {
crosapi::mojom::KeystoreSigningAlgorithmPtr algorithm =
crosapi::mojom::KeystoreSigningAlgorithm::New();
const std::string* name = dictionary.FindStringKey("name");
if (!name)
return base::nullopt;
if (*name == kWebCryptoRsassaPkcs1v15) {
base::Optional<int> modulus_length = dictionary.FindIntKey("modulusLength");
const std::vector<uint8_t>* public_exponent =
dictionary.FindBlobKey("publicExponent");
if (!modulus_length || !public_exponent)
return base::nullopt;
if (!base::IsValueInRangeForNumericType<uint32_t>(modulus_length.value()))
return base::nullopt;
crosapi::mojom::KeystorePKCS115ParamsPtr params =
crosapi::mojom::KeystorePKCS115Params::New();
params->modulus_length =
base::checked_cast<uint32_t>(modulus_length.value());
params->public_exponent = *public_exponent;
algorithm->set_pkcs115(std::move(params));
return algorithm;
}
if (*name == kWebCryptoEcdsa) {
const std::string* named_curve = dictionary.FindStringKey("namedCurve");
if (!named_curve)
return base::nullopt;
crosapi::mojom::KeystoreECDSAParamsPtr params =
crosapi::mojom::KeystoreECDSAParams::New();
params->named_curve = *named_curve;
algorithm->set_ecdsa(std::move(params));
return algorithm;
}
return base::nullopt;
}
} // namespace keystore_service_util
} // namespace crosapi
// 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.
#ifndef CHROMEOS_CROSAPI_CPP_KEYSTORE_SERVICE_UTIL_H_
#define CHROMEOS_CROSAPI_CPP_KEYSTORE_SERVICE_UTIL_H_
#include "base/component_export.h"
#include "base/optional.h"
#include "base/values.h"
#include "chromeos/crosapi/mojom/keystore_service.mojom.h"
namespace crosapi {
namespace keystore_service_util {
// The WebCrypto string for ECDSA.
COMPONENT_EXPORT(CROSAPI)
extern const char kWebCryptoEcdsa[];
// The WebCrypto string for PKCS1.
COMPONENT_EXPORT(CROSAPI)
extern const char kWebCryptoRsassaPkcs1v15[];
// The WebCrypto string for the P-256 named curve.
COMPONENT_EXPORT(CROSAPI)
extern const char kWebCryptoNamedCurveP256[];
// Converts a crosapi signing algorithm into a WebCrypto dictionary. Returns
// base::nullopt on error.
COMPONENT_EXPORT(CROSAPI)
base::Optional<base::DictionaryValue> DictionaryFromSigningAlgorithm(
const crosapi::mojom::KeystoreSigningAlgorithmPtr& algorithm);
// Converts a WebCrypto dictionary into a crosapi signing algorithm. Returns
// base::nullopt on error.
COMPONENT_EXPORT(CROSAPI)
base::Optional<crosapi::mojom::KeystoreSigningAlgorithmPtr>
SigningAlgorithmFromDictionary(const base::DictionaryValue& dictionary);
} // namespace keystore_service_util
} // namespace crosapi
#endif // CHROMEOS_CROSAPI_CPP_KEYSTORE_SERVICE_UTIL_H_
// 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/crosapi/cpp/keystore_service_util.h"
#include "base/optional.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace crosapi {
namespace keystore_service_util {
TEST(KeystoreServiceUtil, ECDSA) {
base::DictionaryValue value;
value.SetStringKey("name", kWebCryptoEcdsa);
value.SetStringKey("namedCurve", kWebCryptoNamedCurveP256);
base::Optional<crosapi::mojom::KeystoreSigningAlgorithmPtr> ptr =
SigningAlgorithmFromDictionary(value);
ASSERT_TRUE(ptr);
base::Optional<base::DictionaryValue> value2 =
DictionaryFromSigningAlgorithm(ptr.value());
ASSERT_TRUE(value2);
EXPECT_EQ(value, value2);
}
TEST(KeystoreServiceUtil, PKCS) {
base::DictionaryValue value;
value.SetStringKey("name", kWebCryptoRsassaPkcs1v15);
value.SetKey("modulusLength", base::Value(5));
// Equals 65537.
static constexpr uint8_t kDefaultPublicExponent[] = {0x01, 0x00, 0x01};
value.SetKey("publicExponent",
base::Value(base::make_span(kDefaultPublicExponent)));
base::Optional<crosapi::mojom::KeystoreSigningAlgorithmPtr> ptr =
SigningAlgorithmFromDictionary(value);
ASSERT_TRUE(ptr);
base::Optional<base::DictionaryValue> value2 =
DictionaryFromSigningAlgorithm(ptr.value());
ASSERT_TRUE(value2);
EXPECT_EQ(value, value2);
}
} // namespace keystore_service_util
} // namespace crosapi
...@@ -37,7 +37,7 @@ mojom("mojom") { ...@@ -37,7 +37,7 @@ mojom("mojom") {
traits_headers = [ "//chromeos/crosapi/mojom/bitmap_mojom_traits.h" ] traits_headers = [ "//chromeos/crosapi/mojom/bitmap_mojom_traits.h" ]
traits_public_deps = [ traits_public_deps = [
":mojom_traits", ":mojom_traits",
"//chromeos/crosapi/cpp", "//chromeos/crosapi/cpp:cpp_internal",
] ]
}, },
] ]
...@@ -63,7 +63,7 @@ component("mojom_traits") { ...@@ -63,7 +63,7 @@ component("mojom_traits") {
public_deps = [ public_deps = [
":mojom_shared", ":mojom_shared",
"//chromeos/crosapi/cpp", "//chromeos/crosapi/cpp:cpp_internal",
"//mojo/public/cpp/base:shared_typemap_traits", "//mojo/public/cpp/base:shared_typemap_traits",
] ]
} }
...@@ -30,10 +30,13 @@ enum KeystoreType { ...@@ -30,10 +30,13 @@ enum KeystoreType {
}; };
// Input parameters for RSASSA-PKCS1-v1_5. Parameters othan than modulus_length // Input parameters for RSASSA-PKCS1-v1_5. Parameters othan than modulus_length
// are currently not supported. // are currently not supported when used as inputs to GenerateKey().
[Stable, Extensible] [Stable, Extensible]
struct KeystorePKCS115Params { struct KeystorePKCS115Params {
uint32 modulus_length; [MinVersion=0]
uint32 modulus_length@0;
[MinVersion=1]
array<uint8>? public_exponent@1;
}; };
// Input parameters for ECDSA. |named_curve| uses WebCrypto nomenclature. // Input parameters for ECDSA. |named_curve| uses WebCrypto nomenclature.
...@@ -50,6 +53,13 @@ union KeystoreSigningAlgorithm { ...@@ -50,6 +53,13 @@ union KeystoreSigningAlgorithm {
KeystoreECDSAParams ecdsa; KeystoreECDSAParams ecdsa;
}; };
// The name of a WebCrypto signing algorithm.
[Stable, Extensible]
enum KeystoreSigningAlgorithmName {
kUnknown = 0,
kRsassaPkcs115 = 1,
kEcdsa = 2,
};
// Returned by methods that either return a string, or an error. // Returned by methods that either return a string, or an error.
[Stable, RenamedFrom="crosapi.mojom.ChallengeAttestationOnlyKeystoreResult"] [Stable, RenamedFrom="crosapi.mojom.ChallengeAttestationOnlyKeystoreResult"]
...@@ -90,6 +100,26 @@ union GetKeyStoresResult { ...@@ -90,6 +100,26 @@ union GetKeyStoresResult {
array<KeystoreType> key_stores; array<KeystoreType> key_stores;
}; };
// Returned by GetPublicKey() on success.
[Stable]
struct GetPublicKeySuccessResult {
// The public key of the matching certificate.
array<uint8> public_key;
// Provides details about the signing algorithm.
KeystoreSigningAlgorithm algorithm_properties;
};
// Returned by GetPublicKey().
[Stable]
union GetPublicKeyResult {
// Implies failure.
string error_message;
// Implies success.
GetPublicKeySuccessResult success_result;
};
// This interface is implemented by ash-chrome. It provides lacros-chrome a // This interface is implemented by ash-chrome. It provides lacros-chrome a
// mechanism to modify and query the attestation-only and generate purpose // mechanism to modify and query the attestation-only and generate purpose
// keystores. // keystores.
...@@ -137,5 +167,14 @@ interface KeystoreService { ...@@ -137,5 +167,14 @@ interface KeystoreService {
[MinVersion=2] [MinVersion=2]
RemoveCertificate@5(KeystoreType keystore, array<uint8> certificate) => RemoveCertificate@5(KeystoreType keystore, array<uint8> certificate) =>
(string error); (string error);
// Checks whether |certificate| certifies a key that allows usage of the
// WebCrypto algorithm |algorithm_name|. If so, returns the key info and
// details about the signing algorithm. |certificate| must be a DER encoded
// X.509 certificate.
[MinVersion=3]
GetPublicKey@6(array<uint8> certificate,
KeystoreSigningAlgorithmName algorithm_name) =>
(GetPublicKeyResult result);
}; };
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