mirror of https://github.com/ClassiCube/ClassiCube
Remove more unused BearSSL functions
This commit is contained in:
parent
c24ced908c
commit
9c6895247d
|
|
@ -141,47 +141,4 @@
|
|||
#include "bearssl_x509.h"
|
||||
#include "bearssl_pem.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \brief Type for a configuration option.
|
||||
*
|
||||
* A "configuration option" is a value that is selected when the BearSSL
|
||||
* library itself is compiled. Most options are boolean; their value is
|
||||
* then either 1 (option is enabled) or 0 (option is disabled). Some
|
||||
* values have other integer values. Option names correspond to macro
|
||||
* names. Some of the options can be explicitly set in the internal
|
||||
* `"config.h"` file.
|
||||
*/
|
||||
typedef struct {
|
||||
/** \brief Configurable option name. */
|
||||
const char *name;
|
||||
/** \brief Configurable option value. */
|
||||
long value;
|
||||
} br_config_option;
|
||||
|
||||
/** \brief Get configuration report.
|
||||
*
|
||||
* This function returns compiled configuration options, each as a
|
||||
* 'long' value. Names match internal macro names, in particular those
|
||||
* that can be set in the `"config.h"` inner file. For boolean options,
|
||||
* the numerical value is 1 if enabled, 0 if disabled. For maximum
|
||||
* key sizes, values are expressed in bits.
|
||||
*
|
||||
* The returned array is terminated by an entry whose `name` is `NULL`.
|
||||
*
|
||||
* \return the configuration report.
|
||||
*/
|
||||
const br_config_option *br_get_config(void);
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
/** \brief Version feature: support for time callback. */
|
||||
#define BR_FEATURE_X509_TIME_CALLBACK 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -364,19 +364,9 @@ extern "C" {
|
|||
* construction, where the Poly1305 part is performed with mixed 32-bit
|
||||
* multiplications (operands are 32-bit, result is 64-bit).
|
||||
*
|
||||
* `poly1305_ctmul32` implements ChaCha20+Poly1305 using pure 32-bit
|
||||
* multiplications (32-bit operands, 32-bit result). It is slower than
|
||||
* `poly1305_ctmul`, except on some specific architectures such as
|
||||
* the ARM Cortex M0+.
|
||||
*
|
||||
* `poly1305_ctmulq` implements ChaCha20+Poly1305 with mixed 64-bit
|
||||
* multiplications (operands are 64-bit, result is 128-bit) on 64-bit
|
||||
* platforms that support such operations.
|
||||
*
|
||||
* `poly1305_i15` implements ChaCha20+Poly1305 with the generic "i15"
|
||||
* big integer implementation. It is meant mostly for testing purposes,
|
||||
* although it can help with saving a few hundred bytes of code footprint
|
||||
* on systems where code size is scarce.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
@ -2234,50 +2224,6 @@ void br_poly1305_ctmul_run(const void *key, const void *iv,
|
|||
void *data, size_t len, const void *aad, size_t aad_len,
|
||||
void *tag, br_chacha20_run ichacha, int encrypt);
|
||||
|
||||
/**
|
||||
* \brief ChaCha20+Poly1305 AEAD implementation (pure 32-bit multiplications).
|
||||
*
|
||||
* \see br_poly1305_run
|
||||
*
|
||||
* \param key secret key (32 bytes).
|
||||
* \param iv nonce (12 bytes).
|
||||
* \param data data to encrypt or decrypt.
|
||||
* \param len data length (in bytes).
|
||||
* \param aad additional authenticated data.
|
||||
* \param aad_len length of additional authenticated data (in bytes).
|
||||
* \param tag output buffer for the authentication tag.
|
||||
* \param ichacha implementation of ChaCha20.
|
||||
* \param encrypt non-zero for encryption, zero for decryption.
|
||||
*/
|
||||
void br_poly1305_ctmul32_run(const void *key, const void *iv,
|
||||
void *data, size_t len, const void *aad, size_t aad_len,
|
||||
void *tag, br_chacha20_run ichacha, int encrypt);
|
||||
|
||||
/**
|
||||
* \brief ChaCha20+Poly1305 AEAD implementation (i15).
|
||||
*
|
||||
* This implementation relies on the generic big integer code "i15"
|
||||
* (which uses pure 32-bit multiplications). As such, it may save a
|
||||
* little code footprint in a context where "i15" is already included
|
||||
* (e.g. for elliptic curves or for RSA); however, it is also
|
||||
* substantially slower than the ctmul and ctmul32 implementations.
|
||||
*
|
||||
* \see br_poly1305_run
|
||||
*
|
||||
* \param key secret key (32 bytes).
|
||||
* \param iv nonce (12 bytes).
|
||||
* \param data data to encrypt or decrypt.
|
||||
* \param len data length (in bytes).
|
||||
* \param aad additional authenticated data.
|
||||
* \param aad_len length of additional authenticated data (in bytes).
|
||||
* \param tag output buffer for the authentication tag.
|
||||
* \param ichacha implementation of ChaCha20.
|
||||
* \param encrypt non-zero for encryption, zero for decryption.
|
||||
*/
|
||||
void br_poly1305_i15_run(const void *key, const void *iv,
|
||||
void *data, size_t len, const void *aad, size_t aad_len,
|
||||
void *tag, br_chacha20_run ichacha, int encrypt);
|
||||
|
||||
/**
|
||||
* \brief ChaCha20+Poly1305 AEAD implementation (ctmulq).
|
||||
*
|
||||
|
|
|
|||
|
|
@ -423,25 +423,6 @@ typedef struct {
|
|||
*/
|
||||
extern const br_ec_impl br_ec_prime_i31;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i15".
|
||||
*
|
||||
* This implementation internally uses generic code for modular integers,
|
||||
* with a representation as sequences of 15-bit words. It supports secp256r1,
|
||||
* secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_prime_i15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m15" for P-256.
|
||||
*
|
||||
* This implementation uses specialised code for curve secp256r1 (also
|
||||
* known as NIST P-256), with optional Karatsuba decomposition, and fast
|
||||
* modular reduction thanks to the field modulus special format. Only
|
||||
* 32-bit multiplications are used (with 32-bit results, not 64-bit).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_p256_m15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m31" for P-256.
|
||||
*
|
||||
|
|
@ -487,20 +468,6 @@ extern const br_ec_impl br_ec_p256_m64;
|
|||
*/
|
||||
const br_ec_impl *br_ec_p256_m64_get(void);
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i15" (generic code) for Curve25519.
|
||||
*
|
||||
* This implementation uses the generic code for modular integers (with
|
||||
* 15-bit words) to support Curve25519. Due to the specificities of the
|
||||
* curve definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_i15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i31" (generic code) for Curve25519.
|
||||
*
|
||||
|
|
@ -515,20 +482,6 @@ extern const br_ec_impl br_ec_c25519_i15;
|
|||
*/
|
||||
extern const br_ec_impl br_ec_c25519_i31;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m15" (specialised code) for Curve25519.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 15 bits. Due to the specificities of the curve
|
||||
* definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_m15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m31" (specialised code) for Curve25519.
|
||||
*
|
||||
|
|
@ -591,17 +544,6 @@ extern const br_ec_impl br_ec_c25519_m64;
|
|||
*/
|
||||
const br_ec_impl *br_ec_c25519_m64_get(void);
|
||||
|
||||
/**
|
||||
* \brief Aggregate EC implementation "m15".
|
||||
*
|
||||
* This implementation is a wrapper for:
|
||||
*
|
||||
* - `br_ec_c25519_m15` for Curve25519
|
||||
* - `br_ec_p256_m15` for NIST P-256
|
||||
* - `br_ec_prime_i15` for other curves (NIST P-384 and NIST-P512)
|
||||
*/
|
||||
extern const br_ec_impl br_ec_all_m15;
|
||||
|
||||
/**
|
||||
* \brief Aggregate EC implementation "m31".
|
||||
*
|
||||
|
|
@ -777,72 +719,6 @@ uint32_t br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl,
|
|||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature generator, "i15" implementation, "asn1" format.
|
||||
*
|
||||
* \see br_ecdsa_sign()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_i15_sign_asn1(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature generator, "i15" implementation, "raw" format.
|
||||
*
|
||||
* \see br_ecdsa_sign()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_i15_sign_raw(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature verifier, "i15" implementation, "asn1" format.
|
||||
*
|
||||
* \see br_ecdsa_vrfy()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t br_ecdsa_i15_vrfy_asn1(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature verifier, "i15" implementation, "raw" format.
|
||||
*
|
||||
* \see br_ecdsa_vrfy()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief Get "default" ECDSA implementation (signer, asn1 format).
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1256,22 +1256,6 @@ typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len);
|
|||
*/
|
||||
void br_ghash_ctmul(void *y, const void *h, const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* \brief GHASH implementation using multiplications (strict 32-bit).
|
||||
*
|
||||
* This implementation uses multiplications of 32-bit values, with a
|
||||
* 32-bit result. It is usually somewhat slower than `br_ghash_ctmul()`,
|
||||
* but it is expected to be faster on architectures for which the
|
||||
* 32-bit multiplication opcode does not yield the upper 32 bits of the
|
||||
* product. It is constant-time (if multiplications are constant-time).
|
||||
*
|
||||
* \param y the array to update.
|
||||
* \param h the GHASH key.
|
||||
* \param data the input data (may be `NULL` if `len` is zero).
|
||||
* \param len the input data length (in bytes).
|
||||
*/
|
||||
void br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* \brief GHASH implementation using multiplications (64-bit).
|
||||
*
|
||||
|
|
|
|||
|
|
@ -55,16 +55,6 @@
|
|||
#define BR_64 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_LOMUL is enabled, then multiplications of 32-bit values whose
|
||||
* result are truncated to the low 32 bits are assumed to be
|
||||
* substantially more efficient than 32-bit multiplications that yield
|
||||
* 64-bit results. This is typically the case on low-end ARM Cortex M
|
||||
* systems (M0, M0+, M1, and arguably M3 and M4 as well).
|
||||
*
|
||||
#define BR_LOMUL 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_SLOW_MUL is enabled, multiplications are assumed to be
|
||||
* substantially slow with regards to other integer operations, thus
|
||||
|
|
|
|||
|
|
@ -1,121 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const unsigned char *
|
||||
api_generator(int curve, size_t *len)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return br_ec_p256_m15.generator(curve, len);
|
||||
case BR_EC_curve25519:
|
||||
return br_ec_c25519_m15.generator(curve, len);
|
||||
default:
|
||||
return br_ec_prime_i15.generator(curve, len);
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
api_order(int curve, size_t *len)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return br_ec_p256_m15.order(curve, len);
|
||||
case BR_EC_curve25519:
|
||||
return br_ec_c25519_m15.order(curve, len);
|
||||
default:
|
||||
return br_ec_prime_i15.order(curve, len);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_xoff(int curve, size_t *len)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return br_ec_p256_m15.xoff(curve, len);
|
||||
case BR_EC_curve25519:
|
||||
return br_ec_c25519_m15.xoff(curve, len);
|
||||
default:
|
||||
return br_ec_prime_i15.xoff(curve, len);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_mul(unsigned char *G, size_t Glen,
|
||||
const unsigned char *kb, size_t kblen, int curve)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return br_ec_p256_m15.mul(G, Glen, kb, kblen, curve);
|
||||
case BR_EC_curve25519:
|
||||
return br_ec_c25519_m15.mul(G, Glen, kb, kblen, curve);
|
||||
default:
|
||||
return br_ec_prime_i15.mul(G, Glen, kb, kblen, curve);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_mulgen(unsigned char *R,
|
||||
const unsigned char *x, size_t xlen, int curve)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return br_ec_p256_m15.mulgen(R, x, xlen, curve);
|
||||
case BR_EC_curve25519:
|
||||
return br_ec_c25519_m15.mulgen(R, x, xlen, curve);
|
||||
default:
|
||||
return br_ec_prime_i15.mulgen(R, x, xlen, curve);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_muladd(unsigned char *A, const unsigned char *B, size_t len,
|
||||
const unsigned char *x, size_t xlen,
|
||||
const unsigned char *y, size_t ylen, int curve)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return br_ec_p256_m15.muladd(A, B, len,
|
||||
x, xlen, y, ylen, curve);
|
||||
case BR_EC_curve25519:
|
||||
return br_ec_c25519_m15.muladd(A, B, len,
|
||||
x, xlen, y, ylen, curve);
|
||||
default:
|
||||
return br_ec_prime_i15.muladd(A, B, len,
|
||||
x, xlen, y, ylen, curve);
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
const br_ec_impl br_ec_all_m15 = {
|
||||
(uint32_t)0x23800000,
|
||||
&api_generator,
|
||||
&api_order,
|
||||
&api_xoff,
|
||||
&api_mul,
|
||||
&api_mulgen,
|
||||
&api_muladd
|
||||
};
|
||||
|
|
@ -1,398 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Parameters for the field:
|
||||
* - field modulus p = 2^255-19
|
||||
* - R^2 mod p (R = 2^(15k) for the smallest k such that R >= p)
|
||||
*/
|
||||
|
||||
static const uint16_t C255_P[] = {
|
||||
0x0110,
|
||||
0x7FED, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
|
||||
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
|
||||
0x7FFF
|
||||
};
|
||||
|
||||
#define P0I 0x4A1B
|
||||
|
||||
static const uint16_t C255_R2[] = {
|
||||
0x0110,
|
||||
0x0169, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000
|
||||
};
|
||||
|
||||
/* obsolete
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
static void
|
||||
print_int_mont(const char *name, const uint16_t *x)
|
||||
{
|
||||
uint16_t y[18];
|
||||
unsigned char tmp[32];
|
||||
size_t u;
|
||||
|
||||
printf("%s = ", name);
|
||||
memcpy(y, x, sizeof y);
|
||||
br_i15_from_monty(y, C255_P, P0I);
|
||||
br_i15_encode(tmp, sizeof tmp, y);
|
||||
for (u = 0; u < sizeof tmp; u ++) {
|
||||
printf("%02X", tmp[u]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
*/
|
||||
|
||||
static const uint16_t C255_A24[] = {
|
||||
0x0110,
|
||||
0x45D3, 0x0046, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000
|
||||
};
|
||||
|
||||
static const unsigned char GEN[] = {
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static const unsigned char ORDER[] = {
|
||||
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
static const unsigned char *
|
||||
api_generator(int curve, size_t *len)
|
||||
{
|
||||
(void)curve;
|
||||
*len = 32;
|
||||
return GEN;
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
api_order(int curve, size_t *len)
|
||||
{
|
||||
(void)curve;
|
||||
*len = 32;
|
||||
return ORDER;
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_xoff(int curve, size_t *len)
|
||||
{
|
||||
(void)curve;
|
||||
*len = 32;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
cswap(uint16_t *a, uint16_t *b, uint32_t ctl)
|
||||
{
|
||||
int i;
|
||||
|
||||
ctl = -ctl;
|
||||
for (i = 0; i < 18; i ++) {
|
||||
uint32_t aw, bw, tw;
|
||||
|
||||
aw = a[i];
|
||||
bw = b[i];
|
||||
tw = ctl & (aw ^ bw);
|
||||
a[i] = aw ^ tw;
|
||||
b[i] = bw ^ tw;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
c255_add(uint16_t *d, const uint16_t *a, const uint16_t *b)
|
||||
{
|
||||
uint32_t ctl;
|
||||
uint16_t t[18];
|
||||
|
||||
memcpy(t, a, sizeof t);
|
||||
ctl = br_i15_add(t, b, 1);
|
||||
ctl |= NOT(br_i15_sub(t, C255_P, 0));
|
||||
br_i15_sub(t, C255_P, ctl);
|
||||
memcpy(d, t, sizeof t);
|
||||
}
|
||||
|
||||
static void
|
||||
c255_sub(uint16_t *d, const uint16_t *a, const uint16_t *b)
|
||||
{
|
||||
uint16_t t[18];
|
||||
|
||||
memcpy(t, a, sizeof t);
|
||||
br_i15_add(t, C255_P, br_i15_sub(t, b, 1));
|
||||
memcpy(d, t, sizeof t);
|
||||
}
|
||||
|
||||
static void
|
||||
c255_mul(uint16_t *d, const uint16_t *a, const uint16_t *b)
|
||||
{
|
||||
uint16_t t[18];
|
||||
|
||||
br_i15_montymul(t, a, b, C255_P, P0I);
|
||||
memcpy(d, t, sizeof t);
|
||||
}
|
||||
|
||||
static void
|
||||
byteswap(unsigned char *G)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i ++) {
|
||||
unsigned char t;
|
||||
|
||||
t = G[i];
|
||||
G[i] = G[31 - i];
|
||||
G[31 - i] = t;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_mul(unsigned char *G, size_t Glen,
|
||||
const unsigned char *kb, size_t kblen, int curve)
|
||||
{
|
||||
#define ILEN (18 * sizeof(uint16_t))
|
||||
|
||||
/*
|
||||
* The a[] and b[] arrays have an extra word to allow for
|
||||
* decoding without using br_i15_decode_reduce().
|
||||
*/
|
||||
uint16_t x1[18], x2[18], x3[18], z2[18], z3[18];
|
||||
uint16_t a[19], aa[18], b[19], bb[18];
|
||||
uint16_t c[18], d[18], e[18], da[18], cb[18];
|
||||
unsigned char k[32];
|
||||
uint32_t swap;
|
||||
int i;
|
||||
|
||||
(void)curve;
|
||||
|
||||
/*
|
||||
* Points are encoded over exactly 32 bytes. Multipliers must fit
|
||||
* in 32 bytes as well.
|
||||
* RFC 7748 mandates that the high bit of the last point byte must
|
||||
* be ignored/cleared.
|
||||
*/
|
||||
if (Glen != 32 || kblen > 32) {
|
||||
return 0;
|
||||
}
|
||||
G[31] &= 0x7F;
|
||||
|
||||
/*
|
||||
* Byteswap the point encoding, because it uses little-endian, and
|
||||
* the generic decoding routine uses big-endian.
|
||||
*/
|
||||
byteswap(G);
|
||||
|
||||
/*
|
||||
* Decode the point ('u' coordinate). This should be reduced
|
||||
* modulo p, but we prefer to avoid the dependency on
|
||||
* br_i15_decode_reduce(). Instead, we use br_i15_decode_mod()
|
||||
* with a synthetic modulus of value 2^255 (this must work
|
||||
* since G was truncated to 255 bits), then use a conditional
|
||||
* subtraction. We use br_i15_decode_mod() and not
|
||||
* br_i15_decode(), because the ec_prime_i15 implementation uses
|
||||
* the former but not the latter.
|
||||
* br_i15_decode_reduce(a, G, 32, C255_P);
|
||||
*/
|
||||
br_i15_zero(b, 0x111);
|
||||
b[18] = 1;
|
||||
br_i15_decode_mod(a, G, 32, b);
|
||||
a[0] = 0x110;
|
||||
br_i15_sub(a, C255_P, NOT(br_i15_sub(a, C255_P, 0)));
|
||||
|
||||
/*
|
||||
* Initialise variables x1, x2, z2, x3 and z3. We set all of them
|
||||
* into Montgomery representation.
|
||||
*/
|
||||
br_i15_montymul(x1, a, C255_R2, C255_P, P0I);
|
||||
memcpy(x3, x1, ILEN);
|
||||
br_i15_zero(z2, C255_P[0]);
|
||||
memcpy(x2, z2, ILEN);
|
||||
x2[1] = 19;
|
||||
memcpy(z3, x2, ILEN);
|
||||
|
||||
memset(k, 0, (sizeof k) - kblen);
|
||||
memcpy(k + (sizeof k) - kblen, kb, kblen);
|
||||
k[31] &= 0xF8;
|
||||
k[0] &= 0x7F;
|
||||
k[0] |= 0x40;
|
||||
|
||||
/* obsolete
|
||||
print_int_mont("x1", x1);
|
||||
*/
|
||||
|
||||
swap = 0;
|
||||
for (i = 254; i >= 0; i --) {
|
||||
uint32_t kt;
|
||||
|
||||
kt = (k[31 - (i >> 3)] >> (i & 7)) & 1;
|
||||
swap ^= kt;
|
||||
cswap(x2, x3, swap);
|
||||
cswap(z2, z3, swap);
|
||||
swap = kt;
|
||||
|
||||
/* obsolete
|
||||
print_int_mont("x2", x2);
|
||||
print_int_mont("z2", z2);
|
||||
print_int_mont("x3", x3);
|
||||
print_int_mont("z3", z3);
|
||||
*/
|
||||
|
||||
c255_add(a, x2, z2);
|
||||
c255_mul(aa, a, a);
|
||||
c255_sub(b, x2, z2);
|
||||
c255_mul(bb, b, b);
|
||||
c255_sub(e, aa, bb);
|
||||
c255_add(c, x3, z3);
|
||||
c255_sub(d, x3, z3);
|
||||
c255_mul(da, d, a);
|
||||
c255_mul(cb, c, b);
|
||||
|
||||
/* obsolete
|
||||
print_int_mont("a ", a);
|
||||
print_int_mont("aa", aa);
|
||||
print_int_mont("b ", b);
|
||||
print_int_mont("bb", bb);
|
||||
print_int_mont("e ", e);
|
||||
print_int_mont("c ", c);
|
||||
print_int_mont("d ", d);
|
||||
print_int_mont("da", da);
|
||||
print_int_mont("cb", cb);
|
||||
*/
|
||||
|
||||
c255_add(x3, da, cb);
|
||||
c255_mul(x3, x3, x3);
|
||||
c255_sub(z3, da, cb);
|
||||
c255_mul(z3, z3, z3);
|
||||
c255_mul(z3, z3, x1);
|
||||
c255_mul(x2, aa, bb);
|
||||
c255_mul(z2, C255_A24, e);
|
||||
c255_add(z2, z2, aa);
|
||||
c255_mul(z2, e, z2);
|
||||
|
||||
/* obsolete
|
||||
print_int_mont("x2", x2);
|
||||
print_int_mont("z2", z2);
|
||||
print_int_mont("x3", x3);
|
||||
print_int_mont("z3", z3);
|
||||
*/
|
||||
}
|
||||
cswap(x2, x3, swap);
|
||||
cswap(z2, z3, swap);
|
||||
|
||||
/*
|
||||
* Inverse z2 with a modular exponentiation. This is a simple
|
||||
* square-and-multiply algorithm; we mutualise most non-squarings
|
||||
* since the exponent contains almost only ones.
|
||||
*/
|
||||
memcpy(a, z2, ILEN);
|
||||
for (i = 0; i < 15; i ++) {
|
||||
c255_mul(a, a, a);
|
||||
c255_mul(a, a, z2);
|
||||
}
|
||||
memcpy(b, a, ILEN);
|
||||
for (i = 0; i < 14; i ++) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < 16; j ++) {
|
||||
c255_mul(b, b, b);
|
||||
}
|
||||
c255_mul(b, b, a);
|
||||
}
|
||||
for (i = 14; i >= 0; i --) {
|
||||
c255_mul(b, b, b);
|
||||
if ((0xFFEB >> i) & 1) {
|
||||
c255_mul(b, z2, b);
|
||||
}
|
||||
}
|
||||
c255_mul(b, x2, b);
|
||||
|
||||
/*
|
||||
* To avoid a dependency on br_i15_from_monty(), we use a
|
||||
* Montgomery multiplication with 1.
|
||||
* memcpy(x2, b, ILEN);
|
||||
* br_i15_from_monty(x2, C255_P, P0I);
|
||||
*/
|
||||
br_i15_zero(a, C255_P[0]);
|
||||
a[1] = 1;
|
||||
br_i15_montymul(x2, a, b, C255_P, P0I);
|
||||
|
||||
br_i15_encode(G, 32, x2);
|
||||
byteswap(G);
|
||||
return 1;
|
||||
|
||||
#undef ILEN
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_mulgen(unsigned char *R,
|
||||
const unsigned char *x, size_t xlen, int curve)
|
||||
{
|
||||
const unsigned char *G;
|
||||
size_t Glen;
|
||||
|
||||
G = api_generator(curve, &Glen);
|
||||
memcpy(R, G, Glen);
|
||||
api_mul(R, Glen, x, xlen, curve);
|
||||
return Glen;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_muladd(unsigned char *A, const unsigned char *B, size_t len,
|
||||
const unsigned char *x, size_t xlen,
|
||||
const unsigned char *y, size_t ylen, int curve)
|
||||
{
|
||||
/*
|
||||
* We don't implement this method, since it is used for ECDSA
|
||||
* only, and there is no ECDSA over Curve25519 (which instead
|
||||
* uses EdDSA).
|
||||
*/
|
||||
(void)A;
|
||||
(void)B;
|
||||
(void)len;
|
||||
(void)x;
|
||||
(void)xlen;
|
||||
(void)y;
|
||||
(void)ylen;
|
||||
(void)curve;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
const br_ec_impl br_ec_c25519_i15 = {
|
||||
(uint32_t)0x20000000,
|
||||
&api_generator,
|
||||
&api_order,
|
||||
&api_xoff,
|
||||
&api_mul,
|
||||
&api_mulgen,
|
||||
&api_muladd
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -28,9 +28,5 @@
|
|||
const br_ec_impl *
|
||||
br_ec_get_default(void)
|
||||
{
|
||||
#if BR_LOMUL
|
||||
return &br_ec_all_m15;
|
||||
#else
|
||||
return &br_ec_all_m31;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,824 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Parameters for supported curves:
|
||||
* - field modulus p
|
||||
* - R^2 mod p (R = 2^(15k) for the smallest k such that R >= p)
|
||||
* - b*R mod p (b is the second curve equation parameter)
|
||||
*/
|
||||
|
||||
static const uint16_t P256_P[] = {
|
||||
0x0111,
|
||||
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x003F, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x4000, 0x7FFF,
|
||||
0x7FFF, 0x0001
|
||||
};
|
||||
|
||||
static const uint16_t P256_R2[] = {
|
||||
0x0111,
|
||||
0x0000, 0x6000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7FFC, 0x7FFF,
|
||||
0x7FBF, 0x7FFF, 0x7FBF, 0x7FFF, 0x7FFF, 0x7FFF, 0x77FF, 0x7FFF,
|
||||
0x4FFF, 0x0000
|
||||
};
|
||||
|
||||
static const uint16_t P256_B[] = {
|
||||
0x0111,
|
||||
0x770C, 0x5EEF, 0x29C4, 0x3EC4, 0x6273, 0x0486, 0x4543, 0x3993,
|
||||
0x3C01, 0x6B56, 0x212E, 0x57EE, 0x4882, 0x204B, 0x7483, 0x3C16,
|
||||
0x0187, 0x0000
|
||||
};
|
||||
|
||||
static const uint16_t P384_P[] = {
|
||||
0x0199,
|
||||
0x7FFF, 0x7FFF, 0x0003, 0x0000, 0x0000, 0x0000, 0x7FC0, 0x7FFF,
|
||||
0x7EFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
|
||||
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
|
||||
0x7FFF, 0x01FF
|
||||
};
|
||||
|
||||
static const uint16_t P384_R2[] = {
|
||||
0x0199,
|
||||
0x1000, 0x0000, 0x0000, 0x7FFF, 0x7FFF, 0x0001, 0x0000, 0x0010,
|
||||
0x0000, 0x0000, 0x0000, 0x7F00, 0x7FFF, 0x01FF, 0x0000, 0x1000,
|
||||
0x0000, 0x2000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000
|
||||
};
|
||||
|
||||
static const uint16_t P384_B[] = {
|
||||
0x0199,
|
||||
0x7333, 0x2096, 0x70D1, 0x2310, 0x3020, 0x6197, 0x1464, 0x35BB,
|
||||
0x70CA, 0x0117, 0x1920, 0x4136, 0x5FC8, 0x5713, 0x4938, 0x7DD2,
|
||||
0x4DD2, 0x4A71, 0x0220, 0x683E, 0x2C87, 0x4DB1, 0x7BFF, 0x6C09,
|
||||
0x0452, 0x0084
|
||||
};
|
||||
|
||||
static const uint16_t P521_P[] = {
|
||||
0x022B,
|
||||
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
|
||||
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
|
||||
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
|
||||
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
|
||||
0x7FFF, 0x7FFF, 0x07FF
|
||||
};
|
||||
|
||||
static const uint16_t P521_R2[] = {
|
||||
0x022B,
|
||||
0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000
|
||||
};
|
||||
|
||||
static const uint16_t P521_B[] = {
|
||||
0x022B,
|
||||
0x7002, 0x6A07, 0x751A, 0x228F, 0x71EF, 0x5869, 0x20F4, 0x1EFC,
|
||||
0x7357, 0x37E0, 0x4EEC, 0x605E, 0x1652, 0x26F6, 0x31FA, 0x4A8F,
|
||||
0x6193, 0x3C2A, 0x3C42, 0x48C7, 0x3489, 0x6771, 0x4C57, 0x5CCD,
|
||||
0x2725, 0x545B, 0x503B, 0x5B42, 0x21A0, 0x2534, 0x687E, 0x70E4,
|
||||
0x1618, 0x27D7, 0x0465
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const uint16_t *p;
|
||||
const uint16_t *b;
|
||||
const uint16_t *R2;
|
||||
uint16_t p0i;
|
||||
size_t point_len;
|
||||
} curve_params;
|
||||
|
||||
static inline const curve_params *
|
||||
id_to_curve(int curve)
|
||||
{
|
||||
static const curve_params pp[] = {
|
||||
{ P256_P, P256_B, P256_R2, 0x0001, 65 },
|
||||
{ P384_P, P384_B, P384_R2, 0x0001, 97 },
|
||||
{ P521_P, P521_B, P521_R2, 0x0001, 133 }
|
||||
};
|
||||
|
||||
return &pp[curve - BR_EC_secp256r1];
|
||||
}
|
||||
|
||||
#define I15_LEN ((BR_MAX_EC_SIZE + 29) / 15)
|
||||
|
||||
/*
|
||||
* Type for a point in Jacobian coordinates:
|
||||
* -- three values, x, y and z, in Montgomery representation
|
||||
* -- affine coordinates are X = x / z^2 and Y = y / z^3
|
||||
* -- for the point at infinity, z = 0
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t c[3][I15_LEN];
|
||||
} jacobian;
|
||||
|
||||
/*
|
||||
* We use a custom interpreter that uses a dozen registers, and
|
||||
* only six operations:
|
||||
* MSET(d, a) copy a into d
|
||||
* MADD(d, a) d = d+a (modular)
|
||||
* MSUB(d, a) d = d-a (modular)
|
||||
* MMUL(d, a, b) d = a*b (Montgomery multiplication)
|
||||
* MINV(d, a, b) invert d modulo p; a and b are used as scratch registers
|
||||
* MTZ(d) clear return value if d = 0
|
||||
* Destination of MMUL (d) must be distinct from operands (a and b).
|
||||
* There is no such constraint for MSUB and MADD.
|
||||
*
|
||||
* Registers include the operand coordinates, and temporaries.
|
||||
*/
|
||||
#define MSET(d, a) (0x0000 + ((d) << 8) + ((a) << 4))
|
||||
#define MADD(d, a) (0x1000 + ((d) << 8) + ((a) << 4))
|
||||
#define MSUB(d, a) (0x2000 + ((d) << 8) + ((a) << 4))
|
||||
#define MMUL(d, a, b) (0x3000 + ((d) << 8) + ((a) << 4) + (b))
|
||||
#define MINV(d, a, b) (0x4000 + ((d) << 8) + ((a) << 4) + (b))
|
||||
#define MTZ(d) (0x5000 + ((d) << 8))
|
||||
#define ENDCODE 0
|
||||
|
||||
/*
|
||||
* Registers for the input operands.
|
||||
*/
|
||||
#define P1x 0
|
||||
#define P1y 1
|
||||
#define P1z 2
|
||||
#define P2x 3
|
||||
#define P2y 4
|
||||
#define P2z 5
|
||||
|
||||
/*
|
||||
* Alternate names for the first input operand.
|
||||
*/
|
||||
#define Px 0
|
||||
#define Py 1
|
||||
#define Pz 2
|
||||
|
||||
/*
|
||||
* Temporaries.
|
||||
*/
|
||||
#define t1 6
|
||||
#define t2 7
|
||||
#define t3 8
|
||||
#define t4 9
|
||||
#define t5 10
|
||||
#define t6 11
|
||||
#define t7 12
|
||||
|
||||
/*
|
||||
* Extra scratch registers available when there is no second operand (e.g.
|
||||
* for "double" and "affine").
|
||||
*/
|
||||
#define t8 3
|
||||
#define t9 4
|
||||
#define t10 5
|
||||
|
||||
/*
|
||||
* Doubling formulas are:
|
||||
*
|
||||
* s = 4*x*y^2
|
||||
* m = 3*(x + z^2)*(x - z^2)
|
||||
* x' = m^2 - 2*s
|
||||
* y' = m*(s - x') - 8*y^4
|
||||
* z' = 2*y*z
|
||||
*
|
||||
* If y = 0 (P has order 2) then this yields infinity (z' = 0), as it
|
||||
* should. This case should not happen anyway, because our curves have
|
||||
* prime order, and thus do not contain any point of order 2.
|
||||
*
|
||||
* If P is infinity (z = 0), then again the formulas yield infinity,
|
||||
* which is correct. Thus, this code works for all points.
|
||||
*
|
||||
* Cost: 8 multiplications
|
||||
*/
|
||||
static const uint16_t code_double[] = {
|
||||
/*
|
||||
* Compute z^2 (in t1).
|
||||
*/
|
||||
MMUL(t1, Pz, Pz),
|
||||
|
||||
/*
|
||||
* Compute x-z^2 (in t2) and then x+z^2 (in t1).
|
||||
*/
|
||||
MSET(t2, Px),
|
||||
MSUB(t2, t1),
|
||||
MADD(t1, Px),
|
||||
|
||||
/*
|
||||
* Compute m = 3*(x+z^2)*(x-z^2) (in t1).
|
||||
*/
|
||||
MMUL(t3, t1, t2),
|
||||
MSET(t1, t3),
|
||||
MADD(t1, t3),
|
||||
MADD(t1, t3),
|
||||
|
||||
/*
|
||||
* Compute s = 4*x*y^2 (in t2) and 2*y^2 (in t3).
|
||||
*/
|
||||
MMUL(t3, Py, Py),
|
||||
MADD(t3, t3),
|
||||
MMUL(t2, Px, t3),
|
||||
MADD(t2, t2),
|
||||
|
||||
/*
|
||||
* Compute x' = m^2 - 2*s.
|
||||
*/
|
||||
MMUL(Px, t1, t1),
|
||||
MSUB(Px, t2),
|
||||
MSUB(Px, t2),
|
||||
|
||||
/*
|
||||
* Compute z' = 2*y*z.
|
||||
*/
|
||||
MMUL(t4, Py, Pz),
|
||||
MSET(Pz, t4),
|
||||
MADD(Pz, t4),
|
||||
|
||||
/*
|
||||
* Compute y' = m*(s - x') - 8*y^4. Note that we already have
|
||||
* 2*y^2 in t3.
|
||||
*/
|
||||
MSUB(t2, Px),
|
||||
MMUL(Py, t1, t2),
|
||||
MMUL(t4, t3, t3),
|
||||
MSUB(Py, t4),
|
||||
MSUB(Py, t4),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
/*
|
||||
* Addtions formulas are:
|
||||
*
|
||||
* u1 = x1 * z2^2
|
||||
* u2 = x2 * z1^2
|
||||
* s1 = y1 * z2^3
|
||||
* s2 = y2 * z1^3
|
||||
* h = u2 - u1
|
||||
* r = s2 - s1
|
||||
* x3 = r^2 - h^3 - 2 * u1 * h^2
|
||||
* y3 = r * (u1 * h^2 - x3) - s1 * h^3
|
||||
* z3 = h * z1 * z2
|
||||
*
|
||||
* If both P1 and P2 are infinity, then z1 == 0 and z2 == 0, implying that
|
||||
* z3 == 0, so the result is correct.
|
||||
* If either of P1 or P2 is infinity, but not both, then z3 == 0, which is
|
||||
* not correct.
|
||||
* h == 0 only if u1 == u2; this happens in two cases:
|
||||
* -- if s1 == s2 then P1 and/or P2 is infinity, or P1 == P2
|
||||
* -- if s1 != s2 then P1 + P2 == infinity (but neither P1 or P2 is infinity)
|
||||
*
|
||||
* Thus, the following situations are not handled correctly:
|
||||
* -- P1 = 0 and P2 != 0
|
||||
* -- P1 != 0 and P2 = 0
|
||||
* -- P1 = P2
|
||||
* All other cases are properly computed. However, even in "incorrect"
|
||||
* situations, the three coordinates still are properly formed field
|
||||
* elements.
|
||||
*
|
||||
* The returned flag is cleared if r == 0. This happens in the following
|
||||
* cases:
|
||||
* -- Both points are on the same horizontal line (same Y coordinate).
|
||||
* -- Both points are infinity.
|
||||
* -- One point is infinity and the other is on line Y = 0.
|
||||
* The third case cannot happen with our curves (there is no valid point
|
||||
* on line Y = 0 since that would be a point of order 2). If the two
|
||||
* source points are non-infinity, then remains only the case where the
|
||||
* two points are on the same horizontal line.
|
||||
*
|
||||
* This allows us to detect the "P1 == P2" case, assuming that P1 != 0 and
|
||||
* P2 != 0:
|
||||
* -- If the returned value is not the point at infinity, then it was properly
|
||||
* computed.
|
||||
* -- Otherwise, if the returned flag is 1, then P1+P2 = 0, and the result
|
||||
* is indeed the point at infinity.
|
||||
* -- Otherwise (result is infinity, flag is 0), then P1 = P2 and we should
|
||||
* use the 'double' code.
|
||||
*
|
||||
* Cost: 16 multiplications
|
||||
*/
|
||||
static const uint16_t code_add[] = {
|
||||
/*
|
||||
* Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3).
|
||||
*/
|
||||
MMUL(t3, P2z, P2z),
|
||||
MMUL(t1, P1x, t3),
|
||||
MMUL(t4, P2z, t3),
|
||||
MMUL(t3, P1y, t4),
|
||||
|
||||
/*
|
||||
* Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
|
||||
*/
|
||||
MMUL(t4, P1z, P1z),
|
||||
MMUL(t2, P2x, t4),
|
||||
MMUL(t5, P1z, t4),
|
||||
MMUL(t4, P2y, t5),
|
||||
|
||||
/*
|
||||
* Compute h = u2 - u1 (in t2) and r = s2 - s1 (in t4).
|
||||
*/
|
||||
MSUB(t2, t1),
|
||||
MSUB(t4, t3),
|
||||
|
||||
/*
|
||||
* Report cases where r = 0 through the returned flag.
|
||||
*/
|
||||
MTZ(t4),
|
||||
|
||||
/*
|
||||
* Compute u1*h^2 (in t6) and h^3 (in t5).
|
||||
*/
|
||||
MMUL(t7, t2, t2),
|
||||
MMUL(t6, t1, t7),
|
||||
MMUL(t5, t7, t2),
|
||||
|
||||
/*
|
||||
* Compute x3 = r^2 - h^3 - 2*u1*h^2.
|
||||
* t1 and t7 can be used as scratch registers.
|
||||
*/
|
||||
MMUL(P1x, t4, t4),
|
||||
MSUB(P1x, t5),
|
||||
MSUB(P1x, t6),
|
||||
MSUB(P1x, t6),
|
||||
|
||||
/*
|
||||
* Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
|
||||
*/
|
||||
MSUB(t6, P1x),
|
||||
MMUL(P1y, t4, t6),
|
||||
MMUL(t1, t5, t3),
|
||||
MSUB(P1y, t1),
|
||||
|
||||
/*
|
||||
* Compute z3 = h*z1*z2.
|
||||
*/
|
||||
MMUL(t1, P1z, P2z),
|
||||
MMUL(P1z, t1, t2),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
/*
|
||||
* Check that the point is on the curve. This code snippet assumes the
|
||||
* following conventions:
|
||||
* -- Coordinates x and y have been freshly decoded in P1 (but not
|
||||
* converted to Montgomery coordinates yet).
|
||||
* -- P2x, P2y and P2z are set to, respectively, R^2, b*R and 1.
|
||||
*/
|
||||
static const uint16_t code_check[] = {
|
||||
|
||||
/* Convert x and y to Montgomery representation. */
|
||||
MMUL(t1, P1x, P2x),
|
||||
MMUL(t2, P1y, P2x),
|
||||
MSET(P1x, t1),
|
||||
MSET(P1y, t2),
|
||||
|
||||
/* Compute x^3 in t1. */
|
||||
MMUL(t2, P1x, P1x),
|
||||
MMUL(t1, P1x, t2),
|
||||
|
||||
/* Subtract 3*x from t1. */
|
||||
MSUB(t1, P1x),
|
||||
MSUB(t1, P1x),
|
||||
MSUB(t1, P1x),
|
||||
|
||||
/* Add b. */
|
||||
MADD(t1, P2y),
|
||||
|
||||
/* Compute y^2 in t2. */
|
||||
MMUL(t2, P1y, P1y),
|
||||
|
||||
/* Compare y^2 with x^3 - 3*x + b; they must match. */
|
||||
MSUB(t1, t2),
|
||||
MTZ(t1),
|
||||
|
||||
/* Set z to 1 (in Montgomery representation). */
|
||||
MMUL(P1z, P2x, P2z),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
/*
|
||||
* Conversion back to affine coordinates. This code snippet assumes that
|
||||
* the z coordinate of P2 is set to 1 (not in Montgomery representation).
|
||||
*/
|
||||
static const uint16_t code_affine[] = {
|
||||
|
||||
/* Save z*R in t1. */
|
||||
MSET(t1, P1z),
|
||||
|
||||
/* Compute z^3 in t2. */
|
||||
MMUL(t2, P1z, P1z),
|
||||
MMUL(t3, P1z, t2),
|
||||
MMUL(t2, t3, P2z),
|
||||
|
||||
/* Invert to (1/z^3) in t2. */
|
||||
MINV(t2, t3, t4),
|
||||
|
||||
/* Compute y. */
|
||||
MSET(t3, P1y),
|
||||
MMUL(P1y, t2, t3),
|
||||
|
||||
/* Compute (1/z^2) in t3. */
|
||||
MMUL(t3, t2, t1),
|
||||
|
||||
/* Compute x. */
|
||||
MSET(t2, P1x),
|
||||
MMUL(P1x, t2, t3),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
static uint32_t
|
||||
run_code(jacobian *P1, const jacobian *P2,
|
||||
const curve_params *cc, const uint16_t *code)
|
||||
{
|
||||
uint32_t r;
|
||||
uint16_t t[13][I15_LEN];
|
||||
size_t u;
|
||||
|
||||
r = 1;
|
||||
|
||||
/*
|
||||
* Copy the two operands in the dedicated registers.
|
||||
*/
|
||||
memcpy(t[P1x], P1->c, 3 * I15_LEN * sizeof(uint16_t));
|
||||
memcpy(t[P2x], P2->c, 3 * I15_LEN * sizeof(uint16_t));
|
||||
|
||||
/*
|
||||
* Run formulas.
|
||||
*/
|
||||
for (u = 0;; u ++) {
|
||||
unsigned op, d, a, b;
|
||||
|
||||
op = code[u];
|
||||
if (op == 0) {
|
||||
break;
|
||||
}
|
||||
d = (op >> 8) & 0x0F;
|
||||
a = (op >> 4) & 0x0F;
|
||||
b = op & 0x0F;
|
||||
op >>= 12;
|
||||
switch (op) {
|
||||
uint32_t ctl;
|
||||
size_t plen;
|
||||
unsigned char tp[(BR_MAX_EC_SIZE + 7) >> 3];
|
||||
|
||||
case 0:
|
||||
memcpy(t[d], t[a], I15_LEN * sizeof(uint16_t));
|
||||
break;
|
||||
case 1:
|
||||
ctl = br_i15_add(t[d], t[a], 1);
|
||||
ctl |= NOT(br_i15_sub(t[d], cc->p, 0));
|
||||
br_i15_sub(t[d], cc->p, ctl);
|
||||
break;
|
||||
case 2:
|
||||
br_i15_add(t[d], cc->p, br_i15_sub(t[d], t[a], 1));
|
||||
break;
|
||||
case 3:
|
||||
br_i15_montymul(t[d], t[a], t[b], cc->p, cc->p0i);
|
||||
break;
|
||||
case 4:
|
||||
plen = (cc->p[0] - (cc->p[0] >> 4) + 7) >> 3;
|
||||
br_i15_encode(tp, plen, cc->p);
|
||||
tp[plen - 1] -= 2;
|
||||
br_i15_modpow(t[d], tp, plen,
|
||||
cc->p, cc->p0i, t[a], t[b]);
|
||||
break;
|
||||
default:
|
||||
r &= ~br_i15_iszero(t[d]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy back result.
|
||||
*/
|
||||
memcpy(P1->c, t[P1x], 3 * I15_LEN * sizeof(uint16_t));
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
set_one(uint16_t *x, const uint16_t *p)
|
||||
{
|
||||
size_t plen;
|
||||
|
||||
plen = (p[0] + 31) >> 4;
|
||||
memset(x, 0, plen * sizeof *x);
|
||||
x[0] = p[0];
|
||||
x[1] = 0x0001;
|
||||
}
|
||||
|
||||
static void
|
||||
point_zero(jacobian *P, const curve_params *cc)
|
||||
{
|
||||
memset(P, 0, sizeof *P);
|
||||
P->c[0][0] = P->c[1][0] = P->c[2][0] = cc->p[0];
|
||||
}
|
||||
|
||||
static inline void
|
||||
point_double(jacobian *P, const curve_params *cc)
|
||||
{
|
||||
run_code(P, P, cc, code_double);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
point_add(jacobian *P1, const jacobian *P2, const curve_params *cc)
|
||||
{
|
||||
return run_code(P1, P2, cc, code_add);
|
||||
}
|
||||
|
||||
static void
|
||||
point_mul(jacobian *P, const unsigned char *x, size_t xlen,
|
||||
const curve_params *cc)
|
||||
{
|
||||
/*
|
||||
* We do a simple double-and-add ladder with a 2-bit window
|
||||
* to make only one add every two doublings. We thus first
|
||||
* precompute 2P and 3P in some local buffers.
|
||||
*
|
||||
* We always perform two doublings and one addition; the
|
||||
* addition is with P, 2P and 3P and is done in a temporary
|
||||
* array.
|
||||
*
|
||||
* The addition code cannot handle cases where one of the
|
||||
* operands is infinity, which is the case at the start of the
|
||||
* ladder. We therefore need to maintain a flag that controls
|
||||
* this situation.
|
||||
*/
|
||||
uint32_t qz;
|
||||
jacobian P2, P3, Q, T, U;
|
||||
|
||||
memcpy(&P2, P, sizeof P2);
|
||||
point_double(&P2, cc);
|
||||
memcpy(&P3, P, sizeof P3);
|
||||
point_add(&P3, &P2, cc);
|
||||
|
||||
point_zero(&Q, cc);
|
||||
qz = 1;
|
||||
while (xlen -- > 0) {
|
||||
int k;
|
||||
|
||||
for (k = 6; k >= 0; k -= 2) {
|
||||
uint32_t bits;
|
||||
uint32_t bnz;
|
||||
|
||||
point_double(&Q, cc);
|
||||
point_double(&Q, cc);
|
||||
memcpy(&T, P, sizeof T);
|
||||
memcpy(&U, &Q, sizeof U);
|
||||
bits = (*x >> k) & (uint32_t)3;
|
||||
bnz = NEQ(bits, 0);
|
||||
CCOPY(EQ(bits, 2), &T, &P2, sizeof T);
|
||||
CCOPY(EQ(bits, 3), &T, &P3, sizeof T);
|
||||
point_add(&U, &T, cc);
|
||||
CCOPY(bnz & qz, &Q, &T, sizeof Q);
|
||||
CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
|
||||
qz &= ~bnz;
|
||||
}
|
||||
x ++;
|
||||
}
|
||||
memcpy(P, &Q, sizeof Q);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode point into Jacobian coordinates. This function does not support
|
||||
* the point at infinity. If the point is invalid then this returns 0, but
|
||||
* the coordinates are still set to properly formed field elements.
|
||||
*/
|
||||
static uint32_t
|
||||
point_decode(jacobian *P, const void *src, size_t len, const curve_params *cc)
|
||||
{
|
||||
/*
|
||||
* Points must use uncompressed format:
|
||||
* -- first byte is 0x04;
|
||||
* -- coordinates X and Y use unsigned big-endian, with the same
|
||||
* length as the field modulus.
|
||||
*
|
||||
* We don't support hybrid format (uncompressed, but first byte
|
||||
* has value 0x06 or 0x07, depending on the least significant bit
|
||||
* of Y) because it is rather useless, and explicitly forbidden
|
||||
* by PKIX (RFC 5480, section 2.2).
|
||||
*
|
||||
* We don't support compressed format either, because it is not
|
||||
* much used in practice (there are or were patent-related
|
||||
* concerns about point compression, which explains the lack of
|
||||
* generalised support). Also, point compression support would
|
||||
* need a bit more code.
|
||||
*/
|
||||
const unsigned char *buf;
|
||||
size_t plen, zlen;
|
||||
uint32_t r;
|
||||
jacobian Q;
|
||||
|
||||
buf = src;
|
||||
point_zero(P, cc);
|
||||
plen = (cc->p[0] - (cc->p[0] >> 4) + 7) >> 3;
|
||||
if (len != 1 + (plen << 1)) {
|
||||
return 0;
|
||||
}
|
||||
r = br_i15_decode_mod(P->c[0], buf + 1, plen, cc->p);
|
||||
r &= br_i15_decode_mod(P->c[1], buf + 1 + plen, plen, cc->p);
|
||||
|
||||
/*
|
||||
* Check first byte.
|
||||
*/
|
||||
r &= EQ(buf[0], 0x04);
|
||||
/* obsolete
|
||||
r &= EQ(buf[0], 0x04) | (EQ(buf[0] & 0xFE, 0x06)
|
||||
& ~(uint32_t)(buf[0] ^ buf[plen << 1]));
|
||||
*/
|
||||
|
||||
/*
|
||||
* Convert coordinates and check that the point is valid.
|
||||
*/
|
||||
zlen = ((cc->p[0] + 31) >> 4) * sizeof(uint16_t);
|
||||
memcpy(Q.c[0], cc->R2, zlen);
|
||||
memcpy(Q.c[1], cc->b, zlen);
|
||||
set_one(Q.c[2], cc->p);
|
||||
r &= ~run_code(P, &Q, cc, code_check);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode a point. This method assumes that the point is correct and is
|
||||
* not the point at infinity. Encoded size is always 1+2*plen, where
|
||||
* plen is the field modulus length, in bytes.
|
||||
*/
|
||||
static void
|
||||
point_encode(void *dst, const jacobian *P, const curve_params *cc)
|
||||
{
|
||||
unsigned char *buf;
|
||||
size_t plen;
|
||||
jacobian Q, T;
|
||||
|
||||
buf = dst;
|
||||
plen = (cc->p[0] - (cc->p[0] >> 4) + 7) >> 3;
|
||||
buf[0] = 0x04;
|
||||
memcpy(&Q, P, sizeof *P);
|
||||
set_one(T.c[2], cc->p);
|
||||
run_code(&Q, &T, cc, code_affine);
|
||||
br_i15_encode(buf + 1, plen, Q.c[0]);
|
||||
br_i15_encode(buf + 1 + plen, plen, Q.c[1]);
|
||||
}
|
||||
|
||||
static const br_ec_curve_def *
|
||||
id_to_curve_def(int curve)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return &br_secp256r1;
|
||||
case BR_EC_secp384r1:
|
||||
return &br_secp384r1;
|
||||
case BR_EC_secp521r1:
|
||||
return &br_secp521r1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
api_generator(int curve, size_t *len)
|
||||
{
|
||||
const br_ec_curve_def *cd;
|
||||
|
||||
cd = id_to_curve_def(curve);
|
||||
*len = cd->generator_len;
|
||||
return cd->generator;
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
api_order(int curve, size_t *len)
|
||||
{
|
||||
const br_ec_curve_def *cd;
|
||||
|
||||
cd = id_to_curve_def(curve);
|
||||
*len = cd->order_len;
|
||||
return cd->order;
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_xoff(int curve, size_t *len)
|
||||
{
|
||||
api_generator(curve, len);
|
||||
*len >>= 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_mul(unsigned char *G, size_t Glen,
|
||||
const unsigned char *x, size_t xlen, int curve)
|
||||
{
|
||||
uint32_t r;
|
||||
const curve_params *cc;
|
||||
jacobian P;
|
||||
|
||||
cc = id_to_curve(curve);
|
||||
if (Glen != cc->point_len) {
|
||||
return 0;
|
||||
}
|
||||
r = point_decode(&P, G, Glen, cc);
|
||||
point_mul(&P, x, xlen, cc);
|
||||
point_encode(G, &P, cc);
|
||||
return r;
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_mulgen(unsigned char *R,
|
||||
const unsigned char *x, size_t xlen, int curve)
|
||||
{
|
||||
const unsigned char *G;
|
||||
size_t Glen;
|
||||
|
||||
G = api_generator(curve, &Glen);
|
||||
memcpy(R, G, Glen);
|
||||
api_mul(R, Glen, x, xlen, curve);
|
||||
return Glen;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_muladd(unsigned char *A, const unsigned char *B, size_t len,
|
||||
const unsigned char *x, size_t xlen,
|
||||
const unsigned char *y, size_t ylen, int curve)
|
||||
{
|
||||
uint32_t r, t, z;
|
||||
const curve_params *cc;
|
||||
jacobian P, Q;
|
||||
|
||||
/*
|
||||
* TODO: see about merging the two ladders. Right now, we do
|
||||
* two independent point multiplications, which is a bit
|
||||
* wasteful of CPU resources (but yields short code).
|
||||
*/
|
||||
|
||||
cc = id_to_curve(curve);
|
||||
if (len != cc->point_len) {
|
||||
return 0;
|
||||
}
|
||||
r = point_decode(&P, A, len, cc);
|
||||
if (B == NULL) {
|
||||
size_t Glen;
|
||||
|
||||
B = api_generator(curve, &Glen);
|
||||
}
|
||||
r &= point_decode(&Q, B, len, cc);
|
||||
point_mul(&P, x, xlen, cc);
|
||||
point_mul(&Q, y, ylen, cc);
|
||||
|
||||
/*
|
||||
* We want to compute P+Q. Since the base points A and B are distinct
|
||||
* from infinity, and the multipliers are non-zero and lower than the
|
||||
* curve order, then we know that P and Q are non-infinity. This
|
||||
* leaves two special situations to test for:
|
||||
* -- If P = Q then we must use point_double().
|
||||
* -- If P+Q = 0 then we must report an error.
|
||||
*/
|
||||
t = point_add(&P, &Q, cc);
|
||||
point_double(&Q, cc);
|
||||
z = br_i15_iszero(P.c[2]);
|
||||
|
||||
/*
|
||||
* If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we
|
||||
* have the following:
|
||||
*
|
||||
* z = 0, t = 0 return P (normal addition)
|
||||
* z = 0, t = 1 return P (normal addition)
|
||||
* z = 1, t = 0 return Q (a 'double' case)
|
||||
* z = 1, t = 1 report an error (P+Q = 0)
|
||||
*/
|
||||
CCOPY(z & ~t, &P, &Q, sizeof Q);
|
||||
point_encode(A, &P, cc);
|
||||
r &= ~(z & t);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
const br_ec_impl br_ec_prime_i15 = {
|
||||
(uint32_t)0x03800000,
|
||||
&api_generator,
|
||||
&api_order,
|
||||
&api_xoff,
|
||||
&api_mul,
|
||||
&api_mulgen,
|
||||
&api_muladd
|
||||
};
|
||||
|
|
@ -28,9 +28,5 @@
|
|||
br_ecdsa_sign
|
||||
br_ecdsa_sign_asn1_get_default(void)
|
||||
{
|
||||
#if BR_LOMUL
|
||||
return &br_ecdsa_i15_sign_asn1;
|
||||
#else
|
||||
return &br_ecdsa_i31_sign_asn1;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,9 +28,5 @@
|
|||
br_ecdsa_sign
|
||||
br_ecdsa_sign_raw_get_default(void)
|
||||
{
|
||||
#if BR_LOMUL
|
||||
return &br_ecdsa_i15_sign_raw;
|
||||
#else
|
||||
return &br_ecdsa_i31_sign_raw;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,9 +28,5 @@
|
|||
br_ecdsa_vrfy
|
||||
br_ecdsa_vrfy_asn1_get_default(void)
|
||||
{
|
||||
#if BR_LOMUL
|
||||
return &br_ecdsa_i15_vrfy_asn1;
|
||||
#else
|
||||
return &br_ecdsa_i31_vrfy_asn1;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,9 +28,5 @@
|
|||
br_ecdsa_vrfy
|
||||
br_ecdsa_vrfy_raw_get_default(void)
|
||||
{
|
||||
#if BR_LOMUL
|
||||
return &br_ecdsa_i15_vrfy_raw;
|
||||
#else
|
||||
return &br_ecdsa_i31_vrfy_raw;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_ecdsa_i15_bits2int(uint16_t *x,
|
||||
const void *src, size_t len, uint32_t ebitlen)
|
||||
{
|
||||
uint32_t bitlen, hbitlen;
|
||||
int sc;
|
||||
|
||||
bitlen = ebitlen - (ebitlen >> 4);
|
||||
hbitlen = (uint32_t)len << 3;
|
||||
if (hbitlen > bitlen) {
|
||||
len = (bitlen + 7) >> 3;
|
||||
sc = (int)((hbitlen - bitlen) & 7);
|
||||
} else {
|
||||
sc = 0;
|
||||
}
|
||||
br_i15_zero(x, ebitlen);
|
||||
br_i15_decode(x, src, len);
|
||||
br_i15_rshift(x, sc);
|
||||
x[0] = ebitlen;
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
size_t
|
||||
br_ecdsa_i15_sign_asn1(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig)
|
||||
{
|
||||
unsigned char rsig[(ORDER_LEN << 1) + 12];
|
||||
size_t sig_len;
|
||||
|
||||
sig_len = br_ecdsa_i15_sign_raw(impl, hf, hash_value, sk, rsig);
|
||||
if (sig_len == 0) {
|
||||
return 0;
|
||||
}
|
||||
sig_len = br_ecdsa_raw_to_asn1(rsig, sig_len);
|
||||
memcpy(sig, rsig, sig_len);
|
||||
return sig_len;
|
||||
}
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define I15_LEN ((BR_MAX_EC_SIZE + 29) / 15)
|
||||
#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))
|
||||
#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
size_t
|
||||
br_ecdsa_i15_sign_raw(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig)
|
||||
{
|
||||
/*
|
||||
* IMPORTANT: this code is fit only for curves with a prime
|
||||
* order. This is needed so that modular reduction of the X
|
||||
* coordinate of a point can be done with a simple subtraction.
|
||||
* We also rely on the last byte of the curve order to be distinct
|
||||
* from 0 and 1.
|
||||
*/
|
||||
const br_ec_curve_def *cd;
|
||||
uint16_t n[I15_LEN], r[I15_LEN], s[I15_LEN], x[I15_LEN];
|
||||
uint16_t m[I15_LEN], k[I15_LEN], t1[I15_LEN], t2[I15_LEN];
|
||||
unsigned char tt[ORDER_LEN << 1];
|
||||
unsigned char eU[POINT_LEN];
|
||||
size_t hash_len, nlen, ulen;
|
||||
uint16_t n0i;
|
||||
uint32_t ctl;
|
||||
br_hmac_drbg_context drbg;
|
||||
|
||||
/*
|
||||
* If the curve is not supported, then exit with an error.
|
||||
*/
|
||||
if (((impl->supported_curves >> sk->curve) & 1) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the curve parameters (generator and order).
|
||||
*/
|
||||
switch (sk->curve) {
|
||||
case BR_EC_secp256r1:
|
||||
cd = &br_secp256r1;
|
||||
break;
|
||||
case BR_EC_secp384r1:
|
||||
cd = &br_secp384r1;
|
||||
break;
|
||||
case BR_EC_secp521r1:
|
||||
cd = &br_secp521r1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get modulus.
|
||||
*/
|
||||
nlen = cd->order_len;
|
||||
br_i15_decode(n, cd->order, nlen);
|
||||
n0i = br_i15_ninv15(n[1]);
|
||||
|
||||
/*
|
||||
* Get private key as an i15 integer. This also checks that the
|
||||
* private key is well-defined (not zero, and less than the
|
||||
* curve order).
|
||||
*/
|
||||
if (!br_i15_decode_mod(x, sk->x, sk->xlen, n)) {
|
||||
return 0;
|
||||
}
|
||||
if (br_i15_iszero(x)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get hash length.
|
||||
*/
|
||||
hash_len = (hf->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
|
||||
|
||||
/*
|
||||
* Truncate and reduce the hash value modulo the curve order.
|
||||
*/
|
||||
br_ecdsa_i15_bits2int(m, hash_value, hash_len, n[0]);
|
||||
br_i15_sub(m, n, br_i15_sub(m, n, 0) ^ 1);
|
||||
|
||||
/*
|
||||
* RFC 6979 generation of the "k" value.
|
||||
*
|
||||
* The process uses HMAC_DRBG (with the hash function used to
|
||||
* process the message that is to be signed). The seed is the
|
||||
* concatenation of the encodings of the private key and
|
||||
* the hash value (after truncation and modular reduction).
|
||||
*/
|
||||
br_i15_encode(tt, nlen, x);
|
||||
br_i15_encode(tt + nlen, nlen, m);
|
||||
br_hmac_drbg_init(&drbg, hf, tt, nlen << 1);
|
||||
for (;;) {
|
||||
br_hmac_drbg_generate(&drbg, tt, nlen);
|
||||
br_ecdsa_i15_bits2int(k, tt, nlen, n[0]);
|
||||
if (br_i15_iszero(k)) {
|
||||
continue;
|
||||
}
|
||||
if (br_i15_sub(k, n, 0)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute k*G and extract the X coordinate, then reduce it
|
||||
* modulo the curve order. Since we support only curves with
|
||||
* prime order, that reduction is only a matter of computing
|
||||
* a subtraction.
|
||||
*/
|
||||
br_i15_encode(tt, nlen, k);
|
||||
ulen = impl->mulgen(eU, tt, nlen, sk->curve);
|
||||
br_i15_zero(r, n[0]);
|
||||
br_i15_decode(r, &eU[1], ulen >> 1);
|
||||
r[0] = n[0];
|
||||
br_i15_sub(r, n, br_i15_sub(r, n, 0) ^ 1);
|
||||
|
||||
/*
|
||||
* Compute 1/k in double-Montgomery representation. We do so by
|
||||
* first converting _from_ Montgomery representation (twice),
|
||||
* then using a modular exponentiation.
|
||||
*/
|
||||
br_i15_from_monty(k, n, n0i);
|
||||
br_i15_from_monty(k, n, n0i);
|
||||
memcpy(tt, cd->order, nlen);
|
||||
tt[nlen - 1] -= 2;
|
||||
br_i15_modpow(k, tt, nlen, n, n0i, t1, t2);
|
||||
|
||||
/*
|
||||
* Compute s = (m+xr)/k (mod n).
|
||||
* The k[] array contains R^2/k (double-Montgomery representation);
|
||||
* we thus can use direct Montgomery multiplications and conversions
|
||||
* from Montgomery, avoiding any call to br_i15_to_monty() (which
|
||||
* is slower).
|
||||
*/
|
||||
br_i15_from_monty(m, n, n0i);
|
||||
br_i15_montymul(t1, x, r, n, n0i);
|
||||
ctl = br_i15_add(t1, m, 1);
|
||||
ctl |= br_i15_sub(t1, n, 0) ^ 1;
|
||||
br_i15_sub(t1, n, ctl);
|
||||
br_i15_montymul(s, t1, k, n, n0i);
|
||||
|
||||
/*
|
||||
* Encode r and s in the signature.
|
||||
*/
|
||||
br_i15_encode(sig, nlen, r);
|
||||
br_i15_encode((unsigned char *)sig + nlen, nlen, s);
|
||||
return nlen << 1;
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define FIELD_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
uint32_t
|
||||
br_ecdsa_i15_vrfy_asn1(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk,
|
||||
const void *sig, size_t sig_len)
|
||||
{
|
||||
/*
|
||||
* We use a double-sized buffer because a malformed ASN.1 signature
|
||||
* may trigger a size expansion when converting to "raw" format.
|
||||
*/
|
||||
unsigned char rsig[(FIELD_LEN << 2) + 24];
|
||||
|
||||
if (sig_len > ((sizeof rsig) >> 1)) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(rsig, sig, sig_len);
|
||||
sig_len = br_ecdsa_asn1_to_raw(rsig, sig_len);
|
||||
return br_ecdsa_i15_vrfy_raw(impl, hash, hash_len, pk, rsig, sig_len);
|
||||
}
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define I15_LEN ((BR_MAX_EC_SIZE + 29) / 15)
|
||||
#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
uint32_t
|
||||
br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk,
|
||||
const void *sig, size_t sig_len)
|
||||
{
|
||||
/*
|
||||
* IMPORTANT: this code is fit only for curves with a prime
|
||||
* order. This is needed so that modular reduction of the X
|
||||
* coordinate of a point can be done with a simple subtraction.
|
||||
*/
|
||||
const br_ec_curve_def *cd;
|
||||
uint16_t n[I15_LEN], r[I15_LEN], s[I15_LEN], t1[I15_LEN], t2[I15_LEN];
|
||||
unsigned char tx[(BR_MAX_EC_SIZE + 7) >> 3];
|
||||
unsigned char ty[(BR_MAX_EC_SIZE + 7) >> 3];
|
||||
unsigned char eU[POINT_LEN];
|
||||
size_t nlen, rlen, ulen;
|
||||
uint16_t n0i;
|
||||
uint32_t res;
|
||||
|
||||
/*
|
||||
* If the curve is not supported, then report an error.
|
||||
*/
|
||||
if (((impl->supported_curves >> pk->curve) & 1) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the curve parameters (generator and order).
|
||||
*/
|
||||
switch (pk->curve) {
|
||||
case BR_EC_secp256r1:
|
||||
cd = &br_secp256r1;
|
||||
break;
|
||||
case BR_EC_secp384r1:
|
||||
cd = &br_secp384r1;
|
||||
break;
|
||||
case BR_EC_secp521r1:
|
||||
cd = &br_secp521r1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Signature length must be even.
|
||||
*/
|
||||
if (sig_len & 1) {
|
||||
return 0;
|
||||
}
|
||||
rlen = sig_len >> 1;
|
||||
|
||||
/*
|
||||
* Public key point must have the proper size for this curve.
|
||||
*/
|
||||
if (pk->qlen != cd->generator_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get modulus; then decode the r and s values. They must be
|
||||
* lower than the modulus, and s must not be null.
|
||||
*/
|
||||
nlen = cd->order_len;
|
||||
br_i15_decode(n, cd->order, nlen);
|
||||
n0i = br_i15_ninv15(n[1]);
|
||||
if (!br_i15_decode_mod(r, sig, rlen, n)) {
|
||||
return 0;
|
||||
}
|
||||
if (!br_i15_decode_mod(s, (const unsigned char *)sig + rlen, rlen, n)) {
|
||||
return 0;
|
||||
}
|
||||
if (br_i15_iszero(s)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invert s. We do that with a modular exponentiation; we use
|
||||
* the fact that for all the curves we support, the least
|
||||
* significant byte is not 0 or 1, so we can subtract 2 without
|
||||
* any carry to process.
|
||||
* We also want 1/s in Montgomery representation, which can be
|
||||
* done by converting _from_ Montgomery representation before
|
||||
* the inversion (because (1/s)*R = 1/(s/R)).
|
||||
*/
|
||||
br_i15_from_monty(s, n, n0i);
|
||||
memcpy(tx, cd->order, nlen);
|
||||
tx[nlen - 1] -= 2;
|
||||
br_i15_modpow(s, tx, nlen, n, n0i, t1, t2);
|
||||
|
||||
/*
|
||||
* Truncate the hash to the modulus length (in bits) and reduce
|
||||
* it modulo the curve order. The modular reduction can be done
|
||||
* with a subtraction since the truncation already reduced the
|
||||
* value to the modulus bit length.
|
||||
*/
|
||||
br_ecdsa_i15_bits2int(t1, hash, hash_len, n[0]);
|
||||
br_i15_sub(t1, n, br_i15_sub(t1, n, 0) ^ 1);
|
||||
|
||||
/*
|
||||
* Multiply the (truncated, reduced) hash value with 1/s, result in
|
||||
* t2, encoded in ty.
|
||||
*/
|
||||
br_i15_montymul(t2, t1, s, n, n0i);
|
||||
br_i15_encode(ty, nlen, t2);
|
||||
|
||||
/*
|
||||
* Multiply r with 1/s, result in t1, encoded in tx.
|
||||
*/
|
||||
br_i15_montymul(t1, r, s, n, n0i);
|
||||
br_i15_encode(tx, nlen, t1);
|
||||
|
||||
/*
|
||||
* Compute the point x*Q + y*G.
|
||||
*/
|
||||
ulen = cd->generator_len;
|
||||
memcpy(eU, pk->q, ulen);
|
||||
res = impl->muladd(eU, NULL, ulen,
|
||||
tx, nlen, ty, nlen, cd->curve);
|
||||
|
||||
/*
|
||||
* Get the X coordinate, reduce modulo the curve order, and
|
||||
* compare with the 'r' value.
|
||||
*
|
||||
* The modular reduction can be done with subtractions because
|
||||
* we work with curves of prime order, so the curve order is
|
||||
* close to the field order (Hasse's theorem).
|
||||
*/
|
||||
br_i15_zero(t1, n[0]);
|
||||
br_i15_decode(t1, &eU[1], ulen >> 1);
|
||||
t1[0] = n[0];
|
||||
br_i15_sub(t1, n, br_i15_sub(t1, n, 0) ^ 1);
|
||||
res &= ~br_i15_sub(t1, r, 1);
|
||||
res &= br_i15_iszero(t1);
|
||||
return res;
|
||||
}
|
||||
|
|
@ -1,251 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* This implementation uses 32-bit multiplications, and only the low
|
||||
* 32 bits for each multiplication result. This is meant primarily for
|
||||
* the ARM Cortex M0 and M0+, whose multiplication opcode does not yield
|
||||
* the upper 32 bits; but it might also be useful on architectures where
|
||||
* access to the upper 32 bits requires use of specific registers that
|
||||
* create contention (e.g. on i386, "mul" necessarily outputs the result
|
||||
* in edx:eax, while "imul" can use any registers but is limited to the
|
||||
* low 32 bits).
|
||||
*
|
||||
* The implementation trick that is used here is bit-reversing (bit 0
|
||||
* is swapped with bit 31, bit 1 with bit 30, and so on). In GF(2)[X],
|
||||
* for all values x and y, we have:
|
||||
* rev32(x) * rev32(y) = rev64(x * y)
|
||||
* In other words, if we bit-reverse (over 32 bits) the operands, then we
|
||||
* bit-reverse (over 64 bits) the result.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Multiplication in GF(2)[X], truncated to its low 32 bits.
|
||||
*/
|
||||
static inline uint32_t
|
||||
bmul32(uint32_t x, uint32_t y)
|
||||
{
|
||||
uint32_t x0, x1, x2, x3;
|
||||
uint32_t y0, y1, y2, y3;
|
||||
uint32_t z0, z1, z2, z3;
|
||||
|
||||
x0 = x & (uint32_t)0x11111111;
|
||||
x1 = x & (uint32_t)0x22222222;
|
||||
x2 = x & (uint32_t)0x44444444;
|
||||
x3 = x & (uint32_t)0x88888888;
|
||||
y0 = y & (uint32_t)0x11111111;
|
||||
y1 = y & (uint32_t)0x22222222;
|
||||
y2 = y & (uint32_t)0x44444444;
|
||||
y3 = y & (uint32_t)0x88888888;
|
||||
z0 = (x0 * y0) ^ (x1 * y3) ^ (x2 * y2) ^ (x3 * y1);
|
||||
z1 = (x0 * y1) ^ (x1 * y0) ^ (x2 * y3) ^ (x3 * y2);
|
||||
z2 = (x0 * y2) ^ (x1 * y1) ^ (x2 * y0) ^ (x3 * y3);
|
||||
z3 = (x0 * y3) ^ (x1 * y2) ^ (x2 * y1) ^ (x3 * y0);
|
||||
z0 &= (uint32_t)0x11111111;
|
||||
z1 &= (uint32_t)0x22222222;
|
||||
z2 &= (uint32_t)0x44444444;
|
||||
z3 &= (uint32_t)0x88888888;
|
||||
return z0 | z1 | z2 | z3;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bit-reverse a 32-bit word.
|
||||
*/
|
||||
static uint32_t
|
||||
rev32(uint32_t x)
|
||||
{
|
||||
#define RMS(m, s) do { \
|
||||
x = ((x & (uint32_t)(m)) << (s)) \
|
||||
| ((x >> (s)) & (uint32_t)(m)); \
|
||||
} while (0)
|
||||
|
||||
RMS(0x55555555, 1);
|
||||
RMS(0x33333333, 2);
|
||||
RMS(0x0F0F0F0F, 4);
|
||||
RMS(0x00FF00FF, 8);
|
||||
return (x << 16) | (x >> 16);
|
||||
|
||||
#undef RMS
|
||||
}
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
void
|
||||
br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len)
|
||||
{
|
||||
/*
|
||||
* This implementation is similar to br_ghash_ctmul() except
|
||||
* that we have to do the multiplication twice, with the
|
||||
* "normal" and "bit reversed" operands. Hence we end up with
|
||||
* eighteen 32-bit multiplications instead of nine.
|
||||
*/
|
||||
|
||||
const unsigned char *buf, *hb;
|
||||
unsigned char *yb;
|
||||
uint32_t yw[4];
|
||||
uint32_t hw[4], hwr[4];
|
||||
|
||||
buf = data;
|
||||
yb = y;
|
||||
hb = h;
|
||||
yw[3] = br_dec32be(yb);
|
||||
yw[2] = br_dec32be(yb + 4);
|
||||
yw[1] = br_dec32be(yb + 8);
|
||||
yw[0] = br_dec32be(yb + 12);
|
||||
hw[3] = br_dec32be(hb);
|
||||
hw[2] = br_dec32be(hb + 4);
|
||||
hw[1] = br_dec32be(hb + 8);
|
||||
hw[0] = br_dec32be(hb + 12);
|
||||
hwr[3] = rev32(hw[3]);
|
||||
hwr[2] = rev32(hw[2]);
|
||||
hwr[1] = rev32(hw[1]);
|
||||
hwr[0] = rev32(hw[0]);
|
||||
while (len > 0) {
|
||||
const unsigned char *src;
|
||||
unsigned char tmp[16];
|
||||
int i;
|
||||
uint32_t a[18], b[18], c[18];
|
||||
uint32_t d0, d1, d2, d3, d4, d5, d6, d7;
|
||||
uint32_t zw[8];
|
||||
|
||||
if (len >= 16) {
|
||||
src = buf;
|
||||
buf += 16;
|
||||
len -= 16;
|
||||
} else {
|
||||
memcpy(tmp, buf, len);
|
||||
memset(tmp + len, 0, (sizeof tmp) - len);
|
||||
src = tmp;
|
||||
len = 0;
|
||||
}
|
||||
yw[3] ^= br_dec32be(src);
|
||||
yw[2] ^= br_dec32be(src + 4);
|
||||
yw[1] ^= br_dec32be(src + 8);
|
||||
yw[0] ^= br_dec32be(src + 12);
|
||||
|
||||
/*
|
||||
* We are using Karatsuba: the 128x128 multiplication is
|
||||
* reduced to three 64x64 multiplications, hence nine
|
||||
* 32x32 multiplications. With the bit-reversal trick,
|
||||
* we have to perform 18 32x32 multiplications.
|
||||
*/
|
||||
|
||||
/*
|
||||
* y[0,1]*h[0,1] -> 0,1,4
|
||||
* y[2,3]*h[2,3] -> 2,3,5
|
||||
* (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6,7,8
|
||||
*/
|
||||
|
||||
a[0] = yw[0];
|
||||
a[1] = yw[1];
|
||||
a[2] = yw[2];
|
||||
a[3] = yw[3];
|
||||
a[4] = a[0] ^ a[1];
|
||||
a[5] = a[2] ^ a[3];
|
||||
a[6] = a[0] ^ a[2];
|
||||
a[7] = a[1] ^ a[3];
|
||||
a[8] = a[6] ^ a[7];
|
||||
|
||||
a[ 9] = rev32(yw[0]);
|
||||
a[10] = rev32(yw[1]);
|
||||
a[11] = rev32(yw[2]);
|
||||
a[12] = rev32(yw[3]);
|
||||
a[13] = a[ 9] ^ a[10];
|
||||
a[14] = a[11] ^ a[12];
|
||||
a[15] = a[ 9] ^ a[11];
|
||||
a[16] = a[10] ^ a[12];
|
||||
a[17] = a[15] ^ a[16];
|
||||
|
||||
b[0] = hw[0];
|
||||
b[1] = hw[1];
|
||||
b[2] = hw[2];
|
||||
b[3] = hw[3];
|
||||
b[4] = b[0] ^ b[1];
|
||||
b[5] = b[2] ^ b[3];
|
||||
b[6] = b[0] ^ b[2];
|
||||
b[7] = b[1] ^ b[3];
|
||||
b[8] = b[6] ^ b[7];
|
||||
|
||||
b[ 9] = hwr[0];
|
||||
b[10] = hwr[1];
|
||||
b[11] = hwr[2];
|
||||
b[12] = hwr[3];
|
||||
b[13] = b[ 9] ^ b[10];
|
||||
b[14] = b[11] ^ b[12];
|
||||
b[15] = b[ 9] ^ b[11];
|
||||
b[16] = b[10] ^ b[12];
|
||||
b[17] = b[15] ^ b[16];
|
||||
|
||||
for (i = 0; i < 18; i ++) {
|
||||
c[i] = bmul32(a[i], b[i]);
|
||||
}
|
||||
|
||||
c[4] ^= c[0] ^ c[1];
|
||||
c[5] ^= c[2] ^ c[3];
|
||||
c[8] ^= c[6] ^ c[7];
|
||||
|
||||
c[13] ^= c[ 9] ^ c[10];
|
||||
c[14] ^= c[11] ^ c[12];
|
||||
c[17] ^= c[15] ^ c[16];
|
||||
|
||||
/*
|
||||
* y[0,1]*h[0,1] -> 0,9^4,1^13,10
|
||||
* y[2,3]*h[2,3] -> 2,11^5,3^14,12
|
||||
* (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6,15^8,7^17,16
|
||||
*/
|
||||
d0 = c[0];
|
||||
d1 = c[4] ^ (rev32(c[9]) >> 1);
|
||||
d2 = c[1] ^ c[0] ^ c[2] ^ c[6] ^ (rev32(c[13]) >> 1);
|
||||
d3 = c[4] ^ c[5] ^ c[8]
|
||||
^ (rev32(c[10] ^ c[9] ^ c[11] ^ c[15]) >> 1);
|
||||
d4 = c[2] ^ c[1] ^ c[3] ^ c[7]
|
||||
^ (rev32(c[13] ^ c[14] ^ c[17]) >> 1);
|
||||
d5 = c[5] ^ (rev32(c[11] ^ c[10] ^ c[12] ^ c[16]) >> 1);
|
||||
d6 = c[3] ^ (rev32(c[14]) >> 1);
|
||||
d7 = rev32(c[12]) >> 1;
|
||||
|
||||
zw[0] = d0 << 1;
|
||||
zw[1] = (d1 << 1) | (d0 >> 31);
|
||||
zw[2] = (d2 << 1) | (d1 >> 31);
|
||||
zw[3] = (d3 << 1) | (d2 >> 31);
|
||||
zw[4] = (d4 << 1) | (d3 >> 31);
|
||||
zw[5] = (d5 << 1) | (d4 >> 31);
|
||||
zw[6] = (d6 << 1) | (d5 >> 31);
|
||||
zw[7] = (d7 << 1) | (d6 >> 31);
|
||||
|
||||
for (i = 0; i < 4; i ++) {
|
||||
uint32_t lw;
|
||||
|
||||
lw = zw[i];
|
||||
zw[i + 4] ^= lw ^ (lw >> 1) ^ (lw >> 2) ^ (lw >> 7);
|
||||
zw[i + 3] ^= (lw << 31) ^ (lw << 30) ^ (lw << 25);
|
||||
}
|
||||
memcpy(yw, zw + 4, sizeof yw);
|
||||
}
|
||||
br_enc32be(yb, yw[3]);
|
||||
br_enc32be(yb + 4, yw[2]);
|
||||
br_enc32be(yb + 8, yw[1]);
|
||||
br_enc32be(yb + 12, yw[0]);
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i15_add(uint16_t *a, const uint16_t *b, uint32_t ctl)
|
||||
{
|
||||
uint32_t cc;
|
||||
size_t u, m;
|
||||
|
||||
cc = 0;
|
||||
m = (a[0] + 31) >> 4;
|
||||
for (u = 1; u < m; u ++) {
|
||||
uint32_t aw, bw, naw;
|
||||
|
||||
aw = a[u];
|
||||
bw = b[u];
|
||||
naw = aw + bw + cc;
|
||||
cc = naw >> 15;
|
||||
a[u] = MUX(ctl, naw & 0x7FFF, aw);
|
||||
}
|
||||
return cc;
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i15_bit_length(uint16_t *x, size_t xlen)
|
||||
{
|
||||
uint32_t tw, twk;
|
||||
|
||||
tw = 0;
|
||||
twk = 0;
|
||||
while (xlen -- > 0) {
|
||||
uint32_t w, c;
|
||||
|
||||
c = EQ(tw, 0);
|
||||
w = x[xlen];
|
||||
tw = MUX(c, w, tw);
|
||||
twk = MUX(c, (uint32_t)xlen, twk);
|
||||
}
|
||||
return (twk << 4) + BIT_LENGTH(tw);
|
||||
}
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i15_decode_mod(uint16_t *x, const void *src, size_t len, const uint16_t *m)
|
||||
{
|
||||
/*
|
||||
* Two-pass algorithm: in the first pass, we determine whether the
|
||||
* value fits; in the second pass, we do the actual write.
|
||||
*
|
||||
* During the first pass, 'r' contains the comparison result so
|
||||
* far:
|
||||
* 0x00000000 value is equal to the modulus
|
||||
* 0x00000001 value is greater than the modulus
|
||||
* 0xFFFFFFFF value is lower than the modulus
|
||||
*
|
||||
* Since we iterate starting with the least significant bytes (at
|
||||
* the end of src[]), each new comparison overrides the previous
|
||||
* except when the comparison yields 0 (equal).
|
||||
*
|
||||
* During the second pass, 'r' is either 0xFFFFFFFF (value fits)
|
||||
* or 0x00000000 (value does not fit).
|
||||
*
|
||||
* We must iterate over all bytes of the source, _and_ possibly
|
||||
* some extra virtual bytes (with value 0) so as to cover the
|
||||
* complete modulus as well. We also add 4 such extra bytes beyond
|
||||
* the modulus length because it then guarantees that no accumulated
|
||||
* partial word remains to be processed.
|
||||
*/
|
||||
const unsigned char *buf;
|
||||
size_t mlen, tlen;
|
||||
int pass;
|
||||
uint32_t r;
|
||||
|
||||
buf = src;
|
||||
mlen = (m[0] + 15) >> 4;
|
||||
tlen = (mlen << 1);
|
||||
if (tlen < len) {
|
||||
tlen = len;
|
||||
}
|
||||
tlen += 4;
|
||||
r = 0;
|
||||
for (pass = 0; pass < 2; pass ++) {
|
||||
size_t u, v;
|
||||
uint32_t acc;
|
||||
int acc_len;
|
||||
|
||||
v = 1;
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
for (u = 0; u < tlen; u ++) {
|
||||
uint32_t b;
|
||||
|
||||
if (u < len) {
|
||||
b = buf[len - 1 - u];
|
||||
} else {
|
||||
b = 0;
|
||||
}
|
||||
acc |= (b << acc_len);
|
||||
acc_len += 8;
|
||||
if (acc_len >= 15) {
|
||||
uint32_t xw;
|
||||
|
||||
xw = acc & (uint32_t)0x7FFF;
|
||||
acc_len -= 15;
|
||||
acc = b >> (8 - acc_len);
|
||||
if (v <= mlen) {
|
||||
if (pass) {
|
||||
x[v] = r & xw;
|
||||
} else {
|
||||
uint32_t cc;
|
||||
|
||||
cc = (uint32_t)CMP(xw, m[v]);
|
||||
r = MUX(EQ(cc, 0), r, cc);
|
||||
}
|
||||
} else {
|
||||
if (!pass) {
|
||||
r = MUX(EQ(xw, 0), r, 1);
|
||||
}
|
||||
}
|
||||
v ++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* When we reach this point at the end of the first pass:
|
||||
* r is either 0, 1 or -1; we want to set r to 0 if it
|
||||
* is equal to 0 or 1, and leave it to -1 otherwise.
|
||||
*
|
||||
* When we reach this point at the end of the second pass:
|
||||
* r is either 0 or -1; we want to leave that value
|
||||
* untouched. This is a subcase of the previous.
|
||||
*/
|
||||
r >>= 1;
|
||||
r |= (r << 1);
|
||||
}
|
||||
|
||||
x[0] = m[0];
|
||||
return r & (uint32_t)1;
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i15_decode(uint16_t *x, const void *src, size_t len)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
size_t v;
|
||||
uint32_t acc;
|
||||
int acc_len;
|
||||
|
||||
buf = src;
|
||||
v = 1;
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
while (len -- > 0) {
|
||||
uint32_t b;
|
||||
|
||||
b = buf[len];
|
||||
acc |= (b << acc_len);
|
||||
acc_len += 8;
|
||||
if (acc_len >= 15) {
|
||||
x[v ++] = acc & 0x7FFF;
|
||||
acc_len -= 15;
|
||||
acc >>= 15;
|
||||
}
|
||||
}
|
||||
if (acc_len != 0) {
|
||||
x[v ++] = acc;
|
||||
}
|
||||
x[0] = br_i15_bit_length(x + 1, v - 1);
|
||||
}
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i15_decode_reduce(uint16_t *x,
|
||||
const void *src, size_t len, const uint16_t *m)
|
||||
{
|
||||
uint32_t m_ebitlen, m_rbitlen;
|
||||
size_t mblen, k;
|
||||
const unsigned char *buf;
|
||||
uint32_t acc;
|
||||
int acc_len;
|
||||
|
||||
/*
|
||||
* Get the encoded bit length.
|
||||
*/
|
||||
m_ebitlen = m[0];
|
||||
|
||||
/*
|
||||
* Special case for an invalid (null) modulus.
|
||||
*/
|
||||
if (m_ebitlen == 0) {
|
||||
x[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the destination.
|
||||
*/
|
||||
br_i15_zero(x, m_ebitlen);
|
||||
|
||||
/*
|
||||
* First decode directly as many bytes as possible. This requires
|
||||
* computing the actual bit length.
|
||||
*/
|
||||
m_rbitlen = m_ebitlen >> 4;
|
||||
m_rbitlen = (m_ebitlen & 15) + (m_rbitlen << 4) - m_rbitlen;
|
||||
mblen = (m_rbitlen + 7) >> 3;
|
||||
k = mblen - 1;
|
||||
if (k >= len) {
|
||||
br_i15_decode(x, src, len);
|
||||
x[0] = m_ebitlen;
|
||||
return;
|
||||
}
|
||||
buf = src;
|
||||
br_i15_decode(x, buf, k);
|
||||
x[0] = m_ebitlen;
|
||||
|
||||
/*
|
||||
* Input remaining bytes, using 15-bit words.
|
||||
*/
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
while (k < len) {
|
||||
uint32_t v;
|
||||
|
||||
v = buf[k ++];
|
||||
acc = (acc << 8) | v;
|
||||
acc_len += 8;
|
||||
if (acc_len >= 15) {
|
||||
br_i15_muladd_small(x, acc >> (acc_len - 15), m);
|
||||
acc_len -= 15;
|
||||
acc &= ~((uint32_t)-1 << acc_len);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We may have some bits accumulated. We then perform a shift to
|
||||
* be able to inject these bits as a full 15-bit word.
|
||||
*/
|
||||
if (acc_len != 0) {
|
||||
acc = (acc | (x[1] << acc_len)) & 0x7FFF;
|
||||
br_i15_rshift(x, 15 - acc_len);
|
||||
br_i15_muladd_small(x, acc, m);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i15_encode(void *dst, size_t len, const uint16_t *x)
|
||||
{
|
||||
unsigned char *buf;
|
||||
size_t u, xlen;
|
||||
uint32_t acc;
|
||||
int acc_len;
|
||||
|
||||
xlen = (x[0] + 15) >> 4;
|
||||
if (xlen == 0) {
|
||||
memset(dst, 0, len);
|
||||
return;
|
||||
}
|
||||
u = 1;
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
buf = dst;
|
||||
while (len -- > 0) {
|
||||
if (acc_len < 8) {
|
||||
if (u <= xlen) {
|
||||
acc += (uint32_t)x[u ++] << acc_len;
|
||||
}
|
||||
acc_len += 15;
|
||||
}
|
||||
buf[len] = (unsigned char)acc;
|
||||
acc >>= 8;
|
||||
acc_len -= 8;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i15_from_monty(uint16_t *x, const uint16_t *m, uint16_t m0i)
|
||||
{
|
||||
size_t len, u, v;
|
||||
|
||||
len = (m[0] + 15) >> 4;
|
||||
for (u = 0; u < len; u ++) {
|
||||
uint32_t f, cc;
|
||||
|
||||
f = MUL15(x[1], m0i) & 0x7FFF;
|
||||
cc = 0;
|
||||
for (v = 0; v < len; v ++) {
|
||||
uint32_t z;
|
||||
|
||||
z = (uint32_t)x[v + 1] + MUL15(f, m[v + 1]) + cc;
|
||||
cc = z >> 15;
|
||||
if (v != 0) {
|
||||
x[v] = z & 0x7FFF;
|
||||
}
|
||||
}
|
||||
x[len] = cc;
|
||||
}
|
||||
|
||||
/*
|
||||
* We may have to do an extra subtraction, but only if the
|
||||
* value in x[] is indeed greater than or equal to that of m[],
|
||||
* which is why we must do two calls (first call computes the
|
||||
* carry, second call performs the subtraction only if the carry
|
||||
* is 0).
|
||||
*/
|
||||
br_i15_sub(x, m, NOT(br_i15_sub(x, m, 0)));
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i15_iszero(const uint16_t *x)
|
||||
{
|
||||
uint32_t z;
|
||||
size_t u;
|
||||
|
||||
z = 0;
|
||||
for (u = (x[0] + 15) >> 4; u > 0; u --) {
|
||||
z |= x[u];
|
||||
}
|
||||
return ~(z | -z) >> 31;
|
||||
}
|
||||
|
|
@ -1,465 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* In this file, we handle big integers with a custom format, i.e.
|
||||
* without the usual one-word header. Value is split into 15-bit words,
|
||||
* each stored in a 16-bit slot (top bit is zero) in little-endian
|
||||
* order. The length (in words) is provided explicitly. In some cases,
|
||||
* the value can be negative (using two's complement representation). In
|
||||
* some cases, the top word is allowed to have a 16th bit.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Negate big integer conditionally. The value consists of 'len' words,
|
||||
* with 15 bits in each word (the top bit of each word should be 0,
|
||||
* except possibly for the last word). If 'ctl' is 1, the negation is
|
||||
* computed; otherwise, if 'ctl' is 0, then the value is unchanged.
|
||||
*/
|
||||
static void
|
||||
cond_negate(uint16_t *a, size_t len, uint32_t ctl)
|
||||
{
|
||||
size_t k;
|
||||
uint32_t cc, xm;
|
||||
|
||||
cc = ctl;
|
||||
xm = 0x7FFF & -ctl;
|
||||
for (k = 0; k < len; k ++) {
|
||||
uint32_t aw;
|
||||
|
||||
aw = a[k];
|
||||
aw = (aw ^ xm) + cc;
|
||||
a[k] = aw & 0x7FFF;
|
||||
cc = (aw >> 15) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish modular reduction. Rules on input parameters:
|
||||
*
|
||||
* if neg = 1, then -m <= a < 0
|
||||
* if neg = 0, then 0 <= a < 2*m
|
||||
*
|
||||
* If neg = 0, then the top word of a[] may use 16 bits.
|
||||
*
|
||||
* Also, modulus m must be odd.
|
||||
*/
|
||||
static void
|
||||
finish_mod(uint16_t *a, size_t len, const uint16_t *m, uint32_t neg)
|
||||
{
|
||||
size_t k;
|
||||
uint32_t cc, xm, ym;
|
||||
|
||||
/*
|
||||
* First pass: compare a (assumed nonnegative) with m.
|
||||
*/
|
||||
cc = 0;
|
||||
for (k = 0; k < len; k ++) {
|
||||
uint32_t aw, mw;
|
||||
|
||||
aw = a[k];
|
||||
mw = m[k];
|
||||
cc = (aw - mw - cc) >> 31;
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point:
|
||||
* if neg = 1, then we must add m (regardless of cc)
|
||||
* if neg = 0 and cc = 0, then we must subtract m
|
||||
* if neg = 0 and cc = 1, then we must do nothing
|
||||
*/
|
||||
xm = 0x7FFF & -neg;
|
||||
ym = -(neg | (1 - cc));
|
||||
cc = neg;
|
||||
for (k = 0; k < len; k ++) {
|
||||
uint32_t aw, mw;
|
||||
|
||||
aw = a[k];
|
||||
mw = (m[k] ^ xm) & ym;
|
||||
aw = aw - mw - cc;
|
||||
a[k] = aw & 0x7FFF;
|
||||
cc = aw >> 31;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute:
|
||||
* a <- (a*pa+b*pb)/(2^15)
|
||||
* b <- (a*qa+b*qb)/(2^15)
|
||||
* The division is assumed to be exact (i.e. the low word is dropped).
|
||||
* If the final a is negative, then it is negated. Similarly for b.
|
||||
* Returned value is the combination of two bits:
|
||||
* bit 0: 1 if a had to be negated, 0 otherwise
|
||||
* bit 1: 1 if b had to be negated, 0 otherwise
|
||||
*
|
||||
* Factors pa, pb, qa and qb must be at most 2^15 in absolute value.
|
||||
* Source integers a and b must be nonnegative; top word is not allowed
|
||||
* to contain an extra 16th bit.
|
||||
*/
|
||||
static uint32_t
|
||||
co_reduce(uint16_t *a, uint16_t *b, size_t len,
|
||||
int32_t pa, int32_t pb, int32_t qa, int32_t qb)
|
||||
{
|
||||
size_t k;
|
||||
int32_t cca, ccb;
|
||||
uint32_t nega, negb;
|
||||
|
||||
cca = 0;
|
||||
ccb = 0;
|
||||
for (k = 0; k < len; k ++) {
|
||||
uint32_t wa, wb, za, zb;
|
||||
uint16_t tta, ttb;
|
||||
|
||||
/*
|
||||
* Since:
|
||||
* |pa| <= 2^15
|
||||
* |pb| <= 2^15
|
||||
* 0 <= wa <= 2^15 - 1
|
||||
* 0 <= wb <= 2^15 - 1
|
||||
* |cca| <= 2^16 - 1
|
||||
* Then:
|
||||
* |za| <= (2^15-1)*(2^16) + (2^16-1) = 2^31 - 1
|
||||
*
|
||||
* Thus, the new value of cca is such that |cca| <= 2^16 - 1.
|
||||
* The same applies to ccb.
|
||||
*/
|
||||
wa = a[k];
|
||||
wb = b[k];
|
||||
za = wa * (uint32_t)pa + wb * (uint32_t)pb + (uint32_t)cca;
|
||||
zb = wa * (uint32_t)qa + wb * (uint32_t)qb + (uint32_t)ccb;
|
||||
if (k > 0) {
|
||||
a[k - 1] = za & 0x7FFF;
|
||||
b[k - 1] = zb & 0x7FFF;
|
||||
}
|
||||
tta = za >> 15;
|
||||
ttb = zb >> 15;
|
||||
cca = *(int16_t *)&tta;
|
||||
ccb = *(int16_t *)&ttb;
|
||||
}
|
||||
a[len - 1] = (uint16_t)cca;
|
||||
b[len - 1] = (uint16_t)ccb;
|
||||
nega = (uint32_t)cca >> 31;
|
||||
negb = (uint32_t)ccb >> 31;
|
||||
cond_negate(a, len, nega);
|
||||
cond_negate(b, len, negb);
|
||||
return nega | (negb << 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute:
|
||||
* a <- (a*pa+b*pb)/(2^15) mod m
|
||||
* b <- (a*qa+b*qb)/(2^15) mod m
|
||||
*
|
||||
* m0i is equal to -1/m[0] mod 2^15.
|
||||
*
|
||||
* Factors pa, pb, qa and qb must be at most 2^15 in absolute value.
|
||||
* Source integers a and b must be nonnegative; top word is not allowed
|
||||
* to contain an extra 16th bit.
|
||||
*/
|
||||
static void
|
||||
co_reduce_mod(uint16_t *a, uint16_t *b, size_t len,
|
||||
int32_t pa, int32_t pb, int32_t qa, int32_t qb,
|
||||
const uint16_t *m, uint16_t m0i)
|
||||
{
|
||||
size_t k;
|
||||
int32_t cca, ccb, fa, fb;
|
||||
|
||||
cca = 0;
|
||||
ccb = 0;
|
||||
fa = ((a[0] * (uint32_t)pa + b[0] * (uint32_t)pb) * m0i) & 0x7FFF;
|
||||
fb = ((a[0] * (uint32_t)qa + b[0] * (uint32_t)qb) * m0i) & 0x7FFF;
|
||||
for (k = 0; k < len; k ++) {
|
||||
uint32_t wa, wb, za, zb;
|
||||
uint32_t tta, ttb;
|
||||
|
||||
/*
|
||||
* In this loop, carries 'cca' and 'ccb' always fit on
|
||||
* 17 bits (in absolute value).
|
||||
*/
|
||||
wa = a[k];
|
||||
wb = b[k];
|
||||
za = wa * (uint32_t)pa + wb * (uint32_t)pb
|
||||
+ m[k] * (uint32_t)fa + (uint32_t)cca;
|
||||
zb = wa * (uint32_t)qa + wb * (uint32_t)qb
|
||||
+ m[k] * (uint32_t)fb + (uint32_t)ccb;
|
||||
if (k > 0) {
|
||||
a[k - 1] = za & 0x7FFF;
|
||||
b[k - 1] = zb & 0x7FFF;
|
||||
}
|
||||
|
||||
/*
|
||||
* The XOR-and-sub construction below does an arithmetic
|
||||
* right shift in a portable way (technically, right-shifting
|
||||
* a negative signed value is implementation-defined in C).
|
||||
*/
|
||||
#define M ((uint32_t)1 << 16)
|
||||
tta = za >> 15;
|
||||
ttb = zb >> 15;
|
||||
tta = (tta ^ M) - M;
|
||||
ttb = (ttb ^ M) - M;
|
||||
cca = *(int32_t *)&tta;
|
||||
ccb = *(int32_t *)&ttb;
|
||||
#undef M
|
||||
}
|
||||
a[len - 1] = (uint32_t)cca;
|
||||
b[len - 1] = (uint32_t)ccb;
|
||||
|
||||
/*
|
||||
* At this point:
|
||||
* -m <= a < 2*m
|
||||
* -m <= b < 2*m
|
||||
* (this is a case of Montgomery reduction)
|
||||
* The top word of 'a' and 'b' may have a 16-th bit set.
|
||||
* We may have to add or subtract the modulus.
|
||||
*/
|
||||
finish_mod(a, len, m, (uint32_t)cca >> 31);
|
||||
finish_mod(b, len, m, (uint32_t)ccb >> 31);
|
||||
}
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i15_moddiv(uint16_t *x, const uint16_t *y, const uint16_t *m, uint16_t m0i,
|
||||
uint16_t *t)
|
||||
{
|
||||
/*
|
||||
* Algorithm is an extended binary GCD. We maintain four values
|
||||
* a, b, u and v, with the following invariants:
|
||||
*
|
||||
* a * x = y * u mod m
|
||||
* b * x = y * v mod m
|
||||
*
|
||||
* Starting values are:
|
||||
*
|
||||
* a = y
|
||||
* b = m
|
||||
* u = x
|
||||
* v = 0
|
||||
*
|
||||
* The formal definition of the algorithm is a sequence of steps:
|
||||
*
|
||||
* - If a is even, then a <- a/2 and u <- u/2 mod m.
|
||||
* - Otherwise, if b is even, then b <- b/2 and v <- v/2 mod m.
|
||||
* - Otherwise, if a > b, then a <- (a-b)/2 and u <- (u-v)/2 mod m.
|
||||
* - Otherwise, b <- (b-a)/2 and v <- (v-u)/2 mod m.
|
||||
*
|
||||
* Algorithm stops when a = b. At that point, they both are equal
|
||||
* to GCD(y,m); the modular division succeeds if that value is 1.
|
||||
* The result of the modular division is then u (or v: both are
|
||||
* equal at that point).
|
||||
*
|
||||
* Each step makes either a or b shrink by at least one bit; hence,
|
||||
* if m has bit length k bits, then 2k-2 steps are sufficient.
|
||||
*
|
||||
*
|
||||
* Though complexity is quadratic in the size of m, the bit-by-bit
|
||||
* processing is not very efficient. We can speed up processing by
|
||||
* remarking that the decisions are taken based only on observation
|
||||
* of the top and low bits of a and b.
|
||||
*
|
||||
* In the loop below, at each iteration, we use the two top words
|
||||
* of a and b, and the low words of a and b, to compute reduction
|
||||
* parameters pa, pb, qa and qb such that the new values for a
|
||||
* and b are:
|
||||
*
|
||||
* a' = (a*pa + b*pb) / (2^15)
|
||||
* b' = (a*qa + b*qb) / (2^15)
|
||||
*
|
||||
* the division being exact.
|
||||
*
|
||||
* Since the choices are based on the top words, they may be slightly
|
||||
* off, requiring an optional correction: if a' < 0, then we replace
|
||||
* pa with -pa, and pb with -pb. The total length of a and b is
|
||||
* thus reduced by at least 14 bits at each iteration.
|
||||
*
|
||||
* The stopping conditions are still the same, though: when a
|
||||
* and b become equal, they must be both odd (since m is odd,
|
||||
* the GCD cannot be even), therefore the next operation is a
|
||||
* subtraction, and one of the values becomes 0. At that point,
|
||||
* nothing else happens, i.e. one value is stuck at 0, and the
|
||||
* other one is the GCD.
|
||||
*/
|
||||
size_t len, k;
|
||||
uint16_t *a, *b, *u, *v;
|
||||
uint32_t num, r;
|
||||
|
||||
len = (m[0] + 15) >> 4;
|
||||
a = t;
|
||||
b = a + len;
|
||||
u = x + 1;
|
||||
v = b + len;
|
||||
memcpy(a, y + 1, len * sizeof *y);
|
||||
memcpy(b, m + 1, len * sizeof *m);
|
||||
memset(v, 0, len * sizeof *v);
|
||||
|
||||
/*
|
||||
* Loop below ensures that a and b are reduced by some bits each,
|
||||
* for a total of at least 14 bits.
|
||||
*/
|
||||
for (num = ((m[0] - (m[0] >> 4)) << 1) + 14; num >= 14; num -= 14) {
|
||||
size_t j;
|
||||
uint32_t c0, c1;
|
||||
uint32_t a0, a1, b0, b1;
|
||||
uint32_t a_hi, b_hi, a_lo, b_lo;
|
||||
int32_t pa, pb, qa, qb;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Extract top words of a and b. If j is the highest
|
||||
* index >= 1 such that a[j] != 0 or b[j] != 0, then we want
|
||||
* (a[j] << 15) + a[j - 1], and (b[j] << 15) + b[j - 1].
|
||||
* If a and b are down to one word each, then we use a[0]
|
||||
* and b[0].
|
||||
*/
|
||||
c0 = (uint32_t)-1;
|
||||
c1 = (uint32_t)-1;
|
||||
a0 = 0;
|
||||
a1 = 0;
|
||||
b0 = 0;
|
||||
b1 = 0;
|
||||
j = len;
|
||||
while (j -- > 0) {
|
||||
uint32_t aw, bw;
|
||||
|
||||
aw = a[j];
|
||||
bw = b[j];
|
||||
a0 ^= (a0 ^ aw) & c0;
|
||||
a1 ^= (a1 ^ aw) & c1;
|
||||
b0 ^= (b0 ^ bw) & c0;
|
||||
b1 ^= (b1 ^ bw) & c1;
|
||||
c1 = c0;
|
||||
c0 &= (((aw | bw) + 0xFFFF) >> 16) - (uint32_t)1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If c1 = 0, then we grabbed two words for a and b.
|
||||
* If c1 != 0 but c0 = 0, then we grabbed one word. It
|
||||
* is not possible that c1 != 0 and c0 != 0, because that
|
||||
* would mean that both integers are zero.
|
||||
*/
|
||||
a1 |= a0 & c1;
|
||||
a0 &= ~c1;
|
||||
b1 |= b0 & c1;
|
||||
b0 &= ~c1;
|
||||
a_hi = (a0 << 15) + a1;
|
||||
b_hi = (b0 << 15) + b1;
|
||||
a_lo = a[0];
|
||||
b_lo = b[0];
|
||||
|
||||
/*
|
||||
* Compute reduction factors:
|
||||
*
|
||||
* a' = a*pa + b*pb
|
||||
* b' = a*qa + b*qb
|
||||
*
|
||||
* such that a' and b' are both multiple of 2^15, but are
|
||||
* only marginally larger than a and b.
|
||||
*/
|
||||
pa = 1;
|
||||
pb = 0;
|
||||
qa = 0;
|
||||
qb = 1;
|
||||
for (i = 0; i < 15; i ++) {
|
||||
/*
|
||||
* At each iteration:
|
||||
*
|
||||
* a <- (a-b)/2 if: a is odd, b is odd, a_hi > b_hi
|
||||
* b <- (b-a)/2 if: a is odd, b is odd, a_hi <= b_hi
|
||||
* a <- a/2 if: a is even
|
||||
* b <- b/2 if: a is odd, b is even
|
||||
*
|
||||
* We multiply a_lo and b_lo by 2 at each
|
||||
* iteration, thus a division by 2 really is a
|
||||
* non-multiplication by 2.
|
||||
*/
|
||||
uint32_t r, oa, ob, cAB, cBA, cA;
|
||||
|
||||
/*
|
||||
* cAB = 1 if b must be subtracted from a
|
||||
* cBA = 1 if a must be subtracted from b
|
||||
* cA = 1 if a is divided by 2, 0 otherwise
|
||||
*
|
||||
* Rules:
|
||||
*
|
||||
* cAB and cBA cannot be both 1.
|
||||
* if a is not divided by 2, b is.
|
||||
*/
|
||||
r = GT(a_hi, b_hi);
|
||||
oa = (a_lo >> i) & 1;
|
||||
ob = (b_lo >> i) & 1;
|
||||
cAB = oa & ob & r;
|
||||
cBA = oa & ob & NOT(r);
|
||||
cA = cAB | NOT(oa);
|
||||
|
||||
/*
|
||||
* Conditional subtractions.
|
||||
*/
|
||||
a_lo -= b_lo & -cAB;
|
||||
a_hi -= b_hi & -cAB;
|
||||
pa -= qa & -(int32_t)cAB;
|
||||
pb -= qb & -(int32_t)cAB;
|
||||
b_lo -= a_lo & -cBA;
|
||||
b_hi -= a_hi & -cBA;
|
||||
qa -= pa & -(int32_t)cBA;
|
||||
qb -= pb & -(int32_t)cBA;
|
||||
|
||||
/*
|
||||
* Shifting.
|
||||
*/
|
||||
a_lo += a_lo & (cA - 1);
|
||||
pa += pa & ((int32_t)cA - 1);
|
||||
pb += pb & ((int32_t)cA - 1);
|
||||
a_hi ^= (a_hi ^ (a_hi >> 1)) & -cA;
|
||||
b_lo += b_lo & -cA;
|
||||
qa += qa & -(int32_t)cA;
|
||||
qb += qb & -(int32_t)cA;
|
||||
b_hi ^= (b_hi ^ (b_hi >> 1)) & (cA - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Replace a and b with new values a' and b'.
|
||||
*/
|
||||
r = co_reduce(a, b, len, pa, pb, qa, qb);
|
||||
pa -= pa * ((r & 1) << 1);
|
||||
pb -= pb * ((r & 1) << 1);
|
||||
qa -= qa * (r & 2);
|
||||
qb -= qb * (r & 2);
|
||||
co_reduce_mod(u, v, len, pa, pb, qa, qb, m + 1, m0i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now one of the arrays should be 0, and the other contains
|
||||
* the GCD. If a is 0, then u is 0 as well, and v contains
|
||||
* the division result.
|
||||
* Result is correct if and only if GCD is 1.
|
||||
*/
|
||||
r = (a[0] | b[0]) ^ 1;
|
||||
u[0] |= v[0];
|
||||
for (k = 1; k < len; k ++) {
|
||||
r |= a[k] | b[k];
|
||||
u[k] |= v[k];
|
||||
}
|
||||
return EQ0(r);
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i15_modpow(uint16_t *x,
|
||||
const unsigned char *e, size_t elen,
|
||||
const uint16_t *m, uint16_t m0i, uint16_t *t1, uint16_t *t2)
|
||||
{
|
||||
size_t mlen;
|
||||
unsigned k;
|
||||
|
||||
mlen = ((m[0] + 31) >> 4) * sizeof m[0];
|
||||
memcpy(t1, x, mlen);
|
||||
br_i15_to_monty(t1, m);
|
||||
br_i15_zero(x, m[0]);
|
||||
x[1] = 1;
|
||||
for (k = 0; k < ((unsigned)elen << 3); k ++) {
|
||||
uint32_t ctl;
|
||||
|
||||
ctl = (e[elen - 1 - (k >> 3)] >> (k & 7)) & 1;
|
||||
br_i15_montymul(t2, x, t1, m, m0i);
|
||||
CCOPY(ctl, x, t2, mlen);
|
||||
br_i15_montymul(t2, t1, t1, m, m0i);
|
||||
memcpy(t1, t2, mlen);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,160 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i15_modpow_opt(uint16_t *x,
|
||||
const unsigned char *e, size_t elen,
|
||||
const uint16_t *m, uint16_t m0i, uint16_t *tmp, size_t twlen)
|
||||
{
|
||||
size_t mlen, mwlen;
|
||||
uint16_t *t1, *t2, *base;
|
||||
size_t u, v;
|
||||
uint32_t acc;
|
||||
int acc_len, win_len;
|
||||
|
||||
/*
|
||||
* Get modulus size.
|
||||
*/
|
||||
mwlen = (m[0] + 31) >> 4;
|
||||
mlen = mwlen * sizeof m[0];
|
||||
mwlen += (mwlen & 1);
|
||||
t1 = tmp;
|
||||
t2 = tmp + mwlen;
|
||||
|
||||
/*
|
||||
* Compute possible window size, with a maximum of 5 bits.
|
||||
* When the window has size 1 bit, we use a specific code
|
||||
* that requires only two temporaries. Otherwise, for a
|
||||
* window of k bits, we need 2^k+1 temporaries.
|
||||
*/
|
||||
if (twlen < (mwlen << 1)) {
|
||||
return 0;
|
||||
}
|
||||
for (win_len = 5; win_len > 1; win_len --) {
|
||||
if ((((uint32_t)1 << win_len) + 1) * mwlen <= twlen) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Everything is done in Montgomery representation.
|
||||
*/
|
||||
br_i15_to_monty(x, m);
|
||||
|
||||
/*
|
||||
* Compute window contents. If the window has size one bit only,
|
||||
* then t2 is set to x; otherwise, t2[0] is left untouched, and
|
||||
* t2[k] is set to x^k (for k >= 1).
|
||||
*/
|
||||
if (win_len == 1) {
|
||||
memcpy(t2, x, mlen);
|
||||
} else {
|
||||
memcpy(t2 + mwlen, x, mlen);
|
||||
base = t2 + mwlen;
|
||||
for (u = 2; u < ((unsigned)1 << win_len); u ++) {
|
||||
br_i15_montymul(base + mwlen, base, x, m, m0i);
|
||||
base += mwlen;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to set x to 1, in Montgomery representation. This can
|
||||
* be done efficiently by setting the high word to 1, then doing
|
||||
* one word-sized shift.
|
||||
*/
|
||||
br_i15_zero(x, m[0]);
|
||||
x[(m[0] + 15) >> 4] = 1;
|
||||
br_i15_muladd_small(x, 0, m);
|
||||
|
||||
/*
|
||||
* We process bits from most to least significant. At each
|
||||
* loop iteration, we have acc_len bits in acc.
|
||||
*/
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
while (acc_len > 0 || elen > 0) {
|
||||
int i, k;
|
||||
uint32_t bits;
|
||||
|
||||
/*
|
||||
* Get the next bits.
|
||||
*/
|
||||
k = win_len;
|
||||
if (acc_len < win_len) {
|
||||
if (elen > 0) {
|
||||
acc = (acc << 8) | *e ++;
|
||||
elen --;
|
||||
acc_len += 8;
|
||||
} else {
|
||||
k = acc_len;
|
||||
}
|
||||
}
|
||||
bits = (acc >> (acc_len - k)) & (((uint32_t)1 << k) - 1);
|
||||
acc_len -= k;
|
||||
|
||||
/*
|
||||
* We could get exactly k bits. Compute k squarings.
|
||||
*/
|
||||
for (i = 0; i < k; i ++) {
|
||||
br_i15_montymul(t1, x, x, m, m0i);
|
||||
memcpy(x, t1, mlen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Window lookup: we want to set t2 to the window
|
||||
* lookup value, assuming the bits are non-zero. If
|
||||
* the window length is 1 bit only, then t2 is
|
||||
* already set; otherwise, we do a constant-time lookup.
|
||||
*/
|
||||
if (win_len > 1) {
|
||||
br_i15_zero(t2, m[0]);
|
||||
base = t2 + mwlen;
|
||||
for (u = 1; u < ((uint32_t)1 << k); u ++) {
|
||||
uint32_t mask;
|
||||
|
||||
mask = -EQ(u, bits);
|
||||
for (v = 1; v < mwlen; v ++) {
|
||||
t2[v] |= mask & base[v];
|
||||
}
|
||||
base += mwlen;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Multiply with the looked-up value. We keep the
|
||||
* product only if the exponent bits are not all-zero.
|
||||
*/
|
||||
br_i15_montymul(t1, x, t2, m, m0i);
|
||||
CCOPY(NEQ(bits, 0), x, t1, mlen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert back from Montgomery representation, and exit.
|
||||
*/
|
||||
br_i15_from_monty(x, m, m0i);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1,184 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i15_montymul(uint16_t *d, const uint16_t *x, const uint16_t *y,
|
||||
const uint16_t *m, uint16_t m0i)
|
||||
{
|
||||
size_t len, len4, u, v;
|
||||
uint32_t dh;
|
||||
|
||||
len = (m[0] + 15) >> 4;
|
||||
len4 = len & ~(size_t)3;
|
||||
br_i15_zero(d, m[0]);
|
||||
dh = 0;
|
||||
for (u = 0; u < len; u ++) {
|
||||
uint32_t f, xu, r, zh;
|
||||
|
||||
xu = x[u + 1];
|
||||
f = MUL15((d[1] + MUL15(x[u + 1], y[1])) & 0x7FFF, m0i)
|
||||
& 0x7FFF;
|
||||
#if BR_ARMEL_CORTEXM_GCC
|
||||
if (len4 != 0) {
|
||||
uint16_t *limit;
|
||||
|
||||
limit = d + len4;
|
||||
asm volatile (
|
||||
"\n\
|
||||
@ carry: r=r2 \n\
|
||||
@ multipliers: xu=r3 f=r4 \n\
|
||||
@ base registers: d+v=r5 y+v=r6 m+v=r7 \n\
|
||||
@ r8 contains 0x7FFF \n\
|
||||
@ r9 contains d+len4 \n\
|
||||
ldr r0, %[limit] \n\
|
||||
ldr r3, %[xu] \n\
|
||||
mov r9, r0 \n\
|
||||
ldr r4, %[f] \n\
|
||||
eor r2, r2 \n\
|
||||
ldr r5, %[d] \n\
|
||||
sub r1, r2, #1 \n\
|
||||
ldr r6, %[y] \n\
|
||||
lsr r1, r1, #17 \n\
|
||||
ldr r7, %[m] \n\
|
||||
mov r8, r1 \n\
|
||||
loop%=: \n\
|
||||
ldrh r0, [r6, #2] \n\
|
||||
ldrh r1, [r7, #2] \n\
|
||||
mul r0, r3 \n\
|
||||
mul r1, r4 \n\
|
||||
add r2, r0, r2 \n\
|
||||
ldrh r0, [r5, #2] \n\
|
||||
add r2, r1, r2 \n\
|
||||
mov r1, r8 \n\
|
||||
add r2, r0, r2 \n\
|
||||
and r1, r2 \n\
|
||||
lsr r2, r2, #15 \n\
|
||||
strh r1, [r5, #0] \n\
|
||||
\n\
|
||||
ldrh r0, [r6, #4] \n\
|
||||
ldrh r1, [r7, #4] \n\
|
||||
mul r0, r3 \n\
|
||||
mul r1, r4 \n\
|
||||
add r2, r0, r2 \n\
|
||||
ldrh r0, [r5, #4] \n\
|
||||
add r2, r1, r2 \n\
|
||||
mov r1, r8 \n\
|
||||
add r2, r0, r2 \n\
|
||||
and r1, r2 \n\
|
||||
lsr r2, r2, #15 \n\
|
||||
strh r1, [r5, #2] \n\
|
||||
\n\
|
||||
ldrh r0, [r6, #6] \n\
|
||||
ldrh r1, [r7, #6] \n\
|
||||
mul r0, r3 \n\
|
||||
mul r1, r4 \n\
|
||||
add r2, r0, r2 \n\
|
||||
ldrh r0, [r5, #6] \n\
|
||||
add r2, r1, r2 \n\
|
||||
mov r1, r8 \n\
|
||||
add r2, r0, r2 \n\
|
||||
and r1, r2 \n\
|
||||
lsr r2, r2, #15 \n\
|
||||
strh r1, [r5, #4] \n\
|
||||
\n\
|
||||
ldrh r0, [r6, #8] \n\
|
||||
ldrh r1, [r7, #8] \n\
|
||||
mul r0, r3 \n\
|
||||
mul r1, r4 \n\
|
||||
add r2, r0, r2 \n\
|
||||
ldrh r0, [r5, #8] \n\
|
||||
add r2, r1, r2 \n\
|
||||
mov r1, r8 \n\
|
||||
add r2, r0, r2 \n\
|
||||
and r1, r2 \n\
|
||||
lsr r2, r2, #15 \n\
|
||||
strh r1, [r5, #6] \n\
|
||||
\n\
|
||||
add r5, r5, #8 \n\
|
||||
add r6, r6, #8 \n\
|
||||
add r7, r7, #8 \n\
|
||||
cmp r5, r9 \n\
|
||||
bne loop%= \n\
|
||||
\n\
|
||||
str r2, %[carry] \n\
|
||||
"
|
||||
: [carry] "=m" (r)
|
||||
: [xu] "m" (xu), [f] "m" (f), [d] "m" (d), [y] "m" (y),
|
||||
[m] "m" (m), [limit] "m" (limit)
|
||||
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
|
||||
} else {
|
||||
r = 0;
|
||||
}
|
||||
v = len4;
|
||||
#else
|
||||
r = 0;
|
||||
for (v = 0; v < len4; v += 4) {
|
||||
uint32_t z;
|
||||
|
||||
z = d[v + 1] + MUL15(xu, y[v + 1])
|
||||
+ MUL15(f, m[v + 1]) + r;
|
||||
r = z >> 15;
|
||||
d[v + 0] = z & 0x7FFF;
|
||||
z = d[v + 2] + MUL15(xu, y[v + 2])
|
||||
+ MUL15(f, m[v + 2]) + r;
|
||||
r = z >> 15;
|
||||
d[v + 1] = z & 0x7FFF;
|
||||
z = d[v + 3] + MUL15(xu, y[v + 3])
|
||||
+ MUL15(f, m[v + 3]) + r;
|
||||
r = z >> 15;
|
||||
d[v + 2] = z & 0x7FFF;
|
||||
z = d[v + 4] + MUL15(xu, y[v + 4])
|
||||
+ MUL15(f, m[v + 4]) + r;
|
||||
r = z >> 15;
|
||||
d[v + 3] = z & 0x7FFF;
|
||||
}
|
||||
#endif
|
||||
for (; v < len; v ++) {
|
||||
uint32_t z;
|
||||
|
||||
z = d[v + 1] + MUL15(xu, y[v + 1])
|
||||
+ MUL15(f, m[v + 1]) + r;
|
||||
r = z >> 15;
|
||||
d[v + 0] = z & 0x7FFF;
|
||||
}
|
||||
|
||||
zh = dh + r;
|
||||
d[len] = zh & 0x7FFF;
|
||||
dh = zh >> 15;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore the bit length (it was overwritten in the loop above).
|
||||
*/
|
||||
d[0] = m[0];
|
||||
|
||||
/*
|
||||
* d[] may be greater than m[], but it is still lower than twice
|
||||
* the modulus.
|
||||
*/
|
||||
br_i15_sub(d, m, NEQ(dh, 0) | NOT(br_i15_sub(d, m, 0)));
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i15_mulacc(uint16_t *d, const uint16_t *a, const uint16_t *b)
|
||||
{
|
||||
size_t alen, blen, u;
|
||||
unsigned dl, dh;
|
||||
|
||||
alen = (a[0] + 15) >> 4;
|
||||
blen = (b[0] + 15) >> 4;
|
||||
|
||||
/*
|
||||
* Announced bit length of d[] will be the sum of the announced
|
||||
* bit lengths of a[] and b[]; but the lengths are encoded.
|
||||
*/
|
||||
dl = (a[0] & 15) + (b[0] & 15);
|
||||
dh = (a[0] >> 4) + (b[0] >> 4);
|
||||
d[0] = (dh << 4) + dl + (~(uint32_t)(dl - 15) >> 31);
|
||||
|
||||
for (u = 0; u < blen; u ++) {
|
||||
uint32_t f;
|
||||
size_t v;
|
||||
uint32_t cc;
|
||||
|
||||
f = b[1 + u];
|
||||
cc = 0;
|
||||
for (v = 0; v < alen; v ++) {
|
||||
uint32_t z;
|
||||
|
||||
z = (uint32_t)d[1 + u + v] + MUL15(f, a[1 + v]) + cc;
|
||||
cc = z >> 15;
|
||||
d[1 + u + v] = z & 0x7FFF;
|
||||
}
|
||||
d[1 + u + alen] = cc;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,173 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Constant-time division. The divisor must not be larger than 16 bits,
|
||||
* and the quotient must fit on 17 bits.
|
||||
*/
|
||||
static uint32_t
|
||||
divrem16(uint32_t x, uint32_t d, uint32_t *r)
|
||||
{
|
||||
int i;
|
||||
uint32_t q;
|
||||
|
||||
q = 0;
|
||||
d <<= 16;
|
||||
for (i = 16; i >= 0; i --) {
|
||||
uint32_t ctl;
|
||||
|
||||
ctl = LE(d, x);
|
||||
q |= ctl << i;
|
||||
x -= (-ctl) & d;
|
||||
d >>= 1;
|
||||
}
|
||||
if (r != NULL) {
|
||||
*r = x;
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i15_muladd_small(uint16_t *x, uint16_t z, const uint16_t *m)
|
||||
{
|
||||
/*
|
||||
* Constant-time: we accept to leak the exact bit length of the
|
||||
* modulus m.
|
||||
*/
|
||||
unsigned m_bitlen, mblr;
|
||||
size_t u, mlen;
|
||||
uint32_t hi, a0, a, b, q;
|
||||
uint32_t cc, tb, over, under;
|
||||
|
||||
/*
|
||||
* Simple case: the modulus fits on one word.
|
||||
*/
|
||||
m_bitlen = m[0];
|
||||
if (m_bitlen == 0) {
|
||||
return;
|
||||
}
|
||||
if (m_bitlen <= 15) {
|
||||
uint32_t rem;
|
||||
|
||||
divrem16(((uint32_t)x[1] << 15) | z, m[1], &rem);
|
||||
x[1] = rem;
|
||||
return;
|
||||
}
|
||||
mlen = (m_bitlen + 15) >> 4;
|
||||
mblr = m_bitlen & 15;
|
||||
|
||||
/*
|
||||
* Principle: we estimate the quotient (x*2^15+z)/m by
|
||||
* doing a 30/15 division with the high words.
|
||||
*
|
||||
* Let:
|
||||
* w = 2^15
|
||||
* a = (w*a0 + a1) * w^N + a2
|
||||
* b = b0 * w^N + b2
|
||||
* such that:
|
||||
* 0 <= a0 < w
|
||||
* 0 <= a1 < w
|
||||
* 0 <= a2 < w^N
|
||||
* w/2 <= b0 < w
|
||||
* 0 <= b2 < w^N
|
||||
* a < w*b
|
||||
* I.e. the two top words of a are a0:a1, the top word of b is
|
||||
* b0, we ensured that b0 is "full" (high bit set), and a is
|
||||
* such that the quotient q = a/b fits on one word (0 <= q < w).
|
||||
*
|
||||
* If a = b*q + r (with 0 <= r < q), then we can estimate q by
|
||||
* using a division on the top words:
|
||||
* a0*w + a1 = b0*u + v (with 0 <= v < b0)
|
||||
* Then the following holds:
|
||||
* 0 <= u <= w
|
||||
* u-2 <= q <= u
|
||||
*/
|
||||
hi = x[mlen];
|
||||
if (mblr == 0) {
|
||||
a0 = x[mlen];
|
||||
memmove(x + 2, x + 1, (mlen - 1) * sizeof *x);
|
||||
x[1] = z;
|
||||
a = (a0 << 15) + x[mlen];
|
||||
b = m[mlen];
|
||||
} else {
|
||||
a0 = (x[mlen] << (15 - mblr)) | (x[mlen - 1] >> mblr);
|
||||
memmove(x + 2, x + 1, (mlen - 1) * sizeof *x);
|
||||
x[1] = z;
|
||||
a = (a0 << 15) | (((x[mlen] << (15 - mblr))
|
||||
| (x[mlen - 1] >> mblr)) & 0x7FFF);
|
||||
b = (m[mlen] << (15 - mblr)) | (m[mlen - 1] >> mblr);
|
||||
}
|
||||
q = divrem16(a, b, NULL);
|
||||
|
||||
/*
|
||||
* We computed an estimate for q, but the real one may be q,
|
||||
* q-1 or q-2; moreover, the division may have returned a value
|
||||
* 8000 or even 8001 if the two high words were identical, and
|
||||
* we want to avoid values beyond 7FFF. We thus adjust q so
|
||||
* that the "true" multiplier will be q+1, q or q-1, and q is
|
||||
* in the 0000..7FFF range.
|
||||
*/
|
||||
q = MUX(EQ(b, a0), 0x7FFF, q - 1 + ((q - 1) >> 31));
|
||||
|
||||
/*
|
||||
* We subtract q*m from x (x has an extra high word of value 'hi').
|
||||
* Since q may be off by 1 (in either direction), we may have to
|
||||
* add or subtract m afterwards.
|
||||
*
|
||||
* The 'tb' flag will be true (1) at the end of the loop if the
|
||||
* result is greater than or equal to the modulus (not counting
|
||||
* 'hi' or the carry).
|
||||
*/
|
||||
cc = 0;
|
||||
tb = 1;
|
||||
for (u = 1; u <= mlen; u ++) {
|
||||
uint32_t mw, zl, xw, nxw;
|
||||
|
||||
mw = m[u];
|
||||
zl = MUL15(mw, q) + cc;
|
||||
cc = zl >> 15;
|
||||
zl &= 0x7FFF;
|
||||
xw = x[u];
|
||||
nxw = xw - zl;
|
||||
cc += nxw >> 31;
|
||||
nxw &= 0x7FFF;
|
||||
x[u] = nxw;
|
||||
tb = MUX(EQ(nxw, mw), tb, GT(nxw, mw));
|
||||
}
|
||||
|
||||
/*
|
||||
* If we underestimated q, then either cc < hi (one extra bit
|
||||
* beyond the top array word), or cc == hi and tb is true (no
|
||||
* extra bit, but the result is not lower than the modulus).
|
||||
*
|
||||
* If we overestimated q, then cc > hi.
|
||||
*/
|
||||
over = GT(cc, hi);
|
||||
under = ~over & (tb | LT(cc, hi));
|
||||
br_i15_add(x, m, over);
|
||||
br_i15_sub(x, m, under);
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint16_t
|
||||
br_i15_ninv15(uint16_t x)
|
||||
{
|
||||
uint32_t y;
|
||||
|
||||
y = 2 - x;
|
||||
y = MUL15(y, 2 - MUL15(x, y));
|
||||
y = MUL15(y, 2 - MUL15(x, y));
|
||||
y = MUL15(y, 2 - MUL15(x, y));
|
||||
return MUX(x & 1, -y, 0) & 0x7FFF;
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i15_reduce(uint16_t *x, const uint16_t *a, const uint16_t *m)
|
||||
{
|
||||
uint32_t m_bitlen, a_bitlen;
|
||||
size_t mlen, alen, u;
|
||||
|
||||
m_bitlen = m[0];
|
||||
mlen = (m_bitlen + 15) >> 4;
|
||||
|
||||
x[0] = m_bitlen;
|
||||
if (m_bitlen == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the source is shorter, then simply copy all words from a[]
|
||||
* and zero out the upper words.
|
||||
*/
|
||||
a_bitlen = a[0];
|
||||
alen = (a_bitlen + 15) >> 4;
|
||||
if (a_bitlen < m_bitlen) {
|
||||
memcpy(x + 1, a + 1, alen * sizeof *a);
|
||||
for (u = alen; u < mlen; u ++) {
|
||||
x[u + 1] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The source length is at least equal to that of the modulus.
|
||||
* We must thus copy N-1 words, and input the remaining words
|
||||
* one by one.
|
||||
*/
|
||||
memcpy(x + 1, a + 2 + (alen - mlen), (mlen - 1) * sizeof *a);
|
||||
x[mlen] = 0;
|
||||
for (u = 1 + alen - mlen; u > 0; u --) {
|
||||
br_i15_muladd_small(x, a[u], m);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i15_rshift(uint16_t *x, int count)
|
||||
{
|
||||
size_t u, len;
|
||||
unsigned r;
|
||||
|
||||
len = (x[0] + 15) >> 4;
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
r = x[1] >> count;
|
||||
for (u = 2; u <= len; u ++) {
|
||||
unsigned w;
|
||||
|
||||
w = x[u];
|
||||
x[u - 1] = ((w << (15 - count)) | r) & 0x7FFF;
|
||||
r = w >> count;
|
||||
}
|
||||
x[len] = r;
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i15_sub(uint16_t *a, const uint16_t *b, uint32_t ctl)
|
||||
{
|
||||
uint32_t cc;
|
||||
size_t u, m;
|
||||
|
||||
cc = 0;
|
||||
m = (a[0] + 31) >> 4;
|
||||
for (u = 1; u < m; u ++) {
|
||||
uint32_t aw, bw, naw;
|
||||
|
||||
aw = a[u];
|
||||
bw = b[u];
|
||||
naw = aw - bw - cc;
|
||||
cc = naw >> 31;
|
||||
a[u] = MUX(ctl, naw & 0x7FFF, aw);
|
||||
}
|
||||
return cc;
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i15_to_monty(uint16_t *x, const uint16_t *m)
|
||||
{
|
||||
unsigned k;
|
||||
|
||||
for (k = (m[0] + 15) >> 4; k > 0; k --) {
|
||||
br_i15_muladd_small(x, 0, m);
|
||||
}
|
||||
}
|
||||
|
|
@ -125,15 +125,6 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set BR_LOMUL on platforms where it makes sense.
|
||||
*/
|
||||
#ifndef BR_LOMUL
|
||||
#if BR_ARMEL_CORTEXM_GCC
|
||||
#define BR_LOMUL 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Architecture detection.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,297 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Perform the inner processing of blocks for Poly1305.
|
||||
*/
|
||||
static void
|
||||
poly1305_inner(uint32_t *a, const uint32_t *r, const void *data, size_t len)
|
||||
{
|
||||
/*
|
||||
* Implementation notes: we split the 130-bit values into ten
|
||||
* 13-bit words. This gives us some space for carries and allows
|
||||
* using only 32x32->32 multiplications, which are way faster than
|
||||
* 32x32->64 multiplications on the ARM Cortex-M0/M0+, and also
|
||||
* help in making constant-time code on the Cortex-M3.
|
||||
*
|
||||
* Since we compute modulo 2^130-5, the "upper words" become
|
||||
* low words with a factor of 5; that is, x*2^130 = x*5 mod p.
|
||||
* This has already been integrated in the r[] array, which
|
||||
* is extended to the 0..18 range.
|
||||
*
|
||||
* In each loop iteration, a[] and r[] words are 13-bit each,
|
||||
* except a[1] which may use 14 bits.
|
||||
*/
|
||||
const unsigned char *buf;
|
||||
|
||||
buf = data;
|
||||
while (len > 0) {
|
||||
unsigned char tmp[16];
|
||||
uint32_t b[10];
|
||||
unsigned u, v;
|
||||
uint32_t z, cc1, cc2;
|
||||
|
||||
/*
|
||||
* If there is a partial block, right-pad it with zeros.
|
||||
*/
|
||||
if (len < 16) {
|
||||
memset(tmp, 0, sizeof tmp);
|
||||
memcpy(tmp, buf, len);
|
||||
buf = tmp;
|
||||
len = 16;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode next block and apply the "high bit"; that value
|
||||
* is added to the accumulator.
|
||||
*/
|
||||
v = br_dec16le(buf);
|
||||
a[0] += v & 0x01FFF;
|
||||
v >>= 13;
|
||||
v |= buf[2] << 3;
|
||||
v |= buf[3] << 11;
|
||||
a[1] += v & 0x01FFF;
|
||||
v >>= 13;
|
||||
v |= buf[4] << 6;
|
||||
a[2] += v & 0x01FFF;
|
||||
v >>= 13;
|
||||
v |= buf[5] << 1;
|
||||
v |= buf[6] << 9;
|
||||
a[3] += v & 0x01FFF;
|
||||
v >>= 13;
|
||||
v |= buf[7] << 4;
|
||||
v |= buf[8] << 12;
|
||||
a[4] += v & 0x01FFF;
|
||||
v >>= 13;
|
||||
v |= buf[9] << 7;
|
||||
a[5] += v & 0x01FFF;
|
||||
v >>= 13;
|
||||
v |= buf[10] << 2;
|
||||
v |= buf[11] << 10;
|
||||
a[6] += v & 0x01FFF;
|
||||
v >>= 13;
|
||||
v |= buf[12] << 5;
|
||||
a[7] += v & 0x01FFF;
|
||||
v = br_dec16le(buf + 13);
|
||||
a[8] += v & 0x01FFF;
|
||||
v >>= 13;
|
||||
v |= buf[15] << 3;
|
||||
a[9] += v | 0x00800;
|
||||
|
||||
/*
|
||||
* At that point, all a[] values fit on 14 bits, while
|
||||
* all r[] values fit on 13 bits. Thus products fit on
|
||||
* 27 bits, and we can accumulate up to 31 of them in
|
||||
* a 32-bit word and still have some room for carries.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Now a[] contains words with values up to 14 bits each.
|
||||
* We perform the multiplication with r[].
|
||||
*
|
||||
* The extended words of r[] may be larger than 13 bits
|
||||
* (they are 5 times a 13-bit word) so the full summation
|
||||
* may yield values up to 46 times a 27-bit word, which
|
||||
* does not fit on a 32-bit word. To avoid that issue, we
|
||||
* must split the loop below in two, with a carry
|
||||
* propagation operation in the middle.
|
||||
*/
|
||||
cc1 = 0;
|
||||
for (u = 0; u < 10; u ++) {
|
||||
uint32_t s;
|
||||
|
||||
s = cc1
|
||||
+ MUL15(a[0], r[u + 9 - 0])
|
||||
+ MUL15(a[1], r[u + 9 - 1])
|
||||
+ MUL15(a[2], r[u + 9 - 2])
|
||||
+ MUL15(a[3], r[u + 9 - 3])
|
||||
+ MUL15(a[4], r[u + 9 - 4]);
|
||||
b[u] = s & 0x1FFF;
|
||||
cc1 = s >> 13;
|
||||
}
|
||||
cc2 = 0;
|
||||
for (u = 0; u < 10; u ++) {
|
||||
uint32_t s;
|
||||
|
||||
s = b[u] + cc2
|
||||
+ MUL15(a[5], r[u + 9 - 5])
|
||||
+ MUL15(a[6], r[u + 9 - 6])
|
||||
+ MUL15(a[7], r[u + 9 - 7])
|
||||
+ MUL15(a[8], r[u + 9 - 8])
|
||||
+ MUL15(a[9], r[u + 9 - 9]);
|
||||
b[u] = s & 0x1FFF;
|
||||
cc2 = s >> 13;
|
||||
}
|
||||
memcpy(a, b, sizeof b);
|
||||
|
||||
/*
|
||||
* The two carries "loop back" with a factor of 5. We
|
||||
* propagate them into a[0] and a[1].
|
||||
*/
|
||||
z = cc1 + cc2;
|
||||
z += (z << 2) + a[0];
|
||||
a[0] = z & 0x1FFF;
|
||||
a[1] += z >> 13;
|
||||
|
||||
buf += 16;
|
||||
len -= 16;
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_block.h */
|
||||
void
|
||||
br_poly1305_ctmul32_run(const void *key, const void *iv,
|
||||
void *data, size_t len, const void *aad, size_t aad_len,
|
||||
void *tag, br_chacha20_run ichacha, int encrypt)
|
||||
{
|
||||
unsigned char pkey[32], foot[16];
|
||||
uint32_t z, r[19], acc[10], cc, ctl;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Compute the MAC key. The 'r' value is the first 16 bytes of
|
||||
* pkey[].
|
||||
*/
|
||||
memset(pkey, 0, sizeof pkey);
|
||||
ichacha(key, iv, 0, pkey, sizeof pkey);
|
||||
|
||||
/*
|
||||
* If encrypting, ChaCha20 must run first, followed by Poly1305.
|
||||
* When decrypting, the operations are reversed.
|
||||
*/
|
||||
if (encrypt) {
|
||||
ichacha(key, iv, 1, data, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Run Poly1305. We must process the AAD, then ciphertext, then
|
||||
* the footer (with the lengths). Note that the AAD and ciphertext
|
||||
* are meant to be padded with zeros up to the next multiple of 16,
|
||||
* and the length of the footer is 16 bytes as well.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Decode the 'r' value into 13-bit words, with the "clamping"
|
||||
* operation applied.
|
||||
*/
|
||||
z = br_dec32le(pkey) & 0x03FFFFFF;
|
||||
r[9] = z & 0x1FFF;
|
||||
r[10] = z >> 13;
|
||||
z = (br_dec32le(pkey + 3) >> 2) & 0x03FFFF03;
|
||||
r[11] = z & 0x1FFF;
|
||||
r[12] = z >> 13;
|
||||
z = (br_dec32le(pkey + 6) >> 4) & 0x03FFC0FF;
|
||||
r[13] = z & 0x1FFF;
|
||||
r[14] = z >> 13;
|
||||
z = (br_dec32le(pkey + 9) >> 6) & 0x03F03FFF;
|
||||
r[15] = z & 0x1FFF;
|
||||
r[16] = z >> 13;
|
||||
z = (br_dec32le(pkey + 12) >> 8) & 0x000FFFFF;
|
||||
r[17] = z & 0x1FFF;
|
||||
r[18] = z >> 13;
|
||||
|
||||
/*
|
||||
* Extend r[] with the 5x factor pre-applied.
|
||||
*/
|
||||
for (i = 0; i < 9; i ++) {
|
||||
r[i] = MUL15(5, r[i + 10]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Accumulator is 0.
|
||||
*/
|
||||
memset(acc, 0, sizeof acc);
|
||||
|
||||
/*
|
||||
* Process the additional authenticated data, ciphertext, and
|
||||
* footer in due order.
|
||||
*/
|
||||
br_enc64le(foot, (uint64_t)aad_len);
|
||||
br_enc64le(foot + 8, (uint64_t)len);
|
||||
poly1305_inner(acc, r, aad, aad_len);
|
||||
poly1305_inner(acc, r, data, len);
|
||||
poly1305_inner(acc, r, foot, sizeof foot);
|
||||
|
||||
/*
|
||||
* Finalise modular reduction. This is done with carry propagation
|
||||
* and applying the '2^130 = -5 mod p' rule. Note that the output
|
||||
* of poly1035_inner() is already mostly reduced, since only
|
||||
* acc[1] may be (very slightly) above 2^13. A single loop back
|
||||
* to acc[1] will be enough to make the value fit in 130 bits.
|
||||
*/
|
||||
cc = 0;
|
||||
for (i = 1; i < 10; i ++) {
|
||||
z = acc[i] + cc;
|
||||
acc[i] = z & 0x1FFF;
|
||||
cc = z >> 13;
|
||||
}
|
||||
z = acc[0] + cc + (cc << 2);
|
||||
acc[0] = z & 0x1FFF;
|
||||
acc[1] += z >> 13;
|
||||
|
||||
/*
|
||||
* We may still have a value in the 2^130-5..2^130-1 range, in
|
||||
* which case we must reduce it again. The code below selects,
|
||||
* in constant-time, between 'acc' and 'acc-p',
|
||||
*/
|
||||
ctl = GT(acc[0], 0x1FFA);
|
||||
for (i = 1; i < 10; i ++) {
|
||||
ctl &= EQ(acc[i], 0x1FFF);
|
||||
}
|
||||
acc[0] = MUX(ctl, acc[0] - 0x1FFB, acc[0]);
|
||||
for (i = 1; i < 10; i ++) {
|
||||
acc[i] &= ~(-ctl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert back the accumulator to 32-bit words, and add the
|
||||
* 's' value (second half of pkey[]). That addition is done
|
||||
* modulo 2^128.
|
||||
*/
|
||||
z = acc[0] + (acc[1] << 13) + br_dec16le(pkey + 16);
|
||||
br_enc16le((unsigned char *)tag, z & 0xFFFF);
|
||||
z = (z >> 16) + (acc[2] << 10) + br_dec16le(pkey + 18);
|
||||
br_enc16le((unsigned char *)tag + 2, z & 0xFFFF);
|
||||
z = (z >> 16) + (acc[3] << 7) + br_dec16le(pkey + 20);
|
||||
br_enc16le((unsigned char *)tag + 4, z & 0xFFFF);
|
||||
z = (z >> 16) + (acc[4] << 4) + br_dec16le(pkey + 22);
|
||||
br_enc16le((unsigned char *)tag + 6, z & 0xFFFF);
|
||||
z = (z >> 16) + (acc[5] << 1) + (acc[6] << 14) + br_dec16le(pkey + 24);
|
||||
br_enc16le((unsigned char *)tag + 8, z & 0xFFFF);
|
||||
z = (z >> 16) + (acc[7] << 11) + br_dec16le(pkey + 26);
|
||||
br_enc16le((unsigned char *)tag + 10, z & 0xFFFF);
|
||||
z = (z >> 16) + (acc[8] << 8) + br_dec16le(pkey + 28);
|
||||
br_enc16le((unsigned char *)tag + 12, z & 0xFFFF);
|
||||
z = (z >> 16) + (acc[9] << 5) + br_dec16le(pkey + 30);
|
||||
br_enc16le((unsigned char *)tag + 14, z & 0xFFFF);
|
||||
|
||||
/*
|
||||
* If decrypting, then ChaCha20 runs _after_ Poly1305.
|
||||
*/
|
||||
if (!encrypt) {
|
||||
ichacha(key, iv, 1, data, len);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,221 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* This is a "reference" implementation of Poly1305 that uses the
|
||||
* generic "i15" code for big integers. It is slow, but it handles all
|
||||
* big-integer operations with generic code, thereby avoiding most
|
||||
* tricky situations with carry propagation and modular reduction.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modulus: 2^130-5.
|
||||
*/
|
||||
static const uint16_t P1305[] = {
|
||||
0x008A,
|
||||
0x7FFB, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x03FF
|
||||
};
|
||||
|
||||
/*
|
||||
* -p mod 2^15.
|
||||
*/
|
||||
#define P0I 0x4CCD
|
||||
|
||||
/*
|
||||
* R^2 mod p, for conversion to Montgomery representation (R = 2^135,
|
||||
* since we use 9 words of 15 bits each, and 15*9 = 135).
|
||||
*/
|
||||
static const uint16_t R2[] = {
|
||||
0x008A,
|
||||
0x6400, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
|
||||
};
|
||||
|
||||
/*
|
||||
* Perform the inner processing of blocks for Poly1305. The "r" array
|
||||
* is in Montgomery representation, while the "a" array is not.
|
||||
*/
|
||||
static void
|
||||
poly1305_inner(uint16_t *a, const uint16_t *r, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
|
||||
buf = data;
|
||||
while (len > 0) {
|
||||
unsigned char tmp[16], rev[16];
|
||||
uint16_t b[10];
|
||||
uint32_t ctl;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* If there is a partial block, right-pad it with zeros.
|
||||
*/
|
||||
if (len < 16) {
|
||||
memset(tmp, 0, sizeof tmp);
|
||||
memcpy(tmp, buf, len);
|
||||
buf = tmp;
|
||||
len = 16;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode next block and apply the "high bit". Since
|
||||
* decoding is little-endian, we must byte-swap the buffer.
|
||||
*/
|
||||
for (i = 0; i < 16; i ++) {
|
||||
rev[i] = buf[15 - i];
|
||||
}
|
||||
br_i15_decode_mod(b, rev, sizeof rev, P1305);
|
||||
b[9] |= 0x0100;
|
||||
|
||||
/*
|
||||
* Add the accumulator to the decoded block (modular
|
||||
* addition).
|
||||
*/
|
||||
ctl = br_i15_add(b, a, 1);
|
||||
ctl |= NOT(br_i15_sub(b, P1305, 0));
|
||||
br_i15_sub(b, P1305, ctl);
|
||||
|
||||
/*
|
||||
* Multiply by r, result is the new accumulator value.
|
||||
*/
|
||||
br_i15_montymul(a, b, r, P1305, P0I);
|
||||
|
||||
buf += 16;
|
||||
len -= 16;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Byteswap a 16-byte value.
|
||||
*/
|
||||
static void
|
||||
byteswap16(unsigned char *buf)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i ++) {
|
||||
unsigned x;
|
||||
|
||||
x = buf[i];
|
||||
buf[i] = buf[15 - i];
|
||||
buf[15 - i] = x;
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_block.h */
|
||||
void
|
||||
br_poly1305_i15_run(const void *key, const void *iv,
|
||||
void *data, size_t len, const void *aad, size_t aad_len,
|
||||
void *tag, br_chacha20_run ichacha, int encrypt)
|
||||
{
|
||||
unsigned char pkey[32], foot[16];
|
||||
uint16_t t[10], r[10], acc[10];
|
||||
|
||||
/*
|
||||
* Compute the MAC key. The 'r' value is the first 16 bytes of
|
||||
* pkey[].
|
||||
*/
|
||||
memset(pkey, 0, sizeof pkey);
|
||||
ichacha(key, iv, 0, pkey, sizeof pkey);
|
||||
|
||||
/*
|
||||
* If encrypting, ChaCha20 must run first, followed by Poly1305.
|
||||
* When decrypting, the operations are reversed.
|
||||
*/
|
||||
if (encrypt) {
|
||||
ichacha(key, iv, 1, data, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Run Poly1305. We must process the AAD, then ciphertext, then
|
||||
* the footer (with the lengths). Note that the AAD and ciphertext
|
||||
* are meant to be padded with zeros up to the next multiple of 16,
|
||||
* and the length of the footer is 16 bytes as well.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Apply the "clamping" operation on the encoded 'r' value.
|
||||
*/
|
||||
pkey[ 3] &= 0x0F;
|
||||
pkey[ 7] &= 0x0F;
|
||||
pkey[11] &= 0x0F;
|
||||
pkey[15] &= 0x0F;
|
||||
pkey[ 4] &= 0xFC;
|
||||
pkey[ 8] &= 0xFC;
|
||||
pkey[12] &= 0xFC;
|
||||
|
||||
/*
|
||||
* Decode the clamped 'r' value. Decoding should use little-endian
|
||||
* so we must byteswap the value first.
|
||||
*/
|
||||
byteswap16(pkey);
|
||||
br_i15_decode_mod(t, pkey, 16, P1305);
|
||||
|
||||
/*
|
||||
* Convert 'r' to Montgomery representation.
|
||||
*/
|
||||
br_i15_montymul(r, t, R2, P1305, P0I);
|
||||
|
||||
/*
|
||||
* Accumulator is 0.
|
||||
*/
|
||||
br_i15_zero(acc, 0x8A);
|
||||
|
||||
/*
|
||||
* Process the additional authenticated data, ciphertext, and
|
||||
* footer in due order.
|
||||
*/
|
||||
br_enc64le(foot, (uint64_t)aad_len);
|
||||
br_enc64le(foot + 8, (uint64_t)len);
|
||||
poly1305_inner(acc, r, aad, aad_len);
|
||||
poly1305_inner(acc, r, data, len);
|
||||
poly1305_inner(acc, r, foot, sizeof foot);
|
||||
|
||||
/*
|
||||
* Decode the value 's'. Again, a byteswap is needed.
|
||||
*/
|
||||
byteswap16(pkey + 16);
|
||||
br_i15_decode_mod(t, pkey + 16, 16, P1305);
|
||||
|
||||
/*
|
||||
* Add the value 's' to the accumulator. That addition is done
|
||||
* modulo 2^128, so we just ignore the carry.
|
||||
*/
|
||||
br_i15_add(acc, t, 1);
|
||||
|
||||
/*
|
||||
* Encode the result (128 low bits) to the tag. Encoding should
|
||||
* be little-endian.
|
||||
*/
|
||||
br_i15_encode(tag, 16, acc);
|
||||
byteswap16(tag);
|
||||
|
||||
/*
|
||||
* If decrypting, then ChaCha20 runs _after_ Poly1305.
|
||||
*/
|
||||
if (!encrypt) {
|
||||
ichacha(key, iv, 1, data, len);
|
||||
}
|
||||
}
|
||||
|
|
@ -30,8 +30,6 @@ br_rsa_keygen_get_default(void)
|
|||
{
|
||||
#if BR_INT128 || BR_UMUL128
|
||||
return &br_rsa_i62_keygen;
|
||||
#elif BR_LOMUL
|
||||
return &br_rsa_i15_keygen;
|
||||
#else
|
||||
return &br_rsa_i31_keygen;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -28,9 +28,5 @@
|
|||
br_rsa_compute_modulus
|
||||
br_rsa_compute_modulus_get_default(void)
|
||||
{
|
||||
#if BR_LOMUL
|
||||
return &br_rsa_i15_compute_modulus;
|
||||
#else
|
||||
return &br_rsa_i31_compute_modulus;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@ br_rsa_oaep_decrypt_get_default(void)
|
|||
{
|
||||
#if BR_INT128 || BR_UMUL128
|
||||
return &br_rsa_i62_oaep_decrypt;
|
||||
#elif BR_LOMUL
|
||||
return &br_rsa_i15_oaep_decrypt;
|
||||
#else
|
||||
return &br_rsa_i31_oaep_decrypt;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@ br_rsa_oaep_encrypt_get_default(void)
|
|||
{
|
||||
#if BR_INT128 || BR_UMUL128
|
||||
return &br_rsa_i62_oaep_encrypt;
|
||||
#elif BR_LOMUL
|
||||
return &br_rsa_i15_oaep_encrypt;
|
||||
#else
|
||||
return &br_rsa_i31_oaep_encrypt;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@ br_rsa_pkcs1_sign_get_default(void)
|
|||
{
|
||||
#if BR_INT128 || BR_UMUL128
|
||||
return &br_rsa_i62_pkcs1_sign;
|
||||
#elif BR_LOMUL
|
||||
return &br_rsa_i15_pkcs1_sign;
|
||||
#else
|
||||
return &br_rsa_i31_pkcs1_sign;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@ br_rsa_pkcs1_vrfy_get_default(void)
|
|||
{
|
||||
#if BR_INT128 || BR_UMUL128
|
||||
return &br_rsa_i62_pkcs1_vrfy;
|
||||
#elif BR_LOMUL
|
||||
return &br_rsa_i15_pkcs1_vrfy;
|
||||
#else
|
||||
return &br_rsa_i31_pkcs1_vrfy;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@ br_rsa_private_get_default(void)
|
|||
{
|
||||
#if BR_INT128 || BR_UMUL128
|
||||
return &br_rsa_i62_private;
|
||||
#elif BR_LOMUL
|
||||
return &br_rsa_i15_private;
|
||||
#else
|
||||
return &br_rsa_i31_private;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -28,9 +28,5 @@
|
|||
br_rsa_compute_privexp
|
||||
br_rsa_compute_privexp_get_default(void)
|
||||
{
|
||||
#if BR_LOMUL
|
||||
return &br_rsa_i15_compute_privexp;
|
||||
#else
|
||||
return &br_rsa_i31_compute_privexp;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@ br_rsa_pss_sign_get_default(void)
|
|||
{
|
||||
#if BR_INT128 || BR_UMUL128
|
||||
return &br_rsa_i62_pss_sign;
|
||||
#elif BR_LOMUL
|
||||
return &br_rsa_i15_pss_sign;
|
||||
#else
|
||||
return &br_rsa_i31_pss_sign;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@ br_rsa_pss_vrfy_get_default(void)
|
|||
{
|
||||
#if BR_INT128 || BR_UMUL128
|
||||
return &br_rsa_i62_pss_vrfy;
|
||||
#elif BR_LOMUL
|
||||
return &br_rsa_i15_pss_vrfy;
|
||||
#else
|
||||
return &br_rsa_i31_pss_vrfy;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@ br_rsa_public_get_default(void)
|
|||
{
|
||||
#if BR_INT128 || BR_UMUL128
|
||||
return &br_rsa_i62_public;
|
||||
#elif BR_LOMUL
|
||||
return &br_rsa_i15_public;
|
||||
#else
|
||||
return &br_rsa_i31_public;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -28,9 +28,5 @@
|
|||
br_rsa_compute_pubexp
|
||||
br_rsa_compute_pubexp_get_default(void)
|
||||
{
|
||||
#if BR_LOMUL
|
||||
return &br_rsa_i15_compute_pubexp;
|
||||
#else
|
||||
return &br_rsa_i31_compute_pubexp;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,583 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Make a random integer of the provided size. The size is encoded.
|
||||
* The header word is untouched.
|
||||
*/
|
||||
static void
|
||||
mkrand(const br_prng_class **rng, uint16_t *x, uint32_t esize)
|
||||
{
|
||||
size_t u, len;
|
||||
unsigned m;
|
||||
|
||||
len = (esize + 15) >> 4;
|
||||
(*rng)->generate(rng, x + 1, len * sizeof(uint16_t));
|
||||
for (u = 1; u < len; u ++) {
|
||||
x[u] &= 0x7FFF;
|
||||
}
|
||||
m = esize & 15;
|
||||
if (m == 0) {
|
||||
x[len] &= 0x7FFF;
|
||||
} else {
|
||||
x[len] &= 0x7FFF >> (15 - m);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the big-endian unsigned representation of the product of
|
||||
* all small primes from 13 to 1481.
|
||||
*/
|
||||
static const unsigned char SMALL_PRIMES[] = {
|
||||
0x2E, 0xAB, 0x92, 0xD1, 0x8B, 0x12, 0x47, 0x31, 0x54, 0x0A,
|
||||
0x99, 0x5D, 0x25, 0x5E, 0xE2, 0x14, 0x96, 0x29, 0x1E, 0xB7,
|
||||
0x78, 0x70, 0xCC, 0x1F, 0xA5, 0xAB, 0x8D, 0x72, 0x11, 0x37,
|
||||
0xFB, 0xD8, 0x1E, 0x3F, 0x5B, 0x34, 0x30, 0x17, 0x8B, 0xE5,
|
||||
0x26, 0x28, 0x23, 0xA1, 0x8A, 0xA4, 0x29, 0xEA, 0xFD, 0x9E,
|
||||
0x39, 0x60, 0x8A, 0xF3, 0xB5, 0xA6, 0xEB, 0x3F, 0x02, 0xB6,
|
||||
0x16, 0xC3, 0x96, 0x9D, 0x38, 0xB0, 0x7D, 0x82, 0x87, 0x0C,
|
||||
0xF7, 0xBE, 0x24, 0xE5, 0x5F, 0x41, 0x04, 0x79, 0x76, 0x40,
|
||||
0xE7, 0x00, 0x22, 0x7E, 0xB5, 0x85, 0x7F, 0x8D, 0x01, 0x50,
|
||||
0xE9, 0xD3, 0x29, 0x42, 0x08, 0xB3, 0x51, 0x40, 0x7B, 0xD7,
|
||||
0x8D, 0xCC, 0x10, 0x01, 0x64, 0x59, 0x28, 0xB6, 0x53, 0xF3,
|
||||
0x50, 0x4E, 0xB1, 0xF2, 0x58, 0xCD, 0x6E, 0xF5, 0x56, 0x3E,
|
||||
0x66, 0x2F, 0xD7, 0x07, 0x7F, 0x52, 0x4C, 0x13, 0x24, 0xDC,
|
||||
0x8E, 0x8D, 0xCC, 0xED, 0x77, 0xC4, 0x21, 0xD2, 0xFD, 0x08,
|
||||
0xEA, 0xD7, 0xC0, 0x5C, 0x13, 0x82, 0x81, 0x31, 0x2F, 0x2B,
|
||||
0x08, 0xE4, 0x80, 0x04, 0x7A, 0x0C, 0x8A, 0x3C, 0xDC, 0x22,
|
||||
0xE4, 0x5A, 0x7A, 0xB0, 0x12, 0x5E, 0x4A, 0x76, 0x94, 0x77,
|
||||
0xC2, 0x0E, 0x92, 0xBA, 0x8A, 0xA0, 0x1F, 0x14, 0x51, 0x1E,
|
||||
0x66, 0x6C, 0x38, 0x03, 0x6C, 0xC7, 0x4A, 0x4B, 0x70, 0x80,
|
||||
0xAF, 0xCA, 0x84, 0x51, 0xD8, 0xD2, 0x26, 0x49, 0xF5, 0xA8,
|
||||
0x5E, 0x35, 0x4B, 0xAC, 0xCE, 0x29, 0x92, 0x33, 0xB7, 0xA2,
|
||||
0x69, 0x7D, 0x0C, 0xE0, 0x9C, 0xDB, 0x04, 0xD6, 0xB4, 0xBC,
|
||||
0x39, 0xD7, 0x7F, 0x9E, 0x9D, 0x78, 0x38, 0x7F, 0x51, 0x54,
|
||||
0x50, 0x8B, 0x9E, 0x9C, 0x03, 0x6C, 0xF5, 0x9D, 0x2C, 0x74,
|
||||
0x57, 0xF0, 0x27, 0x2A, 0xC3, 0x47, 0xCA, 0xB9, 0xD7, 0x5C,
|
||||
0xFF, 0xC2, 0xAC, 0x65, 0x4E, 0xBD
|
||||
};
|
||||
|
||||
/*
|
||||
* We need temporary values for at least 7 integers of the same size
|
||||
* as a factor (including header word); more space helps with performance
|
||||
* (in modular exponentiations), but we much prefer to remain under
|
||||
* 2 kilobytes in total, to save stack space. The macro TEMPS below
|
||||
* exceeds 1024 (which is a count in 16-bit words) when BR_MAX_RSA_SIZE
|
||||
* is greater than 4350 (default value is 4096, so the 2-kB limit is
|
||||
* maintained unless BR_MAX_RSA_SIZE was modified).
|
||||
*/
|
||||
#define MAX(x, y) ((x) > (y) ? (x) : (y))
|
||||
#define TEMPS MAX(1024, 7 * ((((BR_MAX_RSA_SIZE + 1) >> 1) + 29) / 15))
|
||||
|
||||
/*
|
||||
* Perform trial division on a candidate prime. This computes
|
||||
* y = SMALL_PRIMES mod x, then tries to compute y/y mod x. The
|
||||
* br_i15_moddiv() function will report an error if y is not invertible
|
||||
* modulo x. Returned value is 1 on success (none of the small primes
|
||||
* divides x), 0 on error (a non-trivial GCD is obtained).
|
||||
*
|
||||
* This function assumes that x is odd.
|
||||
*/
|
||||
static uint32_t
|
||||
trial_divisions(const uint16_t *x, uint16_t *t)
|
||||
{
|
||||
uint16_t *y;
|
||||
uint16_t x0i;
|
||||
|
||||
y = t;
|
||||
t += 1 + ((x[0] + 15) >> 4);
|
||||
x0i = br_i15_ninv15(x[1]);
|
||||
br_i15_decode_reduce(y, SMALL_PRIMES, sizeof SMALL_PRIMES, x);
|
||||
return br_i15_moddiv(y, y, x, x0i, t);
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform n rounds of Miller-Rabin on the candidate prime x. This
|
||||
* function assumes that x = 3 mod 4.
|
||||
*
|
||||
* Returned value is 1 on success (all rounds completed successfully),
|
||||
* 0 otherwise.
|
||||
*/
|
||||
static uint32_t
|
||||
miller_rabin(const br_prng_class **rng, const uint16_t *x, int n,
|
||||
uint16_t *t, size_t tlen)
|
||||
{
|
||||
/*
|
||||
* Since x = 3 mod 4, the Miller-Rabin test is simple:
|
||||
* - get a random base a (such that 1 < a < x-1)
|
||||
* - compute z = a^((x-1)/2) mod x
|
||||
* - if z != 1 and z != x-1, the number x is composite
|
||||
*
|
||||
* We generate bases 'a' randomly with a size which is
|
||||
* one bit less than x, which ensures that a < x-1. It
|
||||
* is not useful to verify that a > 1 because the probability
|
||||
* that we get a value a equal to 0 or 1 is much smaller
|
||||
* than the probability of our Miller-Rabin tests not to
|
||||
* detect a composite, which is already quite smaller than the
|
||||
* probability of the hardware misbehaving and return a
|
||||
* composite integer because of some glitch (e.g. bad RAM
|
||||
* or ill-timed cosmic ray).
|
||||
*/
|
||||
unsigned char *xm1d2;
|
||||
size_t xlen, xm1d2_len, xm1d2_len_u16, u;
|
||||
uint32_t asize;
|
||||
unsigned cc;
|
||||
uint16_t x0i;
|
||||
|
||||
/*
|
||||
* Compute (x-1)/2 (encoded).
|
||||
*/
|
||||
xm1d2 = (unsigned char *)t;
|
||||
xm1d2_len = ((x[0] - (x[0] >> 4)) + 7) >> 3;
|
||||
br_i15_encode(xm1d2, xm1d2_len, x);
|
||||
cc = 0;
|
||||
for (u = 0; u < xm1d2_len; u ++) {
|
||||
unsigned w;
|
||||
|
||||
w = xm1d2[u];
|
||||
xm1d2[u] = (unsigned char)((w >> 1) | cc);
|
||||
cc = w << 7;
|
||||
}
|
||||
|
||||
/*
|
||||
* We used some words of the provided buffer for (x-1)/2.
|
||||
*/
|
||||
xm1d2_len_u16 = (xm1d2_len + 1) >> 1;
|
||||
t += xm1d2_len_u16;
|
||||
tlen -= xm1d2_len_u16;
|
||||
|
||||
xlen = (x[0] + 15) >> 4;
|
||||
asize = x[0] - 1 - EQ0(x[0] & 15);
|
||||
x0i = br_i15_ninv15(x[1]);
|
||||
while (n -- > 0) {
|
||||
uint16_t *a;
|
||||
uint32_t eq1, eqm1;
|
||||
|
||||
/*
|
||||
* Generate a random base. We don't need the base to be
|
||||
* really uniform modulo x, so we just get a random
|
||||
* number which is one bit shorter than x.
|
||||
*/
|
||||
a = t;
|
||||
a[0] = x[0];
|
||||
a[xlen] = 0;
|
||||
mkrand(rng, a, asize);
|
||||
|
||||
/*
|
||||
* Compute a^((x-1)/2) mod x. We assume here that the
|
||||
* function will not fail (the temporary array is large
|
||||
* enough).
|
||||
*/
|
||||
br_i15_modpow_opt(a, xm1d2, xm1d2_len,
|
||||
x, x0i, t + 1 + xlen, tlen - 1 - xlen);
|
||||
|
||||
/*
|
||||
* We must obtain either 1 or x-1. Note that x is odd,
|
||||
* hence x-1 differs from x only in its low word (no
|
||||
* carry).
|
||||
*/
|
||||
eq1 = a[1] ^ 1;
|
||||
eqm1 = a[1] ^ (x[1] - 1);
|
||||
for (u = 2; u <= xlen; u ++) {
|
||||
eq1 |= a[u];
|
||||
eqm1 |= a[u] ^ x[u];
|
||||
}
|
||||
|
||||
if ((EQ0(eq1) | EQ0(eqm1)) == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a random prime of the provided size. 'size' is the _encoded_
|
||||
* bit length. The two top bits and the two bottom bits are set to 1.
|
||||
*/
|
||||
static void
|
||||
mkprime(const br_prng_class **rng, uint16_t *x, uint32_t esize,
|
||||
uint32_t pubexp, uint16_t *t, size_t tlen)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
x[0] = esize;
|
||||
len = (esize + 15) >> 4;
|
||||
for (;;) {
|
||||
size_t u;
|
||||
uint32_t m3, m5, m7, m11;
|
||||
int rounds;
|
||||
|
||||
/*
|
||||
* Generate random bits. We force the two top bits and the
|
||||
* two bottom bits to 1.
|
||||
*/
|
||||
mkrand(rng, x, esize);
|
||||
if ((esize & 15) == 0) {
|
||||
x[len] |= 0x6000;
|
||||
} else if ((esize & 15) == 1) {
|
||||
x[len] |= 0x0001;
|
||||
x[len - 1] |= 0x4000;
|
||||
} else {
|
||||
x[len] |= 0x0003 << ((esize & 15) - 2);
|
||||
}
|
||||
x[1] |= 0x0003;
|
||||
|
||||
/*
|
||||
* Trial division with low primes (3, 5, 7 and 11). We
|
||||
* use the following properties:
|
||||
*
|
||||
* 2^2 = 1 mod 3
|
||||
* 2^4 = 1 mod 5
|
||||
* 2^3 = 1 mod 7
|
||||
* 2^10 = 1 mod 11
|
||||
*/
|
||||
m3 = 0;
|
||||
m5 = 0;
|
||||
m7 = 0;
|
||||
m11 = 0;
|
||||
for (u = 0; u < len; u ++) {
|
||||
uint32_t w;
|
||||
|
||||
w = x[1 + u];
|
||||
m3 += w << (u & 1);
|
||||
m3 = (m3 & 0xFF) + (m3 >> 8);
|
||||
m5 += w << ((4 - u) & 3);
|
||||
m5 = (m5 & 0xFF) + (m5 >> 8);
|
||||
m7 += w;
|
||||
m7 = (m7 & 0x1FF) + (m7 >> 9);
|
||||
m11 += w << (5 & -(u & 1));
|
||||
m11 = (m11 & 0x3FF) + (m11 >> 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Maximum values of m* at this point:
|
||||
* m3: 511
|
||||
* m5: 2310
|
||||
* m7: 510
|
||||
* m11: 2047
|
||||
* We use the same properties to make further reductions.
|
||||
*/
|
||||
|
||||
m3 = (m3 & 0x0F) + (m3 >> 4); /* max: 46 */
|
||||
m3 = (m3 & 0x0F) + (m3 >> 4); /* max: 16 */
|
||||
m3 = ((m3 * 43) >> 5) & 3;
|
||||
|
||||
m5 = (m5 & 0xFF) + (m5 >> 8); /* max: 263 */
|
||||
m5 = (m5 & 0x0F) + (m5 >> 4); /* max: 30 */
|
||||
m5 = (m5 & 0x0F) + (m5 >> 4); /* max: 15 */
|
||||
m5 -= 10 & -GT(m5, 9);
|
||||
m5 -= 5 & -GT(m5, 4);
|
||||
|
||||
m7 = (m7 & 0x3F) + (m7 >> 6); /* max: 69 */
|
||||
m7 = (m7 & 7) + (m7 >> 3); /* max: 14 */
|
||||
m7 = ((m7 * 147) >> 7) & 7;
|
||||
|
||||
/*
|
||||
* 2^5 = 32 = -1 mod 11.
|
||||
*/
|
||||
m11 = (m11 & 0x1F) + 66 - (m11 >> 5); /* max: 97 */
|
||||
m11 -= 88 & -GT(m11, 87);
|
||||
m11 -= 44 & -GT(m11, 43);
|
||||
m11 -= 22 & -GT(m11, 21);
|
||||
m11 -= 11 & -GT(m11, 10);
|
||||
|
||||
/*
|
||||
* If any of these modulo is 0, then the candidate is
|
||||
* not prime. Also, if pubexp is 3, 5, 7 or 11, and the
|
||||
* corresponding modulus is 1, then the candidate must
|
||||
* be rejected, because we need e to be invertible
|
||||
* modulo p-1. We can use simple comparisons here
|
||||
* because they won't leak information on a candidate
|
||||
* that we keep, only on one that we reject (and is thus
|
||||
* not secret).
|
||||
*/
|
||||
if (m3 == 0 || m5 == 0 || m7 == 0 || m11 == 0) {
|
||||
continue;
|
||||
}
|
||||
if ((pubexp == 3 && m3 == 1)
|
||||
|| (pubexp == 5 && m5 == 1)
|
||||
|| (pubexp == 7 && m7 == 1)
|
||||
|| (pubexp == 11 && m11 == 1))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* More trial divisions.
|
||||
*/
|
||||
if (!trial_divisions(x, t)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Miller-Rabin algorithm. Since we selected a random
|
||||
* integer, not a maliciously crafted integer, we can use
|
||||
* relatively few rounds to lower the risk of a false
|
||||
* positive (i.e. declaring prime a non-prime) under
|
||||
* 2^(-80). It is not useful to lower the probability much
|
||||
* below that, since that would be substantially below
|
||||
* the probability of the hardware misbehaving. Sufficient
|
||||
* numbers of rounds are extracted from the Handbook of
|
||||
* Applied Cryptography, note 4.49 (page 149).
|
||||
*
|
||||
* Since we work on the encoded size (esize), we need to
|
||||
* compare with encoded thresholds.
|
||||
*/
|
||||
if (esize < 320) {
|
||||
rounds = 12;
|
||||
} else if (esize < 480) {
|
||||
rounds = 9;
|
||||
} else if (esize < 693) {
|
||||
rounds = 6;
|
||||
} else if (esize < 906) {
|
||||
rounds = 4;
|
||||
} else if (esize < 1386) {
|
||||
rounds = 3;
|
||||
} else {
|
||||
rounds = 2;
|
||||
}
|
||||
|
||||
if (miller_rabin(rng, x, rounds, t, tlen)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Let p be a prime (p > 2^33, p = 3 mod 4). Let m = (p-1)/2, provided
|
||||
* as parameter (with announced bit length equal to that of p). This
|
||||
* function computes d = 1/e mod p-1 (for an odd integer e). Returned
|
||||
* value is 1 on success, 0 on error (an error is reported if e is not
|
||||
* invertible modulo p-1).
|
||||
*
|
||||
* The temporary buffer (t) must have room for at least 4 integers of
|
||||
* the size of p.
|
||||
*/
|
||||
static uint32_t
|
||||
invert_pubexp(uint16_t *d, const uint16_t *m, uint32_t e, uint16_t *t)
|
||||
{
|
||||
uint16_t *f;
|
||||
uint32_t r;
|
||||
|
||||
f = t;
|
||||
t += 1 + ((m[0] + 15) >> 4);
|
||||
|
||||
/*
|
||||
* Compute d = 1/e mod m. Since p = 3 mod 4, m is odd.
|
||||
*/
|
||||
br_i15_zero(d, m[0]);
|
||||
d[1] = 1;
|
||||
br_i15_zero(f, m[0]);
|
||||
f[1] = e & 0x7FFF;
|
||||
f[2] = (e >> 15) & 0x7FFF;
|
||||
f[3] = e >> 30;
|
||||
r = br_i15_moddiv(d, f, m, br_i15_ninv15(m[1]), t);
|
||||
|
||||
/*
|
||||
* We really want d = 1/e mod p-1, with p = 2m. By the CRT,
|
||||
* the result is either the d we got, or d + m.
|
||||
*
|
||||
* Let's write e*d = 1 + k*m, for some integer k. Integers e
|
||||
* and m are odd. If d is odd, then e*d is odd, which implies
|
||||
* that k must be even; in that case, e*d = 1 + (k/2)*2m, and
|
||||
* thus d is already fine. Conversely, if d is even, then k
|
||||
* is odd, and we must add m to d in order to get the correct
|
||||
* result.
|
||||
*/
|
||||
br_i15_add(d, m, (uint32_t)(1 - (d[1] & 1)));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Swap two buffers in RAM. They must be disjoint.
|
||||
*/
|
||||
static void
|
||||
bufswap(void *b1, void *b2, size_t len)
|
||||
{
|
||||
size_t u;
|
||||
unsigned char *buf1, *buf2;
|
||||
|
||||
buf1 = b1;
|
||||
buf2 = b2;
|
||||
for (u = 0; u < len; u ++) {
|
||||
unsigned w;
|
||||
|
||||
w = buf1[u];
|
||||
buf1[u] = buf2[u];
|
||||
buf2[u] = w;
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
uint32_t
|
||||
br_rsa_i15_keygen(const br_prng_class **rng,
|
||||
br_rsa_private_key *sk, void *kbuf_priv,
|
||||
br_rsa_public_key *pk, void *kbuf_pub,
|
||||
unsigned size, uint32_t pubexp)
|
||||
{
|
||||
uint32_t esize_p, esize_q;
|
||||
size_t plen, qlen, tlen;
|
||||
uint16_t *p, *q, *t;
|
||||
uint16_t tmp[TEMPS];
|
||||
uint32_t r;
|
||||
|
||||
if (size < BR_MIN_RSA_SIZE || size > BR_MAX_RSA_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
if (pubexp == 0) {
|
||||
pubexp = 3;
|
||||
} else if (pubexp == 1 || (pubexp & 1) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
esize_p = (size + 1) >> 1;
|
||||
esize_q = size - esize_p;
|
||||
sk->n_bitlen = size;
|
||||
sk->p = kbuf_priv;
|
||||
sk->plen = (esize_p + 7) >> 3;
|
||||
sk->q = sk->p + sk->plen;
|
||||
sk->qlen = (esize_q + 7) >> 3;
|
||||
sk->dp = sk->q + sk->qlen;
|
||||
sk->dplen = sk->plen;
|
||||
sk->dq = sk->dp + sk->dplen;
|
||||
sk->dqlen = sk->qlen;
|
||||
sk->iq = sk->dq + sk->dqlen;
|
||||
sk->iqlen = sk->plen;
|
||||
|
||||
if (pk != NULL) {
|
||||
pk->n = kbuf_pub;
|
||||
pk->nlen = (size + 7) >> 3;
|
||||
pk->e = pk->n + pk->nlen;
|
||||
pk->elen = 4;
|
||||
br_enc32be(pk->e, pubexp);
|
||||
while (*pk->e == 0) {
|
||||
pk->e ++;
|
||||
pk->elen --;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We now switch to encoded sizes.
|
||||
*
|
||||
* floor((x * 17477) / (2^18)) is equal to floor(x/15) for all
|
||||
* integers x from 0 to 23833.
|
||||
*/
|
||||
esize_p += MUL15(esize_p, 17477) >> 18;
|
||||
esize_q += MUL15(esize_q, 17477) >> 18;
|
||||
plen = (esize_p + 15) >> 4;
|
||||
qlen = (esize_q + 15) >> 4;
|
||||
p = tmp;
|
||||
q = p + 1 + plen;
|
||||
t = q + 1 + qlen;
|
||||
tlen = ((sizeof tmp) / sizeof(uint16_t)) - (2 + plen + qlen);
|
||||
|
||||
/*
|
||||
* When looking for primes p and q, we temporarily divide
|
||||
* candidates by 2, in order to compute the inverse of the
|
||||
* public exponent.
|
||||
*/
|
||||
|
||||
for (;;) {
|
||||
mkprime(rng, p, esize_p, pubexp, t, tlen);
|
||||
br_i15_rshift(p, 1);
|
||||
if (invert_pubexp(t, p, pubexp, t + 1 + plen)) {
|
||||
br_i15_add(p, p, 1);
|
||||
p[1] |= 1;
|
||||
br_i15_encode(sk->p, sk->plen, p);
|
||||
br_i15_encode(sk->dp, sk->dplen, t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
mkprime(rng, q, esize_q, pubexp, t, tlen);
|
||||
br_i15_rshift(q, 1);
|
||||
if (invert_pubexp(t, q, pubexp, t + 1 + qlen)) {
|
||||
br_i15_add(q, q, 1);
|
||||
q[1] |= 1;
|
||||
br_i15_encode(sk->q, sk->qlen, q);
|
||||
br_i15_encode(sk->dq, sk->dqlen, t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If p and q have the same size, then it is possible that q > p
|
||||
* (when the target modulus size is odd, we generate p with a
|
||||
* greater bit length than q). If q > p, we want to swap p and q
|
||||
* (and also dp and dq) for two reasons:
|
||||
* - The final step below (inversion of q modulo p) is easier if
|
||||
* p > q.
|
||||
* - While BearSSL's RSA code is perfectly happy with RSA keys such
|
||||
* that p < q, some other implementations have restrictions and
|
||||
* require p > q.
|
||||
*
|
||||
* Note that we can do a simple non-constant-time swap here,
|
||||
* because the only information we leak here is that we insist on
|
||||
* returning p and q such that p > q, which is not a secret.
|
||||
*/
|
||||
if (esize_p == esize_q && br_i15_sub(p, q, 0) == 1) {
|
||||
bufswap(p, q, (1 + plen) * sizeof *p);
|
||||
bufswap(sk->p, sk->q, sk->plen);
|
||||
bufswap(sk->dp, sk->dq, sk->dplen);
|
||||
}
|
||||
|
||||
/*
|
||||
* We have produced p, q, dp and dq. We can now compute iq = 1/d mod p.
|
||||
*
|
||||
* We ensured that p >= q, so this is just a matter of updating the
|
||||
* header word for q (and possibly adding an extra word).
|
||||
*
|
||||
* Theoretically, the call below may fail, in case we were
|
||||
* extraordinarily unlucky, and p = q. Another failure case is if
|
||||
* Miller-Rabin failed us _twice_, and p and q are non-prime and
|
||||
* have a factor is common. We report the error mostly because it
|
||||
* is cheap and we can, but in practice this never happens (or, at
|
||||
* least, it happens way less often than hardware glitches).
|
||||
*/
|
||||
q[0] = p[0];
|
||||
if (plen > qlen) {
|
||||
q[plen] = 0;
|
||||
t ++;
|
||||
tlen --;
|
||||
}
|
||||
br_i15_zero(t, p[0]);
|
||||
t[1] = 1;
|
||||
r = br_i15_moddiv(t, q, p, br_i15_ninv15(p[1]), t + 1 + plen);
|
||||
br_i15_encode(sk->iq, sk->iqlen, t);
|
||||
|
||||
/*
|
||||
* Compute the public modulus too, if required.
|
||||
*/
|
||||
if (pk != NULL) {
|
||||
br_i15_zero(t, p[0]);
|
||||
br_i15_mulacc(t, p, q);
|
||||
br_i15_encode(pk->n, pk->nlen, t);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
size_t
|
||||
br_rsa_i15_compute_modulus(void *n, const br_rsa_private_key *sk)
|
||||
{
|
||||
uint16_t tmp[4 * (((BR_MAX_RSA_SIZE / 2) + 14) / 15) + 5];
|
||||
uint16_t *t, *p, *q;
|
||||
const unsigned char *pbuf, *qbuf;
|
||||
size_t nlen, plen, qlen, tlen;
|
||||
|
||||
/*
|
||||
* Compute actual byte and lengths for p and q.
|
||||
*/
|
||||
pbuf = sk->p;
|
||||
plen = sk->plen;
|
||||
while (plen > 0 && *pbuf == 0) {
|
||||
pbuf ++;
|
||||
plen --;
|
||||
}
|
||||
qbuf = sk->q;
|
||||
qlen = sk->qlen;
|
||||
while (qlen > 0 && *qbuf == 0) {
|
||||
qbuf ++;
|
||||
qlen --;
|
||||
}
|
||||
|
||||
t = tmp;
|
||||
tlen = (sizeof tmp) / (sizeof tmp[0]);
|
||||
|
||||
/*
|
||||
* Decode p.
|
||||
*/
|
||||
if ((15 * tlen) < (plen << 3) + 15) {
|
||||
return 0;
|
||||
}
|
||||
br_i15_decode(t, pbuf, plen);
|
||||
p = t;
|
||||
plen = (p[0] + 31) >> 4;
|
||||
t += plen;
|
||||
tlen -= plen;
|
||||
|
||||
/*
|
||||
* Decode q.
|
||||
*/
|
||||
if ((15 * tlen) < (qlen << 3) + 15) {
|
||||
return 0;
|
||||
}
|
||||
br_i15_decode(t, qbuf, qlen);
|
||||
q = t;
|
||||
qlen = (q[0] + 31) >> 4;
|
||||
t += qlen;
|
||||
tlen -= qlen;
|
||||
|
||||
/*
|
||||
* Computation can proceed only if we have enough room for the
|
||||
* modulus.
|
||||
*/
|
||||
if (tlen < (plen + qlen + 1)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Private key already contains the modulus bit length, from which
|
||||
* we can infer the output length. Even if n is NULL, we still had
|
||||
* to decode p and q to make sure that the product can be computed.
|
||||
*/
|
||||
nlen = (sk->n_bitlen + 7) >> 3;
|
||||
if (n != NULL) {
|
||||
br_i15_zero(t, p[0]);
|
||||
br_i15_mulacc(t, p, q);
|
||||
br_i15_encode(n, nlen, t);
|
||||
}
|
||||
return nlen;
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
uint32_t
|
||||
br_rsa_i15_oaep_decrypt(const br_hash_class *dig,
|
||||
const void *label, size_t label_len,
|
||||
const br_rsa_private_key *sk, void *data, size_t *len)
|
||||
{
|
||||
uint32_t r;
|
||||
|
||||
if (*len != ((sk->n_bitlen + 7) >> 3)) {
|
||||
return 0;
|
||||
}
|
||||
r = br_rsa_i15_private(data, sk);
|
||||
r &= br_rsa_oaep_unpad(dig, label, label_len, data, len);
|
||||
return r;
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
size_t
|
||||
br_rsa_i15_oaep_encrypt(
|
||||
const br_prng_class **rnd, const br_hash_class *dig,
|
||||
const void *label, size_t label_len,
|
||||
const br_rsa_public_key *pk,
|
||||
void *dst, size_t dst_max_len,
|
||||
const void *src, size_t src_len)
|
||||
{
|
||||
size_t dlen;
|
||||
|
||||
dlen = br_rsa_oaep_pad(rnd, dig, label, label_len,
|
||||
pk, dst, dst_max_len, src, src_len);
|
||||
if (dlen == 0) {
|
||||
return 0;
|
||||
}
|
||||
return dlen & -(size_t)br_rsa_i15_public(dst, dlen, pk);
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
uint32_t
|
||||
br_rsa_i15_pkcs1_sign(const unsigned char *hash_oid,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
const br_rsa_private_key *sk, unsigned char *x)
|
||||
{
|
||||
if (!br_rsa_pkcs1_sig_pad(hash_oid, hash, hash_len, sk->n_bitlen, x)) {
|
||||
return 0;
|
||||
}
|
||||
return br_rsa_i15_private(x, sk);
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
uint32_t
|
||||
br_rsa_i15_pkcs1_vrfy(const unsigned char *x, size_t xlen,
|
||||
const unsigned char *hash_oid, size_t hash_len,
|
||||
const br_rsa_public_key *pk, unsigned char *hash_out)
|
||||
{
|
||||
unsigned char sig[BR_MAX_RSA_SIZE >> 3];
|
||||
|
||||
if (xlen > (sizeof sig)) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(sig, x, xlen);
|
||||
if (!br_rsa_i15_public(sig, xlen, pk)) {
|
||||
return 0;
|
||||
}
|
||||
return br_rsa_pkcs1_sig_unpad(sig, xlen, hash_oid, hash_len, hash_out);
|
||||
}
|
||||
|
|
@ -1,209 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define U (2 + ((BR_MAX_RSA_FACTOR + 14) / 15))
|
||||
#define TLEN (8 * U)
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
uint32_t
|
||||
br_rsa_i15_private(unsigned char *x, const br_rsa_private_key *sk)
|
||||
{
|
||||
const unsigned char *p, *q;
|
||||
size_t plen, qlen;
|
||||
size_t fwlen;
|
||||
uint16_t p0i, q0i;
|
||||
size_t xlen, u;
|
||||
uint16_t tmp[1 + TLEN];
|
||||
long z;
|
||||
uint16_t *mp, *mq, *s1, *s2, *t1, *t2, *t3;
|
||||
uint32_t r;
|
||||
|
||||
/*
|
||||
* Compute the actual lengths of p and q, in bytes.
|
||||
* These lengths are not considered secret (we cannot really hide
|
||||
* them anyway in constant-time code).
|
||||
*/
|
||||
p = sk->p;
|
||||
plen = sk->plen;
|
||||
while (plen > 0 && *p == 0) {
|
||||
p ++;
|
||||
plen --;
|
||||
}
|
||||
q = sk->q;
|
||||
qlen = sk->qlen;
|
||||
while (qlen > 0 && *q == 0) {
|
||||
q ++;
|
||||
qlen --;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the maximum factor length, in words.
|
||||
*/
|
||||
z = (long)(plen > qlen ? plen : qlen) << 3;
|
||||
fwlen = 1;
|
||||
while (z > 0) {
|
||||
z -= 15;
|
||||
fwlen ++;
|
||||
}
|
||||
/*
|
||||
* Round up the word length to an even number.
|
||||
*/
|
||||
fwlen += (fwlen & 1);
|
||||
|
||||
/*
|
||||
* We need to fit at least 6 values in the stack buffer.
|
||||
*/
|
||||
if (6 * fwlen > TLEN) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute signature length (in bytes).
|
||||
*/
|
||||
xlen = (sk->n_bitlen + 7) >> 3;
|
||||
|
||||
/*
|
||||
* Ensure 32-bit alignment for value words.
|
||||
*/
|
||||
mq = tmp;
|
||||
if (((uintptr_t)mq & 2) == 0) {
|
||||
mq ++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode q.
|
||||
*/
|
||||
br_i15_decode(mq, q, qlen);
|
||||
|
||||
/*
|
||||
* Decode p.
|
||||
*/
|
||||
t1 = mq + fwlen;
|
||||
br_i15_decode(t1, p, plen);
|
||||
|
||||
/*
|
||||
* Compute the modulus (product of the two factors), to compare
|
||||
* it with the source value. We use br_i15_mulacc(), since it's
|
||||
* already used later on.
|
||||
*/
|
||||
t2 = mq + 2 * fwlen;
|
||||
br_i15_zero(t2, mq[0]);
|
||||
br_i15_mulacc(t2, mq, t1);
|
||||
|
||||
/*
|
||||
* We encode the modulus into bytes, to perform the comparison
|
||||
* with bytes. We know that the product length, in bytes, is
|
||||
* exactly xlen.
|
||||
* The comparison actually computes the carry when subtracting
|
||||
* the modulus from the source value; that carry must be 1 for
|
||||
* a value in the correct range. We keep it in r, which is our
|
||||
* accumulator for the error code.
|
||||
*/
|
||||
t3 = mq + 4 * fwlen;
|
||||
br_i15_encode(t3, xlen, t2);
|
||||
u = xlen;
|
||||
r = 0;
|
||||
while (u > 0) {
|
||||
uint32_t wn, wx;
|
||||
|
||||
u --;
|
||||
wn = ((unsigned char *)t3)[u];
|
||||
wx = x[u];
|
||||
r = ((wx - (wn + r)) >> 8) & 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the decoded p to another temporary buffer.
|
||||
*/
|
||||
mp = mq + 2 * fwlen;
|
||||
memmove(mp, t1, fwlen * sizeof *t1);
|
||||
|
||||
/*
|
||||
* Compute s2 = x^dq mod q.
|
||||
*/
|
||||
q0i = br_i15_ninv15(mq[1]);
|
||||
s2 = mq + fwlen;
|
||||
br_i15_decode_reduce(s2, x, xlen, mq);
|
||||
r &= br_i15_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i,
|
||||
mq + 3 * fwlen, TLEN - 3 * fwlen);
|
||||
|
||||
/*
|
||||
* Compute s1 = x^dq mod q.
|
||||
*/
|
||||
p0i = br_i15_ninv15(mp[1]);
|
||||
s1 = mq + 3 * fwlen;
|
||||
br_i15_decode_reduce(s1, x, xlen, mp);
|
||||
r &= br_i15_modpow_opt(s1, sk->dp, sk->dplen, mp, p0i,
|
||||
mq + 4 * fwlen, TLEN - 4 * fwlen);
|
||||
|
||||
/*
|
||||
* Compute:
|
||||
* h = (s1 - s2)*(1/q) mod p
|
||||
* s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is
|
||||
* unclear about whether p may be lower than q (some existing,
|
||||
* widely deployed implementations of RSA don't tolerate p < q),
|
||||
* but we want to support that occurrence, so we need to use the
|
||||
* reduction function.
|
||||
*
|
||||
* Since we use br_i15_decode_reduce() for iq (purportedly, the
|
||||
* inverse of q modulo p), we also tolerate improperly large
|
||||
* values for this parameter.
|
||||
*/
|
||||
t1 = mq + 4 * fwlen;
|
||||
t2 = mq + 5 * fwlen;
|
||||
br_i15_reduce(t2, s2, mp);
|
||||
br_i15_add(s1, mp, br_i15_sub(s1, t2, 1));
|
||||
br_i15_to_monty(s1, mp);
|
||||
br_i15_decode_reduce(t1, sk->iq, sk->iqlen, mp);
|
||||
br_i15_montymul(t2, s1, t1, mp, p0i);
|
||||
|
||||
/*
|
||||
* h is now in t2. We compute the final result:
|
||||
* s = s2 + q*h
|
||||
* All these operations are non-modular.
|
||||
*
|
||||
* We need mq, s2 and t2. We use the t3 buffer as destination.
|
||||
* The buffers mp, s1 and t1 are no longer needed, so we can
|
||||
* reuse them for t3. Moreover, the first step of the computation
|
||||
* is to copy s2 into t3, after which s2 is not needed. Right
|
||||
* now, mq is in slot 0, s2 is in slot 1, and t2 in slot 5.
|
||||
* Therefore, we have ample room for t3 by simply using s2.
|
||||
*/
|
||||
t3 = s2;
|
||||
br_i15_mulacc(t3, mq, t2);
|
||||
|
||||
/*
|
||||
* Encode the result. Since we already checked the value of xlen,
|
||||
* we can just use it right away.
|
||||
*/
|
||||
br_i15_encode(x, xlen, t3);
|
||||
|
||||
/*
|
||||
* The only error conditions remaining at that point are invalid
|
||||
* values for p and q (even integers).
|
||||
*/
|
||||
return p0i & q0i & r;
|
||||
}
|
||||
|
|
@ -1,320 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
size_t
|
||||
br_rsa_i15_compute_privexp(void *d,
|
||||
const br_rsa_private_key *sk, uint32_t e)
|
||||
{
|
||||
/*
|
||||
* We want to invert e modulo phi = (p-1)(q-1). This first
|
||||
* requires computing phi, which is easy since we have the factors
|
||||
* p and q in the private key structure.
|
||||
*
|
||||
* Since p = 3 mod 4 and q = 3 mod 4, phi/4 is an odd integer.
|
||||
* We could invert e modulo phi/4 then patch the result to
|
||||
* modulo phi, but this would involve assembling three modulus-wide
|
||||
* values (phi/4, 1 and e) and calling moddiv, that requires
|
||||
* three more temporaries, for a total of six big integers, or
|
||||
* slightly more than 3 kB of stack space for RSA-4096. This
|
||||
* exceeds our stack requirements.
|
||||
*
|
||||
* Instead, we first use one step of the extended GCD:
|
||||
*
|
||||
* - We compute phi = k*e + r (Euclidean division of phi by e).
|
||||
* If public exponent e is correct, then r != 0 (e must be
|
||||
* invertible modulo phi). We also have k != 0 since we
|
||||
* enforce non-ridiculously-small factors.
|
||||
*
|
||||
* - We find small u, v such that u*e - v*r = 1 (using a
|
||||
* binary GCD; we can arrange for u < r and v < e, i.e. all
|
||||
* values fit on 32 bits).
|
||||
*
|
||||
* - Solution is: d = u + v*k
|
||||
* This last computation is exact: since u < r and v < e,
|
||||
* the above implies d < r + e*((phi-r)/e) = phi
|
||||
*/
|
||||
|
||||
uint16_t tmp[4 * ((BR_MAX_RSA_FACTOR + 14) / 15) + 12];
|
||||
uint16_t *p, *q, *k, *m, *z, *phi;
|
||||
const unsigned char *pbuf, *qbuf;
|
||||
size_t plen, qlen, u, len, dlen;
|
||||
uint32_t r, a, b, u0, v0, u1, v1, he, hr;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Check that e is correct.
|
||||
*/
|
||||
if (e < 3 || (e & 1) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check lengths of p and q, and that they are both odd.
|
||||
*/
|
||||
pbuf = sk->p;
|
||||
plen = sk->plen;
|
||||
while (plen > 0 && *pbuf == 0) {
|
||||
pbuf ++;
|
||||
plen --;
|
||||
}
|
||||
if (plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8)
|
||||
|| (pbuf[plen - 1] & 1) != 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
qbuf = sk->q;
|
||||
qlen = sk->qlen;
|
||||
while (qlen > 0 && *qbuf == 0) {
|
||||
qbuf ++;
|
||||
qlen --;
|
||||
}
|
||||
if (qlen < 5 || qlen > (BR_MAX_RSA_FACTOR / 8)
|
||||
|| (qbuf[qlen - 1] & 1) != 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Output length is that of the modulus.
|
||||
*/
|
||||
dlen = (sk->n_bitlen + 7) >> 3;
|
||||
if (d == NULL) {
|
||||
return dlen;
|
||||
}
|
||||
|
||||
p = tmp;
|
||||
br_i15_decode(p, pbuf, plen);
|
||||
plen = (p[0] + 15) >> 4;
|
||||
q = p + 1 + plen;
|
||||
br_i15_decode(q, qbuf, qlen);
|
||||
qlen = (q[0] + 15) >> 4;
|
||||
|
||||
/*
|
||||
* Compute phi = (p-1)*(q-1), then move it over p-1 and q-1 (that
|
||||
* we do not need anymore). The mulacc function sets the announced
|
||||
* bit length of t to be the sum of the announced bit lengths of
|
||||
* p-1 and q-1, which is usually exact but may overshoot by one 1
|
||||
* bit in some cases; we readjust it to its true length.
|
||||
*/
|
||||
p[1] --;
|
||||
q[1] --;
|
||||
phi = q + 1 + qlen;
|
||||
br_i15_zero(phi, p[0]);
|
||||
br_i15_mulacc(phi, p, q);
|
||||
len = (phi[0] + 15) >> 4;
|
||||
memmove(tmp, phi, (1 + len) * sizeof *phi);
|
||||
phi = tmp;
|
||||
phi[0] = br_i15_bit_length(phi + 1, len);
|
||||
len = (phi[0] + 15) >> 4;
|
||||
|
||||
/*
|
||||
* Divide phi by public exponent e. The final remainder r must be
|
||||
* non-zero (otherwise, the key is invalid). The quotient is k,
|
||||
* which we write over phi, since we don't need phi after that.
|
||||
*/
|
||||
r = 0;
|
||||
for (u = len; u >= 1; u --) {
|
||||
/*
|
||||
* Upon entry, r < e, and phi[u] < 2^15; hence,
|
||||
* hi:lo < e*2^15. Thus, the produced word k[u]
|
||||
* must be lower than 2^15, and the new remainder r
|
||||
* is lower than e.
|
||||
*/
|
||||
uint32_t hi, lo;
|
||||
|
||||
hi = r >> 17;
|
||||
lo = (r << 15) + phi[u];
|
||||
phi[u] = br_divrem(hi, lo, e, &r);
|
||||
}
|
||||
if (r == 0) {
|
||||
return 0;
|
||||
}
|
||||
k = phi;
|
||||
|
||||
/*
|
||||
* Compute u and v such that u*e - v*r = GCD(e,r). We use
|
||||
* a binary GCD algorithm, with 6 extra integers a, b,
|
||||
* u0, u1, v0 and v1. Initial values are:
|
||||
* a = e u0 = 1 v0 = 0
|
||||
* b = r u1 = r v1 = e-1
|
||||
* The following invariants are maintained:
|
||||
* a = u0*e - v0*r
|
||||
* b = u1*e - v1*r
|
||||
* 0 < a <= e
|
||||
* 0 < b <= r
|
||||
* 0 <= u0 <= r
|
||||
* 0 <= v0 <= e
|
||||
* 0 <= u1 <= r
|
||||
* 0 <= v1 <= e
|
||||
*
|
||||
* At each iteration, we reduce either a or b by one bit, and
|
||||
* adjust u0, u1, v0 and v1 to maintain the invariants:
|
||||
* - if a is even, then a <- a/2
|
||||
* - otherwise, if b is even, then b <- b/2
|
||||
* - otherwise, if a > b, then a <- (a-b)/2
|
||||
* - otherwise, if b > a, then b <- (b-a)/2
|
||||
* Algorithm stops when a = b. At that point, the common value
|
||||
* is the GCD of e and r; it must be 1 (otherwise, the private
|
||||
* key or public exponent is not valid). The (u0,v0) or (u1,v1)
|
||||
* pairs are the solution we are looking for.
|
||||
*
|
||||
* Since either a or b is reduced by at least 1 bit at each
|
||||
* iteration, 62 iterations are enough to reach the end
|
||||
* condition.
|
||||
*
|
||||
* To maintain the invariants, we must compute the same operations
|
||||
* on the u* and v* values that we do on a and b:
|
||||
* - When a is divided by 2, u0 and v0 must be divided by 2.
|
||||
* - When b is divided by 2, u1 and v1 must be divided by 2.
|
||||
* - When b is subtracted from a, u1 and v1 are subtracted from
|
||||
* u0 and v0, respectively.
|
||||
* - When a is subtracted from b, u0 and v0 are subtracted from
|
||||
* u1 and v1, respectively.
|
||||
*
|
||||
* However, we want to keep the u* and v* values in their proper
|
||||
* ranges. The following remarks apply:
|
||||
*
|
||||
* - When a is divided by 2, then a is even. Therefore:
|
||||
*
|
||||
* * If r is odd, then u0 and v0 must have the same parity;
|
||||
* if they are both odd, then adding r to u0 and e to v0
|
||||
* makes them both even, and the division by 2 brings them
|
||||
* back to the proper range.
|
||||
*
|
||||
* * If r is even, then u0 must be even; if v0 is odd, then
|
||||
* adding r to u0 and e to v0 makes them both even, and the
|
||||
* division by 2 brings them back to the proper range.
|
||||
*
|
||||
* Thus, all we need to do is to look at the parity of v0,
|
||||
* and add (r,e) to (u0,v0) when v0 is odd. In order to avoid
|
||||
* a 32-bit overflow, we can add ((r+1)/2,(e/2)+1) after the
|
||||
* division (r+1 does not overflow since r < e; and (e/2)+1
|
||||
* is equal to (e+1)/2 since e is odd).
|
||||
*
|
||||
* - When we subtract b from a, three cases may occur:
|
||||
*
|
||||
* * u1 <= u0 and v1 <= v0: just do the subtractions
|
||||
*
|
||||
* * u1 > u0 and v1 > v0: compute:
|
||||
* (u0, v0) <- (u0 + r - u1, v0 + e - v1)
|
||||
*
|
||||
* * u1 <= u0 and v1 > v0: compute:
|
||||
* (u0, v0) <- (u0 + r - u1, v0 + e - v1)
|
||||
*
|
||||
* The fourth case (u1 > u0 and v1 <= v0) is not possible
|
||||
* because it would contradict "b < a" (which is the reason
|
||||
* why we subtract b from a).
|
||||
*
|
||||
* The tricky case is the third one: from the equations, it
|
||||
* seems that u0 may go out of range. However, the invariants
|
||||
* and ranges of other values imply that, in that case, the
|
||||
* new u0 does not actually exceed the range.
|
||||
*
|
||||
* We can thus handle the subtraction by adding (r,e) based
|
||||
* solely on the comparison between v0 and v1.
|
||||
*/
|
||||
a = e;
|
||||
b = r;
|
||||
u0 = 1;
|
||||
v0 = 0;
|
||||
u1 = r;
|
||||
v1 = e - 1;
|
||||
hr = (r + 1) >> 1;
|
||||
he = (e >> 1) + 1;
|
||||
for (i = 0; i < 62; i ++) {
|
||||
uint32_t oa, ob, agtb, bgta;
|
||||
uint32_t sab, sba, da, db;
|
||||
uint32_t ctl;
|
||||
|
||||
oa = a & 1; /* 1 if a is odd */
|
||||
ob = b & 1; /* 1 if b is odd */
|
||||
agtb = GT(a, b); /* 1 if a > b */
|
||||
bgta = GT(b, a); /* 1 if b > a */
|
||||
|
||||
sab = oa & ob & agtb; /* 1 if a <- a-b */
|
||||
sba = oa & ob & bgta; /* 1 if b <- b-a */
|
||||
|
||||
/* a <- a-b, u0 <- u0-u1, v0 <- v0-v1 */
|
||||
ctl = GT(v1, v0);
|
||||
a -= b & -sab;
|
||||
u0 -= (u1 - (r & -ctl)) & -sab;
|
||||
v0 -= (v1 - (e & -ctl)) & -sab;
|
||||
|
||||
/* b <- b-a, u1 <- u1-u0 mod r, v1 <- v1-v0 mod e */
|
||||
ctl = GT(v0, v1);
|
||||
b -= a & -sba;
|
||||
u1 -= (u0 - (r & -ctl)) & -sba;
|
||||
v1 -= (v0 - (e & -ctl)) & -sba;
|
||||
|
||||
da = NOT(oa) | sab; /* 1 if a <- a/2 */
|
||||
db = (oa & NOT(ob)) | sba; /* 1 if b <- b/2 */
|
||||
|
||||
/* a <- a/2, u0 <- u0/2, v0 <- v0/2 */
|
||||
ctl = v0 & 1;
|
||||
a ^= (a ^ (a >> 1)) & -da;
|
||||
u0 ^= (u0 ^ ((u0 >> 1) + (hr & -ctl))) & -da;
|
||||
v0 ^= (v0 ^ ((v0 >> 1) + (he & -ctl))) & -da;
|
||||
|
||||
/* b <- b/2, u1 <- u1/2 mod r, v1 <- v1/2 mod e */
|
||||
ctl = v1 & 1;
|
||||
b ^= (b ^ (b >> 1)) & -db;
|
||||
u1 ^= (u1 ^ ((u1 >> 1) + (hr & -ctl))) & -db;
|
||||
v1 ^= (v1 ^ ((v1 >> 1) + (he & -ctl))) & -db;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that the GCD is indeed 1. If not, then the key is invalid
|
||||
* (and there's no harm in leaking that piece of information).
|
||||
*/
|
||||
if (a != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we have u0*e - v0*r = 1. Let's compute the result as:
|
||||
* d = u0 + v0*k
|
||||
* We still have k in the tmp[] array, and its announced bit
|
||||
* length is that of phi.
|
||||
*/
|
||||
m = k + 1 + len;
|
||||
m[0] = (2 << 4) + 2; /* bit length is 32 bits, encoded */
|
||||
m[1] = v0 & 0x7FFF;
|
||||
m[2] = (v0 >> 15) & 0x7FFF;
|
||||
m[3] = v0 >> 30;
|
||||
z = m + 4;
|
||||
br_i15_zero(z, k[0]);
|
||||
z[1] = u0 & 0x7FFF;
|
||||
z[2] = (u0 >> 15) & 0x7FFF;
|
||||
z[3] = u0 >> 30;
|
||||
br_i15_mulacc(z, k, m);
|
||||
|
||||
/*
|
||||
* Encode the result.
|
||||
*/
|
||||
br_i15_encode(d, dlen, z);
|
||||
return dlen;
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
uint32_t
|
||||
br_rsa_i15_pss_sign(const br_prng_class **rng,
|
||||
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
|
||||
const unsigned char *hash, size_t salt_len,
|
||||
const br_rsa_private_key *sk, unsigned char *x)
|
||||
{
|
||||
if (!br_rsa_pss_sig_pad(rng, hf_data, hf_mgf1, hash,
|
||||
salt_len, sk->n_bitlen, x))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return br_rsa_i15_private(x, sk);
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
uint32_t
|
||||
br_rsa_i15_pss_vrfy(const unsigned char *x, size_t xlen,
|
||||
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
|
||||
const void *hash, size_t salt_len, const br_rsa_public_key *pk)
|
||||
{
|
||||
unsigned char sig[BR_MAX_RSA_SIZE >> 3];
|
||||
|
||||
if (xlen > (sizeof sig)) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(sig, x, xlen);
|
||||
if (!br_rsa_i15_public(sig, xlen, pk)) {
|
||||
return 0;
|
||||
}
|
||||
return br_rsa_pss_sig_unpad(hf_data, hf_mgf1,
|
||||
hash, salt_len, pk, sig);
|
||||
}
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* As a strict minimum, we need four buffers that can hold a
|
||||
* modular integer.
|
||||
*/
|
||||
#define TLEN (4 * (2 + ((BR_MAX_RSA_SIZE + 14) / 15)))
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
uint32_t
|
||||
br_rsa_i15_public(unsigned char *x, size_t xlen,
|
||||
const br_rsa_public_key *pk)
|
||||
{
|
||||
const unsigned char *n;
|
||||
size_t nlen;
|
||||
uint16_t tmp[1 + TLEN];
|
||||
uint16_t *m, *a, *t;
|
||||
size_t fwlen;
|
||||
long z;
|
||||
uint16_t m0i;
|
||||
uint32_t r;
|
||||
|
||||
/*
|
||||
* Get the actual length of the modulus, and see if it fits within
|
||||
* our stack buffer. We also check that the length of x[] is valid.
|
||||
*/
|
||||
n = pk->n;
|
||||
nlen = pk->nlen;
|
||||
while (nlen > 0 && *n == 0) {
|
||||
n ++;
|
||||
nlen --;
|
||||
}
|
||||
if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) {
|
||||
return 0;
|
||||
}
|
||||
z = (long)nlen << 3;
|
||||
fwlen = 1;
|
||||
while (z > 0) {
|
||||
z -= 15;
|
||||
fwlen ++;
|
||||
}
|
||||
/*
|
||||
* Round up length to an even number.
|
||||
*/
|
||||
fwlen += (fwlen & 1);
|
||||
|
||||
/*
|
||||
* The modulus gets decoded into m[].
|
||||
* The value to exponentiate goes into a[].
|
||||
* The temporaries for modular exponentiations are in t[].
|
||||
*
|
||||
* We want the first value word of each integer to be aligned
|
||||
* on a 32-bit boundary.
|
||||
*/
|
||||
m = tmp;
|
||||
if (((uintptr_t)m & 2) == 0) {
|
||||
m ++;
|
||||
}
|
||||
a = m + fwlen;
|
||||
t = m + 2 * fwlen;
|
||||
|
||||
/*
|
||||
* Decode the modulus.
|
||||
*/
|
||||
br_i15_decode(m, n, nlen);
|
||||
m0i = br_i15_ninv15(m[1]);
|
||||
|
||||
/*
|
||||
* Note: if m[] is even, then m0i == 0. Otherwise, m0i must be
|
||||
* an odd integer.
|
||||
*/
|
||||
r = m0i & 1;
|
||||
|
||||
/*
|
||||
* Decode x[] into a[]; we also check that its value is proper.
|
||||
*/
|
||||
r &= br_i15_decode_mod(a, x, xlen, m);
|
||||
|
||||
/*
|
||||
* Compute the modular exponentiation.
|
||||
*/
|
||||
br_i15_modpow_opt(a, pk->e, pk->elen, m, m0i, t, TLEN - 2 * fwlen);
|
||||
|
||||
/*
|
||||
* Encode the result.
|
||||
*/
|
||||
br_i15_encode(x, xlen, a);
|
||||
return r;
|
||||
}
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Recompute public exponent, based on factor p and reduced private
|
||||
* exponent dp.
|
||||
*/
|
||||
static uint32_t
|
||||
get_pubexp(const unsigned char *pbuf, size_t plen,
|
||||
const unsigned char *dpbuf, size_t dplen)
|
||||
{
|
||||
/*
|
||||
* dp is the inverse of e modulo p-1. If p = 3 mod 4, then
|
||||
* p-1 = 2*((p-1)/2). Taken modulo 2, e is odd and has inverse 1;
|
||||
* thus, dp must be odd.
|
||||
*
|
||||
* We compute the inverse of dp modulo (p-1)/2. This requires
|
||||
* first reducing dp modulo (p-1)/2 (this can be done with a
|
||||
* conditional subtract, no need to use the generic modular
|
||||
* reduction function); then, we use moddiv.
|
||||
*/
|
||||
|
||||
uint16_t tmp[6 * ((BR_MAX_RSA_FACTOR + 29) / 15)];
|
||||
uint16_t *p, *dp, *x;
|
||||
size_t len;
|
||||
uint32_t e;
|
||||
|
||||
/*
|
||||
* Compute actual factor length (in bytes) and check that it fits
|
||||
* under our size constraints.
|
||||
*/
|
||||
while (plen > 0 && *pbuf == 0) {
|
||||
pbuf ++;
|
||||
plen --;
|
||||
}
|
||||
if (plen == 0 || plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute actual reduced exponent length (in bytes) and check that
|
||||
* it is not longer than p.
|
||||
*/
|
||||
while (dplen > 0 && *dpbuf == 0) {
|
||||
dpbuf ++;
|
||||
dplen --;
|
||||
}
|
||||
if (dplen > plen || dplen == 0
|
||||
|| (dplen == plen && dpbuf[0] > pbuf[0]))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that p = 3 mod 4 and that dp is odd.
|
||||
*/
|
||||
if ((pbuf[plen - 1] & 3) != 3 || (dpbuf[dplen - 1] & 1) != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode p and compute (p-1)/2.
|
||||
*/
|
||||
p = tmp;
|
||||
br_i15_decode(p, pbuf, plen);
|
||||
len = (p[0] + 31) >> 4;
|
||||
br_i15_rshift(p, 1);
|
||||
|
||||
/*
|
||||
* Decode dp and make sure its announced bit length matches that of
|
||||
* p (we already know that the size of dp, in bits, does not exceed
|
||||
* the size of p, so we just have to copy the header word).
|
||||
*/
|
||||
dp = p + len;
|
||||
memset(dp, 0, len * sizeof *dp);
|
||||
br_i15_decode(dp, dpbuf, dplen);
|
||||
dp[0] = p[0];
|
||||
|
||||
/*
|
||||
* Subtract (p-1)/2 from dp if necessary.
|
||||
*/
|
||||
br_i15_sub(dp, p, NOT(br_i15_sub(dp, p, 0)));
|
||||
|
||||
/*
|
||||
* If another subtraction is needed, then this means that the
|
||||
* value was invalid. We don't care to leak information about
|
||||
* invalid keys.
|
||||
*/
|
||||
if (br_i15_sub(dp, p, 0) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invert dp modulo (p-1)/2. If the inversion fails, then the
|
||||
* key value was invalid.
|
||||
*/
|
||||
x = dp + len;
|
||||
br_i15_zero(x, p[0]);
|
||||
x[1] = 1;
|
||||
if (br_i15_moddiv(x, dp, p, br_i15_ninv15(p[1]), x + len) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We now have an inverse. We must set it to zero (error) if its
|
||||
* length is greater than 32 bits and/or if it is an even integer.
|
||||
* Take care that the bit_length function returns an encoded
|
||||
* bit length.
|
||||
*/
|
||||
e = (uint32_t)x[1] | ((uint32_t)x[2] << 15) | ((uint32_t)x[3] << 30);
|
||||
e &= -LT(br_i15_bit_length(x + 1, len - 1), 35);
|
||||
e &= -(e & 1);
|
||||
return e;
|
||||
}
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
uint32_t
|
||||
br_rsa_i15_compute_pubexp(const br_rsa_private_key *sk)
|
||||
{
|
||||
/*
|
||||
* Get the public exponent from both p and q. This is the right
|
||||
* exponent if we get twice the same value.
|
||||
*/
|
||||
uint32_t ep, eq;
|
||||
|
||||
ep = get_pubexp(sk->p, sk->plen, sk->dp, sk->dplen);
|
||||
eq = get_pubexp(sk->q, sk->qlen, sk->dq, sk->dqlen);
|
||||
return ep & -EQ(ep, eq);
|
||||
}
|
||||
|
|
@ -1,299 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const br_config_option config[] = {
|
||||
{ "BR_64",
|
||||
#if BR_64
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_AES_X86NI",
|
||||
#if BR_AES_X86NI
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_amd64",
|
||||
#if BR_amd64
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_ARMEL_CORTEXM_GCC",
|
||||
#if BR_ARMEL_CORTEXM_GCC
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_BE_UNALIGNED",
|
||||
#if BR_BE_UNALIGNED
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_CLANG",
|
||||
#if BR_CLANG
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_CLANG_3_7",
|
||||
#if BR_CLANG_3_7
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_CLANG_3_8",
|
||||
#if BR_CLANG_3_8
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_CT_MUL15",
|
||||
#if BR_CT_MUL15
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_CT_MUL31",
|
||||
#if BR_CT_MUL31
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_GCC",
|
||||
#if BR_GCC
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_GCC_4_4",
|
||||
#if BR_GCC_4_4
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_GCC_4_5",
|
||||
#if BR_GCC_4_5
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_GCC_4_6",
|
||||
#if BR_GCC_4_6
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_GCC_4_7",
|
||||
#if BR_GCC_4_7
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_GCC_4_8",
|
||||
#if BR_GCC_4_8
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_GCC_4_9",
|
||||
#if BR_GCC_4_9
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_GCC_5_0",
|
||||
#if BR_GCC_5_0
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_i386",
|
||||
#if BR_i386
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_INT128",
|
||||
#if BR_INT128
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_LE_UNALIGNED",
|
||||
#if BR_LE_UNALIGNED
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_LOMUL",
|
||||
#if BR_LOMUL
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_MAX_EC_SIZE", BR_MAX_EC_SIZE },
|
||||
{ "BR_MAX_RSA_SIZE", BR_MAX_RSA_SIZE },
|
||||
{ "BR_MAX_RSA_FACTOR", BR_MAX_RSA_FACTOR },
|
||||
{ "BR_MSC",
|
||||
#if BR_MSC
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_MSC_2005",
|
||||
#if BR_MSC_2005
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_MSC_2008",
|
||||
#if BR_MSC_2008
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_MSC_2010",
|
||||
#if BR_MSC_2010
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_MSC_2012",
|
||||
#if BR_MSC_2012
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_MSC_2013",
|
||||
#if BR_MSC_2013
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_MSC_2015",
|
||||
#if BR_MSC_2015
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_RDRAND",
|
||||
#if BR_RDRAND
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_SLOW_MUL",
|
||||
#if BR_SLOW_MUL
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_SLOW_MUL15",
|
||||
#if BR_SLOW_MUL15
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_SSE2",
|
||||
#if BR_SSE2
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_UMUL128",
|
||||
#if BR_UMUL128
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_USE_UNIX_TIME",
|
||||
#if BR_USE_UNIX_TIME
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_USE_WIN32_RAND",
|
||||
#if BR_USE_WIN32_RAND
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "BR_USE_WIN32_TIME",
|
||||
#if BR_USE_WIN32_TIME
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
/* see bearssl.h */
|
||||
const br_config_option *
|
||||
br_get_config(void)
|
||||
{
|
||||
return config;
|
||||
}
|
||||
|
|
@ -61,9 +61,7 @@ br_ssl_engine_set_default_aes_gcm(br_ssl_engine_context *cc)
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
#if BR_LOMUL
|
||||
br_ssl_engine_set_ghash(cc, &br_ghash_ctmul32);
|
||||
#elif BR_64
|
||||
#if BR_64
|
||||
br_ssl_engine_set_ghash(cc, &br_ghash_ctmul64);
|
||||
#else
|
||||
br_ssl_engine_set_ghash(cc, &br_ghash_ctmul);
|
||||
|
|
|
|||
|
|
@ -54,11 +54,7 @@ br_ssl_engine_set_default_chapol(br_ssl_engine_context *cc)
|
|||
br_ssl_engine_set_poly1305(cc, bp);
|
||||
} else {
|
||||
#endif
|
||||
#if BR_LOMUL
|
||||
br_ssl_engine_set_poly1305(cc, &br_poly1305_ctmul32_run);
|
||||
#else
|
||||
br_ssl_engine_set_poly1305(cc, &br_poly1305_ctmul_run);
|
||||
#endif
|
||||
#if BR_INT128 || BR_UMUL128
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -28,9 +28,5 @@
|
|||
void
|
||||
br_ssl_engine_set_default_ec(br_ssl_engine_context *cc)
|
||||
{
|
||||
#if BR_LOMUL
|
||||
br_ssl_engine_set_ec(cc, &br_ec_all_m15);
|
||||
#else
|
||||
br_ssl_engine_set_ec(cc, &br_ec_all_m31);
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,11 +28,6 @@
|
|||
void
|
||||
br_ssl_engine_set_default_ecdsa(br_ssl_engine_context *cc)
|
||||
{
|
||||
#if BR_LOMUL
|
||||
br_ssl_engine_set_ec(cc, &br_ec_all_m15);
|
||||
br_ssl_engine_set_ecdsa(cc, &br_ecdsa_i15_vrfy_asn1);
|
||||
#else
|
||||
br_ssl_engine_set_ec(cc, &br_ec_all_m31);
|
||||
br_ssl_engine_set_ecdsa(cc, &br_ecdsa_i31_vrfy_asn1);
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,537 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Each entry consists in a fixed number of bytes. Entries are concatenated
|
||||
* in the store block. "Addresses" are really offsets in the block,
|
||||
* expressed over 32 bits (so the cache may have size at most 4 GB, which
|
||||
* "ought to be enough for everyone"). The "null address" is 0xFFFFFFFF.
|
||||
* Note that since the storage block alignment is in no way guaranteed, we
|
||||
* perform only accesses that can handle unaligned data.
|
||||
*
|
||||
* Two concurrent data structures are maintained:
|
||||
*
|
||||
* -- Entries are organised in a doubly-linked list; saved entries are added
|
||||
* at the head, and loaded entries are moved to the head. Eviction uses
|
||||
* the list tail (this is the LRU algorithm).
|
||||
*
|
||||
* -- Entries are indexed with a binary tree: all left descendants of a
|
||||
* node have a lower session ID (in lexicographic order), while all
|
||||
* right descendants have a higher session ID. The tree is heuristically
|
||||
* balanced.
|
||||
*
|
||||
* Entry format:
|
||||
*
|
||||
* session ID 32 bytes
|
||||
* master secret 48 bytes
|
||||
* protocol version 2 bytes (big endian)
|
||||
* cipher suite 2 bytes (big endian)
|
||||
* list prev 4 bytes (big endian)
|
||||
* list next 4 bytes (big endian)
|
||||
* tree left child 4 bytes (big endian)
|
||||
* tree right child 4 bytes (big endian)
|
||||
*
|
||||
* If an entry has a protocol version set to 0, then it is "disabled":
|
||||
* it was a session pushed to the cache at some point, but it has
|
||||
* been explicitly removed.
|
||||
*
|
||||
* We need to keep the tree balanced because an attacker could make
|
||||
* handshakes, selecting some specific sessions (by reusing them) to
|
||||
* try to make us make an imbalanced tree that makes lookups expensive
|
||||
* (a denial-of-service attack that would persist as long as the cache
|
||||
* remains, i.e. even after the attacker made all his connections).
|
||||
* To do that, we replace the session ID (or the start of the session ID)
|
||||
* with a HMAC value computed over the replaced part; the hash function
|
||||
* implementation and the key are obtained from the server context upon
|
||||
* first save() call.
|
||||
*
|
||||
* Theoretically, an attacker could use the exact timing of the lookup
|
||||
* to infer the current tree topology, and try to revive entries to make
|
||||
* it as unbalanced as possible. However, since the session ID are
|
||||
* chosen randomly by the server, and the attacker cannot see the
|
||||
* indexing values and must thus rely on blind selection, it should be
|
||||
* exponentially difficult for the attacker to maintain a large
|
||||
* imbalance.
|
||||
*/
|
||||
#define SESSION_ID_LEN 32
|
||||
#define MASTER_SECRET_LEN 48
|
||||
|
||||
#define SESSION_ID_OFF 0
|
||||
#define MASTER_SECRET_OFF 32
|
||||
#define VERSION_OFF 80
|
||||
#define CIPHER_SUITE_OFF 82
|
||||
#define LIST_PREV_OFF 84
|
||||
#define LIST_NEXT_OFF 88
|
||||
#define TREE_LEFT_OFF 92
|
||||
#define TREE_RIGHT_OFF 96
|
||||
|
||||
#define LRU_ENTRY_LEN 100
|
||||
|
||||
#define ADDR_NULL ((uint32_t)-1)
|
||||
|
||||
#define GETSET(name, off) \
|
||||
static inline uint32_t get_ ## name(br_ssl_session_cache_lru *cc, uint32_t x) \
|
||||
{ \
|
||||
return br_dec32be(cc->store + x + (off)); \
|
||||
} \
|
||||
static inline void set_ ## name(br_ssl_session_cache_lru *cc, \
|
||||
uint32_t x, uint32_t val) \
|
||||
{ \
|
||||
br_enc32be(cc->store + x + (off), val); \
|
||||
}
|
||||
|
||||
GETSET(prev, LIST_PREV_OFF)
|
||||
GETSET(next, LIST_NEXT_OFF)
|
||||
GETSET(left, TREE_LEFT_OFF)
|
||||
GETSET(right, TREE_RIGHT_OFF)
|
||||
|
||||
/*
|
||||
* Transform the session ID by replacing the first N bytes with a HMAC
|
||||
* value computed over these bytes, using the random key K (the HMAC
|
||||
* value is truncated if needed). HMAC will use the same hash function
|
||||
* as the DRBG in the SSL server context, so with SHA-256, SHA-384,
|
||||
* or SHA-1, depending on what is available.
|
||||
*
|
||||
* The risk of collision is considered too small to be a concern; and
|
||||
* the impact of a collision is low (the handshake won't succeed). This
|
||||
* risk is much lower than any transmission error, which would lead to
|
||||
* the same consequences.
|
||||
*
|
||||
* Source and destination arrays msut be disjoint.
|
||||
*/
|
||||
static void
|
||||
mask_id(br_ssl_session_cache_lru *cc,
|
||||
const unsigned char *src, unsigned char *dst)
|
||||
{
|
||||
br_hmac_key_context hkc;
|
||||
br_hmac_context hc;
|
||||
|
||||
memcpy(dst, src, SESSION_ID_LEN);
|
||||
br_hmac_key_init(&hkc, cc->hash, cc->index_key, sizeof cc->index_key);
|
||||
br_hmac_init(&hc, &hkc, SESSION_ID_LEN);
|
||||
br_hmac_update(&hc, src, SESSION_ID_LEN);
|
||||
br_hmac_out(&hc, dst);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a node by ID. Returned value is the node address, or ADDR_NULL if
|
||||
* the node is not found.
|
||||
*
|
||||
* If addr_link is not NULL, then '*addr_link' is set to the address of the
|
||||
* last followed link. If the found node is the root, or if the tree is
|
||||
* empty, then '*addr_link' is set to ADDR_NULL.
|
||||
*/
|
||||
static uint32_t
|
||||
find_node(br_ssl_session_cache_lru *cc, const unsigned char *id,
|
||||
uint32_t *addr_link)
|
||||
{
|
||||
uint32_t x, y;
|
||||
|
||||
x = cc->root;
|
||||
y = ADDR_NULL;
|
||||
while (x != ADDR_NULL) {
|
||||
int r;
|
||||
|
||||
r = memcmp(id, cc->store + x + SESSION_ID_OFF, SESSION_ID_LEN);
|
||||
if (r < 0) {
|
||||
y = x + TREE_LEFT_OFF;
|
||||
x = get_left(cc, x);
|
||||
} else if (r == 0) {
|
||||
if (addr_link != NULL) {
|
||||
*addr_link = y;
|
||||
}
|
||||
return x;
|
||||
} else {
|
||||
y = x + TREE_RIGHT_OFF;
|
||||
x = get_right(cc, x);
|
||||
}
|
||||
}
|
||||
if (addr_link != NULL) {
|
||||
*addr_link = y;
|
||||
}
|
||||
return ADDR_NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* For node x, find its replacement upon removal.
|
||||
*
|
||||
* -- If node x has no child, then this returns ADDR_NULL.
|
||||
* -- Otherwise, if node x has a left child, then the replacement is the
|
||||
* rightmost left-descendent.
|
||||
* -- Otherwise, the replacement is the leftmost right-descendent.
|
||||
*
|
||||
* If a node is returned, then '*al' is set to the address of the field
|
||||
* that points to that node. Otherwise (node x has no child), '*al' is
|
||||
* set to ADDR_NULL.
|
||||
*
|
||||
* Note that the replacement node, when found, is always a descendent
|
||||
* of node 'x', so it cannot be the tree root. Thus, '*al' can be set
|
||||
* to ADDR_NULL only when no node is found and ADDR_NULL is returned.
|
||||
*/
|
||||
static uint32_t
|
||||
find_replacement_node(br_ssl_session_cache_lru *cc, uint32_t x, uint32_t *al)
|
||||
{
|
||||
uint32_t y1, y2;
|
||||
|
||||
y1 = get_left(cc, x);
|
||||
if (y1 != ADDR_NULL) {
|
||||
y2 = x + TREE_LEFT_OFF;
|
||||
for (;;) {
|
||||
uint32_t z;
|
||||
|
||||
z = get_right(cc, y1);
|
||||
if (z == ADDR_NULL) {
|
||||
*al = y2;
|
||||
return y1;
|
||||
}
|
||||
y2 = y1 + TREE_RIGHT_OFF;
|
||||
y1 = z;
|
||||
}
|
||||
}
|
||||
y1 = get_right(cc, x);
|
||||
if (y1 != ADDR_NULL) {
|
||||
y2 = x + TREE_RIGHT_OFF;
|
||||
for (;;) {
|
||||
uint32_t z;
|
||||
|
||||
z = get_left(cc, y1);
|
||||
if (z == ADDR_NULL) {
|
||||
*al = y2;
|
||||
return y1;
|
||||
}
|
||||
y2 = y1 + TREE_LEFT_OFF;
|
||||
y1 = z;
|
||||
}
|
||||
}
|
||||
*al = ADDR_NULL;
|
||||
return ADDR_NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the link at address 'alx' to point to node 'x'. If 'alx' is
|
||||
* ADDR_NULL, then this sets the tree root to 'x'.
|
||||
*/
|
||||
static inline void
|
||||
set_link(br_ssl_session_cache_lru *cc, uint32_t alx, uint32_t x)
|
||||
{
|
||||
if (alx == ADDR_NULL) {
|
||||
cc->root = x;
|
||||
} else {
|
||||
br_enc32be(cc->store + alx, x);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove node 'x' from the tree. This function shall not be called if
|
||||
* node 'x' is not part of the tree.
|
||||
*/
|
||||
static void
|
||||
remove_node(br_ssl_session_cache_lru *cc, uint32_t x)
|
||||
{
|
||||
uint32_t alx, y, aly;
|
||||
|
||||
/*
|
||||
* Removal algorithm:
|
||||
* ------------------
|
||||
*
|
||||
* - If we remove the root, then the tree becomes empty.
|
||||
*
|
||||
* - If the removed node has no child, then we can simply remove
|
||||
* it, with nothing else to do.
|
||||
*
|
||||
* - Otherwise, the removed node must be replaced by either its
|
||||
* rightmost left-descendent, or its leftmost right-descendent.
|
||||
* The replacement node itself must be removed from its current
|
||||
* place. By definition, that replacement node has either no
|
||||
* child, or at most a single child that will replace it in the
|
||||
* tree.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Find node back and its ancestor link. If the node was the
|
||||
* root, then alx is set to ADDR_NULL.
|
||||
*/
|
||||
find_node(cc, cc->store + x + SESSION_ID_OFF, &alx);
|
||||
|
||||
/*
|
||||
* Find replacement node 'y', and 'aly' is set to the address of
|
||||
* the link to that replacement node. If the removed node has no
|
||||
* child, then both 'y' and 'aly' are set to ADDR_NULL.
|
||||
*/
|
||||
y = find_replacement_node(cc, x, &aly);
|
||||
|
||||
if (y != ADDR_NULL) {
|
||||
uint32_t z;
|
||||
|
||||
/*
|
||||
* The unlinked replacement node may have one child (but
|
||||
* not two) that takes its place.
|
||||
*/
|
||||
z = get_left(cc, y);
|
||||
if (z == ADDR_NULL) {
|
||||
z = get_right(cc, y);
|
||||
}
|
||||
set_link(cc, aly, z);
|
||||
|
||||
/*
|
||||
* Link the replacement node in its new place, overwriting
|
||||
* the current link to the node 'x' (which removes 'x').
|
||||
*/
|
||||
set_link(cc, alx, y);
|
||||
|
||||
/*
|
||||
* The replacement node adopts the left and right children
|
||||
* of the removed node. Note that this also works even if
|
||||
* the replacement node was a direct descendent of the
|
||||
* removed node, since we unlinked it previously.
|
||||
*/
|
||||
set_left(cc, y, get_left(cc, x));
|
||||
set_right(cc, y, get_right(cc, x));
|
||||
} else {
|
||||
/*
|
||||
* No replacement, we simply unlink the node 'x'.
|
||||
*/
|
||||
set_link(cc, alx, ADDR_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lru_save(const br_ssl_session_cache_class **ctx,
|
||||
br_ssl_server_context *server_ctx,
|
||||
const br_ssl_session_parameters *params)
|
||||
{
|
||||
br_ssl_session_cache_lru *cc;
|
||||
unsigned char id[SESSION_ID_LEN];
|
||||
uint32_t x, alx;
|
||||
|
||||
cc = (br_ssl_session_cache_lru *)ctx;
|
||||
|
||||
/*
|
||||
* If the buffer is too small, we don't record anything. This
|
||||
* test avoids problems in subsequent code.
|
||||
*/
|
||||
if (cc->store_len < LRU_ENTRY_LEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Upon the first save in a session cache instance, we obtain
|
||||
* a random key for our indexing.
|
||||
*/
|
||||
if (!cc->init_done) {
|
||||
br_hmac_drbg_generate(&server_ctx->eng.rng,
|
||||
cc->index_key, sizeof cc->index_key);
|
||||
cc->hash = br_hmac_drbg_get_hash(&server_ctx->eng.rng);
|
||||
cc->init_done = 1;
|
||||
}
|
||||
mask_id(cc, params->session_id, id);
|
||||
|
||||
/*
|
||||
* Look for the node in the tree. If the same ID is already used,
|
||||
* then reject it. This is a collision event, which should be
|
||||
* exceedingly rare.
|
||||
* Note: we do NOT record the emplacement here, because the
|
||||
* removal of an entry may change the tree topology.
|
||||
*/
|
||||
if (find_node(cc, id, NULL) != ADDR_NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find some room for the new parameters. If the cache is not
|
||||
* full yet, add it to the end of the area and bump the pointer up.
|
||||
* Otherwise, evict the list tail entry. Note that we already
|
||||
* filtered out the case of a ridiculously small buffer that
|
||||
* cannot hold any entry at all; thus, if there is no room for an
|
||||
* extra entry, then the cache cannot be empty.
|
||||
*/
|
||||
if (cc->store_ptr > (cc->store_len - LRU_ENTRY_LEN)) {
|
||||
/*
|
||||
* Evict tail. If the buffer has room for a single entry,
|
||||
* then this may also be the head.
|
||||
*/
|
||||
x = cc->tail;
|
||||
cc->tail = get_prev(cc, x);
|
||||
if (cc->tail == ADDR_NULL) {
|
||||
cc->head = ADDR_NULL;
|
||||
} else {
|
||||
set_next(cc, cc->tail, ADDR_NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the node from the tree.
|
||||
*/
|
||||
remove_node(cc, x);
|
||||
} else {
|
||||
/*
|
||||
* Allocate room for new node.
|
||||
*/
|
||||
x = cc->store_ptr;
|
||||
cc->store_ptr += LRU_ENTRY_LEN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the emplacement for the new node, and link it.
|
||||
*/
|
||||
find_node(cc, id, &alx);
|
||||
set_link(cc, alx, x);
|
||||
set_left(cc, x, ADDR_NULL);
|
||||
set_right(cc, x, ADDR_NULL);
|
||||
|
||||
/*
|
||||
* New entry becomes new list head. It may also become the list
|
||||
* tail if the cache was empty at that point.
|
||||
*/
|
||||
if (cc->head == ADDR_NULL) {
|
||||
cc->tail = x;
|
||||
} else {
|
||||
set_prev(cc, cc->head, x);
|
||||
}
|
||||
set_prev(cc, x, ADDR_NULL);
|
||||
set_next(cc, x, cc->head);
|
||||
cc->head = x;
|
||||
|
||||
/*
|
||||
* Fill data in the entry.
|
||||
*/
|
||||
memcpy(cc->store + x + SESSION_ID_OFF, id, SESSION_ID_LEN);
|
||||
memcpy(cc->store + x + MASTER_SECRET_OFF,
|
||||
params->master_secret, MASTER_SECRET_LEN);
|
||||
br_enc16be(cc->store + x + VERSION_OFF, params->version);
|
||||
br_enc16be(cc->store + x + CIPHER_SUITE_OFF, params->cipher_suite);
|
||||
}
|
||||
|
||||
static int
|
||||
lru_load(const br_ssl_session_cache_class **ctx,
|
||||
br_ssl_server_context *server_ctx,
|
||||
br_ssl_session_parameters *params)
|
||||
{
|
||||
br_ssl_session_cache_lru *cc;
|
||||
unsigned char id[SESSION_ID_LEN];
|
||||
uint32_t x;
|
||||
|
||||
(void)server_ctx;
|
||||
cc = (br_ssl_session_cache_lru *)ctx;
|
||||
if (!cc->init_done) {
|
||||
return 0;
|
||||
}
|
||||
mask_id(cc, params->session_id, id);
|
||||
x = find_node(cc, id, NULL);
|
||||
if (x != ADDR_NULL) {
|
||||
unsigned version;
|
||||
|
||||
version = br_dec16be(cc->store + x + VERSION_OFF);
|
||||
if (version == 0) {
|
||||
/*
|
||||
* Entry is disabled, we pretend we did not find it.
|
||||
* Notably, we don't move it to the front of the
|
||||
* LRU list.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
params->version = version;
|
||||
params->cipher_suite = br_dec16be(
|
||||
cc->store + x + CIPHER_SUITE_OFF);
|
||||
memcpy(params->master_secret,
|
||||
cc->store + x + MASTER_SECRET_OFF,
|
||||
MASTER_SECRET_LEN);
|
||||
if (x != cc->head) {
|
||||
/*
|
||||
* Found node is not at list head, so move
|
||||
* it to the head.
|
||||
*/
|
||||
uint32_t p, n;
|
||||
|
||||
p = get_prev(cc, x);
|
||||
n = get_next(cc, x);
|
||||
set_next(cc, p, n);
|
||||
if (n == ADDR_NULL) {
|
||||
cc->tail = p;
|
||||
} else {
|
||||
set_prev(cc, n, p);
|
||||
}
|
||||
set_prev(cc, cc->head, x);
|
||||
set_next(cc, x, cc->head);
|
||||
set_prev(cc, x, ADDR_NULL);
|
||||
cc->head = x;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const br_ssl_session_cache_class lru_class = {
|
||||
sizeof(br_ssl_session_cache_lru),
|
||||
&lru_save,
|
||||
&lru_load
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_ssl_session_cache_lru_init(br_ssl_session_cache_lru *cc,
|
||||
unsigned char *store, size_t store_len)
|
||||
{
|
||||
cc->vtable = &lru_class;
|
||||
cc->store = store;
|
||||
cc->store_len = store_len;
|
||||
cc->store_ptr = 0;
|
||||
cc->init_done = 0;
|
||||
cc->head = ADDR_NULL;
|
||||
cc->tail = ADDR_NULL;
|
||||
cc->root = ADDR_NULL;
|
||||
}
|
||||
|
||||
/* see bearssl_ssl.h */
|
||||
void br_ssl_session_cache_lru_forget(
|
||||
br_ssl_session_cache_lru *cc, const unsigned char *id)
|
||||
{
|
||||
unsigned char mid[SESSION_ID_LEN];
|
||||
uint32_t addr;
|
||||
|
||||
/*
|
||||
* If the cache is not initialised yet, then it is empty, and
|
||||
* there is nothing to forget.
|
||||
*/
|
||||
if (!cc->init_done) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for the node in the tree. If found, the entry is marked
|
||||
* as "disabled"; it will be reused in due course, as it ages
|
||||
* through the list.
|
||||
*
|
||||
* We do not go through the complex moves of actually releasing
|
||||
* the entry right away because explicitly forgetting sessions
|
||||
* should be a rare event, meant mostly for testing purposes,
|
||||
* so this is not worth the extra code size.
|
||||
*/
|
||||
mask_id(cc, id, mid);
|
||||
addr = find_node(cc, mid, NULL);
|
||||
if (addr != ADDR_NULL) {
|
||||
br_enc16be(cc->store + addr + VERSION_OFF, 0);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue