VirtualBox

source: vbox/trunk/src/libs/openssl-3.4.1/crypto/hmac/hmac_s390x.c@ 109302

Last change on this file since 109302 was 109052, checked in by vboxsync, 4 weeks ago

openssl-3.4.1: Applied our changes, regenerated files, added missing files and functions. This time with a three way merge. ​bugref:10890

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.3 KB
Line 
1/*
2 * Copyright 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
10/* We need to use some engine deprecated APIs */
11#define OPENSSL_SUPPRESS_DEPRECATED
12
13#include "crypto/s390x_arch.h"
14#include "hmac_local.h"
15#include "openssl/obj_mac.h"
16#include "openssl/evp.h"
17#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
18# include <openssl/engine.h>
19#endif
20
21#ifdef OPENSSL_HMAC_S390X
22
23static int s390x_fc_from_md(const EVP_MD *md)
24{
25 int fc;
26
27 if (EVP_MD_is_a(md, "SHA2-224"))
28 fc = S390X_HMAC_SHA_224;
29 else if (EVP_MD_is_a(md, "SHA2-256"))
30 fc = S390X_HMAC_SHA_256;
31 else if (EVP_MD_is_a(md, "SHA2-384"))
32 fc = S390X_HMAC_SHA_384;
33 else if (EVP_MD_is_a(md, "SHA2-512"))
34 fc = S390X_HMAC_SHA_512;
35 else
36 return 0;
37
38 if ((OPENSSL_s390xcap_P.kmac[1] & S390X_CAPBIT(fc)) == 0)
39 return 0;
40
41 return fc;
42}
43
44static void s390x_call_kmac(HMAC_CTX *ctx, const unsigned char *in, size_t len)
45{
46 unsigned int fc = ctx->plat.s390x.fc;
47
48 if (ctx->plat.s390x.ikp)
49 fc |= S390X_KMAC_IKP;
50
51 if (ctx->plat.s390x.iimp)
52 fc |= S390X_KMAC_IIMP;
53
54 switch (ctx->plat.s390x.fc) {
55 case S390X_HMAC_SHA_224:
56 case S390X_HMAC_SHA_256:
57 ctx->plat.s390x.param.hmac_224_256.imbl += ((uint64_t)len * 8);
58 break;
59 case S390X_HMAC_SHA_384:
60 case S390X_HMAC_SHA_512:
61 ctx->plat.s390x.param.hmac_384_512.imbl += ((uint128_t)len * 8);
62 break;
63 default:
64 break;
65 }
66
67 s390x_kmac(in, len, fc, &ctx->plat.s390x.param);
68
69 ctx->plat.s390x.ikp = 1;
70}
71
72static int s390x_check_engine_used(const EVP_MD *md, ENGINE *impl)
73{
74# if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
75 const EVP_MD *d;
76
77 if (impl != NULL) {
78 if (!ENGINE_init(impl))
79 return 0;
80 } else {
81 impl = ENGINE_get_digest_engine(EVP_MD_get_type(md));
82 }
83
84 if (impl == NULL)
85 return 0;
86
87 d = ENGINE_get_digest(impl, EVP_MD_get_type(md));
88 ENGINE_finish(impl);
89
90 if (d != NULL)
91 return 1;
92# endif
93
94 return 0;
95}
96
97int s390x_HMAC_init(HMAC_CTX *ctx, const void *key, int key_len, ENGINE *impl)
98{
99 unsigned char *key_param;
100 unsigned int key_param_len;
101
102 ctx->plat.s390x.fc = s390x_fc_from_md(ctx->md);
103 if (ctx->plat.s390x.fc == 0)
104 return -1; /* Not supported by kmac instruction */
105
106 if (s390x_check_engine_used(ctx->md, impl)) {
107 ctx->plat.s390x.fc = 0;
108 return -1; /* An engine handles the digest, disable acceleration */
109 }
110
111 ctx->plat.s390x.blk_size = EVP_MD_get_block_size(ctx->md);
112 if (ctx->plat.s390x.blk_size < 0)
113 return 0;
114
115 if (ctx->plat.s390x.size !=
116 (size_t)(ctx->plat.s390x.blk_size * HMAC_S390X_BUF_NUM_BLOCKS)) {
117 OPENSSL_clear_free(ctx->plat.s390x.buf, ctx->plat.s390x.size);
118 ctx->plat.s390x.size = 0;
119 ctx->plat.s390x.buf = OPENSSL_zalloc(ctx->plat.s390x.blk_size *
120 HMAC_S390X_BUF_NUM_BLOCKS);
121 if (ctx->plat.s390x.buf == NULL)
122 return 0;
123 ctx->plat.s390x.size = ctx->plat.s390x.blk_size *
124 HMAC_S390X_BUF_NUM_BLOCKS;
125 }
126 ctx->plat.s390x.num = 0;
127
128 ctx->plat.s390x.ikp = 0;
129 ctx->plat.s390x.iimp = 1;
130
131 switch (ctx->plat.s390x.fc) {
132 case S390X_HMAC_SHA_224:
133 case S390X_HMAC_SHA_256:
134 ctx->plat.s390x.param.hmac_224_256.imbl = 0;
135 OPENSSL_cleanse(ctx->plat.s390x.param.hmac_224_256.h,
136 sizeof(ctx->plat.s390x.param.hmac_224_256.h));
137 break;
138 case S390X_HMAC_SHA_384:
139 case S390X_HMAC_SHA_512:
140 ctx->plat.s390x.param.hmac_384_512.imbl = 0;
141 OPENSSL_cleanse(ctx->plat.s390x.param.hmac_384_512.h,
142 sizeof(ctx->plat.s390x.param.hmac_384_512.h));
143 break;
144 default:
145 return 0;
146 }
147
148 if (key != NULL) {
149 switch (ctx->plat.s390x.fc) {
150 case S390X_HMAC_SHA_224:
151 case S390X_HMAC_SHA_256:
152 OPENSSL_cleanse(&ctx->plat.s390x.param.hmac_224_256.key,
153 sizeof(ctx->plat.s390x.param.hmac_224_256.key));
154 key_param = ctx->plat.s390x.param.hmac_224_256.key;
155 key_param_len = sizeof(ctx->plat.s390x.param.hmac_224_256.key);
156 break;
157 case S390X_HMAC_SHA_384:
158 case S390X_HMAC_SHA_512:
159 OPENSSL_cleanse(&ctx->plat.s390x.param.hmac_384_512.key,
160 sizeof(ctx->plat.s390x.param.hmac_384_512.key));
161 key_param = ctx->plat.s390x.param.hmac_384_512.key;
162 key_param_len = sizeof(ctx->plat.s390x.param.hmac_384_512.key);
163 break;
164 default:
165 return 0;
166 }
167
168 if (!ossl_assert(ctx->plat.s390x.blk_size <= (int)key_param_len))
169 return 0;
170
171 if (key_len > ctx->plat.s390x.blk_size) {
172 if (!EVP_DigestInit_ex(ctx->md_ctx, ctx->md, impl)
173 || !EVP_DigestUpdate(ctx->md_ctx, key, key_len)
174 || !EVP_DigestFinal_ex(ctx->md_ctx, key_param,
175 &key_param_len))
176 return 0;
177 } else {
178 if (key_len < 0 || key_len > (int)key_param_len)
179 return 0;
180 memcpy(key_param, key, key_len);
181 /* remaining key bytes already zeroed out above */
182 }
183 }
184
185 return 1;
186}
187
188int s390x_HMAC_update(HMAC_CTX *ctx, const unsigned char *data, size_t len)
189{
190 size_t remain, num;
191
192 if (len == 0)
193 return 1;
194
195 /* buffer is full, process it now */
196 if (ctx->plat.s390x.num == ctx->plat.s390x.size) {
197 s390x_call_kmac(ctx, ctx->plat.s390x.buf, ctx->plat.s390x.num);
198
199 ctx->plat.s390x.num = 0;
200 }
201
202 remain = ctx->plat.s390x.size - ctx->plat.s390x.num;
203 if (len > remain) {
204 /* data does not fit into buffer */
205 if (ctx->plat.s390x.num > 0) {
206 /* first fill buffer and process it */
207 memcpy(&ctx->plat.s390x.buf[ctx->plat.s390x.num], data, remain);
208 ctx->plat.s390x.num += remain;
209
210 s390x_call_kmac(ctx, ctx->plat.s390x.buf, ctx->plat.s390x.num);
211
212 ctx->plat.s390x.num = 0;
213
214 data += remain;
215 len -= remain;
216 }
217
218 if (!ossl_assert(ctx->plat.s390x.num == 0))
219 return 0;
220
221 if (len > ctx->plat.s390x.size) {
222 /*
223 * remaining data is still larger than buffer, process remaining
224 * full blocks of input directly
225 */
226 remain = len % ctx->plat.s390x.blk_size;
227 num = len - remain;
228
229 s390x_call_kmac(ctx, data, num);
230
231 data += num;
232 len -= num;
233 }
234 }
235
236 /* add remaining input data (which is < buffer size) to buffer */
237 if (!ossl_assert(len <= ctx->plat.s390x.size))
238 return 0;
239
240 if (len > 0) {
241 memcpy(&ctx->plat.s390x.buf[ctx->plat.s390x.num], data, len);
242 ctx->plat.s390x.num += len;
243 }
244
245 return 1;
246}
247
248int s390x_HMAC_final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len)
249{
250 void *result;
251 unsigned int res_len;
252
253 ctx->plat.s390x.iimp = 0; /* last block */
254 s390x_call_kmac(ctx, ctx->plat.s390x.buf, ctx->plat.s390x.num);
255
256 ctx->plat.s390x.num = 0;
257
258 switch (ctx->plat.s390x.fc) {
259 case S390X_HMAC_SHA_224:
260 result = &ctx->plat.s390x.param.hmac_224_256.h[0];
261 res_len = SHA224_DIGEST_LENGTH;
262 break;
263 case S390X_HMAC_SHA_256:
264 result = &ctx->plat.s390x.param.hmac_224_256.h[0];
265 res_len = SHA256_DIGEST_LENGTH;
266 break;
267 case S390X_HMAC_SHA_384:
268 result = &ctx->plat.s390x.param.hmac_384_512.h[0];
269 res_len = SHA384_DIGEST_LENGTH;
270 break;
271 case S390X_HMAC_SHA_512:
272 result = &ctx->plat.s390x.param.hmac_384_512.h[0];
273 res_len = SHA512_DIGEST_LENGTH;
274 break;
275 default:
276 return 0;
277 }
278
279 memcpy(md, result, res_len);
280 if (len != NULL)
281 *len = res_len;
282
283 return 1;
284}
285
286int s390x_HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx)
287{
288 dctx->plat.s390x.fc = sctx->plat.s390x.fc;
289 dctx->plat.s390x.blk_size = sctx->plat.s390x.blk_size;
290 dctx->plat.s390x.ikp = sctx->plat.s390x.ikp;
291 dctx->plat.s390x.iimp = sctx->plat.s390x.iimp;
292
293 memcpy(&dctx->plat.s390x.param, &sctx->plat.s390x.param,
294 sizeof(dctx->plat.s390x.param));
295
296 OPENSSL_clear_free(dctx->plat.s390x.buf, dctx->plat.s390x.size);
297 dctx->plat.s390x.buf = NULL;
298 if (sctx->plat.s390x.buf != NULL) {
299 dctx->plat.s390x.buf = OPENSSL_memdup(sctx->plat.s390x.buf,
300 sctx->plat.s390x.size);
301 if (dctx->plat.s390x.buf == NULL)
302 return 0;
303 }
304
305 dctx->plat.s390x.size = sctx->plat.s390x.size;
306 dctx->plat.s390x.num = sctx->plat.s390x.num;
307
308 return 1;
309}
310
311int s390x_HMAC_CTX_cleanup(HMAC_CTX *ctx)
312{
313 OPENSSL_clear_free(ctx->plat.s390x.buf, ctx->plat.s390x.size);
314 ctx->plat.s390x.buf = NULL;
315 ctx->plat.s390x.size = 0;
316 ctx->plat.s390x.num = 0;
317
318 OPENSSL_cleanse(&ctx->plat.s390x.param, sizeof(ctx->plat.s390x.param));
319
320 ctx->plat.s390x.blk_size = 0;
321 ctx->plat.s390x.ikp = 0;
322 ctx->plat.s390x.iimp = 1;
323
324 ctx->plat.s390x.fc = 0;
325
326 return 1;
327}
328
329#endif
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette