1 /*
2 * xfm.c
3 *
4 * Crypto transform implementation
5 *
6 * David A. McGrew
7 * Cisco Systems, Inc.
8 */
9
10 #include "cryptoalg.h"
11 #include "aes_cbc.h"
12 #include "hmac.h"
13 #include "crypto_kernel.h" /* for crypto_get_random() */
14
15 #define KEY_LEN 16
16 #define ENC_KEY_LEN 16
17 #define MAC_KEY_LEN 16
18 #define IV_LEN 16
19 #define TAG_LEN 12
20 #define MAX_EXPAND 27
21
22 err_status_t
aes_128_cbc_hmac_sha1_96_func(void * key,void * clear,unsigned clear_len,void * iv,void * opaque,unsigned * opaque_len,void * auth_tag)23 aes_128_cbc_hmac_sha1_96_func(void *key,
24 void *clear,
25 unsigned clear_len,
26 void *iv,
27 void *opaque,
28 unsigned *opaque_len,
29 void *auth_tag) {
30 aes_cbc_ctx_t aes_ctx;
31 hmac_ctx_t hmac_ctx;
32 unsigned char enc_key[ENC_KEY_LEN];
33 unsigned char mac_key[MAC_KEY_LEN];
34 err_status_t status;
35
36 /* check if we're doing authentication only */
37 if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
38
39 /* perform authentication only */
40
41 } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
42
43 /*
44 * bad parameter - we expect either all three pointers to be NULL,
45 * or none of those pointers to be NULL
46 */
47 return err_status_fail;
48
49 } else {
50
51 /* derive encryption and authentication keys from the input key */
52 status = hmac_init(&hmac_ctx, key, KEY_LEN);
53 if (status) return status;
54 status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key);
55 if (status) return status;
56
57 status = hmac_init(&hmac_ctx, key, KEY_LEN);
58 if (status) return status;
59 status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key);
60 if (status) return status;
61
62
63 /* perform encryption and authentication */
64
65 /* set aes key */
66 status = aes_cbc_context_init(&aes_ctx, key, direction_encrypt);
67 if (status) return status;
68
69 /* set iv */
70 status = crypto_get_random(iv, IV_LEN);
71 if (status) return status;
72 status = aes_cbc_set_iv(&aes_ctx, iv);
73
74 /* encrypt the opaque data */
75 status = aes_cbc_nist_encrypt(&aes_ctx, opaque, opaque_len);
76 if (status) return status;
77
78 /* authenticate clear and opaque data */
79 status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN);
80 if (status) return status;
81
82 status = hmac_start(&hmac_ctx);
83 if (status) return status;
84
85 status = hmac_update(&hmac_ctx, clear, clear_len);
86 if (status) return status;
87
88 status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, auth_tag);
89 if (status) return status;
90
91 }
92
93 return err_status_ok;
94 }
95
96 err_status_t
aes_128_cbc_hmac_sha1_96_inv(void * key,void * clear,unsigned clear_len,void * iv,void * opaque,unsigned * opaque_len,void * auth_tag)97 aes_128_cbc_hmac_sha1_96_inv(void *key,
98 void *clear,
99 unsigned clear_len,
100 void *iv,
101 void *opaque,
102 unsigned *opaque_len,
103 void *auth_tag) {
104 aes_cbc_ctx_t aes_ctx;
105 hmac_ctx_t hmac_ctx;
106 unsigned char enc_key[ENC_KEY_LEN];
107 unsigned char mac_key[MAC_KEY_LEN];
108 unsigned char tmp_tag[TAG_LEN];
109 unsigned char *tag = auth_tag;
110 err_status_t status;
111 int i;
112
113 /* check if we're doing authentication only */
114 if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
115
116 /* perform authentication only */
117
118 } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
119
120 /*
121 * bad parameter - we expect either all three pointers to be NULL,
122 * or none of those pointers to be NULL
123 */
124 return err_status_fail;
125
126 } else {
127
128 /* derive encryption and authentication keys from the input key */
129 status = hmac_init(&hmac_ctx, key, KEY_LEN);
130 if (status) return status;
131 status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key);
132 if (status) return status;
133
134 status = hmac_init(&hmac_ctx, key, KEY_LEN);
135 if (status) return status;
136 status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key);
137 if (status) return status;
138
139 /* perform encryption and authentication */
140
141 /* set aes key */
142 status = aes_cbc_context_init(&aes_ctx, key, direction_decrypt);
143 if (status) return status;
144
145 /* set iv */
146 status = rand_source_get_octet_string(iv, IV_LEN);
147 if (status) return status;
148 status = aes_cbc_set_iv(&aes_ctx, iv);
149
150 /* encrypt the opaque data */
151 status = aes_cbc_nist_decrypt(&aes_ctx, opaque, opaque_len);
152 if (status) return status;
153
154 /* authenticate clear and opaque data */
155 status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN);
156 if (status) return status;
157
158 status = hmac_start(&hmac_ctx);
159 if (status) return status;
160
161 status = hmac_update(&hmac_ctx, clear, clear_len);
162 if (status) return status;
163
164 status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, tmp_tag);
165 if (status) return status;
166
167 /* compare the computed tag with the one provided as input */
168 for (i=0; i < TAG_LEN; i++)
169 if (tmp_tag[i] != tag[i])
170 return err_status_auth_fail;
171
172 }
173
174 return err_status_ok;
175 }
176
177
178 #define ENC 1
179
180 #undef DEBUG
181 #define DEBUG 0
182
183 err_status_t
aes_128_cbc_hmac_sha1_96_enc(void * key,const void * clear,unsigned clear_len,void * iv,void * opaque,unsigned * opaque_len)184 aes_128_cbc_hmac_sha1_96_enc(void *key,
185 const void *clear,
186 unsigned clear_len,
187 void *iv,
188 void *opaque,
189 unsigned *opaque_len) {
190 aes_cbc_ctx_t aes_ctx;
191 hmac_ctx_t hmac_ctx;
192 unsigned char enc_key[ENC_KEY_LEN];
193 unsigned char mac_key[MAC_KEY_LEN];
194 unsigned char *auth_tag;
195 err_status_t status;
196
197 /* check if we're doing authentication only */
198 if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
199
200 /* perform authentication only */
201
202 } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
203
204 /*
205 * bad parameter - we expect either all three pointers to be NULL,
206 * or none of those pointers to be NULL
207 */
208 return err_status_fail;
209
210 } else {
211
212 #if DEBUG
213 printf("ENC using key %s\n", octet_string_hex_string(key, KEY_LEN));
214 #endif
215
216 /* derive encryption and authentication keys from the input key */
217 status = hmac_init(&hmac_ctx, key, KEY_LEN);
218 if (status) return status;
219 status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key);
220 if (status) return status;
221
222 status = hmac_init(&hmac_ctx, key, KEY_LEN);
223 if (status) return status;
224 status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key);
225 if (status) return status;
226
227
228 /* perform encryption and authentication */
229
230 /* set aes key */
231 status = aes_cbc_context_init(&aes_ctx, key, direction_encrypt);
232 if (status) return status;
233
234 /* set iv */
235 status = rand_source_get_octet_string(iv, IV_LEN);
236 if (status) return status;
237 status = aes_cbc_set_iv(&aes_ctx, iv);
238 if (status) return status;
239
240 #if DEBUG
241 printf("plaintext len: %d\n", *opaque_len);
242 printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN));
243 printf("plaintext: %s\n", octet_string_hex_string(opaque, *opaque_len));
244 #endif
245
246 #if ENC
247 /* encrypt the opaque data */
248 status = aes_cbc_nist_encrypt(&aes_ctx, opaque, opaque_len);
249 if (status) return status;
250 #endif
251
252 #if DEBUG
253 printf("ciphertext len: %d\n", *opaque_len);
254 printf("ciphertext: %s\n", octet_string_hex_string(opaque, *opaque_len));
255 #endif
256
257 /*
258 * authenticate clear and opaque data, then write the
259 * authentication tag to the location immediately following the
260 * ciphertext
261 */
262 status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN);
263 if (status) return status;
264
265 status = hmac_start(&hmac_ctx);
266 if (status) return status;
267
268 status = hmac_update(&hmac_ctx, clear, clear_len);
269 if (status) return status;
270 #if DEBUG
271 printf("hmac input: %s\n",
272 octet_string_hex_string(clear, clear_len));
273 #endif
274 auth_tag = (unsigned char *)opaque;
275 auth_tag += *opaque_len;
276 status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, auth_tag);
277 if (status) return status;
278 #if DEBUG
279 printf("hmac input: %s\n",
280 octet_string_hex_string(opaque, *opaque_len));
281 #endif
282 /* bump up the opaque_len to reflect the authentication tag */
283 *opaque_len += TAG_LEN;
284
285 #if DEBUG
286 printf("prot data len: %d\n", *opaque_len);
287 printf("prot data: %s\n", octet_string_hex_string(opaque, *opaque_len));
288 #endif
289 }
290
291 return err_status_ok;
292 }
293
294 err_status_t
aes_128_cbc_hmac_sha1_96_dec(void * key,const void * clear,unsigned clear_len,void * iv,void * opaque,unsigned * opaque_len)295 aes_128_cbc_hmac_sha1_96_dec(void *key,
296 const void *clear,
297 unsigned clear_len,
298 void *iv,
299 void *opaque,
300 unsigned *opaque_len) {
301 aes_cbc_ctx_t aes_ctx;
302 hmac_ctx_t hmac_ctx;
303 unsigned char enc_key[ENC_KEY_LEN];
304 unsigned char mac_key[MAC_KEY_LEN];
305 unsigned char tmp_tag[TAG_LEN];
306 unsigned char *auth_tag;
307 unsigned ciphertext_len;
308 err_status_t status;
309 int i;
310
311 /* check if we're doing authentication only */
312 if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
313
314 /* perform authentication only */
315
316 } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
317
318 /*
319 * bad parameter - we expect either all three pointers to be NULL,
320 * or none of those pointers to be NULL
321 */
322 return err_status_fail;
323
324 } else {
325 #if DEBUG
326 printf("DEC using key %s\n", octet_string_hex_string(key, KEY_LEN));
327 #endif
328
329 /* derive encryption and authentication keys from the input key */
330 status = hmac_init(&hmac_ctx, key, KEY_LEN);
331 if (status) return status;
332 status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key);
333 if (status) return status;
334
335 status = hmac_init(&hmac_ctx, key, KEY_LEN);
336 if (status) return status;
337 status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key);
338 if (status) return status;
339
340 #if DEBUG
341 printf("prot data len: %d\n", *opaque_len);
342 printf("prot data: %s\n", octet_string_hex_string(opaque, *opaque_len));
343 #endif
344
345 /*
346 * set the protected data length to that of the ciphertext, by
347 * subtracting out the length of the authentication tag
348 */
349 ciphertext_len = *opaque_len - TAG_LEN;
350
351 #if DEBUG
352 printf("ciphertext len: %d\n", ciphertext_len);
353 #endif
354 /* verify the authentication tag */
355
356 /*
357 * compute the authentication tag for the clear and opaque data,
358 * and write it to a temporary location
359 */
360 status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN);
361 if (status) return status;
362
363 status = hmac_start(&hmac_ctx);
364 if (status) return status;
365
366 status = hmac_update(&hmac_ctx, clear, clear_len);
367 if (status) return status;
368
369 #if DEBUG
370 printf("hmac input: %s\n",
371 octet_string_hex_string(clear, clear_len));
372 #endif
373
374 status = hmac_compute(&hmac_ctx, opaque, ciphertext_len, TAG_LEN, tmp_tag);
375 if (status) return status;
376
377 #if DEBUG
378 printf("hmac input: %s\n",
379 octet_string_hex_string(opaque, ciphertext_len));
380 #endif
381
382 /*
383 * compare the computed tag with the one provided as input (which
384 * immediately follows the ciphertext)
385 */
386 auth_tag = (unsigned char *)opaque;
387 auth_tag += ciphertext_len;
388 #if DEBUG
389 printf("auth_tag: %s\n", octet_string_hex_string(auth_tag, TAG_LEN));
390 printf("tmp_tag: %s\n", octet_string_hex_string(tmp_tag, TAG_LEN));
391 #endif
392 for (i=0; i < TAG_LEN; i++) {
393 if (tmp_tag[i] != auth_tag[i])
394 return err_status_auth_fail;
395 }
396
397 /* bump down the opaque_len to reflect the authentication tag */
398 *opaque_len -= TAG_LEN;
399
400 /* decrypt the confidential data */
401 status = aes_cbc_context_init(&aes_ctx, key, direction_decrypt);
402 if (status) return status;
403 status = aes_cbc_set_iv(&aes_ctx, iv);
404 if (status) return status;
405
406 #if DEBUG
407 printf("ciphertext: %s\n", octet_string_hex_string(opaque, *opaque_len));
408 printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN));
409 #endif
410
411 #if ENC
412 status = aes_cbc_nist_decrypt(&aes_ctx, opaque, &ciphertext_len);
413 if (status) return status;
414 #endif
415
416 #if DEBUG
417 printf("plaintext len: %d\n", ciphertext_len);
418 printf("plaintext: %s\n",
419 octet_string_hex_string(opaque, ciphertext_len));
420 #endif
421
422 /* indicate the length of the plaintext */
423 *opaque_len = ciphertext_len;
424 }
425
426 return err_status_ok;
427 }
428
429 cryptoalg_ctx_t cryptoalg_ctx = {
430 aes_128_cbc_hmac_sha1_96_enc,
431 aes_128_cbc_hmac_sha1_96_dec,
432 KEY_LEN,
433 IV_LEN,
434 TAG_LEN,
435 MAX_EXPAND,
436 };
437
438 cryptoalg_t cryptoalg = &cryptoalg_ctx;
439
440 #define NULL_TAG_LEN 12
441
442 err_status_t
null_enc(void * key,const void * clear,unsigned clear_len,void * iv,void * opaque,unsigned * opaque_len)443 null_enc(void *key,
444 const void *clear,
445 unsigned clear_len,
446 void *iv,
447 void *opaque,
448 unsigned *opaque_len) {
449 int i;
450 unsigned char *auth_tag;
451 unsigned char *init_vec = iv;
452
453 /* check if we're doing authentication only */
454 if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
455
456 /* perform authentication only */
457
458 } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
459
460 /*
461 * bad parameter - we expect either all three pointers to be NULL,
462 * or none of those pointers to be NULL
463 */
464 return err_status_fail;
465
466 } else {
467
468 #if DEBUG
469 printf("NULL ENC using key %s\n", octet_string_hex_string(key, KEY_LEN));
470 printf("NULL_TAG_LEN: %d\n", NULL_TAG_LEN);
471 printf("plaintext len: %d\n", *opaque_len);
472 #endif
473 for (i=0; i < IV_LEN; i++)
474 init_vec[i] = i + (i * 16);
475 #if DEBUG
476 printf("iv: %s\n",
477 octet_string_hex_string(iv, IV_LEN));
478 printf("plaintext: %s\n",
479 octet_string_hex_string(opaque, *opaque_len));
480 #endif
481 auth_tag = opaque;
482 auth_tag += *opaque_len;
483 for (i=0; i < NULL_TAG_LEN; i++)
484 auth_tag[i] = i + (i * 16);
485 *opaque_len += NULL_TAG_LEN;
486 #if DEBUG
487 printf("protected data len: %d\n", *opaque_len);
488 printf("protected data: %s\n",
489 octet_string_hex_string(opaque, *opaque_len));
490 #endif
491
492 }
493
494 return err_status_ok;
495 }
496
497 err_status_t
null_dec(void * key,const void * clear,unsigned clear_len,void * iv,void * opaque,unsigned * opaque_len)498 null_dec(void *key,
499 const void *clear,
500 unsigned clear_len,
501 void *iv,
502 void *opaque,
503 unsigned *opaque_len) {
504 unsigned char *auth_tag;
505
506 /* check if we're doing authentication only */
507 if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
508
509 /* perform authentication only */
510
511 } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
512
513 /*
514 * bad parameter - we expect either all three pointers to be NULL,
515 * or none of those pointers to be NULL
516 */
517 return err_status_fail;
518
519 } else {
520
521 #if DEBUG
522 printf("NULL DEC using key %s\n", octet_string_hex_string(key, KEY_LEN));
523
524 printf("protected data len: %d\n", *opaque_len);
525 printf("protected data: %s\n",
526 octet_string_hex_string(opaque, *opaque_len));
527 #endif
528 auth_tag = opaque;
529 auth_tag += (*opaque_len - NULL_TAG_LEN);
530 #if DEBUG
531 printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN));
532 #endif
533 *opaque_len -= NULL_TAG_LEN;
534 #if DEBUG
535 printf("plaintext len: %d\n", *opaque_len);
536 printf("plaintext: %s\n",
537 octet_string_hex_string(opaque, *opaque_len));
538 #endif
539 }
540
541 return err_status_ok;
542 }
543
544 cryptoalg_ctx_t null_cryptoalg_ctx = {
545 null_enc,
546 null_dec,
547 KEY_LEN,
548 IV_LEN,
549 NULL_TAG_LEN,
550 MAX_EXPAND,
551 };
552
553 cryptoalg_t null_cryptoalg = &null_cryptoalg_ctx;
554
555 int
cryptoalg_get_id(cryptoalg_t c)556 cryptoalg_get_id(cryptoalg_t c) {
557 if (c == cryptoalg)
558 return 1;
559 return 0;
560 }
561
562 cryptoalg_t
cryptoalg_find_by_id(int id)563 cryptoalg_find_by_id(int id) {
564 switch(id) {
565 case 1:
566 return cryptoalg;
567 default:
568 break;
569 }
570 return 0;
571 }
572