Coverage Report

Created: 2026-06-28 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/evp/p_mlkem.cc
Line
Count
Source
1
// Copyright 2026 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 <assert.h>
18
#include <stddef.h>
19
#include <stdint.h>
20
21
#include <type_traits>
22
23
#include <openssl/bytestring.h>
24
#include <openssl/err.h>
25
#include <openssl/evp_errors.h>
26
#include <openssl/mlkem.h>
27
#include <openssl/nid.h>
28
#include <openssl/span.h>
29
30
#include "../fipsmodule/bcm_interface.h"
31
#include "../internal.h"
32
#include "../mem_internal.h"
33
#include "internal.h"
34
35
using namespace bssl;
36
37
namespace {
38
39
constexpr CBS_ASN1_TAG kSeedTag = CBS_ASN1_CONTEXT_SPECIFIC | 0;
40
41
constexpr uint8_t kMLKEM768OID[] = {OBJ_ENC_ML_KEM_768};
42
constexpr uint8_t kMLKEM1024OID[] = {OBJ_ENC_ML_KEM_1024};
43
44
// Generate EVP bindings for multiple ML-KEM algorithms.
45
#define MAKE_MLKEM_TRAITS(x)                                                   \
46
  struct MLKEM##x##Traits {                                                    \
47
    using PublicKey = MLKEM##x##_public_key;                                   \
48
    using PrivateKey = MLKEM##x##_private_key;                                 \
49
    static constexpr size_t kPublicKeyBytes = MLKEM##x##_PUBLIC_KEY_BYTES;     \
50
    static constexpr size_t kCiphertextBytes = MLKEM##x##_CIPHERTEXT_BYTES;    \
51
    static constexpr int kType = EVP_PKEY_ML_KEM_##x;                          \
52
    static constexpr Span<const uint8_t> kOID = kMLKEM##x##OID;                \
53
    static constexpr auto GenerateKey = &MLKEM##x##_generate_key;              \
54
    static constexpr auto PrivateKeyFromSeed =                                 \
55
        &MLKEM##x##_private_key_from_seed;                                     \
56
    static constexpr auto PublicOfPrivate = &BCM_mlkem##x##_public_of_private; \
57
    static constexpr auto PublicKeysEqual = &BCM_mlkem##x##_public_keys_equal; \
58
    static constexpr auto Encap = &MLKEM##x##_encap;                           \
59
    static constexpr auto Decap = &MLKEM##x##_decap;                           \
60
    static constexpr auto MarshalPublicKey = &MLKEM##x##_marshal_public_key;   \
61
    static constexpr auto ParsePublicKey = &MLKEM##x##_parse_public_key;       \
62
    static_assert(std::is_trivially_copyable_v<PublicKey>,                     \
63
                  "PublicKey type must be trivially copyable.");               \
64
  };
