blob: 0655aca4f685742c73584763300bc0efa400892a [file] [log] [blame]
Benny Prijono8a0ab282008-01-23 20:17:42 +00001/*
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
22err_status_t
23aes_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
96err_status_t
97aes_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
Benny Prijono2c423752008-01-24 10:23:43 +0000179
180// eVC4 declares DEBUG
181#undef DEBUG
Benny Prijono8a0ab282008-01-23 20:17:42 +0000182
183#define DEBUG 0
184
185err_status_t
186aes_128_cbc_hmac_sha1_96_enc(void *key,
187 const void *clear,
188 unsigned clear_len,
189 void *iv,
190 void *opaque,
191 unsigned *opaque_len) {
192 aes_cbc_ctx_t aes_ctx;
193 hmac_ctx_t hmac_ctx;
194 unsigned char enc_key[ENC_KEY_LEN];
195 unsigned char mac_key[MAC_KEY_LEN];
196 unsigned char *auth_tag;
197 err_status_t status;
198
199 /* check if we're doing authentication only */
200 if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
201
202 /* perform authentication only */
203
204 } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
205
206 /*
207 * bad parameter - we expect either all three pointers to be NULL,
208 * or none of those pointers to be NULL
209 */
210 return err_status_fail;
211
212 } else {
213
214#if DEBUG
215 printf("ENC using key %s\n", octet_string_hex_string(key, KEY_LEN));
216#endif
217
218 /* derive encryption and authentication keys from the input key */
219 status = hmac_init(&hmac_ctx, key, KEY_LEN);
220 if (status) return status;
221 status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key);
222 if (status) return status;
223
224 status = hmac_init(&hmac_ctx, key, KEY_LEN);
225 if (status) return status;
226 status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key);
227 if (status) return status;
228
229
230 /* perform encryption and authentication */
231
232 /* set aes key */
233 status = aes_cbc_context_init(&aes_ctx, key, direction_encrypt);
234 if (status) return status;
235
236 /* set iv */
237 status = rand_source_get_octet_string(iv, IV_LEN);
238 if (status) return status;
239 status = aes_cbc_set_iv(&aes_ctx, iv);
240 if (status) return status;
241
242#if DEBUG
243 printf("plaintext len: %d\n", *opaque_len);
244 printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN));
245 printf("plaintext: %s\n", octet_string_hex_string(opaque, *opaque_len));
246#endif
247
248#if ENC
249 /* encrypt the opaque data */
250 status = aes_cbc_nist_encrypt(&aes_ctx, opaque, opaque_len);
251 if (status) return status;
252#endif
253
254#if DEBUG
255 printf("ciphertext len: %d\n", *opaque_len);
256 printf("ciphertext: %s\n", octet_string_hex_string(opaque, *opaque_len));
257#endif
258
259 /*
260 * authenticate clear and opaque data, then write the
261 * authentication tag to the location immediately following the
262 * ciphertext
263 */
264 status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN);
265 if (status) return status;
266
267 status = hmac_start(&hmac_ctx);
268 if (status) return status;
269
270 status = hmac_update(&hmac_ctx, clear, clear_len);
271 if (status) return status;
272#if DEBUG
273 printf("hmac input: %s\n",
274 octet_string_hex_string(clear, clear_len));
275#endif
276 auth_tag = (unsigned char *)opaque;
277 auth_tag += *opaque_len;
278 status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, auth_tag);
279 if (status) return status;
280#if DEBUG
281 printf("hmac input: %s\n",
282 octet_string_hex_string(opaque, *opaque_len));
283#endif
284 /* bump up the opaque_len to reflect the authentication tag */
285 *opaque_len += TAG_LEN;
286
287#if DEBUG
288 printf("prot data len: %d\n", *opaque_len);
289 printf("prot data: %s\n", octet_string_hex_string(opaque, *opaque_len));
290#endif
291 }
292
293 return err_status_ok;
294}
295
296err_status_t
297aes_128_cbc_hmac_sha1_96_dec(void *key,
298 const void *clear,
299 unsigned clear_len,
300 void *iv,
301 void *opaque,
302 unsigned *opaque_len) {
303 aes_cbc_ctx_t aes_ctx;
304 hmac_ctx_t hmac_ctx;
305 unsigned char enc_key[ENC_KEY_LEN];
306 unsigned char mac_key[MAC_KEY_LEN];
307 unsigned char tmp_tag[TAG_LEN];
308 unsigned char *auth_tag;
309 unsigned ciphertext_len;
310 err_status_t status;
311 int i;
312
313 /* check if we're doing authentication only */
314 if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
315
316 /* perform authentication only */
317
318 } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
319
320 /*
321 * bad parameter - we expect either all three pointers to be NULL,
322 * or none of those pointers to be NULL
323 */
324 return err_status_fail;
325
326 } else {
327#if DEBUG
328 printf("DEC using key %s\n", octet_string_hex_string(key, KEY_LEN));
329#endif
330
331 /* derive encryption and authentication keys from the input key */
332 status = hmac_init(&hmac_ctx, key, KEY_LEN);
333 if (status) return status;
334 status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key);
335 if (status) return status;
336
337 status = hmac_init(&hmac_ctx, key, KEY_LEN);
338 if (status) return status;
339 status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key);
340 if (status) return status;
341
342#if DEBUG
343 printf("prot data len: %d\n", *opaque_len);
344 printf("prot data: %s\n", octet_string_hex_string(opaque, *opaque_len));
345#endif
346
347 /*
348 * set the protected data length to that of the ciphertext, by
349 * subtracting out the length of the authentication tag
350 */
351 ciphertext_len = *opaque_len - TAG_LEN;
352
353#if DEBUG
354 printf("ciphertext len: %d\n", ciphertext_len);
355#endif
356 /* verify the authentication tag */
357
358 /*
359 * compute the authentication tag for the clear and opaque data,
360 * and write it to a temporary location
361 */
362 status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN);
363 if (status) return status;
364
365 status = hmac_start(&hmac_ctx);
366 if (status) return status;
367
368 status = hmac_update(&hmac_ctx, clear, clear_len);
369 if (status) return status;
370
371#if DEBUG
372 printf("hmac input: %s\n",
373 octet_string_hex_string(clear, clear_len));
374#endif
375
376 status = hmac_compute(&hmac_ctx, opaque, ciphertext_len, TAG_LEN, tmp_tag);
377 if (status) return status;
378
379#if DEBUG
380 printf("hmac input: %s\n",
381 octet_string_hex_string(opaque, ciphertext_len));
382#endif
383
384 /*
385 * compare the computed tag with the one provided as input (which
386 * immediately follows the ciphertext)
387 */
388 auth_tag = (unsigned char *)opaque;
389 auth_tag += ciphertext_len;
390#if DEBUG
391 printf("auth_tag: %s\n", octet_string_hex_string(auth_tag, TAG_LEN));
392 printf("tmp_tag: %s\n", octet_string_hex_string(tmp_tag, TAG_LEN));
393#endif
394 for (i=0; i < TAG_LEN; i++) {
395 if (tmp_tag[i] != auth_tag[i])
396 return err_status_auth_fail;
397 }
398
399 /* bump down the opaque_len to reflect the authentication tag */
400 *opaque_len -= TAG_LEN;
401
402 /* decrypt the confidential data */
403 status = aes_cbc_context_init(&aes_ctx, key, direction_decrypt);
404 if (status) return status;
405 status = aes_cbc_set_iv(&aes_ctx, iv);
406 if (status) return status;
407
408#if DEBUG
409 printf("ciphertext: %s\n", octet_string_hex_string(opaque, *opaque_len));
410 printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN));
411#endif
412
413#if ENC
414 status = aes_cbc_nist_decrypt(&aes_ctx, opaque, &ciphertext_len);
415 if (status) return status;
416#endif
417
418#if DEBUG
419 printf("plaintext len: %d\n", ciphertext_len);
420 printf("plaintext: %s\n",
421 octet_string_hex_string(opaque, ciphertext_len));
422#endif
423
424 /* indicate the length of the plaintext */
425 *opaque_len = ciphertext_len;
426 }
427
428 return err_status_ok;
429}
430
431cryptoalg_ctx_t cryptoalg_ctx = {
432 aes_128_cbc_hmac_sha1_96_enc,
433 aes_128_cbc_hmac_sha1_96_dec,
434 KEY_LEN,
435 IV_LEN,
436 TAG_LEN,
437 MAX_EXPAND,
438};
439
440cryptoalg_t cryptoalg = &cryptoalg_ctx;
441
442#define NULL_TAG_LEN 12
443
444err_status_t
445null_enc(void *key,
446 const void *clear,
447 unsigned clear_len,
448 void *iv,
449 void *opaque,
450 unsigned *opaque_len) {
451 int i;
452 unsigned char *auth_tag;
453 unsigned char *init_vec = iv;
454
455 /* check if we're doing authentication only */
456 if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
457
458 /* perform authentication only */
459
460 } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
461
462 /*
463 * bad parameter - we expect either all three pointers to be NULL,
464 * or none of those pointers to be NULL
465 */
466 return err_status_fail;
467
468 } else {
469
470#if DEBUG
471 printf("NULL ENC using key %s\n", octet_string_hex_string(key, KEY_LEN));
472 printf("NULL_TAG_LEN: %d\n", NULL_TAG_LEN);
473 printf("plaintext len: %d\n", *opaque_len);
474#endif
475 for (i=0; i < IV_LEN; i++)
476 init_vec[i] = i + (i * 16);
477#if DEBUG
478 printf("iv: %s\n",
479 octet_string_hex_string(iv, IV_LEN));
480 printf("plaintext: %s\n",
481 octet_string_hex_string(opaque, *opaque_len));
482#endif
483 auth_tag = opaque;
484 auth_tag += *opaque_len;
485 for (i=0; i < NULL_TAG_LEN; i++)
486 auth_tag[i] = i + (i * 16);
487 *opaque_len += NULL_TAG_LEN;
488#if DEBUG
489 printf("protected data len: %d\n", *opaque_len);
490 printf("protected data: %s\n",
491 octet_string_hex_string(opaque, *opaque_len));
492#endif
493
494 }
495
496 return err_status_ok;
497}
498
499err_status_t
500null_dec(void *key,
501 const void *clear,
502 unsigned clear_len,
503 void *iv,
504 void *opaque,
505 unsigned *opaque_len) {
506 unsigned char *auth_tag;
507
508 /* check if we're doing authentication only */
509 if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
510
511 /* perform authentication only */
512
513 } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
514
515 /*
516 * bad parameter - we expect either all three pointers to be NULL,
517 * or none of those pointers to be NULL
518 */
519 return err_status_fail;
520
521 } else {
522
523#if DEBUG
524 printf("NULL DEC using key %s\n", octet_string_hex_string(key, KEY_LEN));
525
526 printf("protected data len: %d\n", *opaque_len);
527 printf("protected data: %s\n",
528 octet_string_hex_string(opaque, *opaque_len));
529#endif
530 auth_tag = opaque;
531 auth_tag += (*opaque_len - NULL_TAG_LEN);
532#if DEBUG
533 printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN));
534#endif
535 *opaque_len -= NULL_TAG_LEN;
536#if DEBUG
537 printf("plaintext len: %d\n", *opaque_len);
538 printf("plaintext: %s\n",
539 octet_string_hex_string(opaque, *opaque_len));
540#endif
541 }
542
543 return err_status_ok;
544}
545
546cryptoalg_ctx_t null_cryptoalg_ctx = {
547 null_enc,
548 null_dec,
549 KEY_LEN,
550 IV_LEN,
551 NULL_TAG_LEN,
552 MAX_EXPAND,
553};
554
555cryptoalg_t null_cryptoalg = &null_cryptoalg_ctx;
556
557int
558cryptoalg_get_id(cryptoalg_t c) {
559 if (c == cryptoalg)
560 return 1;
561 return 0;
562}
563
564cryptoalg_t
565cryptoalg_find_by_id(int id) {
566 switch(id) {
567 case 1:
568 return cryptoalg;
569 default:
570 break;
571 }
572 return 0;
573}