Coverage Report

Created: 2026-09-14 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwebsockets/lib/tls/openssl/lws-genhash.c
Line
Count
Source
1
 /*
2
 * libwebsockets - small server side websockets and web server implementation
3
 *
4
 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to
8
 * deal in the Software without restriction, including without limitation the
9
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10
 * sell copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
 * IN THE SOFTWARE.
23
 *
24
 *  lws_genhash provides a hash / hmac abstraction api in lws that works the
25
 *  same whether you are using openssl or mbedtls hash functions underneath.
26
 */
27
#include <private-lib-core.h>
28
#include "private-lib-tls-openssl.h"
29
#include <openssl/obj_mac.h>
30
#include <openssl/opensslv.h>
31
/*
32
 * Care: many openssl apis return 1 for success.  These are translated to the
33
 * lws convention of 0 for success.
34
 */
35
36
int
37
lws_genhash_init(struct lws_genhash_ctx *ctx, enum lws_genhash_types type)
38
0
{
39
0
  ctx->type = (uint8_t)type;
40
0
  ctx->mdctx = EVP_MD_CTX_create();
41
0
  if (!ctx->mdctx)
42
0
    return 1;
43
44
0
  switch (ctx->type) {
45
0
  case LWS_GENHASH_TYPE_MD5:
46
0
    ctx->evp_type = EVP_md5();
47
0
    break;
48
0
  case LWS_GENHASH_TYPE_SHA1:
49
0
    ctx->evp_type = EVP_sha1();
50
0
    break;
51
0
  case LWS_GENHASH_TYPE_SHA256:
52
0
    ctx->evp_type = EVP_sha256();
53
0
    break;
54
0
  case LWS_GENHASH_TYPE_SHA384:
55
0
    ctx->evp_type = EVP_sha384();
56
0
    break;
57
0
  case LWS_GENHASH_TYPE_SHA512:
58
0
    ctx->evp_type = EVP_sha512();
59
0
    break;
60
0
  default:
61
0
    goto bail;
62
0
  }
63
64
0
  if (EVP_DigestInit_ex(ctx->mdctx, ctx->evp_type, NULL) != 1)
65
0
    goto bail;
66
67
0
  return 0;
68
69
0
bail:
70
  /*
71
   * Callers follow the "destroy again on failure" idiom, so a failed
72
   * init must not leave the freed ctx behind for the second destroy to
73
   * free again (and the unknown-type arm must not leak it either)
74
   */
75
76
0
  EVP_MD_CTX_destroy(ctx->mdctx);
77
0
  ctx->mdctx = NULL;
78
79
0
  return 1;
80
0
}
81
82
int
83
lws_genhash_update(struct lws_genhash_ctx *ctx, const void *in, size_t len)
84
0
{
85
0
  if (!len)
86
0
    return 0;
87
88
0
  return EVP_DigestUpdate(ctx->mdctx, in, len) != 1;
89
0
}
90
91
int
92
lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result)
93
0
{
94
0
  unsigned int len;
95
0
  int ret = 0;
96
97
0
  if (!ctx->mdctx)
98
0
    return 0;
99
100
0
  if (result)
101
0
    ret = EVP_DigestFinal_ex(ctx->mdctx, result, &len) != 1;
102
103
0
  (void)len;
104
105
0
  EVP_MD_CTX_destroy(ctx->mdctx);
106
0
  ctx->mdctx = NULL;
107
108
0
  return ret;
109
0
}
110
111
#if defined(LWS_HAVE_EVP_PKEY_new_raw_private_key) && !defined(LWS_WITH_BORINGSSL) && !defined(LWS_WITH_AWSLC)
112
113
int
114
lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type,
115
     const uint8_t *key, size_t key_len)
116
0
{
117
0
  ctx->key = NULL;
118
0
  ctx->ctx = EVP_MD_CTX_create();
119
0
  if (!ctx->ctx)
120
0
    return -1;
121
122
0
  ctx->evp_type = 0;
123
0
  ctx->type = (uint8_t)type;
124
125
0
  switch (type) {
126
0
  case LWS_GENHMAC_TYPE_SHA1:
127
0
    ctx->evp_type = EVP_sha1();
128
0
    break;
129
0
  case LWS_GENHMAC_TYPE_SHA256:
130
0
    ctx->evp_type = EVP_sha256();
131
0
    break;
132
0
  case LWS_GENHMAC_TYPE_SHA384:
133
0
    ctx->evp_type = EVP_sha384();
134
0
    break;
135
0
  case LWS_GENHMAC_TYPE_SHA512:
136
0
    ctx->evp_type = EVP_sha512();
137
0
    break;
138
0
  default:
139
0
    lwsl_err("%s: unknown HMAC type %d\n", __func__, type);
140
0
    goto bail;
141
0
  }
142
143
0
  ctx->key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, key, key_len);
144
0
  if (!ctx->key)
145
0
    goto bail;
146
147
0
  if (EVP_DigestSignInit(ctx->ctx, NULL, ctx->evp_type, NULL, ctx->key) != 1)
148
0
    goto bail1;
149
150
0
  return 0;
151
152
0
bail1:
153
0
  EVP_PKEY_free(ctx->key);
