Coverage Report

Created: 2025-07-23 07:18

/src/gnutls/lib/accelerated/x86/hmac-padlock.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2008, 2010-2012 Free Software Foundation, Inc.
3
 *
4
 * Author: Nikos Mavrogiannopoulos
5
 *
6
 * This file is part of GNUTLS.
7
 *
8
 * The GNUTLS library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public License
10
 * as published by the Free Software Foundation; either version 2.1 of
11
 * the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
20
 *
21
 */
22
23
/* This file provides the backend hash/mac implementation for
24
 * VIA Padlock hardware acceleration.
25
 */
26
27
#include "gnutls_int.h"
28
#include "hash_int.h"
29
#include "errors.h"
30
#include <nettle/sha.h>
31
#include <nettle/hmac.h>
32
#include <nettle/macros.h>
33
#include <nettle/memxor.h>
34
#include "aes-padlock.h"
35
#include "sha-padlock.h"
36
#include "algorithms.h"
37
38
#ifdef HAVE_LIBNETTLE
39
40
0
#define IPAD 0x36
41
0
#define OPAD 0x5c
42
#define MAX_SHA_DIGEST_SIZE (512 / 8)
43
44
typedef void (*update_func)(void *, size_t, const uint8_t *);
45
typedef void (*digest_func)(void *, size_t, uint8_t *);
46
typedef void (*set_key_func)(void *, size_t, const uint8_t *);
47
48
struct padlock_hmac_ctx {
49
  union {
50
    struct hmac_sha224_ctx sha224;
51
    struct hmac_sha256_ctx sha256;
52
    struct hmac_sha384_ctx sha384;
53
    struct hmac_sha512_ctx sha512;
54
    struct hmac_sha1_ctx sha1;
55
  } ctx;
56
57
  void *ctx_ptr;
58
  gnutls_mac_algorithm_t algo;
59
  size_t length;
60
  update_func update;
61
  digest_func digest;
62
  set_key_func setkey;
63
};
64
65
static void padlock_hmac_sha1_set_key(struct hmac_sha1_ctx *ctx,
66
              size_t key_length, const uint8_t *key)
67
0
{
68
0
  HMAC_SET_KEY(ctx, &padlock_sha1, key_length, key);
69
0
}
70
71
static void padlock_hmac_sha1_update(struct hmac_sha1_ctx *ctx, size_t length,
72
             const uint8_t *data)
73
0
{
74
0
  padlock_sha1_update(&ctx->state, length, data);
75
0
}
76
77
static void padlock_hmac_sha1_digest(struct hmac_sha1_ctx *ctx, size_t length,
78
             uint8_t *digest)
79
0
{
80
0
  HMAC_DIGEST(ctx, &padlock_sha1, length, digest);
81
0
}
82
83
static void padlock_hmac_sha256_set_key(struct hmac_sha256_ctx *ctx,
84
          size_t key_length, const uint8_t *key)
85
0
{
86
0
  HMAC_SET_KEY(ctx, &padlock_sha256, key_length, key);
87
0
}
88
89
static void padlock_hmac_sha256_update(struct hmac_sha256_ctx *ctx,
90
               size_t length, const uint8_t *data)
91
0
{
92
0
  padlock_sha256_update(&ctx->state, length, data);
93
0
}
94
95
static void padlock_hmac_sha256_digest(struct hmac_sha256_ctx *ctx,
96
               size_t length, uint8_t *digest)
97
0
{
98
0
  HMAC_DIGEST(ctx, &padlock_sha256, length, digest);
99
0
}
100
101
static void padlock_hmac_sha224_set_key(struct hmac_sha224_ctx *ctx,
102
          size_t key_length, const uint8_t *key)
103
0
{
104
0
  HMAC_SET_KEY(ctx, &padlock_sha224, key_length, key);
105
0
}
106
107
static void padlock_hmac_sha224_digest(struct hmac_sha224_ctx *ctx,
108
               size_t length, uint8_t *digest)
109
0
{
110
0
  HMAC_DIGEST(ctx, &padlock_sha224, length, digest);
111
0
}
112
113
static void padlock_hmac_sha384_set_key(struct hmac_sha384_ctx *ctx,
114
          size_t key_length, const uint8_t *key)
115
0
{
116
0
  HMAC_SET_KEY(ctx, &padlock_sha384, key_length, key);
117
0
}
118
119
static void padlock_hmac_sha384_digest(struct hmac_sha384_ctx *ctx,
120
               size_t length, uint8_t *digest)
121
0
{
122
0
  HMAC_DIGEST(ctx, &padlock_sha384, length, digest);
123
0
}
124
125
static void padlock_hmac_sha512_set_key(struct hmac_sha512_ctx *ctx,
126
          size_t key_length, const uint8_t *key)
127
0
{
128
0
  HMAC_SET_KEY(ctx, &padlock_sha512, key_length, key);
129
0
}
130
131
static void padlock_hmac_sha512_update(struct hmac_sha512_ctx *ctx,
132
               size_t length, const uint8_t *data)
