mirror of
https://github.com/cesanta/mongoose.git
synced 2026-11-07 16:01:30 +00:00
Drop x25519, use p256 only
This commit is contained in:
1 parent
b68da1548b
commit
37f3ed5ba4
87 files changed
+12928
-32874
No files matched your search
+231
-664
@@ -1486,10 +1486,28 @@ struct timeval {
|
||||
#define MG_ENABLE_TCPIP_PRINT_DEBUG_STATS 0
|
||||
#endif
|
||||
|
||||
#ifndef MG_TLS_RECORD_SIZE
|
||||
#define MG_TLS_RECORD_SIZE 16384 // Max plaintext per sent TLS record, builtin
|
||||
#endif
|
||||
|
||||
#ifndef MG_ENABLE_CHACHA20
|
||||
#define MG_ENABLE_CHACHA20 1 // When set to 0, GCM is used. For MG_TLS_BUILTIN
|
||||
#endif
|
||||
|
||||
// P-256 implementation, for MG_TLS_BUILTIN
|
||||
#define MG_P256_LENNGREN 1 // Cortex-M4/M7/M33 asm, see tls_p256_cortex.c
|
||||
#define MG_P256_BEAR 3 // Portable C, BearSSL, see tls_p256.c
|
||||
|
||||
#ifndef MG_P256
|
||||
#if defined(__GNUC__) && defined(__ARM_ARCH_PROFILE) && \
|
||||
__ARM_ARCH_PROFILE == 'M' && defined(__ARM_FEATURE_DSP) && \
|
||||
!defined(__ARM_BIG_ENDIAN)
|
||||
#define MG_P256 MG_P256_LENNGREN // Cortex-M with DSP: M4, M7, M33, M55, M85
|
||||
#else
|
||||
#define MG_P256 MG_P256_BEAR
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MG_ENABLE_HEALTH
|
||||
#define MG_ENABLE_HEALTH 0
|
||||
#endif
|
||||
@@ -2964,26 +2982,13 @@ void mg_tls_ctx_free(struct mg_mgr *);
|
||||
#if MG_TLS == MG_TLS_BUILTIN
|
||||
// Extracts a 32-byte P-256 private scalar from EC PRIVATE KEY or PKCS#8 PRIVATE
|
||||
// KEY input. Accepts PEM or DER. Returns key size, or 0 on error.
|
||||
size_t mg_uecc_parse_private_key(struct mg_str key, uint8_t *buf, size_t len);
|
||||
size_t mg_p256_parse_private_key(struct mg_str key, uint8_t *buf, size_t len);
|
||||
#endif
|
||||
|
||||
// Low-level IO primitives used by TLS layer
|
||||
enum { MG_IO_ERR = -1, MG_IO_WAIT = -2 };
|
||||
long mg_io_send(struct mg_connection *c, const void *buf, size_t len);
|
||||
long mg_io_recv(struct mg_connection *c, void *buf, size_t len);
|
||||
#ifndef TLS_X15519_H
|
||||
#define TLS_X15519_H
|
||||
|
||||
|
||||
|
||||
#define X25519_BYTES 32
|
||||
extern const uint8_t X25519_BASE_POINT[X25519_BYTES];
|
||||
|
||||
int mg_tls_x25519(uint8_t out[X25519_BYTES], const uint8_t scalar[X25519_BYTES],
|
||||
const uint8_t x1[X25519_BYTES], int clamp);
|
||||
|
||||
|
||||
#endif /* TLS_X15519_H */
|
||||
/******************************************************************************
|
||||
*
|
||||
* THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL
|
||||
@@ -3052,665 +3057,227 @@ int mg_aes_gcm_decrypt(unsigned char *output, const unsigned char *input,
|
||||
#endif /* TLS_AES128_H */
|
||||
|
||||
// End of aes128 PD
|
||||
// P-256 API, mg_p256_*(), used by built-in TLS, JWT and OTA. Implemented by
|
||||
// BearSSL code below (MG_P256=MG_P256_BEAR) or tls_p256_cortex.c (LENNGREN)
|
||||
// BearSSL code: https://bearssl.org commit 7bea48e. Shared bignum and ECDSA
|
||||
// code is always compiled, it is also used by P-384, see tls_p384.c
|
||||
//
|
||||
// Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
// 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.
|
||||
//
|
||||
// Mongoose changes: br_ / BR_ names are prefixed with mg_ / MG_, as are the
|
||||
// constant-time helpers from inner.h (NOT, MUX, EQ, ...). Structs are not
|
||||
// typedef-ed. ECDSA signing takes the caller's k instead of HMAC-DRBG, k is
|
||||
// computed by mg_p256_sign() (RFC 6979). ECDSA functions take the curve id and
|
||||
// public key directly
|
||||
|
||||
|
||||
|
||||
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_H_
|
||||
#define _UECC_H_
|
||||
|
||||
/* Platform selection options.
|
||||
If MG_UECC_PLATFORM is not defined, the code will try to guess it based on
|
||||
compiler macros. Possible values for MG_UECC_PLATFORM are defined below: */
|
||||
#define mg_uecc_arch_other 0
|
||||
#define mg_uecc_x86 1
|
||||
#define mg_uecc_x86_64 2
|
||||
#define mg_uecc_arm 3
|
||||
#define mg_uecc_arm_thumb 4
|
||||
#define mg_uecc_arm_thumb2 5
|
||||
#define mg_uecc_arm64 6
|
||||
#define mg_uecc_avr 7
|
||||
|
||||
/* If desired, you can define MG_UECC_WORD_SIZE as appropriate for your platform
|
||||
(1, 4, or 8 bytes). If MG_UECC_WORD_SIZE is not explicitly defined then it will
|
||||
be automatically set based on your platform. */
|
||||
|
||||
/* Optimization level; trade speed for code size.
|
||||
Larger values produce code that is faster but larger.
|
||||
Currently supported values are 0 - 4; 0 is unusably slow for most
|
||||
applications. Optimization level 4 currently only has an effect ARM platforms
|
||||
where more than one curve is enabled. */
|
||||
#ifndef MG_UECC_OPTIMIZATION_LEVEL
|
||||
#define MG_UECC_OPTIMIZATION_LEVEL 2
|
||||
#endif
|
||||
#if MG_TLS == MG_TLS_BUILTIN || defined(MG_OTA_PUBLIC_KEY)
|
||||
|
||||
/* MG_UECC_SQUARE_FUNC - If enabled (defined as nonzero), this will cause a
|
||||
specific function to be used for (scalar) squaring instead of the generic
|
||||
multiplication function. This can make things faster somewhat faster, but
|
||||
increases the code size. */
|
||||
#ifndef MG_UECC_SQUARE_FUNC
|
||||
#define MG_UECC_SQUARE_FUNC 0
|
||||
#endif
|
||||
#define MG_BR_EC_secp256r1 23 // Curve IDs, same as TLS named groups
|
||||
#define MG_BR_EC_secp384r1 24
|
||||
#define MG_BR_MAX_EC_SIZE 384 // Largest supported curve, bits
|
||||
|
||||
/* MG_UECC_VLI_NATIVE_LITTLE_ENDIAN - If enabled (defined as nonzero), this will
|
||||
switch to native little-endian format for *all* arrays passed in and out of the
|
||||
public API. This includes public and private keys, shared secrets, signatures
|
||||
and message hashes. Using this switch reduces the amount of call stack memory
|
||||
used by uECC, since less intermediate translations are required. Note that this
|
||||
will *only* work on native little-endian processors and it will treat the
|
||||
uint8_t arrays passed into the public API as word arrays, therefore requiring
|
||||
the provided byte arrays to be word aligned on architectures that do not support
|
||||
unaligned accesses. IMPORTANT: Keys and signatures generated with
|
||||
MG_UECC_VLI_NATIVE_LITTLE_ENDIAN=1 are incompatible with keys and signatures
|
||||
generated with MG_UECC_VLI_NATIVE_LITTLE_ENDIAN=0; all parties must use the same
|
||||
endianness. */
|
||||
#ifndef MG_UECC_VLI_NATIVE_LITTLE_ENDIAN
|
||||
#define MG_UECC_VLI_NATIVE_LITTLE_ENDIAN 0
|
||||
#endif
|
||||
// From BearSSL inc/bearssl_ec.h: an EC implementation
|
||||
struct mg_br_ec_impl {
|
||||
uint32_t supported_curves; // Bit mask of curve IDs
|
||||
const unsigned char *(*generator)(int curve, size_t *len);
|
||||
const unsigned char *(*order)(int curve, size_t *len);
|
||||
size_t (*xoff)(int curve, size_t *len);
|
||||
uint32_t (*mul)(unsigned char *G, size_t Glen, const unsigned char *x,
|
||||
size_t xlen, int curve);
|
||||
size_t (*mulgen)(unsigned char *R, const unsigned char *x, size_t xlen,
|
||||
int curve);
|
||||
uint32_t (*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);
|
||||
};
|
||||
|
||||
/* Curve support selection. Set to 0 to remove that curve. */
|
||||
#ifndef MG_UECC_SUPPORTS_secp160r1
|
||||
#define MG_UECC_SUPPORTS_secp160r1 0
|
||||
#endif
|
||||
#ifndef MG_UECC_SUPPORTS_secp192r1
|
||||
#define MG_UECC_SUPPORTS_secp192r1 0
|
||||
#endif
|
||||
#ifndef MG_UECC_SUPPORTS_secp224r1
|
||||
#define MG_UECC_SUPPORTS_secp224r1 0
|
||||
#endif
|
||||
#ifndef MG_UECC_SUPPORTS_secp256r1
|
||||
#define MG_UECC_SUPPORTS_secp256r1 1
|
||||
#endif
|
||||
#ifndef MG_UECC_SUPPORTS_secp256k1
|
||||
#define MG_UECC_SUPPORTS_secp256k1 0
|
||||
#endif
|
||||
#ifndef MG_UECC_SUPPORTS_secp384r1
|
||||
#define MG_UECC_SUPPORTS_secp384r1 1
|
||||
#endif
|
||||
|
||||
/* Specifies whether compressed point format is supported.
|
||||
Set to 0 to disable point compression/decompression functions. */
|
||||
#ifndef MG_UECC_SUPPORT_COMPRESSED_POINT
|
||||
#define MG_UECC_SUPPORT_COMPRESSED_POINT 1
|
||||
#endif
|
||||
|
||||
struct MG_UECC_Curve_t;
|
||||
typedef const struct MG_UECC_Curve_t *MG_UECC_Curve;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if MG_UECC_SUPPORTS_secp160r1
|
||||
MG_UECC_Curve mg_uecc_secp160r1(void);
|
||||
#endif
|
||||
#if MG_UECC_SUPPORTS_secp192r1
|
||||
MG_UECC_Curve mg_uecc_secp192r1(void);
|
||||
#endif
|
||||
#if MG_UECC_SUPPORTS_secp224r1
|
||||
MG_UECC_Curve mg_uecc_secp224r1(void);
|
||||
#endif
|
||||
#if MG_UECC_SUPPORTS_secp256r1
|
||||
MG_UECC_Curve mg_uecc_secp256r1(void);
|
||||
#endif
|
||||
#if MG_UECC_SUPPORTS_secp256k1
|
||||
MG_UECC_Curve mg_uecc_secp256k1(void);
|
||||
#endif
|
||||
#if MG_UECC_SUPPORTS_secp384r1
|
||||
MG_UECC_Curve mg_uecc_secp384r1(void);
|
||||
#endif
|
||||
|
||||
/* MG_UECC_RNG_Function type
|
||||
The RNG function should fill 'size' random bytes into 'dest'. It should return 1
|
||||
if 'dest' was filled with random data, or 0 if the random data could not be
|
||||
generated. The filled-in values should be either truly random, or from a
|
||||
cryptographically-secure PRNG.
|
||||
|
||||
A correctly functioning RNG is required before calling mg_uecc_make_key() or
|
||||
mg_uecc_sign().
|
||||
|
||||
Setting a correctly functioning RNG function improves the resistance to
|
||||
side-channel attacks for mg_uecc_shared_secret() and
|
||||
mg_uecc_sign_deterministic().
|
||||
*/
|
||||
typedef int (*MG_UECC_RNG_Function)(uint8_t *dest, unsigned size);
|
||||
|
||||
// Mongoose: mg_uecc_make_key() and mg_uecc_sign() use mg_random() when no
|
||||
// explicit uECC RNG is installed. If mg_random() cannot provide a strong source,
|
||||
// those operations fail. Deterministic signing works without RNG, but only an
|
||||
// explicit uECC RNG enables its optional side-channel blinding.
|
||||
|
||||
/* mg_uecc_set_rng() function.
|
||||
Set the function that will be used to generate random bytes. The RNG function
|
||||
should return 1 if the random data was generated, or 0 if the random data could
|
||||
not be generated.
|
||||
|
||||
Mongoose: this overrides the default mg_random() fallback used by
|
||||
mg_uecc_make_key() and mg_uecc_sign(). Do not call mg_uecc_set_rng() unless the
|
||||
application must provide its own cryptographic RNG.
|
||||
|
||||
Inputs:
|
||||
rng_function - The function that will be used to generate random bytes.
|
||||
*/
|
||||
void mg_uecc_set_rng(MG_UECC_RNG_Function rng_function);
|
||||
|
||||
/* mg_uecc_get_rng() function.
|
||||
|
||||
Returns the function that will be used to generate random bytes.
|
||||
*/
|
||||
MG_UECC_RNG_Function mg_uecc_get_rng(void);
|
||||
|
||||
/* mg_uecc_curve_private_key_size() function.
|
||||
|
||||
Returns the size of a private key for the curve in bytes.
|
||||
*/
|
||||
int mg_uecc_curve_private_key_size(MG_UECC_Curve curve);
|
||||
|
||||
/* mg_uecc_curve_public_key_size() function.
|
||||
|
||||
Returns the size of a public key for the curve in bytes.
|
||||
*/
|
||||
int mg_uecc_curve_public_key_size(MG_UECC_Curve curve);
|
||||
|
||||
/* mg_uecc_make_key() function.
|
||||
Create a public/private key pair.
|
||||
|
||||
Outputs:
|
||||
public_key - Will be filled in with the public key. Must be at least 2 *
|
||||
the curve size (in bytes) long. For example, if the curve is secp256r1,
|
||||
public_key must be 64 bytes long. private_key - Will be filled in with the
|
||||
private key. Must be as long as the curve order; this is typically the same as
|
||||
the curve size, except for secp160r1. For example, if the curve is secp256r1,
|
||||
private_key must be 32 bytes long.
|
||||
|
||||
For secp160r1, private_key must be 21 bytes long! Note that
|
||||
the first byte will almost always be 0 (there is about a 1 in 2^80 chance of it
|
||||
being non-zero).
|
||||
|
||||
Returns 1 if the key pair was generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int mg_uecc_make_key(uint8_t *public_key, uint8_t *private_key,
|
||||
MG_UECC_Curve curve);
|
||||
|
||||
/* mg_uecc_shared_secret() function.
|
||||
Compute a shared secret given your secret key and someone else's public key. If
|
||||
the public key is not from a trusted source and has not been previously
|
||||
verified, you should verify it first using mg_uecc_valid_public_key(). Note: It
|
||||
is recommended that you hash the result of mg_uecc_shared_secret() before using
|
||||
it for symmetric encryption or HMAC.
|
||||
|
||||
Inputs:
|
||||
public_key - The public key of the remote party.
|
||||
private_key - Your private key.
|
||||
|
||||
Outputs:
|
||||
secret - Will be filled in with the shared secret value. Must be the same
|
||||
size as the curve size; for example, if the curve is secp256r1, secret must be
|
||||
32 bytes long.
|
||||
|
||||
Returns 1 if the shared secret was generated successfully, 0 if an error
|
||||
occurred.
|
||||
*/
|
||||
int mg_uecc_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
|
||||
uint8_t *secret, MG_UECC_Curve curve);
|
||||
|
||||
#if MG_UECC_SUPPORT_COMPRESSED_POINT
|
||||
/* mg_uecc_compress() function.
|
||||
Compress a public key.
|
||||
|
||||
Inputs:
|
||||
public_key - The public key to compress.
|
||||
|
||||
Outputs:
|
||||
compressed - Will be filled in with the compressed public key. Must be at
|
||||
least (curve size + 1) bytes long; for example, if the curve is secp256r1,
|
||||
compressed must be 33 bytes long.
|
||||
*/
|
||||
void mg_uecc_compress(const uint8_t *public_key, uint8_t *compressed,
|
||||
MG_UECC_Curve curve);
|
||||
|
||||
/* mg_uecc_decompress() function.
|
||||
Decompress a compressed public key.
|
||||
|
||||
Inputs:
|
||||
compressed - The compressed public key.
|
||||
|
||||
Outputs:
|
||||
public_key - Will be filled in with the decompressed public key.
|
||||
*/
|
||||
void mg_uecc_decompress(const uint8_t *compressed, uint8_t *public_key,
|
||||
MG_UECC_Curve curve);
|
||||
#endif /* MG_UECC_SUPPORT_COMPRESSED_POINT */
|
||||
|
||||
/* mg_uecc_valid_public_key() function.
|
||||
Check to see if a public key is valid.
|
||||
|
||||
Note that you are not required to check for a valid public key before using any
|
||||
other uECC functions. However, you may wish to avoid spending CPU time computing
|
||||
a shared secret or verifying a signature using an invalid public key.
|
||||
|
||||
Inputs:
|
||||
public_key - The public key to check.
|
||||
|
||||
Returns 1 if the public key is valid, 0 if it is invalid.
|
||||
*/
|
||||
int mg_uecc_valid_public_key(const uint8_t *public_key, MG_UECC_Curve curve);
|
||||
|
||||
/* mg_uecc_compute_public_key() function.
|
||||
Compute the corresponding public key for a private key.
|
||||
|
||||
Inputs:
|
||||
private_key - The private key to compute the public key for
|
||||
|
||||
Outputs:
|
||||
public_key - Will be filled in with the corresponding public key
|
||||
|
||||
Returns 1 if the key was computed successfully, 0 if an error occurred.
|
||||
*/
|
||||
int mg_uecc_compute_public_key(const uint8_t *private_key, uint8_t *public_key,
|
||||
MG_UECC_Curve curve);
|
||||
|
||||
/* mg_uecc_sign() function.
|
||||
Generate an ECDSA signature for a given hash value.
|
||||
|
||||
Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and
|
||||
pass it in to this function along with your private key.
|
||||
|
||||
Inputs:
|
||||
private_key - Your private key.
|
||||
message_hash - The hash of the message to sign.
|
||||
hash_size - The size of message_hash in bytes.
|
||||
|
||||
Outputs:
|
||||
signature - Will be filled in with the signature value. Must be at least 2 *
|
||||
curve size long. For example, if the curve is secp256r1, signature must be 64
|
||||
bytes long.
|
||||
|
||||
Returns 1 if the signature generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int mg_uecc_sign(const uint8_t *private_key, const uint8_t *message_hash,
|
||||
unsigned hash_size, uint8_t *signature, MG_UECC_Curve curve);
|
||||
|
||||
/* MG_UECC_HashContext structure.
|
||||
This is used to pass in an arbitrary hash function to
|
||||
mg_uecc_sign_deterministic(). The structure will be used for multiple hash
|
||||
computations; each time a new hash is computed, init_hash() will be called,
|
||||
followed by one or more calls to update_hash(), and finally a call to
|
||||
finish_hash() to produce the resulting hash.
|
||||
|
||||
The intention is that you will create a structure that includes
|
||||
MG_UECC_HashContext followed by any hash-specific data. For example:
|
||||
|
||||
typedef struct SHA256_HashContext {
|
||||
MG_UECC_HashContext uECC;
|
||||
SHA256_CTX ctx;
|
||||
} SHA256_HashContext;
|
||||
|
||||
void init_SHA256(MG_UECC_HashContext *base) {
|
||||
SHA256_HashContext *context = (SHA256_HashContext *)base;
|
||||
SHA256_Init(&context->ctx);
|
||||
// From BearSSL src/inner.h: constant-time helpers
|
||||
static inline uint32_t MG_BR_NOT(uint32_t ctl) {
|
||||
return ctl ^ 1;
|
||||
}
|
||||
static inline uint32_t MG_BR_MUX(uint32_t ctl, uint32_t x, uint32_t y) {
|
||||
return y ^ (-ctl & (x ^ y));
|
||||
}
|
||||
static inline uint32_t MG_BR_EQ(uint32_t x, uint32_t y) {
|
||||
uint32_t q = x ^ y;
|
||||
return MG_BR_NOT((q | -q) >> 31);
|
||||
}
|
||||
static inline uint32_t MG_BR_NEQ(uint32_t x, uint32_t y) {
|
||||
uint32_t q = x ^ y;
|
||||
return (q | -q) >> 31;
|
||||
}
|
||||
static inline uint32_t MG_BR_GT(uint32_t x, uint32_t y) {
|
||||
uint32_t z = y - x;
|
||||
return (z ^ ((x ^ y) & (x ^ z))) >> 31;
|
||||
}
|
||||
#define MG_BR_GE(x, y) MG_BR_NOT(MG_BR_GT(y, x))
|
||||
#define MG_BR_LT(x, y) MG_BR_GT(y, x)
|
||||
static inline int32_t MG_BR_CMP(uint32_t x, uint32_t y) {
|
||||
return (int32_t) MG_BR_GT(x, y) | -(int32_t) MG_BR_GT(y, x);
|
||||
}
|
||||
static inline uint32_t MG_BR_BIT_LENGTH(uint32_t x) {
|
||||
uint32_t k, c;
|
||||
k = MG_BR_NEQ(x, 0);
|
||||
c = MG_BR_GT(x, 0xFFFF), x = MG_BR_MUX(c, x >> 16, x), k += c << 4;
|
||||
c = MG_BR_GT(x, 0x00FF), x = MG_BR_MUX(c, x >> 8, x), k += c << 3;
|
||||
c = MG_BR_GT(x, 0x000F), x = MG_BR_MUX(c, x >> 4, x), k += c << 2;
|
||||
c = MG_BR_GT(x, 0x0003), x = MG_BR_MUX(c, x >> 2, x), k += c << 1;
|
||||
k += MG_BR_GT(x, 0x0001);
|
||||
return k;
|
||||
}
|
||||
#define MG_BR_MUL31(x, y) ((uint64_t) (x) * (uint64_t) (y))
|
||||
#define MG_BR_MUL31_lo(x, y) \
|
||||
(((uint32_t) (x) * (uint32_t) (y)) & (uint32_t) 0x7FFFFFFF)
|
||||
#define MG_BR_CCOPY mg_br_ccopy
|
||||
void mg_br_ccopy(uint32_t ctl, void *dst, const void *src, size_t len);
|
||||
uint32_t mg_br_divrem(uint32_t hi, uint32_t lo, uint32_t d, uint32_t *r);
|
||||
static inline uint32_t mg_br_rem(uint32_t hi, uint32_t lo, uint32_t d) {
|
||||
uint32_t r;
|
||||
mg_br_divrem(hi, lo, d, &r);
|
||||
return r;
|
||||
}
|
||||
static inline uint32_t mg_br_div(uint32_t hi, uint32_t lo, uint32_t d) {
|
||||
uint32_t r;
|
||||
return mg_br_divrem(hi, lo, d, &r);
|
||||
}
|
||||
static inline void mg_br_enc32be(void *dst, uint32_t x) {
|
||||
unsigned char *buf = (unsigned char *) dst;
|
||||
buf[0] = (unsigned char) (x >> 24), buf[1] = (unsigned char) (x >> 16);
|
||||
buf[2] = (unsigned char) (x >> 8), buf[3] = (unsigned char) x;
|
||||
}
|
||||
static inline void mg_br_i31_zero(uint32_t *x, uint32_t bit_len) {
|
||||
*x++ = bit_len;
|
||||
memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x);
|
||||
}
|
||||
|
||||
void update_SHA256(MG_UECC_HashContext *base,
|
||||
const uint8_t *message,
|
||||
unsigned message_size) {
|
||||
SHA256_HashContext *context = (SHA256_HashContext *)base;
|
||||
SHA256_Update(&context->ctx, message, message_size);
|
||||
}
|
||||
|
||||
void finish_SHA256(MG_UECC_HashContext *base, uint8_t *hash_result) {
|
||||
SHA256_HashContext *context = (SHA256_HashContext *)base;
|
||||
SHA256_Final(hash_result, &context->ctx);
|
||||
}
|
||||
|
||||
... when signing ...
|
||||
{
|
||||
uint8_t tmp[32 + 32 + 64];
|
||||
SHA256_HashContext ctx = {{&init_SHA256, &update_SHA256, &finish_SHA256, 64,
|
||||
32, tmp}}; mg_uecc_sign_deterministic(key, message_hash, &ctx.uECC, signature);
|
||||
}
|
||||
*/
|
||||
typedef struct MG_UECC_HashContext {
|
||||
void (*init_hash)(const struct MG_UECC_HashContext *context);
|
||||
void (*update_hash)(const struct MG_UECC_HashContext *context,
|
||||
const uint8_t *message, unsigned message_size);
|
||||
void (*finish_hash)(const struct MG_UECC_HashContext *context,
|
||||
uint8_t *hash_result);
|
||||
unsigned
|
||||
block_size; /* Hash function block size in bytes, eg 64 for SHA-256. */
|
||||
unsigned
|
||||
result_size; /* Hash function result size in bytes, eg 32 for SHA-256. */
|
||||
uint8_t *tmp; /* Must point to a buffer of at least (2 * result_size +
|
||||
block_size) bytes. */
|
||||
} MG_UECC_HashContext;
|
||||
|
||||
/* mg_uecc_sign_deterministic() function.
|
||||
Generate an ECDSA signature for a given hash value, using a deterministic
|
||||
algorithm (see RFC 6979). You do not need to set the RNG using mg_uecc_set_rng()
|
||||
before calling this function; however, if the RNG is defined it will improve
|
||||
resistance to side-channel attacks.
|
||||
|
||||
Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and
|
||||
pass it to this function along with your private key and a hash context. Note
|
||||
that the message_hash does not need to be computed with the same hash function
|
||||
used by hash_context.
|
||||
|
||||
Inputs:
|
||||
private_key - Your private key.
|
||||
message_hash - The hash of the message to sign.
|
||||
hash_size - The size of message_hash in bytes.
|
||||
hash_context - A hash context to use.
|
||||
|
||||
Outputs:
|
||||
signature - Will be filled in with the signature value.
|
||||
|
||||
Returns 1 if the signature generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int mg_uecc_sign_deterministic(const uint8_t *private_key,
|
||||
const uint8_t *message_hash, unsigned hash_size,
|
||||
const MG_UECC_HashContext *hash_context,
|
||||
uint8_t *signature, MG_UECC_Curve curve);
|
||||
|
||||
/* mg_uecc_verify() function.
|
||||
Verify an ECDSA signature.
|
||||
|
||||
Usage: Compute the hash of the signed data using the same hash as the signer and
|
||||
pass it to this function along with the signer's public key and the signature
|
||||
values (r and s).
|
||||
|
||||
Inputs:
|
||||
public_key - The signer's public key.
|
||||
message_hash - The hash of the signed data.
|
||||
hash_size - The size of message_hash in bytes.
|
||||
signature - The signature value.
|
||||
|
||||
Returns 1 if the signature is valid, 0 if it is invalid.
|
||||
*/
|
||||
int mg_uecc_verify(const uint8_t *public_key, const uint8_t *message_hash,
|
||||
unsigned hash_size, const uint8_t *signature,
|
||||
MG_UECC_Curve curve);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _UECC_H_ */
|
||||
|
||||
/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_TYPES_H_
|
||||
#define _UECC_TYPES_H_
|
||||
|
||||
#ifndef MG_UECC_PLATFORM
|
||||
#if defined(__AVR__) && __AVR__
|
||||
#define MG_UECC_PLATFORM mg_uecc_avr
|
||||
#elif defined(__thumb2__) || \
|
||||
defined(_M_ARMT) /* I think MSVC only supports Thumb-2 targets */
|
||||
#define MG_UECC_PLATFORM mg_uecc_arm_thumb2
|
||||
#elif defined(__thumb__)
|
||||
#define MG_UECC_PLATFORM mg_uecc_arm_thumb
|
||||
#elif defined(__arm__) || defined(_M_ARM)
|
||||
#define MG_UECC_PLATFORM mg_uecc_arm
|
||||
#elif defined(__aarch64__)
|
||||
#define MG_UECC_PLATFORM mg_uecc_arm64
|
||||
#elif defined(__i386__) || defined(_M_IX86) || defined(_X86_) || \
|
||||
defined(__I86__)
|
||||
#define MG_UECC_PLATFORM mg_uecc_x86
|
||||
#elif defined(__amd64__) || defined(_M_X64)
|
||||
#define MG_UECC_PLATFORM mg_uecc_x86_64
|
||||
#else
|
||||
#define MG_UECC_PLATFORM mg_uecc_arch_other
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MG_UECC_ARM_USE_UMAAL
|
||||
#if (MG_UECC_PLATFORM == mg_uecc_arm) && (__ARM_ARCH >= 6)
|
||||
#define MG_UECC_ARM_USE_UMAAL 1
|
||||
#elif (MG_UECC_PLATFORM == mg_uecc_arm_thumb2) && (__ARM_ARCH >= 6) && \
|
||||
(!defined(__ARM_ARCH_7M__) || !__ARM_ARCH_7M__)
|
||||
#define MG_UECC_ARM_USE_UMAAL 1
|
||||
#else
|
||||
#define MG_UECC_ARM_USE_UMAAL 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MG_UECC_WORD_SIZE
|
||||
#if MG_UECC_PLATFORM == mg_uecc_avr
|
||||
#define MG_UECC_WORD_SIZE 1
|
||||
#elif (MG_UECC_PLATFORM == mg_uecc_x86_64 || MG_UECC_PLATFORM == mg_uecc_arm64)
|
||||
#define MG_UECC_WORD_SIZE 8
|
||||
#else
|
||||
#define MG_UECC_WORD_SIZE 4
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (MG_UECC_WORD_SIZE != 1) && (MG_UECC_WORD_SIZE != 4) && \
|
||||
(MG_UECC_WORD_SIZE != 8)
|
||||
#error "Unsupported value for MG_UECC_WORD_SIZE"
|
||||
#endif
|
||||
|
||||
#if ((MG_UECC_PLATFORM == mg_uecc_avr) && (MG_UECC_WORD_SIZE != 1))
|
||||
#pragma message("MG_UECC_WORD_SIZE must be 1 for AVR")
|
||||
#undef MG_UECC_WORD_SIZE
|
||||
#define MG_UECC_WORD_SIZE 1
|
||||
#endif
|
||||
|
||||
#if ((MG_UECC_PLATFORM == mg_uecc_arm || \
|
||||
MG_UECC_PLATFORM == mg_uecc_arm_thumb || \
|
||||
MG_UECC_PLATFORM == mg_uecc_arm_thumb2) && \
|
||||
(MG_UECC_WORD_SIZE != 4))
|
||||
#pragma message("MG_UECC_WORD_SIZE must be 4 for ARM")
|
||||
#undef MG_UECC_WORD_SIZE
|
||||
#define MG_UECC_WORD_SIZE 4
|
||||
#endif
|
||||
|
||||
typedef int8_t wordcount_t;
|
||||
typedef int16_t bitcount_t;
|
||||
typedef int8_t cmpresult_t;
|
||||
|
||||
#if (MG_UECC_WORD_SIZE == 1)
|
||||
|
||||
typedef uint8_t mg_uecc_word_t;
|
||||
typedef uint16_t mg_uecc_dword_t;
|
||||
|
||||
#define HIGH_BIT_SET 0x80
|
||||
#define MG_UECC_WORD_BITS 8
|
||||
#define MG_UECC_WORD_BITS_SHIFT 3
|
||||
#define MG_UECC_WORD_BITS_MASK 0x07
|
||||
|
||||
#elif (MG_UECC_WORD_SIZE == 4)
|
||||
|
||||
typedef uint32_t mg_uecc_word_t;
|
||||
typedef uint64_t mg_uecc_dword_t;
|
||||
|
||||
#define HIGH_BIT_SET 0x80000000
|
||||
#define MG_UECC_WORD_BITS 32
|
||||
#define MG_UECC_WORD_BITS_SHIFT 5
|
||||
#define MG_UECC_WORD_BITS_MASK 0x01F
|
||||
|
||||
#elif (MG_UECC_WORD_SIZE == 8)
|
||||
|
||||
typedef uint64_t mg_uecc_word_t;
|
||||
|
||||
#define HIGH_BIT_SET 0x8000000000000000U
|
||||
#define MG_UECC_WORD_BITS 64
|
||||
#define MG_UECC_WORD_BITS_SHIFT 6
|
||||
#define MG_UECC_WORD_BITS_MASK 0x03F
|
||||
|
||||
#endif /* MG_UECC_WORD_SIZE */
|
||||
|
||||
#endif /* _UECC_TYPES_H_ */
|
||||
|
||||
/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_VLI_H_
|
||||
#define _UECC_VLI_H_
|
||||
|
||||
//
|
||||
//
|
||||
|
||||
/* Functions for raw large-integer manipulation. These are only available
|
||||
if uECC.c is compiled with MG_UECC_ENABLE_VLI_API defined to 1. */
|
||||
#ifndef MG_UECC_ENABLE_VLI_API
|
||||
#define MG_UECC_ENABLE_VLI_API 0
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if MG_UECC_ENABLE_VLI_API
|
||||
|
||||
void mg_uecc_vli_clear(mg_uecc_word_t *vli, wordcount_t num_words);
|
||||
|
||||
/* Constant-time comparison to zero - secure way to compare long integers */
|
||||
/* Returns 1 if vli == 0, 0 otherwise. */
|
||||
mg_uecc_word_t mg_uecc_vli_isZero(const mg_uecc_word_t *vli,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Returns nonzero if bit 'bit' of vli is set. */
|
||||
mg_uecc_word_t mg_uecc_vli_testBit(const mg_uecc_word_t *vli, bitcount_t bit);
|
||||
|
||||
/* Counts the number of bits required to represent vli. */
|
||||
bitcount_t mg_uecc_vli_numBits(const mg_uecc_word_t *vli,
|
||||
const wordcount_t max_words);
|
||||
|
||||
/* Sets dest = src. */
|
||||
void mg_uecc_vli_set(mg_uecc_word_t *dest, const mg_uecc_word_t *src,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Constant-time comparison function - secure way to compare long integers */
|
||||
/* Returns one if left == right, zero otherwise */
|
||||
mg_uecc_word_t mg_uecc_vli_equal(const mg_uecc_word_t *left,
|
||||
const mg_uecc_word_t *right,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Constant-time comparison function - secure way to compare long integers */
|
||||
/* Returns sign of left - right, in constant time. */
|
||||
cmpresult_t mg_uecc_vli_cmp(const mg_uecc_word_t *left,
|
||||
const mg_uecc_word_t *right, wordcount_t num_words);
|
||||
|
||||
/* Computes vli = vli >> 1. */
|
||||
void mg_uecc_vli_rshift1(mg_uecc_word_t *vli, wordcount_t num_words);
|
||||
|
||||
/* Computes result = left + right, returning carry. Can modify in place. */
|
||||
mg_uecc_word_t mg_uecc_vli_add(mg_uecc_word_t *result,
|
||||
const mg_uecc_word_t *left,
|
||||
const mg_uecc_word_t *right,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = left - right, returning borrow. Can modify in place. */
|
||||
mg_uecc_word_t mg_uecc_vli_sub(mg_uecc_word_t *result,
|
||||
const mg_uecc_word_t *left,
|
||||
const mg_uecc_word_t *right,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = left * right. Result must be 2 * num_words long. */
|
||||
void mg_uecc_vli_mult(mg_uecc_word_t *result, const mg_uecc_word_t *left,
|
||||
const mg_uecc_word_t *right, wordcount_t num_words);
|
||||
|
||||
/* Computes result = left^2. Result must be 2 * num_words long. */
|
||||
void mg_uecc_vli_square(mg_uecc_word_t *result, const mg_uecc_word_t *left,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = (left + right) % mod.
|
||||
Assumes that left < mod and right < mod, and that result does not overlap
|
||||
mod. */
|
||||
void mg_uecc_vli_modAdd(mg_uecc_word_t *result, const mg_uecc_word_t *left,
|
||||
const mg_uecc_word_t *right, const mg_uecc_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = (left - right) % mod.
|
||||
Assumes that left < mod and right < mod, and that result does not overlap
|
||||
mod. */
|
||||
void mg_uecc_vli_modSub(mg_uecc_word_t *result, const mg_uecc_word_t *left,
|
||||
const mg_uecc_word_t *right, const mg_uecc_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = product % mod, where product is 2N words long.
|
||||
Currently only designed to work for mod == curve->p or curve_n. */
|
||||
void mg_uecc_vli_mmod(mg_uecc_word_t *result, mg_uecc_word_t *product,
|
||||
const mg_uecc_word_t *mod, wordcount_t num_words);
|
||||
|
||||
/* Calculates result = product (mod curve->p), where product is up to
|
||||
2 * curve->num_words long. */
|
||||
void mg_uecc_vli_mmod_fast(mg_uecc_word_t *result, mg_uecc_word_t *product,
|
||||
MG_UECC_Curve curve);
|
||||
|
||||
/* Computes result = (left * right) % mod.
|
||||
Currently only designed to work for mod == curve->p or curve_n. */
|
||||
void mg_uecc_vli_modMult(mg_uecc_word_t *result, const mg_uecc_word_t *left,
|
||||
const mg_uecc_word_t *right, const mg_uecc_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = (left * right) % curve->p. */
|
||||
void mg_uecc_vli_modMult_fast(mg_uecc_word_t *result,
|
||||
const mg_uecc_word_t *left,
|
||||
const mg_uecc_word_t *right, MG_UECC_Curve curve);
|
||||
|
||||
/* Computes result = left^2 % mod.
|
||||
Currently only designed to work for mod == curve->p or curve_n. */
|
||||
void mg_uecc_vli_modSquare(mg_uecc_word_t *result, const mg_uecc_word_t *left,
|
||||
const mg_uecc_word_t *mod, wordcount_t num_words);
|
||||
|
||||
/* Computes result = left^2 % curve->p. */
|
||||
void mg_uecc_vli_modSquare_fast(mg_uecc_word_t *result,
|
||||
const mg_uecc_word_t *left,
|
||||
MG_UECC_Curve curve);
|
||||
|
||||
/* Computes result = (1 / input) % mod.*/
|
||||
void mg_uecc_vli_modInv(mg_uecc_word_t *result, const mg_uecc_word_t *input,
|
||||
const mg_uecc_word_t *mod, wordcount_t num_words);
|
||||
|
||||
#if MG_UECC_SUPPORT_COMPRESSED_POINT
|
||||
/* Calculates a = sqrt(a) (mod curve->p) */
|
||||
void mg_uecc_vli_mod_sqrt(mg_uecc_word_t *a, MG_UECC_Curve curve);
|
||||
#endif
|
||||
|
||||
/* Converts an integer in uECC native format to big-endian bytes. */
|
||||
void mg_uecc_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
|
||||
const mg_uecc_word_t *native);
|
||||
/* Converts big-endian bytes to an integer in uECC native format. */
|
||||
void mg_uecc_vli_bytesToNative(mg_uecc_word_t *native, const uint8_t *bytes,
|
||||
int num_bytes);
|
||||
|
||||
unsigned mg_uecc_curve_num_words(MG_UECC_Curve curve);
|
||||
unsigned mg_uecc_curve_num_bytes(MG_UECC_Curve curve);
|
||||
unsigned mg_uecc_curve_num_bits(MG_UECC_Curve curve);
|
||||
unsigned mg_uecc_curve_num_n_words(MG_UECC_Curve curve);
|
||||
unsigned mg_uecc_curve_num_n_bytes(MG_UECC_Curve curve);
|
||||
unsigned mg_uecc_curve_num_n_bits(MG_UECC_Curve curve);
|
||||
|
||||
const mg_uecc_word_t *mg_uecc_curve_p(MG_UECC_Curve curve);
|
||||
const mg_uecc_word_t *mg_uecc_curve_n(MG_UECC_Curve curve);
|
||||
const mg_uecc_word_t *mg_uecc_curve_G(MG_UECC_Curve curve);
|
||||
const mg_uecc_word_t *mg_uecc_curve_b(MG_UECC_Curve curve);
|
||||
|
||||
int mg_uecc_valid_point(const mg_uecc_word_t *point, MG_UECC_Curve curve);
|
||||
|
||||
/* Multiplies a point by a scalar. Points are represented by the X coordinate
|
||||
followed by the Y coordinate in the same array, both coordinates are
|
||||
curve->num_words long. Note that scalar must be curve->num_n_words long (NOT
|
||||
curve->num_words). */
|
||||
void mg_uecc_point_mult(mg_uecc_word_t *result, const mg_uecc_word_t *point,
|
||||
const mg_uecc_word_t *scalar, MG_UECC_Curve curve);
|
||||
|
||||
/* Generates a random integer in the range 0 < random < top.
|
||||
Both random and top have num_words words. */
|
||||
int mg_uecc_generate_random_int(mg_uecc_word_t *random,
|
||||
const mg_uecc_word_t *top,
|
||||
wordcount_t num_words);
|
||||
|
||||
#endif /* MG_UECC_ENABLE_VLI_API */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _UECC_VLI_H_ */
|
||||
|
||||
// End of uecc BSD-2
|
||||
// Big integers, "i31" format, see BearSSL src/inner.h
|
||||
uint32_t mg_br_i31_add(uint32_t *a, const uint32_t *b, uint32_t ctl);
|
||||
uint32_t mg_br_i31_sub(uint32_t *a, const uint32_t *b, uint32_t ctl);
|
||||
uint32_t mg_br_i31_bit_length(uint32_t *x, size_t xlen);
|
||||
uint32_t mg_br_i31_decode_mod(uint32_t *x, const void *src, size_t len,
|
||||
const uint32_t *m);
|
||||
void mg_br_i31_decode(uint32_t *x, const void *src, size_t len);
|
||||
void mg_br_i31_encode(void *dst, size_t len, const uint32_t *x);
|
||||
void mg_br_i31_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i);
|
||||
void mg_br_i31_to_monty(uint32_t *x, const uint32_t *m);
|
||||
uint32_t mg_br_i31_iszero(const uint32_t *x);
|
||||
void mg_br_i31_modpow(uint32_t *x, const unsigned char *e, size_t elen,
|
||||
const uint32_t *m, uint32_t m0i, uint32_t *t1,
|
||||
uint32_t *t2);
|
||||
void mg_br_i31_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y,
|
||||
const uint32_t *m, uint32_t m0i);
|
||||
void mg_br_i31_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m);
|
||||
uint32_t mg_br_i31_ninv31(uint32_t x);
|
||||
void mg_br_i31_rshift(uint32_t *x, int count);
|
||||
|
||||
// ECDSA, see BearSSL src/ec/ecdsa_i31_*.c. q is an uncompressed point
|
||||
void mg_br_ecdsa_i31_bits2int(uint32_t *x, const void *src, size_t len,
|
||||
uint32_t ebitlen);
|
||||
uint32_t mg_br_ecdsa_i31_vrfy_raw(const struct mg_br_ec_impl *impl, int curve,
|
||||
const void *hash, size_t hash_len,
|
||||
const unsigned char *q, size_t qlen,
|
||||
const void *sig, size_t sig_len);
|
||||
size_t mg_br_ecdsa_i31_sign_raw(const struct mg_br_ec_impl *impl, int curve,
|
||||
const void *hash, size_t hash_len,
|
||||
const unsigned char *x, size_t xlen,
|
||||
const unsigned char *k, void *sig);
|
||||
|
||||
// P-256 (secp256r1) API. Keys and signatures are big endian byte strings,
|
||||
// a public key is X || Y, a signature is r || s. Functions return 1 on
|
||||
// success, 0 on failure
|
||||
|
||||
// Generate a random key pair, using mg_random()
|
||||
int mg_p256_make_key(uint8_t public_key[64], uint8_t private_key[32]);
|
||||
|
||||
// Compute public key from a private key. Return 0 if private key is invalid
|
||||
int mg_p256_compute_public_key(const uint8_t private_key[32],
|
||||
uint8_t public_key[64]);
|
||||
|
||||
// ECDH. Validates the peer public key, returns 0 if it is not on the curve
|
||||
int mg_p256_shared_secret(const uint8_t public_key[64],
|
||||
const uint8_t private_key[32], uint8_t secret[32]);
|
||||
|
||||
// ECDSA sign with a deterministic k, RFC 6979 with HMAC-SHA256
|
||||
int mg_p256_sign(const uint8_t private_key[32], const uint8_t *hash,
|
||||
size_t hash_size, uint8_t signature[64]);
|
||||
|
||||
// ECDSA verify. Validates the public key
|
||||
int mg_p256_verify(const uint8_t public_key[64], const uint8_t *hash,
|
||||
size_t hash_size, const uint8_t signature[64]);
|
||||
|
||||
// Internal: ECDSA sign with a given k, 32 bytes big endian, in [1, n-1].
|
||||
// Provided by the selected implementation, used by mg_p256_sign()
|
||||
int mg_p256_sign_with_k(const uint8_t private_key[32], const uint8_t *hash,
|
||||
size_t hash_size, const uint8_t k[32],
|
||||
uint8_t signature[64]);
|
||||
#endif // MG_TLS == MG_TLS_BUILTIN || defined(MG_OTA_PUBLIC_KEY)
|
||||
// P-384 from BearSSL, https://bearssl.org commit 7bea48e
|
||||
// P-384 signature verification, used by built-in TLS for certificates and
|
||||
// CertificateVerify. Shared bignum and ECDSA code is in tls_p256.c
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Mongoose changes: br_ / BR_ names are prefixed with mg_ / MG_, static
|
||||
// functions with p384_. Trimmed to P-384. Structs are not typedef-ed
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if MG_TLS == MG_TLS_BUILTIN || defined(MG_OTA_PUBLIC_KEY)
|
||||
// Verify ECDSA P-384 signature r || s over hash. Public key is X || Y.
|
||||
// Return 1 on success, 0 on failure
|
||||
int mg_p384_verify(const uint8_t public_key[96], const uint8_t *hash,
|
||||
size_t hash_size, const uint8_t signature[96]);
|
||||
#endif // MG_TLS == MG_TLS_BUILTIN || defined(MG_OTA_PUBLIC_KEY)
|
||||
// portable8439 v1.0.1
|
||||
// Source: https://github.com/DavyLandman/portable8439
|
||||
// Licensed under CC0-1.0
|
||||
@@ -5425,9 +4992,6 @@ void mg_bsd_poll(struct mg_mgr *);
|
||||
#endif
|
||||
|
||||
#if MG_ENABLE_BSD_PROTOTYPES
|
||||
#if defined(FD_SET) || defined(FD_ZERO) || defined(FD_ISSET)
|
||||
#error "Include mongoose.h before system select headers"
|
||||
#endif
|
||||
typedef unsigned int socklen_t;
|
||||
typedef unsigned long nfds_t;
|
||||
typedef uint32_t in_addr_t;
|
||||
@@ -5471,6 +5035,8 @@ struct pollfd { int fd; short events; short revents; };
|
||||
#ifndef FD_SETSIZE
|
||||
#define FD_SETSIZE 64
|
||||
#endif
|
||||
|
||||
#ifndef FD_ZERO
|
||||
#define _NFDBITS ((int) sizeof(__fd_mask) * 8)
|
||||
#define _howmany(x, y) (((x) + ((y) - 1)) / (y))
|
||||
typedef struct fd_set {
|
||||
@@ -5487,6 +5053,7 @@ typedef struct fd_set {
|
||||
size_t _n = _howmany(FD_SETSIZE, _NFDBITS); \
|
||||
while (_n > 0) _p->__fds_bits[--_n] = 0; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define h_addr h_addr_list[0]
|
||||
#define AF_INET 2
|
||||
|
||||
Reference in new issue
Block a user