45 0xFFFFFFFFu, 0xFFFFFFFFu, 0x8AACaa68u, 0x15728E5Au, 0x98FA0510u, 0x15D22618u, 0xEA956AE5u, 0x3995497Cu,
46 0x95581718u, 0xDE2BCBF6u, 0x6F4C52C9u, 0xB5C55DF0u, 0xEC07A28Fu, 0x9B2783A2u, 0x180E8603u, 0xE39E772Cu,
47 0x2E36CE3Bu, 0x32905E46u, 0xCA18217Cu, 0xF1746C08u, 0x4ABC9804u, 0x670C354Eu, 0x7096966Du, 0x9ED52907u,
48 0x208552BBu, 0x1C62F356u, 0xDCA3AD96u, 0x83655D23u, 0xFD24CF5Fu, 0x69163FA8u, 0x1C55D39Au, 0x98DA4836u,
49 0xA163BF05u, 0xC2007CB8u, 0xECE45B3Du, 0x49286651u, 0x7C4B1FE6u, 0xAE9F2411u, 0x5A899FA5u, 0xEE386BFBu,
50 0xF406B7EDu, 0x0BFF5CB6u, 0xA637ED6Bu, 0xF44C42E9u, 0x625E7EC6u, 0xE485B576u, 0x6D51C245u, 0x4FE1356Du,
51 0xF25F1437u, 0x302B0A6Du, 0xCD3A431Bu, 0xEF9519B3u, 0x8E3404DDu, 0x514A0879u, 0x3B139B22u, 0x020BBEa6u,
52 0x8A67CC74u, 0x29024E08u, 0x80DC1CD1u, 0xC4C6628Bu, 0x2168C234u, 0xC90FDAA2u, 0xFFFFFFFFu, 0xFFFFFFFFu,
56 2u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
57 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
58 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
72 bool initialized =
false;
74static Group14Ctx s_g14;
81static int bn_cmp_raw(
const uint32_t *a,
const uint32_t *b,
int n)
83 for (
int i = n - 1; i >= 0; i--)
95static void bn_sub_inplace(uint32_t *a,
const uint32_t *b,
int n)
98 for (
int i = 0; i < n; i++)
100 uint64_t v = (uint64_t)a[i] - b[i] - borrow;
102 borrow = (v >> 32) & 1u;
107static uint32_t bn_shl1(uint32_t *a,
int n)
110 for (
int i = 0; i < n; i++)
112 uint32_t nc = a[i] >> 31;
113 a[i] = (a[i] << 1) | carry;
123static void bn_init(
void)
125 if (s_g14.initialized)
135 uint64_t v = (uint64_t)0 -
group14_p.
d[i] - borrow;
136 s_g14.r1.d[i] = (uint32_t)v;
137 borrow = (v >> 32) & 1u;
145 memcpy(s_g14.r2.d, s_g14.r1.d,
sizeof(
SshBigNum));
146 for (
int i = 0; i < 2048; i++)
154 s_g14.initialized =
true;
168 memset(t, 0, 129 *
sizeof(uint32_t));
176 uint64_t uv = (uint64_t)t[i + j] + (uint64_t)a->
d[i] * (uint64_t)b->
d[j] + carry;
177 t[i + j] = (uint32_t)uv;
187 uint64_t uv = (uint64_t)t[i + j] + (uint64_t)m * (uint64_t)
group14_p.
d[j] + carry;
188 t[i + j] = (uint32_t)uv;
214 size_t blen = len < 256 ? len : 256;
215 for (
size_t i = 0; i < blen; i++)
218 out->
d[byte_pos / 4] |= (uint32_t)bytes[len - 1 - i] << ((byte_pos % 4) * 8);
227 bytes[i * 4 + 0] = (uint8_t)(v >> 24);
228 bytes[i * 4 + 1] = (uint8_t)(v >> 16);
229 bytes[i * 4 + 2] = (uint8_t)(v >> 8);
230 bytes[i * 4 + 3] = (uint8_t)(v);
257 if (!ok && v->
d[0] <= 1u)
274#include <mbedtls/bignum.h>
278 uint8_t base_be[256];
290 mbedtls_mpi_init(&B);
291 mbedtls_mpi_init(&E);
292 mbedtls_mpi_init(&P);
293 mbedtls_mpi_init(&R);
295 mbedtls_mpi_read_binary(&B, base_be, 256);
296 mbedtls_mpi_read_binary(&E, exp_be, 256);
297 mbedtls_mpi_read_binary(&P, p_be, 256);
299 mbedtls_mpi_exp_mod(&R, &B, &E, &P, NULL);
300 mbedtls_mpi_write_binary(&R, res_be, 256);
302 mbedtls_mpi_free(&B);
303 mbedtls_mpi_free(&E);
304 mbedtls_mpi_free(&P);
305 mbedtls_mpi_free(&R);
309 ssh_wipe(exp_be, 256);
310 ssh_wipe(res_be, 256);
327 bn_monpro(base_mont, base, &s_g14.r2);
330 memcpy(result->
d, s_g14.r1.d,
sizeof(
SshBigNum));
335 for (
int b = 31; b >= 0; b--)
338 bn_monpro(tmp, result, result);
341 if ((exp->
d[i] >> b) & 1u)
344 bn_monpro(tmp, result, base_mont);
355 bn_monpro(out, result, &one);
#define SSH_CRYPTO_WORK_SIZE
Shared scratch buffer for SSH big-number operations.
void bn_expmod_group14(SshBigNum *out, const SshBigNum *base, const SshBigNum *exp)
Compute out = base^exp mod group14_p.
int bn_cmp(const SshBigNum *a, const SshBigNum *b)
Compare two SshBigNum values.
void bn_to_bytes(uint8_t bytes[256], const SshBigNum *in)
Write a SshBigNum as a 256-byte big-endian array.
const SshBigNum group14_g
Generator for group-14: g = 2.
uint8_t crypto_work[SSH_CRYPTO_WORK_SIZE]
Global scratch buffer for big-number temporaries.
int bn_dh_validate(const SshBigNum *v)
Validate a received DH public value.
const SshBigNum group14_p
The RFC 3526 MODP group-14 prime (2048-bit).
void bn_from_bytes(SshBigNum *out, const uint8_t *bytes, size_t len)
Read a big-endian byte array of len bytes into a SshBigNum.
int bn_is_zero(const SshBigNum *a)
Return non-zero if a is zero (all limbs zero).
2048-bit big-integer arithmetic for DH-group14 and RSA-2048.
#define SSH_BN_LIMBS
Number of 32-bit limbs in a 2048-bit integer.
SSH session key material - types, pools, and security model.
A 2048-bit unsigned integer stored as 64 little-endian 32-bit limbs.
uint32_t d[SSH_BN_LIMBS]
256 bytes of magnitude, little-endian limbs.