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