65
66
MAKE_MLKEM_TRAITS(768)
67
MAKE_MLKEM_TRAITS(1024)
68
69
template <typename Traits>
70
class PrivateKeyData;
71
72
// The private key type contains the public key struct in it, so we use a
73
// pointer to either a PrivateKeyData<Traits> or PublicKeyData<Traits>, with a
74
// common base class to dispatch between them.
75
template <typename Traits>
76
class KeyData {
77
 public:
78
  // Returns the underlying public key for the key.
79
  const typename Traits::PublicKey *GetPublicKey() const;
80
81
  // Returns the PrivateKeyData struct for the key, or nullptr if this is a
82
  // public key.
83
  PrivateKeyData<Traits> *AsPrivateKeyData();
84
119
  const PrivateKeyData<Traits> *AsPrivateKeyData() const {
85
119
    return const_cast<KeyData *>(this)->AsPrivateKeyData();
86
119
  }
p_mlkem.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLKEM768Traits>::AsPrivateKeyData() const
Line
Count
Source
84
37
  const PrivateKeyData<Traits> *AsPrivateKeyData() const {
85
37
    return const_cast<KeyData *>(this)->AsPrivateKeyData();
86
37
  }
p_mlkem.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLKEM1024Traits>::AsPrivateKeyData() const
Line
Count
Source
84
82
  const PrivateKeyData<Traits> *AsPrivateKeyData() const {
85
82
    return const_cast<KeyData *>(this)->AsPrivateKeyData();
86
82
  }
87
88
  // A KeyData cannot be freed directly. Rather, it must use this wrapper which
89
  // calls the correct subclass's destructor.
90
  static void Free(KeyData *data);
91
92
 protected:
93
456
  explicit KeyData(bool is_private) : is_private_(is_private) {}
p_mlkem.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLKEM768Traits>::KeyData(bool)
Line
Count
Source
93
207
  explicit KeyData(bool is_private) : is_private_(is_private) {}
p_mlkem.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLKEM1024Traits>::KeyData(bool)
Line
Count
Source
93
249
  explicit KeyData(bool is_private) : is_private_(is_private) {}
94
  ~KeyData() = default;
95
  bool is_private_;
96
};
97
98
template <typename Traits>
99
class PublicKeyData : public KeyData<Traits> {
100
 public:
101
  enum { kAllowUniquePtr = true };
102
302
  PublicKeyData() : KeyData<Traits>(/*is_private=*/false) {}
p_mlkem.cc:(anonymous namespace)::PublicKeyData<(anonymous namespace)::MLKEM768Traits>::PublicKeyData()
Line
Count
Source
102
137
  PublicKeyData() : KeyData<Traits>(/*is_private=*/false) {}
p_mlkem.cc:(anonymous namespace)::PublicKeyData<(anonymous namespace)::MLKEM1024Traits>::PublicKeyData()
Line
Count
Source
102
165
  PublicKeyData() : KeyData<Traits>(/*is_private=*/false) {}
103
104
  // Allows copying the PublicKey.
105
  explicit PublicKeyData(const typename Traits::PublicKey &key)
106
0
      : KeyData<Traits>(/*is_private=*/false), pub(key) {}
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::PublicKeyData<(anonymous namespace)::MLKEM768Traits>::PublicKeyData(MLKEM768_public_key const&)
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::PublicKeyData<(anonymous namespace)::MLKEM1024Traits>::PublicKeyData(MLKEM1024_public_key const&)
107
108
  typename Traits::PublicKey pub;
109
};
110
111
template <typename Traits>
112
class PrivateKeyData : public KeyData<Traits> {
113
 public:
114
  enum { kAllowUniquePtr = true };
115
154
  PrivateKeyData() : KeyData<Traits>(/*is_private=*/true) {}
p_mlkem.cc:(anonymous namespace)::PrivateKeyData<(anonymous namespace)::MLKEM768Traits>::PrivateKeyData()
Line
Count
Source
115
70
  PrivateKeyData() : KeyData<Traits>(/*is_private=*/true) {}
p_mlkem.cc:(anonymous namespace)::PrivateKeyData<(anonymous namespace)::MLKEM1024Traits>::PrivateKeyData()
Line
Count
Source
115
84
  PrivateKeyData() : KeyData<Traits>(/*is_private=*/true) {}
116
  typename Traits::PrivateKey priv;
117
  uint8_t seed[MLKEM_SEED_BYTES];
118
};
119
120
template <typename Traits>
121
29
const typename Traits::PublicKey *KeyData<Traits>::GetPublicKey() const {
122
29
  auto *priv_data = AsPrivateKeyData();
123
29
  if (priv_data != nullptr) {
124
0
    return Traits::PublicOfPrivate(&priv_data->priv);
125
0
  }
126
29
  return &static_cast<const PublicKeyData<Traits> *>(this)->pub;
127
29
}
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLKEM768Traits>::GetPublicKey() const
p_mlkem.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLKEM1024Traits>::GetPublicKey() const
Line
Count
Source
121
29
const typename Traits::PublicKey *KeyData<Traits>::GetPublicKey() const {
122
29
  auto *priv_data = AsPrivateKeyData();
123
29
  if (priv_data != nullptr) {
124
0
    return Traits::PublicOfPrivate(&priv_data->priv);
125
0
  }
126
29
  return &static_cast<const PublicKeyData<Traits> *>(this)->pub;
127
29
}
128
129
template <typename Traits>
130
251
PrivateKeyData<Traits> *KeyData<Traits>::AsPrivateKeyData() {
131
251
  if (is_private_) {
132
180
    return static_cast<PrivateKeyData<Traits> *>(this);
133
180
  }
134
71
  return nullptr;
135
251
}
p_mlkem.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLKEM768Traits>::AsPrivateKeyData()
Line
Count
Source
130
81
PrivateKeyData<Traits> *KeyData<Traits>::AsPrivateKeyData() {
131
81
  if (is_private_) {
132
74
    return static_cast<PrivateKeyData<Traits> *>(this);
133
74
  }
134
7
  return nullptr;
135
81
}
p_mlkem.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLKEM1024Traits>::AsPrivateKeyData()
Line
Count
Source
130
170
PrivateKeyData<Traits> *KeyData<Traits>::AsPrivateKeyData() {
131
170
  if (is_private_) {
132
106
    return static_cast<PrivateKeyData<Traits> *>(this);
133
106
  }
134
64
  return nullptr;
135
170
}
136
137
template <typename Traits>
138
132
void KeyData<Traits>::Free(KeyData<Traits> *data) {
139
132
  if (data == nullptr) {
140
0
    return;
141
0
  }
142
  // Delete the more specific subclass. This is moot for now, because neither
143
  // type has a non-trivial destructor.
144
132
  auto *priv_data = data->AsPrivateKeyData();
145
132
  if (priv_data) {
146
90
    Delete(priv_data);
147
90
  } else {
148
42
    Delete(static_cast<PublicKeyData<Traits> *>(data));
149
42
  }
150
132
}
p_mlkem.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLKEM768Traits>::Free((anonymous namespace)::KeyData<(anonymous namespace)::MLKEM768Traits>*)
Line
Count
Source
138
44
void KeyData<Traits>::Free(KeyData<Traits> *data) {
139
44
  if (data == nullptr) {
140
0
    return;
141
0
  }
142
  // Delete the more specific subclass. This is moot for now, because neither
143
  // type has a non-trivial destructor.
144
44
  auto *priv_data = data->AsPrivateKeyData();
145
44
  if (priv_data) {
146
37
    Delete(priv_data);
147
37
  } else {
148
7
    Delete(static_cast<PublicKeyData<Traits> *>(data));
149
7
  }
150
44
}
p_mlkem.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLKEM1024Traits>::Free((anonymous namespace)::KeyData<(anonymous namespace)::MLKEM1024Traits>*)
Line
Count
Source
138
88
void KeyData<Traits>::Free(KeyData<Traits> *data) {
139
88
  if (data == nullptr) {
140
0
    return;
141
0
  }
142
  // Delete the more specific subclass. This is moot for now, because neither
143
  // type has a non-trivial destructor.
144
88
  auto *priv_data = data->AsPrivateKeyData();
145
88
  if (priv_data) {
146
53
    Delete(priv_data);
147
53
  } else {
148
35
    Delete(static_cast<PublicKeyData<Traits> *>(data));
149
35
  }
150
88
}
151
152
template <typename Traits>
153
struct MLKEMImplementation {
154
251
  static KeyData<Traits> *GetKeyData(EvpPkey *pkey) {
155
251
    assert(pkey->ameth == &asn1_method);
156
251
    return static_cast<KeyData<Traits> *>(pkey->pkey);
157
251
  }
p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::GetKeyData(bssl::EvpPkey*)
Line
Count
Source
154
81
  static KeyData<Traits> *GetKeyData(EvpPkey *pkey) {
155
81
    assert(pkey->ameth == &asn1_method);
156
81
    return static_cast<KeyData<Traits> *>(pkey->pkey);
157
81
  }
p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::GetKeyData(bssl::EvpPkey*)
Line
Count
Source
154
170
  static KeyData<Traits> *GetKeyData(EvpPkey *pkey) {
155
170
    assert(pkey->ameth == &asn1_method);
156
170
    return static_cast<KeyData<Traits> *>(pkey->pkey);
157
170
  }
158
159
119
  static const KeyData<Traits> *GetKeyData(const EvpPkey *pkey) {
160
119
    return GetKeyData(const_cast<EvpPkey *>(pkey));
161
119
  }
p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::GetKeyData(bssl::EvpPkey const*)
Line
Count
Source
159
37
  static const KeyData<Traits> *GetKeyData(const EvpPkey *pkey) {
160
37
    return GetKeyData(const_cast<EvpPkey *>(pkey));
161
37
  }
p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::GetKeyData(bssl::EvpPkey const*)
Line
Count
Source
159
82
  static const KeyData<Traits> *GetKeyData(const EvpPkey *pkey) {
160
82
    return GetKeyData(const_cast<EvpPkey *>(pkey));
161
82
  }
162
163
132
  static void PkeyFree(EvpPkey *pkey) {
164
132
    KeyData<Traits>::Free(GetKeyData(pkey));
165
132
    pkey->pkey = nullptr;
166
132
  }
p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::PkeyFree(bssl::EvpPkey*)
Line
Count
Source
163
44
  static void PkeyFree(EvpPkey *pkey) {
164
44
    KeyData<Traits>::Free(GetKeyData(pkey));
165
44
    pkey->pkey = nullptr;
166
44
  }
p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::PkeyFree(bssl::EvpPkey*)
Line
Count
Source
163
88
  static void PkeyFree(EvpPkey *pkey) {
164
88
    KeyData<Traits>::Free(GetKeyData(pkey));
165
88
    pkey->pkey = nullptr;
166
88
  }
167
168
154
  static int SetPrivateSeed(EvpPkey *pkey, const uint8_t *in, size_t len) {
169
154
    auto priv = MakeUnique<PrivateKeyData<Traits>>();
170
154
    if (priv == nullptr) {
171
0
      return 0;
172
0
    }
173
174
154
    if (len != MLKEM_SEED_BYTES ||
175
90
        !Traits::PrivateKeyFromSeed(&priv->priv, in, len)) {
176
64
      OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
177
64
      return 0;
178
64
    }
179
90
    OPENSSL_memcpy(priv->seed, in, len);
180
90
    evp_pkey_set0(pkey, &asn1_method, priv.release());
181
90
    return 1;
182
154
  }
p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::SetPrivateSeed(bssl::EvpPkey*, unsigned char const*, unsigned long)
Line
Count
Source
168
70
  static int SetPrivateSeed(EvpPkey *pkey, const uint8_t *in, size_t len) {
169
70
    auto priv = MakeUnique<PrivateKeyData<Traits>>();
170
70
    if (priv == nullptr) {
171
0
      return 0;
172
0
    }
173
174
70
    if (len != MLKEM_SEED_BYTES ||
175
37
        !Traits::PrivateKeyFromSeed(&priv->priv, in, len)) {
176
33
      OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
177
33
      return 0;
178
33
    }
179
37
    OPENSSL_memcpy(priv->seed, in, len);
180
37
    evp_pkey_set0(pkey, &asn1_method, priv.release());
181
37
    return 1;
182
70
  }
p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::SetPrivateSeed(bssl::EvpPkey*, unsigned char const*, unsigned long)
Line
Count
Source
168
84
  static int SetPrivateSeed(EvpPkey *pkey, const uint8_t *in, size_t len) {
169
84
    auto priv = MakeUnique<PrivateKeyData<Traits>>();
170
84
    if (priv == nullptr) {
171
0
      return 0;
172
0
    }
173
174
84
    if (len != MLKEM_SEED_BYTES ||
175
53
        !Traits::PrivateKeyFromSeed(&priv->priv, in, len)) {
176
31
      OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
177
31
      return 0;
178
31
    }
179
53
    OPENSSL_memcpy(priv->seed, in, len);
180
53
    evp_pkey_set0(pkey, &asn1_method, priv.release());
181
53
    return 1;
182
84
  }
183
184
302
  static int SetRawPublic(EvpPkey *pkey, const uint8_t *in, size_t len) {
185
302
    auto pub = MakeUnique<PublicKeyData<Traits>>();
186
302
    if (pub == nullptr) {
187
0
      return 0;
188
0
    }
189
302
    CBS cbs;
190
302
    CBS_init(&cbs, in, len);
191
302
    if (!Traits::ParsePublicKey(&pub->pub, &cbs) || CBS_len(&cbs) != 0) {
192
260
      OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
193
260
      return 0;
194
260
    }
195
42
    evp_pkey_set0(pkey, &asn1_method, pub.release());
196
42
    return 1;
197
302
  }
p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::SetRawPublic(bssl::EvpPkey*, unsigned char const*, unsigned long)
Line
Count
Source
184
137
  static int SetRawPublic(EvpPkey *pkey, const uint8_t *in, size_t len) {
185
137
    auto pub = MakeUnique<PublicKeyData<Traits>>();
186
137
    if (pub == nullptr) {
187
0
      return 0;
188
0
    }
189
137
    CBS cbs;
190
137
    CBS_init(&cbs, in, len);
191
137
    if (!Traits::ParsePublicKey(&pub->pub, &cbs) || CBS_len(&cbs) != 0) {
192
130
      OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
193
130
      return 0;
194
130
    }
195
7
    evp_pkey_set0(pkey, &asn1_method, pub.release());
196
7
    return 1;
197
137
  }
p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::SetRawPublic(bssl::EvpPkey*, unsigned char const*, unsigned long)
Line
Count
Source
184
165
  static int SetRawPublic(EvpPkey *pkey, const uint8_t *in, size_t len) {
185
165
    auto pub = MakeUnique<PublicKeyData<Traits>>();
186
165
    if (pub == nullptr) {
187
0
      return 0;
188
0
    }
189
165
    CBS cbs;
190
165
    CBS_init(&cbs, in, len);
191
165
    if (!Traits::ParsePublicKey(&pub->pub, &cbs) || CBS_len(&cbs) != 0) {
192
130
      OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
193
130
      return 0;
194
130
    }
195
35
    evp_pkey_set0(pkey, &asn1_method, pub.release());
196
35
    return 1;
197
165
  }
198
199
  static int GetPrivateSeed(const EvpPkey *pkey, uint8_t *out,
200
0
                            size_t *out_len) {
201
0
    const auto *priv = GetKeyData(pkey)->AsPrivateKeyData();
202
0
    if (priv == nullptr) {
203
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY);
204
0
      return 0;
205
0
    }
206
0
    if (out == nullptr) {
207
0
      *out_len = MLKEM_SEED_BYTES;
208
0
      return 1;
209
0
    }
210
0
    if (*out_len < MLKEM_SEED_BYTES) {
211
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
212
0
      return 0;
213
0
    }
214
0
    OPENSSL_memcpy(out, priv->seed, MLKEM_SEED_BYTES);
215
0
    *out_len = MLKEM_SEED_BYTES;
216
0
    return 1;
217
0
  }
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::GetPrivateSeed(bssl::EvpPkey const*, unsigned char*, unsigned long*)
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::GetPrivateSeed(bssl::EvpPkey const*, unsigned char*, unsigned long*)
218
219
0
  static int GetRawPublic(const EvpPkey *pkey, uint8_t *out, size_t *out_len) {
220
0
    const auto *pub = GetKeyData(pkey)->GetPublicKey();
221
0
    if (out == nullptr) {
222
0
      *out_len = Traits::kPublicKeyBytes;
223
0
      return 1;
224
0
    }
225
0
    if (*out_len < Traits::kPublicKeyBytes) {
226
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
227
0
      return 0;
228
0
    }
229
0
    CBB cbb;
230
0
    CBB_init_fixed(&cbb, out, Traits::kPublicKeyBytes);
231
0
    BSSL_CHECK(Traits::MarshalPublicKey(&cbb, pub));
232
0
    BSSL_CHECK(CBB_len(&cbb) == Traits::kPublicKeyBytes);
233
0
    *out_len = Traits::kPublicKeyBytes;
234
0
    return 1;
235
0
  }
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::GetRawPublic(bssl::EvpPkey const*, unsigned char*, unsigned long*)
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::GetRawPublic(bssl::EvpPkey const*, unsigned char*, unsigned long*)
236
237
  static evp_decode_result_t DecodePublic(const EVP_PKEY_ALG *alg, EvpPkey *out,
238
432
                                          CBS *params, CBS *key) {
239
    // Parameters must be absent. See RFC 9935, section 3.
240
432
    if (CBS_len(params) != 0) {
241
130
      OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
242
130
      return evp_decode_error;
243
130
    }
244
302
    return SetRawPublic(out, CBS_data(key), CBS_len(key)) ? evp_decode_ok
245
302
                                                          : evp_decode_error;
246
432
  }
