Coverage Report

Created: 2026-05-24 07:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl34/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
151k
#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.68k
{
42
1.68k
    c448_dsword_t chain = 0;
43
1.68k
    unsigned int i;
44
1.68k
    c448_word_t borrow;
45
46
13.4k
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
47
11.7k
        chain = (chain + accum[i]) - sub->limb[i];
48
11.7k
        out->limb[i] = (c448_word_t)chain;
49
11.7k
        chain >>= WBITS;
50
11.7k
    }
51
1.68k
    borrow = (c448_word_t)chain + extra; /* = 0 or -1 */
52
53
1.68k
    chain = 0;
54
13.4k
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
55
11.7k
        chain = (chain + out->limb[i]) + (p->limb[i] & borrow);
56
11.7k
        out->limb[i] = (c448_word_t)chain;
57
11.7k
        chain >>= WBITS;
58
11.7k
    }
59
1.68k
}
60
61
static void sc_montmul(curve448_scalar_t out, const curve448_scalar_t a,
62
    const curve448_scalar_t b)
63
1.12k
{
64
1.12k
    unsigned int i, j;
65
1.12k
    c448_word_t accum[C448_SCALAR_LIMBS + 1] = { 0 };
66
1.12k
    c448_word_t hi_carry = 0;
67
68
9.01k
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
69
7.88k
        c448_word_t mand = a->limb[i];
70
7.88k
        const c448_word_t *mier = b->limb;
71
72
7.88k
        c448_dword_t chain = 0;
73
63.1k
        for (j = 0; j < C448_SCALAR_LIMBS; j++) {
74
55.2k
            chain += ((c448_dword_t)mand) * mier[j] + accum[j];
75
55.2k
            accum[j] = (c448_word_t)chain;
76
55.2k
            chain >>= WBITS;
77
55.2k
        }
78
7.88k
        accum[j] = (c448_word_t)chain;
79
80
7.88k
        mand = accum[0] * MONTGOMERY_FACTOR;
81
7.88k
        chain = 0;
82
7.88k
        mier = sc_p->limb;
83
63.1k
        for (j = 0; j < C448_SCALAR_LIMBS; j++) {
84
55.2k
            chain += (c448_dword_t)mand * mier[j] + accum[j];
85
55.2k
            if (j)
86
47.3k
                accum[j - 1] = (c448_word_t)chain;
87
55.2k
            chain >>= WBITS;
88
55.2k
        }
89
7.88k
        chain += accum[j];
90
7.88k
        chain += hi_carry;
91
7.88k
        accum[j - 1] = (c448_word_t)chain;
92
7.88k
        hi_carry = chain >> WBITS;
93
7.88k
    }
94
95
1.12k
    sc_subx(out, accum, sc_p, sc_p, hi_carry);
96
1.12k
}
97
98
void ossl_curve448_scalar_mul(curve448_scalar_t out, const curve448_scalar_t a,
99
    const curve448_scalar_t b)
100
492
{
101
492
    sc_montmul(out, a, b);
102
492
    sc_montmul(out, out, sc_r2);
103
492
}
104
105
void ossl_curve448_scalar_sub(curve448_scalar_t out, const curve448_scalar_t a,
106
    const curve448_scalar_t b)
107
40
{
108
40
    sc_subx(out, a->limb, b, sc_p, 0);
109
40
}
110
111
void ossl_curve448_scalar_add(curve448_scalar_t out, const curve448_scalar_t a,
112
    const curve448_scalar_t b)
113
515
{
114
515
    c448_dword_t chain = 0;
115
515
    unsigned int i;
116
117
4.12k
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
118
3.60k
        chain = (chain + a->limb[i]) + b->limb[i];
119
3.60k
        out->limb[i] = (c448_word_t)chain;
120
3.60k
        chain >>= WBITS;
121
3.60k
    }
122
515
    sc_subx(out, out->limb, sc_p, sc_p, (c448_word_t)chain);
123
515
}
124
125
static ossl_inline void scalar_decode_short(curve448_scalar_t s,
126
    const unsigned char *ser,
127
    size_t nbytes)
