1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-12 01:53:07 +03:00

new trunk

git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@78 9a5d90b5-6617-0410-8a86-bb477d3ed2e3
This commit is contained in:
cameronrich
2007-03-14 12:03:51 +00:00
parent 974cf12924
commit 73dfbb7568
177 changed files with 46362 additions and 0 deletions

132
ssl/BigIntConfig.in Normal file
View File

@ -0,0 +1,132 @@
#
# For a description of the syntax of this configuration file,
# see scripts/config/Kconfig-language.txt
#
menu "BigInt Options"
depends on !CONFIG_SSL_SKELETON_MODE
choice
prompt "Reduction Algorithm"
default CONFIG_BIGINT_BARRETT
config CONFIG_BIGINT_CLASSICAL
bool "Classical"
help
Classical uses standard division. It has no limitations and is
theoretically the slowest due to the divisions used. For this particular
implementation it is surprisingly quite fast.
config CONFIG_BIGINT_MONTGOMERY
bool "Montgomery"
help
Montgomery uses simple addition and multiplication to achieve its
performance. In this implementation it is slower than classical,
and it has the limitation that 0 <= x, y < m, and so is not used
when CRT is active.
This option will not be normally selected.
config CONFIG_BIGINT_BARRETT
bool "Barrett"
help
Barrett performs expensive precomputation before reduction and partial
multiplies for computational speed. It can't be used with some of the
calculations when CRT is used, and so defaults to classical when this
occurs.
It is about 40% faster than Classical/Montgomery with the expense of
about 2kB, and so this option is normally selected.
endchoice
config CONFIG_BIGINT_CRT
bool "Chinese Remainder Theorem (CRT)"
default y
help
Allow the Chinese Remainder Theorem (CRT) to be used.
Uses a number of extra coefficients from the private key to improve the
performance of a decryption. This feature is one of the most
significant performance improvements (it reduces a decryption time by
over 3 times).
This option should be selected.
config CONFIG_BIGINT_KARATSUBA
bool "Karatsuba Multiplication"
default n
help
Allow Karasuba multiplication to be used.
Uses 3 multiplications (plus a number of additions/subtractions)
instead of 4. Multiplications are O(N^2) but addition/subtraction
is O(N) hence for large numbers is beneficial. For this project, the
effect was only useful for 4096 bit keys. As these aren't likely to
be used, the feature is disabled by default.
It costs about 2kB to enable it.
config MUL_KARATSUBA_THRESH
int "Karatsuba Multiplication Theshold"
default 20
depends on CONFIG_BIGINT_KARATSUBA
help
The minimum number of components needed before Karasuba muliplication
is used.
This is very dependent on the speed/implementation of bi_add()/
bi_subtract(). There is a bit of trial and error here and will be
at a different point for different architectures.
config SQU_KARATSUBA_THRESH
int "Karatsuba Square Threshold"
default 40
depends on CONFIG_BIGINT_KARATSUBA && CONFIG_BIGINT_SQUARE
help
The minimum number of components needed before Karatsuba squaring
is used.
This is very dependent on the speed/implementation of bi_add()/
bi_subtract(). There is a bit of trial and error here and will be
at a different point for different architectures.
config CONFIG_BIGINT_SLIDING_WINDOW
bool "Sliding Window Exponentiation"
default y
help
Allow Sliding-Window Exponentiation to be used.
Potentially processes more than 1 bit at a time when doing
exponentiation. The sliding-window technique reduces the number of
precomputations compared to other precomputed techniques.
It results in a considerable performance improvement with it enabled
(it halves the decryption time) and so should be selected.
config CONFIG_BIGINT_SQUARE
bool "Square Algorithm"
default y
help
Allow squaring to be used instead of a multiplication.
Squaring is theoretically 50% faster than a standard multiply
(but is actually about 25% faster).
It gives a 20% speed improvement and so should be selected.
config CONFIG_BIGINT_CHECK_ON
bool "BigInt Integrity Checking"
default n if !CONFIG_DEBUG
default y if CONFIG_DEBUG
help
This is used when developing bigint algorithms. It performs a sanity
check on all operations at the expense of speed.
This option is only selected when developing and should normally be
turned off.
endmenu

274
ssl/Config.in Normal file
View File

@ -0,0 +1,274 @@
#
# For a description of the syntax of this configuration file,
# see scripts/config/Kconfig-language.txt
#
menu "SSL Library"
choice
prompt "Mode"
default CONFIG_SSL_FULL_MODE
config CONFIG_SSL_SERVER_ONLY
bool "Server only - no verification"
help
Enable server functionality (no client functionality).
This mode still supports sessions and chaining (which can be turned
off in configuration).
The axssl sample runs with the minimum of features.
This is the most space efficient of the modes with the library
about 45kB in size. Use this mode if you are doing standard SSL server
work.
config CONFIG_SSL_CERT_VERIFICATION
bool "Server only - with verification"
help
Enable server functionality with client authentication (no client
functionality).
The axssl sample runs with the "-verify" and "-CAfile" options.
This mode produces a library about 49kB in size. Use this mode if you
have an SSL server which requires client authentication (which is
uncommon in browser applications).
config CONFIG_SSL_ENABLE_CLIENT
bool "Client/Server enabled"
help
Enable client/server functionality (including peer authentication).
The axssl sample runs with the "s_client" option enabled.
This mode produces a library about 51kB in size. Use this mode if you
require axTLS to use SSL client functionality (the SSL server code
is always enabled).
config CONFIG_SSL_FULL_MODE
bool "Client/Server enabled with diagnostics"
help
Enable client/server functionality including diagnostics. Most of the
extra size in this mode is due to the storage of various strings that
are used.
The axssl sample has 3 more options, "-debug", "-state" and "-show-rsa"
This mode produces a library about 58kB in size. It is suggested that
this mode is used only during development, or systems that have more
generous memory limits.
It is the default to demonstrate the features of axTLS.
config CONFIG_SSL_SKELETON_MODE
bool "Skeleton mode - the smallest server mode"
help
This is an experiment to build the smallest library at the expense of
features and speed.
* Server mode only.
* The AES cipher is disabled.
* No session resumption.
* No external keys/certificates are supported.
* The bigint library has most of the performance features disabled.
* Some other features/API calls may not work.
This mode produces a library about 37kB in size. The main
disadvantage of this mode is speed - it will be much slower than the
other build modes.
endchoice
choice
prompt "Protocol Preference"
depends on !CONFIG_SSL_SKELETON_MODE
default CONFIG_SSL_PROT_MEDIUM
config CONFIG_SSL_PROT_LOW
bool "Low"
help
Chooses the cipher in the order of RC4-SHA, AES128-SHA, AES256-SHA.
This will use the fastest cipher(s) but at the expense of security.
config CONFIG_SSL_PROT_MEDIUM
bool "Medium"
help
Chooses the cipher in the order of AES128-SHA, AES256-SHA, RC4-SHA.
This mode is a balance between speed and security and is the default.
config CONFIG_SSL_PROT_HIGH
bool "High"
help
Chooses the cipher in the order of AES256-SHA, AES128-SHA, RC4-SHA.
This will use the strongest cipher(s) at the cost of speed.
endchoice
config CONFIG_SSL_USE_DEFAULT_KEY
bool "Enable default key"
depends on !CONFIG_SSL_SKELETON_MODE
default y
help
Some applications will not require the default private key/certificate
that is built in. This is one way to save on a couple of kB's if an
external private key/certificate is used.
The advantage of a built-in private key/certificate is that no file
system is required for access.
However this private key/certificate can never be changed (without a
code update).
This mode is enabled by default. Disable this mode if the
built-in key/certificate is not used.
config CONFIG_SSL_ENABLE_V23_HANDSHAKE
bool "Enable v23 Handshake"
default y
help
Some browsers use the v23 handshake client hello message
(an SSL2 format message which all SSL servers can understand).
It may be used if SSL2 is enabled in the browser.
Since this feature takes a kB or so, this feature may be disabled - at
the risk of making it incompatible with some browsers (IE6 is ok,
Firefox 1.5 and below use it).
Disable if backwards compatibility is not an issue (i.e. the client is
always using TLS1.0)
config CONFIG_SSL_HAS_PEM
bool "Enable PEM"
default n if !CONFIG_SSL_FULL_MODE
default y if CONFIG_SSL_FULL_MODE
depends on !CONFIG_SSL_SKELETON_MODE
help
Enable the use of PEM format for certificates and private keys.
PEM is not normally needed - PEM files can be converted into DER files
quite easily. However they have the convenience of allowing multiple
certificates/keys in the same file.
This feature will add a couple of kB to the library.
Disable if PEM is not used (which will be in most cases).
config CONFIG_SSL_USE_PKCS12
bool "Use PKCS8/PKCS12"
default n if !CONFIG_SSL_FULL_MODE
default y if CONFIG_SSL_FULL_MODE
depends on !CONFIG_SSL_SERVER_ONLY && !CONFIG_SSL_SKELETON_MODE
help
PKCS#12 certificates combine private keys and certificates together in
one file.
PKCS#8 private keys are also suppported (as it is a subset of PKCS#12).
The decryption of these certificates uses RC4-128 (and these
certificates must be encrypted using this cipher). The actual
algorithm is "PBE-SHA1-RC4-128".
Disable if PKCS#12 is not used (which will be in most cases).
config CONFIG_SSL_EXPIRY_TIME
int "Session expiry time (in hours)"
depends on !CONFIG_SSL_SKELETON_MODE
default 24
help
The time (in hours) before a session expires.
A longer time means that the expensive parts of a handshake don't
need to be run when a client reconnects later.
The default is 1 day.
config CONFIG_X509_MAX_CA_CERTS
int "Maximum number of certificate authorites"
default 4
depends on !CONFIG_SSL_SERVER_ONLY && !CONFIG_SSL_SKELETON_MODE
help
Determines the number of CA's allowed.
Increase this figure if more trusted sites are allowed. Each
certificate adds about 300 bytes (when added).
The default is to allow four certification authorities.
config CONFIG_SSL_MAX_CERTS
int "Maximum number of chained certificates"
default 2
help
Determines the number of certificates used in a certificate
chain. The chain length must be at least 1.
Increase this figure if more certificates are to be added to the
chain. Each certificate adds about 300 bytes (when added).
The default is to allow one certificate + 1 certificate in the chain
(which may be the certificate authority certificate).
config CONFIG_SSL_CTX_MUTEXING
bool "Enable SSL_CTX mutexing"
default n
help
Normally mutexing is not required - each SSL_CTX object can deal with
many SSL objects (as long as each SSL_CTX object is using a single
thread).
If the SSL_CTX object is not thread safe e.g. the case where a
new thread is created for each SSL object, then mutexing is required.
Select y when a mutex on the SSL_CTX object is required.
config CONFIG_USE_DEV_URANDOM
bool "Use /dev/urandom"
default y
depends on !CONFIG_PLATFORM_WIN32
help
Use /dev/urandom. Otherwise a custom RNG is used.
This will be the default on most Linux systems.
config CONFIG_WIN32_USE_CRYPTO_LIB
bool "Use Win32 Crypto Library"
default y if !CONFIG_VISUAL_STUDIO_6_0
default n if CONFIG_VISUAL_STUDIO_6_0
depends on CONFIG_PLATFORM_WIN32
help
Microsoft produce a Crypto API which requires the Platform SDK to be
installed. It's used for the RNG.
This will be the default on most Win32 systems. If using Visual Studio
6.0, then the SDK containing the crypto libraries must be used.
config CONFIG_OPENSSL_COMPATIBLE
bool "Enable openssl API compatibility"
default n
help
To ease the porting of openssl applications, a subset of the openssl
API is wrapped around the axTLS API.
Note: not all the API is implemented, so parts may still break. And
it's definitely not 100% compatible.
config CONFIG_PERFORMANCE_TESTING
bool "Build the bigint performance test tool"
default n
help
Used for performance testing of bigint.
This is a testing tool and is normally disabled.
config CONFIG_SSL_TEST
bool "Build the SSL testing tool"
default n
depends on CONFIG_SSL_FULL_MODE
help
Used for sanity checking the SSL handshaking.
This is a testing tool and is normally disabled.
endmenu

101
ssl/Makefile Normal file
View File

@ -0,0 +1,101 @@
#
# Copyright(C) 2007 Cameron Rich
#
# This library is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
include ../config/.config
include ../config/makefile.conf
all: libs
ifdef CONFIG_PERFORMANCE_TESTING
$(MAKE) -C test
else
ifdef CONFIG_SSL_TEST
$(MAKE) -C test
endif
endif
ifndef CONFIG_PLATFORM_WIN32
TARGET1=../$(STAGE)/libaxtls.a
BASETARGET=libaxtls.so
ifdef CONFIG_PLATFORM_CYGWIN
TARGET2=../$(STAGE)/libaxtls.dll.a
else
TARGET2=../$(STAGE)/$(LIBMINOR)
endif
# shared library major/minor numbers
LIBMAJOR=$(BASETARGET).1
LIBMINOR=$(BASETARGET).1.1
else
TARGET1=axtls.lib
TARGET2=../$(STAGE)/axtls.dll
STATIC_LIB=../$(STAGE)/axtls.static.lib
endif
libs: $(TARGET1) $(TARGET2)
OBJ=\
aes.o \
asn1.o \
bigint.o \
crypto_misc.o \
hmac.o \
os_port.o \
loader.o \
md5.o \
openssl.o \
p12.o \
rsa.o \
rc4.o \
sha1.o \
tls1.o \
tls1_svr.o \
tls1_clnt.o
include ../config/makefile.post
ifndef CONFIG_PLATFORM_WIN32 # Linux/Unix/Cygwin
$(TARGET1) : $(OBJ)
$(AR) -r $@ $(OBJ)
$(TARGET2) : $(OBJ)
ifndef CONFIG_PLATFORM_CYGWIN
$(LD) $(LDFLAGS) $(LDSHARED) -Wl,-soname,$(LIBMAJOR) -o ../$(STAGE)/$(LIBMINOR) $(OBJ)
cd ../$(STAGE); ln -sf $(LIBMINOR) $(LIBMAJOR); ln -sf $(LIBMAJOR) $(BASETARGET); cd -
else
$(LD) $(LDFLAGS) $(LDSHARED) -o ../$(STAGE)/cygaxtls.dll \
-Wl,--out-implib=../$(STAGE)/libaxtls.dll.a \
-Wl,--export-all-symbols \
-Wl,--enable-auto-import $(OBJ)
endif
else # Win32
$(TARGET1) : $(OBJ)
$(AR) /out:$@ $(OBJ)
$(TARGET2) : $(OBJ)
cp $(TARGET1) $(STATIC_LIB)
$(LD) $(LDFLAGS) $(LDSHARED) /out:$@ $(OBJ)
endif
clean::
$(MAKE) -C test clean
-@rm -f ../$(STAGE)/* *.a *.lib

444
ssl/aes.c Normal file
View File

@ -0,0 +1,444 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* AES implementation - this is a small code version. There are much faster
* versions around but they are much larger in size (i.e. they use large
* submix tables).
*/
#include <string.h>
#include "crypto.h"
/* all commented out in skeleton mode */
#ifndef CONFIG_SSL_SKELETON_MODE
#define rot1(x) (((x) << 24) | ((x) >> 8))
#define rot2(x) (((x) << 16) | ((x) >> 16))
#define rot3(x) (((x) << 8) | ((x) >> 24))
/*
* This cute trick does 4 'mul by two' at once. Stolen from
* Dr B. R. Gladman <brg@gladman.uk.net> but I'm sure the u-(u>>7) is
* a standard graphics trick
* The key to this is that we need to xor with 0x1b if the top bit is set.
* a 1xxx xxxx 0xxx 0xxx First we mask the 7bit,
* b 1000 0000 0000 0000 then we shift right by 7 putting the 7bit in 0bit,
* c 0000 0001 0000 0000 we then subtract (c) from (b)
* d 0111 1111 0000 0000 and now we and with our mask
* e 0001 1011 0000 0000
*/
#define mt 0x80808080
#define ml 0x7f7f7f7f
#define mh 0xfefefefe
#define mm 0x1b1b1b1b
#define mul2(x,t) ((t)=((x)&mt), \
((((x)+(x))&mh)^(((t)-((t)>>7))&mm)))
#define inv_mix_col(x,f2,f4,f8,f9) (\
(f2)=mul2(x,f2), \
(f4)=mul2(f2,f4), \
(f8)=mul2(f4,f8), \
(f9)=(x)^(f8), \
(f8)=((f2)^(f4)^(f8)), \
(f2)^=(f9), \
(f4)^=(f9), \
(f8)^=rot3(f2), \
(f8)^=rot2(f4), \
(f8)^rot1(f9))
/*
* AES S-box
*/
static const uint8_t aes_sbox[256] =
{
0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,
0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76,
0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,
0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0,
0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,
0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15,
0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,
0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75,
0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,
0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84,
0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,
0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF,
0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,
0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8,
0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,
0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2,
0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,
0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73,
0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,
0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB,
0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,
0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79,
0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,
0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08,
0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,
0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A,
0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,
0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E,
0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,
0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF,
0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,
0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16,
};
/*
* AES is-box
*/
static const uint8_t aes_isbox[256] =
{
0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,
0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,
0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,
0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,
0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,
0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,
0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,
0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,
0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,
0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,
0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,
0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,
0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,
0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,
0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,
0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,
0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,
0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,
0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,
0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,
0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,
0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,
0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,
0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,
0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,
0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,
0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,
0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,
0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,
0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,
0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
};
static const unsigned char Rcon[30]=
{
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,
0x1b,0x36,0x6c,0xd8,0xab,0x4d,0x9a,0x2f,
0x5e,0xbc,0x63,0xc6,0x97,0x35,0x6a,0xd4,
0xb3,0x7d,0xfa,0xef,0xc5,0x91,
};
/* ----- static functions ----- */
static void AES_encrypt(const AES_CTX *ctx, uint32_t *data);
static void AES_decrypt(const AES_CTX *ctx, uint32_t *data);
/* Perform doubling in Galois Field GF(2^8) using the irreducible polynomial
x^8+x^4+x^3+x+1 */
static unsigned char AES_xtime(uint32_t x)
{
return x = (x&0x80) ? (x<<1)^0x1b : x<<1;
}
/**
* Set up AES with the key/iv and cipher size.
*/
void AES_set_key(AES_CTX *ctx, const uint8_t *key,
const uint8_t *iv, AES_MODE mode)
{
int i, ii;
uint32_t *W, tmp, tmp2;
const unsigned char *ip;
int words;
switch (mode)
{
case AES_MODE_128:
i = 10;
words = 4;
break;
case AES_MODE_256:
i = 14;
words = 8;
break;
default: /* fail silently */
return;
}
ctx->rounds = i;
ctx->key_size = words;
W = ctx->ks;
for (i = 0; i < words; i+=2)
{
W[i+0]= ((uint32_t)key[ 0]<<24)|
((uint32_t)key[ 1]<<16)|
((uint32_t)key[ 2]<< 8)|
((uint32_t)key[ 3] );
W[i+1]= ((uint32_t)key[ 4]<<24)|
((uint32_t)key[ 5]<<16)|
((uint32_t)key[ 6]<< 8)|
((uint32_t)key[ 7] );
key += 8;
}
ip = Rcon;
ii = 4 * (ctx->rounds+1);
for (i = words; i<ii; i++)
{
tmp = W[i-1];
if ((i % words) == 0)
{
tmp2 =(uint32_t)aes_sbox[(tmp )&0xff]<< 8;
tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<<16;
tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<24;
tmp2|=(uint32_t)aes_sbox[(tmp>>24) ];
tmp=tmp2^(((unsigned int)*ip)<<24);
ip++;
}
if ((words == 8) && ((i % words) == 4))
{
tmp2 =(uint32_t)aes_sbox[(tmp )&0xff] ;
tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<< 8;
tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<16;
tmp2|=(uint32_t)aes_sbox[(tmp>>24) ]<<24;
tmp=tmp2;
}
W[i]=W[i-words]^tmp;
}
/* copy the iv across */
memcpy(ctx->iv, iv, 16);
}
/**
* Change a key for decryption.
*/
void AES_convert_key(AES_CTX *ctx)
{
int i;
uint32_t *k,w,t1,t2,t3,t4;
k = ctx->ks;
k += 4;
for (i= ctx->rounds*4; i > 4; i--)
{
w= *k;
w = inv_mix_col(w,t1,t2,t3,t4);
*k++ =w;
}
}
/**
* Encrypt a byte sequence (with a block size 16) using the AES cipher.
*/
void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
{
int i;
uint32_t tin[4], tout[4], iv[4];
memcpy(iv, ctx->iv, AES_IV_SIZE);
for (i = 0; i < 4; i++)
tout[i] = ntohl(iv[i]);
for (length -= AES_BLOCKSIZE; length >= 0; length -= AES_BLOCKSIZE)
{
uint32_t msg_32[4];
uint32_t out_32[4];
memcpy(msg_32, msg, AES_BLOCKSIZE);
msg += AES_BLOCKSIZE;
for (i = 0; i < 4; i++)
tin[i] = ntohl(msg_32[i])^tout[i];
AES_encrypt(ctx, tin);
for (i = 0; i < 4; i++)
{
tout[i] = tin[i];
out_32[i] = htonl(tout[i]);
}
memcpy(out, out_32, AES_BLOCKSIZE);
out += AES_BLOCKSIZE;
}
for (i = 0; i < 4; i++)
iv[i] = htonl(tout[i]);
memcpy(ctx->iv, iv, AES_IV_SIZE);
}
/**
* Decrypt a byte sequence (with a block size 16) using the AES cipher.
*/
void AES_cbc_decrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
{
int i;
uint32_t tin[4], xor[4], tout[4], data[4], iv[4];
memcpy(iv, ctx->iv, AES_IV_SIZE);
for (i = 0; i < 4; i++)
xor[i] = ntohl(iv[i]);
for (length -= 16; length >= 0; length -= 16)
{
uint32_t msg_32[4];
uint32_t out_32[4];
memcpy(msg_32, msg, AES_BLOCKSIZE);
msg += AES_BLOCKSIZE;
for (i = 0; i < 4; i++)
{
tin[i] = ntohl(msg_32[i]);
data[i] = tin[i];
}
AES_decrypt(ctx, data);
for (i = 0; i < 4; i++)
{
tout[i] = data[i]^xor[i];
xor[i] = tin[i];
out_32[i] = htonl(tout[i]);
}
memcpy(out, out_32, AES_BLOCKSIZE);
out += AES_BLOCKSIZE;
}
for (i = 0; i < 4; i++)
iv[i] = htonl(xor[i]);
memcpy(ctx->iv, iv, AES_IV_SIZE);
}
/**
* Encrypt a single block (16 bytes) of data
*/
static void AES_encrypt(const AES_CTX *ctx, uint32_t *data)
{
/* To make this code smaller, generate the sbox entries on the fly.
* This will have a really heavy effect upon performance.
*/
uint32_t tmp[4];
uint32_t tmp1, old_a0, a0, a1, a2, a3, row;
int curr_rnd;
int rounds = ctx->rounds;
const uint32_t *k = ctx->ks;
/* Pre-round key addition */
for (row = 0; row < 4; row++)
data[row] ^= *(k++);
/* Encrypt one block. */
for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++)
{
/* Perform ByteSub and ShiftRow operations together */
for (row = 0; row < 4; row++)
{
a0 = (uint32_t)aes_sbox[(data[row%4]>>24)&0xFF];
a1 = (uint32_t)aes_sbox[(data[(row+1)%4]>>16)&0xFF];
a2 = (uint32_t)aes_sbox[(data[(row+2)%4]>>8)&0xFF];
a3 = (uint32_t)aes_sbox[(data[(row+3)%4])&0xFF];
/* Perform MixColumn iff not last round */
if (curr_rnd < (rounds - 1))
{
tmp1 = a0 ^ a1 ^ a2 ^ a3;
old_a0 = a0;
a0 ^= tmp1 ^ AES_xtime(a0 ^ a1);
a1 ^= tmp1 ^ AES_xtime(a1 ^ a2);
a2 ^= tmp1 ^ AES_xtime(a2 ^ a3);
a3 ^= tmp1 ^ AES_xtime(a3 ^ old_a0);
}
tmp[row] = ((a0 << 24) | (a1 << 16) | (a2 << 8) | a3);
}
/* KeyAddition - note that it is vital that this loop is separate from
the MixColumn operation, which must be atomic...*/
for (row = 0; row < 4; row++)
data[row] = tmp[row] ^ *(k++);
}
}
/**
* Decrypt a single block (16 bytes) of data
*/
static void AES_decrypt(const AES_CTX *ctx, uint32_t *data)
{
uint32_t tmp[4];
uint32_t xt0,xt1,xt2,xt3,xt4,xt5,xt6;
uint32_t a0, a1, a2, a3, row;
int curr_rnd;
int rounds = ctx->rounds;
const uint32_t *k = ctx->ks + ((rounds+1)*4);
/* pre-round key addition */
for (row=4; row > 0;row--)
data[row-1] ^= *(--k);
/* Decrypt one block */
for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++)
{
/* Perform ByteSub and ShiftRow operations together */
for (row = 4; row > 0; row--)
{
a0 = aes_isbox[(data[(row+3)%4]>>24)&0xFF];
a1 = aes_isbox[(data[(row+2)%4]>>16)&0xFF];
a2 = aes_isbox[(data[(row+1)%4]>>8)&0xFF];
a3 = aes_isbox[(data[row%4])&0xFF];
/* Perform MixColumn iff not last round */
if (curr_rnd<(rounds-1))
{
/* The MDS cofefficients (0x09, 0x0B, 0x0D, 0x0E)
are quite large compared to encryption; this
operation slows decryption down noticeably. */
xt0 = AES_xtime(a0^a1);
xt1 = AES_xtime(a1^a2);
xt2 = AES_xtime(a2^a3);
xt3 = AES_xtime(a3^a0);
xt4 = AES_xtime(xt0^xt1);
xt5 = AES_xtime(xt1^xt2);
xt6 = AES_xtime(xt4^xt5);
xt0 ^= a1^a2^a3^xt4^xt6;
xt1 ^= a0^a2^a3^xt5^xt6;
xt2 ^= a0^a1^a3^xt4^xt6;
xt3 ^= a0^a1^a2^xt5^xt6;
tmp[row-1] = ((xt0<<24)|(xt1<<16)|(xt2<<8)|xt3);
}
else
tmp[row-1] = ((a0<<24)|(a1<<16)|(a2<<8)|a3);
}
for (row = 4; row > 0; row--)
data[row-1] = tmp[row-1] ^ *(--k);
}
}
#endif

864
ssl/asn1.c Normal file
View File

