Coverage Report

Created: 2026-03-31 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnutls/lib/accelerated/x86/hmac-padlock.c
Line
Count
Source
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/sha1.h>
31
#include <nettle/sha2.h>
32
#include <nettle/hmac.h>
33
#include <nettle/macros.h>
34
#include <nettle/memxor.h>
35
#include "aes-padlock.h"
36
#include "sha-padlock.h"
37
#include "algorithms.h"
38
39
#if defined(HAVE_LIBNETTLE) && defined(HMAC_SET_KEY)
40
41
0
#define IPAD 0x36
42
0
#define OPAD 0x5c
43
#define MAX_SHA_DIGEST_SIZE (512 / 8)
44
45
typedef void (*update_func)(void *, size_t, const uint8_t *);
46
typedef void (*digest_func)(void *, size_t, uint8_t *);
47
typedef void (*set_key_func)(void *, size_t, const uint8_t *);
48
49
struct padlock_hmac_ctx {
50
  union {
51
    struct hmac_sha224_ctx sha224;
52
    struct hmac_sha256_ctx sha256;
53
    struct hmac_sha384_ctx sha384;
54
    struct hmac_sha512_ctx sha512;
55
    struct hmac_sha1_ctx sha1;
56
  } ctx;
57
58
  void *ctx_ptr;
59
  gnutls_mac_algorithm_t algo;
60
  size_t length;
61
  update_func update;
62
  digest_func digest;
63
  set_key_func setkey;
64
};
65
66
static void padlock_hmac_sha1_set_key(struct hmac_sha1_ctx *ctx,
67
              size_t key_length, const uint8_t *key)
68
0
{
69
0
  HMAC_SET_KEY(ctx, &padlock_sha1, key_length, key);
70
0
}
71
72
static void padlock_hmac_sha1_update(struct hmac_sha1_ctx *ctx, size_t length,
73
             const uint8_t *data)
74
0
{
75
0
  padlock_sha1_update(&ctx->state, length, data);
76
0
}
77
78
static void padlock_hmac_sha1_digest(struct hmac_sha1_ctx *ctx, size_t length,
79
             uint8_t *digest)
80
0
{
81
0
  HMAC_DIGEST(ctx, &padlock_sha1, length, digest);
82
0
}
83
84
static void padlock_hmac_sha256_set_key(struct hmac_sha256_ctx *ctx,
85
          size_t key_length, const uint8_t *key)
86
0
{
87
0
  HMAC_SET_KEY(ctx, &padlock_sha256, key_length, key);
88
0
}
89
90
static void padlock_hmac_sha256_update(struct hmac_sha256_ctx *ctx,
91
               size_t length, const uint8_t *data)
92
0
{
93
0
  padlock_sha256_update(&ctx->state, length, data);
94
0
}
95
96
static void padlock_hmac_sha256_digest(struct hmac_sha256_ctx *ctx,
97
               size_t length, uint8_t *digest)
98
0
{
99
0
  HMAC_DIGEST(ctx, &padlock_sha256, length, digest);
100
0
}
101
102
static void padlock_hmac_sha224_set_key(struct hmac_sha224_ctx *ctx,
103
          size_t key_length, const uint8_t *key)
104
0
{
105
0
  HMAC_SET_KEY(ctx, &padlock_sha224, key_length, key);
106
0
}
107
108
static void padlock_hmac_sha224_digest(struct hmac_sha224_ctx *ctx,
109
               size_t length, uint8_t *digest)
110
0
{
111
0
  HMAC_DIGEST(ctx, &padlock_sha224, length, digest);
112
0
}
113
114
static void padlock_hmac_sha384_set_key(struct hmac_sha384_ctx *ctx,
115
          size_t key_length, const uint8_t *key)
116
0
{
117
0
  HMAC_SET_KEY(ctx, &padlock_sha384, key_length, key);
118
0
}
119
120
static void padlock_hmac_sha384_digest(struct hmac_sha384_ctx *ctx,
121
               size_t length, uint8_t *digest)
122
0
{
123
0
  HMAC_DIGEST(ctx, &padlock_sha384, length, digest);
124
0
}
125
126
static void padlock_hmac_sha512_set_key(struct hmac_sha512_ctx *ctx,
127
          size_t key_length, const uint8_t *key)
128
0
{
129
0
  HMAC_SET_KEY(ctx, &padlock_sha512, key_length, key);
130
0
}
131
132
static void padlock_hmac_sha512_update(struct hmac_sha512_ctx *ctx,
133
               size_t length, const uint8_t *data)
134
0
{
135
0
  padlock_sha512_update(&ctx->state, length, data);
136
0
}
137
138
static void padlock_hmac_sha512_digest(struct hmac_sha512_ctx *ctx,
139
               size_t length, uint8_t *digest)
140
0
{
141
0
  HMAC_DIGEST(ctx, &padlock_sha512, length, digest);
142
0
}
143
144
static int _hmac_ctx_init(gnutls_mac_algorithm_t algo,
145
        struct padlock_hmac_ctx *ctx)
