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