LCOV - code coverage report
Current view: top level - evp - e_rc4_hmac_md5.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 2 92 2.2 %
Date: 2014-08-02 Functions: 1 4 25.0 %
Branches: 0 47 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* ====================================================================
       2                 :            :  * Copyright (c) 2011 The OpenSSL Project.  All rights reserved.
       3                 :            :  *
       4                 :            :  * Redistribution and use in source and binary forms, with or without
       5                 :            :  * modification, are permitted provided that the following conditions
       6                 :            :  * are met:
       7                 :            :  *
       8                 :            :  * 1. Redistributions of source code must retain the above copyright
       9                 :            :  *    notice, this list of conditions and the following disclaimer.
      10                 :            :  *
      11                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      12                 :            :  *    notice, this list of conditions and the following disclaimer in
      13                 :            :  *    the documentation and/or other materials provided with the
      14                 :            :  *    distribution.
      15                 :            :  *
      16                 :            :  * 3. All advertising materials mentioning features or use of this
      17                 :            :  *    software must display the following acknowledgment:
      18                 :            :  *    "This product includes software developed by the OpenSSL Project
      19                 :            :  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
      20                 :            :  *
      21                 :            :  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
      22                 :            :  *    endorse or promote products derived from this software without
      23                 :            :  *    prior written permission. For written permission, please contact
      24                 :            :  *    licensing@OpenSSL.org.
      25                 :            :  *
      26                 :            :  * 5. Products derived from this software may not be called "OpenSSL"
      27                 :            :  *    nor may "OpenSSL" appear in their names without prior written
      28                 :            :  *    permission of the OpenSSL Project.
      29                 :            :  *
      30                 :            :  * 6. Redistributions of any form whatsoever must retain the following
      31                 :            :  *    acknowledgment:
      32                 :            :  *    "This product includes software developed by the OpenSSL Project
      33                 :            :  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
      34                 :            :  *
      35                 :            :  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
      36                 :            :  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      37                 :            :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      38                 :            :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
      39                 :            :  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      40                 :            :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      41                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
      42                 :            :  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      43                 :            :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
      44                 :            :  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      45                 :            :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
      46                 :            :  * OF THE POSSIBILITY OF SUCH DAMAGE.
      47                 :            :  * ====================================================================
      48                 :            :  */
      49                 :            : 
      50                 :            : #include <openssl/opensslconf.h>
      51                 :            : 
      52                 :            : #include <stdio.h>
      53                 :            : #include <string.h>
      54                 :            : 
      55                 :            : #if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_MD5)
      56                 :            : 
      57                 :            : #include <openssl/evp.h>
      58                 :            : #include <openssl/objects.h>
      59                 :            : #include <openssl/rc4.h>
      60                 :            : #include <openssl/md5.h>
      61                 :            : 
      62                 :            : #ifndef EVP_CIPH_FLAG_AEAD_CIPHER
      63                 :            : #define EVP_CIPH_FLAG_AEAD_CIPHER       0x200000
      64                 :            : #define EVP_CTRL_AEAD_TLS1_AAD          0x16
      65                 :            : #define EVP_CTRL_AEAD_SET_MAC_KEY       0x17
      66                 :            : #endif
      67                 :            : 
      68                 :            : /* FIXME: surely this is available elsewhere? */
      69                 :            : #define EVP_RC4_KEY_SIZE                16
      70                 :            : 
      71                 :            : typedef struct
      72                 :            :     {
      73                 :            :     RC4_KEY             ks;
      74                 :            :     MD5_CTX             head,tail,md;
      75                 :            :     size_t              payload_length;
      76                 :            :     } EVP_RC4_HMAC_MD5;
      77                 :            : 
      78                 :            : #define NO_PAYLOAD_LENGTH       ((size_t)-1)
      79                 :            : 
      80                 :            : void rc4_md5_enc (RC4_KEY *key, const void *in0, void *out,
      81                 :            :                 MD5_CTX *ctx,const void *inp,size_t blocks);
      82                 :            : 
      83                 :            : #define data(ctx) ((EVP_RC4_HMAC_MD5 *)(ctx)->cipher_data)
      84                 :            : 
      85                 :          0 : static int rc4_hmac_md5_init_key(EVP_CIPHER_CTX *ctx,
      86                 :            :                         const unsigned char *inkey,
      87                 :            :                         const unsigned char *iv, int enc)
      88                 :            :         {
      89                 :          0 :         EVP_RC4_HMAC_MD5 *key = data(ctx);
      90                 :            : 
      91                 :          0 :         RC4_set_key(&key->ks,EVP_CIPHER_CTX_key_length(ctx),
      92                 :            :                     inkey);
      93                 :            : 
      94                 :          0 :         MD5_Init(&key->head);    /* handy when benchmarking */
      95                 :          0 :         key->tail = key->head;
      96                 :          0 :         key->md   = key->head;
      97                 :            : 
      98                 :          0 :         key->payload_length = NO_PAYLOAD_LENGTH;
      99                 :            : 
     100                 :          0 :         return 1;
     101                 :            :         }
     102                 :            : 
     103                 :            : #if     !defined(OPENSSL_NO_ASM) &&     ( \
     104                 :            :         defined(__x86_64)       || defined(__x86_64__)  || \
     105                 :            :         defined(_M_AMD64)       || defined(_M_X64)      || \
     106                 :            :         defined(__INTEL__)              )
     107                 :            : #define STITCHED_CALL
     108                 :            : #endif
     109                 :            : 
     110                 :            : #if !defined(STITCHED_CALL)
     111                 :            : #define rc4_off 0
     112                 :            : #define md5_off 0
     113                 :            : #endif
     114                 :            : 
     115                 :          0 : static int rc4_hmac_md5_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
     116                 :            :                       const unsigned char *in, size_t len)
     117                 :            :         {
     118                 :          0 :         EVP_RC4_HMAC_MD5 *key = data(ctx);
     119                 :            : #if defined(STITCHED_CALL)
     120                 :          0 :         size_t  rc4_off = 32-1-(key->ks.x&(32-1)),       /* 32 is $MOD from rc4_md5-x86_64.pl */
     121                 :          0 :                 md5_off = MD5_CBLOCK-key->md.num,
     122                 :            :                 blocks;
     123                 :            :         unsigned int l;
     124                 :            :         extern unsigned int OPENSSL_ia32cap_P[];
     125                 :            : #endif
     126                 :          0 :         size_t  plen = key->payload_length;
     127                 :            : 
     128 [ #  # ][ #  # ]:          0 :         if (plen!=NO_PAYLOAD_LENGTH && len!=(plen+MD5_DIGEST_LENGTH)) return 0;
     129                 :            : 
     130         [ #  # ]:          0 :         if (ctx->encrypt) {
     131         [ #  # ]:          0 :                 if (plen==NO_PAYLOAD_LENGTH) plen = len;
     132                 :            : #if defined(STITCHED_CALL)
     133                 :            :                 /* cipher has to "fall behind" */
     134         [ #  # ]:          0 :                 if (rc4_off>md5_off) md5_off+=MD5_CBLOCK;
     135                 :            : 
     136 [ #  # ][ #  # ]:          0 :                 if (plen>md5_off && (blocks=(plen-md5_off)/MD5_CBLOCK) &&
                 [ #  # ]
     137                 :          0 :                     (OPENSSL_ia32cap_P[0]&(1<<20))==0) {
     138                 :          0 :                         MD5_Update(&key->md,in,md5_off);
     139                 :          0 :                         RC4(&key->ks,rc4_off,in,out);
     140                 :            : 
     141                 :          0 :                         rc4_md5_enc(&key->ks,in+rc4_off,out+rc4_off,
     142                 :            :                                 &key->md,in+md5_off,blocks);
     143                 :          0 :                         blocks *= MD5_CBLOCK;
     144                 :          0 :                         rc4_off += blocks;
     145                 :          0 :                         md5_off += blocks;
     146                 :          0 :                         key->md.Nh += blocks>>29;
     147                 :          0 :                         key->md.Nl += blocks<<=3;
     148         [ #  # ]:          0 :                         if (key->md.Nl<(unsigned int)blocks) key->md.Nh++;
     149                 :            :                 } else {
     150                 :            :                         rc4_off = 0;
     151                 :            :                         md5_off = 0;
     152                 :            :                 }
     153                 :            : #endif
     154                 :          0 :                 MD5_Update(&key->md,in+md5_off,plen-md5_off);
     155                 :            : 
     156         [ #  # ]:          0 :                 if (plen!=len) {        /* "TLS" mode of operation */
     157         [ #  # ]:          0 :                         if (in!=out)
     158                 :          0 :                                 memcpy(out+rc4_off,in+rc4_off,plen-rc4_off);
     159                 :            : 
     160                 :            :                         /* calculate HMAC and append it to payload */
     161                 :          0 :                         MD5_Final(out+plen,&key->md);
     162                 :          0 :                         key->md = key->tail;
     163                 :          0 :                         MD5_Update(&key->md,out+plen,MD5_DIGEST_LENGTH);
     164                 :          0 :                         MD5_Final(out+plen,&key->md);
     165                 :            :                         /* encrypt HMAC at once */
     166                 :          0 :                         RC4(&key->ks,len-rc4_off,out+rc4_off,out+rc4_off);
     167                 :            :                 } else {
     168                 :          0 :                         RC4(&key->ks,len-rc4_off,in+rc4_off,out+rc4_off);
     169                 :            :                 }
     170                 :            :         } else {
     171                 :            :                 unsigned char mac[MD5_DIGEST_LENGTH];
     172                 :            : #if defined(STITCHED_CALL)
     173                 :            :                 /* digest has to "fall behind" */
     174         [ #  # ]:          0 :                 if (md5_off>rc4_off) rc4_off += 2*MD5_CBLOCK;
     175                 :          0 :                 else                    rc4_off += MD5_CBLOCK;
     176                 :            : 
     177 [ #  # ][ #  # ]:          0 :                 if (len>rc4_off && (blocks=(len-rc4_off)/MD5_CBLOCK) &&
                 [ #  # ]
     178                 :          0 :                     (OPENSSL_ia32cap_P[0]&(1<<20))==0) {
     179                 :          0 :                         RC4(&key->ks,rc4_off,in,out);
     180                 :          0 :                         MD5_Update(&key->md,out,md5_off);
     181                 :            : 
     182                 :          0 :                         rc4_md5_enc(&key->ks,in+rc4_off,out+rc4_off,
     183                 :            :                                 &key->md,out+md5_off,blocks);
     184                 :          0 :                         blocks *= MD5_CBLOCK;
     185                 :          0 :                         rc4_off += blocks;
     186                 :          0 :                         md5_off += blocks;
     187                 :          0 :                         l = (key->md.Nl+(blocks<<3))&0xffffffffU;
     188         [ #  # ]:          0 :                         if (l<key->md.Nl) key->md.Nh++;
     189                 :          0 :                         key->md.Nl  = l;
     190                 :          0 :                         key->md.Nh += blocks>>29;
     191                 :            :                 } else {
     192                 :            :                         md5_off=0;
     193                 :            :                         rc4_off=0;
     194                 :            :                 }
     195                 :            : #endif
     196                 :            :                 /* decrypt HMAC at once */
     197                 :          0 :                 RC4(&key->ks,len-rc4_off,in+rc4_off,out+rc4_off);
     198         [ #  # ]:          0 :                 if (plen!=NO_PAYLOAD_LENGTH) {  /* "TLS" mode of operation */
     199                 :          0 :                         MD5_Update(&key->md,out+md5_off,plen-md5_off);
     200                 :            : 
     201                 :            :                         /* calculate HMAC and verify it */
     202                 :          0 :                         MD5_Final(mac,&key->md);
     203                 :          0 :                         key->md = key->tail;
     204                 :          0 :                         MD5_Update(&key->md,mac,MD5_DIGEST_LENGTH);
     205                 :          0 :                         MD5_Final(mac,&key->md);
     206                 :            : 
     207         [ #  # ]:          0 :                         if (memcmp(out+plen,mac,MD5_DIGEST_LENGTH))
     208                 :          0 :                                 return 0;
     209                 :            :                 } else {
     210                 :          0 :                         MD5_Update(&key->md,out+md5_off,len-md5_off);
     211                 :            :                 }
     212                 :            :         }
     213                 :            : 
     214                 :          0 :         key->payload_length = NO_PAYLOAD_LENGTH;
     215                 :            : 
     216                 :          0 :         return 1;
     217                 :            :         }
     218                 :            : 
     219                 :          0 : static int rc4_hmac_md5_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
     220                 :            :         {
     221                 :          0 :         EVP_RC4_HMAC_MD5 *key = data(ctx);
     222                 :            : 
     223      [ #  #  # ]:          0 :         switch (type)
     224                 :            :                 {
     225                 :            :         case EVP_CTRL_AEAD_SET_MAC_KEY:
     226                 :            :                 {
     227                 :            :                 unsigned int  i;
     228                 :            :                 unsigned char hmac_key[64];
     229                 :            : 
     230                 :            :                 memset (hmac_key,0,sizeof(hmac_key));
     231                 :            : 
     232         [ #  # ]:          0 :                 if (arg > (int)sizeof(hmac_key)) {
     233                 :          0 :                         MD5_Init(&key->head);
     234                 :          0 :                         MD5_Update(&key->head,ptr,arg);
     235                 :          0 :                         MD5_Final(hmac_key,&key->head);
     236                 :            :                 } else {
     237                 :          0 :                         memcpy(hmac_key,ptr,arg);
     238                 :            :                 }
     239                 :            : 
     240         [ #  # ]:          0 :                 for (i=0;i<sizeof(hmac_key);i++)
     241                 :          0 :                         hmac_key[i] ^= 0x36;            /* ipad */
     242                 :          0 :                 MD5_Init(&key->head);
     243                 :          0 :                 MD5_Update(&key->head,hmac_key,sizeof(hmac_key));
     244                 :            : 
     245         [ #  # ]:          0 :                 for (i=0;i<sizeof(hmac_key);i++)
     246                 :          0 :                         hmac_key[i] ^= 0x36^0x5c;       /* opad */
     247                 :          0 :                 MD5_Init(&key->tail);
     248                 :          0 :                 MD5_Update(&key->tail,hmac_key,sizeof(hmac_key));
     249                 :            : 
     250                 :            :                 return 1;
     251                 :            :                 }
     252                 :            :         case EVP_CTRL_AEAD_TLS1_AAD:
     253                 :            :                 {
     254                 :          0 :                 unsigned char *p=ptr;
     255                 :          0 :                 unsigned int   len=p[arg-2]<<8|p[arg-1];
     256                 :            : 
     257         [ #  # ]:          0 :                 if (!ctx->encrypt)
     258                 :            :                         {
     259                 :          0 :                         len -= MD5_DIGEST_LENGTH;
     260                 :          0 :                         p[arg-2] = len>>8;
     261                 :          0 :                         p[arg-1] = len;
     262                 :            :                         }
     263                 :          0 :                 key->payload_length=len;
     264                 :          0 :                 key->md = key->head;
     265                 :          0 :                 MD5_Update(&key->md,p,arg);
     266                 :            : 
     267                 :          0 :                 return MD5_DIGEST_LENGTH;
     268                 :            :                 }
     269                 :            :         default:
     270                 :            :                 return -1;
     271                 :            :                 }
     272                 :            :         }
     273                 :            : 
     274                 :            : static EVP_CIPHER r4_hmac_md5_cipher=
     275                 :            :         {
     276                 :            : #ifdef NID_rc4_hmac_md5
     277                 :            :         NID_rc4_hmac_md5,
     278                 :            : #else
     279                 :            :         NID_undef,
     280                 :            : #endif
     281                 :            :         1,EVP_RC4_KEY_SIZE,0,
     282                 :            :         EVP_CIPH_STREAM_CIPHER|EVP_CIPH_VARIABLE_LENGTH|EVP_CIPH_FLAG_AEAD_CIPHER,
     283                 :            :         rc4_hmac_md5_init_key,
     284                 :            :         rc4_hmac_md5_cipher,
     285                 :            :         NULL,
     286                 :            :         sizeof(EVP_RC4_HMAC_MD5),
     287                 :            :         NULL,
     288                 :            :         NULL,
     289                 :            :         rc4_hmac_md5_ctrl,
     290                 :            :         NULL
     291                 :            :         };
     292                 :            : 
     293                 :       1695 : const EVP_CIPHER *EVP_rc4_hmac_md5(void)
     294                 :            :         {
     295                 :       1695 :         return(&r4_hmac_md5_cipher);
     296                 :            :         }
     297                 :            : #endif

Generated by: LCOV version 1.9