Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
aes.c
Go to the documentation of this file.
1/*
2 * Copyright 2015-2018 Yubico AB
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "aes.h"
19
20#include <string.h>
21#include <assert.h>
22
23#ifdef _WIN32_BCRYPT
24#include <ntstatus.h>
25#endif
26
27#ifdef _WIN32_BCRYPT
28static NTSTATUS init_ctx(aes_context *ctx) {
29 NTSTATUS status = STATUS_SUCCESS;
30 BCRYPT_ALG_HANDLE hAlgCBC = 0;
31 BCRYPT_ALG_HANDLE hAlgECB = 0;
32 DWORD cbKeyObj = 0;
33 DWORD cbData = 0;
34
35 if (!ctx) {
36 return STATUS_INVALID_PARAMETER;
37 }
38
39 if (ctx->hAlgCBC) {
40 return STATUS_SUCCESS;
41 }
42
43 /* clear the context, to "reset" */
44
45 insecure_memzero(ctx, sizeof(aes_context));
46
47 if (!BCRYPT_SUCCESS(status = BCryptOpenAlgorithmProvider(&hAlgCBC,
48 BCRYPT_AES_ALGORITHM,
49 NULL, 0))) {
50 goto cleanup;
51 }
52
53 if (!BCRYPT_SUCCESS(status =
54 BCryptSetProperty(hAlgCBC, BCRYPT_CHAINING_MODE,
55 (PBYTE) BCRYPT_CHAIN_MODE_CBC,
56 sizeof(BCRYPT_CHAIN_MODE_CBC), 0))) {
57 goto cleanup;
58 }
59
60 if (!BCRYPT_SUCCESS(status = BCryptOpenAlgorithmProvider(&hAlgECB,
61 BCRYPT_AES_ALGORITHM,
62 NULL, 0))) {
63 goto cleanup;
64 }
65
66 if (!BCRYPT_SUCCESS(status =
67 BCryptSetProperty(hAlgECB, BCRYPT_CHAINING_MODE,
68 (PBYTE) BCRYPT_CHAIN_MODE_ECB,
69 sizeof(BCRYPT_CHAIN_MODE_ECB), 0))) {
70 goto cleanup;
71 }
72
73 if (!BCRYPT_SUCCESS(status = BCryptGetProperty(hAlgCBC, BCRYPT_OBJECT_LENGTH,
74 (PBYTE) &cbKeyObj,
75 sizeof(DWORD), &cbData, 0))) {
76 goto cleanup;
77 }
78
79 ctx->hAlgCBC = hAlgCBC;
80 hAlgCBC = 0;
81 ctx->hAlgECB = hAlgECB;
82 hAlgECB = 0;
83 ctx->cbKeyObj = cbKeyObj;
84
85cleanup:
86
87 if (hAlgCBC) {
88 BCryptCloseAlgorithmProvider(hAlgCBC, 0);
89 }
90 if (hAlgECB) {
91 BCryptCloseAlgorithmProvider(hAlgECB, 0);
92 }
93
94 return status;
95}
96
97static NTSTATUS import_key(BCRYPT_ALG_HANDLE hAlg, BCRYPT_KEY_HANDLE *phKey,
98 PBYTE *ppbKeyObj, DWORD cbKeyObj, const uint8_t *key,
99 size_t key_len) {
100 NTSTATUS status = STATUS_SUCCESS;
101 PBYTE pbKeyObj = NULL;
102 BCRYPT_KEY_HANDLE hKey = 0;
103 PBYTE pbKeyBlob = NULL;
104 DWORD cbKeyBlob = 0;
105
106 if (!phKey || !ppbKeyObj) {
107 return STATUS_INVALID_PARAMETER;
108 }
109
110 /* close existing key first */
111 if (*phKey) {
112 BCryptDestroyKey(*phKey);
113 *phKey = 0;
114 }
115
116 /* free existing key object */
117 if (*ppbKeyObj) {
118 free(*ppbKeyObj);
119 *ppbKeyObj = NULL;
120 }
121
122 /* allocate new key object */
123 if (!(pbKeyObj = (PBYTE) malloc(cbKeyObj))) {
124 status = STATUS_NO_MEMORY;
125 goto cleanup;
126 }
127
128 cbKeyBlob = (DWORD)(sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + key_len);
129
130 if (!(pbKeyBlob = (PBYTE) malloc(cbKeyBlob))) {
131 status = STATUS_NO_MEMORY;
132 goto cleanup;
133 }
134
135 /* set up BCrypt Key Blob for import */
136 ((BCRYPT_KEY_DATA_BLOB_HEADER *) pbKeyBlob)->dwMagic =
137 BCRYPT_KEY_DATA_BLOB_MAGIC;
138 ((BCRYPT_KEY_DATA_BLOB_HEADER *) pbKeyBlob)->dwVersion =
139 BCRYPT_KEY_DATA_BLOB_VERSION1;
140 ((BCRYPT_KEY_DATA_BLOB_HEADER *) pbKeyBlob)->cbKeyData = (DWORD) key_len;
141 memcpy(pbKeyBlob + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER), key, key_len);
142
143 if (!BCRYPT_SUCCESS(status = BCryptImportKey(hAlg, NULL, BCRYPT_KEY_DATA_BLOB,
144 &hKey, pbKeyObj, cbKeyObj,
145 pbKeyBlob, cbKeyBlob, 0))) {
146 goto cleanup;
147 }
148
149 /* set output params */
150 *phKey = hKey;
151 hKey = 0;
152 *ppbKeyObj = pbKeyObj;
153 pbKeyObj = 0;
154
155cleanup:
156
157 if (hKey) {
158 BCryptDestroyKey(hKey);
159 }
160 if (pbKeyObj) {
161 free(pbKeyObj);
162 }
163 if (pbKeyBlob) {
164 free(pbKeyBlob);
165 }
166
167 return !BCRYPT_SUCCESS(status);
168}
169
170#endif
171
173#ifdef _WIN32_BCRYPT
174 NTSTATUS status = STATUS_SUCCESS;
175
176 if (!BCRYPT_SUCCESS(status = init_ctx(ctx))) {
177 return 1;
178 }
179
180 if (!BCRYPT_SUCCESS(status = import_key(ctx->hAlgCBC, &(ctx->hKeyCBC),
181 &(ctx->pbKeyCBCObj), ctx->cbKeyObj,
182 key, key_len))) {
183 return 1;
184 }
185
186 if (!BCRYPT_SUCCESS(status = import_key(ctx->hAlgECB, &(ctx->hKeyECB),
187 &(ctx->pbKeyECBObj), ctx->cbKeyObj,
188 key, key_len))) {
189 return 1;
190 }
191
192#else
193 AES_set_encrypt_key(key, key_len * 8, &ctx->key);
194 ctx->key_len = key_len;
195
196#endif
197
198 return 0;
199}
200
202#ifdef _WIN32_BCRYPT
203 NTSTATUS status = STATUS_SUCCESS;
204
205 if (!BCRYPT_SUCCESS(status = init_ctx(ctx))) {
206 return 1;
207 }
208
209 if (!BCRYPT_SUCCESS(status = import_key(ctx->hAlgCBC, &(ctx->hKeyCBC),
210 &(ctx->pbKeyCBCObj), ctx->cbKeyObj,
211 key, key_len))) {
212 return 1;
213 }
214
215 if (!BCRYPT_SUCCESS(status = import_key(ctx->hAlgECB, &(ctx->hKeyECB),
216 &(ctx->pbKeyECBObj), ctx->cbKeyObj,
217 key, key_len))) {
218 return 1;
219 }
220
221#else
222 AES_set_decrypt_key(key, key_len * 8, &ctx->key);
223 ctx->key_len = key_len;
224
225#endif
226 return 0;
227}
228
230#ifdef _WIN32_BCRYPT
231 NTSTATUS status = STATUS_SUCCESS;
232 ULONG cbResult = 0;
233
234 if (!BCRYPT_SUCCESS(status = BCryptEncrypt(ctx->hKeyECB, in, AES_BLOCK_SIZE,
235 NULL, NULL, 0, out, AES_BLOCK_SIZE,
236 &cbResult, 0))) {
237 return -2;
238 }
239
240#else
241
242 AES_ecb_encrypt(in, out, &ctx->key, AES_ENCRYPT);
243
244#endif
245
246 return 0;
247}
248
250#ifdef _WIN32_BCRYPT
251 NTSTATUS status = STATUS_SUCCESS;
252 ULONG cbResult = 0;
253
254 if (!BCRYPT_SUCCESS(status = BCryptDecrypt(ctx->hKeyECB, in, AES_BLOCK_SIZE,
255 NULL, NULL, 0, out, AES_BLOCK_SIZE,
256 &cbResult, 0))) {
257 return -1;
258 }
259
260 assert(cbResult == AES_BLOCK_SIZE);
261
262#else
263
264 AES_ecb_encrypt(in, out, &ctx->key, AES_DECRYPT);
265
266#endif
267
268 return 0;
269}
270
272 aes_context *ctx) {
273#ifdef _WIN32_BCRYPT
274 NTSTATUS status = STATUS_SUCCESS;
275 ULONG cbResult = 0;
276
277 if (!BCRYPT_SUCCESS(status = BCryptEncrypt(ctx->hKeyCBC, in, len, NULL, iv,
278 AES_BLOCK_SIZE, out, len,
279 &cbResult, 0))) {
280 return -1;
281 }
282
283#else
284
285 AES_cbc_encrypt(in, out, len, &ctx->key, iv, AES_ENCRYPT);
286
287#endif
288
289 return 0;
290}
291
293 aes_context *ctx) {
294#ifdef _WIN32_BCRYPT
295 NTSTATUS status = STATUS_SUCCESS;
296 ULONG cbResult = 0;
297
298 if (!BCRYPT_SUCCESS(status = BCryptDecrypt(ctx->hKeyCBC, in, len, NULL, iv,
299 AES_BLOCK_SIZE, out, len,
300 &cbResult, 0))) {
301 return -1;
302 }
303
304#else
305
306 AES_cbc_encrypt(in, out, len, &ctx->key, iv, AES_DECRYPT);
307
308#endif
309
310 return 0;
311}
312
314
315 in[(*len)++] = 0x80;
316 while ((*len) % AES_BLOCK_SIZE != 0) {
317 in[(*len)++] = 0x00;
318 }
319}
320
322
323 while (in[(*len) - 1] == 0) {
324 (*len)--;
325 }
326
327 (*len)--;
328}
329
331 if (!ctx) {
332 return;
333 }
334
335#ifdef _WIN32_BCRYPT
336
337 if (ctx->hKeyCBC) {
338 BCryptDestroyKey(ctx->hKeyCBC);
339 }
340 if (ctx->pbKeyCBCObj) {
341 free(ctx->pbKeyCBCObj);
342 }
343 if (ctx->hKeyECB) {
344 BCryptDestroyKey(ctx->hKeyECB);
345 }
346 if (ctx->pbKeyECBObj) {
347 free(ctx->pbKeyECBObj);
348 }
349 if (ctx->hAlgCBC) {
350 BCryptCloseAlgorithmProvider(ctx->hAlgCBC, 0);
351 }
352 if (ctx->hAlgECB) {
353 BCryptCloseAlgorithmProvider(ctx->hAlgECB, 0);
354 }
355
356#endif
357
358 insecure_memzero(ctx, sizeof(aes_context));
359}
void aes_remove_padding(uint8_t *in, uint16_t *len)
Definition aes.c:321
uint8_t aes_set_encrypt_key(uint8_t *key, uint16_t key_len, aes_context *ctx)
Definition aes.c:172
void aes_destroy(aes_context *ctx)
Definition aes.c:330
uint8_t aes_encrypt(uint8_t *in, uint8_t *out, const aes_context *ctx)
Definition aes.c:229
uint8_t aes_decrypt(uint8_t *in, uint8_t *out, const aes_context *ctx)
Definition aes.c:249
uint8_t aes_cbc_decrypt(uint8_t *in, uint8_t *out, uint16_t len, uint8_t *iv, aes_context *ctx)
Definition aes.c:292
void aes_add_padding(uint8_t *in, uint16_t *len)
Definition aes.c:313
uint8_t aes_set_decrypt_key(uint8_t *key, uint16_t key_len, aes_context *ctx)
Definition aes.c:201
uint8_t aes_cbc_encrypt(uint8_t *in, uint8_t *out, uint16_t len, uint8_t *iv, aes_context *ctx)
Definition aes.c:271
#define AES_BLOCK_SIZE
Definition aes.h:35
#define insecure_memzero(buf, len)
unsigned short uint16_t
Definition stdint.h:125
unsigned char uint8_t
Definition stdint.h:124
AES_KEY key
Definition aes.h:52
uint16_t key_len
Definition aes.h:53
CK_SESSION_HANDLE CK_MECHANISM_PTR CK_OBJECT_HANDLE hKey
size_t len
session operation op sign key_len
memcpy((char *) pInfo->slotDescription, s, l)
CK_SESSION_HANDLE CK_MECHANISM_PTR CK_ATTRIBUTE_PTR CK_ULONG CK_OBJECT_HANDLE_PTR phKey