/src/rnp/src/lib/crypto/ec.h
Line | Count | Source |
1 | | /*- |
2 | | * Copyright (c) 2017-2024 Ribose Inc. |
3 | | * All rights reserved. |
4 | | * |
5 | | * Redistribution and use in source and binary forms, with or without |
6 | | * modification, are permitted provided that the following conditions |
7 | | * are met: |
8 | | * 1. Redistributions of source code must retain the above copyright |
9 | | * notice, this list of conditions and the following disclaimer. |
10 | | * 2. Redistributions in binary form must reproduce the above copyright |
11 | | * notice, this list of conditions and the following disclaimer in the |
12 | | * documentation and/or other materials provided with the distribution. |
13 | | * |
14 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
15 | | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
16 | | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
17 | | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS |
18 | | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
19 | | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
20 | | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
21 | | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
22 | | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
23 | | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
24 | | * POSSIBILITY OF SUCH DAMAGE. |
25 | | */ |
26 | | #ifndef EC_H_ |
27 | | #define EC_H_ |
28 | | |
29 | | #include "config.h" |
30 | | #include <rnp/rnp_def.h> |
31 | | #include <repgp/repgp_def.h> |
32 | | #include "crypto/rng.h" |
33 | | #include "crypto/mpi.hpp" |
34 | | #include "crypto/mem.h" |
35 | | #include "utils.h" |
36 | | #include <vector> |
37 | | |
38 | 40.3k | #define MAX_CURVE_BIT_SIZE 521 // secp521r1 |
39 | | /* Maximal byte size of elliptic curve order (NIST P-521) */ |
40 | 40.3k | #define MAX_CURVE_BYTELEN ((MAX_CURVE_BIT_SIZE + 7) / 8) |
41 | | |
42 | | namespace pgp { |
43 | | namespace ec { |
44 | | /** |
45 | | * Structure holds description of elliptic curve |
46 | | */ |
47 | | class Curve { |
48 | | public: |
49 | | const pgp_curve_t rnp_curve_id; |
50 | | const size_t bitlen; |
51 | | const std::vector<uint8_t> OID; |
52 | | #if defined(CRYPTO_BACKEND_BOTAN) |
53 | | const char *botan_name; |
54 | | #endif |
55 | | #if defined(CRYPTO_BACKEND_OPENSSL) |
56 | | const char *openssl_name; |
57 | | #endif |
58 | | const char *pgp_name; |
59 | | /* Curve is supported for keygen/sign/encrypt operations */ |
60 | | bool supported; |
61 | | /* Curve parameters below. Needed for grip calculation */ |
62 | | const char *p; |
63 | | const char *a; |
64 | | const char *b; |
65 | | const char *n; |
66 | | const char *gx; |
67 | | const char *gy; |
68 | | const char *h; |
69 | | |
70 | | /** |
71 | | * @brief Finds curve ID by hex representation of OID |
72 | | * @param oid buffer with OID in hex |
73 | | * @returns success curve ID |
74 | | * failure PGP_CURVE_MAX is returned |
75 | | * @remarks see RFC 4880 bis 01 - 9.2 ECC Curve OID |
76 | | */ |
77 | | static pgp_curve_t by_OID(const std::vector<uint8_t> &oid); |
78 | | |
79 | | static pgp_curve_t by_name(const char *name); |
80 | | |
81 | | /** |
82 | | * @brief Returns pointer to the curve descriptor |
83 | | * |
84 | | * @param Valid curve ID |
85 | | * |
86 | | * @returns NULL if wrong ID provided, otherwise descriptor |
87 | | * |
88 | | */ |
89 | | static const Curve *get(const pgp_curve_t curve_id); |
90 | | |
91 | | static bool alg_allows(pgp_pubkey_alg_t alg, pgp_curve_t curve); |
92 | | |
93 | | /** |
94 | | * @brief Check whether curve is supported for operations. |
95 | | * All available curves are supported for reading/parsing key data, however some of |
96 | | * them may be disabled for use, i.e. for key generation/signing/encryption. |
97 | | */ |
98 | | static bool is_supported(pgp_curve_t curve); |
99 | | |
100 | | size_t |
101 | | bytes() const noexcept |
102 | 144k | { |
103 | 144k | return BITS_TO_BYTES(bitlen); |
104 | 144k | } |
105 | | }; |
106 | | |
107 | | class Signature { |
108 | | public: |
109 | | mpi r{}; |
110 | | mpi s{}; |
111 | | }; |
112 | | |
113 | | class Key { |
114 | | public: |
115 | | pgp_curve_t curve; |
116 | | mpi p; |
117 | | /* secret mpi */ |
118 | | mpi x; |
119 | | /* ecdh params */ |
120 | | pgp_hash_alg_t kdf_hash_alg; /* Hash used by kdf */ |
121 | | pgp_symm_alg_t key_wrap_alg; /* Symmetric algorithm used to wrap KEK*/ |
122 | | |
123 | | void |
124 | | clear_secret() |
125 | 867k | { |
126 | 867k | x.forget(); |
127 | 867k | } |
128 | | |
129 | | ~Key() |
130 | 806k | { |
131 | 806k | clear_secret(); |
132 | 806k | } |
133 | | |
134 | | /** |
135 | | * @brief Generates EC key in uncompressed format |
136 | | * |
137 | | * @param rng initialized rnp::RNG context |
138 | | * @param alg_id ID of EC algorithm |
139 | | * @param curve underlying ECC curve ID |
140 | | * |
141 | | * @pre alg_id MUST be supported algorithm |
142 | | * |
143 | | * @returns RNP_ERROR_BAD_PARAMETERS unknown curve_id |
144 | | * @returns RNP_ERROR_OUT_OF_MEMORY memory allocation failed |
145 | | * @returns RNP_ERROR_KEY_GENERATION implementation error |
146 | | */ |
147 | | rnp_result_t generate(rnp::RNG & rng, |
148 | | const pgp_pubkey_alg_t alg_id, |
149 | | const pgp_curve_t curve); |
150 | | |
151 | | /** |
152 | | * @brief Generates x25519 ECDH key in x25519-specific format |
153 | | * |
154 | | * @param rng initialized rnp::RNG context* |
155 | | * |
156 | | * @returns RNP_ERROR_KEY_GENERATION implementation error |
157 | | */ |
158 | | rnp_result_t generate_x25519(rnp::RNG &rng); |
159 | | }; |
160 | | |
161 | | } // namespace ec |
162 | | } // namespace pgp |
163 | | |
164 | | /** |
165 | | * @brief Set least significant/most significant bits of the 25519 secret key as per |
166 | | * specification. |
167 | | * |
168 | | * @param key secret key. |
169 | | * @return true on success or false otherwise. |
170 | | */ |
171 | | bool x25519_tweak_bits(pgp::ec::Key &key); |
172 | | |
173 | | /** |
174 | | * @brief Check whether least significant/most significant bits of 25519 secret key are |
175 | | * correctly tweaked. |
176 | | * |
177 | | * @param key secret key. |
178 | | * @return true if bits are set correctly, and false otherwise. |
179 | | */ |
180 | | bool x25519_bits_tweaked(const pgp::ec::Key &key); |
181 | | |
182 | | #if defined(ENABLE_CRYPTO_REFRESH) || defined(ENABLE_PQC) |
183 | | typedef struct pgp_ed25519_key_t { |
184 | | std::vector<uint8_t> pub; // \ native encoding |
185 | | std::vector<uint8_t> priv; // / |
186 | | |
187 | | void |
188 | | clear_secret() |
189 | 55.4k | { |
190 | 55.4k | secure_clear(priv.data(), priv.size()); |
191 | 55.4k | priv.resize(0); |
192 | 55.4k | } |
193 | | |
194 | | ~pgp_ed25519_key_t() |
195 | 50.2k | { |
196 | 50.2k | clear_secret(); |
197 | 50.2k | } |
198 | | } pgp_ed25519_key_t; |
199 | | |
200 | | typedef struct pgp_ed25519_signature_t { |
201 | | std::vector<uint8_t> sig; // native encoding |
202 | | } pgp_ed25519_signature_t; |
203 | | |
204 | | typedef struct pgp_x25519_key_t { |
205 | | std::vector<uint8_t> pub; // \ native encoding |
206 | | std::vector<uint8_t> priv; // / |
207 | | |
208 | | void |
209 | | clear_secret() |
210 | 31.7k | { |
211 | 31.7k | secure_clear(priv.data(), priv.size()); |
212 | 31.7k | priv.resize(0); |
213 | 31.7k | } |
214 | | |
215 | | ~pgp_x25519_key_t() |
216 | 28.3k | { |
217 | 28.3k | clear_secret(); |
218 | 28.3k | } |
219 | | } pgp_x25519_key_t; |
220 | | |
221 | | typedef struct pgp_x25519_encrypted_t { |
222 | | std::vector<uint8_t> eph_key; |
223 | | std::vector<uint8_t> enc_sess_key; |
224 | | } pgp_x25519_encrypted_t; |
225 | | |
226 | | /* |
227 | | * @brief Generates EC keys in "native" or SEC1-encoded uncompressed format |
228 | | * |
229 | | * @param rng initialized rnp::RNG context* |
230 | | * @param privkey private key to be generated |
231 | | * @param pubkey public key to be generated |
232 | | * @param curve chosen curve |
233 | | * @param alg algorithm id |
234 | | * |
235 | | * @returns RNP_ERROR_BAD_PARAMETERS if the curve or alg parameter is invalid. |
236 | | */ |
237 | | rnp_result_t ec_generate_native(rnp::RNG * rng, |
238 | | std::vector<uint8_t> &privkey, |
239 | | std::vector<uint8_t> &pubkey, |
240 | | pgp_curve_t curve, |
241 | | pgp_pubkey_alg_t alg); |
242 | | #endif |
243 | | |
244 | | #endif |