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