mirror of
https://github.com/cesanta/mongoose.git
synced 2024-11-27 20:59:00 +08:00
commit
d042697b10
6
.github/workflows/quicktest.yml
vendored
6
.github/workflows/quicktest.yml
vendored
@ -15,8 +15,8 @@ jobs:
|
||||
matrix:
|
||||
cc: [gcc, clang++]
|
||||
target: [test, mip_test]
|
||||
ssl: ["", MBEDTLS]
|
||||
name: linux ${{ matrix.target }} CC=${{ matrix.cc }} SSL=${{ matrix.ssl }}}
|
||||
ssl: ["", MBEDTLS, BUILTIN]
|
||||
name: linux ${{ matrix.target }} CC=${{ matrix.cc }} SSL=${{ matrix.ssl }}
|
||||
env:
|
||||
CC: ${{ matrix.cc }}
|
||||
SSL: ${{ matrix.ssl }}
|
||||
@ -57,7 +57,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
ssl: ["", MBEDTLS]
|
||||
ssl: ["", MBEDTLS, BUILTIN]
|
||||
name: macos SSL=${{ matrix.ssl }}
|
||||
env:
|
||||
SSL: ${{ matrix.ssl }}
|
||||
|
10
Makefile
10
Makefile
@ -47,6 +47,10 @@ CFLAGS += -DMG_TLS=MG_TLS_OPENSSL -I$(OPENSSL)/include
|
||||
LDFLAGS += -L$(OPENSSL)/lib -lssl -lcrypto
|
||||
endif
|
||||
|
||||
ifeq "$(SSL)" "BUILTIN"
|
||||
CFLAGS += -DMG_TLS=MG_TLS_BUILTIN
|
||||
endif
|
||||
|
||||
all:
|
||||
$(MAKE) -C examples/http-server
|
||||
|
||||
@ -75,9 +79,9 @@ examples_win:
|
||||
clean_examples_win:
|
||||
$(foreach X, $(EXAMPLES_WIN), $(MAKE) -C $(X) clean &)
|
||||
|
||||
test/packed_fs.c: Makefile src/ssi.h test/fuzz.c test/data/a.txt test/data/ca.pem
|
||||
test/packed_fs.c: Makefile src/ssi.h test/fuzz.c test/data/a.txt test/data/ca.pem test/certs/ca.crt test/certs/server.crt test/certs/server.key
|
||||
$(CC) $(CFLAGS) test/pack.c -o pack
|
||||
$(RUN) ./pack Makefile src/ssi.h test/fuzz.c test/data/a.txt test/data/range.txt test/data/ca.pem > $@
|
||||
$(RUN) ./pack Makefile src/ssi.h test/fuzz.c test/data/a.txt test/data/range.txt test/data/ca.pem test/certs/ca.crt test/certs/server.crt test/certs/server.key test/certs/client.key test/certs/client.crt > $@
|
||||
|
||||
# Check that all external (exported) symbols have "mg_" prefix
|
||||
mg_prefix: mongoose.c mongoose.h
|
||||
@ -184,7 +188,7 @@ mongoose.c: Makefile $(wildcard src/*.c) $(wildcard src/drivers/*.c)
|
||||
(export LC_ALL=C ; cat src/license.h; echo; echo '#include "mongoose.h"' ; (for F in src/*.c src/drivers/*.c ; do echo; echo '#ifdef MG_ENABLE_LINES'; echo "#line 1 \"$$F\""; echo '#endif'; cat $$F | sed -e 's,#include ".*,,'; done))> $@
|
||||
|
||||
mongoose.h: $(HDRS) Makefile
|
||||
(cat src/license.h; echo; echo '#ifndef MONGOOSE_H'; echo '#define MONGOOSE_H'; echo; cat src/version.h ; echo; echo '#ifdef __cplusplus'; echo 'extern "C" {'; echo '#endif'; cat src/arch.h src/arch_*.h src/net_ft.h src/net_lwip.h src/net_rl.h src/config.h src/str.h src/queue.h src/fmt.h src/printf.h src/log.h src/timer.h src/fs.h src/util.h src/url.h src/iobuf.h src/base64.h src/md5.h src/sha1.h src/sha256.h src/tls_aes128.h src/tls_uecc.h src/event.h src/net.h src/http.h src/ssi.h src/tls.h src/tls_mbed.h src/tls_openssl.h src/ws.h src/sntp.h src/mqtt.h src/dns.h src/json.h src/rpc.h src/ota.h src/device.h src/net_builtin.h src/profile.h src/drivers/*.h | sed -e '/keep/! s,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@
|
||||
(cat src/license.h; echo; echo '#ifndef MONGOOSE_H'; echo '#define MONGOOSE_H'; echo; cat src/version.h ; echo; echo '#ifdef __cplusplus'; echo 'extern "C" {'; echo '#endif'; cat src/arch.h src/arch_*.h src/net_ft.h src/net_lwip.h src/net_rl.h src/config.h src/str.h src/queue.h src/fmt.h src/printf.h src/log.h src/timer.h src/fs.h src/util.h src/url.h src/iobuf.h src/base64.h src/md5.h src/sha1.h src/sha256.h src/tls_x25519.h src/tls_aes128.h src/tls_uecc.h src/event.h src/net.h src/http.h src/ssi.h src/tls.h src/tls_mbed.h src/tls_openssl.h src/ws.h src/sntp.h src/mqtt.h src/dns.h src/json.h src/rpc.h src/ota.h src/device.h src/net_builtin.h src/profile.h src/drivers/*.h | sed -e '/keep/! s,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@
|
||||
|
||||
|
||||
clean: clean_examples clean_embedded
|
||||
|
4535
mongoose.c
4535
mongoose.c
File diff suppressed because it is too large
Load Diff
757
mongoose.h
757
mongoose.h
File diff suppressed because it is too large
Load Diff
@ -19,7 +19,7 @@ enum {
|
||||
MG_PHY_KSZ8x_REG_PC2R = 31,
|
||||
MG_PHY_LAN87x_REG_SCSR = 31,
|
||||
MG_PHY_RTL8201_REG_RMSR = 16, // in page 7
|
||||
MG_PHY_RTL8201_REG_PAGESEL = 31,
|
||||
MG_PHY_RTL8201_REG_PAGESEL = 31
|
||||
};
|
||||
|
||||
static const char *mg_phy_id_to_str(uint16_t id1, uint16_t id2) {
|
||||
@ -39,11 +39,12 @@ static const char *mg_phy_id_to_str(uint16_t id1, uint16_t id2) {
|
||||
}
|
||||
|
||||
void mg_phy_init(struct mg_phy *phy, uint8_t phy_addr, uint8_t config) {
|
||||
uint16_t id1, id2;
|
||||
phy->write_reg(phy_addr, MG_PHY_REG_BCR, MG_BIT(15)); // Reset PHY
|
||||
phy->write_reg(phy_addr, MG_PHY_REG_BCR, MG_BIT(12)); // Autonegotiation
|
||||
|
||||
uint16_t id1 = phy->read_reg(phy_addr, MG_PHY_REG_ID1);
|
||||
uint16_t id2 = phy->read_reg(phy_addr, MG_PHY_REG_ID2);
|
||||
id1 = phy->read_reg(phy_addr, MG_PHY_REG_ID1);
|
||||
id2 = phy->read_reg(phy_addr, MG_PHY_REG_ID2);
|
||||
MG_INFO(("PHY ID: %#04x %#04x (%s)", id1, id2, mg_phy_id_to_str(id1, id2)));
|
||||
|
||||
if (config & MG_PHY_CLOCKS_MAC) {
|
||||
@ -76,10 +77,11 @@ void mg_phy_init(struct mg_phy *phy, uint8_t phy_addr, uint8_t config) {
|
||||
|
||||
bool mg_phy_up(struct mg_phy *phy, uint8_t phy_addr, bool *full_duplex,
|
||||
uint8_t *speed) {
|
||||
bool up = false;
|
||||
uint16_t bsr = phy->read_reg(phy_addr, MG_PHY_REG_BSR);
|
||||
if ((bsr & MG_BIT(5)) && !(bsr & MG_BIT(2))) // some PHYs latch down events
|
||||
bsr = phy->read_reg(phy_addr, MG_PHY_REG_BSR); // read again
|
||||
bool up = bsr & MG_BIT(2);
|
||||
up = bsr & MG_BIT(2);
|
||||
if (up && full_duplex != NULL && speed != NULL) {
|
||||
uint16_t id1 = phy->read_reg(phy_addr, MG_PHY_REG_ID1);
|
||||
if (id1 == MG_PHY_DP83x) {
|
||||
|
@ -12,7 +12,7 @@ enum {
|
||||
MG_PHY_LEDS_ACTIVE_HIGH =
|
||||
(1 << 0), // Set if PHY LEDs are connected to ground
|
||||
MG_PHY_CLOCKS_MAC =
|
||||
(1 << 1), // Set when PHY clocks MAC. Otherwise, MAC clocks PHY
|
||||
(1 << 1) // Set when PHY clocks MAC. Otherwise, MAC clocks PHY
|
||||
};
|
||||
|
||||
enum { MG_PHY_SPEED_10M, MG_PHY_SPEED_100M, MG_PHY_SPEED_1000M };
|
||||
|
15
src/sha256.c
15
src/sha256.c
@ -1,3 +1,9 @@
|
||||
// https://github.com/B-Con/crypto-algorithms
|
||||
// Author: Brad Conte (brad AT bradconte.com)
|
||||
// Disclaimer: This code is presented "as is" without any guarantees.
|
||||
// Details: Defines the API for the corresponding SHA1 implementation.
|
||||
// Copyright: public domain
|
||||
|
||||
#include "sha256.h"
|
||||
|
||||
#define ror(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
|
||||
@ -39,8 +45,10 @@ static void mg_sha256_chunk(mg_sha256_ctx *ctx) {
|
||||
uint32_t a, b, c, d, e, f, g, h;
|
||||
uint32_t m[64];
|
||||
for (i = 0, j = 0; i < 16; ++i, j += 4)
|
||||
m[i] = (uint32_t) ((ctx->buffer[j] << 24) | (ctx->buffer[j + 1] << 16) |
|
||||
(ctx->buffer[j + 2] << 8) | (ctx->buffer[j + 3]));
|
||||
m[i] = (uint32_t) (((uint32_t) ctx->buffer[j] << 24) |
|
||||
((uint32_t) ctx->buffer[j + 1] << 16) |
|
||||
((uint32_t) ctx->buffer[j + 2] << 8) |
|
||||
((uint32_t) ctx->buffer[j + 3]));
|
||||
for (; i < 64; ++i)
|
||||
m[i] = sig1(m[i - 2]) + m[i - 7] + sig0(m[i - 15]) + m[i - 16];
|
||||
|
||||
@ -138,7 +146,7 @@ void mg_hmac_sha256(uint8_t dst[32], uint8_t *key, size_t keysz, uint8_t *data,
|
||||
memset(i_pad, 0x36, sizeof(i_pad));
|
||||
memset(o_pad, 0x5c, sizeof(o_pad));
|
||||
if (keysz < 64) {
|
||||
memmove(k, key, keysz);
|
||||
if (keysz > 0) memmove(k, key, keysz);
|
||||
} else {
|
||||
mg_sha256_init(&ctx);
|
||||
mg_sha256_update(&ctx, key, keysz);
|
||||
@ -157,4 +165,3 @@ void mg_hmac_sha256(uint8_t dst[32], uint8_t *key, size_t keysz, uint8_t *data,
|
||||
mg_sha256_update(&ctx, dst, 32);
|
||||
mg_sha256_final(dst, &ctx);
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,9 @@
|
||||
// https://github.com/B-Con/crypto-algorithms
|
||||
// Author: Brad Conte (brad AT bradconte.com)
|
||||
// Disclaimer: This code is presented "as is" without any guarantees.
|
||||
// Details: Defines the API for the corresponding SHA1 implementation.
|
||||
// Copyright: public domain
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch.h"
|
||||
|
@ -15,10 +15,11 @@
|
||||
#include "tls_openssl.h"
|
||||
|
||||
struct mg_tls_opts {
|
||||
struct mg_str ca; // PEM or DER
|
||||
struct mg_str cert; // PEM or DER
|
||||
struct mg_str key; // PEM or DER
|
||||
struct mg_str name; // If not empty, enable host name verification
|
||||
struct mg_str ca; // PEM or DER
|
||||
struct mg_str cert; // PEM or DER
|
||||
struct mg_str key; // PEM or DER
|
||||
struct mg_str name; // If not empty, enable host name verification
|
||||
int skip_verification; // Skip certificate and host name verification
|
||||
};
|
||||
|
||||
void mg_tls_init(struct mg_connection *, const struct mg_tls_opts *opts);
|
||||
|
337
src/tls_aes128.c
337
src/tls_aes128.c
@ -20,10 +20,177 @@
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "tls_aes128.h"
|
||||
/******************************************************************************/
|
||||
#define AES_DECRYPTION 1 // whether AES decryption is supported
|
||||
/******************************************************************************/
|
||||
|
||||
#define MG_ENCRYPT 1 // specify whether we're encrypting
|
||||
#define MG_DECRYPT 0 // or decrypting
|
||||
|
||||
#include "arch.h"
|
||||
#include "tls.h"
|
||||
#include "tls_aes128.h"
|
||||
|
||||
#if MG_TLS == MG_TLS_BUILTIN
|
||||
/******************************************************************************
|
||||
* AES_INIT_KEYGEN_TABLES : MUST be called once before any AES use
|
||||
******************************************************************************/
|
||||
static void aes_init_keygen_tables(void);
|
||||
|
||||
/******************************************************************************
|
||||
* AES_SETKEY : called to expand the key for encryption or decryption
|
||||
******************************************************************************/
|
||||
static int aes_setkey(aes_context *ctx, // pointer to context
|
||||
int mode, // 1 or 0 for Encrypt/Decrypt
|
||||
const uchar *key, // AES input key
|
||||
uint keysize); // size in bytes (must be 16, 24, 32 for
|
||||
// 128, 192 or 256-bit keys respectively)
|
||||
// returns 0 for success
|
||||
|
||||
/******************************************************************************
|
||||
* AES_CIPHER : called to encrypt or decrypt ONE 128-bit block of data
|
||||
******************************************************************************/
|
||||
static int aes_cipher(aes_context *ctx, // pointer to context
|
||||
const uchar input[16], // 128-bit block to en/decipher
|
||||
uchar output[16]); // 128-bit output result block
|
||||
// returns 0 for success
|
||||
|
||||
/******************************************************************************
|
||||
* GCM_CONTEXT : GCM context / holds keytables, instance data, and AES ctx
|
||||
******************************************************************************/
|
||||
typedef struct {
|
||||
int mode; // cipher direction: encrypt/decrypt
|
||||
uint64_t len; // cipher data length processed so far
|
||||
uint64_t add_len; // total add data length
|
||||
uint64_t HL[16]; // precalculated lo-half HTable
|
||||
uint64_t HH[16]; // precalculated hi-half HTable
|
||||
uchar base_ectr[16]; // first counter-mode cipher output for tag
|
||||
uchar y[16]; // the current cipher-input IV|Counter value
|
||||
uchar buf[16]; // buf working value
|
||||
aes_context aes_ctx; // cipher context used
|
||||
} gcm_context;
|
||||
|
||||
/******************************************************************************
|
||||
* GCM_SETKEY : sets the GCM (and AES) keying material for use
|
||||
******************************************************************************/
|
||||
static int gcm_setkey(
|
||||
gcm_context *ctx, // caller-provided context ptr
|
||||
const uchar *key, // pointer to cipher key
|
||||
const uint keysize // size in bytes (must be 16, 24, 32 for
|
||||
// 128, 192 or 256-bit keys respectively)
|
||||
); // returns 0 for success
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_CRYPT_AND_TAG
|
||||
*
|
||||
* This either encrypts or decrypts the user-provided data and, either
|
||||
* way, generates an authentication tag of the requested length. It must be
|
||||
* called with a GCM context whose key has already been set with GCM_SETKEY.
|
||||
*
|
||||
* The user would typically call this explicitly to ENCRYPT a buffer of data
|
||||
* and optional associated data, and produce its an authentication tag.
|
||||
*
|
||||
* To reverse the process the user would typically call the companion
|
||||
* GCM_AUTH_DECRYPT function to decrypt data and verify a user-provided
|
||||
* authentication tag. The GCM_AUTH_DECRYPT function calls this function
|
||||
* to perform its decryption and tag generation, which it then compares.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int gcm_crypt_and_tag(
|
||||
gcm_context *ctx, // gcm context with key already setup
|
||||
int mode, // cipher direction: MG_ENCRYPT (1) or MG_DECRYPT (0)
|
||||
const uchar *iv, // pointer to the 12-byte initialization vector
|
||||
size_t iv_len, // byte length if the IV. should always be 12
|
||||
const uchar *add, // pointer to the non-ciphered additional data
|
||||
size_t add_len, // byte length of the additional AEAD data
|
||||
const uchar *input, // pointer to the cipher data source
|
||||
uchar *output, // pointer to the cipher data destination
|
||||
size_t length, // byte length of the cipher data
|
||||
uchar *tag, // pointer to the tag to be generated
|
||||
size_t tag_len); // byte length of the tag to be generated
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_START
|
||||
*
|
||||
* Given a user-provided GCM context, this initializes it, sets the encryption
|
||||
* mode, and preprocesses the initialization vector and additional AEAD data.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int gcm_start(
|
||||
gcm_context *ctx, // pointer to user-provided GCM context
|
||||
int mode, // MG_ENCRYPT (1) or MG_DECRYPT (0)
|
||||
const uchar *iv, // pointer to initialization vector
|
||||
size_t iv_len, // IV length in bytes (should == 12)
|
||||
const uchar *add, // pointer to additional AEAD data (NULL if none)
|
||||
size_t add_len); // length of additional AEAD data (bytes)
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_UPDATE
|
||||
*
|
||||
* This is called once or more to process bulk plaintext or ciphertext data.
|
||||
* We give this some number of bytes of input and it returns the same number
|
||||
* of output bytes. If called multiple times (which is fine) all but the final
|
||||
* invocation MUST be called with length mod 16 == 0. (Only the final call can
|
||||
* have a partial block length of < 128 bits.)
|
||||
*
|
||||
******************************************************************************/
|
||||
static int gcm_update(gcm_context *ctx, // pointer to user-provided GCM context
|
||||
size_t length, // length, in bytes, of data to process
|
||||
const uchar *input, // pointer to source data
|
||||
uchar *output); // pointer to destination data
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_FINISH
|
||||
*
|
||||
* This is called once after all calls to GCM_UPDATE to finalize the GCM.
|
||||
* It performs the final GHASH to produce the resulting authentication TAG.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int gcm_finish(
|
||||
gcm_context *ctx, // pointer to user-provided GCM context
|
||||
uchar *tag, // ptr to tag buffer - NULL if tag_len = 0
|
||||
size_t tag_len); // length, in bytes, of the tag-receiving buf
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_ZERO_CTX
|
||||
*
|
||||
* The GCM context contains both the GCM context and the AES context.
|
||||
* This includes keying and key-related material which is security-
|
||||
* sensitive, so it MUST be zeroed after use. This function does that.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void gcm_zero_ctx(gcm_context *ctx);
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL
|
||||
*
|
||||
* This is a simple and straightforward implementation of the AES Rijndael
|
||||
* 128-bit block cipher designed by Vincent Rijmen and Joan Daemen. The focus
|
||||
* of this work was correctness & accuracy. It is written in 'C' without any
|
||||
* particular focus upon optimization or speed. It should be endian (memory
|
||||
* byte order) neutral since the few places that care are handled explicitly.
|
||||
*
|
||||
* This implementation of Rijndael was created by Steven M. Gibson of GRC.com.
|
||||
*
|
||||
* It is intended for general purpose use, but was written in support of GRC's
|
||||
* reference implementation of the SQRL (Secure Quick Reliable Login) client.
|
||||
*
|
||||
* See: http://csrc.nist.gov/archive/aes/rijndael/wsdindex.html
|
||||
*
|
||||
* NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE
|
||||
* REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "tls.h"
|
||||
#include "tls_aes128.h"
|
||||
|
||||
static int aes_tables_inited = 0; // run-once flag for performing key
|
||||
// expasion table generation (see below)
|
||||
/*
|
||||
@ -77,34 +244,34 @@ static uint32_t RCON[10]; // AES round constants
|
||||
/*
|
||||
* AES forward and reverse encryption round processing macros
|
||||
*/
|
||||
#define AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3) \
|
||||
{ \
|
||||
X0 = *RK++ ^ FT0[(Y0) &0xFF] ^ FT1[(Y1 >> 8) & 0xFF] ^ \
|
||||
FT2[(Y2 >> 16) & 0xFF] ^ FT3[(Y3 >> 24) & 0xFF]; \
|
||||
\
|
||||
X1 = *RK++ ^ FT0[(Y1) &0xFF] ^ FT1[(Y2 >> 8) & 0xFF] ^ \
|
||||
FT2[(Y3 >> 16) & 0xFF] ^ FT3[(Y0 >> 24) & 0xFF]; \
|
||||
\
|
||||
X2 = *RK++ ^ FT0[(Y2) &0xFF] ^ FT1[(Y3 >> 8) & 0xFF] ^ \
|
||||
FT2[(Y0 >> 16) & 0xFF] ^ FT3[(Y1 >> 24) & 0xFF]; \
|
||||
\
|
||||
X3 = *RK++ ^ FT0[(Y3) &0xFF] ^ FT1[(Y0 >> 8) & 0xFF] ^ \
|
||||
FT2[(Y1 >> 16) & 0xFF] ^ FT3[(Y2 >> 24) & 0xFF]; \
|
||||
#define AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3) \
|
||||
{ \
|
||||
X0 = *RK++ ^ FT0[(Y0) & 0xFF] ^ FT1[(Y1 >> 8) & 0xFF] ^ \
|
||||
FT2[(Y2 >> 16) & 0xFF] ^ FT3[(Y3 >> 24) & 0xFF]; \
|
||||
\
|
||||
X1 = *RK++ ^ FT0[(Y1) & 0xFF] ^ FT1[(Y2 >> 8) & 0xFF] ^ \
|
||||
FT2[(Y3 >> 16) & 0xFF] ^ FT3[(Y0 >> 24) & 0xFF]; \
|
||||
\
|
||||
X2 = *RK++ ^ FT0[(Y2) & 0xFF] ^ FT1[(Y3 >> 8) & 0xFF] ^ \
|
||||
FT2[(Y0 >> 16) & 0xFF] ^ FT3[(Y1 >> 24) & 0xFF]; \
|
||||
\
|
||||
X3 = *RK++ ^ FT0[(Y3) & 0xFF] ^ FT1[(Y0 >> 8) & 0xFF] ^ \
|
||||
FT2[(Y1 >> 16) & 0xFF] ^ FT3[(Y2 >> 24) & 0xFF]; \
|
||||
}
|
||||
|
||||
#define AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3) \
|
||||
{ \
|
||||
X0 = *RK++ ^ RT0[(Y0) &0xFF] ^ RT1[(Y3 >> 8) & 0xFF] ^ \
|
||||
RT2[(Y2 >> 16) & 0xFF] ^ RT3[(Y1 >> 24) & 0xFF]; \
|
||||
\
|
||||
X1 = *RK++ ^ RT0[(Y1) &0xFF] ^ RT1[(Y0 >> 8) & 0xFF] ^ \
|
||||
RT2[(Y3 >> 16) & 0xFF] ^ RT3[(Y2 >> 24) & 0xFF]; \
|
||||
\
|
||||
X2 = *RK++ ^ RT0[(Y2) &0xFF] ^ RT1[(Y1 >> 8) & 0xFF] ^ \
|
||||
RT2[(Y0 >> 16) & 0xFF] ^ RT3[(Y3 >> 24) & 0xFF]; \
|
||||
\
|
||||
X3 = *RK++ ^ RT0[(Y3) &0xFF] ^ RT1[(Y2 >> 8) & 0xFF] ^ \
|
||||
RT2[(Y1 >> 16) & 0xFF] ^ RT3[(Y0 >> 24) & 0xFF]; \
|
||||
#define AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3) \
|
||||
{ \
|
||||
X0 = *RK++ ^ RT0[(Y0) & 0xFF] ^ RT1[(Y3 >> 8) & 0xFF] ^ \
|
||||
RT2[(Y2 >> 16) & 0xFF] ^ RT3[(Y1 >> 24) & 0xFF]; \
|
||||
\
|
||||
X1 = *RK++ ^ RT0[(Y1) & 0xFF] ^ RT1[(Y0 >> 8) & 0xFF] ^ \
|
||||
RT2[(Y3 >> 16) & 0xFF] ^ RT3[(Y2 >> 24) & 0xFF]; \
|
||||
\
|
||||
X2 = *RK++ ^ RT0[(Y2) & 0xFF] ^ RT1[(Y1 >> 8) & 0xFF] ^ \
|
||||
RT2[(Y0 >> 16) & 0xFF] ^ RT3[(Y3 >> 24) & 0xFF]; \
|
||||
\
|
||||
X3 = *RK++ ^ RT0[(Y3) & 0xFF] ^ RT1[(Y2 >> 8) & 0xFF] ^ \
|
||||
RT2[(Y1 >> 16) & 0xFF] ^ RT3[(Y0 >> 24) & 0xFF]; \
|
||||
}
|
||||
|
||||
/*
|
||||
@ -210,7 +377,8 @@ void aes_init_keygen_tables(void) {
|
||||
* Valid lengths are: 16, 24 or 32 bytes (128, 192, 256 bits).
|
||||
*
|
||||
******************************************************************************/
|
||||
static int aes_set_encryption_key(aes_context *ctx, const uchar *key, uint keysize) {
|
||||
static int aes_set_encryption_key(aes_context *ctx, const uchar *key,
|
||||
uint keysize) {
|
||||
uint i; // general purpose iteration local
|
||||
uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
|
||||
|
||||
@ -287,7 +455,8 @@ static int aes_set_encryption_key(aes_context *ctx, const uchar *key, uint keysi
|
||||
* length in bits. Valid lengths are: 128, 192, or 256 bits.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int aes_set_decryption_key(aes_context *ctx, const uchar *key, uint keysize) {
|
||||
static int aes_set_decryption_key(aes_context *ctx, const uchar *key,
|
||||
uint keysize) {
|
||||
int i, j;
|
||||
aes_context cty; // a calling aes context for set_encryption_key
|
||||
uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
|
||||
@ -323,10 +492,10 @@ static int aes_set_decryption_key(aes_context *ctx, const uchar *key, uint keysi
|
||||
* Invoked to establish the key schedule for subsequent encryption/decryption
|
||||
*
|
||||
******************************************************************************/
|
||||
int aes_setkey(aes_context *ctx, // AES context provided by our caller
|
||||
int mode, // ENCRYPT or DECRYPT flag
|
||||
const uchar *key, // pointer to the key
|
||||
uint keysize) // key length in bytes
|
||||
static int aes_setkey(aes_context *ctx, // AES context provided by our caller
|
||||
int mode, // ENCRYPT or DECRYPT flag
|
||||
const uchar *key, // pointer to the key
|
||||
uint keysize) // key length in bytes
|
||||
{
|
||||
// since table initialization is not thread safe, we could either add
|
||||
// system-specific mutexes and init the AES key generation tables on
|
||||
@ -369,7 +538,8 @@ int aes_setkey(aes_context *ctx, // AES context provided by our caller
|
||||
* and all keying information appropriate for the task.
|
||||
*
|
||||
******************************************************************************/
|
||||
int aes_cipher(aes_context *ctx, const uchar input[16], uchar output[16]) {
|
||||
static int aes_cipher(aes_context *ctx, const uchar input[16],
|
||||
uchar output[16]) {
|
||||
int i;
|
||||
uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; // general purpose locals
|
||||
|
||||
@ -394,22 +564,22 @@ int aes_cipher(aes_context *ctx, const uchar input[16], uchar output[16]) {
|
||||
|
||||
AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);
|
||||
|
||||
X0 = *RK++ ^ ((uint32_t) RSb[(Y0) &0xFF]) ^
|
||||
X0 = *RK++ ^ ((uint32_t) RSb[(Y0) & 0xFF]) ^
|
||||
((uint32_t) RSb[(Y3 >> 8) & 0xFF] << 8) ^
|
||||
((uint32_t) RSb[(Y2 >> 16) & 0xFF] << 16) ^
|
||||
((uint32_t) RSb[(Y1 >> 24) & 0xFF] << 24);
|
||||
|
||||
X1 = *RK++ ^ ((uint32_t) RSb[(Y1) &0xFF]) ^
|
||||
X1 = *RK++ ^ ((uint32_t) RSb[(Y1) & 0xFF]) ^
|
||||
((uint32_t) RSb[(Y0 >> 8) & 0xFF] << 8) ^
|
||||
((uint32_t) RSb[(Y3 >> 16) & 0xFF] << 16) ^
|
||||
((uint32_t) RSb[(Y2 >> 24) & 0xFF] << 24);
|
||||
|
||||
X2 = *RK++ ^ ((uint32_t) RSb[(Y2) &0xFF]) ^
|
||||
X2 = *RK++ ^ ((uint32_t) RSb[(Y2) & 0xFF]) ^
|
||||
((uint32_t) RSb[(Y1 >> 8) & 0xFF] << 8) ^
|
||||
((uint32_t) RSb[(Y0 >> 16) & 0xFF] << 16) ^
|
||||
((uint32_t) RSb[(Y3 >> 24) & 0xFF] << 24);
|
||||
|
||||
X3 = *RK++ ^ ((uint32_t) RSb[(Y3) &0xFF]) ^
|
||||
X3 = *RK++ ^ ((uint32_t) RSb[(Y3) & 0xFF]) ^
|
||||
((uint32_t) RSb[(Y2 >> 8) & 0xFF] << 8) ^
|
||||
((uint32_t) RSb[(Y1 >> 16) & 0xFF] << 16) ^
|
||||
((uint32_t) RSb[(Y0 >> 24) & 0xFF] << 24);
|
||||
@ -424,22 +594,22 @@ int aes_cipher(aes_context *ctx, const uchar input[16], uchar output[16]) {
|
||||
|
||||
AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);
|
||||
|
||||
X0 = *RK++ ^ ((uint32_t) FSb[(Y0) &0xFF]) ^
|
||||
X0 = *RK++ ^ ((uint32_t) FSb[(Y0) & 0xFF]) ^
|
||||
((uint32_t) FSb[(Y1 >> 8) & 0xFF] << 8) ^
|
||||
((uint32_t) FSb[(Y2 >> 16) & 0xFF] << 16) ^
|
||||
((uint32_t) FSb[(Y3 >> 24) & 0xFF] << 24);
|
||||
|
||||
X1 = *RK++ ^ ((uint32_t) FSb[(Y1) &0xFF]) ^
|
||||
X1 = *RK++ ^ ((uint32_t) FSb[(Y1) & 0xFF]) ^
|
||||
((uint32_t) FSb[(Y2 >> 8) & 0xFF] << 8) ^
|
||||
((uint32_t) FSb[(Y3 >> 16) & 0xFF] << 16) ^
|
||||
((uint32_t) FSb[(Y0 >> 24) & 0xFF] << 24);
|
||||
|
||||
X2 = *RK++ ^ ((uint32_t) FSb[(Y2) &0xFF]) ^
|
||||
X2 = *RK++ ^ ((uint32_t) FSb[(Y2) & 0xFF]) ^
|
||||
((uint32_t) FSb[(Y3 >> 8) & 0xFF] << 8) ^
|
||||
((uint32_t) FSb[(Y0 >> 16) & 0xFF] << 16) ^
|
||||
((uint32_t) FSb[(Y1 >> 24) & 0xFF] << 24);
|
||||
|
||||
X3 = *RK++ ^ ((uint32_t) FSb[(Y3) &0xFF]) ^
|
||||
X3 = *RK++ ^ ((uint32_t) FSb[(Y3) & 0xFF]) ^
|
||||
((uint32_t) FSb[(Y0 >> 8) & 0xFF] << 8) ^
|
||||
((uint32_t) FSb[(Y1 >> 16) & 0xFF] << 16) ^
|
||||
((uint32_t) FSb[(Y2 >> 24) & 0xFF] << 24);
|
||||
@ -480,7 +650,6 @@ int aes_cipher(aes_context *ctx, const uchar input[16], uchar output[16]) {
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* ==== IMPLEMENTATION WARNING ====
|
||||
*
|
||||
@ -565,7 +734,7 @@ static const uint64_t last4[16] = {
|
||||
* environment is running.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_initialize(void) {
|
||||
int mg_gcm_initialize(void) {
|
||||
aes_init_keygen_tables();
|
||||
return (0);
|
||||
}
|
||||
@ -625,10 +794,11 @@ static void gcm_mult(gcm_context *ctx, // pointer to established context
|
||||
* and populates the gcm context's pre-calculated HTables.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_setkey(gcm_context *ctx, // pointer to caller-provided gcm context
|
||||
const uchar *key, // pointer to the AES encryption key
|
||||
const uint keysize) // size in bytes (must be 16, 24, 32 for
|
||||
// 128, 192 or 256-bit keys respectively)
|
||||
static int gcm_setkey(
|
||||
gcm_context *ctx, // pointer to caller-provided gcm context
|
||||
const uchar *key, // pointer to the AES encryption key
|
||||
const uint keysize) // size in bytes (must be 16, 24, 32 for
|
||||
// 128, 192 or 256-bit keys respectively)
|
||||
{
|
||||
int ret, i, j;
|
||||
uint64_t hi, lo;
|
||||
@ -717,7 +887,7 @@ int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
|
||||
ctx->len = 0;
|
||||
ctx->add_len = 0;
|
||||
|
||||
ctx->mode = mode; // set the GCM encryption/decryption mode
|
||||
ctx->mode = mode; // set the GCM encryption/decryption mode
|
||||
ctx->aes_ctx.mode = MG_ENCRYPT; // GCM *always* runs AES in ENCRYPTION mode
|
||||
|
||||
if (iv_len == 12) { // GCM natively uses a 12-byte, 96-bit IV
|
||||
@ -895,51 +1065,6 @@ int gcm_crypt_and_tag(
|
||||
return (0);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_AUTH_DECRYPT
|
||||
*
|
||||
* This DECRYPTS a user-provided data buffer with optional associated data.
|
||||
* It then verifies a user-supplied authentication tag against the tag just
|
||||
* re-created during decryption to verify that the data has not been altered.
|
||||
*
|
||||
* This function calls GCM_CRYPT_AND_TAG (above) to perform the decryption
|
||||
* and authentication tag generation.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_auth_decrypt(
|
||||
gcm_context *ctx, // gcm context with key already setup
|
||||
const uchar *iv, // pointer to the 12-byte initialization vector
|
||||
size_t iv_len, // byte length if the IV. should always be 12
|
||||
const uchar *add, // pointer to the non-ciphered additional data
|
||||
size_t add_len, // byte length of the additional AEAD data
|
||||
const uchar *input, // pointer to the cipher data source
|
||||
uchar *output, // pointer to the cipher data destination
|
||||
size_t length, // byte length of the cipher data
|
||||
const uchar *tag, // pointer to the tag to be authenticated
|
||||
size_t tag_len) // byte length of the tag <= 16
|
||||
{
|
||||
uchar check_tag[16]; // the tag generated and returned by decryption
|
||||
int diff; // an ORed flag to detect authentication errors
|
||||
size_t i; // our local iterator
|
||||
/*
|
||||
we use GCM_DECRYPT_AND_TAG (above) to perform our decryption
|
||||
(which is an identical XORing to reverse the previous one)
|
||||
and also to re-generate the matching authentication tag
|
||||
*/
|
||||
gcm_crypt_and_tag(ctx, MG_DECRYPT, iv, iv_len, add, add_len, input, output,
|
||||
length, check_tag, tag_len);
|
||||
|
||||
// now we verify the authentication tag in 'constant time'
|
||||
for (diff = 0, i = 0; i < tag_len; i++) diff |= tag[i] ^ check_tag[i];
|
||||
|
||||
if (diff != 0) { // see whether any bits differed?
|
||||
memset(output, 0, length); // if so... wipe the output data
|
||||
return (GCM_AUTH_FAILURE); // return GCM_AUTH_FAILURE
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_ZERO_CTX
|
||||
@ -961,29 +1086,29 @@ void gcm_zero_ctx(gcm_context *ctx) {
|
||||
//
|
||||
//
|
||||
|
||||
int aes_gcm_encrypt(unsigned char *output, //
|
||||
const unsigned char *input, size_t input_length,
|
||||
const unsigned char *key, const size_t key_len,
|
||||
const unsigned char *iv, const size_t iv_len,
|
||||
unsigned char *aead, size_t aead_len, unsigned char *tag,
|
||||
const size_t tag_len) {
|
||||
int mg_aes_gcm_encrypt(unsigned char *output, //
|
||||
const unsigned char *input, size_t input_length,
|
||||
const unsigned char *key, const size_t key_len,
|
||||
const unsigned char *iv, const size_t iv_len,
|
||||
unsigned char *aead, size_t aead_len, unsigned char *tag,
|
||||
const size_t tag_len) {
|
||||
int ret = 0; // our return value
|
||||
gcm_context ctx; // includes the AES context structure
|
||||
|
||||
gcm_setkey(&ctx, key, (const uint) key_len);
|
||||
|
||||
ret = gcm_crypt_and_tag(&ctx, MG_ENCRYPT, iv, iv_len, aead, aead_len, input, output,
|
||||
input_length, tag, tag_len);
|
||||
ret = gcm_crypt_and_tag(&ctx, MG_ENCRYPT, iv, iv_len, aead, aead_len, input,
|
||||
output, input_length, tag, tag_len);
|
||||
|
||||
gcm_zero_ctx(&ctx);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int aes_gcm_decrypt(unsigned char *output, const unsigned char *input,
|
||||
size_t input_length, const unsigned char *key,
|
||||
const size_t key_len, const unsigned char *iv,
|
||||
const size_t iv_len) {
|
||||
int mg_aes_gcm_decrypt(unsigned char *output, const unsigned char *input,
|
||||
size_t input_length, const unsigned char *key,
|
||||
const size_t key_len, const unsigned char *iv,
|
||||
const size_t iv_len) {
|
||||
int ret = 0; // our return value
|
||||
gcm_context ctx; // includes the AES context structure
|
||||
|
||||
|
249
src/tls_aes128.h
249
src/tls_aes128.h
@ -1,74 +1,3 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL
|
||||
*
|
||||
* This is a simple and straightforward implementation of the AES Rijndael
|
||||
* 128-bit block cipher designed by Vincent Rijmen and Joan Daemen. The focus
|
||||
* of this work was correctness & accuracy. It is written in 'C' without any
|
||||
* particular focus upon optimization or speed. It should be endian (memory
|
||||
* byte order) neutral since the few places that care are handled explicitly.
|
||||
*
|
||||
* This implementation of Rijndael was created by Steven M. Gibson of GRC.com.
|
||||
*
|
||||
* It is intended for general purpose use, but was written in support of GRC's
|
||||
* reference implementation of the SQRL (Secure Quick Reliable Login) client.
|
||||
*
|
||||
* See: http://csrc.nist.gov/archive/aes/rijndael/wsdindex.html
|
||||
*
|
||||
* NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE
|
||||
* REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef AES_HEADER
|
||||
#define AES_HEADER
|
||||
|
||||
/******************************************************************************/
|
||||
#define AES_DECRYPTION 1 // whether AES decryption is supported
|
||||
/******************************************************************************/
|
||||
|
||||
#define MG_ENCRYPT 1 // specify whether we're encrypting
|
||||
#define MG_DECRYPT 0 // or decrypting
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
typedef unsigned char uchar; // add some convienent shorter types
|
||||
typedef unsigned int uint;
|
||||
|
||||
/******************************************************************************
|
||||
* AES_INIT_KEYGEN_TABLES : MUST be called once before any AES use
|
||||
******************************************************************************/
|
||||
void aes_init_keygen_tables(void);
|
||||
|
||||
/******************************************************************************
|
||||
* AES_CONTEXT : cipher context / holds inter-call data
|
||||
******************************************************************************/
|
||||
typedef struct {
|
||||
int mode; // 1 for Encryption, 0 for Decryption
|
||||
int rounds; // keysize-based rounds count
|
||||
uint32_t *rk; // pointer to current round key
|
||||
uint32_t buf[68]; // key expansion buffer
|
||||
} aes_context;
|
||||
|
||||
/******************************************************************************
|
||||
* AES_SETKEY : called to expand the key for encryption or decryption
|
||||
******************************************************************************/
|
||||
int aes_setkey(aes_context *ctx, // pointer to context
|
||||
int mode, // 1 or 0 for Encrypt/Decrypt
|
||||
const uchar *key, // AES input key
|
||||
uint keysize); // size in bytes (must be 16, 24, 32 for
|
||||
// 128, 192 or 256-bit keys respectively)
|
||||
// returns 0 for success
|
||||
|
||||
/******************************************************************************
|
||||
* AES_CIPHER : called to encrypt or decrypt ONE 128-bit block of data
|
||||
******************************************************************************/
|
||||
int aes_cipher(aes_context *ctx, // pointer to context
|
||||
const uchar input[16], // 128-bit block to en/decipher
|
||||
uchar output[16]); // 128-bit output result block
|
||||
// returns 0 for success
|
||||
|
||||
#endif /* AES_HEADER */
|
||||
/******************************************************************************
|
||||
*
|
||||
* THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL
|
||||
@ -92,151 +21,30 @@ int aes_cipher(aes_context *ctx, // pointer to context
|
||||
* REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#ifndef GCM_HEADER
|
||||
#define GCM_HEADER
|
||||
#ifndef TLS_AES128_H
|
||||
#define TLS_AES128_H
|
||||
|
||||
typedef unsigned char uchar; // add some convienent shorter types
|
||||
typedef unsigned int uint;
|
||||
|
||||
/******************************************************************************
|
||||
* AES_CONTEXT : cipher context / holds inter-call data
|
||||
******************************************************************************/
|
||||
typedef struct {
|
||||
int mode; // 1 for Encryption, 0 for Decryption
|
||||
int rounds; // keysize-based rounds count
|
||||
uint32_t *rk; // pointer to current round key
|
||||
uint32_t buf[68]; // key expansion buffer
|
||||
} aes_context;
|
||||
|
||||
#include "arch.h"
|
||||
#define GCM_AUTH_FAILURE 0x55555555 // authentication failure
|
||||
|
||||
/******************************************************************************
|
||||
* GCM_CONTEXT : GCM context / holds keytables, instance data, and AES ctx
|
||||
******************************************************************************/
|
||||
typedef struct {
|
||||
int mode; // cipher direction: encrypt/decrypt
|
||||
uint64_t len; // cipher data length processed so far
|
||||
uint64_t add_len; // total add data length
|
||||
uint64_t HL[16]; // precalculated lo-half HTable
|
||||
uint64_t HH[16]; // precalculated hi-half HTable
|
||||
uchar base_ectr[16]; // first counter-mode cipher output for tag
|
||||
uchar y[16]; // the current cipher-input IV|Counter value
|
||||
uchar buf[16]; // buf working value
|
||||
aes_context aes_ctx; // cipher context used
|
||||
} gcm_context;
|
||||
|
||||
/******************************************************************************
|
||||
* GCM_CONTEXT : MUST be called once before ANY use of this library
|
||||
******************************************************************************/
|
||||
int gcm_initialize(void);
|
||||
int mg_gcm_initialize(void);
|
||||
|
||||
/******************************************************************************
|
||||
* GCM_SETKEY : sets the GCM (and AES) keying material for use
|
||||
******************************************************************************/
|
||||
int gcm_setkey(gcm_context *ctx, // caller-provided context ptr
|
||||
const uchar *key, // pointer to cipher key
|
||||
const uint keysize // size in bytes (must be 16, 24, 32 for
|
||||
// 128, 192 or 256-bit keys respectively)
|
||||
); // returns 0 for success
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_CRYPT_AND_TAG
|
||||
*
|
||||
* This either encrypts or decrypts the user-provided data and, either
|
||||
* way, generates an authentication tag of the requested length. It must be
|
||||
* called with a GCM context whose key has already been set with GCM_SETKEY.
|
||||
*
|
||||
* The user would typically call this explicitly to ENCRYPT a buffer of data
|
||||
* and optional associated data, and produce its an authentication tag.
|
||||
*
|
||||
* To reverse the process the user would typically call the companion
|
||||
* GCM_AUTH_DECRYPT function to decrypt data and verify a user-provided
|
||||
* authentication tag. The GCM_AUTH_DECRYPT function calls this function
|
||||
* to perform its decryption and tag generation, which it then compares.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_crypt_and_tag(
|
||||
gcm_context *ctx, // gcm context with key already setup
|
||||
int mode, // cipher direction: MG_ENCRYPT (1) or MG_DECRYPT (0)
|
||||
const uchar *iv, // pointer to the 12-byte initialization vector
|
||||
size_t iv_len, // byte length if the IV. should always be 12
|
||||
const uchar *add, // pointer to the non-ciphered additional data
|
||||
size_t add_len, // byte length of the additional AEAD data
|
||||
const uchar *input, // pointer to the cipher data source
|
||||
uchar *output, // pointer to the cipher data destination
|
||||
size_t length, // byte length of the cipher data
|
||||
uchar *tag, // pointer to the tag to be generated
|
||||
size_t tag_len); // byte length of the tag to be generated
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_AUTH_DECRYPT
|
||||
*
|
||||
* This DECRYPTS a user-provided data buffer with optional associated data.
|
||||
* It then verifies a user-supplied authentication tag against the tag just
|
||||
* re-created during decryption to verify that the data has not been altered.
|
||||
*
|
||||
* This function calls GCM_CRYPT_AND_TAG (above) to perform the decryption
|
||||
* and authentication tag generation.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_auth_decrypt(
|
||||
gcm_context *ctx, // gcm context with key already setup
|
||||
const uchar *iv, // pointer to the 12-byte initialization vector
|
||||
size_t iv_len, // byte length if the IV. should always be 12
|
||||
const uchar *add, // pointer to the non-ciphered additional data
|
||||
size_t add_len, // byte length of the additional AEAD data
|
||||
const uchar *input, // pointer to the cipher data source
|
||||
uchar *output, // pointer to the cipher data destination
|
||||
size_t length, // byte length of the cipher data
|
||||
const uchar *tag, // pointer to the tag to be authenticated
|
||||
size_t tag_len); // byte length of the tag <= 16
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_START
|
||||
*
|
||||
* Given a user-provided GCM context, this initializes it, sets the encryption
|
||||
* mode, and preprocesses the initialization vector and additional AEAD data.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_start(
|
||||
gcm_context *ctx, // pointer to user-provided GCM context
|
||||
int mode, // MG_ENCRYPT (1) or MG_DECRYPT (0)
|
||||
const uchar *iv, // pointer to initialization vector
|
||||
size_t iv_len, // IV length in bytes (should == 12)
|
||||
const uchar *add, // pointer to additional AEAD data (NULL if none)
|
||||
size_t add_len); // length of additional AEAD data (bytes)
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_UPDATE
|
||||
*
|
||||
* This is called once or more to process bulk plaintext or ciphertext data.
|
||||
* We give this some number of bytes of input and it returns the same number
|
||||
* of output bytes. If called multiple times (which is fine) all but the final
|
||||
* invocation MUST be called with length mod 16 == 0. (Only the final call can
|
||||
* have a partial block length of < 128 bits.)
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_update(gcm_context *ctx, // pointer to user-provided GCM context
|
||||
size_t length, // length, in bytes, of data to process
|
||||
const uchar *input, // pointer to source data
|
||||
uchar *output); // pointer to destination data
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_FINISH
|
||||
*
|
||||
* This is called once after all calls to GCM_UPDATE to finalize the GCM.
|
||||
* It performs the final GHASH to produce the resulting authentication TAG.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_finish(gcm_context *ctx, // pointer to user-provided GCM context
|
||||
uchar *tag, // ptr to tag buffer - NULL if tag_len = 0
|
||||
size_t tag_len); // length, in bytes, of the tag-receiving buf
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_ZERO_CTX
|
||||
*
|
||||
* The GCM context contains both the GCM context and the AES context.
|
||||
* This includes keying and key-related material which is security-
|
||||
* sensitive, so it MUST be zeroed after use. This function does that.
|
||||
*
|
||||
******************************************************************************/
|
||||
void gcm_zero_ctx(gcm_context *ctx);
|
||||
|
||||
#endif /* GCM_HEADER */
|
||||
//
|
||||
// aes-gcm.h
|
||||
// MKo
|
||||
@ -244,21 +52,18 @@ void gcm_zero_ctx(gcm_context *ctx);
|
||||
// Created by Markus Kosmal on 20/11/14.
|
||||
//
|
||||
//
|
||||
int mg_aes_gcm_encrypt(unsigned char *output, const unsigned char *input,
|
||||
size_t input_length, const unsigned char *key,
|
||||
const size_t key_len, const unsigned char *iv,
|
||||
const size_t iv_len, unsigned char *aead,
|
||||
size_t aead_len, unsigned char *tag,
|
||||
const size_t tag_len);
|
||||
|
||||
#ifndef mko_aes_gcm_h
|
||||
#define mko_aes_gcm_h
|
||||
int mg_aes_gcm_decrypt(unsigned char *output, const unsigned char *input,
|
||||
size_t input_length, const unsigned char *key,
|
||||
const size_t key_len, const unsigned char *iv,
|
||||
const size_t iv_len);
|
||||
|
||||
int aes_gcm_encrypt(unsigned char *output, const unsigned char *input,
|
||||
size_t input_length, const unsigned char *key,
|
||||
const size_t key_len, const unsigned char *iv,
|
||||
const size_t iv_len, unsigned char *aead, size_t aead_len,
|
||||
unsigned char *tag, const size_t tag_len);
|
||||
|
||||
int aes_gcm_decrypt(unsigned char *output, const unsigned char *input,
|
||||
size_t input_length, const unsigned char *key,
|
||||
const size_t key_len, const unsigned char *iv,
|
||||
const size_t iv_len);
|
||||
|
||||
#endif
|
||||
#endif /* TLS_AES128_H */
|
||||
|
||||
// End of aes128 PD
|
||||
|
1810
src/tls_builtin.c
1810
src/tls_builtin.c
File diff suppressed because it is too large
Load Diff
2115
src/tls_uecc.c
2115
src/tls_uecc.c
File diff suppressed because it is too large
Load Diff
482
src/tls_uecc.h
482
src/tls_uecc.h
@ -1,46 +1,46 @@
|
||||
#pragma once
|
||||
#include "arch.h"
|
||||
|
||||
#define uECC_SUPPORTS_secp256r1 1
|
||||
#define MG_UECC_SUPPORTS_secp256r1 1
|
||||
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_H_
|
||||
#define _UECC_H_
|
||||
|
||||
/* Platform selection options.
|
||||
If uECC_PLATFORM is not defined, the code will try to guess it based on compiler
|
||||
macros. Possible values for uECC_PLATFORM are defined below: */
|
||||
#define uECC_arch_other 0
|
||||
#define uECC_x86 1
|
||||
#define uECC_x86_64 2
|
||||
#define uECC_arm 3
|
||||
#define uECC_arm_thumb 4
|
||||
#define uECC_arm_thumb2 5
|
||||
#define uECC_arm64 6
|
||||
#define uECC_avr 7
|
||||
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 uECC_WORD_SIZE as appropriate for your platform
|
||||
(1, 4, or 8 bytes). If uECC_WORD_SIZE is not explicitly defined then it will be
|
||||
automatically set based on your platform. */
|
||||
/* 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 uECC_OPTIMIZATION_LEVEL
|
||||
#define uECC_OPTIMIZATION_LEVEL 2
|
||||
#ifndef MG_UECC_OPTIMIZATION_LEVEL
|
||||
#define MG_UECC_OPTIMIZATION_LEVEL 2
|
||||
#endif
|
||||
|
||||
/* uECC_SQUARE_FUNC - If enabled (defined as nonzero), this will cause a
|
||||
/* 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 uECC_SQUARE_FUNC
|
||||
#define uECC_SQUARE_FUNC 0
|
||||
#ifndef MG_UECC_SQUARE_FUNC
|
||||
#define MG_UECC_SQUARE_FUNC 0
|
||||
#endif
|
||||
|
||||
/* uECC_VLI_NATIVE_LITTLE_ENDIAN - If enabled (defined as nonzero), this will
|
||||
/* 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
|
||||
@ -49,111 +49,112 @@ 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
|
||||
uECC_VLI_NATIVE_LITTLE_ENDIAN=1 are incompatible with keys and signatures
|
||||
generated with uECC_VLI_NATIVE_LITTLE_ENDIAN=0; all parties must use the same
|
||||
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 uECC_VLI_NATIVE_LITTLE_ENDIAN
|
||||
#define uECC_VLI_NATIVE_LITTLE_ENDIAN 0
|
||||
#ifndef MG_UECC_VLI_NATIVE_LITTLE_ENDIAN
|
||||
#define MG_UECC_VLI_NATIVE_LITTLE_ENDIAN 0
|
||||
#endif
|
||||
|
||||
/* Curve support selection. Set to 0 to remove that curve. */
|
||||
#ifndef uECC_SUPPORTS_secp160r1
|
||||
#define uECC_SUPPORTS_secp160r1 0
|
||||
#ifndef MG_UECC_SUPPORTS_secp160r1
|
||||
#define MG_UECC_SUPPORTS_secp160r1 0
|
||||
#endif
|
||||
#ifndef uECC_SUPPORTS_secp192r1
|
||||
#define uECC_SUPPORTS_secp192r1 0
|
||||
#ifndef MG_UECC_SUPPORTS_secp192r1
|
||||
#define MG_UECC_SUPPORTS_secp192r1 0
|
||||
#endif
|
||||
#ifndef uECC_SUPPORTS_secp224r1
|
||||
#define uECC_SUPPORTS_secp224r1 0
|
||||
#ifndef MG_UECC_SUPPORTS_secp224r1
|
||||
#define MG_UECC_SUPPORTS_secp224r1 0
|
||||
#endif
|
||||
#ifndef uECC_SUPPORTS_secp256r1
|
||||
#define uECC_SUPPORTS_secp256r1 1
|
||||
#ifndef MG_UECC_SUPPORTS_secp256r1
|
||||
#define MG_UECC_SUPPORTS_secp256r1 1
|
||||
#endif
|
||||
#ifndef uECC_SUPPORTS_secp256k1
|
||||
#define uECC_SUPPORTS_secp256k1 0
|
||||
#ifndef MG_UECC_SUPPORTS_secp256k1
|
||||
#define MG_UECC_SUPPORTS_secp256k1 0
|
||||
#endif
|
||||
|
||||
/* Specifies whether compressed point format is supported.
|
||||
Set to 0 to disable point compression/decompression functions. */
|
||||
#ifndef uECC_SUPPORT_COMPRESSED_POINT
|
||||
#define uECC_SUPPORT_COMPRESSED_POINT 1
|
||||
#ifndef MG_UECC_SUPPORT_COMPRESSED_POINT
|
||||
#define MG_UECC_SUPPORT_COMPRESSED_POINT 1
|
||||
#endif
|
||||
|
||||
struct uECC_Curve_t;
|
||||
typedef const struct uECC_Curve_t *uECC_Curve;
|
||||
struct MG_UECC_Curve_t;
|
||||
typedef const struct MG_UECC_Curve_t *MG_UECC_Curve;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
uECC_Curve uECC_secp160r1(void);
|
||||
#if MG_UECC_SUPPORTS_secp160r1
|
||||
MG_UECC_Curve mg_uecc_secp160r1(void);
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
uECC_Curve uECC_secp192r1(void);
|
||||
#if MG_UECC_SUPPORTS_secp192r1
|
||||
MG_UECC_Curve mg_uecc_secp192r1(void);
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
uECC_Curve uECC_secp224r1(void);
|
||||
#if MG_UECC_SUPPORTS_secp224r1
|
||||
MG_UECC_Curve mg_uecc_secp224r1(void);
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp256r1
|
||||
uECC_Curve uECC_secp256r1(void);
|
||||
#if MG_UECC_SUPPORTS_secp256r1
|
||||
MG_UECC_Curve mg_uecc_secp256r1(void);
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp256k1
|
||||
uECC_Curve uECC_secp256k1(void);
|
||||
#if MG_UECC_SUPPORTS_secp256k1
|
||||
MG_UECC_Curve mg_uecc_secp256k1(void);
|
||||
#endif
|
||||
|
||||
/* uECC_RNG_Function type
|
||||
/* 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 function must be set (using uECC_set_rng()) before
|
||||
calling uECC_make_key() or uECC_sign().
|
||||
A correctly functioning RNG function must be set (using mg_uecc_set_rng())
|
||||
before calling mg_uecc_make_key() or mg_uecc_sign().
|
||||
|
||||
Setting a correctly functioning RNG function improves the resistance to
|
||||
side-channel attacks for uECC_shared_secret() and uECC_sign_deterministic().
|
||||
side-channel attacks for mg_uecc_shared_secret() and
|
||||
mg_uecc_sign_deterministic().
|
||||
|
||||
A correct RNG function is set by default when building for Windows, Linux, or OS
|
||||
X. If you are building on another POSIX-compliant system that supports
|
||||
/dev/random or /dev/urandom, you can define uECC_POSIX to use the predefined
|
||||
/dev/random or /dev/urandom, you can define MG_UECC_POSIX to use the predefined
|
||||
RNG. For embedded platforms there is no predefined RNG function; you must
|
||||
provide your own.
|
||||
*/
|
||||
typedef int (*uECC_RNG_Function)(uint8_t *dest, unsigned size);
|
||||
typedef int (*MG_UECC_RNG_Function)(uint8_t *dest, unsigned size);
|
||||
|
||||
/* uECC_set_rng() function.
|
||||
/* 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.
|
||||
|
||||
On platforms where there is no predefined RNG function (eg embedded platforms),
|
||||
this must be called before uECC_make_key() or uECC_sign() are used.
|
||||
this must be called before mg_uecc_make_key() or mg_uecc_sign() are used.
|
||||
|
||||
Inputs:
|
||||
rng_function - The function that will be used to generate random bytes.
|
||||
*/
|
||||
void uECC_set_rng(uECC_RNG_Function rng_function);
|
||||
void mg_uecc_set_rng(MG_UECC_RNG_Function rng_function);
|
||||
|
||||
/* uECC_get_rng() function.
|
||||
/* mg_uecc_get_rng() function.
|
||||
|
||||
Returns the function that will be used to generate random bytes.
|
||||
*/
|
||||
uECC_RNG_Function uECC_get_rng(void);
|
||||
MG_UECC_RNG_Function mg_uecc_get_rng(void);
|
||||
|
||||
/* uECC_curve_private_key_size() function.
|
||||
/* mg_uecc_curve_private_key_size() function.
|
||||
|
||||
Returns the size of a private key for the curve in bytes.
|
||||
*/
|
||||
int uECC_curve_private_key_size(uECC_Curve curve);
|
||||
int mg_uecc_curve_private_key_size(MG_UECC_Curve curve);
|
||||
|
||||
/* uECC_curve_public_key_size() function.
|
||||
/* mg_uecc_curve_public_key_size() function.
|
||||
|
||||
Returns the size of a public key for the curve in bytes.
|
||||
*/
|
||||
int uECC_curve_public_key_size(uECC_Curve curve);
|
||||
int mg_uecc_curve_public_key_size(MG_UECC_Curve curve);
|
||||
|
||||
/* uECC_make_key() function.
|
||||
/* mg_uecc_make_key() function.
|
||||
Create a public/private key pair.
|
||||
|
||||
Outputs:
|
||||
@ -170,14 +171,15 @@ being non-zero).
|
||||
|
||||
Returns 1 if the key pair was generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve);
|
||||
int mg_uecc_make_key(uint8_t *public_key, uint8_t *private_key,
|
||||
MG_UECC_Curve curve);
|
||||
|
||||
/* uECC_shared_secret() function.
|
||||
/* 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 uECC_valid_public_key(). Note: It is
|
||||
recommended that you hash the result of uECC_shared_secret() before using it for
|
||||
symmetric encryption or HMAC.
|
||||
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.
|
||||
@ -191,11 +193,11 @@ size as the curve size; for example, if the curve is secp256r1, secret must be
|
||||
Returns 1 if the shared secret was generated successfully, 0 if an error
|
||||
occurred.
|
||||
*/
|
||||
int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
|
||||
uint8_t *secret, uECC_Curve curve);
|
||||
int mg_uecc_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
|
||||
uint8_t *secret, MG_UECC_Curve curve);
|
||||
|
||||
#if uECC_SUPPORT_COMPRESSED_POINT
|
||||
/* uECC_compress() function.
|
||||
#if MG_UECC_SUPPORT_COMPRESSED_POINT
|
||||
/* mg_uecc_compress() function.
|
||||
Compress a public key.
|
||||
|
||||
Inputs:
|
||||
@ -206,10 +208,10 @@ Outputs:
|
||||
least (curve size + 1) bytes long; for example, if the curve is secp256r1,
|
||||
compressed must be 33 bytes long.
|
||||
*/
|
||||
void uECC_compress(const uint8_t *public_key, uint8_t *compressed,
|
||||
uECC_Curve curve);
|
||||
void mg_uecc_compress(const uint8_t *public_key, uint8_t *compressed,
|
||||
MG_UECC_Curve curve);
|
||||
|
||||
/* uECC_decompress() function.
|
||||
/* mg_uecc_decompress() function.
|
||||
Decompress a compressed public key.
|
||||
|
||||
Inputs:
|
||||
@ -218,11 +220,11 @@ Inputs:
|
||||
Outputs:
|
||||
public_key - Will be filled in with the decompressed public key.
|
||||
*/
|
||||
void uECC_decompress(const uint8_t *compressed, uint8_t *public_key,
|
||||
uECC_Curve curve);
|
||||
#endif /* uECC_SUPPORT_COMPRESSED_POINT */
|
||||
void mg_uecc_decompress(const uint8_t *compressed, uint8_t *public_key,
|
||||
MG_UECC_Curve curve);
|
||||
#endif /* MG_UECC_SUPPORT_COMPRESSED_POINT */
|
||||
|
||||
/* uECC_valid_public_key() function.
|
||||
/* 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
|
||||
@ -234,9 +236,9 @@ Inputs:
|
||||
|
||||
Returns 1 if the public key is valid, 0 if it is invalid.
|
||||
*/
|
||||
int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve);
|
||||
int mg_uecc_valid_public_key(const uint8_t *public_key, MG_UECC_Curve curve);
|
||||
|
||||
/* uECC_compute_public_key() function.
|
||||
/* mg_uecc_compute_public_key() function.
|
||||
Compute the corresponding public key for a private key.
|
||||
|
||||
Inputs:
|
||||
@ -247,10 +249,10 @@ Outputs:
|
||||
|
||||
Returns 1 if the key was computed successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key,
|
||||
uECC_Curve curve);
|
||||
int mg_uecc_compute_public_key(const uint8_t *private_key, uint8_t *public_key,
|
||||
MG_UECC_Curve curve);
|
||||
|
||||
/* uECC_sign() function.
|
||||
/* 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
|
||||
@ -268,37 +270,37 @@ bytes long.
|
||||
|
||||
Returns 1 if the signature generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash,
|
||||
unsigned hash_size, uint8_t *signature, uECC_Curve curve);
|
||||
int mg_uecc_sign(const uint8_t *private_key, const uint8_t *message_hash,
|
||||
unsigned hash_size, uint8_t *signature, MG_UECC_Curve curve);
|
||||
|
||||
/* uECC_HashContext structure.
|
||||
This is used to pass in an arbitrary hash function to 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.
|
||||
/* 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 uECC_HashContext
|
||||
followed by any hash-specific data. For example:
|
||||
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 {
|
||||
uECC_HashContext uECC;
|
||||
MG_UECC_HashContext uECC;
|
||||
SHA256_CTX ctx;
|
||||
} SHA256_HashContext;
|
||||
|
||||
void init_SHA256(uECC_HashContext *base) {
|
||||
void init_SHA256(MG_UECC_HashContext *base) {
|
||||
SHA256_HashContext *context = (SHA256_HashContext *)base;
|
||||
SHA256_Init(&context->ctx);
|
||||
}
|
||||
|
||||
void update_SHA256(uECC_HashContext *base,
|
||||
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(uECC_HashContext *base, uint8_t *hash_result) {
|
||||
void finish_SHA256(MG_UECC_HashContext *base, uint8_t *hash_result) {
|
||||
SHA256_HashContext *context = (SHA256_HashContext *)base;
|
||||
SHA256_Final(hash_result, &context->ctx);
|
||||
}
|
||||
@ -307,14 +309,14 @@ void finish_SHA256(uECC_HashContext *base, uint8_t *hash_result) {
|
||||
{
|
||||
uint8_t tmp[32 + 32 + 64];
|
||||
SHA256_HashContext ctx = {{&init_SHA256, &update_SHA256, &finish_SHA256, 64,
|
||||
32, tmp}}; uECC_sign_deterministic(key, message_hash, &ctx.uECC, signature);
|
||||
32, tmp}}; mg_uecc_sign_deterministic(key, message_hash, &ctx.uECC, signature);
|
||||
}
|
||||
*/
|
||||
typedef struct uECC_HashContext {
|
||||
void (*init_hash)(const struct uECC_HashContext *context);
|
||||
void (*update_hash)(const struct uECC_HashContext *context,
|
||||
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 uECC_HashContext *context,
|
||||
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. */
|
||||
@ -322,11 +324,11 @@ typedef struct uECC_HashContext {
|
||||
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. */
|
||||
} uECC_HashContext;
|
||||
} MG_UECC_HashContext;
|
||||
|
||||
/* uECC_sign_deterministic() function.
|
||||
/* 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 uECC_set_rng()
|
||||
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.
|
||||
|
||||
@ -346,12 +348,12 @@ Outputs:
|
||||
|
||||
Returns 1 if the signature generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_sign_deterministic(const uint8_t *private_key,
|
||||
const uint8_t *message_hash, unsigned hash_size,
|
||||
const uECC_HashContext *hash_context,
|
||||
uint8_t *signature, uECC_Curve curve);
|
||||
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);
|
||||
|
||||
/* uECC_verify() function.
|
||||
/* mg_uecc_verify() function.
|
||||
Verify an ECDSA signature.
|
||||
|
||||
Usage: Compute the hash of the signed data using the same hash as the signer and
|
||||
@ -366,8 +368,9 @@ Inputs:
|
||||
|
||||
Returns 1 if the signature is valid, 0 if it is invalid.
|
||||
*/
|
||||
int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash,
|
||||
unsigned hash_size, const uint8_t *signature, uECC_Curve curve);
|
||||
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" */
|
||||
@ -380,153 +383,162 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash,
|
||||
#ifndef _UECC_VLI_H_
|
||||
#define _UECC_VLI_H_
|
||||
|
||||
//#include "types.h"
|
||||
//#include "uECC.h"
|
||||
// #include "types.h"
|
||||
// #include "uECC.h"
|
||||
|
||||
/* Functions for raw large-integer manipulation. These are only available
|
||||
if uECC.c is compiled with uECC_ENABLE_VLI_API defined to 1. */
|
||||
#ifndef uECC_ENABLE_VLI_API
|
||||
#define uECC_ENABLE_VLI_API 0
|
||||
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 uECC_ENABLE_VLI_API
|
||||
#if MG_UECC_ENABLE_VLI_API
|
||||
|
||||
void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words);
|
||||
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. */
|
||||
uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words);
|
||||
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. */
|
||||
uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit);
|
||||
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 uECC_vli_numBits(const uECC_word_t *vli,
|
||||
const wordcount_t max_words);
|
||||
bitcount_t mg_uecc_vli_numBits(const mg_uecc_word_t *vli,
|
||||
const wordcount_t max_words);
|
||||
|
||||
/* Sets dest = src. */
|
||||
void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src,
|
||||
wordcount_t num_words);
|
||||
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 */
|
||||
uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right,
|
||||
wordcount_t num_words);
|
||||
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 uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right,
|
||||
wordcount_t num_words);
|
||||
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 uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words);
|
||||
void mg_uecc_vli_rshift1(mg_uecc_word_t *vli, wordcount_t num_words);
|
||||
|
||||
/* Computes result = left + right, returning carry. Can modify in place. */
|
||||
uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, wordcount_t num_words);
|
||||
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. */
|
||||
uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, wordcount_t num_words);
|
||||
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 uECC_vli_mult(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, wordcount_t num_words);
|
||||
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 uECC_vli_square(uECC_word_t *result, const uECC_word_t *left,
|
||||
wordcount_t num_words);
|
||||
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 uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
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 uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
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 uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
|
||||
const uECC_word_t *mod, wordcount_t num_words);
|
||||
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 uECC_vli_mmod_fast(uECC_word_t *result, uECC_word_t *product,
|
||||
uECC_Curve curve);
|
||||
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 uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
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 uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, uECC_Curve curve);
|
||||
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 uECC_vli_modSquare(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *mod, wordcount_t num_words);
|
||||
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 uECC_vli_modSquare_fast(uECC_word_t *result, const uECC_word_t *left,
|
||||
uECC_Curve curve);
|
||||
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 uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
|
||||
const uECC_word_t *mod, wordcount_t num_words);
|
||||
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 uECC_SUPPORT_COMPRESSED_POINT
|
||||
#if MG_UECC_SUPPORT_COMPRESSED_POINT
|
||||
/* Calculates a = sqrt(a) (mod curve->p) */
|
||||
void uECC_vli_mod_sqrt(uECC_word_t *a, uECC_Curve curve);
|
||||
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 uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
|
||||
const uECC_word_t *native);
|
||||
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 uECC_vli_bytesToNative(uECC_word_t *native, const uint8_t *bytes,
|
||||
int num_bytes);
|
||||
void mg_uecc_vli_bytesToNative(mg_uecc_word_t *native, const uint8_t *bytes,
|
||||
int num_bytes);
|
||||
|
||||
unsigned uECC_curve_num_words(uECC_Curve curve);
|
||||
unsigned uECC_curve_num_bytes(uECC_Curve curve);
|
||||
unsigned uECC_curve_num_bits(uECC_Curve curve);
|
||||
unsigned uECC_curve_num_n_words(uECC_Curve curve);
|
||||
unsigned uECC_curve_num_n_bytes(uECC_Curve curve);
|
||||
unsigned uECC_curve_num_n_bits(uECC_Curve curve);
|
||||
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 uECC_word_t *uECC_curve_p(uECC_Curve curve);
|
||||
const uECC_word_t *uECC_curve_n(uECC_Curve curve);
|
||||
const uECC_word_t *uECC_curve_G(uECC_Curve curve);
|
||||
const uECC_word_t *uECC_curve_b(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 uECC_valid_point(const uECC_word_t *point, 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 uECC_point_mult(uECC_word_t *result, const uECC_word_t *point,
|
||||
const uECC_word_t *scalar, uECC_Curve curve);
|
||||
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 uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
|
||||
wordcount_t num_words);
|
||||
int mg_uecc_generate_random_int(mg_uecc_word_t *random,
|
||||
const mg_uecc_word_t *top,
|
||||
wordcount_t num_words);
|
||||
|
||||
#endif /* uECC_ENABLE_VLI_API */
|
||||
#endif /* MG_UECC_ENABLE_VLI_API */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
@ -539,101 +551,103 @@ int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
|
||||
#ifndef _UECC_TYPES_H_
|
||||
#define _UECC_TYPES_H_
|
||||
|
||||
#ifndef uECC_PLATFORM
|
||||
#ifndef MG_UECC_PLATFORM
|
||||
#if defined(__AVR__) && __AVR__
|
||||
#define uECC_PLATFORM uECC_avr
|
||||
#define MG_UECC_PLATFORM mg_uecc_avr
|
||||
#elif defined(__thumb2__) || \
|
||||
defined(_M_ARMT) /* I think MSVC only supports Thumb-2 targets */
|
||||
#define uECC_PLATFORM uECC_arm_thumb2
|
||||
#define MG_UECC_PLATFORM mg_uecc_arm_thumb2
|
||||
#elif defined(__thumb__)
|
||||
#define uECC_PLATFORM uECC_arm_thumb
|
||||
#define MG_UECC_PLATFORM mg_uecc_arm_thumb
|
||||
#elif defined(__arm__) || defined(_M_ARM)
|
||||
#define uECC_PLATFORM uECC_arm
|
||||
#define MG_UECC_PLATFORM mg_uecc_arm
|
||||
#elif defined(__aarch64__)
|
||||
#define uECC_PLATFORM uECC_arm64
|
||||
#define MG_UECC_PLATFORM mg_uecc_arm64
|
||||
#elif defined(__i386__) || defined(_M_IX86) || defined(_X86_) || \
|
||||
defined(__I86__)
|
||||
#define uECC_PLATFORM uECC_x86
|
||||
#define MG_UECC_PLATFORM mg_uecc_x86
|
||||
#elif defined(__amd64__) || defined(_M_X64)
|
||||
#define uECC_PLATFORM uECC_x86_64
|
||||
#define MG_UECC_PLATFORM mg_uecc_x86_64
|
||||
#else
|
||||
#define uECC_PLATFORM uECC_arch_other
|
||||
#define MG_UECC_PLATFORM mg_uecc_arch_other
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef uECC_ARM_USE_UMAAL
|
||||
#if (uECC_PLATFORM == uECC_arm) && (__ARM_ARCH >= 6)
|
||||
#define uECC_ARM_USE_UMAAL 1
|
||||
#elif (uECC_PLATFORM == uECC_arm_thumb2) && (__ARM_ARCH >= 6) && \
|
||||
#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 uECC_ARM_USE_UMAAL 1
|
||||
#define MG_UECC_ARM_USE_UMAAL 1
|
||||
#else
|
||||
#define uECC_ARM_USE_UMAAL 0
|
||||
#define MG_UECC_ARM_USE_UMAAL 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef uECC_WORD_SIZE
|
||||
#if uECC_PLATFORM == uECC_avr
|
||||
#define uECC_WORD_SIZE 1
|
||||
#elif (uECC_PLATFORM == uECC_x86_64 || uECC_PLATFORM == uECC_arm64)
|
||||
#define uECC_WORD_SIZE 8
|
||||
#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 uECC_WORD_SIZE 4
|
||||
#define MG_UECC_WORD_SIZE 4
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (uECC_WORD_SIZE != 1) && (uECC_WORD_SIZE != 4) && (uECC_WORD_SIZE != 8)
|
||||
#error "Unsupported value for uECC_WORD_SIZE"
|
||||
#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 ((uECC_PLATFORM == uECC_avr) && (uECC_WORD_SIZE != 1))
|
||||
#pragma message("uECC_WORD_SIZE must be 1 for AVR")
|
||||
#undef uECC_WORD_SIZE
|
||||
#define uECC_WORD_SIZE 1
|
||||
#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 ((uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb || \
|
||||
uECC_PLATFORM == uECC_arm_thumb2) && \
|
||||
(uECC_WORD_SIZE != 4))
|
||||
#pragma message("uECC_WORD_SIZE must be 4 for ARM")
|
||||
#undef uECC_WORD_SIZE
|
||||
#define uECC_WORD_SIZE 4
|
||||
#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 (uECC_WORD_SIZE == 1)
|
||||
#if (MG_UECC_WORD_SIZE == 1)
|
||||
|
||||
typedef uint8_t uECC_word_t;
|
||||
typedef uint16_t uECC_dword_t;
|
||||
typedef uint8_t mg_uecc_word_t;
|
||||
typedef uint16_t mg_uecc_dword_t;
|
||||
|
||||
#define HIGH_BIT_SET 0x80
|
||||
#define uECC_WORD_BITS 8
|
||||
#define uECC_WORD_BITS_SHIFT 3
|
||||
#define uECC_WORD_BITS_MASK 0x07
|
||||
#define MG_UECC_WORD_BITS 8
|
||||
#define MG_UECC_WORD_BITS_SHIFT 3
|
||||
#define MG_UECC_WORD_BITS_MASK 0x07
|
||||
|
||||
#elif (uECC_WORD_SIZE == 4)
|
||||
#elif (MG_UECC_WORD_SIZE == 4)
|
||||
|
||||
typedef uint32_t uECC_word_t;
|
||||
typedef uint64_t uECC_dword_t;
|
||||
typedef uint32_t mg_uecc_word_t;
|
||||
typedef uint64_t mg_uecc_dword_t;
|
||||
|
||||
#define HIGH_BIT_SET 0x80000000
|
||||
#define uECC_WORD_BITS 32
|
||||
#define uECC_WORD_BITS_SHIFT 5
|
||||
#define uECC_WORD_BITS_MASK 0x01F
|
||||
#define MG_UECC_WORD_BITS 32
|
||||
#define MG_UECC_WORD_BITS_SHIFT 5
|
||||
#define MG_UECC_WORD_BITS_MASK 0x01F
|
||||
|
||||
#elif (uECC_WORD_SIZE == 8)
|
||||
#elif (MG_UECC_WORD_SIZE == 8)
|
||||
|
||||
typedef uint64_t uECC_word_t;
|
||||
typedef uint64_t mg_uecc_word_t;
|
||||
|
||||
#define HIGH_BIT_SET 0x8000000000000000U
|
||||
#define uECC_WORD_BITS 64
|
||||
#define uECC_WORD_BITS_SHIFT 6
|
||||
#define uECC_WORD_BITS_MASK 0x03F
|
||||
#define MG_UECC_WORD_BITS 64
|
||||
#define MG_UECC_WORD_BITS_SHIFT 6
|
||||
#define MG_UECC_WORD_BITS_MASK 0x03F
|
||||
|
||||
#endif /* uECC_WORD_SIZE */
|
||||
#endif /* MG_UECC_WORD_SIZE */
|
||||
|
||||
#endif /* _UECC_TYPES_H_ */
|
||||
// End of uecc BSD-2
|
||||
|
246
src/tls_x25519.c
Normal file
246
src/tls_x25519.c
Normal file
@ -0,0 +1,246 @@
|
||||
/**
|
||||
* Adapted from STROBE: https://strobe.sourceforge.io/
|
||||
* Copyright (c) 2015-2016 Cryptography Research, Inc.
|
||||
* Author: Mike Hamburg
|
||||
* License: MIT License
|
||||
*/
|
||||
#include "tls_x25519.h"
|
||||
|
||||
const uint8_t X25519_BASE_POINT[X25519_BYTES] = {9};
|
||||
|
||||
#define X25519_WBITS 32
|
||||
|
||||
typedef uint32_t limb_t;
|
||||
typedef uint64_t dlimb_t;
|
||||
typedef int64_t sdlimb_t;
|
||||
#define LIMB(x) (uint32_t)(x##ull), (uint32_t) ((x##ull) >> 32)
|
||||
|
||||
#define NLIMBS (256 / X25519_WBITS)
|
||||
typedef limb_t fe[NLIMBS];
|
||||
|
||||
static limb_t umaal(limb_t *carry, limb_t acc, limb_t mand, limb_t mier) {
|
||||
dlimb_t tmp = (dlimb_t) mand * mier + acc + *carry;
|
||||
*carry = (limb_t) (tmp >> X25519_WBITS);
|
||||
return (limb_t) tmp;
|
||||
}
|
||||
|
||||
// These functions are implemented in terms of umaal on ARM
|
||||
static limb_t adc(limb_t *carry, limb_t acc, limb_t mand) {
|
||||
dlimb_t total = (dlimb_t) *carry + acc + mand;
|
||||
*carry = (limb_t) (total >> X25519_WBITS);
|
||||
return (limb_t) total;
|
||||
}
|
||||
|
||||
static limb_t adc0(limb_t *carry, limb_t acc) {
|
||||
dlimb_t total = (dlimb_t) *carry + acc;
|
||||
*carry = (limb_t) (total >> X25519_WBITS);
|
||||
return (limb_t) total;
|
||||
}
|
||||
|
||||
// - Precondition: carry is small.
|
||||
// - Invariant: result of propagate is < 2^255 + 1 word
|
||||
// - In particular, always less than 2p.
|
||||
// - Also, output x >= min(x,19)
|
||||
static void propagate(fe x, limb_t over) {
|
||||
unsigned i;
|
||||
limb_t carry;
|
||||
over = x[NLIMBS - 1] >> (X25519_WBITS - 1) | over << 1;
|
||||
x[NLIMBS - 1] &= ~((limb_t) 1 << (X25519_WBITS - 1));
|
||||
|
||||
carry = over * 19;
|
||||
for (i = 0; i < NLIMBS; i++) {
|
||||
x[i] = adc0(&carry, x[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void add(fe out, const fe a, const fe b) {
|
||||
unsigned i;
|
||||
limb_t carry = 0;
|
||||
for (i = 0; i < NLIMBS; i++) {
|
||||
out[i] = adc(&carry, a[i], b[i]);
|
||||
}
|
||||
propagate(out, carry);
|
||||
}
|
||||
|
||||
static void sub(fe out, const fe a, const fe b) {
|
||||
unsigned i;
|
||||
sdlimb_t carry = -38;
|
||||
for (i = 0; i < NLIMBS; i++) {
|
||||
carry = carry + a[i] - b[i];
|
||||
out[i] = (limb_t) carry;
|
||||
carry >>= X25519_WBITS;
|
||||
}
|
||||
propagate(out, (limb_t) (1 + carry));
|
||||
}
|
||||
|
||||
// `b` can contain less than 8 limbs, thus we use `limb_t *` instead of `fe`
|
||||
// to avoid build warnings
|
||||
static void mul(fe out, const fe a, const limb_t *b, unsigned nb) {
|
||||
limb_t accum[2 * NLIMBS] = {0};
|
||||
unsigned i, j;
|
||||
|
||||
limb_t carry2;
|
||||
for (i = 0; i < nb; i++) {
|
||||
limb_t mand = b[i];
|
||||
carry2 = 0;
|
||||
for (j = 0; j < NLIMBS; j++) {
|
||||
limb_t tmp; // "a" may be misaligned
|
||||
memcpy(&tmp, &a[j], sizeof(tmp)); // So make an aligned copy
|
||||
accum[i + j] = umaal(&carry2, accum[i + j], mand, tmp);
|
||||
}
|
||||
accum[i + j] = carry2;
|
||||
}
|
||||
|
||||
carry2 = 0;
|
||||
for (j = 0; j < NLIMBS; j++) {
|
||||
out[j] = umaal(&carry2, accum[j], 38, accum[j + NLIMBS]);
|
||||
}
|
||||
propagate(out, carry2);
|
||||
}
|
||||
|
||||
static void sqr(fe out, const fe a) {
|
||||
mul(out, a, a, NLIMBS);
|
||||
}
|
||||
static void mul1(fe out, const fe a) {
|
||||
mul(out, a, out, NLIMBS);
|
||||
}
|
||||
static void sqr1(fe a) {
|
||||
mul1(a, a);
|
||||
}
|
||||
|
||||
static void condswap(limb_t a[2 * NLIMBS], limb_t b[2 * NLIMBS],
|
||||
limb_t doswap) {
|
||||
unsigned i;
|
||||
for (i = 0; i < 2 * NLIMBS; i++) {
|
||||
limb_t xor_ab = (a[i] ^ b[i]) & doswap;
|
||||
a[i] ^= xor_ab;
|
||||
b[i] ^= xor_ab;
|
||||
}
|
||||
}
|
||||
|
||||
// Canonicalize a field element x, reducing it to the least residue which is
|
||||
// congruent to it mod 2^255-19
|
||||
// - Precondition: x < 2^255 + 1 word
|
||||
static limb_t canon(fe x) {
|
||||
// First, add 19.
|
||||
unsigned i;
|
||||
limb_t carry0 = 19;
|
||||
limb_t res;
|
||||
sdlimb_t carry;
|
||||
for (i = 0; i < NLIMBS; i++) {
|
||||
x[i] = adc0(&carry0, x[i]);
|
||||
}
|
||||
propagate(x, carry0);
|
||||
|
||||
// Here, 19 <= x2 < 2^255
|
||||
// - This is because we added 19, so before propagate it can't be less
|
||||
// than 19. After propagate, it still can't be less than 19, because if
|
||||
// propagate does anything it adds 19.
|
||||
// - We know that the high bit must be clear, because either the input was ~
|
||||
// 2^255 + one word + 19 (in which case it propagates to at most 2 words) or
|
||||
// it was < 2^255. So now, if we subtract 19, we will get back to something in
|
||||
// [0,2^255-19).
|
||||
carry = -19;
|
||||
res = 0;
|
||||
for (i = 0; i < NLIMBS; i++) {
|
||||
carry += x[i];
|
||||
res |= x[i] = (limb_t) carry;
|
||||
carry >>= X25519_WBITS;
|
||||
}
|
||||
return (limb_t) (((dlimb_t) res - 1) >> X25519_WBITS);
|
||||
}
|
||||
|
||||
static const limb_t a24[1] = {121665};
|
||||
|
||||
static void ladder_part1(fe xs[5]) {
|
||||
limb_t *x2 = xs[0], *z2 = xs[1], *x3 = xs[2], *z3 = xs[3], *t1 = xs[4];
|
||||
add(t1, x2, z2); // t1 = A
|
||||
sub(z2, x2, z2); // z2 = B
|
||||
add(x2, x3, z3); // x2 = C
|
||||
sub(z3, x3, z3); // z3 = D
|
||||
mul1(z3, t1); // z3 = DA
|
||||
mul1(x2, z2); // x3 = BC
|
||||
add(x3, z3, x2); // x3 = DA+CB
|
||||
sub(z3, z3, x2); // z3 = DA-CB
|
||||
sqr1(t1); // t1 = AA
|
||||
sqr1(z2); // z2 = BB
|
||||
sub(x2, t1, z2); // x2 = E = AA-BB
|
||||
mul(z2, x2, a24, sizeof(a24) / sizeof(a24[0])); // z2 = E*a24
|
||||
add(z2, z2, t1); // z2 = E*a24 + AA
|
||||
}
|
||||
|
||||
static void ladder_part2(fe xs[5], const fe x1) {
|
||||
limb_t *x2 = xs[0], *z2 = xs[1], *x3 = xs[2], *z3 = xs[3], *t1 = xs[4];
|
||||
sqr1(z3); // z3 = (DA-CB)^2
|
||||
mul1(z3, x1); // z3 = x1 * (DA-CB)^2
|
||||
sqr1(x3); // x3 = (DA+CB)^2
|
||||
mul1(z2, x2); // z2 = AA*(E*a24+AA)
|
||||
sub(x2, t1, x2); // x2 = BB again
|
||||
mul1(x2, t1); // x2 = AA*BB
|
||||
}
|
||||
|
||||
static void x25519_core(fe xs[5], const uint8_t scalar[X25519_BYTES],
|
||||
const uint8_t *x1, int clamp) {
|
||||
int i;
|
||||
limb_t swap = 0;
|
||||
limb_t *x2 = xs[0], *x3 = xs[2], *z3 = xs[3];
|
||||
memset(xs, 0, 4 * sizeof(fe));
|
||||
x2[0] = z3[0] = 1;
|
||||
memcpy(x3, x1, sizeof(fe));
|
||||
|
||||
for (i = 255; i >= 0; i--) {
|
||||
uint8_t bytei = scalar[i / 8];
|
||||
limb_t doswap;
|
||||
if (clamp) {
|
||||
if (i / 8 == 0) {
|
||||
bytei &= (uint8_t) ~7U;
|
||||
} else if (i / 8 == X25519_BYTES - 1) {
|
||||
bytei &= 0x7F;
|
||||
bytei |= 0x40;
|
||||
}
|
||||
}
|
||||
doswap = 0 - (limb_t) ((bytei >> (i % 8)) & 1);
|
||||
condswap(x2, x3, swap ^ doswap);
|
||||
swap = doswap;
|
||||
|
||||
ladder_part1(xs);
|
||||
ladder_part2(xs, (const limb_t *) x1);
|
||||
}
|
||||
condswap(x2, x3, swap);
|
||||
}
|
||||
|
||||
int mg_tls_x25519(uint8_t out[X25519_BYTES], const uint8_t scalar[X25519_BYTES],
|
||||
const uint8_t x1[X25519_BYTES], int clamp) {
|
||||
int i, ret;
|
||||
fe xs[5];
|
||||
limb_t *x2, *z2, *z3, *prev;
|
||||
static const struct {
|
||||
uint8_t a, c, n;
|
||||
} steps[13] = {{2, 1, 1}, {2, 1, 1}, {4, 2, 3}, {2, 4, 6}, {3, 1, 1},
|
||||
{3, 2, 12}, {4, 3, 25}, {2, 3, 25}, {2, 4, 50}, {3, 2, 125},
|
||||
{3, 1, 2}, {3, 1, 2}, {3, 1, 1}};
|
||||
x25519_core(xs, scalar, x1, clamp);
|
||||
|
||||
// Precomputed inversion chain
|
||||
x2 = xs[0];
|
||||
z2 = xs[1];
|
||||
z3 = xs[3];
|
||||
|
||||
prev = z2;
|
||||
for (i = 0; i < 13; i++) {
|
||||
int j;
|
||||
limb_t *a = xs[steps[i].a];
|
||||
for (j = steps[i].n; j > 0; j--) {
|
||||
sqr(a, prev);
|
||||
prev = a;
|
||||
}
|
||||
mul1(a, xs[steps[i].c]);
|
||||
}
|
||||
|
||||
// Here prev = z3
|
||||
// x2 /= z2
|
||||
mul((limb_t *) out, x2, z3, NLIMBS);
|
||||
ret = (int) canon((limb_t *) out);
|
||||
if (!clamp) ret = 0;
|
||||
return ret;
|
||||
}
|
13
src/tls_x25519.h
Normal file
13
src/tls_x25519.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef TLS_X15519_H
|
||||
#define TLS_X15519_H
|
||||
|
||||
#include "arch.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 */
|
8
test/certs/ca.crt
Normal file
8
test/certs/ca.crt
Normal file
@ -0,0 +1,8 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBFTCBvAIJAJiASLWtAz5MMAoGCCqGSM49BAMCMBMxETAPBgNVBAMMCE1vbmdv
|
||||
b3NlMB4XDTI0MDMyNTExNTU0NVoXDTM0MDMyMzExNTU0NVowEzERMA8GA1UEAwwI
|
||||
TW9uZ29vc2UwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARaohnchUT4QTRIYKBX
|
||||
1k0n3/PDwpXwiPyJIb+Wwfsmx0Y74KU7xGZLHK2C1PmIADVnTf3z304E97AXM+WV
|
||||
3gkOMAoGCCqGSM49BAMCA0gAMEUCIQDJ0GYwCwucIKl+K/zRgptW6HVxD5y6+hu4
|
||||
YBP9j+vwCAIgWJswYluq0szGxmfKnSXyTDioA1XrDhCVjYGO61U60Gk=
|
||||
-----END CERTIFICATE-----
|
5
test/certs/ca.key
Normal file
5
test/certs/ca.key
Normal file
@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIHtFV1AGKDqJRVBg3hQEmkHQDlXxCDFpIJ4b7UUyUtHRoAoGCCqGSM49
|
||||
AwEHoUQDQgAEWqIZ3IVE+EE0SGCgV9ZNJ9/zw8KV8Ij8iSG/lsH7JsdGO+ClO8Rm
|
||||
SxytgtT5iAA1Z039899OBPewFzPlld4JDg==
|
||||
-----END EC PRIVATE KEY-----
|
1
test/certs/ca.srl
Normal file
1
test/certs/ca.srl
Normal file
@ -0,0 +1 @@
|
||||
96EAA481EB95FF30
|
9
test/certs/client.crt
Normal file
9
test/certs/client.crt
Normal file
@ -0,0 +1,9 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBLTCB1KADAgECAgkAluqkgeuV/zAwCgYIKoZIzj0EAwIwEzERMA8GA1UEAwwI
|
||||
TW9uZ29vc2UwHhcNMjQwMzI1MTE1NTQ1WhcNMjQwNDI0MTE1NTQ1WjAMMQowCAYD
|
||||
VQQDDAFjMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoyB/9kTJJnPLlLFrQmME
|
||||
6LMvCpjp05MuSTOvEmXqfWH+eC2e0bb6h7YIW+lcOrVQhDEt6xKFs1rqKUR0lgou
|
||||
/6MYMBYwFAYDVR0RBA0wC4IJbG9jYWxob3N0MAoGCCqGSM49BAMCA0gAMEUCIQDy
|
||||
11QWTyWuTq6avrsVi4lWfjMQSm14RxtyYUiStaahnwIgcXrf5MeOlupWLxPqEZTz
|
||||
uOejUi45wZ6m3S1BLa31g3Y=
|
||||
-----END CERTIFICATE-----
|
7
test/certs/client.csr
Normal file
7
test/certs/client.csr
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIHGMG4CAQAwDDEKMAgGA1UEAwwBYzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA
|
||||
BKMgf/ZEySZzy5Sxa0JjBOizLwqY6dOTLkkzrxJl6n1h/ngtntG2+oe2CFvpXDq1
|
||||
UIQxLesShbNa6ilEdJYKLv+gADAKBggqhkjOPQQDAgNIADBFAiBDSG3wDIJaEn5c
|
||||
PU+4WLGJ8+nzTewHGtpQELOXWURxLQIhAP5BocCQyrGW/5dEc/VWMgqH2eznZJcT
|
||||
ftb9Tk6I6Pjx
|
||||
-----END CERTIFICATE REQUEST-----
|
5
test/certs/client.key
Normal file
5
test/certs/client.key
Normal file
@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIPEthf+Qq9dXJBxSZuYr2WhgzuhrDfMaD1kQzeKHZFfDoAoGCCqGSM49
|
||||
AwEHoUQDQgAEoyB/9kTJJnPLlLFrQmME6LMvCpjp05MuSTOvEmXqfWH+eC2e0bb6
|
||||
h7YIW+lcOrVQhDEt6xKFs1rqKUR0lgou/w==
|
||||
-----END EC PRIVATE KEY-----
|
36
test/certs/generate.sh
Normal file
36
test/certs/generate.sh
Normal file
@ -0,0 +1,36 @@
|
||||
#/bin/sh
|
||||
#
|
||||
# Geneate self-signed ECC certificates
|
||||
|
||||
cd `dirname $0`
|
||||
|
||||
# Create cnf for adding SAN DNS:localhost
|
||||
# See https://security.stackexchange.com/questions/190905/subject-alternative-name-in-certificate-signing-request-apparently-does-not-surv
|
||||
cat > cnf <<EOF
|
||||
[SAN]
|
||||
subjectAltName=DNS:localhost
|
||||
EOF
|
||||
|
||||
# Generate CA
|
||||
# Important: CN names must be different for CA and client/server certs
|
||||
openssl ecparam -noout -name prime256v1 -genkey -out ca.key
|
||||
openssl req -x509 -new -key ca.key -days 3650 -subj /CN=Mongoose -out ca.crt
|
||||
|
||||
# Generate server cert
|
||||
openssl ecparam -noout -name prime256v1 -genkey -out server.key
|
||||
openssl req -new -sha256 -key server.key -days 3650 -subj /CN=s -out server.csr
|
||||
openssl x509 -req -sha256 -in server.csr -extensions SAN -extfile cnf \
|
||||
-CAkey ca.key -CA ca.crt -CAcreateserial -out server.crt
|
||||
|
||||
# Generate client cert
|
||||
openssl ecparam -noout -name prime256v1 -genkey -out client.key
|
||||
openssl req -new -sha256 -key client.key -days 3650 -subj /CN=c -out client.csr
|
||||
openssl x509 -req -sha256 -in client.csr -extensions SAN -extfile cnf \
|
||||
-CAkey ca.key -CA ca.crt -CAcreateserial -out client.crt
|
||||
|
||||
# Verify
|
||||
openssl verify -verbose -CAfile ca.crt server.crt
|
||||
openssl verify -verbose -CAfile ca.crt client.crt
|
||||
|
||||
# Inspect
|
||||
# openssl x509 -text -noout -ext subjectAltName -in server.crt
|
9
test/certs/server.crt
Normal file
9
test/certs/server.crt
Normal file
@ -0,0 +1,9 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBLTCB1KADAgECAgkAluqkgeuV/y8wCgYIKoZIzj0EAwIwEzERMA8GA1UEAwwI
|
||||
TW9uZ29vc2UwHhcNMjQwMzI1MTE1NTQ1WhcNMjQwNDI0MTE1NTQ1WjAMMQowCAYD
|
||||
VQQDDAFzMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEMExDcDCj1g8MeQrY+Ccy
|
||||
voozGUcp7pi9M09q5GKYJ++WOEuEHDqnu4vEr/PQdgGhmeA5JmWEsztz1f0XgNuK
|
||||
MaMYMBYwFAYDVR0RBA0wC4IJbG9jYWxob3N0MAoGCCqGSM49BAMCA0gAMEUCIQCn
|
||||
K8fWr7ULIpU3Dq5IDm6NpNLd/fv4A5it0H0Un9noEAIgPdeWcFVsL7YrGfs0QkWV
|
||||
y4ES/uFAj0jdQy8Vm+jzfD8=
|
||||
-----END CERTIFICATE-----
|
7
test/certs/server.csr
Normal file
7
test/certs/server.csr
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIHFMG4CAQAwDDEKMAgGA1UEAwwBczBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA
|
||||
BDBMQ3Awo9YPDHkK2PgnMr6KMxlHKe6YvTNPauRimCfvljhLhBw6p7uLxK/z0HYB
|
||||
oZngOSZlhLM7c9X9F4DbijGgADAKBggqhkjOPQQDAgNHADBEAiB4+PwVzRQn4dSE
|
||||
I958FyxOJjKlKQ9DjBZCOStqrp2IugIgbAJG26EqDew7MvZWLtCR6ug6qBU2/hjG
|
||||
0QDyaZrCHeQ=
|
||||
-----END CERTIFICATE REQUEST-----
|
5
test/certs/server.key
Normal file
5
test/certs/server.key
Normal file
@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIFw94mvaH1YQyHWQRMNLU62csD8nu9GHJH5mKkiuJpPDoAoGCCqGSM49
|
||||
AwEHoUQDQgAEMExDcDCj1g8MeQrY+CcyvoozGUcp7pi9M09q5GKYJ++WOEuEHDqn
|
||||
u4vEr/PQdgGhmeA5JmWEsztz1f0XgNuKMQ==
|
||||
-----END EC PRIVATE KEY-----
|
@ -16,40 +16,6 @@ static int s_num_tests = 0;
|
||||
|
||||
#define FETCH_BUF_SIZE (256 * 1024)
|
||||
|
||||
// Self-signed CA, CERT, KEY
|
||||
const char *s_tls_ca =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIBqjCCAU+gAwIBAgIUESoOPGqMhf9uarzblVFwzrQweMcwCgYIKoZIzj0EAwIw\n"
|
||||
"RDELMAkGA1UEBhMCSUUxDzANBgNVBAcMBkR1YmxpbjEQMA4GA1UECgwHQ2VzYW50\n"
|
||||
"YTESMBAGA1UEAwwJVGVzdCBSb290MCAXDTIwMDUwOTIxNTE0NFoYDzIwNTAwNTA5\n"
|
||||
"MjE1MTQ0WjBEMQswCQYDVQQGEwJJRTEPMA0GA1UEBwwGRHVibGluMRAwDgYDVQQK\n"
|
||||
"DAdDZXNhbnRhMRIwEAYDVQQDDAlUZXN0IFJvb3QwWTATBgcqhkjOPQIBBggqhkjO\n"
|
||||
"PQMBBwNCAAQsq9ECZiSW1xI+CVBP8VDuUehVA166sR2YsnJ5J6gbMQ1dUCH/QvLa\n"
|
||||
"dBdeU7JlQcH8hN5KEbmM9BnZxMor6ussox0wGzAMBgNVHRMEBTADAQH/MAsGA1Ud\n"
|
||||
"DwQEAwIBrjAKBggqhkjOPQQDAgNJADBGAiEAnHFsAIwGQQyRL81B04dH6d86Iq0l\n"
|
||||
"fL8OKzndegxOaB0CIQCPwSIwEGFdURDqCC0CY2dnMrUGY5ZXu3hHCojZGS7zvg==\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
const char *s_tls_cert =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIBhzCCASygAwIBAgIUbnMoVd8TtWH1T09dANkK2LU6IUswCgYIKoZIzj0EAwIw\n"
|
||||
"RDELMAkGA1UEBhMCSUUxDzANBgNVBAcMBkR1YmxpbjEQMA4GA1UECgwHQ2VzYW50\n"
|
||||
"YTESMBAGA1UEAwwJVGVzdCBSb290MB4XDTIwMDUwOTIxNTE0OVoXDTMwMDUwOTIx\n"
|
||||
"NTE0OVowETEPMA0GA1UEAwwGc2VydmVyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\n"
|
||||
"QgAEkuBGnInDN6l06zVVQ1VcrOvH5FDu9MC6FwJc2e201P8hEpq0Q/SJS2nkbSuW\n"
|
||||
"H/wBTTBaeXN2uhlBzMUWK790KKMvMC0wCQYDVR0TBAIwADALBgNVHQ8EBAMCA6gw\n"
|
||||
"EwYDVR0lBAwwCgYIKwYBBQUHAwEwCgYIKoZIzj0EAwIDSQAwRgIhAPo6xx7LjCdZ\n"
|
||||
"QY133XvLjAgVFrlucOZHONFVQuDXZsjwAiEAzHBNligA08c5U3SySYcnkhurGg50\n"
|
||||
"BllCI0eYQ9ggp/o=\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
const char *s_tls_key =
|
||||
"-----BEGIN PRIVATE KEY-----\n"
|
||||
"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQglNni0t9Dg9icgG8w\n"
|
||||
"kbfxWSS+TuNgbtNybIQXcm3NHpmhRANCAASS4EacicM3qXTrNVVDVVys68fkUO70\n"
|
||||
"wLoXAlzZ7bTU/yESmrRD9IlLaeRtK5Yf/AFNMFp5c3a6GUHMxRYrv3Qo\n"
|
||||
"-----END PRIVATE KEY-----\n";
|
||||
|
||||
// Important: we use different port numbers for the Windows bug workaround. See
|
||||
// https://support.microsoft.com/en-ae/help/3039044/error-10013-wsaeacces-is-returned-when-a-second-bind-to-a-excluded-por
|
||||
|
||||
@ -743,10 +709,11 @@ static int fetch(struct mg_mgr *mgr, char *buf, const char *url,
|
||||
if (c != NULL && mg_url_is_ssl(url)) {
|
||||
struct mg_tls_opts opts;
|
||||
memset(&opts, 0, sizeof(opts)); // read CA from packed_fs
|
||||
opts.name = mg_url_host(url);
|
||||
opts.ca = mg_unpacked("/test/data/ca.pem");
|
||||
if (strstr(url, "127.0.0.1") != NULL) {
|
||||
if (strstr(url, "localhost") != NULL) {
|
||||
// Local connection, use self-signed certificates
|
||||
opts.ca = mg_str(s_tls_ca);
|
||||
opts.ca = mg_unpacked("/test/certs/ca.crt");
|
||||
// opts.cert = mg_str(s_tls_cert);
|
||||
// opts.key = mg_str(s_tls_key);
|
||||
}
|
||||
@ -1207,14 +1174,14 @@ static void test_tls(void) {
|
||||
#if MG_TLS
|
||||
struct mg_mgr mgr;
|
||||
struct mg_connection *c;
|
||||
const char *url = "https://127.0.0.1:12347";
|
||||
const char *url = "https://localhost:12347";
|
||||
char buf[FETCH_BUF_SIZE];
|
||||
struct mg_tls_opts opts;
|
||||
struct mg_str data = mg_unpacked("/Makefile");
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
// opts.ca = mg_str(s_tls_ca);
|
||||
opts.cert = mg_str(s_tls_cert);
|
||||
opts.key = mg_str(s_tls_key);
|
||||
opts.cert = mg_unpacked("/test/certs/server.crt");
|
||||
opts.key = mg_unpacked("/test/certs/server.key");
|
||||
mg_mgr_init(&mgr);
|
||||
c = mg_http_listen(&mgr, url, eh1, &opts);
|
||||
ASSERT(c != NULL);
|
||||
@ -1334,6 +1301,7 @@ static void test_host_validation(void) {
|
||||
c = mg_http_connect(&mgr, url, f3, &ok);
|
||||
ASSERT(c != NULL);
|
||||
opts.ca = mg_unpacked("/test/data/ca.pem");
|
||||
opts.name = mg_url_host(url);
|
||||
mg_tls_init(c, &opts);
|
||||
for (i = 0; i < 1500 && ok <= 0; i++) mg_mgr_poll(&mgr, 10);
|
||||
ASSERT(ok == 200);
|
||||
|
Loading…
Reference in New Issue
Block a user