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