1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-30 16:24:09 +03:00

some directory restructuring

git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@141 9a5d90b5-6617-0410-8a86-bb477d3ed2e3
This commit is contained in:
cameronrich
2007-11-13 08:36:58 +00:00
parent 70ed44946e
commit 4a82037346
15 changed files with 439 additions and 111 deletions

View File

@ -35,10 +35,13 @@ AXTLS_HOME=..
OBJ=\
aes.o \
bigint.o \
crypto_misc.o \
hmac.o \
md2.o \
md5.o \
rc4.o \
rsa.o \
sha1.o
include ../config/makefile.post

1571
crypto/bigint.c Normal file

File diff suppressed because it is too large Load Diff

99
crypto/bigint.h Normal file
View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2007, Cameron Rich
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the axTLS project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BIGINT_HEADER
#define BIGINT_HEADER
#include "crypto.h"
BI_CTX *bi_initialize(void);
void bi_terminate(BI_CTX *ctx);
void bi_permanent(bigint *bi);
void bi_depermanent(bigint *bi);
void bi_clear_cache(BI_CTX *ctx);
void bi_free(BI_CTX *ctx, bigint *bi);
bigint *bi_copy(bigint *bi);
bigint *bi_clone(BI_CTX *ctx, const bigint *bi);
void bi_export(BI_CTX *ctx, bigint *bi, uint8_t *data, int size);
bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int len);
bigint *int_to_bi(BI_CTX *ctx, comp i);
/* the functions that actually do something interesting */
bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib);
bigint *bi_subtract(BI_CTX *ctx, bigint *bia,
bigint *bib, int *is_negative);
bigint *bi_divide(BI_CTX *ctx, bigint *bia, bigint *bim, int is_mod);
bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib);
bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp);
bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp);
int bi_compare(bigint *bia, bigint *bib);
void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset);
void bi_free_mod(BI_CTX *ctx, int mod_offset);
#ifdef CONFIG_SSL_FULL_MODE
void bi_print(const char *label, bigint *bi);
bigint *bi_str_import(BI_CTX *ctx, const char *data);
#endif
/**
* @def bi_mod
* Find the residue of B. bi_set_mod() must be called before hand.
*/
#define bi_mod(A, B) bi_divide(A, B, ctx->bi_mod[ctx->mod_offset], 1)
/**
* bi_residue() is technically the same as bi_mod(), but it uses the
* appropriate reduction technique (which is bi_mod() when doing classical
* reduction).
*/
#if defined(CONFIG_BIGINT_MONTGOMERY)
#define bi_residue(A, B) bi_mont(A, B)
bigint *bi_mont(BI_CTX *ctx, bigint *bixy);
#elif defined(CONFIG_BIGINT_BARRETT)
#define bi_residue(A, B) bi_barrett(A, B)
bigint *bi_barrett(BI_CTX *ctx, bigint *bi);
#else /* if defined(CONFIG_BIGINT_CLASSICAL) */
#define bi_residue(A, B) bi_mod(A, B)
#endif
#ifdef CONFIG_BIGINT_SQUARE
bigint *bi_square(BI_CTX *ctx, bigint *bi);
#else
#define bi_square(A, B) bi_multiply(A, bi_copy(B), B)
#endif
#ifdef CONFIG_BIGINT_CRT
bigint *bi_crt(BI_CTX *ctx, bigint *bi,
bigint *dP, bigint *dQ,
bigint *p, bigint *q,
bigint *qInv);
#endif
#endif

112
crypto/bigint_impl.h Normal file
View File

