move from polarssl to mbedtls (#708)
authorOleg Moiseenko <807634+merlokk@users.noreply.github.com>
Mon, 19 Nov 2018 08:02:38 +0000 (10:02 +0200)
committerpwpiwi <pwpiwi@users.noreply.github.com>
Mon, 19 Nov 2018 08:02:38 +0000 (09:02 +0100)
* update polarssl to mbedtls
* fix a warning in armsrc/iso15693
* added random generator and ecdsa test
* added signature check to test
* move crypto lib to client directory

114 files changed:
.travis.yml [new file with mode: 0644]
client/Makefile
client/cmdhfmfp.c
client/cmdhfmfu.c
client/crypto/asn1utils.c [new file with mode: 0644]
client/crypto/asn1utils.h [new file with mode: 0644]
client/crypto/libpcrypto.c [new file with mode: 0644]
client/crypto/libpcrypto.h [new file with mode: 0644]
client/emv/crypto_polarssl.c
client/emv/test/cryptotest.c
client/mifare4.c
client/obj/crypto/.dummy [new file with mode: 0644]
client/scripting.c
common/mbedtls/Makefile [new file with mode: 0644]
common/mbedtls/aes.c [new file with mode: 0644]
common/mbedtls/aes.h [new file with mode: 0644]
common/mbedtls/arc4.c [new file with mode: 0644]
common/mbedtls/arc4.h [new file with mode: 0644]
common/mbedtls/asn1.h [new file with mode: 0644]
common/mbedtls/asn1parse.c [new file with mode: 0644]
common/mbedtls/asn1write.c [new file with mode: 0644]
common/mbedtls/asn1write.h [new file with mode: 0644]
common/mbedtls/base64.c [new file with mode: 0644]
common/mbedtls/base64.h [new file with mode: 0644]
common/mbedtls/bignum.c [new file with mode: 0644]
common/mbedtls/bignum.h [new file with mode: 0644]
common/mbedtls/blowfish.c [new file with mode: 0644]
common/mbedtls/blowfish.h [new file with mode: 0644]
common/mbedtls/bn_mul.h [new file with mode: 0644]
common/mbedtls/camellia.c [new file with mode: 0644]
common/mbedtls/camellia.h [new file with mode: 0644]
common/mbedtls/certs.c [new file with mode: 0644]
common/mbedtls/certs.h [new file with mode: 0644]
common/mbedtls/check_config.h [new file with mode: 0644]
common/mbedtls/cipher.c [new file with mode: 0644]
common/mbedtls/cipher.h [new file with mode: 0644]
common/mbedtls/cipher_internal.h [new file with mode: 0644]
common/mbedtls/cipher_wrap.c [new file with mode: 0644]
common/mbedtls/cmac.c [new file with mode: 0644]
common/mbedtls/cmac.h [new file with mode: 0644]
common/mbedtls/config.h [new file with mode: 0644]
common/mbedtls/ctr_drbg.c [new file with mode: 0644]
common/mbedtls/ctr_drbg.h [new file with mode: 0644]
common/mbedtls/des.c [new file with mode: 0644]
common/mbedtls/des.h [new file with mode: 0644]
common/mbedtls/ecdsa.c [new file with mode: 0644]
common/mbedtls/ecdsa.h [new file with mode: 0644]
common/mbedtls/ecp.c [new file with mode: 0644]
common/mbedtls/ecp.h [new file with mode: 0644]
common/mbedtls/ecp_curves.c [new file with mode: 0644]
common/mbedtls/ecp_internal.h [new file with mode: 0644]
common/mbedtls/entropy.c [new file with mode: 0644]
common/mbedtls/entropy.h [new file with mode: 0644]
common/mbedtls/entropy_poll.c [new file with mode: 0644]
common/mbedtls/entropy_poll.h [new file with mode: 0644]
common/mbedtls/error.c [new file with mode: 0644]
common/mbedtls/error.h [new file with mode: 0644]
common/mbedtls/md.c [new file with mode: 0644]
common/mbedtls/md.h [new file with mode: 0644]
common/mbedtls/md5.c [new file with mode: 0644]
common/mbedtls/md5.h [new file with mode: 0644]
common/mbedtls/md_internal.h [new file with mode: 0644]
common/mbedtls/md_wrap.c [new file with mode: 0644]
common/mbedtls/oid.c [new file with mode: 0644]
common/mbedtls/oid.h [new file with mode: 0644]
common/mbedtls/pem.c [new file with mode: 0644]
common/mbedtls/pem.h [new file with mode: 0644]
common/mbedtls/pk.c [new file with mode: 0644]
common/mbedtls/pk.h [new file with mode: 0644]
common/mbedtls/pk_internal.h [new file with mode: 0644]
common/mbedtls/pk_wrap.c [new file with mode: 0644]
common/mbedtls/pkcs12.c [new file with mode: 0644]
common/mbedtls/pkcs12.h [new file with mode: 0644]
common/mbedtls/pkcs5.c [new file with mode: 0644]
common/mbedtls/pkcs5.h [new file with mode: 0644]
common/mbedtls/pkparse.c [new file with mode: 0644]
common/mbedtls/platform.c [new file with mode: 0644]
common/mbedtls/platform.h [new file with mode: 0644]
common/mbedtls/platform_util.c [new file with mode: 0644]
common/mbedtls/platform_util.h [new file with mode: 0644]
common/mbedtls/rsa.c [new file with mode: 0644]
common/mbedtls/rsa.h [new file with mode: 0644]
common/mbedtls/rsa_internal.c [new file with mode: 0644]
common/mbedtls/rsa_internal.h [new file with mode: 0644]
common/mbedtls/sha1.c [new file with mode: 0644]
common/mbedtls/sha1.h [new file with mode: 0644]
common/mbedtls/sha256.c [new file with mode: 0644]
common/mbedtls/sha256.h [new file with mode: 0644]
common/mbedtls/sha512.c [new file with mode: 0644]
common/mbedtls/sha512.h [new file with mode: 0644]
common/mbedtls/threading.c [new file with mode: 0644]
common/mbedtls/threading.h [new file with mode: 0644]
common/mbedtls/timing.c [new file with mode: 0644]
common/mbedtls/timing.h [new file with mode: 0644]
common/mbedtls/x509.c [new file with mode: 0644]
common/mbedtls/x509.h [new file with mode: 0644]
common/mbedtls/x509_crl.c [new file with mode: 0644]
common/mbedtls/x509_crl.h [new file with mode: 0644]
common/mbedtls/x509_crt.c [new file with mode: 0644]
common/mbedtls/x509_crt.h [new file with mode: 0644]
common/polarssl/aes.c [deleted file]
common/polarssl/aes.h [deleted file]
common/polarssl/aes_cmac128.c [deleted file]
common/polarssl/aes_cmac128.h [deleted file]
common/polarssl/bignum.c [deleted file]
common/polarssl/bignum.h [deleted file]
common/polarssl/bn_mul.h [deleted file]
common/polarssl/libpcrypto.c [deleted file]
common/polarssl/libpcrypto.h [deleted file]
common/polarssl/rsa.c [deleted file]
common/polarssl/rsa.h [deleted file]
common/polarssl/sha1.c [deleted file]
common/polarssl/sha1.h [deleted file]
travis_test_commands.scr [new file with mode: 0644]

diff --git a/.travis.yml b/.travis.yml
new file mode 100644 (file)
index 0000000..f5fed7a
--- /dev/null
@@ -0,0 +1,55 @@
+# Travis-CI config
+# variable REPOSITORY_EP must be filled with repository name. as sample: "merlokk/proxmark3"
+language: c
+
+compiler: gcc
+
+# Test on Linux and MacOS
+matrix:
+  include:
+    - os: osx
+      osx_image: xcode7.3      # OS X 10.11
+    - os: osx
+      osx_image: xcode8.3   # OS X 10.12
+    - os: osx
+      osx_image: xcode9.4   # OS X 10.13
+    - os: osx
+      osx_image: xcode10    # OS X 10.13
+    - os: linux
+      dist: trusty
+      sudo: required
+
+before_install:
+## Install ARM toolchain on Linux.
+## add our homebrew tap for MacOS
+## Note: all dependencies on MacOS should be resolved by the brew install command
+  echo $REPOSITORY_EP;
+  if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then 
+    sudo apt-get update -qq;
+    sudo apt-get install -y gcc-arm-none-eabi;
+  elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
+    brew update;
+    if [[ "$REPOSITORY_EP" == "" ]]; then
+      brew tap proxmark/proxmark3;
+    else
+      brew tap "$REPOSITORY_EP" --env=std;
+    fi
+  fi
+
+install:
+  if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then 
+    brew info proxmark3;
+    brew install -v --HEAD proxmark3;
+  elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then 
+    make all;
+  fi
+
+before_script:
+
+script: 
+## for the time being we are satisfied if it can be build and then successfully started
+  if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then 
+    proxmark3 /dev/notexists travis_test_commands.scr ;
+  elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then 
+    ./client/proxmark3  /dev/notexists travis_test_commands.scr ;
+  fi
index 969eb2411b87b981626fc7b5640f1a30a9a673e8..bf884f1f14614628c6f613df212dfa93b02a0b28 100644 (file)
@@ -21,8 +21,10 @@ LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread -lm
 LUALIB = ../liblua/liblua.a
 JANSSONLIBPATH = ./jansson
 JANSSONLIB = $(JANSSONLIBPATH)/libjansson.a
+MBEDTLSLIBPATH = ../common/mbedtls
+MBEDTLSLIB = $(MBEDTLSLIBPATH)/libmbedtls.a
 LDFLAGS = $(ENV_LDFLAGS)
-CFLAGS = $(ENV_CFLAGS) -std=c99 -D_ISOC99_SOURCE -I. -I../include -I../common -I../common/polarssl -I../zlib -I../uart -I/opt/local/include -I../liblua -I$(JANSSONLIBPATH) -Wall -g -O3
+CFLAGS = $(ENV_CFLAGS) -std=c99 -D_ISOC99_SOURCE -I. -I../include -I../common -I../common/polarssl -I../zlib -I../uart -I/opt/local/include -I../liblua -I$(JANSSONLIBPATH) -I$(MBEDTLSLIBPATH) -Wall -g -O3
 CXXFLAGS = -I../include -Wall -O3
 
 APP_CFLAGS =
@@ -105,13 +107,9 @@ CORESRCS =         uart_posix.c \
 CMDSRCS =      $(SRC_SMARTCARD) \
                        crapto1/crapto1.c\
                        crapto1/crypto1.c\
-                       polarssl/des.c \
-                       polarssl/aes.c\
-                       polarssl/aes_cmac128.c\
-                       polarssl/bignum.c\
-                       polarssl/rsa.c\
-                       polarssl/sha1.c\
-                       polarssl/libpcrypto.c\
+                       polarssl/des.c\
+                       crypto/libpcrypto.c\
+                       crypto/asn1utils.c\
                        cliparser/argtable3.c\
                        cliparser/cliparser.c\
                        mfkey.c\
@@ -247,12 +245,12 @@ WINBINS = $(patsubst %, %.exe, $(BINS))
 CLEAN = $(BINS) $(WINBINS) $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(ZLIBOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(OBJDIR)/*.o *.moc.cpp ui/ui_overlays.h
 
 # need to assign dependancies to build these first...
-all: lua_build jansson_build $(BINS)
+all: lua_build jansson_build mbedtls_build $(BINS)
 
 all-static: LDLIBS:=-static $(LDLIBS)
 all-static: proxmark3 flasher fpga_compress
 
-proxmark3: LDLIBS+=$(LUALIB) $(JANSSONLIB) $(QTLDLIBS)
+proxmark3: LDLIBS+=$(LUALIB) $(JANSSONLIB) $(MBEDTLSLIB) $(QTLDLIBS)
 proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) lualibs/usb_cmd.lua
        $(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) $(LDLIBS) -o $@
 
@@ -277,6 +275,7 @@ clean:
        $(RM) $(CLEAN)
        cd ../liblua && make clean
        cd ./jansson && make clean
+       cd $(MBEDTLSLIBPATH) && make clean
 
 tarbin: $(BINS)
        $(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%) $(WINBINS:%=client/%)
@@ -288,6 +287,10 @@ lua_build:
 jansson_build:
        @echo Compiling jansson
        cd ./jansson && make all
+       
+mbedtls_build:
+       @echo Compiling mbedtls
+       cd $(MBEDTLSLIBPATH) && make all
 
 .PHONY: all clean
 
index 1ff24eb18f1815234e70f3d89f1ef4b1a7ef332f..1e5bbe1a5c400c0b5c72b9db242cea9696848f1f 100644 (file)
@@ -24,7 +24,7 @@
 #include "mifare.h"
 #include "mifare4.h"
 #include "cliparser/cliparser.h"
-#include "polarssl/libpcrypto.h"
+#include "crypto/libpcrypto.h"
 
 static const uint8_t DefaultKey[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
index 1077ec992fe9826e650ff4557fde8362c208f118..f167bae519602715656356ca6e0a57d33511cc4d 100644 (file)
@@ -16,7 +16,7 @@
 #include "usb_cmd.h"
 #include "cmdmain.h"
 #include "ui.h"
-#include "polarssl/des.h"
+#include "mbedtls/des.h"
 #include "cmdhfmf.h"
 #include "cmdhf14a.h"
 #include "mifare.h"
@@ -1742,11 +1742,11 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){
        mix[6] = block ^ uid[2];
        mix[7] = uid[3];
 
-       des3_context ctx = { 0x00 };
-       des3_set2key_enc(&ctx, masterkey);
+       mbedtls_des3_context ctx = { 0x00 };
+       mbedtls_des3_set2key_enc(&ctx, masterkey);
 
-       des3_crypt_cbc(&ctx  // des3_context
-               , DES_ENCRYPT    // int mode
+       mbedtls_des3_crypt_cbc(&ctx  // des3_context
+               , MBEDTLS_DES_ENCRYPT    // int mode
                , sizeof(mix)    // length
                , iv             // iv[8]
                , mix            // input
@@ -1781,10 +1781,10 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){
        memcpy(dmkey+16, dkeyA, 8);
        memset(iv, 0x00, 8);
 
-       des3_set3key_enc(&ctx, dmkey);
+       mbedtls_des3_set3key_enc(&ctx, dmkey);
 
-       des3_crypt_cbc(&ctx  // des3_context
-               , DES_ENCRYPT    // int mode
+       mbedtls_des3_crypt_cbc(&ctx  // des3_context
+               , MBEDTLS_DES_ENCRYPT    // int mode
                , sizeof(newpwd) // length
                , iv             // iv[8]
                , zeros         // input
diff --git a/client/crypto/asn1utils.c b/client/crypto/asn1utils.c
new file mode 100644 (file)
index 0000000..2a3fe69
--- /dev/null
@@ -0,0 +1,63 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2018 Merlok
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// asn.1 utils
+//-----------------------------------------------------------------------------
+
+#include "asn1utils.h"
+#include <mbedtls/asn1.h>
+
+int ecdsa_asn1_get_signature(uint8_t *signature, size_t signaturelen, uint8_t *rval, uint8_t *sval) {
+       if (!signature || !signaturelen || !rval || !sval)
+               return 1;
+
+       int res = 0;
+       unsigned char *p = signature;
+       const unsigned char *end = p + signaturelen;
+       size_t len;
+       mbedtls_mpi xmpi;
+
+       if ((res = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) == 0) {
+               mbedtls_mpi_init(&xmpi);
+               res = mbedtls_asn1_get_mpi(&p, end, &xmpi);
+               if (res) {
+                       mbedtls_mpi_free(&xmpi);
+                       goto exit;
+               }
+               
+               res = mbedtls_mpi_write_binary(&xmpi, rval, 32);
+               mbedtls_mpi_free(&xmpi);
+               if (res) 
+                       goto exit;
+
+               mbedtls_mpi_init(&xmpi);
+               res = mbedtls_asn1_get_mpi(&p, end, &xmpi);
+               if (res) {
+                       mbedtls_mpi_free(&xmpi);
+                       goto exit;
+               }
+               
+               res = mbedtls_mpi_write_binary(&xmpi, sval, 32);
+               mbedtls_mpi_free(&xmpi);
+               if (res) 
+                       goto exit;
+
+               // check size
+               if (end != p)
+                       return 2;
+               }
+
+exit:
+       return res;
+}
+
+int asn1_print(uint8_t *asn1buf, int level) {
+       
+       return 0;
+}
+
+
diff --git a/client/crypto/asn1utils.h b/client/crypto/asn1utils.h
new file mode 100644 (file)
index 0000000..2b00f45
--- /dev/null
@@ -0,0 +1,21 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2018 Merlok
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// asn.1 utils
+//-----------------------------------------------------------------------------
+
+#ifndef ASN1UTILS_H
+#define ASN1UTILS_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+extern int asn1_print(uint8_t *asn1buf, int level);
+extern int ecdsa_asn1_get_signature(uint8_t *signature, size_t signaturelen, uint8_t *rval, uint8_t *sval);
+
+#endif /* asn1utils.h */
diff --git a/client/crypto/libpcrypto.c b/client/crypto/libpcrypto.c
new file mode 100644 (file)
index 0000000..030be15
--- /dev/null
@@ -0,0 +1,381 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2018 Merlok
+// Copyright (C) 2018 drHatson
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// crypto commands
+//-----------------------------------------------------------------------------
+
+#include "crypto/libpcrypto.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <mbedtls/asn1.h>
+#include <mbedtls/aes.h>
+#include <mbedtls/cmac.h>
+#include <mbedtls/ecdsa.h>
+#include <mbedtls/sha256.h>
+#include <mbedtls/ctr_drbg.h>
+#include <mbedtls/entropy.h>
+#include <mbedtls/error.h>
+#include <crypto/asn1utils.h>
+#include <util.h>
+
+// NIST Special Publication 800-38A — Recommendation for block cipher modes of operation: methods and techniques, 2001.
+int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){
+       uint8_t iiv[16] = {0};
+       if (iv)
+               memcpy(iiv, iv, 16);
+       
+       mbedtls_aes_context aes;
+       mbedtls_aes_init(&aes);
+       if (mbedtls_aes_setkey_enc(&aes, key, 128))
+               return 1;
+       if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, length, iiv, input, output))
+               return 2;
+       mbedtls_aes_free(&aes);
+
+       return 0;
+}
+
+int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){
+       uint8_t iiv[16] = {0};
+       if (iv)
+               memcpy(iiv, iv, 16);
+       
+       mbedtls_aes_context aes;
+       mbedtls_aes_init(&aes);
+       if (mbedtls_aes_setkey_dec(&aes, key, 128))
+               return 1;
+       if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, length, iiv, input, output))
+               return 2;
+       mbedtls_aes_free(&aes);
+
+       return 0;
+}
+
+// NIST Special Publication 800-38B — Recommendation for block cipher modes of operation: The CMAC mode for authentication.
+// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CMAC.pdf
+int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length) {
+       memset(mac, 0x00, 16);
+       
+       //  NIST 800-38B 
+       return mbedtls_aes_cmac_prf_128(key, MBEDTLS_AES_BLOCK_SIZE, input, length, mac);
+}
+
+int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length) {
+       uint8_t cmac[16] = {0};
+       memset(mac, 0x00, 8);
+       
+       int res = aes_cmac(iv, key, input, cmac, length);
+       if (res)
+               return res;
+       
+       for(int i = 0; i < 8; i++) 
+               mac[i] = cmac[i * 2 + 1];
+
+       return 0;
+}
+
+static uint8_t fixed_rand_value[250] = {0};
+static int fixed_rand(void *rng_state, unsigned char *output, size_t len) {
+       if (len <= 250) {
+               memcpy(output, fixed_rand_value, len);
+       } else {
+               memset(output, 0x00, len);
+       }
+       
+       return 0;
+}
+
+int sha256hash(uint8_t *input, int length, uint8_t *hash) {
+       if (!hash || !input)
+               return 1;
+       
+       mbedtls_sha256_context sctx;
+       mbedtls_sha256_init(&sctx);
+       mbedtls_sha256_starts(&sctx, 0); // SHA-256, not 224 
+       mbedtls_sha256_update(&sctx, input, length);
+       mbedtls_sha256_finish(&sctx, hash);     
+       mbedtls_sha256_free(&sctx);
+       
+       return 0;
+}
+
+int ecdsa_init_str(mbedtls_ecdsa_context *ctx, char * key_d, char *key_x, char *key_y) {
+       if (!ctx)
+               return 1;
+       
+       int res;
+
+       mbedtls_ecdsa_init(ctx);
+       res = mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1); // secp256r1
+       if (res) 
+               return res;
+       
+       if (key_d) {
+               res = mbedtls_mpi_read_string(&ctx->d, 16, key_d);
+               if (res) 
+                       return res;
+       }
+       
+       if (key_x && key_y) {
+               res = mbedtls_ecp_point_read_string(&ctx->Q, 16, key_x, key_y);
+               if (res) 
+                       return res;
+       }
+       
+       return 0;
+}
+
+int ecdsa_init(mbedtls_ecdsa_context *ctx, uint8_t * key_d, uint8_t *key_xy) {
+       if (!ctx)
+               return 1;
+       
+       int res;
+
+       mbedtls_ecdsa_init(ctx);
+       res = mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1); // secp256r1
+       if (res) 
+               return res;
+       
+       if (key_d) {
+               res = mbedtls_mpi_read_binary(&ctx->d, key_d, 32);
+               if (res) 
+                       return res;
+       }
+       
+       if (key_xy) {
+               res = mbedtls_ecp_point_read_binary(&ctx->grp, &ctx->Q, key_xy, 32 * 2 + 1);
+               if (res) 
+                       return res;
+       }
+       
+       return 0;
+}
+
+int ecdsa_key_create(uint8_t * key_d, uint8_t *key_xy) {
+       int res;
+       mbedtls_ecdsa_context ctx;
+       ecdsa_init(&ctx, NULL, NULL);
+
+
+    mbedtls_entropy_context entropy;
+    mbedtls_ctr_drbg_context ctr_drbg;
+       const char *pers = "ecdsaproxmark";
+
+    mbedtls_entropy_init(&entropy);
+    mbedtls_ctr_drbg_init(&ctr_drbg);
+
+    res = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers));
+       if (res)
+        goto exit;
+
+    res = mbedtls_ecdsa_genkey(&ctx, MBEDTLS_ECP_DP_SECP256R1, mbedtls_ctr_drbg_random, &ctr_drbg);
+       if (res)
+               goto exit;
+
+       res = mbedtls_mpi_write_binary(&ctx.d, key_d, 32);
+       if (res)
+               goto exit;
+
+       size_t keylen = 0;
+       uint8_t public_key[200] = {0};
+       res = mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &keylen, public_key, sizeof(public_key));
+       if (res)
+               goto exit;
+       
+       if (keylen != 65) { // 0x04 <key x 32b><key y 32b>
+               res = 1;
+               goto exit;
+       }
+       memcpy(key_xy, public_key, 65);
+
+exit:
+    mbedtls_entropy_free(&entropy);
+    mbedtls_ctr_drbg_free(&ctr_drbg);
+       mbedtls_ecdsa_free(&ctx);
+       return res;
+}
+
+char *ecdsa_get_error(int ret) {
+       static char retstr[300];
+       memset(retstr, 0x00, sizeof(retstr));
+       mbedtls_strerror(ret, retstr, sizeof(retstr));
+       return retstr;
+}
+
+int ecdsa_signature_create(uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen) {
+       int res;
+       *signaturelen = 0;
+       
+       uint8_t shahash[32] = {0}; 
+       res = sha256hash(input, length, shahash);
+       if (res)
+               return res;
+
+    mbedtls_entropy_context entropy;
+    mbedtls_ctr_drbg_context ctr_drbg;
+       const char *pers = "ecdsaproxmark";
+
+    mbedtls_entropy_init(&entropy);
+    mbedtls_ctr_drbg_init(&ctr_drbg);
+
+    res = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers));
+       if (res)
+        goto exit;
+
+       mbedtls_ecdsa_context ctx;      
+       ecdsa_init(&ctx, key_d, key_xy);
+       res = mbedtls_ecdsa_write_signature(&ctx, MBEDTLS_MD_SHA256, shahash, sizeof(shahash), signature, signaturelen, mbedtls_ctr_drbg_random, &ctr_drbg);
+       
+exit:
+    mbedtls_ctr_drbg_free(&ctr_drbg);
+       mbedtls_ecdsa_free(&ctx);
+       return res;
+}
+
+int ecdsa_signature_create_test(char * key_d, char *key_x, char *key_y, char *random, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen) {
+       int res;
+       *signaturelen = 0;
+       
+       uint8_t shahash[32] = {0}; 
+       res = sha256hash(input, length, shahash);
+       if (res)
+               return res;
+
+       int rndlen = 0;
+       param_gethex_to_eol(random, 0, fixed_rand_value, sizeof(fixed_rand_value), &rndlen);
+       
+       mbedtls_ecdsa_context ctx;      
+       ecdsa_init_str(&ctx, key_d, key_x, key_y);
+       res = mbedtls_ecdsa_write_signature(&ctx, MBEDTLS_MD_SHA256, shahash, sizeof(shahash), signature, signaturelen, fixed_rand, NULL);
+       
+       mbedtls_ecdsa_free(&ctx);
+       return res;
+}
+
+int ecdsa_signature_verify_keystr(char *key_x, char *key_y, uint8_t *input, int length, uint8_t *signature, size_t signaturelen) {
+       int res;
+       uint8_t shahash[32] = {0}; 
+       res = sha256hash(input, length, shahash);
+       if (res)
+               return res;
+
+       mbedtls_ecdsa_context ctx;      
+       ecdsa_init_str(&ctx, NULL, key_x, key_y);
+       res = mbedtls_ecdsa_read_signature(&ctx, shahash, sizeof(shahash), signature, signaturelen);
+       
+       mbedtls_ecdsa_free(&ctx);
+       return res;
+}
+
+int ecdsa_signature_verify(uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t signaturelen) {
+       int res;
+       uint8_t shahash[32] = {0}; 
+       res = sha256hash(input, length, shahash);
+       if (res)
+               return res;
+
+       mbedtls_ecdsa_context ctx;      
+       ecdsa_init(&ctx, NULL, key_xy);
+       res = mbedtls_ecdsa_read_signature(&ctx, shahash, sizeof(shahash), signature, signaturelen);
+       
+       mbedtls_ecdsa_free(&ctx);
+       return res;
+}
+
+#define T_PRIVATE_KEY "C477F9F65C22CCE20657FAA5B2D1D8122336F851A508A1ED04E479C34985BF96"
+#define T_Q_X         "B7E08AFDFE94BAD3F1DC8C734798BA1C62B3A0AD1E9EA2A38201CD0889BC7A19"
+#define T_Q_Y         "3603F747959DBF7A4BB226E41928729063ADC7AE43529E61B563BBC606CC5E09"
+#define T_K           "7A1A7E52797FC8CAAA435D2A4DACE39158504BF204FBE19F14DBB427FAEE50AE"
+#define T_R           "2B42F576D07F4165FF65D1F3B1500F81E44C316F1F0B3EF57325B69ACA46104F"
+#define T_S           "DC42C2122D6392CD3E3A993A89502A8198C1886FE69D262C4B329BDB6B63FAF1"
+
+int ecdsa_nist_test(bool verbose) {
+       int res;
+       uint8_t input[] = "Example of ECDSA with P-256";
+       int length = strlen((char *)input);
+       uint8_t signature[300] = {0}; 
+       size_t siglen = 0; 
+
+       // NIST ecdsa test
+       if (verbose)
+               printf("  ECDSA NIST test: ");
+       // make signature
+       res = ecdsa_signature_create_test(T_PRIVATE_KEY, T_Q_X, T_Q_Y, T_K, input, length, signature, &siglen);
+//     printf("res: %x signature[%x]: %s\n", (res<0)?-res:res, siglen, sprint_hex(signature, siglen));
+       if (res) 
+               goto exit;
+
+       // check vectors
+       uint8_t rval[300] = {0}; 
+       uint8_t sval[300] = {0}; 
+       res = ecdsa_asn1_get_signature(signature, siglen, rval, sval);
+       if (res)
+               goto exit;
+       
+       int slen = 0;
+       uint8_t rval_s[33] = {0};
+       param_gethex_to_eol(T_R, 0, rval_s, sizeof(rval_s), &slen);
+       uint8_t sval_s[33] = {0}; 
+       param_gethex_to_eol(T_S, 0, sval_s, sizeof(sval_s), &slen);
+       if (strncmp((char *)rval, (char *)rval_s, 32) || strncmp((char *)sval, (char *)sval_s, 32)) {
+               printf("R or S check error\n");
+               res = 100;
+               goto exit;
+       }
+       
+       // verify signature
+       res = ecdsa_signature_verify_keystr(T_Q_X, T_Q_Y, input, length, signature, siglen);
+       if (res) 
+               goto exit;
+               
+       // verify wrong signature
+       input[0] ^= 0xFF;
+       res = ecdsa_signature_verify_keystr(T_Q_X, T_Q_Y, input, length, signature, siglen);
+       if (!res) {
+               res = 1;
+               goto exit;
+       }
+       if (verbose)
+               printf("passed\n");
+
+       // random ecdsa test
+       if (verbose)
+               printf("  ECDSA binary signature create/check test: ");
+
+       uint8_t key_d[32] = {0};
+       uint8_t key_xy[32 * 2 + 2] = {0};
+       memset(signature, 0x00, sizeof(signature));
+       siglen = 0;
+       
+       res = ecdsa_key_create(key_d, key_xy);
+       if (res) 
+               goto exit;
+
+       res = ecdsa_signature_create(key_d, key_xy, input, length, signature, &siglen);
+       if (res) 
+               goto exit;
+
+       res = ecdsa_signature_verify(key_xy, input, length, signature, siglen);
+       if (res) 
+               goto exit;
+
+       input[0] ^= 0xFF;
+       res = ecdsa_signature_verify(key_xy, input, length, signature, siglen);
+       if (!res) 
+               goto exit;
+       
+       if (verbose)
+               printf("passed\n\n");
+       
+       return 0;
+exit:
+       if (verbose)
+               printf("failed\n\n");
+       return res;
+}
diff --git a/client/crypto/libpcrypto.h b/client/crypto/libpcrypto.h
new file mode 100644 (file)
index 0000000..8d4b4a0
--- /dev/null
@@ -0,0 +1,32 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2018 Merlok
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// crypto commands
+//-----------------------------------------------------------------------------
+
+#ifndef LIBPCRYPTO_H
+#define LIBPCRYPTO_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+extern int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length);
+extern int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length);
+extern int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length);
+extern int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length);
+
+extern int sha256hash(uint8_t *input, int length, uint8_t *hash);
+
+extern int ecdsa_key_create(uint8_t * key_d, uint8_t *key_xy);
+extern int ecdsa_signature_create(uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen);
+extern int ecdsa_signature_verify(uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t signaturelen);
+extern char *ecdsa_get_error(int ret);
+
+extern int ecdsa_nist_test(bool verbose);
+
+#endif /* libpcrypto.h */
index 5a3db8eae4803f3e7f44dcb5620c110886e22132..9385350591278854cdd76b961ccbebbfc677dddb 100644 (file)
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
-#include "rsa.h"
-#include "sha1.h"
+#include "mbedtls/rsa.h"
+#include "mbedtls/sha1.h"
 
 struct crypto_hash_polarssl {
        struct crypto_hash ch;
-       sha1_context ctx;
+       mbedtls_sha1_context ctx;
 };
 
 static void crypto_hash_polarssl_close(struct crypto_hash *_ch)