@ -0,0 +1,864 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* @file asn1.c
*
* Some primitive asn methods for extraction rsa modulus information. It also
* is used for retrieving information from X.509 certificates.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "crypto.h"
#define SIG_OID_PREFIX_SIZE 8
#define SIG_TYPE_MD2 0x02
#define SIG_TYPE_MD5 0x04
#define SIG_TYPE_SHA1 0x05
/* Must be an RSA algorithm with either SHA1 or MD5 for verifying to work */
static const uint8_t sig_oid_prefix[SIG_OID_PREFIX_SIZE] =
{
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01
};
/* CN, O, OU */
static const uint8_t g_dn_types[] = { 3, 10, 11 };
static int get_asn1_length(const uint8_t *buf, int *offset)
{
int len, i;
if (!(buf[*offset] & 0x80)) /* short form */
{
len = buf[(*offset)++];
}
else /* long form */
{
int length_bytes = buf[(*offset)++]&0x7f;
len = 0;
for (i = 0; i < length_bytes; i++)
{
len <<= 8;
len += buf[(*offset)++];
}
}
return len;
}
/**
* Skip the ASN1.1 object type and its length. Get ready to read the object's
* data.
*/
int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type)
{
if (buf[*offset] != obj_type)
return X509_NOT_OK;
(*offset)++;
return get_asn1_length(buf, offset);
}
/**
* Skip over an ASN.1 object type completely. Get ready to read the next
* object.
*/
int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type)
{
int len;
if (buf[*offset] != obj_type)
return X509_NOT_OK;
(*offset)++;
len = get_asn1_length(buf, offset);
*offset += len;
return 0;
}
/**
* Read an integer value for ASN.1 data
* Note: This function allocates memory which must be freed by the user.
*/
int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object)
{
int len;
if ((len = asn1_next_obj(buf, offset, ASN1_INTEGER)) < 0)
goto end_int_array;
*object = (uint8_t *)malloc(len);
memcpy(*object, &buf[*offset], len);
*offset += len;
end_int_array:
return len;
}
/**
* Get all the RSA private key specifics from an ASN.1 encoded file
*/
int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx)
{
int offset = 7;
uint8_t *modulus, *priv_exp, *pub_exp;
int mod_len, priv_len, pub_len;
#ifdef CONFIG_BIGINT_CRT
uint8_t *p, *q, *dP, *dQ, *qInv;
int p_len, q_len, dP_len, dQ_len, qInv_len;
#endif
/* not in der format */
if (buf[0] != ASN1_SEQUENCE) /* basic sanity check */
{
#ifdef CONFIG_SSL_FULL_MODE
printf("Error: This is not a valid ASN.1 file\n");
#endif
return X509_INVALID_PRIV_KEY;
}
/* initialise the RNG */
RNG_initialize(buf, len);
mod_len = asn1_get_int(buf, &offset, &modulus);
pub_len = asn1_get_int(buf, &offset, &pub_exp);
priv_len = asn1_get_int(buf, &offset, &priv_exp);
if (mod_len <= 0 || pub_len <= 0 || priv_len <= 0)
return X509_INVALID_PRIV_KEY;
#ifdef CONFIG_BIGINT_CRT
p_len = asn1_get_int(buf, &offset, &p);
q_len = asn1_get_int(buf, &offset, &q);
dP_len = asn1_get_int(buf, &offset, &dP);
dQ_len = asn1_get_int(buf, &offset, &dQ);
qInv_len = asn1_get_int(buf, &offset, &qInv);
if (p_len <= 0 || q_len <= 0 || dP_len <= 0 || dQ_len <= 0 || qInv_len <= 0)
return X509_INVALID_PRIV_KEY;
RSA_priv_key_new(rsa_ctx,
modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len,
p, p_len, q, p_len, dP, dP_len, dQ, dQ_len, qInv, qInv_len);
free(p);
free(q);
free(dP);
free(dQ);
free(qInv);
#else
RSA_priv_key_new(rsa_ctx,
modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len);
#endif
free(modulus);
free(priv_exp);
free(pub_exp);
return X509_OK;
}
/**
* Get the time of a certificate. Ignore hours/minutes/seconds.
*/
static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
{
int ret = X509_NOT_OK, len, t_offset;
struct tm tm;
if (buf[(*offset)++] != ASN1_UTC_TIME)
goto end_utc_time;
len = get_asn1_length(buf, offset);
t_offset = *offset;
memset(&tm, 0, sizeof(struct tm));
tm.tm_year = (buf[t_offset] - '0')*10 + (buf[t_offset+1] - '0');
if (tm.tm_year <= 50) /* 1951-2050 thing */
{
tm.tm_year += 100;
}
tm.tm_mon = (buf[t_offset+2] - '0')*10 + (buf[t_offset+3] - '0') - 1;
tm.tm_mday = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0');
*t = mktime(&tm);
*offset += len;
ret = X509_OK;
end_utc_time:
return ret;
}
/**
* Get the version type of a certificate (which we don't actually care about)
*/
static int asn1_version(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
{
int ret = X509_NOT_OK;
(*offset) += 2; /* get past explicit tag */
if (asn1_skip_obj(cert, offset, ASN1_INTEGER))
goto end_version;
ret = X509_OK;
end_version:
return ret;
}
/**
* Retrieve the notbefore and notafter certificate times.
*/
static int asn1_validity(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
{
return (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
asn1_get_utc_time(cert, offset, &x509_ctx->not_before) ||
asn1_get_utc_time(cert, offset, &x509_ctx->not_after));
}
/**
* Get the components of a distinguished name
*/
static int asn1_get_oid_x520(const uint8_t *buf, int *offset)
{
int dn_type = 0;
int len;
if ((len = asn1_next_obj(buf, offset, ASN1_OID)) < 0)
goto end_oid;
/* expect a sequence of 2.5.4.[x] where x is a one of distinguished name
components we are interested in. */
if (len == 3 && buf[(*offset)++] == 0x55 && buf[(*offset)++] == 0x04)
dn_type = buf[(*offset)++];
else
{
*offset += len; /* skip over it */
}
end_oid:
return dn_type;
}
/**
* Obtain an ASN.1 printable string type.
*/
static int asn1_get_printable_str(const uint8_t *buf, int *offset, char **str)
{
int len = X509_NOT_OK;
/* some certs have this awful crud in them for some reason */
if (buf[*offset] != ASN1_PRINTABLE_STR &&
buf[*offset] != ASN1_TELETEX_STR && buf[*offset] != ASN1_IA5_STR)
goto end_pnt_str;
(*offset)++;
len = get_asn1_length(buf, offset);
*str = (char *)malloc(len+1); /* allow for null */
memcpy(*str, &buf[*offset], len);
(*str)[len] = 0; /* null terminate */
*offset += len;
end_pnt_str:
return len;
}
/**
* Get the subject name (or the issuer) of a certificate.
*/
static int asn1_name(const uint8_t *cert, int *offset, char *dn[])
{
int ret = X509_NOT_OK;
int dn_type;
char *tmp = NULL;
if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
goto end_name;
while (asn1_next_obj(cert, offset, ASN1_SET) >= 0)
{
int i, found = 0;
if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
(dn_type = asn1_get_oid_x520(cert, offset)) < 0)
goto end_name;
if (asn1_get_printable_str(cert, offset, &tmp) < 0)
{
free(tmp);
goto end_name;
}
/* find the distinguished named type */
for (i = 0; i < X509_NUM_DN_TYPES; i++)
{
if (dn_type == g_dn_types[i])
{
if (dn[i] == NULL)
{
dn[i] = tmp;
found = 1;
break;
}
}
}
if (found == 0) /* not found so get rid of it */
{
free(tmp);
}
}
ret = X509_OK;
end_name:
return ret;
}
/**
* Read the modulus and public exponent of a certificate.
*/
static int asn1_public_key(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
{
int ret = X509_NOT_OK, mod_len, pub_len;
uint8_t *modulus, *pub_exp;
if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
asn1_skip_obj(cert, offset, ASN1_SEQUENCE) ||
asn1_next_obj(cert, offset, ASN1_BIT_STRING) < 0)
goto end_pub_key;
(*offset)++;
if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
goto end_pub_key;
mod_len = asn1_get_int(cert, offset, &modulus);
pub_len = asn1_get_int(cert, offset, &pub_exp);
RSA_pub_key_new(&x509_ctx->rsa_ctx, modulus, mod_len, pub_exp, pub_len);
free(modulus);
free(pub_exp);
ret = X509_OK;
end_pub_key:
return ret;
}
#ifdef CONFIG_SSL_CERT_VERIFICATION
/**
* Read the signature of the certificate.
*/
static int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
{
int ret = X509_NOT_OK;
if (cert[(*offset)++] != ASN1_BIT_STRING)
goto end_sig;
x509_ctx->sig_len = get_asn1_length(cert, offset);
x509_ctx->signature = (uint8_t *)malloc(x509_ctx->sig_len);
memcpy(x509_ctx->signature, &cert[*offset], x509_ctx->sig_len);
*offset += x509_ctx->sig_len;
ret = X509_OK;
end_sig:
return ret;
}
/*
* Compare 2 distinguished name components for equality
* @return 0 if a match
*/
static int asn1_compare_dn_comp(const char *dn1, const char *dn2)
{
int ret = 1;
if ((dn1 && dn2 == NULL) || (dn1 == NULL && dn2)) goto err_no_match;
ret = (dn1 && dn2) ? strcmp(dn1, dn2) : 0;
err_no_match:
return ret;
}
/**
* Clean up all of the CA certificates.
*/
void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx)
{
int i = 0;
while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
{
x509_free(ca_cert_ctx->cert[i]);
ca_cert_ctx->cert[i++] = NULL;
}
free(ca_cert_ctx);
}
/*
* Compare 2 distinguished names for equality
* @return 0 if a match
*/
static int asn1_compare_dn(char * const dn1[], char * const dn2[])
{
int i;
for (i = 0; i < X509_NUM_DN_TYPES; i++)
{
if (asn1_compare_dn_comp(dn1[i], dn2[i]))
{
return 1;
}
}
return 0; /* all good */
}
/**
* Retrieve the signature from a certificate.
*/
const uint8_t *x509_get_signature(const uint8_t *asn1_sig, int *len)
{
int offset = 0;
const uint8_t *ptr = NULL;
if (asn1_next_obj(asn1_sig, &offset, ASN1_SEQUENCE) < 0 ||
asn1_skip_obj(asn1_sig, &offset, ASN1_SEQUENCE))
goto end_get_sig;
if (asn1_sig[offset++] != ASN1_OCTET_STRING)
goto end_get_sig;
*len = get_asn1_length(asn1_sig, &offset);
ptr = &asn1_sig[offset]; /* all ok */
end_get_sig:
return ptr;
}
#endif
/**
* Read the signature type of the certificate. We only support RSA-MD5 and
* RSA-SHA1 signature types.
*/
static int asn1_signature_type(const uint8_t *cert,
int *offset, X509_CTX *x509_ctx)
{
int ret = X509_NOT_OK, len;
if (cert[(*offset)++] != ASN1_OID)
goto end_check_sig;
len = get_asn1_length(cert, offset);
if (memcmp(sig_oid_prefix, &cert[*offset], SIG_OID_PREFIX_SIZE))
goto end_check_sig; /* unrecognised cert type */
x509_ctx->sig_type = cert[*offset + SIG_OID_PREFIX_SIZE];
*offset += len;
if (asn1_skip_obj(cert, offset, ASN1_NULL))
goto end_check_sig;
ret = X509_OK;
end_check_sig:
return ret;
}
/**
* Construct a new x509 object.
* @return 0 if ok. < 0 if there was a problem.
*/
int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
{
int begin_tbs, end_tbs;
int ret = X509_NOT_OK, offset = 0, cert_size = 0;
X509_CTX *x509_ctx;
BI_CTX *bi_ctx;
*ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX));
x509_ctx = *ctx;
/* get the certificate size */
asn1_skip_obj(cert, &cert_size, ASN1_SEQUENCE);
if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
goto end_cert;
begin_tbs = offset; /* start of the tbs */
end_tbs = begin_tbs; /* work out the end of the tbs */
asn1_skip_obj(cert, &end_tbs, ASN1_SEQUENCE);
if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
goto end_cert;
if (cert[offset] == ASN1_EXPLICIT_TAG) /* optional version */
{
if (asn1_version(cert, &offset, x509_ctx))
goto end_cert;
}
if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */
asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
goto end_cert;
/* make sure the signature is ok */
if (asn1_signature_type(cert, &offset, x509_ctx))
{
ret = X509_VFY_ERROR_UNSUPPORTED_DIGEST;
goto end_cert;
}
if (asn1_name(cert, &offset, x509_ctx->ca_cert_dn) ||
asn1_validity(cert, &offset, x509_ctx) ||
asn1_name(cert, &offset, x509_ctx->cert_dn) ||
asn1_public_key(cert, &offset, x509_ctx))
goto end_cert;
bi_ctx = x509_ctx->rsa_ctx->bi_ctx;
#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
/* use the appropriate signature algorithm (either SHA1 or MD5) */
if (x509_ctx->sig_type == SIG_TYPE_MD5)
{
MD5_CTX md5_ctx;
uint8_t md5_dgst[MD5_SIZE];
MD5Init(&md5_ctx);
MD5Update(&md5_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
MD5Final(&md5_ctx, md5_dgst);
x509_ctx->digest = bi_import(bi_ctx, md5_dgst, MD5_SIZE);
}
else if (x509_ctx->sig_type == SIG_TYPE_SHA1)
{
SHA1_CTX sha_ctx;
uint8_t sha_dgst[SHA1_SIZE];
SHA1Init(&sha_ctx);
SHA1Update(&sha_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
SHA1Final(&sha_ctx, sha_dgst);
x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE);
}
offset = end_tbs; /* skip the v3 data */
if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) ||
asn1_signature(cert, &offset, x509_ctx))
goto end_cert;
#endif
if (len)
{
*len = cert_size;
}
ret = X509_OK;
end_cert:
#ifdef CONFIG_SSL_FULL_MODE
if (ret)
{
printf("Error: Invalid X509 ASN.1 file\n");
}
#endif
return ret;
}
/**
* Free an X.509 object's resources.
*/
void x509_free(X509_CTX *x509_ctx)
{
X509_CTX *next;
int i;
if (x509_ctx == NULL) /* if already null, then don't bother */
return;
for (i = 0; i < X509_NUM_DN_TYPES; i++)
{
free(x509_ctx->ca_cert_dn[i]);
free(x509_ctx->cert_dn[i]);
}
free(x509_ctx->signature);
#ifdef CONFIG_SSL_CERT_VERIFICATION
if (x509_ctx->digest)
{
bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->digest);
}
#endif
RSA_free(x509_ctx->rsa_ctx);
next = x509_ctx->next;
free(x509_ctx);
x509_free(next); /* clear the chain */
}
#ifdef CONFIG_SSL_CERT_VERIFICATION
/**
* Do some basic checks on the certificate chain.
*
* Certificate verification consists of a number of checks:
* - A root certificate exists in the certificate store.
* - The date of the certificate is after the start date.
* - The date of the certificate is before the finish date.
* - The certificate chain is valid.
* - That the certificate(s) are not self-signed.
* - The signature of the certificate is valid.
*/
int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert)
{
int ret = X509_OK, i = 0;
bigint *cert_sig;
X509_CTX *next_cert = NULL;
BI_CTX *ctx;
bigint *mod, *expn;
struct timeval tv;
int match_ca_cert = 0;
if (cert == NULL || ca_cert_ctx == NULL)
{
ret = X509_VFY_ERROR_NO_TRUSTED_CERT;
goto end_verify;
}
/* last cert in the chain - look for a trusted cert */
if (cert->next == NULL)
{
while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
{
if (asn1_compare_dn(cert->ca_cert_dn,
ca_cert_ctx->cert[i]->cert_dn) == 0)
{
match_ca_cert = 1;
break;
}
i++;
}
if (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
{
next_cert = ca_cert_ctx->cert[i];
}
else /* trusted cert not found */
{
ret = X509_VFY_ERROR_NO_TRUSTED_CERT;
goto end_verify;
}
}
else
{
next_cert = cert->next;
}
gettimeofday(&tv, NULL);
/* check the not before date */
if (tv.tv_sec < cert->not_before)
{
ret = X509_VFY_ERROR_NOT_YET_VALID;
goto end_verify;
}
/* check the not after date */
if (tv.tv_sec > cert->not_after)
{
ret = X509_VFY_ERROR_EXPIRED;
goto end_verify;
}
/* check the chain integrity */
if (asn1_compare_dn(cert->ca_cert_dn, next_cert->cert_dn))
{
ret = X509_VFY_ERROR_INVALID_CHAIN;
goto end_verify;
}
/* check for self-signing */
if (!match_ca_cert && asn1_compare_dn(cert->ca_cert_dn, cert->cert_dn) == 0)
{
ret = X509_VFY_ERROR_SELF_SIGNED;
goto end_verify;
}
/* check the signature */
ctx = cert->rsa_ctx->bi_ctx;
mod = next_cert->rsa_ctx->m;
expn = next_cert->rsa_ctx->e;
cert_sig = RSA_sign_verify(ctx, cert->signature, cert->sig_len,
bi_clone(ctx, mod), bi_clone(ctx, expn));
if (cert_sig)
{
ret = cert->digest ? /* check the signature */
bi_compare(cert_sig, cert->digest) :
X509_VFY_ERROR_UNSUPPORTED_DIGEST;
bi_free(ctx, cert_sig);
if (ret)
goto end_verify;
}
else
{
ret = X509_VFY_ERROR_BAD_SIGNATURE;
goto end_verify;
}
/* go down the certificate chain using recursion. */
if (ret == 0 && cert->next)
{
ret = x509_verify(ca_cert_ctx, next_cert);
}
end_verify:
return ret;
}
#endif
#if defined (CONFIG_SSL_FULL_MODE)
/**
* Used for diagnostics.
*/
void x509_print(CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert)
{
if (cert == NULL)
return;
printf("---------------- CERT DEBUG ----------------\n");
printf("* CA Cert Distinguished Name\n");
if (cert->ca_cert_dn[X509_COMMON_NAME])
{
printf("Common Name (CN):\t%s\n", cert->ca_cert_dn[X509_COMMON_NAME]);
}
if (cert->ca_cert_dn[X509_ORGANIZATION])
{
printf("Organization (O):\t%s\n", cert->ca_cert_dn[X509_ORGANIZATION]);
}
if (cert->ca_cert_dn[X509_ORGANIZATIONAL_TYPE])
{
printf("Organizational Unit (OU): %s\n",
cert->ca_cert_dn[X509_ORGANIZATIONAL_TYPE]);
}
printf("* Cert Distinguished Name\n");
if (cert->cert_dn[X509_COMMON_NAME])
{
printf("Common Name (CN):\t%s\n", cert->cert_dn[X509_COMMON_NAME]);
}
if (cert->cert_dn[X509_ORGANIZATION])
{
printf("Organization (O):\t%s\n", cert->cert_dn[X509_ORGANIZATION]);
}
if (cert->cert_dn[X509_ORGANIZATIONAL_TYPE])
{
printf("Organizational Unit (OU): %s\n",
cert->cert_dn[X509_ORGANIZATIONAL_TYPE]);
}
printf("Not Before:\t\t%s", ctime(&cert->not_before));
printf("Not After:\t\t%s", ctime(&cert->not_after));
printf("RSA bitsize:\t\t%d\n", cert->rsa_ctx->num_octets*8);
printf("Sig Type:\t\t");
switch (cert->sig_type)
{
case SIG_TYPE_MD5:
printf("MD5\n");
break;
case SIG_TYPE_SHA1:
printf("SHA1\n");
break;
case SIG_TYPE_MD2:
printf("MD2\n");
break;
default:
printf("Unrecognized: %d\n", cert->sig_type);
break;
}
printf("Verify:\t\t\t");
if (ca_cert_ctx)
{
x509_display_error(x509_verify(ca_cert_ctx, cert));
}
printf("\n");
#if 0
print_blob("Signature", cert->signature, cert->sig_len);
bi_print("Modulus", cert->rsa_ctx->m);
bi_print("Pub Exp", cert->rsa_ctx->e);
#endif
if (ca_cert_ctx)
{
x509_print(ca_cert_ctx, cert->next);
}
}
void x509_display_error(int error)
{
switch (error)
{
case X509_NOT_OK:
printf("X509 not ok");
break;
case X509_VFY_ERROR_NO_TRUSTED_CERT:
printf("No trusted cert is available");
break;
case X509_VFY_ERROR_BAD_SIGNATURE:
printf("Bad signature");
break;
case X509_VFY_ERROR_NOT_YET_VALID:
printf("Cert is not yet valid");
break;
case X509_VFY_ERROR_EXPIRED:
printf("Cert has expired");
break;
case X509_VFY_ERROR_SELF_SIGNED:
printf("Cert is self-signed");
break;
case X509_VFY_ERROR_INVALID_CHAIN:
printf("Chain is invalid (check order of certs)");
break;
case X509_VFY_ERROR_UNSUPPORTED_DIGEST:
printf("Unsupported digest");
break;
case X509_INVALID_PRIV_KEY:
printf("Invalid private key");
break;
}
}
#endif /* CONFIG_SSL_FULL_MODE */

1506
ssl/bigint.c Normal file

File diff suppressed because it is too large Load Diff

93
ssl/bigint.h Normal file
View File

@ -0,0 +1,93 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef BIGINT_HEADER
#define BIGINT_HEADER
#include "config.h"
/* enable features based on a 'super-set' capbaility. */
#if defined(CONFIG_SSL_FULL_MODE)
#define CONFIG_SSL_ENABLE_CLIENT
#define CONFIG_SSL_CERT_VERIFICATION
#elif defined(CONFIG_SSL_ENABLE_CLIENT)
#define CONFIG_SSL_CERT_VERIFICATION
#endif
#include "os_port.h"
#include "bigint_impl.h"
#ifndef CONFIG_BIGINT_CHECK_ON
#define check(A) /**< disappears in normal production mode */
#endif
BI_CTX *bi_initialize(void);
void bi_terminate(BI_CTX *ctx);
void bi_permanent(bigint *bi);
void bi_depermanent(bigint *bi);
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
#endif

105
ssl/bigint_impl.h Normal file
View File

@ -0,0 +1,105 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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. */
#define V1 v->comps[v->size-1] /**< v1 for division */
#define V2 v->comps[v->size-2] /**< v2 for division */
#define U(j) tmp_u->comps[tmp_u->size-j-1] /**< uj for division */
#define Q(j) quotient->comps[quotient->size-j-1] /**< qj for division */
#endif

43
ssl/cert.h Normal file
View File

@ -0,0 +1,43 @@
unsigned char default_certificate[] = {
0x30, 0x82, 0x01, 0xd7, 0x30, 0x82, 0x01, 0x40, 0x02, 0x09, 0x00, 0xf1,
0xc3, 0x87, 0xc0, 0xd4, 0xf4, 0x57, 0xc3, 0x30, 0x0d, 0x06, 0x09, 0x2a,
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x34,
0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x29, 0x61,
0x78, 0x54, 0x4c, 0x53, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
0x20, 0x44, 0x6f, 0x64, 0x67, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69,
0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f,
0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36,
0x30, 0x37, 0x31, 0x31, 0x34, 0x34, 0x33, 0x32, 0x5a, 0x17, 0x0d, 0x33,
0x33, 0x31, 0x30, 0x32, 0x33, 0x31, 0x31, 0x34, 0x34, 0x33, 0x32, 0x5a,
0x30, 0x2c, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
0x0d, 0x61, 0x78, 0x54, 0x4c, 0x53, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65,
0x63, 0x74, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x81,
0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02,
0x81, 0x81, 0x00, 0xd8, 0xe0, 0xbf, 0x15, 0xde, 0xea, 0xaf, 0xe8, 0xd5,
0xfd, 0x0b, 0xa8, 0xa8, 0xb3, 0xd7, 0x46, 0x5d, 0xa7, 0x26, 0x6c, 0x0c,
0xb5, 0xd9, 0xbc, 0xc6, 0xf8, 0xc0, 0x78, 0xd0, 0xf6, 0x56, 0x65, 0xf8,
0x29, 0x48, 0x0e, 0x7b, 0x0b, 0xa6, 0x25, 0x7e, 0xe8, 0x7b, 0x79, 0x6f,
0x38, 0xe5, 0xb5, 0xb7, 0xf4, 0xe0, 0x9c, 0x91, 0x60, 0xf4, 0x06, 0xf3,
0x40, 0x1e, 0xf9, 0x91, 0x19, 0xa9, 0x2f, 0x47, 0x43, 0xb5, 0x9b, 0x1e,
0xdc, 0xf6, 0xaa, 0x1c, 0x49, 0x79, 0x21, 0x28, 0xcb, 0xaa, 0x49, 0x73,
0xd9, 0x09, 0x05, 0x4c, 0x02, 0xf2, 0x4c, 0x4d, 0x6c, 0x1c, 0x80, 0xa7,
0x14, 0x91, 0x44, 0xfc, 0x12, 0xb3, 0xe1, 0xe7, 0xe3, 0x4f, 0x44, 0xba,
0x8c, 0xc3, 0x74, 0x39, 0xe8, 0x4c, 0xd0, 0xd4, 0x4c, 0x24, 0x61, 0xb4,
0x40, 0x95, 0x8c, 0xc0, 0x0a, 0xb7, 0x02, 0x39, 0x31, 0x85, 0x93, 0x02,
0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x0b,
0x47, 0x24, 0x52, 0x7d, 0xb6, 0x63, 0x78, 0xbc, 0x80, 0xdd, 0x87, 0x6c,
0x90, 0x4c, 0x33, 0xc3, 0x5c, 0xa7, 0x97, 0x09, 0x1c, 0x09, 0x4f, 0x9b,
0x6e, 0xb3, 0x5a, 0x3e, 0x46, 0x92, 0x1a, 0xc7, 0x87, 0x15, 0x59, 0xe1,
0x88, 0x5c, 0xce, 0x6a, 0xe2, 0x96, 0xaa, 0x32, 0xec, 0xc2, 0xed, 0x78,
0x8b, 0xe0, 0x90, 0x66, 0x93, 0x14, 0xc3, 0x98, 0xab, 0x33, 0x35, 0xd3,
0x7d, 0x5d, 0x51, 0x0a, 0x9c, 0xb9, 0x10, 0x58, 0x47, 0x7a, 0x98, 0x95,
0x64, 0xff, 0x4c, 0x5d, 0x82, 0x19, 0xf9, 0xea, 0x0f, 0x5e, 0x9a, 0xcb,
0x32, 0x27, 0x64, 0xca, 0x6f, 0x58, 0x8a, 0xd0, 0xc0, 0x36, 0xf4, 0xb9,
0x63, 0x34, 0xa5, 0xda, 0x36, 0x50, 0x36, 0x49, 0xd2, 0xb7, 0x3a, 0x21,
0x33, 0x5b, 0x3e, 0xd6, 0x5f, 0x0c, 0x99, 0x83, 0xb7, 0xb2, 0xf7, 0x8b,
0x44, 0xc4, 0x5e, 0x73, 0x41, 0xa9, 0x02
};
unsigned int default_certificate_len = 475;

285
ssl/crypto.h Normal file
View File

@ -0,0 +1,285 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* @file crypto.h
*/
#ifndef HEADER_CRYPTO_H
#define HEADER_CRYPTO_H
#ifdef __cplusplus
extern "C" {
#endif
#include "bigint.h"
/**************************************************************************
* AES declarations
**************************************************************************/
#define AES_MAXROUNDS 14
#define AES_BLOCKSIZE 16
#define AES_IV_SIZE 16
typedef struct aes_key_st
{
uint16_t rounds;
uint16_t key_size;
uint32_t ks[(AES_MAXROUNDS+1)*8];
uint8_t iv[AES_IV_SIZE];
} AES_CTX;
typedef enum
{
AES_MODE_128,
AES_MODE_256
} AES_MODE;
void AES_set_key(AES_CTX *ctx, const uint8_t *key,
const uint8_t *iv, AES_MODE mode);
void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg,
uint8_t *out, int length);
void AES_cbc_decrypt(AES_CTX *ks, const uint8_t *in, uint8_t *out, int length);
void AES_convert_key(AES_CTX *ctx);
/**************************************************************************
* RC4 declarations
**************************************************************************/
typedef struct
{
int x, y, m[256];
} RC4_CTX;
void RC4_setup(RC4_CTX *s, const uint8_t *key, int length);
void RC4_crypt(RC4_CTX *s, const uint8_t *msg, uint8_t *data, int length);
/**************************************************************************
* SHA1 declarations
**************************************************************************/
#define SHA1_SIZE 20
/*
* This structure will hold context information for the SHA-1
* hashing operation
*/
typedef struct
{
uint32_t Intermediate_Hash[SHA1_SIZE/4]; /* Message Digest */
uint32_t Length_Low; /* Message length in bits */
uint32_t Length_High; /* Message length in bits */
uint16_t Message_Block_Index; /* Index into message block array */
uint8_t Message_Block[64]; /* 512-bit message blocks */
} SHA1_CTX;
void SHA1Init(SHA1_CTX *);
void SHA1Update(SHA1_CTX *, const uint8_t * msg, int len);
void SHA1Final(SHA1_CTX *, uint8_t *digest);
/**************************************************************************
* MD5 declarations
**************************************************************************/
/* MD5 context. */
#define MD5_SIZE 16
typedef struct
{
uint32_t state[4]; /* state (ABCD) */
uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
uint8_t buffer[64]; /* input buffer */
} MD5_CTX;
EXP_FUNC void STDCALL MD5Init(MD5_CTX *);
EXP_FUNC void STDCALL MD5Update(MD5_CTX *, const uint8_t *msg, int len);
EXP_FUNC void STDCALL MD5Final(MD5_CTX *, uint8_t *digest);
/**************************************************************************
* HMAC declarations
**************************************************************************/
void hmac_md5(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest);
void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest);
/**************************************************************************
* 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);
/**************************************************************************
* 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
/**************************************************************************
* ASN1 declarations
**************************************************************************/
#define X509_OK 0
#define X509_NOT_OK -1
#define X509_VFY_ERROR_NO_TRUSTED_CERT -2
#define X509_VFY_ERROR_BAD_SIGNATURE -3
#define X509_VFY_ERROR_NOT_YET_VALID -4
#define X509_VFY_ERROR_EXPIRED -5
#define X509_VFY_ERROR_SELF_SIGNED -6
#define X509_VFY_ERROR_INVALID_CHAIN -7
#define X509_VFY_ERROR_UNSUPPORTED_DIGEST -8
#define X509_INVALID_PRIV_KEY -9
/*
* The Distinguished Name
*/
#define X509_NUM_DN_TYPES 3
#define X509_COMMON_NAME 0
#define X509_ORGANIZATION 1
#define X509_ORGANIZATIONAL_TYPE 2
#define ASN1_INTEGER 0x02
#define ASN1_BIT_STRING 0x03
#define ASN1_OCTET_STRING 0x04
#define ASN1_NULL 0x05
#define ASN1_OID 0x06
#define ASN1_PRINTABLE_STR 0x13
#define ASN1_TELETEX_STR 0x14
#define ASN1_IA5_STR 0x16
#define ASN1_UTC_TIME 0x17
#define ASN1_SEQUENCE 0x30
#define ASN1_SET 0x31
#define ASN1_IMPLICIT_TAG 0x80
#define ASN1_EXPLICIT_TAG 0xa0
#define SALT_SIZE 8
struct _x509_ctx
{
char *ca_cert_dn[X509_NUM_DN_TYPES];
char *cert_dn[X509_NUM_DN_TYPES];
#if defined(_WIN32_WCE)
long not_before;
long not_after;
#else
time_t not_before;
time_t not_after;
#endif
uint8_t *signature;
uint16_t sig_len;
uint8_t sig_type;
RSA_CTX *rsa_ctx;
bigint *digest;
struct _x509_ctx *next;
};
typedef struct _x509_ctx X509_CTX;
#ifdef CONFIG_SSL_CERT_VERIFICATION
typedef struct
{
X509_CTX *cert[CONFIG_X509_MAX_CA_CERTS];
} CA_CERT_CTX;
#endif
int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx);
int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type);
int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type);
int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object);
int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx);
void x509_free(X509_CTX *x509_ctx);
#ifdef CONFIG_SSL_CERT_VERIFICATION
int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert);
const uint8_t *x509_get_signature(const uint8_t *asn1_signature, int *len);
#endif
#ifdef CONFIG_SSL_FULL_MODE
void x509_print(CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert);
void x509_display_error(int error);
#endif
/**************************************************************************
* MISC declarations
**************************************************************************/
extern const char * const unsupported_str;
typedef void (*crypt_func)(void *, const uint8_t *, uint8_t *, int);
typedef void (*hmac_func)(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest);
int get_file(const char *filename, uint8_t **buf);
#if defined(CONFIG_SSL_FULL_MODE) || defined(WIN32) || defined(CONFIG_DEBUG)
EXP_FUNC void STDCALL print_blob(const char *format, const uint8_t *data, int size, ...);
#else
#define print_blob(...)
#endif
EXP_FUNC int STDCALL base64_decode(const char *in, int len,
uint8_t *out, int *outlen);
#ifdef __cplusplus
}
#endif
#endif

