void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest) { assert(handle != NULL); mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)handle; if (digest != NULL) { mbedtls_sha256_finish(ctx, digest); } mbedtls_sha256_free(ctx); free(handle); }
/* * 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; }
static void boot_test_util_write_hash(const struct image_header *hdr, int slot) { uint8_t tmpdata[1024]; uint8_t hash[32]; int rc; uint32_t off; uint32_t blk_sz; uint32_t sz; mbedtls_sha256_context ctx; uint8_t flash_id; uint32_t addr; struct image_tlv tlv; mbedtls_sha256_init(&ctx); mbedtls_sha256_starts(&ctx, 0); flash_id = boot_test_img_addrs[slot].flash_id; addr = boot_test_img_addrs[slot].address; sz = hdr->ih_hdr_size + hdr->ih_img_size; for (off = 0; off < sz; off += blk_sz) { blk_sz = sz - off; if (blk_sz > sizeof(tmpdata)) { blk_sz = sizeof(tmpdata); } rc = hal_flash_read(flash_id, addr + off, tmpdata, blk_sz); TEST_ASSERT(rc == 0); mbedtls_sha256_update(&ctx, tmpdata, blk_sz); } mbedtls_sha256_finish(&ctx, hash); tlv.it_type = IMAGE_TLV_SHA256; tlv._pad = 0; tlv.it_len = sizeof(hash); rc = hal_flash_write(flash_id, addr + off, &tlv, sizeof(tlv)); TEST_ASSERT(rc == 0); off += sizeof(tlv); rc = hal_flash_write(flash_id, addr + off, hash, sizeof(hash)); TEST_ASSERT(rc == 0); }
/** * fast_sha256_vector - SHA256 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 of failure */ int fast_sha256_vector(size_t num_elem, const uint8_t *addr[], const size_t *len, uint8_t *mac) { mbedtls_sha256_context ctx; mbedtls_sha256_init(&ctx); mbedtls_sha256_starts(&ctx, 0); for(size_t index = 0; index < num_elem; index++) { mbedtls_sha256_update(&ctx, addr[index], len[index]); } mbedtls_sha256_finish(&ctx, mac); mbedtls_sha256_free(&ctx); return 0; }
static void sha224_finish_wrap( void *ctx, unsigned char *output ) { mbedtls_sha256_finish( (mbedtls_sha256_context *) ctx, output ); }
int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) { int ret, count = 0, i, done; mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data; unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; if( len > MBEDTLS_ENTROPY_BLOCK_SIZE ) return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); #if defined(MBEDTLS_THREADING_C) if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) return( ret ); #endif /* * Always gather extra entropy before a call */ do { if( count++ > ENTROPY_MAX_LOOP ) { ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; goto exit; } if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) goto exit; done = 1; for( i = 0; i < ctx->source_count; i++ ) if( ctx->source[i].size < ctx->source[i].threshold ) done = 0; } while( ! done ); memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) mbedtls_sha512_finish( &ctx->accumulator, buf ); /* * Reset accumulator and counters and recycle existing entropy */ memset( &ctx->accumulator, 0, sizeof( mbedtls_sha512_context ) ); mbedtls_sha512_starts( &ctx->accumulator, 0 ); mbedtls_sha512_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); /* * Perform second SHA-512 on entropy */ mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); #else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ mbedtls_sha256_finish( &ctx->accumulator, buf ); /* * Reset accumulator and counters and recycle existing entropy */ memset( &ctx->accumulator, 0, sizeof( mbedtls_sha256_context ) ); mbedtls_sha256_starts( &ctx->accumulator, 0 ); mbedtls_sha256_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); /* * Perform second SHA-256 on entropy */ mbedtls_sha256( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); #endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ for( i = 0; i < ctx->source_count; i++ ) ctx->source[i].size = 0; memcpy( output, buf, len ); ret = 0; exit: #if defined(MBEDTLS_THREADING_C) if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); #endif return( ret ); }
int example(void) { printf( "\r\n\r\n" ); /* * Method 1: use all-in-one function of a specific SHA-xxx module */ unsigned char output1[32]; /* SHA-256 outputs 32 bytes */ /* 0 here means use the full SHA-256, not the SHA-224 variant */ mbedtls_sha256(hello_buffer, hello_len, output1, 0); print_hex("Method 1", output1, sizeof output1); /* * Method 2: use the streaming interface of a specific SHA-xxx module * This is useful if we get our input piecewise. */ unsigned char output2[32]; mbedtls_sha256_context ctx2; mbedtls_sha256_init(&ctx2); mbedtls_sha256_starts(&ctx2, 0); /* SHA-256, not 224 */ /* Simulating multiple fragments */ mbedtls_sha256_update(&ctx2, hello_buffer, 1); mbedtls_sha256_update(&ctx2, hello_buffer + 1, 1); mbedtls_sha256_update(&ctx2, hello_buffer + 2, hello_len - 2); mbedtls_sha256_finish(&ctx2, output2); print_hex("Method 2", output2, sizeof output2); /* Or you could re-use the context by doing mbedtls_sha256_starts() again */ mbedtls_sha256_free(&ctx2); /* * Method 3: use all-in-one function of the generice interface */ unsigned char output3[MBEDTLS_MD_MAX_SIZE]; /* Enough for any hash */ /* Can easily pick any hash you want, by identifier */ const mbedtls_md_info_t *md_info3 = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); if (md_info3 == NULL) { printf("SHA256 not available\r\n"); return 1; } int ret3 = mbedtls_md(md_info3, hello_buffer, hello_len, output3); if (ret3 != 0) { printf("md() returned -0x%04X\r\n", -ret3); return 1; } print_hex("Method 3", output3, mbedtls_md_get_size(md_info3)); /* * Method 4: streaming & generic interface */ unsigned char output4[MBEDTLS_MD_MAX_SIZE]; /* Enough for any hash */ const mbedtls_md_info_t *md_info4 = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); if (md_info4 == NULL) { printf("SHA256 not available\r\n"); return 1; } mbedtls_md_context_t ctx4; mbedtls_md_init(&ctx4); int ret4 = mbedtls_md_init_ctx(&ctx4, md_info4); if (ret4 != 0) { printf("md_init_ctx() returned -0x%04X\r\n", -ret4); return 1; } mbedtls_md_starts(&ctx4); /* Simulating multiple fragments */ mbedtls_md_update(&ctx4, hello_buffer, 1); mbedtls_md_update(&ctx4, hello_buffer + 1, 1); mbedtls_md_update(&ctx4, hello_buffer + 2, hello_len - 2); mbedtls_md_finish(&ctx4, output4); print_hex("Method 4", output4, mbedtls_md_get_size(md_info4)); /* Or you could re-use the context by doing mbedtls_md_starts() again */ mbedtls_md_free(&ctx4); printf("\r\nDONE\r\n"); 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, uint8_t flash_id, uint32_t addr, uint8_t *tmp_buf, uint32_t tmp_buf_sz) { uint32_t blk_sz; uint32_t off; uint32_t size; mbedtls_sha256_context sha256_ctx; struct image_tlv tlv; uint8_t flash_hash[32]; uint8_t computed_hash[32]; int rc; if (hdr->ih_flags & IMAGE_F_HAS_SHA256) { /* * After image there's a TLV containing the hash. */ mbedtls_sha256_init(&sha256_ctx); mbedtls_sha256_starts(&sha256_ctx, 0); /* * 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) { blk_sz = size - off; if (blk_sz > tmp_buf_sz) { blk_sz = tmp_buf_sz; } rc = hal_flash_read(flash_id, addr + off, tmp_buf, blk_sz); if (rc) { return rc; } mbedtls_sha256_update(&sha256_ctx, tmp_buf, blk_sz); } mbedtls_sha256_finish(&sha256_ctx, computed_hash); /* * Then find the hash TLV and this should match. */ size += hdr->ih_tlv_size; for (; off < size; off += sizeof(tlv) + tlv.it_len) { rc = hal_flash_read(flash_id, addr + off, &tlv, sizeof(tlv)); if (rc) { return rc; } if (tlv.it_type == IMAGE_TLV_SHA256) { if (tlv.it_len != sizeof(flash_hash)) { return -1; } rc = hal_flash_read(flash_id, addr + off + sizeof(tlv), flash_hash, sizeof(flash_hash)); if (rc) { return rc; } if (memcmp(flash_hash, computed_hash, sizeof(flash_hash))) { return -1; } return 0; } } /* * Header said there should hash TLV, no TLV found. */ return -1; } return -1; }
int crypto_hash_sha256_final(crypto_hash_sha256_state *state, unsigned char *out) { mbedtls_sha256_finish(state, out); return 0; }