p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::DecodePublic(evp_pkey_alg_st const*, bssl::EvpPkey*, cbs_st*, cbs_st*)
Line
Count
Source
238
190
                                          CBS *params, CBS *key) {
239
    // Parameters must be absent. See RFC 9935, section 3.
240
190
    if (CBS_len(params) != 0) {
241
53
      OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
242
53
      return evp_decode_error;
243
53
    }
244
137
    return SetRawPublic(out, CBS_data(key), CBS_len(key)) ? evp_decode_ok
245
137
                                                          : evp_decode_error;
246
190
  }
p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::DecodePublic(evp_pkey_alg_st const*, bssl::EvpPkey*, cbs_st*, cbs_st*)
Line
Count
Source
238
242
                                          CBS *params, CBS *key) {
239
    // Parameters must be absent. See RFC 9935, section 3.
240
242
    if (CBS_len(params) != 0) {
241
77
      OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
242
77
      return evp_decode_error;
243
77
    }
244
165
    return SetRawPublic(out, CBS_data(key), CBS_len(key)) ? evp_decode_ok
245
165
                                                          : evp_decode_error;
246
242
  }
247
248
29
  static int EncodePublic(CBB *out, const EvpPkey *pkey) {
249
29
    const auto *pub = GetKeyData(pkey)->GetPublicKey();
250
    // See RFC 9935, section 4.
251
29
    CBB spki, algorithm, key_bitstring;
252
29
    if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
253
29
        !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
254
29
        !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, Traits::kOID.data(),
255
29
                              Traits::kOID.size()) ||