345
ssl/crypto_misc.c Normal file
View File

@ -0,0 +1,345 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* Some misc. routines to help things out
*/
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include "crypto.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

88
ssl/hmac.c Normal file
View File

@ -0,0 +1,88 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* HMAC implementation - This code was originally taken from RFC2104
*/
#include <string.h>
#include "crypto.h"
/**
* Perform HMAC-MD5
*/
void hmac_md5(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest)
{
MD5_CTX context;
uint8_t k_ipad[64];
uint8_t k_opad[64];
int i;
memset(k_ipad, 0, sizeof k_ipad);
memset(k_opad, 0, sizeof k_opad);
memcpy(k_ipad, key, key_len);
memcpy(k_opad, key, key_len);
for (i = 0; i < 64; i++)
{
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
MD5Init(&context);
MD5Update(&context, k_ipad, 64);
MD5Update(&context, msg, length);
MD5Final(&context, digest);
MD5Init(&context);
MD5Update(&context, k_opad, 64);
MD5Update(&context, digest, MD5_SIZE);
MD5Final(&context, digest);
}
/**
* Perform HMAC-SHA1
*/
void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest)
{
SHA1_CTX context;
uint8_t k_ipad[64];
uint8_t k_opad[64];
int i;
memset(k_ipad, 0, sizeof k_ipad);
memset(k_opad, 0, sizeof k_opad);
memcpy(k_ipad, key, key_len);
memcpy(k_opad, key, key_len);
for (i = 0; i < 64; i++)
{
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
SHA1Init(&context);
SHA1Update(&context, k_ipad, 64);
SHA1Update(&context, msg, length);
SHA1Final(&context, digest);
SHA1Init(&context);
SHA1Update(&context, k_opad, 64);
SHA1Update(&context, digest, SHA1_SIZE);
SHA1Final(&context, digest);
}

375
ssl/loader.c Normal file
View File

@ -0,0 +1,375 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* Load certificates/keys into memory. These can be in many different formats.
* PEM support and other formats can be processed here.
*
* The PEM private keys may be optionally encrypted with AES128 or AES256.
* The encrypted PEM keys were generated with something like:
*
* openssl genrsa -aes128 -passout pass:abcd -out axTLS.key_aes128.pem 512
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "ssl.h"
static int do_obj(SSL_CTX *ssl_ctx, int obj_type,
SSLObjLoader *ssl_obj, const char *password);
#ifdef CONFIG_SSL_HAS_PEM
static int ssl_obj_PEM_load(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj,
const char *password);
#endif
/*
* Load a file into memory that is in binary DER (or ascii PEM) format.
*/
EXP_FUNC int STDCALL ssl_obj_load(SSL_CTX *ssl_ctx, int obj_type,
const char *filename, const char *password)
{
#ifndef CONFIG_SSL_SKELETON_MODE
static const char * const begin = "-----BEGIN";
int ret = SSL_OK;
SSLObjLoader *ssl_obj = NULL;
if (filename == NULL)
{
ret = SSL_ERROR_INVALID_KEY;
goto error;
}
ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader));
ssl_obj->len = get_file(filename, &ssl_obj->buf);
if (ssl_obj->len <= 0)
{
ret = SSL_ERROR_INVALID_KEY;
goto error;
}
/* is the file a PEM file? */
if (strncmp((char *)ssl_obj->buf, begin, strlen(begin)) == 0)
{
#ifdef CONFIG_SSL_HAS_PEM
ret = ssl_obj_PEM_load(ssl_ctx, ssl_obj, password);
#else
printf(unsupported_str);
ret = SSL_ERROR_NOT_SUPPORTED;
#endif
}
else
ret = do_obj(ssl_ctx, obj_type, ssl_obj, password);
error:
ssl_obj_free(ssl_obj);
return ret;
#else
printf(unsupported_str);
return SSL_ERROR_NOT_SUPPORTED;
#endif /* CONFIG_SSL_SKELETON_MODE */
}
/*
* Transfer binary data into the object loader.
*/
EXP_FUNC int STDCALL ssl_obj_memory_load(SSL_CTX *ssl_ctx, int mem_type,
const uint8_t *data, int len, const char *password)
{
int ret;
SSLObjLoader *ssl_obj;
ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader));
ssl_obj->buf = (uint8_t *)malloc(len);
memcpy(ssl_obj->buf, data, len);
ssl_obj->len = len;
ret = do_obj(ssl_ctx, mem_type, ssl_obj, password);
ssl_obj_free(ssl_obj);
return ret;
}
/*
* Actually work out what we are doing
*/
static int do_obj(SSL_CTX *ssl_ctx, int obj_type,
SSLObjLoader *ssl_obj, const char *password)
{
int ret = SSL_OK;
switch (obj_type)
{
case SSL_OBJ_RSA_KEY:
ret = add_private_key(ssl_ctx, ssl_obj);
break;
case SSL_OBJ_X509_CERT:
ret = add_cert(ssl_ctx, ssl_obj->buf, ssl_obj->len);
break;
#ifdef CONFIG_SSL_CERT_VERIFICATION
case SSL_OBJ_X509_CACERT:
ret = add_cert_auth(ssl_ctx, ssl_obj->buf, ssl_obj->len);
break;
#endif
#ifdef CONFIG_SSL_USE_PKCS12
case SSL_OBJ_PKCS8:
ret = pkcs8_decode(ssl_ctx, ssl_obj, password);
break;
case SSL_OBJ_PKCS12:
ret = pkcs12_decode(ssl_ctx, ssl_obj, password);
break;
#endif
default:
printf(unsupported_str);
ret = SSL_ERROR_NOT_SUPPORTED;
break;
}
return ret;
}
/*
* Clean up our mess.
*/
void ssl_obj_free(SSLObjLoader *ssl_obj)
{
if (ssl_obj)
{
free(ssl_obj->buf);
free(ssl_obj);
}
}
/*
* Support for PEM encoded keys/certificates.
*/
#ifdef CONFIG_SSL_HAS_PEM
#define NUM_PEM_TYPES 3
#define IV_SIZE 16
#define IS_RSA_PRIVATE_KEY 0
#define IS_ENCRYPTED_PRIVATE_KEY 1
#define IS_CERTIFICATE 2
static const char * const begins[NUM_PEM_TYPES] =
{
"-----BEGIN RSA PRIVATE KEY-----",
"-----BEGIN ENCRYPTED PRIVATE KEY-----",
"-----BEGIN CERTIFICATE-----",
};
static const char * const ends[NUM_PEM_TYPES] =
{
"-----END RSA PRIVATE KEY-----",
"-----END ENCRYPTED PRIVATE KEY-----",
"-----END CERTIFICATE-----",
};
static const char * const aes_str[2] =
{
"DEK-Info: AES-128-CBC,",
"DEK-Info: AES-256-CBC,"
};
/**
* Take a base64 blob of data and decrypt it (using AES) into its
* proper ASN.1 form.
*/
static int pem_decrypt(const char *where, const char *end,
const char *password, SSLObjLoader *ssl_obj)
{
int ret = -1;
int is_aes_256 = 0;
char *start = NULL;
uint8_t iv[IV_SIZE];
int i, pem_size;
MD5_CTX md5_ctx;
AES_CTX aes_ctx;
uint8_t key[32]; /* AES256 size */
if (password == NULL)
{
#ifdef CONFIG_SSL_FULL_MODE
printf("Error: need a password for this PEM file\n");
#endif
goto error;
}
if ((start = strstr((const char *)where, aes_str[0]))) /* AES128? */
{
start += strlen(aes_str[0]);
}
else if ((start = strstr((const char *)where, aes_str[1]))) /* AES256? */
{
is_aes_256 = 1;
start += strlen(aes_str[1]);
}
else
{
#ifdef CONFIG_SSL_FULL_MODE
printf("Error: Unsupported password cipher\n");
#endif
goto error;
}
/* convert from hex to binary - assumes uppercase hex */
for (i = 0; i < IV_SIZE; i++)
{
char c = *start++ - '0';
iv[i] = (c > 9 ? c + '0' - 'A' + 10 : c) << 4;
c = *start++ - '0';
iv[i] += (c > 9 ? c + '0' - 'A' + 10 : c);
}
while (*start == '\r' || *start == '\n')
start++;
/* turn base64 into binary */
pem_size = (int)(end-start);
if (base64_decode(start, pem_size, ssl_obj->buf, &ssl_obj->len) != 0)
goto error;
/* work out the key */
MD5Init(&md5_ctx);
MD5Update(&md5_ctx, (const uint8_t *)password, strlen(password));
MD5Update(&md5_ctx, iv, SALT_SIZE);
MD5Final(&md5_ctx, key);
if (is_aes_256)
{
MD5Init(&md5_ctx);
MD5Update(&md5_ctx, key, MD5_SIZE);
MD5Update(&md5_ctx, (const uint8_t *)password, strlen(password));
MD5Update(&md5_ctx, iv, SALT_SIZE);
MD5Final(&md5_ctx, &key[MD5_SIZE]);
}
/* decrypt using the key/iv */
AES_set_key(&aes_ctx, key, iv, is_aes_256 ? AES_MODE_256 : AES_MODE_128);
AES_convert_key(&aes_ctx);
AES_cbc_decrypt(&aes_ctx, ssl_obj->buf, ssl_obj->buf, ssl_obj->len);
ret = 0;
error:
return ret;
}
/**
* Take a base64 blob of data and turn it into its proper ASN.1 form.
*/
static int new_pem_obj(SSL_CTX *ssl_ctx, char *where,
int remain, const char *password)
{
int ret = SSL_OK;
SSLObjLoader *ssl_obj = NULL;
int i, pem_size, obj_type;
char *start = NULL, *end = NULL;
for (i = 0; i < NUM_PEM_TYPES; i++)
{
if ((start = strstr(where, begins[i])) &&
(end = strstr(where, ends[i])))
{
remain -= (int)(end-start);
start += strlen(begins[i]);
pem_size = (int)(end-start);
ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader));
/* 4/3 bigger than what we need but so what */
ssl_obj->buf = (uint8_t *)calloc(1, pem_size);
if (i == IS_RSA_PRIVATE_KEY &&
strstr(start, "Proc-Type:") &&
strstr(start, "4,ENCRYPTED"))
{
/* check for encrypted PEM file */
if (pem_decrypt(start, end, password, ssl_obj) < 0)
goto error;
}
else if (base64_decode(start, pem_size,
ssl_obj->buf, &ssl_obj->len) != 0)
goto error;
switch (i)
{
case IS_RSA_PRIVATE_KEY:
obj_type = SSL_OBJ_RSA_KEY;
break;
case IS_ENCRYPTED_PRIVATE_KEY:
obj_type = SSL_OBJ_PKCS8;
break;
case IS_CERTIFICATE:
obj_type = SSL_OBJ_X509_CERT;
break;
default:
goto error;
}
/* In a format we can now understand - so process it */
if ((ret = do_obj(ssl_ctx, obj_type, ssl_obj, password)))
goto error;
end += strlen(ends[i]);
remain -= strlen(ends[i]);
while (remain > 0 && (*end == '\r' || *end == '\n'))
{
end++;
remain--;
}
break;
}
}
if (i == NUM_PEM_TYPES)
goto error;
/* more PEM stuff to process? */
if (remain)
ret = new_pem_obj(ssl_ctx, end, remain, password);
error:
ssl_obj_free(ssl_obj);
return ret;
}
/*
* Load a file into memory that is in ASCII PEM format.
*/
static int ssl_obj_PEM_load(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj,
const char *password)
{
char *start;
/* add a null terminator */
ssl_obj->len++;
ssl_obj->buf = (uint8_t *)realloc(ssl_obj->buf, ssl_obj->len);
ssl_obj->buf[ssl_obj->len-1] = 0;
start = (char *)ssl_obj->buf;
return new_pem_obj(ssl_ctx, start, ssl_obj->len, password);
}
#endif /* CONFIG_SSL_HAS_PEM */

281
ssl/md5.c Normal file
View File

@ -0,0 +1,281 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* This file implements the MD5 algorithm as defined in RFC1321
*/
#include <string.h>
#include "crypto.h"
/* Constants for MD5Transform routine.
*/
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
/* ----- static functions ----- */
static void MD5Transform(uint32_t state[4], const uint8_t block[64]);
static void Encode(uint8_t *output, uint32_t *input, uint32_t len);
static void Decode(uint32_t *output, const uint8_t *input, uint32_t len);
static const uint8_t PADDING[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits. */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation. */
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
/**
* MD5 initialization - begins an MD5 operation, writing a new ctx.
*/
EXP_FUNC void STDCALL MD5Init(MD5_CTX *ctx)
{
ctx->count[0] = ctx->count[1] = 0;
/* Load magic initialization constants.
*/
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xefcdab89;
ctx->state[2] = 0x98badcfe;
ctx->state[3] = 0x10325476;
}
/**
* Accepts an array of octets as the next portion of the message.
*/
EXP_FUNC void STDCALL MD5Update(MD5_CTX *ctx, const uint8_t * msg, int len)
{
uint32_t x;
int i, partLen;
/* Compute number of bytes mod 64 */
x = (uint32_t)((ctx->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((ctx->count[0] += ((uint32_t)len << 3)) < ((uint32_t)len << 3))
ctx->count[1]++;
ctx->count[1] += ((uint32_t)len >> 29);
partLen = 64 - x;
/* Transform as many times as possible. */
if (len >= partLen)
{
memcpy(&ctx->buffer[x], msg, partLen);
MD5Transform(ctx->state, ctx->buffer);
for (i = partLen; i + 63 < len; i += 64)
MD5Transform(ctx->state, &msg[i]);
x = 0;
}
else
i = 0;
/* Buffer remaining input */
memcpy(&ctx->buffer[x], &msg[i], len-i);
}
/**
* Return the 128-bit message digest into the user's array
*/
EXP_FUNC void STDCALL MD5Final(MD5_CTX *ctx, uint8_t *digest)
{
uint8_t bits[8];
uint32_t x, padLen;
/* Save number of bits */
Encode(bits, ctx->count, 8);
/* Pad out to 56 mod 64.
*/
x = (uint32_t)((ctx->count[0] >> 3) & 0x3f);
padLen = (x < 56) ? (56 - x) : (120 - x);
MD5Update(ctx, PADDING, padLen);
/* Append length (before padding) */
MD5Update(ctx, bits, 8);
/* Store state in digest */
Encode(digest, ctx->state, MD5_SIZE);
}
/**
* MD5 basic transformation. Transforms state based on block.
*/
static void MD5Transform(uint32_t state[4], const uint8_t block[64])
{
uint32_t a = state[0], b = state[1], c = state[2],
d = state[3], x[MD5_SIZE];
Decode(x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
}
/**
* Encodes input (uint32_t) into output (uint8_t). Assumes len is
* a multiple of 4.
*/
static void Encode(uint8_t *output, uint32_t *input, uint32_t len)
{
uint32_t i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
{
output[j] = (uint8_t)(input[i] & 0xff);
output[j+1] = (uint8_t)((input[i] >> 8) & 0xff);
output[j+2] = (uint8_t)((input[i] >> 16) & 0xff);
output[j+3] = (uint8_t)((input[i] >> 24) & 0xff);
}
}
/**
* Decodes input (uint8_t) into output (uint32_t). Assumes len is
* a multiple of 4.
*/
static void Decode(uint32_t *output, const uint8_t *input, uint32_t len)
{
uint32_t i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) |
(((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24);
}

209
ssl/openssl.c Normal file
View File

@ -0,0 +1,209 @@
/*
* Copyright(C) 2007 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Lesser License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Enable a subset of openssl compatible functions. We don't aim to be 100%
* compatible - just to be able to do basic ports etc.
*
* Only really tested on mini_httpd, so I'm not too sure how extensive this
* port is.
*/
#include "config.h"
#ifdef CONFIG_OPENSSL_COMPATIBLE
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "ssl.h"
#define OPENSSL_CTX_ATTR ((OPENSSL_CTX *)ssl_ctx->bonus_attr)
void *SSLv23_server_method(void) { return NULL; }
void *SSLv3_server_method(void) { return NULL; }
void *TLSv1_server_method(void) { return NULL; }
void *SSLv23_client_method(void) { return NULL; }
void *SSLv3_client_method(void) { return NULL; }
void *TLSv1_client_method(void) { return NULL; }
typedef void * (*ssl_func_type_t)(void);
typedef void * (*bio_func_type_t)(void);
typedef struct
{
ssl_func_type_t ssl_func_type;
} OPENSSL_CTX;
SSL_CTX * SSL_CTX_new(ssl_func_type_t meth)
{
SSL_CTX *ssl_ctx = ssl_ctx_new(0, 5);
ssl_ctx->bonus_attr = malloc(sizeof(OPENSSL_CTX));
OPENSSL_CTX_ATTR->ssl_func_type = meth;
return ssl_ctx;
}
void SSL_CTX_free(SSL_CTX * ssl_ctx)
{
free(ssl_ctx->bonus_attr);
ssl_ctx_free(ssl_ctx);
}
SSL * SSL_new(SSL_CTX *ssl_ctx)
{
SSL *ssl;
ssl_func_type_t ssl_func_type;
ssl = ssl_new(ssl_ctx, -1); /* fd is set later */
ssl_func_type = OPENSSL_CTX_ATTR->ssl_func_type;
#ifdef CONFIG_SSL_ENABLE_CLIENT
if (ssl_func_type == SSLv23_client_method ||
ssl_func_type == SSLv3_client_method ||
ssl_func_type == TLSv1_client_method)
{
SET_SSL_FLAG(SSL_IS_CLIENT);
}
else
#endif
{
ssl->next_state = HS_CLIENT_HELLO;
}
return ssl;
}
int SSL_set_fd(SSL *s, int fd)
{
s->client_fd = fd;
return 1; /* always succeeds */
}
int SSL_accept(SSL *ssl)
{
while (ssl_read(ssl, NULL) == SSL_OK)
{
if (ssl->next_state == HS_CLIENT_HELLO)
return 1; /* we're done */
}
return -1;
}
#ifdef CONFIG_SSL_ENABLE_CLIENT
int SSL_connect(SSL *ssl)
{
return do_client_connect(ssl) == SSL_OK ? 1 : -1;
}
#endif
void SSL_free(SSL *ssl)
{
ssl_free(ssl);
}
int SSL_read(SSL *ssl, void *buf, int num)
{
uint8_t *read_buf;
int ret;
while ((ret = ssl_read(ssl, &read_buf)) == SSL_OK);
if (ret > SSL_OK)
{
memcpy(buf, read_buf, ret > num ? num : ret);
}
return ret;
}
int SSL_write(SSL *ssl, const void *buf, int num)
{
return ssl_write(ssl, buf, num);
}
int SSL_CTX_use_certificate_file(SSL_CTX *ssl_ctx, const char *file, int type)
{
return (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, file, NULL) == SSL_OK);
}
int SSL_CTX_use_PrivateKey_file(SSL_CTX *ssl_ctx, const char *file, int type)
{
return (ssl_obj_load(ssl_ctx, SSL_OBJ_RSA_KEY, file, NULL) == SSL_OK);
}
int SSL_CTX_use_certificate_ASN1(SSL_CTX *ssl_ctx, int len, const uint8_t *d)
{
return (ssl_obj_memory_load(ssl_ctx,
SSL_OBJ_X509_CERT, d, len, NULL) == SSL_OK);
}
#if 0
const uint8_t *SSL_get_session(const SSL *ssl)
{
/* TODO: return SSL_SESSION type */
return ssl_get_session_id(ssl);
}
#endif
int SSL_CTX_check_private_key(const SSL_CTX *ctx)
{
return 1;
}
int SSL_CTX_set_cipher_list(SSL *s, const char *str)
{
return 1;
}
int SSL_get_error(const SSL *ssl, int ret)
{
ssl_display_error(ret);
return 0; /* TODO: return proper return code */
}
void SSL_CTX_set_options(SSL_CTX *ssl_ctx, int option) {}
int SSL_library_init(void ) { return 1; }
void SSL_load_error_strings(void ) {}
void ERR_print_errors_fp(FILE *fp) {}
long SSL_CTX_get_timeout(const SSL_CTX *ssl_ctx) {
return CONFIG_SSL_EXPIRY_TIME*3600; }
long SSL_CTX_set_timeout(SSL_CTX *ssl_ctx, long t) {
return SSL_CTX_get_timeout(ssl_ctx); }
void BIO_printf(FILE *f, const char *format, ...)
{
va_list(ap);
va_start(ap, format);
vfprintf(f, format, ap);
va_end(ap);
}
void* BIO_s_null(void) { return NULL; }
FILE *BIO_new(bio_func_type_t func)
{
if (func == BIO_s_null)
return fopen("/dev/null", "r");
else
return NULL;
}
FILE *BIO_new_fp(FILE *stream, int close_flag) { return stream; }
int BIO_free(FILE *a) { if (a != stdout && a != stderr) fclose(a); return 1; }
#endif

142
ssl/os_port.c Normal file
View File

@ -0,0 +1,142 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* @file os_port.c
*
* OS specific functions.
*/
#include <time.h>
#include <stdlib.h>
#include <errno.h>
#include <stdarg.h>
#include "os_port.h"
#ifdef WIN32
/**
* gettimeofday() not in Win32
*/
EXP_FUNC void STDCALL gettimeofday(struct timeval* t, void* timezone)
{
#if defined(_WIN32_WCE)
t->tv_sec = time(NULL);
t->tv_usec = 0; /* 1sec precision only */
#else
struct _timeb timebuffer;
_ftime(&timebuffer);
t->tv_sec = (long)timebuffer.time;
t->tv_usec = 1000 * timebuffer.millitm; /* 1ms precision */
#endif
}
/**
* strcasecmp() not in Win32
*/
EXP_FUNC int STDCALL strcasecmp(const char *s1, const char *s2)
{
while (tolower(*s1) == tolower(*s2++))
{
if (*s1++ == '\0')
{
return 0;
}
}
return *(unsigned char *)s1 - *(unsigned char *)(s2 - 1);
}
#endif
#undef malloc
#undef realloc
#undef calloc
#undef open
#undef fopen
static const char * out_of_mem_str = "out of memory";
static const char * file_open_str = "Could not open file \"%s\"";
/*
* Some functions that call display some error trace and then call abort().
* This just makes life much easier on embedded systems, since we're
* suffering major trauma...
*/
EXP_FUNC void * STDCALL ax_malloc(size_t s)
{
void *x;
if ((x = malloc(s)) == NULL)
exit_now(out_of_mem_str);
return x;
}
EXP_FUNC void * STDCALL ax_realloc(void *y, size_t s)
{
void *x;
if ((x = realloc(y, s)) == NULL)
exit_now(out_of_mem_str);
return x;
}
EXP_FUNC void * STDCALL ax_calloc(size_t n, size_t s)
{
void *x;
if ((x = calloc(n, s)) == NULL)
exit_now(out_of_mem_str);
return x;
}
EXP_FUNC FILE * STDCALL ax_fopen(const char *pathname, const char *type)
{
FILE *f;
if ((f = fopen(pathname, type)) == NULL)
exit_now(file_open_str, pathname);
return f;
}
EXP_FUNC int STDCALL ax_open(const char *pathname, int flags)
{
int x;
if ((x = open(pathname, flags)) < 0)
exit_now(file_open_str, pathname);
return x;
}
/**
* This is a call which will deliberately exit an application, but will
* display some information before dying.
*/
void exit_now(const char *format, ...)
{
va_list argp;
va_start(argp, format);
vfprintf(stderr, format, argp);
va_end(argp);
abort();
}

166
ssl/os_port.h Normal file
View File

@ -0,0 +1,166 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* @file os_port.h
*
* Some stuff to minimise the differences between windows and linux/unix
*/
#ifndef HEADER_OS_PORT_H
#define HEADER_OS_PORT_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#if defined(WIN32)
#define STDCALL __stdcall
#define EXP_FUNC __declspec(dllexport)
#else
#define STDCALL
#define EXP_FUNC
#endif
#if defined(_WIN32_WCE)
#undef WIN32
#define WIN32
#endif
#ifdef WIN32
/* Windows CE stuff */
#if defined(_WIN32_WCE)
#include <basetsd.h>
#define abort() exit(1)
#else
#include <io.h>
#include <process.h>
#include <sys/timeb.h>
#include <fcntl.h>
#endif /* _WIN32_WCE */
#include <winsock.h>
#include <direct.h>
#undef getpid
#undef open
#undef close
#undef sleep
#undef gettimeofday
#undef dup2
#undef unlink
#define SOCKET_READ(A,B,C) recv(A,B,C,0)
#define SOCKET_WRITE(A,B,C) send(A,B,C,0)
#define SOCKET_CLOSE(A) closesocket(A)
#define srandom(A) srand(A)
#define random() rand()
#define getpid() _getpid()
#define snprintf _snprintf
#define open(A,B) _open(A,B)
#define dup2(A,B) _dup2(A,B)
#define unlink(A) _unlink(A)
#define close(A) _close(A)
#define read(A,B,C) _read(A,B,C)
#define write(A,B,C) _write(A,B,C)
#define sleep(A) Sleep(A*1000)
#define usleep(A) Sleep(A/1000)
#define strdup(A) _strdup(A)
#define chroot(A) _chdir(A)
#ifndef lseek
#define lseek(A,B,C) _lseek(A,B,C)
#endif
/* This fix gets around a problem where a win32 application on a cygwin xterm
doesn't display regular output (until a certain buffer limit) - but it works
fine under a normal DOS window. This is a hack to get around the issue -
see http://www.khngai.com/emacs/tty.php */
#define TTY_FLUSH() if (!_isatty(_fileno(stdout))) fflush(stdout);
/*
* automatically build some library dependencies.
*/
#pragma comment(lib, "WS2_32.lib")
#ifdef CONFIG_WIN32_USE_CRYPTO_LIB
#pragma comment(lib, "AdvAPI32.lib")
#endif
typedef UINT8 uint8_t;
typedef INT8 int8_t;
typedef UINT16 uint16_t;
typedef INT16 int16_t;
typedef UINT32 uint32_t;
typedef INT32 int32_t;
typedef UINT64 uint64_t;
typedef INT64 int64_t;
EXP_FUNC void STDCALL gettimeofday(struct timeval* t,void* timezone);
EXP_FUNC int STDCALL strcasecmp(const char *s1, const char *s2);
#else /* Not Win32 */
#ifdef CONFIG_PLATFORM_SOLARIS
#include <inttypes.h>
#else
#include <stdint.h>
#endif /* Not Solaris */
#include <unistd.h>
#include <pwd.h>
#include <netdb.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define SOCKET_READ(A,B,C) read(A,B,C)
#define SOCKET_WRITE(A,B,C) write(A,B,C)
#define SOCKET_CLOSE(A) close(A)
#define TTY_FLUSH()
#endif /* Not Win32 */
/* some functions to mutate the way these work */
#define malloc(A) ax_malloc(A)
#define realloc(A,B) ax_realloc(A,B)
#define calloc(A,B) ax_calloc(A,B)
EXP_FUNC void * STDCALL ax_malloc(size_t s);
EXP_FUNC void * STDCALL ax_realloc(void *y, size_t s);
EXP_FUNC void * STDCALL ax_calloc(size_t n, size_t s);
EXP_FUNC FILE * STDCALL ax_fopen(const char *name, const char *type);
EXP_FUNC int STDCALL ax_open(const char *pathname, int flags);
#ifdef CONFIG_PLATFORM_LINUX
void exit_now(const char *format, ...) __attribute((noreturn));
#else
void exit_now(const char *format, ...);
#endif
#ifdef __cplusplus
}
#endif
#endif

474
ssl/p12.c Normal file
View File

@ -0,0 +1,474 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* Process PKCS#8/PKCS#12 keys.
*
* The decoding of a PKCS#12 key is fairly specific - this code was tested on a
* key generated with:
*
* openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem
* -keypbe PBE-SHA1-RC4-128 -certpbe PBE-SHA1-RC4-128
* -name "p12_withoutCA" -out axTLS.withoutCA.p12 -password pass:abcd
*
* or with a certificate chain:
*
* openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem
* -certfile axTLS.ca_x509.pem -keypbe PBE-SHA1-RC4-128 -certpbe
* PBE-SHA1-RC4-128 -name "p12_withCA" -out axTLS.withCA.p12 -password pass:abcd
*
* Note that the PBE has to be specified with PBE-SHA1-RC4-128. The
* private/public keys/certs have to use RSA encryption. Both the integrity
* and privacy passwords are the same.
*
* The PKCS#8 files were generated with something like:
*
* PEM format:
* openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -v1
* PBE-SHA1-RC4-128 -out axTLS.encrypted_pem.p8
*
* DER format:
* openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -outform DER
* -v1 PBE-SHA1-RC4-128 -out axTLS.encrypted.p8
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "ssl.h"
/* all commented out if not used */
#ifdef CONFIG_SSL_USE_PKCS12
#define BLOCK_SIZE 64
#define PKCS12_KEY_ID 1
#define PKCS12_IV_ID 2
#define PKCS12_MAC_ID 3
static char *make_uni_pass(const char *password, int *uni_pass_len);
static int p8_decrypt(const char *uni_pass, int uni_pass_len,
const uint8_t *salt, int iter,
uint8_t *priv_key, int priv_key_len, int id);
static int p8_add_key(SSL_CTX *ssl_ctx, uint8_t *priv_key);
static int get_pbe_params(uint8_t *buf, int *offset,
const uint8_t **salt, int *iterations);
/*
* Take a raw pkcs8 block and then decrypt it and turn it into a normal key.
*/
int pkcs8_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
{
uint8_t *buf = ssl_obj->buf;
int len, offset = 0;
int iterations;
int ret = SSL_NOT_OK;
uint8_t *version = NULL;
const uint8_t *salt;
uint8_t *priv_key;
int uni_pass_len;
char *uni_pass = make_uni_pass(password, &uni_pass_len);
if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0)
{
#ifdef CONFIG_SSL_FULL_MODE
printf("Error: Invalid p8 ASN.1 file\n");
#endif
goto error;
}
/* unencrypted key? */
if (asn1_get_int(buf, &offset, &version) > 0 && *version == 0)
{
ret = p8_add_key(ssl_ctx, buf);
goto error;
}
if (get_pbe_params(buf, &offset, &salt, &iterations) < 0)
goto error;
if ((len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0)
goto error;
priv_key = &buf[offset];
p8_decrypt(uni_pass, uni_pass_len, salt,
iterations, priv_key, len, PKCS12_KEY_ID);
ret = p8_add_key(ssl_ctx, priv_key);
error:
free(version);
free(uni_pass);
return ret;
}
/*
* Take the unencrypted pkcs8 and turn it into a private key
*/
static int p8_add_key(SSL_CTX *ssl_ctx, uint8_t *priv_key)
{
uint8_t *buf = priv_key;
int len, offset = 0;
int ret = SSL_NOT_OK;
/* Skip the preamble and go straight to the private key.
We only support rsaEncryption (1.2.840.113549.1.1.1) */
if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
asn1_skip_obj(buf, &offset, ASN1_INTEGER) < 0 ||
asn1_skip_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
(len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0)
goto error;
ret = asn1_get_private_key(&buf[offset], len, &ssl_ctx->rsa_ctx);
error:
return ret;
}
/*
* Create the unicode password
*/
static char *make_uni_pass(const char *password, int *uni_pass_len)
{
int pass_len = 0, i;
char *uni_pass;
if (password == NULL)
{
password = "";
}
uni_pass = (char *)malloc((strlen(password)+1)*2);
/* modify the password into a unicode version */
for (i = 0; i < (int)strlen(password); i++)
{
uni_pass[pass_len++] = 0;
uni_pass[pass_len++] = password[i];
}
uni_pass[pass_len++] = 0; /* null terminate */
uni_pass[pass_len++] = 0;
*uni_pass_len = pass_len;
return uni_pass;
}
/*
* Decrypt a pkcs8 block.
*/
static int p8_decrypt(const char *uni_pass, int uni_pass_len,
const uint8_t *salt, int iter,
uint8_t *priv_key, int priv_key_len, int id)
{
uint8_t p[BLOCK_SIZE*2];
uint8_t d[BLOCK_SIZE];
uint8_t Ai[SHA1_SIZE];
SHA1_CTX sha_ctx;
RC4_CTX rc4_ctx;
int i;
for (i = 0; i < BLOCK_SIZE; i++)
{
p[i] = salt[i % SALT_SIZE];
p[BLOCK_SIZE+i] = uni_pass[i % uni_pass_len];
d[i] = id;
}
/* get the key - no IV since we are using RC4 */
SHA1Init(&sha_ctx);
SHA1Update(&sha_ctx, d, sizeof(d));
SHA1Update(&sha_ctx, p, sizeof(p));
SHA1Final(&sha_ctx, Ai);
for (i = 1; i < iter; i++)
{
SHA1Init(&sha_ctx);
SHA1Update(&sha_ctx, Ai, SHA1_SIZE);
SHA1Final(&sha_ctx, Ai);
}
/* do the decryption */
if (id == PKCS12_KEY_ID)
{
RC4_setup(&rc4_ctx, Ai, 16);
RC4_crypt(&rc4_ctx, priv_key, priv_key, priv_key_len);
}
else /* MAC */
memcpy(priv_key, Ai, SHA1_SIZE);
return 0;
}
/*
* Take a raw pkcs12 block and the decrypt it and turn it into a certificate(s)
* and keys.
*/
int pkcs12_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
{
uint8_t *buf = ssl_obj->buf;
int all_ok = 0, len, iterations, auth_safes_start,
auth_safes_end, auth_safes_len, key_offset, offset = 0;
int all_certs = 0;
uint8_t *version = NULL, *auth_safes = NULL, *cert, *orig_mac;
uint8_t key[SHA1_SIZE];
uint8_t mac[SHA1_SIZE];
const uint8_t *salt;
int uni_pass_len, ret;
int error_code = SSL_ERROR_NOT_SUPPORTED;
char *uni_pass = make_uni_pass(password, &uni_pass_len);
static const uint8_t pkcs_data[] = /* pkc7 data */
{ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01 };
static const uint8_t pkcs_encrypted[] = /* pkc7 encrypted */
{ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x06 };
static const uint8_t pkcs8_key_bag[] = /* 1.2.840.113549.1.12.10.1.2 */
{ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02 };
if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0)
{
#ifdef CONFIG_SSL_FULL_MODE
printf("Error: Invalid p12 ASN.1 file\n");
#endif
goto error;
}
if (asn1_get_int(buf, &offset, &version) < 0 || *version != 3)
{
error_code = SSL_ERROR_INVALID_VERSION;
goto error;
}
/* remove all the boring pcks7 bits */
if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
(len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
len != sizeof(pkcs_data) ||
memcmp(&buf[offset], pkcs_data, sizeof(pkcs_data)))
goto error;
offset += len;
if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
asn1_next_obj(buf, &offset, ASN1_OCTET_STRING) < 0)
goto error;
/* work out the MAC start/end points (done on AuthSafes) */
auth_safes_start = offset;
auth_safes_end = offset;
if (asn1_skip_obj(buf, &auth_safes_end, ASN1_SEQUENCE) < 0)
goto error;
auth_safes_len = auth_safes_end - auth_safes_start;
auth_safes = malloc(auth_safes_len);
memcpy(auth_safes, &buf[auth_safes_start], auth_safes_len);
if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
(len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
(len != sizeof(pkcs_encrypted) ||
memcmp(&buf[offset], pkcs_encrypted, sizeof(pkcs_encrypted))))
goto error;
offset += len;
if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
asn1_skip_obj(buf, &offset, ASN1_INTEGER) < 0 ||
asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
(len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
len != sizeof(pkcs_data) ||
memcmp(&buf[offset], pkcs_data, sizeof(pkcs_data)))
goto error;
offset += len;
/* work out the salt for the certificate */
if (get_pbe_params(buf, &offset, &salt, &iterations) < 0 ||
(len = asn1_next_obj(buf, &offset, ASN1_IMPLICIT_TAG)) < 0)
goto error;
/* decrypt the certificate */
cert = &buf[offset];
if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations, cert,
len, PKCS12_KEY_ID)) < 0)
goto error;
offset += len;
/* load the certificate */
key_offset = 0;
all_certs = asn1_next_obj(cert, &key_offset, ASN1_SEQUENCE);
/* keep going until all certs are loaded */
while (key_offset < all_certs)
{
int cert_offset = key_offset;
if (asn1_skip_obj(cert, &cert_offset, ASN1_SEQUENCE) < 0 ||
asn1_next_obj(cert, &key_offset, ASN1_SEQUENCE) < 0 ||
asn1_skip_obj(cert, &key_offset, ASN1_OID) < 0 ||
asn1_next_obj(cert, &key_offset, ASN1_EXPLICIT_TAG) < 0 ||
asn1_next_obj(cert, &key_offset, ASN1_SEQUENCE) < 0 ||
asn1_skip_obj(cert, &key_offset, ASN1_OID) < 0 ||
asn1_next_obj(cert, &key_offset, ASN1_EXPLICIT_TAG) < 0 ||
(len = asn1_next_obj(cert, &key_offset, ASN1_OCTET_STRING)) < 0)
goto error;
if ((ret = add_cert(ssl_ctx, &cert[key_offset], len)) < 0)
goto error;
key_offset = cert_offset;
}
if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
(len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
len != sizeof(pkcs_data) ||
memcmp(&buf[offset], pkcs_data, sizeof(pkcs_data)))
goto error;
offset += len;
if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
asn1_next_obj(buf, &offset, ASN1_OCTET_STRING) < 0 ||
asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
(len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
(len != sizeof(pkcs8_key_bag)) ||
memcmp(&buf[offset], pkcs8_key_bag, sizeof(pkcs8_key_bag)))
goto error;
offset += len;
/* work out the salt for the private key */
if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
get_pbe_params(buf, &offset, &salt, &iterations) < 0 ||
(len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0)
goto error;
/* decrypt the private key */
cert = &buf[offset];
if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations, cert,
len, PKCS12_KEY_ID)) < 0)
goto error;
offset += len;
/* load the private key */
if ((ret = p8_add_key(ssl_ctx, cert)) < 0)
goto error;
/* miss out on friendly name, local key id etc */
if (asn1_skip_obj(buf, &offset, ASN1_SET) < 0)
goto error;
/* work out the MAC */
if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
asn1_skip_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
(len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0 ||
len != SHA1_SIZE)
goto error;
orig_mac = &buf[offset];
offset += len;
/* get the salt */
if ((len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0 || len != 8)
goto error;
salt = &buf[offset];
/* work out what the mac should be */
if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations,
key, SHA1_SIZE, PKCS12_MAC_ID)) < 0)
goto error;
hmac_sha1(auth_safes, auth_safes_len, key, SHA1_SIZE, mac);
if (memcmp(mac, orig_mac, SHA1_SIZE))
{
error_code = SSL_ERROR_INVALID_HMAC;
goto error;
}
all_ok = 1;
error:
free(version);
free(uni_pass);
free(auth_safes);
return all_ok ? SSL_OK : error_code;
}
/*
* Retrieve the salt/iteration details from a PBE block.
*/
static int get_pbe_params(uint8_t *buf, int *offset,
const uint8_t **salt, int *iterations)
{
static const uint8_t pbeSH1RC4[] = /* pbeWithSHAAnd128BitRC4 */
{ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x01 };
int i, len;
uint8_t *iter = NULL;
int error_code = SSL_ERROR_NOT_SUPPORTED;
/* Get the PBE type */
if (asn1_next_obj(buf, offset, ASN1_SEQUENCE) < 0 ||
(len = asn1_next_obj(buf, offset, ASN1_OID)) < 0)
goto error;
/* we expect pbeWithSHAAnd128BitRC4 (1.2.840.113549.1.12.1.1)
which is the only algorithm we support */
if (len != sizeof(pbeSH1RC4) ||
memcmp(&buf[*offset], pbeSH1RC4, sizeof(pbeSH1RC4)))
{
#ifdef CONFIG_SSL_FULL_MODE
printf("Error: pkcs8/pkcs12 must use \"PBE-SHA1-RC4-128\"\n");
#endif
goto error;
}
*offset += len;
if (asn1_next_obj(buf, offset, ASN1_SEQUENCE) < 0 ||
(len = asn1_next_obj(buf, offset, ASN1_OCTET_STRING)) < 0 ||
len != 8)
goto error;
*salt = &buf[*offset];
*offset += len;
if ((len = asn1_get_int(buf, offset, &iter)) < 0)
goto error;
*iterations = 0;
for (i = 0; i < len; i++)
{
(*iterations) <<= 8;
(*iterations) += iter[i];
}
free(iter);
error_code = SSL_OK; /* got here - we are ok */
error:
return error_code;
}
#endif

