1 /*
2 * Copyright (C) 2020 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 <getopt.h>
18
19 #include <string>
20
21 #include <android-base/properties.h>
22 #include <trusty_keymaster/ipc/trusty_keymaster_ipc.h>
23
24 namespace {
25
26 const char* sopts = "hb:d:p:s:M:m:i:c:";
27 const struct option lopts[] = {
28 {"help", no_argument, nullptr, 'h'},
29 {"brand", required_argument, nullptr, 'b'},
30 {"device", required_argument, nullptr, 'd'},
31 {"product", required_argument, nullptr, 'p'},
32 {"serial", required_argument, nullptr, 's'},
33 {"manufacturer", required_argument, nullptr, 'M'},
34 {"model", required_argument, nullptr, 'm'},
35 {"imei", required_argument, nullptr, 'i'},
36 {"meid", required_argument, nullptr, 'c'},
37 {0, 0, 0, 0},
38 };
39
buf2string(const keymaster::Buffer & buf)40 std::string buf2string(const keymaster::Buffer& buf) {
41 return std::string(reinterpret_cast<const char*>(buf.peek_read()), buf.available_read());
42 }
43
print_usage(const char * prog,const keymaster::SetAttestationIdsRequest & req)44 void print_usage(const char* prog, const keymaster::SetAttestationIdsRequest& req) {
45 fprintf(stderr,
46 "Usage: %s [options]\n"
47 "\n"
48 "options:\n"
49 " -h, --help prints this message and exit\n"
50 " -b, --brand <val> set brand (default '%s')\n"
51 " -d, --device <val> set device (default '%s')\n"
52 " -p, --product <val> set product (default '%s')\n"
53 " -s, --serial <val> set serial (default '%s')\n"
54 " -M, --manufacturer <val> set manufacturer (default '%s')\n"
55 " -m, --model <val> set model (default '%s')\n"
56 " -i, --imei <val> set IMEI (default '%s')\n"
57 " -c, --meid <val> set MEID (default '%s')\n"
58 "\n",
59 prog, buf2string(req.brand).c_str(), buf2string(req.device).c_str(),
60 buf2string(req.product).c_str(), buf2string(req.serial).c_str(),
61 buf2string(req.manufacturer).c_str(), buf2string(req.model).c_str(),
62 buf2string(req.imei).c_str(), buf2string(req.meid).c_str());
63 }
64
set_from_prop(keymaster::Buffer * buf,const std::string & prop)65 void set_from_prop(keymaster::Buffer* buf, const std::string& prop) {
66 std::string prop_value = ::android::base::GetProperty(prop, /* default_value = */ "");
67 if (!prop_value.empty()) {
68 buf->Reinitialize(prop_value.data(), prop_value.size());
69 }
70 }
71
populate_ids(keymaster::SetAttestationIdsRequest * req)72 void populate_ids(keymaster::SetAttestationIdsRequest* req) {
73 set_from_prop(&req->brand, "ro.product.brand");
74 set_from_prop(&req->device, "ro.product.device");
75 set_from_prop(&req->product, "ro.product.name");
76 set_from_prop(&req->serial, "ro.serialno");
77 set_from_prop(&req->manufacturer, "ro.product.manufacturer");
78 set_from_prop(&req->model, "ro.product.model");
79 }
80
81 } // namespace
82
main(int argc,char ** argv)83 int main(int argc, char** argv) {
84 // By default, set attestation IDs to the values in userspace properties.
85 keymaster::SetAttestationIdsRequest req(/* ver = */ 4);
86 populate_ids(&req);
87
88 while (true) {
89 int oidx = 0;
90 int c = getopt_long(argc, argv, sopts, lopts, &oidx);
91 if (c == -1) {
92 break; /* done */
93 }
94
95 switch (c) {
96 case 'b':
97 req.brand.Reinitialize(optarg, strlen(optarg));
98 break;
99 case 'd':
100 req.device.Reinitialize(optarg, strlen(optarg));
101 break;
102 case 'p':
103 req.product.Reinitialize(optarg, strlen(optarg));
104 break;
105 case 's':
106 req.serial.Reinitialize(optarg, strlen(optarg));
107 break;
108 case 'M':
109 req.manufacturer.Reinitialize(optarg, strlen(optarg));
110 break;
111 case 'm':
112 req.model.Reinitialize(optarg, strlen(optarg));
113 break;
114 case 'i':
115 req.imei.Reinitialize(optarg, strlen(optarg));
116 break;
117 case 'c':
118 req.meid.Reinitialize(optarg, strlen(optarg));
119 break;
120 case 'h':
121 print_usage(argv[0], req);
122 exit(EXIT_SUCCESS);
123 default:
124 print_usage(argv[0], req);
125 exit(EXIT_FAILURE);
126 }
127 }
128 if (optind != argc) {
129 print_usage(argv[0], req);
130 exit(EXIT_FAILURE);
131 }
132
133 int ret = trusty_keymaster_connect();
134 if (ret) {
135 fprintf(stderr, "trusty_keymaster_connect failed: %d\n", ret);
136 return EXIT_FAILURE;
137 }
138
139 printf("Setting:\n"
140 " brand: %s\n"
141 " device: %s\n"
142 " product: %s\n"
143 " serial: %s\n"
144 " manufacturer: %s\n"
145 " model: %s\n"
146 " IMEI: %s\n"
147 " MEID: %s\n",
148 buf2string(req.brand).c_str(), buf2string(req.device).c_str(),
149 buf2string(req.product).c_str(), buf2string(req.serial).c_str(),
150 buf2string(req.manufacturer).c_str(), buf2string(req.model).c_str(),
151 buf2string(req.imei).c_str(), buf2string(req.meid).c_str());
152
153 keymaster::EmptyKeymasterResponse rsp(/* ver = */ 4);
154 ret = trusty_keymaster_send(KM_SET_ATTESTATION_IDS, req, &rsp);
155 if (ret) {
156 fprintf(stderr, "SET_ATTESTATION_IDS failed: %d\n", ret);
157 trusty_keymaster_disconnect();
158 return EXIT_FAILURE;
159 }
160
161 return EXIT_SUCCESS;
162 }
163