@ -0,0 +1,112 @@
/*
* Copyright (c) 2007, Cameron Rich
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the axTLS project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BIGINT_IMPL_HEADER
#define BIGINT_IMPL_HEADER
/* Maintain a number of precomputed variables when doing reduction */
#define BIGINT_M_OFFSET 0 /**< Normal modulo offset. */
#ifdef CONFIG_BIGINT_CRT
#define BIGINT_P_OFFSET 1 /**< p modulo offset. */
#define BIGINT_Q_OFFSET 2 /**< q module offset. */
#define BIGINT_NUM_MODS 3 /**< The number of modulus constants used. */
#else
#define BIGINT_NUM_MODS 1
#endif
/* Architecture specific functions for big ints */
#ifdef WIN32
#define COMP_RADIX 4294967296i64
#define COMP_BIG_MSB 0x8000000000000000i64
#else
#define COMP_RADIX 4294967296ULL /**< Max component + 1 */
#define COMP_BIG_MSB 0x8000000000000000ULL /**< (Max dbl comp + 1)/ 2 */
#endif
#define COMP_BIT_SIZE 32 /**< Number of bits in a component. */
#define COMP_BYTE_SIZE 4 /**< Number of bytes in a component. */
#define COMP_NUM_NIBBLES 8 /**< Used For diagnostics only. */
typedef uint32_t comp; /**< A single precision component. */
typedef uint64_t long_comp; /**< A double precision component. */
typedef int64_t slong_comp; /**< A signed double precision component. */
/**
* @struct _bigint
* @brief A big integer basic object
*/
struct _bigint
{
struct _bigint* next; /**< The next bigint in the cache. */
short size; /**< The number of components in this bigint. */
short max_comps; /**< The heapsize allocated for this bigint */
int refs; /**< An internal reference count. */
comp* comps; /**< A ptr to the actual component data */
};
typedef struct _bigint bigint; /**< An alias for _bigint */
/**
* Maintains the state of the cache, and a number of variables used in
* reduction.
*/
typedef struct /**< A big integer "session" context. */
{
bigint *active_list; /**< Bigints currently used. */
bigint *free_list; /**< Bigints not used. */
bigint *bi_radix; /**< The radix used. */
bigint *bi_mod[BIGINT_NUM_MODS]; /**< modulus */
#if defined(CONFIG_BIGINT_MONTGOMERY)
bigint *bi_RR_mod_m[BIGINT_NUM_MODS]; /**< R^2 mod m */
bigint *bi_R_mod_m[BIGINT_NUM_MODS]; /**< R mod m */
comp N0_dash[BIGINT_NUM_MODS];
#elif defined(CONFIG_BIGINT_BARRETT)
bigint *bi_mu[BIGINT_NUM_MODS]; /**< Storage for mu */
#endif
bigint *bi_normalised_mod[BIGINT_NUM_MODS]; /**< Normalised mod storage. */
bigint **g; /**< Used by sliding-window. */
int window; /**< The size of the sliding window */
int active_count; /**< Number of active bigints. */
int free_count; /**< Number of free bigints. */
#ifdef CONFIG_BIGINT_MONTGOMERY
uint8_t use_classical; /**< Use classical reduction. */
#endif
uint8_t mod_offset; /**< The mod offset we are using */
} BI_CTX;
#ifndef WIN32
#define max(a,b) ((a)>(b)?(a):(b)) /**< Find the maximum of 2 numbers. */
#define min(a,b) ((a)<(b)?(a):(b)) /**< Find the minimum of 2 numbers. */
#endif
#define PERMANENT 0x7FFF55AA /**< A magic number for permanents. */
#endif

View File

@ -41,6 +41,8 @@ extern "C" {
#include "config.h"
#include "os_port.h"
#include "bigint_impl.h"
#include "bigint.h"
/* enable features based on a 'super-set' capbaility. */
#if defined(CONFIG_SSL_FULL_MODE)
@ -157,7 +159,61 @@ void hmac_md5(const uint8_t *msg, int length, const uint8_t *key,
void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest);
/**************************************************************************
* RSA declarations
**************************************************************************/
typedef struct
{
bigint *m; /* modulus */
bigint *e; /* public exponent */
bigint *d; /* private exponent */
#ifdef CONFIG_BIGINT_CRT
bigint *p; /* p as in m = pq */
bigint *q; /* q as in m = pq */
bigint *dP; /* d mod (p-1) */
bigint *dQ; /* d mod (q-1) */
bigint *qInv; /* q^-1 mod p */
#endif
int num_octets;
BI_CTX *bi_ctx;
} RSA_CTX;
void RSA_priv_key_new(RSA_CTX **rsa_ctx,
const uint8_t *modulus, int mod_len,
const uint8_t *pub_exp, int pub_len,
const uint8_t *priv_exp, int priv_len
#ifdef CONFIG_BIGINT_CRT
, const uint8_t *p, int p_len,
const uint8_t *q, int q_len,
const uint8_t *dP, int dP_len,
const uint8_t *dQ, int dQ_len,
const uint8_t *qInv, int qInv_len
#endif
);
void RSA_pub_key_new(RSA_CTX **rsa_ctx,
const uint8_t *modulus, int mod_len,
const uint8_t *pub_exp, int pub_len);
void RSA_free(RSA_CTX *ctx);
int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data,
int is_decryption);
bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg);
#ifdef CONFIG_SSL_CERT_VERIFICATION
bigint *RSA_sign_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,
bigint *modulus, bigint *pub_exp);
bigint *RSA_public(const RSA_CTX * c, bigint *bi_msg);
int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len,
uint8_t *out_data, int is_signing);
void RSA_print(const RSA_CTX *ctx);
#endif
/**************************************************************************
* RNG declarations
**************************************************************************/
EXP_FUNC void STDCALL RNG_initialize(const uint8_t *seed_buf, int size);
EXP_FUNC void STDCALL RNG_terminate(void);
EXP_FUNC void STDCALL get_random(int num_rand_bytes, uint8_t *rand_data);
void get_random_NZ(int num_rand_bytes, uint8_t *rand_data);
#ifdef __cplusplus
}