54
ssl/private_key.h Normal file
View File

@ -0,0 +1,54 @@
unsigned char default_private_key[] = {
0x30, 0x82, 0x02, 0x5d, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xd8,
0xe0, 0xbf, 0x15, 0xde, 0xea, 0xaf, 0xe8, 0xd5, 0xfd, 0x0b, 0xa8, 0xa8,
0xb3, 0xd7, 0x46, 0x5d, 0xa7, 0x26, 0x6c, 0x0c, 0xb5, 0xd9, 0xbc, 0xc6,
0xf8, 0xc0, 0x78, 0xd0, 0xf6, 0x56, 0x65, 0xf8, 0x29, 0x48, 0x0e, 0x7b,
0x0b, 0xa6, 0x25, 0x7e, 0xe8, 0x7b, 0x79, 0x6f, 0x38, 0xe5, 0xb5, 0xb7,
0xf4, 0xe0, 0x9c, 0x91, 0x60, 0xf4, 0x06, 0xf3, 0x40, 0x1e, 0xf9, 0x91,
0x19, 0xa9, 0x2f, 0x47, 0x43, 0xb5, 0x9b, 0x1e, 0xdc, 0xf6, 0xaa, 0x1c,
0x49, 0x79, 0x21, 0x28, 0xcb, 0xaa, 0x49, 0x73, 0xd9, 0x09, 0x05, 0x4c,
0x02, 0xf2, 0x4c, 0x4d, 0x6c, 0x1c, 0x80, 0xa7, 0x14, 0x91, 0x44, 0xfc,
0x12, 0xb3, 0xe1, 0xe7, 0xe3, 0x4f, 0x44, 0xba, 0x8c, 0xc3, 0x74, 0x39,
0xe8, 0x4c, 0xd0, 0xd4, 0x4c, 0x24, 0x61, 0xb4, 0x40, 0x95, 0x8c, 0xc0,
0x0a, 0xb7, 0x02, 0x39, 0x31, 0x85, 0x93, 0x02, 0x03, 0x01, 0x00, 0x01,
0x02, 0x81, 0x81, 0x00, 0x94, 0x07, 0x72, 0xe5, 0xbe, 0xad, 0x79, 0x3b,
0xf7, 0x33, 0x2c, 0x8e, 0x05, 0xf8, 0x1a, 0x6b, 0xd0, 0xe8, 0x91, 0xf5,
0x16, 0x07, 0xd9, 0x82, 0x5c, 0x5c, 0xd5, 0x22, 0xa1, 0x9e, 0x42, 0x02,
0x7f, 0x8b, 0xcd, 0xbe, 0xf4, 0x85, 0x52, 0xf6, 0x2c, 0xd5, 0x09, 0xd2,
0x2c, 0xf4, 0x2c, 0xf6, 0x07, 0x85, 0x80, 0xf9, 0xdc, 0xd0, 0xcc, 0x3f,
0x22, 0x31, 0x15, 0xf3, 0x49, 0xf2, 0xb5, 0xe2, 0x69, 0x99, 0x04, 0x04,
0x49, 0x21, 0xdb, 0x9f, 0xa1, 0x54, 0x5a, 0xfa, 0xe4, 0xd9, 0xf9, 0x07,
0x05, 0xff, 0x9a, 0x65, 0xa4, 0xeb, 0xf2, 0x47, 0xce, 0x56, 0xc7, 0x72,
0x49, 0x48, 0x5c, 0xe8, 0x14, 0xd7, 0x8f, 0x25, 0xcc, 0x49, 0x29, 0x06,
0x6a, 0x54, 0x7b, 0x17, 0xdc, 0x9e, 0xd4, 0x53, 0xf0, 0xf5, 0x9e, 0x85,
0x25, 0xa1, 0xeb, 0x3d, 0xe9, 0x2f, 0xb9, 0x9c, 0xf6, 0xe1, 0x80, 0x81,
0x02, 0x41, 0x00, 0xee, 0x02, 0x78, 0xc7, 0x78, 0x85, 0x04, 0x97, 0xcc,
0x36, 0xbd, 0xd6, 0x11, 0xe2, 0xc7, 0x39, 0xd9, 0x34, 0x51, 0x72, 0x6f,
0x8a, 0x0f, 0xcd, 0x88, 0x32, 0x33, 0x9b, 0xc7, 0xa7, 0x03, 0x77, 0xd9,
0x82, 0x35, 0xb6, 0xdd, 0x1f, 0xc2, 0xc1, 0x13, 0x40, 0x83, 0x55, 0xeb,
0x60, 0xeb, 0x81, 0x8e, 0x0c, 0x16, 0x62, 0xb4, 0xb4, 0x3c, 0xeb, 0x08,
0x80, 0x9c, 0x79, 0xd3, 0x38, 0xca, 0xf1, 0x02, 0x41, 0x00, 0xe9, 0x45,
0x5f, 0x2e, 0x16, 0xcc, 0x93, 0x50, 0x40, 0xb6, 0x79, 0xbc, 0x38, 0xe0,
0x56, 0x68, 0x50, 0xd3, 0x2f, 0x73, 0x8c, 0x8c, 0x2a, 0x0e, 0x81, 0x4a,
0x8a, 0xbb, 0xcc, 0xf0, 0x64, 0x34, 0x46, 0x9f, 0x07, 0x7d, 0x22, 0xb6,
0xf9, 0x46, 0xac, 0x57, 0x23, 0x8c, 0x1e, 0xeb, 0xd3, 0x05, 0x4d, 0xa8,
0x83, 0x6a, 0x67, 0xf6, 0xa6, 0xb1, 0xab, 0x8e, 0xc1, 0xef, 0xef, 0x7d,
0xf0, 0xc3, 0x02, 0x40, 0x2f, 0xc6, 0x59, 0x3e, 0x18, 0xe8, 0x02, 0x73,
0x01, 0xef, 0xdf, 0x0d, 0x30, 0x4b, 0xe8, 0x17, 0xa9, 0x8c, 0xc1, 0xe8,
0x89, 0x91, 0x19, 0xf8, 0xf4, 0xa4, 0xb7, 0x0d, 0x46, 0xf7, 0x34, 0x50,
0x03, 0x5e, 0x0a, 0xb0, 0x29, 0x14, 0xae, 0x00, 0x19, 0x80, 0x32, 0x9c,
0xb5, 0x81, 0x9f, 0xe4, 0x42, 0x82, 0x14, 0xa0, 0x3d, 0x8b, 0x8c, 0x4a,
0xd5, 0x4b, 0x13, 0x9d, 0xb4, 0x93, 0x4a, 0xd1, 0x02, 0x40, 0x64, 0x8c,
0x83, 0x77, 0x61, 0x5a, 0x73, 0x11, 0x3f, 0xa3, 0xa8, 0x1b, 0x8a, 0xc4,
0xa0, 0x5a, 0x3c, 0xa4, 0x9b, 0x2a, 0x8a, 0x65, 0x8c, 0x67, 0x4e, 0x31,
0xac, 0x55, 0x41, 0x04, 0x49, 0x9d, 0x02, 0xe7, 0xdf, 0x99, 0x7f, 0xd2,
0x30, 0xe6, 0xd6, 0xb8, 0x84, 0xd9, 0x0c, 0x27, 0x08, 0x81, 0x9b, 0xb4,
0xcc, 0x58, 0x9c, 0x51, 0x84, 0x0e, 0xc7, 0x6d, 0x34, 0x89, 0x50, 0xc9,
0x0f, 0x73, 0x02, 0x41, 0x00, 0xda, 0xde, 0x5e, 0x1a, 0xac, 0x1d, 0x1d,
0xd7, 0xb9, 0x65, 0x26, 0x00, 0xf5, 0xd4, 0xe4, 0x28, 0x84, 0x86, 0x2f,
0x00, 0x9c, 0x41, 0x00, 0x52, 0xe1, 0x47, 0x91, 0xc0, 0x52, 0x05, 0x4e,
0x0f, 0x2f, 0x0d, 0xca, 0x9b, 0x3d, 0x89, 0x41, 0xbf, 0xee, 0x9f, 0xa1,
0xe6, 0x9d, 0xa4, 0xeb, 0x45, 0x7f, 0xe3, 0xcb, 0xa4, 0x6b, 0x0a, 0xe2,
0x7e, 0xb0, 0x87, 0x5c, 0x40, 0xb1, 0x51, 0x11, 0x1d
};
unsigned int default_private_key_len = 609;

78
ssl/rc4.c Normal file
View File

@ -0,0 +1,78 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* An implementation of the RC4/ARC4 algorithm.
* Originally written by Christophe Devine.
*/
#include <string.h>
#include "crypto.h"
/**
* Get ready for an encrypt/decrypt operation
*/
void RC4_setup(RC4_CTX *ctx, const uint8_t *key, int length)
{
int i, j = 0, k = 0, *m, a;
ctx->x = 0;
ctx->y = 0;
m = ctx->m;
for (i = 0; i < 256; i++)
m[i] = i;
for (i = 0; i < 256; i++)
{
a = m[i];
j = (uint8_t)(j + a + key[k]);
m[i] = m[j];
m[j] = a;
if (++k >= length)
k = 0;
}
}
/**
* Perform the encrypt/decrypt operation (can use it for either since
* this is a stream cipher).
*/
void RC4_crypt(RC4_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
{
int i, x, y, *m, a, b;
out = (uint8_t *)msg;
x = ctx->x;
y = ctx->y;
m = ctx->m;
for (i = 0; i < length; i++)
{
x = (uint8_t)(x + 1);
a = m[x];
y = (uint8_t)(y + a);
m[x] = b = m[y];
m[y] = a;
out[i] ^= m[(uint8_t)(a + b)];
}
ctx->x = x;
ctx->y = y;
}

330
ssl/rsa.c Normal file
View File

@ -0,0 +1,330 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* 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"
#ifdef CONFIG_BIGINT_CRT
static bigint *bi_crt(const RSA_CTX *rsa, bigint *bi);
#endif
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)
{
int byte_size = ctx->num_octets;
uint8_t *block;
int i, size;
bigint *decrypted_bi, *dat_bi;
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 */
block = (uint8_t *)malloc(byte_size);
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);
free(block);
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_msg);
#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_BIGINT_CRT
/**
* Use the Chinese Remainder Theorem to quickly perform RSA decrypts.
* This should really be in bigint.c (and was at one stage), but needs
* access to the RSA_CTX context...
*/
static bigint *bi_crt(const RSA_CTX *rsa, bigint *bi)
{
BI_CTX *ctx = rsa->bi_ctx;
bigint *m1, *m2, *h;
/* Montgomery has a condition the 0 < x, y < m and these products violate
* that condition. So disable Montgomery when using CRT */
#if defined(CONFIG_BIGINT_MONTGOMERY)
ctx->use_classical = 1;
#endif
ctx->mod_offset = BIGINT_P_OFFSET;
m1 = bi_mod_power(ctx, bi_copy(bi), rsa->dP);
ctx->mod_offset = BIGINT_Q_OFFSET;
m2 = bi_mod_power(ctx, bi, rsa->dQ);
h = bi_subtract(ctx, bi_add(ctx, m1, rsa->p), bi_copy(m2), NULL);
h = bi_multiply(ctx, h, rsa->qInv);
ctx->mod_offset = BIGINT_P_OFFSET;
h = bi_residue(ctx, h);
#if defined(CONFIG_BIGINT_MONTGOMERY)
ctx->use_classical = 0; /* reset for any further operation */
#endif
return bi_add(ctx, m2, bi_multiply(ctx, rsa->q, h));
}
#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);
return byte_size;
}
/**
* Take a signature and decrypt it.
*/
bigint *RSA_sign_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,
bigint *modulus, bigint *pub_exp)
{
uint8_t *block;
int i, size;
bigint *decrypted_bi, *dat_bi;
bigint *bir = NULL;
block = (uint8_t *)malloc(sig_len);
/* decrypt */
dat_bi = bi_import(ctx, sig, sig_len);
ctx->mod_offset = BIGINT_M_OFFSET;
/* convert to a normal block */
decrypted_bi = bi_mod_power2(ctx, dat_bi, modulus, pub_exp);
bi_export(ctx, decrypted_bi, block, sig_len);
ctx->mod_offset = BIGINT_M_OFFSET;
i = 10; /* start at the first possible non-padded byte */
while (block[i++] && i < sig_len);
size = sig_len - i;
/* get only the bit we want */
if (size > 0)
{
int len;
const uint8_t *sig_ptr = x509_get_signature(&block[i], &len);
if (sig_ptr)
{
bir = bi_import(ctx, sig_ptr, len);
}
}
free(block);
return bir;
}
#endif /* CONFIG_SSL_CERT_VERIFICATION */

236
ssl/sha1.c Normal file
View File

