1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
// Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
// 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
import "core:crypto"
import "core:crypto/_aes"
import "core:encoding/endian"
@(private, require_results)
sub_word :: proc "contextless" (x: u32) -> u32 {
q := [8]u64{u64(x), 0, 0, 0, 0, 0, 0, 0}
orthogonalize(&q)
sub_bytes(&q)
orthogonalize(&q)
ret := u32(q[0])
crypto.zero_explicit(&q[0], size_of(u64))
return ret
}
@(private, require_results)
keysched :: proc "contextless" (comp_skey: []u64, key: []byte) -> int {
num_rounds, key_len := 0, len(key)
switch key_len {
case _aes.KEY_SIZE_128:
num_rounds = _aes.ROUNDS_128
case _aes.KEY_SIZE_192:
num_rounds = _aes.ROUNDS_192
case _aes.KEY_SIZE_256:
num_rounds = _aes.ROUNDS_256
case:
panic_contextless("crypto/aes: invalid AES key size")
}
skey: [60]u32 = ---
nk, nkf := key_len >> 2, (num_rounds + 1) << 2
for i in 0 ..< nk {
skey[i] = endian.unchecked_get_u32le(key[i << 2:])
}
tmp := skey[(key_len >> 2) - 1]
for i, j, k := nk, 0, 0; i < nkf; i += 1 {
if j == 0 {
tmp = (tmp << 24) | (tmp >> 8)
tmp = sub_word(tmp) ~ u32(_aes.RCON[k])
} else if nk > 6 && j == 4 {
tmp = sub_word(tmp)
}
tmp ~= skey[i - nk]
skey[i] = tmp
if j += 1; j == nk {
j = 0
k += 1
}
}
q: [8]u64 = ---
for i, j := 0, 0; i < nkf; i, j = i + 4, j + 2 {
q[0], q[4] = interleave_in(skey[i], skey[i+1], skey[i+2], skey[i+3])
q[1] = q[0]
q[2] = q[0]
q[3] = q[0]
q[5] = q[4]
q[6] = q[4]
q[7] = q[4]
orthogonalize(&q)
comp_skey[j + 0] =
(q[0] & 0x1111111111111111) |
(q[1] & 0x2222222222222222) |
(q[2] & 0x4444444444444444) |
(q[3] & 0x8888888888888888)
comp_skey[j + 1] =
(q[4] & 0x1111111111111111) |
(q[5] & 0x2222222222222222) |
(q[6] & 0x4444444444444444) |
(q[7] & 0x8888888888888888)
}
crypto.zero_explicit(&skey, size_of(skey))
crypto.zero_explicit(&q, size_of(q))
return num_rounds
}
@(private)
skey_expand :: proc "contextless" (skey, comp_skey: []u64, num_rounds: int) {
n := (num_rounds + 1) << 1
for u, v := 0, 0; u < n; u, v = u + 1, v + 4 {
x0 := comp_skey[u]
x1, x2, x3 := x0, x0, x0
x0 &= 0x1111111111111111
x1 &= 0x2222222222222222
x2 &= 0x4444444444444444
x3 &= 0x8888888888888888
x1 >>= 1
x2 >>= 2
x3 >>= 3
skey[v + 0] = (x0 << 4) - x0
skey[v + 1] = (x1 << 4) - x1
skey[v + 2] = (x2 << 4) - x2
skey[v + 3] = (x3 << 4) - x3
}
}
|