@@ -44,7 +45,7 @@ static void crypto_hash_polarssl_write(struct crypto_hash *_ch, const unsigned c
 {
        struct crypto_hash_polarssl *ch = (struct crypto_hash_polarssl *)_ch;
 
-       sha1_update(&(ch->ctx), buf, len);
+       mbedtls_sha1_update(&(ch->ctx), buf, len);
 }
 
 static unsigned char *crypto_hash_polarssl_read(struct crypto_hash *_ch)
@@ -52,7 +53,7 @@ static unsigned char *crypto_hash_polarssl_read(struct crypto_hash *_ch)
        struct crypto_hash_polarssl *ch = (struct crypto_hash_polarssl *)_ch;
 
        static unsigned char sha1sum[20];
-       sha1_finish(&(ch->ctx), sha1sum);
+       mbedtls_sha1_finish(&(ch->ctx), sha1sum);
        return sha1sum;
 }
 
@@ -71,7 +72,7 @@ static struct crypto_hash *crypto_hash_polarssl_open(enum crypto_algo_hash hash)
 
        struct crypto_hash_polarssl *ch = malloc(sizeof(*ch));
 
-       sha1_starts(&(ch->ctx));
+       mbedtls_sha1_starts(&(ch->ctx));
 
        ch->ch.write = crypto_hash_polarssl_write;
        ch->ch.read = crypto_hash_polarssl_read;
@@ -83,7 +84,7 @@ static struct crypto_hash *crypto_hash_polarssl_open(enum crypto_algo_hash hash)
 
 struct crypto_pk_polarssl {
        struct crypto_pk cp;
-       rsa_context ctx;
+       mbedtls_rsa_context ctx;
 };
 
 static struct crypto_pk *crypto_pk_polarssl_open_rsa(va_list vl)
@@ -96,13 +97,13 @@ static struct crypto_pk *crypto_pk_polarssl_open_rsa(va_list vl)
        char *exp = va_arg(vl, char *);  // E
        int explen = va_arg(vl, size_t);
 
-       rsa_init(&cp->ctx, RSA_PKCS_V15, 0);
+       mbedtls_rsa_init(&cp->ctx, MBEDTLS_RSA_PKCS_V15, 0);
        
        cp->ctx.len = modlen; // size(N) in bytes
-       mpi_read_binary(&cp->ctx.N, (const unsigned char *)mod, modlen);
-       mpi_read_binary(&cp->ctx.E, (const unsigned char *)exp, explen);
+       mbedtls_mpi_read_binary(&cp->ctx.N, (const unsigned char *)mod, modlen);
+       mbedtls_mpi_read_binary(&cp->ctx.E, (const unsigned char *)exp, explen);
        
