Coverage Report

Created: 2025-12-07 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/evp/p_hkdf.cc
Line
Count
Source
1
// Copyright 2022 The BoringSSL Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
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 =
39
0
      reinterpret_cast<HKDF_PKEY_CTX *>(OPENSSL_zalloc(sizeof(HKDF_PKEY_CTX)));
40
0
  if (hctx == nullptr) {
41
0
    return 0;
42
0
  }
43
44
0
  if (!CBB_init(&hctx->info, 0)) {
45
0
    OPENSSL_free(hctx);
46
0
    return 0;
47
0
  }
48
49
0
  ctx->data = hctx;
50
0
  return 1;
51
0
}
52
53
0
static int pkey_hkdf_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) {
54
0
  if (!pkey_hkdf_init(dst)) {
55
0
    return 0;
56
0
  }
57
58
0
  HKDF_PKEY_CTX *hctx_dst = reinterpret_cast<HKDF_PKEY_CTX *>(dst->data);
59
0
  const HKDF_PKEY_CTX *hctx_src =
60
0
      reinterpret_cast<const HKDF_PKEY_CTX *>(src->data);
61
0
  hctx_dst->mode = hctx_src->mode;
62
0
  hctx_dst->md = hctx_src->md;
63
64
0
  if (hctx_src->key_len != 0) {
65
0
    hctx_dst->key = reinterpret_cast<uint8_t *>(
66
0
        OPENSSL_memdup(hctx_src->key, hctx_src->key_len));
67
0
    if (hctx_dst->key == nullptr) {
68
0
      return 0;
69
0
    }
70
0
    hctx_dst->key_len = hctx_src->key_len;
71
0
  }
72
73
0
  if (hctx_src->salt_len != 0) {
74
0
    hctx_dst->salt = reinterpret_cast<uint8_t *>(
75
0
        OPENSSL_memdup(hctx_src->salt, hctx_src->salt_len));
76
0
    if (hctx_dst->salt == nullptr) {
77
0
      return 0;
78
0
    }
79
0
    hctx_dst->salt_len = hctx_src->salt_len;
80
0
  }
81
82
0
  if (!CBB_add_bytes(&hctx_dst->info, CBB_data(&hctx_src->info),
83
0
                     CBB_len(&hctx_src->info))) {
84
0
    return 0;
85
0
  }
86
87
0
  return 1;
88
0
}
89
90
0
static void pkey_hkdf_cleanup(EVP_PKEY_CTX *ctx) {
91
0
  HKDF_PKEY_CTX *hctx = reinterpret_cast<HKDF_PKEY_CTX *>(ctx->data);
92
0
  if (hctx != nullptr) {
93
0
    OPENSSL_free(hctx->key);
94
0
    OPENSSL_free(hctx->salt);
95
0
    CBB_cleanup(&hctx->info);
96
0
    OPENSSL_free(hctx);
97
0
    ctx->data = nullptr;
98
0
  }
99
0
}
100
101
0
static int pkey_hkdf_derive(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len) {
102
0
  HKDF_PKEY_CTX *hctx = reinterpret_cast<HKDF_PKEY_CTX *>(ctx->data);
103
0
  if (hctx->md == nullptr) {
104
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
105
0
    return 0;
106
0
  }
107
0
  if (hctx->key_len == 0) {
108
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_NO_KEY_SET);
109
0
    return 0;
110
0
  }
111
112
0
  if (out == nullptr) {
113
0
    if (hctx->mode == EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY) {
114
0
      *out_len = EVP_MD_size(hctx->md);
115
0
    }
116
    // HKDF-Expand is variable-length and returns |*out_len| bytes. "Output" the
117
    // input length by leaving it alone.
118
0
    return 1;
119
0
  }
120
121
0
  switch (hctx->mode) {
122
0
    case EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND:
123
0
      return HKDF(out, *out_len, hctx->md, hctx->key, hctx->key_len, hctx->salt,
124
0
                  hctx->salt_len, CBB_data(&hctx->info), CBB_len(&hctx->info));
125
126
0
    case EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY:
127
0
      if (*out_len < EVP_MD_size(hctx->md)) {
128
0
        OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
129
0
        return 0;
130
0
      }
131
0
      return HKDF_extract(out, out_len, hctx->md, hctx->key, hctx->key_len,
132
0
                          hctx->salt, hctx->salt_len);
133
134
0
    case EVP_PKEY_HKDEF_MODE_EXPAND_ONLY:
135
0
      return HKDF_expand(out, *out_len, hctx->md, hctx->key, hctx->key_len,
136
0
                         CBB_data(&hctx->info), CBB_len(&hctx->info));
137
0
  }
