void mbedtls_sha256_clone(mbedtls_sha256_context *dst, const mbedtls_sha256_context *src) { if (src->ishw) { // Clone S/W ctx from H/W ctx dst->ishw = 0; dst->sw_ctx.total[0] = src->hw_ctx.total; dst->sw_ctx.total[1] = 0; { unsigned char output[32]; crypto_sha_getinternstate(output, sizeof (output)); unsigned char *output_pos = output; unsigned char *output_end = output + (sizeof (output) / sizeof (output[0])); uint32_t *state_pos = (uint32_t *) &(dst->sw_ctx.state[0]); while (output_pos != output_end) { *state_pos ++ = nu_get32_be(output_pos); output_pos += 4; } } memcpy(dst->sw_ctx.buffer, src->hw_ctx.buffer, src->hw_ctx.buffer_left); dst->sw_ctx.is224 = src->hw_ctx.is224; if (src->hw_ctx.buffer_left == src->hw_ctx.blocksize) { mbedtls_sha256_sw_process(&dst->sw_ctx, dst->sw_ctx.buffer); } } else { // Clone S/W ctx from S/W ctx dst->sw_ctx = src->sw_ctx; } }
void mbedtls_sha1_hw_finish(crypto_sha_context *ctx, unsigned char output[20]) { // H/W SHA cannot handle zero data well. Fall back to S/W SHA. if (ctx->total) { crypto_sha_update_nobuf(ctx, ctx->buffer, ctx->buffer_left, 1); ctx->buffer_left = 0; crypto_sha_getinternstate(output, 20); CRPT->SHA_CTL |= CRPT_SHA_CTL_STOP_Msk; } else { mbedtls_sha1_sw_context ctx_sw; mbedtls_sha1_sw_init(&ctx_sw); mbedtls_sha1_sw_starts(&ctx_sw); mbedtls_sha1_sw_finish(&ctx_sw, output); mbedtls_sha1_sw_free(&ctx_sw); } }
void mbedtls_sha512_clone(mbedtls_sha512_context *dst, const mbedtls_sha512_context *src) { // Corner case: Destination/source contexts are the same if (dst == src) { return; } // If dst is H/W context, we need to change it to S/W context first before cloning to. if (dst->active_ctx == &dst->hw_ctx) { mbedtls_sha512_free(dst); // Force S/W context mbedtls_sha512_init_internal(dst, 0); } if (src->active_ctx == &src->hw_ctx) { // Clone S/W ctx from H/W ctx dst->sw_ctx.total[0] = src->hw_ctx.total; dst->sw_ctx.total[1] = 0; { unsigned char output[128]; crypto_sha_getinternstate(output, sizeof (output)); unsigned char *output_pos = output; unsigned char *output_end = output + (sizeof (output) / sizeof (output[0])); uint32_t *state_pos = (uint32_t *) &(dst->sw_ctx.state[0]); while (output_pos != output_end) { *state_pos ++ = nu_get32_be(output_pos + 4); *state_pos ++ = nu_get32_be(output_pos); output_pos += 8; } } memcpy(dst->sw_ctx.buffer, src->hw_ctx.buffer, src->hw_ctx.buffer_left); dst->sw_ctx.is384 = src->hw_ctx.is224_384; if (src->hw_ctx.buffer_left == src->hw_ctx.blocksize) { mbedtls_sha512_sw_process(&dst->sw_ctx, dst->sw_ctx.buffer); } } else if (src->active_ctx == &src->sw_ctx) { // Clone S/W ctx from S/W ctx dst->sw_ctx = src->sw_ctx; } }