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