/*
 * Given offset in flash area, fill in rest of the fcb_entry, and crc8 over
 * the data.
 */
int
fcb_elem_crc8(struct fcb *fcb, struct fcb_entry *loc, uint8_t *c8p)
{
    uint8_t tmp_str[FCB_TMP_BUF_SZ];
    int cnt;
    int blk_sz;
    uint8_t crc8;
    uint16_t len;
    uint32_t off;
    uint32_t end;
    int rc;

    if (loc->fe_elem_off + 2 > loc->fe_area->fa_size) {
        return FCB_ERR_NOVAR;
    }
    rc = flash_area_read(loc->fe_area, loc->fe_elem_off, tmp_str, 2);
    if (rc) {
        return FCB_ERR_FLASH;
    }

    cnt = fcb_get_len(tmp_str, &len);
    if (cnt < 0) {
        return cnt;
    }
    loc->fe_data_off = loc->fe_elem_off + fcb_len_in_flash(fcb, cnt);
    loc->fe_data_len = len;

    crc8 = crc8_init();
    crc8 = crc8_calc(crc8, tmp_str, cnt);

    off = loc->fe_data_off;
    end = loc->fe_data_off + len;
    for (; off < end; off += blk_sz) {
        blk_sz = end - off;
        if (blk_sz > sizeof(tmp_str)) {
            blk_sz = sizeof(tmp_str);
        }

        rc = flash_area_read(loc->fe_area, off, tmp_str, blk_sz);
        if (rc) {
            return FCB_ERR_FLASH;
        }
        crc8 = crc8_calc(crc8, tmp_str, blk_sz);
    }
    *c8p = crc8;

    return 0;
}
/**
 * Deletes the main image version number from the boot vector.
 * This must be called by the app to confirm that it is ok to keep booting
 * to this image.
 *
 * @return                  0 on success; nonzero on failure.
 */
int
boot_vect_write_main(void)
{
    const struct flash_area *fap;
    uint32_t off;
    int rc;
    uint8_t val;

    /*
     * Write to slot 0.
     */
    rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
    if (rc) {
        return rc;
    }

    off = fap->fa_size - sizeof(struct boot_img_trailer);
    off += (sizeof(uint32_t) + sizeof(uint8_t));
    rc = flash_area_read(fap, off, &val, sizeof(val));
    if (!rc && val == 0xff) {
        val = 0;
        rc = flash_area_write(fap, off, &val, sizeof(val));
    }
    return rc;
}
示例#3
0
/*
 * Read version from image header from flash area 'area_id'.
 * Returns -1 if area is not readable.
 * Returns 0 if image in slot is ok, and version string is valid.
 * Returns 1 if there is not a full image.
 * Returns 2 if slot is empty.
 */
