diff options
49 files changed, 2219 insertions, 121 deletions
@@ -87,7 +87,7 @@ GEN_SERVICE_SOURCE = GEN_SERVICE + " --nos-client-cpp_out=source:$(genDir) " GEN_SERVICE_HEADER = GEN_SERVICE + " --nos-client-cpp_out=header:$(genDir) " GEN_SERVICE_MOCK = GEN_SERVICE + " --nos-client-cpp_out=mock:$(genDir) " -// A special target to be statically linkeed into recovery which is a system +// A special target to be statically linked into recovery which is a system // (not vendor) component. cc_library_static { name: "libnos_for_recovery", @@ -100,7 +100,6 @@ cc_library_static { export_include_dirs: [ "nugget/include", "libnos/include", - "libnos_datagram/include", "libnos_transport/include", ], srcs: [ @@ -113,7 +112,7 @@ cc_library_static { ], } -// A special target to be statically linkeed into fastboot hal. +// A special target to be statically linked into fastboot hal. cc_library_static { name: "libnos_for_fastboot", recovery: true, @@ -126,7 +125,6 @@ cc_library_static { export_include_dirs: [ "nugget/include", "libnos/include", - "libnos_datagram/include", "libnos_transport/include", ], srcs: [ @@ -139,7 +137,7 @@ cc_library_static { ], } -// A special target to be statically linkeed into recovery which is a system +// A special target to be statically linked into recovery which is a system // (not vendor) component. cc_library_static { name: "libnos_citadel_for_recovery", @@ -150,14 +148,17 @@ cc_library_static { ], srcs: [ ":libnos_client", - "libnos_datagram/citadel.c", + "libnos_datagram/citadel.cpp", ], static_libs: [ "libnos_for_recovery", ], + shared_libs: [ + "libbase", + ], } -// A special target to be statically linkeed into fastboot hal. +// A special target to be statically linked into fastboot hal. cc_library_static { name: "libnos_citadel_for_fastboot", recovery: true, @@ -168,11 +169,14 @@ cc_library_static { ], srcs: [ ":libnos_client", - "libnos_datagram/citadel.c", + "libnos_datagram/citadel.cpp", ], static_libs: [ "libnos_for_fastboot", ], + shared_libs: [ + "libbase", + ], } // Language and vendor related defaults @@ -184,6 +188,7 @@ cc_defaults { "-Wall", "-Wextra", "-Werror", + "-Wno-gcc-compat", "-Wno-gnu-zero-variadic-macro-arguments", "-Wno-zero-length-array", ], @@ -215,5 +220,7 @@ cc_library { "libnos_client_defaults", "nos_cc_defaults", ], - shared_libs: ["libnos_datagram_citadel"], + shared_libs: [ + "libnos_datagram_citadel", + ], } @@ -6,10 +6,25 @@ cc_library( "nugget/include/application.h", "nugget/include/avb.h", "nugget/include/citadel_events.h", + "nugget/include/feature_map.h", "nugget/include/flash_layout.h", "nugget/include/keymaster.h", + "nugget/include/nos/device.h", "nugget/include/signed_header.h", ], + deps = [ + "nos_headers_hals", + ], + strip_include_prefix = "nugget/include/", + visibility = ["//visibility:public"], +) + +cc_library( + name = "nos_headers_hals", + hdrs = [ + "nugget/include/hals/common.h", + "nugget/include/hals/weaver.h", + ], strip_include_prefix = "nugget/include/", visibility = ["//visibility:public"], ) @@ -2,6 +2,6 @@ # or people with more than 10 commits last year. # Please update this list if you find better owner candidates. wfrichar@google.com +tommychiu@google.com +zhakevin@google.com kroot@google.com -dybertwang@google.com -byi@google.com diff --git a/libnos/Android.bp b/libnos/Android.bp index f68df27..2fdb924 100644 --- a/libnos/Android.bp +++ b/libnos/Android.bp @@ -30,9 +30,17 @@ cc_library { ], defaults: ["nos_cc_host_supported_defaults"], header_libs: ["nos_headers"], - shared_libs: ["libnos_datagram"], export_include_dirs: ["include"], - export_shared_lib_headers: ["libnos_datagram"], +} + +cc_library { + name: "libnos_feature", + srcs: [ + "feature.cpp", + ], + defaults: ["nos_cc_host_supported_defaults"], + header_libs: ["nos_headers"], + export_include_dirs: ["include"], } // This part of libnos must be linked with the target's implementation of diff --git a/libnos/BUILD b/libnos/BUILD index a03ec8f..627b721 100644 --- a/libnos/BUILD +++ b/libnos/BUILD @@ -3,12 +3,14 @@ cc_library( srcs = [ "NuggetClient.cpp", "debug.cpp", + "feature.cpp", ], hdrs = [ "include/nos/AppClient.h", "include/nos/NuggetClient.h", "include/nos/NuggetClientInterface.h", "include/nos/debug.h", + "include/nos/feature.h", ], includes = [ "include", @@ -16,7 +18,6 @@ cc_library( visibility = ["//visibility:public"], deps = [ "//host/generic:nos_headers", - "//host/generic/libnos_datagram", "//host/generic/libnos_transport", ], ) diff --git a/libnos/NuggetClient.cpp b/libnos/NuggetClient.cpp index c361463..d27e19b 100644 --- a/libnos/NuggetClient.cpp +++ b/libnos/NuggetClient.cpp @@ -84,6 +84,15 @@ uint32_t NuggetClient::CallApp(uint32_t appId, uint16_t arg, return status_code; } +uint32_t NuggetClient::CallApp(uint32_t appId, uint16_t arg, + const void* req_ptr, uint32_t req_len, + void* resp_ptr, uint32_t* resp_len) { + if (!open_) return APP_ERROR_IO; + + return nos_call_application(&device_, appId, arg, (const uint8_t*)req_ptr, + req_len, (uint8_t*)resp_ptr, resp_len); +} + uint32_t NuggetClient::Reset() const { if (!open_) diff --git a/libnos/debug.cpp b/libnos/debug.cpp index 0398d54..cc8a2c2 100644 --- a/libnos/debug.cpp +++ b/libnos/debug.cpp @@ -35,6 +35,7 @@ std::string StatusCodeString(uint32_t code) { ErrorString_helper(APP_ERROR_CHECKSUM) ErrorString_helper(APP_ERROR_BUSY) ErrorString_helper(APP_ERROR_TIMEOUT) + ErrorString_helper(APP_ERROR_NOT_READY) default: if (code >= APP_LINE_NUMBER_BASE && code < MAX_APP_STATUS) { return "APP_LINE_NUMBER " + std::to_string(code - APP_LINE_NUMBER_BASE); diff --git a/libnos/feature.cpp b/libnos/feature.cpp new file mode 100644 index 0000000..6651319 --- /dev/null +++ b/libnos/feature.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2022 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 <nos/feature.h> + +namespace nos { + +bool has_feature(NuggetClientInterface& nug, enum feature_support_app_id app_id, + uint32_t feature) { + uint32_t feature_id = (app_id << TA_OFFSET) | (feature & FEATURE_MASK); + + std::vector<uint8_t> req(sizeof(feature_id)); + memcpy(req.data(), &feature_id, sizeof(feature_id)); + + std::vector<uint8_t> resp; + resp.reserve(sizeof(uint8_t)); + + uint32_t rv = + nug.CallApp(APP_ID_NUGGET, NUGGET_PARAM_GET_FEATURE_SUPPORT, req, &resp); + if (rv != APP_SUCCESS) { + return false; + } + + if (resp.size() < 1) { + return false; // I guess? + } + + return !!resp[0]; +} + +} // namespace nos diff --git a/libnos/generator/Android.bp b/libnos/generator/Android.bp index a7cc964..9e5a688 100644 --- a/libnos/generator/Android.bp +++ b/libnos/generator/Android.bp @@ -30,6 +30,9 @@ cc_binary_host { "nos_proto_defaults", "nos_cc_defaults", ], - static_libs: ["libnosprotos"], + static_libs: [ + "libabsl_host", + "libnosprotos", + ], shared_libs: ["libprotoc"], } diff --git a/libnos/generator/BUILD b/libnos/generator/BUILD index fc8bc33..1f9ed42 100644 --- a/libnos/generator/BUILD +++ b/libnos/generator/BUILD @@ -3,12 +3,10 @@ cc_binary( srcs = [ "main.cpp", ], - copts = [ - "-std=c++11", - ], visibility = ["//visibility:public"], deps = [ "//host/generic/nugget/proto:nugget_protobuf_options_cc_proto", "@com_google_protobuf//:protoc_lib", + "@com_google_absl//absl/strings", ], ) diff --git a/libnos/generator/main.cpp b/libnos/generator/main.cpp index 04dfa89..51acfa2 100644 --- a/libnos/generator/main.cpp +++ b/libnos/generator/main.cpp @@ -24,17 +24,16 @@ #include <google/protobuf/compiler/code_generator.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/stubs/strutil.h> +#include "absl/strings/strip.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_join.h" +#include "absl/strings/str_split.h" #include "nugget/protobuf/options.pb.h" using ::google::protobuf::FileDescriptor; -using ::google::protobuf::JoinStrings; using ::google::protobuf::MethodDescriptor; using ::google::protobuf::ServiceDescriptor; -using ::google::protobuf::Split; -using ::google::protobuf::SplitStringUsing; -using ::google::protobuf::StripSuffixString; using ::google::protobuf::compiler::CodeGenerator; using ::google::protobuf::compiler::OutputDirectory; using ::google::protobuf::io::Printer; @@ -61,8 +60,8 @@ std::string validateServiceOptions(const ServiceDescriptor& service) { template <typename Descriptor> std::vector<std::string> Packages(const Descriptor& descriptor) { - std::vector<std::string> namespaces; - SplitStringUsing(descriptor.full_name(), ".", &namespaces); + std::vector<std::string> namespaces = + absl::StrSplit(descriptor.full_name(), '.'); namespaces.pop_back(); // just take the package return namespaces; } @@ -73,23 +72,21 @@ std::string FullyQualifiedIdentifier(const Descriptor& descriptor) { if (namespaces.empty()) { return "::" + descriptor.name(); } else { - std::string namespace_path; - JoinStrings(namespaces, "::", &namespace_path); - return "::" + namespace_path + "::" + descriptor.name(); + return absl::StrCat("::", absl::StrJoin(namespaces, "::"), "::", descriptor.name()); } } template <typename Descriptor> std::string FullyQualifiedHeader(const Descriptor& descriptor) { - const auto packages = Packages(descriptor); - const auto file = Split(descriptor.file()->name(), "/").back(); - const auto header = StripSuffixString(file, ".proto") + ".pb.h"; + const std::vector<std::string> packages = Packages(descriptor); + const std::vector<std::string_view> path_components = + absl::StrSplit(descriptor.file()->name(), '/'); + const std::string file(path_components.back()); + const std::string header = absl::StrCat(absl::StripSuffix(file, ".proto"), ".pb.h"); if (packages.empty()) { return header; } else { - std::string package_path; - JoinStrings(packages, "/", &package_path); - return package_path + "/" + header; + return absl::StrCat(absl::StrJoin(packages, "/"), "/", header); } } @@ -240,7 +237,7 @@ void GenerateClientSource(Printer& printer, const ServiceDescriptor& service) { methodVars.insert(vars.begin(), vars.end()); printer.Print(methodVars, R"( uint32_t $class$::$method_name$(const $method_input_type$& request, $method_output_type$* response) { - const size_t request_size = request.ByteSize(); + const size_t request_size = request.ByteSizeLong(); if (request_size > $max_request_size$) { return APP_ERROR_TOO_MUCH; } @@ -270,6 +267,8 @@ uint32_t $class$::$method_name$(const $method_input_type$& request, $method_outp class CppNuggetServiceClientGenerator : public CodeGenerator { public: CppNuggetServiceClientGenerator() = default; + CppNuggetServiceClientGenerator(const CppNuggetServiceClientGenerator&) = delete; + CppNuggetServiceClientGenerator& operator=(const CppNuggetServiceClientGenerator&) = delete; ~CppNuggetServiceClientGenerator() override = default; bool Generate(const FileDescriptor* file, @@ -307,9 +306,6 @@ public: return true; } - -private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CppNuggetServiceClientGenerator); }; } // namespace diff --git a/libnos/generator/test/Android.bp b/libnos/generator/test/Android.bp index 30287aa..e0c4d32 100644 --- a/libnos/generator/test/Android.bp +++ b/libnos/generator/test/Android.bp @@ -26,7 +26,11 @@ package { genrule { name: "nos_generator_test_service_genc++", out: ["Hello.client.cpp"], - srcs: ["nos/generator/test/test.proto"], + srcs: [ + "nos/generator/test/test.proto", + ":nugget_options_proto", + ":libprotobuf-internal-protos", + ], tools: ["aprotoc", "protoc-gen-nos-client-cpp"], cmd: GEN_SERVICE_SOURCE + "-Iexternal/nos/host/generic/libnos/generator/test", } @@ -34,7 +38,11 @@ genrule { genrule { name: "nos_generator_test_service_genc++_headers", out: ["Hello.client.h"], - srcs: ["nos/generator/test/test.proto"], + srcs: [ + "nos/generator/test/test.proto", + ":nugget_options_proto", + ":libprotobuf-internal-protos", + ], tools: ["aprotoc", "protoc-gen-nos-client-cpp"], cmd: GEN_SERVICE_HEADER + "-Iexternal/nos/host/generic/libnos/generator/test", } @@ -42,7 +50,11 @@ genrule { genrule { name: "nos_generator_test_service_genc++_mock", out: ["MockHello.client.h"], - srcs: ["nos/generator/test/test.proto"], + srcs: [ + "nos/generator/test/test.proto", + ":nugget_options_proto", + ":libprotobuf-internal-protos", + ], tools: ["aprotoc", "protoc-gen-nos-client-cpp"], cmd: GEN_SERVICE_MOCK + "-Iexternal/nos/host/generic/libnos/generator/test", } diff --git a/libnos/generator/test/test.cpp b/libnos/generator/test/test.cpp index 4542c88..f6a4835 100644 --- a/libnos/generator/test/test.cpp +++ b/libnos/generator/test/test.cpp @@ -79,7 +79,7 @@ TEST(GeneratedServiceClientTest, DataSuccessfullyExchanged) { GreetResponse response; response.set_greeting("Hello, Tester age 78"); - std::vector<uint8_t> responseBytes(response.ByteSize()); + std::vector<uint8_t> responseBytes(response.ByteSizeLong()); ASSERT_TRUE(response.SerializeToArray(responseBytes.data(), responseBytes.size())); EXPECT_CALL(client, CallApp(_, _, DecodesToProtoMessage(request), _)) @@ -114,7 +114,7 @@ TEST(GeneratedServiceClientTest, AppErrorsPropagatedWithoutResponseDecode) { GreetResponse response; response.set_greeting("Ignore me"); - std::vector<uint8_t> responseBytes(response.ByteSize()); + std::vector<uint8_t> responseBytes(response.ByteSizeLong()); ASSERT_TRUE(response.SerializeToArray(responseBytes.data(), responseBytes.size())); EXPECT_CALL(client, CallApp(_, _, _, _)) diff --git a/libnos/include/nos/AppClient.h b/libnos/include/nos/AppClient.h index 0a35d82..1299100 100644 --- a/libnos/include/nos/AppClient.h +++ b/libnos/include/nos/AppClient.h @@ -51,6 +51,21 @@ public: return _client.CallApp(_appId, arg, request, response); } + /** + * Call the app. + * + * @param arg Argument to pass to the app. + * @param req_ptr Data to send to the app. + * @param req_len Number of bytes to send to the app. + * @param resp_ptr Buffer to receive data from the app. + * @param resp_len In: Max number of bytes to receive from the app. + * Out: Actual number of bytes received from the app. + */ + uint32_t Call(uint16_t arg, const void* req_ptr, uint32_t req_len, + void* resp_ptr, uint32_t* resp_len) { + return _client.CallApp(_appId, arg, req_ptr, req_len, resp_ptr, + resp_len); + } private: NuggetClientInterface& _client; diff --git a/libnos/include/nos/NuggetClient.h b/libnos/include/nos/NuggetClient.h index 9484bd8..c4dc1cb 100644 --- a/libnos/include/nos/NuggetClient.h +++ b/libnos/include/nos/NuggetClient.h @@ -73,6 +73,22 @@ public: std::vector<uint8_t>* response) override; /** + * Call into an app running on Nugget. + * + * @param app_id The ID of the app to call. + * @param arg Argument to pass to the app. + * @param req_ptr Data to send to the app. + * @param req_len Number of bytes to send to the app. + * @param resp_ptr Buffer to receive data from the app. + * @param resp_len In: Max number of bytes to receive from the app. + * Out: Actual number of bytes received from the app. + * @return Status code from the app. + */ + uint32_t CallApp(uint32_t appId, uint16_t arg, const void* req_ptr, + uint32_t req_len, void* resp_ptr, + uint32_t* resp_len) override; + + /** * Reset the device. Use with caution; context may be lost. */ uint32_t Reset() const override; diff --git a/libnos/include/nos/NuggetClientInterface.h b/libnos/include/nos/NuggetClientInterface.h index 8d78185..e14c794 100644 --- a/libnos/include/nos/NuggetClientInterface.h +++ b/libnos/include/nos/NuggetClientInterface.h @@ -58,6 +58,23 @@ public: virtual uint32_t CallApp(uint32_t appId, uint16_t arg, const std::vector<uint8_t>& request, std::vector<uint8_t>* response) = 0; + + /** + * Call into an app running on Nugget. + * + * @param app_id The ID of the app to call. + * @param arg Argument to pass to the app. + * @param req_ptr Data to send to the app. + * @param req_len Number of bytes to send to the app. + * @param resp_ptr Buffer to receive data from the app. + * @param resp_len In: Max number of bytes to receive from the app. + * Out: Actual number of bytes received from the app. + * @return Status code from the app. + */ + virtual uint32_t CallApp(uint32_t appId, uint16_t arg, const void* req_ptr, + uint32_t req_len, void* resp_ptr, + uint32_t* resp_len) = 0; + /** * Reset the device. Use with caution; context may be lost. */ diff --git a/libnos/include/nos/feature.h b/libnos/include/nos/feature.h new file mode 100644 index 0000000..0ed6d0a --- /dev/null +++ b/libnos/include/nos/feature.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2022 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. + */ + +#pragma once + +#include <app_nugget.h> +#include <application.h> +#include <feature_map.h> +#include <nos/NuggetClientInterface.h> + +namespace nos { + +bool has_feature(NuggetClientInterface& nug, enum feature_support_app_id app_id, + uint32_t feature); + +} // namespace nos diff --git a/libnos/test/include/nos/MockNuggetClient.h b/libnos/test/include/nos/MockNuggetClient.h index 48814c9..19e7f00 100644 --- a/libnos/test/include/nos/MockNuggetClient.h +++ b/libnos/test/include/nos/MockNuggetClient.h @@ -33,6 +33,9 @@ struct MockNuggetClient : public NuggetClientInterface { MOCK_METHOD4(CallApp, uint32_t(uint32_t, uint16_t, const std::vector<uint8_t>&, std::vector<uint8_t>*)); + MOCK_METHOD6(CallApp, uint32_t(uint32_t, uint16_t, + const void*, uint32_t, + void*, uint32_t*)); MOCK_CONST_METHOD0(Reset, uint32_t()); }; diff --git a/libnos_datagram/Android.bp b/libnos_datagram/Android.bp index 0176e00..f854bd8 100644 --- a/libnos_datagram/Android.bp +++ b/libnos_datagram/Android.bp @@ -36,15 +36,17 @@ license { cc_library { name: "libnos_datagram", defaults: ["nos_cc_host_supported_defaults"], - export_include_dirs: ["include"], } cc_library { name: "libnos_datagram_citadel", - srcs: ["citadel.c"], + srcs: ["citadel.cpp"], + header_libs: ["nos_headers"], defaults: ["nos_cc_defaults"], shared_libs: [ + "libbase", "liblog", + "libnos_transport", "libnos_datagram", ], } diff --git a/libnos_datagram/BUILD b/libnos_datagram/BUILD deleted file mode 100644 index e6f029c..0000000 --- a/libnos_datagram/BUILD +++ /dev/null @@ -1,10 +0,0 @@ -cc_library( - name = "libnos_datagram", - hdrs = [ - "include/nos/device.h", - ], - includes = [ - "./include", - ], - visibility = ["//visibility:public"], -) diff --git a/libnos_datagram/citadel.c b/libnos_datagram/citadel.cpp index 7d1d893..199635c 100644 --- a/libnos_datagram/citadel.c +++ b/libnos_datagram/citadel.cpp @@ -35,6 +35,9 @@ #include <sys/types.h> #include <unistd.h> +#include <android-base/properties.h> +#include <application.h> + /*****************************************************************************/ /* Ideally, this should be in <linux/citadel.h> */ #define CITADEL_IOC_MAGIC 'c' @@ -43,14 +46,33 @@ struct citadel_ioc_tpm_datagram { __u32 len; __u32 command; }; + +/* GSA nos call request struct */ +struct gsa_ioc_nos_call_req { + __u8 app_id; + __u8 reserved; + __u16 params; + __u32 arg_len; + __u64 buf; + __u32 reply_len; + __u32 call_status; +}; + #define CITADEL_IOC_TPM_DATAGRAM _IOW(CITADEL_IOC_MAGIC, 1, \ struct citadel_ioc_tpm_datagram) #define CITADEL_IOC_RESET _IO(CITADEL_IOC_MAGIC, 2) +#define GSC_IOC_GSA_NOS_CALL _IOW(CITADEL_IOC_MAGIC, 3, \ + struct gsa_ioc_nos_call_req) /*****************************************************************************/ #define DEV_CITADEL "/dev/citadel0" #define DEV_DAUNTLESS "/dev/gsc0" +/* Allocate 4KB buffer for GSA mbox data transmission */ +#define MAX_GSA_NOS_CALL_TRANSFER 4096 +static uint8_t gsa_nos_call_buf[MAX_GSA_NOS_CALL_TRANSFER]; +static pthread_mutex_t nos_call_buf_mutex = PTHREAD_MUTEX_INITIALIZER; + static pthread_mutex_t in_buf_mutex = PTHREAD_MUTEX_INITIALIZER; static uint8_t in_buf[MAX_DEVICE_TRANSFER]; static int read_datagram(void *ctx, uint32_t command, uint8_t *buf, uint32_t len) { @@ -206,6 +228,112 @@ static void close_device(void *ctx) { free(ctx); } +/* Detect if GSA kernel support nos_call interface + * Returns true on success or false on failure. + */ +static bool detect_gsa_nos_call_interface(int fd) { + int ret; + errno = 0; + + if (fd < 0) { + ALOGE("invalid device handle (%d)", fd); + return false; + } + + /* Send app_id = 0 and params = 0 to detect GSA IOCTL interface */ + struct gsa_ioc_nos_call_req gsa_nos_call_req = { + .app_id = 0, + .reserved = 0, + .params = 0, + .arg_len = 0, + .buf = (unsigned long)gsa_nos_call_buf, + .reply_len = 0, + .call_status = 0, + }; + + ret = ioctl(fd, GSC_IOC_GSA_NOS_CALL, &gsa_nos_call_req); + if (ret < 0) { + ALOGE("can't send GSA mbox command: %s", strerror(errno)); + } + + /* GSA kernel is not support GSA_NOS_CALL if return EINVAL or ENOTTY */ + if (!errno) { + return true; + } else { + return false; + } +} + +static int one_pass_call(void *ctx, uint8_t app_id, uint16_t params, + const uint8_t *args, uint32_t arg_len, + uint8_t *reply, uint32_t *reply_len, + uint32_t *status_code) { + *status_code = APP_SUCCESS; + int ret; + int fd; + + struct gsa_ioc_nos_call_req gsa_nos_call_req = { + .app_id = app_id, + .reserved = 0, + .params = params, + .arg_len = arg_len, + .buf = (unsigned long)gsa_nos_call_buf, + .reply_len = *reply_len, + .call_status = *status_code, + }; + + ALOGD("Calling App 0x%02x with params 0x%04x", app_id, params); + + if (!ctx || (arg_len && !args) || + (reply_len && *reply_len && !reply) || + (arg_len > MAX_GSA_NOS_CALL_TRANSFER) || + (reply_len && *reply_len > MAX_GSA_NOS_CALL_TRANSFER) || + !status_code) { + ALOGE("Invalid args to %s()", __func__); + return -EINVAL; + } + + fd = *(int *)ctx; + if (fd < 0) { + ALOGE("%s: invalid device\n", __func__); + return -ENODEV; + } + + /* Lock the out buffer while it is used for this transaction */ + if (pthread_mutex_lock(&nos_call_buf_mutex) != 0) { + ALOGE("%s: failed to lock nos_call_buf_mutex: %s", __func__, strerror(errno)); + return -errno; + } + + if (arg_len) { + memcpy(gsa_nos_call_buf, args, arg_len); + } + + ret = ioctl(fd, GSC_IOC_GSA_NOS_CALL, &gsa_nos_call_req); + if (ret < 0) { + ALOGE("can't send GSA mbox command: %s", strerror(errno)); + goto exit; + } + + *status_code = gsa_nos_call_req.call_status; + if (reply_len != NULL) { + *reply_len = gsa_nos_call_req.reply_len; + if (*reply_len) { + memcpy(reply, gsa_nos_call_buf, *reply_len); + } + } + +exit: + if (pthread_mutex_unlock(&nos_call_buf_mutex) != 0) { + ALOGE("%s: failed to unlock nos_call_buf_mutex: %s", __func__, + strerror(errno)); + return -errno; + } + + ALOGD("App 0x%02x returning 0x%x", app_id, *status_code); + return ret; +} + static const char *default_device(void) { struct stat statbuf; int rv; @@ -256,5 +384,7 @@ int nos_device_open(const char *device_name, struct nos_device *dev) { dev->ops.wait_for_interrupt = wait_for_interrupt; dev->ops.reset = reset; dev->ops.close = close_device; + dev->ops.one_pass_call = one_pass_call; + dev->use_one_pass_call = detect_gsa_nos_call_interface(fd); return 0; } diff --git a/libnos_transport/Android.bp b/libnos_transport/Android.bp index 1dd8992..ee519c5 100644 --- a/libnos_transport/Android.bp +++ b/libnos_transport/Android.bp @@ -47,7 +47,6 @@ cc_library { shared_libs: [ "libbase", "liblog", - "libnos_datagram", ], export_include_dirs: ["include"], } diff --git a/libnos_transport/BUILD b/libnos_transport/BUILD index 9fc9017..0d70a0d 100644 --- a/libnos_transport/BUILD +++ b/libnos_transport/BUILD @@ -14,7 +14,6 @@ cc_library( visibility = ["//visibility:public"], deps = [ "//host/generic:nos_headers", - "//host/generic/libnos_datagram", ], ) diff --git a/libnos_transport/test/test.cpp b/libnos_transport/test/test.cpp index 1090de4..c995c60 100644 --- a/libnos_transport/test/test.cpp +++ b/libnos_transport/test/test.cpp @@ -201,7 +201,7 @@ ACTION(ReadStatusV42_Working) { status->length = STATUS_MAX_LENGTH; status->version = 42; status->flags = STATUS_FLAG_WORKING; - status->crc = 0xaec0; + status->crc = 0xf781; status->reply_crc = 0; } diff --git a/libnos_transport/transport.c b/libnos_transport/transport.c index 855b884..b3a3a40 100644 --- a/libnos_transport/transport.c +++ b/libnos_transport/transport.c @@ -191,7 +191,7 @@ static int get_status(const struct transport_context *ctx, /* Check the CRC, if it fails we will retry */ if (out->crc != our_crc) { - NLOGW("App %d status CRC mismatch: theirs=%04x ours=%04x", + NLOGW("App 0x%02x status CRC mismatch: theirs=%04x ours=%04x", ctx->app_id, out->crc, our_crc); continue; } @@ -227,8 +227,9 @@ static uint32_t make_ready(const struct transport_context *ctx) { NLOGE("Failed to inspect app %d", ctx->app_id); return APP_ERROR_IO; } - NLOGD("App %d inspection status=0x%08x reply_len=%d protocol=%d flags=0x%04x", - ctx->app_id, status.status, status.reply_len, status.version, status.flags); + NLOGD("App 0x%02x check status=0x%08x reply_len=%d protocol=%d flags=0x%04x", + ctx->app_id, status.status, status.reply_len, status.version, + status.flags); /* If it's already idle then we're ready to proceed */ if (status.status == APP_STATUS_IDLE) { @@ -236,7 +237,7 @@ static uint32_t make_ready(const struct transport_context *ctx) { && (status.flags & STATUS_FLAG_WORKING)) { /* The app is still working when we don't expect it to be. We won't be * able to clear the state so might need to force a reset to recover. */ - NLOGE("App %d is still working", ctx->app_id); + NLOGE("App 0x%02x is still working", ctx->app_id); return APP_ERROR_BUSY; } return APP_SUCCESS; @@ -259,7 +260,7 @@ static uint32_t make_ready(const struct transport_context *ctx) { /* It's ignoring us and is still not ready, so it's broken */ if (status.status != APP_STATUS_IDLE) { - NLOGE("App %d is not responding", ctx->app_id); + NLOGE("App 0x%02x is not responding", ctx->app_id); return APP_ERROR_IO; } @@ -369,17 +370,20 @@ static uint32_t poll_until_done(const struct transport_context *ctx, poll_count++; /* Log at higher priority every 16 polls */ if ((poll_count & (16 - 1)) == 0) { - NLOGD("App %d poll=%d status=0x%08x reply_len=%d flags=0x%04x", - ctx->app_id, poll_count, status->status, status->reply_len, status->flags); + NLOGD("App 0x%02x poll=%d status=0x%08x reply_len=%d flags=0x%04x", + ctx->app_id, poll_count, status->status, status->reply_len, + status->flags); } else { - NLOGV("App %d poll=%d status=0x%08x reply_len=%d flags=0x%04x", - ctx->app_id, poll_count, status->status, status->reply_len, status->flags); + NLOGV("App 0x%02x poll=%d status=0x%08x reply_len=%d flags=0x%04x", + ctx->app_id, poll_count, status->status, status->reply_len, + status->flags); } /* Check whether the app is done */ if (status->status & APP_STATUS_DONE) { - NLOGD("App %d polled=%d status=0x%08x reply_len=%d flags=0x%04x", - ctx->app_id, poll_count, status->status, status->reply_len, status->flags); + NLOGD("App 0x%02x polled=%d status=0x%08x reply_len=%d flags=0x%04x", + ctx->app_id, poll_count, status->status, status->reply_len, + status->flags); return APP_STATUS_CODE(status->status); } @@ -387,7 +391,7 @@ static uint32_t poll_until_done(const struct transport_context *ctx, if (status->version != TRANSPORT_V0 && !(status->flags & STATUS_FLAG_WORKING)) { /* The slave has stopped working without being done so it's misbehaving */ - NLOGE("App %d just stopped working", ctx->app_id); + NLOGE("App 0x%02x just stopped working", ctx->app_id); return APP_ERROR_INTERNAL; } if (clock_gettime(CLOCK_MONOTONIC, &now) != 0) { @@ -396,8 +400,8 @@ static uint32_t poll_until_done(const struct transport_context *ctx, } } while (timespec_before(&now, &abort_at)); - NLOGE("App %d not done after polling %d times in %d seconds", - ctx->app_id, poll_count, POLL_LIMIT_SECONDS); + NLOGE("App 0x%02x not done after polling %d times in %d seconds", ctx->app_id, + poll_count, POLL_LIMIT_SECONDS); return APP_ERROR_TIMEOUT; } @@ -440,7 +444,8 @@ static uint32_t receive_reply(const struct transport_context *ctx, if (status->version == TRANSPORT_V0) return APP_SUCCESS; if (crc == status->reply_crc) return APP_SUCCESS; - NLOGW("App %d reply CRC mismatch: theirs=%04x ours=%04x", ctx->app_id, status->reply_crc, crc); + NLOGW("App 0x%02x reply CRC mismatch: theirs=%04x ours=%04x", ctx->app_id, + status->reply_crc, crc); } NLOGE("Unable to get valid checksum on app %d reply data", ctx->app_id); @@ -456,6 +461,7 @@ uint32_t nos_call_application(const struct nos_device *dev, uint8_t *reply, uint32_t *reply_len) { uint32_t res; + uint32_t status_code; const struct transport_context ctx = { .dev = dev, .app_id = app_id, @@ -472,10 +478,28 @@ uint32_t nos_call_application(const struct nos_device *dev, return APP_ERROR_IO; } - NLOGD("Calling App %d with params 0x%04x", app_id, params); +#ifdef ANDROID + if (!dev) { + NLOGE("Invalid args to %s()", __func__); + return APP_ERROR_IO; + } + + // Call GSA nos_call IOCTL interface if needed + if (dev->use_one_pass_call) { + int err = dev->ops.one_pass_call(dev->ctx, app_id, params, args, arg_len, + reply, reply_len, &status_code); + if (err < 0) { + NLOGE("one_pass_call failed: %s", strerror(-err)); + status_code = APP_ERROR_IO; + } + + return status_code; + } +#endif + + NLOGD("Calling App 0x%02x with params 0x%04x", app_id, params); struct transport_status status; - uint32_t status_code; int retries = CRC_RETRY_COUNT; while (retries--) { /* Wake up and wait for Citadel to be ready */ @@ -493,16 +517,16 @@ uint32_t nos_call_application(const struct nos_device *dev, * or more than it can accept but this should not happen. Give to the chip a * little bit of time and retry calling again. */ if (status_code == APP_ERROR_TOO_MUCH) { - NLOGD("App %d returning 0x%x, give a retry(%d/%d)", - app_id, status_code, retries, CRC_RETRY_COUNT); + NLOGD("App 0x%02x returning 0x%x, give a retry(%d/%d)", app_id, + status_code, retries, CRC_RETRY_COUNT); usleep(RETRY_WAIT_TIME_US); continue; } if (status_code != APP_ERROR_CHECKSUM) break; - NLOGW("App %d request checksum error", app_id); + NLOGW("App 0x%02x request checksum error", app_id); } if (status_code == APP_ERROR_CHECKSUM) { - NLOGE("App %d request checksum failed too many times", app_id); + NLOGE("App 0x%02x request checksum failed too many times", app_id); status_code = APP_ERROR_IO; } @@ -519,6 +543,6 @@ uint32_t nos_call_application(const struct nos_device *dev, * next call will try again. */ (void)clear_status(&ctx); - NLOGD("App %d returning 0x%x", app_id, status_code); + NLOGD("App 0x%02x returning 0x%x", app_id, status_code); return status_code; } diff --git a/nugget/include/app_nugget.h b/nugget/include/app_nugget.h index cd8bf33..49ca2de 100644 --- a/nugget/include/app_nugget.h +++ b/nugget/include/app_nugget.h @@ -29,8 +29,9 @@ extern "C" { /* App-specific errors (across all commands) */ enum { - NUGGET_ERROR_LOCKED = APP_SPECIFIC_ERROR, + NUGGET_ERROR_LOCKED = APP_SPECIFIC_ERROR + 0, NUGGET_ERROR_RETRY, + NUGGET_ERROR_VERIFY, }; /****************************************************************************/ @@ -299,15 +300,15 @@ struct nugget_app_board_id { uint32_t inv; /* must equal ~type when setting */ } __packed; -#define NUGGET_PARAM_GET_EVENT_RECORD 0x0010 +#define NUGGET_PARAM_GET_EVENT_REPORT 0x0010 /* - * This retrieves one pending event_record (defined in citadel_events.h). + * This retrieves one pending event_report (defined in citadel_events.h). * If none are pending, it returns nothing. * * @param args <none> * @param arg_len 0 - * @param reply struct event_record - * @param reply_len sizeof struct event_record OR 0 + * @param reply struct event_report + * @param reply_len sizeof struct event_report OR 0 */ #define NUGGET_PARAM_AP_IS_REBOOTING 0x0011 @@ -461,10 +462,27 @@ struct gsa_gsc_psk_persist_storage { /* * GSA key provision command * - * @param args gsa unique public key + * We use the same command id to support multiple GSA-GSC PSK + * provision handshaking. List possible args and reply usage by + * each case. + * + * Non-secure PSK provision case: + * @param args GSA-GSC PSK (plaintext) * @param arg_len 32 - * @param reply gsc public key + sha256(pre-shared key) - * @param reply_len 64 + 32 + * @param reply GSA-GSC PSK (plaintext) + * @param reply_len 32 + * + * Ephemeral ec key handshaking case: + * @param args GSA public key + * @param arg_len 64 + * @param reply GSC public key + signature + * @param reply_len 64 + 64 + * + * Secure PSK provision case: + * @param args encrypted GSA-GSC PSK (nonce + PSK + tag) + * @param arg_len 12 + 32 + 16 + * @param reply <none> + * @param reply_len 0 */ /** @@ -551,7 +569,8 @@ struct secure_channel_retry_count_persist_storage { * * @param args GSA EC public_key + AES_GCM256("MSGA") + AES_GSC_TAG * @param arg_len 64 + 4 + 16 bytes = 84 - * @param reply GSC EC public_key + AES_GCM256("MSGB") + AES_GSC_TAG OR 1 byte error state + * @param reply GSC EC public_key + AES_GCM256("MSGB") + AES_GSC_TAG + * OR 1 byte error state * @param reply_len 64 + 4 + 16 bytes = 84 OR 1 */ @@ -559,10 +578,55 @@ struct secure_channel_retry_count_persist_storage { /* * Secure transport report noise handshake state command * - * @param args GSA noise handshake state - * @param arg_len 1 + * @param args GSA noise handshake state + report suez state + * @param arg_len 2 * @param reply <none> - * @param reply_len 0 + * @param reply_len 1 + */ + +#define NUGGET_PARAM_GET_BIG_EVENT_REPORT 0x001b +/* + * This retrieves one pending big_event_report (defined in citadel_events.h). + * If none are pending, it returns nothing. + * + * @param args <none> + * @param arg_len 0 + * @param reply struct big_event_report + * @param reply_len sizeof struct big_event_report OR 0 + */ + +#define NUGGET_PARAM_GET_FEATURE_SUPPORT 0x001c +/* + * Get the specific feature supportness from the specific TA. + * + * @param args feature_id + * @param arg_len 4 byte + * @param reply 0 or 1 + * @param reply_len 1 byte + * + * @errors APP_ERROR_BOGUS_ARGS + */ + +#define NUGGET_PARAM_SECURE_TRANSPORT_USECASE_HANDSHAKE 0x001d +/* + * Secure transport usecase handshake command + * + * @param args AES_GCM256(struct secure_transport_usecase) + + * AES_GCM_TAG_SIZE + * @param arg_len 64 + 16 = 80 bytes + * @param reply AES_GCM256(struct secure_transport_usecase) + + * AES_GCM_TAG_SIZE OR 1 byte error state + * @param reply_len 64 + 16 = 80 OR 1 bytes + */ + +#define NUGGET_PARAM_SECURE_TRANSPORT_TEST 0x001e +/* + * Secure transport test command + * + * @param args 1008 (1024 - 16 bytes AES_TAG_SIZE) bytes test data + * @param arg_len 1008 bytes + * @param reply 1008 (1024 - 16 bytes AES_TAG_SIZE) bytes test data + * @param reply_len 1008 bytes */ /****************************************************************************/ diff --git a/nugget/include/application.h b/nugget/include/application.h index 1d485c6..053d016 100644 --- a/nugget/include/application.h +++ b/nugget/include/application.h @@ -79,9 +79,13 @@ typedef const void * const __private; #define APP_ID_AVB_TEST 0x11 #define APP_ID_TRANSPORT_TEST 0x12 #define APP_ID_FACEAUTH_TEST 0x13 +#define APP_ID_TEST 0x7f -/* This app ID should only be used by tests. */ -#define APP_ID_TEST 0xff +/* OR this with the APP_ID to request no-protobuf messages */ +#define APP_ID_NO_PROTO_FLAG 0x80 + +/* No-protobuf app, experimental for now */ +#define APP_ID_WEAVER2 (APP_ID_WEAVER | APP_ID_NO_PROTO_FLAG) /****************************************************************************/ /* Other command fields */ @@ -90,7 +94,7 @@ typedef const void * const __private; * The Command encoding is: * * Bits 31-24 Control flags (reserved) - * Bits 23-16 Application ID + * Bits 23-16 Application ID (bit 23 indicates C protocol, not protobuf) * Bits 15-0 Parameters (application-specific) */ @@ -239,7 +243,7 @@ struct transport_status { /* Valid range of lengths for the status message */ #define STATUS_MIN_LENGTH 0x10 -#define STATUS_MAX_LENGTH 0xff +#define STATUS_MAX_LENGTH (sizeof(struct transport_status)) /* 0x10 */ /* Flags used in the status message */ #define STATUS_FLAG_WORKING 0x0001 /* added in v1 */ diff --git a/nugget/include/citadel_events.h b/nugget/include/citadel_events.h index 24babee..00780ad 100644 --- a/nugget/include/citadel_events.h +++ b/nugget/include/citadel_events.h @@ -31,7 +31,7 @@ extern "C" { * When Citadel needs to tell the AP something without waiting to be asked, the * process is as follows: * - * 1. Citadel adds an event_record to its internal queue, then asserts + * 1. Citadel adds an event_report to its internal queue, then asserts * the CTDL_AP_IRQ signal to notify the AP. * * 2. The AP (citadeld) requests pending events from Citadel until they've @@ -59,12 +59,14 @@ enum event_priority { * Add to the list, but NEVER change or delete existing entries. */ enum event_id { - EVENT_NONE = 0, // Unused ID, used as empty marker. - EVENT_ALERT = 1, // Globalsec alert fired. - EVENT_REBOOTED = 2, // Device rebooted. - EVENT_UPGRADED = 3, // Device has upgraded. - EVENT_ALERT_V2 = 4, // Globalsec Alertv2 fired + EVENT_NONE = 0, // Unused ID, used as empty marker. + EVENT_ALERT = 1, // Globalsec alert fired. + EVENT_REBOOTED = 2, // Device rebooted. + EVENT_UPGRADED = 3, // Device has upgraded. + EVENT_ALERT_V2 = 4, // Globalsec Alertv2 fired EVENT_SEC_CH_STATE = 5, // Update GSA-GSC secure channel state. + EVENT_V1_NO_SUPPORT = + 6 // Report a VXX event that can't fit in struct event_report. }; /* @@ -76,9 +78,17 @@ enum upgrade_state_def { UPGRADE_EN_FW_FAIL =2, }; +/* + * Big event header flags. + */ +enum hdr_flags { + HDR_FLAG_EMPTY_SLOT = 0, // Used to determine empty slot. + HDR_FLAG_OCCUPIED_SLOT = 1 // Used to indicate an occupied slot. +}; + /* Please do not change the size of this struct */ -#define EVENT_RECORD_SIZE 64 -struct event_record { +#define EVENT_REPORT_SIZE 64 +struct event_report { uint64_t reset_count; /* zeroed by Citadel power cycle */ uint64_t uptime_usecs; /* since last Citadel reset */ uint32_t id; @@ -117,9 +127,23 @@ struct event_record { } event; } __packed; /* Please do not change the size of this struct */ -static_assert(sizeof(struct event_record) == EVENT_RECORD_SIZE, +static_assert(sizeof(struct event_report) == EVENT_REPORT_SIZE, "Muting the Immutable"); +struct big_event_report { + struct hdr { + /* Redundant w.r.t. to v1 event records */ + uint64_t reset_count; + uint64_t uptime_usecs; + uint32_t priority; + + uint8_t version; + uint8_t flags; + uint16_t length; + } hdr; + uint8_t data[384]; +} __packed; + #ifdef __cplusplus } #endif diff --git a/nugget/include/feature_map.h b/nugget/include/feature_map.h new file mode 100644 index 0000000..7ff697b --- /dev/null +++ b/nugget/include/feature_map.h @@ -0,0 +1,67 @@ +/** + * \file + * Feature ID format and inline decode functions + */ + +#pragma once + +/*****************************************************************************/ + +#define TA_MASK 0xFF000000 +#define TA_OFFSET 24 +#define TA_FIELD 8 // Max 256 TAs + +#define FEATURE_MASK 0x00FFFFFF +#define FEATURE_OFFSET 0 +#define FEATURE_FIELD 24 // Can support up to 2^24 features + +#define TA_FROM_FEATURE_ID(id) \ + ((enum feature_support_app_id)((id & TA_MASK) >> TA_OFFSET)) +#define MODULE_FROM_FEATURE_ID(id) ((id & FEATURE_MASK) >> FEATURE_OFFSET) +/*****************************************************************************/ + +enum feature_support_app_id { + feature_id_avb = 0, + feature_id_gfa = 1, + feature_id_identity = 2, + feature_id_keymint = 3, + feature_id_nugget = 4, + feature_id_weaver = 5, + + /* Please do not change numbers after they've been released */ + + feature_id_count, // used in sparse lookup table + feature_id_max = 0xff, // 8-bit TA_FIELD +}; +static_assert(feature_id_count <= feature_id_max, + "Too many enum feature_support_app_id values"); + +enum km_feature_list { + km_feature_individual_attest = 0, + km_feature_batch_attest = 1, + km_feature_gnubby_attest = 2, + km_feature_rkp = 3, + km_feature_rkp_dice = 4, + km_feature_dice = 5, + km_feature_multimei = 6, + + /* Please do not change numbers after they've been released */ + + km_feature_max = FEATURE_MASK, // 24-bit FEATURE_FIELD +}; + +enum nugget_feature_list { + nugget_feature_test_image = 0, + + /* Please do not change numbers after they've been released */ + + nugget_feature_max = FEATURE_MASK, // 24-bit FEATURE_FIELD +}; + +enum weaver_feature_list { + weaver_feature_api_no_proto = 0, + + /* Please do not change numbers after they've been released */ + + weaver_feature_max = FEATURE_MASK, // 24-bit FEATURE_FIELD +}; diff --git a/nugget/include/hals/common.h b/nugget/include/hals/common.h new file mode 100644 index 0000000..ed02484 --- /dev/null +++ b/nugget/include/hals/common.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2022 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. + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef __packed +#define __packed __attribute__((packed)) +#endif + +/****************************************************************************/ +/** + * This should be the start of EVERY request and response struct. + * + * We don't really need a struct just to hold one integer, but if we need to add + * to it later, we'll be glad we did. + */ +struct nos2_cmd_hal { + uint32_t version; +} __packed; +/** + * IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT + * + * Do *NOT* increment the version number with each new dessert release! + * + * We'll use a (major << 16) | (minor) value for the version. The major + * versionn indicates when the command was first supported, and the minor + * indicates variations to it since then. + * + * We're currently working on Android 14 (UDC), so start with that. Bump minor + * values ONLY if the behavior changes. + * + * By including the version struct in every request and response, we can + * support multiple minor HAL changes independently. Add a new version + * constant below IF AND ONLY IF a command's struct changes or its behavior is + * different. THEN use that version internally to + * + * 1. Reject the command if the version is one you don't know about, AND + * + * 2. Verify that the incoming struct matches expectations for the versions + * you do know about, AND + * + * 3. Support as many versions as possible, in case Android is downgraded and + * Nugget OS is not (or vice-versa), SO + * + * 4) Make sure to indicate the version in the output structs too, in case the + * command has no input args but the output later changes. + * + * IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT + */ +#define NOS2_HAL_VERSION_UDC (14U << 16) +/* STOP! Don't just randomly add new values here! Read the comment above! */ + +/****************************************************************************/ +/* Common types */ + +/* TODO(b/257251378): We'll need some <tag,len,bytes[]> stuff here. */ + +/****************************************************************************/ +#ifdef __cplusplus +} +#endif diff --git a/nugget/include/hals/weaver.h b/nugget/include/hals/weaver.h new file mode 100644 index 0000000..29bd67c --- /dev/null +++ b/nugget/include/hals/weaver.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2022 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. + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "application.h" +#include "hals/common.h" + +/****************************************************************************/ +/* Magic constants + * + * Only Acropora knows these numbers. The AP has to ask. + * + * It's a pain to create multiple variable-length arrays using strictly correct + * C, but the Weaver service is in the Nugget OS repo so we can hard-code the + * sizes here. If it ever changes we'll use the hal.version field to distinguish + * which one we're using. + * + * Still, we want to match the AIDL definitions as closely as possible, to + * make our code easier to understand and maintain. + */ +#define NOS2_WEAVER_NUM_SLOTS 64 +#define NOS2_WEAVER_KEY_BYTES (128 / 8) +#define NOS2_WEAVER_VALUE_BYTES (128 / 8) +static_assert((NOS2_WEAVER_KEY_BYTES & 0x4) == 0, + "NOS2_WEAVER_KEY_BYTES is not a multiple of 4"); +static_assert((NOS2_WEAVER_VALUE_BYTES & 0x4) == 0, + "NOS2_WEAVER_VALUE_BYTES is not a multiple of 4"); + +typedef uint8_t nos2_weaver_key_t[NOS2_WEAVER_KEY_BYTES]; +typedef uint8_t nos2_weaver_value_t[NOS2_WEAVER_VALUE_BYTES]; + +/****************************************************************************/ +/* The command is sent separately from any data */ + +enum nos2_weaver_cmd { + NOS2_WEAVER_GET_CONFIG, + NOS2_WEAVER_WRITE, + NOS2_WEAVER_READ, + NOS2_WEAVER_ERASE_VALUE, + + NOS2_WEAVER_NUM_CMDS +}; + +/****************************************************************************/ +/* Request/Response data. Both are optional and depend on the command. */ + +/** NOS2_WEAVER_GET_CONFIG */ +/* There is no struct nos2_weaver_get_config_request */ +struct nos2_weaver_get_config_response { + struct nos2_cmd_hal hal; + + uint32_t slots; + uint32_t key_size; + uint32_t value_size; +}; + +/** NOS2_WEAVER_WRITE */ +struct nos2_weaver_write_request { + struct nos2_cmd_hal hal; + + uint32_t slot_id; + nos2_weaver_key_t key; + nos2_weaver_value_t value; +}; +/* There is no struct nos2_weaver_write_response */ + +/** NOS2_WEAVER_READ */ +struct nos2_weaver_read_request { + struct nos2_cmd_hal hal; + + uint32_t slot_id; + nos2_weaver_key_t key; +}; + +enum nos2_weaver_read_status { + NOS2_WEAVER_READ_STATUS_OK, + NOS2_WEAVER_READ_STATUS_FAILED, + NOS2_WEAVER_READ_STATUS_INCORRECT_KEY, + NOS2_WEAVER_READ_STATUS_THROTTLE, +}; + +struct nos2_weaver_read_response { + struct nos2_cmd_hal hal; + + uint32_t timeout; + uint32_t status; /* enum nos2_weaver_read_status, but of specified size */ + /* Put potentially variable-length members at the end. It's NOT, though */ + nos2_weaver_value_t value; +}; + +/** NOS2_WEAVER_ERASE_VALUE */ +struct nos2_weaver_erase_request { + struct nos2_cmd_hal hal; + + uint32_t slot_id; +}; +/* There is no struct nos2_weaver_erase_response */ + +/****************************************************************************/ +#ifdef __cplusplus +} +#endif diff --git a/libnos_datagram/include/nos/device.h b/nugget/include/nos/device.h index 2ba57e0..d1fb0d6 100644 --- a/libnos_datagram/include/nos/device.h +++ b/nugget/include/nos/device.h @@ -16,6 +16,9 @@ #ifndef NOS_DEVICE_H #define NOS_DEVICE_H +#ifdef ANDROID +#include <stdbool.h> +#endif #include <stdint.h> #ifdef __cplusplus @@ -69,12 +72,28 @@ struct nos_device_ops { * The device must not be used after closing. */ void (*close)(void *ctx); + +#ifdef ANDROID + /** + * one_pass_call: sending whole data payload directly to GSA FW + * and rely on GSA libnos_transport library to communicate with GSC. + * + * Return 0 on success. A negative value on I/O failure. + */ + int (*one_pass_call)(void *ctx, uint8_t app_id, uint16_t params, + const uint8_t *args, uint32_t arg_len, + uint8_t *reply, uint32_t *reply_len, + uint32_t *status_code); +#endif }; struct nos_device { void *ctx; struct nos_device_ops ops; uint32_t config; +#ifdef ANDROID + bool use_one_pass_call; +#endif }; /* diff --git a/nugget/proto/Android.bp b/nugget/proto/Android.bp index b9f1220..b4ee2a0 100644 --- a/nugget/proto/Android.bp +++ b/nugget/proto/Android.bp @@ -43,3 +43,8 @@ cc_library { }, } + +filegroup { + name: "nugget_options_proto", + srcs: ["nugget/protobuf/options.proto"], +}
\ No newline at end of file diff --git a/nugget/proto/nugget/app/avb/Android.bp b/nugget/proto/nugget/app/avb/Android.bp index 136b9d5..53b284a 100644 --- a/nugget/proto/nugget/app/avb/Android.bp +++ b/nugget/proto/nugget/app/avb/Android.bp @@ -26,7 +26,11 @@ package { genrule { name: "nos_app_avb_service_genc++", out: ["Avb.client.cpp"], - srcs: ["avb.proto"], + srcs: [ + "avb.proto", + ":nugget_options_proto", + ":libprotobuf-internal-protos", + ], tools: ["aprotoc", "protoc-gen-nos-client-cpp"], cmd: GEN_SERVICE_SOURCE, } @@ -34,7 +38,11 @@ genrule { genrule { name: "nos_app_avb_service_genc++_headers", out: ["Avb.client.h"], - srcs: ["avb.proto"], + srcs: [ + "avb.proto", + ":nugget_options_proto", + ":libprotobuf-internal-protos", + ], tools: ["aprotoc", "protoc-gen-nos-client-cpp"], cmd: GEN_SERVICE_HEADER, } @@ -42,7 +50,11 @@ genrule { genrule { name: "nos_app_avb_service_genc++_mock", out: ["MockAvb.client.h"], - srcs: ["avb.proto"], + srcs: [ + "avb.proto", + ":nugget_options_proto", + ":libprotobuf-internal-protos", + ], tools: ["aprotoc", "protoc-gen-nos-client-cpp"], cmd: GEN_SERVICE_MOCK, } diff --git a/nugget/proto/nugget/app/avb/avb.proto b/nugget/proto/nugget/app/avb/avb.proto index 9aec71e..99e1882 100644 --- a/nugget/proto/nugget/app/avb/avb.proto +++ b/nugget/proto/nugget/app/avb/avb.proto @@ -43,6 +43,7 @@ service Avb { rpc GetOwnerKey (GetOwnerKeyRequest) returns (GetOwnerKeyResponse); rpc GetResetChallenge (GetResetChallengeRequest) returns (GetResetChallengeResponse); rpc ProductionResetTest (ProductionResetTestRequest) returns (ProductionResetTestResponse); + rpc GetCarrierLockName (GetCarrierLockNameRequest) returns (GetCarrierLockNameResponse); } enum LockIndex { @@ -192,3 +193,10 @@ message ProductionResetTestResponse {} message BootloaderDoneRequest {} message BootloaderDoneResponse {} + +// Carrier lock name +message GetCarrierLockNameRequest {} + +message GetCarrierLockNameResponse { + string name = 1; +} diff --git a/nugget/proto/nugget/app/identity/Android.bp b/nugget/proto/nugget/app/identity/Android.bp index b65297a..c557182 100644 --- a/nugget/proto/nugget/app/identity/Android.bp +++ b/nugget/proto/nugget/app/identity/Android.bp @@ -26,7 +26,13 @@ package { genrule { name: "nos_app_identity_service_genc++", out: ["Identity.client.cpp"], - srcs: ["identity.proto"], + srcs: [ + "identity.proto", + "identity_defs.proto", + "identity_types.proto", + ":nugget_options_proto", + ":libprotobuf-internal-protos", + ], tools: ["aprotoc", "protoc-gen-nos-client-cpp"], cmd: GEN_SERVICE_SOURCE, } @@ -34,7 +40,13 @@ genrule { genrule { name: "nos_app_identity_service_genc++_headers", out: ["Identity.client.h"], - srcs: ["identity.proto"], + srcs: [ + "identity.proto", + "identity_defs.proto", + "identity_types.proto", + ":nugget_options_proto", + ":libprotobuf-internal-protos", + ], tools: ["aprotoc", "protoc-gen-nos-client-cpp"], cmd: GEN_SERVICE_HEADER, } @@ -42,7 +54,13 @@ genrule { genrule { name: "nos_app_identity_service_genc++_mock", out: ["MockIdentity.client.h"], - srcs: ["identity.proto"], + srcs: [ + "identity.proto", + "identity_defs.proto", + "identity_types.proto", + ":nugget_options_proto", + ":libprotobuf-internal-protos", + ], tools: ["aprotoc", "protoc-gen-nos-client-cpp"], cmd: GEN_SERVICE_MOCK, } diff --git a/nugget/proto/nugget/app/identity/identity.proto b/nugget/proto/nugget/app/identity/identity.proto index a29aa16..58e656e 100644 --- a/nugget/proto/nugget/app/identity/identity.proto +++ b/nugget/proto/nugget/app/identity/identity.proto @@ -18,7 +18,6 @@ syntax = "proto3"; package nugget.app.identity; -import "nugget/app/identity/identity_defs.proto"; import "nugget/app/identity/identity_types.proto"; import "nugget/protobuf/options.proto"; @@ -61,6 +60,11 @@ service Identity { rpc SessionInitialize (SessionInitializeRequest) returns (SessionInitializeResponse); rpc SessionSetReaderEphemeralPublicKey (SessionSetReaderEphemeralPublicKeyRequest) returns (SessionSetReaderEphemeralPublicKeyResponse); rpc SessionSetSessionTranscript (SessionSetSessionTranscriptRequest) returns (SessionSetSessionTranscriptResponse); + + // For Android 14 new APIs + rpc ICprepareDeviceAuthentication (ICprepareDeviceAuthenticationRequest) returns (ICprepareDeviceAuthenticationResponse); + rpc ICfinishRetrievalWithSignature (ICfinishRetrievalWithSignatureRequest) returns (ICfinishRetrievalWithSignatureResponse); + rpc SessionGetEphemeralKeyPair (SessionGetEphemeralKeyPairRequest) returns (SessionGetEphemeralKeyPairResponse); } enum RequestType { @@ -251,7 +255,7 @@ message ICvalidateAccessControlProfileRequest{ uint64 secureUserId = 5; bytes mac = 6; uint32 publicKeyOffset = 7; - uint32 publicKeysize = 8; + uint32 publicKeySize = 8; } message ICvalidateAccessControlProfileResponse{ @@ -285,6 +289,20 @@ message ICcalcMacKeyResponse{ Result result = 1; } +// ICprepareDeviceAuthentication +message ICprepareDeviceAuthenticationRequest{ + bytes sessionTranscript = 1; + bytes readerEphemeralPublicKey = 2; + bytes signingKeyBlob = 3; + bytes docType = 4; + uint32 numNamespacesWithValues = 5; + uint32 expectedDeviceNamespacesSize = 6; +} + +message ICprepareDeviceAuthenticationResponse{ + Result result = 1; +} + // ICstartRetrieveEntryValue message ICstartRetrieveEntryValueRequest{ string nameSpace = 1; @@ -297,6 +315,7 @@ message ICstartRetrieveEntryValueRequest{ message ICstartRetrieveEntryValueResponse{ AccessResult accessCheckResult = 1; uint32 sessionCookie = 2; + Result result = 3; } // ICretrieveEntryValue @@ -322,6 +341,16 @@ message ICfinishRetrievalResponse{ bytes mac = 2; } +// ICfinishRetrievalWithSignature +message ICfinishRetrievalWithSignatureRequest{ +} + +message ICfinishRetrievalWithSignatureResponse{ + Result result = 1; + bytes mac = 2; + bytes ecdsaSignature = 3; +} + // ICdeleteCredential message ICdeleteCredentialRequest{ bytes docType = 1; @@ -369,6 +398,7 @@ message SessionShutdownResponse{ // SessionInitialize message SessionInitializeRequest{ + uint32 oemHalVersion = 1; } message SessionInitializeResponse{ @@ -394,3 +424,12 @@ message SessionSetSessionTranscriptRequest{ message SessionSetSessionTranscriptResponse{ Result result = 1; } + +// SessionGetEphemeralKeyPair +message SessionGetEphemeralKeyPairRequest{ +} + +message SessionGetEphemeralKeyPairResponse{ + Result result = 1; + bytes ephemeralPrivateKey = 2; +} diff --git a/nugget/proto/nugget/app/identity/identity_types.proto b/nugget/proto/nugget/app/identity/identity_types.proto index 4c50f2c..66420a1 100644 --- a/nugget/proto/nugget/app/identity/identity_types.proto +++ b/nugget/proto/nugget/app/identity/identity_types.proto @@ -18,7 +18,6 @@ syntax = "proto3"; package nugget.app.identity; -import "nugget/protobuf/options.proto"; import "nugget/app/identity/identity_defs.proto"; message Result { diff --git a/nugget/proto/nugget/app/keymaster/Android.bp b/nugget/proto/nugget/app/keymaster/Android.bp index 32e3479..8afadc9 100644 --- a/nugget/proto/nugget/app/keymaster/Android.bp +++ b/nugget/proto/nugget/app/keymaster/Android.bp @@ -26,7 +26,13 @@ package { genrule { name: "nos_app_keymaster_service_genc++", out: ["Keymaster.client.cpp"], - srcs: ["keymaster.proto"], + srcs: [ + "keymaster.proto", + "keymaster_defs.proto", + "keymaster_types.proto", + ":nugget_options_proto", + ":libprotobuf-internal-protos", + ], tools: ["aprotoc", "protoc-gen-nos-client-cpp"], cmd: GEN_SERVICE_SOURCE, } @@ -34,7 +40,13 @@ genrule { genrule { name: "nos_app_keymaster_service_genc++_headers", out: ["Keymaster.client.h"], - srcs: ["keymaster.proto"], + srcs: [ + "keymaster.proto", + "keymaster_defs.proto", + "keymaster_types.proto", + ":nugget_options_proto", + ":libprotobuf-internal-protos", + ], tools: ["aprotoc", "protoc-gen-nos-client-cpp"], cmd: GEN_SERVICE_HEADER, } @@ -42,7 +54,13 @@ genrule { genrule { name: "nos_app_keymaster_service_genc++_mock", out: ["MockKeymaster.client.h"], - srcs: ["keymaster.proto"], + srcs: [ + "keymaster.proto", + "keymaster_defs.proto", + "keymaster_types.proto", + ":nugget_options_proto", + ":libprotobuf-internal-protos", + ], tools: ["aprotoc", "protoc-gen-nos-client-cpp"], cmd: GEN_SERVICE_MOCK, } diff --git a/nugget/proto/nugget/app/keymaster/ctdl/Android.bp b/nugget/proto/nugget/app/keymaster/ctdl/Android.bp new file mode 100644 index 0000000..480cceb --- /dev/null +++ b/nugget/proto/nugget/app/keymaster/ctdl/Android.bp @@ -0,0 +1,75 @@ +// +// Copyright (C) 2017 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. +// + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "external_nos_host_generic_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["external_nos_host_generic_license"], +} + +// For keymaster 3/4/4.1 @ citadel +genrule { + name: "nos_app_keymaster_service_ctdl_genc++", + out: ["Keymaster.client.cpp"], + srcs: [ + "keymaster.proto", + "keymaster_defs.proto", + "keymaster_types.proto", + ":nugget_options_proto", + ":libprotobuf-internal-protos", + ], + tools: ["aprotoc", "protoc-gen-nos-client-cpp"], + cmd: GEN_SERVICE_SOURCE, +} + +genrule { + name: "nos_app_keymaster_service_ctdl_genc++_headers", + out: ["Keymaster.client.h"], + srcs: [ + "keymaster.proto", + "keymaster_defs.proto", + "keymaster_types.proto", + ":nugget_options_proto", + ":libprotobuf-internal-protos", + ], + tools: ["aprotoc", "protoc-gen-nos-client-cpp"], + cmd: GEN_SERVICE_HEADER, +} + +genrule { + name: "nos_app_keymaster_service_ctdl_genc++_mock", + out: ["MockKeymaster.client.h"], + srcs: [ + "keymaster.proto", + "keymaster_defs.proto", + "keymaster_types.proto", + ":nugget_options_proto", + ":libprotobuf-internal-protos", + ], + tools: ["aprotoc", "protoc-gen-nos-client-cpp"], + cmd: GEN_SERVICE_MOCK, +} + +cc_library { + name: "nos_app_keymaster_ctdl", + generated_sources: ["nos_app_keymaster_service_ctdl_genc++"], + generated_headers: ["nos_app_keymaster_service_ctdl_genc++_headers"], + defaults: ["nos_app_service_defaults"], + export_generated_headers: ["nos_app_keymaster_service_ctdl_genc++_headers"], +} diff --git a/nugget/proto/nugget/app/keymaster/ctdl/keymaster.options b/nugget/proto/nugget/app/keymaster/ctdl/keymaster.options new file mode 100644 index 0000000..daec677 --- /dev/null +++ b/nugget/proto/nugget/app/keymaster/ctdl/keymaster.options @@ -0,0 +1,21 @@ +nugget.app.keymaster.ctdl.ImportWrappedKeyRequest.initialization_vector max_size:12 +nugget.app.keymaster.ctdl.ImportWrappedKeyRequest.gcm_tag max_size:16 +nugget.app.keymaster.ctdl.ImportWrappedKeyRequest.masking_key max_size:32 +nugget.app.keymaster.ctdl.SetRootOfTrustRequest.digest max_size:32 +nugget.app.keymaster.ctdl.SetBootStateRequest.public_key max_size:32 +nugget.app.keymaster.ctdl.SetBootStateRequest.boot_hash max_size:32 +nugget.app.keymaster.ctdl.ComputeSharedHmacRequest.hmac_sharing_params max_count:10 +nugget.app.keymaster.ctdl.ComputeSharedHmacResponse.sharing_check max_size:32 +nugget.app.keymaster.ctdl.DTupHandshakeRequest.nonce_client max_size:32 +nugget.app.keymaster.ctdl.DTupHandshakeResponse.nonce_citadel max_size:32 +nugget.app.keymaster.ctdl.DTupHandshakeResponse.signature max_size:32 +nugget.app.keymaster.ctdl.DTupFetchInputEventResponse.signature max_size:32 +nugget.app.keymaster.ctdl.GetBootInfoResponse.boot_key max_size:32 +nugget.app.keymaster.ctdl.GetBootInfoResponse.boot_hash max_size:32 +nugget.app.keymaster.ctdl.ProvisionPresharedSecretRequest.preshared_secret max_size:32 +nugget.app.keymaster.ctdl.StartAttestKeyRequest.not_before max_size:15 +nugget.app.keymaster.ctdl.StartAttestKeyRequest.not_after max_size:15 +nugget.app.keymaster.ctdl.StartAttestKeyRequest.caller_issuer_subj_name max_size:100 +nugget.app.keymaster.ctdl.ProvisionPresharedSecretResponse.digest max_size:32 +nugget.app.keymaster.ctdl.ProvisionCertificatesRequest.cert_block max_size: 1024 +nugget.app.keymaster.ctdl.ProvisionCertificatesRequest.digest max_size: 32 diff --git a/nugget/proto/nugget/app/keymaster/ctdl/keymaster.proto b/nugget/proto/nugget/app/keymaster/ctdl/keymaster.proto new file mode 100644 index 0000000..49f18b1 --- /dev/null +++ b/nugget/proto/nugget/app/keymaster/ctdl/keymaster.proto @@ -0,0 +1,658 @@ +/* + * Copyright (C) 2017 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. + */ + +syntax = "proto3"; + +package nugget.app.keymaster.ctdl; + +import "nugget/app/keymaster/ctdl/keymaster_defs.proto"; +import "nugget/app/keymaster/ctdl/keymaster_types.proto"; +import "nugget/protobuf/options.proto"; + +/* + * Keymaster service methods. + * + * TODO: some methods may be implemented in the host side HAL implementation. + */ +service Keymaster { + option (nugget.protobuf.app_id) = "KEYMASTER"; + option (nugget.protobuf.app_name) = "Keymaster"; + option (nugget.protobuf.app_version) = 1; + /* + * Both request and response buffers are sized such + * that a key-blob may be fully contained. + * + * TODO: revisit this choice in the event that memory + * is running out. Supporting smaller buffers will + * require that the keymaster app switch from the + * transport API to the datagram API. + */ + option (nugget.protobuf.request_buffer_size) = 3072; + option (nugget.protobuf.response_buffer_size) = 2048; + + /* + * KM3 methods, from: + * ::android::hardware::keymaster::V3_0::IKeymasterDevice + */ + rpc AddRngEntropy (AddRngEntropyRequest) returns (AddRngEntropyResponse); + rpc GenerateKey (GenerateKeyRequest) returns (GenerateKeyResponse); + rpc GetKeyCharacteristics (GetKeyCharacteristicsRequest) returns (GetKeyCharacteristicsResponse); + rpc ImportKey (ImportKeyRequest) returns (ImportKeyResponse); + rpc ExportKey (ExportKeyRequest) returns (ExportKeyResponse); + rpc StartAttestKey (StartAttestKeyRequest) returns (StartAttestKeyResponse); + rpc UpgradeKey (UpgradeKeyRequest) returns (UpgradeKeyResponse); + rpc DeleteKey (DeleteKeyRequest) returns (DeleteKeyResponse); + rpc DeleteAllKeys (DeleteAllKeysRequest) returns (DeleteAllKeysResponse); + rpc DestroyAttestationIds (DestroyAttestationIdsRequest) returns (DestroyAttestationIdsResponse); + rpc BeginOperation (BeginOperationRequest) returns (BeginOperationResponse); + rpc UpdateOperation (UpdateOperationRequest) returns (UpdateOperationResponse); + rpc FinishOperation (FinishOperationRequest) returns (FinishOperationResponse); + rpc AbortOperation (AbortOperationRequest) returns (AbortOperationResponse); + + /* + * KM4 methods. + */ + rpc ImportWrappedKey (ImportWrappedKeyRequest) returns (ImportKeyResponse); + + /* + * Vendor specific methods (bootloader, manufacturing, status, + * factory reset, upgrade). + */ + // Only callable by the Bootloader. + rpc SetRootOfTrust (SetRootOfTrustRequest) returns (SetRootOfTrustResponse); + // Only callable by the Bootloader. + rpc SetBootState (SetBootStateRequest) returns (SetBootStateResponse); + // Only callable at the Device Factory. + rpc ProvisionDeviceIds (ProvisionDeviceIdsRequest) returns (ProvisionDeviceIdsResponse); + // Only callable at the Device Factory. + rpc ReadTeeBatchCertificate (ReadTeeBatchCertificateRequest) returns (ReadTeeBatchCertificateResponse); + + /* + * More KM4 methods. + */ + rpc GetHmacSharingParameters (GetHmacSharingParametersRequest) returns (GetHmacSharingParametersResponse); + rpc ComputeSharedHmac (ComputeSharedHmacRequest) returns (ComputeSharedHmacResponse); + + /* + * DTup input session methods. + */ + rpc HandshakeDTup (DTupHandshakeRequest) returns (DTupHandshakeResponse); + rpc FetchDTupInputEvent (DTupFetchInputEventRequest) returns (DTupFetchInputEventResponse); + + /* + * More vendor specific methods. + */ + // Only callable once per boot. + rpc SetSystemVersionInfo (SetSystemVersionInfoRequest) returns (SetSystemVersionInfoResponse); + rpc GetBootInfo (GetBootInfoRequest) returns (GetBootInfoResponse); + + /* + * Called during provisioning by the CitadelProvision tool. + */ + rpc ProvisionPresharedSecret (ProvisionPresharedSecretRequest) returns (ProvisionPresharedSecretResponse); + + /* + * Additional attestation methods. + */ + rpc ContinueAttestKey(ContinueAttestKeyRequest) returns (ContinueAttestKeyResponse); + rpc FinishAttestKey(FinishAttestKeyRequest) returns (FinishAttestKeyResponse); + + /* + * More vendor specific methods. + */ + rpc ProvisionCertificates(ProvisionCertificatesRequest) returns (ProvisionCertificatesResponse); + + /* + * KM4.1 methods. + */ + rpc DeviceLocked(DeviceLockedRequest) returns (DeviceLockedResponse); + rpc EarlyBootEnded(EarlyBootEndedRequest) returns (EarlyBootEndedResponse); + + /* + * More vendor specific methods. + */ + rpc ReadCertificate(ReadCertificateRequest) returns (ReadCertificateResponse); + rpc IdentityStartAttestKey (IdentityStartAttestKeyRequest) returns (IdentityStartAttestKeyResponse); + rpc IdentityFinishAttestKey (IdentityFinishAttestKeyRequest) returns (IdentityFinishAttestKeyResponse); + + /* + * Resume-on-Reboot implementation. + */ + rpc VigoReadVS(VigoReadVSRequest) returns (VigoReadVSResponse); + rpc VigoStartChannel(VigoStartChannelRequest) + returns (VigoStartChannelResponse); + rpc VigoStoreSecret(VigoStoreSecretRequest) returns (VigoStoreSecretResponse); + rpc VigoReleaseSecret(VigoReleaseSecretRequest) + returns (VigoReleaseSecretResponse); + + /* + * pKVM implementation + */ + rpc GetPerFactoryResetValue(GetPerFactoryResetValueRequest) returns (GetPerFactoryResetValueResponse); + + /* + * RKP implementation + */ + rpc GenerateRkpKey(GenerateRkpKeyRequest) returns (GenerateRkpKeyResponse); + rpc GenerateRkpCsr(GenerateRkpCsrRequest) returns (GenerateRkpCsrResponse); + + /* + * Vendor specific method. To export IMEI/DSU to trusty only + */ + rpc ExportDeviceIds(ExportDeviceIdsRequest) returns (ExportDeviceIdsResponse); + + /* + * RKP v3 implementation + */ + rpc GenerateRkpCsrV2(GenerateRkpCsrV2Request) returns (GenerateRkpCsrV2Response); + // These are implemented with a enum, so new RPCs must be appended, and + // deprecated RPCs need placeholders. +} + +/* + * KM3 messages. + */ + +// AddEntropy +message AddRngEntropyRequest { + bytes data = 1; +} +message AddRngEntropyResponse { + ErrorCode error_code = 1; +} + +// GenerateKey +message GenerateKeyRequest { + KeyParameters params = 1; + uint64 creation_time_ms = 2; // Rough current time (ms since epoch). +} +message GenerateKeyResponse { + ErrorCode error_code = 1; + KeyBlob blob = 2; + KeyCharacteristics characteristics = 3; +} + +// GetKeyCharacteristics +message GetKeyCharacteristicsRequest { + KeyBlob blob = 1; + bytes client_id = 2; + bytes app_data = 3; +} +message GetKeyCharacteristicsResponse { + ErrorCode error_code = 1; + KeyCharacteristics characteristics = 2; +} + +// ImportKey +message ImportKeyRequest { + KeyParameters params = 1; + RSAKey rsa = 2; + ECKey ec = 3; + SymmetricKey symmetric_key = 4; + uint64 creation_time_ms = 5; // Rough current time (ms since epoch). +}; +message ImportKeyResponse { + ErrorCode error_code = 1; + KeyBlob blob = 2; + KeyCharacteristics characteristics = 3; +}; + +// ExportKey +message ExportKeyRequest { + KeyFormat format = 1; + KeyBlob blob = 2; + bytes client_id = 3; + bytes app_data = 4; +}; +message ExportKeyResponse { + ErrorCode error_code = 1; + Algorithm algorithm = 2; + RSAKey rsa = 3; + ECKey ec = 4; +}; + +// StartAttestKey +message StartAttestKeyRequest { + KeyBlob blob = 1; + KeyParameters params = 2; + uint32 attestation_app_id_len = 3; + AttestationSelector selector = 4; + bytes not_before = 5; // strftime('%Y%m%d%H%M%SZ') [15 octects] + bytes not_after = 6; // strftime('%Y%m%d%H%M%SZ') [15 octects] + bytes caller_issuer_subj_name = 7; + KeyParameters caller_key_params = 8; +} +message StartAttestKeyResponse { + ErrorCode error_code = 1; + OperationHandle handle = 2; + bytes certificate_prologue = 3; +} + +// ContinueAttestKeyRequest +message ContinueAttestKeyRequest { + OperationHandle handle = 1; + // bytes attestation_app_id = 2; // Unused, contained within params + KeyParameters params = 3; +} +message ContinueAttestKeyResponse { + ErrorCode error_code = 1; + bytes certificate_body = 2; +} + +// FinishAttestKeyRequest +message FinishAttestKeyRequest { + OperationHandle handle = 1; + KeyBlob caller_blob = 2; + KeyParameters caller_key_params = 3; +} +message FinishAttestKeyResponse { + ErrorCode error_code = 1; + bytes certificate_epilogue = 2; + ChipFusing chip_fusing = 3; + bool nodelocked_ro = 4; +} + +// UpgradeKey +message UpgradeKeyRequest { + KeyBlob blob = 1; + KeyParameters params = 2; +} +message UpgradeKeyResponse { + ErrorCode error_code = 1; + KeyBlob blob = 2; +} + +// DeleteKey +message DeleteKeyRequest { + KeyBlob blob = 1; +} +message DeleteKeyResponse { + ErrorCode error_code = 1; +} + +// DeleteAllKeys +message DeleteAllKeysRequest {} +message DeleteAllKeysResponse { + ErrorCode error_code = 1; +} + +// DestroyAttestationIds +message DestroyAttestationIdsRequest {} +message DestroyAttestationIdsResponse { + ErrorCode error_code = 1; +} + +// BeginOperation +message BeginOperationRequest { + KeyPurpose purpose = 1; + KeyBlob blob = 2; + KeyParameters params = 3; + HardwareAuthToken auth_token = 4; +} +message BeginOperationResponse { + ErrorCode error_code = 1; + KeyParameters params = 2; + OperationHandle handle = 3; + Algorithm algorithm = 4; + uint32 key_bits = 5; +} + +// UpdateOperation +message UpdateOperationRequest { + OperationHandle handle = 1; + KeyParameters params = 2; + bytes input = 3; + HardwareAuthToken auth_token = 4; + VerificationToken verification_token = 5; +} +message UpdateOperationResponse { + ErrorCode error_code = 1; + uint32 consumed = 2; + KeyParameters params = 3; + bytes output = 4; +} + +// FinishOperation +message FinishOperationRequest { + OperationHandle handle = 1; + KeyParameters params = 2; + bytes input = 3; + bytes signature = 4; + HardwareAuthToken auth_token = 5; + VerificationToken verification_token = 6; +}; +message FinishOperationResponse { + ErrorCode error_code = 1; + KeyParameters params = 2; + bytes output = 3; +}; + +// AbortOperation +message AbortOperationRequest { + OperationHandle handle = 1; +}; +message AbortOperationResponse { + ErrorCode error_code = 1; +}; + +/* + * KM4 messages. + */ + +// ImportWrappedKey +message ImportWrappedKeyRequest { + uint32 key_format = 1; + KeyParameters params = 2; + bytes rsa_envelope = 3; + bytes initialization_vector = 4; // Fixed sized array. + bytes encrypted_import_key = 5; + bytes aad = 6; + bytes gcm_tag = 7; // Fixed sized array. + KeyBlob wrapping_key_blob = 8; + bytes masking_key = 9; // Fixed sized array. + uint64 creation_time_ms = 10; // Rough current time (ms since epoch). +} +// ImportWrappedKey returns a ImportKeyResponse. + +// GetHmacSharingParametersRequest +message GetHmacSharingParametersRequest { +} +message GetHmacSharingParametersResponse { + ErrorCode error_code = 1; + HmacSharingParameters hmac_sharing_params = 2; +} + +// ComputeSharedHmacRequest +message ComputeSharedHmacRequest { + repeated HmacSharingParameters hmac_sharing_params = 1; +} +message ComputeSharedHmacResponse { + ErrorCode error_code = 1; + bytes sharing_check = 2; +} + +// DeviceLockedRequest +message DeviceLockedRequest { + bool password_only = 1; + VerificationToken verification_token = 2; +} +message DeviceLockedResponse { + ErrorCode error_code = 1; +} + +// DeviceLockedRequest +message EarlyBootEndedRequest {} +message EarlyBootEndedResponse { + ErrorCode error_code = 1; +} + +/* + * Vendor HAL. + */ + +// SetRootOfTrustRequest +// Only callable by the Bootloader. +message SetRootOfTrustRequest { + bytes digest = 1; // This is a SHA256 digest. +} +message SetRootOfTrustResponse { + // Specified in keymaster_defs.proto:ErrorCode + ErrorCode error_code = 1; +} + +// SetBootStateRequest +// Only callable by the Bootloader. +message SetBootStateRequest { + bool is_unlocked = 1; + bytes public_key = 2; // This is a SHA256 digest. + BootColor color = 3; + uint32 system_version = 4; // Deprecated. + uint32 system_security_level = 5; // Patch level of the boot partition. + bytes boot_hash = 6; // This is a SHA256 digest. + uint32 boot_security_level = 7; +} +message SetBootStateResponse { + // Specified in keymaster_defs.proto:ErrorCode + ErrorCode error_code = 1; +} + +// ProvisionDeviceIds +// Only callable at the Device Factory +message ProvisionDeviceIdsRequest { + bytes product_brand = 1; + bytes product_device = 2; + bytes product_name = 3; + bytes serialno = 4; + bytes product_manufacturer = 5; + bytes product_model = 6; + bytes imei = 7; + bytes meid = 8; + bytes imei2 = 9; +} +message ProvisionDeviceIdsResponse { + // Specified in keymaster_defs.proto:ErrorCode + ErrorCode error_code = 1; + ChipFusing chip_fusing = 2; + bool nodelocked_ro = 3; +} + +message ExportDeviceIdsRequest { + bytes challenge = 1; + bytes challenge_hmac = 2; +} + +message ExportDeviceIdsResponse { + ErrorCode error_code = 1; + bytes product_brand = 2; + bytes product_device = 3; + bytes product_name = 4; + bytes serialno = 5; + bytes product_manufacturer = 6; + bytes product_model = 7; + bytes imei = 8; + bytes meid = 9; + bytes ids_hmac = 10; +} + +// ReadTeeBatchCertificate +// Only callable at the Device Factory +message ReadTeeBatchCertificateRequest { + Algorithm algorithm = 1; +} +message ReadTeeBatchCertificateResponse { + ErrorCode error_code = 1; + RSAKey rsa = 2; // rsa or ec set based on request algorithm selector. + ECKey ec = 3; + bytes batch_cert = 4; +} + +message DTupHandshakeRequest { + bytes nonce_client = 1; +} + +message DTupHandshakeResponse { + DTupError error_code = 1; + bytes nonce_citadel = 2; + bytes signature = 3; +} + +message DTupFetchInputEventRequest {} + +message DTupFetchInputEventResponse { + DTupError error_code = 1; + DTupKeyEvent event = 2; + bytes signature = 3; +} + +message SetSystemVersionInfoRequest { + uint32 system_version = 1; // getprop "ro.build.version.release" + uint32 system_security_level = 2; // getprop "ro.build.version.security_patch" + uint32 vendor_security_level = 3; // getprop "ro.vendor.build.security_patch" + uint32 vendor_api_level = 4; +} + +message SetSystemVersionInfoResponse { + // Specified in keymaster_defs.proto:ErrorCode + ErrorCode error_code = 1; +} + +message GetBootInfoRequest {} + +message GetBootInfoResponse { + ErrorCode error_code = 1; + bool is_unlocked = 2; + BootColor boot_color = 3; + bytes boot_key = 4; // This is a SHA256 digest. + bytes boot_hash = 5; // This is a SHA256 digest. +} + +message ProvisionPresharedSecretRequest { + bytes preshared_secret = 1; + bool get_status = 2; +} +message ProvisionPresharedSecretResponse { + ErrorCode error_code = 1; + PresharedSecretStatus status = 2; + BootColor color = 3; + bytes digest = 4; +} + +message ProvisionCertificatesRequest { + uint32 block_number = 1; + bytes cert_block = 2; + bytes digest = 3; +} +message ProvisionCertificatesResponse { + ErrorCode error_code = 1; + CertificateStatus cert_status = 2; +} + +message ReadCertificateRequest { + AttestationSelector selector = 1; + Algorithm algorithm = 2; +} +message ReadCertificateResponse { + ErrorCode error_code = 1; + Certificate cert = 2; +} + +message VigoReadVSRequest {} +message VigoReadVSResponse { + ErrorCode error_code = 1; + VigoKey vs_key = 2; +} +message VigoStartChannelRequest { + VigoKey client_key = 1; +} +message VigoStartChannelResponse { + ErrorCode error_code = 1; + VigoKey server_key = 2; + VigoSignature channel_signature = 3; +} +message VigoStoreSecretRequest { + VigoKey rs_key = 1; + VigoSecret secret_encrypted = 2; +} +message VigoStoreSecretResponse { + ErrorCode error_code = 1; +} +message VigoReleaseSecretRequest { + VigoSignature rs_signature = 1; +} +message VigoReleaseSecretResponse { + ErrorCode error_code = 1; + VigoSecret secret_encrypted = 2; +} + +// IdentityStartAttestKey +message IdentityStartAttestKeyRequest { + bytes pubkey = 1; + KeyParameters params = 2; + uint32 attestation_app_id_len = 3; + AttestationSelector selector = 4; + bytes not_before = 5; // strftime('%y%m%d%H%M%SZ') [15 octects] + bytes not_after = 6; // strftime('%y%m%d%H%M%SZ') [15 octects] + uint64 creation_time_ms = 7; // Rough current time (ms since epoch). + bool use_km_attest_key = 8; + bytes caller_issuer_subj_name = 9; +} +message IdentityStartAttestKeyResponse { + ErrorCode error_code = 1; + OperationHandle handle = 2; + bytes certificate_prologue = 3; +} + +// IdentityFinishAttestKeyRequest +message IdentityFinishAttestKeyRequest { + OperationHandle handle = 1; + bool use_km_attest_key = 2; + KeyBlob caller_blob = 3; +} +message IdentityFinishAttestKeyResponse { + ErrorCode error_code = 1; + bytes certificate_epilogue = 2; + ChipFusing chip_fusing = 3; + bool nodelocked_ro = 4; +} + +// pKVM messages +message GetPerFactoryResetValueRequest { + bool bootloader_only = 1; + bytes input = 2; +} +message GetPerFactoryResetValueResponse { + ErrorCode error_code = 1; + bytes output = 2; +} + +// RKP messages +message GenerateRkpKeyRequest{ + bool test_mode = 1; + KeyParameters params = 2; + KeyBlob blob = 3; +} +message GenerateRkpKeyResponse{ + ErrorCode error_code = 1; + bytes maced_public_key = 2; +} + +message GenerateRkpCsrRequest{ + bool test_mode = 1; + KeysToSign keys_to_sign = 2; + bytes endpoint_enc_cert_chain = 3; + bytes challenge = 4; +} +message GenerateRkpCsrResponse{ + ErrorCode error_code = 1; + bytes keys_to_sign_mac = 2; + bytes device_info_blob = 3; + bytes protected_data_blob = 4; +} + +message GenerateRkpCsrV2Request{ + RkpCsrV2Operation step = 1; + bytes challenge = 2; + uint32 num_of_public_keys = 3; + MacedKey key_to_sign = 4; + OperationHandle handle = 5; +} +message GenerateRkpCsrV2Response{ + ErrorCode error_code = 1; + OperationHandle handle = 2; + bytes device_info_blob = 3; + bytes dice_cert_chain = 4; + bytes signature = 5; +} diff --git a/nugget/proto/nugget/app/keymaster/ctdl/keymaster_defs.proto b/nugget/proto/nugget/app/keymaster/ctdl/keymaster_defs.proto new file mode 100644 index 0000000..1927026 --- /dev/null +++ b/nugget/proto/nugget/app/keymaster/ctdl/keymaster_defs.proto @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2017 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. + */ + +syntax = "proto3"; + +package nugget.app.keymaster.ctdl; + +/* + * Minimal type definitions required for building protos. Sourced from: + * ::android::hardware::keymaster::V3_0 + */ +enum TagType { + TAG_TYPE_INVALID = 0x0; /* 0 << 16 */ + ENUM = 0x10000; /* 1 << 16 */ + ENUM_REP = 0x20000; /* 2 << 16 */ + UINT = 0x30000; /* 3 << 16 */ + UINT_REP = 0x40000; /* 4 << 16 */ + ULONG = 0x50000; /* 5 << 16 */ + DATE = 0x60000; /* 6 << 16 */ + BOOL = 0x70000; /* 7 << 16 */ + BIGNUM_ = 0x80000; /* 8 << 16 */ + BYTES = 0x90000; /* 9 << 16 */ + ULONG_REP = 0xA0000; /* 10 << 16 */ +}; + +enum Tag { + TAG_INVALID = 0; // (TagType:INVALID | 0) + PURPOSE = 0x20001; // (TagType:ENUM_REP | 1) + ALGORITHM = 0x10002; // (TagType:ENUM | 2) + KEY_SIZE = 0x30003; // (TagType:UINT | 3) + BLOCK_MODE = 0x20004; // (TagType:ENUM_REP | 4) + DIGEST = 0x20005; // (TagType:ENUM_REP | 5) + PADDING = 0x20006; // (TagType:ENUM_REP | 6) + CALLER_NONCE = 0x70007; // (TagType:BOOL | 7) + MIN_MAC_LENGTH = 0x30008; // (TagType:UINT | 8) + /* RESERVED: KDF = 0x20009; // (TagType:ENUM_REP | 9) */ + EC_CURVE = 0x1000a; // (TagType:ENUM | 10) + RSA_PUBLIC_EXPONENT = 0x500c8; // (TagType:ULONG | 200) + /* RESERVED: ECIES_SINGLE_HASH_MODE = 0x700c9; // (TagType:BOOL | 201) */ + INCLUDE_UNIQUE_ID = 0x700ca; // (TagType:BOOL | 202) + RSA_OAEP_MGF_DIGEST = 0x200cb; // (TagType:ENUM_REP | 203) + BLOB_USAGE_REQUIREMENTS = 0x1012d; // (TagType:ENUM | 301) + BOOTLOADER_ONLY = 0x7012e; // (TagType:BOOL | 302) + ROLLBACK_RESISTANCE = 0x7012f; // (TagType:BOOL | 303) + HARDWARE_TYPE = 0x10130; // TagType:ENUM | 304, + EARLY_BOOT_ONLY = 0x70131; // TagType:BOOL | 305, + ACTIVE_DATETIME = 0x60190; // (TagType:DATE | 400) + ORIGINATION_EXPIRE_DATETIME = 0x60191; // (TagType:DATE | 401) + USAGE_EXPIRE_DATETIME = 0x60192; // (TagType:DATE | 402) + MIN_SECONDS_BETWEEN_OPS = 0x30193; // (TagType:UINT | 403) + MAX_USES_PER_BOOT = 0x30194; // (TagType:UINT | 404) + USAGE_COUNT_LIMIT = 0x30195; // (TagType:UINT | 405) + /* RESERVED: ALL_USERS = 0x701f4; // (TagType:BOOL | 500) */ + USER_ID = 0x301f5; // (TagType:UINT | 501) + USER_SECURE_ID = 0xa01f6; // (TagType:ULONG_REP | 502) + NO_AUTH_REQUIRED = 0x701f7; // (TagType:BOOL | 503) + USER_AUTH_TYPE = 0x101f8; // (TagType:ENUM | 504) + AUTH_TIMEOUT = 0x301f9; // (TagType:UINT | 505) + ALLOW_WHILE_ON_BODY = 0x701fa; // (TagType:BOOL | 506) + TRUSTED_USER_PRESENCE_REQUIRED = 0x701fb; // (TagType:BOOL | 507) + TRUSTED_CONFIRMATION_REQUIRED = 0x701fc; // (TagType:BOOL | 508) + UNLOCKED_DEVICE_REQUIRED = 0x701fd; // (TagType:BOOL | 509) + /* RESERVED: ALL_APPLICATIONS = 0x70258; // (TagType:BOOL | 600) */ + APPLICATION_ID = 0x90259; // (TagType:BYTES | 601) + /* RESERVED: EXPORTABLE = 0x7025a; // (TagType:BOOL | 602) */ + APPLICATION_DATA = 0x902bc; // (TagType:BYTES | 700) + CREATION_DATETIME = 0x602bd; // (TagType:DATE | 701) + ORIGIN = 0x102be; // (TagType:ENUM | 702) + /* RESERVED: ROLLBACK_RESISTANT = 0x702bf; // (TagType:BOOL | 703) */ + ROOT_OF_TRUST = 0x902c0; // (TagType:BYTES | 704) + OS_VERSION = 0x302c1; // (TagType:UINT | 705) + OS_PATCHLEVEL = 0x302c2; // (TagType:UINT | 706) + UNIQUE_ID = 0x902c3; // (TagType:BYTES | 707) + ATTESTATION_CHALLENGE = 0x902c4; // (TagType:BYTES | 708) + ATTESTATION_APPLICATION_ID = 0x902c5; // (TagType:BYTES | 709) + ATTESTATION_ID_BRAND = 0x902c6; // (TagType:BYTES | 710) + ATTESTATION_ID_DEVICE = 0x902c7; // (TagType:BYTES | 711) + ATTESTATION_ID_PRODUCT = 0x902c8; // (TagType:BYTES | 712) + ATTESTATION_ID_SERIAL = 0x902c9; // (TagType:BYTES | 713) + ATTESTATION_ID_IMEI = 0x902ca; // (TagType:BYTES | 714) + ATTESTATION_ID_MEID = 0x902cb; // (TagType:BYTES | 715) + ATTESTATION_ID_MANUFACTURER = 0x902cc; // (TagType:BYTES | 716) + ATTESTATION_ID_MODEL = 0x902cd; // (TagType:BYTES | 717) + VENDOR_PATCHLEVEL = 0x302ce; // (TagType:UINT | 718) + BOOT_PATCHLEVEL = 0x302cf; // (TagType:UINT | 719) + DEVICE_UNIQUE_ATTESTATION = 0x702d0; // (TagType:BOOL | 720) + IDENTITY_CREDENTIAL_KEY = 0x702d1; // (TagType:BOOL | 721) + STORAGE_KEY = 0x702d2; // (TagType:BOOL | 722) + ATTESTATION_ID_SECOND_IMEI = 0x902d3; // (TagType:BYTES | 723) + ASSOCIATED_DATA = 0x903e8; // (TagType:BYTES | 1000) + NONCE = 0x903e9; // (TagType:BYTES | 1001) + /* RESERVED: AUTH_TOKEN = 0x903ea; // (TagType:BYTES | 1002) */ + MAC_LENGTH = 0x303eb; // (TagType:UINT | 1003) + RESET_SINCE_ID_ROTATION = 0x703ec; // (TagType:BOOL | 1004) + CONFIRMATION_TOKEN = 0x903ed; // (TagType:BYTES | 1005) + CERTIFICATE_SERIAL = 0x803ee; // (TagType:BIGNUM | 1006) + CERTIFICATE_SUBJECT = 0x903ef; // (TagType:BYTES | 1007) +}; + +enum Algorithm { + RSA = 0; + EC = 1; + AES = 2; + DES = 3; + HMAC = 4; + ALGORITHM_MAX = 5; +}; + +enum BlockMode { + ECB = 0; + CBC = 1; + CTR = 2; + GCM = 3; + BLOCK_MODE_MAX = 4; +}; + +enum PaddingMode { + PADDING_NONE = 0; + PADDING_RSA_OAEP = 1; + PADDING_RSA_PSS = 2; + PADDING_RSA_PKCS1_1_5_ENCRYPT = 3; + PADDING_RSA_PKCS1_1_5_SIGN = 4; + PADDING_PKCS7 = 5; + PADDING_MODE_MAX = 6; +}; + +enum Digest { + DIGEST_NONE = 0; + DIGEST_MD5 = 1; + DIGEST_SHA1 = 2; + DIGEST_SHA_2_224 = 3; + DIGEST_SHA_2_256 = 4; + DIGEST_SHA_2_384 = 5; + DIGEST_SHA_2_512 = 6; + DIGEST_MAX = 7; +}; + +enum EcCurve { + P_224 = 0; + P_256 = 1; + P_384 = 2; + P_521 = 3; + EC_CURVE_MAX = 4; +}; + +enum KeyOrigin { + GENERATED = 0; + DERIVED = 1; + IMPORTED = 2; + UNKNOWN = 3; + SECURELY_IMPORTED = 4; + KEY_ORIGIN_MAX = 5; +}; + +enum KeyBlobUsageRequirements { + STANDALONE = 0; + REQUIRES_FILE_SYSTEM = 1; + KEY_USAGE_MAX = 2; +}; + +enum KeyPurpose { + ENCRYPT = 0; + DECRYPT = 1; + SIGN = 2; + VERIFY = 3; + /* RESERVED: DERIVE_KEY = 4; */ + WRAP_KEY = 5; + AGREE_KEY = 6; + ATTEST_KEY = 7; + PURPOSE_MAX = 8; +}; + +enum ErrorCode { + OK = 0; + ROOT_OF_TRUST_ALREADY_SET = 1; + UNSUPPORTED_PURPOSE = 2; + INCOMPATIBLE_PURPOSE = 3; + UNSUPPORTED_ALGORITHM = 4; + INCOMPATIBLE_ALGORITHM = 5; + UNSUPPORTED_KEY_SIZE = 6; + UNSUPPORTED_BLOCK_MODE = 7; + INCOMPATIBLE_BLOCK_MODE = 8; + UNSUPPORTED_MAC_LENGTH = 9; + UNSUPPORTED_PADDING_MODE = 10; + INCOMPATIBLE_PADDING_MODE = 11; + UNSUPPORTED_DIGEST = 12; + INCOMPATIBLE_DIGEST = 13; + INVALID_EXPIRATION_TIME = 14; + INVALID_USER_ID = 15; + INVALID_AUTHORIZATION_TIMEOUT = 16; + UNSUPPORTED_KEY_FORMAT = 17; + INCOMPATIBLE_KEY_FORMAT = 18; + UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = 19; + UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = 20; + INVALID_INPUT_LENGTH = 21; + KEY_EXPORT_OPTIONS_INVALID = 22; + DELEGATION_NOT_ALLOWED = 23; + KEY_NOT_YET_VALID = 24; + KEY_EXPIRED = 25; + KEY_USER_NOT_AUTHENTICATED = 26; + OUTPUT_PARAMETER_NULL = 27; + INVALID_OPERATION_HANDLE = 28; + INSUFFICIENT_BUFFER_SPACE = 29; + VERIFICATION_FAILED = 30; + TOO_MANY_OPERATIONS = 31; + UNEXPECTED_NULL_POINTER = 32; + INVALID_KEY_BLOB = 33; + IMPORTED_KEY_NOT_ENCRYPTED = 34; + IMPORTED_KEY_DECRYPTION_FAILED = 35; + IMPORTED_KEY_NOT_SIGNED = 36; + IMPORTED_KEY_VERIFICATION_FAILED = 37; + INVALID_ARGUMENT = 38; + UNSUPPORTED_TAG = 39; + INVALID_TAG = 40; + MEMORY_ALLOCATION_FAILED = 41; + IMPORT_PARAMETER_MISMATCH = 42; + SECURE_HW_ACCESS_DENIED = 43; + OPERATION_CANCELLED = 44; + CONCURRENT_ACCESS_CONFLICT = 45; + SECURE_HW_BUSY = 46; + SECURE_HW_COMMUNICATION_FAILED = 47; + UNSUPPORTED_EC_FIELD = 48; + MISSING_NONCE = 49; + INVALID_NONCE = 50; + MISSING_MAC_LENGTH = 51; + KEY_RATE_LIMIT_EXCEEDED = 52; + CALLER_NONCE_PROHIBITED = 53; + KEY_MAX_OPS_EXCEEDED = 54; + INVALID_MAC_LENGTH = 55; + MISSING_MIN_MAC_LENGTH = 56; + UNSUPPORTED_MIN_MAC_LENGTH = 57; + UNSUPPORTED_KDF = 58; + UNSUPPORTED_EC_CURVE = 59; + KEY_REQUIRES_UPGRADE = 60; + ATTESTATION_CHALLENGE_MISSING = 61; + KEYMASTER_NOT_CONFIGURED = 62; + ATTESTATION_APPLICATION_ID_MISSING = 63; + CANNOT_ATTEST_IDS = 64; + UNIMPLEMENTED = 65; + VERSION_MISMATCH = 66; + ROLLBACK_RESISTANCE_UNAVAILABLE = 67; + HARDWARE_TYPE_UNAVAILABLE = 68; + PROOF_OF_PRESENCE_REQUIRED = 69; + CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = 70; + UNKNOWN_ERROR = 71; + INVALID_DEVICE_IDS = 72; // Vendor specific. + PRODUCTION_MODE_PROVISIONING = 73; // Vendor specific. + NO_USER_CONFIRMATION = 74; + KEY_UPGRADE_NOT_REQUIRED = 75; // Vendor specific. + DEVICE_LOCKED = 76; + EARLY_BOOT_ENDED = 77; + ATTESTATION_KEYS_NOT_PROVISIONED = 78; + ATTESTATION_IDS_NOT_PROVISIONED = 79; + INVALID_OPERATION = 80; + STORAGE_KEY_UNSUPPORTED = 81; + INCOMPATIBLE_MGF_DIGEST = 82; + UNSUPPORTED_MGF_DIGEST = 83; + INVALID_MAC = 84; // RKP specific. + PRODUCTION_KEY_IN_TEST_REQUEST = 85; // RKP specific. + TEST_KEY_IN_PRODUCTION_REQUEST = 86; // RKP specific. + INVALID_EEK = 87; // RKP specific. +}; + +enum SecurityLevel { + SOFTWARE = 0; + TRUSTED_ENVIRONMENT = 1; + STRONGBOX = 2; +}; + +// NOTE: these enum values must be kept in sync with the HAL, +// as they are used in an HMAC calculation. +enum HardwareAuthenticatorType { + HW_AUTH_NONE = 0; + HW_AUTH_PASSWORD = 1; + HW_AUTH_FINGERPRINT = 2; + // Additional entries must be powers of 2. +}; + +enum KeyFormat { + X509 = 0; /* for public key export */ + PKCS8 = 1; /* for asymmetric key pair import */ + RAW = 3; /* for symmetric key import and export*/ +} + +enum DTupError { + DTUP_OK = 0; + DTUP_NO_EVENT = 1; +} + +/* matches Linux event device codes */ +enum DTupKeyEvent { + DTUP_RESERVED = 0; + DTUP_VOL_DOWN = 114; + DTUP_VOL_UP = 115; + DTUP_PWR = 116; +} + +enum BootColor { + BOOT_VERIFIED_GREEN = 0; + BOOT_SELFSIGNED_YELLOW = 1; + BOOT_UNVERIFIED_ORANGE = 2; + BOOT_VERIFY_FAILED_RED = 3; +} + +enum ChipFusing { + FUSING_PROTO = 0; + FUSING_DVT = 1; + FUSING_PVT = 2; // Strongbox gen v0 certs. + FUSING_PVT_1 = 3; // Strongbox gen v1 certs. + FUSING_D_PVT = 4; // Dauntless gen v0 certs. + FUSING_D_PVT_1 = 5; // Dauntless gen v1 certs. + FUSING_D_PVT_2 = 6; // Dauntless gen v2 certs (D3M2). +} + +enum CertificateStatus { + CERT_PREVIOUSLY_PROVISIONED = 0; + CERT_MISSING = 1; + CERT_CHECKSUM = 2; + CERT_UNKNOWN_ERROR = 3; + CERT_WRONG_PACKET = 4; +} + +enum RkpCsrV2Operation { + RKP_CSR_V2_BEGIN = 0; + RKP_CSR_V2_UPDATE = 1; + RKP_CSR_V2_FINISH = 2; +} diff --git a/nugget/proto/nugget/app/keymaster/ctdl/keymaster_types.options b/nugget/proto/nugget/app/keymaster/ctdl/keymaster_types.options new file mode 100644 index 0000000..b38e786 --- /dev/null +++ b/nugget/proto/nugget/app/keymaster/ctdl/keymaster_types.options @@ -0,0 +1,12 @@ +nugget.app.keymaster.ctdl.KeyParameters.params max_count:20 +nugget.app.keymaster.ctdl.HmacSharingParameters.seed max_size:32 +nugget.app.keymaster.ctdl.HmacSharingParameters.nonce max_size:32 +nugget.app.keymaster.ctdl.HardwareAuthToken.mac max_size:32 +nugget.app.keymaster.ctdl.VerificationToken.mac max_size:32 +nugget.app.keymaster.ctdl.VigoKey.x max_size:64 +nugget.app.keymaster.ctdl.VigoSignature.r max_size:32 +nugget.app.keymaster.ctdl.VigoSignature.s max_size:32 +nugget.app.keymaster.ctdl.VigoSecret.material max_size:32 +nugget.app.keymaster.ctdl.VigoSecret.iv max_size:16 +nugget.app.keymaster.ctdl.VigoSecret.tag max_size:16 +nugget.app.keymaster.ctdl.KeysToSign.keys max_count:20 diff --git a/nugget/proto/nugget/app/keymaster/ctdl/keymaster_types.proto b/nugget/proto/nugget/app/keymaster/ctdl/keymaster_types.proto new file mode 100644 index 0000000..6a8f5a8 --- /dev/null +++ b/nugget/proto/nugget/app/keymaster/ctdl/keymaster_types.proto @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2017 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. + */ + +syntax = "proto3"; + +package nugget.app.keymaster.ctdl; + +import "nugget/app/keymaster/ctdl/keymaster_defs.proto"; + +message KeyParameter { + Tag tag = 1; /* Possible values defined here + * ::android::hardware::keymaster::V3_0::Tag + */ + uint32 integer = 2; + uint64 long_integer = 3; + bytes blob = 4; +} + +message KeyParameters { + repeated KeyParameter params = 1; +} + +message KeyBlob { + bytes blob = 1; +} + +message OperationHandle { + uint64 handle = 1; +} + +message Certificate { + bytes data = 1; +} + +message CertificateChain { + repeated Certificate certificates = 1; +} + +message KeyCharacteristics { + KeyParameters software_enforced = 1; + KeyParameters tee_enforced = 2; +} + +message HmacSharingParameters { + bytes seed = 1; + bytes nonce = 2; +} + +message HardwareAuthToken { + uint64 challenge = 1; + uint64 user_id = 2; + uint64 authenticator_id = 3; + // Deprecated in favor of tag 7. + // HardwareAuthenticatorType authenticator_type = 4; + uint64 timestamp = 5; + bytes mac = 6; + uint32 authenticator_type = 7; +} + +message VerificationToken { + uint64 challenge = 1; + uint64 timestamp = 2; + KeyParameters params_verified = 3; + SecurityLevel security_level = 4; + bytes mac = 5; +} + +/* + * Internal types. + */ +message RSAKey { + uint32 e = 1; + bytes d = 2; + bytes n = 3; +} + +message ECKey { + /* TODO: should this be EcCurve. */ + uint32 curve_id = 1; + bytes d = 2; + bytes x = 3; + bytes y = 4; +} + +message SymmetricKey { + bytes material = 1; +} + +enum PresharedSecretStatus { + NOT_SET = 0; + ALREADY_SET = 1; +} + +enum AttestationSelector { + ATTEST_TEST = 0; + ATTEST_BATCH = 1; + ATTEST_INDIVIDUAL = 2; + ATTEST_SELF = 3; + ATTEST_CALLER = 4; +} + +message VigoKey { + bytes x = 1; +} + +message VigoSignature { + bytes r = 1; + bytes s = 2; +} + +message VigoSecret { + bytes material = 1; + bytes iv = 2; + bytes tag = 3; +} + +message MacedKey{ + bytes blob = 1; +} + +message KeysToSign { + repeated MacedKey keys = 1; +} diff --git a/nugget/proto/nugget/app/keymaster/keymaster.proto b/nugget/proto/nugget/app/keymaster/keymaster.proto index 89710e6..496018a 100644 --- a/nugget/proto/nugget/app/keymaster/keymaster.proto +++ b/nugget/proto/nugget/app/keymaster/keymaster.proto @@ -149,6 +149,15 @@ service Keymaster { rpc GenerateRkpKey(GenerateRkpKeyRequest) returns (GenerateRkpKeyResponse); rpc GenerateRkpCsr(GenerateRkpCsrRequest) returns (GenerateRkpCsrResponse); + /* + * Vendor specific method. To export IMEI/DSU to trusty only + */ + rpc ExportDeviceIds(ExportDeviceIdsRequest) returns (ExportDeviceIdsResponse); + + /* + * RKP v3 implementation + */ + rpc GenerateRkpCsrV2(GenerateRkpCsrV2Request) returns (GenerateRkpCsrV2Response); // These are implemented with a enum, so new RPCs must be appended, and // deprecated RPCs need placeholders. } @@ -431,6 +440,7 @@ message ProvisionDeviceIdsRequest { bytes product_model = 6; bytes imei = 7; bytes meid = 8; + bytes imei2 = 9; } message ProvisionDeviceIdsResponse { // Specified in keymaster_defs.proto:ErrorCode @@ -439,6 +449,24 @@ message ProvisionDeviceIdsResponse { bool nodelocked_ro = 3; } +message ExportDeviceIdsRequest { + bytes challenge = 1; + bytes challenge_hmac = 2; +} + +message ExportDeviceIdsResponse { + ErrorCode error_code = 1; + bytes product_brand = 2; + bytes product_device = 3; + bytes product_name = 4; + bytes serialno = 5; + bytes product_manufacturer = 6; + bytes product_model = 7; + bytes imei = 8; + bytes meid = 9; + bytes ids_hmac = 10; +} + // ReadTeeBatchCertificate // Only callable at the Device Factory message ReadTeeBatchCertificateRequest { @@ -473,6 +501,7 @@ message SetSystemVersionInfoRequest { uint32 system_version = 1; // getprop "ro.build.version.release" uint32 system_security_level = 2; // getprop "ro.build.version.security_patch" uint32 vendor_security_level = 3; // getprop "ro.vendor.build.security_patch" + uint32 vendor_api_level = 4; } message SetSystemVersionInfoResponse { @@ -612,3 +641,18 @@ message GenerateRkpCsrResponse{ bytes device_info_blob = 3; bytes protected_data_blob = 4; } + +message GenerateRkpCsrV2Request{ + RkpCsrV2Operation step = 1; + bytes challenge = 2; + uint32 num_of_public_keys = 3; + MacedKey key_to_sign = 4; + OperationHandle handle = 5; +} +message GenerateRkpCsrV2Response{ + ErrorCode error_code = 1; + OperationHandle handle = 2; + bytes device_info_blob = 3; + bytes dice_cert_chain = 4; + bytes signature = 5; +} diff --git a/nugget/proto/nugget/app/keymaster/keymaster_defs.proto b/nugget/proto/nugget/app/keymaster/keymaster_defs.proto index dfdfeeb..db352c7 100644 --- a/nugget/proto/nugget/app/keymaster/keymaster_defs.proto +++ b/nugget/proto/nugget/app/keymaster/keymaster_defs.proto @@ -99,6 +99,7 @@ enum Tag { DEVICE_UNIQUE_ATTESTATION = 0x702d0; // (TagType:BOOL | 720) IDENTITY_CREDENTIAL_KEY = 0x702d1; // (TagType:BOOL | 721) STORAGE_KEY = 0x702d2; // (TagType:BOOL | 722) + ATTESTATION_ID_SECOND_IMEI = 0x902d3; // (TagType:BYTES | 723) ASSOCIATED_DATA = 0x903e8; // (TagType:BYTES | 1000) NONCE = 0x903e9; // (TagType:BYTES | 1001) /* RESERVED: AUTH_TOKEN = 0x903ea; // (TagType:BYTES | 1002) */ @@ -331,3 +332,9 @@ enum CertificateStatus { CERT_UNKNOWN_ERROR = 3; CERT_WRONG_PACKET = 4; } + +enum RkpCsrV2Operation { + RKP_CSR_V2_BEGIN = 0; + RKP_CSR_V2_UPDATE = 1; + RKP_CSR_V2_FINISH = 2; +} diff --git a/nugget/proto/nugget/app/keymaster/keymaster_types.options b/nugget/proto/nugget/app/keymaster/keymaster_types.options index 417e181..6ffce96 100644 --- a/nugget/proto/nugget/app/keymaster/keymaster_types.options +++ b/nugget/proto/nugget/app/keymaster/keymaster_types.options @@ -1,4 +1,4 @@ -nugget.app.keymaster.KeyParameters.params max_count:20 +nugget.app.keymaster.KeyParameters.params max_count:25 nugget.app.keymaster.HmacSharingParameters.seed max_size:32 nugget.app.keymaster.HmacSharingParameters.nonce max_size:32 nugget.app.keymaster.HardwareAuthToken.mac max_size:32 diff --git a/nugget/proto/nugget/app/weaver/Android.bp b/nugget/proto/nugget/app/weaver/Android.bp index 6a1dbde..1c4535a 100644 --- a/nugget/proto/nugget/app/weaver/Android.bp +++ b/nugget/proto/nugget/app/weaver/Android.bp @@ -26,7 +26,11 @@ package { genrule { name: "nos_app_weaver_service_genc++", out: ["Weaver.client.cpp"], - srcs: ["weaver.proto"], + srcs: [ + "weaver.proto", + ":nugget_options_proto", + ":libprotobuf-internal-protos", + ], tools: ["aprotoc", "protoc-gen-nos-client-cpp"], cmd: GEN_SERVICE_SOURCE, } @@ -34,7 +38,11 @@ genrule { genrule { name: "nos_app_weaver_service_genc++_headers", out: ["Weaver.client.h"], - srcs: ["weaver.proto"], + srcs: [ + "weaver.proto", + ":nugget_options_proto", + ":libprotobuf-internal-protos", + ], tools: ["aprotoc", "protoc-gen-nos-client-cpp"], cmd: GEN_SERVICE_HEADER, } @@ -42,7 +50,11 @@ genrule { genrule { name: "nos_app_weaver_service_genc++_mock", out: ["MockWeaver.client.h"], - srcs: ["weaver.proto"], + srcs: [ + "weaver.proto", + ":nugget_options_proto", + ":libprotobuf-internal-protos", + ], tools: ["aprotoc", "protoc-gen-nos-client-cpp"], cmd: GEN_SERVICE_MOCK, } |