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