Coverage Report

Created: 2025-08-28 06:26

/src/serenity/Userland/Libraries/LibCrypto/Curves/SECPxxxr1.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2023, Michiel Visser <opensource@webmichiel.nl>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#pragma once
8
9
#include <AK/ByteBuffer.h>
10
#include <AK/Endian.h>
11
#include <AK/MemoryStream.h>
12
#include <AK/Random.h>
13
#include <AK/StdLibExtras.h>
14
#include <AK/StringView.h>
15
#include <AK/UFixedBigInt.h>
16
#include <AK/UFixedBigIntDivision.h>
17
#include <LibCrypto/ASN1/DER.h>
18
#include <LibCrypto/Curves/EllipticCurve.h>
19
20
namespace Crypto::Curves {
21
22
struct SECPxxxr1CurveParameters {
23
    StringView prime;
24
    StringView a;
25
    StringView b;
26
    StringView order;
27
    StringView generator_point;
28
};
29
30
template<size_t bit_size, SECPxxxr1CurveParameters const& CURVE_PARAMETERS>
31
class SECPxxxr1 : public EllipticCurve {
32
private:
33
    using StorageType = AK::UFixedBigInt<bit_size>;
34
    using StorageTypeX2 = AK::UFixedBigInt<bit_size * 2>;
35
36
    struct JacobianPoint {
37
        StorageType x;
38
        StorageType y;
39
        StorageType z;
40
    };
41
42
    // Curve parameters
43
    static constexpr size_t KEY_BIT_SIZE = bit_size;
44
    static constexpr size_t KEY_BYTE_SIZE = KEY_BIT_SIZE / 8;
45
    static constexpr size_t POINT_BYTE_SIZE = 1 + 2 * KEY_BYTE_SIZE;
46
47
    static constexpr StorageType make_unsigned_fixed_big_int_from_string(StringView str)
48
0
    {
49
0
        StorageType result { 0 };
50
0
        for (auto c : str) {
51
0
            if (c == '_')
52
0
                continue;
53
0
54
0
            result <<= 4;
55
0
            result |= parse_ascii_hex_digit(c);
56
0
        }
57
0
        return result;
58
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::make_unsigned_fixed_big_int_from_string(AK::StringView)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::make_unsigned_fixed_big_int_from_string(AK::StringView)
59
60
    static constexpr StorageType PRIME = make_unsigned_fixed_big_int_from_string(CURVE_PARAMETERS.prime);
61
    static constexpr StorageType A = make_unsigned_fixed_big_int_from_string(CURVE_PARAMETERS.a);
62
    static constexpr StorageType B = make_unsigned_fixed_big_int_from_string(CURVE_PARAMETERS.b);
63
    static constexpr StorageType ORDER = make_unsigned_fixed_big_int_from_string(CURVE_PARAMETERS.order);
64
65
    static constexpr Array<u8, POINT_BYTE_SIZE> make_generator_point_bytes(StringView generator_point)
66
0
    {
67
0
        Array<u8, POINT_BYTE_SIZE> buf_array { 0 };
68
0
69
0
        auto it = generator_point.begin();
70
0
        for (size_t i = 0; i < POINT_BYTE_SIZE; i++) {
71
0
            if (it == CURVE_PARAMETERS.generator_point.end())
72
0
                break;
73
0
74
0
            while (*it == '_') {
75
0
                it++;
76
0
            }
77
0
78
0
            buf_array[i] = parse_ascii_hex_digit(*it) * 16;
79
0
            it++;
80
0
            if (it == CURVE_PARAMETERS.generator_point.end())
81
0
                break;
82
0
83
0
            buf_array[i] += parse_ascii_hex_digit(*it);
84
0
            it++;
85
0
        }
86
0
87
0
        return buf_array;
88
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::make_generator_point_bytes(AK::StringView)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::make_generator_point_bytes(AK::StringView)
89
90
    static constexpr Array<u8, POINT_BYTE_SIZE> GENERATOR_POINT = make_generator_point_bytes(CURVE_PARAMETERS.generator_point);
91
92
    // Check that the generator point starts with 0x04
93
    static_assert(GENERATOR_POINT[0] == 0x04);
94
95
    static constexpr StorageType calculate_modular_inverse_mod_r(StorageType value)
96
0
    {
97
0
        // Calculate the modular multiplicative inverse of value mod 2^bit_size using the extended euclidean algorithm
98
0
        using StorageTypeP1 = AK::UFixedBigInt<bit_size + 1>;
99
0
100
0
        StorageTypeP1 old_r = value;
101
0
        StorageTypeP1 r = static_cast<StorageTypeP1>(1u) << KEY_BIT_SIZE;
102
0
        StorageTypeP1 old_s = 1u;
103
0
        StorageTypeP1 s = 0u;
104
0
105
0
        while (!r.is_zero_constant_time()) {
106
0
            StorageTypeP1 r_save = r;
107
0
            StorageTypeP1 quotient = old_r.div_mod(r, r);
108
0
            old_r = r_save;
109
0
110
0
            StorageTypeP1 s_save = s;
111
0
            s = old_s - quotient * s;
112
0
            old_s = s_save;
113
0
        }
114
0
115
0
        return static_cast<StorageType>(old_s);
116
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::calculate_modular_inverse_mod_r(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> >)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::calculate_modular_inverse_mod_r(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> >)
117
118
    static constexpr StorageType calculate_r2_mod(StorageType modulus)
119
0
    {
120
0
        // Calculate the value of R^2 mod modulus, where R = 2^bit_size
121
0
        using StorageTypeX2P1 = AK::UFixedBigInt<bit_size * 2 + 1>;
122
0
123
0
        StorageTypeX2P1 r2 = static_cast<StorageTypeX2P1>(1u) << (2 * KEY_BIT_SIZE);
124
0
        return r2 % modulus;
125
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::calculate_r2_mod(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> >)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::calculate_r2_mod(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> >)
126
127
    // Verify that A = -3 mod p, which is required for some optimizations
128
    static_assert(A == PRIME - 3);
129
130
    // Precomputed helper values for reduction and Montgomery multiplication
131
    static constexpr StorageType REDUCE_PRIME = StorageType { 0 } - PRIME;
132
    static constexpr StorageType REDUCE_ORDER = StorageType { 0 } - ORDER;
133
    static constexpr StorageType PRIME_INVERSE_MOD_R = StorageType { 0 } - calculate_modular_inverse_mod_r(PRIME);
134
    static constexpr StorageType ORDER_INVERSE_MOD_R = StorageType { 0 } - calculate_modular_inverse_mod_r(ORDER);
135
    static constexpr StorageType R2_MOD_PRIME = calculate_r2_mod(PRIME);
136
    static constexpr StorageType R2_MOD_ORDER = calculate_r2_mod(ORDER);
137
138
public:
139
0
    size_t key_size() override { return POINT_BYTE_SIZE; }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::key_size()
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::key_size()
140
141
    ErrorOr<ByteBuffer> generate_private_key() override
142
0
    {
143
0
        auto buffer = TRY(ByteBuffer::create_uninitialized(KEY_BYTE_SIZE));
144
0
        fill_with_random(buffer);
145
0
        return buffer;
146
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::generate_private_key()
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::generate_private_key()
147
148
    ErrorOr<ByteBuffer> generate_public_key(ReadonlyBytes a) override
149
0
    {
150
0
        return compute_coordinate(a, GENERATOR_POINT);
151
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::generate_public_key(AK::Span<unsigned char const>)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::generate_public_key(AK::Span<unsigned char const>)
152
153
    ErrorOr<ByteBuffer> compute_coordinate(ReadonlyBytes scalar_bytes, ReadonlyBytes point_bytes) override
154
0
    {
155
0
        AK::FixedMemoryStream scalar_stream { scalar_bytes };
156
0
        AK::FixedMemoryStream point_stream { point_bytes };
157
158
0
        StorageType scalar = TRY(scalar_stream.read_value<BigEndian<StorageType>>());
159
0
        JacobianPoint point = TRY(read_uncompressed_point(point_stream));
160
0
        JacobianPoint result = TRY(compute_coordinate_internal(scalar, point));
161
162
        // Export the values into an output buffer
163
0
        auto buf = TRY(ByteBuffer::create_uninitialized(POINT_BYTE_SIZE));
164
0
        AK::FixedMemoryStream buf_stream { buf.bytes() };
165
0
        TRY(buf_stream.write_value<u8>(0x04));
166
0
        TRY(buf_stream.write_value<BigEndian<StorageType>>(result.x));
167
0
        TRY(buf_stream.write_value<BigEndian<StorageType>>(result.y));
168
0
        return buf;
169
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::compute_coordinate(AK::Span<unsigned char const>, AK::Span<unsigned char const>)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::compute_coordinate(AK::Span<unsigned char const>, AK::Span<unsigned char const>)
170
171
    ErrorOr<ByteBuffer> derive_premaster_key(ReadonlyBytes shared_point) override
172
0
    {
173
0
        VERIFY(shared_point.size() == POINT_BYTE_SIZE);
174
0
        VERIFY(shared_point[0] == 0x04);
175
176
0
        ByteBuffer premaster_key = TRY(ByteBuffer::create_uninitialized(KEY_BYTE_SIZE));
177
0
        premaster_key.overwrite(0, shared_point.data() + 1, KEY_BYTE_SIZE);
178
0
        return premaster_key;
179
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::derive_premaster_key(AK::Span<unsigned char const>)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::derive_premaster_key(AK::Span<unsigned char const>)
180
181
    ErrorOr<bool> verify(ReadonlyBytes hash, ReadonlyBytes pubkey, ReadonlyBytes signature)
182
0
    {
183
0
        Crypto::ASN1::Decoder asn1_decoder(signature);
184
0
        TRY(asn1_decoder.enter());
185
186
0
        auto r_bigint = TRY(asn1_decoder.read<Crypto::UnsignedBigInteger>(Crypto::ASN1::Class::Universal, Crypto::ASN1::Kind::Integer));
187
0
        auto s_bigint = TRY(asn1_decoder.read<Crypto::UnsignedBigInteger>(Crypto::ASN1::Class::Universal, Crypto::ASN1::Kind::Integer));
188
189
0
        size_t expected_word_count = KEY_BIT_SIZE / 32;
190
0
        if (r_bigint.length() < expected_word_count || s_bigint.length() < expected_word_count) {
191
0
            return false;
192
0
        }
193
194
0
        StorageType r = 0u;
195
0
        StorageType s = 0u;
196
0
        for (size_t i = 0; i < (KEY_BIT_SIZE / 32); i++) {
197
0
            StorageType rr = r_bigint.words()[i];
198
0
            StorageType ss = s_bigint.words()[i];
199
0
            r |= (rr << (i * 32));
200
0
            s |= (ss << (i * 32));
201
0
        }
202
203
        // z is the hash
204
0
        StorageType z = 0u;
205
0
        for (uint8_t byte : hash) {
206
0
            z <<= 8;
207
0
            z |= byte;
208
0
        }
209
210
0
        AK::FixedMemoryStream pubkey_stream { pubkey };
211
0
        JacobianPoint pubkey_point = TRY(read_uncompressed_point(pubkey_stream));
212
213
0
        StorageType r_mo = to_montgomery_order(r);
214
0
        StorageType s_mo = to_montgomery_order(s);
215
0
        StorageType z_mo = to_montgomery_order(z);
216
217
0
        StorageType s_inv = modular_inverse_order(s_mo);
218
219
0
        StorageType u1 = modular_multiply_order(z_mo, s_inv);
220
0
        StorageType u2 = modular_multiply_order(r_mo, s_inv);
221
222
0
        u1 = from_montgomery_order(u1);
223
0
        u2 = from_montgomery_order(u2);
224
225
0
        JacobianPoint point1 = TRY(generate_public_key_internal(u1));
226
0
        JacobianPoint point2 = TRY(compute_coordinate_internal(u2, pubkey_point));
227
228
        // Convert the input point into Montgomery form
229
0
        point1.x = to_montgomery(point1.x);
230
0
        point1.y = to_montgomery(point1.y);
231
0
        point1.z = to_montgomery(point1.z);
232
233
0
        VERIFY(is_point_on_curve(point1));
234
235
        // Convert the input point into Montgomery form
236
0
        point2.x = to_montgomery(point2.x);
237
0
        point2.y = to_montgomery(point2.y);
238
0
        point2.z = to_montgomery(point2.z);
239
240
0
        VERIFY(is_point_on_curve(point2));
241
242
0
        JacobianPoint result = point_add(point1, point2);
243
244
        // Convert from Jacobian coordinates back to Affine coordinates
245
0
        convert_jacobian_to_affine(result);
246
247
        // Make sure the resulting point is on the curve
248
0
        VERIFY(is_point_on_curve(result));
249
250
        // Convert the result back from Montgomery form
251
0
        result.x = from_montgomery(result.x);
252
0
        result.y = from_montgomery(result.y);
253
        // Final modular reduction on the coordinates
254
0
        result.x = modular_reduce(result.x);
255
0
        result.y = modular_reduce(result.y);
256
257
0
        return r.is_equal_to_constant_time(result.x);
258
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::verify(AK::Span<unsigned char const>, AK::Span<unsigned char const>, AK::Span<unsigned char const>)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::verify(AK::Span<unsigned char const>, AK::Span<unsigned char const>, AK::Span<unsigned char const>)
259
260
private:
261
    ErrorOr<JacobianPoint> generate_public_key_internal(StorageType a)
262
0
    {
263
0
        AK::FixedMemoryStream generator_point_stream { GENERATOR_POINT };
264
0
        JacobianPoint point = TRY(read_uncompressed_point(generator_point_stream));
265
0
        return compute_coordinate_internal(a, point);
266
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::generate_public_key_internal(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> >)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::generate_public_key_internal(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> >)
267
268
    ErrorOr<JacobianPoint> compute_coordinate_internal(StorageType scalar, JacobianPoint point)
269
0
    {
270
        // FIXME: This will slightly bias the distribution of client secrets
271
0
        scalar = modular_reduce_order(scalar);
272
0
        if (scalar.is_zero_constant_time())
273
0
            return Error::from_string_literal("SECPxxxr1: scalar is zero");
274
275
        // Convert the input point into Montgomery form
276
0
        point.x = to_montgomery(point.x);
277
0
        point.y = to_montgomery(point.y);
278
0
        point.z = to_montgomery(point.z);
279
280
        // Check that the point is on the curve
281
0
        if (!is_point_on_curve(point))
282
0
            return Error::from_string_literal("SECPxxxr1: point is not on the curve");
283
284
0
        JacobianPoint result { 0, 0, 0 };
285
0
        JacobianPoint temp_result { 0, 0, 0 };
286
287
        // Calculate the scalar times point multiplication in constant time
288
0
        for (size_t i = 0; i < KEY_BIT_SIZE; i++) {
289
0
            temp_result = point_add(result, point);
290
291
0
            auto condition = (scalar & 1u) == 1u;
292
0
            result.x = select(result.x, temp_result.x, condition);
293
0
            result.y = select(result.y, temp_result.y, condition);
294
0
            result.z = select(result.z, temp_result.z, condition);
295
296
0
            point = point_double(point);
297
0
            scalar >>= 1u;
298
0
        }
299
300
        // Convert from Jacobian coordinates back to Affine coordinates
301
0
        convert_jacobian_to_affine(result);
302
303
        // Make sure the resulting point is on the curve
304
0
        VERIFY(is_point_on_curve(result));
305
306
        // Convert the result back from Montgomery form
307
0
        result.x = from_montgomery(result.x);
308
0
        result.y = from_montgomery(result.y);
309
0
        result.z = from_montgomery(result.z);
310
        // Final modular reduction on the coordinates
311
0
        result.x = modular_reduce(result.x);
312
0
        result.y = modular_reduce(result.y);
313
0
        result.z = modular_reduce(result.z);
314
315
0
        return result;
316
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::compute_coordinate_internal(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> >, Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::JacobianPoint)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::compute_coordinate_internal(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> >, Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::JacobianPoint)
317
318
    static ErrorOr<JacobianPoint> read_uncompressed_point(Stream& stream)
319
0
    {
320
        // Make sure the point is uncompressed
321
0
        if (TRY(stream.read_value<u8>()) != 0x04)
322
0
            return Error::from_string_literal("SECPxxxr1: point is not uncompressed format");
323
324
0
        JacobianPoint point {
325
0
            TRY(stream.read_value<BigEndian<StorageType>>()),
326
0
            TRY(stream.read_value<BigEndian<StorageType>>()),
327
0
            1u,
328
0
        };
329
330
0
        return point;
331
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::read_uncompressed_point(AK::Stream&)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::read_uncompressed_point(AK::Stream&)
332
333
    constexpr StorageType select(StorageType const& left, StorageType const& right, bool condition)
334
0
    {
335
        // If condition = 0 return left else right
336
0
        StorageType mask = static_cast<StorageType>(condition) - 1;
337
0
        AK::taint_for_optimizer(mask);
338
339
0
        return (left & mask) | (right & ~mask);
340
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::select(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&, AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&, bool)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::select(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&, AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&, bool)
341
342
    constexpr StorageType modular_reduce(StorageType const& value)
343
0
    {
344
        // Add -prime % 2^KEY_BIT_SIZE
345
0
        bool carry = false;
346
0
        StorageType other = value.addc(REDUCE_PRIME, carry);
347
348
        // Check for overflow
349
0
        return select(value, other, carry);
350
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::modular_reduce(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::modular_reduce(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&)
351
352
    constexpr StorageType modular_reduce_order(StorageType const& value)
353
0
    {
354
        // Add -order % 2^KEY_BIT_SIZE
355
0
        bool carry = false;
356
0
        StorageType other = value.addc(REDUCE_ORDER, carry);
357
358
        // Check for overflow
359
0
        return select(value, other, carry);
360
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::modular_reduce_order(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::modular_reduce_order(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&)
361
362
    constexpr StorageType modular_add(StorageType const& left, StorageType const& right, bool carry_in = false)
363
0
    {
364
0
        bool carry = carry_in;
365
0
        StorageType output = left.addc(right, carry);
366
367
        // If there is a carry, subtract p by adding 2^KEY_BIT_SIZE - p
368
0
        StorageType addend = select(0u, REDUCE_PRIME, carry);
369
0
        carry = false;
370
0
        output = output.addc(addend, carry);
371
372
        // If there is still a carry, subtract p by adding 2^KEY_BIT_SIZE - p
373
0
        addend = select(0u, REDUCE_PRIME, carry);
374
0
        return output + addend;
375
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::modular_add(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&, AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&, bool)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::modular_add(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&, AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&, bool)
376
377
    constexpr StorageType modular_sub(StorageType const& left, StorageType const& right)
378
0
    {
379
0
        bool borrow = false;
380
0
        StorageType output = left.subc(right, borrow);
381
382
        // If there is a borrow, add p by subtracting 2^KEY_BIT_SIZE - p
383
0
        StorageType sub = select(0u, REDUCE_PRIME, borrow);
384
0
        borrow = false;
385
0
        output = output.subc(sub, borrow);
386
387
        // If there is still a borrow, add p by subtracting 2^KEY_BIT_SIZE - p
388
0
        sub = select(0u, REDUCE_PRIME, borrow);
389
0
        return output - sub;
390
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::modular_sub(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&, AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::modular_sub(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&, AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&)
391
392
    constexpr StorageType modular_multiply(StorageType const& left, StorageType const& right)
393
0
    {
394
        // Modular multiplication using the Montgomery method: https://en.wikipedia.org/wiki/Montgomery_modular_multiplication
395
        // This requires that the inputs to this function are in Montgomery form.
396
397
        // T = left * right
398
0
        StorageTypeX2 mult = left.wide_multiply(right);
399
0
        StorageType mult_mod_r = static_cast<StorageType>(mult);
400
401
        // m = ((T mod R) * curve_p')
402
0
        StorageType m = mult_mod_r * PRIME_INVERSE_MOD_R;
403
404
        // mp = (m mod R) * curve_p
405
0
        StorageTypeX2 mp = m.wide_multiply(PRIME);
406
407
        // t = (T + mp)
408
0
        bool carry = false;
409
0
        mult_mod_r.addc(static_cast<StorageType>(mp), carry);
410
411
        // output = t / R
412
0
        StorageType mult_high = static_cast<StorageType>(mult >> KEY_BIT_SIZE);
413
0
        StorageType mp_high = static_cast<StorageType>(mp >> KEY_BIT_SIZE);
414
0
        return modular_add(mult_high, mp_high, carry);
415
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::modular_multiply(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&, AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::modular_multiply(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&, AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&)
416
417
    constexpr StorageType modular_square(StorageType const& value)
418
0
    {
419
0
        return modular_multiply(value, value);
420
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::modular_square(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::modular_square(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&)
421
422
    constexpr StorageType to_montgomery(StorageType const& value)
423
0
    {
424
0
        return modular_multiply(value, R2_MOD_PRIME);
425
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::to_montgomery(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::to_montgomery(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&)
426
427
    constexpr StorageType from_montgomery(StorageType const& value)
428
0
    {
429
0
        return modular_multiply(value, 1u);
430
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::from_montgomery(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::from_montgomery(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&)
431
432
    constexpr StorageType modular_inverse(StorageType const& value)
433
0
    {
434
        // Modular inverse modulo the curve prime can be computed using Fermat's little theorem: a^(p-2) mod p = a^-1 mod p.
435
        // Calculating a^(p-2) mod p can be done using the square-and-multiply exponentiation method, as p-2 is constant.
436
0
        StorageType base = value;
437
0
        StorageType result = to_montgomery(1u);
438
0
        StorageType prime_minus_2 = PRIME - 2u;
439
440
0
        for (size_t i = 0; i < KEY_BIT_SIZE; i++) {
441
0
            if ((prime_minus_2 & 1u) == 1u) {
442
0
                result = modular_multiply(result, base);
443
0
            }
444
0
            base = modular_square(base);
445
0
            prime_minus_2 >>= 1u;
446
0
        }
447
448
0
        return result;
449
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::modular_inverse(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::modular_inverse(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&)
450
451
    constexpr StorageType modular_add_order(StorageType const& left, StorageType const& right, bool carry_in = false)
452
0
    {
453
0
        bool carry = carry_in;
454
0
        StorageType output = left.addc(right, carry);
455
456
        // If there is a carry, subtract n by adding 2^KEY_BIT_SIZE - n
457
0
        StorageType addend = select(0u, REDUCE_ORDER, carry);
458
0
        carry = false;
459
0
        output = output.addc(addend, carry);
460
461
        // If there is still a carry, subtract n by adding 2^KEY_BIT_SIZE - n
462
0
        addend = select(0u, REDUCE_ORDER, carry);
463
0
        return output + addend;
464
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::modular_add_order(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&, AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&, bool)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::modular_add_order(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&, AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&, bool)
465
466
    constexpr StorageType modular_multiply_order(StorageType const& left, StorageType const& right)
467
0
    {
468
        // Modular multiplication using the Montgomery method: https://en.wikipedia.org/wiki/Montgomery_modular_multiplication
469
        // This requires that the inputs to this function are in Montgomery form.
470
471
        // T = left * right
472
0
        StorageTypeX2 mult = left.wide_multiply(right);
473
0
        StorageType mult_mod_r = static_cast<StorageType>(mult);
474
475
        // m = ((T mod R) * curve_n')
476
0
        StorageType m = mult_mod_r * ORDER_INVERSE_MOD_R;
477
478
        // mp = (m mod R) * curve_n
479
0
        StorageTypeX2 mp = m.wide_multiply(ORDER);
480
481
        // t = (T + mp)
482
0
        bool carry = false;
483
0
        mult_mod_r.addc(static_cast<StorageType>(mp), carry);
484
485
        // output = t / R
486
0
        StorageType mult_high = static_cast<StorageType>(mult >> KEY_BIT_SIZE);
487
0
        StorageType mp_high = static_cast<StorageType>(mp >> KEY_BIT_SIZE);
488
0
        return modular_add_order(mult_high, mp_high, carry);
489
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::modular_multiply_order(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&, AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::modular_multiply_order(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&, AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&)
490
491
    constexpr StorageType modular_square_order(StorageType const& value)
492
0
    {
493
0
        return modular_multiply_order(value, value);
494
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::modular_square_order(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::modular_square_order(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&)
495
496
    constexpr StorageType to_montgomery_order(StorageType const& value)
497
0
    {
498
0
        return modular_multiply_order(value, R2_MOD_ORDER);
499
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::to_montgomery_order(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::to_montgomery_order(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&)
500
501
    constexpr StorageType from_montgomery_order(StorageType const& value)
502
0
    {
503
0
        return modular_multiply_order(value, 1u);
504
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::from_montgomery_order(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::from_montgomery_order(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&)
505
506
    constexpr StorageType modular_inverse_order(StorageType const& value)
507
0
    {
508
        // Modular inverse modulo the curve order can be computed using Fermat's little theorem: a^(n-2) mod n = a^-1 mod n.
509
        // Calculating a^(n-2) mod n can be done using the square-and-multiply exponentiation method, as n-2 is constant.
510
0
        StorageType base = value;
511
0
        StorageType result = to_montgomery_order(1u);
512
0
        StorageType order_minus_2 = ORDER - 2u;
513
514
0
        for (size_t i = 0; i < KEY_BIT_SIZE; i++) {
515
0
            if ((order_minus_2 & 1u) == 1u) {
516
0
                result = modular_multiply_order(result, base);
517
0
            }
518
0
            base = modular_square_order(base);
519
0
            order_minus_2 >>= 1u;
520
0
        }
521
522
0
        return result;
523
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::modular_inverse_order(AK::Detail::UFixedBigInt<256ul, AK::Detail::StaticStorage<false, 256ul> > const&)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::modular_inverse_order(AK::Detail::UFixedBigInt<384ul, AK::Detail::StaticStorage<false, 384ul> > const&)
524
525
    JacobianPoint point_double(JacobianPoint const& point)
526
0
    {
527
        // Based on "Point Doubling" from http://point-at-infinity.org/ecc/Prime_Curve_Jacobian_Coordinates.html
528
529
        // if (Y == 0)
530
        //   return POINT_AT_INFINITY
531
0
        if (point.y.is_zero_constant_time()) {
532
0
            VERIFY_NOT_REACHED();
533
0
        }
534
535
0
        StorageType temp;
536
537
        // Y2 = Y^2
538
0
        StorageType y2 = modular_square(point.y);
539
540
        // S = 4*X*Y2
541
0
        StorageType s = modular_multiply(point.x, y2);
542
0
        s = modular_add(s, s);
543
0
        s = modular_add(s, s);
544
545
        // M = 3*X^2 + a*Z^4 = 3*(X + Z^2)*(X - Z^2)
546
        // This specific equation from https://github.com/earlephilhower/bearssl-esp8266/blob/6105635531027f5b298aa656d44be2289b2d434f/src/ec/ec_p256_m64.c#L811-L816
547
        // This simplification only works because a = -3 mod p
548
0
        temp = modular_square(point.z);
549
0
        StorageType m = modular_add(point.x, temp);
550
0
        temp = modular_sub(point.x, temp);
551
0
        m = modular_multiply(m, temp);
552
0
        temp = modular_add(m, m);
553
0
        m = modular_add(m, temp);
554
555
        // X' = M^2 - 2*S
556
0
        StorageType xp = modular_square(m);
557
0
        xp = modular_sub(xp, s);
558
0
        xp = modular_sub(xp, s);
559
560
        // Y' = M*(S - X') - 8*Y2^2
561
0
        StorageType yp = modular_sub(s, xp);
562
0
        yp = modular_multiply(yp, m);
563
0
        temp = modular_square(y2);
564
0
        temp = modular_add(temp, temp);
565
0
        temp = modular_add(temp, temp);
566
0
        temp = modular_add(temp, temp);
567
0
        yp = modular_sub(yp, temp);
568
569
        // Z' = 2*Y*Z
570
0
        StorageType zp = modular_multiply(point.y, point.z);
571
0
        zp = modular_add(zp, zp);
572
573
        // return (X', Y', Z')
574
0
        return JacobianPoint { xp, yp, zp };
575
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::point_double(Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::JacobianPoint const&)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::point_double(Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::JacobianPoint const&)
576
577
    JacobianPoint point_add(JacobianPoint const& point_a, JacobianPoint const& point_b)
578
0
    {
579
        // Based on "Point Addition" from  http://point-at-infinity.org/ecc/Prime_Curve_Jacobian_Coordinates.html
580
0
        if (point_a.x.is_zero_constant_time() && point_a.y.is_zero_constant_time() && point_a.z.is_zero_constant_time()) {
581
0
            return point_b;
582
0
        }
583
584
0
        StorageType temp;
585
586
0
        temp = modular_square(point_b.z);
587
        // U1 = X1*Z2^2
588
0
        StorageType u1 = modular_multiply(point_a.x, temp);
589
        // S1 = Y1*Z2^3
590
0
        StorageType s1 = modular_multiply(point_a.y, temp);
591
0
        s1 = modular_multiply(s1, point_b.z);
592
593
0
        temp = modular_square(point_a.z);
594
        // U2 = X2*Z1^2
595
0
        StorageType u2 = modular_multiply(point_b.x, temp);
596
        // S2 = Y2*Z1^3
597
0
        StorageType s2 = modular_multiply(point_b.y, temp);
598
0
        s2 = modular_multiply(s2, point_a.z);
599
600
        // if (U1 == U2)
601
        //   if (S1 != S2)
602
        //     return POINT_AT_INFINITY
603
        //   else
604
        //     return POINT_DOUBLE(X1, Y1, Z1)
605
0
        if (u1.is_equal_to_constant_time(u2)) {
606
0
            if (s1.is_equal_to_constant_time(s2)) {
607
0
                return point_double(point_a);
608
0
            } else {
609
0
                VERIFY_NOT_REACHED();
610
0
            }
611
0
        }
612
613
        // H = U2 - U1
614
0
        StorageType h = modular_sub(u2, u1);
615
0
        StorageType h2 = modular_square(h);
616
0
        StorageType h3 = modular_multiply(h2, h);
617
        // R = S2 - S1
618
0
        StorageType r = modular_sub(s2, s1);
619
        // X3 = R^2 - H^3 - 2*U1*H^2
620
0
        StorageType x3 = modular_square(r);
621
0
        x3 = modular_sub(x3, h3);
622
0
        temp = modular_multiply(u1, h2);
623
0
        temp = modular_add(temp, temp);
624
0
        x3 = modular_sub(x3, temp);
625
        // Y3 = R*(U1*H^2 - X3) - S1*H^3
626
0
        StorageType y3 = modular_multiply(u1, h2);
627
0
        y3 = modular_sub(y3, x3);
628
0
        y3 = modular_multiply(y3, r);
629
0
        temp = modular_multiply(s1, h3);
630
0
        y3 = modular_sub(y3, temp);
631
        // Z3 = H*Z1*Z2
632
0
        StorageType z3 = modular_multiply(h, point_a.z);
633
0
        z3 = modular_multiply(z3, point_b.z);
634
        // return (X3, Y3, Z3)
635
0
        return JacobianPoint { x3, y3, z3 };
636
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::point_add(Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::JacobianPoint const&, Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::JacobianPoint const&)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::point_add(Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::JacobianPoint const&, Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::JacobianPoint const&)
637
638
    void convert_jacobian_to_affine(JacobianPoint& point)
639
0
    {
640
0
        StorageType temp;
641
        // X' = X/Z^2
642
0
        temp = modular_square(point.z);
643
0
        temp = modular_inverse(temp);
644
0
        point.x = modular_multiply(point.x, temp);
645
        // Y' = Y/Z^3
646
0
        temp = modular_square(point.z);
647
0
        temp = modular_multiply(temp, point.z);
648
0
        temp = modular_inverse(temp);
649
0
        point.y = modular_multiply(point.y, temp);
650
        // Z' = 1
651
0
        point.z = to_montgomery(1u);
652
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::convert_jacobian_to_affine(Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::JacobianPoint&)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::convert_jacobian_to_affine(Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::JacobianPoint&)
653
654
    bool is_point_on_curve(JacobianPoint const& point)
655
0
    {
656
        // This check requires the point to be in Montgomery form, with Z=1
657
0
        StorageType temp, temp2;
658
659
        // Calulcate Y^2 - X^3 - a*X - b = Y^2 - X^3 + 3*X - b
660
0
        temp = modular_square(point.y);
661
0
        temp2 = modular_square(point.x);
662
0
        temp2 = modular_multiply(temp2, point.x);
663
0
        temp = modular_sub(temp, temp2);
664
0
        temp = modular_add(temp, point.x);
665
0
        temp = modular_add(temp, point.x);
666
0
        temp = modular_add(temp, point.x);
667
0
        temp = modular_sub(temp, to_montgomery(B));
668
0
        temp = modular_reduce(temp);
669
670
0
        return temp.is_zero_constant_time() && point.z.is_equal_to_constant_time(to_montgomery(1u));
671
0
    }
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::is_point_on_curve(Crypto::Curves::SECPxxxr1<256ul, Crypto::Curves::SECP256r1_CURVE_PARAMETERS>::JacobianPoint const&)
Unexecuted instantiation: CryptoAlgorithms.cpp:Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::is_point_on_curve(Crypto::Curves::SECPxxxr1<384ul, Crypto::Curves::SECP384r1_CURVE_PARAMETERS>::JacobianPoint const&)
672
};
673
674
// SECP256r1 curve
675
static constexpr SECPxxxr1CurveParameters SECP256r1_CURVE_PARAMETERS {
676
    .prime = "FFFFFFFF_00000001_00000000_00000000_00000000_FFFFFFFF_FFFFFFFF_FFFFFFFF"sv,
677
    .a = "FFFFFFFF_00000001_00000000_00000000_00000000_FFFFFFFF_FFFFFFFF_FFFFFFFC"sv,
678
    .b = "5AC635D8_AA3A93E7_B3EBBD55_769886BC_651D06B0_CC53B0F6_3BCE3C3E_27D2604B"sv,
679
    .order = "FFFFFFFF_00000000_FFFFFFFF_FFFFFFFF_BCE6FAAD_A7179E84_F3B9CAC2_FC632551"sv,
680
    .generator_point = "04_6B17D1F2_E12C4247_F8BCE6E5_63A440F2_77037D81_2DEB33A0_F4A13945_D898C296_4FE342E2_FE1A7F9B_8EE7EB4A_7C0F9E16_2BCE3357_6B315ECE_CBB64068_37BF51F5"sv,
681
};
682
using SECP256r1 = SECPxxxr1<256, SECP256r1_CURVE_PARAMETERS>;
683
684
// SECP384r1 curve
685
static constexpr SECPxxxr1CurveParameters SECP384r1_CURVE_PARAMETERS {
686
    .prime = "FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFE_FFFFFFFF_00000000_00000000_FFFFFFFF"sv,
687
    .a = "FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFE_FFFFFFFF_00000000_00000000_FFFFFFFC"sv,
688
    .b = "B3312FA7_E23EE7E4_988E056B_E3F82D19_181D9C6E_FE814112_0314088F_5013875A_C656398D_8A2ED19D_2A85C8ED_D3EC2AEF"sv,
689
    .order = "FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_C7634D81_F4372DDF_581A0DB2_48B0A77A_ECEC196A_CCC52973"sv,
690
    .generator_point = "04_AA87CA22_BE8B0537_8EB1C71E_F320AD74_6E1D3B62_8BA79B98_59F741E0_82542A38_5502F25D_BF55296C_3A545E38_72760AB7_3617DE4A_96262C6F_5D9E98BF_9292DC29_F8F41DBD_289A147C_E9DA3113_B5F0B8C0_0A60B1CE_1D7E819D_7A431D7C_90EA0E5F"sv,
691
};
692
using SECP384r1 = SECPxxxr1<384, SECP384r1_CURVE_PARAMETERS>;
693
694
}