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_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; } }
void crypto_sha_update_nobuf(crypto_sha_context *ctx, const unsigned char *input, size_t ilen, int islast) { // Accept only: // 1. Last block which may be incomplete // 2. Non-last block which is complete MBED_ASSERT(islast || ilen == ctx->blocksize); const unsigned char *in_pos = input; int rmn = ilen; uint32_t sha_ctl_start = (CRPT->SHA_CTL & ~(CRPT_SHA_CTL_DMALAST_Msk | CRPT_SHA_CTL_DMAEN_Msk)) | CRPT_SHA_CTL_START_Msk; uint32_t sha_opmode = (CRPT->SHA_CTL & CRPT_SHA_CTL_OPMODE_Msk) >> CRPT_SHA_CTL_OPMODE_Pos; uint32_t DGST0_old, DGST1_old, DGST2_old, DGST3_old, DGST4_old, DGST5_old, DGST6_old, DGST7_old; while (rmn > 0) { CRPT->SHA_CTL = sha_ctl_start; uint32_t data = nu_get32_be(in_pos); if (rmn <= 4) { // Last word of a (in)complete block if (islast) { uint32_t lastblock_size = ctx->total & ctx->blocksize_mask; if (lastblock_size == 0) { lastblock_size = ctx->blocksize; } CRPT->SHA_DMACNT = lastblock_size; CRPT->SHA_CTL = sha_ctl_start | CRPT_SHA_CTL_DMALAST_Msk; } else { switch (sha_opmode) { case SHA_MODE_SHA256: DGST7_old = CRPT->SHA_DGST7; case SHA_MODE_SHA224: DGST5_old = CRPT->SHA_DGST5; DGST6_old = CRPT->SHA_DGST6; case SHA_MODE_SHA1: DGST0_old = CRPT->SHA_DGST0; DGST1_old = CRPT->SHA_DGST1; DGST2_old = CRPT->SHA_DGST2; DGST3_old = CRPT->SHA_DGST3; DGST4_old = CRPT->SHA_DGST4; } CRPT->SHA_CTL = sha_ctl_start; } } else { // Non-last word of a complete block CRPT->SHA_CTL = sha_ctl_start; } while (! (CRPT->SHA_STS & CRPT_SHA_STS_DATINREQ_Msk)); CRPT->SHA_DATIN = data; in_pos += 4; rmn -= 4; } if (islast) { // Finish of last block while (CRPT->SHA_STS & CRPT_SHA_STS_BUSY_Msk); } else { // Finish of non-last block // No H/W flag to indicate finish of non-last block process. // Values of SHA_DGSTx registers will change as last word of the block is input, so use it for judgement. int isfinish = 0; while (! isfinish) { switch (sha_opmode) { case SHA_MODE_SHA256: if (DGST7_old != CRPT->SHA_DGST7) { isfinish = 1; break; } case SHA_MODE_SHA224: if (DGST5_old != CRPT->SHA_DGST5 || DGST6_old != CRPT->SHA_DGST6) { isfinish = 1; break; } case SHA_MODE_SHA1: if (DGST0_old != CRPT->SHA_DGST0 || DGST1_old != CRPT->SHA_DGST1 || DGST2_old != CRPT->SHA_DGST2 || DGST3_old != CRPT->SHA_DGST3 || DGST4_old != CRPT->SHA_DGST4) { isfinish = 1; break; } } } } }
static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_SIZE], int enc, uint32_t tdes_opmode, size_t length, unsigned char iv[8], const unsigned char *input, unsigned char *output) { if (length % 8) { return MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH; } // NOTE: Don't call driver function TDES_Open in BSP because it doesn't support TDES_CTL[3KEYS] setting. CRPT->TDES_CTL = (0 << CRPT_TDES_CTL_CHANNEL_Pos) | (enc << CRPT_TDES_CTL_ENCRPT_Pos) | tdes_opmode | (TDES_IN_OUT_WHL_SWAP << CRPT_TDES_CTL_BLKSWAP_Pos); // Keying option 1: All three keys are independent. // Keying option 2: K1 and K2 are independent, and K3 = K1. // Keying option 3: All three keys are identical, i.e. K1 = K2 = K3. if (keyopt == 1) { CRPT->TDES_CTL |= CRPT_TDES_CTL_3KEYS_Msk; } else { CRPT->TDES_CTL &= ~CRPT_TDES_CTL_3KEYS_Msk; } // Set DES/TDES keys // NOTE: Don't call driver function TDES_SetKey in BSP because it doesn't support endian swap. uint32_t val; volatile uint32_t *tdes_key = (uint32_t *) ((uint32_t) &CRPT->TDES0_KEY1H + (0x40 * 0)); val = nu_get32_be(key[0] + 0); *tdes_key ++ = val; val = nu_get32_be(key[0] + 4); *tdes_key ++ = val; val = nu_get32_be(key[1] + 0); *tdes_key ++ = val; val = nu_get32_be(key[1] + 4); *tdes_key ++ = val; val = nu_get32_be(key[2] + 0); *tdes_key ++ = val; val = nu_get32_be(key[2] + 4); *tdes_key ++ = val; uint32_t rmn = length; const unsigned char *in_pos = input; const unsigned char *out_pos = output; while (rmn) { uint32_t data_len = (rmn <= MAXSIZE_DMABUF) ? rmn : MAXSIZE_DMABUF; uint32_t ivh, ivl; ivh = nu_get32_be(iv); ivl = nu_get32_be(iv + 4); TDES_SetInitVect(0, ivh, ivl); memcpy(dmabuf_in, in_pos, data_len); TDES_SetDMATransfer(0, (uint32_t) dmabuf_in, (uint32_t) dmabuf_out, data_len); // Start enc/dec. // NOTE: Don't call driver function TDES_Start in BSP because it will override TDES_CTL[3KEYS] setting. CRPT->TDES_CTL |= CRPT_TDES_CTL_START_Msk | (CRYPTO_DMA_ONE_SHOT << CRPT_TDES_CTL_DMALAST_Pos); while (CRPT->TDES_STS & CRPT_TDES_STS_BUSY_Msk); memcpy(out_pos, dmabuf_out, data_len); in_pos += data_len; out_pos += data_len; rmn -= data_len; // Update IV for next block enc/dec in next function call switch (tdes_opmode) { case DES_MODE_OFB: case TDES_MODE_OFB: { // OFB: IV (enc/dec) = output block XOR input block uint32_t lbh, lbl; // Last block of input data lbh = nu_get32_be(dmabuf_in + data_len - 8 + 4); lbl = nu_get32_be(dmabuf_in + data_len - 8 + 0); // Last block of output data ivh = nu_get32_be(dmabuf_out + 4); ivl = nu_get32_be(dmabuf_out + 0); ivh = ivh ^ lbh; ivl = ivl ^ lbl; nu_set32_be(iv + 4, ivh); nu_set32_be(iv, ivl); break; } case DES_MODE_CBC: case DES_MODE_CFB: case TDES_MODE_CBC: case TDES_MODE_CFB: { // CBC/CFB: IV (enc) = output block // IV (dec) = input block if (enc) { memcpy(iv, dmabuf_out + data_len - 8, 8); } else { memcpy(iv, dmabuf_in + data_len - 8, 8); } } } } return 0; }