/src/boringssl/crypto/evp/p_mldsa.cc
Line | Count | Source |
1 | | // Copyright 2025 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 | | |
19 | | #include <type_traits> |
20 | | |
21 | | #include <openssl/bytestring.h> |
22 | | #include <openssl/err.h> |
23 | | #include <openssl/mldsa.h> |
24 | | #include <openssl/nid.h> |
25 | | #include <openssl/span.h> |
26 | | |
27 | | #include "../fipsmodule/bcm_interface.h" |
28 | | #include "../mem_internal.h" |
29 | | #include "internal.h" |
30 | | |
31 | | using namespace bssl; |
32 | | |
33 | | namespace { |
34 | | |
35 | | constexpr CBS_ASN1_TAG kSeedTag = CBS_ASN1_CONTEXT_SPECIFIC | 0; |
36 | | |
37 | | constexpr uint8_t kMLDSA44OID[] = {OBJ_ENC_ML_DSA_44}; |
38 | | constexpr uint8_t kMLDSA65OID[] = {OBJ_ENC_ML_DSA_65}; |
39 | | constexpr uint8_t kMLDSA87OID[] = {OBJ_ENC_ML_DSA_87}; |
40 | | |
41 | | constexpr int kMaxContextLength = 255; |
42 | | |
43 | | // We must generate EVP bindings for three ML-DSA algorithms. Define a traits |
44 | | // type that captures the functions and other parameters of an ML-DSA algorithm. |
45 | | #define MAKE_MLDSA_TRAITS(kl) \ |
46 | | struct MLDSA##kl##Traits { \ |
47 | | using PublicKey = MLDSA##kl##_public_key; \ |
48 | | using PrivateKey = MLDSA##kl##_private_key; \ |
49 | | static constexpr size_t kPublicKeyBytes = MLDSA##kl##_PUBLIC_KEY_BYTES; \ |
50 | | static constexpr size_t kSignatureBytes = MLDSA##kl##_SIGNATURE_BYTES; \ |
51 | | static constexpr int kType = EVP_PKEY_ML_DSA_##kl; \ |
52 | | static constexpr Span<const uint8_t> kOID = kMLDSA##kl##OID; \ |
53 | | static constexpr auto PrivateKeyFromSeed = \ |
54 | | &MLDSA##kl##_private_key_from_seed; \ |
55 | | static constexpr auto GenerateKey = &MLDSA##kl##_generate_key; \ |
56 | | static constexpr auto Sign = &MLDSA##kl##_sign; \ |
57 | | static constexpr auto ParsePublicKey = &MLDSA##kl##_parse_public_key; \ |
58 | | static constexpr auto PublicOfPrivate = \ |
59 | | &BCM_mldsa##kl##_public_of_private; \ |
60 | | static constexpr auto MarshalPublicKey = &MLDSA##kl##_marshal_public_key; \ |
61 | | static constexpr auto PublicKeysEqual = \ |
62 | | &BCM_mldsa##kl##_public_keys_equal; \ |
63 | | static constexpr auto Verify = &MLDSA##kl##_verify; \ |
64 | | static_assert(std::is_trivially_copyable_v<PublicKey>, \ |
65 | | "PublicKey type must be trivially copyable."); \ |
66 | | }; |
67 | | |
68 | | MAKE_MLDSA_TRAITS(44) |
69 | | MAKE_MLDSA_TRAITS(65) |
70 | | MAKE_MLDSA_TRAITS(87) |
71 | | |
72 | | // For each ML-DSA variant, the |EvpPkey| must hold a public or private key. |
73 | | // EVP uses the same type for public and private keys, so the representation |
74 | | // must support both. The private key type contains the public key struct in it, |
75 | | // so we use a pointer to either a PrivateKeyData<Traits> or |
76 | | // PublicKeyData<Traits>, with a common base class to dispatch between them. |
77 | | // |
78 | | // TODO(crbug.com/404286922): In C++20, we need fewer |typename|s in front of |
79 | | // dependent type names. |
80 | | |
81 | | template <typename Traits> |
82 | | class PrivateKeyData; |
83 | | |
84 | | template <typename Traits> |
85 | | class KeyData { |
86 | | public: |
87 | | // Returns the underlying public key for the key. |
88 | | const typename Traits::PublicKey *GetPublicKey() const; |
89 | | |
90 | | // Returns the PrivateKeyData struct for the key, or nullptr if this is a |
91 | | // public key. |
92 | | PrivateKeyData<Traits> *AsPrivateKeyData(); |
93 | 528 | const PrivateKeyData<Traits> *AsPrivateKeyData() const { |
94 | 528 | return const_cast<KeyData *>(this)->AsPrivateKeyData(); |
95 | 528 | } p_mldsa.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLDSA44Traits>::AsPrivateKeyData() const Line | Count | Source | 93 | 175 | const PrivateKeyData<Traits> *AsPrivateKeyData() const { | 94 | 175 | return const_cast<KeyData *>(this)->AsPrivateKeyData(); | 95 | 175 | } |
p_mldsa.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLDSA65Traits>::AsPrivateKeyData() const Line | Count | Source | 93 | 163 | const PrivateKeyData<Traits> *AsPrivateKeyData() const { | 94 | 163 | return const_cast<KeyData *>(this)->AsPrivateKeyData(); | 95 | 163 | } |
p_mldsa.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLDSA87Traits>::AsPrivateKeyData() const Line | Count | Source | 93 | 190 | const PrivateKeyData<Traits> *AsPrivateKeyData() const { | 94 | 190 | return const_cast<KeyData *>(this)->AsPrivateKeyData(); | 95 | 190 | } |
|
96 | | |
97 | | // A KeyData cannot be freed directly. Rather, it must use this wrapper which |
98 | | // calls the correct subclass's destructor. |
99 | | static void Free(KeyData *data); |
100 | | |
101 | | protected: |
102 | 485 | explicit KeyData(bool is_private) : is_private_(is_private) {}p_mldsa.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLDSA44Traits>::KeyData(bool) Line | Count | Source | 102 | 162 | explicit KeyData(bool is_private) : is_private_(is_private) {} |
p_mldsa.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLDSA65Traits>::KeyData(bool) Line | Count | Source | 102 | 156 | explicit KeyData(bool is_private) : is_private_(is_private) {} |
p_mldsa.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLDSA87Traits>::KeyData(bool) Line | Count | Source | 102 | 167 | explicit KeyData(bool is_private) : is_private_(is_private) {} |
|
103 | | ~KeyData() = default; |
104 | | bool is_private_; |
105 | | }; |
106 | | |
107 | | template <typename Traits> |
108 | | class PublicKeyData : public KeyData<Traits> { |
109 | | public: |
110 | | enum { kAllowUniquePtr = true }; |
111 | 71 | PublicKeyData() : KeyData<Traits>(/*is_private=*/false) {}p_mldsa.cc:(anonymous namespace)::PublicKeyData<(anonymous namespace)::MLDSA44Traits>::PublicKeyData() Line | Count | Source | 111 | 24 | PublicKeyData() : KeyData<Traits>(/*is_private=*/false) {} |
p_mldsa.cc:(anonymous namespace)::PublicKeyData<(anonymous namespace)::MLDSA65Traits>::PublicKeyData() Line | Count | Source | 111 | 20 | PublicKeyData() : KeyData<Traits>(/*is_private=*/false) {} |
p_mldsa.cc:(anonymous namespace)::PublicKeyData<(anonymous namespace)::MLDSA87Traits>::PublicKeyData() Line | Count | Source | 111 | 27 | PublicKeyData() : KeyData<Traits>(/*is_private=*/false) {} |
|
112 | | |
113 | | // Allows copying the PublicKey. |
114 | | explicit PublicKeyData(const typename Traits::PublicKey &key) |
115 | 0 | : KeyData<Traits>(/*is_private=*/false), pub(key) {}Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::PublicKeyData<(anonymous namespace)::MLDSA44Traits>::PublicKeyData(MLDSA44_public_key const&) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::PublicKeyData<(anonymous namespace)::MLDSA65Traits>::PublicKeyData(MLDSA65_public_key const&) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::PublicKeyData<(anonymous namespace)::MLDSA87Traits>::PublicKeyData(MLDSA87_public_key const&) |
116 | | |
117 | | typename Traits::PublicKey pub; |
118 | | }; |
119 | | |
120 | | template <typename Traits> |
121 | | class PrivateKeyData : public KeyData<Traits> { |
122 | | public: |
123 | | enum { kAllowUniquePtr = true }; |
124 | 414 | PrivateKeyData() : KeyData<Traits>(/*is_private=*/true) {}p_mldsa.cc:(anonymous namespace)::PrivateKeyData<(anonymous namespace)::MLDSA44Traits>::PrivateKeyData() Line | Count | Source | 124 | 138 | PrivateKeyData() : KeyData<Traits>(/*is_private=*/true) {} |
p_mldsa.cc:(anonymous namespace)::PrivateKeyData<(anonymous namespace)::MLDSA65Traits>::PrivateKeyData() Line | Count | Source | 124 | 136 | PrivateKeyData() : KeyData<Traits>(/*is_private=*/true) {} |
p_mldsa.cc:(anonymous namespace)::PrivateKeyData<(anonymous namespace)::MLDSA87Traits>::PrivateKeyData() Line | Count | Source | 124 | 140 | PrivateKeyData() : KeyData<Traits>(/*is_private=*/true) {} |
|
125 | | typename Traits::PrivateKey priv; |
126 | | uint8_t seed[MLDSA_SEED_BYTES]; |
127 | | }; |
128 | | |
129 | | template <typename Traits> |
130 | 185 | const typename Traits::PublicKey *KeyData<Traits>::GetPublicKey() const { |
131 | 185 | auto *priv_data = AsPrivateKeyData(); |
132 | 185 | if (priv_data != nullptr) { |
133 | 178 | return Traits::PublicOfPrivate(&priv_data->priv); |
134 | 178 | } |
135 | 7 | return &static_cast<const PublicKeyData<Traits> *>(this)->pub; |
136 | 185 | } p_mldsa.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLDSA44Traits>::GetPublicKey() const Line | Count | Source | 130 | 70 | const typename Traits::PublicKey *KeyData<Traits>::GetPublicKey() const { | 131 | 70 | auto *priv_data = AsPrivateKeyData(); | 132 | 70 | if (priv_data != nullptr) { | 133 | 63 | return Traits::PublicOfPrivate(&priv_data->priv); | 134 | 63 | } | 135 | 7 | return &static_cast<const PublicKeyData<Traits> *>(this)->pub; | 136 | 70 | } |
p_mldsa.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLDSA65Traits>::GetPublicKey() const Line | Count | Source | 130 | 54 | const typename Traits::PublicKey *KeyData<Traits>::GetPublicKey() const { | 131 | 54 | auto *priv_data = AsPrivateKeyData(); | 132 | 54 | if (priv_data != nullptr) { | 133 | 54 | return Traits::PublicOfPrivate(&priv_data->priv); | 134 | 54 | } | 135 | 0 | return &static_cast<const PublicKeyData<Traits> *>(this)->pub; | 136 | 54 | } |
p_mldsa.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLDSA87Traits>::GetPublicKey() const Line | Count | Source | 130 | 61 | const typename Traits::PublicKey *KeyData<Traits>::GetPublicKey() const { | 131 | 61 | auto *priv_data = AsPrivateKeyData(); | 132 | 61 | if (priv_data != nullptr) { | 133 | 61 | return Traits::PublicOfPrivate(&priv_data->priv); | 134 | 61 | } | 135 | 0 | return &static_cast<const PublicKeyData<Traits> *>(this)->pub; | 136 | 61 | } |
|
137 | | |
138 | | template <typename Traits> |
139 | 881 | PrivateKeyData<Traits> *KeyData<Traits>::AsPrivateKeyData() { |
140 | 881 | if (is_private_) { |
141 | 864 | return static_cast<PrivateKeyData<Traits> *>(this); |
142 | 864 | } |
143 | 17 | return nullptr; |
144 | 881 | } p_mldsa.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLDSA44Traits>::AsPrivateKeyData() Line | Count | Source | 139 | 288 | PrivateKeyData<Traits> *KeyData<Traits>::AsPrivateKeyData() { | 140 | 288 | if (is_private_) { | 141 | 273 | return static_cast<PrivateKeyData<Traits> *>(this); | 142 | 273 | } | 143 | 15 | return nullptr; | 144 | 288 | } |
p_mldsa.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLDSA65Traits>::AsPrivateKeyData() Line | Count | Source | 139 | 273 | PrivateKeyData<Traits> *KeyData<Traits>::AsPrivateKeyData() { | 140 | 273 | if (is_private_) { | 141 | 272 | return static_cast<PrivateKeyData<Traits> *>(this); | 142 | 272 | } | 143 | 1 | return nullptr; | 144 | 273 | } |
p_mldsa.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLDSA87Traits>::AsPrivateKeyData() Line | Count | Source | 139 | 320 | PrivateKeyData<Traits> *KeyData<Traits>::AsPrivateKeyData() { | 140 | 320 | if (is_private_) { | 141 | 319 | return static_cast<PrivateKeyData<Traits> *>(this); | 142 | 319 | } | 143 | 1 | return nullptr; | 144 | 320 | } |
|
145 | | |
146 | | template <typename Traits> |
147 | 353 | void KeyData<Traits>::Free(KeyData<Traits> *data) { |
148 | 353 | if (data == nullptr) { |
149 | 0 | return; |
150 | 0 | } |
151 | | // Delete the more specific subclass. This is moot for now, because neither |
152 | | // type has a non-trivial destructor. |
153 | 353 | auto *priv_data = data->AsPrivateKeyData(); |
154 | 353 | if (priv_data) { |
155 | 343 | Delete(priv_data); |
156 | 343 | } else { |
157 | 10 | Delete(static_cast<PublicKeyData<Traits> *>(data)); |
158 | 10 | } |
159 | 353 | } p_mldsa.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLDSA44Traits>::Free((anonymous namespace)::KeyData<(anonymous namespace)::MLDSA44Traits>*) Line | Count | Source | 147 | 113 | void KeyData<Traits>::Free(KeyData<Traits> *data) { | 148 | 113 | if (data == nullptr) { | 149 | 0 | return; | 150 | 0 | } | 151 | | // Delete the more specific subclass. This is moot for now, because neither | 152 | | // type has a non-trivial destructor. | 153 | 113 | auto *priv_data = data->AsPrivateKeyData(); | 154 | 113 | if (priv_data) { | 155 | 105 | Delete(priv_data); | 156 | 105 | } else { | 157 | 8 | Delete(static_cast<PublicKeyData<Traits> *>(data)); | 158 | 8 | } | 159 | 113 | } |
p_mldsa.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLDSA65Traits>::Free((anonymous namespace)::KeyData<(anonymous namespace)::MLDSA65Traits>*) Line | Count | Source | 147 | 110 | void KeyData<Traits>::Free(KeyData<Traits> *data) { | 148 | 110 | if (data == nullptr) { | 149 | 0 | return; | 150 | 0 | } | 151 | | // Delete the more specific subclass. This is moot for now, because neither | 152 | | // type has a non-trivial destructor. | 153 | 110 | auto *priv_data = data->AsPrivateKeyData(); | 154 | 110 | if (priv_data) { | 155 | 109 | Delete(priv_data); | 156 | 109 | } else { | 157 | 1 | Delete(static_cast<PublicKeyData<Traits> *>(data)); | 158 | 1 | } | 159 | 110 | } |
p_mldsa.cc:(anonymous namespace)::KeyData<(anonymous namespace)::MLDSA87Traits>::Free((anonymous namespace)::KeyData<(anonymous namespace)::MLDSA87Traits>*) Line | Count | Source | 147 | 130 | void KeyData<Traits>::Free(KeyData<Traits> *data) { | 148 | 130 | if (data == nullptr) { | 149 | 0 | return; | 150 | 0 | } | 151 | | // Delete the more specific subclass. This is moot for now, because neither | 152 | | // type has a non-trivial destructor. | 153 | 130 | auto *priv_data = data->AsPrivateKeyData(); | 154 | 130 | if (priv_data) { | 155 | 129 | Delete(priv_data); | 156 | 129 | } else { | 157 | 1 | Delete(static_cast<PublicKeyData<Traits> *>(data)); | 158 | 1 | } | 159 | 130 | } |
|
160 | | |
161 | | struct MldsaPkeyCtx { |
162 | | bssl::Array<uint8_t> context; |
163 | | }; |
164 | | |
165 | | |
166 | | // Finally, MLDSAImplementation instantiates the methods themselves. |
167 | | |
168 | | template <typename Traits> |
169 | | struct MLDSAImplementation { |
170 | 881 | static KeyData<Traits> *GetKeyData(EvpPkey *pkey) { |
171 | 881 | assert(pkey->ameth == &asn1_method); |
172 | 881 | return static_cast<KeyData<Traits> *>(pkey->pkey); |
173 | 881 | } p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::GetKeyData(bssl::EvpPkey*) Line | Count | Source | 170 | 288 | static KeyData<Traits> *GetKeyData(EvpPkey *pkey) { | 171 | 288 | assert(pkey->ameth == &asn1_method); | 172 | 288 | return static_cast<KeyData<Traits> *>(pkey->pkey); | 173 | 288 | } |
p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::GetKeyData(bssl::EvpPkey*) Line | Count | Source | 170 | 273 | static KeyData<Traits> *GetKeyData(EvpPkey *pkey) { | 171 | 273 | assert(pkey->ameth == &asn1_method); | 172 | 273 | return static_cast<KeyData<Traits> *>(pkey->pkey); | 173 | 273 | } |
p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::GetKeyData(bssl::EvpPkey*) Line | Count | Source | 170 | 320 | static KeyData<Traits> *GetKeyData(EvpPkey *pkey) { | 171 | 320 | assert(pkey->ameth == &asn1_method); | 172 | 320 | return static_cast<KeyData<Traits> *>(pkey->pkey); | 173 | 320 | } |
|
174 | | |
175 | 528 | static const KeyData<Traits> *GetKeyData(const EvpPkey *pkey) { |
176 | 528 | return GetKeyData(const_cast<EvpPkey *>(pkey)); |
177 | 528 | } p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::GetKeyData(bssl::EvpPkey const*) Line | Count | Source | 175 | 175 | static const KeyData<Traits> *GetKeyData(const EvpPkey *pkey) { | 176 | 175 | return GetKeyData(const_cast<EvpPkey *>(pkey)); | 177 | 175 | } |
p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::GetKeyData(bssl::EvpPkey const*) Line | Count | Source | 175 | 163 | static const KeyData<Traits> *GetKeyData(const EvpPkey *pkey) { | 176 | 163 | return GetKeyData(const_cast<EvpPkey *>(pkey)); | 177 | 163 | } |
p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::GetKeyData(bssl::EvpPkey const*) Line | Count | Source | 175 | 190 | static const KeyData<Traits> *GetKeyData(const EvpPkey *pkey) { | 176 | 190 | return GetKeyData(const_cast<EvpPkey *>(pkey)); | 177 | 190 | } |
|
178 | | |
179 | 353 | static void PkeyFree(EvpPkey *pkey) { |
180 | 353 | KeyData<Traits>::Free(GetKeyData(pkey)); |
181 | 353 | pkey->pkey = nullptr; |
182 | 353 | } p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::PkeyFree(bssl::EvpPkey*) Line | Count | Source | 179 | 113 | static void PkeyFree(EvpPkey *pkey) { | 180 | 113 | KeyData<Traits>::Free(GetKeyData(pkey)); | 181 | 113 | pkey->pkey = nullptr; | 182 | 113 | } |
p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::PkeyFree(bssl::EvpPkey*) Line | Count | Source | 179 | 110 | static void PkeyFree(EvpPkey *pkey) { | 180 | 110 | KeyData<Traits>::Free(GetKeyData(pkey)); | 181 | 110 | pkey->pkey = nullptr; | 182 | 110 | } |
p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::PkeyFree(bssl::EvpPkey*) Line | Count | Source | 179 | 130 | static void PkeyFree(EvpPkey *pkey) { | 180 | 130 | KeyData<Traits>::Free(GetKeyData(pkey)); | 181 | 130 | pkey->pkey = nullptr; | 182 | 130 | } |
|
183 | | |
184 | 414 | static int SetPrivateSeed(EvpPkey *pkey, const uint8_t *in, size_t len) { |
185 | 414 | auto priv = MakeUnique<PrivateKeyData<Traits>>(); |
186 | 414 | if (priv == nullptr) { |
187 | 0 | return 0; |
188 | 0 | } |
189 | | |
190 | 414 | if (len != MLDSA_SEED_BYTES || |
191 | 343 | !Traits::PrivateKeyFromSeed(&priv->priv, in, len)) { |
192 | 71 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); |
193 | 71 | return 0; |
194 | 71 | } |
195 | 343 | OPENSSL_memcpy(priv->seed, in, len); |
196 | 343 | evp_pkey_set0(pkey, &asn1_method, priv.release()); |
197 | 343 | return 1; |
198 | 414 | } p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::SetPrivateSeed(bssl::EvpPkey*, unsigned char const*, unsigned long) Line | Count | Source | 184 | 138 | static int SetPrivateSeed(EvpPkey *pkey, const uint8_t *in, size_t len) { | 185 | 138 | auto priv = MakeUnique<PrivateKeyData<Traits>>(); | 186 | 138 | if (priv == nullptr) { | 187 | 0 | return 0; | 188 | 0 | } | 189 | | | 190 | 138 | if (len != MLDSA_SEED_BYTES || | 191 | 105 | !Traits::PrivateKeyFromSeed(&priv->priv, in, len)) { | 192 | 33 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | 193 | 33 | return 0; | 194 | 33 | } | 195 | 105 | OPENSSL_memcpy(priv->seed, in, len); | 196 | 105 | evp_pkey_set0(pkey, &asn1_method, priv.release()); | 197 | 105 | return 1; | 198 | 138 | } |
p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::SetPrivateSeed(bssl::EvpPkey*, unsigned char const*, unsigned long) Line | Count | Source | 184 | 136 | static int SetPrivateSeed(EvpPkey *pkey, const uint8_t *in, size_t len) { | 185 | 136 | auto priv = MakeUnique<PrivateKeyData<Traits>>(); | 186 | 136 | if (priv == nullptr) { | 187 | 0 | return 0; | 188 | 0 | } | 189 | | | 190 | 136 | if (len != MLDSA_SEED_BYTES || | 191 | 109 | !Traits::PrivateKeyFromSeed(&priv->priv, in, len)) { | 192 | 27 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | 193 | 27 | return 0; | 194 | 27 | } | 195 | 109 | OPENSSL_memcpy(priv->seed, in, len); | 196 | 109 | evp_pkey_set0(pkey, &asn1_method, priv.release()); | 197 | 109 | return 1; | 198 | 136 | } |
p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::SetPrivateSeed(bssl::EvpPkey*, unsigned char const*, unsigned long) Line | Count | Source | 184 | 140 | static int SetPrivateSeed(EvpPkey *pkey, const uint8_t *in, size_t len) { | 185 | 140 | auto priv = MakeUnique<PrivateKeyData<Traits>>(); | 186 | 140 | if (priv == nullptr) { | 187 | 0 | return 0; | 188 | 0 | } | 189 | | | 190 | 140 | if (len != MLDSA_SEED_BYTES || | 191 | 129 | !Traits::PrivateKeyFromSeed(&priv->priv, in, len)) { | 192 | 11 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | 193 | 11 | return 0; | 194 | 11 | } | 195 | 129 | OPENSSL_memcpy(priv->seed, in, len); | 196 | 129 | evp_pkey_set0(pkey, &asn1_method, priv.release()); | 197 | 129 | return 1; | 198 | 140 | } |
|
199 | | |
200 | 71 | static int SetRawPublic(EvpPkey *pkey, const uint8_t *in, size_t len) { |
201 | 71 | auto pub = MakeUnique<PublicKeyData<Traits>>(); |
202 | 71 | if (pub == nullptr) { |
203 | 0 | return 0; |
204 | 0 | } |
205 | 71 | CBS cbs; |
206 | 71 | CBS_init(&cbs, in, len); |
207 | 71 | if (!Traits::ParsePublicKey(&pub->pub, &cbs) || CBS_len(&cbs) != 0) { |
208 | 61 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); |
209 | 61 | return 0; |
210 | 61 | } |
211 | 10 | evp_pkey_set0(pkey, &asn1_method, pub.release()); |
212 | 10 | return 1; |
213 | 71 | } p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::SetRawPublic(bssl::EvpPkey*, unsigned char const*, unsigned long) Line | Count | Source | 200 | 24 | static int SetRawPublic(EvpPkey *pkey, const uint8_t *in, size_t len) { | 201 | 24 | auto pub = MakeUnique<PublicKeyData<Traits>>(); | 202 | 24 | if (pub == nullptr) { | 203 | 0 | return 0; | 204 | 0 | } | 205 | 24 | CBS cbs; | 206 | 24 | CBS_init(&cbs, in, len); | 207 | 24 | if (!Traits::ParsePublicKey(&pub->pub, &cbs) || CBS_len(&cbs) != 0) { | 208 | 16 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | 209 | 16 | return 0; | 210 | 16 | } | 211 | 8 | evp_pkey_set0(pkey, &asn1_method, pub.release()); | 212 | 8 | return 1; | 213 | 24 | } |
p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::SetRawPublic(bssl::EvpPkey*, unsigned char const*, unsigned long) Line | Count | Source | 200 | 20 | static int SetRawPublic(EvpPkey *pkey, const uint8_t *in, size_t len) { | 201 | 20 | auto pub = MakeUnique<PublicKeyData<Traits>>(); | 202 | 20 | if (pub == nullptr) { | 203 | 0 | return 0; | 204 | 0 | } | 205 | 20 | CBS cbs; | 206 | 20 | CBS_init(&cbs, in, len); | 207 | 20 | if (!Traits::ParsePublicKey(&pub->pub, &cbs) || CBS_len(&cbs) != 0) { | 208 | 19 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | 209 | 19 | return 0; | 210 | 19 | } | 211 | 1 | evp_pkey_set0(pkey, &asn1_method, pub.release()); | 212 | 1 | return 1; | 213 | 20 | } |
p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::SetRawPublic(bssl::EvpPkey*, unsigned char const*, unsigned long) Line | Count | Source | 200 | 27 | static int SetRawPublic(EvpPkey *pkey, const uint8_t *in, size_t len) { | 201 | 27 | auto pub = MakeUnique<PublicKeyData<Traits>>(); | 202 | 27 | if (pub == nullptr) { | 203 | 0 | return 0; | 204 | 0 | } | 205 | 27 | CBS cbs; | 206 | 27 | CBS_init(&cbs, in, len); | 207 | 27 | if (!Traits::ParsePublicKey(&pub->pub, &cbs) || CBS_len(&cbs) != 0) { | 208 | 26 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | 209 | 26 | return 0; | 210 | 26 | } | 211 | 1 | evp_pkey_set0(pkey, &asn1_method, pub.release()); | 212 | 1 | return 1; | 213 | 27 | } |
|
214 | | |
215 | | static int GetPrivateSeed(const EvpPkey *pkey, uint8_t *out, |
216 | 0 | size_t *out_len) { |
217 | 0 | const auto *priv = GetKeyData(pkey)->AsPrivateKeyData(); |
218 | 0 | if (priv == nullptr) { |
219 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY); |
220 | 0 | return 0; |
221 | 0 | } |
222 | 0 | if (out == nullptr) { |
223 | 0 | *out_len = MLDSA_SEED_BYTES; |
224 | 0 | return 1; |
225 | 0 | } |
226 | 0 | if (*out_len < MLDSA_SEED_BYTES) { |
227 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL); |
228 | 0 | return 0; |
229 | 0 | } |
230 | 0 | OPENSSL_memcpy(out, priv->seed, MLDSA_SEED_BYTES); |
231 | 0 | *out_len = MLDSA_SEED_BYTES; |
232 | 0 | return 1; |
233 | 0 | } Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::GetPrivateSeed(bssl::EvpPkey const*, unsigned char*, unsigned long*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::GetPrivateSeed(bssl::EvpPkey const*, unsigned char*, unsigned long*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::GetPrivateSeed(bssl::EvpPkey const*, unsigned char*, unsigned long*) |
234 | | |
235 | 0 | static int GetRawPublic(const EvpPkey *pkey, uint8_t *out, size_t *out_len) { |
236 | 0 | const auto *pub = GetKeyData(pkey)->GetPublicKey(); |
237 | 0 | if (out == nullptr) { |
238 | 0 | *out_len = Traits::kPublicKeyBytes; |
239 | 0 | return 1; |
240 | 0 | } |
241 | 0 | if (*out_len < Traits::kPublicKeyBytes) { |
242 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL); |
243 | 0 | return 0; |
244 | 0 | } |
245 | 0 | CBB cbb; |
246 | 0 | CBB_init_fixed(&cbb, out, Traits::kPublicKeyBytes); |
247 | 0 | BSSL_CHECK(Traits::MarshalPublicKey(&cbb, pub)); |
248 | 0 | BSSL_CHECK(CBB_len(&cbb) == Traits::kPublicKeyBytes); |
249 | 0 | *out_len = Traits::kPublicKeyBytes; |
250 | 0 | return 1; |
251 | 0 | } Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::GetRawPublic(bssl::EvpPkey const*, unsigned char*, unsigned long*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::GetRawPublic(bssl::EvpPkey const*, unsigned char*, unsigned long*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::GetRawPublic(bssl::EvpPkey const*, unsigned char*, unsigned long*) |
252 | | |
253 | | static evp_decode_result_t DecodePublic(const EVP_PKEY_ALG *alg, EvpPkey *out, |
254 | 261 | CBS *params, CBS *key) { |
255 | | // The parameters must be omitted. See |
256 | | // draft-ietf-lamps-dilithium-certificates-13, Section 2. |
257 | 261 | if (CBS_len(params) != 0) { |
258 | 190 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); |
259 | 190 | return evp_decode_error; |
260 | 190 | } |
261 | 71 | return SetRawPublic(out, CBS_data(key), CBS_len(key)) ? evp_decode_ok |
262 | 71 | : evp_decode_error; |
263 | 261 | } p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::DecodePublic(evp_pkey_alg_st const*, bssl::EvpPkey*, cbs_st*, cbs_st*) Line | Count | Source | 254 | 52 | CBS *params, CBS *key) { | 255 | | // The parameters must be omitted. See | 256 | | // draft-ietf-lamps-dilithium-certificates-13, Section 2. | 257 | 52 | if (CBS_len(params) != 0) { | 258 | 28 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | 259 | 28 | return evp_decode_error; | 260 | 28 | } | 261 | 24 | return SetRawPublic(out, CBS_data(key), CBS_len(key)) ? evp_decode_ok | 262 | 24 | : evp_decode_error; | 263 | 52 | } |
p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::DecodePublic(evp_pkey_alg_st const*, bssl::EvpPkey*, cbs_st*, cbs_st*) Line | Count | Source | 254 | 85 | CBS *params, CBS *key) { | 255 | | // The parameters must be omitted. See | 256 | | // draft-ietf-lamps-dilithium-certificates-13, Section 2. | 257 | 85 | if (CBS_len(params) != 0) { | 258 | 65 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | 259 | 65 | return evp_decode_error; | 260 | 65 | } | 261 | 20 | return SetRawPublic(out, CBS_data(key), CBS_len(key)) ? evp_decode_ok | 262 | 20 | : evp_decode_error; | 263 | 85 | } |
p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::DecodePublic(evp_pkey_alg_st const*, bssl::EvpPkey*, cbs_st*, cbs_st*) Line | Count | Source | 254 | 124 | CBS *params, CBS *key) { | 255 | | // The parameters must be omitted. See | 256 | | // draft-ietf-lamps-dilithium-certificates-13, Section 2. | 257 | 124 | if (CBS_len(params) != 0) { | 258 | 97 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | 259 | 97 | return evp_decode_error; | 260 | 97 | } | 261 | 27 | return SetRawPublic(out, CBS_data(key), CBS_len(key)) ? evp_decode_ok | 262 | 27 | : evp_decode_error; | 263 | 124 | } |
|
264 | | |
265 | 185 | static int EncodePublic(CBB *out, const EvpPkey *pkey) { |
266 | 185 | const auto *pub = GetKeyData(pkey)->GetPublicKey(); |
267 | | // See draft-ietf-lamps-dilithium-certificates-13, Sections 2 and 4. |
268 | 185 | CBB spki, algorithm, key_bitstring; |
269 | 185 | if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) || |
270 | 185 | !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || |
271 | 185 | !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, Traits::kOID.data(), |
272 | 185 | Traits::kOID.size()) || |
273 | 185 | !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) || |
274 | 185 | !CBB_add_u8(&key_bitstring, 0 /* no unused bits */) || |
275 | 185 | !Traits::MarshalPublicKey(&key_bitstring, pub) || |
276 | 185 | !CBB_flush(out)) { |
277 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); |
278 | 0 | return 0; |
279 | 0 | } |
280 | 185 | return 1; |
281 | 185 | } p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::EncodePublic(cbb_st*, bssl::EvpPkey const*) Line | Count | Source | 265 | 70 | static int EncodePublic(CBB *out, const EvpPkey *pkey) { | 266 | 70 | const auto *pub = GetKeyData(pkey)->GetPublicKey(); | 267 | | // See draft-ietf-lamps-dilithium-certificates-13, Sections 2 and 4. | 268 | 70 | CBB spki, algorithm, key_bitstring; | 269 | 70 | if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) || | 270 | 70 | !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || | 271 | 70 | !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, Traits::kOID.data(), | 272 | 70 | Traits::kOID.size()) || | 273 | 70 | !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) || | 274 | 70 | !CBB_add_u8(&key_bitstring, 0 /* no unused bits */) || | 275 | 70 | !Traits::MarshalPublicKey(&key_bitstring, pub) || | 276 | 70 | !CBB_flush(out)) { | 277 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); | 278 | 0 | return 0; | 279 | 0 | } | 280 | 70 | return 1; | 281 | 70 | } |
p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::EncodePublic(cbb_st*, bssl::EvpPkey const*) Line | Count | Source | 265 | 54 | static int EncodePublic(CBB *out, const EvpPkey *pkey) { | 266 | 54 | const auto *pub = GetKeyData(pkey)->GetPublicKey(); | 267 | | // See draft-ietf-lamps-dilithium-certificates-13, Sections 2 and 4. | 268 | 54 | CBB spki, algorithm, key_bitstring; | 269 | 54 | if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) || | 270 | 54 | !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || | 271 | 54 | !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, Traits::kOID.data(), | 272 | 54 | Traits::kOID.size()) || | 273 | 54 | !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) || | 274 | 54 | !CBB_add_u8(&key_bitstring, 0 /* no unused bits */) || | 275 | 54 | !Traits::MarshalPublicKey(&key_bitstring, pub) || | 276 | 54 | !CBB_flush(out)) { | 277 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); | 278 | 0 | return 0; | 279 | 0 | } | 280 | 54 | return 1; | 281 | 54 | } |
p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::EncodePublic(cbb_st*, bssl::EvpPkey const*) Line | Count | Source | 265 | 61 | static int EncodePublic(CBB *out, const EvpPkey *pkey) { | 266 | 61 | const auto *pub = GetKeyData(pkey)->GetPublicKey(); | 267 | | // See draft-ietf-lamps-dilithium-certificates-13, Sections 2 and 4. | 268 | 61 | CBB spki, algorithm, key_bitstring; | 269 | 61 | if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) || | 270 | 61 | !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || | 271 | 61 | !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, Traits::kOID.data(), | 272 | 61 | Traits::kOID.size()) || | 273 | 61 | !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) || | 274 | 61 | !CBB_add_u8(&key_bitstring, 0 /* no unused bits */) || | 275 | 61 | !Traits::MarshalPublicKey(&key_bitstring, pub) || | 276 | 61 | !CBB_flush(out)) { | 277 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); | 278 | 0 | return 0; | 279 | 0 | } | 280 | 61 | return 1; | 281 | 61 | } |
|
282 | | |
283 | 0 | static bool EqualPublic(const EvpPkey *a, const EvpPkey *b) { |
284 | 0 | const auto *a_pub = GetKeyData(a)->GetPublicKey(); |
285 | 0 | const auto *b_pub = GetKeyData(b)->GetPublicKey(); |
286 | 0 | return Traits::PublicKeysEqual(a_pub, b_pub); |
287 | 0 | } Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::EqualPublic(bssl::EvpPkey const*, bssl::EvpPkey const*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::EqualPublic(bssl::EvpPkey const*, bssl::EvpPkey const*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::EqualPublic(bssl::EvpPkey const*, bssl::EvpPkey const*) |
288 | | |
289 | 0 | static bool HasPublic(const EvpPkey *pk) { return true; }Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::HasPublic(bssl::EvpPkey const*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::HasPublic(bssl::EvpPkey const*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::HasPublic(bssl::EvpPkey const*) |
290 | | |
291 | 0 | static bool CopyPublic(EvpPkey *out, const EvpPkey *pk) { |
292 | 0 | auto *public_copy = |
293 | 0 | New<PublicKeyData<Traits>>(*GetKeyData(pk)->GetPublicKey()); |
294 | 0 | if (public_copy == nullptr) { |
295 | 0 | OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR); |
296 | 0 | return false; |
297 | 0 | } |
298 | 0 | evp_pkey_set0(out, pk->ameth, public_copy); |
299 | 0 | return true; |
300 | 0 | } Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::CopyPublic(bssl::EvpPkey*, bssl::EvpPkey const*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::CopyPublic(bssl::EvpPkey*, bssl::EvpPkey const*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::CopyPublic(bssl::EvpPkey*, bssl::EvpPkey const*) |
301 | | |
302 | | static evp_decode_result_t DecodePrivate(const EVP_PKEY_ALG *alg, |
303 | | EvpPkey *out, CBS *params, |
304 | 523 | CBS *key) { |
305 | | // The parameters must be omitted. See |
306 | | // draft-ietf-lamps-dilithium-certificates-13, Section 2. |
307 | 523 | if (CBS_len(params) != 0) { |
308 | 41 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); |
309 | 41 | return evp_decode_error; |
310 | 41 | } |
311 | | |
312 | | // See draft-ietf-lamps-dilithium-certificates-13, Section 6. Three |
313 | | // different encodings were specified, adding complexity to the question of |
314 | | // whether a private key is valid. We only implement the "seed" |
315 | | // representation. Give this case a different error for easier diagnostics. |
316 | | // |
317 | | // The "expandedKey" representation was a last-minute accommodation for |
318 | | // legacy hardware, which should be updated to use seeds. Supporting it |
319 | | // complicates the notion of a private key with both seedful and seedless |
320 | | // variants. |
321 | | // |
322 | | // The "both" representation is technically unsound and |
323 | | // dangerous, so we do not implement it. Systems composed of components, |
324 | | // some of which look at one half of the "both" representation, and half of |
325 | | // the other, will appear to interop, but break when an input is |
326 | | // inconsistent. The expanded key can be computed from the seed, so there is |
327 | | // no purpose in this form. |
328 | 482 | CBS seed; |
329 | 482 | if (!CBS_get_asn1(key, &seed, kSeedTag)) { |
330 | 14 | OPENSSL_PUT_ERROR(EVP, EVP_R_PRIVATE_KEY_WAS_NOT_SEED); |
331 | 14 | return evp_decode_error; |
332 | 14 | } |
333 | 468 | if (CBS_len(key) != 0) { |
334 | 54 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); |
335 | 54 | return evp_decode_error; |
336 | 54 | } |
337 | 414 | return SetPrivateSeed(out, CBS_data(&seed), CBS_len(&seed)) |
338 | 414 | ? evp_decode_ok |
339 | 414 | : evp_decode_error; |
340 | 468 | } p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::DecodePrivate(evp_pkey_alg_st const*, bssl::EvpPkey*, cbs_st*, cbs_st*) Line | Count | Source | 304 | 165 | CBS *key) { | 305 | | // The parameters must be omitted. See | 306 | | // draft-ietf-lamps-dilithium-certificates-13, Section 2. | 307 | 165 | if (CBS_len(params) != 0) { | 308 | 7 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | 309 | 7 | return evp_decode_error; | 310 | 7 | } | 311 | | | 312 | | // See draft-ietf-lamps-dilithium-certificates-13, Section 6. Three | 313 | | // different encodings were specified, adding complexity to the question of | 314 | | // whether a private key is valid. We only implement the "seed" | 315 | | // representation. Give this case a different error for easier diagnostics. | 316 | | // | 317 | | // The "expandedKey" representation was a last-minute accommodation for | 318 | | // legacy hardware, which should be updated to use seeds. Supporting it | 319 | | // complicates the notion of a private key with both seedful and seedless | 320 | | // variants. | 321 | | // | 322 | | // The "both" representation is technically unsound and | 323 | | // dangerous, so we do not implement it. Systems composed of components, | 324 | | // some of which look at one half of the "both" representation, and half of | 325 | | // the other, will appear to interop, but break when an input is | 326 | | // inconsistent. The expanded key can be computed from the seed, so there is | 327 | | // no purpose in this form. | 328 | 158 | CBS seed; | 329 | 158 | if (!CBS_get_asn1(key, &seed, kSeedTag)) { | 330 | 4 | OPENSSL_PUT_ERROR(EVP, EVP_R_PRIVATE_KEY_WAS_NOT_SEED); | 331 | 4 | return evp_decode_error; | 332 | 4 | } | 333 | 154 | if (CBS_len(key) != 0) { | 334 | 16 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | 335 | 16 | return evp_decode_error; | 336 | 16 | } | 337 | 138 | return SetPrivateSeed(out, CBS_data(&seed), CBS_len(&seed)) | 338 | 138 | ? evp_decode_ok | 339 | 138 | : evp_decode_error; | 340 | 154 | } |
p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::DecodePrivate(evp_pkey_alg_st const*, bssl::EvpPkey*, cbs_st*, cbs_st*) Line | Count | Source | 304 | 177 | CBS *key) { | 305 | | // The parameters must be omitted. See | 306 | | // draft-ietf-lamps-dilithium-certificates-13, Section 2. | 307 | 177 | if (CBS_len(params) != 0) { | 308 | 12 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | 309 | 12 | return evp_decode_error; | 310 | 12 | } | 311 | | | 312 | | // See draft-ietf-lamps-dilithium-certificates-13, Section 6. Three | 313 | | // different encodings were specified, adding complexity to the question of | 314 | | // whether a private key is valid. We only implement the "seed" | 315 | | // representation. Give this case a different error for easier diagnostics. | 316 | | // | 317 | | // The "expandedKey" representation was a last-minute accommodation for | 318 | | // legacy hardware, which should be updated to use seeds. Supporting it | 319 | | // complicates the notion of a private key with both seedful and seedless | 320 | | // variants. | 321 | | // | 322 | | // The "both" representation is technically unsound and | 323 | | // dangerous, so we do not implement it. Systems composed of components, | 324 | | // some of which look at one half of the "both" representation, and half of | 325 | | // the other, will appear to interop, but break when an input is | 326 | | // inconsistent. The expanded key can be computed from the seed, so there is | 327 | | // no purpose in this form. | 328 | 165 | CBS seed; | 329 | 165 | if (!CBS_get_asn1(key, &seed, kSeedTag)) { | 330 | 4 | OPENSSL_PUT_ERROR(EVP, EVP_R_PRIVATE_KEY_WAS_NOT_SEED); | 331 | 4 | return evp_decode_error; | 332 | 4 | } | 333 | 161 | if (CBS_len(key) != 0) { | 334 | 25 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | 335 | 25 | return evp_decode_error; | 336 | 25 | } | 337 | 136 | return SetPrivateSeed(out, CBS_data(&seed), CBS_len(&seed)) | 338 | 136 | ? evp_decode_ok | 339 | 136 | : evp_decode_error; | 340 | 161 | } |
p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::DecodePrivate(evp_pkey_alg_st const*, bssl::EvpPkey*, cbs_st*, cbs_st*) Line | Count | Source | 304 | 181 | CBS *key) { | 305 | | // The parameters must be omitted. See | 306 | | // draft-ietf-lamps-dilithium-certificates-13, Section 2. | 307 | 181 | if (CBS_len(params) != 0) { | 308 | 22 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | 309 | 22 | return evp_decode_error; | 310 | 22 | } | 311 | | | 312 | | // See draft-ietf-lamps-dilithium-certificates-13, Section 6. Three | 313 | | // different encodings were specified, adding complexity to the question of | 314 | | // whether a private key is valid. We only implement the "seed" | 315 | | // representation. Give this case a different error for easier diagnostics. | 316 | | // | 317 | | // The "expandedKey" representation was a last-minute accommodation for | 318 | | // legacy hardware, which should be updated to use seeds. Supporting it | 319 | | // complicates the notion of a private key with both seedful and seedless | 320 | | // variants. | 321 | | // | 322 | | // The "both" representation is technically unsound and | 323 | | // dangerous, so we do not implement it. Systems composed of components, | 324 | | // some of which look at one half of the "both" representation, and half of | 325 | | // the other, will appear to interop, but break when an input is | 326 | | // inconsistent. The expanded key can be computed from the seed, so there is | 327 | | // no purpose in this form. | 328 | 159 | CBS seed; | 329 | 159 | if (!CBS_get_asn1(key, &seed, kSeedTag)) { | 330 | 6 | OPENSSL_PUT_ERROR(EVP, EVP_R_PRIVATE_KEY_WAS_NOT_SEED); | 331 | 6 | return evp_decode_error; | 332 | 6 | } | 333 | 153 | if (CBS_len(key) != 0) { | 334 | 13 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | 335 | 13 | return evp_decode_error; | 336 | 13 | } | 337 | 140 | return SetPrivateSeed(out, CBS_data(&seed), CBS_len(&seed)) | 338 | 140 | ? evp_decode_ok | 339 | 140 | : evp_decode_error; | 340 | 153 | } |
|
341 | | |
342 | 343 | static int EncodePrivate(CBB *out, const EvpPkey *pkey) { |
343 | 343 | const auto *priv = GetKeyData(pkey)->AsPrivateKeyData(); |
344 | 343 | if (priv == nullptr) { |
345 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY); |
346 | 0 | return 0; |
347 | 0 | } |
348 | | // See draft-ietf-lamps-dilithium-certificates-13, Sections 2 and 6. We |
349 | | // encode only the seed representation. |
350 | 343 | CBB pkcs8, algorithm, private_key; |
351 | 343 | if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) || |
352 | 343 | !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) || |
353 | 343 | !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || |
354 | 343 | !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, Traits::kOID.data(), |
355 | 343 | Traits::kOID.size()) || |
356 | 343 | !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) || |
357 | 343 | !CBB_add_asn1_element(&private_key, kSeedTag, priv->seed, |
358 | 343 | sizeof(priv->seed)) || |
359 | 343 | !CBB_flush(out)) { |
360 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); |
361 | 0 | return 0; |
362 | 0 | } |
363 | 343 | return 1; |
364 | 343 | } p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::EncodePrivate(cbb_st*, bssl::EvpPkey const*) Line | Count | Source | 342 | 105 | static int EncodePrivate(CBB *out, const EvpPkey *pkey) { | 343 | 105 | const auto *priv = GetKeyData(pkey)->AsPrivateKeyData(); | 344 | 105 | if (priv == nullptr) { | 345 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY); | 346 | 0 | return 0; | 347 | 0 | } | 348 | | // See draft-ietf-lamps-dilithium-certificates-13, Sections 2 and 6. We | 349 | | // encode only the seed representation. | 350 | 105 | CBB pkcs8, algorithm, private_key; | 351 | 105 | if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) || | 352 | 105 | !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) || | 353 | 105 | !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || | 354 | 105 | !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, Traits::kOID.data(), | 355 | 105 | Traits::kOID.size()) || | 356 | 105 | !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) || | 357 | 105 | !CBB_add_asn1_element(&private_key, kSeedTag, priv->seed, | 358 | 105 | sizeof(priv->seed)) || | 359 | 105 | !CBB_flush(out)) { | 360 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); | 361 | 0 | return 0; | 362 | 0 | } | 363 | 105 | return 1; | 364 | 105 | } |
p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::EncodePrivate(cbb_st*, bssl::EvpPkey const*) Line | Count | Source | 342 | 109 | static int EncodePrivate(CBB *out, const EvpPkey *pkey) { | 343 | 109 | const auto *priv = GetKeyData(pkey)->AsPrivateKeyData(); | 344 | 109 | if (priv == nullptr) { | 345 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY); | 346 | 0 | return 0; | 347 | 0 | } | 348 | | // See draft-ietf-lamps-dilithium-certificates-13, Sections 2 and 6. We | 349 | | // encode only the seed representation. | 350 | 109 | CBB pkcs8, algorithm, private_key; | 351 | 109 | if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) || | 352 | 109 | !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) || | 353 | 109 | !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || | 354 | 109 | !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, Traits::kOID.data(), | 355 | 109 | Traits::kOID.size()) || | 356 | 109 | !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) || | 357 | 109 | !CBB_add_asn1_element(&private_key, kSeedTag, priv->seed, | 358 | 109 | sizeof(priv->seed)) || | 359 | 109 | !CBB_flush(out)) { | 360 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); | 361 | 0 | return 0; | 362 | 0 | } | 363 | 109 | return 1; | 364 | 109 | } |
p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::EncodePrivate(cbb_st*, bssl::EvpPkey const*) Line | Count | Source | 342 | 129 | static int EncodePrivate(CBB *out, const EvpPkey *pkey) { | 343 | 129 | const auto *priv = GetKeyData(pkey)->AsPrivateKeyData(); | 344 | 129 | if (priv == nullptr) { | 345 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY); | 346 | 0 | return 0; | 347 | 0 | } | 348 | | // See draft-ietf-lamps-dilithium-certificates-13, Sections 2 and 6. We | 349 | | // encode only the seed representation. | 350 | 129 | CBB pkcs8, algorithm, private_key; | 351 | 129 | if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) || | 352 | 129 | !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) || | 353 | 129 | !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || | 354 | 129 | !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, Traits::kOID.data(), | 355 | 129 | Traits::kOID.size()) || | 356 | 129 | !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) || | 357 | 129 | !CBB_add_asn1_element(&private_key, kSeedTag, priv->seed, | 358 | 129 | sizeof(priv->seed)) || | 359 | 129 | !CBB_flush(out)) { | 360 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); | 361 | 0 | return 0; | 362 | 0 | } | 363 | 129 | return 1; | 364 | 129 | } |
|
365 | | |
366 | 0 | static bool HasPrivate(const EvpPkey *pk) { |
367 | 0 | return GetKeyData(pk)->AsPrivateKeyData() != nullptr; |
368 | 0 | } Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::HasPrivate(bssl::EvpPkey const*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::HasPrivate(bssl::EvpPkey const*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::HasPrivate(bssl::EvpPkey const*) |
369 | | |
370 | 0 | static int PkeySize(const EvpPkey *pkey) { return Traits::kSignatureBytes; }Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::PkeySize(bssl::EvpPkey const*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::PkeySize(bssl::EvpPkey const*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::PkeySize(bssl::EvpPkey const*) |
371 | 0 | static int PkeyBits(const EvpPkey *pkey) { |
372 | | // OpenSSL counts the bits in the public key serialization. |
373 | 0 | return Traits::kPublicKeyBytes * 8; |
374 | 0 | } Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::PkeyBits(bssl::EvpPkey const*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::PkeyBits(bssl::EvpPkey const*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::PkeyBits(bssl::EvpPkey const*) |
375 | | |
376 | 0 | static int Init(EvpPkeyCtx *ctx, const EVP_PKEY_ALG *) { |
377 | 0 | MldsaPkeyCtx *mctx = New<MldsaPkeyCtx>(); |
378 | 0 | if (mctx == nullptr) { |
379 | 0 | return 0; |
380 | 0 | } |
381 | 0 | ctx->data = mctx; |
382 | 0 | return 1; |
383 | 0 | } Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::Init(bssl::EvpPkeyCtx*, evp_pkey_alg_st const*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::Init(bssl::EvpPkeyCtx*, evp_pkey_alg_st const*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::Init(bssl::EvpPkeyCtx*, evp_pkey_alg_st const*) |
384 | | |
385 | 0 | static void Cleanup(EvpPkeyCtx *ctx) { |
386 | 0 | Delete(static_cast<MldsaPkeyCtx *>(ctx->data)); |
387 | 0 | } Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::Cleanup(bssl::EvpPkeyCtx*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::Cleanup(bssl::EvpPkeyCtx*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::Cleanup(bssl::EvpPkeyCtx*) |
388 | | |
389 | 0 | static int CopyContext(EvpPkeyCtx *dst, EvpPkeyCtx *src) { |
390 | 0 | if (!Init(dst, nullptr)) { |
391 | 0 | return 0; |
392 | 0 | } |
393 | 0 | MldsaPkeyCtx *sctx = static_cast<MldsaPkeyCtx *>(src->data); |
394 | 0 | MldsaPkeyCtx *dctx = static_cast<MldsaPkeyCtx *>(dst->data); |
395 | 0 | if (!dctx->context.CopyFrom(sctx->context)) { |
396 | 0 | return 0; |
397 | 0 | } |
398 | 0 | return 1; |
399 | 0 | } Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::CopyContext(bssl::EvpPkeyCtx*, bssl::EvpPkeyCtx*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::CopyContext(bssl::EvpPkeyCtx*, bssl::EvpPkeyCtx*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::CopyContext(bssl::EvpPkeyCtx*, bssl::EvpPkeyCtx*) |
400 | | |
401 | 0 | static int KeyGen(EvpPkeyCtx *ctx, EvpPkey *pkey) { |
402 | 0 | auto priv = MakeUnique<PrivateKeyData<Traits>>(); |
403 | 0 | if (priv == nullptr) { |
404 | 0 | return 0; |
405 | 0 | } |
406 | 0 | uint8_t unused_public[Traits::kPublicKeyBytes]; |
407 | 0 | if (!Traits::GenerateKey(unused_public, priv->seed, &priv->priv)) { |
408 | 0 | return 0; |
409 | 0 | } |
410 | 0 | evp_pkey_set0(pkey, &asn1_method, priv.release()); |
411 | 0 | return 1; |
412 | 0 | } Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::KeyGen(bssl::EvpPkeyCtx*, bssl::EvpPkey*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::KeyGen(bssl::EvpPkeyCtx*, bssl::EvpPkey*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::KeyGen(bssl::EvpPkeyCtx*, bssl::EvpPkey*) |
413 | | |
414 | | static int SignMessage(EvpPkeyCtx *ctx, uint8_t *sig, size_t *siglen, |
415 | 0 | const uint8_t *tbs, size_t tbslen) { |
416 | 0 | const auto *priv_data = GetKeyData(ctx->pkey.get())->AsPrivateKeyData(); |
417 | 0 | if (priv_data == nullptr) { |
418 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY); |
419 | 0 | return 0; |
420 | 0 | } |
421 | 0 | if (sig == nullptr) { |
422 | 0 | *siglen = Traits::kSignatureBytes; |
423 | 0 | return 1; |
424 | 0 | } |
425 | 0 | if (*siglen < Traits::kSignatureBytes) { |
426 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL); |
427 | 0 | return 0; |
428 | 0 | } |
429 | 0 | MldsaPkeyCtx *mctx = static_cast<MldsaPkeyCtx *>(ctx->data); |
430 | 0 | if (!Traits::Sign(sig, &priv_data->priv, tbs, tbslen, mctx->context.data(), |
431 | 0 | mctx->context.size())) { |
432 | 0 | return 0; |
433 | 0 | } |
434 | 0 | *siglen = Traits::kSignatureBytes; |
435 | 0 | return 1; |
436 | 0 | } Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::SignMessage(bssl::EvpPkeyCtx*, unsigned char*, unsigned long*, unsigned char const*, unsigned long) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::SignMessage(bssl::EvpPkeyCtx*, unsigned char*, unsigned long*, unsigned char const*, unsigned long) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::SignMessage(bssl::EvpPkeyCtx*, unsigned char*, unsigned long*, unsigned char const*, unsigned long) |
437 | | |
438 | | static int VerifyMessage(EvpPkeyCtx *ctx, const uint8_t *sig, size_t siglen, |
439 | 0 | const uint8_t *tbs, size_t tbslen) { |
440 | 0 | const auto *pub = GetKeyData(ctx->pkey.get())->GetPublicKey(); |
441 | 0 | MldsaPkeyCtx *mctx = static_cast<MldsaPkeyCtx *>(ctx->data); |
442 | 0 | if (!Traits::Verify(pub, sig, siglen, tbs, tbslen, mctx->context.data(), |
443 | 0 | mctx->context.size())) { |
444 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_SIGNATURE); |
445 | 0 | return 0; |
446 | 0 | } |
447 | 0 | return 1; |
448 | 0 | } Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::VerifyMessage(bssl::EvpPkeyCtx*, unsigned char const*, unsigned long, unsigned char const*, unsigned long) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::VerifyMessage(bssl::EvpPkeyCtx*, unsigned char const*, unsigned long, unsigned char const*, unsigned long) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::VerifyMessage(bssl::EvpPkeyCtx*, unsigned char const*, unsigned long, unsigned char const*, unsigned long) |
449 | | |
450 | 0 | static int Ctrl(EvpPkeyCtx *ctx, int type, int p1, void *p2) { |
451 | 0 | MldsaPkeyCtx *mctx = static_cast<MldsaPkeyCtx *>(ctx->data); |
452 | 0 | switch (type) { |
453 | 0 | case EVP_PKEY_CTRL_SIGNATURE_CONTEXT_STRING: { |
454 | 0 | const auto *context_string = |
455 | 0 | reinterpret_cast<const Span<const uint8_t> *>(p2); |
456 | 0 | if (context_string == nullptr || |
457 | 0 | context_string->size() > kMaxContextLength) { |
458 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PARAMETERS); |
459 | 0 | return 0; |
460 | 0 | } |
461 | 0 | return mctx->context.CopyFrom(*context_string); |
462 | 0 | } |
463 | | |
464 | 0 | default: |
465 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED); |
466 | 0 | return 0; |
467 | 0 | } |
468 | 0 | } Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::Ctrl(bssl::EvpPkeyCtx*, int, int, void*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::Ctrl(bssl::EvpPkeyCtx*, int, int, void*) Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::Ctrl(bssl::EvpPkeyCtx*, int, int, void*) |
469 | | |
470 | | static constexpr EVP_PKEY_CTX_METHOD pkey_method = { |
471 | | Traits::kType, |
472 | | &Init, |
473 | | &CopyContext, |
474 | | &Cleanup, |
475 | | &KeyGen, |
476 | | /*sign=*/nullptr, |
477 | | &SignMessage, |
478 | | /*verify=*/nullptr, |
479 | | &VerifyMessage, |
480 | | /*verify_recover=*/nullptr, |
481 | | /*encrypt=*/nullptr, |
482 | | /*decrypt=*/nullptr, |
483 | | /*derive=*/nullptr, |
484 | | /*paramgen=*/nullptr, |
485 | | /*encap=*/nullptr, |
486 | | /*decap=*/nullptr, |
487 | | &Ctrl, |
488 | | }; |
489 | | |
490 | 0 | static constexpr EVP_PKEY_ASN1_METHOD BuildASN1Method() { |
491 | 0 | EVP_PKEY_ASN1_METHOD ret = { |
492 | 0 | Traits::kType, |
493 | 0 | // The OID is filled in below. |
494 | 0 | /*oid=*/{}, |
495 | 0 | /*oid_len=*/0, |
496 | 0 | &pkey_method, |
497 | 0 | &DecodePublic, |
498 | 0 | &EncodePublic, |
499 | 0 | &EqualPublic, |
500 | 0 | &HasPublic, |
501 | 0 | &CopyPublic, |
502 | 0 | &DecodePrivate, |
503 | 0 | &EncodePrivate, |
504 | 0 | &HasPrivate, |
505 | 0 | // While exporting the seed as the "raw" private key would be natural, |
506 | 0 | // OpenSSL connected these APIs to the "raw private key", so we export |
507 | 0 | // the seed separately. |
508 | 0 | /*set_priv_raw=*/nullptr, |
509 | 0 | &SetPrivateSeed, |
510 | 0 | &SetRawPublic, |
511 | 0 | /*get_priv_raw=*/nullptr, |
512 | 0 | &GetPrivateSeed, |
513 | 0 | &GetRawPublic, |
514 | 0 | /*set1_tls_encodedpoint=*/nullptr, |
515 | 0 | /*get1_tls_encodedpoint=*/nullptr, |
516 | 0 | /*pkey_opaque=*/nullptr, |
517 | 0 | &PkeySize, |
518 | 0 | &PkeyBits, |
519 | 0 | /*param_missing=*/nullptr, |
520 | 0 | /*param_copy=*/nullptr, |
521 | 0 | /*param_equal=*/nullptr, |
522 | 0 | &PkeyFree, |
523 | 0 | }; |
524 | 0 | // TODO(crbug.com/404286922): Use std::copy in C++20, when it's constexpr. |
525 | 0 | // TODO(crbug.com/450823446): Better yet, make this field an InplaceVector |
526 | 0 | // and give it a suitable constructor. |
527 | 0 | constexpr auto oid = Traits::kOID; |
528 | 0 | static_assert(oid.size() <= sizeof(ret.oid)); |
529 | 0 | for (size_t i = 0; i < oid.size(); i++) { |
530 | 0 | ret.oid[i] = oid[i]; |
531 | 0 | } |
532 | 0 | ret.oid_len = oid.size(); |
533 | 0 | return ret; |
534 | 0 | } Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA44Traits>::BuildASN1Method() Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA65Traits>::BuildASN1Method() Unexecuted instantiation: p_mldsa.cc:(anonymous namespace)::MLDSAImplementation<(anonymous namespace)::MLDSA87Traits>::BuildASN1Method() |
535 | | |
536 | | static constexpr EVP_PKEY_ASN1_METHOD asn1_method = BuildASN1Method(); |
537 | | static constexpr EVP_PKEY_ALG pkey_alg = {&asn1_method, &pkey_method}; |
538 | | }; |
539 | | |
540 | | } // namespace |
541 | | |
542 | 256k | const EVP_PKEY_ALG *EVP_pkey_ml_dsa_44() { |
543 | 256k | return &MLDSAImplementation<MLDSA44Traits>::pkey_alg; |
544 | 256k | } |
545 | | |
546 | 256k | const EVP_PKEY_ALG *EVP_pkey_ml_dsa_65() { |
547 | 256k | return &MLDSAImplementation<MLDSA65Traits>::pkey_alg; |
548 | 256k | } |
549 | | |
550 | 256k | const EVP_PKEY_ALG *EVP_pkey_ml_dsa_87() { |
551 | 256k | return &MLDSAImplementation<MLDSA87Traits>::pkey_alg; |
552 | 256k | } |