Пример #1
0
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;
    }
}
Пример #2
0
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;
    }
}
Пример #3
0
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;
                    }
            }
        }
    }
}
Пример #4
0
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;
}