RTDECL(void) RTSha1Final(PRTSHA1CONTEXT pCtx, uint8_t pabDigest[RTSHA1_HASH_SIZE])
{
    Assert(pCtx->AltPrivate.cbMessage < UINT64_MAX / 2);

    /*
     * Complete the message by adding a single bit (0x80), padding till
     * the next 448-bit boundrary, the add the message length.
     */
    uint64_t const cMessageBits = pCtx->AltPrivate.cbMessage * 8;

    unsigned cbMissing = RTSHA1_BLOCK_SIZE - ((unsigned)pCtx->AltPrivate.cbMessage & (RTSHA1_BLOCK_SIZE - 1U));
    static uint8_t const s_abSingleBitAndSomePadding[12] =  { 0x80, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0, };
    if (cbMissing < 1U + 8U)
        /* Less than 64+8 bits left in the current block, force a new block. */
        RTSha1Update(pCtx, &s_abSingleBitAndSomePadding, sizeof(s_abSingleBitAndSomePadding));
    else
        RTSha1Update(pCtx, &s_abSingleBitAndSomePadding, 1);

    unsigned cbBuffered = (unsigned)pCtx->AltPrivate.cbMessage & (RTSHA1_BLOCK_SIZE - 1U);
    cbMissing = RTSHA1_BLOCK_SIZE - cbBuffered;
    Assert(cbMissing >= 8);
    memset((uint8_t *)&pCtx->AltPrivate.auW[0] + cbBuffered, 0, cbMissing - 8);

    *(uint64_t *)&pCtx->AltPrivate.auW[14] = RT_H2BE_U64(cMessageBits);

    /*
     * Process the last buffered block constructed/completed above.
     */
    rtSha1BlockInitBuffered(pCtx);
    rtSha1BlockProcess(pCtx);

    /*
     * Convert the byte order of the hash words and we're done.
     */
    pCtx->AltPrivate.auH[0] = RT_H2BE_U32(pCtx->AltPrivate.auH[0]);
    pCtx->AltPrivate.auH[1] = RT_H2BE_U32(pCtx->AltPrivate.auH[1]);
    pCtx->AltPrivate.auH[2] = RT_H2BE_U32(pCtx->AltPrivate.auH[2]);
    pCtx->AltPrivate.auH[3] = RT_H2BE_U32(pCtx->AltPrivate.auH[3]);
    pCtx->AltPrivate.auH[4] = RT_H2BE_U32(pCtx->AltPrivate.auH[4]);

    memcpy(pabDigest, &pCtx->AltPrivate.auH[0], RTSHA1_HASH_SIZE);

    RT_ZERO(pCtx->AltPrivate);
    pCtx->AltPrivate.cbMessage = UINT64_MAX;
}
Пример #2
0
RTDECL(void) RTSha1Update(PRTSHA1CONTEXT pCtx, const void *pvBuf, size_t cbBuf)
{
    Assert(pCtx->AltPrivate.cbMessage < UINT64_MAX / 2);
    uint8_t const *pbBuf = (uint8_t const *)pvBuf;

    /*
     * Deal with buffered bytes first.
     */
    size_t cbBuffered = (size_t)pCtx->AltPrivate.cbMessage & (RTSHA1_BLOCK_SIZE - 1U);
    if (cbBuffered)
    {
        size_t cbMissing = RTSHA1_BLOCK_SIZE - cbBuffered;
        if (cbBuf >= cbMissing)
        {
            memcpy((uint8_t *)&pCtx->AltPrivate.auW[0] + cbBuffered, pbBuf, cbMissing);
            pCtx->AltPrivate.cbMessage += cbMissing;
            pbBuf += cbMissing;
            cbBuf -= cbMissing;

            rtSha1BlockInitBuffered(pCtx);
            rtSha1BlockProcess(pCtx);
        }
        else
        {
            memcpy((uint8_t *)&pCtx->AltPrivate.auW[0] + cbBuffered, pbBuf, cbBuf);
            pCtx->AltPrivate.cbMessage += cbBuf;
            return;
        }
    }

    if (!((uintptr_t)pbBuf & 3))
    {
        /*
         * Process full blocks directly from the input buffer.
         */
        while (cbBuf >= RTSHA1_BLOCK_SIZE)
        {
            rtSha1BlockInit(pCtx, pbBuf);
            rtSha1BlockProcess(pCtx);

            pCtx->AltPrivate.cbMessage += RTSHA1_BLOCK_SIZE;
            pbBuf += RTSHA1_BLOCK_SIZE;
            cbBuf -= RTSHA1_BLOCK_SIZE;
        }
    }
    else
    {
        /*
         * Unaligned input, so buffer it.
         */
        while (cbBuf >= RTSHA1_BLOCK_SIZE)
        {
            memcpy((uint8_t *)&pCtx->AltPrivate.auW[0], pbBuf, RTSHA1_BLOCK_SIZE);
            rtSha1BlockInitBuffered(pCtx);
            rtSha1BlockProcess(pCtx);

            pCtx->AltPrivate.cbMessage += RTSHA1_BLOCK_SIZE;
            pbBuf += RTSHA1_BLOCK_SIZE;
            cbBuf -= RTSHA1_BLOCK_SIZE;
        }
    }

    /*
     * Stash any remaining bytes into the context buffer.
     */
    if (cbBuf > 0)
    {
        memcpy((uint8_t *)&pCtx->AltPrivate.auW[0], pbBuf, cbBuf);
        pCtx->AltPrivate.cbMessage += cbBuf;
    }
}