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