256
29
        !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
257
29
        !CBB_add_u8(&key_bitstring, 0 /* no unused bits */) ||
258
29
        !Traits::MarshalPublicKey(&key_bitstring, pub) ||  //
259
29
        !CBB_flush(out)) {
260
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
261
0
      return 0;
262
0
    }
263
29
    return 1;
264
29
  }
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::EncodePublic(cbb_st*, bssl::EvpPkey const*)
p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::EncodePublic(cbb_st*, bssl::EvpPkey const*)
Line
Count
Source
248
29
  static int EncodePublic(CBB *out, const EvpPkey *pkey) {
249
29
    const auto *pub = GetKeyData(pkey)->GetPublicKey();
250
    // See RFC 9935, section 4.
251
29
    CBB spki, algorithm, key_bitstring;
252
29
    if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
253
29
        !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
254
29
        !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, Traits::kOID.data(),
255
29
                              Traits::kOID.size()) ||
256
29
        !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
257
29
        !CBB_add_u8(&key_bitstring, 0 /* no unused bits */) ||
258
29
        !Traits::MarshalPublicKey(&key_bitstring, pub) ||  //
259
29
        !CBB_flush(out)) {
260
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
261
0
      return 0;
262
0
    }
263
29
    return 1;
264
29
  }
265
266
0
  static bool EqualPublic(const EvpPkey *a, const EvpPkey *b) {
267
0
    const auto *a_pub = GetKeyData(a)->GetPublicKey();
268
0
    const auto *b_pub = GetKeyData(b)->GetPublicKey();
269
0
    return Traits::PublicKeysEqual(a_pub, b_pub);
270
0
  }
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::EqualPublic(bssl::EvpPkey const*, bssl::EvpPkey const*)
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::EqualPublic(bssl::EvpPkey const*, bssl::EvpPkey const*)
271
272
0
  static bool HasPublic(const EvpPkey *pk) { return true; }
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::HasPublic(bssl::EvpPkey const*)
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::HasPublic(bssl::EvpPkey const*)
273
274
0
  static bool CopyPublic(EvpPkey *out, const EvpPkey *pk) {
275
0
    auto *public_copy =
276
0
        New<PublicKeyData<Traits>>(*GetKeyData(pk)->GetPublicKey());
277
0
    if (public_copy == nullptr) {
278
0
      return false;
279
0
    }
280
0
    evp_pkey_set0(out, pk->ameth, public_copy);
281
0
    return true;
282
0
  }
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::CopyPublic(bssl::EvpPkey*, bssl::EvpPkey const*)
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::CopyPublic(bssl::EvpPkey*, bssl::EvpPkey const*)
283
284
  static evp_decode_result_t DecodePrivate(const EVP_PKEY_ALG *alg,
285
                                           EvpPkey *out, CBS *params,
286
230
                                           CBS *key) {
287
    // Parameters must be absent. See RFC 9935, section 3.
288
230
    if (CBS_len(params) != 0) {
289
30
      OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
290
30
      return evp_decode_error;
291
30
    }
292
293
    // See RFC 9935, section 6. Three different encodings are specified. We only
294
    // implement the "seed" representation.
295
200
    CBS seed;
296
200
    if (!CBS_get_asn1(key, &seed, kSeedTag)) {
297
9
      OPENSSL_PUT_ERROR(EVP, EVP_R_PRIVATE_KEY_WAS_NOT_SEED);
298
9
      return evp_decode_error;
299
9
    }
300
191
    if (CBS_len(key) != 0) {
301
37
      OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
302
37
      return evp_decode_error;
303
37
    }
304
154
    return SetPrivateSeed(out, CBS_data(&seed), CBS_len(&seed))
305
154
               ? evp_decode_ok
306
154
               : evp_decode_error;
307
191
  }
