12c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org/* ==================================================================== 22c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * Copyright (c) 2011 The OpenSSL Project. All rights reserved. 32c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 42c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * Redistribution and use in source and binary forms, with or without 52c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * modification, are permitted provided that the following conditions 62c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * are met: 72c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 82c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 1. Redistributions of source code must retain the above copyright 92c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * notice, this list of conditions and the following disclaimer. 102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 2. Redistributions in binary form must reproduce the above copyright 122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * notice, this list of conditions and the following disclaimer in 132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * the documentation and/or other materials provided with the 142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * distribution. 152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 3. All advertising materials mentioning features or use of this 172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * software must display the following acknowledgment: 182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * "This product includes software developed by the OpenSSL Project 192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * endorse or promote products derived from this software without 232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * prior written permission. For written permission, please contact 242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * licensing@OpenSSL.org. 252c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 262c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 5. Products derived from this software may not be called "OpenSSL" 272c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * nor may "OpenSSL" appear in their names without prior written 282c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * permission of the OpenSSL Project. 292c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 302c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 6. Redistributions of any form whatsoever must retain the following 312c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * acknowledgment: 322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * "This product includes software developed by the OpenSSL Project 332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 422c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 432c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 442c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * OF THE POSSIBILITY OF SUCH DAMAGE. 472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * ==================================================================== 482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org */ 492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#include <openssl/opensslconf.h> 512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#include <stdio.h> 532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#include <string.h> 542c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 552c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_MD5) 562c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 572c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#include <openssl/evp.h> 582c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#include <openssl/objects.h> 592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#include <openssl/rc4.h> 602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#include <openssl/md5.h> 612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifndef EVP_CIPH_FLAG_AEAD_CIPHER 632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#define EVP_CIPH_FLAG_AEAD_CIPHER 0x200000 642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#define EVP_CTRL_AEAD_TLS1_AAD 0x16 652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#define EVP_CTRL_AEAD_SET_MAC_KEY 0x17 662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif 672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org/* FIXME: surely this is available elsewhere? */ 692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#define EVP_RC4_KEY_SIZE 16 702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgtypedef struct 722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org { 732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org RC4_KEY ks; 742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_CTX head,tail,md; 752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org size_t payload_length; 762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } EVP_RC4_HMAC_MD5; 772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#define NO_PAYLOAD_LENGTH ((size_t)-1) 792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgvoid rc4_md5_enc (RC4_KEY *key, const void *in0, void *out, 812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_CTX *ctx,const void *inp,size_t blocks); 822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#define data(ctx) ((EVP_RC4_HMAC_MD5 *)(ctx)->cipher_data) 842c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 852c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic int rc4_hmac_md5_init_key(EVP_CIPHER_CTX *ctx, 862c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org const unsigned char *inkey, 872c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org const unsigned char *iv, int enc) 882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org { 892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org EVP_RC4_HMAC_MD5 *key = data(ctx); 902c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 912c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org RC4_set_key(&key->ks,EVP_CIPHER_CTX_key_length(ctx), 922c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org inkey); 932c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 942c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Init(&key->head); /* handy when benchmarking */ 952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org key->tail = key->head; 962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org key->md = key->head; 972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org key->payload_length = NO_PAYLOAD_LENGTH; 992c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1002c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org return 1; 1012c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 1022c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1032c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#if !defined(OPENSSL_NO_ASM) && ( \ 1042c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org defined(__x86_64) || defined(__x86_64__) || \ 1052c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org defined(_M_AMD64) || defined(_M_X64) || \ 1062c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org defined(__INTEL__) ) && \ 1072c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org !(defined(__APPLE__) && defined(__MACH__)) 1082c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#define STITCHED_CALL 1092c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif 1102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#if !defined(STITCHED_CALL) 1122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#define rc4_off 0 1132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#define md5_off 0 1142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif 1152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic int rc4_hmac_md5_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 1172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org const unsigned char *in, size_t len) 1182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org { 1192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org EVP_RC4_HMAC_MD5 *key = data(ctx); 1202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#if defined(STITCHED_CALL) 1212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org size_t rc4_off = 32-1-(key->ks.x&(32-1)), /* 32 is $MOD from rc4_md5-x86_64.pl */ 1222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org md5_off = MD5_CBLOCK-key->md.num, 1232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org blocks; 1242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org unsigned int l; 1252c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org extern unsigned int OPENSSL_ia32cap_P[]; 1262c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif 1272c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org size_t plen = key->payload_length; 1282c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1292c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (plen!=NO_PAYLOAD_LENGTH && len!=(plen+MD5_DIGEST_LENGTH)) return 0; 1302c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1312c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (ctx->encrypt) { 1322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (plen==NO_PAYLOAD_LENGTH) plen = len; 1332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#if defined(STITCHED_CALL) 1342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org /* cipher has to "fall behind" */ 1352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (rc4_off>md5_off) md5_off+=MD5_CBLOCK; 1362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (plen>md5_off && (blocks=(plen-md5_off)/MD5_CBLOCK) && 1382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (OPENSSL_ia32cap_P[0]&(1<<20))==0) { 1392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Update(&key->md,in,md5_off); 1402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org RC4(&key->ks,rc4_off,in,out); 1412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1422c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org rc4_md5_enc(&key->ks,in+rc4_off,out+rc4_off, 1432c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org &key->md,in+md5_off,blocks); 1442c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org blocks *= MD5_CBLOCK; 1452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org rc4_off += blocks; 1462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org md5_off += blocks; 1472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org key->md.Nh += blocks>>29; 1482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org key->md.Nl += blocks<<=3; 1492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (key->md.Nl<(unsigned int)blocks) key->md.Nh++; 1502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } else { 1512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org rc4_off = 0; 1522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org md5_off = 0; 1532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 1542c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif 1552c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Update(&key->md,in+md5_off,plen-md5_off); 1562c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1572c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (plen!=len) { /* "TLS" mode of operation */ 1582c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (in!=out) 1592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org memcpy(out+rc4_off,in+rc4_off,plen-rc4_off); 1602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org /* calculate HMAC and append it to payload */ 1622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Final(out+plen,&key->md); 1632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org key->md = key->tail; 1642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Update(&key->md,out+plen,MD5_DIGEST_LENGTH); 1652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Final(out+plen,&key->md); 1662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org /* encrypt HMAC at once */ 1672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org RC4(&key->ks,len-rc4_off,out+rc4_off,out+rc4_off); 1682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } else { 1692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org RC4(&key->ks,len-rc4_off,in+rc4_off,out+rc4_off); 1702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 1712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } else { 1722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org unsigned char mac[MD5_DIGEST_LENGTH]; 1732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#if defined(STITCHED_CALL) 1742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org /* digest has to "fall behind" */ 1752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (md5_off>rc4_off) rc4_off += 2*MD5_CBLOCK; 1762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org else rc4_off += MD5_CBLOCK; 1772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (len>rc4_off && (blocks=(len-rc4_off)/MD5_CBLOCK) && 1792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (OPENSSL_ia32cap_P[0]&(1<<20))==0) { 1802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org RC4(&key->ks,rc4_off,in,out); 1812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Update(&key->md,out,md5_off); 1822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org rc4_md5_enc(&key->ks,in+rc4_off,out+rc4_off, 1842c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org &key->md,out+md5_off,blocks); 1852c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org blocks *= MD5_CBLOCK; 1862c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org rc4_off += blocks; 1872c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org md5_off += blocks; 1882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org l = (key->md.Nl+(blocks<<3))&0xffffffffU; 1892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (l<key->md.Nl) key->md.Nh++; 1902c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org key->md.Nl = l; 1912c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org key->md.Nh += blocks>>29; 1922c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } else { 1932c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org md5_off=0; 1942c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org rc4_off=0; 1952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 1962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif 1972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org /* decrypt HMAC at once */ 1982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org RC4(&key->ks,len-rc4_off,in+rc4_off,out+rc4_off); 1992c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (plen!=NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */ 2002c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Update(&key->md,out+md5_off,plen-md5_off); 2012c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2022c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org /* calculate HMAC and verify it */ 2032c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Final(mac,&key->md); 2042c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org key->md = key->tail; 2052c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Update(&key->md,mac,MD5_DIGEST_LENGTH); 2062c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Final(mac,&key->md); 2072c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2082c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (memcmp(out+plen,mac,MD5_DIGEST_LENGTH)) 2092c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org return 0; 2102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } else { 2112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Update(&key->md,out+md5_off,len-md5_off); 2122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 2132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 2142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org key->payload_length = NO_PAYLOAD_LENGTH; 2162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org return 1; 2182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 2192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic int rc4_hmac_md5_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) 2212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org { 2222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org EVP_RC4_HMAC_MD5 *key = data(ctx); 2232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org switch (type) 2252c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org { 2262c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org case EVP_CTRL_AEAD_SET_MAC_KEY: 2272c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org { 2282c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org unsigned int i; 2292c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org unsigned char hmac_key[64]; 2302c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2312c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org memset (hmac_key,0,sizeof(hmac_key)); 2322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (arg > (int)sizeof(hmac_key)) { 2342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Init(&key->head); 2352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Update(&key->head,ptr,arg); 2362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Final(hmac_key,&key->head); 2372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } else { 2382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org memcpy(hmac_key,ptr,arg); 2392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 2402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org for (i=0;i<sizeof(hmac_key);i++) 2422c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org hmac_key[i] ^= 0x36; /* ipad */ 2432c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Init(&key->head); 2442c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Update(&key->head,hmac_key,sizeof(hmac_key)); 2452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org for (i=0;i<sizeof(hmac_key);i++) 2472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org hmac_key[i] ^= 0x36^0x5c; /* opad */ 2482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Init(&key->tail); 2492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Update(&key->tail,hmac_key,sizeof(hmac_key)); 2502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org return 1; 2522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 2532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org case EVP_CTRL_AEAD_TLS1_AAD: 2542c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org { 2552c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org unsigned char *p=ptr; 2562c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org unsigned int len=p[arg-2]<<8|p[arg-1]; 2572c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2582c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (!ctx->encrypt) 2592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org { 2602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org len -= MD5_DIGEST_LENGTH; 2612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org p[arg-2] = len>>8; 2622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org p[arg-1] = len; 2632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 2642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org key->payload_length=len; 2652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org key->md = key->head; 2662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org MD5_Update(&key->md,p,arg); 2672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org return MD5_DIGEST_LENGTH; 2692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 2702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org default: 2712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org return -1; 2722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 2732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 2742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic EVP_CIPHER r4_hmac_md5_cipher= 2762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org { 2772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef NID_rc4_hmac_md5 2782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org NID_rc4_hmac_md5, 2792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#else 2802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org NID_undef, 2812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif 2822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1,EVP_RC4_KEY_SIZE,0, 2832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org EVP_CIPH_STREAM_CIPHER|EVP_CIPH_VARIABLE_LENGTH|EVP_CIPH_FLAG_AEAD_CIPHER, 2842c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org rc4_hmac_md5_init_key, 2852c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org rc4_hmac_md5_cipher, 2862c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org NULL, 2872c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org sizeof(EVP_RC4_HMAC_MD5), 2882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org NULL, 2892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org NULL, 2902c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org rc4_hmac_md5_ctrl, 2912c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org NULL 2922c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org }; 2932c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2942c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgconst EVP_CIPHER *EVP_rc4_hmac_md5(void) 2952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org { 2962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org return(&r4_hmac_md5_cipher); 2972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 2982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif 299