Home | History | Annotate | Download | only in ae_xfm
      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
     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
     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
    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
    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
    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
    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
    556 cryptoalg_get_id(cryptoalg_t c) {
    557   if (c == cryptoalg)
    558     return 1;
    559   return 0;
    560 }
    561 
    562 cryptoalg_t
    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