p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::DecodePrivate(evp_pkey_alg_st const*, bssl::EvpPkey*, cbs_st*, cbs_st*)
Line
Count
Source
286
98
                                           CBS *key) {
287
    // Parameters must be absent. See RFC 9935, section 3.
288
98
    if (CBS_len(params) != 0) {
289
11
      OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
290
11
      return evp_decode_error;
291
11
    }
292
293
    // See RFC 9935, section 6. Three different encodings are specified. We only
294
    // implement the "seed" representation.
295
87
    CBS seed;
296
87
    if (!CBS_get_asn1(key, &seed, kSeedTag)) {
297
4
      OPENSSL_PUT_ERROR(EVP, EVP_R_PRIVATE_KEY_WAS_NOT_SEED);
298
4
      return evp_decode_error;
299
4
    }
300
83
    if (CBS_len(key) != 0) {
301
13
      OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
302
13
      return evp_decode_error;
303
13
    }
304
70
    return SetPrivateSeed(out, CBS_data(&seed), CBS_len(&seed))
305
70
               ? evp_decode_ok
306
70
               : evp_decode_error;
307
83
  }
p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::DecodePrivate(evp_pkey_alg_st const*, bssl::EvpPkey*, cbs_st*, cbs_st*)
Line
Count
Source
286
132
                                           CBS *key) {
287
    // Parameters must be absent. See RFC 9935, section 3.
288
132
    if (CBS_len(params) != 0) {
289
19
      OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
290
19
      return evp_decode_error;
291
19
    }
292
293
    // See RFC 9935, section 6. Three different encodings are specified. We only
294
    // implement the "seed" representation.
295
113
    CBS seed;
296
113
    if (!CBS_get_asn1(key, &seed, kSeedTag)) {
297
5
      OPENSSL_PUT_ERROR(EVP, EVP_R_PRIVATE_KEY_WAS_NOT_SEED);
298
5
      return evp_decode_error;
299
5
    }
300
108
    if (CBS_len(key) != 0) {
301
24
      OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
302
24
      return evp_decode_error;
303
24
    }
304
84
    return SetPrivateSeed(out, CBS_data(&seed), CBS_len(&seed))
305
84
               ? evp_decode_ok
306
84
               : evp_decode_error;
307
108
  }
