2 * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
3 * Copyright 2015-2016 Cryptography Research, Inc.
5 * Licensed under the OpenSSL license (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
10 * Originally written by Mike Hamburg
12 #include <openssl/crypto.h>
15 #include "constant_time.h"
16 #include "point_448.h"
18 static const c448_word_t MONTGOMERY_FACTOR
= (c448_word_t
) 0x3bd440fae918bc5;
19 static const curve448_scalar_t sc_p
= {
22 SC_LIMB(0x2378c292ab5844f3), SC_LIMB(0x216cc2728dc58f55),
23 SC_LIMB(0xc44edb49aed63690), SC_LIMB(0xffffffff7cca23e9),
24 SC_LIMB(0xffffffffffffffff), SC_LIMB(0xffffffffffffffff),
25 SC_LIMB(0x3fffffffffffffff)
32 SC_LIMB(0xe3539257049b9b60), SC_LIMB(0x7af32c4bc1b195d9),
33 SC_LIMB(0x0d66de2388ea1859), SC_LIMB(0xae17cf725ee4d838),
34 SC_LIMB(0x1a9cc14ba3c47c44), SC_LIMB(0x2052bcb7e4d070af),
35 SC_LIMB(0x3402a939f823b729)
40 #define WBITS C448_WORD_BITS /* NB this may be different from ARCH_WORD_BITS */
42 const curve448_scalar_t curve448_scalar_one
= {{{1}}};
43 const curve448_scalar_t curve448_scalar_zero
= {{{0}}};
46 * {extra,accum} - sub +? p
47 * Must have extra <= 1
49 static void sc_subx(curve448_scalar_t out
,
50 const c448_word_t accum
[C448_448_SCALAR_LIMBS
],
51 const curve448_scalar_t sub
,
52 const curve448_scalar_t p
, c448_word_t extra
)
54 c448_dsword_t chain
= 0;
58 for (i
= 0; i
< C448_448_SCALAR_LIMBS
; i
++) {
59 chain
= (chain
+ accum
[i
]) - sub
->limb
[i
];
63 borrow
= chain
+ extra
; /* = 0 or -1 */
66 for (i
= 0; i
< C448_448_SCALAR_LIMBS
; i
++) {
67 chain
= (chain
+ out
->limb
[i
]) + (p
->limb
[i
] & borrow
);
73 static void sc_montmul(curve448_scalar_t out
, const curve448_scalar_t a
,
74 const curve448_scalar_t b
)
77 c448_word_t accum
[C448_448_SCALAR_LIMBS
+ 1] = { 0 };
78 c448_word_t hi_carry
= 0;
80 for (i
= 0; i
< C448_448_SCALAR_LIMBS
; i
++) {
81 c448_word_t mand
= a
->limb
[i
];
82 const c448_word_t
*mier
= b
->limb
;
84 c448_dword_t chain
= 0;
85 for (j
= 0; j
< C448_448_SCALAR_LIMBS
; j
++) {
86 chain
+= ((c448_dword_t
) mand
) * mier
[j
] + accum
[j
];
92 mand
= accum
[0] * MONTGOMERY_FACTOR
;
95 for (j
= 0; j
< C448_448_SCALAR_LIMBS
; j
++) {
96 chain
+= (c448_dword_t
) mand
*mier
[j
] + accum
[j
];
103 accum
[j
- 1] = chain
;
104 hi_carry
= chain
>> WBITS
;
107 sc_subx(out
, accum
, sc_p
, sc_p
, hi_carry
);
110 void curve448_scalar_mul(curve448_scalar_t out
, const curve448_scalar_t a
,
111 const curve448_scalar_t b
)
113 sc_montmul(out
, a
, b
);
114 sc_montmul(out
, out
, sc_r2
);
117 void curve448_scalar_sub(curve448_scalar_t out
, const curve448_scalar_t a
,
118 const curve448_scalar_t b
)
120 sc_subx(out
, a
->limb
, b
, sc_p
, 0);
123 void curve448_scalar_add(curve448_scalar_t out
, const curve448_scalar_t a
,
124 const curve448_scalar_t b
)
126 c448_dword_t chain
= 0;
129 for (i
= 0; i
< C448_448_SCALAR_LIMBS
; i
++) {
130 chain
= (chain
+ a
->limb
[i
]) + b
->limb
[i
];
131 out
->limb
[i
] = chain
;
134 sc_subx(out
, out
->limb
, sc_p
, sc_p
, chain
);
137 static ossl_inline
void scalar_decode_short(curve448_scalar_t s
,
138 const unsigned char *ser
,
141 unsigned int i
, j
, k
= 0;
143 for (i
= 0; i
< C448_448_SCALAR_LIMBS
; i
++) {
146 for (j
= 0; j
< sizeof(c448_word_t
) && k
< nbytes
; j
++, k
++)
147 out
|= ((c448_word_t
) ser
[k
]) << (8 * j
);
152 c448_error_t
curve448_scalar_decode(
154 const unsigned char ser
[C448_448_SCALAR_BYTES
])
157 c448_dsword_t accum
= 0;
159 scalar_decode_short(s
, ser
, C448_448_SCALAR_BYTES
);
160 for (i
= 0; i
< C448_448_SCALAR_LIMBS
; i
++)
161 accum
= (accum
+ s
->limb
[i
] - sc_p
->limb
[i
]) >> WBITS
;
162 /* Here accum == 0 or -1 */
164 curve448_scalar_mul(s
, s
, curve448_scalar_one
); /* ham-handed reduce */
166 return c448_succeed_if(~word_is_zero(accum
));
169 void curve448_scalar_destroy(curve448_scalar_t scalar
)
171 OPENSSL_cleanse(scalar
, sizeof(curve448_scalar_t
));
174 void curve448_scalar_decode_long(curve448_scalar_t s
,
175 const unsigned char *ser
, size_t ser_len
)
178 curve448_scalar_t t1
, t2
;
181 curve448_scalar_copy(s
, curve448_scalar_zero
);
185 i
= ser_len
- (ser_len
% C448_448_SCALAR_BYTES
);
187 i
-= C448_448_SCALAR_BYTES
;
189 scalar_decode_short(t1
, &ser
[i
], ser_len
- i
);
191 if (ser_len
== sizeof(curve448_scalar_t
)) {
193 /* ham-handed reduce */
194 curve448_scalar_mul(s
, t1
, curve448_scalar_one
);
195 curve448_scalar_destroy(t1
);
200 i
-= C448_448_SCALAR_BYTES
;
201 sc_montmul(t1
, t1
, sc_r2
);
202 ignore_result(curve448_scalar_decode(t2
, ser
+ i
));
203 curve448_scalar_add(t1
, t1
, t2
);
206 curve448_scalar_copy(s
, t1
);
207 curve448_scalar_destroy(t1
);
208 curve448_scalar_destroy(t2
);
211 void curve448_scalar_encode(unsigned char ser
[C448_448_SCALAR_BYTES
],
212 const curve448_scalar_t s
)
214 unsigned int i
, j
, k
= 0;
216 for (i
= 0; i
< C448_448_SCALAR_LIMBS
; i
++) {
217 for (j
= 0; j
< sizeof(c448_word_t
); j
++, k
++)
218 ser
[k
] = s
->limb
[i
] >> (8 * j
);
222 void curve448_scalar_halve(curve448_scalar_t out
, const curve448_scalar_t a
)
224 c448_word_t mask
= -(a
->limb
[0] & 1);
225 c448_dword_t chain
= 0;
227 for (i
= 0; i
< C448_448_SCALAR_LIMBS
; i
++) {
228 chain
= (chain
+ a
->limb
[i
]) + (sc_p
->limb
[i
] & mask
);
229 out
->limb
[i
] = chain
;
230 chain
>>= C448_WORD_BITS
;
232 for (i
= 0; i
< C448_448_SCALAR_LIMBS
- 1; i
++)
233 out
->limb
[i
] = out
->limb
[i
] >> 1 | out
->limb
[i
+ 1] << (WBITS
- 1);
234 out
->limb
[i
] = out
->limb
[i
] >> 1 | chain
<< (WBITS
- 1);