blob: ed9503a46a4be0ce89e8b333ad1b9b78202cd69f [file] [log] [blame]
Jiyong Parka7266ac2021-05-17 21:57:24 +09001/*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Andrew Scull66616612021-06-17 16:41:03 +000016#include <aidl/android/system/keystore2/IKeystoreService.h>
Andrew Scull11cf0902021-06-22 12:08:10 +000017#include <android-base/result.h>
Andrew Scull66616612021-06-17 16:41:03 +000018#include <android/binder_auto_utils.h>
19#include <android/binder_manager.h>
Jiyong Parka7266ac2021-05-17 21:57:24 +090020#include <stdio.h>
Jiyong Park23934392021-06-16 01:59:10 +090021#include <sys/system_properties.h>
Jiyong Parka7266ac2021-05-17 21:57:24 +090022
Andrew Scull11cf0902021-06-22 12:08:10 +000023using aidl::android::hardware::security::keymint::Algorithm;
24using aidl::android::hardware::security::keymint::Digest;
25using aidl::android::hardware::security::keymint::KeyParameter;
26using aidl::android::hardware::security::keymint::KeyParameterValue;
27using aidl::android::hardware::security::keymint::KeyPurpose;
Andrew Scull66616612021-06-17 16:41:03 +000028using aidl::android::hardware::security::keymint::SecurityLevel;
Andrew Scull11cf0902021-06-22 12:08:10 +000029using aidl::android::hardware::security::keymint::Tag;
Andrew Scull66616612021-06-17 16:41:03 +000030
Andrew Scull11cf0902021-06-22 12:08:10 +000031using aidl::android::system::keystore2::CreateOperationResponse;
32using aidl::android::system::keystore2::Domain;
Andrew Scull66616612021-06-17 16:41:03 +000033using aidl::android::system::keystore2::IKeystoreSecurityLevel;
34using aidl::android::system::keystore2::IKeystoreService;
Andrew Scull11cf0902021-06-22 12:08:10 +000035using aidl::android::system::keystore2::KeyDescriptor;
36using aidl::android::system::keystore2::KeyMetadata;
37
38using android::base::Error;
39using android::base::Result;
Andrew Scull66616612021-06-17 16:41:03 +000040
Jiyong Parkfe5b28e2021-06-24 00:19:02 +090041extern void testlib_sub();
42
Andrew Scull66616612021-06-17 16:41:03 +000043namespace {
44
Andrew Scull11cf0902021-06-22 12:08:10 +000045Result<void> test_keystore() {
46 // Connect to Keystore.
Andrew Scull66616612021-06-17 16:41:03 +000047 ndk::SpAIBinder binder(
48 AServiceManager_getService("android.system.keystore2.IKeystoreService/default"));
49 auto service = IKeystoreService::fromBinder(binder);
50 if (service == nullptr) {
Andrew Scull11cf0902021-06-22 12:08:10 +000051 return Error() << "Failed to find Keystore";
Andrew Scull66616612021-06-17 16:41:03 +000052 }
53 std::shared_ptr<IKeystoreSecurityLevel> securityLevel;
54 auto status = service->getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT, &securityLevel);
55 if (!status.isOk()) {
Andrew Scull11cf0902021-06-22 12:08:10 +000056 return Error() << "Failed to get security level";
Andrew Scull66616612021-06-17 16:41:03 +000057 }
Andrew Scull11cf0902021-06-22 12:08:10 +000058
59 // Create a signing key.
60 std::vector<KeyParameter> params;
61
62 KeyParameter algo;
63 algo.tag = Tag::ALGORITHM;
64 algo.value = KeyParameterValue::make<KeyParameterValue::algorithm>(Algorithm::HMAC);
65 params.push_back(algo);
66
67 KeyParameter key_size;
68 key_size.tag = Tag::KEY_SIZE;
69 key_size.value = KeyParameterValue::make<KeyParameterValue::integer>(256);
70 params.push_back(key_size);
71
72 KeyParameter min_mac_length;
73 min_mac_length.tag = Tag::MIN_MAC_LENGTH;
74 min_mac_length.value = KeyParameterValue::make<KeyParameterValue::integer>(256);
75 params.push_back(min_mac_length);
76
77 KeyParameter digest;
78 digest.tag = Tag::DIGEST;
79 digest.value = KeyParameterValue::make<KeyParameterValue::digest>(Digest::SHA_2_256);
80 params.push_back(digest);
81
82 KeyParameter purposeSign;
83 purposeSign.tag = Tag::PURPOSE;
84 purposeSign.value = KeyParameterValue::make<KeyParameterValue::keyPurpose>(KeyPurpose::SIGN);
85 params.push_back(purposeSign);
86
87 KeyParameter purposeVerify;
88 purposeVerify.tag = Tag::PURPOSE;
89 purposeVerify.value =
90 KeyParameterValue::make<KeyParameterValue::keyPurpose>(KeyPurpose::VERIFY);
91 params.push_back(purposeVerify);
92
93 KeyParameter auth;
94 auth.tag = Tag::NO_AUTH_REQUIRED;
95 auth.value = KeyParameterValue::make<KeyParameterValue::boolValue>(true);
96 params.push_back(auth);
97
98 KeyDescriptor descriptor;
99 descriptor.domain = Domain::SELINUX;
100 descriptor.alias = "payload-test-key";
101 descriptor.nspace = 140; // vm_payload_key
102
103 KeyMetadata metadata;
104 status = securityLevel->generateKey(descriptor, {}, params, 0, {}, &metadata);
105 if (!status.isOk()) {
106 return Error() << "Failed to create new HMAC key";
107 }
108
109 // Sign something.
110 params.clear();
111 params.push_back(algo);
112 params.push_back(digest);
113 params.push_back(purposeSign);
114
115 KeyParameter mac_length;
116 mac_length.tag = Tag::MAC_LENGTH;
117 mac_length.value = KeyParameterValue::make<KeyParameterValue::integer>(256);
118 params.push_back(mac_length);
119
120 CreateOperationResponse opResponse;
121 status = securityLevel->createOperation(descriptor, params, false, &opResponse);
122 if (!status.isOk()) {
123 return Error() << "Failed to create keystore signing operation: "
124 << status.getServiceSpecificError();
125 }
126 auto operation = opResponse.iOperation;
127
128 std::string message = "This is the message to sign";
129 std::optional<std::vector<uint8_t>> out;
130 status = operation->update({message.begin(), message.end()}, &out);
131 if (!status.isOk()) {
132 return Error() << "Failed to call keystore update operation.";
133 }
134
135 std::optional<std::vector<uint8_t>> signature;
136 status = operation->finish({}, {}, &signature);
137 if (!status.isOk()) {
138 return Error() << "Failed to call keystore finish operation.";
139 }
140
141 if (!signature.has_value()) {
142 return Error() << "Didn't receive a signature from keystore finish operation.";
143 }
144
145 // Verify the signature.
146 params.clear();
147 params.push_back(algo);
148 params.push_back(digest);
149 params.push_back(purposeVerify);
150
151 status = securityLevel->createOperation(descriptor, params, false, &opResponse);
152 if (!status.isOk()) {
153 return Error() << "Failed to create keystore verification operation: "
154 << status.getServiceSpecificError();
155 }
156 operation = opResponse.iOperation;
157
158 status = operation->update({message.begin(), message.end()}, &out);
159 if (!status.isOk()) {
160 return Error() << "Failed to call keystore update operation.";
161 }
162
163 std::optional<std::vector<uint8_t>> out_signature;
164 status = operation->finish({}, signature.value(), &out_signature);
165 if (!status.isOk()) {
166 return Error() << "Failed to call keystore finish operation.";
167 }
168
169 return {};
170}
171
172template <typename T>
Andrew Sculledbe75e2021-07-06 10:44:31 +0000173Result<T> report_test(std::string name, Result<T> result) {
Andrew Scull11cf0902021-06-22 12:08:10 +0000174 auto property = "debug.microdroid.test." + name;
175 std::stringstream outcome;
176 if (result.ok()) {
177 outcome << "PASS";
178 } else {
179 outcome << "FAIL: " << result.error();
180 // Pollute stdout with the error in case the property is truncated.
181 std::cout << "[" << name << "] test failed: " << result.error() << "\n";
182 }
183 __system_property_set(property.c_str(), outcome.str().c_str());
Andrew Sculledbe75e2021-07-06 10:44:31 +0000184 return result;
Andrew Scull66616612021-06-17 16:41:03 +0000185}
186
187} // Anonymous namespace
188
Jiyong Park40699612021-05-24 16:55:06 +0900189extern "C" int android_native_main(int argc, char* argv[]) {
190 printf("Hello Microdroid ");
191 for (int i = 0; i < argc; i++) {
192 printf("%s", argv[i]);
193 bool last = i == (argc - 1);
194 if (!last) {
195 printf(" ");
196 }
197 }
Jiyong Parkfe5b28e2021-06-24 00:19:02 +0900198 testlib_sub();
Jiyong Park40699612021-05-24 16:55:06 +0900199 printf("\n");
Jiyong Park23934392021-06-16 01:59:10 +0900200
201 __system_property_set("debug.microdroid.app.run", "true");
Andrew Sculledbe75e2021-07-06 10:44:31 +0000202 if (!report_test("keystore", test_keystore()).ok()) return 1;
203
Jiyong Park40699612021-05-24 16:55:06 +0900204 return 0;
Jiyong Parka7266ac2021-05-17 21:57:24 +0900205}