Coverage Report

Created: 2026-02-14 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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