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
|
/* Copyright 2015 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "dcrypto.h"
#include "internal.h"
#include "registers.h"
static void set_control_register(
unsigned mode, unsigned key_size, unsigned encrypt)
{
GWRITE_FIELD(KEYMGR, AES_CTRL, RESET, CTRL_NO_SOFT_RESET);
GWRITE_FIELD(KEYMGR, AES_CTRL, KEYSIZE, key_size);
GWRITE_FIELD(KEYMGR, AES_CTRL, CIPHER_MODE, mode);
GWRITE_FIELD(KEYMGR, AES_CTRL, ENC_MODE, encrypt);
GWRITE_FIELD(KEYMGR, AES_CTRL, CTR_ENDIAN, CTRL_CTR_BIG_ENDIAN);
GWRITE_FIELD(KEYMGR, AES_CTRL, ENABLE, CTRL_ENABLE);
}
static int wait_read_data(volatile uint32_t *addr)
{
int empty;
int count = 20; /* Wait these many ~cycles. */
do {
empty = REG32(addr);
count--;
} while (count && empty);
return empty ? 0 : 1;
}
int DCRYPTO_aes_init(const uint8_t *key, uint32_t key_len, const uint8_t *iv,
enum cipher_mode c_mode, enum encrypt_mode e_mode)
{
int i;
const struct access_helper *p;
uint32_t key_mode;
switch (key_len) {
case 128:
key_mode = 0;
break;
case 192:
key_mode = 1;
break;
case 256:
key_mode = 2;
break;
default:
/* Invalid key length specified. */
return 0;
}
set_control_register(c_mode, key_mode, e_mode);
/* Initialize hardware with AES key */
p = (struct access_helper *) key;
for (i = 0; i < (key_len >> 5); i++)
GR_KEYMGR_AES_KEY(i) = p[i].udata;
/* Trigger key expansion. */
GREG32(KEYMGR, AES_KEY_START) = 1;
/* Wait for key expansion. */
if (!wait_read_data(GREG32_ADDR(KEYMGR, AES_KEY_START))) {
/* Should not happen. */
return 0;
}
/* Initialize IV for modes that require it. */
if (iv) {
p = (struct access_helper *) iv;
for (i = 0; i < 4; i++)
GR_KEYMGR_AES_CTR(i) = p[i].udata;
}
return 1;
}
int DCRYPTO_aes_block(const uint8_t *in, uint8_t *out)
{
int i;
struct access_helper *outw;
const struct access_helper *inw = (struct access_helper *) in;
/* Write plaintext. */
for (i = 0; i < 4; i++)
GREG32(KEYMGR, AES_WFIFO_DATA) = inw[i].udata;
/* Wait for the result. */
if (!wait_read_data(GREG32_ADDR(KEYMGR, AES_RFIFO_EMPTY))) {
/* Should not happen, ciphertext not ready. */
return 0;
}
/* Read ciphertext. */
outw = (struct access_helper *) out;
for (i = 0; i < 4; i++)
outw[i].udata = GREG32(KEYMGR, AES_RFIFO_DATA);
return 1;
}
void DCRYPTO_aes_write_iv(const uint8_t *iv)
{
int i;
const uint32_t *p = (const uint32_t *) iv;
for (i = 0; i < 4; i++)
GR_KEYMGR_AES_CTR(i) = p[i];
}
void DCRYPTO_aes_read_iv(uint8_t *iv)
{
int i;
uint32_t *p = (uint32_t *) iv;
for (i = 0; i < 4; i++)
p[i] = GR_KEYMGR_AES_CTR(i);
}
|