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