• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "rpmb.h"
18 #include "error_reporting.h"
19 #include "rpmb_protocol.h"
20 
21 #include <assert.h>
22 #include <ctype.h>
23 #include <errno.h>
24 #include <lk/compiler.h>
25 #include <stdbool.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include <openssl/hmac.h>
31 #include <openssl/mem.h>
32 #include <openssl/rand.h>
33 
34 #define RPMB_DEBUG 0
35 #define MAX_PACKET_COUNT 2
36 
37 #define RPMB_PROTOCOL_MMC 1
38 #define RPMB_PROTOCOL_UFS 2
39 
40 #define RPMB_READ_COUNTER_MAX_RETRIES 3
41 
42 #if RPMB_PROTOCOL != RPMB_PROTOCOL_MMC && RPMB_PROTOCOL != RPMB_PROTOCOL_UFS
43 #error "invalid RPMB_PROTOCOL!"
44 #endif
45 
46 struct rpmb_state {
47     struct rpmb_key key;
48     void* mmc_handle;
49     uint32_t write_counter;
50     bool first_write_complete;
51     bool verify_failed;
52 };
53 
54 #if RPMB_DEBUG
55 #define rpmb_dprintf(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
56 #else
57 #define rpmb_dprintf(fmt, ...) \
58     do {                       \
59     } while (0)
60 #endif
61 
rpmb_dprint_buf(const char * prefix,const uint8_t * buf,size_t size)62 static void rpmb_dprint_buf(const char* prefix,
63                             const uint8_t* buf,
64                             size_t size) {
65 #if RPMB_DEBUG
66     size_t i, j;
67 
68     rpmb_dprintf("%s", prefix);
69     for (i = 0; i < size; i++) {
70         if (i && i % 32 == 0) {
71             rpmb_dprintf("\n");
72             j = strlen(prefix);
73             while (j) {
74                 rpmb_dprintf(" ");
75                 j--;
76             }
77         }
78         rpmb_dprintf(" %02x", buf[i]);
79     }
80     rpmb_dprintf("\n");
81 #endif
82 }
83 
rpmb_dprint_u16(const char * prefix,const struct rpmb_u16 u16)84 static void rpmb_dprint_u16(const char* prefix, const struct rpmb_u16 u16) {
85     rpmb_dprint_buf(prefix, u16.byte, sizeof(u16.byte));
86 }
87 
rpmb_dprint_u32(const char * prefix,const struct rpmb_u32 u32)88 static void rpmb_dprint_u32(const char* prefix, const struct rpmb_u32 u32) {
89     rpmb_dprint_buf(prefix, u32.byte, sizeof(u32.byte));
90 }
91 
rpmb_dprint_key(const char * prefix,const struct rpmb_key key,const char * expected_prefix,const struct rpmb_key expected_key)92 static void rpmb_dprint_key(const char* prefix,
93                             const struct rpmb_key key,
94                             const char* expected_prefix,
95                             const struct rpmb_key expected_key) {
96 #if RPMB_DEBUG
97     rpmb_dprint_buf(prefix, key.byte, sizeof(key.byte));
98     if (CRYPTO_memcmp(key.byte, expected_key.byte, sizeof(key.byte)))
99         rpmb_dprint_buf(expected_prefix, expected_key.byte,
100                         sizeof(expected_key.byte));
101 #endif
102 }
103 
rpmb_nonce_init(void)104 static struct rpmb_nonce rpmb_nonce_init(void) {
105     struct rpmb_nonce rpmb_nonce;
106 
107     RAND_bytes(rpmb_nonce.byte, sizeof(rpmb_nonce.byte));
108 
109     return rpmb_nonce;
110 }
111 
rpmb_mac(struct rpmb_key key,struct rpmb_packet * packet,size_t packet_count,struct rpmb_key * mac)112 static int rpmb_mac(struct rpmb_key key,
113                     struct rpmb_packet* packet,
114                     size_t packet_count,
115                     struct rpmb_key* mac) {
116     size_t i;
117     int hmac_ret;
118     unsigned int md_len;
119     HMAC_CTX hmac_ctx;
120 
121     HMAC_CTX_init(&hmac_ctx);
122     hmac_ret = HMAC_Init_ex(&hmac_ctx, &key, sizeof(key), EVP_sha256(), NULL);
123     if (!hmac_ret) {
124         fprintf(stderr, "HMAC_Init_ex failed\n");
125         goto err;
126     }
127     for (i = 0; i < packet_count; i++) {
128         STATIC_ASSERT(sizeof(*packet) - offsetof(__typeof__(*packet), data) ==
129                       284);
130         hmac_ret = HMAC_Update(&hmac_ctx, packet[i].data, 284);
131         if (!hmac_ret) {
132             fprintf(stderr, "HMAC_Update failed\n");
133             goto err;
134         }
135     }
136     hmac_ret = HMAC_Final(&hmac_ctx, mac->byte, &md_len);
137     if (md_len != sizeof(mac->byte)) {
138         fprintf(stderr, "bad md_len %d != %zd\n", md_len, sizeof(mac->byte));
139         exit(1);
140     }
141     if (!hmac_ret) {
142         fprintf(stderr, "HMAC_Final failed\n");
143         goto err;
144     }
145 
146 err:
147     HMAC_CTX_cleanup(&hmac_ctx);
148     return hmac_ret ? 0 : -1;
149 }
150 
rpmb_check_response(const char * cmd_str,enum rpmb_response response_type,struct rpmb_packet * res,int res_count,struct rpmb_key * mac,struct rpmb_nonce * nonce,uint16_t * addrp,uint32_t write_counter)151 static int rpmb_check_response(const char* cmd_str,
152                                enum rpmb_response response_type,
153                                struct rpmb_packet* res,
154                                int res_count,
155                                struct rpmb_key* mac,
156                                struct rpmb_nonce* nonce,
157                                uint16_t* addrp,
158                                uint32_t write_counter) {
159     int i;
160     for (i = 0; i < res_count; i++) {
161         if (rpmb_get_u16(res[i].req_resp) != response_type) {
162             fprintf(stderr, "%s: Bad response type, 0x%x, expected 0x%x\n",
163                     cmd_str, rpmb_get_u16(res[i].req_resp), response_type);
164             return -1;
165         }
166 
167         if (rpmb_get_u16(res[i].result) != RPMB_RES_OK) {
168             if (rpmb_get_u16(res[i].result) == RPMB_RES_ADDR_FAILURE) {
169                 fprintf(stderr, "%s: Addr failure, %u\n", cmd_str,
170                         rpmb_get_u16(res[i].address));
171                 return -ENOENT;
172             }
173             fprintf(stderr, "%s: Bad result, 0x%x\n", cmd_str,
174                     rpmb_get_u16(res[i].result));
175             return -1;
176         }
177 
178         if (i == res_count - 1 && mac &&
179             CRYPTO_memcmp(res[i].key_mac.byte, mac->byte, sizeof(mac->byte))) {
180             fprintf(stderr, "%s: Bad MAC\n", cmd_str);
181             error_report_rpmb_mac_mismatch();
182             return -1;
183         }
184 
185         if (nonce && CRYPTO_memcmp(res[i].nonce.byte, nonce->byte,
186                                    sizeof(nonce->byte))) {
187             fprintf(stderr, "%s: Bad nonce\n", cmd_str);
188             return -1;
189         }
190 
191         if (write_counter &&
192             write_counter != rpmb_get_u32(res[i].write_counter)) {
193             fprintf(stderr, "%s: Bad write counter, got %u, expected %u\n",
194                     cmd_str, rpmb_get_u32(res[i].write_counter), write_counter);
195             error_report_rpmb_counter_mismatch();
196             return -1;
197         }
198 
199         if (addrp && *addrp != rpmb_get_u16(res[i].address)) {
200             fprintf(stderr, "%s: Bad addr, got %u, expected %u\n", cmd_str,
201                     rpmb_get_u16(res[i].address), *addrp);
202             error_report_rpmb_addr_mismatch();
203             return -1;
204         }
205     }
206 
207     return 0;
208 }
209 
rpmb_program_key(struct rpmb_state * state,const struct rpmb_key * key)210 int rpmb_program_key(struct rpmb_state* state, const struct rpmb_key* key) {
211     int ret;
212     struct rpmb_packet cmd = {
213             .req_resp = rpmb_u16(RPMB_REQ_PROGRAM_KEY),
214     };
215     struct rpmb_packet rescmd = {
216             .req_resp = rpmb_u16(RPMB_REQ_RESULT_READ),
217     };
218     struct rpmb_packet res;
219 
220     memcpy(cmd.key_mac.byte, key->byte, sizeof(cmd.key_mac.byte));
221 
222     ret = rpmb_send(state->mmc_handle, &cmd, sizeof(cmd), &rescmd,
223                     sizeof(rescmd), &res, sizeof(res), false, false);
224     if (ret < 0)
225         return ret;
226 
227     rpmb_dprint_key("  key/mac       ", res.key_mac, "   expected mac ",
228                     res.key_mac);
229     rpmb_dprint_buf("  nonce         ", res.nonce.byte, sizeof(res.nonce.byte));
230     rpmb_dprint_u32("  write_counter ", res.write_counter);
231     rpmb_dprint_u16("  result        ", res.result);
232     rpmb_dprint_u16("  req/resp      ", res.req_resp);
233 
234     ret = rpmb_check_response("program key", RPMB_RESP_PROGRAM_KEY, &res, 1,
235                               NULL, NULL, NULL, 0);
236     return ret;
237 }
238 
rpmb_read_counter(struct rpmb_state * state,uint32_t * write_counter)239 static int rpmb_read_counter(struct rpmb_state* state,
240                              uint32_t* write_counter) {
241     int ret;
242     struct rpmb_key mac;
243     struct rpmb_nonce nonce = rpmb_nonce_init();
244     struct rpmb_packet cmd = {
245             .nonce = nonce,
246             .req_resp = rpmb_u16(RPMB_REQ_GET_COUNTER),
247     };
248     struct rpmb_packet res;
249 
250     ret = rpmb_send(state->mmc_handle, NULL, 0, &cmd, sizeof(cmd), &res,
251                     sizeof(res), false, false);
252     if (ret < 0)
253         return ret;
254 
255     ret = rpmb_mac(state->key, &res, 1, &mac);
256     if (ret < 0)
257         return ret;
258 
259     rpmb_dprintf("rpmb: read counter response:\n");
260     rpmb_dprint_key("  key/mac       ", res.key_mac, "   expected mac ", mac);
261     rpmb_dprint_buf("  nonce         ", res.nonce.byte, sizeof(res.nonce.byte));
262     rpmb_dprint_u32("  write_counter ", res.write_counter);
263     rpmb_dprint_u16("  result        ", res.result);
264     rpmb_dprint_u16("  req/resp      ", res.req_resp);
265 
266     ret = rpmb_check_response("read counter", RPMB_RESP_GET_COUNTER, &res, 1,
267                               &mac, &nonce, NULL, 0);
268     if (ret < 0)
269         return ret;
270 
271     if (write_counter)
272         *write_counter = rpmb_get_u32(res.write_counter);
273 
274     return 0;
275 }
276 
rpmb_read_counter_retry(struct rpmb_state * state,uint32_t * write_counter)277 static int rpmb_read_counter_retry(struct rpmb_state* state,
278                                    uint32_t* write_counter) {
279     int retries;
280     int ret = 0;
281     for (retries = 0; retries < RPMB_READ_COUNTER_MAX_RETRIES; retries++) {
282         ret = rpmb_read_counter(state, write_counter);
283         if (ret >= 0) {
284             return ret;
285         }
286     }
287 
288     /* Return the last error */
289     error_report_rpmb_counter_read_failure();
290     return ret;
291 }
292 
rpmb_read_data(struct rpmb_state * state,const void * cmp_buf,void * out_buf,uint16_t addr,uint16_t count,struct rpmb_key * mac)293 static int rpmb_read_data(struct rpmb_state* state,
294                           const void* cmp_buf,
295                           void* out_buf,
296                           uint16_t addr,
297                           uint16_t count,
298                           struct rpmb_key* mac) {
299     int i;
300     int ret;
301     struct rpmb_nonce nonce = rpmb_nonce_init();
302     struct rpmb_packet cmd = {
303         .nonce = nonce,
304         .address = rpmb_u16(addr),
305 #if RPMB_PROTOCOL == RPMB_PROTOCOL_UFS
306         .block_count = rpmb_u16(count),
307 #endif
308         .req_resp = rpmb_u16(RPMB_REQ_DATA_READ),
309     };
310     struct rpmb_packet res[MAX_PACKET_COUNT];
311     const uint8_t* cmp_bufp;
312     uint8_t* out_bufp;
313 
314     assert(count <= MAX_PACKET_COUNT);
315 
316     if (!state)
317         return -EINVAL;
318     if (state->verify_failed)
319         return -EIO;
320 
321     ret = rpmb_send(state->mmc_handle, NULL, 0, &cmd, sizeof(cmd), res,
322                     sizeof(res[0]) * count, false, false);
323     if (ret < 0)
324         return ret;
325 
326     if (mac) {
327         ret = rpmb_mac(state->key, res, count, mac);
328         if (ret < 0)
329             return ret;
330     }
331 
332     rpmb_dprintf("rpmb: read data, addr %d, count %d, response:\n", addr,
333                  count);
334     for (i = 0; i < count; i++) {
335         rpmb_dprintf("  block %d\n", i);
336         if (i == count - 1 && mac)
337             rpmb_dprint_key("    key/mac       ", res[i].key_mac,
338                             "     expected mac ", *mac);
339         rpmb_dprint_buf("    data          ", res[i].data, sizeof(res[i].data));
340         rpmb_dprint_buf("    nonce         ", res[i].nonce.byte,
341                         sizeof(res[i].nonce.byte));
342         rpmb_dprint_u16("    address       ", res[i].address);
343         rpmb_dprint_u16("    block_count   ", res[i].block_count);
344         rpmb_dprint_u16("    result        ", res[i].result);
345         rpmb_dprint_u16("    req/resp      ", res[i].req_resp);
346     }
347 
348     ret = rpmb_check_response("read data", RPMB_RESP_DATA_READ, res, count, mac,
349                               &nonce, &addr, 0);
350     if (ret < 0)
351         return ret;
352 
353     if (cmp_buf) {
354         for (cmp_bufp = cmp_buf, i = 0; i < count;
355              i++, cmp_bufp += sizeof(res[i].data)) {
356             if (memcmp(cmp_bufp, res[i].data, sizeof(res[i].data))) {
357                 fprintf(stderr, "verify read: data compare failed\n");
358                 return -1;
359             }
360         }
361     }
362 
363     if (out_buf) {
364         for (out_bufp = out_buf, i = 0; i < count;
365              i++, out_bufp += sizeof(res[i].data)) {
366             memcpy(out_bufp, res[i].data, sizeof(res[i].data));
367         }
368     }
369 
370     return 0;
371 }
372 
rpmb_read(struct rpmb_state * state,void * buf,uint16_t addr,uint16_t count)373 int rpmb_read(struct rpmb_state* state,
374               void* buf,
375               uint16_t addr,
376               uint16_t count) {
377     struct rpmb_key mac;
378     return rpmb_read_data(state, NULL, buf, addr, count, &mac);
379 }
380 
rpmb_read_no_mac(struct rpmb_state * state,void * buf,uint16_t addr,uint16_t count)381 int rpmb_read_no_mac(struct rpmb_state* state,
382                      void* buf,
383                      uint16_t addr,
384                      uint16_t count) {
385     return rpmb_read_data(state, NULL, buf, addr, count, NULL);
386 }
387 
rpmb_verify(struct rpmb_state * state,const void * buf,uint16_t addr,uint16_t count)388 int rpmb_verify(struct rpmb_state* state,
389                 const void* buf,
390                 uint16_t addr,
391                 uint16_t count) {
392     struct rpmb_key mac;
393     return rpmb_read_data(state, buf, NULL, addr, count, &mac);
394 }
395 
396 /**
397  * check_write_counter() - Check that the write counter matches
398  *                         @expected_write_counter
399  * @state:                  Current RPMB state
400  * @expected_write_counter: Write counter we expect
401  *
402  * Return: %true if the write counter is confirmed to be
403  *         @expected_write_counter
404  */
check_write_counter(struct rpmb_state * state,uint32_t expected_write_counter)405 static bool check_write_counter(struct rpmb_state* state,
406                                 uint32_t expected_write_counter) {
407     /*
408      * Query the RPMB chip for the current write counter. Although there was
409      * some sort of exceptional condition, we don't actually know if a
410      * write went through and therefore the counter was incremented.
411      */
412     int ret;
413     uint32_t new_write_counter = 0;
414     ret = rpmb_read_counter_retry(state, &new_write_counter);
415     if (ret == 0) {
416         if (new_write_counter == expected_write_counter) {
417             return true;
418         } else {
419             fprintf(stderr,
420                     "%s: Could not resync write counter. "
421                     "expected write counter: %u, queried write counter: %u\n",
422                     __func__, expected_write_counter, new_write_counter);
423         }
424     } else {
425         fprintf(stderr, "%s: rpmb_read_counter failed: %d\n", __func__, ret);
426     }
427 
428     return false;
429 }
430 
rpmb_write_data(struct rpmb_state * state,const char * buf,uint16_t addr,uint16_t count,bool sync,bool sync_checkpoint)431 static int rpmb_write_data(struct rpmb_state* state,
432                            const char* buf,
433                            uint16_t addr,
434                            uint16_t count,
435                            bool sync,
436                            bool sync_checkpoint) {
437     int i;
438     int ret;
439     struct rpmb_key mac;
440     struct rpmb_packet cmd[MAX_PACKET_COUNT];
441     struct rpmb_packet rescmd = {
442             .req_resp = rpmb_u16(RPMB_REQ_RESULT_READ),
443     };
444     struct rpmb_packet res;
445 
446     assert(count <= MAX_PACKET_COUNT);
447 
448     rpmb_dprintf("rpmb: write data, addr %d, count %d\n", addr, count);
449     for (i = 0; i < count; i++) {
450         memset(&cmd[i], 0, sizeof(cmd[i]));
451         memcpy(cmd[i].data, buf + i * sizeof(cmd[i].data), sizeof(cmd[i].data));
452         rpmb_dprint_buf("    data          ", cmd[i].data, sizeof(cmd[i].data));
453         cmd[i].write_counter = rpmb_u32(state->write_counter);
454         cmd[i].address = rpmb_u16(addr);
455         cmd[i].block_count = rpmb_u16(count);
456         cmd[i].req_resp = rpmb_u16(RPMB_REQ_DATA_WRITE);
457     }
458     ret = rpmb_mac(state->key, cmd, count, &cmd[count - 1].key_mac);
459     if (ret < 0) {
460         fprintf(stderr, "rpmb command mac failed\n");
461         return ret;
462     }
463 
464     ret = rpmb_send(state->mmc_handle, cmd, sizeof(cmd[0]) * count, &rescmd,
465                     sizeof(rescmd), &res, sizeof(res), sync, sync_checkpoint);
466     if (ret < 0) {
467         fprintf(stderr, "rpmb send failed: %d, result: %hu\n", ret,
468                 rpmb_get_u16(res.result));
469         goto err_sent;
470     }
471 
472     ret = rpmb_mac(state->key, &res, 1, &mac);
473     if (ret < 0) {
474         fprintf(stderr, "rpmb response mac failed\n");
475         goto err_sent;
476     }
477 
478     rpmb_dprintf(
479             "rpmb: write data, addr %d, count %d, write_counter %d, response\n",
480             addr, count, state->write_counter);
481     rpmb_dprint_key("  key/mac       ", res.key_mac, "   expected mac ", mac);
482     rpmb_dprint_buf("  nonce         ", res.nonce.byte, sizeof(res.nonce.byte));
483     rpmb_dprint_u32("  write_counter ", res.write_counter);
484     rpmb_dprint_u16("  address       ", res.address);
485     rpmb_dprint_u16("  result        ", res.result);
486     rpmb_dprint_u16("  req/resp      ", res.req_resp);
487 
488     ret = rpmb_check_response("write data", RPMB_RESP_DATA_WRITE, &res, 1, &mac,
489                               NULL, &addr, state->write_counter + 1);
490     if (ret < 0) {
491         fprintf(stderr, "rpmb_check_response_failed: %d, result: %hu\n", ret,
492                 rpmb_get_u16(res.result));
493         if (check_write_counter(state, state->write_counter + 1)) {
494             state->write_counter++;
495 
496             fprintf(stderr,
497                     "Write was committed with failed response. New write counter: %u\n",
498                     state->write_counter);
499             error_report_rpmb_counter_mismatch_recovered();
500 
501             /*
502              * Indicate to block device that the FS state is unknown and a clean
503              * superblock must be written.
504              */
505             ret = -EUCLEAN;
506         }
507 
508         goto err_sent;
509     }
510 
511     state->write_counter++;
512 
513     return 0;
514 
515 err_sent:
516     /*
517      * An error occurred after the write request was sent. An attacker might
518      * have saved this write request and might send it to the rpmb device at
519      * any time. Any other write with this write counter value now needs extra
520      * checks to make sure there is no corruption.
521      *
522      * 1. The next write fails.
523      *
524      * 1.1. The failure is a count failure.
525      * A write operation that was previously reported as an error must have
526      * actually been written. The filesystem may now be in a state where is it
527      * not safe to write any other block. The write that actually went through
528      * may have been from a previous write attempt, so we don't know the current
529      * state.
530      *
531      * We pass BLOCK_WRITE_FAILED_UNKNOWN_STATE to block_cache_complete_write()
532      * in this case which causes the block device to queue writes of all
533      * filesystem superblocks before doing any new writes.
534      *
535      * 1.1.1. The block actually written was a super-block.
536      * This means a transaction was committed to disk that the file-system code
537      * thought was aborted. The in-memory view of free blocks will not match the
538      * on disk state. It is not safe to proceed with any other write operations
539      * in this state as the file-system could pick a block to write to that is
540      * not actually free until the super block gets updated again with the
541      * in-memory state.
542      *
543      * We mitigate this case by immediately rewriting a new, valid super-block
544      * with the current in-memory (i.e. not including the current, failing
545      * transaction) state when a super-block write fails. If this second write
546      * fails, we are left with a failed transaction in fs->inital_super_block_tr
547      * and all future writes to this filesystem will fail. If it succeeds we
548      * validate the write in 2.1 below. If the device reboots before completing
549      * the second super-block write attempt, a malicious host can replay this
550      * block on a later boot. In the case of TD filesystems, this can cause
551      * detectable filesystem corruption as data blocks may not match the
552      * super-block now, however, that is allowed. For TP filesystems, the next
553      * data write will be validated as it is the first RPMB write after boot,
554      * and if it fails we abort the service (2.1.1), forcing a reboot and
555      * re-initializing the filesystem state from the now committed super-block.
556      *
557      * It's worth noting that in this case, we may have sent a failed response
558      * to a client for a transaction that was eventually committed.
559      *
560      * 1.1.2. The block actually written was a data block.
561      *
562      * The write must have been to a block that was free, and the transaction
563      * that block was part of could never have been committed. We don't actually
564      * care about this write, but we rewrite the superblock as described in
565      * 1.1.1. because we can't know what was written.
566      *
567      * 1.2. The failure is not reported as count failure.
568      * This can be handled the same way as the inital failure. We now have one
569      * more possible write request that can be saved and written at any time by
570      * an attacker, but it is in the same class as before.
571      *
572      * 2. The next write succeeds.
573      *
574      * 2.1. The same block number and counter value has already been sent.
575      * This success status cannot be trusted. We read back the data to verify.
576      * 2.1.1. Verify failed.
577      * This has the same effect as 1.1. We currently block all further
578      * read/write operations after this point (until reboot or FS re-mount)
579      * because it is not safe to recover from this state in a TP filesystem.
580      *
581      * 2.1.2. Verify passed.
582      * We are back to a normal state.
583      *
584      * 2.2. The same block number and counter has not already been sent.
585      * We are back to a normal state.
586      */
587     fprintf(stderr, "rpmb: write failed for write counter %u\n",
588             state->write_counter);
589     state->first_write_complete = false;
590     return ret;
591 }
592 
rpmb_write(struct rpmb_state * state,const void * buf,uint16_t addr,uint16_t count,bool sync,bool sync_checkpoint)593 int rpmb_write(struct rpmb_state* state,
594                const void* buf,
595                uint16_t addr,
596                uint16_t count,
597                bool sync,
598                bool sync_checkpoint) {
599     int ret;
600 
601     if (!state)
602         return -EINVAL;
603     if (state->verify_failed)
604         return -EIO;
605 
606     ret = rpmb_write_data(state, buf, addr, count, sync, sync_checkpoint);
607     if (ret < 0)
608         return ret;
609 
610     if (!state->first_write_complete) {
611         /*
612          * The first write request after reading the write counter could get a
613          * signed response from a different write request. There is no nonce in
614          * the write request, only a write counter. The response could be from
615          * another valid write request we generated on a previous boot that was
616          * not completed. Read back the data and verify that the correct data
617          * was written for this case. Note that this only works if we never
618          * send more than one write request to the non-secure proxy at once. If
619          * we later add support for pipelining rpmb operation we need to verify
620          * the first n write requests here instead, where n is the max pipeline
621          * depth of any build that may have run on the same device. We would
622          * also need ensure that a superblock write request is not sent until
623          * all other write requests have been validated and that an attacker
624          * cannot have any saved write requests to the same filesystem with a
625          * larger write-counter value than the superblock update (e.g. by
626          * repeating a non-superblock write request until only one write
627          * operation remains to be verified).
628          */
629         ret = rpmb_verify(state, buf, addr, count);
630         if (ret < 0) {
631             fprintf(stderr,
632                     "rpmb write verify failure: %d, addr: %hu, count: %hu\n",
633                     ret, addr, count);
634             state->verify_failed = true;
635             return ret;
636         }
637         state->first_write_complete = true;
638     }
639 
640     return 0;
641 }
642 
rpmb_set_key(struct rpmb_state * state,const struct rpmb_key * key)643 void rpmb_set_key(struct rpmb_state* state, const struct rpmb_key* key) {
644     assert(state);
645     state->key = *key;
646 
647     /*
648      * We need to read the counter before reading the super blocks. If an
649      * attacker writes to a super block after we read it, but before we read the
650      * write counter, or next write would succeed without us detecting that the
651      * in-memory super block does not match the on-disk state.
652      *
653      * We retry reading the write counter several times because
654      * we occasionally get an incorrect response
655      */
656     int ret;
657     ret = rpmb_read_counter_retry(state, &state->write_counter);
658     if (ret < 0) {
659         fprintf(stderr, "failed to read rpmb write counter\n");
660         /*
661          * Ignore errors. Any future write will fail since we initialized the
662          * write_counter with the value where it expires.
663          */
664     }
665 }
666 
rpmb_init(struct rpmb_state ** statep,void * mmc_handle)667 int rpmb_init(struct rpmb_state** statep, void* mmc_handle) {
668     struct rpmb_state* state = malloc(sizeof(*state));
669     if (!state)
670         return -ENOMEM;
671 
672     state->mmc_handle = mmc_handle;
673     state->write_counter = RPMB_WRITE_COUNTER_EXPIRED_VALUE;
674     /*
675      * We don't know if the last write before reboot completed successfully.
676      * There may be writes for the current write counter that can be replayed at
677      * this point, so we need to validate our next write.
678      */
679     state->first_write_complete = false;
680     state->verify_failed = false;
681 
682     *statep = state;
683 
684     return 0;
685 }
686 
rpmb_uninit(struct rpmb_state * statep)687 void rpmb_uninit(struct rpmb_state* statep) {
688     free(statep);
689 }
690