146
0
{
147
0
  switch (algo) {
148
0
  case GNUTLS_MAC_SHA1:
149
0
    ctx->update = (update_func)padlock_hmac_sha1_update;
150
0
    ctx->digest = (digest_func)padlock_hmac_sha1_digest;
151
0
    ctx->setkey = (set_key_func)padlock_hmac_sha1_set_key;
152
0
    ctx->ctx_ptr = &ctx->ctx.sha1;
153
0
    ctx->length = SHA1_DIGEST_SIZE;
154
0
    break;
155
0
  case GNUTLS_MAC_SHA224:
156
0
    ctx->update = (update_func)padlock_hmac_sha256_update;
157
0
    ctx->digest = (digest_func)padlock_hmac_sha224_digest;
158
0
    ctx->setkey = (set_key_func)padlock_hmac_sha224_set_key;
159
0
    ctx->ctx_ptr = &ctx->ctx.sha224;
160
0
    ctx->length = SHA224_DIGEST_SIZE;
161
0
    break;
162
0
  case GNUTLS_MAC_SHA256:
163
0
    ctx->update = (update_func)padlock_hmac_sha256_update;
164
0
    ctx->digest = (digest_func)padlock_hmac_sha256_digest;
165
0
    ctx->setkey = (set_key_func)padlock_hmac_sha256_set_key;
166
0
    ctx->ctx_ptr = &ctx->ctx.sha256;
167
0
    ctx->length = SHA256_DIGEST_SIZE;
168
0
    break;
169
0
  case GNUTLS_MAC_SHA384:
170
0
    ctx->update = (update_func)padlock_hmac_sha512_update;
171
0
    ctx->digest = (digest_func)padlock_hmac_sha384_digest;
172
0
    ctx->setkey = (set_key_func)padlock_hmac_sha384_set_key;
173
0
    ctx->ctx_ptr = &ctx->ctx.sha384;
174
0
    ctx->length = SHA384_DIGEST_SIZE;
175
0
    break;
176
0
  case GNUTLS_MAC_SHA512:
177
0
    ctx->update = (update_func)padlock_hmac_sha512_update;
178
0
    ctx->digest = (digest_func)padlock_hmac_sha512_digest;
179
0
    ctx->setkey = (set_key_func)padlock_hmac_sha512_set_key;
180
0
    ctx->ctx_ptr = &ctx->ctx.sha512;
181
0
    ctx->length = SHA512_DIGEST_SIZE;
182
0
    break;
183
0
  default:
184
0
    gnutls_assert();
185
0
    return GNUTLS_E_INVALID_REQUEST;
186
0
  }
187
188
0
  return 0;
189
0
}
190
191
static int wrap_padlock_hmac_init(gnutls_mac_algorithm_t algo, void **_ctx)
192
0
{
193
0
  struct padlock_hmac_ctx *ctx;
194
0
  int ret;
195
196
0
  ctx = gnutls_calloc(1, sizeof(struct padlock_hmac_ctx));
197
0
  if (ctx == NULL) {
198
0
    gnutls_assert();
199
0
    return GNUTLS_E_MEMORY_ERROR;
200
0
  }
201
202
0
  ctx->algo = algo;
203
204
0
  ret = _hmac_ctx_init(algo, ctx);
205
0
  if (ret < 0) {
206
0
    gnutls_free(ctx);
207
0
    return gnutls_assert_val(ret);
208
0
  }
209
210
0
  *_ctx = ctx;
211
212
0
  return 0;
213
0
}
214
215
static void *wrap_padlock_hmac_copy(const void *_ctx)
216
0
{
217
0
  struct padlock_hmac_ctx *new_ctx;
218
0
  const struct padlock_hmac_ctx *ctx = _ctx;
219
0
  ptrdiff_t off = (uint8_t *)ctx->ctx_ptr - (uint8_t *)(&ctx->ctx);
220
221
0
  new_ctx = gnutls_malloc(sizeof(struct padlock_hmac_ctx));
222
0
  if (new_ctx == NULL) {
223
0
    gnutls_assert();
224
0
    return NULL;
225
0
  }
226
227
0
  memcpy(new_ctx, ctx, sizeof(*new_ctx));
228
0
  new_ctx->ctx_ptr = (uint8_t *)&new_ctx->ctx + off;
229
230
0
  return new_ctx;
231
0
}
232
233
static int wrap_padlock_hmac_setkey(void *_ctx, const void *key, size_t keylen)
234
0
{
235
0
  struct padlock_hmac_ctx *ctx = _ctx;
236
237
0
  ctx->setkey(ctx->ctx_ptr, keylen, key);
238
239
0
  return GNUTLS_E_SUCCESS;
240
0
}
241
242
static int wrap_padlock_hmac_update(void *_ctx, const void *text,
243
            size_t textsize)
