xref: /dflybsd-src/crypto/libressl/crypto/evp/e_aes_cbc_hmac_sha1.c (revision 961e30ea7dc61d1112b778ea4981eac68129fb86)
1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: e_aes_cbc_hmac_sha1.c,v 1.16 2021/12/12 21:30:13 tb Exp $ */
2f5b1c8a1SJohn Marino /* ====================================================================
3f5b1c8a1SJohn Marino  * Copyright (c) 2011-2013 The OpenSSL Project.  All rights reserved.
4f5b1c8a1SJohn Marino  *
5f5b1c8a1SJohn Marino  * Redistribution and use in source and binary forms, with or without
6f5b1c8a1SJohn Marino  * modification, are permitted provided that the following conditions
7f5b1c8a1SJohn Marino  * are met:
8f5b1c8a1SJohn Marino  *
9f5b1c8a1SJohn Marino  * 1. Redistributions of source code must retain the above copyright
10f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer.
11f5b1c8a1SJohn Marino  *
12f5b1c8a1SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
13f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer in
14f5b1c8a1SJohn Marino  *    the documentation and/or other materials provided with the
15f5b1c8a1SJohn Marino  *    distribution.
16f5b1c8a1SJohn Marino  *
17f5b1c8a1SJohn Marino  * 3. All advertising materials mentioning features or use of this
18f5b1c8a1SJohn Marino  *    software must display the following acknowledgment:
19f5b1c8a1SJohn Marino  *    "This product includes software developed by the OpenSSL Project
20f5b1c8a1SJohn Marino  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
21f5b1c8a1SJohn Marino  *
22f5b1c8a1SJohn Marino  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23f5b1c8a1SJohn Marino  *    endorse or promote products derived from this software without
24f5b1c8a1SJohn Marino  *    prior written permission. For written permission, please contact
25f5b1c8a1SJohn Marino  *    licensing@OpenSSL.org.
26f5b1c8a1SJohn Marino  *
27f5b1c8a1SJohn Marino  * 5. Products derived from this software may not be called "OpenSSL"
28f5b1c8a1SJohn Marino  *    nor may "OpenSSL" appear in their names without prior written
29f5b1c8a1SJohn Marino  *    permission of the OpenSSL Project.
30f5b1c8a1SJohn Marino  *
31f5b1c8a1SJohn Marino  * 6. Redistributions of any form whatsoever must retain the following
32f5b1c8a1SJohn Marino  *    acknowledgment:
33f5b1c8a1SJohn Marino  *    "This product includes software developed by the OpenSSL Project
34f5b1c8a1SJohn Marino  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
35f5b1c8a1SJohn Marino  *
36f5b1c8a1SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37f5b1c8a1SJohn Marino  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38f5b1c8a1SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39f5b1c8a1SJohn Marino  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40f5b1c8a1SJohn Marino  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41f5b1c8a1SJohn Marino  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42f5b1c8a1SJohn Marino  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43f5b1c8a1SJohn Marino  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44f5b1c8a1SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45f5b1c8a1SJohn Marino  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46f5b1c8a1SJohn Marino  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47f5b1c8a1SJohn Marino  * OF THE POSSIBILITY OF SUCH DAMAGE.
48f5b1c8a1SJohn Marino  * ====================================================================
49f5b1c8a1SJohn Marino  */
50f5b1c8a1SJohn Marino 
51f5b1c8a1SJohn Marino #include <stdio.h>
52f5b1c8a1SJohn Marino #include <string.h>
53f5b1c8a1SJohn Marino 
54f5b1c8a1SJohn Marino #include <openssl/opensslconf.h>
55f5b1c8a1SJohn Marino 
56f5b1c8a1SJohn Marino #if !defined(OPENSSL_NO_AES) && !defined(OPENSSL_NO_SHA1)
57f5b1c8a1SJohn Marino 
58f5b1c8a1SJohn Marino #include <openssl/evp.h>
59f5b1c8a1SJohn Marino #include <openssl/objects.h>
60f5b1c8a1SJohn Marino #include <openssl/aes.h>
61f5b1c8a1SJohn Marino #include <openssl/sha.h>
62*de0e0e4dSAntonio Huete Jimenez 
63f5b1c8a1SJohn Marino #include "constant_time_locl.h"
64*de0e0e4dSAntonio Huete Jimenez #include "evp_locl.h"
65f5b1c8a1SJohn Marino 
66f5b1c8a1SJohn Marino #define TLS1_1_VERSION 0x0302
67f5b1c8a1SJohn Marino 
68f5b1c8a1SJohn Marino typedef struct {
69f5b1c8a1SJohn Marino 	AES_KEY		ks;
70f5b1c8a1SJohn Marino 	SHA_CTX		head, tail, md;
71f5b1c8a1SJohn Marino 	size_t		payload_length;	/* AAD length in decrypt case */
72f5b1c8a1SJohn Marino 	union {
73f5b1c8a1SJohn Marino 		unsigned int	tls_ver;
74f5b1c8a1SJohn Marino 		unsigned char	tls_aad[16];	/* 13 used */
75f5b1c8a1SJohn Marino 	} aux;
76f5b1c8a1SJohn Marino } EVP_AES_HMAC_SHA1;
77f5b1c8a1SJohn Marino 
78f5b1c8a1SJohn Marino #define NO_PAYLOAD_LENGTH	((size_t)-1)
79f5b1c8a1SJohn Marino 
80f5b1c8a1SJohn Marino #if	defined(AES_ASM) &&	( \
81f5b1c8a1SJohn Marino 	defined(__x86_64)	|| defined(__x86_64__)	|| \
82f5b1c8a1SJohn Marino 	defined(_M_AMD64)	|| defined(_M_X64)	|| \
83f5b1c8a1SJohn Marino 	defined(__INTEL__)	)
84f5b1c8a1SJohn Marino 
8572c33676SMaxim Ag #include "x86_arch.h"
8672c33676SMaxim Ag 
87f5b1c8a1SJohn Marino #if defined(__GNUC__) && __GNUC__>=2
88f5b1c8a1SJohn Marino # define BSWAP(x) ({ unsigned int r=(x); asm ("bswapl %0":"=r"(r):"0"(r)); r; })
89f5b1c8a1SJohn Marino #endif
90f5b1c8a1SJohn Marino 
91f5b1c8a1SJohn Marino int aesni_set_encrypt_key(const unsigned char *userKey, int bits, AES_KEY *key);
92f5b1c8a1SJohn Marino int aesni_set_decrypt_key(const unsigned char *userKey, int bits, AES_KEY *key);
93f5b1c8a1SJohn Marino 
94f5b1c8a1SJohn Marino void aesni_cbc_encrypt(const unsigned char *in, unsigned char *out,
95f5b1c8a1SJohn Marino     size_t length, const AES_KEY *key, unsigned char *ivec, int enc);
96f5b1c8a1SJohn Marino 
97f5b1c8a1SJohn Marino void aesni_cbc_sha1_enc (const void *inp, void *out, size_t blocks,
98f5b1c8a1SJohn Marino     const AES_KEY *key, unsigned char iv[16], SHA_CTX *ctx, const void *in0);
99f5b1c8a1SJohn Marino 
100f5b1c8a1SJohn Marino #define data(ctx) ((EVP_AES_HMAC_SHA1 *)(ctx)->cipher_data)
101f5b1c8a1SJohn Marino 
102f5b1c8a1SJohn Marino static int
aesni_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * inkey,const unsigned char * iv,int enc)103f5b1c8a1SJohn Marino aesni_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *inkey,
104f5b1c8a1SJohn Marino     const unsigned char *iv, int enc)
105f5b1c8a1SJohn Marino {
106f5b1c8a1SJohn Marino 	EVP_AES_HMAC_SHA1 *key = data(ctx);
107f5b1c8a1SJohn Marino 	int ret;
108f5b1c8a1SJohn Marino 
109f5b1c8a1SJohn Marino 	if (enc)
110f5b1c8a1SJohn Marino 		ret = aesni_set_encrypt_key(inkey, ctx->key_len * 8, &key->ks);
111f5b1c8a1SJohn Marino 	else
112f5b1c8a1SJohn Marino 		ret = aesni_set_decrypt_key(inkey, ctx->key_len * 8, &key->ks);
113f5b1c8a1SJohn Marino 
114f5b1c8a1SJohn Marino 	SHA1_Init(&key->head);	/* handy when benchmarking */
115f5b1c8a1SJohn Marino 	key->tail = key->head;
116f5b1c8a1SJohn Marino 	key->md = key->head;
117f5b1c8a1SJohn Marino 
118f5b1c8a1SJohn Marino 	key->payload_length = NO_PAYLOAD_LENGTH;
119f5b1c8a1SJohn Marino 
120f5b1c8a1SJohn Marino 	return ret < 0 ? 0 : 1;
121f5b1c8a1SJohn Marino }
122f5b1c8a1SJohn Marino 
123f5b1c8a1SJohn Marino #define	STITCHED_CALL
124f5b1c8a1SJohn Marino 
125f5b1c8a1SJohn Marino #if !defined(STITCHED_CALL)
126f5b1c8a1SJohn Marino #define	aes_off 0
127f5b1c8a1SJohn Marino #endif
128f5b1c8a1SJohn Marino 
129f5b1c8a1SJohn Marino void sha1_block_data_order (void *c, const void *p, size_t len);
130f5b1c8a1SJohn Marino 
131f5b1c8a1SJohn Marino static void
sha1_update(SHA_CTX * c,const void * data,size_t len)132f5b1c8a1SJohn Marino sha1_update(SHA_CTX *c, const void *data, size_t len)
133f5b1c8a1SJohn Marino {
134f5b1c8a1SJohn Marino 	const unsigned char *ptr = data;
135f5b1c8a1SJohn Marino 	size_t res;
136f5b1c8a1SJohn Marino 
137f5b1c8a1SJohn Marino 	if ((res = c->num)) {
138f5b1c8a1SJohn Marino 		res = SHA_CBLOCK - res;
139f5b1c8a1SJohn Marino 		if (len < res)
140f5b1c8a1SJohn Marino 			res = len;
141f5b1c8a1SJohn Marino 		SHA1_Update(c, ptr, res);
142f5b1c8a1SJohn Marino 		ptr += res;
143f5b1c8a1SJohn Marino 		len -= res;
144f5b1c8a1SJohn Marino 	}
145f5b1c8a1SJohn Marino 
146f5b1c8a1SJohn Marino 	res = len % SHA_CBLOCK;
147f5b1c8a1SJohn Marino 	len -= res;
148f5b1c8a1SJohn Marino 
149f5b1c8a1SJohn Marino 	if (len) {
150f5b1c8a1SJohn Marino 		sha1_block_data_order(c, ptr, len / SHA_CBLOCK);
151f5b1c8a1SJohn Marino 
152f5b1c8a1SJohn Marino 		ptr += len;
153f5b1c8a1SJohn Marino 		c->Nh += len >> 29;
154f5b1c8a1SJohn Marino 		c->Nl += len <<= 3;
155f5b1c8a1SJohn Marino 		if (c->Nl < (unsigned int)len)
156f5b1c8a1SJohn Marino 			c->Nh++;
157f5b1c8a1SJohn Marino 	}
158f5b1c8a1SJohn Marino 
159f5b1c8a1SJohn Marino 	if (res)
160f5b1c8a1SJohn Marino 		SHA1_Update(c, ptr, res);
161f5b1c8a1SJohn Marino }
162f5b1c8a1SJohn Marino 
163f5b1c8a1SJohn Marino #ifdef SHA1_Update
164f5b1c8a1SJohn Marino #undef SHA1_Update
165f5b1c8a1SJohn Marino #endif
166f5b1c8a1SJohn Marino #define SHA1_Update sha1_update
167f5b1c8a1SJohn Marino 
168f5b1c8a1SJohn Marino static int
aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)169f5b1c8a1SJohn Marino aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
170f5b1c8a1SJohn Marino     const unsigned char *in, size_t len)
171f5b1c8a1SJohn Marino {
172f5b1c8a1SJohn Marino 	EVP_AES_HMAC_SHA1 *key = data(ctx);
173f5b1c8a1SJohn Marino 	unsigned int l;
174f5b1c8a1SJohn Marino 	size_t plen = key->payload_length,
175f5b1c8a1SJohn Marino 	    iv = 0,		/* explicit IV in TLS 1.1 and later */
176f5b1c8a1SJohn Marino 	    sha_off = 0;
177f5b1c8a1SJohn Marino #if defined(STITCHED_CALL)
178f5b1c8a1SJohn Marino 	size_t aes_off = 0, blocks;
179f5b1c8a1SJohn Marino 
180f5b1c8a1SJohn Marino 	sha_off = SHA_CBLOCK - key->md.num;
181f5b1c8a1SJohn Marino #endif
182f5b1c8a1SJohn Marino 
183f5b1c8a1SJohn Marino 	key->payload_length = NO_PAYLOAD_LENGTH;
184f5b1c8a1SJohn Marino 
185f5b1c8a1SJohn Marino 	if (len % AES_BLOCK_SIZE)
186f5b1c8a1SJohn Marino 		return 0;
187f5b1c8a1SJohn Marino 
188f5b1c8a1SJohn Marino 	if (ctx->encrypt) {
189f5b1c8a1SJohn Marino 		if (plen == NO_PAYLOAD_LENGTH)
190f5b1c8a1SJohn Marino 			plen = len;
191f5b1c8a1SJohn Marino 		else if (len != ((plen + SHA_DIGEST_LENGTH + AES_BLOCK_SIZE) &
192f5b1c8a1SJohn Marino 		    -AES_BLOCK_SIZE))
193f5b1c8a1SJohn Marino 			return 0;
194f5b1c8a1SJohn Marino 		else if (key->aux.tls_ver >= TLS1_1_VERSION)
195f5b1c8a1SJohn Marino 			iv = AES_BLOCK_SIZE;
196f5b1c8a1SJohn Marino 
197f5b1c8a1SJohn Marino #if defined(STITCHED_CALL)
198f5b1c8a1SJohn Marino 		if (plen > (sha_off + iv) &&
199f5b1c8a1SJohn Marino 		    (blocks = (plen - (sha_off + iv)) / SHA_CBLOCK)) {
200f5b1c8a1SJohn Marino 			SHA1_Update(&key->md, in + iv, sha_off);
201f5b1c8a1SJohn Marino 
202f5b1c8a1SJohn Marino 			aesni_cbc_sha1_enc(in, out, blocks, &key->ks,
203f5b1c8a1SJohn Marino 			    ctx->iv, &key->md, in + iv + sha_off);
204f5b1c8a1SJohn Marino 			blocks *= SHA_CBLOCK;
205f5b1c8a1SJohn Marino 			aes_off += blocks;
206f5b1c8a1SJohn Marino 			sha_off += blocks;
207f5b1c8a1SJohn Marino 			key->md.Nh += blocks >> 29;
208f5b1c8a1SJohn Marino 			key->md.Nl += blocks <<= 3;
209f5b1c8a1SJohn Marino 			if (key->md.Nl < (unsigned int)blocks)
210f5b1c8a1SJohn Marino 				key->md.Nh++;
211f5b1c8a1SJohn Marino 		} else {
212f5b1c8a1SJohn Marino 			sha_off = 0;
213f5b1c8a1SJohn Marino 		}
214f5b1c8a1SJohn Marino #endif
215f5b1c8a1SJohn Marino 		sha_off += iv;
216f5b1c8a1SJohn Marino 		SHA1_Update(&key->md, in + sha_off, plen - sha_off);
217f5b1c8a1SJohn Marino 
218f5b1c8a1SJohn Marino 		if (plen != len) {	/* "TLS" mode of operation */
219f5b1c8a1SJohn Marino 			if (in != out)
220f5b1c8a1SJohn Marino 				memcpy(out + aes_off, in + aes_off,
221f5b1c8a1SJohn Marino 				    plen - aes_off);
222f5b1c8a1SJohn Marino 
223f5b1c8a1SJohn Marino 			/* calculate HMAC and append it to payload */
224f5b1c8a1SJohn Marino 			SHA1_Final(out + plen, &key->md);
225f5b1c8a1SJohn Marino 			key->md = key->tail;
226f5b1c8a1SJohn Marino 			SHA1_Update(&key->md, out + plen, SHA_DIGEST_LENGTH);
227f5b1c8a1SJohn Marino 			SHA1_Final(out + plen, &key->md);
228f5b1c8a1SJohn Marino 
229f5b1c8a1SJohn Marino 			/* pad the payload|hmac */
230f5b1c8a1SJohn Marino 			plen += SHA_DIGEST_LENGTH;
231f5b1c8a1SJohn Marino 			for (l = len - plen - 1; plen < len; plen++)
232f5b1c8a1SJohn Marino 				out[plen] = l;
233f5b1c8a1SJohn Marino 
234f5b1c8a1SJohn Marino 			/* encrypt HMAC|padding at once */
235f5b1c8a1SJohn Marino 			aesni_cbc_encrypt(out + aes_off, out + aes_off,
236f5b1c8a1SJohn Marino 			    len - aes_off, &key->ks, ctx->iv, 1);
237f5b1c8a1SJohn Marino 		} else {
238f5b1c8a1SJohn Marino 			aesni_cbc_encrypt(in + aes_off, out + aes_off,
239f5b1c8a1SJohn Marino 			    len - aes_off, &key->ks, ctx->iv, 1);
240f5b1c8a1SJohn Marino 		}
241f5b1c8a1SJohn Marino 	} else {
242f5b1c8a1SJohn Marino 		union {
243f5b1c8a1SJohn Marino 			unsigned int u[SHA_DIGEST_LENGTH/sizeof(unsigned int)];
244f5b1c8a1SJohn Marino 			unsigned char c[32 + SHA_DIGEST_LENGTH];
245f5b1c8a1SJohn Marino 		} mac, *pmac;
246f5b1c8a1SJohn Marino 
247f5b1c8a1SJohn Marino 		/* arrange cache line alignment */
248f5b1c8a1SJohn Marino 		pmac = (void *)(((size_t)mac.c + 31) & ((size_t)0 - 32));
249f5b1c8a1SJohn Marino 
250f5b1c8a1SJohn Marino 		/* decrypt HMAC|padding at once */
251f5b1c8a1SJohn Marino 		aesni_cbc_encrypt(in, out, len, &key->ks, ctx->iv, 0);
252f5b1c8a1SJohn Marino 
25372c33676SMaxim Ag 		if (plen == 0 || plen == NO_PAYLOAD_LENGTH) {
25472c33676SMaxim Ag 			SHA1_Update(&key->md, out, len);
25572c33676SMaxim Ag 		} else if (plen < 4) {
25672c33676SMaxim Ag 			return 0;
25772c33676SMaxim Ag 		} else {	/* "TLS" mode of operation */
258f5b1c8a1SJohn Marino 			size_t inp_len, mask, j, i;
259f5b1c8a1SJohn Marino 			unsigned int res, maxpad, pad, bitlen;
260f5b1c8a1SJohn Marino 			int ret = 1;
261f5b1c8a1SJohn Marino 			union {
262f5b1c8a1SJohn Marino 				unsigned int u[SHA_LBLOCK];
263f5b1c8a1SJohn Marino 				unsigned char c[SHA_CBLOCK];
264f5b1c8a1SJohn Marino 			}
265f5b1c8a1SJohn Marino 			*data = (void *)key->md.data;
266f5b1c8a1SJohn Marino 
267f5b1c8a1SJohn Marino 			if ((key->aux.tls_aad[plen - 4] << 8 |
268f5b1c8a1SJohn Marino 			    key->aux.tls_aad[plen - 3]) >= TLS1_1_VERSION)
269f5b1c8a1SJohn Marino 				iv = AES_BLOCK_SIZE;
270f5b1c8a1SJohn Marino 
271f5b1c8a1SJohn Marino 			if (len < (iv + SHA_DIGEST_LENGTH + 1))
272f5b1c8a1SJohn Marino 				return 0;
273f5b1c8a1SJohn Marino 
274f5b1c8a1SJohn Marino 			/* omit explicit iv */
275f5b1c8a1SJohn Marino 			out += iv;
276f5b1c8a1SJohn Marino 			len -= iv;
277f5b1c8a1SJohn Marino 
278f5b1c8a1SJohn Marino 			/* figure out payload length */
279f5b1c8a1SJohn Marino 			pad = out[len - 1];
280f5b1c8a1SJohn Marino 			maxpad = len - (SHA_DIGEST_LENGTH + 1);
281f5b1c8a1SJohn Marino 			maxpad |= (255 - maxpad) >> (sizeof(maxpad) * 8 - 8);
282f5b1c8a1SJohn Marino 			maxpad &= 255;
283f5b1c8a1SJohn Marino 
284f5b1c8a1SJohn Marino 			ret &= constant_time_ge(maxpad, pad);
285f5b1c8a1SJohn Marino 
286f5b1c8a1SJohn Marino 			inp_len = len - (SHA_DIGEST_LENGTH + pad + 1);
287f5b1c8a1SJohn Marino 			mask = (0 - ((inp_len - len) >>
288f5b1c8a1SJohn Marino 			    (sizeof(inp_len) * 8 - 1)));
289f5b1c8a1SJohn Marino 			inp_len &= mask;
290f5b1c8a1SJohn Marino 			ret &= (int)mask;
291f5b1c8a1SJohn Marino 
292f5b1c8a1SJohn Marino 			key->aux.tls_aad[plen - 2] = inp_len >> 8;
293f5b1c8a1SJohn Marino 			key->aux.tls_aad[plen - 1] = inp_len;
294f5b1c8a1SJohn Marino 
295f5b1c8a1SJohn Marino 			/* calculate HMAC */
296f5b1c8a1SJohn Marino 			key->md = key->head;
297f5b1c8a1SJohn Marino 			SHA1_Update(&key->md, key->aux.tls_aad, plen);
298f5b1c8a1SJohn Marino 
299f5b1c8a1SJohn Marino #if 1
300f5b1c8a1SJohn Marino 			len -= SHA_DIGEST_LENGTH;		/* amend mac */
301f5b1c8a1SJohn Marino 			if (len >= (256 + SHA_CBLOCK)) {
302f5b1c8a1SJohn Marino 				j = (len - (256 + SHA_CBLOCK)) &
303f5b1c8a1SJohn Marino 				    (0 - SHA_CBLOCK);
304f5b1c8a1SJohn Marino 				j += SHA_CBLOCK - key->md.num;
305f5b1c8a1SJohn Marino 				SHA1_Update(&key->md, out, j);
306f5b1c8a1SJohn Marino 				out += j;
307f5b1c8a1SJohn Marino 				len -= j;
308f5b1c8a1SJohn Marino 				inp_len -= j;
309f5b1c8a1SJohn Marino 			}
310f5b1c8a1SJohn Marino 
311f5b1c8a1SJohn Marino 			/* but pretend as if we hashed padded payload */
312f5b1c8a1SJohn Marino 			bitlen = key->md.Nl + (inp_len << 3);	/* at most 18 bits */
313f5b1c8a1SJohn Marino #ifdef BSWAP
314f5b1c8a1SJohn Marino 			bitlen = BSWAP(bitlen);
315f5b1c8a1SJohn Marino #else
316f5b1c8a1SJohn Marino 			mac.c[0] = 0;
317f5b1c8a1SJohn Marino 			mac.c[1] = (unsigned char)(bitlen >> 16);
318f5b1c8a1SJohn Marino 			mac.c[2] = (unsigned char)(bitlen >> 8);
319f5b1c8a1SJohn Marino 			mac.c[3] = (unsigned char)bitlen;
320f5b1c8a1SJohn Marino 			bitlen = mac.u[0];
321f5b1c8a1SJohn Marino #endif
322f5b1c8a1SJohn Marino 
323f5b1c8a1SJohn Marino 			pmac->u[0] = 0;
324f5b1c8a1SJohn Marino 			pmac->u[1] = 0;
325f5b1c8a1SJohn Marino 			pmac->u[2] = 0;
326f5b1c8a1SJohn Marino 			pmac->u[3] = 0;
327f5b1c8a1SJohn Marino 			pmac->u[4] = 0;
328f5b1c8a1SJohn Marino 
329f5b1c8a1SJohn Marino 			for (res = key->md.num, j = 0; j < len; j++) {
330f5b1c8a1SJohn Marino 				size_t c = out[j];
331f5b1c8a1SJohn Marino 				mask = (j - inp_len) >> (sizeof(j) * 8 - 8);
332f5b1c8a1SJohn Marino 				c &= mask;
333f5b1c8a1SJohn Marino 				c |= 0x80 & ~mask &
334f5b1c8a1SJohn Marino 				    ~((inp_len - j) >> (sizeof(j) * 8 - 8));
335f5b1c8a1SJohn Marino 				data->c[res++] = (unsigned char)c;
336f5b1c8a1SJohn Marino 
337f5b1c8a1SJohn Marino 				if (res != SHA_CBLOCK)
338f5b1c8a1SJohn Marino 					continue;
339f5b1c8a1SJohn Marino 
340f5b1c8a1SJohn Marino 				/* j is not incremented yet */
341f5b1c8a1SJohn Marino 				mask = 0 - ((inp_len + 7 - j) >>
342f5b1c8a1SJohn Marino 				    (sizeof(j) * 8 - 1));
343f5b1c8a1SJohn Marino 				data->u[SHA_LBLOCK - 1] |= bitlen&mask;
344f5b1c8a1SJohn Marino 				sha1_block_data_order(&key->md, data, 1);
345f5b1c8a1SJohn Marino 				mask &= 0 - ((j - inp_len - 72) >>
346f5b1c8a1SJohn Marino 				    (sizeof(j) * 8 - 1));
347f5b1c8a1SJohn Marino 				pmac->u[0] |= key->md.h0 & mask;
348f5b1c8a1SJohn Marino 				pmac->u[1] |= key->md.h1 & mask;
349f5b1c8a1SJohn Marino 				pmac->u[2] |= key->md.h2 & mask;
350f5b1c8a1SJohn Marino 				pmac->u[3] |= key->md.h3 & mask;
351f5b1c8a1SJohn Marino 				pmac->u[4] |= key->md.h4 & mask;
352f5b1c8a1SJohn Marino 				res = 0;
353f5b1c8a1SJohn Marino 			}
354f5b1c8a1SJohn Marino 
355f5b1c8a1SJohn Marino 			for (i = res; i < SHA_CBLOCK; i++, j++)
356f5b1c8a1SJohn Marino 				data->c[i] = 0;
357f5b1c8a1SJohn Marino 
358f5b1c8a1SJohn Marino 			if (res > SHA_CBLOCK - 8) {
359f5b1c8a1SJohn Marino 				mask = 0 - ((inp_len + 8 - j) >>
360f5b1c8a1SJohn Marino 				    (sizeof(j) * 8 - 1));
361f5b1c8a1SJohn Marino 				data->u[SHA_LBLOCK - 1] |= bitlen & mask;
362f5b1c8a1SJohn Marino 				sha1_block_data_order(&key->md, data, 1);
363f5b1c8a1SJohn Marino 				mask &= 0 - ((j - inp_len - 73) >>
364f5b1c8a1SJohn Marino 				    (sizeof(j) * 8 - 1));
365f5b1c8a1SJohn Marino 				pmac->u[0] |= key->md.h0 & mask;
366f5b1c8a1SJohn Marino 				pmac->u[1] |= key->md.h1 & mask;
367f5b1c8a1SJohn Marino 				pmac->u[2] |= key->md.h2 & mask;
368f5b1c8a1SJohn Marino 				pmac->u[3] |= key->md.h3 & mask;
369f5b1c8a1SJohn Marino 				pmac->u[4] |= key->md.h4 & mask;
370f5b1c8a1SJohn Marino 
371f5b1c8a1SJohn Marino 				memset(data, 0, SHA_CBLOCK);
372f5b1c8a1SJohn Marino 				j += 64;
373f5b1c8a1SJohn Marino 			}
374f5b1c8a1SJohn Marino 			data->u[SHA_LBLOCK - 1] = bitlen;
375f5b1c8a1SJohn Marino 			sha1_block_data_order(&key->md, data, 1);
376f5b1c8a1SJohn Marino 			mask = 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1));
377f5b1c8a1SJohn Marino 			pmac->u[0] |= key->md.h0 & mask;
378f5b1c8a1SJohn Marino 			pmac->u[1] |= key->md.h1 & mask;
379f5b1c8a1SJohn Marino 			pmac->u[2] |= key->md.h2 & mask;
380f5b1c8a1SJohn Marino 			pmac->u[3] |= key->md.h3 & mask;
381f5b1c8a1SJohn Marino 			pmac->u[4] |= key->md.h4 & mask;
382f5b1c8a1SJohn Marino 
383f5b1c8a1SJohn Marino #ifdef BSWAP
384f5b1c8a1SJohn Marino 			pmac->u[0] = BSWAP(pmac->u[0]);
385f5b1c8a1SJohn Marino 			pmac->u[1] = BSWAP(pmac->u[1]);
386f5b1c8a1SJohn Marino 			pmac->u[2] = BSWAP(pmac->u[2]);
387f5b1c8a1SJohn Marino 			pmac->u[3] = BSWAP(pmac->u[3]);
388f5b1c8a1SJohn Marino 			pmac->u[4] = BSWAP(pmac->u[4]);
389f5b1c8a1SJohn Marino #else
390f5b1c8a1SJohn Marino 			for (i = 0; i < 5; i++) {
391f5b1c8a1SJohn Marino 				res = pmac->u[i];
392f5b1c8a1SJohn Marino 				pmac->c[4 * i + 0] = (unsigned char)(res >> 24);
393f5b1c8a1SJohn Marino 				pmac->c[4 * i + 1] = (unsigned char)(res >> 16);
394f5b1c8a1SJohn Marino 				pmac->c[4 * i + 2] = (unsigned char)(res >> 8);
395f5b1c8a1SJohn Marino 				pmac->c[4 * i + 3] = (unsigned char)res;
396f5b1c8a1SJohn Marino 			}
397f5b1c8a1SJohn Marino #endif
398f5b1c8a1SJohn Marino 			len += SHA_DIGEST_LENGTH;
399f5b1c8a1SJohn Marino #else
400f5b1c8a1SJohn Marino 			SHA1_Update(&key->md, out, inp_len);
401f5b1c8a1SJohn Marino 			res = key->md.num;
402f5b1c8a1SJohn Marino 			SHA1_Final(pmac->c, &key->md);
403f5b1c8a1SJohn Marino 
404f5b1c8a1SJohn Marino 			{
405f5b1c8a1SJohn Marino 				unsigned int inp_blocks, pad_blocks;
406f5b1c8a1SJohn Marino 
407f5b1c8a1SJohn Marino 				/* but pretend as if we hashed padded payload */
408f5b1c8a1SJohn Marino 				inp_blocks = 1 + ((SHA_CBLOCK - 9 - res) >>
409f5b1c8a1SJohn Marino 				    (sizeof(res) * 8 - 1));
410f5b1c8a1SJohn Marino 				res += (unsigned int)(len - inp_len);
411f5b1c8a1SJohn Marino 				pad_blocks = res / SHA_CBLOCK;
412f5b1c8a1SJohn Marino 				res %= SHA_CBLOCK;
413f5b1c8a1SJohn Marino 				pad_blocks += 1 + ((SHA_CBLOCK - 9 - res) >>
414f5b1c8a1SJohn Marino 				    (sizeof(res) * 8 - 1));
415f5b1c8a1SJohn Marino 				for (; inp_blocks < pad_blocks; inp_blocks++)
416f5b1c8a1SJohn Marino 					sha1_block_data_order(&key->md,
417f5b1c8a1SJohn Marino 					    data, 1);
418f5b1c8a1SJohn Marino 			}
419f5b1c8a1SJohn Marino #endif
420f5b1c8a1SJohn Marino 			key->md = key->tail;
421f5b1c8a1SJohn Marino 			SHA1_Update(&key->md, pmac->c, SHA_DIGEST_LENGTH);
422f5b1c8a1SJohn Marino 			SHA1_Final(pmac->c, &key->md);
423f5b1c8a1SJohn Marino 
424f5b1c8a1SJohn Marino 			/* verify HMAC */
425f5b1c8a1SJohn Marino 			out += inp_len;
426f5b1c8a1SJohn Marino 			len -= inp_len;
427f5b1c8a1SJohn Marino #if 1
428f5b1c8a1SJohn Marino 			{
429f5b1c8a1SJohn Marino 				unsigned char *p =
430f5b1c8a1SJohn Marino 				    out + len - 1 - maxpad - SHA_DIGEST_LENGTH;
431f5b1c8a1SJohn Marino 				size_t off = out - p;
432f5b1c8a1SJohn Marino 				unsigned int c, cmask;
433f5b1c8a1SJohn Marino 
434f5b1c8a1SJohn Marino 				maxpad += SHA_DIGEST_LENGTH;
435f5b1c8a1SJohn Marino 				for (res = 0, i = 0, j = 0; j < maxpad; j++) {
436f5b1c8a1SJohn Marino 					c = p[j];
437f5b1c8a1SJohn Marino 					cmask = ((int)(j - off -
438f5b1c8a1SJohn Marino 					    SHA_DIGEST_LENGTH)) >>
439f5b1c8a1SJohn Marino 					    (sizeof(int) * 8 - 1);
440f5b1c8a1SJohn Marino 					res |= (c ^ pad) & ~cmask;	/* ... and padding */
441f5b1c8a1SJohn Marino 					cmask &= ((int)(off - 1 - j)) >>
442f5b1c8a1SJohn Marino 					    (sizeof(int) * 8 - 1);
443f5b1c8a1SJohn Marino 					res |= (c ^ pmac->c[i]) & cmask;
444f5b1c8a1SJohn Marino 					i += 1 & cmask;
445f5b1c8a1SJohn Marino 				}
446f5b1c8a1SJohn Marino 				maxpad -= SHA_DIGEST_LENGTH;
447f5b1c8a1SJohn Marino 
448f5b1c8a1SJohn Marino 				res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1));
449f5b1c8a1SJohn Marino 				ret &= (int)~res;
450f5b1c8a1SJohn Marino 			}
451f5b1c8a1SJohn Marino #else
452f5b1c8a1SJohn Marino 			for (res = 0, i = 0; i < SHA_DIGEST_LENGTH; i++)
453f5b1c8a1SJohn Marino 				res |= out[i] ^ pmac->c[i];
454f5b1c8a1SJohn Marino 			res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1));
455f5b1c8a1SJohn Marino 			ret &= (int)~res;
456f5b1c8a1SJohn Marino 
457f5b1c8a1SJohn Marino 			/* verify padding */
458f5b1c8a1SJohn Marino 			pad = (pad & ~res) | (maxpad & res);
459f5b1c8a1SJohn Marino 			out = out + len - 1 - pad;
460f5b1c8a1SJohn Marino 			for (res = 0, i = 0; i < pad; i++)
461f5b1c8a1SJohn Marino 				res |= out[i] ^ pad;
462f5b1c8a1SJohn Marino 
463f5b1c8a1SJohn Marino 			res = (0 - res) >> (sizeof(res) * 8 - 1);
464f5b1c8a1SJohn Marino 			ret &= (int)~res;
465f5b1c8a1SJohn Marino #endif
466f5b1c8a1SJohn Marino 			return ret;
467f5b1c8a1SJohn Marino 		}
468f5b1c8a1SJohn Marino 	}
469f5b1c8a1SJohn Marino 
470f5b1c8a1SJohn Marino 	return 1;
471f5b1c8a1SJohn Marino }
472f5b1c8a1SJohn Marino 
473f5b1c8a1SJohn Marino static int
aesni_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX * ctx,int type,int arg,void * ptr)474f5b1c8a1SJohn Marino aesni_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
475f5b1c8a1SJohn Marino {
476f5b1c8a1SJohn Marino 	EVP_AES_HMAC_SHA1 *key = data(ctx);
477f5b1c8a1SJohn Marino 
478f5b1c8a1SJohn Marino 	switch (type) {
479f5b1c8a1SJohn Marino 	case EVP_CTRL_AEAD_SET_MAC_KEY:
480f5b1c8a1SJohn Marino 		{
481f5b1c8a1SJohn Marino 			unsigned int  i;
482f5b1c8a1SJohn Marino 			unsigned char hmac_key[64];
483f5b1c8a1SJohn Marino 
484f5b1c8a1SJohn Marino 			memset(hmac_key, 0, sizeof(hmac_key));
485f5b1c8a1SJohn Marino 
486f5b1c8a1SJohn Marino 			if (arg > (int)sizeof(hmac_key)) {
487f5b1c8a1SJohn Marino 				SHA1_Init(&key->head);
488f5b1c8a1SJohn Marino 				SHA1_Update(&key->head, ptr, arg);
489f5b1c8a1SJohn Marino 				SHA1_Final(hmac_key, &key->head);
490f5b1c8a1SJohn Marino 			} else {
491f5b1c8a1SJohn Marino 				memcpy(hmac_key, ptr, arg);
492f5b1c8a1SJohn Marino 			}
493f5b1c8a1SJohn Marino 
494f5b1c8a1SJohn Marino 			for (i = 0; i < sizeof(hmac_key); i++)
495f5b1c8a1SJohn Marino 				hmac_key[i] ^= 0x36;		/* ipad */
496f5b1c8a1SJohn Marino 			SHA1_Init(&key->head);
497f5b1c8a1SJohn Marino 			SHA1_Update(&key->head, hmac_key, sizeof(hmac_key));
498f5b1c8a1SJohn Marino 
499f5b1c8a1SJohn Marino 			for (i = 0; i < sizeof(hmac_key); i++)
500f5b1c8a1SJohn Marino 				hmac_key[i] ^= 0x36 ^ 0x5c;	/* opad */
501f5b1c8a1SJohn Marino 			SHA1_Init(&key->tail);
502f5b1c8a1SJohn Marino 			SHA1_Update(&key->tail, hmac_key, sizeof(hmac_key));
503f5b1c8a1SJohn Marino 
504f5b1c8a1SJohn Marino 			explicit_bzero(hmac_key, sizeof(hmac_key));
505f5b1c8a1SJohn Marino 
506f5b1c8a1SJohn Marino 			return 1;
507f5b1c8a1SJohn Marino 		}
508f5b1c8a1SJohn Marino 	case EVP_CTRL_AEAD_TLS1_AAD:
509f5b1c8a1SJohn Marino 		{
510f5b1c8a1SJohn Marino 			unsigned char *p = ptr;
51172c33676SMaxim Ag 			unsigned int len;
51272c33676SMaxim Ag 
51372c33676SMaxim Ag 			/* RFC 5246, 6.2.3.3: additional data has length 13 */
51472c33676SMaxim Ag 			if (arg != 13)
51572c33676SMaxim Ag 				return -1;
51672c33676SMaxim Ag 
51772c33676SMaxim Ag 			len = p[arg - 2] << 8 | p[arg - 1];
518f5b1c8a1SJohn Marino 
519f5b1c8a1SJohn Marino 			if (ctx->encrypt) {
520f5b1c8a1SJohn Marino 				key->payload_length = len;
521f5b1c8a1SJohn Marino 				if ((key->aux.tls_ver = p[arg - 4] << 8 |
522f5b1c8a1SJohn Marino 				    p[arg - 3]) >= TLS1_1_VERSION) {
523f5b1c8a1SJohn Marino 					len -= AES_BLOCK_SIZE;
524f5b1c8a1SJohn Marino 					p[arg - 2] = len >> 8;
525f5b1c8a1SJohn Marino 					p[arg - 1] = len;
526f5b1c8a1SJohn Marino 				}
527f5b1c8a1SJohn Marino 				key->md = key->head;
528f5b1c8a1SJohn Marino 				SHA1_Update(&key->md, p, arg);
529f5b1c8a1SJohn Marino 
530f5b1c8a1SJohn Marino 				return (int)(((len + SHA_DIGEST_LENGTH +
531f5b1c8a1SJohn Marino 				    AES_BLOCK_SIZE) & -AES_BLOCK_SIZE) - len);
532f5b1c8a1SJohn Marino 			} else {
533f5b1c8a1SJohn Marino 				memcpy(key->aux.tls_aad, ptr, arg);
534f5b1c8a1SJohn Marino 				key->payload_length = arg;
535f5b1c8a1SJohn Marino 
536f5b1c8a1SJohn Marino 				return SHA_DIGEST_LENGTH;
537f5b1c8a1SJohn Marino 			}
538f5b1c8a1SJohn Marino 		}
539f5b1c8a1SJohn Marino 	default:
540f5b1c8a1SJohn Marino 		return -1;
541f5b1c8a1SJohn Marino 	}
542f5b1c8a1SJohn Marino }
543f5b1c8a1SJohn Marino 
544f5b1c8a1SJohn Marino static EVP_CIPHER aesni_128_cbc_hmac_sha1_cipher = {
545f5b1c8a1SJohn Marino #ifdef NID_aes_128_cbc_hmac_sha1
546f5b1c8a1SJohn Marino 	.nid = NID_aes_128_cbc_hmac_sha1,
547f5b1c8a1SJohn Marino #else
548f5b1c8a1SJohn Marino 	.nid = NID_undef,
549f5b1c8a1SJohn Marino #endif
550f5b1c8a1SJohn Marino 	.block_size = 16,
551f5b1c8a1SJohn Marino 	.key_len = 16,
552f5b1c8a1SJohn Marino 	.iv_len = 16,
553f5b1c8a1SJohn Marino 	.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 |
554f5b1c8a1SJohn Marino 	    EVP_CIPH_FLAG_AEAD_CIPHER,
555f5b1c8a1SJohn Marino 	.init = aesni_cbc_hmac_sha1_init_key,
556f5b1c8a1SJohn Marino 	.do_cipher = aesni_cbc_hmac_sha1_cipher,
557f5b1c8a1SJohn Marino 	.ctx_size = sizeof(EVP_AES_HMAC_SHA1),
558f5b1c8a1SJohn Marino 	.ctrl = aesni_cbc_hmac_sha1_ctrl
559f5b1c8a1SJohn Marino };
560f5b1c8a1SJohn Marino 
561f5b1c8a1SJohn Marino static EVP_CIPHER aesni_256_cbc_hmac_sha1_cipher = {
562f5b1c8a1SJohn Marino #ifdef NID_aes_256_cbc_hmac_sha1
563f5b1c8a1SJohn Marino 	.nid = NID_aes_256_cbc_hmac_sha1,
564f5b1c8a1SJohn Marino #else
565f5b1c8a1SJohn Marino 	.nid = NID_undef,
566f5b1c8a1SJohn Marino #endif
567f5b1c8a1SJohn Marino 	.block_size = 16,
568f5b1c8a1SJohn Marino 	.key_len = 32,
569f5b1c8a1SJohn Marino 	.iv_len = 16,
570f5b1c8a1SJohn Marino 	.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 |
571f5b1c8a1SJohn Marino 	    EVP_CIPH_FLAG_AEAD_CIPHER,
572f5b1c8a1SJohn Marino 	.init = aesni_cbc_hmac_sha1_init_key,
573f5b1c8a1SJohn Marino 	.do_cipher = aesni_cbc_hmac_sha1_cipher,
574f5b1c8a1SJohn Marino 	.ctx_size = sizeof(EVP_AES_HMAC_SHA1),
575f5b1c8a1SJohn Marino 	.ctrl = aesni_cbc_hmac_sha1_ctrl
576f5b1c8a1SJohn Marino };
577f5b1c8a1SJohn Marino 
578f5b1c8a1SJohn Marino const EVP_CIPHER *
EVP_aes_128_cbc_hmac_sha1(void)579f5b1c8a1SJohn Marino EVP_aes_128_cbc_hmac_sha1(void)
580f5b1c8a1SJohn Marino {
58172c33676SMaxim Ag 	return (OPENSSL_cpu_caps() & CPUCAP_MASK_AESNI) ?
582f5b1c8a1SJohn Marino 	    &aesni_128_cbc_hmac_sha1_cipher : NULL;
583f5b1c8a1SJohn Marino }
584f5b1c8a1SJohn Marino 
585f5b1c8a1SJohn Marino const EVP_CIPHER *
EVP_aes_256_cbc_hmac_sha1(void)586f5b1c8a1SJohn Marino EVP_aes_256_cbc_hmac_sha1(void)
587f5b1c8a1SJohn Marino {
58872c33676SMaxim Ag 	return (OPENSSL_cpu_caps() & CPUCAP_MASK_AESNI) ?
589f5b1c8a1SJohn Marino 	    &aesni_256_cbc_hmac_sha1_cipher : NULL;
590f5b1c8a1SJohn Marino }
591f5b1c8a1SJohn Marino #else
592f5b1c8a1SJohn Marino const EVP_CIPHER *
EVP_aes_128_cbc_hmac_sha1(void)593f5b1c8a1SJohn Marino EVP_aes_128_cbc_hmac_sha1(void)
594f5b1c8a1SJohn Marino {
595f5b1c8a1SJohn Marino 	return NULL;
596f5b1c8a1SJohn Marino }
597f5b1c8a1SJohn Marino 
598f5b1c8a1SJohn Marino const EVP_CIPHER *
EVP_aes_256_cbc_hmac_sha1(void)599f5b1c8a1SJohn Marino EVP_aes_256_cbc_hmac_sha1(void)
600f5b1c8a1SJohn Marino {
601f5b1c8a1SJohn Marino 	    return NULL;
602f5b1c8a1SJohn Marino }
603f5b1c8a1SJohn Marino #endif
604f5b1c8a1SJohn Marino #endif
605