Coverage Report

Created: 2026-07-23 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl35/crypto/ec/curve448/scalar.c
Line
Count
Source
1
/*
2
 * Copyright 2017-2026 The OpenSSL Project Authors. All Rights Reserved.
3
 * Copyright 2015-2016 Cryptography Research, Inc.
4
 *
5
 * Licensed under the Apache License 2.0 (the "License").  You may not use
6
 * this file except in compliance with the License.  You can obtain a copy
7
 * in the file LICENSE in the source distribution or at
8
 * https://www.openssl.org/source/license.html
9
 *
10
 * Originally written by Mike Hamburg
11
 */
12
#include <openssl/crypto.h>
13
14
#include "word.h"
15
#include "point_448.h"
16
17
static const c448_word_t MONTGOMERY_FACTOR = (c448_word_t)0x3bd440fae918bc5ULL;
18
static const curve448_scalar_t sc_p = {
19
    { { SC_LIMB(0x2378c292ab5844f3ULL), SC_LIMB(0x216cc2728dc58f55ULL),
20
        SC_LIMB(0xc44edb49aed63690ULL), SC_LIMB(0xffffffff7cca23e9ULL),
21
        SC_LIMB(0xffffffffffffffffULL), SC_LIMB(0xffffffffffffffffULL),
22
        SC_LIMB(0x3fffffffffffffffULL) } }
23
},
24
                               sc_r2 = { { {
25
26
                                   SC_LIMB(0xe3539257049b9b60ULL), SC_LIMB(0x7af32c4bc1b195d9ULL), SC_LIMB(0x0d66de2388ea1859ULL), SC_LIMB(0xae17cf725ee4d838ULL), SC_LIMB(0x1a9cc14ba3c47c44ULL), SC_LIMB(0x2052bcb7e4d070afULL), SC_LIMB(0x3402a939f823b729ULL) } } };
27
28
96.6k
#define WBITS C448_WORD_BITS /* NB this may be different from ARCH_WORD_BITS */
29
30
const curve448_scalar_t ossl_curve448_scalar_one = { { { 1 } } };
31
const curve448_scalar_t ossl_curve448_scalar_zero = { { { 0 } } };
32
33
/*
34
 * {extra,accum} - sub +? p
35
 * Must have extra <= 1
36
 */
37
static void sc_subx(curve448_scalar_t out,
38
    const c448_word_t accum[C448_SCALAR_LIMBS],
39
    const curve448_scalar_t sub,
40
    const curve448_scalar_t p, c448_word_t extra)
41
1.07k
{
42
1.07k
    c448_dsword_t chain = 0;
43
1.07k
    unsigned int i;
44
1.07k
    c448_word_t borrow;
45
46
8.56k
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
47
7.49k
        chain = (chain + accum[i]) - sub->limb[i];
48
7.49k
        out->limb[i] = (c448_word_t)chain;
49
7.49k
        chain >>= WBITS;
50
7.49k
    }
51
1.07k
    borrow = (c448_word_t)chain + extra; /* = 0 or -1 */
52
53
1.07k
    chain = 0;
54
8.56k
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
55
7.49k
        chain = (chain + out->limb[i]) + (p->limb[i] & borrow);
56
7.49k
        out->limb[i] = (c448_word_t)chain;
57
7.49k
        chain >>= WBITS;
58
7.49k
    }
59
1.07k
}
60
61
static void sc_montmul(curve448_scalar_t out, const curve448_scalar_t a,
62
    const curve448_scalar_t b)
63
705
{
64
705
    unsigned int i, j;
65
705
    c448_word_t accum[C448_SCALAR_LIMBS + 1] = { 0 };
66
705
    c448_word_t hi_carry = 0;
67
68
5.64k
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
69
4.93k
        c448_word_t mand = a->limb[i];
70
4.93k
        const c448_word_t *mier = b->limb;
71
72
4.93k
        c448_dword_t chain = 0;
73
39.4k
        for (j = 0; j < C448_SCALAR_LIMBS; j++) {
74
34.5k
            chain += ((c448_dword_t)mand) * mier[j] + accum[j];
75
34.5k
            accum[j] = (c448_word_t)chain;
76
34.5k
            chain >>= WBITS;
77
34.5k
        }
78
4.93k
        accum[j] = (c448_word_t)chain;
79
80
4.93k
        mand = accum[0] * MONTGOMERY_FACTOR;
81
4.93k
        chain = 0;
82
4.93k
        mier = sc_p->limb;
83
39.4k
        for (j = 0; j < C448_SCALAR_LIMBS; j++) {
84
34.5k
            chain += (c448_dword_t)mand * mier[j] + accum[j];
85
34.5k
            if (j)
86
29.6k
                accum[j - 1] = (c448_word_t)chain;
87
34.5k
            chain >>= WBITS;
88
34.5k
        }
89
4.93k
        chain += accum[j];
90
4.93k
        chain += hi_carry;
91
4.93k
        accum[j - 1] = (c448_word_t)chain;
92
4.93k
        hi_carry = chain >> WBITS;
93
4.93k
    }
94
95
705
    sc_subx(out, accum, sc_p, sc_p, hi_carry);
96
705
}
97
98
void ossl_curve448_scalar_mul(curve448_scalar_t out, const curve448_scalar_t a,
99
    const curve448_scalar_t b)