@ -0,0 +1,236 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* SHA1 implementation - as defined in FIPS PUB 180-1 published April 17, 1995.
* This code was originally taken from RFC3174
*/
#include <string.h>
#include "crypto.h"
/*
* Define the SHA1 circular left shift macro
*/
#define SHA1CircularShift(bits,word) \
(((word) << (bits)) | ((word) >> (32-(bits))))
/* ----- static functions ----- */
static void SHA1PadMessage(SHA1_CTX *ctx);
static void SHA1ProcessMessageBlock(SHA1_CTX *ctx);
/**
* Initialize the SHA1 context
*/
void SHA1Init(SHA1_CTX *ctx)
{
ctx->Length_Low = 0;
ctx->Length_High = 0;
ctx->Message_Block_Index = 0;
ctx->Intermediate_Hash[0] = 0x67452301;
ctx->Intermediate_Hash[1] = 0xEFCDAB89;
ctx->Intermediate_Hash[2] = 0x98BADCFE;
ctx->Intermediate_Hash[3] = 0x10325476;
ctx->Intermediate_Hash[4] = 0xC3D2E1F0;
}
/**
* Accepts an array of octets as the next portion of the message.
*/
void SHA1Update(SHA1_CTX *ctx, const uint8_t *msg, int len)
{
while (len--)
{
ctx->Message_Block[ctx->Message_Block_Index++] = (*msg & 0xFF);
ctx->Length_Low += 8;
if (ctx->Length_Low == 0)
ctx->Length_High++;
if (ctx->Message_Block_Index == 64)
SHA1ProcessMessageBlock(ctx);
msg++;
}
}
/**
* Return the 160-bit message digest into the user's array
*/
void SHA1Final(SHA1_CTX *ctx, uint8_t *digest)
{
int i;
SHA1PadMessage(ctx);
memset(ctx->Message_Block, 0, 64);
ctx->Length_Low = 0; /* and clear length */
ctx->Length_High = 0;
for (i = 0; i < SHA1_SIZE; i++)
{
digest[i] = ctx->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) );
}
}
/**
* Process the next 512 bits of the message stored in the array.
*/
static void SHA1ProcessMessageBlock(SHA1_CTX *ctx)
{
const uint32_t K[] = { /* Constants defined in SHA-1 */
0x5A827999,
0x6ED9EBA1,
0x8F1BBCDC,
0xCA62C1D6
};
int t; /* Loop counter */
uint32_t temp; /* Temporary word value */
uint32_t W[80]; /* Word sequence */
uint32_t A, B, C, D, E; /* Word buffers */
/*
* Initialize the first 16 words in the array W
*/
for (t = 0; t < 16; t++)
{
W[t] = ctx->Message_Block[t * 4] << 24;
W[t] |= ctx->Message_Block[t * 4 + 1] << 16;
W[t] |= ctx->Message_Block[t * 4 + 2] << 8;
W[t] |= ctx->Message_Block[t * 4 + 3];
}
for (t = 16; t < 80; t++)
{
W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
}
A = ctx->Intermediate_Hash[0];
B = ctx->Intermediate_Hash[1];
C = ctx->Intermediate_Hash[2];
D = ctx->Intermediate_Hash[3];
E = ctx->Intermediate_Hash[4];
for (t = 0; t < 20; t++)
{
temp = SHA1CircularShift(5,A) +
((B & C) | ((~B) & D)) + E + W[t] + K[0];
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
for (t = 20; t < 40; t++)
{
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
for (t = 40; t < 60; t++)
{
temp = SHA1CircularShift(5,A) +
((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
for (t = 60; t < 80; t++)
{
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
ctx->Intermediate_Hash[0] += A;
ctx->Intermediate_Hash[1] += B;
ctx->Intermediate_Hash[2] += C;
ctx->Intermediate_Hash[3] += D;
ctx->Intermediate_Hash[4] += E;
ctx->Message_Block_Index = 0;
}
/*
* According to the standard, the message must be padded to an even
* 512 bits. The first padding bit must be a '1'. The last 64
* bits represent the length of the original message. All bits in
* between should be 0. This function will pad the message
* according to those rules by filling the Message_Block array
* accordingly. It will also call the ProcessMessageBlock function
* provided appropriately. When it returns, it can be assumed that
* the message digest has been computed.
*
* @param ctx [in, out] The SHA1 context
*/
static void SHA1PadMessage(SHA1_CTX *ctx)
{
/*
* Check to see if the current message block is too small to hold
* the initial padding bits and length. If so, we will pad the
* block, process it, and then continue padding into a second
* block.
*/
if (ctx->Message_Block_Index > 55)
{
ctx->Message_Block[ctx->Message_Block_Index++] = 0x80;
while(ctx->Message_Block_Index < 64)
{
ctx->Message_Block[ctx->Message_Block_Index++] = 0;
}
SHA1ProcessMessageBlock(ctx);
while (ctx->Message_Block_Index < 56)
{
ctx->Message_Block[ctx->Message_Block_Index++] = 0;
}
}
else
{
ctx->Message_Block[ctx->Message_Block_Index++] = 0x80;
while(ctx->Message_Block_Index < 56)
{
ctx->Message_Block[ctx->Message_Block_Index++] = 0;
}
}
/*
* Store the message length as the last 8 octets
*/
ctx->Message_Block[56] = ctx->Length_High >> 24;
ctx->Message_Block[57] = ctx->Length_High >> 16;
ctx->Message_Block[58] = ctx->Length_High >> 8;
ctx->Message_Block[59] = ctx->Length_High;
ctx->Message_Block[60] = ctx->Length_Low >> 24;
ctx->Message_Block[61] = ctx->Length_Low >> 16;
ctx->Message_Block[62] = ctx->Length_Low >> 8;
ctx->Message_Block[63] = ctx->Length_Low;
SHA1ProcessMessageBlock(ctx);
}

429
ssl/ssl.h Normal file
View File

@ -0,0 +1,429 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* @mainpage axTLS API
*
* @image html axolotl.jpg
*
* The axTLS library has features such as:
* - The TLSv1 SSL client/server protocol
* - No requirement to use any openssl libraries.
* - A choice between AES block (128/256 bit) and RC4 (128 bit) stream ciphers.
* - RSA encryption/decryption with variable sized keys (up to 4096 bits).
* - Certificate chaining and peer authentication.
* - Session resumption, session renegotiation.
* - ASN.1, X.509, PKCS#8, PKCS#12 keys/certificates with DER/PEM encoding.
* - Highly configurable compile time options.
* - Portable across many platforms (written in ANSI C), and has language
* bindings in C, C#, VB.NET, Java and Perl.
* - Partial openssl API compatibility (via a wrapper).
* - A very small footprint for a HTTPS server (around 60-70kB in 'server-only'
* mode).
* - No dependencies on sockets - can use serial connections for example.
* - A very simple API - ~ 20 functions/methods.
*
* A list of these functions/methods are described below.
*
* @ref c_api
*
* @ref bigint_api
*
* @ref csharp_api
*
* @ref java_api
*/
#ifndef HEADER_SSL_H
#define HEADER_SSL_H
#ifdef __cplusplus
extern "C" {
#endif
#include <time.h>
#include "crypto.h"
/* need to predefine before ssl_lib.h gets to it */
#define SSL_SESSION_ID_SIZE 32
#include "tls1.h"
/* The optional parameters that can be given to the client/server SSL engine */
#define SSL_CLIENT_AUTHENTICATION 0x00010000
#define SSL_SERVER_VERIFY_LATER 0x00020000
#define SSL_NO_DEFAULT_KEY 0x00040000
#define SSL_DISPLAY_STATES 0x00080000
#define SSL_DISPLAY_BYTES 0x00100000
#define SSL_DISPLAY_CERTS 0x00200000
#define SSL_DISPLAY_RSA 0x00400000
/* errors that can be generated */
#define SSL_OK 0
#define SSL_NOT_OK -1
#define SSL_ERROR_DEAD -2
#define SSL_ERROR_CONN_LOST -256
#define SSL_ERROR_SOCK_SETUP_FAILURE -258
#define SSL_ERROR_INVALID_HANDSHAKE -260
#define SSL_ERROR_INVALID_PROT_MSG -261
#define SSL_ERROR_INVALID_HMAC -262
#define SSL_ERROR_INVALID_VERSION -263
#define SSL_ERROR_INVALID_SESSION -265
#define SSL_ERROR_NO_CIPHER -266
#define SSL_ERROR_BAD_CERTIFICATE -268
#define SSL_ERROR_INVALID_KEY -269
#define SSL_ERROR_FINISHED_INVALID -271
#define SSL_ERROR_NO_CERT_DEFINED -272
#define SSL_ERROR_NOT_SUPPORTED -274
#define SSL_X509_OFFSET -512
#define SSL_X509_ERROR(A) (SSL_X509_OFFSET+A)
/* these are all the alerts that are recognized */
#define SSL_ALERT_CLOSE_NOTIFY 0
#define SSL_ALERT_UNEXPECTED_MESSAGE 10
#define SSL_ALERT_BAD_RECORD_MAC 20
#define SSL_ALERT_HANDSHAKE_FAILURE 40
#define SSL_ALERT_BAD_CERTIFICATE 42
#define SSL_ALERT_ILLEGAL_PARAMETER 47
#define SSL_ALERT_DECODE_ERROR 50
#define SSL_ALERT_DECRYPT_ERROR 51
#define SSL_ALERT_INVALID_VERSION 70
/* The ciphers that are supported */
#define SSL_AES128_SHA 0x2f
#define SSL_AES256_SHA 0x35
#define SSL_RC4_128_SHA 0x05
#define SSL_RC4_128_MD5 0x04
/* build mode ids' */
#define SSL_BUILD_SKELETON_MODE 0x01
#define SSL_BUILD_SERVER_ONLY 0x02
#define SSL_BUILD_ENABLE_VERIFICATION 0x03
#define SSL_BUILD_ENABLE_CLIENT 0x04
#define SSL_BUILD_FULL_MODE 0x05
/* offsets to retrieve configuration information */
#define SSL_BUILD_MODE 0
#define SSL_MAX_CERT_CFG_OFFSET 1
#define SSL_MAX_CA_CERT_CFG_OFFSET 2
#define SSL_HAS_PEM 3
/* default session sizes */
#define SSL_DEFAULT_SVR_SESS 5
#define SSL_DEFAULT_CLNT_SESS 1
/* X.509/X.520 distinguished name types */
#define SSL_X509_CERT_COMMON_NAME 0
#define SSL_X509_CERT_ORGANIZATION 1
#define SSL_X509_CERT_ORGANIZATIONAL_NAME 2
#define SSL_X509_CA_CERT_COMMON_NAME 3
#define SSL_X509_CA_CERT_ORGANIZATION 4
#define SSL_X509_CA_CERT_ORGANIZATIONAL_NAME 5
/* SSL object loader types */
#define SSL_OBJ_X509_CERT 1
#define SSL_OBJ_X509_CACERT 2
#define SSL_OBJ_RSA_KEY 3
#define SSL_OBJ_PKCS8 4
#define SSL_OBJ_PKCS12 5
/**
* @defgroup c_api Standard C API
* @brief The standard interface in C.
* @{
*/
/**
* @brief Establish a new client/server context.
*
* This function is called before any client/server SSL connections are made.
*
* Each new connection will use the this context's private key and
* certificate chain. If a different certificate chain is required, then a
* different context needs to be be used.
*
* There are two threading models supported - a single thread with one
* SSL_CTX can support any number of SSL connections - and multiple threads can
* support one SSL_CTX object each (the default). But if a single SSL_CTX
* object uses many SSL objects in individual threads, then the
* CONFIG_SSL_CTX_MUTEXING option needs to be configured.
*
* @param options [in] Any particular options. At present the options
* supported are:
* - SSL_SERVER_VERIFY_LATER (client only): Don't stop a handshake if the server
* authentication fails. The certificate can be authenticated later with a
* call to ssl_verify_cert().
* - SSL_CLIENT_AUTHENTICATION (server only): Enforce client authentication
* i.e. each handshake will include a "certificate request" message from the
* server. Only available if verification has been enabled.
* - SSL_NO_DEFAULT_KEY: Don't use the default key/certificate. The user will
* load the key/certificate explicitly.
* - SSL_DISPLAY_BYTES (full mode build only): Display the byte sequences
* during the handshake.
* - SSL_DISPLAY_STATES (full mode build only): Display the state changes
* during the handshake.
* - SSL_DISPLAY_CERTS (full mode build only): Display the certificates that
* are passed during a handshake.
* - SSL_DISPLAY_RSA (full mode build only): Display the RSA key details that
* are passed during a handshake.
*
* @param num_sessions [in] The number of sessions to be used for session
* caching. If this value is 0, then there is no session caching. This option
* is not used in skeleton mode.
* @return A client/server context.
*/
EXP_FUNC SSL_CTX * STDCALL ssl_ctx_new(uint32_t options, int num_sessions);
/**
* @brief Remove a client/server context.
*
* Frees any used resources used by this context. Each connection will be
* sent a "Close Notify" alert (if possible).
* @param ssl_ctx [in] The client/server context.
*/
EXP_FUNC void STDCALL ssl_ctx_free(SSL_CTX *ssl_ctx);
/**
* @brief (server only) Establish a new SSL connection to an SSL client.
*
* It is up to the application to establish the logical connection (whether it
* is a socket, serial connection etc).
* @param ssl_ctx [in] The server context.
* @param client_fd [in] The client's file descriptor.
* @return An SSL object reference.
*/
EXP_FUNC SSL * STDCALL ssl_server_new(SSL_CTX *ssl_ctx, int client_fd);
/**
* @brief (client only) Establish a new SSL connection to an SSL server.
*
* It is up to the application to establish the initial logical connection
* (whether it is a socket, serial connection etc).
*
* This is a blocking call - it will finish when the handshake is complete (or
* has failed).
* @param ssl_ctx [in] The client context.
* @param client_fd [in] The client's file descriptor.
* @param session_id [in] A 32 byte session id for session resumption. This
* can be null if no session resumption is being used or required. This option
* is not used in skeleton mode.
* @return An SSL object reference. Use ssl_handshake_status() to check
* if a handshake succeeded.
*/
EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const uint8_t *session_id);
/**
* @brief Free any used resources on this connection.
* A "Close Notify" message is sent on this connection (if possible). It is up
* to the application to close the socket or file descriptor.
* @param ssl [in] The ssl object reference.
*/
EXP_FUNC void STDCALL ssl_free(SSL *ssl);
/**
* @brief Read the SSL data stream.
* The socket must be in blocking mode.
* @param ssl [in] An SSL object reference.
* @param in_data [out] If the read was successful, a pointer to the read
* buffer will be here. Do NOT ever free this memory as this buffer is used in
* sucessive calls. If the call was unsuccessful, this value will be null.
* @return The number of decrypted bytes:
* - if > 0, then the handshaking is complete and we are returning the number
* of decrypted bytes.
* - SSL_OK if the handshaking stage is successful (but not yet complete).
* - < 0 if an error.
* @see ssl.h for the error code list.
* @note Use in_data before doing any successive ssl calls.
*/
EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data);
/**
* @brief Write to the SSL data stream.
* The socket must be in blocking mode.
* @param ssl [in] An SSL obect reference.
* @param out_data [in] The data to be written
* @param out_len [in] The number of bytes to be written.
* @return The number of bytes sent, or if < 0 if an error.
* @see ssl.h for the error code list.
*/
EXP_FUNC int STDCALL ssl_write(SSL *ssl, const uint8_t *out_data, int out_len);
/**
* @brief Find an ssl object based on a file descriptor.
*
* Goes through the list of SSL objects maintained in a client/server context
* to look for a file descriptor match.
* @param ssl_ctx [in] The client/server context.
* @param client_fd [in] The file descriptor.
* @return A reference to the SSL object. Returns null if the object could not
* be found.
*/
EXP_FUNC SSL * STDCALL ssl_find(SSL_CTX *ssl_ctx, int client_fd);
/**
* @brief Get the session id for a handshake.
*
* This will be a 32 byte sequence and is available after the first
* handshaking messages are sent.
* @param ssl [in] An SSL object reference.
* @return The session id as a 32 byte sequence.
* @note A SSLv23 handshake may have only 16 valid bytes.
*/
EXP_FUNC const uint8_t * STDCALL ssl_get_session_id(const SSL *ssl);
/**
* @brief Return the cipher id (in the SSL form).
* @param ssl [in] An SSL object reference.
* @return The cipher id. This will be one of the following:
* - SSL_AES128_SHA (0x2f)
* - SSL_AES256_SHA (0x35)
* - SSL_RC4_128_SHA (0x05)
* - SSL_RC4_128_MD5 (0x04)
*/
EXP_FUNC uint8_t STDCALL ssl_get_cipher_id(const SSL *ssl);
/**
* @brief Return the status of the handshake.
* @param ssl [in] An SSL object reference.
* @return SSL_OK if the handshake is complete and ok.
* @see ssl.h for the error code list.
*/
EXP_FUNC int STDCALL ssl_handshake_status(const SSL *ssl);
/**
* @brief Retrieve various parameters about the axTLS engine.
* @param offset [in] The configuration offset. It will be one of the following:
* - SSL_BUILD_MODE The build mode. This will be one of the following:
* - SSL_BUILD_SERVER_ONLY (basic server mode)
* - SSL_BUILD_ENABLE_VERIFICATION (server can do client authentication)
* - SSL_BUILD_ENABLE_CLIENT (client/server capabilties)
* - SSL_BUILD_FULL_MODE (client/server with diagnostics)
* - SSL_BUILD_SKELETON_MODE (skeleton mode)
* - SSL_MAX_CERT_CFG_OFFSET The maximum number of certificates allowed.
* - SSL_MAX_CA_CERT_CFG_OFFSET The maximum number of CA certificates allowed.
* - SSL_HAS_PEM 1 if supported
* @return The value of the requested parameter.
*/
EXP_FUNC int STDCALL ssl_get_config(int offset);
/**
* @brief Display why the handshake failed.
*
* This call is only useful in a 'full mode' build. The output is to stdout.
* @param error_code [in] An error code.
* @see ssl.h for the error code list.
*/
EXP_FUNC void STDCALL ssl_display_error(int error_code);
/**
* @brief Authenticate a received certificate.
*
* This call is usually made by a client after a handshake is complete and the
* context is in SSL_SERVER_VERIFY_LATER mode.
* @param ssl [in] An SSL object reference.
* @return SSL_OK if the certificate is verified.
*/
EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl);
/**
* @brief Retrieve an X.509 distinguished name component.
*
* When a handshake is complete and a certificate has been exchanged, then the
* details of the remote certificate can be retrieved.
*
* This will usually be used by a client to check that the server's common
* name matches the URL.
*
* A full handshake needs to occur for this call to work properly.
*
* @param ssl [in] An SSL object reference.
* @param component [in] one of:
* - SSL_X509_CERT_COMMON_NAME
* - SSL_X509_CERT_ORGANIZATION
* - SSL_X509_CERT_ORGANIZATIONAL_NAME
* - SSL_X509_CA_CERT_COMMON_NAME
* - SSL_X509_CA_CERT_ORGANIZATION
* - SSL_X509_CA_CERT_ORGANIZATIONAL_NAME
* @return The appropriate string (or null if not defined)
* @note Verification build mode must be enabled.
*/
EXP_FUNC const char * STDCALL ssl_get_cert_dn(const SSL *ssl, int component);
/**
* @brief Force the client to perform its handshake again.
*
* For a client this involves sending another "client hello" message.
* For the server is means sending a "hello request" message.
*
* This is a blocking call on the client (until the handshake completes).
*
* @param ssl [in] An SSL object reference.
* @return SSL_OK if renegotiation instantiation was ok
*/
EXP_FUNC int STDCALL ssl_renegotiate(SSL *ssl);
/**
* @brief Process a file that is in binary DER or ASCII PEM format.
*
* These are temporary objects that are used to load private keys,
* certificates etc into memory.
* @param ssl_ctx [in] The client/server context.
* @param obj_type [in] The format of the file. Can be one of:
* - SSL_OBJ_X509_CERT (no password required)
* - SSL_OBJ_X509_CACERT (no password required)
* - SSL_OBJ_RSA_KEY (AES128/AES256 PEM encryption supported)
* - SSL_OBJ_PKCS8 (RC4-128 encrypted data supported)
* - SSL_OBJ_PKCS12 (RC4-128 encrypted data supported)
*
* PEM files are automatically detected (if supported). The object type is
* also detected, and so is not relevant for these types of files.
* @param filename [in] The location of a file in DER/PEM format.
* @param password [in] The password used. Can be null if not required.
* @return SSL_OK if all ok
* @note Not available in skeleton build mode.
*/
EXP_FUNC int STDCALL ssl_obj_load(SSL_CTX *ssl_ctx, int obj_type, const char *filename, const char *password);
/**
* @brief Process binary data.
*
* These are temporary objects that are used to load private keys,
* certificates etc into memory.
* @param ssl_ctx [in] The client/server context.
* @param obj_type [in] The format of the memory data.
* @param data [in] The binary data to be loaded.
* @param len [in] The amount of data to be loaded.
* @param password [in] The password used. Can be null if not required.
* @return SSL_OK if all ok
* @see ssl_obj_load for more details on obj_type.
*/
EXP_FUNC int STDCALL ssl_obj_memory_load(SSL_CTX *ssl_ctx, int obj_type, const uint8_t *data, int len, const char *password);
/**
* @brief Return the axTLS library version as a string.
* @note New API function for v1.1
*/
EXP_FUNC const char * STDCALL ssl_version(void);
/** @} */
#ifdef __cplusplus
}
#endif
#endif

65
ssl/test/Makefile Normal file
View File

@ -0,0 +1,65 @@
#
# Copyright(C) 2006 Cameron Rich
#
# This library is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
all:
include ../../config/.config
include ../../config/makefile.conf
ifdef CONFIG_PERFORMANCE_TESTING
all: performance
endif
ifdef CONFIG_SSL_TEST
all: ssltesting
endif
ifndef CONFIG_PLATFORM_WIN32
performance: ../../$(STAGE)/perf_bigint
ssltesting: ../../$(STAGE)/ssltest
LIBS=../../$(STAGE)
CFLAGS += -I../../ssl -I../../config
../../$(STAGE)/perf_bigint: perf_bigint.o $(LIBS)/libaxtls.a
$(CC) $(LDFLAGS) -o $@ $^ -L $(LIBS) -laxtls
../../$(STAGE)/ssltest: ssltest.o $(LIBS)/libaxtls.a
$(CC) $(LDFLAGS) -o $@ $^ -lpthread -L $(LIBS) -laxtls
else
performance: ../../$(STAGE)/perf_bigint.exe
ssltesting: ../../$(STAGE)/ssltest.exe
CFLAGS += /I".." /I"../../config"
%.obj : %.c
$(CC) $(CFLAGS) $<
OBJLIST=..\aes.obj ..\asn1.obj ..\bigint.obj ..\crypto_misc.obj ..\hmac.obj \
..\md5.obj ..\loader.obj ..\p12.obj ..\os_port.obj ..\rc4.obj \
..\rsa.obj ..\sha1.obj ..\tls1.obj ..\tls1_clnt.obj ..\tls1_svr.obj
../../$(STAGE)/perf_bigint.exe: perf_bigint.obj $(OBJLIST)
$(LD) $(LDFLAGS) /out:$@ $^
../../$(STAGE)/ssltest.exe: ssltest.obj $(OBJLIST)
$(LD) $(LDFLAGS) /out:$@ $^
endif
clean::
-@rm -f ../../$(STAGE)/perf_bigint* ../../$(STAGE)/ssltest*
include ../../config/makefile.post

15
ssl/test/axTLS.ca_key.pem Normal file
View File

@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCnZdk20fYWh8O6kDTt0AuJWyp0YIrb7W1UNNMPXI5wA4J59IVj
Nmk5wocm9+Hqzbg7rORAN/mHPBhzLAjhnm1HODs36hW15DtbDkkH4wCM/Tsyv79m
n0xq1V6peK3t9vi2D4p/IRjHkYR2jm+BeknopijhY0kHHfpGTHa2DnVirwIDAQAB
AoGAd4Ia5SxYiBU9A0BYyT8yPUm8sYELIaAL4YYk+F6Xwhh/Whnb8MyzquzaGFP4
Ee30jYYNHlvX5VheDDtvy8OTN5FgKNNdzvW15iA4Hxje04ZI7W87G7OIxm7aYRid
sG4XqZBtsOdj33IRd9hgozywGJ2qRqS6nn2KxRv1w07RniECQQDZAlKxijdn+vQ7
8/8mXzC+FwQtzeTUCuLrBJcos9I/591ABoxYkWcYLxpFqgCEVwb1qfPBJkL07JPt
Fu6CTnBFAkEAxXmUBs47x5QM99qyBO5UwW0Ksrm/WD4guaaxzQShMt/HzgJl613z
/x4FtxiQJHAr6r2K0t5xTJx89LVKuouYYwJAImue6DAvJ5wDfzrtXo28snn+HLHK
uONdKL/apgcXszE4w74GJsoxWwGlniUf3d3b6b1iP2GtPyIDOJjpjduZLQJAE4jS
VtYB3d1MZxxQLeKxqayyuTlcr0r+C79sqT5C//hZGIzuLhlOMLd0k0cvwxsBjSgQ
2ok8pfp49fAVI1z5xwJAVmJgLc/mSti5A2q3c8HW8qvMJEDPWbpb7p8pg4ePtpa8
EE3TO4O4J2H+k40C397km4yZXdkNQsiT1zVljJZpiw==
-----END RSA PRIVATE KEY-----

BIN
ssl/test/axTLS.ca_x509.cer Normal file

Binary file not shown.

View File

@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB3zCCAUgCCQCdbnM4pjqlWjANBgkqhkiG9w0BAQUFADA0MTIwMAYDVQQKEylh
eFRMUyBQcm9qZWN0IERvZGd5IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0wNjA2
MDcxMTQ0MzJaFw0zMzEwMjMxMTQ0MzJaMDQxMjAwBgNVBAoTKWF4VExTIFByb2pl
Y3QgRG9kZ3kgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA
A4GNADCBiQKBgQCnZdk20fYWh8O6kDTt0AuJWyp0YIrb7W1UNNMPXI5wA4J59IVj
Nmk5wocm9+Hqzbg7rORAN/mHPBhzLAjhnm1HODs36hW15DtbDkkH4wCM/Tsyv79m
n0xq1V6peK3t9vi2D4p/IRjHkYR2jm+BeknopijhY0kHHfpGTHa2DnVirwIDAQAB
MA0GCSqGSIb3DQEBBQUAA4GBAB0LgNo0oCcwIie5plgwwFybQ8x95q6e3wndM/Mp
3gjcAFbGuchpo3dfFlTcRI0KyERb3q1MVxPM4sff9nT7EdHVyK9s8/ITkP2dcTKc
flbcTEfJVIeM8L2P5F41Hvn9GuGcMW8EmsC06gdbp1LLnqsdrXdMNBsAUBXfgPrU
+UcZ
-----END CERTIFICATE-----

BIN
ssl/test/axTLS.device_key Normal file

Binary file not shown.

View File

@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDUIg4NEiu/diDAlbsWbTAhMKw4iBf2X5ohGJdTO6vhGQdEkhBR
Bgzdl9+0LbVDJY8YStUghwnuztT+IpNCrUtXtRK8Cn3QP+buzSe2ZGPVoEJIbvV/
QudK/WuUDyTNSRTtW4S3RO36KqtbT6xh1QGTXV3I8sp7qwmcysklqZW8GwIDAQAB
AoGBAKBEDkuPw9+Ftp7pQIxj963LoQGgyEHJ3p9Mfd9TQLrydsw2cf9Uy9mKiWcN
9VkCgkZ/Gt/VRgrW1pIduxXv6O+8S14An+2mTayy3Ga1N6MulD7OHQP9kqR4j8TT
xaYPR/1skjhQ+Y0Uw4NEa3OkQp6lAUEp1aVX/mTfIZBguaUxAkEA/H543Ha6wbUV
iB+pHaBgj1nzarmuEey6kqqs7X0zoZory1X6bdpJ6l0/4qICa6aq+pt/7ywJCNoI
CPK3mL2zGQJBANcUHRBe7/HRWrJNIqB2WDA/gJshq4xOAiIBXWk1wpabvpkCnUjQ
rip5CAL3hXDnCQswZxRN/v7B4IlSxkKiY1MCQQCsL0MUdRMejfLFBXI6defjWiAZ
I86FAr6oziNnQP44sf4zh8pjp3zIihbK4lhsORhYFjrES29NzgG0uHBjhNnhAj97
gBEwVVNyh8SMnb5EZbA+BDjU24CmECUpYZ9Bypzx3nyTX+zw4uMfgGAZVAhLzF5l
DmYiQqcpoipMsDsoCBcCQQCxBYSicXIPG8G6ZuFbgXFcZR7llgq74mbhfGuVEGbP
qS6ldhJb/IG9O3MFlRwdU44YyJ8QGpBKWF94OpIduF6w
-----END RSA PRIVATE KEY-----

BIN
ssl/test/axTLS.encrypted.p8 Normal file

Binary file not shown.

View File

@ -0,0 +1,11 @@
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIBfTAcBgoqhkiG9w0BDAEBMA4ECN+YmhCv0ILdAgIIAASCAVu0QEfMkp0xUsNq
0Ek4Nsa/uxcs8N/2P7Ae7qCakkvsdRvvPPH0y+wuj5NgrG6WpPeeEx9fI2oNNTfC
pwncH0Xm99ofVrgMX6XC45LDZtzXNSZd4TdBP6xvlYXbuGegp5GPJ8emzscHCFhC
JfPHemRAcB7DhiWukPosuSUr5R8OluEMJrQLHuQtlDAvMjLEI98lSchPxF8LKCk3
SS2uCcmc+4WiR0nHG9BOaGi38+PytHAnbfo1mfVSQzLfgLicMAVGysfQ9QOgpQOO
ygYfM/s7Duwbl0rshyXVJP+7BpYJnPtHvO4BTiizU7ZEr4WBiEnnANDrupSdsxeH
+cxZo70YJVdoPdgMd2ke6EIkUhp7HughFg+okldlEtJA4muKeEzwAxZu0TqxOtZ8
UYRS4Ygk+rN7Y0qTKSYwSkrFBwUDkpctYjRUOeAZ/mYMKWmMn1ejAb5Is7bjEIxl
tw==
-----END ENCRYPTED PRIVATE KEY-----

BIN
ssl/test/axTLS.key_1024 Normal file

Binary file not shown.

View File

@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDY4L8V3uqv6NX9C6ios9dGXacmbAy12bzG+MB40PZWZfgpSA57
C6Ylfuh7eW845bW39OCckWD0BvNAHvmRGakvR0O1mx7c9qocSXkhKMuqSXPZCQVM
AvJMTWwcgKcUkUT8ErPh5+NPRLqMw3Q56EzQ1EwkYbRAlYzACrcCOTGFkwIDAQAB
AoGBAJQHcuW+rXk79zMsjgX4GmvQ6JH1FgfZglxc1SKhnkICf4vNvvSFUvYs1QnS
LPQs9geFgPnc0Mw/IjEV80nyteJpmQQESSHbn6FUWvrk2fkHBf+aZaTr8kfOVsdy
SUhc6BTXjyXMSSkGalR7F9ye1FPw9Z6FJaHrPekvuZz24YCBAkEA7gJ4x3iFBJfM
Nr3WEeLHOdk0UXJvig/NiDIzm8enA3fZgjW23R/CwRNAg1XrYOuBjgwWYrS0POsI
gJx50zjK8QJBAOlFXy4WzJNQQLZ5vDjgVmhQ0y9zjIwqDoFKirvM8GQ0Rp8HfSK2
+UasVyOMHuvTBU2og2pn9qaxq47B7+998MMCQC/GWT4Y6AJzAe/fDTBL6BepjMHo
iZEZ+PSktw1G9zRQA14KsCkUrgAZgDKctYGf5EKCFKA9i4xK1UsTnbSTStECQGSM
g3dhWnMRP6OoG4rEoFo8pJsqimWMZ04xrFVBBEmdAuffmX/SMObWuITZDCcIgZu0
zFicUYQOx200iVDJD3MCQQDa3l4arB0d17llJgD11OQohIYvAJxBAFLhR5HAUgVO
Dy8Nyps9iUG/7p+h5p2k60V/48ukawrifrCHXECxUREd
-----END RSA PRIVATE KEY-----

BIN
ssl/test/axTLS.key_2048 Normal file

Binary file not shown.

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAwqC/2/rPcAZEs5/ejT3ZL8Q3Pfdna2WC44i6HYCnCnbOIcW+
6Xub2IXGwRwQBFy+mRE9WjqJ8kuOEkSt6e+8wAhLdag7WXJ6cxoag110t5FEHSyd
GfvFFyUNjMJhLd+EmaQTTpEv9MJPJj0Zdruh1EjyRxa4HJmiD9t7XmWyCfSmM0qM
kgJ0J6s62rRMBX+l/NEEX2VzJugdZAU671RWYOncuxX/2jUYlvIqI1l3SP8acMU5
BtfLsYMj08lNHOjgZCPRwkdjsl6U5EqIizKZygw1FNugVEDHnL2MAYXwqzX3pGr/
72Biy+J4TSH6lt0stszS5m8BirMgYr2FFHslrQIDAQABAoIBAQDBTa0gzEupJOCp
UvhUagBDO+vuBMJX3XuRh6PqV3QQpYz36BJEjXttIvkTpU6XNpIrLv8zlX6bAsW5
iTL+bRiX1eU0l4FSxqutlFiO7oxVIdd37m6edvv6j9eUXR7t09k8S8TNPNBXlYHN
JdQbpCIH2OehCYSVC1X1z/UI/ZJF5VSn7UsYgwReK102svfHtll85K0TgHMir9Rx
Dlh0vYx3IJi2nDOTyJ4JekkyEAcYd3D6JUd0JujcN3Ev3EOsns5GXzN6KYvinmYf
Z1bA/HEMNb9ZS9bdsoAvyeJAeGp8ejzuJVHGL0kATgrAamb58fPS+A8Guk5eN5KY
5zvzNrJVAoGBAPVWvPrDOJX2ZI7poJ269xFteTWWIYA+r+YRRkhMBMcD08H5gs6e
QMWU9w8qjgSmbNkx8skkhn/gV5R3CbVYYRR2osrZIoOayWAsJmY0bHFTIvooYhfp
3lPVNIPzUpRObFksamtrsK+zpx5qOdigNhComXLsGWKfrN9Yvkb7YzIDAoGBAMsV
4UVH9WH0IKV1vx3QtrGEb69SZMpbmM8ZsPvaPgq00In9udY4w5V2ZygfTiq0ChUY
fYy6BeO6Gyp2DSABdz1AUH+0wcnNrHJghFtxtsq4Thu4MHU6ftc+JCGfSeWUapfh
KiHS0TEguRFcYSHnM1IDEiU4aTHY59FRUWMI2hKPAoGAIVfviTk9GIyLMC0qaiV9
7L1vKsxDs1VRvLf+UFcckxu/DO7nS0OQ1Amh5krHUHR5+K7kK1gue3S3EnN3O1FO
qGRTTbRjD3XbBpoZgeyADIrbBxqz8kITuFsSrxhD0eoyqY/yyrSxJ8AH54dSY1Gq
52qyqD7UWGYRLa229pi165cCgYAd7/rGWMY+i1toqMPkpEjaQFiqcq3y+q+7D+F8
Lv7oWyFGxkVn4/RJCyxHyN2gA+xckcCoRx/pIx0wFDj5F945BEsZmE7c7dnW/o1k
YY39sk+pXGygS2A5YKq43h9pnYhdHU81rzsxT86YVZLoCYoSM+uv2vH+7Ce4PpGN
1Nc41wKBgDUrYyfDB1RzdB63FwPRax5uLjewnuMXyZhy70ZkiGh0XBuQt2aCLeCZ
HpAyGcJryxdDFYA+UwJoSWjaW9ku0lp+GxX1F+cResrRHTi70w9czwGVaKmcG3kI
fFjG7w8nkiw5J7IRH7SxmNbmAv8L0Iy6jvoWLFB+EdUGWllkjCmJ
-----END RSA PRIVATE KEY-----

BIN
ssl/test/axTLS.key_4096 Normal file

Binary file not shown.

View File

@ -0,0 +1,51 @@
-----BEGIN RSA PRIVATE KEY-----
MIIJKQIBAAKCAgEA/Ce0mV0qytAwDPrjXRBlUh2gdKs2thDw3N18owXVrSUFq9Sw
AaMNrmep9DR9MEALcdMm3GCEJ7sOOiEQcqTz25di36WJDe+jo1z5nD2XZsPIsp9+
k51Vz+W3B4vsXJAgzV+XZbmv9L0598VEwkpeI3Uc9et8ZhGvDPoHZyBQG1KAj6h3
AKZ1+NthrhajxlrndQZ5Du/R5DSUQOBcCHHdzZgihdfF97Yn/kp1mele1ElZMlqg
BtpDi1TEQJ9XBtjCW0epFAm5THQ3gMx5DCcqB/cNYdZWqpZ0AuwATm61+46m4fFK
g3YAYPOi/74aKFuIQBw/lc8W//SV1x8SL/hf2XIdvSa9QhroNN0d3Xu2EUQzXZxo
PRMKzOqKfwlZW7ozT6hFBwPMh8yfhoPugq2TvqBjke1s3gmvwTgEcf+gY97qXiZC
X5bh/ehmnZ7vIblYFUD2yMlsKaXGJYweh3WKJlQnh71wQUg2Mxa6ig8ijrEozNlw
YfPCQFrNLqQfJOwdx90dy7hpUyUn1wo39p6wmC6n9ex4zeKbO4ndSp+/AJ+d5Qp8
zoMzwneYV9LBQG8ry4uwzDkSWKb/WghsEbQ9O3sGIuI13SlT/B64v3bLb5AHagI8
zS3kPsshjKhkcc2W9MKRBU2wIeCsNS052kaUq3rPMSBROrALmLk3en/Dq48CAwEA
AQKCAgEArPMy7So5Cqjm/FAtGI0BYeRORReWTCSsgGEudsauu7a0ABq+qjDDVodl
y8kgwLJ85xKUCf3tRy8G4BoDpQ688DYSrCFnMvbWP1urHV4ldWf+RX4eHHODAzil
ZHi1ovt8dEEHn89P/8a2dtqIgdbuYNWYCpj9Vyjz7yujXjmMmGDrKx26meiS7CDV
C8odhRSewuawq+0UArmJokIA/g3Tu4uIylKoR3JaVhGOPgYSc/rnQiFkt66HO47l
mQlxcJHGJUOulb7hqK3hz+bvc8V9D7+FH0EbaqANbF+hCirniWZb0odku2x5cAZM
G6uxV1MIzihR+Jf1R5PkHowCNoLegfM45tnuadP1+8Kezv1SsqkrkMEwfb0QN19C
2+bmnwYXagUgg/A2q2Shg9h4/3cpwdrDzGHD8IttGlzLR8HnlHkcAK3qRNqy9h60
JDEW/tOurUSZBXjU9ZyoZSukcK3+yUjCDWS92wMOBlUQGh4/HCOOizahe6lhn2nT
+jkBvl38c+7GBKR0VyCisFi++FukMBbyU/hNNFByZxOj0b/+YVYI0qwM5oDzLhJH
69/VhxMx0xVt9/kOOO3yhdGjKCZztPZZm5mg2OzzXmf4im+hPSg0/OrdXrVNk4v/
w7ouUQHSa3+rAAu8BJFF2rTWA7rjecVEnk6c77I6dEVYXdCfz8kCggEBAP+IJLHo
7Cs51qPcRKQc633phJa3pFGf6O8xN6pl8z1ZQX0voZyROKJLTytSH+zmPdmggUeg
7CRoV8BKY49YiOxO2Kx8BPfftItS9yvA3O9ztcdzQa72nYusMWwvj0yFU8DbYfnx
yYw59F/1pdPKFN83Sj4MJAOb4nAxBP1GiZvsPAgcTpf/197NLNHwUDdk/TXDtTLa
lx4uTn/SJDQuvsCCLBKyx7FdN5NPRN2kIKUWZLd7HRu2EhcSlATwf4TUPZz7atKN
2FD0svErpPOAspNPtnNj3RgeunGVqS2oi/XueuveNNCYLkcV8/UaZm85LBrPoEre
23qK9/ZN0SD534sCggEBAPyd+nD71pScrM0TI4Lc3jMNUKeZj3sT5rlhlkWlARhQ
WPEWYYg5vs3zDiRpG4Xy3n9ey+M6Tuw+/XpcJZxhrLYFOqparxXPP4qc+3EvtzpF
OskLR/2/bVnESf6+pQspmwW6G4IJ9vOmIJeUj9zeU0txuxKkjhAmInCnMxJOlYRm
xeLymuo5LZxrXmSXcX4cyZ0/4bF2L3IE5vH7ffdWXWYzW9wP7M4sFp+0iKjHuhC1
gB6Qg0Mp0TVNUt0ZEelFLEJdA2lbbZ5yHhNXuhOxW/l3ASSe9tjTpy7yBSwBOpFG
l7QGISfJVEFfjyn7yWBYj5LDGnitlP4TtN8zyy6cJI0CggEAPRwY8ncqq7e8Thmq
TLkh1E3ZSJYIdQDSGwnhLx4MirpiwAZ5FtFgAugRueF9AxGY7wfEgxXIA3j0q2be
4nQg4qqEhNNv+LuGGN+xfsQz0gwRB+7XYXlW+gUnGKFTGtCz0+ZjSvv44FEn0R8V
Fk44qZ02YxpSLo7EG2KNt+h7lk9rl+D1JsKnpH/a3SYkeOrs50OzfMLr6urWGRlv
UQ9wzOcUlTAuM4uAc/k8FelfaTuuwHZv4qWrM9tcjMXbKS/8wCMcS9hiSBINDUIL
w7QegL5KetQCFveaTPmmqOWq+xiaSvgsF0qdnqBwZEh5ANZiZtMKmX0sbeT4Ie5A
OiunuwKCAQBlSlrvDqu9rwzCtdfZUwJtaftbGIGlkhdDYdPFXSIRQ7ZGBPlai/zr
y3dyNgrpLLb2T2ZlWC3pIGC2vVf/WlLMMVCSmgX2MsGBrOxNOBq57KRjlHhrUGRi
SAh7cqnuzeHw6+y3uZMhow0Semks4KB5ccLW+NBVvVS14vThdE0TZ7oVA74GCKM3
Qv34S5kgPh7BRKoUZBUmHL0VbgfWMvUEU7eTh3cmPBteMh9RvbPnmz8iAkP/nDbc
roJ5UOITrL7QZUdG6XgMvik9DEH6P3Vnk8YLjwnfaw5wDm7wdBWtxqZxcru8nkeA
ZvaamPDoBtqauExW8xL4xaISlUv1BnrJAoIBAQCiEZk93GeRzYJFCO1YafsGYueX
Pffgd9wM2TpObgaEw8OIfEpGQKDiR35fb0uVzNyI5fVU5D5tP0b3LfvtQXV12ryQ
sVTA5YJcb8mRuUGy/AkjL54kNiZthUnlGHQjY3lqSyI1r5WxRIZBBRn5+g1eSZVq
CYCGjEryKm7vw8Qcvy1+H2crcZ0rRyLTcfFCr1ZXlyEZu48ScOtxcIDHc7j4J0LO
Peq2z0tbBojGkxFLX94J7zpRkWMPX9VHorEavDv7ZJwtgoXn3Lom0xHhO+JQaxY9
FtJ79Ps9+SquXAnkhna4bbkrqrPM3+MAAV/S7bd1T1/8d4YiRQyaMHGS4Yr8
-----END RSA PRIVATE KEY-----

BIN
ssl/test/axTLS.key_512 Normal file

Binary file not shown.

View File

@ -0,0 +1,9 @@
-----BEGIN RSA PRIVATE KEY-----
MIIBPQIBAAJBANE7MF+pAUI9hm1yvkBuUcFJf1d1oS025cE9DyAa0SNt+nTSPiOw
cPygat7sQYiE/lQVa2HFFmK4k0HxTz3/Lr0CAwEAAQJBAJF5xO2ONajX3GK2+B8W
VVO+BYNK71DfranJCX46BxXI/Ra7wOSY0UWZYHVsZGWJxx41os0UBTg5FRq4DwWW
AQECIQDo69eo39iQqjwhpAQxatMh2CWYT7gokyu56V+5o2V3fQIhAOX2b+tQxDsB
w0J9UDN6CdwI5XbzveoP5fHTPS9j4rhBAiEA3c+y6Zx6dZHYf8TdRV5QwDtB2iGY
4/L7Qimvwm6Lc1UCIQDDXWrVsocTTjsReJ6zLOHFcjVnqklU2W7T1E8tvKE3QQIh
AMRpCFM7MrS2axuc8/HzGkqW/3AlIBqdZbilj5zHd2R0
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,12 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,B3A0D2BCEF4DE916D0BBA30A6885251B
v8y74AGReaPLmDt6O8wir6hX1Ze8K4fVNkrLqfDMdW5E7jBXKO8riCMNmSjQ9fyh
eTicej93+8krcIvSXKW18TdO+EWezQevgnLrAZQWaNPH2j4B+K5gm701uiiKFKVa
1zngAOByePYlN6z4JLbiCyJRhxSo5zCaUYkKC2eGh8mlE64QmokPSCAj0wcCDzGh
hdhBg1vm0GmaQwIDVn+8zMfahscXVMtBmyQf5YP4PQW2nqOt7aZHjBNdg9qnBpGw
b6YuY7eZ4FgQvYcsNCi34NroJb9pkTrrF2F9Meb6+3So7jtMFG/YaJdCuXtf01g/
Qm+XA5pJUtIUr/hLQjhkaOVUtXv/k0o/MR4k5CbAmboLt6YHf5V8+01vk0bvv5dI
70pVdXMmx26xDZOGmjYzd93PWc+75jak3GN2fbWryQs=
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,12 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,F076229CDC2BCB3B8722E3865855B45C
WFV9QWzr4tNmD+1OeQ7BceQg5LVQHp20Jo1Ax29lq8JTPzeObhtaU2MUHlcPKHUS
vK4FyQxJ25CyMubbnaZqCCz9pNbseFuJ1tob9UqRmXkZ8HV3snRjJRbcctD+V9x+
Ymi1GreXoDQtMp0FtMiFjPvIYciBQnaRv2ChMAnGXNbZXCxWWA9E5S3a+yWzo+gd
wEcowL+SUac1PEDGHokhKn7nctvI9cC4hE6JmKM1sD68/U3rRPXMGqmC7umqyT5P
gjWBb1uu0iRjFC9eQUsaKPxey5Be710GFlyf/Ff/tep7RhkryIWEPvIzYCBf6rhk
3pysFgTjfiUuBYUNumjXr/q5hgdtb75788XUDxKwAoUx+m8gi0nJg35CN2nmQ054
VJxcZlNv0wqnJ+GTTZeN6fiAhTpVtHsqHQomRSfaBiw=
-----END RSA PRIVATE KEY-----

BIN
ssl/test/axTLS.noname.p12 Normal file

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,10 @@
-----BEGIN PRIVATE KEY-----
MIIBVwIBADANBgkqhkiG9w0BAQEFAASCAUEwggE9AgEAAkEA0TswX6kBQj2GbXK+
QG5RwUl/V3WhLTblwT0PIBrRI236dNI+I7Bw/KBq3uxBiIT+VBVrYcUWYriTQfFP
Pf8uvQIDAQABAkEAkXnE7Y41qNfcYrb4HxZVU74Fg0rvUN+tqckJfjoHFcj9FrvA
5JjRRZlgdWxkZYnHHjWizRQFODkVGrgPBZYBAQIhAOjr16jf2JCqPCGkBDFq0yHY
JZhPuCiTK7npX7mjZXd9AiEA5fZv61DEOwHDQn1QM3oJ3AjldvO96g/l8dM9L2Pi
uEECIQDdz7LpnHp1kdh/xN1FXlDAO0HaIZjj8vtCKa/CbotzVQIhAMNdatWyhxNO
OxF4nrMs4cVyNWeqSVTZbtPUTy28oTdBAiEAxGkIUzsytLZrG5zz8fMaSpb/cCUg
Gp1luKWPnMd3ZHQ=
-----END PRIVATE KEY-----

BIN
ssl/test/axTLS.withCA.p12 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,12 @@
-----BEGIN CERTIFICATE-----
MIIB1zCCAUACCQDxw4fA1PRXwzANBgkqhkiG9w0BAQUFADA0MTIwMAYDVQQKEylh
eFRMUyBQcm9qZWN0IERvZGd5IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0wNjA2
MDcxMTQ0MzJaFw0zMzEwMjMxMTQ0MzJaMCwxFjAUBgNVBAoTDWF4VExTIFByb2pl
Y3QxEjAQBgNVBAMTCTEyNy4wLjAuMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
gYEA2OC/Fd7qr+jV/QuoqLPXRl2nJmwMtdm8xvjAeND2VmX4KUgOewumJX7oe3lv
OOW1t/TgnJFg9AbzQB75kRmpL0dDtZse3PaqHEl5ISjLqklz2QkFTALyTE1sHICn
FJFE/BKz4efjT0S6jMN0OehM0NRMJGG0QJWMwAq3AjkxhZMCAwEAATANBgkqhkiG
9w0BAQUFAAOBgQALRyRSfbZjeLyA3YdskEwzw1ynlwkcCU+bbrNaPkaSGseHFVnh
iFzOauKWqjLswu14i+CQZpMUw5irMzXTfV1RCpy5EFhHepiVZP9MXYIZ+eoPXprL
Midkym9YitDANvS5YzSl2jZQNknStzohM1s+1l8MmYO3sveLRMRec0GpAg==
-----END CERTIFICATE-----

Binary file not shown.

View File

@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICWzCCAcQCCQDxw4fA1PRXxDANBgkqhkiG9w0BAQQFADA0MTIwMAYDVQQKEylh
eFRMUyBQcm9qZWN0IERvZGd5IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0wNjA2
MDcxMTQ0MzJaFw0zMzEwMjMxMTQ0MzJaMCwxFjAUBgNVBAoTDWF4VExTIFByb2pl
Y3QxEjAQBgNVBAMTCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAMKgv9v6z3AGRLOf3o092S/ENz33Z2tlguOIuh2Apwp2ziHFvul7m9iF
xsEcEARcvpkRPVo6ifJLjhJErenvvMAIS3WoO1lyenMaGoNddLeRRB0snRn7xRcl
DYzCYS3fhJmkE06RL/TCTyY9GXa7odRI8kcWuByZog/be15lsgn0pjNKjJICdCer
Otq0TAV/pfzRBF9lcyboHWQFOu9UVmDp3LsV/9o1GJbyKiNZd0j/GnDFOQbXy7GD
I9PJTRzo4GQj0cJHY7JelORKiIsymcoMNRTboFRAx5y9jAGF8Ks196Rq/+9gYsvi
eE0h+pbdLLbM0uZvAYqzIGK9hRR7Ja0CAwEAATANBgkqhkiG9w0BAQQFAAOBgQA8
L1Zz9K6M/PQCYWrfnTjbPKY2rTB1OvSV0Uwy5KKPQRS1+oK9dx4K0miX+1ZvI1bo
f7/1aFXOsW3dpTwYUSjJvTMjSwNUPKiB/q/xwA1mzsbIZsbnhIITU95mOJ3xFhgc
YFdJ4saL7pppTzfOxZ+h9jWbDwgJJAwx/q+O72uE5w==
-----END CERTIFICATE-----

Binary file not shown.

View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDWzCCAsQCCQDxw4fA1PRXxTANBgkqhkiG9w0BAQQFADA0MTIwMAYDVQQKEylh
eFRMUyBQcm9qZWN0IERvZGd5IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0wNjA2
MDcxMTQ0MzJaFw0zMzEwMjMxMTQ0MzJaMCwxFjAUBgNVBAoTDWF4VExTIFByb2pl
Y3QxEjAQBgNVBAMTCTEyNy4wLjAuMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
AgoCggIBAPwntJldKsrQMAz6410QZVIdoHSrNrYQ8NzdfKMF1a0lBavUsAGjDa5n
qfQ0fTBAC3HTJtxghCe7DjohEHKk89uXYt+liQ3vo6Nc+Zw9l2bDyLKffpOdVc/l
tweL7FyQIM1fl2W5r/S9OffFRMJKXiN1HPXrfGYRrwz6B2cgUBtSgI+odwCmdfjb
Ya4Wo8Za53UGeQ7v0eQ0lEDgXAhx3c2YIoXXxfe2J/5KdZnpXtRJWTJaoAbaQ4tU
xECfVwbYwltHqRQJuUx0N4DMeQwnKgf3DWHWVqqWdALsAE5utfuOpuHxSoN2AGDz
ov++GihbiEAcP5XPFv/0ldcfEi/4X9lyHb0mvUIa6DTdHd17thFEM12caD0TCszq
in8JWVu6M0+oRQcDzIfMn4aD7oKtk76gY5HtbN4Jr8E4BHH/oGPe6l4mQl+W4f3o
Zp2e7yG5WBVA9sjJbCmlxiWMHod1iiZUJ4e9cEFINjMWuooPIo6xKMzZcGHzwkBa
zS6kHyTsHcfdHcu4aVMlJ9cKN/aesJgup/XseM3imzuJ3UqfvwCfneUKfM6DM8J3
mFfSwUBvK8uLsMw5Elim/1oIbBG0PTt7BiLiNd0pU/weuL92y2+QB2oCPM0t5D7L
IYyoZHHNlvTCkQVNsCHgrDUtOdpGlKt6zzEgUTqwC5i5N3p/w6uPAgMBAAEwDQYJ
KoZIhvcNAQEEBQADgYEAcrCtPXmZyPX01uNMh2X1VkgmUn/zLemierou7WD/h7xL
dOl4eeKjFBqIiC19382m1DK4h1F8MceqaMgTueCJpLM7A2cwN3ta8/pGP2yEVhdp
h10PkdRPF/AU8JmxnFaADsc6+6xWbbrdNv5xcvP1bJKWWW+30EhRF9PxjXiETXc=
-----END CERTIFICATE-----

BIN
ssl/test/axTLS.x509_512.cer Normal file

Binary file not shown.

View File

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBkjCB/AIJAPHDh8DU9FfCMA0GCSqGSIb3DQEBBQUAMDQxMjAwBgNVBAoTKWF4
VExTIFByb2plY3QgRG9kZ3kgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTA2MDYw
NzExNDQzMloXDTMzMTAyMzExNDQzMlowLDEWMBQGA1UEChMNYXhUTFMgUHJvamVj
dDESMBAGA1UEAxMJMTI3LjAuMC4xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANE7
MF+pAUI9hm1yvkBuUcFJf1d1oS025cE9DyAa0SNt+nTSPiOwcPygat7sQYiE/lQV
a2HFFmK4k0HxTz3/Lr0CAwEAATANBgkqhkiG9w0BAQUFAAOBgQAKRT6LwFr1xedJ
b4qrvjB+EwV/0p4TNNXUS9S30rMSFvRar7VxvLP1lpYj9PR1JGSZMG/B6hR4yumF
Rjwel9FPgNcWCW4DXAWqz3UQF7oZtJL6K+XJpQ0gwC+Nxc+RRGNLMlK7dLiqFh/V
qZLej5Xy93M0JyZBiLV88P+c08gd7A==
-----END CERTIFICATE-----

View File

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBkjCB/AIJAPHDh8DU9FfHMA0GCSqGSIb3DQEBBQUAMDQxMjAwBgNVBAoTKWF4
VExTIFByb2plY3QgRG9kZ3kgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTA2MDYw
NzExNDQzMloXDTMzMTAyMzExNDQzMlowLDEWMBQGA1UEChMNYXhUTFMgUHJvamVj
dDESMBAGA1UEAxMJMTI3LjAuMC4xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMDo
g6K2iXFftW+Qk+rrzkMGWrtfY6YSxPstPRrI7akluUEoyWGITXbK6L3QfERrf2eu
CnWyciQiHVRoHC0EgZUCAwEAATANBgkqhkiG9w0BAQUFAAOBgQBT6YhR8x/bBteK
lr8E0l4mATOnYlsmge+z/SFYs4bDBofqlwQCVJXNSBA4ZsEjgP9qIWTu/85QrVGq
LrkewSM6Oeh95LGnE+uhJVtIX++O+Hsex3H1UL067dCG99XmDhqbEU9AI6YSZu2p
cjoSowFELtOoG667+id9QObfV3EQoQ==
-----END CERTIFICATE-----

View File

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBkjCB/AIJAPHDh8DU9FfIMA0GCSqGSIb3DQEBBQUAMDQxMjAwBgNVBAoTKWF4
VExTIFByb2plY3QgRG9kZ3kgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTA2MDYw
NzExNDQzMloXDTMzMTAyMzExNDQzMlowLDEWMBQGA1UEChMNYXhUTFMgUHJvamVj
dDESMBAGA1UEAxMJMTI3LjAuMC4xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANAW
9PdXa5u4gWi5VB5p/eQmOtteRq9/54JkiEs8cVNrTQgZsjjU1LGedE3JwBqZ1EIW
HGPjcGg5dVxFjkn7RekCAwEAATANBgkqhkiG9w0BAQUFAAOBgQBmJMt0Crdd/BPn
EdmzsVXou0zTizTC8wyUPMVpg/KzzP7fhZux/ZIrH9/RVcJd9y+B2/mXc3C+K99+
TXQoYKsLGArfDPzmpy1wPrdEcB1A9gkWDl1Uq6xRyvrVm3gX8NTITRuGKL9njgWx
2SrApIBtOOUOinYtfH3745cVVl5HOA==
-----END CERTIFICATE-----

View File

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBkjCB/AIJAPHDh8DU9FfKMA0GCSqGSIb3DQEBBQUAMDQxMjAwBgNVBAoTKWF4
VExTIFByb2plY3QgRG9kZ3kgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTA2MDYw
NzExNDQzMloXDTA1MDYwNzExNDQzMlowLDEWMBQGA1UEChMNYXhUTFMgUHJvamVj
dDESMBAGA1UEAxMJMTI3LjAuMC4xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANE7
MF+pAUI9hm1yvkBuUcFJf1d1oS025cE9DyAa0SNt+nTSPiOwcPygat7sQYiE/lQV
a2HFFmK4k0HxTz3/Lr0CAwEAATANBgkqhkiG9w0BAQUFAAOBgQCmPSs9EceViMZD
ZTXDZpQWJFcXaeInrXWgYWyVgnHBY/eSuqNCxkV/ehv/Wc5pWBGnrX+4cSvQ+TpQ
FdZegeOjvgipjtJb/0TJCcvgcdHTntEM0h7VXjfbsJXAHwJPFzWIKxV4jeFXnaaw
W+YHrj9GQ8PnFmapPuh4h/y6LyHAcg==
-----END CERTIFICATE-----

View File

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBkjCB/AIJAPHDh8DU9FfJMA0GCSqGSIb3DQEBBQUAMDQxMjAwBgNVBAoTKWF4
VExTIFByb2plY3QgRG9kZ3kgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTI0MTIz
MTE0MDAwMFoXDTI1MTIzMTE0MDAwMFowLDEWMBQGA1UEChMNYXhUTFMgUHJvamVj
dDESMBAGA1UEAxMJMTI3LjAuMC4xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANE7
MF+pAUI9hm1yvkBuUcFJf1d1oS025cE9DyAa0SNt+nTSPiOwcPygat7sQYiE/lQV
a2HFFmK4k0HxTz3/Lr0CAwEAATANBgkqhkiG9w0BAQUFAAOBgQApbldYefE8A0ez
SYvAuCtYxx/2KHwBRD/cR0q7widl9WGjVC/dsnbFo109vHEr3FP1HVYSI0aweiaK
XZmpUyJ9DprbbWQqaLuDnqIH8X7kfiMuO7/LGQc812iDJI2Akxp9cIlPBFBD8GVx
+0EphzSodDDlLD8bPqLaWTE+8Ydtjw==
-----END CERTIFICATE-----

Binary file not shown.

View File

@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIBjTCCATcCCQDxw4fA1PRXxjANBgkqhkiG9w0BAQUFADAsMRYwFAYDVQQKEw1h
eFRMUyBQcm9qZWN0MRIwEAYDVQQDEwkxMjcuMC4wLjEwHhcNMDYwNjA3MTE0NDMy
WhcNMzMxMDIzMTE0NDMyWjArMSkwJwYDVQQKEyBheFRMUyBQcm9qZWN0IERldmlj
ZSBDZXJ0aWZpY2F0ZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1CIODRIr
v3YgwJW7Fm0wITCsOIgX9l+aIRiXUzur4RkHRJIQUQYM3ZfftC21QyWPGErVIIcJ
7s7U/iKTQq1LV7USvAp90D/m7s0ntmRj1aBCSG71f0LnSv1rlA8kzUkU7VuEt0Tt
+iqrW0+sYdUBk11dyPLKe6sJnMrJJamVvBsCAwEAATANBgkqhkiG9w0BAQUFAANB
ABC3Uc6uImIpcLl1WYu8K8qkGnVT4K9JkdXHQFbhFZs37lvITrOHQ3j2oGXTbdAx
JFJ3II9xXkm+nc7oLHqhXlc=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB3zCCAUgCCQCdbnM4pjqlWjANBgkqhkiG9w0BAQUFADA0MTIwMAYDVQQKEylh
eFRMUyBQcm9qZWN0IERvZGd5IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0wNjA2
MDcxMTQ0MzJaFw0zMzEwMjMxMTQ0MzJaMDQxMjAwBgNVBAoTKWF4VExTIFByb2pl
Y3QgRG9kZ3kgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA
A4GNADCBiQKBgQCnZdk20fYWh8O6kDTt0AuJWyp0YIrb7W1UNNMPXI5wA4J59IVj
Nmk5wocm9+Hqzbg7rORAN/mHPBhzLAjhnm1HODs36hW15DtbDkkH4wCM/Tsyv79m
n0xq1V6peK3t9vi2D4p/IRjHkYR2jm+BeknopijhY0kHHfpGTHa2DnVirwIDAQAB
MA0GCSqGSIb3DQEBBQUAA4GBAB0LgNo0oCcwIie5plgwwFybQ8x95q6e3wndM/Mp
3gjcAFbGuchpo3dfFlTcRI0KyERb3q1MVxPM4sff9nT7EdHVyK9s8/ITkP2dcTKc
flbcTEfJVIeM8L2P5F41Hvn9GuGcMW8EmsC06gdbp1LLnqsdrXdMNBsAUBXfgPrU
+UcZ
-----END CERTIFICATE-----

Binary file not shown.

BIN
ssl/test/equifax.x509_ca Normal file

Binary file not shown.

2
ssl/test/killopenssl.sh Executable file
View File

@ -0,0 +1,2 @@
#!/bin/sh
ps -ef|grep openssl | /usr/bin/awk '{print $2}' |xargs kill -9

162
ssl/test/make_certs.sh Executable file
View File

@ -0,0 +1,162 @@
#!/bin/sh
#
# Copyright(C) 2006 Cameron Rich
#
# This license is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This license is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this license; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#
# Generate the certificates and keys for testing.
#
PROJECT_NAME="axTLS Project"
# Generate the openssl configuration files.
cat > ca_cert.conf << EOF
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = $PROJECT_NAME Dodgy Certificate Authority
EOF
cat > certs.conf << EOF
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = $PROJECT_NAME
CN = 127.0.0.1
EOF
cat > device_cert.conf << EOF
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = $PROJECT_NAME Device Certificate
EOF
# private key generation
openssl genrsa -out axTLS.ca_key.pem 1024
openssl genrsa -out axTLS.key_512.pem 512
openssl genrsa -out axTLS.key_1024.pem 1024
openssl genrsa -out axTLS.key_2048.pem 2048
openssl genrsa -out axTLS.key_4096.pem 4096
openssl genrsa -out axTLS.device_key.pem 1024
openssl genrsa -aes128 -passout pass:abcd -out axTLS.key_aes128.pem 512
openssl genrsa -aes256 -passout pass:abcd -out axTLS.key_aes256.pem 512
# convert private keys into DER format
openssl rsa -in axTLS.key_512.pem -out axTLS.key_512 -outform DER
openssl rsa -in axTLS.key_1024.pem -out axTLS.key_1024 -outform DER
openssl rsa -in axTLS.key_2048.pem -out axTLS.key_2048 -outform DER
openssl rsa -in axTLS.key_4096.pem -out axTLS.key_4096 -outform DER
openssl rsa -in axTLS.device_key.pem -out axTLS.device_key -outform DER
# cert requests
openssl req -out axTLS.ca_x509.req -key axTLS.ca_key.pem -new \
-config ./ca_cert.conf
openssl req -out axTLS.x509_512.req -key axTLS.key_512.pem -new \
-config ./certs.conf
openssl req -out axTLS.x509_1024.req -key axTLS.key_1024.pem -new \
-config ./certs.conf
openssl req -out axTLS.x509_2048.req -key axTLS.key_2048.pem -new \
-config ./certs.conf
openssl req -out axTLS.x509_4096.req -key axTLS.key_4096.pem -new \
-config ./certs.conf
openssl req -out axTLS.x509_device.req -key axTLS.device_key.pem -new \
-config ./device_cert.conf
openssl req -out axTLS.x509_aes128.req -key axTLS.key_aes128.pem \
-new -config ./certs.conf -passin pass:abcd
openssl req -out axTLS.x509_aes256.req -key axTLS.key_aes256.pem \
-new -config ./certs.conf -passin pass:abcd
# generate the actual certs.
openssl x509 -req -in axTLS.ca_x509.req -out axTLS.ca_x509.pem \
-sha1 -days 10000 -signkey axTLS.ca_key.pem
openssl x509 -req -in axTLS.x509_512.req -out axTLS.x509_512.pem \
-sha1 -CAcreateserial -days 10000 \
-CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
openssl x509 -req -in axTLS.x509_1024.req -out axTLS.x509_1024.pem \
-sha1 -CAcreateserial -days 10000 \
-CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
openssl x509 -req -in axTLS.x509_2048.req -out axTLS.x509_2048.pem \
-md5 -CAcreateserial -days 10000 \
-CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
openssl x509 -req -in axTLS.x509_4096.req -out axTLS.x509_4096.pem \
-md5 -CAcreateserial -days 10000 \
-CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
openssl x509 -req -in axTLS.x509_device.req -out axTLS.x509_device.pem \
-sha1 -CAcreateserial -days 10000 \
-CA axTLS.x509_512.pem -CAkey axTLS.key_512.pem
openssl x509 -req -in axTLS.x509_aes128.req \
-out axTLS.x509_aes128.pem \
-sha1 -CAcreateserial -days 10000 \
-CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
openssl x509 -req -in axTLS.x509_aes256.req \
-out axTLS.x509_aes256.pem \
-sha1 -CAcreateserial -days 10000 \
-CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
# note: must be root to do this
DATE_NOW=`date`
if date -s "Jan 1 2025"; then
openssl x509 -req -in axTLS.x509_512.req -out axTLS.x509_bad_before.pem \
-sha1 -CAcreateserial -days 365 \
-CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
date -s "$DATE_NOW"
touch axTLS.x509_bad_before.pem
fi
openssl x509 -req -in axTLS.x509_512.req -out axTLS.x509_bad_after.pem \
-sha1 -CAcreateserial -days -365 \
-CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
# some cleanup
rm axTLS*.req
rm axTLS.srl
rm *.conf
# need this for the client tests
openssl x509 -in axTLS.ca_x509.pem -outform DER -out axTLS.ca_x509.cer
openssl x509 -in axTLS.x509_512.pem -outform DER -out axTLS.x509_512.cer
openssl x509 -in axTLS.x509_1024.pem -outform DER -out axTLS.x509_1024.cer
openssl x509 -in axTLS.x509_2048.pem -outform DER -out axTLS.x509_2048.cer
openssl x509 -in axTLS.x509_4096.pem -outform DER -out axTLS.x509_4096.cer
openssl x509 -in axTLS.x509_device.pem -outform DER -out axTLS.x509_device.cer
# generate pkcs8 files (use RC4-128 for encryption)
openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -v1 PBE-SHA1-RC4-128 -out axTLS.encrypted_pem.p8
openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -outform DER -v1 PBE-SHA1-RC4-128 -out axTLS.encrypted.p8
openssl pkcs8 -in axTLS.key_512.pem -nocrypt -topk8 -out axTLS.unencrypted_pem.p8
openssl pkcs8 -in axTLS.key_512.pem -nocrypt -topk8 -outform DER -out axTLS.unencrypted.p8
# generate pkcs12 files (use RC4-128 for encryption)
openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem -certfile axTLS.ca_x509.pem -keypbe PBE-SHA1-RC4-128 -certpbe PBE-SHA1-RC4-128 -name "p12_with_CA" -out axTLS.withCA.p12 -password pass:abcd
openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem -keypbe PBE-SHA1-RC4-128 -certpbe PBE-SHA1-RC4-128 -name "p12_without_CA" -out axTLS.withoutCA.p12 -password pass:abcd
openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem -keypbe PBE-SHA1-RC4-128 -certpbe PBE-SHA1-RC4-128 -out axTLS.noname.p12 -password pass:abcd
# PEM certificate chain
cat axTLS.ca_x509.pem >> axTLS.x509_device.pem
# set default key/cert for use in the server
xxd -i axTLS.x509_1024.cer | sed -e \
"s/axTLS_x509_1024_cer/default_certificate/" > ../../ssl/cert.h
xxd -i axTLS.key_1024 | sed -e \
"s/axTLS_key_1024/default_private_key/" > ../../ssl/private_key.h

BIN
ssl/test/microsoft.x509_ca Normal file

Binary file not shown.

View File

@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIEEjCCAvqgAwIBAgIPAMEAizw8iBHRPvZj7N9AMA0GCSqGSIb3DQEBBAUAMHAx
KzApBgNVBAsTIkNvcHlyaWdodCAoYykgMTk5NyBNaWNyb3NvZnQgQ29ycC4xHjAc
BgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEhMB8GA1UEAxMYTWljcm9zb2Z0
IFJvb3QgQXV0aG9yaXR5MB4XDTk3MDExMDA3MDAwMFoXDTIwMTIzMTA3MDAwMFow
cDErMCkGA1UECxMiQ29weXJpZ2h0IChjKSAxOTk3IE1pY3Jvc29mdCBDb3JwLjEe
MBwGA1UECxMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSEwHwYDVQQDExhNaWNyb3Nv
ZnQgUm9vdCBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
AQCpAr3BcOY78k4bKJ+XeF4w6qKpjSVf+P6VTKO3/p2iID58UaKboo9gMmvRQmR5
7qx2yVTa8uuchhyPn4Rms8VremIj1h083g8BkuiWxL8tZpqaaCaZ0Dosvwy1WCbB
RucKPjiWLKkoOajsSYNC44QPu5psVWGsgnyhYC13TOmZtGQ7mlAcMQgkFJ+p55Er
GOY9mGMUYFgFZZ8dN1KH96fvlALGG9O/VUWziYC/OuxUlE6u/ad6bXROrxjMlgko
IQBXkGBpN7tLEgc8Vv9b+6RmCgim0oFWV++2O14WgXcE2va+roCV/rDNf9anGnJc
PMq88AijIjCzBoXJsyB3E4XfAgMBAAGjgagwgaUwgaIGA1UdAQSBmjCBl4AQW9Bw
72lyniNRfhSyTY7/y6FyMHAxKzApBgNVBAsTIkNvcHlyaWdodCAoYykgMTk5NyBN
aWNyb3NvZnQgQ29ycC4xHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEh
MB8GA1UEAxMYTWljcm9zb2Z0IFJvb3QgQXV0aG9yaXR5gg8AwQCLPDyIEdE+9mPs
30AwDQYJKoZIhvcNAQEEBQADggEBAJXoC8CN85cYNe24ASTYdxHzXGAyn54Lyz4F
kYiPyTrmIfLwV5MstaBHyGLv/NfMOztaqTZUaf4kbT/JzKreBXzdMY09nxBwarv+
Ek8YacD80EPjEVogT+pie6+qGcgrNyUtvmWhEoolD2Oj91Qc+SHJ1hXzUqxuQzIH
/YIX+OVnbA1R9r3xUse958Qw/CAxCYgdlSkaTdUdAqXxgOADtFv0sd3IV+5lScdS
VLa0AygS/5DW8AiPfriXxas3LOR65Kh343agANBqP8HSNorgQRKoNWobats14dQc
BOSoRQTIWjM4bk0cDWK3CqKM09VUP0bNHFWmcNsSOoeTdZ+n0qA=
-----END CERTIFICATE-----

216
ssl/test/perf_bigint.c Normal file
View File

@ -0,0 +1,216 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This license is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this license; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* Some performance testing of bigint.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ssl.h"
/**************************************************************************
* BIGINT tests
*
**************************************************************************/
int main(int argc, char *argv[])
{
#ifdef CONFIG_SSL_CERT_VERIFICATION
RSA_CTX *rsa_ctx;
BI_CTX *ctx;
bigint *bi_data, *bi_res;
int diff, res = 1;
struct timeval tv_old, tv_new;
const char *plaintext;
uint8_t compare[MAX_KEY_BYTE_SIZE];
int i, max_biggie = 10; /* really crank performance */
int len;
uint8_t *buf;
/**
* 512 bit key
*/
plaintext = /* 64 byte number */
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^";
len = get_file("../ssl/test/axTLS.key_512", &buf);
asn1_get_private_key(buf, len, &rsa_ctx);
ctx = rsa_ctx->bi_ctx;
bi_data = bi_import(ctx, (uint8_t *)plaintext, strlen(plaintext));
bi_res = RSA_public(rsa_ctx, bi_data);
bi_data = bi_res; /* reuse again */
gettimeofday(&tv_old, NULL);
for (i = 0; i < max_biggie; i++)
{
bi_res = RSA_private(rsa_ctx, bi_copy(bi_data));
if (i < max_biggie-1)
{
bi_free(ctx, bi_res);
}
}
gettimeofday(&tv_new, NULL);
bi_free(ctx, bi_data);
diff = (tv_new.tv_sec-tv_old.tv_sec)*1000 +
(tv_new.tv_usec-tv_old.tv_usec)/1000;
printf("512 bit decrypt time: %dms\n", diff/max_biggie);
TTY_FLUSH();
bi_export(ctx, bi_res, compare, 64);
RSA_free(rsa_ctx);
free(buf);
if (memcmp(plaintext, compare, 64) != 0)
goto end;
/**
* 1024 bit key
*/
plaintext = /* 128 byte number */
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^";
len = get_file("../ssl/test/axTLS.key_1024", &buf);
asn1_get_private_key(buf, len, &rsa_ctx);
ctx = rsa_ctx->bi_ctx;
bi_data = bi_import(ctx, (uint8_t *)plaintext, strlen(plaintext));
bi_res = RSA_public(rsa_ctx, bi_data);
bi_data = bi_res; /* reuse again */
gettimeofday(&tv_old, NULL);
for (i = 0; i < max_biggie; i++)
{
bi_res = RSA_private(rsa_ctx, bi_copy(bi_data));
if (i < max_biggie-1)
{
bi_free(ctx, bi_res);
}
}
gettimeofday(&tv_new, NULL);
bi_free(ctx, bi_data);
diff = (tv_new.tv_sec-tv_old.tv_sec)*1000 +
(tv_new.tv_usec-tv_old.tv_usec)/1000;
printf("1024 bit decrypt time: %dms\n", diff/max_biggie);
TTY_FLUSH();
bi_export(ctx, bi_res, compare, 128);
RSA_free(rsa_ctx);
free(buf);
if (memcmp(plaintext, compare, 128) != 0)
goto end;
/**
* 2048 bit key
*/
plaintext = /* 256 byte number */
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^";
len = get_file("../ssl/test/axTLS.key_2048", &buf);
asn1_get_private_key(buf, len, &rsa_ctx);
ctx = rsa_ctx->bi_ctx;
bi_data = bi_import(ctx, (uint8_t *)plaintext, strlen(plaintext));
bi_res = RSA_public(rsa_ctx, bi_data);
bi_data = bi_res; /* reuse again */
gettimeofday(&tv_old, NULL);
for (i = 0; i < max_biggie; i++)
{
bi_res = RSA_private(rsa_ctx, bi_copy(bi_data));
if (i < max_biggie-1)
{
bi_free(ctx, bi_res);
}
}
gettimeofday(&tv_new, NULL);
bi_free(ctx, bi_data);
diff = (tv_new.tv_sec-tv_old.tv_sec)*1000 +
(tv_new.tv_usec-tv_old.tv_usec)/1000;
printf("2048 bit decrypt time: %dms\n", diff/max_biggie);
TTY_FLUSH();
bi_export(ctx, bi_res, compare, 256);
RSA_free(rsa_ctx);
free(buf);
if (memcmp(plaintext, compare, 256) != 0)
goto end;
/**
* 4096 bit key
*/
plaintext = /* 512 byte number */
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^";
len = get_file("../ssl/test/axTLS.key_4096", &buf);
asn1_get_private_key(buf, len, &rsa_ctx);
ctx = rsa_ctx->bi_ctx;
bi_data = bi_import(ctx, (uint8_t *)plaintext, strlen(plaintext));
gettimeofday(&tv_old, NULL);
bi_res = RSA_public(rsa_ctx, bi_data);
gettimeofday(&tv_new, NULL);
diff = (tv_new.tv_sec-tv_old.tv_sec)*1000 +
(tv_new.tv_usec-tv_old.tv_usec)/1000;
printf("4096 bit encrypt time: %dms\n", diff);
TTY_FLUSH();
bi_data = bi_res; /* reuse again */
gettimeofday(&tv_old, NULL);
for (i = 0; i < max_biggie; i++)
{
bi_res = RSA_private(rsa_ctx, bi_copy(bi_data));
if (i < max_biggie-1)
{
bi_free(ctx, bi_res);
}
}
gettimeofday(&tv_new, NULL);
bi_free(ctx, bi_data);
diff = (tv_new.tv_sec-tv_old.tv_sec)*1000 +
(tv_new.tv_usec-tv_old.tv_usec)/1000;
printf("4096 bit decrypt time: %dms\n", diff/max_biggie);
TTY_FLUSH();
bi_export(ctx, bi_res, compare, 512);
RSA_free(rsa_ctx);
free(buf);
if (memcmp(plaintext, compare, 512) != 0)
goto end;
/* done */
printf("Bigint performance testing complete\n");
res = 0;
end:
return res;
#else
return 0;
#endif
}

1813
ssl/test/ssltest.c Normal file

File diff suppressed because it is too large Load Diff

136
ssl/test/test_axssl.sh Executable file
View File

@ -0,0 +1,136 @@
#!/bin/sh
#
# Copyright(C) 2006 Cameron Rich
#
# This license is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This license is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this license; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#
# Test the various axssl bindings. To run it, got to the _install directory
# and run this script from there.
#
if grep "CONFIG_PLATFORM_WIN32=y" "../config/.config" > /dev/null; then
JAVA_BIN="/cygdrive/c/Program Files/Java/jdk1.5.0_06/bin"
PERL_BIN="/cygdrive/c/Perl/bin/perl"
KILL_AXSSL="kill %1"
KILL_CSHARP="kill %1"
KILL_PERL="kill %1"
KILL_JAVA="kill %1"
else
if grep "CONFIG_PLATFORM_CYGWIN=y" "../config/.config" > /dev/null; then
# no .net or java on cygwin
PERL_BIN=/usr/bin/perl
KILL_AXSSL="killall axssl"
KILL_PERL="killall /usr/bin/perl"
else # Linux
JAVA_BIN=/usr/lib/java/bin
PERL_BIN=/usr/bin/perl
KILL_AXSSL="killall axssl"
KILL_CSHARP="killall mono"
KILL_PERL="killall /usr/bin/perl"
RUN_CSHARP="mono"
KILL_JAVA="killall $JAVA_BIN/java"
fi
fi
BASE=..
SERVER_ARGS="s_server -accept 15001 -verify -CAfile $BASE/ssl/test/axTLS.ca_x509.cer"
CLIENT_ARGS="s_client -reconnect -connect localhost:15001 -verify -CAfile $BASE/ssl/test/axTLS.ca_x509.cer -key $BASE/ssl/test/axTLS.key_1024 -cert $BASE/ssl/test/axTLS.x509_1024.cer"
# check pem arguments
SERVER_PEM_ARGS="s_server -accept 15001 -pass abcd -key $BASE/ssl/test/axTLS.key_aes128.pem -cert $BASE/ssl/test/axTLS.x509_aes128.pem"
CLIENT_PEM_ARGS="s_client -connect localhost:15001 -CAfile $BASE/ssl/test/axTLS.ca_x509.pem -key $BASE/ssl/test/axTLS.key_1024.pem -cert $BASE/ssl/test/axTLS.x509_1024.pem"
export LD_LIBRARY_PATH=.:`perl -e 'use Config; print $Config{archlib};'`/CORE
if [ -x ./axssl ]; then
echo "############################# C SAMPLE ###########################"
./axssl $SERVER_ARGS &
echo "C Test passed" | ./axssl $CLIENT_ARGS
$KILL_AXSSL
sleep 1
./axssl $SERVER_PEM_ARGS &
echo "C Test passed" | ./axssl $CLIENT_PEM_ARGS
$KILL_AXSSL
sleep 2
echo "### C tests complete"
fi
if [ -f ./axtls.jar ]; then
echo "########################## JAVA SAMPLE ###########################"
"$JAVA_BIN/java" -jar ./axtls.jar $SERVER_ARGS &
echo "Java Test passed" | "$JAVA_BIN/java" -jar ./axtls.jar $CLIENT_ARGS
$KILL_JAVA
sleep 1
"$JAVA_BIN/java" -jar ./axtls.jar $SERVER_PEM_ARGS &
echo "Java Test passed" | "$JAVA_BIN/java" -jar ./axtls.jar $CLIENT_PEM_ARGS
$KILL_JAVA
sleep 1
echo "### Java tests complete"
fi
if [ -x ./axssl.csharp.exe ]; then
echo "############################ C# SAMPLE ###########################"
$RUN_CSHARP ./axssl.csharp.exe $SERVER_ARGS &
echo "C# Test passed" | $RUN_CSHARP ./axssl.csharp.exe $CLIENT_ARGS
sleep 1
$KILL_CSHARP
sleep 1
$RUN_CSHARP ./axssl.csharp.exe $SERVER_PEM_ARGS &
echo "C# Test passed" | $RUN_CSHARP ./axssl.csharp.exe $CLIENT_PEM_ARGS
sleep 1
$KILL_CSHARP
sleep 1
echo "### C# tests complete"
fi
if [ -x ./axssl.vbnet.exe ]; then
echo "######################## VB.NET SAMPLE ###########################"
./axssl.vbnet $SERVER_ARGS &
sleep 1
echo "VB.NET Test passed" | ./axssl.vbnet.exe $CLIENT_ARGS
kill %1
sleep 1
./axssl.vbnet $SERVER_PEM_ARGS &
sleep 1
echo "VB.NET Test passed" | ./axssl.vbnet.exe $CLIENT_PEM_ARGS
kill %1
sleep 1
echo "### VB.NET tests complete"
fi
if [ -f ./axssl.pl ]; then
echo "########################## PERL SAMPLE ###########################"
"$PERL_BIN" ./axssl.pl $SERVER_ARGS &
echo "Perl Test passed" | "$PERL_BIN" ./axssl.pl $CLIENT_ARGS
$KILL_PERL
sleep 1
"$PERL_BIN" ./axssl.pl $SERVER_PEM_ARGS &
echo "Perl Test passed" | "$PERL_BIN" ./axssl.pl $CLIENT_PEM_ARGS
$KILL_PERL
sleep 1
echo "### Perl tests complete"
fi
echo "########################## ALL TESTS COMPLETE ###########################"

BIN
ssl/test/thawte.x509_ca Normal file

Binary file not shown.

BIN
ssl/test/verisign.x509_ca Normal file

Binary file not shown.

View File

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICmDCCAgECECCol67bggLewTagTia9h3MwDQYJKoZIhvcNAQECBQAwgYwxCzAJ
BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEwMC4GA1UECxMnRm9y
IFRlc3QgUHVycG9zZXMgT25seS4gIE5vIGFzc3VyYW5jZXMuMTIwMAYDVQQDEylW
ZXJpU2lnbiBUcmlhbCBTZWN1cmUgU2VydmVyIFRlc3QgUm9vdCBDQTAeFw0wNTAy
MDkwMDAwMDBaFw0yNTAyMDgyMzU5NTlaMIGMMQswCQYDVQQGEwJVUzEXMBUGA1UE
ChMOVmVyaVNpZ24sIEluYy4xMDAuBgNVBAsTJ0ZvciBUZXN0IFB1cnBvc2VzIE9u
bHkuICBObyBhc3N1cmFuY2VzLjEyMDAGA1UEAxMpVmVyaVNpZ24gVHJpYWwgU2Vj
dXJlIFNlcnZlciBUZXN0IFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
AoGBAJ8h98U7klaZH5cEn6CSEKmGWVBsTwHIaMAAVqGqCUn7Q9C10sEOIHBznyLy
eSDjMs5M1nC/iAA7KCASf/yHz0AdlU+1IRSijwHTF/2dYSoTTxP2GCmtL1Ga4i7+
zDDo086V7+NiFAGJj+CYey47ue4Xa33o/4YOA9PGL87oqFe7AgMBAAEwDQYJKoZI
hvcNAQECBQADgYEAOq447rP5EDqFEl3vhLhgTbnyaskNYwPvxk+0grnQyDA4sF/q
gK8nFlnvLmAOF3DmfuqW6WSr4zqTYzpwmJlsn48Om/yWirL8GuWRftit2POxTfHS
B8VmR+PZx2k24UgWUZyojDGxJtiHd3tjCdqFgTit4NK429cWOcZrh47xeOI=
-----END CERTIFICATE-----

Binary file not shown.

View File

@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIEQzCCA6ygAwIBAgIQR/dXCzC/x5Ta5RvL6hKEojANBgkqhkiG9w0BAQUFADCB
jDELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTAwLgYDVQQL
EydGb3IgVGVzdCBQdXJwb3NlcyBPbmx5LiAgTm8gYXNzdXJhbmNlcy4xMjAwBgNV
BAMTKVZlcmlTaWduIFRyaWFsIFNlY3VyZSBTZXJ2ZXIgVGVzdCBSb290IENBMB4X
DTA2MDExNjAwMDAwMFoXDTA2MDEzMDIzNTk1OVowgbkxCzAJBgNVBAYTAkFVMQww
CgYDVQQIEwNRbGQxETAPBgNVBAcUCEJyaXNiYW5lMRkwFwYDVQQKFBBheG9sb1RM
UyBQcm9qZWN0MRUwEwYDVQQLFAwxMDI0IGJpdCBrZXkxOjA4BgNVBAsUMVRlcm1z
IG9mIHVzZSBhdCB3d3cudmVyaXNpZ24uY29tL2Nwcy90ZXN0Y2EgKGMpMDUxGzAZ
BgNVBAMUEnd3dy5heG9sb3Rscy5jby5ucjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
gYkCgYEAttzj5S7qfOZIrh9xg8bgjTOKbSIbLBuMnxAwfGRcUrQO2EQOHd6kMjXR
hqY/cG2IG4G8AeqdV3nHlKbrbHbRa1lFgP6b0BQCE8TyxmP+tIAqn5L6/HTm+EEi
Ad1Pxjeok6e7F6UXHxJltSGHmOhAf3C5kPq/FQ6QZeG4yD/uzPkCAwEAAaOCAXUw
ggFxMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgWgMEcGA1UdHwRAMD4wPKA6oDiGNmh0
dHA6Ly9TVlJTZWN1cmUtY3JsLnZlcmlzaWduLmNvbS9TVlJUcmlhbFJvb3QyMDA1
LmNybDBKBgNVHSAEQzBBMD8GCmCGSAGG+EUBBxUwMTAvBggrBgEFBQcCARYjaHR0
cHM6Ly93d3cudmVyaXNpZ24uY29tL2Nwcy90ZXN0Y2EwHQYDVR0lBBYwFAYIKwYB
BQUHAwEGCCsGAQUFBwMCMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0
cDovL29jc3AudmVyaXNpZ24uY29tMG0GCCsGAQUFBwEMBGEwX6FdoFswWTBXMFUW
CWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgsexkuMCUW
I2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMA0GCSqGSIb3DQEB
BQUAA4GBACtlCTJFENCcHCQLHJfiotqr2XR+oWu0MstNm8dG6WB+zYprrT+kOPDn
1rMO7YLx76f67fC+lIXz720kQHk6LsZ8hPBQvIXnfIsKjng73DeFzBmTMFz6Qxjd
+E0FUCKplqrdwUkmR4kH6O4pdGE4AlXJNiUI2903yYdSRVMOuLuR
-----END CERTIFICATE-----

2045
ssl/tls1.c Executable file

File diff suppressed because it is too large Load Diff

288
ssl/tls1.h Executable file
View File

@ -0,0 +1,288 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* @file tls1.h
*
* @brief The definitions for the TLS library.
*/
#ifndef HEADER_SSL_LIB_H
#define HEADER_SSL_LIB_H
#ifdef __cplusplus
extern "C" {
#endif
#include "version.h"
/* Mutexing definitions */
#if defined(CONFIG_SSL_CTX_MUTEXING)
#if defined(WIN32)
#define SSL_CTX_MUTEX_TYPE HANDLE
#define SSL_CTX_MUTEX_INIT(A) A=CreateMutex(0, FALSE, 0)
#define SSL_CTX_MUTEX_DESTROY(A) CloseHandle(A)
#define SSL_CTX_LOCK(A) WaitForSingleObject(A, INFINITE)
#define SSL_CTX_UNLOCK(A) ReleaseMutex(A)
#else
#include <pthread.h>
#define SSL_CTX_MUTEX_TYPE pthread_mutex_t
#define SSL_CTX_MUTEX_INIT(A) pthread_mutex_init(&A, NULL)
#define SSL_CTX_MUTEX_DESTROY(A) pthread_mutex_destroy(&A)
#define SSL_CTX_LOCK(A) pthread_mutex_lock(&A)
#define SSL_CTX_UNLOCK(A) pthread_mutex_unlock(&A)
#endif
#else /* no mutexing */
#define SSL_CTX_MUTEX_INIT(A)
#define SSL_CTX_MUTEX_DESTROY(A)
#define SSL_CTX_LOCK(A)
#define SSL_CTX_UNLOCK(A)
#endif
#define SSL_RANDOM_SIZE 32
#define SSL_SECRET_SIZE 48
#define SSL_FINISHED_HASH_SIZE 12
#define SSL_RECORD_SIZE 5
#define SSL_SERVER_READ 0
#define SSL_SERVER_WRITE 1
#define SSL_CLIENT_READ 2
#define SSL_CLIENT_WRITE 3
#define SSL_HS_HDR_SIZE 4
/* the flags we use while establishing a connection */
#define SSL_NEED_RECORD 0x0001
#define SSL_TX_ENCRYPTED 0x0002
#define SSL_RX_ENCRYPTED 0x0004
#define SSL_SESSION_RESUME 0x0008
#define SSL_IS_CLIENT 0x0010
#define SSL_HAS_CERT_REQ 0x0020
/* some macros to muck around with flag bits */
#define SET_SSL_FLAG(A) (ssl->flag |= A)
#define CLR_SSL_FLAG(A) (ssl->flag &= ~A)
#define IS_SET_SSL_FLAG(A) (ssl->flag & A)
#define MAX_KEY_BYTE_SIZE 512 /* for a 4096 bit key */
#define RT_MAX_PLAIN_LENGTH 16384
#define RT_EXTRA 1024
#define BM_RECORD_OFFSET 5
#ifdef CONFIG_SSL_SKELETON_MODE
#define NUM_PROTOCOLS 1
#else
#define NUM_PROTOCOLS 4
#endif
#define PARANOIA_CHECK(A, B) if (A < B) { \
ret = SSL_ERROR_INVALID_HANDSHAKE; goto error; }
/* protocol types */
enum
{
PT_CHANGE_CIPHER_SPEC = 20,
PT_ALERT_PROTOCOL,
PT_HANDSHAKE_PROTOCOL,
PT_APP_PROTOCOL_DATA
};
/* handshaking types */
enum
{
HS_HELLO_REQUEST,
HS_CLIENT_HELLO,
HS_SERVER_HELLO,
HS_CERTIFICATE = 11,
HS_SERVER_KEY_XCHG,
HS_CERT_REQ,
HS_SERVER_HELLO_DONE,
HS_CERT_VERIFY,
HS_CLIENT_KEY_XCHG,
HS_FINISHED = 20
};
typedef struct
{
uint8_t cipher;
uint8_t key_size;
uint8_t iv_size;
uint8_t key_block_size;
uint8_t padding_size;
uint8_t digest_size;
hmac_func hmac;
crypt_func encrypt;
crypt_func decrypt;
} cipher_info_t;
struct _SSLObjLoader
{
uint8_t *buf;
int len;
};
typedef struct _SSLObjLoader SSLObjLoader;
typedef struct
{
time_t conn_time;
uint8_t session_id[SSL_SESSION_ID_SIZE];
uint8_t master_secret[SSL_SECRET_SIZE];
} SSL_SESS;
typedef struct
{
uint8_t *buf;
int size;
} SSL_CERT;
struct _SSL
{
uint32_t flag;
uint16_t need_bytes;
uint16_t got_bytes;
uint8_t record_type;
uint8_t chain_length;
uint8_t cipher;
int16_t next_state;
int16_t hs_status;
uint8_t *all_pkts;
int all_pkts_len;
int client_fd;
const cipher_info_t *cipher_info;
uint8_t *final_finish_mac;
uint8_t *key_block;
void *encrypt_ctx;
void *decrypt_ctx;
uint8_t bm_all_data[RT_MAX_PLAIN_LENGTH+RT_EXTRA];
uint8_t *bm_data;
int bm_index;
struct _SSL *next; /* doubly linked list */
struct _SSL *prev;
SSL_CERT *certs;
struct _SSL_CTX *ssl_ctx; /* back reference to a clnt/svr ctx */
#ifndef CONFIG_SSL_SKELETON_MODE
uint16_t session_index;
SSL_SESS *session;
#endif
#ifdef CONFIG_SSL_CERT_VERIFICATION
X509_CTX *x509_ctx;
#endif
uint8_t session_id[SSL_SESSION_ID_SIZE];
uint8_t client_mac[SHA1_SIZE]; /* for HMAC verification */
uint8_t server_mac[SHA1_SIZE]; /* for HMAC verification */
uint8_t client_random[SSL_RANDOM_SIZE]; /* client's random sequence */
uint8_t server_random[SSL_RANDOM_SIZE]; /* server's random sequence */
uint8_t *master_secret;
uint8_t read_sequence[8]; /* 64 bit sequence number */
uint8_t write_sequence[8]; /* 64 bit sequence number */
uint8_t record_buf[SSL_RECORD_SIZE]; /* storage for hmac calls later */
};
typedef struct _SSL SSL;
struct _SSL_CTX
{
uint32_t options;
uint8_t chain_length;
RSA_CTX *rsa_ctx;
#ifdef CONFIG_SSL_CERT_VERIFICATION
CA_CERT_CTX *ca_cert_ctx;
#endif
SSL *head;
SSL *tail;
SSL_CERT certs[CONFIG_SSL_MAX_CERTS];
#ifndef CONFIG_SSL_SKELETON_MODE
uint16_t num_sessions;
SSL_SESS **ssl_sessions;
#endif
#ifdef CONFIG_SSL_CTX_MUTEXING
SSL_CTX_MUTEX_TYPE mutex;
#endif
#ifdef CONFIG_OPENSSL_COMPATIBLE
void *bonus_attr;
#endif
};
typedef struct _SSL_CTX SSL_CTX;
/* backwards compatibility */
typedef struct _SSL_CTX SSLCTX;
extern const uint8_t ssl_prot_prefs[NUM_PROTOCOLS];
SSL *ssl_new(SSL_CTX *ssl_ctx, int client_fd);
int send_packet(SSL *ssl, uint8_t protocol,
const uint8_t *in, int length);
int do_svr_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len);
int do_clnt_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len);
int process_finished(SSL *ssl, int hs_len);
int process_sslv23_client_hello(SSL *ssl);
int send_alert(SSL *ssl, int error_code);
int send_finished(SSL *ssl);
int send_certificate(SSL *ssl);
int basic_read(SSL *ssl, uint8_t **in_data);
int send_change_cipher_spec(SSL *ssl);
void finished_digest(SSL *ssl, const char *label, uint8_t *digest);
void generate_master_secret(SSL *ssl, const uint8_t *premaster_secret);
void add_packet(SSL *ssl, const uint8_t *pkt, int len);
int add_cert(SSL_CTX *ssl_ctx, const uint8_t *buf, int len);
int add_private_key(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj);
void ssl_obj_free(SSLObjLoader *ssl_obj);
int pkcs8_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password);
int pkcs12_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password);
#ifdef CONFIG_SSL_CERT_VERIFICATION
int add_cert_auth(SSL_CTX *ssl_ctx, const uint8_t *buf, int len);
void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx);
#endif
#ifdef CONFIG_SSL_ENABLE_CLIENT
int do_client_connect(SSL *ssl);
#endif
#ifdef CONFIG_SSL_FULL_MODE
void DISPLAY_STATE(SSL *ssl, int is_send, uint8_t state, int not_ok);
void DISPLAY_BYTES(SSL *ssl, const char *format,
const uint8_t *data, int size, ...);
void DISPLAY_CERT(SSL *ssl, const char *label, const X509_CTX *x509_ctx);
void DISPLAY_RSA(SSL *ssl, const char *label, const RSA_CTX *rsa_ctx);
void DISPLAY_ALERT(SSL *ssl, int alert);
#else
#define DISPLAY_STATE(A,B,C,D)
#define DISPLAY_CERT(A,B,C)
#define DISPLAY_RSA(A,B,C)
#define DISPLAY_ALERT(A, B)
#ifdef WIN32
void DISPLAY_BYTES(SSL *ssl, const char *format,/* win32 has no variadic macros */
const uint8_t *data, int size, ...);
#else
#define DISPLAY_BYTES(A,B,C,D,...)
#endif
#endif
#ifdef CONFIG_SSL_CERT_VERIFICATION
int process_certificate(SSL *ssl, X509_CTX **x509_ctx);
#endif
SSL_SESS *ssl_session_update(int max_sessions,
SSL_SESS *ssl_sessions[], SSL *ssl,
const uint8_t *session_id);
void kill_ssl_session(SSL_SESS **ssl_sessions, SSL *ssl);
#ifdef __cplusplus
}
#endif
#endif