357
crypto/crypto_misc.c Normal file
View File

@ -0,0 +1,357 @@
/*
* Copyright (c) 2007, Cameron Rich
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the axTLS project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Some misc. routines to help things out
*/
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include "crypto_misc.h"
#ifdef CONFIG_WIN32_USE_CRYPTO_LIB
#include "wincrypt.h"
#endif
#ifndef WIN32
static int rng_fd = -1;
#elif defined(CONFIG_WIN32_USE_CRYPTO_LIB)
static HCRYPTPROV gCryptProv;
#endif
#if (!defined(CONFIG_USE_DEV_URANDOM) && !defined(CONFIG_WIN32_USE_CRYPTO_LIB))
static uint64_t rng_num;
#endif
static int rng_ref_count;
const char * const unsupported_str = "Error: feature not supported\n";
#ifndef CONFIG_SSL_SKELETON_MODE
/**
* Retrieve a file and put it into memory
* @return The size of the file, or -1 on failure.
*/
int get_file(const char *filename, uint8_t **buf)
{
int total_bytes = 0;
int bytes_read = 0;
int filesize;
FILE *stream = fopen(filename, "rb");
if (stream == NULL)
{
#ifdef CONFIG_SSL_FULL_MODE
printf("file '%s' does not exist\n", filename); TTY_FLUSH();
#endif
return -1;
}
/* Win CE doesn't support stat() */
fseek(stream, 0, SEEK_END);
filesize = ftell(stream);
*buf = (uint8_t *)malloc(filesize);
fseek(stream, 0, SEEK_SET);
do
{
bytes_read = fread(*buf+total_bytes, 1, filesize-total_bytes, stream);
total_bytes += bytes_read;
} while (total_bytes < filesize && bytes_read > 0);
fclose(stream);
return filesize;
}
#endif
/**
* Initialise the Random Number Generator engine.
* - On Win32 use the platform SDK's crypto engine.
* - On Linux use /dev/urandom
* - If none of these work then use a custom RNG.
*/
EXP_FUNC void STDCALL RNG_initialize(const uint8_t *seed_buf, int size)
{
if (rng_ref_count == 0)
{
#if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM)
rng_fd = ax_open("/dev/urandom", O_RDONLY);
#elif defined(WIN32) && defined(CONFIG_WIN32_USE_CRYPTO_LIB)
if (!CryptAcquireContext(&gCryptProv,
NULL, NULL, PROV_RSA_FULL, 0))
{
if (GetLastError() == NTE_BAD_KEYSET &&
!CryptAcquireContext(&gCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
printf("CryptoLib: %x\n", unsupported_str, GetLastError());
exit(1);
}
}
#else
/* help seed with the user's private key - this is a number that
should be hard to find, due to the fact that it relies on knowing
the private key */
int i;
for (i = 0; i < size/(int)sizeof(uint64_t); i++)
rng_num ^= *((uint64_t *)&seed_buf[i*sizeof(uint64_t)]);
srand((long)seed_buf); /* use the stack ptr as another rnd seed */
#endif
}
rng_ref_count++;
}
/**
* Terminate the RNG engine.
*/
EXP_FUNC void STDCALL RNG_terminate(void)
{
if (--rng_ref_count == 0)
{
#ifndef WIN32
close(rng_fd);
#elif defined(CONFIG_WIN32_USE_CRYPTO_LIB)
CryptReleaseContext(gCryptProv, 0);
#endif
}
}
/**
* Set a series of bytes with a random number. Individual bytes can be 0
*/
EXP_FUNC void STDCALL get_random(int num_rand_bytes, uint8_t *rand_data)
{
#if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM)
/* use the Linux default */
read(rng_fd, rand_data, num_rand_bytes); /* read from /dev/urandom */
#elif defined(WIN32) && defined(CONFIG_WIN32_USE_CRYPTO_LIB)
/* use Microsoft Crypto Libraries */
CryptGenRandom(gCryptProv, num_rand_bytes, rand_data);
#else /* nothing else to use, so use a custom RNG */
/* The method we use when we've got nothing better. Use RC4, time
and a couple of random seeds to generate a random sequence */
RC4_CTX rng_ctx;
struct timeval tv;
uint64_t big_num1, big_num2;
gettimeofday(&tv, NULL); /* yes I know we shouldn't do this */
/* all numbers by themselves are pretty simple, but combined should
* be a challenge */
big_num1 = (uint64_t)tv.tv_sec*(tv.tv_usec+1);
big_num2 = (uint64_t)rand()*big_num1;
big_num1 ^= rng_num;
memcpy(rand_data, &big_num1, sizeof(uint64_t));
if (num_rand_bytes > sizeof(uint64_t))
memcpy(&rand_data[8], &big_num2, sizeof(uint64_t));
if (num_rand_bytes > 16)
{
/* clear rest of data */
memset(&rand_data[16], 0, num_rand_bytes-16);
}
RC4_setup(&rng_ctx, rand_data, 16); /* use as a key */
RC4_crypt(&rng_ctx, rand_data, rand_data, num_rand_bytes);
/* use last 8 bytes for next time */
memcpy(&rng_num, &rand_data[num_rand_bytes-8], sizeof(uint64_t));
#endif
}
/**
* Set a series of bytes with a random number. Individual bytes are not zero.
*/
void get_random_NZ(int num_rand_bytes, uint8_t *rand_data)
{
int i;
get_random(num_rand_bytes, rand_data);
for (i = 0; i < num_rand_bytes; i++)
{
while (rand_data[i] == 0) /* can't be 0 */
rand_data[i] = (uint8_t)(rand());
}
}
/**
* Some useful diagnostic routines
*/
#if defined(CONFIG_SSL_FULL_MODE) || defined(CONFIG_DEBUG)
int hex_finish;
int hex_index;
static void print_hex_init(int finish)
{
hex_finish = finish;
hex_index = 0;
}
static void print_hex(uint8_t hex)
{
static int column;
if (hex_index == 0)
{
column = 0;
}
printf("%02x ", hex);
if (++column == 8)
{
printf(": ");
}
else if (column >= 16)
{
printf("\n");
column = 0;
}
if (++hex_index >= hex_finish && column > 0)
{
printf("\n");
}
}
/**
* Spit out a blob of data for diagnostics. The data is is a nice column format
* for easy reading.
*
* @param format [in] The string (with possible embedded format characters)
* @param size [in] The number of numbers to print
* @param data [in] The start of data to use
* @param ... [in] Any additional arguments
*/
EXP_FUNC void STDCALL print_blob(const char *format,
const uint8_t *data, int size, ...)
{
int i;
char tmp[80];
va_list(ap);
va_start(ap, size);
sprintf(tmp, "%s\n", format);
vprintf(tmp, ap);
print_hex_init(size);
for (i = 0; i < size; i++)
{
print_hex(data[i]);
}
va_end(ap);
TTY_FLUSH();
}
#elif defined(WIN32)
/* VC6.0 doesn't handle variadic macros */
EXP_FUNC void STDCALL print_blob(const char *format, const unsigned char *data,
int size, ...) {}
#endif
#if defined(CONFIG_SSL_HAS_PEM) || defined(CONFIG_HTTP_HAS_AUTHORIZATION)
/* base64 to binary lookup table */
static const uint8_t map[128] =
{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 255, 255, 255, 255, 255
};
EXP_FUNC int STDCALL base64_decode(const char *in, int len,
uint8_t *out, int *outlen)
{
int g, t, x, y, z;
uint8_t c;
int ret = -1;
g = 3;
for (x = y = z = t = 0; x < len; x++)
{
if ((c = map[in[x]&0x7F]) == 0xff)
continue;
if (c == 254) /* this is the end... */
{
c = 0;
if (--g < 0)
goto error;
}
else if (g != 3) /* only allow = at end */
goto error;
t = (t<<6) | c;
if (++y == 4)
{
out[z++] = (uint8_t)((t>>16)&255);
if (g > 1)
out[z++] = (uint8_t)((t>>8)&255);
if (g > 2)
out[z++] = (uint8_t)(t&255);
y = t = 0;
}
}
if (y != 0)
goto error;
if (outlen)
*outlen = z;
ret = 0;
error:
#ifdef CONFIG_SSL_FULL_MODE
if (ret < 0)
printf("Error: Invalid base64\n"); TTY_FLUSH();
#endif
TTY_FLUSH();
return ret;
}
#endif

263
crypto/rsa.c Normal file
View File

@ -0,0 +1,263 @@
/*
* Copyright (c) 2007, Cameron Rich
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the axTLS project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Implements the RSA public encryption algorithm. Uses the bigint library to
* perform its calculations.
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include "crypto.h"
void RSA_priv_key_new(RSA_CTX **ctx,
const uint8_t *modulus, int mod_len,
const uint8_t *pub_exp, int pub_len,
const uint8_t *priv_exp, int priv_len
#if CONFIG_BIGINT_CRT
, const uint8_t *p, int p_len,
const uint8_t *q, int q_len,
const uint8_t *dP, int dP_len,
const uint8_t *dQ, int dQ_len,
const uint8_t *qInv, int qInv_len
#endif
)
{
RSA_CTX *rsa_ctx;
BI_CTX *bi_ctx;
RSA_pub_key_new(ctx, modulus, mod_len, pub_exp, pub_len);
rsa_ctx = *ctx;
bi_ctx = rsa_ctx->bi_ctx;
rsa_ctx->d = bi_import(bi_ctx, priv_exp, priv_len);
bi_permanent(rsa_ctx->d);
#ifdef CONFIG_BIGINT_CRT
rsa_ctx->p = bi_import(bi_ctx, p, p_len);
rsa_ctx->q = bi_import(bi_ctx, q, q_len);
rsa_ctx->dP = bi_import(bi_ctx, dP, dP_len);
rsa_ctx->dQ = bi_import(bi_ctx, dQ, dQ_len);
rsa_ctx->qInv = bi_import(bi_ctx, qInv, qInv_len);
bi_permanent(rsa_ctx->dP);
bi_permanent(rsa_ctx->dQ);
bi_permanent(rsa_ctx->qInv);
bi_set_mod(bi_ctx, rsa_ctx->p, BIGINT_P_OFFSET);
bi_set_mod(bi_ctx, rsa_ctx->q, BIGINT_Q_OFFSET);
#endif
}
void RSA_pub_key_new(RSA_CTX **ctx,
const uint8_t *modulus, int mod_len,
const uint8_t *pub_exp, int pub_len)
{
RSA_CTX *rsa_ctx;
BI_CTX *bi_ctx = bi_initialize();
*ctx = (RSA_CTX *)calloc(1, sizeof(RSA_CTX));
rsa_ctx = *ctx;
rsa_ctx->bi_ctx = bi_ctx;
rsa_ctx->num_octets = (mod_len & 0xFFF0);
rsa_ctx->m = bi_import(bi_ctx, modulus, mod_len);
bi_set_mod(bi_ctx, rsa_ctx->m, BIGINT_M_OFFSET);
rsa_ctx->e = bi_import(bi_ctx, pub_exp, pub_len);
bi_permanent(rsa_ctx->e);
}
/**
* Free up any RSA context resources.
*/
void RSA_free(RSA_CTX *rsa_ctx)
{
BI_CTX *bi_ctx;
if (rsa_ctx == NULL) /* deal with ptrs that are null */
return;
bi_ctx = rsa_ctx->bi_ctx;
bi_depermanent(rsa_ctx->e);
bi_free(bi_ctx, rsa_ctx->e);
bi_free_mod(rsa_ctx->bi_ctx, BIGINT_M_OFFSET);
if (rsa_ctx->d)
{
bi_depermanent(rsa_ctx->d);
bi_free(bi_ctx, rsa_ctx->d);
#ifdef CONFIG_BIGINT_CRT
bi_depermanent(rsa_ctx->dP);
bi_depermanent(rsa_ctx->dQ);
bi_depermanent(rsa_ctx->qInv);
bi_free(bi_ctx, rsa_ctx->dP);
bi_free(bi_ctx, rsa_ctx->dQ);
bi_free(bi_ctx, rsa_ctx->qInv);
bi_free_mod(rsa_ctx->bi_ctx, BIGINT_P_OFFSET);
bi_free_mod(rsa_ctx->bi_ctx, BIGINT_Q_OFFSET);
#endif
}
bi_terminate(bi_ctx);
free(rsa_ctx);
}
/**
* @brief Use PKCS1.5 for decryption/verification.
* @param ctx [in] The context
* @param in_data [in] The data to encrypt (must be < modulus size-11)
* @param out_data [out] The encrypted data.
* @param is_decryption [in] Decryption or verify operation.
* @return The number of bytes that were originally encrypted. -1 on error.
* @see http://www.rsasecurity.com/rsalabs/node.asp?id=2125
*/
int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data,
uint8_t *out_data, int is_decryption)
{
const int byte_size = ctx->num_octets;
int i, size;
bigint *decrypted_bi, *dat_bi;
uint8_t *block = (uint8_t *)alloca(byte_size);
memset(out_data, 0, byte_size); /* initialise */
/* decrypt */
dat_bi = bi_import(ctx->bi_ctx, in_data, byte_size);
#ifdef CONFIG_SSL_CERT_VERIFICATION
decrypted_bi = is_decryption ? /* decrypt or verify? */
RSA_private(ctx, dat_bi) : RSA_public(ctx, dat_bi);
#else /* always a decryption */
decrypted_bi = RSA_private(ctx, dat_bi);
#endif
/* convert to a normal block */
bi_export(ctx->bi_ctx, decrypted_bi, block, byte_size);
i = 10; /* start at the first possible non-padded byte */
#ifdef CONFIG_SSL_CERT_VERIFICATION
if (is_decryption == 0) /* PKCS1.5 signing pads with "0xff"s */
{
while (block[i++] == 0xff && i < byte_size);
if (block[i-2] != 0xff)
i = byte_size; /*ensure size is 0 */
}
else /* PKCS1.5 encryption padding is random */
#endif
{
while (block[i++] && i < byte_size);
}
size = byte_size - i;
/* get only the bit we want */
if (size > 0)
memcpy(out_data, &block[i], size);
return size ? size : -1;
}
/**
* Performs m = c^d mod n
*/
bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg)
{
#ifdef CONFIG_BIGINT_CRT
return bi_crt(c->bi_ctx, bi_msg, c->dP, c->dQ, c->p, c->q, c->qInv);
#else
BI_CTX *ctx = c->bi_ctx;
ctx->mod_offset = BIGINT_M_OFFSET;
return bi_mod_power(ctx, bi_msg, c->d);
#endif
}
#ifdef CONFIG_SSL_FULL_MODE
/**
* Used for diagnostics.
*/
void RSA_print(const RSA_CTX *rsa_ctx)
{
if (rsa_ctx == NULL)
return;
printf("----------------- RSA DEBUG ----------------\n");
printf("Size:\t%d\n", rsa_ctx->num_octets);
bi_print("Modulus", rsa_ctx->m);
bi_print("Public Key", rsa_ctx->e);
bi_print("Private Key", rsa_ctx->d);
}
#endif
#ifdef CONFIG_SSL_CERT_VERIFICATION
/**
* Performs c = m^e mod n
*/
bigint *RSA_public(const RSA_CTX * c, bigint *bi_msg)
{
c->bi_ctx->mod_offset = BIGINT_M_OFFSET;
return bi_mod_power(c->bi_ctx, bi_msg, c->e);
}
/**
* Use PKCS1.5 for encryption/signing.
* see http://www.rsasecurity.com/rsalabs/node.asp?id=2125
*/
int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len,
uint8_t *out_data, int is_signing)
{
int byte_size = ctx->num_octets;
int num_pads_needed = byte_size-in_len-3;
bigint *dat_bi, *encrypt_bi;
/* note: in_len+11 must be > byte_size */
out_data[0] = 0; /* ensure encryption block is < modulus */
if (is_signing)
{
out_data[1] = 1; /* PKCS1.5 signing pads with "0xff"'s */
memset(&out_data[2], 0xff, num_pads_needed);
}
else /* randomize the encryption padding with non-zero bytes */
{
out_data[1] = 2;
get_random_NZ(num_pads_needed, &out_data[2]);
}
out_data[2+num_pads_needed] = 0;
memcpy(&out_data[3+num_pads_needed], in_data, in_len);
/* now encrypt it */
dat_bi = bi_import(ctx->bi_ctx, out_data, byte_size);
encrypt_bi = is_signing ? RSA_private(ctx, dat_bi) :
RSA_public(ctx, dat_bi);
bi_export(ctx->bi_ctx, encrypt_bi, out_data, byte_size);
/* save a few bytes of memory */
bi_clear_cache(ctx->bi_ctx);
return byte_size;
}
#endif /* CONFIG_SSL_CERT_VERIFICATION */