int
imgr_read_ver(int area_id, struct image_version *ver)
{
    struct image_header hdr;
    int rc;
    const struct flash_area *fa;

    rc = flash_area_open(area_id, &fa);
    if (rc) {
        return -1;
    }
    rc = flash_area_read(fa, 0, &hdr, sizeof(hdr));
    if (rc) {
        return -1;
    }
    memset(ver, 0xff, sizeof(*ver));
    if (hdr.ih_magic == 0x96f3b83c) {
        memcpy(ver, &hdr.ih_ver, sizeof(*ver));
        rc = 0;
    } else {
        rc = 1;
    }
    flash_area_close(fa);
    return rc;
}
int
imgr_core_list(struct nmgr_jbuf *njb)
{
    const struct flash_area *fa;
    struct coredump_header hdr;
    struct json_encoder *enc;
    struct json_value jv;
    int rc;

    rc = flash_area_open(FLASH_AREA_CORE, &fa);
    if (rc) {
        rc = NMGR_ERR_EINVAL;
    } else {
        rc = flash_area_read(fa, 0, &hdr, sizeof(hdr));
        if (rc != 0) {
            rc = NMGR_ERR_EINVAL;
        } else if (hdr.ch_magic != COREDUMP_MAGIC) {
            rc = NMGR_ERR_ENOENT;
        } else {
            rc = 0;
        }
    }

    enc = &njb->njb_enc;

    json_encode_object_start(enc);
    JSON_VALUE_INT(&jv, rc);
    json_encode_object_entry(enc, "rc", &jv);
    json_encode_object_finish(enc);

    return 0;
}
void
boot_test_util_copy_area(int from_area_idx, int to_area_idx)
{
    const struct flash_area *from_area_desc;
    const struct flash_area *to_area_desc;
    void *buf;
    int rc;

    from_area_desc = boot_test_area_descs + from_area_idx;
    to_area_desc = boot_test_area_descs + to_area_idx;

    TEST_ASSERT(from_area_desc->fa_size == to_area_desc->fa_size);

    buf = malloc(from_area_desc->fa_size);
    TEST_ASSERT(buf != NULL);

    rc = flash_area_read(from_area_desc, 0, buf,
                         from_area_desc->fa_size);
    TEST_ASSERT(rc == 0);

    rc = flash_area_erase(to_area_desc,
                          0,
                          to_area_desc->fa_size);
    TEST_ASSERT(rc == 0);

    rc = flash_area_write(to_area_desc, 0, buf,
                          to_area_desc->fa_size);
    TEST_ASSERT(rc == 0);

    free(buf);
}
void
boot_test_util_swap_areas(int area_idx1, int area_idx2)
{
    const struct flash_area *area_desc1;
    const struct flash_area *area_desc2;
    uint32_t size;
    void *buf1;
    void *buf2;
    int rc;

    area_desc1 = boot_test_area_descs + area_idx1;
    area_desc2 = boot_test_area_descs + area_idx2;

    TEST_ASSERT(area_desc1->fa_size == area_desc2->fa_size);

    buf1 = malloc(area_desc1->fa_size);
    TEST_ASSERT(buf1 != NULL);

    buf2 = malloc(area_desc2->fa_size);
    TEST_ASSERT(buf2 != NULL);

    rc = flash_area_read(area_desc1, 0, buf1, area_desc1->fa_size);
    TEST_ASSERT(rc == 0);

    rc = flash_area_read(area_desc2, 0, buf2, area_desc2->fa_size);
    TEST_ASSERT(rc == 0);

    rc = flash_area_erase(area_desc1, 0, area_desc1->fa_size);
    TEST_ASSERT(rc == 0);

    rc = flash_area_erase(area_desc2, 0, area_desc2->fa_size);
    TEST_ASSERT(rc == 0);

    size = boot_test_util_area_write_size(area_idx1, 0, area_desc1->fa_size);
    rc = flash_area_write(area_desc1, 0, buf2, size);
    TEST_ASSERT(rc == 0);

    size = boot_test_util_area_write_size(area_idx2, 0, area_desc2->fa_size);
    rc = flash_area_write(area_desc2, 0, buf1, size);
    TEST_ASSERT(rc == 0);

    free(buf1);
    free(buf2);
}
/*
 * Read the image trailer from a given slot.
 */
static int
boot_vect_read_img_trailer(int slot, struct boot_img_trailer *bit)
{
    int rc;
    const struct flash_area *fap;
    uint32_t off;

    rc = flash_area_open(slot, &fap);
    if (rc) {
        return rc;
    }
    off = fap->fa_size - sizeof(struct boot_img_trailer);
    rc = flash_area_read(fap, off, bit, sizeof(*bit));
    flash_area_close(fap);

    return rc;
}
/*
 * Compute SHA256 over the image.
 */
