/* Low-level operations */ static unsafe void norx_init(norx_state_t *state, byte *k, byte *n) { norx_word_t *S = state->S; ulong i; for (i = 0; i < 16; ++i) { S[i] = (norx_word_t)i; } F(S); F(S); S[0] = load32(n + 0 * (((32) + 7) / 8)); S[1] = load32(n + 1 * (((32) + 7) / 8)); S[2] = load32(n + 2 * (((32) + 7) / 8)); S[3] = load32(n + 3 * (((32) + 7) / 8)); S[4] = load32(k + 0 * (((32) + 7) / 8)); S[5] = load32(k + 1 * (((32) + 7) / 8)); S[6] = load32(k + 2 * (((32) + 7) / 8)); S[7] = load32(k + 3 * (((32) + 7) / 8)); S[12] ^= 32; S[13] ^= 4; S[14] ^= 1; S[15] ^= (32 * 4); norx_permute(state); S[12] ^= load32(k + 0 * (((32) + 7) / 8)); S[13] ^= load32(k + 1 * (((32) + 7) / 8)); S[14] ^= load32(k + 2 * (((32) + 7) / 8)); S[15] ^= load32(k + 3 * (((32) + 7) / 8)); }
static unsafe void norx_finalise(norx_state_t *state, byte *tag, byte *k) { norx_word_t *S = state->S; byte * lastblock = stackalloc byte[((((32 * 4)) + 7) / 8)]; S[15] ^= (norx_word_t)tag_t.FINAL_TAG; norx_permute(state); S[12] ^= load32(k + 0 * (((32) + 7) / 8)); S[13] ^= load32(k + 1 * (((32) + 7) / 8)); S[14] ^= load32(k + 2 * (((32) + 7) / 8)); S[15] ^= load32(k + 3 * (((32) + 7) / 8)); norx_permute(state); S[12] ^= load32(k + 0 * (((32) + 7) / 8)); S[13] ^= load32(k + 1 * (((32) + 7) / 8)); S[14] ^= load32(k + 2 * (((32) + 7) / 8)); S[15] ^= load32(k + 3 * (((32) + 7) / 8)); store32(lastblock + 0 * (((32) + 7) / 8), S[12]); store32(lastblock + 1 * (((32) + 7) / 8), S[13]); store32(lastblock + 2 * (((32) + 7) / 8), S[14]); store32(lastblock + 3 * (((32) + 7) / 8), S[15]); memcpy(tag, lastblock, ((((32 * 4)) + 7) / 8)); memset(lastblock, 0, ((((32 * 4)) + 7) / 8)); /* burn buffer */ *state = default(norx_state_t); /* at this point we can also burn the state */ }
static unsafe void norx_absorb_lastblock(norx_state_t *state, byte * @in, ulong inlen, tag_t tag) { byte *lastblock = stackalloc byte[(((((32 * 16) - (32 * 4))) + 7) / 8)]; norx_pad(lastblock, @in, inlen); norx_absorb_block(state, lastblock, tag); }
static unsafe void norx_decrypt_lastblock(norx_state_t *state, byte *@out, byte * @in, ulong inlen) { norx_word_t *S = state->S; byte * lastblock = stackalloc byte[(((((32 * 16) - (32 * 4))) + 7) / 8)]; ulong i; S[15] ^= (norx_word_t)tag_t.PAYLOAD_TAG; norx_permute(state); for (i = 0; i < (((((32 * 16) - (32 * 4))) + (32 - 1)) / 32); ++i) { store32(lastblock + i * (((32) + 7) / 8), S[i]); } memcpy(lastblock, @in, inlen); lastblock[inlen] ^= 0x01; lastblock[(((((32 * 16) - (32 * 4))) + 7) / 8) - 1] ^= 0x80; for (i = 0; i < (((((32 * 16) - (32 * 4))) + (32 - 1)) / 32); ++i) { norx_word_t c = load32(lastblock + i * (((32) + 7) / 8)); store32(lastblock + i * (((32) + 7) / 8), S[i] ^ c); S[i] = c; } memcpy(@out, lastblock, inlen); memset(lastblock, 0, (((((32 * 16) - (32 * 4))) + 7) / 8)); }
static unsafe void norx_encrypt_lastblock(norx_state_t *state, byte *@out, byte * @in, ulong inlen) { byte *lastblock = stackalloc byte[(((((32 * 16) - (32 * 4))) + 7) / 8)]; norx_pad(lastblock, @in, inlen); norx_encrypt_block(state, lastblock, lastblock); memcpy(@out, lastblock, inlen); }
/* The core permutation */ static unsafe void norx_permute(norx_state_t *state) { ulong i; norx_word_t *S = state->S; for (i = 0; i < 4; ++i) { F(S); } }
static unsafe void norx_absorb_block(norx_state_t *state, byte * @in, tag_t tag) { ulong i; norx_word_t *S = state->S; S[15] ^= (norx_word_t)tag; norx_permute(state); for (i = 0; i < (((((32 * 16) - (32 * 4))) + (32 - 1)) / 32); ++i) { S[i] ^= load32(@in + i * (((32) + 7) / 8)); } }
static unsafe void norx_encrypt_block(norx_state_t *state, byte *@out, byte * @in) { ulong i; norx_word_t *S = state->S; S[15] ^= (norx_word_t)tag_t.PAYLOAD_TAG; norx_permute(state); for (i = 0; i < (((((32 * 16) - (32 * 4))) + (32 - 1)) / 32); ++i) { S[i] ^= load32(@in + i * (((32) + 7) / 8)); store32(@out + i * (((32) + 7) / 8), S[i]); } }
static unsafe void norx_decrypt_block(norx_state_t *state, byte *@out, byte * @in) { ulong i; norx_word_t *S = state->S; S[15] ^= (norx_word_t)tag_t.PAYLOAD_TAG; norx_permute(state); for (i = 0; i < (((((64 * 16) - (64 * 4))) + (64 - 1)) / 64); ++i) { norx_word_t c = load64(@in + i * (((64) + 7) / 8)); store64(@out + i * (((64) + 7) / 8), S[i] ^ c); S[i] = c; } }
static unsafe void norx_absorb_data(norx_state_t *state, byte * @in, ulong inlen, tag_t tag) { if (inlen > 0) { while (inlen >= (((((32 * 16) - (32 * 4))) + 7) / 8)) { norx_absorb_block(state, @in, tag); inlen -= (((((32 * 16) - (32 * 4))) + 7) / 8); @in += (((((32 * 16) - (32 * 4))) + 7) / 8); } norx_absorb_lastblock(state, @in, inlen, tag); } }
static unsafe void norx_decrypt_data(norx_state_t *state, byte *@out, byte * @in, ulong inlen) { if (inlen > 0) { while (inlen >= (((((32 * 16) - (32 * 4))) + 7) / 8)) { norx_decrypt_block(state, @out, @in); inlen -= (((((32 * 16) - (32 * 4))) + 7) / 8); @in += (((((32 * 16) - (32 * 4))) + 7) / 8); @out += (((((32 * 16) - (32 * 4))) + 7) / 8); } norx_decrypt_lastblock(state, @out, @in, inlen); } }
/* High-level operations */ static unsafe void norx_aead_encrypt( byte *c, ulong *clen, byte *a, ulong alen, byte *m, ulong mlen, byte *z, ulong zlen, byte *nonce, byte *key ) { byte * k = stackalloc byte[((((32 * 4)) + 7) / 8)]; norx_state_t *state = stackalloc norx_state_t[1]; memcpy(k, key, ((((32 * 4)) + 7) / 8)); norx_init(state, k, nonce); norx_absorb_data(state, a, alen, tag_t.HEADER_TAG); norx_encrypt_data(state, c, m, mlen); norx_absorb_data(state, z, zlen, tag_t.TRAILER_TAG); norx_finalise(state, c + mlen, k); *clen = mlen + ((((32 * 4)) + 7) / 8); *state = default(norx_state_t); memset(k, 0, ((((32 * 4)) + 7) / 8)); }
static unsafe int norx_aead_decrypt( byte *m, ulong *mlen, byte *a, ulong alen, byte *c, ulong clen, byte *z, ulong zlen, byte *nonce, byte *key ) { byte * k = stackalloc byte[((((32 * 4)) + 7) / 8)]; byte * tag = stackalloc byte[((((32 * 4)) + 7) / 8)]; norx_state_t *state = stackalloc norx_state_t[1]; int result = -1; if (clen < ((((32 * 4)) + 7) / 8)) { return(-1); } memcpy(k, key, ((((32 * 4)) + 7) / 8)); norx_init(state, k, nonce); norx_absorb_data(state, a, alen, tag_t.HEADER_TAG); norx_decrypt_data(state, m, c, clen - ((((32 * 4)) + 7) / 8)); norx_absorb_data(state, z, zlen, tag_t.TRAILER_TAG); norx_finalise(state, tag, k); *mlen = clen - ((((32 * 4)) + 7) / 8); result = norx_verify_tag(c + clen - ((((32 * 4)) + 7) / 8), tag); if (result != 0) /* burn decrypted plaintext on auth failure */ { memset(m, 0, clen - ((((32 * 4)) + 7) / 8)); } *state = default(norx_state_t); memset(k, 0, ((((32 * 4)) + 7) / 8)); return(result); }