Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl30/crypto/ec/curve448/scalar.c
Line
Count
Source
1
/*
2
 * Copyright 2017-2021 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
206k
#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
2.28k
{
42
2.28k
    c448_dsword_t chain = 0;
43
2.28k
    unsigned int i;
44
2.28k
    c448_word_t borrow;
45
46
18.2k
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
47
15.9k
        chain = (chain + accum[i]) - sub->limb[i];
48
15.9k
        out->limb[i] = (c448_word_t)chain;
49
15.9k
        chain >>= WBITS;
50
15.9k
    }
51
2.28k
    borrow = (c448_word_t)chain + extra; /* = 0 or -1 */
52
53
2.28k
    chain = 0;
54
18.2k
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
55
15.9k
        chain = (chain + out->limb[i]) + (p->limb[i] & borrow);
56
15.9k
        out->limb[i] = (c448_word_t)chain;
57
15.9k
        chain >>= WBITS;
58
15.9k
    }
59
2.28k
}
60
61
static void sc_montmul(curve448_scalar_t out, const curve448_scalar_t a,
62
    const curve448_scalar_t b)
63
1.52k
{
64
1.52k
    unsigned int i, j;
65
1.52k
    c448_word_t accum[C448_SCALAR_LIMBS + 1] = { 0 };
66
1.52k
    c448_word_t hi_carry = 0;
67
68
12.1k
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
69
10.6k
        c448_word_t mand = a->limb[i];
70
10.6k
        const c448_word_t *mier = b->limb;
71
72
10.6k
        c448_dword_t chain = 0;
73
85.3k
        for (j = 0; j < C448_SCALAR_LIMBS; j++) {
74
74.6k
            chain += ((c448_dword_t)mand) * mier[j] + accum[j];
75
74.6k
            accum[j] = (c448_word_t)chain;
76
74.6k
            chain >>= WBITS;
77
74.6k
        }
78
10.6k
        accum[j] = (c448_word_t)chain;
79
80
10.6k
        mand = accum[0] * MONTGOMERY_FACTOR;
81
10.6k
        chain = 0;
82
10.6k
        mier = sc_p->limb;
83
85.3k
        for (j = 0; j < C448_SCALAR_LIMBS; j++) {
84
74.6k
            chain += (c448_dword_t)mand * mier[j] + accum[j];
85
74.6k
            if (j)
86
64.0k
                accum[j - 1] = (c448_word_t)chain;
87
74.6k
            chain >>= WBITS;
88
74.6k
        }
89
10.6k
        chain += accum[j];
90
10.6k
        chain += hi_carry;
91
10.6k
        accum[j - 1] = (c448_word_t)chain;
92
10.6k
        hi_carry = chain >> WBITS;
93
10.6k
    }
94
95
1.52k
    sc_subx(out, accum, sc_p, sc_p, hi_carry);
96
1.52k
}
97
98
void ossl_curve448_scalar_mul(curve448_scalar_t out, const curve448_scalar_t a,
99
    const curve448_scalar_t b)
100
696
{
101
696
    sc_montmul(out, a, b);
102
696
    sc_montmul(out, out, sc_r2);
103
696
}
104
105
void ossl_curve448_scalar_sub(curve448_scalar_t out, const curve448_scalar_t a,
106
    const curve448_scalar_t b)
107
36
{
108
36
    sc_subx(out, a->limb, b, sc_p, 0);
109
36
}
110
111
void ossl_curve448_scalar_add(curve448_scalar_t out, const curve448_scalar_t a,
112
    const curve448_scalar_t b)
113
720
{
114
720
    c448_dword_t chain = 0;
115
720
    unsigned int i;
116
117
5.76k
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
118
5.04k
        chain = (chain + a->limb[i]) + b->limb[i];
119
5.04k
        out->limb[i] = (c448_word_t)chain;
120
5.04k
        chain >>= WBITS;
121
5.04k
    }
122
720
    sc_subx(out, out->limb, sc_p, sc_p, (c448_word_t)chain);