static int
bootutil_img_hash(struct image_header *hdr, const struct flash_area *fap,
                  uint8_t *tmp_buf, uint32_t tmp_buf_sz,
                  uint8_t *hash_result, uint8_t *seed, int seed_len)
{
    mbedtls_sha256_context sha256_ctx;
    uint32_t blk_sz;
    uint32_t size;
    uint32_t off;
    int rc;

    mbedtls_sha256_init(&sha256_ctx);
    mbedtls_sha256_starts(&sha256_ctx, 0);

    /* in some cases (split image) the hash is seeded with data from
     * the loader image */
    if(seed && (seed_len > 0)) {
        mbedtls_sha256_update(&sha256_ctx, seed, seed_len);
    }

    size = hdr->ih_img_size + hdr->ih_hdr_size;

    /*
     * Hash is computed over image header and image itself. No TLV is
     * included ATM.
     */
    size = hdr->ih_img_size + hdr->ih_hdr_size;
    for (off = 0; off < size; off += blk_sz) {
        /* Pet the watchdog, in case it is still enabled after a soft reset. */
        hal_watchdog_tickle();

        blk_sz = size - off;
        if (blk_sz > tmp_buf_sz) {
            blk_sz = tmp_buf_sz;
        }
        rc = flash_area_read(fap, off, tmp_buf, blk_sz);
        if (rc) {
            return rc;
        }
        mbedtls_sha256_update(&sha256_ctx, tmp_buf, blk_sz);
    }
    mbedtls_sha256_finish(&sha256_ctx, hash_result);

    return 0;
}
示例#9
0
static int
log_fcb_read(struct log *log, void *dptr, void *buf, uint16_t offset,
  uint16_t len)
{
    struct fcb_entry *loc;
    int rc;

    loc = (struct fcb_entry *)dptr;

    if (offset + len > loc->fe_data_len) {
        len = loc->fe_data_len - offset;
    }
    rc = flash_area_read(loc->fe_area, loc->fe_data_off + offset, buf, len);
    if (rc == 0) {
        return len;
    } else {
        return 0;
    }
}
示例#10
0
int
fcb_test_data_walk_cb(struct fcb_entry *loc, void *arg)
{
    uint16_t len;
    uint8_t test_data[128];
    int rc;
    int i;
    int *var_cnt = (int *)arg;

    len = loc->fe_data_len;

    TEST_ASSERT(len == *var_cnt);

    rc = flash_area_read(loc->fe_area, loc->fe_data_off, test_data, len);
    TEST_ASSERT(rc == 0);

    for (i = 0; i < len; i++) {
        TEST_ASSERT(test_data[i] == fcb_test_append_data(len, i));
    }
    (*var_cnt)++;
    return 0;
}
int
fcb_elem_info(struct fcb *fcb, struct fcb_entry *loc)
{
    int rc;
    uint8_t crc8;
    uint8_t fl_crc8;
    uint32_t off;

    rc = fcb_elem_crc8(fcb, loc, &crc8);
    if (rc) {
        return rc;
    }
    off = loc->fe_data_off + fcb_len_in_flash(fcb, loc->fe_data_len);

    rc = flash_area_read(loc->fe_area, off, &fl_crc8, sizeof(fl_crc8));
    if (rc) {
        return FCB_ERR_FLASH;
    }

    if (fl_crc8 != crc8) {
        return FCB_ERR_CRC;
    }
    return 0;
}
int
imgr_core_list(struct mgmt_cbuf *cb)
{
    const struct flash_area *fa;
    struct coredump_header hdr;
    int rc;

    rc = flash_area_open(MYNEWT_VAL(COREDUMP_FLASH_AREA), &fa);
    if (rc) {
        rc = MGMT_ERR_EINVAL;
    } else {
        rc = flash_area_read(fa, 0, &hdr, sizeof(hdr));
        if (rc != 0) {
            rc = MGMT_ERR_EINVAL;
        } else if (hdr.ch_magic != COREDUMP_MAGIC) {
            rc = MGMT_ERR_ENOENT;
        } else {
            rc = 0;
        }
    }

    mgmt_cbuf_setoerr(cb, rc);
    return 0;
}
/*
 * Verify the integrity of the image.
 * Return non-zero if image could not be validated/does not validate.
 */
