First Commit

This commit is contained in:
2025-02-06 22:24:29 +08:00
parent ed7df4c81e
commit 7539e6a53c
18116 changed files with 6181499 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
/* $OpenBSD: bn_arch.h,v 1.7 2023/04/17 12:51:09 jsing Exp $ */
/*
* Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <openssl/bn.h>
#ifndef HEADER_BN_ARCH_H
#define HEADER_BN_ARCH_H
#ifndef OPENSSL_NO_ASM
#if defined(__GNUC__)
#define HAVE_BN_ADDW
static inline void
bn_addw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
{
BN_ULONG carry, r0;
__asm__ (
"adds %[r0], %[a], %[b] \n"
"cset %[carry], cs \n"
: [carry]"=r"(carry), [r0]"=r"(r0)
: [a]"r"(a), [b]"r"(b)
: "cc");
*out_r1 = carry;
*out_r0 = r0;
}
#define HAVE_BN_MULW
static inline void
bn_mulw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
{
BN_ULONG r1, r0;
/* Unsigned multiplication using a umulh/mul pair. */
__asm__ (
"umulh %[r1], %[a], %[b] \n"
"mul %[r0], %[a], %[b] \n"
: [r1]"=&r"(r1), [r0]"=r"(r0)
: [a]"r"(a), [b]"r"(b));
*out_r1 = r1;
*out_r0 = r0;
}
#define HAVE_BN_SUBW
static inline void
bn_subw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_borrow, BN_ULONG *out_r0)
{
BN_ULONG borrow, r0;
__asm__ (
"subs %[r0], %[a], %[b] \n"
"cset %[borrow], cc \n"
: [borrow]"=r"(borrow), [r0]"=r"(r0)
: [a]"r"(a), [b]"r"(b)
: "cc");
*out_borrow = borrow;
*out_r0 = r0;
}
#endif /* __GNUC__ */
#endif
#endif

View File

@@ -0,0 +1,165 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// ----------------------------------------------------------------------------
// Add, z := x + y
// Inputs x[m], y[n]; outputs function return (carry-out) and z[p]
//
// extern uint64_t bignum_add
// (uint64_t p, uint64_t *z,
// uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
//
// Does the z := x + y operation, truncating modulo p words in general and
// returning a top carry (0 or 1) in the p'th place, only adding the input
// words below p (as well as m and n respectively) to get the sum and carry.
//
// Standard x86-64 ABI: RDI = p, RSI = z, RDX = m, RCX = x, R8 = n, R9 = y, returns RAX
// Microsoft x64 ABI: RCX = p, RDX = z, R8 = m, R9 = x, [RSP+40] = n, [RSP+48] = y, returns RAX
// ----------------------------------------------------------------------------
#include "s2n_bignum_internal.h"
.intel_syntax noprefix
S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_add)
S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_add)
.text
#define p rdi
#define z rsi
#define m rdx
#define x rcx
#define n r8
#define y r9
#define i r10
#define a rax
#define ashort eax
S2N_BN_SYMBOL(bignum_add):
endbr64
#if WINDOWS_ABI
push rdi
push rsi
mov rdi, rcx
mov rsi, rdx
mov rdx, r8
mov rcx, r9
mov r8, [rsp+56]
mov r9, [rsp+64]
#endif
// Zero the main index counter for both branches
xor i, i
// First clamp the two input sizes m := min(p,m) and n := min(p,n) since
// we'll never need words past the p'th. Can now assume m <= p and n <= p.
// Then compare the modified m and n and branch accordingly
cmp p, m
cmovc m, p
cmp p, n
cmovc n, p
cmp m, n
jc ylonger
// The case where x is longer or of the same size (p >= m >= n)
sub p, m
sub m, n
inc m
test n, n
jz xtest
xmainloop:
mov a, [x+8*i]
adc a, [y+8*i]
mov [z+8*i],a
inc i
dec n
jnz xmainloop
jmp xtest
xtoploop:
mov a, [x+8*i]
adc a, 0
mov [z+8*i],a
inc i
xtest:
dec m
jnz xtoploop
mov ashort, 0
adc a, 0
test p, p
jnz tails
#if WINDOWS_ABI
pop rsi
pop rdi
#endif
ret
// The case where y is longer (p >= n > m)
ylonger:
sub p, n
sub n, m
test m, m
jz ytoploop
ymainloop:
mov a, [x+8*i]
adc a, [y+8*i]
mov [z+8*i],a
inc i
dec m
jnz ymainloop
ytoploop:
mov a, [y+8*i]
adc a, 0
mov [z+8*i],a
inc i
dec n
jnz ytoploop
mov ashort, 0
adc a, 0
test p, p
jnz tails
#if WINDOWS_ABI
pop rsi
pop rdi
#endif
ret
// Adding a non-trivial tail, when p > max(m,n)
tails:
mov [z+8*i],a
xor a, a
jmp tail
tailloop:
mov [z+8*i],a
tail:
inc i
dec p
jnz tailloop
#if WINDOWS_ABI
pop rsi
pop rdi
#endif
ret
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif

View File

@@ -0,0 +1,155 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// ----------------------------------------------------------------------------
// Multiply-add with single-word multiplier, z := z + c * y
// Inputs c, y[n]; outputs function return (carry-out) and z[k]
//
// extern uint64_t bignum_cmadd
// (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y);
//
// Does the "z := z + c * y" operation where y is n digits, result z is p.
// Truncates the result in general.
//
// The return value is a high/carry word that is meaningful when p = n + 1, or
// more generally when n <= p and the result fits in p + 1 digits. In these
// cases it gives the top digit of the (p + 1)-digit result.
//
// Standard x86-64 ABI: RDI = k, RSI = z, RDX = c, RCX = n, R8 = y, returns RAX
// Microsoft x64 ABI: RCX = k, RDX = z, R8 = c, R9 = n, [RSP+40] = y, returns RAX
// ----------------------------------------------------------------------------
#include "s2n_bignum_internal.h"
.intel_syntax noprefix
S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_cmadd)
S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_cmadd)
.text
#define p rdi
#define z rsi
#define c r9
#define n rcx
#define x r8
#define i r10
#define h r11
#define r rbx
#define hshort r11d
#define ishort r10d
S2N_BN_SYMBOL(bignum_cmadd):
endbr64
#if WINDOWS_ABI
push rdi
push rsi
mov rdi, rcx
mov rsi, rdx
mov rdx, r8
mov rcx, r9
mov r8, [rsp+56]
#endif
// Seems hard to avoid one more register
push rbx
// First clamp the input size n := min(p,n) since we can never need to read
// past the p'th term of the input to generate p-digit output.
// Subtract p := p - min(n,p) so it holds the size of the extra tail needed
cmp p, n
cmovc n, p
sub p, n
// Initialize high part h = 0; if n = 0 do nothing but return that zero
xor h, h
test n, n
jz end
// Move c into a safer register as multiplies overwrite rdx
mov c, rdx
// Initialization of the loop: 2^64 * CF + [h,z_0'] = z_0 + c * x_0
mov rax, [x]
mul c
add [z], rax
mov h, rdx
mov ishort, 1
dec n
jz hightail
// Main loop, where we always have CF + previous high part h to add in
loop:
adc h, [z+8*i]
sbb r, r
mov rax, [x+8*i]
mul c
sub rdx, r
add rax, h
mov [z+8*i], rax
mov h, rdx
inc i
dec n
jnz loop
hightail:
adc h, 0
// Propagate the carry all the way to the end with h as extra carry word
tail:
test p, p
jz end
add [z+8*i], h
mov hshort, 0
inc i
dec p
jz highend
tloop:
adc [z+8*i], h
inc i
dec p
jnz tloop
highend:
adc h, 0
// Return the high/carry word
end:
mov rax, h
pop rbx
#if WINDOWS_ABI
pop rsi
pop rdi
#endif
ret
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif

View File

@@ -0,0 +1,138 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// ----------------------------------------------------------------------------
// Multiply by a single word, z := c * y
// Inputs c, y[n]; outputs function return (carry-out) and z[k]
//
// extern uint64_t bignum_cmul
// (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y);
//
// Does the "z := c * y" operation where y is n digits, result z is p.
// Truncates the result in general unless p >= n + 1.
//
// The return value is a high/carry word that is meaningful when p >= n as
// giving the high part of the result. Since this is always zero if p > n,
// it is mainly of interest in the special case p = n, i.e. where the source
// and destination have the same nominal size, when it gives the extra word
// of the full result.
//
// Standard x86-64 ABI: RDI = k, RSI = z, RDX = c, RCX = n, R8 = y, returns RAX
// Microsoft x64 ABI: RCX = k, RDX = z, R8 = c, R9 = n, [RSP+40] = y, returns RAX
// ----------------------------------------------------------------------------
#include "s2n_bignum_internal.h"
.intel_syntax noprefix
S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_cmul)
S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_cmul)
.text
#define p rdi
#define z rsi
#define c r9
#define n rcx
#define x r8
#define i r10
#define h r11
S2N_BN_SYMBOL(bignum_cmul):
endbr64
#if WINDOWS_ABI
push rdi
push rsi
mov rdi, rcx
mov rsi, rdx
mov rdx, r8
mov rcx, r9
mov r8, [rsp+56]
#endif
// First clamp the input size n := min(p,n) since we can never need to read
// past the p'th term of the input to generate p-digit output. Now we can
// assume that n <= p
cmp p, n
cmovc n, p
// Initialize current input/output pointer offset i and high part h.
// But then if n = 0 skip the multiplication and go to the tail part
xor h, h
xor i, i
test n, n
jz tail
// Move c into a safer register as multiplies overwrite rdx
mov c, rdx
// Initialization of the loop: [h,l] = c * x_0
mov rax, [x]
mul c
mov [z], rax
mov h, rdx
inc i
cmp i, n
jz tail
// Main loop doing the multiplications
loop:
mov rax, [x+8*i]
mul c
add rax, h
adc rdx, 0
mov [z+8*i], rax
mov h, rdx
inc i
cmp i, n
jc loop
// Add a tail when the destination is longer
tail:
cmp i, p
jnc end
mov [z+8*i], h
xor h, h
inc i
cmp i, p
jnc end
tloop:
mov [z+8*i], h
inc i
cmp i, p
jc tloop
// Return the high/carry word
end:
mov rax, h
#if WINDOWS_ABI
pop rsi
pop rdi
#endif
ret
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif

View File

@@ -0,0 +1,167 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// ----------------------------------------------------------------------------
// Multiply z := x * y
// Inputs x[m], y[n]; output z[k]
//
// extern void bignum_mul
// (uint64_t k, uint64_t *z,
// uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
//
// Does the "z := x * y" operation where x is m digits, y is n, result z is k.
// Truncates the result in general unless k >= m + n
//
// Standard x86-64 ABI: RDI = k, RSI = z, RDX = m, RCX = x, R8 = n, R9 = y
// Microsoft x64 ABI: RCX = k, RDX = z, R8 = m, R9 = x, [RSP+40] = n, [RSP+48] = y
// ----------------------------------------------------------------------------
#include "s2n_bignum_internal.h"
.intel_syntax noprefix
S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_mul)
S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_mul)
.text
// These are actually right
#define p rdi
#define z rsi
#define n r8
// These are not
#define c r15
#define h r14
#define l r13
#define x r12
#define y r11
#define i rbx
#define k r10
#define m rbp
// These are always local scratch since multiplier result is in these
#define a rax
#define d rdx
S2N_BN_SYMBOL(bignum_mul):
endbr64
#if WINDOWS_ABI
push rdi
push rsi
mov rdi, rcx
mov rsi, rdx
mov rdx, r8
mov rcx, r9
mov r8, [rsp+56]
mov r9, [rsp+64]
#endif
// We use too many registers, and also we need rax:rdx for multiplications
push rbx
push rbp
push r12
push r13
push r14
push r15
mov m, rdx
// If the result size is zero, do nothing
// Note that even if either or both inputs has size zero, we can't
// just give up because we at least need to zero the output array
// If we did a multiply-add variant, however, then we could
test p, p
jz end
// Set initial 2-part sum to zero (we zero c inside the body)
xor h,h
xor l,l
// Otherwise do outer loop k = 0 ... k = p - 1
xor k, k
outerloop:
// Zero our carry term first; we eventually want it and a zero is useful now
// Set a = max 0 (k + 1 - n), i = min (k + 1) m
// This defines the range a <= j < i for the inner summation
// Note that since k < p < 2^64 we can assume k + 1 doesn't overflow
// And since we want to increment it anyway, we might as well do it now
xor c, c // c = 0
inc k // k = k + 1
mov a, k // a = k + 1
sub a, n // a = k + 1 - n
cmovc a, c // a = max 0 (k + 1 - n)
mov i, m // i = m
cmp k, m // CF <=> k + 1 < m
cmovc i, k // i = min (k + 1) m
// Turn i into a loop count, and skip things if it's <= 0
// Otherwise set up initial pointers x -> x0[a] and y -> y0[k - a]
// and then launch into the main inner loop, postdecrementing i
mov d, k
sub d, i
sub i, a
jbe innerend
lea x,[rcx+8*a]
lea y,[r9+8*d-8]
innerloop:
mov rax, [y+8*i]
mul QWORD PTR [x]
add x, 8
add l, rax
adc h, rdx
adc c, 0
dec i
jnz innerloop
innerend:
mov [z], l
mov l, h
mov h, c
add z, 8
cmp k, p
jc outerloop
end:
pop r15
pop r14
pop r13
pop r12
pop rbp
pop rbx
#if WINDOWS_ABI
pop rsi
pop rdi
#endif
ret
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif

View File

@@ -0,0 +1,157 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// ----------------------------------------------------------------------------
// Multiply z := x * y
// Inputs x[4], y[4]; output z[8]
//
// extern void bignum_mul_4_8_alt
// (uint64_t z[static 8], uint64_t x[static 4], uint64_t y[static 4]);
//
// Standard x86-64 ABI: RDI = z, RSI = x, RDX = y
// Microsoft x64 ABI: RCX = z, RDX = x, R8 = y
// ----------------------------------------------------------------------------
#include "s2n_bignum_internal.h"
.intel_syntax noprefix
S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_mul_4_8_alt)
S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_mul_4_8_alt)
.text
// These are actually right
#define z rdi
#define x rsi
// This is moved from rdx to free it for muls
#define y rcx
// Other variables used as a rotating 3-word window to add terms to
#define t0 r8
#define t1 r9
#define t2 r10
// Macro for the key "multiply and add to (c,h,l)" step
#define combadd(c,h,l,numa,numb) \
mov rax, numa; \
mul QWORD PTR numb; \
add l, rax; \
adc h, rdx; \
adc c, 0
// A minutely shorter form for when c = 0 initially
#define combadz(c,h,l,numa,numb) \
mov rax, numa; \
mul QWORD PTR numb; \
add l, rax; \
adc h, rdx; \
adc c, c
// A short form where we don't expect a top carry
#define combads(h,l,numa,numb) \
mov rax, numa; \
mul QWORD PTR numb; \
add l, rax; \
adc h, rdx
S2N_BN_SYMBOL(bignum_mul_4_8_alt):
endbr64
#if WINDOWS_ABI
push rdi
push rsi
mov rdi, rcx
mov rsi, rdx
mov rdx, r8
#endif
// Copy y into a safe register to start with
mov y, rdx
// Result term 0
mov rax, [x]
mul QWORD PTR [y]
mov [z], rax
mov t0, rdx
xor t1, t1
// Result term 1
xor t2, t2
combads(t1,t0,[x],[y+8])
combadz(t2,t1,t0,[x+8],[y])
mov [z+8], t0
// Result term 2
xor t0, t0
combadz(t0,t2,t1,[x],[y+16])
combadd(t0,t2,t1,[x+8],[y+8])
combadd(t0,t2,t1,[x+16],[y])
mov [z+16], t1
// Result term 3
xor t1, t1
combadz(t1,t0,t2,[x],[y+24])
combadd(t1,t0,t2,[x+8],[y+16])
combadd(t1,t0,t2,[x+16],[y+8])
combadd(t1,t0,t2,[x+24],[y])
mov [z+24], t2
// Result term 4
xor t2, t2
combadz(t2,t1,t0,[x+8],[y+24])
combadd(t2,t1,t0,[x+16],[y+16])
combadd(t2,t1,t0,[x+24],[y+8])
mov [z+32], t0
// Result term 5
xor t0, t0
combadz(t0,t2,t1,[x+16],[y+24])
combadd(t0,t2,t1,[x+24],[y+16])
mov [z+40], t1
// Result term 6
xor t1, t1
combads(t0,t2,[x+24],[y+24])
mov [z+48], t2
// Result term 7
mov [z+56], t0
// Return
#if WINDOWS_ABI
pop rsi
pop rdi
#endif
ret
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif

View File

@@ -0,0 +1,244 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// ----------------------------------------------------------------------------
// Multiply z := x * y
// Inputs x[8], y[8]; output z[16]
//
// extern void bignum_mul_8_16_alt
// (uint64_t z[static 16], uint64_t x[static 8], uint64_t y[static 8]);
//
// Standard x86-64 ABI: RDI = z, RSI = x, RDX = y
// Microsoft x64 ABI: RCX = z, RDX = x, R8 = y
// ----------------------------------------------------------------------------
#include "s2n_bignum_internal.h"
.intel_syntax noprefix
S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_mul_8_16_alt)
S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_mul_8_16_alt)
.text
// These are actually right
#define z rdi
#define x rsi
// This is moved from rdx to free it for muls
#define y rcx
// Other variables used as a rotating 3-word window to add terms to
#define t0 r8
#define t1 r9
#define t2 r10
// Macro for the key "multiply and add to (c,h,l)" step
#define combadd(c,h,l,numa,numb) \
mov rax, numa; \
mul QWORD PTR numb; \
add l, rax; \
adc h, rdx; \
adc c, 0
// A minutely shorter form for when c = 0 initially
#define combadz(c,h,l,numa,numb) \
mov rax, numa; \
mul QWORD PTR numb; \
add l, rax; \
adc h, rdx; \
adc c, c
// A short form where we don't expect a top carry
#define combads(h,l,numa,numb) \
mov rax, numa; \
mul QWORD PTR numb; \
add l, rax; \
adc h, rdx
S2N_BN_SYMBOL(bignum_mul_8_16_alt):
endbr64
#if WINDOWS_ABI
push rdi
push rsi
mov rdi, rcx
mov rsi, rdx
mov rdx, r8
#endif
// Copy y into a safe register to start with
mov y, rdx
// Result term 0
mov rax, [x]
mul QWORD PTR [y]
mov [z], rax
mov t0, rdx
xor t1, t1
// Result term 1
xor t2, t2
combads(t1,t0,[x],[y+8])
combadz(t2,t1,t0,[x+8],[y])
mov [z+8], t0
// Result term 2
xor t0, t0
combadz(t0,t2,t1,[x],[y+16])
combadd(t0,t2,t1,[x+8],[y+8])
combadd(t0,t2,t1,[x+16],[y])
mov [z+16], t1
// Result term 3
xor t1, t1
combadz(t1,t0,t2,[x],[y+24])
combadd(t1,t0,t2,[x+8],[y+16])
combadd(t1,t0,t2,[x+16],[y+8])
combadd(t1,t0,t2,[x+24],[y])
mov [z+24], t2
// Result term 4
xor t2, t2
combadz(t2,t1,t0,[x],[y+32])
combadd(t2,t1,t0,[x+8],[y+24])
combadd(t2,t1,t0,[x+16],[y+16])
combadd(t2,t1,t0,[x+24],[y+8])
combadd(t2,t1,t0,[x+32],[y])
mov [z+32], t0
// Result term 5
xor t0, t0
combadz(t0,t2,t1,[x],[y+40])
combadd(t0,t2,t1,[x+8],[y+32])
combadd(t0,t2,t1,[x+16],[y+24])
combadd(t0,t2,t1,[x+24],[y+16])
combadd(t0,t2,t1,[x+32],[y+8])
combadd(t0,t2,t1,[x+40],[y])
mov [z+40], t1
// Result term 6
xor t1, t1
combadz(t1,t0,t2,[x],[y+48])
combadd(t1,t0,t2,[x+8],[y+40])
combadd(t1,t0,t2,[x+16],[y+32])
combadd(t1,t0,t2,[x+24],[y+24])
combadd(t1,t0,t2,[x+32],[y+16])
combadd(t1,t0,t2,[x+40],[y+8])
combadd(t1,t0,t2,[x+48],[y])
mov [z+48], t2
// Result term 7
xor t2, t2
combadz(t2,t1,t0,[x],[y+56])
combadd(t2,t1,t0,[x+8],[y+48])
combadd(t2,t1,t0,[x+16],[y+40])
combadd(t2,t1,t0,[x+24],[y+32])
combadd(t2,t1,t0,[x+32],[y+24])
combadd(t2,t1,t0,[x+40],[y+16])
combadd(t2,t1,t0,[x+48],[y+8])
combadd(t2,t1,t0,[x+56],[y])
mov [z+56], t0
// Result term 8
xor t0, t0
combadz(t0,t2,t1,[x+8],[y+56])
combadd(t0,t2,t1,[x+16],[y+48])
combadd(t0,t2,t1,[x+24],[y+40])
combadd(t0,t2,t1,[x+32],[y+32])
combadd(t0,t2,t1,[x+40],[y+24])
combadd(t0,t2,t1,[x+48],[y+16])
combadd(t0,t2,t1,[x+56],[y+8])
mov [z+64], t1
// Result term 9
xor t1, t1
combadz(t1,t0,t2,[x+16],[y+56])
combadd(t1,t0,t2,[x+24],[y+48])
combadd(t1,t0,t2,[x+32],[y+40])
combadd(t1,t0,t2,[x+40],[y+32])
combadd(t1,t0,t2,[x+48],[y+24])
combadd(t1,t0,t2,[x+56],[y+16])
mov [z+72], t2
// Result term 10
xor t2, t2
combadz(t2,t1,t0,[x+24],[y+56])
combadd(t2,t1,t0,[x+32],[y+48])
combadd(t2,t1,t0,[x+40],[y+40])
combadd(t2,t1,t0,[x+48],[y+32])
combadd(t2,t1,t0,[x+56],[y+24])
mov [z+80], t0
// Result term 11
xor t0, t0
combadz(t0,t2,t1,[x+32],[y+56])
combadd(t0,t2,t1,[x+40],[y+48])
combadd(t0,t2,t1,[x+48],[y+40])
combadd(t0,t2,t1,[x+56],[y+32])
mov [z+88], t1
// Result term 12
xor t1, t1
combadz(t1,t0,t2,[x+40],[y+56])
combadd(t1,t0,t2,[x+48],[y+48])
combadd(t1,t0,t2,[x+56],[y+40])
mov [z+96], t2
// Result term 13
xor t2, t2
combadz(t2,t1,t0,[x+48],[y+56])
combadd(t2,t1,t0,[x+56],[y+48])
mov [z+104], t0
// Result term 14
combads(t2,t1,[x+56],[y+56])
mov [z+112], t1
// Result term 11
mov [z+120], t2
// Return
#if WINDOWS_ABI
pop rsi
pop rdi
#endif
ret
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif

View File

@@ -0,0 +1,197 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// ----------------------------------------------------------------------------
// Square z := x^2
// Input x[n]; output z[k]
//
// extern void bignum_sqr
// (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x);
//
// Does the "z := x^2" operation where x is n digits and result z is k.
// Truncates the result in general unless k >= 2 * n
//
// Standard x86-64 ABI: RDI = k, RSI = z, RDX = n, RCX = x
// Microsoft x64 ABI: RCX = k, RDX = z, R8 = n, R9 = x
// ----------------------------------------------------------------------------
#include "s2n_bignum_internal.h"
.intel_syntax noprefix
S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_sqr)
S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_sqr)
.text
// First three are where arguments come in, but n is moved.
#define p rdi
#define z rsi
#define x rcx
#define n r8
// These are always local scratch since multiplier result is in these
#define a rax
#define d rdx
// Other variables
#define i rbx
#define ll rbp
#define hh r9
#define k r10
#define y r11
#define htop r12
#define l r13
#define h r14
#define c r15
// Short versions
#define llshort ebp
S2N_BN_SYMBOL(bignum_sqr):
endbr64
#if WINDOWS_ABI
push rdi
push rsi
mov rdi, rcx
mov rsi, rdx
mov rdx, r8
mov rcx, r9
#endif
// We use too many registers, and also we need rax:rdx for multiplications
push rbx
push rbp
push r12
push r13
push r14
push r15
mov n, rdx
// If p = 0 the result is trivial and nothing needs doing
test p, p
jz end
// initialize (hh,ll) = 0
xor llshort, llshort
xor hh, hh
// Iterate outer loop from k = 0 ... k = p - 1 producing result digits
xor k, k
outerloop:
// First let bot = MAX 0 (k + 1 - n) and top = MIN (k + 1) n
// We want to accumulate all x[i] * x[k - i] for bot <= i < top
// For the optimization of squaring we avoid duplication and do
// 2 * x[i] * x[k - i] for i < htop, where htop = MIN ((k+1)/2) n
// Initialize i = bot; in fact just compute bot as i directly.
xor c, c
lea i, [k+1]
mov htop, i
shr htop, 1
sub i, n
cmovc i, c
cmp htop, n
cmovnc htop, n
// Initialize the three-part local sum (c,h,l); c was already done above
xor l, l
xor h, h
// If htop <= bot then main doubled part of the sum is empty
cmp i, htop
jnc nosumming
// Use a moving pointer for [y] = x[k-i] for the cofactor
mov a, k
sub a, i
lea y, [x+8*a]
// Do the main part of the sum x[i] * x[k - i] for 2 * i < k
innerloop:
mov a, [x+8*i]
mul QWORD PTR [y]
add l, a
adc h, d
adc c, 0
sub y, 8
inc i
cmp i, htop
jc innerloop
// Now double it
add l, l
adc h, h
adc c, c
// If k is even (which means 2 * i = k) and i < n add the extra x[i]^2 term
nosumming:
test k, 1
jnz innerend
cmp i, n
jnc innerend
mov a, [x+8*i]
mul a
add l, a
adc h, d
adc c, 0
// Now add the local sum into the global sum, store and shift
innerend:
add l, ll
mov [z+8*k], l
adc h, hh
mov ll, h
adc c, 0
mov hh, c
inc k
cmp k, p
jc outerloop
// Restore registers and return
end:
pop r15
pop r14
pop r13
pop r12
pop rbp
pop rbx
#if WINDOWS_ABI
pop rsi
pop rdi
#endif
ret
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif

View File

@@ -0,0 +1,145 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// ----------------------------------------------------------------------------
// Square, z := x^2
// Input x[4]; output z[8]
//
// extern void bignum_sqr_4_8_alt
// (uint64_t z[static 8], uint64_t x[static 4]);
//
// Standard x86-64 ABI: RDI = z, RSI = x
// Microsoft x64 ABI: RCX = z, RDX = x
// ----------------------------------------------------------------------------
#include "s2n_bignum_internal.h"
.intel_syntax noprefix
S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_sqr_4_8_alt)
S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_sqr_4_8_alt)
.text
// Input arguments
#define z rdi
#define x rsi
// Other variables used as a rotating 3-word window to add terms to
#define t0 rcx
#define t1 r8
#define t2 r9
// Macro for the key "multiply and add to (c,h,l)" step, for square term
#define combadd1(c,h,l,numa) \
mov rax, numa; \
mul rax; \
add l, rax; \
adc h, rdx; \
adc c, 0
// A short form where we don't expect a top carry
#define combads(h,l,numa) \
mov rax, numa; \
mul rax; \
add l, rax; \
adc h, rdx
// A version doubling before adding, for non-square terms
#define combadd2(c,h,l,numa,numb) \
mov rax, numa; \
mul QWORD PTR numb; \
add rax, rax; \
adc rdx, rdx; \
adc c, 0; \
add l, rax; \
adc h, rdx; \
adc c, 0
S2N_BN_SYMBOL(bignum_sqr_4_8_alt):
endbr64
#if WINDOWS_ABI
push rdi
push rsi
mov rdi, rcx
mov rsi, rdx
#endif
// Result term 0
mov rax, [x]
mul rax
mov [z], rax
mov t0, rdx
xor t1, t1
// Result term 1
xor t2, t2
combadd2(t2,t1,t0,[x],[x+8])
mov [z+8], t0
// Result term 2
xor t0, t0
combadd1(t0,t2,t1,[x+8])
combadd2(t0,t2,t1,[x],[x+16])
mov [z+16], t1
// Result term 3
xor t1, t1
combadd2(t1,t0,t2,[x],[x+24])
combadd2(t1,t0,t2,[x+8],[x+16])
mov [z+24], t2
// Result term 4
xor t2, t2
combadd2(t2,t1,t0,[x+8],[x+24])
combadd1(t2,t1,t0,[x+16])
mov [z+32], t0
// Result term 5
xor t0, t0
combadd2(t0,t2,t1,[x+16],[x+24])
mov [z+40], t1
// Result term 6
xor t1, t1
combads(t0,t2,[x+24])
mov [z+48], t2
// Result term 7
mov [z+56], t0
// Return
#if WINDOWS_ABI
pop rsi
pop rdi
#endif
ret
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif

View File

@@ -0,0 +1,242 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// ----------------------------------------------------------------------------
// Square, z := x^2
// Input x[8]; output z[16]
//
// extern void bignum_sqr_8_16_alt (uint64_t z[static 16], uint64_t x[static 8]);
//
// Standard x86-64 ABI: RDI = z, RSI = x
// Microsoft x64 ABI: RCX = z, RDX = x
// ----------------------------------------------------------------------------
#include "s2n_bignum_internal.h"
.intel_syntax noprefix
S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_sqr_8_16_alt)
S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_sqr_8_16_alt)
.text
// Input arguments
#define z rdi
#define x rsi
// Other variables used as a rotating 3-word window to add terms to
#define t0 r8
#define t1 r9
#define t2 r10
// Additional temporaries for local windows to share doublings
#define u0 rcx
#define u1 r11
// Macro for the key "multiply and add to (c,h,l)" step
#define combadd(c,h,l,numa,numb) \
mov rax, numa; \
mul QWORD PTR numb; \
add l, rax; \
adc h, rdx; \
adc c, 0
// Set up initial window (c,h,l) = numa * numb
#define combaddz(c,h,l,numa,numb) \
mov rax, numa; \
mul QWORD PTR numb; \
xor c, c; \
mov l, rax; \
mov h, rdx
// Doubling step (c,h,l) = 2 * (c,hh,ll) + (0,h,l)
#define doubladd(c,h,l,hh,ll) \
add ll, ll; \
adc hh, hh; \
adc c, c; \
add l, ll; \
adc h, hh; \
adc c, 0
// Square term incorporation (c,h,l) += numba^2
#define combadd1(c,h,l,numa) \
mov rax, numa; \
mul rax; \
add l, rax; \
adc h, rdx; \
adc c, 0
// A short form where we don't expect a top carry
#define combads(h,l,numa) \
mov rax, numa; \
mul rax; \
add l, rax; \
adc h, rdx
// A version doubling directly before adding, for single non-square terms
#define combadd2(c,h,l,numa,numb) \
mov rax, numa; \
mul QWORD PTR numb; \
add rax, rax; \
adc rdx, rdx; \
adc c, 0; \
add l, rax; \
adc h, rdx; \
adc c, 0
S2N_BN_SYMBOL(bignum_sqr_8_16_alt):
endbr64
#if WINDOWS_ABI
push rdi
push rsi
mov rdi, rcx
mov rsi, rdx
#endif
// Result term 0
mov rax, [x]
mul rax
mov [z], rax
mov t0, rdx
xor t1, t1
// Result term 1
xor t2, t2
combadd2(t2,t1,t0,[x],[x+8])
mov [z+8], t0
// Result term 2
xor t0, t0
combadd1(t0,t2,t1,[x+8])
combadd2(t0,t2,t1,[x],[x+16])
mov [z+16], t1
// Result term 3
combaddz(t1,u1,u0,[x],[x+24])
combadd(t1,u1,u0,[x+8],[x+16])
doubladd(t1,t0,t2,u1,u0)
mov [z+24], t2
// Result term 4
combaddz(t2,u1,u0,[x],[x+32])
combadd(t2,u1,u0,[x+8],[x+24])
doubladd(t2,t1,t0,u1,u0)
combadd1(t2,t1,t0,[x+16])
mov [z+32], t0
// Result term 5
combaddz(t0,u1,u0,[x],[x+40])
combadd(t0,u1,u0,[x+8],[x+32])
combadd(t0,u1,u0,[x+16],[x+24])
doubladd(t0,t2,t1,u1,u0)
mov [z+40], t1
// Result term 6
combaddz(t1,u1,u0,[x],[x+48])
combadd(t1,u1,u0,[x+8],[x+40])
combadd(t1,u1,u0,[x+16],[x+32])
doubladd(t1,t0,t2,u1,u0)
combadd1(t1,t0,t2,[x+24])
mov [z+48], t2
// Result term 7
combaddz(t2,u1,u0,[x],[x+56])
combadd(t2,u1,u0,[x+8],[x+48])
combadd(t2,u1,u0,[x+16],[x+40])
combadd(t2,u1,u0,[x+24],[x+32])
doubladd(t2,t1,t0,u1,u0)
mov [z+56], t0
// Result term 8
combaddz(t0,u1,u0,[x+8],[x+56])
combadd(t0,u1,u0,[x+16],[x+48])
combadd(t0,u1,u0,[x+24],[x+40])
doubladd(t0,t2,t1,u1,u0)
combadd1(t0,t2,t1,[x+32])
mov [z+64], t1
// Result term 9
combaddz(t1,u1,u0,[x+16],[x+56])
combadd(t1,u1,u0,[x+24],[x+48])
combadd(t1,u1,u0,[x+32],[x+40])
doubladd(t1,t0,t2,u1,u0)
mov [z+72], t2
// Result term 10
combaddz(t2,u1,u0,[x+24],[x+56])
combadd(t2,u1,u0,[x+32],[x+48])
doubladd(t2,t1,t0,u1,u0)
combadd1(t2,t1,t0,[x+40])
mov [z+80], t0
// Result term 11
combaddz(t0,u1,u0,[x+32],[x+56])
combadd(t0,u1,u0,[x+40],[x+48])
doubladd(t0,t2,t1,u1,u0)
mov [z+88], t1
// Result term 12
xor t1, t1
combadd2(t1,t0,t2,[x+40],[x+56])
combadd1(t1,t0,t2,[x+48])
mov [z+96], t2
// Result term 13
xor t2, t2
combadd2(t2,t1,t0,[x+48],[x+56])
mov [z+104], t0
// Result term 14
combads(t2,t1,[x+56])
mov [z+112], t1
// Result term 15
mov [z+120], t2
// Return
#if WINDOWS_ABI
pop rsi
pop rdi
#endif
ret
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif

View File

@@ -0,0 +1,153 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// ----------------------------------------------------------------------------
// Subtract, z := x - y
// Inputs x[m], y[n]; outputs function return (carry-out) and z[p]
//
// extern uint64_t bignum_sub
// (uint64_t p, uint64_t *z,
// uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
//
// Does the z := x - y operation, truncating modulo p words in general and
// returning a top borrow (0 or 1) in the p'th place, only subtracting input
// words below p (as well as m and n respectively) to get the diff and borrow.
//
// Standard x86-64 ABI: RDI = p, RSI = z, RDX = m, RCX = x, R8 = n, R9 = y, returns RAX
// Microsoft x64 ABI: RCX = p, RDX = z, R8 = m, R9 = x, [RSP+40] = n, [RSP+48] = y, returns RAX
// ----------------------------------------------------------------------------
#include "s2n_bignum_internal.h"
.intel_syntax noprefix
S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_sub)
S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_sub)
.text
#define p rdi
#define z rsi
#define m rdx
#define x rcx
#define n r8
#define y r9
#define i r10
#define a rax
#define ashort eax
S2N_BN_SYMBOL(bignum_sub):
endbr64
#if WINDOWS_ABI
push rdi
push rsi
mov rdi, rcx
mov rsi, rdx
mov rdx, r8
mov rcx, r9
mov r8, [rsp+56]
mov r9, [rsp+64]
#endif
// Zero the main index counter for both branches
xor i, i
// First clamp the two input sizes m := min(p,m) and n := min(p,n) since
// we'll never need words past the p'th. Can now assume m <= p and n <= p.
// Then compare the modified m and n and branch accordingly
cmp p, m
cmovc m, p
cmp p, n
cmovc n, p
cmp m, n
jc ylonger
// The case where x is longer or of the same size (p >= m >= n)
sub p, m
sub m, n
inc m
test n, n
jz xtest
xmainloop:
mov a, [x+8*i]
sbb a, [y+8*i]
mov [z+8*i],a
inc i
dec n
jnz xmainloop
jmp xtest
xtoploop:
mov a, [x+8*i]
sbb a, 0
mov [z+8*i],a
inc i
xtest:
dec m
jnz xtoploop
sbb a, a
test p, p
jz tailskip
tailloop:
mov [z+8*i],a
inc i
dec p
jnz tailloop
tailskip:
neg a
#if WINDOWS_ABI
pop rsi
pop rdi
#endif
ret
// The case where y is longer (p >= n > m)
ylonger:
sub p, n
sub n, m
test m, m
jz ytoploop
ymainloop:
mov a, [x+8*i]
sbb a, [y+8*i]
mov [z+8*i],a
inc i
dec m
jnz ymainloop
ytoploop:
mov ashort, 0
sbb a, [y+8*i]
mov [z+8*i],a
inc i
dec n
jnz ytoploop
sbb a, a
test p, p
jnz tailloop
neg a
#if WINDOWS_ABI
pop rsi
pop rdi
#endif
ret
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif

View File

@@ -0,0 +1,131 @@
/* $OpenBSD: bn_arch.c,v 1.6 2023/02/22 05:46:37 jsing Exp $ */
/*
* Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <openssl/bn.h>
#include "bn_arch.h"
#include "bn_local.h"
#include "s2n_bignum.h"
#ifdef HAVE_BN_ADD
BN_ULONG
bn_add(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len, const BN_ULONG *b,
int b_len)
{
return bignum_add(r_len, (uint64_t *)r, a_len, (uint64_t *)a,
b_len, (uint64_t *)b);
}
#endif
#ifdef HAVE_BN_ADD_WORDS
BN_ULONG
bn_add_words(BN_ULONG *rd, const BN_ULONG *ad, const BN_ULONG *bd, int n)
{
return bignum_add(n, (uint64_t *)rd, n, (uint64_t *)ad, n,
(uint64_t *)bd);
}
#endif
#ifdef HAVE_BN_SUB
BN_ULONG
bn_sub(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len, const BN_ULONG *b,
int b_len)
{
return bignum_sub(r_len, (uint64_t *)r, a_len, (uint64_t *)a,
b_len, (uint64_t *)b);
}
#endif
#ifdef HAVE_BN_SUB_WORDS
BN_ULONG
bn_sub_words(BN_ULONG *rd, const BN_ULONG *ad, const BN_ULONG *bd, int n)
{
return bignum_sub(n, (uint64_t *)rd, n, (uint64_t *)ad, n,
(uint64_t *)bd);
}
#endif
#ifdef HAVE_BN_MUL_ADD_WORDS
BN_ULONG
bn_mul_add_words(BN_ULONG *rd, const BN_ULONG *ad, int num, BN_ULONG w)
{
return bignum_cmadd(num, (uint64_t *)rd, w, num, (uint64_t *)ad);
}
#endif
#ifdef HAVE_BN_MUL_WORDS
BN_ULONG
bn_mul_words(BN_ULONG *rd, const BN_ULONG *ad, int num, BN_ULONG w)
{
return bignum_cmul(num, (uint64_t *)rd, w, num, (uint64_t *)ad);
}
#endif
#ifdef HAVE_BN_MUL_COMBA4
void
bn_mul_comba4(BN_ULONG *rd, BN_ULONG *ad, BN_ULONG *bd)
{
/* XXX - consider using non-alt on CPUs that have the ADX extension. */
bignum_mul_4_8_alt((uint64_t *)rd, (uint64_t *)ad, (uint64_t *)bd);
}
#endif
#ifdef HAVE_BN_MUL_COMBA8
void
bn_mul_comba8(BN_ULONG *rd, BN_ULONG *ad, BN_ULONG *bd)
{
/* XXX - consider using non-alt on CPUs that have the ADX extension. */
bignum_mul_8_16_alt((uint64_t *)rd, (uint64_t *)ad, (uint64_t *)bd);
}
#endif
#ifdef HAVE_BN_SQR
int
bn_sqr(BIGNUM *r, const BIGNUM *a, int rn, BN_CTX *ctx)
{
bignum_sqr(rn, (uint64_t *)r->d, a->top, (uint64_t *)a->d);
return 1;
}
#endif
#ifdef HAVE_BN_SQR_COMBA4
void
bn_sqr_comba4(BN_ULONG *rd, const BN_ULONG *ad)
{
/* XXX - consider using non-alt on CPUs that have the ADX extension. */
bignum_sqr_4_8_alt((uint64_t *)rd, (uint64_t *)ad);
}
#endif
#ifdef HAVE_BN_SQR_COMBA8
void
bn_sqr_comba8(BN_ULONG *rd, const BN_ULONG *ad)
{
/* XXX - consider using non-alt on CPUs that have the ADX extension. */
bignum_sqr_8_16_alt((uint64_t *)rd, (uint64_t *)ad);
}
#endif
#ifdef HAVE_BN_WORD_CLZ
int
bn_word_clz(BN_ULONG w)
{
return word_clz(w);
}
#endif

View File

@@ -0,0 +1,95 @@
/* $OpenBSD: bn_arch.h,v 1.13 2023/02/16 11:13:05 jsing Exp $ */
/*
* Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <openssl/bn.h>
#ifndef HEADER_BN_ARCH_H
#define HEADER_BN_ARCH_H
#ifdef _WIN32
#define OPENSSL_NO_ASM
#else
#ifndef OPENSSL_NO_ASM
#define HAVE_BN_ADD
#define HAVE_BN_ADD_WORDS
#define HAVE_BN_DIV_WORDS
#define HAVE_BN_MUL_ADD_WORDS
#define HAVE_BN_MUL_COMBA4
#define HAVE_BN_MUL_COMBA8
#define HAVE_BN_MUL_WORDS
#define HAVE_BN_SQR
#define HAVE_BN_SQR_COMBA4
#define HAVE_BN_SQR_COMBA8
#define HAVE_BN_SUB
#define HAVE_BN_SUB_WORDS
#define HAVE_BN_WORD_CLZ
#if defined(__GNUC__)
#define HAVE_BN_DIV_REM_WORDS_INLINE
static inline void
bn_div_rem_words_inline(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
BN_ULONG *out_r)
{
BN_ULONG q, r;
/*
* Unsigned division of %rdx:%rax by d with quotient being stored in
* %rax and remainder in %rdx.
*/
__asm__ volatile ("divq %4"
: "=a"(q), "=d"(r)
: "d"(h), "a"(l), "rm"(d)
: "cc");
*out_q = q;
*out_r = r;
}
#endif /* __GNUC__ */
#if defined(__GNUC__)
#define HAVE_BN_MULW
static inline void
bn_mulw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
{
BN_ULONG r1, r0;
/*
* Unsigned multiplication of %rax, with the double word result being
* stored in %rdx:%rax.
*/
__asm__ ("mulq %3"
: "=d"(r1), "=a"(r0)
: "a"(a), "rm"(b)
: "cc");
*out_r1 = r1;
*out_r0 = r0;
}
#endif /* __GNUC__ */
#endif /* _WIN32 */
#endif
#endif

View File

@@ -0,0 +1,60 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// ----------------------------------------------------------------------------
// Count leading zero bits in a single word
// Input a; output function return
//
// extern uint64_t word_clz (uint64_t a);
//
// Standard x86-64 ABI: RDI = a, returns RAX
// Microsoft x64 ABI: RCX = a, returns RAX
// ----------------------------------------------------------------------------
#include "s2n_bignum_internal.h"
.intel_syntax noprefix
S2N_BN_SYM_VISIBILITY_DIRECTIVE(word_clz)
S2N_BN_SYM_PRIVACY_DIRECTIVE(word_clz)
.text
S2N_BN_SYMBOL(word_clz):
endbr64
#if WINDOWS_ABI
push rdi
push rsi
mov rdi, rcx
#endif
// First do rax = 63 - bsr(a), which is right except (maybe) for zero inputs
bsr rax, rdi
xor rax, 63
// Force return of 64 in the zero-input case
mov edx, 64
test rdi, rdi
cmove rax, rdx
#if WINDOWS_ABI
pop rsi
pop rdi
#endif
ret
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif

View File

@@ -0,0 +1,24 @@
/* $OpenBSD: bn_arch.h,v 1.1 2023/01/20 10:04:33 jsing Exp $ */
/*
* Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef HEADER_BN_ARCH_H
#define HEADER_BN_ARCH_H
#ifndef OPENSSL_NO_ASM
#endif
#endif

View File

@@ -0,0 +1,86 @@
/* $OpenBSD: bn_arch.h,v 1.9 2023/02/16 10:41:03 jsing Exp $ */
/*
* Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <openssl/bn.h>
#ifndef HEADER_BN_ARCH_H
#define HEADER_BN_ARCH_H
#ifndef OPENSSL_NO_ASM
#define HAVE_BN_ADD_WORDS
#define HAVE_BN_DIV_WORDS
#define HAVE_BN_MUL_ADD_WORDS
#define HAVE_BN_MUL_COMBA4
#define HAVE_BN_MUL_COMBA8
#define HAVE_BN_MUL_WORDS
#define HAVE_BN_SQR_COMBA4
#define HAVE_BN_SQR_COMBA8
#define HAVE_BN_SQR_WORDS
#define HAVE_BN_SUB_WORDS
#if defined(__GNUC__)
#define HAVE_BN_DIV_REM_WORDS_INLINE
static inline void
bn_div_rem_words_inline(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
BN_ULONG *out_r)
{
BN_ULONG q, r;
/*
* Unsigned division of %edx:%eax by d with quotient being stored in
* %eax and remainder in %edx.
*/
__asm__ volatile ("divl %4"
: "=a"(q), "=d"(r)
: "a"(l), "d"(h), "rm"(d)
: "cc");
*out_q = q;
*out_r = r;
}
#endif /* __GNUC__ */
#if defined(__GNUC__)
#define HAVE_BN_MULW
static inline void
bn_mulw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
{
BN_ULONG r1, r0;
/*
* Unsigned multiplication of %eax, with the double word result being
* stored in %edx:%eax.
*/
__asm__ ("mull %3"
: "=d"(r1), "=a"(r0)
: "a"(a), "rm"(b)
: "cc");
*out_r1 = r1;
*out_r0 = r0;
}
#endif /* __GNUC__ */
#endif
#endif

View File

@@ -0,0 +1,24 @@
/* $OpenBSD: bn_arch.h,v 1.1 2023/01/20 10:04:34 jsing Exp $ */
/*
* Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef HEADER_BN_ARCH_H
#define HEADER_BN_ARCH_H
#ifndef OPENSSL_NO_ASM
#endif
#endif

View File

@@ -0,0 +1,40 @@
/* $OpenBSD: bn_arch.h,v 1.7 2023/01/23 12:17:58 jsing Exp $ */
/*
* Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef HEADER_BN_ARCH_H
#define HEADER_BN_ARCH_H
#ifndef OPENSSL_NO_ASM
#define HAVE_BN_ADD_WORDS
#define HAVE_BN_DIV_WORDS
#define HAVE_BN_DIV_3_WORDS
#define HAVE_BN_MUL_ADD_WORDS
#define HAVE_BN_MUL_COMBA4
#define HAVE_BN_MUL_COMBA8
#define HAVE_BN_MUL_WORDS
#define HAVE_BN_SQR_COMBA4
#define HAVE_BN_SQR_COMBA8
#define HAVE_BN_SQR_WORDS
#define HAVE_BN_SUB_WORDS
#endif
#endif

View File

@@ -0,0 +1,39 @@
/* $OpenBSD: bn_arch.h,v 1.6 2023/01/23 12:17:58 jsing Exp $ */
/*
* Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef HEADER_BN_ARCH_H
#define HEADER_BN_ARCH_H
#ifndef OPENSSL_NO_ASM
#define HAVE_BN_ADD_WORDS
#define HAVE_BN_DIV_WORDS
#define HAVE_BN_MUL_ADD_WORDS
#define HAVE_BN_MUL_COMBA4
#define HAVE_BN_MUL_COMBA8
#define HAVE_BN_MUL_WORDS
#define HAVE_BN_SQR_COMBA4
#define HAVE_BN_SQR_COMBA8
#define HAVE_BN_SQR_WORDS
#define HAVE_BN_SUB_WORDS
#endif
#endif

View File

@@ -0,0 +1,44 @@
/* $OpenBSD: bn_arch.h,v 1.4 2023/02/16 10:41:03 jsing Exp $ */
/*
* Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef HEADER_BN_ARCH_H
#define HEADER_BN_ARCH_H
#ifndef OPENSSL_NO_ASM
#if 0 /* Needs testing and enabling. */
#if defined(__GNUC__)
#define HAVE_BN_MULW
static inline void
bn_mulw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
{
BN_ULONG r1, r0;
/* Unsigned multiplication using a mulhdu/mul pair. */
__asm__ ("mulhdu %0, %2, %3; mul %1, %2, %3"
: "=&r"(r1), "=r"(r0)
: "r"(a), "r"(b));
*out_r1 = r1;
*out_r0 = r0;
}
#endif /* __GNUC__ */
#endif
#endif
#endif

View File

@@ -0,0 +1,48 @@
/* $OpenBSD: bn_arch.h,v 1.4 2023/02/16 10:41:03 jsing Exp $ */
/*
* Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef HEADER_BN_ARCH_H
#define HEADER_BN_ARCH_H
#ifndef OPENSSL_NO_ASM
#if 0 /* Needs testing and enabling. */
#if defined(__GNUC__)
#define HAVE_BN_MULW
static inline void
bn_mulw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
{
BN_ULONG r1, r0;
/*
* Unsigned multiplication using a mulh/mul pair. Note that the order
* of these instructions is important, as they can potentially be fused
* into a single operation.
*/
__asm__ ("mulh %0, %2, %3; mul %1, %2, %3"
: "=&r"(r1), "=r"(r0)
: "r"(a), "r"(b));
*out_r1 = r1;
*out_r0 = r0;
}
#endif /* __GNUC__ */
#endif
#endif
#endif

View File

@@ -0,0 +1,24 @@
/* $OpenBSD: bn_arch.h,v 1.1 2023/01/20 10:04:34 jsing Exp $ */
/*
* Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef HEADER_BN_ARCH_H
#define HEADER_BN_ARCH_H
#ifndef OPENSSL_NO_ASM
#endif
#endif

2162
externals/libressl/crypto/bn/bn-mips.S vendored Normal file

File diff suppressed because it is too large Load Diff

345
externals/libressl/crypto/bn/bn_add.c vendored Normal file
View File

@@ -0,0 +1,345 @@
/* $OpenBSD: bn_add.c,v 1.24 2023/02/22 05:46:37 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <openssl/err.h>
#include "bn_arch.h"
#include "bn_local.h"
#include "bn_internal.h"
/*
* bn_add_words() computes (carry:r[i]) = a[i] + b[i] + carry, where a and b
* are both arrays of words. Any carry resulting from the addition is returned.
*/
#ifndef HAVE_BN_ADD_WORDS
BN_ULONG
bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n)
{
BN_ULONG carry = 0;
assert(n >= 0);
if (n <= 0)
return 0;
#ifndef OPENSSL_SMALL_FOOTPRINT
while (n & ~3) {
bn_addw_addw(a[0], b[0], carry, &carry, &r[0]);
bn_addw_addw(a[1], b[1], carry, &carry, &r[1]);
bn_addw_addw(a[2], b[2], carry, &carry, &r[2]);
bn_addw_addw(a[3], b[3], carry, &carry, &r[3]);
a += 4;
b += 4;
r += 4;
n -= 4;
}
#endif
while (n) {
bn_addw_addw(a[0], b[0], carry, &carry, &r[0]);
a++;
b++;
r++;
n--;
}
return carry;
}
#endif
/*
* bn_add() computes (carry:r[i]) = a[i] + b[i] + carry, where a and b are both
* arrays of words (r may be the same as a or b). The length of a and b may
* differ, while r must be at least max(a_len, b_len) in length. Any carry
* resulting from the addition is returned.
*/
#ifndef HAVE_BN_ADD
BN_ULONG
bn_add(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len, const BN_ULONG *b,
int b_len)
{
int min_len, diff_len;
BN_ULONG carry = 0;
if ((min_len = a_len) > b_len)
min_len = b_len;
diff_len = a_len - b_len;
carry = bn_add_words(r, a, b, min_len);
a += min_len;
b += min_len;
r += min_len;
/* XXX - consider doing four at a time to match bn_add_words(). */
while (diff_len < 0) {
/* Compute r[0] = 0 + b[0] + carry. */
bn_addw(b[0], carry, &carry, &r[0]);
diff_len++;
b++;
r++;
}
/* XXX - consider doing four at a time to match bn_add_words(). */
while (diff_len > 0) {
/* Compute r[0] = a[0] + 0 + carry. */
bn_addw(a[0], carry, &carry, &r[0]);
diff_len--;
a++;
r++;
}
return carry;
}
#endif
/*
* bn_sub_words() computes (borrow:r[i]) = a[i] - b[i] - borrow, where a and b
* are both arrays of words. Any borrow resulting from the subtraction is
* returned.
*/
#ifndef HAVE_BN_SUB_WORDS
BN_ULONG
bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n)
{
BN_ULONG borrow = 0;
assert(n >= 0);
if (n <= 0)
return 0;
#ifndef OPENSSL_SMALL_FOOTPRINT
while (n & ~3) {
bn_subw_subw(a[0], b[0], borrow, &borrow, &r[0]);
bn_subw_subw(a[1], b[1], borrow, &borrow, &r[1]);
bn_subw_subw(a[2], b[2], borrow, &borrow, &r[2]);
bn_subw_subw(a[3], b[3], borrow, &borrow, &r[3]);
a += 4;
b += 4;
r += 4;
n -= 4;
}
#endif
while (n) {
bn_subw_subw(a[0], b[0], borrow, &borrow, &r[0]);
a++;
b++;
r++;
n--;
}
return borrow;
}
#endif
/*
* bn_sub() computes (borrow:r[i]) = a[i] - b[i] - borrow, where a and b are both
* arrays of words (r may be the same as a or b). The length of a and b may
* differ, while r must be at least max(a_len, b_len) in length. Any borrow
* resulting from the subtraction is returned.
*/
#ifndef HAVE_BN_SUB
BN_ULONG
bn_sub(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len, const BN_ULONG *b,
int b_len)
{
int min_len, diff_len;
BN_ULONG borrow = 0;
if ((min_len = a_len) > b_len)
min_len = b_len;
diff_len = a_len - b_len;
borrow = bn_sub_words(r, a, b, min_len);
a += min_len;
b += min_len;
r += min_len;
/* XXX - consider doing four at a time to match bn_sub_words. */
while (diff_len < 0) {
/* Compute r[0] = 0 - b[0] - borrow. */
bn_subw(0 - b[0], borrow, &borrow, &r[0]);
diff_len++;
b++;
r++;
}
/* XXX - consider doing four at a time to match bn_sub_words. */
while (diff_len > 0) {
/* Compute r[0] = a[0] - 0 - borrow. */
bn_subw(a[0], borrow, &borrow, &r[0]);
diff_len--;
a++;
r++;
}
return borrow;
}
#endif
int
BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
{
BN_ULONG carry;
int rn;
if ((rn = a->top) < b->top)
rn = b->top;
if (rn == INT_MAX)
return 0;
if (!bn_wexpand(r, rn + 1))
return 0;
carry = bn_add(r->d, rn, a->d, a->top, b->d, b->top);
r->d[rn] = carry;
r->top = rn + (carry & 1);
r->neg = 0;
return 1;
}
int
BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
{
BN_ULONG borrow;
int rn;
if (a->top < b->top) {
BNerror(BN_R_ARG2_LT_ARG3);
return 0;
}
rn = a->top;
if (!bn_wexpand(r, rn))
return 0;
borrow = bn_sub(r->d, rn, a->d, a->top, b->d, b->top);
if (borrow > 0) {
BNerror(BN_R_ARG2_LT_ARG3);
return 0;
}
r->top = rn;
r->neg = 0;
bn_correct_top(r);
return 1;
}
int
BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
{
int ret, r_neg;
if (a->neg == b->neg) {
r_neg = a->neg;
ret = BN_uadd(r, a, b);
} else {
int cmp = BN_ucmp(a, b);
if (cmp > 0) {
r_neg = a->neg;
ret = BN_usub(r, a, b);
} else if (cmp < 0) {
r_neg = b->neg;
ret = BN_usub(r, b, a);
} else {
r_neg = 0;
BN_zero(r);
ret = 1;
}
}
BN_set_negative(r, r_neg);
return ret;
}
int
BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
{
int ret, r_neg;
if (a->neg != b->neg) {
r_neg = a->neg;
ret = BN_uadd(r, a, b);
} else {
int cmp = BN_ucmp(a, b);
if (cmp > 0) {
r_neg = a->neg;
ret = BN_usub(r, a, b);
} else if (cmp < 0) {
r_neg = !b->neg;
ret = BN_usub(r, b, a);
} else {
r_neg = 0;
BN_zero(r);
ret = 1;
}
}
BN_set_negative(r, r_neg);
return ret;
}

365
externals/libressl/crypto/bn/bn_blind.c vendored Normal file
View File

@@ -0,0 +1,365 @@
/* $OpenBSD: bn_blind.c,v 1.22 2023/04/25 19:57:59 tb Exp $ */
/* ====================================================================
* Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include <openssl/opensslconf.h>
#include <openssl/err.h>
#include "bn_local.h"
#define BN_BLINDING_COUNTER 32
struct bn_blinding_st {
BIGNUM *A;
BIGNUM *Ai;
BIGNUM *e;
BIGNUM *mod; /* just a reference */
CRYPTO_THREADID tid;
int counter;
unsigned long flags;
BN_MONT_CTX *m_ctx;
int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
};
BN_BLINDING *
BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod)
{
BN_BLINDING *ret = NULL;
if ((ret = calloc(1, sizeof(BN_BLINDING))) == NULL) {
BNerror(ERR_R_MALLOC_FAILURE);
return (NULL);
}
if (A != NULL) {
if ((ret->A = BN_dup(A)) == NULL)
goto err;
}
if (Ai != NULL) {
if ((ret->Ai = BN_dup(Ai)) == NULL)
goto err;
}
/* save a copy of mod in the BN_BLINDING structure */
if ((ret->mod = BN_dup(mod)) == NULL)
goto err;
if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0)
BN_set_flags(ret->mod, BN_FLG_CONSTTIME);
/* Set the counter to the special value -1
* to indicate that this is never-used fresh blinding
* that does not need updating before first use. */
ret->counter = -1;
CRYPTO_THREADID_current(&ret->tid);
return (ret);
err:
if (ret != NULL)
BN_BLINDING_free(ret);
return (NULL);
}
void
BN_BLINDING_free(BN_BLINDING *r)
{
if (r == NULL)
return;
BN_free(r->A);
BN_free(r->Ai);
BN_free(r->e);
BN_free(r->mod);
free(r);
}
int
BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx)
{
int ret = 0;
if ((b->A == NULL) || (b->Ai == NULL)) {
BNerror(BN_R_NOT_INITIALIZED);
goto err;
}
if (b->counter == -1)
b->counter = 0;
if (++b->counter == BN_BLINDING_COUNTER && b->e != NULL &&
!(b->flags & BN_BLINDING_NO_RECREATE)) {
/* re-create blinding parameters */
if (!BN_BLINDING_create_param(b, NULL, NULL, ctx, NULL, NULL))
goto err;
} else if (!(b->flags & BN_BLINDING_NO_UPDATE)) {
if (!BN_mod_mul(b->A, b->A, b->A, b->mod, ctx))
goto err;
if (!BN_mod_mul(b->Ai, b->Ai, b->Ai, b->mod, ctx))
goto err;
}
ret = 1;
err:
if (b->counter == BN_BLINDING_COUNTER)
b->counter = 0;
return (ret);
}
int
BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx)
{
return BN_BLINDING_convert_ex(n, NULL, b, ctx);
}
int
BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx)
{
int ret = 1;
if ((b->A == NULL) || (b->Ai == NULL)) {
BNerror(BN_R_NOT_INITIALIZED);
return (0);
}
if (b->counter == -1)
/* Fresh blinding, doesn't need updating. */
b->counter = 0;
else if (!BN_BLINDING_update(b, ctx))
return (0);
if (r != NULL) {
if (!bn_copy(r, b->Ai))
ret = 0;
}
if (!BN_mod_mul(n, n,b->A, b->mod, ctx))
ret = 0;
return ret;
}
int
BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx)
{
return BN_BLINDING_invert_ex(n, NULL, b, ctx);
}
int
BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx)
{
int ret;
if (r != NULL)
ret = BN_mod_mul(n, n, r, b->mod, ctx);
else {
if (b->Ai == NULL) {
BNerror(BN_R_NOT_INITIALIZED);
return (0);
}
ret = BN_mod_mul(n, n, b->Ai, b->mod, ctx);
}
return (ret);
}
CRYPTO_THREADID *
BN_BLINDING_thread_id(BN_BLINDING *b)
{
return &b->tid;
}
unsigned long
BN_BLINDING_get_flags(const BN_BLINDING *b)
{
return b->flags;
}
void
BN_BLINDING_set_flags(BN_BLINDING *b, unsigned long flags)
{
b->flags = flags;
}
BN_BLINDING *
BN_BLINDING_create_param(BN_BLINDING *b, const BIGNUM *e, BIGNUM *m,
BN_CTX *ctx, int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx), BN_MONT_CTX *m_ctx)
{
int retry_counter = 32;
BN_BLINDING *ret = NULL;
if (b == NULL)
ret = BN_BLINDING_new(NULL, NULL, m);
else
ret = b;
if (ret == NULL)
goto err;
if (ret->A == NULL && (ret->A = BN_new()) == NULL)
goto err;
if (ret->Ai == NULL && (ret->Ai = BN_new()) == NULL)
goto err;
if (e != NULL) {
BN_free(ret->e);
ret->e = BN_dup(e);
}
if (ret->e == NULL)
goto err;
if (bn_mod_exp != NULL)
ret->bn_mod_exp = bn_mod_exp;
if (m_ctx != NULL)
ret->m_ctx = m_ctx;
do {
if (!BN_rand_range(ret->A, ret->mod))
goto err;
if (BN_mod_inverse_ct(ret->Ai, ret->A, ret->mod, ctx) == NULL) {
/* this should almost never happen for good RSA keys */
unsigned long error = ERR_peek_last_error();
if (ERR_GET_REASON(error) == BN_R_NO_INVERSE) {
if (retry_counter-- == 0) {
BNerror(BN_R_TOO_MANY_ITERATIONS);
goto err;
}
ERR_clear_error();
} else
goto err;
} else
break;
} while (1);
if (ret->bn_mod_exp != NULL && ret->m_ctx != NULL) {
if (!ret->bn_mod_exp(ret->A, ret->A, ret->e, ret->mod,
ctx, ret->m_ctx))
goto err;
} else {
if (!BN_mod_exp_ct(ret->A, ret->A, ret->e, ret->mod, ctx))
goto err;
}
return ret;
err:
if (b == NULL && ret != NULL) {
BN_BLINDING_free(ret);
ret = NULL;
}
return ret;
}

539
externals/libressl/crypto/bn/bn_bpsw.c vendored Normal file
View File

@@ -0,0 +1,539 @@
/* $OpenBSD: bn_bpsw.c,v 1.10 2023/05/10 21:05:24 tb Exp $ */
/*
* Copyright (c) 2022 Martin Grenouilloux <martin.grenouilloux@lse.epita.fr>
* Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <openssl/bn.h>
#include "bn_local.h"
#include "bn_prime.h"
/*
* For an odd n compute a / 2 (mod n). If a is even, we can do a plain
* division, otherwise calculate (a + n) / 2. Then reduce (mod n).
*/
static int
bn_div_by_two_mod_odd_n(BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
{
if (!BN_is_odd(n))
return 0;
if (BN_is_odd(a)) {
if (!BN_add(a, a, n))
return 0;
}
if (!BN_rshift1(a, a))
return 0;
if (!BN_mod_ct(a, a, n, ctx))
return 0;
return 1;
}
/*
* Given the next binary digit of k and the current Lucas terms U and V, this
* helper computes the next terms in the Lucas sequence defined as follows:
*
* U' = U * V (mod n)
* V' = (V^2 + D * U^2) / 2 (mod n)
*
* If digit == 0, bn_lucas_step() returns U' and V'. If digit == 1, it returns
*
* U'' = (U' + V') / 2 (mod n)
* V'' = (V' + D * U') / 2 (mod n)
*
* Compare with FIPS 186-4, Appendix C.3.3, step 6.
*/
static int
bn_lucas_step(BIGNUM *U, BIGNUM *V, int digit, const BIGNUM *D,
const BIGNUM *n, BN_CTX *ctx)
{
BIGNUM *tmp;
int ret = 0;
BN_CTX_start(ctx);
if ((tmp = BN_CTX_get(ctx)) == NULL)
goto err;
/* Calculate D * U^2 before computing U'. */
if (!BN_sqr(tmp, U, ctx))
goto err;
if (!BN_mul(tmp, D, tmp, ctx))
goto err;
/* U' = U * V (mod n). */
if (!BN_mod_mul(U, U, V, n, ctx))
goto err;
/* V' = (V^2 + D * U^2) / 2 (mod n). */
if (!BN_sqr(V, V, ctx))
goto err;
if (!BN_add(V, V, tmp))
goto err;
if (!bn_div_by_two_mod_odd_n(V, n, ctx))
goto err;
if (digit == 1) {
/* Calculate D * U' before computing U''. */
if (!BN_mul(tmp, D, U, ctx))
goto err;
/* U'' = (U' + V') / 2 (mod n). */
if (!BN_add(U, U, V))
goto err;
if (!bn_div_by_two_mod_odd_n(U, n, ctx))
goto err;
/* V'' = (V' + D * U') / 2 (mod n). */
if (!BN_add(V, V, tmp))
goto err;
if (!bn_div_by_two_mod_odd_n(V, n, ctx))
goto err;
}
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Compute the Lucas terms U_k, V_k, see FIPS 186-4, Appendix C.3.3, steps 4-6.
*/
static int
bn_lucas(BIGNUM *U, BIGNUM *V, const BIGNUM *k, const BIGNUM *D,
const BIGNUM *n, BN_CTX *ctx)
{
int digit, i;
int ret = 0;
if (!BN_one(U))
goto err;
if (!BN_one(V))
goto err;
/*
* Iterate over the digits of k from MSB to LSB. Start at digit 2
* since the first digit is dealt with by setting U = 1 and V = 1.
*/
for (i = BN_num_bits(k) - 2; i >= 0; i--) {
digit = BN_is_bit_set(k, i);
if (!bn_lucas_step(U, V, digit, D, n, ctx))
goto err;
}
ret = 1;
err:
return ret;
}
/*
* This is a stronger variant of the Lucas test in FIPS 186-4, Appendix C.3.3.
* Every strong Lucas pseudoprime n is also a Lucas pseudoprime since
* U_{n+1} == 0 follows from U_k == 0 or V_{k * 2^r} == 0 for 0 <= r < s.
*/
static int
bn_strong_lucas_test(int *is_pseudoprime, const BIGNUM *n, const BIGNUM *D,
BN_CTX *ctx)
{
BIGNUM *k, *U, *V;
int r, s;
int ret = 0;
BN_CTX_start(ctx);
if ((k = BN_CTX_get(ctx)) == NULL)
goto err;
if ((U = BN_CTX_get(ctx)) == NULL)
goto err;
if ((V = BN_CTX_get(ctx)) == NULL)
goto err;
/*
* Factorize n + 1 = k * 2^s with odd k: shift away the s trailing ones
* of n and set the lowest bit of the resulting number k.
*/
s = 0;
while (BN_is_bit_set(n, s))
s++;
if (!BN_rshift(k, n, s))
goto err;
if (!BN_set_bit(k, 0))
goto err;
/*
* Calculate the Lucas terms U_k and V_k. If either of them is zero,
* then n is a strong Lucas pseudoprime.
*/
if (!bn_lucas(U, V, k, D, n, ctx))
goto err;
if (BN_is_zero(U) || BN_is_zero(V)) {
*is_pseudoprime = 1;
goto done;
}
/*
* Calculate the Lucas terms U_{k * 2^r}, V_{k * 2^r} for 1 <= r < s.
* If any V_{k * 2^r} is zero then n is a strong Lucas pseudoprime.
*/
for (r = 1; r < s; r++) {
if (!bn_lucas_step(U, V, 0, D, n, ctx))
goto err;
if (BN_is_zero(V)) {
*is_pseudoprime = 1;
goto done;
}
}
/*
* If we got here, n is definitely composite.
*/
*is_pseudoprime = 0;
done:
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Test n for primality using the strong Lucas test with Selfridge's Method A.
* Returns 1 if n is prime or a strong Lucas-Selfridge pseudoprime.
* If it returns 0 then n is definitely composite.
*/
static int
bn_strong_lucas_selfridge(int *is_pseudoprime, const BIGNUM *n, BN_CTX *ctx)
{
BIGNUM *D, *two;
int is_perfect_square, jacobi_symbol, sign;
int ret = 0;
BN_CTX_start(ctx);
/* If n is a perfect square, it is composite. */
if (!bn_is_perfect_square(&is_perfect_square, n, ctx))
goto err;
if (is_perfect_square) {
*is_pseudoprime = 0;
goto done;
}
/*
* Find the first D in the Selfridge sequence 5, -7, 9, -11, 13, ...
* such that the Jacobi symbol (D/n) is -1.
*/
if ((D = BN_CTX_get(ctx)) == NULL)
goto err;
if ((two = BN_CTX_get(ctx)) == NULL)
goto err;
sign = 1;
if (!BN_set_word(D, 5))
goto err;
if (!BN_set_word(two, 2))
goto err;
while (1) {
/* For odd n the Kronecker symbol computes the Jacobi symbol. */
if ((jacobi_symbol = BN_kronecker(D, n, ctx)) == -2)
goto err;
/* We found the value for D. */
if (jacobi_symbol == -1)
break;
/* n and D have prime factors in common. */
if (jacobi_symbol == 0) {
*is_pseudoprime = 0;
goto done;
}
sign = -sign;
if (!BN_uadd(D, D, two))
goto err;
BN_set_negative(D, sign == -1);
}
if (!bn_strong_lucas_test(is_pseudoprime, n, D, ctx))
goto err;
done:
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Fermat criterion in Miller-Rabin test.
*
* Check whether 1 < base < n - 1 witnesses that n is composite. For prime n:
*
* * Fermat's little theorem: base^(n-1) = 1 (mod n).
* * The only square roots of 1 (mod n) are 1 and -1.
*
* Calculate base^((n-1)/2) by writing n - 1 = k * 2^s with odd k. Iteratively
* compute power = (base^k)^(2^(s-1)) by successive squaring of base^k.
*
* If power ever reaches -1, base^(n-1) is equal to 1 and n is a pseudoprime
* for base. If power reaches 1 before -1 during successive squaring, we have
* an unexpected square root of 1 and n is composite. Otherwise base^(n-1) != 1,
* and n is composite.
*/
static int
bn_fermat(int *is_pseudoprime, const BIGNUM *n, const BIGNUM *n_minus_one,
const BIGNUM *k, int s, const BIGNUM *base, BN_CTX *ctx, BN_MONT_CTX *mctx)
{
BIGNUM *power;
int ret = 0;
int i;
BN_CTX_start(ctx);
if ((power = BN_CTX_get(ctx)) == NULL)
goto err;
/* Sanity check: ensure that 1 < base < n - 1. */
if (BN_cmp(base, BN_value_one()) <= 0 || BN_cmp(base, n_minus_one) >= 0)
goto err;
if (!BN_mod_exp_mont_ct(power, base, k, n, ctx, mctx))
goto err;
if (BN_is_one(power) || BN_cmp(power, n_minus_one) == 0) {
*is_pseudoprime = 1;
goto done;
}
/* Loop invariant: power is neither 1 nor -1 (mod n). */
for (i = 1; i < s; i++) {
if (!BN_mod_sqr(power, power, n, ctx))
goto err;
/* n is a pseudoprime for base. */
if (BN_cmp(power, n_minus_one) == 0) {
*is_pseudoprime = 1;
goto done;
}
/* n is composite: there's a square root of unity != 1 or -1. */
if (BN_is_one(power)) {
*is_pseudoprime = 0;
goto done;
}
}
/*
* If we get here, n is definitely composite: base^(n-1) != 1.
*/
*is_pseudoprime = 0;
done:
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Miller-Rabin primality test for base 2 and for |rounds| of random bases.
* On success: is_pseudoprime == 0 implies that n is composite.
*/
static int
bn_miller_rabin(int *is_pseudoprime, const BIGNUM *n, BN_CTX *ctx,
size_t rounds)
{
BN_MONT_CTX *mctx = NULL;
BIGNUM *base, *k, *n_minus_one, *three;
size_t i;
int s;
int ret = 0;
BN_CTX_start(ctx);
if ((base = BN_CTX_get(ctx)) == NULL)
goto err;
if ((k = BN_CTX_get(ctx)) == NULL)
goto err;
if ((n_minus_one = BN_CTX_get(ctx)) == NULL)
goto err;
if ((three = BN_CTX_get(ctx)) == NULL)
goto err;
if (BN_is_word(n, 2) || BN_is_word(n, 3)) {
*is_pseudoprime = 1;
goto done;
}
if (BN_cmp(n, BN_value_one()) <= 0 || !BN_is_odd(n)) {
*is_pseudoprime = 0;
goto done;
}
if (!BN_sub(n_minus_one, n, BN_value_one()))
goto err;
/*
* Factorize n - 1 = k * 2^s.
*/
s = 0;
while (!BN_is_bit_set(n_minus_one, s))
s++;
if (!BN_rshift(k, n_minus_one, s))
goto err;
/*
* Montgomery setup for n.
*/
if ((mctx = BN_MONT_CTX_new()) == NULL)
goto err;
if (!BN_MONT_CTX_set(mctx, n, ctx))
goto err;
/*
* Perform a Miller-Rabin test for base 2 as required by BPSW.
*/
if (!BN_set_word(base, 2))
goto err;
if (!bn_fermat(is_pseudoprime, n, n_minus_one, k, s, base, ctx, mctx))
goto err;
if (!*is_pseudoprime)
goto done;
/*
* Perform Miller-Rabin tests with random 3 <= base < n - 1 to reduce
* risk of false positives in BPSW.
*/
if (!BN_set_word(three, 3))
goto err;
for (i = 0; i < rounds; i++) {
if (!bn_rand_interval(base, three, n_minus_one))
goto err;
if (!bn_fermat(is_pseudoprime, n, n_minus_one, k, s, base, ctx,
mctx))
goto err;
if (!*is_pseudoprime)
goto done;
}
/*
* If we got here, we have a Miller-Rabin pseudoprime.
*/
*is_pseudoprime = 1;
done:
ret = 1;
err:
BN_MONT_CTX_free(mctx);
BN_CTX_end(ctx);
return ret;
}
/*
* The Baillie-Pomerance-Selfridge-Wagstaff algorithm combines a Miller-Rabin
* test for base 2 with a Strong Lucas pseudoprime test.
*/
int
bn_is_prime_bpsw(int *is_pseudoprime, const BIGNUM *n, BN_CTX *in_ctx,
size_t rounds)
{
BN_CTX *ctx = NULL;
BN_ULONG mod;
int i;
int ret = 0;
if (BN_is_word(n, 2)) {
*is_pseudoprime = 1;
goto done;
}
if (BN_cmp(n, BN_value_one()) <= 0 || !BN_is_odd(n)) {
*is_pseudoprime = 0;
goto done;
}
/* Trial divisions with the first 2048 primes. */
for (i = 0; i < NUMPRIMES; i++) {
if ((mod = BN_mod_word(n, primes[i])) == (BN_ULONG)-1)
goto err;
if (mod == 0) {
*is_pseudoprime = BN_is_word(n, primes[i]);
goto done;
}
}
if ((ctx = in_ctx) == NULL)
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
if (!bn_miller_rabin(is_pseudoprime, n, ctx, rounds))
goto err;
if (!*is_pseudoprime)
goto done;
if (!bn_strong_lucas_selfridge(is_pseudoprime, n, ctx))
goto err;
done:
ret = 1;
err:
if (ctx != in_ctx)
BN_CTX_free(ctx);
return ret;
}

457
externals/libressl/crypto/bn/bn_const.c vendored Normal file
View File

@@ -0,0 +1,457 @@
/* $OpenBSD: bn_const.c,v 1.5 2018/02/20 17:02:30 jsing Exp $ */
/* Insert boilerplate */
#include <openssl/bn.h>
/* "First Oakley Default Group" from RFC2409, section 6.1.
*
* The prime is: 2^768 - 2 ^704 - 1 + 2^64 * { [2^638 pi] + 149686 }
*
* RFC2409 specifies a generator of 2.
* RFC2412 specifies a generator of of 22.
*/
BIGNUM *
get_rfc2409_prime_768(BIGNUM *bn)
{
static const unsigned char RFC2409_PRIME_768[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x3A, 0x36, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
};
return BN_bin2bn(RFC2409_PRIME_768, sizeof(RFC2409_PRIME_768), bn);
}
BIGNUM *
BN_get_rfc2409_prime_768(BIGNUM *bn)
{
return get_rfc2409_prime_768(bn);
}
/* "Second Oakley Default Group" from RFC2409, section 6.2.
*
* The prime is: 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }.
*
* RFC2409 specifies a generator of 2.
* RFC2412 specifies a generator of 22.
*/
BIGNUM *
get_rfc2409_prime_1024(BIGNUM *bn)
{
static const unsigned char RFC2409_PRIME_1024[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
};
return BN_bin2bn(RFC2409_PRIME_1024, sizeof(RFC2409_PRIME_1024), bn);
}
BIGNUM *
BN_get_rfc2409_prime_1024(BIGNUM *bn)
{
return get_rfc2409_prime_1024(bn);
}
/* "1536-bit MODP Group" from RFC3526, Section 2.
*
* The prime is: 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 }
*
* RFC3526 specifies a generator of 2.
* RFC2312 specifies a generator of 22.
*/
BIGNUM *
get_rfc3526_prime_1536(BIGNUM *bn)
{
static const unsigned char RFC3526_PRIME_1536[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
};
return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), bn);
}
BIGNUM *
BN_get_rfc3526_prime_1536(BIGNUM *bn)
{
return get_rfc3526_prime_1536(bn);
}
/* "2048-bit MODP Group" from RFC3526, Section 3.
*
* The prime is: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }
*
* RFC3526 specifies a generator of 2.
*/
BIGNUM *
get_rfc3526_prime_2048(BIGNUM *bn)
{
static const unsigned char RFC3526_PRIME_2048[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
};
return BN_bin2bn(RFC3526_PRIME_2048, sizeof(RFC3526_PRIME_2048), bn);
}
BIGNUM *
BN_get_rfc3526_prime_2048(BIGNUM *bn)
{
return get_rfc3526_prime_2048(bn);
}
/* "3072-bit MODP Group" from RFC3526, Section 4.
*
* The prime is: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 }
*
* RFC3526 specifies a generator of 2.
*/
BIGNUM *
get_rfc3526_prime_3072(BIGNUM *bn)
{
static const unsigned char RFC3526_PRIME_3072[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
};
return BN_bin2bn(RFC3526_PRIME_3072, sizeof(RFC3526_PRIME_3072), bn);
}
BIGNUM *
BN_get_rfc3526_prime_3072(BIGNUM *bn)
{
return get_rfc3526_prime_3072(bn);
}
/* "4096-bit MODP Group" from RFC3526, Section 5.
*
* The prime is: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 }
*
* RFC3526 specifies a generator of 2.
*/
BIGNUM *
get_rfc3526_prime_4096(BIGNUM *bn)
{
static const unsigned char RFC3526_PRIME_4096[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
};
return BN_bin2bn(RFC3526_PRIME_4096, sizeof(RFC3526_PRIME_4096), bn);
}
BIGNUM *
BN_get_rfc3526_prime_4096(BIGNUM *bn)
{
return get_rfc3526_prime_4096(bn);
}
/* "6144-bit MODP Group" from RFC3526, Section 6.
*
* The prime is: 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 }
*
* RFC3526 specifies a generator of 2.
*/
BIGNUM *
get_rfc3526_prime_6144(BIGNUM *bn)
{
static const unsigned char RFC3526_PRIME_6144[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92,
0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, 0xC1, 0xD4, 0xDC, 0xB2,
0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F,
0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31,
0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, 0xDA, 0x3E, 0xDB, 0xEB,
0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51,
0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF,
0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, 0x32, 0xEA, 0x15,
0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31,
0x90, 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3,
0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, 0x45, 0xB7,
0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2,
0x0F, 0x80, 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28,
0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, 0x3D,
0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7,
0x6E, 0x3C, 0x04, 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE,
0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E,
0x6D, 0xCC, 0x40, 0x24, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
};
return BN_bin2bn(RFC3526_PRIME_6144, sizeof(RFC3526_PRIME_6144), bn);
}
BIGNUM *
BN_get_rfc3526_prime_6144(BIGNUM *bn)
{
return get_rfc3526_prime_6144(bn);
}
/* "8192-bit MODP Group" from RFC3526, Section 7.
*
* The prime is: 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 }
*
* RFC3526 specifies a generator of 2.
*/
BIGNUM *
get_rfc3526_prime_8192(BIGNUM *bn)
{
static const unsigned char RFC3526_PRIME_8192[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92,
0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, 0xC1, 0xD4, 0xDC, 0xB2,
0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F,
0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31,
0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, 0xDA, 0x3E, 0xDB, 0xEB,
0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51,
0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF,
0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, 0x32, 0xEA, 0x15,
0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31,
0x90, 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3,
0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, 0x45, 0xB7,
0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2,
0x0F, 0x80, 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28,
0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, 0x3D,
0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7,
0x6E, 0x3C, 0x04, 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE,
0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E,
0x6D, 0xBE, 0x11, 0x59, 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4,
0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, 0xD8, 0xBE, 0xC4, 0xD0,
0x73, 0xB9, 0x31, 0xBA, 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00,
0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, 0x25, 0x76, 0xF6, 0x93,
0x6B, 0xA4, 0x24, 0x66, 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68,
0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, 0x23, 0x8F, 0x16, 0xCB,
0xE3, 0x9D, 0x65, 0x2D, 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9,
0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, 0x13, 0xEB, 0x57, 0xA8,
0x1A, 0x23, 0xF0, 0xC7, 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B,
0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, 0xFA, 0x9D, 0x4B, 0x7F,
0xA2, 0xC0, 0x87, 0xE8, 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A,
0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, 0x6D, 0x2A, 0x13, 0xF8,
0x3F, 0x44, 0xF8, 0x2D, 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36,
0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, 0x64, 0xF3, 0x1C, 0xC5,
0x08, 0x46, 0x85, 0x1D, 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1,
0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, 0xFA, 0xF3, 0x6B, 0xC3,
0x1E, 0xCF, 0xA2, 0x68, 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92,
0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, 0x88, 0x9A, 0x00, 0x2E,
0xD5, 0xEE, 0x38, 0x2B, 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47,
0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, 0x9E, 0x30, 0x50, 0xE2,
0x76, 0x56, 0x94, 0xDF, 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71,
0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
};
return BN_bin2bn(RFC3526_PRIME_8192, sizeof(RFC3526_PRIME_8192), bn);
}
BIGNUM *
BN_get_rfc3526_prime_8192(BIGNUM *bn)
{
return get_rfc3526_prime_8192(bn);
}

View File

@@ -0,0 +1,656 @@
/* $OpenBSD: bn_convert.c,v 1.8 2023/05/09 05:15:55 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <openssl/opensslconf.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/err.h>
#include "bn_local.h"
#include "bytestring.h"
static const char hex_digits[] = "0123456789ABCDEF";
typedef enum {
big,
little,
} endianness_t;
/* ignore negative */
static int
bn2binpad(const BIGNUM *a, unsigned char *to, int tolen, endianness_t endianness)
{
int n;
size_t i, lasti, j, atop, mask;
BN_ULONG l;
/*
* In case |a| is fixed-top, BN_num_bytes can return bogus length,
* but it's assumed that fixed-top inputs ought to be "nominated"
* even for padded output, so it works out...
*/
n = BN_num_bytes(a);
if (tolen == -1)
tolen = n;
else if (tolen < n) { /* uncommon/unlike case */
BIGNUM temp = *a;
bn_correct_top(&temp);
n = BN_num_bytes(&temp);
if (tolen < n)
return -1;
}
/* Swipe through whole available data and don't give away padded zero. */
atop = a->dmax * BN_BYTES;
if (atop == 0) {
explicit_bzero(to, tolen);
return tolen;
}
lasti = atop - 1;
atop = a->top * BN_BYTES;
if (endianness == big)
to += tolen; /* start from the end of the buffer */
for (i = 0, j = 0; j < (size_t)tolen; j++) {
unsigned char val;
l = a->d[i / BN_BYTES];
mask = 0 - ((j - atop) >> (8 * sizeof(i) - 1));
val = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask);
if (endianness == big)
*--to = val;
else
*to++ = val;
i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */
}
return tolen;
}
int
BN_bn2bin(const BIGNUM *a, unsigned char *to)
{
return bn2binpad(a, to, -1, big);
}
int
BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
{
if (tolen < 0)
return -1;
return bn2binpad(a, to, tolen, big);
}
BIGNUM *
BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
{
unsigned int i, m;
unsigned int n;
BN_ULONG l;
BIGNUM *bn = NULL;
if (len < 0)
return (NULL);
if (ret == NULL)
ret = bn = BN_new();
if (ret == NULL)
return (NULL);
l = 0;
n = len;
if (n == 0) {
ret->top = 0;
return (ret);
}
i = ((n - 1) / BN_BYTES) + 1;
m = ((n - 1) % (BN_BYTES));
if (!bn_wexpand(ret, (int)i)) {
BN_free(bn);
return NULL;
}
ret->top = i;
ret->neg = 0;
while (n--) {
l = (l << 8L) | *(s++);
if (m-- == 0) {
ret->d[--i] = l;
l = 0;
m = BN_BYTES - 1;
}
}
/* need to call this due to clear byte at top if avoiding
* having the top bit set (-ve number) */
bn_correct_top(ret);
return (ret);
}
int
BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen)
{
if (tolen < 0)
return -1;
return bn2binpad(a, to, tolen, little);
}
BIGNUM *
BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret)
{
unsigned int i, m, n;
BN_ULONG l;
BIGNUM *bn = NULL;
if (ret == NULL)
ret = bn = BN_new();
if (ret == NULL)
return NULL;
s += len;
/* Skip trailing zeroes. */
for (; len > 0 && s[-1] == 0; s--, len--)
continue;
n = len;
if (n == 0) {
ret->top = 0;
return ret;
}
i = ((n - 1) / BN_BYTES) + 1;
m = (n - 1) % BN_BYTES;
if (!bn_wexpand(ret, (int)i)) {
BN_free(bn);
return NULL;
}
ret->top = i;
ret->neg = 0;
l = 0;
while (n-- > 0) {
s--;
l = (l << 8L) | *s;
if (m-- == 0) {
ret->d[--i] = l;
l = 0;
m = BN_BYTES - 1;
}
}
/*
* need to call this due to clear byte at top if avoiding having the
* top bit set (-ve number)
*/
bn_correct_top(ret);
return ret;
}
int
BN_asc2bn(BIGNUM **bn, const char *a)
{
const char *p = a;
if (*p == '-')
p++;
if (p[0] == '0' && (p[1] == 'X' || p[1] == 'x')) {
if (!BN_hex2bn(bn, p + 2))
return 0;
} else {
if (!BN_dec2bn(bn, p))
return 0;
}
if (*a == '-')
BN_set_negative(*bn, 1);
return 1;
}
char *
BN_bn2dec(const BIGNUM *bn)
{
int started = 0;
BIGNUM *tmp = NULL;
uint8_t *data = NULL;
size_t data_len = 0;
uint8_t *s = NULL;
size_t s_len;
BN_ULONG v, w;
uint8_t c;
CBB cbb;
CBS cbs;
int i;
if (!CBB_init(&cbb, 0))
goto err;
if ((tmp = BN_dup(bn)) == NULL)
goto err;
/*
* Divide the BIGNUM by a large multiple of 10, then break the remainder
* into decimal digits. This produces a reversed string of digits,
* potentially with leading zeroes.
*/
while (!BN_is_zero(tmp)) {
if ((w = BN_div_word(tmp, BN_DEC_CONV)) == -1)
goto err;
for (i = 0; i < BN_DEC_NUM; i++) {
v = w % 10;
if (!CBB_add_u8(&cbb, '0' + v))
goto err;
w /= 10;
}
}
if (!CBB_finish(&cbb, &data, &data_len))
goto err;
if (data_len > SIZE_MAX - 3)
goto err;
if (!CBB_init(&cbb, data_len + 3))
goto err;
if (BN_is_negative(bn)) {
if (!CBB_add_u8(&cbb, '-'))
goto err;
}
/* Reverse digits and trim leading zeroes. */
CBS_init(&cbs, data, data_len);
while (CBS_len(&cbs) > 0) {
if (!CBS_get_last_u8(&cbs, &c))
goto err;
if (!started && c == '0')
continue;
if (!CBB_add_u8(&cbb, c))
goto err;
started = 1;
}
if (!started) {
if (!CBB_add_u8(&cbb, '0'))
goto err;
}
if (!CBB_add_u8(&cbb, '\0'))
goto err;
if (!CBB_finish(&cbb, &s, &s_len))
goto err;
err:
BN_free(tmp);
CBB_cleanup(&cbb);
freezero(data, data_len);
return s;
}
int
BN_dec2bn(BIGNUM **bn, const char *a)
{
BIGNUM *ret = NULL;
BN_ULONG l = 0;
int neg = 0, i, j;
int num;
if ((a == NULL) || (*a == '\0'))
return (0);
if (*a == '-') {
neg = 1;
a++;
}
for (i = 0; i <= (INT_MAX / 4) && isdigit((unsigned char)a[i]); i++)
;
if (i > INT_MAX / 4)
return (0);
num = i + neg;
if (bn == NULL)
return (num);
/* a is the start of the digits, and it is 'i' long.
* We chop it into BN_DEC_NUM digits at a time */
if (*bn == NULL) {
if ((ret = BN_new()) == NULL)
return (0);
} else {
ret = *bn;
BN_zero(ret);
}
/* i is the number of digits, a bit of an over expand */
if (!bn_expand(ret, i * 4))
goto err;
j = BN_DEC_NUM - (i % BN_DEC_NUM);
if (j == BN_DEC_NUM)
j = 0;
l = 0;
while (*a) {
l *= 10;
l += *a - '0';
a++;
if (++j == BN_DEC_NUM) {
if (!BN_mul_word(ret, BN_DEC_CONV))
goto err;
if (!BN_add_word(ret, l))
goto err;
l = 0;
j = 0;
}
}
bn_correct_top(ret);
BN_set_negative(ret, neg);
*bn = ret;
return (num);
err:
if (*bn == NULL)
BN_free(ret);
return (0);
}
char *
BN_bn2hex(const BIGNUM *bn)
{
int started = 0;
uint8_t *s = NULL;
size_t s_len;
BN_ULONG v, w;
int i, j;
CBB cbb;
if (!CBB_init(&cbb, 0))
goto err;
if (BN_is_negative(bn)) {
if (!CBB_add_u8(&cbb, '-'))
goto err;
}
if (BN_is_zero(bn)) {
if (!CBB_add_u8(&cbb, '0'))
goto err;
}
for (i = bn->top - 1; i >= 0; i--) {
w = bn->d[i];
for (j = BN_BITS2 - 8; j >= 0; j -= 8) {
v = (w >> j) & 0xff;
if (!started && v == 0)
continue;
if (!CBB_add_u8(&cbb, hex_digits[v >> 4]))
goto err;
if (!CBB_add_u8(&cbb, hex_digits[v & 0xf]))
goto err;
started = 1;
}
}
if (!CBB_add_u8(&cbb, '\0'))
goto err;
if (!CBB_finish(&cbb, &s, &s_len))
goto err;
err:
CBB_cleanup(&cbb);
return s;
}
int
BN_hex2bn(BIGNUM **bn, const char *a)
{
BIGNUM *ret = NULL;
BN_ULONG l = 0;
int neg = 0, h, m, i,j, k, c;
int num;
if ((a == NULL) || (*a == '\0'))
return (0);
if (*a == '-') {
neg = 1;
a++;
}
for (i = 0; i <= (INT_MAX / 4) && isxdigit((unsigned char)a[i]); i++)
;
if (i > INT_MAX / 4)
return (0);
num = i + neg;
if (bn == NULL)
return (num);
/* a is the start of the hex digits, and it is 'i' long */
if (*bn == NULL) {
if ((ret = BN_new()) == NULL)
return (0);
} else {
ret = *bn;
BN_zero(ret);
}
/* i is the number of hex digits */
if (!bn_expand(ret, i * 4))
goto err;
j = i; /* least significant 'hex' */
m = 0;
h = 0;
while (j > 0) {
m = ((BN_BYTES * 2) <= j) ? (BN_BYTES * 2) : j;
l = 0;
for (;;) {
c = a[j - m];
if ((c >= '0') && (c <= '9'))
k = c - '0';
else if ((c >= 'a') && (c <= 'f'))
k = c - 'a' + 10;
else if ((c >= 'A') && (c <= 'F'))
k = c - 'A' + 10;
else
k = 0; /* paranoia */
l = (l << 4) | k;
if (--m <= 0) {
ret->d[h++] = l;
break;
}
}
j -= (BN_BYTES * 2);
}
ret->top = h;
bn_correct_top(ret);
BN_set_negative(ret, neg);
*bn = ret;
return (num);
err:
if (*bn == NULL)
BN_free(ret);
return (0);
}
int
BN_bn2mpi(const BIGNUM *a, unsigned char *d)
{
int bits;
int num = 0;
int ext = 0;
long l;
bits = BN_num_bits(a);
num = (bits + 7) / 8;
if (bits > 0) {
ext = ((bits & 0x07) == 0);
}
if (d == NULL)
return (num + 4 + ext);
l = num + ext;
d[0] = (unsigned char)(l >> 24) & 0xff;
d[1] = (unsigned char)(l >> 16) & 0xff;
d[2] = (unsigned char)(l >> 8) & 0xff;
d[3] = (unsigned char)(l) & 0xff;
if (ext)
d[4] = 0;
num = BN_bn2bin(a, &(d[4 + ext]));
if (a->neg)
d[4] |= 0x80;
return (num + 4 + ext);
}
BIGNUM *
BN_mpi2bn(const unsigned char *d, int n, BIGNUM *ain)
{
BIGNUM *a = ain;
long len;
int neg = 0;
if (n < 4) {
BNerror(BN_R_INVALID_LENGTH);
return (NULL);
}
len = ((long)d[0] << 24) | ((long)d[1] << 16) | ((int)d[2] << 8) |
(int)d[3];
if ((len + 4) != n) {
BNerror(BN_R_ENCODING_ERROR);
return (NULL);
}
if (a == NULL)
a = BN_new();
if (a == NULL)
return (NULL);
if (len == 0) {
a->neg = 0;
a->top = 0;
return (a);
}
d += 4;
if ((*d) & 0x80)
neg = 1;
if (BN_bin2bn(d, (int)len, a) == NULL) {
if (ain == NULL)
BN_free(a);
return (NULL);
}
BN_set_negative(a, neg);
if (neg) {
BN_clear_bit(a, BN_num_bits(a) - 1);
}
return (a);
}
#ifndef OPENSSL_NO_BIO
int
BN_print_fp(FILE *fp, const BIGNUM *a)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL)
return (0);
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = BN_print(b, a);
BIO_free(b);
return (ret);
}
int
BN_print(BIO *bp, const BIGNUM *a)
{
int i, j, v, z = 0;
int ret = 0;
if ((a->neg) && (BIO_write(bp, "-", 1) != 1))
goto end;
if (BN_is_zero(a) && (BIO_write(bp, "0", 1) != 1))
goto end;
for (i = a->top - 1; i >= 0; i--) {
for (j = BN_BITS2 - 4; j >= 0; j -= 4) {
/* strip leading zeros */
v = ((int)(a->d[i] >> (long)j)) & 0x0f;
if (z || (v != 0)) {
if (BIO_write(bp, &hex_digits[v], 1) != 1)
goto end;
z = 1;
}
}
}
ret = 1;
end:
return (ret);
}
#endif

156
externals/libressl/crypto/bn/bn_ctx.c vendored Normal file
View File

@@ -0,0 +1,156 @@
/* $OpenBSD: bn_ctx.c,v 1.21 2023/04/25 16:41:29 tb Exp $ */
/*
* Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stddef.h>
#include <string.h>
#include <openssl/opensslconf.h>
#include <openssl/err.h>
#include "bn_local.h"
#define BN_CTX_INITIAL_LEN 8
struct bignum_ctx {
BIGNUM **bignums;
uint8_t *groups;
uint8_t group;
size_t index;
size_t len;
int error;
};
static int
bn_ctx_grow(BN_CTX *bctx)
{
BIGNUM **bignums = NULL;
uint8_t *groups = NULL;
size_t len;
if ((len = bctx->len) == 0) {
len = BN_CTX_INITIAL_LEN;
} else {
if (SIZE_MAX - len < len)
return 0;
len *= 2;
}
if ((bignums = recallocarray(bctx->bignums, bctx->len, len,
sizeof(bctx->bignums[0]))) == NULL)
return 0;
bctx->bignums = bignums;
if ((groups = reallocarray(bctx->groups, len,
sizeof(bctx->groups[0]))) == NULL)
return 0;
bctx->groups = groups;
bctx->len = len;
return 1;
}
BN_CTX *
BN_CTX_new(void)
{
return calloc(1, sizeof(struct bignum_ctx));
}
void
BN_CTX_free(BN_CTX *bctx)
{
size_t i;
if (bctx == NULL)
return;
for (i = 0; i < bctx->len; i++) {
BN_free(bctx->bignums[i]);
bctx->bignums[i] = NULL;
}
free(bctx->bignums);
free(bctx->groups);
freezero(bctx, sizeof(*bctx));
}
void
BN_CTX_start(BN_CTX *bctx)
{
bctx->group++;
if (bctx->group == 0) {
BNerror(BN_R_TOO_MANY_TEMPORARY_VARIABLES);
bctx->error = 1;
return;
}
}
BIGNUM *
BN_CTX_get(BN_CTX *bctx)
{
BIGNUM *bn = NULL;
if (bctx->error)
return NULL;
if (bctx->group == 0) {
BNerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
bctx->error = 1;
return NULL;
}
if (bctx->index == bctx->len) {
if (!bn_ctx_grow(bctx)) {
BNerror(BN_R_TOO_MANY_TEMPORARY_VARIABLES);
bctx->error = 1;
return NULL;
}
}
if ((bn = bctx->bignums[bctx->index]) == NULL) {
if ((bn = BN_new()) == NULL) {
BNerror(BN_R_TOO_MANY_TEMPORARY_VARIABLES);
bctx->error = 1;
return NULL;
}
bctx->bignums[bctx->index] = bn;
}
bctx->groups[bctx->index] = bctx->group;
bctx->index++;
BN_zero(bn);
return bn;
}
void
BN_CTX_end(BN_CTX *bctx)
{
if (bctx == NULL || bctx->error || bctx->group == 0)
return;
while (bctx->index > 0 && bctx->groups[bctx->index - 1] == bctx->group) {
BN_zero(bctx->bignums[bctx->index - 1]);
bctx->groups[bctx->index - 1] = 0;
bctx->index--;
}
bctx->group--;
}

457
externals/libressl/crypto/bn/bn_div.c vendored Normal file
View File

@@ -0,0 +1,457 @@
/* $OpenBSD: bn_div.c,v 1.40 2023/03/27 10:21:23 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <assert.h>
#include <stdio.h>
#include <openssl/opensslconf.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include "bn_arch.h"
#include "bn_local.h"
#include "bn_internal.h"
BN_ULONG bn_div_3_words(const BN_ULONG *m, BN_ULONG d1, BN_ULONG d0);
#ifndef HAVE_BN_DIV_WORDS
#if defined(BN_LLONG) && defined(BN_DIV2W)
BN_ULONG
bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
{
return ((BN_ULONG)(((((BN_ULLONG)h) << BN_BITS2)|l)/(BN_ULLONG)d));
}
#else
/* Divide h,l by d and return the result. */
/* I need to test this some more :-( */
BN_ULONG
bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
{
BN_ULONG dh, dl, q,ret = 0, th, tl, t;
int i, count = 2;
if (d == 0)
return (BN_MASK2);
i = BN_num_bits_word(d);
assert((i == BN_BITS2) || (h <= (BN_ULONG)1 << i));
i = BN_BITS2 - i;
if (h >= d)
h -= d;
if (i) {
d <<= i;
h = (h << i) | (l >> (BN_BITS2 - i));
l <<= i;
}
dh = (d & BN_MASK2h) >> BN_BITS4;
dl = (d & BN_MASK2l);
for (;;) {
if ((h >> BN_BITS4) == dh)
q = BN_MASK2l;
else
q = h / dh;
th = q * dh;
tl = dl * q;
for (;;) {
t = h - th;
if ((t & BN_MASK2h) ||
((tl) <= (
(t << BN_BITS4) |
((l & BN_MASK2h) >> BN_BITS4))))
break;
q--;
th -= dh;
tl -= dl;
}
t = (tl >> BN_BITS4);
tl = (tl << BN_BITS4) & BN_MASK2h;
th += t;
if (l < tl)
th++;
l -= tl;
if (h < th) {
h += d;
q--;
}
h -= th;
if (--count == 0)
break;
ret = q << BN_BITS4;
h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2;
l = (l & BN_MASK2l) << BN_BITS4;
}
ret |= q;
return (ret);
}
#endif /* !defined(BN_LLONG) && defined(BN_DIV2W) */
#endif
/*
* Divide a double word (h:l) by d, returning the quotient q and the remainder
* r, such that q * d + r is equal to the numerator.
*/
#ifndef HAVE_BN_DIV_REM_WORDS
#ifndef HAVE_BN_DIV_REM_WORDS_INLINE
static inline void
bn_div_rem_words_inline(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
BN_ULONG *out_r)
{
BN_ULONG q, r;
q = bn_div_words(h, l, d);
r = (l - q * d) & BN_MASK2;
*out_q = q;
*out_r = r;
}
#endif
void
bn_div_rem_words(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
BN_ULONG *out_r)
{
bn_div_rem_words_inline(h, l, d, out_q, out_r);
}
#endif
#ifndef HAVE_BN_DIV_3_WORDS
/*
* Interface is somewhat quirky, |m| is pointer to most significant limb,
* and less significant limb is referred at |m[-1]|. This means that caller
* is responsible for ensuring that |m[-1]| is valid. Second condition that
* has to be met is that |d0|'s most significant bit has to be set. Or in
* other words divisor has to be "bit-aligned to the left." The subroutine
* considers four limbs, two of which are "overlapping," hence the name...
*/
BN_ULONG
bn_div_3_words(const BN_ULONG *m, BN_ULONG d1, BN_ULONG d0)
{
BN_ULONG n0, n1, q, t2h, t2l;
BN_ULONG rem = 0;
n0 = m[0];
n1 = m[-1];
if (n0 == d0)
return BN_MASK2;
/* n0 < d0 */
bn_div_rem_words(n0, n1, d0, &q, &rem);
bn_mulw(d1, q, &t2h, &t2l);
for (;;) {
if (t2h < rem || (t2h == rem && t2l <= m[-2]))
break;
q--;
rem += d0;
if (rem < d0)
break; /* don't let rem overflow */
if (t2l < d1)
t2h--;
t2l -= d1;
}
return q;
}
#endif /* !HAVE_BN_DIV_3_WORDS */
/*
* BN_div_internal computes quotient := numerator / divisor, rounding towards
* zero and setting remainder such that quotient * divisor + remainder equals
* the numerator. Thus:
*
* quotient->neg == numerator->neg ^ divisor->neg (unless result is zero)
* remainder->neg == numerator->neg (unless the remainder is zero)
*
* If either the quotient or remainder is NULL, the respective value is not
* returned.
*/
static int
BN_div_internal(BIGNUM *quotient, BIGNUM *remainder, const BIGNUM *numerator,
const BIGNUM *divisor, BN_CTX *ctx, int ct)
{
int norm_shift, i, loop, r_neg;
BIGNUM *tmp, wnum, *snum, *sdiv, *res;
BN_ULONG *resp, *wnump;
BN_ULONG d0, d1;
int num_n, div_n;
int no_branch = 0;
int ret = 0;
BN_CTX_start(ctx);
/* Invalid zero-padding would have particularly bad consequences. */
if (numerator->top > 0 && numerator->d[numerator->top - 1] == 0) {
BNerror(BN_R_NOT_INITIALIZED);
goto err;
}
if (ct)
no_branch = 1;
if (BN_is_zero(divisor)) {
BNerror(BN_R_DIV_BY_ZERO);
goto err;
}
if (!no_branch) {
if (BN_ucmp(numerator, divisor) < 0) {
if (remainder != NULL) {
if (!bn_copy(remainder, numerator))
goto err;
}
if (quotient != NULL)
BN_zero(quotient);
goto done;
}
}
if ((tmp = BN_CTX_get(ctx)) == NULL)
goto err;
if ((snum = BN_CTX_get(ctx)) == NULL)
goto err;
if ((sdiv = BN_CTX_get(ctx)) == NULL)
goto err;
if ((res = quotient) == NULL) {
if ((res = BN_CTX_get(ctx)) == NULL)
goto err;
}
/* First we normalise the numbers. */
norm_shift = BN_BITS2 - BN_num_bits(divisor) % BN_BITS2;
if (!BN_lshift(sdiv, divisor, norm_shift))
goto err;
sdiv->neg = 0;
norm_shift += BN_BITS2;
if (!BN_lshift(snum, numerator, norm_shift))
goto err;
snum->neg = 0;
if (no_branch) {
/*
* Since we don't know whether snum is larger than sdiv, we pad
* snum with enough zeroes without changing its value.
*/
if (snum->top <= sdiv->top + 1) {
if (!bn_wexpand(snum, sdiv->top + 2))
goto err;
for (i = snum->top; i < sdiv->top + 2; i++)
snum->d[i] = 0;
snum->top = sdiv->top + 2;
} else {
if (!bn_wexpand(snum, snum->top + 1))
goto err;
snum->d[snum->top] = 0;
snum->top++;
}
}
div_n = sdiv->top;
num_n = snum->top;
loop = num_n - div_n;
/*
* Setup a 'window' into snum - this is the part that corresponds to the
* current 'area' being divided.
*/
wnum.neg = 0;
wnum.d = &(snum->d[loop]);
wnum.top = div_n;
/* only needed when BN_ucmp messes up the values between top and max */
wnum.dmax = snum->dmax - loop; /* so we don't step out of bounds */
wnum.flags = snum->flags | BN_FLG_STATIC_DATA;
/* Get the top 2 words of sdiv */
/* div_n=sdiv->top; */
d0 = sdiv->d[div_n - 1];
d1 = (div_n == 1) ? 0 : sdiv->d[div_n - 2];
/* pointer to the 'top' of snum */
wnump = &(snum->d[num_n - 1]);
/* Setup to 'res' */
if (!bn_wexpand(res, (loop + 1)))
goto err;
res->top = loop - no_branch;
r_neg = numerator->neg ^ divisor->neg;
resp = &(res->d[loop - 1]);
/* space for temp */
if (!bn_wexpand(tmp, (div_n + 1)))
goto err;
if (!no_branch) {
if (BN_ucmp(&wnum, sdiv) >= 0) {
bn_sub_words(wnum.d, wnum.d, sdiv->d, div_n);
*resp = 1;
} else
res->top--;
}
/*
* If res->top == 0 then clear the neg value otherwise decrease the resp
* pointer.
*/
if (res->top == 0)
res->neg = 0;
else
resp--;
for (i = 0; i < loop - 1; i++, wnump--, resp--) {
BN_ULONG q, l0;
/*
* The first part of the loop uses the top two words of snum and
* sdiv to calculate a BN_ULONG q such that:
*
* | wnum - sdiv * q | < sdiv
*/
q = bn_div_3_words(wnump, d1, d0);
l0 = bn_mul_words(tmp->d, sdiv->d, div_n, q);
tmp->d[div_n] = l0;
wnum.d--;
/*
* Ignore top values of the bignums just sub the two BN_ULONG
* arrays with bn_sub_words.
*/
if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n + 1)) {
/*
* Note: As we have considered only the leading two
* BN_ULONGs in the calculation of q, sdiv * q might be
* greater than wnum (but then (q-1) * sdiv is less or
* equal than wnum).
*/
q--;
if (bn_add_words(wnum.d, wnum.d, sdiv->d, div_n)) {
/*
* We can't have an overflow here (assuming
* that q != 0, but if q == 0 then tmp is
* zero anyway).
*/
(*wnump)++;
}
}
/* store part of the result */
*resp = q;
}
bn_correct_top(snum);
if (remainder != NULL) {
/*
* Keep a copy of the neg flag in numerator because if
* remainder == numerator, BN_rshift() will overwrite it.
*/
int neg = numerator->neg;
BN_rshift(remainder, snum, norm_shift);
BN_set_negative(remainder, neg);
}
if (no_branch)
bn_correct_top(res);
BN_set_negative(res, r_neg);
done:
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
int
BN_div(BIGNUM *quotient, BIGNUM *remainder, const BIGNUM *numerator,
const BIGNUM *divisor, BN_CTX *ctx)
{
int ct;
ct = BN_get_flags(numerator, BN_FLG_CONSTTIME) != 0 ||
BN_get_flags(divisor, BN_FLG_CONSTTIME) != 0;
return BN_div_internal(quotient, remainder, numerator, divisor, ctx, ct);
}
int
BN_div_nonct(BIGNUM *quotient, BIGNUM *remainder, const BIGNUM *numerator,
const BIGNUM *divisor, BN_CTX *ctx)
{
return BN_div_internal(quotient, remainder, numerator, divisor, ctx, 0);
}
int
BN_div_ct(BIGNUM *quotient, BIGNUM *remainder, const BIGNUM *numerator,
const BIGNUM *divisor, BN_CTX *ctx)
{
return BN_div_internal(quotient, remainder, numerator, divisor, ctx, 1);
}

106
externals/libressl/crypto/bn/bn_err.c vendored Normal file
View File

@@ -0,0 +1,106 @@
/* $OpenBSD: bn_err.c,v 1.15 2022/07/12 14:42:48 kn Exp $ */
/* ====================================================================
* Copyright (c) 1999-2007 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include <stdio.h>
#include <openssl/opensslconf.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#ifndef OPENSSL_NO_ERR
#define ERR_FUNC(func) ERR_PACK(ERR_LIB_BN,func,0)
#define ERR_REASON(reason) ERR_PACK(ERR_LIB_BN,0,reason)
static ERR_STRING_DATA BN_str_functs[]= {
{ERR_FUNC(0xfff), "CRYPTO_internal"},
{0, NULL}
};
static ERR_STRING_DATA BN_str_reasons[]= {
{ERR_REASON(BN_R_ARG2_LT_ARG3) , "arg2 lt arg3"},
{ERR_REASON(BN_R_BAD_RECIPROCAL) , "bad reciprocal"},
{ERR_REASON(BN_R_BIGNUM_TOO_LONG) , "bignum too long"},
{ERR_REASON(BN_R_BITS_TOO_SMALL) , "bits too small"},
{ERR_REASON(BN_R_CALLED_WITH_EVEN_MODULUS), "called with even modulus"},
{ERR_REASON(BN_R_DIV_BY_ZERO) , "div by zero"},
{ERR_REASON(BN_R_ENCODING_ERROR) , "encoding error"},
{ERR_REASON(BN_R_EXPAND_ON_STATIC_BIGNUM_DATA), "expand on static bignum data"},
{ERR_REASON(BN_R_INPUT_NOT_REDUCED) , "input not reduced"},
{ERR_REASON(BN_R_INVALID_LENGTH) , "invalid length"},
{ERR_REASON(BN_R_INVALID_RANGE) , "invalid range"},
{ERR_REASON(BN_R_NOT_A_SQUARE) , "not a square"},
{ERR_REASON(BN_R_NOT_INITIALIZED) , "not initialized"},
{ERR_REASON(BN_R_NO_INVERSE) , "no inverse"},
{ERR_REASON(BN_R_NO_SOLUTION) , "no solution"},
{ERR_REASON(BN_R_P_IS_NOT_PRIME) , "p is not prime"},
{ERR_REASON(BN_R_TOO_MANY_ITERATIONS) , "too many iterations"},
{ERR_REASON(BN_R_TOO_MANY_TEMPORARY_VARIABLES), "too many temporary variables"},
{0, NULL}
};
#endif
void
ERR_load_BN_strings(void)
{
#ifndef OPENSSL_NO_ERR
if (ERR_func_error_string(BN_str_functs[0].error) == NULL) {
ERR_load_strings(0, BN_str_functs);
ERR_load_strings(0, BN_str_reasons);
}
#endif
}

1333
externals/libressl/crypto/bn/bn_exp.c vendored Normal file

File diff suppressed because it is too large Load Diff

828
externals/libressl/crypto/bn/bn_gcd.c vendored Normal file
View File

@@ -0,0 +1,828 @@
/* $OpenBSD: bn_gcd.c,v 1.27 2023/04/09 18:38:59 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
/* ====================================================================
* Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include <openssl/err.h>
#include "bn_local.h"
static BIGNUM *
euclid(BIGNUM *a, BIGNUM *b)
{
BIGNUM *t;
int shifts = 0;
/* Loop invariant: 0 <= b <= a. */
while (!BN_is_zero(b)) {
if (BN_is_odd(a) && BN_is_odd(b)) {
if (!BN_sub(a, a, b))
goto err;
if (!BN_rshift1(a, a))
goto err;
} else if (BN_is_odd(a) && !BN_is_odd(b)) {
if (!BN_rshift1(b, b))
goto err;
} else if (!BN_is_odd(a) && BN_is_odd(b)) {
if (!BN_rshift1(a, a))
goto err;
} else {
if (!BN_rshift1(a, a))
goto err;
if (!BN_rshift1(b, b))
goto err;
shifts++;
continue;
}
if (BN_cmp(a, b) < 0) {
t = a;
a = b;
b = t;
}
}
if (shifts) {
if (!BN_lshift(a, a, shifts))
goto err;
}
return a;
err:
return NULL;
}
int
BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx)
{
BIGNUM *a, *b, *t;
int ret = 0;
BN_CTX_start(ctx);
if ((a = BN_CTX_get(ctx)) == NULL)
goto err;
if ((b = BN_CTX_get(ctx)) == NULL)
goto err;
if (!bn_copy(a, in_a))
goto err;
if (!bn_copy(b, in_b))
goto err;
a->neg = 0;
b->neg = 0;
if (BN_cmp(a, b) < 0) {
t = a;
a = b;
b = t;
}
t = euclid(a, b);
if (t == NULL)
goto err;
if (!bn_copy(r, t))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
return (ret);
}
int
BN_gcd_nonct(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx)
{
return BN_gcd(r, in_a, in_b, ctx);
}
/*
* BN_gcd_no_branch is a special version of BN_mod_inverse_no_branch.
* that returns the GCD.
*/
static BIGNUM *
BN_gcd_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n,
BN_CTX *ctx)
{
BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL;
BIGNUM local_A, local_B;
BIGNUM *pA, *pB;
BIGNUM *ret = NULL;
int sign;
if (in == NULL)
goto err;
R = in;
BN_init(&local_A);
BN_init(&local_B);
BN_CTX_start(ctx);
if ((A = BN_CTX_get(ctx)) == NULL)
goto err;
if ((B = BN_CTX_get(ctx)) == NULL)
goto err;
if ((X = BN_CTX_get(ctx)) == NULL)
goto err;
if ((D = BN_CTX_get(ctx)) == NULL)
goto err;
if ((M = BN_CTX_get(ctx)) == NULL)
goto err;
if ((Y = BN_CTX_get(ctx)) == NULL)
goto err;
if ((T = BN_CTX_get(ctx)) == NULL)
goto err;
if (!BN_one(X))
goto err;
BN_zero(Y);
if (!bn_copy(B, a))
goto err;
if (!bn_copy(A, n))
goto err;
A->neg = 0;
if (B->neg || (BN_ucmp(B, A) >= 0)) {
/*
* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
* BN_div_no_branch will be called eventually.
*/
pB = &local_B;
/* BN_init() done at the top of the function. */
BN_with_flags(pB, B, BN_FLG_CONSTTIME);
if (!BN_nnmod(B, pB, A, ctx))
goto err;
}
sign = -1;
/* From B = a mod |n|, A = |n| it follows that
*
* 0 <= B < A,
* -sign*X*a == B (mod |n|),
* sign*Y*a == A (mod |n|).
*/
while (!BN_is_zero(B)) {
BIGNUM *tmp;
/*
* 0 < B < A,
* (*) -sign*X*a == B (mod |n|),
* sign*Y*a == A (mod |n|)
*/
/*
* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
* BN_div_no_branch will be called eventually.
*/
pA = &local_A;
/* BN_init() done at the top of the function. */
BN_with_flags(pA, A, BN_FLG_CONSTTIME);
/* (D, M) := (A/B, A%B) ... */
if (!BN_div_ct(D, M, pA, B, ctx))
goto err;
/* Now
* A = D*B + M;
* thus we have
* (**) sign*Y*a == D*B + M (mod |n|).
*/
tmp = A; /* keep the BIGNUM object, the value does not matter */
/* (A, B) := (B, A mod B) ... */
A = B;
B = M;
/* ... so we have 0 <= B < A again */
/* Since the former M is now B and the former B is now A,
* (**) translates into
* sign*Y*a == D*A + B (mod |n|),
* i.e.
* sign*Y*a - D*A == B (mod |n|).
* Similarly, (*) translates into
* -sign*X*a == A (mod |n|).
*
* Thus,
* sign*Y*a + D*sign*X*a == B (mod |n|),
* i.e.
* sign*(Y + D*X)*a == B (mod |n|).
*
* So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at
* -sign*X*a == B (mod |n|),
* sign*Y*a == A (mod |n|).
* Note that X and Y stay non-negative all the time.
*/
if (!BN_mul(tmp, D, X, ctx))
goto err;
if (!BN_add(tmp, tmp, Y))
goto err;
M = Y; /* keep the BIGNUM object, the value does not matter */
Y = X;
X = tmp;
sign = -sign;
}
/*
* The while loop (Euclid's algorithm) ends when
* A == gcd(a,n);
*/
if (!bn_copy(R, A))
goto err;
ret = R;
err:
if ((ret == NULL) && (in == NULL))
BN_free(R);
BN_CTX_end(ctx);
return (ret);
}
int
BN_gcd_ct(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx)
{
if (BN_gcd_no_branch(r, in_a, in_b, ctx) == NULL)
return 0;
return 1;
}
/* BN_mod_inverse_no_branch is a special version of BN_mod_inverse.
* It does not contain branches that may leak sensitive information.
*/
static BIGNUM *
BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n,
BN_CTX *ctx)
{
BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL;
BIGNUM local_A, local_B;
BIGNUM *pA, *pB;
BIGNUM *ret = NULL;
int sign;
BN_init(&local_A);
BN_init(&local_B);
BN_CTX_start(ctx);
if ((A = BN_CTX_get(ctx)) == NULL)
goto err;
if ((B = BN_CTX_get(ctx)) == NULL)
goto err;
if ((X = BN_CTX_get(ctx)) == NULL)
goto err;
if ((D = BN_CTX_get(ctx)) == NULL)
goto err;
if ((M = BN_CTX_get(ctx)) == NULL)
goto err;
if ((Y = BN_CTX_get(ctx)) == NULL)
goto err;
if ((T = BN_CTX_get(ctx)) == NULL)
goto err;
if (in == NULL)
R = BN_new();
else
R = in;
if (R == NULL)
goto err;
if (!BN_one(X))
goto err;
BN_zero(Y);
if (!bn_copy(B, a))
goto err;
if (!bn_copy(A, n))
goto err;
A->neg = 0;
if (B->neg || (BN_ucmp(B, A) >= 0)) {
/*
* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
* BN_div_no_branch will be called eventually.
*/
pB = &local_B;
/* BN_init() done at the top of the function. */
BN_with_flags(pB, B, BN_FLG_CONSTTIME);
if (!BN_nnmod(B, pB, A, ctx))
goto err;
}
sign = -1;
/* From B = a mod |n|, A = |n| it follows that
*
* 0 <= B < A,
* -sign*X*a == B (mod |n|),
* sign*Y*a == A (mod |n|).
*/
while (!BN_is_zero(B)) {
BIGNUM *tmp;
/*
* 0 < B < A,
* (*) -sign*X*a == B (mod |n|),
* sign*Y*a == A (mod |n|)
*/
/*
* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
* BN_div_no_branch will be called eventually.
*/
pA = &local_A;
/* BN_init() done at the top of the function. */
BN_with_flags(pA, A, BN_FLG_CONSTTIME);
/* (D, M) := (A/B, A%B) ... */
if (!BN_div_ct(D, M, pA, B, ctx))
goto err;
/* Now
* A = D*B + M;
* thus we have
* (**) sign*Y*a == D*B + M (mod |n|).
*/
tmp = A; /* keep the BIGNUM object, the value does not matter */
/* (A, B) := (B, A mod B) ... */
A = B;
B = M;
/* ... so we have 0 <= B < A again */
/* Since the former M is now B and the former B is now A,
* (**) translates into
* sign*Y*a == D*A + B (mod |n|),
* i.e.
* sign*Y*a - D*A == B (mod |n|).
* Similarly, (*) translates into
* -sign*X*a == A (mod |n|).
*
* Thus,
* sign*Y*a + D*sign*X*a == B (mod |n|),
* i.e.
* sign*(Y + D*X)*a == B (mod |n|).
*
* So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at
* -sign*X*a == B (mod |n|),
* sign*Y*a == A (mod |n|).
* Note that X and Y stay non-negative all the time.
*/
if (!BN_mul(tmp, D, X, ctx))
goto err;
if (!BN_add(tmp, tmp, Y))
goto err;
M = Y; /* keep the BIGNUM object, the value does not matter */
Y = X;
X = tmp;
sign = -sign;
}
/*
* The while loop (Euclid's algorithm) ends when
* A == gcd(a,n);
* we have
* sign*Y*a == A (mod |n|),
* where Y is non-negative.
*/
if (sign < 0) {
if (!BN_sub(Y, n, Y))
goto err;
}
/* Now Y*a == A (mod |n|). */
if (BN_is_one(A)) {
/* Y*a == 1 (mod |n|) */
if (!Y->neg && BN_ucmp(Y, n) < 0) {
if (!bn_copy(R, Y))
goto err;
} else {
if (!BN_nnmod(R, Y, n, ctx))
goto err;
}
} else {
BNerror(BN_R_NO_INVERSE);
goto err;
}
ret = R;
err:
if ((ret == NULL) && (in == NULL))
BN_free(R);
BN_CTX_end(ctx);
return (ret);
}
/* solves ax == 1 (mod n) */
static BIGNUM *
BN_mod_inverse_internal(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx,
int ct)
{
BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL;
BIGNUM *ret = NULL;
int sign;
if (ct)
return BN_mod_inverse_no_branch(in, a, n, ctx);
BN_CTX_start(ctx);
if ((A = BN_CTX_get(ctx)) == NULL)
goto err;
if ((B = BN_CTX_get(ctx)) == NULL)
goto err;
if ((X = BN_CTX_get(ctx)) == NULL)
goto err;
if ((D = BN_CTX_get(ctx)) == NULL)
goto err;
if ((M = BN_CTX_get(ctx)) == NULL)
goto err;
if ((Y = BN_CTX_get(ctx)) == NULL)
goto err;
if ((T = BN_CTX_get(ctx)) == NULL)
goto err;
if (in == NULL)
R = BN_new();
else
R = in;
if (R == NULL)
goto err;
if (!BN_one(X))
goto err;
BN_zero(Y);
if (!bn_copy(B, a))
goto err;
if (!bn_copy(A, n))
goto err;
A->neg = 0;
if (B->neg || (BN_ucmp(B, A) >= 0)) {
if (!BN_nnmod(B, B, A, ctx))
goto err;
}
sign = -1;
/* From B = a mod |n|, A = |n| it follows that
*
* 0 <= B < A,
* -sign*X*a == B (mod |n|),
* sign*Y*a == A (mod |n|).
*/
if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS <= 32 ? 450 : 2048))) {
/* Binary inversion algorithm; requires odd modulus.
* This is faster than the general algorithm if the modulus
* is sufficiently small (about 400 .. 500 bits on 32-bit
* systems, but much more on 64-bit systems) */
int shift;
while (!BN_is_zero(B)) {
/*
* 0 < B < |n|,
* 0 < A <= |n|,
* (1) -sign*X*a == B (mod |n|),
* (2) sign*Y*a == A (mod |n|)
*/
/* Now divide B by the maximum possible power of two in the integers,
* and divide X by the same value mod |n|.
* When we're done, (1) still holds. */
shift = 0;
while (!BN_is_bit_set(B, shift)) /* note that 0 < B */
{
shift++;
if (BN_is_odd(X)) {
if (!BN_uadd(X, X, n))
goto err;
}
/* now X is even, so we can easily divide it by two */
if (!BN_rshift1(X, X))
goto err;
}
if (shift > 0) {
if (!BN_rshift(B, B, shift))
goto err;
}
/* Same for A and Y. Afterwards, (2) still holds. */
shift = 0;
while (!BN_is_bit_set(A, shift)) /* note that 0 < A */
{
shift++;
if (BN_is_odd(Y)) {
if (!BN_uadd(Y, Y, n))
goto err;
}
/* now Y is even */
if (!BN_rshift1(Y, Y))
goto err;
}
if (shift > 0) {
if (!BN_rshift(A, A, shift))
goto err;
}
/* We still have (1) and (2).
* Both A and B are odd.
* The following computations ensure that
*
* 0 <= B < |n|,
* 0 < A < |n|,
* (1) -sign*X*a == B (mod |n|),
* (2) sign*Y*a == A (mod |n|),
*
* and that either A or B is even in the next iteration.
*/
if (BN_ucmp(B, A) >= 0) {
/* -sign*(X + Y)*a == B - A (mod |n|) */
if (!BN_uadd(X, X, Y))
goto err;
/* NB: we could use BN_mod_add_quick(X, X, Y, n), but that
* actually makes the algorithm slower */
if (!BN_usub(B, B, A))
goto err;
} else {
/* sign*(X + Y)*a == A - B (mod |n|) */
if (!BN_uadd(Y, Y, X))
goto err;
/* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */
if (!BN_usub(A, A, B))
goto err;
}
}
} else {
/* general inversion algorithm */
while (!BN_is_zero(B)) {
BIGNUM *tmp;
/*
* 0 < B < A,
* (*) -sign*X*a == B (mod |n|),
* sign*Y*a == A (mod |n|)
*/
/* (D, M) := (A/B, A%B) ... */
if (BN_num_bits(A) == BN_num_bits(B)) {
if (!BN_one(D))
goto err;
if (!BN_sub(M, A, B))
goto err;
} else if (BN_num_bits(A) == BN_num_bits(B) + 1) {
/* A/B is 1, 2, or 3 */
if (!BN_lshift1(T, B))
goto err;
if (BN_ucmp(A, T) < 0) {
/* A < 2*B, so D=1 */
if (!BN_one(D))
goto err;
if (!BN_sub(M, A, B))
goto err;
} else {
/* A >= 2*B, so D=2 or D=3 */
if (!BN_sub(M, A, T))
goto err;
if (!BN_add(D,T,B)) goto err; /* use D (:= 3*B) as temp */
if (BN_ucmp(A, D) < 0) {
/* A < 3*B, so D=2 */
if (!BN_set_word(D, 2))
goto err;
/* M (= A - 2*B) already has the correct value */
} else {
/* only D=3 remains */
if (!BN_set_word(D, 3))
goto err;
/* currently M = A - 2*B, but we need M = A - 3*B */
if (!BN_sub(M, M, B))
goto err;
}
}
} else {
if (!BN_div_nonct(D, M, A, B, ctx))
goto err;
}
/* Now
* A = D*B + M;
* thus we have
* (**) sign*Y*a == D*B + M (mod |n|).
*/
tmp = A; /* keep the BIGNUM object, the value does not matter */
/* (A, B) := (B, A mod B) ... */
A = B;
B = M;
/* ... so we have 0 <= B < A again */
/* Since the former M is now B and the former B is now A,
* (**) translates into
* sign*Y*a == D*A + B (mod |n|),
* i.e.
* sign*Y*a - D*A == B (mod |n|).
* Similarly, (*) translates into
* -sign*X*a == A (mod |n|).
*
* Thus,
* sign*Y*a + D*sign*X*a == B (mod |n|),
* i.e.
* sign*(Y + D*X)*a == B (mod |n|).
*
* So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at
* -sign*X*a == B (mod |n|),
* sign*Y*a == A (mod |n|).
* Note that X and Y stay non-negative all the time.
*/
/* most of the time D is very small, so we can optimize tmp := D*X+Y */
if (BN_is_one(D)) {
if (!BN_add(tmp, X, Y))
goto err;
} else {
if (BN_is_word(D, 2)) {
if (!BN_lshift1(tmp, X))
goto err;
} else if (BN_is_word(D, 4)) {
if (!BN_lshift(tmp, X, 2))
goto err;
} else if (D->top == 1) {
if (!bn_copy(tmp, X))
goto err;
if (!BN_mul_word(tmp, D->d[0]))
goto err;
} else {
if (!BN_mul(tmp, D,X, ctx))
goto err;
}
if (!BN_add(tmp, tmp, Y))
goto err;
}
M = Y; /* keep the BIGNUM object, the value does not matter */
Y = X;
X = tmp;
sign = -sign;
}
}
/*
* The while loop (Euclid's algorithm) ends when
* A == gcd(a,n);
* we have
* sign*Y*a == A (mod |n|),
* where Y is non-negative.
*/
if (sign < 0) {
if (!BN_sub(Y, n, Y))
goto err;
}
/* Now Y*a == A (mod |n|). */
if (BN_is_one(A)) {
/* Y*a == 1 (mod |n|) */
if (!Y->neg && BN_ucmp(Y, n) < 0) {
if (!bn_copy(R, Y))
goto err;
} else {
if (!BN_nnmod(R, Y,n, ctx))
goto err;
}
} else {
BNerror(BN_R_NO_INVERSE);
goto err;
}
ret = R;
err:
if ((ret == NULL) && (in == NULL))
BN_free(R);
BN_CTX_end(ctx);
return (ret);
}
BIGNUM *
BN_mod_inverse(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
{
int ct = ((BN_get_flags(a, BN_FLG_CONSTTIME) != 0) ||
(BN_get_flags(n, BN_FLG_CONSTTIME) != 0));
return BN_mod_inverse_internal(in, a, n, ctx, ct);
}
BIGNUM *
BN_mod_inverse_nonct(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
{
return BN_mod_inverse_internal(in, a, n, ctx, 0);
}
BIGNUM *
BN_mod_inverse_ct(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
{
return BN_mod_inverse_internal(in, a, n, ctx, 1);
}

View File

@@ -0,0 +1,390 @@
/* $OpenBSD: bn_internal.h,v 1.11 2023/03/07 09:35:55 jsing Exp $ */
/*
* Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <openssl/bn.h>
#include "bn_arch.h"
#ifndef HEADER_BN_INTERNAL_H
#define HEADER_BN_INTERNAL_H
#ifndef HAVE_BN_CT_NE_ZERO
static inline int
bn_ct_ne_zero(BN_ULONG w)
{
return (w | ~(w - 1)) >> (BN_BITS2 - 1);
}
#endif
#ifndef HAVE_BN_CT_NE_ZERO_MASK
static inline BN_ULONG
bn_ct_ne_zero_mask(BN_ULONG w)
{
return 0 - bn_ct_ne_zero(w);
}
#endif
#ifndef HAVE_BN_CT_EQ_ZERO
static inline int
bn_ct_eq_zero(BN_ULONG w)
{
return 1 - bn_ct_ne_zero(w);
}
#endif
#ifndef HAVE_BN_CT_EQ_ZERO_MASK
static inline BN_ULONG
bn_ct_eq_zero_mask(BN_ULONG w)
{
return 0 - bn_ct_eq_zero(w);
}
#endif
/*
* Big number primitives are named as the operation followed by a suffix
* that indicates the number of words that it operates on, where 'w' means
* single word, 'dw' means double word, 'tw' means triple word and 'qw' means
* quadruple word. Unless otherwise noted, the size of the output is implied
* based on its inputs, for example bn_mulw() takes two single word inputs
* and is going to produce a double word result.
*
* Where a function implements multiple operations, these are listed in order.
* For example, a function that computes (r1:r0) = a * b + c is named
* bn_mulw_addw(), producing a double word result.
*/
/*
* bn_addw() computes (r1:r0) = a + b, where both inputs are single words,
* producing a double word result. The value of r1 is the carry from the
* addition.
*/
#ifndef HAVE_BN_ADDW
#ifdef BN_LLONG
static inline void
bn_addw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
{
BN_ULLONG r;
r = (BN_ULLONG)a + (BN_ULLONG)b;
*out_r1 = r >> BN_BITS2;
*out_r0 = r & BN_MASK2;
}
#else
static inline void
bn_addw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
{
BN_ULONG r1, r0, c1, c2;
c1 = a | b;
c2 = a & b;
r0 = a + b;
r1 = ((c1 & ~r0) | c2) >> (BN_BITS2 - 1); /* carry */
*out_r1 = r1;
*out_r0 = r0;
}
#endif
#endif
/*
* bn_addw_addw() computes (r1:r0) = a + b + c, where all inputs are single
* words, producing a double word result.
*/
#ifndef HAVE_BN_ADDW_ADDW
static inline void
bn_addw_addw(BN_ULONG a, BN_ULONG b, BN_ULONG c, BN_ULONG *out_r1,
BN_ULONG *out_r0)
{
BN_ULONG carry, r1, r0;
bn_addw(a, b, &r1, &r0);
bn_addw(r0, c, &carry, &r0);
r1 += carry;
*out_r1 = r1;
*out_r0 = r0;
}
#endif
/*
* bn_subw() computes r0 = a - b, where both inputs are single words,
* producing a single word result and borrow.
*/
#ifndef HAVE_BN_SUBW
static inline void
bn_subw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_borrow, BN_ULONG *out_r0)
{
BN_ULONG borrow, r0;
r0 = a - b;
borrow = ((r0 | (b & ~a)) & (b | ~a)) >> (BN_BITS2 - 1);
*out_borrow = borrow;
*out_r0 = r0;
}
#endif
/*
* bn_subw_subw() computes r0 = a - b - c, where all inputs are single words,
* producing a single word result and borrow.
*/
#ifndef HAVE_BN_SUBW_SUBW
static inline void
bn_subw_subw(BN_ULONG a, BN_ULONG b, BN_ULONG c, BN_ULONG *out_borrow,
BN_ULONG *out_r0)
{
BN_ULONG b1, b2, r0;
bn_subw(a, b, &b1, &r0);
bn_subw(r0, c, &b2, &r0);
*out_borrow = b1 + b2;
*out_r0 = r0;
}
#endif
/*
* bn_mulw() computes (r1:r0) = a * b, where both inputs are single words,
* producing a double word result.
*/
#ifndef HAVE_BN_MULW
#ifdef BN_LLONG
static inline void
bn_mulw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
{
BN_ULLONG r;
r = (BN_ULLONG)a * (BN_ULLONG)b;
*out_r1 = r >> BN_BITS2;
*out_r0 = r & BN_MASK2;
}
#else /* !BN_LLONG */
/*
* Multiply two words (a * b) producing a double word result (h:l).
*
* This can be rewritten as:
*
* a * b = (hi32(a) * 2^32 + lo32(a)) * (hi32(b) * 2^32 + lo32(b))
* = hi32(a) * hi32(b) * 2^64 +
* hi32(a) * lo32(b) * 2^32 +
* hi32(b) * lo32(a) * 2^32 +
* lo32(a) * lo32(b)
*
* The multiplication for each part of a and b can be calculated for each of
* these four terms without overflowing a BN_ULONG, as the maximum value of a
* 32 bit x 32 bit multiplication is 32 + 32 = 64 bits. Once these
* multiplications have been performed the result can be partitioned and summed
* into a double word (h:l). The same applies on a 32 bit system, substituting
* 16 for 32 and 32 for 64.
*/
#if 1
static inline void
bn_mulw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
{
BN_ULONG a1, a0, b1, b0, r1, r0;
BN_ULONG carry, x;
a1 = a >> BN_BITS4;
a0 = a & BN_MASK2l;
b1 = b >> BN_BITS4;
b0 = b & BN_MASK2l;
r1 = a1 * b1;
r0 = a0 * b0;
/* (a1 * b0) << BN_BITS4, partition the result across r1:r0 with carry. */
x = a1 * b0;
r1 += x >> BN_BITS4;
bn_addw(r0, x << BN_BITS4, &carry, &r0);
r1 += carry;
/* (b1 * a0) << BN_BITS4, partition the result across r1:r0 with carry. */
x = b1 * a0;
r1 += x >> BN_BITS4;
bn_addw(r0, x << BN_BITS4, &carry, &r0);
r1 += carry;
*out_r1 = r1;
*out_r0 = r0;
}
#else
/*
* XXX - this accumulator based version uses fewer instructions, however
* requires more variables/registers. It seems to be slower on at least amd64
* and i386, however may be faster on other architectures that have more
* registers available. Further testing is required and one of the two
* implementations should eventually be removed.
*/
static inline void
bn_mulw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
{
BN_ULONG a1, a0, b1, b0, r1, r0, x;
BN_ULONG acc0, acc1, acc2, acc3;
a1 = a >> BN_BITS4;
b1 = b >> BN_BITS4;
a0 = a & BN_MASK2l;
b0 = b & BN_MASK2l;
r1 = a1 * b1;
r0 = a0 * b0;
acc0 = r0 & BN_MASK2l;
acc1 = r0 >> BN_BITS4;
acc2 = r1 & BN_MASK2l;
acc3 = r1 >> BN_BITS4;
/* (a1 * b0) << BN_BITS4, partition the result across r1:r0. */
x = a1 * b0;
acc1 += x & BN_MASK2l;
acc2 += (acc1 >> BN_BITS4) + (x >> BN_BITS4);
acc1 &= BN_MASK2l;
acc3 += acc2 >> BN_BITS4;
acc2 &= BN_MASK2l;
/* (b1 * a0) << BN_BITS4, partition the result across r1:r0. */
x = b1 * a0;
acc1 += x & BN_MASK2l;
acc2 += (acc1 >> BN_BITS4) + (x >> BN_BITS4);
acc1 &= BN_MASK2l;
acc3 += acc2 >> BN_BITS4;
acc2 &= BN_MASK2l;
*out_r1 = (acc3 << BN_BITS4) | acc2;
*out_r0 = (acc1 << BN_BITS4) | acc0;
}
#endif
#endif /* !BN_LLONG */
#endif
#ifndef HAVE_BN_MULW_LO
static inline BN_ULONG
bn_mulw_lo(BN_ULONG a, BN_ULONG b)
{
return a * b;
}
#endif
#ifndef HAVE_BN_MULW_HI
static inline BN_ULONG
bn_mulw_hi(BN_ULONG a, BN_ULONG b)
{
BN_ULONG h, l;
bn_mulw(a, b, &h, &l);
return h;
}
#endif
/*
* bn_mulw_addw() computes (r1:r0) = a * b + c with all inputs being single
* words, producing a double word result.
*/
#ifndef HAVE_BN_MULW_ADDW
static inline void
bn_mulw_addw(BN_ULONG a, BN_ULONG b, BN_ULONG c, BN_ULONG *out_r1,
BN_ULONG *out_r0)
{
BN_ULONG carry, r1, r0;
bn_mulw(a, b, &r1, &r0);
bn_addw(r0, c, &carry, &r0);
r1 += carry;
*out_r1 = r1;
*out_r0 = r0;
}
#endif
/*
* bn_mulw_addw_addw() computes (r1:r0) = a * b + c + d with all inputs being
* single words, producing a double word result.
*/
#ifndef HAVE_BN_MULW_ADDW_ADDW
static inline void
bn_mulw_addw_addw(BN_ULONG a, BN_ULONG b, BN_ULONG c, BN_ULONG d,
BN_ULONG *out_r1, BN_ULONG *out_r0)
{
BN_ULONG carry, r1, r0;
bn_mulw_addw(a, b, c, &r1, &r0);
bn_addw(r0, d, &carry, &r0);
r1 += carry;
*out_r1 = r1;
*out_r0 = r0;
}
#endif
/*
* bn_mulw_addtw() computes (r2:r1:r0) = a * b + (c2:c1:c0), where a and b are
* single words and (c2:c1:c0) is a triple word, producing a triple word result.
* The caller must ensure that the inputs provided do not result in c2
* overflowing.
*/
#ifndef HAVE_BN_MULW_ADDTW
static inline void
bn_mulw_addtw(BN_ULONG a, BN_ULONG b, BN_ULONG c2, BN_ULONG c1, BN_ULONG c0,
BN_ULONG *out_r2, BN_ULONG *out_r1, BN_ULONG *out_r0)
{
BN_ULONG carry, r2, r1, r0, x1;
bn_mulw_addw(a, b, c0, &x1, &r0);
bn_addw(c1, x1, &carry, &r1);
r2 = c2 + carry;
*out_r2 = r2;
*out_r1 = r1;
*out_r0 = r0;
}
#endif
/*
* bn_mul2_mulw_addtw() computes (r2:r1:r0) = 2 * a * b + (c2:c1:c0), where a
* and b are single words and (c2:c1:c0) is a triple word, producing a triple
* word result. The caller must ensure that the inputs provided do not result
* in c2 overflowing.
*/
#ifndef HAVE_BN_MUL2_MULW_ADDTW
static inline void
bn_mul2_mulw_addtw(BN_ULONG a, BN_ULONG b, BN_ULONG c2, BN_ULONG c1, BN_ULONG c0,
BN_ULONG *out_r2, BN_ULONG *out_r1, BN_ULONG *out_r0)
{
BN_ULONG r2, r1, r0, x1, x0;
BN_ULONG carry;
bn_mulw(a, b, &x1, &x0);
bn_addw(c0, x0, &carry, &r0);
bn_addw(c1, x1 + carry, &r2, &r1);
bn_addw(c2, r2, &carry, &r2);
bn_addw(r0, x0, &carry, &r0);
bn_addw(r1, x1 + carry, &carry, &r1);
r2 += carry;
*out_r2 = r2;
*out_r1 = r1;
*out_r0 = r0;
}
#endif
#endif

236
externals/libressl/crypto/bn/bn_isqrt.c vendored Normal file
View File

@@ -0,0 +1,236 @@
/* $OpenBSD: bn_isqrt.c,v 1.9 2023/05/19 00:54:28 deraadt Exp $ */
/*
* Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stddef.h>
#include <stdint.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include "bn_local.h"
#define CTASSERT(x) extern char _ctassert[(x) ? 1 : -1 ] \
__attribute__((__unused__))
/*
* Calculate integer square root of |n| using a variant of Newton's method.
*
* Returns the integer square root of |n| in the caller-provided |out_sqrt|;
* |*out_perfect| is set to 1 if and only if |n| is a perfect square.
* One of |out_sqrt| and |out_perfect| can be NULL; |in_ctx| can be NULL.
*
* Returns 0 on error, 1 on success.
*
* Adapted from pure Python describing cpython's math.isqrt(), without bothering
* with any of the optimizations in the C code. A correctness proof is here:
* https://github.com/mdickinson/snippets/blob/master/proofs/isqrt/src/isqrt.lean
* The comments in the Python code also give a rather detailed proof.
*/
int
bn_isqrt(BIGNUM *out_sqrt, int *out_perfect, const BIGNUM *n, BN_CTX *in_ctx)
{
BN_CTX *ctx = NULL;
BIGNUM *a, *b;
int c, d, e, s;
int cmp, perfect;
int ret = 0;
if (out_perfect == NULL && out_sqrt == NULL) {
BNerror(ERR_R_PASSED_NULL_PARAMETER);
goto err;
}
if (BN_is_negative(n)) {
BNerror(BN_R_INVALID_RANGE);
goto err;
}
if ((ctx = in_ctx) == NULL)
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
BN_CTX_start(ctx);
if ((a = BN_CTX_get(ctx)) == NULL)
goto err;
if ((b = BN_CTX_get(ctx)) == NULL)
goto err;
if (BN_is_zero(n)) {
perfect = 1;
BN_zero(a);
goto done;
}
if (!BN_one(a))
goto err;
c = (BN_num_bits(n) - 1) / 2;
d = 0;
/* Calculate s = floor(log(c)). */
if (!BN_set_word(b, c))
goto err;
s = BN_num_bits(b) - 1;
/*
* By definition, the loop below is run <= floor(log(log(n))) times.
* Comments in the cpython code establish the loop invariant that
*
* (a - 1)^2 < n / 4^(c - d) < (a + 1)^2
*
* holds true in every iteration. Once this is proved via induction,
* correctness of the algorithm is easy.
*
* Roughly speaking, A = (a << (d - e)) is used for one Newton step
* "a = (A >> 1) + (m >> 1) / A" approximating m = (n >> 2 * (c - d)).
*/
for (; s >= 0; s--) {
e = d;
d = c >> s;
if (!BN_rshift(b, n, 2 * c - d - e + 1))
goto err;
if (!BN_div_ct(b, NULL, b, a, ctx))
goto err;
if (!BN_lshift(a, a, d - e - 1))
goto err;
if (!BN_add(a, a, b))
goto err;
}
/*
* The loop invariant implies that either a or a - 1 is isqrt(n).
* Figure out which one it is. The invariant also implies that for
* a perfect square n, a must be the square root.
*/
if (!BN_sqr(b, a, ctx))
goto err;
/* If a^2 > n, we must have isqrt(n) == a - 1. */
if ((cmp = BN_cmp(b, n)) > 0) {
if (!BN_sub_word(a, 1))
goto err;
}
perfect = cmp == 0;
done:
if (out_perfect != NULL)
*out_perfect = perfect;
if (out_sqrt != NULL) {
if (!bn_copy(out_sqrt, a))
goto err;
}
ret = 1;
err:
BN_CTX_end(ctx);
if (ctx != in_ctx)
BN_CTX_free(ctx);
return ret;
}
/*
* is_square_mod_N[r % N] indicates whether r % N has a square root modulo N.
* The tables are generated in regress/lib/libcrypto/bn/bn_isqrt.c.
*/
const uint8_t is_square_mod_11[] = {
1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
};
CTASSERT(sizeof(is_square_mod_11) == 11);
const uint8_t is_square_mod_63[] = {
1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0,
1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
};
CTASSERT(sizeof(is_square_mod_63) == 63);
const uint8_t is_square_mod_64[] = {
1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
};
CTASSERT(sizeof(is_square_mod_64) == 64);
const uint8_t is_square_mod_65[] = {
1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0,
0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0,
1,
};
CTASSERT(sizeof(is_square_mod_65) == 65);
/*
* Determine whether n is a perfect square or not.
*
* Returns 1 on success and 0 on error. In case of success, |*out_perfect| is
* set to 1 if and only if |n| is a perfect square.
*/
int
bn_is_perfect_square(int *out_perfect, const BIGNUM *n, BN_CTX *ctx)
{
BN_ULONG r;
*out_perfect = 0;
if (BN_is_negative(n))
return 1;
/*
* Before performing an expensive bn_isqrt() operation, weed out many
* obvious non-squares. See H. Cohen, "A course in computational
* algebraic number theory", Algorithm 1.7.3.
*
* The idea is that a square remains a square when reduced modulo any
* number. The moduli are chosen in such a way that a non-square has
* probability < 1% of passing the four table lookups.
*/
/* n % 64 */
r = BN_lsw(n) & 0x3f;
if (!is_square_mod_64[r % 64])
return 1;
if ((r = BN_mod_word(n, 11 * 63 * 65)) == (BN_ULONG)-1)
return 0;
if (!is_square_mod_63[r % 63] ||
!is_square_mod_65[r % 65] ||
!is_square_mod_11[r % 11])
return 1;
return bn_isqrt(NULL, out_perfect, n, ctx);
}

194
externals/libressl/crypto/bn/bn_kron.c vendored Normal file
View File

@@ -0,0 +1,194 @@
/* $OpenBSD: bn_kron.c,v 1.14 2023/03/27 10:21:23 tb Exp $ */
/* ====================================================================
* Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include "bn_local.h"
/*
* Kronecker symbol, implemented according to Henri Cohen, "A Course in
* Computational Algebraic Number Theory", Algorithm 1.4.10.
*
* Returns -1, 0, or 1 on success and -2 on error.
*/
int
BN_kronecker(const BIGNUM *A, const BIGNUM *B, BN_CTX *ctx)
{
/* tab[BN_lsw(n) & 7] = (-1)^((n^2 - 1)) / 8) for odd values of n. */
static const int tab[8] = {0, 1, 0, -1, 0, -1, 0, 1};
BIGNUM *a, *b, *tmp;
int k, v;
int ret = -2;
BN_CTX_start(ctx);
if ((a = BN_CTX_get(ctx)) == NULL)
goto end;
if ((b = BN_CTX_get(ctx)) == NULL)
goto end;
if (!bn_copy(a, A))
goto end;
if (!bn_copy(b, B))
goto end;
/*
* Cohen's step 1:
*/
/* If b is zero, output 1 if |a| is 1, otherwise output 0. */
if (BN_is_zero(b)) {
ret = BN_abs_is_word(a, 1);
goto end;
}
/*
* Cohen's step 2:
*/
/* If both are even, they have a factor in common, so output 0. */
if (!BN_is_odd(a) && !BN_is_odd(b)) {
ret = 0;
goto end;
}
/* Factorize b = 2^v * u with odd u and replace b with u. */
v = 0;
while (!BN_is_bit_set(b, v))
v++;
if (!BN_rshift(b, b, v))
goto end;
/* If v is even set k = 1, otherwise set it to (-1)^((a^2 - 1) / 8). */
k = 1;
if (v % 2 != 0)
k = tab[BN_lsw(a) & 7];
/*
* If b is negative, replace it with -b and if a is also negative
* replace k with -k.
*/
if (BN_is_negative(b)) {
BN_set_negative(b, 0);
if (BN_is_negative(a))
k = -k;
}
/*
* Now b is positive and odd, so compute the Jacobi symbol (a/b)
* and multiply it by k.
*/
while (1) {
/*
* Cohen's step 3:
*/
/* b is positive and odd. */
/* If a is zero output k if b is one, otherwise output 0. */
if (BN_is_zero(a)) {
ret = BN_is_one(b) ? k : 0;
goto end;
}
/* Factorize a = 2^v * u with odd u and replace a with u. */
v = 0;
while (!BN_is_bit_set(a, v))
v++;
if (!BN_rshift(a, a, v))
goto end;
/* If v is odd, multiply k with (-1)^((b^2 - 1) / 8). */
if (v % 2 != 0)
k *= tab[BN_lsw(b) & 7];
/*
* Cohen's step 4:
*/
/*
* Apply the reciprocity law: multiply k by (-1)^((a-1)(b-1)/4).
*
* This expression is -1 if and only if a and b are 3 (mod 4).
* In turn, this is the case if and only if their two's
* complement representations have the second bit set.
* a could be negative in the first iteration, b is positive.
*/
if ((BN_is_negative(a) ? ~BN_lsw(a) : BN_lsw(a)) & BN_lsw(b) & 2)
k = -k;
/*
* (a, b) := (b mod |a|, |a|)
*
* Once this is done, we know that 0 < a < b at the start of the
* loop. Since b is strictly decreasing, the loop terminates.
*/
if (!BN_nnmod(b, b, a, ctx))
goto end;
tmp = a;
a = b;
b = tmp;
BN_set_negative(b, 0);
}
end:
BN_CTX_end(ctx);
return ret;
}

743
externals/libressl/crypto/bn/bn_lib.c vendored Normal file
View File

@@ -0,0 +1,743 @@
/* $OpenBSD: bn_lib.c,v 1.86 2023/04/30 19:15:48 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <openssl/opensslconf.h>
#include <openssl/err.h>
#include "bn_local.h"
#include "bn_internal.h"
BIGNUM *
BN_new(void)
{
BIGNUM *bn;
if ((bn = calloc(1, sizeof(BIGNUM))) == NULL) {
BNerror(ERR_R_MALLOC_FAILURE);
return NULL;
}
bn->flags = BN_FLG_MALLOCED;
return bn;
}
void
BN_init(BIGNUM *a)
{
memset(a, 0, sizeof(BIGNUM));
}
void
BN_clear(BIGNUM *a)
{
if (a->d != NULL)
explicit_bzero(a->d, a->dmax * sizeof(a->d[0]));
a->top = 0;
a->neg = 0;
}
void
BN_free(BIGNUM *bn)
{
if (bn == NULL)
return;
if (!BN_get_flags(bn, BN_FLG_STATIC_DATA))
freezero(bn->d, bn->dmax * sizeof(bn->d[0]));
if (!BN_get_flags(bn, BN_FLG_MALLOCED)) {
explicit_bzero(bn, sizeof(*bn));
return;
}
freezero(bn, sizeof(*bn));
}
void
BN_clear_free(BIGNUM *bn)
{
BN_free(bn);
}
void
BN_set_flags(BIGNUM *b, int n)
{
b->flags |= n;
}
int
BN_get_flags(const BIGNUM *b, int n)
{
return b->flags & n;
}
void
BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags)
{
int dest_flags;
dest_flags = (dest->flags & BN_FLG_MALLOCED) |
(b->flags & ~BN_FLG_MALLOCED) | BN_FLG_STATIC_DATA | flags;
*dest = *b;
dest->flags = dest_flags;
}
static const BN_ULONG bn_value_one_data = 1;
static const BIGNUM bn_value_one = {
.d = (BN_ULONG *)&bn_value_one_data,
.top = 1,
.dmax = 1,
.neg = 0,
.flags = BN_FLG_STATIC_DATA,
};
const BIGNUM *
BN_value_one(void)
{
return &bn_value_one;
}
#ifndef HAVE_BN_WORD_CLZ
int
bn_word_clz(BN_ULONG w)
{
BN_ULONG bits, mask, shift;
bits = shift = BN_BITS2;
mask = 0;
while ((shift >>= 1) != 0) {
bits += (shift & mask) - (shift & ~mask);
mask = bn_ct_ne_zero_mask(w >> bits);
}
bits += 1 & mask;
bits -= bn_ct_eq_zero(w);
return BN_BITS2 - bits;
}
#endif
int
BN_num_bits_word(BN_ULONG w)
{
return BN_BITS2 - bn_word_clz(w);
}
int
BN_num_bits(const BIGNUM *a)
{
int i = a->top - 1;
if (BN_is_zero(a))
return 0;
return ((i * BN_BITS2) + BN_num_bits_word(a->d[i]));
}
void
bn_correct_top(BIGNUM *a)
{
while (a->top > 0 && a->d[a->top - 1] == 0)
a->top--;
}
static int
bn_expand_internal(BIGNUM *bn, int words)
{
BN_ULONG *d;
if (words < 0) {
BNerror(BN_R_BIGNUM_TOO_LONG); // XXX
return 0;
}
if (words > INT_MAX / (4 * BN_BITS2)) {
BNerror(BN_R_BIGNUM_TOO_LONG);
return 0;
}
if (BN_get_flags(bn, BN_FLG_STATIC_DATA)) {
BNerror(BN_R_EXPAND_ON_STATIC_BIGNUM_DATA);
return 0;
}
d = recallocarray(bn->d, bn->dmax, words, sizeof(BN_ULONG));
if (d == NULL) {
BNerror(ERR_R_MALLOC_FAILURE);
return 0;
}
bn->d = d;
bn->dmax = words;
return 1;
}
int
bn_expand(BIGNUM *bn, int bits)
{
int words;
if (bits < 0)
return 0;
if (bits > (INT_MAX - BN_BITS2 + 1))
return 0;
words = (bits + BN_BITS2 - 1) / BN_BITS2;
return bn_wexpand(bn, words);
}
int
bn_wexpand(BIGNUM *bn, int words)
{
if (words < 0)
return 0;
if (words <= bn->dmax)
return 1;
return bn_expand_internal(bn, words);
}
BIGNUM *
BN_dup(const BIGNUM *a)
{
BIGNUM *t;
if (a == NULL)
return NULL;
t = BN_new();
if (t == NULL)
return NULL;
if (!bn_copy(t, a)) {
BN_free(t);
return NULL;
}
return t;
}
static inline void
bn_copy_words(BN_ULONG *ap, const BN_ULONG *bp, int n)
{
while (n > 0) {
ap[0] = bp[0];
ap++;
bp++;
n--;
}
}
BIGNUM *
BN_copy(BIGNUM *a, const BIGNUM *b)
{
if (a == b)
return (a);
if (!bn_wexpand(a, b->top))
return (NULL);
bn_copy_words(a->d, b->d, b->top);
/* Copy constant time flag from b, but make it sticky on a. */
a->flags |= b->flags & BN_FLG_CONSTTIME;
a->top = b->top;
a->neg = b->neg;
return (a);
}
int
bn_copy(BIGNUM *dst, const BIGNUM *src)
{
return BN_copy(dst, src) != NULL;
}
void
BN_swap(BIGNUM *a, BIGNUM *b)
{
int flags_old_a, flags_old_b;
BN_ULONG *tmp_d;
int tmp_top, tmp_dmax, tmp_neg;
flags_old_a = a->flags;
flags_old_b = b->flags;
tmp_d = a->d;
tmp_top = a->top;
tmp_dmax = a->dmax;
tmp_neg = a->neg;
a->d = b->d;
a->top = b->top;
a->dmax = b->dmax;
a->neg = b->neg;
b->d = tmp_d;
b->top = tmp_top;
b->dmax = tmp_dmax;
b->neg = tmp_neg;
a->flags = (flags_old_a & BN_FLG_MALLOCED) |
(flags_old_b & BN_FLG_STATIC_DATA);
b->flags = (flags_old_b & BN_FLG_MALLOCED) |
(flags_old_a & BN_FLG_STATIC_DATA);
}
BN_ULONG
BN_get_word(const BIGNUM *a)
{
if (a->top > 1)
return BN_MASK2;
else if (a->top == 1)
return a->d[0];
/* a->top == 0 */
return 0;
}
int
BN_set_word(BIGNUM *a, BN_ULONG w)
{
if (!bn_wexpand(a, 1))
return (0);
a->neg = 0;
a->d[0] = w;
a->top = (w ? 1 : 0);
return (1);
}
int
BN_ucmp(const BIGNUM *a, const BIGNUM *b)
{
int i;
if (a->top < b->top)
return -1;
if (a->top > b->top)
return 1;
for (i = a->top - 1; i >= 0; i--) {
if (a->d[i] != b->d[i])
return (a->d[i] > b->d[i] ? 1 : -1);
}
return 0;
}
int
BN_cmp(const BIGNUM *a, const BIGNUM *b)
{
if (a == NULL || b == NULL) {
if (a != NULL)
return -1;
if (b != NULL)
return 1;
return 0;
}
if (a->neg != b->neg)
return b->neg - a->neg;
if (a->neg)
return BN_ucmp(b, a);
return BN_ucmp(a, b);
}
int
BN_set_bit(BIGNUM *a, int n)
{
int i, j, k;
if (n < 0)
return 0;
i = n / BN_BITS2;
j = n % BN_BITS2;
if (a->top <= i) {
if (!bn_wexpand(a, i + 1))
return (0);
for (k = a->top; k < i + 1; k++)
a->d[k] = 0;
a->top = i + 1;
}
a->d[i] |= (((BN_ULONG)1) << j);
return (1);
}
int
BN_clear_bit(BIGNUM *a, int n)
{
int i, j;
if (n < 0)
return 0;
i = n / BN_BITS2;
j = n % BN_BITS2;
if (a->top <= i)
return (0);
a->d[i] &= (~(((BN_ULONG)1) << j));
bn_correct_top(a);
return (1);
}
int
BN_is_bit_set(const BIGNUM *a, int n)
{
int i, j;
if (n < 0)
return 0;
i = n / BN_BITS2;
j = n % BN_BITS2;
if (a->top <= i)
return 0;
return (int)(((a->d[i]) >> j) & ((BN_ULONG)1));
}
int
BN_mask_bits(BIGNUM *a, int n)
{
int b, w;
if (n < 0)
return 0;
w = n / BN_BITS2;
b = n % BN_BITS2;
if (w >= a->top)
return 0;
if (b == 0)
a->top = w;
else {
a->top = w + 1;
a->d[w] &= ~(BN_MASK2 << b);
}
bn_correct_top(a);
return (1);
}
void
BN_set_negative(BIGNUM *bn, int neg)
{
bn->neg = ~BN_is_zero(bn) & bn_ct_ne_zero(neg);
}
/*
* Constant-time conditional swap of a and b.
* a and b are swapped if condition is not 0.
* The code assumes that at most one bit of condition is set.
* nwords is the number of words to swap.
* The code assumes that at least nwords are allocated in both a and b,
* and that no more than nwords are used by either a or b.
* a and b cannot be the same number
*/
void
BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords)
{
BN_ULONG t;
int i;
assert(a != b);
assert((condition & (condition - 1)) == 0);
assert(sizeof(BN_ULONG) >= sizeof(int));
condition = ((condition - 1) >> (BN_BITS2 - 1)) - 1;
t = (a->top^b->top) & condition;
a->top ^= t;
b->top ^= t;
#define BN_CONSTTIME_SWAP(ind) \
do { \
t = (a->d[ind] ^ b->d[ind]) & condition; \
a->d[ind] ^= t; \
b->d[ind] ^= t; \
} while (0)
switch (nwords) {
default:
for (i = 10; i < nwords; i++)
BN_CONSTTIME_SWAP(i);
/* Fallthrough */
case 10: BN_CONSTTIME_SWAP(9); /* Fallthrough */
case 9: BN_CONSTTIME_SWAP(8); /* Fallthrough */
case 8: BN_CONSTTIME_SWAP(7); /* Fallthrough */
case 7: BN_CONSTTIME_SWAP(6); /* Fallthrough */
case 6: BN_CONSTTIME_SWAP(5); /* Fallthrough */
case 5: BN_CONSTTIME_SWAP(4); /* Fallthrough */
case 4: BN_CONSTTIME_SWAP(3); /* Fallthrough */
case 3: BN_CONSTTIME_SWAP(2); /* Fallthrough */
case 2: BN_CONSTTIME_SWAP(1); /* Fallthrough */
case 1:
BN_CONSTTIME_SWAP(0);
}
#undef BN_CONSTTIME_SWAP
}
/*
* Constant-time conditional swap of a and b.
* a and b are swapped if condition is not 0.
* nwords is the number of words to swap.
*/
int
BN_swap_ct(BN_ULONG condition, BIGNUM *a, BIGNUM *b, size_t nwords)
{
BN_ULONG t;
int i, words;
if (a == b)
return 1;
if (nwords > INT_MAX)
return 0;
words = (int)nwords;
if (!bn_wexpand(a, words) || !bn_wexpand(b, words))
return 0;
if (a->top > words || b->top > words) {
BNerror(BN_R_INVALID_LENGTH);
return 0;
}
/* Set condition to 0 (if it was zero) or all 1s otherwise. */
condition = ((~condition & (condition - 1)) >> (BN_BITS2 - 1)) - 1;
/* swap top field */
t = (a->top ^ b->top) & condition;
a->top ^= t;
b->top ^= t;
/* swap neg field */
t = (a->neg ^ b->neg) & condition;
a->neg ^= t;
b->neg ^= t;
/* swap BN_FLG_CONSTTIME from flag field */
t = ((a->flags ^ b->flags) & BN_FLG_CONSTTIME) & condition;
a->flags ^= t;
b->flags ^= t;
/* swap the data */
for (i = 0; i < words; i++) {
t = (a->d[i] ^ b->d[i]) & condition;
a->d[i] ^= t;
b->d[i] ^= t;
}
return 1;
}
void
BN_zero(BIGNUM *a)
{
a->neg = 0;
a->top = 0;
}
int
BN_one(BIGNUM *a)
{
return BN_set_word(a, 1);
}
int
BN_abs_is_word(const BIGNUM *a, const BN_ULONG w)
{
return (a->top == 1 && a->d[0] == w) || (w == 0 && a->top == 0);
}
int
BN_is_zero(const BIGNUM *bn)
{
BN_ULONG bits = 0;
int i;
for (i = 0; i < bn->top; i++)
bits |= bn->d[i];
return bits == 0;
}
int
BN_is_one(const BIGNUM *a)
{
return BN_abs_is_word(a, 1) && !a->neg;
}
int
BN_is_word(const BIGNUM *a, const BN_ULONG w)
{
return BN_abs_is_word(a, w) && (w == 0 || !a->neg);
}
int
BN_is_odd(const BIGNUM *a)
{
return a->top > 0 && (a->d[0] & 1);
}
int
BN_is_negative(const BIGNUM *a)
{
return a->neg != 0;
}
char *
BN_options(void)
{
static int init = 0;
static char data[16];
if (!init) {
init++;
#ifdef BN_LLONG
snprintf(data,sizeof data, "bn(%d,%d)",
(int)sizeof(BN_ULLONG) * 8, (int)sizeof(BN_ULONG) * 8);
#else
snprintf(data,sizeof data, "bn(%d,%d)",
(int)sizeof(BN_ULONG) * 8, (int)sizeof(BN_ULONG) * 8);
#endif
}
return (data);
}
/*
* Bits of security, see SP800-57, section 5.6.11, table 2.
*/
int
BN_security_bits(int L, int N)
{
int secbits, bits;
if (L >= 15360)
secbits = 256;
else if (L >= 7680)
secbits = 192;
else if (L >= 3072)
secbits = 128;
else if (L >= 2048)
secbits = 112;
else if (L >= 1024)
secbits = 80;
else
return 0;
if (N == -1)
return secbits;
bits = N / 2;
if (bits < 80)
return 0;
return bits >= secbits ? secbits : bits;
}
BN_GENCB *
BN_GENCB_new(void)
{
BN_GENCB *cb;
if ((cb = calloc(1, sizeof(*cb))) == NULL)
return NULL;
return cb;
}
void
BN_GENCB_free(BN_GENCB *cb)
{
if (cb == NULL)
return;
free(cb);
}
/* Populate a BN_GENCB structure with an "old"-style callback */
void
BN_GENCB_set_old(BN_GENCB *gencb, void (*cb)(int, int, void *), void *cb_arg)
{
gencb->ver = 1;
gencb->cb.cb_1 = cb;
gencb->arg = cb_arg;
}
/* Populate a BN_GENCB structure with a "new"-style callback */
void
BN_GENCB_set(BN_GENCB *gencb, int (*cb)(int, int, BN_GENCB *), void *cb_arg)
{
gencb->ver = 2;
gencb->cb.cb_2 = cb;
gencb->arg = cb_arg;
}
void *
BN_GENCB_get_arg(BN_GENCB *cb)
{
return cb->arg;
}

330
externals/libressl/crypto/bn/bn_local.h vendored Normal file
View File

@@ -0,0 +1,330 @@
/* $OpenBSD: bn_local.h,v 1.22 2023/05/10 12:21:55 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
/* ====================================================================
* Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#ifndef HEADER_BN_LOCAL_H
#define HEADER_BN_LOCAL_H
#include <openssl/opensslconf.h>
#include <openssl/bn.h>
__BEGIN_HIDDEN_DECLS
struct bignum_st {
BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks. */
int top; /* Index of last used d +1. */
/* The next are internal book keeping for bn_expand. */
int dmax; /* Size of the d array. */
int neg; /* one if the number is negative */
int flags;
};
struct bn_mont_ctx_st {
int ri; /* Number of bits in R */
BIGNUM RR; /* Used to convert to Montgomery form */
BIGNUM N; /* Modulus */
/* Least significant word(s) of Ni; R*(1/R mod N) - N*Ni = 1 */
BN_ULONG n0[2];
int flags;
};
/* Used for reciprocal division/mod functions
* It cannot be shared between threads
*/
typedef struct bn_recp_ctx_st {
BIGNUM N; /* the divisor */
BIGNUM Nr; /* the reciprocal */
int num_bits;
int shift;
int flags;
} BN_RECP_CTX;
/* Used for slow "generation" functions. */
struct bn_gencb_st {
unsigned int ver; /* To handle binary (in)compatibility */
void *arg; /* callback-specific data */
union {
/* if(ver==1) - handles old style callbacks */
void (*cb_1)(int, int, void *);
/* if(ver==2) - new callback style */
int (*cb_2)(int, int, BN_GENCB *);
} cb;
};
/*
* BN_window_bits_for_exponent_size -- macro for sliding window mod_exp functions
*
*
* For window size 'w' (w >= 2) and a random 'b' bits exponent,
* the number of multiplications is a constant plus on average
*
* 2^(w-1) + (b-w)/(w+1);
*
* here 2^(w-1) is for precomputing the table (we actually need
* entries only for windows that have the lowest bit set), and
* (b-w)/(w+1) is an approximation for the expected number of
* w-bit windows, not counting the first one.
*
* Thus we should use
*
* w >= 6 if b > 671
* w = 5 if 671 > b > 239
* w = 4 if 239 > b > 79
* w = 3 if 79 > b > 23
* w <= 2 if 23 > b
*
* (with draws in between). Very small exponents are often selected
* with low Hamming weight, so we use w = 1 for b <= 23.
*/
#define BN_window_bits_for_exponent_size(b) \
((b) > 671 ? 6 : \
(b) > 239 ? 5 : \
(b) > 79 ? 4 : \
(b) > 23 ? 3 : 1)
/* BN_mod_exp_mont_consttime is based on the assumption that the
* L1 data cache line width of the target processor is at least
* the following value.
*/
#define MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH ( 64 )
#define MOD_EXP_CTIME_MIN_CACHE_LINE_MASK (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - 1)
/* Window sizes optimized for fixed window size modular exponentiation
* algorithm (BN_mod_exp_mont_consttime).
*
* To achieve the security goals of BN_mode_exp_mont_consttime, the
* maximum size of the window must not exceed
* log_2(MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH).
*
* Window size thresholds are defined for cache line sizes of 32 and 64,
* cache line sizes where log_2(32)=5 and log_2(64)=6 respectively. A
* window size of 7 should only be used on processors that have a 128
* byte or greater cache line size.
*/
#if MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 64
# define BN_window_bits_for_ctime_exponent_size(b) \
((b) > 937 ? 6 : \
(b) > 306 ? 5 : \
(b) > 89 ? 4 : \
(b) > 22 ? 3 : 1)
# define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE (6)
#elif MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 32
# define BN_window_bits_for_ctime_exponent_size(b) \
((b) > 306 ? 5 : \
(b) > 89 ? 4 : \
(b) > 22 ? 3 : 1)
# define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE (5)
#endif
/* Pentium pro 16,16,16,32,64 */
/* Alpha 16,16,16,16.64 */
#define BN_MULL_SIZE_NORMAL (16) /* 32 */
#define BN_MUL_RECURSIVE_SIZE_NORMAL (16) /* 32 less than */
#define BN_SQR_RECURSIVE_SIZE_NORMAL (16) /* 32 */
#define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL (32) /* 32 */
#define BN_MONT_CTX_SET_SIZE_WORD (64) /* 32 */
/* The least significant word of a BIGNUM. */
#define BN_lsw(n) (((n)->top == 0) ? (BN_ULONG) 0 : (n)->d[0])
BN_ULONG bn_add(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len,
const BN_ULONG *b, int b_len);
BN_ULONG bn_sub(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len,
const BN_ULONG *b, int b_len);
void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb);
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b);
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b);
void bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, int n, BN_ULONG *tmp);
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a);
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a);
int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
const BN_ULONG *np, const BN_ULONG *n0, int num);
int bn_word_clz(BN_ULONG w);
void bn_correct_top(BIGNUM *a);
int bn_expand(BIGNUM *a, int bits);
int bn_wexpand(BIGNUM *a, int words);
BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
int num);
BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
int num);
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
void bn_div_rem_words(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
BN_ULONG *out_r);
int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom);
int bn_rand_interval(BIGNUM *rnd, const BIGNUM *lower_inc, const BIGNUM *upper_exc);
void BN_init(BIGNUM *);
int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx);
void BN_RECP_CTX_init(BN_RECP_CTX *recp);
BN_RECP_CTX *BN_RECP_CTX_new(void);
void BN_RECP_CTX_free(BN_RECP_CTX *recp);
int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *rdiv, BN_CTX *ctx);
int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y,
BN_RECP_CTX *recp, BN_CTX *ctx);
int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx);
int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,
BN_RECP_CTX *recp, BN_CTX *ctx);
/* Explicitly const time / non-const time versions for internal use */
int BN_mod_exp_ct(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx);
int BN_mod_exp_nonct(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx);
int BN_mod_exp_mont_ct(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
int BN_mod_exp_mont_nonct(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
int BN_div_nonct(BIGNUM *q, BIGNUM *r, const BIGNUM *n, const BIGNUM *d,
BN_CTX *ctx);
int BN_div_ct(BIGNUM *q, BIGNUM *r, const BIGNUM *n, const BIGNUM *d,
BN_CTX *ctx);
int BN_mod_ct(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
int BN_mod_nonct(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
BIGNUM *BN_mod_inverse_ct(BIGNUM *ret, const BIGNUM *a, const BIGNUM *n,
BN_CTX *ctx);
BIGNUM *BN_mod_inverse_nonct(BIGNUM *ret, const BIGNUM *a, const BIGNUM *n,
BN_CTX *ctx);
int BN_gcd_ct(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
int BN_gcd_nonct(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
int BN_swap_ct(BN_ULONG swap, BIGNUM *a, BIGNUM *b, size_t nwords);
int bn_copy(BIGNUM *dst, const BIGNUM *src);
int bn_isqrt(BIGNUM *out_sqrt, int *out_perfect, const BIGNUM *n, BN_CTX *ctx);
int bn_is_perfect_square(int *out_perfect, const BIGNUM *n, BN_CTX *ctx);
int bn_is_prime_bpsw(int *is_prime, const BIGNUM *n, BN_CTX *ctx, size_t rounds);
__END_HIDDEN_DECLS
#endif /* !HEADER_BN_LOCAL_H */

315
externals/libressl/crypto/bn/bn_mod.c vendored Normal file
View File

@@ -0,0 +1,315 @@
/* $OpenBSD: bn_mod.c,v 1.20 2023/03/27 10:21:23 tb Exp $ */
/* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
* for the OpenSSL project. */
/* ====================================================================
* Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <openssl/err.h>
#include "bn_local.h"
int
BN_mod_ct(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
{
return BN_div_ct(NULL, r, a, m, ctx);
}
int
BN_mod_nonct(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
{
return BN_div_nonct(NULL, r, a, m, ctx);
}
/*
* BN_nnmod() is like BN_mod(), but always returns a non-negative remainder
* (that is 0 <= r < |m| always holds). If both a and m have the same sign then
* the result is already non-negative. Otherwise, -|m| < r < 0, which needs to
* be adjusted as r := r + |m|. This equates to r := |m| - |r|.
*/
int
BN_nnmod(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
{
if (!BN_mod_ct(r, a, m, ctx))
return 0;
if (BN_is_negative(r))
return BN_usub(r, m, r);
return 1;
}
int
BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
BN_CTX *ctx)
{
if (!BN_add(r, a, b))
return 0;
return BN_nnmod(r, r, m, ctx);
}
/*
* BN_mod_add() variant that may only be used if both a and b are non-negative
* and have already been reduced (less than m).
*/
int
BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m)
{
if (!BN_uadd(r, a, b))
return 0;
if (BN_ucmp(r, m) >= 0)
return BN_usub(r, r, m);
return 1;
}
int
BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
BN_CTX *ctx)
{
if (!BN_sub(r, a, b))
return 0;
return BN_nnmod(r, r, m, ctx);
}
/*
* BN_mod_sub() variant that may only be used if both a and b are non-negative
* and have already been reduced (less than m).
*/
int
BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m)
{
if (BN_ucmp(a, b) >= 0)
return BN_usub(r, a, b);
if (!BN_usub(r, b, a))
return 0;
return BN_usub(r, m, r);
}
int
BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
BN_CTX *ctx)
{
BIGNUM *rr;
int ret = 0;
BN_CTX_start(ctx);
rr = r;
if (rr == a || rr == b)
rr = BN_CTX_get(ctx);
if (rr == NULL)
goto err;
if (a == b) {
if (!BN_sqr(rr, a, ctx))
goto err;
} else {
if (!BN_mul(rr, a, b, ctx))
goto err;
}
if (!BN_nnmod(r, rr, m, ctx))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
int
BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
{
return BN_mod_mul(r, a, a, m, ctx);
}
int
BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
{
if (!BN_lshift1(r, a))
return 0;
return BN_nnmod(r, r, m, ctx);
}
/*
* BN_mod_lshift1() variant that may be used if a is non-negative
* and has already been reduced (less than m).
*/
int
BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m)
{
if (!BN_lshift1(r, a))
return 0;
if (BN_ucmp(r, m) >= 0)
return BN_usub(r, r, m);
return 1;
}
int
BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, BN_CTX *ctx)
{
BIGNUM *abs_m;
int ret = 0;
BN_CTX_start(ctx);
if (!BN_nnmod(r, a, m, ctx))
goto err;
if (BN_is_negative(m)) {
if ((abs_m = BN_CTX_get(ctx)) == NULL)
goto err;
if (!bn_copy(abs_m, m))
goto err;
BN_set_negative(abs_m, 0);
m = abs_m;
}
if (!BN_mod_lshift_quick(r, r, n, m))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*
* BN_mod_lshift() variant that may be used if a is non-negative
* and has already been reduced (less than m).
*/
int
BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m)
{
int max_shift;
if (!bn_copy(r, a))
return 0;
while (n > 0) {
if ((max_shift = BN_num_bits(m) - BN_num_bits(r)) < 0) {
BNerror(BN_R_INPUT_NOT_REDUCED);
return 0;
}
if (max_shift == 0)
max_shift = 1;
if (max_shift > n)
max_shift = n;
if (!BN_lshift(r, r, max_shift))
return 0;
n -= max_shift;
if (BN_ucmp(r, m) >= 0) {
if (!BN_usub(r, r, m))
return 0;
}
}
return 1;
}

View File

@@ -0,0 +1,726 @@
/* $OpenBSD: bn_mod_sqrt.c,v 1.1 2023/04/11 10:08:44 tb Exp $ */
/*
* Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <openssl/err.h>
#include "bn_local.h"
/*
* Tonelli-Shanks according to H. Cohen "A Course in Computational Algebraic
* Number Theory", Section 1.5.1, Springer GTM volume 138, Berlin, 1996.
*
* Under the assumption that p is prime and a is a quadratic residue, we know:
*
* a^[(p-1)/2] = 1 (mod p). (*)
*
* To find a square root of a (mod p), we handle three cases of increasing
* complexity. In the first two cases, we can compute a square root using an
* explicit formula, thus avoiding the probabilistic nature of Tonelli-Shanks.
*
* 1. p = 3 (mod 4).
*
* Set n = (p+1)/4. Then 2n = 1 + (p-1)/2 and (*) shows that x = a^n (mod p)
* is a square root of a: x^2 = a^(2n) = a * a^[(p-1)/2] = a (mod p).
*
* 2. p = 5 (mod 8).
*
* This uses a simplification due to Atkin. By Theorem 1.4.7 and 1.4.9, the
* Kronecker symbol (2/p) evaluates to (-1)^[(p^2-1)/8]. From p = 5 (mod 8)
* we get (p^2-1)/8 = 1 (mod 2), so (2/p) = -1, and thus
*
* 2^[(p-1)/2] = -1 (mod p). (**)
*
* Set b = (2a)^[(p-5)/8]. With (p-1)/2 = 2 + (p-5)/2, (*) and (**) show
*
* i = 2 a b^2 is a square root of -1 (mod p).
*
* Indeed, i^2 = 2^2 a^2 b^4 = 2^[(p-1)/2] a^[(p-1)/2] = -1 (mod p). Because
* of (i-1)^2 = -2i (mod p) and i (-i) = 1 (mod p), a square root of a is
*
* x = a b (i-1)
*
* as x^2 = a^2 b^2 (-2i) = a (2 a b^2) (-i) = a (mod p).
*
* 3. p = 1 (mod 8).
*
* This is the Tonelli-Shanks algorithm. For a prime p, the multiplicative
* group of GF(p) is cyclic of order p - 1 = 2^s q, with odd q. Denote its
* 2-Sylow subgroup by S. It is cyclic of order 2^s. The squares in S have
* order dividing 2^(s-1). They are the even powers of any generator z of S.
* If a is a quadratic residue, 1 = a^[(p-1)/2] = (a^q)^[2^(s-1)], so b = a^q
* is a square in S. Therefore there is an integer k such that b z^(2k) = 1.
* Set x = a^[(q+1)/2] z^k, and find x^2 = a (mod p).
*
* The problem is thus reduced to finding a generator z of the 2-Sylow
* subgroup S of GF(p)* and finding k. An iterative constructions avoids
* the need for an explicit k, a generator is found by a randomized search.
*
* While we do not actually know that p is a prime number, we can still apply
* the formulas in cases 1 and 2 and verify that we have indeed found a square
* root of p. Similarly, in case 3, we can try to find a quadratic non-residue,
* which will fail for example if p is a square. The iterative construction
* may or may not find a candidate square root which we can then validate.
*/
/*
* Handle the cases where p is 2, p isn't odd or p is one. Since BN_mod_sqrt()
* can run on untrusted data, a primality check is too expensive. Also treat
* the obvious cases where a is 0 or 1.
*/
static int
bn_mod_sqrt_trivial_cases(int *done, BIGNUM *out_sqrt, const BIGNUM *a,
const BIGNUM *p, BN_CTX *ctx)
{
*done = 1;
if (BN_abs_is_word(p, 2))
return BN_set_word(out_sqrt, BN_is_odd(a));
if (!BN_is_odd(p) || BN_abs_is_word(p, 1)) {
BNerror(BN_R_P_IS_NOT_PRIME);
return 0;
}
if (BN_is_zero(a) || BN_is_one(a))
return BN_set_word(out_sqrt, BN_is_one(a));
*done = 0;
return 1;
}
/*
* Case 1. We know that (a/p) = 1 and that p = 3 (mod 4).
*/
static int
bn_mod_sqrt_p_is_3_mod_4(BIGNUM *out_sqrt, const BIGNUM *a, const BIGNUM *p,
BN_CTX *ctx)
{
BIGNUM *n;
int ret = 0;
BN_CTX_start(ctx);
if ((n = BN_CTX_get(ctx)) == NULL)
goto err;
/* Calculate n = (|p| + 1) / 4. */
if (!BN_uadd(n, p, BN_value_one()))
goto err;
if (!BN_rshift(n, n, 2))
goto err;
/* By case 1 above, out_sqrt = a^n is a square root of a (mod p). */
if (!BN_mod_exp_ct(out_sqrt, a, n, p, ctx))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Case 2. We know that (a/p) = 1 and that p = 5 (mod 8).
*/
static int
bn_mod_sqrt_p_is_5_mod_8(BIGNUM *out_sqrt, const BIGNUM *a, const BIGNUM *p,
BN_CTX *ctx)
{
BIGNUM *b, *i, *n, *tmp;
int ret = 0;
BN_CTX_start(ctx);
if ((b = BN_CTX_get(ctx)) == NULL)
goto err;
if ((i = BN_CTX_get(ctx)) == NULL)
goto err;
if ((n = BN_CTX_get(ctx)) == NULL)
goto err;
if ((tmp = BN_CTX_get(ctx)) == NULL)
goto err;
/* Calculate n = (|p| - 5) / 8. Since p = 5 (mod 8), simply shift. */
if (!BN_rshift(n, p, 3))
goto err;
BN_set_negative(n, 0);
/* Compute tmp = 2a (mod p) for later use. */
if (!BN_mod_lshift1(tmp, a, p, ctx))
goto err;
/* Calculate b = (2a)^n (mod p). */
if (!BN_mod_exp_ct(b, tmp, n, p, ctx))
goto err;
/* Calculate i = 2 a b^2 (mod p). */
if (!BN_mod_sqr(i, b, p, ctx))
goto err;
if (!BN_mod_mul(i, tmp, i, p, ctx))
goto err;
/* A square root is out_sqrt = a b (i-1) (mod p). */
if (!BN_sub_word(i, 1))
goto err;
if (!BN_mod_mul(out_sqrt, a, b, p, ctx))
goto err;
if (!BN_mod_mul(out_sqrt, out_sqrt, i, p, ctx))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Case 3. We know that (a/p) = 1 and that p = 1 (mod 8).
*/
/*
* Simple helper. To find a generator of the 2-Sylow subgroup of GF(p)*, we
* need to find a quadratic non-residue of p, i.e., n such that (n/p) = -1.
*/
static int
bn_mod_sqrt_n_is_non_residue(int *is_non_residue, const BIGNUM *n,
const BIGNUM *p, BN_CTX *ctx)
{
switch (BN_kronecker(n, p, ctx)) {
case -1:
*is_non_residue = 1;
return 1;
case 1:
*is_non_residue = 0;
return 1;
case 0:
/* n divides p, so ... */
BNerror(BN_R_P_IS_NOT_PRIME);
return 0;
default:
return 0;
}
}
/*
* The following is the only non-deterministic part preparing Tonelli-Shanks.
*
* If we find n such that (n/p) = -1, then n^q (mod p) is a generator of the
* 2-Sylow subgroup of GF(p)*. To find such n, first try some small numbers,
* then random ones.
*/
static int
bn_mod_sqrt_find_sylow_generator(BIGNUM *out_generator, const BIGNUM *p,
const BIGNUM *q, BN_CTX *ctx)
{
BIGNUM *n, *p_abs, *thirty_two;
int i, is_non_residue;
int ret = 0;
BN_CTX_start(ctx);
if ((n = BN_CTX_get(ctx)) == NULL)
goto err;
if ((thirty_two = BN_CTX_get(ctx)) == NULL)
goto err;
if ((p_abs = BN_CTX_get(ctx)) == NULL)
goto err;
for (i = 2; i < 32; i++) {
if (!BN_set_word(n, i))
goto err;
if (!bn_mod_sqrt_n_is_non_residue(&is_non_residue, n, p, ctx))
goto err;
if (is_non_residue)
goto found;
}
if (!BN_set_word(thirty_two, 32))
goto err;
if (!bn_copy(p_abs, p))
goto err;
BN_set_negative(p_abs, 0);
for (i = 0; i < 128; i++) {
if (!bn_rand_interval(n, thirty_two, p_abs))
goto err;
if (!bn_mod_sqrt_n_is_non_residue(&is_non_residue, n, p, ctx))
goto err;
if (is_non_residue)
goto found;
}
/*
* The probability to get here is < 2^(-128) for prime p. For squares
* it is easy: for p = 1369 = 37^2 this happens in ~3% of runs.
*/
BNerror(BN_R_TOO_MANY_ITERATIONS);
goto err;
found:
/*
* If p is prime, n^q generates the 2-Sylow subgroup S of GF(p)*.
*/
if (!BN_mod_exp_ct(out_generator, n, q, p, ctx))
goto err;
/* Sanity: p is not necessarily prime, so we could have found 0 or 1. */
if (BN_is_zero(out_generator) || BN_is_one(out_generator)) {
BNerror(BN_R_P_IS_NOT_PRIME);
goto err;
}
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Initialization step for Tonelli-Shanks.
*
* In the end, b = a^q (mod p) and x = a^[(q+1)/2] (mod p). Cohen optimizes this
* to minimize taking powers of a. This is a bit confusing and distracting, so
* factor this into a separate function.
*/
static int
bn_mod_sqrt_tonelli_shanks_initialize(BIGNUM *b, BIGNUM *x, const BIGNUM *a,
const BIGNUM *p, const BIGNUM *q, BN_CTX *ctx)
{
BIGNUM *k;
int ret = 0;
BN_CTX_start(ctx);
if ((k = BN_CTX_get(ctx)) == NULL)
goto err;
/* k = (q-1)/2. Since q is odd, we can shift. */
if (!BN_rshift1(k, q))
goto err;
/* x = a^[(q-1)/2] (mod p). */
if (!BN_mod_exp_ct(x, a, k, p, ctx))
goto err;
/* b = ax^2 = a^q (mod p). */
if (!BN_mod_sqr(b, x, p, ctx))
goto err;
if (!BN_mod_mul(b, a, b, p, ctx))
goto err;
/* x = ax = a^[(q+1)/2] (mod p). */
if (!BN_mod_mul(x, a, x, p, ctx))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Find smallest exponent m such that b^(2^m) = 1 (mod p). Assuming that a
* is a quadratic residue and p is a prime, we know that 1 <= m < r.
*/
static int
bn_mod_sqrt_tonelli_shanks_find_exponent(int *out_exponent, const BIGNUM *b,
const BIGNUM *p, int r, BN_CTX *ctx)
{
BIGNUM *x;
int m;
int ret = 0;
BN_CTX_start(ctx);
if ((x = BN_CTX_get(ctx)) == NULL)
goto err;
/*
* If r <= 1, the Tonelli-Shanks iteration should have terminated as
* r == 1 implies b == 1.
*/
if (r <= 1) {
BNerror(BN_R_P_IS_NOT_PRIME);
goto err;
}
/*
* Sanity check to ensure taking squares actually does something:
* If b is 1, the Tonelli-Shanks iteration should have terminated.
* If b is 0, something's very wrong, in particular p can't be prime.
*/
if (BN_is_zero(b) || BN_is_one(b)) {
BNerror(BN_R_P_IS_NOT_PRIME);
goto err;
}
if (!bn_copy(x, b))
goto err;
for (m = 1; m < r; m++) {
if (!BN_mod_sqr(x, x, p, ctx))
goto err;
if (BN_is_one(x))
break;
}
if (m >= r) {
/* This means a is not a quadratic residue. As (a/p) = 1, ... */
BNerror(BN_R_P_IS_NOT_PRIME);
goto err;
}
*out_exponent = m;
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*
* The update step. With the minimal m such that b^(2^m) = 1 (mod m),
* set t = y^[2^(r-m-1)] (mod p) and update x = xt, y = t^2, b = by.
* This preserves the loop invariants a b = x^2, y^[2^(r-1)] = -1 and
* b^[2^(r-1)] = 1.
*/
static int
bn_mod_sqrt_tonelli_shanks_update(BIGNUM *b, BIGNUM *x, BIGNUM *y,
const BIGNUM *p, int m, int r, BN_CTX *ctx)
{
BIGNUM *t;
int ret = 0;
BN_CTX_start(ctx);
if ((t = BN_CTX_get(ctx)) == NULL)
goto err;
/* t = y^[2^(r-m-1)] (mod p). */
if (!BN_set_bit(t, r - m - 1))
goto err;
if (!BN_mod_exp_ct(t, y, t, p, ctx))
goto err;
/* x = xt (mod p). */
if (!BN_mod_mul(x, x, t, p, ctx))
goto err;
/* y = t^2 = y^[2^(r-m)] (mod p). */
if (!BN_mod_sqr(y, t, p, ctx))
goto err;
/* b = by (mod p). */
if (!BN_mod_mul(b, b, y, p, ctx))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
static int
bn_mod_sqrt_p_is_1_mod_8(BIGNUM *out_sqrt, const BIGNUM *a, const BIGNUM *p,
BN_CTX *ctx)
{
BIGNUM *b, *q, *x, *y;
int e, m, r;
int ret = 0;
BN_CTX_start(ctx);
if ((b = BN_CTX_get(ctx)) == NULL)
goto err;
if ((q = BN_CTX_get(ctx)) == NULL)
goto err;
if ((x = BN_CTX_get(ctx)) == NULL)
goto err;
if ((y = BN_CTX_get(ctx)) == NULL)
goto err;
/*
* Factor p - 1 = 2^e q with odd q. Since p = 1 (mod 8), we know e >= 3.
*/
e = 1;
while (!BN_is_bit_set(p, e))
e++;
if (!BN_rshift(q, p, e))
goto err;
if (!bn_mod_sqrt_find_sylow_generator(y, p, q, ctx))
goto err;
/*
* Set b = a^q (mod p) and x = a^[(q+1)/2] (mod p).
*/
if (!bn_mod_sqrt_tonelli_shanks_initialize(b, x, a, p, q, ctx))
goto err;
/*
* The Tonelli-Shanks iteration. Starting with r = e, the following loop
* invariants hold at the start of the loop.
*
* a b = x^2 (mod p)
* y^[2^(r-1)] = -1 (mod p)
* b^[2^(r-1)] = 1 (mod p)
*
* In particular, if b = 1 (mod p), x is a square root of a.
*
* Since p - 1 = 2^e q, we have 2^(e-1) q = (p - 1) / 2, so in the first
* iteration this follows from (a/p) = 1, (n/p) = -1, y = n^q, b = a^q.
*
* In subsequent iterations, t = y^[2^(r-m-1)], where m is the smallest
* m such that b^(2^m) = 1. With x = xt (mod p) and b = bt^2 (mod p) the
* first invariant is preserved, the second and third follow from
* y = t^2 (mod p) and r = m as well as the choice of m.
*
* Finally, r is strictly decreasing in each iteration. If p is prime,
* let S be the 2-Sylow subgroup of GF(p)*. We can prove the algorithm
* stops: Let S_r be the subgroup of S consisting of elements of order
* dividing 2^r. Then S_r = <y> and b is in S_(r-1). The S_r form a
* descending filtration of S and when r = 1, then b = 1.
*/
for (r = e; r >= 1; r = m) {
/*
* Termination condition. If b == 1 then x is a square root.
*/
if (BN_is_one(b))
goto done;
/* Find smallest exponent 1 <= m < r such that b^(2^m) == 1. */
if (!bn_mod_sqrt_tonelli_shanks_find_exponent(&m, b, p, r, ctx))
goto err;
/*
* With t = y^[2^(r-m-1)], update x = xt, y = t^2, b = by.
*/
if (!bn_mod_sqrt_tonelli_shanks_update(b, x, y, p, m, r, ctx))
goto err;
/*
* Sanity check to make sure we don't loop indefinitely.
* bn_mod_sqrt_tonelli_shanks_find_exponent() ensures m < r.
*/
if (r <= m)
goto err;
}
/*
* If p is prime, we should not get here.
*/
BNerror(BN_R_NOT_A_SQUARE);
goto err;
done:
if (!bn_copy(out_sqrt, x))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Choose the smaller of sqrt and |p| - sqrt.
*/
static int
bn_mod_sqrt_normalize(BIGNUM *sqrt, const BIGNUM *p, BN_CTX *ctx)
{
BIGNUM *x;
int ret = 0;
BN_CTX_start(ctx);
if ((x = BN_CTX_get(ctx)) == NULL)
goto err;
if (!BN_lshift1(x, sqrt))
goto err;
if (BN_ucmp(x, p) > 0) {
if (!BN_usub(sqrt, p, sqrt))
goto err;
}
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*
* Verify that a = (sqrt_a)^2 (mod p). Requires that a is reduced (mod p).
*/
static int
bn_mod_sqrt_verify(const BIGNUM *a, const BIGNUM *sqrt_a, const BIGNUM *p,
BN_CTX *ctx)
{
BIGNUM *x;
int ret = 0;
BN_CTX_start(ctx);
if ((x = BN_CTX_get(ctx)) == NULL)
goto err;
if (!BN_mod_sqr(x, sqrt_a, p, ctx))
goto err;
if (BN_cmp(x, a) != 0) {
BNerror(BN_R_NOT_A_SQUARE);
goto err;
}
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
static int
bn_mod_sqrt_internal(BIGNUM *out_sqrt, const BIGNUM *a, const BIGNUM *p,
BN_CTX *ctx)
{
BIGNUM *a_mod_p, *sqrt;
BN_ULONG lsw;
int done;
int kronecker;
int ret = 0;
BN_CTX_start(ctx);
if ((a_mod_p = BN_CTX_get(ctx)) == NULL)
goto err;
if ((sqrt = BN_CTX_get(ctx)) == NULL)
goto err;
if (!BN_nnmod(a_mod_p, a, p, ctx))
goto err;
if (!bn_mod_sqrt_trivial_cases(&done, sqrt, a_mod_p, p, ctx))
goto err;
if (done)
goto verify;
/*
* Make sure that the Kronecker symbol (a/p) == 1. In case p is prime
* this is equivalent to a having a square root (mod p). The cost of
* BN_kronecker() is O(log^2(n)). This is small compared to the cost
* O(log^4(n)) of Tonelli-Shanks.
*/
if ((kronecker = BN_kronecker(a_mod_p, p, ctx)) == -2)
goto err;
if (kronecker <= 0) {
/* This error is only accurate if p is known to be a prime. */
BNerror(BN_R_NOT_A_SQUARE);
goto err;
}
lsw = BN_lsw(p);
if (lsw % 4 == 3) {
if (!bn_mod_sqrt_p_is_3_mod_4(sqrt, a_mod_p, p, ctx))
goto err;
} else if (lsw % 8 == 5) {
if (!bn_mod_sqrt_p_is_5_mod_8(sqrt, a_mod_p, p, ctx))
goto err;
} else if (lsw % 8 == 1) {
if (!bn_mod_sqrt_p_is_1_mod_8(sqrt, a_mod_p, p, ctx))
goto err;
} else {
/* Impossible to hit since the trivial cases ensure p is odd. */
BNerror(BN_R_P_IS_NOT_PRIME);
goto err;
}
if (!bn_mod_sqrt_normalize(sqrt, p, ctx))
goto err;
verify:
if (!bn_mod_sqrt_verify(a_mod_p, sqrt, p, ctx))
goto err;
if (!bn_copy(out_sqrt, sqrt))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
BIGNUM *
BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
{
BIGNUM *out_sqrt;
if ((out_sqrt = in) == NULL)
out_sqrt = BN_new();
if (out_sqrt == NULL)
goto err;
if (!bn_mod_sqrt_internal(out_sqrt, a, p, ctx))
goto err;
return out_sqrt;
err:
if (out_sqrt != in)
BN_free(out_sqrt);
return NULL;
}

572
externals/libressl/crypto/bn/bn_mont.c vendored Normal file
View File

@@ -0,0 +1,572 @@
/* $OpenBSD: bn_mont.c,v 1.59 2023/04/30 05:21:20 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
/* ====================================================================
* Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
/*
* Details about Montgomery multiplication algorithms can be found at
* http://security.ece.orst.edu/publications.html, e.g.
* http://security.ece.orst.edu/koc/papers/j37acmon.pdf and
* sections 3.8 and 4.2 in http://security.ece.orst.edu/koc/papers/r01rsasw.pdf
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "bn_internal.h"
#include "bn_local.h"
BN_MONT_CTX *
BN_MONT_CTX_new(void)
{
BN_MONT_CTX *mctx;
if ((mctx = calloc(1, sizeof(BN_MONT_CTX))) == NULL)
return NULL;
mctx->flags = BN_FLG_MALLOCED;
BN_init(&mctx->RR);
BN_init(&mctx->N);
return mctx;
}
void
BN_MONT_CTX_free(BN_MONT_CTX *mctx)
{
if (mctx == NULL)
return;
BN_free(&mctx->RR);
BN_free(&mctx->N);
if (mctx->flags & BN_FLG_MALLOCED)
free(mctx);
}
BN_MONT_CTX *
BN_MONT_CTX_copy(BN_MONT_CTX *dst, BN_MONT_CTX *src)
{
if (dst == src)
return dst;
if (!bn_copy(&dst->RR, &src->RR))
return NULL;
if (!bn_copy(&dst->N, &src->N))
return NULL;
dst->ri = src->ri;
dst->n0[0] = src->n0[0];
dst->n0[1] = src->n0[1];
return dst;
}
int
BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
{
BIGNUM *N, *Ninv, *Rinv, *R;
int ret = 0;
BN_CTX_start(ctx);
if ((N = BN_CTX_get(ctx)) == NULL)
goto err;
if ((Ninv = BN_CTX_get(ctx)) == NULL)
goto err;
if ((R = BN_CTX_get(ctx)) == NULL)
goto err;
if ((Rinv = BN_CTX_get(ctx)) == NULL)
goto err;
/* Save modulus and determine length of R. */
if (BN_is_zero(mod))
goto err;
if (!bn_copy(&mont->N, mod))
goto err;
mont->N.neg = 0;
mont->ri = ((BN_num_bits(mod) + BN_BITS2 - 1) / BN_BITS2) * BN_BITS2;
if (mont->ri * 2 < mont->ri)
goto err;
/*
* Compute Ninv = (R * Rinv - 1)/N mod R, for R = 2^64. This provides
* a single or double word result (dependent on BN word size), that is
* later used to implement Montgomery reduction.
*/
BN_zero(R);
if (!BN_set_bit(R, 64))
goto err;
/* N = N mod R. */
if (!bn_wexpand(N, 2))
goto err;
if (!BN_set_word(N, mod->d[0]))
goto err;
#if BN_BITS2 == 32
if (mod->top > 1) {
N->d[1] = mod->d[1];
N->top += bn_ct_ne_zero(N->d[1]);
}
#endif
/* Rinv = R^-1 mod N */
if ((BN_mod_inverse_ct(Rinv, R, N, ctx)) == NULL)
goto err;
/* Ninv = (R * Rinv - 1) / N */
if (!BN_lshift(Ninv, Rinv, 64))
goto err;
if (BN_is_zero(Ninv)) {
/* R * Rinv == 0, set to R so that R * Rinv - 1 is mod R. */
if (!BN_set_bit(Ninv, 64))
goto err;
}
if (!BN_sub_word(Ninv, 1))
goto err;
if (!BN_div_ct(Ninv, NULL, Ninv, N, ctx))
goto err;
/* Store least significant word(s) of Ninv. */
mont->n0[0] = mont->n0[1] = 0;
if (Ninv->top > 0)
mont->n0[0] = Ninv->d[0];
#if BN_BITS2 == 32
/* Some BN_BITS2 == 32 platforms (namely parisc) use two words of Ninv. */
if (Ninv->top > 1)
mont->n0[1] = Ninv->d[1];
#endif
/* Compute RR = R * R mod N, for use when converting to Montgomery form. */
BN_zero(&mont->RR);
if (!BN_set_bit(&mont->RR, mont->ri * 2))
goto err;
if (!BN_mod_ct(&mont->RR, &mont->RR, &mont->N, ctx))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
BN_MONT_CTX *
BN_MONT_CTX_set_locked(BN_MONT_CTX **pmctx, int lock, const BIGNUM *mod,
BN_CTX *ctx)
{
BN_MONT_CTX *mctx = NULL;
CRYPTO_r_lock(lock);
mctx = *pmctx;
CRYPTO_r_unlock(lock);
if (mctx != NULL)
goto done;
if ((mctx = BN_MONT_CTX_new()) == NULL)
goto err;
if (!BN_MONT_CTX_set(mctx, mod, ctx))
goto err;
CRYPTO_w_lock(lock);
if (*pmctx != NULL) {
/* Someone else raced us... */
BN_MONT_CTX_free(mctx);
mctx = *pmctx;
} else {
*pmctx = mctx;
}
CRYPTO_w_unlock(lock);
goto done;
err:
BN_MONT_CTX_free(mctx);
mctx = NULL;
done:
return mctx;
}
static int bn_montgomery_reduce(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mctx);
static int
bn_mod_mul_montgomery_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
BN_MONT_CTX *mctx, BN_CTX *ctx)
{
BIGNUM *tmp;
int ret = 0;
BN_CTX_start(ctx);
if ((tmp = BN_CTX_get(ctx)) == NULL)
goto err;
if (a == b) {
if (!BN_sqr(tmp, a, ctx))
goto err;
} else {
if (!BN_mul(tmp, a, b, ctx))
goto err;
}
/* Reduce from aRR to aR. */
if (!bn_montgomery_reduce(r, tmp, mctx))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*
* bn_montgomery_multiply_words() computes r = aR * bR * R^-1 = abR for the
* given word arrays. The caller must ensure that rp, ap, bp and np are all
* n_len words in length, while tp must be n_len * 2 + 2 words in length.
*/
void
bn_montgomery_multiply_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
const BN_ULONG *np, BN_ULONG *tp, BN_ULONG n0, int n_len)
{
BN_ULONG a0, b, carry_a, carry_n, carry, mask, w, x;
int i, j;
carry_a = carry_n = carry = 0;
for (i = 0; i < n_len; i++)
tp[i] = 0;
a0 = ap[0];
for (i = 0; i < n_len; i++) {
b = bp[i];
/* Compute new t[0] * n0, as we need it inside the loop. */
w = (a0 * b + tp[0]) * n0;
for (j = 0; j < n_len; j++) {
bn_mulw_addw_addw(ap[j], b, tp[j], carry_a, &carry_a, &x);
bn_mulw_addw_addw(np[j], w, x, carry_n, &carry_n, &tp[j]);
}
bn_addw_addw(carry_a, carry_n, carry, &carry, &tp[n_len]);
carry_a = carry_n = 0;
tp++;
}
tp[n_len] = carry;
/*
* The output is now in the range of [0, 2N). Attempt to reduce once by
* subtracting the modulus. If the reduction was necessary then the
* result is already in r, otherwise copy the value prior to reduction
* from tp.
*/
mask = bn_ct_ne_zero(tp[n_len]) - bn_sub_words(rp, tp, np, n_len);
for (i = 0; i < n_len; i++) {
*rp = (*rp & ~mask) | (*tp & mask);
rp++;
tp++;
}
}
/*
* bn_montgomery_multiply() computes r = aR * bR * R^-1 = abR for the given
* BIGNUMs. The caller must ensure that the modulus is two or more words in
* length and that a and b have the same number of words as the modulus.
*/
int
bn_montgomery_multiply(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
BN_MONT_CTX *mctx, BN_CTX *ctx)
{
BIGNUM *t;
int ret = 0;
BN_CTX_start(ctx);
if (mctx->N.top <= 1 || a->top != mctx->N.top || b->top != mctx->N.top)
goto err;
if (!bn_wexpand(r, mctx->N.top))
goto err;
if ((t = BN_CTX_get(ctx)) == NULL)
goto err;
if (!bn_wexpand(t, mctx->N.top * 2 + 2))
goto err;
bn_montgomery_multiply_words(r->d, a->d, b->d, mctx->N.d, t->d,
mctx->n0[0], mctx->N.top);
r->top = mctx->N.top;
bn_correct_top(r);
BN_set_negative(r, a->neg ^ b->neg);
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
#ifndef OPENSSL_BN_ASM_MONT
int
bn_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
BN_MONT_CTX *mctx, BN_CTX *ctx)
{
if (mctx->N.top <= 1 || a->top != mctx->N.top || b->top != mctx->N.top)
return bn_mod_mul_montgomery_simple(r, a, b, mctx, ctx);
return bn_montgomery_multiply(r, a, b, mctx, ctx);
}
#else
int
bn_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
BN_MONT_CTX *mctx, BN_CTX *ctx)
{
if (mctx->N.top <= 1 || a->top != mctx->N.top || b->top != mctx->N.top)
return bn_mod_mul_montgomery_simple(r, a, b, mctx, ctx);
/*
* Legacy bn_mul_mont() performs stack based allocation, without
* size limitation. Allowing a large size results in the stack
* being blown.
*/
if (mctx->N.top > (8 * 1024 / sizeof(BN_ULONG)))
return bn_montgomery_multiply(r, a, b, mctx, ctx);
if (!bn_wexpand(r, mctx->N.top))
return 0;
/*
* Legacy bn_mul_mont() can indicate that we should "fallback" to
* another implementation.
*/
if (!bn_mul_mont(r->d, a->d, b->d, mctx->N.d, mctx->n0, mctx->N.top))
return bn_montgomery_multiply(r, a, b, mctx, ctx);
r->top = mctx->N.top;
bn_correct_top(r);
BN_set_negative(r, a->neg ^ b->neg);
return (1);
}
#endif
int
BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
BN_MONT_CTX *mctx, BN_CTX *ctx)
{
/* Compute r = aR * bR * R^-1 mod N = abR mod N */
return bn_mod_mul_montgomery(r, a, b, mctx, ctx);
}
int
BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mctx, BN_CTX *ctx)
{
/* Compute r = a * R * R * R^-1 mod N = aR mod N */
return bn_mod_mul_montgomery(r, a, &mctx->RR, mctx, ctx);
}
/*
* bn_montgomery_reduce() performs Montgomery reduction, reducing the input
* from its Montgomery form aR to a, returning the result in r. Note that the
* input is mutated in the process of performing the reduction, destroying its
* original value.
*/
static int
bn_montgomery_reduce(BIGNUM *r, BIGNUM *a, BN_MONT_CTX *mctx)
{
BIGNUM *n;
BN_ULONG *ap, *rp, n0, v, carry, mask;
int i, max, n_len;
n = &mctx->N;
n_len = mctx->N.top;
if (n_len == 0) {
BN_zero(r);
return 1;
}
if (!bn_wexpand(r, n_len))
return 0;
/*
* Expand a to twice the length of the modulus, zero if necessary.
* XXX - make this a requirement of the caller.
*/
if ((max = 2 * n_len) < n_len)
return 0;
if (!bn_wexpand(a, max))
return 0;
for (i = a->top; i < max; i++)
a->d[i] = 0;
carry = 0;
n0 = mctx->n0[0];
/* Add multiples of the modulus, so that it becomes divisible by R. */
for (i = 0; i < n_len; i++) {
v = bn_mul_add_words(&a->d[i], n->d, n_len, a->d[i] * n0);
bn_addw_addw(v, a->d[i + n_len], carry, &carry,
&a->d[i + n_len]);
}
/* Divide by R (this is the equivalent of right shifting by n_len). */
ap = &a->d[n_len];
/*
* The output is now in the range of [0, 2N). Attempt to reduce once by
* subtracting the modulus. If the reduction was necessary then the
* result is already in r, otherwise copy the value prior to reduction
* from the top half of a.
*/
mask = carry - bn_sub_words(r->d, ap, n->d, n_len);
rp = r->d;
for (i = 0; i < n_len; i++) {
*rp = (*rp & ~mask) | (*ap & mask);
rp++;
ap++;
}
r->top = n_len;
bn_correct_top(r);
BN_set_negative(r, a->neg ^ n->neg);
return 1;
}
int
BN_from_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mctx, BN_CTX *ctx)
{
BIGNUM *tmp;
int ret = 0;
BN_CTX_start(ctx);
if ((tmp = BN_CTX_get(ctx)) == NULL)
goto err;
if (!bn_copy(tmp, a))
goto err;
if (!bn_montgomery_reduce(r, tmp, mctx))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}

376
externals/libressl/crypto/bn/bn_mul.c vendored Normal file
View File

@@ -0,0 +1,376 @@
/* $OpenBSD: bn_mul.c,v 1.37 2023/04/19 10:51:22 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <openssl/opensslconf.h>
#include "bn_arch.h"
#include "bn_internal.h"
#include "bn_local.h"
/*
* bn_mul_comba4() computes r[] = a[] * b[] using Comba multiplication
* (https://everything2.com/title/Comba+multiplication), where a and b are both
* four word arrays, producing an eight word array result.
*/
#ifndef HAVE_BN_MUL_COMBA4
void
bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
{
BN_ULONG c0, c1, c2;
bn_mulw_addtw(a[0], b[0], 0, 0, 0, &c2, &c1, &r[0]);
bn_mulw_addtw(a[0], b[1], 0, c2, c1, &c2, &c1, &c0);
bn_mulw_addtw(a[1], b[0], c2, c1, c0, &c2, &c1, &r[1]);
bn_mulw_addtw(a[2], b[0], 0, c2, c1, &c2, &c1, &c0);
bn_mulw_addtw(a[1], b[1], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[0], b[2], c2, c1, c0, &c2, &c1, &r[2]);
bn_mulw_addtw(a[0], b[3], 0, c2, c1, &c2, &c1, &c0);
bn_mulw_addtw(a[1], b[2], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[2], b[1], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[3], b[0], c2, c1, c0, &c2, &c1, &r[3]);
bn_mulw_addtw(a[3], b[1], 0, c2, c1, &c2, &c1, &c0);
bn_mulw_addtw(a[2], b[2], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[1], b[3], c2, c1, c0, &c2, &c1, &r[4]);
bn_mulw_addtw(a[2], b[3], 0, c2, c1, &c2, &c1, &c0);
bn_mulw_addtw(a[3], b[2], c2, c1, c0, &c2, &c1, &r[5]);
bn_mulw_addtw(a[3], b[3], 0, c2, c1, &c2, &r[7], &r[6]);
}
#endif
/*
* bn_mul_comba8() computes r[] = a[] * b[] using Comba multiplication
* (https://everything2.com/title/Comba+multiplication), where a and b are both
* eight word arrays, producing a 16 word array result.
*/
#ifndef HAVE_BN_MUL_COMBA8
void
bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
{
BN_ULONG c0, c1, c2;
bn_mulw_addtw(a[0], b[0], 0, 0, 0, &c2, &c1, &r[0]);
bn_mulw_addtw(a[0], b[1], 0, c2, c1, &c2, &c1, &c0);
bn_mulw_addtw(a[1], b[0], c2, c1, c0, &c2, &c1, &r[1]);
bn_mulw_addtw(a[2], b[0], 0, c2, c1, &c2, &c1, &c0);
bn_mulw_addtw(a[1], b[1], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[0], b[2], c2, c1, c0, &c2, &c1, &r[2]);
bn_mulw_addtw(a[0], b[3], 0, c2, c1, &c2, &c1, &c0);
bn_mulw_addtw(a[1], b[2], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[2], b[1], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[3], b[0], c2, c1, c0, &c2, &c1, &r[3]);
bn_mulw_addtw(a[4], b[0], 0, c2, c1, &c2, &c1, &c0);
bn_mulw_addtw(a[3], b[1], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[2], b[2], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[1], b[3], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[0], b[4], c2, c1, c0, &c2, &c1, &r[4]);
bn_mulw_addtw(a[0], b[5], 0, c2, c1, &c2, &c1, &c0);
bn_mulw_addtw(a[1], b[4], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[2], b[3], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[3], b[2], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[4], b[1], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[5], b[0], c2, c1, c0, &c2, &c1, &r[5]);
bn_mulw_addtw(a[6], b[0], 0, c2, c1, &c2, &c1, &c0);
bn_mulw_addtw(a[5], b[1], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[4], b[2], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[3], b[3], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[2], b[4], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[1], b[5], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[0], b[6], c2, c1, c0, &c2, &c1, &r[6]);
bn_mulw_addtw(a[0], b[7], 0, c2, c1, &c2, &c1, &c0);
bn_mulw_addtw(a[1], b[6], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[2], b[5], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[3], b[4], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[4], b[3], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[5], b[2], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[6], b[1], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[7], b[0], c2, c1, c0, &c2, &c1, &r[7]);
bn_mulw_addtw(a[7], b[1], 0, c2, c1, &c2, &c1, &c0);
bn_mulw_addtw(a[6], b[2], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[5], b[3], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[4], b[4], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[3], b[5], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[2], b[6], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[1], b[7], c2, c1, c0, &c2, &c1, &r[8]);
bn_mulw_addtw(a[2], b[7], 0, c2, c1, &c2, &c1, &c0);
bn_mulw_addtw(a[3], b[6], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[4], b[5], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[5], b[4], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[6], b[3], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[7], b[2], c2, c1, c0, &c2, &c1, &r[9]);
bn_mulw_addtw(a[7], b[3], 0, c2, c1, &c2, &c1, &c0);
bn_mulw_addtw(a[6], b[4], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[5], b[5], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[4], b[6], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[3], b[7], c2, c1, c0, &c2, &c1, &r[10]);
bn_mulw_addtw(a[4], b[7], 0, c2, c1, &c2, &c1, &c0);
bn_mulw_addtw(a[5], b[6], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[6], b[5], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[7], b[4], c2, c1, c0, &c2, &c1, &r[11]);
bn_mulw_addtw(a[7], b[5], 0, c2, c1, &c2, &c1, &c0);
bn_mulw_addtw(a[6], b[6], c2, c1, c0, &c2, &c1, &c0);
bn_mulw_addtw(a[5], b[7], c2, c1, c0, &c2, &c1, &r[12]);
bn_mulw_addtw(a[6], b[7], 0, c2, c1, &c2, &c1, &c0);
bn_mulw_addtw(a[7], b[6], c2, c1, c0, &c2, &c1, &r[13]);
bn_mulw_addtw(a[7], b[7], 0, c2, c1, &c2, &r[15], &r[14]);
}
#endif
/*
* bn_mul_words() computes (carry:r[i]) = a[i] * w + carry, where a is an array
* of words and w is a single word. This should really be called bn_mulw_words()
* since only one input is an array. This is used as a step in the multiplication
* of word arrays.
*/
#ifndef HAVE_BN_MUL_WORDS
BN_ULONG
bn_mul_words(BN_ULONG *r, const BN_ULONG *a, int num, BN_ULONG w)
{
BN_ULONG carry = 0;
assert(num >= 0);
if (num <= 0)
return 0;
#ifndef OPENSSL_SMALL_FOOTPRINT
while (num & ~3) {
bn_mulw_addw(a[0], w, carry, &carry, &r[0]);
bn_mulw_addw(a[1], w, carry, &carry, &r[1]);
bn_mulw_addw(a[2], w, carry, &carry, &r[2]);
bn_mulw_addw(a[3], w, carry, &carry, &r[3]);
a += 4;
r += 4;
num -= 4;
}
#endif
while (num) {
bn_mulw_addw(a[0], w, carry, &carry, &r[0]);
a++;
r++;
num--;
}
return carry;
}
#endif
/*
* bn_mul_add_words() computes (carry:r[i]) = a[i] * w + r[i] + carry, where
* a is an array of words and w is a single word. This should really be called
* bn_mulw_add_words() since only one input is an array. This is used as a step
* in the multiplication of word arrays.
*/
#ifndef HAVE_BN_MUL_ADD_WORDS
BN_ULONG
bn_mul_add_words(BN_ULONG *r, const BN_ULONG *a, int num, BN_ULONG w)
{
BN_ULONG carry = 0;
assert(num >= 0);
if (num <= 0)
return 0;
#ifndef OPENSSL_SMALL_FOOTPRINT
while (num & ~3) {
bn_mulw_addw_addw(a[0], w, r[0], carry, &carry, &r[0]);
bn_mulw_addw_addw(a[1], w, r[1], carry, &carry, &r[1]);
bn_mulw_addw_addw(a[2], w, r[2], carry, &carry, &r[2]);
bn_mulw_addw_addw(a[3], w, r[3], carry, &carry, &r[3]);
a += 4;
r += 4;
num -= 4;
}
#endif
while (num) {
bn_mulw_addw_addw(a[0], w, r[0], carry, &carry, &r[0]);
a++;
r++;
num--;
}
return carry;
}
#endif
void
bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb)
{
BN_ULONG *rr;
if (na < nb) {
int itmp;
BN_ULONG *ltmp;
itmp = na;
na = nb;
nb = itmp;
ltmp = a;
a = b;
b = ltmp;
}
rr = &(r[na]);
if (nb <= 0) {
(void)bn_mul_words(r, a, na, 0);
return;
} else
rr[0] = bn_mul_words(r, a, na, b[0]);
for (;;) {
if (--nb <= 0)
return;
rr[1] = bn_mul_add_words(&(r[1]), a, na, b[1]);
if (--nb <= 0)
return;
rr[2] = bn_mul_add_words(&(r[2]), a, na, b[2]);
if (--nb <= 0)
return;
rr[3] = bn_mul_add_words(&(r[3]), a, na, b[3]);
if (--nb <= 0)
return;
rr[4] = bn_mul_add_words(&(r[4]), a, na, b[4]);
rr += 4;
r += 4;
b += 4;
}
}
#ifndef HAVE_BN_MUL
int
bn_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, int rn, BN_CTX *ctx)
{
bn_mul_normal(r->d, a->d, a->top, b->d, b->top);
return 1;
}
#endif /* HAVE_BN_MUL */
int
BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
{
BIGNUM *rr;
int rn;
int ret = 0;
BN_CTX_start(ctx);
if (BN_is_zero(a) || BN_is_zero(b)) {
BN_zero(r);
goto done;
}
rr = r;
if (rr == a || rr == b)
rr = BN_CTX_get(ctx);
if (rr == NULL)
goto err;
rn = a->top + b->top;
if (rn < a->top)
goto err;
if (!bn_wexpand(rr, rn))
goto err;
if (a->top == 4 && b->top == 4) {
bn_mul_comba4(rr->d, a->d, b->d);
} else if (a->top == 8 && b->top == 8) {
bn_mul_comba8(rr->d, a->d, b->d);
} else {
if (!bn_mul(rr, a, b, rn, ctx))
goto err;
}
rr->top = rn;
bn_correct_top(rr);
BN_set_negative(rr, a->neg ^ b->neg);
if (!bn_copy(r, rr))
goto err;
done:
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}

408
externals/libressl/crypto/bn/bn_prime.c vendored Normal file
View File

@@ -0,0 +1,408 @@
/* $OpenBSD: bn_prime.c,v 1.32 2023/05/10 12:21:55 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
/* ====================================================================
* Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include <stdio.h>
#include <time.h>
#include <openssl/err.h>
#include "bn_local.h"
/* The quick sieve algorithm approach to weeding out primes is
* Philip Zimmermann's, as implemented in PGP. I have had a read of
* his comments and implemented my own version.
*/
#include "bn_prime.h"
static int probable_prime(BIGNUM *rnd, int bits);
static int probable_prime_dh(BIGNUM *rnd, int bits,
const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx);
static int probable_prime_dh_safe(BIGNUM *rnd, int bits,
const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx);
int
BN_GENCB_call(BN_GENCB *cb, int a, int b)
{
/* No callback means continue */
if (!cb)
return 1;
switch (cb->ver) {
case 1:
/* Deprecated-style callbacks */
if (!cb->cb.cb_1)
return 1;
cb->cb.cb_1(a, b, cb->arg);
return 1;
case 2:
/* New-style callbacks */
return cb->cb.cb_2(a, b, cb);
default:
break;
}
/* Unrecognised callback type */
return 0;
}
int
BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add,
const BIGNUM *rem, BN_GENCB *cb)
{
BN_CTX *ctx;
BIGNUM *p;
int is_prime;
int loops = 0;
int found = 0;
if (bits < 2 || (bits == 2 && safe)) {
/*
* There are no prime numbers smaller than 2, and the smallest
* safe prime (7) spans three bits.
*/
BNerror(BN_R_BITS_TOO_SMALL);
return 0;
}
if ((ctx = BN_CTX_new()) == NULL)
goto err;
BN_CTX_start(ctx);
if ((p = BN_CTX_get(ctx)) == NULL)
goto err;
loop:
/* Make a random number and set the top and bottom bits. */
if (add == NULL) {
if (!probable_prime(ret, bits))
goto err;
} else {
if (safe) {
if (!probable_prime_dh_safe(ret, bits, add, rem, ctx))
goto err;
} else {
if (!probable_prime_dh(ret, bits, add, rem, ctx))
goto err;
}
}
if (!BN_GENCB_call(cb, 0, loops++))
goto err;
if (!safe) {
if (!bn_is_prime_bpsw(&is_prime, ret, ctx, 1))
goto err;
if (!is_prime)
goto loop;
} else {
if (!bn_is_prime_bpsw(&is_prime, ret, ctx, 1))
goto err;
if (!is_prime)
goto loop;
/*
* For safe prime generation, check that p = (ret-1)/2 is prime.
* Since this prime has >= 3 bits, it is odd, and we can simply
* divide by 2.
*/
if (!BN_rshift1(p, ret))
goto err;
if (!bn_is_prime_bpsw(&is_prime, p, ctx, 1))
goto err;
if (!is_prime)
goto loop;
if (!BN_GENCB_call(cb, 2, loops - 1))
goto err;
}
found = 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return found;
}
int
BN_is_prime_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed, BN_GENCB *cb)
{
return BN_is_prime_fasttest_ex(a, checks, ctx_passed, 0, cb);
}
int
BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed,
int do_trial_division, BN_GENCB *cb)
{
int is_prime;
if (checks < 0)
return -1;
if (checks == BN_prime_checks)
checks = BN_prime_checks_for_size(BN_num_bits(a));
/* XXX - tickle BN_GENCB in bn_is_prime_bpsw(). */
if (!bn_is_prime_bpsw(&is_prime, a, ctx_passed, checks))
return -1;
return is_prime;
}
static int
probable_prime(BIGNUM *rnd, int bits)
{
int i;
BN_ULONG mods[NUMPRIMES];
BN_ULONG delta, maxdelta;
again:
if (!BN_rand(rnd, bits, 1, 1))
return (0);
/* we now have a random number 'rand' to test. */
for (i = 1; i < NUMPRIMES; i++) {
BN_ULONG mod = BN_mod_word(rnd, primes[i]);
if (mod == (BN_ULONG)-1)
return (0);
mods[i] = mod;
}
maxdelta = BN_MASK2 - primes[NUMPRIMES - 1];
delta = 0;
loop:
for (i = 1; i < NUMPRIMES; i++) {
/* check that rnd is not a prime and also
* that gcd(rnd-1,primes) == 1 (except for 2) */
if (((mods[i] + delta) % primes[i]) <= 1) {
delta += 2;
if (delta > maxdelta)
goto again;
goto loop;
}
}
if (!BN_add_word(rnd, delta))
return (0);
return (1);
}
static int
probable_prime_dh(BIGNUM *rnd, int bits, const BIGNUM *add, const BIGNUM *rem,
BN_CTX *ctx)
{
int i, ret = 0;
BIGNUM *t1;
BN_CTX_start(ctx);
if ((t1 = BN_CTX_get(ctx)) == NULL)
goto err;
if (!BN_rand(rnd, bits, 0, 1))
goto err;
/* we need ((rnd-rem) % add) == 0 */
if (!BN_mod_ct(t1, rnd, add, ctx))
goto err;
if (!BN_sub(rnd, rnd, t1))
goto err;
if (rem == NULL) {
if (!BN_add_word(rnd, 1))
goto err;
} else {
if (!BN_add(rnd, rnd, rem))
goto err;
}
/* we now have a random number 'rand' to test. */
loop:
for (i = 1; i < NUMPRIMES; i++) {
/* check that rnd is a prime */
BN_LONG mod = BN_mod_word(rnd, primes[i]);
if (mod == (BN_ULONG)-1)
goto err;
if (mod <= 1) {
if (!BN_add(rnd, rnd, add))
goto err;
goto loop;
}
}
ret = 1;
err:
BN_CTX_end(ctx);
return (ret);
}
static int
probable_prime_dh_safe(BIGNUM *p, int bits, const BIGNUM *padd,
const BIGNUM *rem, BN_CTX *ctx)
{
int i, ret = 0;
BIGNUM *t1, *qadd, *q;
bits--;
BN_CTX_start(ctx);
if ((t1 = BN_CTX_get(ctx)) == NULL)
goto err;
if ((q = BN_CTX_get(ctx)) == NULL)
goto err;
if ((qadd = BN_CTX_get(ctx)) == NULL)
goto err;
if (!BN_rshift1(qadd, padd))
goto err;
if (!BN_rand(q, bits, 0, 1))
goto err;
/* we need ((rnd-rem) % add) == 0 */
if (!BN_mod_ct(t1, q,qadd, ctx))
goto err;
if (!BN_sub(q, q, t1))
goto err;
if (rem == NULL) {
if (!BN_add_word(q, 1))
goto err;
} else {
if (!BN_rshift1(t1, rem))
goto err;
if (!BN_add(q, q, t1))
goto err;
}
/* we now have a random number 'rand' to test. */
if (!BN_lshift1(p, q))
goto err;
if (!BN_add_word(p, 1))
goto err;
loop:
for (i = 1; i < NUMPRIMES; i++) {
/* check that p and q are prime */
/* check that for p and q
* gcd(p-1,primes) == 1 (except for 2) */
BN_ULONG pmod = BN_mod_word(p, primes[i]);
BN_ULONG qmod = BN_mod_word(q, primes[i]);
if (pmod == (BN_ULONG)-1 || qmod == (BN_ULONG)-1)
goto err;
if (pmod == 0 || qmod == 0) {
if (!BN_add(p, p, padd))
goto err;
if (!BN_add(q, q, qadd))
goto err;
goto loop;
}
}
ret = 1;
err:
BN_CTX_end(ctx);
return (ret);
}

14
externals/libressl/crypto/bn/bn_prime.h vendored Normal file
View File

@@ -0,0 +1,14 @@
/* $OpenBSD: bn_prime.h,v 1.9 2022/11/10 10:24:50 tb Exp $ */
/*
* Public domain.
*/
#include <stdint.h>
__BEGIN_HIDDEN_DECLS
#define NUMPRIMES 2048
extern const uint16_t primes[NUMPRIMES];
__END_HIDDEN_DECLS

314
externals/libressl/crypto/bn/bn_rand.c vendored Normal file
View File

@@ -0,0 +1,314 @@
/* $OpenBSD: bn_rand.c,v 1.27 2022/11/26 16:08:51 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
/* ====================================================================
* Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <openssl/err.h>
#include "bn_local.h"
static int
bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom)
{
unsigned char *buf = NULL;
int ret = 0, bit, bytes, mask;
if (rnd == NULL) {
BNerror(ERR_R_PASSED_NULL_PARAMETER);
return (0);
}
if (bits < 0 || (bits == 1 && top > 0)) {
BNerror(BN_R_BITS_TOO_SMALL);
return (0);
}
if (bits == 0) {
BN_zero(rnd);
return (1);
}
bytes = (bits + 7) / 8;
bit = (bits - 1) % 8;
mask = 0xff << (bit + 1);
buf = malloc(bytes);
if (buf == NULL) {
BNerror(ERR_R_MALLOC_FAILURE);
goto err;
}
/* make a random number and set the top and bottom bits */
arc4random_buf(buf, bytes);
#if 1
if (pseudorand == 2) {
/* generate patterns that are more likely to trigger BN
library bugs */
int i;
unsigned char c;
for (i = 0; i < bytes; i++) {
arc4random_buf(&c, 1);
if (c >= 128 && i > 0)
buf[i] = buf[i - 1];
else if (c < 42)
buf[i] = 0;
else if (c < 84)
buf[i] = 255;
}
}
#endif
if (top > 0) {
if (bit == 0) {
buf[0] = 1;
buf[1] |= 0x80;
} else {
buf[0] |= (3 << (bit - 1));
}
}
if (top == 0)
buf[0] |= (1 << bit);
buf[0] &= ~mask;
if (bottom) /* set bottom bit if requested */
buf[bytes - 1] |= 1;
if (BN_bin2bn(buf, bytes, rnd) == NULL)
goto err;
ret = 1;
err:
freezero(buf, bytes);
return (ret);
}
int
BN_rand(BIGNUM *rnd, int bits, int top, int bottom)
{
return bnrand(0, rnd, bits, top, bottom);
}
int
BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom)
{
return bnrand(1, rnd, bits, top, bottom);
}
#if 1
int
BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom)
{
return bnrand(2, rnd, bits, top, bottom);
}
#endif
/* random number r: 0 <= r < range */
static int
bn_rand_range(int pseudo, BIGNUM *r, const BIGNUM *range)
{
int (*bn_rand)(BIGNUM *, int, int, int) = pseudo ? BN_pseudo_rand : BN_rand;
int n;
int count = 100;
if (range->neg || BN_is_zero(range)) {
BNerror(BN_R_INVALID_RANGE);
return 0;
}
n = BN_num_bits(range); /* n > 0 */
/* BN_is_bit_set(range, n - 1) always holds */
if (n == 1)
BN_zero(r);
else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) {
/* range = 100..._2,
* so 3*range (= 11..._2) is exactly one bit longer than range */
do {
if (!bn_rand(r, n + 1, -1, 0))
return 0;
/* If r < 3*range, use r := r MOD range
* (which is either r, r - range, or r - 2*range).
* Otherwise, iterate once more.
* Since 3*range = 11..._2, each iteration succeeds with
* probability >= .75. */
if (BN_cmp(r, range) >= 0) {
if (!BN_sub(r, r, range))
return 0;
if (BN_cmp(r, range) >= 0)
if (!BN_sub(r, r, range))
return 0;
}
if (!--count) {
BNerror(BN_R_TOO_MANY_ITERATIONS);
return 0;
}
} while (BN_cmp(r, range) >= 0);
} else {
do {
/* range = 11..._2 or range = 101..._2 */
if (!bn_rand(r, n, -1, 0))
return 0;
if (!--count) {
BNerror(BN_R_TOO_MANY_ITERATIONS);
return 0;
}
} while (BN_cmp(r, range) >= 0);
}
return 1;
}
int
BN_rand_range(BIGNUM *r, const BIGNUM *range)
{
return bn_rand_range(0, r, range);
}
int
bn_rand_interval(BIGNUM *rnd, const BIGNUM *lower_inc, const BIGNUM *upper_exc)
{
BIGNUM *len = NULL;
int ret = 0;
if (BN_cmp(lower_inc, upper_exc) >= 0)
goto err;
if ((len = BN_new()) == NULL)
goto err;
if (!BN_sub(len, upper_exc, lower_inc))
goto err;
if (!bn_rand_range(0, rnd, len))
goto err;
if (!BN_add(rnd, rnd, lower_inc))
goto err;
ret = 1;
err:
BN_free(len);
return ret;
}
int
BN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range)
{
return bn_rand_range(1, r, range);
}

260
externals/libressl/crypto/bn/bn_recp.c vendored Normal file
View File

@@ -0,0 +1,260 @@
/* $OpenBSD: bn_recp.c,v 1.19 2023/03/27 10:25:02 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include <openssl/err.h>
#include "bn_local.h"
void
BN_RECP_CTX_init(BN_RECP_CTX *recp)
{
BN_init(&(recp->N));
BN_init(&(recp->Nr));
recp->num_bits = 0;
recp->flags = 0;
}
BN_RECP_CTX *
BN_RECP_CTX_new(void)
{
BN_RECP_CTX *ret;
if ((ret = malloc(sizeof(BN_RECP_CTX))) == NULL)
return (NULL);
BN_RECP_CTX_init(ret);
ret->flags = BN_FLG_MALLOCED;
return (ret);
}
void
BN_RECP_CTX_free(BN_RECP_CTX *recp)
{
if (recp == NULL)
return;
BN_free(&(recp->N));
BN_free(&(recp->Nr));
if (recp->flags & BN_FLG_MALLOCED)
free(recp);
}
int
BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *d, BN_CTX *ctx)
{
if (!bn_copy(&(recp->N), d))
return 0;
BN_zero(&(recp->Nr));
recp->num_bits = BN_num_bits(d);
recp->shift = 0;
return (1);
}
int
BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y,
BN_RECP_CTX *recp, BN_CTX *ctx)
{
int ret = 0;
BIGNUM *a;
const BIGNUM *ca;
BN_CTX_start(ctx);
if ((a = BN_CTX_get(ctx)) == NULL)
goto err;
if (y != NULL) {
if (x == y) {
if (!BN_sqr(a, x, ctx))
goto err;
} else {
if (!BN_mul(a, x, y, ctx))
goto err;
}
ca = a;
} else
ca = x; /* Just do the mod */
ret = BN_div_recp(NULL, r, ca, recp, ctx);
err:
BN_CTX_end(ctx);
return (ret);
}
int
BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, BN_RECP_CTX *recp,
BN_CTX *ctx)
{
int i, j, ret = 0;
BIGNUM *a, *b, *d, *r;
BN_CTX_start(ctx);
a = BN_CTX_get(ctx);
b = BN_CTX_get(ctx);
if (dv != NULL)
d = dv;
else
d = BN_CTX_get(ctx);
if (rem != NULL)
r = rem;
else
r = BN_CTX_get(ctx);
if (a == NULL || b == NULL || d == NULL || r == NULL)
goto err;
if (BN_ucmp(m, &(recp->N)) < 0) {
BN_zero(d);
if (!bn_copy(r, m)) {
BN_CTX_end(ctx);
return 0;
}
BN_CTX_end(ctx);
return (1);
}
/* We want the remainder
* Given input of ABCDEF / ab
* we need multiply ABCDEF by 3 digests of the reciprocal of ab
*
*/
/* i := max(BN_num_bits(m), 2*BN_num_bits(N)) */
i = BN_num_bits(m);
j = recp->num_bits << 1;
if (j > i)
i = j;
/* Nr := round(2^i / N) */
if (i != recp->shift)
recp->shift = BN_reciprocal(&(recp->Nr), &(recp->N), i, ctx);
/* BN_reciprocal returns i, or -1 for an error */
if (recp->shift == -1)
goto err;
/* d := |round(round(m / 2^BN_num_bits(N)) * recp->Nr / 2^(i - BN_num_bits(N)))|
* = |round(round(m / 2^BN_num_bits(N)) * round(2^i / N) / 2^(i - BN_num_bits(N)))|
* <= |(m / 2^BN_num_bits(N)) * (2^i / N) * (2^BN_num_bits(N) / 2^i)|
* = |m/N|
*/
if (!BN_rshift(a, m, recp->num_bits))
goto err;
if (!BN_mul(b, a,&(recp->Nr), ctx))
goto err;
if (!BN_rshift(d, b, i - recp->num_bits))
goto err;
d->neg = 0;
if (!BN_mul(b, &(recp->N), d, ctx))
goto err;
if (!BN_usub(r, m, b))
goto err;
r->neg = 0;
#if 1
j = 0;
while (BN_ucmp(r, &(recp->N)) >= 0) {
if (j++ > 2) {
BNerror(BN_R_BAD_RECIPROCAL);
goto err;
}
if (!BN_usub(r, r, &(recp->N)))
goto err;
if (!BN_add_word(d, 1))
goto err;
}
#endif
BN_set_negative(r, m->neg);
BN_set_negative(d, m->neg ^ recp->N.neg);
ret = 1;
err:
BN_CTX_end(ctx);
return (ret);
}
/* len is the expected size of the result
* We actually calculate with an extra word of precision, so
* we can do faster division if the remainder is not required.
*/
/* r := 2^len / m */
int
BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx)
{
int ret = -1;
BIGNUM *t;
BN_CTX_start(ctx);
if ((t = BN_CTX_get(ctx)) == NULL)
goto err;
if (!BN_set_bit(t, len))
goto err;
if (!BN_div_ct(r, NULL, t,m, ctx))
goto err;
ret = len;
err:
BN_CTX_end(ctx);
return (ret);
}

171
externals/libressl/crypto/bn/bn_shift.c vendored Normal file
View File

@@ -0,0 +1,171 @@
/* $OpenBSD: bn_shift.c,v 1.21 2023/02/13 04:25:37 jsing Exp $ */
/*
* Copyright (c) 2022, 2023 Joel Sing <jsing@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <openssl/bn.h>
#include <openssl/err.h>
#include "bn_local.h"
static inline int
bn_lshift(BIGNUM *r, const BIGNUM *a, int n)
{
size_t count, shift_bits, shift_words;
size_t lshift, rshift;
ssize_t rstride;
BN_ULONG *dst, *src;
if (n < 0) {
BNerror(BN_R_INVALID_LENGTH);
return 0;
}
shift_bits = n;
/*
* Left bit shift, potentially across word boundaries.
*
* When shift is not an exact multiple of BN_BITS2, the bottom bits of
* the previous word need to be right shifted and combined with the left
* shifted bits using bitwise OR. If shift is an exact multiple of
* BN_BITS2, the source for the left and right shifts are the same
* and the shifts become zero bits (which is effectively a memmove).
*/
shift_words = shift_bits / BN_BITS2;
lshift = shift_bits % BN_BITS2;
rshift = (BN_BITS2 - lshift) % BN_BITS2;
rstride = 0 - (lshift + rshift) / BN_BITS2;
if (a->top < 1) {
BN_zero(r);
return 1;
}
count = a->top + shift_words + 1;
if (count < shift_words)
return 0;
if (!bn_wexpand(r, count))
return 0;
src = a->d + a->top - 1;
dst = r->d + a->top + shift_words;
/* Handle right shift for top most word. */
*dst = (*src >> rshift) & rstride;
dst--;
/* Handle left shift and right shift for remaining words. */
while (src > a->d) {
*dst = *src << lshift | src[rstride] >> rshift;
src--;
dst--;
}
*dst = *src << lshift;
/* Zero any additional words resulting from the left shift. */
while (dst > r->d) {
dst--;
*dst = 0;
}
r->top = count;
bn_correct_top(r);
BN_set_negative(r, a->neg);
return 1;
}
static inline int
bn_rshift(BIGNUM *r, const BIGNUM *a, int n)
{
size_t count, shift_bits, shift_words;
size_t lshift, rshift;
ssize_t lstride;
BN_ULONG *dst, *src;
size_t i;
if (n < 0) {
BNerror(BN_R_INVALID_LENGTH);
return 0;
}
shift_bits = n;
/*
* Right bit shift, potentially across word boundaries.
*
* When shift is not an exact multiple of BN_BITS2, the top bits of
* the next word need to be left shifted and combined with the right
* shifted bits using bitwise OR. If shift is an exact multiple of
* BN_BITS2, the source for the left and right shifts are the same
* and the shifts become zero (which is effectively a memmove).
*/
shift_words = shift_bits / BN_BITS2;
rshift = shift_bits % BN_BITS2;
lshift = (BN_BITS2 - rshift) % BN_BITS2;
lstride = (lshift + rshift) / BN_BITS2;
if (a->top <= shift_words) {
BN_zero(r);
return 1;
}
count = a->top - shift_words;
if (!bn_wexpand(r, count))
return 0;
src = a->d + shift_words;
dst = r->d;
for (i = 1; i < count; i++) {
*dst = src[lstride] << lshift | *src >> rshift;
src++;
dst++;
}
*dst = *src >> rshift;
r->top = count;
bn_correct_top(r);
BN_set_negative(r, a->neg);
return 1;
}
int
BN_lshift1(BIGNUM *r, const BIGNUM *a)
{
return bn_lshift(r, a, 1);
}
int
BN_lshift(BIGNUM *r, const BIGNUM *a, int n)
{
return bn_lshift(r, a, n);
}
int
BN_rshift1(BIGNUM *r, const BIGNUM *a)
{
return bn_rshift(r, a, 1);
}
int
BN_rshift(BIGNUM *r, const BIGNUM *a, int n)
{
return bn_rshift(r, a, n);
}

View File

@@ -0,0 +1,265 @@
/* $OpenBSD: bn_small_primes.c,v 1.1 2022/11/09 22:52:51 tb Exp $ */
/*
* Public domain, generated by bn_prime.pl.
*/
#include "bn_prime.h"
const uint16_t primes[NUMPRIMES] = {
2, 3, 5, 7, 11, 13, 17, 19,
23, 29, 31, 37, 41, 43, 47, 53,
59, 61, 67, 71, 73, 79, 83, 89,
97, 101, 103, 107, 109, 113, 127, 131,
137, 139, 149, 151, 157, 163, 167, 173,
179, 181, 191, 193, 197, 199, 211, 223,
227, 229, 233, 239, 241, 251, 257, 263,
269, 271, 277, 281, 283, 293, 307, 311,
313, 317, 331, 337, 347, 349, 353, 359,
367, 373, 379, 383, 389, 397, 401, 409,
419, 421, 431, 433, 439, 443, 449, 457,
461, 463, 467, 479, 487, 491, 499, 503,
509, 521, 523, 541, 547, 557, 563, 569,
571, 577, 587, 593, 599, 601, 607, 613,
617, 619, 631, 641, 643, 647, 653, 659,
661, 673, 677, 683, 691, 701, 709, 719,
727, 733, 739, 743, 751, 757, 761, 769,
773, 787, 797, 809, 811, 821, 823, 827,
829, 839, 853, 857, 859, 863, 877, 881,
883, 887, 907, 911, 919, 929, 937, 941,
947, 953, 967, 971, 977, 983, 991, 997,
1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049,
1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097,
1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163,
1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,
1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283,
1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321,
1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423,
1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459,
1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571,
1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619,
1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693,
1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747,
1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877,
1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949,
1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003,
2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069,
2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129,
2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203,
2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267,
2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311,
2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377,
2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423,
2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503,
2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579,
2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657,
2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693,
2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741,
2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801,
2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861,
2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939,
2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011,
3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079,
3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167,
3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221,
3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301,
3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347,
3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413,
3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491,
3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541,
3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607,
3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671,
3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727,
3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797,
3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863,
3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923,
3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003,
4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057,
4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129,
4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211,
4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259,
4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337,
4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409,
4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481,
4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547,
4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621,
4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673,
4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751,
4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813,
4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909,
4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967,
4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011,
5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087,
5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167,
5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233,
5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309,
5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399,
5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443,
5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507,
5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573,
5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653,
5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711,
5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849,
5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897,
5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007,
6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073,
6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133,
6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211,
6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271,
6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329,
6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379,
6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563,
6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637,
6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701,
6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779,
6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833,
6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907,
6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971,
6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027,
7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121,
7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207,
7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253,
7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349,
7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457,
7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517,
7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561,
7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621,
7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691,
7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757,
7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853,
7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919,
7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009,
8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087,
8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161,
8167, 8171, 8179, 8191, 8209, 8219, 8221, 8231,
8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291,
8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369,
8377, 8387, 8389, 8419, 8423, 8429, 8431, 8443,
8447, 8461, 8467, 8501, 8513, 8521, 8527, 8537,
8539, 8543, 8563, 8573, 8581, 8597, 8599, 8609,
8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677,
8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731,
8737, 8741, 8747, 8753, 8761, 8779, 8783, 8803,
8807, 8819, 8821, 8831, 8837, 8839, 8849, 8861,
8863, 8867, 8887, 8893, 8923, 8929, 8933, 8941,
8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011,
9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091,
9103, 9109, 9127, 9133, 9137, 9151, 9157, 9161,
9173, 9181, 9187, 9199, 9203, 9209, 9221, 9227,
9239, 9241, 9257, 9277, 9281, 9283, 9293, 9311,
9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377,
9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433,
9437, 9439, 9461, 9463, 9467, 9473, 9479, 9491,
9497, 9511, 9521, 9533, 9539, 9547, 9551, 9587,
9601, 9613, 9619, 9623, 9629, 9631, 9643, 9649,
9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733,
9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791,
9803, 9811, 9817, 9829, 9833, 9839, 9851, 9857,
9859, 9871, 9883, 9887, 9901, 9907, 9923, 9929,
9931, 9941, 9949, 9967, 9973, 10007, 10009, 10037,
10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099,
10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163,
10169, 10177, 10181, 10193, 10211, 10223, 10243, 10247,
10253, 10259, 10267, 10271, 10273, 10289, 10301, 10303,
10313, 10321, 10331, 10333, 10337, 10343, 10357, 10369,
10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459,
10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531,
10559, 10567, 10589, 10597, 10601, 10607, 10613, 10627,
10631, 10639, 10651, 10657, 10663, 10667, 10687, 10691,
10709, 10711, 10723, 10729, 10733, 10739, 10753, 10771,
10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859,
10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937,
10939, 10949, 10957, 10973, 10979, 10987, 10993, 11003,
11027, 11047, 11057, 11059, 11069, 11071, 11083, 11087,
11093, 11113, 11117, 11119, 11131, 11149, 11159, 11161,
11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251,
11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317,
11321, 11329, 11351, 11353, 11369, 11383, 11393, 11399,
11411, 11423, 11437, 11443, 11447, 11467, 11471, 11483,
11489, 11491, 11497, 11503, 11519, 11527, 11549, 11551,
11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657,
11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731,
11743, 11777, 11779, 11783, 11789, 11801, 11807, 11813,
11821, 11827, 11831, 11833, 11839, 11863, 11867, 11887,
11897, 11903, 11909, 11923, 11927, 11933, 11939, 11941,
11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011,
12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101,
12107, 12109, 12113, 12119, 12143, 12149, 12157, 12161,
12163, 12197, 12203, 12211, 12227, 12239, 12241, 12251,
12253, 12263, 12269, 12277, 12281, 12289, 12301, 12323,
12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401,
12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473,
12479, 12487, 12491, 12497, 12503, 12511, 12517, 12527,
12539, 12541, 12547, 12553, 12569, 12577, 12583, 12589,
12601, 12611, 12613, 12619, 12637, 12641, 12647, 12653,
12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739,
12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821,
12823, 12829, 12841, 12853, 12889, 12893, 12899, 12907,
12911, 12917, 12919, 12923, 12941, 12953, 12959, 12967,
12973, 12979, 12983, 13001, 13003, 13007, 13009, 13033,
13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109,
13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177,
13183, 13187, 13217, 13219, 13229, 13241, 13249, 13259,
13267, 13291, 13297, 13309, 13313, 13327, 13331, 13337,
13339, 13367, 13381, 13397, 13399, 13411, 13417, 13421,
13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499,
13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597,
13613, 13619, 13627, 13633, 13649, 13669, 13679, 13681,
13687, 13691, 13693, 13697, 13709, 13711, 13721, 13723,
13729, 13751, 13757, 13759, 13763, 13781, 13789, 13799,
13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879,
13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933,
13963, 13967, 13997, 13999, 14009, 14011, 14029, 14033,
14051, 14057, 14071, 14081, 14083, 14087, 14107, 14143,
14149, 14153, 14159, 14173, 14177, 14197, 14207, 14221,
14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323,
14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407,
14411, 14419, 14423, 14431, 14437, 14447, 14449, 14461,
14479, 14489, 14503, 14519, 14533, 14537, 14543, 14549,
14551, 14557, 14561, 14563, 14591, 14593, 14621, 14627,
14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699,
14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753,
14759, 14767, 14771, 14779, 14783, 14797, 14813, 14821,
14827, 14831, 14843, 14851, 14867, 14869, 14879, 14887,
14891, 14897, 14923, 14929, 14939, 14947, 14951, 14957,
14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073,
15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137,
15139, 15149, 15161, 15173, 15187, 15193, 15199, 15217,
15227, 15233, 15241, 15259, 15263, 15269, 15271, 15277,
15287, 15289, 15299, 15307, 15313, 15319, 15329, 15331,
15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401,
15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473,
15493, 15497, 15511, 15527, 15541, 15551, 15559, 15569,
15581, 15583, 15601, 15607, 15619, 15629, 15641, 15643,
15647, 15649, 15661, 15667, 15671, 15679, 15683, 15727,
15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773,
15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859,
15877, 15881, 15887, 15889, 15901, 15907, 15913, 15919,
15923, 15937, 15959, 15971, 15973, 15991, 16001, 16007,
16033, 16057, 16061, 16063, 16067, 16069, 16073, 16087,
16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183,
16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249,
16253, 16267, 16273, 16301, 16319, 16333, 16339, 16349,
16361, 16363, 16369, 16381, 16411, 16417, 16421, 16427,
16433, 16447, 16451, 16453, 16477, 16481, 16487, 16493,
16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603,
16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661,
16673, 16691, 16693, 16699, 16703, 16729, 16741, 16747,
16759, 16763, 16787, 16811, 16823, 16829, 16831, 16843,
16871, 16879, 16883, 16889, 16901, 16903, 16921, 16927,
16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993,
17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053,
17077, 17093, 17099, 17107, 17117, 17123, 17137, 17159,
17167, 17183, 17189, 17191, 17203, 17207, 17209, 17231,
17239, 17257, 17291, 17293, 17299, 17317, 17321, 17327,
17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389,
17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467,
17471, 17477, 17483, 17489, 17491, 17497, 17509, 17519,
17539, 17551, 17569, 17573, 17579, 17581, 17597, 17599,
17609, 17623, 17627, 17657, 17659, 17669, 17681, 17683,
17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783,
17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863,
};

309
externals/libressl/crypto/bn/bn_sqr.c vendored Normal file
View File

@@ -0,0 +1,309 @@
/* $OpenBSD: bn_sqr.c,v 1.30 2023/04/19 10:51:22 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "bn_arch.h"
#include "bn_local.h"
#include "bn_internal.h"
int bn_sqr(BIGNUM *r, const BIGNUM *a, int max, BN_CTX *ctx);
/*
* bn_sqr_comba4() computes r[] = a[] * a[] using Comba multiplication
* (https://everything2.com/title/Comba+multiplication), where a is a
* four word array, producing an eight word array result.
*/
#ifndef HAVE_BN_SQR_COMBA4
void
bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a)
{
BN_ULONG c2, c1, c0;
bn_mulw_addtw(a[0], a[0], 0, 0, 0, &c2, &c1, &r[0]);
bn_mul2_mulw_addtw(a[1], a[0], 0, c2, c1, &c2, &c1, &r[1]);
bn_mulw_addtw(a[1], a[1], 0, c2, c1, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[2], a[0], c2, c1, c0, &c2, &c1, &r[2]);
bn_mul2_mulw_addtw(a[3], a[0], 0, c2, c1, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[2], a[1], c2, c1, c0, &c2, &c1, &r[3]);
bn_mulw_addtw(a[2], a[2], 0, c2, c1, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[3], a[1], c2, c1, c0, &c2, &c1, &r[4]);
bn_mul2_mulw_addtw(a[3], a[2], 0, c2, c1, &c2, &c1, &r[5]);
bn_mulw_addtw(a[3], a[3], 0, c2, c1, &c2, &r[7], &r[6]);
}
#endif
/*
* bn_sqr_comba8() computes r[] = a[] * a[] using Comba multiplication
* (https://everything2.com/title/Comba+multiplication), where a is an
* eight word array, producing an 16 word array result.
*/
#ifndef HAVE_BN_SQR_COMBA8
void
bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a)
{
BN_ULONG c2, c1, c0;
bn_mulw_addtw(a[0], a[0], 0, 0, 0, &c2, &c1, &r[0]);
bn_mul2_mulw_addtw(a[1], a[0], 0, c2, c1, &c2, &c1, &r[1]);
bn_mulw_addtw(a[1], a[1], 0, c2, c1, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[2], a[0], c2, c1, c0, &c2, &c1, &r[2]);
bn_mul2_mulw_addtw(a[3], a[0], 0, c2, c1, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[2], a[1], c2, c1, c0, &c2, &c1, &r[3]);
bn_mulw_addtw(a[2], a[2], 0, c2, c1, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[3], a[1], c2, c1, c0, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[4], a[0], c2, c1, c0, &c2, &c1, &r[4]);
bn_mul2_mulw_addtw(a[5], a[0], 0, c2, c1, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[4], a[1], c2, c1, c0, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[3], a[2], c2, c1, c0, &c2, &c1, &r[5]);
bn_mulw_addtw(a[3], a[3], 0, c2, c1, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[4], a[2], c2, c1, c0, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[5], a[1], c2, c1, c0, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[6], a[0], c2, c1, c0, &c2, &c1, &r[6]);
bn_mul2_mulw_addtw(a[7], a[0], 0, c2, c1, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[6], a[1], c2, c1, c0, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[5], a[2], c2, c1, c0, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[4], a[3], c2, c1, c0, &c2, &c1, &r[7]);
bn_mulw_addtw(a[4], a[4], 0, c2, c1, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[5], a[3], c2, c1, c0, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[6], a[2], c2, c1, c0, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[7], a[1], c2, c1, c0, &c2, &c1, &r[8]);
bn_mul2_mulw_addtw(a[7], a[2], 0, c2, c1, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[6], a[3], c2, c1, c0, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[5], a[4], c2, c1, c0, &c2, &c1, &r[9]);
bn_mulw_addtw(a[5], a[5], 0, c2, c1, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[6], a[4], c2, c1, c0, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[7], a[3], c2, c1, c0, &c2, &c1, &r[10]);
bn_mul2_mulw_addtw(a[7], a[4], 0, c2, c1, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[6], a[5], c2, c1, c0, &c2, &c1, &r[11]);
bn_mulw_addtw(a[6], a[6], 0, c2, c1, &c2, &c1, &c0);
bn_mul2_mulw_addtw(a[7], a[5], c2, c1, c0, &c2, &c1, &r[12]);
bn_mul2_mulw_addtw(a[7], a[6], 0, c2, c1, &c2, &c1, &r[13]);
bn_mulw_addtw(a[7], a[7], 0, c2, c1, &c2, &r[15], &r[14]);
}
#endif
#ifndef HAVE_BN_SQR_WORDS
/*
* bn_sqr_words() computes (r[i*2+1]:r[i*2]) = a[i] * a[i].
*/
void
bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n)
{
assert(n >= 0);
if (n <= 0)
return;
#ifndef OPENSSL_SMALL_FOOTPRINT
while (n & ~3) {
bn_mulw(a[0], a[0], &r[1], &r[0]);
bn_mulw(a[1], a[1], &r[3], &r[2]);
bn_mulw(a[2], a[2], &r[5], &r[4]);
bn_mulw(a[3], a[3], &r[7], &r[6]);
a += 4;
r += 8;
n -= 4;
}
#endif
while (n) {
bn_mulw(a[0], a[0], &r[1], &r[0]);
a++;
r += 2;
n--;
}
}
#endif
/* tmp must have 2*n words */
void
bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, int n, BN_ULONG *tmp)
{
int i, j, max;
const BN_ULONG *ap;
BN_ULONG *rp;
max = n * 2;
ap = a;
rp = r;
rp[0] = rp[max - 1] = 0;
rp++;
j = n;
if (--j > 0) {
ap++;
rp[j] = bn_mul_words(rp, ap, j, ap[-1]);
rp += 2;
}
for (i = n - 2; i > 0; i--) {
j--;
ap++;
rp[j] = bn_mul_add_words(rp, ap, j, ap[-1]);
rp += 2;
}
bn_add_words(r, r, r, max);
/* There will not be a carry */
bn_sqr_words(tmp, a, n);
bn_add_words(r, r, tmp, max);
}
/*
* bn_sqr() computes a * a, storing the result in r. The caller must ensure that
* r is not the same BIGNUM as a and that r has been expanded to rn = a->top * 2
* words.
*/
#ifndef HAVE_BN_SQR
int
bn_sqr(BIGNUM *r, const BIGNUM *a, int rn, BN_CTX *ctx)
{
BIGNUM *tmp;
int ret = 0;
BN_CTX_start(ctx);
if ((tmp = BN_CTX_get(ctx)) == NULL)
goto err;
if (!bn_wexpand(tmp, rn))
goto err;
bn_sqr_normal(r->d, a->d, a->top, tmp->d);
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
#endif
int
BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
{
BIGNUM *rr;
int rn;
int ret = 1;
BN_CTX_start(ctx);
if (BN_is_zero(a)) {
BN_zero(r);
goto done;
}
if ((rr = r) == a)
rr = BN_CTX_get(ctx);
if (rr == NULL)
goto err;
rn = a->top * 2;
if (rn < a->top)
goto err;
if (!bn_wexpand(rr, rn))
goto err;
if (a->top == 4) {
bn_sqr_comba4(rr->d, a->d);
} else if (a->top == 8) {
bn_sqr_comba8(rr->d, a->d);
} else {
if (!bn_sqr(rr, a, rn, ctx))
goto err;
}
rr->top = rn;
bn_correct_top(rr);
rr->neg = 0;
if (!bn_copy(r, rr))
goto err;
done:
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}

240
externals/libressl/crypto/bn/bn_word.c vendored Normal file
View File

@@ -0,0 +1,240 @@
/* $OpenBSD: bn_word.c,v 1.20 2023/03/11 14:14:54 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "bn_local.h"
BN_ULONG
BN_mod_word(const BIGNUM *a, BN_ULONG w)
{
#ifndef BN_LLONG
BN_ULONG ret = 0;
#else
BN_ULLONG ret = 0;
#endif
int i;
if (w == 0)
return (BN_ULONG) - 1;
#ifndef BN_ULLONG
/* If |w| is too long and we don't have |BN_ULLONG| then we need to fall back
* to using |BN_div_word|. */
if (w > ((BN_ULONG)1 << BN_BITS4)) {
BIGNUM *tmp = BN_dup(a);
if (tmp == NULL) {
return (BN_ULONG)-1;
}
ret = BN_div_word(tmp, w);
BN_free(tmp);
return ret;
}
#endif
w &= BN_MASK2;
for (i = a->top - 1; i >= 0; i--) {
#ifndef BN_LLONG
ret = ((ret << BN_BITS4) | ((a->d[i] >> BN_BITS4) &
BN_MASK2l)) % w;
ret = ((ret << BN_BITS4) | (a->d[i] & BN_MASK2l)) % w;
#else
ret = (BN_ULLONG)(((ret << (BN_ULLONG)BN_BITS2) |
a->d[i]) % (BN_ULLONG)w);
#endif
}
return ((BN_ULONG)ret);
}
BN_ULONG
BN_div_word(BIGNUM *a, BN_ULONG w)
{
BN_ULONG ret = 0;
int i, j;
w &= BN_MASK2;
if (!w)
/* actually this an error (division by zero) */
return (BN_ULONG) - 1;
if (a->top == 0)
return 0;
/* normalize input (so bn_div_words doesn't complain) */
j = BN_BITS2 - BN_num_bits_word(w);
w <<= j;
if (!BN_lshift(a, a, j))
return (BN_ULONG) - 1;
for (i = a->top - 1; i >= 0; i--) {
BN_ULONG l, d;
l = a->d[i];
bn_div_rem_words(ret, l, w, &d, &ret);
a->d[i] = d;
}
if ((a->top > 0) && (a->d[a->top - 1] == 0))
a->top--;
ret >>= j;
/* Set negative again, to handle -0 case. */
BN_set_negative(a, a->neg);
return (ret);
}
int
BN_add_word(BIGNUM *a, BN_ULONG w)
{
BN_ULONG l;
int i;
w &= BN_MASK2;
/* degenerate case: w is zero */
if (!w)
return 1;
/* degenerate case: a is zero */
if (BN_is_zero(a))
return BN_set_word(a, w);
/* handle 'a' when negative */
if (a->neg) {
a->neg = 0;
i = BN_sub_word(a, w);
BN_set_negative(a, !a->neg);
return (i);
}
for (i = 0; w != 0 && i < a->top; i++) {
a->d[i] = l = (a->d[i] + w) & BN_MASK2;
w = (w > l) ? 1 : 0;
}
if (w && i == a->top) {
if (!bn_wexpand(a, a->top + 1))
return 0;
a->top++;
a->d[i] = w;
}
return (1);
}
int
BN_sub_word(BIGNUM *a, BN_ULONG w)
{
int i;
w &= BN_MASK2;
/* degenerate case: w is zero */
if (!w)
return 1;
/* degenerate case: a is zero */
if (BN_is_zero(a)) {
i = BN_set_word(a, w);
if (i != 0)
BN_set_negative(a, 1);
return i;
}
/* handle 'a' when negative */
if (a->neg) {
a->neg = 0;
i = BN_add_word(a, w);
BN_set_negative(a, !a->neg);
return (i);
}
if ((a->top == 1) && (a->d[0] < w)) {
a->d[0] = w - a->d[0];
BN_set_negative(a, 1);
return (1);
}
i = 0;
for (;;) {
if (a->d[i] >= w) {
a->d[i] -= w;
break;
} else {
a->d[i] = (a->d[i] - w) & BN_MASK2;
i++;
w = 1;
}
}
if ((a->d[i] == 0) && (i == (a->top - 1)))
a->top--;
return (1);
}
int
BN_mul_word(BIGNUM *a, BN_ULONG w)
{
BN_ULONG ll;
w &= BN_MASK2;
if (a->top) {
if (w == 0)
BN_zero(a);
else {
ll = bn_mul_words(a->d, a->d, a->top, w);
if (ll) {
if (!bn_wexpand(a, a->top + 1))
return (0);
a->d[a->top++] = ll;
}
}
}
return (1);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,148 @@
.text
.global bn_mul_mont
.type bn_mul_mont,%function
.align 2
bn_mul_mont:
stmdb sp!,{r0,r2} @ sp points at argument block
ldr r0,[sp,#3*4] @ load num
cmp r0,#2
movlt r0,#0
addlt sp,sp,#2*4
blt .Labrt
stmdb sp!,{r4-r12,lr} @ save 10 registers
mov r0,r0,lsl#2 @ rescale r0 for byte count
sub sp,sp,r0 @ alloca(4*num)
sub sp,sp,#4 @ +extra dword
sub r0,r0,#4 @ "num=num-1"
add r4,r2,r0 @ &bp[num-1]
add r0,sp,r0 @ r0 to point at &tp[num-1]
ldr r8,[r0,#14*4] @ &n0
ldr r2,[r2] @ bp[0]
ldr r5,[r1],#4 @ ap[0],ap++
ldr r6,[r3],#4 @ np[0],np++
ldr r8,[r8] @ *n0
str r4,[r0,#15*4] @ save &bp[num]
umull r10,r11,r5,r2 @ ap[0]*bp[0]
str r8,[r0,#14*4] @ save n0 value
mul r8,r10,r8 @ "tp[0]"*n0
mov r12,#0
umlal r10,r12,r6,r8 @ np[0]*n0+"t[0]"
mov r4,sp
.L1st:
ldr r5,[r1],#4 @ ap[j],ap++
mov r10,r11
ldr r6,[r3],#4 @ np[j],np++
mov r11,#0
umlal r10,r11,r5,r2 @ ap[j]*bp[0]
mov r14,#0
umlal r12,r14,r6,r8 @ np[j]*n0
adds r12,r12,r10
str r12,[r4],#4 @ tp[j-1]=,tp++
adc r12,r14,#0
cmp r4,r0
bne .L1st
adds r12,r12,r11
ldr r4,[r0,#13*4] @ restore bp
mov r14,#0
ldr r8,[r0,#14*4] @ restore n0
adc r14,r14,#0
str r12,[r0] @ tp[num-1]=
str r14,[r0,#4] @ tp[num]=
.Louter:
sub r7,r0,sp @ "original" r0-1 value
sub r1,r1,r7 @ "rewind" ap to &ap[1]
ldr r2,[r4,#4]! @ *(++bp)
sub r3,r3,r7 @ "rewind" np to &np[1]
ldr r5,[r1,#-4] @ ap[0]
ldr r10,[sp] @ tp[0]
ldr r6,[r3,#-4] @ np[0]
ldr r7,[sp,#4] @ tp[1]
mov r11,#0
umlal r10,r11,r5,r2 @ ap[0]*bp[i]+tp[0]
str r4,[r0,#13*4] @ save bp
mul r8,r10,r8
mov r12,#0
umlal r10,r12,r6,r8 @ np[0]*n0+"tp[0]"
mov r4,sp
.Linner:
ldr r5,[r1],#4 @ ap[j],ap++
adds r10,r11,r7 @ +=tp[j]
ldr r6,[r3],#4 @ np[j],np++
mov r11,#0
umlal r10,r11,r5,r2 @ ap[j]*bp[i]
mov r14,#0
umlal r12,r14,r6,r8 @ np[j]*n0
adc r11,r11,#0
ldr r7,[r4,#8] @ tp[j+1]
adds r12,r12,r10
str r12,[r4],#4 @ tp[j-1]=,tp++
adc r12,r14,#0
cmp r4,r0
bne .Linner
adds r12,r12,r11
mov r14,#0
ldr r4,[r0,#13*4] @ restore bp
adc r14,r14,#0
ldr r8,[r0,#14*4] @ restore n0
adds r12,r12,r7
ldr r7,[r0,#15*4] @ restore &bp[num]
adc r14,r14,#0
str r12,[r0] @ tp[num-1]=
str r14,[r0,#4] @ tp[num]=
cmp r4,r7
bne .Louter
ldr r2,[r0,#12*4] @ pull rp
add r0,r0,#4 @ r0 to point at &tp[num]
sub r5,r0,sp @ "original" num value
mov r4,sp @ "rewind" r4
mov r1,r4 @ "borrow" r1
sub r3,r3,r5 @ "rewind" r3 to &np[0]
subs r7,r7,r7 @ "clear" carry flag
.Lsub: ldr r7,[r4],#4
ldr r6,[r3],#4
sbcs r7,r7,r6 @ tp[j]-np[j]
str r7,[r2],#4 @ rp[j]=
teq r4,r0 @ preserve carry
bne .Lsub
sbcs r14,r14,#0 @ upmost carry
mov r4,sp @ "rewind" r4
sub r2,r2,r5 @ "rewind" r2
and r1,r4,r14
bic r3,r2,r14
orr r1,r1,r3 @ ap=borrow?tp:rp
.Lcopy: ldr r7,[r1],#4 @ copy or in-place refresh
str sp,[r4],#4 @ zap tp
str r7,[r2],#4
cmp r4,r0
bne .Lcopy
add sp,r0,#4 @ skip over tp[num+1]
ldmia sp!,{r4-r12,lr} @ restore registers
add sp,sp,#2*4 @ skip over {r0,r2}
mov r0,#1
.Labrt: tst lr,#1
moveq pc,lr @ be binary compatible with V4, yet
.word 0xe12fff1e @ interoperable with Thumb ISA:-)
.size bn_mul_mont,.-bn_mul_mont
.asciz "Montgomery multiplication for ARMv4, CRYPTOGAMS by <appro@openssl.org>"
.align 2
#if defined(HAVE_GNU_STACK)
.section .note.GNU-stack,"",%progbits
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

287
externals/libressl/crypto/bn/mont-mips.S vendored Normal file
View File

@@ -0,0 +1,287 @@
.text
.set noat
.set noreorder
.align 5
.globl bn_mul_mont
.ent bn_mul_mont
bn_mul_mont:
lw $8,16($29)
lw $9,20($29)
slt $1,$9,4
bnez $1,1f
li $2,0
slt $1,$9,17 # on in-order CPU
bnez $1,bn_mul_mont_internal
nop
1: jr $31
li $4,0
.end bn_mul_mont
.align 5
.ent bn_mul_mont_internal
bn_mul_mont_internal:
.frame $30,14*4,$31
.mask 0x40000000|16711680,-4
sub $29,14*4
sw $30,(14-1)*4($29)
sw $23,(14-2)*4($29)
sw $22,(14-3)*4($29)
sw $21,(14-4)*4($29)
sw $20,(14-5)*4($29)
sw $19,(14-6)*4($29)
sw $18,(14-7)*4($29)
sw $17,(14-8)*4($29)
sw $16,(14-9)*4($29)
move $30,$29
.set reorder
lw $8,0($8)
lw $13,0($6) # bp[0]
lw $12,0($5) # ap[0]
lw $14,0($7) # np[0]
sub $29,2*4 # place for two extra words
sll $9,2
li $1,-4096
sub $29,$9
and $29,$1
multu $12,$13
lw $16,4($5)
lw $18,4($7)
mflo $10
mfhi $11
multu $10,$8
mflo $23
multu $16,$13
mflo $16
mfhi $17
multu $14,$23
mflo $24
mfhi $25
multu $18,$23
addu $24,$10
sltu $1,$24,$10
addu $25,$1
mflo $18
mfhi $19
move $15,$29
li $22,2*4
.align 4
.L1st:
.set noreorder
add $12,$5,$22
add $14,$7,$22
lw $12,($12)
lw $14,($14)
multu $12,$13
addu $10,$16,$11
addu $24,$18,$25
sltu $1,$10,$11
sltu $2,$24,$25
addu $11,$17,$1
addu $25,$19,$2
mflo $16
mfhi $17
addu $24,$10
sltu $1,$24,$10
multu $14,$23
addu $25,$1
addu $22,4
sw $24,($15)
sltu $2,$22,$9
mflo $18
mfhi $19
bnez $2,.L1st
add $15,4
.set reorder
addu $10,$16,$11
sltu $1,$10,$11
addu $11,$17,$1
addu $24,$18,$25
sltu $2,$24,$25
addu $25,$19,$2
addu $24,$10
sltu $1,$24,$10
addu $25,$1
sw $24,($15)
addu $25,$11
sltu $1,$25,$11
sw $25,4($15)
sw $1,2*4($15)
li $21,4
.align 4
.Louter:
add $13,$6,$21
lw $13,($13)
lw $12,($5)
lw $16,4($5)
lw $20,($29)
multu $12,$13
lw $14,($7)
lw $18,4($7)
mflo $10
mfhi $11
addu $10,$20
multu $10,$8
sltu $1,$10,$20
addu $11,$1
mflo $23
multu $16,$13
mflo $16
mfhi $17
multu $14,$23
mflo $24
mfhi $25
multu $18,$23
addu $24,$10
sltu $1,$24,$10
addu $25,$1
mflo $18
mfhi $19
move $15,$29
li $22,2*4
lw $20,4($15)
.align 4
.Linner:
.set noreorder
add $12,$5,$22
add $14,$7,$22
lw $12,($12)
lw $14,($14)
multu $12,$13
addu $10,$16,$11
addu $24,$18,$25
sltu $1,$10,$11
sltu $2,$24,$25
addu $11,$17,$1
addu $25,$19,$2
mflo $16
mfhi $17
addu $10,$20
addu $22,4
multu $14,$23
sltu $1,$10,$20
addu $24,$10
addu $11,$1
sltu $2,$24,$10
lw $20,2*4($15)
addu $25,$2
sltu $1,$22,$9
mflo $18
mfhi $19
sw $24,($15)
bnez $1,.Linner
add $15,4
.set reorder
addu $10,$16,$11
sltu $1,$10,$11
addu $11,$17,$1
addu $10,$20
sltu $2,$10,$20
addu $11,$2
lw $20,2*4($15)
addu $24,$18,$25
sltu $1,$24,$25
addu $25,$19,$1
addu $24,$10
sltu $2,$24,$10
addu $25,$2
sw $24,($15)
addu $24,$25,$11
sltu $25,$24,$11
addu $24,$20
sltu $1,$24,$20
addu $25,$1
sw $24,4($15)
sw $25,2*4($15)
addu $21,4
sltu $2,$21,$9
bnez $2,.Louter
.set noreorder
add $20,$29,$9 # &tp[num]
move $15,$29
move $5,$29
li $11,0 # clear borrow bit
.align 4
.Lsub: lw $10,($15)
lw $24,($7)
add $15,4
add $7,4
subu $24,$10,$24 # tp[i]-np[i]
sgtu $1,$24,$10
subu $10,$24,$11
sgtu $11,$10,$24
sw $10,($4)
or $11,$1
sltu $1,$15,$20
bnez $1,.Lsub
add $4,4
subu $11,$25,$11 # handle upmost overflow bit
move $15,$29
sub $4,$9 # restore rp
not $25,$11
and $5,$11,$29
and $6,$25,$4
or $5,$5,$6 # ap=borrow?tp:rp
.align 4
.Lcopy: lw $12,($5)
add $5,4
sw $0,($15)
add $15,4
sltu $1,$15,$20
sw $12,($4)
bnez $1,.Lcopy
add $4,4
li $4,1
li $2,1
.set noreorder
move $29,$30
lw $30,(14-1)*4($29)
lw $23,(14-2)*4($29)
lw $22,(14-3)*4($29)
lw $21,(14-4)*4($29)
lw $20,(14-5)*4($29)
lw $19,(14-6)*4($29)
lw $18,(14-7)*4($29)
lw $17,(14-8)*4($29)
lw $16,(14-9)*4($29)
jr $31
add $29,14*4
.end bn_mul_mont_internal
.rdata
.asciiz "Montgomery Multiplication for MIPS, CRYPTOGAMS by <appro@openssl.org>"
#if defined(HAVE_GNU_STACK)
.section .note.GNU-stack,"",%progbits
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,856 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// ----------------------------------------------------------------------------
// C prototypes for s2n-bignum functions, so you can use them in C programs via
//
// #include "s2n-bignum.h"
//
// The functions are listed in alphabetical order with a brief description
// in comments for each one. For more detailed documentation see the comment
// banner at the top of the corresponding assembly (.S) file, and
// for the last word in what properties it satisfies see the spec in the
// formal proof (the .ml file in the architecture-specific directory).
//
// For some functions there are additional variants with names ending in
// "_alt". These have the same core mathematical functionality as their
// non-"alt" versions, but can be better suited to some microarchitectures:
//
// - On x86, the "_alt" forms avoid BMI and ADX instruction set
// extensions, so will run on any x86_64 machine, even older ones
//
// - On ARM, the "_alt" forms target machines with higher multiplier
// throughput, generally offering higher performance there.
// ----------------------------------------------------------------------------
// Add, z := x + y
// Inputs x[m], y[n]; outputs function return (carry-out) and z[p]
extern uint64_t bignum_add (uint64_t p, uint64_t *z, uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
// Add modulo p_25519, z := (x + y) mod p_25519, assuming x and y reduced
// Inputs x[4], y[4]; output z[4]
extern void bignum_add_p25519 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
// Add modulo p_256, z := (x + y) mod p_256, assuming x and y reduced
// Inputs x[4], y[4]; output z[4]
extern void bignum_add_p256 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
// Add modulo p_256k1, z := (x + y) mod p_256k1, assuming x and y reduced
// Inputs x[4], y[4]; output z[4]
extern void bignum_add_p256k1 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
// Add modulo p_384, z := (x + y) mod p_384, assuming x and y reduced
// Inputs x[6], y[6]; output z[6]
extern void bignum_add_p384 (uint64_t z[static 6], uint64_t x[static 6], uint64_t y[static 6]);
// Add modulo p_521, z := (x + y) mod p_521, assuming x and y reduced
// Inputs x[9], y[9]; output z[9]
extern void bignum_add_p521 (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]);
// Compute "amontification" constant z :== 2^{128k} (congruent mod m)
// Input m[k]; output z[k]; temporary buffer t[>=k]
extern void bignum_amontifier (uint64_t k, uint64_t *z, uint64_t *m, uint64_t *t);
// Almost-Montgomery multiply, z :== (x * y / 2^{64k}) (congruent mod m)
// Inputs x[k], y[k], m[k]; output z[k]
extern void bignum_amontmul (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y, uint64_t *m);
// Almost-Montgomery reduce, z :== (x' / 2^{64p}) (congruent mod m)
// Inputs x[n], m[k], p; output z[k]
extern void bignum_amontredc (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t *m, uint64_t p);
// Almost-Montgomery square, z :== (x^2 / 2^{64k}) (congruent mod m)
// Inputs x[k], m[k]; output z[k]
extern void bignum_amontsqr (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *m);
// Convert 4-digit (256-bit) bignum to/from big-endian form
// Input x[4]; output z[4]
extern void bignum_bigendian_4 (uint64_t z[static 4], uint64_t x[static 4]);
// Convert 6-digit (384-bit) bignum to/from big-endian form
// Input x[6]; output z[6]
extern void bignum_bigendian_6 (uint64_t z[static 6], uint64_t x[static 6]);
// Select bitfield starting at bit n with length l <= 64
// Inputs x[k], n, l; output function return
extern uint64_t bignum_bitfield (uint64_t k, uint64_t *x, uint64_t n, uint64_t l);
// Return size of bignum in bits
// Input x[k]; output function return
extern uint64_t bignum_bitsize (uint64_t k, uint64_t *x);
// Divide by a single (nonzero) word, z := x / m and return x mod m
// Inputs x[n], m; outputs function return (remainder) and z[k]
extern uint64_t bignum_cdiv (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t m);
// Divide by a single word, z := x / m when known to be exact
// Inputs x[n], m; output z[k]
extern void bignum_cdiv_exact (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t m);
// Count leading zero digits (64-bit words)
// Input x[k]; output function return
extern uint64_t bignum_cld (uint64_t k, uint64_t *x);
// Count leading zero bits
// Input x[k]; output function return
extern uint64_t bignum_clz (uint64_t k, uint64_t *x);
// Multiply-add with single-word multiplier, z := z + c * y
// Inputs c, y[n]; outputs function return (carry-out) and z[k]
extern uint64_t bignum_cmadd (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y);
// Negated multiply-add with single-word multiplier, z := z - c * y
// Inputs c, y[n]; outputs function return (negative carry-out) and z[k]
extern uint64_t bignum_cmnegadd (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y);
// Find modulus of bignum w.r.t. single nonzero word m, returning x mod m
// Input x[k], m; output function return
extern uint64_t bignum_cmod (uint64_t k, uint64_t *x, uint64_t m);
// Multiply by a single word, z := c * y
// Inputs c, y[n]; outputs function return (carry-out) and z[k]
extern uint64_t bignum_cmul (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y);
// Multiply by a single word modulo p_25519, z := (c * x) mod p_25519, assuming x reduced
// Inputs c, x[4]; output z[4]
extern void bignum_cmul_p25519 (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]);
extern void bignum_cmul_p25519_alt (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]);
// Multiply by a single word modulo p_256, z := (c * x) mod p_256, assuming x reduced
// Inputs c, x[4]; output z[4]
extern void bignum_cmul_p256 (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]);
extern void bignum_cmul_p256_alt (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]);
// Multiply by a single word modulo p_256k1, z := (c * x) mod p_256k1, assuming x reduced
// Inputs c, x[4]; output z[4]
extern void bignum_cmul_p256k1 (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]);
extern void bignum_cmul_p256k1_alt (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]);
// Multiply by a single word modulo p_384, z := (c * x) mod p_384, assuming x reduced
// Inputs c, x[6]; output z[6]
extern void bignum_cmul_p384 (uint64_t z[static 6], uint64_t c, uint64_t x[static 6]);
extern void bignum_cmul_p384_alt (uint64_t z[static 6], uint64_t c, uint64_t x[static 6]);
// Multiply by a single word modulo p_521, z := (c * x) mod p_521, assuming x reduced
// Inputs c, x[9]; output z[9]
extern void bignum_cmul_p521 (uint64_t z[static 9], uint64_t c, uint64_t x[static 9]);
extern void bignum_cmul_p521_alt (uint64_t z[static 9], uint64_t c, uint64_t x[static 9]);
// Test bignums for coprimality, gcd(x,y) = 1
// Inputs x[m], y[n]; output function return; temporary buffer t[>=2*max(m,n)]
extern uint64_t bignum_coprime (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y, uint64_t *t);
// Copy bignum with zero-extension or truncation, z := x
// Input x[n]; output z[k]
extern void bignum_copy (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x);
// Count trailing zero digits (64-bit words)
// Input x[k]; output function return
extern uint64_t bignum_ctd (uint64_t k, uint64_t *x);
// Count trailing zero bits
// Input x[k]; output function return
extern uint64_t bignum_ctz (uint64_t k, uint64_t *x);
// Convert from almost-Montgomery form, z := (x / 2^256) mod p_256
// Input x[4]; output z[4]
extern void bignum_deamont_p256 (uint64_t z[static 4], uint64_t x[static 4]);
extern void bignum_deamont_p256_alt (uint64_t z[static 4], uint64_t x[static 4]);
// Convert from almost-Montgomery form, z := (x / 2^256) mod p_256k1
// Input x[4]; output z[4]
extern void bignum_deamont_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
// Convert from almost-Montgomery form, z := (x / 2^384) mod p_384
// Input x[6]; output z[6]
extern void bignum_deamont_p384 (uint64_t z[static 6], uint64_t x[static 6]);
extern void bignum_deamont_p384_alt (uint64_t z[static 6], uint64_t x[static 6]);
// Convert from almost-Montgomery form z := (x / 2^576) mod p_521
// Input x[9]; output z[9]
extern void bignum_deamont_p521 (uint64_t z[static 9], uint64_t x[static 9]);
// Convert from (almost-)Montgomery form z := (x / 2^{64k}) mod m
// Inputs x[k], m[k]; output z[k]
extern void bignum_demont (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *m);
// Convert from Montgomery form z := (x / 2^256) mod p_256, assuming x reduced
// Input x[4]; output z[4]
extern void bignum_demont_p256 (uint64_t z[static 4], uint64_t x[static 4]);
extern void bignum_demont_p256_alt (uint64_t z[static 4], uint64_t x[static 4]);
// Convert from Montgomery form z := (x / 2^256) mod p_256k1, assuming x reduced
// Input x[4]; output z[4]
extern void bignum_demont_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
// Convert from Montgomery form z := (x / 2^384) mod p_384, assuming x reduced
// Input x[6]; output z[6]
extern void bignum_demont_p384 (uint64_t z[static 6], uint64_t x[static 6]);
extern void bignum_demont_p384_alt (uint64_t z[static 6], uint64_t x[static 6]);
// Convert from Montgomery form z := (x / 2^576) mod p_521, assuming x reduced
// Input x[9]; output z[9]
extern void bignum_demont_p521 (uint64_t z[static 9], uint64_t x[static 9]);
// Select digit x[n]
// Inputs x[k], n; output function return
extern uint64_t bignum_digit (uint64_t k, uint64_t *x, uint64_t n);
// Return size of bignum in digits (64-bit word)
// Input x[k]; output function return
extern uint64_t bignum_digitsize (uint64_t k, uint64_t *x);
// Divide bignum by 10: z' := z div 10, returning remainder z mod 10
// Inputs z[k]; outputs function return (remainder) and z[k]
extern uint64_t bignum_divmod10 (uint64_t k, uint64_t *z);
// Double modulo p_25519, z := (2 * x) mod p_25519, assuming x reduced
// Input x[4]; output z[4]
extern void bignum_double_p25519 (uint64_t z[static 4], uint64_t x[static 4]);
// Double modulo p_256, z := (2 * x) mod p_256, assuming x reduced
// Input x[4]; output z[4]
extern void bignum_double_p256 (uint64_t z[static 4], uint64_t x[static 4]);
// Double modulo p_256k1, z := (2 * x) mod p_256k1, assuming x reduced
// Input x[4]; output z[4]
extern void bignum_double_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
// Double modulo p_384, z := (2 * x) mod p_384, assuming x reduced
// Input x[6]; output z[6]
extern void bignum_double_p384 (uint64_t z[static 6], uint64_t x[static 6]);
// Double modulo p_521, z := (2 * x) mod p_521, assuming x reduced
// Input x[9]; output z[9]
extern void bignum_double_p521 (uint64_t z[static 9], uint64_t x[static 9]);
// Extended Montgomery reduce, returning results in input-output buffer
// Inputs z[2*k], m[k], w; outputs function return (extra result bit) and z[2*k]
extern uint64_t bignum_emontredc (uint64_t k, uint64_t *z, uint64_t *m, uint64_t w);
// Extended Montgomery reduce in 8-digit blocks, results in input-output buffer
// Inputs z[2*k], m[k], w; outputs function return (extra result bit) and z[2*k]
extern uint64_t bignum_emontredc_8n (uint64_t k, uint64_t *z, uint64_t *m, uint64_t w);
// Test bignums for equality, x = y
// Inputs x[m], y[n]; output function return
extern uint64_t bignum_eq (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
// Test bignum for even-ness
// Input x[k]; output function return
extern uint64_t bignum_even (uint64_t k, uint64_t *x);
// Convert 4-digit (256-bit) bignum from big-endian bytes
// Input x[32] (bytes); output z[4]
extern void bignum_frombebytes_4 (uint64_t z[static 4], uint8_t x[static 32]);
// Convert 6-digit (384-bit) bignum from big-endian bytes
// Input x[48] (bytes); output z[6]
extern void bignum_frombebytes_6 (uint64_t z[static 6], uint8_t x[static 48]);
// Convert 4-digit (256-bit) bignum from little-endian bytes
// Input x[32] (bytes); output z[4]
extern void bignum_fromlebytes_4 (uint64_t z[static 4], uint8_t x[static 32]);
// Convert 6-digit (384-bit) bignum from little-endian bytes
// Input x[48] (bytes); output z[6]
extern void bignum_fromlebytes_6 (uint64_t z[static 6], uint8_t x[static 48]);
// Convert little-endian bytes to 9-digit 528-bit bignum
// Input x[66] (bytes); output z[9]
extern void bignum_fromlebytes_p521 (uint64_t z[static 9],uint8_t x[static 66]);
// Compare bignums, x >= y
// Inputs x[m], y[n]; output function return
extern uint64_t bignum_ge (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
// Compare bignums, x > y
// Inputs x[m], y[n]; output function return
extern uint64_t bignum_gt (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
// Halve modulo p_256, z := (x / 2) mod p_256, assuming x reduced
// Input x[4]; output z[4]
extern void bignum_half_p256 (uint64_t z[static 4], uint64_t x[static 4]);
// Halve modulo p_256k1, z := (x / 2) mod p_256k1, assuming x reduced
// Input x[4]; output z[4]
extern void bignum_half_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
// Halve modulo p_384, z := (x / 2) mod p_384, assuming x reduced
// Input x[6]; output z[6]
extern void bignum_half_p384 (uint64_t z[static 6], uint64_t x[static 6]);
// Halve modulo p_521, z := (x / 2) mod p_521, assuming x reduced
// Input x[9]; output z[9]
extern void bignum_half_p521 (uint64_t z[static 9], uint64_t x[static 9]);
// Test bignum for zero-ness, x = 0
// Input x[k]; output function return
extern uint64_t bignum_iszero (uint64_t k, uint64_t *x);
// Multiply z := x * y
// Inputs x[16], y[16]; output z[32]; temporary buffer t[>=32]
extern void bignum_kmul_16_32 (uint64_t z[static 32], uint64_t x[static 16], uint64_t y[static 16], uint64_t t[static 32]);
// Multiply z := x * y
// Inputs x[32], y[32]; output z[64]; temporary buffer t[>=96]
extern void bignum_kmul_32_64 (uint64_t z[static 64], uint64_t x[static 32], uint64_t y[static 32], uint64_t t[static 96]);
// Square, z := x^2
// Input x[16]; output z[32]; temporary buffer t[>=24]
extern void bignum_ksqr_16_32 (uint64_t z[static 32], uint64_t x[static 16], uint64_t t[static 24]);
// Square, z := x^2
// Input x[32]; output z[64]; temporary buffer t[>=72]
extern void bignum_ksqr_32_64 (uint64_t z[static 64], uint64_t x[static 32], uint64_t t[static 72]);
// Compare bignums, x <= y
// Inputs x[m], y[n]; output function return
extern uint64_t bignum_le (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
// Convert 4-digit (256-bit) bignum to/from little-endian form
// Input x[4]; output z[4]
extern void bignum_littleendian_4 (uint64_t z[static 4], uint64_t x[static 4]);
// Convert 6-digit (384-bit) bignum to/from little-endian form
// Input x[6]; output z[6]
extern void bignum_littleendian_6 (uint64_t z[static 6], uint64_t x[static 6]);
// Compare bignums, x < y
// Inputs x[m], y[n]; output function return
extern uint64_t bignum_lt (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
// Multiply-add, z := z + x * y
// Inputs x[m], y[n]; outputs function return (carry-out) and z[k]
extern uint64_t bignum_madd (uint64_t k, uint64_t *z, uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
// Reduce modulo group order, z := x mod n_256
// Input x[k]; output z[4]
extern void bignum_mod_n256 (uint64_t z[static 4], uint64_t k, uint64_t *x);
extern void bignum_mod_n256_alt (uint64_t z[static 4], uint64_t k, uint64_t *x);
// Reduce modulo group order, z := x mod n_256
// Input x[4]; output z[4]
extern void bignum_mod_n256_4 (uint64_t z[static 4], uint64_t x[static 4]);
// Reduce modulo group order, z := x mod n_256k1
// Input x[4]; output z[4]
extern void bignum_mod_n256k1_4 (uint64_t z[static 4], uint64_t x[static 4]);
// Reduce modulo group order, z := x mod n_384
// Input x[k]; output z[6]
extern void bignum_mod_n384 (uint64_t z[static 6], uint64_t k, uint64_t *x);
extern void bignum_mod_n384_alt (uint64_t z[static 6], uint64_t k, uint64_t *x);
// Reduce modulo group order, z := x mod n_384
// Input x[6]; output z[6]
extern void bignum_mod_n384_6 (uint64_t z[static 6], uint64_t x[static 6]);
// Reduce modulo group order, z := x mod n_521
// Input x[9]; output z[9]
extern void bignum_mod_n521_9 (uint64_t z[static 9], uint64_t x[static 9]);
extern void bignum_mod_n521_9_alt (uint64_t z[static 9], uint64_t x[static 9]);
// Reduce modulo field characteristic, z := x mod p_25519
// Input x[4]; output z[4]
extern void bignum_mod_p25519_4 (uint64_t z[static 4], uint64_t x[static 4]);
// Reduce modulo field characteristic, z := x mod p_256
// Input x[k]; output z[4]
extern void bignum_mod_p256 (uint64_t z[static 4], uint64_t k, uint64_t *x);
extern void bignum_mod_p256_alt (uint64_t z[static 4], uint64_t k, uint64_t *x);
// Reduce modulo field characteristic, z := x mod p_256
// Input x[4]; output z[4]
extern void bignum_mod_p256_4 (uint64_t z[static 4], uint64_t x[static 4]);
// Reduce modulo field characteristic, z := x mod p_256k1
// Input x[4]; output z[4]
extern void bignum_mod_p256k1_4 (uint64_t z[static 4], uint64_t x[static 4]);
// Reduce modulo field characteristic, z := x mod p_384
// Input x[k]; output z[6]
extern void bignum_mod_p384 (uint64_t z[static 6], uint64_t k, uint64_t *x);
extern void bignum_mod_p384_alt (uint64_t z[static 6], uint64_t k, uint64_t *x);
// Reduce modulo field characteristic, z := x mod p_384
// Input x[6]; output z[6]
extern void bignum_mod_p384_6 (uint64_t z[static 6], uint64_t x[static 6]);
// Reduce modulo field characteristic, z := x mod p_521
// Input x[9]; output z[9]
extern void bignum_mod_p521_9 (uint64_t z[static 9], uint64_t x[static 9]);
// Add modulo m, z := (x + y) mod m, assuming x and y reduced
// Inputs x[k], y[k], m[k]; output z[k]
extern void bignum_modadd (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y, uint64_t *m);
// Double modulo m, z := (2 * x) mod m, assuming x reduced
// Inputs x[k], m[k]; output z[k]
extern void bignum_moddouble (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *m);
// Compute "modification" constant z := 2^{64k} mod m
// Input m[k]; output z[k]; temporary buffer t[>=k]
extern void bignum_modifier (uint64_t k, uint64_t *z, uint64_t *m, uint64_t *t);
// Invert modulo m, z = (1/a) mod b, assuming b is an odd number > 1, a coprime to b
// Inputs a[k], b[k]; output z[k]; temporary buffer t[>=3*k]
extern void bignum_modinv (uint64_t k, uint64_t *z, uint64_t *a, uint64_t *b, uint64_t *t);
// Optionally negate modulo m, z := (-x) mod m (if p nonzero) or z := x (if p zero), assuming x reduced
// Inputs p, x[k], m[k]; output z[k]
extern void bignum_modoptneg (uint64_t k, uint64_t *z, uint64_t p, uint64_t *x, uint64_t *m);
// Subtract modulo m, z := (x - y) mod m, assuming x and y reduced
// Inputs x[k], y[k], m[k]; output z[k]
extern void bignum_modsub (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y, uint64_t *m);
// Compute "montification" constant z := 2^{128k} mod m
// Input m[k]; output z[k]; temporary buffer t[>=k]
extern void bignum_montifier (uint64_t k, uint64_t *z, uint64_t *m, uint64_t *t);
// Montgomery multiply, z := (x * y / 2^{64k}) mod m
// Inputs x[k], y[k], m[k]; output z[k]
extern void bignum_montmul (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y, uint64_t *m);
// Montgomery multiply, z := (x * y / 2^256) mod p_256
// Inputs x[4], y[4]; output z[4]
extern void bignum_montmul_p256 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
extern void bignum_montmul_p256_alt (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
// Montgomery multiply, z := (x * y / 2^256) mod p_256k1
// Inputs x[4], y[4]; output z[4]
extern void bignum_montmul_p256k1 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
extern void bignum_montmul_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
// Montgomery multiply, z := (x * y / 2^384) mod p_384
// Inputs x[6], y[6]; output z[6]
extern void bignum_montmul_p384 (uint64_t z[static 6], uint64_t x[static 6], uint64_t y[static 6]);
extern void bignum_montmul_p384_alt (uint64_t z[static 6], uint64_t x[static 6], uint64_t y[static 6]);
// Montgomery multiply, z := (x * y / 2^576) mod p_521
// Inputs x[9], y[9]; output z[9]
extern void bignum_montmul_p521 (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]);
extern void bignum_montmul_p521_alt (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]);
// Montgomery reduce, z := (x' / 2^{64p}) MOD m
// Inputs x[n], m[k], p; output z[k]
extern void bignum_montredc (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t *m, uint64_t p);
// Montgomery square, z := (x^2 / 2^{64k}) mod m
// Inputs x[k], m[k]; output z[k]
extern void bignum_montsqr (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *m);
// Montgomery square, z := (x^2 / 2^256) mod p_256
// Input x[4]; output z[4]
extern void bignum_montsqr_p256 (uint64_t z[static 4], uint64_t x[static 4]);
extern void bignum_montsqr_p256_alt (uint64_t z[static 4], uint64_t x[static 4]);
// Montgomery square, z := (x^2 / 2^256) mod p_256k1
// Input x[4]; output z[4]
extern void bignum_montsqr_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
extern void bignum_montsqr_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4]);
// Montgomery square, z := (x^2 / 2^384) mod p_384
// Input x[6]; output z[6]
extern void bignum_montsqr_p384 (uint64_t z[static 6], uint64_t x[static 6]);
extern void bignum_montsqr_p384_alt (uint64_t z[static 6], uint64_t x[static 6]);
// Montgomery square, z := (x^2 / 2^576) mod p_521
// Input x[9]; output z[9]
extern void bignum_montsqr_p521 (uint64_t z[static 9], uint64_t x[static 9]);
extern void bignum_montsqr_p521_alt (uint64_t z[static 9], uint64_t x[static 9]);
// Multiply z := x * y
// Inputs x[m], y[n]; output z[k]
extern void bignum_mul (uint64_t k, uint64_t *z, uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
// Multiply z := x * y
// Inputs x[4], y[4]; output z[8]
extern void bignum_mul_4_8 (uint64_t z[static 8], uint64_t x[static 4], uint64_t y[static 4]);
extern void bignum_mul_4_8_alt (uint64_t z[static 8], uint64_t x[static 4], uint64_t y[static 4]);
// Multiply z := x * y
// Inputs x[6], y[6]; output z[12]
extern void bignum_mul_6_12 (uint64_t z[static 12], uint64_t x[static 6], uint64_t y[static 6]);
extern void bignum_mul_6_12_alt (uint64_t z[static 12], uint64_t x[static 6], uint64_t y[static 6]);
// Multiply z := x * y
// Inputs x[8], y[8]; output z[16]
extern void bignum_mul_8_16 (uint64_t z[static 16], uint64_t x[static 8], uint64_t y[static 8]);
extern void bignum_mul_8_16_alt (uint64_t z[static 16], uint64_t x[static 8], uint64_t y[static 8]);
// Multiply modulo p_25519, z := (x * y) mod p_25519
// Inputs x[4], y[4]; output z[4]
extern void bignum_mul_p25519 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
extern void bignum_mul_p25519_alt (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
// Multiply modulo p_256k1, z := (x * y) mod p_256k1
// Inputs x[4], y[4]; output z[4]
extern void bignum_mul_p256k1 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
extern void bignum_mul_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
// Multiply modulo p_521, z := (x * y) mod p_521, assuming x and y reduced
// Inputs x[9], y[9]; output z[9]
extern void bignum_mul_p521 (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]);
extern void bignum_mul_p521_alt (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]);
// Multiply bignum by 10 and add word: z := 10 * z + d
// Inputs z[k], d; outputs function return (carry) and z[k]
extern uint64_t bignum_muladd10 (uint64_t k, uint64_t *z, uint64_t d);
// Multiplex/select z := x (if p nonzero) or z := y (if p zero)
// Inputs p, x[k], y[k]; output z[k]
extern void bignum_mux (uint64_t p, uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y);
// 256-bit multiplex/select z := x (if p nonzero) or z := y (if p zero)
// Inputs p, x[4], y[4]; output z[4]
extern void bignum_mux_4 (uint64_t p, uint64_t z[static 4],uint64_t x[static 4], uint64_t y[static 4]);
// 384-bit multiplex/select z := x (if p nonzero) or z := y (if p zero)
// Inputs p, x[6], y[6]; output z[6]
extern void bignum_mux_6 (uint64_t p, uint64_t z[static 6],uint64_t x[static 6], uint64_t y[static 6]);
// Select element from 16-element table, z := xs[k*i]
// Inputs xs[16*k], i; output z[k]
extern void bignum_mux16 (uint64_t k, uint64_t *z, uint64_t *xs, uint64_t i);
// Negate modulo p_25519, z := (-x) mod p_25519, assuming x reduced
// Input x[4]; output z[4]
extern void bignum_neg_p25519 (uint64_t z[static 4], uint64_t x[static 4]);
// Negate modulo p_256, z := (-x) mod p_256, assuming x reduced
// Input x[4]; output z[4]
extern void bignum_neg_p256 (uint64_t z[static 4], uint64_t x[static 4]);
// Negate modulo p_256k1, z := (-x) mod p_256k1, assuming x reduced
// Input x[4]; output z[4]
extern void bignum_neg_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
// Negate modulo p_384, z := (-x) mod p_384, assuming x reduced
// Input x[6]; output z[6]
extern void bignum_neg_p384 (uint64_t z[static 6], uint64_t x[static 6]);
// Negate modulo p_521, z := (-x) mod p_521, assuming x reduced
// Input x[9]; output z[9]
extern void bignum_neg_p521 (uint64_t z[static 9], uint64_t x[static 9]);
// Negated modular inverse, z := (-1/x) mod 2^{64k}
// Input x[k]; output z[k]
extern void bignum_negmodinv (uint64_t k, uint64_t *z, uint64_t *x);
// Test bignum for nonzero-ness x =/= 0
// Input x[k]; output function return
extern uint64_t bignum_nonzero (uint64_t k, uint64_t *x);
// Test 256-bit bignum for nonzero-ness x =/= 0
// Input x[4]; output function return
extern uint64_t bignum_nonzero_4(uint64_t x[static 4]);
// Test 384-bit bignum for nonzero-ness x =/= 0
// Input x[6]; output function return
extern uint64_t bignum_nonzero_6(uint64_t x[static 6]);
// Normalize bignum in-place by shifting left till top bit is 1
// Input z[k]; outputs function return (bits shifted left) and z[k]
extern uint64_t bignum_normalize (uint64_t k, uint64_t *z);
// Test bignum for odd-ness
// Input x[k]; output function return
extern uint64_t bignum_odd (uint64_t k, uint64_t *x);
// Convert single digit to bignum, z := n
// Input n; output z[k]
extern void bignum_of_word (uint64_t k, uint64_t *z, uint64_t n);
// Optionally add, z := x + y (if p nonzero) or z := x (if p zero)
// Inputs x[k], p, y[k]; outputs function return (carry-out) and z[k]
extern uint64_t bignum_optadd (uint64_t k, uint64_t *z, uint64_t *x, uint64_t p, uint64_t *y);
// Optionally negate, z := -x (if p nonzero) or z := x (if p zero)
// Inputs p, x[k]; outputs function return (nonzero input) and z[k]
extern uint64_t bignum_optneg (uint64_t k, uint64_t *z, uint64_t p, uint64_t *x);
// Optionally negate modulo p_25519, z := (-x) mod p_25519 (if p nonzero) or z := x (if p zero), assuming x reduced
// Inputs p, x[4]; output z[4]
extern void bignum_optneg_p25519 (uint64_t z[static 4], uint64_t p, uint64_t x[static 4]);
// Optionally negate modulo p_256, z := (-x) mod p_256 (if p nonzero) or z := x (if p zero), assuming x reduced
// Inputs p, x[4]; output z[4]
extern void bignum_optneg_p256 (uint64_t z[static 4], uint64_t p, uint64_t x[static 4]);
// Optionally negate modulo p_256k1, z := (-x) mod p_256k1 (if p nonzero) or z := x (if p zero), assuming x reduced
// Inputs p, x[4]; output z[4]
extern void bignum_optneg_p256k1 (uint64_t z[static 4], uint64_t p, uint64_t x[static 4]);
// Optionally negate modulo p_384, z := (-x) mod p_384 (if p nonzero) or z := x (if p zero), assuming x reduced
// Inputs p, x[6]; output z[6]
extern void bignum_optneg_p384 (uint64_t z[static 6], uint64_t p, uint64_t x[static 6]);
// Optionally negate modulo p_521, z := (-x) mod p_521 (if p nonzero) or z := x (if p zero), assuming x reduced
// Inputs p, x[9]; output z[9]
extern void bignum_optneg_p521 (uint64_t z[static 9], uint64_t p, uint64_t x[static 9]);
// Optionally subtract, z := x - y (if p nonzero) or z := x (if p zero)
// Inputs x[k], p, y[k]; outputs function return (carry-out) and z[k]
extern uint64_t bignum_optsub (uint64_t k, uint64_t *z, uint64_t *x, uint64_t p, uint64_t *y);
// Optionally subtract or add, z := x + sgn(p) * y interpreting p as signed
// Inputs x[k], p, y[k]; outputs function return (carry-out) and z[k]
extern uint64_t bignum_optsubadd (uint64_t k, uint64_t *z, uint64_t *x, uint64_t p, uint64_t *y);
// Return bignum of power of 2, z := 2^n
// Input n; output z[k]
extern void bignum_pow2 (uint64_t k, uint64_t *z, uint64_t n);
// Shift bignum left by c < 64 bits z := x * 2^c
// Inputs x[n], c; outputs function return (carry-out) and z[k]
extern uint64_t bignum_shl_small (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t c);
// Shift bignum right by c < 64 bits z := floor(x / 2^c)
// Inputs x[n], c; outputs function return (bits shifted out) and z[k]
extern uint64_t bignum_shr_small (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t c);
// Square, z := x^2
// Input x[n]; output z[k]
extern void bignum_sqr (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x);
// Square, z := x^2
// Input x[4]; output z[8]
extern void bignum_sqr_4_8 (uint64_t z[static 8], uint64_t x[static 4]);
extern void bignum_sqr_4_8_alt (uint64_t z[static 8], uint64_t x[static 4]);
// Square, z := x^2
// Input x[6]; output z[12]
extern void bignum_sqr_6_12 (uint64_t z[static 12], uint64_t x[static 6]);
extern void bignum_sqr_6_12_alt (uint64_t z[static 12], uint64_t x[static 6]);
// Square, z := x^2
// Input x[8]; output z[16]
extern void bignum_sqr_8_16 (uint64_t z[static 16], uint64_t x[static 8]);
extern void bignum_sqr_8_16_alt (uint64_t z[static 16], uint64_t x[static 8]);
// Square modulo p_25519, z := (x^2) mod p_25519
// Input x[4]; output z[4]
extern void bignum_sqr_p25519 (uint64_t z[static 4], uint64_t x[static 4]);
extern void bignum_sqr_p25519_alt (uint64_t z[static 4], uint64_t x[static 4]);
// Square modulo p_256k1, z := (x^2) mod p_256k1
// Input x[4]; output z[4]
extern void bignum_sqr_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
extern void bignum_sqr_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4]);
// Square modulo p_521, z := (x^2) mod p_521, assuming x reduced
// Input x[9]; output z[9]
extern void bignum_sqr_p521 (uint64_t z[static 9], uint64_t x[static 9]);
extern void bignum_sqr_p521_alt (uint64_t z[static 9], uint64_t x[static 9]);
// Subtract, z := x - y
// Inputs x[m], y[n]; outputs function return (carry-out) and z[p]
extern uint64_t bignum_sub (uint64_t p, uint64_t *z, uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
// Subtract modulo p_25519, z := (x - y) mod p_25519, assuming x and y reduced
// Inputs x[4], y[4]; output z[4]
extern void bignum_sub_p25519 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
// Subtract modulo p_256, z := (x - y) mod p_256, assuming x and y reduced
// Inputs x[4], y[4]; output z[4]
extern void bignum_sub_p256 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
// Subtract modulo p_256k1, z := (x - y) mod p_256k1, assuming x and y reduced
// Inputs x[4], y[4]; output z[4]
extern void bignum_sub_p256k1 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
// Subtract modulo p_384, z := (x - y) mod p_384, assuming x and y reduced
// Inputs x[6], y[6]; output z[6]
extern void bignum_sub_p384 (uint64_t z[static 6], uint64_t x[static 6], uint64_t y[static 6]);
// Subtract modulo p_521, z := (x - y) mod p_521, assuming x and y reduced
// Inputs x[9], y[9]; output z[9]
extern void bignum_sub_p521 (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]);
// Convert 4-digit (256-bit) bignum to big-endian bytes
// Input x[4]; output z[32] (bytes)
extern void bignum_tobebytes_4 (uint8_t z[static 32], uint64_t x[static 4]);
// Convert 6-digit (384-bit) bignum to big-endian bytes
// Input x[6]; output z[48] (bytes)
extern void bignum_tobebytes_6 (uint8_t z[static 48], uint64_t x[static 6]);
// Convert 4-digit (256-bit) bignum to little-endian bytes
// Input x[4]; output z[32] (bytes)
extern void bignum_tolebytes_4 (uint8_t z[static 32], uint64_t x[static 4]);
// Convert 6-digit (384-bit) bignum to little-endian bytes
// Input x[6]; output z[48] (bytes)
extern void bignum_tolebytes_6 (uint8_t z[static 48], uint64_t x[static 6]);
// Convert 9-digit 528-bit bignum to little-endian bytes
// Input x[6]; output z[66] (bytes)
extern void bignum_tolebytes_p521 (uint8_t z[static 66], uint64_t x[static 9]);
// Convert to Montgomery form z := (2^256 * x) mod p_256
// Input x[4]; output z[4]
extern void bignum_tomont_p256 (uint64_t z[static 4], uint64_t x[static 4]);
extern void bignum_tomont_p256_alt (uint64_t z[static 4], uint64_t x[static 4]);
// Convert to Montgomery form z := (2^256 * x) mod p_256k1
// Input x[4]; output z[4]
extern void bignum_tomont_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
extern void bignum_tomont_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4]);
// Convert to Montgomery form z := (2^384 * x) mod p_384
// Input x[6]; output z[6]
extern void bignum_tomont_p384 (uint64_t z[static 6], uint64_t x[static 6]);
extern void bignum_tomont_p384_alt (uint64_t z[static 6], uint64_t x[static 6]);
// Convert to Montgomery form z := (2^576 * x) mod p_521
// Input x[9]; output z[9]
extern void bignum_tomont_p521 (uint64_t z[static 9], uint64_t x[static 9]);
// Triple modulo p_256, z := (3 * x) mod p_256
// Input x[4]; output z[4]
extern void bignum_triple_p256 (uint64_t z[static 4], uint64_t x[static 4]);
extern void bignum_triple_p256_alt (uint64_t z[static 4], uint64_t x[static 4]);
// Triple modulo p_256k1, z := (3 * x) mod p_256k1
// Input x[4]; output z[4]
extern void bignum_triple_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
extern void bignum_triple_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4]);
// Triple modulo p_384, z := (3 * x) mod p_384
// Input x[6]; output z[6]
extern void bignum_triple_p384 (uint64_t z[static 6], uint64_t x[static 6]);
extern void bignum_triple_p384_alt (uint64_t z[static 6], uint64_t x[static 6]);
// Triple modulo p_521, z := (3 * x) mod p_521, assuming x reduced
// Input x[9]; output z[9]
extern void bignum_triple_p521 (uint64_t z[static 9], uint64_t x[static 9]);
extern void bignum_triple_p521_alt (uint64_t z[static 9], uint64_t x[static 9]);
// Montgomery ladder step for curve25519
// Inputs point[8], pp[16], b; output rr[16]
extern void curve25519_ladderstep(uint64_t rr[16],uint64_t point[8],uint64_t pp[16],uint64_t b);
extern void curve25519_ladderstep_alt(uint64_t rr[16],uint64_t point[8],uint64_t pp[16],uint64_t b);
// Projective scalar multiplication, x coordinate only, for curve25519
// Inputs scalar[4], point[4]; output res[8]
extern void curve25519_pxscalarmul(uint64_t res[static 8],uint64_t scalar[static 4],uint64_t point[static 4]);
extern void curve25519_pxscalarmul_alt(uint64_t res[static 8],uint64_t scalar[static 4],uint64_t point[static 4]);
// x25519 function for curve25519
// Inputs scalar[4], point[4]; output res[4]
extern void curve25519_x25519(uint64_t res[static 4],uint64_t scalar[static 4],uint64_t point[static 4]);
extern void curve25519_x25519_alt(uint64_t res[static 4],uint64_t scalar[static 4],uint64_t point[static 4]);
// x25519 function for curve25519 on base element 9
// Input scalar[4]; output res[4]
extern void curve25519_x25519base(uint64_t res[static 4],uint64_t scalar[static 4]);
extern void curve25519_x25519base_alt(uint64_t res[static 4],uint64_t scalar[static 4]);
// Extended projective addition for edwards25519
// Inputs p1[16], p2[16]; output p3[16]
extern void edwards25519_epadd(uint64_t p3[static 16],uint64_t p1[static 16],uint64_t p2[static 16]);
extern void edwards25519_epadd_alt(uint64_t p3[static 16],uint64_t p1[static 16],uint64_t p2[static 16]);
// Extended projective doubling for edwards25519
// Inputs p1[12]; output p3[16]
extern void edwards25519_epdouble(uint64_t p3[static 16],uint64_t p1[static 12]);
extern void edwards25519_epdouble_alt(uint64_t p3[static 16],uint64_t p1[static 12]);
// Projective doubling for edwards25519
// Inputs p1[12]; output p3[12]
extern void edwards25519_pdouble(uint64_t p3[static 12],uint64_t p1[static 12]);
extern void edwards25519_pdouble_alt(uint64_t p3[static 12],uint64_t p1[static 12]);
// Extended projective + precomputed mixed addition for edwards25519
// Inputs p1[16], p2[12]; output p3[16]
extern void edwards25519_pepadd(uint64_t p3[static 16],uint64_t p1[static 16],uint64_t p2[static 12]);
extern void edwards25519_pepadd_alt(uint64_t p3[static 16],uint64_t p1[static 16],uint64_t p2[static 12]);
// Point addition on NIST curve P-256 in Montgomery-Jacobian coordinates
// Inputs p1[12], p2[12]; output p3[12]
extern void p256_montjadd(uint64_t p3[static 12],uint64_t p1[static 12],uint64_t p2[static 12]);
// Point doubling on NIST curve P-256 in Montgomery-Jacobian coordinates
// Inputs p1[12]; output p3[12]
extern void p256_montjdouble(uint64_t p3[static 12],uint64_t p1[static 12]);
// Point mixed addition on NIST curve P-256 in Montgomery-Jacobian coordinates
// Inputs p1[12], p2[8]; output p3[12]
extern void p256_montjmixadd(uint64_t p3[static 12],uint64_t p1[static 12],uint64_t p2[static 8]);
// Point addition on NIST curve P-384 in Montgomery-Jacobian coordinates
// Inputs p1[18], p2[18]; output p3[18]
extern void p384_montjadd(uint64_t p3[static 18],uint64_t p1[static 18],uint64_t p2[static 18]);
// Point doubling on NIST curve P-384 in Montgomery-Jacobian coordinates
// Inputs p1[18]; output p3[18]
extern void p384_montjdouble(uint64_t p3[static 18],uint64_t p1[static 18]);
// Point mixed addition on NIST curve P-384 in Montgomery-Jacobian coordinates
// Inputs p1[18], p2[12]; output p3[18]
extern void p384_montjmixadd(uint64_t p3[static 18],uint64_t p1[static 18],uint64_t p2[static 12]);
// Point addition on NIST curve P-521 in Jacobian coordinates
// Inputs p1[27], p2[27]; output p3[27]
extern void p521_jadd(uint64_t p3[static 27],uint64_t p1[static 27],uint64_t p2[static 27]);
// Point doubling on NIST curve P-521 in Jacobian coordinates
// Input p1[27]; output p3[27]
extern void p521_jdouble(uint64_t p3[static 27],uint64_t p1[static 27]);
// Point mixed addition on NIST curve P-521 in Jacobian coordinates
// Inputs p1[27], p2[18]; output p3[27]
extern void p521_jmixadd(uint64_t p3[static 27],uint64_t p1[static 27],uint64_t p2[static 18]);
// Point addition on SECG curve secp256k1 in Jacobian coordinates
// Inputs p1[12], p2[12]; output p3[12]
extern void secp256k1_jadd(uint64_t p3[static 12],uint64_t p1[static 12],uint64_t p2[static 12]);
// Point doubling on SECG curve secp256k1 in Jacobian coordinates
// Input p1[12]; output p3[12]
extern void secp256k1_jdouble(uint64_t p3[static 12],uint64_t p1[static 12]);
// Point mixed addition on SECG curve secp256k1 in Jacobian coordinates
// Inputs p1[12], p2[8]; output p3[12]
extern void secp256k1_jmixadd(uint64_t p3[static 12],uint64_t p1[static 12],uint64_t p2[static 8]);
// Reverse the bytes in a single word
// Input a; output function return
extern uint64_t word_bytereverse (uint64_t a);
// Count leading zero bits in a single word
// Input a; output function return
extern uint64_t word_clz (uint64_t a);
// Count trailing zero bits in a single word
// Input a; output function return
extern uint64_t word_ctz (uint64_t a);
// Return maximum of two unsigned 64-bit words
// Inputs a, b; output function return
extern uint64_t word_max (uint64_t a, uint64_t b);
// Return minimum of two unsigned 64-bit words
// Inputs a, b; output function return
extern uint64_t word_min (uint64_t a, uint64_t b);
// Single-word negated modular inverse (-1/a) mod 2^64
// Input a; output function return
extern uint64_t word_negmodinv (uint64_t a);
// Single-word reciprocal, 2^64 + ret = ceil(2^128/a) - 1 if MSB of "a" is set
// Input a; output function return
extern uint64_t word_recip (uint64_t a);

View File

@@ -0,0 +1,30 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifdef __APPLE__
# define S2N_BN_SYMBOL(NAME) _##NAME
#else
# define S2N_BN_SYMBOL(name) name
#endif
#define S2N_BN_SYM_VISIBILITY_DIRECTIVE(name) .globl S2N_BN_SYMBOL(name)
#ifdef S2N_BN_HIDE_SYMBOLS
# ifdef __APPLE__
# define S2N_BN_SYM_PRIVACY_DIRECTIVE(name) .private_extern S2N_BN_SYMBOL(name)
# else
# define S2N_BN_SYM_PRIVACY_DIRECTIVE(name) .hidden S2N_BN_SYMBOL(name)
# endif
#else
# define S2N_BN_SYM_PRIVACY_DIRECTIVE(name) /* NO-OP: S2N_BN_SYM_PRIVACY_DIRECTIVE */
#endif