123
720
}
124
125
static ossl_inline void scalar_decode_short(curve448_scalar_t s,
126
    const unsigned char *ser,
127
    size_t nbytes)
128
792
{
129
792
    size_t i, j, k = 0;
130
131
6.33k
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
132
5.54k
        c448_word_t out = 0;
133
134
44.6k
        for (j = 0; j < sizeof(c448_word_t) && k < nbytes; j++, k++)
135
39.1k
            out |= ((c448_word_t)ser[k]) << (8 * j);
136
5.54k
        s->limb[i] = out;
137
5.54k
    }
138
792
}
139
140
c448_error_t
141
ossl_curve448_scalar_decode(curve448_scalar_t s,
142
    const unsigned char ser[C448_SCALAR_BYTES])
143
132
{
144
132
    unsigned int i;
145
132
    c448_dsword_t accum = 0;
146
147
132
    scalar_decode_short(s, ser, C448_SCALAR_BYTES);
148
1.05k
    for (i = 0; i < C448_SCALAR_LIMBS; i++)
149
924
        accum = (accum + s->limb[i] - sc_p->limb[i]) >> WBITS;
150
    /* Here accum == 0 or -1 */
151
152
132
    ossl_curve448_scalar_mul(s, s, ossl_curve448_scalar_one); /* ham-handed reduce */
153
154
132
    return c448_succeed_if(~word_is_zero((uint32_t)accum));
155
132
}
156
157
void ossl_curve448_scalar_destroy(curve448_scalar_t scalar)
158
780
{
159
780
    OPENSSL_cleanse(scalar, sizeof(curve448_scalar_t));
160
780
}
161
162
void ossl_curve448_scalar_decode_long(curve448_scalar_t s,
163
    const unsigned char *ser, size_t ser_len)
164
660
{
165
660
    size_t i;
166
660
    curve448_scalar_t t1, t2;
167
168
660
    if (ser_len == 0) {
169
0
        curve448_scalar_copy(s, ossl_curve448_scalar_zero);
170
0
        return;
171
0
    }
172
173
660
    i = ser_len - (ser_len % C448_SCALAR_BYTES);
174
660
    if (i == ser_len)
175
564
        i -= C448_SCALAR_BYTES;
176
177
660
    scalar_decode_short(t1, &ser[i], ser_len - i);
178
179
660
    if (ser_len == sizeof(curve448_scalar_t)) {
180
564
        assert(i == 0);
181
        /* ham-handed reduce */
182
564
        ossl_curve448_scalar_mul(s, t1, ossl_curve448_scalar_one);
183
564
        ossl_curve448_scalar_destroy(t1);
184
564
        return;
185
564
    }
186
187
228
    while (i) {
188
132
        i -= C448_SCALAR_BYTES;
189
132
        sc_montmul(t1, t1, sc_r2);
190
132
        (void)ossl_curve448_scalar_decode(t2, ser + i);
191
132
        ossl_curve448_scalar_add(t1, t1, t2);
192
132
    }
193
194
96
    curve448_scalar_copy(s, t1);
195
96
    ossl_curve448_scalar_destroy(t1);
196
96
    ossl_curve448_scalar_destroy(t2);
197
96
}
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
1.20k
{
212
1.20k
    c448_word_t mask = 0 - (a->limb[0] & 1);
213
1.20k
    c448_dword_t chain = 0;
214
1.20k
    unsigned int i;
215
216
9.60k
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
217
8.40k
        chain = (chain + a->limb[i]) + (sc_p->limb[i] & mask);
218
8.40k
        out->limb[i] = (c448_word_t)chain;
219
8.40k
        chain >>= C448_WORD_BITS;
220
8.40k
    }
221
8.40k
    for (i = 0; i < C448_SCALAR_LIMBS - 1; i++)
222
7.20k
        out->limb[i] = out->limb[i] >> 1 | out->limb[i + 1] << (WBITS - 1);
223
1.20k
    out->limb[i] = out->limb[i] >> 1 | (c448_word_t)(chain << (WBITS - 1));
224
1.20k
}