int
bootutil_img_validate(struct image_header *hdr, const struct flash_area *fap,
                      uint8_t *tmp_buf, uint32_t tmp_buf_sz,
                      uint8_t *seed, int seed_len, uint8_t *out_hash)
{
    uint32_t off;
    uint32_t size;
    uint32_t sha_off = 0;
#if MYNEWT_VAL(BOOTUTIL_SIGN_RSA) || MYNEWT_VAL(BOOTUTIL_SIGN_EC) || \
    MYNEWT_VAL(BOOTUTIL_SIGN_EC256)
    uint32_t sig_off = 0;
    uint32_t sig_len = 0;
#endif
    struct image_tlv tlv;
    uint8_t buf[256];
    uint8_t hash[32];
    int rc;

#if MYNEWT_VAL(BOOTUTIL_SIGN_RSA)
    if ((hdr->ih_flags & IMAGE_F_PKCS15_RSA2048_SHA256) == 0) {
        return -1;
    }
#endif
#if MYNEWT_VAL(BOOTUTIL_SIGN_EC)
    if ((hdr->ih_flags & IMAGE_F_ECDSA224_SHA256) == 0) {
        return -1;
    }
#endif
#if MYNEWT_VAL(BOOTUTIL_SIGN_EC256)
    if ((hdr->ih_flags & IMAGE_F_ECDSA256_SHA256) == 0) {
        return -1;
    }
#endif
    if ((hdr->ih_flags & IMAGE_F_SHA256) == 0) {
        return -1;
    }

    rc = bootutil_img_hash(hdr, fap, tmp_buf, tmp_buf_sz, hash,
                           seed, seed_len);
    if (rc) {
        return rc;
    }

    if (out_hash) {
        memcpy(out_hash, hash, 32);
    }

    /* After image there are TLVs. */
    off = hdr->ih_img_size + hdr->ih_hdr_size;
    size = off + hdr->ih_tlv_size;

    for (; off < size; off += sizeof(tlv) + tlv.it_len) {
        rc = flash_area_read(fap, off, &tlv, sizeof tlv);
        if (rc) {
            return rc;
        }
        if (tlv.it_type == IMAGE_TLV_SHA256) {
            if (tlv.it_len != sizeof(hash)) {
                return -1;
            }
            sha_off = off + sizeof(tlv);
        }
#if MYNEWT_VAL(BOOTUTIL_SIGN_RSA)
        if (tlv.it_type == IMAGE_TLV_RSA2048) {
            if (tlv.it_len != 256) { /* 2048 bits */
                return -1;
            }
            sig_off = off + sizeof(tlv);
            sig_len = tlv.it_len;
        }
#endif
#if MYNEWT_VAL(BOOTUTIL_SIGN_EC)
        if (tlv.it_type == IMAGE_TLV_ECDSA224) {
            if (tlv.it_len < 64) { /* oids + 2 * 28 bytes */
                return -1;
            }
            sig_off = off + sizeof(tlv);
            sig_len = tlv.it_len;
        }
#endif
#if MYNEWT_VAL(BOOTUTIL_SIGN_EC256)
        if (tlv.it_type == IMAGE_TLV_ECDSA256) {
            if (tlv.it_len < 72) { /* oids + 2 * 32 bytes */
                return -1;
            }
            sig_off = off + sizeof(tlv);
            sig_len = tlv.it_len;
        }
#endif
    }
    if (hdr->ih_flags & IMAGE_F_SHA256) {
        if (!sha_off) {
            /*
             * Header said there should be hash TLV, no TLV found.
             */
            return -1;
        }
        rc = flash_area_read(fap, sha_off, buf, sizeof hash);
        if (rc) {
            return rc;
        }
        if (memcmp(hash, buf, sizeof(hash))) {
            return -1;
        }
    }
#if MYNEWT_VAL(BOOTUTIL_SIGN_RSA) || MYNEWT_VAL(BOOTUTIL_SIGN_EC) || \
    MYNEWT_VAL(BOOTUTIL_SIGN_EC256)
    if (!sig_off) {
        /*
         * Header said there should be PKCS1.v5 signature, no TLV
         * found.
         */
        return -1;
    }
    rc = flash_area_read(fap, sig_off, buf, sig_len);
    if (rc) {
        return -1;
    }

    if (hdr->ih_key_id >= bootutil_key_cnt) {
        return -1;
    }
    rc = bootutil_verify_sig(hash, sizeof(hash), buf, sig_len, hdr->ih_key_id);
    if (rc) {
        return -1;
    }
#endif
    return 0;
}
示例#14
0
void
coredump_dump(void *regs, int regs_sz)
{
    struct coredump_header hdr;
    struct coredump_tlv tlv;
    const struct flash_area *fa;
    struct image_version ver;
    const struct bsp_mem_dump *mem, *cur;
    int area_cnt, i;
    uint8_t hash[IMGMGR_HASH_LEN];
    uint32_t off;
    uint32_t area_off, area_end;

    if (coredump_disabled) {
        return;
    }
    if (flash_area_open(FLASH_AREA_CORE, &fa)) {
        return;
    }

    if (flash_area_read(fa, 0, &hdr, sizeof(hdr))) {
        return;
    }
    if (hdr.ch_magic == COREDUMP_MAGIC) {
        /*
         * Don't override corefile.
         */
        return;
    }

    if (flash_area_erase(fa, 0, fa->fa_size)) {
        return;
    }

    /*
     * First put in data, followed by the header.
     */
    tlv.ct_type = COREDUMP_TLV_REGS;
    tlv._pad = 0;
    tlv.ct_len = regs_sz;
    tlv.ct_off = 0;

    off = sizeof(hdr);
    dump_core_tlv(fa, &off, &tlv, regs);

    if (imgr_read_info(bsp_imgr_current_slot(), &ver, hash) == 0) {
        tlv.ct_type = COREDUMP_TLV_IMAGE;
        tlv.ct_len = IMGMGR_HASH_LEN;

        dump_core_tlv(fa, &off, &tlv, hash);
    }

    mem = bsp_core_dump(&area_cnt);
    for (i = 0; i < area_cnt; i++) {
        cur = &mem[i];
        area_off = (uint32_t)cur->bmd_start;
        area_end = area_off + cur->bmd_size;
        while (area_off < area_end) {
            tlv.ct_type = COREDUMP_TLV_MEM;
            if (cur->bmd_size > USHRT_MAX) {
                tlv.ct_len = SHRT_MAX + 1;
            } else {
                tlv.ct_len = cur->bmd_size;
            }
            tlv.ct_off = area_off;
            dump_core_tlv(fa, &off, &tlv, (void *)area_off);
            area_off += tlv.ct_len;
        }
    }
    hdr.ch_magic = COREDUMP_MAGIC;
    hdr.ch_size = off;

    flash_area_write(fa, 0, &hdr, sizeof(hdr));
}
示例#15
0
/*
 * Read version and build hash from image located slot "image_slot".  Note:
 * this is a slot index, not a flash area ID.
 *
 * @param image_slot
 * @param ver (optional)
 * @param hash (optional)
 * @param flags
 *
 * Returns -1 if area is not readable.
 * Returns 0 if image in slot is ok, and version string is valid.
 * Returns 1 if there is not a full image.
 * Returns 2 if slot is empty. XXXX not there yet
 */