133
0
{
134
0
  padlock_sha512_update(&ctx->state, length, data);
135
0
}
136
137
static void padlock_hmac_sha512_digest(struct hmac_sha512_ctx *ctx,
138
               size_t length, uint8_t *digest)
139
0
{
140
0
  HMAC_DIGEST(ctx, &padlock_sha512, length, digest);
141
0
}
142
143
static int _hmac_ctx_init(gnutls_mac_algorithm_t algo,
144
        struct padlock_hmac_ctx *ctx)
145
0
{
146
0
  switch (algo) {
147
0
  case GNUTLS_MAC_SHA1:
148
0
    ctx->update = (update_func)padlock_hmac_sha1_update;
149
0
    ctx->digest = (digest_func)padlock_hmac_sha1_digest;
150
0
    ctx->setkey = (set_key_func)padlock_hmac_sha1_set_key;
151
0
    ctx->ctx_ptr = &ctx->ctx.sha1;
152
0
    ctx->length = SHA1_DIGEST_SIZE;
153
0
    break;
154
0
  case GNUTLS_MAC_SHA224:
155
0
    ctx->update = (update_func)padlock_hmac_sha256_update;
156
0
    ctx->digest = (digest_func)padlock_hmac_sha224_digest;
157
0
    ctx->setkey = (set_key_func)padlock_hmac_sha224_set_key;
158
0
    ctx->ctx_ptr = &ctx->ctx.sha224;
159
0
    ctx->length = SHA224_DIGEST_SIZE;
160
0
    break;
161
0
  case GNUTLS_MAC_SHA256:
162
0
    ctx->update = (update_func)padlock_hmac_sha256_update;
163
0
    ctx->digest = (digest_func)padlock_hmac_sha256_digest;
164
0
    ctx->setkey = (set_key_func)padlock_hmac_sha256_set_key;
165
0
    ctx->ctx_ptr = &ctx->ctx.sha256;
166
0
    ctx->length = SHA256_DIGEST_SIZE;
167
0
    break;
168
0
  case GNUTLS_MAC_SHA384:
169
0
    ctx->update = (update_func)padlock_hmac_sha512_update;
170
0
    ctx->digest = (digest_func)padlock_hmac_sha384_digest;
171
0
    ctx->setkey = (set_key_func)padlock_hmac_sha384_set_key;
172
0
    ctx->ctx_ptr = &ctx->ctx.sha384;
173
0
    ctx->length = SHA384_DIGEST_SIZE;
174
0
    break;
175
0
  case GNUTLS_MAC_SHA512:
176
0
    ctx->update = (update_func)padlock_hmac_sha512_update;
177
0
    ctx->digest = (digest_func)padlock_hmac_sha512_digest;
178
0
    ctx->setkey = (set_key_func)padlock_hmac_sha512_set_key;
179
0
    ctx->ctx_ptr = &ctx->ctx.sha512;
180
0
    ctx->length = SHA512_DIGEST_SIZE;
181
0
    break;
182
0
  default:
183
0
    gnutls_assert();
184
0
    return GNUTLS_E_INVALID_REQUEST;
185
0
  }
186
187
0
  return 0;
188
0
}
189
190
static int wrap_padlock_hmac_init(gnutls_mac_algorithm_t algo, void **_ctx)
191
0
{
192
0
  struct padlock_hmac_ctx *ctx;
193
0
  int ret;
194
195
0
  ctx = gnutls_calloc(1, sizeof(struct padlock_hmac_ctx));
196
0
  if (ctx == NULL) {
197
0
    gnutls_assert();
198
0
    return GNUTLS_E_MEMORY_ERROR;
199
0
  }
200
201
0
  ctx->algo = algo;
202
203
0
  ret = _hmac_ctx_init(algo, ctx);
204
0
  if (ret < 0) {
205
0
    gnutls_free(ctx);
206
0
    return gnutls_assert_val(ret);
207
0
  }
208
209
0
  *_ctx = ctx;
210
211
0
  return 0;
212
0
}
213
214
static void *wrap_padlock_hmac_copy(const void *_ctx)
215
0
{
216
0
  struct padlock_hmac_ctx *new_ctx;
217
0
  const struct padlock_hmac_ctx *ctx = _ctx;
218
0
  ptrdiff_t off = (uint8_t *)ctx->ctx_ptr - (uint8_t *)(&ctx->ctx);
219
220
0
  new_ctx = gnutls_malloc(sizeof(struct padlock_hmac_ctx));
221
0
  if (new_ctx == NULL) {
222
0
    gnutls_assert();
223
0
    return NULL;
224
0
  }
225
226
0
  memcpy(new_ctx, ctx, sizeof(*new_ctx));
227
0
  new_ctx->ctx_ptr = (uint8_t *)&new_ctx->ctx + off;
228
229
0
  return new_ctx;
230
0
}
231
232
static int wrap_padlock_hmac_setkey(void *_ctx, const void *key, size_t keylen)
233
0
{
234
0
  struct padlock_hmac_ctx *ctx = _ctx;
235
236
0
  ctx->setkey(ctx->ctx_ptr, keylen, key);
237
238
0
  return GNUTLS_E_SUCCESS;
239
0
}
240
241
static int wrap_padlock_hmac_update(void *_ctx, const void *text,
242
            size_t textsize)