308
309
90
  static int EncodePrivate(CBB *out, const EvpPkey *pkey) {
310
90
    const auto *priv = GetKeyData(pkey)->AsPrivateKeyData();
311
90
    if (priv == nullptr) {
312
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY);
313
0
      return 0;
314
0
    }
315
316
    // See RFC 9935, section 6. Three different encodings are specified. We only
317
    // implement the "seed" representation.
318
90
    CBB pkcs8, algorithm, private_key;
319
90
    if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
320
90
        !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
321
90
        !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
322
90
        !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, Traits::kOID.data(),
323
90
                              Traits::kOID.size()) ||
324
90
        !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
325
90
        !CBB_add_asn1_element(&private_key, kSeedTag, priv->seed,
326
90
                              sizeof(priv->seed)) ||
327
90
        !CBB_flush(out)) {
328
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
329
0
      return 0;
330
0
    }
331
90
    return 1;
332
90
  }
p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::EncodePrivate(cbb_st*, bssl::EvpPkey const*)
Line
Count
Source
309
37
  static int EncodePrivate(CBB *out, const EvpPkey *pkey) {
310
37
    const auto *priv = GetKeyData(pkey)->AsPrivateKeyData();
311
37
    if (priv == nullptr) {
312
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY);
313
0
      return 0;
314
0
    }
315
316
    // See RFC 9935, section 6. Three different encodings are specified. We only
