-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathAArch64cryptolib.h
253 lines (233 loc) · 11.3 KB
/
AArch64cryptolib.h
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
//Copyright (c) 2018-2019, ARM Limited. All rights reserved.
//
//SPDX-License-Identifier: BSD-3-Clause
#ifndef AARCH64CRYPTOLIB_H
#define AARCH64CRYPTOLIB_H
#include <stdint.h>
#include <stdlib.h>
typedef enum cipher_mode { AES_GCM_128, AES_GCM_192, AES_GCM_256 } armv8_cipher_mode_t;
typedef enum operation_result { SUCCESSFUL_OPERATION = 0, AUTHENTICATION_FAILURE=1, INTERNAL_FAILURE, INVALID_PARAMETER } armv8_operation_result_t;
typedef union doubleword {
uint8_t b[8];
uint16_t h[4];
uint32_t s[2];
uint64_t d[1];
} armv8_doubleword_t;
typedef union quadword {
uint8_t b[16];
uint16_t h[8];
uint32_t s[4];
uint64_t d[2];
} armv8_quadword_t;
#if defined(PERF_GCM_LITTLE) || defined(PERF_GCM_BIG)
#define IPSEC_ENABLED
#define MAX_UNROLL_FACTOR 4
#else
#if defined(PERF_GCM_BIGGER)
#define MAX_UNROLL_FACTOR 8
#else
#define MAX_UNROLL_FACTOR 1
#endif
#endif
typedef struct cipher_constants {
armv8_quadword_t expanded_aes_keys[15];
armv8_quadword_t expanded_hash_keys[MAX_UNROLL_FACTOR];
armv8_doubleword_t karat_hash_keys[MAX_UNROLL_FACTOR];
armv8_cipher_mode_t mode;
uint8_t tag_byte_length;
} armv8_cipher_constants_t;
typedef struct cipher_state {
armv8_quadword_t counter;
armv8_quadword_t current_tag;
armv8_cipher_constants_t * constants;
} armv8_cipher_state_t;
typedef struct {
struct {
uint8_t *key;
uint8_t *iv;
} cipher;
struct {
struct {
uint8_t *key;
uint8_t *i_key_pad;
uint8_t *o_key_pad;
} hmac;
} digest;
} armv8_cipher_digest_t;
/*
* Auxiliary calls for AES-CBC/SHA
*/
void armv8_expandkeys_enc_aes_cbc_128(uint8_t *expanded_key, const uint8_t *user_key);
void armv8_expandkeys_dec_aes_cbc_128(uint8_t *expanded_key, const uint8_t *user_key);
int armv8_sha1_block_partial(uint8_t *init, const uint8_t *src, uint8_t *dst,
uint64_t len);
int armv8_sha256_block_partial(uint8_t *init, const uint8_t *src, uint8_t *dst,
uint64_t len);
/*
* Main interface calls for AES-CBC+SHA1/256 encryption and decryption
*/
int armv8_enc_aes_cbc_sha1_128(
uint8_t *csrc, uint8_t *cdst, uint64_t clen,
uint8_t *dsrc, uint8_t *ddst, uint64_t dlen,
armv8_cipher_digest_t *arg);
int armv8_enc_aes_cbc_sha256_128(
uint8_t *csrc, uint8_t *cdst, uint64_t clen,
uint8_t *dsrc, uint8_t *ddst, uint64_t dlen,
armv8_cipher_digest_t *arg);
int armv8_dec_aes_cbc_sha1_128(
uint8_t *csrc, uint8_t *cdst, uint64_t clen,
uint8_t *dsrc, uint8_t *ddst, uint64_t dlen,
armv8_cipher_digest_t *arg);
int armv8_dec_aes_cbc_sha256_128(
uint8_t *csrc, uint8_t *cdst, uint64_t clen,
uint8_t *dsrc, uint8_t *ddst, uint64_t dlen,
armv8_cipher_digest_t *arg);
// set the cipher_constants
armv8_operation_result_t armv8_aes_gcm_set_constants(
armv8_cipher_mode_t mode,
uint8_t tag_byte_length,
uint8_t * restrict key,
armv8_cipher_constants_t * restrict cc);
// set the counter based on a nonce value (will invoke GHASH if nonce_length!=96)
armv8_operation_result_t armv8_aes_gcm_set_counter(
uint8_t * restrict nonce, uint64_t nonce_length,
//assumed that nonce can be read in 16B blocks - will read (but not use) up to 15B beyond the end of the nonce
armv8_cipher_state_t * restrict cs);
// mode indicates which AEAD is being used (currently only planning to support AES-GCM variants)
// key is secret key K as in RFC5116 - length determined by mode
// nonce and aad as in RFC5116
// aad is authenticated but not encrypted
// plaintext is input to be encrypted and authenticated
// ciphertext is the resultant encrypted data with the authentication tag appended to it (should be 16B longer than plaintext)
// expected return value is SUCCESSFUL_OPERATION
// but will return INTERNAL_FAILURE if you hit any functions not yet implemented
armv8_operation_result_t armv8_enc_aes_gcm_full(
//Inputs
armv8_cipher_mode_t mode,
uint8_t * restrict key,
uint8_t * restrict nonce, uint64_t nonce_bit_length,
//assumed that nonce can be read in 16B blocks - will read (but not use) up to 15B beyond the end of the nonce
uint8_t * restrict aad, uint64_t aad_bit_length,
//assumed that aad can be read in 16B blocks - will read (but not use) up to 15B beyond the end of the aad
uint8_t * plaintext, uint64_t plaintext_bit_length,
//assumed that plaintext can be read in 16B blocks - will read (but not use) up to 15B beyond the end of the plaintext
//Outputs
uint8_t * ciphertext,
//assumed that ciphertext can be written in 16B blocks - will write up to 15B of 0s beyond the end of the ciphertext
uint8_t * tag
//assumed that bytes up to tag+15 are accessible and 16B tag always written
);
// Given a set up state, we can do the encrypt operation
// - plaintext and ciphertext can point to the same place for in place operation
// NOTE - cipher_state set up:
// 1) cipher_constants set up:
// set mode and tag_length as appropriate
// call appropriate aes_gcm_expandkeys_*_kernel for your mode (expects master 128/192/256b key as input)
// 2) cipher_state set up:
// set constants pointer to point to a set up cipher_constants
// call aes_gcm_set_counter_kernel with your nonce
// NOTE - encrypt_from_state will ignore and overwrite any current value in cs->current_tag
// expected return value is SUCCESSFUL_OPERATION
// but will return INTERNAL_FAILURE if you hit any functions not yet implemented
armv8_operation_result_t armv8_enc_aes_gcm_from_state(
//Inputs
armv8_cipher_state_t * cs,
uint8_t * restrict aad, uint64_t aad_bit_length,
//assumed that aad can be read in 16B blocks - will read (but not use) up to 15B beyond the end of the aad
uint8_t * plaintext, uint64_t plaintext_bit_length,
//assumed that plaintext can be read in 16B blocks - will read (but not use) up to 15B beyond the end of the plaintext
//Outputs
uint8_t * ciphertext,
//assumed that ciphertext can be written in 16B blocks - will write up to 15B of 0s beyond the end of the ciphertext
uint8_t * tag
//assumed that bytes up to tag+15 are accessible and 16B tag always written
);
// Given a set up cipher_constants_t and the IPsec salt and ESPIV, perform encryption in place
armv8_operation_result_t armv8_enc_aes_gcm_from_constants_IPsec(
//Inputs
const armv8_cipher_constants_t * cc,
uint32_t salt,
uint64_t ESPIV,
const uint8_t * restrict aad, uint32_t aad_byte_length,
//assumes aad zero padded to 16B and 0 < aad_byte_length <=16
uint8_t * plaintext, uint32_t plaintext_byte_length,
//in place operation - plaintext becomes ciphertext
//assumed that ciphertext can be written in 16B blocks - will write up to 15B of 0s beyond the end of the plaintext
//Output
uint8_t * tag
//tag written after ciphertext, so tag will be produced correctly if directly after plaintext
//will always write 16B of tag, regardless of the tag_byte_length specified in cc
//caller must ensure that this region is accessible and must preserve any important data
);
// mode indicates which AEAD is being used (currently only planning to support AES-GCM variants)
// key is secret key K as in RFC5116 - length determined by mode
// nonce and aad as in RFC5116
// aad is authenticated but not decrypted
// ciphertext is the input data to be decrypted with the authentication tag appended to it
// plaintext is the resultant decrypted data (should be 16B shorter than ciphertext)
// expected return value is SUCCESSFUL_OPERATION or AUTHENTICATION_FAILURE (if the provided tag does not match the computed tag)
// but will return INTERNAL_FAILURE if you hit any functions not yet implemented
armv8_operation_result_t armv8_dec_aes_gcm_full(
//Inputs
armv8_cipher_mode_t mode,
uint8_t * restrict key,
uint8_t * restrict nonce, uint64_t nonce_bit_length,
//assumed that nonce can be read in 16B blocks - will read (but not use) up to 15B beyond the end of the nonce
uint8_t * restrict aad, uint64_t aad_bit_length,
//assumed that aad can be read in 16B blocks - will read (but not use) up to 15B beyond the end of the aad
uint8_t * ciphertext, uint64_t ciphertext_bit_length,
//assumed that ciphertext can be read in 16B blocks - will read (but not use) up to 15B beyond the end of the ciphertext
uint8_t * tag, uint64_t tag_byte_length,
//assumed that bytes up to tag+15 are accessible, though only the number specified in cipher_constants are used
//Output
uint8_t * plaintext
//assumed that plaintext can be written in 16B blocks - will write up to 15B of 0s beyond the end of the plaintext
);
// Given a set up state, we can do the decrypt operation
// - ciphertext and plaintext can point to the same place for in place operation
// NOTE - cipher_state set up:
// 1) cipher_constants set up:
// set mode and tag_length as appropriate
// call appropriate aes_gcm_expandkeys_*_kernel for your mode (expects master 128/192/256b key as input)
// 2) cipher_state set up:
// set constants pointer to point to a set up cipher_constants
// call aes_gcm_set_counter_kernel with your nonce
// NOTE - decrypt_from_state will ignore and overwrite any current value in cs->current_tag
// expected return value is SUCCESSFUL_OPERATION or AUTHENTICATION_FAILURE (if the provided tag does not match the computed tag)
// but will return INTERNAL_FAILURE if you hit any functions not yet implemented
armv8_operation_result_t armv8_dec_aes_gcm_from_state(
//Inputs
armv8_cipher_state_t * cs,
uint8_t * restrict aad, uint64_t aad_bit_length,
//assumed that aad can be read in 16B blocks - will read (but not use) up to 15B beyond the end of the aad
uint8_t * ciphertext, uint64_t ciphertext_bit_length,
//assumed that ciphertext can be read in 16B blocks - will read (but not use) up to 15B beyond the end of the ciphertext
uint8_t * tag,
//tag_byte_length specified in cipher_constants
//assumed that bytes up to tag+15 are accessible, though only the number specified in cipher_constants are used
//Output
uint8_t * plaintext
//assumed that plaintext can be written in 16B blocks - will write up to 15B of 0s beyond the end of the ciphertext
);
// Given a set up cipher_constants_t and the IPsec salt and ESPIV, perform decryption in place
// Compute checksum of the plaintext at the same time
armv8_operation_result_t armv8_dec_aes_gcm_from_constants_IPsec(
//Inputs
const armv8_cipher_constants_t * cc,
uint32_t salt,
uint64_t ESPIV,
const uint8_t * restrict aad, uint32_t aad_byte_length,
//aad_byte_length 8 or 12
//assumed that aad can be read with a 16B read - will read (but not use) up to 8B beyond the end of aad
uint8_t * ciphertext, uint32_t ciphertext_byte_length,
//in place operation - ciphertext becomes plaintext
//assumed that plaintext can be written in 8B blocks - will write up to 7B of 0s beyond the end of the ciphertext
const uint8_t * tag,
//tag_byte_length specified in cipher_constants
//tag is read before last block of plaintext is written and written back afterwards, so tag will be preserved
//supported tag sizes are 8B, 12B and 16B, and precisely the size specified will be read/written
//Output
uint64_t * checksum
//one's complement sum of all 64b words in the plaintext
);
#endif