1 /*
2  * Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 #include "internal/deprecated.h"
10 #include "cipher_aes_cbc_hmac_sha_etm.h"
11 
12 #if !defined(AES_CBC_HMAC_SHA_ETM_CAPABLE)
ossl_cipher_capable_aes_cbc_hmac_sha1_etm(void)13 int ossl_cipher_capable_aes_cbc_hmac_sha1_etm(void)
14 {
15     return 0;
16 }
17 
ossl_prov_cipher_hw_aes_cbc_hmac_sha1_etm(void)18 const PROV_CIPHER_HW_AES_HMAC_SHA_ETM *ossl_prov_cipher_hw_aes_cbc_hmac_sha1_etm(void)
19 {
20     return NULL;
21 }
22 #else
23 void sha1_block_data_order(void *c, const void *p, size_t len);
24 
25 # if defined(__aarch64__)
26 int asm_aescbc_sha1_hmac(const uint8_t *csrc, uint8_t *cdst, uint64_t clen,
27                          uint8_t *dsrc, uint8_t *ddst, uint64_t dlen,
28                          CIPH_DIGEST *arg);
29 void asm_sha1_hmac_aescbc_dec(const uint8_t *csrc, uint8_t *cdst, uint64_t clen,
30                               const unsigned char *dsrc, uint8_t *ddst, size_t dlen,
31                               CIPH_DIGEST *arg);
32 #  define HWAES128_ENC_CBC_SHA1_ETM asm_aescbc_sha1_hmac
33 #  define HWAES128_DEC_CBC_SHA1_ETM asm_sha1_hmac_aescbc_dec
34 # endif
35 
ossl_cipher_capable_aes_cbc_hmac_sha1_etm(void)36 int ossl_cipher_capable_aes_cbc_hmac_sha1_etm(void)
37 {
38     return HWAES_CBC_HMAC_SHA1_ETM_CAPABLE;
39 }
40 
aes_cbc_hmac_sha1_init_key(PROV_CIPHER_CTX * vctx,const unsigned char * key,size_t keylen)41 static int aes_cbc_hmac_sha1_init_key(PROV_CIPHER_CTX *vctx,
42                                       const unsigned char *key, size_t keylen)
43 {
44     int ret;
45     PROV_AES_HMAC_SHA_ETM_CTX *ctx = (PROV_AES_HMAC_SHA_ETM_CTX *)vctx;
46     PROV_AES_HMAC_SHA1_ETM_CTX *sctx = (PROV_AES_HMAC_SHA1_ETM_CTX *)vctx;
47 
48     if (ctx->base.enc)
49         ret = aes_v8_set_encrypt_key(key, keylen * 8, &ctx->ks);
50     else
51         ret = aes_v8_set_decrypt_key(key, keylen * 8, &ctx->ks);
52 
53     SHA1_Init(&sctx->head);      /* handy when benchmarking */
54     sctx->tail = sctx->head;
55 
56     return ret < 0 ? 0 : 1;
57 }
58 
ciph_digest_arg_init(CIPH_DIGEST * arg,PROV_CIPHER_CTX * vctx)59 static void ciph_digest_arg_init(CIPH_DIGEST *arg, PROV_CIPHER_CTX *vctx)
60 {
61     PROV_AES_HMAC_SHA_ETM_CTX *ctx = (PROV_AES_HMAC_SHA_ETM_CTX *)vctx;
62     PROV_AES_HMAC_SHA1_ETM_CTX *sctx = (PROV_AES_HMAC_SHA1_ETM_CTX *)vctx;
63 
64     arg->cipher.key = (uint8_t *)&(ctx->ks);
65     arg->cipher.key_rounds = ctx->ks.rounds;
66     arg->cipher.iv = (uint8_t *)&(ctx->base.iv);
67     arg->digest.hmac.i_key_pad = (uint8_t *)&(sctx->head);
68     arg->digest.hmac.o_key_pad = (uint8_t *)&(sctx->tail);
69 }
70 
hwaes_cbc_hmac_sha1_etm(PROV_CIPHER_CTX * vctx,unsigned char * out,const unsigned char * in,size_t len)71 static int hwaes_cbc_hmac_sha1_etm(PROV_CIPHER_CTX *vctx,
72                                    unsigned char *out,
73                                    const unsigned char *in, size_t len)
74 {
75     PROV_AES_HMAC_SHA_ETM_CTX *ctx = (PROV_AES_HMAC_SHA_ETM_CTX *)vctx;
76     CIPH_DIGEST arg = {0};
77 
78     ciph_digest_arg_init(&arg, vctx);
79 
80     if (len % AES_BLOCK_SIZE) {
81         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH);
82         return 0;
83     }
84     if (ctx->base.enc) {
85         HWAES128_ENC_CBC_SHA1_ETM(in, out, len, out, ctx->tag, len, &arg);
86         return 1;
87     } else {
88         if (ctx->taglen == 0) {
89             ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_SET);
90             return 0;
91         }
92         HWAES128_DEC_CBC_SHA1_ETM(in, out, len, in, ctx->tag, len, &arg);
93         if (CRYPTO_memcmp(ctx->exp_tag, ctx->tag, ctx->taglen)) {
94             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG);
95             return 0;
96         }
97         return 1;
98     }
99 }
100 
sha1_update(SHA_CTX * c,const void * data,size_t len)101 static void sha1_update(SHA_CTX *c, const void *data, size_t len)
102 {
103     const unsigned char *ptr = data;
104     size_t res;
105 
106     if ((res = c->num)) {
107         res = SHA_CBLOCK - res;
108         if (len < res)
109             res = len;
110         SHA1_Update(c, ptr, res);
111         ptr += res;
112         len -= res;
113     }
114 
115     res = len % SHA_CBLOCK;
116     len -= res;
117 
118     if (len) {
119         sha1_block_data_order(c, ptr, len / SHA_CBLOCK);
120 
121         ptr += len;
122         c->Nh += len >> 29;
123         c->Nl += len <<= 3;
124         if (c->Nl < (unsigned int)len)
125             c->Nh++;
126     }
127 
128     if (res)
129         SHA1_Update(c, ptr, res);
130 }
131 
aes_cbc_hmac_sha1_set_mac_key(void * vctx,const unsigned char * mac,size_t len)132 static void aes_cbc_hmac_sha1_set_mac_key(void *vctx,
133                                           const unsigned char *mac, size_t len)
134 {
135     PROV_AES_HMAC_SHA1_ETM_CTX *ctx = (PROV_AES_HMAC_SHA1_ETM_CTX *)vctx;
136     unsigned int i;
137     unsigned char hmac_key[64];
138 
139     memset(hmac_key, 0, sizeof(hmac_key));
140 
141     if (len > (int)sizeof(hmac_key)) {
142         SHA1_Init(&ctx->head);
143         sha1_update(&ctx->head, mac, len);
144         SHA1_Final(hmac_key, &ctx->head);
145     } else {
146         memcpy(hmac_key, mac, len);
147     }
148 
149     for (i = 0; i < sizeof(hmac_key); i++)
150         hmac_key[i] ^= 0x36; /* ipad */
151     SHA1_Init(&ctx->head);
152     sha1_update(&ctx->head, hmac_key, sizeof(hmac_key));
153 
154     for (i = 0; i < sizeof(hmac_key); i++)
155         hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */
156     SHA1_Init(&ctx->tail);
157     sha1_update(&ctx->tail, hmac_key, sizeof(hmac_key));
158 
159     OPENSSL_cleanse(hmac_key, sizeof(hmac_key));
160 }
161 
aes_cbc_hmac_sha1_cipher(PROV_CIPHER_CTX * vctx,unsigned char * out,const unsigned char * in,size_t len)162 static int aes_cbc_hmac_sha1_cipher(PROV_CIPHER_CTX *vctx,
163                                     unsigned char *out,
164                                     const unsigned char *in, size_t len)
165 {
166     return hwaes_cbc_hmac_sha1_etm(vctx, out, in, len);
167 }
168 
169 static const PROV_CIPHER_HW_AES_HMAC_SHA_ETM cipher_hw_aes_hmac_sha1_etm = {
170     {
171         aes_cbc_hmac_sha1_init_key,
172         aes_cbc_hmac_sha1_cipher
173     },
174     aes_cbc_hmac_sha1_set_mac_key
175 };
176 
ossl_prov_cipher_hw_aes_cbc_hmac_sha1_etm(void)177 const PROV_CIPHER_HW_AES_HMAC_SHA_ETM *ossl_prov_cipher_hw_aes_cbc_hmac_sha1_etm(void)
178 {
179     return &cipher_hw_aes_hmac_sha1_etm;
180 }
181 #endif
182