154
0
  ctx->key = NULL;
155
0
bail:
156
  /*
157
   * Callers follow the "destroy again on failure" idiom, so a failed
158
   * init must leave nothing dangling in the ctx for the second destroy
159
   */
160
161
0
  EVP_MD_CTX_free(ctx->ctx);
162
0
  ctx->ctx = NULL;
163
164
0
  return -1;
165
0
}
166
167
int
168
lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len)
169
0
{
170
171
#if defined(USE_WOLFSSL)
172
  if (EVP_DigestSignUpdate(ctx->ctx, in, (unsigned int)len) != 1)
173
#else
174
0
  if (EVP_DigestSignUpdate(ctx->ctx, in, len) != 1)
175
0
#endif
176
0
    return -1;
177
178
0
  return 0;
179
0
}
180
181
int
182
lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result)
183
0
{
184
0
  size_t size = (size_t)lws_genhmac_size(ctx->type);
185
0
  int n = 1;
186
187
  /* idempotent: destroying an already-destroyed ctx is a NOP */
188
189
0
  if (!ctx->ctx)
190
0
    return 0;
191
192
0
  if (result)
193
0
    n = EVP_DigestSignFinal(ctx->ctx, result, &size);
194
195
0
  EVP_MD_CTX_free(ctx->ctx);
196
0
  ctx->ctx = NULL;
197
0
  EVP_PKEY_free(ctx->key);
198
0
  ctx->key = NULL;
199
200
0
  if (n != 1)
201
0
    return -1;
202
203
0
  return 0;
204
0
}
205
206
#else
207
208
int
209
lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type,
210
     const uint8_t *key, size_t key_len)
211
{
212
#if defined(LWS_HAVE_HMAC_CTX_new) || defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
213
  ctx->ctx = HMAC_CTX_new();
214
  if (!ctx->ctx)
215
    return -1;
216
#else
217
  HMAC_CTX_init(&ctx->ctx);
218
#endif
219
220
  ctx->evp_type = 0;
221
  ctx->type = (uint8_t)type;
222
223
  switch (type) {
224
  case LWS_GENHMAC_TYPE_SHA1:
225
    ctx->evp_type = EVP_sha1();
226
    break;
227
  case LWS_GENHMAC_TYPE_SHA256:
228
    ctx->evp_type = EVP_sha256();
229
    break;
230
  case LWS_GENHMAC_TYPE_SHA384:
231
    ctx->evp_type = EVP_sha384();
232
    break;
233
  case LWS_GENHMAC_TYPE_SHA512:
234
    ctx->evp_type = EVP_sha512();
235
    break;
236
  default:
237
    lwsl_err("%s: unknown HMAC type %d\n", __func__, type);
238
    goto bail;
239
  }
240
241
#if defined(LWS_HAVE_HMAC_CTX_new) || defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
242
        if (HMAC_Init_ex(ctx->ctx, key, 
243
        SSL_SIZE_T_CAST(key_len), ctx->evp_type, NULL) != 1)
244
#else
245
        if (HMAC_Init_ex(&ctx->ctx, key, SSL_SIZE_T_CAST(key_len), ctx->evp_type, NULL) != 1)
246
#endif
247
          goto bail;
248
249
  return 0;
250
251
bail:
252
  /*
253
   * Callers follow the "destroy again on failure" idiom, so a failed
254
   * init must leave nothing dangling in the ctx for the second destroy
255
   */
256
257
#if defined(LWS_HAVE_HMAC_CTX_new) || defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
258
  HMAC_CTX_free(ctx->ctx);
259
  ctx->ctx = NULL;
260
#endif
261
262
  return -1;
263
}
264
265
int
266
lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len)
267
{
268
#if defined(LWS_HAVE_HMAC_CTX_new) || defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
269
#if defined(LIBRESSL_VERSION_NUMBER)
270
  if (HMAC_Update(ctx->ctx, in, len) != 1)
271
#else
272
  if (HMAC_Update(ctx->ctx, in, SSL_SIZE_T_CAST(len)) != 1)
273
#endif
274
#else /* HMAC_CTX_new */
275
  if (HMAC_Update(&ctx->ctx, in, len) != 1)
276
#endif
277
    return -1;
278
279
  return 0;
280
}
281
282
int
283
lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result)
284
{
285
  unsigned int size = (unsigned int)lws_genhmac_size(ctx->type);
286
  int n = 1;
287
288
#if defined(LWS_HAVE_HMAC_CTX_new) || defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
289
290
  /* idempotent: destroying an already-destroyed ctx is a NOP */
291
292
  if (!ctx->ctx)
293
    return 0;
294
295
  /*
296
   * HMAC_Final() has no size-query form, it would deref the NULL, so
297
   * only take the MAC if the caller actually wants it
298
   */
299
300
  if (result)
301
    n = HMAC_Final(ctx->ctx, result, &size);
302
303
  HMAC_CTX_free(ctx->ctx);
304
  ctx->ctx = NULL;
305
#else
306
  if (result)
307
    n = HMAC_Final(&ctx->ctx, result, &size);
308
#endif
309
310
  if (n != 1)
311
    return -1;
312
313
  return 0;
314
}
315
316
317
#endif