xref: /aosp_15_r20/external/libese/apps/boot/ese_boot_tool.cpp (revision 5c4dab75aa57366379dce576b1a9e082a44e2b3a)
1*5c4dab75SAndroid Build Coastguard Worker /*
2*5c4dab75SAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*5c4dab75SAndroid Build Coastguard Worker  *
4*5c4dab75SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*5c4dab75SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*5c4dab75SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*5c4dab75SAndroid Build Coastguard Worker  *
8*5c4dab75SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*5c4dab75SAndroid Build Coastguard Worker  *
10*5c4dab75SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*5c4dab75SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*5c4dab75SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*5c4dab75SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*5c4dab75SAndroid Build Coastguard Worker  * limitations under the License.
15*5c4dab75SAndroid Build Coastguard Worker  *
16*5c4dab75SAndroid Build Coastguard Worker  * Commandline tool for interfacing with the Boot Storage app.
17*5c4dab75SAndroid Build Coastguard Worker  */
18*5c4dab75SAndroid Build Coastguard Worker 
19*5c4dab75SAndroid Build Coastguard Worker #include <ctype.h>
20*5c4dab75SAndroid Build Coastguard Worker #include <inttypes.h>
21*5c4dab75SAndroid Build Coastguard Worker #include <stdio.h>
22*5c4dab75SAndroid Build Coastguard Worker #include <stdint.h>
23*5c4dab75SAndroid Build Coastguard Worker #include <unistd.h>
24*5c4dab75SAndroid Build Coastguard Worker 
25*5c4dab75SAndroid Build Coastguard Worker #include <string>
26*5c4dab75SAndroid Build Coastguard Worker #include <vector>
27*5c4dab75SAndroid Build Coastguard Worker 
28*5c4dab75SAndroid Build Coastguard Worker #include <cutils/properties.h>
29*5c4dab75SAndroid Build Coastguard Worker #include <ese/ese.h>
30*5c4dab75SAndroid Build Coastguard Worker ESE_INCLUDE_HW(ESE_HW_NXP_PN80T_NQ_NCI);
31*5c4dab75SAndroid Build Coastguard Worker 
32*5c4dab75SAndroid Build Coastguard Worker #include "include/ese/app/boot.h"
33*5c4dab75SAndroid Build Coastguard Worker 
usage(const char * prog)34*5c4dab75SAndroid Build Coastguard Worker void usage(const char *prog) {
35*5c4dab75SAndroid Build Coastguard Worker   fprintf(stderr,
36*5c4dab75SAndroid Build Coastguard Worker     "Usage:\n"
37*5c4dab75SAndroid Build Coastguard Worker     "%s <cmd> <args>\n"
38*5c4dab75SAndroid Build Coastguard Worker     "    state    get\n"
39*5c4dab75SAndroid Build Coastguard Worker     "    production set {true,false}\n"
40*5c4dab75SAndroid Build Coastguard Worker     "    rollback set <іndex> <value>\n"
41*5c4dab75SAndroid Build Coastguard Worker     "             get <іndex>\n"
42*5c4dab75SAndroid Build Coastguard Worker     "    lock get {carrier,device,boot,owner}\n"
43*5c4dab75SAndroid Build Coastguard Worker     "         set carrier 0 <unlockToken>\n"
44*5c4dab75SAndroid Build Coastguard Worker     "                     <nonzero byte> {IMEI,MEID}\n"
45*5c4dab75SAndroid Build Coastguard Worker     "             device <byte>\n"
46*5c4dab75SAndroid Build Coastguard Worker     "             boot <byte>\n"
47*5c4dab75SAndroid Build Coastguard Worker     "             owner 0\n"
48*5c4dab75SAndroid Build Coastguard Worker     "             owner <non-zero byte> <keyValue>\n"
49*5c4dab75SAndroid Build Coastguard Worker     "         reset\n"
50*5c4dab75SAndroid Build Coastguard Worker     "    verify-key test <blob>\n"
51*5c4dab75SAndroid Build Coastguard Worker     "    verify-key auto\n"
52*5c4dab75SAndroid Build Coastguard Worker     "\n"
53*5c4dab75SAndroid Build Coastguard Worker     "Note, any non-zero byte value is considered 'locked'.\n"
54*5c4dab75SAndroid Build Coastguard Worker     "\n\n", prog);
55*5c4dab75SAndroid Build Coastguard Worker }
56*5c4dab75SAndroid Build Coastguard Worker 
57*5c4dab75SAndroid Build Coastguard Worker #define handle_error(ese, result) ;
58*5c4dab75SAndroid Build Coastguard Worker #if 0  // TODO
59*5c4dab75SAndroid Build Coastguard Worker void handle_error(struct EseInterface *ese, EseAppResult result) {
60*5c4dab75SAndroid Build Coastguard Worker    show how to handle different errors, like cooldown before use or after.
61*5c4dab75SAndroid Build Coastguard Worker }
62*5c4dab75SAndroid Build Coastguard Worker #endif
63*5c4dab75SAndroid Build Coastguard Worker 
print_hexdump(const uint8_t * data,int start,int stop)64*5c4dab75SAndroid Build Coastguard Worker static void print_hexdump(const uint8_t* data, int start, int stop) {
65*5c4dab75SAndroid Build Coastguard Worker   for (int i = start; i < stop; ++i) {
66*5c4dab75SAndroid Build Coastguard Worker     if (i % 20 == start - 1) {
67*5c4dab75SAndroid Build Coastguard Worker       printf("\n");
68*5c4dab75SAndroid Build Coastguard Worker     }
69*5c4dab75SAndroid Build Coastguard Worker     printf("%.2x ", data[i]);
70*5c4dab75SAndroid Build Coastguard Worker   }
71*5c4dab75SAndroid Build Coastguard Worker   printf("\n");
72*5c4dab75SAndroid Build Coastguard Worker }
73*5c4dab75SAndroid Build Coastguard Worker 
hexify(const std::string & input,std::vector<uint8_t> * output)74*5c4dab75SAndroid Build Coastguard Worker static uint16_t hexify(const std::string& input, std::vector<uint8_t> *output) {
75*5c4dab75SAndroid Build Coastguard Worker   for (auto it = input.cbegin(); it != input.cend(); ++it) {
76*5c4dab75SAndroid Build Coastguard Worker     std::string hex;
77*5c4dab75SAndroid Build Coastguard Worker     hex.push_back(*it++);
78*5c4dab75SAndroid Build Coastguard Worker     hex.push_back(*it);
79*5c4dab75SAndroid Build Coastguard Worker     output->push_back(static_cast<uint8_t>(std::stoi(hex, nullptr, 16)));
80*5c4dab75SAndroid Build Coastguard Worker   }
81*5c4dab75SAndroid Build Coastguard Worker   return static_cast<uint16_t>(output->size() & 0xffff);
82*5c4dab75SAndroid Build Coastguard Worker }
83*5c4dab75SAndroid Build Coastguard Worker 
84*5c4dab75SAndroid Build Coastguard Worker 
get_property_helper(const char * key,char * value)85*5c4dab75SAndroid Build Coastguard Worker bool get_property_helper(const char *key, char *value) {
86*5c4dab75SAndroid Build Coastguard Worker   if (property_get(key, value, NULL) == 0) {
87*5c4dab75SAndroid Build Coastguard Worker     fprintf(stderr, "Property '%s' is empty!\n", key);
88*5c4dab75SAndroid Build Coastguard Worker     return false;
89*5c4dab75SAndroid Build Coastguard Worker   }
90*5c4dab75SAndroid Build Coastguard Worker   return true;
91*5c4dab75SAndroid Build Coastguard Worker }
92*5c4dab75SAndroid Build Coastguard Worker 
93*5c4dab75SAndroid Build Coastguard Worker // Serializes the data to a string which is hashed by the applet.
collect_device_data(const std::string & modem_id,std::string * device_data)94*5c4dab75SAndroid Build Coastguard Worker bool collect_device_data(const std::string &modem_id, std::string *device_data) {
95*5c4dab75SAndroid Build Coastguard Worker   static const char *kDeviceKeys[] = {
96*5c4dab75SAndroid Build Coastguard Worker     "ro.product.brand",
97*5c4dab75SAndroid Build Coastguard Worker     "ro.product.device",
98*5c4dab75SAndroid Build Coastguard Worker     "ro.build.product",
99*5c4dab75SAndroid Build Coastguard Worker     "ro.serialno",
100*5c4dab75SAndroid Build Coastguard Worker     "",
101*5c4dab75SAndroid Build Coastguard Worker     "ro.product.manufacturer",
102*5c4dab75SAndroid Build Coastguard Worker     "ro.product.model",
103*5c4dab75SAndroid Build Coastguard Worker     NULL,
104*5c4dab75SAndroid Build Coastguard Worker   };
105*5c4dab75SAndroid Build Coastguard Worker   bool collect_from_env = getenv("COLLECT_FROM_ENV") != NULL;
106*5c4dab75SAndroid Build Coastguard Worker   uint8_t len = 0;
107*5c4dab75SAndroid Build Coastguard Worker   const char **key = &kDeviceKeys[0];
108*5c4dab75SAndroid Build Coastguard Worker   do {
109*5c4dab75SAndroid Build Coastguard Worker     if (strlen(*key) == 0) {
110*5c4dab75SAndroid Build Coastguard Worker       len = static_cast<uint8_t>(modem_id.length());
111*5c4dab75SAndroid Build Coastguard Worker       device_data->push_back(len);
112*5c4dab75SAndroid Build Coastguard Worker       device_data->append(modem_id);
113*5c4dab75SAndroid Build Coastguard Worker     } else {
114*5c4dab75SAndroid Build Coastguard Worker       char value[PROPERTY_VALUE_MAX];
115*5c4dab75SAndroid Build Coastguard Worker       char *value_ptr = &value[0];
116*5c4dab75SAndroid Build Coastguard Worker       if (collect_from_env) {
117*5c4dab75SAndroid Build Coastguard Worker         // Use the last dotted value.
118*5c4dab75SAndroid Build Coastguard Worker         value_ptr = getenv(strrchr(*key, '.') + 1);
119*5c4dab75SAndroid Build Coastguard Worker         if (value_ptr == NULL) {
120*5c4dab75SAndroid Build Coastguard Worker           fprintf(stderr, "fake property '%s' not in env\n",
121*5c4dab75SAndroid Build Coastguard Worker                   strrchr(*key, '.') + 1);
122*5c4dab75SAndroid Build Coastguard Worker           return false;
123*5c4dab75SAndroid Build Coastguard Worker         }
124*5c4dab75SAndroid Build Coastguard Worker       } else if (!get_property_helper(*key, value_ptr)) {
125*5c4dab75SAndroid Build Coastguard Worker         return false;
126*5c4dab75SAndroid Build Coastguard Worker       }
127*5c4dab75SAndroid Build Coastguard Worker       len = static_cast<uint8_t>(strlen(value_ptr));
128*5c4dab75SAndroid Build Coastguard Worker       device_data->push_back(len);
129*5c4dab75SAndroid Build Coastguard Worker       device_data->append(value_ptr);
130*5c4dab75SAndroid Build Coastguard Worker     }
131*5c4dab75SAndroid Build Coastguard Worker     if (*++key == NULL) {
132*5c4dab75SAndroid Build Coastguard Worker       break;
133*5c4dab75SAndroid Build Coastguard Worker     }
134*5c4dab75SAndroid Build Coastguard Worker   } while (*key != NULL);
135*5c4dab75SAndroid Build Coastguard Worker   return true;
136*5c4dab75SAndroid Build Coastguard Worker }
137*5c4dab75SAndroid Build Coastguard Worker 
handle_production(struct EseBootSession * session,std::vector<std::string> & args)138*5c4dab75SAndroid Build Coastguard Worker int handle_production(struct EseBootSession *session, std::vector<std::string> &args) {
139*5c4dab75SAndroid Build Coastguard Worker   EseAppResult res;
140*5c4dab75SAndroid Build Coastguard Worker   if (args[1] != "set") {
141*5c4dab75SAndroid Build Coastguard Worker     fprintf(stderr, "production: unknown command '%s'\n", args[2].c_str());
142*5c4dab75SAndroid Build Coastguard Worker     return -1;
143*5c4dab75SAndroid Build Coastguard Worker   }
144*5c4dab75SAndroid Build Coastguard Worker   if (args.size() < 3) {
145*5c4dab75SAndroid Build Coastguard Worker     fprintf(stderr, "production: not enough arguments\n");
146*5c4dab75SAndroid Build Coastguard Worker     return -1;
147*5c4dab75SAndroid Build Coastguard Worker   }
148*5c4dab75SAndroid Build Coastguard Worker   bool prod = false;
149*5c4dab75SAndroid Build Coastguard Worker   if (args[2] == "true") {
150*5c4dab75SAndroid Build Coastguard Worker     prod = true;
151*5c4dab75SAndroid Build Coastguard Worker   } else if (args[2] == "false") {
152*5c4dab75SAndroid Build Coastguard Worker     prod = false;
153*5c4dab75SAndroid Build Coastguard Worker   } else {
154*5c4dab75SAndroid Build Coastguard Worker     fprintf(stderr, "production: must be 'true' or 'false'\n");
155*5c4dab75SAndroid Build Coastguard Worker     return -1;
156*5c4dab75SAndroid Build Coastguard Worker   }
157*5c4dab75SAndroid Build Coastguard Worker   res = ese_boot_set_production(session, prod);
158*5c4dab75SAndroid Build Coastguard Worker   if (res == ESE_APP_RESULT_OK) {
159*5c4dab75SAndroid Build Coastguard Worker     printf("production mode changed\n");
160*5c4dab75SAndroid Build Coastguard Worker     return 0;
161*5c4dab75SAndroid Build Coastguard Worker   }
162*5c4dab75SAndroid Build Coastguard Worker   fprintf(stderr, "production: failed to change (%.8x)\n", res);
163*5c4dab75SAndroid Build Coastguard Worker   return 1;
164*5c4dab75SAndroid Build Coastguard Worker }
165*5c4dab75SAndroid Build Coastguard Worker 
handle_state(struct EseBootSession * session,std::vector<std::string> & args)166*5c4dab75SAndroid Build Coastguard Worker int handle_state(struct EseBootSession *session, std::vector<std::string> &args) {
167*5c4dab75SAndroid Build Coastguard Worker   EseAppResult res;
168*5c4dab75SAndroid Build Coastguard Worker   if (args[1] != "get") {
169*5c4dab75SAndroid Build Coastguard Worker     fprintf(stderr, "state: unknown command '%s'\n", args[2].c_str());
170*5c4dab75SAndroid Build Coastguard Worker     return -1;
171*5c4dab75SAndroid Build Coastguard Worker   }
172*5c4dab75SAndroid Build Coastguard Worker   // Read in the hex unlockToken and hope for the best.
173*5c4dab75SAndroid Build Coastguard Worker   std::vector<uint8_t> data;
174*5c4dab75SAndroid Build Coastguard Worker   data.resize(8192);
175*5c4dab75SAndroid Build Coastguard Worker   uint16_t len = static_cast<uint16_t>(data.size());
176*5c4dab75SAndroid Build Coastguard Worker   res = ese_boot_get_state(session, data.data(), len);
177*5c4dab75SAndroid Build Coastguard Worker   if (res != ESE_APP_RESULT_OK) {
178*5c4dab75SAndroid Build Coastguard Worker     fprintf(stderr, "state: failed (%.8x)\n", res);
179*5c4dab75SAndroid Build Coastguard Worker     return 1;
180*5c4dab75SAndroid Build Coastguard Worker   }
181*5c4dab75SAndroid Build Coastguard Worker   // TODO: ese_boot_get_state should guarantee length is safe...
182*5c4dab75SAndroid Build Coastguard Worker   len = (data[1] << 8) | (data[2]) + 3;
183*5c4dab75SAndroid Build Coastguard Worker   printf("Boot Storage State:\n    ");
184*5c4dab75SAndroid Build Coastguard Worker   print_hexdump(data.data(), 3, len);
185*5c4dab75SAndroid Build Coastguard Worker   return 0;
186*5c4dab75SAndroid Build Coastguard Worker }
187*5c4dab75SAndroid Build Coastguard Worker 
188*5c4dab75SAndroid Build Coastguard Worker static const uint8_t auto_data[] = {
189*5c4dab75SAndroid Build Coastguard Worker   // lastNonce
190*5c4dab75SAndroid Build Coastguard Worker   0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x40,
191*5c4dab75SAndroid Build Coastguard Worker   // deviceData
192*5c4dab75SAndroid Build Coastguard Worker   0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
193*5c4dab75SAndroid Build Coastguard Worker   0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
194*5c4dab75SAndroid Build Coastguard Worker   0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
195*5c4dab75SAndroid Build Coastguard Worker   0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
196*5c4dab75SAndroid Build Coastguard Worker   // Version
197*5c4dab75SAndroid Build Coastguard Worker   0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198*5c4dab75SAndroid Build Coastguard Worker   // Nonce
199*5c4dab75SAndroid Build Coastguard Worker   0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
200*5c4dab75SAndroid Build Coastguard Worker   // Signature
201*5c4dab75SAndroid Build Coastguard Worker   0x68, 0x86, 0x9a, 0x16, 0xca, 0x62, 0xea, 0xa9,
202*5c4dab75SAndroid Build Coastguard Worker   0x9b, 0xa0, 0x51, 0x03, 0xa6, 0x00, 0x3f, 0xe8,
203*5c4dab75SAndroid Build Coastguard Worker   0xf1, 0x43, 0xe6, 0xb7, 0xde, 0x76, 0xfe, 0x21,
204*5c4dab75SAndroid Build Coastguard Worker   0x65, 0x87, 0x78, 0xe5, 0x1d, 0x11, 0x6a, 0xe1,
205*5c4dab75SAndroid Build Coastguard Worker   0x7b, 0xc6, 0x2e, 0xe2, 0x96, 0x25, 0x48, 0xa7,
206*5c4dab75SAndroid Build Coastguard Worker   0x09, 0x43, 0x2c, 0xfd, 0x28, 0xa9, 0x66, 0x8a,
207*5c4dab75SAndroid Build Coastguard Worker   0x09, 0xd5, 0x83, 0x3b, 0xde, 0x18, 0x5d, 0xef,
208*5c4dab75SAndroid Build Coastguard Worker   0x50, 0x12, 0x8a, 0x8d, 0xfb, 0x2d, 0x46, 0x20,
209*5c4dab75SAndroid Build Coastguard Worker   0x69, 0x55, 0x4e, 0x86, 0x63, 0xf6, 0x10, 0xe3,
210*5c4dab75SAndroid Build Coastguard Worker   0x59, 0x3f, 0x55, 0x72, 0x18, 0xcb, 0x60, 0x80,
211*5c4dab75SAndroid Build Coastguard Worker   0x0d, 0x2e, 0x2f, 0xfc, 0xc2, 0xbf, 0xda, 0x3f,
212*5c4dab75SAndroid Build Coastguard Worker   0x4f, 0x2b, 0x6b, 0xf1, 0x5d, 0x28, 0x6b, 0x2b,
213*5c4dab75SAndroid Build Coastguard Worker   0x9b, 0x92, 0xf3, 0x4e, 0xf2, 0xb6, 0x23, 0x8e,
214*5c4dab75SAndroid Build Coastguard Worker   0x50, 0x64, 0xf6, 0xee, 0xc7, 0x78, 0x6a, 0xe0,
215*5c4dab75SAndroid Build Coastguard Worker   0xed, 0xce, 0x2c, 0x1f, 0x0a, 0x47, 0x43, 0x5c,
216*5c4dab75SAndroid Build Coastguard Worker   0xe4, 0x69, 0xc5, 0xc1, 0xf9, 0x52, 0x8c, 0xed,
217*5c4dab75SAndroid Build Coastguard Worker   0xfd, 0x71, 0x8f, 0x9a, 0xde, 0x62, 0xfc, 0x21,
218*5c4dab75SAndroid Build Coastguard Worker   0x07, 0xf9, 0x5f, 0xe1, 0x1e, 0xdc, 0x65, 0x95,
219*5c4dab75SAndroid Build Coastguard Worker   0x15, 0xc8, 0xe7, 0xf2, 0xce, 0xa9, 0xd0, 0x55,
220*5c4dab75SAndroid Build Coastguard Worker   0xf1, 0x18, 0x89, 0xae, 0xe8, 0x47, 0xd8, 0x8a,
221*5c4dab75SAndroid Build Coastguard Worker   0x1f, 0x68, 0xa8, 0x6f, 0x5e, 0x5c, 0xda, 0x3d,
222*5c4dab75SAndroid Build Coastguard Worker   0x98, 0xeb, 0x82, 0xf8, 0x1f, 0x7a, 0x43, 0x6d,
223*5c4dab75SAndroid Build Coastguard Worker   0x3a, 0x7c, 0x36, 0x76, 0x4f, 0x55, 0xa4, 0x55,
224*5c4dab75SAndroid Build Coastguard Worker   0x5f, 0x52, 0x47, 0xa5, 0x71, 0x17, 0x7b, 0x73,
225*5c4dab75SAndroid Build Coastguard Worker   0xaa, 0x5c, 0x85, 0x94, 0xb6, 0xe2, 0x37, 0x1f,
226*5c4dab75SAndroid Build Coastguard Worker   0x22, 0x29, 0x46, 0x59, 0x20, 0x1f, 0x49, 0x36,
227*5c4dab75SAndroid Build Coastguard Worker   0x50, 0xa9, 0x60, 0x5d, 0xeb, 0x99, 0x3f, 0x92,
228*5c4dab75SAndroid Build Coastguard Worker   0x31, 0xa0, 0x1d, 0xad, 0xdb, 0xde, 0x40, 0xf6,
229*5c4dab75SAndroid Build Coastguard Worker   0xaf, 0x9c, 0x36, 0xe4, 0x0c, 0xf4, 0xcc, 0xaf,
230*5c4dab75SAndroid Build Coastguard Worker   0x9f, 0x8b, 0xf9, 0xe6, 0x12, 0x53, 0x4e, 0x58,
231*5c4dab75SAndroid Build Coastguard Worker   0xeb, 0x9a, 0x57, 0x08, 0x89, 0xa5, 0x4f, 0x7c,
232*5c4dab75SAndroid Build Coastguard Worker   0xb9, 0x78, 0x07, 0x02, 0x17, 0x2c, 0xce, 0xb8,
233*5c4dab75SAndroid Build Coastguard Worker };
234*5c4dab75SAndroid Build Coastguard Worker 
handle_verify_key(struct EseBootSession * session,std::vector<std::string> & args)235*5c4dab75SAndroid Build Coastguard Worker int handle_verify_key(struct EseBootSession *session, std::vector<std::string> &args) {
236*5c4dab75SAndroid Build Coastguard Worker   EseAppResult res;
237*5c4dab75SAndroid Build Coastguard Worker   if (args[1] != "test" && args[1] != "auto") {
238*5c4dab75SAndroid Build Coastguard Worker     fprintf(stderr, "verify-key: unknown command '%s'\n", args[2].c_str());
239*5c4dab75SAndroid Build Coastguard Worker     return -1;
240*5c4dab75SAndroid Build Coastguard Worker   }
241*5c4dab75SAndroid Build Coastguard Worker   // Read in the hex unlockToken and hope for the best.
242*5c4dab75SAndroid Build Coastguard Worker   std::vector<uint8_t> data;
243*5c4dab75SAndroid Build Coastguard Worker   uint16_t len;
244*5c4dab75SAndroid Build Coastguard Worker   if (args[1] == "test") {
245*5c4dab75SAndroid Build Coastguard Worker     len = hexify(args[2], &data);
246*5c4dab75SAndroid Build Coastguard Worker     const uint16_t kExpectedLength = (sizeof(uint64_t) * 2 + sizeof(uint64_t) + 32 + 256);
247*5c4dab75SAndroid Build Coastguard Worker     if (len != kExpectedLength) {
248*5c4dab75SAndroid Build Coastguard Worker       fprintf(stderr, "verify-key: expected blob of length %hu not %hu\n", kExpectedLength, len);
249*5c4dab75SAndroid Build Coastguard Worker       fprintf(stderr, "verify-key: format is as follows (in hex):\n");
250*5c4dab75SAndroid Build Coastguard Worker       fprintf(stderr, "[lastNonce:8][deviceData:32][version:8][unlockNonce:8][RSA-SHA256PKCS#1 Signature:256]\n");
251*5c4dab75SAndroid Build Coastguard Worker       return 2;
252*5c4dab75SAndroid Build Coastguard Worker     }
253*5c4dab75SAndroid Build Coastguard Worker   } else {
254*5c4dab75SAndroid Build Coastguard Worker     len = sizeof(auto_data);
255*5c4dab75SAndroid Build Coastguard Worker     data.assign(&auto_data[0], auto_data + sizeof(auto_data));
256*5c4dab75SAndroid Build Coastguard Worker   }
257*5c4dab75SAndroid Build Coastguard Worker   printf("verify-key: sending the following test data:\n");
258*5c4dab75SAndroid Build Coastguard Worker   print_hexdump(data.data(), 0, data.size());
259*5c4dab75SAndroid Build Coastguard Worker   res = ese_boot_carrier_lock_test(session, data.data(), len);
260*5c4dab75SAndroid Build Coastguard Worker   if (res == ESE_APP_RESULT_OK) {
261*5c4dab75SAndroid Build Coastguard Worker     printf("verified\n");
262*5c4dab75SAndroid Build Coastguard Worker     return 0;
263*5c4dab75SAndroid Build Coastguard Worker   }
264*5c4dab75SAndroid Build Coastguard Worker   printf("failed to verify (%.8x)\n", res);
265*5c4dab75SAndroid Build Coastguard Worker   return 1;
266*5c4dab75SAndroid Build Coastguard Worker }
267*5c4dab75SAndroid Build Coastguard Worker 
handle_lock_state(struct EseBootSession * session,std::vector<std::string> & args)268*5c4dab75SAndroid Build Coastguard Worker int handle_lock_state(struct EseBootSession *session, std::vector<std::string> &args) {
269*5c4dab75SAndroid Build Coastguard Worker   EseAppResult res;
270*5c4dab75SAndroid Build Coastguard Worker   EseBootLockId lockId;
271*5c4dab75SAndroid Build Coastguard Worker   uint16_t lockMetaLen = 0;
272*5c4dab75SAndroid Build Coastguard Worker   uint8_t lockMeta[kEseBootOwnerKeyMax + 1];
273*5c4dab75SAndroid Build Coastguard Worker   if (args[1] == "reset") {
274*5c4dab75SAndroid Build Coastguard Worker     // No work.
275*5c4dab75SAndroid Build Coastguard Worker   } else if (args[2] == "carrier") {
276*5c4dab75SAndroid Build Coastguard Worker     lockId = kEseBootLockIdCarrier;
277*5c4dab75SAndroid Build Coastguard Worker   } else if (args[2] == "device") {
278*5c4dab75SAndroid Build Coastguard Worker     lockId = kEseBootLockIdDevice;
279*5c4dab75SAndroid Build Coastguard Worker   } else if (args[2] == "boot") {
280*5c4dab75SAndroid Build Coastguard Worker     lockId = kEseBootLockIdBoot;
281*5c4dab75SAndroid Build Coastguard Worker   } else if (args[2] == "owner") {
282*5c4dab75SAndroid Build Coastguard Worker     lockId = kEseBootLockIdOwner;
283*5c4dab75SAndroid Build Coastguard Worker   } else {
284*5c4dab75SAndroid Build Coastguard Worker     fprintf(stderr, "lock: unknown lock '%s'\n", args[2].c_str());
285*5c4dab75SAndroid Build Coastguard Worker     return 1;
286*5c4dab75SAndroid Build Coastguard Worker   }
287*5c4dab75SAndroid Build Coastguard Worker 
288*5c4dab75SAndroid Build Coastguard Worker   if (args[1] == "get") {
289*5c4dab75SAndroid Build Coastguard Worker     uint8_t lockVal = 0;
290*5c4dab75SAndroid Build Coastguard Worker     if (lockId == kEseBootLockIdCarrier ||
291*5c4dab75SAndroid Build Coastguard Worker         lockId == kEseBootLockIdOwner) {
292*5c4dab75SAndroid Build Coastguard Worker       res = ese_boot_lock_xget(session, lockId, lockMeta,
293*5c4dab75SAndroid Build Coastguard Worker                                sizeof(lockMeta), &lockMetaLen);
294*5c4dab75SAndroid Build Coastguard Worker     } else {
295*5c4dab75SAndroid Build Coastguard Worker       res = ese_boot_lock_get(session, lockId, &lockVal);
296*5c4dab75SAndroid Build Coastguard Worker     }
297*5c4dab75SAndroid Build Coastguard Worker     if (res == ESE_APP_RESULT_OK) {
298*5c4dab75SAndroid Build Coastguard Worker       if (lockMetaLen > 0) {
299*5c4dab75SAndroid Build Coastguard Worker         lockVal = lockMeta[0];
300*5c4dab75SAndroid Build Coastguard Worker       }
301*5c4dab75SAndroid Build Coastguard Worker       printf("%.2x\n", lockVal);
302*5c4dab75SAndroid Build Coastguard Worker       if (lockMetaLen > 0) {
303*5c4dab75SAndroid Build Coastguard Worker         print_hexdump(&lockMeta[1], 0, lockMetaLen - 1);
304*5c4dab75SAndroid Build Coastguard Worker       }
305*5c4dab75SAndroid Build Coastguard Worker       return 0;
306*5c4dab75SAndroid Build Coastguard Worker      }
307*5c4dab75SAndroid Build Coastguard Worker     fprintf(stderr, "lock: failed to get '%s' (%.8x)\n", args[2].c_str(), res);
308*5c4dab75SAndroid Build Coastguard Worker     handle_error(session->ese, res);
309*5c4dab75SAndroid Build Coastguard Worker     return 2;
310*5c4dab75SAndroid Build Coastguard Worker   } else if (args[1] == "reset") {
311*5c4dab75SAndroid Build Coastguard Worker     res = ese_boot_reset_locks(session);
312*5c4dab75SAndroid Build Coastguard Worker     if (res == ESE_APP_RESULT_OK) {
313*5c4dab75SAndroid Build Coastguard Worker       printf("done.\n");
314*5c4dab75SAndroid Build Coastguard Worker       return 0;
315*5c4dab75SAndroid Build Coastguard Worker     } else {
316*5c4dab75SAndroid Build Coastguard Worker       fprintf(stderr, "lock: failed to reset (%.8x)\n", res);
317*5c4dab75SAndroid Build Coastguard Worker       handle_error(session->ese, res);
318*5c4dab75SAndroid Build Coastguard Worker       return 3;
319*5c4dab75SAndroid Build Coastguard Worker     }
320*5c4dab75SAndroid Build Coastguard Worker   } else if (args[1] == "set") {
321*5c4dab75SAndroid Build Coastguard Worker     if (args.size() < 4) {
322*5c4dab75SAndroid Build Coastguard Worker       fprintf(stderr, "lock set: not enough arguments supplied\n");
323*5c4dab75SAndroid Build Coastguard Worker       return 2;
324*5c4dab75SAndroid Build Coastguard Worker     }
325*5c4dab75SAndroid Build Coastguard Worker     uint8_t lockVal = static_cast<uint8_t>(std::stoi(args[3], nullptr, 0));
326*5c4dab75SAndroid Build Coastguard Worker     if (lockId == kEseBootLockIdCarrier) {
327*5c4dab75SAndroid Build Coastguard Worker       res = ESE_APP_RESULT_ERROR_UNCONFIGURED;
328*5c4dab75SAndroid Build Coastguard Worker       if (lockVal != 0) {
329*5c4dab75SAndroid Build Coastguard Worker         std::string device_data;
330*5c4dab75SAndroid Build Coastguard Worker         device_data.push_back(lockVal);
331*5c4dab75SAndroid Build Coastguard Worker         if (!collect_device_data(args[4], &device_data)) {
332*5c4dab75SAndroid Build Coastguard Worker           fprintf(stderr, "carrier set 1: failed to aggregate device data\n");
333*5c4dab75SAndroid Build Coastguard Worker           return 3;
334*5c4dab75SAndroid Build Coastguard Worker         }
335*5c4dab75SAndroid Build Coastguard Worker         printf("Setting carrier lock with '");
336*5c4dab75SAndroid Build Coastguard Worker         for (std::string::iterator it = device_data.begin();
337*5c4dab75SAndroid Build Coastguard Worker              it != device_data.end(); ++it) {
338*5c4dab75SAndroid Build Coastguard Worker           if (isprint(*it)) {
339*5c4dab75SAndroid Build Coastguard Worker             printf("%c", *it);
340*5c4dab75SAndroid Build Coastguard Worker           } else {
341*5c4dab75SAndroid Build Coastguard Worker             printf("[0x%.2x]", *it);
342*5c4dab75SAndroid Build Coastguard Worker           }
343*5c4dab75SAndroid Build Coastguard Worker         }
344*5c4dab75SAndroid Build Coastguard Worker         printf("'\n");
345*5c4dab75SAndroid Build Coastguard Worker         const uint8_t *data = reinterpret_cast<const uint8_t *>(device_data.data());
346*5c4dab75SAndroid Build Coastguard Worker         res = ese_boot_lock_xset(session, lockId, data, device_data.length());
347*5c4dab75SAndroid Build Coastguard Worker       } else {
348*5c4dab75SAndroid Build Coastguard Worker         // Read in the hex unlockToken and hope for the best.
349*5c4dab75SAndroid Build Coastguard Worker         std::vector<uint8_t> data;
350*5c4dab75SAndroid Build Coastguard Worker         data.push_back(lockVal);
351*5c4dab75SAndroid Build Coastguard Worker         uint16_t len = hexify(args[4], &data);
352*5c4dab75SAndroid Build Coastguard Worker         if (len == 1) {
353*5c4dab75SAndroid Build Coastguard Worker           fprintf(stderr, "lock: carrier unlock requires a token\n");
354*5c4dab75SAndroid Build Coastguard Worker           return 5;
355*5c4dab75SAndroid Build Coastguard Worker         }
356*5c4dab75SAndroid Build Coastguard Worker         printf("Passing an unlockToken of length %d to the eSE\n", len - 1);
357*5c4dab75SAndroid Build Coastguard Worker         res = ese_boot_lock_xset(session, lockId, data.data(), len);
358*5c4dab75SAndroid Build Coastguard Worker       }
359*5c4dab75SAndroid Build Coastguard Worker     } else if (lockId == kEseBootLockIdOwner && lockVal != 0) {
360*5c4dab75SAndroid Build Coastguard Worker       std::vector<uint8_t> data;
361*5c4dab75SAndroid Build Coastguard Worker       data.push_back(lockVal);
362*5c4dab75SAndroid Build Coastguard Worker       uint16_t len = hexify(args[4], &data);
363*5c4dab75SAndroid Build Coastguard Worker       res = ese_boot_lock_xset(session, lockId, data.data(), len);
364*5c4dab75SAndroid Build Coastguard Worker     } else {
365*5c4dab75SAndroid Build Coastguard Worker       res = ese_boot_lock_set(session, lockId, lockVal);
366*5c4dab75SAndroid Build Coastguard Worker     }
367*5c4dab75SAndroid Build Coastguard Worker     if (res != ESE_APP_RESULT_OK) {
368*5c4dab75SAndroid Build Coastguard Worker       fprintf(stderr, "lock: failed to set %s state (%.8x)\n",
369*5c4dab75SAndroid Build Coastguard Worker               args[2].c_str(), res);
370*5c4dab75SAndroid Build Coastguard Worker       handle_error(session->ese, res);
371*5c4dab75SAndroid Build Coastguard Worker       return 4;
372*5c4dab75SAndroid Build Coastguard Worker     }
373*5c4dab75SAndroid Build Coastguard Worker     return 0;
374*5c4dab75SAndroid Build Coastguard Worker   }
375*5c4dab75SAndroid Build Coastguard Worker   fprintf(stderr, "lock: invalid command\n");
376*5c4dab75SAndroid Build Coastguard Worker   return -1;
377*5c4dab75SAndroid Build Coastguard Worker }
378*5c4dab75SAndroid Build Coastguard Worker 
handle_rollback(struct EseBootSession * session,std::vector<std::string> & args)379*5c4dab75SAndroid Build Coastguard Worker int handle_rollback(struct EseBootSession *session, std::vector<std::string> &args) {
380*5c4dab75SAndroid Build Coastguard Worker   int index = std::stoi(args[2], nullptr, 0);
381*5c4dab75SAndroid Build Coastguard Worker   uint8_t slot = static_cast<uint8_t>(index & 0xff);
382*5c4dab75SAndroid Build Coastguard Worker   if (slot > 7) {
383*5c4dab75SAndroid Build Coastguard Worker     fprintf(stderr, "rollback: slot must be one of [0-7]\n");
384*5c4dab75SAndroid Build Coastguard Worker     return 2;
385*5c4dab75SAndroid Build Coastguard Worker   }
386*5c4dab75SAndroid Build Coastguard Worker 
387*5c4dab75SAndroid Build Coastguard Worker   uint64_t value = 0;
388*5c4dab75SAndroid Build Coastguard Worker   if (args.size() > 3) {
389*5c4dab75SAndroid Build Coastguard Worker     unsigned long long conv = std::stoull(args[3], nullptr, 0);
390*5c4dab75SAndroid Build Coastguard Worker     value = static_cast<uint64_t>(conv);
391*5c4dab75SAndroid Build Coastguard Worker   }
392*5c4dab75SAndroid Build Coastguard Worker 
393*5c4dab75SAndroid Build Coastguard Worker   EseAppResult res;
394*5c4dab75SAndroid Build Coastguard Worker   if (args[1] == "get") {
395*5c4dab75SAndroid Build Coastguard Worker     res = ese_boot_rollback_index_read(session, slot, &value);
396*5c4dab75SAndroid Build Coastguard Worker     if (res != ESE_APP_RESULT_OK) {
397*5c4dab75SAndroid Build Coastguard Worker       fprintf(stderr, "rollback: failed to read slot %2x (%.8x)\n",
398*5c4dab75SAndroid Build Coastguard Worker               slot, res);
399*5c4dab75SAndroid Build Coastguard Worker       handle_error(session->ese, res);
400*5c4dab75SAndroid Build Coastguard Worker       return 3;
401*5c4dab75SAndroid Build Coastguard Worker     }
402*5c4dab75SAndroid Build Coastguard Worker     printf("%" PRIu64 "\n", value);
403*5c4dab75SAndroid Build Coastguard Worker     return 0;
404*5c4dab75SAndroid Build Coastguard Worker   } else if (args[1] == "set") {
405*5c4dab75SAndroid Build Coastguard Worker     res = ese_boot_rollback_index_write(session, slot, value);
406*5c4dab75SAndroid Build Coastguard Worker     if (res != ESE_APP_RESULT_OK) {
407*5c4dab75SAndroid Build Coastguard Worker       fprintf(stderr, "rollback: failed to write slot %2x (%.8x)\n",
408*5c4dab75SAndroid Build Coastguard Worker               slot, res);
409*5c4dab75SAndroid Build Coastguard Worker       handle_error(session->ese, res);
410*5c4dab75SAndroid Build Coastguard Worker       return 4;
411*5c4dab75SAndroid Build Coastguard Worker     }
412*5c4dab75SAndroid Build Coastguard Worker     return 0;
413*5c4dab75SAndroid Build Coastguard Worker   }
414*5c4dab75SAndroid Build Coastguard Worker   fprintf(stderr, "rollback: unknown command '%s'\n", args[1].c_str());
415*5c4dab75SAndroid Build Coastguard Worker   return -1;
416*5c4dab75SAndroid Build Coastguard Worker }
417*5c4dab75SAndroid Build Coastguard Worker 
handle_args(struct EseBootSession * session,const char * prog,std::vector<std::string> & args)418*5c4dab75SAndroid Build Coastguard Worker int handle_args(struct EseBootSession *session, const char *prog, std::vector<std::string> &args) {
419*5c4dab75SAndroid Build Coastguard Worker   if (args[0] == "rollback") {
420*5c4dab75SAndroid Build Coastguard Worker     return handle_rollback(session, args);
421*5c4dab75SAndroid Build Coastguard Worker   } else if (args[0] == "lock") {
422*5c4dab75SAndroid Build Coastguard Worker     return handle_lock_state(session, args);
423*5c4dab75SAndroid Build Coastguard Worker   } else if (args[0] == "verify-key") {
424*5c4dab75SAndroid Build Coastguard Worker     return handle_verify_key(session, args);
425*5c4dab75SAndroid Build Coastguard Worker   } else if (args[0] == "production") {
426*5c4dab75SAndroid Build Coastguard Worker     return handle_production(session, args);
427*5c4dab75SAndroid Build Coastguard Worker   } else if (args[0] == "state") {
428*5c4dab75SAndroid Build Coastguard Worker     return handle_state(session, args);
429*5c4dab75SAndroid Build Coastguard Worker   } else {
430*5c4dab75SAndroid Build Coastguard Worker     usage(prog);
431*5c4dab75SAndroid Build Coastguard Worker     return 1;
432*5c4dab75SAndroid Build Coastguard Worker   }
433*5c4dab75SAndroid Build Coastguard Worker   return 0;
434*5c4dab75SAndroid Build Coastguard Worker }
435*5c4dab75SAndroid Build Coastguard Worker 
main(int argc,char ** argv)436*5c4dab75SAndroid Build Coastguard Worker int main(int argc, char **argv) {
437*5c4dab75SAndroid Build Coastguard Worker   if (argc < 3) {
438*5c4dab75SAndroid Build Coastguard Worker     usage(argv[0]);
439*5c4dab75SAndroid Build Coastguard Worker     return 1;
440*5c4dab75SAndroid Build Coastguard Worker   }
441*5c4dab75SAndroid Build Coastguard Worker   // TODO(wad): move main to a class so we can just dep inject the hw.
442*5c4dab75SAndroid Build Coastguard Worker   struct EseInterface ese = ESE_INITIALIZER(ESE_HW_NXP_PN80T_NQ_NCI);
443*5c4dab75SAndroid Build Coastguard Worker   if (ese_open(&ese, nullptr) != 0) {
444*5c4dab75SAndroid Build Coastguard Worker     fprintf(stderr, "failed to open device\n");
445*5c4dab75SAndroid Build Coastguard Worker     return 2;
446*5c4dab75SAndroid Build Coastguard Worker   }
447*5c4dab75SAndroid Build Coastguard Worker   EseBootSession session;
448*5c4dab75SAndroid Build Coastguard Worker   ese_boot_session_init(&session);
449*5c4dab75SAndroid Build Coastguard Worker   EseAppResult res = ese_boot_session_open(&ese, &session);
450*5c4dab75SAndroid Build Coastguard Worker   if (res != ESE_APP_RESULT_OK) {
451*5c4dab75SAndroid Build Coastguard Worker     fprintf(stderr, "failed to initiate session (%.8x)\n", res);
452*5c4dab75SAndroid Build Coastguard Worker     handle_error(ese, res);
453*5c4dab75SAndroid Build Coastguard Worker     ese_close(&ese);
454*5c4dab75SAndroid Build Coastguard Worker     return 1;
455*5c4dab75SAndroid Build Coastguard Worker   }
456*5c4dab75SAndroid Build Coastguard Worker   std::vector<std::string> args;
457*5c4dab75SAndroid Build Coastguard Worker   args.assign(argv + 1, argv + argc);
458*5c4dab75SAndroid Build Coastguard Worker   int ret = handle_args(&session, argv[0], args);
459*5c4dab75SAndroid Build Coastguard Worker 
460*5c4dab75SAndroid Build Coastguard Worker   res = ese_boot_session_close(&session);
461*5c4dab75SAndroid Build Coastguard Worker   if (res != ESE_APP_RESULT_OK) {
462*5c4dab75SAndroid Build Coastguard Worker     handle_error(&ese, res);
463*5c4dab75SAndroid Build Coastguard Worker   }
464*5c4dab75SAndroid Build Coastguard Worker   ese_close(&ese);
465*5c4dab75SAndroid Build Coastguard Worker   return ret;
466*5c4dab75SAndroid Build Coastguard Worker }
467