138
0
  OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR);
139
0
  return 0;
140
0
}
141
142
0
static int pkey_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
143
0
  HKDF_PKEY_CTX *hctx = reinterpret_cast<HKDF_PKEY_CTX *>(ctx->data);
144
0
  switch (type) {
145
0
    case EVP_PKEY_CTRL_HKDF_MODE:
146
0
      if (p1 != EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND &&
147
0
          p1 != EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY &&
148
0
          p1 != EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) {
149
0
        OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_OPERATION);
150
0
        return 0;
151
0
      }
152
0
      hctx->mode = p1;
153
0
      return 1;
154
0
    case EVP_PKEY_CTRL_HKDF_MD:
155
0
      hctx->md = reinterpret_cast<const EVP_MD *>(p2);
156
0
      return 1;
157
0
    case EVP_PKEY_CTRL_HKDF_KEY: {
158
0
      const CBS *key = reinterpret_cast<const CBS *>(p2);
159
0
      if (!CBS_stow(key, &hctx->key, &hctx->key_len)) {
160
0
        return 0;
161
0
      }
162
0
      return 1;
163
0
    }
164
0
    case EVP_PKEY_CTRL_HKDF_SALT: {
165
0
      const CBS *salt = reinterpret_cast<const CBS *>(p2);
166
0
      if (!CBS_stow(salt, &hctx->salt, &hctx->salt_len)) {
167
0
        return 0;
168
0
      }
169
0
      return 1;
170
0
    }
171
0
    case EVP_PKEY_CTRL_HKDF_INFO: {
172
0
      const CBS *info = reinterpret_cast<const CBS *>(p2);
173
      // |EVP_PKEY_CTX_add1_hkdf_info| appends to the info string, rather than
174
      // replacing it.
175
0
      if (!CBB_add_bytes(&hctx->info, CBS_data(info), CBS_len(info))) {
176
0
        return 0;
177
0
      }
178
0
      return 1;
179
0
    }
180
0
    default:
181
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED);
182
0
      return 0;
183
0
  }
184
0
}
185
186
const EVP_PKEY_CTX_METHOD hkdf_pkey_meth = {
187
    /*pkey_id=*/EVP_PKEY_HKDF,  pkey_hkdf_init,   pkey_hkdf_copy,
188
    pkey_hkdf_cleanup,
189
    /*keygen=*/nullptr,
190
    /*sign=*/nullptr,
191
    /*sign_message=*/nullptr,
192
    /*verify=*/nullptr,
193
    /*verify_message=*/nullptr,
194
    /*verify_recover=*/nullptr,
195
    /*encrypt=*/nullptr,
196
    /*decrypt=*/nullptr,        pkey_hkdf_derive,
197
    /*paramgen=*/nullptr,       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, nullptr);
203
0
}
204
205
0
int EVP_PKEY_CTX_set_hkdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
206
0
  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_HKDF, EVP_PKEY_OP_DERIVE,
207
0
                           EVP_PKEY_CTRL_HKDF_MD, 0, (void *)md);
208
0
}
209
210
int EVP_PKEY_CTX_set1_hkdf_key(EVP_PKEY_CTX *ctx, const uint8_t *key,
211
0
                               size_t key_len) {
212
0
  CBS cbs;
213
0
  CBS_init(&cbs, key, key_len);
214
0
  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_HKDF, EVP_PKEY_OP_DERIVE,
215
0
                           EVP_PKEY_CTRL_HKDF_KEY, 0, &cbs);
216
0
}
217
218
int EVP_PKEY_CTX_set1_hkdf_salt(EVP_PKEY_CTX *ctx, const uint8_t *salt,
219
0
                                size_t salt_len) {
220
0
  CBS cbs;
221
0
  CBS_init(&cbs, salt, salt_len);
222
0
  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_HKDF, EVP_PKEY_OP_DERIVE,
223
0
                           EVP_PKEY_CTRL_HKDF_SALT, 0, &cbs);
224
0
}
225
226
int EVP_PKEY_CTX_add1_hkdf_info(EVP_PKEY_CTX *ctx, const uint8_t *info,
227
0
                                size_t info_len) {
228
0
  CBS cbs;
229
0
  CBS_init(&cbs, info, info_len);
230
0
  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_HKDF, EVP_PKEY_OP_DERIVE,
231
0
                           EVP_PKEY_CTRL_HKDF_INFO, 0, &cbs);
232
0
}