Coverage Report

Created: 2022-08-24 06:30

/src/libressl/crypto/kdf/hkdf_evp.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: hkdf_evp.c,v 1.18 2022/05/05 19:48:06 tb Exp $ */
2
/* ====================================================================
3
 * Copyright (c) 2016-2018 The OpenSSL Project.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 *
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 *
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in
14
 *    the documentation and/or other materials provided with the
15
 *    distribution.
16
 *
17
 * 3. All advertising materials mentioning features or use of this
18
 *    software must display the following acknowledgment:
19
 *    "This product includes software developed by the OpenSSL Project
20
 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21
 *
22
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23
 *    endorse or promote products derived from this software without
24
 *    prior written permission. For written permission, please contact
25
 *    openssl-core@openssl.org.
26
 *
27
 * 5. Products derived from this software may not be called "OpenSSL"
28
 *    nor may "OpenSSL" appear in their names without prior written
29
 *    permission of the OpenSSL Project.
30
 *
31
 * 6. Redistributions of any form whatsoever must retain the following
32
 *    acknowledgment:
33
 *    "This product includes software developed by the OpenSSL Project
34
 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35
 *
36
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47
 * OF THE POSSIBILITY OF SUCH DAMAGE.
48
 */
49
50
#include <stdlib.h>
51
#include <string.h>
52
53
#include <openssl/err.h>
54
#include <openssl/evp.h>
55
#include <openssl/hmac.h>
56
#include <openssl/hkdf.h>
57
#include <openssl/kdf.h>
58
59
#include "evp_locl.h"
60
61
0
#define HKDF_MAXBUF 1024
62
63
typedef struct {
64
  int mode;
65
  const EVP_MD *md;
66
  unsigned char *salt;
67
  size_t salt_len;
68
  unsigned char *key;
69
  size_t key_len;
70
  unsigned char info[HKDF_MAXBUF];
71
  size_t info_len;
72
} HKDF_PKEY_CTX;
73
74
static int
75
pkey_hkdf_init(EVP_PKEY_CTX *ctx)
76
0
{
77
0
  HKDF_PKEY_CTX *kctx;
78
79
0
  if ((kctx = calloc(1, sizeof(*kctx))) == NULL) {
80
0
    KDFerror(ERR_R_MALLOC_FAILURE);
81
0
    return 0;
82
0
  }
83
84
0
  ctx->data = kctx;
85
86
0
  return 1;
87
0
}
88
89
static void
90
pkey_hkdf_cleanup(EVP_PKEY_CTX *ctx)
91
0
{
92
0
  HKDF_PKEY_CTX *kctx = ctx->data;
93
94
0
  freezero(kctx->salt, kctx->salt_len);
95
0
  freezero(kctx->key, kctx->key_len);
96
0
  freezero(kctx, sizeof(*kctx));
97
0
}
98
99
static int
100
pkey_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
101
0
{
102
0
  HKDF_PKEY_CTX *kctx = ctx->data;
103
104
0
  switch (type) {
105
0
  case EVP_PKEY_CTRL_HKDF_MD:
106
0
    if (p2 == NULL)
107
0
      return 0;
108
109
0
    kctx->md = p2;
110
0
    return 1;
111
112
0
  case EVP_PKEY_CTRL_HKDF_MODE:
113
0
    kctx->mode = p1;
114
0
    return 1;
115
116
0
  case EVP_PKEY_CTRL_HKDF_SALT:
117
0
    if (p1 == 0 || p2 == NULL)
118
0
      return 1;
119
120
0
    if (p1 < 0)
121
0
      return 0;
122
123
0
    freezero(kctx->salt, kctx->salt_len);
124
0
    if ((kctx->salt = malloc(p1)) == NULL)
125
0
      return 0;
126
0
    memcpy(kctx->salt, p2, p1);
127
128
0
    kctx->salt_len = p1;
129
0
    return 1;
130
131
0
  case EVP_PKEY_CTRL_HKDF_KEY:
132
0
    if (p1 <= 0)
133
0
      return 0;
134
135
0
    freezero(kctx->key, kctx->key_len);
136
0
    if ((kctx->key = malloc(p1)) == NULL)
137
0
      return 0;
138
0
    memcpy(kctx->key, p2, p1);
139
140
0
    kctx->key_len = p1;
141
0
    return 1;
142
143
0
  case EVP_PKEY_CTRL_HKDF_INFO:
144
0
    if (p1 == 0 || p2 == NULL)
145
0
      return 1;
146
147
0
    if (p1 < 0 || p1 > (int)(HKDF_MAXBUF - kctx->info_len))
148
0
      return 0;
149
150
0
    memcpy(kctx->info + kctx->info_len, p2, p1);
151
0
    kctx->info_len += p1;
152
0
    return 1;
153
154
0
  default:
155
0
    return -2;
156
0
  }
157
0
}
158
159
static int
160
pkey_hkdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
161
    const char *value)
