aboutsummaryrefslogtreecommitdiff
path: root/core/crypto/_aes/ct64/api.odin
blob: 08acd37ed572ea1d49a0c0dd21bd701cfec292c1 (plain)
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
package aes_ct64

import "core:crypto"

STRIDE :: 4

// Context is a keyed AES (ECB) instance.
Context :: struct {
	_sk_exp:     [120]u64,
	_num_rounds: int,
}

// init initializes a context for AES with the provided key.
init :: proc(ctx: ^Context, key: []byte) {
	skey: [30]u64 = ---

	ctx._num_rounds = keysched(skey[:], key)
	skey_expand(ctx._sk_exp[:], skey[:], ctx._num_rounds)
}

// encrypt_block sets `dst` to `AES-ECB-Encrypt(src)`.
encrypt_block :: proc(ctx: ^Context, dst, src: []byte) {
	q: [8]u64
	load_blockx1(&q, src)
	_encrypt(&q, ctx._sk_exp[:], ctx._num_rounds)
	store_blockx1(dst, &q)
}

// encrypt_block sets `dst` to `AES-ECB-Decrypt(src)`.
decrypt_block :: proc(ctx: ^Context, dst, src: []byte) {
	q: [8]u64
	load_blockx1(&q, src)
	_decrypt(&q, ctx._sk_exp[:], ctx._num_rounds)
	store_blockx1(dst, &q)
}

// encrypt_blocks sets `dst` to `AES-ECB-Encrypt(src[0], .. src[n])`.
encrypt_blocks :: proc(ctx: ^Context, dst, src: [][]byte) {
	q: [8]u64 = ---
	src, dst := src, dst

	n := len(src)
	for n > 4 {
		load_blocks(&q, src[0:4])
		_encrypt(&q, ctx._sk_exp[:], ctx._num_rounds)
		store_blocks(dst[0:4], &q)

		src = src[4:]
		dst = dst[4:]
		n -= 4
	}
	if n > 0 {
		load_blocks(&q, src)
		_encrypt(&q, ctx._sk_exp[:], ctx._num_rounds)
		store_blocks(dst, &q)
	}
}

// decrypt_blocks sets dst to `AES-ECB-Decrypt(src[0], .. src[n])`.
decrypt_blocks :: proc(ctx: ^Context, dst, src: [][]byte) {
	q: [8]u64 = ---
	src, dst := src, dst

	n := len(src)
	for n > 4 {
		load_blocks(&q, src[0:4])
		_decrypt(&q, ctx._sk_exp[:], ctx._num_rounds)
		store_blocks(dst[0:4], &q)

		src = src[4:]
		dst = dst[4:]
		n -= 4
	}
	if n > 0 {
		load_blocks(&q, src)
		_decrypt(&q, ctx._sk_exp[:], ctx._num_rounds)
		store_blocks(dst, &q)
	}
}

// reset sanitizes the Context.  The Context must be re-initialized to
// be used again.
reset :: proc(ctx: ^Context) {
	crypto.zero_explicit(ctx, size_of(ctx))
}