1 /*
2 * Copyright (C) 2018 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 #define LOG_TAG "rpmb_mock"
18
19 #include "rpmb_protocol.h"
20
21 #include <assert.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <getopt.h>
25 #include <log/log.h>
26 #include <openssl/hmac.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/socket.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <sys/un.h>
34 #include <unistd.h>
35
36 /* verbose is an int for getopt */
37 static int verbose = false;
38
39 #if OPENSSL_VERSION_NUMBER < 0x10100000L
40
HMAC_CTX_new(void)41 HMAC_CTX* HMAC_CTX_new(void) {
42 HMAC_CTX* ctx = malloc(sizeof(*ctx));
43 if (ctx != NULL) {
44 HMAC_CTX_init(ctx);
45 }
46 return ctx;
47 }
48
HMAC_CTX_free(HMAC_CTX * ctx)49 void HMAC_CTX_free(HMAC_CTX* ctx) {
50 if (ctx != NULL) {
51 HMAC_CTX_cleanup(ctx);
52 free(ctx);
53 }
54 }
55
56 #endif
57
58 #define MAX_WRITE_COUNTER (0xffffffff)
59
60 struct rpmb_data_header {
61 uint32_t write_counter;
62 uint16_t max_block;
63 uint8_t pad1;
64 uint8_t key_programmed;
65 struct rpmb_key key;
66 uint8_t pad[512 - 4 - 2 - 1 - 1 - sizeof(struct rpmb_key)];
67 };
68
69 #define MAX_PACKET_COUNT (8)
70
71 struct rpmb_dev_state {
72 struct rpmb_data_header header;
73 struct rpmb_packet cmd[MAX_PACKET_COUNT];
74 struct rpmb_packet res[MAX_PACKET_COUNT];
75 uint16_t cmd_count;
76 uint16_t res_count;
77 int data_fd;
78 };
79
80 /* TODO: move to common location */
rpmb_mac(struct rpmb_key key,struct rpmb_packet * packet,size_t packet_count,struct rpmb_key * mac)81 static int rpmb_mac(struct rpmb_key key, struct rpmb_packet* packet, size_t packet_count,
82 struct rpmb_key* mac) {
83 size_t i;
84 int hmac_ret;
85 unsigned int md_len;
86 HMAC_CTX* hmac_ctx;
87
88 hmac_ctx = HMAC_CTX_new();
89 hmac_ret = HMAC_Init_ex(hmac_ctx, &key, sizeof(key), EVP_sha256(), NULL);
90 if (!hmac_ret) {
91 ALOGE("HMAC_Init_ex failed\n");
92 goto err;
93 }
94 for (i = 0; i < packet_count; i++) {
95 hmac_ret = HMAC_Update(hmac_ctx, packet[i].data, 284);
96 if (!hmac_ret) {
97 ALOGE("HMAC_Update failed\n");
98 goto err;
99 }
100 }
101 hmac_ret = HMAC_Final(hmac_ctx, mac->byte, &md_len);
102 if (md_len != sizeof(mac->byte)) {
103 ALOGE("bad md_len %d != %zd\n", md_len, sizeof(mac->byte));
104 exit(1);
105 }
106 if (!hmac_ret) {
107 ALOGE("HMAC_Final failed\n");
108 goto err;
109 }
110
111 err:
112 HMAC_CTX_free(hmac_ctx);
113 return hmac_ret ? 0 : -1;
114 }
115
rpmb_file_seek(struct rpmb_dev_state * s,uint16_t addr)116 static int rpmb_file_seek(struct rpmb_dev_state* s, uint16_t addr) {
117 int ret;
118 int pos = addr * RPMB_PACKET_DATA_SIZE + sizeof(s->header);
119 ret = lseek(s->data_fd, pos, SEEK_SET);
120 if (ret != pos) {
121 ALOGE("rpmb_dev: seek to %d failed, got %d\n", pos, ret);
122 return -1;
123 }
124 return 0;
125 }
126
rpmb_dev_program_key(struct rpmb_dev_state * s)127 static uint16_t rpmb_dev_program_key(struct rpmb_dev_state* s) {
128 int ret;
129
130 if (s->header.key_programmed) {
131 return RPMB_RES_WRITE_FAILURE;
132 }
133
134 s->header.key = s->cmd[0].key_mac;
135 s->header.key_programmed = 1;
136
137 ret = lseek(s->data_fd, 0, SEEK_SET);
138 if (ret) {
139 ALOGE("rpmb_dev: Failed to seek rpmb data file\n");
140 return RPMB_RES_WRITE_FAILURE;
141 }
142
143 ret = write(s->data_fd, &s->header, sizeof(s->header));
144 if (ret != sizeof(s->header)) {
145 ALOGE("rpmb_dev: Failed to write rpmb key: %d, %s\n", ret, strerror(errno));
146
147 return RPMB_RES_WRITE_FAILURE;
148 }
149
150 return RPMB_RES_OK;
151 }
152
rpmb_dev_get_counter(struct rpmb_dev_state * s)153 static uint16_t rpmb_dev_get_counter(struct rpmb_dev_state* s) {
154 s->res[0].write_counter = rpmb_u32(s->header.write_counter);
155
156 return RPMB_RES_OK;
157 }
158
rpmb_dev_data_write(struct rpmb_dev_state * s)159 static uint16_t rpmb_dev_data_write(struct rpmb_dev_state* s) {
160 uint16_t addr = rpmb_get_u16(s->cmd[0].address);
161 uint16_t block_count = s->cmd_count;
162 uint32_t write_counter;
163 int ret;
164
165 if (s->header.write_counter == MAX_WRITE_COUNTER) {
166 if (verbose) {
167 ALOGE("rpmb_dev: Write counter expired\n");
168 }
169 return RPMB_RES_WRITE_FAILURE;
170 }
171
172 write_counter = rpmb_get_u32(s->cmd[0].write_counter);
173 if (s->header.write_counter != write_counter) {
174 if (verbose) {
175 ALOGE("rpmb_dev: Invalid write counter %u. Expected: %u\n", write_counter,
176 s->header.write_counter);
177 }
178 return RPMB_RES_COUNT_FAILURE;
179 }
180
181 ret = rpmb_file_seek(s, addr);
182 if (ret) {
183 ALOGE("rpmb_dev: Failed to seek rpmb data file\n");
184 return RPMB_RES_WRITE_FAILURE;
185 }
186
187 for (int i = 0; i < block_count; i++) {
188 ret = write(s->data_fd, s->cmd[i].data, RPMB_PACKET_DATA_SIZE);
189 if (ret != RPMB_PACKET_DATA_SIZE) {
190 ALOGE("rpmb_dev: Failed to write rpmb data file: %d, %s\n", ret, strerror(errno));
191 return RPMB_RES_WRITE_FAILURE;
192 }
193 }
194
195 s->header.write_counter++;
196
197 ret = lseek(s->data_fd, 0, SEEK_SET);
198 if (ret) {
199 ALOGE("rpmb_dev: Failed to seek rpmb data file\n");
200 return RPMB_RES_WRITE_FAILURE;
201 }
202
203 ret = write(s->data_fd, &s->header.write_counter, sizeof(s->header.write_counter));
204 if (ret != sizeof(s->header.write_counter)) {
205 ALOGE("rpmb_dev: Failed to write rpmb write counter: %d, %s\n", ret, strerror(errno));
206
207 return RPMB_RES_WRITE_FAILURE;
208 }
209
210 s->res[0].write_counter = rpmb_u32(s->header.write_counter);
211 return RPMB_RES_OK;
212 }
213
rpmb_dev_data_read(struct rpmb_dev_state * s)214 static uint16_t rpmb_dev_data_read(struct rpmb_dev_state* s) {
215 uint16_t addr;
216 uint16_t block_count;
217 int ret;
218
219 addr = rpmb_get_u16(s->cmd[0].address);
220 block_count = s->res_count;
221
222 rpmb_file_seek(s, addr);
223
224 for (int i = 0; i < block_count; i++) {
225 ret = read(s->data_fd, s->res[i].data, RPMB_PACKET_DATA_SIZE);
226 if (ret != 0 && ret != RPMB_PACKET_DATA_SIZE) {
227 ALOGE("rpmb_dev: Failed to read rpmb data file: %d, %s\n", ret, strerror(errno));
228 return RPMB_RES_READ_FAILURE;
229 }
230 }
231
232 return RPMB_RES_OK;
233 }
234
235 struct rpmb_dev_cmd {
236 uint16_t (*func)(struct rpmb_dev_state* s);
237 uint16_t resp;
238 bool key_mac_is_key;
239 bool check_mac;
240 bool check_result_read;
241 bool check_key_programmed;
242 bool check_addr;
243 bool multi_packet_cmd;
244 bool multi_packet_res;
245 bool res_mac;
246 };
247
248 static struct rpmb_dev_cmd rpmb_dev_cmd_table[] = {
249 [RPMB_REQ_PROGRAM_KEY] =
250 {
251 .func = rpmb_dev_program_key,
252 .resp = RPMB_RESP_PROGRAM_KEY,
253 .key_mac_is_key = true,
254 .check_result_read = true,
255 },
256 [RPMB_REQ_GET_COUNTER] =
257 {
258 .func = rpmb_dev_get_counter,
259 .resp = RPMB_RESP_GET_COUNTER,
260 .check_key_programmed = true,
261 .res_mac = true,
262 },
263 [RPMB_REQ_DATA_WRITE] =
264 {
265 .func = rpmb_dev_data_write,
266 .resp = RPMB_RESP_DATA_WRITE,
267 .check_mac = true,
268 .check_result_read = true,
269 .check_key_programmed = true,
270 .check_addr = true,
271 .multi_packet_cmd = true,
272 .res_mac = true,
273 },
274 [RPMB_REQ_DATA_READ] =
275 {
276 .func = rpmb_dev_data_read,
277 .resp = RPMB_RESP_DATA_READ,
278 .check_key_programmed = true,
279 .check_addr = true,
280 .multi_packet_res = true,
281 .res_mac = true,
282 },
283 };
284
285 #define countof(arr) (sizeof(arr) / sizeof(arr[0]))
286
rpmb_dev_process_cmd(struct rpmb_dev_state * s)287 static void rpmb_dev_process_cmd(struct rpmb_dev_state* s) {
288 assert(s->cmd_count > 0);
289 assert(s->res_count > 0);
290 uint16_t req_resp = rpmb_get_u16(s->cmd[0].req_resp);
291 uint16_t addr = rpmb_get_u16(s->cmd[0].address);
292 uint16_t sub_req;
293 uint16_t cmd_index = req_resp < countof(rpmb_dev_cmd_table) ? req_resp : 0;
294 struct rpmb_dev_cmd* cmd = &rpmb_dev_cmd_table[cmd_index];
295 uint16_t result = RPMB_RES_GENERAL_FAILURE;
296 struct rpmb_key mac;
297 uint16_t block_count = 0;
298
299 if (cmd->check_result_read) {
300 sub_req = rpmb_get_u16(s->cmd[s->cmd_count - 1].req_resp);
301 if (sub_req != RPMB_REQ_RESULT_READ) {
302 if (verbose) {
303 ALOGE("rpmb_dev: Request %d, missing result read request, got %d, cmd_count %d\n",
304 req_resp, sub_req, s->cmd_count);
305 }
306 goto err;
307 }
308 assert(s->cmd_count > 1);
309 s->cmd_count--;
310 }
311
312 if (cmd->check_mac) {
313 if (rpmb_mac(s->header.key, s->cmd, s->cmd_count, &mac) != 0) {
314 ALOGE("rpmb_dev: failed to caclulate mac\n");
315 goto err;
316 }
317 } else if (cmd->key_mac_is_key) {
318 mac = s->cmd[s->cmd_count - 1].key_mac;
319 } else {
320 memset(mac.byte, 0, sizeof(mac.byte));
321 }
322
323 if (memcmp(&mac, s->cmd[s->cmd_count - 1].key_mac.byte, sizeof(mac))) {
324 if (verbose) {
325 ALOGE("rpmb_dev: Request %d, invalid MAC, cmd_count %d\n", req_resp, s->cmd_count);
326 }
327 if (cmd->check_mac) {
328 result = RPMB_RES_AUTH_FAILURE;
329 }
330 goto err;
331 }
332
333 if (cmd->multi_packet_cmd) {
334 block_count = s->cmd_count;
335 }
336 if (cmd->multi_packet_res) {
337 block_count = s->res_count;
338 }
339
340 if (cmd->check_addr && (addr + block_count > s->header.max_block + 1)) {
341 if (verbose) {
342 ALOGE("rpmb_dev: Request %d, invalid addr: 0x%x count 0x%x, Out of bounds. Max addr "
343 "0x%x\n",
344 req_resp, addr, block_count, s->header.max_block + 1);
345 }
346 result = RPMB_RES_ADDR_FAILURE;
347 goto err;
348 }
349 if (!cmd->check_addr && addr) {
350 if (verbose) {
351 ALOGE("rpmb_dev: Request %d, invalid addr: 0x%x != 0\n", req_resp, addr);
352 }
353 goto err;
354 }
355
356 for (int i = 1; i < s->cmd_count; i++) {
357 sub_req = rpmb_get_u16(s->cmd[i].req_resp);
358 if (sub_req != req_resp) {
359 if (verbose) {
360 ALOGE("rpmb_dev: Request %d, sub-request mismatch, %d, at %d\n", req_resp, i,
361 sub_req);
362 }
363 goto err;
364 }
365 }
366 if (!cmd->multi_packet_cmd && s->cmd_count != 1) {
367 if (verbose) {
368 ALOGE("rpmb_dev: Request %d, bad cmd count %d, expected 1\n", req_resp, s->cmd_count);
369 }
370 goto err;
371 }
372 if (!cmd->multi_packet_res && s->res_count != 1) {
373 if (verbose) {
374 ALOGE("rpmb_dev: Request %d, bad res count %d, expected 1\n", req_resp, s->res_count);
375 }
376 goto err;
377 }
378
379 if (cmd->check_key_programmed && !s->header.key_programmed) {
380 if (verbose) {
381 ALOGE("rpmb_dev: Request %d, key is not programmed\n", req_resp);
382 }
383 s->res[0].result = rpmb_u16(RPMB_RES_NO_AUTH_KEY);
384 return;
385 }
386
387 if (!cmd->func) {
388 if (verbose) {
389 ALOGE("rpmb_dev: Unsupported request: %d\n", req_resp);
390 }
391 goto err;
392 }
393
394 result = cmd->func(s);
395
396 err:
397 if (s->header.write_counter == MAX_WRITE_COUNTER) {
398 result |= RPMB_RES_WRITE_COUNTER_EXPIRED;
399 }
400
401 for (int i = 0; i < s->res_count; i++) {
402 s->res[i].nonce = s->cmd[0].nonce;
403 s->res[i].address = rpmb_u16(addr);
404 s->res[i].block_count = rpmb_u16(block_count);
405 s->res[i].result = rpmb_u16(result);
406 s->res[i].req_resp = rpmb_u16(cmd->resp);
407 }
408 if (cmd->res_mac) {
409 rpmb_mac(s->header.key, s->res, s->res_count, &s->res[s->res_count - 1].key_mac);
410 }
411 }
412
413 /*
414 * Receives data until one of the following is true:
415 * - The buffer is full (return will be len)
416 * - The connection closed (return > 0, < len)
417 * - An error occurred (return will be the negative error code from recv)
418 */
recv_until(int sock,void * dest_in,size_t len)419 ssize_t recv_until(int sock, void* dest_in, size_t len) {
420 size_t bytes_recvd = 0;
421 char* dest = dest_in;
422 while (bytes_recvd < len) {
423 ssize_t ret = recv(sock, dest, len - bytes_recvd, 0);
424 if (ret < 0) {
425 return ret;
426 }
427 dest += ret;
428 bytes_recvd += ret;
429 if (ret == 0) {
430 break;
431 }
432 }
433 return bytes_recvd;
434 }
435
436 /*
437 * Handles an incoming connection to the rpmb daemon.
438 * Returns 0 if the client disconnects without violating the protocol.
439 * Returns a negative value if we terminated the connection abnormally.
440 *
441 * Arguments:
442 * conn_sock - an fd to send/recv on
443 * s - an initialized rpmb device
444 */
handle_conn(struct rpmb_dev_state * s,int conn_sock)445 int handle_conn(struct rpmb_dev_state* s, int conn_sock) {
446 int ret;
447
448 while (true) {
449 memset(s->res, 0, sizeof(s->res));
450 ret = recv_until(conn_sock, &s->res_count, sizeof(s->res_count));
451
452 /*
453 * Disconnected while not in the middle of anything.
454 */
455 if (ret <= 0) {
456 return 0;
457 }
458
459 if (s->res_count > MAX_PACKET_COUNT) {
460 ALOGE("rpmb_dev: Receive count too large: %d\n", s->res_count);
461 return -1;
462 }
463 if (s->res_count <= 0) {
464 ALOGE("rpmb_dev: Receive count too small: %d\n", s->res_count);
465 return -1;
466 }
467
468 ret = recv_until(conn_sock, &s->cmd_count, sizeof(s->cmd_count));
469 if (ret != sizeof(s->cmd_count)) {
470 ALOGE("rpmb_dev: Failed to read cmd_count");
471 return -1;
472 }
473
474 if (s->cmd_count == 0) {
475 ALOGE("rpmb_dev: Must contain at least one command\n");
476 return -1;
477 }
478
479 if (s->cmd_count > MAX_PACKET_COUNT) {
480 ALOGE("rpmb_dev: Command count is too large\n");
481 return -1;
482 }
483
484 size_t cmd_size = s->cmd_count * sizeof(s->cmd[0]);
485 ret = recv_until(conn_sock, s->cmd, cmd_size);
486 if (ret != (int)cmd_size) {
487 ALOGE("rpmb_dev: Failed to read command: "
488 "cmd_size: %zu ret: %d, %s\n",
489 cmd_size, ret, strerror(errno));
490 return -1;
491 }
492
493 rpmb_dev_process_cmd(s);
494
495 size_t resp_size = sizeof(s->res[0]) * s->res_count;
496 ret = send(conn_sock, s->res, resp_size, 0);
497 if (ret != (int)resp_size) {
498 ALOGE("rpmb_dev: Failed to send response: %d, %s\n", ret, strerror(errno));
499 return -1;
500 }
501 }
502 }
503
usage(const char * argv0)504 void usage(const char* argv0) {
505 fprintf(stderr, "Usage: %s [-d|--dev] <datafile> [--sock] <socket_path>\n", argv0);
506 fprintf(stderr, "or: %s [-d|--dev] <datafile> [--size <size>] [--key key]\n", argv0);
507 }
508
main(int argc,char ** argv)509 int main(int argc, char** argv) {
510 struct rpmb_dev_state s;
511 int ret;
512 int cmdres_sock;
513 struct sockaddr_un cmdres_sockaddr;
514 const char* data_file_name = NULL;
515 const char* socket_path = NULL;
516 int open_flags;
517 int init = false;
518
519 struct option long_options[] = {{"size", required_argument, 0, 0},
520 {"key", required_argument, 0, 0},
521 {"sock", required_argument, 0, 0},
522 {"dev", required_argument, 0, 'd'},
523 {"init", no_argument, &init, true},
524 {"verbose", no_argument, &verbose, true},
525 {0, 0, 0, 0}};
526
527 memset(&s.header, 0, sizeof(s.header));
528
529 while (1) {
530 int c;
531 int option_index = 0;
532 c = getopt_long(argc, argv, "d:", long_options, &option_index);
533 if (c == -1) {
534 break;
535 }
536
537 switch (c) {
538 /* long args */
539 case 0:
540 switch (option_index) {
541 /* size */
542 case 0:
543 s.header.max_block = atoi(optarg) - 1;
544 break;
545 /* key */
546 case 1:
547 for (size_t i = 0; i < sizeof(s.header.key.byte); i++) {
548 if (!optarg) {
549 break;
550 }
551 s.header.key.byte[i] = strtol(optarg, &optarg, 16);
552 s.header.key_programmed = 1;
553 }
554 break;
555 /* sock */
556 case 2:
557 socket_path = optarg;
558 break;
559 }
560 break;
561 /* dev */
562 case 'd':
563 data_file_name = optarg;
564 break;
565 default:
566 usage(argv[0]);
567 return EXIT_FAILURE;
568 }
569 }
570
571 /*
572 * We always need a data file, and at exactly one of --init or --sock
573 * must be specified.
574 */
575 if (!data_file_name || (!init == !socket_path)) {
576 usage(argv[0]);
577 return EXIT_FAILURE;
578 }
579
580 /*
581 * If the file is already initialized, exit early.
582 */
583 if (init && !access(data_file_name, F_OK)) {
584 return EXIT_SUCCESS;
585 }
586
587 open_flags = O_RDWR | O_SYNC;
588 if (init) {
589 open_flags |= O_CREAT | O_TRUNC;
590 }
591 s.data_fd = open(data_file_name, open_flags, S_IWUSR | S_IRUSR);
592 if (s.data_fd < 0) {
593 ALOGE("rpmb_dev: Failed to open rpmb data file, %s: %s\n", data_file_name, strerror(errno));
594 return EXIT_FAILURE;
595 }
596
597 if (init) {
598 /* Create new rpmb data file */
599 if (s.header.max_block == 0) {
600 s.header.max_block = 512 - 1;
601 }
602 ret = write(s.data_fd, &s.header, sizeof(s.header));
603 if (ret != sizeof(s.header)) {
604 ALOGE("rpmb_dev: Failed to write rpmb data file: %d, %s\n", ret, strerror(errno));
605 return EXIT_FAILURE;
606 }
607 return EXIT_SUCCESS;
608 }
609
610 ret = read(s.data_fd, &s.header, sizeof(s.header));
611 if (ret != sizeof(s.header)) {
612 ALOGE("rpmb_dev: Failed to read rpmb data file: %d, %s\n", ret, strerror(errno));
613 return EXIT_FAILURE;
614 }
615
616 cmdres_sock = socket(AF_UNIX, SOCK_STREAM, 0);
617 if (cmdres_sock < 0) {
618 ALOGE("rpmb_dev: Failed to create command/response socket: %s\n", strerror(errno));
619 return EXIT_FAILURE;
620 }
621
622 cmdres_sockaddr.sun_family = AF_UNIX;
623 strncpy(cmdres_sockaddr.sun_path, socket_path, sizeof(cmdres_sockaddr.sun_path));
624
625 ret = bind(cmdres_sock, (struct sockaddr*)&cmdres_sockaddr, sizeof(struct sockaddr_un));
626 if (ret < 0) {
627 ALOGE("rpmb_dev: Failed to bind command/response socket: %s: %s\n", socket_path,
628 strerror(errno));
629 return EXIT_FAILURE;
630 }
631
632 ret = listen(cmdres_sock, 1);
633 if (ret < 0) {
634 ALOGE("rpmb_dev: Failed to listen on command/response socket: %s\n", strerror(errno));
635 return EXIT_FAILURE;
636 }
637
638 while (true) {
639 int conn_sock = accept(cmdres_sock, NULL, NULL);
640 if (conn_sock < 0) {
641 ALOGE("rpmb_dev: Could not accept connection: %s\n", strerror(errno));
642 return EXIT_FAILURE;
643 }
644 ret = handle_conn(&s, conn_sock);
645 close(conn_sock);
646 if (ret) {
647 ALOGE("rpmb_dev: Connection terminated: %d", ret);
648 }
649 }
650 }
651