317
    // implement the "seed" representation.
318
37
    CBB pkcs8, algorithm, private_key;
319
37
    if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
320
37
        !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
321
37
        !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
322
37
        !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, Traits::kOID.data(),
323
37
                              Traits::kOID.size()) ||
324
37
        !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
325
37
        !CBB_add_asn1_element(&private_key, kSeedTag, priv->seed,
326
37
                              sizeof(priv->seed)) ||
327
37
        !CBB_flush(out)) {
328
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
329
0
      return 0;
330
0
    }
331
37
    return 1;
332
37
  }
p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::EncodePrivate(cbb_st*, bssl::EvpPkey const*)
Line
Count
Source
309
53
  static int EncodePrivate(CBB *out, const EvpPkey *pkey) {
310
53
    const auto *priv = GetKeyData(pkey)->AsPrivateKeyData();
311
53
    if (priv == nullptr) {
312
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY);
313
0
      return 0;
314
0
    }
315
316
    // See RFC 9935, section 6. Three different encodings are specified. We only
317
    // implement the "seed" representation.
318
53
    CBB pkcs8, algorithm, private_key;
319
53
    if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
320
53
        !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
321
53
        !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
322
53
        !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, Traits::kOID.data(),
323
53
                              Traits::kOID.size()) ||
324
53
        !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
325
53
        !CBB_add_asn1_element(&private_key, kSeedTag, priv->seed,
326
53
                              sizeof(priv->seed)) ||
327
53
        !CBB_flush(out)) {
328
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
329
0
      return 0;
330
0
    }
331
53
    return 1;
332
53
  }
333
334
0
  static bool HasPrivate(const EvpPkey *pk) {
335
0
    return GetKeyData(pk)->AsPrivateKeyData() != nullptr;
336
0
  }
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::HasPrivate(bssl::EvpPkey const*)
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::HasPrivate(bssl::EvpPkey const*)
337
338
0
  static int PkeySize(const EvpPkey *pkey) { return Traits::kCiphertextBytes; }
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::PkeySize(bssl::EvpPkey const*)
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::PkeySize(bssl::EvpPkey const*)
339
0
  static int PkeyBits(const EvpPkey *pkey) {
340
0
    return Traits::kPublicKeyBytes * 8;
341
0
  }
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::PkeyBits(bssl::EvpPkey const*)
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::PkeyBits(bssl::EvpPkey const*)
342
343
0
  static int CopyCtx(EvpPkeyCtx *dst, EvpPkeyCtx *src) { return 1; }
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::CopyCtx(bssl::EvpPkeyCtx*, bssl::EvpPkeyCtx*)
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::CopyCtx(bssl::EvpPkeyCtx*, bssl::EvpPkeyCtx*)
344
345
0
  static int KeyGen(EvpPkeyCtx *ctx, EvpPkey *pkey) {
346
0
    auto priv = MakeUnique<PrivateKeyData<Traits>>();
347
0
    if (priv == nullptr) {
348
0
      OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR);
349
0
      return 0;
350
0
    }
351
0
    uint8_t unused_public[Traits::kPublicKeyBytes];
352
0
    Traits::GenerateKey(unused_public, priv->seed, &priv->priv);
353
0
    evp_pkey_set0(pkey, &asn1_method, priv.release());
354
0
    return 1;
355
0
  }
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::KeyGen(bssl::EvpPkeyCtx*, bssl::EvpPkey*)
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::KeyGen(bssl::EvpPkeyCtx*, bssl::EvpPkey*)
356
357
  static int KemEncap(uint8_t *out_ciphertext, size_t ciphertext_len,
358
                      uint8_t *out_secret, size_t secret_len,
359
0
                      const EVP_PKEY *peer_key) {
360
0
    const auto *peer_pubkey = GetKeyData(FromOpaque(peer_key))->GetPublicKey();
361
0
    if (ciphertext_len != Traits::kCiphertextBytes) {
362
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_CIPHERTEXT_LENGTH);
363
0
      return 0;
364
0
    }
365
0
    if (secret_len != MLKEM_SHARED_SECRET_BYTES) {
366
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_SECRET_LENGTH);
367
0
      return 0;
368
0
    }
369
0
    Traits::Encap(out_ciphertext, out_secret, peer_pubkey);
370
0
    return 1;
371
0
  }
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::KemEncap(unsigned char*, unsigned long, unsigned char*, unsigned long, evp_pkey_st const*)
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::KemEncap(unsigned char*, unsigned long, unsigned char*, unsigned long, evp_pkey_st const*)
372
373
  static int KemDecap(uint8_t *out_secret, size_t secret_len,
374
                      const uint8_t *ciphertext, size_t ciphertext_len,
375
0
                      const EVP_PKEY *key) {
376
0
    const auto *priv = GetKeyData(FromOpaque(key))->AsPrivateKeyData();
377
0
    if (priv == nullptr) {
378
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY);
379
0
      return 0;
380
0
    }
