1 /* ====================================================================
2 * Copyright (c) 2011 The OpenSSL Project. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
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
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/)"
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.
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.
30 * 6. Redistributions of any form whatsoever must retain the following
32 * "This product includes software developed by the OpenSSL Project
33 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
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 * ====================================================================
50 #include <openssl/opensslconf.h>
55 #if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_MD5)
57 # include <openssl/crypto.h>
58 # include <openssl/evp.h>
59 # include <openssl/objects.h>
60 # include <openssl/rc4.h>
61 # include <openssl/md5.h>
63 # ifndef EVP_CIPH_FLAG_AEAD_CIPHER
64 # define EVP_CIPH_FLAG_AEAD_CIPHER 0x200000
65 # define EVP_CTRL_AEAD_TLS1_AAD 0x16
66 # define EVP_CTRL_AEAD_SET_MAC_KEY 0x17
69 /* FIXME: surely this is available elsewhere? */
70 # define EVP_RC4_KEY_SIZE 16
74 MD5_CTX head
, tail
, md
;
75 size_t payload_length
;
78 # define NO_PAYLOAD_LENGTH ((size_t)-1)
80 void rc4_md5_enc(RC4_KEY
*key
, const void *in0
, void *out
,
81 MD5_CTX
*ctx
, const void *inp
, size_t blocks
);
83 # define data(ctx) ((EVP_RC4_HMAC_MD5 *)(ctx)->cipher_data)
85 static int rc4_hmac_md5_init_key(EVP_CIPHER_CTX
*ctx
,
86 const unsigned char *inkey
,
87 const unsigned char *iv
, int enc
)
89 EVP_RC4_HMAC_MD5
*key
= data(ctx
);
91 RC4_set_key(&key
->ks
, EVP_CIPHER_CTX_key_length(ctx
), inkey
);
93 MD5_Init(&key
->head
); /* handy when benchmarking */
94 key
->tail
= key
->head
;
97 key
->payload_length
= NO_PAYLOAD_LENGTH
;
102 # if defined(RC4_ASM) && defined(MD5_ASM) && ( \
103 defined(__x86_64) || defined(__x86_64__) || \
104 defined(_M_AMD64) || defined(_M_X64) || \
105 defined(__INTEL__) ) && \
106 !(defined(__APPLE__) && defined(__MACH__))
107 # define STITCHED_CALL
110 # if !defined(STITCHED_CALL)
115 static int rc4_hmac_md5_cipher(EVP_CIPHER_CTX
*ctx
, unsigned char *out
,
116 const unsigned char *in
, size_t len
)
118 EVP_RC4_HMAC_MD5
*key
= data(ctx
);
119 # if defined(STITCHED_CALL)
120 size_t rc4_off
= 32 - 1 - (key
->ks
.x
& (32 - 1)), /* 32 is $MOD from
121 * rc4_md5-x86_64.pl */
122 md5_off
= MD5_CBLOCK
- key
->md
.num
, blocks
;
124 extern unsigned int OPENSSL_ia32cap_P
[];
126 size_t plen
= key
->payload_length
;
128 if (plen
!= NO_PAYLOAD_LENGTH
&& len
!= (plen
+ MD5_DIGEST_LENGTH
))
132 if (plen
== NO_PAYLOAD_LENGTH
)
134 # if defined(STITCHED_CALL)
135 /* cipher has to "fall behind" */
136 if (rc4_off
> md5_off
)
137 md5_off
+= MD5_CBLOCK
;
139 if (plen
> md5_off
&& (blocks
= (plen
- md5_off
) / MD5_CBLOCK
) &&
140 (OPENSSL_ia32cap_P
[0] & (1 << 20)) == 0) {
141 MD5_Update(&key
->md
, in
, md5_off
);
142 RC4(&key
->ks
, rc4_off
, in
, out
);
144 rc4_md5_enc(&key
->ks
, in
+ rc4_off
, out
+ rc4_off
,
145 &key
->md
, in
+ md5_off
, blocks
);
146 blocks
*= MD5_CBLOCK
;
149 key
->md
.Nh
+= blocks
>> 29;
150 key
->md
.Nl
+= blocks
<<= 3;
151 if (key
->md
.Nl
< (unsigned int)blocks
)
158 MD5_Update(&key
->md
, in
+ md5_off
, plen
- md5_off
);
160 if (plen
!= len
) { /* "TLS" mode of operation */
162 memcpy(out
+ rc4_off
, in
+ rc4_off
, plen
- rc4_off
);
164 /* calculate HMAC and append it to payload */
165 MD5_Final(out
+ plen
, &key
->md
);
167 MD5_Update(&key
->md
, out
+ plen
, MD5_DIGEST_LENGTH
);
168 MD5_Final(out
+ plen
, &key
->md
);
169 /* encrypt HMAC at once */
170 RC4(&key
->ks
, len
- rc4_off
, out
+ rc4_off
, out
+ rc4_off
);
172 RC4(&key
->ks
, len
- rc4_off
, in
+ rc4_off
, out
+ rc4_off
);
175 unsigned char mac
[MD5_DIGEST_LENGTH
];
176 # if defined(STITCHED_CALL)
177 /* digest has to "fall behind" */
178 if (md5_off
> rc4_off
)
179 rc4_off
+= 2 * MD5_CBLOCK
;
181 rc4_off
+= MD5_CBLOCK
;
183 if (len
> rc4_off
&& (blocks
= (len
- rc4_off
) / MD5_CBLOCK
) &&
184 (OPENSSL_ia32cap_P
[0] & (1 << 20)) == 0) {
185 RC4(&key
->ks
, rc4_off
, in
, out
);
186 MD5_Update(&key
->md
, out
, md5_off
);
188 rc4_md5_enc(&key
->ks
, in
+ rc4_off
, out
+ rc4_off
,
189 &key
->md
, out
+ md5_off
, blocks
);
190 blocks
*= MD5_CBLOCK
;
193 l
= (key
->md
.Nl
+ (blocks
<< 3)) & 0xffffffffU
;
197 key
->md
.Nh
+= blocks
>> 29;
203 /* decrypt HMAC at once */
204 RC4(&key
->ks
, len
- rc4_off
, in
+ rc4_off
, out
+ rc4_off
);
205 if (plen
!= NO_PAYLOAD_LENGTH
) { /* "TLS" mode of operation */
206 MD5_Update(&key
->md
, out
+ md5_off
, plen
- md5_off
);
208 /* calculate HMAC and verify it */
209 MD5_Final(mac
, &key
->md
);
211 MD5_Update(&key
->md
, mac
, MD5_DIGEST_LENGTH
);
212 MD5_Final(mac
, &key
->md
);
214 if (CRYPTO_memcmp(out
+ plen
, mac
, MD5_DIGEST_LENGTH
))
217 MD5_Update(&key
->md
, out
+ md5_off
, len
- md5_off
);
221 key
->payload_length
= NO_PAYLOAD_LENGTH
;
226 static int rc4_hmac_md5_ctrl(EVP_CIPHER_CTX
*ctx
, int type
, int arg
,
229 EVP_RC4_HMAC_MD5
*key
= data(ctx
);
232 case EVP_CTRL_AEAD_SET_MAC_KEY
:
235 unsigned char hmac_key
[64];
237 memset(hmac_key
, 0, sizeof(hmac_key
));
239 if (arg
> (int)sizeof(hmac_key
)) {
240 MD5_Init(&key
->head
);
241 MD5_Update(&key
->head
, ptr
, arg
);
242 MD5_Final(hmac_key
, &key
->head
);
244 memcpy(hmac_key
, ptr
, arg
);
247 for (i
= 0; i
< sizeof(hmac_key
); i
++)
248 hmac_key
[i
] ^= 0x36; /* ipad */
249 MD5_Init(&key
->head
);
250 MD5_Update(&key
->head
, hmac_key
, sizeof(hmac_key
));
252 for (i
= 0; i
< sizeof(hmac_key
); i
++)
253 hmac_key
[i
] ^= 0x36 ^ 0x5c; /* opad */
254 MD5_Init(&key
->tail
);
255 MD5_Update(&key
->tail
, hmac_key
, sizeof(hmac_key
));
257 OPENSSL_cleanse(hmac_key
, sizeof(hmac_key
));
261 case EVP_CTRL_AEAD_TLS1_AAD
:
263 unsigned char *p
= ptr
;
266 if (arg
!= EVP_AEAD_TLS1_AAD_LEN
)
269 len
= p
[arg
- 2] << 8 | p
[arg
- 1];
272 if (len
< MD5_DIGEST_LENGTH
)
274 len
-= MD5_DIGEST_LENGTH
;
275 p
[arg
- 2] = len
>> 8;
278 key
->payload_length
= len
;
280 MD5_Update(&key
->md
, p
, arg
);
282 return MD5_DIGEST_LENGTH
;
289 static EVP_CIPHER r4_hmac_md5_cipher
= {
290 # ifdef NID_rc4_hmac_md5
295 1, EVP_RC4_KEY_SIZE
, 0,
296 EVP_CIPH_STREAM_CIPHER
| EVP_CIPH_VARIABLE_LENGTH
|
297 EVP_CIPH_FLAG_AEAD_CIPHER
,
298 rc4_hmac_md5_init_key
,
301 sizeof(EVP_RC4_HMAC_MD5
),
308 const EVP_CIPHER
*EVP_rc4_hmac_md5(void)
310 return (&r4_hmac_md5_cipher
);