243
0
{
244
0
  struct padlock_hmac_ctx *ctx = _ctx;
245
246
0
  ctx->update(ctx->ctx_ptr, textsize, text);
247
248
0
  return GNUTLS_E_SUCCESS;
249
0
}
250
251
static int wrap_padlock_hmac_output(void *src_ctx, void *digest,
252
            size_t digestsize)
253
0
{
254
0
  struct padlock_hmac_ctx *ctx;
255
0
  ctx = src_ctx;
256
257
0
  if (digestsize < ctx->length) {
258
0
    gnutls_assert();
259
0
    return GNUTLS_E_SHORT_MEMORY_BUFFER;
260
0
  }
261
262
0
  ctx->digest(ctx->ctx_ptr, digestsize, digest);
263
264
0
  return 0;
265
0
}
266
267
static void wrap_padlock_hmac_deinit(void *hd)
268
0
{
269
0
  struct padlock_hmac_ctx *ctx = hd;
270
271
0
  zeroize_temp_key(ctx, sizeof(*ctx));
272
0
  gnutls_free(ctx);
273
0
}
274
275
static int wrap_padlock_hmac_fast(gnutls_mac_algorithm_t algo,
276
          const void *nonce, size_t nonce_size,
277
          const void *key, size_t key_size,
278
          const void *text, size_t text_size,
279
          void *digest)
280
0
{
281
0
  if (algo == GNUTLS_MAC_SHA1 || algo == GNUTLS_MAC_SHA256) {
282
0
    unsigned char *pad;
283
0
    unsigned char pad2[SHA1_DATA_SIZE + MAX_SHA_DIGEST_SIZE];
284
0
    unsigned char hkey[MAX_SHA_DIGEST_SIZE];
285
0
    unsigned int digest_size =
286
0
      _gnutls_mac_get_algo_len(mac_to_entry(algo));
287
288
0
    if (key_size > SHA1_DATA_SIZE) {
289
0
      wrap_padlock_hash_fast((gnutls_digest_algorithm_t)algo,
290
0
                 key, key_size, hkey);
291
0
      key = hkey;
292
0
      key_size = digest_size;
293
0
    }
294
295
0
    pad = gnutls_malloc(text_size + SHA1_DATA_SIZE);
296
0
    if (pad == NULL)
297
0
      return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
298
299
0
    memset(pad, IPAD, SHA1_DATA_SIZE);
300
0
    memxor(pad, key, key_size);
301
302
0
    memcpy(&pad[SHA1_DATA_SIZE], text, text_size);
303
304
0
    wrap_padlock_hash_fast((gnutls_digest_algorithm_t)algo, pad,
305
0
               text_size + SHA1_DATA_SIZE,
306
0
               &pad2[SHA1_DATA_SIZE]);
307
308
0
    zeroize_temp_key(pad, text_size + SHA1_DATA_SIZE);
309
0
    gnutls_free(pad);
310
311
0
    memset(pad2, OPAD, SHA1_DATA_SIZE);
312
0
    memxor(pad2, key, key_size);
313
314
0
    wrap_padlock_hash_fast((gnutls_digest_algorithm_t)algo, pad2,
315
0
               digest_size + SHA1_DATA_SIZE, digest);
316
317
0
    zeroize_temp_key(pad2, sizeof(pad2));
318
0
    zeroize_temp_key(hkey, sizeof(hkey));
319
0
  } else {
320
0
    struct padlock_hmac_ctx ctx;
321
0
    int ret;
322
323
0
    ret = _hmac_ctx_init(algo, &ctx);
324
0
    if (ret < 0)
325
0
      return gnutls_assert_val(ret);
326
0
    ctx.algo = algo;
327
328
0
    wrap_padlock_hmac_setkey(&ctx, key, key_size);
329
330
0
    wrap_padlock_hmac_update(&ctx, text, text_size);
331
332
0
    wrap_padlock_hmac_output(&ctx, digest, ctx.length);
333
334
0
    zeroize_temp_key(&ctx, sizeof(ctx));
335
0
  }
336
337
0
  return 0;
338
0
}
339
340
const gnutls_crypto_mac_st _gnutls_hmac_sha_padlock_oneshot = {
341
  .init = NULL,
342
  .setkey = NULL,
343
  .setnonce = NULL,
344
  .hash = NULL,
345
  .output = NULL,
346
  .deinit = NULL,
347
  .fast = wrap_padlock_hmac_fast
348
};
349
350
const gnutls_crypto_mac_st _gnutls_hmac_sha_padlock = {
351
  .init = wrap_padlock_hmac_init,
352
  .setkey = wrap_padlock_hmac_setkey,
353
  .setnonce = NULL,
354
  .hash = wrap_padlock_hmac_update,
355
  .output = wrap_padlock_hmac_output,
356
  .copy = wrap_padlock_hmac_copy,
357
  .deinit = wrap_padlock_hmac_deinit,
358
  .fast = wrap_padlock_hmac_fast,
359
};
360
361
#endif /* HAVE_LIBNETTLE */