netwerk/srtp/src/crypto/ae_xfm/xfm.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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  */
    45 #include "cryptoalg.h"
    46 #include "aes_cbc.h"
    47 #include "hmac.h"
    48 #include "crypto_kernel.h"   /* for crypto_get_random() */
    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
    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;
    71   /* check if we're doing authentication only */
    72   if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
    74       /* perform authentication only */
    76   } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
    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;
    84   } else {
    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;
    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;
    98     /* perform encryption and authentication */
   100     /* set aes key */
   101     status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_encrypt);
   102     if (status) return status;
   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);
   109     /* encrypt the opaque data  */
   110     status = aes_cbc_nist_encrypt(&aes_ctx, opaque, opaque_len);
   111     if (status) return status;
   113     /* authenticate clear and opaque data */
   114     status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN);
   115     if (status) return status;
   117     status = hmac_start(&hmac_ctx);
   118     if (status) return status;
   120     status = hmac_update(&hmac_ctx, clear, clear_len);
   121     if (status) return status;
   123     status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, auth_tag);
   124     if (status) return status;
   126   }
   128   return err_status_ok;
   129 }
   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;
   148   /* check if we're doing authentication only */
   149   if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
   151       /* perform authentication only */
   153   } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
   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;
   161   } else {
   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;
   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;
   174     /* perform encryption and authentication */
   176     /* set aes key */
   177     status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_decrypt);
   178     if (status) return status;
   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);
   185     /* encrypt the opaque data  */
   186     status = aes_cbc_nist_decrypt(&aes_ctx, opaque, opaque_len);
   187     if (status) return status;
   189     /* authenticate clear and opaque data */
   190     status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN);
   191     if (status) return status;
   193     status = hmac_start(&hmac_ctx);
   194     if (status) return status;
   196     status = hmac_update(&hmac_ctx, clear, clear_len);
   197     if (status) return status;
   199     status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, tmp_tag);
   200     if (status) return status;
   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; 
   207   }
   209   return err_status_ok;
   210 }
   213 #define ENC 1
   215 #define DEBUG 0
   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;
   231   /* check if we're doing authentication only */
   232   if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
   234       /* perform authentication only */
   236   } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
   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;
   244   } else {
   246 #if DEBUG
   247     printf("ENC using key %s\n", octet_string_hex_string(key, KEY_LEN));
   248 #endif
   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;
   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;
   262     /* perform encryption and authentication */
   264     /* set aes key */
   265     status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_encrypt);
   266     if (status) return status;
   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;
   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
   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
   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
   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;
   299     status = hmac_start(&hmac_ctx);
   300     if (status) return status;
   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;
   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   }
   325   return err_status_ok;
   326 }
   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;
   345   /* check if we're doing authentication only */
   346   if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
   348       /* perform authentication only */
   350   } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
   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;
   358   } else {
   359 #if DEBUG
   360     printf("DEC using key %s\n", octet_string_hex_string(key, KEY_LEN));
   361 #endif
   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;
   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;
   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
   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;
   385 #if DEBUG
   386     printf("ciphertext len: %d\n", ciphertext_len);
   387 #endif    
   388     /* verify the authentication tag */
   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;
   397     status = hmac_start(&hmac_ctx);
   398     if (status) return status;
   400     status = hmac_update(&hmac_ctx, clear, clear_len);
   401     if (status) return status;
   403 #if DEBUG
   404     printf("hmac input: %s\n", 
   405 	   octet_string_hex_string(clear, clear_len));
   406 #endif
   408     status = hmac_compute(&hmac_ctx, opaque, ciphertext_len, TAG_LEN, tmp_tag);
   409     if (status) return status;
   411 #if DEBUG
   412     printf("hmac input: %s\n", 
   413 	   octet_string_hex_string(opaque, ciphertext_len));
   414 #endif
   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     }
   431     /* bump down the opaque_len to reflect the authentication tag */
   432     *opaque_len -= TAG_LEN;
   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;
   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
   445 #if ENC
   446     status = aes_cbc_nist_decrypt(&aes_ctx, opaque, &ciphertext_len);
   447     if (status) return status;
   448 #endif
   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
   456     /* indicate the length of the plaintext  */
   457     *opaque_len = ciphertext_len;
   458   }
   460   return err_status_ok;
   461 }
   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 };
   472 cryptoalg_t cryptoalg = &cryptoalg_ctx;
   474 #define NULL_TAG_LEN 12
   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;
   487   /* check if we're doing authentication only */
   488   if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
   490       /* perform authentication only */
   492   } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
   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;
   500   } else {
   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
   526   }
   528   return err_status_ok;
   529 }
   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;
   540   /* check if we're doing authentication only */
   541   if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
   543       /* perform authentication only */
   545   } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
   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;
   553   } else {
   555 #if DEBUG
   556     printf("NULL DEC using key %s\n", octet_string_hex_string(key, KEY_LEN));
   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   }
   575   return err_status_ok;
   576 }
   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 };
   587 cryptoalg_t null_cryptoalg = &null_cryptoalg_ctx;
   589 int
   590 cryptoalg_get_id(cryptoalg_t c) {
   591   if (c == cryptoalg)
   592     return 1;
   593   return 0;
   594 }
   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 }

mercurial