aboutsummaryrefslogtreecommitdiff
path: root/circuitpython/lib/axtls/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'circuitpython/lib/axtls/crypto')
-rw-r--r--circuitpython/lib/axtls/crypto/Makefile52
-rw-r--r--circuitpython/lib/axtls/crypto/aes.c453
-rw-r--r--circuitpython/lib/axtls/crypto/bigint.c1516
-rw-r--r--circuitpython/lib/axtls/crypto/bigint.h99
-rw-r--r--circuitpython/lib/axtls/crypto/bigint_impl.h131
-rw-r--r--circuitpython/lib/axtls/crypto/crypto.h275
-rw-r--r--circuitpython/lib/axtls/crypto/crypto_misc.c390
-rw-r--r--circuitpython/lib/axtls/crypto/hmac.c145
-rw-r--r--circuitpython/lib/axtls/crypto/md5.c433
-rw-r--r--circuitpython/lib/axtls/crypto/os_int.h67
-rw-r--r--circuitpython/lib/axtls/crypto/rc4.c97
-rw-r--r--circuitpython/lib/axtls/crypto/rsa.c284
-rw-r--r--circuitpython/lib/axtls/crypto/sha1.c249
-rw-r--r--circuitpython/lib/axtls/crypto/sha256.c278
-rw-r--r--circuitpython/lib/axtls/crypto/sha384.c77
-rw-r--r--circuitpython/lib/axtls/crypto/sha512.c220
16 files changed, 4766 insertions, 0 deletions
diff --git a/circuitpython/lib/axtls/crypto/Makefile b/circuitpython/lib/axtls/crypto/Makefile
new file mode 100644
index 0000000..126ae78
--- /dev/null
+++ b/circuitpython/lib/axtls/crypto/Makefile
@@ -0,0 +1,52 @@
+#
+# Copyright (c) 2007, Cameron Rich
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the axTLS project nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+include ../config/.config
+include ../config/makefile.conf
+
+AXTLS_HOME=..
+
+OBJ=\
+ aes.o \
+ bigint.o \
+ crypto_misc.o \
+ hmac.o \
+ md5.o \
+ rc4.o \
+ rsa.o \
+ sha1.o \
+ sha256.o \
+ sha384.o \
+ sha512.o
+
+include ../config/makefile.post
+
+all: $(OBJ)
+
diff --git a/circuitpython/lib/axtls/crypto/aes.c b/circuitpython/lib/axtls/crypto/aes.c
new file mode 100644
index 0000000..c260a2a
--- /dev/null
+++ b/circuitpython/lib/axtls/crypto/aes.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright (c) 2007-2016, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * 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 "os_port.h"
+#include "crypto.h"
+
+#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 ----- */
+
+/* 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&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 */
+ if (iv)
+ {
+ 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
+ */
+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
+ */
+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);
+ }
+}
diff --git a/circuitpython/lib/axtls/crypto/bigint.c b/circuitpython/lib/axtls/crypto/bigint.c
new file mode 100644
index 0000000..9c16428
--- /dev/null
+++ b/circuitpython/lib/axtls/crypto/bigint.c
@@ -0,0 +1,1516 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @defgroup bigint_api Big Integer API
+ * @brief The bigint implementation as used by the axTLS project.
+ *
+ * The bigint library is for RSA encryption/decryption as well as signing.
+ * This code tries to minimise use of malloc/free by maintaining a small
+ * cache. A bigint context may maintain state by being made "permanent".
+ * It be be later released with a bi_depermanent() and bi_free() call.
+ *
+ * It supports the following reduction techniques:
+ * - Classical
+ * - Barrett
+ * - Montgomery
+ *
+ * It also implements the following:
+ * - Karatsuba multiplication
+ * - Squaring
+ * - Sliding window exponentiation
+ * - Chinese Remainder Theorem (implemented in rsa.c).
+ *
+ * All the algorithms used are pretty standard, and designed for different
+ * data bus sizes. Negative numbers are not dealt with at all, so a subtraction
+ * may need to be tested for negativity.
+ *
+ * This library steals some ideas from Jef Poskanzer
+ * <http://cs.marlboro.edu/term/cs-fall02/algorithms/crypto/RSA/bigint>
+ * and GMP <http://www.swox.com/gmp>. It gets most of its implementation
+ * detail from "The Handbook of Applied Cryptography"
+ * <http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf>
+ * @{
+ */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+#include "os_port.h"
+#include "bigint.h"
+
+#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 */
+
+static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bi, comp i);
+static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom);
+static bigint *alloc(BI_CTX *ctx, int size);
+static bigint *trim(bigint *bi);
+static void more_comps(bigint *bi, int n);
+#if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \
+ defined(CONFIG_BIGINT_MONTGOMERY)
+static bigint *comp_right_shift(bigint *biR, int num_shifts);
+static bigint *comp_left_shift(bigint *biR, int num_shifts);
+#endif
+
+#ifdef CONFIG_BIGINT_CHECK_ON
+static void check(const bigint *bi);
+#else
+#define check(A) /**< disappears in normal production mode */
+#endif
+
+
+/**
+ * @brief Start a new bigint context.
+ * @return A bigint context.
+ */
+BI_CTX *bi_initialize(void)
+{
+ /* calloc() sets everything to zero */
+ BI_CTX *ctx = (BI_CTX *)calloc(1, sizeof(BI_CTX));
+
+ /* the radix */
+ ctx->bi_radix = alloc(ctx, 2);
+ ctx->bi_radix->comps[0] = 0;
+ ctx->bi_radix->comps[1] = 1;
+ bi_permanent(ctx->bi_radix);
+ return ctx;
+}
+
+/**
+ * @brief Close the bigint context and free any resources.
+ *
+ * Free up any used memory - a check is done if all objects were not
+ * properly freed.
+ * @param ctx [in] The bigint session context.
+ */
+void bi_terminate(BI_CTX *ctx)
+{
+ bi_depermanent(ctx->bi_radix);
+ bi_free(ctx, ctx->bi_radix);
+
+ if (ctx->active_count != 0)
+ {
+#ifdef CONFIG_SSL_FULL_MODE
+ printf("bi_terminate: there were %d un-freed bigints\n",
+ ctx->active_count);
+#endif
+ abort();
+ }
+
+ bi_clear_cache(ctx);
+ free(ctx);
+}
+
+/**
+ *@brief Clear the memory cache.
+ */
+void bi_clear_cache(BI_CTX *ctx)
+{
+ bigint *p, *pn;
+
+ if (ctx->free_list == NULL)
+ return;
+
+ for (p = ctx->free_list; p != NULL; p = pn)
+ {
+ pn = p->next;
+ free(p->comps);
+ free(p);
+ }
+
+ ctx->free_count = 0;
+ ctx->free_list = NULL;
+}
+
+/**
+ * @brief Increment the number of references to this object.
+ * It does not do a full copy.
+ * @param bi [in] The bigint to copy.
+ * @return A reference to the same bigint.
+ */
+bigint *bi_copy(bigint *bi)
+{
+ check(bi);
+ if (bi->refs != PERMANENT)
+ bi->refs++;
+ return bi;
+}
+
+/**
+ * @brief Simply make a bigint object "unfreeable" if bi_free() is called on it.
+ *
+ * For this object to be freed, bi_depermanent() must be called.
+ * @param bi [in] The bigint to be made permanent.
+ */
+void bi_permanent(bigint *bi)
+{
+ check(bi);
+ if (bi->refs != 1)
+ {
+#ifdef CONFIG_SSL_FULL_MODE
+ printf("bi_permanent: refs was not 1\n");
+#endif
+ abort();
+ }
+
+ bi->refs = PERMANENT;
+}
+
+/**
+ * @brief Take a permanent object and make it eligible for freedom.
+ * @param bi [in] The bigint to be made back to temporary.
+ */
+void bi_depermanent(bigint *bi)
+{
+ check(bi);
+ if (bi->refs != PERMANENT)
+ {
+#ifdef CONFIG_SSL_FULL_MODE
+ printf("bi_depermanent: bigint was not permanent\n");
+#endif
+ abort();
+ }
+
+ bi->refs = 1;
+}
+
+/**
+ * @brief Free a bigint object so it can be used again.
+ *
+ * The memory itself it not actually freed, just tagged as being available
+ * @param ctx [in] The bigint session context.
+ * @param bi [in] The bigint to be freed.
+ */
+void bi_free(BI_CTX *ctx, bigint *bi)
+{
+ check(bi);
+ if (bi->refs == PERMANENT)
+ {
+ return;
+ }
+
+ if (--bi->refs > 0)
+ {
+ return;
+ }
+
+ bi->next = ctx->free_list;
+ ctx->free_list = bi;
+ ctx->free_count++;
+
+ if (--ctx->active_count < 0)
+ {
+#ifdef CONFIG_SSL_FULL_MODE
+ printf("bi_free: active_count went negative "
+ "- double-freed bigint?\n");
+#endif
+ abort();
+ }
+}
+
+/**
+ * @brief Convert an (unsigned) integer into a bigint.
+ * @param ctx [in] The bigint session context.
+ * @param i [in] The (unsigned) integer to be converted.
+ *
+ */
+bigint *int_to_bi(BI_CTX *ctx, comp i)
+{
+ bigint *biR = alloc(ctx, 1);
+ biR->comps[0] = i;
+ return biR;
+}
+
+/**
+ * @brief Do a full copy of the bigint object.
+ * @param ctx [in] The bigint session context.
+ * @param bi [in] The bigint object to be copied.
+ */
+bigint *bi_clone(BI_CTX *ctx, const bigint *bi)
+{
+ bigint *biR = alloc(ctx, bi->size);
+ check(bi);
+ memcpy(biR->comps, bi->comps, bi->size*COMP_BYTE_SIZE);
+ return biR;
+}
+
+/**
+ * @brief Perform an addition operation between two bigints.
+ * @param ctx [in] The bigint session context.
+ * @param bia [in] A bigint.
+ * @param bib [in] Another bigint.
+ * @return The result of the addition.
+ */
+bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib)
+{
+ int n;
+ comp carry = 0;
+ comp *pa, *pb;
+
+ check(bia);
+ check(bib);
+
+ n = max(bia->size, bib->size);
+ more_comps(bia, n+1);
+ more_comps(bib, n);
+ pa = bia->comps;
+ pb = bib->comps;
+
+ do
+ {
+ comp sl, rl, cy1;
+ sl = *pa + *pb++;
+ rl = sl + carry;
+ cy1 = sl < *pa;
+ carry = cy1 | (rl < sl);
+ *pa++ = rl;
+ } while (--n != 0);
+
+ *pa = carry; /* do overflow */
+ bi_free(ctx, bib);
+ return trim(bia);
+}
+
+/**
+ * @brief Perform a subtraction operation between two bigints.
+ * @param ctx [in] The bigint session context.
+ * @param bia [in] A bigint.
+ * @param bib [in] Another bigint.
+ * @param is_negative [out] If defined, indicates that the result was negative.
+ * is_negative may be null.
+ * @return The result of the subtraction. The result is always positive.
+ */
+bigint *bi_subtract(BI_CTX *ctx,
+ bigint *bia, bigint *bib, int *is_negative)
+{
+ int n = bia->size;
+ comp *pa, *pb, carry = 0;
+
+ check(bia);
+ check(bib);
+
+ more_comps(bib, n);
+ pa = bia->comps;
+ pb = bib->comps;
+
+ do
+ {
+ comp sl, rl, cy1;
+ sl = *pa - *pb++;
+ rl = sl - carry;
+ cy1 = sl > *pa;
+ carry = cy1 | (rl > sl);
+ *pa++ = rl;
+ } while (--n != 0);
+
+ if (is_negative) /* indicate a negative result */
+ {
+ *is_negative = carry;
+ }
+
+ bi_free(ctx, trim(bib)); /* put bib back to the way it was */
+ return trim(bia);
+}
+
+/**
+ * Perform a multiply between a bigint an an (unsigned) integer
+ */
+static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bia, comp b)
+{
+ int j = 0, n = bia->size;
+ bigint *biR = alloc(ctx, n + 1);
+ comp carry = 0;
+ comp *r = biR->comps;
+ comp *a = bia->comps;
+
+ check(bia);
+
+ /* clear things to start with */
+ memset(r, 0, ((n+1)*COMP_BYTE_SIZE));
+
+ do
+ {
+ long_comp tmp = *r + (long_comp)a[j]*b + carry;
+ *r++ = (comp)tmp; /* downsize */
+ carry = (comp)(tmp >> COMP_BIT_SIZE);
+ } while (++j < n);
+
+ *r = carry;
+ bi_free(ctx, bia);
+ return trim(biR);
+}
+
+/**
+ * @brief Does both division and modulo calculations.
+ *
+ * Used extensively when doing classical reduction.
+ * @param ctx [in] The bigint session context.
+ * @param u [in] A bigint which is the numerator.
+ * @param v [in] Either the denominator or the modulus depending on the mode.
+ * @param is_mod [n] Determines if this is a normal division (0) or a reduction
+ * (1).
+ * @return The result of the division/reduction.
+ */
+bigint *bi_divide(BI_CTX *ctx, bigint *u, bigint *v, int is_mod)
+{
+ int n = v->size, m = u->size-n;
+ int j = 0, orig_u_size = u->size;
+ uint8_t mod_offset = ctx->mod_offset;
+ comp d;
+ bigint *quotient, *tmp_u;
+ comp q_dash;
+
+ check(u);
+ check(v);
+
+ /* if doing reduction and we are < mod, then return mod */
+ if (is_mod && bi_compare(v, u) > 0)
+ {
+ bi_free(ctx, v);
+ return u;
+ }
+
+ quotient = alloc(ctx, m+1);
+ tmp_u = alloc(ctx, n+1);
+ v = trim(v); /* make sure we have no leading 0's */
+ d = (comp)((long_comp)COMP_RADIX/(V1+1));
+
+ /* clear things to start with */
+ memset(quotient->comps, 0, ((quotient->size)*COMP_BYTE_SIZE));
+
+ /* normalise */
+ if (d > 1)
+ {
+ u = bi_int_multiply(ctx, u, d);
+
+ if (is_mod)
+ {
+ v = ctx->bi_normalised_mod[mod_offset];
+ }
+ else
+ {
+ v = bi_int_multiply(ctx, v, d);
+ }
+ }
+
+ if (orig_u_size == u->size) /* new digit position u0 */
+ {
+ more_comps(u, orig_u_size + 1);
+ }
+
+ do
+ {
+ /* get a temporary short version of u */
+ memcpy(tmp_u->comps, &u->comps[u->size-n-1-j], (n+1)*COMP_BYTE_SIZE);
+
+ /* calculate q' */
+ if (U(0) == V1)
+ {
+ q_dash = COMP_RADIX-1;
+ }
+ else
+ {
+ q_dash = (comp)(((long_comp)U(0)*COMP_RADIX + U(1))/V1);
+
+ if (v->size > 1 && V2)
+ {
+ /* we are implementing the following:
+ if (V2*q_dash > (((U(0)*COMP_RADIX + U(1) -
+ q_dash*V1)*COMP_RADIX) + U(2))) ... */
+ comp inner = (comp)((long_comp)COMP_RADIX*U(0) + U(1) -
+ (long_comp)q_dash*V1);
+ if ((long_comp)V2*q_dash > (long_comp)inner*COMP_RADIX + U(2))
+ {
+ q_dash--;
+ }
+ }
+ }
+
+ /* multiply and subtract */
+ if (q_dash)
+ {
+ int is_negative;
+ tmp_u = bi_subtract(ctx, tmp_u,
+ bi_int_multiply(ctx, bi_copy(v), q_dash), &is_negative);
+ more_comps(tmp_u, n+1);
+
+ Q(j) = q_dash;
+
+ /* add back */
+ if (is_negative)
+ {
+ Q(j)--;
+ tmp_u = bi_add(ctx, tmp_u, bi_copy(v));
+
+ /* lop off the carry */
+ tmp_u->size--;
+ v->size--;
+ }
+ }
+ else
+ {
+ Q(j) = 0;
+ }
+
+ /* copy back to u */
+ memcpy(&u->comps[u->size-n-1-j], tmp_u->comps, (n+1)*COMP_BYTE_SIZE);
+ } while (++j <= m);
+
+ bi_free(ctx, tmp_u);
+ bi_free(ctx, v);
+
+ if (is_mod) /* get the remainder */
+ {
+ bi_free(ctx, quotient);
+ return bi_int_divide(ctx, trim(u), d);
+ }
+ else /* get the quotient */
+ {
+ bi_free(ctx, u);
+ return trim(quotient);
+ }
+}
+
+/*
+ * Perform an integer divide on a bigint.
+ */
+static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom)
+{
+ int i = biR->size - 1;
+ long_comp r = 0;
+
+ check(biR);
+
+ do
+ {
+ r = (r<<COMP_BIT_SIZE) + biR->comps[i];
+ biR->comps[i] = (comp)(r / denom);
+ r %= denom;
+ } while (--i >= 0);
+
+ return trim(biR);
+}
+
+#ifdef CONFIG_BIGINT_MONTGOMERY
+/**
+ * There is a need for the value of integer N' such that B^-1(B-1)-N^-1N'=1,
+ * where B^-1(B-1) mod N=1. Actually, only the least significant part of
+ * N' is needed, hence the definition N0'=N' mod b. We reproduce below the
+ * simple algorithm from an article by Dusse and Kaliski to efficiently
+ * find N0' from N0 and b */
+static comp modular_inverse(bigint *bim)
+{
+ int i;
+ comp t = 1;
+ comp two_2_i_minus_1 = 2; /* 2^(i-1) */
+ long_comp two_2_i = 4; /* 2^i */
+ comp N = bim->comps[0];
+
+ for (i = 2; i <= COMP_BIT_SIZE; i++)
+ {
+ if ((long_comp)N*t%two_2_i >= two_2_i_minus_1)
+ {
+ t += two_2_i_minus_1;
+ }
+
+ two_2_i_minus_1 <<= 1;
+ two_2_i <<= 1;
+ }
+
+ return (comp)(COMP_RADIX-t);
+}
+#endif
+
+#if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \
+ defined(CONFIG_BIGINT_MONTGOMERY)
+/**
+ * Take each component and shift down (in terms of components)
+ */
+static bigint *comp_right_shift(bigint *biR, int num_shifts)
+{
+ int i = biR->size-num_shifts;
+ comp *x = biR->comps;
+ comp *y = &biR->comps[num_shifts];
+
+ check(biR);
+
+ if (i <= 0) /* have we completely right shifted? */
+ {
+ biR->comps[0] = 0; /* return 0 */
+ biR->size = 1;
+ return biR;
+ }
+
+ do
+ {
+ *x++ = *y++;
+ } while (--i > 0);
+
+ biR->size -= num_shifts;
+ return biR;
+}
+
+/**
+ * Take each component and shift it up (in terms of components)
+ */
+static bigint *comp_left_shift(bigint *biR, int num_shifts)
+{
+ int i = biR->size-1;
+ comp *x, *y;
+
+ check(biR);
+
+ if (num_shifts <= 0)
+ {
+ return biR;
+ }
+
+ more_comps(biR, biR->size + num_shifts);
+
+ x = &biR->comps[i+num_shifts];
+ y = &biR->comps[i];
+
+ do
+ {
+ *x-- = *y--;
+ } while (i--);
+
+ memset(biR->comps, 0, num_shifts*COMP_BYTE_SIZE); /* zero LS comps */
+ return biR;
+}
+#endif
+
+/**
+ * @brief Allow a binary sequence to be imported as a bigint.
+ * @param ctx [in] The bigint session context.
+ * @param data [in] The data to be converted.
+ * @param size [in] The number of bytes of data.
+ * @return A bigint representing this data.
+ */
+bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int size)
+{
+ bigint *biR = alloc(ctx, (size+COMP_BYTE_SIZE-1)/COMP_BYTE_SIZE);
+ int i, j = 0, offset = 0;
+
+ memset(biR->comps, 0, biR->size*COMP_BYTE_SIZE);
+
+ for (i = size-1; i >= 0; i--)
+ {
+ biR->comps[offset] += (unsigned int)data[i] << (j*8);
+
+ if (++j == COMP_BYTE_SIZE)
+ {
+ j = 0;
+ offset ++;
+ }
+ }
+
+ return trim(biR);
+}
+
+#ifdef CONFIG_SSL_FULL_MODE
+/**
+ * @brief The testharness uses this code to import text hex-streams and
+ * convert them into bigints.
+ * @param ctx [in] The bigint session context.
+ * @param data [in] A string consisting of hex characters. The characters must
+ * be in upper case.
+ * @return A bigint representing this data.
+ */
+bigint *bi_str_import(BI_CTX *ctx, const char *data)
+{
+ int size = strlen(data);
+ bigint *biR = alloc(ctx, (size+COMP_NUM_NIBBLES-1)/COMP_NUM_NIBBLES);
+ int i, j = 0, offset = 0;
+ memset(biR->comps, 0, biR->size*COMP_BYTE_SIZE);
+
+ for (i = size-1; i >= 0; i--)
+ {
+ int num = (data[i] <= '9') ? (data[i] - '0') : (data[i] - 'A' + 10);
+ biR->comps[offset] += num << (j*4);
+
+ if (++j == COMP_NUM_NIBBLES)
+ {
+ j = 0;
+ offset ++;
+ }
+ }
+
+ return biR;
+}
+
+void bi_print(const char *label, bigint *x)
+{
+ int i, j;
+
+ if (x == NULL)
+ {
+ printf("%s: (null)\n", label);
+ return;
+ }
+
+ printf("%s: (size %d)\n", label, x->size);
+ for (i = x->size-1; i >= 0; i--)
+ {
+ for (j = COMP_NUM_NIBBLES-1; j >= 0; j--)
+ {
+ comp mask = 0x0f << (j*4);
+ comp num = (x->comps[i] & mask) >> (j*4);
+ putc((num <= 9) ? (num + '0') : (num + 'A' - 10), stdout);
+ }
+ }
+
+ printf("\n");
+}
+#endif
+
+/**
+ * @brief Take a bigint and convert it into a byte sequence.
+ *
+ * This is useful after a decrypt operation.
+ * @param ctx [in] The bigint session context.
+ * @param x [in] The bigint to be converted.
+ * @param data [out] The converted data as a byte stream.
+ * @param size [in] The maximum size of the byte stream. Unused bytes will be
+ * zeroed.
+ */
+void bi_export(BI_CTX *ctx, bigint *x, uint8_t *data, int size)
+{
+ int i, j, k = size-1;
+
+ check(x);
+ memset(data, 0, size); /* ensure all leading 0's are cleared */
+
+ for (i = 0; i < x->size; i++)
+ {
+ for (j = 0; j < COMP_BYTE_SIZE; j++)
+ {
+ comp mask = 0xff << (j*8);
+ int num = (x->comps[i] & mask) >> (j*8);
+ data[k--] = num;
+
+ if (k < 0)
+ {
+ goto buf_done;
+ }
+ }
+ }
+buf_done:
+
+ bi_free(ctx, x);
+}
+
+/**
+ * @brief Pre-calculate some of the expensive steps in reduction.
+ *
+ * This function should only be called once (normally when a session starts).
+ * When the session is over, bi_free_mod() should be called. bi_mod_power()
+ * relies on this function being called.
+ * @param ctx [in] The bigint session context.
+ * @param bim [in] The bigint modulus that will be used.
+ * @param mod_offset [in] There are three moduluii that can be stored - the
+ * standard modulus, and its two primes p and q. This offset refers to which
+ * modulus we are referring to.
+ * @see bi_free_mod(), bi_mod_power().
+ */
+void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset)
+{
+ int k = bim->size;
+ comp d = (comp)((long_comp)COMP_RADIX/(bim->comps[k-1]+1));
+#ifdef CONFIG_BIGINT_MONTGOMERY
+ bigint *R, *R2;
+#endif
+
+ ctx->bi_mod[mod_offset] = bim;
+ bi_permanent(ctx->bi_mod[mod_offset]);
+ ctx->bi_normalised_mod[mod_offset] = bi_int_multiply(ctx, bim, d);
+ bi_permanent(ctx->bi_normalised_mod[mod_offset]);
+
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+ /* set montgomery variables */
+ R = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k-1); /* R */
+ R2 = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k*2-1); /* R^2 */
+ ctx->bi_RR_mod_m[mod_offset] = bi_mod(ctx, R2); /* R^2 mod m */
+ ctx->bi_R_mod_m[mod_offset] = bi_mod(ctx, R); /* R mod m */
+
+ bi_permanent(ctx->bi_RR_mod_m[mod_offset]);
+ bi_permanent(ctx->bi_R_mod_m[mod_offset]);
+
+ ctx->N0_dash[mod_offset] = modular_inverse(ctx->bi_mod[mod_offset]);
+
+#elif defined (CONFIG_BIGINT_BARRETT)
+ ctx->bi_mu[mod_offset] =
+ bi_divide(ctx, comp_left_shift(
+ bi_clone(ctx, ctx->bi_radix), k*2-1), ctx->bi_mod[mod_offset], 0);
+ bi_permanent(ctx->bi_mu[mod_offset]);
+#endif
+}
+
+/**
+ * @brief Used when cleaning various bigints at the end of a session.
+ * @param ctx [in] The bigint session context.
+ * @param mod_offset [in] The offset to use.
+ * @see bi_set_mod().
+ */
+void bi_free_mod(BI_CTX *ctx, int mod_offset)
+{
+ bi_depermanent(ctx->bi_mod[mod_offset]);
+ bi_free(ctx, ctx->bi_mod[mod_offset]);
+#if defined (CONFIG_BIGINT_MONTGOMERY)
+ bi_depermanent(ctx->bi_RR_mod_m[mod_offset]);
+ bi_depermanent(ctx->bi_R_mod_m[mod_offset]);
+ bi_free(ctx, ctx->bi_RR_mod_m[mod_offset]);
+ bi_free(ctx, ctx->bi_R_mod_m[mod_offset]);
+#elif defined(CONFIG_BIGINT_BARRETT)
+ bi_depermanent(ctx->bi_mu[mod_offset]);
+ bi_free(ctx, ctx->bi_mu[mod_offset]);
+#endif
+ bi_depermanent(ctx->bi_normalised_mod[mod_offset]);
+ bi_free(ctx, ctx->bi_normalised_mod[mod_offset]);
+}
+
+/**
+ * Perform a standard multiplication between two bigints.
+ *
+ * Barrett reduction has no need for some parts of the product, so ignore bits
+ * of the multiply. This routine gives Barrett its big performance
+ * improvements over Classical/Montgomery reduction methods.
+ */
+static bigint *regular_multiply(BI_CTX *ctx, bigint *bia, bigint *bib,
+ int inner_partial, int outer_partial)
+{
+ int i = 0, j;
+ int n = bia->size;
+ int t = bib->size;
+ bigint *biR = alloc(ctx, n + t);
+ comp *sr = biR->comps;
+ comp *sa = bia->comps;
+ comp *sb = bib->comps;
+
+ check(bia);
+ check(bib);
+
+ /* clear things to start with */
+ memset(biR->comps, 0, ((n+t)*COMP_BYTE_SIZE));
+
+ do
+ {
+ long_comp tmp;
+ comp carry = 0;
+ int r_index = i;
+ j = 0;
+
+ if (outer_partial && outer_partial-i > 0 && outer_partial < n)
+ {
+ r_index = outer_partial-1;
+ j = outer_partial-i-1;
+ }
+
+ do
+ {
+ if (inner_partial && r_index >= inner_partial)
+ {
+ break;
+ }
+
+ tmp = sr[r_index] + ((long_comp)sa[j])*sb[i] + carry;
+ sr[r_index++] = (comp)tmp; /* downsize */
+ carry = tmp >> COMP_BIT_SIZE;
+ } while (++j < n);
+
+ sr[r_index] = carry;
+ } while (++i < t);
+
+ bi_free(ctx, bia);
+ bi_free(ctx, bib);
+ return trim(biR);
+}
+
+#ifdef CONFIG_BIGINT_KARATSUBA
+/*
+ * Karatsuba improves on regular multiplication due to only 3 multiplications
+ * being done instead of 4. The additional additions/subtractions are O(N)
+ * rather than O(N^2) and so for big numbers it saves on a few operations
+ */
+static bigint *karatsuba(BI_CTX *ctx, bigint *bia, bigint *bib, int is_square)
+{
+ bigint *x0, *x1;
+ bigint *p0, *p1, *p2;
+ int m;
+
+ if (is_square)
+ {
+ m = (bia->size + 1)/2;
+ }
+ else
+ {
+ m = (max(bia->size, bib->size) + 1)/2;
+ }
+
+ x0 = bi_clone(ctx, bia);
+ x0->size = m;
+ x1 = bi_clone(ctx, bia);
+ comp_right_shift(x1, m);
+ bi_free(ctx, bia);
+
+ /* work out the 3 partial products */
+ if (is_square)
+ {
+ p0 = bi_square(ctx, bi_copy(x0));
+ p2 = bi_square(ctx, bi_copy(x1));
+ p1 = bi_square(ctx, bi_add(ctx, x0, x1));
+ }
+ else /* normal multiply */
+ {
+ bigint *y0, *y1;
+ y0 = bi_clone(ctx, bib);
+ y0->size = m;
+ y1 = bi_clone(ctx, bib);
+ comp_right_shift(y1, m);
+ bi_free(ctx, bib);
+
+ p0 = bi_multiply(ctx, bi_copy(x0), bi_copy(y0));
+ p2 = bi_multiply(ctx, bi_copy(x1), bi_copy(y1));
+ p1 = bi_multiply(ctx, bi_add(ctx, x0, x1), bi_add(ctx, y0, y1));
+ }
+
+ p1 = bi_subtract(ctx,
+ bi_subtract(ctx, p1, bi_copy(p2), NULL), bi_copy(p0), NULL);
+
+ comp_left_shift(p1, m);
+ comp_left_shift(p2, 2*m);
+ return bi_add(ctx, p1, bi_add(ctx, p0, p2));
+}
+#endif
+
+/**
+ * @brief Perform a multiplication operation between two bigints.
+ * @param ctx [in] The bigint session context.
+ * @param bia [in] A bigint.
+ * @param bib [in] Another bigint.
+ * @return The result of the multiplication.
+ */
+bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib)
+{
+ check(bia);
+ check(bib);
+
+#ifdef CONFIG_BIGINT_KARATSUBA
+ if (min(bia->size, bib->size) < MUL_KARATSUBA_THRESH)
+ {
+ return regular_multiply(ctx, bia, bib, 0, 0);
+ }
+
+ return karatsuba(ctx, bia, bib, 0);
+#else
+ return regular_multiply(ctx, bia, bib, 0, 0);
+#endif
+}
+
+#ifdef CONFIG_BIGINT_SQUARE
+/*
+ * Perform the actual square operion. It takes into account overflow.
+ */
+static bigint *regular_square(BI_CTX *ctx, bigint *bi)
+{
+ int t = bi->size;
+ int i = 0, j;
+ bigint *biR = alloc(ctx, t*2+1);
+ comp *w = biR->comps;
+ comp *x = bi->comps;
+ long_comp carry;
+ memset(w, 0, biR->size*COMP_BYTE_SIZE);
+
+ do
+ {
+ long_comp tmp = w[2*i] + (long_comp)x[i]*x[i];
+ w[2*i] = (comp)tmp;
+ carry = tmp >> COMP_BIT_SIZE;
+
+ for (j = i+1; j < t; j++)
+ {
+ uint8_t c = 0;
+ long_comp xx = (long_comp)x[i]*x[j];
+ if ((COMP_MAX-xx) < xx)
+ c = 1;
+
+ tmp = (xx<<1);
+
+ if ((COMP_MAX-tmp) < w[i+j])
+ c = 1;
+
+ tmp += w[i+j];
+
+ if ((COMP_MAX-tmp) < carry)
+ c = 1;
+
+ tmp += carry;
+ w[i+j] = (comp)tmp;
+ carry = tmp >> COMP_BIT_SIZE;
+
+ if (c)
+ carry += COMP_RADIX;
+ }
+
+ tmp = w[i+t] + carry;
+ w[i+t] = (comp)tmp;
+ w[i+t+1] = tmp >> COMP_BIT_SIZE;
+ } while (++i < t);
+
+ bi_free(ctx, bi);
+ return trim(biR);
+}
+
+/**
+ * @brief Perform a square operation on a bigint.
+ * @param ctx [in] The bigint session context.
+ * @param bia [in] A bigint.
+ * @return The result of the multiplication.
+ */
+bigint *bi_square(BI_CTX *ctx, bigint *bia)
+{
+ check(bia);
+
+#ifdef CONFIG_BIGINT_KARATSUBA
+ if (bia->size < SQU_KARATSUBA_THRESH)
+ {
+ return regular_square(ctx, bia);
+ }
+
+ return karatsuba(ctx, bia, NULL, 1);
+#else
+ return regular_square(ctx, bia);
+#endif
+}
+#endif
+
+/**
+ * @brief Compare two bigints.
+ * @param bia [in] A bigint.
+ * @param bib [in] Another bigint.
+ * @return -1 if smaller, 1 if larger and 0 if equal.
+ */
+int bi_compare(bigint *bia, bigint *bib)
+{
+ int r, i;
+
+ check(bia);
+ check(bib);
+
+ if (bia->size > bib->size)
+ r = 1;
+ else if (bia->size < bib->size)
+ r = -1;
+ else
+ {
+ comp *a = bia->comps;
+ comp *b = bib->comps;
+
+ /* Same number of components. Compare starting from the high end
+ * and working down. */
+ r = 0;
+ i = bia->size - 1;
+
+ do
+ {
+ if (a[i] > b[i])
+ {
+ r = 1;
+ break;
+ }
+ else if (a[i] < b[i])
+ {
+ r = -1;
+ break;
+ }
+ } while (--i >= 0);
+ }
+
+ return r;
+}
+
+/*
+ * Allocate and zero more components. Does not consume bi.
+ */
+static void more_comps(bigint *bi, int n)
+{
+ if (n > bi->max_comps)
+ {
+ bi->max_comps = max(bi->max_comps * 2, n);
+ bi->comps = (comp*)realloc(bi->comps, bi->max_comps * COMP_BYTE_SIZE);
+ }
+
+ if (n > bi->size)
+ {
+ memset(&bi->comps[bi->size], 0, (n-bi->size)*COMP_BYTE_SIZE);
+ }
+
+ bi->size = n;
+}
+
+/*
+ * Make a new empty bigint. It may just use an old one if one is available.
+ * Otherwise get one off the heap.
+ */
+static bigint *alloc(BI_CTX *ctx, int size)
+{
+ bigint *biR;
+
+ /* Can we recycle an old bigint? */
+ if (ctx->free_list != NULL)
+ {
+ biR = ctx->free_list;
+ ctx->free_list = biR->next;
+ ctx->free_count--;
+
+ if (biR->refs != 0)
+ {
+#ifdef CONFIG_SSL_FULL_MODE
+ printf("alloc: refs was not 0\n");
+#endif
+ abort(); /* create a stack trace from a core dump */
+ }
+
+ more_comps(biR, size);
+ }
+ else
+ {
+ /* No free bigints available - create a new one. */
+ biR = (bigint *)malloc(sizeof(bigint));
+ biR->comps = (comp*)malloc(size * COMP_BYTE_SIZE);
+ biR->max_comps = size; /* give some space to spare */
+ }
+
+ biR->size = size;
+ biR->refs = 1;
+ biR->next = NULL;
+ ctx->active_count++;
+ return biR;
+}
+
+/*
+ * Work out the highest '1' bit in an exponent. Used when doing sliding-window
+ * exponentiation.
+ */
+static int find_max_exp_index(bigint *biexp)
+{
+ int i = COMP_BIT_SIZE-1;
+ comp shift = COMP_RADIX/2;
+ comp test = biexp->comps[biexp->size-1]; /* assume no leading zeroes */
+
+ check(biexp);
+
+ do
+ {
+ if (test & shift)
+ {
+ return i+(biexp->size-1)*COMP_BIT_SIZE;
+ }
+
+ shift >>= 1;
+ } while (i-- != 0);
+
+ return -1; /* error - must have been a leading 0 */
+}
+
+/*
+ * Is a particular bit is an exponent 1 or 0? Used when doing sliding-window
+ * exponentiation.
+ */
+static int exp_bit_is_one(bigint *biexp, int offset)
+{
+ comp test = biexp->comps[offset / COMP_BIT_SIZE];
+ int num_shifts = offset % COMP_BIT_SIZE;
+ comp shift = 1;
+ int i;
+
+ check(biexp);
+
+ for (i = 0; i < num_shifts; i++)
+ {
+ shift <<= 1;
+ }
+
+ return (test & shift) != 0;
+}
+
+#ifdef CONFIG_BIGINT_CHECK_ON
+/*
+ * Perform a sanity check on bi.
+ */
+static void check(const bigint *bi)
+{
+ if (bi->refs <= 0)
+ {
+ printf("check: zero or negative refs in bigint\n");
+ abort();
+ }
+
+ if (bi->next != NULL)
+ {
+ printf("check: attempt to use a bigint from "
+ "the free list\n");
+ abort();
+ }
+}
+#endif
+
+/*
+ * Delete any leading 0's (and allow for 0).
+ */
+static bigint *trim(bigint *bi)
+{
+ check(bi);
+
+ while (bi->comps[bi->size-1] == 0 && bi->size > 1)
+ {
+ bi->size--;
+ }
+
+ return bi;
+}
+
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+/**
+ * @brief Perform a single montgomery reduction.
+ * @param ctx [in] The bigint session context.
+ * @param bixy [in] A bigint.
+ * @return The result of the montgomery reduction.
+ */
+bigint *bi_mont(BI_CTX *ctx, bigint *bixy)
+{
+ int i = 0, n;
+ uint8_t mod_offset = ctx->mod_offset;
+ bigint *bim = ctx->bi_mod[mod_offset];
+ comp mod_inv = ctx->N0_dash[mod_offset];
+
+ check(bixy);
+
+ if (ctx->use_classical) /* just use classical instead */
+ {
+ return bi_mod(ctx, bixy);
+ }
+
+ n = bim->size;
+
+ do
+ {
+ bixy = bi_add(ctx, bixy, comp_left_shift(
+ bi_int_multiply(ctx, bim, bixy->comps[i]*mod_inv), i));
+ } while (++i < n);
+
+ comp_right_shift(bixy, n);
+
+ if (bi_compare(bixy, bim) >= 0)
+ {
+ bixy = bi_subtract(ctx, bixy, bim, NULL);
+ }
+
+ return bixy;
+}
+
+#elif defined(CONFIG_BIGINT_BARRETT)
+/*
+ * Stomp on the most significant components to give the illusion of a "mod base
+ * radix" operation
+ */
+static bigint *comp_mod(bigint *bi, int mod)
+{
+ check(bi);
+
+ if (bi->size > mod)
+ {
+ bi->size = mod;
+ }
+
+ return bi;
+}
+
+/**
+ * @brief Perform a single Barrett reduction.
+ * @param ctx [in] The bigint session context.
+ * @param bi [in] A bigint.
+ * @return The result of the Barrett reduction.
+ */
+bigint *bi_barrett(BI_CTX *ctx, bigint *bi)
+{
+ bigint *q1, *q2, *q3, *r1, *r2, *r;
+ uint8_t mod_offset = ctx->mod_offset;
+ bigint *bim = ctx->bi_mod[mod_offset];
+ int k = bim->size;
+
+ check(bi);
+ check(bim);
+
+ /* use Classical method instead - Barrett cannot help here */
+ if (bi->size > k*2)
+ {
+ return bi_mod(ctx, bi);
+ }
+
+ q1 = comp_right_shift(bi_clone(ctx, bi), k-1);
+
+ /* do outer partial multiply */
+ q2 = regular_multiply(ctx, q1, ctx->bi_mu[mod_offset], 0, k-1);
+ q3 = comp_right_shift(q2, k+1);
+ r1 = comp_mod(bi, k+1);
+
+ /* do inner partial multiply */
+ r2 = comp_mod(regular_multiply(ctx, q3, bim, k+1, 0), k+1);
+ r = bi_subtract(ctx, r1, r2, NULL);
+
+ /* if (r >= m) r = r - m; */
+ if (bi_compare(r, bim) >= 0)
+ {
+ r = bi_subtract(ctx, r, bim, NULL);
+ }
+
+ return r;
+}
+#endif /* CONFIG_BIGINT_BARRETT */
+
+#ifdef CONFIG_BIGINT_SLIDING_WINDOW
+/*
+ * Work out g1, g3, g5, g7... etc for the sliding-window algorithm
+ */
+static void precompute_slide_window(BI_CTX *ctx, int window, bigint *g1)
+{
+ int k = 1, i;
+ bigint *g2;
+
+ for (i = 0; i < window-1; i++) /* compute 2^(window-1) */
+ {
+ k <<= 1;
+ }
+
+ ctx->g = (bigint **)malloc(k*sizeof(bigint *));
+ ctx->g[0] = bi_clone(ctx, g1);
+ bi_permanent(ctx->g[0]);
+ g2 = bi_residue(ctx, bi_square(ctx, ctx->g[0])); /* g^2 */
+
+ for (i = 1; i < k; i++)
+ {
+ ctx->g[i] = bi_residue(ctx, bi_multiply(ctx, ctx->g[i-1], bi_copy(g2)));
+ bi_permanent(ctx->g[i]);
+ }
+
+ bi_free(ctx, g2);
+ ctx->window = k;
+}
+#endif
+
+/**
+ * @brief Perform a modular exponentiation.
+ *
+ * This function requires bi_set_mod() to have been called previously. This is
+ * one of the optimisations used for performance.
+ * @param ctx [in] The bigint session context.
+ * @param bi [in] The bigint on which to perform the mod power operation.
+ * @param biexp [in] The bigint exponent.
+ * @return The result of the mod exponentiation operation
+ * @see bi_set_mod().
+ */
+bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp)
+{
+ int i = find_max_exp_index(biexp), j, window_size = 1;
+ bigint *biR = int_to_bi(ctx, 1);
+
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+ uint8_t mod_offset = ctx->mod_offset;
+ if (!ctx->use_classical)
+ {
+ /* preconvert */
+ bi = bi_mont(ctx,
+ bi_multiply(ctx, bi, ctx->bi_RR_mod_m[mod_offset])); /* x' */
+ bi_free(ctx, biR);
+ biR = ctx->bi_R_mod_m[mod_offset]; /* A */
+ }
+#endif
+
+ check(bi);
+ check(biexp);
+
+#ifdef CONFIG_BIGINT_SLIDING_WINDOW
+ for (j = i; j > 32; j /= 5) /* work out an optimum size */
+ window_size++;
+
+ /* work out the slide constants */
+ precompute_slide_window(ctx, window_size, bi);
+#else /* just one constant */
+ ctx->g = (bigint **)malloc(sizeof(bigint *));
+ ctx->g[0] = bi_clone(ctx, bi);
+ ctx->window = 1;
+ bi_permanent(ctx->g[0]);
+#endif
+
+ /* if sliding-window is off, then only one bit will be done at a time and
+ * will reduce to standard left-to-right exponentiation */
+ do
+ {
+#ifdef __ets__
+ void ets_loop_iter(void);
+ ets_loop_iter();
+#endif
+ if (exp_bit_is_one(biexp, i))
+ {
+ int l = i-window_size+1;
+ int part_exp = 0;
+
+ if (l < 0) /* LSB of exponent will always be 1 */
+ l = 0;
+ else
+ {
+ while (exp_bit_is_one(biexp, l) == 0)
+ l++; /* go back up */
+ }
+
+ /* build up the section of the exponent */
+ for (j = i; j >= l; j--)
+ {
+ biR = bi_residue(ctx, bi_square(ctx, biR));
+ if (exp_bit_is_one(biexp, j))
+ part_exp++;
+
+ if (j != l)
+ part_exp <<= 1;
+ }
+
+ part_exp = (part_exp-1)/2; /* adjust for array */
+ biR = bi_residue(ctx, bi_multiply(ctx, biR, ctx->g[part_exp]));
+ i = l-1;
+ }
+ else /* square it */
+ {
+ biR = bi_residue(ctx, bi_square(ctx, biR));
+ i--;
+ }
+ } while (i >= 0);
+
+ /* cleanup */
+ for (i = 0; i < ctx->window; i++)
+ {
+ bi_depermanent(ctx->g[i]);
+ bi_free(ctx, ctx->g[i]);
+ }
+
+ free(ctx->g);
+ bi_free(ctx, bi);
+ bi_free(ctx, biexp);
+#if defined CONFIG_BIGINT_MONTGOMERY
+ return ctx->use_classical ? biR : bi_mont(ctx, biR); /* convert back */
+#else /* CONFIG_BIGINT_CLASSICAL or CONFIG_BIGINT_BARRETT */
+ return biR;
+#endif
+}
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+/**
+ * @brief Perform a modular exponentiation using a temporary modulus.
+ *
+ * We need this function to check the signatures of certificates. The modulus
+ * of this function is temporary as it's just used for authentication.
+ * @param ctx [in] The bigint session context.
+ * @param bi [in] The bigint to perform the exp/mod.
+ * @param bim [in] The temporary modulus.
+ * @param biexp [in] The bigint exponent.
+ * @return The result of the mod exponentiation operation
+ * @see bi_set_mod().
+ */
+bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp)
+{
+ bigint *biR, *tmp_biR;
+
+ /* Set up a temporary bigint context and transfer what we need between
+ * them. We need to do this since we want to keep the original modulus
+ * which is already in this context. This operation is only called when
+ * doing peer verification, and so is not expensive :-) */
+ BI_CTX *tmp_ctx = bi_initialize();
+ bi_set_mod(tmp_ctx, bi_clone(tmp_ctx, bim), BIGINT_M_OFFSET);
+ tmp_biR = bi_mod_power(tmp_ctx,
+ bi_clone(tmp_ctx, bi),
+ bi_clone(tmp_ctx, biexp));
+ biR = bi_clone(ctx, tmp_biR);
+ bi_free(tmp_ctx, tmp_biR);
+ bi_free_mod(tmp_ctx, BIGINT_M_OFFSET);
+ bi_terminate(tmp_ctx);
+
+ bi_free(ctx, bi);
+ bi_free(ctx, bim);
+ bi_free(ctx, biexp);
+ return biR;
+}
+#endif
+
+#ifdef CONFIG_BIGINT_CRT
+/**
+ * @brief Use the Chinese Remainder Theorem to quickly perform RSA decrypts.
+ *
+ * @param ctx [in] The bigint session context.
+ * @param bi [in] The bigint to perform the exp/mod.
+ * @param dP [in] CRT's dP bigint
+ * @param dQ [in] CRT's dQ bigint
+ * @param p [in] CRT's p bigint
+ * @param q [in] CRT's q bigint
+ * @param qInv [in] CRT's qInv bigint
+ * @return The result of the CRT operation
+ */
+bigint *bi_crt(BI_CTX *ctx, bigint *bi,
+ bigint *dP, bigint *dQ,
+ bigint *p, bigint *q, bigint *qInv)
+{
+ 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), dP);
+
+ ctx->mod_offset = BIGINT_Q_OFFSET;
+ m2 = bi_mod_power(ctx, bi, dQ);
+
+ h = bi_subtract(ctx, bi_add(ctx, m1, p), bi_copy(m2), NULL);
+ h = bi_multiply(ctx, h, 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, q, h));
+}
+#endif
+/** @} */
diff --git a/circuitpython/lib/axtls/crypto/bigint.h b/circuitpython/lib/axtls/crypto/bigint.h
new file mode 100644
index 0000000..2966a3e
--- /dev/null
+++ b/circuitpython/lib/axtls/crypto/bigint.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BIGINT_HEADER
+#define BIGINT_HEADER
+
+#include "crypto.h"
+
+BI_CTX *bi_initialize(void);
+void bi_terminate(BI_CTX *ctx);
+void bi_permanent(bigint *bi);
+void bi_depermanent(bigint *bi);
+void bi_clear_cache(BI_CTX *ctx);
+void bi_free(BI_CTX *ctx, bigint *bi);
+bigint *bi_copy(bigint *bi);
+bigint *bi_clone(BI_CTX *ctx, const bigint *bi);
+void bi_export(BI_CTX *ctx, bigint *bi, uint8_t *data, int size);
+bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int len);
+bigint *int_to_bi(BI_CTX *ctx, comp i);
+
+/* the functions that actually do something interesting */
+bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib);
+bigint *bi_subtract(BI_CTX *ctx, bigint *bia,
+ bigint *bib, int *is_negative);
+bigint *bi_divide(BI_CTX *ctx, bigint *bia, bigint *bim, int is_mod);
+bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib);
+bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp);
+bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp);
+int bi_compare(bigint *bia, bigint *bib);
+void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset);
+void bi_free_mod(BI_CTX *ctx, int mod_offset);
+
+#ifdef CONFIG_SSL_FULL_MODE
+void bi_print(const char *label, bigint *bi);
+bigint *bi_str_import(BI_CTX *ctx, const char *data);
+#endif
+
+/**
+ * @def bi_mod
+ * Find the residue of B. bi_set_mod() must be called before hand.
+ */
+#define bi_mod(A, B) bi_divide(A, B, ctx->bi_mod[ctx->mod_offset], 1)
+
+/**
+ * bi_residue() is technically the same as bi_mod(), but it uses the
+ * appropriate reduction technique (which is bi_mod() when doing classical
+ * reduction).
+ */
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+#define bi_residue(A, B) bi_mont(A, B)
+bigint *bi_mont(BI_CTX *ctx, bigint *bixy);
+#elif defined(CONFIG_BIGINT_BARRETT)
+#define bi_residue(A, B) bi_barrett(A, B)
+bigint *bi_barrett(BI_CTX *ctx, bigint *bi);
+#else /* if defined(CONFIG_BIGINT_CLASSICAL) */
+#define bi_residue(A, B) bi_mod(A, B)
+#endif
+
+#ifdef CONFIG_BIGINT_SQUARE
+bigint *bi_square(BI_CTX *ctx, bigint *bi);
+#else
+#define bi_square(A, B) bi_multiply(A, bi_copy(B), B)
+#endif
+
+#ifdef CONFIG_BIGINT_CRT
+bigint *bi_crt(BI_CTX *ctx, bigint *bi,
+ bigint *dP, bigint *dQ,
+ bigint *p, bigint *q,
+ bigint *qInv);
+#endif
+
+#endif
diff --git a/circuitpython/lib/axtls/crypto/bigint_impl.h b/circuitpython/lib/axtls/crypto/bigint_impl.h
new file mode 100644
index 0000000..fef6e03
--- /dev/null
+++ b/circuitpython/lib/axtls/crypto/bigint_impl.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BIGINT_IMPL_HEADER
+#define BIGINT_IMPL_HEADER
+
+/* Maintain a number of precomputed variables when doing reduction */
+#define BIGINT_M_OFFSET 0 /**< Normal modulo offset. */
+#ifdef CONFIG_BIGINT_CRT
+#define BIGINT_P_OFFSET 1 /**< p modulo offset. */
+#define BIGINT_Q_OFFSET 2 /**< q module offset. */
+#define BIGINT_NUM_MODS 3 /**< The number of modulus constants used. */
+#else
+#define BIGINT_NUM_MODS 1
+#endif
+
+/* Architecture specific functions for big ints */
+#if defined(CONFIG_INTEGER_8BIT)
+#define COMP_RADIX 256U /**< Max component + 1 */
+#define COMP_MAX 0xFFFFU/**< (Max dbl comp -1) */
+#define COMP_BIT_SIZE 8 /**< Number of bits in a component. */
+#define COMP_BYTE_SIZE 1 /**< Number of bytes in a component. */
+#define COMP_NUM_NIBBLES 2 /**< Used For diagnostics only. */
+typedef uint8_t comp; /**< A single precision component. */
+typedef uint16_t long_comp; /**< A double precision component. */
+typedef int16_t slong_comp; /**< A signed double precision component. */
+#elif defined(CONFIG_INTEGER_16BIT)
+#define COMP_RADIX 65536U /**< Max component + 1 */
+#define COMP_MAX 0xFFFFFFFFU/**< (Max dbl comp -1) */
+#define COMP_BIT_SIZE 16 /**< Number of bits in a component. */
+#define COMP_BYTE_SIZE 2 /**< Number of bytes in a component. */
+#define COMP_NUM_NIBBLES 4 /**< Used For diagnostics only. */
+typedef uint16_t comp; /**< A single precision component. */
+typedef uint32_t long_comp; /**< A double precision component. */
+typedef int32_t slong_comp; /**< A signed double precision component. */
+#else /* regular 32 bit */
+#ifdef WIN32
+#define COMP_RADIX 4294967296i64
+#define COMP_MAX 0xFFFFFFFFFFFFFFFFui64
+#else
+#define COMP_RADIX 4294967296ULL /**< Max component + 1 */
+#define COMP_MAX 0xFFFFFFFFFFFFFFFFULL/**< (Max dbl comp -1) */
+#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. */
+#endif
+
+/**
+ * @struct _bigint
+ * @brief A big integer basic object
+ */
+struct _bigint
+{
+ struct _bigint* next; /**< The next bigint in the cache. */
+ short size; /**< The number of components in this bigint. */
+ short max_comps; /**< The heapsize allocated for this bigint */
+ int refs; /**< An internal reference count. */
+ comp* comps; /**< A ptr to the actual component data */
+};
+
+typedef struct _bigint bigint; /**< An alias for _bigint */
+
+/**
+ * Maintains the state of the cache, and a number of variables used in
+ * reduction.
+ */
+typedef struct /**< A big integer "session" context. */
+{
+ bigint *active_list; /**< Bigints currently used. */
+ bigint *free_list; /**< Bigints not used. */
+ bigint *bi_radix; /**< The radix used. */
+ bigint *bi_mod[BIGINT_NUM_MODS]; /**< modulus */
+
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+ bigint *bi_RR_mod_m[BIGINT_NUM_MODS]; /**< R^2 mod m */
+ bigint *bi_R_mod_m[BIGINT_NUM_MODS]; /**< R mod m */
+ comp N0_dash[BIGINT_NUM_MODS];
+#elif defined(CONFIG_BIGINT_BARRETT)
+ bigint *bi_mu[BIGINT_NUM_MODS]; /**< Storage for mu */
+#endif
+ bigint *bi_normalised_mod[BIGINT_NUM_MODS]; /**< Normalised mod storage. */
+ bigint **g; /**< Used by sliding-window. */
+ int window; /**< The size of the sliding window */
+ int active_count; /**< Number of active bigints. */
+ int free_count; /**< Number of free bigints. */
+
+#ifdef CONFIG_BIGINT_MONTGOMERY
+ uint8_t use_classical; /**< Use classical reduction. */
+#endif
+ uint8_t mod_offset; /**< The mod offset we are using */
+} BI_CTX;
+
+#ifndef WIN32
+#define max(a,b) ((a)>(b)?(a):(b)) /**< Find the maximum of 2 numbers. */
+#define min(a,b) ((a)<(b)?(a):(b)) /**< Find the minimum of 2 numbers. */
+#endif
+
+#define PERMANENT 0x7FFF55AA /**< A magic number for permanents. */
+
+#endif
diff --git a/circuitpython/lib/axtls/crypto/crypto.h b/circuitpython/lib/axtls/crypto/crypto.h
new file mode 100644
index 0000000..df232a3
--- /dev/null
+++ b/circuitpython/lib/axtls/crypto/crypto.h
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2007-2016, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file crypto.h
+ */
+
+#ifndef HEADER_CRYPTO_H
+#define HEADER_CRYPTO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "bigint_impl.h"
+#include "bigint.h"
+
+#ifndef STDCALL
+#define STDCALL
+#endif
+#ifndef EXP_FUNC
+#define EXP_FUNC
+#endif
+
+
+/* enable features based on a 'super-set' capbaility. */
+#if 0
+#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
+#endif
+
+/**************************************************************************
+ * 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);
+void AES_encrypt(const AES_CTX *ctx, uint32_t *data);
+void AES_decrypt(const AES_CTX *ctx, uint32_t *data);
+
+/**************************************************************************
+ * RC4 declarations
+ **************************************************************************/
+
+typedef struct
+{
+ uint8_t 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 SHA1_Init(SHA1_CTX *);
+void SHA1_Update(SHA1_CTX *, const uint8_t * msg, int len);
+void SHA1_Final(uint8_t *digest, SHA1_CTX *);
+
+/**************************************************************************
+ * SHA256 declarations
+ **************************************************************************/
+
+#define SHA256_SIZE 32
+
+#ifndef SHA256_CTX
+#define SHA256_CTX SHA256_CTX
+typedef struct
+{
+ uint32_t total[2];
+ uint32_t state[8];
+ uint8_t buffer[64];
+} SHA256_CTX;
+
+void SHA256_Init(SHA256_CTX *c);
+void SHA256_Update(SHA256_CTX *, const uint8_t *input, int len);
+void SHA256_Final(uint8_t *digest, SHA256_CTX *);
+#endif
+
+/**************************************************************************
+ * SHA512 declarations
+ **************************************************************************/
+
+#define SHA512_SIZE 64
+
+typedef struct
+{
+ union
+ {
+ uint64_t h[8];
+ uint8_t digest[64];
+ } h_dig;
+ union
+ {
+ uint64_t w[80];
+ uint8_t buffer[128];
+ } w_buf;
+ size_t size;
+ uint64_t totalSize;
+} SHA512_CTX;
+
+void SHA512_Init(SHA512_CTX *c);
+void SHA512_Update(SHA512_CTX *, const uint8_t *input, int len);
+void SHA512_Final(uint8_t *digest, SHA512_CTX *);
+
+/**************************************************************************
+ * SHA384 declarations
+ **************************************************************************/
+
+#define SHA384_SIZE 48
+
+typedef SHA512_CTX SHA384_CTX;
+void SHA384_Init(SHA384_CTX *c);
+void SHA384_Update(SHA384_CTX *, const uint8_t *input, int len);
+void SHA384_Final(uint8_t *digest, SHA384_CTX *);
+
+/**************************************************************************
+ * MD5 declarations
+ **************************************************************************/
+
+#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 MD5_Init(MD5_CTX *);
+EXP_FUNC void STDCALL MD5_Update(MD5_CTX *, const uint8_t *msg, int len);
+EXP_FUNC void STDCALL MD5_Final(uint8_t *digest, MD5_CTX *);
+
+/**************************************************************************
+ * HMAC declarations
+ **************************************************************************/
+void ssl_hmac_md5(const uint8_t *msg, int length, const uint8_t *key,
+ int key_len, uint8_t *digest);
+void ssl_hmac_sha1(const uint8_t *msg, int length, const uint8_t *key,
+ int key_len, uint8_t *digest);
+void hmac_sha256(const uint8_t *msg, int length, const uint8_t *key,
+ int key_len, uint8_t *digest);
+
+/**************************************************************************
+ * RSA declarations
+ **************************************************************************/
+
+typedef struct
+{
+ bigint *m; /* modulus */
+ bigint *e; /* public exponent */
+ bigint *d; /* private exponent */
+#ifdef CONFIG_BIGINT_CRT
+ bigint *p; /* p as in m = pq */
+ bigint *q; /* q as in m = pq */
+ bigint *dP; /* d mod (p-1) */
+ bigint *dQ; /* d mod (q-1) */
+ bigint *qInv; /* q^-1 mod p */
+#endif
+ int num_octets;
+ BI_CTX *bi_ctx;
+} RSA_CTX;
+
+void RSA_priv_key_new(RSA_CTX **rsa_ctx,
+ const uint8_t *modulus, int mod_len,
+ const uint8_t *pub_exp, int pub_len,
+ const uint8_t *priv_exp, int priv_len
+#ifdef CONFIG_BIGINT_CRT
+ , const uint8_t *p, int p_len,
+ const uint8_t *q, int q_len,
+ const uint8_t *dP, int dP_len,
+ const uint8_t *dQ, int dQ_len,
+ const uint8_t *qInv, int qInv_len
+#endif
+ );
+void RSA_pub_key_new(RSA_CTX **rsa_ctx,
+ const uint8_t *modulus, int mod_len,
+ const uint8_t *pub_exp, int pub_len);
+void RSA_free(RSA_CTX *ctx);
+int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data,
+ int out_len, int is_decryption);
+bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg);
+// Don't bother to ifdef prototypes, let them be
+//#if defined(CONFIG_SSL_CERT_VERIFICATION) || defined(CONFIG_SSL_GENERATE_X509_CERT)
+bigint *RSA_sign_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,
+ bigint *modulus, bigint *pub_exp);
+bigint *RSA_public(const RSA_CTX * c, bigint *bi_msg);
+int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len,
+ uint8_t *out_data, int is_signing);
+void RSA_print(const RSA_CTX *ctx);
+//#endif
+
+/**************************************************************************
+ * RNG declarations
+ **************************************************************************/
+EXP_FUNC void STDCALL RNG_initialize(void);
+EXP_FUNC void STDCALL RNG_custom_init(const uint8_t *seed_buf, int size);
+EXP_FUNC void STDCALL RNG_terminate(void);
+EXP_FUNC int STDCALL get_random(int num_rand_bytes, uint8_t *rand_data);
+int get_random_NZ(int num_rand_bytes, uint8_t *rand_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/circuitpython/lib/axtls/crypto/crypto_misc.c b/circuitpython/lib/axtls/crypto/crypto_misc.c
new file mode 100644
index 0000000..bba5a20
--- /dev/null
+++ b/circuitpython/lib/axtls/crypto/crypto_misc.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2007-2019, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Some misc. routines to help things out
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include "os_port.h"
+#include "crypto_misc.h"
+#ifdef CONFIG_WIN32_USE_CRYPTO_LIB
+#include "wincrypt.h"
+#endif
+
+#if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM)
+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))
+/* change to processor registers as appropriate */
+#define ENTROPY_POOL_SIZE 32
+#define ENTROPY_COUNTER1 ((((uint64_t)tv.tv_sec)<<32) | tv.tv_usec)
+#define ENTROPY_COUNTER2 rand()
+static uint8_t entropy_pool[ENTROPY_POOL_SIZE];
+#endif
+
+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.
+ */
+#ifdef __GNUC__
+// The stack-entropy-grabbing memcpy() is tagged as an error by gcc
+// -fsanitize=undefined.
+__attribute__((no_sanitize_address))
+#if __GNUC__ >= 5
+__attribute__((no_sanitize_undefined))
+#endif
+#endif
+EXP_FUNC void STDCALL RNG_initialize()
+{
+#if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM)
+ rng_fd = 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);
+ }
+ }
+#elif !defined(__ets__)
+ /* start of with a stack to copy across */
+ int i = rand();
+ memcpy(entropy_pool, &i, ENTROPY_POOL_SIZE);
+ #ifdef __ANDROID__
+ /* Later android releases have rand_r(), but classic ones, e.g.
+ android-3 (1.5) have jrand48(). */
+ jrand48((unsigned short *)entropy_pool);
+ #else
+ rand_r((unsigned int *)entropy_pool);
+ #endif
+#endif
+}
+
+/**
+ * If no /dev/urandom, then initialise the RNG with something interesting.
+ */
+EXP_FUNC void STDCALL RNG_custom_init(const uint8_t *seed_buf, int size)
+{
+#if defined(WIN32) || defined(CONFIG_WIN32_USE_CRYPTO_LIB)
+ int i;
+
+ for (i = 0; i < ENTROPY_POOL_SIZE && i < size; i++)
+ entropy_pool[i] ^= seed_buf[i];
+#endif
+}
+
+/**
+ * Terminate the RNG engine.
+ */
+EXP_FUNC void STDCALL RNG_terminate(void)
+{
+#if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM)
+ 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 int STDCALL get_random(int num_rand_bytes, uint8_t *rand_data)
+{
+#if defined(PLATFORM_RNG_U8)
+ while (num_rand_bytes--) {
+ *rand_data++ = PLATFORM_RNG_U8();
+ }
+#elif !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM)
+ /* use the Linux default - read from /dev/urandom */
+ if (read(rng_fd, rand_data, num_rand_bytes) < 0)
+ return -1;
+#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 */
+ AES_CTX rng_ctx;
+ struct timeval tv;
+ MD5_CTX rng_digest_ctx;
+ uint8_t digest[MD5_SIZE];
+ uint64_t *ep;
+ int i;
+
+ /* A proper implementation would use counters etc for entropy */
+ gettimeofday(&tv, NULL);
+ ep = (uint64_t *)entropy_pool;
+ ep[0] ^= ENTROPY_COUNTER1;
+ ep[1] ^= ENTROPY_COUNTER2;
+
+ /* use a digested version of the entropy pool as a key */
+ MD5_Init(&rng_digest_ctx);
+ MD5_Update(&rng_digest_ctx, entropy_pool, ENTROPY_POOL_SIZE);
+ MD5_Final(digest, &rng_digest_ctx);
+
+ /* come up with the random sequence */
+ AES_set_key(&rng_ctx, digest, (const uint8_t *)ep, AES_MODE_128); /* use as a key */
+ memcpy(rand_data, entropy_pool, num_rand_bytes < ENTROPY_POOL_SIZE ?
+ num_rand_bytes : ENTROPY_POOL_SIZE);
+ AES_cbc_encrypt(&rng_ctx, rand_data, rand_data, num_rand_bytes);
+
+ /* move things along */
+ for (i = ENTROPY_POOL_SIZE-1; i >= MD5_SIZE ; i--)
+ entropy_pool[i] = entropy_pool[i-MD5_SIZE];
+
+ /* insert the digest at the start of the entropy pool */
+ memcpy(entropy_pool, digest, MD5_SIZE);
+#endif
+ return 0;
+}
+
+/**
+ * Set a series of bytes with a random number. Individual bytes are not zero.
+ */
+int get_random_NZ(int num_rand_bytes, uint8_t *rand_data)
+{
+ int i;
+ if (get_random(num_rand_bytes, rand_data))
+ return -1;
+
+ for (i = 0; i < num_rand_bytes; i++)
+ {
+ while (rand_data[i] == 0) /* can't be 0 */
+ rand_data[i] = (uint8_t)(rand());
+ }
+
+ return 0;
+}
+
+/**
+ * Some useful diagnostic routines
+ */
+#if defined(CONFIG_SSL_DIAGNOSTICS) || 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);
+ snprintf(tmp, sizeof(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;
+ }
+
+ /* check that we don't go past the output buffer */
+ if (z > *outlen)
+ goto error;
+ }
+
+ if (y != 0)
+ goto error;
+
+ *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
+
diff --git a/circuitpython/lib/axtls/crypto/hmac.c b/circuitpython/lib/axtls/crypto/hmac.c
new file mode 100644
index 0000000..ac5bb18
--- /dev/null
+++ b/circuitpython/lib/axtls/crypto/hmac.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2007-2016, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * HMAC implementation - This code was originally taken from RFC2104
+ * See http://www.ietf.org/rfc/rfc2104.txt and
+ * http://www.faqs.org/rfcs/rfc2202.html
+ */
+
+#include <string.h>
+#include "os_port.h"
+#include "crypto.h"
+
+/**
+ * Perform HMAC-MD5
+ * NOTE: does not handle keys larger than the block size.
+ */
+void ssl_hmac_md5(const uint8_t *msg, int length, const uint8_t *key,
+ int key_len, uint8_t *digest)
+{
+ MD5_CTX context;
+ uint8_t k_pad[64];
+ int i;
+
+ memset(k_pad, 0, sizeof k_pad);
+ memcpy(k_pad, key, key_len);
+ for (i = 0; i < 64; i++)
+ {
+ k_pad[i] ^= 0x36;
+ }
+
+ MD5_Init(&context);
+ MD5_Update(&context, k_pad, 64);
+ MD5_Update(&context, msg, length);
+ MD5_Final(digest, &context);
+
+ memset(k_pad, 0, sizeof k_pad);
+ memcpy(k_pad, key, key_len);
+ for (i = 0; i < 64; i++)
+ {
+ k_pad[i] ^= 0x5c;
+ }
+
+ MD5_Init(&context);
+ MD5_Update(&context, k_pad, 64);
+ MD5_Update(&context, digest, MD5_SIZE);
+ MD5_Final(digest, &context);
+}
+
+/**
+ * Perform HMAC-SHA1
+ * NOTE: does not handle keys larger than the block size.
+ */
+void ssl_hmac_sha1(const uint8_t *msg, int length, const uint8_t *key,
+ int key_len, uint8_t *digest)
+{
+ SHA1_CTX context;
+ uint8_t k_pad[64];
+ int i;
+
+ memset(k_pad, 0, sizeof k_pad);
+ memcpy(k_pad, key, key_len);
+ for (i = 0; i < 64; i++)
+ {
+ k_pad[i] ^= 0x36;
+ }
+
+ SHA1_Init(&context);
+ SHA1_Update(&context, k_pad, 64);
+ SHA1_Update(&context, msg, length);
+ SHA1_Final(digest, &context);
+
+ memset(k_pad, 0, sizeof k_pad);
+ memcpy(k_pad, key, key_len);
+ for (i = 0; i < 64; i++)
+ {
+ k_pad[i] ^= 0x5c;
+ }
+
+ SHA1_Init(&context);
+ SHA1_Update(&context, k_pad, 64);
+ SHA1_Update(&context, digest, SHA1_SIZE);
+ SHA1_Final(digest, &context);
+}
+
+/**
+ * Perform HMAC-SHA256
+ * NOTE: does not handle keys larger than the block size.
+ */
+void hmac_sha256(const uint8_t *msg, int length, const uint8_t *key,
+ int key_len, uint8_t *digest)
+{
+ SHA256_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;
+ }
+
+ SHA256_Init(&context);
+ SHA256_Update(&context, k_ipad, 64);
+ SHA256_Update(&context, msg, length);
+ SHA256_Final(digest, &context);
+ SHA256_Init(&context);
+ SHA256_Update(&context, k_opad, 64);
+ SHA256_Update(&context, digest, SHA256_SIZE);
+ SHA256_Final(digest, &context);
+}
+
diff --git a/circuitpython/lib/axtls/crypto/md5.c b/circuitpython/lib/axtls/crypto/md5.c
new file mode 100644
index 0000000..86534c8
--- /dev/null
+++ b/circuitpython/lib/axtls/crypto/md5.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * This file implements the MD5 algorithm as defined in RFC1321
+ */
+
+#include <string.h>
+#include "os_port.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)))
+
+/* Versions for size-optimized code. */
+#define IDX(v) ((v) & 3)
+#define F_(a, i) ((a[IDX(i + 1)] & a[IDX(i + 2)]) | (~a[IDX(i + 1)] & a[IDX(i + 3)]))
+#define G_(a, i) ((a[IDX(i + 1)] & a[IDX(i + 3)]) | (a[IDX(i + 2)] & ~a[IDX(i + 3)]))
+#define H_(a, i) (a[IDX(i + 1)] ^ a[IDX(i + 2)] ^ a[IDX(i + 3)])
+#define I_(a, i) (a[IDX(i + 2)] ^ (a[IDX(i + 1)] | ~a[IDX(i + 3)]))
+
+/* 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 MD5_Init(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 MD5_Update(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 MD5_Final(uint8_t *digest, MD5_CTX *ctx)
+{
+ 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);
+ MD5_Update(ctx, PADDING, padLen);
+
+ /* Append length (before padding) */
+ MD5_Update(ctx, bits, 8);
+
+ /* Store state in digest */
+ Encode(digest, ctx->state, MD5_SIZE);
+}
+
+/**
+ * MD5 basic transformation. Transforms state based on block.
+ */
+#if OPTIMIZE_FOR_SPEED
+
+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;
+}
+
+#else
+
+static void MD5Transform(uint32_t state[4], const uint8_t block[64])
+{
+ uint32_t arr[4], x[MD5_SIZE];
+ memcpy(arr, state, sizeof(arr));
+
+ Decode(x, block, 64);
+
+ static const uint32_t round_ac[] = {
+ 0xd76aa478, /* 1 */
+ 0xe8c7b756, /* 2 */
+ 0x242070db, /* 3 */
+ 0xc1bdceee, /* 4 */
+ 0xf57c0faf, /* 5 */
+ 0x4787c62a, /* 6 */
+ 0xa8304613, /* 7 */
+ 0xfd469501, /* 8 */
+ 0x698098d8, /* 9 */
+ 0x8b44f7af, /* 10 */
+ 0xffff5bb1, /* 11 */
+ 0x895cd7be, /* 12 */
+ 0x6b901122, /* 13 */
+ 0xfd987193, /* 14 */
+ 0xa679438e, /* 15 */
+ 0x49b40821, /* 16 */
+ 0xf61e2562, /* 17 */
+ 0xc040b340, /* 18 */
+ 0x265e5a51, /* 19 */
+ 0xe9b6c7aa, /* 20 */
+ 0xd62f105d, /* 21 */
+ 0x2441453, /* 22 */
+ 0xd8a1e681, /* 23 */
+ 0xe7d3fbc8, /* 24 */
+ 0x21e1cde6, /* 25 */
+ 0xc33707d6, /* 26 */
+ 0xf4d50d87, /* 27 */
+ 0x455a14ed, /* 28 */
+ 0xa9e3e905, /* 29 */
+ 0xfcefa3f8, /* 30 */
+ 0x676f02d9, /* 31 */
+ 0x8d2a4c8a, /* 32 */
+ 0xfffa3942, /* 33 */
+ 0x8771f681, /* 34 */
+ 0x6d9d6122, /* 35 */
+ 0xfde5380c, /* 36 */
+ 0xa4beea44, /* 37 */
+ 0x4bdecfa9, /* 38 */
+ 0xf6bb4b60, /* 39 */
+ 0xbebfbc70, /* 40 */
+ 0x289b7ec6, /* 41 */
+ 0xeaa127fa, /* 42 */
+ 0xd4ef3085, /* 43 */
+ 0x4881d05, /* 44 */
+ 0xd9d4d039, /* 45 */
+ 0xe6db99e5, /* 46 */
+ 0x1fa27cf8, /* 47 */
+ 0xc4ac5665, /* 48 */
+ 0xf4292244, /* 49 */
+ 0x432aff97, /* 50 */
+ 0xab9423a7, /* 51 */
+ 0xfc93a039, /* 52 */
+ 0x655b59c3, /* 53 */
+ 0x8f0ccc92, /* 54 */
+ 0xffeff47d, /* 55 */
+ 0x85845dd1, /* 56 */
+ 0x6fa87e4f, /* 57 */
+ 0xfe2ce6e0, /* 58 */
+ 0xa3014314, /* 59 */
+ 0x4e0811a1, /* 60 */
+ 0xf7537e82, /* 61 */
+ 0xbd3af235, /* 62 */
+ 0x2ad7d2bb, /* 63 */
+ 0xeb86d391, /* 64 */
+ };
+
+ static const uint8_t round1_s[] = {
+ 7, 12, 17, 22,
+ 5, 9, 14, 20,
+ 4, 11, 16, 23,
+ 6, 10, 15, 21,
+ };
+
+ static const uint8_t round_order[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12,
+ 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2,
+ 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9,
+ };
+
+ unsigned i;
+
+ const uint8_t *round_s = round1_s - 4;
+ for (i = 0; i < 64; i++) {
+ int off = IDX(4 - i);
+ uint32_t v;
+
+ // Code size is bigger
+ //round_s = round1_s + (i >> 4) * 4;
+ if ((i & 15) == 0) {
+ round_s += 4;
+ }
+
+ if (i < 32) {
+ if (i < 16) {
+ v = F_(arr, off);
+ } else {
+ v = G_(arr, off);
+ }
+ } else {
+ if (i < 48) {
+ v = H_(arr, off);
+ } else {
+ v = I_(arr, off);
+ }
+ }
+ v += arr[off];
+ v += x[round_order[i]] + round_ac[i];
+ v = ROTATE_LEFT(v, round_s[i & 3]);
+ v += arr[IDX(off + 1)];
+ arr[off] = v;
+ }
+
+ state[0] += arr[0];
+ state[1] += arr[1];
+ state[2] += arr[2];
+ state[3] += arr[3];
+}
+#endif // OPTIMIZE_FOR_SPEED
+
+/**
+ * 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);
+}
diff --git a/circuitpython/lib/axtls/crypto/os_int.h b/circuitpython/lib/axtls/crypto/os_int.h
new file mode 100644
index 0000000..a849e5b
--- /dev/null
+++ b/circuitpython/lib/axtls/crypto/os_int.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012-2016, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file os_int.h
+ *
+ * Ensure a consistent bit size
+ */
+
+#ifndef HEADER_OS_INT_H
+#define HEADER_OS_INT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(WIN32)
+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;
+#else /* Not Win32 */
+
+#ifdef CONFIG_PLATFORM_SOLARIS
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif /* Not Solaris */
+
+#endif /* Not Win32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/circuitpython/lib/axtls/crypto/rc4.c b/circuitpython/lib/axtls/crypto/rc4.c
new file mode 100644
index 0000000..edfb27a
--- /dev/null
+++ b/circuitpython/lib/axtls/crypto/rc4.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * An implementation of the RC4/ARC4 algorithm.
+ * Originally written by Christophe Devine.
+ */
+
+#include <string.h>
+#include "os_port.h"
+#include "crypto.h"
+
+/* only used for PKCS12 now */
+#ifdef CONFIG_SSL_USE_PKCS12
+
+/**
+ * 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, a;
+ uint8_t *m;
+
+ 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).
+ * NOTE: *msg and *out must be the same pointer (performance tweak)
+ */
+void RC4_crypt(RC4_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
+{
+ int i;
+ uint8_t *m, x, y, a, b;
+
+ x = ctx->x;
+ y = ctx->y;
+ m = ctx->m;
+
+ for (i = 0; i < length; i++)
+ {
+ a = m[++x];
+ y += a;
+ m[x] = b = m[y];
+ m[y] = a;
+ out[i] ^= m[(uint8_t)(a + b)];
+ }
+
+ ctx->x = x;
+ ctx->y = y;
+}
+
+#endif
diff --git a/circuitpython/lib/axtls/crypto/rsa.c b/circuitpython/lib/axtls/crypto/rsa.c
new file mode 100644
index 0000000..742cd71
--- /dev/null
+++ b/circuitpython/lib/axtls/crypto/rsa.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2007-2014, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Implements the RSA public encryption algorithm. Uses the bigint library to
+ * perform its calculations.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+#include "os_port.h"
+#include "crypto.h"
+
+void RSA_priv_key_new(RSA_CTX **ctx,
+ const uint8_t *modulus, int mod_len,
+ const uint8_t *pub_exp, int pub_len,
+ const uint8_t *priv_exp, int priv_len
+#if CONFIG_BIGINT_CRT
+ , const uint8_t *p, int p_len,
+ const uint8_t *q, int q_len,
+ const uint8_t *dP, int dP_len,
+ const uint8_t *dQ, int dQ_len,
+ const uint8_t *qInv, int qInv_len
+#endif
+ )
+{
+ RSA_CTX *rsa_ctx;
+ BI_CTX *bi_ctx;
+ RSA_pub_key_new(ctx, modulus, mod_len, pub_exp, pub_len);
+ rsa_ctx = *ctx;
+ bi_ctx = rsa_ctx->bi_ctx;
+ rsa_ctx->d = bi_import(bi_ctx, priv_exp, priv_len);
+ bi_permanent(rsa_ctx->d);
+
+#ifdef CONFIG_BIGINT_CRT
+ rsa_ctx->p = bi_import(bi_ctx, p, p_len);
+ rsa_ctx->q = bi_import(bi_ctx, q, q_len);
+ rsa_ctx->dP = bi_import(bi_ctx, dP, dP_len);
+ rsa_ctx->dQ = bi_import(bi_ctx, dQ, dQ_len);
+ rsa_ctx->qInv = bi_import(bi_ctx, qInv, qInv_len);
+ bi_permanent(rsa_ctx->dP);
+ bi_permanent(rsa_ctx->dQ);
+ bi_permanent(rsa_ctx->qInv);
+ bi_set_mod(bi_ctx, rsa_ctx->p, BIGINT_P_OFFSET);
+ bi_set_mod(bi_ctx, rsa_ctx->q, BIGINT_Q_OFFSET);
+#endif
+}
+
+void RSA_pub_key_new(RSA_CTX **ctx,
+ const uint8_t *modulus, int mod_len,
+ const uint8_t *pub_exp, int pub_len)
+{
+ RSA_CTX *rsa_ctx;
+ BI_CTX *bi_ctx;
+
+ if (*ctx) /* if we load multiple certs, dump the old one */
+ RSA_free(*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;
+ 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 decrypt (must be < modulus size-11)
+ * @param out_data [out] The decrypted data.
+ * @param out_len [int] The size of the decrypted buffer in bytes
+ * @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 out_len, int is_decryption)
+{
+ const int byte_size = ctx->num_octets;
+ int i = 0, size;
+ bigint *decrypted_bi, *dat_bi;
+ uint8_t *block = (uint8_t *)alloca(byte_size);
+ int pad_count = 0;
+
+ if (out_len < byte_size) /* check output has enough size */
+ return -1;
+
+ memset(out_data, 0, out_len); /* initialise */
+
+ /* decrypt */
+ dat_bi = bi_import(ctx->bi_ctx, in_data, byte_size);
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+ decrypted_bi = is_decryption ? /* decrypt or verify? */
+ RSA_private(ctx, dat_bi) : RSA_public(ctx, dat_bi);
+#else /* always a decryption */
+ decrypted_bi = RSA_private(ctx, dat_bi);
+#endif
+
+ /* convert to a normal block */
+ bi_export(ctx->bi_ctx, decrypted_bi, block, byte_size);
+
+ if (block[i++] != 0) /* leading 0? */
+ return -1;
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+ if (is_decryption == 0) /* PKCS1.5 signing pads with "0xff"s */
+ {
+ if (block[i++] != 0x01) /* BT correct? */
+ return -1;
+
+ while (block[i++] == 0xff && i < byte_size)
+ pad_count++;
+ }
+ else /* PKCS1.5 encryption padding is random */
+#endif
+ {
+ if (block[i++] != 0x02) /* BT correct? */
+ return -1;
+
+ while (block[i++] && i < byte_size)
+ pad_count++;
+ }
+
+ /* check separator byte 0x00 - and padding must be 8 or more bytes */
+ if (i == byte_size || pad_count < 8)
+ return -1;
+
+ size = byte_size - i;
+
+ /* get only the bit we want */
+ memcpy(out_data, &block[i], size);
+ return size;
+}
+
+/**
+ * Performs m = c^d mod n
+ */
+bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg)
+{
+#ifdef CONFIG_BIGINT_CRT
+ return bi_crt(c->bi_ctx, bi_msg, c->dP, c->dQ, c->p, c->q, c->qInv);
+#else
+ BI_CTX *ctx = c->bi_ctx;
+ ctx->mod_offset = BIGINT_M_OFFSET;
+ return bi_mod_power(ctx, bi_msg, c->d);
+#endif
+}
+
+#ifdef CONFIG_SSL_FULL_MODE
+/**
+ * Used for diagnostics.
+ */
+void RSA_print(const RSA_CTX *rsa_ctx)
+{
+ if (rsa_ctx == NULL)
+ return;
+
+ printf("----------------- RSA DEBUG ----------------\n");
+ printf("Size:\t%d\n", rsa_ctx->num_octets);
+ bi_print("Modulus", rsa_ctx->m);
+ bi_print("Public Key", rsa_ctx->e);
+ bi_print("Private Key", rsa_ctx->d);
+}
+#endif
+
+#if defined(CONFIG_SSL_CERT_VERIFICATION) || defined(CONFIG_SSL_GENERATE_X509_CERT) || (CONFIG_SSL_ENABLE_CLIENT)
+/**
+ * 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;
+ if (get_random_NZ(num_pads_needed, &out_data[2]) < 0)
+ return -1;
+ }
+
+ out_data[2+num_pads_needed] = 0;
+ memcpy(&out_data[3+num_pads_needed], in_data, in_len);
+
+ /* now encrypt it */
+ dat_bi = bi_import(ctx->bi_ctx, out_data, byte_size);
+ encrypt_bi = is_signing ? RSA_private(ctx, dat_bi) :
+ RSA_public(ctx, dat_bi);
+ bi_export(ctx->bi_ctx, encrypt_bi, out_data, byte_size);
+
+ /* save a few bytes of memory */
+ bi_clear_cache(ctx->bi_ctx);
+ return byte_size;
+}
+
+#endif /* CONFIG_SSL_CERT_VERIFICATION */
diff --git a/circuitpython/lib/axtls/crypto/sha1.c b/circuitpython/lib/axtls/crypto/sha1.c
new file mode 100644
index 0000000..097302a
--- /dev/null
+++ b/circuitpython/lib/axtls/crypto/sha1.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * SHA1 implementation - as defined in FIPS PUB 180-1 published April 17, 1995.
+ * This code was originally taken from RFC3174
+ */
+
+#include <string.h>
+#include "os_port.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 SHA1_Init(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 SHA1_Update(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 SHA1_Final(uint8_t *digest, SHA1_CTX *ctx)
+{
+ 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] = (uint32_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);
+}
diff --git a/circuitpython/lib/axtls/crypto/sha256.c b/circuitpython/lib/axtls/crypto/sha256.c
new file mode 100644
index 0000000..e15e315
--- /dev/null
+++ b/circuitpython/lib/axtls/crypto/sha256.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2015, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include "os_port.h"
+#include "crypto.h"
+
+#ifndef SHA256_CTX
+
+#define GET_UINT32(n,b,i) \
+{ \
+ (n) = ((uint32_t) (b)[(i) ] << 24) \
+ | ((uint32_t) (b)[(i) + 1] << 16) \
+ | ((uint32_t) (b)[(i) + 2] << 8) \
+ | ((uint32_t) (b)[(i) + 3] ); \
+}
+
+#define PUT_UINT32(n,b,i) \
+{ \
+ (b)[(i) ] = (uint8_t) ((n) >> 24); \
+ (b)[(i) + 1] = (uint8_t) ((n) >> 16); \
+ (b)[(i) + 2] = (uint8_t) ((n) >> 8); \
+ (b)[(i) + 3] = (uint8_t) ((n) ); \
+}
+
+static const uint8_t sha256_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
+};
+
+/**
+ * Initialize the SHA256 context
+ */
+void SHA256_Init(SHA256_CTX *ctx)
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x6A09E667;
+ ctx->state[1] = 0xBB67AE85;
+ ctx->state[2] = 0x3C6EF372;
+ ctx->state[3] = 0xA54FF53A;
+ ctx->state[4] = 0x510E527F;
+ ctx->state[5] = 0x9B05688C;
+ ctx->state[6] = 0x1F83D9AB;
+ ctx->state[7] = 0x5BE0CD19;
+}
+
+static void SHA256_Process(const uint8_t digest[64], SHA256_CTX *ctx)
+{
+ uint32_t temp1, temp2, W[64];
+ uint32_t A, B, C, D, E, F, G, H;
+
+ GET_UINT32(W[0], digest, 0);
+ GET_UINT32(W[1], digest, 4);
+ GET_UINT32(W[2], digest, 8);
+ GET_UINT32(W[3], digest, 12);
+ GET_UINT32(W[4], digest, 16);
+ GET_UINT32(W[5], digest, 20);
+ GET_UINT32(W[6], digest, 24);
+ GET_UINT32(W[7], digest, 28);
+ GET_UINT32(W[8], digest, 32);
+ GET_UINT32(W[9], digest, 36);
+ GET_UINT32(W[10], digest, 40);
+ GET_UINT32(W[11], digest, 44);
+ GET_UINT32(W[12], digest, 48);
+ GET_UINT32(W[13], digest, 52);
+ GET_UINT32(W[14], digest, 56);
+ GET_UINT32(W[15], digest, 60);
+
+#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
+
+#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
+#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
+
+#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
+#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
+
+#define F0(x,y,z) ((x & y) | (z & (x | y)))
+#define F1(x,y,z) (z ^ (x & (y ^ z)))
+
+#define R(t) \
+( \
+ W[t] = S1(W[t - 2]) + W[t - 7] + \
+ S0(W[t - 15]) + W[t - 16] \
+)
+
+#define P(a,b,c,d,e,f,g,h,x,K) \
+{ \
+ temp1 = h + S3(e) + F1(e,f,g) + K + x; \
+ temp2 = S2(a) + F0(a,b,c); \
+ d += temp1; h = temp1 + temp2; \
+}
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+ F = ctx->state[5];
+ G = ctx->state[6];
+ H = ctx->state[7];
+
+ P(A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98);
+ P(H, A, B, C, D, E, F, G, W[ 1], 0x71374491);
+ P(G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF);
+ P(F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5);
+ P(E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B);
+ P(D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1);
+ P(C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4);
+ P(B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5);
+ P(A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98);
+ P(H, A, B, C, D, E, F, G, W[ 9], 0x12835B01);
+ P(G, H, A, B, C, D, E, F, W[10], 0x243185BE);
+ P(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3);
+ P(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74);
+ P(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE);
+ P(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7);
+ P(B, C, D, E, F, G, H, A, W[15], 0xC19BF174);
+ P(A, B, C, D, E, F, G, H, R(16), 0xE49B69C1);
+ P(H, A, B, C, D, E, F, G, R(17), 0xEFBE4786);
+ P(G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6);
+ P(F, G, H, A, B, C, D, E, R(19), 0x240CA1CC);
+ P(E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F);
+ P(D, E, F, G, H, A, B, C, R(21), 0x4A7484AA);
+ P(C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC);
+ P(B, C, D, E, F, G, H, A, R(23), 0x76F988DA);
+ P(A, B, C, D, E, F, G, H, R(24), 0x983E5152);
+ P(H, A, B, C, D, E, F, G, R(25), 0xA831C66D);
+ P(G, H, A, B, C, D, E, F, R(26), 0xB00327C8);
+ P(F, G, H, A, B, C, D, E, R(27), 0xBF597FC7);
+ P(E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3);
+ P(D, E, F, G, H, A, B, C, R(29), 0xD5A79147);
+ P(C, D, E, F, G, H, A, B, R(30), 0x06CA6351);
+ P(B, C, D, E, F, G, H, A, R(31), 0x14292967);
+ P(A, B, C, D, E, F, G, H, R(32), 0x27B70A85);
+ P(H, A, B, C, D, E, F, G, R(33), 0x2E1B2138);
+ P(G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC);
+ P(F, G, H, A, B, C, D, E, R(35), 0x53380D13);
+ P(E, F, G, H, A, B, C, D, R(36), 0x650A7354);
+ P(D, E, F, G, H, A, B, C, R(37), 0x766A0ABB);
+ P(C, D, E, F, G, H, A, B, R(38), 0x81C2C92E);
+ P(B, C, D, E, F, G, H, A, R(39), 0x92722C85);
+ P(A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1);
+ P(H, A, B, C, D, E, F, G, R(41), 0xA81A664B);
+ P(G, H, A, B, C, D, E, F, R(42), 0xC24B8B70);
+ P(F, G, H, A, B, C, D, E, R(43), 0xC76C51A3);
+ P(E, F, G, H, A, B, C, D, R(44), 0xD192E819);
+ P(D, E, F, G, H, A, B, C, R(45), 0xD6990624);
+ P(C, D, E, F, G, H, A, B, R(46), 0xF40E3585);
+ P(B, C, D, E, F, G, H, A, R(47), 0x106AA070);
+ P(A, B, C, D, E, F, G, H, R(48), 0x19A4C116);
+ P(H, A, B, C, D, E, F, G, R(49), 0x1E376C08);
+ P(G, H, A, B, C, D, E, F, R(50), 0x2748774C);
+ P(F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5);
+ P(E, F, G, H, A, B, C, D, R(52), 0x391C0CB3);
+ P(D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A);
+ P(C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F);
+ P(B, C, D, E, F, G, H, A, R(55), 0x682E6FF3);
+ P(A, B, C, D, E, F, G, H, R(56), 0x748F82EE);
+ P(H, A, B, C, D, E, F, G, R(57), 0x78A5636F);
+ P(G, H, A, B, C, D, E, F, R(58), 0x84C87814);
+ P(F, G, H, A, B, C, D, E, R(59), 0x8CC70208);
+ P(E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA);
+ P(D, E, F, G, H, A, B, C, R(61), 0xA4506CEB);
+ P(C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7);
+ P(B, C, D, E, F, G, H, A, R(63), 0xC67178F2);
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+ ctx->state[5] += F;
+ ctx->state[6] += G;
+ ctx->state[7] += H;
+}
+
+/**
+ * Accepts an array of octets as the next portion of the message.
+ */
+void SHA256_Update(SHA256_CTX *ctx, const uint8_t * msg, int len)
+{
+ uint32_t left = ctx->total[0] & 0x3F;
+ uint32_t fill = 64 - left;
+
+ ctx->total[0] += len;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if (ctx->total[0] < len)
+ ctx->total[1]++;
+
+ if (left && len >= fill)
+ {
+ memcpy((void *) (ctx->buffer + left), (void *)msg, fill);
+ SHA256_Process(ctx->buffer, ctx);
+ len -= fill;
+ msg += fill;
+ left = 0;
+ }
+
+ while (len >= 64)
+ {
+ SHA256_Process(msg, ctx);
+ len -= 64;
+ msg += 64;
+ }
+
+ if (len)
+ {
+ memcpy((void *) (ctx->buffer + left), (void *) msg, len);
+ }
+}
+
+/**
+ * Return the 256-bit message digest into the user's array
+ */
+void SHA256_Final(uint8_t *digest, SHA256_CTX *ctx)
+{
+ uint32_t last, padn;
+ uint32_t high, low;
+ uint8_t msglen[8];
+
+ high = (ctx->total[0] >> 29)
+ | (ctx->total[1] << 3);
+ low = (ctx->total[0] << 3);
+
+ PUT_UINT32(high, msglen, 0);
+ PUT_UINT32(low, msglen, 4);
+
+ last = ctx->total[0] & 0x3F;
+ padn = (last < 56) ? (56 - last) : (120 - last);
+
+ SHA256_Update(ctx, sha256_padding, padn);
+ SHA256_Update(ctx, msglen, 8);
+
+ PUT_UINT32(ctx->state[0], digest, 0);
+ PUT_UINT32(ctx->state[1], digest, 4);
+ PUT_UINT32(ctx->state[2], digest, 8);
+ PUT_UINT32(ctx->state[3], digest, 12);
+ PUT_UINT32(ctx->state[4], digest, 16);
+ PUT_UINT32(ctx->state[5], digest, 20);
+ PUT_UINT32(ctx->state[6], digest, 24);
+ PUT_UINT32(ctx->state[7], digest, 28);
+}
+
+#endif // SHA256_CTX
diff --git a/circuitpython/lib/axtls/crypto/sha384.c b/circuitpython/lib/axtls/crypto/sha384.c
new file mode 100644
index 0000000..f1071be
--- /dev/null
+++ b/circuitpython/lib/axtls/crypto/sha384.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include "os_port.h"
+#include "crypto.h"
+
+/**
+* Initialize the SHA384 context
+*/
+ void SHA384_Init(SHA384_CTX *ctx)
+ {
+ //Set initial hash value
+ ctx->h_dig.h[0] = 0xCBBB9D5DC1059ED8LL;
+ ctx->h_dig.h[1] = 0x629A292A367CD507LL;
+ ctx->h_dig.h[2] = 0x9159015A3070DD17LL;
+ ctx->h_dig.h[3] = 0x152FECD8F70E5939LL;
+ ctx->h_dig.h[4] = 0x67332667FFC00B31LL;
+ ctx->h_dig.h[5] = 0x8EB44A8768581511LL;
+ ctx->h_dig.h[6] = 0xDB0C2E0D64F98FA7LL;
+ ctx->h_dig.h[7] = 0x47B5481DBEFA4FA4LL;
+
+ // Number of bytes in the buffer
+ ctx->size = 0;
+ // Total length of the message
+ ctx->totalSize = 0;
+ }
+
+/**
+* Accepts an array of octets as the next portion of the message.
+*/
+void SHA384_Update(SHA384_CTX *ctx, const uint8_t * msg, int len)
+{
+ // The function is defined in the exact same manner as SHA-512
+ SHA512_Update(ctx, msg, len);
+}
+
+/**
+* Return the 384-bit message digest into the user's array
+*/
+void SHA384_Final(uint8_t *digest, SHA384_CTX *ctx)
+{
+ // The function is defined in the exact same manner as SHA-512
+ SHA512_Final(NULL, ctx);
+
+ // Copy the resulting digest
+ if (digest != NULL)
+ memcpy(digest, ctx->h_dig.digest, SHA384_SIZE);
+}
+
diff --git a/circuitpython/lib/axtls/crypto/sha512.c b/circuitpython/lib/axtls/crypto/sha512.c
new file mode 100644
index 0000000..aa2f589
--- /dev/null
+++ b/circuitpython/lib/axtls/crypto/sha512.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2015, Cameron Rich
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include "os_port.h"
+#include "crypto.h"
+
+#define SHR64(a, n) ((a) >> (n))
+#define ROR64(a, n) (((a) >> (n)) | ((a) << (64 - (n))))
+#define CH(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define MAJ(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define SIGMA1(x) (ROR64(x, 28) ^ ROR64(x, 34) ^ ROR64(x, 39))
+#define SIGMA2(x) (ROR64(x, 14) ^ ROR64(x, 18) ^ ROR64(x, 41))
+#define SIGMA3(x) (ROR64(x, 1) ^ ROR64(x, 8) ^ SHR64(x, 7))
+#define SIGMA4(x) (ROR64(x, 19) ^ ROR64(x, 61) ^ SHR64(x, 6))
+#define MIN(x, y) ((x) < (y) ? x : y)
+
+static const uint8_t padding[128] =
+{
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const uint64_t k[80] =
+{
+ 0x428A2F98D728AE22LL, 0x7137449123EF65CDLL, 0xB5C0FBCFEC4D3B2FLL, 0xE9B5DBA58189DBBCLL,
+ 0x3956C25BF348B538LL, 0x59F111F1B605D019LL, 0x923F82A4AF194F9BLL, 0xAB1C5ED5DA6D8118LL,
+ 0xD807AA98A3030242LL, 0x12835B0145706FBELL, 0x243185BE4EE4B28CLL, 0x550C7DC3D5FFB4E2LL,
+ 0x72BE5D74F27B896FLL, 0x80DEB1FE3B1696B1LL, 0x9BDC06A725C71235LL, 0xC19BF174CF692694LL,
+ 0xE49B69C19EF14AD2LL, 0xEFBE4786384F25E3LL, 0x0FC19DC68B8CD5B5LL, 0x240CA1CC77AC9C65LL,
+ 0x2DE92C6F592B0275LL, 0x4A7484AA6EA6E483LL, 0x5CB0A9DCBD41FBD4LL, 0x76F988DA831153B5LL,
+ 0x983E5152EE66DFABLL, 0xA831C66D2DB43210LL, 0xB00327C898FB213FLL, 0xBF597FC7BEEF0EE4LL,
+ 0xC6E00BF33DA88FC2LL, 0xD5A79147930AA725LL, 0x06CA6351E003826FLL, 0x142929670A0E6E70LL,
+ 0x27B70A8546D22FFCLL, 0x2E1B21385C26C926LL, 0x4D2C6DFC5AC42AEDLL, 0x53380D139D95B3DFLL,
+ 0x650A73548BAF63DELL, 0x766A0ABB3C77B2A8LL, 0x81C2C92E47EDAEE6LL, 0x92722C851482353BLL,
+ 0xA2BFE8A14CF10364LL, 0xA81A664BBC423001LL, 0xC24B8B70D0F89791LL, 0xC76C51A30654BE30LL,
+ 0xD192E819D6EF5218LL, 0xD69906245565A910LL, 0xF40E35855771202ALL, 0x106AA07032BBD1B8LL,
+ 0x19A4C116B8D2D0C8LL, 0x1E376C085141AB53LL, 0x2748774CDF8EEB99LL, 0x34B0BCB5E19B48A8LL,
+ 0x391C0CB3C5C95A63LL, 0x4ED8AA4AE3418ACBLL, 0x5B9CCA4F7763E373LL, 0x682E6FF3D6B2B8A3LL,
+ 0x748F82EE5DEFB2FCLL, 0x78A5636F43172F60LL, 0x84C87814A1F0AB72LL, 0x8CC702081A6439ECLL,
+ 0x90BEFFFA23631E28LL, 0xA4506CEBDE82BDE9LL, 0xBEF9A3F7B2C67915LL, 0xC67178F2E372532BLL,
+ 0xCA273ECEEA26619CLL, 0xD186B8C721C0C207LL, 0xEADA7DD6CDE0EB1ELL, 0xF57D4F7FEE6ED178LL,
+ 0x06F067AA72176FBALL, 0x0A637DC5A2C898A6LL, 0x113F9804BEF90DAELL, 0x1B710B35131C471BLL,
+ 0x28DB77F523047D84LL, 0x32CAAB7B40C72493LL, 0x3C9EBE0A15C9BEBCLL, 0x431D67C49C100D4CLL,
+ 0x4CC5D4BECB3E42B6LL, 0x597F299CFC657E2ALL, 0x5FCB6FAB3AD6FAECLL, 0x6C44198C4A475817LL
+};
+
+/**
+* Initialize the SHA512 context
+*/
+void SHA512_Init(SHA512_CTX *ctx)
+{
+ ctx->h_dig.h[0] = 0x6A09E667F3BCC908LL;
+ ctx->h_dig.h[1] = 0xBB67AE8584CAA73BLL;
+ ctx->h_dig.h[2] = 0x3C6EF372FE94F82BLL;
+ ctx->h_dig.h[3] = 0xA54FF53A5F1D36F1LL;
+ ctx->h_dig.h[4] = 0x510E527FADE682D1LL;
+ ctx->h_dig.h[5] = 0x9B05688C2B3E6C1FLL;
+ ctx->h_dig.h[6] = 0x1F83D9ABFB41BD6BLL;
+ ctx->h_dig.h[7] = 0x5BE0CD19137E2179LL;
+ ctx->size = 0;
+ ctx->totalSize = 0;
+}
+
+static void SHA512_Process(SHA512_CTX *ctx)
+{
+ int t;
+ uint64_t temp1;
+ uint64_t temp2;
+
+ // Initialize the 8 working registers
+ uint64_t a = ctx->h_dig.h[0];
+ uint64_t b = ctx->h_dig.h[1];
+ uint64_t c = ctx->h_dig.h[2];
+ uint64_t d = ctx->h_dig.h[3];
+ uint64_t e = ctx->h_dig.h[4];
+ uint64_t f = ctx->h_dig.h[5];
+ uint64_t g = ctx->h_dig.h[6];
+ uint64_t h = ctx->h_dig.h[7];
+
+ // Process message in 16-word blocks
+ uint64_t *w = ctx->w_buf.w;
+
+ // Convert from big-endian byte order to host byte order
+ for (t = 0; t < 16; t++)
+ w[t] = be64toh(w[t]);
+
+ // Prepare the message schedule
+ for (t = 16; t < 80; t++)
+ w[t] = SIGMA4(w[t - 2]) + w[t - 7] + SIGMA3(w[t - 15]) + w[t - 16];
+
+ // SHA-512 hash computation
+ for (t = 0; t < 80; t++)
+ {
+ // Calculate T1 and T2
+ temp1 = h + SIGMA2(e) + CH(e, f, g) + k[t] + w[t];
+ temp2 = SIGMA1(a) + MAJ(a, b, c);
+
+ // Update the working registers
+ h = g;
+ g = f;
+ f = e;
+ e = d + temp1;
+ d = c;
+ c = b;
+ b = a;
+ a = temp1 + temp2;
+ }
+
+ // Update the hash value
+ ctx->h_dig.h[0] += a;
+ ctx->h_dig.h[1] += b;
+ ctx->h_dig.h[2] += c;
+ ctx->h_dig.h[3] += d;
+ ctx->h_dig.h[4] += e;
+ ctx->h_dig.h[5] += f;
+ ctx->h_dig.h[6] += g;
+ ctx->h_dig.h[7] += h;
+ }
+
+/**
+* Accepts an array of octets as the next portion of the message.
+*/
+void SHA512_Update(SHA512_CTX *ctx, const uint8_t * msg, int len)
+{
+ // Process the incoming data
+ while (len > 0)
+ {
+ // The buffer can hold at most 128 bytes
+ size_t n = MIN(len, 128 - ctx->size);
+
+ // Copy the data to the buffer
+ memcpy(ctx->w_buf.buffer + ctx->size, msg, n);
+
+ // Update the SHA-512 ctx
+ ctx->size += n;
+ ctx->totalSize += n;
+ // Advance the data pointer
+ msg = (uint8_t *) msg + n;
+ // Remaining bytes to process
+ len -= n;
+
+ // Process message in 16-word blocks
+ if (ctx->size == 128)
+ {
+ // Transform the 16-word block
+ SHA512_Process(ctx);
+ // Empty the buffer
+ ctx->size = 0;
+ }
+ }
+}
+
+/**
+* Return the 512-bit message digest into the user's array
+*/
+void SHA512_Final(uint8_t *digest, SHA512_CTX *ctx)
+{
+ int i;
+ size_t paddingSize;
+ uint64_t totalSize;
+
+ // Length of the original message (before padding)
+ totalSize = ctx->totalSize * 8;
+
+ // Pad the message so that its length is congruent to 112 modulo 128
+ paddingSize = (ctx->size < 112) ? (112 - ctx->size) :
+ (128 + 112 - ctx->size);
+ // Append padding
+ SHA512_Update(ctx, padding, paddingSize);
+
+ // Append the length of the original message
+ ctx->w_buf.w[14] = 0;
+ ctx->w_buf.w[15] = be64toh(totalSize);
+
+ // Calculate the message digest
+ SHA512_Process(ctx);
+
+ // Convert from host byte order to big-endian byte order
+ for (i = 0; i < 8; i++)
+ ctx->h_dig.h[i] = be64toh(ctx->h_dig.h[i]);
+
+ // Copy the resulting digest
+ if (digest != NULL)
+ memcpy(digest, ctx->h_dig.digest, SHA512_SIZE);
+ }
+