-       int res = rsa_check_pubkey(&cp->ctx);
+       int res = mbedtls_rsa_check_pubkey(&cp->ctx);
        if(res != 0) {
                fprintf(stderr, "PolarSSL public key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen);
                free(cp);
@@ -134,20 +135,20 @@ static struct crypto_pk *crypto_pk_polarssl_open_priv_rsa(va_list vl)
 //     char *inv = va_arg(vl, char *);
 //     int invlen = va_arg(vl, size_t);        
        
-       rsa_init(&cp->ctx, RSA_PKCS_V15, 0);
+       mbedtls_rsa_init(&cp->ctx, MBEDTLS_RSA_PKCS_V15, 0);
        
        cp->ctx.len = modlen; // size(N) in bytes
-       mpi_read_binary(&cp->ctx.N,  (const unsigned char *)mod, modlen);
-       mpi_read_binary(&cp->ctx.E,  (const unsigned char *)exp, explen);
-
-       mpi_read_binary(&cp->ctx.D,  (const unsigned char *)d, dlen);
-       mpi_read_binary(&cp->ctx.P,  (const unsigned char *)p, plen);
-       mpi_read_binary(&cp->ctx.Q,  (const unsigned char *)q, qlen);
-       mpi_read_binary(&cp->ctx.DP, (const unsigned char *)dp, dplen);
-       mpi_read_binary(&cp->ctx.DQ, (const unsigned char *)dq, dqlen);
-       mpi_inv_mod(&cp->ctx.QP, &cp->ctx.Q, &cp->ctx.P);
+       mbedtls_mpi_read_binary(&cp->ctx.N,  (const unsigned char *)mod, modlen);
+       mbedtls_mpi_read_binary(&cp->ctx.E,  (const unsigned char *)exp, explen);
+
+       mbedtls_mpi_read_binary(&cp->ctx.D,  (const unsigned char *)d, dlen);
+       mbedtls_mpi_read_binary(&cp->ctx.P,  (const unsigned char *)p, plen);
+       mbedtls_mpi_read_binary(&cp->ctx.Q,  (const unsigned char *)q, qlen);
+       mbedtls_mpi_read_binary(&cp->ctx.DP, (const unsigned char *)dp, dplen);
+       mbedtls_mpi_read_binary(&cp->ctx.DQ, (const unsigned char *)dq, dqlen);
+       mbedtls_mpi_inv_mod(&cp->ctx.QP, &cp->ctx.Q, &cp->ctx.P);
        
-       int res = rsa_check_privkey(&cp->ctx);
+       int res = mbedtls_rsa_check_privkey(&cp->ctx);
        if(res != 0) {
                fprintf(stderr, "PolarSSL private key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen);
                free(cp);
@@ -182,7 +183,7 @@ static struct crypto_pk *crypto_pk_polarssl_genkey_rsa(va_list vl)
        if (transient) {
        }
        
-       int res = rsa_gen_key(&cp->ctx, &myrand, NULL, nbits, exp);
+       int res = mbedtls_rsa_gen_key(&cp->ctx, &myrand, NULL, nbits, exp);
        if (res) {
                fprintf(stderr, "PolarSSL private key generation error res=%x exp=%d nbits=%d.\n", res * -1, exp, nbits);
                free(cp);
@@ -196,7 +197,7 @@ static void crypto_pk_polarssl_close(struct crypto_pk *_cp)
 {
        struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp;
 
-       rsa_free(&cp->ctx);
+       mbedtls_rsa_free(&cp->ctx);
        free(cp);
 }
 
@@ -207,7 +208,7 @@ static unsigned char *crypto_pk_polarssl_encrypt(const struct crypto_pk *_cp, co
        unsigned char *result;
        
        *clen = 0;
-       size_t keylen = mpi_size(&cp->ctx.N);
+       size_t keylen = mbedtls_mpi_size(&cp->ctx.N);
 
        result = malloc(keylen);
        if (!result) {
@@ -215,7 +216,7 @@ static unsigned char *crypto_pk_polarssl_encrypt(const struct crypto_pk *_cp, co
                return NULL;
        }
 
-       res = rsa_public(&cp->ctx, buf, result);
+       res = mbedtls_rsa_public(&cp->ctx, buf, result);
        if(res) {
                printf("RSA encrypt failed. Error: %x data len: %zd key len: %zd\n", res * -1, len, keylen);
                free(result);
@@ -234,7 +235,7 @@ static unsigned char *crypto_pk_polarssl_decrypt(const struct crypto_pk *_cp, co
        unsigned char *result;
        
        *clen = 0;
-       size_t keylen = mpi_size(&cp->ctx.N);
+       size_t keylen = mbedtls_mpi_size(&cp->ctx.N);
 
        result = malloc(keylen);
        if (!result) {
@@ -242,7 +243,7 @@ static unsigned char *crypto_pk_polarssl_decrypt(const struct crypto_pk *_cp, co
                return NULL;
        }
 
-       res = rsa_private(&cp->ctx, buf, result); // CHECK???
+       res = mbedtls_rsa_private(&cp->ctx, NULL, NULL, buf, result); // CHECK???
        if(res) {
                printf("RSA decrypt failed. Error: %x data len: %zd key len: %zd\n", res * -1, len, keylen);
                free(result);
@@ -269,17 +270,17 @@ static unsigned char *crypto_pk_polarssl_get_parameter(const struct crypto_pk *_
        switch(param){
                // mod
                case 0:
-                       *plen = mpi_size(&cp->ctx.N);
+                       *plen = mbedtls_mpi_size(&cp->ctx.N);
                        result = malloc(*plen);
                        memset(result, 0x00, *plen);
-                       mpi_write_binary(&cp->ctx.N, result, *plen);
+                       mbedtls_mpi_write_binary(&cp->ctx.N, result, *plen);
                        break;
                // exp
                case 1:
-                       *plen = mpi_size(&cp->ctx.E);
+                       *plen = mbedtls_mpi_size(&cp->ctx.E);
                        result = malloc(*plen);
                        memset(result, 0x00, *plen);
-                       mpi_write_binary(&cp->ctx.E, result, *plen);
+                       mbedtls_mpi_write_binary(&cp->ctx.E, result, *plen);
                        break;
                default:
                        printf("Error get parameter. Param=%d", param);
index b778d25629748d16837fde06e4d060e6bedd97a3..1d5891fe06cae649f3166b710cdd3642de17ce2c 100644 (file)
 #include "util.h"
 #include "ui.h"
 
-#include "bignum.h"
-#include "aes.h"
-#include "aes_cmac128.h"
-#include "des.h"
-#include "rsa.h"
-#include "sha1.h"
+#include "mbedtls/bignum.h"
+#include "mbedtls/aes.h"
+#include "mbedtls/cmac.h"
+#include "mbedtls/des.h"
+#include "mbedtls/ecp.h"
+#include "mbedtls/rsa.h"
+#include "mbedtls/sha1.h"
+#include "mbedtls/md5.h"
+#include "mbedtls/x509.h"
+#include "mbedtls/base64.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/timing.h"
 
 #include "crypto_test.h"
 #include "sda_test.h"
 #include "dda_test.h"
 #include "cda_test.h"
+#include "crypto/libpcrypto.h"
 
 int ExecuteCryptoTests(bool verbose) {
        int res;
        bool TestFail = false;
        
-       res = mpi_self_test(verbose);
+       res = mbedtls_mpi_self_test(verbose);
        if (res) TestFail = true;
        
-       res = aes_self_test(verbose);
+       res = mbedtls_aes_self_test(verbose);
        if (res) TestFail = true;
 
-       res = aes_cmac_self_test(verbose);
+       res = mbedtls_des_self_test(verbose);
+       if (res) TestFail = true;
+       
+       res = mbedtls_sha1_self_test(verbose);
        if (res) TestFail = true;
 
-       res = des_self_test(verbose);
+       res = mbedtls_md5_self_test(verbose);
+       if (res) TestFail = true;
+       
+       res = mbedtls_rsa_self_test(verbose);
        if (res) TestFail = true;
        
-       res = sha1_self_test(verbose);
+       res = mbedtls_entropy_self_test(verbose);
+       if (res) TestFail = true;
+
+       res = mbedtls_timing_self_test(verbose);
+       if (res) TestFail = true;
+
+       res = mbedtls_ctr_drbg_self_test(verbose);
        if (res) TestFail = true;
        
-       res = rsa_self_test(verbose);
+       res = mbedtls_base64_self_test(verbose);
+       if (res) TestFail = true;
+
+       res = mbedtls_cmac_self_test(verbose);
+       if (res) TestFail = true;
+
+       res = ecdsa_nist_test(verbose);
+       if (res) TestFail = true;
+
+       res = mbedtls_ecp_self_test(verbose);
+       if (res) TestFail = true;
+
+       res = mbedtls_x509_self_test(verbose);
        if (res) TestFail = true;
        
        res = exec_sda_test(verbose);
index 866e854f9ce50f58cda52895f338d68322fb8ec1..069c54d4937a23d682cc427936900b7badd32f74 100644 (file)
@@ -15,7 +15,7 @@
 #include "cmdhf14a.h"
 #include "util.h"
 #include "ui.h"
-#include "polarssl/libpcrypto.h"
+#include "crypto/libpcrypto.h"
 
 int CalculateEncIVCommand(mf4Session *session, uint8_t *iv, bool verbose) {
        memcpy(&iv[0], session->TI, 4);
diff --git a/client/obj/crypto/.dummy b/client/obj/crypto/.dummy
new file mode 100644 (file)
index 0000000..e69de29
index 232da889703618914bd8e4ec73fcacb0332d559a..ed7ae007c63a854ceceb4cee8908d33780336ec5 100644 (file)
@@ -24,8 +24,8 @@
 #include "iso14443crc.h"
 #include "../common/crc16.h"
 #include "../common/crc64.h"
-#include "../common/polarssl/sha1.h"
-#include "../common/polarssl/aes.h"
+#include <mbedtls/sha1.h>
+#include <mbedtls/aes.h>
 
 /**
  * The following params expected:
@@ -257,10 +257,10 @@ static int l_aes128decrypt_cbc(lua_State *L)
                sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
        }
 
-       aes_context ctx;
-       aes_init(&ctx);
-       aes_setkey_dec(&ctx, aes_key, 128);
-       aes_crypt_cbc(&ctx,AES_DECRYPT,sizeof(indata), iv, indata,outdata );
+       mbedtls_aes_context ctx;
+       mbedtls_aes_init(&ctx);
+       mbedtls_aes_setkey_dec(&ctx, aes_key, 128);
+       mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, sizeof(indata), iv, indata,outdata );
        //Push decrypted array as a string
        lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
        return 1;// return 1 to signal one return value
@@ -284,10 +284,10 @@ static int l_aes128decrypt_ecb(lua_State *L)
                sscanf(&p_encTxt[i], "%02x", (unsigned int *)&indata[i / 2]);
                sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
        }
-       aes_context ctx;
-       aes_init(&ctx);
-       aes_setkey_dec(&ctx, aes_key, 128);
-       aes_crypt_ecb(&ctx, AES_DECRYPT, indata, outdata );
+       mbedtls_aes_context ctx;
+       mbedtls_aes_init(&ctx);
+       mbedtls_aes_setkey_dec(&ctx, aes_key, 128);
+       mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_DECRYPT, indata, outdata );
 
        //Push decrypted array as a string
        lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
@@ -314,10 +314,10 @@ static int l_aes128encrypt_cbc(lua_State *L)
                sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
        }
 
-       aes_context ctx;
-       aes_init(&ctx);
-       aes_setkey_enc(&ctx, aes_key, 128);
-       aes_crypt_cbc(&ctx, AES_ENCRYPT, sizeof(indata), iv, indata, outdata );
+       mbedtls_aes_context ctx;
+       mbedtls_aes_init(&ctx);
+       mbedtls_aes_setkey_enc(&ctx, aes_key, 128);
+       mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, sizeof(indata), iv, indata, outdata );
        //Push encrypted array as a string
        lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
        return 1;// return 1 to signal one return value
@@ -341,10 +341,10 @@ static int l_aes128encrypt_ecb(lua_State *L)
                sscanf(&p_txt[i], "%02x", (unsigned int *)&indata[i / 2]);
                sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
        }
-       aes_context ctx;
-       aes_init(&ctx);
-       aes_setkey_enc(&ctx, aes_key, 128);
-       aes_crypt_ecb(&ctx, AES_ENCRYPT, indata, outdata );
+       mbedtls_aes_context ctx;
+       mbedtls_aes_init(&ctx);
+       mbedtls_aes_setkey_enc(&ctx, aes_key, 128);
+       mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, indata, outdata );
        //Push encrypted array as a string
        lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
        return 1;// return 1 to signal one return value
@@ -387,7 +387,7 @@ static int l_sha1(lua_State *L)
        size_t size;
        const char *p_str = luaL_checklstring(L, 1, &size);
        unsigned char outdata[20] = {0x00};
-       sha1( (uint8_t*) p_str, size, outdata);
+       mbedtls_sha1( (uint8_t*) p_str, size, outdata);
        lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
        return 1;
 }
diff --git a/common/mbedtls/Makefile b/common/mbedtls/Makefile
new file mode 100644 (file)
index 0000000..3e57fda
--- /dev/null
@@ -0,0 +1,86 @@
+
+LIB_A = libmbedtls.a
+mbedtls_SOURCES = \
+       aes.c \
+       asn1parse.c \
+       asn1write.c \
+       base64.c \
+       bignum.c \
+       ctr_drbg.c \
+       entropy_poll.c \
+       entropy.c \
+       error.c \
+       timing.c \
+       ecp.c \
+       ecp_curves.c \
+       certs.c \
+       camellia.c \
+       blowfish.c \
+       cipher_wrap.c \
+       cipher.c \
+       cmac.c \
+       des.c \
+       ecdsa.c \
+       md.c \
+       md_wrap.c \
+       md5.c \
+       oid.c \
+       pem.c \
+       arc4.c \
+       pk.c \
+       pk_wrap.c \
+       pkcs5.c \
+       pkcs12.c \
+       pkparse.c \
+       platform.c \
+       platform_util.c \
+       rsa.c \
+       rsa_internal.c \
+       sha1.c \
+       sha256.c \
+       sha512.c \
+       threading.c \
+       x509.c \
+       x509_crl.c \
+       x509_crt.c
+mbedtls_LDFLAGS = \
+       -no-undefined \
+       -export-symbols-regex '^mbedtls_' \
+       -version-info 15:0:11
+
+       
+CFILES = $(filter %.c, $(mbedtls_SOURCES))
+CMDOBJS = $(CFILES:%.c=%.o)
+CLEAN = $(CMDOBJS)
+       
+CC= gcc
+CFLAGS= -O2 -Wall -Wno-unused-variable -Wno-unused-function
+LDFLAGS= $(SYSLDFLAGS) $(mbedtls_LDFLAGS)
+LIBS= -lm $(SYSLIBS) $(MYLIBS)
+DEFAULT_INCLUDES = -I. -I..
+DEFS = -DHAVE_STDINT_H
+
+AR= ar rcs
+RANLIB= ranlib
+RM= rm -f
+TST= echo
+
+SYSLDFLAGS=
+SYSLIBS=
+
+MYLIBS=
+MYOBJS=
+
+all: $(CMDOBJS)
+       $(AR) $(LIB_A) $(CMDOBJS)
+       $(RANLIB) $(LIB_A)
+       
+clean:
+       $(RM) $(CLEAN)
+       $(RM) $(LIB_A)
+       
+%.o: %.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(CFLAGS) -c -o $@ $< $(LIBS)
+       
+.PHONY: all clean
+
diff --git a/common/mbedtls/aes.c b/common/mbedtls/aes.c
new file mode 100644 (file)
index 0000000..07391ec
--- /dev/null
@@ -0,0 +1,2125 @@
+/*
+ *  FIPS-197 compliant AES implementation
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: GPL-2.0
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+/*
+ *  The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
+ *
+ *  http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
+ *  http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_AES_C)
+
+#include <string.h>
+
+#include "mbedtls/aes.h"
+#include "mbedtls/platform_util.h"
+#if defined(MBEDTLS_PADLOCK_C)
+#include "mbedtls/padlock.h"
+#endif
+#if defined(MBEDTLS_AESNI_C)
+#include "mbedtls/aesni.h"
+#endif
+
+#if defined(MBEDTLS_SELF_TEST)
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#define mbedtls_printf printf
+#endif /* MBEDTLS_PLATFORM_C */
+#endif /* MBEDTLS_SELF_TEST */
+
+#if !defined(MBEDTLS_AES_ALT)
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_UINT32_LE
+#define GET_UINT32_LE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ]       )             \
+        | ( (uint32_t) (b)[(i) + 1] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 2] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 3] << 24 );            \
+}
+#endif
+
+#ifndef PUT_UINT32_LE
+#define PUT_UINT32_LE(n,b,i)                                    \
+{                                                               \
+    (b)[(i)    ] = (unsigned char) ( ( (n)       ) & 0xFF );    \
+    (b)[(i) + 1] = (unsigned char) ( ( (n) >>  8 ) & 0xFF );    \
+    (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF );    \
+    (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF );    \
+}
+#endif
+
+#if defined(MBEDTLS_PADLOCK_C) &&                      \
+    ( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) )
+static int aes_padlock_ace = -1;
+#endif
+
+#if defined(MBEDTLS_AES_ROM_TABLES)
+/*
+ * Forward S-box
+ */
+static const unsigned char FSb[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
+};
+
+/*
+ * Forward tables
+ */
+#define FT \
+\
+    V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \
+    V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \
+    V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \
+    V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \
+    V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \
+    V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \
+    V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \
+    V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \
+    V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \
+    V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \
+    V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \
+    V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \
+    V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \
+    V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \
+    V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \
+    V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \
+    V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \
+    V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \
+    V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \
+    V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \
+    V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \
+    V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \
+    V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \
+    V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \
+    V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \
+    V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \
+    V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \
+    V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \
+    V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \
+    V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \
+    V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \
+    V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \
+    V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \
+    V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \
+    V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \
+    V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \
+    V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \
+    V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \
+    V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \
+    V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \
+    V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \
+    V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \
+    V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \
+    V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \
+    V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \
+    V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \
+    V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \
+    V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \
+    V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \
+    V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \
+    V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \
+    V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \
+    V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \
+    V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \
+    V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \
+    V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \
+    V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \
+    V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \
+    V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \
+    V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \
+    V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \
+    V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \
+    V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \
+    V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static const uint32_t FT0[256] = { FT };
+#undef V
+
+#if !defined(MBEDTLS_AES_FEWER_TABLES)
+
+#define V(a,b,c,d) 0x##b##c##d##a
+static const uint32_t FT1[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+static const uint32_t FT2[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static const uint32_t FT3[256] = { FT };
+#undef V
+
+#endif /* !MBEDTLS_AES_FEWER_TABLES */
+
+#undef FT
+
+/*
+ * Reverse S-box
+ */
+static const unsigned char RSb[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
+};
+
+/*
+ * Reverse tables
+ */
+#define RT \
+\
+    V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \
+    V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \
+    V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \
+    V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \
+    V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \
+    V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \
+    V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \
+    V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \
+    V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \
+    V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \
+    V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \
+    V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \
+    V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \
+    V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \
+    V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \
+    V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \
+    V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \
+    V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \
+    V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \
+    V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \
+    V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \
+    V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \
+    V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \
+    V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \
+    V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \
+    V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \
+    V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \
+    V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \
+    V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \
+    V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \
+    V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \
+    V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \
+    V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \
+    V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \
+    V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \
+    V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \
+    V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \
+    V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \
+    V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \
+    V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \
+    V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \
+    V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \
+    V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \
+    V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \
+    V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \
+    V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \
+    V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \
+    V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \
+    V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \
+    V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \
+    V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \
+    V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \
+    V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \
+    V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \
+    V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \
+    V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \
+    V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \
+    V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \
+    V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \
+    V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \
+    V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \
+    V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \
+    V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \
+    V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static const uint32_t RT0[256] = { RT };
+#undef V
+
+#if !defined(MBEDTLS_AES_FEWER_TABLES)
+
+#define V(a,b,c,d) 0x##b##c##d##a
+static const uint32_t RT1[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+static const uint32_t RT2[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static const uint32_t RT3[256] = { RT };
+#undef V
+
+#endif /* !MBEDTLS_AES_FEWER_TABLES */
+
+#undef RT
+
+/*
+ * Round constants
+ */
+static const uint32_t RCON[10] =
+{
+    0x00000001, 0x00000002, 0x00000004, 0x00000008,
+    0x00000010, 0x00000020, 0x00000040, 0x00000080,
+    0x0000001B, 0x00000036
+};
+
+#else /* MBEDTLS_AES_ROM_TABLES */
+
+/*
+ * Forward S-box & tables
+ */
+static unsigned char FSb[256];
+static uint32_t FT0[256];
+#if !defined(MBEDTLS_AES_FEWER_TABLES)
+static uint32_t FT1[256];
+static uint32_t FT2[256];
+static uint32_t FT3[256];
+#endif /* !MBEDTLS_AES_FEWER_TABLES */
+
+/*
+ * Reverse S-box & tables
+ */
+static unsigned char RSb[256];
+static uint32_t RT0[256];
+#if !defined(MBEDTLS_AES_FEWER_TABLES)
+static uint32_t RT1[256];
+static uint32_t RT2[256];
+static uint32_t RT3[256];
+#endif /* !MBEDTLS_AES_FEWER_TABLES */
+
+/*
+ * Round constants
+ */
+static uint32_t RCON[10];
+
+/*
+ * Tables generation code
+ */
+#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )
+#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
+#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )
+
+static int aes_init_done = 0;
+
+static void aes_gen_tables( void )
+{
+    int i, x, y, z;
+    int pow[256];
+    int log[256];
+
+    /*
+     * compute pow and log tables over GF(2^8)
+     */
+    for( i = 0, x = 1; i < 256; i++ )
+    {
+        pow[i] = x;
+        log[x] = i;
+        x = ( x ^ XTIME( x ) ) & 0xFF;
+    }
+
+    /*
+     * calculate the round constants
+     */
+    for( i = 0, x = 1; i < 10; i++ )
+    {
+        RCON[i] = (uint32_t) x;
+        x = XTIME( x ) & 0xFF;
+    }
+
+    /*
+     * generate the forward and reverse S-boxes
+     */
+    FSb[0x00] = 0x63;
+    RSb[0x63] = 0x00;
+
+    for( i = 1; i < 256; i++ )
+    {
+        x = pow[255 - log[i]];
+
+        y  = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
+        x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
+        x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
+        x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
+        x ^= y ^ 0x63;
+
+        FSb[i] = (unsigned char) x;
+        RSb[x] = (unsigned char) i;
+    }
+
+    /*
+     * generate the forward and reverse tables
+     */
+    for( i = 0; i < 256; i++ )
+    {
+        x = FSb[i];
+        y = XTIME( x ) & 0xFF;
+        z =  ( y ^ x ) & 0xFF;
+
+        FT0[i] = ( (uint32_t) y       ) ^
+                 ( (uint32_t) x <<  8 ) ^
+                 ( (uint32_t) x << 16 ) ^
+                 ( (uint32_t) z << 24 );
+
+#if !defined(MBEDTLS_AES_FEWER_TABLES)
+        FT1[i] = ROTL8( FT0[i] );
+        FT2[i] = ROTL8( FT1[i] );
+        FT3[i] = ROTL8( FT2[i] );
+#endif /* !MBEDTLS_AES_FEWER_TABLES */
+
+        x = RSb[i];
+
+        RT0[i] = ( (uint32_t) MUL( 0x0E, x )       ) ^
+                 ( (uint32_t) MUL( 0x09, x ) <<  8 ) ^
+                 ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^
+                 ( (uint32_t) MUL( 0x0B, x ) << 24 );
+
+#if !defined(MBEDTLS_AES_FEWER_TABLES)
+        RT1[i] = ROTL8( RT0[i] );
+        RT2[i] = ROTL8( RT1[i] );
+        RT3[i] = ROTL8( RT2[i] );
+#endif /* !MBEDTLS_AES_FEWER_TABLES */
+    }
+}
+
+#undef ROTL8
+
+#endif /* MBEDTLS_AES_ROM_TABLES */
+
+#if defined(MBEDTLS_AES_FEWER_TABLES)
+
+#define ROTL8(x)  ( (uint32_t)( ( x ) <<  8 ) + (uint32_t)( ( x ) >> 24 ) )
+#define ROTL16(x) ( (uint32_t)( ( x ) << 16 ) + (uint32_t)( ( x ) >> 16 ) )
+#define ROTL24(x) ( (uint32_t)( ( x ) << 24 ) + (uint32_t)( ( x ) >>  8 ) )
+
+#define AES_RT0(idx) RT0[idx]
+#define AES_RT1(idx) ROTL8(  RT0[idx] )
+#define AES_RT2(idx) ROTL16( RT0[idx] )
+#define AES_RT3(idx) ROTL24( RT0[idx] )
+
+#define AES_FT0(idx) FT0[idx]
+#define AES_FT1(idx) ROTL8(  FT0[idx] )
+#define AES_FT2(idx) ROTL16( FT0[idx] )
+#define AES_FT3(idx) ROTL24( FT0[idx] )
+
+#else /* MBEDTLS_AES_FEWER_TABLES */
+
+#define AES_RT0(idx) RT0[idx]
+#define AES_RT1(idx) RT1[idx]
+#define AES_RT2(idx) RT2[idx]
+#define AES_RT3(idx) RT3[idx]
+
+#define AES_FT0(idx) FT0[idx]
+#define AES_FT1(idx) FT1[idx]
+#define AES_FT2(idx) FT2[idx]
+#define AES_FT3(idx) FT3[idx]
+
+#endif /* MBEDTLS_AES_FEWER_TABLES */
+
+void mbedtls_aes_init( mbedtls_aes_context *ctx )
+{
+    memset( ctx, 0, sizeof( mbedtls_aes_context ) );
+}
+
+void mbedtls_aes_free( mbedtls_aes_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) );
+}
+
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx )
+{
+    mbedtls_aes_init( &ctx->crypt );
+    mbedtls_aes_init( &ctx->tweak );
+}
+
+void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx )
+{
+    mbedtls_aes_free( &ctx->crypt );
+    mbedtls_aes_free( &ctx->tweak );
+}
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
+/*
+ * AES key schedule (encryption)
+ */
+#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT)
+int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
+                    unsigned int keybits )
+{
+    unsigned int i;
+    uint32_t *RK;
+
+#if !defined(MBEDTLS_AES_ROM_TABLES)
+    if( aes_init_done == 0 )
+    {
+        aes_gen_tables();
+        aes_init_done = 1;
+
+    }
+#endif
+
+    switch( keybits )
+    {
+        case 128: ctx->nr = 10; break;
+        case 192: ctx->nr = 12; break;
+        case 256: ctx->nr = 14; break;
+        default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
+    }
+
+#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16)
+    if( aes_padlock_ace == -1 )
+        aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE );
+
+    if( aes_padlock_ace )
+        ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf );
+    else
+#endif
+    ctx->rk = RK = ctx->buf;
+
+#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+    if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) )
+        return( mbedtls_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) );
+#endif
+
+    for( i = 0; i < ( keybits >> 5 ); i++ )
+    {
+        GET_UINT32_LE( RK[i], key, i << 2 );
+    }
+
+    switch( ctx->nr )
+    {
+        case 10:
+
+            for( i = 0; i < 10; i++, RK += 4 )
+            {
+                RK[4]  = RK[0] ^ RCON[i] ^
+                ( (uint32_t) FSb[ ( RK[3] >>  8 ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( RK[3]       ) & 0xFF ] << 24 );
+
+                RK[5]  = RK[1] ^ RK[4];
+                RK[6]  = RK[2] ^ RK[5];
+                RK[7]  = RK[3] ^ RK[6];
+            }
+            break;
+
+        case 12:
+
+            for( i = 0; i < 8; i++, RK += 6 )
+            {
+                RK[6]  = RK[0] ^ RCON[i] ^
+                ( (uint32_t) FSb[ ( RK[5] >>  8 ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( RK[5]       ) & 0xFF ] << 24 );
+
+                RK[7]  = RK[1] ^ RK[6];
+                RK[8]  = RK[2] ^ RK[7];
+                RK[9]  = RK[3] ^ RK[8];
+                RK[10] = RK[4] ^ RK[9];
+                RK[11] = RK[5] ^ RK[10];
+            }
+            break;
+
+        case 14:
+
+            for( i = 0; i < 7; i++, RK += 8 )
+            {
+                RK[8]  = RK[0] ^ RCON[i] ^
+                ( (uint32_t) FSb[ ( RK[7] >>  8 ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( RK[7]       ) & 0xFF ] << 24 );
+
+                RK[9]  = RK[1] ^ RK[8];
+                RK[10] = RK[2] ^ RK[9];
+                RK[11] = RK[3] ^ RK[10];
+
+                RK[12] = RK[4] ^
+                ( (uint32_t) FSb[ ( RK[11]       ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( RK[11] >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
+
+                RK[13] = RK[5] ^ RK[12];
+                RK[14] = RK[6] ^ RK[13];
+                RK[15] = RK[7] ^ RK[14];
+            }
+            break;
+    }
+
+    return( 0 );
+}
+#endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */
+
+/*
+ * AES key schedule (decryption)
+ */
+#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT)
+int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
+                    unsigned int keybits )
+{
+    int i, j, ret;
+    mbedtls_aes_context cty;
+    uint32_t *RK;
+    uint32_t *SK;
+
+    mbedtls_aes_init( &cty );
+
+#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16)
+    if( aes_padlock_ace == -1 )
+        aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE );
+
+    if( aes_padlock_ace )
+        ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf );
+    else
+#endif
+    ctx->rk = RK = ctx->buf;
+
+    /* Also checks keybits */
+    if( ( ret = mbedtls_aes_setkey_enc( &cty, key, keybits ) ) != 0 )
+        goto exit;
+
+    ctx->nr = cty.nr;
+
+#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+    if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) )
+    {
+        mbedtls_aesni_inverse_key( (unsigned char *) ctx->rk,
+                           (const unsigned char *) cty.rk, ctx->nr );
+        goto exit;
+    }
+#endif
+
+    SK = cty.rk + cty.nr * 4;
+
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+
+    for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 )
+    {
+        for( j = 0; j < 4; j++, SK++ )
+        {
+            *RK++ = AES_RT0( FSb[ ( *SK       ) & 0xFF ] ) ^
+                    AES_RT1( FSb[ ( *SK >>  8 ) & 0xFF ] ) ^
+                    AES_RT2( FSb[ ( *SK >> 16 ) & 0xFF ] ) ^
+                    AES_RT3( FSb[ ( *SK >> 24 ) & 0xFF ] );
+        }
+    }
+
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+
+exit:
+    mbedtls_aes_free( &cty );
+
+    return( ret );
+}
+
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+static int mbedtls_aes_xts_decode_keys( const unsigned char *key,
+                                        unsigned int keybits,
+                                        const unsigned char **key1,
+                                        unsigned int *key1bits,
+                                        const unsigned char **key2,
+                                        unsigned int *key2bits )
+{
+    const unsigned int half_keybits = keybits / 2;
+    const unsigned int half_keybytes = half_keybits / 8;
+
+    switch( keybits )
+    {
+        case 256: break;
+        case 512: break;
+        default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
+    }
+
+    *key1bits = half_keybits;
+    *key2bits = half_keybits;
+    *key1 = &key[0];
+    *key2 = &key[half_keybytes];
+
+    return 0;
+}
+
+int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
+                                const unsigned char *key,
+                                unsigned int keybits)
+{
+    int ret;
+    const unsigned char *key1, *key2;
+    unsigned int key1bits, key2bits;
+
+    ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
+                                       &key2, &key2bits );
+    if( ret != 0 )
+        return( ret );
+
+    /* Set the tweak key. Always set tweak key for the encryption mode. */
+    ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits );
+    if( ret != 0 )
+        return( ret );
+
+    /* Set crypt key for encryption. */
+    return mbedtls_aes_setkey_enc( &ctx->crypt, key1, key1bits );
+}
+
+int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
+                                const unsigned char *key,
+                                unsigned int keybits)
+{
+    int ret;
+    const unsigned char *key1, *key2;
+    unsigned int key1bits, key2bits;
+
+    ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
+                                       &key2, &key2bits );
+    if( ret != 0 )
+        return( ret );
+
+    /* Set the tweak key. Always set tweak key for encryption. */
+    ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits );
+    if( ret != 0 )
+        return( ret );
+
+    /* Set crypt key for decryption. */
+    return mbedtls_aes_setkey_dec( &ctx->crypt, key1, key1bits );
+}
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
+#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */
+
+#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)         \
+{                                                   \
+    X0 = *RK++ ^ AES_FT0( ( Y0       ) & 0xFF ) ^   \
+                 AES_FT1( ( Y1 >>  8 ) & 0xFF ) ^   \
+                 AES_FT2( ( Y2 >> 16 ) & 0xFF ) ^   \
+                 AES_FT3( ( Y3 >> 24 ) & 0xFF );    \
+                                                    \
+    X1 = *RK++ ^ AES_FT0( ( Y1       ) & 0xFF ) ^   \
+                 AES_FT1( ( Y2 >>  8 ) & 0xFF ) ^   \
+                 AES_FT2( ( Y3 >> 16 ) & 0xFF ) ^   \
+                 AES_FT3( ( Y0 >> 24 ) & 0xFF );    \
+                                                    \
+    X2 = *RK++ ^ AES_FT0( ( Y2       ) & 0xFF ) ^   \
+                 AES_FT1( ( Y3 >>  8 ) & 0xFF ) ^   \
+                 AES_FT2( ( Y0 >> 16 ) & 0xFF ) ^   \
+                 AES_FT3( ( Y1 >> 24 ) & 0xFF );    \
+                                                    \
+    X3 = *RK++ ^ AES_FT0( ( Y3       ) & 0xFF ) ^   \
+                 AES_FT1( ( Y0 >>  8 ) & 0xFF ) ^   \
+                 AES_FT2( ( Y1 >> 16 ) & 0xFF ) ^   \
+                 AES_FT3( ( Y2 >> 24 ) & 0xFF );    \
+}
+
+#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)         \
+{                                                   \
+    X0 = *RK++ ^ AES_RT0( ( Y0       ) & 0xFF ) ^   \
+                 AES_RT1( ( Y3 >>  8 ) & 0xFF ) ^   \
+                 AES_RT2( ( Y2 >> 16 ) & 0xFF ) ^   \
+                 AES_RT3( ( Y1 >> 24 ) & 0xFF );    \
+                                                    \
+    X1 = *RK++ ^ AES_RT0( ( Y1       ) & 0xFF ) ^   \
+                 AES_RT1( ( Y0 >>  8 ) & 0xFF ) ^   \
+                 AES_RT2( ( Y3 >> 16 ) & 0xFF ) ^   \
+                 AES_RT3( ( Y2 >> 24 ) & 0xFF );    \
+                                                    \
+    X2 = *RK++ ^ AES_RT0( ( Y2       ) & 0xFF ) ^   \
+                 AES_RT1( ( Y1 >>  8 ) & 0xFF ) ^   \
+                 AES_RT2( ( Y0 >> 16 ) & 0xFF ) ^   \
+                 AES_RT3( ( Y3 >> 24 ) & 0xFF );    \
+                                                    \
+    X3 = *RK++ ^ AES_RT0( ( Y3       ) & 0xFF ) ^   \
+                 AES_RT1( ( Y2 >>  8 ) & 0xFF ) ^   \
+                 AES_RT2( ( Y1 >> 16 ) & 0xFF ) ^   \
+                 AES_RT3( ( Y0 >> 24 ) & 0xFF );    \
+}
+
+/*
+ * AES-ECB block encryption
+ */
+#if !defined(MBEDTLS_AES_ENCRYPT_ALT)
+int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx,
+                                  const unsigned char input[16],
+                                  unsigned char output[16] )
+{
+    int i;
+    uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+
+    RK = ctx->rk;
+
+    GET_UINT32_LE( X0, input,  0 ); X0 ^= *RK++;
+    GET_UINT32_LE( X1, input,  4 ); X1 ^= *RK++;
+    GET_UINT32_LE( X2, input,  8 ); X2 ^= *RK++;
+    GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++;
+
+    for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
+    {
+        AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+        AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+    }
+
+    AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+
+    X0 = *RK++ ^ \
+            ( (uint32_t) FSb[ ( Y0       ) & 0xFF ]       ) ^
+            ( (uint32_t) FSb[ ( Y1 >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+
+    X1 = *RK++ ^ \
+            ( (uint32_t) FSb[ ( Y1       ) & 0xFF ]       ) ^
+            ( (uint32_t) FSb[ ( Y2 >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+
+    X2 = *RK++ ^ \
+            ( (uint32_t) FSb[ ( Y2       ) & 0xFF ]       ) ^
+            ( (uint32_t) FSb[ ( Y3 >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+
+    X3 = *RK++ ^ \
+            ( (uint32_t) FSb[ ( Y3       ) & 0xFF ]       ) ^
+            ( (uint32_t) FSb[ ( Y0 >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+
+    PUT_UINT32_LE( X0, output,  0 );
+    PUT_UINT32_LE( X1, output,  4 );
+    PUT_UINT32_LE( X2, output,  8 );
+    PUT_UINT32_LE( X3, output, 12 );
+
+    return( 0 );
+}
+#endif /* !MBEDTLS_AES_ENCRYPT_ALT */
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+void mbedtls_aes_encrypt( mbedtls_aes_context *ctx,
+                          const unsigned char input[16],
+                          unsigned char output[16] )
+{
+    mbedtls_internal_aes_encrypt( ctx, input, output );
+}
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+
+/*
+ * AES-ECB block decryption
+ */
+#if !defined(MBEDTLS_AES_DECRYPT_ALT)
+int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx,
+                                  const unsigned char input[16],
+                                  unsigned char output[16] )
+{
+    int i;
+    uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+
+    RK = ctx->rk;
+
+    GET_UINT32_LE( X0, input,  0 ); X0 ^= *RK++;
+    GET_UINT32_LE( X1, input,  4 ); X1 ^= *RK++;
+    GET_UINT32_LE( X2, input,  8 ); X2 ^= *RK++;
+    GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++;
+
+    for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
+    {
+        AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+        AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+    }
+
+    AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+
+    X0 = *RK++ ^ \
+            ( (uint32_t) RSb[ ( Y0       ) & 0xFF ]       ) ^
+            ( (uint32_t) RSb[ ( Y3 >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+
+    X1 = *RK++ ^ \
+            ( (uint32_t) RSb[ ( Y1       ) & 0xFF ]       ) ^
+            ( (uint32_t) RSb[ ( Y0 >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+
+    X2 = *RK++ ^ \
+            ( (uint32_t) RSb[ ( Y2       ) & 0xFF ]       ) ^
+            ( (uint32_t) RSb[ ( Y1 >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+
+    X3 = *RK++ ^ \
+            ( (uint32_t) RSb[ ( Y3       ) & 0xFF ]       ) ^
+            ( (uint32_t) RSb[ ( Y2 >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+
+    PUT_UINT32_LE( X0, output,  0 );
+    PUT_UINT32_LE( X1, output,  4 );
+    PUT_UINT32_LE( X2, output,  8 );
+    PUT_UINT32_LE( X3, output, 12 );
+
+    return( 0 );
+}
+#endif /* !MBEDTLS_AES_DECRYPT_ALT */
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
+                          const unsigned char input[16],
+                          unsigned char output[16] )
+{
+    mbedtls_internal_aes_decrypt( ctx, input, output );
+}
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+
+/*
+ * AES-ECB block encryption/decryption
+ */
+int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
+                    int mode,
+                    const unsigned char input[16],
+                    unsigned char output[16] )
+{
+#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+    if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) )
+        return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) );
+#endif
+
+#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
+    if( aes_padlock_ace )
+    {
+        if( mbedtls_padlock_xcryptecb( ctx, mode, input, output ) == 0 )
+            return( 0 );
+
+        // If padlock data misaligned, we just fall back to
+        // unaccelerated mode
+        //
+    }
+#endif
+
+    if( mode == MBEDTLS_AES_ENCRYPT )
+        return( mbedtls_internal_aes_encrypt( ctx, input, output ) );
+    else
+        return( mbedtls_internal_aes_decrypt( ctx, input, output ) );
+}
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+/*
+ * AES-CBC buffer encryption/decryption
+ */
+int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[16],
+                    const unsigned char *input,
+                    unsigned char *output )
+{
+    int i;
+    unsigned char temp[16];
+
+    if( length % 16 )
+        return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
+
+#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
+    if( aes_padlock_ace )
+    {
+        if( mbedtls_padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 )
+            return( 0 );
+
+        // If padlock data misaligned, we just fall back to
+        // unaccelerated mode
+        //
+    }
+#endif
+
+    if( mode == MBEDTLS_AES_DECRYPT )
+    {
+        while( length > 0 )
+        {
+            memcpy( temp, input, 16 );
+            mbedtls_aes_crypt_ecb( ctx, mode, input, output );
+
+            for( i = 0; i < 16; i++ )
+                output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+            memcpy( iv, temp, 16 );
+
+            input  += 16;
+            output += 16;
+            length -= 16;
+        }
+    }
+    else
+    {
+        while( length > 0 )
+        {
+            for( i = 0; i < 16; i++ )
+                output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+            mbedtls_aes_crypt_ecb( ctx, mode, output, output );
+            memcpy( iv, output, 16 );
+
+            input  += 16;
+            output += 16;
+            length -= 16;
+        }
+    }
+
+    return( 0 );
+}
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+
+/* Endianess with 64 bits values */
+#ifndef GET_UINT64_LE
+#define GET_UINT64_LE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint64_t) (b)[(i) + 7] << 56 )             \
+        | ( (uint64_t) (b)[(i) + 6] << 48 )             \
+        | ( (uint64_t) (b)[(i) + 5] << 40 )             \
+        | ( (uint64_t) (b)[(i) + 4] << 32 )             \
+        | ( (uint64_t) (b)[(i) + 3] << 24 )             \
+        | ( (uint64_t) (b)[(i) + 2] << 16 )             \
+        | ( (uint64_t) (b)[(i) + 1] <<  8 )             \
+        | ( (uint64_t) (b)[(i)    ]       );            \
+}
+#endif
+
+#ifndef PUT_UINT64_LE
+#define PUT_UINT64_LE(n,b,i)                            \
+{                                                       \
+    (b)[(i) + 7] = (unsigned char) ( (n) >> 56 );       \
+    (b)[(i) + 6] = (unsigned char) ( (n) >> 48 );       \
+    (b)[(i) + 5] = (unsigned char) ( (n) >> 40 );       \
+    (b)[(i) + 4] = (unsigned char) ( (n) >> 32 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i)    ] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+typedef unsigned char mbedtls_be128[16];
+
+/*
+ * GF(2^128) multiplication function
+ *
+ * This function multiplies a field element by x in the polynomial field
+ * representation. It uses 64-bit word operations to gain speed but compensates
+ * for machine endianess and hence works correctly on both big and little
+ * endian machines.
+ */
+static void mbedtls_gf128mul_x_ble( unsigned char r[16],
+                                    const unsigned char x[16] )
+{
+    uint64_t a, b, ra, rb;
+
+    GET_UINT64_LE( a, x, 0 );
+    GET_UINT64_LE( b, x, 8 );
+
+    ra = ( a << 1 )  ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) );
+    rb = ( a >> 63 ) | ( b << 1 );
+
+    PUT_UINT64_LE( ra, r, 0 );
+    PUT_UINT64_LE( rb, r, 8 );
+}
+
+/*
+ * AES-XTS buffer encryption/decryption
+ */
+int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
+                           int mode,
+                           size_t length,
+                           const unsigned char data_unit[16],
+                           const unsigned char *input,
+                           unsigned char *output )
+{
+    int ret;
+    size_t blocks = length / 16;
+    size_t leftover = length % 16;
+    unsigned char tweak[16];
+    unsigned char prev_tweak[16];
+    unsigned char tmp[16];
+
+    /* Sectors must be at least 16 bytes. */
+    if( length < 16 )
+        return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
+
+    /* NIST SP 80-38E disallows data units larger than 2**20 blocks. */
+    if( length > ( 1 << 20 ) * 16 )
+        return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
+
+    /* Compute the tweak. */
+    ret = mbedtls_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT,
+                                 data_unit, tweak );
+    if( ret != 0 )
+        return( ret );
+
+    while( blocks-- )
+    {
+        size_t i;
+
+        if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 )
+        {
+            /* We are on the last block in a decrypt operation that has
+             * leftover bytes, so we need to use the next tweak for this block,
+             * and this tweak for the lefover bytes. Save the current tweak for
+             * the leftovers and then update the current tweak for use on this,
+             * the last full block. */
+            memcpy( prev_tweak, tweak, sizeof( tweak ) );
+            mbedtls_gf128mul_x_ble( tweak, tweak );
+        }
+
+        for( i = 0; i < 16; i++ )
+            tmp[i] = input[i] ^ tweak[i];
+
+        ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
+        if( ret != 0 )
+            return( ret );
+
+        for( i = 0; i < 16; i++ )
+            output[i] = tmp[i] ^ tweak[i];
+
+        /* Update the tweak for the next block. */
+        mbedtls_gf128mul_x_ble( tweak, tweak );
+
+        output += 16;
+        input += 16;
+    }
+
+    if( leftover )
+    {
+        /* If we are on the leftover bytes in a decrypt operation, we need to
+         * use the previous tweak for these bytes (as saved in prev_tweak). */
+        unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak;
+
+        /* We are now on the final part of the data unit, which doesn't divide
+         * evenly by 16. It's time for ciphertext stealing. */
+        size_t i;
+        unsigned char *prev_output = output - 16;
+
+        /* Copy ciphertext bytes from the previous block to our output for each
+         * byte of cyphertext we won't steal. At the same time, copy the
+         * remainder of the input for this final round (since the loop bounds
+         * are the same). */
+        for( i = 0; i < leftover; i++ )
+        {
+            output[i] = prev_output[i];
+            tmp[i] = input[i] ^ t[i];
+        }
+
+        /* Copy ciphertext bytes from the previous block for input in this
+         * round. */
+        for( ; i < 16; i++ )
+            tmp[i] = prev_output[i] ^ t[i];
+
+        ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
+        if( ret != 0 )
+            return ret;
+
+        /* Write the result back to the previous block, overriding the previous
+         * output we copied. */
+        for( i = 0; i < 16; i++ )
+            prev_output[i] = tmp[i] ^ t[i];
+    }
+
+    return( 0 );
+}
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+/*
+ * AES-CFB128 buffer encryption/decryption
+ */
+int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
+                       int mode,
+                       size_t length,
+                       size_t *iv_off,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output )
+{
+    int c;
+    size_t n = *iv_off;
+
+    if( mode == MBEDTLS_AES_DECRYPT )
+    {
+        while( length-- )
+        {
+            if( n == 0 )
+                mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+
+            c = *input++;
+            *output++ = (unsigned char)( c ^ iv[n] );
+            iv[n] = (unsigned char) c;
+
+            n = ( n + 1 ) & 0x0F;
+        }
+    }
+    else
+    {
+        while( length-- )
+        {
+            if( n == 0 )
+                mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+
+            iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+
+            n = ( n + 1 ) & 0x0F;
+        }
+    }
+
+    *iv_off = n;
+
+    return( 0 );
+}
+
+/*
+ * AES-CFB8 buffer encryption/decryption
+ */
+int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
+                       int mode,
+                       size_t length,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output )
+{
+    unsigned char c;
+    unsigned char ov[17];
+
+    while( length-- )
+    {
+        memcpy( ov, iv, 16 );
+        mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+
+        if( mode == MBEDTLS_AES_DECRYPT )
+            ov[16] = *input;
+
+        c = *output++ = (unsigned char)( iv[0] ^ *input++ );
+
+        if( mode == MBEDTLS_AES_ENCRYPT )
+            ov[16] = c;
+
+        memcpy( iv, ov + 1, 16 );
+    }
+
+    return( 0 );
+}
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+/*
+ * AES-OFB (Output Feedback Mode) buffer encryption/decryption
+ */
+int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
+                           size_t length,
+                           size_t *iv_off,
+                           unsigned char iv[16],
+                           const unsigned char *input,
+                           unsigned char *output )
+{
+    int ret = 0;
+    size_t n = *iv_off;
+
+    while( length-- )
+    {
+        if( n == 0 )
+        {
+            ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+            if( ret != 0 )
+                goto exit;
+        }
+        *output++ =  *input++ ^ iv[n];
+
+        n = ( n + 1 ) & 0x0F;
+    }
+
+    *iv_off = n;
+
+exit:
+    return( ret );
+}
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+/*
+ * AES-CTR buffer encryption/decryption
+ */
+int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
+                       size_t length,
+                       size_t *nc_off,
+                       unsigned char nonce_counter[16],
+                       unsigned char stream_block[16],
+                       const unsigned char *input,
+                       unsigned char *output )
+{
+    int c, i;
+    size_t n = *nc_off;
+
+    if ( n > 0x0F )
+        return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
+
+    while( length-- )
+    {
+        if( n == 0 ) {
+            mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block );
+
+            for( i = 16; i > 0; i-- )
+                if( ++nonce_counter[i - 1] != 0 )
+                    break;
+        }
+        c = *input++;
+        *output++ = (unsigned char)( c ^ stream_block[n] );
+
+        n = ( n + 1 ) & 0x0F;
+    }
+
+    *nc_off = n;
+
+    return( 0 );
+}
+#endif /* MBEDTLS_CIPHER_MODE_CTR */
+
+#endif /* !MBEDTLS_AES_ALT */
+
+#if defined(MBEDTLS_SELF_TEST)
+/*
+ * AES test vectors from:
+ *
+ * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip
+ */
+static const unsigned char aes_test_ecb_dec[3][16] =
+{
+    { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58,
+      0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 },
+    { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2,
+      0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 },
+    { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D,
+      0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE }
+};
+
+static const unsigned char aes_test_ecb_enc[3][16] =
+{
+    { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73,
+      0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F },
+    { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11,
+      0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 },
+    { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D,
+      0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 }
+};
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+static const unsigned char aes_test_cbc_dec[3][16] =
+{
+    { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73,
+      0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 },
+    { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75,
+      0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B },
+    { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75,
+      0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 }
+};
+
+static const unsigned char aes_test_cbc_enc[3][16] =
+{
+    { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84,
+      0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D },
+    { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB,
+      0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 },
+    { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5,
+      0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 }
+};
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+/*
+ * AES-CFB128 test vectors from:
+ *
+ * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ */
+static const unsigned char aes_test_cfb128_key[3][32] =
+{
+    { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+      0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },
+    { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
+      0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
+      0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },
+    { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+      0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+      0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+      0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+};
+
+static const unsigned char aes_test_cfb128_iv[16] =
+{
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+};
+
+static const unsigned char aes_test_cfb128_pt[64] =
+{
+    0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+    0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
+    0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+    0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
+    0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+    0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
+    0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
+    0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
+};
+
+static const unsigned char aes_test_cfb128_ct[3][64] =
+{
+    { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
+      0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
+      0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F,
+      0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B,
+      0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40,
+      0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF,
+      0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E,
+      0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 },
+    { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,
+      0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,
+      0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21,
+      0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A,
+      0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1,
+      0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9,
+      0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0,
+      0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF },
+    { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,
+      0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,
+      0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8,
+      0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B,
+      0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92,
+      0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9,
+      0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8,
+      0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 }
+};
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+/*
+ * AES-OFB test vectors from:
+ *
+ * https://csrc.nist.gov/publications/detail/sp/800-38a/final
+ */
+static const unsigned char aes_test_ofb_key[3][32] =
+{
+    { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+      0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },
+    { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
+      0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
+      0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },
+    { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+      0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+      0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+      0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+};
+
+static const unsigned char aes_test_ofb_iv[16] =
+{
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+};
+
+static const unsigned char aes_test_ofb_pt[64] =
+{
+    0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+    0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
+    0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+    0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
+    0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+    0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
+    0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
+    0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
+};
+
+static const unsigned char aes_test_ofb_ct[3][64] =
+{
+    { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
+      0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
+      0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03,
+      0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25,
+      0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6,
+      0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc,
+      0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78,
+      0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e },
+    { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,
+      0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,
+      0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c,
+      0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01,
+      0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f,
+      0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2,
+      0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e,
+      0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a },
+    { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,
+      0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,
+      0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a,
+      0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d,
+      0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed,
+      0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08,
+      0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8,
+      0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 }
+};
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+/*
+ * AES-CTR test vectors from:
+ *
+ * http://www.faqs.org/rfcs/rfc3686.html
+ */
+
+static const unsigned char aes_test_ctr_key[3][16] =
+{
+    { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
+      0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },
+    { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,
+      0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },
+    { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
+      0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }
+};
+
+static const unsigned char aes_test_ctr_nonce_counter[3][16] =
+{
+    { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+    { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,
+      0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },
+    { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,
+      0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }
+};
+
+static const unsigned char aes_test_ctr_pt[3][48] =
+{
+    { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
+      0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },
+
+    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
+
+    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+      0x20, 0x21, 0x22, 0x23 }
+};
+
+static const unsigned char aes_test_ctr_ct[3][48] =
+{
+    { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79,
+      0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 },
+    { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9,
+      0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88,
+      0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8,
+      0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 },
+    { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9,
+      0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7,
+      0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36,
+      0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53,
+      0x25, 0xB2, 0x07, 0x2F }
+};
+
+static const int aes_test_ctr_len[3] =
+    { 16, 32, 36 };
+#endif /* MBEDTLS_CIPHER_MODE_CTR */
+
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+/*
+ * AES-XTS test vectors from:
+ *
+ * IEEE P1619/D16 Annex B
+ * https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf
+ * (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf)
+ */
+static const unsigned char aes_test_xts_key[][32] =
+{
+    { 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 },
+    { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+      0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+      0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+      0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
+    { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+      0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
+      0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+      0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
+};
+
+static const unsigned char aes_test_xts_pt32[][32] =
+{
+    { 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 },
+    { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+      0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+      0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+      0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
+    { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+      0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+      0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+      0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
+};
+
+static const unsigned char aes_test_xts_ct32[][32] =
+{
+    { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec,
+      0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92,
+      0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85,
+      0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e },
+    { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e,
+      0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b,
+      0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4,
+      0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 },
+    { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a,
+      0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2,
+      0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53,
+      0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 },
+};
+
+static const unsigned char aes_test_xts_data_unit[][16] =
+{
+   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+   { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+   { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+};
+
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
+/*
+ * Checkup routine
+ */
+int mbedtls_aes_self_test( int verbose )
+{
+    int ret = 0, i, j, u, mode;
+    unsigned int keybits;
+    unsigned char key[32];
+    unsigned char buf[64];
+    const unsigned char *aes_tests;
+#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)
+    unsigned char iv[16];
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    unsigned char prv[16];
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \
+    defined(MBEDTLS_CIPHER_MODE_OFB)
+    size_t offset;
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_XTS)
+    int len;
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    unsigned char nonce_counter[16];
+    unsigned char stream_block[16];
+#endif
+    mbedtls_aes_context ctx;
+
+    memset( key, 0, 32 );
+    mbedtls_aes_init( &ctx );
+
+    /*
+     * ECB mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        keybits = 128 + u * 64;
+        mode = i & 1;
+
+        if( verbose != 0 )
+            mbedtls_printf( "  AES-ECB-%3d (%s): ", keybits,
+                            ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+
+        memset( buf, 0, 16 );
+
+        if( mode == MBEDTLS_AES_DECRYPT )
+        {
+            ret = mbedtls_aes_setkey_dec( &ctx, key, keybits );
+            aes_tests = aes_test_ecb_dec[u];
+        }
+        else
+        {
+            ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
+            aes_tests = aes_test_ecb_enc[u];
+        }
+
+        /*
+         * AES-192 is an optional feature that may be unavailable when
+         * there is an alternative underlying implementation i.e. when
+         * MBEDTLS_AES_ALT is defined.
+         */
+        if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
+        {
+            mbedtls_printf( "skipped\n" );
+            continue;
+        }
+        else if( ret != 0 )
+        {
+            goto exit;
+        }
+
+        for( j = 0; j < 10000; j++ )
+        {
+            ret = mbedtls_aes_crypt_ecb( &ctx, mode, buf, buf );
+            if( ret != 0 )
+                goto exit;
+        }
+
+        if( memcmp( buf, aes_tests, 16 ) != 0 )
+        {
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "\n" );
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    /*
+     * CBC mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        keybits = 128 + u * 64;
+        mode = i & 1;
+
+        if( verbose != 0 )
+            mbedtls_printf( "  AES-CBC-%3d (%s): ", keybits,
+                            ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+
+        memset( iv , 0, 16 );
+        memset( prv, 0, 16 );
+        memset( buf, 0, 16 );
+
+        if( mode == MBEDTLS_AES_DECRYPT )
+        {
+            ret = mbedtls_aes_setkey_dec( &ctx, key, keybits );
+            aes_tests = aes_test_cbc_dec[u];
+        }
+        else
+        {
+            ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
+            aes_tests = aes_test_cbc_enc[u];
+        }
+
+        /*
+         * AES-192 is an optional feature that may be unavailable when
+         * there is an alternative underlying implementation i.e. when
+         * MBEDTLS_AES_ALT is defined.
+         */
+        if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
+        {
+            mbedtls_printf( "skipped\n" );
+            continue;
+        }
+        else if( ret != 0 )
+        {
+            goto exit;
+        }
+
+        for( j = 0; j < 10000; j++ )
+        {
+            if( mode == MBEDTLS_AES_ENCRYPT )
+            {
+                unsigned char tmp[16];
+
+                memcpy( tmp, prv, 16 );
+                memcpy( prv, buf, 16 );
+                memcpy( buf, tmp, 16 );
+            }
+
+            ret = mbedtls_aes_crypt_cbc( &ctx, mode, 16, iv, buf, buf );
+            if( ret != 0 )
+                goto exit;
+
+        }
+
+        if( memcmp( buf, aes_tests, 16 ) != 0 )
+        {
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "\n" );
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    /*
+     * CFB128 mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        keybits = 128 + u * 64;
+        mode = i & 1;
+
+        if( verbose != 0 )
+            mbedtls_printf( "  AES-CFB128-%3d (%s): ", keybits,
+                            ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( iv,  aes_test_cfb128_iv, 16 );
+        memcpy( key, aes_test_cfb128_key[u], keybits / 8 );
+
+        offset = 0;
+        ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
+        /*
+         * AES-192 is an optional feature that may be unavailable when
+         * there is an alternative underlying implementation i.e. when
+         * MBEDTLS_AES_ALT is defined.
+         */
+        if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
+        {
+            mbedtls_printf( "skipped\n" );
+            continue;
+        }
+        else if( ret != 0 )
+        {
+            goto exit;
+        }
+
+        if( mode == MBEDTLS_AES_DECRYPT )
+        {
+            memcpy( buf, aes_test_cfb128_ct[u], 64 );
+            aes_tests = aes_test_cfb128_pt;
+        }
+        else
+        {
+            memcpy( buf, aes_test_cfb128_pt, 64 );
+            aes_tests = aes_test_cfb128_ct[u];
+        }
+
+        ret = mbedtls_aes_crypt_cfb128( &ctx, mode, 64, &offset, iv, buf, buf );
+        if( ret != 0 )
+            goto exit;
+
+        if( memcmp( buf, aes_tests, 64 ) != 0 )
+        {
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "\n" );
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    /*
+     * OFB mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        keybits = 128 + u * 64;
+        mode = i & 1;
+
+        if( verbose != 0 )
+            mbedtls_printf( "  AES-OFB-%3d (%s): ", keybits,
+                            ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( iv,  aes_test_ofb_iv, 16 );
+        memcpy( key, aes_test_ofb_key[u], keybits / 8 );
+
+        offset = 0;
+        ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
+        /*
+         * AES-192 is an optional feature that may be unavailable when
+         * there is an alternative underlying implementation i.e. when
+         * MBEDTLS_AES_ALT is defined.
+         */
+        if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
+        {
+            mbedtls_printf( "skipped\n" );
+            continue;
+        }
+        else if( ret != 0 )
+        {
+            goto exit;
+        }
+
+        if( mode == MBEDTLS_AES_DECRYPT )
+        {
+            memcpy( buf, aes_test_ofb_ct[u], 64 );
+            aes_tests = aes_test_ofb_pt;
+        }
+        else
+        {
+            memcpy( buf, aes_test_ofb_pt, 64 );
+            aes_tests = aes_test_ofb_ct[u];
+        }
+
+        ret = mbedtls_aes_crypt_ofb( &ctx, 64, &offset, iv, buf, buf );
+        if( ret != 0 )
+            goto exit;
+
+        if( memcmp( buf, aes_tests, 64 ) != 0 )
+        {
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "\n" );
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    /*
+     * CTR mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        mode = i & 1;
+
+        if( verbose != 0 )
+            mbedtls_printf( "  AES-CTR-128 (%s): ",
+                            ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 );
+        memcpy( key, aes_test_ctr_key[u], 16 );
+
+        offset = 0;
+        if( ( ret = mbedtls_aes_setkey_enc( &ctx, key, 128 ) ) != 0 )
+            goto exit;
+
+        len = aes_test_ctr_len[u];
+
+        if( mode == MBEDTLS_AES_DECRYPT )
+        {
+            memcpy( buf, aes_test_ctr_ct[u], len );
+            aes_tests = aes_test_ctr_pt[u];
+        }
+        else
+        {
+            memcpy( buf, aes_test_ctr_pt[u], len );
+            aes_tests = aes_test_ctr_ct[u];
+        }
+
+        ret = mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter,
+                                     stream_block, buf, buf );
+        if( ret != 0 )
+            goto exit;
+
+        if( memcmp( buf, aes_tests, len ) != 0 )
+        {
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "\n" );
+#endif /* MBEDTLS_CIPHER_MODE_CTR */
+
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    {
+    static const int num_tests =
+        sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key);
+    mbedtls_aes_xts_context ctx_xts;
+
+    /*
+     * XTS mode
+     */
+    mbedtls_aes_xts_init( &ctx_xts );
+
+    for( i = 0; i < num_tests << 1; i++ )
+    {
+        const unsigned char *data_unit;
+        u = i >> 1;
+        mode = i & 1;
+
+        if( verbose != 0 )
+            mbedtls_printf( "  AES-XTS-128 (%s): ",
+                            ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+
+        memset( key, 0, sizeof( key ) );
+        memcpy( key, aes_test_xts_key[u], 32 );
+        data_unit = aes_test_xts_data_unit[u];
+
+        len = sizeof( *aes_test_xts_ct32 );
+
+        if( mode == MBEDTLS_AES_DECRYPT )
+        {
+            ret = mbedtls_aes_xts_setkey_dec( &ctx_xts, key, 256 );
+            if( ret != 0)
+                goto exit;
+            memcpy( buf, aes_test_xts_ct32[u], len );
+            aes_tests = aes_test_xts_pt32[u];
+        }
+        else
+        {
+            ret = mbedtls_aes_xts_setkey_enc( &ctx_xts, key, 256 );
+            if( ret != 0)
+                goto exit;
+            memcpy( buf, aes_test_xts_pt32[u], len );
+            aes_tests = aes_test_xts_ct32[u];
+        }
+
+
+        ret = mbedtls_aes_crypt_xts( &ctx_xts, mode, len, data_unit,
+                                     buf, buf );
+        if( ret != 0 )
+            goto exit;
+
+        if( memcmp( buf, aes_tests, len ) != 0 )
+        {
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "\n" );
+
+    mbedtls_aes_xts_free( &ctx_xts );
+    }
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
+    ret = 0;
+
+exit:
+    if( ret != 0 && verbose != 0 )
+        mbedtls_printf( "failed\n" );
+
+    mbedtls_aes_free( &ctx );
+
+    return( ret );
+}
+
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_AES_C */
diff --git a/common/mbedtls/aes.h b/common/mbedtls/aes.h
new file mode 100644 (file)
index 0000000..9af6bb7
--- /dev/null
@@ -0,0 +1,628 @@
+/**
+ * \file aes.h
+ *
+ * \brief   This file contains AES definitions and functions.
+ *
+ *          The Advanced Encryption Standard (AES) specifies a FIPS-approved
+ *          cryptographic algorithm that can be used to protect electronic
+ *          data.
+ *
+ *          The AES algorithm is a symmetric block cipher that can
+ *          encrypt and decrypt information. For more information, see
+ *          <em>FIPS Publication 197: Advanced Encryption Standard</em> and
+ *          <em>ISO/IEC 18033-2:2006: Information technology -- Security
+ *          techniques -- Encryption algorithms -- Part 2: Asymmetric
+ *          ciphers</em>.
+ *
+ *          The AES-XTS block mode is standardized by NIST SP 800-38E
+ *          <https://nvlpubs.nist.gov/nistpubs/legacy/sp/nistspecialpublication800-38e.pdf>
+ *          and described in detail by IEEE P1619
+ *          <https://ieeexplore.ieee.org/servlet/opac?punumber=4375278>.
+ */
+
+/*  Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved.
+ *  SPDX-License-Identifier: GPL-2.0
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *  This file is part of Mbed TLS (https://tls.mbed.org)
+ */
+
+#ifndef MBEDTLS_AES_H
+#define MBEDTLS_AES_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+/* padlock.c and aesni.c rely on these values! */
+#define MBEDTLS_AES_ENCRYPT     1 /**< AES encryption. */
+#define MBEDTLS_AES_DECRYPT     0 /**< AES decryption. */
+
+/* Error codes in range 0x0020-0x0022 */
+#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH                -0x0020  /**< Invalid key length. */
+#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH              -0x0022  /**< Invalid data input length. */
+
+/* Error codes in range 0x0021-0x0025 */
+#define MBEDTLS_ERR_AES_BAD_INPUT_DATA                    -0x0021  /**< Invalid input data. */
+#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE               -0x0023  /**< Feature not available. For example, an unsupported AES key size. */
+#define MBEDTLS_ERR_AES_HW_ACCEL_FAILED                   -0x0025  /**< AES hardware accelerator failed. */
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDTLS_AES_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief The AES context-type definition.
+ */
+typedef struct mbedtls_aes_context
+{
+    int nr;                     /*!< The number of rounds. */
+    uint32_t *rk;               /*!< AES round keys. */
+    uint32_t buf[68];           /*!< Unaligned data buffer. This buffer can
+                                     hold 32 extra Bytes, which can be used for
+                                     one of the following purposes:
+                                     <ul><li>Alignment if VIA padlock is
+                                             used.</li>
+                                     <li>Simplifying key expansion in the 256-bit
+                                         case by generating an extra round key.
+                                         </li></ul> */
+}
+mbedtls_aes_context;
+
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+/**
+ * \brief The AES XTS context-type definition.
+ */
+typedef struct mbedtls_aes_xts_context
+{
+    mbedtls_aes_context crypt; /*!< The AES context to use for AES block
+                                        encryption or decryption. */
+    mbedtls_aes_context tweak; /*!< The AES context used for tweak
+                                        computation. */
+} mbedtls_aes_xts_context;
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
+#else  /* MBEDTLS_AES_ALT */
+#include "aes_alt.h"
+#endif /* MBEDTLS_AES_ALT */
+
+/**
+ * \brief          This function initializes the specified AES context.
+ *
+ *                 It must be the first API called before using
+ *                 the context.
+ *
+ * \param ctx      The AES context to initialize.
+ */
+void mbedtls_aes_init( mbedtls_aes_context *ctx );
+
+/**
+ * \brief          This function releases and clears the specified AES context.
+ *
+ * \param ctx      The AES context to clear.
+ */
+void mbedtls_aes_free( mbedtls_aes_context *ctx );
+
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+/**
+ * \brief          This function initializes the specified AES XTS context.
+ *
+ *                 It must be the first API called before using
+ *                 the context.
+ *
+ * \param ctx      The AES XTS context to initialize.
+ */
+void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx );
+
+/**
+ * \brief          This function releases and clears the specified AES XTS context.
+ *
+ * \param ctx      The AES XTS context to clear.
+ */
+void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx );
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
+/**
+ * \brief          This function sets the encryption key.
+ *
+ * \param ctx      The AES context to which the key should be bound.
+ * \param key      The encryption key.
+ * \param keybits  The size of data passed in bits. Valid options are:
+ *                 <ul><li>128 bits</li>
+ *                 <li>192 bits</li>
+ *                 <li>256 bits</li></ul>
+ *
+ * \return         \c 0 on success.
+ * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
+ */
+int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
+                    unsigned int keybits );
+
+/**
+ * \brief          This function sets the decryption key.
+ *
+ * \param ctx      The AES context to which the key should be bound.
+ * \param key      The decryption key.
+ * \param keybits  The size of data passed. Valid options are:
+ *                 <ul><li>128 bits</li>
+ *                 <li>192 bits</li>
+ *                 <li>256 bits</li></ul>
+ *
+ * \return         \c 0 on success.
+ * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
+ */
+int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
+                    unsigned int keybits );
+
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+/**
+ * \brief          This function prepares an XTS context for encryption and
+ *                 sets the encryption key.
+ *
+ * \param ctx      The AES XTS context to which the key should be bound.
+ * \param key      The encryption key. This is comprised of the XTS key1
+ *                 concatenated with the XTS key2.
+ * \param keybits  The size of \p key passed in bits. Valid options are:
+ *                 <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
+ *                 <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
+ *
+ * \return         \c 0 on success.
+ * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
+ */
+int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
+                                const unsigned char *key,
+                                unsigned int keybits );
+
+/**
+ * \brief          This function prepares an XTS context for decryption and
+ *                 sets the decryption key.
+ *
+ * \param ctx      The AES XTS context to which the key should be bound.
+ * \param key      The decryption key. This is comprised of the XTS key1
+ *                 concatenated with the XTS key2.
+ * \param keybits  The size of \p key passed in bits. Valid options are:
+ *                 <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
+ *                 <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
+ *
+ * \return         \c 0 on success.
+ * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
+ */
+int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
+                                const unsigned char *key,
+                                unsigned int keybits );
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
+/**
+ * \brief          This function performs an AES single-block encryption or
+ *                 decryption operation.
+ *
+ *                 It performs the operation defined in the \p mode parameter
+ *                 (encrypt or decrypt), on the input data buffer defined in
+ *                 the \p input parameter.
+ *
+ *                 mbedtls_aes_init(), and either mbedtls_aes_setkey_enc() or
+ *                 mbedtls_aes_setkey_dec() must be called before the first
+ *                 call to this API with the same context.
+ *
+ * \param ctx      The AES context to use for encryption or decryption.
+ * \param mode     The AES operation: #MBEDTLS_AES_ENCRYPT or
+ *                 #MBEDTLS_AES_DECRYPT.
+ * \param input    The 16-Byte buffer holding the input data.
+ * \param output   The 16-Byte buffer holding the output data.
+
+ * \return         \c 0 on success.
+ */
+int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
+                    int mode,
+                    const unsigned char input[16],
+                    unsigned char output[16] );
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+/**
+ * \brief  This function performs an AES-CBC encryption or decryption operation
+ *         on full blocks.
+ *
+ *         It performs the operation defined in the \p mode
+ *         parameter (encrypt/decrypt), on the input data buffer defined in
+ *         the \p input parameter.
+ *
+ *         It can be called as many times as needed, until all the input
+ *         data is processed. mbedtls_aes_init(), and either
+ *         mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called
+ *         before the first call to this API with the same context.
+ *
+ * \note   This function operates on aligned blocks, that is, the input size
+ *         must be a multiple of the AES block size of 16 Bytes.
+ *
+ * \note   Upon exit, the content of the IV is updated so that you can
+ *         call the same function again on the next
+ *         block(s) of data and get the same result as if it was
+ *         encrypted in one call. This allows a "streaming" usage.
+ *         If you need to retain the contents of the IV, you should
+ *         either save it manually or use the cipher module instead.
+ *
+ *
+ * \param ctx      The AES context to use for encryption or decryption.
+ * \param mode     The AES operation: #MBEDTLS_AES_ENCRYPT or
+ *                 #MBEDTLS_AES_DECRYPT.
+ * \param length   The length of the input data in Bytes. This must be a
+ *                 multiple of the block size (16 Bytes).
+ * \param iv       Initialization vector (updated after use).
+ * \param input    The buffer holding the input data.
+ * \param output   The buffer holding the output data.
+ *
+ * \return         \c 0 on success.
+ * \return         #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
+ *                 on failure.
+ */
+int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[16],
+                    const unsigned char *input,
+                    unsigned char *output );
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+/**
+ * \brief      This function performs an AES-XTS encryption or decryption
+ *             operation for an entire XTS data unit.
+ *
+ *             AES-XTS encrypts or decrypts blocks based on their location as
+ *             defined by a data unit number. The data unit number must be
+ *             provided by \p data_unit.
+ *
+ *             NIST SP 800-38E limits the maximum size of a data unit to 2^20
+ *             AES blocks. If the data unit is larger than this, this function
+ *             returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH.
+ *
+ * \param ctx          The AES XTS context to use for AES XTS operations.
+ * \param mode         The AES operation: #MBEDTLS_AES_ENCRYPT or
+ *                     #MBEDTLS_AES_DECRYPT.
+ * \param length       The length of a data unit in bytes. This can be any
+ *                     length between 16 bytes and 2^24 bytes inclusive
+ *                     (between 1 and 2^20 block cipher blocks).
+ * \param data_unit    The address of the data unit encoded as an array of 16
+ *                     bytes in little-endian format. For disk encryption, this
+ *                     is typically the index of the block device sector that
+ *                     contains the data.
+ * \param input        The buffer holding the input data (which is an entire
+ *                     data unit). This function reads \p length bytes from \p
+ *                     input.
+ * \param output       The buffer holding the output data (which is an entire
+ *                     data unit). This function writes \p length bytes to \p
+ *                     output.
+ *
+ * \return             \c 0 on success.
+ * \return             #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is
+ *                     smaller than an AES block in size (16 bytes) or if \p
+ *                     length is larger than 2^20 blocks (16 MiB).
+ */
+int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
+                           int mode,
+                           size_t length,
+                           const unsigned char data_unit[16],
+                           const unsigned char *input,
+                           unsigned char *output );
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+/**
+ * \brief This function performs an AES-CFB128 encryption or decryption
+ *        operation.
+ *
+ *        It performs the operation defined in the \p mode
+ *        parameter (encrypt or decrypt), on the input data buffer
+ *        defined in the \p input parameter.
+ *
+ *        For CFB, you must set up the context with mbedtls_aes_setkey_enc(),
+ *        regardless of whether you are performing an encryption or decryption
+ *        operation, that is, regardless of the \p mode parameter. This is
+ *        because CFB mode uses the same key schedule for encryption and
+ *        decryption.
+ *
+ * \note  Upon exit, the content of the IV is updated so that you can
+ *        call the same function again on the next
+ *        block(s) of data and get the same result as if it was
+ *        encrypted in one call. This allows a "streaming" usage.
+ *        If you need to retain the contents of the
+ *        IV, you must either save it manually or use the cipher
+ *        module instead.
+ *
+ *
+ * \param ctx      The AES context to use for encryption or decryption.
+ * \param mode     The AES operation: #MBEDTLS_AES_ENCRYPT or
+ *                 #MBEDTLS_AES_DECRYPT.
+ * \param length   The length of the input data.
+ * \param iv_off   The offset in IV (updated after use).
+ * \param iv       The initialization vector (updated after use).
+ * \param input    The buffer holding the input data.
+ * \param output   The buffer holding the output data.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
+                       int mode,
+                       size_t length,
+                       size_t *iv_off,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output );
+
+/**
+ * \brief This function performs an AES-CFB8 encryption or decryption
+ *        operation.
+ *
+ *        It performs the operation defined in the \p mode
+ *        parameter (encrypt/decrypt), on the input data buffer defined
+ *        in the \p input parameter.
+ *
+ *        Due to the nature of CFB, you must use the same key schedule for
+ *        both encryption and decryption operations. Therefore, you must
+ *        use the context initialized with mbedtls_aes_setkey_enc() for
+ *        both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT.
+ *
+ * \note  Upon exit, the content of the IV is updated so that you can
+ *        call the same function again on the next
+ *        block(s) of data and get the same result as if it was
+ *        encrypted in one call. This allows a "streaming" usage.
+ *        If you need to retain the contents of the
+ *        IV, you should either save it manually or use the cipher
+ *        module instead.
+ *
+ *
+ * \param ctx      The AES context to use for encryption or decryption.
+ * \param mode     The AES operation: #MBEDTLS_AES_ENCRYPT or
+ *                 #MBEDTLS_AES_DECRYPT
+ * \param length   The length of the input data.
+ * \param iv       The initialization vector (updated after use).
+ * \param input    The buffer holding the input data.
+ * \param output   The buffer holding the output data.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[16],
+                    const unsigned char *input,
+                    unsigned char *output );
+#endif /*MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+/**
+ * \brief       This function performs an AES-OFB (Output Feedback Mode)
+ *              encryption or decryption operation.
+ *
+ *              For OFB, you must set up the context with
+ *              mbedtls_aes_setkey_enc(), regardless of whether you are
+ *              performing an encryption or decryption operation. This is
+ *              because OFB mode uses the same key schedule for encryption and
+ *              decryption.
+ *
+ *              The OFB operation is identical for encryption or decryption,
+ *              therefore no operation mode needs to be specified.
+ *
+ * \note        Upon exit, the content of iv, the Initialisation Vector, is
+ *              updated so that you can call the same function again on the next
+ *              block(s) of data and get the same result as if it was encrypted
+ *              in one call. This allows a "streaming" usage, by initialising
+ *              iv_off to 0 before the first call, and preserving its value
+ *              between calls.
+ *
+ *              For non-streaming use, the iv should be initialised on each call
+ *              to a unique value, and iv_off set to 0 on each call.
+ *
+ *              If you need to retain the contents of the initialisation vector,
+ *              you must either save it manually or use the cipher module
+ *              instead.
+ *
+ * \warning     For the OFB mode, the initialisation vector must be unique
+ *              every encryption operation. Reuse of an initialisation vector
+ *              will compromise security.
+ *
+ * \param ctx      The AES context to use for encryption or decryption.
+ * \param length   The length of the input data.
+ * \param iv_off   The offset in IV (updated after use).
+ * \param iv       The initialization vector (updated after use).
+ * \param input    The buffer holding the input data.
+ * \param output   The buffer holding the output data.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
+                       size_t length,
+                       size_t *iv_off,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output );
+
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+/**
+ * \brief      This function performs an AES-CTR encryption or decryption
+ *             operation.
+ *
+ *             This function performs the operation defined in the \p mode
+ *             parameter (encrypt/decrypt), on the input data buffer
+ *             defined in the \p input parameter.
+ *
+ *             Due to the nature of CTR, you must use the same key schedule
+ *             for both encryption and decryption operations. Therefore, you
+ *             must use the context initialized with mbedtls_aes_setkey_enc()
+ *             for both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT.
+ *
+ * \warning    You must never reuse a nonce value with the same key. Doing so
+ *             would void the encryption for the two messages encrypted with
+ *             the same nonce and key.
+ *
+ *             There are two common strategies for managing nonces with CTR:
+ *
+ *             1. You can handle everything as a single message processed over
+ *             successive calls to this function. In that case, you want to
+ *             set \p nonce_counter and \p nc_off to 0 for the first call, and
+ *             then preserve the values of \p nonce_counter, \p nc_off and \p
+ *             stream_block across calls to this function as they will be
+ *             updated by this function.
+ *
+ *             With this strategy, you must not encrypt more than 2**128
+ *             blocks of data with the same key.
+ *
+ *             2. You can encrypt separate messages by dividing the \p
+ *             nonce_counter buffer in two areas: the first one used for a
+ *             per-message nonce, handled by yourself, and the second one
+ *             updated by this function internally.
+ *
+ *             For example, you might reserve the first 12 bytes for the
+ *             per-message nonce, and the last 4 bytes for internal use. In that
+ *             case, before calling this function on a new message you need to
+ *             set the first 12 bytes of \p nonce_counter to your chosen nonce
+ *             value, the last 4 to 0, and \p nc_off to 0 (which will cause \p
+ *             stream_block to be ignored). That way, you can encrypt at most
+ *             2**96 messages of up to 2**32 blocks each with the same key.
+ *
+ *             The per-message nonce (or information sufficient to reconstruct
+ *             it) needs to be communicated with the ciphertext and must be unique.
+ *             The recommended way to ensure uniqueness is to use a message
+ *             counter. An alternative is to generate random nonces, but this
+ *             limits the number of messages that can be securely encrypted:
+ *             for example, with 96-bit random nonces, you should not encrypt
+ *             more than 2**32 messages with the same key.
+ *
+ *             Note that for both stategies, sizes are measured in blocks and
+ *             that an AES block is 16 bytes.
+ *
+ * \warning    Upon return, \p stream_block contains sensitive data. Its
+ *             content must not be written to insecure storage and should be
+ *             securely discarded as soon as it's no longer needed.
+ *
+ * \param ctx              The AES context to use for encryption or decryption.
+ * \param length           The length of the input data.
+ * \param nc_off           The offset in the current \p stream_block, for
+ *                         resuming within the current cipher stream. The
+ *                         offset pointer should be 0 at the start of a stream.
+ * \param nonce_counter    The 128-bit nonce and counter.
+ * \param stream_block     The saved stream block for resuming. This is
+ *                         overwritten by the function.
+ * \param input            The buffer holding the input data.
+ * \param output           The buffer holding the output data.
+ *
+ * \return                 \c 0 on success.
+ */
+int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
+                       size_t length,
+                       size_t *nc_off,
+                       unsigned char nonce_counter[16],
+                       unsigned char stream_block[16],
+                       const unsigned char *input,
+                       unsigned char *output );
+#endif /* MBEDTLS_CIPHER_MODE_CTR */
+
+/**
+ * \brief           Internal AES block encryption function. This is only
+ *                  exposed to allow overriding it using
+ *                  \c MBEDTLS_AES_ENCRYPT_ALT.
+ *
+ * \param ctx       The AES context to use for encryption.
+ * \param input     The plaintext block.
+ * \param output    The output (ciphertext) block.
+ *
+ * \return          \c 0 on success.
+ */
+int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx,
+                                  const unsigned char input[16],
+                                  unsigned char output[16] );
+
+/**
+ * \brief           Internal AES block decryption function. This is only
+ *                  exposed to allow overriding it using see
+ *                  \c MBEDTLS_AES_DECRYPT_ALT.
+ *
+ * \param ctx       The AES context to use for decryption.
+ * \param input     The ciphertext block.
+ * \param output    The output (plaintext) block.
+ *
+ * \return          \c 0 on success.
+ */
+int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx,
+                                  const unsigned char input[16],
+                                  unsigned char output[16] );
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+#if defined(MBEDTLS_DEPRECATED_WARNING)
+#define MBEDTLS_DEPRECATED      __attribute__((deprecated))
+#else
+#define MBEDTLS_DEPRECATED
+#endif
+/**
+ * \brief           Deprecated internal AES block encryption function
+ *                  without return value.
+ *
+ * \deprecated      Superseded by mbedtls_aes_encrypt_ext() in 2.5.0.
+ *
+ * \param ctx       The AES context to use for encryption.
+ * \param input     Plaintext block.
+ * \param output    Output (ciphertext) block.
+ */
+MBEDTLS_DEPRECATED void mbedtls_aes_encrypt( mbedtls_aes_context *ctx,
+                                             const unsigned char input[16],
+                                             unsigned char output[16] );
+
+/**
+ * \brief           Deprecated internal AES block decryption function
+ *                  without return value.
+ *
+ * \deprecated      Superseded by mbedtls_aes_decrypt_ext() in 2.5.0.
+ *
+ * \param ctx       The AES context to use for decryption.
+ * \param input     Ciphertext block.
+ * \param output    Output (plaintext) block.
+ */
+MBEDTLS_DEPRECATED void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
+                                             const unsigned char input[16],
+                                             unsigned char output[16] );
+
+#undef MBEDTLS_DEPRECATED
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+
+/**
+ * \brief          Checkup routine.
+ *
+ * \return         \c 0 on success.
+ * \return         \c 1 on failure.
+ */
+int mbedtls_aes_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* aes.h */
diff --git a/common/mbedtls/arc4.c b/common/mbedtls/arc4.c
new file mode 100644 (file)
index 0000000..22992dd
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ *  An implementation of the ARCFOUR algorithm
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: GPL-2.0
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+/*
+ *  The ARCFOUR algorithm was publicly disclosed on 94/09.
+ *
+ *  http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_ARC4_C)
+
+#include "mbedtls/arc4.h"
+#include "mbedtls/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDTLS_SELF_TEST)
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#define mbedtls_printf printf
+#endif /* MBEDTLS_PLATFORM_C */
+#endif /* MBEDTLS_SELF_TEST */
+
+#if !defined(MBEDTLS_ARC4_ALT)
+
+void mbedtls_arc4_init( mbedtls_arc4_context *ctx )
+{
+    memset( ctx, 0, sizeof( mbedtls_arc4_context ) );
+}
+
+void mbedtls_arc4_free( mbedtls_arc4_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_arc4_context ) );
+}
+
+/*
+ * ARC4 key schedule
+ */
+void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key,
+                 unsigned int keylen )
+{
+    int i, j, a;
+    unsigned int k;
+    unsigned char *m;
+
+    ctx->x = 0;
+    ctx->y = 0;
+    m = ctx->m;
+
+    for( i = 0; i < 256; i++ )
+        m[i] = (unsigned char) i;
+
+    j = k = 0;
+
+    for( i = 0; i < 256; i++, k++ )
+    {
+        if( k >= keylen ) k = 0;
+
+        a = m[i];
+        j = ( j + a + key[k] ) & 0xFF;
+        m[i] = m[j];
+        m[j] = (unsigned char) a;
+    }
+}
+
+/*
+ * ARC4 cipher function
+ */
+int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input,
+                unsigned char *output )
+{
+    int x, y, a, b;
+    size_t i;
+    unsigned char *m;
+
+    x = ctx->x;
+    y = ctx->y;
+    m = ctx->m;
+
+    for( i = 0; i < length; i++ )
+    {
+        x = ( x + 1 ) & 0xFF; a = m[x];
+        y = ( y + a ) & 0xFF; b = m[y];
+
+        m[x] = (unsigned char) b;
+        m[y] = (unsigned char) a;
+
+        output[i] = (unsigned char)
+            ( input[i] ^ m[(unsigned char)( a + b )] );
+    }
+
+    ctx->x = x;
+    ctx->y = y;
+
+    return( 0 );
+}
+
+#endif /* !MBEDTLS_ARC4_ALT */
+
+#if defined(MBEDTLS_SELF_TEST)
+/*
+ * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994:
+ *
+ * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0
+ */
+static const unsigned char arc4_test_key[3][8] =
+{
+    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char arc4_test_pt[3][8] =
+{
+    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char arc4_test_ct[3][8] =
+{
+    { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 },
+    { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 },
+    { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A }
+};
+
+/*
+ * Checkup routine
+ */
+int mbedtls_arc4_self_test( int verbose )
+{
+    int i, ret = 0;
+    unsigned char ibuf[8];
+    unsigned char obuf[8];
+    mbedtls_arc4_context ctx;
+
+    mbedtls_arc4_init( &ctx );
+
+    for( i = 0; i < 3; i++ )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "  ARC4 test #%d: ", i + 1 );
+
+        memcpy( ibuf, arc4_test_pt[i], 8 );
+
+        mbedtls_arc4_setup( &ctx, arc4_test_key[i], 8 );
+        mbedtls_arc4_crypt( &ctx, 8, ibuf, obuf );
+
+        if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 )
+        {
+            if( verbose != 0 )
+                mbedtls_printf( "failed\n" );
+
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "\n" );
+
+exit:
+    mbedtls_arc4_free( &ctx );
+
+    return( ret );
+}
+
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_ARC4_C */
diff --git a/common/mbedtls/arc4.h b/common/mbedtls/arc4.h
new file mode 100644 (file)
index 0000000..0355fb8
--- /dev/null
@@ -0,0 +1,143 @@
+/**
+ * \file arc4.h
+ *
+ * \brief The ARCFOUR stream cipher
+ *
+ * \warning   ARC4 is considered a weak cipher and its use constitutes a
+ *            security risk. We recommend considering stronger ciphers instead.
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: GPL-2.0
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ */
+#ifndef MBEDTLS_ARC4_H
+#define MBEDTLS_ARC4_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED                  -0x0019  /**< ARC4 hardware accelerator failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDTLS_ARC4_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief     ARC4 context structure
+ *
+ * \warning   ARC4 is considered a weak cipher and its use constitutes a
+ *            security risk. We recommend considering stronger ciphers instead.
+ *
+ */
+typedef struct mbedtls_arc4_context
+{
+    int x;                      /*!< permutation index */
+    int y;                      /*!< permutation index */
+    unsigned char m[256];       /*!< permutation table */
+}
+mbedtls_arc4_context;
+
+#else  /* MBEDTLS_ARC4_ALT */
+#include "arc4_alt.h"
+#endif /* MBEDTLS_ARC4_ALT */
+
+/**
+ * \brief          Initialize ARC4 context
+ *
+ * \param ctx      ARC4 context to be initialized
+ *
+ * \warning        ARC4 is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ *
+ */
+void mbedtls_arc4_init( mbedtls_arc4_context *ctx );
+
+/**
+ * \brief          Clear ARC4 context
+ *
+ * \param ctx      ARC4 context to be cleared
+ *
+ * \warning        ARC4 is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ *
+ */
+void mbedtls_arc4_free( mbedtls_arc4_context *ctx );
+
+/**
+ * \brief          ARC4 key schedule
+ *
+ * \param ctx      ARC4 context to be setup
+ * \param key      the secret key
+ * \param keylen   length of the key, in bytes
+ *
+ * \warning        ARC4 is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ *
+ */
+void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key,
+                 unsigned int keylen );
+
+/**
+ * \brief          ARC4 cipher function
+ *
+ * \param ctx      ARC4 context
+ * \param length   length of the input data
+ * \param input    buffer holding the input data
+ * \param output   buffer for the output data
+ *
+ * \return         0 if successful
+ *
+ * \warning        ARC4 is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ *
+ */
+int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input,
+                unsigned char *output );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ *
+ * \warning        ARC4 is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ *
+ */
+int mbedtls_arc4_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* arc4.h */
diff --git a/common/mbedtls/asn1.h b/common/mbedtls/asn1.h
new file mode 100644 (file)
index 0000000..00b6f2c
--- /dev/null
@@ -0,0 +1,360 @@
+/**
+ * \file asn1.h
+ *
+ * \brief Generic ASN.1 parsing
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: GPL-2.0
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+#ifndef MBEDTLS_ASN1_H
+#define MBEDTLS_ASN1_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#if defined(MBEDTLS_BIGNUM_C)
+#include "bignum.h"
+#endif
+
+/**
+ * \addtogroup asn1_module
+ * \{
+ */
+
+/**
+ * \name ASN1 Error codes
+ * These error codes are OR'ed to X509 error codes for
+ * higher error granularity.
+ * ASN1 is a standard to specify data structures.
+ * \{
+ */
+#define MBEDTLS_ERR_ASN1_OUT_OF_DATA                      -0x0060  /**< Out of data when parsing an ASN1 data structure. */
+#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG                   -0x0062  /**< ASN1 tag was of an unexpected value. */
+#define MBEDTLS_ERR_ASN1_INVALID_LENGTH                   -0x0064  /**< Error when trying to determine the length or invalid length. */
+#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH                  -0x0066  /**< Actual length differs from expected length. */
+#define MBEDTLS_ERR_ASN1_INVALID_DATA                     -0x0068  /**< Data is invalid. (not used) */
+#define MBEDTLS_ERR_ASN1_ALLOC_FAILED                     -0x006A  /**< Memory allocation failed */
+#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL                    -0x006C  /**< Buffer too small when writing ASN.1 data structure. */
+
+/* \} name */
+
+/**
+ * \name DER constants
+ * These constants comply with the DER encoded ASN.1 type tags.
+ * DER encoding uses hexadecimal representation.
+ * An example DER sequence is:\n
+ * - 0x02 -- tag indicating INTEGER
+ * - 0x01 -- length in octets
+ * - 0x05 -- value
+ * Such sequences are typically read into \c ::mbedtls_x509_buf.
+ * \{
+ */
+#define MBEDTLS_ASN1_BOOLEAN                 0x01
+#define MBEDTLS_ASN1_INTEGER                 0x02
+#define MBEDTLS_ASN1_BIT_STRING              0x03
+#define MBEDTLS_ASN1_OCTET_STRING            0x04
+#define MBEDTLS_ASN1_NULL                    0x05
+#define MBEDTLS_ASN1_OID                     0x06
+#define MBEDTLS_ASN1_UTF8_STRING             0x0C
+#define MBEDTLS_ASN1_SEQUENCE                0x10
+#define MBEDTLS_ASN1_SET                     0x11
+#define MBEDTLS_ASN1_PRINTABLE_STRING        0x13
+#define MBEDTLS_ASN1_T61_STRING              0x14
+#define MBEDTLS_ASN1_IA5_STRING              0x16
+#define MBEDTLS_ASN1_UTC_TIME                0x17
+#define MBEDTLS_ASN1_GENERALIZED_TIME        0x18
+#define MBEDTLS_ASN1_UNIVERSAL_STRING        0x1C
+#define MBEDTLS_ASN1_BMP_STRING              0x1E
+#define MBEDTLS_ASN1_PRIMITIVE               0x00
+#define MBEDTLS_ASN1_CONSTRUCTED             0x20
+#define MBEDTLS_ASN1_CONTEXT_SPECIFIC        0x80
+
+/*
+ * Bit masks for each of the components of an ASN.1 tag as specified in
+ * ITU X.690 (08/2015), section 8.1 "General rules for encoding",
+ * paragraph 8.1.2.2:
+ *
+ * Bit  8     7   6   5          1
+ *     +-------+-----+------------+
+ *     | Class | P/C | Tag number |
+ *     +-------+-----+------------+
+ */
+#define MBEDTLS_ASN1_TAG_CLASS_MASK          0xC0
+#define MBEDTLS_ASN1_TAG_PC_MASK             0x20
+#define MBEDTLS_ASN1_TAG_VALUE_MASK          0x1F
+
+/* \} name */
+/* \} addtogroup asn1_module */
+
+/** Returns the size of the binary string, without the trailing \\0 */
+#define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1)
+
+/**
+ * Compares an mbedtls_asn1_buf structure to a reference OID.
+ *
+ * Only works for 'defined' oid_str values (MBEDTLS_OID_HMAC_SHA1), you cannot use a
+ * 'unsigned char *oid' here!
+ */
+#define MBEDTLS_OID_CMP(oid_str, oid_buf)                                   \
+        ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) ||                \
+          memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name Functions to parse ASN.1 data structures
+ * \{
+ */
+
+/**
+ * Type-length-value structure that allows for ASN1 using DER.
+ */
+typedef struct mbedtls_asn1_buf
+{
+    int tag;                /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */
+    size_t len;             /**< ASN1 length, in octets. */
+    unsigned char *p;       /**< ASN1 data, e.g. in ASCII. */
+}
+mbedtls_asn1_buf;
+
+/**
+ * Container for ASN1 bit strings.
+ */
+typedef struct mbedtls_asn1_bitstring
+{
+    size_t len;                 /**< ASN1 length, in octets. */
+    unsigned char unused_bits;  /**< Number of unused bits at the end of the string */
+    unsigned char *p;           /**< Raw ASN1 data for the bit string */
+}
+mbedtls_asn1_bitstring;
+
+/**
+ * Container for a sequence of ASN.1 items
+ */
+typedef struct mbedtls_asn1_sequence
+{
+    mbedtls_asn1_buf buf;                   /**< Buffer containing the given ASN.1 item. */
+    struct mbedtls_asn1_sequence *next;    /**< The next entry in the sequence. */
+}
+mbedtls_asn1_sequence;
+
+/**
+ * Container for a sequence or list of 'named' ASN.1 data items
+ */
+typedef struct mbedtls_asn1_named_data
+{
+    mbedtls_asn1_buf oid;                   /**< The object identifier. */
+    mbedtls_asn1_buf val;                   /**< The named value. */
+    struct mbedtls_asn1_named_data *next;  /**< The next entry in the sequence. */
+    unsigned char next_merged;      /**< Merge next item into the current one? */
+}
+mbedtls_asn1_named_data;
+
+/**
+ * \brief       Get the length of an ASN.1 element.
+ *              Updates the pointer to immediately behind the length.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param len   The variable that will receive the value
+ *
+ * \return      0 if successful, MBEDTLS_ERR_ASN1_OUT_OF_DATA on reaching
+ *              end of data, MBEDTLS_ERR_ASN1_INVALID_LENGTH if length is
+ *              unparseable.
+ */
+int mbedtls_asn1_get_len( unsigned char **p,
+                  const unsigned char *end,
+                  size_t *len );
+
+/**
+ * \brief       Get the tag and length of the tag. Check for the requested tag.
+ *              Updates the pointer to immediately behind the tag and length.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param len   The variable that will receive the length
+ * \param tag   The expected tag
+ *
+ * \return      0 if successful, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if tag did
+ *              not match requested tag, or another specific ASN.1 error code.
+ */
+int mbedtls_asn1_get_tag( unsigned char **p,
+                  const unsigned char *end,
+                  size_t *len, int tag );
+
+/**
+ * \brief       Retrieve a boolean ASN.1 tag and its value.
+ *              Updates the pointer to immediately behind the full tag.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param val   The variable that will receive the value
+ *
+ * \return      0 if successful or a specific ASN.1 error code.
+ */
+int mbedtls_asn1_get_bool( unsigned char **p,
+                   const unsigned char *end,
+                   int *val );
+
+/**
+ * \brief       Retrieve an integer ASN.1 tag and its value.
+ *              Updates the pointer to immediately behind the full tag.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param val   The variable that will receive the value
+ *
+ * \return      0 if successful or a specific ASN.1 error code.
+ */
+int mbedtls_asn1_get_int( unsigned char **p,
+                  const unsigned char *end,
+                  int *val );
+
+/**
+ * \brief       Retrieve a bitstring ASN.1 tag and its value.
+ *              Updates the pointer to immediately behind the full tag.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param bs    The variable that will receive the value
+ *
+ * \return      0 if successful or a specific ASN.1 error code.
+ */
+int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end,
+                        mbedtls_asn1_bitstring *bs);
+
+/**
+ * \brief       Retrieve a bitstring ASN.1 tag without unused bits and its
+ *              value.
+ *              Updates the pointer to the beginning of the bit/octet string.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param len   Length of the actual bit/octect string in bytes
+ *
+ * \return      0 if successful or a specific ASN.1 error code.
+ */
+int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
+                             size_t *len );
+
+/**
+ * \brief       Parses and splits an ASN.1 "SEQUENCE OF <tag>"
+ *              Updated the pointer to immediately behind the full sequence tag.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param cur   First variable in the chain to fill
+ * \param tag   Type of sequence
+ *
+ * \return      0 if successful or a specific ASN.1 error code.
+ */
+int mbedtls_asn1_get_sequence_of( unsigned char **p,
+                          const unsigned char *end,
+                          mbedtls_asn1_sequence *cur,
+                          int tag);
+
+#if defined(MBEDTLS_BIGNUM_C)
+/**
+ * \brief       Retrieve a MPI value from an integer ASN.1 tag.
+ *              Updates the pointer to immediately behind the full tag.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param X     The MPI that will receive the value
+ *
+ * \return      0 if successful or a specific ASN.1 or MPI error code.
+ */
+int mbedtls_asn1_get_mpi( unsigned char **p,
+                  const unsigned char *end,
+                  mbedtls_mpi *X );
+#endif /* MBEDTLS_BIGNUM_C */
+
+/**
+ * \brief       Retrieve an AlgorithmIdentifier ASN.1 sequence.
+ *              Updates the pointer to immediately behind the full
+ *              AlgorithmIdentifier.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param alg   The buffer to receive the OID
+ * \param params The buffer to receive the params (if any)
+ *
+ * \return      0 if successful or a specific ASN.1 or MPI error code.
+ */
+int mbedtls_asn1_get_alg( unsigned char **p,
+                  const unsigned char *end,
+                  mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params );
+
+/**
+ * \brief       Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no
+ *              params.
+ *              Updates the pointer to immediately behind the full
+ *              AlgorithmIdentifier.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param alg   The buffer to receive the OID
+ *
+ * \return      0 if successful or a specific ASN.1 or MPI error code.
+ */
+int mbedtls_asn1_get_alg_null( unsigned char **p,
+                       const unsigned char *end,
+                       mbedtls_asn1_buf *alg );
+
+/**
+ * \brief       Find a specific named_data entry in a sequence or list based on
+ *              the OID.
+ *
+ * \param list  The list to seek through
+ * \param oid   The OID to look for
+ * \param len   Size of the OID
+ *
+ * \return      NULL if not found, or a pointer to the existing entry.
+ */
+mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list,
+                                       const char *oid, size_t len );
+
+/**
+ * \brief       Free a mbedtls_asn1_named_data entry
+ *
+ * \param entry The named data entry to free
+ */
+void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry );
+
+/**
+ * \brief       Free all entries in a mbedtls_asn1_named_data list
+ *              Head will be set to NULL
+ *
+ * \param head  Pointer to the head of the list of named data entries to free
+ */
+void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* asn1.h */
diff --git a/common/mbedtls/asn1parse.c b/common/mbedtls/asn1parse.c
new file mode 100644 (file)
index 0000000..aeec173
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+ *  Generic ASN.1 parsing
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: GPL-2.0
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_ASN1_PARSE_C)
+
+#include "mbedtls/asn1.h"
+#include "mbedtls/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDTLS_BIGNUM_C)
+#include "mbedtls/bignum.h"
+#endif
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdlib.h>
+#define mbedtls_calloc    calloc
+#define mbedtls_free       free
+#endif
+
+/*
+ * ASN.1 DER decoding routines
+ */
+int mbedtls_asn1_get_len( unsigned char **p,
+                  const unsigned char *end,
+                  size_t *len )
+{
+    if( ( end - *p ) < 1 )
+        return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+
+    if( ( **p & 0x80 ) == 0 )
+        *len = *(*p)++;
+    else
+    {
+        switch( **p & 0x7F )
+        {
+        case 1:
+            if( ( end - *p ) < 2 )
+                return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+
+            *len = (*p)[1];
+            (*p) += 2;
+            break;
+
+        case 2:
+            if( ( end - *p ) < 3 )
+                return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+
+            *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2];
+            (*p) += 3;
+            break;
+
+        case 3:
+            if( ( end - *p ) < 4 )
+                return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+
+            *len = ( (size_t)(*p)[1] << 16 ) |
+                   ( (size_t)(*p)[2] << 8  ) | (*p)[3];
+            (*p) += 4;
+            break;
+
+        case 4:
+            if( ( end - *p ) < 5 )
+                return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+
+            *len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) |
+                   ( (size_t)(*p)[3] << 8  ) |           (*p)[4];
+            (*p) += 5;
+            break;
+
+        default:
+            return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+        }
+    }
+
+    if( *len > (size_t) ( end - *p ) )
+        return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+
+    return( 0 );
+}
+
+int mbedtls_asn1_get_tag( unsigned char **p,
+                  const unsigned char *end,
+                  size_t *len, int tag )
+{
+    if( ( end - *p ) < 1 )
+        return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+
+    if( **p != tag )
+        return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+
+    (*p)++;
+
+    return( mbedtls_asn1_get_len( p, end, len ) );
+}
+
+int mbedtls_asn1_get_bool( unsigned char **p,
+                   const unsigned char *end,
+                   int *val )
+{
+    int ret;
+    size_t len;
+
+    if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 )
+        return( ret );
+
+    if( len != 1 )
+        return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+
+    *val = ( **p != 0 ) ? 1 : 0;
+    (*p)++;
+
+    return( 0 );
+}
+
+int mbedtls_asn1_get_int( unsigned char **p,
+                  const unsigned char *end,
+                  int *val )
+{
+    int ret;
+    size_t len;
+
+    if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
+        return( ret );
+
+    if( len == 0 || len > sizeof( int ) || ( **p & 0x80 ) != 0 )
+        return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+
+    *val = 0;
+
+    while( len-- > 0 )
+    {
+        *val = ( *val << 8 ) | **p;
+        (*p)++;
+    }
+
+    return( 0 );
+}
+
+#if defined(MBEDTLS_BIGNUM_C)
+int mbedtls_asn1_get_mpi( unsigned char **p,
+                  const unsigned char *end,
+                  mbedtls_mpi *X )
+{
+    int ret;
+    size_t len;
+
+    if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
+        return( ret );
+
+    ret = mbedtls_mpi_read_binary( X, *p, len );
+
+    *p += len;
+
+    return( ret );
+}
+#endif /* MBEDTLS_BIGNUM_C */
+
+int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end,
+                        mbedtls_asn1_bitstring *bs)
+{
+    int ret;
+
+    /* Certificate type is a single byte bitstring */
+    if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 )
+        return( ret );
+
+    /* Check length, subtract one for actual bit string length */
+    if( bs->len < 1 )
+        return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+    bs->len -= 1;
+
+    /* Get number of unused bits, ensure unused bits <= 7 */
+    bs->unused_bits = **p;
+    if( bs->unused_bits > 7 )
+        return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+    (*p)++;
+
+    /* Get actual bitstring */
+    bs->p = *p;
+    *p += bs->len;
+
+    if( *p != end )
+        return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+/*
+ * Get a bit string without unused bits
+ */
+int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
+                             size_t *len )
+{
+    int ret;
+
+    if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 )
+        return( ret );
+
+    if( (*len)-- < 2 || *(*p)++ != 0 )
+        return( MBEDTLS_ERR_ASN1_INVALID_DATA );
+
+    return( 0 );
+}
+
+
+
+/*
+ *  Parses and splits an ASN.1 "SEQUENCE OF <tag>"
+ */
+int mbedtls_asn1_get_sequence_of( unsigned char **p,
+                          const unsigned char *end,
+                          mbedtls_asn1_sequence *cur,
+                          int tag)
+{
+    int ret;
+    size_t len;
+    mbedtls_asn1_buf *buf;
+
+    /* Get main sequence tag */
+    if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
+            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+        return( ret );
+
+    if( *p + len != end )
+        return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+
+    while( *p < end )
+    {
+        buf = &(cur->buf);
+        buf->tag = **p;
+
+        if( ( ret = mbedtls_asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
+            return( ret );
+
+        buf->p = *p;
+        *p += buf->len;
+
+        /* Allocate and assign next pointer */
+        if( *p < end )
+        {
+            cur->next = (mbedtls_asn1_sequence*)mbedtls_calloc( 1,
+                                            sizeof( mbedtls_asn1_sequence ) );
+
+            if( cur->next == NULL )
+                return( MBEDTLS_ERR_ASN1_ALLOC_FAILED );
+
+            cur = cur->next;
+        }
+    }
+
+    /* Set final sequence entry's next pointer to NULL */
+    cur->next = NULL;
+
+    if( *p != end )
+        return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+int mbedtls_asn1_get_alg( unsigned char **p,
+                  const unsigned char *end,
+                  mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params )
+{
+    int ret;
+    size_t len;
+
+    if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
+            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+        return( ret );
+
+    if( ( end - *p ) < 1 )
+        return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+
+    alg->tag = **p;
+    end = *p + len;
+
+    if( ( ret = mbedtls_asn1_get_tag( p, end, &alg->len, MBEDTLS_ASN1_OID ) ) != 0 )
+        return( ret );
+
+    alg->p = *p;
+    *p += alg->len;
+
+    if( *p == end )
+    {
+        mbedtls_platform_zeroize( params, sizeof(mbedtls_asn1_buf) );
+        return( 0 );
+    }
+
+    params->tag = **p;
+    (*p)++;
+
+    if( ( ret = mbedtls_asn1_get_len( p, end, &params->len ) ) != 0 )
+        return( ret );
+
+    params->p = *p;
+    *p += params->len;
+
+    if( *p != end )
+        return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+int mbedtls_asn1_get_alg_null( unsigned char **p,
+                       const unsigned char *end,
+                       mbedtls_asn1_buf *alg )
+{
+    int ret;
+    mbedtls_asn1_buf params;
+
+    memset( &params, 0, sizeof(mbedtls_asn1_buf) );
+
+    if( ( ret = mbedtls_asn1_get_alg( p, end, alg, &params ) ) != 0 )
+        return( ret );
+
+    if( ( params.tag != MBEDTLS_ASN1_NULL && params.tag != 0 ) || params.len != 0 )
+        return( MBEDTLS_ERR_ASN1_INVALID_DATA );
+
+    return( 0 );
+}
+
+void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur )
+{
+    if( cur == NULL )
+        return;
+
+    mbedtls_free( cur->oid.p );
+    mbedtls_free( cur->val.p );
+
+    mbedtls_platform_zeroize( cur, sizeof( mbedtls_asn1_named_data ) );
+}
+
+void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head )
+{
+    mbedtls_asn1_named_data *cur;
+
+    while( ( cur = *head ) != NULL )
+    {
+        *head = cur->next;
+        mbedtls_asn1_free_named_data( cur );
+        mbedtls_free( cur );
+    }
+}
+
+mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list,
+                                       const char *oid, size_t len )
+{
+    while( list != NULL )
+    {
+        if( list->oid.len == len &&
+            memcmp( list->oid.p, oid, len ) == 0 )
+        {
+            break;
+        }
+
+        list = list->next;
+    }
+
+    return( list );
+}
+
+#endif /* MBEDTLS_ASN1_PARSE_C */
diff --git a/common/mbedtls/asn1write.c b/common/mbedtls/asn1write.c
new file mode 100644 (file)
index 0000000..f8e29dc
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ * ASN.1 buffer writing functionality
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: GPL-2.0
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_ASN1_WRITE_C)
+
+#include "mbedtls/asn1write.h"
+
+#include <string.h>
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdlib.h>
+#define mbedtls_calloc    calloc
+#define mbedtls_free       free
+#endif
+
+int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len )
+{
+    if( len < 0x80 )
+    {
+        if( *p - start < 1 )
+            return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+
+        *--(*p) = (unsigned char) len;
+        return( 1 );
+    }
+
+    if( len <= 0xFF )
+    {
+        if( *p - start < 2 )
+            return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+
+        *--(*p) = (unsigned char) len;
+        *--(*p) = 0x81;
+        return( 2 );
+    }
+
+    if( len <= 0xFFFF )
+    {
+        if( *p - start < 3 )
+            return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+
+        *--(*p) = ( len       ) & 0xFF;
+        *--(*p) = ( len >>  8 ) & 0xFF;
+        *--(*p) = 0x82;
+        return( 3 );
+    }
+
+    if( len <= 0xFFFFFF )
+    {
+        if( *p - start < 4 )
+            return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+
+        *--(*p) = ( len       ) & 0xFF;
+        *--(*p) = ( len >>  8 ) & 0xFF;
+        *--(*p) = ( len >> 16 ) & 0xFF;
+        *--(*p) = 0x83;
+        return( 4 );
+    }
+
+#if SIZE_MAX > 0xFFFFFFFF
+    if( len <= 0xFFFFFFFF )
+#endif
+    {
+        if( *p - start < 5 )
+            return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+
+        *--(*p) = ( len       ) & 0xFF;
+        *--(*p) = ( len >>  8 ) & 0xFF;
+        *--(*p) = ( len >> 16 ) & 0xFF;
+        *--(*p) = ( len >> 24 ) & 0xFF;
+        *--(*p) = 0x84;
+        return( 5 );
+    }
+
+#if SIZE_MAX > 0xFFFFFFFF
+    return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+#endif
+}
+
+int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag )
+{
+    if( *p - start < 1 )
+        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+
+    *--(*p) = tag;
+
+    return( 1 );
+}
+
+int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
+                           const unsigned char *buf, size_t size )
+{
+    size_t len = 0;
+
+    if( *p < start || (size_t)( *p - start ) < size )
+        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+
+    len = size;
+    (*p) -= len;
+    memcpy( *p, buf, len );
+
+    return( (int) len );
+}
+
+#if defined(MBEDTLS_BIGNUM_C)
+int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X )
+{
+    int ret;
+    size_t len = 0;
+
+    // Write the MPI
+    //
+    len = mbedtls_mpi_size( X );
+
+    if( *p < start || (size_t)( *p - start ) < len )
+        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+
+    (*p) -= len;
+    MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) );
+
+    // DER format assumes 2s complement for numbers, so the leftmost bit
+    // should be 0 for positive numbers and 1 for negative numbers.
+    //
+    if( X->s ==1 && **p & 0x80 )
+    {
+        if( *p - start < 1 )
+            return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+
+        *--(*p) = 0x00;
+        len += 1;
+    }
+
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) );
+
+    ret = (int) len;
+
+cleanup:
+    return( ret );
+}
+#endif /* MBEDTLS_BIGNUM_C */
+
+int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start )
+{
+    int ret;
+    size_t len = 0;
+
+    // Write NULL
+    //
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) );
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) );
+
+    return( (int) len );
+}
+
+int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start,
+                    const char *oid, size_t oid_len )
+{
+    int ret;
+    size_t len = 0;
+
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
+                                  (const unsigned char *) oid, oid_len ) );
+    MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) );
+    MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) );
+
+    return( (int) len );
+}
+
+int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start,
+                                     const char *oid, size_t oid_len,
+                                     size_t par_len )
+{
+    int ret;
+    size_t len = 0;
+
+    if( par_len == 0 )
+        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) );
+    else
+        len += par_len;
+
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
+
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
+                                       MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
+
+    return( (int) len );
+}
+
+int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean )
+{
+    int ret;
+    size_t len = 0;
+
+    if( *p - start < 1 )
+        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+
+    *--(*p) = (boolean) ? 255 : 0;
+    len++;
+
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) );
+
+    return( (int) len );
+}
+
+int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
+{
+    int ret;
+    size_t len = 0;
+
+    if( *p - start < 1 )
+        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+
+    len += 1;
+    *--(*p) = val;
+
+    if( val > 0 && **p & 0x80 )
+    {
+        if( *p - start < 1 )
+            return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+
+        *--(*p) = 0x00;
+        len += 1;
+    }
+
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) );
+
+    return( (int) len );
+}
+
+int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start,
+                                 const char *text, size_t text_len )
+{
+    int ret;
+    size_t len = 0;
+
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
+                  (const unsigned char *) text, text_len ) );
+
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_PRINTABLE_STRING ) );
+
+    return( (int) len );
+}
+
+int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start,
+                           const char *text, size_t text_len )
+{
+    int ret;
+    size_t len = 0;
+
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
+                  (const unsigned char *) text, text_len ) );
+
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_IA5_STRING ) );
+
+    return( (int) len );
+}
+
+int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,
+                          const unsigned char *buf, size_t bits )
+{
+    int ret;
+    size_t len = 0, size;
+
+    size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 );
+
+    // Calculate byte length
+    //
+    if( *p < start || (size_t)( *p - start ) < size + 1 )
+        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+
+    len = size + 1;
+    (*p) -= size;
+    memcpy( *p, buf, size );
+
+    // Write unused bits
+    //
+    *--(*p) = (unsigned char) (size * 8 - bits);
+
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) );
+
+    return( (int) len );
+}
+
+int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start,
+                             const unsigned char *buf, size_t size )
+{
+    int ret;
+    size_t len = 0;
+
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) );
+
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) );
+
+    return( (int) len );
+}
+
+mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **head,
+                                        const char *oid, size_t oid_len,
+                                        const unsigned char *val,
+                                        size_t val_len )
+{
+    mbedtls_asn1_named_data *cur;
+
+    if( ( cur = mbedtls_asn1_find_named_data( *head, oid, oid_len ) ) == NULL )
+    {
+        // Add new entry if not present yet based on OID
+        //
+        cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1,
+                                            sizeof(mbedtls_asn1_named_data) );
+        if( cur == NULL )
+            return( NULL );
+
+        cur->oid.len = oid_len;
+        cur->oid.p = mbedtls_calloc( 1, oid_len );
+        if( cur->oid.p == NULL )
+        {
+            mbedtls_free( cur );
+            return( NULL );
+        }
+
+        memcpy( cur->oid.p, oid, oid_len );
+
+        cur->val.len = val_len;
+        cur->val.p = mbedtls_calloc( 1, val_len );
+        if( cur->val.p == NULL )
+        {
+            mbedtls_free( cur->oid.p );
+            mbedtls_free( cur );
+            return( NULL );
+        }
+
+        cur->next = *head;
+        *head = cur;
+    }
+    else if( cur->val.len < val_len )
+    {
+        /*
+         * Enlarge existing value buffer if needed
+         * Preserve old data until the allocation succeeded, to leave list in
+         * a consistent state in case allocation fails.
+         */
+        void *p = mbedtls_calloc( 1, val_len );
+        if( p == NULL )
+            return( NULL );
+
+        mbedtls_free( cur->val.p );
+        cur->val.p = p;
+        cur->val.len = val_len;
+    }
+
+    if( val != NULL )
+        memcpy( cur->val.p, val, val_len );
+
+    return( cur );
+}
+#endif /* MBEDTLS_ASN1_WRITE_C */
diff --git a/common/mbedtls/asn1write.h b/common/mbedtls/asn1write.h
new file mode 100644 (file)
index 0000000..0b832e5
--- /dev/null
@@ -0,0 +1,242 @@
+/**
+ * \file asn1write.h
+ *
+ * \brief ASN.1 buffer writing functionality
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: GPL-2.0
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+#ifndef MBEDTLS_ASN1_WRITE_H
+#define MBEDTLS_ASN1_WRITE_H
+
+#include "asn1.h"
+
+#define MBEDTLS_ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else   \
+                                g += ret; } while( 0 )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief           Write a length field in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param len       the length to write
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len );
+
+/**
+ * \brief           Write a ASN.1 tag in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param tag       the tag to write
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start,
+                    unsigned char tag );
+
+/**
+ * \brief           Write raw buffer data
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param buf       data buffer to write
+ * \param size      length of the data buffer
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
+                           const unsigned char *buf, size_t size );
+
+#if defined(MBEDTLS_BIGNUM_C)
+/**
+ * \brief           Write a big number (MBEDTLS_ASN1_INTEGER) in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param X         the MPI to write
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X );
+#endif /* MBEDTLS_BIGNUM_C */
+
+/**
+ * \brief           Write a NULL tag (MBEDTLS_ASN1_NULL) with zero data in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start );
+
+/**
+ * \brief           Write an OID tag (MBEDTLS_ASN1_OID) and data in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param oid       the OID to write
+ * \param oid_len   length of the OID
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start,
+                    const char *oid, size_t oid_len );
+
+/**
+ * \brief           Write an AlgorithmIdentifier sequence in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param oid       the OID of the algorithm
+ * \param oid_len   length of the OID
+ * \param par_len   length of parameters, which must be already written.
+ *                  If 0, NULL parameters are added
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start,
+                                     const char *oid, size_t oid_len,
+                                     size_t par_len );
+
+/**
+ * \brief           Write a boolean tag (MBEDTLS_ASN1_BOOLEAN) and value in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param boolean   0 or 1
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean );
+
+/**
+ * \brief           Write an int tag (MBEDTLS_ASN1_INTEGER) and value in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param val       the integer value
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val );
+
+/**
+ * \brief           Write a printable string tag (MBEDTLS_ASN1_PRINTABLE_STRING) and
+ *                  value in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param text      the text to write
+ * \param text_len  length of the text
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start,
+                                 const char *text, size_t text_len );
+
+/**
+ * \brief           Write an IA5 string tag (MBEDTLS_ASN1_IA5_STRING) and
+ *                  value in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param text      the text to write
+ * \param text_len  length of the text
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start,
+                           const char *text, size_t text_len );
+
+/**
+ * \brief           Write a bitstring tag (MBEDTLS_ASN1_BIT_STRING) and
+ *                  value in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param buf       the bitstring
+ * \param bits      the total number of bits in the bitstring
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,
+                          const unsigned char *buf, size_t bits );
+
+/**
+ * \brief           Write an octet string tag (MBEDTLS_ASN1_OCTET_STRING) and
+ *                  value in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param buf       data buffer to write
+ * \param size      length of the data buffer
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start,
+                             const unsigned char *buf, size_t size );
+
+/**
+ * \brief           Create or find a specific named_data entry for writing in a
+ *                  sequence or list based on the OID. If not already in there,
+ *                  a new entry is added to the head of the list.
+ *                  Warning: Destructive behaviour for the val data!
+ *
+ * \param list      Pointer to the location of the head of the list to seek
+ *                  through (will be updated in case of a new entry)
+ * \param oid       The OID to look for
+ * \param oid_len   Size of the OID
+ * \param val       Data to store (can be NULL if you want to fill it by hand)
+ * \param val_len   Minimum length of the data buffer needed
+ *
+ * \return      NULL if if there was a memory allocation error, or a pointer
+ *              to the new / existing entry.
+ */
+mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list,
+                                        const char *oid, size_t oid_len,
+                                        const unsigned char *val,
+                                        size_t val_len );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_ASN1_WRITE_H */
diff --git a/common/mbedtls/base64.c b/common/mbedtls/base64.c
new file mode 100644 (file)
index 0000000..4120002
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ *  RFC 1521 base64 encoding/decoding
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: GPL-2.0
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_BASE64_C)
+
+#include "mbedtls/base64.h"
+
+#include <stdint.h>
+
+#if defined(MBEDTLS_SELF_TEST)
+#include <string.h>
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#define mbedtls_printf printf
+#endif /* MBEDTLS_PLATFORM_C */
+#endif /* MBEDTLS_SELF_TEST */
+
+static const unsigned char base64_enc_map[64] =
+{
+    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+    'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+    'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
+    'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+    'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
+    '8', '9', '+', '/'
+};
+
+static const unsigned char base64_dec_map[128] =
+{
+    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+    127, 127, 127,  62, 127, 127, 127,  63,  52,  53,
+     54,  55,  56,  57,  58,  59,  60,  61, 127, 127,
+    127,  64, 127, 127, 127,   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, 127, 127, 127, 127, 127, 127,  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, 127, 127, 127, 127, 127
+};
+
+#define BASE64_SIZE_T_MAX   ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
+
+/*
+ * Encode a buffer into base64 format
+ */
+int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
+                   const unsigned char *src, size_t slen )
+{
+    size_t i, n;
+    int C1, C2, C3;
+    unsigned char *p;
+
+    if( slen == 0 )
+    {
+        *olen = 0;
+        return( 0 );
+    }
+
+    n = slen / 3 + ( slen % 3 != 0 );
+
+    if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 )
+    {
+        *olen = BASE64_SIZE_T_MAX;
+        return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
+    }
+
+    n *= 4;
+
+    if( ( dlen < n + 1 ) || ( NULL == dst ) )
+    {
+        *olen = n + 1;
+        return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
+    }
+
+    n = ( slen / 3 ) * 3;
+
+    for( i = 0, p = dst; i < n; i += 3 )
+    {
+        C1 = *src++;
+        C2 = *src++;
+        C3 = *src++;
+
+        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
+        *p++ = base64_enc_map[(((C1 &  3) << 4) + (C2 >> 4)) & 0x3F];
+        *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
+        *p++ = base64_enc_map[C3 & 0x3F];
+    }
+
+    if( i < slen )
+    {
+        C1 = *src++;
+        C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
+
+        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
+        *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
+
+        if( ( i + 1 ) < slen )
+             *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
+        else *p++ = '=';
+
+        *p++ = '=';
+    }
+
+    *olen = p - dst;
+    *p = 0;
+
+    return( 0 );
+}
+
+/*
+ * Decode a base64-formatted buffer
+ */
+int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
+                   const unsigned char *src, size_t slen )
+{
+    size_t i, n;
+    uint32_t j, x;
+    unsigned char *p;
+
+    /* First pass: check for validity and get output length */
+    for( i = n = j = 0; i < slen; i++ )
+    {
+        /* Skip spaces before checking for EOL */
+        x = 0;
+        while( i < slen && src[i] == ' ' )
+        {
+            ++i;
+            ++x;
+        }
+
+        /* Spaces at end of buffer are OK */
+        if( i == slen )
+            break;
+
+        if( ( slen - i ) >= 2 &&
+            src[i] == '\r' && src[i + 1] == '\n' )
+            continue;
+
+        if( src[i] == '\n' )
+            continue;
+
+        /* Space inside a line is an error */
+        if( x != 0 )
+            return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+
+        if( src[i] == '=' && ++j > 2 )
+            return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+
+        if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
+            return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+
+        if( base64_dec_map[src[i]] < 64 && j != 0 )
+            return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+
+        n++;
+    }
+
+    if( n == 0 )
+    {
+        *olen = 0;
+        return( 0 );
+    }
+
+    /* The following expression is to calculate the following formula without
+     * risk of integer overflow in n:
+     *     n = ( ( n * 6 ) + 7 ) >> 3;
+     */
+    n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 );
+    n -= j;
+
+    if( dst == NULL || dlen < n )
+    {
+        *olen = n;
+        return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
+    }
+
+   for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
+   {
+        if( *src == '\r' || *src == '\n' || *src == ' ' )
+            continue;
+
+        j -= ( base64_dec_map[*src] == 64 );
+        x  = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
+
+        if( ++n == 4 )
+        {
+            n = 0;
+            if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
+            if( j > 1 ) *p++ = (unsigned char)( x >>  8 );
+            if( j > 2 ) *p++ = (unsigned char)( x       );
+        }
+    }
+
+    *olen = p - dst;
+
+    return( 0 );
+}
+
+#if defined(MBEDTLS_SELF_TEST)
+
+static const unsigned char base64_test_dec[64] =
+{
+    0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
+    0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
+    0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
+    0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
+    0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
+    0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
+    0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
+    0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
+};
+
+static const unsigned char base64_test_enc[] =
+    "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
+    "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
+
+/*
+ * Checkup routine
+ */
+int mbedtls_base64_self_test( int verbose )
+{
+    size_t len;
+    const unsigned char *src;
+    unsigned char buffer[128];
+
+    if( verbose != 0 )
+        mbedtls_printf( "  Base64 encoding test: " );
+
+    src = base64_test_dec;
+
+    if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 ||
+         memcmp( base64_test_enc, buffer, 88 ) != 0 )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "passed\n  Base64 decoding test: " );
+
+    src = base64_test_enc;
+
+    if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 ||
+         memcmp( base64_test_dec, buffer, 64 ) != 0 )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "passed\n\n" );
+
+    return( 0 );
+}
+
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_BASE64_C */
diff --git a/common/mbedtls/base64.h b/common/mbedtls/base64.h
new file mode 100644 (file)
index 0000000..ce5563e
--- /dev/null
@@ -0,0 +1,91 @@
+/**
+ * \file base64.h
+ *
+ * \brief RFC 1521 base64 encoding/decoding
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: GPL-2.0
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+#ifndef MBEDTLS_BASE64_H
+#define MBEDTLS_BASE64_H
+
+#include <stddef.h>
+
+#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL               -0x002A  /**< Output buffer too small. */
+#define MBEDTLS_ERR_BASE64_INVALID_CHARACTER              -0x002C  /**< Invalid character in input. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Encode a buffer into base64 format
+ *
+ * \param dst      destination buffer
+ * \param dlen     size of the destination buffer
+ * \param olen     number of bytes written
+ * \param src      source buffer
+ * \param slen     amount of data to be encoded
+ *
+ * \return         0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL.
+ *                 *olen is always updated to reflect the amount
+ *                 of data that has (or would have) been written.
+ *                 If that length cannot be represented, then no data is
+ *                 written to the buffer and *olen is set to the maximum
+ *                 length representable as a size_t.
+ *
+ * \note           Call this function with dlen = 0 to obtain the
+ *                 required buffer size in *olen
+ */
+int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
+                   const unsigned char *src, size_t slen );
+
+/**
+ * \brief          Decode a base64-formatted buffer
+ *
+ * \param dst      destination buffer (can be NULL for checking size)
+ * \param dlen     size of the destination buffer
+ * \param olen     number of bytes written
+ * \param src      source buffer
+ * \param slen     amount of data to be decoded
+ *
+ * \return         0 if successful, MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL, or
+ *                 MBEDTLS_ERR_BASE64_INVALID_CHARACTER if the input data is
+ *                 not correct. *olen is always updated to reflect the amount
+ *                 of data that has (or would have) been written.
+ *
+ * \note           Call this function with *dst = NULL or dlen = 0 to obtain
+ *                 the required buffer size in *olen
+ */
+int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
+                   const unsigned char *src, size_t slen );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int mbedtls_base64_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* base64.h */
diff --git a/common/mbedtls/bignum.c b/common/mbedtls/bignum.c
new file mode 100644 (file)
index 0000000..2c9ecbe
--- /dev/null
@@ -0,0 +1,2470 @@
+/*
+ *  Multi-precision integer library
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: GPL-2.0
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+/*
+ *  The following sources were referenced in the design of this Multi-precision
+ *  Integer library:
+ *
+ *  [1] Handbook of Applied Cryptography - 1997
+ *      Menezes, van Oorschot and Vanstone
+ *
+ *  [2] Multi-Precision Math
+ *      Tom St Denis
+ *      https://github.com/libtom/libtommath/blob/develop/tommath.pdf
+ *
+ *  [3] GNU Multi-Precision Arithmetic Library
+ *      https://gmplib.org/manual/index.html
+ *
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_BIGNUM_C)
+
+#include "mbedtls/bignum.h"
+#include "mbedtls/bn_mul.h"
+#include "mbedtls/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#define mbedtls_printf     printf
+#define mbedtls_calloc    calloc
+#define mbedtls_free       free
+#endif
+
+#define ciL    (sizeof(mbedtls_mpi_uint))         /* chars in limb  */
+#define biL    (ciL << 3)               /* bits  in limb  */
+#define biH    (ciL << 2)               /* half limb size */
+
+#define MPI_SIZE_T_MAX  ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
+
+/*
+ * Convert between bits/chars and number of limbs
+ * Divide first in order to avoid potential overflows
+ */
+#define BITS_TO_LIMBS(i)  ( (i) / biL + ( (i) % biL != 0 ) )
+#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
+
+/* Implementation that should never be optimized out by the compiler */
+static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
+{
+    mbedtls_platform_zeroize( v, ciL * n );
+}
+
+/*
+ * Initialize one MPI
+ */
+void mbedtls_mpi_init( mbedtls_mpi *X )
+{
+    if( X == NULL )
+        return;
+
+    X->s = 1;
+    X->n = 0;
+    X->p = NULL;
+}
+
+/*
+ * Unallocate one MPI
+ */
+void mbedtls_mpi_free( mbedtls_mpi *X )
+{
+    if( X == NULL )
+        return;
+
+    if( X->p != NULL )
+    {
+        mbedtls_mpi_zeroize( X->p, X->n );
+        mbedtls_free( X->p );
+    }
+
+    X->s = 1;
+    X->n = 0;
+    X->p = NULL;
+}
+
+/*
+ * Enlarge to the specified number of limbs
+ */
+int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
+{
+    mbedtls_mpi_uint *p;
+
+    if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
+        return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
+
+    if( X->n < nblimbs )
+    {
+        if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
+            return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
+
+        if( X->p != NULL )
+        {
+            memcpy( p, X->p, X->n * ciL );
+            mbedtls_mpi_zeroize( X->p, X->n );
+            mbedtls_free( X->p );
+        }
+
+        X->n = nblimbs;
+        X->p = p;
+    }
+
+    return( 0 );
+}
+
+/*
+ * Resize down as much as possible,
+ * while keeping at least the specified number of limbs
+ */
+int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
+{
+    mbedtls_mpi_uint *p;
+    size_t i;
+
+    /* Actually resize up in this case */
+    if( X->n <= nblimbs )
+        return( mbedtls_mpi_grow( X, nblimbs ) );
+
+    for( i = X->n - 1; i > 0; i-- )
+        if( X->p[i] != 0 )
+            break;
+    i++;
+
+    if( i < nblimbs )
+        i = nblimbs;
+
+    if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
+        return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
+
+    if( X->p != NULL )
+    {
+        memcpy( p, X->p, i * ciL );
+        mbedtls_mpi_zeroize( X->p, X->n );
+        mbedtls_free( X->p );
+    }
+
+    X->n = i;
+    X->p = p;
+
+    return( 0 );
+}
+
+/*
+ * Copy the contents of Y into X
+ */
+int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
+{
+    int ret = 0;
+    size_t i;
+
+    if( X == Y )
+        return( 0 );
+
+    if( Y->p == NULL )
+    {
+        mbedtls_mpi_free( X );
+        return( 0 );
+    }
+
+    for( i = Y->n - 1; i > 0; i-- )
+        if( Y->p[i] != 0 )
+            break;
+    i++;
+
+    X->s = Y->s;
+
+    if( X->n < i )
+    {
+        MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
+    }
+    else
+    {
+        memset( X->p + i, 0, ( X->n - i ) * ciL );
+    }
+
+    memcpy( X->p, Y->p, i * ciL );
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Swap the contents of X and Y
+ */
+void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
+{
+    mbedtls_mpi T;
+
+    memcpy( &T,  X, sizeof( mbedtls_mpi ) );
+    memcpy(  X,  Y, sizeof( mbedtls_mpi ) );
+    memcpy(  Y, &T, sizeof( mbedtls_mpi ) );
+}
+
+/*
+ * Conditionally assign X = Y, without leaking information
+ * about whether the assignment was made or not.
+ * (Leaking information about the respective sizes of X and Y is ok however.)
+ */
+int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
+{
+    int ret = 0;
+    size_t i;
+
+    /* make sure assign is 0 or 1 in a time-constant manner */
+    assign = (assign | (unsigned char)-assign) >> 7;
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
+
+    X->s = X->s * ( 1 - assign ) + Y->s * assign;
+
+    for( i = 0; i < Y->n; i++ )
+        X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
+
+    for( ; i < X->n; i++ )
+        X->p[i] *= ( 1 - assign );
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Conditionally swap X and Y, without leaking information
+ * about whether the swap was made or not.
+ * Here it is not ok to simply swap the pointers, which whould lead to
+ * different memory access patterns when X and Y are used afterwards.
+ */
+int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
+{
+    int ret, s;
+    size_t i;
+    mbedtls_mpi_uint tmp;
+
+    if( X == Y )
+        return( 0 );
+
+    /* make sure swap is 0 or 1 in a time-constant manner */
+    swap = (swap | (unsigned char)-swap) >> 7;
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
+
+    s = X->s;
+    X->s = X->s * ( 1 - swap ) + Y->s * swap;
+    Y->s = Y->s * ( 1 - swap ) +    s * swap;
+
+
+    for( i = 0; i < X->n; i++ )
+    {
+        tmp = X->p[i];
+        X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
+        Y->p[i] = Y->p[i] * ( 1 - swap ) +     tmp * swap;
+    }
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Set value from integer
+ */
+int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
+{
+    int ret;
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
+    memset( X->p, 0, X->n * ciL );
+
+    X->p[0] = ( z < 0 ) ? -z : z;
+    X->s    = ( z < 0 ) ? -1 : 1;
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Get a specific bit
+ */
+int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
+{
+    if( X->n * biL <= pos )
+        return( 0 );
+
+    return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
+}
+
+/*
+ * Set a bit to a specific value of 0 or 1
+ */
+int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
+{
+    int ret = 0;
+    size_t off = pos / biL;
+    size_t idx = pos % biL;
+
+    if( val != 0 && val != 1 )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+    if( X->n * biL <= pos )
+    {
+        if( val == 0 )
+            return( 0 );
+
+        MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
+    }
+
+    X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
+    X->p[off] |= (mbedtls_mpi_uint) val << idx;
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Return the number of less significant zero-bits
+ */
+size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
+{
+    size_t i, j, count = 0;
+
+    for( i = 0; i < X->n; i++ )
+        for( j = 0; j < biL; j++, count++ )
+            if( ( ( X->p[i] >> j ) & 1 ) != 0 )
+                return( count );
+
+    return( 0 );
+}
+
+/*
+ * Count leading zero bits in a given integer
+ */
+static size_t mbedtls_clz( const mbedtls_mpi_uint x )
+{
+    size_t j;
+    mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
+
+    for( j = 0; j < biL; j++ )
+    {
+        if( x & mask ) break;
+
+        mask >>= 1;
+    }
+
+    return j;
+}
+
+/*
+ * Return the number of bits
+ */
+size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
+{
+    size_t i, j;
+
+    if( X->n == 0 )
+        return( 0 );
+
+    for( i = X->n - 1; i > 0; i-- )
+        if( X->p[i] != 0 )
+            break;
+
+    j = biL - mbedtls_clz( X->p[i] );
+
+    return( ( i * biL ) + j );
+}
+
+/*
+ * Return the total size in bytes
+ */
+size_t mbedtls_mpi_size( const mbedtls_mpi *X )
+{
+    return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
+}
+
+/*
+ * Convert an ASCII character to digit value
+ */
+static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
+{
+    *d = 255;
+
+    if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
+    if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
+    if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
+
+    if( *d >= (mbedtls_mpi_uint) radix )
+        return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
+
+    return( 0 );
+}
+
+/*
+ * Import from an ASCII string
+ */
+int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
+{
+    int ret;
+    size_t i, j, slen, n;
+    mbedtls_mpi_uint d;
+    mbedtls_mpi T;
+
+    if( radix < 2 || radix > 16 )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+    mbedtls_mpi_init( &T );
+
+    slen = strlen( s );
+
+    if( radix == 16 )
+    {
+        if( slen > MPI_SIZE_T_MAX >> 2 )
+            return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+        n = BITS_TO_LIMBS( slen << 2 );
+
+        MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
+
+        for( i = slen, j = 0; i > 0; i--, j++ )
+        {
+            if( i == 1 && s[i - 1] == '-' )
+            {
+                X->s = -1;
+                break;
+            }
+
+            MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
+            X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
+        }
+    }
+    else
+    {
+        MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
+
+        for( i = 0; i < slen; i++ )
+        {
+            if( i == 0 && s[i] == '-' )
+            {
+                X->s = -1;
+                continue;
+            }
+
+            MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
+
+            if( X->s == 1 )
+            {
+                MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
+            }
+            else
+            {
+                MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
+            }
+        }
+    }
+
+cleanup:
+
+    mbedtls_mpi_free( &T );
+
+    return( ret );
+}
+
+/*
+ * Helper to write the digits high-order first
+ */
+static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
+{
+    int ret;
+    mbedtls_mpi_uint r;
+
+    if( radix < 2 || radix > 16 )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
+
+    if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
+        MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
+
+    if( r < 10 )
+        *(*p)++ = (char)( r + 0x30 );
+    else
+        *(*p)++ = (char)( r + 0x37 );
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Export into an ASCII string
+ */
+int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
+                              char *buf, size_t buflen, size_t *olen )
+{
+    int ret = 0;
+    size_t n;
+    char *p;
+    mbedtls_mpi T;
+
+    if( radix < 2 || radix > 16 )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+    n = mbedtls_mpi_bitlen( X );
+    if( radix >=  4 ) n >>= 1;
+    if( radix >= 16 ) n >>= 1;
+    /*
+     * Round up the buffer length to an even value to ensure that there is
+     * enough room for hexadecimal values that can be represented in an odd
+     * number of digits.
+     */
+    n += 3 + ( ( n + 1 ) & 1 );
+
+    if( buflen < n )
+    {
+        *olen = n;
+        return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
+    }
+
+    p = buf;
+    mbedtls_mpi_init( &T );
+
+    if( X->s == -1 )
+        *p++ = '-';
+
+    if( radix == 16 )
+    {
+        int c;
+        size_t i, j, k;
+
+        for( i = X->n, k = 0; i > 0; i-- )
+        {
+            for( j = ciL; j > 0; j-- )
+            {
+                c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
+
+                if( c == 0 && k == 0 && ( i + j ) != 2 )
+                    continue;
+
+                *(p++) = "0123456789ABCDEF" [c / 16];
+                *(p++) = "0123456789ABCDEF" [c % 16];
+                k = 1;
+            }
+        }
+    }
+    else
+    {
+        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
+
+        if( T.s == -1 )
+            T.s = 1;
+
+        MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
+    }
+
+    *p++ = '\0';
+    *olen = p - buf;
+
+cleanup:
+
+    mbedtls_mpi_free( &T );
+
+    return( ret );
+}
+
+#if defined(MBEDTLS_FS_IO)
+/*
+ * Read X from an opened file
+ */
+int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
+{
+    mbedtls_mpi_uint d;
+    size_t slen;
+    char *p;
+    /*
+     * Buffer should have space for (short) label and decimal formatted MPI,
+     * newline characters and '\0'
+     */
+    char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
+
+    memset( s, 0, sizeof( s ) );
+    if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
+        return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
+
+    slen = strlen( s );
+    if( slen == sizeof( s ) - 2 )
+        return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
+
+    if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
+    if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
+
+    p = s + slen;
+    while( p-- > s )
+        if( mpi_get_digit( &d, radix, *p ) != 0 )
+            break;
+
+    return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
+}
+
+/*
+ * Write X into an opened file (or stdout if fout == NULL)
+ */
+int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
+{
+    int ret;
+    size_t n, slen, plen;
+    /*
+     * Buffer should have space for (short) label and decimal formatted MPI,
+     * newline characters and '\0'
+     */
+    char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
+
+    memset( s, 0, sizeof( s ) );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
+
+    if( p == NULL ) p = "";
+
+    plen = strlen( p );
+    slen = strlen( s );
+    s[slen++] = '\r';
+    s[slen++] = '\n';
+
+    if( fout != NULL )
+    {
+        if( fwrite( p, 1, plen, fout ) != plen ||
+            fwrite( s, 1, slen, fout ) != slen )
+            return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
+    }
+    else
+        mbedtls_printf( "%s%s", p, s );
+
+cleanup:
+
+    return( ret );
+}
+#endif /* MBEDTLS_FS_IO */
+
+/*
+ * Import X from unsigned binary data, big endian
+ */
+int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
+{
+    int ret;
+    size_t i, j;
+    size_t const limbs = CHARS_TO_LIMBS( buflen );
+
+    /* Ensure that target MPI has exactly the necessary number of limbs */
+    if( X->n != limbs )
+    {
+        mbedtls_mpi_free( X );
+        mbedtls_mpi_init( X );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
+    }
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
+
+    for( i = buflen, j = 0; i > 0; i--, j++ )
+        X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Export X into unsigned binary data, big endian
+ */
+int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
+{
+    size_t i, j, n;
+
+    n = mbedtls_mpi_size( X );
+
+    if( buflen < n )
+        return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
+
+    memset( buf, 0, buflen );
+
+    for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
+        buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
+
+    return( 0 );
+}
+
+/*
+ * Left-shift: X <<= count
+ */
+int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
+{
+    int ret;
+    size_t i, v0, t1;
+    mbedtls_mpi_uint r0 = 0, r1;
+
+    v0 = count / (biL    );
+    t1 = count & (biL - 1);
+
+    i = mbedtls_mpi_bitlen( X ) + count;
+
+    if( X->n * biL < i )
+        MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
+
+    ret = 0;
+
+    /*
+     * shift by count / limb_size
+     */
+    if( v0 > 0 )
+    {
+        for( i = X->n; i > v0; i-- )
+            X->p[i - 1] = X->p[i - v0 - 1];
+
+        for( ; i > 0; i-- )
+            X->p[i - 1] = 0;
+    }
+
+    /*
+     * shift by count % limb_size
+     */
+    if( t1 > 0 )
+    {
+        for( i = v0; i < X->n; i++ )
+        {
+            r1 = X->p[i] >> (biL - t1);
+            X->p[i] <<= t1;
+            X->p[i] |= r0;
+            r0 = r1;
+        }
+    }
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Right-shift: X >>= count
+ */
+int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
+{
+    size_t i, v0, v1;
+    mbedtls_mpi_uint r0 = 0, r1;
+
+    v0 = count /  biL;
+    v1 = count & (biL - 1);
+
+    if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
+        return mbedtls_mpi_lset( X, 0 );
+
+    /*
+     * shift by count / limb_size
+     */
+    if( v0 > 0 )
+    {
+        for( i = 0; i < X->n - v0; i++ )
+            X->p[i] = X->p[i + v0];
+
+        for( ; i < X->n; i++ )
+            X->p[i] = 0;
+    }
+
+    /*
+     * shift by count % limb_size
+     */
+    if( v1 > 0 )
+    {
+        for( i = X->n; i > 0; i-- )
+        {
+            r1 = X->p[i - 1] << (biL - v1);
+            X->p[i - 1] >>= v1;
+            X->p[i - 1] |= r0;
+            r0 = r1;
+        }
+    }
+
+    return( 0 );
+}
+
+/*
+ * Compare unsigned values
+ */
+int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
+{
+    size_t i, j;
+
+    for( i = X->n; i > 0; i-- )
+        if( X->p[i - 1] != 0 )
+            break;
+
+    for( j = Y->n; j > 0; j-- )
+        if( Y->p[j - 1] != 0 )
+            break;
+
+    if( i == 0 && j == 0 )
+        return( 0 );
+
+    if( i > j ) return(  1 );
+    if( j > i ) return( -1 );
+
+    for( ; i > 0; i-- )
+    {
+        if( X->p[i - 1] > Y->p[i - 1] ) return(  1 );
+        if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
+{
+    size_t i, j;
+
+    for( i = X->n; i > 0; i-- )
+        if( X->p[i - 1] != 0 )
+            break;
+
+    for( j = Y->n; j > 0; j-- )
+        if( Y->p[j - 1] != 0 )
+            break;
+
+    if( i == 0 && j == 0 )
+        return( 0 );
+
+    if( i > j ) return(  X->s );
+    if( j > i ) return( -Y->s );
+
+    if( X->s > 0 && Y->s < 0 ) return(  1 );
+    if( Y->s > 0 && X->s < 0 ) return( -1 );
+
+    for( ; i > 0; i-- )
+    {
+        if( X->p[i - 1] > Y->p[i - 1] ) return(  X->s );
+        if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
+{
+    mbedtls_mpi Y;
+    mbedtls_mpi_uint p[1];
+
+    *p  = ( z < 0 ) ? -z : z;
+    Y.s = ( z < 0 ) ? -1 : 1;
+    Y.n = 1;
+    Y.p = p;
+
+    return( mbedtls_mpi_cmp_mpi( X, &Y ) );
+}
+
+/*
+ * Unsigned addition: X = |A| + |B|  (HAC 14.7)
+ */
+int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
+{
+    int ret;
+    size_t i, j;
+    mbedtls_mpi_uint *o, *p, c, tmp;
+
+    if( X == B )
+    {
+        const mbedtls_mpi *T = A; A = X; B = T;
+    }
+
+    if( X != A )
+        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
+
+    /*
+     * X should always be positive as a result of unsigned additions.
+     */
+    X->s = 1;
+
+    for( j = B->n; j > 0; j-- )
+        if( B->p[j - 1] != 0 )
+            break;
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
+
+    o = B->p; p = X->p; c = 0;
+
+    /*
+     * tmp is used because it might happen that p == o
+     */
+    for( i = 0; i < j; i++, o++, p++ )
+    {
+        tmp= *o;
+        *p +=  c; c  = ( *p <  c );
+        *p += tmp; c += ( *p < tmp );
+    }
+
+    while( c != 0 )
+    {
+        if( i >= X->n )
+        {
+            MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
+            p = X->p + i;
+        }
+
+        *p += c; c = ( *p < c ); i++; p++;
+    }
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Helper for mbedtls_mpi subtraction
+ */
+static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
+{
+    size_t i;
+    mbedtls_mpi_uint c, z;
+
+    for( i = c = 0; i < n; i++, s++, d++ )
+    {
+        z = ( *d <  c );     *d -=  c;
+        c = ( *d < *s ) + z; *d -= *s;
+    }
+
+    while( c != 0 )
+    {
+        z = ( *d < c ); *d -= c;
+        c = z; d++;
+    }
+}
+
+/*
+ * Unsigned subtraction: X = |A| - |B|  (HAC 14.9)
+ */
+int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
+{
+    mbedtls_mpi TB;
+    int ret;
+    size_t n;
+
+    if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
+        return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
+
+    mbedtls_mpi_init( &TB );
+
+    if( X == B )
+    {
+        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
+        B = &TB;
+    }
+
+    if( X != A )
+        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
+
+    /*
+     * X should always be positive as a result of unsigned subtractions.
+     */
+    X->s = 1;
+
+    ret = 0;
+
+    for( n = B->n; n > 0; n-- )
+        if( B->p[n - 1] != 0 )
+            break;
+
+    mpi_sub_hlp( n, B->p, X->p );
+
+cleanup:
+
+    mbedtls_mpi_free( &TB );
+
+    return( ret );
+}
+
+/*
+ * Signed addition: X = A + B
+ */
+int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
+{
+    int ret, s = A->s;
+
+    if( A->s * B->s < 0 )
+    {
+        if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
+        {
+            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
+            X->s =  s;
+        }
+        else
+        {
+            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
+            X->s = -s;
+        }
+    }
+    else
+    {
+        MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
+        X->s = s;
+    }
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Signed subtraction: X = A - B
+ */
+int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
+{
+    int ret, s = A->s;
+
+    if( A->s * B->s > 0 )
+    {
+        if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
+        {
+            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
+            X->s =  s;
+        }
+        else
+        {
+            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
+            X->s = -s;
+        }
+    }
+    else
+    {
+        MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
+        X->s = s;
+    }
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Signed addition: X = A + b
+ */
+int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
+{
+    mbedtls_mpi _B;
+    mbedtls_mpi_uint p[1];
+
+    p[0] = ( b < 0 ) ? -b : b;
+    _B.s = ( b < 0 ) ? -1 : 1;
+    _B.n = 1;
+    _B.p = p;
+
+    return( mbedtls_mpi_add_mpi( X, A, &_B ) );
+}
+
+/*
+ * Signed subtraction: X = A - b
+ */
+int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
+{
+    mbedtls_mpi _B;
+    mbedtls_mpi_uint p[1];
+
+    p[0] = ( b < 0 ) ? -b : b;
+    _B.s = ( b < 0 ) ? -1 : 1;
+    _B.n = 1;
+    _B.p = p;
+
+    return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
+}
+
+/*
+ * Helper for mbedtls_mpi multiplication
+ */
+static
+#if defined(__APPLE__) && defined(__arm__)
+/*
+ * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
+ * appears to need this to prevent bad ARM code generation at -O3.
+ */
+__attribute__ ((noinline))
+#endif
+void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b )
+{
+    mbedtls_mpi_uint c = 0, t = 0;
+
+#if defined(MULADDC_HUIT)
+    for( ; i >= 8; i -= 8 )
+    {
+        MULADDC_INIT
+        MULADDC_HUIT
+        MULADDC_STOP
+    }
+
+    for( ; i > 0; i-- )
+    {
+        MULADDC_INIT
+        MULADDC_CORE
+        MULADDC_STOP
+    }
+#else /* MULADDC_HUIT */
+    for( ; i >= 16; i -= 16 )
+    {
+        MULADDC_INIT
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_STOP
+    }
+
+    for( ; i >= 8; i -= 8 )
+    {
+        MULADDC_INIT
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_STOP
+    }
+
+    for( ; i > 0; i-- )
+    {
+        MULADDC_INIT
+        MULADDC_CORE
+        MULADDC_STOP
+    }
+#endif /* MULADDC_HUIT */
+
+    t++;
+
+    do {
+        *d += c; c = ( *d < c ); d++;
+    }
+    while( c != 0 );
+}
+
+/*
+ * Baseline multiplication: X = A * B  (HAC 14.12)
+ */
+int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
+{
+    int ret;
+    size_t i, j;
+    mbedtls_mpi TA, TB;
+
+    mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
+
+    if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
+    if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
+
+    for( i = A->n; i > 0; i-- )
+        if( A->p[i - 1] != 0 )
+            break;
+
+    for( j = B->n; j > 0; j-- )
+        if( B->p[j - 1] != 0 )
+            break;
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
+
+    for( ; j > 0; j-- )
+        mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
+
+    X->s = A->s * B->s;
+
+cleanup:
+
+    mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
+
+    return( ret );
+}
+
+/*
+ * Baseline multiplication: X = A * b
+ */
+int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
+{
+    mbedtls_mpi _B;
+    mbedtls_mpi_uint p[1];
+
+    _B.s = 1;
+    _B.n = 1;
+    _B.p = p;
+    p[0] = b;
+
+    return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
+}
+
+/*
+ * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
+ * mbedtls_mpi_uint divisor, d
+ */
+static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
+            mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
+{
+#if defined(MBEDTLS_HAVE_UDBL)
+    mbedtls_t_udbl dividend, quotient;
+#else
+    const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
+    const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
+    mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
+    mbedtls_mpi_uint u0_msw, u0_lsw;
+    size_t s;
+#endif
+
+    /*
+     * Check for overflow
+     */
+    if( 0 == d || u1 >= d )
+    {
+        if (r != NULL) *r = ~0;
+
+        return ( ~0 );
+    }
+
+#if defined(MBEDTLS_HAVE_UDBL)
+    dividend  = (mbedtls_t_udbl) u1 << biL;
+    dividend |= (mbedtls_t_udbl) u0;
+    quotient = dividend / d;
+    if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
+        quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
+
+    if( r != NULL )
+        *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
+
+    return (mbedtls_mpi_uint) quotient;
+#else
+
+    /*
+     * Algorithm D, Section 4.3.1 - The Art of Computer Programming
+     *   Vol. 2 - Seminumerical Algorithms, Knuth
+     */
+
+    /*
+     * Normalize the divisor, d, and dividend, u0, u1
+     */
+    s = mbedtls_clz( d );
+    d = d << s;
+
+    u1 = u1 << s;
+    u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
+    u0 =  u0 << s;
+
+    d1 = d >> biH;
+    d0 = d & uint_halfword_mask;
+
+    u0_msw = u0 >> biH;
+    u0_lsw = u0 & uint_halfword_mask;
+
+    /*
+     * Find the first quotient and remainder
+     */
+    q1 = u1 / d1;
+    r0 = u1 - d1 * q1;
+
+    while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
+    {
+        q1 -= 1;
+        r0 += d1;
+
+        if ( r0 >= radix ) break;
+    }
+
+    rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
+    q0 = rAX / d1;
+    r0 = rAX - q0 * d1;
+
+    while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
+    {
+        q0 -= 1;
+        r0 += d1;
+
+        if ( r0 >= radix ) break;
+    }
+
+    if (r != NULL)
+        *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
+
+    quotient = q1 * radix + q0;
+
+    return quotient;
+#endif
+}
+
+/*
+ * Division by mbedtls_mpi: A = Q * B + R  (HAC 14.20)
+ */
+int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
+{
+    int ret;
+    size_t i, n, t, k;
+    mbedtls_mpi X, Y, Z, T1, T2;
+
+    if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
+        return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
+
+    mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
+    mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
+
+    if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
+    {
+        if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
+        if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
+        return( 0 );
+    }
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
+    X.s = Y.s = 1;
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z,  0 ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
+
+    k = mbedtls_mpi_bitlen( &Y ) % biL;
+    if( k < biL - 1 )
+    {
+        k = biL - 1 - k;
+        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
+    }
+    else k = 0;
+
+    n = X.n - 1;
+    t = Y.n - 1;
+    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
+
+    while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
+    {
+        Z.p[n - t]++;
+        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
+    }
+    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
+
+    for( i = n; i > t ; i-- )
+    {
+        if( X.p[i] >= Y.p[t] )
+            Z.p[i - t - 1] = ~0;
+        else
+        {
+            Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
+                                                            Y.p[t], NULL);
+        }
+
+        Z.p[i - t - 1]++;
+        do
+        {
+            Z.p[i - t - 1]--;
+
+            MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
+            T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
+            T1.p[1] = Y.p[t];
+            MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
+
+            MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
+            T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
+            T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
+            T2.p[2] = X.p[i];
+        }
+        while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
+
+        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1,  biL * ( i - t - 1 ) ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
+
+        if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
+        {
+            MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
+            Z.p[i - t - 1]--;
+        }
+    }
+
+    if( Q != NULL )
+    {
+        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
+        Q->s = A->s * B->s;
+    }
+
+    if( R != NULL )
+    {
+        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
+        X.s = A->s;
+        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
+
+        if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
+            R->s = 1;
+    }
+
+cleanup:
+
+    mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
+    mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
+
+    return( ret );
+}
+
+/*
+ * Division by int: A = Q * b + R
+ */
+int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b )
+{
+    mbedtls_mpi _B;
+    mbedtls_mpi_uint p[1];
+
+    p[0] = ( b < 0 ) ? -b : b;
+    _B.s = ( b < 0 ) ? -1 : 1;
+    _B.n = 1;
+    _B.p = p;
+
+    return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
+}
+
+/*
+ * Modulo: R = A mod B
+ */
+int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
+{
+    int ret;
+
+    if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
+        return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
+
+    while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
+      MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
+
+    while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
+      MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Modulo: r = A mod b
+ */
+int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
+{
+    size_t i;
+    mbedtls_mpi_uint x, y, z;
+
+    if( b == 0 )
+        return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
+
+    if( b < 0 )
+        return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
+
+    /*
+     * handle trivial cases
+     */
+    if( b == 1 )
+    {
+        *r = 0;
+        return( 0 );
+    }
+
+    if( b == 2 )
+    {
+        *r = A->p[0] & 1;
+        return( 0 );
+    }
+
+    /*
+     * general case
+     */
+    for( i = A->n, y = 0; i > 0; i-- )
+    {
+        x  = A->p[i - 1];
+        y  = ( y << biH ) | ( x >> biH );
+        z  = y / b;
+        y -= z * b;
+
+        x <<= biH;
+        y  = ( y << biH ) | ( x >> biH );
+        z  = y / b;
+        y -= z * b;
+    }
+
+    /*
+     * If A is negative, then the current y represents a negative value.
+     * Flipping it to the positive side.
+     */
+    if( A->s < 0 && y != 0 )
+        y = b - y;
+
+    *r = y;
+
+    return( 0 );
+}
+
+/*
+ * Fast Montgomery initialization (thanks to Tom St Denis)
+ */
+static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
+{
+    mbedtls_mpi_uint x, m0 = N->p[0];
+    unsigned int i;
+
+    x  = m0;
+    x += ( ( m0 + 2 ) & 4 ) << 1;
+
+    for( i = biL; i >= 8; i /= 2 )
+        x *= ( 2 - ( m0 * x ) );
+
+    *mm = ~x + 1;
+}
+
+/*
+ * Montgomery multiplication: A = A * B * R^-1 mod N  (HAC 14.36)
+ */
+static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
+                         const mbedtls_mpi *T )
+{
+    size_t i, n, m;
+    mbedtls_mpi_uint u0, u1, *d;
+
+    if( T->n < N->n + 1 || T->p == NULL )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+    memset( T->p, 0, T->n * ciL );
+
+    d = T->p;
+    n = N->n;
+    m = ( B->n < n ) ? B->n : n;
+
+    for( i = 0; i < n; i++ )
+    {
+        /*
+         * T = (T + u0*B + u1*N) / 2^biL
+         */
+        u0 = A->p[i];
+        u1 = ( d[0] + u0 * B->p[0] ) * mm;
+
+        mpi_mul_hlp( m, B->p, d, u0 );
+        mpi_mul_hlp( n, N->p, d, u1 );
+
+        *d++ = u0; d[n + 1] = 0;
+    }
+
+    memcpy( A->p, d, ( n + 1 ) * ciL );
+
+    if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
+        mpi_sub_hlp( n, N->p, A->p );
+    else
+        /* prevent timing attacks */
+        mpi_sub_hlp( n, A->p, T->p );
+
+    return( 0 );
+}
+
+/*
+ * Montgomery reduction: A = A * R^-1 mod N
+ */
+static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
+{
+    mbedtls_mpi_uint z = 1;
+    mbedtls_mpi U;
+
+    U.n = U.s = (int) z;
+    U.p = &z;
+
+    return( mpi_montmul( A, &U, N, mm, T ) );
+}
+
+/*
+ * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
+ */
+int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR )
+{
+    int ret;
+    size_t wbits, wsize, one = 1;
+    size_t i, j, nblimbs;
+    size_t bufsize, nbits;
+    mbedtls_mpi_uint ei, mm, state;
+    mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
+    int neg;
+
+    if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+    if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+    /*
+     * Init temps and window size
+     */
+    mpi_montg_init( &mm, N );
+    mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
+    mbedtls_mpi_init( &Apos );
+    memset( W, 0, sizeof( W ) );
+
+    i = mbedtls_mpi_bitlen( E );
+
+    wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
+            ( i >  79 ) ? 4 : ( i >  23 ) ? 3 : 1;
+
+    if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
+        wsize = MBEDTLS_MPI_WINDOW_SIZE;
+
+    j = N->n + 1;
+    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1],  j ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
+
+    /*
+     * Compensate for negative A (and correct at the end)
+     */
+    neg = ( A->s == -1 );
+    if( neg )
+    {
+        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
+        Apos.s = 1;
+        A = &Apos;
+    }
+
+    /*
+     * If 1st call, pre-compute R^2 mod N
+     */
+    if( _RR == NULL || _RR->p == NULL )
+    {
+        MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
+
+        if( _RR != NULL )
+            memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
+    }
+    else
+        memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
+
+    /*
+     * W[1] = A * R^2 * R^-1 mod N = A * R mod N
+     */
+    if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
+        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
+    else
+        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
+
+    MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
+
+    /*
+     * X = R^2 * R^-1 mod N = R mod N
+     */
+    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
+    MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
+
+    if( wsize > 1 )
+    {
+        /*
+         * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
+         */
+        j =  one << ( wsize - 1 );
+
+        MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1]    ) );
+
+        for( i = 0; i < wsize - 1; i++ )
+            MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
+
+        /*
+         * W[i] = W[i - 1] * W[1]
+         */
+        for( i = j + 1; i < ( one << wsize ); i++ )
+        {
+            MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
+
+            MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
+        }
+    }
+
+    nblimbs = E->n;
+    bufsize = 0;
+    nbits   = 0;
+    wbits   = 0;
+    state   = 0;
+
+    while( 1 )
+    {
+        if( bufsize == 0 )
+        {
+            if( nblimbs == 0 )
+                break;
+
+            nblimbs--;
+
+            bufsize = sizeof( mbedtls_mpi_uint ) << 3;
+        }
+
+        bufsize--;
+
+        ei = (E->p[nblimbs] >> bufsize) & 1;
+
+        /*
+         * skip leading 0s
+         */
+        if( ei == 0 && state == 0 )
+            continue;
+
+        if( ei == 0 && state == 1 )
+        {
+            /*
+             * out of window, square X
+             */
+            MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
+            continue;
+        }
+
+        /*
+         * add ei to current window
+         */
+        state = 2;
+
+        nbits++;
+        wbits |= ( ei << ( wsize - nbits ) );
+
+        if( nbits == wsize )
+        {
+            /*
+             * X = X^wsize R^-1 mod N
+             */
+            for( i = 0; i < wsize; i++ )
+                MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
+
+            /*
+             * X = X * W[wbits] R^-1 mod N
+             */
+            MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
+
+            state--;
+            nbits = 0;
+            wbits = 0;
+        }
+    }
+
+    /*
+     * process the remaining bits
+     */
+    for( i = 0; i < nbits; i++ )
+    {
+        MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
+
+        wbits <<= 1;
+
+        if( ( wbits & ( one << wsize ) ) != 0 )
+            MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
+    }
+
+    /*
+     * X = A^E * R * R^-1 mod N = A^E mod N
+     */
+    MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
+
+    if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
+    {
+        X->s = -1;
+        MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
+    }
+
+cleanup:
+
+    for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
+        mbedtls_mpi_free( &W[i] );
+
+    mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
+
+    if( _RR == NULL || _RR->p == NULL )
+        mbedtls_mpi_free( &RR );
+
+    return( ret );
+}
+
+/*
+ * Greatest common divisor: G = gcd(A, B)  (HAC 14.54)
+ */
+int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
+{
+    int ret;
+    size_t lz, lzt;
+    mbedtls_mpi TG, TA, TB;
+
+    mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
+
+    lz = mbedtls_mpi_lsb( &TA );
+    lzt = mbedtls_mpi_lsb( &TB );
+
+    if( lzt < lz )
+        lz = lzt;
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
+
+    TA.s = TB.s = 1;
+
+    while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
+    {
+        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
+
+        if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
+        {
+            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
+        }
+        else
+        {
+            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
+        }
+    }
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
+
+cleanup:
+
+    mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
+
+    return( ret );
+}
+
+/*
+ * Fill X with size bytes of random.
+ *
+ * Use a temporary bytes representation to make sure the result is the same
+ * regardless of the platform endianness (useful when f_rng is actually
+ * deterministic, eg for tests).
+ */
+int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng )
+{
+    int ret;
+    unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
+
+    if( size > MBEDTLS_MPI_MAX_SIZE )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+    MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
+
+cleanup:
+    mbedtls_platform_zeroize( buf, sizeof( buf ) );
+    return( ret );
+}
+
+/*
+ * Modular inverse: X = A^-1 mod N  (HAC 14.61 / 14.64)
+ */
+int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
+{
+    int ret;
+    mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
+
+    if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+    mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
+    mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
+    mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
+
+    if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
+    {
+        ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
+        goto cleanup;
+    }
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
+
+    do
+    {
+        while( ( TU.p[0] & 1 ) == 0 )
+        {
+            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
+
+            if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
+            {
+                MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
+                MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
+            }
+
+            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
+        }
+
+        while( ( TV.p[0] & 1 ) == 0 )
+        {
+            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
+
+            if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
+            {
+                MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
+                MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
+            }
+
+            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
+        }
+
+        if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
+        {
+            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
+        }
+        else
+        {
+            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
+        }
+    }
+    while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
+
+    while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
+        MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
+
+    while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
+        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
+
+cleanup:
+
+    mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
+    mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
+    mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
+
+    return( ret );
+}
+
+#if defined(MBEDTLS_GENPRIME)
+
+static const int small_prime[] =
+{
+        3,    5,    7,   11,   13,   17,   19,   23,
+       29,   31,   37,   41,   43,   47,   53,   59,
+       61,   67,   71,   73,   79,   83,   89,   97,
+      101,  103,  107,  109,  113,  127,  131,  137,
+      139,  149,  151,  157,  163,  167,  173,  179,
+      181,  191,  193,  197,  199,  211,  223,  227,
+      229,  233,  239,  241,  251,  257,  263,  269,
+      271,  277,  281,  283,  293,  307,  311,  313,
+      317,  331,  337,  347,  349,  353,  359,  367,
+      373,  379,  383,  389,  397,  401,  409,  419,
+      421,  431,  433,  439,  443,  449,  457,  461,
+      463,  467,  479,  487,  491,  499,  503,  509,
+      521,  523,  541,  547,  557,  563,  569,  571,
+      577,  587,  593,  599,  601,  607,  613,  617,
+      619,  631,  641,  643,  647,  653,  659,  661,
+      673,  677,  683,  691,  701,  709,  719,  727,
+      733,  739,  743,  751,  757,  761,  769,  773,
+      787,  797,  809,  811,  821,  823,  827,  829,
+      839,  853,  857,  859,  863,  877,  881,  883,
+      887,  907,  911,  919,  929,  937,  941,  947,
+      953,  967,  971,  977,  983,  991,  997, -103
+};
+
+/*
+ * Small divisors test (X must be positive)
+ *
+ * Return values:
+ * 0: no small factor (possible prime, more tests needed)
+ * 1: certain prime
+ * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
+ * other negative: error
+ */
+static int mpi_check_small_factors( const mbedtls_mpi *X )
+{
+    int ret = 0;
+    size_t i;
+    mbedtls_mpi_uint r;
+
+    if( ( X->p[0] & 1 ) == 0 )
+        return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
+
+    for( i = 0; small_prime[i] > 0; i++ )
+    {
+        if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
+            return( 1 );
+
+        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
+
+        if( r == 0 )
+            return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
+    }
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Miller-Rabin pseudo-primality test  (HAC 4.24)
+ */
+static int mpi_miller_rabin( const mbedtls_mpi *X,
+                             int (*f_rng)(void *, unsigned char *, size_t),
+                             void *p_rng )
+{
+    int ret, count;
+    size_t i, j, k, n, s;
+    mbedtls_mpi W, R, T, A, RR;
+
+    mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
+    mbedtls_mpi_init( &RR );
+
+    /*
+     * W = |X| - 1
+     * R = W >> lsb( W )
+     */
+    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
+    s = mbedtls_mpi_lsb( &W );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
+
+    i = mbedtls_mpi_bitlen( X );
+    /*
+     * HAC, table 4.4
+     */
+    n = ( ( i >= 1300 ) ?  2 : ( i >=  850 ) ?  3 :
+          ( i >=  650 ) ?  4 : ( i >=  350 ) ?  8 :
+          ( i >=  250 ) ? 12 : ( i >=  150 ) ? 18 : 27 );
+
+    for( i = 0; i < n; i++ )
+    {
+        /*
+         * pick a random A, 1 < A < |X| - 1
+         */
+        MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
+
+        if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
+        {
+            j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
+        }
+        A.p[0] |= 3;
+
+        count = 0;
+        do {
+            MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
+
+            j = mbedtls_mpi_bitlen( &A );
+            k = mbedtls_mpi_bitlen( &W );
+            if (j > k) {
+                MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
+            }
+
+            if (count++ > 30) {
+                return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
+            }
+
+        } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
+                  mbedtls_mpi_cmp_int( &A, 1 )  <= 0    );
+
+        /*
+         * A = A^R mod |X|
+         */
+        MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
+
+        if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
+            mbedtls_mpi_cmp_int( &A,  1 ) == 0 )
+            continue;
+
+        j = 1;
+        while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
+        {
+            /*
+             * A = A * A mod |X|
+             */
+            MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X  ) );
+
+            if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
+                break;
+
+            j++;
+        }
+
+        /*
+         * not prime if A != |X| - 1 or A == 1
+         */
+        if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
+            mbedtls_mpi_cmp_int( &A,  1 ) == 0 )
+        {
+            ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
+            break;
+        }
+    }
+
+cleanup:
+    mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
+    mbedtls_mpi_free( &RR );
+
+    return( ret );
+}
+
+/*
+ * Pseudo-primality test: small factors, then Miller-Rabin
+ */
+int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
+                  int (*f_rng)(void *, unsigned char *, size_t),
+                  void *p_rng )
+{
+    int ret;
+    mbedtls_mpi XX;
+
+    XX.s = 1;
+    XX.n = X->n;
+    XX.p = X->p;
+
+    if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
+        mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
+        return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
+
+    if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
+        return( 0 );
+
+    if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
+    {
+        if( ret == 1 )
+            return( 0 );
+
+        return( ret );
+    }
+
+    return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
+}
+
+/*
+ * Prime number generation
+ *
+ * If dh_flag is 0 and nbits is at least 1024, then the procedure
+ * follows the RSA probably-prime generation method of FIPS 186-4.
+ * NB. FIPS 186-4 only allows the specific bit lengths of 1024 and 1536.
+ */
+int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
+                   int (*f_rng)(void *, unsigned char *, size_t),
+                   void *p_rng )
+{
+#ifdef MBEDTLS_HAVE_INT64
+// ceil(2^63.5)
+#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
+#else
+// ceil(2^31.5)
+#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
+#endif
+    int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
+    size_t k, n;
+    mbedtls_mpi_uint r;
+    mbedtls_mpi Y;
+
+    if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+    mbedtls_mpi_init( &Y );
+
+    n = BITS_TO_LIMBS( nbits );
+
+    while( 1 )
+    {
+        MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
+        /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
+        if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
+
+        k = n * biL;
+        if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
+        X->p[0] |= 1;
+
+        if( dh_flag == 0 )
+        {
+            ret = mbedtls_mpi_is_prime( X, f_rng, p_rng );
+
+            if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
+                goto cleanup;
+        }
+        else
+        {
+            /*
+             * An necessary condition for Y and X = 2Y + 1 to be prime
+             * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
+             * Make sure it is satisfied, while keeping X = 3 mod 4
+             */
+
+            X->p[0] |= 2;
+
+            MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
+            if( r == 0 )
+                MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
+            else if( r == 1 )
+                MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
+
+            /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
+            MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
+
+            while( 1 )
+            {
+                /*
+                 * First, check small factors for X and Y
+                 * before doing Miller-Rabin on any of them
+                 */
+                if( ( ret = mpi_check_small_factors(  X         ) ) == 0 &&
+                    ( ret = mpi_check_small_factors( &Y         ) ) == 0 &&
+                    ( ret = mpi_miller_rabin(  X, f_rng, p_rng  ) ) == 0 &&
+                    ( ret = mpi_miller_rabin( &Y, f_rng, p_rng  ) ) == 0 )
+                    goto cleanup;
+
+                if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
+                    goto cleanup;
+
+                /*
+                 * Next candidates. We want to preserve Y = (X-1) / 2 and
+                 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
+                 * so up Y by 6 and X by 12.
+                 */
+                MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(  X,  X, 12 ) );
+                MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6  ) );
+            }
+        }
+    }
+
+cleanup:
+
+    mbedtls_mpi_free( &Y );
+
+    return( ret );
+}
+
+#endif /* MBEDTLS_GENPRIME */
+
+#if defined(MBEDTLS_SELF_TEST)
+
+#define GCD_PAIR_COUNT  3
+
+static const int gcd_pairs[GCD_PAIR_COUNT][3] =
+{
+    { 693, 609, 21 },
+    { 1764, 868, 28 },
+    { 768454923, 542167814, 1 }
+};
+
+/*
+ * Checkup routine
+ */
+int mbedtls_mpi_self_test( int verbose )
+{
+    int ret, i;
+    mbedtls_mpi A, E, N, X, Y, U, V;
+
+    mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
+    mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
+        "EFE021C2645FD1DC586E69184AF4A31E" \
+        "D5F53E93B5F123FA41680867BA110131" \
+        "944FE7952E2517337780CB0DB80E61AA" \
+        "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
+        "B2E7EFD37075B9F03FF989C7C5051C20" \
+        "34D2A323810251127E7BF8625A4F49A5" \
+        "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
+        "5B5C25763222FEFCCFC38B832366C29E" ) );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
+        "0066A198186C18C10B2F5ED9B522752A" \
+        "9830B69916E535C8F047518A889A43A5" \
+        "94B6BED27A168D31D4A52F88925AA8F5" ) );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
+        "602AB7ECA597A3D6B56FF9829A5E8B85" \
+        "9E857EA95A03512E2BAE7391688D264A" \
+        "A5663B0341DB9CCFD2C4C5F421FEC814" \
+        "8001B72E848A38CAE1C65F78E56ABDEF" \
+        "E12D3C039B8A02D6BE593F0BBBDA56F1" \
+        "ECF677152EF804370C1A305CAF3B5BF1" \
+        "30879B56C61DE584A0F53A2447A51E" ) );
+
+    if( verbose != 0 )
+        mbedtls_printf( "  MPI test #1 (mul_mpi): " );
+
+    if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "failed\n" );
+
+        ret = 1;
+        goto cleanup;
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "passed\n" );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
+        "256567336059E52CAE22925474705F39A94" ) );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
+        "6613F26162223DF488E9CD48CC132C7A" \
+        "0AC93C701B001B092E4E5B9F73BCD27B" \
+        "9EE50D0657C77F374E903CDFA4C642" ) );
+
+    if( verbose != 0 )
+        mbedtls_printf( "  MPI test #2 (div_mpi): " );
+
+    if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
+        mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "failed\n" );
+
+        ret = 1;
+        goto cleanup;
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "passed\n" );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
+        "36E139AEA55215609D2816998ED020BB" \
+        "BD96C37890F65171D948E9BC7CBAA4D9" \
+        "325D24D6A3C12710F10A09FA08AB87" ) );
+
+    if( verbose != 0 )
+        mbedtls_printf( "  MPI test #3 (exp_mod): " );
+
+    if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "failed\n" );
+
+        ret = 1;
+        goto cleanup;
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "passed\n" );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
+        "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
+        "C3DBA76456363A10869622EAC2DD84EC" \
+        "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
+
+    if( verbose != 0 )
+        mbedtls_printf( "  MPI test #4 (inv_mod): " );
+
+    if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "failed\n" );
+
+        ret = 1;
+        goto cleanup;
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "passed\n" );
+
+    if( verbose != 0 )
+        mbedtls_printf( "  MPI test #5 (simple gcd): " );
+
+    for( i = 0; i < GCD_PAIR_COUNT; i++ )
+    {
+        MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
+
+        MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
+
+        if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
+        {
+            if( verbose != 0 )
+                mbedtls_printf( "failed at %d\n", i );
+
+            ret = 1;
+            goto cleanup;
+        }
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "passed\n" );
+
+cleanup:
+
+    if( ret != 0 && verbose != 0 )
+        mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
+
+    mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
+    mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
+
+    if( verbose != 0 )
+        mbedtls_printf( "\n" );
+
+    return( ret );
+}
+
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_BIGNUM_C */
diff --git a/common/mbedtls/bignum.h b/common/mbedtls/bignum.h
new file mode 100644 (file)
index 0000000..0078790
--- /dev/null
@@ -0,0 +1,774 @@
+/**
+ * \file bignum.h
+ *
+ * \brief Multi-precision integer library
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: GPL-2.0
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+#ifndef MBEDTLS_BIGNUM_H
+#define MBEDTLS_BIGNUM_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#if defined(MBEDTLS_FS_IO)
+#include <stdio.h>
+#endif
+
+#define MBEDTLS_ERR_MPI_FILE_IO_ERROR                     -0x0002  /**< An error occurred while reading from or writing to a file. */
+#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA                    -0x0004  /**< Bad input parameters to function. */
+#define MBEDTLS_ERR_MPI_INVALID_CHARACTER                 -0x0006  /**< There is an invalid character in the digit string. */
+#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL                  -0x0008  /**< The buffer is too small to write to. */
+#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE                    -0x000A  /**< The input arguments are negative or result in illegal output. */
+#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO                  -0x000C  /**< The input argument for division is zero, which is not allowed. */
+#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE                    -0x000E  /**< The input arguments are not acceptable. */
+#define MBEDTLS_ERR_MPI_ALLOC_FAILED                      -0x0010  /**< Memory allocation failed. */
+
+#define MBEDTLS_MPI_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 )
+
+/*
+ * Maximum size MPIs are allowed to grow to in number of limbs.
+ */
+#define MBEDTLS_MPI_MAX_LIMBS                             10000
+
+#if !defined(MBEDTLS_MPI_WINDOW_SIZE)
+/*
+ * Maximum window size used for modular exponentiation. Default: 6
+ * Minimum value: 1. Maximum value: 6.
+ *
+ * Result is an array of ( 2 << MBEDTLS_MPI_WINDOW_SIZE ) MPIs used
+ * for the sliding window calculation. (So 64 by default)
+ *
+ * Reduction in size, reduces speed.
+ */
+#define MBEDTLS_MPI_WINDOW_SIZE                           6        /**< Maximum windows size used. */
+#endif /* !MBEDTLS_MPI_WINDOW_SIZE */
+
+#if !defined(MBEDTLS_MPI_MAX_SIZE)
+/*
+ * Maximum size of MPIs allowed in bits and bytes for user-MPIs.
+ * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits )
+ *
+ * Note: Calculations can temporarily result in larger MPIs. So the number
+ * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher.
+ */
+#define MBEDTLS_MPI_MAX_SIZE                              1024     /**< Maximum number of bytes for usable MPIs. */
+#endif /* !MBEDTLS_MPI_MAX_SIZE */
+
+#define MBEDTLS_MPI_MAX_BITS                              ( 8 * MBEDTLS_MPI_MAX_SIZE )    /**< Maximum number of bits for usable MPIs. */
+
+/*
+ * When reading from files with mbedtls_mpi_read_file() and writing to files with
+ * mbedtls_mpi_write_file() the buffer should have space
+ * for a (short) label, the MPI (in the provided radix), the newline
+ * characters and the '\0'.
+ *
+ * By default we assume at least a 10 char label, a minimum radix of 10
+ * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars).
+ * Autosized at compile time for at least a 10 char label, a minimum radix
+ * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size.
+ *
+ * This used to be statically sized to 1250 for a maximum of 4096 bit
+ * numbers (1234 decimal chars).
+ *
+ * Calculate using the formula:
+ *  MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) +
+ *                                LabelSize + 6
+ */
+#define MBEDTLS_MPI_MAX_BITS_SCALE100          ( 100 * MBEDTLS_MPI_MAX_BITS )
+#define MBEDTLS_LN_2_DIV_LN_10_SCALE100                 332
+#define MBEDTLS_MPI_RW_BUFFER_SIZE             ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 )
+
+/*
+ * Define the base integer type, architecture-wise.
+ *
+ * 32 or 64-bit integer types can be forced regardless of the underlying
+ * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64
+ * respectively and undefining MBEDTLS_HAVE_ASM.
+ *
+ * Double-width integers (e.g. 128-bit in 64-bit architectures) can be
+ * disabled by defining MBEDTLS_NO_UDBL_DIVISION.
+ */
+#if !defined(MBEDTLS_HAVE_INT32)
+    #if defined(_MSC_VER) && defined(_M_AMD64)
+        /* Always choose 64-bit when using MSC */
+        #if !defined(MBEDTLS_HAVE_INT64)
+            #define MBEDTLS_HAVE_INT64
+        #endif /* !MBEDTLS_HAVE_INT64 */
+        typedef  int64_t mbedtls_mpi_sint;
+        typedef uint64_t mbedtls_mpi_uint;
+    #elif defined(__GNUC__) && (                         \
+        defined(__amd64__) || defined(__x86_64__)     || \
+        defined(__ppc64__) || defined(__powerpc64__)  || \
+        defined(__ia64__)  || defined(__alpha__)      || \
+        ( defined(__sparc__) && defined(__arch64__) ) || \
+        defined(__s390x__) || defined(__mips64) )
+        #if !defined(MBEDTLS_HAVE_INT64)
+            #define MBEDTLS_HAVE_INT64
+        #endif /* MBEDTLS_HAVE_INT64 */
+        typedef  int64_t mbedtls_mpi_sint;
+        typedef uint64_t mbedtls_mpi_uint;
+        #if !defined(MBEDTLS_NO_UDBL_DIVISION)
+            /* mbedtls_t_udbl defined as 128-bit unsigned int */
+            typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI)));
+            #define MBEDTLS_HAVE_UDBL
+        #endif /* !MBEDTLS_NO_UDBL_DIVISION */
+    #elif defined(__ARMCC_VERSION) && defined(__aarch64__)
+        /*
+         * __ARMCC_VERSION is defined for both armcc and armclang and
+         * __aarch64__ is only defined by armclang when compiling 64-bit code
+         */
+        #if !defined(MBEDTLS_HAVE_INT64)
+            #define MBEDTLS_HAVE_INT64
+        #endif /* !MBEDTLS_HAVE_INT64 */
+        typedef  int64_t mbedtls_mpi_sint;
+        typedef uint64_t mbedtls_mpi_uint;
+        #if !defined(MBEDTLS_NO_UDBL_DIVISION)
+            /* mbedtls_t_udbl defined as 128-bit unsigned int */
+            typedef __uint128_t mbedtls_t_udbl;
+            #define MBEDTLS_HAVE_UDBL
+        #endif /* !MBEDTLS_NO_UDBL_DIVISION */
+    #elif defined(MBEDTLS_HAVE_INT64)
+        /* Force 64-bit integers with unknown compiler */
+        typedef  int64_t mbedtls_mpi_sint;
+        typedef uint64_t mbedtls_mpi_uint;
+    #endif
+#endif /* !MBEDTLS_HAVE_INT32 */
+
+#if !defined(MBEDTLS_HAVE_INT64)
+    /* Default to 32-bit compilation */
+    #if !defined(MBEDTLS_HAVE_INT32)
+        #define MBEDTLS_HAVE_INT32
+    #endif /* !MBEDTLS_HAVE_INT32 */
+    typedef  int32_t mbedtls_mpi_sint;
+    typedef uint32_t mbedtls_mpi_uint;
+    #if !defined(MBEDTLS_NO_UDBL_DIVISION)
+        typedef uint64_t mbedtls_t_udbl;
+        #define MBEDTLS_HAVE_UDBL
+    #endif /* !MBEDTLS_NO_UDBL_DIVISION */
+#endif /* !MBEDTLS_HAVE_INT64 */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          MPI structure
+ */
+typedef struct mbedtls_mpi
+{
+    int s;              /*!<  integer sign      */
+    size_t n;           /*!<  total # of limbs  */
+    mbedtls_mpi_uint *p;          /*!<  pointer to limbs  */
+}
+mbedtls_mpi;
+
+/**
+ * \brief           Initialize one MPI (make internal references valid)
+ *                  This just makes it ready to be set or freed,
+ *                  but does not define a value for the MPI.
+ *
+ * \param X         One MPI to initialize.
+ */
+void mbedtls_mpi_init( mbedtls_mpi *X );
+
+/**
+ * \brief          Unallocate one MPI
+ *
+ * \param X        One MPI to unallocate.
+ */
+void mbedtls_mpi_free( mbedtls_mpi *X );
+
+/**
+ * \brief          Enlarge to the specified number of limbs
+ *
+ *                 This function does nothing if the MPI is already large enough.
+ *
+ * \param X        MPI to grow
+ * \param nblimbs  The target number of limbs
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs );
+
+/**
+ * \brief          Resize down, keeping at least the specified number of limbs
+ *
+ *                 If \c X is smaller than \c nblimbs, it is resized up
+ *                 instead.
+ *
+ * \param X        MPI to shrink
+ * \param nblimbs  The minimum number of limbs to keep
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ *                 (this can only happen when resizing up).
+ */
+int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs );
+
+/**
+ * \brief          Copy the contents of Y into X
+ *
+ * \param X        Destination MPI. It is enlarged if necessary.
+ * \param Y        Source MPI.
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y );
+
+/**
+ * \brief          Swap the contents of X and Y
+ *
+ * \param X        First MPI value
+ * \param Y        Second MPI value
+ */
+void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y );
+
+/**
+ * \brief          Safe conditional assignement X = Y if assign is 1
+ *
+ * \param X        MPI to conditionally assign to
+ * \param Y        Value to be assigned
+ * \param assign   1: perform the assignment, 0: keep X's original value
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *
+ * \note           This function is equivalent to
+ *                      if( assign ) mbedtls_mpi_copy( X, Y );
+ *                 except that it avoids leaking any information about whether
+ *                 the assignment was done or not (the above code may leak
+ *                 information through branch prediction and/or memory access
+ *                 patterns analysis).
+ */
+int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign );
+
+/**
+ * \brief          Safe conditional swap X <-> Y if swap is 1
+ *
+ * \param X        First mbedtls_mpi value
+ * \param Y        Second mbedtls_mpi value
+ * \param assign   1: perform the swap, 0: keep X and Y's original values
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *
+ * \note           This function is equivalent to
+ *                      if( assign ) mbedtls_mpi_swap( X, Y );
+ *                 except that it avoids leaking any information about whether
+ *                 the assignment was done or not (the above code may leak
+ *                 information through branch prediction and/or memory access
+ *                 patterns analysis).
+ */
+int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign );
+
+/**
+ * \brief          Set value from integer
+ *
+ * \param X        MPI to set
+ * \param z        Value to use
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z );
+
+/**
+ * \brief          Get a specific bit from X
+ *
+ * \param X        MPI to use
+ * \param pos      Zero-based index of the bit in X
+ *
+ * \return         Either a 0 or a 1
+ */
+int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos );
+
+/**
+ * \brief          Set a bit of X to a specific value of 0 or 1
+ *
+ * \note           Will grow X if necessary to set a bit to 1 in a not yet
+ *                 existing limb. Will not grow if bit should be set to 0
+ *
+ * \param X        MPI to use
+ * \param pos      Zero-based index of the bit in X
+ * \param val      The value to set the bit to (0 or 1)
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *                 MBEDTLS_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1
+ */
+int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val );
+
+/**
+ * \brief          Return the number of zero-bits before the least significant
+ *                 '1' bit
+ *
+ * Note: Thus also the zero-based index of the least significant '1' bit
+ *
+ * \param X        MPI to use
+ */
+size_t mbedtls_mpi_lsb( const mbedtls_mpi *X );
+
+/**
+ * \brief          Return the number of bits up to and including the most
+ *                 significant '1' bit'
+ *
+ * Note: Thus also the one-based index of the most significant '1' bit
+ *
+ * \param X        MPI to use
+ */
+size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X );
+
+/**
+ * \brief          Return the total size in bytes
+ *
+ * \param X        MPI to use
+ */
+size_t mbedtls_mpi_size( const mbedtls_mpi *X );
+
+/**
+ * \brief          Import from an ASCII string
+ *
+ * \param X        Destination MPI
+ * \param radix    Input numeric base
+ * \param s        Null-terminated string buffer
+ *
+ * \return         0 if successful, or a MBEDTLS_ERR_MPI_XXX error code
+ */
+int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s );
+
+/**
+ * \brief          Export into an ASCII string
+ *
+ * \param X        Source MPI
+ * \param radix    Output numeric base
+ * \param buf      Buffer to write the string to
+ * \param buflen   Length of buf
+ * \param olen     Length of the string written, including final NUL byte
+ *
+ * \return         0 if successful, or a MBEDTLS_ERR_MPI_XXX error code.
+ *                 *olen is always updated to reflect the amount
+ *                 of data that has (or would have) been written.
+ *
+ * \note           Call this function with buflen = 0 to obtain the
+ *                 minimum required buffer size in *olen.
+ */
+int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
+                              char *buf, size_t buflen, size_t *olen );
+
+#if defined(MBEDTLS_FS_IO)
+/**
+ * \brief          Read MPI from a line in an opened file
+ *
+ * \param X        Destination MPI
+ * \param radix    Input numeric base
+ * \param fin      Input file handle
+ *
+ * \return         0 if successful, MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if
+ *                 the file read buffer is too small or a
+ *                 MBEDTLS_ERR_MPI_XXX error code
+ *
+ * \note           On success, this function advances the file stream
+ *                 to the end of the current line or to EOF.
+ *
+ *                 The function returns 0 on an empty line.
+ *
+ *                 Leading whitespaces are ignored, as is a
+ *                 '0x' prefix for radix 16.
+ *
+ */
+int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin );
+
+/**
+ * \brief          Write X into an opened file, or stdout if fout is NULL
+ *
+ * \param p        Prefix, can be NULL
+ * \param X        Source MPI
+ * \param radix    Output numeric base
+ * \param fout     Output file handle (can be NULL)
+ *
+ * \return         0 if successful, or a MBEDTLS_ERR_MPI_XXX error code
+ *
+ * \note           Set fout == NULL to print X on the console.
+ */
+int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout );
+#endif /* MBEDTLS_FS_IO */
+
+/**
+ * \brief          Import X from unsigned binary data, big endian
+ *
+ * \param X        Destination MPI
+ * \param buf      Input buffer
+ * \param buflen   Input buffer size
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen );
+
+/**
+ * \brief          Export X into unsigned binary data, big endian.
+ *                 Always fills the whole buffer, which will start with zeros
+ *                 if the number is smaller.
+ *
+ * \param X        Source MPI
+ * \param buf      Output buffer
+ * \param buflen   Output buffer size
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
+ */
+int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen );
+
+/**
+ * \brief          Left-shift: X <<= count
+ *
+ * \param X        MPI to shift
+ * \param count    Amount to shift
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count );
+
+/**
+ * \brief          Right-shift: X >>= count
+ *
+ * \param X        MPI to shift
+ * \param count    Amount to shift
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count );
+
+/**
+ * \brief          Compare unsigned values
+ *
+ * \param X        Left-hand MPI
+ * \param Y        Right-hand MPI
+ *
+ * \return         1 if |X| is greater than |Y|,
+ *                -1 if |X| is lesser  than |Y| or
+ *                 0 if |X| is equal to |Y|
+ */
+int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y );
+
+/**
+ * \brief          Compare signed values
+ *
+ * \param X        Left-hand MPI
+ * \param Y        Right-hand MPI
+ *
+ * \return         1 if X is greater than Y,
+ *                -1 if X is lesser  than Y or
+ *                 0 if X is equal to Y
+ */
+int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y );
+
+/**
+ * \brief          Compare signed values
+ *
+ * \param X        Left-hand MPI
+ * \param z        The integer value to compare to
+ *
+ * \return         1 if X is greater than z,
+ *                -1 if X is lesser  than z or
+ *                 0 if X is equal to z
+ */
+int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z );
+
+/**
+ * \brief          Unsigned addition: X = |A| + |B|
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
+
+/**
+ * \brief          Unsigned subtraction: X = |A| - |B|
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B is greater than A
+ */
+int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
+
+/**
+ * \brief          Signed addition: X = A + B
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
+
+/**
+ * \brief          Signed subtraction: X = A - B
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
+
+/**
+ * \brief          Signed addition: X = A + b
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param b        The integer value to add
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b );
+
+/**
+ * \brief          Signed subtraction: X = A - b
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param b        The integer value to subtract
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b );
+
+/**
+ * \brief          Baseline multiplication: X = A * B
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
+
+/**
+ * \brief          Baseline multiplication: X = A * b
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param b        The unsigned integer value to multiply with
+ *
+ * \note           b is unsigned
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b );
+
+/**
+ * \brief          Division by mbedtls_mpi: A = Q * B + R
+ *
+ * \param Q        Destination MPI for the quotient
+ * \param R        Destination MPI for the rest value
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *                 MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0
+ *
+ * \note           Either Q or R can be NULL.
+ */
+int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B );
+
+/**
+ * \brief          Division by int: A = Q * b + R
+ *
+ * \param Q        Destination MPI for the quotient
+ * \param R        Destination MPI for the rest value
+ * \param A        Left-hand MPI
+ * \param b        Integer to divide by
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *                 MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0
+ *
+ * \note           Either Q or R can be NULL.
+ */
+int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b );
+
+/**
+ * \brief          Modulo: R = A mod B
+ *
+ * \param R        Destination MPI for the rest value
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *                 MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0,
+ *                 MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B < 0
+ */
+int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B );
+
+/**
+ * \brief          Modulo: r = A mod b
+ *
+ * \param r        Destination mbedtls_mpi_uint
+ * \param A        Left-hand MPI
+ * \param b        Integer to divide by
+ *
+ * \return         0 if successful,
+ *                 MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *                 MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0,
+ *                 MBEDTLS_ERR_MPI_NEGATIVE_VALUE if b < 0
+ */
+int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b );
+
+/**
+ * \brief          Sliding-window exponentiation: X