Coverage Report

Created: 2025-03-18 06:55

/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
    return gnutls_assert_val(ret);
206
207
0
  *_ctx = ctx;
208
209
0
  return 0;
210
0
}
211
212
static void *wrap_padlock_hmac_copy(const void *_ctx)
213
0
{
214
0
  struct padlock_hmac_ctx *new_ctx;
215
0
  const struct padlock_hmac_ctx *ctx = _ctx;
216
0
  ptrdiff_t off = (uint8_t *)ctx->ctx_ptr - (uint8_t *)(&ctx->ctx);
217
218
0
  new_ctx = gnutls_malloc(sizeof(struct padlock_hmac_ctx));
219
0
  if (new_ctx == NULL) {
220
0
    gnutls_assert();
221
0
    return NULL;
222
0
  }
223
224
0
  memcpy(new_ctx, ctx, sizeof(*new_ctx));
225
0
  new_ctx->ctx_ptr = (uint8_t *)&new_ctx->ctx + off;
226
227
0
  return new_ctx;
228
0
}
229
230
static int wrap_padlock_hmac_setkey(void *_ctx, const void *key, size_t keylen)
231
0
{
232
0
  struct padlock_hmac_ctx *ctx = _ctx;
233
234
0
  ctx->setkey(ctx->ctx_ptr, keylen, key);
235
236
0
  return GNUTLS_E_SUCCESS;
237
0
}
238
239
static int wrap_padlock_hmac_update(void *_ctx, const void *text,
240
            size_t textsize)
241
0
{
242
0
  struct padlock_hmac_ctx *ctx = _ctx;
243
244
0
  ctx->update(ctx->ctx_ptr, textsize, text);
245
246
0
  return GNUTLS_E_SUCCESS;
247
0
}
248
249
static int wrap_padlock_hmac_output(void *src_ctx, void *digest,
250
            size_t digestsize)
251
0
{
252
0
  struct padlock_hmac_ctx *ctx;
253
0
  ctx = src_ctx;
254
255
0
  if (digestsize < ctx->length) {
256
0
    gnutls_assert();
257
0
    return GNUTLS_E_SHORT_MEMORY_BUFFER;
258
0
  }
259
260
0
  ctx->digest(ctx->ctx_ptr, digestsize, digest);
261
262
0
  return 0;
263
0
}
264
265
static void wrap_padlock_hmac_deinit(void *hd)
266
0
{
267
0
  struct padlock_hmac_ctx *ctx = hd;
268
269
0
  zeroize_temp_key(ctx, sizeof(*ctx));
270
0
  gnutls_free(ctx);
271
0
}
272
273
static int wrap_padlock_hmac_fast(gnutls_mac_algorithm_t algo,
274
          const void *nonce, size_t nonce_size,
275
          const void *key, size_t key_size,
276
          const void *text, size_t text_size,
277
          void *digest)
278
0
{
279
0
  if (algo == GNUTLS_MAC_SHA1 || algo == GNUTLS_MAC_SHA256) {
280
0
    unsigned char *pad;
281
0
    unsigned char pad2[SHA1_DATA_SIZE + MAX_SHA_DIGEST_SIZE];
282
0
    unsigned char hkey[MAX_SHA_DIGEST_SIZE];
283
0
    unsigned int digest_size =
284
0
      _gnutls_mac_get_algo_len(mac_to_entry(algo));
285
286
0
    if (key_size > SHA1_DATA_SIZE) {
287
0
      wrap_padlock_hash_fast((gnutls_digest_algorithm_t)algo,
288
0
                 key, key_size, hkey);
289
0
      key = hkey;
290
0
      key_size = digest_size;
291
0
    }
292
293
0
    pad = gnutls_malloc(text_size + SHA1_DATA_SIZE);
294
0
    if (pad == NULL)
295
0
      return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
296
297
0
    memset(pad, IPAD, SHA1_DATA_SIZE);
298
0
    memxor(pad, key, key_size);
299
300
0
    memcpy(&pad[SHA1_DATA_SIZE], text, text_size);
301
302
0
    wrap_padlock_hash_fast((gnutls_digest_algorithm_t)algo, pad,
303
0
               text_size + SHA1_DATA_SIZE,
304
0
               &pad2[SHA1_DATA_SIZE]);
305
306
0
    zeroize_temp_key(pad, text_size + SHA1_DATA_SIZE);
307
0
    gnutls_free(pad);
308
309
0
    memset(pad2, OPAD, SHA1_DATA_SIZE);
310
0
    memxor(pad2, key, key_size);
311
312
0
    wrap_padlock_hash_fast((gnutls_digest_algorithm_t)algo, pad2,
313
0
               digest_size + SHA1_DATA_SIZE, digest);
314
315
0
    zeroize_temp_key(pad2, sizeof(pad2));
316
0
    zeroize_temp_key(hkey, sizeof(hkey));
317
0
  } else {
318
0
    struct padlock_hmac_ctx ctx;
319
0
    int ret;
320
321
0
    ret = _hmac_ctx_init(algo, &ctx);
322
0
    if (ret < 0)
323
0
      return gnutls_assert_val(ret);
324
0
    ctx.algo = algo;
325
326
0
    wrap_padlock_hmac_setkey(&ctx, key, key_size);
327
328
0
    wrap_padlock_hmac_update(&ctx, text, text_size);
329
330
0
    wrap_padlock_hmac_output(&ctx, digest, ctx.length);
331
332
0
    zeroize_temp_key(&ctx, sizeof(ctx));
333
0
  }
334
335
0
  return 0;
336
0
}
337
338
const gnutls_crypto_mac_st _gnutls_hmac_sha_padlock_oneshot = {
339
  .init = NULL,
340
  .setkey = NULL,
341
  .setnonce = NULL,
342
  .hash = NULL,
343
  .output = NULL,
344
  .deinit = NULL,
345
  .fast = wrap_padlock_hmac_fast
346
};
347
348
const gnutls_crypto_mac_st _gnutls_hmac_sha_padlock = {
349
  .init = wrap_padlock_hmac_init,
350
  .setkey = wrap_padlock_hmac_setkey,
351
  .setnonce = NULL,
352
  .hash = wrap_padlock_hmac_update,
353
  .output = wrap_padlock_hmac_output,
354
  .copy = wrap_padlock_hmac_copy,
355
  .deinit = wrap_padlock_hmac_deinit,
356
  .fast = wrap_padlock_hmac_fast,
357
};
358
359
#endif /* HAVE_LIBNETTLE */