int
imgr_read_info(int image_slot, struct image_version *ver, uint8_t *hash,
               uint32_t *flags)
{
    struct image_header *hdr;
    struct image_tlv *tlv;
    int rc = -1;
    int rc2;
    const struct flash_area *fa;
    uint8_t data[sizeof(struct image_header)];
    uint32_t data_off, data_end;
    int area_id;

    area_id = flash_area_id_from_image_slot(image_slot);

    hdr = (struct image_header *)data;
    rc2 = flash_area_open(area_id, &fa);
    if (rc2) {
        return -1;
    }
    rc2 = flash_area_read(fa, 0, hdr, sizeof(*hdr));
    if (rc2) {
        goto end;
    }

    if (ver != NULL) {
        memset(ver, 0xff, sizeof(*ver));
        if (hdr->ih_magic == IMAGE_MAGIC) {
            memcpy(ver, &hdr->ih_ver, sizeof(*ver));
        } else if (hdr->ih_magic == 0xffffffff) {
            rc = 2;
            goto end;
        } else {
            rc = 1;
            goto end;
        }
    }

    if(flags) {
        *flags = hdr->ih_flags;
    }
    /*
     * Build ID is in a TLV after the image.
     */
    data_off = hdr->ih_hdr_size + hdr->ih_img_size;
    data_end = data_off + hdr->ih_tlv_size;

    if (data_end > fa->fa_size) {
        rc = 1;
        goto end;
    }
    tlv = (struct image_tlv *)data;
    while (data_off + sizeof(*tlv) <= data_end) {
        rc2 = flash_area_read(fa, data_off, tlv, sizeof(*tlv));
        if (rc2) {
            goto end;
        }
        if (tlv->it_type == 0xff && tlv->it_len == 0xffff) {
            break;
        }
        if (tlv->it_type != IMAGE_TLV_SHA256 ||
          tlv->it_len != IMGMGR_HASH_LEN) {
            data_off += sizeof(*tlv) + tlv->it_len;
            continue;
        }
        data_off += sizeof(*tlv);
        if (hash) {
            if (data_off + IMGMGR_HASH_LEN > data_end) {
                goto end;
            }
            rc2 = flash_area_read(fa, data_off, hash, IMGMGR_HASH_LEN);
            if (rc2) {
                goto end;
            }
        }
        rc = 0;
        goto end;
    }
    rc = 1;
end:
    flash_area_close(fa);
    return rc;
}