1 /*
2 * Copyright 2022 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 */
16
17 #include <android-base/file.h>
18 #include <android-base/logging.h>
19 #include <unistd.h>
20 #include <vm_payload_restricted.h>
21
22 #include <string_view>
23 #include <vector>
24
25 #include "compos_key.h"
26
27 using android::base::Error;
28 using android::base::ReadFdToString;
29 using android::base::Result;
30 using android::base::WriteFully;
31 using namespace std::literals;
32 using compos_key::Ed25519KeyPair;
33 using compos_key::Seed;
34
35 namespace {
36
37 constexpr const char* kSigningKeySeedIdentifier = "CompOS signing key seed";
38
getSigningKey()39 Result<Ed25519KeyPair> getSigningKey() {
40 Seed seed;
41 AVmPayload_getVmInstanceSecret(kSigningKeySeedIdentifier, strlen(kSigningKeySeedIdentifier),
42 seed.data(), seed.size());
43 return compos_key::keyFromSeed(seed);
44 }
45
write_public_key()46 int write_public_key() {
47 auto key_pair = getSigningKey();
48 if (!key_pair.ok()) {
49 LOG(ERROR) << key_pair.error();
50 return 1;
51 }
52 if (!WriteFully(STDOUT_FILENO, key_pair->public_key.data(), key_pair->public_key.size())) {
53 PLOG(ERROR) << "Write failed";
54 return 1;
55 }
56 return 0;
57 }
58
write_bcc()59 int write_bcc() {
60 size_t bcc_size = AVmPayload_getDiceAttestationChain(nullptr, 0);
61 std::vector<uint8_t> bcc(bcc_size);
62 AVmPayload_getDiceAttestationChain(bcc.data(), bcc.size());
63
64 if (!WriteFully(STDOUT_FILENO, bcc.data(), bcc.size())) {
65 PLOG(ERROR) << "Write failed";
66 return 1;
67 }
68
69 return 0;
70 }
71
sign_input()72 int sign_input() {
73 std::string to_sign;
74 if (!ReadFdToString(STDIN_FILENO, &to_sign)) {
75 PLOG(ERROR) << "Read failed";
76 return 1;
77 }
78
79 auto key_pair = getSigningKey();
80 if (!key_pair.ok()) {
81 LOG(ERROR) << key_pair.error();
82 return 1;
83 }
84
85 auto signature =
86 compos_key::sign(key_pair->private_key,
87 reinterpret_cast<const uint8_t*>(to_sign.data()), to_sign.size());
88 if (!signature.ok()) {
89 LOG(ERROR) << signature.error();
90 return 1;
91 }
92
93 if (!WriteFully(STDOUT_FILENO, signature->data(), signature->size())) {
94 PLOG(ERROR) << "Write failed";
95 return 1;
96 }
97 return 0;
98 }
99 } // namespace
100
main(int argc,char ** argv)101 int main(int argc, char** argv) {
102 android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
103
104 if (argc == 2) {
105 if (argv[1] == "public_key"sv) {
106 return write_public_key();
107 } else if (argv[1] == "bcc"sv) {
108 return write_bcc();
109 } else if (argv[1] == "sign"sv) {
110 return sign_input();
111 }
112 }
113
114 LOG(INFO) << "Usage: compos_key_helper <command>. Available commands are:\n"
115 "public_key Write current public key to stdout\n"
116 "sign Consume stdin, sign it and write signature to stdout\n";
117 return 1;
118 }
119