100
340
{
101
340
    sc_montmul(out, a, b);
102
340
    sc_montmul(out, out, sc_r2);
103
340
}
104
105
void ossl_curve448_scalar_sub(curve448_scalar_t out, const curve448_scalar_t a,
106
    const curve448_scalar_t b)
107
0
{
108
0
    sc_subx(out, a->limb, b, sc_p, 0);
109
0
}
110
111
void ossl_curve448_scalar_add(curve448_scalar_t out, const curve448_scalar_t a,
112
    const curve448_scalar_t b)
113
365
{
114
365
    c448_dword_t chain = 0;
115
365
    unsigned int i;
116
117
2.92k
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
118
2.55k
        chain = (chain + a->limb[i]) + b->limb[i];
119
2.55k
        out->limb[i] = (c448_word_t)chain;
120
2.55k
        chain >>= WBITS;
121
2.55k
    }
122
365
    sc_subx(out, out->limb, sc_p, sc_p, (c448_word_t)chain);
123
365
}
124
125
static ossl_inline void scalar_decode_short(curve448_scalar_t s,
126
    const unsigned char *ser,
127
    size_t nbytes)
128
365
{
129
365
    size_t i, j, k = 0;
130
131
2.92k
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
132
2.55k
        c448_word_t out = 0;
133
134
21.6k
        for (j = 0; j < sizeof(c448_word_t) && k < nbytes; j++, k++)
135
19.0k
            out |= ((c448_word_t)ser[k]) << (8 * j);
136
2.55k
        s->limb[i] = out;
137
2.55k
    }
138
365
}
139
140
c448_error_t
141
ossl_curve448_scalar_decode(curve448_scalar_t s,
142
    const unsigned char ser[C448_SCALAR_BYTES])
143
25
{
144
25
    unsigned int i;
145
25
    c448_dsword_t accum = 0;
146
147
25
    scalar_decode_short(s, ser, C448_SCALAR_BYTES);
148
200
    for (i = 0; i < C448_SCALAR_LIMBS; i++)
149
175
        accum = (accum + s->limb[i] - sc_p->limb[i]) >> WBITS;
150
    /* Here accum == 0 or -1 */
151
152
25
    ossl_curve448_scalar_mul(s, s, ossl_curve448_scalar_one); /* ham-handed reduce */
153
154
25
    return c448_succeed_if(~word_is_zero((uint32_t)accum));
155
25
}
156
157
void ossl_curve448_scalar_destroy(curve448_scalar_t scalar)
158
390
{
159
390
    OPENSSL_cleanse(scalar, sizeof(curve448_scalar_t));
160
390
}
161
162
void ossl_curve448_scalar_decode_long(curve448_scalar_t s,
163
    const unsigned char *ser, size_t ser_len)
164
340
{
165
340
    size_t i;
166
340
    curve448_scalar_t t1, t2;
167
168
340
    if (ser_len == 0) {
169
0
        curve448_scalar_copy(s, ossl_curve448_scalar_zero);
170
0
        return;
171
0
    }
172
173
340
    i = ser_len - (ser_len % C448_SCALAR_BYTES);
174
340
    if (i == ser_len)
175
315
        i -= C448_SCALAR_BYTES;
176
177
340
    scalar_decode_short(t1, &ser[i], ser_len - i);
178
179
340
    if (ser_len == sizeof(curve448_scalar_t)) {
180
315
        assert(i == 0);
181
        /* ham-handed reduce */
182
315
        ossl_curve448_scalar_mul(s, t1, ossl_curve448_scalar_one);
183
315
        ossl_curve448_scalar_destroy(t1);
184
315
        return;
185
315
    }
186
187
50
    while (i) {
188
25
        i -= C448_SCALAR_BYTES;
189
25
        sc_montmul(t1, t1, sc_r2);
190
25
        (void)ossl_curve448_scalar_decode(t2, ser + i);
191
25
        ossl_curve448_scalar_add(t1, t1, t2);
192
25
    }
193
194
25
    curve448_scalar_copy(s, t1);
195
25
    ossl_curve448_scalar_destroy(t1);
196
25
    ossl_curve448_scalar_destroy(t2);
197
25
}
198
199
void ossl_curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES],
200
    const curve448_scalar_t s)
201
0
{
202
0
    unsigned int i, j, k = 0;
203
204
0
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
205
0
        for (j = 0; j < sizeof(c448_word_t); j++, k++)
206
0
            ser[k] = s->limb[i] >> (8 * j);
207
0
    }
208
0
}
209
210
void ossl_curve448_scalar_halve(curve448_scalar_t out, const curve448_scalar_t a)
211
705
{
212
705
    c448_word_t mask = 0 - (a->limb[0] & 1);
213
705
    c448_dword_t chain = 0;
214
705
    unsigned int i;
215
216
705
    mask = value_barrier_c448(mask);
217
5.64k
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
218
4.93k
        chain = (chain + a->limb[i]) + (sc_p->limb[i] & mask);
219
4.93k
        out->limb[i] = (c448_word_t)chain;
220
4.93k
        chain >>= C448_WORD_BITS;
221
4.93k
    }
222
4.93k
    for (i = 0; i < C448_SCALAR_LIMBS - 1; i++)
223
4.23k
        out->limb[i] = out->limb[i] >> 1 | out->limb[i + 1] << (WBITS - 1);
224
705
    out->limb[i] = out->limb[i] >> 1 | (c448_word_t)(chain << (WBITS - 1));
225
705
}