void cf_blockwise_xor(uint8_t *partial, size_t *npartial, size_t nblock, const void *inp, void *outp, size_t nbytes, cf_blockwise_out_fn process, void *ctx) { const uint8_t *inb = inp; uint8_t *outb = outp; assert(partial && *npartial < nblock); assert(inp || !nbytes); assert(process && ctx); while (nbytes) { /* If we're out of material, and need more, produce a block. */ if (*npartial == 0) { process(ctx, partial); *npartial = nblock; } size_t offset = nblock - *npartial; size_t taken = MIN(*npartial, nbytes); xor_bb(outb, inb, partial + offset, taken); *npartial -= taken; nbytes -= taken; outb += taken; inb += taken; } }
static void F(const cf_hmac_ctx *startctx, uint32_t counter, const uint8_t *salt, size_t nsalt, uint32_t iterations, uint8_t *out) { uint8_t U[CF_MAXHASH]; size_t hashsz = startctx->hash->hashsz; uint8_t countbuf[4]; write32_be(counter, countbuf); /* First iteration: * U_1 = PRF(P, S || INT_32_BE(i)) */ cf_hmac_ctx ctx = *startctx; cf_hmac_update(&ctx, salt, nsalt); cf_hmac_update(&ctx, countbuf, sizeof countbuf); cf_hmac_finish(&ctx, U); memcpy(out, U, hashsz); /* Subsequent iterations: * U_c = PRF(P, U_{c-1}) */ for (uint32_t i = 1; i < iterations; i++) { ctx = *startctx; cf_hmac_update(&ctx, U, hashsz); cf_hmac_finish(&ctx, U); xor_bb(out, out, U, hashsz); } }
static void cmac_process_final(cf_cmac_stream *ctx, const uint8_t *block, const uint8_t *xor) { uint8_t input[CF_MAXBLOCK]; uint8_t output[CF_MAXBLOCK]; xor_bb(input, block, xor, ctx->cmac.prp->blocksz); cf_cbc_encrypt(&ctx->cbc, input, output, 1); ctx->processed += ctx->cmac.prp->blocksz; /* signature is in ctx->cbc.block. */ }
void cf_cbc_decrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks) { uint8_t buf[CF_MAXBLOCK]; size_t nblk = ctx->prp->blocksz; while (blocks--) { ctx->prp->decrypt(ctx->prpctx, input, buf); xor_bb(output, buf, ctx->block, nblk); memcpy(ctx->block, input, nblk); input += nblk; output += nblk; } }