// Copyright (c) 2016 Thomas Pornin // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // THIS SOFTWARE IS PROVIDED BY THE AUTHORS “AS IS” AND ANY EXPRESS OR // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package aes_ct64 add_round_key :: proc "contextless" (q: ^[8]u64, sk: []u64) #no_bounds_check { ensure_contextless(len(sk) >= 8, "aes/ct64: invalid round key size") q[0] ~= sk[0] q[1] ~= sk[1] q[2] ~= sk[2] q[3] ~= sk[3] q[4] ~= sk[4] q[5] ~= sk[5] q[6] ~= sk[6] q[7] ~= sk[7] } shift_rows :: proc "contextless" (q: ^[8]u64) { for x, i in q { q[i] = (x & 0x000000000000FFFF) | ((x & 0x00000000FFF00000) >> 4) | ((x & 0x00000000000F0000) << 12) | ((x & 0x0000FF0000000000) >> 8) | ((x & 0x000000FF00000000) << 8) | ((x & 0xF000000000000000) >> 12) | ((x & 0x0FFF000000000000) << 4) } } mix_columns :: proc "contextless" (q: ^[8]u64) { q0 := q[0] q1 := q[1] q2 := q[2] q3 := q[3] q4 := q[4] q5 := q[5] q6 := q[6] q7 := q[7] r0 := (q0 >> 16) | (q0 << 48) r1 := (q1 >> 16) | (q1 << 48) r2 := (q2 >> 16) | (q2 << 48) r3 := (q3 >> 16) | (q3 << 48) r4 := (q4 >> 16) | (q4 << 48) r5 := (q5 >> 16) | (q5 << 48) r6 := (q6 >> 16) | (q6 << 48) r7 := (q7 >> 16) | (q7 << 48) q[0] = q7 ~ r7 ~ r0 ~ rotr32(q0 ~ r0) q[1] = q0 ~ r0 ~ q7 ~ r7 ~ r1 ~ rotr32(q1 ~ r1) q[2] = q1 ~ r1 ~ r2 ~ rotr32(q2 ~ r2) q[3] = q2 ~ r2 ~ q7 ~ r7 ~ r3 ~ rotr32(q3 ~ r3) q[4] = q3 ~ r3 ~ q7 ~ r7 ~ r4 ~ rotr32(q4 ~ r4) q[5] = q4 ~ r4 ~ r5 ~ rotr32(q5 ~ r5) q[6] = q5 ~ r5 ~ r6 ~ rotr32(q6 ~ r6) q[7] = q6 ~ r6 ~ r7 ~ rotr32(q7 ~ r7) } @(private) _encrypt :: proc "contextless" (q: ^[8]u64, skey: []u64, num_rounds: int) { add_round_key(q, skey) for u in 1 ..< num_rounds { sub_bytes(q) shift_rows(q) mix_columns(q) add_round_key(q, skey[u << 3:]) } sub_bytes(q) shift_rows(q) add_round_key(q, skey[num_rounds << 3:]) }