381
0
    if (secret_len != MLKEM_SHARED_SECRET_BYTES) {
382
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_SECRET_LENGTH);
383
0
      return 0;
384
0
    }
385
0
    return Traits::Decap(out_secret, ciphertext, ciphertext_len, &priv->priv);
386
0
  }
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::KemDecap(unsigned char*, unsigned long, unsigned char const*, unsigned long, evp_pkey_st const*)
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::KemDecap(unsigned char*, unsigned long, unsigned char const*, unsigned long, evp_pkey_st const*)
387
388
  static constexpr EVP_KEM evp_kem = {
389
      /*pkey_id=*/Traits::kType,
390
      /*ciphertext_len=*/Traits::kCiphertextBytes,
391
      /*secret_len=*/MLKEM_SHARED_SECRET_BYTES,
392
      &KemEncap,
393
      &KemDecap,
394
  };
395
396
  static constexpr EVP_PKEY_CTX_METHOD pkey_method = {
397
      Traits::kType,
398
      /*init=*/nullptr,
399
      &CopyCtx,
400
      /*cleanup=*/nullptr,
401
      &KeyGen,
402
      /*sign=*/nullptr,
403
      /*sign_message=*/nullptr,
404
      /*verify=*/nullptr,
405
      /*verify_message=*/nullptr,
406
      /*verify_recover=*/nullptr,
407
      /*encrypt=*/nullptr,
408
      /*decrypt=*/nullptr,
409
      /*derive=*/nullptr,
410
      /*paramgen=*/nullptr,
411
      &KemAdapter<evp_kem>::EncapMethod,
412
      &KemAdapter<evp_kem>::DecapMethod,
413
      /*ctrl=*/nullptr,
414
  };
415
416
0
  static constexpr EVP_PKEY_ASN1_METHOD BuildASN1Method() {
417
0
    EVP_PKEY_ASN1_METHOD ret = {
418
0
        Traits::kType,
419
0
        // The OID is filled in below.
420
0
        /*oid=*/{},
421
0
        /*oid_len=*/0,
422
0
423
0
        &pkey_method,
424
0
425
0
        &DecodePublic,
426
0
        &EncodePublic,
427
0
        &EqualPublic,
428
0
        &HasPublic,
429
0
        &CopyPublic,
430
0
        &DecodePrivate,
431
0
        &EncodePrivate,
432
0
        &HasPrivate,
433
0
434
0
        /*set_priv_raw=*/nullptr,
435
0
        &SetPrivateSeed,
436
0
        &SetRawPublic,
437
0
        /*get_priv_raw=*/nullptr,
438
0
        &GetPrivateSeed,
439
0
        &GetRawPublic,
440
0
441
0
        /*set1_tls_encodedpoint=*/nullptr,
442
0
        /*get1_tls_encodedpoint=*/nullptr,
443
0
        /*pkey_opaque=*/nullptr,
444
0
        &PkeySize,
445
0
        &PkeyBits,
446
0
447
0
        /*param_missing=*/nullptr,
448
0
        /*param_copy=*/nullptr,
449
0
        /*param_equal=*/nullptr,
450
0
451
0
        &PkeyFree,
452
0
    };
453
0
    // TODO(crbug.com/404286922): Use std::copy in C++20, when it's constexpr.
454
0
    // TODO(crbug.com/450823446): Better yet, make this field an InplaceVector
455
0
    // and give it a suitable constructor.
456
0
    constexpr auto oid = Traits::kOID;
457
0
    static_assert(oid.size() <= sizeof(ret.oid));
458
0
    for (size_t i = 0; i < oid.size(); i++) {
459
0
      ret.oid[i] = oid[i];
460
0
    }
461
0
    ret.oid_len = oid.size();
462
0
    return ret;
463
0
  }
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM768Traits>::BuildASN1Method()
Unexecuted instantiation: p_mlkem.cc:(anonymous namespace)::MLKEMImplementation<(anonymous namespace)::MLKEM1024Traits>::BuildASN1Method()
464
465
  static constexpr EVP_PKEY_ASN1_METHOD asn1_method = BuildASN1Method();
466
  static constexpr EVP_PKEY_ALG pkey_alg = {&asn1_method, &pkey_method};
467
};
468
469
}  // namespace
470
471
209k
const EVP_PKEY_ALG *EVP_pkey_ml_kem_768() {
472
209k
  return &MLKEMImplementation<MLKEM768Traits>::pkey_alg;
473
209k
}
474
475
209k
const EVP_PKEY_ALG *EVP_pkey_ml_kem_1024() {
476
209k
  return &MLKEMImplementation<MLKEM1024Traits>::pkey_alg;
477
209k
}
478
479
0
const EVP_KEM *EVP_kem_ml_kem_768() {
480
0
  return &MLKEMImplementation<MLKEM768Traits>::evp_kem;
481
0
}
482
483
0
const EVP_KEM *EVP_kem_ml_kem_1024() {
484
0
  return &MLKEMImplementation<MLKEM1024Traits>::evp_kem;
485
0
}