Coverage Report

Created: 2024-11-21 07:03

/src/boringssl/crypto/evp/p_hkdf.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (c) 2022, Google Inc.
2
 *
3
 * Permission to use, copy, modify, and/or distribute this software for any
4
 * purpose with or without fee is hereby granted, provided that the above
5
 * copyright notice and this permission notice appear in all copies.
6
 *
7
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15
#include <openssl/evp.h>
16
17
#include <openssl/bytestring.h>
18
#include <openssl/err.h>
19
#include <openssl/hkdf.h>
20
#include <openssl/kdf.h>
21
#include <openssl/mem.h>
22
23
#include "../internal.h"
24
#include "internal.h"
25
26
27
typedef struct {
28
  int mode;
29
  const EVP_MD *md;
30
  uint8_t *key;
31
  size_t key_len;
32
  uint8_t *salt;
33
  size_t salt_len;
34
  CBB info;
35
} HKDF_PKEY_CTX;
36
37
0
static int pkey_hkdf_init(EVP_PKEY_CTX *ctx) {
38
0
  HKDF_PKEY_CTX *hctx = OPENSSL_zalloc(sizeof(HKDF_PKEY_CTX));
39
0
  if (hctx == NULL) {
40
0
    return 0;
41
0
  }
42
43
0
  if (!CBB_init(&hctx->info, 0)) {
44
0
    OPENSSL_free(hctx);
45
0
    return 0;
46
0
  }
47
48
0
  ctx->data = hctx;
49
0
  return 1;
50
0
}
51
52
0
static int pkey_hkdf_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) {
53
0
  if (!pkey_hkdf_init(dst)) {
54
0
    return 0;
55
0
  }
56
57
0
  HKDF_PKEY_CTX *hctx_dst = dst->data;
58
0
  const HKDF_PKEY_CTX *hctx_src = src->data;
59
0
  hctx_dst->mode = hctx_src->mode;
60
0
  hctx_dst->md = hctx_src->md;
61
62
0
  if (hctx_src->key_len != 0) {
63
0
    hctx_dst->key = OPENSSL_memdup(hctx_src->key, hctx_src->key_len);
64
0
    if (hctx_dst->key == NULL) {
65
0
      return 0;
66
0
    }
67
0
    hctx_dst->key_len = hctx_src->key_len;
68
0
  }
69
70
0
  if (hctx_src->salt_len != 0) {
71
0
    hctx_dst->salt = OPENSSL_memdup(hctx_src->salt, hctx_src->salt_len);
72
0
    if (hctx_dst->salt == NULL) {
73
0
      return 0;
74
0
    }
75
0
    hctx_dst->salt_len = hctx_src->salt_len;
76
0
  }
77
78
0
  if (!CBB_add_bytes(&hctx_dst->info, CBB_data(&hctx_src->info),
79
0
                     CBB_len(&hctx_src->info))) {
80
0
    return 0;
81
0
  }
82
83
0
  return 1;
84
0
}
85
86
0
static void pkey_hkdf_cleanup(EVP_PKEY_CTX *ctx) {
87
0
  HKDF_PKEY_CTX *hctx = ctx->data;
88
0
  if (hctx != NULL) {
89
0
    OPENSSL_free(hctx->key);
90
0
    OPENSSL_free(hctx->salt);
91
0
    CBB_cleanup(&hctx->info);
92
0
    OPENSSL_free(hctx);
93
0
    ctx->data = NULL;
94
0
  }
95
0
}
96
97
0
static int pkey_hkdf_derive(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len) {
98
0
  HKDF_PKEY_CTX *hctx = ctx->data;
99
0
  if (hctx->md == NULL) {
100
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
101
0
    return 0;
102
0
  }
103
0
  if (hctx->key_len == 0) {
104
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_NO_KEY_SET);
105
0
    return 0;
106
0
  }
107
108
0
  if (out == NULL) {
109
0
    if (hctx->mode == EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY) {
110
0
      *out_len = EVP_MD_size(hctx->md);
111
0
    }
112
    // HKDF-Expand is variable-length and returns |*out_len| bytes. "Output" the
113
    // input length by leaving it alone.
114
0
    return 1;
115
0
  }
116
117
0
  switch (hctx->mode) {
118
0
    case EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND:
119
0
      return HKDF(out, *out_len, hctx->md, hctx->key, hctx->key_len, hctx->salt,
120
0
                  hctx->salt_len, CBB_data(&hctx->info), CBB_len(&hctx->info));
121
122
0
    case EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY:
123
0
      if (*out_len < EVP_MD_size(hctx->md)) {
124
0
        OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
125
0
        return 0;
126
0
      }
127
0
      return HKDF_extract(out, out_len, hctx->md, hctx->key, hctx->key_len,
128
0
                          hctx->salt, hctx->salt_len);
129
130
0
    case EVP_PKEY_HKDEF_MODE_EXPAND_ONLY:
131
0
      return HKDF_expand(out, *out_len, hctx->md, hctx->key, hctx->key_len,
132
0
                         CBB_data(&hctx->info), CBB_len(&hctx->info));
133
0
  }
