uboot/common/avb_verify.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2018, Linaro Limited
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <avb_verify.h>
   8#include <blk.h>
   9#include <cpu_func.h>
  10#include <image.h>
  11#include <malloc.h>
  12#include <part.h>
  13#include <tee.h>
  14#include <tee/optee_ta_avb.h>
  15
  16static const unsigned char avb_root_pub[1032] = {
  17        0x0, 0x0, 0x10, 0x0, 0x55, 0xd9, 0x4, 0xad, 0xd8, 0x4,
  18        0xaf, 0xe3, 0xd3, 0x84, 0x6c, 0x7e, 0xd, 0x89, 0x3d, 0xc2,
  19        0x8c, 0xd3, 0x12, 0x55, 0xe9, 0x62, 0xc9, 0xf1, 0xf, 0x5e,
  20        0xcc, 0x16, 0x72, 0xab, 0x44, 0x7c, 0x2c, 0x65, 0x4a, 0x94,
  21        0xb5, 0x16, 0x2b, 0x0, 0xbb, 0x6, 0xef, 0x13, 0x7, 0x53,
  22        0x4c, 0xf9, 0x64, 0xb9, 0x28, 0x7a, 0x1b, 0x84, 0x98, 0x88,
  23        0xd8, 0x67, 0xa4, 0x23, 0xf9, 0xa7, 0x4b, 0xdc, 0x4a, 0xf,
  24        0xf7, 0x3a, 0x18, 0xae, 0x54, 0xa8, 0x15, 0xfe, 0xb0, 0xad,
  25        0xac, 0x35, 0xda, 0x3b, 0xad, 0x27, 0xbc, 0xaf, 0xe8, 0xd3,
  26        0x2f, 0x37, 0x34, 0xd6, 0x51, 0x2b, 0x6c, 0x5a, 0x27, 0xd7,
  27        0x96, 0x6, 0xaf, 0x6b, 0xb8, 0x80, 0xca, 0xfa, 0x30, 0xb4,
  28        0xb1, 0x85, 0xb3, 0x4d, 0xaa, 0xaa, 0xc3, 0x16, 0x34, 0x1a,
  29        0xb8, 0xe7, 0xc7, 0xfa, 0xf9, 0x9, 0x77, 0xab, 0x97, 0x93,
  30        0xeb, 0x44, 0xae, 0xcf, 0x20, 0xbc, 0xf0, 0x80, 0x11, 0xdb,
  31        0x23, 0xc, 0x47, 0x71, 0xb9, 0x6d, 0xd6, 0x7b, 0x60, 0x47,
  32        0x87, 0x16, 0x56, 0x93, 0xb7, 0xc2, 0x2a, 0x9a, 0xb0, 0x4c,
  33        0x1, 0xc, 0x30, 0xd8, 0x93, 0x87, 0xf0, 0xed, 0x6e, 0x8b,
  34        0xbe, 0x30, 0x5b, 0xf6, 0xa6, 0xaf, 0xdd, 0x80, 0x7c, 0x45,
  35        0x5e, 0x8f, 0x91, 0x93, 0x5e, 0x44, 0xfe, 0xb8, 0x82, 0x7,
  36        0xee, 0x79, 0xca, 0xbf, 0x31, 0x73, 0x62, 0x58, 0xe3, 0xcd,
  37        0xc4, 0xbc, 0xc2, 0x11, 0x1d, 0xa1, 0x4a, 0xbf, 0xfe, 0x27,
  38        0x7d, 0xa1, 0xf6, 0x35, 0xa3, 0x5e, 0xca, 0xdc, 0x57, 0x2f,
  39        0x3e, 0xf0, 0xc9, 0x5d, 0x86, 0x6a, 0xf8, 0xaf, 0x66, 0xa7,
  40        0xed, 0xcd, 0xb8, 0xed, 0xa1, 0x5f, 0xba, 0x9b, 0x85, 0x1a,
  41        0xd5, 0x9, 0xae, 0x94, 0x4e, 0x3b, 0xcf, 0xcb, 0x5c, 0xc9,
  42        0x79, 0x80, 0xf7, 0xcc, 0xa6, 0x4a, 0xa8, 0x6a, 0xd8, 0xd3,
  43        0x31, 0x11, 0xf9, 0xf6, 0x2, 0x63, 0x2a, 0x1a, 0x2d, 0xd1,
  44        0x1a, 0x66, 0x1b, 0x16, 0x41, 0xbd, 0xbd, 0xf7, 0x4d, 0xc0,
  45        0x4a, 0xe5, 0x27, 0x49, 0x5f, 0x7f, 0x58, 0xe3, 0x27, 0x2d,
  46        0xe5, 0xc9, 0x66, 0xe, 0x52, 0x38, 0x16, 0x38, 0xfb, 0x16,
  47        0xeb, 0x53, 0x3f, 0xe6, 0xfd, 0xe9, 0xa2, 0x5e, 0x25, 0x59,
  48        0xd8, 0x79, 0x45, 0xff, 0x3, 0x4c, 0x26, 0xa2, 0x0, 0x5a,
  49        0x8e, 0xc2, 0x51, 0xa1, 0x15, 0xf9, 0x7b, 0xf4, 0x5c, 0x81,
  50        0x9b, 0x18, 0x47, 0x35, 0xd8, 0x2d, 0x5, 0xe9, 0xad, 0xf,
  51        0x35, 0x74, 0x15, 0xa3, 0x8e, 0x8b, 0xcc, 0x27, 0xda, 0x7c,
  52        0x5d, 0xe4, 0xfa, 0x4, 0xd3, 0x5, 0xb, 0xba, 0x3a, 0xb2,
  53        0x49, 0x45, 0x2f, 0x47, 0xc7, 0xd, 0x41, 0x3f, 0x97, 0x80,
  54        0x4d, 0x3f, 0xc1, 0xb5, 0xbb, 0x70, 0x5f, 0xa7, 0x37, 0xaf,
  55        0x48, 0x22, 0x12, 0x45, 0x2e, 0xf5, 0xf, 0x87, 0x92, 0xe2,
  56        0x84, 0x1, 0xf9, 0x12, 0xf, 0x14, 0x15, 0x24, 0xce, 0x89,
  57        0x99, 0xee, 0xb9, 0xc4, 0x17, 0x70, 0x70, 0x15, 0xea, 0xbe,
  58        0xc6, 0x6c, 0x1f, 0x62, 0xb3, 0xf4, 0x2d, 0x16, 0x87, 0xfb,
  59        0x56, 0x1e, 0x45, 0xab, 0xae, 0x32, 0xe4, 0x5e, 0x91, 0xed,
  60        0x53, 0x66, 0x5e, 0xbd, 0xed, 0xad, 0xe6, 0x12, 0x39, 0xd,
  61        0x83, 0xc9, 0xe8, 0x6b, 0x6c, 0x2d, 0xa5, 0xee, 0xc4, 0x5a,
  62        0x66, 0xae, 0x8c, 0x97, 0xd7, 0xd, 0x6c, 0x49, 0xc7, 0xf5,
  63        0xc4, 0x92, 0x31, 0x8b, 0x9, 0xee, 0x33, 0xda, 0xa9, 0x37,
  64        0xb6, 0x49, 0x18, 0xf8, 0xe, 0x60, 0x45, 0xc8, 0x33, 0x91,
  65        0xef, 0x20, 0x57, 0x10, 0xbe, 0x78, 0x2d, 0x83, 0x26, 0xd6,
  66        0xca, 0x61, 0xf9, 0x2f, 0xe0, 0xbf, 0x5, 0x30, 0x52, 0x5a,
  67        0x12, 0x1c, 0x0, 0xa7, 0x5d, 0xcc, 0x7c, 0x2e, 0xc5, 0x95,
  68        0x8b, 0xa3, 0x3b, 0xf0, 0x43, 0x2e, 0x5e, 0xdd, 0x0, 0xdb,
  69        0xd, 0xb3, 0x37, 0x99, 0xa9, 0xcd, 0x9c, 0xb7, 0x43, 0xf7,
  70        0x35, 0x44, 0x21, 0xc2, 0x82, 0x71, 0xab, 0x8d, 0xaa, 0xb4,
  71        0x41, 0x11, 0xec, 0x1e, 0x8d, 0xfc, 0x14, 0x82, 0x92, 0x4e,
  72        0x83, 0x6a, 0xa, 0x6b, 0x35, 0x5e, 0x5d, 0xe9, 0x5c, 0xcc,
  73        0x8c, 0xde, 0x39, 0xd1, 0x4a, 0x5b, 0x5f, 0x63, 0xa9, 0x64,
  74        0xe0, 0xa, 0xcb, 0xb, 0xb8, 0x5a, 0x7c, 0xc3, 0xb, 0xe6,
  75        0xbe, 0xfe, 0x8b, 0xf, 0x7d, 0x34, 0x8e, 0x2, 0x66, 0x74,
  76        0x1, 0x6c, 0xca, 0x76, 0xac, 0x7c, 0x67, 0x8, 0x2f, 0x3f,
  77        0x1a, 0xa6, 0x2c, 0x60, 0xb3, 0xff, 0xda, 0x8d, 0xb8, 0x12,
  78        0xc, 0x0, 0x7f, 0xcc, 0x50, 0xa1, 0x5c, 0x64, 0xa1, 0xe2,
  79        0x5f, 0x32, 0x65, 0xc9, 0x9c, 0xbe, 0xd6, 0xa, 0x13, 0x87,
  80        0x3c, 0x2a, 0x45, 0x47, 0xc, 0xca, 0x42, 0x82, 0xfa, 0x89,
  81        0x65, 0xe7, 0x89, 0xb4, 0x8f, 0xf7, 0x1e, 0xe6, 0x23, 0xa5,
  82        0xd0, 0x59, 0x37, 0x79, 0x92, 0xd7, 0xce, 0x3d, 0xfd, 0xe3,
  83        0xa1, 0xb, 0xcf, 0x6c, 0x85, 0xa0, 0x65, 0xf3, 0x5c, 0xc6,
  84        0x4a, 0x63, 0x5f, 0x6e, 0x3a, 0x3a, 0x2a, 0x8b, 0x6a, 0xb6,
  85        0x2f, 0xbb, 0xf8, 0xb2, 0x4b, 0x62, 0xbc, 0x1a, 0x91, 0x25,
  86        0x66, 0xe3, 0x69, 0xca, 0x60, 0x49, 0xb, 0xf6, 0x8a, 0xbe,
  87        0x3e, 0x76, 0x53, 0xc2, 0x7a, 0xa8, 0x4, 0x17, 0x75, 0xf1,
  88        0xf3, 0x3, 0x62, 0x1b, 0x85, 0xb2, 0xb0, 0xef, 0x80, 0x15,
  89        0xb6, 0xd4, 0x4e, 0xdf, 0x71, 0xac, 0xdb, 0x2a, 0x4, 0xd4,
  90        0xb4, 0x21, 0xba, 0x65, 0x56, 0x57, 0xe8, 0xfa, 0x84, 0xa2,
  91        0x7d, 0x13, 0xe, 0xaf, 0xd7, 0x9a, 0x58, 0x2a, 0xa3, 0x81,
  92        0x84, 0x8d, 0x9, 0xa0, 0x6a, 0xc1, 0xbb, 0xd9, 0xf5, 0x86,
  93        0xac, 0xbd, 0x75, 0x61, 0x9, 0xe6, 0x8c, 0x3d, 0x77, 0xb2,
  94        0xed, 0x30, 0x20, 0xe4, 0x0, 0x1d, 0x97, 0xe8, 0xbf, 0xc7,
  95        0x0, 0x1b, 0x21, 0xb1, 0x16, 0xe7, 0x41, 0x67, 0x2e, 0xec,
  96        0x38, 0xbc, 0xe5, 0x1b, 0xb4, 0x6, 0x23, 0x31, 0x71, 0x1c,
  97        0x49, 0xcd, 0x76, 0x4a, 0x76, 0x36, 0x8d, 0xa3, 0x89, 0x8b,
  98        0x4a, 0x7a, 0xf4, 0x87, 0xc8, 0x15, 0xf, 0x37, 0x39, 0xf6,
  99        0x6d, 0x80, 0x19, 0xef, 0x5c, 0xa8, 0x66, 0xce, 0x1b, 0x16,
 100        0x79, 0x21, 0xdf, 0xd7, 0x31, 0x30, 0xc4, 0x21, 0xdd, 0x34,
 101        0x5b, 0xd2, 0x1a, 0x2b, 0x3e, 0x5d, 0xf7, 0xea, 0xca, 0x5,
 102        0x8e, 0xb7, 0xcb, 0x49, 0x2e, 0xa0, 0xe3, 0xf4, 0xa7, 0x48,
 103        0x19, 0x10, 0x9c, 0x4, 0xa7, 0xf4, 0x28, 0x74, 0xc8, 0x6f,
 104        0x63, 0x20, 0x2b, 0x46, 0x24, 0x26, 0x19, 0x1d, 0xd1, 0x2c,
 105        0x31, 0x6d, 0x5a, 0x29, 0xa2, 0x6, 0xa6, 0xb2, 0x41, 0xcc,
 106        0xa, 0x27, 0x96, 0x9, 0x96, 0xac, 0x47, 0x65, 0x78, 0x68,
 107        0x51, 0x98, 0xd6, 0xd8, 0xa6, 0x2d, 0xa0, 0xcf, 0xec, 0xe2,
 108        0x74, 0xf2, 0x82, 0xe3, 0x97, 0xd9, 0x7e, 0xd4, 0xf8, 0xb,
 109        0x70, 0x43, 0x3d, 0xb1, 0x7b, 0x97, 0x80, 0xd6, 0xcb, 0xd7,
 110        0x19, 0xbc, 0x63, 0xb, 0xfd, 0x4d, 0x88, 0xfe, 0x67, 0xac,
 111        0xb8, 0xcc, 0x50, 0xb7, 0x68, 0xb3, 0x5b, 0xd6, 0x1e, 0x25,
 112        0xfc, 0x5f, 0x3c, 0x8d, 0xb1, 0x33, 0x7c, 0xb3, 0x49, 0x1,
 113        0x3f, 0x71, 0x55, 0xe, 0x51, 0xba, 0x61, 0x26, 0xfa, 0xea,
 114        0xe5, 0xb5, 0xe8, 0xaa, 0xcf, 0xcd, 0x96, 0x9f, 0xd6, 0xc1,
 115        0x5f, 0x53, 0x91, 0xad, 0x5, 0xde, 0x20, 0xe7, 0x51, 0xda,
 116        0x5b, 0x95, 0x67, 0xed, 0xf4, 0xee, 0x42, 0x65, 0x70, 0x13,
 117        0xb, 0x70, 0x14, 0x1c, 0xc9, 0xe0, 0x19, 0xca, 0x5f, 0xf5,
 118        0x1d, 0x70, 0x4b, 0x6c, 0x6, 0x74, 0xec, 0xb5, 0x2e, 0x77,
 119        0xe1, 0x74, 0xa1, 0xa3, 0x99, 0xa0, 0x85, 0x9e, 0xf1, 0xac,
 120        0xd8, 0x7e,
 121};
 122
 123/**
 124 * ============================================================================
 125 * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity
 126 * ============================================================================
 127 */
 128char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state)
 129{
 130        struct AvbOpsData *data;
 131        char *cmdline = NULL;
 132
 133        if (!ops)
 134                return NULL;
 135
 136        data = (struct AvbOpsData *)ops->user_data;
 137        if (!data)
 138                return NULL;
 139
 140        data->boot_state = boot_state;
 141        switch (boot_state) {
 142        case AVB_GREEN:
 143                cmdline = "androidboot.verifiedbootstate=green";
 144                break;
 145        case AVB_YELLOW:
 146                cmdline = "androidboot.verifiedbootstate=yellow";
 147                break;
 148        case AVB_ORANGE:
 149                cmdline = "androidboot.verifiedbootstate=orange";
 150        case AVB_RED:
 151                break;
 152        }
 153
 154        return cmdline;
 155}
 156
 157char *append_cmd_line(char *cmdline_orig, char *cmdline_new)
 158{
 159        char *cmd_line;
 160
 161        if (!cmdline_new)
 162                return cmdline_orig;
 163
 164        if (cmdline_orig)
 165                cmd_line = cmdline_orig;
 166        else
 167                cmd_line = " ";
 168
 169        cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL);
 170
 171        return cmd_line;
 172}
 173
 174static int avb_find_dm_args(char **args, char *str)
 175{
 176        int i;
 177
 178        if (!str)
 179                return -1;
 180
 181        for (i = 0; i < AVB_MAX_ARGS && args[i]; ++i) {
 182                if (strstr(args[i], str))
 183                        return i;
 184        }
 185
 186        return -1;
 187}
 188
 189static char *avb_set_enforce_option(const char *cmdline, const char *option)
 190{
 191        char *cmdarg[AVB_MAX_ARGS];
 192        char *newargs = NULL;
 193        int i = 0;
 194        int total_args;
 195
 196        memset(cmdarg, 0, sizeof(cmdarg));
 197        cmdarg[i++] = strtok((char *)cmdline, " ");
 198
 199        do {
 200                cmdarg[i] = strtok(NULL, " ");
 201                if (!cmdarg[i])
 202                        break;
 203
 204                if (++i >= AVB_MAX_ARGS) {
 205                        printf("%s: Can't handle more then %d args\n",
 206                               __func__, i);
 207                        return NULL;
 208                }
 209        } while (true);
 210
 211        total_args = i;
 212        i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_LOGGING);
 213        if (i >= 0) {
 214                cmdarg[i] = (char *)option;
 215        } else {
 216                i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_RESTART);
 217                if (i < 0) {
 218                        printf("%s: No verity options found\n", __func__);
 219                        return NULL;
 220                }
 221
 222                cmdarg[i] = (char *)option;
 223        }
 224
 225        for (i = 0; i <= total_args; i++)
 226                newargs = append_cmd_line(newargs, cmdarg[i]);
 227
 228        return newargs;
 229}
 230
 231char *avb_set_ignore_corruption(const char *cmdline)
 232{
 233        char *newargs = NULL;
 234
 235        newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING);
 236        if (newargs)
 237                newargs = append_cmd_line(newargs,
 238                                          "androidboot.veritymode=eio");
 239
 240        return newargs;
 241}
 242
 243char *avb_set_enforce_verity(const char *cmdline)
 244{
 245        char *newargs;
 246
 247        newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_RESTART);
 248        if (newargs)
 249                newargs = append_cmd_line(newargs,
 250                                          "androidboot.veritymode=enforcing");
 251        return newargs;
 252}
 253
 254/**
 255 * ============================================================================
 256 * IO(mmc) auxiliary functions
 257 * ============================================================================
 258 */
 259static unsigned long mmc_read_and_flush(struct mmc_part *part,
 260                                        lbaint_t start,
 261                                        lbaint_t sectors,
 262                                        void *buffer)
 263{
 264        unsigned long blks;
 265        void *tmp_buf;
 266        size_t buf_size;
 267        bool unaligned = is_buf_unaligned(buffer);
 268
 269        if (start < part->info.start) {
 270                printf("%s: partition start out of bounds\n", __func__);
 271                return 0;
 272        }
 273        if ((start + sectors) > (part->info.start + part->info.size)) {
 274                sectors = part->info.start + part->info.size - start;
 275                printf("%s: read sector aligned to partition bounds (%ld)\n",
 276                       __func__, sectors);
 277        }
 278
 279        /*
 280         * Reading fails on unaligned buffers, so we have to
 281         * use aligned temporary buffer and then copy to destination
 282         */
 283
 284        if (unaligned) {
 285                printf("Handling unaligned read buffer..\n");
 286                tmp_buf = get_sector_buf();
 287                buf_size = get_sector_buf_size();
 288                if (sectors > buf_size / part->info.blksz)
 289                        sectors = buf_size / part->info.blksz;
 290        } else {
 291                tmp_buf = buffer;
 292        }
 293
 294        blks = blk_dread(part->mmc_blk,
 295                         start, sectors, tmp_buf);
 296        /* flush cache after read */
 297        flush_cache((ulong)tmp_buf, sectors * part->info.blksz);
 298
 299        if (unaligned)
 300                memcpy(buffer, tmp_buf, sectors * part->info.blksz);
 301
 302        return blks;
 303}
 304
 305static unsigned long mmc_write(struct mmc_part *part, lbaint_t start,
 306                               lbaint_t sectors, void *buffer)
 307{
 308        void *tmp_buf;
 309        size_t buf_size;
 310        bool unaligned = is_buf_unaligned(buffer);
 311
 312        if (start < part->info.start) {
 313                printf("%s: partition start out of bounds\n", __func__);
 314                return 0;
 315        }
 316        if ((start + sectors) > (part->info.start + part->info.size)) {
 317                sectors = part->info.start + part->info.size - start;
 318                printf("%s: sector aligned to partition bounds (%ld)\n",
 319                       __func__, sectors);
 320        }
 321        if (unaligned) {
 322                tmp_buf = get_sector_buf();
 323                buf_size = get_sector_buf_size();
 324                printf("Handling unaligned wrire buffer..\n");
 325                if (sectors > buf_size / part->info.blksz)
 326                        sectors = buf_size / part->info.blksz;
 327
 328                memcpy(tmp_buf, buffer, sectors * part->info.blksz);
 329        } else {
 330                tmp_buf = buffer;
 331        }
 332
 333        return blk_dwrite(part->mmc_blk,
 334                          start, sectors, tmp_buf);
 335}
 336
 337static struct mmc_part *get_partition(AvbOps *ops, const char *partition)
 338{
 339        int ret;
 340        u8 dev_num;
 341        int part_num = 0;
 342        struct mmc_part *part;
 343        struct blk_desc *mmc_blk;
 344
 345        part = malloc(sizeof(struct mmc_part));
 346        if (!part)
 347                return NULL;
 348
 349        dev_num = get_boot_device(ops);
 350        part->mmc = find_mmc_device(dev_num);
 351        if (!part->mmc) {
 352                printf("No MMC device at slot %x\n", dev_num);
 353                goto err;
 354        }
 355
 356        if (mmc_init(part->mmc)) {
 357                printf("MMC initialization failed\n");
 358                goto err;
 359        }
 360
 361        ret = mmc_switch_part(part->mmc, part_num);
 362        if (ret)
 363                goto err;
 364
 365        mmc_blk = mmc_get_blk_desc(part->mmc);
 366        if (!mmc_blk) {
 367                printf("Error - failed to obtain block descriptor\n");
 368                goto err;
 369        }
 370
 371        ret = part_get_info_by_name(mmc_blk, partition, &part->info);
 372        if (!ret) {
 373                printf("Can't find partition '%s'\n", partition);
 374                goto err;
 375        }
 376
 377        part->dev_num = dev_num;
 378        part->mmc_blk = mmc_blk;
 379
 380        return part;
 381err:
 382        free(part);
 383        return NULL;
 384}
 385
 386static AvbIOResult mmc_byte_io(AvbOps *ops,
 387                               const char *partition,
 388                               s64 offset,
 389                               size_t num_bytes,
 390                               void *buffer,
 391                               size_t *out_num_read,
 392                               enum mmc_io_type io_type)
 393{
 394        ulong ret;
 395        struct mmc_part *part;
 396        u64 start_offset, start_sector, sectors, residue;
 397        u8 *tmp_buf;
 398        size_t io_cnt = 0;
 399
 400        if (!partition || !buffer || io_type > IO_WRITE)
 401                return AVB_IO_RESULT_ERROR_IO;
 402
 403        part = get_partition(ops, partition);
 404        if (!part)
 405                return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
 406
 407        if (!part->info.blksz)
 408                return AVB_IO_RESULT_ERROR_IO;
 409
 410        start_offset = calc_offset(part, offset);
 411        while (num_bytes) {
 412                start_sector = start_offset / part->info.blksz;
 413                sectors = num_bytes / part->info.blksz;
 414                /* handle non block-aligned reads */
 415                if (start_offset % part->info.blksz ||
 416                    num_bytes < part->info.blksz) {
 417                        tmp_buf = get_sector_buf();
 418                        if (start_offset % part->info.blksz) {
 419                                residue = part->info.blksz -
 420                                        (start_offset % part->info.blksz);
 421                                if (residue > num_bytes)
 422                                        residue = num_bytes;
 423                        } else {
 424                                residue = num_bytes;
 425                        }
 426
 427                        if (io_type == IO_READ) {
 428                                ret = mmc_read_and_flush(part,
 429                                                         part->info.start +
 430                                                         start_sector,
 431                                                         1, tmp_buf);
 432
 433                                if (ret != 1) {
 434                                        printf("%s: read error (%ld, %lld)\n",
 435                                               __func__, ret, start_sector);
 436                                        return AVB_IO_RESULT_ERROR_IO;
 437                                }
 438                                /*
 439                                 * if this is not aligned at sector start,
 440                                 * we have to adjust the tmp buffer
 441                                 */
 442                                tmp_buf += (start_offset % part->info.blksz);
 443                                memcpy(buffer, (void *)tmp_buf, residue);
 444                        } else {
 445                                ret = mmc_read_and_flush(part,
 446                                                         part->info.start +
 447                                                         start_sector,
 448                                                         1, tmp_buf);
 449
 450                                if (ret != 1) {
 451                                        printf("%s: read error (%ld, %lld)\n",
 452                                               __func__, ret, start_sector);
 453                                        return AVB_IO_RESULT_ERROR_IO;
 454                                }
 455                                memcpy((void *)tmp_buf +
 456                                        start_offset % part->info.blksz,
 457                                        buffer, residue);
 458
 459                                ret = mmc_write(part, part->info.start +
 460                                                start_sector, 1, tmp_buf);
 461                                if (ret != 1) {
 462                                        printf("%s: write error (%ld, %lld)\n",
 463                                               __func__, ret, start_sector);
 464                                        return AVB_IO_RESULT_ERROR_IO;
 465                                }
 466                        }
 467
 468                        io_cnt += residue;
 469                        buffer += residue;
 470                        start_offset += residue;
 471                        num_bytes -= residue;
 472                        continue;
 473                }
 474
 475                if (sectors) {
 476                        if (io_type == IO_READ) {
 477                                ret = mmc_read_and_flush(part,
 478                                                         part->info.start +
 479                                                         start_sector,
 480                                                         sectors, buffer);
 481                        } else {
 482                                ret = mmc_write(part,
 483                                                part->info.start +
 484                                                start_sector,
 485                                                sectors, buffer);
 486                        }
 487
 488                        if (!ret) {
 489                                printf("%s: sector read error\n", __func__);
 490                                return AVB_IO_RESULT_ERROR_IO;
 491                        }
 492
 493                        io_cnt += ret * part->info.blksz;
 494                        buffer += ret * part->info.blksz;
 495                        start_offset += ret * part->info.blksz;
 496                        num_bytes -= ret * part->info.blksz;
 497                }
 498        }
 499
 500        /* Set counter for read operation */
 501        if (io_type == IO_READ && out_num_read)
 502                *out_num_read = io_cnt;
 503
 504        return AVB_IO_RESULT_OK;
 505}
 506
 507/**
 508 * ============================================================================
 509 * AVB 2.0 operations
 510 * ============================================================================
 511 */
 512
 513/**
 514 * read_from_partition() - reads @num_bytes from  @offset from partition
 515 * identified by a string name
 516 *
 517 * @ops: contains AVB ops handlers
 518 * @partition_name: partition name, NUL-terminated UTF-8 string
 519 * @offset: offset from the beginning of partition
 520 * @num_bytes: amount of bytes to read
 521 * @buffer: destination buffer to store data
 522 * @out_num_read:
 523 *
 524 * @return:
 525 *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
 526 *      AVB_IO_RESULT_ERROR_IO, if i/o error occurred from the underlying i/o
 527 *            subsystem
 528 *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with
 529 *      the given name
 530 */
 531static AvbIOResult read_from_partition(AvbOps *ops,
 532                                       const char *partition_name,
 533                                       s64 offset_from_partition,
 534                                       size_t num_bytes,
 535                                       void *buffer,
 536                                       size_t *out_num_read)
 537{
 538        return mmc_byte_io(ops, partition_name, offset_from_partition,
 539                           num_bytes, buffer, out_num_read, IO_READ);
 540}
 541
 542/**
 543 * write_to_partition() - writes N bytes to a partition identified by a string
 544 * name
 545 *
 546 * @ops: AvbOps, contains AVB ops handlers
 547 * @partition_name: partition name
 548 * @offset_from_partition: offset from the beginning of partition
 549 * @num_bytes: amount of bytes to write
 550 * @buf: data to write
 551 * @out_num_read:
 552 *
 553 * @return:
 554 *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
 555 *      AVB_IO_RESULT_ERROR_IO, if input/output error occurred
 556 *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition, specified in
 557 *            @partition_name was not found
 558 */
 559static AvbIOResult write_to_partition(AvbOps *ops,
 560                                      const char *partition_name,
 561                                      s64 offset_from_partition,
 562                                      size_t num_bytes,
 563                                      const void *buffer)
 564{
 565        return mmc_byte_io(ops, partition_name, offset_from_partition,
 566                           num_bytes, (void *)buffer, NULL, IO_WRITE);
 567}
 568
 569/**
 570 * validate_vmbeta_public_key() - checks if the given public key used to sign
 571 * the vbmeta partition is trusted
 572 *
 573 * @ops: AvbOps, contains AVB ops handlers
 574 * @public_key_data: public key for verifying vbmeta partition signature
 575 * @public_key_length: length of public key
 576 * @public_key_metadata:
 577 * @public_key_metadata_length:
 578 * @out_key_is_trusted:
 579 *
 580 * @return:
 581 *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
 582 */
 583static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
 584                                              const u8 *public_key_data,
 585                                              size_t public_key_length,
 586                                              const u8
 587                                              *public_key_metadata,
 588                                              size_t
 589                                              public_key_metadata_length,
 590                                              bool *out_key_is_trusted)
 591{
 592        if (!public_key_length || !public_key_data || !out_key_is_trusted)
 593                return AVB_IO_RESULT_ERROR_IO;
 594
 595        *out_key_is_trusted = false;
 596        if (public_key_length != sizeof(avb_root_pub))
 597                return AVB_IO_RESULT_ERROR_IO;
 598
 599        if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0)
 600                *out_key_is_trusted = true;
 601
 602        return AVB_IO_RESULT_OK;
 603}
 604
 605#ifdef CONFIG_OPTEE_TA_AVB
 606static int get_open_session(struct AvbOpsData *ops_data)
 607{
 608        struct udevice *tee = NULL;
 609
 610        while (!ops_data->tee) {
 611                const struct tee_optee_ta_uuid uuid = TA_AVB_UUID;
 612                struct tee_open_session_arg arg;
 613                int rc;
 614
 615                tee = tee_find_device(tee, NULL, NULL, NULL);
 616                if (!tee)
 617                        return -ENODEV;
 618
 619                memset(&arg, 0, sizeof(arg));
 620                tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
 621                rc = tee_open_session(tee, &arg, 0, NULL);
 622                if (!rc) {
 623                        ops_data->tee = tee;
 624                        ops_data->session = arg.session;
 625                }
 626        }
 627
 628        return 0;
 629}
 630
 631static AvbIOResult invoke_func(struct AvbOpsData *ops_data, u32 func,
 632                               ulong num_param, struct tee_param *param)
 633{
 634        struct tee_invoke_arg arg;
 635
 636        if (get_open_session(ops_data))
 637                return AVB_IO_RESULT_ERROR_IO;
 638
 639        memset(&arg, 0, sizeof(arg));
 640        arg.func = func;
 641        arg.session = ops_data->session;
 642
 643        if (tee_invoke_func(ops_data->tee, &arg, num_param, param))
 644                return AVB_IO_RESULT_ERROR_IO;
 645        switch (arg.ret) {
 646        case TEE_SUCCESS:
 647                return AVB_IO_RESULT_OK;
 648        case TEE_ERROR_OUT_OF_MEMORY:
 649                return AVB_IO_RESULT_ERROR_OOM;
 650        case TEE_ERROR_STORAGE_NO_SPACE:
 651                return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
 652        case TEE_ERROR_ITEM_NOT_FOUND:
 653                return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
 654        case TEE_ERROR_TARGET_DEAD:
 655                /*
 656                 * The TA has paniced, close the session to reload the TA
 657                 * for the next request.
 658                 */
 659                tee_close_session(ops_data->tee, ops_data->session);
 660                ops_data->tee = NULL;
 661                return AVB_IO_RESULT_ERROR_IO;
 662        default:
 663                return AVB_IO_RESULT_ERROR_IO;
 664        }
 665}
 666#endif
 667
 668/**
 669 * read_rollback_index() - gets the rollback index corresponding to the
 670 * location of given by @out_rollback_index.
 671 *
 672 * @ops: contains AvbOps handlers
 673 * @rollback_index_slot:
 674 * @out_rollback_index: used to write a retrieved rollback index.
 675 *
 676 * @return
 677 *       AVB_IO_RESULT_OK, if the roolback index was retrieved
 678 */
 679static AvbIOResult read_rollback_index(AvbOps *ops,
 680                                       size_t rollback_index_slot,
 681                                       u64 *out_rollback_index)
 682{
 683#ifndef CONFIG_OPTEE_TA_AVB
 684        /* For now we always return 0 as the stored rollback index. */
 685        printf("%s not supported yet\n", __func__);
 686
 687        if (out_rollback_index)
 688                *out_rollback_index = 0;
 689
 690        return AVB_IO_RESULT_OK;
 691#else
 692        AvbIOResult rc;
 693        struct tee_param param[2];
 694
 695        if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
 696                return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
 697
 698        memset(param, 0, sizeof(param));
 699        param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
 700        param[0].u.value.a = rollback_index_slot;
 701        param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;
 702
 703        rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_ROLLBACK_INDEX,
 704                         ARRAY_SIZE(param), param);
 705        if (rc)
 706                return rc;
 707
 708        *out_rollback_index = (u64)param[1].u.value.a << 32 |
 709                              (u32)param[1].u.value.b;
 710        return AVB_IO_RESULT_OK;
 711#endif
 712}
 713
 714/**
 715 * write_rollback_index() - sets the rollback index corresponding to the
 716 * location of given by @out_rollback_index.
 717 *
 718 * @ops: contains AvbOps handlers
 719 * @rollback_index_slot:
 720 * @rollback_index: rollback index to write.
 721 *
 722 * @return
 723 *       AVB_IO_RESULT_OK, if the roolback index was retrieved
 724 */
 725static AvbIOResult write_rollback_index(AvbOps *ops,
 726                                        size_t rollback_index_slot,
 727                                        u64 rollback_index)
 728{
 729#ifndef CONFIG_OPTEE_TA_AVB
 730        /* For now this is a no-op. */
 731        printf("%s not supported yet\n", __func__);
 732
 733        return AVB_IO_RESULT_OK;
 734#else
 735        struct tee_param param[2];
 736
 737        if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
 738                return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
 739
 740        memset(param, 0, sizeof(param));
 741        param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
 742        param[0].u.value.a = rollback_index_slot;
 743        param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
 744        param[1].u.value.a = (u32)(rollback_index >> 32);
 745        param[1].u.value.b = (u32)rollback_index;
 746
 747        return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_ROLLBACK_INDEX,
 748                           ARRAY_SIZE(param), param);
 749#endif
 750}
 751
 752/**
 753 * read_is_device_unlocked() - gets whether the device is unlocked
 754 *
 755 * @ops: contains AVB ops handlers
 756 * @out_is_unlocked: device unlock state is stored here, true if unlocked,
 757 *       false otherwise
 758 *
 759 * @return:
 760 *       AVB_IO_RESULT_OK: state is retrieved successfully
 761 *       AVB_IO_RESULT_ERROR_IO: an error occurred
 762 */
 763static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
 764{
 765#ifndef CONFIG_OPTEE_TA_AVB
 766        /* For now we always return that the device is unlocked. */
 767
 768        printf("%s not supported yet\n", __func__);
 769
 770        *out_is_unlocked = true;
 771
 772        return AVB_IO_RESULT_OK;
 773#else
 774        AvbIOResult rc;
 775        struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
 776
 777        rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_LOCK_STATE, 1, &param);
 778        if (rc)
 779                return rc;
 780        *out_is_unlocked = !param.u.value.a;
 781        return AVB_IO_RESULT_OK;
 782#endif
 783}
 784
 785/**
 786 * get_unique_guid_for_partition() - gets the GUID for a partition identified
 787 * by a string name
 788 *
 789 * @ops: contains AVB ops handlers
 790 * @partition: partition name (NUL-terminated UTF-8 string)
 791 * @guid_buf: buf, used to copy in GUID string. Example of value:
 792 *      527c1c6d-6361-4593-8842-3c78fcd39219
 793 * @guid_buf_size: @guid_buf buffer size
 794 *
 795 * @return:
 796 *      AVB_IO_RESULT_OK, on success (GUID found)
 797 *      AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
 798 *             provided
 799 *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
 800 */
 801static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
 802                                                 const char *partition,
 803                                                 char *guid_buf,
 804                                                 size_t guid_buf_size)
 805{
 806        struct mmc_part *part;
 807        size_t uuid_size;
 808
 809        part = get_partition(ops, partition);
 810        if (!part)
 811                return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
 812
 813        uuid_size = sizeof(part->info.uuid);
 814        if (uuid_size > guid_buf_size)
 815                return AVB_IO_RESULT_ERROR_IO;
 816
 817        memcpy(guid_buf, part->info.uuid, uuid_size);
 818        guid_buf[uuid_size - 1] = 0;
 819
 820        return AVB_IO_RESULT_OK;
 821}
 822
 823/**
 824 * get_size_of_partition() - gets the size of a partition identified
 825 * by a string name
 826 *
 827 * @ops: contains AVB ops handlers
 828 * @partition: partition name (NUL-terminated UTF-8 string)
 829 * @out_size_num_bytes: returns the value of a partition size
 830 *
 831 * @return:
 832 *      AVB_IO_RESULT_OK, on success (GUID found)
 833 *      AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE, out_size_num_bytes is NULL
 834 *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
 835 */
 836static AvbIOResult get_size_of_partition(AvbOps *ops,
 837                                         const char *partition,
 838                                         u64 *out_size_num_bytes)
 839{
 840        struct mmc_part *part;
 841
 842        if (!out_size_num_bytes)
 843                return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
 844
 845        part = get_partition(ops, partition);
 846        if (!part)
 847                return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
 848
 849        *out_size_num_bytes = part->info.blksz * part->info.size;
 850
 851        return AVB_IO_RESULT_OK;
 852}
 853
 854#ifdef CONFIG_OPTEE_TA_AVB
 855static AvbIOResult read_persistent_value(AvbOps *ops,
 856                                         const char *name,
 857                                         size_t buffer_size,
 858                                         u8 *out_buffer,
 859                                         size_t *out_num_bytes_read)
 860{
 861        AvbIOResult rc;
 862        struct tee_shm *shm_name;
 863        struct tee_shm *shm_buf;
 864        struct tee_param param[2];
 865        struct udevice *tee;
 866        size_t name_size = strlen(name) + 1;
 867
 868        if (get_open_session(ops->user_data))
 869                return AVB_IO_RESULT_ERROR_IO;
 870
 871        tee = ((struct AvbOpsData *)ops->user_data)->tee;
 872
 873        rc = tee_shm_alloc(tee, name_size,
 874                           TEE_SHM_ALLOC, &shm_name);
 875        if (rc)
 876                return AVB_IO_RESULT_ERROR_OOM;
 877
 878        rc = tee_shm_alloc(tee, buffer_size,
 879                           TEE_SHM_ALLOC, &shm_buf);
 880        if (rc) {
 881                rc = AVB_IO_RESULT_ERROR_OOM;
 882                goto free_name;
 883        }
 884
 885        memcpy(shm_name->addr, name, name_size);
 886
 887        memset(param, 0, sizeof(param));
 888        param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
 889        param[0].u.memref.shm = shm_name;
 890        param[0].u.memref.size = name_size;
 891        param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
 892        param[1].u.memref.shm = shm_buf;
 893        param[1].u.memref.size = buffer_size;
 894
 895        rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_PERSIST_VALUE,
 896                         2, param);
 897        if (rc)
 898                goto out;
 899
 900        if (param[1].u.memref.size > buffer_size) {
 901                rc = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
 902                goto out;
 903        }
 904
 905        *out_num_bytes_read = param[1].u.memref.size;
 906
 907        memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read);
 908
 909out:
 910        tee_shm_free(shm_buf);
 911free_name:
 912        tee_shm_free(shm_name);
 913
 914        return rc;
 915}
 916
 917static AvbIOResult write_persistent_value(AvbOps *ops,
 918                                          const char *name,
 919                                          size_t value_size,
 920                                          const u8 *value)
 921{
 922        AvbIOResult rc;
 923        struct tee_shm *shm_name;
 924        struct tee_shm *shm_buf;
 925        struct tee_param param[2];
 926        struct udevice *tee;
 927        size_t name_size = strlen(name) + 1;
 928
 929        if (get_open_session(ops->user_data))
 930                return AVB_IO_RESULT_ERROR_IO;
 931
 932        tee = ((struct AvbOpsData *)ops->user_data)->tee;
 933
 934        if (!value_size)
 935                return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
 936
 937        rc = tee_shm_alloc(tee, name_size,
 938                           TEE_SHM_ALLOC, &shm_name);
 939        if (rc)
 940                return AVB_IO_RESULT_ERROR_OOM;
 941
 942        rc = tee_shm_alloc(tee, value_size,
 943                           TEE_SHM_ALLOC, &shm_buf);
 944        if (rc) {
 945                rc = AVB_IO_RESULT_ERROR_OOM;
 946                goto free_name;
 947        }
 948
 949        memcpy(shm_name->addr, name, name_size);
 950        memcpy(shm_buf->addr, value, value_size);
 951
 952        memset(param, 0, sizeof(param));
 953        param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
 954        param[0].u.memref.shm = shm_name;
 955        param[0].u.memref.size = name_size;
 956        param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
 957        param[1].u.memref.shm = shm_buf;
 958        param[1].u.memref.size = value_size;
 959
 960        rc = invoke_func(ops->user_data, TA_AVB_CMD_WRITE_PERSIST_VALUE,
 961                         2, param);
 962        if (rc)
 963                goto out;
 964
 965out:
 966        tee_shm_free(shm_buf);
 967free_name:
 968        tee_shm_free(shm_name);
 969
 970        return rc;
 971}
 972#endif
 973
 974/**
 975 * ============================================================================
 976 * AVB2.0 AvbOps alloc/initialisation/free
 977 * ============================================================================
 978 */
 979AvbOps *avb_ops_alloc(int boot_device)
 980{
 981        struct AvbOpsData *ops_data;
 982
 983        ops_data = avb_calloc(sizeof(struct AvbOpsData));
 984        if (!ops_data)
 985                return NULL;
 986
 987        ops_data->ops.user_data = ops_data;
 988
 989        ops_data->ops.read_from_partition = read_from_partition;
 990        ops_data->ops.write_to_partition = write_to_partition;
 991        ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key;
 992        ops_data->ops.read_rollback_index = read_rollback_index;
 993        ops_data->ops.write_rollback_index = write_rollback_index;
 994        ops_data->ops.read_is_device_unlocked = read_is_device_unlocked;
 995        ops_data->ops.get_unique_guid_for_partition =
 996                get_unique_guid_for_partition;
 997#ifdef CONFIG_OPTEE_TA_AVB
 998        ops_data->ops.write_persistent_value = write_persistent_value;
 999        ops_data->ops.read_persistent_value = read_persistent_value;
1000#endif
1001        ops_data->ops.get_size_of_partition = get_size_of_partition;
1002        ops_data->mmc_dev = boot_device;
1003
1004        return &ops_data->ops;
1005}
1006
1007void avb_ops_free(AvbOps *ops)
1008{
1009        struct AvbOpsData *ops_data;
1010
1011        if (!ops)
1012                return;
1013
1014        ops_data = ops->user_data;
1015
1016        if (ops_data) {
1017#ifdef CONFIG_OPTEE_TA_AVB
1018                if (ops_data->tee)
1019                        tee_close_session(ops_data->tee, ops_data->session);
1020#endif
1021                avb_free(ops_data);
1022        }
1023}
1024