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