338
ssl/tls1_clnt.c Normal file
View File

@ -0,0 +1,338 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdio.h>
#include "ssl.h"
#ifdef CONFIG_SSL_ENABLE_CLIENT /* all commented out if no client */
static int send_client_hello(SSL *ssl);
static int process_server_hello(SSL *ssl);
static int process_server_hello_done(SSL *ssl);
static int send_client_key_xchg(SSL *ssl);
static int process_cert_req(SSL *ssl);
static int send_cert_verify(SSL *ssl);
/*
* Establish a new SSL connection to an SSL server.
*/
EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const uint8_t *session_id)
{
int ret;
SSL *ssl = ssl_new(ssl_ctx, client_fd);
if (session_id && ssl_ctx->num_sessions)
{
memcpy(ssl->session_id, session_id, SSL_SESSION_ID_SIZE);
SET_SSL_FLAG(SSL_SESSION_RESUME); /* just flag for later */
}
SET_SSL_FLAG(SSL_IS_CLIENT);
ret = do_client_connect(ssl);
return ssl;
}
/*
* Process the handshake record.
*/
int do_clnt_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len)
{
int ret = SSL_OK;
/* To get here the state must be valid */
switch (handshake_type)
{
case HS_SERVER_HELLO:
ret = process_server_hello(ssl);
break;
case HS_CERTIFICATE:
ret = process_certificate(ssl, &ssl->x509_ctx);
break;
case HS_SERVER_HELLO_DONE:
if ((ret = process_server_hello_done(ssl)) == SSL_OK)
{
if (IS_SET_SSL_FLAG(SSL_HAS_CERT_REQ))
{
if ((ret = send_certificate(ssl)) == SSL_OK &&
(ret = send_client_key_xchg(ssl)) == SSL_OK)
{
ret = send_cert_verify(ssl);
}
}
else
{
ret = send_client_key_xchg(ssl);
}
if (ret == SSL_OK &&
(ret = send_change_cipher_spec(ssl)) == SSL_OK)
{
ret = send_finished(ssl);
}
}
break;
case HS_CERT_REQ:
ret = process_cert_req(ssl);
break;
case HS_FINISHED:
ret = process_finished(ssl, hs_len);
break;
case HS_HELLO_REQUEST:
ret = do_client_connect(ssl);
break;
}
return ret;
}
/*
* Do the handshaking from the beginning.
*/
int do_client_connect(SSL *ssl)
{
int ret = SSL_OK;
send_client_hello(ssl); /* send the client hello */
ssl->bm_index = 0;
ssl->next_state = HS_SERVER_HELLO;
ssl->hs_status = SSL_NOT_OK; /* not connected */
/* sit in a loop until it all looks good */
while (ssl->hs_status != SSL_OK)
{
ret = basic_read(ssl, NULL);
if (ret < SSL_OK)
{
if (ret != SSL_ERROR_CONN_LOST)
{
/* let the server know we are dying and why */
if (send_alert(ssl, ret))
{
/* something nasty happened, so get rid of it */
kill_ssl_session(ssl->ssl_ctx->ssl_sessions, ssl);
}
}
break;
}
}
ssl->hs_status = ret; /* connected? */
return ret;
}
/*
* Send the initial client hello.
*/
static int send_client_hello(SSL *ssl)
{
uint8_t *buf = ssl->bm_data;
time_t tm = time(NULL);
uint8_t *tm_ptr = &buf[6]; /* time will go here */
int i, offset;
buf[0] = HS_CLIENT_HELLO;
buf[1] = 0;
buf[2] = 0;
/* byte 3 is calculated later */
buf[4] = 0x03;
buf[5] = 0x01;
/* client random value - spec says that 1st 4 bytes are big endian time */
*tm_ptr++ = (uint8_t)(((long)tm & 0xff000000) >> 24);
*tm_ptr++ = (uint8_t)(((long)tm & 0x00ff0000) >> 16);
*tm_ptr++ = (uint8_t)(((long)tm & 0x0000ff00) >> 8);
*tm_ptr++ = (uint8_t)(((long)tm & 0x000000ff));
get_random(SSL_RANDOM_SIZE-4, &buf[10]);
memcpy(ssl->client_random, &buf[6], SSL_RANDOM_SIZE);
offset = 6 + SSL_RANDOM_SIZE;
/* give session resumption a go */
if (IS_SET_SSL_FLAG(SSL_SESSION_RESUME)) /* set initially bu user */
{
buf[offset++] = SSL_SESSION_ID_SIZE;
memcpy(&buf[offset], ssl->session_id, SSL_SESSION_ID_SIZE);
offset += SSL_SESSION_ID_SIZE;
CLR_SSL_FLAG(SSL_SESSION_RESUME); /* clear so we can set later */
}
else
{
/* no session id - because no session resumption just yet */
buf[offset++] = 0;
}
buf[offset++] = 0; /* number of ciphers */
buf[offset++] = NUM_PROTOCOLS*2;/* number of ciphers */
/* put all our supported protocols in our request */
for (i = 0; i < NUM_PROTOCOLS; i++)
{
buf[offset++] = 0; /* cipher we are using */
buf[offset++] = ssl_prot_prefs[i];
}
buf[offset++] = 1; /* no compression */
buf[offset++] = 0;
buf[3] = offset - 4; /* handshake size */
return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
}
/*
* Process the server hello.
*/
static int process_server_hello(SSL *ssl)
{
uint8_t *buf = ssl->bm_data;
int pkt_size = ssl->bm_index;
int offset;
int version = (buf[4] << 4) + buf[5];
int num_sessions = ssl->ssl_ctx->num_sessions;
int ret = SSL_OK;
/* check that we are talking to a TLSv1 server */
if (version != 0x31)
return SSL_ERROR_INVALID_VERSION;
/* get the server random value */
memcpy(ssl->server_random, &buf[6], SSL_RANDOM_SIZE);
offset = 7 + SSL_RANDOM_SIZE; /* skip of session id size */
if (num_sessions)
{
ssl->session = ssl_session_update(num_sessions,
ssl->ssl_ctx->ssl_sessions, ssl, &buf[offset]);
memcpy(ssl->session->session_id, &buf[offset], SSL_SESSION_ID_SIZE);
}
memcpy(ssl->session_id, &buf[offset], SSL_SESSION_ID_SIZE);
offset += SSL_SESSION_ID_SIZE;
/* get the real cipher we are using */
ssl->cipher = buf[++offset];
ssl->next_state = IS_SET_SSL_FLAG(SSL_SESSION_RESUME) ?
HS_FINISHED : HS_CERTIFICATE;
PARANOIA_CHECK(pkt_size, offset);
error:
return ret;
}
/**
* Process the server hello done message.
*/
static int process_server_hello_done(SSL *ssl)
{
ssl->next_state = HS_FINISHED;
return SSL_OK;
}
/*
* Send a client key exchange message.
*/
static int send_client_key_xchg(SSL *ssl)
{
uint8_t *buf = ssl->bm_data;
uint8_t premaster_secret[SSL_SECRET_SIZE];
int enc_secret_size = -1;
buf[0] = HS_CLIENT_KEY_XCHG;
buf[1] = 0;
premaster_secret[0] = 0x03; /* encode the version number */
premaster_secret[1] = 0x01;
get_random(SSL_SECRET_SIZE-2, &premaster_secret[2]);
DISPLAY_RSA(ssl, "send_client_key_xchg", ssl->x509_ctx->rsa_ctx);
/* rsa_ctx->bi_ctx is not thread-safe */
SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
enc_secret_size = RSA_encrypt(ssl->x509_ctx->rsa_ctx, premaster_secret,
SSL_SECRET_SIZE, &buf[6], 0);
SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
buf[2] = (enc_secret_size + 2) >> 8;
buf[3] = (enc_secret_size + 2) & 0xff;
buf[4] = enc_secret_size >> 8;
buf[5] = enc_secret_size & 0xff;
generate_master_secret(ssl, premaster_secret);
return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, enc_secret_size+6);
}
/*
* Process the certificate request.
*/
static int process_cert_req(SSL *ssl)
{
/* don't do any processing - we will send back an RSA certificate anyway */
ssl->next_state = HS_SERVER_HELLO_DONE;
SET_SSL_FLAG(SSL_HAS_CERT_REQ);
return SSL_OK;
}
/*
* Send a certificate verify message.
*/
static int send_cert_verify(SSL *ssl)
{
uint8_t *buf = ssl->bm_data;
uint8_t dgst[MD5_SIZE+SHA1_SIZE];
RSA_CTX *rsa_ctx = ssl->ssl_ctx->rsa_ctx;
int n, ret;
DISPLAY_RSA(ssl, "send_cert_verify", rsa_ctx);
buf[0] = HS_CERT_VERIFY;
buf[1] = 0;
finished_digest(ssl, NULL, dgst); /* calculate the digest */
/* rsa_ctx->bi_ctx is not thread-safe */
SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
n = RSA_encrypt(rsa_ctx, dgst, sizeof(dgst), &buf[6], 1);
SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
if (n == 0)
{
ret = SSL_ERROR_INVALID_KEY;
goto error;
}
buf[4] = n >> 8; /* add the RSA size (not officially documented) */
buf[5] = n & 0xff;
n += 2;
buf[2] = n >> 8;
buf[3] = n & 0xff;
ret = send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, n+4);
error:
return ret;
}
#endif /* CONFIG_SSL_ENABLE_CLIENT */

