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; }
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; } }