/* This can be used for SHA1, SHA256 and SHA224 */ void ccdigest_final_64be(const struct ccdigest_info *di, ccdigest_ctx_t ctx, unsigned char *digest) { ccdigest_nbits(di, ctx) += ccdigest_num(di, ctx) * 8; ccdigest_data(di, ctx)[ccdigest_num(di, ctx)++] = 0x80; /* If we don't have at least 8 bytes (for the length) left we need to add a second block. */ if (ccdigest_num(di, ctx) > 64 - 8) { while (ccdigest_num(di, ctx) < 64) { ccdigest_data(di, ctx)[ccdigest_num(di, ctx)++] = 0; } di->compress(ccdigest_state(di, ctx), 1, ccdigest_data(di, ctx)); ccdigest_num(di, ctx) = 0; } /* pad upto block_size minus 8 with 0s */ while (ccdigest_num(di, ctx) < 64 - 8) { ccdigest_data(di, ctx)[ccdigest_num(di, ctx)++] = 0; } CC_STORE64_BE(ccdigest_nbits(di, ctx), ccdigest_data(di, ctx) + 64 - 8); di->compress(ccdigest_state(di, ctx), 1, ccdigest_data(di, ctx)); /* copy output */ for (unsigned int i = 0; i < di->output_size / 4; i++) { CC_STORE32_BE(ccdigest_state_u32(di, ctx)[i], digest+(4*i)); } }
void ccsha512_final(const struct ccdigest_info *di, ccdigest_ctx_t ctx, unsigned char *digest) { ccdigest_nbits(di, ctx) += ccdigest_num(di, ctx) << 3; ccdigest_data(di, ctx)[ccdigest_num(di, ctx)++] = 0x80; /* If we don't have at least 16 bytes (for the length) left we need to add a second block. */ if (ccdigest_num(di, ctx) > di->block_size - 16) { while (ccdigest_num(di, ctx) < di->block_size) { ccdigest_data(di, ctx)[ccdigest_num(di, ctx)++] = 0; } di->compress(ccdigest_state(di, ctx), 1, ccdigest_data(di, ctx)); ccdigest_num(di, ctx) = 0; } /* Pad up to block_size minus 8 with 0s */ while (ccdigest_num(di, ctx) < di->block_size - 8) { ccdigest_data(di, ctx)[ccdigest_num(di, ctx)++] = 0; } CC_STORE64_BE(ccdigest_nbits(di, ctx), ccdigest_data(di, ctx) + di->block_size - 8); di->compress(ccdigest_state(di, ctx), 1, ccdigest_data(di, ctx)); /* Copy output */ for (unsigned int i = 0; i < di->output_size / 8; i++) { CC_STORE64_BE(ccdigest_state_u64(di, ctx)[i], digest+(8*i)); } }
void ccdigest_update(const struct ccdigest_info *di, ccdigest_ctx_t ctx, unsigned long len, const void *data) { const char * data_ptr = data; while (len > 0) { if (ccdigest_num(di, ctx) == 0 && len > di->block_size) { unsigned long nblocks = len / di->block_size; di->compress(ccdigest_state(di, ctx), nblocks, data_ptr); unsigned long nbytes = nblocks * di->block_size; len -= nbytes; data_ptr += nbytes; ccdigest_nbits(di, ctx) += nbytes * 8; } else { unsigned long n = di->block_size - ccdigest_num(di, ctx); if (len < n) n = len; CC_MEMCPY(ccdigest_data(di, ctx) + ccdigest_num(di, ctx), data_ptr, n); /* typecast: less than block size, will always fit into an int */ ccdigest_num(di, ctx) += (unsigned int)n; len -= n; data_ptr += n; if (ccdigest_num(di, ctx) == di->block_size) { di->compress(ccdigest_state(di, ctx), 1, ccdigest_data(di, ctx)); ccdigest_nbits(di, ctx) += ccdigest_num(di, ctx) * 8; ccdigest_num(di, ctx) = 0; } } } }
void ccdigest_init(const struct ccdigest_info *di, ccdigest_ctx_t ctx) { ccdigest_copy_state(di, ccdigest_state_ccn(di, ctx), di->initial_state); ccdigest_nbits(di, ctx) = 0; ccdigest_num(di, ctx) = 0; }