244
0
{
245
0
  struct padlock_hmac_ctx *ctx = _ctx;
246
247
0
  ctx->update(ctx->ctx_ptr, textsize, text);
248
249
0
  return GNUTLS_E_SUCCESS;
250
0
}
251
252
static int wrap_padlock_hmac_output(void *src_ctx, void *digest,
253
            size_t digestsize)
254
0
{
255
0
  struct padlock_hmac_ctx *ctx;
256
0
  ctx = src_ctx;
257
258
0
  if (digestsize < ctx->length) {
259
0
    gnutls_assert();
260
0
    return GNUTLS_E_SHORT_MEMORY_BUFFER;
261
0
  }
262
263
0
  ctx->digest(ctx->ctx_ptr, digestsize, digest);
264
265
0
  return 0;
266
0
}
267
268
static void wrap_padlock_hmac_deinit(void *hd)
269
0
{
270
0
  struct padlock_hmac_ctx *ctx = hd;
271
272
0
  zeroize_key(ctx, sizeof(*ctx));
273
0
  gnutls_free(ctx);
274
0
}
275
276
static int wrap_padlock_hmac_fast(gnutls_mac_algorithm_t algo,
277
          const void *nonce, size_t nonce_size,
278
          const void *key, size_t key_size,
279
          const void *text, size_t text_size,
280
          void *digest)
281
0
{
282
0
  if (algo == GNUTLS_MAC_SHA1 || algo == GNUTLS_MAC_SHA256) {
283
0
    unsigned char *pad;
284
0
    unsigned char pad2[SHA1_BLOCK_SIZE + MAX_SHA_DIGEST_SIZE];
285
0
    unsigned char hkey[MAX_SHA_DIGEST_SIZE];
286
0
    unsigned int digest_size =
287
0
      _gnutls_mac_get_algo_len(mac_to_entry(algo));
288
289
0
    if (key_size > SHA1_BLOCK_SIZE) {
290
0
      wrap_padlock_hash_fast((gnutls_digest_algorithm_t)algo,
291
0
                 key, key_size, hkey);
292
0
      key = hkey;
293
0
      key_size = digest_size;
294
0
    }
295
296
0
    pad = gnutls_malloc(text_size + SHA1_BLOCK_SIZE);
297
0
    if (pad == NULL)
298
0
      return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
299
300
0
    memset(pad, IPAD, SHA1_BLOCK_SIZE);
301
0
    memxor(pad, key, key_size);
302
303
0
    memcpy(&pad[SHA1_BLOCK_SIZE], text, text_size);
304
305
0
    wrap_padlock_hash_fast((gnutls_digest_algorithm_t)algo, pad,
306
0
               text_size + SHA1_BLOCK_SIZE,
307
0
               &pad2[SHA1_BLOCK_SIZE]);
308
309
0
    zeroize_key(pad, text_size + SHA1_BLOCK_SIZE);
310
0
    gnutls_free(pad);
311
312
0
    memset(pad2, OPAD, SHA1_BLOCK_SIZE);
313
0
    memxor(pad2, key, key_size);
314
315
0
    wrap_padlock_hash_fast((gnutls_digest_algorithm_t)algo, pad2,
316
0
               digest_size + SHA1_BLOCK_SIZE, digest);
317
318
0
    zeroize_key(pad2, sizeof(pad2));
319
0
    zeroize_key(hkey, sizeof(hkey));
320
0
  } else {
321
0
    struct padlock_hmac_ctx ctx;
322
0
    int ret;
323
324
0
    ret = _hmac_ctx_init(algo, &ctx);
325
0
    if (ret < 0)
326
0
      return gnutls_assert_val(ret);
327
0
    ctx.algo = algo;
328
329
0
    wrap_padlock_hmac_setkey(&ctx, key, key_size);
330
331
0
    wrap_padlock_hmac_update(&ctx, text, text_size);
332
333
0
    wrap_padlock_hmac_output(&ctx, digest, ctx.length);
334
335
0
    zeroize_key(&ctx, sizeof(ctx));
336
0
  }
337
338
0
  return 0;
339
0
}
340
341
const gnutls_crypto_mac_st _gnutls_hmac_sha_padlock_oneshot = {
342
  .init = NULL,
343
  .setkey = NULL,
344
  .setnonce = NULL,
345
  .hash = NULL,
346
  .output = NULL,
347
  .deinit = NULL,
348
  .fast = wrap_padlock_hmac_fast
349
};
350
351
const gnutls_crypto_mac_st _gnutls_hmac_sha_padlock = {
352
  .init = wrap_padlock_hmac_init,
353
  .setkey = wrap_padlock_hmac_setkey,
354
  .setnonce = NULL,
355
  .hash = wrap_padlock_hmac_update,
356
  .output = wrap_padlock_hmac_output,
357
  .copy = wrap_padlock_hmac_copy,
358
  .deinit = wrap_padlock_hmac_deinit,
359
  .fast = wrap_padlock_hmac_fast,
360
};
361
362
#endif /* HAVE_LIBNETTLE && HMAC_SET_KEY */