128
595
{
129
595
    size_t i, j, k = 0;
130
131
4.76k
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
132
4.16k
        c448_word_t out = 0;
133
134
31.8k
        for (j = 0; j < sizeof(c448_word_t) && k < nbytes; j++, k++)
135
27.6k
            out |= ((c448_word_t)ser[k]) << (8 * j);
136
4.16k
        s->limb[i] = out;
137
4.16k
    }
138
595
}
139
140
c448_error_t
141
ossl_curve448_scalar_decode(curve448_scalar_t s,
142
    const unsigned char ser[C448_SCALAR_BYTES])
143
143
{
144
143
    unsigned int i;
145
143
    c448_dsword_t accum = 0;
146
147
143
    scalar_decode_short(s, ser, C448_SCALAR_BYTES);
148
1.14k
    for (i = 0; i < C448_SCALAR_LIMBS; i++)
149
1.00k
        accum = (accum + s->limb[i] - sc_p->limb[i]) >> WBITS;
150
    /* Here accum == 0 or -1 */
151
152
143
    ossl_curve448_scalar_mul(s, s, ossl_curve448_scalar_one); /* ham-handed reduce */
153
154
143
    return c448_succeed_if(~word_is_zero((uint32_t)accum));
155
143
}
156
157
void ossl_curve448_scalar_destroy(curve448_scalar_t scalar)
158
578
{
159
578
    OPENSSL_cleanse(scalar, sizeof(curve448_scalar_t));
160
578
}
161
162
void ossl_curve448_scalar_decode_long(curve448_scalar_t s,
163
    const unsigned char *ser, size_t ser_len)
164
452
{
165
452
    size_t i;
166
452
    curve448_scalar_t t1, t2;
167
168
452
    if (ser_len == 0) {
169
0
        curve448_scalar_copy(s, ossl_curve448_scalar_zero);
170
0
        return;
171
0
    }
172
173
452
    i = ser_len - (ser_len % C448_SCALAR_BYTES);
174
452
    if (i == ser_len)
175
349
        i -= C448_SCALAR_BYTES;
176
177
452
    scalar_decode_short(t1, &ser[i], ser_len - i);
178
179
452
    if (ser_len == sizeof(curve448_scalar_t)) {
180
349
        assert(i == 0);
181
        /* ham-handed reduce */
182
349
        ossl_curve448_scalar_mul(s, t1, ossl_curve448_scalar_one);
183
349
        ossl_curve448_scalar_destroy(t1);
184
349
        return;
185
349
    }
186
187
246
    while (i) {
188
143
        i -= C448_SCALAR_BYTES;
189
143
        sc_montmul(t1, t1, sc_r2);
190
143
        (void)ossl_curve448_scalar_decode(t2, ser + i);
191
143
        ossl_curve448_scalar_add(t1, t1, t2);
192
143
    }
193
194
103
    curve448_scalar_copy(s, t1);
195
103
    ossl_curve448_scalar_destroy(t1);
196
103
    ossl_curve448_scalar_destroy(t2);
197
103
}
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
767
{
212
767
    c448_word_t mask = 0 - (a->limb[0] & 1);
213
767
    c448_dword_t chain = 0;
214
767
    unsigned int i;
215
216
767
    mask = value_barrier_c448(mask);
217
6.13k
    for (i = 0; i < C448_SCALAR_LIMBS; i++) {
218
5.36k
        chain = (chain + a->limb[i]) + (sc_p->limb[i] & mask);
219
5.36k
        out->limb[i] = (c448_word_t)chain;
220
5.36k
        chain >>= C448_WORD_BITS;
221
5.36k
    }
222
5.36k
    for (i = 0; i < C448_SCALAR_LIMBS - 1; i++)
223
4.60k
        out->limb[i] = out->limb[i] >> 1 | out->limb[i + 1] << (WBITS - 1);
224
767
    out->limb[i] = out->limb[i] >> 1 | (c448_word_t)(chain << (WBITS - 1));
225
767
}