void skein512_update(struct skein512_ctx *ctx, uint8_t *data, uint32_t len) { uint32_t to_fill; to_fill = 64 - ctx->bufindex; if (ctx->bufindex == 64) { skein512_do_chunk(ctx, (uint64_t *) ctx->buf, 64); ctx->bufindex = 0; } /* process partial buffer if there's enough data to make a block */ if (ctx->bufindex && len >= to_fill) { memcpy(ctx->buf + ctx->bufindex, data, to_fill); skein512_do_chunk(ctx, (uint64_t *) ctx->buf, 64); len -= to_fill; data += to_fill; ctx->bufindex = 0; } /* process as much 64-block as possible except the last one in case we finalize */ for (; len > 64; len -= 64, data += 64) skein512_do_chunk(ctx, (uint64_t *) data, 64); /* append data into buf */ if (len) { memcpy(ctx->buf + ctx->bufindex, data, len); ctx->bufindex += len; } }
void cryptonite_skein512_update(struct skein512_ctx *ctx, const uint8_t *data, uint32_t len) { uint32_t to_fill; if (!len) return; to_fill = 64 - ctx->bufindex; if (ctx->bufindex == 64) { skein512_do_chunk(ctx, (uint64_t *) ctx->buf, 64); ctx->bufindex = 0; } /* process partial buffer if there's enough data to make a block * and there's without doubt further blocks */ if (ctx->bufindex && len > to_fill) { memcpy(ctx->buf + ctx->bufindex, data, to_fill); skein512_do_chunk(ctx, (uint64_t *) ctx->buf, 64); len -= to_fill; data += to_fill; ctx->bufindex = 0; } if (need_alignment(data, 8)) { uint64_t tramp[8]; ASSERT_ALIGNMENT(tramp, 8); for (; len > 64; len -= 64, data += 64) { memcpy(tramp, data, 64); skein512_do_chunk(ctx, tramp, 64); } } else { /* process as much 64-block as possible except the last one in case we finalize */ for (; len > 64; len -= 64, data += 64) skein512_do_chunk(ctx, (uint64_t *) data, 64); } /* append data into buf */ if (len) { memcpy(ctx->buf + ctx->bufindex, data, len); ctx->bufindex += len; } }
void skein512_finalize(struct skein512_ctx *ctx, uint8_t *out) { uint32_t outsize; uint64_t *p = (uint64_t *) out; uint64_t x[8]; int i, j, n; ctx->t1 |= FLAG_FINAL; /* if buf is not complete pad with 0 bytes */ if (ctx->bufindex < 64) memset(ctx->buf + ctx->bufindex, '\0', 64 - ctx->bufindex); skein512_do_chunk(ctx, (uint64_t *) ctx->buf, ctx->bufindex); memset(ctx->buf, '\0', 64); /* make sure we have a 8 bit rounded value */ outsize = ctx->hashlen; /* backup h[0--7] */ for (j = 0; j < 8; j++) x[j] = ctx->h[j]; /* threefish in counter mode, 0 for 1st 64 bytes, 1 for 2nd 64 bytes, .. */ for (i = 0; i*64 < outsize; i++) { uint64_t w[8]; *((uint64_t *) ctx->buf) = cpu_to_le64(i); SET_TYPE(ctx, FLAG_FIRST | FLAG_FINAL | FLAG_TYPE(TYPE_OUT)); skein512_do_chunk(ctx, (uint64_t *) ctx->buf, sizeof(uint64_t)); n = outsize - i * 64; if (n >= 64) n = 64; cpu_to_le64_array(w, ctx->h, 8); memcpy(out + i*64, w, n); /* restore h[0--7] */ for (j = 0; j < 8; j++) ctx->h[j] = x[j]; } }
void cryptonite_skein512_init(struct skein512_ctx *ctx, uint32_t hashlen) { uint64_t buf[8]; memset(ctx, 0, sizeof(*ctx)); SET_TYPE(ctx, FLAG_FIRST | FLAG_FINAL | FLAG_TYPE(TYPE_CFG)); memset(buf, '\0', sizeof(buf)); buf[0] = cpu_to_le64((SKEIN_VERSION << 32) | SKEIN_IDSTRING); buf[1] = cpu_to_le64(hashlen); buf[2] = 0; /* tree info, not implemented */ skein512_do_chunk(ctx, buf, 4*8); SET_TYPE(ctx, FLAG_FIRST | FLAG_TYPE(TYPE_MSG)); }