134
0
  OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR);
135
0
  return 0;
136
0
}
137
138
0
static int pkey_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
139
0
  HKDF_PKEY_CTX *hctx = ctx->data;
140
0
  switch (type) {
141
0
    case EVP_PKEY_CTRL_HKDF_MODE:
142
0
      if (p1 != EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND &&
143
0
          p1 != EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY &&
144
0
          p1 != EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) {
145
0
        OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_OPERATION);
146
0
        return 0;
147
0
      }
148
0
      hctx->mode = p1;
149
0
      return 1;
150
0
    case EVP_PKEY_CTRL_HKDF_MD:
151
0
      hctx->md = p2;
152
0
      return 1;
153
0
    case EVP_PKEY_CTRL_HKDF_KEY: {
154
0
      const CBS *key = p2;
155
0
      if (!CBS_stow(key, &hctx->key, &hctx->key_len)) {
156
0
        return 0;
157
0
      }
158
0
      return 1;
159
0
    }
160
0
    case EVP_PKEY_CTRL_HKDF_SALT: {
161
0
      const CBS *salt = p2;
162
0
      if (!CBS_stow(salt, &hctx->salt, &hctx->salt_len)) {
163
0
        return 0;
164
0
      }
165
0
      return 1;
166
0
    }
167
0
    case EVP_PKEY_CTRL_HKDF_INFO: {
168
0
      const CBS *info = p2;
169
      // |EVP_PKEY_CTX_add1_hkdf_info| appends to the info string, rather than
170
      // replacing it.
171
0
      if (!CBB_add_bytes(&hctx->info, CBS_data(info), CBS_len(info))) {
172
0
        return 0;
173
0
      }
174
0
      return 1;
175
0
    }
176
0
    default:
177
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED);
178
0
      return 0;
179
0
  }
180
0
}
181
182
const EVP_PKEY_METHOD hkdf_pkey_meth = {
183
    EVP_PKEY_HKDF,
184
    pkey_hkdf_init,
185
    pkey_hkdf_copy,
186
    pkey_hkdf_cleanup,
187
    /*keygen=*/NULL,
188
    /*sign=*/NULL,
189
    /*sign_message=*/NULL,
190
    /*verify=*/NULL,
191
    /*verify_message=*/NULL,
192
    /*verify_recover=*/NULL,
193
    /*encrypt=*/NULL,
194
    /*decrypt=*/NULL,
195
    pkey_hkdf_derive,
196
    /*paramgen=*/NULL,
197
    pkey_hkdf_ctrl,
198
};
199
200
0
int EVP_PKEY_CTX_hkdf_mode(EVP_PKEY_CTX *ctx, int mode) {
201
0
  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_HKDF, EVP_PKEY_OP_DERIVE,
202
0
                           EVP_PKEY_CTRL_HKDF_MODE, mode, NULL);
203
0
}
204
205
int EVP_PKEY_CTX_set_hkdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
206
  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_HKDF, EVP_PKEY_OP_DERIVE,
207
                           EVP_PKEY_CTRL_HKDF_MD, 0, (void *)md);
208
}
209
210
int EVP_PKEY_CTX_set1_hkdf_key(EVP_PKEY_CTX *ctx, const uint8_t *key,
211
                               size_t key_len) {
212
  CBS cbs;
213
  CBS_init(&cbs, key, key_len);
214
  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_HKDF, EVP_PKEY_OP_DERIVE,
215
                           EVP_PKEY_CTRL_HKDF_KEY, 0, &cbs);
216
}
217
218
int EVP_PKEY_CTX_set1_hkdf_salt(EVP_PKEY_CTX *ctx, const uint8_t *salt,
219
                                size_t salt_len) {
220
  CBS cbs;
221
  CBS_init(&cbs, salt, salt_len);
222
  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_HKDF, EVP_PKEY_OP_DERIVE,
223
                           EVP_PKEY_CTRL_HKDF_SALT, 0, &cbs);
224
}
225
226
int EVP_PKEY_CTX_add1_hkdf_info(EVP_PKEY_CTX *ctx, const uint8_t *info,
227
                                size_t info_len) {
228
  CBS cbs;
229
  CBS_init(&cbs, info, info_len);
230
  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_HKDF, EVP_PKEY_OP_DERIVE,
231
                           EVP_PKEY_CTRL_HKDF_INFO, 0, &cbs);
232
}