450
ssl/tls1_svr.c Normal file
View File

@ -0,0 +1,450 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "ssl.h"
static const uint8_t g_hello_done[] = { HS_SERVER_HELLO_DONE, 0, 0, 0 };
static int process_client_hello(SSL *ssl);
static int send_server_hello_sequence(SSL *ssl);
static int send_server_hello(SSL *ssl);
static int send_server_hello_done(SSL *ssl);
static int process_client_key_xchg(SSL *ssl);
#ifdef CONFIG_SSL_CERT_VERIFICATION
static int send_certificate_request(SSL *ssl);
static int process_cert_verify(SSL *ssl);
#endif
/*
* Establish a new SSL connection to an SSL client.
*/
EXP_FUNC SSL * STDCALL ssl_server_new(SSL_CTX *ssl_ctx, int client_fd)
{
SSL *ssl = ssl_new(ssl_ctx, client_fd);
ssl->next_state = HS_CLIENT_HELLO;
#ifdef CONFIG_SSL_FULL_MODE
if (ssl_ctx->chain_length == 0)
printf("Warning - no server certificate defined\n"); TTY_FLUSH();
#endif
return ssl;
}
/*
* Process the handshake record.
*/
int do_svr_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len)
{
int ret = SSL_OK;
ssl->hs_status = SSL_NOT_OK; /* not connected */
/* To get here the state must be valid */
switch (handshake_type)
{
case HS_CLIENT_HELLO:
if ((ret = process_client_hello(ssl)) == SSL_OK)
ret = send_server_hello_sequence(ssl);
break;
#ifdef CONFIG_SSL_CERT_VERIFICATION
case HS_CERTIFICATE:/* the client sends its cert */
ret = process_certificate(ssl, &ssl->x509_ctx);
if (ret == SSL_OK) /* verify the cert */
{
int cert_res;
cert_res = x509_verify(
ssl->ssl_ctx->ca_cert_ctx, ssl->x509_ctx);
ret = (cert_res == 0) ? SSL_OK : SSL_X509_ERROR(cert_res);
}
break;
case HS_CERT_VERIFY:
ret = process_cert_verify(ssl);
add_packet(ssl, buf, hs_len); /* needs to be done after */
break;
#endif
case HS_CLIENT_KEY_XCHG:
ret = process_client_key_xchg(ssl);
break;
case HS_FINISHED:
ret = process_finished(ssl, hs_len);
break;
}
return ret;
}
/*
* Process a client hello message.
*/
static int process_client_hello(SSL *ssl)
{
uint8_t *buf = ssl->bm_data;
uint8_t *record_buf = ssl->record_buf;
int pkt_size = ssl->bm_index;
int i, j, cs_len, id_len, offset = 6 + SSL_RANDOM_SIZE;
int version = (record_buf[1] << 4) + record_buf[2];
int ret = SSL_OK;
/* should be v3.1 (TLSv1) or better - we'll send in v3.1 mode anyway */
if (version < 0x31)
{
ret = SSL_ERROR_INVALID_VERSION;
ssl_display_error(ret);
goto error;
}
memcpy(ssl->client_random, &buf[6], SSL_RANDOM_SIZE);
/* process the session id */
id_len = buf[offset++];
if (id_len > SSL_SESSION_ID_SIZE)
{
return SSL_ERROR_INVALID_SESSION;
}
#ifndef CONFIG_SSL_SKELETON_MODE
ssl->session = ssl_session_update(ssl->ssl_ctx->num_sessions,
ssl->ssl_ctx->ssl_sessions, ssl, id_len ? &buf[offset] : NULL);
#endif
offset += id_len;
cs_len = (buf[offset]<<8) + buf[offset+1];
offset += 3; /* add 1 due to all cipher suites being 8 bit */
PARANOIA_CHECK(pkt_size, offset);
/* work out what cipher suite we are going to use */
for (j = 0; j < NUM_PROTOCOLS; j++)
{
for (i = 0; i < cs_len; i += 2)
{
if (ssl_prot_prefs[j] == buf[offset+i]) /* got a match? */
{
ssl->cipher = ssl_prot_prefs[j];
goto do_state;
}
}
}
/* ouch! protocol is not supported */
ret = SSL_ERROR_NO_CIPHER;
do_state:
error:
return ret;
}
#ifdef CONFIG_SSL_ENABLE_V23_HANDSHAKE
/*
* Some browsers use a hybrid SSLv2 "client hello"
*/
int process_sslv23_client_hello(SSL *ssl)
{
uint8_t *buf = ssl->bm_data;
int bytes_needed = ((buf[0] & 0x7f) << 8) + buf[1];
int version = (buf[3] << 4) + buf[4];
int ret = SSL_OK;
/* we have already read 3 extra bytes so far */
int read_len = SOCKET_READ(ssl->client_fd, buf, bytes_needed-3);
int cs_len = buf[1];
int id_len = buf[3];
int ch_len = buf[5];
int i, j, offset = 8; /* start at first cipher */
int random_offset = 0;
DISPLAY_BYTES(ssl, "received %d bytes", buf, read_len, read_len);
/* should be v3.1 (TLSv1) or better - we'll send in v3.1 mode anyway */
if (version < 0x31)
{
return SSL_ERROR_INVALID_VERSION;
}
add_packet(ssl, buf, read_len);
/* connection has gone, so die */
if (bytes_needed < 0)
{
return SSL_ERROR_CONN_LOST;
}
/* now work out what cipher suite we are going to use */
for (j = 0; j < NUM_PROTOCOLS; j++)
{
for (i = 0; i < cs_len; i += 3)
{
if (ssl_prot_prefs[j] == buf[offset+i])
{
ssl->cipher = ssl_prot_prefs[j];
goto server_hello;
}
}
}
/* ouch! protocol is not supported */
ret = SSL_ERROR_NO_CIPHER;
goto error;
server_hello:
/* get the session id */
offset += cs_len - 2; /* we've gone 2 bytes past the end */
#ifndef CONFIG_SSL_SKELETON_MODE
ssl->session = ssl_session_update(ssl->ssl_ctx->num_sessions,
ssl->ssl_ctx->ssl_sessions, ssl, id_len ? &buf[offset] : NULL);
#endif
/* get the client random data */
offset += id_len;
/* random can be anywhere between 16 and 32 bytes long - so it is padded
* with 0's to the left */
if (ch_len == 0x10)
{
random_offset += 0x10;
}
memcpy(&ssl->client_random[random_offset], &buf[offset], ch_len);
ret = send_server_hello_sequence(ssl);
error:
return ret;
}
#endif
/*
* Send the entire server hello sequence
*/
static int send_server_hello_sequence(SSL *ssl)
{
int ret;
if ((ret = send_server_hello(ssl)) == SSL_OK)
{
#ifndef CONFIG_SSL_SKELETON_MODE
/* resume handshake? */
if (IS_SET_SSL_FLAG(SSL_SESSION_RESUME))
{
if ((ret = send_change_cipher_spec(ssl)) == SSL_OK)
{
ret = send_finished(ssl);
ssl->next_state = HS_FINISHED;
}
}
else
#endif
if ((ret = send_certificate(ssl)) == SSL_OK)
{
#ifdef CONFIG_SSL_CERT_VERIFICATION
/* ask the client for its certificate */
if (IS_SET_SSL_FLAG(SSL_CLIENT_AUTHENTICATION))
{
if ((ret = send_certificate_request(ssl)) == SSL_OK)
{
ret = send_server_hello_done(ssl);
ssl->next_state = HS_CERTIFICATE;
}
}
else
#endif
{
ret = send_server_hello_done(ssl);
ssl->next_state = HS_CLIENT_KEY_XCHG;
}
}
}
return ret;
}
/*
* Send a server hello message.
*/
static int send_server_hello(SSL *ssl)
{
uint8_t *buf = ssl->bm_data;
int offset = 0;
buf[0] = HS_SERVER_HELLO;
buf[1] = 0;
buf[2] = 0;
/* byte 3 is calculated later */
buf[4] = 0x03;
buf[5] = 0x01;
/* server random value */
get_random(SSL_RANDOM_SIZE, &buf[6]);
memcpy(ssl->server_random, &buf[6], SSL_RANDOM_SIZE);
offset = 6 + SSL_RANDOM_SIZE;
/* send a session id - and put it into the cache */
buf[offset++] = SSL_SESSION_ID_SIZE;
#ifndef CONFIG_SSL_SKELETON_MODE
if (IS_SET_SSL_FLAG(SSL_SESSION_RESUME))
{
/* retrieve id from session cache */
memcpy(&buf[offset], ssl->session->session_id,
SSL_SESSION_ID_SIZE);
memcpy(ssl->session_id, ssl->session->session_id, SSL_SESSION_ID_SIZE);
}
else /* generate our own session id */
#endif
{
get_random(SSL_SESSION_ID_SIZE, &buf[offset]);
memcpy(ssl->session_id, &buf[offset], SSL_SESSION_ID_SIZE);
#ifndef CONFIG_SSL_SKELETON_MODE
/* store id in session cache */
if (ssl->ssl_ctx->num_sessions)
{
memcpy(ssl->session->session_id,
ssl->session_id, SSL_SESSION_ID_SIZE);
}
#endif
}
offset += SSL_SESSION_ID_SIZE;
buf[offset++] = 0; /* cipher we are using */
buf[offset++] = ssl->cipher;
buf[offset++] = 0; /* no compression */
buf[3] = offset - 4; /* handshake size */
return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
}
/*
* Send the server hello done message.
*/
static int send_server_hello_done(SSL *ssl)
{
return send_packet(ssl, PT_HANDSHAKE_PROTOCOL,
g_hello_done, sizeof(g_hello_done));
}
/*
* Pull apart a client key exchange message. Decrypt the pre-master key (using
* our RSA private key) and then work out the master key. Initialise the
* ciphers.
*/
static int process_client_key_xchg(SSL *ssl)
{
uint8_t *buf = ssl->bm_data;
int pkt_size = ssl->bm_index;
int premaster_size, secret_length = (buf[2] << 8) + buf[3];
uint8_t premaster_secret[MAX_KEY_BYTE_SIZE];
RSA_CTX *rsa_ctx = ssl->ssl_ctx->rsa_ctx;
int offset = 4;
int ret = SSL_OK;
DISPLAY_RSA(ssl, "process_client_key_xchg", rsa_ctx);
/* is there an extra size field? */
if ((secret_length - 2) == rsa_ctx->num_octets)
offset += 2;
PARANOIA_CHECK(pkt_size, rsa_ctx->num_octets+offset);
/* rsa_ctx->bi_ctx is not thread-safe */
SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
premaster_size = RSA_decrypt(rsa_ctx, &buf[offset], premaster_secret, 1);
SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
if (premaster_size != SSL_SECRET_SIZE ||
premaster_secret[0] != 0x03 || /* check version is 3.1 (TLS) */
premaster_secret[1] != 0x01)
{
/* guard against a Bleichenbacher attack */
memset(premaster_secret, 0, SSL_SECRET_SIZE);
/* and continue - will die eventually when checking the mac */
}
#if 0
print_blob("pre-master", premaster_secret, SSL_SECRET_SIZE);
#endif
generate_master_secret(ssl, premaster_secret);
#ifdef CONFIG_SSL_CERT_VERIFICATION
ssl->next_state = IS_SET_SSL_FLAG(SSL_CLIENT_AUTHENTICATION) ?
HS_CERT_VERIFY : HS_FINISHED;
#else
ssl->next_state = HS_FINISHED;
#endif
error:
return ret;
}
#ifdef CONFIG_SSL_CERT_VERIFICATION
static const uint8_t g_cert_request[] = { HS_CERT_REQ, 0, 0, 4, 1, 0, 0, 0 };
/*
* Send the certificate request message.
*/
static int send_certificate_request(SSL *ssl)
{
return send_packet(ssl, PT_HANDSHAKE_PROTOCOL,
g_cert_request, sizeof(g_cert_request));
}
/*
* Ensure the client has the private key by first decrypting the packet and
* then checking the packet digests.
*/
static int process_cert_verify(SSL *ssl)
{
uint8_t *buf = ssl->bm_data;
int pkt_size = ssl->bm_index;
uint8_t dgst_buf[MAX_KEY_BYTE_SIZE];
uint8_t dgst[MD5_SIZE+SHA1_SIZE];
X509_CTX *x509_ctx = ssl->x509_ctx;
int ret = SSL_OK;
int n;
PARANOIA_CHECK(pkt_size, x509_ctx->rsa_ctx->num_octets+6);
DISPLAY_RSA(ssl, "process_cert_verify", x509_ctx->rsa_ctx);
n = RSA_decrypt(x509_ctx->rsa_ctx, &buf[6], dgst_buf, 0);
if (n != SHA1_SIZE + MD5_SIZE)
{
ret = SSL_ERROR_INVALID_KEY;
goto end_cert_vfy;
}
finished_digest(ssl, NULL, dgst); /* calculate the digest */
if (memcmp(dgst_buf, dgst, MD5_SIZE + SHA1_SIZE))
{
ret = SSL_ERROR_INVALID_KEY;
}
end_cert_vfy:
ssl->next_state = HS_FINISHED;
error:
return ret;
}
#endif