162
0
{
163
0
  if (strcmp(type, "mode") == 0) {
164
0
    int mode;
165
166
0
    if (strcmp(value, "EXTRACT_AND_EXPAND") == 0)
167
0
      mode = EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND;
168
0
    else if (strcmp(value, "EXTRACT_ONLY") == 0)
169
0
      mode = EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY;
170
0
    else if (strcmp(value, "EXPAND_ONLY") == 0)
171
0
      mode = EVP_PKEY_HKDEF_MODE_EXPAND_ONLY;
172
0
    else
173
0
      return 0;
174
175
0
    return EVP_PKEY_CTX_hkdf_mode(ctx, mode);
176
0
  }
177
178
0
  if (strcmp(type, "md") == 0)
179
0
    return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_DERIVE,
180
0
        EVP_PKEY_CTRL_HKDF_MD, value);
181
182
0
  if (strcmp(type, "salt") == 0)
183
0
    return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT,
184
0
        value);
185
186
0
  if (strcmp(type, "hexsalt") == 0)
187
0
    return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT,
188
0
        value);
189
190
0
  if (strcmp(type, "key") == 0)
191
0
    return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
192
193
0
  if (strcmp(type, "hexkey") == 0)
194
0
    return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
195
196
0
  if (strcmp(type, "info") == 0)
197
0
    return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO,
198
0
        value);
199
200
0
  if (strcmp(type, "hexinfo") == 0)
201
0
    return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO,
202
0
        value);
203
204
0
  KDFerror(KDF_R_UNKNOWN_PARAMETER_TYPE);
205
0
  return -2;
206
0
}
207
208
static int
209
pkey_hkdf_derive_init(EVP_PKEY_CTX *ctx)
210
0
{
211
0
  HKDF_PKEY_CTX *kctx = ctx->data;
212
213
0
  freezero(kctx->key, kctx->key_len);
214
0
  freezero(kctx->salt, kctx->salt_len);
215
0
  explicit_bzero(kctx, sizeof(*kctx));
216
217
0
  return 1;
218
0
}
219
220
static int
221
pkey_hkdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
222
    size_t *keylen)
223
0
{
224
0
  HKDF_PKEY_CTX *kctx = ctx->data;
225
226
0
  if (kctx->md == NULL) {
227
0
    KDFerror(KDF_R_MISSING_MESSAGE_DIGEST);
228
0
    return 0;
229
0
  }
230
0
  if (kctx->key == NULL) {
231
0
    KDFerror(KDF_R_MISSING_KEY);
232
0
    return 0;
233
0
  }
234
235
0
  switch (kctx->mode) {
236
0
  case EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND:
237
0
    return HKDF(key, *keylen, kctx->md, kctx->key, kctx->key_len,
238
0
        kctx->salt, kctx->salt_len, kctx->info, kctx->info_len);
239
240
0
  case EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY:
241
0
    if (key == NULL) {
242
0
      *keylen = EVP_MD_size(kctx->md);
243
0
      return 1;
244
0
    }
245
0
    return HKDF_extract(key, keylen, kctx->md, kctx->key,
246
0
        kctx->key_len, kctx->salt, kctx->salt_len);
247
248
0
  case EVP_PKEY_HKDEF_MODE_EXPAND_ONLY:
249
0
    return HKDF_expand(key, *keylen, kctx->md, kctx->key,
250
0
        kctx->key_len, kctx->info, kctx->info_len);
251
252
0
  default:
253
0
    return 0;
254
0
  }
255
0
}
256
257
const EVP_PKEY_METHOD hkdf_pkey_meth = {
258
  .pkey_id = EVP_PKEY_HKDF,
259
  .flags = 0,
260
261
  .init = pkey_hkdf_init,
262
  .copy = NULL,
263
  .cleanup = pkey_hkdf_cleanup,
264
265
  .derive_init = pkey_hkdf_derive_init,
266
  .derive = pkey_hkdf_derive,
267
  .ctrl = pkey_hkdf_ctrl,
268
  .ctrl_str = pkey_hkdf_ctrl_str,
269
};