diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..bd79a97 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,9 @@ +# Specify which files to substitute Format statements on export +*.[chsS] export-subst +*.ld export-subst +*.sh export-subst +*.mk export-subst +Makefile export-subst +.git* export-ignore + + diff --git a/.gitignore b/.gitignore index edf6645..66b3392 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,32 @@ *.i*86 *.x86_64 *.hex + +# Xcode +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 +*.xcuserstate +project.xcworkspace/ +xcuserdata/ + +#OS X +*.DS_Store + +#MatrixSSL Additional Generated Files +/core/memset_s.s +/core/test/test +/crypto/test/algorithmTest +/crypto/test/dhperf/dhperf +/crypto/test/eccperf/eccperf +/crypto/test/rsaperf/rsaperf +/crypto/test/sigVerify +/crypto/test/throughputTest +/matrixssl/test/certValidate +/matrixssl/test/sslTest +/apps/dtls/dtlsClient +/apps/dtls/dtlsServer +/apps/ssl/client +/apps/ssl/server + diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..def32e0 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,9 @@ +J Harper +Bryan Klisch +Steve Lokos + +Tom St.Denis + +PeerSec Networks +AuthenTec +INSIDE Secure diff --git a/FILES b/FILES new file mode 100644 index 0000000..1a61137 --- /dev/null +++ b/FILES @@ -0,0 +1,66 @@ +MatrixSSL Directory Structure + +/ +Makefile + Top level Makefile. Builds core, crypto, matrixssl and apps +common.mk + Top level file for common make definitions. + +matrixssl/ + This directory contains files the implement the SSL and TLS protocol. + test/ + sslTest - Single-process SSL handshake test application that + exercises the cipher suites and handshakes that are available + in the currently built library. + +crypto/ + digest/ + Message digests (SHA256, etc.) + symmetric/ + Symmetric ciphers (AES-GCM, etc.) + keyformat/ + Decode/encode Certificates and keys (X.509, .pem, etc.) + pubkey/ + RSA, ECC and DH operations + math/ + Large integer math operations + prng/ + Psuedo random number generation + layer/ + Cryptographic algorithm provider layer (FIPS, PKCS#11, etc.) + test/ + Functionality and performance tests. + +core/ + Utility functions + POSIX/ + Operating system layer for Linux, OS X, BSD + WIN32/ + Operating system layer for Windows + +apps/ + ssl/ + Example SSL client using blocking sockets and session resumption + Example SSL server using non-blocking sockets and simultaneous connections + dtls/ + Example DTLS client + Example DTLS server + +doc/ + Release notes + Developer guides + API documentation + +testkeys/ + Sample RSA, ECC, DH and PSK keys and certificate files for test and example apps + +xcode/ + Project files for XCode. These files directly call the Makefiles in + the source directories to build the matrixssl static libraries and + example applications. + +visualstudio/ + Project files for Visual Studio 2013. Builds the core, crypto and + matrixssl source into a single static library, and various example + applications. + diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..fc21d1d --- /dev/null +++ b/INSTALL @@ -0,0 +1,28 @@ +For detailed information, see Getting Started Guide + +Quick Start for Linux / Mac OS X +==== + +Configuration is done by manually editing the *Config.h files: +core/coreConfig.h +crypto/cryptoConfig.h +matrixssl/matrixsslConfig.h + +$ make +Builds static libraries: +core/libcore_s.a +crypto/libcrypt_s.a +matrixssl/libssl_s.a + +$ cd apps/ssl +$ make +Builds example client and server: +apps/ssl/client +apps/ssl/server + +$ ./server +Runs server example, listening on port 4433 + +$ ./runClient.sh +Runs client example with default parameters + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..af5dc1b --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +# Recursively build the directories below, in one of modes +# fips, nonfips, combined +# $Format:%h%d$ +all: + $(MAKE) --directory=core + $(MAKE) --directory=crypto + $(MAKE) --directory=matrixssl + +test: + $(MAKE) --directory=crypto/test + $(MAKE) --directory=matrixssl/test + +clean: + $(MAKE) clean --directory=core + $(MAKE) clean --directory=crypto + $(MAKE) clean --directory=crypto/test + $(MAKE) clean --directory=matrixssl + $(MAKE) clean --directory=matrixssl/test diff --git a/apps/dtls/Makefile b/apps/dtls/Makefile new file mode 100755 index 0000000..384a47b --- /dev/null +++ b/apps/dtls/Makefile @@ -0,0 +1,50 @@ +# +# Makefile for MatrixDTLS example apps +# 'make' builds debug (Default). +# 'make gold' builds optimized. +# +# Copyright (c) 2013-2016 INSIDE Secure Corporation. All Rights Reserved. +# + +MATRIXSSL_ROOT:=../.. +SERVER_SRC:=dtlsServer.c dtlsCommon.c +CLIENT_SRC:=dtlsClient.c dtlsCommon.c +SRC:=$(SERVER_SRC) $(CLIENT_SRC) + +include $(MATRIXSSL_ROOT)/common.mk + +# Generated files +SERVER_EXE:=dtlsServer$(E) +CLIENT_EXE:=dtlsClient$(E) + +# Linked files +STATIC:=\ + $(MATRIXSSL_ROOT)/matrixssl/libssl_s.a \ + $(MATRIXSSL_ROOT)/crypto/libcrypt_s.a \ + $(MATRIXSSL_ROOT)/core/libcore_s.a + +CIPHER_OPTION=ID_RSA # The default cipher option +CFLAGS+=-D$(CIPHER_OPTION) + + +ifdef DTLS_PACKET_LOSS_TEST +# Enable all packet-loss related tests +CFLAGS+=-DDTLS_PACKET_LOSS_TEST -DTEST_DTLS_CLIENT_REHANDSHAKE=1 -DDTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE +endif + +all: compile + +compile: $(OBJS) $(SERVER_EXE) $(CLIENT_EXE) + +# Additional Dependencies +$(OBJS): $(MATRIXSSL_ROOT)/common.mk Makefile $(wildcard *.h) + +$(SERVER_EXE): $(SERVER_SRC:.c=.o) $(STATIC) + $(CC) -o $@ $^ $(LDFLAGS) + +$(CLIENT_EXE): $(CLIENT_SRC:.c=.o) $(STATIC) + $(CC) -o $@ $^ $(LDFLAGS) + +clean: + rm -f $(SERVER_EXE) $(CLIENT_EXE) $(OBJS) TLS_*.tmp SSL_*.tmp + diff --git a/apps/dtls/dtlsClient.c b/apps/dtls/dtlsClient.c new file mode 100644 index 0000000..29cbc15 --- /dev/null +++ b/apps/dtls/dtlsClient.c @@ -0,0 +1,1101 @@ +/** + * @file dtlsClient.c + * @version $Format:%h%d$ + * + * MatrixDTLS client example. + */ +/* + * Copyright (c) 2014-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "dtlsCommon.h" + +#ifdef USE_CLIENT_SIDE_SSL + + +static int packet_loss_prob = 0; /* Reciprocal of packet loss probability + (i.e. P(packet loss) = 1/x). + Default value is 0 (no packet loss). */ + +#ifdef DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE +static int test_lost_cipherspec_change_rehandshake = 0; +#endif /* DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE */ + +/* Client DTLS context data type */ +typedef struct { + SOCKET fd; + struct sockaddr_in addr; + ssl_t *ssl; +} sslDtls_t; + +#ifdef WIN32 +#pragma message("DO NOT USE THESE DEFAULT KEYS IN PRODUCTION ENVIRONMENTS.") +#else +#warning "DO NOT USE THESE DEFAULT KEYS IN PRODUCTION ENVIRONMENTS." +#endif + +#define ALLOW_ANON_CONNECTIONS 1 +#define USE_HEADER_KEYS + +/* + If supporting client authentication, pick ONE identity to auto select a + certificate and private key that support desired algorithms. +*/ +//#define ID_RSA /* RSA Certificate and Key */ +//#define ID_ECDH_ECDSA /* EC Certificate and Key */ +//#define ID_ECDH_RSA /* EC Key with RSA signed certificate */ + + +/* If the algorithm type is supported, load a CA for it */ +#ifdef USE_HEADER_KEYS +/* CAs */ +#ifdef USE_RSA_CIPHER_SUITE +#include "testkeys/RSA/ALL_RSA_CAS.h" +#ifdef USE_ECC_CIPHER_SUITE +#include "testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS.h" +#endif +#endif +#ifdef USE_ECC_CIPHER_SUITE + +#if defined(USE_SECP192R1) && defined(USE_SECP224R1) && defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS.h" +#endif /* USE_SECP192R1 && USE_SECP224R1 && USE_SECP521R1 */ + +#if !defined(USE_SECP192R1) && defined(USE_SECP224R1) && defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192.h" +#endif /* !USE_SECP192R1 && USE_SECP224R1 && USE_SECP521R1 */ + +#if defined(USE_SECP192R1) && !defined(USE_SECP224R1) && defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P224.h" +#endif /* USE_SECP192R1 && !USE_SECP224R1 && USE_SECP521R1 */ + +#if defined(USE_SECP192R1) && defined(USE_SECP224R1) && !defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P521.h" +#endif /* USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ + +#if !defined(USE_SECP192R1) && !defined(USE_SECP224R1) && defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P224.h" +#endif /* !USE_SECP192R1 && !USE_SECP224R1 && USE_SECP521R1 */ + +#if !defined(USE_SECP192R1) && defined(USE_SECP224R1) && !defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P521.h" +#endif /* !USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ + +#if defined(USE_SECP192R1) && !defined(USE_SECP224R1) && !defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P224_AND_P521.h" +#endif /* USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ + +#if !defined(USE_SECP192R1) && !defined(USE_SECP224R1) && !defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192_P224_AND_P521.h" +#endif /* !USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ + +#endif /* USE_ECC_CIPHER_SUITE */ + +/* Identity Certs and Keys for use with Client Authentication */ +#ifdef ID_RSA +#define EXAMPLE_RSA_KEYS +#include "testkeys/RSA/1024_RSA.h" +#include "testkeys/RSA/1024_RSA_KEY.h" +#include "testkeys/RSA/2048_RSA.h" +#include "testkeys/RSA/2048_RSA_KEY.h" +#include "testkeys/RSA/3072_RSA.h" +#include "testkeys/RSA/3072_RSA_KEY.h" +#include "testkeys/RSA/4096_RSA.h" +#include "testkeys/RSA/4096_RSA_KEY.h" +#endif + +#ifdef ID_ECDH_ECDSA +#define EXAMPLE_EC_KEYS +#include "testkeys/EC/384_EC.h" +#include "testkeys/EC/384_EC_KEY.h" +#endif + +#ifdef ID_ECDH_RSA +#define EXAMPLE_ECDH_RSA_KEYS +#include "testkeys/ECDH_RSA/521_ECDH-RSA.h" +#include "testkeys/ECDH_RSA/521_ECDH-RSA_KEY.h" +#endif + +/* File-based keys */ +#else +/* CAs */ +#ifdef USE_RSA_CIPHER_SUITE +static char rsaCAFile[] = "testkeys/RSA/ALL_RSA_CAS.pem"; +#ifdef USE_ECC_CIPHER_SUITE +static char ecdhRsaCAFile[] = "testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS.pem"; +#endif +#endif +#ifdef USE_ECC_CIPHER_SUITE + +#if defined(USE_SECP192R1) && defined(USE_SECP521R1) +static char ecCAFile[] = "testkeys/EC/ALL_EC_CAS.pem"; +#endif /* USE_SECP192R1 && USE_SECP521R1 */ + +#if !defined(USE_SECP192R1) && defined(USE_SECP521R1) +static char ecCAFile[] = "testkeys/EC/ALL_EC_CAS_EXCEPT_P192.pem"; +#endif /* USE_SECP192R1 && USE_SECP521R1 */ + +#if defined(USE_SECP192R1) && !defined(USE_SECP521R1) +static char ecCAFile[] = "testkeys/EC/ALL_EC_CAS_EXCEPT_P521.pem"; +#endif /* USE_SECP192R1 && USE_SECP521R1 */ + +#if !defined(USE_SECP192R1) && !defined(USE_SECP521R1) +static char ecCAFile[] = "testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P521.pem"; +#endif /* USE_SECP192R1 && USE_SECP521R1 */ + +#endif /* USE_ECC_CIPHER_SUITE */ + +/* Identity Certs and Keys for use with Client Authentication */ +#ifdef ID_RSA +#define EXAMPLE_RSA_KEYS +static char rsaCertFile[] = "testkeys/RSA/2048_RSA.pem"; +static char rsaPrivkeyFile[] = "testkeys/RSA/2048_RSA_KEY.pem"; +#endif + +#ifdef ID_ECDH_ECDSA +#define EXAMPLE_EC_KEYS +static char ecCertFile[] = "testkeys/EC/384_EC.pem"; +static char ecPrivkeyFile[] = "testkeys/EC/384_EC_KEY.pem"; +#endif + +#ifdef ID_ECDH_RSA +#define EXAMPLE_ECDH_RSA_KEYS +static char ecdhRsaCertFile[] = "testkeys/ECDH_RSA/521_ECDH-RSA.pem"; +static char ecdhRsaPrivkeyFile[] = "testkeys/ECDH_RSA/521_ECDH-RSA_KEY.pem"; +#endif + +#endif /* USE_HEADER_KEYS */ + +#ifdef USE_PSK_CIPHER_SUITE +#include "testkeys/PSK/psk.h" +#endif + +/* + Test rehandshakes +*/ +#ifndef TEST_DTLS_CLIENT_REHANDSHAKE +#define TEST_DTLS_CLIENT_REHANDSHAKE 0 +#endif /* TEST_DTLS_CLIENT_REHANDSHAKE */ +#ifndef TEST_DTLS_CLIENT_RESUMED_REHANDSHAKE +#define TEST_DTLS_CLIENT_RESUMED_REHANDSHAKE 0 +#endif /* TEST_DTLS_CLIENT_RESUMED_REHANDSHAKE */ + +/********************************** Globals ***********************************/ + +static unsigned char helloWorld[] = "!!! MatrixDTLS Connection Complete !!!\n\n"; + +extern int opterr; +static char g_ip[16]; +static char g_path[256]; +static int g_port, g_new, g_resumed, g_ciphers; +static int g_key_len, g_disableCertNameChk; +static uint16_t g_cipher[16]; + +/****************************** Local Functions *******************************/ + +static int32 certCb(ssl_t *ssl, psX509Cert_t *cert, int32 alert); +static void closeConn(sslDtls_t *dtls, SOCKET fd); +static int32 sendHelloWorld(sslDtls_t *dtlsCtx); + + +/******************************************************************************/ +/* + Allocate the data structure to manage the socket and ssl combo of + a DTLS client. +*/ +static SOCKET dtlsInitClientSocket(sslDtls_t **newCtx, ssl_t *ssl) +{ + sslDtls_t *dtls; + + *newCtx = NULL; + + if ((dtls = psMalloc(NULL, sizeof(sslDtls_t))) == NULL) { + return PS_MEM_FAIL; + } + dtls->ssl = ssl; + + if ((dtls->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + _psTrace("Error creating INET UDP socket\n"); + psFree(dtls, NULL); + return INVALID_SOCKET; + } + + memset(&dtls->addr, 0x0, sizeof(struct sockaddr_in)); + dtls->addr.sin_family = AF_INET; + dtls->addr.sin_port = htons((short)g_port); + dtls->addr.sin_addr.s_addr = inet_addr(g_ip); + *newCtx = dtls; + + udpInitProxy(); + + return dtls->fd; +} + +/******************************************************************************/ +/* + Make a secure HTTP request to a defined IP and port + Connection is made in blocking socket mode + The connection is considered successful if the SSL/TLS session is + negotiated successfully, a request is sent, and a HTTP response is received. + */ +static int32 dtlsClientConnection(sslKeys_t *keys, sslSessionId_t *sid) +{ + int32 rc, transferred, len, val, weAreDone; + ssl_t *ssl; + sslDtls_t *dtlsCtx; + unsigned char *buf; + socklen_t addrlen; + struct sockaddr_in from; + socklen_t fromLen; + struct timeval timeout; + long tSec; + fd_set readfd; + SOCKET fd; + sslSessOpts_t options; + int16 rehandshakeTestDone, resumedRehandshakeTestDone; + +#ifdef DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE + int drop_next_cipherspec_packet = 0; +#endif /* DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE */ + + memset(&options, 0x0, sizeof(sslSessOpts_t)); + options.versionFlag = SSL_FLAGS_DTLS; + options.trustedCAindication = 1; + + + /* We are passing the IP address of the server as the expected name */ + /* To skip certificate subject name tests, pass NULL instead of g_ip */ + if (g_disableCertNameChk == 0) { + rc = matrixSslNewClientSession(&ssl, keys, sid, g_cipher, g_ciphers, + certCb, g_ip, NULL, NULL, &options); + } else { + rc = matrixSslNewClientSession(&ssl, keys, sid, g_cipher, g_ciphers, + certCb, NULL, NULL, NULL, &options); + } + + if (rc != MATRIXSSL_REQUEST_SEND) { + _psTraceInt("New Client Session Failed: %d. Exiting\n", rc); + return PS_ARG_FAIL; + } + +/* + Create the UDP socket and associate the SSL context with it +*/ + if ((fd = dtlsInitClientSocket(&dtlsCtx, ssl)) < 0) { + matrixSslDeleteSession(ssl); + return fd; + } +/* + Local inits +*/ + rehandshakeTestDone = resumedRehandshakeTestDone = 0; + weAreDone = 0; /* resumed handshake exit hint mechanism */ + addrlen = sizeof(dtlsCtx->addr); + memset(&from, 0x0, sizeof(struct sockaddr_in)); + +/* + Timeout mechanism is implemented according to guidelines in spec +*/ + tSec = MIN_WAIT_SECS; + timeout.tv_usec = 0; + +/* + matrixDtlsGetOutdata will always return data to send. If a new outgoing + flight is not waiting to be send a resend of the previous flight will be + returned. +*/ +WRITE_MORE: + while ((len = matrixDtlsGetOutdata(ssl, &buf)) > 0) { +#ifdef DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE + if (test_lost_cipherspec_change_rehandshake && drop_next_cipherspec_packet) + transferred = udpSend(fd, buf, len, (struct sockaddr*)&dtlsCtx->addr, + addrlen, (int)tSec, + packet_loss_prob, &drop_next_cipherspec_packet); + else +#endif /* DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE */ + transferred = udpSend(fd, buf, len, (struct sockaddr*)&dtlsCtx->addr, + addrlen, (int)tSec, + packet_loss_prob, NULL); + + if (transferred <= 0) { + goto L_CLOSE_ERR; + } else { + /* Always indicate the entire datagram was sent as there is no + way for DTLS to handle partial records. Resends and timeouts will + handle any problems */ + if ((rc = matrixDtlsSentData(ssl, len)) < 0) { + goto L_CLOSE_ERR; + } + if (rc == MATRIXSSL_REQUEST_CLOSE) { + /* This is a 'graceful' exit so return success */ + closeConn(dtlsCtx, fd); + return MATRIXSSL_SUCCESS; + } + if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) { + /* This is the resumed handshake endgame case and is a bit more + problematic than the standard case because we are the last + to send and we can't be sure the server received our FINISHED + message. Let's handle this in our example by waiting another + timeout to see if the server is trying to resend */ + _psTrace("Resumed handshake case. Pausing to check "); + _psTrace("server received final FINISHED message\n"); + tSec = 4; + timeout.tv_usec = 0; + weAreDone = 1; + } + /* SSL_REQUEST_SEND is handled by loop logic */ + } + } + +READ_MORE: + /* Select is the DTLS timeout/resend mechanism */ + FD_ZERO(&readfd); + FD_SET(fd, &readfd); + timeout.tv_sec = tSec; + + if ((val = select(fd+1, &readfd, NULL, NULL, &timeout)) < 0) { + if (SOCKET_ERRNO != EINTR) { + psTraceIntDtls("unhandled error %d from select", SOCKET_ERRNO); + goto L_CLOSE_ERR; + } + goto READ_MORE; + } + /* Check for timeout or select wake-up */ + if (!FD_ISSET(fd, &readfd)) { + /* Timed out. For good? */ + psTraceIntDtls("select timed out %d\n", val); + if (tSec == MAX_WAIT_SECS) { + psTraceDtls("Max Timeout. Leaving\n"); + goto L_CLOSE_ERR; + } + tSec *= 2; + /* Our special exit case for resumed handshakes was simply to wait + and see if the server was resending its FINISHED message. If not, + safe to assume we are connected. Send app data and leave */ + if (weAreDone == 1) { + if (TEST_DTLS_CLIENT_RESUMED_REHANDSHAKE == 1 && + resumedRehandshakeTestDone == 0) { + sendHelloWorld(dtlsCtx); + _psTrace("--- Initiating resumed rehandshake ---\n"); + resumedRehandshakeTestDone = 1; + weAreDone = 0; + matrixSslEncodeRehandshake(ssl, NULL, NULL, 0, g_cipher, + g_ciphers); + goto WRITE_MORE; + } + sendHelloWorld(dtlsCtx); + closeConn(dtlsCtx, fd); + return MATRIXSSL_SUCCESS; + } + /* Normal timeout case is to resend flight */ + goto WRITE_MORE; + } + + /* Select woke. Reset timeout */ + tSec = MIN_WAIT_SECS; + + if ((len = matrixSslGetReadbuf(ssl, &buf)) <= 0) { + goto L_CLOSE_ERR; + } + fromLen = sizeof(struct sockaddr_in); + if ((transferred = (int32)recvfrom(fd, buf, len, MSG_DONTWAIT, + (struct sockaddr*)&from, &fromLen)) < 0) { + goto L_CLOSE_ERR; + } + +#ifdef USE_DTLS_DEBUG_TRACE + /* nice for debugging */ + psTraceIntDtls("Read %d bytes from server\n", transferred); +#endif + + /* If EOF, remote socket closed. But we haven't received the HTTP response + so we consider it an error in the case of an HTTP client */ + if (transferred == 0) { + goto L_CLOSE_ERR; + } + if ((rc = matrixSslReceivedData(ssl, (int32)transferred, &buf, + (uint32*)&len)) < 0) { + goto L_CLOSE_ERR; + } + +PROCESS_MORE: + switch (rc) { + case MATRIXSSL_HANDSHAKE_COMPLETE: + /* This is the ideal protocol scenario to know that the handshake is + complete when the client sends app data first. This is the normal + handshake case and the client is the last to receive FINISHED + + If enabled, perform a rehandshake test */ + if (TEST_DTLS_CLIENT_REHANDSHAKE == 1 && rehandshakeTestDone == 0) { + sendHelloWorld(dtlsCtx); + _psTrace("--- Initiating rehandshake ---\n"); + +#ifdef DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE + if (test_lost_cipherspec_change_rehandshake) { + /* + Cause an encryption algorithm change during a re-handshake. + The aim here is to test the dtlsRevertWriteCipher() function, + in the situation where the CHANGE_CIPHER_SPEC message + that is supposed to inform the server about the + algorithm change gets lost. + The following cipher spec changes are supported: + TLS_RSA_WITH_AES_128_GCM_SHA256 --> TLS_RSA_WITH_AES_128_CBC_SHA256 + (anything) --> TLS_RSA_WITH_AES_128_GCM_SHA256. + */ + _psTrace("Forcing a change cipher spec...\n"); + if (g_cipher[0] == TLS_RSA_WITH_AES_128_GCM_SHA256) + g_cipher[0] = TLS_RSA_WITH_AES_128_CBC_SHA256; + else + g_cipher[0] = TLS_RSA_WITH_AES_128_GCM_SHA256; + if (drop_next_cipherspec_packet == 1) + drop_next_cipherspec_packet = 0; + else + drop_next_cipherspec_packet = 1; + } +#endif /* DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE */ + if (matrixSslEncodeRehandshake(ssl, NULL, NULL, + SSL_OPTION_FULL_HANDSHAKE, + g_cipher, g_ciphers) == MATRIXSSL_SUCCESS) { + rehandshakeTestDone = 1; + goto WRITE_MORE; + } + else { + _psTrace("matrixSslEncodeRehandshake failed\n"); + goto L_CLOSE_ERR; + } + } + + sendHelloWorld(dtlsCtx); + closeConn(dtlsCtx, fd); + return MATRIXSSL_SUCCESS; + + case MATRIXSSL_APP_DATA: +/* + Would process app data here +*/ + if ((rc = matrixSslProcessedData(ssl, &buf, (uint32*)&len)) == 0) { + goto READ_MORE; + } + goto PROCESS_MORE; + case MATRIXSSL_REQUEST_SEND: + goto WRITE_MORE; + case MATRIXSSL_REQUEST_RECV: + goto READ_MORE; + case MATRIXSSL_RECEIVED_ALERT: + /* The first byte of the buffer is the level */ + /* The second byte is the description */ + if (*buf == SSL_ALERT_LEVEL_FATAL) { + psTraceIntInfo("Fatal alert: %d, closing connection.\n", + *(buf + 1)); + goto L_CLOSE_ERR; + } + /* Closure alert is normal (and best) way to close */ + if (*(buf + 1) == SSL_ALERT_CLOSE_NOTIFY) { + closeConn(dtlsCtx, fd); + return MATRIXSSL_SUCCESS; + } + psTraceIntInfo("Warning alert: %d\n", *(buf + 1)); + if ((rc = matrixSslProcessedData(ssl, &buf, (uint32*)&len)) == 0) { + /* No more data in buffer. Might as well read for more. */ + goto READ_MORE; + } + goto PROCESS_MORE; + default: + /* If rc <= 0 we fall here */ + goto L_CLOSE_ERR; + } + +L_CLOSE_ERR: + _psTrace("DTLS Connection FAIL. Exiting\n"); + closeConn(dtlsCtx, fd); + return MATRIXSSL_ERROR; +} + +/******************************************************************************/ +/* + Example application data send +*/ +static int32 sendHelloWorld(sslDtls_t *dtlsCtx) +{ + unsigned char *buf; + int32 avail, len, ret; + + _psTrace("DTLS handshake complete. Sending sample application data\n"); + len = (int32)strlen((char*)helloWorld) + 1; +/* + Get free buffer, copy in plaintext, and encode +*/ + if ((avail = matrixSslGetWritebuf(dtlsCtx->ssl, &buf, len)) < 0) { + return PS_MEM_FAIL; + } + avail = min(avail, len); + strncpy((char*)buf, (char*)helloWorld, avail); + + matrixSslEncodeWritebuf(dtlsCtx->ssl, avail); +/* + Get the encoded buffer and write it out +*/ + while ((len = matrixDtlsGetOutdata(dtlsCtx->ssl, &buf)) > 0) { + ret = (int32)sendto(dtlsCtx->fd, buf, len, 0, + (struct sockaddr*)&dtlsCtx->addr, sizeof(struct sockaddr_in)); + if (ret == -1) { + perror("sendto"); + exit(1); + } + matrixDtlsSentData(dtlsCtx->ssl, len); + } + return PS_SUCCESS; +} + +static void usage(void) +{ + printf("\nusage: client { option }\n" + "\n" + "where option can be one of the following:\n" + "\n" + "-c - Comma separated list of ciphers nums\n" + "-d - Disable server certicate name/addr chk\n" + "-h - Print usage and exit\n" + "-k - RSA keyLen (if using client auth)\n" + "-n - Num of new (full handshake) sessions\n" + "-p - Port number for DTLS server\n" + "-r - Num of resumed DTLS sesssions\n" + "-s - IP address of server machine/interface\n" +#ifdef DTLS_PACKET_LOSS_TEST + "-l - Reciprocal of packet loss probability\n" + " (for packet loss simulation tests)\n" +#endif /* DTLS_PACKET_LOSS_TEST */ +#ifdef DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE + "-x - Run test, where the client tries to change\n" + " the cipher spec during a re-handshake and\n" + " the CHANGE_CIPHER_SPEC message is lost.\n" +#endif /* DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE */ + "\n" + "where -s is a required option (i.e. has no current default, and\n" + "serverPortNum is usually 443 or 4433. The cipherList is a comma separated list\n" + "of cipher numbers to propose. It should NOT contain any spaces.\n\n"); + + printf("Common ciphers and the cipher number to use in the cipherList:\n" + " 53 TLS_RSA_WITH_AES_256_CBC_SHA\n" + " 47 TLS_RSA_WITH_AES_128_CBC_SHA\n" + " 10 SSL_RSA_WITH_3DES_EDE_CBC_SHA\n" + " 5 SSL_RSA_WITH_RC4_128_SHA\n" + " 4 SSL_RSA_WITH_RC4_128_MD5\n"); +} + +// Returns number of cipher numbers found, or -1 if an error. +static int32 parse_cipher_list(char *cipherListString, + uint16_t cipher_array[], + uint32 size_of_cipher_array) +{ + int32 numCiphers, cipher; + char *endPtr; + + // Convert the cipherListString into an array of cipher numbers. + numCiphers = 0; + while (cipherListString != NULL) + { + cipher = (int32)strtol(cipherListString, &endPtr, 10); + if (endPtr == cipherListString) + { + printf("The remaining cipherList has no cipher numbers - '%s'\n", + cipherListString); + return -1; + } + else if (size_of_cipher_array <= numCiphers) + { + printf("Too many cipher numbers supplied. limit is %d\n", + size_of_cipher_array); + return -1; + } + else + { + cipher_array[numCiphers++] = cipher; + if (*endPtr == '\0') + break; + else if (*endPtr != ',') + { + printf("\n"); + return -1; + } + + cipherListString = endPtr + 1; + } + } + + return numCiphers; +} + +/* Return 0 on good set of cmd options, return -1 if a bad cmd option is + encountered OR a request for help is seen (i.e. '-h' option). */ +static int32 process_cmd_options(int32 argc, char **argv) +{ + int optionChar, key_len, numCiphers, g_ip_set; + char *cipherListString; + + // Set some default options: + memset(g_cipher, 0, sizeof(g_cipher)); + memset(g_ip, 0, sizeof(g_ip)); + memset(g_path, 0, sizeof(g_path)); + + g_ip_set = 0; + g_ciphers = 1; + g_cipher[0] = 47; + g_disableCertNameChk = 0; + g_key_len = 1024; + g_new = 1; + g_port = 4433; + g_resumed = 1; + + opterr = 0; + while ((optionChar = getopt(argc, argv, "c:dhk:n:p:r:s:l:x")) != -1) + { + switch (optionChar) + { + case '?': + return -1; + + + case 'c': + // Convert the cipherListString into an array of cipher numbers. + cipherListString = optarg; + numCiphers = parse_cipher_list(cipherListString, g_cipher, 16); + if (numCiphers <= 0) + return -1; + + g_ciphers = numCiphers; + break; + + case 'd': + g_disableCertNameChk = 1; + break; + + case 'h': + return -1; + + case 'k': + key_len = atoi(optarg); + if ((key_len != 1024) && (key_len != 2048) && (key_len != 3072) + && (key_len != 4096)) + { + printf("-k option must be followed by a key_len whose value " + " must be 1024, 2048, 3072 or 4096\n"); + return -1; + } + + g_key_len = key_len; + break; + + case 'n': + g_new = atoi(optarg); + break; + + case 'p': + g_port = atoi(optarg); + break; + + case 'r': + g_resumed = atoi(optarg); + break; + + case 's': + g_ip_set = 1; + strncpy(g_ip, optarg, 15); + break; + +#ifdef DTLS_PACKET_LOSS_TEST + case 'l': + packet_loss_prob = atoi(optarg); + if (packet_loss_prob < 0) { + printf("invalid -l option\n"); + return -1; + } + if (packet_loss_prob > 0) { + printf("Client simulating packet loss with probability 1/%d\n", + packet_loss_prob); + } + break; + +#ifdef DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE + case 'x': + test_lost_cipherspec_change_rehandshake = 1; + break; +#endif /* DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE */ +#endif /* DTLS_PACKET_LOSS_TEST */ + } + } + + if (g_ip_set == 0) + { + printf("The -s option is currently required!\n"); + return -1; + } + + return 0; +} + +#if defined(USE_HEADER_KEYS) && defined(ID_RSA) +static int32 loadRsaKeys(uint32 key_len, sslKeys_t *keys, + unsigned char *CAstream, int32 CAstreamLen) +{ + int32 rc; + + if (key_len == 1024) { + _psTrace("Using 1024 bit RSA private key\n"); + rc = matrixSslLoadRsaKeysMem(keys, RSA1024, sizeof(RSA1024), + RSA1024KEY, sizeof(RSA1024KEY), CAstream, CAstreamLen); + } else if (key_len == 2048) { + _psTrace("Using 2048 bit RSA private key\n"); + rc = matrixSslLoadRsaKeysMem(keys, RSA2048, sizeof(RSA2048), + RSA2048KEY, sizeof(RSA2048KEY), CAstream, CAstreamLen); + } else if (key_len == 3072) { + _psTrace("Using 3072 bit RSA private key\n"); + rc = matrixSslLoadRsaKeysMem(keys, RSA3072, sizeof(RSA3072), + RSA3072KEY, sizeof(RSA3072KEY), CAstream, CAstreamLen); + } else if (key_len == 4096) { + _psTrace("Using 4096 bit RSA private key\n"); + rc = matrixSslLoadRsaKeysMem(keys, RSA4096, sizeof(RSA4096), + RSA4096KEY, sizeof(RSA4096KEY), CAstream, CAstreamLen); + } else { + rc = -1; + psAssert((key_len == 1024) || (key_len == 2048) || (key_len == 3072) + ||(key_len == 4096)); + } + + if (rc < 0) { + _psTrace("No certificate material loaded. Exiting\n"); + if (CAstream) { + psFree(CAstream, NULL); + } + matrixSslDeleteKeys(keys); + matrixSslClose(); + } + + return rc; +} +#endif + +/******************************************************************************/ +/* + Main routine. Initialize SSL keys and structures, and make two DTLS + connections, the first with a blank session Id, and the second with + a session ID populated during the first connection to do a much faster + session resumption connection the second time. + */ +int32 main(int32 argc, char **argv) +{ + int32 rc, CAstreamLen; + sslKeys_t *keys; + sslSessionId_t *sid; + unsigned char *CAstream; + int32 rv; +#ifdef WIN32 + WSADATA wsaData; + WSAStartup(MAKEWORD(1, 1), &wsaData); +#endif + if ((rc = matrixSslOpen()) < 0) { + _psTrace("MatrixSSL library init failure. Exiting\n"); + return rc; + } + if (matrixSslNewKeys(&keys, NULL) < 0) { + matrixSslClose(); + _psTrace("MatrixSSL library key init failure. Exiting\n"); + return -1; + } + + if (0 != process_cmd_options(argc, argv)) { + usage(); + return 0; + } + printf("client https://%s:%d%s " + "new:%d resumed:%d keylen:%d nciphers:%d\n", + g_ip, g_port, g_path, g_new, g_resumed, g_key_len, + g_ciphers); + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#ifdef USE_HEADER_KEYS +/* + In-memory based keys + Build the CA list first for potential client auth usage +*/ + CAstreamLen = 0; +#ifdef USE_RSA_CIPHER_SUITE + CAstreamLen += sizeof(RSACAS); +#ifdef USE_ECC_CIPHER_SUITE + CAstreamLen += sizeof(ECDHRSACAS); +#endif +#endif +#ifdef USE_ECC_CIPHER_SUITE + CAstreamLen += sizeof(ECCAS); +#endif + if (CAstreamLen > 0) { + CAstream = psMalloc(NULL, CAstreamLen); + } else { + CAstream = NULL; + } + + CAstreamLen = 0; +#ifdef USE_RSA_CIPHER_SUITE + memcpy(CAstream, RSACAS, sizeof(RSACAS)); + CAstreamLen += sizeof(RSACAS); +#ifdef USE_ECC_CIPHER_SUITE + memcpy(CAstream + CAstreamLen, ECDHRSACAS, sizeof(ECDHRSACAS)); + CAstreamLen += sizeof(ECDHRSACAS); +#endif +#endif +#ifdef USE_ECC_CIPHER_SUITE + memcpy(CAstream + CAstreamLen, ECCAS, sizeof(ECCAS)); + CAstreamLen += sizeof(ECCAS); +#endif + +#ifdef ID_RSA + rc = loadRsaKeys(g_key_len, keys, CAstream, CAstreamLen); + if (rc < 0) { + return rc; + } +#endif + +#ifdef ID_ECDH_RSA + if ((rc = matrixSslLoadEcKeysMem(keys, ECDHRSA521, sizeof(ECDHRSA521), + ECDHRSA521KEY, sizeof(ECDHRSA521KEY), CAstream, CAstreamLen)) < 0) { + _psTrace("No certificate material loaded. Exiting\n"); + if (CAstream) psFree(CAstream, NULL); + matrixSslDeleteKeys(keys); + matrixSslClose(); + return rc; + } +#endif + +#ifdef ID_ECDH_ECDSA + if ((rc = matrixSslLoadEcKeysMem(keys, EC384, sizeof(EC384), + EC384KEY, sizeof(EC384KEY), CAstream, CAstreamLen)) < 0) { + _psTrace("No certificate material loaded. Exiting\n"); + if (CAstream) psFree(CAstream, NULL); + matrixSslDeleteKeys(keys); + matrixSslClose(); + return rc; + } +#endif + + if (CAstream) psFree(CAstream, NULL); + +#else +/* + File based keys +*/ + CAstreamLen = 0; +#ifdef USE_RSA_CIPHER_SUITE + CAstreamLen += (int32)strlen(rsaCAFile) + 1; +#ifdef USE_ECC_CIPHER_SUITE + CAstreamLen += (int32)strlen(ecdhRsaCAFile) + 1; +#endif +#endif +#ifdef USE_ECC_CIPHER_SUITE + CAstreamLen += (int32)strlen(ecCAFile) + 1; +#endif + if (CAstreamLen > 0) { + CAstream = psMalloc(NULL, CAstreamLen); + memset(CAstream, 0x0, CAstreamLen); + } else { + CAstream = NULL; + } + + CAstreamLen = 0; +#ifdef USE_RSA_CIPHER_SUITE + memcpy(CAstream, rsaCAFile, strlen(rsaCAFile)); + CAstreamLen += strlen(rsaCAFile); +#ifdef USE_ECC_CIPHER_SUITE + memcpy(CAstream + CAstreamLen, ";", 1); CAstreamLen++; + memcpy(CAstream + CAstreamLen, ecdhRsaCAFile, strlen(ecdhRsaCAFile)); + CAstreamLen += strlen(ecdhRsaCAFile); +#endif +#endif +#ifdef USE_ECC_CIPHER_SUITE + if (CAstreamLen > 0) { + memcpy(CAstream + CAstreamLen, ";", 1); CAstreamLen++; + } + memcpy(CAstream + CAstreamLen, ecCAFile, strlen(ecCAFile)); +#endif + +/* Load Identiy */ +#ifdef EXAMPLE_RSA_KEYS + if ((rc = matrixSslLoadRsaKeys(keys, rsaCertFile, rsaPrivkeyFile, NULL, + (char*)CAstream)) < 0) { + _psTrace("No certificate material loaded. Exiting\n"); + if (CAstream) psFree(CAstream); + matrixSslDeleteKeys(keys); + matrixSslClose(); + return rc; + } +#endif + +#ifdef EXAMPLE_ECDH_RSA_KEYS + if ((rc = matrixSslLoadEcKeys(keys, ecdhRsaCertFile, ecdhRsaPrivkeyFile, + NULL, (char*)CAstream)) < 0) { + _psTrace("No certificate material loaded. Exiting\n"); + if (CAstream) psFree(CAstream); + matrixSslDeleteKeys(keys); + matrixSslClose(); + return rc; + } +#endif + +#ifdef EXAMPLE_EC_KEYS + if ((rc = matrixSslLoadEcKeys(keys, ecCertFile, ecPrivkeyFile, NULL, + (char*)CAstream)) < 0) { + _psTrace("No certificate material loaded. Exiting\n"); + if (CAstream) psFree(CAstream); + matrixSslDeleteKeys(keys); + matrixSslClose(); + return rc; + } +#endif + + if (CAstream) psFree(CAstream); +#endif /* USE_HEADER_KEYS */ +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ + +#ifdef USE_PSK_CIPHER_SUITE + for (rc = 0; rc < PSK_HEADER_TABLE_COUNT; rc++) { + matrixSslLoadPsk(keys, + PSK_HEADER_TABLE[rc].key, sizeof(PSK_HEADER_TABLE[rc].key), + PSK_HEADER_TABLE[rc].id, sizeof(PSK_HEADER_TABLE[rc].id)); + } +#endif /* USE_PSK_CIPHER_SUITE */ + + rv = MATRIXSSL_ERROR; + + matrixSslNewSessionId(&sid, NULL); + printf("=== %d new connections ===\n", g_new); + for (rc = 0; rc < g_new; rc++) { + matrixSslNewSessionId(&sid, NULL); + rv = dtlsClientConnection(keys, sid); + if (rv < 0) + goto out_main; + /* Leave the final sessionID for resumed connections */ + if (rc + 1 < g_new) matrixSslDeleteSessionId(sid); + } + if (g_new) printf("\n"); + + + + printf("=== %d resumed connections ===\n", g_resumed); + for (rc = 0; rc < g_resumed; rc++) { + rv = dtlsClientConnection(keys, sid); + if (rv < 0) + goto out_main; + } + +out_main: + matrixSslDeleteSessionId(sid); + matrixSslDeleteKeys(keys); + matrixSslClose(); + +#ifdef WIN32 + _psTrace("Press any key to close"); + getchar(); +#endif + + if (rv == 0) + return 0; + else + return 1; +} + +/******************************************************************************/ +/* + Close a socket and free associated SSL context and buffers + An attempt is made to send a closure alert + */ +static void closeConn(sslDtls_t *dtls, SOCKET fd) +{ + ssl_t *ssl; + unsigned char *buf; + int32 len, ret; + + ssl = dtls->ssl; + + /* Quick attempt to send a closure alert, don't worry about failure */ + if (matrixSslEncodeClosureAlert(ssl) >= 0) { + if ((len = matrixDtlsGetOutdata(ssl, &buf)) > 0) { + ret = (int32)sendto(fd, buf, len, 0, (struct sockaddr*)&dtls->addr, + sizeof(struct sockaddr_in)); + if (ret == -1) { + /* sendto failed, but we don't care about that because + the connection was closing. Maybe server was faster + in closing the connection down. */ + } + matrixDtlsSentData(ssl, len); + } + } + psFree(dtls, NULL); + matrixSslDeleteSession(ssl); + close(fd); +} + +/******************************************************************************/ +/* + Example callback to do additional certificate validation. + If this callback is not registered in matrixSslNewService, + the connection will be accepted or closed based on the status flag. + */ +static int32 certCb(ssl_t *ssl, psX509Cert_t *cert, int32 alert) +{ +#ifndef USE_ONLY_PSK_CIPHER_SUITE + + /* Example to allow anonymous connections based on a define */ + if (alert > 0) { + if (ALLOW_ANON_CONNECTIONS) { + _psTraceStr("Allowing anonymous connection for: %s.\n", + cert->subject.commonName); + return SSL_ALLOW_ANON_CONNECTION; + } + _psTrace("Certificate callback returning fatal alert\n"); + return alert; + } + + psTraceStrDtls("Validated cert for: %s.\n", cert->subject.commonName); + +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + return PS_SUCCESS; +} + +#else +/******************************************************************************/ +/* + Stub main for compiling without client enabled +*/ +int32 main(int32 argc, char **argv) +{ + printf("USE_CLIENT_SIDE_SSL must be enabled in matrixsslConfig.h at build" \ + " time to run this application\n"); + return -1; +} +#endif /* USE_CLIENT_SIDE_SSL */ + +/******************************************************************************/ + diff --git a/apps/dtls/dtlsCommon.c b/apps/dtls/dtlsCommon.c new file mode 100644 index 0000000..966a323 --- /dev/null +++ b/apps/dtls/dtlsCommon.c @@ -0,0 +1,123 @@ +/** + * @file dtlsCommon.c + * @version $Format:%h%d$ + */ +/* + * Copyright (c) 2014-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ + +#include "dtlsCommon.h" + +#ifdef DTLS_PACKET_LOSS_TEST +static int num_dropped = 0; +#endif /* DTLS_PACKET_LOSS_TEST */ + +/******************************************************************************/ +/* + Set up a PRNG context for dropping random packets +*/ +void udpInitProxy(void) +{ + /* This function is no longer needed, since we are + using matrixCryptoGetPrngData instead of psGetPrng. + TODO: remove? */ +} + +/******************************************************************************/ +/* + Wrapper around sendto to easily plug in and out the dropped packet tests +*/ +int32 udpSend(SOCKET s, unsigned char *buf, int len, + const struct sockaddr *to, int tolen, int flags, + int packet_loss_prob, int *drop_rehandshake_cipher_spec) +{ + int32 sent; + +#ifdef DTLS_PACKET_LOSS_TEST +#ifdef DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE + if (drop_rehandshake_cipher_spec != NULL + && *drop_rehandshake_cipher_spec == 1) { + /* Test dropping a CIPHER_SPEC_CHANGE containing the new cipher spec + during a re-handshake. */ + if (buf[12] == 0x40 || + buf[12] == 0x26 /* Quick hack: use record length to find our re-handshake + CIPHER_SPEC_CHANGE. Note: this trick will probably + only work in our current test scenario and may stop + working if e.g. the ciphers used in the test + are changed. */ + ) { + *drop_rehandshake_cipher_spec = 0; + psTraceIntDtls("Didn't send (CHANGE_CIPHER_SPEC flight): %d\n", len); + ++num_dropped; + } + else { + if ((sent = sendto(s, buf, len, 0, to, tolen)) < 0) { + return -1; + } + psTraceIntDtls("Sent %d bytes\n", sent); + } + } + else { +#endif /* DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE */ + /* Test random packet loss. */ + uint32 randInt; + (void)matrixCryptoGetPrngData((unsigned char*)&randInt, + sizeof(uint32), NULL); + + if ((packet_loss_prob == 0) || (randInt % packet_loss_prob)) { + if ((sent = sendto(s, buf, len, 0, to, tolen)) < 0) { + return -1; + } + psTraceIntDtls("Sent %d bytes\n", sent); + } else { + /* flags is used here as the current timeout value. if it's too high + we've already skipped a few sends so let's not timeout */ + if (flags >= 16) { + if ((sent = sendto(s, buf, len, 0, to, tolen)) < 0) { + return -1; + } + psTraceIntDtls("Sent %d bytes\n", sent); + } else { + psTraceIntDtls("Didn't send: %d\n", len); + ++num_dropped; + } + } +#ifdef DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE + } +#endif /* DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE */ +#else + if ((sent = (int32)sendto(s, buf, len, 0, to, tolen)) < 0) { + return -1; + } + psTraceIntDtls("Sent %d bytes\n", sent); +#endif /* DTLS_PACKET_LOSS_TEST */ +#ifdef DTLS_PACKET_LOSS_TEST + psTraceIntDtls("%d packets dropped so far\n", + num_dropped); /* TODO: print different counts + for client and server. */ +#endif /* DTLS_PACKET_LOSS_TEST */ + return len; +} diff --git a/apps/dtls/dtlsCommon.h b/apps/dtls/dtlsCommon.h new file mode 100644 index 0000000..3cbbb54 --- /dev/null +++ b/apps/dtls/dtlsCommon.h @@ -0,0 +1,121 @@ +/** + * @file dtlsCommon.h + * @version $Format:%h%d$ + */ +/* + * Copyright (c) 2014-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ + +#ifndef _h_DTLSCOMMON +#define _h_DTLSCOMMON + +#include "matrixssl/matrixsslApi.h" + +#ifndef USE_DTLS + #error USE_DTLS must be defined in matrixsslConfig.h +#endif + +#include +#include +#include +#include /* Defines FD_CLOEXEC, etc. */ +#include /* Defines EWOULDBLOCK, etc. */ + +#ifdef POSIX +#include +#include /* Defines AF_INET, etc. */ +#include /* sockaddr */ +#include /* inet_addr */ +#endif /* POSIX */ + +#ifdef WIN32 +#include +#include + +#define SIGPIPE SIGABRT +#define close closesocket +#define MSG_DONTWAIT 0 +#endif /* WIN32 */ + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef SOCKET +typedef int SOCKET; +#endif + +/* + Timeout and debug settings +*/ + +#define MIN_WAIT_SECS 1 /* SHOULD be 1. Also the default */ +#define MAX_WAIT_SECS 32 /* SHOULD be 2^x as time is doubled on timeout */ + +/* + Enable to intentially not send some datagrams for testing purposes +*/ +#ifndef DTLS_PACKET_LOSS_TEST +/* #define DTLS_PACKET_LOSS_TEST */ +#endif /* DTLS_PACKET_LOSS_TEST */ + +/* + Enable a test where the client tries to change the cipher spec during + a re-handshake and the resulting CHANGE_CIPHER_SPEC message is lost. + Requires #define DTLS_PACKET_LOST_TEST. +*/ +#ifdef DTLS_PACKET_LOSS_TEST +#ifndef DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE +/* #define DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE */ +#endif /* DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE */ +#endif /* DTLS_PACKET_LOSS_TEST */ + +#define DTLS_FATAL -1 + + +#ifdef WIN32 +#define SOCKET_ERRNO WSAGetLastError() +#else +#define SOCKET_ERRNO errno +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET -1 +#endif + +extern void udpInitProxy(void); +extern int32 udpSend(SOCKET s, unsigned char *buf, int len, + const struct sockaddr *to, int tolen, int flags, + int packet_loss_prob, int *drop_rehandshake_cipher_spec); + +#ifdef __cplusplus +} +#endif + +#endif /* _h_DTLSCOMMON */ + +/******************************************************************************/ diff --git a/apps/dtls/dtlsServer.c b/apps/dtls/dtlsServer.c new file mode 100644 index 0000000..2440a70 --- /dev/null +++ b/apps/dtls/dtlsServer.c @@ -0,0 +1,1282 @@ +/** + * @file dtlsServer.c + * @version $Format:%h%d$ + * + * Sample DTLS server. + * Supports multiple simultaneous clients and non-blocking sockets + */ +/* + * Copyright (c) 2014-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ + +#include /* Defines SIGTERM, etc. */ +#ifdef OSX +#include /* Defines fd_set, etc. */ +#define MSG_NOSIGNAL 0 +#endif + +#include "dtlsCommon.h" +#include "../../crypto/cryptoApi.h" + + +/* #define USE_CERT_VALIDATOR */ + +#define DTLS_PORT 4433 +static int packet_loss_prob = 0; /* Reciprocal of packet loss probability + (i.e. P(packet loss) = 1/x). + Default value is 0 (no packet loss). */ +/* + Client management +*/ +#define MAX_CLIENTS 16 + +typedef struct { + psTime_t lastRecvTime; + uint32 timeout; /* in seconds */ + uint32 connStatus; + SOCKET fd; + struct sockaddr_in addr; + ssl_t *ssl; +} serverDtls_t; + +static serverDtls_t *clientTable; +static uint16 tableSize; + +#define RESUMED_HANDSHAKE_COMPLETE 1 + +/* Static Prototypes */ +static int32 initClientList(uint16 maxPeers); +static int32 handleResends(SOCKET sock); +static serverDtls_t *findClient(struct sockaddr_in addr); +static serverDtls_t *registerClient(struct sockaddr_in addr, SOCKET sock, + ssl_t *ssl); +static void clearClient(serverDtls_t *dtls); +static void closeClientList(); +static SOCKET newUdpSocket(char *ip, short port, int *err); +static int sigsetup(void); +static void sigsegv_handler(int); +static void sigintterm_handler(int); +static void usage(void); +static int32 process_cmd_options(int32 argc, char **argv); + +#ifdef USE_DTLS_DEBUG_TRACE +static unsigned char * getaddrstring(struct sockaddr *addr, int withport); +#endif + +#ifdef WIN32 +#pragma message("DO NOT USE THESE DEFAULT KEYS IN PRODUCTION ENVIRONMENTS.") +#else +#warning "DO NOT USE THESE DEFAULT KEYS IN PRODUCTION ENVIRONMENTS." +#endif + +/* Pick ONE cipher suite type you want to use to auto select a certificate + and private key identity that support those algorithms. + + In general, it works the other way: a server would obtain an identity + certificate and private key and then only enable cipher suites that the + material supports. +*/ +//#define ID_RSA /* Standard RSA suites. RSA Key Exchange and Authentication */ +//#define ID_DHE_RSA /* Diffie-Hellman key exchange. RSA Authentication */ +//#define ID_DH_ANON /* Diffie-Hellman key exchange. No auth */ +//#define ID_DHE_PSK /* Diffie-Hellman key exchange. Pre-Shared Key Auth */ +//#define ID_PSK /* Basic Pre-Shared Key suites */ +//#define ID_ECDH_ECDSA /* Elliptic Curve Key Exchange and Authentication */ +//#define ID_ECDHE_ECDSA /* Same as above with ephemeral Key Exchange */ +//#define ID_ECDHE_RSA /* Ephemeral EC Key Exchange, RSA Authentication */ +//#define ID_ECDH_RSA /* EC Key Exchange, RSA Authentication */ + +#ifdef ID_RSA +#ifndef USE_RSA +#error USE_RSA shall be defined for ID_RSA +#endif /* USE_RSA */ +#endif /* ID_RSA */ + +#ifdef ID_DHE_RSA +#if !defined(USE_DH) || !defined(USE_RSA) +#error USE_DH and USE_RSA shall be defined for ID_DHE_RSA +#endif /* USE_DH || USE_RSA */ +#endif /* ID_DHE_RSA */ + +#if defined(ID_DH_ANON) || defined(ID_DHE_PSK) +#ifndef USE_DH +#error USE_DH shall be defined for ID_DH_ANON and ID_DHE_PSK +#endif /* USE_DH */ +#endif /* ID_DH_ANON */ + +#if defined(ID_ECDH_ECDSA) || defined(ID_ECDHE_ECDSA) +#ifndef USE_ECC +#error USE_ECC shall be defined for ID_ECDH_ECDSA and ID_ECDHE_ECDSA +#endif /* USE_ECC */ +#endif /* ID_ECDH_ECDSA || ID_ECDHE_ECDSA */ + +#if defined(ID_ECDHE_RSA) || defined(ID_ECDH_RSA) +#if !defined(USE_ECC) || !defined(USE_RSA) +#error USE_ECC and USE_RSA shall be defined for ID_ECDHE_RSA and ID_ECDH_RSA +#endif /* USE_ECC || USE_RSA */ +#endif /* ID_ECDHE_RSA || ID_ECDH_RSA */ + + +#define ALLOW_ANON_CONNECTIONS 1 +#define USE_HEADER_KEYS + + +/* The keys that are loaded are compatible with the MatrixSSL sample client. + The CA files loaded assume the same authentication mechanism as the + cipher suite +*/ +#ifdef USE_HEADER_KEYS +/* Identity Key and Cert */ +#ifdef ID_RSA +#define EXAMPLE_RSA_KEYS +#include "testkeys/RSA/1024_RSA.h" +#include "testkeys/RSA/1024_RSA_KEY.h" +#include "testkeys/RSA/2048_RSA.h" +#include "testkeys/RSA/2048_RSA_KEY.h" +#include "testkeys/RSA/3072_RSA.h" +#include "testkeys/RSA/3072_RSA_KEY.h" +#include "testkeys/RSA/4096_RSA.h" +#include "testkeys/RSA/4096_RSA_KEY.h" +#endif + + +#if defined(ID_DHE_RSA) || defined(ID_ECDHE_RSA) +#define EXAMPLE_RSA_KEYS +#include "testkeys/RSA/1024_RSA.h" +#include "testkeys/RSA/1024_RSA_KEY.h" +#include "testkeys/RSA/2048_RSA.h" +#include "testkeys/RSA/2048_RSA_KEY.h" +#include "testkeys/RSA/3072_RSA.h" +#include "testkeys/RSA/3072_RSA_KEY.h" +#include "testkeys/RSA/4096_RSA.h" +#include "testkeys/RSA/4096_RSA_KEY.h" +#endif + +#if defined(ID_ECDHE_ECDSA) || defined(ID_ECDH_ECDSA) +#define EXAMPLE_EC_KEYS +#include "testkeys/EC/192_EC.h" +#include "testkeys/EC/192_EC_KEY.h" +#include "testkeys/EC/224_EC.h" +#include "testkeys/EC/224_EC_KEY.h" +#include "testkeys/EC/256_EC.h" +#include "testkeys/EC/256_EC_KEY.h" +#include "testkeys/EC/384_EC.h" +#include "testkeys/EC/384_EC_KEY.h" +#include "testkeys/EC/521_EC.h" +#include "testkeys/EC/521_EC_KEY.h" +#endif + +#ifdef ID_ECDH_RSA +#define EXAMPLE_ECDH_RSA_KEYS +#include "testkeys/ECDH_RSA/256_ECDH-RSA.h" +#include "testkeys/ECDH_RSA/256_ECDH-RSA_KEY.h" +#include "testkeys/ECDH_RSA/521_ECDH-RSA.h" +#include "testkeys/ECDH_RSA/521_ECDH-RSA_KEY.h" +#endif + +#ifdef REQUIRE_DH_PARAMS +#include "testkeys/DH/2048_DH_PARAMS.h" +#endif + + +/* CA files for client auth are selected more generously. If the algorithm + type is supported, we'll load it */ +#ifdef USE_RSA +#include "testkeys/RSA/ALL_RSA_CAS.h" +#ifdef USE_ECC +#include "testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS.h" +#endif /* USE_ECC */ +#endif /* USE_RSA */ +#ifdef USE_ECC + +#if defined(USE_SECP192R1) && defined(USE_SECP224R1) && defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS.h" +#endif /* USE_SECP192R1 && USE_SECP224R1 && USE_SECP521R1 */ + +#if !defined(USE_SECP192R1) && defined(USE_SECP224R1) && defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192.h" +#endif /* !USE_SECP192R1 && USE_SECP224R1 && USE_SECP521R1 */ + +#if defined(USE_SECP192R1) && !defined(USE_SECP224R1) && defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P224.h" +#endif /* USE_SECP192R1 && !USE_SECP224R1 && USE_SECP521R1 */ + +#if defined(USE_SECP192R1) && defined(USE_SECP224R1) && !defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P521.h" +#endif /* USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ + +#if !defined(USE_SECP192R1) && !defined(USE_SECP224R1) && defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P224.h" +#endif /* !USE_SECP192R1 && !USE_SECP224R1 && USE_SECP521R1 */ + +#if !defined(USE_SECP192R1) && defined(USE_SECP224R1) && !defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P521.h" +#endif /* !USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ + +#if defined(USE_SECP192R1) && !defined(USE_SECP224R1) && !defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P224_AND_P521.h" +#endif /* USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ + +#if !defined(USE_SECP192R1) && !defined(USE_SECP224R1) && !defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192_P224_AND_P521.h" +#endif /* !USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ + +#endif /* USE_ECC */ + + +/* File-based keys */ +#else +#ifdef ID_RSA +#define EXAMPLE_RSA_KEYS +static char rsaCertFile[] = "testkeys/RSA/2048_RSA.pem"; +static char rsaPrivkeyFile[] = "testkeys/RSA/2048_RSA_KEY.pem"; +#endif + + +#if defined(ID_DHE_RSA) || defined(ID_ECDHE_RSA) +#define EXAMPLE_RSA_KEYS +static char rsaCertFile[] = "testkeys/RSA/2048_RSA.pem"; +static char rsaPrivkeyFile[] = "testkeys/RSA/2048_RSA_KEY.pem"; +#endif + +#if defined(ID_ECDHE_ECDSA) || defined(ID_ECDH_ECDSA) +#define EXAMPLE_EC_KEYS +static char ecCertFile[] = "testkeys/EC/256_EC.pem"; +static char ecPrivkeyFile[] = "testkeys/EC/256_EC_KEY.pem"; +#endif + +#ifdef ID_ECDH_RSA +#define EXAMPLE_ECDH_RSA_KEYS +static char ecdhRsaCertFile[] = "testkeys/ECDH_RSA/256_ECDH-RSA.pem"; +static char ecdhRsaPrivkeyFile[] = "testkeys/ECDH_RSA/256_ECDH-RSA_KEY.pem"; +#endif + +#ifdef REQUIRE_DH_PARAMS +static char dhParamFile[] = "testkeys/DH/2048_DH_PARAMS.pem"; +#endif + + +/* CA files for client auth are selected more generously. If the algorithm + type is supported, we'll load it */ +#ifdef USE_RSA +static char rsaCAFile[] = "testkeys/RSA/ALL_RSA_CAS.pem"; +static char rsaCA3072File[] = "testkeys/RSA/3072_RSA_CA.pem"; +#ifdef USE_ECC +static char ecdhRsaCAFile[] = "testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS.pem"; +#endif /* USE_ECC */ +#endif /* USE_RSA */ +#ifdef USE_ECC + +#if defined(USE_SECP192R1) && defined(USE_SECP521R1) +static char ecCAFile[] = "testkeys/EC/ALL_EC_CAS.pem"; +#endif /* USE_SECP192R1 && USE_SECP521R1 */ + +#if !defined(USE_SECP192R1) && defined(USE_SECP521R1) +static char ecCAFile[] = "testkeys/EC/ALL_EC_CAS_EXCEPT_P192.pem"; +#endif /* USE_SECP192R1 && USE_SECP521R1 */ + +#if defined(USE_SECP192R1) && !defined(USE_SECP521R1) +static char ecCAFile[] = "testkeys/EC/ALL_EC_CAS_EXCEPT_P521.pem"; +#endif /* USE_SECP192R1 && USE_SECP521R1 */ + +#if !defined(USE_SECP192R1) && !defined(USE_SECP521R1) +static char ecCAFile[] = "testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P521.pem"; +#endif /* USE_SECP192R1 && USE_SECP521R1 */ + +#endif /* USE_ECC */ + +#endif /* USE_FILE_KEYS */ + + +#ifdef USE_PSK_CIPHER_SUITE +#include "testkeys/PSK/psk.h" +#endif /* PSK */ + + + +static int exitFlag; + +static uint32_t g_rsaKeySize; +static uint32_t g_eccKeySize; +static uint32_t g_ecdhKeySize; + +#ifdef USE_CERT_VALIDATOR +/******************************************************************************/ +/* + Stub for a user-level certificate validator. Just using + the default validation value here. + */ +static int32 certValidator(ssl_t *ssl, psX509Cert_t *cert, int32 alert) +{ + /* Example to allow anonymous connections based on a define */ + if (alert > 0) { + if (ALLOW_ANON_CONNECTIONS) { + /* Could be NULL if SERVER_WILL_ACCEPT_EMPTY_CLIENT_CERT_MSG */ + if (cert) { + _psTraceStr("Allowing anonymous connection for: %s.\n", + cert->subject.commonName); + } else { + _psTrace("Client didn't send certificate. Reverting to standard handshake due to SERVER_WILL_ACCEPT_EMPTY_CLIENT_CERT_MSG\n"); + } + return SSL_ALLOW_ANON_CONNECTION; + } + _psTrace("Certificate callback returning fatal alert\n"); + return alert; + } + _psTraceStr("Validated cert for: %s.\n", cert->subject.commonName); + return 0; +} +#else +/* No certificate validator is needed */ +#define certValidator NULL +#endif /* USE_CERT_VALIDATOR */ + +static void usage(void) +{ + printf("\nusage: dltsServer { option }\n" + "\n" + "where option can be one of the following:\n" + "\n" + "-h - Print usage and exit\n" + "-r - RSA keyLen (1024|2048|3072|4096)\n" + "-e - ECC keyLen (192|224|256|384|521)" + "-d - ECDH_RSA keyLen (256|521)\n" +#ifdef DTLS_PACKET_LOSS_TEST + "-l - Reciprocal of packet loss probability\n" + " (for packet loss simulation tests)\n" +#endif /* DTLS_PACKET_LOSS_TEST */ + ); +} + +/* Return 0 on good set of cmd options, return -1 if a bad cmd option is + encountered OR a request for help is seen (i.e. '-h' option). */ +static int32 process_cmd_options(int32 argc, char **argv) +{ + int32 optionChar; + + // Set some default options: + g_rsaKeySize = 2048; + g_eccKeySize = g_ecdhKeySize = 256; + + opterr = 0; + while ((optionChar = getopt(argc, argv, "hr:e:d:l:")) != -1) + { + switch (optionChar) { + case '?': + return -1; + + case 'h': + break; + + case 'r': + g_rsaKeySize = atoi(optarg); + if ((g_rsaKeySize != 1024) && (g_rsaKeySize != 2048) + && (g_rsaKeySize != 3072) && (g_rsaKeySize != 4096)) { + printf("invalid -r option\n"); + return -1; + } + break; + + case 'e': + g_eccKeySize = atoi(optarg); + if ((g_eccKeySize != 192) && (g_eccKeySize != 224) + && (g_eccKeySize != 256) && (g_eccKeySize != 384) + && (g_eccKeySize != 521)) { + printf("invalid -e option\n"); + return -1; + } + break; + + case 'd': + g_ecdhKeySize = atoi(optarg); + if ((g_ecdhKeySize != 256) && (g_ecdhKeySize != 521)) { + printf("invalid -d option\n"); + return -1; + } + break; + +#ifdef DTLS_PACKET_LOSS_TEST + case 'l': + packet_loss_prob = atoi(optarg); + if (packet_loss_prob < 0) { + printf("invalid -l option\n"); + return -1; + } + if (packet_loss_prob > 0) { + printf("Server simulating packet loss with probability 1/%d\n", + packet_loss_prob); + } + break; +#endif /* DTLS_PACKET_LOSS_TEST */ + } + } + + return 0; +} + +/******************************************************************************/ +/* + Main +*/ +int main(int argc, char ** argv) +{ + struct sockaddr_in inaddr; + socklen_t inaddrlen; + struct timeval timeout; + ssl_t *ssl; + serverDtls_t *dtlsCtx; + SOCKET sock; + fd_set readfd; + unsigned char *sslBuf, *recvfromBuf, *CAstream; +#ifdef USE_DTLS_DEBUG_TRACE + unsigned char *addrstr; +#endif +#if !defined(ID_PSK) && !defined(ID_DHE_PSK) + unsigned char *keyValue, *certValue; + int32 keyLen, certLen; +#endif + sslKeys_t *keys; + int32 freeBufLen, rc, val, recvLen, err, CAstreamLen; + int32 sslBufLen, rcr, rcs, sendLen, recvfromBufLen; + sslSessOpts_t options; + +#ifdef WIN32 + WSADATA wsaData; + WSAStartup(MAKEWORD(1, 1), &wsaData); +#endif + + rc = 0; + ssl = NULL; + dtlsCtx = NULL; + sock = INVALID_SOCKET; + + /* parse input arguments */ + if (0 != process_cmd_options(argc, argv)) { + usage(); + return 0; + } + + if (sigsetup() < 0) { + _psTrace("Init error creating signal handlers\n"); + return DTLS_FATAL; + } + + if (matrixSslOpen() < 0) { + _psTrace("Init error opening MatrixDTLS library\n"); + return DTLS_FATAL; + } + if (matrixSslNewKeys(&keys, NULL) < 0) { + _psTrace("Init error allocating key structure\n"); + matrixSslClose(); + return DTLS_FATAL; + } + + if ((rc = initClientList(MAX_CLIENTS)) < 0) { + _psTrace("Init error opening client list\n"); + goto MATRIX_EXIT; + } + + recvfromBufLen = matrixDtlsGetPmtu(); + if ((recvfromBuf = psMalloc(MATRIX_NO_POOL, recvfromBufLen)) == NULL) { + rc = PS_MEM_FAIL; + _psTrace("Init error allocating receive buffer\n"); + goto CLIENT_EXIT; + } + +#ifdef USE_HEADER_KEYS +/* + In-memory based keys + Build the CA list first for potential client auth usage +*/ + CAstreamLen = 0; +#ifdef USE_RSA + CAstreamLen += sizeof(RSACAS); +#ifdef USE_ECC + CAstreamLen += sizeof(ECDHRSACAS); +#endif +#endif +#ifdef USE_ECC + CAstreamLen += sizeof(ECCAS); +#endif + CAstream = psMalloc(NULL, CAstreamLen); + + CAstreamLen = 0; +#ifdef USE_RSA + memcpy(CAstream, RSACAS, sizeof(RSACAS)); + CAstreamLen += sizeof(RSACAS); +#ifdef USE_ECC + memcpy(CAstream + CAstreamLen, ECDHRSACAS, sizeof(ECDHRSACAS)); + CAstreamLen += sizeof(ECDHRSACAS); +#endif +#endif +#ifdef USE_ECC + memcpy(CAstream + CAstreamLen, ECCAS, sizeof(ECCAS)); + CAstreamLen += sizeof(ECCAS); +#endif + +#ifdef EXAMPLE_RSA_KEYS + switch (g_rsaKeySize) { + case 1024: + certValue = (unsigned char *)RSA1024; + certLen = sizeof(RSA1024); + keyValue = (unsigned char *)RSA1024KEY; + keyLen = sizeof(RSA1024KEY); + break; + case 2048: + certValue = (unsigned char *)RSA2048; + certLen = sizeof(RSA2048); + keyValue = (unsigned char *)RSA2048KEY; + keyLen = sizeof(RSA2048KEY); + break; + case 3072: + certValue = (unsigned char *)RSA3072; + certLen = sizeof(RSA3072); + keyValue = (unsigned char *)RSA3072KEY; + keyLen = sizeof(RSA3072KEY); + break; + case 4096: + certValue = (unsigned char *)RSA4096; + certLen = sizeof(RSA4096); + keyValue = (unsigned char *)RSA4096KEY; + keyLen = sizeof(RSA4096KEY); + break; + default: + _psTraceInt("Invalid RSA key length (%d)\n", g_rsaKeySize); + return -1; + } + + if ((rc = matrixSslLoadRsaKeysMem(keys, (const unsigned char *)certValue, + certLen, (const unsigned char *)keyValue, keyLen, CAstream, + CAstreamLen)) < 0) { + _psTrace("No certificate material loaded. Exiting\n"); + psFree(CAstream, NULL); + matrixSslDeleteKeys(keys); + matrixSslClose(); + return rc; + } +#endif + + +#ifdef EXAMPLE_ECDH_RSA_KEYS + switch (g_ecdhKeySize) { + case 256: + certValue = (unsigned char *)ECDHRSA256; + certLen = sizeof(ECDHRSA256); + keyValue = (unsigned char *)ECDHRSA256KEY; + keyLen = sizeof(ECDHRSA256KEY); + break; + case 521: + certValue = (unsigned char *)ECDHRSA521; + certLen = sizeof(ECDHRSA521); + keyValue = (unsigned char *)ECDHRSA521KEY; + keyLen = sizeof(ECDHRSA521KEY); + break; + default: + _psTraceInt("Invalid ECDH_RSA key length (%d)\n", g_ecdhKeySize); + return -1; + } + + if ((rc = matrixSslLoadEcKeysMem(keys, (const unsigned char *)certValue, + certLen, (const unsigned char *)keyValue, keyLen, CAstream, + CAstreamLen)) < 0) { + _psTrace("No certificate material loaded. Exiting\n"); + psFree(CAstream, NULL); + matrixSslDeleteKeys(keys); + matrixSslClose(); + return rc; + } +#endif + +#ifdef EXAMPLE_EC_KEYS + switch (g_eccKeySize) { + case 192: + certValue = (unsigned char *)EC192; + certLen = sizeof(EC192); + keyValue = (unsigned char *)EC192KEY; + keyLen = sizeof(EC192KEY); + break; + case 224: + certValue = (unsigned char *)EC224; + certLen = sizeof(EC224); + keyValue = (unsigned char *)EC224KEY; + keyLen = sizeof(EC224KEY); + break; + case 256: + certValue = (unsigned char *)EC256; + certLen = sizeof(EC256); + keyValue = (unsigned char *)EC256KEY; + keyLen = sizeof(EC256KEY); + break; + case 384: + certValue = (unsigned char *)EC384; + certLen = sizeof(EC384); + keyValue = (unsigned char *)EC384KEY; + keyLen = sizeof(EC384KEY); + break; + case 521: + certValue = (unsigned char *)EC521; + certLen = sizeof(EC521); + keyValue = (unsigned char *)EC521KEY; + keyLen = sizeof(EC521KEY); + break; + default: + _psTraceInt("Invalid ECC key length (%d)\n", g_eccKeySize); + return -1; + } + + if ((rc = matrixSslLoadEcKeysMem(keys, certValue, certLen, + keyValue, keyLen, CAstream, CAstreamLen)) < 0) { + _psTrace("No certificate material loaded. Exiting\n"); + psFree(CAstream, NULL); + matrixSslDeleteKeys(keys); + matrixSslClose(); + return rc; + } +#endif + +#ifdef REQUIRE_DH_PARAMS + if (matrixSslLoadDhParamsMem(keys, DHPARAM2048, DHPARAM2048_SIZE) + < 0) { + _psTrace("Unable to load DH parameters\n"); + } +#endif /* DH_PARAMS */ + + + psFree(CAstream, NULL); +#else /* USE_HEADER_KEYS */ +/* + File based keys + Build the CA list first for potential client auth usage +*/ + CAstreamLen = 0; +#ifdef USE_RSA + if (g_rsaKeySize == 3072) + CAstreamLen += (int32)strlen(rsaCA3072File) + 1; + else + CAstreamLen += (int32)strlen(rsaCAFile) + 1; +#ifdef USE_ECC + CAstreamLen += (int32)strlen(ecdhRsaCAFile) + 1; +#endif +#endif +#ifdef USE_ECC + CAstreamLen += (int32)strlen(ecCAFile) + 1; +#endif + CAstream = psMalloc(NULL, CAstreamLen); + memset(CAstream, 0x0, CAstreamLen); + + CAstreamLen = 0; +#ifdef USE_RSA + if (g_rsaKeySize == 3072) { + memcpy(CAstream, rsaCA3072File, strlen(rsaCA3072File)); + CAstreamLen += strlen(rsaCA3072File); + } + else { + memcpy(CAstream, rsaCAFile, strlen(rsaCAFile)); + CAstreamLen += strlen(rsaCAFile); + } +#ifdef USE_ECC + memcpy(CAstream + CAstreamLen, ";", 1); CAstreamLen++; + memcpy(CAstream + CAstreamLen, ecdhRsaCAFile, strlen(ecdhRsaCAFile)); + CAstreamLen += strlen(ecdhRsaCAFile); +#endif +#endif +#ifdef USE_ECC + if (CAstreamLen > 0) { + memcpy(CAstream + CAstreamLen, ";", 1); CAstreamLen++; + } + memcpy(CAstream + CAstreamLen, ecCAFile, strlen(ecCAFile)); +#endif + +/* Load Identiy */ +#ifdef EXAMPLE_RSA_KEYS + if ((rc = matrixSslLoadRsaKeys(keys, rsaCertFile, rsaPrivkeyFile, NULL, + (char*)CAstream)) < 0) { + _psTrace("No certificate material loaded. Exiting\n"); + psFree(CAstream); + matrixSslDeleteKeys(keys); + matrixSslClose(); + return rc; + } +#endif + + +#ifdef EXAMPLE_ECDH_RSA_KEYS + if ((rc = matrixSslLoadEcKeys(keys, ecdhRsaCertFile, ecdhRsaPrivkeyFile, + NULL, (char*)CAstream)) < 0) { + _psTrace("No certificate material loaded. Exiting\n"); + psFree(CAstream); + matrixSslDeleteKeys(keys); + matrixSslClose(); + return rc; + } +#endif + +#ifdef EXAMPLE_EC_KEYS + if ((rc = matrixSslLoadEcKeys(keys, ecCertFile, ecPrivkeyFile, NULL, + (char*)CAstream)) < 0) { + _psTrace("No certificate material loaded. Exiting\n"); + psFree(CAstream); + matrixSslDeleteKeys(keys); + matrixSslClose(); + return rc; + } +#endif + +#ifdef REQUIRE_DH_PARAMS + if (matrixSslLoadDhParams(keys, dhParamFile) < 0) { + _psTrace("Unable to load DH parameters\n"); + } +#endif + + + psFree(CAstream); +#endif /* USE_HEADER_KEYS */ + + +#ifdef USE_PSK_CIPHER_SUITE + /* The first ID is considered as null-terminiated string for + compatibility with OpenSSL's s_client default client identity + "Client_identity" */ + + matrixSslLoadPsk(keys, + PSK_HEADER_TABLE[0].key, + sizeof(PSK_HEADER_TABLE[0].key), + PSK_HEADER_TABLE[0].id, + strlen((const char *)PSK_HEADER_TABLE[0].id)); + + for (rc = 1; rc < PSK_HEADER_TABLE_COUNT; rc++) { + matrixSslLoadPsk(keys, + PSK_HEADER_TABLE[rc].key, + sizeof(PSK_HEADER_TABLE[rc].key), + PSK_HEADER_TABLE[rc].id, + sizeof(PSK_HEADER_TABLE[rc].id)); + } +#endif /* PSK */ + + + if ((sock = newUdpSocket(NULL, DTLS_PORT, &err)) == INVALID_SOCKET) { + _psTrace("Error creating UDP socket\n"); + goto DTLS_EXIT; + } + _psTraceInt("DTLS server running on port %d\n", DTLS_PORT); + +/* + Server loop +*/ + for (exitFlag = 0; exitFlag == 0;) { + timeout.tv_sec = 1; + timeout.tv_usec = 0; + FD_ZERO(&readfd); + FD_SET(sock, &readfd); +/* + Always just wait a second for any incoming data. The primary loop + mechanism reads data from one source and replies with handshake data + if needed (that reply may be a resend if reading a repeat message). + Individual client timeouts are then handled +*/ + val = select(sock+1, &readfd, NULL, NULL, &timeout); + + if (val > 0 && FD_ISSET(sock, &readfd)) { + psTraceIntDtls("Select woke %d\n", val); + /* recvfrom data must always go into generic buffer becuase we + don't yet know who it is from */ + inaddrlen = sizeof(struct sockaddr_in); + if ((recvLen = (int32)recvfrom(sock, recvfromBuf, recvfromBufLen, 0, + (struct sockaddr *)&inaddr, &inaddrlen)) < 0) { +#ifdef WIN32 + if (SOCKET_ERRNO != EWOULDBLOCK && + SOCKET_ERRNO != WSAECONNRESET) { +#else + if (SOCKET_ERRNO != EWOULDBLOCK) { +#endif + _psTraceInt("recvfrom error %d. Exiting\n", SOCKET_ERRNO); + goto DTLS_EXIT; + } + continue; + } +#ifdef USE_DTLS_DEBUG_TRACE + /* nice for debugging */ + { + const char *addrstr; + addrstr = getaddrstring((struct sockaddr *)&inaddr, 1); + psTraceIntDtls("Read %d bytes ", recvLen); + psTraceStrDtls("from %s\n", (char*)addrstr); + psFree(addrstr, NULL); + } +#endif + + /* Locate the SSL context of this receive and create a new session + if not found */ + if ((dtlsCtx = findClient(inaddr)) == NULL) { + memset(&options, 0x0, sizeof(sslSessOpts_t)); + options.versionFlag = SSL_FLAGS_DTLS; + options.truncHmac = -1; + + if (matrixSslNewServerSession(&ssl, keys, + certValidator, &options) < 0) { + rc = DTLS_FATAL; goto DTLS_EXIT; + } + if ((dtlsCtx = registerClient(inaddr, sock, ssl)) == NULL) { + /* Client list is full. Just have to ignore */ + matrixSslDeleteSession(ssl); + continue; + } + } + + ssl = dtlsCtx->ssl; + /* Move socket data into internal buffer */ + freeBufLen = matrixSslGetReadbuf(ssl, &sslBuf); + psAssert(freeBufLen >= recvLen); + psAssert(freeBufLen == matrixDtlsGetPmtu()); + memcpy(sslBuf, recvfromBuf, recvLen); + + /* Notify SSL state machine that we've received more data into the + ssl buffer retreived with matrixSslGetReadbuf. */ + if ((rcr = matrixSslReceivedData(ssl, recvLen, &sslBuf, + (uint32*)&freeBufLen)) < 0) { + clearClient(dtlsCtx); + continue; /* Next connection */ + } + /* Update last activity time and reset timeout*/ + psGetTime(&dtlsCtx->lastRecvTime, NULL); + dtlsCtx->timeout = MIN_WAIT_SECS; + +PROCESS_MORE_FROM_BUFFER: + /* Process any incoming plaintext application data */ + switch (rcr) { + case MATRIXSSL_HANDSHAKE_COMPLETE: + /* This is a resumed handshake case which means we are + the last to receive handshake flights and we know the + handshake is complete. However, the internal workings + will not flag us officially complete until we receive + application data from the peer so we need a local flag + to handle this case so we are not resending our final + flight */ + dtlsCtx->connStatus = RESUMED_HANDSHAKE_COMPLETE; + psTraceDtls("Got HANDSHAKE_COMPLETE out of ReceivedData\n"); + break; + case MATRIXSSL_APP_DATA: + /* Now safe to clear the connStatus flag that was keeping + track of the state between receiving the final flight of + a resumed handshake and receiving application data. The + reciept of app data has now internally disabled flight + resends */ + dtlsCtx->connStatus = 0; + _psTrace("Client connected. Received...\n"); + _psTraceStr("%s\n", (char*)sslBuf); + break; + case MATRIXSSL_REQUEST_SEND: + /* Still handshaking with this particular client */ + while ((sslBufLen = matrixDtlsGetOutdata(ssl, + &sslBuf)) > 0) { + if ((sendLen = udpSend(dtlsCtx->fd, sslBuf, sslBufLen, + (struct sockaddr*)&inaddr, + sizeof(struct sockaddr_in), + dtlsCtx->timeout, + packet_loss_prob, + NULL)) < 0) { + psTraceDtls("udpSend error. Ignoring\n"); + } + /* Always indicate the entire datagram was sent as + there is no way for DTLS to handle partial records. + Resends and timeouts will handle any problems */ + rcs = matrixDtlsSentData(ssl, sslBufLen); + + if (rcs == MATRIXSSL_REQUEST_CLOSE) { + psTraceDtls("Got REQUEST_CLOSE out of SentData\n"); + clearClient(dtlsCtx); + break; + } + if (rcs == MATRIXSSL_HANDSHAKE_COMPLETE) { + /* This is the standard handshake case */ + _psTrace("Got HANDSHAKE_COMPLETE from SentData\n"); + break; + } + /* SSL_REQUEST_SEND is handled by loop logic */ + } + break; + case MATRIXSSL_REQUEST_RECV: + psTraceDtls("Got REQUEST_RECV from ReceivedData\n"); + break; + case MATRIXSSL_RECEIVED_ALERT: + /* The first byte of the buffer is the level */ + /* The second byte is the description */ + if (*sslBuf == SSL_ALERT_LEVEL_FATAL) { + psTraceIntDtls("Fatal alert: %d, closing connection.\n", + *(sslBuf + 1)); + clearClient(dtlsCtx); + continue; /* Next connection */ + } + /* Closure alert is normal (and best) way to close */ + if (*(sslBuf + 1) == SSL_ALERT_CLOSE_NOTIFY) { + clearClient(dtlsCtx); + continue; /* Next connection */ + } + psTraceIntDtls("Warning alert: %d\n", *(sslBuf + 1)); + if ((rcr = matrixSslProcessedData(ssl, &sslBuf, + (uint32*)&freeBufLen)) == 0) { + continue; + } + goto PROCESS_MORE_FROM_BUFFER; + + default: + continue; /* Next connection */ + } + } else if (val < 0) { + if (SOCKET_ERRNO != EINTR) { + psTraceIntDtls("unhandled error %d from select", SOCKET_ERRNO); + } + } +/* + Have either timed out waiting for a read or have processed a single + recv. Now check to see if any timeout resends are required +*/ + rc = handleResends(sock); + } /* Main Select Loop */ + + +DTLS_EXIT: + psFree(recvfromBuf, NULL); +CLIENT_EXIT: + closeClientList(); +MATRIX_EXIT: + matrixSslDeleteKeys(keys); + matrixSslClose(); + if (sock != INVALID_SOCKET) close(sock); + return rc; +} + +/******************************************************************************/ +/* + Work through client list and resend handshake flight if haven't heard + from them in a while +*/ +static int32 handleResends(SOCKET sock) +{ + serverDtls_t *dtlsCtx; + ssl_t *ssl; + psTime_t now; + unsigned char *sslBuf; + int16 i; + int32 sendLen, rc; + uint32 timeout, sslBufLen, clientCount; + + clientCount = 0; /* return code is number of active clients or < 0 on error */ + psGetTime(&now, NULL); + for (i = 0; i < tableSize; i++) { + dtlsCtx = &clientTable[i]; + if (dtlsCtx->ssl != NULL) { + clientCount++; + timeout = psDiffMsecs(dtlsCtx->lastRecvTime, now, NULL) / 1000; + /* Haven't heard from this client in a while. Might need resend */ + if (timeout > dtlsCtx->timeout) { + /* if timeout is too great. clear conn */ + if (dtlsCtx->timeout >= MAX_WAIT_SECS) { + clearClient(dtlsCtx); + clientCount--; + break; + } + /* Increase the timeout for next pass */ + dtlsCtx->timeout *= 2; + + /* If we are in a RESUMED_HANDSHAKE_COMPLETE state that means + we are positive the handshake is complete so we don't want to + resend no matter what. This is an interim state before the + internal mechaism sees an application data record and flags + us as complete officially */ + if (dtlsCtx->connStatus == RESUMED_HANDSHAKE_COMPLETE) { + psTraceDtls("Connected but awaiting data\n"); + continue; + } + ssl = dtlsCtx->ssl; + while ((sslBufLen = matrixDtlsGetOutdata(ssl, + &sslBuf)) > 0) { + if ((sendLen = udpSend(dtlsCtx->fd, sslBuf, sslBufLen, + (struct sockaddr*)&dtlsCtx->addr, + sizeof(struct sockaddr_in), + dtlsCtx->timeout / 2, + packet_loss_prob, + NULL)) < 0) { + psTraceDtls("udpSend error. Ignoring\n"); + } + /* Always indicate the entire datagram was sent as + there is no way for DTLS to handle partial records. + Resends and timeouts will handle any problems */ + if ((rc = matrixDtlsSentData(ssl, sslBufLen)) < 0) { + psTraceDtls("internal error\n"); + clearClient(dtlsCtx); + clientCount--; + break; + } + if (rc == MATRIXSSL_REQUEST_CLOSE) { + psTraceDtls("Got REQUEST_CLOSE out of SentData\n"); + clearClient(dtlsCtx); + clientCount--; + break; + } + if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) { + /* This is the standard handshake case */ + psTraceDtls("Got HANDSHAKE_COMPLETE out of SentData\n"); + break; + } + /* SSL_REQUEST_SEND is handled by loop logic */ + } + + } + } + } + return clientCount; +} + +/******************************************************************************/ +/* + Make sure the socket is not inherited by exec'd processes + Set the REUSE flag to minimize the number of sockets in TIME_WAIT + Then we set REUSEADDR, NODELAY and NONBLOCK on the socket +*/ +static void setSocketOptions(SOCKET fd) +{ + int32 rc; + +#ifdef POSIX + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif + rc = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc)); +} + + +static SOCKET newUdpSocket(char *ip, short port, int *err) +{ + struct sockaddr_in addr; + SOCKET fd; + + if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + _psTraceInt("Error creating socket %d\n", SOCKET_ERRNO); + *err = SOCKET_ERRNO; + return INVALID_SOCKET; + } + + setSocketOptions(fd); + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + if (ip == NULL) { + addr.sin_addr.s_addr = INADDR_ANY; + if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + _psTrace("Can't bind socket. Port in use or permission problem\n"); + *err = SOCKET_ERRNO; + return INVALID_SOCKET; + } + } + return fd; +} + +/* catch any segvs */ +static void sigsegv_handler(int arg) +{ + _psTrace("Aiee, segfault! You should probably report " + "this as a bug to the developer\n"); + exit(EXIT_FAILURE); +} + +/* catch ctrl-c or sigterm */ +static void sigintterm_handler(int arg) +{ + exitFlag = 1; /* Rudimentary exit flagging */ +} + +static int sigsetup(void) +{ + /* set up cleanup handler */ + if (signal(SIGINT, sigintterm_handler) == SIG_ERR || +#ifndef DEBUG_VALGRIND + signal(SIGTERM, sigintterm_handler) == SIG_ERR || +#endif + signal(SIGPIPE, SIG_IGN) == SIG_ERR) { + return -1; + } + if (signal(SIGSEGV, sigsegv_handler) == SIG_ERR) { + return -1; + } + + return 0; +} + +#ifdef USE_DTLS_DEBUG_TRACE +/******************************************************************************/ +/* Return a string representation of the socket address passed. The return + * value is allocated with malloc() */ +static unsigned char * getaddrstring(struct sockaddr *addr, + int withport) { + + char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; + char *retstring = NULL; + int ret; + unsigned int len; + + len = sizeof(struct sockaddr_storage); + /* Some platforms such as Solaris 8 require that len is the length + * of the specific structure. Some older linux systems (glibc 2.1.3 + * such as debian potato) have sockaddr_storage.__ss_family instead + * but we'll ignore them */ +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY + if (addr->ss_family == AF_INET) { + len = sizeof(struct sockaddr_in); + } +#ifdef AF_INET6 + if (addr->ss_family == AF_INET6) { + len = sizeof(struct sockaddr_in6); + } +#endif +#endif + + ret = getnameinfo((struct sockaddr*)addr, len, hbuf, sizeof(hbuf), + sbuf, sizeof(sbuf), NI_NUMERICSERV | NI_NUMERICHOST); + + if (ret != 0) { + /* This is a fairly bad failure - it'll fallback to IP if it + * just can't resolve */ + _psTrace("failed lookup for getaddrstring"); + strcpy(hbuf, "UNKNOWN"); + strcpy(sbuf, "?"); + } + + if (withport) { + len = strlen(hbuf) + 2 + strlen(sbuf); + retstring = (char*)psMalloc(MATRIX_NO_POOL, len); + snprintf(retstring, len, "%s:%s", hbuf, sbuf); + } else { + retstring = strdup(hbuf); + } + + return (unsigned char *)retstring; +} +#endif /* USE_DTLS_DEBUG_TRACE */ + +/******************************************************************************/ +/* + Client management +*/ +/******************************************************************************/ +static int32 initClientList(uint16 maxPeers) +{ + clientTable = psCalloc(NULL, maxPeers, sizeof(serverDtls_t)); + if (clientTable == NULL) { + return PS_MEM_FAIL; + } + tableSize = maxPeers; + + udpInitProxy(); + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Associates a new sockaddr with an existing ssl context and returns context + */ +serverDtls_t *registerClient(struct sockaddr_in addr, SOCKET sock, + ssl_t *ssl) +{ + int16 i; + serverDtls_t *dtlsCtx; + + for (i = 0; i < tableSize && clientTable[i].ssl != NULL && + (clientTable[i].addr.sin_addr.s_addr != addr.sin_addr.s_addr || + clientTable[i].addr.sin_port != addr.sin_port); i++); + if (i >= tableSize) { + /* no available slots */ + return NULL; + } + + dtlsCtx = &clientTable[i]; + + dtlsCtx->addr = addr; + dtlsCtx->fd = sock; + dtlsCtx->timeout = MIN_WAIT_SECS; + dtlsCtx->connStatus = 0; + psGetTime(&dtlsCtx->lastRecvTime, NULL); + dtlsCtx->ssl = ssl; + return dtlsCtx; +} + +static void clearClient(serverDtls_t *dtls) +{ + ssl_t *ssl; + unsigned char *buf; + int32 len; + + ssl = dtls->ssl; + + /* Quick attempt to send a closure alert, don't worry about failure */ + if (matrixSslEncodeClosureAlert(ssl) >= 0) { + if ((len = matrixDtlsGetOutdata(ssl, &buf)) > 0) { + sendto(dtls->fd, buf, len, 0, (struct sockaddr*)&dtls->addr, + sizeof(struct sockaddr_in)); + matrixDtlsSentData(ssl, len); + } + } + matrixSslDeleteSession(ssl); + +/* + Free up the entry in the client table +*/ + dtls->ssl = NULL; + dtls->connStatus = 0; + dtls->fd = 0; + memset(&dtls->addr, 0x0, sizeof(struct sockaddr_in)); + return; +} + +/******************************************************************************/ +/* + Return the ssl_t given the sockaddr or NULL if doesn't exist +*/ +serverDtls_t *findClient(struct sockaddr_in addr) +{ + int i; + + for (i = 0; i < tableSize; i++) { + if (clientTable[i].ssl != NULL) { + if (clientTable[i].addr.sin_addr.s_addr == addr.sin_addr.s_addr && + clientTable[i].addr.sin_port == addr.sin_port) { + return &clientTable[i]; + } + } + } + return NULL; +} + +static void closeClientList() +{ + int i; + /* Free any leftover clients */ + for (i = 0; i < tableSize && clientTable[i].ssl != NULL; i++) { + matrixSslDeleteSession(clientTable[i].ssl); + } + psFree(clientTable, NULL); + tableSize = 0; +} diff --git a/apps/dtls/runClient.sh b/apps/dtls/runClient.sh new file mode 100755 index 0000000..bab1bd4 --- /dev/null +++ b/apps/dtls/runClient.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +# Some cipher suites +CIPHER_SUITE="47" #AES128-SHA +#CIPHER_SUITE="5" #RC4128-SHA +#CIPHER_SUITE="4" #RC4128-MD5 +#CIPHER_SUITE="60" #AES128-SHA256 +#CIPHER_SUITE="10" #DES-CBC3-SHA +#CIPHER_SUITE="141" #PSK_AES256-SHA +#CIPHER_SUITE="49156" #ECDH_ECDSA-AES128-SHA +#CIPHER_SUITE="49162" #ECDHE_ECDSA-AES256-SHA +#CIPHER_SUITE="1567" #RSA AES128-GCM-SHA256 +#CIPHER_SUITE="57" #DHE_RSA AES256-SHA +#CIPHER_SUITE="49195" #ECDHE_ECDSA-AES128-GCM-SHA256 +#CIPHER_SUITE="49196" #ECDHE_ECDSA-AES256-GCM-SHA384 + +IPADDR="127.0.0.1" +PORT="4433" +NEW_SESSIONS="1" +RESUMED_SESSIONS="0" + +./dtlsClient -s${IPADDR} -p${PORT} -n${NEW_SESSIONS} -r${RESUMED_SESSIONS} -c${CIPHER_SUITE} -d diff --git a/apps/ssl/Makefile b/apps/ssl/Makefile new file mode 100755 index 0000000..cfbf048 --- /dev/null +++ b/apps/ssl/Makefile @@ -0,0 +1,46 @@ +# +# Makefile for MatrixSSL example apps +# 'make' builds debug (Default). +# 'make gold' builds optimized. +# +# Copyright (c) 2013-2016 INSIDE Secure Corporation. All Rights Reserved. +# + +MATRIXSSL_ROOT:=../.. +SERVER_SRC:=server.c http.c +CLIENT_SRC:=client.c http.c + +SRC:=$(SERVER_SRC) $(CLIENT_SRC) + +include $(MATRIXSSL_ROOT)/common.mk + +# Generated files +SERVER_EXE:=server$(E) +CLIENT_EXE:=client$(E) + +# Linked files +STATIC:=\ + $(MATRIXSSL_ROOT)/matrixssl/libssl_s.a \ + $(MATRIXSSL_ROOT)/crypto/libcrypt_s.a \ + $(MATRIXSSL_ROOT)/core/libcore_s.a + + +CIPHER_OPTION=ID_RSA # The default cipher option +CFLAGS+=-D$(CIPHER_OPTION) + +all: compile + +compile: $(OBJS) $(SERVER_EXE) $(CLIENT_EXE) + +# Additional Dependencies +$(OBJS): $(MATRIXSSL_ROOT)/common.mk Makefile $(wildcard *.h) + +$(SERVER_EXE): $(SERVER_SRC:.c=.o) $(STATIC) + $(CC) -o $@ $^ $(LDFLAGS) $(CFLAGS) + +$(CLIENT_EXE): $(CLIENT_SRC:.c=.o) $(STATIC) + $(CC) -o $@ $^ $(LDFLAGS) $(CFLAGS) + +clean: + rm -f $(SERVER_EXE) $(CLIENT_EXE) $(OBJS) TLS_*.tmp SSL_*.tmp + diff --git a/apps/ssl/XGetopt.c b/apps/ssl/XGetopt.c new file mode 100755 index 0000000..081d139 --- /dev/null +++ b/apps/ssl/XGetopt.c @@ -0,0 +1,210 @@ +// XGetopt.cpp Version 1.2 +// +// Author: Hans Dietrich +// hdietrich2@hotmail.com +// +// Description: +// XGetopt.cpp implements getopt(), a function to parse command lines. +// +// History +// Version 1.2 - 2003 May 17 +// - Added Unicode support +// +// Version 1.1 - 2002 March 10 +// - Added example to XGetopt.cpp module header +// +// This software is released into the public domain. +// You are free to use it in any way you like. +// +// This software is provided "as is" with no expressed +// or implied warranty. I accept no liability for any +// damage or loss of business that this software may cause. +// +/////////////////////////////////////////////////////////////////////////////// +#include "app.h" + +#ifdef WIN32 +#include "XGetopt.h" + +/////////////////////////////////////////////////////////////////////////////// +// +// X G e t o p t . c p p +// +// +// NAME +// getopt -- parse command line options +// +// SYNOPSIS +// int getopt(int argc, TCHAR *argv[], TCHAR *optstring) +// +// extern TCHAR *optarg; +// extern int optind; +// +// DESCRIPTION +// The getopt() function parses the command line arguments. Its +// arguments argc and argv are the argument count and array as +// passed into the application on program invocation. In the case +// of Visual C++ programs, argc and argv are available via the +// variables __argc and __argv (double underscores), respectively. +// getopt returns the next option letter in argv that matches a +// letter in optstring. (Note: Unicode programs should use +// __targv instead of __argv. Also, all character and string +// literals should be enclosed in _T( ) ). +// +// optstring is a string of recognized option letters; if a letter +// is followed by a colon, the option is expected to have an argument +// that may or may not be separated from it by white space. optarg +// is set to point to the start of the option argument on return from +// getopt. +// +// Option letters may be combined, e.g., "-ab" is equivalent to +// "-a -b". Option letters are case sensitive. +// +// getopt places in the external variable optind the argv index +// of the next argument to be processed. optind is initialized +// to 0 before the first call to getopt. +// +// When all options have been processed (i.e., up to the first +// non-option argument), getopt returns EOF, optarg will point +// to the argument, and optind will be set to the argv index of +// the argument. If there are no non-option arguments, optarg +// will be set to NULL. +// +// The special option "--" may be used to delimit the end of the +// options; EOF will be returned, and "--" (and everything after it) +// will be skipped. +// +// RETURN VALUE +// For option letters contained in the string optstring, getopt +// will return the option letter. getopt returns a question mark (?) +// when it encounters an option letter not included in optstring. +// EOF is returned when processing is finished. +// +// BUGS +// 1) Long options are not supported. +// 2) The GNU double-colon extension is not supported. +// 3) The environment variable POSIXLY_CORRECT is not supported. +// 4) The + syntax is not supported. +// 5) The automatic permutation of arguments is not supported. +// 6) This implementation of getopt() returns EOF if an error is +// encountered, instead of -1 as the latest standard requires. +// +// EXAMPLE +// BOOL CMyApp::ProcessCommandLine(int argc, TCHAR *argv[]) +// { +// int c; +// +// while ((c = getopt(argc, argv, _T("aBn:"))) != EOF) +// { +// switch (c) +// { +// case _T('a'): +// TRACE(_T("option a\n")); +// // +// // set some flag here +// // +// break; +// +// case _T('B'): +// TRACE( _T("option B\n")); +// // +// // set some other flag here +// // +// break; +// +// case _T('n'): +// TRACE(_T("option n: value=%d\n"), atoi(optarg)); +// // +// // do something with value here +// // +// break; +// +// case _T('?'): +// TRACE(_T("ERROR: illegal option %s\n"), argv[optind-1]); +// return FALSE; +// break; +// +// default: +// TRACE(_T("WARNING: no handler for option %c\n"), c); +// return FALSE; +// break; +// } +// } +// // +// // check for non-option args here +// // +// return TRUE; +// } +// +/////////////////////////////////////////////////////////////////////////////// + +char *optarg; // global argument pointer +int optind = 0; // global argv index +int opterr = 0; + +int getopt(int argc, char *argv[], char *optstring) +{ + static char *next = NULL; + char c; + char *cp; + if (optind == 0) + next = NULL; + + optarg = NULL; + + if (next == NULL || *next == '\0') + { + if (optind == 0) + optind++; + + if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0') + { + optarg = NULL; + if (optind < argc) + optarg = argv[optind]; + return EOF; + } + + if (strcmp(argv[optind], "--") == 0) + { + optind++; + optarg = NULL; + if (optind < argc) + optarg = argv[optind]; + return EOF; + } + + next = argv[optind]; + next++; // skip past - + optind++; + } + + c = *next++; + cp = strchr(optstring, c); + + if (cp == NULL || c == ':') + return '?'; + + cp++; + if (*cp == ':') + { + if (*next != '\0') + { + optarg = next; + next = NULL; + } + else if (optind < argc) + { + optarg = argv[optind]; + optind++; + } + else + { + return '?'; + } + } + + return c; +} + +#endif /* WIN32 */ diff --git a/apps/ssl/XGetopt.h b/apps/ssl/XGetopt.h new file mode 100755 index 0000000..db6ea60 --- /dev/null +++ b/apps/ssl/XGetopt.h @@ -0,0 +1,26 @@ +// XGetopt.h Version 1.2 +// +// Author: Hans Dietrich +// hdietrich2@hotmail.com +// +// This software is released into the public domain. +// You are free to use it in any way you like. +// +// This software is provided "as is" with no expressed +// or implied warranty. I accept no liability for any +// damage or loss of business that this software may cause. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef XGETOPT_H +#define XGETOPT_H + +#include +#include + +extern int optind, opterr; +extern char *optarg; + +int getopt(int argc, char *argv[], char *optstring); + +#endif //XGETOPT_H diff --git a/apps/ssl/app.h b/apps/ssl/app.h new file mode 100644 index 0000000..9dd4a4c --- /dev/null +++ b/apps/ssl/app.h @@ -0,0 +1,130 @@ +/** + * @file app.h + * @version $Format:%h%d$ + * + * Header for MatrixSSL example sockets client and server applications. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_MATRIXSSLAPP +#define _h_MATRIXSSLAPP + +#ifdef __cplusplus +extern "C" { +#endif +/******************************************************************************/ + +#include "core/coreApi.h" +#include "matrixssl/matrixsslApi.h" + +#include /* Defines EWOULDBLOCK, etc. */ +#include /* Defines FD_CLOEXEC, etc. */ +#include /* Defines malloc, exit, etc. */ + +#ifdef POSIX +#include /* Defines AF_INET, etc. */ +#include /* Defines close() */ +#include /* Defines TCP_NODELAY, etc. */ +#include /* inet_addr */ +#endif + +#ifdef WIN32 +#define SIGPIPE SIGABRT +#define snprintf _snprintf +#define close closesocket +#define MSG_DONTWAIT 0 +#ifndef EWOULDBLOCK +#define EWOULDBLOCK WSAEWOULDBLOCK +#endif +#ifndef EINPROGRESS +#define EINPROGRESS WSAEINPROGRESS +#endif +#endif /* WIN32 */ + + +/******************************************************************************/ +/* + Platform independent socket defines for convenience + */ +#ifndef INVALID_SOCKET + #define INVALID_SOCKET (-1) + typedef int32 SOCKET; +#endif + +#ifdef WIN32 + #define SOCKET_ERRNO WSAGetLastError() +#else + #define SOCKET_ERRNO errno +#endif + +/******************************************************************************/ +/* + Configuration Options +*/ +#define HTTPS_PORT 4433 /* Port to run the server/client on */ + +/******************************************************************************/ +/* + Protocol specific defines + */ +/* Maximum size of parseable http element. In this case, a HTTP header line. */ +#define HTTPS_BUFFER_MAX 256 + +/* Return codes from http parsing routine */ +#define HTTPS_COMPLETE 1 /* Full request/response parsed */ +#define HTTPS_PARTIAL 0 /* Only a partial request/response was received */ +#define HTTPS_ERROR MATRIXSSL_ERROR /* Invalid/unsupported HTTP syntax */ + +typedef struct { + DLListEntry List; + ssl_t *ssl; + SOCKET fd; + psTime_t time; /* Last time there was activity */ + uint32 timeout; /* in milliseconds*/ + uint32 flags; + unsigned char *parsebuf; /* Partial data */ + uint32 parsebuflen; + uint32 bytes_received; + uint32 bytes_requested; + uint32 bytes_sent; + psPool_t *bufPool; /* Mem pool to allocate inbuf and outbuf */ +} httpConn_t; + +extern int32 httpBasicParse(httpConn_t *cp, unsigned char *buf, uint32 len, + int32 trace); + +/******************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* _h_MATRIXSSLAPP */ + +/******************************************************************************/ diff --git a/apps/ssl/client.c b/apps/ssl/client.c new file mode 100644 index 0000000..bbb6a25 --- /dev/null +++ b/apps/ssl/client.c @@ -0,0 +1,1569 @@ +/** + * @file client.c + * @version $Format:%h%d$ + * + * Simple MatrixSSL blocking client example. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include +#include +#include +#include +#include "app.h" +#ifndef WIN32 +#include +#else +#include "XGetopt.h" +#endif +#include "matrixssl/matrixsslApi.h" + +#ifdef USE_CLIENT_SIDE_SSL + +#ifdef WIN32 +#pragma message("DO NOT USE THESE DEFAULT KEYS IN PRODUCTION ENVIRONMENTS.") +#else +#warning "DO NOT USE THESE DEFAULT KEYS IN PRODUCTION ENVIRONMENTS." +#endif + +/* + If supporting client authentication, pick ONE identity to auto select a + certificate and private key that support desired algorithms. +*/ +//#define ID_RSA /* RSA Certificate and Key */ +//#define ID_ECDH_ECDSA /* EC Certificate and Key */ +//#define ID_ECDH_RSA /* EC Key with RSA signed certificate */ + +#define USE_HEADER_KEYS +#define ALLOW_ANON_CONNECTIONS 1 + +/* If the algorithm type is supported, load a CA for it */ +#ifdef USE_HEADER_KEYS +/* CAs */ +#ifdef USE_RSA_CIPHER_SUITE +#include "testkeys/RSA/ALL_RSA_CAS.h" +#ifdef USE_ECC_CIPHER_SUITE +#include "testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS.h" +#endif +#endif + +#ifdef USE_ECC_CIPHER_SUITE + +#if defined(USE_SECP192R1) && defined(USE_SECP224R1) && defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS.h" +#endif /* USE_SECP192R1 && USE_SECP224R1 && USE_SECP521R1 */ + +#if !defined(USE_SECP192R1) && defined(USE_SECP224R1) && defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192.h" +#endif /* !USE_SECP192R1 && USE_SECP224R1 && USE_SECP521R1 */ + +#if defined(USE_SECP192R1) && !defined(USE_SECP224R1) && defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P224.h" +#endif /* USE_SECP192R1 && !USE_SECP224R1 && USE_SECP521R1 */ + +#if defined(USE_SECP192R1) && defined(USE_SECP224R1) && !defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P521.h" +#endif /* USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ + +#if !defined(USE_SECP192R1) && !defined(USE_SECP224R1) && defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P224.h" +#endif /* !USE_SECP192R1 && !USE_SECP224R1 && USE_SECP521R1 */ + +#if !defined(USE_SECP192R1) && defined(USE_SECP224R1) && !defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P521.h" +#endif /* !USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ + +#if defined(USE_SECP192R1) && !defined(USE_SECP224R1) && !defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P224_AND_P521.h" +#endif /* USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ + +#if !defined(USE_SECP192R1) && !defined(USE_SECP224R1) && !defined(USE_SECP521R1) +#include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192_P224_AND_P521.h" +#endif /* !USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ + +#endif /* USE_ECC_CIPHER_SUITE */ + +/* Identity Certs and Keys for use with Client Authentication */ +#ifdef ID_RSA +#define EXAMPLE_RSA_KEYS +#include "testkeys/RSA/1024_RSA.h" +#include "testkeys/RSA/1024_RSA_KEY.h" +#include "testkeys/RSA/2048_RSA.h" +#include "testkeys/RSA/2048_RSA_KEY.h" +#include "testkeys/RSA/4096_RSA.h" +#include "testkeys/RSA/4096_RSA_KEY.h" +#endif + +#ifdef ID_ECDH_ECDSA +#define EXAMPLE_EC_KEYS +#include "testkeys/EC/384_EC.h" +#include "testkeys/EC/384_EC_KEY.h" +#endif + +#ifdef ID_ECDH_RSA +#define EXAMPLE_ECDH_RSA_KEYS +#include "testkeys/ECDH_RSA/521_ECDH-RSA.h" +#include "testkeys/ECDH_RSA/521_ECDH-RSA_KEY.h" +#endif + +/* File-based keys */ +#else +/* CAs */ +#ifdef USE_RSA_CIPHER_SUITE +static char rsaCAFile[] = "../../testkeys/RSA/ALL_RSA_CAS.pem"; +#ifdef USE_ECC_CIPHER_SUITE +static char ecdhRsaCAFile[] = "../../testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS.pem"; +#endif +#endif + +#ifdef USE_ECC_CIPHER_SUITE +#if defined(USE_SECP192R1) && defined(USE_SECP521R1) +static char ecCAFile[] = "../../testkeys/EC/ALL_EC_CAS.pem"; +#endif /* USE_SECP192R1 && USE_SECP521R1 */ + +#if !defined(USE_SECP192R1) && defined(USE_SECP521R1) +static char ecCAFile[] = "../../testkeys/EC/ALL_EC_CAS_EXCEPT_P192.pem"; +#endif /* USE_SECP192R1 && USE_SECP521R1 */ + +#if defined(USE_SECP192R1) && !defined(USE_SECP521R1) +static char ecCAFile[] = "../../testkeys/EC/ALL_EC_CAS_EXCEPT_P521.pem"; +#endif /* USE_SECP192R1 && USE_SECP521R1 */ + +#if !defined(USE_SECP192R1) && !defined(USE_SECP521R1) +static char ecCAFile[] = "../../testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P521.pem"; +#endif /* USE_SECP192R1 && USE_SECP521R1 */ + +#endif /* USE_ECC_CIPHER_SUITE */ + +/* Identity Certs and Keys for use with Client Authentication */ +#ifdef ID_RSA +#define EXAMPLE_RSA_KEYS +static char rsaCertFile[] = "../../testkeys/RSA/2048_RSA.pem"; +static char rsaPrivkeyFile[] = "../../testkeys/RSA/2048_RSA_KEY.pem"; +#endif + +#ifdef ID_ECDH_ECDSA +#define EXAMPLE_EC_KEYS +static char ecCertFile[] = "../../testkeys/EC/521_EC.pem"; +static char ecPrivkeyFile[] = "../../testkeys/EC/521_EC_KEY.pem"; +#endif + +#ifdef ID_ECDH_RSA +#define EXAMPLE_ECDH_RSA_KEYS +static char ecdhRsaCertFile[] = "../../testkeys/ECDH_RSA/521_ECDH-RSA.pem"; +static char ecdhRsaPrivkeyFile[] = "../../testkeys/ECDH_RSA/521_ECDH-RSA_KEY.pem"; +#endif + +#endif /* USE_HEADER_KEYS */ + +#ifdef USE_PSK_CIPHER_SUITE +/* Defines PSK_HEADER_TABLE and PSK_HEADER_TABLE_COUNT */ +#include "../../testkeys/PSK/psk.h" +#endif + +//#define REHANDSHAKE_TEST +#ifdef REHANDSHAKE_TEST +static int g_rehandshakeFlag = 0; +#endif + +/********************************** Globals ***********************************/ +static unsigned char g_httpRequestHdr[] = "GET %s HTTP/1.0\r\n" + "User-Agent: MatrixSSL/" MATRIXSSL_VERSION "\r\n" + "Accept: */*\r\n" + "Content-Length: 0\r\n" + "\r\n"; + +static const char g_strver[][8] = + { "SSL 3.0", "TLS 1.0", "TLS 1.1", "TLS 1.2" }; + +static unsigned char g_matrixShutdownServer[] = "MATRIX_SHUTDOWN"; + +extern int opterr; +static char g_ip[16]; +static char g_path[256]; +static int g_port, g_new, g_resumed, g_ciphers, g_version, g_closeServer; +static int g_key_len, g_disableCertNameChk; +static uint16_t g_cipher[16]; +static int g_trace; +static int g_keepalive; + +static uint32_t g_bytes_requested; +static uint8_t g_send_closure_alert; + +struct g_sslstats { + int rbytes; /* Bytes read */ + int64 hstime; + int64 datatime; +}; + +/********************************** Defines ***********************************/ + +/****************************** Local Functions *******************************/ + +static int32 httpWriteRequest(ssl_t *ssl); +static int32 certCb(ssl_t *ssl, psX509Cert_t *cert, int32 alert); +static SOCKET lsocketConnect(char *ip, int32 port, int32 *err); +static void closeConn(ssl_t *ssl, SOCKET fd); +static int32_t extensionCb(ssl_t *ssl, + uint16_t extType, uint8_t extLen, void *e); + +#ifdef USE_CRL +static int32 crlCb(psPool_t *pool, psX509Cert_t *CA, int append, + char *url, uint32 urlLen); +#endif + + +/******************************************************************************/ +/* + Make a secure HTTP request to a defined IP and port + Connection is made in blocking socket mode + The connection is considered successful if the SSL/TLS session is + negotiated successfully, a request is sent, and a HTTP response is received. + */ + +static int g_alreadyopen = 0; + +static int32 httpsClientConnection(sslKeys_t *keys, sslSessionId_t *sid, + struct g_sslstats *stats) +{ + tlsExtension_t *extension; + int32 rc, transferred, len, sessionFlag, extLen; + ssl_t *ssl; + unsigned char *buf, *ext; + httpConn_t cp; + SOCKET fd; + psTime_t t1, t2; + sslSessOpts_t options; +#ifdef USE_ALPN + unsigned char *alpn[MAX_PROTO_EXT]; + int32 alpnLen[MAX_PROTO_EXT]; +#endif + + memset(&cp, 0x0, sizeof(httpConn_t)); + if (g_alreadyopen == 0) { + fd = lsocketConnect(g_ip, g_port, &rc); + if (g_keepalive == 1) { + g_alreadyopen = fd; + } + } else { + fd = g_alreadyopen; + rc = PS_SUCCESS; + } + if (fd == INVALID_SOCKET || rc != PS_SUCCESS) { + return PS_PLATFORM_FAIL; + } + +#ifdef SSL_FLAGS_SSLV3 + /* Corresponds to version 3.g_version */ + switch (g_version) { + case 0: + sessionFlag = SSL_FLAGS_SSLV3; + break; + case 1: + sessionFlag = SSL_FLAGS_TLS_1_0; + break; + case 2: + sessionFlag = SSL_FLAGS_TLS_1_1; + break; + case 3: + sessionFlag = SSL_FLAGS_TLS_1_2; + break; + default: + sessionFlag = SSL_FLAGS_TLS_1_0; + break; + } +#else + /* MatrixSSL <= 3.4.2 don't support setting version on request */ + sessionFlag = 0; +#endif + + memset(&options, 0x0, sizeof(sslSessOpts_t)); + options.versionFlag = sessionFlag; + options.userPtr = keys; + //options.maxFragLen = 512; + //options.truncHmac = PS_TRUE; + //options.ticketResumption = PS_TRUE; + //options.ecFlags |= SSL_OPT_SECP521R1; + //options.ecFlags |= SSL_OPT_SECP384R1; + //options.ecFlags |= SSL_OPT_SECP256R1; + //options.ecFlags |= SSL_OPT_SECP224R1; + //options.ecFlags |= SSL_OPT_SECP192R1; + + matrixSslNewHelloExtension(&extension, NULL); + matrixSslCreateSNIext(NULL, (unsigned char*)g_ip, (uint32)strlen(g_ip), + &ext, &extLen); + matrixSslLoadHelloExtension(extension, ext, extLen, EXT_SNI); + psFree(ext, NULL); + +#ifdef USE_ALPN + /* Application Layer Protocol Negotiation */ + alpn[0] = psMalloc(NULL, strlen("http/1.0")); + memcpy(alpn[0], "http/1.0", strlen("http/1.0")); + alpnLen[0] = strlen("http/1.0"); + + alpn[1] = psMalloc(NULL, strlen("http/1.1")); + memcpy(alpn[1], "http/1.1", strlen("http/1.1")); + alpnLen[1] = strlen("http/1.1"); + + matrixSslCreateALPNext(NULL, 2, alpn, alpnLen, &ext, &extLen); + matrixSslLoadHelloExtension(extension, ext, extLen, EXT_ALPN); + psFree(alpn[0], NULL); + psFree(alpn[1], NULL); +#endif + + /* We are passing the IP address of the server as the expected name */ + /* To skip certificate subject name tests, pass NULL instead of g_ip */ + if (g_disableCertNameChk == 0) { + rc = matrixSslNewClientSession(&ssl, keys, sid, g_cipher, g_ciphers, + certCb, g_ip, extension, extensionCb, &options); + + + } else { + rc = matrixSslNewClientSession(&ssl, keys, sid, g_cipher, g_ciphers, + certCb, NULL, extension, extensionCb, &options); + } + + matrixSslDeleteHelloExtension(extension); + if (rc != MATRIXSSL_REQUEST_SEND) { + _psTraceInt("New Client Session Failed: %d. Exiting\n", rc); + close(fd); + return PS_ARG_FAIL; + } +WRITE_MORE: + while ((len = matrixSslGetOutdata(ssl, &buf)) > 0) { + if (g_trace) psTraceBytes("SEND", buf, len); + transferred = send(fd, buf, len, 0); + if (transferred <= 0) { + printf("Error sending\n"); + goto L_CLOSE_ERR; + } else { + /* Indicate that we've written > 0 bytes of data */ + if ((rc = matrixSslSentData(ssl, transferred)) < 0) { + goto L_CLOSE_ERR; + } + if (rc == MATRIXSSL_REQUEST_CLOSE) { + closeConn(ssl, fd); + return MATRIXSSL_SUCCESS; + } + if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) { + /* If we sent the Finished SSL message, initiate the HTTP req */ + /* (This occurs on a resumption handshake) */ + if ((rc = httpWriteRequest(ssl)) < 0) { + goto L_CLOSE_ERR; + } + if (rc == MATRIXSSL_REQUEST_SEND) { + /* We have a HTTP request to send */ + goto WRITE_MORE; + } + closeConn(ssl, fd); + return MATRIXSSL_SUCCESS; + } + /* MATRIXSSL_REQUEST_SEND is handled by loop logic */ + } + } + +READ_MORE: + if ((len = matrixSslGetReadbuf(ssl, &buf)) <= 0) { + goto L_CLOSE_ERR; + } + if ((transferred = recv(fd, buf, len, 0)) < 0) { + goto L_CLOSE_ERR; + } + if (g_trace) psTraceBytes("RECV", buf, transferred); + /* If EOF, remote socket closed. But we haven't received the HTTP response + so we consider it an error in the case of an HTTP client */ + if (transferred == 0) { + goto L_CLOSE_ERR; + } + psGetTime(&t1, NULL); + if ((rc = matrixSslReceivedData(ssl, (int32)transferred, &buf, + (uint32*)&len)) < 0) { + psGetTime(&t2, NULL); + if (ssl->hsState == SSL_HS_DONE) { +#ifdef USE_HIGHRES_TIME + stats->datatime += psDiffUsecs(t1, t2); +#else + stats->datatime += psDiffMsecs(t1, t2, NULL); +#endif + } else { +#ifdef USE_HIGHRES_TIME + stats->hstime += psDiffUsecs(t1, t2); +#else + stats->hstime += psDiffMsecs(t1, t2, NULL); +#endif + } + goto L_CLOSE_ERR; + } + psGetTime(&t2, NULL); + if (ssl->hsState == SSL_HS_DONE) { +#ifdef USE_HIGHRES_TIME + stats->datatime += psDiffUsecs(t1, t2); +#else + stats->datatime += psDiffMsecs(t1, t2, NULL); +#endif + } else { +#ifdef USE_HIGHRES_TIME + stats->hstime += psDiffUsecs(t1, t2); +#else + stats->hstime += psDiffMsecs(t1, t2, NULL); +#endif + } + +PROCESS_MORE: + switch (rc) { + case MATRIXSSL_HANDSHAKE_COMPLETE: +#ifdef REHANDSHAKE_TEST +/* + Test rehandshake capabilities of server. A full re-handshake + is first tested. After that, a session resmption rehandshake + is attempted. In that case, this client will be last to + send handshake data and MATRIXSSL_HANDSHAKE_COMPLETE will hit on + the WRITE_MORE handler and httpWriteRequest will occur there. + + NOTE: If the server doesn't support session resumption it is + possible to fall into an endless rehandshake loop +*/ + if (g_rehandshakeFlag == 0) { + /* Full rehandshake */ + if (matrixSslEncodeRehandshake(ssl, NULL, NULL, + SSL_OPTION_FULL_HANDSHAKE, g_cipher, g_ciphers) < 0) { + goto L_CLOSE_ERR; + } + g_rehandshakeFlag = 1; + } else if (g_rehandshakeFlag == 1) { + /* Resumed rehandshake */ + if (matrixSslEncodeRehandshake(ssl, NULL, NULL, 0, + g_cipher, g_ciphers) < 0) { + goto L_CLOSE_ERR; + } + g_rehandshakeFlag = 2; + } else { + if ((rc = httpWriteRequest(ssl)) < 0) { + goto L_CLOSE_ERR; + } + if (rc != MATRIXSSL_REQUEST_SEND) { + closeConn(ssl, fd); + return MATRIXSSL_SUCCESS; + } + } + goto WRITE_MORE; +#else + /* We got the Finished SSL message, initiate the HTTP req */ + if ((rc = httpWriteRequest(ssl)) < 0) { + goto L_CLOSE_ERR; + } + if (rc == MATRIXSSL_REQUEST_SEND) { + /* We have a HTTP request to send */ + goto WRITE_MORE; + } + closeConn(ssl, fd); + return MATRIXSSL_SUCCESS; +#endif + case MATRIXSSL_APP_DATA: + case MATRIXSSL_APP_DATA_COMPRESSED: + if (g_trace) psTraceBytes("Decrypted app data", buf, len); + if (cp.flags != HTTPS_COMPLETE) { + rc = httpBasicParse(&cp, buf, len, g_trace); + if (rc < 0) { + closeConn(ssl, fd); + if (cp.parsebuf) free(cp.parsebuf); cp.parsebuf = NULL; + cp.parsebuflen = 0; + return MATRIXSSL_ERROR; + } + if (rc == HTTPS_COMPLETE) { + cp.flags = HTTPS_COMPLETE; + } + } + cp.bytes_received += len; + stats->rbytes += len; + if (g_trace) { + psTraceBytes("HTTP DATA", buf, len); + } + rc = matrixSslProcessedData(ssl, &buf, (uint32*)&len); + if (rc < 0) { + goto L_CLOSE_ERR; + } + if (g_bytes_requested > 0) { + if (cp.bytes_received >= g_bytes_requested) { + /* We've received all that was requested, so close */ + closeConn(ssl, fd); + if (cp.parsebuf) free(cp.parsebuf); cp.parsebuf = NULL; + cp.parsebuflen = 0; + return MATRIXSSL_SUCCESS; + } + if (rc == 0) { + /* We processed a partial HTTP message */ + goto READ_MORE; + } + } + goto PROCESS_MORE; + case MATRIXSSL_REQUEST_SEND: + goto WRITE_MORE; + case MATRIXSSL_REQUEST_RECV: + goto READ_MORE; + case MATRIXSSL_RECEIVED_ALERT: + /* The first byte of the buffer is the level */ + /* The second byte is the description */ + if (*buf == SSL_ALERT_LEVEL_FATAL) { + psTraceIntInfo("Fatal alert: %d, closing connection.\n", + *(buf + 1)); + goto L_CLOSE_ERR; + } + /* Closure alert is normal (and best) way to close */ + if (*(buf + 1) == SSL_ALERT_CLOSE_NOTIFY) { + closeConn(ssl, fd); + if (cp.parsebuf) free(cp.parsebuf); cp.parsebuf = NULL; + cp.parsebuflen = 0; + return MATRIXSSL_SUCCESS; + } + psTraceIntInfo("Warning alert: %d\n", *(buf + 1)); + if ((rc = matrixSslProcessedData(ssl, &buf, (uint32*)&len)) == 0) { + /* No more data in buffer. Might as well read for more. */ + goto READ_MORE; + } + goto PROCESS_MORE; + default: + /* If rc <= 0 we fall here */ + goto L_CLOSE_ERR; + } + +L_CLOSE_ERR: + if (cp.flags != HTTPS_COMPLETE) { + _psTrace("FAIL: No HTTP Response\n"); + } else { +/* + printf("Received %d bytes %d usecs, state %d\n", + stats->rbytes, (int)stats->hstime, (int)stats->datatime, + ssl->hsState); +*/ + } + matrixSslDeleteSession(ssl); + if (g_keepalive == 0) { + close(fd); + } + if (cp.parsebuf) free(cp.parsebuf); cp.parsebuf = NULL; + cp.parsebuflen = 0; + return rc; +} + +/******************************************************************************/ +/* + Create an HTTP request and encode it to the SSL buffer + */ +static int32 httpWriteRequest(ssl_t *ssl) +{ + unsigned char *buf; + int32 available, requested; + + /* If we don't have a path defined and are sending zero bytes, skip http */ + if (g_bytes_requested == 0 && *g_path == '\0') { + return PS_SUCCESS; + } + + if (g_closeServer) { + /* A value of 0 to the 'new' connections is the key to sending the + server a shutdown message */ + requested = strlen((char *)g_matrixShutdownServer) + 1; + if ((available = matrixSslGetWritebuf(ssl, &buf, requested)) < 0) { + return PS_MEM_FAIL; + } + if (available < requested) { + return PS_FAILURE; + } + memset(buf, 0x0, requested); /* So strlen will work below */ + strncpy((char *)buf, (char *)g_matrixShutdownServer, + (uint32)strlen((char *)g_matrixShutdownServer)); + if (matrixSslEncodeWritebuf(ssl, (uint32)strlen((char *)buf)) < 0) { + return PS_MEM_FAIL; + } + return MATRIXSSL_REQUEST_SEND; + } + + requested = strlen((char *)g_httpRequestHdr) + strlen(g_path) + 1; + if ((available = matrixSslGetWritebuf(ssl, &buf, requested)) < 0) { + return PS_MEM_FAIL; + } + requested = min(requested, available); + snprintf((char *)buf, requested, (char *)g_httpRequestHdr, g_path); + + + if (g_trace) _psTraceStr("SEND: [%s]\n", (char*)buf); + if (matrixSslEncodeWritebuf(ssl, strlen((char *)buf)) < 0) { + return PS_MEM_FAIL; + } + return MATRIXSSL_REQUEST_SEND; +} + +#ifdef ID_RSA +#ifdef USE_HEADER_KEYS +static int32 loadRsaKeys(uint32 key_len, sslKeys_t *keys, + unsigned char *CAstream, int32 CAstreamLen) +{ + int32 rc; + + if (key_len == 1024) { + _psTrace("Using 1024 bit RSA private key\n"); + rc = matrixSslLoadRsaKeysMem(keys, RSA1024, sizeof(RSA1024), + RSA1024KEY, sizeof(RSA1024KEY), CAstream, CAstreamLen); + } else if (key_len == 2048) { + _psTrace("Using 2048 bit RSA private key\n"); + rc = matrixSslLoadRsaKeysMem(keys, RSA2048, sizeof(RSA2048), + RSA2048KEY, sizeof(RSA2048KEY), CAstream, CAstreamLen); + } else if (key_len == 4096) { + _psTrace("Using 4096 bit RSA private key\n"); + rc = matrixSslLoadRsaKeysMem(keys, RSA4096, sizeof(RSA4096), + RSA4096KEY, sizeof(RSA4096KEY), CAstream, CAstreamLen); + } else { + rc = -1; + psAssert((key_len == 1024) || (key_len == 2048) || (key_len == 4096)); + } + + if (rc < 0) { + _psTrace("No certificate material loaded. Exiting\n"); + if (CAstream) { + psFree(CAstream, NULL); + } + matrixSslDeleteKeys(keys); + matrixSslClose(); + } + + return rc; +} +#endif +#endif + +static void usage(void) +{ + printf( + "\nusage: client { options }\n" + "\n" + "Options can be one or more of the following:\n" + "\n" + "-a - Disable sending closure alerts\n" + "-b - Client request size\n" + " Generates an HTTPS request after TLS negotiation\n" + " Uses URL path of '/bytes?'\n" + " Mutually exclusive with '-u' flag\n" + "-c - Comma separated list of ciphers numbers\n" + " - Example cipher numbers:\n" + " - '53' TLS_RSA_WITH_AES_256_CBC_SHA\n" + " - '47' TLS_RSA_WITH_AES_128_CBC_SHA\n" + " - '10' SSL_RSA_WITH_3DES_EDE_CBC_SHA\n" + " - '5' SSL_RSA_WITH_RC4_128_SHA\n" + " - '4' SSL_RSA_WITH_RC4_128_MD5\n" + "-d - Disable server certicate name/addr chk\n" + "-h - Help, print usage and exit\n" + "-k - RSA keyLen\n" + " - Must be one of 1024, 2048 or 4096\n" + "-K - Keepalive (Re-use socket after TLS session close)\n" + "-n - Num of new (full handshake) sessions\n" + " - Default 1\n" + "-p - Port number for SSL/TLS server\n" + " - Default 4433 (HTTPS is 443)\n" + "-r - Num of resumed SSL/TLS sesssions\n" + " - Default 0\n" + "-s - IP address of server machine/interface\n" + " - Default 127.0.0.1 (localhost)\n" + "-u - URL path, eg. '/index.html'\n" + " Generates an HTTPS request after TLS negotiation\n" + " Mutually exclusive with '-b' flag\n" + "-V - SSL/TLS version to use\n" + " - '0' SSL 3.0\n" + " - '1' TLS 1.0\n" + " - '2' TLS 1.1\n" + " - '3' TLS 1.2 (default)\n" + "\n"); +} + +/* Returns number of cipher numbers found, or -1 if an error. */ +#include +static int32_t parse_cipher_list(char *cipherListString, + uint16_t cipher_array[], uint8_t size_of_cipher_array) +{ + uint32 numCiphers, cipher; + char *endPtr; + + /* Convert the cipherListString into an array of cipher numbers. */ + numCiphers = 0; + while (cipherListString != NULL) { + cipher = strtol(cipherListString, &endPtr, 10); + if (endPtr == cipherListString) { + printf("The remaining cipherList has no cipher numbers - '%s'\n", + cipherListString); + return -1; + } else if (size_of_cipher_array <= numCiphers) { + printf("Too many cipher numbers supplied. limit is %d\n", + size_of_cipher_array); + return -1; + } + cipher_array[numCiphers++] = cipher; + while (*endPtr != '\0' && !isdigit(*endPtr)) { + endPtr++; + } + cipherListString = endPtr; + if (*endPtr == '\0') { + break; + } + } + + return numCiphers; +} + +/* Return 0 on good set of cmd options, return -1 if a bad cmd option is + encountered OR a request for help is seen (i.e. '-h' option). */ +static int32 process_cmd_options(int32 argc, char **argv) +{ + int optionChar, key_len, version, numCiphers; + char *cipherListString; + + // Set some default options: + memset(g_cipher, 0, sizeof(g_cipher)); + memset(g_ip, 0, sizeof(g_ip)); + memset(g_path, 0, sizeof(g_path)); + + strcpy(g_ip, "127.0.0.1"); + g_bytes_requested = 0; + g_send_closure_alert = 1; + g_ciphers = 1; + g_cipher[0] = 47; + g_disableCertNameChk = 0; + g_key_len = 1024; + g_new = 1; + g_port = 4433; + g_resumed = 0; + g_version = 3; + g_keepalive = 0; + + opterr = 0; + while ((optionChar = getopt(argc, argv, "ab:c:dhk:Kn:p:r:s:u:V:")) != -1) + { + switch (optionChar) + { + case 'h': + return -1; + + + case 'a': + g_send_closure_alert = 0; + break; + + case 'b': + if (*g_path) { + printf("-b and -u options cannot both be provided\n"); + return -1; + } + g_bytes_requested = atoi(optarg); + snprintf(g_path, sizeof(g_path), "/bytes?%u", g_bytes_requested); + break; + + case 'c': + // Convert the cipherListString into an array of cipher numbers. + cipherListString = optarg; + numCiphers = parse_cipher_list(cipherListString, g_cipher, 16); + if (numCiphers <= 0) { + return -1; + } + g_ciphers = numCiphers; + break; + + case 'd': + g_disableCertNameChk = 1; + break; + + case 'k': + key_len = atoi(optarg); + if ((key_len != 1024) && (key_len != 2048) && (key_len != 4096)) { + printf("-k option must be followed by a key_len whose value " + " must be 1024, 2048 or 4096\n"); + return -1; + } + g_key_len = key_len; + break; + + case 'K': + g_keepalive = 1; + break; + + case 'n': + g_new = atoi(optarg); + break; + + case 'p': + g_port = atoi(optarg); + break; + + case 'r': + g_resumed = atoi(optarg); + break; + + case 's': + strncpy(g_ip, optarg, 15); + break; + + case 'u': + if (*g_path) { + printf("-b and -u options cannot both be provided\n"); + return -1; + } + strncpy(g_path, optarg, sizeof(g_path) - 1); + g_bytes_requested = 0; + break; + + case 'V': + version = atoi(optarg); + if (version < 0 || version > 3) { + printf("Invalid version: %d\n", version); + return -1; + } + g_version = version; + break; + } + } + + return 0; +} + +/******************************************************************************/ +/* + Main routine. Initialize SSL keys and structures, and make two SSL + connections, the first with a blank session Id, and the second with + a session ID populated during the first connection to do a much faster + session resumption connection the second time. + */ +int32 main(int32 argc, char **argv) +{ + int32 rc, CAstreamLen, i; + sslKeys_t *keys; + sslSessionId_t *sid; + struct g_sslstats stats; + unsigned char *CAstream; +#ifdef USE_CRL + int32 numLoaded; +#endif +#ifdef WIN32 + WSADATA wsaData; + WSAStartup(MAKEWORD(1, 1), &wsaData); +#endif + + if ((rc = matrixSslOpen()) < 0) { + _psTrace("MatrixSSL library init failure. Exiting\n"); + return rc; + } + + + if (matrixSslNewKeys(&keys, NULL) < 0) { + _psTrace("MatrixSSL library key init failure. Exiting\n"); + return -1; + } + + if (0 != process_cmd_options(argc, argv)) { + usage(); + return 0; + } + + if (g_new <= 1 && g_resumed <= 1) { + g_trace = 1; + } else { + g_trace = 0; + } + + if (g_bytes_requested == 0 && *g_path == '\0') { + printf("client %s:%d " + "new:%d resumed:%d keylen:%d nciphers:%d version:%s\n", + g_ip, g_port, g_new, g_resumed, g_key_len, + g_ciphers, g_strver[g_version]); + } else { + printf("client https://%s:%d%s " + "new:%d resumed:%d keylen:%d nciphers:%d version:%s\n", + g_ip, g_port, g_path, g_new, g_resumed, g_key_len, + g_ciphers, g_strver[g_version]); + } + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#ifdef USE_HEADER_KEYS +/* + In-memory based keys + Build the CA list first for potential client auth usage +*/ + CAstreamLen = 0; +#ifdef USE_RSA_CIPHER_SUITE + CAstreamLen += sizeof(RSACAS); +#ifdef USE_ECC_CIPHER_SUITE + CAstreamLen += sizeof(ECDHRSACAS); +#endif +#endif +#ifdef USE_ECC_CIPHER_SUITE + CAstreamLen += sizeof(ECCAS); +#endif + if (CAstreamLen > 0) { + CAstream = psMalloc(NULL, CAstreamLen); + } else { + CAstream = NULL; + } + + CAstreamLen = 0; +#ifdef USE_RSA_CIPHER_SUITE + memcpy(CAstream, RSACAS, sizeof(RSACAS)); + CAstreamLen += sizeof(RSACAS); +#ifdef USE_ECC_CIPHER_SUITE + memcpy(CAstream + CAstreamLen, ECDHRSACAS, sizeof(ECDHRSACAS)); + CAstreamLen += sizeof(ECDHRSACAS); +#endif +#endif +#ifdef USE_ECC_CIPHER_SUITE + memcpy(CAstream + CAstreamLen, ECCAS, sizeof(ECCAS)); + CAstreamLen += sizeof(ECCAS); +#endif + + +#ifdef ID_RSA + rc = loadRsaKeys(g_key_len, keys, CAstream, CAstreamLen); + if (rc < 0) { + return rc; + } +#endif + +#ifdef ID_ECDH_RSA + if ((rc = matrixSslLoadEcKeysMem(keys, ECDHRSA521, sizeof(ECDHRSA521), + ECDHRSA521KEY, sizeof(ECDHRSA521KEY), (unsigned char*)CAstream, + CAstreamLen)) < 0) { + _psTrace("No certificate material loaded. Exiting\n"); + if (CAstream) psFree(CAstream, NULL); + matrixSslDeleteKeys(keys); + matrixSslClose(); + return rc; + } +#endif + +#ifdef ID_ECDH_ECDSA + if ((rc = matrixSslLoadEcKeysMem(keys, EC384, sizeof(EC384), + EC384KEY, sizeof(EC384KEY), (unsigned char*)CAstream, + CAstreamLen)) < 0) { + _psTrace("No certificate material loaded. Exiting\n"); + if (CAstream) psFree(CAstream, NULL); + matrixSslDeleteKeys(keys); + matrixSslClose(); + return rc; + } +#endif + + if (CAstream) psFree(CAstream, NULL); + +#else +/* + File based keys +*/ + CAstreamLen = 0; +#ifdef USE_RSA_CIPHER_SUITE + CAstreamLen += (int32)strlen(rsaCAFile) + 1; +#ifdef USE_ECC_CIPHER_SUITE + CAstreamLen += (int32)strlen(ecdhRsaCAFile) + 1; +#endif +#endif +#ifdef USE_ECC_CIPHER_SUITE + CAstreamLen += (int32)strlen(ecCAFile) + 1; +#endif + if (CAstreamLen > 0) { + CAstream = psMalloc(NULL, CAstreamLen); + memset(CAstream, 0x0, CAstreamLen); + } else { + CAstream = NULL; + } + + CAstreamLen = 0; +#ifdef USE_RSA_CIPHER_SUITE + memcpy(CAstream, rsaCAFile, strlen(rsaCAFile)); + CAstreamLen += strlen(rsaCAFile); +#ifdef USE_ECC_CIPHER_SUITE + memcpy(CAstream + CAstreamLen, ";", 1); CAstreamLen++; + memcpy(CAstream + CAstreamLen, ecdhRsaCAFile, strlen(ecdhRsaCAFile)); + CAstreamLen += strlen(ecdhRsaCAFile); +#endif +#endif +#ifdef USE_ECC_CIPHER_SUITE + if (CAstreamLen > 0) { + memcpy(CAstream + CAstreamLen, ";", 1); CAstreamLen++; + } + memcpy(CAstream + CAstreamLen, ecCAFile, strlen(ecCAFile)); +#endif + +/* Load Identiy */ +#ifdef EXAMPLE_RSA_KEYS + if ((rc = matrixSslLoadRsaKeys(keys, rsaCertFile, rsaPrivkeyFile, NULL, + (char*)CAstream)) < 0) { + _psTrace("No certificate material loaded. Exiting\n"); + if (CAstream) psFree(CAstream, NULL); + matrixSslDeleteKeys(keys); + matrixSslClose(); + return rc; + } +#endif + +#ifdef EXAMPLE_ECDH_RSA_KEYS + if ((rc = matrixSslLoadEcKeys(keys, ecdhRsaCertFile, ecdhRsaPrivkeyFile, + NULL, (char*)CAstream)) < 0) { + _psTrace("No certificate material loaded. Exiting\n"); + if (CAstream) psFree(CAstream, NULL); + matrixSslDeleteKeys(keys); + matrixSslClose(); + return rc; + } +#endif + +#ifdef EXAMPLE_EC_KEYS + if ((rc = matrixSslLoadEcKeys(keys, ecCertFile, ecPrivkeyFile, NULL, + (char*)CAstream)) < 0) { + _psTrace("No certificate material loaded. Exiting\n"); + if (CAstream) psFree(CAstream, NULL); + matrixSslDeleteKeys(keys); + matrixSslClose(); + return rc; + } +#endif + + if (CAstream) psFree(CAstream, NULL); +#endif /* USE_HEADER_KEYS */ +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ + +#ifdef USE_PSK_CIPHER_SUITE + for (rc = 0; rc < PSK_HEADER_TABLE_COUNT; rc++) { + matrixSslLoadPsk(keys, + PSK_HEADER_TABLE[rc].key, sizeof(PSK_HEADER_TABLE[rc].key), + PSK_HEADER_TABLE[rc].id, sizeof(PSK_HEADER_TABLE[rc].id)); + } +#endif /* USE_PSK_CIPHER_SUITE */ + +#ifdef USE_CRL + if (matrixSslGetCRL(keys, crlCb, &numLoaded) < 0) { + _psTrace("WARNING: A CRL failed to load\n"); + } + _psTraceInt("CRLs loaded: %d\n", numLoaded); +#endif + + + memset(&stats, 0x0, sizeof(struct g_sslstats)); + printf("=== %d new connections ===\n", g_new); + + if (g_new == 0) { + /* Special case where client is being used to remotely shut down + the server for automated tests */ + g_closeServer = 1; + g_bytes_requested = 0; /* Disable data exchange in this case */ + g_new++; + } + + for (i = 0; i < g_new; i++) { + matrixSslNewSessionId(&sid, NULL); + rc = httpsClientConnection(keys, sid, &stats); + if (rc < 0) { + printf("F %d/%d\n", i, g_new); + return 0; + } else { + printf("N"); fflush(stdout); + } + /* Leave the final sessionID for resumed connections */ + if (i + 1 < g_new) matrixSslDeleteSessionId(sid); + } + if (g_new) printf("\n"); + if (g_bytes_requested > 0) { + psAssert(g_bytes_requested * g_new == stats.rbytes); + } + printf("%d bytes received\n", stats.rbytes); +#ifdef USE_HIGHRES_TIME + printf("%d usec (%d avg usec/conn SSL handshake overhead)\n", + (int)stats.hstime, (int)(stats.hstime/ g_new)); + printf("%d usec (%d avg usec/conn SSL data overhead)\n", + (int)stats.datatime, (int)(stats.datatime/ g_new)); +#else + printf("%d msec (%d avg msec/conn SSL handshake overhead)\n", + (int)stats.hstime, (int)(stats.hstime/ g_new)); + printf("%d msec (%d avg msec/conn SSL data overhead)\n", + (int)stats.datatime, (int)(stats.datatime/ g_new)); +#endif + + memset(&stats, 0x0, sizeof(struct g_sslstats)); + printf("=== %d resumed connections ===\n", g_resumed); + for (i = 0; i < g_resumed; i++) { + rc = httpsClientConnection(keys, sid, &stats); + if (rc < 0) { + printf("f %d/%d\n", i, g_resumed); + } else { + printf("R"); fflush(stdout); + } + } + if (g_keepalive) { + printf("Closing socket\n"); + close(g_keepalive); + g_keepalive = 0; + } + if (g_resumed) { + if (g_bytes_requested > 0) { + psAssert(g_bytes_requested * g_resumed == stats.rbytes); + } + printf("\n%d bytes received\n", stats.rbytes); +#ifdef USE_HIGHRES_TIME + printf("%d usec (%d avg usec/conn SSL handshake overhead)\n", + (int)stats.hstime, (int)(stats.hstime/ g_resumed)); + printf("%d usec (%d avg usec/conn SSL data overhead)\n", + (int)stats.datatime, (int)(stats.datatime/ g_resumed)); +#else + printf("%d msec (%d avg msec/conn SSL handshake overhead)\n", + (int)stats.hstime, (int)(stats.hstime/ g_resumed)); + printf("%d msec (%d avg msec/conn SSL data overhead)\n", + (int)stats.datatime, (int)(stats.datatime/ g_resumed)); +#endif + } + + matrixSslDeleteSessionId(sid); + + matrixSslDeleteKeys(keys); + matrixSslClose(); + +#ifdef WIN32 + _psTrace("Press any key to close"); + getchar(); +#endif + return 0; +} + +/******************************************************************************/ +/* + Close a socket and free associated SSL context and buffers + An attempt is made to send a closure alert + */ +static void closeConn(ssl_t *ssl, SOCKET fd) +{ + unsigned char *buf; + int32 len; + + if (g_send_closure_alert) { +#if 1 + /* Set the socket to non-blocking to flush remaining data */ +#ifdef POSIX + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); +#endif +#ifdef WIN32 + len = 1; /* 1 for non-block, 0 for block */ + ioctlsocket(fd, FIONBIO, &len); +#endif + /* Quick attempt to send a closure alert, don't worry about failure */ + if (matrixSslEncodeClosureAlert(ssl) >= 0) { + if ((len = matrixSslGetOutdata(ssl, &buf)) > 0) { + if ((len = send(fd, buf, len, MSG_DONTWAIT)) > 0) { + matrixSslSentData(ssl, len); + } + } + } +#endif + } + matrixSslDeleteSession(ssl); + + if (fd != INVALID_SOCKET && g_keepalive == 0) { + //printf("Closing socket from closeConn\n"); + close(fd); + } +} + +static int32_t extensionCb(ssl_t *ssl, + uint16_t extType, uint8_t extLen, void *e) +{ + unsigned char *c; + short len; + char proto[128]; + + c = (unsigned char*)e; + + if (extType == EXT_ALPN) { + memset(proto, 0x0, 128); + /* two byte proto list len, one byte proto len, then proto */ + c += 2; /* Skip proto list len */ + len = *c; c++; + memcpy(proto, c, len); + printf("Server agreed to use %s\n", proto); + } + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Example callback to show possiblie outcomes of certificate validation. + If this callback is not registered in matrixSslNewClientSession + the connection will be accepted or closed based on the alert value. + */ +static int32 certCb(ssl_t *ssl, psX509Cert_t *cert, int32 alert) +{ +#ifndef USE_ONLY_PSK_CIPHER_SUITE + psX509Cert_t *next; + + /* An immediate SSL_ALERT_UNKNOWN_CA alert means we could not find the + CA to authenticate the server's certificate */ + if (alert == SSL_ALERT_UNKNOWN_CA) { + /* Example to allow anonymous connections based on a define */ + if (ALLOW_ANON_CONNECTIONS) { + if (g_trace) { + _psTraceStr("Allowing anonymous connection for: %s.\n", + cert->subject.commonName); + } + return SSL_ALLOW_ANON_CONNECTION; + } + _psTrace("ERROR: No matching CA found. Terminating connection\n"); + } + + /* Check for "major" authentication problems within the server certificate + chain. + + The "alert" is the translation of the very first authentication problem + found. So if we are dealing with a certificate chain we should walk to + the parent-most cert to confirm there are no authentication problems + that indicate the chain itself did not validate or this client did + not find a CA to authenticate the server. + + Some certificate callback implemenations might choose to ignore some + alerts that are considered minor to the use case, so this is an example + of how to make sure a minor alert (such as expired date) is not + overriding a more serious authentication problem + */ + for (next = cert; next != NULL; next = next->next) { + if (next->authStatus == PS_CERT_AUTH_FAIL_SIG) { + _psTrace("Public key signature failure in server cert chain\n"); + /* This should result in a BAD_CERTIFICATE alert */ + alert = SSL_ALERT_BAD_CERTIFICATE; + break; + } + if (next->authStatus == PS_CERT_AUTH_FAIL_DN) { + /* A CA file was never located to support this chain */ + _psTrace("No CA file was found to support server's certificate\n"); + /* This should result in a SSL_ALERT_UNKNOWN_CA alert */ + alert = SSL_ALERT_UNKNOWN_CA; + break; + } + if (next->authStatus == PS_CERT_AUTH_FAIL_AUTHKEY) { + /* Subject and Issuer Key Id extension */ + _psTrace("Subject and Issuer Key Id mismatch error\n"); + /* This should be a BAD_CERTIFICATE alert */ + alert = SSL_ALERT_BAD_CERTIFICATE; + break; + } + } + + /* + If the expectedName passed to matrixSslNewClientSession does not + match any of the server subject name or subjAltNames, we will have + the alert below. + For security, the expected name (typically a domain name) _must_ + match one of the certificate subject names, or the connection + should not continue. + The default MatrixSSL certificates use localhost and 127.0.0.1 as + the subjects, so unless the server IP matches one of those, this + alert will happen. + To temporarily disable the subjet name validation, NULL can be passed + as expectedName to matrixNewClientSession. + */ + if (alert == SSL_ALERT_CERTIFICATE_UNKNOWN) { + _psTraceStr("ERROR: %s not found in cert subject names\n", + ssl->expectedName); + } + + if (alert == SSL_ALERT_CERTIFICATE_EXPIRED) { +#ifdef POSIX + _psTrace("ERROR: A cert did not fall within the notBefore/notAfter window\n"); +#else + _psTrace("WARNING: Certificate date window validation not implemented\n"); + alert = 0; +#endif + } + + if (alert == SSL_ALERT_ILLEGAL_PARAMETER) { + _psTrace("ERROR: Found correct CA but X.509 extension details are wrong\n"); + } + + /* Key usage related problems on chain */ + for (next = cert; next != NULL; next = next->next) { + if (next->authStatus == PS_CERT_AUTH_FAIL_EXTENSION) { + if (next->authFailFlags & PS_CERT_AUTH_FAIL_KEY_USAGE_FLAG) { + _psTrace("CA keyUsage extension doesn't allow cert signing\n"); + } + if (next->authFailFlags & PS_CERT_AUTH_FAIL_EKU_FLAG) { + _psTrace("Cert extendedKeyUsage extension doesn't allow TLS\n"); + } + } + } + + if (alert == SSL_ALERT_BAD_CERTIFICATE) { + /* Should never let a connection happen if this is set. There was + either a problem in the presented chain or in the final CA test */ + _psTrace("ERROR: Problem in certificate validation. Exiting.\n"); + } + + + if (g_trace && alert == 0) _psTraceStr("SUCCESS: Validated cert for: %s.\n", + cert->subject.commonName); + +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + return alert; +} + +#ifdef USE_CRL +/* Basic example of matrixSslGetCRL callback for downloading a CRL from a given + URL and passing the CRL contents to matrixSslLoadCRL + + < 0 - Error loading CRL + > 0 - Success +*/ +static unsigned char crl_getHdr[] = "GET "; +#define GET_OH_LEN 4 +static unsigned char crl_httpHdr[] = " HTTP/1.0\r\n"; +#define HTTP_OH_LEN 11 +static unsigned char crl_hostHdr[] = "Host: "; +#define HOST_OH_LEN 6 +static unsigned char crl_acceptHdr[] = "\r\nAccept: */*\r\n\r\n"; +#define ACCEPT_OH_LEN 17 + +#define HOST_ADDR_LEN 64 /* max to hold 'www.something.com' */ +#define GET_REQ_LEN 128 /* max to hold http GET request */ +#define CRL_BUF_SIZE 4096 /* max size of incoming CRL */ + +int32 crlCb(psPool_t *pool, psX509Cert_t *CA, int append, char *url, + uint32 urlLen) +{ + SOCKET fd; + struct hostent *ip; + struct in_addr intaddr; + char *pageStart, *replyPtr, *ipAddr; + char hostAddr[HOST_ADDR_LEN], getReq[GET_REQ_LEN]; + char crlBuf[CRL_BUF_SIZE]; + int hostAddrLen, getReqLen, pageLen; + int32 transferred; + int32 err, httpUriLen, port, offset; + uint32 crlBinLen; + + /* Is URI in expected URL form? */ + if (strstr(url, "http://") == NULL) { + if (strstr(url, "https://") == NULL) { + _psTraceStr("crlCb: Unsupported CRL URI: %s\n", url); + return -1; + } + httpUriLen = 8; + port = 80; /* No example yet of using SSL to fetch CRL */ + } else { + httpUriLen = 7; + port = 80; + } + + /* Parsing host and page and setting up IP address and GET request */ + if ((pageStart = strchr(url + httpUriLen, '/')) == NULL) { + _psTrace("crlCb: No host/page divider found\n"); + return -1; + } + if ((hostAddrLen = (int)(pageStart - url) - httpUriLen) > HOST_ADDR_LEN) { + _psTrace("crlCb: HOST_ADDR_LEN needs to be increased\n"); + return -1; /* ipAddr too small to hold */ + } + + memset(hostAddr, 0, HOST_ADDR_LEN); + memcpy(hostAddr, url + httpUriLen, hostAddrLen); + if ((ip = gethostbyname(hostAddr)) == NULL) { + _psTrace("crlCb: gethostbyname failed\n"); + return -1; + } + + memcpy((char *) &intaddr, (char *) ip->h_addr_list[0], + (size_t) ip->h_length); + if ((ipAddr = inet_ntoa(intaddr)) == NULL) { + _psTrace("crlCb: inet_ntoa failed\n"); + return -1; + } + + pageLen = (urlLen - hostAddrLen - httpUriLen); + getReqLen = pageLen + hostAddrLen + GET_OH_LEN + HTTP_OH_LEN + + HOST_OH_LEN + ACCEPT_OH_LEN; + if (getReqLen > GET_REQ_LEN) { + _psTrace("crlCb: GET_REQ_LEN needs to be increased\n"); + return -1; + } + + // Build the request: + // + // GET /page.crl HTTP/1.0 + // Host: www.host.com + // Accept: */* + // + memset(getReq, 0, GET_REQ_LEN); + memcpy(getReq, crl_getHdr, GET_OH_LEN); + offset = GET_OH_LEN; + memcpy(getReq + offset, pageStart, pageLen); + offset += pageLen; + memcpy(getReq + offset, crl_httpHdr, HTTP_OH_LEN); + offset += HTTP_OH_LEN; + memcpy(getReq + offset, crl_hostHdr, HOST_OH_LEN); + offset += HOST_OH_LEN; + memcpy(getReq + offset, hostAddr, hostAddrLen); + offset += hostAddrLen; + memcpy(getReq + offset, crl_acceptHdr, ACCEPT_OH_LEN); + + /* Connect and send */ + fd = lsocketConnect(ipAddr, port, &err); + if (fd == INVALID_SOCKET || err != PS_SUCCESS) { + _psTraceInt("crlCb: socketConnect failed: %d\n", err); + return PS_PLATFORM_FAIL; + } + + /* Send request and receive response */ + offset = 0; + while (getReqLen) { + if ((transferred = send(fd, getReq + offset, getReqLen, 0)) < 0) { + _psTraceInt("crlCb: socket send failed: %d\n", errno); + close(fd); + return PS_PLATFORM_FAIL; + } + getReqLen -= transferred; + offset += transferred; + } + + /* Not a good full recv */ + if ((transferred = recv(fd, crlBuf, CRL_BUF_SIZE, 0)) <= 0) { + _psTrace("crlCb: socket recv closed or failed\n"); + close(fd); + return PS_PLATFORM_FAIL; + } + if (transferred == CRL_BUF_SIZE) { + /* CRL larger than max */ + _psTrace("crlCb: CRL_BUF_SIZE needs to be increased\n"); + close(fd); + return -1; + } + close(fd); + + /* Did we get an OK response? */ + if (strstr(crlBuf, "200 OK") == NULL) { + _psTrace("crlCb: server reply was not '200 OK'\n"); + return -1; + } + /* Length parse */ + if ((replyPtr = strstr(crlBuf, "Content-Length: ")) == NULL) { + return -1; + } + crlBinLen = (int)atoi(replyPtr + 16); + + /* Data begins after CRLF CRLF */ + if ((replyPtr = strstr(crlBuf, "\r\n\r\n")) == NULL) { + return -1; + } + /* A sanity test that the length matches the remainder */ + if ((transferred - (replyPtr - crlBuf) - 4) != crlBinLen) { + return -1; + } + + /* Lastly, pass the CRL to matrixSslLoadCRL to parse, perform signature + validation, and cache the revoked certificates for this CA */ + return matrixSslLoadCRL(pool, CA, append, replyPtr + 4, crlBinLen, NULL); +} +#endif + +/******************************************************************************/ +/* + Open an outgoing blocking socket connection to a remote ip and port. + Caller should always check *err value, even if a valid socket is returned + */ +static SOCKET lsocketConnect(char *ip, int32 port, int32 *err) +{ + struct sockaddr_in addr; + SOCKET fd; + int32 rc; + + /* By default, this will produce a blocking socket */ + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { + perror("socket()"); + _psTrace("Error creating socket\n"); + *err = SOCKET_ERRNO; + return INVALID_SOCKET; + } +#ifdef POSIX + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif +#if 0 + { + struct linger lin; + rc = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc)); + rc = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *)&rc, sizeof(rc)); + lin.l_onoff = 0; + lin.l_linger = 0; // Seconds + setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&lin, sizeof(struct linger)); + } + { + uint32 len; + getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rc, &len); + printf("SO_RCVBUF: %d\n", rc); + } +#endif +#ifdef POSIX + rc = 1; +// setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&rc, sizeof(rc)); +// fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); +#elif defined(WIN32) + rc = 1; /* 1 for non-block, 0 for block */ +// ioctlsocket(fd, FIONBIO, &rc); +#endif +#ifdef __APPLE__ /* MAC OS X */ + rc = 1; + setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&rc, sizeof(rc)); +#endif + + memset((char *) &addr, 0x0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons((short)port); + addr.sin_addr.s_addr = inet_addr(ip); + rc = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); + if (rc < 0) { + perror("connect()"); + *err = SOCKET_ERRNO; + } else { + *err = 0; + } + return fd; +} + +#else + +/******************************************************************************/ +/* + Stub main for compiling without client enabled +*/ +int32 main(int32 argc, char **argv) +{ + printf("USE_CLIENT_SIDE_SSL must be enabled in matrixsslConfig.h at build" \ + " time to run this application\n"); + return -1; +} +#endif /* USE_CLIENT_SIDE_SSL */ + +/******************************************************************************/ + diff --git a/apps/ssl/http.c b/apps/ssl/http.c new file mode 100644 index 0000000..110d3d9 --- /dev/null +++ b/apps/ssl/http.c @@ -0,0 +1,136 @@ +/** + * @file http.c + * @version $Format:%h%d$ + * + * Simple INCOMPLETE HTTP parser for example applications. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "app.h" +//#define TEST + +/******************************************************************************/ +/* + EXAMPLE ONLY - SHOULD NOT BE USED FOR PRODUCTION CODE + + Process an HTTP request from a client. + Very simple - we just print it, and return success. + No HTTP validation at all is done on the data. + */ +int32 httpBasicParse(httpConn_t *cp, unsigned char *buf, uint32 len, + int32 trace) +{ + unsigned char *c, *end, *tmp; + int32 l; + + /* + SSL/TLS can provide zero length records, which we just ignore here + because the code below assumes we have at least one byte + */ + if (len == 0) { + return HTTPS_PARTIAL; + } + + c = buf; + end = c + len; +/* + If we have an existing partial HTTP buffer, append to it the data in buf + up to the first newline, or 'len' data, if no newline is in buf. + */ + if (cp->parsebuf != NULL) { + for (tmp = c; c < end && *c != '\n'; c++); + /* We want c to point to 'end' or to the byte after \r\n */ + if (*c == '\n') { + c++; + } + l = (int32)(c - tmp); + if (l > HTTPS_BUFFER_MAX) { + return HTTPS_ERROR; + } + cp->parsebuf = realloc(cp->parsebuf, l + cp->parsebuflen); + memcpy(cp->parsebuf + cp->parsebuflen, tmp, l); + cp->parsebuflen += l; + /* Parse the data out of the saved buffer first */ + c = cp->parsebuf; + end = c + cp->parsebuflen; + /* We've "moved" some data from buf into parsebuf, so account for it */ + buf += l; + len -= l; + } + +L_PARSE_LINE: + for (tmp = c; c < end && *c != '\n'; c++); + if (c < end) { + if (*(c - 1) != '\r') { + return HTTPS_ERROR; + } + /* If the \r\n started the line, we're done reading headers */ + if (*tmp == '\r' && (tmp + 1 == c)) { +/* + if ((c + 1) != end) { + _psTrace("HTTP data parsing not supported, ignoring.\n"); + } +*/ + if (cp->parsebuf != NULL) { + free(cp->parsebuf); cp->parsebuf = NULL; + cp->parsebuflen = 0; + if (len != 0) { + _psTrace("HTTP data parsing not supported, ignoring.\n"); + } + } + if (trace) _psTrace("RECV COMPLETE HTTP MESSAGE\n"); + return HTTPS_COMPLETE; + } + } else { + /* If parsebuf is non-null, we have already saved it */ + if (cp->parsebuf == NULL && (l = (int32)(end -tmp)) > 0) { + cp->parsebuflen = l; + cp->parsebuf = malloc(cp->parsebuflen); + psAssert(cp->parsebuf != NULL); + memcpy(cp->parsebuf, tmp, cp->parsebuflen); + } + return HTTPS_PARTIAL; + } + *(c - 1) = '\0'; /* Replace \r with \0 just for printing */ + if (trace) _psTraceStr("RECV PARSED: [%s]\n", (char *)tmp); + /* Finished parsing the saved buffer, now start parsing from incoming buf */ + if (cp->parsebuf != NULL) { + free(cp->parsebuf); cp->parsebuf = NULL; + cp->parsebuflen = 0; + c = buf; + end = c + len; + } else { + c++; /* point c to the next char after \r\n */ + } + goto L_PARSE_LINE; + + return HTTPS_ERROR; +} + +/******************************************************************************/ diff --git a/apps/ssl/runClient.sh b/apps/ssl/runClient.sh new file mode 100755 index 0000000..c4793eb --- /dev/null +++ b/apps/ssl/runClient.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +# Some cipher suites +CIPHER_SUITE="47" #AES128-SHA +#CIPHER_SUITE="5" #RC4128-SHA +#CIPHER_SUITE="4" #RC4128-MD5 +#CIPHER_SUITE="60" #AES128-SHA256 +#CIPHER_SUITE="10" #DES-CBC3-SHA +#CIPHER_SUITE="141" #PSK_AES256-SHA +#CIPHER_SUITE="49156" #ECDH_ECDSA-AES128-SHA +#CIPHER_SUITE="49162" #ECDHE_ECDSA-AES256-SHA +#CIPHER_SUITE="156" #RSA AES128-GCM-SHA256 +#CIPHER_SUITE="157" #RSA AES256-GCM-SHA384 +#CIPHER_SUITE="57" #DHE_RSA AES256-SHA +#CIPHER_SUITE="49195" #ECDHE_ECDSA-AES128-GCM-SHA256 +#CIPHER_SUITE="49196" #ECDHE_ECDSA-AES256-GCM-SHA384 + +#PROTOCOL_VERSION="1" #TLS1.0 +#PROTOCOL_VERSION="2" #TLS1.1 +PROTOCOL_VERSION="3" #TLS1.2 + +IPADDR="127.0.0.1" +PORT="4433" +NEW_SESSIONS="1" +RESUMED_SESSIONS="0" +BYTES="1024" + +# +# HTTP GET ./index.html request for testing against any server +# +./client -s${IPADDR} -p${PORT} -u./index.html -n${NEW_SESSIONS} -r${RESUMED_SESSIONS} -V${PROTOCOL_VERSION} -c${CIPHER_SUITE} -d + +# +# Byte count request for testing against MatrixSSL sample server +# +#./client -s${IPADDR} -p${PORT} -b${BYTES} -n${NEW_SESSIONS} -r${RESUMED_SESSIONS} -V${PROTOCOL_VERSION} -c${CIPHER_SUITE} -d + + diff --git a/apps/ssl/server.c b/apps/ssl/server.c new file mode 100644 index 0000000..6969762 --- /dev/null +++ b/apps/ssl/server.c @@ -0,0 +1,801 @@ +/** + * @file server.c + * @version $Format:%h%d$ + * + * Simple non-blocking MatrixSSL server example for multiple connections. + * Uses a single, hardcoded RSA identity. No client authentication. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "app.h" +#include "matrixssl/matrixsslApi.h" + +#ifdef USE_SERVER_SIDE_SSL + +#include /* Defines SIGTERM, etc. */ + +#ifdef WIN32 +#pragma message("DO NOT USE THESE DEFAULT KEYS IN PRODUCTION ENVIRONMENTS.") +#else +#warning "DO NOT USE THESE DEFAULT KEYS IN PRODUCTION ENVIRONMENTS." +#endif + +#define ALLOW_ANON_CONNECTIONS 1 +#define SEND_CLOSURE_ALERT + +/* Directory path to MatrixSSL testkeys */ +#define KEY_DIR "../../" + +const static char certFile[] = "testkeys/RSA/2048_RSA.pem"; +const static char privkeyFile[] = "testkeys/RSA/2048_RSA_KEY.pem"; + +#ifdef REQUIRE_DH_PARAMS +const static char dhParamFile[] = "testkeys/DH/1024_DH_PARAMS.pem"; +#endif + +/********************************** Defines ***********************************/ + +#define SSL_TIMEOUT 45000 /* In milliseconds */ +#define SELECT_TIME 1000 /* In milliseconds */ +#define RESPONSE_REC_LEN SSL_MAX_PLAINTEXT_LEN + +#define GOTO_SANITY 32 /* Must be <= 255 */ +/* + The ACCEPT_QUEUE is an optimization mechanism that allows the server to + accept() up to this many connections before serving any of them. The + reason is that the timeout waiting for the accept() is much shorter + than the timeout for the actual processing. +*/ +#define ACCEPT_QUEUE 16 + +/********************************** Globals ***********************************/ + +static DLListEntry g_conns; +static int32 g_exitFlag; + +static unsigned char g_httpResponseHdr[] = "HTTP/1.0 200 OK\r\n" + "Server: MatrixSSL/" MATRIXSSL_VERSION "\r\n" + "Pragma: no-cache\r\n" + "Cache-Control: no-cache\r\n" + "Content-type: text/plain\r\n" + "Content-length: 9\r\n" + "\r\n" + "MatrixSSL"; + +/****************************** Local Functions *******************************/ + +static int32 selectLoop(sslKeys_t *keys, SOCKET lfd); +static int32 httpWriteResponse(httpConn_t *conn); +static void setSocketOptions(SOCKET fd); +static SOCKET lsocketListen(short port, int32 *err); +static void closeConn(httpConn_t *cp, int32 reason); + +#ifdef POSIX +static void sigsegv_handler(int i); +static void sigintterm_handler(int i); +static int32 sighandlers(void); +#endif /* POSIX */ + +/******************************************************************************/ +/** + Display connections per second (if more than 0), at most once per second +*/ +static uint64_t g_handshakes = 0; +static void displayStats(void) +{ + static uint64_t s_handshakes = 0; /* last value displayed */ + static time_t s_t = (time_t)0; /* last time displayed */ + time_t t; + + if (g_handshakes > s_handshakes) { + t = time(NULL); + if (t > s_t) { + printf("%llu CPS\n", (g_handshakes - s_handshakes) / (t - s_t)); + s_handshakes = g_handshakes; + s_t = t; + } + } +} + +/******************************************************************************/ +/* + Non-blocking socket event handler + Wait one time in select for events on any socket + This will accept new connections, read and write to sockets that are + connected, and close sockets as required. + */ +static int32 selectLoop(sslKeys_t *keys, SOCKET lfd) +{ + httpConn_t *cp; + psTime_t now; + DLListEntry connsTmp; + DLListEntry *pList; + + fd_set readfd, writefd; + struct timeval timeout; + SOCKET fd, maxfd; + + unsigned char *buf; + int32 rc, len, transferred, val, specialAppData; + unsigned char rSanity, wSanity, acceptSanity; + + sslSessOpts_t options; + + DLListInit(&connsTmp); + rc = PS_SUCCESS; + maxfd = INVALID_SOCKET; + timeout.tv_sec = SELECT_TIME / 1000; + timeout.tv_usec = (SELECT_TIME % 1000) * 1000; + FD_ZERO(&readfd); + FD_ZERO(&writefd); + + /* Always set readfd for listening socket */ + FD_SET(lfd, &readfd); + if (lfd > maxfd) { + maxfd = lfd; + } +/* + Check timeouts and set readfd and writefd for connections as required. + We use connsTemp so that removal on error from the active iteration list + doesn't interfere with list traversal + */ + psGetTime(&now, NULL); + while (!DLListIsEmpty(&g_conns)) { + pList = DLListGetHead(&g_conns); + cp = DLListGetContainer(pList, httpConn_t, List); + DLListInsertTail(&connsTmp, &cp->List); + /* If timeout != 0 msec ith no new data, close */ + if (cp->timeout && (psDiffMsecs(cp->time, now, NULL) > + (int32)cp->timeout)) { + closeConn(cp, PS_TIMEOUT_FAIL); + continue; /* Next connection */ + } + /* Always select for read */ + FD_SET(cp->fd, &readfd); + /* Select for write if there's pending write data or connection */ + if (matrixSslGetOutdata(cp->ssl, NULL) > 0) { + FD_SET(cp->fd, &writefd); + } + /* Housekeeping for maxsock in select call */ + if (cp->fd > maxfd) { + maxfd = cp->fd; + } + } + + /* Use select to check for events on the sockets */ + if ((val = select(maxfd + 1, &readfd, &writefd, NULL, &timeout)) <= 0) { + /* On error, restore global connections list */ + while (!DLListIsEmpty(&connsTmp)) { + pList = DLListGetHead(&connsTmp); + cp = DLListGetContainer(pList, httpConn_t, List); + DLListInsertTail(&g_conns, &cp->List); + } + /* Select timeout */ + if (val == 0) { + return PS_TIMEOUT_FAIL; + } + /* Woke due to interrupt */ + if (SOCKET_ERRNO == EINTR) { + return PS_TIMEOUT_FAIL; + } + /* Should attempt to handle more errnos, such as EBADF */ + return PS_PLATFORM_FAIL; + } + + /* Check listener for new incoming socket connections */ + if (FD_ISSET(lfd, &readfd)) { + for (acceptSanity = 0; acceptSanity < ACCEPT_QUEUE; acceptSanity++) { + fd = accept(lfd, NULL, NULL); + if (fd == INVALID_SOCKET) { + break; /* Nothing more to accept; next listener */ + } + setSocketOptions(fd); + cp = malloc(sizeof(httpConn_t)); + memset(cp, 0x0, sizeof(httpConn_t)); + + memset(&options, 0x0, sizeof(sslSessOpts_t)); + options.userPtr = keys; + + if ((rc = matrixSslNewServerSession(&cp->ssl, keys, NULL, + &options)) < 0) { + close(fd); fd = INVALID_SOCKET; + continue; + } + + cp->fd = fd; + fd = INVALID_SOCKET; + cp->timeout = SSL_TIMEOUT; + psGetTime(&cp->time, NULL); + cp->parsebuf = NULL; + cp->parsebuflen = 0; + DLListInsertTail(&connsTmp, &cp->List); + /* Fake that there is read data available, no harm if there isn't */ + FD_SET(cp->fd, &readfd); +/* _psTraceInt("=== New Client %d ===\n", cp->fd); */ + } + } + + /* Check each connection for read/write activity */ + while (!DLListIsEmpty(&connsTmp)) { + pList = DLListGetHead(&connsTmp); + cp = DLListGetContainer(pList, httpConn_t, List); + DLListInsertTail(&g_conns, &cp->List); + + rSanity = wSanity = 0; +/* + See if there's pending data to send on this connection + We could use FD_ISSET, but this is more reliable for the current + state of data to send. + */ +WRITE_MORE: + if ((len = matrixSslGetOutdata(cp->ssl, &buf)) > 0) { + /* Could get a EWOULDBLOCK since we don't check FD_ISSET */ + transferred = (int32)send(cp->fd, buf, len, MSG_DONTWAIT); + if (transferred <= 0) { +#ifdef WIN32 + if (SOCKET_ERRNO != EWOULDBLOCK && + SOCKET_ERRNO != WSAEWOULDBLOCK) { + +#else + if (SOCKET_ERRNO != EWOULDBLOCK) { +#endif + closeConn(cp, PS_PLATFORM_FAIL); + continue; /* Next connection */ + } + } else { + /* Indicate that we've written > 0 bytes of data */ + if ((rc = matrixSslSentData(cp->ssl, transferred)) < 0) { + closeConn(cp, PS_ARG_FAIL); + continue; /* Next connection */ + } + if (rc == MATRIXSSL_REQUEST_CLOSE) { + closeConn(cp, MATRIXSSL_REQUEST_CLOSE); + continue; /* Next connection */ + } else if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) { + /* If the protocol is server initiated, send data here */ + g_handshakes++; +#ifdef ENABLE_FALSE_START + /* OR this could be a Chrome browser using + FALSE_START and the application data is already + waiting in our inbuf for processing */ + if ((rc = matrixSslReceivedData(cp->ssl, 0, + &buf, (uint32*)&len)) < 0) { + closeConn(cp, 0); + continue; /* Next connection */ + } + if (rc > 0) { /* There was leftover data */ + goto PROCESS_MORE; + } +#endif /* ENABLE_FALSE_START */ + + } + /* Update activity time */ + psGetTime(&cp->time, NULL); + /* Try to send again if more data to send */ + if (rc == MATRIXSSL_REQUEST_SEND || transferred < len) { + if (wSanity++ < GOTO_SANITY) goto WRITE_MORE; + } + } + } else if (len < 0) { + closeConn(cp, PS_ARG_FAIL); + continue; /* Next connection */ + } + + /* If we are sending response data and it's all encoded and sent, close conn */ + if (cp->bytes_requested > 0 && + cp->bytes_requested == cp->bytes_sent && + matrixSslGetOutdata(cp->ssl, &buf) <= 0) { + closeConn(cp, PS_SUCCESS); + continue; /* Next connection */ + } + +/* + Check the file descriptor returned from select to see if the connection + has data to be read + */ + if (FD_ISSET(cp->fd, &readfd)) { +READ_MORE: + /* Get the ssl buffer and how much data it can accept */ + /* Note 0 is a return failure, unlike with matrixSslGetOutdata */ + if ((len = matrixSslGetReadbuf(cp->ssl, &buf)) <= 0) { + closeConn(cp, PS_ARG_FAIL); + continue; /* Next connection */ + } + if ((transferred = (int32)recv(cp->fd, buf, len, MSG_DONTWAIT)) < 0) { + /* We could get EWOULDBLOCK despite the FD_ISSET on goto */ +#ifdef WIN32 + if (SOCKET_ERRNO != EWOULDBLOCK && + SOCKET_ERRNO != WSAEWOULDBLOCK) { + +#else + if (SOCKET_ERRNO != EWOULDBLOCK) { +#endif + closeConn(cp, PS_PLATFORM_FAIL); + } + continue; /* Next connection */ + } + + /* If EOF, remote socket closed. This is semi-normal closure. + Officially, we should close on closure alert. */ + if (transferred == 0) { +/* psTraceIntInfo("Closing connection %d on EOF\n", cp->fd); */ + closeConn(cp, 0); + continue; /* Next connection */ + } +/* + Notify SSL state machine that we've received more data into the + ssl buffer retreived with matrixSslGetReadbuf. + */ + if ((rc = matrixSslReceivedData(cp->ssl, (int32)transferred, &buf, + (uint32*)&len)) < 0) { + closeConn(cp, 0); + continue; /* Next connection */ + } + /* Update activity time */ + psGetTime(&cp->time, NULL); + +PROCESS_MORE: + /* Process any incoming plaintext application data */ + switch (rc) { + case MATRIXSSL_HANDSHAKE_COMPLETE: + g_handshakes++; + /* If the protocol is server initiated, send data here */ + goto READ_MORE; + case MATRIXSSL_APP_DATA: + case MATRIXSSL_APP_DATA_COMPRESSED: + //psTraceBytes("DATA", buf, len); + + /* First test to see if this is one of the special data + requests used for testing. + + First is a "GET /bytes?" format + */ + specialAppData = 0; + if (len > 11 && + strncmp((char *)buf, "GET /bytes?", 11) == 0) { + cp->bytes_requested = atoi((char *)buf + 11); + if (cp->bytes_requested < + strlen((char *)g_httpResponseHdr) || + cp->bytes_requested > 1073741824) { + cp->bytes_requested = + (uint32)strlen((char *)g_httpResponseHdr); + } + cp->bytes_sent = 0; + specialAppData = 1; + } + /* A special test for TLS 1.0 where BEAST workaround used */ + if (len > 10 && + strncmp((char *)buf, "ET /bytes?", 10) == 0) { + cp->bytes_requested = atoi((char *)buf + 10); + if (cp->bytes_requested < + strlen((char *)g_httpResponseHdr) || + cp->bytes_requested > 1073741824) { + cp->bytes_requested = + (uint32)strlen((char *)g_httpResponseHdr); + } + cp->bytes_sent = 0; + specialAppData = 1; + } + /* Shutdown the server */ + if (len >= 15 && + strncmp((char*)buf, "MATRIX_SHUTDOWN", 15) == 0) { + g_exitFlag = 1; + matrixSslEncodeClosureAlert(cp->ssl); + _psTrace("Got MATRIX_SHUTDOWN. Exiting\n"); + goto WRITE_MORE; + } + + if (specialAppData == 0) { + if ((rc = httpBasicParse(cp, buf, len, 0)) < 0) { + _psTrace("Couldn't parse HTTP data. Closing...\n"); + closeConn(cp, PS_PROTOCOL_FAIL); + continue; /* Next connection */ + } + } + + if (rc == HTTPS_COMPLETE || specialAppData == 1) { + if (httpWriteResponse(cp) < 0) { + closeConn(cp, PS_PROTOCOL_FAIL); + continue; /* Next connection */ + } + /* For HTTP, we assume no pipelined requests, so we + close after parsing a single HTTP request */ + /* Ignore return of closure alert, it's optional */ +#ifdef SEND_CLOSURE_ALERT +// matrixSslEncodeClosureAlert(cp->ssl); +#endif + rc = matrixSslProcessedData(cp->ssl, &buf, (uint32*)&len); + if (rc > 0) { + /* Additional data is available, but we ignore it */ + _psTrace("HTTP data parsing not supported, ignoring.\n"); + closeConn(cp, PS_SUCCESS); + continue; /* Next connection */ + } else if (rc < 0) { + closeConn(cp, PS_PROTOCOL_FAIL); + continue; /* Next connection */ + } + /* rc == 0, write out our response and closure alert */ + goto WRITE_MORE; + } + /* We processed a partial HTTP message */ + if ((rc = matrixSslProcessedData(cp->ssl, &buf, (uint32*)&len)) == 0) { + goto READ_MORE; + } + goto PROCESS_MORE; + case MATRIXSSL_REQUEST_SEND: + /* Prevent us from reading again after the write, + although that wouldn't be the end of the world */ + FD_CLR(cp->fd, &readfd); + if (wSanity++ < GOTO_SANITY) goto WRITE_MORE; + break; + case MATRIXSSL_REQUEST_RECV: + if (rSanity++ < GOTO_SANITY) goto READ_MORE; + break; + case MATRIXSSL_RECEIVED_ALERT: + /* The first byte of the buffer is the level */ + /* The second byte is the description */ + if (*buf == SSL_ALERT_LEVEL_FATAL) { + psTraceIntInfo("Fatal alert: %d, closing connection.\n", + *(buf + 1)); + closeConn(cp, PS_PROTOCOL_FAIL); + continue; /* Next connection */ + } + /* Closure alert is normal (and best) way to close */ + if (*(buf + 1) == SSL_ALERT_CLOSE_NOTIFY) { + closeConn(cp, PS_SUCCESS); + continue; /* Next connection */ + } + psTraceIntInfo("Warning alert: %d\n", *(buf + 1)); + if ((rc = matrixSslProcessedData(cp->ssl, &buf, (uint32*)&len)) == 0) { + /* No more data in buffer. Might as well read for more. */ + goto READ_MORE; + } + goto PROCESS_MORE; + + default: + /* If rc <= 0 we fall here */ + closeConn(cp, PS_PROTOCOL_FAIL); + continue; /* Next connection */ + } + /* Always try to read more if we processed some data */ + if (rSanity++ < GOTO_SANITY) goto READ_MORE; + } /* readfd handling */ + } /* connection loop */ + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Create an HTTP response and encode it to the SSL buffer + */ +#define TEST_SIZE 16000 +static int32 httpWriteResponse(httpConn_t *cp) +{ + unsigned char *buf; + ssl_t *ssl; + int32 available, len, rc; + + + ssl = cp->ssl; + /* The /bytes? HTTP request assigns bytes_requested */ + if (cp->bytes_requested) { + /* + Generate TLS records for all the requested bytes. + This can put a lot of data in ssl outbuf, so we attempt + to flush it out at the bottom of the loop. + Anything left over will be sent out in the main server loop. + */ + while (cp->bytes_sent < cp->bytes_requested) { + len = cp->bytes_requested - cp->bytes_sent; + if (len > RESPONSE_REC_LEN) { + len = RESPONSE_REC_LEN; + } + psAssert(len > 0); + rc = matrixSslGetWritebuf(ssl, &buf, len); + if (rc < len) { + len = rc; /* could have been shortened due to max_frag */ + } + memset(buf, 'J', len); + if (cp->bytes_sent == 0) { + /* Overwrite first N bytes with HTTP header the first time */ + strncpy((char *)buf, (char *)g_httpResponseHdr, + strlen((char*)g_httpResponseHdr)); + } + if ((rc = matrixSslEncodeWritebuf(ssl, len)) < 0) { + printf("couldn't encode data %d\n", rc); + } + cp->bytes_sent += len; + /* + Do a quick, non-blocking send here to start flushing the + generated records. We could flush after each record encode, + or only on a multiple of record encodes. + */ + if ((len = matrixSslGetOutdata(ssl, &buf)) > (RESPONSE_REC_LEN * 4)) { + if ((len = (int32)send(cp->fd, buf, len, MSG_DONTWAIT)) > 0) { + rc = matrixSslSentData(ssl, len); +// psAssert(rc != MATRIXSSL_REQUEST_SEND); /* Some data remains */ + } +// psAssert(len > 0); /* Probably an EWOULDBLOCK */ + } + } + return MATRIXSSL_REQUEST_SEND; + } + + /* Usual reply */ + if ((available = matrixSslGetWritebuf(ssl, &buf, + (uint32)strlen((char *)g_httpResponseHdr) + 1)) < 0) { + return PS_MEM_FAIL; + } + strncpy((char *)buf, (char *)g_httpResponseHdr, available); + //psTraceBytes("Replying", buf, (uint32)strlen((char *)buf)); + if (matrixSslEncodeWritebuf(ssl, (uint32)strlen((char *)buf)) < 0) { + return PS_MEM_FAIL; + } + return MATRIXSSL_REQUEST_SEND; +} + +static void usage(void) +{ + printf( "This application takes no runtime parameters.\n" + "Configuration is through defines in the source.\n"); +} + +/******************************************************************************/ +/* + Main non-blocking SSL server + Initialize MatrixSSL and sockets layer, and loop on select + */ +int32 main(int32 argc, char **argv) +{ + SOCKET lfd; + int32 err, rc; +#ifdef WIN32 + WSADATA wsaData; +#endif + char certpath[FILENAME_MAX]; + char keypath[FILENAME_MAX]; + sslKeys_t *keys = NULL; + + if (argc > 1) { + usage(); + return 0; + } + +#ifdef WIN32 + WSAStartup(MAKEWORD(1, 1), &wsaData); +#endif + + + DLListInit(&g_conns); + g_exitFlag = 0; + lfd = INVALID_SOCKET; + +#ifdef POSIX + if (sighandlers() < 0) { + return PS_PLATFORM_FAIL; + } +#endif /* POSIX */ + + if ((rc = matrixSslOpen()) < 0) { + _psTrace("MatrixSSL library init failure. Exiting\n"); + return rc; + } + + + if (matrixSslNewKeys(&keys, NULL) < 0) { + return -1; + } + snprintf(certpath, FILENAME_MAX - 1, "%s/%s", KEY_DIR, certFile); + snprintf(keypath, FILENAME_MAX - 1, "%s/%s", KEY_DIR, privkeyFile); + if ((rc = matrixSslLoadRsaKeys(keys, certpath, keypath, NULL, NULL)) < 0) { + _psTrace("Unable to load static key material. Exiting\n"); + return rc; + } + +#ifdef REQUIRE_DH_PARAMS + snprintf(certpath, FILENAME_MAX - 1, "%s/%s", KEY_DIR, dhParamFile); + if ((rc = matrixSslLoadDhParams(keys, certpath)) < 0) { + _psTrace("Unable to load static key material. Exiting\n"); + return rc; + } +#endif + + /* Create the listening socket that will accept incoming connections */ + if ((lfd = lsocketListen(HTTPS_PORT, &err)) == INVALID_SOCKET) { + _psTraceInt("Can't listen on port %d\n", HTTPS_PORT); + goto L_EXIT; + } + + /* Main select loop to handle sockets events */ + while (!g_exitFlag) { + selectLoop(keys, lfd); + displayStats(); + } + +L_EXIT: + if (lfd != INVALID_SOCKET) close(lfd); + matrixSslClose(); + + return 0; +} + +/******************************************************************************/ +/* + Close a socket and free associated SSL context and buffers + */ +static void closeConn(httpConn_t *cp, int32 reason) +{ +#ifdef SEND_CLOSURE_ALERT + unsigned char *buf; +#endif + int32 len; + + DLListRemove(&cp->List); +#ifdef SEND_CLOSURE_ALERT + /* Quick attempt to send a closure alert, don't worry about failure */ + if (matrixSslEncodeClosureAlert(cp->ssl) >= 0) { + if ((len = matrixSslGetOutdata(cp->ssl, &buf)) > 0) { + //psTraceBytes("closure alert", buf, len); + if ((len = (int32)send(cp->fd, buf, len, MSG_DONTWAIT)) > 0) { + matrixSslSentData(cp->ssl, len); + } + } + } +#endif + if (cp->parsebuf != NULL) { + psAssert(cp->parsebuflen > 0); + free(cp->parsebuf); + cp->parsebuflen = 0; + } + + matrixSslDeleteSession(cp->ssl); + + if (cp->fd != INVALID_SOCKET) { + close(cp->fd); + } + if (reason >= 0) { +/* _psTraceInt("=== Closing Client %d ===\n", cp->fd); */ + } else { + _psTraceInt("=== Closing Client %d on Error ===\n", cp->fd); + } + free(cp); +} + +/******************************************************************************/ +/* + Establish a listening socket for incomming connections + */ +static SOCKET lsocketListen(short port, int32 *err) +{ + struct sockaddr_in addr; + SOCKET fd; + + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { + _psTrace("Error creating listen socket\n"); + *err = SOCKET_ERRNO; + return INVALID_SOCKET; + } + + setSocketOptions(fd); + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = INADDR_ANY; + if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + _psTrace("Can't bind socket. Port in use or insufficient privilege\n"); + *err = SOCKET_ERRNO; + return INVALID_SOCKET; + } + if (listen(fd, SOMAXCONN) < 0) { + _psTrace("Error listening on socket\n"); + *err = SOCKET_ERRNO; + return INVALID_SOCKET; + } + _psTraceInt("Listening on port %d\n", port); + return fd; +} + +/******************************************************************************/ +/* + Make sure the socket is not inherited by exec'd processes + Set the REUSE flag to minimize the number of sockets in TIME_WAIT + Then we set REUSEADDR, NODELAY and NONBLOCK on the socket +*/ +static void setSocketOptions(SOCKET fd) +{ + int32 rc; + +#ifdef POSIX + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif + rc = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc)); +#ifdef POSIX + rc = 1; + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&rc, sizeof(rc)); + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); +#elif defined(WIN32) + rc = 1; /* 1 for non-block, 0 for block */ + ioctlsocket(fd, FIONBIO, &rc); +#endif +#ifdef __APPLE__ /* MAC OS X */ + rc = 1; + setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&rc, sizeof(rc)); +#endif +} + +#ifdef POSIX +/******************************************************************************/ +/* + Handle some signals on POSIX platforms + Lets ctrl-c do a clean exit of the server. + */ +static int32 sighandlers(void) +{ + if (signal(SIGINT, sigintterm_handler) == SIG_ERR || + signal(SIGTERM, sigintterm_handler) == SIG_ERR || + signal(SIGPIPE, SIG_IGN) == SIG_ERR || + signal(SIGSEGV, sigsegv_handler) == SIG_ERR) { + return PS_PLATFORM_FAIL; + } + return 0; +} + +/* Warn on segmentation violation */ +static void sigsegv_handler(int unused) +{ + printf("Segfault! Please report this as a bug to support@peersec.com\n"); + exit(EXIT_FAILURE); +} + +/* catch ctrl-c or sigterm */ +static void sigintterm_handler(int unused) +{ + g_exitFlag = 1; /* Rudimentary exit flagging */ + printf("Exiting due to interrupt.\n"); +} +#endif /* POSIX */ + + +#else + +/******************************************************************************/ +/* + Stub main for compiling without server enabled +*/ +int32 main(int32 argc, char **argv) +{ + printf("USE_SERVER_SIDE_SSL must be enabled in matrixsslConfig.h at build" \ + " time to run this application\n"); + return -1; +} +#endif /* USE_SERVER_SIDE_SSL */ + +/******************************************************************************/ + diff --git a/common.mk b/common.mk new file mode 100755 index 0000000..893aa01 --- /dev/null +++ b/common.mk @@ -0,0 +1,291 @@ +## +# Common Makefile definitions. +# Copyright (c) 2013-2016 INSIDE Secure Corporation. All Rights Reserved. +# +#------------------------------------------------------------------------------- + +#------------------------------------------------------------------------------- +## Makefile variables that must be defined in this file +# @param[out] $(BUILD) Set here for release or debug +BUILD:=release ##< Release build strips binary and optimizes +#BUILD:=debug ##< Debug build keeps debug symbols and disables compiler optimizations. Assembly language optimizations remain enabled + +#------------------------------------------------------------------------------- +## Makefile variables that are read by this file. +# @param[in] $(MATRIXSSL_ROOT) Must be set to root MatrixSSL directory +# @param[in] $(CC) Used to determine the target platform, which will differ +# from host if cross compiling. +# @param[in] $(CPU) If set, should be the target cpu for the compiler, +# suitable for the '-mcpu=' flag. See 'gcc --help=target' for valid values. +# @param[in] $(SRC) List of source files to be compiled. Used to make $(OBJS), +# the list of object files to build. + +#------------------------------------------------------------------------------- +## Makefile variables that are modified by this file +# @param[in,out] $(CFLAGS) Appended with many options as determined by this file, to be passed to compiler +# @param[in,out] $(LDFLAGS) Appended with many options as determined by this file, to be passed to linker + +#------------------------------------------------------------------------------- +## Makefile variables that are created by this file +# @param[out] $(OSDEP) Set to platform code directory (./core/$OSDEP/osdep.c), based on $(CC) +# @param[out] $(CCARCH) Set to compiler's target architecture, based on $(CC) +# @param[out] $(STRIP) Set to the executable to use to strip debug symbols from executables +# @param[out] $(STROPS) Human readable description of relevant MatrixSSL compile options. +# @param[out] $(O) Set to the target platform specific object file extension +# @param[out] $(A) Set to the target phatform specific static library (archive) file extension +# @param[out] $(E) Set to the target platform specific executable file extension +# @param[out] $(OBJS) Set to the list of objects that is to be built + +#------------------------------------------------------------------------------- + +## Auto-detect cross compiler for some platforms based on environment variables + +## Based on the value of CC, determine the target, eg. +# x86_64-redhat-linux +# i686-linux-gnu +# x86_64-apple-darwin14.0.0 +# arm-linux-gnueabi +# arm-linux-gnueabihf +# arm-none-eabi +# mips-linux-gnu +# mipsisa64-octeon-elf-gcc +# powerpc-linux-gnu +CCARCH:=$(shell $(CC) -v 2>&1 | sed -n '/Target: / s/// p') +CCVER:=$(shell $(CC) --version 2>&1) +STROPTS:="Built for $(CCARCH)" + +## uname of the Host environment, eg. +# Linux +# Darwin +# @note Unused +#UNAME:=$(shell uname) + +## Standard file extensions for Linux/OS X. +O:=.o +A:=.a +E= + +# Check if this version of make supports undefine +ifneq (,$(findstring undefine,$(.FEATURES))) + HAVE_UNDEFINE:=1 +endif + +#On OS X, Xcode sets CURRENT_VARIANT to normal, debug or profile +ifneq (,$(findstring -apple,$(CCARCH))) + ifneq (,$(findstring ebug,$(CONFIGURATION))) + MATRIX_DEBUG:=1 + endif +endif + +#Manually enable debug here +#MATRIX_DEBUG:=1 + +ifdef MATRIX_DEBUG + OPT:=-O0 -g -DDEBUG -Wall + #OPT+=-Wconversion + STRIP:=test # no-op +else + ifneq (,$(findstring -none,$(CCARCH))) + OPT:=-Os -Wall # Compile bare-metal for size + else + OPT:=-O3 -Wall # Compile all others for speed + endif + STRIP:=strip +endif +CFLAGS+=$(OPT) + +# Detect multicore and do parallel build. Uncomment if desired +#ifneq (,$(findstring -linux,$(CCARCH))) +# JOBS:=-j$(shell grep -ic processor /proc/cpuinfo) +#else ifneq (,$(findstring apple,$(CCARCH))) +# JOBS:=-j$(shell sysctl -n machdep.cpu.thread_count) +#endif + +default: $(BUILD) + +debug: + @$(MAKE) compile "MATRIX_DEBUG=1" + +release: + @$(MAKE) $(JOBS) compile + +# 64 Bit Intel Target +ifneq (,$(findstring x86_64-,$(CCARCH))) + CFLAGS+=-m64 + STROPTS+=", 64-bit Intel RSA/ECC ASM" + # Enable AES-NI if the host supports it (assumes Host is Target) + ifneq (,$(findstring -linux,$(CCARCH))) + ifeq ($(shell grep -o -m1 aes /proc/cpuinfo),aes) + CFLAGS+=-maes -mpclmul -msse4.1 + STROPTS+=", AES-NI ASM" + endif + else ifneq (,$(findstring apple,$(CCARCH))) + ifeq ($(shell sysctl -n hw.optional.aes),1) + CFLAGS+=-maes -mpclmul -msse4.1 + STROPTS+=", AES-NI ASM" + endif + endif + +# 32 Bit Intel Edison Target +else ifneq (,$(findstring i586-,$(CCARCH))) + CFLAGS+=-m32 + ifneq (,$(findstring edison,$(shell uname -n))) + ifneq (,$(findstring -O3,$(OPT))) + #Edison does not like -O3 + OPT:=-O2 + endif + CFLAGS+=-DEDISON -maes -mpclmul -msse4.1 + STROPTS+=", 32-bit Intel RSA/ECC ASM, AES-NI ASM, Intel Edison" + else + STROPTS+=", 32-bit Intel RSA/ECC ASM" + endif + +# 32 Bit Intel Target +else ifneq (,$(findstring i686-,$(CCARCH))) + CFLAGS+=-m32 + STROPTS+=", 32-bit Intel RSA/ECC ASM" + +# MIPS Target +else ifneq (,$(findstring mips-,$(CCARCH))) + STROPTS+=", 32-bit MIPS RSA/ECC ASM" + +# MIPS64 Target +else ifneq (,$(filter mips%64-,$(CCARCH))) +# STROPTS+=", 64-bit MIPS64 RSA/ECC ASM" + +# ARM Target +else ifneq (,$(findstring arm,$(CCARCH))) + STROPTS+=", 32-bit ARM RSA/ECC ASM" + ifneq (,$(findstring linux-,$(CCARCH))) + HARDWARE:=$(shell sed -n '/Hardware[ \t]*: / s/// p' /proc/cpuinfo) + # Raspberry Pi Host and Target + ifneq (,$(findstring BCM2708,$(HARDWARE))) + CFLAGS+=-DRASPBERRYPI -mfpu=vfp -mfloat-abi=hard -ffast-math -march=armv6zk -mtune=arm1176jzf-s + STROPTS+=", Raspberry Pi" + endif + # Raspberry Pi 2 Host and Target + ifneq (,$(findstring BCM2709,$(HARDWARE))) + ifneq (,$(findstring 4.6,$(CCVER))) + CFLAGS+=-march=armv7-a + else + # Newer gcc (4.8+ supports this cpu type) + CFLAGS+=-mcpu=cortex-a7 + endif + CFLAGS+=-DRASPBERRYPI2 -mfpu=neon-vfpv4 -mfloat-abi=hard + STROPTS+=", Raspberry Pi2" + endif + # Beagleboard/Beaglebone Host and Target + ifneq (,$(findstring AM33XX,$(HARDWARE))) + CFLAGS+=-BEAGLEBOARD -mfpu=neon -mfloat-abi=hard -ffast-math -march=armv7-a -mtune=cortex-a8 + STROPTS+=", Beagleboard" + endif + # Samsung Exynos 5 (Can also -mtune=cortex-a15 or a8) + ifneq (,$(findstring EXYNOS5,$(HARDWARE))) + CFLAGS+=-DEXYNOS5 -mfpu=neon -mfloat-abi=hard -ffast-math -march=armv7-a + STROPTS+=", Exynos 5" + endif + ifdef HAVE_UNDEFINE + undefine HARDWARE + endif + endif + +endif + +ifdef MATRIX_DEBUG +CFLAGS+=-ffunction-sections -fdata-sections +else +CFLAGS+=-ffunction-sections -fdata-sections -fomit-frame-pointer +endif + +# If we're using clang (it may be invoked via 'cc' or 'gcc'), +# handle minor differences in compiler behavior vs. gcc +ifneq (,$(findstring clang,$(CCVER))) + CFLAGS+=-Wno-error=unused-variable -Wno-error=\#warnings -Wno-error=\#pragma-messages +endif + +# Handle differences between the OS X ld and GNU ld +ifneq (,$(findstring -apple,$(CCARCH))) + LDFLAGS+=-Wl,-dead_strip +else + LDFLAGS+=-Wl,--gc-sections +endif + +CFLAGS+=-I$(MATRIXSSL_ROOT) + +#OPENSSL +#PS_OPENSSL:=1 +ifdef PS_OPENSSL + OPENSSL_ROOT:=/opt/openssl-1.0.2d + ifdef OPENSSL_ROOT + # Statically link against a given openssl tree + CFLAGS+=-I$(OPENSSL_ROOT)/include + LDFLAGS+=$(OPENSSL_ROOT)/libcrypto.a -ldl + else ifneq (,$(findstring -apple,$(CCARCH))) + # Dynamically link against the sytem default openssl tree + # Apple has deprecated the built in openssl, so supress warnings here + CFLAGS+=-Wno-error=deprecated-declarations -Wno-deprecated-declarations + LDFLAGS+=-lcrypto + else ifneq (,$(findstring -linux,$(CCARCH))) + # Dynamically link against the sytem default openssl tree + LDFLAGS+=-lcrypto + else + $(error Please define OPENSSL_ROOT) + endif + CFLAGS+=-DUSE_OPENSSL_CRYPTO + STROPTS+=", USE_OPENSSL_CRYPTO" +endif +#OPENSSL + +#LIBSODIUM +#PS_LIBSODIUM:=1 +ifdef PS_LIBSODIUM + LIBSODIUM_ROOT:=/opt/libsodium-1.0.10/src/libsodium + ifdef LIBSODIUM_ROOT + # Statically link against a given libsodium + CFLAGS+=-I$(LIBSODIUM_ROOT)/include + LDFLAGS+=$(LIBSODIUM_ROOT)/.libs/libsodium.a + else + $(error Please define LIBSODIUM_ROOT) + endif + CFLAGS+=-DUSE_LIBSODIUM_CRYPTO + STROPTS+=", USE_LIBSODIUM_CRYPTO" +endif +#LIBSODIUM + +# Linux Target +ifneq (,$(findstring -linux,$(CCARCH))) + OSDEP:=POSIX + #For USE_HIGHRES_TIME + LDFLAGS+=-lrt + +# OS X Target +else ifneq (,$(findstring -apple,$(CCARCH))) + OSDEP:=POSIX + CFLAGS+=-isystem -I/usr/include + +# Bare Metal / RTOS Target +else ifneq (,$(findstring -none,$(CCARCH))) + OSDEP:=METAL + CFLAGS+=-fno-exceptions -fno-unwind-tables -fno-non-call-exceptions -fno-asynchronous-unwind-tables -ffreestanding -fno-builtin -nostartfiles + ifneq (,$(findstring cortex-,$(CPU))) + CFLAGS+=-mthumb -mcpu=$(CPU) -mslow-flash-data + ifeq (cortex-m4,$(CPU)) + CFLAGS+=-mcpu=cortex-m4 -mtune=cortex-m4 + else ifeq (cortex-m3,$(CPU)) + CFLAGS+=-mcpu=cortex-m3 -mtune=cortex-m3 -mfpu=vpf + else ifeq (cortex-m0,$(CPU)) + CFLAGS+=-mcpu=cortex-m0 -mtune=cortex-m0 -mfpu=vpf + endif + endif +endif + +# This must be defined after OSDEP, because core/Makefile uses OSDEP in SRC +OBJS=$(SRC:.c=.o) $(SRC:.S:*.o) + +# Remove extra spaces in CFLAGS +#CFLAGS=$(strip $(CFLAGS)) + +# Display the precompiler defines for the current build settings +defines: + :| $(CC) $(CFLAGS) -dM -E -x c - + diff --git a/core/Makefile b/core/Makefile new file mode 100755 index 0000000..c431cf4 --- /dev/null +++ b/core/Makefile @@ -0,0 +1,44 @@ +# +# Makefile for core static library +# +# Copyright (c) 2013-2016 INSIDE Secure Corporation. All Rights Reserved. +# + +MATRIXSSL_ROOT:=.. +include $(MATRIXSSL_ROOT)/common.mk + +SRC:=\ + memset_s.c \ + corelib.c \ + $(OSDEP)/osdep.c + + + +ASM:=memset_s.s + +# Generated files +STATIC:=libcore_s.a + +all: compile + +compile: $(ASM) $(OBJS) $(STATIC) + +# Special rule to build memset_s function without optimization +memset_s.o: memset_s.c + $(CC) -O0 -Wall -ffunction-sections -fdata-sections -o $@ -c $< + +# Generate the (.s) assembly file to verify zero is being performed +$(ASM): memset_s.c + $(CC) -O0 -g -fverbose-asm -S $< + +# Additional Dependencies +$(OBJS): $(MATRIXSSL_ROOT)/common.mk Makefile *.h + +# Build the static library +# Redirect stderr to null so we don't see the 'empty file' warnings +$(STATIC): $(OBJS) + $(AR) -rcuv $@ $^ 2>/dev/null + +clean: + rm -f $(STATIC) $(OBJS) $(ASM) + diff --git a/core/POSIX/osdep.c b/core/POSIX/osdep.c new file mode 100644 index 0000000..9135657 --- /dev/null +++ b/core/POSIX/osdep.c @@ -0,0 +1,509 @@ +/** + * @file osdep.c + * @version $Format:%h%d$ + * + * POSIX layer. + * Mac OSX 10.5 + * Linux + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../coreApi.h" + +#ifdef POSIX +/******************************************************************************/ +/* + Universal system POSIX headers and then PScore/coreApi.h + OS-specific header includes should be added to PScore/osdep.h +*/ +#include /* abort() */ +#include /* open(), O_RDONLY, ect... */ +#include /* close() */ +#include /* errno */ +#include /* gettimeofday */ + +/******************************************************************************/ +/* + TIME FUNCTIONS +*/ +#ifndef USE_HIGHRES_TIME +/******************************************************************************/ +/* + Module open and close +*/ +int osdepTimeOpen(void) +{ + psTime_t lt; +/* + Just a check that gettimeofday is functioning +*/ + if (gettimeofday(<, NULL) < 0) { + return PS_FAILURE; + } + return PS_SUCCESS; +} + +void osdepTimeClose(void) +{ +} + +/* + PScore Public API implementations + + This function always returns seconds/ticks AND OPTIONALLY populates + whatever psTime_t happens to be on the given platform. +*/ +int32 psGetTime(psTime_t *t, void *userPtr) +{ + psTime_t lt; + + if (t == NULL) { + if (gettimeofday(<, NULL) < 0) { + return PS_FAILURE; + } + return lt.tv_sec; + } + + if (gettimeofday(t, NULL) < 0) { + return PS_FAILURE; + } + return t->tv_sec; +} + +int32 psDiffMsecs(psTime_t then, psTime_t now, void *userPtr) +{ + if (now.tv_usec < then.tv_usec) { + now.tv_sec--; + now.tv_usec += 1000000; /* borrow 1 second worth of usec */ + } + return (int32)((now.tv_sec - then.tv_sec) * 1000) + + ((now.tv_usec - then.tv_usec)/ 1000); +} + +int32 psCompareTime(psTime_t a, psTime_t b, void *userPtr) +{ +/* + Time comparison. 1 if 'a' is less than or equal. 0 if 'a' is greater +*/ + if (a.tv_sec < b.tv_sec) { + return 1; + } + if (a.tv_sec == b.tv_sec && a.tv_usec <= b.tv_usec) { + return 1; + } + return 0; +} + +#else /* USE_HIGHRES_TIME */ +/******************************************************************************/ +#ifdef __APPLE__ +/* MAC OS X */ + +#include + +static mach_timebase_info_data_t hiresFreq; + +int osdepTimeOpen(void) +{ + mach_timebase_info(&hiresFreq); + return PS_SUCCESS; +} + +void osdepTimeClose(void) +{ +} + +int32 psGetTime(psTime_t *t, void *userPtr) +{ + psTime_t lt; + + if (t == NULL) { + t = < + } + *t = mach_absolute_time(); + return (int32)((*t * hiresFreq.numer) / (hiresFreq.denom * 1000000000L)); +} + +int32 psDiffMsecs(psTime_t then, psTime_t now, void *userPtr) +{ + return (int32)(((now - then) * hiresFreq.numer) / (hiresFreq.denom * 1000000)); +} + +int64_t psDiffUsecs(psTime_t then, psTime_t now) +{ + return (int64_t)(((now - then) * hiresFreq.numer) / (hiresFreq.denom * 1000)); +} + +int32 psCompareTime(psTime_t a, psTime_t b, void *userPtr) +{ + return a <= b ? 1 : 0; +} + +/******************************************************************************/ +#else /* !APPLE, !tile */ +/******************************************************************************/ +/* LINUX */ +int osdepTimeOpen(void) +{ + return PS_SUCCESS; +} + +void osdepTimeClose(void) +{ +} + +int32 psGetTime(psTime_t *t, void *userPtr) +{ + psTime_t lt; + + if (t == NULL) { + t = < + } + clock_gettime(CLOCK_MONOTONIC, t); + return t->tv_sec; +} + +int32 psDiffMsecs(psTime_t then, psTime_t now, void *userPtr) +{ + if (now.tv_nsec < then.tv_nsec) { + now.tv_sec--; + now.tv_nsec += 1000000000L; /* borrow 1 second worth of nsec */ + } + return (int32)((now.tv_sec - then.tv_sec) * 1000) + + ((now.tv_nsec - then.tv_nsec)/ 1000000); +} + +int64_t psDiffUsecs(psTime_t then, psTime_t now) +{ + if (now.tv_nsec < then.tv_nsec) { + now.tv_sec--; + now.tv_nsec += 1000000000L; /* borrow 1 second worth of nsec */ + } + return (int32)((now.tv_sec - then.tv_sec) * 1000) + + ((now.tv_nsec - then.tv_nsec)/ 1000); +} + +int32 psCompareTime(psTime_t a, psTime_t b, void *userPtr) +{ + /* Time comparison. 1 if 'a' is less than or equal. 0 if 'a' is greater */ + if (a.tv_sec < b.tv_sec) { + return 1; + } + if (a.tv_sec == b.tv_sec && a.tv_nsec <= b.tv_nsec) { + return 1; + } + return 0; +} +#endif /* !APPLE */ + +#endif /* USE_HIGHRES_TIME */ + +/******************************************************************************/ + +#ifdef USE_MULTITHREADING +/******************************************************************************/ +/* + MUTEX FUNCTIONS +*/ +/******************************************************************************/ +static pthread_mutexattr_t attr; +/* + Module open and close +*/ +int osdepMutexOpen(void) +{ + int32 rc; + + if ((rc = pthread_mutexattr_init(&attr)) < 0) { + psErrorInt("pthread_mutexattr_init failed %d\n", rc); + return PS_PLATFORM_FAIL; + } + return PS_SUCCESS; +} + +int osdepMutexClose(void) +{ + if (pthread_mutexattr_destroy(&attr) != 0) { + psTraceCore("pthread_mutex_destroy failed\n"); + } + return PS_SUCCESS; +} + +/* + PScore Public API implementations +*/ +int32 psCreateMutex(psMutex_t *mutex) +{ + int32 err; + + if ((err = pthread_mutex_init(mutex, &attr)) != 0) { + psTraceIntCore("pthread_mutex_init failed %d\n", err); + return PS_PLATFORM_FAIL; + } + return PS_SUCCESS; +} + +int32 psLockMutex(psMutex_t *mutex) +{ + if (pthread_mutex_lock(mutex) != 0) { + psTraceCore("pthread_mutex_lock failed\n"); + return PS_PLATFORM_FAIL; + } + return PS_SUCCESS; +} + +int32 psUnlockMutex(psMutex_t *mutex) +{ + if (pthread_mutex_unlock(mutex) != 0) { + psTraceCore("pthread_mutex_unlock failed\n"); + return PS_PLATFORM_FAIL; + } + return PS_SUCCESS; +} + +void psDestroyMutex(psMutex_t *mutex) +{ + pthread_mutex_destroy(mutex); +} +#endif /* USE_MULTITHREADING */ +/******************************************************************************/ + + +/******************************************************************************/ +/* + ENTROPY FUNCTIONS +*/ +/******************************************************************************/ +#define MAX_RAND_READS 1024 + +static int32 urandfd = -1; +static int32 randfd = -1; +/* + Module open and close +*/ +int osdepEntropyOpen(void) +{ +/* + Open /dev/random access non-blocking. +*/ + if ((urandfd = open("/dev/urandom", O_RDONLY)) < 0) { + psErrorInt("open of urandom failed %d\n", urandfd); + return PS_PLATFORM_FAIL; + } +/* + For platforms that don't have /dev/random, just assign it to urandom +*/ + if ((randfd = open("/dev/random", O_RDONLY | O_NONBLOCK)) < 0) { + randfd=urandfd; + } + return PS_SUCCESS; +} + +void osdepEntropyClose(void) +{ + if (randfd != urandfd) { + close(randfd); + } + close(urandfd); +} + +/* + PScore Public API implementations +*/ +int32 psGetEntropy(unsigned char *bytes, uint32 size, void *userPtr) +{ +/* + Read from /dev/random non-blocking first, then from urandom if it would + block. Also, handle file closure case and re-open. +*/ + int32 rc, sanity, retry, readBytes; + unsigned char *where = bytes; + + sanity = retry = rc = readBytes = 0; + + while (size) { + if ((rc = read(randfd, where, size)) < 0 || sanity > MAX_RAND_READS) { + if (errno == EINTR) { + if (sanity > MAX_RAND_READS) { + psTraceCore("psGetEntropy failed randfd sanity\n"); + return PS_PLATFORM_FAIL; + } + sanity++; + continue; + } else if (errno == EAGAIN) { + break; + } else if (errno == EBADF && retry == 0) { + close(randfd); + if ((randfd = open("/dev/random", O_RDONLY | O_NONBLOCK)) < 0) { + break; + } + retry++; + continue; + } else { + break; + } + } + readBytes += rc; + where += rc; + size -= rc; + } + + sanity = retry = 0; + while (size) { + if ((rc = read(urandfd, where, size)) < 0 || sanity > MAX_RAND_READS) { + if (errno == EINTR) { + if (sanity > MAX_RAND_READS) { + psTraceCore("psGetEntropy failed urandfd sanity\n"); + return PS_PLATFORM_FAIL; + } + sanity++; + continue; + } else if (errno == EBADF && retry == 0) { + close(urandfd); + if ((urandfd = + open("/dev/urandom", O_RDONLY | O_NONBLOCK)) < 0) { + psTraceCore("psGetEntropy failed urandom open\n"); + return PS_PLATFORM_FAIL; + } + retry++; + continue; + } else { + psTraceIntCore("psGetEntropy fail errno %d\n", errno); + return PS_PLATFORM_FAIL; + } + } + readBytes += rc; + where += rc; + size -= rc; + } + return readBytes; +} +/******************************************************************************/ + + +/******************************************************************************/ +/* + RAW TRACE FUNCTIONS +*/ +/******************************************************************************/ + +int osdepTraceOpen(void) +{ + return PS_SUCCESS; +} + +void osdepTraceClose(void) +{ +} + +void _psTrace(const char *msg) +{ + printf("%s", msg); +} + +/* message should contain one %s, unless value is NULL */ +void _psTraceStr(const char *message, const char *value) +{ + if (value) { + printf(message, value); + } else { + printf("%s", message); + } +} + +/* message should contain one %d */ +void _psTraceInt(const char *message, int32 value) +{ + printf(message, value); +} + +/* message should contain one %p */ +void _psTracePtr(const char *message, const void *value) +{ + printf(message, value); +} + +/******************************************************************************/ + +#ifdef HALT_ON_PS_ERROR +/******************************************************************************/ +/* + POSIX - abort() on psError when HALT_ON_PS_ERROR enabled +*/ +void osdepBreak(void) +{ + abort(); +} +#endif /* HALT_ON_PS_ERROR */ + + +#ifdef MATRIX_USE_FILE_SYSTEM +/******************************************************************************/ +/* + FILE APIs +*/ +/** + Allocate a buffer and read in a file. + @note Caller must free 'buf' parameter on success. + Callers do not need to free buf on function failure. +*/ +int32 psGetFileBuf(psPool_t *pool, const char *fileName, unsigned char **buf, + int32 *bufLen) +{ + FILE *fp; + struct stat fstat; + size_t tmp = 0; + + *bufLen = 0; + *buf = NULL; + + if (fileName == NULL) { + return PS_ARG_FAIL; + } + if ((stat(fileName, &fstat) != 0) || (fp = fopen(fileName, "r")) == NULL) { + psTraceStrCore("Unable to open %s\n", (char*)fileName); + return PS_PLATFORM_FAIL; + } + + *buf = psMalloc(pool, (size_t)(fstat.st_size + 1)); + if (*buf == NULL) { + return PS_MEM_FAIL; + } + memset(*buf, 0x0, (size_t)fstat.st_size + 1); + + while (((tmp = fread(*buf + *bufLen, sizeof(char), 512, fp)) > 0) && + (*bufLen < fstat.st_size)) { + *bufLen += (int32)tmp; + } + fclose(fp); + return PS_SUCCESS; +} +#endif /* MATRIX_USE_FILE_SYSTEM */ +#endif /* POSIX */ +/******************************************************************************/ diff --git a/core/WIN32/osdep.c b/core/WIN32/osdep.c new file mode 100644 index 0000000..84de000 --- /dev/null +++ b/core/WIN32/osdep.c @@ -0,0 +1,278 @@ +/** + * @file osdep.c + * @version $Format:%h%d$ + * + * WIN32 platform PScore . + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../coreApi.h" + +#ifdef WIN32 +#include + +/******************************************************************************/ +/* TIME */ + +static LARGE_INTEGER hiresStart; /* zero-time */ +static LARGE_INTEGER hiresFreq; /* tics per second */ + +int osdepTimeOpen(void) +{ + if (QueryPerformanceFrequency(&hiresFreq) == PS_FALSE) { + return PS_FAILURE; + } + if (QueryPerformanceCounter(&hiresStart) == PS_FALSE) { + return PS_FAILURE; + } + return PS_SUCCESS; +} + +void osdepTimeClose(void) +{ +} + +/* PScore Public API implementations */ +int32 psGetTime(psTime_t *t, void *userPtr) +{ + psTime_t lt; + __int64 diff; + int32 d; + + if (t == NULL) { + QueryPerformanceCounter(<); + diff = lt.QuadPart - hiresStart.QuadPart; + d = (int32)((diff * 1000) / hiresFreq.QuadPart); + return d; + } + + QueryPerformanceCounter(t); + diff = t->QuadPart - hiresStart.QuadPart; + d = (int32)((diff * 1000) / hiresFreq.QuadPart); + return d; +} + +int32 psDiffMsecs(psTime_t then, psTime_t now, void *userPtr) +{ + __int64 diff; + + diff = now.QuadPart - then.QuadPart; + return (int32)((diff*1000) / hiresFreq.QuadPart); +} + +int32 psCompareTime(psTime_t a, psTime_t b, void *userPtr) +{ + if (a.QuadPart <= b.QuadPart) { + return 1; + } + return 0; +} + +/******************************************************************************/ +/* MUTEX */ + +#ifdef USE_MULTITHREADING + +int osdepMutexOpen(void) +{ + return PS_SUCCESS; +} + +int osdepMutexClose(void) +{ + return PS_SUCCESS; +} + +/* PScore Public API implementations */ +int32 psCreateMutex(psMutex_t *mutex) +{ + InitializeCriticalSection(mutex); + return PS_SUCCESS; +} + +int32 psLockMutex(psMutex_t *mutex) +{ + EnterCriticalSection(mutex); + return PS_SUCCESS; +} + +int32 psUnlockMutex(psMutex_t *mutex) +{ + LeaveCriticalSection(mutex); + return PS_SUCCESS; +} + +void psDestroyMutex(psMutex_t *mutex) +{ + DeleteCriticalSection(mutex); +} +#endif /* USE_MULTITHREADING */ + +/******************************************************************************/ +/* ENTROPY */ + +static HCRYPTPROV hProv; /* Crypto context for random bytes */ + +int osdepEntropyOpen(void) +{ + if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) { + return PS_FAILURE; + } + return PS_SUCCESS; +} + +void osdepEntropyClose(void) +{ + CryptReleaseContext(hProv, 0); +} + +int32 psGetEntropy(unsigned char *bytes, uint32 size, void *userPtr) +{ + if (CryptGenRandom(hProv, size, bytes)) { + return size; + } + return PS_FAILURE; +} + +/******************************************************************************/ +/* TRACE */ + +int osdepTraceOpen(void) +{ + return PS_SUCCESS; +} + +void osdepTraceClose(void) +{ +} + +void _psTrace(const char *msg) +{ + printf(msg); +} + +/* Message should contain one %s, unless value is NULL */ +void _psTraceStr(const char *message, const char *value) +{ + if (value) { + printf(message, value); + } else { + printf(message); + } +} + +/* message should contain one %d */ +void _psTraceInt(const char *message, int32 value) +{ + printf(message, value); +} + +/* message should contain one %p */ +void _psTracePtr(const char *message, const void *value) +{ + printf(message, value); +} + +/******************************************************************************/ +/* DEBUGGING */ + +#ifdef HALT_ON_PS_ERROR +void osdepBreak(void) +{ + /* System halt on psError (and assert) */ + DebugBreak(); +} +#endif /* HALT_ON_PS_ERROR */ + +/******************************************************************************/ +/* FILE SYSTEM */ + +#ifdef MATRIX_USE_FILE_SYSTEM +/* + Memory info: + Caller must free 'buf' parameter on success + Callers do not need to free buf on function failure +*/ +int32 psGetFileBuf(psPool_t *pool, const char *fileName, unsigned char **buf, + int32 *bufLen) +{ + DWORD dwAttributes; + HANDLE hFile; + int32 size; + DWORD tmp = 0; + + *bufLen = 0; + *buf = NULL; + + dwAttributes = GetFileAttributesA(fileName); + if (dwAttributes != 0xFFFFFFFF && dwAttributes & FILE_ATTRIBUTE_DIRECTORY) { + psTraceStrCore("Unable to find %s\n", (char*)fileName); + return PS_PLATFORM_FAIL; + } + + /* Open an existing file read-only (we are not actually creating) */ + if ((hFile = CreateFileA(fileName, GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) { + psTraceStrCore("Unable to open %s\n", (char*)fileName); + return PS_PLATFORM_FAIL; + } + + size = GetFileSize(hFile, NULL); + + *buf = psMalloc(pool, size + 1); + if (*buf == NULL) { + CloseHandle(hFile); + return PS_MEM_FAIL; + } + memset(*buf, 0x0, size + 1); + + while (*bufLen < size) { + if (ReadFile(hFile, *buf + *bufLen, + (size - *bufLen > 512 ? 512 : size - *bufLen), + &tmp, NULL) == FALSE) { + + psFree(*buf, pool); + psTraceStrCore("Unable to read %s\n", (char*)fileName); + CloseHandle(hFile); + return PS_PLATFORM_FAIL; + } + *bufLen += (int32)tmp; + } + + CloseHandle(hFile); + return PS_SUCCESS; +} +#endif /* MATRIX_USE_FILE_SYSTEM */ + +#endif /* WIN32 */ + +/******************************************************************************/ + diff --git a/core/coreApi.h b/core/coreApi.h new file mode 100644 index 0000000..7f54f89 --- /dev/null +++ b/core/coreApi.h @@ -0,0 +1,237 @@ +/** + * @file coreApi.h + * @version $Format:%h%d$ + * + * Prototypes for the Matrix core public APIs. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_PS_COREAPI +#define _h_PS_COREAPI + +#ifdef __cplusplus +extern "C" { +#endif + +#include "coreConfig.h" /* Must be first included */ +#include "osdep.h" +#include "list.h" +#include "psmalloc.h" + +/******************************************************************************/ +/* + psCore return codes +*/ +#define PS_CORE_IS_OPEN 1 + +/******************************************************************************/ +/* + Universal return codes +*/ +#define PS_SUCCESS 0 +#define PS_FAILURE -1 +#define PS_FAIL PS_FAILURE /* Just another name */ + +/* NOTE: Failure return codes MUST be < 0 */ +/* NOTE: The range for core error codes should be between -2 and -29 */ +#define PS_ARG_FAIL -6 /* Failure due to bad function param */ +#define PS_PLATFORM_FAIL -7 /* Failure as a result of system call error */ +#define PS_MEM_FAIL -8 /* Failure to allocate requested memory */ +#define PS_LIMIT_FAIL -9 /* Failure on sanity/limit tests */ +#define PS_UNSUPPORTED_FAIL -10 /* Unimplemented feature error */ +#define PS_DISABLED_FEATURE_FAIL -11 /* Incorrect #define toggle for feature */ +#define PS_PROTOCOL_FAIL -12 /* A protocol error occurred */ +#define PS_TIMEOUT_FAIL -13 /* A timeout occurred and MAY be an error */ +#define PS_INTERRUPT_FAIL -14 /* An interrupt occurred and MAY be an error */ +#define PS_PENDING -15 /* In process. Not necessarily an error */ +#define PS_EAGAIN -16 /* Try again later. Not necessarily an error */ + +#define PS_TRUE 1 +#define PS_FALSE 0 + +/******************************************************************************/ +/* Public structures */ +/******************************************************************************/ +/* + psBuf_t + Empty buffer: + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + |.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.| + ^ + \end + \start + \buf + size = 16 + len = (end - start) = 0 + + Buffer with data: + + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + |.|.|a|b|c|d|e|f|g|h|i|j|.|.|.|.| + ^ ^ ^ + | | \end + | \start + \buf + size = 16 + len = (end - start) = 10 + + Read from start pointer + Write to end pointer + Free from buf pointer +*/ +typedef struct { + unsigned char *buf; /* Pointer to the start of the buffer */ + unsigned char *start; /* Pointer to start of valid data */ + unsigned char *end; /* Pointer to first byte of invalid data */ + int32 size; /* Size of buffer in bytes */ +} psBuf_t; + +/******************************************************************************/ + +#ifdef MATRIX_USE_FILE_SYSTEM + #define FILESYSTEM_CONFIG_STR "Y" +#else + #define FILESYSTEM_CONFIG_STR "N" +#endif + #define PSMALLOC_CONFIG_STR "N" +#ifdef USE_MULTITHREADING + #define MULTITHREAD_CONFIG_STR "Y" +#else + #define MULTITHREAD_CONFIG_STR "N" +#endif + +#define PSCORE_CONFIG \ + "Y" \ + FILESYSTEM_CONFIG_STR \ + PSMALLOC_CONFIG_STR \ + MULTITHREAD_CONFIG_STR + +/******************************************************************************/ +/* Public APIs */ + #include +/******************************************************************************/ + +PSPUBLIC int32 psCoreOpen(const char *config); +PSPUBLIC void psCoreClose(void); +PSPUBLIC void psBurnStack(uint32 len); +PSPUBLIC int32 memcmpct(const void *s1, const void *s2, size_t len); + + +/******************************************************************************/ +/* + Public interface to OS-dependant core functionality + + OS/osdep.c must implement the below functions +*/ +PSPUBLIC int32 psGetEntropy(unsigned char *bytes, uint32 size, + void *userPtr); + +PSPUBLIC int32 psGetTime(psTime_t *t, void *userPtr); +PSPUBLIC int32 psDiffMsecs(psTime_t then, psTime_t now, void *userPtr); + +/* psCompareTime is no longer used */ +PSPUBLIC int32 psCompareTime(psTime_t a, psTime_t b, void *userPtr); + +#ifdef MATRIX_USE_FILE_SYSTEM +PSPUBLIC int32 psGetFileBuf(psPool_t *pool, const char *fileName, + unsigned char **buf, int32 *bufLen); +#endif /* MATRIX_USE_FILE_SYSTEM */ + +#ifdef USE_MULTITHREADING +PSPUBLIC int32 psCreateMutex(psMutex_t *mutex); +PSPUBLIC int32 psLockMutex(psMutex_t *mutex); +PSPUBLIC int32 psUnlockMutex(psMutex_t *mutex); +PSPUBLIC void psDestroyMutex(psMutex_t *mutex); +#else +#define psCreateMutex(A) (PS_SUCCESS) +#define psLockMutex(A) (PS_SUCCESS) +#define psUnlockMutex(A) (PS_SUCCESS) +#define psDestroyMutex(A) +#endif /* USE_MULTITHREADING */ + +/******************************************************************************/ +/* + Internal list helpers +*/ +extern int32 psParseList(psPool_t *pool, char *list, const char separator, + psList_t **items); +extern void psFreeList(psList_t *list, psPool_t *pool); + +/******************************************************************************/ +/* + Statistics helpers +*/ + +/** Number of samples to store take for running average. */ +#define STAT_AVG_SAMPLES 32 + +typedef struct { + uint32_t h; /**< High water */ + uint32_t a[STAT_AVG_SAMPLES]; /**< Values */ + uint32_t atot; /**< Running total of a[] values */ + uint16_t ai; /**< Most recent index into a[] */ + uint16_t an; /**< Current number of valid entries in a[] */ +} psAvgStat_t; + +__inline static void STAT_INC_AVG(psAvgStat_t *s, uint32_t val) +{ + /* Update high water */ + if (val > s->h) { + s->h = val; + } + if (s->an < STAT_AVG_SAMPLES) { + /* Update total number of stats, if not at max */ + s->an++; + } else { + /* Subtract the oldest value from the running total, if we're replacing */ + s->atot -= s->a[s->ai]; + } + /* Point to next entry, replace it and increment running total */ + s->ai = (s->ai + 1) % STAT_AVG_SAMPLES; + s->a[s->ai] = val; + s->atot += val; +} + +__inline static uint32_t STAT_AVG(psAvgStat_t *s) +{ + return (s->atot / s->an); +} + +__inline static uint32_t STAT_HIGH(psAvgStat_t *s) +{ + return s->h; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _h_PS_COREAPI */ +/******************************************************************************/ + diff --git a/core/coreConfig.h b/core/coreConfig.h new file mode 100644 index 0000000..60e85ca --- /dev/null +++ b/core/coreConfig.h @@ -0,0 +1,77 @@ +/** + * @file coreConfig.h + * @version $Format:%h%d$ + * + * Configuration settings for Matrix core module. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_PS_CORECONFIG +#define _h_PS_CORECONFIG + + +/******************************************************************************/ +/* Configurable features */ +/******************************************************************************/ +/** + Enable various levels of trace. + When these option is turned off, messages are silently + discarded and their text does not take space in the binary image. +*/ +//#define USE_CORE_TRACE +#ifndef NO_CORE_ERROR + #define USE_CORE_ERROR +#endif +#ifndef NO_CORE_ASSERT + #define USE_CORE_ASSERT +#endif + +/** + If enabled, calls to the psError set of APIs will perform a platform + abort on the exeutable to aid in debugging. +*/ +#ifdef DEBUG +//#define HALT_ON_PS_ERROR /* NOT RECOMMENDED FOR PRODUCTION BUILDS */ +#endif + + +/** + Include the psCoreOsdepMutex family of APIs +*/ +#ifndef NO_MULTITHREADING +//#define USE_MULTITHREADING +#endif /* NO_MULTITHREADING */ + + + + +#endif /* _h_PS_CORECONFIG */ + +/******************************************************************************/ + diff --git a/core/corelib.c b/core/corelib.c new file mode 100644 index 0000000..3fac4a7 --- /dev/null +++ b/core/corelib.c @@ -0,0 +1,314 @@ +/** + * @file corelib.c + * @version $Format:%h%d$ + * + * Open and Close APIs and utilities for Matrix core library. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "coreApi.h" + +/******************************************************************************/ +/* + Open (initialize) the Core module + The config param should always be passed as: + PSCORE_CONFIG +*/ +static char g_config[32] = "N"; + +/******************************************************************************/ +int32 psCoreOpen(const char *config) +{ + if (*g_config == 'Y') { + return PS_CORE_IS_OPEN; + } + strncpy(g_config, PSCORE_CONFIG, sizeof(g_config) - 1); + if (strncmp(g_config, config, strlen(PSCORE_CONFIG)) != 0) { + psErrorStr( "Core config mismatch.\n" \ + "Library: " PSCORE_CONFIG\ + "\nCurrent: %s\n", config); + return -1; + } + + + if (osdepTimeOpen() < 0) { + psTraceCore("osdepTimeOpen failed\n"); + return PS_FAILURE; + } + if (osdepEntropyOpen() < 0) { + psTraceCore("osdepEntropyOpen failed\n"); + osdepTimeClose(); + return PS_FAILURE; + } + +#ifdef USE_MULTITHREADING + if (osdepMutexOpen() < 0) { + psTraceCore("osdepMutexOpen failed\n"); + osdepEntropyClose(); + osdepTimeClose(); + return PS_FAILURE; + } +#endif /* USE_MULTITHREADING */ + + + return PS_SUCCESS; +} + +/******************************************************************************/ +void psCoreClose(void) +{ + if (*g_config == 'Y') { + *g_config = 'N'; + +#ifdef USE_MULTITHREADING + osdepMutexClose(); +#endif /* USE_MULTITHREADING */ + + osdepEntropyClose(); + + osdepTimeClose(); + } +} + +/******************************************************************************/ +/** + Constant time memory comparison - like memcmp but w/o data dependent branch. + @security SECURITY - Should be used when comparing values that use or have + been derived or have been decrypted/encrypted/signed from secret information. + + @param[in] s1 Pointer to first buffer to compare + @param[in] s2 Pointer to first buffer to compare + @param[in] len number of bytes to compare in s1 and s2 + @return 0 on successful match, nonzero on failure. +*/ +int32 memcmpct(const void *s1, const void *s2, size_t len) +{ + int xor = 0; + + while(len > 0) { + len--; + xor |= ((unsigned char *)s1)[len] ^ ((unsigned char *)s2)[len]; + } + return xor; +} + +/******************************************************************************/ +/* + ERROR FUNCTIONS + Tap into platform trace and break execution if DEBUG compile + + Modules should tie themselves to these low levels + with compile-time defines +*/ +void _psError(const char *msg) +{ + _psTrace(msg); + _psTrace("\n"); +#ifdef HALT_ON_PS_ERROR + osdepBreak(); +#endif +} +void _psErrorInt(const char *msg, int32 val) +{ + _psTraceInt(msg, val); + _psTrace("\n"); +#ifdef HALT_ON_PS_ERROR + osdepBreak(); +#endif +} +void _psErrorStr(const char *msg, const char *val) +{ + _psTraceStr(msg, val); + _psTrace("\n"); +#ifdef HALT_ON_PS_ERROR + osdepBreak(); +#endif +} + +/* + copy 'len' bytes from 'b' to 's', converting all to printable characters +*/ +static void mem2str(char *s, const unsigned char *b, uint32 len) +{ + for (; len > 0; len--) { + if (*b > 31 && *b < 127) { + *s = *b; + } else { + *s = '.'; + } + b++; + s++; + } +} + +void psTraceBytes(const char *tag, const unsigned char *p, int l) +{ + char s[17]; + int i; + + s[16] = '\0'; + if (tag) { + _psTraceStr("psTraceBytes(%s, ", tag); + _psTraceInt("%d);", l); + } else { + _psTrace("\""); + } + for (i = 0; i < l; i++) { + if (!(i & 0xF)) { + if (tag) { + if (i != 0) { + mem2str(s, p - 16, 16); + _psTraceStr(" %s", s); + } +#ifdef _LP64 + _psTraceInt("\n0x%08x:", (int64)p); +#else + _psTraceInt("\n0x%04x:", (int32)p); +#endif + } else { + _psTrace("\"\n\""); + } + } + if (tag) { + _psTraceInt("%02x ", *p++); + } else { + _psTraceInt("\\x%02x", *p++); + } + } + if (tag) { + memset(s, 0x0, 16); + i = l & 0xF; + mem2str(s, p - i, (unsigned int)i); + for (;i < 16; i++) { + _psTrace(" "); + } + _psTraceStr(" %s", s); + _psTrace("\n"); + } else { + _psTrace("\"\n"); + } +} + +/******************************************************************************/ +/* + Creates a simple linked list from a given stream and separator char + + Memory info: + Callers do not have to free 'items' on function failure. +*/ +int32 psParseList(psPool_t *pool, char *list, const char separator, + psList_t **items) +{ + psList_t *litems, *start, *prev; + uint32 itemLen, listLen; + char *tmp; + + *items = NULL; + prev = NULL; + + listLen = (int32)strlen(list) + 1; + if (listLen == 1) { + return PS_ARG_FAIL; + } + start = litems = psMalloc(pool, sizeof(psList_t)); + if (litems == NULL) { + return PS_MEM_FAIL; + } + memset(litems, 0, sizeof(psList_t)); + + while (listLen > 0) { + itemLen = 0; + tmp = list; + if (litems == NULL) { + litems = psMalloc(pool, sizeof(psList_t)); + if (litems == NULL) { + psFreeList(start, pool); + return PS_MEM_FAIL; + } + memset(litems, 0, sizeof(psList_t)); + prev->next = litems; + + } + while (*list != separator && *list != '\0') { + itemLen++; + listLen--; + list++; + } + litems->item = psMalloc(pool, itemLen + 1); + if (litems->item == NULL) { + psFreeList(start, pool); + return PS_MEM_FAIL; + } + litems->len = itemLen; + memset(litems->item, 0x0, itemLen + 1); + memcpy(litems->item, tmp, itemLen); + list++; + listLen--; + prev = litems; + litems = litems->next; + } + *items = start; + return PS_SUCCESS; +} + +void psFreeList(psList_t *list, psPool_t *pool) +{ + psList_t *next, *current; + + if (list == NULL) { + return; + } + current = list; + while (current) { + next = current->next; + if (current->item) { + psFree(current->item, pool); + } + psFree(current, pool); + current = next; + } +} + +/******************************************************************************/ +/* + Clear the stack deeper than the caller to erase any potential secrets + or keys. +*/ +void psBurnStack(uint32 len) +{ + unsigned char buf[32]; + + memset_s(buf, sizeof(buf), 0x0, sizeof(buf)); + if (len > (uint32)sizeof(buf)) { + psBurnStack(len - sizeof(buf)); + } +} + +/******************************************************************************/ + diff --git a/core/list.h b/core/list.h new file mode 100644 index 0000000..a41e031 --- /dev/null +++ b/core/list.h @@ -0,0 +1,168 @@ +/** + * @file list.h + * @version $Format:%h%d$ + * + * List utilities. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_PS_COREUTIL +#define _h_PS_COREUTIL + +/********************************** Defines ***********************************/ +/* + * Fast circular doubly-linked list and branchless macro-functions. + * Provides a struct-independent way to have a small head and hang a list + * of structs off of it. Examples of use: + * + * typedef struct { + * int bar; + * DLListEntry List; + * } foo; + * + * Define foo list head: + * DLListEntry FooListHead; + * + * Init for list head: + * DLListInit(&FooListHead); + * + * Define and init list head: + * DEFINE_DLLIST(FooListHead); + * or + * static DEFINE_DLLIST(FooListHead); + * + * Insert *pMyFoo after the head: + * foo *pMyFoo; + * pMyFoo = malloc(sizeof(foo)); + * DLListInsertHead(&FooListHead, &pMyFoo->List); + * + * Do the same but place at tail: + * DLListInsertTail(&FooListHead, &pMyFoo->List); + * + * Given a foo that you know is in a list, detach it from the list: + * DLListRemove(&pMyFoo->List); + * + * Detach and return the list entry for the head item: + * DLListEntry *pList; + * pList = DLListGetHead(&FooListHead); + * pMyFoo = DLListGetContainer(pList, foo, List); + * + * Iterate the entire list: + * DLListEntry *pList; + * pList = FooListHead.pNext; + * while (pList != &FooListHead) { + * pCurFoo = DLListGetContainer(pList, foo, List); + * ... (do something with the current foo) + * pList = pList->pNext; + * } + * + * Iterate the entire list, removing each item (e.g. on all-list destruction): + * DLListEntry *pList; + * while (!DLListIsEmpty(&FooListHead)) { + * pList = DLListGetHead(&FooListHead); + * pMyFoo = DLListGetContainer(pList, foo, List); + * DestroyFoo(pMyFoo); + * free(pMyFoo); + * } + */ +typedef struct _DLListEntry { + struct _DLListEntry *pNext, *pPrev; +} DLListEntry; + +#define DEFINE_DLLIST(x) DLListEntry x = { .pNext = &x, .pPrev = &x }; + +#define DLListInit(__pList) \ +(__pList)->pNext = (__pList)->pPrev = (__pList) + +/* Inserts an item as the first item of the list */ +#define DLListInsertHead(__pHead, __pNode) { \ +psAssert((__pHead) != (__pNode)); \ +(__pNode)->pNext = (__pHead)->pNext; \ +(__pNode)->pPrev = (__pHead); \ +(__pHead)->pNext->pPrev = (__pNode); \ +(__pHead)->pNext = (__pNode); \ +} + +/* Inserts an item as the last in the list */ +#define DLListInsertTail(__pHead, __pNode) { \ +psAssert((__pHead) != (__pNode)); \ +(__pNode)->pNext = (__pHead); \ +(__pNode)->pPrev = (__pHead)->pPrev; \ +(__pHead)->pPrev->pNext = (__pNode); \ +(__pHead)->pPrev = (__pNode); \ +} + +/* Detaches node from current position in the list. */ +#define DLListRemove(__pNode) { \ +(__pNode)->pNext->pPrev = (__pNode)->pPrev; \ +(__pNode)->pPrev->pNext = (__pNode)->pNext; \ +} + +#define DLListIsEmpty(__pHead) ((__pHead)->pNext == (__pHead)) + +/* + Gets the pointer to the containing object given the DLList pointer, + the type name of the struct, and the name of the DLList field within + the struct. + */ +#define DLListGetContainer(__pDLList, __ContainerType, __DLListFieldName) \ +((__ContainerType *)((char *)(__pDLList) - \ +(long)(&((__ContainerType *)0)->__DLListFieldName))) + +/* + Detaches first list item after the head and returns a pointer to it. + List must not be empty. + */ +#define DLListGetHead(__pHead) \ +(__pHead)->pNext; \ +(__pHead)->pNext->pNext->pPrev = (__pHead); \ +(__pHead)->pNext = (__pHead)->pNext->pNext; + +/* + Detaches list list item before the head and returns a pointer to it. + List must not be empty. + */ +#define DLListGetTail(__pHead) \ +(__pHead)->pPrev; \ +(__pHead)->pPrev->pPrev->pNext = (__pHead); \ +(__pHead)->pPrev = (__pHead)->pPrev->pPrev; + +/******************************************************************************/ +/* + Simpler, single linked list +*/ +typedef struct psList { + unsigned char *item; + struct psList *next; + uint16_t len; +} psList_t; + +#endif /* _h_PS_COREUTIL */ +/******************************************************************************/ + diff --git a/core/memset_s.c b/core/memset_s.c new file mode 100644 index 0000000..d44cf4f --- /dev/null +++ b/core/memset_s.c @@ -0,0 +1,84 @@ +/** + * @file memset_s.c + * @version $Format:%h%d$ + * + * Secure memset api that will not be optimized out by compiler. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ + +/******************************************************************************/ +/** + Implementation of C11 API for platforms that do not have it. + + In contrast to the memset(3) function, calls to memset_s() will never be + "optimised away" by a compiler. This property is required by the follow- + ing sentences in section K.3.7.4.1 of ISO/IEC 9899:2011 ("ISO C11"): + Unlike memset(), any call to the memset_s() function shall be evalu- + ated strictly according to the rules of the abstract machine as + described in (5.1.2.3). That is, any call to the memset_s() function + shall assume that the memory indicated by s and n may be accessible + in the future and thus must contain the values indicated by c. + + On Mac OS X, this api is natively implemented. + On Windows, this api is mapped to SecureZeroMemory() +*/ +#if !defined(_WIN32) && !defined(__APPLE__) + +#ifdef __OPTIMIZE__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpragmas" +#pragma GCC push_options +#pragma GCC optimize("O0") +#define NO_OPTIM __attribute__((noinline)) __attribute__((optimize("O0"))) +#else +#define NO_OPTIM +#endif + +#include + +typedef size_t rsize_t; +typedef int errno_t; + +errno_t NO_OPTIM memset_s(void *s, rsize_t smax, int c, rsize_t n) +{ + if (n > smax) { + n = smax; + } + memset(s, c, n); + return ((unsigned char volatile *)s)[0]; +} + +#ifdef __OPTIMIZE__ +#pragma GCC pop_options +#pragma GCC diagnostic pop +#endif +#undef NO_OPTIM + +#endif /* !WIN && ! APPLE */ + +/******************************************************************************/ diff --git a/core/osdep.h b/core/osdep.h new file mode 100644 index 0000000..b57c631 --- /dev/null +++ b/core/osdep.h @@ -0,0 +1,425 @@ +/** + * @file osdep.h + * @version $Format:%h%d$ + * + * Operating System and Hardware Abstraction Layer. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_PS_PLATFORM +#define _h_PS_PLATFORM + +/******************************************************************************/ +/* + Platform detection based on compiler settings + @see http://sourceforge.net/p/predef/wiki/Home/ +*/ +/* Determine the operating system (if any) */ +#if defined(__linux__) /* Linux and Android */ + #define POSIX + #define LINUX + #define MATRIX_USE_FILE_SYSTEM +#elif defined(__APPLE__) && defined(__MACH__) /* Mac OS X */ + #define POSIX + #define OSX + #define HAVE_NATIVE_INT64 + #define MATRIX_USE_FILE_SYSTEM +#elif defined(_WIN32) /* Windows */ + #ifndef WIN32 + #define WIN32 + #endif + #define HAVE_NATIVE_INT64 + #define MATRIX_USE_FILE_SYSTEM +#endif +/* For others such as FREERTOS, define in build system */ + +/* Use packed attribute on compilers that support it */ +#if defined(__GNUC__) || defined(__clang__) + #define PACKED __attribute__((__packed__)) +#else + #define PACKED +#endif + +/* Determine which assembly language optimizations we can use */ +#if defined(__GNUC__) || defined(__clang__) /* Only supporting gcc-like */ +#if defined(__x86_64__) + #define PSTM_X86_64 + #define PSTM_64BIT /* Supported by architecture */ +#elif defined(__i386__) + #define PSTM_X86 +#elif defined(__arm__) + #define PSTM_ARM + //__aarch64__ /* 64 bit arm */ + //__thumb__ /* Thumb mode */ +#elif defined(__mips__) + #if defined(__mips64) + #define PSTM_64BIT + #else + #define PSTM_MIPS /* MIPS assembly supported on 32 bit only */ + #endif +#endif +#endif /* GNUC/CLANG */ + +/* Try to determine if the compiler/platform supports 64 bit integer ops */ +#if !defined(HAVE_NATIVE_INT64) && defined(__SIZEOF_LONG_LONG__) + #define HAVE_NATIVE_INT64 /* Supported by compiler */ +#endif + +/* Detect endian based on platform */ +#if (defined __LITTLE_ENDIAN__ || defined __i386__ || defined __x86_64__ || \ + defined _M_X64 || defined _M_IX86 || \ + defined __ARMEL__ || defined __MIPSEL__) + #define __ORDER_LITTLE_ENDIAN__ 1234 + #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ +#elif (defined __BIG_ENDIAN__ || defined __MIPSEB__) + #define __ORDER_BIG_ENDIAN__ 4321 + #define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__ +#endif + +#ifdef __BYTE_ORDER__ /* Newer GCC and LLVM */ + #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + #define ENDIAN_LITTLE + #else + #define ENDIAN_BIG + #endif + #ifdef PSTM_64BIT + #define ENDIAN_64BITWORD + #else + #define ENDIAN_32BITWORD + #endif +#else + #if (defined(_MSC_VER) && defined(WIN32)) || \ + (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || \ + defined(__MINGW32__) || defined(__i386__))) + #define ENDIAN_LITTLE + #define ENDIAN_32BITWORD + #else + #warning "Cannot determine endianness, using neutral" + #endif +/* #define ENDIAN_LITTLE */ +/* #define ENDIAN_BIG */ + +/* #define ENDIAN_32BITWORD */ +/* #define ENDIAN_64BITWORD */ +#endif + +#if (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && \ + !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD)) + #error You must specify a word size as well as endianness +#endif + +#if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) + #define ENDIAN_NEUTRAL +#endif + +/******************************************************************************/ +/* + APIs that must be implemented on every platform +*/ + +#ifdef WIN32 + #ifdef _LIB /* Static library */ + #define PSPUBLIC extern + #else + #ifdef _USRDLL /* DLL */ + #define PSPUBLIC extern __declspec(dllexport) + #else + #define PSPUBLIC extern __declspec(dllimport) + #endif + #endif +#else + #define PSPUBLIC extern +#endif /* !WIN32 */ + +extern int osdepTraceOpen(void); +extern void osdepTraceClose(void); +extern int osdepTimeOpen(void); +extern void osdepTimeClose(void); +extern int osdepEntropyOpen(void); +extern void osdepEntropyClose(void); +#ifdef HALT_ON_PS_ERROR + extern void osdepBreak(void); +#endif + +#ifndef min + #define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif /* min */ + +/******************************************************************************/ +/* + If the Makefile specifies that MatrixSSL does not currently have + a layer for the given OS, or the port is to "bare metal" hardware, + do basic defines here and include externally provided file "matrixos.h". + In addition, if building for such a platform, a C file defining the above + functions must be linked with the final executable. +*/ +#ifdef PS_UNSUPPORTED_OS + #include "matrixos.h" +#else +/******************************************************************************/ +/* + Supported Platforms below. The implementations of the apis are in + platform specific directories, such as core/POSIX and core/ECOS + + POSIX define is used for Linux and Mac OS X +*/ +#include + +#ifndef POSIX + #if defined(LINUX) || defined(OSX) + #define POSIX + #endif +#endif + +#if defined(POSIX) + #include + typedef int32_t int32; + typedef uint32_t uint32; + typedef int16_t int16; + typedef uint16_t uint16; + typedef uint8_t uint8; + #ifdef HAVE_NATIVE_INT64 + typedef int64_t int64; + typedef uint64_t uint64; + #endif +#elif defined(WIN32) + #include + #define strcasecmp lstrcmpiA + #define snprintf _snprintf + typedef signed long int32; + typedef unsigned long uint32; + typedef signed short int16; + typedef unsigned short uint16; + typedef unsigned char uint8; + typedef signed long int32_t; + typedef unsigned long uint32_t; + typedef signed short int16_t; + typedef unsigned short uint16_t; + typedef unsigned char uint8_t; + typedef signed char int8_t; + #ifdef HAVE_NATIVE_INT64 + typedef unsigned long long uint64; + typedef signed long long int64; + typedef unsigned long long uint64_t; + typedef signed long long int64_t; + #endif +#elif defined(METAL) + typedef signed long int32; + typedef unsigned long uint32; + typedef signed short int16; + typedef unsigned short uint16; + #ifdef HAVE_NATIVE_INT64 + typedef unsigned long long uint64; + typedef signed long long int64; + #endif +#elif defined (NUCLEUS) + #include + typedef int32_t int32; + typedef uint32_t uint32; + typedef int16_t int16; + typedef uint16_t uint16; + typedef uint8_t uint8; + #ifdef HAVE_NATIVE_INT64 + typedef int64_t int64; + typedef uint64_t uint64; + #endif +#endif + +/******************************************************************************/ +/* + Secure memset/memzero +*/ +#if defined(WIN32) + #undef memset_s + #define memset_s(A,B,C,D) SecureZeroMemory(A,D) +#elif defined(OSX) + #define __STDC_WANT_LIB_EXT1__ 1 + #include +#else + #include +typedef size_t rsize_t; +typedef int errno_t; +extern errno_t memset_s(void *s, rsize_t smax, int c, rsize_t n); +#endif + +#define memzero_s(S,N) memset_s(S, N, 0x0, N) + +/******************************************************************************/ +/* + Hardware Abstraction Layer +*/ +/* Hardware Abstraction Layer - define functions in HAL directory */ +#if defined(POSIX) || defined(WIN32) || defined(ECOS) || defined(FREERTOS) || defined(NUCLEUS) + #define halOpen() 0 + #define halClose() + #define halAlert() +#else + extern int halOpen(void); + extern void halAlert(void); + extern void halClose(void); +#endif /* HAL */ + +/******************************************************************************/ +/* + OS-specific psTime_t types + + Make psTime_t an opaque time value. +*/ + +#if defined(__x86_64__) + #define USE_HIGHRES_TIME +#endif + +#if defined(POSIX) + #ifndef USE_HIGHRES_TIME + #include + #include + typedef struct timeval psTime_t; + #else + #if defined(__APPLE__) || defined(__tile__) + typedef uint64_t psTime_t; + #else + #include + typedef struct timespec psTime_t; + #endif + extern int64_t psDiffUsecs(psTime_t then, psTime_t now); + #endif +#elif defined(WIN32) + typedef LARGE_INTEGER psTime_t; +#elif defined(METAL) + typedef unsigned int psTime_t; +#elif defined(NUCLEUS) + typedef uint64_t psTime_t; +#elif defined(VXWORKS) + typedef struct { + long sec; + long usec; + } psTime_t; +#endif + +/******************************************************************************/ +/* + Raw trace and error +*/ +PSPUBLIC void _psTrace(const char *msg); +PSPUBLIC void _psTraceInt(const char *msg, int32 val); +PSPUBLIC void _psTraceStr(const char *msg, const char *val); +PSPUBLIC void _psTracePtr(const char *message, const void *value); +PSPUBLIC void psTraceBytes(const char *tag, const unsigned char *p, int l); + +PSPUBLIC void _psError(const char *msg); +PSPUBLIC void _psErrorInt(const char *msg, int32 val); +PSPUBLIC void _psErrorStr(const char *msg, const char *val); + +/******************************************************************************/ +/* + Core trace +*/ +#ifndef USE_CORE_TRACE + #define psTraceCore(x) + #define psTraceStrCore(x, y) + #define psTraceIntCore(x, y) + #define psTracePtrCore(x, y) +#else + #define psTraceCore(x) _psTrace(x) + #define psTraceStrCore(x, y) _psTraceStr(x, y) + #define psTraceIntCore(x, y) _psTraceInt(x, y) + #define psTracePtrCore(x, y) _psTracePtr(x, y) +#endif /* USE_CORE_TRACE */ + +/******************************************************************************/ +/* + HALT_ON_PS_ERROR define at compile-time determines whether to halt on + psAssert and psError calls +*/ +#ifdef USE_CORE_ASSERT +#define psAssert(C) if (C) ; else \ + {halAlert();_psTraceStr("psAssert %s", __FILE__);_psTraceInt(":%d ", __LINE__);\ + _psError(#C);} +#else +#define psAssert(C) if (C) ; else do { /* assert ignored. */} while (0) +#endif + +#ifdef USE_CORE_ERROR +#define psError(a) \ + halAlert();_psTraceStr("psError %s", __FILE__);_psTraceInt(":%d ", __LINE__); \ + _psError(a); + +#define psErrorStr(a,b) \ + halAlert();_psTraceStr("psError %s", __FILE__);_psTraceInt(":%d ", __LINE__); \ + _psErrorStr(a,b) + +#define psErrorInt(a,b) \ + halAlert();_psTraceStr("psError %s", __FILE__);_psTraceInt(":%d ", __LINE__); \ + _psErrorInt(a,b) +#else +#define psError(a) do { /* error ignored. */} while (0) +#define psErrorStr(a,b) do { /* error ignored. */} while (0) +#define psErrorInt(a,b) do { /* error ignored. */} while (0) +#endif + +/******************************************************************************/ +/* + OS specific file system apis +*/ +#ifdef MATRIX_USE_FILE_SYSTEM + #ifdef POSIX + #include + #endif /* POSIX */ +#endif /* MATRIX_USE_FILE_SYSTEM */ + +/******************************************************************************/ +/* + Defines to make library multithreading safe +*/ +#ifdef USE_MULTITHREADING + +extern int32 osdepMutexOpen(void); +extern int32 osdepMutexClose(void); + +#if defined(WIN32) + typedef CRITICAL_SECTION psMutex_t; +#elif defined(POSIX) + #include + #include + typedef pthread_mutex_t psMutex_t; +#elif defined(VXWORKS) + #include "semLib.h" + typedef SEM_ID psMutex_t; +#else + #error psMutex_t must be defined +#endif /* OS specific mutex */ + +#endif /* USE_MULTITHREADING */ + +/******************************************************************************/ + +#endif /* !PS_UNSUPPORTED_OS */ +#endif /* _h_PS_PLATFORM */ + diff --git a/core/psmalloc.h b/core/psmalloc.h new file mode 100644 index 0000000..1268fdb --- /dev/null +++ b/core/psmalloc.h @@ -0,0 +1,79 @@ +/** + * @file psmalloc.h + * @version $Format:%h%d$ + * + * Header for psMalloc functions. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_PS_MALLOC +#define _h_PS_MALLOC + +/******************************************************************************/ +/* +*/ +#ifdef PS_UNSUPPORTED_OS + #include "matrixos.h" +#else +/******************************************************************************/ +/* +*/ + +#include /* memset, memcpy */ + +#define MATRIX_NO_POOL (void *)0x0 + +/******************************************************************************/ +/* + Native memory routines +*/ +#include /* malloc, free, etc... */ + +#define MAX_MEMORY_USAGE 0 +#define psOpenMalloc() 0 +#define psCloseMalloc() +#define psDefineHeap(A, B) +#define psAddPoolCache(A, B) +#define psMalloc(A, B) malloc(B) +#define psCalloc(A, B, C) calloc(B, C) +#define psMallocNoPool malloc +#define psRealloc(A, B, C) realloc(A, B) +#define psFree(A, B) free(A) +#define psMemset memset +#define psMemcpy memcpy + +typedef int32 psPool_t; + + +/******************************************************************************/ + +#endif /* !PS_UNSUPPORTED_OS */ +#endif /* _h_PS_MALLOC */ +/******************************************************************************/ + diff --git a/crypto/Makefile b/crypto/Makefile new file mode 100755 index 0000000..2988150 --- /dev/null +++ b/crypto/Makefile @@ -0,0 +1,82 @@ +# +# Makefile for MatrixSSL crypto static library +# 'make' builds debug (Default). +# 'make gold' builds optimized. +# +# Copyright (c) 2013-2016 INSIDE Secure Corporation. All Rights Reserved. +# + +MATRIXSSL_ROOT:=.. +include $(MATRIXSSL_ROOT)/common.mk + +SRC:=\ + symmetric/aes.c \ + symmetric/aesCBC.c \ + symmetric/aesGCM.c \ + symmetric/aes_aesni.c \ + symmetric/arc4.c \ + symmetric/des3.c \ + symmetric/idea.c \ + symmetric/rc2.c \ + symmetric/seed.c \ + digest/sha1.c \ + digest/sha256.c \ + digest/sha512.c \ + digest/md5sha1.c \ + digest/md5.c \ + digest/hmac.c \ + digest/md4.c \ + digest/md2.c \ + keyformat/asn1.c \ + keyformat/base64.c \ + keyformat/pkcs.c \ + keyformat/x509.c \ + layer/matrix.c \ + math/pstm.c \ + math/pstm_montgomery_reduce.c \ + math/pstm_mul_comba.c \ + math/pstm_sqr_comba.c \ + prng/prng.c \ + prng/yarrow.c \ + pubkey/dh.c \ + pubkey/ecc.c \ + pubkey/pubkey.c \ + pubkey/rsa.c +#OPENSSL +ifdef PS_OPENSSL +SRC+=\ + digest/digest_openssl.c \ + symmetric/symmetric_openssl.c \ + pubkey/rsa_openssl.c +endif +#OPENSSL +#LIBSODIUM +ifdef PS_LIBSODIUM +SRC+=\ + symmetric/symmetric_libsodium.c \ + digest/digest_libsodium.c +endif +#LIBSODIUM + +# Generated files +STATIC:=libcrypt_s.a + +all: compile + +compile: $(OBJS) $(STATIC) + @echo $(STROPTS) + +# Additional Dependencies +$(OBJS): $(MATRIXSSL_ROOT)/common.mk Makefile *.h */*.h + +# Build the static library +# Direct stderr to null so we don't see the 'empty file' warnings +$(STATIC): $(OBJS) + $(AR) -rcuv $@ $^ 2>/dev/null + +clean: + rm -f $(STATIC) $(OBJS) + +# Allows to check configuration options. +parse-config: + echo '#include "cryptoConfig.h"' | $(CC) $(CFLAGS) -dM -E -x c - diff --git a/crypto/cryptoApi.h b/crypto/cryptoApi.h new file mode 100644 index 0000000..9421a38 --- /dev/null +++ b/crypto/cryptoApi.h @@ -0,0 +1,749 @@ +/** + * @file cryptoApi.h + * @version $Format:%h%d$ + * + * Prototypes for the Matrix crypto public APIs. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_PS_CRYPTOAPI +#define _h_PS_CRYPTOAPI + +#ifdef __cplusplus +extern "C" { +#endif + +#include "core/coreApi.h" /* Must be included first */ +#include "cryptoConfig.h" /* Must be included second */ +#include "cryptolib.h" + +/******************************************************************************/ +/** + Public return codes. + These are in addition to those in core/ + Failure codes MUST be < 0 + @note The range for crypto error codes must be between -30 and -49 +*/ +#define PS_PARSE_FAIL -31 +/** + @note Any future additions to certificate authentication failures + must be carried through to MatrixSSL code +*/ +#define PS_CERT_AUTH_PASS PS_TRUE +#define PS_CERT_AUTH_FAIL_BC -32 /* BasicConstraint failure */ +#define PS_CERT_AUTH_FAIL_DN -33 /* DistinguishedName failure */ +#define PS_CERT_AUTH_FAIL_SIG -34 /* Signature validation failure */ +#define PS_CERT_AUTH_FAIL_REVOKED -35 /* Revoked via CRL */ +#define PS_CERT_AUTH_FAIL -36 /* Generic cert auth fail */ +#define PS_CERT_AUTH_FAIL_EXTENSION -37 /* extension permission problem */ +#define PS_CERT_AUTH_FAIL_PATH_LEN -38 /* pathLen exceeded */ +#define PS_CERT_AUTH_FAIL_AUTHKEY -39 /* subjectKeyid != issuer authKeyid */ + +#define PS_SIGNATURE_MISMATCH -40 /* Algorithms all work but sig not a match */ + +#define PS_AUTH_FAIL -41 /* An AEAD or HASH authentication fail */ + +/* Set as authStatusFlags to certificate callback when authStatus + is PS_CERT_AUTH_FAIL_EXTENSION */ +#define PS_CERT_AUTH_FAIL_KEY_USAGE_FLAG 0x01 +#define PS_CERT_AUTH_FAIL_EKU_FLAG 0x02 +#define PS_CERT_AUTH_FAIL_SUBJECT_FLAG 0x04 +#define PS_CERT_AUTH_FAIL_DATE_FLAG 0x08 + +/******************************************************************************/ +/** + Build the configuration string with the relevant build options for + runtime validation of compile-time configuration. +*/ +#if defined PSTM_X86 || defined PSTM_X86_64 || defined PSTM_ARM || \ + defined PSTM_MIPS + #define PSTM_ASM_CONFIG_STR "Y" +#else + #define PSTM_ASM_CONFIG_STR "N" +#endif +#ifdef PSTM_64BIT + #define PSTM_64_CONFIG_STR "Y" +#else + #define PSTM_64_CONFIG_STR "N" +#endif +#ifdef USE_AESNI_CRYPTO + #define AESNI_CONFIG_STR "Y" +#else + #define AESNI_CONFIG_STR "N" +#endif + #define HW_PKA_CONFIG_STR "N" + #define PKCS11_CONFIG_STR "N" + #define FIPS_CONFIG_STR "N" + +#define PSCRYPTO_CONFIG \ + "Y" \ + PSTM_ASM_CONFIG_STR \ + PSTM_64_CONFIG_STR \ + AESNI_CONFIG_STR \ + HW_PKA_CONFIG_STR \ + PKCS11_CONFIG_STR \ + FIPS_CONFIG_STR \ + PSCORE_CONFIG + +/******************************************************************************/ +/* + Crypto module open/close +*/ +PSPUBLIC int32_t psCryptoOpen(const char *config); +PSPUBLIC void psCryptoClose(void); + +/******************************************************************************/ +/* + Abstract Cipher API + Handles symmetric crypto, aead ciphers, hashes and macs. +*/ +typedef enum { + + AES_CBC_ENC = 1, + AES_CBC_DEC, + AES_GCM_ENC, + AES_GCM_DEC, + CHACHA20_POLY1305_ENC, + CHACHA20_POLY1305_DEC, + ARC4, + DES3, + IDEA, + SEED, + + HASH_MD2, + HASH_MD5, + HASH_SHA1, + HASH_MD5SHA1, + HASH_SHA256, + HASH_SHA384, + HASH_SHA512, + + HMAC_MD5, + HMAC_SHA1, + HMAC_SHA256, + HMAC_SHA384, + +} psCipherType_e; + +/******************************************************************************/ +/* + Symmetric Cipher Algorithms +*/ +#ifdef USE_AES + +#define PS_AES_ENCRYPT 0x1 +#define PS_AES_DECRYPT 0x2 + +#ifdef USE_AES_BLOCK +/******************************************************************************/ +PSPUBLIC int32_t psAesInitBlockKey(psAesKey_t *key, + const unsigned char ckey[AES_MAXKEYLEN], uint8_t keylen, + uint32_t flags); +PSPUBLIC void psAesEncryptBlock(psAesKey_t *key, const unsigned char *pt, + unsigned char *ct); +PSPUBLIC void psAesDecryptBlock(psAesKey_t *key, const unsigned char *ct, + unsigned char *pt); +PSPUBLIC void psAesClearBlockKey(psAesKey_t *key); +#endif + +#ifdef USE_AES_CBC +/******************************************************************************/ +PSPUBLIC int32_t psAesInitCBC(psAesCbc_t *ctx, + const unsigned char IV[AES_IVLEN], + const unsigned char key[AES_MAXKEYLEN], uint8_t keylen, + uint32_t flags); +PSPUBLIC void psAesDecryptCBC(psAesCbc_t *ctx, + const unsigned char *ct, unsigned char *pt, + uint32_t len); +PSPUBLIC void psAesEncryptCBC(psAesCbc_t *ctx, + const unsigned char *pt, unsigned char *ct, + uint32_t len); +PSPUBLIC void psAesClearCBC(psAesCbc_t *ctx); +#endif + +#ifdef USE_AES_GCM +/******************************************************************************/ +PSPUBLIC int32_t psAesInitGCM(psAesGcm_t *ctx, + const unsigned char key[AES_MAXKEYLEN], uint8_t keylen); +PSPUBLIC void psAesReadyGCM(psAesGcm_t *ctx, + const unsigned char IV[AES_IVLEN], + const unsigned char *aad, uint16_t aadLen); +PSPUBLIC void psAesEncryptGCM(psAesGcm_t *ctx, + const unsigned char *pt, unsigned char *ct, + uint32_t len); +PSPUBLIC int32_t psAesDecryptGCM(psAesGcm_t *ctx, + const unsigned char *ct, uint32_t ctLen, + unsigned char *pt, uint32_t ptLen); + +PSPUBLIC void psAesDecryptGCMtagless(psAesGcm_t *ctx, + const unsigned char *ct, unsigned char *pt, + uint32_t len); +PSPUBLIC void psAesGetGCMTag(psAesGcm_t *ctx, + uint8_t tagBytes, unsigned char tag[AES_BLOCKLEN]); +PSPUBLIC void psAesClearGCM(psAesGcm_t *ctx); + +#endif /* USE_AES_GCM */ + + + +#endif /* USE_AES */ + +#ifdef USE_CHACHA20_POLY1305 +/******************************************************************************/ +PSPUBLIC int32_t psChacha20Poly1305Init(psChacha20Poly1305_t *ctx, + const unsigned char key[crypto_aead_chacha20poly1305_KEYBYTES], + uint8_t keylen); +PSPUBLIC void psChacha20Poly1305Ready(psChacha20Poly1305_t *ctx, + const unsigned char IV[crypto_aead_chacha20poly1305_NPUBBYTES+4], + const unsigned char *aad, uint16_t aadLen); +PSPUBLIC void psChacha20Poly1305Encrypt(psChacha20Poly1305_t *ctx, + const unsigned char *pt, unsigned char *ct,uint32_t len); + +PSPUBLIC int32_t psChacha20Poly1305Decrypt(psChacha20Poly1305_t *ctx, + const unsigned char *ct, uint32_t ctLen, + unsigned char *pt, uint32_t ptLen); + +PSPUBLIC void psChacha20Poly1305DecryptTagless(psChacha20Poly1305_t *ctx, + const unsigned char *ct, unsigned char *pt, + uint32_t len); + +PSPUBLIC void psChacha20Poly1305GetTag(psChacha20Poly1305_t *ctx, + uint8_t tagBytes, + unsigned char tag[crypto_aead_chacha20poly1305_ABYTES]); +PSPUBLIC void psChacha20Poly1305Clear(psChacha20Poly1305_t *ctx); +#endif + +#ifdef USE_3DES +/******************************************************************************/ +PSPUBLIC int32_t psDes3Init(psDes3_t *ctx, const unsigned char IV[DES3_IVLEN], + const unsigned char key[DES3_KEYLEN]); +PSPUBLIC void psDes3Decrypt(psDes3_t *ctx, const unsigned char *ct, + unsigned char *pt, uint32_t len); +PSPUBLIC void psDes3Encrypt(psDes3_t *ctx, const unsigned char *pt, + unsigned char *ct, uint32_t len); +PSPUBLIC void psDes3Clear(psDes3_t *ctx); +#endif + +/******************************************************************************/ +/* + Hash Digest Algorithms +*/ +#ifdef USE_MD5 +/******************************************************************************/ +PSPUBLIC int32_t psMd5Init(psMd5_t *md5); +PSPUBLIC void psMd5Update(psMd5_t *md5, const unsigned char *buf, uint32_t len); +PSPUBLIC void psMd5Final(psMd5_t *md, unsigned char hash[MD5_HASHLEN]); +#endif + +#ifdef USE_SHA1 +/******************************************************************************/ +PSPUBLIC int32_t psSha1Init(psSha1_t *sha1); +PSPUBLIC void psSha1Update(psSha1_t *sha1, + const unsigned char *buf, uint32_t len); +PSPUBLIC void psSha1Final(psSha1_t *sha1, unsigned char hash[SHA1_HASHLEN]); +#ifdef USE_CL_DIGESTS +PSPUBLIC void psSha1Sync(psSha1_t *ctx, int sync_all); +PSPUBLIC void psSha1Cpy(psSha1_t *ctx, const psSha1_t *ctx_in); +#else +static __inline void psSha1Sync(psSha1_t *ctx, int sync_all) +{ +} +static __inline void psSha1Cpy(psSha1_t *d, const psSha1_t *s) +{ + memcpy(d, s, sizeof(psSha1_t)); +} +#endif /* USE_CL_DIGESTS */ +#endif /* USE_SHA1 */ + +#ifdef USE_MD5SHA1 +/******************************************************************************/ +PSPUBLIC int32_t psMd5Sha1Init(psMd5Sha1_t *md); +PSPUBLIC void psMd5Sha1Update(psMd5Sha1_t *md, + const unsigned char *buf, uint32_t len); +PSPUBLIC void psMd5Sha1Final(psMd5Sha1_t *md, + unsigned char hash[MD5SHA1_HASHLEN]); +static __inline void psMd5Sha1Sync(psMd5Sha1_t *ctx, int sync_all) +{ +} +static __inline void psMd5Sha1Cpy(psMd5Sha1_t *d, const psMd5Sha1_t *s) +{ + memcpy(d, s, sizeof(psMd5Sha1_t)); +} +#endif /* USE_MD5SHA1 */ + +#ifdef USE_SHA256 +/******************************************************************************/ + +PSPUBLIC int32_t psSha256Init(psSha256_t *sha256); +PSPUBLIC void psSha256Update(psSha256_t *sha256, + const unsigned char *buf, uint32_t len); +PSPUBLIC void psSha256Final(psSha256_t *sha256, + unsigned char hash[SHA256_HASHLEN]); +#ifdef USE_CL_DIGESTS +PSPUBLIC void psSha256Sync(psSha256_t * md, int sync_all); +PSPUBLIC void psSha256Cpy(psSha256_t * d, const psSha256_t * s); +#else +static __inline void psSha256Sync(psSha256_t * md, int sync_all) +{ +} +static __inline void psSha256Cpy(psSha256_t * d, const psSha256_t * s) +{ + memcpy(d, s, sizeof(psSha256_t)); +} +#endif /* USE_CL_DIGESTS */ +#endif /* USE_SHA256 */ + +/******************************************************************************/ +#ifdef USE_SHA384 +PSPUBLIC int32_t psSha384Init(psSha384_t *sha384); +PSPUBLIC void psSha384Update(psSha384_t *sha384, + const unsigned char *buf, uint32_t len); +PSPUBLIC void psSha384Final(psSha384_t *sha384, + unsigned char hash[SHA384_HASHLEN]); +#ifdef USE_CL_DIGESTS +PSPUBLIC void psSha384Sync(psSha384_t * md, int sync_all); +PSPUBLIC void psSha384Cpy(psSha384_t * d, const psSha384_t * s); +#else +static __inline void psSha384Sync(psSha384_t * md, int sync_all) +{ +} +static __inline void psSha384Cpy(psSha384_t * d, const psSha384_t * s) +{ + memcpy(d, s, sizeof(psSha384_t)); +} +#endif /* USE_CL_DIGESTS */ +#endif /* USE_SHA384 */ + +#ifdef USE_SHA512 +/******************************************************************************/ +PSPUBLIC int32_t psSha512Init(psSha512_t *md); +PSPUBLIC void psSha512Update(psSha512_t *md, + const unsigned char *buf, uint32_t len); +PSPUBLIC void psSha512Final(psSha512_t *md, + unsigned char hash[SHA512_HASHLEN]); +#ifdef USE_CL_DIGESTS +PSPUBLIC void psSha512Sync(psSha512_t * md, int sync_all); +PSPUBLIC void psSha512Cpy(psSha512_t * d, const psSha512_t * s); +#else +static __inline void psSha512Sync(psSha512_t * md, int sync_all) +{ +} +static __inline void psSha512Cpy(psSha512_t * d, const psSha512_t * s) +{ + memcpy(d, s, sizeof(psSha512_t)); +} +#endif /* USE_CL_DIGESTS */ +#endif /* USE_SHA512 */ + +/******************************************************************************/ +/* + HMAC Algorithms +*/ +/* Generic HMAC algorithms, specify cipher by type. */ +PSPUBLIC int32_t psHmacInit(psHmac_t *ctx, psCipherType_e type, + const unsigned char *key, uint16_t keyLen); +PSPUBLIC void psHmacUpdate(psHmac_t *ctx, + const unsigned char *buf, uint32_t len); +PSPUBLIC void psHmacFinal(psHmac_t *ctx, + unsigned char hash[MAX_HASHLEN]); + +#ifdef USE_HMAC_MD5 +/******************************************************************************/ +PSPUBLIC int32_t psHmacMd5(const unsigned char *key, uint16_t keyLen, + const unsigned char *buf, uint32_t len, + unsigned char hash[MD5_HASHLEN], + unsigned char *hmacKey, uint16_t *hmacKeyLen); +PSPUBLIC int32_t psHmacMd5Init(psHmacMd5_t *ctx, + const unsigned char *key, uint16_t keyLen); +PSPUBLIC void psHmacMd5Update(psHmacMd5_t *ctx, + const unsigned char *buf, uint32_t len); +PSPUBLIC void psHmacMd5Final(psHmacMd5_t *ctx, + unsigned char hash[MD5_HASHLEN]); +#endif + +#ifdef USE_HMAC_SHA1 +/******************************************************************************/ +PSPUBLIC int32_t psHmacSha1(const unsigned char *key, uint16_t keyLen, + const unsigned char *buf, uint32_t len, + unsigned char hash[SHA1_HASHLEN], + unsigned char *hmacKey, uint16_t *hmacKeyLen); +#ifdef USE_HMAC_TLS +PSPUBLIC int32_t psHmacSha1Tls(const unsigned char *key, uint32_t keyLen, + const unsigned char *buf1, uint32_t len1, + const unsigned char *buf2, uint32_t len2, + const unsigned char *buf3, uint32_t len3, + uint32_t len3_alt, unsigned char *hmac); +#endif +PSPUBLIC int32_t psHmacSha1Init(psHmacSha1_t *ctx, + const unsigned char *key, uint16_t keyLen); +PSPUBLIC void psHmacSha1Update(psHmacSha1_t *ctx, + const unsigned char *buf, uint32_t len); +PSPUBLIC void psHmacSha1Final(psHmacSha1_t *ctx, + unsigned char hash[SHA1_HASHLEN]); +#endif + +#ifdef USE_HMAC_SHA256 +/******************************************************************************/ +PSPUBLIC int32_t psHmacSha256(const unsigned char *key, uint16_t keyLen, + const unsigned char *buf, uint32_t len, + unsigned char hash[SHA256_HASHLEN], + unsigned char *hmacKey, uint16_t *hmacKeyLen); +#ifdef USE_HMAC_TLS +PSPUBLIC int32 psHmacSha2Tls(const unsigned char *key, uint32 keyLen, + const unsigned char *buf1, uint32 len1, + const unsigned char *buf2, uint32 len2, + const unsigned char *buf3, uint32 len3, + uint32 len3_alt, unsigned char *hmac, + uint32 hashSize); +#endif +PSPUBLIC int32_t psHmacSha256Init(psHmacSha256_t *ctx, + const unsigned char *key, uint16_t keyLen); +PSPUBLIC void psHmacSha256Update(psHmacSha256_t *ctx, + const unsigned char *buf, uint32_t len); +PSPUBLIC void psHmacSha256Final(psHmacSha256_t *ctx, + unsigned char hash[SHA256_HASHLEN]); +#endif +#ifdef USE_HMAC_SHA384 +/******************************************************************************/ +PSPUBLIC int32_t psHmacSha384(const unsigned char *key, uint16_t keyLen, + const unsigned char *buf, uint32_t len, + unsigned char hash[SHA384_HASHLEN], + unsigned char *hmacKey, uint16_t *hmacKeyLen); +PSPUBLIC int32_t psHmacSha384Init(psHmacSha384_t *ctx, + const unsigned char *key, uint16_t keyLen); +PSPUBLIC void psHmacSha384Update(psHmacSha384_t *ctx, + const unsigned char *buf, uint32_t len); +PSPUBLIC void psHmacSha384Final(psHmacSha384_t *ctx, + unsigned char hash[SHA384_HASHLEN]); +#endif + + + +/******************************************************************************/ +/* + Private Key Parsing + PKCS#1 - RSA specific + PKCS#8 - General private key storage format +*/ +#ifdef USE_PRIVATE_KEY_PARSING +#ifdef MATRIX_USE_FILE_SYSTEM +#ifdef USE_RSA +PSPUBLIC int32_t pkcs1ParsePrivFile(psPool_t *pool, const char *fileName, + const char *password, psRsaKey_t *key); +#endif +PSPUBLIC int32_t pkcs1DecodePrivFile(psPool_t *pool, const char *fileName, + const char *password, unsigned char **DERout, uint16_t *DERlen); +#endif /* MATRIX_USE_FILESYSTEM */ +#ifdef USE_PKCS8 +PSPUBLIC int32 pkcs8ParsePrivBin(psPool_t *pool, unsigned char *p, + int32 size, char *pass, psPubKey_t *key); +#if defined(MATRIX_USE_FILE_SYSTEM) && defined (USE_PKCS12) +PSPUBLIC int32 psPkcs12Parse(psPool_t *pool, psX509Cert_t **cert, + psPubKey_t *privKey, const unsigned char *file, int32 flags, + unsigned char *importPass, int32 ipasslen, + unsigned char *privkeyPass, int32 kpasslen); +#endif +#endif /* USE_PKCS8 */ +#endif /* USE_PRIVATE_KEY_PARSING */ + +#ifdef USE_PKCS5 +/******************************************************************************/ +/* + PKCS#5 PBKDF v1 and v2 key generation +*/ +PSPUBLIC void pkcs5pbkdf1(unsigned char *pass, uint32 passlen, + unsigned char *salt, int32 iter, unsigned char *key); +PSPUBLIC void pkcs5pbkdf2(unsigned char *password, uint32 pLen, + unsigned char *salt, uint32 sLen, int32 rounds, + unsigned char *key, uint32 kLen); +#endif /* USE_PKCS5 */ + +/******************************************************************************/ +/* + Public Key Cryptography +*/ +#if defined(USE_RSA) || defined(USE_ECC) || defined(USE_DH) +PSPUBLIC int32_t psInitPubKey(psPool_t *pool, psPubKey_t *key, uint8_t type); +PSPUBLIC void psClearPubKey(psPubKey_t *key); +PSPUBLIC int32_t psNewPubKey(psPool_t *pool, uint8_t type, psPubKey_t **key); +PSPUBLIC void psDeletePubKey(psPubKey_t **key); +PSPUBLIC int32_t psParseUnknownPrivKey(psPool_t *pool, int pemOrDer, + char *keyfile, char *password, psPubKey_t *privkey); +#endif + +#ifdef USE_RSA +/******************************************************************************/ + +PSPUBLIC int32_t psRsaInitKey(psPool_t *pool, psRsaKey_t *key); +PSPUBLIC void psRsaClearKey(psRsaKey_t *key); +PSPUBLIC int32_t psRsaCopyKey(psRsaKey_t *to, const psRsaKey_t *from); + +PSPUBLIC int32_t psRsaParsePkcs1PrivKey(psPool_t *pool, + const unsigned char *p, uint16_t size, + psRsaKey_t *key); +PSPUBLIC int32_t psRsaParseAsnPubKey(psPool_t *pool, + const unsigned char **pp, uint16_t len, + psRsaKey_t *key, unsigned char sha1KeyHash[SHA1_HASHLEN]); +PSPUBLIC uint16_t psRsaSize(const psRsaKey_t *key); +PSPUBLIC int32_t psRsaCmpPubKey(const psRsaKey_t *k1, const psRsaKey_t *k2); + +PSPUBLIC int32_t psRsaEncryptPriv(psPool_t *pool, psRsaKey_t *key, + const unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + void *data); +PSPUBLIC int32_t psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key, + const unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + void *data); +PSPUBLIC int32_t psRsaDecryptPriv(psPool_t *pool, psRsaKey_t *key, + unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + void *data); +PSPUBLIC int32_t psRsaDecryptPub(psPool_t *pool, psRsaKey_t *key, + unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + void *data); + + +PSPUBLIC int32_t psRsaCrypt(psPool_t *pool, psRsaKey_t *key, + const unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t *outlen, + uint8_t type, void *data); + +PSPUBLIC int32_t pubRsaDecryptSignedElement(psPool_t *pool, psRsaKey_t *key, + unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + void *data); +PSPUBLIC int32_t privRsaEncryptSignedElement(psPool_t *pool, psRsaKey_t *key, + const unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + void *data); +#ifdef USE_PKCS1_OAEP +PSPUBLIC int32 pkcs1OaepEncode(psPool_t *pool, const unsigned char *msg, + uint32 msglen, const unsigned char *lparam, + uint32 lparamlen, unsigned char *seed, uint32 seedLen, + uint32 modulus_bitlen, int32 hash_idx, + unsigned char *out, uint16_t *outlen); +PSPUBLIC int32 pkcs1OaepDecode(psPool_t *pool, const unsigned char *msg, + uint32 msglen, const unsigned char *lparam, uint32 lparamlen, + uint32 modulus_bitlen, int32 hash_idx, + unsigned char *out, uint16_t *outlen); +#endif /* USE_PKCS1_OAEP */ +#ifdef USE_PKCS1_PSS +PSPUBLIC int32 pkcs1PssEncode(psPool_t *pool, const unsigned char *msghash, + uint32 msghashlen, unsigned char *salt, uint32 saltlen, + int32 hash_idx, uint32 modulus_bitlen, unsigned char *out, + uint16_t *outlen); +PSPUBLIC int32 pkcs1PssDecode(psPool_t *pool, const unsigned char *msghash, + uint32 msghashlen, const unsigned char *sig, uint32 siglen, + uint32 saltlen, int32 hash_idx, uint32 modulus_bitlen, int32 *res); +#endif /* USE_PKCS1_PSS */ +#endif /* USE_RSA */ + +#ifdef USE_ECC +/******************************************************************************/ + +PSPUBLIC int32_t psEccInitKey(psPool_t *pool, psEccKey_t *key, + const psEccCurve_t *curve); +PSPUBLIC void psEccClearKey(psEccKey_t *key); +PSPUBLIC int32_t psEccNewKey(psPool_t *pool, psEccKey_t **key, + const psEccCurve_t *curve); +PSPUBLIC void psEccDeleteKey(psEccKey_t **key); +PSPUBLIC int32 psEccCopyKey(psEccKey_t *to, psEccKey_t *from); +PSPUBLIC uint8_t psEccSize(const psEccKey_t *key); + +PSPUBLIC int32_t psEccGenKey(psPool_t *pool, psEccKey_t *key, + const psEccCurve_t *curve, void *usrData); + +PSPUBLIC int32_t psEccParsePrivKey(psPool_t *pool, + const unsigned char *keyBuf, uint16_t keyBufLen, + psEccKey_t *keyPtr, const psEccCurve_t *curve); +PSPUBLIC int32_t psEccParsePrivFile(psPool_t *pool, + const char *fileName, const char *password, + psEccKey_t *key); + +PSPUBLIC int32_t psEccX963ImportKey(psPool_t *pool, + const unsigned char *in, uint16_t inlen, + psEccKey_t *key, const psEccCurve_t *curve); +PSPUBLIC int32_t psEccX963ExportKey(psPool_t *pool, const psEccKey_t *key, + unsigned char *out, uint16_t *outlen); + +PSPUBLIC int32_t psEccGenSharedSecret(psPool_t *pool, + const psEccKey_t *privKey, const psEccKey_t *pubKey, + unsigned char *outbuf, uint16_t *outlen, void *usrData); + +PSPUBLIC int32_t psEccDsaSign(psPool_t *pool, const psEccKey_t *privKey, + const unsigned char *buf, uint16_t buflen, + unsigned char *sig, uint16_t *siglen, + uint8_t includeSize, void *usrData); +PSPUBLIC int32_t psEccDsaVerify(psPool_t *pool, const psEccKey_t *key, + const unsigned char *buf, uint16_t bufLen, + const unsigned char *sig, uint16_t siglen, + int32_t *status, void *usrData); +#endif /* USE_ECC */ + +#ifdef USE_DH +/******************************************************************************/ +/* + PKCS#3 - Diffie-Hellman parameters +*/ +PSPUBLIC int32_t pkcs3ParseDhParamBin(psPool_t *pool, + const unsigned char *dhBin, uint16_t dhBinLen, + psDhParams_t *params); +#ifdef MATRIX_USE_FILE_SYSTEM +PSPUBLIC int32_t pkcs3ParseDhParamFile(psPool_t *pool,const char *fileName, + psDhParams_t *params); +#endif +PSPUBLIC int32_t psDhExportParameters(psPool_t *pool, + const psDhParams_t *params, + unsigned char **pp, uint16_t *pLen, + unsigned char **pg, uint16_t *gLen); +PSPUBLIC void pkcs3ClearDhParams(psDhParams_t *params); + +PSPUBLIC int32_t psDhImportPubKey(psPool_t *pool, + const unsigned char *inbuf, uint16_t inlen, + psDhKey_t *key); +PSPUBLIC int32_t psDhExportPubKey(psPool_t *pool, const psDhKey_t *key, + unsigned char *out, uint16_t *outlen); +PSPUBLIC void psDhClearKey(psDhKey_t *key); +PSPUBLIC uint16_t psDhSize(const psDhKey_t *key); + +PSPUBLIC int32_t psDhGenKey(psPool_t *pool, uint16_t keysize, + const unsigned char *pBin, uint16_t pLen, + const unsigned char *gBin, uint16_t gLen, + psDhKey_t *key, void *usrData); +PSPUBLIC int32_t psDhGenKeyInts(psPool_t *pool, uint16_t keysize, + const pstm_int *p, const pstm_int *g, + psDhKey_t *key, void *usrData); + +PSPUBLIC int32_t psDhGenSharedSecret(psPool_t *pool, + const psDhKey_t *privKey, const psDhKey_t *pubKey, + const unsigned char *pBin, uint16_t pBinLen, + unsigned char *out, uint16_t *outlen, void *usrData); + +#endif /* USE_DH */ + +#ifdef USE_X509 +/******************************************************************************/ +/* + X.509 Certificate support +*/ +PSPUBLIC int32 psX509ParseCertFile(psPool_t *pool, char *fileName, + psX509Cert_t **outcert, int32 flags); +PSPUBLIC int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 size, + psX509Cert_t **outcert, int32 flags); +PSPUBLIC void psX509FreeCert(psX509Cert_t *cert); +#ifdef USE_CERT_PARSE +PSPUBLIC int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert, + psX509Cert_t *issuerCert, psX509Cert_t **foundIssuer, + void *hwCtx, void *poolUserPtr); +#endif +#ifdef USE_CRL +PSPUBLIC int32 psX509ParseCrl(psPool_t *pool, psX509Cert_t *CA, int append, + unsigned char *crlBin, int32 crlBinLen, void *poolUserPtr); +#endif /* USE_CRL */ +#endif /* USE_X509 */ + +/******************************************************************************/ +/* + Pseudorandom Number Generation +*/ +PSPUBLIC int32_t psInitPrng(psRandom_t *ctx, void *userPtr); +PSPUBLIC int32_t psGetPrng(psRandom_t *ctx, unsigned char *bytes, uint16_t size, + void *userPtr); + + +/******************************************************************************/ +/* + Deprecated Algorithms +*/ +#ifdef USE_ARC4 +/******************************************************************************/ +PSPUBLIC int32_t psArc4Init(psArc4_t *ctx, + const unsigned char *key, uint8_t keylen); +PSPUBLIC void psArc4(psArc4_t *ctx, const unsigned char *in, + unsigned char *out, uint32_t len); +PSPUBLIC void psArc4Clear(psArc4_t *ctx); +#endif + +#ifdef USE_SEED +/******************************************************************************/ +PSPUBLIC int32_t psSeedInit(psSeed_t *ctx, const unsigned char IV[SEED_IVLEN], + const unsigned char key[SEED_KEYLEN]); +PSPUBLIC void psSeedDecrypt(psSeed_t *ctx, const unsigned char *ct, + unsigned char *pt, uint32_t len); +PSPUBLIC void psSeedEncrypt(psSeed_t *ctx, const unsigned char *pt, + unsigned char *ct, uint32_t len); +PSPUBLIC void psSeedClear(psSeed_t *ctx); +#endif + +#ifdef USE_IDEA +/******************************************************************************/ +PSPUBLIC int32_t psIdeaInit(psIdea_t *ctx, const unsigned char IV[IDEA_IVLEN], + const unsigned char key[IDEA_KEYLEN]); +PSPUBLIC void psIdeaDecrypt(psIdea_t *ctx, const unsigned char *ct, + unsigned char *pt, uint32_t len); +PSPUBLIC void psIdeaEncrypt(psIdea_t *ctx, const unsigned char *pt, + unsigned char *ct, uint32_t len); +PSPUBLIC void psIdeaClear(psIdea_t *ctx); +#endif + +#ifdef USE_RC2 +/******************************************************************************/ +PSPUBLIC int32_t psRc2Init(psRc2Cbc_t *ctx, const unsigned char *IV, + const unsigned char *key, uint8_t keylen); +PSPUBLIC int32_t psRc2Decrypt(psRc2Cbc_t *ctx, const unsigned char *ct, + unsigned char *pt, uint32_t len); +PSPUBLIC int32_t psRc2Encrypt(psRc2Cbc_t *ctx, const unsigned char *pt, + unsigned char *ct, uint32_t len); +#endif + +#ifdef USE_MD4 +/******************************************************************************/ +PSPUBLIC void psMd4Init(psMd4_t *md); +PSPUBLIC void psMd4Update(psMd4_t *md, const unsigned char *buf, uint32_t len); +PSPUBLIC int32_t psMd4Final(psMd4_t *md, unsigned char *hash); +#endif + +#ifdef USE_MD2 +/******************************************************************************/ +PSPUBLIC void psMd2Init(psMd2_t *md); +PSPUBLIC int32_t psMd2Update(psMd2_t *md, const unsigned char *buf, + uint32_t len); +PSPUBLIC int32_t psMd2Final(psMd2_t *md, unsigned char *hash); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _h_PS_CRYPTOAPI */ + +/******************************************************************************/ + diff --git a/crypto/cryptoCheck.h b/crypto/cryptoCheck.h new file mode 100644 index 0000000..1a40151 --- /dev/null +++ b/crypto/cryptoCheck.h @@ -0,0 +1,130 @@ +/** + * @file cryptoCheck.h + * @version $Format:%h%d$ + * + * Configuration validation/sanity checks. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_PS_CRYPTOCHECK +#define _h_PS_CRYPTOCHECK + +/******************************************************************************/ +/* +*/ +#ifdef USE_CERT_PARSE + #ifndef USE_X509 + #error "Must enable USE_X509 if USE_CERT_PARSE is enabled" + #endif + #if !defined(USE_MD5) && !defined(USE_SHA1) && !defined(USE_SHA256) + #error "At least one of USE_MD5, USE_SHA1 or USE_SHA256 must be enabled for USE_CERT_PARSE" + #endif +#endif + +#ifdef USE_PKCS5 + #ifndef USE_MD5 + #error "Enable USE_MD5 in cryptoConfig.h for PKCS5 support" + #endif + #ifndef USE_3DES + #error "Enable USE_3DES in cryptoConfig.h for PKCS5 support" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for PKCS5 support" + #endif +#endif + +#ifdef USE_PKCS8 + #ifndef USE_HMAC_SHA1 + #error "Enable USE_HMAC_SHA1 in cryptoConfig.h for PKCS8 support" + #endif +#endif + + #define USE_NATIVE_ECC + #define USE_NATIVE_AES + #define USE_NATIVE_HASH + +#ifdef USE_PKCS12 + #ifndef USE_PKCS8 + #error "Enable USE_PKCS8 in cryptoConfig.h for PKCS12 support" + #endif +#else + #ifdef USE_RC2 + #error "RC2 only allowed for PKCS12 support" + #endif +#endif + +#ifdef USE_CERT_PARSE + #ifndef USE_X509 + #error "USE_X509 required for USE_CERT_PARSE" + #endif +#endif + +#ifdef USE_FULL_CERT_PARSE + #ifndef USE_CERT_PARSE + #error "USE_CERT_PARSE required for USE_FULL_CERT_PARSE" + #endif +#endif + +#ifdef ENABLE_CA_CERT_HASH + #if !defined(USE_SHA1) || !defined(USE_X509) + #error "USE_SHA1 and USE_X509 required for ENABLE_CA_CERT_HASH" + #endif +#endif + +#ifdef USE_OCSP + #ifndef USE_SHA1 + #error "Enable USE_SHA1 in cryptoConfig.h for OCSP support" + #endif +#endif + +/******************************************************************************/ +/** + Below this point, no configurations should be automatically set or unset + Above, it's allowed to a point. +*/ + +/** + Allow only FIPS approved algorithm configuration. + FIPSLib runtime will not support these algorithms anyway, but this is a configuration + time check +*/ + +/** + NIST mode configuration checks. + Allow NIST_SHALL NIST_SHOULD and NIST_MAY algorithm configuration. + Warn on NIST_SHOULD_NOT + Error on NIST_SHALL_NOT +*/ +#ifdef USE_NIST_RECOMMENDATIONS +#endif + +#endif /* _h_PS_CRYPTOCHECK */ + +/******************************************************************************/ + diff --git a/crypto/cryptoConfig.h b/crypto/cryptoConfig.h new file mode 100644 index 0000000..73ee731 --- /dev/null +++ b/crypto/cryptoConfig.h @@ -0,0 +1,189 @@ +/** + * @file cryptoConfig.h + * @version $Format:%h%d$ + * + * Configuration file for crypto features. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_PS_CRYPTOCONFIG +#define _h_PS_CRYPTOCONFIG + +/******************************************************************************/ +/* Configurable features */ +/******************************************************************************/ +/** + Define to enable psTrace*Crypto APIs for debugging the crypto module. +*/ +//#define USE_CRYPTO_TRACE + +#ifdef DEBUG +// #define CRYPTO_ASSERT /**< Extra sanity asserts */ +#endif + +/******************************************************************************/ +/** + Security related settings. + + @security MIN_*_BITS is the minimum supported key sizes in bits, weaker + keys will be rejected. +*/ +#define MIN_ECC_BITS 192 /**< @security Affects ECC curves below */ + +#define MIN_RSA_BITS 1024 + +#define MIN_DH_BITS 1024 + +#define USE_BURN_STACK /**< @security Zero sensitive data from the stack. */ + + + +/******************************************************************************/ +/** + Public-Key Algorithm Support. +*/ +#define USE_RSA +#define USE_ECC +//#define USE_DH + +/******************************************************************************/ + +/** + Define to enable the individual NIST Prime curves. + @see http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf +*/ +#ifdef USE_ECC + #define USE_SECP192R1 /**< @security FIPS allowed for sig ver only. */ + #define USE_SECP224R1 + #define USE_SECP256R1 /**< @security NIST_SHALL */ + #define USE_SECP384R1 /**< @security NIST_SHALL */ + #define USE_SECP521R1 +#endif + +/** + Define to enable the individual Brainpool curves. + @see https://tools.ietf.org/html/rfc5639 + @security WARNING: Public points on Brainpool curves are not validated +*/ +#ifdef USE_ECC +//#define USE_BRAIN224R1 +//#define USE_BRAIN256R1 +//#define USE_BRAIN384R1 +//#define USE_BRAIN512R1 +#endif + +/******************************************************************************/ +/** + Symmetric and AEAD ciphers. + @security Deprecated ciphers must be enabled in cryptolib.h +*/ +#define USE_AES_CBC +#define USE_AES_GCM + +#ifdef USE_LIBSODIUM_CRYPTO + #define USE_CHACHA20_POLY1305 +#endif + +/** @security 3DES is still relatively secure, however is deprecated for TLS */ +//#define USE_3DES + +/******************************************************************************/ +/** + Digest algorithms. + + @note SHA256 and above are used with TLS 1.2, and also used for + certificate signatures on some certificates regardless of TLS version. + + @security MD5 is deprecated, but still required in combination with SHA-1 + for TLS handshakes before TLS 1.2, meaning that the strength is at least + that of SHA-1 in this usage. The only other usage of MD5 by TLS is for + certificate signatures and MD5 based cipher suites. Both of which are + disabled at compile time by default. + + @security SHA1 will be deprecated in the future, but is still required in + combination with MD5 for versions prior to TLS 1.2. In addition, SHA1 + certificates are still commonly used, so SHA1 support may be needed + to validate older certificates. It is possible to completely disable + SHA1 using TLS 1.2 and SHA2 based ciphersuites, and interacting + only with newer certificates. +*/ +//#define USE_SHA224 /**< @note Used only for cert signature */ +#define USE_SHA256 /**< @note Required for TLS 1.2 and above */ +#define USE_HMAC_SHA256 +#define USE_SHA384 /**< @pre USE_SHA512 */ +#define USE_HMAC_SHA384 +#define USE_SHA512 + +/** + @security SHA-1 based hashes are deprecated but enabled by default + @note ENABLE_SHA1_SIGNED_CERTS can additionally be configured below. +*/ +#define USE_SHA1 +#define USE_HMAC_SHA1 + +/** + @security MD5 is considered insecure, but required by TLS < 1.2 + @note ENABLE_MD5_SIGNED_CERTS can additionally be configured below. +*/ +#define USE_MD5 +#define USE_MD5SHA1 /* Required for < TLS 1.2 Handshake */ +#define USE_HMAC_MD5 /* TODO currently needed for prf */ + + +/******************************************************************************/ +/** + X.509 Certificates/PKI +*/ +#define USE_BASE64_DECODE +#define USE_X509 +#define USE_CERT_PARSE /**< Usually required. @pre USE_X509 */ +#define USE_FULL_CERT_PARSE /**< @pre USE_CERT_PARSE */ +//#define ENABLE_CA_CERT_HASH /**< Used only for TLS trusted CA ind ext. */ +//#define ENABLE_MD5_SIGNED_CERTS /** @security Accept MD5 signed certs? */ +#define ENABLE_SHA1_SIGNED_CERTS /** @security Accept SHA1 signed certs? */ + +//#define USE_CRL /***< @pre USE_FULL_CERT_PARSE */ +//#define USE_OCSP /**< @pre USE_SHA1 */ + +/******************************************************************************/ +/** + Various PKCS standards support +*/ +#define USE_PRIVATE_KEY_PARSING +//#define USE_PKCS5 /**< v2.0 PBKDF encrypted priv keys. @pre USE_3DES */ +//#define USE_PKCS8 /* Alternative private key storage format */ +//#define USE_PKCS12 /**< @pre USE_PKCS8 */ +//#define USE_PKCS1_OAEP /* OAEP padding algorithm */ +//#define USE_PKCS1_PSS /* PSS padding algorithm */ + + +#endif /* _h_PS_CRYPTOCONFIG */ + +/******************************************************************************/ + diff --git a/crypto/cryptolib.h b/crypto/cryptolib.h new file mode 100644 index 0000000..7530701 --- /dev/null +++ b/crypto/cryptolib.h @@ -0,0 +1,560 @@ +/** + * @file cryptolib.h + * @version $Format:%h%d$ + * + * Header file for definitions used with crypto lib. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_PS_CRYPTOLIB +#define _h_PS_CRYPTOLIB + +/******************************************************************************/ +/* + Additional 'hidden' algorithm configuration here for deprecated support +*/ + +/** Symmetric. @security These are generally insecure and not enabled by default. */ +//#define USE_ARC4 +//#define USE_SEED +//#define USE_IDEA +#ifdef USE_PKCS12 +//#define USE_RC2 /* Only PKCS#12 parse should ever want this algorithm */ +#endif + +/** Digest. @security These are generally insecure and not enabled by default */ +//#define USE_MD4 +//#define USE_MD2 + +/** PRNG. @security By default the OS PRNG will be used directly. */ +#define USE_PRNG +//#define USE_YARROW + +/******************************************************************************/ +/* + Additional configuration that is usually not modified. +*/ +#define OCSP_VALID_TIME_WINDOW 604800 /* In seconds (1 week default window) */ + +/******************************************************************************/ +/* + Include crypto provider layer headers +*/ +#include "layer/layer.h" + + +/* Configuration validation/sanity checks */ +#include "cryptoCheck.h" + +/* Implementation layer */ +#include "symmetric/symmetric.h" +#include "digest/digest.h" +#include "math/pstm.h" +#include "pubkey/pubkey.h" +#include "keyformat/asn1.h" +#include "keyformat/x509.h" +#include "prng/prng.h" + +/******************************************************************************/ +/* + Crypto trace +*/ +#ifndef USE_CRYPTO_TRACE +#define psTraceCrypto(x) +#define psTraceStrCrypto(x, y) +#define psTraceIntCrypto(x, y) +#define psTracePtrCrypto(x, y) +#else +#define psTraceCrypto(x) _psTrace(x) +#define psTraceStrCrypto(x, y) _psTraceStr(x, y) +#define psTraceIntCrypto(x, y) _psTraceInt(x, y) +#define psTracePtrCrypto(x, y) _psTracePtr(x, y) +#endif /* USE_CRYPTO_TRACE */ + +/******************************************************************************/ +/* + Helpers +*/ +extern int32_t psBase64decode(const unsigned char *in, uint16_t len, + unsigned char *out, uint16_t *outlen); +extern void psOpenPrng(void); +extern void psClosePrng(void); +extern int32_t matrixCryptoGetPrngData(unsigned char *bytes, uint16_t size, + void *userPtr); + +/******************************************************************************/ +/* + RFC 3279 OID + Matrix uses an oid summing mechanism to arrive at these defines. + The byte values of the OID are summed to produce a "relatively unique" int + + The duplicate defines do not pose a problem as long as they don't + exist in the same OID groupings +*/ +/* Raw digest algorithms */ +#define OID_SHA1_ALG 88 +#define OID_SHA256_ALG 414 +#define OID_SHA384_ALG 415 +#define OID_SHA512_ALG 416 +#define OID_MD2_ALG 646 +#define OID_MD5_ALG 649 + +/* Signature algorithms */ +#define OID_MD2_RSA_SIG 646 +#define OID_MD5_RSA_SIG 648 /* 42.134.72.134.247.13.1.1.4 */ +#define OID_SHA1_RSA_SIG 649 /* 42.134.72.134.247.13.1.1.5 */ +#define OID_ID_MGF1 652 /* 42.134.72.134.247.13.1.1.8 */ +#define OID_RSASSA_PSS 654 /* 42.134.72.134.247.13.1.1.10 */ +#define OID_SHA256_RSA_SIG 655 /* 42.134.72.134.247.13.1.1.11 */ +#define OID_SHA384_RSA_SIG 656 /* 42.134.72.134.247.13.1.1.12 */ +#define OID_SHA512_RSA_SIG 657 /* 42.134.72.134.247.13.1.1.13 */ +#define OID_SHA1_ECDSA_SIG 520 /* 42.134.72.206.61.4.1 */ +#define OID_SHA224_ECDSA_SIG 523 /* 42.134.72.206.61.4.3.1 */ +#define OID_SHA256_ECDSA_SIG 524 /* 42.134.72.206.61.4.3.2 */ +#define OID_SHA384_ECDSA_SIG 525 /* 42.134.72.206.61.4.3.3 */ +#define OID_SHA512_ECDSA_SIG 526 /* 42.134.72.206.61.4.3.4 */ + +/* Public key algorithms */ +#define OID_RSA_KEY_ALG 645 +#define OID_ECDSA_KEY_ALG 518 /* 1.2.840.10045.2.1 */ + +/* Encryption algorithms */ +#define OID_DES_EDE3_CBC 652 /* 42.134.72.134.247.13.3.7 */ +#define OID_AES_128_CBC 414 /* 2.16.840.1.101.3.4.1.2 */ +#define OID_AES_128_WRAP 417 /* 2.16.840.1.101.3.4.1.5 */ +#define OID_AES_128_GCM 418 /* 2.16.840.1.101.3.4.1.6 */ +#define OID_AES_192_CBC 434 /* 2.16.840.1.101.3.4.1.22 */ +#define OID_AES_192_WRAP 437 /* 2.16.840.1.101.3.4.1.25 */ +#define OID_AES_192_GCM 438 /* 2.16.840.1.101.3.4.1.26 */ +#define OID_AES_256_CBC 454 /* 2.16.840.1.101.3.4.1.42 */ +#define OID_AES_256_WRAP 457 /* 2.16.840.1.101.3.4.1.45 */ +#define OID_AES_256_GCM 458 /* 2.16.840.1.101.3.4.1.46 */ + + /* TODO: Made this up. Couldn't find */ +#define OID_AES_CMAC 612 /* 2.16.840.1.101.3.4.1.200 */ + +/* TODO: These are not officially defined yet */ +#define OID_AES_CBC_CMAC_128 143 +#define OID_AES_CBC_CMAC_192 144 +#define OID_AES_CBC_CMAC_256 145 + +#define OID_AUTH_ENC_256_SUM 687 /* The RFC 6476 authEnc OID */ + +#ifdef USE_PKCS5 +#define OID_PKCS_PBKDF2 660 /* 42.134.72.134.247.13.1.5.12 */ +#define OID_PKCS_PBES2 661 /* 42.134.72.134.247.13.1.5.13 */ +#endif /* USE_PKCS5 */ + +#ifdef USE_PKCS12 +#define OID_PKCS_PBESHA128RC4 657 +#define OID_PKCS_PBESHA40RC4 658 +#define OID_PKCS_PBESHA3DES3 659 +#define OID_PKCS_PBESHA3DES2 660 /* warning: collision with pkcs5 */ +#define OID_PKCS_PBESHA128RC2 661 /* warning: collision with pkcs5 */ +#define OID_PKCS_PBESHA40RC2 662 + +#define PKCS12_BAG_TYPE_KEY 667 +#define PKCS12_BAG_TYPE_SHROUD 668 +#define PKCS12_BAG_TYPE_CERT 669 +#define PKCS12_BAG_TYPE_CRL 670 +#define PKCS12_BAG_TYPE_SECRET 671 +#define PKCS12_BAG_TYPE_SAFE 672 + +#define PBE12 1 +#define PBES2 2 +#define AUTH_SAFE_3DES 1 +#define AUTH_SAFE_RC2 2 + +#define PKCS12_KEY_ID 1 +#define PKCS12_IV_ID 2 +#define PKCS12_MAC_ID 3 + +#define PKCS9_CERT_TYPE_X509 675 +#define PKCS9_CERT_TYPE_SDSI 676 + +#define PKCS7_DATA 651 +/* signedData 1.2.840.113549.1.7.2 (2A 86 48 86 F7 0D 01 07 02) */ +#define PKCS7_SIGNED_DATA 652 +#define PKCS7_ENVELOPED_DATA 653 +#define PKCS7_SIGNED_ENVELOPED_DATA 654 +#define PKCS7_DIGESTED_DATA 655 +#define PKCS7_ENCRYPTED_DATA 656 +#endif /* USE_PKCS12 */ + +#if defined(USE_PKCS1_OAEP) || defined(USE_PKCS1_PSS) +#define PKCS1_SHA1_ID 0 +#define PKCS1_MD5_ID 1 +#define PKCS1_SHA256_ID 2 +#define PKCS1_SHA384_ID 3 +#define PKCS1_SHA512_ID 4 +#endif + +/******************************************************************************/ +/* These values are all mutually exlusive bits to define Cipher flags */ +#define CRYPTO_FLAGS_AES (1<<0) +#define CRYPTO_FLAGS_AES256 (1<<1) +#define CRYPTO_FLAGS_3DES (1<<2) +#define CRYPTO_FLAGS_ARC4 (1<<3) +#define CRYPTO_FLAGS_SEED (1<<4) +#define CRYPTO_FLAGS_IDEA (1<<5) +#define CRYPTO_FLAGS_CHACHA (1<<6) /* Short for CHACHA20_POLY2305 */ + +#define CRYPTO_FLAGS_SHA1 (1<< 8) +#define CRYPTO_FLAGS_SHA2 (1<< 9) +#define CRYPTO_FLAGS_SHA3 (1<<10) +#define CRYPTO_FLAGS_GCM (1<<11) +#define CRYPTO_FLAGS_CCM (1<<12) +#define CRYPTO_FLAGS_CCM8 (1<<13) /* CCM mode with 8 byte ICV */ +#define CRYPTO_FLAGS_MD5 (1<<14) + +#define CRYPTO_FLAGS_TLS (1<<16) +#define CRYPTO_FLAGS_TLS_1_1 (1<<17) +#define CRYPTO_FLAGS_TLS_1_2 (1<<18) + +#define CRYPTO_FLAGS_INBOUND (1<<24) +#define CRYPTO_FLAGS_ARC4INITE (1<<25) +#define CRYPTO_FLAGS_ARC4INITD (1<<26) +#define CRYPTO_FLAGS_BLOCKING (1<<27) + +#define CRYPTO_FLAGS_DISABLED (1<<30) + +/******************************************************************************/ + +#define CRYPT_INVALID_KEYSIZE -21 +#define CRYPT_INVALID_ROUNDS -22 + +/******************************************************************************/ +/* 32-bit Rotates */ +/******************************************************************************/ +#if defined(_MSC_VER) +/******************************************************************************/ + +/* instrinsic rotate */ +#include +#pragma intrinsic(_lrotr,_lrotl) +#define ROR(x,n) _lrotr(x,n) +#define ROL(x,n) _lrotl(x,n) + +/******************************************************************************/ +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && \ + !defined(INTEL_CC) && !defined(PS_NO_ASM) + +static __inline unsigned ROL(unsigned word, int i) +{ + asm ("roll %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +static __inline unsigned ROR(unsigned word, int i) +{ + asm ("rorl %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +/******************************************************************************/ +#else + +/* rotates the hard way */ +#define ROL(x, y) \ + ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | \ + (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & \ + 0xFFFFFFFFUL) +#define ROR(x, y) \ + ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | \ + ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) + +#endif /* 32-bit Rotates */ +/******************************************************************************/ + +#ifdef HAVE_NATIVE_INT64 +#ifdef _MSC_VER + #define CONST64(n) n ## ui64 +#else + #define CONST64(n) n ## ULL +#endif +#endif + +/******************************************************************************/ +/* + Endian helper macros + */ +#if defined (ENDIAN_NEUTRAL) +#define STORE32L(x, y) { \ +(y)[3] = (unsigned char)(((x)>>24)&255); \ +(y)[2] = (unsigned char)(((x)>>16)&255); \ +(y)[1] = (unsigned char)(((x)>>8)&255); \ +(y)[0] = (unsigned char)((x)&255); \ +} + +#define LOAD32L(x, y) { \ +x = ((unsigned long)((y)[3] & 255)<<24) | \ +((unsigned long)((y)[2] & 255)<<16) | \ +((unsigned long)((y)[1] & 255)<<8) | \ +((unsigned long)((y)[0] & 255)); \ +} + +#define STORE64L(x, y) { \ +(y)[7] = (unsigned char)(((x)>>56)&255); \ +(y)[6] = (unsigned char)(((x)>>48)&255); \ +(y)[5] = (unsigned char)(((x)>>40)&255); \ +(y)[4] = (unsigned char)(((x)>>32)&255); \ +(y)[3] = (unsigned char)(((x)>>24)&255); \ +(y)[2] = (unsigned char)(((x)>>16)&255); \ +(y)[1] = (unsigned char)(((x)>>8)&255); \ +(y)[0] = (unsigned char)((x)&255); \ +} + +#define LOAD64L(x, y) { \ +x = (((uint64)((y)[7] & 255))<<56)|(((uint64)((y)[6] & 255))<<48)| \ +(((uint64)((y)[5] & 255))<<40)|(((uint64)((y)[4] & 255))<<32)| \ +(((uint64)((y)[3] & 255))<<24)|(((uint64)((y)[2] & 255))<<16)| \ +(((uint64)((y)[1] & 255))<<8)|(((uint64)((y)[0] & 255))); \ +} + +#define STORE32H(x, y) { \ +(y)[0] = (unsigned char)(((x)>>24)&255); \ +(y)[1] = (unsigned char)(((x)>>16)&255); \ +(y)[2] = (unsigned char)(((x)>>8)&255); \ +(y)[3] = (unsigned char)((x)&255); \ +} + +#define LOAD32H(x, y) { \ +x = ((unsigned long)((y)[0] & 255)<<24) | \ +((unsigned long)((y)[1] & 255)<<16) | \ +((unsigned long)((y)[2] & 255)<<8) | \ +((unsigned long)((y)[3] & 255)); \ +} + +#define STORE64H(x, y) { \ +(y)[0] = (unsigned char)(((x)>>56)&255); \ +(y)[1] = (unsigned char)(((x)>>48)&255); \ +(y)[2] = (unsigned char)(((x)>>40)&255); \ +(y)[3] = (unsigned char)(((x)>>32)&255); \ +(y)[4] = (unsigned char)(((x)>>24)&255); \ +(y)[5] = (unsigned char)(((x)>>16)&255); \ +(y)[6] = (unsigned char)(((x)>>8)&255); \ +(y)[7] = (unsigned char)((x)&255); \ +} + +#define LOAD64H(x, y) { \ +x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48) | \ +(((uint64)((y)[2] & 255))<<40)|(((uint64)((y)[3] & 255))<<32) | \ +(((uint64)((y)[4] & 255))<<24)|(((uint64)((y)[5] & 255))<<16) | \ +(((uint64)((y)[6] & 255))<<8)|(((uint64)((y)[7] & 255))); \ +} + +#endif /* ENDIAN_NEUTRAL */ + +#ifdef ENDIAN_LITTLE +#define STORE32H(x, y) { \ +(y)[0] = (unsigned char)(((x)>>24)&255); \ +(y)[1] = (unsigned char)(((x)>>16)&255); \ +(y)[2] = (unsigned char)(((x)>>8)&255); \ +(y)[3] = (unsigned char)((x)&255); \ +} + +#define LOAD32H(x, y) { \ +x = ((unsigned long)((y)[0] & 255)<<24) | \ +((unsigned long)((y)[1] & 255)<<16) | \ +((unsigned long)((y)[2] & 255)<<8) | \ +((unsigned long)((y)[3] & 255)); \ +} + +#define STORE64H(x, y) { \ +(y)[0] = (unsigned char)(((x)>>56)&255); \ +(y)[1] = (unsigned char)(((x)>>48)&255); \ +(y)[2] = (unsigned char)(((x)>>40)&255); \ +(y)[3] = (unsigned char)(((x)>>32)&255); \ +(y)[4] = (unsigned char)(((x)>>24)&255); \ +(y)[5] = (unsigned char)(((x)>>16)&255); \ +(y)[6] = (unsigned char)(((x)>>8)&255); \ +(y)[7] = (unsigned char)((x)&255); \ +} + +#define LOAD64H(x, y) { \ +x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48) | \ +(((uint64)((y)[2] & 255))<<40)|(((uint64)((y)[3] & 255))<<32) | \ +(((uint64)((y)[4] & 255))<<24)|(((uint64)((y)[5] & 255))<<16) | \ +(((uint64)((y)[6] & 255))<<8)|(((uint64)((y)[7] & 255))); } + +#ifdef ENDIAN_32BITWORD +#define STORE32L(x, y) { \ +unsigned long __t = (x); memcpy(y, &__t, 4); \ +} + +#define LOAD32L(x, y) memcpy(&(x), y, 4); + +#define STORE64L(x, y) { \ +(y)[7] = (unsigned char)(((x)>>56)&255); \ +(y)[6] = (unsigned char)(((x)>>48)&255); \ +(y)[5] = (unsigned char)(((x)>>40)&255); \ +(y)[4] = (unsigned char)(((x)>>32)&255); \ +(y)[3] = (unsigned char)(((x)>>24)&255); \ +(y)[2] = (unsigned char)(((x)>>16)&255); \ +(y)[1] = (unsigned char)(((x)>>8)&255); \ +(y)[0] = (unsigned char)((x)&255); \ +} + +#define LOAD64L(x, y) { \ +x = (((uint64)((y)[7] & 255))<<56)|(((uint64)((y)[6] & 255))<<48)| \ +(((uint64)((y)[5] & 255))<<40)|(((uint64)((y)[4] & 255))<<32)| \ +(((uint64)((y)[3] & 255))<<24)|(((uint64)((y)[2] & 255))<<16)| \ +(((uint64)((y)[1] & 255))<<8)|(((uint64)((y)[0] & 255))); \ +} + +#else /* 64-bit words then */ +#define STORE32L(x, y) \ +{ unsigned int __t = (x); memcpy(y, &__t, 4); } + +#define LOAD32L(x, y) \ +{ memcpy(&(x), y, 4); x &= 0xFFFFFFFF; } + +#define STORE64L(x, y) \ +{ uint64 __t = (x); memcpy(y, &__t, 8); } + +#define LOAD64L(x, y) \ +{ memcpy(&(x), y, 8); } + +#endif /* ENDIAN_64BITWORD */ +#endif /* ENDIAN_LITTLE */ + +/******************************************************************************/ + +#ifdef ENDIAN_BIG +#define STORE32L(x, y) { \ +(y)[3] = (unsigned char)(((x)>>24)&255); \ +(y)[2] = (unsigned char)(((x)>>16)&255); \ +(y)[1] = (unsigned char)(((x)>>8)&255); \ +(y)[0] = (unsigned char)((x)&255); \ +} + +#define LOAD32L(x, y) { \ +x = ((unsigned long)((y)[3] & 255)<<24) | \ +((unsigned long)((y)[2] & 255)<<16) | \ +((unsigned long)((y)[1] & 255)<<8) | \ +((unsigned long)((y)[0] & 255)); \ +} + +#define STORE64L(x, y) { \ +(y)[7] = (unsigned char)(((x)>>56)&255); \ +(y)[6] = (unsigned char)(((x)>>48)&255); \ +(y)[5] = (unsigned char)(((x)>>40)&255); \ +(y)[4] = (unsigned char)(((x)>>32)&255); \ +(y)[3] = (unsigned char)(((x)>>24)&255); \ +(y)[2] = (unsigned char)(((x)>>16)&255); \ +(y)[1] = (unsigned char)(((x)>>8)&255); \ +(y)[0] = (unsigned char)((x)&255); \ +} + +#define LOAD64L(x, y) { \ +x = (((uint64)((y)[7] & 255))<<56)|(((uint64)((y)[6] & 255))<<48) | \ +(((uint64)((y)[5] & 255))<<40)|(((uint64)((y)[4] & 255))<<32) | \ +(((uint64)((y)[3] & 255))<<24)|(((uint64)((y)[2] & 255))<<16) | \ +(((uint64)((y)[1] & 255))<<8)|(((uint64)((y)[0] & 255))); \ +} + +/******************************************************************************/ + +#ifdef ENDIAN_32BITWORD +#define STORE32H(x, y) \ +{ unsigned int __t = (x); memcpy(y, &__t, 4); } + +#define LOAD32H(x, y) memcpy(&(x), y, 4); + +#define STORE64H(x, y) { \ +(y)[0] = (unsigned char)(((x)>>56)&255); \ +(y)[1] = (unsigned char)(((x)>>48)&255); \ +(y)[2] = (unsigned char)(((x)>>40)&255); \ +(y)[3] = (unsigned char)(((x)>>32)&255); \ +(y)[4] = (unsigned char)(((x)>>24)&255); \ +(y)[5] = (unsigned char)(((x)>>16)&255); \ +(y)[6] = (unsigned char)(((x)>>8)&255); \ +(y)[7] = (unsigned char)((x)&255); \ +} + +#define LOAD64H(x, y) { \ +x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48)| \ +(((uint64)((y)[2] & 255))<<40)|(((uint64)((y)[3] & 255))<<32)| \ +(((uint64)((y)[4] & 255))<<24)|(((uint64)((y)[5] & 255))<<16)| \ +(((uint64)((y)[6] & 255))<<8)| (((uint64)((y)[7] & 255))); \ +} + +/******************************************************************************/ + +#else /* 64-bit words then */ + +#define STORE32H(x, y) \ +{ unsigned int __t = (x); memcpy(y, &__t, 4); } + +#define LOAD32H(x, y) \ +{ memcpy(&(x), y, 4); x &= 0xFFFFFFFF; } + +#define STORE64H(x, y) \ +{ uint64 __t = (x); memcpy(y, &__t, 8); } + +#define LOAD64H(x, y) \ +{ memcpy(&(x), y, 8); } + +#endif /* ENDIAN_64BITWORD */ +#endif /* ENDIAN_BIG */ + +/******************************************************************************/ + +#ifdef HAVE_NATIVE_INT64 +#define ROL64c(x, y) \ +( (((x)<<((uint64)(y)&63)) | \ +(((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((uint64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#define ROR64c(x, y) \ +( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((uint64)(y)&CONST64(63))) | \ +((x)<<((uint64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF)) +#endif /* HAVE_NATIVE_INT64 */ + +/******************************************************************************/ +/* + Return the length of padding bytes required for a record of 'LEN' bytes + The name Pwr2 indicates that calculations will work with 'BLOCKSIZE' + that are powers of 2. + Because of the trailing pad length byte, a length that is a multiple + of the pad bytes +*/ +#define psPadLenPwr2(LEN, BLOCKSIZE) \ + BLOCKSIZE <= 1 ? (unsigned char)0 : \ + (unsigned char)(BLOCKSIZE - ((LEN) & (BLOCKSIZE - 1))) + + + +#endif /* _h_PS_CRYPTOLIB */ + +/******************************************************************************/ + diff --git a/crypto/digest/digest.h b/crypto/digest/digest.h new file mode 100644 index 0000000..0bd9de5 --- /dev/null +++ b/crypto/digest/digest.h @@ -0,0 +1,124 @@ +/** + * @file digest.h + * @version $Format:%h%d$ + * + * Header for internal symmetric key cryptography support. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ + +/******************************************************************************/ + +#ifndef _h_CRYPTO_DIGEST +#define _h_CRYPTO_DIGEST +/******************************************************************************/ + +#define SHA1_HASH_SIZE 20 +#define SHA224_HASH_SIZE 28 +#define SHA256_HASH_SIZE 32 +#define SHA384_HASH_SIZE 48 +#define SHA512_HASH_SIZE 64 +#define MD5_HASH_SIZE 16 + +#define SHA1_HASHLEN 20 +#define SHA256_HASHLEN 32 +#define SHA384_HASHLEN 48 +#define SHA512_HASHLEN 64 +#define MD5_HASHLEN 16 +#define MD5SHA1_HASHLEN (MD5_HASHLEN + SHA1_HASHLEN) + +#if defined(USE_SHA512) + #define MAX_HASH_SIZE SHA512_HASHLEN +#elif defined(USE_SHA384) + #define MAX_HASH_SIZE SHA384_HASHLEN +#elif defined(USE_SHA256) + #define MAX_HASH_SIZE SHA256_HASHLEN +#else + #define MAX_HASH_SIZE SHA1_HASHLEN +#endif + +#define MAX_HASHLEN MAX_HASH_SIZE + +#ifdef USE_LIBSODIUM_CRYPTO +#include "digest_libsodium.h" +#endif +#include "digest_matrix.h" +#ifdef USE_OPENSSL_CRYPTO +#include "digest_openssl.h" +#endif + +/******************************************************************************/ + +typedef union { +#ifdef USE_SHA1 + psSha1_t sha1; +#endif +#ifdef USE_MD5SHA1 + psMd5Sha1_t md5sha1; +#endif +#ifdef USE_SHA256 + psSha256_t sha256; +#endif +#ifdef USE_SHA384 + psSha384_t sha384; +#endif +#ifdef USE_SHA512 + psSha512_t sha512; +#endif +#ifdef USE_MD5 + psMd5_t md5; +#endif +#ifdef USE_MD2 + psMd2_t md2; +#endif +#ifdef USE_MD4 + psMd4_t md4; +#endif +} psDigestContext_t; + +typedef struct { + union { +#ifdef USE_HMAC_MD5 + psHmacMd5_t md5; +#endif +#ifdef USE_HMAC_SHA1 + psHmacSha1_t sha1; +#endif +#ifdef USE_HMAC_SHA256 + psHmacSha256_t sha256; +#endif +#ifdef USE_HMAC_SHA384 + psHmacSha384_t sha384; +#endif + } u; + uint8_t type; /* psCipherType_e */ +} psHmac_t; + +#endif /* _h_CRYPTO_DIGEST */ + +/******************************************************************************/ + diff --git a/crypto/digest/digest_libsodium.c b/crypto/digest/digest_libsodium.c new file mode 100755 index 0000000..a29b10b --- /dev/null +++ b/crypto/digest/digest_libsodium.c @@ -0,0 +1,194 @@ +/** + * @file digest_libsodium.c + * @version $Format:%h%d$ + * + * Digest compatibility layer between MatrixSSL and libsodium. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +/******************************************************************************/ + +#ifdef USE_LIBSODIUM_SHA256 +int32_t psSha256Init(psSha256_t *sha256) +{ + if (crypto_hash_sha256_init(sha256) != 0) { + return PS_FAIL; + } + return PS_SUCCESS; +} + +void psSha256Update(psSha256_t *sha256, const unsigned char *buf, uint32_t len) +{ + if (crypto_hash_sha256_update(sha256, buf, len) != 0) { + memset(sha256, 0x0, sizeof(psSha256_t)); + } +} + +void psSha256Final(psSha256_t *sha256, unsigned char hash[SHA256_HASHLEN]) +{ + + if (crypto_hash_sha256_final(sha256,hash) != 0) { + memset(hash, 0x0, SHA256_HASHLEN); + memset(sha256, 0x0, sizeof(psSha256_t)); + } +} +#endif /* USE_LIBSODIUM_SHA256 */ + +#ifdef USE_LIBSODIUM_SHA384 +/** + libsodium doesn't explicitly support sha384, but since 384 uses the + same compression as 512, we can use it here. + @note This uses an internal field of crypto_hash_sha512_state, which + may change with different versions of libsodium. +*/ +int32_t psSha384Init(psSha384_t *sha384) +{ + static const uint64_t sha384_initstate[8] = { + 0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL, + 0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL, + 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL, + 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL + }; + /* Sanity check libsodium hash structure for what we expect */ + if (sizeof(sha384->state) != 64) { + psAssert(sizeof(sha384->state) == 64); + return PS_FAIL; + } + if (crypto_hash_sha512_init(sha384) != 0) { + return PS_FAIL; + } + /* 384 uses a different initial state than 512 */ + memcpy(sha384->state, sha384_initstate, sizeof sha384_initstate); + return PS_SUCCESS; +} +void psSha384Update(psSha384_t *sha384, const unsigned char *buf, uint32_t len) +{ + if (crypto_hash_sha512_update(sha384, buf, len) != 0) { + memset(sha384, 0x0, sizeof(psSha384_t)); + } +} +void psSha384Final(psSha384_t *sha384, unsigned char hash[SHA384_HASHLEN]) +{ + unsigned char buf[SHA512_HASHLEN]; + if (crypto_hash_sha512_final(sha384, buf) != 0) { + memset(buf, 0x0, SHA512_HASHLEN); + memset(sha384, 0x0, sizeof(psSha384_t)); + } + memcpy(hash, buf, SHA384_HASHLEN); + memzero_s(buf, SHA512_HASHLEN); +} +#endif /* USE_LIBSODIUM_SHA384 */ + +#ifdef USE_LIBSODIUM_SHA512 +int32_t psSha512Init(psSha512_t *sha512) +{ + if (crypto_hash_sha512_init(sha512) != 0) { + return PS_FAIL; + } + return PS_SUCCESS; +} +void psSha512Update(psSha512_t *sha512, const unsigned char *buf, uint32_t len) +{ + if (crypto_hash_sha512_update(sha512, buf, len) != 0) { + memset(sha512, 0x0, sizeof(psSha512_t)); + } +} +void psSha512Final(psSha512_t *sha512, unsigned char hash[SHA512_HASHLEN]) +{ + if (crypto_hash_sha512_final(sha512,hash) != 0) { + memset(hash, 0x0, SHA512_HASHLEN); + memset(sha512, 0x0, sizeof(psSha512_t)); + } +} +#endif /* USE_LIBSODIUM_SHA512 */ + +/******************************************************************************/ + +#ifdef USE_LIBSODIUM_HMAC_SHA256 +int32_t psHmacSha256(const unsigned char *key, uint16_t keyLen, + const unsigned char *buf, uint32_t len, + unsigned char hash[SHA256_HASHLEN], unsigned char *hmacKey, + uint16_t *hmacKeyLen) +{ + psHmacSha256_t sha256; + + if (crypto_auth_hmacsha256_init(&sha256,key,keyLen) != 0) { + psAssert(0); + return PS_FAIL; + } + crypto_auth_hmacsha256_update(&sha256,buf,len); + crypto_auth_hmacsha256_final(&sha256,hash); + + if (keyLen > 64) { + crypto_hash_sha256(hmacKey, key, keyLen); + *hmacKeyLen = SHA256_HASHLEN; + } else { + hmacKey = (unsigned char*)key; + *hmacKeyLen = keyLen; + } + + return PS_SUCCESS; +} + +int32_t psHmacSha256Init(psHmacSha256_t *ctx, + const unsigned char *key, uint16_t keyLen) +{ + + if (crypto_auth_hmacsha256_init(ctx,key,keyLen) != 0) { + memset(ctx, 0x0, sizeof(psHmacSha256_t)); + psAssert(0); + return PS_FAIL; + } + return PS_SUCCESS; + +} + +void psHmacSha256Update(psHmacSha256_t *ctx, + const unsigned char *buf, uint32_t len) +{ + if (crypto_auth_hmacsha256_update(ctx,buf,len) != 0) { + memset(ctx, 0x0, sizeof(psHmacSha256_t)); + } + +} + +void psHmacSha256Final(psHmacSha256_t *ctx, + unsigned char hash[SHA256_HASHLEN]) +{ + + if (crypto_auth_hmacsha256_final(ctx, hash) != 0) { + psAssert(0); + } + memset(ctx, 0x0, sizeof(psHmacSha256_t)); +} +#endif /* USE_LIBSODIUM_HMAC_SHA256 */ + +/******************************************************************************/ diff --git a/crypto/digest/digest_libsodium.h b/crypto/digest/digest_libsodium.h new file mode 100755 index 0000000..6ed196c --- /dev/null +++ b/crypto/digest/digest_libsodium.h @@ -0,0 +1,65 @@ +/** + * @file digest_openssl.h + * @version $Format:%h%d$ + * + * Header for libsodium crypto Layer. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ + +/******************************************************************************/ + +#ifndef _h_LIBSODIUM_DIGEST +#define _h_LIBSODIUM_DIGEST + +/******************************************************************************/ + + +#ifdef USE_LIBSODIUM_SHA256 +#include "sodium/crypto_hash_sha256.h" +typedef crypto_hash_sha256_state psSha256_t; +#endif + +#ifdef USE_LIBSODIUM_SHA512 +#include "sodium/crypto_hash_sha512.h" +#ifdef USE_LIBSODIUM_SHA384 +typedef crypto_hash_sha512_state psSha384_t; +#endif +typedef crypto_hash_sha512_state psSha512_t; +#endif + +/******************************************************************************/ + +#ifdef USE_LIBSODIUM_HMAC_SHA256 +#include "sodium/crypto_auth_hmacsha256.h" +typedef crypto_auth_hmacsha256_state psHmacSha256_t; +#endif + +/******************************************************************************/ + +#endif /* _h_LIBSODIUM_DIGEST */ + diff --git a/crypto/digest/digest_matrix.h b/crypto/digest/digest_matrix.h new file mode 100644 index 0000000..69839ed --- /dev/null +++ b/crypto/digest/digest_matrix.h @@ -0,0 +1,156 @@ +/** + * @file digest_matrix.h + * @version $Format:%h%d$ + * + * Header for internal digest support. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ + +/******************************************************************************/ + +#ifndef _h_MATRIX_DIGEST +#define _h_MATRIX_DIGEST + +/******************************************************************************/ + +#ifdef USE_MATRIX_SHA1 +typedef struct { +#ifdef HAVE_NATIVE_INT64 + uint64 length; +#else + uint32 lengthHi; + uint32 lengthLo; +#endif /* HAVE_NATIVE_INT64 */ + uint32 state[5], curlen; + unsigned char buf[64]; +} psSha1_t; +#endif + +#ifdef USE_MATRIX_SHA256 +typedef struct { +#ifdef HAVE_NATIVE_INT64 + uint64 length; +#else + uint32 lengthHi; + uint32 lengthLo; +#endif /* HAVE_NATIVE_INT64 */ + uint32 state[8], curlen; + unsigned char buf[64]; +} psSha256_t; +#endif + +#ifdef USE_MATRIX_SHA512 +typedef struct { + uint64 length, state[8]; + unsigned long curlen; + unsigned char buf[128]; +} psSha512_t; +#endif + +#ifdef USE_MATRIX_SHA384 +#ifndef USE_MATRIX_SHA512 +#error "USE_MATRIX_SHA512 must be enabled if USE_MATRIX_SHA384 is enabled" +#endif +typedef psSha512_t psSha384_t; +#endif + +#ifdef USE_MATRIX_MD5 +typedef struct { +#ifdef HAVE_NATIVE_INT64 + uint64 length; +#else + uint32 lengthHi; + uint32 lengthLo; +#endif /* HAVE_NATIVE_INT64 */ + uint32 state[4], curlen; + unsigned char buf[64]; +} psMd5_t; +#endif + +#ifdef USE_MATRIX_MD5SHA1 +typedef struct { + psMd5_t md5; + psSha1_t sha1; +} psMd5Sha1_t; +#endif + +#ifdef USE_MATRIX_MD4 +typedef struct { +#ifdef HAVE_NATIVE_INT64 + uint64 length; +#else + uint32 lengthHi; + uint32 lengthLo; +#endif /* HAVE_NATIVE_INT64 */ + uint32 state[4], curlen; + unsigned char buf[64]; +} psMd4_t; +#endif + +#ifdef USE_MATRIX_MD2 +typedef struct { + unsigned char chksum[16], X[48], buf[16]; + uint32 curlen; +} psMd2_t; +#endif + + +/******************************************************************************/ + +#ifdef USE_MATRIX_HMAC_MD5 +typedef struct { + unsigned char pad[64]; + psMd5_t md5; +} psHmacMd5_t; +#endif + +#ifdef USE_MATRIX_HMAC_SHA1 +typedef struct { + unsigned char pad[64]; + psSha1_t sha1; +} psHmacSha1_t; +#endif + +#ifdef USE_MATRIX_HMAC_SHA256 +typedef struct { + unsigned char pad[64]; + psSha256_t sha256; +} psHmacSha256_t; +#endif + +#ifdef USE_MATRIX_HMAC_SHA384 +typedef struct { + unsigned char pad[128]; + psSha384_t sha384; +} psHmacSha384_t; +#endif + +#endif /* _h_MATRIX_DIGEST */ + +/******************************************************************************/ + diff --git a/crypto/digest/digest_openssl.c b/crypto/digest/digest_openssl.c new file mode 100644 index 0000000..6459217 --- /dev/null +++ b/crypto/digest/digest_openssl.c @@ -0,0 +1,407 @@ +/** + * @file digest_openssl.c + * @version $Format:%h%d$ + * + * Digest compatibility layer between MatrixSSL and OpenSSL. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +/******************************************************************************/ + +#ifdef USE_OPENSSL_HMAC_MD5 + +int32_t psHmacMd5(const unsigned char *key, uint16_t keyLen, + const unsigned char *buf, uint32_t len, + unsigned char hash[MD5_HASHLEN], unsigned char *hmacKey, + uint16_t *hmacKeyLen) +{ + psMd5_t md; + /* + Support for keys larger than 64 bytes. In this case, we take the + hash of the key itself and use that instead. Inform the caller by + updating the hmacKey and hmacKeyLen outputs + */ + if (keyLen > 64) { + psMd5Init(&md); + psMd5Update(&md, key, keyLen); + psMd5Final(&md, hash); + *hmacKeyLen = MD5_HASHLEN; + memcpy(hmacKey, hash, *hmacKeyLen); + } else { + hmacKey = (unsigned char*)key; + *hmacKeyLen = keyLen; + } + if (HMAC(EVP_md5(), hmacKey, *hmacKeyLen, buf, len, hash, NULL) != NULL) { + return PS_SUCCESS; + } + return PS_FAIL; +} + +int32_t psHmacMd5Init(psHmacMd5_t *ctx, const unsigned char *key, + uint16_t keyLen) +{ + HMAC_CTX_init(ctx); + if (HMAC_Init_ex(ctx, key, keyLen, EVP_md5(), NULL) == 1) { + return PS_SUCCESS; + } + HMAC_CTX_cleanup(ctx); + psAssert(0); + return PS_FAIL; +} + +void psHmacMd5Update(psHmacMd5_t *ctx, const unsigned char *buf, + uint32_t len) +{ + HMAC_Update(ctx, buf, len); +} + +void psHmacMd5Final(psHmacMd5_t *ctx, unsigned char hash[MD5_HASHLEN]) +{ + HMAC_Final(ctx, hash, NULL); + HMAC_CTX_cleanup(ctx); +} + +#endif /* USE_OPENSSL_HMAC_MD5 */ + +/******************************************************************************/ + +#ifdef USE_OPENSSL_SHA1 + +int32_t psHmacSha1(const unsigned char *key, uint16_t keyLen, + const unsigned char *buf, uint32_t len, + unsigned char hash[SHA1_HASHLEN], unsigned char *hmacKey, + uint16_t *hmacKeyLen) +{ + psSha1_t sha; +/* + Support for keys larger than 64 bytes. In this case, we take the + hash of the key itself and use that instead. Inform the caller by + updating the hmacKey and hmacKeyLen outputs +*/ + if (keyLen > 64) { + psSha1Init(&sha); + psSha1Update(&sha, key, keyLen); + psSha1Final(&sha, hash); + *hmacKeyLen = SHA1_HASHLEN; + memcpy(hmacKey, hash, *hmacKeyLen); + } else { + hmacKey = (unsigned char*)key; + *hmacKeyLen = keyLen; + } + if (HMAC(EVP_sha1(), hmacKey, *hmacKeyLen, buf, len, hash, NULL) != NULL) { + return PS_SUCCESS; + } + return PS_FAIL; +} + +int32_t psHmacSha1Init(psHmacSha1_t *ctx, const unsigned char *key, + uint16_t keyLen) +{ + HMAC_CTX_init(ctx); + if (HMAC_Init_ex(ctx, key, keyLen, EVP_sha1(), NULL) == 1) { + return PS_SUCCESS; + } + HMAC_CTX_cleanup(ctx); + return PS_FAIL; +} + +void psHmacSha1Update(psHmacSha1_t *ctx, const unsigned char *buf, + uint32_t len) +{ + HMAC_Update(ctx, buf, len); +} + +void psHmacSha1Final(psHmacSha1_t *ctx, unsigned char hash[SHA1_HASHLEN]) +{ + HMAC_Final(ctx, hash, NULL); + HMAC_CTX_cleanup(ctx); +} +#endif /* USE_OPENSSL_HMAC_SHA1 */ + +/******************************************************************************/ + +#ifdef USE_OPENSSL_HMAC_SHA256 +int32_t psHmacSha256(const unsigned char *key, uint16_t keyLen, + const unsigned char *buf, uint32_t len, + unsigned char hash[SHA256_HASHLEN], unsigned char *hmacKey, + uint16_t *hmacKeyLen) +{ + psSha256_t sha; + + if (keyLen > 64) { + psSha256Init(&sha); + psSha256Update(&sha, key, keyLen); + psSha256Final(&sha, hash); + *hmacKeyLen = SHA256_HASHLEN; + memcpy(hmacKey, hash, *hmacKeyLen); + } else { + hmacKey = (unsigned char*)key; + *hmacKeyLen = keyLen; + } + if (HMAC(EVP_sha256(), hmacKey, *hmacKeyLen, buf, len, hash, NULL) != NULL){ + return PS_SUCCESS; + } + psAssert(0); + return PS_FAIL; +} + +int32_t psHmacSha256Init(psHmacSha256_t *ctx, + const unsigned char *key, uint16_t keyLen) +{ + HMAC_CTX_init(ctx); + if (HMAC_Init_ex(ctx, key, keyLen, EVP_sha256(), NULL) == 1) { + return PS_SUCCESS; + } + HMAC_CTX_cleanup(ctx); + psAssert(0); + return PS_FAIL; +} + +void psHmacSha256Update(psHmacSha256_t *ctx, + const unsigned char *buf, uint32_t len) +{ + if (HMAC_Update(ctx, buf, len) != 1) { + HMAC_CTX_cleanup(ctx); + } +} + +void psHmacSha256Final(psHmacSha256_t *ctx, + unsigned char hash[SHA256_HASHLEN]) +{ + if (HMAC_Final(ctx, hash, NULL) != 1) { + psAssert(0); + } + HMAC_CTX_cleanup(ctx); +} +#endif /* USE_OPENSSL_HMAC_SHA256 */ + +#ifdef USE_OPENSSL_HMAC_SHA384 +int32_t psHmacSha384(const unsigned char *key, uint16_t keyLen, + const unsigned char *buf, uint32_t len, + unsigned char hash[SHA384_HASHLEN], unsigned char *hmacKey, + uint16_t *hmacKeyLen) +{ + psSha384_t sha; + + if (keyLen > 64) { + psSha384Init(&sha); + psSha384Update(&sha, key, keyLen); + psSha384Final(&sha, hash); + *hmacKeyLen = SHA384_HASHLEN; + memcpy(hmacKey, hash, *hmacKeyLen); + } else { + hmacKey = (unsigned char*)key; + *hmacKeyLen = keyLen; + } + + if (HMAC(EVP_sha384(), hmacKey, *hmacKeyLen, buf, len, hash, NULL) != NULL){ + return PS_SUCCESS; + } + psAssert(0); + return PS_FAIL; +} + +int32_t psHmacSha384Init(psHmacSha384_t *ctx, + const unsigned char *key, uint16_t keyLen) +{ + HMAC_CTX_init(ctx); + if (HMAC_Init_ex(ctx, key, keyLen, EVP_sha384(), NULL) == 1) { + return PS_SUCCESS; + } + HMAC_CTX_cleanup(ctx); + psAssert(0); + return PS_FAIL; +} + +void psHmacSha384Update(psHmacSha384_t *ctx, + const unsigned char *buf, uint32_t len) +{ + if (HMAC_Update(ctx, buf, len) != 1) { + HMAC_CTX_cleanup(ctx); + } +} + +void psHmacSha384Final(psHmacSha384_t *ctx, + unsigned char hash[SHA384_HASHLEN]) +{ + if (HMAC_Final(ctx, hash, NULL) != 1) { + psAssert(0); + } + HMAC_CTX_cleanup(ctx); +} +#endif /* USE_OPENSSL_HMAC_SHA384 */ + + +#ifdef USE_OPENSSL_MD5 +int32_t psMd5Init(psMd5_t *md5) +{ + if (MD5_Init(md5) != 1) { + return PS_FAIL; + } + return PS_SUCCESS; +} +void psMd5Update(psMd5_t *md5, const unsigned char *buf, uint32_t len) +{ + if (MD5_Update(md5, buf, len) != 1) { + memset(md5, 0x0, sizeof(psMd5_t)); + } +} +void psMd5Final(psMd5_t *md5, unsigned char hash[MD5_HASHLEN]) +{ + if (MD5_Final(hash, md5) != 1) { + memset(hash, 0x0, MD5_HASHLEN); + memset(md5, 0x0, sizeof(psMd5_t)); + } +} +#endif + +#ifdef USE_OPENSSL_MD5SHA1 +int32_t psMd5Sha1Init(psMd5Sha1_t *md) +{ + if (MD5_Init(&md->md5) != 1 || SHA1_Init(&md->sha1) != 1) { + memset(md, 0x0, sizeof(psMd5Sha1_t)); + return PS_FAIL; + } + return PS_SUCCESS; +} + +void psMd5Sha1Update(psMd5Sha1_t *md, + const unsigned char *buf, uint32_t len) +{ + if (MD5_Update(&md->md5, buf, len) != 1 || SHA1_Update(&md->sha1, buf, len) != 1 ) { + memset(md, 0x0, sizeof(psMd5Sha1_t)); + } +} + +void psMd5Sha1Final(psMd5Sha1_t *md, + unsigned char hash[MD5SHA1_HASHLEN]) +{ + if (MD5_Final(hash, &md->md5) != 1 || + SHA1_Final(hash + MD5_HASHLEN, &md->sha1) != 1 ) { + memset(hash, 0x0, MD5SHA1_HASHLEN); + memset(md, 0x0, sizeof(psMd5Sha1_t)); + } +} +#endif + +#ifdef USE_OPENSSL_SHA1 +int32_t psSha1Init(psSha1_t *sha1) +{ + if (SHA1_Init(sha1) != 1) { + return PS_FAIL; + } + return PS_SUCCESS; +} +void psSha1Update(psSha1_t *sha1, const unsigned char *buf, uint32_t len) +{ + if (SHA1_Update(sha1, buf, len) != 1) { + memset(sha1, 0x0, sizeof(psSha1_t)); + } +} +void psSha1Final(psSha1_t *sha1, unsigned char hash[SHA1_HASHLEN]) +{ + if (SHA1_Final(hash, sha1) != 1) { + memset(hash, 0x0, SHA1_HASHLEN); + memset(sha1, 0x0, sizeof(psSha1_t)); + } +} +#endif + +#ifdef USE_OPENSSL_SHA256 +int32_t psSha256Init(psSha256_t *sha256) +{ + if (SHA256_Init(sha256) != 1) { + return PS_FAIL; + } + return PS_SUCCESS; +} +void psSha256Update(psSha256_t *sha256, const unsigned char *buf, uint32_t len) +{ + if (SHA256_Update(sha256, buf, len) != 1) { + memset(sha256, 0x0, sizeof(psSha256_t)); + } +} +void psSha256Final(psSha256_t *sha256, unsigned char hash[SHA256_HASHLEN]) +{ + if (SHA256_Final(hash, sha256) != 1) { + memset(hash, 0x0, SHA256_HASHLEN); + memset(sha256, 0x0, sizeof(psSha256_t)); + } +} +#endif + +#ifdef USE_OPENSSL_SHA384 +int32_t psSha384Init(psSha384_t *sha384) +{ + if (SHA384_Init(sha384) != 1) { + return PS_FAIL; + } + return PS_SUCCESS; +} +void psSha384Update(psSha384_t *sha384, const unsigned char *buf, uint32_t len) +{ + if (SHA384_Update(sha384, buf, len) != 1) { + memset(sha384, 0x0, sizeof(psSha384_t)); + } +} +void psSha384Final(psSha384_t *sha384, unsigned char hash[SHA384_HASHLEN]) +{ + if (SHA384_Final(hash, sha384) != 1) { + memset(hash, 0x0, SHA384_HASHLEN); + memset(sha384, 0x0, sizeof(psSha384_t)); + } +} +#endif + +#ifdef USE_OPENSSL_SHA512 +int32_t psSha512Init(psSha512_t *sha512) +{ + if (SHA512_Init(sha512) != 1) { + return PS_FAIL; + } + return PS_SUCCESS; +} +void psSha512Update(psSha512_t *sha512, const unsigned char *buf, uint32_t len) +{ + if (SHA512_Update(sha512, buf, len) != 1) { + memset(sha512, 0x0, sizeof(psSha512_t)); + } +} +void psSha512Final(psSha512_t *sha512, unsigned char hash[SHA512_HASHLEN]) +{ + if (SHA512_Final(hash, sha512) != 1) { + memset(hash, 0x0, SHA512_HASHLEN); + memset(sha512, 0x0, sizeof(psSha512_t)); + } +} +#endif + +/******************************************************************************/ diff --git a/crypto/digest/digest_openssl.h b/crypto/digest/digest_openssl.h new file mode 100644 index 0000000..bdd706d --- /dev/null +++ b/crypto/digest/digest_openssl.h @@ -0,0 +1,95 @@ +/** + * @file digest_openssl.h + * @version $Format:%h%d$ + * + * Header for OpenSSL Crypto Layer. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ + +/******************************************************************************/ + +#ifndef _h_OPENSSL_DIGEST +#define _h_OPENSSL_DIGEST + +/******************************************************************************/ + +#if defined(USE_OPENSSL_MD5) || defined(USE_OPENSSL_MD5SHA1) +#include +#endif + +#if defined(USE_OPENSSL_SHA1) || defined(USE_OPENSSL_SHA256) || \ + defined(USE_OPENSSL_SHA384) || defined(USE_OPENSSL_SHA512) +#include +#endif + +#ifdef USE_OPENSSL_MD5 +typedef MD5_CTX psMd5_t; +#endif + +#ifdef USE_OPENSSL_MD5SHA1 +typedef struct { + MD5_CTX md5; + SHA_CTX sha1; +} psMd5Sha1_t; +#endif + +#ifdef USE_OPENSSL_SHA1 +typedef SHA_CTX psSha1_t; +#endif + +#ifdef USE_OPENSSL_SHA256 +typedef SHA256_CTX psSha256_t; +#endif + +#ifdef USE_OPENSSL_SHA384 +typedef SHA512_CTX psSha384_t; +#endif + +#ifdef USE_OPENSSL_SHA512 +typedef SHA512_CTX psSha512_t; +#endif + +/******************************************************************************/ + +#if defined(USE_OPENSSL_HMAC_SHA1) || defined(USE_OPENSSL_HMAC_SHA256) || \ + defined(USE_OPENSSL_HMAC_SHA384) || defined(USE_OPENSSL_HMAC_SHA512) + +#include +#include + +typedef HMAC_CTX psHmacMd5_t; +typedef HMAC_CTX psHmacSha1_t; +typedef HMAC_CTX psHmacSha256_t; +typedef HMAC_CTX psHmacSha384_t; + +#endif + +/******************************************************************************/ + +#endif /* _h_OPENSSL_DIGEST */ + diff --git a/crypto/digest/hmac.c b/crypto/digest/hmac.c new file mode 100644 index 0000000..b015587 --- /dev/null +++ b/crypto/digest/hmac.c @@ -0,0 +1,570 @@ +/** + * @file hmac.c + * @version $Format:%h%d$ + * + * HMAC implementation. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +int32_t psHmacInit(psHmac_t *ctx, psCipherType_e type, + const unsigned char *key, uint16_t keyLen) +{ + ctx->type = (uint8_t)type; + switch(type) { +#ifdef USE_HMAC_MD5 + case HMAC_MD5: + return psHmacMd5Init(&ctx->u.md5, key, keyLen); +#endif +#ifdef USE_HMAC_SHA1 + case HMAC_SHA1: + return psHmacSha1Init(&ctx->u.sha1, key, keyLen); +#endif +#ifdef USE_HMAC_SHA256 + case HMAC_SHA256: + return psHmacSha256Init(&ctx->u.sha256, key, keyLen); +#endif +#ifdef USE_HMAC_SHA384 + case HMAC_SHA384: + return psHmacSha384Init(&ctx->u.sha384, key, keyLen); +#endif + default: + return PS_ARG_FAIL; + } + /* Redundant return */ + return PS_ARG_FAIL; +} + +void psHmacUpdate(psHmac_t *ctx, const unsigned char *buf, uint32_t len) +{ + switch((psCipherType_e)ctx->type) { +#ifdef USE_HMAC_MD5 + case HMAC_MD5: + psHmacMd5Update(&ctx->u.md5, buf, len); + break; +#endif +#ifdef USE_HMAC_SHA1 + case HMAC_SHA1: + psHmacSha1Update(&ctx->u.sha1, buf, len); + break; +#endif +#ifdef USE_HMAC_SHA256 + case HMAC_SHA256: + psHmacSha256Update(&ctx->u.sha256, buf, len); + break; +#endif +#ifdef USE_HMAC_SHA384 + case HMAC_SHA384: + psHmacSha384Update(&ctx->u.sha384, buf, len); + break; +#endif + default: + break; + } +} + +void psHmacFinal(psHmac_t *ctx, unsigned char hash[MAX_HASHLEN]) +{ + switch((psCipherType_e)ctx->type) { +#ifdef USE_HMAC_MD5 + case HMAC_MD5: + psHmacMd5Final(&ctx->u.md5, hash); + break; +#endif +#ifdef USE_HMAC_SHA1 + case HMAC_SHA1: + psHmacSha1Final(&ctx->u.sha1, hash); + break; +#endif +#ifdef USE_HMAC_SHA256 + case HMAC_SHA256: + psHmacSha256Final(&ctx->u.sha256, hash); + break; +#endif +#ifdef USE_HMAC_SHA384 + case HMAC_SHA384: + psHmacSha384Final(&ctx->u.sha384, hash); + break; +#endif + default: + break; + } + ctx->type = 0; +} + +#ifdef USE_MATRIX_HMAC_MD5 +/******************************************************************************/ +/* + HMAC-MD5 + http://www.faqs.org/rfcs/rfc2104.html + + the HMAC_MD5 transform looks like: + + MD5(K XOR opad, MD5(K XOR ipad, text)) + + where K is an n byte key + ipad is the byte 0x36 repeated 64 times + + opad is the byte 0x5c repeated 64 times + and text is the data being protected + + If the keyLen is > 64 bytes, we hash the key and use it instead +*/ +#ifndef USE_MATRIX_MD5 +#error USE_MATRIX_MD5 required +#endif +int32_t psHmacMd5(const unsigned char *key, uint16_t keyLen, + const unsigned char *buf, uint32_t len, + unsigned char hash[MD5_HASHLEN], + unsigned char *hmacKey, uint16_t *hmacKeyLen) +{ + int32_t rc; + union { + psHmacMd5_t mac; + psMd5_t md; + } u; + psHmacMd5_t *mac = &u.mac; + psMd5_t *md = &u.md; +/* + Support for keys larger than 64 bytes. In this case, we take the + hash of the key itself and use that instead. Inform the caller by + updating the hmacKey and hmacKeyLen outputs +*/ + if (keyLen > 64) { + if ((rc = psMd5Init(md)) < 0) { + return rc; + } + psMd5Update(md, key, keyLen); + psMd5Final(md, hash); + *hmacKeyLen = MD5_HASHLEN; + memcpy(hmacKey, hash, *hmacKeyLen); + } else { + hmacKey = (unsigned char *)key; /* @note typecasting from const */ + *hmacKeyLen = keyLen; + } + if ((rc = psHmacMd5Init(mac, hmacKey, *hmacKeyLen)) < 0) { + return rc; + } + psHmacMd5Update(mac, buf, len); + psHmacMd5Final(mac, hash); + return PS_SUCCESS; +} + +int32_t psHmacMd5Init(psHmacMd5_t *ctx, + const unsigned char *key, uint16_t keyLen) +{ + int32_t rc, i; + +#ifdef CRYPTO_ASSERT + psAssert(keyLen <= 64); +#endif + for (i = 0; (uint32)i < keyLen; i++) { + ctx->pad[i] = key[i] ^ 0x36; + } + for (i = keyLen; i < 64; i++) { + ctx->pad[i] = 0x36; + } + if ((rc = psMd5Init(&ctx->md5)) < 0) { + return rc; + } + psMd5Update(&ctx->md5, ctx->pad, 64); + for (i = 0; (uint32)i < keyLen; i++) { + ctx->pad[i] = key[i] ^ 0x5c; + } + for (i = keyLen; i < 64; i++) { + ctx->pad[i] = 0x5c; + } + return PS_SUCCESS; +} + +void psHmacMd5Update(psHmacMd5_t *ctx, + const unsigned char *buf, uint32_t len) +{ +#ifdef CRYPTO_ASSERT + psAssert(ctx != NULL && buf != NULL); +#endif + psMd5Update(&ctx->md5, buf, len); +} + +void psHmacMd5Final(psHmacMd5_t *ctx, unsigned char hash[MD5_HASHLEN]) +{ + int32_t rc; +#ifdef CRYPTO_ASSERT + psAssert(ctx != NULL); + if (hash == NULL) { + psTraceCrypto("NULL hash storage passed to psHmacMd5Final\n"); + return; + } +#endif + psMd5Final(&ctx->md5, hash); + + /* This Init should succeed, even if it allocates memory since an + psMd5_t was just Finalized the line above */ + if ((rc = psMd5Init(&ctx->md5)) < 0) { + psAssert(rc >= 0); + return; + } + psMd5Update(&ctx->md5, ctx->pad, 64); + psMd5Update(&ctx->md5, hash, MD5_HASHLEN); + psMd5Final(&ctx->md5, hash); + + memset(ctx->pad, 0x0, sizeof(ctx->pad)); +} + +#endif /* USE_MATRIX_HMAC_MD5 */ + +#ifdef USE_MATRIX_HMAC_SHA1 +/******************************************************************************/ +/* + HMAC-SHA1 + @see http://www.faqs.org/rfcs/rfc2104.html +*/ +#ifndef USE_SHA1 +#error USE_SHA1 required +#endif + +int32_t psHmacSha1(const unsigned char *key, uint16_t keyLen, + const unsigned char *buf, uint32_t len, + unsigned char hash[SHA1_HASHLEN], + unsigned char *hmacKey, uint16_t *hmacKeyLen) +{ + int32_t rc; + union { + psHmacSha1_t mac; + psSha1_t md; + } u; + psHmacSha1_t *mac = &u.mac; + psSha1_t *md = &u.md; +/* + Support for keys larger than 64 bytes. In this case, we take the + hash of the key itself and use that instead. Inform the caller by + updating the hmacKey and hmacKeyLen outputs +*/ + if (keyLen > 64) { + if ((rc = psSha1Init(md)) < 0) { + return rc; + } + psSha1Update(md, key, keyLen); + psSha1Final(md, hash); + *hmacKeyLen = SHA1_HASHLEN; + memcpy(hmacKey, hash, *hmacKeyLen); + } else { + hmacKey = (unsigned char *)key; /* @note typecasting from const */ + *hmacKeyLen = keyLen; + } + + if ((rc = psHmacSha1Init(mac, hmacKey, *hmacKeyLen)) < 0) { + return rc; + } + psHmacSha1Update(mac, buf, len); + psHmacSha1Final(mac, hash); + return PS_SUCCESS; +} + +int32_t psHmacSha1Init(psHmacSha1_t *ctx, + const unsigned char *key, uint16_t keyLen) +{ + int32_t rc, i; +#ifdef CRYPTO_ASSERT + psAssert(keyLen <= 64); +#endif + for (i = 0; (uint32)i < keyLen; i++) { + ctx->pad[i] = key[i] ^ 0x36; + } + for (i = keyLen; (uint32)i < 64; i++) { + ctx->pad[i] = 0x36; + } + if ((rc = psSha1Init(&ctx->sha1)) < 0) { + return rc; + } + psSha1Update(&ctx->sha1, ctx->pad, 64); + for (i = 0; (uint32)i < keyLen; i++) { + ctx->pad[i] = key[i] ^ 0x5c; + } + for (i = keyLen; i < 64; i++) { + ctx->pad[i] = 0x5c; + } + return PS_SUCCESS; +} + +void psHmacSha1Update(psHmacSha1_t *ctx, + const unsigned char *buf, uint32_t len) +{ +#ifdef CRYPTO_ASSERT + psAssert(ctx != NULL && buf != NULL); +#endif + psSha1Update(&ctx->sha1, buf, len); +} + +void psHmacSha1Final(psHmacSha1_t *ctx, unsigned char hash[SHA1_HASHLEN]) +{ + int32_t rc; +#ifdef CRYPTO_ASSERT + psAssert(ctx != NULL); + if (hash == NULL) { + psTraceCrypto("NULL hash storage passed to psHmacSha1Final\n"); + return; + } +#endif + psSha1Final(&ctx->sha1, hash); + + if ((rc = psSha1Init(&ctx->sha1)) < 0) { + psAssert(rc >= 0); + return; + } + psSha1Update(&ctx->sha1, ctx->pad, 64); + psSha1Update(&ctx->sha1, hash, SHA1_HASHLEN); + psSha1Final(&ctx->sha1, hash); + + memset(ctx->pad, 0x0, sizeof(ctx->pad)); +} + +#endif /* USE_MATRIX_HMAC_SHA1 */ + +#ifdef USE_MATRIX_HMAC_SHA256 +/******************************************************************************/ +/* + HMAC-SHA256 +*/ +int32_t psHmacSha256(const unsigned char *key, uint16_t keyLen, + const unsigned char *buf, uint32_t len, + unsigned char hash[SHA256_HASHLEN], unsigned char *hmacKey, + uint16_t *hmacKeyLen) +{ + int32 rc, padLen; + union { + psHmacSha256_t mac; + psSha256_t md; + } u; + psHmacSha256_t *mac = &u.mac; + psSha256_t *md = &u.md; + + padLen = 64; + +/* + Support for keys larger than hash block size. In this case, we take the + hash of the key itself and use that instead. Inform the caller by + updating the hmacKey and hmacKeyLen outputs +*/ + if (keyLen > (uint32)padLen) { + if ((rc = psSha256Init(md)) < 0) { + return rc; + } + psSha256Update(md, key, keyLen); + psSha256Final(md, hash); + memcpy(hmacKey, hash, SHA256_HASHLEN); + *hmacKeyLen = SHA256_HASHLEN; + } else { + hmacKey = (unsigned char *)key; /* @note typecasting from const */ + *hmacKeyLen = keyLen; + } + + if ((rc = psHmacSha256Init(mac, hmacKey, *hmacKeyLen)) < 0) { + return rc; + } + psHmacSha256Update(mac, buf, len); + psHmacSha256Final(mac, hash); + return PS_SUCCESS; +} + +int32_t psHmacSha256Init(psHmacSha256_t *ctx, + const unsigned char *key, uint16_t keyLen) +{ + int32_t rc, i, padLen = 64; + +#ifdef CRYPTO_ASSERT + psAssert(keyLen <= (uint32)padLen); +#endif + for (i = 0; (uint32)i < keyLen; i++) { + ctx->pad[i] = key[i] ^ 0x36; + } + for (i = keyLen; i < padLen; i++) { + ctx->pad[i] = 0x36; + } + if ((rc = psSha256Init(&ctx->sha256)) < 0) { + return rc; + } + psSha256Update(&ctx->sha256, ctx->pad, padLen); + for (i = 0; (uint32)i < keyLen; i++) { + ctx->pad[i] = key[i] ^ 0x5c; + } + for (i = keyLen; i < padLen; i++) { + ctx->pad[i] = 0x5c; + } + return PS_SUCCESS; +} + +void psHmacSha256Update(psHmacSha256_t *ctx, + const unsigned char *buf, uint32_t len) +{ +#ifdef CRYPTO_ASSERT + psAssert(ctx != NULL && buf != NULL); +#endif + psSha256Update(&ctx->sha256, buf, len); +} + +void psHmacSha256Final(psHmacSha256_t *ctx, + unsigned char hash[SHA256_HASHLEN]) +{ + int32_t rc; +#ifdef CRYPTO_ASSERT + psAssert(ctx != NULL); + if (hash == NULL) { + psTraceCrypto("NULL hash storage passed to psHmacSha256Final\n"); + return; + } +#endif + + psSha256Final(&ctx->sha256, hash); + + if ((rc = psSha256Init(&ctx->sha256)) < 0) { + psAssert(rc >= 0); + return; + } + psSha256Update(&ctx->sha256, ctx->pad, 64); + psSha256Update(&ctx->sha256, hash, SHA256_HASHLEN); + psSha256Final(&ctx->sha256, hash); + memset(ctx->pad, 0x0, sizeof(ctx->pad)); +} +#endif /* USE_MATRIX_HMAC_SHA256 */ + +#ifdef USE_MATRIX_HMAC_SHA384 +/******************************************************************************/ +/* + HMAC-SHA384 +*/ +int32_t psHmacSha384(const unsigned char *key, uint16_t keyLen, + const unsigned char *buf, uint32_t len, + unsigned char hash[SHA384_HASHLEN], + unsigned char *hmacKey, uint16_t *hmacKeyLen) +{ + int32 rc, padLen; + union { + psHmacSha384_t mac; + psSha384_t md; + } u; + psHmacSha384_t *mac = &u.mac; + psSha384_t *md = &u.md; + + padLen = 128; + +/* + Support for keys larger than hash block size. In this case, we take the + hash of the key itself and use that instead. Inform the caller by + updating the hmacKey and hmacKeyLen outputs +*/ + if (keyLen > (uint32)padLen) { + if ((rc = psSha384Init(md)) < 0) { + return rc; + } + psSha384Update(md, key, keyLen); + psSha384Final(md, hash); + memcpy(hmacKey, hash, SHA384_HASHLEN); + *hmacKeyLen = SHA384_HASHLEN; + } else { + hmacKey = (unsigned char *)key; /* @note typecasting from const */ + *hmacKeyLen = keyLen; + } + + if ((rc = psHmacSha384Init(mac, hmacKey, *hmacKeyLen)) < 0) { + return rc; + } + psHmacSha384Update(mac, buf, len); + psHmacSha384Final(mac, hash); + return PS_SUCCESS; +} + +int32_t psHmacSha384Init(psHmacSha384_t *ctx, + const unsigned char *key, uint16_t keyLen) +{ + int32_t rc, i, padLen; + + padLen = 128; + +#ifdef CRYPTO_ASSERT + psAssert(keyLen <= (uint32)padLen); +#endif + for (i = 0; (uint32)i < keyLen; i++) { + ctx->pad[i] = key[i] ^ 0x36; + } + for (i = keyLen; i < padLen; i++) { + ctx->pad[i] = 0x36; + } + if ((rc = psSha384Init(&ctx->sha384)) < 0) { + return rc; + } + psSha384Update(&ctx->sha384, ctx->pad, padLen); + + for (i = 0; (uint32)i < keyLen; i++) { + ctx->pad[i] = key[i] ^ 0x5c; + } + for (i = keyLen; i < padLen; i++) { + ctx->pad[i] = 0x5c; + } + return PS_SUCCESS; +} + +void psHmacSha384Update(psHmacSha384_t *ctx, + const unsigned char *buf, uint32_t len) +{ +#ifdef CRYPTO_ASSERT + psAssert(ctx != NULL && buf != NULL); +#endif + psSha384Update(&ctx->sha384, buf, len); +} + +void psHmacSha384Final(psHmacSha384_t *ctx, + unsigned char hash[SHA384_HASHLEN]) +{ + int32_t rc; +#ifdef CRYPTO_ASSERT + psAssert(ctx != NULL); + if (hash == NULL) { + psTraceCrypto("NULL hash storage passed to psHmacSha256Final\n"); + return; + } +#endif + + psSha384Final(&ctx->sha384, hash); + + if ((rc = psSha384Init(&ctx->sha384)) < 0) { + psAssert(rc >= 0); + return; + } + psSha384Update(&ctx->sha384, ctx->pad, 128); + psSha384Update(&ctx->sha384, hash, SHA384_HASHLEN); + psSha384Final(&ctx->sha384, hash); + + memset(ctx->pad, 0x0, sizeof(ctx->pad)); +} +#endif /* USE_MATRIX_HMAC_SHA384 */ + +/******************************************************************************/ + diff --git a/crypto/digest/md2.c b/crypto/digest/md2.c new file mode 100644 index 0000000..8ad5d0d --- /dev/null +++ b/crypto/digest/md2.c @@ -0,0 +1,180 @@ +/** + * @file md2.c + * @version $Format:%h%d$ + * + * MD2 hash implementation. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_MATRIX_MD2 +/******************************************************************************/ + +static const unsigned char PI_SUBST[256] = { + 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, + 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, + 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, + 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, + 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, + 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, + 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, + 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, + 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, + 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, + 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, + 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, + 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, + 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, + 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, + 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, + 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, + 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 +}; + +/* adds 16 bytes to the checksum */ +static void md2_update_chksum(psMd2_t *md) +{ + int32 j; + unsigned char L; + L = md->chksum[15]; + for (j = 0; j < 16; j++) { + +/* + caution, the RFC says its "C[j] = S[M[i*16+j] xor L]" but the reference + source code [and test vectors] say otherwise. +*/ + L = (md->chksum[j] ^= PI_SUBST[(int32)(md->buf[j] ^ L)] & 255); + } +} + +static void md2_compress(psMd2_t *md) +{ + int32 j, k; + unsigned char t; + + /* copy block */ + for (j = 0; j < 16; j++) { + md->X[16+j] = md->buf[j]; + md->X[32+j] = md->X[j] ^ md->X[16+j]; + } + + t = (unsigned char)0; + + /* do 18 rounds */ + for (j = 0; j < 18; j++) { + for (k = 0; k < 48; k++) { + t = (md->X[k] ^= PI_SUBST[(int32)(t & 255)]); + } + t = (t + (unsigned char)j) & 255; + } +} + +void psMd2Init(psMd2_t *md) +{ +#ifdef CRYPTO_ASSERT + psAssert(md != NULL); +#endif + + /* MD2 uses a zero'ed state... */ + memset(md->X, 0x0, sizeof(md->X)); + memset(md->chksum, 0x0, sizeof(md->chksum)); + memset(md->buf, 0x0, sizeof(md->buf)); + md->curlen = 0; +} + +int32_t psMd2Update(psMd2_t *md, const unsigned char *buf, uint32_t len) +{ + uint32_t n; + +#ifdef CRYPTO_ASSERT + psAssert(md != NULL); + psAssert(buf != NULL); + if (md->curlen > sizeof(md->buf)) { + psTraceCrypto("psMd2Update error\n"); + return PS_LIMIT_FAIL; + } +#endif + while (len > 0) { + n = min(len, (16 - md->curlen)); + memcpy(md->buf + md->curlen, buf, (size_t)n); + md->curlen += n; + buf += n; + len -= n; + + /* is 16 bytes full? */ + if (md->curlen == 16) { + md2_compress(md); + md2_update_chksum(md); + md->curlen = 0; + } + } + return PS_SUCCESS; +} + +int32_t psMd2Final(psMd2_t * md, unsigned char *hash) +{ + uint32 i, k; + +#ifdef CRYPTO_ASSERT + psAssert(md != NULL); + psAssert(hash != NULL); +#endif + + if (md->curlen >= sizeof(md->buf)) { + psTraceCrypto("psMd2Final error\n"); + return PS_LIMIT_FAIL; + } + + + /* pad the message */ + k = 16 - md->curlen; + for (i = md->curlen; i < 16; i++) { + md->buf[i] = (unsigned char)k; + } + + /* hash and update */ + md2_compress(md); + md2_update_chksum(md); + + /* hash checksum */ + memcpy(md->buf, md->chksum, 16); + md2_compress(md); + + /* output is lower 16 bytes of X */ + memcpy(hash, md->X, 16); + + memset(md, 0x0, sizeof(psMd2_t)); + return PS_SUCCESS; +} + +#endif /* USE_MATRIX_MD2 */ + +/******************************************************************************/ + diff --git a/crypto/digest/md4.c b/crypto/digest/md4.c new file mode 100644 index 0000000..ef8833c --- /dev/null +++ b/crypto/digest/md4.c @@ -0,0 +1,289 @@ +/** + * @file md4.c + * @version $Format:%h%d$ + * + * MD4 hash implementation. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_MATRIX_MD4 + +/******************************************************************************/ + +#define S11 3 +#define S12 7 +#define S13 11 +#define S14 19 +#define S21 3 +#define S22 5 +#define S23 9 +#define S24 13 +#define S31 3 +#define S32 9 +#define S33 11 +#define S34 15 + +/* F, G and H are basic MD4 functions. */ +#define F(x, y, z) (z ^ (x & (y ^ z))) +#define G(x, y, z) ((x & y) | (z & (x | y))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +/* ROTATE_LEFT rotates x left n bits. */ +#define ROTATE_LEFT(x, n) ROL(x, n) + +/* FF, GG and HH are transformations for rounds 1, 2 and 3 */ +/* Rotation is separate from addition to prevent recomputation */ + +#define FF(a, b, c, d, x, s) { \ + (a) += F ((b), (c), (d)) + (x); \ + (a) = ROTATE_LEFT ((a), (s)); \ + } +#define GG(a, b, c, d, x, s) { \ + (a) += G ((b), (c), (d)) + (x) + 0x5a827999UL; \ + (a) = ROTATE_LEFT ((a), (s)); \ + } +#define HH(a, b, c, d, x, s) { \ + (a) += H ((b), (c), (d)) + (x) + 0x6ed9eba1UL; \ + (a) = ROTATE_LEFT ((a), (s)); \ + } + +#ifdef USE_BURN_STACK +static int32 _md4_compress(psMd4_t *md, const unsigned char *buf) +#else +static int32 md4_compress(psMd4_t *md, const unsigned char *buf) +#endif +{ + uint32 x[16], a, b, c, d, i; + + /* copy state */ + a = md->state[0]; + b = md->state[1]; + c = md->state[2]; + d = md->state[3]; + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32L(x[i], buf + (4*i)); + } + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11); /* 1 */ + FF (d, a, b, c, x[ 1], S12); /* 2 */ + FF (c, d, a, b, x[ 2], S13); /* 3 */ + FF (b, c, d, a, x[ 3], S14); /* 4 */ + FF (a, b, c, d, x[ 4], S11); /* 5 */ + FF (d, a, b, c, x[ 5], S12); /* 6 */ + FF (c, d, a, b, x[ 6], S13); /* 7 */ + FF (b, c, d, a, x[ 7], S14); /* 8 */ + FF (a, b, c, d, x[ 8], S11); /* 9 */ + FF (d, a, b, c, x[ 9], S12); /* 10 */ + FF (c, d, a, b, x[10], S13); /* 11 */ + FF (b, c, d, a, x[11], S14); /* 12 */ + FF (a, b, c, d, x[12], S11); /* 13 */ + FF (d, a, b, c, x[13], S12); /* 14 */ + FF (c, d, a, b, x[14], S13); /* 15 */ + FF (b, c, d, a, x[15], S14); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 0], S21); /* 17 */ + GG (d, a, b, c, x[ 4], S22); /* 18 */ + GG (c, d, a, b, x[ 8], S23); /* 19 */ + GG (b, c, d, a, x[12], S24); /* 20 */ + GG (a, b, c, d, x[ 1], S21); /* 21 */ + GG (d, a, b, c, x[ 5], S22); /* 22 */ + GG (c, d, a, b, x[ 9], S23); /* 23 */ + GG (b, c, d, a, x[13], S24); /* 24 */ + GG (a, b, c, d, x[ 2], S21); /* 25 */ + GG (d, a, b, c, x[ 6], S22); /* 26 */ + GG (c, d, a, b, x[10], S23); /* 27 */ + GG (b, c, d, a, x[14], S24); /* 28 */ + GG (a, b, c, d, x[ 3], S21); /* 29 */ + GG (d, a, b, c, x[ 7], S22); /* 30 */ + GG (c, d, a, b, x[11], S23); /* 31 */ + GG (b, c, d, a, x[15], S24); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 0], S31); /* 33 */ + HH (d, a, b, c, x[ 8], S32); /* 34 */ + HH (c, d, a, b, x[ 4], S33); /* 35 */ + HH (b, c, d, a, x[12], S34); /* 36 */ + HH (a, b, c, d, x[ 2], S31); /* 37 */ + HH (d, a, b, c, x[10], S32); /* 38 */ + HH (c, d, a, b, x[ 6], S33); /* 39 */ + HH (b, c, d, a, x[14], S34); /* 40 */ + HH (a, b, c, d, x[ 1], S31); /* 41 */ + HH (d, a, b, c, x[ 9], S32); /* 42 */ + HH (c, d, a, b, x[ 5], S33); /* 43 */ + HH (b, c, d, a, x[13], S34); /* 44 */ + HH (a, b, c, d, x[ 3], S31); /* 45 */ + HH (d, a, b, c, x[11], S32); /* 46 */ + HH (c, d, a, b, x[ 7], S33); /* 47 */ + HH (b, c, d, a, x[15], S34); /* 48 */ + + + /* Update our state */ + md->state[0] = md->state[0] + a; + md->state[1] = md->state[1] + b; + md->state[2] = md->state[2] + c; + md->state[3] = md->state[3] + d; + + return PS_SUCCESS; +} + +#ifdef USE_BURN_STACK +static int32 md4_compress(psMd4_t *md, const unsigned char *buf) +{ + int32 err; + err = _md4_compress(md, buf); + psBurnStack(sizeof(uint32) * 20 + sizeof(int32)); + return err; +} +#endif + +void psMd4Init(psMd4_t * md) +{ +#ifdef CRYPTO_ASSERT + psAssert(md != NULL); +#endif + md->state[0] = 0x67452301UL; + md->state[1] = 0xefcdab89UL; + md->state[2] = 0x98badcfeUL; + md->state[3] = 0x10325476UL; + md->curlen = 0; +#ifdef HAVE_NATIVE_INT64 + md->length = 0; +#else + md->lengthHi = 0; + md->lengthLo = 0; +#endif /* HAVE_NATIVE_INT64 */ +} + +void psMd4Update(psMd4_t * md, const unsigned char *buf, uint32_t len) +{ + uint32 n; + +#ifdef CRYPTO_ASSERT + psAssert(md != NULL); + psAssert(buf != NULL); +#endif + while (len > 0) { + n = min(len, (64 - md->curlen)); + memcpy(md->buf + md->curlen, buf, (size_t)n); + md->curlen += n; + buf += n; + len -= n; + + /* is 64 bytes full? */ + if (md->curlen == 64) { + md4_compress(md, md->buf); +#ifdef HAVE_NATIVE_INT64 + md->length += 512; +#else + n = (md->lengthLo + 512) & 0xFFFFFFFFL; + if (n < md->lengthLo) { + md->lengthHi++; + } + md->lengthLo = n; +#endif /* HAVE_NATIVE_INT64 */ + md->curlen = 0; + } + } +} + +int32_t psMd4Final(psMd4_t * md, unsigned char *out) +{ + int32 i; +#ifndef HAVE_NATIVE_INT64 + uint32 n; +#endif + +#ifdef CRYPTO_ASSERT + psAssert(md != NULL); + psAssert(out != NULL); + if (md->curlen >= sizeof(md->buf)) { + psTraceCrypto("psMd4Final error\n"); + return PS_LIMIT_FAIL; + } +#endif + + /* increase the length of the message */ +#ifdef HAVE_NATIVE_INT64 + md->length += md->curlen << 3; +#else + n = (md->lengthLo + (md->curlen << 3)) & 0xFFFFFFFFL; + if (n < md->lengthLo) { + md->lengthHi++; + } + md->lengthHi += (md->curlen >> 29); + md->lengthLo = n; +#endif /* HAVE_NATIVE_INT64 */ + + /* append the '1' bit */ + md->buf[md->curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->curlen > 56) { + while (md->curlen < 64) { + md->buf[md->curlen++] = (unsigned char)0; + } + md4_compress(md, md->buf); + md->curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->curlen < 56) { + md->buf[md->curlen++] = (unsigned char)0; + } + + /* store length */ +#ifdef HAVE_NATIVE_INT64 + STORE64L(md->length, md->buf+56); +#else + STORE32L(md->lengthLo, md->buf+56); + STORE32L(md->lengthHi, md->buf+60); +#endif /* HAVE_NATIVE_INT64 */ + md4_compress(md, md->buf); + + /* copy output */ + for (i = 0; i < 4; i++) { + STORE32L(md->state[i], out+(4*i)); + } + memset(md, 0x0, sizeof(psMd4_t)); + return PS_SUCCESS; +} + +#endif /* USE_MATRIX_MD4 */ + +/******************************************************************************/ + diff --git a/crypto/digest/md5.c b/crypto/digest/md5.c new file mode 100644 index 0000000..425ae22 --- /dev/null +++ b/crypto/digest/md5.c @@ -0,0 +1,366 @@ +/** + * @file md5.c + * @version $Format:%h%d$ + * + * MD5 hash implementation. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_MATRIX_MD5 + +static void md5_compress(psMd5_t *md5); + +/******************************************************************************/ + +int32_t psMd5Init(psMd5_t *md5) +{ +#ifdef CRYPTO_ASSERT + psAssert(md5 != NULL); +#endif + md5->state[0] = 0x67452301UL; + md5->state[1] = 0xefcdab89UL; + md5->state[2] = 0x98badcfeUL; + md5->state[3] = 0x10325476UL; + md5->curlen = 0; +#ifdef HAVE_NATIVE_INT64 + md5->length = 0; +#else + md5->lengthHi = 0; + md5->lengthLo = 0; +#endif /* HAVE_NATIVE_INT64 */ + return PS_SUCCESS; +} + +/******************************************************************************/ + +void psMd5Update(psMd5_t *md5, const unsigned char *buf, uint32_t len) +{ + uint32_t n; + +#ifdef CRYPTO_ASSERT + psAssert(md5 != NULL); + psAssert(buf != NULL); +#endif + while (len > 0) { + n = min(len, (64 - md5->curlen)); + memcpy(md5->buf + md5->curlen, buf, (size_t)n); + md5->curlen += n; + buf += n; + len -= n; + + /* is 64 bytes full? */ + if (md5->curlen == 64) { + md5_compress(md5); +#ifdef HAVE_NATIVE_INT64 + md5->length += 512; +#else + n = (md5->lengthLo + 512) & 0xFFFFFFFFL; + if (n < md5->lengthLo) { + md5->lengthHi++; + } + md5->lengthLo = n; +#endif /* HAVE_NATIVE_INT64 */ + md5->curlen = 0; + } + } +} + +/******************************************************************************/ +/** + Finalize and clear/free a hash context. + @param[in,out] md5 Hash Context + @param[out] hash Pointer to a buffer to receive finalized hash value, or + NULL to ignore output and just clear hash context. +*/ + +void psMd5Final(psMd5_t *md5, unsigned char hash[MD5_HASHLEN]) +{ + int32 i; +#ifndef HAVE_NATIVE_INT64 + uint32 n; +#endif + +#ifdef CRYPTO_ASSERT + psAssert(md5); +#endif + + /* If output parameter is NULL, just clear the context */ + if (!hash) { + goto L_CLEAR; + } + /* increase the length of the message */ +#ifdef HAVE_NATIVE_INT64 + md5->length += md5->curlen << 3; +#else + n = (md5->lengthLo + (md5->curlen << 3)) & 0xFFFFFFFFL; + if (n < md5->lengthLo) { + md5->lengthHi++; + } + md5->lengthHi += (md5->curlen >> 29); + md5->lengthLo = n; +#endif /* HAVE_NATIVE_INT64 */ + + /* append the '1' bit */ + md5->buf[md5->curlen++] = 0x80; + + /* + if the length is currently above 56 bytes we append zeros then compress. + Then we can fall back to padding zeros and length encoding like normal. + */ + if (md5->curlen > 56) { + while (md5->curlen < 64) { + md5->buf[md5->curlen++] = 0x0; + } + md5_compress(md5); + md5->curlen = 0; + } + /* pad up to 56 bytes of zeroes */ + while (md5->curlen < 56) { + md5->buf[md5->curlen++] = 0x0; + } + /* store length */ +#ifdef HAVE_NATIVE_INT64 + STORE64L(md5->length, md5->buf+56); +#else + STORE32L(md5->lengthLo, md5->buf+56); + STORE32L(md5->lengthHi, md5->buf+60); +#endif /* HAVE_NATIVE_INT64 */ + md5_compress(md5); + + /* copy output */ + for (i = 0; i < 4; i++) { + STORE32L(md5->state[i], hash+(4*i)); + } +L_CLEAR: + memset(md5, 0x0, sizeof(psMd5_t)); +} + +/******************************************************************************/ + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define G(x,y,z) (y ^ (z & (y ^ x))) +#define H(x,y,z) (x^y^z) +#define I(x,y,z) (y^(x|(~z))) + +#ifndef PS_MD5_IMPROVE_PERF_INCREASE_CODESIZE + +#define FF(a,b,c,d,M,s,t) \ + a = (a + F(b,c,d) + M + t); a = ROL(a, s) + b; + +#define GG(a,b,c,d,M,s,t) \ + a = (a + G(b,c,d) + M + t); a = ROL(a, s) + b; + +#define HH(a,b,c,d,M,s,t) \ + a = (a + H(b,c,d) + M + t); a = ROL(a, s) + b; + +#define II(a,b,c,d,M,s,t) \ + a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b; + +static const unsigned char Worder[64] = { + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, + 1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12, + 5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2, + 0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9 +}; + +static const unsigned char Rorder[64] = { + 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22, + 5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20, + 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23, + 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21 +}; + +static const uint32 Korder[] = { + 0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL, + 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL, + 0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL, + 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL, + 0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL, + 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL, + 0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL, + 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL, + 0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL, + 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL, + 0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL, + 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL, + 0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL, + 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL, + 0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL, + 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL, + 0xe1f27f3aUL, 0xf5710fb0UL, 0xada0e5c4UL, 0x98e4c919UL + }; +#else /* PS_MD5_IMPROVE_PERF_INCREASE_CODESIZE */ + +#define FF(a,b,c,d,M,s,t) \ + a = (a + F(b,c,d) + M + t); a = ROL(a, s) + b; + +#define GG(a,b,c,d,M,s,t) \ + a = (a + G(b,c,d) + M + t); a = ROL(a, s) + b; + +#define HH(a,b,c,d,M,s,t) \ + a = (a + H(b,c,d) + M + t); a = ROL(a, s) + b; + +#define II(a,b,c,d,M,s,t) \ + a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b; + +#endif /* PS_MD5_IMPROVE_PERF_INCREASE_CODESIZE */ + +#ifdef USE_BURN_STACK +static void _md5_compress(psMd5_t *md5) +#else +static void md5_compress(psMd5_t *md5) +#endif /* USE_BURN_STACK */ +{ + uint32 i, W[16], a, b, c, d; +#ifndef PS_MD5_IMPROVE_PERF_INCREASE_CODESIZE + uint32 t; +#endif +#ifdef CRYPTO_ASSERT + psAssert(md5 != NULL); +#endif + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32L(W[i], md5->buf + (4*i)); + } + + /* copy state */ + a = md5->state[0]; + b = md5->state[1]; + c = md5->state[2]; + d = md5->state[3]; + +#ifndef PS_MD5_IMPROVE_PERF_INCREASE_CODESIZE + for (i = 0; i < 16; ++i) { + FF(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + + for (; i < 32; ++i) { + GG(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + + for (; i < 48; ++i) { + HH(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + + for (; i < 64; ++i) { + II(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + +#else /* PS_MD5_IMPROVE_PERF_INCREASE_CODESIZE */ + + FF(a,b,c,d,W[0],7,0xd76aa478UL) + FF(d,a,b,c,W[1],12,0xe8c7b756UL) + FF(c,d,a,b,W[2],17,0x242070dbUL) + FF(b,c,d,a,W[3],22,0xc1bdceeeUL) + FF(a,b,c,d,W[4],7,0xf57c0fafUL) + FF(d,a,b,c,W[5],12,0x4787c62aUL) + FF(c,d,a,b,W[6],17,0xa8304613UL) + FF(b,c,d,a,W[7],22,0xfd469501UL) + FF(a,b,c,d,W[8],7,0x698098d8UL) + FF(d,a,b,c,W[9],12,0x8b44f7afUL) + FF(c,d,a,b,W[10],17,0xffff5bb1UL) + FF(b,c,d,a,W[11],22,0x895cd7beUL) + FF(a,b,c,d,W[12],7,0x6b901122UL) + FF(d,a,b,c,W[13],12,0xfd987193UL) + FF(c,d,a,b,W[14],17,0xa679438eUL) + FF(b,c,d,a,W[15],22,0x49b40821UL) + GG(a,b,c,d,W[1],5,0xf61e2562UL) + GG(d,a,b,c,W[6],9,0xc040b340UL) + GG(c,d,a,b,W[11],14,0x265e5a51UL) + GG(b,c,d,a,W[0],20,0xe9b6c7aaUL) + GG(a,b,c,d,W[5],5,0xd62f105dUL) + GG(d,a,b,c,W[10],9,0x02441453UL) + GG(c,d,a,b,W[15],14,0xd8a1e681UL) + GG(b,c,d,a,W[4],20,0xe7d3fbc8UL) + GG(a,b,c,d,W[9],5,0x21e1cde6UL) + GG(d,a,b,c,W[14],9,0xc33707d6UL) + GG(c,d,a,b,W[3],14,0xf4d50d87UL) + GG(b,c,d,a,W[8],20,0x455a14edUL) + GG(a,b,c,d,W[13],5,0xa9e3e905UL) + GG(d,a,b,c,W[2],9,0xfcefa3f8UL) + GG(c,d,a,b,W[7],14,0x676f02d9UL) + GG(b,c,d,a,W[12],20,0x8d2a4c8aUL) + HH(a,b,c,d,W[5],4,0xfffa3942UL) + HH(d,a,b,c,W[8],11,0x8771f681UL) + HH(c,d,a,b,W[11],16,0x6d9d6122UL) + HH(b,c,d,a,W[14],23,0xfde5380cUL) + HH(a,b,c,d,W[1],4,0xa4beea44UL) + HH(d,a,b,c,W[4],11,0x4bdecfa9UL) + HH(c,d,a,b,W[7],16,0xf6bb4b60UL) + HH(b,c,d,a,W[10],23,0xbebfbc70UL) + HH(a,b,c,d,W[13],4,0x289b7ec6UL) + HH(d,a,b,c,W[0],11,0xeaa127faUL) + HH(c,d,a,b,W[3],16,0xd4ef3085UL) + HH(b,c,d,a,W[6],23,0x04881d05UL) + HH(a,b,c,d,W[9],4,0xd9d4d039UL) + HH(d,a,b,c,W[12],11,0xe6db99e5UL) + HH(c,d,a,b,W[15],16,0x1fa27cf8UL) + HH(b,c,d,a,W[2],23,0xc4ac5665UL) + II(a,b,c,d,W[0],6,0xf4292244UL) + II(d,a,b,c,W[7],10,0x432aff97UL) + II(c,d,a,b,W[14],15,0xab9423a7UL) + II(b,c,d,a,W[5],21,0xfc93a039UL) + II(a,b,c,d,W[12],6,0x655b59c3UL) + II(d,a,b,c,W[3],10,0x8f0ccc92UL) + II(c,d,a,b,W[10],15,0xffeff47dUL) + II(b,c,d,a,W[1],21,0x85845dd1UL) + II(a,b,c,d,W[8],6,0x6fa87e4fUL) + II(d,a,b,c,W[15],10,0xfe2ce6e0UL) + II(c,d,a,b,W[6],15,0xa3014314UL) + II(b,c,d,a,W[13],21,0x4e0811a1UL) + II(a,b,c,d,W[4],6,0xf7537e82UL) + II(d,a,b,c,W[11],10,0xbd3af235UL) + II(c,d,a,b,W[2],15,0x2ad7d2bbUL) + II(b,c,d,a,W[9],21,0xeb86d391UL) +#endif /* PS_MD5_IMPROVE_PERF_INCREASE_CODESIZE */ + + md5->state[0] = md5->state[0] + a; + md5->state[1] = md5->state[1] + b; + md5->state[2] = md5->state[2] + c; + md5->state[3] = md5->state[3] + d; +} + +#ifdef USE_BURN_STACK +static void md5_compress(psMd5_t *md5) +{ + _md5_compress(md5); + psBurnStack(sizeof(uint32) * 21); +} +#endif /* USE_BURN_STACK */ + +#endif /* USE_MATRIX_MD5 */ +/******************************************************************************/ + diff --git a/crypto/digest/md5sha1.c b/crypto/digest/md5sha1.c new file mode 100644 index 0000000..bb7c53a --- /dev/null +++ b/crypto/digest/md5sha1.c @@ -0,0 +1,96 @@ +/** + * @file md5sha1.c + * @version $Format:%h%d$ + * + * Combined MD5+SHA1 hash for SSL 3.0 and TLS 1.0/1.1 handshake hash. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_MATRIX_MD5SHA1 + +#if !defined(USE_MD5) || !defined(USE_SHA1) +#error USE_MD5 and USE_SHA1 required +#endif + +/******************************************************************************/ +/** + Maintain MD5 and SHA1 hashes of the same data. + @note This could be done more optimally, give the use of this in TLS. + Some state is shared between the two contexts, and some paralellism + could be used in calculation. +*/ +int32_t psMd5Sha1Init(psMd5Sha1_t *md) +{ + int32_t rc; +#ifdef CRYPTO_ASSERT + psAssert(md); +#endif + if ((rc = psMd5Init(&md->md5)) < 0) { + return rc; + } + if ((rc = psSha1Init(&md->sha1)) < 0) { + /* We call Final to clear the state, ignoring the output */ + psMd5Final(&md->md5, NULL); + return rc; + } + return PS_SUCCESS; +} + +/** + Update MD5 and SHA1 hashes of the same data. +*/ +void psMd5Sha1Update(psMd5Sha1_t *md, const unsigned char *buf, + uint32_t len) +{ +#ifdef CRYPTO_ASSERT + psAssert(md && buf); +#endif + psMd5Update(&md->md5, buf, len); + psSha1Update(&md->sha1, buf, len); +} + +/** + Finalize output of the combined MD5-SHA1 + The output is 36 bytes, first the 16 bytes MD5 then the 20 bytes SHA1 +*/ +void psMd5Sha1Final(psMd5Sha1_t *md, unsigned char hash[MD5SHA1_HASHLEN]) +{ +#ifdef CRYPTO_ASSERT + psAssert(md && hash); +#endif + psMd5Final(&md->md5, hash); + psSha1Final(&md->sha1, hash + MD5_HASHLEN); +} + +#endif /* USE_MATRIX_MD5SHA1 */ + +/******************************************************************************/ + diff --git a/crypto/digest/sha1.c b/crypto/digest/sha1.c new file mode 100644 index 0000000..78c2832 --- /dev/null +++ b/crypto/digest/sha1.c @@ -0,0 +1,272 @@ +/** + * @file sha1.c + * @version $Format:%h%d$ + * + * SHA1 hash implementation. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_MATRIX_SHA1 + +/******************************************************************************/ + +#define F0(x,y,z) (z ^ (x & (y ^ z))) +#define F1(x,y,z) (x ^ y ^ z) +#define F2(x,y,z) ((x & y) | (z & (x | y))) +#define F3(x,y,z) (x ^ y ^ z) + +#ifdef USE_BURN_STACK +static void _sha1_compress(psSha1_t *sha1) +#else +static void sha1_compress(psSha1_t *sha1) +#endif /* USE_BURN_STACK */ +{ + uint32 a,b,c,d,e,W[80],i; +#ifndef PS_SHA1_IMPROVE_PERF_INCREASE_CODESIZE + uint32 t; +#endif + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32H(W[i], sha1->buf + (4*i)); + } + + /* copy state */ + a = sha1->state[0]; + b = sha1->state[1]; + c = sha1->state[2]; + d = sha1->state[3]; + e = sha1->state[4]; + + /* expand it */ + for (i = 16; i < 80; i++) { + W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); + } + + /* compress round one */ + #define FF0(a,b,c,d,e,i) e = (ROL(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROL(b, 30); + #define FF1(a,b,c,d,e,i) e = (ROL(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROL(b, 30); + #define FF2(a,b,c,d,e,i) e = (ROL(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROL(b, 30); + #define FF3(a,b,c,d,e,i) e = (ROL(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROL(b, 30); + +#ifndef PS_SHA1_IMPROVE_PERF_INCREASE_CODESIZE + for (i = 0; i < 20; ) { + FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 40; ) { + FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 60; ) { + FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 80; ) { + FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } +#else /* PS_SHA1_IMPROVE_PERF_INCREASE_CODESIZE */ + for (i = 0; i < 20; ) { + FF0(a,b,c,d,e,i++); + FF0(e,a,b,c,d,i++); + FF0(d,e,a,b,c,i++); + FF0(c,d,e,a,b,i++); + FF0(b,c,d,e,a,i++); + } + + /* round two */ + for (; i < 40; ) { + FF1(a,b,c,d,e,i++); + FF1(e,a,b,c,d,i++); + FF1(d,e,a,b,c,i++); + FF1(c,d,e,a,b,i++); + FF1(b,c,d,e,a,i++); + } + + /* round three */ + for (; i < 60; ) { + FF2(a,b,c,d,e,i++); + FF2(e,a,b,c,d,i++); + FF2(d,e,a,b,c,i++); + FF2(c,d,e,a,b,i++); + FF2(b,c,d,e,a,i++); + } + + /* round four */ + for (; i < 80; ) { + FF3(a,b,c,d,e,i++); + FF3(e,a,b,c,d,i++); + FF3(d,e,a,b,c,i++); + FF3(c,d,e,a,b,i++); + FF3(b,c,d,e,a,i++); + } +#endif /* PS_SHA1_IMPROVE_PERF_INCREASE_CODESIZE */ + + #undef FF0 + #undef FF1 + #undef FF2 + #undef FF3 + + /* store */ + sha1->state[0] = sha1->state[0] + a; + sha1->state[1] = sha1->state[1] + b; + sha1->state[2] = sha1->state[2] + c; + sha1->state[3] = sha1->state[3] + d; + sha1->state[4] = sha1->state[4] + e; +} + +#ifdef USE_BURN_STACK +static void sha1_compress(psSha1_t *sha1) +{ + _sha1_compress(sha1); + psBurnStack(sizeof(uint32) * 87); +} +#endif /* USE_BURN_STACK */ + +/******************************************************************************/ + +int32_t psSha1Init(psSha1_t *sha1) +{ +#ifdef CRYPTO_ASSERT + psAssert(sha1 != NULL); +#endif + sha1->state[0] = 0x67452301UL; + sha1->state[1] = 0xefcdab89UL; + sha1->state[2] = 0x98badcfeUL; + sha1->state[3] = 0x10325476UL; + sha1->state[4] = 0xc3d2e1f0UL; + sha1->curlen = 0; +#ifdef HAVE_NATIVE_INT64 + sha1->length = 0; +#else + sha1->lengthHi = 0; + sha1->lengthLo = 0; +#endif /* HAVE_NATIVE_INT64 */ + return PS_SUCCESS; +} + +void psSha1Update(psSha1_t *sha1, const unsigned char *buf, uint32_t len) +{ + uint32_t n; + +#ifdef CRYPTO_ASSERT + psAssert(sha1 != NULL); + psAssert(buf != NULL); +#endif + while (len > 0) { + n = min(len, (64 - sha1->curlen)); + memcpy(sha1->buf + sha1->curlen, buf, (size_t)n); + sha1->curlen += n; + buf += n; + len -= n; + + /* is 64 bytes full? */ + if (sha1->curlen == 64) { + sha1_compress(sha1); +#ifdef HAVE_NATIVE_INT64 + sha1->length += 512; +#else + n = (sha1->lengthLo + 512) & 0xFFFFFFFFL; + if (n < sha1->lengthLo) { + sha1->lengthHi++; + } + sha1->lengthLo = n; +#endif /* HAVE_NATIVE_INT64 */ + sha1->curlen = 0; + } + } +} + +/******************************************************************************/ + +void psSha1Final(psSha1_t *sha1, unsigned char hash[SHA1_HASHLEN]) +{ + int32 i; +#ifndef HAVE_NATIVE_INT64 + uint32 n; +#endif +#ifdef CRYPTO_ASSERT + psAssert(sha1 != NULL); + if (sha1->curlen >= sizeof(sha1->buf) || hash == NULL) { + psTraceCrypto("psSha1Final error\n"); + return; + } +#endif + /* increase the length of the message */ +#ifdef HAVE_NATIVE_INT64 + sha1->length += sha1->curlen << 3; +#else + n = (sha1->lengthLo + (sha1->curlen << 3)) & 0xFFFFFFFFL; + if (n < sha1->lengthLo) { + sha1->lengthHi++; + } + sha1->lengthHi += (sha1->curlen >> 29); + sha1->lengthLo = n; +#endif /* HAVE_NATIVE_INT64 */ + + /* append the '1' bit */ + sha1->buf[sha1->curlen++] = (unsigned char)0x80; + + /* + if the length is currently above 56 bytes we append zeros then compress. + Then we can fall back to padding zeros and length encoding like normal. + */ + if (sha1->curlen > 56) { + while (sha1->curlen < 64) { + sha1->buf[sha1->curlen++] = (unsigned char)0; + } + sha1_compress(sha1); + sha1->curlen = 0; + } + /* pad upto 56 bytes of zeroes */ + while (sha1->curlen < 56) { + sha1->buf[sha1->curlen++] = (unsigned char)0; + } + /* store length */ +#ifdef HAVE_NATIVE_INT64 + STORE64H(sha1->length, sha1->buf+56); +#else + STORE32H(sha1->lengthHi, sha1->buf+56); + STORE32H(sha1->lengthLo, sha1->buf+60); +#endif /* HAVE_NATIVE_INT64 */ + sha1_compress(sha1); + + /* copy output */ + for (i = 0; i < 5; i++) { + STORE32H(sha1->state[i], hash+(4*i)); + } + memset(sha1, 0x0, sizeof(psSha1_t)); +} + +#endif /* USE_MATRIX_SHA1 */ + +/******************************************************************************/ + diff --git a/crypto/digest/sha256.c b/crypto/digest/sha256.c new file mode 100644 index 0000000..97fcab4 --- /dev/null +++ b/crypto/digest/sha256.c @@ -0,0 +1,401 @@ +/** + * @file sha256.c + * @version $Format:%h%d$ + * + * SHA256 hash implementation. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_MATRIX_SHA256 + +/******************************************************************************/ + +#ifndef PS_SHA256_IMPROVE_PERF_INCREASE_CODESIZE + +/* The K array */ +static const uint32_t K[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, + 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, + 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, + 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, + 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, + 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, + 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, + 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, + 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, + 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; +#endif /* PS_SHA256_IMPROVE_PERF_INCREASE_CODESIZE */ + +/* Various logical functions */ +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) (((x | y) & z) | (x & y)) +#define S(x, n) ROR((x),(n)) +#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) +#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) +#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) +#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) +#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) + + +/* + compress 512-bits + */ +#ifdef USE_BURN_STACK +static void _sha256_compress(psSha256_t *sha256, const unsigned char *buf) +#else +static void sha256_compress(psSha256_t *sha256, const unsigned char *buf) +#endif /* CLEAN_STACK */ +{ + + uint32 S[8], W[64], t0, t1; +#ifndef PS_SHA256_IMPROVE_PERF_INCREASE_CODESIZE + uint32 t; +#endif /* PS_SHA256_IMPROVE_PERF_INCREASE_CODESIZE */ + int32 i; + + /* copy state into S */ + for (i = 0; i < 8; i++) { + S[i] = sha256->state[i]; + } + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32H(W[i], buf + (4*i)); + } + + /* fill W[16..63] */ + for (i = 16; i < 64; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; + } + + /* Compress */ +#ifndef PS_SHA256_IMPROVE_PERF_INCREASE_CODESIZE +#define RND(a,b,c,d,e,f,g,h,i) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + + for (i = 0; i < 64; ++i) { + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i); + t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; + S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; + } +#else /* PS_SHA256_IMPROVE_PERF_INCREASE_CODESIZE */ +#define RND(a,b,c,d,e,f,g,h,i,ki) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2); + +#undef RND + +#endif /* PS_SHA256_IMPROVE_PERF_INCREASE_CODESIZE */ + + /* feedback */ + for (i = 0; i < 8; i++) { + sha256->state[i] = sha256->state[i] + S[i]; + } + +} + +#ifdef USE_BURN_STACK +static void sha256_compress(psSha256_t *sha256, const unsigned char *buf) +{ + _sha256_compress(sha256, buf); + psBurnStack(sizeof(uint32) * 74); +} +#endif /* USE_BURN_STACK */ + +/******************************************************************************/ + +int32_t psSha256Init(psSha256_t *sha256) +{ +#ifdef CRYPTO_ASSERT + psAssert(sha256 != NULL); +#endif + sha256->curlen = 0; + sha256->state[0] = 0x6A09E667UL; + sha256->state[1] = 0xBB67AE85UL; + sha256->state[2] = 0x3C6EF372UL; + sha256->state[3] = 0xA54FF53AUL; + sha256->state[4] = 0x510E527FUL; + sha256->state[5] = 0x9B05688CUL; + sha256->state[6] = 0x1F83D9ABUL; + sha256->state[7] = 0x5BE0CD19UL; +#ifdef HAVE_NATIVE_INT64 + sha256->length = 0; +#else + sha256->lengthHi = 0; + sha256->lengthLo = 0; +#endif /* HAVE_NATIVE_INT64 */ + return PS_SUCCESS; +} + +/******************************************************************************/ + +void psSha256Update(psSha256_t *sha256, const unsigned char *buf, uint32_t len) +{ + uint32 n; + +#ifdef CRYPTO_ASSERT + psAssert(sha256 != NULL); + psAssert(buf != NULL); +#endif + + while (len > 0) { + if (sha256->curlen == 0 && len >= 64) { + sha256_compress(sha256, (unsigned char *)buf); +#ifdef HAVE_NATIVE_INT64 + sha256->length += 512; +#else + n = (sha256->lengthLo + 512) & 0xFFFFFFFFL; + if (n < sha256->lengthLo) { + sha256->lengthHi++; + } + sha256->lengthLo = n; +#endif /* HAVE_NATIVE_INT64 */ + buf += 64; + len -= 64; + } else { + n = min(len, (64 - sha256->curlen)); + memcpy(sha256->buf + sha256->curlen, buf, (size_t)n); + sha256->curlen += n; + buf += n; + len -= n; + + if (sha256->curlen == 64) { + sha256_compress (sha256, sha256->buf); +#ifdef HAVE_NATIVE_INT64 + sha256->length += 512; +#else + n = (sha256->lengthLo + 512) & 0xFFFFFFFFL; + if (n < sha256->lengthLo) { + sha256->lengthHi++; + } + sha256->lengthLo = n; +#endif /* HAVE_NATIVE_INT64 */ + sha256->curlen = 0; + } + } + } + return; +} + +/******************************************************************************/ + +void psSha256Final(psSha256_t *sha256, unsigned char hash[SHA256_HASHLEN]) +{ + int32 i; +#ifndef HAVE_NATIVE_INT64 + uint32 n; +#endif + +#ifdef CRYPTO_ASSERT + psAssert(sha256 != NULL); + psAssert(hash != NULL); + if (sha256->curlen >= sizeof(sha256->buf)) { + psTraceCrypto("psSha256Final error\n"); + return; + } +#endif + + /* increase the length of the message */ +#ifdef HAVE_NATIVE_INT64 + sha256->length += sha256->curlen << 3; +#else + n = (sha256->lengthLo + (sha256->curlen << 3)) & 0xFFFFFFFFL; + if (n < sha256->lengthLo) { + sha256->lengthHi++; + } + sha256->lengthHi += (sha256->curlen >> 29); + sha256->lengthLo = n; +#endif /* HAVE_NATIVE_INT64 */ + + /* append the '1' bit */ + sha256->buf[sha256->curlen++] = (unsigned char)0x80; + +/* + if the length is currently above 56 bytes we append zeros then compress. + Then we can fall back to padding zeros and length encoding like normal. +*/ + if (sha256->curlen > 56) { + while (sha256->curlen < 64) { + sha256->buf[sha256->curlen++] = (unsigned char)0; + } + sha256_compress(sha256, sha256->buf); + sha256->curlen = 0; + } + /* pad upto 56 bytes of zeroes */ + while (sha256->curlen < 56) { + sha256->buf[sha256->curlen++] = (unsigned char)0; + } + + /* store length */ +#ifdef HAVE_NATIVE_INT64 + STORE64H(sha256->length, sha256->buf+56); +#else + STORE32H(sha256->lengthHi, sha256->buf+56); + STORE32H(sha256->lengthLo, sha256->buf+60); +#endif /* HAVE_NATIVE_INT64 */ + sha256_compress(sha256, sha256->buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE32H(sha256->state[i], hash+(4*i)); + } + memset(sha256, 0x0, sizeof(psSha256_t)); +} + +#ifdef USE_SHA224 +/******************************************************************************/ + +void psSha224Init(psSha256_t *sha256) +{ +#ifdef CRYPTO_ASSERT + psAssert(sha256 != NULL); +#endif + + sha256->curlen = 0; +#ifdef HAVE_NATIVE_INT64 + sha256->length = 0; +#else + sha256->lengthHi = 0; + sha256->lengthLo = 0; +#endif /* HAVE_NATIVE_INT64 */ + sha256->state[0] = 0xc1059ed8UL; + sha256->state[1] = 0x367cd507UL; + sha256->state[2] = 0x3070dd17UL; + sha256->state[3] = 0xf70e5939UL; + sha256->state[4] = 0xffc00b31UL; + sha256->state[5] = 0x68581511UL; + sha256->state[6] = 0x64f98fa7UL; + sha256->state[7] = 0xbefa4fa4UL; +} + +/******************************************************************************/ + +void psSha224Update(psSha256_t *sha256, const unsigned char *buf, uint32 len) +{ + psSha256Update(sha256, buf, len); +} + +/******************************************************************************/ + +void psSha224Final(psSha256_t *sha256, unsigned char out[SHA224_HASHLEN]) +{ + unsigned char buf[SHA224_HASHLEN]; + +#ifdef CRYPTO_ASSERT + psAssert(sha256 != NULL); + psAssert(out != NULL); +#endif + psSha256Final(sha256, buf); + memcpy(out, buf, SHA224_HASH_SIZE); +#ifdef USE_BURN_STACK + psBurnStack(sizeof(buf)); +#endif +} +#endif /* USE_SHA224 */ + +#endif /* USE_MATRIX_SHA256 */ + +/******************************************************************************/ + diff --git a/crypto/digest/sha512.c b/crypto/digest/sha512.c new file mode 100644 index 0000000..f4a51d3 --- /dev/null +++ b/crypto/digest/sha512.c @@ -0,0 +1,336 @@ +/** + * @file sha512.c + * @version $Format:%h%d$ + * + * SHA256 hash implementation. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#if defined(USE_MATRIX_SHA384) || defined(USE_MATRIX_SHA512) + +#ifndef HAVE_NATIVE_INT64 +#error Must have NATIVE_INT64 support +#endif + +/******************************************************************************/ + +/* the K array */ +static const uint64_t K[80] = { +CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd), +CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc), +CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019), +CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118), +CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe), +CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2), +CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1), +CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694), +CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3), +CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65), +CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483), +CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5), +CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210), +CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4), +CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725), +CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70), +CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926), +CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df), +CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8), +CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b), +CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001), +CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30), +CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910), +CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8), +CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53), +CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8), +CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb), +CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3), +CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60), +CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec), +CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9), +CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b), +CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207), +CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178), +CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6), +CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b), +CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493), +CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c), +CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a), +CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817) +}; + +/* Various logical functions */ +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) (((x | y) & z) | (x & y)) +#define S(x, n) ROR64c(x, n) +#define R(x, n) (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((uint64)n)) +#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39)) +#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41)) +#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7)) +#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6)) + +/* compress 1024-bits */ +#ifdef USE_BURN_STACK +static void _sha512_compress(psSha512_t *sha512, const unsigned char *buf) +#else +static void sha512_compress(psSha512_t *sha512, const unsigned char *buf) +#endif +{ + uint64 S[8], W[80], t0, t1; + int i; + + /* copy state into S */ + for (i = 0; i < 8; i++) { + S[i] = sha512->state[i]; + } + + /* copy the state into 1024-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD64H(W[i], buf + (8*i)); + } + + /* fill W[16..79] */ + for (i = 16; i < 80; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; + } + + /* Compress */ +#ifndef PS_SHA512_IMPROVE_PERF_INCREASE_CODESIZE + for (i = 0; i < 80; i++) { + t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i]; + t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]); + S[7] = S[6]; + S[6] = S[5]; + S[5] = S[4]; + S[4] = S[3] + t0; + S[3] = S[2]; + S[2] = S[1]; + S[1] = S[0]; + S[0] = t0 + t1; + } +#else +#define RND(a,b,c,d,e,f,g,h,i) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + + for (i = 0; i < 80; i += 8) { + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); + } +#endif /* PS_SHA512_IMPROVE_PERF_INCREASE_CODESIZE */ + + /* feedback */ + for (i = 0; i < 8; i++) { + sha512->state[i] = sha512->state[i] + S[i]; + } +} + +/* compress 1024-bits */ +#ifdef USE_BURN_STACK +static void sha512_compress(psSha512_t *sha512, const unsigned char *buf) +{ + _sha512_compress(sha512, buf); + psBurnStack(sizeof(uint64) * 90 + sizeof(int)); +} +#endif + +/******************************************************************************/ +#ifdef USE_MATRIX_SHA512 +/* Other 512 functions are used by 384 */ +int32_t psSha512Init(psSha512_t *sha512) +{ +#ifdef CRYPTO_ASSERT + psAssert(sha512 != NULL); +#endif + sha512->curlen = 0; + sha512->length = 0; + sha512->state[0] = CONST64(0x6a09e667f3bcc908); + sha512->state[1] = CONST64(0xbb67ae8584caa73b); + sha512->state[2] = CONST64(0x3c6ef372fe94f82b); + sha512->state[3] = CONST64(0xa54ff53a5f1d36f1); + sha512->state[4] = CONST64(0x510e527fade682d1); + sha512->state[5] = CONST64(0x9b05688c2b3e6c1f); + sha512->state[6] = CONST64(0x1f83d9abfb41bd6b); + sha512->state[7] = CONST64(0x5be0cd19137e2179); + return PS_SUCCESS; +} +#endif +/******************************************************************************/ + +#ifdef USE_MATRIX_SHA512 +void psSha512Update(psSha512_t *sha512, const unsigned char *buf, uint32_t len) +#else +static void psSha512Update(psSha512_t *sha512, const unsigned char *buf, uint32_t len) +#endif +{ + uint32_t n; + + psAssert(sha512 != NULL); + psAssert(buf != NULL); + + while (len > 0) { + if (sha512->curlen == 0 && len >= 128) { + sha512_compress(sha512, (unsigned char *)buf); + sha512->length += 1024; + buf += 128; + len -= 128; + } else { + n = min(len, (128 - sha512->curlen)); + memcpy(sha512->buf + sha512->curlen, buf, (size_t)n); + sha512->curlen += n; + buf += n; + len -= n; + + if (sha512->curlen == 128) { + sha512_compress (sha512, sha512->buf); + sha512->length += 1024; + sha512->curlen = 0; + } + } + } +} + +/******************************************************************************/ + +#ifdef USE_MATRIX_SHA512 +void psSha512Final(psSha512_t *sha512, unsigned char out[SHA512_HASHLEN]) +#else +static void psSha512Final(psSha512_t *sha512, unsigned char out[SHA512_HASHLEN]) +#endif +{ + int i; +#ifdef CRYPTO_ASSERT + psAssert(sha512 != NULL); + psAssert(out != NULL); + if (sha512->curlen >= sizeof(sha512->buf)) { + return; + } +#endif + /* increase the length of the message */ + sha512->length += sha512->curlen * CONST64(8); + + /* append the '1' bit */ + sha512->buf[sha512->curlen++] = (unsigned char)0x80; + + /* if the length is currently above 112 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (sha512->curlen > 112) { + while (sha512->curlen < 128) { + sha512->buf[sha512->curlen++] = (unsigned char)0; + } + sha512_compress(sha512, sha512->buf); + sha512->curlen = 0; + } + + /* pad upto 120 bytes of zeroes + @note from 112 to 120 is the 64 MSB of the length. + We assume that you won't hash > 2^64 bits of data... :-) + */ + while (sha512->curlen < 120) { + sha512->buf[sha512->curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(sha512->length, sha512->buf+120); + sha512_compress(sha512, sha512->buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE64H(sha512->state[i], out+(8*i)); + } +#ifdef USE_BURN_STACK + psBurnStack(sizeof(psSha512_t)); +#endif +} + +#ifdef USE_MATRIX_SHA384 +/******************************************************************************/ + +int32_t psSha384Init(psSha384_t *sha384) +{ +#ifdef CRYPTO_ASSERT + psAssert(sha384 != NULL); +#endif + sha384->curlen = 0; + sha384->length = 0; + sha384->state[0] = CONST64(0xcbbb9d5dc1059ed8); + sha384->state[1] = CONST64(0x629a292a367cd507); + sha384->state[2] = CONST64(0x9159015a3070dd17); + sha384->state[3] = CONST64(0x152fecd8f70e5939); + sha384->state[4] = CONST64(0x67332667ffc00b31); + sha384->state[5] = CONST64(0x8eb44a8768581511); + sha384->state[6] = CONST64(0xdb0c2e0d64f98fa7); + sha384->state[7] = CONST64(0x47b5481dbefa4fa4); + return PS_SUCCESS; +} + +/******************************************************************************/ + +void psSha384Update(psSha384_t *sha384, const unsigned char *buf, uint32_t len) +{ + psSha512Update(sha384, buf, len); +} + +/******************************************************************************/ + +void psSha384Final(psSha384_t *sha384, unsigned char out[SHA384_HASHLEN]) +{ + unsigned char buf[SHA512_HASHLEN]; + +#ifdef CRYPTO_ASSERT + psAssert(sha384 != NULL); + psAssert(out != NULL); + if (sha384->curlen >= sizeof(sha384->buf)) { + return; + } +#endif + psSha512Final(sha384, buf); + memcpy(out, buf, SHA384_HASHLEN); +#ifdef USE_BURN_STACK + psBurnStack(sizeof(buf)); +#endif +} + +#endif /* USE_MATRIX_SHA384 */ + +#endif /* USE_MATRIX_SHA384 || USE_MATRIX_SHA512 */ + +/******************************************************************************/ + diff --git a/crypto/keyformat/asn1.c b/crypto/keyformat/asn1.c new file mode 100644 index 0000000..fc04f38 --- /dev/null +++ b/crypto/keyformat/asn1.c @@ -0,0 +1,424 @@ +/** + * @file asn1.c + * @version $Format:%h%d$ + * + * DER/BER coding. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +/******************************************************************************/ +/* + On success, p will be updated to point to first character of value and + len will contain number of bytes in value. + + Indefinite length formats return ASN_UNKNOWN_LEN and *len will simply + be updated with the overall remaining length +*/ +int32_t getAsnLength(const unsigned char **pp, uint16_t size, uint16_t *len) +{ + uint32_t len32; + int32_t rc; + + len32 = *len; + if ((rc = getAsnLength32(pp, size, &len32, 0)) < 0) { + return rc; + } + /* @note len32 is < size here, so it is <= 0xFFFF */ + *len = (uint16_t)len32; + return PS_SUCCESS; +} + +int32_t getAsnLength32(const unsigned char **pp, uint32_t size, uint32_t *len, + uint32_t indefinite) +{ + const unsigned char *c, *end; + uint32_t l; + + c = *pp; + end = c + size; + *len = 0; + if (end - c < 1) { + psTraceCrypto("getAsnLength called on empty buffer\n"); + return PS_LIMIT_FAIL; + } +/* + If the high bit is set, the lower 7 bits represent the number of + bytes that follow defining length + If the high bit is not set, the lower 7 represent the actual length +*/ + l = *c & 0x7F; + if (*c & 0x80) { + /* Point c at first length byte */ + c++; + /* Ensure we have that many bytes left in the buffer. */ + if (end - c < l) { + psTraceCrypto("Malformed stream in getAsnLength\n"); + return PS_LIMIT_FAIL; + } + + switch (l) { + case 4: + l = *c << 24; c++; + l |= *c << 16; c++; + l |= *c << 8; c++; + l |= *c; c++; + break; + case 3: + l = *c << 16; c++; + l |= *c << 8; c++; + l |= *c; c++; + break; + case 2: + l = *c << 8; c++; + l |= *c; c++; + break; + case 1: + l = *c; c++; + break; +/* + If the length byte has high bit only set, it's an indefinite + length. If allowed, return the number of bytes remaining in buffer. +*/ + case 0: + if (indefinite) { + *pp = c; + *len = size - 1; + return ASN_UNKNOWN_LEN; + } + return PS_LIMIT_FAIL; + + /* Make sure there aren't more than 4 bytes of length specifier. */ + default: + psTraceCrypto("Malformed stream in getAsnLength\n"); + return PS_LIMIT_FAIL; + } + } else { + c++; + } + + /* Stream parsers will not require the entire data to be present */ + if (!indefinite && (end - c < l)) { + psTraceCrypto("getAsnLength longer than remaining buffer.\n"); + return PS_LIMIT_FAIL; + } + + *pp = c; + *len = l; + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Callback to extract a sequence length from the DER stream + Verifies that 'len' bytes are >= 'seqlen' + Move pp to the first character in the sequence +*/ +/* #define DISABLE_STRICT_ASN_LENGTH_CHECK */ +int32_t getAsnSequence32(const unsigned char **pp, uint32_t size, + uint32_t *len, uint32_t indefinite) +{ + const unsigned char *p = *pp; + int32_t rc; + + rc = PS_PARSE_FAIL; + if (size < 1 || *(p++) != (ASN_SEQUENCE | ASN_CONSTRUCTED) || + ((rc = getAsnLength32(&p, size - 1, len, indefinite)) < 0)) { + psTraceCrypto("ASN getSequence failed\n"); + return rc; + } +#ifndef DISABLE_STRICT_ASN_LENGTH_CHECK + /* The (p - *pp) is taking the length encoding bytes into account */ + if (!indefinite && (size - ((uint32_t)(p - *pp))) < *len) { + /* It isn't cool but some encodings have an outer length layer that + is smaller than the inner. Normally you'll want this check but if + you're hitting this case, you could try skipping it to see if there + is an error in the encoding */ + psTraceCrypto("ASN_SEQUENCE parse found length greater than total\n"); + psTraceCrypto("Could try enabling DISABLE_STRICT_ASN_LENGTH_CHECK\n"); + return PS_LIMIT_FAIL; + } +#endif + *pp = p; + return rc; +} + +int32_t getAsnSequence(const unsigned char **pp, uint16_t size, uint16_t *len) +{ + uint32_t len32; + int32_t rc; + + len32 = *len; + if ((rc = getAsnSequence32(pp, size, &len32, 0)) < 0) { + return rc; + } + /* @note len32 is < size here, so it is <= 0xFFFF */ + *len = (uint16_t)len32; + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Extract a set length from the DER stream. Will also test that there + is enough data available to hold it all. Returns LIMIT_FAIL if not. +*/ +int32_t getAsnSet32(const unsigned char **pp, uint32_t size, uint32_t *len, + uint32_t indefinite) +{ + const unsigned char *p = *pp; + int32_t rc; + + rc = PS_PARSE_FAIL; + if (size < 1 || *(p++) != (ASN_SET | ASN_CONSTRUCTED) || + ((rc = getAsnLength32(&p, size - 1, len, indefinite)) < 0)) { + psTraceCrypto("ASN getSet failed\n"); + return rc; + } + /* Account for overhead needed to get the length */ + if (size < ((uint32_t)(p - *pp) + *len)) { + return PS_LIMIT_FAIL; + } + *pp = p; + return rc; +} + +int32_t getAsnSet(const unsigned char **pp, uint16_t size, uint16_t *len) +{ + uint32_t len32; + int32_t rc; + + len32 = *len; + if ((rc = getAsnSet32(pp, size, &len32, 0)) < 0) { + return rc; + } + /* @note len32 is < size here, so it is <= 0xFFFF */ + *len = (uint16_t)len32; + return PS_SUCCESS; +} +/******************************************************************************/ +/* + Get an enumerated value +*/ +int32_t getAsnEnumerated(const unsigned char **pp, uint32_t len, int32_t *val) +{ + const unsigned char *p = *pp, *end; + uint32_t ui, slen; + int32_t rc; + uint32_t vlen; + + rc = PS_PARSE_FAIL; + end = p + len; + if (len < 1 || *(p++) != ASN_ENUMERATED || + ((rc = getAsnLength32(&p, len - 1, &vlen, 0)) < 0)) { + psTraceCrypto("ASN getInteger failed from the start\n"); + return rc; + } +/* + This check prevents us from having a big positive integer where the + high bit is set because it will be encoded as 5 bytes (with leading + blank byte). If that is required, a getUnsigned routine should be used +*/ + if (vlen > sizeof(int32_t) || (uint32_t)(end - p) < vlen) { + psTraceCrypto("ASN getInteger had limit failure\n"); + return PS_LIMIT_FAIL; + } + ui = 0; +/* + If high bit is set, it's a negative integer, so perform the two's compliment + Otherwise do a standard big endian read (most likely case for RSA) +*/ + if (*p & 0x80) { + while (vlen > 0) { + ui = (ui << 8) | (*p ^ 0xFF); + p++; + vlen--; + } + slen = ui; + slen++; + slen = -slen; + *val = slen; + } else { + while (vlen > 0) { + ui = (ui << 8) | *p; + p++; + vlen--; + } + *val = ui; + } + *pp = p; + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Get an integer +*/ +int32_t getAsnInteger(const unsigned char **pp, uint32_t len, int32_t *val) +{ + const unsigned char *p = *pp, *end; + uint32_t ui, slen; + int32_t rc; + uint32_t vlen; + + rc = PS_PARSE_FAIL; + end = p + len; + if (len < 1 || *(p++) != ASN_INTEGER || + ((rc = getAsnLength32(&p, len - 1, &vlen, 0)) < 0)) { + psTraceCrypto("ASN getInteger failed from the start\n"); + return rc; + } +/* + This check prevents us from having a big positive integer where the + high bit is set because it will be encoded as 5 bytes (with leading + blank byte). If that is required, a getUnsigned routine should be used +*/ + if (vlen > sizeof(int32_t) || (uint32_t)(end - p) < vlen) { + psTraceCrypto("ASN getInteger had limit failure\n"); + return PS_LIMIT_FAIL; + } + ui = 0; +/* + If high bit is set, it's a negative integer, so perform the two's compliment + Otherwise do a standard big endian read (most likely case for RSA) +*/ + if (*p & 0x80) { + while (vlen > 0) { + ui = (ui << 8) | (*p ^ 0xFF); + p++; + vlen--; + } + slen = ui; + slen++; + slen = -slen; + *val = slen; + } else { + while (vlen > 0) { + ui = (ui << 8) | *p; + p++; + vlen--; + } + *val = ui; + } + *pp = p; + return PS_SUCCESS; +} + + +/******************************************************************************/ +/* + Implementation specific OID parser +*/ +int32_t getAsnAlgorithmIdentifier(const unsigned char **pp, uint32_t len, + int32_t *oi, uint16_t *paramLen) +{ + const unsigned char *p = *pp, *end; + int32_t rc; + uint32_t llen; + + rc = PS_PARSE_FAIL; + end = p + len; + if (len < 1 || (rc = getAsnSequence32(&p, len, &llen, 0)) < 0) { + psTraceCrypto("getAsnAlgorithmIdentifier failed on inital parse\n"); + return rc; + } + /* Always checks for parameter length */ + if (end - p < 1) { + return PS_LIMIT_FAIL; + } + rc = getAsnOID(&p, llen, oi, 1, paramLen); + *pp = p; + return rc; +} + +/******************************************************************************/ + +int32_t getAsnOID(const unsigned char **pp, uint32_t len, int32_t *oi, + uint8_t checkForParams, uint16_t *paramLen) +{ + const unsigned char *p = *pp, *end; + int32_t plen, rc; + uint32_t arcLen; + + rc = PS_PARSE_FAIL; + end = p + len; + plen = end - p; + if (*(p++) != ASN_OID || (rc = getAsnLength32(&p, (uint32_t)(end - p), &arcLen, 0)) + < 0) { + psTraceCrypto("Malformed algorithmId 2\n"); + return rc; + } + if (end - p < arcLen) { + return PS_LIMIT_FAIL; + } + if (end - p < 2) { + psTraceCrypto("Malformed algorithmId 3\n"); + return PS_LIMIT_FAIL; + } + *oi = 0; + while (arcLen > 0) { + *oi += *p; + p++; + arcLen--; + } + + if (checkForParams) { + plen -= (end - p); + *paramLen = len - plen; + if (*p != ASN_NULL) { + *pp = p; + /* paramLen tells whether params exist or completely missing (0) */ + if (*paramLen > 0) { + //psTraceIntCrypto("OID %d has parameters to process\n", *oi); + } + return PS_SUCCESS; + } + /* NULL parameter case. Somewhat common. Skip it for the caller */ + if (end - p < 2) { + psTraceCrypto("Malformed algorithmId 4\n"); + return PS_LIMIT_FAIL; + } + if (*paramLen < 2) { + psTraceCrypto("Malformed algorithmId 5\n"); + return PS_LIMIT_FAIL; + } + *paramLen -= 2; /* 1 for the OID tag and 1 for the NULL */ + *pp = p + 2; + } else { + *paramLen = 0; + *pp = p; + } + return PS_SUCCESS; +} + + +#ifdef USE_RSA +#endif /* USE_RSA */ +/******************************************************************************/ + diff --git a/crypto/keyformat/asn1.h b/crypto/keyformat/asn1.h new file mode 100644 index 0000000..6600f34 --- /dev/null +++ b/crypto/keyformat/asn1.h @@ -0,0 +1,106 @@ +/** + * @file asn1.h + * @version $Format:%h%d$ + * + * ASN.1 header. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ + +/******************************************************************************/ + +#ifndef _h_PS_ASN1 +#define _h_PS_ASN1 +#include "crypto/cryptoConfig.h" + +/******************************************************************************/ +/* + 8 bit bit masks for ASN.1 tag field +*/ +#define ASN_PRIMITIVE 0x0 +#define ASN_CONSTRUCTED 0x20 + +#define ASN_UNIVERSAL 0x0 +#define ASN_APPLICATION 0x40 +#define ASN_CONTEXT_SPECIFIC 0x80 +#define ASN_PRIVATE 0xC0 + +/* + ASN.1 primitive data types +*/ +enum { + ASN_BOOLEAN = 1, + ASN_INTEGER, + ASN_BIT_STRING, + ASN_OCTET_STRING, + ASN_NULL, + ASN_OID, + ASN_ENUMERATED = 10, + ASN_UTF8STRING = 12, + ASN_SEQUENCE = 16, + ASN_SET, + ASN_PRINTABLESTRING = 19, + ASN_T61STRING, + ASN_IA5STRING = 22, + ASN_UTCTIME, + ASN_GENERALIZEDTIME, + ASN_GENERAL_STRING = 27, + ASN_BMPSTRING = 30 +}; + +#define ASN_UNKNOWN_LEN 65533 + +extern int32_t getAsnLength(const unsigned char **p, uint16_t size, + uint16_t *valLen); +extern int32_t getAsnLength32(const unsigned char **p, uint32_t size, + uint32_t *valLen, uint32_t indefinite); +extern int32_t getAsnSequence(const unsigned char **pp, uint16_t len, + uint16_t *seqlen); +extern int32_t getAsnSequence32(const unsigned char **pp, uint32_t size, + uint32_t *len, uint32_t indefinite); +extern int32_t getAsnSet(const unsigned char **pp, uint16_t len, + uint16_t *setlen); +extern int32_t getAsnSet32(const unsigned char **pp, uint32_t size, + uint32_t *len, uint32_t indefinite); +extern int32_t getAsnEnumerated(const unsigned char **pp, uint32_t len, + int32_t *val); + +extern int32_t getAsnInteger(const unsigned char **pp, uint32_t len, + int32_t *val); +extern int32_t getAsnAlgorithmIdentifier(const unsigned char **pp, uint32_t len, + int32_t *oi, uint16_t *paramLen); +extern int32_t getAsnOID(const unsigned char **pp, uint32_t len, int32_t *oi, + uint8_t checkForParams, uint16_t *paramLen); + +/******************************************************************************/ + + + +#endif /* _h_PS_ASN1 */ + +/******************************************************************************/ + diff --git a/crypto/keyformat/base64.c b/crypto/keyformat/base64.c new file mode 100644 index 0000000..98e2095 --- /dev/null +++ b/crypto/keyformat/base64.c @@ -0,0 +1,133 @@ +/** + * @file base64.c + * @version $Format:%h%d$ + * + * Base64 operations. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_BASE64_DECODE + +static const unsigned char map[] = { +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, +255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, +255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51 +/* , 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255 +*/ +}; + +int32_t psBase64decode(const unsigned char *in, uint16_t len, + unsigned char *out, uint16_t *outlen) +{ + unsigned int t; + unsigned char c; + uint16_t x, y, z; + int16_t g; + + if (in == NULL || out == NULL || outlen == NULL) { + psTraceCrypto("Arg failure to psBase64decode\n"); + return PS_ARG_FAIL; + } + g = 3; + for (x = y = z = t = 0; x < len; x++) { + /* Save a little space by skipping values that would be 255 in the full map */ + if (in[x] > 122) { + continue; + } + c = map[in[x]]; + if (c == 255) { + continue; + } + /* the final '=' symbols are read and used to trim the remaining bytes */ + if (c == 254) { + c = 0; + /* prevent g < 0 which would potentially allow an overflow later */ + if (--g < 0) { + psTraceCrypto("Negative g failure in psBase64decode\n"); + return PS_LIMIT_FAIL; + } + } else if (g != 3) { + /* we only allow = to be at the end */ + psTraceCrypto("g failure in psBase64decode\n"); + return PS_PARSE_FAIL; + } + + t = (t << 6) | c; + + if (++y == 4) { + if (z + g > *outlen) { + psTraceCrypto("outlen too small for psBase64decode\n"); + return PS_LIMIT_FAIL; + } + out[z++] = (unsigned char)((t>>16) & 0xFF); + if (g > 1) { + out[z++] = (unsigned char)((t>>8) & 0xFF); + } + if (g > 2) { + out[z++] = (unsigned char)(t & 0xFF); + } + y = t = 0; + } + } + if (y != 0) { + psTraceCrypto("y failure in psBase64decode\n"); + return PS_PARSE_FAIL; + } + *outlen = z; + return PS_SUCCESS; +} + +#endif /* USE_BASE64_DECODE */ + +/******************************************************************************/ + + +/******************************************************************************/ + diff --git a/crypto/keyformat/pkcs.c b/crypto/keyformat/pkcs.c new file mode 100644 index 0000000..c118c77 --- /dev/null +++ b/crypto/keyformat/pkcs.c @@ -0,0 +1,2671 @@ +/** + * @file pkcs.c + * @version $Format:%h%d$ + * + * Collection of RSA PKCS standards . + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +/******************************************************************************/ +/* + Pad a value to be encrypted by RSA, according to PKCS#1 v1.5 + http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ + When encrypting a value with RSA, the value is first padded to be + equal to the public key size using the following method: + 00 00 + - id denotes a public or private key operation + - if id is private, data is however many non-zero bytes it takes to pad the + value to the key length (randomLen = keyLen - 3 - valueLen). + - if id is public, data is FF for the same length as described above + - There must be at least 8 bytes of data. +*/ +int32_t pkcs1Pad(const unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + uint8_t cryptType, void *userPtr) +{ + unsigned char *c; + uint32_t randomLen; + + randomLen = outlen - 3 - inlen; + if (randomLen < 8) { + psTraceCrypto("pkcs1Pad failure\n"); + return PS_LIMIT_FAIL; + } + c = out; + *c = 0x00; + c++; + *c = (unsigned char)cryptType; + c++; + if (cryptType == PS_PUBKEY) { + while (randomLen > 0) { + *c++ = 0xFF; + randomLen--; + } + } else { + if (matrixCryptoGetPrngData(c, randomLen, userPtr) < 0) { + return PS_PLATFORM_FAIL; + } +/* + SECURITY: Read through the random data and change all 0x0 to 0x01. + This is per spec that no random bytes should be 0 +*/ + while (randomLen > 0) { + if (*c == 0x0) { + *c = 0x01; + } + randomLen--; + c++; + } + } + *c = 0x00; + c++; + memcpy(c, in, inlen); + + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Unpad a value decrypted by RSA, according to PKCS#1 v1.5 + http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ + + When decrypted, the data will look like the pad, including the inital + byte (00). Form: + 00 00 + + We don't worry about v2 rollback issues because we don't support v2 +*/ +int32_t pkcs1Unpad(const unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + uint8_t decryptType) +{ + const unsigned char *c, *end; + + if (inlen < outlen + 10) { + psTraceCrypto("pkcs1Unpad failure\n"); + return PS_ARG_FAIL; + } + c = in; + end = in + inlen; + + /* Verify the first byte (block type) is correct. */ + if (*c++ != 0x00 || *c != decryptType) { + psTraceCrypto("pkcs1Unpad parse failure\n"); + return PS_FAILURE; + } + c++; + + /* Skip over the random, non-zero bytes used as padding */ + while (c < end && *c != 0x0) { + if (decryptType == PS_PUBKEY) { + if (*c != 0xFF) { + psTraceCrypto("pkcs1Unpad pubkey parse failure\n"); + return PS_FAILURE; + } + } + c++; + } + c++; +/* + The length of the remaining data should be equal to what was expected + Combined with the initial length check, there must be >= 8 bytes of pad + ftp://ftp.rsa.com/pub/pdfs/bulletn7.pdf +*/ + if ((uint32)(end - c) != outlen) { + psTraceCrypto("pkcs1Unpad verification failure\n"); + return PS_LIMIT_FAIL; + } + + /* Copy the value bytes to the out buffer */ + while (c < end) { + *out = *c; + out++; c++; + } + return PS_SUCCESS; +} + +#ifdef USE_PRIVATE_KEY_PARSING + +#ifdef USE_PKCS8 +/******************************************************************************/ +/** + Parse PKCS#8 format keys (from DER formatted binary) + + 'key' is dynamically allocated and must be freed with psFreePubKey() if + no error is returned from this API + + Unencrypted private keys are supported if 'pass' is NULL + Encrypted private keys are supported if 'pass' is non-null for the + des-EDE3-CBC algorithm only (3DES). Other PKCS#5 symmetric algorithms + are not supported. + + @return < 0 on error, private keysize in bytes on success. +*/ +int32 pkcs8ParsePrivBin(psPool_t *pool, unsigned char *buf, int32 size, + char *pass, psPubKey_t *key) +{ + const unsigned char *end, *p; + int32 version, oi; + uint16_t seqlen, len, plen; + +#ifdef USE_ECC + int32 coi; + const psEccCurve_t *eccSet; +#endif +#ifdef USE_PKCS5 + unsigned char desKeyBin[24]; + psCipherContext_t ctx; + char iv[8], salt[8]; + int32 icount; +#endif /* USE_PKCS5 */ + + p = buf; + end = p + size; + + if (pass) { +#ifdef USE_PKCS5 +/* An encrypted PKCS#8 key has quite a bit more information we must parse + We actually parse a good bit of PKCS#5 structures here +*/ + if (getAsnSequence(&p, (int32)(end - p), &seqlen) < 0) { + return PS_FAILURE; + } + if (getAsnAlgorithmIdentifier(&p, (int32)(end - p), &oi, &plen) < 0){ + psTraceCrypto("Couldn't parse PKCS#8 algorithm identifier\n"); + return PS_FAILURE; + } + if (oi != OID_PKCS_PBES2 || plen != 53) { + psTraceCrypto("Only supporting PKCS#8 id-PBES2 OID\n"); + return PS_FAILURE; + } + if (getAsnSequence(&p, (int32)(end - p), &seqlen) < 0) { + return PS_FAILURE; + } + if (getAsnAlgorithmIdentifier(&p, (int32)(end - p), &oi, &plen) < 0){ + psTraceCrypto("Couldn't parse PKCS#8 keyDerivationFunc\n"); + return PS_FAILURE; + } + if (oi != OID_PKCS_PBKDF2 || plen != 16) { + psTraceCrypto("Only support PKCS#8 id-PBKDF2 OID\n"); + return PS_FAILURE; + } + if (getAsnSequence(&p, (int32)(end - p), &seqlen) < 0) { + return PS_FAILURE; + } + if ((*p++ != ASN_OCTET_STRING) || + getAsnLength(&p, (int32)(end - p), &len) < 0 || + (uint32)(end - p) < len || + len != 8) { + + psTraceCrypto("Couldn't parse PKCS#8 param salt\n"); + return PS_FAILURE; + } + /* Get the PBKDF2 Salt */ + memcpy(salt, p, 8); p += 8; + /* Get the PBKDF2 Iteration count (rounds) */ + if (getAsnInteger(&p, (int32)(end - p), &icount) < 0) { + psTraceCrypto("Couldn't parse PKCS#8 param iterationCount\n"); + return PS_FAILURE; + } + /* Get encryptionScheme */ + if (getAsnAlgorithmIdentifier(&p, (int32)(end - p), &oi, &plen) + < 0){ + psTraceCrypto("Couldn't parse PKCS#8 encryptionScheme\n"); + return PS_FAILURE; + } + if (oi != OID_DES_EDE3_CBC || plen != 10) { + psTraceCrypto("Only support des-EDE3-CBC OID\n"); + return PS_FAILURE; + } + if ((uint32)(end - p) < 1) { + psTraceCrypto("Couldn't parse PKCS#8 param CBC IV\n"); + return PS_FAILURE; + } + if ((*p++ != ASN_OCTET_STRING) || + getAsnLength(&p, (int32)(end - p), &len) < 0 || + (uint32)(end - p) < len || + len != DES3_IVLEN) { + + psTraceCrypto("Couldn't parse PKCS#8 param CBC IV\n"); + return PS_FAILURE; + } + /* Get the 3DES IV */ + memcpy(iv, p, DES3_IVLEN); p += DES3_IVLEN; + + /* Now p points to the 3DES encrypted RSA key */ + if ((uint32)(end - p) < 1) { + psTraceCrypto("Couldn't parse PKCS#8 param CBC IV\n"); + return PS_FAILURE; + } + if ((*p++ != ASN_OCTET_STRING) || + getAsnLength(&p, (int32)(end - p), &len) < 0 || + (uint32)(end - p) < len || +#ifdef USE_ECC + /* May actually be an RSA key, but this check will be OK for now */ + len < MIN_ECC_BITS/8) { +#else + len < MIN_RSA_BITS/8) { +#endif + + psTraceCrypto("PKCS#8 decryption error\n"); + return PS_FAILURE; + } + /* Derive the 3DES key and decrypt the RSA key*/ + pkcs5pbkdf2((unsigned char*)pass, (int32)strlen(pass), + (unsigned char*)salt, 8, icount, (unsigned char*)desKeyBin, + DES3_KEYLEN); + psDes3Init(&ctx.des3, (unsigned char*)iv, desKeyBin); + /* TODO: possible some compilers will not like this const removal */ + psDes3Decrypt(&ctx.des3, p, (unsigned char*)p, len); + /* @security SECURITY - we zero out des3 key when done with it */ + memset_s(&ctx, sizeof(psCipherContext_t), 0x0, sizeof(psCipherContext_t)); + memset_s(desKeyBin, DES3_KEYLEN, 0x0, DES3_KEYLEN); +#else /* !USE_PKCS5 */ +/* + The private key is encrypted, but PKCS5 support has been turned off + */ + psTraceCrypto("USE_PKCS5 must be enabled for key file password\n"); + return PS_UNSUPPORTED_FAIL; +#endif /* USE_PKCS5 */ + } + + /* PrivateKeyInfo per PKCS#8 Section 6. */ + if (getAsnSequence(&p, (int32)(end - p), &seqlen) < 0) { + psTraceCrypto("Initial PrivateKeyInfo parse failure\n"); + if (pass) { + psTraceCrypto("Is it possible the password is incorrect?\n"); + } + return PS_FAILURE; + } + /* Version */ + if (getAsnInteger(&p, (int32)(end - p), &version) < 0 || version != 0) { + psTraceCrypto("Couldn't parse PKCS#8 algorithm identifier\n"); + return PS_FAILURE; + } + /* privateKeyAlgorithmIdentifier */ + if (getAsnAlgorithmIdentifier(&p, (int32)(end - p), &oi, &plen) < 0) { + psTraceCrypto("Couldn't parse PKCS#8 algorithm identifier\n"); + return PS_FAILURE; + } +#ifdef USE_ECC + if (oi != OID_ECDSA_KEY_ALG && oi != OID_RSA_KEY_ALG) { + psTraceCrypto("Unsupported public key type in PKCS#8 parse\n"); + return PS_UNSUPPORTED_FAIL; + } + if (oi == OID_ECDSA_KEY_ALG) { + /* Still a curve identifier sitting as param in the SEQUENCE */ + if ((uint32)(end - p) < 1 || *p++ != ASN_OID) { + psTraceCrypto("Expecting EC curve OID next\n"); + return PS_PARSE_FAIL; + } + if (getAsnLength(&p, (uint32)(end - p), &len) < 0 || + (uint32)(end - p) < len) { + psTraceCrypto("Malformed extension length\n"); + return PS_PARSE_FAIL; + } + coi = 0; + while (len > 0) { + coi += *p; p++; + len--; + } + if (getEccParamByOid(coi, &eccSet) < 0) { + psTraceCrypto("Unsupported EC curve OID\n"); + return PS_UNSUPPORTED_FAIL; + } + } +#else + if (oi != OID_RSA_KEY_ALG || plen != 0) { + psTraceCrypto("Unsupported public key type in PKCS#8 parse\n"); + return PS_UNSUPPORTED_FAIL; + } +#endif + /* PrivateKey Octet Stream */ + if ((uint32)(end - p) < 1) { + psTraceCrypto("Private Key len failure\n"); + return PS_PARSE_FAIL; + } + if ((*p++ != ASN_OCTET_STRING) || + getAsnLength(&p, (int32)(end - p), &len) < 0 || + (uint32)(end - p) < len) { + psTraceCrypto("getAsnLength parse error in pkcs8ParsePrivBin\n"); + return PS_FAILURE; + } + /* Note len can be zero here */ +#ifdef USE_RSA + if (oi == OID_RSA_KEY_ALG) { + /* Create the actual key here from the octet string */ + psRsaInitKey(pool, &key->key.rsa); + if (psRsaParsePkcs1PrivKey(pool, p, len, &key->key.rsa) < 0) { + psRsaClearKey(&key->key.rsa); + return PS_FAILURE; + } + key->type = PS_RSA; + key->keysize = psRsaSize(&key->key.rsa); + } +#endif +#ifdef USE_ECC + if (oi == OID_ECDSA_KEY_ALG) { + psEccInitKey(pool, &key->key.ecc, eccSet); + if (psEccParsePrivKey(pool, p, len, &key->key.ecc, eccSet) < 0) { + return PS_FAILURE; + } + key->type = PS_ECC; + key->keysize = psEccSize(&key->key.ecc); + } +#endif + p += len; + + plen = (int32)(end - p); + if (plen > 0) { + /* attributes [0] Attributes OPTIONAL */ + if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + p++; + if (getAsnLength(&p, (int32)(end - p), &len) < 0 || + (uint32)(end - p) < len) { + + psTraceCrypto("Error parsing pkcs#8 PrivateKey attributes\n"); + return PS_FAILURE; + } + /* Ignore any attributes */ + p += len; + plen = (int32)(end - p); + } + /* Any remaining bytes should be non ASN.1 bytes that correspond + to the 3DES block padding */ + while (p < end) { + if (*p++ != (char)plen) { + goto PKCS8_FAIL; + } + } + } else if (plen < 0) { + goto PKCS8_FAIL; + } + + return PS_SUCCESS; + +PKCS8_FAIL: + psClearPubKey(key); + psTraceCrypto("Did not parse key in PKCS#8 parse\n"); + return PS_FAILURE; +} + +#ifdef MATRIX_USE_FILE_SYSTEM +#ifdef USE_PKCS12 +/******************************************************************************/ +/* + A PKCS #7 ContentInfo, whose contentType is signedData in public-key + integrity mode and data in password integrity mode. + + Returns integrity mode or < 0 on failure +*/ +#define PASSWORD_INTEGRITY 1 +#define PUBKEY_INTEGRITY 2 +static int32 psParseIntegrityMode(const unsigned char **buf, int32 totLen) +{ + const unsigned char *p, *end; + uint16_t totcontentlen, len, oiLen; + int32 rc, oi; + + p = *buf; + end = p + totLen; + + if ((rc = getAsnAlgorithmIdentifier(&p, totLen, &oi, &oiLen)) < 0) { + psTraceCrypto("Initial integrity parse error\n"); + return rc; + } + + if (oi == PKCS7_DATA) { + /* Data ::= OCTET STRING */ + if (*p++ != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + return PS_PARSE_FAIL; + } + if ((rc = getAsnLength(&p, (int32)(end - p), &len)) < 0) { + return PS_PARSE_FAIL; + } + if ((*p++ != ASN_OCTET_STRING) || + getAsnLength(&p, (int32)(end - p), &totcontentlen) < 0) { + psTraceCrypto("Couldn't parse data from ContentInfo\n"); + return PS_FAILURE; + } + rc = PASSWORD_INTEGRITY; + } else if (oi == PKCS7_SIGNED_DATA) { + psTraceCrypto("SignedData integrity mode not supported\n"); + return PS_UNSUPPORTED_FAIL; + /* rc = PUBKEY_INTEGRITY; */ + } else { + psTraceCrypto("Unknown integrity mode\n"); + return PS_UNSUPPORTED_FAIL; + } + + *buf = (unsigned char*)p; + return rc; +} + +/******************************************************************************/ +/* + Generate a key given a password, salt and iteration value. + + B.2 General method from PKCS#12 + + Assumptions: hash is SHA-1, password is < 128 bytes +*/ +static int32 pkcs12pbe(psPool_t *pool, unsigned char *password, uint32 passLen, + unsigned char *salt, int saltLen, int32 iter, int32 id, + unsigned char **out, uint32 *outlen) +{ + psSha1_t ctx; + pstm_int bigb, bigone, bigtmp; + unsigned char diversifier[64], saltpass[192], hash[SHA1_HASH_SIZE]; + unsigned char B[65]; + unsigned char *p, *front; + int32 i, j, copy, count, cpyLen, binsize, plen; + + *out = NULL; + memset(diversifier, id, 64); + + for (i = 0; i < 64;) { + if ((64 - i) < saltLen) { + memcpy(&saltpass[i], salt, 64 - i); + i = 64; + } else { + memcpy(&saltpass[i], salt, saltLen); + i += saltLen; + } + } + + plen = 64 * ((passLen + 64 - 1) / 64); + if (plen + 64 > 192) { + return PS_UNSUPPORTED_FAIL; + } + for (i = 0; i < plen; i++) { + saltpass[64 + i] = password[i % passLen]; + } + + if (*outlen == SHA1_HASH_SIZE) { + count = 1; + } else { + count = (*outlen/SHA1_HASH_SIZE) + 1; + } + cpyLen = *outlen; + + front = p = psMalloc(pool, cpyLen); + if (front == NULL) { + return PS_MEM_FAIL; + } + + while (count) { + psSha1Init(&ctx); + psSha1Update(&ctx, diversifier, 64); + psSha1Update(&ctx, saltpass, 64 + plen); + psSha1Final(&ctx, hash); + for (j = 1; j < iter; j++) { + psSha1Init(&ctx); + psSha1Update(&ctx, hash, SHA1_HASH_SIZE); + psSha1Final(&ctx, hash); + } + /* Copy into outgoing key now */ + copy = min(cpyLen, SHA1_HASH_SIZE); + memcpy(p, hash, copy); + p += copy; + count--; + cpyLen -= copy; + + if (cpyLen > 0) { + /* manipulate saltpass */ + for (j = 0; j < 64; j++) { + B[j] = hash[j % SHA1_HASH_SIZE]; + } + if (pstm_init_for_read_unsigned_bin(pool, &bigb, 64) < 0) { + psFree(front, pool); + return PS_MEM_FAIL; + } + if (pstm_read_unsigned_bin(&bigb, B, 64) < 0) { + pstm_clear(&bigb); + psFree(front, pool); + return PS_MEM_FAIL; + } + if (pstm_init_for_read_unsigned_bin(pool, &bigone, 1) < 0) { + pstm_clear(&bigb); + psFree(front, pool); + return PS_MEM_FAIL; + } + pstm_set(&bigone, 1); + if (pstm_add(&bigb, &bigone, &bigb) < 0) { + pstm_clear(&bigone); + pstm_clear(&bigb); + psFree(front, pool); + return PS_MEM_FAIL; + } + pstm_clear(&bigone); + for (j = 0; j < 64 + plen; j+=64) { + if (pstm_init_for_read_unsigned_bin(pool, &bigtmp, 64) < 0) { + pstm_clear(&bigone); + pstm_clear(&bigb); + psFree(front, pool); + return PS_MEM_FAIL; + } + if (pstm_read_unsigned_bin(&bigtmp, saltpass + j, 64) < 0) { + pstm_clear(&bigone); + pstm_clear(&bigb); + pstm_clear(&bigtmp); + psFree(front, pool); + return PS_MEM_FAIL; + } + if (pstm_add(&bigb, &bigtmp, &bigtmp) < 0) { + pstm_clear(&bigone); + pstm_clear(&bigb); + pstm_clear(&bigtmp); + psFree(front, pool); + return PS_MEM_FAIL; + } + binsize = pstm_unsigned_bin_size(&bigtmp); + if (binsize > 64) { + psAssert(binsize == 65); + if (pstm_to_unsigned_bin(pool, &bigtmp, B) < 0) { + pstm_clear(&bigone); + pstm_clear(&bigb); + pstm_clear(&bigtmp); + psFree(front, pool); + return PS_MEM_FAIL; + } + memcpy(saltpass + j, B + 1, 64); /* truncate */ + } else if (binsize < 64) { + psAssert(binsize == 63); + memset(saltpass + j, 0x0, 1); /* pad with a zero */ + if (pstm_to_unsigned_bin(pool, &bigtmp, saltpass + j + 1) < 0) { + pstm_clear(&bigone); + pstm_clear(&bigb); + pstm_clear(&bigtmp); + psFree(front, pool); + return PS_MEM_FAIL; + } + } else { + if (pstm_to_unsigned_bin(pool, &bigtmp, saltpass + j) < 0) { + pstm_clear(&bigone); + pstm_clear(&bigb); + pstm_clear(&bigtmp); + psFree(front, pool); + return PS_MEM_FAIL; + } + } + pstm_clear(&bigtmp); + } + pstm_clear(&bigone); + pstm_clear(&bigb); + } + } + + *out = front; + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Return value is how many bytes were parsed out of buf +*/ +static int32 pkcs12import(psPool_t *pool, const unsigned char **buf, + uint16_t bufLen, unsigned char *password, uint16_t passLen, + unsigned char **plaintext, uint16_t *ptLen) +{ + psCipherContext_t ctx; + const unsigned char *p, *start, *end; + unsigned char *iv, *decryptKey, *pt; + unsigned char salt[8]; + int32 rc, oi, asnint; + uint32_t keyLen, ivLen; + uint16_t tmplen, tmpint; + short armor, cipher; + + *plaintext = NULL; + *ptLen = 0; + decryptKey = NULL; + + p = start = *buf; + end = p + bufLen; + + /* Encryption Algorithm */ + if ((rc = getAsnAlgorithmIdentifier(&p, (int32)(end - p), &oi, + &tmpint)) < 0) { + psTraceCrypto("Initial pkcs12import parse failure\n"); + return rc; + } + + if (oi == OID_PKCS_PBESHA40RC2) { +#ifdef USE_RC2 + armor = PBE12; + cipher = AUTH_SAFE_RC2; + keyLen = 8; +#else + psTraceCrypto("Must enable USE_RC2 in cryptoConfig.h to parse\n"); + return PS_UNSUPPORTED_FAIL; +#endif + } else if (oi == OID_PKCS_PBESHA3DES3) { + armor = PBE12; + cipher = AUTH_SAFE_3DES; + keyLen = DES3_KEYLEN; + } else { + psTraceIntCrypto("Unsupported PBE algorithm %d\n", oi); + return PS_UNSUPPORTED_FAIL; + } + + if (armor == PBE12) { + /* If PKCS12 param will be + pkcs-12PbeParams ::= SEQUENCE { + salt OCTET STRING, + iterations INTEGER + } + */ + if ((rc = getAsnSequence(&p, (int32)(end - p), &tmplen)) < 0) { + psTraceCrypto("Initial PBE12 parse failure\n"); + return rc; + } + /* salt len */ + if ((uint32)(end - p) < 1 || (*p++ != ASN_OCTET_STRING) || + getAsnLength(&p, (int32)(end - p), &tmplen) < 0 || + (uint32)(end - p) < tmplen || + tmplen != 8) { + + psTraceCrypto("Bad salt length parsing import\n"); + return PS_PARSE_FAIL; + } + memcpy(salt, p, tmplen); + p += tmplen; + /* iteration count */ + if (getAsnInteger(&p, (int32)(end - p), &asnint) < 0) { + return PS_PARSE_FAIL; + } + if (pkcs12pbe(pool, password, passLen, salt, 8, asnint, + PKCS12_KEY_ID, &decryptKey, &keyLen) < 0) { + psTraceCrypto("Error generating pkcs12 key\n"); + return PS_UNSUPPORTED_FAIL; + } + ivLen = 8; + if (pkcs12pbe(pool, password, passLen, salt, 8, asnint, + PKCS12_IV_ID, &iv, &ivLen) < 0) { + psTraceCrypto("Error generating pkcs12 iv\n"); + if (decryptKey) { + memset_s(decryptKey, keyLen, 0x0, keyLen); + psFree(decryptKey, pool); + } + return PS_UNSUPPORTED_FAIL; + } + + } else { + /* PBES2 */ + psTraceCrypto("Error PBES2 unsupported\n"); + return PS_UNSUPPORTED_FAIL; + } + + /* Got the keys but we still need to find the start of the encrypted data. + Have seen a few different BER variations at this point in the spec + depending on what wrapper we are in. Try all that we know about + */ + if ((uint32)(end - p) < 1) { + return PS_PARSE_FAIL; + } + if (*p == (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE)) { + p++; + if ((rc = getAsnLength(&p, (int32)(end - p), &tmplen)) < 0) { + if (decryptKey) { + memset_s(decryptKey, keyLen, 0x0, keyLen); + psFree(decryptKey, pool); + } + psFree(iv, pool); + return PS_PARSE_FAIL; + } + } else if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + p++; + if ((rc = getAsnLength(&p, (int32)(end - p), &tmplen)) < 0) { + if (decryptKey) { + memset_s(decryptKey, keyLen, 0x0, keyLen); + psFree(decryptKey, pool); + } + psFree(iv, pool); + return PS_PARSE_FAIL; + } + if ((uint32)(end - p) < 1 || + *p++ != ASN_OCTET_STRING || + getAsnLength(&p, (int32)(end - p), &tmplen) < 0) { + if (decryptKey) { + memset_s(decryptKey, keyLen, 0x0, keyLen); + psFree(decryptKey, pool); + } + psFree(iv, pool); + return PS_PARSE_FAIL; + } + } else if (*p == ASN_OCTET_STRING) { + p++; + if ((rc = getAsnLength(&p, (int32)(end - p), &tmplen)) < 0) { + if (decryptKey) { + memset_s(decryptKey, keyLen, 0x0, keyLen); + psFree(decryptKey, pool); + } + psFree(iv, pool); + return PS_PARSE_FAIL; + } + } else { + psTraceCrypto("Error finding ciphertext in pkcs12import\n"); + if (decryptKey) { + memset_s(decryptKey, keyLen, 0x0, keyLen); + psFree(decryptKey, pool); + } + psFree(iv, pool); + return PS_PARSE_FAIL; + } + + if (tmplen < 1 || (uint32)(end - p) < tmplen) { + return PS_PARSE_FAIL; + } + + /* Don't decrypt in-situ because we'll need to MAC this all later */ + if ((pt = psMalloc(pool, tmplen)) == NULL) { + psTraceCrypto("Out-of-memory. Increase SSL_KEY_POOL_SIZE\n"); + if (decryptKey) { + memset_s(decryptKey, keyLen, 0x0, keyLen); + psFree(decryptKey, pool); + } + psFree(iv, pool); + return PS_MEM_FAIL; + } + if (cipher == AUTH_SAFE_3DES) { + if ((rc = psDes3Init(&ctx.des3, iv, decryptKey)) < 0) { + memset_s(&ctx, sizeof(psCipherContext_t), 0x0, sizeof(psCipherContext_t)); + if (decryptKey) { + memset_s(decryptKey, keyLen, 0x0, keyLen); + psFree(decryptKey, pool); + } + psFree(iv, pool); + psFree(pt, pool); + return rc; + } + psDes3Decrypt(&ctx.des3, p, pt, tmplen); + } +#ifdef USE_RC2 + if (cipher == AUTH_SAFE_RC2) { + + /* This is a 40-bit RC2! */ + if ((rc = psRc2Init(&ctx.rc2, iv, decryptKey, 5)) < 0) { + memset_s(&ctx, sizeof(psCipherContext_t), 0x0, sizeof(psCipherContext_t)); + if (decryptKey) { + memset_s(decryptKey, keyLen, 0x0, keyLen); + psFree(decryptKey, pool); + } + psFree(iv, pool); + psFree(pt, pool); + return rc; + } + if ((rc = psRc2Decrypt(&ctx.rc2, p, pt, tmplen)) < 0) { + memset_s(&ctx, sizeof(psCipherContext_t), 0x0, sizeof(psCipherContext_t)); + if (decryptKey) { + memset_s(decryptKey, keyLen, 0x0, keyLen); + psFree(decryptKey, pool); + } + psFree(iv, pool); + psFree(pt, pool); + return rc; + } + } +#endif /* USE_RC2 */ + + if (decryptKey) { + memset_s(decryptKey, keyLen, 0x0, keyLen); + psFree(decryptKey, pool); + } + psFree(iv, pool); + + *plaintext = pt; + *ptLen = tmplen; + return (int32)(p - start); +} + +/******************************************************************************/ +/* + Determines what the safebag is and loads the material into the users + data structure (cert or private key) +*/ +static int32 parseSafeContents(psPool_t *pool, unsigned char *password, + uint32 passLen, psX509Cert_t **cert, psPubKey_t *privKey, + unsigned char *buf, uint32 totlen) +{ + psX509Cert_t *currCert, *frontCert; + const unsigned char *p, *end; + unsigned char *pt, *safeLen; + uint16_t tmplen, cryptlen, tmpint; + int32 rc, bagoi, certoi; +#ifdef PARSE_PKCS12_SAFE_ATTRIBS + uint32 attriblen; + int32 attriboi; +#endif + + p = buf; + end = p + totlen; + + /* SafeContents ::= SEQUENCE OF SafeBag + + SafeBag ::= SEQUENCE { + bagId BAG-TYPE.&id ({PKCS12BagSet}) + bagValue [0] EXPLICIT BAG-TYPE.&Type({PKCS12BagSet}{@bagId}), + bagAttributes SET OF PKCS12Attribute OPTIONAL + } */ + if ((rc = getAsnSequence(&p, (int32)(end - p), &tmplen)) < 0) { + psTraceCrypto("Initial SafeContents parse failure\n"); + return rc; + } + + end = p + tmplen; + + while (p < end) { + /* + bagtypes OBJECT IDENTIFIER ::= {pkcs-12 10 1} + + BAG-TYPE ::= TYPE-IDENTIFIER + keyBag BAG-TYPE ::= {KeyBag IDENTIFIED BY {bagtypes 1}} + pkcs8ShroudedKeyBag BAG-TYPE ::= {PKCS8ShroudedKeyBag IDENTIFIED BY + {bagtypes 2}} + certBag BAG-TYPE ::= {CertBag IDENTIFIED BY {bagtypes 3}} + crlBag BAG-TYPE ::= {CRLBag IDENTIFIED BY {bagtypes 4}} + secretBag BAG-TYPE ::= {SecretBag IDENTIFIED BY {bagtypes 5}} + safeContentsBag BAG-TYPE ::= {SafeContents IDENTIFIED BY + {bagtypes 6}} + + PKCS12BagSet BAG-TYPE ::= { + keyBag | pkcs8ShroudedKeyBag | certBag | crlBag | secretBag | + safeContentsBag, ... -- For future extensions} + + */ + if ((rc = getAsnAlgorithmIdentifier(&p, (int32)(end - p), &bagoi, + &tmpint)) < 0) { + psTraceCrypto("Initial BagType parse failure\n"); + return rc; + } + safeLen = (unsigned char*)p + tmpint; + if (*p++ != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + return PS_PARSE_FAIL; + } + if ((rc = getAsnLength(&p, (int32)(end - p), &tmplen)) < 0) { + return PS_PARSE_FAIL; + } + + switch (bagoi) { + case PKCS12_BAG_TYPE_CERT: + /* + CertBag ::= SEQUENCE { + certId BAG-TYPE.&id ({CertTypes}), + certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId}) } + + x509Certificate BAG-TYPE ::= + {OCTET STRING IDENTIFIED BY {certTypes 1}} + -- DER-encoded X.509 certificate stored in OCTET STRING + sdsiCertificate BAG-TYPE ::= + {IA5String IDENTIFIED BY {certTypes 2}} + -- Base64-encoded SDSI certificate stored in IA5String + + CertTypes BAG-TYPE ::= { + x509Certificate | + sdsiCertificate, + ... -- For future extensions + } + */ + if ((rc = getAsnAlgorithmIdentifier(&p, (int32)(end - p), + &certoi, &tmpint)) < 0) { + psTraceCrypto("Initial CertBag parse failure\n"); + return rc; + } + if (certoi != PKCS9_CERT_TYPE_X509) { + psTraceIntCrypto("Unsupported CertBag type %d\n", certoi); + return PS_UNSUPPORTED_FAIL; + } + if (*p++ != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + return PS_PARSE_FAIL; + } + if ((rc = getAsnLength(&p, (int32)(end - p), &tmplen)) < 0) { + return rc; + } + if ((*p++ != ASN_OCTET_STRING) || + getAsnLength(&p, (int32)(end - p), &tmplen) < 0) { + psTraceCrypto("Couldn't extract X509 CertBag\n"); + return PS_FAILURE; + } + /* Support cert chains */ + currCert = frontCert = *cert; + while (currCert != NULL) { + currCert = currCert->next; + } + if ((rc = psX509ParseCert(pool, p, tmplen, &currCert, + CERT_STORE_UNPARSED_BUFFER)) < 0) { + psX509FreeCert(*cert); + *cert = NULL; + psTraceCrypto("Couldn't parse certificate from CertBag\n"); + return rc; + } + if (*cert == NULL) { + *cert = currCert; + } else { + while (frontCert->next != NULL) { + frontCert = frontCert->next; + } + frontCert->next = currCert; + } + p += rc; + break; + + case PKCS12_BAG_TYPE_SHROUD: + /* A PKCS8ShroudedKeyBag holds a private key, which has been + shrouded in accordance with PKCS #8. Note that a + PKCS8ShroudedKeyBag holds only one shrouded private key. */ + if (getAsnSequence(&p, (int32)(end - p), &tmplen) < 0) { + psTraceCrypto("Initial PKCS8 ShroudKeyBag parse failure\n"); + return PS_PARSE_FAIL; + } + if ((rc = pkcs12import(pool, &p, + (int32)(end - p), password, passLen, &pt, &cryptlen)) < 0) { + psTraceIntCrypto("Import failed from AuthSafe %d\n", rc); + return rc; + } + p += rc; + /* Result of decrypt will be a PKCS#8 key */ + if ((rc = pkcs8ParsePrivBin(pool, pt, cryptlen, NULL, privKey)) + < 0) { + psFree(pt, pool); + psTraceIntCrypto("Failed shroud PKCS8 key parse %d\n", rc); + return rc; + } + psFree(pt, pool); + p += cryptlen; + break; + case PKCS12_BAG_TYPE_KEY: + if ((rc = pkcs8ParsePrivBin(pool, (unsigned char*)p, tmplen, + NULL, privKey)) < 0) { + psTraceIntCrypto("Failed PKCS8 key parse %d\n", rc); + return rc; + } + p += tmplen; + break; + default: + psTraceIntCrypto("Unsupported BAG_TYPE %d\n", bagoi); + return PS_UNSUPPORTED_FAIL; + } + + /* Attributes are at the end of the data */ + while (p != safeLen) { +#ifdef PARSE_PKCS12_SAFE_ATTRIBS + /* + TODO: incomplete parse + + PKCS12Attribute ::= SEQUENCE { + attrId ATTRIBUTE.&id ({PKCS12AttrSet}), + attrValues SET OF ATTRIBUTE.&Type ({PKCS12AttrSet}{@attrId}) + } -- This type is compatible with the X.500 type ’Attribute’ + + PKCS12AttrSet ATTRIBUTE ::= { + PKCS 12 V1.0: PERSONAL INFORMATION EXCHANGE SYNTAX 9 + friendlyName | -- from PKCS #9 + localKeyId, -- from PKCS #9 + ... -- Other attributes are allowed + } + */ + if ((rc = getAsnSet(&p, (int32)(end - p), &attriblen)) < 0) { + return rc; + } + if ((rc = getAsnAlgorithmIdentifier(&p, (int32)(end - p), &attriboi, + &pLen)) < 0) { + return rc; + } + if ((rc = getAsnSet(&p, (int32)(end - p), &attriblen)) < 0) { + return rc; + } + if ((*p++ != ASN_OCTET_STRING) || + getAsnLength(&p, (int32)(end - p), &tmplen) < 0) { + psTraceCrypto("Couldn't parse PKCS#8 param salt\n"); + return PS_FAILURE; + } + p += tmplen; +#else + p = safeLen; +#endif + } + } + return totlen; +} + +/******************************************************************************/ +/* + AuthenticatedSafe ::= SEQUENCE OF ContentInfo + -- Data if unencrypted + -- EncryptedData if password-encrypted + -- EnvelopedData if public key-encrypted +*/ +static int32 psParseAuthenticatedSafe(psPool_t *pool, psX509Cert_t **cert, + psPubKey_t *privKey, unsigned char *importPass, int32 ipassLen, + unsigned char **buf, int32 totLen) +{ + const unsigned char *p, *end; + unsigned char *pt; + uint16_t tmplen, tmpint; + int32_t asnint; + int32 rc, oi; + + p = *buf; + end = p + totLen; + if ((rc = getAsnSequence(&p, (int32)(end - p), &tmplen)) < 0) { + psTraceCrypto("Initial authenticated safe parse failure\n"); + return rc; + } + + end = p + tmplen; /* Set end to be end of authSafe for list walk */ + + while (p < end) { + if ((rc = getAsnAlgorithmIdentifier(&p, (int32)(end - p), &oi, + &tmpint)) < 0) { + psTraceCrypto("Initial content info parse failure\n"); + return rc; + } + if (oi == PKCS7_ENCRYPTED_DATA) { + /* password protected mode */ + if (*p++ != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + psTraceCrypto("Initial pkcs7 encrypted data parse failure\n"); + return PS_PARSE_FAIL; + } + if ((rc = getAsnLength(&p, (int32)(end - p), &tmplen)) < 0) { + return PS_PARSE_FAIL; + } + /* EncryptedData ::= SEQUENCE { + version Version, + encryptedContentInfo EncryptedContentInfo } */ + if ((rc = getAsnSequence(&p, (int32)(end - p), &tmplen)) < 0) { + return rc; + } + /* Version */ + if (getAsnInteger(&p, (int32)(end - p), &asnint) < 0 || + asnint != 0) { + psTraceIntCrypto("Unsupported encryptd data version %d\n", + asnint); + return PS_UNSUPPORTED_FAIL; + } + /* + EncryptedContentInfo ::= SEQUENCE { + contentType ContentType, + contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, + encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL } + + 5.1 2b) If SCi is to be encrypted with a password, make a + ContentInfo CIi of type EncryptedData. The encryptedContentInfo + field of CIi has its contentType field set to data and its + encryptedContent field set to the encryption of the BER-encoding + of SCi (note that the tag and length octets shall be present). */ + if ((rc = getAsnAlgorithmIdentifier(&p, (int32)(end - p), &oi, + &tmpint)) < 0) { + psTraceCrypto("Initial EncryptedContentInfo parse failure\n"); + return rc; + } + psAssert(oi == PKCS7_DATA); + + if ((rc = pkcs12import(pool, &p, (int32)(end - p), importPass, + ipassLen, &pt, &tmplen)) < 0) { + psTraceIntCrypto("Import failed from AuthSafe %d\n", rc); + return rc; + } + p += rc; + + /* pt is now a BER-encoded SafeContents */ + if ((rc = parseSafeContents(pool, importPass, ipassLen, cert, + privKey, pt, tmplen)) < 0) { + psTraceCrypto("Error parsing encrypted safe contents\n"); + psTraceCrypto("Is it possible the password is incorrect?\n"); + psFree(pt, pool); + return rc; + } + psFree(pt, pool); + p += rc; + } else if (oi == PKCS7_DATA) { + /* Data ::= OCTET STRING */ + if (*p++ != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + psTraceCrypto("Initial pkcs7 data parse failure\n"); + return PS_PARSE_FAIL; + } + if ((rc = getAsnLength(&p, (int32)(end - p), &tmplen)) < 0) { + return PS_PARSE_FAIL; + } + if (*p++ != ASN_OCTET_STRING || getAsnLength(&p, + (int32)(end - p), &tmplen) < 0) { + return PS_PARSE_FAIL; + } + if ((rc = parseSafeContents(pool, importPass, ipassLen, cert, + privKey, (unsigned char*)p, tmplen)) < 0) { + psTraceCrypto("Error parsing plaintext safe contents\n"); + return rc; + } + p += rc; + } else { + psTraceIntCrypto("Unsupported PKCS7 data type parse %d\n", oi); + return PS_UNSUPPORTED_FAIL; + } + } + + *buf = (unsigned char*)p; + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + + MacData ::= SEQUENCE { + mac DigestInfo, + macSalt OCTET STRING, + iterations INTEGER DEFAULT 1 + } +*/ +int32 psPkcs12Parse(psPool_t *pool, psX509Cert_t **cert, psPubKey_t *privKey, + const unsigned char *file, int32 flags, unsigned char *password, + int32 pLen, unsigned char *macPass, int32 macPassLen) +{ + psHmacSha1_t hmac; + const unsigned char *p, *end, *macStart, *macEnd; + unsigned char *fileBuf, *macKey; + unsigned char iwidePass[128]; /* 63 char password max */ + unsigned char mwidePass[128]; + unsigned char mac[SHA1_HASH_SIZE]; + unsigned char macSalt[20]; + unsigned char digest[SHA1_HASH_SIZE]; + uint16_t tmplen, tmpint; + uint32 digestLen, macKeyLen; + int32 fsize, i, j, rc, mpassLen, ipassLen, integrity, oi, asnint; + + *cert = NULL; + if ((rc = psGetFileBuf(pool, (char *)file, &fileBuf, &fsize)) < PS_SUCCESS){ + psTraceStrCrypto("Couldn't open PKCS#12 file %s\n", (char*)file); + return rc; + } + p = fileBuf; + end = p + fsize; + + /* Begin with a PFX + PFX ::= SEQUENCE { + version INTEGER {v3(3)}(v3,...), + authSafe ContentInfo, + macData MacData OPTIONAL } */ + if ((rc = getAsnSequence(&p, (int32)(end - p), &tmplen)) < 0) { + psTraceCrypto("Initial PKCS#12 parse fail\n"); + goto ERR_FBUF; + } + /* Version */ + if (getAsnInteger(&p, (int32)(end - p), &asnint) < 0 || asnint != 3) { + psTraceIntCrypto("Unsupported PKCS#12 version %d\n", asnint); + rc = PS_UNSUPPORTED_FAIL; + goto ERR_FBUF; + } + + /* Content type is the integrity mode (4 of the spec). + signedData for public-key integrity or data for password integrity */ + if ((integrity = psParseIntegrityMode(&p, (int32)(end - p))) + < PS_SUCCESS) { + psTraceCrypto("Couldn't determine PKCS#12 integrity\n"); + rc = integrity; + goto ERR_FBUF; + } + + /* Passwords are wide BMPString types + ipass is import password + mpass is MAC password */ + ipassLen = (pLen * 2) + 2; /* 2 for each char put double 0x0 to terminate */ + memset(iwidePass, 0x0, ipassLen); + for (i = 1, j = 0; i < ipassLen - 1; i += 2, j++) { + iwidePass[i] = password[j]; + } + + /* Content data is an AuthenticatedSafe */ + macStart = p; + if ((rc = psParseAuthenticatedSafe(pool, cert, privKey, iwidePass, ipassLen, + (unsigned char**)&p, (int32)(end - p))) < PS_SUCCESS) { + psTraceIntCrypto("PKCS#12 AuthenticatedSafe parse failure %d\n", rc); + goto ERR_FBUF; + } + macEnd = p; + + /* Integrity validation */ + if (integrity == PASSWORD_INTEGRITY) { + mpassLen = (macPassLen * 2) + 2; + memset(mwidePass, 0x0, mpassLen); + for (i = 1, j = 0; i < mpassLen - 1; i += 2, j++) { + mwidePass[i] = macPass[j]; + } + /* MacData ::= SEQUENCE { + mac DigestInfo, + macSalt OCTET STRING, + iterations INTEGER DEFAULT 1 + -- Note: The default is for historical reasons and its use is + -- deprecated. A higher value, like 1024 is recommended. } */ + if ((rc = getAsnSequence(&p, (int32)(end - p), &tmplen)) < 0) { + psTraceCrypto("Initial password integrity parse failure\n"); + goto ERR_FBUF; + } + /* DigestInfo ::= SEQUENCE { + digestAlgorithm DigestAlgorithmIdentifier, + digest Digest } */ + if ((rc = getAsnSequence(&p, (int32)(end - p), &tmplen)) < 0) { + psTraceCrypto("Sequence password integrity parse failure\n"); + goto ERR_FBUF; + } + if ((rc = getAsnAlgorithmIdentifier(&p, (uint32)(end - p), + &oi, &tmpint)) < 0) { + psTraceCrypto("Algorithm password integrity parse failure\n"); + goto ERR_FBUF; + } + if ((*p++ != ASN_OCTET_STRING) || + getAsnLength(&p, (int32)(end - p), &tmplen) < 0) { + psTraceCrypto("Octet digest password integrity parse failure\n"); + rc = PS_PARSE_FAIL; + goto ERR_FBUF; + } + memcpy(digest, p, tmplen); + p += tmplen; + if ((*p++ != ASN_OCTET_STRING) || + getAsnLength(&p, (int32)(end - p), &tmplen) < 0) { + psTraceCrypto("Octet macSalt password integrity parse failure\n"); + rc = PS_PARSE_FAIL; + goto ERR_FBUF; + } + if (tmplen > 20) { + psTraceCrypto("macSalt length too long\n"); + rc = PS_PARSE_FAIL; + goto ERR_FBUF; + } + memcpy(macSalt, p, tmplen); + p += tmplen; + /* Iteration count */ + if (p != end) { + if (getAsnInteger(&p, (int32)(end - p), &asnint) < 0) { + psTraceCrypto("Iteration password integrity parse failure\n"); + rc = PS_PARSE_FAIL; + goto ERR_FBUF; + } + } else { + asnint = 0; + } + psAssert(p == end); /* That's all folks */ + + if (oi == OID_SHA1_ALG) { + /* When password integrity mode is used to secure a PFX PDU, + an SHA-1 HMAC is computed on the BER-encoding of the contents + of the content field of the authSafe field in the PFX PDU */ + macKeyLen = 20; + if (pkcs12pbe(pool, mwidePass, mpassLen, macSalt, tmplen, + asnint, PKCS12_MAC_ID, &macKey, &macKeyLen) < 0) { + psTraceCrypto("Error generating pkcs12 hmac key\n"); + rc = PS_UNSUPPORTED_FAIL; + goto ERR_FBUF; + } + digestLen = (uint32)(macEnd - macStart); + psHmacSha1Init(&hmac, macKey, macKeyLen); + psHmacSha1Update(&hmac, macStart, digestLen); + psHmacSha1Final(&hmac, mac); + psFree(macKey, pool); + if (memcmp(digest, mac, SHA1_HASH_SIZE) != 0) { + psTraceCrypto("CAUTION: PKCS#12 MAC did not validate\n"); + } + } else { + psTraceCrypto("PKCS#12 must use SHA1 HMAC validation\n"); + rc = PS_UNSUPPORTED_FAIL; + goto ERR_FBUF; + } + + } + rc = PS_SUCCESS; +ERR_FBUF: + memset_s(iwidePass, sizeof(iwidePass), 0x0, sizeof(iwidePass)); + memset_s(mwidePass, sizeof(mwidePass), 0x0, sizeof(mwidePass)); + psFree(fileBuf, pool); + return rc; +} + +#endif /* USE_PKCS12 */ +#endif /* MATRIX_USE_FILE_SYSTEM */ + +#endif /* USE_PKCS8 */ + +#ifdef MATRIX_USE_FILE_SYSTEM + +#ifdef USE_PKCS5 +/******************************************************************************/ +/* + Convert an ASCII hex representation to a binary buffer. + Decode enough data out of 'hex' buffer to produce 'binlen' bytes in 'bin' + Two digits of ASCII hex map to the high and low nybbles (in that order), + so this function assumes that 'hex' points to 2x 'binlen' bytes of data. + Return the number of bytes processed from hex (2x binlen) or < 0 on error. +*/ +static int32 hexToBinary(unsigned char *hex, unsigned char *bin, int32 binlen) +{ + unsigned char *end, c, highOrder; + + highOrder = 1; + for (end = hex + binlen * 2; hex < end; hex++) { + c = *hex; + if ('0' <= c && c <='9') { + c -= '0'; + } else if ('a' <= c && c <='f') { + c -= ('a' - 10); + } else if ('A' <= c && c <='F') { + c -= ('A' - 10); + } else { + psTraceCrypto("hexToBinary failure\n"); + return PS_FAILURE; + } + if (highOrder++ & 0x1) { + *bin = c << 4; + } else { + *bin |= c; + bin++; + } + } + return binlen * 2; +} +#endif /* USE_PKCS5 */ + +#ifdef USE_RSA +/******************************************************************************/ +/** + Parse a PEM format private key file. + + @pre File must be a PEM format RSA keys. + @return < 0 on error +*/ +int32_t pkcs1ParsePrivFile(psPool_t *pool, const char *fileName, + const char *password, psRsaKey_t *key) +{ + unsigned char *DERout; + int32_t rc; + uint16_t DERlen; +#ifdef USE_PKCS8 + psPubKey_t pubkey; +#endif + + if ((rc = pkcs1DecodePrivFile(pool, fileName, password, &DERout, &DERlen)) + < PS_SUCCESS) { + return rc; + } + + if ((rc = psRsaParsePkcs1PrivKey(pool, DERout, DERlen, key)) < 0) { +#ifdef USE_PKCS8 + /* This logic works for processing PKCS#8 files because the above file + and bin decodes will always leave the unprocessed buffer intact and + the password protection is done in the internal ASN.1 encoding */ + if ((rc = pkcs8ParsePrivBin(pool, DERout, DERlen, (char*)password, + &pubkey)) < 0) { + psFree(DERout, pool); + return rc; + } + rc = psRsaCopyKey(key, &pubkey.key.rsa); + psClearPubKey(&pubkey); +#else + psFree(DERout, pool); + return rc; +#endif + } + + psFree(DERout, pool); + return rc; +} +#endif /* USE_RSA */ + +/******************************************************************************/ +/** + Return the DER stream from a private key PEM file. + + Memory info: + Caller must call psFree on DERout on function success +*/ +int32_t pkcs1DecodePrivFile(psPool_t *pool, const char *fileName, + const char *password, unsigned char **DERout, uint16_t *DERlen) +{ + unsigned char *keyBuf; + char *start, *end, *endTmp; + int32 keyBufLen, rc; + uint32 PEMlen = 0; +#ifdef USE_PKCS5 + psDes3_t dctx; + psAesCbc_t actx; + unsigned char passKey[32]; /* AES-256 max */ + unsigned char cipherIV[16]; /* AES-256 max */ + int32 tmp, encrypted = 0; + + static const char des3encryptHeader[] = "DEK-Info: DES-EDE3-CBC,"; + static const char aes128encryptHeader[] = "DEK-Info: AES-128-CBC,"; +#endif /* USE_PKCS5 */ + + if (fileName == NULL) { + psTraceCrypto("No fileName passed to pkcs1DecodePrivFile\n"); + return PS_ARG_FAIL; + } + if ((rc = psGetFileBuf(pool, fileName, &keyBuf, &keyBufLen)) < PS_SUCCESS) { + return rc; + } + start = end = NULL; + + /* Check header and encryption parameters. */ + if (((start = strstr((char*)keyBuf, "-----BEGIN")) != NULL) && + ((start = strstr((char*)keyBuf, "PRIVATE KEY-----")) != NULL) && + ((end = strstr(start, "-----END")) != NULL) && + ((endTmp = strstr(end, "PRIVATE KEY-----")) != NULL)) { + start += strlen("PRIVATE KEY-----"); + while (*start == '\x0d' || *start == '\x0a') { + start++; + } + PEMlen = (uint32)(end - start); + } else { + psTraceCrypto("File buffer does not look to be in PKCS#1 PEM format\n"); + psFree(keyBuf, pool); + return PS_PARSE_FAIL; + } + + if (strstr((char*)keyBuf, "Proc-Type:") && + strstr((char*)keyBuf, "4,ENCRYPTED")) { +#ifdef USE_PKCS5 + if (password == NULL) { + psTraceCrypto("No password given for encrypted private key file\n"); + psFree(keyBuf, pool); + return PS_ARG_FAIL; + } + if ((start = strstr((char*)keyBuf, des3encryptHeader)) != NULL) { + start += strlen(des3encryptHeader); + encrypted = 1; + /* we assume here that header points to at least 16 bytes of data */ + tmp = hexToBinary((unsigned char*)start, cipherIV, DES3_IVLEN); + } else if ((start = strstr((char*)keyBuf, aes128encryptHeader)) + != NULL) { + start += strlen(aes128encryptHeader); + encrypted = 2; + /* we assume here that header points to at least 32 bytes of data */ + tmp = hexToBinary((unsigned char*)start, cipherIV, 16); + } else { + psTraceCrypto("Unrecognized private key file encoding\n"); + psFree(keyBuf, pool); + return PS_PARSE_FAIL; + } + + if (tmp < 0) { + psTraceCrypto("Invalid private key file salt\n"); + psFree(keyBuf, pool); + return PS_FAILURE; + } + start += tmp; + pkcs5pbkdf1((unsigned char*)password, strlen(password), + cipherIV, 1, (unsigned char*)passKey); + PEMlen = (int32)(end - start); +#else /* !USE_PKCS5 */ + /* The private key is encrypted, but PKCS5 support has been turned off */ + psTraceCrypto("USE_PKCS5 must be enabled for key file password\n"); + psFree(keyBuf, pool); + return PS_UNSUPPORTED_FAIL; +#endif /* USE_PKCS5 */ + } + + /* Take the raw input and do a base64 decode */ + *DERout = psMalloc(pool, PEMlen); + if (*DERout == NULL) { + psFree(keyBuf, pool); + psError("Memory allocation error in pkcs1DecodePrivFile\n"); + return PS_MEM_FAIL; + } + *DERlen = PEMlen; + if ((rc = psBase64decode((unsigned char*)start, PEMlen, *DERout, + DERlen)) != 0) { + psTraceCrypto("Error base64 decode of private key\n"); + if (password) { + psTraceCrypto("Is it possible the password is incorrect?\n"); + } + psFree(*DERout, pool); + psFree(keyBuf, pool); + return rc; + } + psFree(keyBuf, pool); + +#ifdef USE_PKCS5 + if (encrypted == 1 && password) { + psDes3Init(&dctx, cipherIV, passKey); + psDes3Decrypt(&dctx, *DERout, *DERout, *DERlen); + memset_s(&dctx, sizeof(psDes3_t), 0x0, sizeof(psDes3_t)); + } + if (encrypted == 2 && password) { + /* AES 128 */ + psAesInitCBC(&actx, cipherIV, passKey, 16, PS_AES_DECRYPT); + psAesDecryptCBC(&actx, *DERout, *DERout, *DERlen); + memset_s(&actx, sizeof(psAesCbc_t), 0x0, sizeof(psAesCbc_t)); + } + /* SECURITY - zero out keys when finished */ + memset_s(passKey, sizeof(passKey), 0x0, sizeof(passKey)); + +#endif /* USE_PKCS5 */ + + return PS_SUCCESS; +} + +#endif /* MATRIX_USE_FILE_SYSTEM */ +#endif /* USE_PRIVATE_KEY_PARSING */ +/******************************************************************************/ + +/******************************************************************************/ +#ifdef USE_PKCS5 +/******************************************************************************/ +/* + Generate a key given a password and salt value. + PKCS#5 2.0 PBKDF1 key derivation format with MD5 and count == 1 per: + http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html + + This key is compatible with the algorithm used by OpenSSL to encrypt keys + generated with 'openssl genrsa'. If other encryption formats are used + (for example PBKDF2), or an iteration count != 1 is used, they are not + compatible with this simple implementation. OpenSSL provides many options + for converting key formats to the one used here. + + A 3DES key is 24 bytes long, to generate it with this algorithm, + we md5 hash the password and salt for the first 16 bytes. We then + hash these first 16 bytes with the password and salt again, generating + another 16 bytes. We take the first 16 bytes and 8 of the second 16 to + form the 24 byte key. + + salt is assumed to point to 8 bytes of data + key is assumed to point to 24 bytes of data + */ +void pkcs5pbkdf1(unsigned char *pass, uint32 passlen, unsigned char *salt, + int32 iter, unsigned char *key) +{ + psDigestContext_t md; + unsigned char md5[MD5_HASH_SIZE]; + + psAssert(iter == 1); + + psMd5Init(&md.md5); + psMd5Update(&md.md5, pass, passlen); + psMd5Update(&md.md5, salt, 8); + psMd5Final(&md.md5, md5); + memcpy(key, md5, MD5_HASH_SIZE); + + psMd5Init(&md.md5); + psMd5Update(&md.md5, md5, MD5_HASH_SIZE); + psMd5Update(&md.md5, pass, passlen); + psMd5Update(&md.md5, salt, 8); + psMd5Final(&md.md5, md5); + memcpy(key + MD5_HASH_SIZE, md5, 24 - MD5_HASH_SIZE); + + memset_s(md5, MD5_HASH_SIZE, 0x0, MD5_HASH_SIZE); + memset_s(&md, sizeof(psDigestContext_t), 0x0, sizeof(psDigestContext_t)); +} + +#if defined(USE_HMAC_SHA1) +/******************************************************************************/ +/* + Generate a key given a password, salt and iteration value. + PKCS#5 2.0 PBKDF2 key derivation format with HMAC-SHA per: + http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html + + Given a password, a salt, and an iteration count (rounds), generate a + key suitable for encrypting data with 3DES, AES, etc. + key should point to storage as large as kLen +*/ +void pkcs5pbkdf2(unsigned char *password, uint32 pLen, + unsigned char *salt, uint32 sLen, int32 rounds, + unsigned char *key, uint32 kLen) +{ + int32 itts; + uint32 blkno; + unsigned long stored, left, i; + unsigned char buf[2][SHA1_HASH_SIZE]; + psHmacSha1_t hmac; + + psAssert(password && salt && key && kLen); + + left = kLen; + blkno = 1; + stored = 0; + while (left != 0) { + /* process block number blkno */ + memset(buf[0], 0x0, SHA1_HASH_SIZE * 2); + + /* store current block number and increment for next pass */ + STORE32H(blkno, buf[1]); + ++blkno; + + /* get PRF(P, S||int(blkno)) */ + psHmacSha1Init(&hmac, password, pLen); + psHmacSha1Update(&hmac, salt, sLen); + psHmacSha1Update(&hmac, buf[1], 4); + psHmacSha1Final(&hmac, buf[0]); + + /* now compute repeated and XOR it in buf[1] */ + memcpy(buf[1], buf[0], SHA1_HASH_SIZE); + for (itts = 1; itts < rounds; ++itts) { + psHmacSha1Init(&hmac, password, pLen); + psHmacSha1Update(&hmac, buf[0], SHA1_HASH_SIZE); + psHmacSha1Final(&hmac, buf[0]); + for (i = 0; i < SHA1_HASH_SIZE; i++) { + buf[1][i] ^= buf[0][i]; + } + } + /* now emit upto x bytes of buf[1] to output */ + for (i = 0; i < SHA1_HASH_SIZE && left != 0; ++i) { + key[stored++] = buf[1][i]; + --left; + } + } + + memset_s(buf, SHA1_HASH_SIZE * 2, 0x0, SHA1_HASH_SIZE * 2); + memset_s(&hmac, sizeof(psHmacSha1_t), 0x0, sizeof(psHmacSha1_t)); +} +#endif /* USE_HMAC && USE_SHA1 */ +#endif /* USE_PKCS5 */ + +#if defined(USE_DH) && defined(MATRIX_USE_FILE_SYSTEM) +/******************************************************************************/ +/** + Extract Diffie-Hellman parameters from a PEM encoded file. + This API decodes the PEM format and passes the ASN.1 encoded parameters + to pkcs3ParseDhParamBin() to parse the ASN.1. + + @param pool Memory pool + @param[in] fileName File name of PEM encoded ASN.1 to load. + @param[in,out] params Allocated parameter structure to receive parsed + params. + @return < on error. +*/ +int32_t pkcs3ParseDhParamFile(psPool_t *pool, const char *fileName, psDhParams_t *params) +{ + unsigned char *pemOut, *p; + char *dhFileBuf, *start, *end; + int32_t rc; + uint16_t baseLen, pemOutLen; + int32_t dhFileLen; + + if (!params || !fileName) { + return PS_ARG_FAIL; + } + /* This is part of key assignment at startup. Base pool is fine here */ + if ((rc = psGetFileBuf(pool, fileName, + (unsigned char **)&dhFileBuf, &dhFileLen)) < 0) { + return rc; + } + /* Set end to end of file buffer */ + end = dhFileBuf + dhFileLen; + /* Set start to start of token */ + if ((start = strstr(dhFileBuf, "-----BEGIN DH PARAMETERS-----")) == NULL) { + psTraceStrCrypto("Error parsing dh file buffer header: %s\n", fileName); + psFree(dhFileBuf, pool); + return PS_PARSE_FAIL; + } + /* Move start to start of PEM data, skipping CR/LF */ + start += 29; /* strlen("-----BEGIN DH PARAMETERS-----"); */ + while (start < end && (*start == '\x0d' || *start == '\x0a')) { + start++; + } + /* Set end to end token */ + if ((end = strstr(start, "-----END DH PARAMETERS-----")) == NULL) { + psTraceStrCrypto("Error parsing dh file buffer footer: %s\n", fileName); + psFree(dhFileBuf, pool); + return PS_PARSE_FAIL; + } + baseLen = (uint16_t)(end - start); + + p = NULL; + p = pemOut = psMalloc(pool, baseLen); + if (p == NULL) { + psError("Memory allocation error in pkcs3ParseDhParamFile\n"); + return PS_MEM_FAIL; + } + + pemOutLen = baseLen; + if (psBase64decode((unsigned char *)start, baseLen, p, &pemOutLen) != 0) { + psFree(dhFileBuf, pool); + psFree(pemOut, pool); + return PS_PARSE_FAIL; + } + psFree(dhFileBuf, pool); + + if ((rc = pkcs3ParseDhParamBin(pool, p, pemOutLen, params)) < 0) { + psFree(pemOut, pool); + return rc; + } + psFree(pemOut, pool); + return 0; +} +#endif /* USE_DH && MATRIX_USE_FILE_SYSTEM */ + +/******************************************************************************/ + +/******************************************************************************/ +#if defined(USE_PKCS1_OAEP) || defined(USE_PKCS1_PSS) +/* + The reason we weren't able to create a callback structure for the hash + routines was because of the Mac relocation build errors related to + the register usage when assembly code is used in pstm +*/ +/******************************************************************************/ +/* + Perform PKCS #1 Mask Generation Function (internal) + pool Memory pool + seed The seed for MGF1 + seedlen The length of the seed + hash_idx The index of the hash desired + mask [out] The destination + masklen The length of the mask desired + return 0 if successful +*/ +static int32 pkcs_1_mgf1(psPool_t *pool, const unsigned char *seed, + unsigned long seedlen, int32 hash_idx, unsigned char *mask, + unsigned long masklen) +{ + unsigned long hLen, x; + uint32 counter; + psDigestContext_t md; + unsigned char *buf; + + if ((seed == NULL) || (mask == NULL)) { + return -1; + } + hLen = 0; +/* + Get hash output size. Index has already been verified by caller so + don't need 'else' error cases +*/ + if (hash_idx == PKCS1_SHA1_ID) { + hLen = SHA1_HASH_SIZE; + } else if (hash_idx == PKCS1_MD5_ID) { + hLen = MD5_HASH_SIZE; +#ifdef USE_SHA256 + } else if (hash_idx == PKCS1_SHA256_ID) { + hLen = SHA256_HASH_SIZE; +#endif +#ifdef USE_SHA384 + } else if (hash_idx == PKCS1_SHA384_ID) { + hLen = SHA384_HASH_SIZE; +#endif +#ifdef USE_SHA512 + } else if (hash_idx == PKCS1_SHA512_ID) { + hLen = SHA512_HASH_SIZE; +#endif + } else { + return PS_UNSUPPORTED_FAIL; + } + + buf = psMalloc(pool, hLen); + if (buf == NULL) { + psTraceCrypto("Memory allocation error in MGF\n"); + return -1; + } +/* + Start counter +*/ + counter = 0; + + while (masklen > 0) { + /* handle counter */ + STORE32H(counter, buf); + ++counter; + +/* + Get hash of seed || counter +*/ + if (hash_idx == PKCS1_SHA1_ID) { + psSha1Init(&md.sha1); + psSha1Update(&md.sha1, seed, seedlen); + psSha1Update(&md.sha1, buf, 4); + psSha1Final(&md.sha1, buf); + } else if (hash_idx == PKCS1_MD5_ID) { + psMd5Init(&md.md5); + psMd5Update(&md.md5, seed, seedlen); + psMd5Update(&md.md5, buf, 4); + psMd5Final(&md.md5, buf); +#ifdef USE_SHA256 + } else if (hash_idx == PKCS1_SHA256_ID) { + psSha256Init(&md.sha256); + psSha256Update(&md.sha256, seed, seedlen); + psSha256Update(&md.sha256, buf, 4); + psSha256Final(&md.sha256, buf); +#endif +#ifdef USE_SHA384 + } else if (hash_idx == PKCS1_SHA384_ID) { + psSha384Init(&md.sha384); + psSha384Update(&md.sha384, seed, seedlen); + psSha384Update(&md.sha384, buf, 4); + psSha384Final(&md.sha384, buf); +#endif +#ifdef USE_SHA512 + } else if (hash_idx == PKCS1_SHA512_ID) { + psSha512Init(&md.sha512); + psSha512Update(&md.sha512, seed, seedlen); + psSha512Update(&md.sha512, buf, 4); + psSha512Final(&md.sha512, buf); +#endif + } else { + return PS_UNSUPPORTED_FAIL; + } + + /* store it */ + for (x = 0; x < hLen && masklen > 0; x++, masklen--) { + *mask++ = buf[x]; + } + } + + psFree(buf, pool); + return PS_SUCCESS; +} +#endif /* defined(USE_PKCS1_OAEP) || defined(USE_PKCS1_PSS) */ + + +#ifdef USE_PKCS1_OAEP +/******************************************************************************/ +/* + PKCS #1 v2.00 OAEP encode + pool Memory pool + msg The data to encode + msglen The length of the data to encode (octets) + lparam A session or system parameter (can be NULL) + lparamlen The length of the lparam data + seed Reserved for vector testing. Should be NULL + seedLen Reserved for vector testing. Should be 0 + modulus_bitlen The bit length of the RSA modulus + hash_idx The index of the hash desired (see psHashList table above) + out [out] The destination for the encoded data + outlen [in/out] The max size and resulting size of the encoded data + + return 0 if successful, -1 on failure +*/ +int32 pkcs1OaepEncode(psPool_t *pool, const unsigned char *msg, uint32 msglen, + const unsigned char *lparam, uint32 lparamlen, + unsigned char *seed, uint32 seedLen, + uint32 modulus_bitlen, int32 hash_idx, + unsigned char *out, uint16_t *outlen) +{ + unsigned char *DB, *lseed, *mask; + uint32 hLen, x, y, modulus_len; + int32 err; + psDigestContext_t md; + + if ((msg == NULL) || (out == NULL) || (outlen == NULL) || (hash_idx < 0)) { + psTraceStrCrypto("Bad parameter to OAEP encode\n", NULL); + return PS_ARG_FAIL; + } +/* + Verify hash routines +*/ + if (hash_idx == PKCS1_SHA1_ID) { + hLen = SHA1_HASH_SIZE; + } else if (hash_idx == PKCS1_MD5_ID) { + hLen = MD5_HASH_SIZE; + } else { + psTraceStrCrypto("Bad hash index to OAEP encode\n", NULL); + return PS_ARG_FAIL; + } +/* + Seed should be generated randomly below but this helps for test vectors +*/ + if (seed != NULL && seedLen != hLen) { + psTraceIntCrypto("Seed must be length of %d\n", hLen); + return PS_ARG_FAIL; + } + + modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); + +/* + Test message size +*/ + if ((2*hLen >= (modulus_len - 2)) || (msglen > (modulus_len - 2*hLen - 2))) { + psTraceStrCrypto("Bad message size to OAEP encode\n", NULL); + return PS_LIMIT_FAIL; + } + +/* + Allocate ram for DB/mask/salt of size modulus_len +*/ + lseed = NULL; + DB = psMalloc(pool, modulus_len); + mask = psMalloc(pool, modulus_len); + if (DB == NULL || mask == NULL) { + if (DB != NULL) { + psFree(DB, pool); + } + if (mask != NULL) { + psFree(mask, pool); + } + psTraceCrypto("Memory allocation error in OAEP encode\n"); + return PS_MEM_FAIL; + } + +/* + Create lhash for DB block format: + + DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes +*/ + x = modulus_len; + + if (lparam != NULL) { + if (hash_idx == PKCS1_SHA1_ID) { + psSha1Init(&md.sha1); + psSha1Update(&md.sha1, lparam, lparamlen); + psSha1Final(&md.sha1, DB); + } else { + psMd5Init(&md.md5); + psMd5Update(&md.md5, lparam, lparamlen); + psMd5Final(&md.md5, DB); + } + } else { + /* can't pass hash a NULL so use DB with zero length */ + if (hash_idx == PKCS1_SHA1_ID) { + psSha1Init(&md.sha1); + psSha1Update(&md.sha1, DB, 0); + psSha1Final(&md.sha1, DB); + } else { + psMd5Init(&md.md5); + psMd5Update(&md.md5, DB, 0); + psMd5Final(&md.md5, DB); + } + } + +/* + Append PS then 0x01 (to lhash) +*/ + x = hLen; + y = modulus_len - msglen - 2*hLen - 2; + memset(DB+x, 0, y); + x += y; + + DB[x++] = 0x01; + +/* + Message (length = msglen) +*/ + memcpy(DB+x, msg, msglen); + x += msglen; + +/* + Use matrixCryptoGetPrngData to choose a random seed (if not provided) +*/ + if (seed != NULL) { + lseed = seed; + } else { + lseed = psMalloc(pool, hLen); + if (lseed == NULL) { + err = PS_MEM_FAIL; + goto LBL_ERR; + } + if (matrixCryptoGetPrngData(lseed, hLen, NULL) != (int32)hLen) { + psTraceCrypto("matrixCryptoGetPrngData fail in OAEP encode\n"); + err = PS_PLATFORM_FAIL; + goto LBL_ERR; + } + } + +/* + Compute MGF1 of seed (k - hlen - 1) +*/ + if ((err = pkcs_1_mgf1(pool, lseed, hLen, hash_idx, mask, + modulus_len - hLen - 1)) != PS_SUCCESS) { + psTraceStrCrypto("MGF for seed failed in OAEP encode\n", NULL); + goto LBL_ERR; + } + +/* + xor against DB +*/ + for (y = 0; y < (modulus_len - hLen - 1); y++) { + DB[y] ^= mask[y]; + } + +/* + Compute MGF1 of maskedDB (hLen) +*/ + if ((err = pkcs_1_mgf1(pool, DB, modulus_len - hLen - 1, hash_idx, + mask, hLen)) != PS_SUCCESS) { + psTraceStrCrypto("MGF for DB failed in OAEP encode\n", NULL); + goto LBL_ERR; + } + +/* + XOR against seed +*/ + for (y = 0; y < hLen; y++) { + lseed[y] ^= mask[y]; + } + +/* + Create string of length modulus_len +*/ + if (*outlen < modulus_len) { + psTraceStrCrypto("Bad outlen in OAEP encode\n", NULL); + err = -1; + goto LBL_ERR; + } + +/* + Start output which is 0x00 || maskedSeed || maskedDB +*/ + x = 0; + out[x++] = 0x00; + memcpy(out+x, lseed, hLen); + x += hLen; + memcpy(out+x, DB, modulus_len - hLen - 1); + x += modulus_len - hLen - 1; + + *outlen = x; + + err = PS_SUCCESS; + +LBL_ERR: + if (seed == NULL) { + psFree(lseed, pool); + } + psFree(mask, pool); + psFree(DB, pool); + + return err; +} + +/******************************************************************************/ +/* + PKCS #1 v2.00 OAEP decode + pool Memory pool + msg The encoded data to decode + msglen The length of the encoded data (octets) + lparam The session or system data (can be NULL) + lparamlen The length of the lparam + modulus_bitlen The bit length of the RSA modulus + hash_idx The index of the hash desired + out [out] Destination of decoding + outlen [in/out] The max size and resulting size of the decoding + + return 0 if successful +*/ +int32 pkcs1OaepDecode(psPool_t *pool, const unsigned char *msg, uint32 msglen, + const unsigned char *lparam, uint32 lparamlen, + uint32 modulus_bitlen, int32 hash_idx, + unsigned char *out, uint16_t *outlen) +{ + unsigned char *DB, *seed, *mask; + uint32 hLen, x, y, modulus_len; + int32 err; + psDigestContext_t md; + + if ((msg == NULL) || (out == NULL) || (outlen == NULL) || (hash_idx < 0)) { + psTraceCrypto("Bad parameter to OAEP decode\n"); + return PS_ARG_FAIL; + } +/* + Verify hash routines +*/ + if (hash_idx == PKCS1_SHA1_ID) { + hLen = SHA1_HASH_SIZE; + } else if (hash_idx == PKCS1_MD5_ID) { + hLen = MD5_HASH_SIZE; + } else { + psTraceStrCrypto("Bad hash index to OAEP decode\n", NULL); + return PS_ARG_FAIL; + } + + modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); + +/* + Test hash/message size +*/ + if ((2*hLen >= (modulus_len - 2)) || (msglen != modulus_len)) { + psTraceCrypto("Message/Modulus length mismatch in OAEP decode\n"); + return PS_LIMIT_FAIL; + } + +/* + Allocate ram for DB/mask/salt of size modulus_len +*/ + DB = psMalloc(pool, modulus_len); + mask = psMalloc(pool, modulus_len); + seed = psMalloc(pool, hLen); + if (DB == NULL || mask == NULL || seed == NULL) { + if (DB != NULL) { + psFree(DB, pool); + } + if (mask != NULL) { + psFree(mask, pool); + } + if (seed != NULL) { + psFree(seed, pool); + } + psTraceCrypto("Memory allocation error in OAEP decode\n"); + return -1; + } + +/* + It's now in the form + + 0x00 || maskedseed || maskedDB + + 1 || hLen || modulus_len - hLen - 1 +*/ + if (msg[0] != 0x00) { + psTraceCrypto("Message format error in OAEP decode\n"); + err = PS_FAILURE; + goto LBL_ERR; + } + +/* + Now read the masked seed +*/ + x = 1; + memcpy(seed, msg + x, hLen); + x += hLen; + +/* + Now read the masked DB +*/ + memcpy(DB, msg + x, modulus_len - hLen - 1); + x += modulus_len - hLen - 1; + +/* + Compute MGF1 of maskedDB (hLen) +*/ + if ((err = pkcs_1_mgf1(pool, DB, modulus_len - hLen - 1, hash_idx, + mask, hLen)) != PS_SUCCESS) { + psTraceCrypto("MGF for DB failed in OAEP decode\n"); + goto LBL_ERR; + } + +/* + XOR against seed +*/ + for (y = 0; y < hLen; y++) { + seed[y] ^= mask[y]; + } + +/* + Compute MGF1 of seed (k - hlen - 1) +*/ + if ((err = pkcs_1_mgf1(pool, seed, hLen, hash_idx, mask, + modulus_len - hLen - 1)) != PS_SUCCESS) { + psTraceCrypto("MGF for seed failed in OAEP decode\n"); + goto LBL_ERR; + } + +/* + xor against DB +*/ + for (y = 0; y < (modulus_len - hLen - 1); y++) { + DB[y] ^= mask[y]; + } + +/* + compute lhash and store it in seed [reuse temps!] + + DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes +*/ + x = modulus_len; + + if (lparam != NULL) { + if (hash_idx == PKCS1_SHA1_ID) { + psSha1Init(&md.sha1); + psSha1Update(&md.sha1, lparam, lparamlen); + psSha1Final(&md.sha1, seed); + } else { + psMd5Init(&md.md5); + psMd5Update(&md.md5, lparam, lparamlen); + psMd5Final(&md.md5, seed); + } + if (err < 0) { + psTraceCrypto("Hash error in OAEP decode\n"); + goto LBL_ERR; + } + } else { + /* can't pass hash routine a NULL so use DB with zero length */ + if (hash_idx == PKCS1_SHA1_ID) { + psSha1Init(&md.sha1); + psSha1Update(&md.sha1, DB, 0); + psSha1Final(&md.sha1, seed); + } else { + psMd5Init(&md.md5); + psMd5Update(&md.md5, DB, 0); + psMd5Final(&md.md5, seed); + } + if (err < 0) { + psTraceCrypto("Zero hash error in OAEP decode\n"); + goto LBL_ERR; + } + } + +/* + Compare the lhash'es +*/ + if (memcmp(seed, DB, hLen) != 0) { + psTraceCrypto("Seed/DB mismatch in OAEP decode\n"); + err = -1; + goto LBL_ERR; + } + +/* + Now zeroes before a 0x01 +*/ + for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++) { + /* step... */ + } + +/* + Error out if wasn't 0x01 +*/ + if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) { + psTraceCrypto("DB format error in OAEP decode\n"); + err = -1; + goto LBL_ERR; + } + +/* + Rest is the message (and skip 0x01) +*/ + if ((modulus_len - hLen - 1) - ++x > *outlen) { + psTraceCrypto("Bad outlen in OAEP decode\n"); + err = -1; + goto LBL_ERR; + } + +/* + Copy message +*/ + *outlen = (modulus_len - hLen - 1) - x; + memcpy(out, DB + x, modulus_len - hLen - 1 - x); + x += modulus_len - hLen - 1; + + err = PS_SUCCESS; +LBL_ERR: + + psFree(seed, pool); + psFree(mask, pool); + psFree(DB, pool); + + return err; +} +#endif /* USE_PKCS1_OAEP */ +/******************************************************************************/ + +#ifdef USE_PKCS1_PSS +/******************************************************************************/ +/* + PKCS #1 v2.00 Signature Encoding + @param msghash The hash to encode + @param msghashlen The length of the hash (octets) + @param saltlen The length of the salt desired (octets) + @param hash_idx The index of the hash desired + @param modulus_bitlen The bit length of the RSA modulus + @param out [out] The destination of the encoding + @param outlen [in/out] The max size and resulting size of the encoded data + @return CRYPT_OK if successful +*/ +int32 pkcs1PssEncode(psPool_t *pool, const unsigned char *msghash, + uint32 msghashlen, unsigned char* tsalt, uint32 saltlen, + int32 hash_idx, uint32 modulus_bitlen, unsigned char *out, + uint16_t *outlen) +{ + unsigned char *DB, *mask, *salt, *hash; + uint32 x, y, hLen, modulus_len; + int32 err; + psDigestContext_t md; + + if ((msghash == NULL) || (out == NULL) || (outlen == NULL)) { + psTraceCrypto("Bad parameter to PSS encode\n"); + return PS_ARG_FAIL; + } + + if (hash_idx == PKCS1_SHA1_ID) { + hLen = SHA1_HASH_SIZE; + } else if (hash_idx == PKCS1_MD5_ID) { + hLen = MD5_HASH_SIZE; +#ifdef USE_SHA256 + } else if (hash_idx == PKCS1_SHA256_ID) { + hLen = SHA256_HASH_SIZE; +#endif + } else { + psTraceStrCrypto("Bad hash index to PSS encode\n", NULL); + return PS_ARG_FAIL; + } + + modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); + + /* check sizes */ + if ((saltlen > modulus_len) || (modulus_len < hLen + saltlen + 2)) { + psTraceCrypto("Bad saltlen or modulus len to PSS encode\n"); + return PS_ARG_FAIL; + } + + /* allocate ram for DB/mask/salt/hash of size modulus_len */ + err = PS_MEM_FAIL; + if ((DB = psMalloc(pool, modulus_len)) == NULL) { + return err; + } + memset(DB, 0x0, modulus_len); + if ((mask = psMalloc(pool, modulus_len)) == NULL) { + goto LBL_DB; + } + memset(mask, 0x0, modulus_len); + if ((salt = psMalloc(pool, modulus_len)) == NULL) { + goto LBL_MASK; + } + memset(salt, 0x0, modulus_len); + if ((hash = psMalloc(pool, modulus_len)) == NULL) { + goto LBL_SALT; + } + memset(hash, 0x0, modulus_len); + + /* generate random salt */ + if (saltlen > 0) { + if (tsalt != NULL) { + memcpy(salt, tsalt, saltlen); + } else { + if (matrixCryptoGetPrngData(salt, saltlen, NULL) != (int32)saltlen){ + err = PS_PLATFORM_FAIL; + goto LBL_ERR; + } + } + } + + /* M = (eight) 0x00 || msghash || salt, hash = H(M) */ + if (hash_idx == PKCS1_SHA1_ID) { + psSha1Init(&md.sha1); + psSha1Update(&md.sha1, DB, 8); /* 8 0's */ + psSha1Update(&md.sha1, msghash, msghashlen); + psSha1Update(&md.sha1, salt, saltlen); + psSha1Final(&md.sha1, hash); + } else if (hash_idx == PKCS1_MD5_ID) { + psMd5Init(&md.md5); + psMd5Update(&md.md5, DB, 8); /* 8 0's */ + psMd5Update(&md.md5, msghash, msghashlen); + psMd5Update(&md.md5, salt, saltlen); + psMd5Final(&md.md5, hash); + } +#ifdef USE_SHA256 + if (hash_idx == PKCS1_SHA256_ID) { + psSha256Init(&md.sha256); + psSha256Update(&md.sha256, DB, 8); /* 8 0's */ + psSha256Update(&md.sha256, msghash, msghashlen); + psSha256Update(&md.sha256, salt, saltlen); + psSha256Final(&md.sha256, hash); + } +#endif + + /* generate DB = PS || 0x01 || salt + PS == modulus_len - saltlen - hLen - 2 zero bytes */ + x = 0; + memset(DB + x, 0, modulus_len - saltlen - hLen - 2); + x += modulus_len - saltlen - hLen - 2; + DB[x++] = 0x01; + memcpy(DB + x, salt, saltlen); + x += saltlen; + + /* generate mask of length modulus_len - hLen - 1 from hash */ + if ((err = pkcs_1_mgf1(pool, hash, hLen, hash_idx, mask, + modulus_len - hLen - 1)) != PS_SUCCESS) { + goto LBL_ERR; + } + + /* xor against DB */ + for (y = 0; y < (modulus_len - hLen - 1); y++) { + DB[y] ^= mask[y]; + } + + /* output is DB || hash || 0xBC */ + if (*outlen < modulus_len) { + *outlen = modulus_len; + err = PS_LIMIT_FAIL; + goto LBL_ERR; + } + + /* DB len = modulus_len - hLen - 1 */ + y = 0; + memcpy(out + y, DB, modulus_len - hLen - 1); + y += modulus_len - hLen - 1; + + /* hash */ + memcpy(out + y, hash, hLen); + y += hLen; + + /* 0xBC */ + out[y] = 0xBC; + + /* now clear the 8*modulus_len - modulus_bitlen most significant bits */ + out[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)); + + /* store output size */ + *outlen = modulus_len; + err = PS_SUCCESS; + +LBL_ERR: psFree(hash, pool); +LBL_SALT: psFree(salt, pool); +LBL_MASK: psFree(mask, pool); +LBL_DB: psFree(DB, pool); + + return err; +} + +/******************************************************************************/ +/** + PKCS #1 v2.00 PSS decode + @param msghash The hash to verify + @param msghashlen The length of the hash (octets) + @param sig The signature data (encoded data) + @param siglen The length of the signature data (octets) + @param saltlen The length of the salt used (octets) + @param hash_idx The index of the hash desired + @param modulus_bitlen The bit length of the RSA modulus + @param res [out] The result of the comparison, 1==valid, 0==invalid + +*/ +int32 pkcs1PssDecode(psPool_t *pool, const unsigned char *msghash, + uint32 msghashlen, const unsigned char *sig, uint32 siglen, + uint32 saltlen, int32 hash_idx, uint32 modulus_bitlen, int32 *res) +{ + unsigned char *DB, *mask, *salt, *hash; + uint32 x, y, hLen, modulus_len; + int32 err; + psDigestContext_t md; + + if ((msghash == NULL) || (res == NULL)) { + psTraceCrypto("Bad parameters to pkcs1PssDecode\n"); + return PS_ARG_FAIL; + } + + /* default to invalid */ + *res = 0; + + if (hash_idx == PKCS1_SHA1_ID) { + hLen = SHA1_HASH_SIZE; + } else if (hash_idx == PKCS1_MD5_ID) { + hLen = MD5_HASH_SIZE; +#ifdef USE_SHA256 + } else if (hash_idx == PKCS1_SHA256_ID) { + hLen = SHA256_HASH_SIZE; +#endif +#ifdef USE_SHA384 + } else if (hash_idx == PKCS1_SHA384_ID) { + hLen = SHA384_HASH_SIZE; +#endif +#ifdef USE_SHA512 + } else if (hash_idx == PKCS1_SHA512_ID) { + hLen = SHA512_HASH_SIZE; +#endif + } else { + psTraceStrCrypto("Bad hash index to PSS decode\n", NULL); + return PS_ARG_FAIL; + } + + modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); + + /* check sizes */ + if ((saltlen > modulus_len) || + (modulus_len < hLen + saltlen + 2) || (siglen != modulus_len)) { + psTraceCrypto("Bad saltlen or modulus len to PSS decode\n"); + return PS_ARG_FAIL; + } + + /* allocate ram for DB/mask/salt/hash of size modulus_len */ + err = PS_MEM_FAIL; + if ((DB = psMalloc(pool, modulus_len)) == NULL) { + return err; + } + memset(DB, 0x0, modulus_len); + if ((mask = psMalloc(pool, modulus_len)) == NULL) { + goto LBL_DB; + } + memset(mask, 0x0, modulus_len); + if ((salt = psMalloc(pool, modulus_len)) == NULL) { + goto LBL_MASK; + } + memset(salt, 0x0, modulus_len); + if ((hash = psMalloc(pool, modulus_len)) == NULL) { + goto LBL_SALT; + } + memset(hash, 0x0, modulus_len); + + /* ensure the 0xBC byte */ + if (sig[siglen-1] != 0xBC) { + err = PS_FAILURE; + goto LBL_ERR; + } + + /* copy out the DB */ + x = 0; + memcpy(DB, sig + x, modulus_len - hLen - 1); + x += modulus_len - hLen - 1; + + /* copy out the hash */ + memcpy(hash, sig + x, hLen); + x += hLen; + + /* check the MSB */ + if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)))) != 0) { + err = PS_FAILURE; + goto LBL_ERR; + } + + /* generate mask of length modulus_len - hLen - 1 from hash */ + if ((err = pkcs_1_mgf1(pool, hash, hLen, hash_idx, mask, + modulus_len - hLen - 1)) != PS_SUCCESS) { + goto LBL_ERR; + } + + /* xor against DB */ + for (y = 0; y < (modulus_len - hLen - 1); y++) { + DB[y] ^= mask[y]; + } + + /* now clear the first byte [make sure smaller than modulus] */ + DB[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)); + + /* DB = PS || 0x01 || salt, + PS == modulus_len - saltlen - hLen - 2 zero bytes */ + + /* check for zeroes and 0x01 */ + for (x = 0; x < modulus_len - saltlen - hLen - 2; x++) { + if (DB[x] != 0x00) { + err = PS_FAILURE; + goto LBL_ERR; + } + } + + /* check for the 0x01 */ + if (DB[x++] != 0x01) { + err = PS_FAILURE; + goto LBL_ERR; + } + + /* M = (eight) 0x00 || msghash || salt, mask = H(M) */ + if (hash_idx == PKCS1_SHA1_ID) { + psSha1Init(&md.sha1); + memset(mask, 0x0, 8); + psSha1Update(&md.sha1, mask, 8); + psSha1Update(&md.sha1, msghash, msghashlen); + psSha1Update(&md.sha1, DB+x, saltlen); + psSha1Final(&md.sha1, mask); + } else if (hash_idx == PKCS1_MD5_ID) { + psMd5Init(&md.md5); + memset(mask, 0x0, 8); + psMd5Update(&md.md5, mask, 8); + psMd5Update(&md.md5, msghash, msghashlen); + psMd5Update(&md.md5, DB+x, saltlen); + psMd5Final(&md.md5, mask); + } +#ifdef USE_SHA256 + if (hash_idx == PKCS1_SHA256_ID) { + psSha256Init(&md.sha256); + memset(mask, 0x0, 8); + psSha256Update(&md.sha256, mask, 8); + psSha256Update(&md.sha256, msghash, msghashlen); + psSha256Update(&md.sha256, DB+x, saltlen); + psSha256Final(&md.sha256, mask); + } +#endif +#ifdef USE_SHA384 + if (hash_idx == PKCS1_SHA384_ID) { + psSha384Init(&md.sha384); + memset(mask, 0x0, 8); + psSha384Update(&md.sha384, mask, 8); + psSha384Update(&md.sha384, msghash, msghashlen); + psSha384Update(&md.sha384, DB+x, saltlen); + psSha384Final(&md.sha384, mask); + } +#endif +#ifdef USE_SHA512 + if (hash_idx == PKCS1_SHA512_ID) { + psSha512Init(&md.sha512); + memset(mask, 0x0, 8); + psSha512Update(&md.sha512, mask, 8); + psSha512Update(&md.sha512, msghash, msghashlen); + psSha512Update(&md.sha512, DB+x, saltlen); + psSha512Final(&md.sha512, mask); + } +#endif + + /* mask == hash means valid signature */ + if (memcmp(mask, hash, hLen) == 0) { + *res = 1; + } + + err = PS_SUCCESS; + +LBL_ERR: + psFree(hash, pool); +LBL_SALT: + psFree(salt, pool); +LBL_MASK: + psFree(mask, pool); +LBL_DB: + psFree(DB, pool); + memset_s(&md, sizeof(psDigestContext_t), 0x0, sizeof(psDigestContext_t)); + + return err; +} +#endif /* USE_PKCS1_PSS */ + +/******************************************************************************/ + + +/******************************************************************************/ + diff --git a/crypto/keyformat/x509.c b/crypto/keyformat/x509.c new file mode 100644 index 0000000..76b30e8 --- /dev/null +++ b/crypto/keyformat/x509.c @@ -0,0 +1,4423 @@ +/** + * @file x509.c + * @version $Format:%h%d$ + * + * X.509 Parser. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_X509 + +/******************************************************************************/ + +#ifdef POSIX +#include +#endif + +/******************************************************************************/ + +#define MAX_CERTS_PER_FILE 16 + +#ifdef USE_CERT_PARSE +/* + Certificate extensions +*/ +#define IMPLICIT_ISSUER_ID 1 +#define IMPLICIT_SUBJECT_ID 2 +#define EXPLICIT_EXTENSION 3 + +/* + Distinguished Name attributes +*/ +#define ATTRIB_COUNTRY_NAME 6 +#define ATTRIB_LOCALITY 7 +#define ATTRIB_ORGANIZATION 10 +#define ATTRIB_ORG_UNIT 11 +#define ATTRIB_DN_QUALIFIER 46 +#define ATTRIB_STATE_PROVINCE 8 +#define ATTRIB_COMMON_NAME 3 + +/** Enumerate X.509 milestones for issuedBefore() api */ +typedef enum { + RFC_6818, /* January 2013 X.509 Updates Below */ + RFC_5280, /* May 2008 X.509 Obsoletes Below */ + RFC_3280, /* April 2002 X.509 Obsoletes Below */ + RFC_2459, /* January 1999 X.509 First RFC */ + X509_V3, /* 1996 X.509v3 Pre-RFC */ + X509_V2, /* 1993 X.509v2 Pre-RFC */ + X509_V1, /* 1988 X.509v1 Pre-RFC */ +} rfc_e; + +#define USE_OID_TRACE + +#ifdef USE_OID_TRACE +#define OID_LIST(A, B) { { A, B }, #B, oid_##B } +#else +#define OID_LIST(A, B) { { A, B }, oid_##B } +#endif +static const struct { + uint16_t oid[MAX_OID_LEN]; +#ifdef USE_OID_TRACE + char name[32]; +#endif + int id; +} oid_list[] = { + /* X.509 certificate extensions */ + OID_LIST(id_ce, id_ce_authorityKeyIdentifier), + OID_LIST(id_ce, id_ce_subjectKeyIdentifier), + OID_LIST(id_ce, id_ce_keyUsage), + OID_LIST(id_ce, id_ce_certificatePolicies), + OID_LIST(id_ce, id_ce_policyMappings), + OID_LIST(id_ce, id_ce_subjectAltName), + OID_LIST(id_ce, id_ce_issuerAltName), + OID_LIST(id_ce, id_ce_subjectDirectoryAttributes), + OID_LIST(id_ce, id_ce_basicConstraints), + OID_LIST(id_ce, id_ce_nameConstraints), + OID_LIST(id_ce, id_ce_policyConstraints), + OID_LIST(id_ce, id_ce_extKeyUsage), + OID_LIST(id_ce, id_ce_cRLDistributionPoints), + OID_LIST(id_ce, id_ce_inhibitAnyPolicy), + OID_LIST(id_ce, id_ce_freshestCRL), + OID_LIST(id_pe, id_pe_authorityInfoAccess), + OID_LIST(id_pe, id_pe_subjectInfoAccess), + /* Extended Key Usage */ + OID_LIST(id_ce_eku, id_ce_eku_anyExtendedKeyUsage), + OID_LIST(id_kp, id_kp_serverAuth), + OID_LIST(id_kp, id_kp_clientAuth), + OID_LIST(id_kp, id_kp_codeSigning), + OID_LIST(id_kp, id_kp_emailProtection), + OID_LIST(id_kp, id_kp_timeStamping), + OID_LIST(id_kp, id_kp_OCSPSigning), + + /* List terminator */ + OID_LIST(0, 0), +}; + +/* + Hybrid ASN.1/X.509 cert parsing helpers +*/ +static int32_t getExplicitVersion(const unsigned char **pp, uint16_t len, + int32_t expVal, int32_t *val); +static int32_t getTimeValidity(psPool_t *pool, const unsigned char **pp, + uint16_t len, + int32_t *notBeforeTimeType, int32_t *notAfterTimeType, + char **notBefore, char **notAfter); +static int32_t getImplicitBitString(psPool_t *pool, const unsigned char **pp, + uint16_t len, int32_t impVal, unsigned char **bitString, + uint16_t *bitLen); +static int32_t validateDateRange(psX509Cert_t *cert); +static int32_t issuedBefore(rfc_e rfc, const psX509Cert_t *cert); + +#ifdef USE_RSA +static int32_t x509ConfirmSignature(const unsigned char *sigHash, + const unsigned char *sigOut, uint16_t sigLen); +#endif + +#ifdef USE_CRL +static void x509FreeRevoked(x509revoked_t **revoked); +#endif + +#endif /* USE_CERT_PARSE */ + +/******************************************************************************/ +#ifdef MATRIX_USE_FILE_SYSTEM +/******************************************************************************/ + +static int32_t pemCertFileBufToX509(psPool_t *pool, const unsigned char *fileBuf, + uint16_t fileBufLen, psList_t **x509certList); + +/******************************************************************************/ +/* + Open a PEM X.509 certificate file and parse it + + Memory info: + Caller must free outcert with psX509FreeCert on function success + Caller does not have to free outcert on function failure +*/ +int32 psX509ParseCertFile(psPool_t *pool, char *fileName, + psX509Cert_t **outcert, int32 flags) +{ + int32 fileBufLen, err; + unsigned char *fileBuf; + psList_t *fileList, *currentFile, *x509list, *frontX509; + psX509Cert_t *currentCert, *firstCert, *prevCert; + + *outcert = NULL; +/* + First test to see if there are multiple files being passed in. + Looking for a semi-colon delimiter +*/ + if ((err = psParseList(pool, fileName, ';', &fileList)) < 0) { + return err; + } + currentFile = fileList; + firstCert = prevCert = NULL; + + /* Recurse each individual file */ + while (currentFile) { + if ((err = psGetFileBuf(pool, (char*)currentFile->item, &fileBuf, + &fileBufLen)) < PS_SUCCESS) { + psFreeList(fileList, pool); + if (firstCert) psX509FreeCert(firstCert); + return err; + } + + if ((err = pemCertFileBufToX509(pool, fileBuf, fileBufLen, &x509list)) + < PS_SUCCESS) { + psFreeList(fileList, pool); + psFree(fileBuf, pool); + if (firstCert) psX509FreeCert(firstCert); + return err; + } + psFree(fileBuf, pool); + + frontX509 = x509list; +/* + Recurse each individual cert buffer from within the file +*/ + while (x509list != NULL) { + if ((err = psX509ParseCert(pool, x509list->item, x509list->len, + ¤tCert, flags)) < PS_SUCCESS) { + psX509FreeCert(currentCert); + psFreeList(fileList, pool); + psFreeList(frontX509, pool); + if (firstCert) psX509FreeCert(firstCert); + return err; + } + + x509list = x509list->next; + if (firstCert == NULL) { + firstCert = currentCert; + } else { + prevCert->next = currentCert; + } + prevCert = currentCert; + currentCert = currentCert->next; + } + currentFile = currentFile->next; + psFreeList(frontX509, pool); + } + psFreeList(fileList, pool); + + *outcert = firstCert; + + return PS_SUCCESS; +} + +/******************************************************************************/ +/* +*/ +static int32_t pemCertFileBufToX509(psPool_t *pool, const unsigned char *fileBuf, + uint16_t fileBufLen, psList_t **x509certList) +{ + psList_t *front, *prev, *current; + unsigned char *start, *end, *endTmp; + const unsigned char *chFileBuf; + unsigned char l; + + *x509certList = NULL; + prev = NULL; + if (fileBufLen < 0 || fileBuf == NULL) { + psTraceCrypto("Bad parameters to pemCertFileBufToX509\n"); + return PS_ARG_FAIL; + } + front = current = psMalloc(pool, sizeof(psList_t)); + if (current == NULL) { + psError("Memory allocation error first pemCertFileBufToX509\n"); + return PS_MEM_FAIL; + } + l = strlen("CERTIFICATE-----"); + memset(current, 0x0, sizeof(psList_t)); + chFileBuf = fileBuf; + while (fileBufLen > 0) { + if ( +((start = (unsigned char *)strstr((char *)chFileBuf, "-----BEGIN")) != NULL) && +((start = (unsigned char *)strstr((char *)chFileBuf, "CERTIFICATE-----")) != NULL) && +((end = (unsigned char *)strstr((char *)start, "-----END")) != NULL) && +((endTmp = (unsigned char *)strstr((char *)end,"CERTIFICATE-----")) != NULL) + ) { + start += l; + if (current == NULL) { + current = psMalloc(pool, sizeof(psList_t)); + if (current == NULL) { + psFreeList(front, pool); + psError("Memory allocation error: pemCertFileBufToX509\n"); + return PS_MEM_FAIL; + } + memset(current, 0x0, sizeof(psList_t)); + prev->next = current; + } + current->len = (uint16_t)(end - start); + end = endTmp + l; + while (*end == '\x0d' || *end == '\x0a' || *end == '\x09' + || *end == ' ') { + end++; + } + } else { + psFreeList(front, pool); + psTraceCrypto("File buffer does not look to be X.509 PEM format\n"); + return PS_PARSE_FAIL; + } + current->item = psMalloc(pool, current->len); + if (current->item == NULL) { + psFreeList(front, pool); + psError("Memory allocation error: pemCertFileBufToX509\n"); + return PS_MEM_FAIL; + } + memset(current->item, '\0', current->len); + + fileBufLen -= (uint16_t)(end - fileBuf); + fileBuf = end; + + if (psBase64decode(start, current->len, current->item, ¤t->len) != 0) { + psFreeList(front, pool); + psTraceCrypto("Unable to base64 decode certificate\n"); + return PS_PARSE_FAIL; + } + prev = current; + current = current->next; + chFileBuf = fileBuf; + } + *x509certList = front; + return PS_SUCCESS; +} +#endif /* MATRIX_USE_FILE_SYSTEM */ +/******************************************************************************/ + + +#ifdef USE_PKCS1_PSS +/* + RSASSA-PSS-params ::= SEQUENCE { + hashAlgorithm [0] HashAlgorithm DEFAULT sha1, + maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1, + saltLength [2] INTEGER DEFAULT 20, + trailerField [3] TrailerField DEFAULT trailerFieldBC + } + Note, each of these is sequential, but optional. +*/ +static int32 getRsaPssParams(const unsigned char **pp, int32 size, + psX509Cert_t *cert, int32 secondPass) +{ + const unsigned char *p, *end; + int32 oi, second, asnint; + uint16_t plen; + + p = *pp; + /* SEQUENCE has already been pulled off into size */ + end = p + size; + + /* The signature algorithm appears twice in an X.509 cert and must be + identical. If secondPass is set we check for that */ + if ((uint32)(end - p) < 1) { + return PS_PARSE_FAIL; + } + if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { + p++; + if (getAsnLength(&p, (uint32)(end - p), &plen) < 0 || + (end - p) < plen) { + psTraceCrypto("Error parsing rsapss hash alg\n"); + return PS_PARSE_FAIL; + } + /* hashAlgorithm is OID */ + if (getAsnAlgorithmIdentifier(&p, (uint32)(end - p), &oi, &plen) < 0) { + psTraceCrypto("Error parsing rsapss hash alg 2\n"); + return PS_PARSE_FAIL; + } + if (secondPass) { + if (oi != cert->pssHash) { + psTraceCrypto("rsapss hash alg doesn't repeat\n"); + return PS_PARSE_FAIL; + } + /* Convert to PKCS1_ ID for pssDecode on second pass */ + if (oi == OID_SHA1_ALG) { + second = PKCS1_SHA1_ID; + } else if (oi == OID_SHA256_ALG) { + second = PKCS1_SHA256_ID; + } else if (oi == OID_MD5_ALG) { + second = PKCS1_MD5_ID; +#ifdef USE_SHA384 + } else if (oi == OID_SHA384_ALG) { + second = PKCS1_SHA384_ID; +#endif +#ifdef USE_SHA512 + } else if (oi == OID_SHA512_ALG) { + second = PKCS1_SHA512_ID; +#endif + } else { + psTraceCrypto("Unsupported rsapss hash alg\n"); + return PS_UNSUPPORTED_FAIL; + } + cert->pssHash = second; + } else { + /* first time, save the OID for compare */ + cert->pssHash = oi; + } + } + if ((uint32)(end - p) < 1) { + return PS_PARSE_FAIL; + } + if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) { + /* maskGenAlgorthm is OID */ + p++; + if (getAsnLength(&p, (uint32)(end - p), &plen) < 0 || + (end - p) < plen) { + psTraceCrypto("Error parsing mask gen alg\n"); + return PS_PARSE_FAIL; + } + if (getAsnAlgorithmIdentifier(&p, (uint32)(end - p), &oi, &plen) < 0) { + psTraceCrypto("Error parsing mask gen alg 2\n"); + return PS_PARSE_FAIL; + } + if (secondPass) { + if (oi != cert->maskGen) { + psTraceCrypto("rsapss mask gen alg doesn't repeat\n"); + return PS_PARSE_FAIL; + } + } + cert->maskGen = oi; + if (cert->maskGen != OID_ID_MGF1) { + psTraceCrypto("Unsupported RSASSA-PSS maskGenAlgorithm\n"); + return PS_UNSUPPORTED_FAIL; + } + /* MaskGenAlgorithm ::= AlgorithmIdentifier { + {PKCS1MGFAlgorithms} + } + PKCS1MGFAlgorithms ALGORITHM-IDENTIFIER ::= { + { OID id-mgf1 PARAMETERS HashAlgorithm }, + ... -- Allows for future expansion -- + } + + The default mask generation function is MGF1 with SHA-1: + + mgf1SHA1 MaskGenAlgorithm ::= { + algorithm id-mgf1, + parameters HashAlgorithm : sha1 + } + */ + if (getAsnAlgorithmIdentifier(&p, (uint32)(end - p), &oi, &plen) < 0) { + psTraceCrypto("Error parsing mask hash alg\n"); + return PS_PARSE_FAIL; + } + if (secondPass) { + if (oi != cert->maskHash) { + psTraceCrypto("rsapss mask hash alg doesn't repeat\n"); + return PS_PARSE_FAIL; + } + } + cert->maskHash = oi; + } + if ((uint32)(end - p) < 1) { + return PS_PARSE_FAIL; + } + if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)) { + /* saltLen */ + p++; + if (getAsnLength(&p, (uint32)(end - p), &plen) < 0 || + (end - p) < plen) { + psTraceCrypto("Error parsing salt len\n"); + return PS_PARSE_FAIL; + } + if (getAsnInteger(&p, (uint32)(end - p), &asnint) < 0) { + psTraceCrypto("Error parsing salt len 2\n"); + return PS_PARSE_FAIL; + } + if (secondPass) { + if (asnint != cert->saltLen) { + psTraceCrypto("Error: salt len doesn't repeat\n"); + return PS_PARSE_FAIL; + } + } + cert->saltLen = plen; + } + if ((uint32)(end - p) < 1) { + return PS_PARSE_FAIL; + } + if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 3)) { + /* It shall be 1 for this version of the document, which represents + the trailer field with hexadecimal value 0xBC */ + p++; + if (getAsnLength(&p, (uint32)(end - p), &plen) < 0 || + (end - p) < plen) { + psTraceCrypto("Error parsing rsapss trailer\n"); + return PS_PARSE_FAIL; + } + if (getAsnInteger(&p, (uint32)(end - p), &asnint) < 0 || + plen != 0xBC) { + psTraceCrypto("Error parsing rsapss trailer 2\n"); + return PS_PARSE_FAIL; + } + } + + if (p != end) { + return PS_PARSE_FAIL; + } + *pp = (unsigned char*)p; + return PS_SUCCESS; +} +#endif + +/******************************************************************************/ +/* + Parse an X509 v3 ASN.1 certificate stream + http://tools.ietf.org/html/rfc3280 + + flags + CERT_STORE_UNPARSED_BUFFER + CERT_STORE_DN_BUFFER + + Memory info: + Caller must always free outcert with psX509FreeCert. Even on failure +*/ +int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 size, + psX509Cert_t **outcert, int32 flags) +{ + psX509Cert_t *cert; + const unsigned char *p, *end, *far_end, *certStart; + uint16_t len; + uint32_t oneCertLen; + int32 parsing, rc; + unsigned char sha1KeyHash[SHA1_HASH_SIZE]; +#ifdef USE_CERT_PARSE + psDigestContext_t hashCtx; + const unsigned char *certEnd; + uint16_t certLen, plen; +#endif + +/* + Allocate the cert structure right away. User MUST always call + psX509FreeCert regardless of whether this function succeeds. + memset is important because the test for NULL is what is used + to determine what to free +*/ + *outcert = cert = psMalloc(pool, sizeof(psX509Cert_t)); + if (cert == NULL) { + psError("Memory allocation failure in psX509ParseCert\n"); + return PS_MEM_FAIL; + } + memset(cert, 0x0, sizeof(psX509Cert_t)); + cert->pool = pool; + + p = pp; + far_end = p + size; +/* + Certificate ::= SEQUENCE { + tbsCertificate TBSCertificate, + signatureAlgorithm AlgorithmIdentifier, + signatureValue BIT STRING } +*/ + parsing = 1; + while (parsing) { + certStart = p; + if ((rc = getAsnSequence32(&p, (uint32_t)(far_end - p), &oneCertLen, 0)) + < 0){ + psTraceCrypto("Initial cert parse error\n"); + return rc; + } + /* The whole list of certs could be > 64K bytes, but we still + restrict individual certs to 64KB */ + if (oneCertLen > 0xFFFF) { + psAssert(oneCertLen <= 0xFFFF); + return PS_FAILURE; + } + end = p + oneCertLen; +/* + If the user has specified to keep the ASN.1 buffer in the X.509 + structure, now is the time to account for it +*/ + if (flags & CERT_STORE_UNPARSED_BUFFER) { + cert->binLen = oneCertLen + (int32)(p - certStart); + cert->unparsedBin = psMalloc(pool, cert->binLen); + if (cert->unparsedBin == NULL) { + psError("Memory allocation error in psX509ParseCert\n"); + return PS_MEM_FAIL; + } + memcpy(cert->unparsedBin, certStart, cert->binLen); + } + +#ifdef ENABLE_CA_CERT_HASH + /* We use the cert_sha1_hash type for the Trusted CA Indication so + run a SHA1 has over the entire Certificate DER encoding. */ + psSha1Init(&hashCtx.sha1); + psSha1Update(&hashCtx.sha1, certStart, + oneCertLen + (int32)(p - certStart)); + psSha1Final(&hashCtx.sha1, cert->sha1CertHash); +#endif + +#ifdef USE_CERT_PARSE + certStart = p; +/* + TBSCertificate ::= SEQUENCE { + version [0] EXPLICIT Version DEFAULT v1, + serialNumber CertificateSerialNumber, + signature AlgorithmIdentifier, + issuer Name, + validity Validity, + subject Name, + subjectPublicKeyInfo SubjectPublicKeyInfo, + issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + -- If present, version shall be v2 or v3 + subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + -- If present, version shall be v2 or v3 + extensions [3] EXPLICIT Extensions OPTIONAL + -- If present, version shall be v3 } +*/ + if ((rc = getAsnSequence(&p, (uint32)(end - p), &len)) < 0) { + psTraceCrypto("ASN sequence parse error\n"); + return rc; + } + certEnd = p + len; + certLen = certEnd - certStart; + +/* + Version ::= INTEGER { v1(0), v2(1), v3(2) } +*/ + if ((rc = getExplicitVersion(&p, (uint32)(end - p), 0, &cert->version)) + < 0) { + psTraceCrypto("ASN version parse error\n"); + return rc; + } + if (cert->version != 2) { + psTraceIntCrypto("ERROR: non-v3 certificate version %d insecure\n", + cert->version); + return PS_PARSE_FAIL; + } +/* + CertificateSerialNumber ::= INTEGER + There is a special return code for a missing serial number that + will get written to the parse warning flag +*/ + if ((rc = getSerialNum(pool, &p, (uint32)(end - p), &cert->serialNumber, + &cert->serialNumberLen)) < 0) { + psTraceCrypto("ASN serial number parse error\n"); + return rc; + } +/* + AlgorithmIdentifier ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters ANY DEFINED BY algorithm OPTIONAL } +*/ + if ((rc = getAsnAlgorithmIdentifier(&p, (uint32)(end - p), + &cert->certAlgorithm, &plen)) < 0) { + psTraceCrypto("Couldn't parse algorithm identifier for certAlgorithm\n"); + return rc; + } + if (plen != 0) { +#ifdef USE_PKCS1_PSS + if (cert->certAlgorithm == OID_RSASSA_PSS) { + /* RSASSA-PSS-params ::= SEQUENCE { + hashAlgorithm [0] HashAlgorithm DEFAULT sha1, + maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1, + saltLength [2] INTEGER DEFAULT 20, + trailerField [3] TrailerField DEFAULT trailerFieldBC + } + */ + if ((rc = getAsnSequence(&p, (uint32)(end - p), &len)) < 0) { + psTraceCrypto("ASN sequence parse error\n"); + return rc; + } + /* Always set the defaults before parsing */ + cert->pssHash = PKCS1_SHA1_ID; + cert->saltLen = SHA1_HASH_SIZE; + /* Something other than defaults to parse here? */ + if (len > 0) { + if ((rc = getRsaPssParams(&p, len, cert, 0)) < 0) { + return rc; + } + } + } else { + psTraceCrypto("Unsupported X.509 certAlgorithm\n"); + return PS_UNSUPPORTED_FAIL; + } +#else + psTraceCrypto("Unsupported X.509 certAlgorithm\n"); + return PS_UNSUPPORTED_FAIL; +#endif + } +/* + Name ::= CHOICE { + RDNSequence } + + RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + + RelativeDistinguishedName ::= SET OF AttributeTypeAndValue + + AttributeTypeAndValue ::= SEQUENCE { + type AttributeType, + value AttributeValue } + + AttributeType ::= OBJECT IDENTIFIER + + AttributeValue ::= ANY DEFINED BY AttributeType +*/ + if ((rc = psX509GetDNAttributes(pool, &p, (uint32)(end - p), + &cert->issuer, flags)) < 0) { + psTraceCrypto("Couldn't parse issuer DN attributes\n"); + return rc; + } +/* + Validity ::= SEQUENCE { + notBefore Time, + notAfter Time } +*/ + if ((rc = getTimeValidity(pool, &p, (uint32)(end - p), + &cert->notBeforeTimeType, &cert->notAfterTimeType, + &cert->notBefore, &cert->notAfter)) < 0) { + psTraceCrypto("Couldn't parse validity\n"); + return rc; + } + + /* SECURITY - platforms without a date function will always succeed */ + if ((rc = validateDateRange(cert)) < 0) { + psTraceCrypto("Validity date check failed\n"); + return rc; + } +/* + Subject DN +*/ + if ((rc = psX509GetDNAttributes(pool, &p, (uint32)(end - p), + &cert->subject, flags)) < 0) { + psTraceCrypto("Couldn't parse subject DN attributes\n"); + return rc; + } +/* + SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey BIT STRING } +*/ + if ((rc = getAsnSequence(&p, (uint32)(end - p), &len)) < 0) { + psTraceCrypto("Couldn't get ASN sequence for pubKeyAlgorithm\n"); + return rc; + } + if ((rc = getAsnAlgorithmIdentifier(&p, (uint32)(end - p), + &cert->pubKeyAlgorithm, &plen)) < 0) { + psTraceCrypto("Couldn't parse algorithm id for pubKeyAlgorithm\n"); + return rc; + } + + /* Populate with correct type based on pubKeyAlgorithm OID */ + switch (cert->pubKeyAlgorithm) { +#ifdef USE_ECC + case OID_ECDSA_KEY_ALG: + if (plen == 0 || plen > (int32)(end - p)) { + psTraceCrypto("Bad params on EC OID\n"); + return PS_PARSE_FAIL; + } + psInitPubKey(pool, &cert->publicKey, PS_ECC); + if (getEcPubKey(pool, &p, (uint16_t)(end - p), + &cert->publicKey.key.ecc, sha1KeyHash) < 0) { + return PS_PARSE_FAIL; + } + /* keysize will be the size of the public ecc key (2 * privateLen) */ + cert->publicKey.keysize = psEccSize(&cert->publicKey.key.ecc); + if (cert->publicKey.keysize < (MIN_ECC_BITS / 8)) { + psTraceIntCrypto("ECC key size < %d\n", MIN_ECC_BITS); + psClearPubKey(&cert->publicKey); + return PS_PARSE_FAIL; + } + break; +#endif +#ifdef USE_RSA + case OID_RSA_KEY_ALG: + psAssert(plen == 0); /* No parameters on RSA pub key OID */ + psInitPubKey(pool, &cert->publicKey, PS_RSA); + if ((rc = psRsaParseAsnPubKey(pool, &p, (uint16_t)(end - p), + &cert->publicKey.key.rsa, sha1KeyHash)) < 0) { + psTraceCrypto("Couldn't get RSA pub key from cert\n"); + return rc; + } + cert->publicKey.keysize = psRsaSize(&cert->publicKey.key.rsa); + + if (cert->publicKey.keysize < (MIN_RSA_BITS / 8)) { + psTraceIntCrypto("RSA key size < %d\n", MIN_RSA_BITS); + psClearPubKey(&cert->publicKey); + return PS_PARSE_FAIL; + } + + break; +#endif + default: + psTraceIntCrypto("Unsupported public key algorithm in cert parse: %d\n", + cert->pubKeyAlgorithm); + return PS_UNSUPPORTED_FAIL; + } + +#ifdef USE_OCSP + /* A sha1 hash of the public key is useful for OCSP */ + memcpy(cert->sha1KeyHash, sha1KeyHash, SHA1_HASH_SIZE); +#endif + + /* As the next three values are optional, we can do a specific test here */ + if (*p != (ASN_SEQUENCE | ASN_CONSTRUCTED)) { + if (getImplicitBitString(pool, &p, (uint32)(end - p), + IMPLICIT_ISSUER_ID, &cert->uniqueIssuerId, + &cert->uniqueIssuerIdLen) < 0 || + getImplicitBitString(pool, &p, (uint32)(end - p), + IMPLICIT_SUBJECT_ID, &cert->uniqueSubjectId, + &cert->uniqueSubjectIdLen) < 0 || + getExplicitExtensions(pool, &p, (uint32)(end - p), + EXPLICIT_EXTENSION, &cert->extensions, 0) < 0) { + psTraceCrypto("There was an error parsing a certificate\n"); + psTraceCrypto("extension. This is likely caused by an\n"); + psTraceCrypto("extension format that is not currently\n"); + psTraceCrypto("recognized. Please email Inside support\n"); + psTraceCrypto("to add support for the extension.\n\n"); + return PS_PARSE_FAIL; + } + } + + /* This is the end of the cert. Do a check here to be certain */ + if (certEnd != p) { + psTraceCrypto("Error. Expecting end of cert\n"); + return PS_LIMIT_FAIL; + } + + /* Reject any cert without a distinguishedName or subjectAltName */ + if (cert->subject.commonName == NULL && + cert->subject.country == NULL && + cert->subject.state == NULL && + cert->subject.locality == NULL && + cert->subject.organization == NULL && + cert->subject.orgUnit == NULL && + cert->extensions.san == NULL) { + psTraceCrypto("Error. Cert has no name information\n"); + return PS_PARSE_FAIL; + } + /* Certificate signature info */ + if ((rc = getAsnAlgorithmIdentifier(&p, (uint32)(end - p), + &cert->sigAlgorithm, &plen)) < 0) { + psTraceCrypto("Couldn't get algorithm identifier for sigAlgorithm\n"); + return rc; + } + if (plen != 0) { +#ifdef USE_PKCS1_PSS + if (cert->sigAlgorithm == OID_RSASSA_PSS) { + /* RSASSA-PSS-params ::= SEQUENCE { + hashAlgorithm [0] HashAlgorithm DEFAULT sha1, + maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1, + saltLength [2] INTEGER DEFAULT 20, + trailerField [3] TrailerField DEFAULT trailerFieldBC + } + */ + if ((rc = getAsnSequence(&p, (uint32)(end - p), &len)) < 0) { + psTraceCrypto("ASN sequence parse error\n"); + return rc; + } + /* Something other than defaults to parse here? */ + if (len > 0) { + if ((rc = getRsaPssParams(&p, len, cert, 1)) < 0) { + return rc; + } + } + } else { + psTraceCrypto("Unsupported X.509 sigAlgorithm\n"); + return PS_UNSUPPORTED_FAIL; + } +#else + psTraceCrypto("Unsupported X.509 sigAlgorithm\n"); + return PS_UNSUPPORTED_FAIL; +#endif + } +/* + Signature algorithm must match that specified in TBS cert +*/ + if (cert->certAlgorithm != cert->sigAlgorithm) { + psTraceCrypto("Parse error: mismatched signature type\n"); + return PS_CERT_AUTH_FAIL; + } + +/* + Compute the hash of the cert here for CA validation +*/ + switch (cert->certAlgorithm) { +#ifdef ENABLE_MD5_SIGNED_CERTS +#ifdef USE_MD2 + case OID_MD2_RSA_SIG: + psMd2Init(&hashCtx.md2); + psMd2Update(&hashCtx.md2, certStart, certLen); + psMd2Final(&hashCtx.md2, cert->sigHash); + break; +#endif + case OID_MD5_RSA_SIG: + psMd5Init(&hashCtx.md5); + psMd5Update(&hashCtx.md5, certStart, certLen); + psMd5Final(&hashCtx.md5, cert->sigHash); + break; +#endif +#ifdef ENABLE_SHA1_SIGNED_CERTS + case OID_SHA1_RSA_SIG: +#ifdef USE_ECC + case OID_SHA1_ECDSA_SIG: +#endif + psSha1Init(&hashCtx.sha1); + psSha1Update(&hashCtx.sha1, certStart, certLen); + psSha1Final(&hashCtx.sha1, cert->sigHash); + break; +#endif +#ifdef USE_SHA256 + case OID_SHA256_RSA_SIG: +#ifdef USE_ECC + case OID_SHA256_ECDSA_SIG: +#endif + psSha256Init(&hashCtx.sha256); + psSha256Update(&hashCtx.sha256, certStart, certLen); + psSha256Final(&hashCtx.sha256, cert->sigHash); + break; +#endif +#ifdef USE_SHA384 + case OID_SHA384_RSA_SIG: +#ifdef USE_ECC + case OID_SHA384_ECDSA_SIG: +#endif + psSha384Init(&hashCtx.sha384); + psSha384Update(&hashCtx.sha384, certStart, certLen); + psSha384Final(&hashCtx.sha384, cert->sigHash); + break; +#endif +#ifdef USE_SHA512 + case OID_SHA512_RSA_SIG: +#ifdef USE_ECC + case OID_SHA512_ECDSA_SIG: +#endif + psSha512Init(&hashCtx.sha512); + psSha512Update(&hashCtx.sha512, certStart, certLen); + psSha512Final(&hashCtx.sha512, cert->sigHash); + break; +#endif +#ifdef USE_PKCS1_PSS + case OID_RSASSA_PSS: + switch (cert->pssHash) { +#ifdef ENABLE_MD5_SIGNED_CERTS + case PKCS1_MD5_ID: + psMd5Init(&hashCtx.md5); + psMd5Update(&hashCtx.md5, certStart, certLen); + psMd5Final(&hashCtx.md5, cert->sigHash); + break; +#endif +#ifdef ENABLE_SHA1_SIGNED_CERTS + case PKCS1_SHA1_ID: + psSha1Init(&hashCtx.sha1); + psSha1Update(&hashCtx.sha1, certStart, certLen); + psSha1Final(&hashCtx.sha1, cert->sigHash); + break; +#endif +#ifdef USE_SHA256 + case PKCS1_SHA256_ID: + psSha256Init(&hashCtx.sha256); + psSha256Update(&hashCtx.sha256, certStart, certLen); + psSha256Final(&hashCtx.sha256, cert->sigHash); + break; +#endif +#ifdef USE_SHA384 + case PKCS1_SHA384_ID: + psSha384Init(&hashCtx.sha384); + psSha384Update(&hashCtx.sha384, certStart, certLen); + psSha384Final(&hashCtx.sha384, cert->sigHash); + break; +#endif +#ifdef USE_SHA512 + case PKCS1_SHA512_ID: + psSha512Init(&hashCtx.sha512); + psSha512Update(&hashCtx.sha512, certStart, certLen); + psSha512Final(&hashCtx.sha512, cert->sigHash); + break; +#endif + default: + return PS_UNSUPPORTED_FAIL; + + } /* switch pssHash */ + break; +#endif /* USE_PKCS1_PSS */ + + default: + psTraceCrypto("Unsupported cert algorithm\n"); + return PS_UNSUPPORTED_FAIL; + + } /* switch certAlgorithm */ + + /* 6 empty bytes is plenty enough to know if sigHash didn't calculate */ + if (memcmp(cert->sigHash, "\0\0\0\0\0\0", 6) == 0) { + psTraceIntCrypto("No library signature alg support for cert: %d\n", + cert->certAlgorithm); + return PS_UNSUPPORTED_FAIL; + } + + if ((rc = psX509GetSignature(pool, &p, (uint32)(end - p), + &cert->signature, &cert->signatureLen)) < 0) { + psTraceCrypto("Couldn't parse signature\n"); + return rc; + } + +#else /* !USE_CERT_PARSE */ + p = certStart + len + (int32)(p - certStart); +#endif /* USE_CERT_PARSE */ +/* + The ability to parse additional chained certs is a PKI product + feature addition. Chaining in MatrixSSL is handled internally. +*/ + if ((p != far_end) && (p < (far_end + 1))) { + if (*p == 0x0 && *(p + 1) == 0x0) { + parsing = 0; /* An indefinite length stream was passed in */ + /* caller will have to deal with skipping these becuase they + would have read off the TL of this ASN.1 stream */ + } else { + cert->next = psMalloc(pool, sizeof(psX509Cert_t)); + if (cert->next == NULL) { + psError("Memory allocation error in psX509ParseCert\n"); + return PS_MEM_FAIL; + } + cert = cert->next; + memset(cert, 0x0, sizeof(psX509Cert_t)); + cert->pool = pool; + } + } else { + parsing = 0; + } + } + + return (int32)(p - pp); +} + +#ifdef USE_CERT_PARSE +void x509FreeExtensions(x509v3extensions_t *extensions) +{ + + x509GeneralName_t *active, *inc; + + if (extensions->san) { + active = extensions->san; + while (active != NULL) { + inc = active->next; + psFree(active->data, extensions->pool); + psFree(active, extensions->pool); + active = inc; + } + } + +#ifdef USE_CRL + if (extensions->crlDist) { + active = extensions->crlDist; + while (active != NULL) { + inc = active->next; + psFree(active->data, extensions->pool); + psFree(active, extensions->pool); + active = inc; + } + } +#endif /* CRL */ + +#ifdef USE_FULL_CERT_PARSE + if (extensions->nameConstraints.excluded) { + active = extensions->nameConstraints.excluded; + while (active != NULL) { + inc = active->next; + psFree(active->data, extensions->pool); + psFree(active, extensions->pool); + active = inc; + } + } + if (extensions->nameConstraints.permitted) { + active = extensions->nameConstraints.permitted; + while (active != NULL) { + inc = active->next; + psFree(active->data, extensions->pool); + psFree(active, extensions->pool); + active = inc; + } + } +#endif /* USE_FULL_CERT_PARSE */ + if (extensions->sk.id) psFree(extensions->sk.id, extensions->pool); + if (extensions->ak.keyId) psFree(extensions->ak.keyId, extensions->pool); + if (extensions->ak.serialNum) psFree(extensions->ak.serialNum, + extensions->pool); + if (extensions->ak.attribs.commonName) + psFree(extensions->ak.attribs.commonName, extensions->pool); + if (extensions->ak.attribs.country) psFree(extensions->ak.attribs.country, + extensions->pool); + if (extensions->ak.attribs.state) psFree(extensions->ak.attribs.state, + extensions->pool); + if (extensions->ak.attribs.locality) + psFree(extensions->ak.attribs.locality, extensions->pool); + if (extensions->ak.attribs.organization) + psFree(extensions->ak.attribs.organization, extensions->pool); + if (extensions->ak.attribs.orgUnit) psFree(extensions->ak.attribs.orgUnit, + extensions->pool); + if (extensions->ak.attribs.dnenc) psFree(extensions->ak.attribs.dnenc, + extensions->pool); +} +#endif /* USE_CERT_PARSE */ + +/******************************************************************************/ +/* + User must call after all calls to psX509ParseCert + (we violate the coding standard a bit here for clarity) +*/ +void psX509FreeCert(psX509Cert_t *cert) +{ + psX509Cert_t *curr, *next; + psPool_t *pool; + + curr = cert; + while (curr) { + pool = curr->pool; + if (curr->unparsedBin) psFree(curr->unparsedBin, pool); +#ifdef USE_CERT_PARSE + psX509FreeDNStruct(&curr->issuer, pool); + psX509FreeDNStruct(&curr->subject, pool); + if (curr->serialNumber) psFree(curr->serialNumber, pool); + if (curr->notBefore) psFree(curr->notBefore, pool); + if (curr->notAfter) psFree(curr->notAfter, pool); + if (curr->signature) psFree(curr->signature, pool); + if (curr->uniqueIssuerId) psFree(curr->uniqueIssuerId, pool); + if (curr->uniqueSubjectId) psFree(curr->uniqueSubjectId, pool); + + + if (curr->publicKey.type != PS_NONE) { + switch (curr->pubKeyAlgorithm) { +#ifdef USE_RSA + case OID_RSA_KEY_ALG: + psRsaClearKey(&curr->publicKey.key.rsa); + break; +#endif + +#ifdef USE_ECC + case OID_ECDSA_KEY_ALG: + psEccClearKey(&curr->publicKey.key.ecc); + break; +#endif + default: + psAssert(0); + break; + } + curr->publicKey.type = PS_NONE; + } + + x509FreeExtensions(&curr->extensions); +#ifdef USE_CRL + x509FreeRevoked(&curr->revoked); +#endif +#endif /* USE_CERT_PARSE */ + next = curr->next; + psFree(curr, pool); + curr = next; + } +} + +#ifdef USE_CERT_PARSE +/******************************************************************************/ +/* + Currently just returning the raw BIT STRING and size in bytes +*/ +#define MIN_HASH_SIZE 16 +int32_t psX509GetSignature(psPool_t *pool, const unsigned char **pp, uint16_t len, + unsigned char **sig, uint16_t *sigLen) +{ + const unsigned char *p = *pp, *end; + uint16_t llen; + + end = p + len; + if (len < 1 || (*(p++) != ASN_BIT_STRING) || + getAsnLength(&p, len - 1, &llen) < 0 || + (uint32)(end - p) < llen || + llen < (1 + MIN_HASH_SIZE)) { + + psTraceCrypto("Initial parse error in getSignature\n"); + return PS_PARSE_FAIL; + } + /* We assume this ignore_bits byte is always 0. */ + psAssert(*p == 0); + p++; + /* Length was including the ignore_bits byte, subtract it */ + *sigLen = llen - 1; + *sig = psMalloc(pool, *sigLen); + if (*sig == NULL) { + psError("Memory allocation error in getSignature\n"); + return PS_MEM_FAIL; + } + memcpy(*sig, p, *sigLen); + *pp = p + *sigLen; + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Validate the expected name against a subset of the GeneralName rules + for DNS, Email and IP types. + We assume the expected name is not maliciously entered. If it is, it may + match an invalid GeneralName in a remote cert chain. + Returns 0 on valid format, PS_FAILURE on invalid format of GeneralName +*/ +int32_t psX509ValidateGeneralName(const char *n) +{ + const char *c; + int atfound; /* Ampersand found */ + int notip; /* Not an ip address */ + + if (n == NULL) return 0; + + /* Must be at least one character */ + if (*n == '\0') return PS_FAILURE; + + atfound = notip = 0; + for (c = n; *c != '\0'; c++ ) { + + /* Negative tests first in the loop */ + /* Can't have any combination of . and - and @ together */ + if (c != n) { + if (*c == '.' && *(c-1) == '.') return PS_FAILURE; + if (*c == '.' && *(c-1) == '-') return PS_FAILURE; + if (*c == '.' && *(c-1) == '@') return PS_FAILURE; + if (*c == '-' && *(c-1) == '.') return PS_FAILURE; + if (*c == '-' && *(c-1) == '-') return PS_FAILURE; + if (*c == '-' && *(c-1) == '@') return PS_FAILURE; + if (*c == '@' && *(c-1) == '.') return PS_FAILURE; + if (*c == '@' && *(c-1) == '-') return PS_FAILURE; + if (*c == '@' && *(c-1) == '@') return PS_FAILURE; + } + + /* Note whether we have hit a non numeric name */ + if (*c != '.' && (*c < '0' || *c > '9')) notip++; + + /* Now positive tests */ + /* Cannot start or end with . or -, but can contain them */ + if (c != n && *(c + 1) != '\0' && (*c == '.' || *c == '-')) continue; + /* Can contain at most one @ , and not at the start or end */ + if (*c == '@') { + atfound++; + if (c != n && *(c + 1) != '\0' && atfound == 1) { + continue; + } + } + /* Numbers allowed generally */ + if (*c >= '0' && *c <= '9') continue; + /* Upper and lowercase characters allowed */ + if (*c >= 'A' && *c <= 'Z') continue; + if (*c >= 'a' && *c <= 'z') continue; + + /* Everything else is a failure */ + return PS_FAILURE; + } + /* RFC 1034 states if it's not an IP, it can't start with a number, + However, RFC 1123 updates this and does allow a number as the + first character of a DNS name. + See the X.509 RFC: http://tools.ietf.org/html/rfc5280#section-4.2.1.6 */ + if (atfound && (*n >= '0' && *n <= '9')) return PS_FAILURE; + + /* We could at this point store whether it is a DNS, Email or IP */ + + return 0; +} + +/******************************************************************************/ +/* + Parses a sequence of GeneralName types + TODO: the actual types should be parsed. Just copying data blob + + GeneralName ::= CHOICE { + otherName [0] OtherName, + rfc822Name [1] IA5String, + dNSName [2] IA5String, + x400Address [3] ORAddress, + directoryName [4] Name, + ediPartyName [5] EDIPartyName, + uniformResourceIdentifier [6] IA5String, + iPAddress [7] OCTET STRING, + registeredID [8] OBJECT IDENTIFIER } +*/ +static int32_t parseGeneralNames(psPool_t *pool, const unsigned char **buf, + uint16_t len, const unsigned char *extEnd, + x509GeneralName_t **name, int16_t limit) +{ + uint16_t otherNameLen; + const unsigned char *p, *c, *save, *end; + x509GeneralName_t *activeName, *firstName, *prevName; + + if (*name == NULL) { + firstName = NULL; + } else { + firstName = *name; + } + p = *buf; + end = p + len; + + while (len > 0) { + if (firstName == NULL) { + activeName = firstName = psMalloc(pool, sizeof(x509GeneralName_t)); + if (activeName == NULL) { + return PS_MEM_FAIL; + } + memset(firstName, 0x0, sizeof(x509GeneralName_t)); + firstName->pool = pool; + *name = firstName; + } else { +/* + Find the end +*/ + prevName = firstName; + activeName = firstName->next; + while (activeName != NULL) { + prevName = activeName; + activeName = activeName->next; + } + prevName->next = psMalloc(pool, sizeof(x509GeneralName_t)); + if (prevName->next == NULL) { + /* TODO: free the list */ + return PS_MEM_FAIL; + } + activeName = prevName->next; + memset(activeName, 0x0, sizeof(x509GeneralName_t)); + activeName->pool = pool; + } + activeName->id = *p & 0xF; + p++; len--; + switch (activeName->id) { + case GN_OTHER: + strncpy((char *)activeName->name, "other", + sizeof(activeName->name) - 1); + /* OtherName ::= SEQUENCE { + type-id OBJECT IDENTIFIER, + value [0] EXPLICIT ANY DEFINED BY type-id } + */ + save = p; + if (getAsnLength(&p, (uint32)(extEnd - p), &otherNameLen) < 0 || + otherNameLen < 1 || + (uint32)(extEnd - p) < otherNameLen) { + psTraceCrypto("ASN parse error SAN otherName\n"); + return PS_PARSE_FAIL; + } + if (*(p++) != ASN_OID || + getAsnLength(&p, (int32)(extEnd - p), &activeName->oidLen) < 0 || + (uint32)(extEnd - p) < activeName->oidLen) { + + psTraceCrypto("ASN parse error SAN otherName oid\n"); + return -1; + } + /* Note activeName->oidLen could be zero here */ + memcpy(activeName->oid, p, activeName->oidLen); + p += activeName->oidLen; + /* value looks like + 0xA0, , , , + We're supporting only string-type TYPE so just skipping it + */ + if ((uint32)(extEnd - p) < 1 || *p != 0xA0) { + psTraceCrypto("ASN parse error SAN otherName\n"); + return PS_PARSE_FAIL; + } + p++; /* Jump over A0 */ + if (getAsnLength(&p, (uint32)(extEnd - p), &otherNameLen) < 0 || + otherNameLen < 1 || + (uint32)(extEnd - p) < otherNameLen) { + psTraceCrypto("ASN parse error SAN otherName value\n"); + return PS_PARSE_FAIL; + } + if ((uint32)(extEnd - p) < 1) { + psTraceCrypto("ASN parse error SAN otherName len\n"); + return PS_PARSE_FAIL; + } + /* TODO - validate *p == STRING type? */ + p++; /* Jump over TYPE */ + len -= (p - save); + break; + case GN_EMAIL: + strncpy((char *)activeName->name, "email", + sizeof(activeName->name) - 1); + break; + case GN_DNS: + strncpy((char *)activeName->name, "DNS", + sizeof(activeName->name) - 1); + break; + case GN_X400: + strncpy((char *)activeName->name, "x400Address", + sizeof(activeName->name) - 1); + break; + case GN_DIR: + strncpy((char *)activeName->name, "directoryName", + sizeof(activeName->name) - 1); + break; + case GN_EDI: + strncpy((char *)activeName->name, "ediPartyName", + sizeof(activeName->name) - 1); + break; + case GN_URI: + strncpy((char *)activeName->name, "URI", + sizeof(activeName->name) - 1); + break; + case GN_IP: + strncpy((char *)activeName->name, "iPAddress", + sizeof(activeName->name) - 1); + break; + case GN_REGID: + strncpy((char *)activeName->name, "registeredID", + sizeof(activeName->name) - 1); + break; + default: + strncpy((char *)activeName->name, "unknown", + sizeof(activeName->name) - 1); + break; + } + + save = p; + if (getAsnLength(&p, (uint32)(extEnd - p), &activeName->dataLen) < 0 || + activeName->dataLen < 1 || + (uint32)(extEnd - p) < activeName->dataLen) { + psTraceCrypto("ASN len error in parseGeneralNames\n"); + return PS_PARSE_FAIL; + } + len -= (p - save); + + /* Currently we validate that the IA5String fields are printable + At a minimum, this prevents attacks with null terminators or + invisible characters in the certificate. + Additional validation of name format is done indirectly + via byte comparison to the expected name in ValidateGeneralName + or directly by the user in the certificate callback */ + switch (activeName->id) { + case GN_EMAIL: + case GN_DNS: + case GN_URI: + save = p + activeName->dataLen; + for (c = p; c < save; c++) { + if (*c < ' ' || *c > '~') { + psTraceCrypto("ASN invalid GeneralName character\n"); + return PS_PARSE_FAIL; + } + } + break; + case GN_IP: + if (activeName->dataLen < 4) { + psTraceCrypto("Unknown GN_IP format\n"); + return PS_PARSE_FAIL; + } + break; + default: + break; + } + + activeName->data = psMalloc(pool, activeName->dataLen + 1); + if (activeName->data == NULL) { + psError("Memory allocation error: activeName->data\n"); + return PS_MEM_FAIL; + } + /* This guarantees data is null terminated, even for non IA5Strings */ + memset(activeName->data, 0x0, activeName->dataLen + 1); + memcpy(activeName->data, p, activeName->dataLen); + + p = p + activeName->dataLen; + len -= activeName->dataLen; + + if (limit > 0) { + if (--limit == 0) { + *buf = end; + return PS_SUCCESS; + } + } + } + *buf = p; + return PS_SUCCESS; +} + +/******************************************************************************/ +/** + Parse ASN.1 DER encoded OBJECT bytes into an OID array. + @param[in] der Pointer to start of OBJECT encoding. + @param[in] derlen Number of bytes pointed to by 'der'. + @param[out] oid Caller allocated array to receive OID, of + at least MAX_OID_LEN elements. + @return Number of OID elements written to 'oid', 0 on error. +*/ +static uint8_t psParseOid(const unsigned char *der, uint16_t derlen, + uint32_t oid[MAX_OID_LEN]) +{ + const unsigned char *end; + uint8_t n, sanity; + + if (derlen < 1) { + return 0; + } + end = der + derlen; + /* First two OID elements are single octet, base 40 for some reason */ + oid[0] = *der / 40; + oid[1] = *der % 40; + der++; + /* Zero the remainder of OID and leave n == 2 */ + for (n = MAX_OID_LEN - 1; n > 2; n--) { + oid[n] = 0; + } + while (der < end && n < MAX_OID_LEN) { + /* If the high bit is 0, it's short form variable length quantity */ + if (!(*der & 0x80)) { + oid[n++] = *der++; + } else { + sanity = 0; + /* Long form. High bit means another (lower) 7 bits following */ + do { + oid[n] |= (*der & 0x7F); + /* A clear high bit ends the byte sequence */ + if (!(*der & 0x80)) { + break; + } + /* Allow a maximum of 4 x 7 bit shifts (28 bits) */ + if (++sanity > 4) { + return 0; + } + /* Make room for the next 7 bits */ + oid[n] <<= 7; + der++; + } while (der < end); + der++; + n++; + } + } + if (n < MAX_OID_LEN) { + return n; + } + return 0; +} + +/** + Look up an OID in our known oid table. + @param[in] oid Array of OID segments to look up in table. + @param[in] oidlen Number of segments in 'oid' + @return A valid OID enum on success, 0 on failure. +*/ +static oid_e psFindOid(const uint32_t oid[MAX_OID_LEN], uint8_t oidlen) +{ + int i, j; + + psAssert(oidlen <= MAX_OID_LEN); + for (j = 0; oid_list[j].id != 0; j++) { + for (i = 0; i < oidlen; i++) { + if ((uint16_t)(oid[i] & 0xFFFF) != oid_list[j].oid[i]) { + break; + } + if ((i + 1) == oidlen) { + return oid_list[j].id; + } + } + } + return 0; +} + +#ifdef USE_OID_TRACE +/** + Print an OID in dot notation, with it's symbolic name, if found. + @param[in] oid Array of OID segments print. + @param[in] oidlen Number of segments in 'oid' + @return void +*/ +static void psTraceOid(uint32_t oid[MAX_OID_LEN], uint8_t oidlen) +{ + int i, j, found; + + for (i = 0; i < oidlen; i++) { + if ((i + 1) < oidlen) { + psTraceIntCrypto("%u.", oid[i]); + } else { + psTraceIntCrypto("%u", oid[i]); + } + } + found = 0; + for (j = 0; oid_list[j].oid[0] != 0 && !found; j++) { + for (i = 0; i < oidlen; i++) { + if ((uint8_t)(oid[i] & 0xFF) != oid_list[j].oid[i]) { + break; + } + if ((i + 1) == oidlen) { + psTraceStrCrypto(" (%s)", oid_list[j].name); + found++; + } + } + } + psTraceCrypto("\n"); +} +#else +#define psTraceOid(A, B) psTraceCrypto("\n"); +#endif + +/******************************************************************************/ +/* + X509v3 extensions +*/ + +int32_t getExplicitExtensions(psPool_t *pool, const unsigned char **pp, + uint16_t inlen, int32_t expVal, + x509v3extensions_t *extensions, uint8_t known) +{ + const unsigned char *p = *pp, *end; + const unsigned char *extEnd, *extStart, *save; + unsigned char critical; + uint16_t len, fullExtLen; + uint32_t oid[MAX_OID_LEN]; + uint8_t oidlen; + oid_e noid; +#ifdef USE_FULL_CERT_PARSE + uint16_t subExtLen; + const unsigned char *subSave; + int32_t nc = 0; +#endif + + end = p + inlen; + if (inlen < 1) { + return PS_ARG_FAIL; + } + extensions->pool = pool; + if (known) { + goto KNOWN_EXT; + } +/* + Not treating this as an error because it is optional. +*/ + if (*p != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | expVal)) { + return 0; + } + p++; + if (getAsnLength(&p, (uint32)(end - p), &len) < 0 || + (uint32)(end - p) < len) { + psTraceCrypto("Initial getAsnLength failure in extension parse\n"); + return PS_PARSE_FAIL; + } +KNOWN_EXT: +/* + Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + + Extension ::= SEQUENCE { + extnID OBJECT IDENTIFIER, + extnValue OCTET STRING } +*/ + if (getAsnSequence(&p, (uint32)(end - p), &len) < 0 || + (uint32)(end - p) < len) { + psTraceCrypto("Initial getAsnSequence failure in extension parse\n"); + return PS_PARSE_FAIL; + } + extEnd = p + len; + while ((p != extEnd) && *p == (ASN_SEQUENCE | ASN_CONSTRUCTED)) { + if (getAsnSequence(&p, (uint32)(extEnd - p), &fullExtLen) < 0) { + psTraceCrypto("getAsnSequence failure in extension parse\n"); + return PS_PARSE_FAIL; + } + extStart = p; +/* + Conforming CAs MUST support key identifiers, basic constraints, + key usage, and certificate policies extensions +*/ + if (extEnd - p < 1 || *p++ != ASN_OID) { + psTraceCrypto("Malformed extension header\n"); + return PS_PARSE_FAIL; + } + if (getAsnLength(&p, (uint32)(extEnd - p), &len) < 0 || + (uint32)(extEnd - p) < len) { + psTraceCrypto("Malformed extension length\n"); + return PS_PARSE_FAIL; + } + if ((oidlen = psParseOid(p, len, oid)) < 1) { + psTraceCrypto("Malformed extension OID\n"); + return PS_PARSE_FAIL; + } + noid = psFindOid(oid, oidlen); + p += len; +/* + Possible boolean value here for 'critical' id. It's a failure if a + critical extension is found that is not supported +*/ + critical = 0; + if (extEnd - p < 1) { + psTraceCrypto("Malformed extension length\n"); + return PS_PARSE_FAIL; + } + if (*p == ASN_BOOLEAN) { + p++; + if (extEnd - p < 2) { + psTraceCrypto("Error parsing critical id len for cert extension\n"); + return PS_PARSE_FAIL; + } + if (*p != 1) { + psTraceCrypto("Error parsing critical id for cert extension\n"); + return PS_PARSE_FAIL; + } + p++; + if (*p > 0) { + /* Officially DER TRUE must be 0xFF, openssl is more lax */ + if (*p != 0xFF) { + psTraceCrypto("Warning: DER BOOLEAN TRUE should be 0xFF\n"); + } + critical = 1; + } + p++; + } + if (extEnd - p < 1 || (*p++ != ASN_OCTET_STRING) || + getAsnLength(&p, (uint32)(extEnd - p), &len) < 0 || + (uint32)(extEnd - p) < len) { + psTraceCrypto("Expecting OCTET STRING in ext parse\n"); + return PS_PARSE_FAIL; + } + + /* Set bits 1..9 to indicate criticality of known extensions */ + if (critical) { + extensions->critFlags |= EXT_CRIT_FLAG(noid); + } + + switch (noid) { +/* + BasicConstraints ::= SEQUENCE { + cA BOOLEAN DEFAULT FALSE, + pathLenConstraint INTEGER (0..MAX) OPTIONAL } +*/ + case OID_ENUM(id_ce_basicConstraints): + if (getAsnSequence(&p, (uint32)(extEnd - p), &len) < 0) { + psTraceCrypto("Error parsing BasicConstraints extension\n"); + return PS_PARSE_FAIL; + } +/* + "This goes against PKIX guidelines but some CAs do it and some + software requires this to avoid interpreting an end user + certificate as a CA." + - OpenSSL certificate configuration doc + + basicConstraints=CA:FALSE +*/ + if (len == 0) { + break; + } +/* + Have seen some certs that don't include a cA bool. +*/ + if (*p == ASN_BOOLEAN) { + if (extEnd - p < 3) { + psTraceCrypto("Error parsing BC extension\n"); + return PS_PARSE_FAIL; + } + p++; + if (*p++ != 1) { + psTraceCrypto("Error parse BasicConstraints CA bool\n"); + return PS_PARSE_FAIL; + } + /* Officially DER TRUE must be 0xFF, openssl is more lax */ + if (*p > 0 && *p != 0xFF) { + psTraceCrypto("Warning: cA TRUE should be 0xFF\n"); + } + extensions->bc.cA = *p++; + } else { + extensions->bc.cA = 0; + } +/* + Now need to check if there is a path constraint. Only makes + sense if cA is true. If it's missing, there is no limit to + the cert path +*/ + if (*p == ASN_INTEGER) { + if (getAsnInteger(&p, (uint32)(extEnd - p), + &(extensions->bc.pathLenConstraint)) < 0) { + psTraceCrypto("Error parsing BasicConstraints pathLen\n"); + return PS_PARSE_FAIL; + } + } else { + extensions->bc.pathLenConstraint = -1; + } + break; + + case OID_ENUM(id_ce_subjectAltName): + if (getAsnSequence(&p, (uint32)(extEnd - p), &len) < 0) { + psTraceCrypto("Error parsing altSubjectName extension\n"); + return PS_PARSE_FAIL; + } + /* NOTE: The final limit parameter was introduced for this + case because a well known search engine site sends back + about 7 KB worth of subject alt names and that has created + memory problems for a couple users. Set the -1 here to + something reasonable (5) if you've found yourself here + for this memory reason */ + if (parseGeneralNames(pool, &p, len, extEnd, &extensions->san, + -1) < 0) { + psTraceCrypto("Error parsing altSubjectName names\n"); + return PS_PARSE_FAIL; + } + + break; + + case OID_ENUM(id_ce_keyUsage): +/* + KeyUsage ::= BIT STRING { + digitalSignature (0), + nonRepudiation (1), + keyEncipherment (2), + dataEncipherment (3), + keyAgreement (4), + keyCertSign (5), + cRLSign (6), + encipherOnly (7), + decipherOnly (8) } +*/ + if (*p++ != ASN_BIT_STRING) { + psTraceCrypto("Error parsing keyUsage extension\n"); + return PS_PARSE_FAIL; + } + if (getAsnLength(&p, (int32)(extEnd - p), &len) < 0 || + (uint32)(extEnd - p) < len) { + psTraceCrypto("Malformed keyUsage extension\n"); + return PS_PARSE_FAIL; + } + if (len < 2) { + psTraceCrypto("Malformed keyUsage extension\n"); + return PS_PARSE_FAIL; + } +/* + If the lenth is <= 3, then there might be a + KEY_USAGE_DECIPHER_ONLY (or maybe just some empty bytes). +*/ + if (len >= 3) { + if (p[2] == (KEY_USAGE_DECIPHER_ONLY >> 8) && p[0] == 7) { + extensions->keyUsageFlags |= KEY_USAGE_DECIPHER_ONLY; + } + } + extensions->keyUsageFlags |= p[1]; + p = p + len; + break; + + case OID_ENUM(id_ce_extKeyUsage): + if (getAsnSequence(&p, (int32)(extEnd - p), &fullExtLen) < 0) { + psTraceCrypto("Error parsing authKeyId extension\n"); + return PS_PARSE_FAIL; + } + save = p; + while (fullExtLen > 0) { + if (*p++ != ASN_OID) { + psTraceCrypto("Malformed extension header\n"); + return PS_PARSE_FAIL; + } + if (getAsnLength(&p, fullExtLen, &len) < 0 || + fullExtLen < len) { + psTraceCrypto("Malformed extension length\n"); + return PS_PARSE_FAIL; + } + if ((oidlen = psParseOid(p, len, oid)) < 1) { + psTraceCrypto("Malformed extension OID\n"); + return PS_PARSE_FAIL; + } + noid = psFindOid(oid, oidlen); + p += len; + if (fullExtLen < (uint32)(p - save)) { + psTraceCrypto("Inner OID parse fail EXTND_KEY_USAGE\n"); + return PS_PARSE_FAIL; + } + fullExtLen -= (p - save); + save = p; + switch (noid) { + case OID_ENUM(id_kp_serverAuth): + extensions->ekuFlags |= EXT_KEY_USAGE_TLS_SERVER_AUTH; + break; + case OID_ENUM(id_kp_clientAuth): + extensions->ekuFlags |= EXT_KEY_USAGE_TLS_CLIENT_AUTH; + break; + case OID_ENUM(id_kp_codeSigning): + extensions->ekuFlags |= EXT_KEY_USAGE_CODE_SIGNING; + break; + case OID_ENUM(id_kp_emailProtection): + extensions->ekuFlags |= EXT_KEY_USAGE_EMAIL_PROTECTION; + break; + case OID_ENUM(id_kp_timeStamping): + extensions->ekuFlags |= EXT_KEY_USAGE_TIME_STAMPING; + break; + case OID_ENUM(id_kp_OCSPSigning): + extensions->ekuFlags |= EXT_KEY_USAGE_OCSP_SIGNING; + break; + case OID_ENUM(id_ce_eku_anyExtendedKeyUsage): + extensions->ekuFlags |= EXT_KEY_USAGE_ANY; + break; + default: + psTraceCrypto("WARNING: Unknown EXT_KEY_USAGE:"); + psTraceOid(oid, oidlen); + break; + } /* end switch */ + } + break; + +#ifdef USE_FULL_CERT_PARSE + + case OID_ENUM(id_ce_nameConstraints): + if (critical) { + /* We're going to fail if critical since no real + pattern matching is happening yet */ + psTraceCrypto("ERROR: critical nameConstraints unsupported\n"); + return PS_PARSE_FAIL; + } + if (getAsnSequence(&p, (int32)(extEnd - p), &fullExtLen) < 0) { + psTraceCrypto("Error parsing authKeyId extension\n"); + return PS_PARSE_FAIL; + } + while (fullExtLen > 0) { + save = p; + + if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { + /* permittedSubtrees */ + p++; + nc = 0; + } + if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) { + /* excludedSubtrees */ + p++; + nc = 1; + } + subExtLen = 0; + if (getAsnLength(&p, (uint32)(extEnd - p), &subExtLen) < 0 || + subExtLen < 1 || (uint32)(extEnd - p) < subExtLen) { + psTraceCrypto("ASN get len error in nameConstraint\n"); + return PS_PARSE_FAIL; + } + if (fullExtLen < (subExtLen + (p - save))) { + psTraceCrypto("fullExtLen parse fail nameConstraint\n"); + return PS_PARSE_FAIL; + } + fullExtLen -= subExtLen + (p - save); + while (subExtLen > 0) { + subSave = p; + if (getAsnSequence(&p, (int32)(extEnd - p), &len) < 0) { + psTraceCrypto("Error parsing nameConst ext\n"); + return PS_PARSE_FAIL; + } + if (subExtLen < (len + (p - subSave))) { + psTraceCrypto("subExtLen fail nameConstraint\n"); + return PS_PARSE_FAIL; + } + subExtLen -= len + (p - subSave); + if (nc == 0) { + if (parseGeneralNames(pool, &p, len, extEnd, + &extensions->nameConstraints.permitted, -1) <0){ + psTraceCrypto("Error parsing nameConstraint\n"); + return PS_PARSE_FAIL; + } + } else { + if (parseGeneralNames(pool, &p, len, extEnd, + &extensions->nameConstraints.excluded, -1) < 0){ + psTraceCrypto("Error parsing nameConstraint\n"); + return PS_PARSE_FAIL; + } + } + } + } + break; + +#ifdef USE_CRL + case OID_ENUM(id_ce_cRLDistributionPoints): + + if (getAsnSequence(&p, (int32)(extEnd - p), &fullExtLen) < 0) { + psTraceCrypto("Error parsing authKeyId extension\n"); + return PS_PARSE_FAIL; + } + + while (fullExtLen > 0) { + save = p; + if (getAsnSequence(&p, (uint32)(extEnd - p), &len) < 0) { + psTraceCrypto("getAsnSequence fail in crldist parse\n"); + return PS_PARSE_FAIL; + } + if (fullExtLen < (len + (p - save))) { + psTraceCrypto("fullExtLen parse fail crldist\n"); + return PS_PARSE_FAIL; + } + fullExtLen -= len + (p - save); + /* All memebers are optional */ + if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { + /* DistributionPointName */ + p++; + if (getAsnLength(&p, (uint32)(extEnd - p), &len) < 0 || + len < 1 || (uint32)(extEnd - p) < len) { + psTraceCrypto("ASN get len error in CRL extension\n"); + return PS_PARSE_FAIL; + } + + if ((*p & 0xF) == 0) { /* fullName (GeneralNames) */ + p++; + if (getAsnLength(&p, (uint32)(extEnd - p), &len) < 0 + || len < 1 || (uint32)(extEnd - p) < len) { + psTraceCrypto("ASN get len error in CRL extension\n"); + return PS_PARSE_FAIL; + } + if (parseGeneralNames(pool, &p, len, extEnd, + &extensions->crlDist, -1) > 0) { + psTraceCrypto("dist gen name parse fail\n"); + return PS_PARSE_FAIL; + } + } else if ((*p & 0xF) == 1) { /* RelativeDistName */ + p++; + /* RelativeDistName not parsed */ + if (getAsnLength(&p, (uint32)(extEnd - p), &len) < 0 + || len < 1 || (uint32)(extEnd - p) < len) { + psTraceCrypto("ASN get len error in CRL extension\n"); + return PS_PARSE_FAIL; + } + p += len; + } else { + psTraceCrypto("DistributionPointName parse fail\n"); + return PS_PARSE_FAIL; + } + } + if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) { + p++; + /* ReasonFlags not parsed */ + if (getAsnLength(&p, (uint32)(extEnd - p), &len) < 0 || + len < 1 || (uint32)(extEnd - p) < len) { + psTraceCrypto("ASN get len error in CRL extension\n"); + return PS_PARSE_FAIL; + } + p += len; + } + if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)) { + p++; + /* General Names not parsed */ + if (getAsnLength(&p, (uint32)(extEnd - p), &len) < 0 || + len < 1 || (uint32)(extEnd - p) < len) { + psTraceCrypto("ASN get len error in CRL extension\n"); + return PS_PARSE_FAIL; + } + p += len; + } + } + break; +#endif /* USE_CRL */ +#endif /* FULL_CERT_PARSE */ + + case OID_ENUM(id_ce_authorityKeyIdentifier): +/* + AuthorityKeyIdentifier ::= SEQUENCE { + keyIdentifier [0] KeyIdentifier OPTIONAL, + authorityCertIssuer [1] GeneralNames OPTIONAL, + authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } + + KeyIdentifier ::= OCTET STRING +*/ + if (getAsnSequence(&p, (int32)(extEnd - p), &len) < 0) { + psTraceCrypto("Error parsing authKeyId extension\n"); + return PS_PARSE_FAIL; + } + /* Have seen a cert that has a zero length ext here. Let it pass. */ + if (len == 0) { + break; + } + /* All members are optional */ + if (*p == (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 0)) { + p++; + if (getAsnLength(&p, (int32)(extEnd - p), + &extensions->ak.keyLen) < 0 || + (uint32)(extEnd - p) < extensions->ak.keyLen) { + psTraceCrypto("Error keyLen in authKeyId extension\n"); + return PS_PARSE_FAIL; + } + extensions->ak.keyId =psMalloc(pool, extensions->ak.keyLen); + if (extensions->ak.keyId == NULL) { + psError("Mem allocation err: extensions->ak.keyId\n"); + return PS_MEM_FAIL; + } + memcpy(extensions->ak.keyId, p, extensions->ak.keyLen); + p = p + extensions->ak.keyLen; + } + if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) { + p++; + if (getAsnLength(&p, (int32)(extEnd - p), &len) < 0 || + len < 1 || (uint32)(extEnd - p) < len) { + psTraceCrypto("ASN get len error in authKeyId extension\n"); + return PS_PARSE_FAIL; + } + if ((*p ^ ASN_CONTEXT_SPECIFIC ^ ASN_CONSTRUCTED) != 4) { + /* We are just dealing with DN formats here */ + psTraceIntCrypto("Error auth key-id name type: %d\n", + *p ^ ASN_CONTEXT_SPECIFIC ^ ASN_CONSTRUCTED); + return PS_PARSE_FAIL; + } + p++; + if (getAsnLength(&p, (int32)(extEnd - p), &len) < 0 || + (uint32)(extEnd - p) < len) { + psTraceCrypto("ASN get len error2 in authKeyId extension\n"); + return PS_PARSE_FAIL; + } + if (psX509GetDNAttributes(pool, &p, (int32)(extEnd - p), + &(extensions->ak.attribs), 0) < 0) { + psTraceCrypto("Error parsing ak.attribs\n"); + return PS_PARSE_FAIL; + } + } + if ((*p == (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 2)) || + (*p == ASN_INTEGER)){ +/* + Treat as a serial number (not a native INTEGER) +*/ + if (getSerialNum(pool, &p, (int32)(extEnd - p), + &(extensions->ak.serialNum), &len) < 0) { + psTraceCrypto("Error parsing ak.serialNum\n"); + return PS_PARSE_FAIL; + } + extensions->ak.serialNumLen = len; + } + break; + + case OID_ENUM(id_ce_subjectKeyIdentifier): +/* + The value of the subject key identifier MUST be the value + placed in the key identifier field of the Auth Key Identifier + extension of certificates issued by the subject of + this certificate. +*/ + if (*p++ != ASN_OCTET_STRING || getAsnLength(&p, + (int32)(extEnd - p), &(extensions->sk.len)) < 0 || + (uint32)(extEnd - p) < extensions->sk.len) { + psTraceCrypto("Error parsing subjectKeyId extension\n"); + return PS_PARSE_FAIL; + } + extensions->sk.id = psMalloc(pool, extensions->sk.len); + if (extensions->sk.id == NULL) { + psError("Memory allocation error extensions->sk.id\n"); + return PS_MEM_FAIL; + } + memcpy(extensions->sk.id, p, extensions->sk.len); + p = p + extensions->sk.len; + break; + + /* These extensions are known but not handled */ + case OID_ENUM(id_ce_certificatePolicies): + case OID_ENUM(id_ce_policyMappings): + case OID_ENUM(id_ce_issuerAltName): + case OID_ENUM(id_ce_subjectDirectoryAttributes): + case OID_ENUM(id_ce_policyConstraints): + case OID_ENUM(id_ce_inhibitAnyPolicy): + case OID_ENUM(id_ce_freshestCRL): + case OID_ENUM(id_pe_subjectInfoAccess): + default: + /* Unsupported or skipping because USE_FULL_CERT_PARSE undefd */ + if (critical) { + psTraceCrypto("Unsupported critical ext encountered: "); + psTraceOid(oid, oidlen); +#ifndef ALLOW_UNKNOWN_CRITICAL_EXTENSIONS + _psTrace("An unsupported critical extension was " + "encountered. X.509 specifications say " + "connections must be terminated in this case. " + "Define ALLOW_UNKNOWN_CRITICAL_EXTENSIONS to " + "bypass this rule if testing and email Inside " + "support to inquire about this extension.\n\n"); + return PS_PARSE_FAIL; +#else +#ifdef WIN32 +#pragma message("IGNORING UNKNOWN CRITICAL EXTENSIONS IS A SECURITY RISK") +#else +#warning "IGNORING UNKNOWN CRITICAL EXTENSIONS IS A SECURITY RISK" +#endif +#endif + } + p++; +/* + Skip over based on the length reported from the ASN_SEQUENCE + surrounding the entire extension. It is not a guarantee that + the value of the extension itself will contain it's own length. +*/ + p = p + (fullExtLen - (p - extStart)); + break; + } + } + *pp = p; + return 0; +} + +/******************************************************************************/ +/* + Although a certificate serial number is encoded as an integer type, that + doesn't prevent it from being abused as containing a variable length + binary value. Get it here. +*/ +int32_t getSerialNum(psPool_t *pool, const unsigned char **pp, uint16_t len, + unsigned char **sn, uint16_t *snLen) +{ + const unsigned char *p = *pp; + uint16_t vlen; + + if ((*p != (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 2)) && + (*p != ASN_INTEGER)) { + psTraceCrypto("X.509 getSerialNum failed on first bytes\n"); + return PS_PARSE_FAIL; + } + p++; + + if (len < 1 || getAsnLength(&p, len - 1, &vlen) < 0 || (len - 1) < vlen) { + psTraceCrypto("ASN getSerialNum failed\n"); + return PS_PARSE_FAIL; + } + *snLen = vlen; + + if (vlen > 0) { + *sn = psMalloc(pool, vlen); + if (*sn == NULL) { + psError("Memory allocation failure in getSerialNum\n"); + return PS_MEM_FAIL; + } + memcpy(*sn, p, vlen); + p += vlen; + } + *pp = p; + return PS_SUCCESS; +} + +/******************************************************************************/ +/** + Explicit value encoding has an additional tag layer. + */ +static int32_t getExplicitVersion(const unsigned char **pp, uint16_t len, + int32_t expVal, int32_t *val) +{ + const unsigned char *p = *pp; + uint16_t exLen; + + if (len < 1) { + psTraceCrypto("Invalid length to getExplicitVersion\n"); + return PS_PARSE_FAIL; + } +/* + This is an optional value, so don't error if not present. The default + value is version 1 +*/ + if (*p != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | expVal)) { + *val = 0; + return PS_SUCCESS; + } + p++; + if (getAsnLength(&p, len - 1, &exLen) < 0 || (len - 1) < exLen) { + psTraceCrypto("getAsnLength failure in getExplicitVersion\n"); + return PS_PARSE_FAIL; + } + if (getAsnInteger(&p, exLen, val) < 0) { + psTraceCrypto("getAsnInteger failure in getExplicitVersion\n"); + return PS_PARSE_FAIL; + } + *pp = p; + return PS_SUCCESS; +} + +/******************************************************************************/ +/** + Verify a string has nearly valid date range format and length. + */ +static unsigned char asciidate(const unsigned char *c, unsigned int utctime) +{ + if (utctime != ASN_UTCTIME) { /* 4 character year */ + if (*c < '1' && *c > '2') return 0; c++; /* Year 1900 - 2999 */ + if (*c < '0' && *c > '9') return 0; c++; + } + if (*c < '0' && *c > '9') return 0; c++; + if (*c < '0' && *c > '9') return 0; c++; + if (*c < '0' && *c > '1') return 0; c++; /* Month 00 - 19 */ + if (*c < '0' && *c > '9') return 0; c++; + if (*c < '0' && *c > '3') return 0; c++; /* Day 00 - 39 */ + if (*c < '0' && *c > '9') return 0; + return 1; +} + +/******************************************************************************/ +/** + Tests if the certificate was issued before the given date. + Because there is no actual issuance date in the certificate, we use the + 'notBefore' date (the initial date the certificate is valid) as the + effective issuance date. + @security This api is used to be more lenient on certificates that are still + valid, but were created before certain more strict certificate rules + were specified. + + @param[in] rfc The RFC to check against. + @param[in] cert The cert to check the issuing date on. + @return 1 if yes, 0 if no, -1 on parse error. +*/ +static int32 issuedBefore(rfc_e rfc, const psX509Cert_t *cert) +{ + unsigned char *c; + unsigned int y; + unsigned short m; + + /* Validate the 'not before' date */ + if ((c = (unsigned char *)cert->notBefore) == NULL) { + return PS_FAILURE; + } + /* UTCTIME, defined in 1982, has just a 2 digit year */ + /* year as unsigned int handles over/underflows */ + if (cert->notBeforeTimeType == ASN_UTCTIME) { + if (!asciidate(c, ASN_UTCTIME)) { + return PS_FAILURE; + } + y = 2000 + 10 * (c[0] - '0') + (c[1] - '0'); c += 2; + /* Years from '96 through '99 are in the 1900's */ + if (y >= 2096) { + y -= 100; + } + } else { + if (!asciidate(c, 0)) { + return PS_FAILURE; + } + y = 1000 * (c[0] - '0') + 100 * (c[1] - '0') + + 10 * (c[2] - '0') + (c[3] - '0'); c += 4; + } + /* month as unsigned short handles over/underflows */ + m = 10 * (c[0] - '0') + (c[1] - '0'); + /* Must have been issued at least when X509v3 was added */ + if (y < 1996 || m < 1 || m > 12) { + return -1; + } + switch (rfc) { + case RFC_6818: + if (y < 2013) { /* No month check needed for Jan */ + return 1; + } + return 0; + case RFC_5280: + if (y < 2008 || (y == 2008 && m < 5)) { + return 1; + } + return 0; + case RFC_3280: + if (y < 2002 || (y == 2002 && m < 4)) { + return 1; + } + return 0; + case RFC_2459: + if (y < 1999) { /* No month check needed for Jan */ + return 1; + } + return 0; + default: + return -1; + } + return -1; +} + +/******************************************************************************/ +/** + Validate the dates in the cert to machine date. + SECURITY - always succeeds on systems without date support + Returns + 0 on success + PS_CERT_AUTH_FAIL_DATE if date is out of range + PS_FAILURE on parse error +*/ +static int32 validateDateRange(psX509Cert_t *cert) +{ +#ifdef POSIX + struct tm t; + time_t rawtime; + unsigned char *c; + unsigned int y; + unsigned short m, d; + + time(&rawtime); + localtime_r(&rawtime, &t); + /* Localtime does months from 0-11 and (year-1900)! Normalize it. */ + t.tm_mon++; + t.tm_year += 1900; + + /* Validate the 'not before' date */ + if ((c = (unsigned char *)cert->notBefore) == NULL) { + return PS_FAILURE; + } + /* UTCTIME, defined in 1982, has just a 2 digit year */ + /* year as unsigned int handles over/underflows */ + if (cert->notBeforeTimeType == ASN_UTCTIME) { + if (!asciidate(c, ASN_UTCTIME)) { + return PS_FAILURE; + } + y = 2000 + 10 * (c[0] - '0') + (c[1] - '0'); c += 2; + /* Years from '96 through '99 are in the 1900's */ + if (y >= 2096) { + y -= 100; + } + } else { + if (!asciidate(c, 0)) { + return PS_FAILURE; + } + y = 1000 * (c[0] - '0') + 100 * (c[1] - '0') + + 10 * (c[2] - '0') + (c[3] - '0'); c += 4; + } + /* month,day as unsigned short handles over/underflows */ + m = 10 * (c[0] - '0') + (c[1] - '0'); c += 2; + d = 10 * (c[0] - '0') + (c[1] - '0'); + /* Must have been issued at least when X509v3 was added */ + if (y < 1996 || m < 1 || m > 12 || d < 1 || d > 31) { + return PS_FAILURE; + } + if (t.tm_year < (int)y) { + cert->authFailFlags |= PS_CERT_AUTH_FAIL_DATE_FLAG; + } else if (t.tm_year == (int)y) { + if (t.tm_mon < m) { + cert->authFailFlags |= PS_CERT_AUTH_FAIL_DATE_FLAG; + } else if (t.tm_mon == m && t.tm_mday < d) { + cert->authFailFlags |= PS_CERT_AUTH_FAIL_DATE_FLAG; + } + } + + /* Validate the 'not after' date */ + if ((c = (unsigned char *)cert->notAfter) == NULL) { + return PS_FAILURE; + } + /* UTCTIME, defined in 1982, has just a 2 digit year */ + /* year as unsigned int handles over/underflows */ + if (cert->notAfterTimeType == ASN_UTCTIME) { + if (!asciidate(c, ASN_UTCTIME)) { + return PS_FAILURE; + } + y = 2000 + 10 * (c[0] - '0') + (c[1] - '0'); c += 2; + /* Years from '96 through '99 are in the 1900's */ + if (y >= 2096) { + y -= 100; + } + } else { + if (!asciidate(c, 0)) { + return PS_FAILURE; + } + y = 1000 * (c[0] - '0') + 100 * (c[1] - '0') + + 10 * (c[2] - '0') + (c[3] - '0'); c += 4; + } + /* month,day as unsigned short handles over/underflows */ + m = 10 * (c[0] - '0') + (c[1] - '0'); c += 2; + d = 10 * (c[0] - '0') + (c[1] - '0'); + /* Must have been issued at least when X509v3 was added */ + if (y < 1996 || m < 1 || m > 12 || d < 1 || d > 31) { + return PS_FAILURE; + } + if (t.tm_year > (int)y) { + cert->authFailFlags |= PS_CERT_AUTH_FAIL_DATE_FLAG; + } else if (t.tm_year == (int)y) { + if (t.tm_mon > m) { + cert->authFailFlags |= PS_CERT_AUTH_FAIL_DATE_FLAG; + } else if (t.tm_mon == m && t.tm_mday > d) { + cert->authFailFlags |= PS_CERT_AUTH_FAIL_DATE_FLAG; + } + } + return 0; +#else +/* Warn if we are skipping the date validation checks. */ +#ifdef WIN32 +#pragma message("CERTIFICATE DATE VALIDITY NOT SUPPORTED ON THIS PLATFORM.") +#else +#warning "CERTIFICATE DATE VALIDITY NOT SUPPORTED ON THIS PLATFORM." +#endif + cert->authFailFlags |= PS_CERT_AUTH_FAIL_DATE_FLAG; + return 0; +#endif /* POSIX */ +} + +/******************************************************************************/ +/* + Implementation specific date parser. Does not actually verify the date +*/ +static int32_t getTimeValidity(psPool_t *pool, const unsigned char **pp, + uint16_t len, int32_t *notBeforeTimeType, + int32_t *notAfterTimeType, + char **notBefore, char **notAfter) +{ + const unsigned char *p = *pp, *end; + uint16_t seqLen, timeLen; + + end = p + len; + if (len < 1 || *(p++) != (ASN_SEQUENCE | ASN_CONSTRUCTED) || + getAsnLength(&p, len - 1, &seqLen) < 0 || + (uint32)(end - p) < seqLen) { + psTraceCrypto("getTimeValidity failed on inital parse\n"); + return PS_PARSE_FAIL; + } +/* + Have notBefore and notAfter times in UTCTime or GeneralizedTime formats +*/ + if ((end - p) < 1 || ((*p != ASN_UTCTIME) && (*p != ASN_GENERALIZEDTIME))) { + psTraceCrypto("Malformed validity\n"); + return PS_PARSE_FAIL; + } + *notBeforeTimeType = *p; + p++; +/* + Allocate them as null terminated strings +*/ + if (getAsnLength(&p, seqLen, &timeLen) < 0 || (uint32)(end - p) < timeLen) { + psTraceCrypto("Malformed validity 2\n"); + return PS_PARSE_FAIL; + } + *notBefore = psMalloc(pool, timeLen + 1); + if (*notBefore == NULL) { + psError("Memory allocation error in getTimeValidity for notBefore\n"); + return PS_MEM_FAIL; + } + memcpy(*notBefore, p, timeLen); + (*notBefore)[timeLen] = '\0'; + p = p + timeLen; + if ((end - p) < 1 || ((*p != ASN_UTCTIME) && (*p != ASN_GENERALIZEDTIME))) { + psTraceCrypto("Malformed validity 3\n"); + return PS_PARSE_FAIL; + } + *notAfterTimeType = *p; + p++; + if (getAsnLength(&p, seqLen - timeLen, &timeLen) < 0 || + (uint32)(end - p) < timeLen) { + psTraceCrypto("Malformed validity 4\n"); + return PS_PARSE_FAIL; + } + *notAfter = psMalloc(pool, timeLen + 1); + if (*notAfter == NULL) { + psError("Memory allocation error in getTimeValidity for notAfter\n"); + return PS_MEM_FAIL; + } + memcpy(*notAfter, p, timeLen); + (*notAfter)[timeLen] = '\0'; + p = p + timeLen; + + *pp = p; + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Could be optional. If the tag doesn't contain the value from the left + of the IMPLICIT keyword we don't have a match and we don't incr the pointer. +*/ +static int32_t getImplicitBitString(psPool_t *pool, const unsigned char **pp, + uint16_t len, int32_t impVal, unsigned char **bitString, + uint16_t *bitLen) +{ + const unsigned char *p = *pp; + int32_t ignore_bits; + + if (len < 1) { + psTraceCrypto("Initial parse error in getImplicitBitString\n"); + return PS_PARSE_FAIL; + } +/* + We don't treat this case as an error, because of the optional nature. +*/ + if (*p != (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | impVal)) { + return PS_SUCCESS; + } + + p++; + if (getAsnLength(&p, len, bitLen) < 0) { + psTraceCrypto("Malformed implicitBitString\n"); + return PS_PARSE_FAIL; + } + ignore_bits = *p++; + (*bitLen)--; + psAssert(ignore_bits == 0); + + *bitString = psMalloc(pool, *bitLen); + if (*bitString == NULL) { + psError("Memory allocation error in getImplicitBitString\n"); + return PS_MEM_FAIL; + } + memcpy(*bitString, p, *bitLen); + *pp = p + *bitLen; + return PS_SUCCESS; +} + + +/******************************************************************************/ +/* + Implementations of this specification MUST be prepared to receive + the following standard attribute types in issuer names: + country, organization, organizational-unit, distinguished name qualifier, + state or province name, and common name +*/ +int32_t psX509GetDNAttributes(psPool_t *pool, const unsigned char **pp, + uint16_t len, x509DNattributes_t *attribs, uint32_t flags) +{ + const unsigned char *p = *pp; + const unsigned char *dnEnd, *dnStart, *moreInSetPtr; + int32 id, stringType, checkHiddenNull, moreInSet; + uint16_t llen, setlen, arcLen; + char *stringOut; +#ifdef USE_SHA1 + psSha1_t hash; +#elif defined(USE_SHA256) + psSha256_t hash; +#else +//TODO can we avoid hash altogether? We do not free/finalize the hash ctx on error return below. +#error USE_SHA1 or USE_SHA256 must be defined +#endif + + dnStart = p; + if (getAsnSequence(&p, len, &llen) < 0) { + return PS_PARSE_FAIL; + } + dnEnd = p + llen; + +/* + The possibility of a CERTIFICATE_REQUEST message. Set aside full DN +*/ + if (flags & CERT_STORE_DN_BUFFER) { + attribs->dnencLen = (uint32)(dnEnd - dnStart); + attribs->dnenc = psMalloc(pool, attribs->dnencLen); + if (attribs->dnenc == NULL) { + psError("Memory allocation error in getDNAttributes\n"); + return PS_MEM_FAIL; + } + memcpy(attribs->dnenc, dnStart, attribs->dnencLen); + } + moreInSet = 0; + while (p < dnEnd) { + if (getAsnSet(&p, (uint32)(dnEnd - p), &setlen) < 0) { + psTraceCrypto("Malformed DN attributes\n"); + return PS_PARSE_FAIL; + } + /* 99.99% of certs have one attribute per SET but did come across + one that nested a couple at this level so let's watch out for + that with the "moreInSet" logic */ +MORE_IN_SET: + moreInSetPtr = p; + if (getAsnSequence(&p, (uint32)(dnEnd - p), &llen) < 0) { + psTraceCrypto("Malformed DN attributes 2\n"); + return PS_PARSE_FAIL; + } + if (moreInSet > 0) { + moreInSet -= llen + (int32)(p - moreInSetPtr); + } else { + if (setlen != llen + (int32)(p - moreInSetPtr)) { + moreInSet = setlen - (int32)(p - moreInSetPtr) - llen; + } + } + if (dnEnd <= p || (*(p++) != ASN_OID) || + getAsnLength(&p, (uint32)(dnEnd - p), &arcLen) < 0 || + (uint32)(dnEnd - p) < arcLen) { + psTraceCrypto("Malformed DN attributes 3\n"); + return PS_PARSE_FAIL; + } +/* + id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} + id-at-commonName OBJECT IDENTIFIER ::= {id-at 3} + id-at-countryName OBJECT IDENTIFIER ::= {id-at 6} + id-at-localityName OBJECT IDENTIFIER ::= {id-at 7} + id-at-stateOrProvinceName OBJECT IDENTIFIER ::= {id-at 8} + id-at-organizationName OBJECT IDENTIFIER ::= {id-at 10} + id-at-organizationalUnitName OBJECT IDENTIFIER ::= {id-at 11} +*/ + *pp = p; +/* + Currently we are skipping OIDs not of type {joint-iso-ccitt(2) ds(5) 4} + However, we could be dealing with an OID we MUST support per RFC. + domainComponent is one such example. +*/ + if (dnEnd - p < 2) { + psTraceCrypto("Malformed DN attributes 4\n"); + return PS_LIMIT_FAIL; + } + /* check id-at */ + if ((*p++ != 85) || (*p++ != 4) ) { + /* OIDs we are not parsing */ + p = *pp; +/* + Move past the OID and string type, get data size, and skip it. + NOTE: Have had problems parsing older certs in this area. +*/ + if ((uint32)(dnEnd - p) < arcLen + 1) { + psTraceCrypto("Malformed DN attributes 5\n"); + return PS_LIMIT_FAIL; + } + p += arcLen + 1; + if (getAsnLength(&p, (uint32)(dnEnd - p), &llen) < 0 || + (uint32)(dnEnd - p) < llen) { + psTraceCrypto("Malformed DN attributes 6\n"); + return PS_PARSE_FAIL; + } + p = p + llen; + continue; + } + /* Next are the id of the attribute type and the ASN string type */ + if (arcLen != 3 || dnEnd - p < 2) { + psTraceCrypto("Malformed DN attributes 7\n"); + return PS_LIMIT_FAIL; + } + id = (int32)*p++; + /* Done with OID parsing */ + stringType = (int32)*p++; + + if (getAsnLength(&p, (uint32)(dnEnd - p), &llen) < 0 || + (uint32)(dnEnd - p) < llen) { + psTraceCrypto("Malformed DN attributes 8\n"); + return PS_LIMIT_FAIL; + } +/* + For the known 8-bit character string types, we flag that we want + to test for a hidden null in the middle of the string to address the + issue of www.goodguy.com\0badguy.com. For BMPSTRING, the user will + have to validate against the xLen member for such abuses. +*/ + checkHiddenNull = PS_FALSE; + switch (stringType) { + case ASN_PRINTABLESTRING: + case ASN_UTF8STRING: + case ASN_IA5STRING: + checkHiddenNull = PS_TRUE; + case ASN_T61STRING: + case ASN_BMPSTRING: + case ASN_BIT_STRING: + stringOut = psMalloc(pool, llen + 2); + if (stringOut == NULL) { + psError("Memory allocation error in getDNAttributes\n"); + return PS_MEM_FAIL; + } + memcpy(stringOut, p, llen); +/* + Terminate with 2 null chars to support standard string + manipulations with any potential unicode types. +*/ + stringOut[llen] = '\0'; + stringOut[llen + 1] = '\0'; + + if (checkHiddenNull) { + if ((uint32)strlen(stringOut) != llen) { + psFree(stringOut, pool); + psTraceCrypto("Malformed DN attributes 9\n"); + return PS_PARSE_FAIL; + } + } + + p = p + llen; + llen += 2; /* Add the two null bytes for length assignments */ + break; + default: + psTraceIntCrypto("Unsupported DN attrib type %d\n", stringType); + return PS_UNSUPPORTED_FAIL; + } + + switch (id) { + case ATTRIB_COUNTRY_NAME: + if (attribs->country) { + psFree(attribs->country, pool); + } + attribs->country = stringOut; + attribs->countryType = (short)stringType; + attribs->countryLen = (short)llen; + break; + case ATTRIB_STATE_PROVINCE: + if (attribs->state) { + psFree(attribs->state, pool); + } + attribs->state = stringOut; + attribs->stateType = (short)stringType; + attribs->stateLen = (short)llen; + break; + case ATTRIB_LOCALITY: + if (attribs->locality) { + psFree(attribs->locality, pool); + } + attribs->locality = stringOut; + attribs->localityType = (short)stringType; + attribs->localityLen = (short)llen; + break; + case ATTRIB_ORGANIZATION: + if (attribs->organization) { + psFree(attribs->organization, pool); + } + attribs->organization = stringOut; + attribs->organizationType = (short)stringType; + attribs->organizationLen = (short)llen; + break; + case ATTRIB_ORG_UNIT: + if (attribs->orgUnit) { + psFree(attribs->orgUnit, pool); + } + attribs->orgUnit = stringOut; + attribs->orgUnitType = (short)stringType; + attribs->orgUnitLen = (short)llen; + break; + case ATTRIB_COMMON_NAME: + if (attribs->commonName) { + psFree(attribs->commonName, pool); + } + attribs->commonName = stringOut; + attribs->commonNameType = (short)stringType; + attribs->commonNameLen = (short)llen; + break; + default: + /* Not a MUST support, so just ignore unknown */ + psFree(stringOut, pool); + stringOut = NULL; + break; + } + if (moreInSet) { + goto MORE_IN_SET; + } + } + /* Hash is used to quickly compare DNs */ +#ifdef USE_SHA1 + psSha1Init(&hash); + psSha1Update(&hash, dnStart, (dnEnd - dnStart)); + psSha1Final(&hash, (unsigned char*)attribs->hash); +#else + psSha256Init(&hash); + psSha256Update(&hash, dnStart, (dnEnd - dnStart)); + psSha256Final(&hash, (unsigned char*)attribs->hash); +#endif + *pp = p; + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Free helper +*/ +void psX509FreeDNStruct(x509DNattributes_t *dn, psPool_t *allocPool) +{ + if (dn->country) psFree(dn->country, allocPool); + if (dn->state) psFree(dn->state, allocPool); + if (dn->locality) psFree(dn->locality, allocPool); + if (dn->organization) psFree(dn->organization, allocPool); + if (dn->orgUnit) psFree(dn->orgUnit, allocPool); + if (dn->commonName) psFree(dn->commonName, allocPool); + if (dn->dnenc) psFree(dn->dnenc, allocPool); +} + + +/******************************************************************************/ +/* + Fundamental routine to test whether the supplied issuerCert issued + the supplied subjectCert. There are currently two tests that are + performed here: + 1. A strict SHA1 hash comparison of the Distinguished Name details + 2. A test of the public key cryptographic cert signature + + subjectCert may be a chain. Cert chains must always be passed with + the child-most as the first in the list (the 'next' structure member + points to the parent). The authentication of the entire chain + will be tested before the issuerCert is used to authenticate the + parent-most certificate + + issuerCert will always be a treated as a single certificate even if it + is a chain + + If there is no issuerCert the parent-most subejct cert will always + be tested as a self-signed CA certificate. + + So there are three uses: + 1. Test a cert was issued by another (single subjectCert, single issuerCert) + 1. Test a self signed cert (single cert to subjectCert, no issuerCert) + 2. Test a CA terminated chain (cert chain to subjectCert, no issuerCert) + + This function exits with a failure code on the first authentication + that doesn't succeed. The 'authStatus' members may be examined for more + information of where the authentication failed. + + The 'authStatus' member of the issuerCert will be set to PS_FALSE + since it will not be authenticated. + + The 'authStatus' members of the subjectCert structures will always + be reset to PS_FALSE when this routine is called and set to PS_TRUE + when authenticated. Any error during the authentication will set the + current subject cert 'authStatus' member to PS_CERT_AUTH_FAIL and the + function will return with an error code. + + Return codes: + PS_SUCCESS - yes + + PS_CERT_AUTH_FAIL - nope. these certs are not a match + PS_UNSUPPORTED_FAIL - unrecognized cert format + PS_ARG_FAIL - local, psRsaDecryptPub + PS_LIMIT_FAIL - psRsaDecryptPub + PS_FAILURE - internal psRsaDecryptPub failure + + There is nothing for the caller to free at the completion of this + routine. +*/ +int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert, + psX509Cert_t *issuerCert, psX509Cert_t **foundIssuer, + void *hwCtx, void *poolUserPtr) +{ + psX509Cert_t *ic, *sc; + int32 sigType, rc; + uint32 sigLen; + void *rsaData; +#ifdef USE_ECC + int32 sigStat; +#endif /* USE_ECC */ +#ifdef USE_RSA + unsigned char sigOut[10 + MAX_HASH_SIZE + 9]; /* Max size */ + unsigned char *tempSig = NULL; +#endif /* USE_RSA */ + psPool_t *pkiPool = NULL; +#ifdef USE_CRL + x509revoked_t *curr, *next; +#endif +#ifdef USE_PKCS1_PSS + uint16_t pssLen; +#endif + + rc = 0; + sigLen = 0; + if (subjectCert == NULL) { + psTraceCrypto("No subject cert given to psX509AuthenticateCert\n"); + return PS_ARG_FAIL; + } + +/* + Determine what we've been passed +*/ + if (issuerCert == NULL) { + /* reset auth flags in subjectCert chain and find first sc and ic */ + sc = subjectCert; + while (sc) { + sc->authStatus = PS_FALSE; + sc = sc->next; + } + /* Now see if this is a chain or just a single cert */ + sc = subjectCert; + if (sc->next == NULL) { + ic = sc; /* A single subject cert for self-signed test */ + } else { + ic = sc->next; + } + } else { + issuerCert->authStatus = PS_FALSE; + ic = issuerCert; /* Easy case of single subject and single issuer */ + sc = subjectCert; + } + +/* + Error on first problem seen and set the subject status to FAIL +*/ + while (ic) { +/* + Certificate authority constraint only available in version 3 certs. + Only parsing version 3 certs by default though. +*/ + if ((ic->version > 1) && (ic->extensions.bc.cA <= 0)) { + if (sc != ic) { + psTraceCrypto("Issuer does not have basicConstraint CA permissions\n"); + sc->authStatus = PS_CERT_AUTH_FAIL_BC; + return PS_CERT_AUTH_FAIL_BC; + } + } + +/* + Use sha1 hash of issuer fields computed at parse time to compare +*/ + if (memcmp(sc->issuer.hash, ic->subject.hash, SHA1_HASH_SIZE) != 0) { + if (sc == ic) { + psTraceCrypto("Info: not a self-signed certificate\n"); + } else { + //psTraceCrypto("Issuer DN attributes do not match subject\n"); + } + sc->authStatus = PS_CERT_AUTH_FAIL_DN; + return PS_CERT_AUTH_FAIL_DN; + } + +#ifdef USE_CRL + /* Does this issuer have a list of revoked serial numbers that needs + to be checked? */ + if (ic->revoked) { + curr = ic->revoked; + while (curr != NULL) { + next = curr->next; + if (curr->serialLen == sc->serialNumberLen) { + if (memcmp(curr->serial, sc->serialNumber, curr->serialLen) + == 0) { + sc->authStatus = PS_CERT_AUTH_FAIL_REVOKED; + return -1; + } + } + curr = next; + } + + } +#endif + +/* + Signature confirmation + The sigLen is the ASN.1 size in bytes for encoding the hash. + The magic 10 is comprised of the SEQUENCE and ALGORITHM ID overhead. + The magic 9, 8, or 5 is the OID length of the corresponding algorithm. +*/ + sigType = PS_UNSUPPORTED_FAIL; + switch (sc->sigAlgorithm) { +#ifdef USE_RSA +#ifdef ENABLE_MD5_SIGNED_CERTS +#ifdef USE_MD2 + case OID_MD2_RSA_SIG: +#endif + case OID_MD5_RSA_SIG: + sigType = RSA_TYPE_SIG; + sigLen = 10 + MD5_HASH_SIZE + 8; + break; +#endif +#ifdef ENABLE_SHA1_SIGNED_CERTS + case OID_SHA1_RSA_SIG: + sigLen = 10 + SHA1_HASH_SIZE + 5; + sigType = RSA_TYPE_SIG; + break; +#endif +#ifdef USE_SHA256 + case OID_SHA256_RSA_SIG: + sigLen = 10 + SHA256_HASH_SIZE + 9; + sigType = RSA_TYPE_SIG; + break; +#endif +#ifdef USE_SHA384 + case OID_SHA384_RSA_SIG: + sigLen = 10 + SHA384_HASH_SIZE + 9; + sigType = RSA_TYPE_SIG; + break; +#endif +#ifdef USE_SHA512 + case OID_SHA512_RSA_SIG: + sigLen = 10 + SHA512_HASH_SIZE + 9; + sigType = RSA_TYPE_SIG; + break; +#endif +#endif /* USE_RSA */ +#ifdef USE_ECC +#ifdef ENABLE_SHA1_SIGNED_CERTS + case OID_SHA1_ECDSA_SIG: + sigLen = SHA1_HASH_SIZE; + sigType = ECDSA_TYPE_SIG; + break; +#endif +#ifdef USE_SHA256 + case OID_SHA256_ECDSA_SIG: + sigLen = SHA256_HASH_SIZE; + sigType = ECDSA_TYPE_SIG; + break; +#endif +#ifdef USE_SHA384 + case OID_SHA384_ECDSA_SIG: + sigLen = SHA384_HASH_SIZE; + sigType = ECDSA_TYPE_SIG; + break; +#endif +#ifdef USE_SHA512 + case OID_SHA512_ECDSA_SIG: + sigLen = SHA512_HASH_SIZE; + sigType = ECDSA_TYPE_SIG; + break; +#endif +#endif /* USE_ECC */ + +#ifdef USE_PKCS1_PSS + case OID_RSASSA_PSS: + switch (sc->pssHash) { +#ifdef ENABLE_MD5_SIGNED_CERTS + case PKCS1_MD5_ID: + sigLen = MD5_HASH_SIZE; + break; +#endif +#ifdef ENABLE_SHA1_SIGNED_CERTS + case PKCS1_SHA1_ID: + sigLen = SHA1_HASH_SIZE; + break; +#endif +#ifdef USE_SHA256 + case PKCS1_SHA256_ID: + sigLen = SHA256_HASH_SIZE; + break; +#endif +#ifdef USE_SHA384 + case PKCS1_SHA384_ID: + sigLen = SHA384_HASH_SIZE; + break; +#endif +#ifdef USE_SHA512 + case PKCS1_SHA512_ID: + sigLen = SHA512_HASH_SIZE; + break; +#endif + default: + return PS_UNSUPPORTED_FAIL; + } + sigType = RSAPSS_TYPE_SIG; + break; +#endif + default: + sigType = PS_UNSUPPORTED_FAIL; + break; + } + + if (sigType == PS_UNSUPPORTED_FAIL) { + sc->authStatus = PS_CERT_AUTH_FAIL_SIG; + psTraceIntCrypto("Unsupported certificate signature algorithm %d\n", + subjectCert->sigAlgorithm); + return sigType; + } + +#ifdef USE_RSA + if (sigType == RSA_TYPE_SIG || sigType == RSAPSS_TYPE_SIG) { + } + /* Now do the signature validation */ + if (sigType == RSA_TYPE_SIG) { + psAssert(sigLen <= sizeof(sigOut)); +/* + psRsaDecryptPub destroys the 'in' parameter so let it be a tmp +*/ + tempSig = psMalloc(pool, sc->signatureLen); + if (tempSig == NULL) { + psError("Memory allocation error: psX509AuthenticateCert\n"); + return PS_MEM_FAIL; + } + memcpy(tempSig, sc->signature, sc->signatureLen); + + rsaData = NULL; + + if ((rc = psRsaDecryptPub(pkiPool, &ic->publicKey.key.rsa, + tempSig, sc->signatureLen, sigOut, sigLen, rsaData)) < 0) { + + + psTraceCrypto("Unable to RSA decrypt certificate signature\n"); + sc->authStatus = PS_CERT_AUTH_FAIL_SIG; + psFree(tempSig, pool); + return rc; + } + psFree(tempSig, pool); + rc = x509ConfirmSignature(sc->sigHash, sigOut, sigLen); + } +#if defined(USE_PKCS1_PSS) && !defined(USE_PKCS1_PSS_VERIFY_ONLY) + if (sigType == RSAPSS_TYPE_SIG) { + tempSig = psMalloc(pool, sc->signatureLen); + if (tempSig == NULL) { + psError("Memory allocation error: psX509AuthenticateCert\n"); + return PS_MEM_FAIL; + } + pssLen = sc->signatureLen; + if ((rc = psRsaCrypt(pkiPool, &ic->publicKey.key.rsa, + sc->signature, sc->signatureLen, tempSig, &pssLen, + PS_PUBKEY, rsaData)) < 0) { + psFree(tempSig, pool); + return rc; + } + + if (pkcs1PssDecode(pkiPool, sc->sigHash, sigLen, tempSig, + pssLen, sc->saltLen, sc->pssHash, ic->publicKey.keysize * 8, + &rc) < 0) { + psFree(tempSig, pool); + return PS_FAILURE; + } + psFree(tempSig, pool); + + if (rc == 0) { + /* This is an indication the hash did NOT match */ + rc = -1; /* The test below is looking for < 0 */ + } + } +#endif /* defined(USE_PKCS1_PSS) && !defined(USE_PKCS1_PSS_VERIFY_ONLY) */ +#endif /* USE_RSA */ + +#ifdef USE_ECC + if (sigType == ECDSA_TYPE_SIG) { + rsaData = NULL; + if ((rc = psEccDsaVerify(pkiPool, + &ic->publicKey.key.ecc, + sc->sigHash, sigLen, + sc->signature, sc->signatureLen, + &sigStat, rsaData)) != 0) { + psTraceCrypto("Error validating ECDSA certificate signature\n"); + sc->authStatus = PS_CERT_AUTH_FAIL_SIG; + return rc; + } + if (sigStat == -1) { + /* No errors, but signature didn't pass */ + psTraceCrypto("ECDSA certificate signature failed\n"); + rc = -1; + } + } +#endif /* USE_ECC */ + + +/* + Test what happen in the signature test? +*/ + if (rc < PS_SUCCESS) { + sc->authStatus = PS_CERT_AUTH_FAIL_SIG; + return rc; + } + + + /* X.509 extension tests. Problems below here will be collected + in flags and given to the user */ + + /* If date was out of range in parse, flag it here */ + if (sc->authFailFlags & PS_CERT_AUTH_FAIL_DATE_FLAG) { + sc->authStatus = PS_CERT_AUTH_FAIL_EXTENSION; + } + + /* Verify subject key and auth key if either is non-zero */ + if (sc->extensions.ak.keyLen > 0 || ic->extensions.sk.len > 0) { + if (ic->extensions.sk.len != sc->extensions.ak.keyLen) { + /* The one exception to this test would be if this is a + self-signed CA being authenticated with the exact same + self-signed CA and that certificate does not popluate + the Authority Key Identifier extension */ + if ((sc->signatureLen == ic->signatureLen) && + (memcmp(sc->signature, ic->signature, ic->signatureLen) + == 0)) { + if (sc->extensions.ak.keyLen != 0) { + psTraceCrypto("Subject/Issuer key id mismatch\n"); + sc->authStatus = PS_CERT_AUTH_FAIL_AUTHKEY; + } + } else { + psTraceCrypto("Subject/Issuer key id mismatch\n"); + sc->authStatus = PS_CERT_AUTH_FAIL_AUTHKEY; + } + } else { + if (memcmp(ic->extensions.sk.id, sc->extensions.ak.keyId, + ic->extensions.sk.len) != 0) { + psTraceCrypto("Subject/Issuer key id data mismatch\n"); + sc->authStatus = PS_CERT_AUTH_FAIL_AUTHKEY; + } + } + } + + /* Ensure keyCertSign of KeyUsage. The second byte of the BIT STRING + will always contain the relevant information. */ + if ( ! (ic->extensions.keyUsageFlags & KEY_USAGE_KEY_CERT_SIGN)) { + /* @security If keyUsageFlags is zero, it may not exist at all + in the cert. This is allowed if the cert was issued before + the RFC was updated to require this field for CA certificates. + RFC3280 and above specify this as a MUST for CACerts. */ + if (ic->extensions.keyUsageFlags == 0) { + rc = issuedBefore(RFC_3280, ic); + } else { + rc = 0; /* Awkward code to force the compare below */ + } + /* Iff rc == 1 we won't error */ + if (!rc) { + psTraceCrypto("Issuer does not allow keyCertSign in keyUsage\n"); + sc->authFailFlags |= PS_CERT_AUTH_FAIL_KEY_USAGE_FLAG; + sc->authStatus = PS_CERT_AUTH_FAIL_EXTENSION; + } else if (rc < 0) { + psTraceCrypto("Issue date check failed\n"); + return PS_PARSE_FAIL; + } + } +/* + Fall through to here only if passed all non-failure checks. +*/ + if (sc->authStatus == PS_FALSE) { /* Hasn't been touched */ + sc->authStatus = PS_CERT_AUTH_PASS; + } +/* + Loop control for finding next ic and sc. +*/ + if (ic == sc) { + *foundIssuer = ic; + ic = NULL; /* Single self-signed test completed */ + } else if (ic == issuerCert) { + *foundIssuer = ic; + ic = NULL; /* If issuerCert was used, that is always final test */ + } else { + sc = ic; + ic = sc->next; + if (ic == NULL) { /* Reached end of chain */ + *foundIssuer = ic; + ic = sc; /* Self-signed test on final subectCert chain */ + } + } + + } + return PS_SUCCESS; +} + +#ifdef USE_RSA +/******************************************************************************/ +/* + Do the signature validation for a subject certificate against a + known CA certificate +*/ +static int32_t x509ConfirmSignature(const unsigned char *sigHash, + const unsigned char *sigOut, uint16_t sigLen) +{ + const unsigned char *end; + const unsigned char *p = sigOut; + unsigned char hash[MAX_HASH_SIZE]; + int32_t oi; + uint16_t len, plen; + + end = p + sigLen; +/* + DigestInfo ::= SEQUENCE { + digestAlgorithm DigestAlgorithmIdentifier, + digest Digest } + + DigestAlgorithmIdentifier ::= AlgorithmIdentifier + + Digest ::= OCTET STRING +*/ + if (getAsnSequence(&p, (uint32)(end - p), &len) < 0) { + psTraceCrypto("Initial parse error in x509ConfirmSignature\n"); + return PS_PARSE_FAIL; + } + + /* Could be MD5 or SHA1 */ + if (getAsnAlgorithmIdentifier(&p, (uint32)(end - p), &oi, &plen) < 0) { + psTraceCrypto("Algorithm ID parse error in x509ConfirmSignature\n"); + return PS_PARSE_FAIL; + } + psAssert(plen == 0); + if ((*p++ != ASN_OCTET_STRING) || + getAsnLength(&p, (uint32)(end - p), &len) < 0 || + (uint32)(end - p) < len) { + psTraceCrypto("getAsnLength parse error in x509ConfirmSignature\n"); + return PS_PARSE_FAIL; + } + memcpy(hash, p, len); + switch (oi) { +#ifdef ENABLE_MD5_SIGNED_CERTS +#ifdef USE_MD2 + case OID_MD2_ALG: +#endif + case OID_MD5_ALG: + if (len != MD5_HASH_SIZE) { + psTraceCrypto("MD5_HASH_SIZE error in x509ConfirmSignature\n"); + return PS_LIMIT_FAIL; + } + break; +#endif +#ifdef ENABLE_SHA1_SIGNED_CERTS + case OID_SHA1_ALG: + if (len != SHA1_HASH_SIZE) { + psTraceCrypto("SHA1_HASH_SIZE error in x509ConfirmSignature\n"); + return PS_LIMIT_FAIL; + } + break; +#endif +#ifdef USE_SHA256 + case OID_SHA256_ALG: + if (len != SHA256_HASH_SIZE) { + psTraceCrypto("SHA256_HASH_SIZE error in x509ConfirmSignature\n"); + return PS_LIMIT_FAIL; + } + break; +#endif +#ifdef USE_SHA384 + case OID_SHA384_ALG: + if (len != SHA384_HASH_SIZE) { + psTraceCrypto("SHA384_HASH_SIZE error in x509ConfirmSignature\n"); + return PS_LIMIT_FAIL; + } + break; +#endif +#ifdef USE_SHA512 + case OID_SHA512_ALG: + if (len != SHA512_HASH_SIZE) { + psTraceCrypto("SHA512_HASH_SIZE error in x509ConfirmSignature\n"); + return PS_LIMIT_FAIL; + } + break; +#endif + default: + psTraceCrypto("Unsupported alg ID error in x509ConfirmSignature\n"); + return PS_UNSUPPORTED_FAIL; + } + /* hash should match sigHash */ + if (memcmp(hash, sigHash, len) != 0) { + psTraceCrypto("Signature failure in x509ConfirmSignature\n"); + return PS_SIGNATURE_MISMATCH; + } + return PS_SUCCESS; +} +#endif /* USE_RSA */ + +/******************************************************************************/ +#ifdef USE_CRL +static void x509FreeRevoked(x509revoked_t **revoked) +{ + x509revoked_t *next, *curr = *revoked; + + while (curr) { + next = curr->next; + psFree(curr->serial, curr->pool); + psFree(curr, curr->pool); + curr = next; + } + *revoked = NULL; +} + +/* + Parse a CRL and confirm was issued by supplied CA. + + Only interested in the revoked serial numbers which are stored in the + CA structure if all checks out. Used during cert validation as part of + the default tests + + poolUserPtr is for the TMP_PKI pool +*/ +int32 psX509ParseCrl(psPool_t *pool, psX509Cert_t *CA, int append, + unsigned char *crlBin, int32 crlBinLen, + void *poolUserPtr) +{ + unsigned char *end, *start, *revStart, *sigStart, *sigEnd,*p = crlBin; + int32 oi, plen, sigLen, version, rc; + unsigned char sigHash[SHA512_HASH_SIZE], sigOut[SHA512_HASH_SIZE]; + x509revoked_t *curr, *next; + x509DNattributes_t issuer; + x509v3extensions_t ext; + psDigestContext_t hashCtx; + psPool_t *pkiPool = MATRIX_NO_POOL; + uint16_t glen, ilen, timelen; + + end = p + crlBinLen; + /* + CertificateList ::= SEQUENCE { + tbsCertList TBSCertList, + signatureAlgorithm AlgorithmIdentifier, + signatureValue BIT STRING } + + TBSCertList ::= SEQUENCE { + version Version OPTIONAL, + -- if present, shall be v2 + signature AlgorithmIdentifier, + issuer Name, + thisUpdate Time, + nextUpdate Time OPTIONAL, + revokedCertificates SEQUENCE OF SEQUENCE { + userCertificate CertificateSerialNumber, + revocationDate Time, + crlEntryExtensions Extensions OPTIONAL + -- if present, shall be v2 + } OPTIONAL, + crlExtensions [0] EXPLICIT Extensions OPTIONAL + -- if present, shall be v2 + } + */ + if (getAsnSequence(&p, (uint32)(end - p), &glen) < 0) { + psTraceCrypto("Initial parse error in psX509ParseCrl\n"); + return PS_PARSE_FAIL; + } + + sigStart = p; + if (getAsnSequence(&p, (uint32)(end - p), &glen) < 0) { + psTraceCrypto("Initial parse error in psX509ParseCrl\n"); + return PS_PARSE_FAIL; + } + if (*p == ASN_INTEGER) { + version = 0; + if (getAsnInteger(&p, (uint32)(end - p), &version) < 0 || version != 1){ + psTraceIntCrypto("Version parse error in psX509ParseCrl %d\n", + version); + return PS_PARSE_FAIL; + } + } + /* signature */ + if (getAsnAlgorithmIdentifier(&p, (int32)(end - p), &oi, &plen) < 0) { + psTraceCrypto("Couldn't parse crl sig algorithm identifier\n"); + return PS_PARSE_FAIL; + } + + /* + Name ::= CHOICE { -- only one possibility for now -- + rdnSequence RDNSequence } + + RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + + DistinguishedName ::= RDNSequence + + RelativeDistinguishedName ::= + SET SIZE (1 .. MAX) OF AttributeTypeAndValue + */ + memset(&issuer, 0x0, sizeof(x509DNattributes_t)); + if ((rc = psX509GetDNAttributes(pool, &p, (uint32)(end - p), + &issuer, 0)) < 0) { + psTraceCrypto("Couldn't parse crl issuer DN attributes\n"); + return rc; + } + /* Ensure crlSign flag of KeyUsage for the given CA. */ + if ( ! (CA->extensions.keyUsageFlags & KEY_USAGE_CRL_SIGN)) { + psTraceCrypto("Issuer does not allow crlSign in keyUsage\n"); + CA->authFailFlags |= PS_CERT_AUTH_FAIL_KEY_USAGE_FLAG; + CA->authStatus = PS_CERT_AUTH_FAIL_EXTENSION; + psX509FreeDNStruct(&issuer, pool); + return PS_CERT_AUTH_FAIL_EXTENSION; + } + if (memcmp(issuer.hash, CA->subject.hash, SHA1_HASH_SIZE) != 0) { + psTraceCrypto("CRL NOT ISSUED BY THIS CA\n"); + psX509FreeDNStruct(&issuer, pool); + return PS_CERT_AUTH_FAIL_DN; + } + psX509FreeDNStruct(&issuer, pool); + + /* thisUpdate TIME */ + if ((end - p) < 1 || ((*p != ASN_UTCTIME) && (*p != ASN_GENERALIZEDTIME))) { + psTraceCrypto("Malformed thisUpdate CRL\n"); + return PS_PARSE_FAIL; + } + p++; + if (getAsnLength(&p, (uint32)(end - p), &timelen) < 0 || + (uint32)(end - p) < timelen) { + psTraceCrypto("Malformed thisUpdate CRL\n"); + return PS_PARSE_FAIL; + } + p += timelen; /* Skip it */ + /* nextUpdateTIME - Optional */ + if ((end - p) < 1 || ((*p == ASN_UTCTIME) || (*p == ASN_GENERALIZEDTIME))) { + p++; + if (getAsnLength(&p, (uint32)(end - p), &timelen) < 0 || + (uint32)(end - p) < timelen) { + psTraceCrypto("Malformed nextUpdateTIME CRL\n"); + return PS_PARSE_FAIL; + } + p += timelen; /* Skip it */ + } + /* + revokedCertificates SEQUENCE OF SEQUENCE { + userCertificate CertificateSerialNumber, + revocationDate Time, + crlEntryExtensions Extensions OPTIONAL + -- if present, shall be v2 + } OPTIONAL, + */ + if (getAsnSequence(&p, (uint32)(end - p), &glen) < 0) { + psTraceCrypto("Initial revokedCertificates error in psX509ParseCrl\n"); + return PS_PARSE_FAIL; + } + + if (CA->revoked) { + /* Append or refresh */ + if (append == 0) { + /* refresh */ + x509FreeRevoked(&CA->revoked); + CA->revoked = curr = psMalloc(pool, sizeof(x509revoked_t)); + if (curr == NULL) { + return PS_MEM_FAIL; + } + } else { + /* append. not looking for duplicates */ + curr = psMalloc(pool, sizeof(x509revoked_t)); + if (curr == NULL) { + return PS_MEM_FAIL; + } + curr->pool = pool; + next = CA->revoked; + while (next->next != NULL) { + next = next->next; + } + next->next = curr; + } + } else { + CA->revoked = curr = psMalloc(pool, sizeof(x509revoked_t)); + if (curr == NULL) { + return PS_MEM_FAIL; + } + } + memset(curr, 0x0, sizeof(x509revoked_t)); + curr->pool = pool; + + + while (glen > 0) { + revStart = p; + if (getAsnSequence(&p, (uint32)(end - p), &ilen) < 0) { + psTraceCrypto("Deep revokedCertificates error in psX509ParseCrl\n"); + return PS_PARSE_FAIL; + } + start = p; + if ((rc = getSerialNum(pool, &p, (uint32)(end - p), &curr->serial, + &curr->serialLen)) < 0) { + psTraceCrypto("ASN serial number parse error\n"); + return rc; + } + /* skipping time and extensions */ + p += ilen - (uint32)(p - start); + if (glen < (uint32)(p - revStart)) { + psTraceCrypto("Deeper revokedCertificates err in psX509ParseCrl\n"); + return PS_PARSE_FAIL; + } + glen -= (uint32)(p - revStart); + + // psTraceBytes("revoked", curr->serial, curr->serialLen); + if (glen > 0) { + if ((next = psMalloc(pool, sizeof(x509revoked_t))) == NULL) { + x509FreeRevoked(&CA->revoked); + return PS_MEM_FAIL; + } + memset(next, 0x0, sizeof(x509revoked_t)); + next->pool = pool; + curr->next = next; + curr = next; + } + } + memset(&ext, 0x0, sizeof(x509v3extensions_t)); + if (getExplicitExtensions(pool, &p, (uint32)(end - p), 0, &ext, 0) < 0) { + psTraceCrypto("Extension parse error in psX509ParseCrl\n"); + x509FreeRevoked(&CA->revoked); + return PS_PARSE_FAIL; + } + x509FreeExtensions(&ext); + sigEnd = p; + + if (getAsnAlgorithmIdentifier(&p, (int32)(end - p), &oi, &plen) < 0) { + x509FreeRevoked(&CA->revoked); + psTraceCrypto("Couldn't parse crl sig algorithm identifier\n"); + return PS_PARSE_FAIL; + } + + if ((rc = psX509GetSignature(pool, &p, (uint32)(end - p), &revStart, &ilen)) + < 0) { + x509FreeRevoked(&CA->revoked); + psTraceCrypto("Couldn't parse signature\n"); + return rc; + } + + switch (oi) { +#ifdef ENABLE_MD5_SIGNED_CERTS + case OID_MD5_RSA_SIG: + sigLen = MD5_HASH_SIZE; + psMd5Init(&hashCtx); + psMd5Update(&hashCtx, sigStart, (uint32)(sigEnd - sigStart)); + psMd5Final(&hashCtx, sigHash); + break; +#endif +#ifdef ENABLE_SHA1_SIGNED_CERTS + case OID_SHA1_RSA_SIG: + sigLen = SHA1_HASH_SIZE; + psSha1Init(&hashCtx); + psSha1Update(&hashCtx, sigStart, (uint32)(sigEnd - sigStart)); + psSha1Final(&hashCtx, sigHash); + break; +#endif +#ifdef USE_SHA256 + case OID_SHA256_RSA_SIG: + sigLen = SHA256_HASH_SIZE; + psSha256Init(&hashCtx); + psSha256Update(&hashCtx, sigStart, (uint32)(sigEnd - sigStart)); + psSha256Final(&hashCtx, sigHash); + break; +#endif + default: + psTraceCrypto("Need more signatuare alg support for CRL\n"); + x509FreeRevoked(&CA->revoked); + return PS_UNSUPPORTED_FAIL; + } + + + + if ((rc = pubRsaDecryptSignedElement(pkiPool, &CA->publicKey.key.rsa, + revStart, ilen, sigOut, sigLen, NULL)) < 0) { + x509FreeRevoked(&CA->revoked); + psTraceCrypto("Unable to RSA decrypt CRL signature\n"); + return rc; + } + + + if (memcmp(sigHash, sigOut, sigLen) != 0) { + x509FreeRevoked(&CA->revoked); + psTraceCrypto("Unable to verify CRL signature\n"); + return PS_CERT_AUTH_FAIL_SIG; + } + + return PS_SUCCESS; +} +#endif /* USE_CRL */ +#endif /* USE_CERT_PARSE */ + + +#ifdef USE_OCSP +static int32_t parseSingleResponse(uint32_t len, const unsigned char **cp, + const unsigned char *end, mOCSPSingleResponse_t *res) +{ + const unsigned char *p; + uint16_t glen, plen; + int32_t oi; + + p = *cp; + + /* SingleResponse ::= SEQUENCE { + certID CertID, + certStatus CertStatus, + thisUpdate GeneralizedTime, + nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, + singleExtensions [1] EXPLICIT Extensions OPTIONAL } + */ + if (getAsnSequence(&p, (int32)(end - p), &glen) < 0) { + psTraceCrypto("Initial parseSingleResponse parse failure\n"); + return PS_PARSE_FAIL; + } + /* CertID ::= SEQUENCE { + hashAlgorithm AlgorithmIdentifier + {DIGEST-ALGORITHM, {...}}, + issuerNameHash OCTET STRING, -- Hash of issuer's DN + issuerKeyHash OCTET STRING, -- Hash of issuer's public key + serialNumber CertificateSerialNumber } + */ + if (getAsnSequence(&p, (int32)(end - p), &glen) < 0) { + psTraceCrypto("Initial parseSingleResponse parse failure\n"); + return PS_PARSE_FAIL; + } + if (getAsnAlgorithmIdentifier(&p, (int32)(end - p), &oi, &plen) < 0){ + return PS_FAILURE; + } + psAssert(plen == 0); + res->certIdHashAlg = oi; + + if ((*p++ != ASN_OCTET_STRING) || + getAsnLength(&p, (int32)(end - p), &glen) < 0 || + (uint32)(end - p) < glen) { + return PS_PARSE_FAIL; + } + res->certIdNameHash = p; + p += glen; + + if ((*p++ != ASN_OCTET_STRING) || + getAsnLength(&p, (int32)(end - p), &glen) < 0 || + (uint32)(end - p) < glen) { + return PS_PARSE_FAIL; + } + res->certIdKeyHash = p; + p += glen; + + /* serialNumber CertificateSerialNumber + + CertificateSerialNumber ::= INTEGER + */ + if ((*p != (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 2)) && + (*p != ASN_INTEGER)) { + psTraceCrypto("X.509 getSerialNum failed on first bytes\n"); + return PS_PARSE_FAIL; + } + p++; + + if (getAsnLength(&p, (int32)(end - p), &glen) < 0 || + (uint32)(end - p) < glen) { + psTraceCrypto("ASN getSerialNum failed\n"); + return PS_PARSE_FAIL; + } + res->certIdSerialLen = glen; + res->certIdSerial = p; + p += glen; + + /* CertStatus ::= CHOICE { + good [0] IMPLICIT NULL, + revoked [1] IMPLICIT RevokedInfo, + unknown [2] IMPLICIT UnknownInfo } + */ + if (*p == (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 0)) { + res->certStatus = 0; + p += 2; + } else if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) { + res->certStatus = 1; + psTraceCrypto("OCSP CertStatus is revoked. Skipping details\n"); + /* RevokedInfo ::= SEQUENCE { + revocationTime GeneralizedTime, + revocationReason [0] EXPLICIT CRLReason OPTIONAL } + */ + if (getAsnSequence(&p, (int32)(end - p), &glen) < 0) { + psTraceCrypto("Initial parseSingleResponse parse failure\n"); + return PS_PARSE_FAIL; + } + /* skip it */ + p += glen; + } else if (*p == (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 2)) { + res->certStatus = 2; + p += 2; /* TOOD: Untested parse. Might be CONSTRUCTED encoding */ + /* UnknownInfo ::= NULL */ + } else { + psTraceCrypto("OCSP CertStatus parse fail\n"); + return PS_PARSE_FAIL; + } + + /* thisUpdate GeneralizedTime, */ + if ((end - p) < 1 || (*p != ASN_GENERALIZEDTIME)) { + psTraceCrypto("Malformed thisUpdate OCSP\n"); + return PS_PARSE_FAIL; + } + p++; + if (getAsnLength(&p, (uint32)(end - p), &glen) < 0 || + (uint32)(end - p) < glen) { + return PS_PARSE_FAIL; + } + res->thisUpdateLen = glen; + res->thisUpdate = p; + p += glen; + + /* nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, */ + + if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { + p++; + if (getAsnLength(&p, (uint32)(end - p), &glen) < 0 || + (uint32)(end - p) < glen) { + return PS_PARSE_FAIL; + } + p += glen; /* SKIPPING */ + } + + /* singleExtensions [1] EXPLICIT Extensions OPTIONAL */ + if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) { + p++; + if (getAsnLength(&p, (uint32)(end - p), &glen) < 0 || + (uint32)(end - p) < glen) { + return PS_PARSE_FAIL; + } + /* TODO */ + p += glen; /* SKIPPING */ + } + + *cp = (unsigned char*)p; + return PS_SUCCESS; +} + +static int32_t parseBasicOCSPResponse(psPool_t *pool, uint32_t len, + const unsigned char **cp, unsigned char *end, + mOCSPResponse_t *res) +{ + const unsigned char *p, *seqend, *startRes, *endRes; + mOCSPSingleResponse_t *singleResponse; + psSha1_t sha; +#ifdef USE_SHA256 + psSha256_t sha2; +#endif +#ifdef USE_SHA384 + psSha384_t sha3; +#endif + uint16_t glen, plen; + uint32_t blen; + int32_t version, oid; + + /* id-pkix-ocsp-basic + + BasicOCSPResponse ::= SEQUENCE { + tbsResponseData ResponseData, + signatureAlgorithm AlgorithmIdentifier, + signature BIT STRING, + certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } + */ + p = *cp; + + if (getAsnSequence(&p, (uint32)(end - p), &glen) < 0) { + psTraceCrypto("Initial parse error in parseBasicOCSPResponse\n"); + return PS_PARSE_FAIL; + } + /* + ResponseData ::= SEQUENCE { + version [0] EXPLICIT Version DEFAULT v1, + responderID ResponderID, + producedAt GeneralizedTime, + responses SEQUENCE OF SingleResponse, + responseExtensions [1] EXPLICIT Extensions OPTIONAL } + */ + startRes = p; /* A response signature will be over ResponseData */ + if (getAsnSequence(&p, (uint32)(end - p), &glen) < 0) { + psTraceCrypto("Early ResponseData parse error in parseOCSPResponse\n"); + return PS_PARSE_FAIL; + } + if (getExplicitVersion(&p, (uint32)(end - p), 0, &version) < 0) { + psTraceCrypto("Version parse error in ResponseData\n"); + return PS_PARSE_FAIL; + } + if (version != 0) { + psTraceIntCrypto("WARNING: Unknown OCSP ResponseData version %d\n", + version); + } + /* + ResponderID ::= CHOICE { + byName [1] Name, + byKey [2] KeyHash } + */ + if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) { + psTraceCrypto("TODO: Unsupported byName ResponderID in ResponseData\n"); + return PS_PARSE_FAIL; + } else if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)) { + p++; + if (getAsnLength32(&p, (uint32_t)(end - p), &blen, 0) < 0 || + (uint32_t)(end - p) < blen) { + psTraceCrypto("Error parsing KeyHash in ResponseData\n"); + return PS_PARSE_FAIL; + } + /* KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key + -- (i.e., the SHA-1 hash of the value of the + -- BIT STRING subjectPublicKey [excluding + -- the tag, length, and number of unused + -- bits] in the responder's certificate) */ + if ((*p++ != ASN_OCTET_STRING) || + getAsnLength(&p, (int32)(end - p), &glen) < 0 || + (uint32)(end - p) < glen) { + + psTraceCrypto("Couldn't parse KeyHash in ResponseData\n"); + return PS_FAILURE; + } + psAssert(glen == SHA1_HASH_SIZE); + res->responderKeyHash = p; + p += SHA1_HASH_SIZE; + } else { + psTraceCrypto("ResponderID parse error in ResponseData\n"); + return PS_PARSE_FAIL; + } + + /* producedAt GeneralizedTime, */ + if ((end - p) < 1 || (*p != ASN_GENERALIZEDTIME)) { + psTraceCrypto("Malformed thisUpdate CRL\n"); + return PS_PARSE_FAIL; + } + p++; + if (getAsnLength(&p, (uint32)(end - p), &glen) < 0 || + (uint32)(end - p) < glen) { + psTraceCrypto("Malformed producedAt in ResponseData\n"); + return PS_PARSE_FAIL; + } + psAssert(glen <= 20); /* TODO: length hardcoded in structure */ + res->timeProducedLen = glen; + res->timeProduced = p; + p += glen; + + /* responses SEQUENCE OF SingleResponse, */ + if (getAsnSequence(&p, (int32)(end - p), &glen) < 0) { + psTraceCrypto("Initial SingleResponse parse failure\n"); + return PS_PARSE_FAIL; + } + + seqend = p + glen; + + plen = 0; /* for MAX_OCSP_RESPONSES control */ + while (p < seqend) { + singleResponse = &res->singleResponse[plen]; + if (parseSingleResponse(glen, &p, seqend, singleResponse) < 0) { + return PS_PARSE_FAIL; + } + plen++; + if (p < seqend) { + /* Additional responses */ + if (plen == MAX_OCSP_RESPONSES) { + psTraceCrypto("ERROR: Multiple OCSP SingleResponse items. "); + psTraceCrypto("Increase MAX_OCSP_RESPONSES to support\n"); + return PS_PARSE_FAIL; + } + } + } + + /* responseExtensions [1] EXPLICIT Extensions OPTIONAL } */ + if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) { + p++; + if (getAsnLength(&p, (uint32)(end - p), &glen) < 0 || + (uint32)(end - p) < glen) { + return PS_PARSE_FAIL; + } + /* TODO: */ + p += glen; /* SKIPPING */ + } + endRes = p; + + /* ResponseData DONE. On to signature: + + signatureAlgorithm AlgorithmIdentifier + signature BIT STRING, + + The value for signature SHALL be computed on the hash of the DER + encoding of ResponseData. The responder MAY include certificates in + the certs field of BasicOCSPResponse that help the OCSP client + verify the responder's signature. If no certificates are included, + then certs SHOULD be absent. */ + if (getAsnAlgorithmIdentifier(&p, (uint32)(end - p), &oid, &plen) < 0) { + psTraceCrypto("Initial SingleResponse parse failure\n"); + return PS_PARSE_FAIL; + } + if (plen > 0) { + psTraceCrypto("Algorithm parameters on ResponseData sigAlg\n"); + p += plen; + } + res->sigAlg = oid; + + switch (oid) { + /* OSCP requires SHA1 so no wrapper here */ + case OID_SHA1_RSA_SIG: +#ifdef USE_ECC + case OID_SHA1_ECDSA_SIG: +#endif + res->hashLen = SHA1_HASH_SIZE; + psSha1Init(&sha); + psSha1Update(&sha, startRes, (int32)(endRes - startRes)); + psSha1Final(&sha, res->hashResult); + break; +#ifdef USE_SHA256 + case OID_SHA256_RSA_SIG: +#ifdef USE_ECC + case OID_SHA256_ECDSA_SIG: +#endif + res->hashLen = SHA256_HASH_SIZE; + psSha256Init(&sha2); + psSha256Update(&sha2, startRes, (int32)(endRes - startRes)); + psSha256Final(&sha2, res->hashResult); + break; +#endif +#ifdef USE_SHA384 + case OID_SHA384_RSA_SIG: +#ifdef USE_ECC + case OID_SHA384_ECDSA_SIG: +#endif + res->hashLen = SHA384_HASH_SIZE; + psSha384Init(&sha3); + psSha384Update(&sha3, startRes, (int32)(endRes - startRes)); + psSha384Final(&sha3, res->hashResult); + break; +#endif + default: + psTraceCrypto("No support for sigAlg in OCSP ResponseData\n"); + return PS_UNSUPPORTED_FAIL; + } + + if (*p++ != ASN_BIT_STRING) { + psTraceCrypto("Error parsing signature in ResponseData\n"); + return PS_PARSE_FAIL; + } + if (getAsnLength(&p, (int32)(end - p), &glen) < 0 || + (uint32)(end - p) < glen) { + psTraceCrypto("Error parsing signature in ResponseData\n"); + return PS_PARSE_FAIL; + } + if (*p++ != 0) { + psTraceCrypto("Error parsing ignore bits in ResponseData sig\n"); + return PS_PARSE_FAIL; + } + glen--; /* ignore bits above */ + res->sig = p; + res->sigLen = glen; + p += glen; + + /* certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } */ + if (end != p) { + /* The responder MAY include certificates in the certs field of + BasicOCSPResponse that help the OCSP client verify the responder's + signature. */ + if (*p != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { + psTraceCrypto("Unexpected Certificage encoding in OCSPResponse\n"); + return PS_PARSE_FAIL; + } + p++; + if (getAsnLength(&p, (uint32)(end - p), &glen) < 0 || + (uint32)(end - p) < glen) { + return PS_PARSE_FAIL; + } + /* If here, this is the cert that issued the OCSPResponse. Will + authenticate during validateOCSPResponse */ + if (getAsnSequence(&p, (uint32)(end - p), &glen) < 0) { + psTraceCrypto("\n"); + return PS_PARSE_FAIL; + } + psAssert(glen == (end - p)); + /* reusing oid. will handle multiple certs if needed */ + oid = psX509ParseCert(pool, p, glen, &res->OCSPResponseCert, 0); + if (oid < 0) { + psX509FreeCert(res->OCSPResponseCert); + return PS_PARSE_FAIL; + } + p += oid; + } + psAssert(p == end); + + *cp = (unsigned char*)p; + return PS_SUCCESS; +} + +int32_t parseOCSPResponse(psPool_t *pool, int32_t len, unsigned char **cp, + unsigned char *end, mOCSPResponse_t *response) +{ + const unsigned char *p; + int32_t status, oi; + uint16_t glen; + uint32_t blen; + + p = *cp; + //psTraceBytes("OCSPResponse", p, len); + /* + OCSPResponse ::= SEQUENCE { + responseStatus OCSPResponseStatus, + responseBytes [0] EXPLICIT ResponseBytes OPTIONAL } + */ + if (getAsnSequence(&p, (uint32)(end - p), &glen) < 0) { + psTraceCrypto("Initial parse error in parseOCSPResponse\n"); + return PS_PARSE_FAIL; + } + if (getAsnEnumerated(&p, (uint32)(end - p), &status) < 0) { + psTraceCrypto("Enum parse error in parseOCSPResponse\n"); + return PS_PARSE_FAIL; + } + /* + OCSPResponseStatus ::= ENUMERATED { + successful (0), -- Response has valid confirmations + malformedRequest (1), -- Illegal confirmation request + internalError (2), -- Internal error in issuer + tryLater (3), -- Try again later + -- (4) is not used + sigRequired (5), -- Must sign the request + unauthorized (6) -- Request unauthorized + } + */ + if (status != 0) { + /* Something other than success. List right above here */ + psTraceCrypto("OCSPResponse contains no valid confirmations\n"); + return PS_PARSE_FAIL; + } + + /* responseBytes [0] EXPLICIT ResponseBytes OPTIONAL, */ + if (*p == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + p++; + if (getAsnLength32(&p, (uint32_t)(end - p), &blen, 0) < 0 || + (uint32_t)(end - p) < blen) { + psTraceCrypto("Error parsing UserKeyingMaterial\n"); + return PS_PARSE_FAIL; + } + + /* ResponseBytes ::= SEQUENCE { + responseType OBJECT IDENTIFIER, + response OCTET STRING } + */ + if (getAsnSequence(&p, (uint32)(end - p), &glen) < 0) { + psTraceCrypto("ResponseBytes parse error in parseOCSPResponse\n"); + return PS_PARSE_FAIL; + } + if (getAsnOID(&p, (uint32)(end - p), &oi, 1, &glen) < 0) { + psTraceCrypto("responseType parse error in parseOCSPResponse\n"); + return PS_PARSE_FAIL; + } + if ((*p++ != ASN_OCTET_STRING) || + getAsnLength32(&p, (int32)(end - p), &blen, 0) < 0 || + (uint32)(end - p) < blen) { + + psTraceCrypto("Couldn't parse response in parseOCSPResponse\n"); + return PS_PARSE_FAIL; + } + if (oi == 117) { + /* id-pkix-ocsp-basic + + BasicOCSPResponse ::= SEQUENCE { + tbsResponseData ResponseData, + signatureAlgorithm AlgorithmIdentifier, + signature BIT STRING, + certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } + */ + if (parseBasicOCSPResponse(pool, blen, &p, end, response) < 0) { + psTraceCrypto("parseBasicOCSPResponse failure\n"); + return PS_PARSE_FAIL; + } + } else if (oi == 116) { + /* id-pkix-ocsp */ + psTraceCrypto("unsupported id-pkix-ocsp in parseOCSPResponse\n"); + return PS_PARSE_FAIL; + } else { + psTraceCrypto("unsupported responseType in parseOCSPResponse\n"); + return PS_PARSE_FAIL; + } + + } + psAssert(end == p); + *cp = (unsigned char*)p; + return PS_SUCCESS; +} + +/* Diff the current time against the OCSP timestamp and confirm it's not + longer than the user is willing to trust */ +static int16_t checkOCSPtimestamp(mOCSPResponse_t *response) +{ + /* GeneralizedTime values MUST be + expressed in Greenwich Mean Time (Zulu) and MUST include seconds + (i.e., times are YYYYMMDDHHMMSSZ), even where the number of seconds + is zero. GeneralizedTime values MUST NOT include fractional seconds. + */ +#ifdef POSIX + struct tm mytime; + time_t currrawtime, myrawtime; + double diffsecs; + const unsigned char *c; + + /* timeProduced here is the producedAt of the response which is the + time the signature was generated */ + c = response->timeProduced; + + /* Goal is to create time_t from this GeneralizedTime to perform a + diff against current time (also a time_t) */ + memset(&mytime, 0x0, sizeof(struct tm)); + mytime.tm_year = 1000 * (c[0] - '0') + 100 * (c[1] - '0') + + 10 * (c[2] - '0') + (c[3] - '0'); c += 4; + mytime.tm_year -= 1900; + mytime.tm_mon = 10 * (c[0] - '0') + (c[1] - '0'); c += 2; + mytime.tm_mon--; /* month is 0 based for some reason */ + mytime.tm_mday = 10 * (c[0] - '0') + (c[1] - '0'); c += 2; + mytime.tm_hour = 10 * (c[0] - '0') + (c[1] - '0'); c += 2; + mytime.tm_min = 10 * (c[0] - '0') + (c[1] - '0'); c += 2; + mytime.tm_sec = 10 * (c[0] - '0') + (c[1] - '0'); + + /* If there is no timegm on the platform, maybe there will be a mktime + which will interpret 'mytime' as local time rather than GMT. This + change will cause a margin of error in the difftime below if + the current time is not adjusted for GMT */ + //myrawtime = mktime(&mytime); /* margin of error will exist */ + myrawtime = timegm(&mytime); /* Adds missing members of mytime */ + + /* current time */ + time(&currrawtime); + + diffsecs = difftime(currrawtime, myrawtime); + + if (diffsecs < 0 || diffsecs > OCSP_VALID_TIME_WINDOW) { + return PS_LIMIT_FAIL; + } + return PS_SUCCESS; + +#else +/* Warn if we are skipping the date validation checks. */ +#ifdef WIN32 +#pragma message("OCSP DATE VALIDITY NOT SUPPORTED ON THIS PLATFORM.") +#else +#warning "OCSP DATE VALIDITY NOT SUPPORTED ON THIS PLATFORM." +#endif + return PS_SUCCESS; +#endif /* POSIX */ +} + +int32_t validateOCSPResponse(psPool_t *pool, psX509Cert_t *trustedOCSP, + psX509Cert_t *srvCerts, mOCSPResponse_t *response) +{ + psX509Cert_t *curr, *issuer, *subject, *ocspResIssuer; + mOCSPSingleResponse_t *subjectResponse; + unsigned char sigOut[MAX_HASH_SIZE]; + int32 sigOutLen, sigType, index; + psPool_t *pkiPool = NULL; + + /* Find the OCSP cert that signed the response. First place to look is + within the OCSPResponse itself */ + issuer = NULL; + if (response->OCSPResponseCert) { + /* If there is a cert here it is something that has to be authenticated. + We will either leave this case with a successful auth or failure */ + curr = response->OCSPResponseCert; + while (curr != NULL) { + /* The outer responderKeyHash should be matching one of the certs + that was attached to the OCSPResonse itself */ + if (memcmp(response->responderKeyHash, curr->sha1KeyHash, 20) == 0){ + /* Found it... but now we have to authenticate it against + our known list of CAs. issuer in the context of this + function is the OCSPResponse issuer but here we are looking + for the CA of THAT cert so it's 'subject' in this area */ + subject = curr; + ocspResIssuer = trustedOCSP; /* preloaded sslKeys->CA */ + while (ocspResIssuer) { + if (memcmp(ocspResIssuer->subject.hash, + subject->issuer.hash, 20) == 0) { + + if (psX509AuthenticateCert(pool, subject, ocspResIssuer, + &ocspResIssuer, NULL, NULL) == 0) { + /* OK, we held the CA that issued the OCSPResponse + so we'll now trust that cert that was provided + in the OCSPResponse */ + ocspResIssuer = NULL; + issuer = subject; + } else { + /* Auth failure */ + psTraceCrypto("Attached OCSP cert didn't auth\n"); + return PS_FAILURE; + } + } else { + ocspResIssuer = ocspResIssuer->next; + } + } + curr = NULL; + } else { + curr = curr->next; + } + } + if (issuer == NULL) { + psTraceCrypto("Found no CA to authenticate attached OCSP cert\n"); + return PS_FAILURE; /* no preloaded CA to auth cert in response */ + } + } + + /* Issuer will be NULL if there was no certificate attached to the + OCSP response. Now look to the user loaded CA files */ + if (issuer == NULL) { + curr = trustedOCSP; + while (curr != NULL) { + /* Currently looking for the subjectKey extension to match the + public key hash from the response */ + if (memcmp(response->responderKeyHash, curr->sha1KeyHash, 20) == 0){ + issuer = curr; + curr = NULL; + } else { + curr = curr->next; + } + } + } + + /* It is possible a certificate embedded in the server certificate + chain was itself the OCSP responder */ + if (issuer == NULL) { + /* Don't look at the first cert in the chain because that is the + one we are trying to find the OCSP responder public key for */ + curr = srvCerts->next; + while (curr != NULL) { + /* Currently looking for the subjectKey extension to match the + public key hash from the response */ + if (memcmp(response->responderKeyHash, curr->sha1KeyHash, 20) == 0){ + issuer = curr; + curr = NULL; + } else { + curr = curr->next; + } + } + } + + if (issuer == NULL) { + psTraceCrypto("Unable to locate OCSP responder CA for validation\n"); + return PS_FAILURE; + } + + /* Now check to see that the response is vouching for the subject cert + that we are interested in. The subject will always be the first + cert in the server CERTIFICATE chain */ + subject = srvCerts; + + /* Now look to match this cert within the singleResponse members. + + There are three components to a CertID that should be used to validate + we are looking at the correct OCSP response for the subjecct cert. + + It appears the only "unique" portion of our subject cert that + went into the signature of this response is the serial number. + The "issuer" information of the subject cert also went into the + signature but that isn't exactly unique. Seems a bit odd that the + combo of the issuer and the serial number are the only thing that tie + this subject cert back to the response but serial numbers are the basis + for CRL as well so it must be good enough */ + index = 0; + while (index < MAX_OCSP_RESPONSES) { + subjectResponse = &response->singleResponse[index]; + if ((subject->serialNumberLen == subjectResponse->certIdSerialLen) && + (memcmp(subject->serialNumber, subjectResponse->certIdSerial, + subject->serialNumberLen) == 0)) { + break; /* got it */ + } + index++; + } + if (index == MAX_OCSP_RESPONSES) { + psTraceCrypto("Unable to locate our subject cert in OCSP response\n"); + return PS_FAILURE; + } + + /* If the response is reporting that this cert is bad right in the status, + just return that immediately and stop the connection */ + if (subjectResponse->certStatus != 0) { + psTraceCrypto("ERROR: OCSP info: server cert is revoked!\n"); + return PS_FAILURE; + } + + /* Is the response within the acceptable time window */ + if (checkOCSPtimestamp(response) < 0) { + psTraceCrypto("ERROR: OCSP response older than threshold\n"); + return PS_FAILURE; + } + + /* Issuer portion of the validation - the subject cert issuer key and name + hash should match what the subjectResponse reports + + POSSIBLE PROBLEMS: Only supporting a SHA1 hash here. The MatrixSSL + parser will only use SHA1 for the DN and key hash. Just warning on + this for now. The signature validation will catch any key mismatch */ + if (subjectResponse->certIdHashAlg != OID_SHA1_ALG) { + psTraceCrypto("WARNING: Non-SHA1 OCSP CertID. Issuer check bypassed\n"); + } else { + if (memcmp(subjectResponse->certIdKeyHash, issuer->sha1KeyHash, 20) + != 0) { + psTraceCrypto("Failed OCP issuer key hash validation\n"); + return PS_FAILURE; + } + /* Either subject->issuer or issuer->subject would work for testing */ + if (memcmp(subjectResponse->certIdNameHash, issuer->subject.hash, 20) + != 0){ + psTraceCrypto("Failed OCP issuer name hash validation\n"); + return PS_FAILURE; + } + } + + /* Finally do the sig validation */ + switch (response->sigAlg) { +#ifdef USE_SHA256 + case OID_SHA256_RSA_SIG: + sigOutLen = SHA256_HASH_SIZE; + sigType = PS_RSA; + break; + case OID_SHA256_ECDSA_SIG: + sigOutLen = SHA256_HASH_SIZE; + sigType = PS_ECC; + break; +#endif +#ifdef USE_SHA384 + case OID_SHA384_RSA_SIG: + sigOutLen = SHA384_HASH_SIZE; + sigType = PS_RSA; + break; + case OID_SHA384_ECDSA_SIG: + sigOutLen = SHA384_HASH_SIZE; + sigType = PS_ECC; + break; +#endif + case OID_SHA1_RSA_SIG: + sigOutLen = SHA1_HASH_SIZE; + sigType = PS_RSA; + break; + case OID_SHA1_ECDSA_SIG: + sigOutLen = SHA1_HASH_SIZE; + sigType = PS_ECC; + break; + default: + /* Should have been caught in parse phase */ + return PS_UNSUPPORTED_FAIL; + } + + /* Finally test the signature */ + if (sigType == PS_RSA) { + if (issuer->publicKey.type != PS_RSA) { + return PS_FAILURE; + } + if (pubRsaDecryptSignedElement(pkiPool, &issuer->publicKey.key.rsa, + (unsigned char*)response->sig, response->sigLen, sigOut, + sigOutLen, NULL) < 0) { + psTraceCrypto("Unable to decode signature in validateOCSPResponse\n"); + return PS_FAILURE; + } + if (memcmp(response->hashResult, sigOut, sigOutLen) != 0) { + psTraceCrypto("OCSP RSA signature validation failed\n"); + return PS_FAILURE; + } + } +#ifdef USE_ECC + else { + if (issuer->publicKey.type != PS_ECC) { + return PS_FAILURE; + } + /* ECDSA signature */ + index = 0; + if (psEccDsaVerify(pkiPool, &issuer->publicKey.key.ecc, + response->hashResult, sigOutLen, (unsigned char*)response->sig, + response->sigLen, &index, NULL) < 0) { + psTraceCrypto("ECC OCSP sig validation"); + return PS_FAILURE; + } + if (index != 1) { + psTraceCrypto("OCSP ECDSA signature validation failed\n"); + return PS_FAILURE; + } + } +#endif + + + /* Was able to successfully confirm OCSP signature for our subject */ + return PS_SUCCESS; +} +#endif /* USE_OCSP */ + +#endif /* USE_X509 */ +/******************************************************************************/ + + diff --git a/crypto/keyformat/x509.h b/crypto/keyformat/x509.h new file mode 100644 index 0000000..a5a4e5c --- /dev/null +++ b/crypto/keyformat/x509.h @@ -0,0 +1,448 @@ +/** + * @file x509.h + * @version $Format:%h%d$ + * + * X.509 header. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_PS_X509 +#define _h_PS_X509 + +#ifdef USE_X509 + +/******************************************************************************/ + +/* ClientCertificateType */ +enum { + RSA_SIGN = 1, + DSS_SIGN, + RSA_FIXED_DH, + DSS_FIXED_DH, + ECDSA_SIGN = 64, + RSA_FIXED_ECDH, + ECDSA_FIXED_ECDH +}; + +/* Parsing flags */ +#define CERT_STORE_UNPARSED_BUFFER 0x1 +#define CERT_STORE_DN_BUFFER 0x2 + +#ifdef USE_CERT_PARSE + +/* Per specification, any critical extension in an X.509 cert should cause + the connection to fail. SECURITY - Uncomment at your own risk */ +/* #define ALLOW_UNKNOWN_CRITICAL_EXTENSIONS */ + +/* + DN attributes are used outside the X509 area for cert requests, + which have been included in the RSA portions of the code +*/ +typedef struct { + char *country; + char *state; + char *locality; + char *organization; + char *orgUnit; + char *commonName; + char hash[MAX_HASH_SIZE]; + char *dnenc; /* CERT_STORE_DN_BUFFER */ + uint16_t dnencLen; + short countryType; + uint16_t countryLen; + short stateType; + uint16_t stateLen; + short localityType; + uint16_t localityLen; + short organizationType; + uint16_t organizationLen; + short orgUnitType; + uint16_t orgUnitLen; + short commonNameType; + uint16_t commonNameLen; +} x509DNattributes_t; + +typedef struct { + int32 cA; + int32 pathLenConstraint; +} x509extBasicConstraints_t; + +typedef struct psGeneralNameEntry { + psPool_t *pool; + enum { + GN_OTHER = 0, // OtherName + GN_EMAIL, // IA5String + GN_DNS, // IA5String + GN_X400, // ORAddress + GN_DIR, // Name + GN_EDI, // EDIPartyName + GN_URI, // IA5String + GN_IP, // OCTET STRING + GN_REGID // OBJECT IDENTIFIER + } id; + unsigned char name[16]; + unsigned char oid[32]; /* SubjectAltName OtherName */ + unsigned char *data; + uint16_t oidLen; + uint16_t dataLen; + struct psGeneralNameEntry *next; +} x509GeneralName_t; + +typedef struct { + unsigned char *id; + uint16_t len; +} x509extSubjectKeyId_t; + +typedef struct { + unsigned char *keyId; + unsigned char *serialNum; + x509DNattributes_t attribs; + uint16_t keyLen; + uint16_t serialNumLen; +} x509extAuthKeyId_t; + +#ifdef USE_FULL_CERT_PARSE +typedef struct { + x509GeneralName_t *permitted; + x509GeneralName_t *excluded; +} x509nameConstraints_t; +#endif /* USE_FULL_CERT_PARSE */ + +/******************************************************************************/ +/* + OID parsing and lookup. +*/ +#define MAX_OID_LEN 16 /**< Maximum number of segments in OID */ + +/* + X.509 Certificate Extension OIDs + @see https://tools.ietf.org/html/rfc5280#section-4.2 + + id-ce OBJECT IDENTIFIER ::= { joint-iso-ccitt(2) ds(5) 29 } + + id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } + id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } + id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } + id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } + id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } + id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } + id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } + id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } + id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } + id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } + id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } + id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } + id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } + id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } + id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } +*/ +#define id_ce 2,5,29 +enum { + id_ce_authorityKeyIdentifier = 35, + id_ce_subjectKeyIdentifier = 14, + id_ce_keyUsage = 15, + id_ce_certificatePolicies = 32, + id_ce_policyMappings = 33, + id_ce_subjectAltName = 17, + id_ce_issuerAltName = 18, + id_ce_subjectDirectoryAttributes = 9, + id_ce_basicConstraints = 19, + id_ce_nameConstraints = 30, + id_ce_policyConstraints = 36, + id_ce_extKeyUsage = 37, + id_ce_cRLDistributionPoints = 31, + id_ce_inhibitAnyPolicy = 54, + id_ce_freshestCRL = 46, +}; + +/* id-pkix OBJECT IDENTIFIER ::= { + iso(1) identified-organization(3) dod(6) internet(1) + security(5) mechanisms(5) pkix(7) } +*/ +#define id_pxix 1,3,6,1,5,5,7 + +/* +The following key usage purposes are defined: + + anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } + + id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } + + id_kp_serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } + -- TLS WWW server authentication + -- Key usage bits that may be consistent: digitalSignature, + -- keyEncipherment or keyAgreement + + id_kp_clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } + -- TLS WWW client authentication + -- Key usage bits that may be consistent: digitalSignature + -- and/or keyAgreement + + id_kp_codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } + -- Signing of downloadable executable code + -- Key usage bits that may be consistent: digitalSignature + + id_kp_emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } + -- Email protection + -- Key usage bits that may be consistent: digitalSignature, + -- nonRepudiation, and/or (keyEncipherment or keyAgreement) + + id_kp_timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } + -- Binding the hash of an object to a time + -- Key usage bits that may be consistent: digitalSignature + -- and/or nonRepudiation + + id_kp_OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } + -- Signing OCSP responses + -- Key usage bits that may be consistent: digitalSignature + -- and/or nonRepudiation +*/ +#define id_ce_eku id_ce,id_ce_extKeyUsage +#define id_kp id_pxix,3 +enum { + id_ce_eku_anyExtendedKeyUsage = 0, + id_kp_serverAuth = 1, + id_kp_clientAuth = 2, + id_kp_codeSigning = 3, + id_kp_emailProtection = 4, + id_kp_timeStamping = 8, + id_kp_OCSPSigning = 9, +}; + +/* + id-pe OBJECT IDENTIFIER ::= { id-pkix 1 } + + id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 } + id-pe-subjectInfoAccess OBJECT IDENTIFIER ::= { id-pe 11 } +*/ +#define id_pe id_pxix,1 +enum { + id_pe_authorityInfoAccess = 1, + id_pe_subjectInfoAccess = 11, +}; + +#define OID_ENUM(A) oid_##A +typedef enum { + OID_ENUM(0) = 0, + /* X.509 certificate extensions */ + OID_ENUM(id_ce_authorityKeyIdentifier), + OID_ENUM(id_ce_subjectKeyIdentifier), + OID_ENUM(id_ce_keyUsage), + OID_ENUM(id_ce_certificatePolicies), + OID_ENUM(id_ce_policyMappings), + OID_ENUM(id_ce_subjectAltName), + OID_ENUM(id_ce_issuerAltName), + OID_ENUM(id_ce_subjectDirectoryAttributes), + OID_ENUM(id_ce_basicConstraints), + OID_ENUM(id_ce_nameConstraints), + OID_ENUM(id_ce_policyConstraints), + OID_ENUM(id_ce_extKeyUsage), + OID_ENUM(id_ce_cRLDistributionPoints), + OID_ENUM(id_ce_inhibitAnyPolicy), + OID_ENUM(id_ce_freshestCRL), + OID_ENUM(id_pe_authorityInfoAccess), + OID_ENUM(id_pe_subjectInfoAccess), + /* Extended Key Usage */ + OID_ENUM(id_ce_eku_anyExtendedKeyUsage), + OID_ENUM(id_kp_serverAuth), + OID_ENUM(id_kp_clientAuth), + OID_ENUM(id_kp_codeSigning), + OID_ENUM(id_kp_emailProtection), + OID_ENUM(id_kp_timeStamping), + OID_ENUM(id_kp_OCSPSigning), +} oid_e; + +/* Make the flag value, given the enum above */ +#define EXT_CRIT_FLAG(A) (unsigned int)(1 << (A)) + +/* Flags for known keyUsage (first byte) */ +#define KEY_USAGE_DIGITAL_SIGNATURE 0x0080 +#define KEY_USAGE_NON_REPUDIATION 0x0040 +#define KEY_USAGE_KEY_ENCIPHERMENT 0x0020 +#define KEY_USAGE_DATA_ENCIPHERMENT 0x0010 +#define KEY_USAGE_KEY_AGREEMENT 0x0008 +#define KEY_USAGE_KEY_CERT_SIGN 0x0004 +#define KEY_USAGE_CRL_SIGN 0x0002 +#define KEY_USAGE_ENCIPHER_ONLY 0x0001 +/* Flags for known keyUsage (second, optional byte) */ +#define KEY_USAGE_DECIPHER_ONLY 0x8000 + +/* Flags for known extendedKeyUsage */ +#define EXT_KEY_USAGE_ANY (1 << 0) +#define EXT_KEY_USAGE_TLS_SERVER_AUTH (1 << 1) +#define EXT_KEY_USAGE_TLS_CLIENT_AUTH (1 << 2) +#define EXT_KEY_USAGE_CODE_SIGNING (1 << 3) +#define EXT_KEY_USAGE_EMAIL_PROTECTION (1 << 4) +#define EXT_KEY_USAGE_TIME_STAMPING (1 << 8) +#define EXT_KEY_USAGE_OCSP_SIGNING (1 << 9) + +/******************************************************************************/ + +/* Holds the known extensions we support */ +typedef struct { + psPool_t *pool; + x509extBasicConstraints_t bc; + x509GeneralName_t *san; + uint32 critFlags; /* EXT_CRIT_FLAG(EXT_KEY_USE) */ + uint32 keyUsageFlags; /* KEY_USAGE_ */ + uint32 ekuFlags; /* EXT_KEY_USAGE_ */ + x509extSubjectKeyId_t sk; + x509extAuthKeyId_t ak; +#ifdef USE_FULL_CERT_PARSE + x509nameConstraints_t nameConstraints; +#endif /* USE_FULL_CERT_PARSE */ +#ifdef USE_CRL + x509GeneralName_t *crlDist; +#endif +} x509v3extensions_t; + +#endif /* USE_CERT_PARSE */ + +#ifdef USE_CRL +typedef struct x509revoked { + psPool_t *pool; + unsigned char *serial; + uint16_t serialLen; + struct x509revoked *next; +} x509revoked_t; +#endif + + + +typedef struct psCert { + psPool_t *pool; +#ifdef USE_CERT_PARSE + psPubKey_t publicKey; + int32 version; + unsigned char *serialNumber; + uint16_t serialNumberLen; + x509DNattributes_t issuer; + x509DNattributes_t subject; + int32 notBeforeTimeType; + int32 notAfterTimeType; + char *notBefore; + char *notAfter; + int32 pubKeyAlgorithm; /* public key algorithm OID */ + int32 certAlgorithm; /* signature algorithm OID */ + int32 sigAlgorithm; /* signature algorithm OID */ +#ifdef USE_PKCS1_PSS + int32 pssHash; /* RSAPSS sig hash OID */ + int32 maskGen; /* RSAPSS maskgen OID */ + int32 maskHash; /* hash OID for MGF1 */ + uint16_t saltLen; /* RSAPSS salt len param */ +#endif + unsigned char *signature; + unsigned char *uniqueIssuerId; + unsigned char *uniqueSubjectId; + uint16_t signatureLen; + uint16_t uniqueIssuerIdLen; + uint16_t uniqueSubjectIdLen; + x509v3extensions_t extensions; + int32 authStatus; /* See psX509AuthenticateCert doc */ + uint32 authFailFlags; /* Flags for extension check failures */ +#ifdef USE_CRL + x509revoked_t *revoked; +#endif + unsigned char sigHash[MAX_HASH_SIZE]; +#endif /* USE_CERT_PARSE */ +#ifdef USE_OCSP + unsigned char sha1KeyHash[SHA1_HASH_SIZE]; +#endif +#ifdef ENABLE_CA_CERT_HASH + /** @note this is used only by MatrixSSL for Trusted CA Indication extension */ + unsigned char sha1CertHash[SHA1_HASH_SIZE]; +#endif + unsigned char *unparsedBin; /* see psX509ParseCertFile */ + uint16_t binLen; + struct psCert *next; +} psX509Cert_t; + + +#ifdef USE_CERT_PARSE +extern int32_t psX509GetSignature(psPool_t *pool, const unsigned char **pp, + uint16_t len, unsigned char **sig, uint16_t *sigLen); +extern int32_t psX509GetDNAttributes(psPool_t *pool, const unsigned char **pp, + uint16_t len, x509DNattributes_t *attribs, uint32_t flags); +extern void psX509FreeDNStruct(x509DNattributes_t *dn, psPool_t *allocPool); +extern int32_t getSerialNum(psPool_t *pool, const unsigned char **pp, + uint16_t len, unsigned char **sn, uint16_t *snLen); +extern int32_t getExplicitExtensions(psPool_t *pool, const unsigned char **pp, + uint16_t inlen, int32_t expVal, x509v3extensions_t *extensions, + uint8_t known); +extern void x509FreeExtensions(x509v3extensions_t *extensions); +extern int32_t psX509ValidateGeneralName(const char *n); +#endif /* USE_CERT_PARSE */ + +#ifdef USE_OCSP +/* The OCSP structure members point directly into an OCSPResponse stream. + They are validated immediately after the parse so if a change request + requires these fields to persist, this will all have to change */ +typedef struct { + uint16_t certIdHashAlg; /* hashAlgorithm in CertID */ + const unsigned char *certIdNameHash; + const unsigned char *certIdKeyHash; + const unsigned char *certIdSerial; + short certIdSerialLen; + short certStatus; + const unsigned char *thisUpdate; + short thisUpdateLen; +} mOCSPSingleResponse_t; + +#define MAX_OCSP_RESPONSES 3 + +typedef struct { + const unsigned char *responderKeyHash; + const unsigned char *timeProduced; + short timeProducedLen; + mOCSPSingleResponse_t singleResponse[MAX_OCSP_RESPONSES]; + uint16_t sigAlg; + const unsigned char *sig; + uint16_t sigLen; + unsigned char hashResult[MAX_HASH_SIZE]; + uint16_t hashLen; + psX509Cert_t *OCSPResponseCert; /* Allocated to hsPool */ +} mOCSPResponse_t; + +extern int32_t parseOCSPResponse(psPool_t *pool, int32_t len, + unsigned char **cp, unsigned char *end, + mOCSPResponse_t *response); +extern int32_t validateOCSPResponse(psPool_t *pool, psX509Cert_t *trustedOCSP, + psX509Cert_t *srvCerts, mOCSPResponse_t *response); +#endif + +/******************************************************************************/ + + +/******************************************************************************/ + +#endif /* USE_X509 */ + +#endif /* _h_PS_X509 */ + +/******************************************************************************/ diff --git a/crypto/layer/layer.h b/crypto/layer/layer.h new file mode 100644 index 0000000..92b5644 --- /dev/null +++ b/crypto/layer/layer.h @@ -0,0 +1,332 @@ +/** + * @file layer.h + * @version $Format:%h%d$ + * + * Header file to determine crypto algorithm provider. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_PS_CRYPTOLAYER +#define _h_PS_CRYPTOLAYER +/** + Layer implementations of configured crypto APIs. + First we define MATRIX as the crypto provider for each enabled algorithm + that was enabled above and then we can override with other providers. +*/ +#if (defined(USE_AES_CBC) || defined(USE_AES_GCM) || \ + defined(USE_AES_WRAP) || defined(USE_AES_CMAC) || \ + defined(USE_AES_CTR)) + #define USE_MATRIX_AES_BLOCK + #define USE_AES_BLOCK + #define USE_AES +#endif + +#define USE_MATRIX_RAW_KEY /* Default, unless changed by lower layers */ + +#if defined(USE_AES_CBC) + #define USE_MATRIX_AES_CBC +#endif +#if defined(USE_AES_GCM) + #define USE_MATRIX_AES_GCM +#endif + +#ifdef USE_CHACHA20_POLY1305 + #ifndef USE_LIBSODIUM_CRYPTO + #error "libsodium required for chacha20_poly1305" + #endif +#endif + +#ifdef USE_ARC4 + #define USE_MATRIX_ARC4 +#endif +#ifdef USE_RC2 + #define USE_MATRIX_RC2 +#endif +#ifdef USE_3DES + #define USE_MATRIX_3DES +#endif +#ifdef USE_SEED + #define USE_MATRIX_SEED +#endif +#ifdef USE_IDEA + #define USE_MATRIX_IDEA +#endif + +#if defined(USE_SHA256) + #define USE_MATRIX_SHA256 +#endif +#if defined(USE_HMAC_SHA256) + #define USE_MATRIX_HMAC_SHA256 +#endif + +#if defined(USE_SHA384) + #define USE_MATRIX_SHA384 +#endif +#if defined(USE_HMAC_SHA384) + #define USE_MATRIX_HMAC_SHA384 +#endif + +#if defined(USE_SHA512) + #define USE_MATRIX_SHA512 +#endif + +#if defined(USE_SHA1) + #define USE_MATRIX_SHA1 +#endif +#if defined(USE_HMAC_SHA1) + #define USE_MATRIX_HMAC_SHA1 +#endif +#if defined(USE_MD5SHA1) + #define USE_MATRIX_MD5SHA1 +#endif + +#if defined(USE_MD5) + #define USE_MATRIX_MD5 +#endif +#if defined(USE_HMAC_MD5) + #define USE_MATRIX_HMAC_MD5 +#endif + +#if defined(USE_MD4) + #define USE_MATRIX_MD4 +#endif + +#if defined(USE_MD2) + #define USE_MATRIX_MD2 +#endif + +#if defined(USE_RSA) + #define USE_MATRIX_RSA +#endif + +#if defined(USE_ECC) + #define USE_MATRIX_ECC +#endif + +#if defined(USE_DH) + #define USE_MATRIX_DH +#endif + +#if defined(USE_PRNG) + #define USE_MATRIX_PRNG +#endif + + +#ifdef USE_LIBSODIUM_CRYPTO +/******************************************************************************/ +/** + Use libsodium cryptography primitives (link with libsodium.a). +*/ + #ifdef USE_CHACHA20_POLY1305 +// #undef USE_MATRIX_CHACHA20_POLY1305 /* @note, not defined in matrix crypto */ + #define USE_LIBSODIUM_CHACHA20_POLY1305 + #endif + + #ifdef USE_MATRIX_AES_GCM + #undef USE_MATRIX_AES_GCM + #define USE_LIBSODIUM_AES_GCM + #endif + + #ifdef USE_MATRIX_SHA256 + #undef USE_MATRIX_SHA256 + #define USE_LIBSODIUM_SHA256 + #endif + + #ifdef USE_MATRIX_SHA384 + #undef USE_MATRIX_SHA384 + #define USE_LIBSODIUM_SHA384 + #endif + + #ifdef USE_MATRIX_SHA512 + #undef USE_MATRIX_SHA512 + #define USE_LIBSODIUM_SHA512 + #endif + + #ifdef USE_MATRIX_HMAC_SHA256 + #undef USE_MATRIX_HMAC_SHA256 + #define USE_LIBSODIUM_HMAC_SHA256 + #endif + +#endif /* USE_LIBSODIUM_CRYPTO */ + + +/* Common for CL CRYPTO and FIPS CRYPTO */ + +#ifdef USE_OPENSSL_CRYPTO +/******************************************************************************/ +/** + Use OpenSSL cryptography primitives (link with libcrypto.a). + This can take advantage of hardware which has a specifically optimized + libcrypto library, for example Cavium Octeon. +*/ + #ifdef USE_MATRIX_AES_CBC + #undef USE_MATRIX_AES_CBC + #define USE_OPENSSL_AES_CBC + #endif + #ifdef USE_MATRIX_MD5 + #undef USE_MATRIX_MD5 + #define USE_OPENSSL_MD5 + #endif + #ifdef USE_MATRIX_SHA1 + #undef USE_MATRIX_SHA1 + #define USE_OPENSSL_SHA1 + #endif + #ifdef USE_MATRIX_MD5SHA1 + #undef USE_MATRIX_MD5SHA1 + #define USE_OPENSSL_MD5SHA1 + #endif + #ifdef USE_MATRIX_SHA256 + #undef USE_MATRIX_SHA256 + #define USE_OPENSSL_SHA256 + #endif + #ifdef USE_MATRIX_SHA384 + #undef USE_MATRIX_SHA384 + #define USE_OPENSSL_SHA384 + #endif + #ifdef USE_MATRIX_SHA512 + #undef USE_MATRIX_SHA512 + #define USE_OPENSSL_SHA512 + #endif + #ifdef USE_MATRIX_HMAC_MD5 + #undef USE_MATRIX_HMAC_MD5 + #define USE_OPENSSL_HMAC_MD5 + #endif + #ifdef USE_MATRIX_HMAC_SHA1 + #undef USE_MATRIX_HMAC_SHA1 + #define USE_OPENSSL_HMAC_SHA1 + #endif + #ifdef USE_MATRIX_HMAC_SHA256 + #undef USE_MATRIX_HMAC_SHA256 + #define USE_OPENSSL_HMAC_SHA256 + #endif + #ifdef USE_MATRIX_HMAC_SHA384 + #undef USE_MATRIX_HMAC_SHA384 + #define USE_OPENSSL_HMAC_SHA384 + #endif + #ifdef USE_MATRIX_RSA + #undef USE_MATRIX_RSA + #define USE_OPENSSL_RSA + #endif +#endif /* USE_OPENSSL_CRYPTO */ + +#if defined(__AES__) && !defined(USE_FIPS_CRYPTO) +/******************************************************************************/ +/** + This is defined if the -maes compiler flag is used on Intel platforms. + @see https://en.wikipedia.org/wiki/AES_instruction_set +*/ + #ifdef USE_MATRIX_AES_BLOCK + #undef USE_MATRIX_AES_BLOCK + #define USE_AESNI_AES_BLOCK + #endif + #ifdef USE_MATRIX_AES_CBC + #undef USE_MATRIX_AES_CBC + #define USE_AESNI_AES_CBC + #endif + #ifdef USE_MATRIX_AES_GCM + #undef USE_MATRIX_AES_GCM + #define USE_AESNI_AES_GCM + #endif + #if defined(USE_AESNI_AES_BLOCK) || defined(USE_AESNI_AES_CBC) || \ + defined(USE_AESNI_AES_GCM) + #define USE_AESNI_CRYPTO + #endif +#endif /* __AES__ */ + + + + +/******************************************************************************/ +/* + Enable algorithm optimizations based on the compiler optimization settings. + GCC compatible compilers will define: + __OPTIMIZE__ for all -O1 and above (include -Os) + __OPTIMIZE_SIZE__ in addition to __OPTIMIZE__ for -Os + + Both code size and RAM usage are affected by these defines. + + By default below, these will be enabled on an optimized build that is + not optimized for size. Eg. for -O[1-3,fast], but not for -Os + + For a specific platform, it is best to tune these by hand to get the + right balance of speed and size. +*/ +#if defined(__OPTIMIZE__) + #if !defined(__OPTIMIZE_SIZE__) +/* + Improve block cipher performance, but produce larger code. + Platforms vary, but ciphers will generally see a 5%-10% performance + boost at the cost of 10-20 kilobytes (per algorithm). +*/ + #ifdef USE_MATRIX_AES_BLOCK + #define PS_AES_IMPROVE_PERF_INCREASE_CODESIZE + #endif + #ifdef USE_MATRIX_3DES + #define PS_3DES_IMPROVE_PERF_INCREASE_CODESIZE + #endif +/* + Improve hashing performance, but produce larger code. + Platforms vary, but digests will generally see a 5%-10% performance + boost at the cost of 1-10 kilobytes (per algorithm). +*/ + #ifdef USE_MATRIX_MD5 + #define PS_MD5_IMPROVE_PERF_INCREASE_CODESIZE + #endif + #ifdef USE_MATRIX_SHA1 + #define PS_SHA1_IMPROVE_PERF_INCREASE_CODESIZE + #endif +/* + Optimize public/private key operations for speed. + Optimizations for 1024/2048 bit key size multiplication and squaring math. + The library size can increase significantly if enabled. +*/ + #if defined(USE_MATRIX_RSA) || defined(USE_MATRIX_ECC) || defined(USE_MATRIX_DH) + #define PS_PUBKEY_OPTIMIZE_FOR_FASTER_SPEED + #endif + #if defined(USE_MATRIX_RSA) || defined(USE_MATRIX_DH) + #define USE_1024_KEY_SPEED_OPTIMIZATIONS + #define USE_2048_KEY_SPEED_OPTIMIZATIONS + #endif + + #else /* OPTIMIZE_SIZE */ +/* + Optimize public/private key operations for smaller ram usage. + The memory savings for optimizing for ram is around 50% +*/ + #if defined(USE_MATRIX_RSA) || defined(USE_MATRIX_ECC) || defined(USE_MATRIX_DH) + #define PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM + #endif + + #endif /* OPTIMIZE_SIZE */ +#endif /* OPTIMIZE */ + +#endif /* _h_PS_CRYPTOLAYER */ + +/******************************************************************************/ + diff --git a/crypto/layer/matrix.c b/crypto/layer/matrix.c new file mode 100644 index 0000000..584ea50 --- /dev/null +++ b/crypto/layer/matrix.c @@ -0,0 +1,81 @@ +/** + * @file matrixcrypto.c + * @version $Format:%h%d$ + * + * Matrix Crypto Initialization and utility layer. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +/******************************************************************************/ +/** + Open (initialize) the Crypto module. + + The config param should always be passed as: + PSCRYPTO_CONFIG +*/ +static char g_config[32] = "N"; + +int32_t psCryptoOpen(const char *config) +{ + uint32_t clen; + + if (*g_config == 'Y') { + return PS_SUCCESS; /* Function has been called previously */ + } + /* 'config' is cryptoconfig + coreconfig */ + strncpy(g_config, PSCRYPTO_CONFIG, sizeof(g_config) - 1); + clen = strlen(PSCRYPTO_CONFIG) - strlen(PSCORE_CONFIG); + if (strncmp(g_config, config, clen) != 0) { + psErrorStr( "Crypto config mismatch.\n" \ + "Library: " PSCRYPTO_CONFIG\ + "\nCurrent: %s\n", config); + return -1; + } + if (psCoreOpen(config + clen) < 0) { + psError("pscore open failure\n"); + return PS_FAILURE; + } + psOpenPrng(); + return 0; +} + +void psCryptoClose(void) +{ + if (*g_config == 'Y') { + *g_config = 'N'; + psClosePrng(); + psCoreClose(); + } +} + + + +/******************************************************************************/ diff --git a/crypto/math/pstm.c b/crypto/math/pstm.c new file mode 100644 index 0000000..5548377 --- /dev/null +++ b/crypto/math/pstm.c @@ -0,0 +1,2368 @@ +/** + * @file pstm.c + * @version $Format:%h%d$ + * + * Multiprecision number implementation. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#if defined(USE_MATRIX_RSA) || defined(USE_CL_RSA) \ + || defined(USE_MATRIX_ECC) \ + || defined(USE_MATRIX_DH) || defined(USE_CL_DH) \ + || defined(USE_QUICK_ASSIST_RSA) || defined(USE_QUICK_ASSIST_ECC) + +static int32_t pstm_mul_2d(const pstm_int *a, int16_t b, pstm_int *c); + +/******************************************************************************/ +/** + Initialize a pstm_int and allocate working memory for a given initial size. + + @param[in] pool Memory pool to use for allocation. + @param[in,out] a Allocated pstm_int to initialize. + @param[in] size Number of digits to pre-allocate for integer. Typically + a digit is 32 or 64 bits. + + @return < 0 on failure, >=0 on success. + */ +int32_t pstm_init_size(psPool_t *pool, pstm_int *a, uint16_t size) +{ + uint16_t x; + + if (size > PSTM_MAX_SIZE) { + return PSTM_MEM; + } + a->dp = psMalloc(pool, sizeof(pstm_digit) * size); + if (a->dp == NULL) { + return PSTM_MEM; + } + a->pool = pool; /* Pool to use when growing or shrinking digits */ + a->used = 0; /* Zero of the digits are currently used */ + a->alloc = size; /* How many digits are pre-allocated */ + a->sign = PSTM_ZPOS; /* Number is positive */ + /* zero the digits */ + for (x = 0; x < size; x++) { + a->dp[x] = 0; + } + return PSTM_OKAY; +} + +/******************************************************************************/ +/* + Init a new pstm_int with a default size. +*/ +int32_t pstm_init(psPool_t *pool, pstm_int *a) +{ + return pstm_init_size(pool, a, (MIN_RSA_BITS / DIGIT_BIT) * 3); +} + +/******************************************************************************/ +/** + Grow a pstm_int to the give size in digits. + + @param[in,out] a Allocated and initialized pstm_int to grow. + @param[in] size Number of digits to grow to. This is not the the number + of digits to grow _by_. 'size' <= current size is ignored, so this + api cannot be used to shrink the integer. + */ +int32_t pstm_grow(pstm_int * a, uint16_t size) +{ + uint16_t i; + pstm_digit *tmp; + + if (size > PSTM_MAX_SIZE) { + return PSTM_MEM; + } + /* If the alloc size is smaller alloc more ram. */ + if (a->alloc < size) { +/* + Reallocate the array a->dp + We store the return in a temporary variable in case the operation + failed we don't want to overwrite the dp member of a. +*/ + tmp = psRealloc(a->dp, sizeof (pstm_digit) * size, a->pool); + if (tmp == NULL) { + /* reallocation failed but "a" is still valid [can be freed] */ + return PSTM_MEM; + } + /* reallocation succeeded so set a->dp */ + a->dp = tmp; + i = a->alloc; + a->alloc = size; + /* zero excess digits */ + for (; i < a->alloc; i++) { + a->dp[i] = 0; + } + } + return PSTM_OKAY; +} + +/******************************************************************************/ +/* + copy, b = a (b must be pre-allocated) + */ +int32_t pstm_copy(const pstm_int * a, pstm_int * b) +{ + int32_t res, n; + + /* If dst == src do nothing */ + if (a == b) { + return PSTM_OKAY; + } + /* Grow dest */ + if (b->alloc < a->used) { + if ((res = pstm_grow(b, a->used)) != PSTM_OKAY) { + return res; + } + } + /* Zero b and copy the parameters over */ + { + /* pointer aliases */ + register pstm_digit *tmpa, *tmpb; + + /* source */ + tmpa = a->dp; + /* destination */ + tmpb = b->dp; + + /* copy all the digits */ + for (n = 0; n < a->used; n++) { + *tmpb++ = *tmpa++; + } + /* clear high digits */ + for (; n < b->used; n++) { + *tmpb++ = 0; + } + } + /* copy used count and sign */ + b->used = a->used; + b->sign = a->sign; + return PSTM_OKAY; +} + +/******************************************************************************/ +/** + Trim unused digits. + + This is used to ensure that leading zero digits are trimed and the + leading "used" digit will be non-zero. Typically very fast. Also fixes + the sign if there are no more leading digits +*/ +void pstm_clamp(pstm_int *a) +{ + /* decrease used while the most significant digit is zero. */ + while (a->used > 0 && a->dp[a->used - 1] == 0) { + --(a->used); + } + /* reset the sign flag if used == 0 */ + if (a->used == 0) { + a->sign = PSTM_ZPOS; + } +} + +/******************************************************************************/ +/** + Clear a big integer, and free associated working memory. + */ +void pstm_clear(pstm_int *a) +{ + int32 i; + + /* only do anything if a hasn't been freed previously */ + if (a != NULL && a->dp != NULL) { + /* first zero the digits */ + for (i = 0; i < a->used; i++) { + a->dp[i] = 0; + } + psFree (a->dp, a->pool); + /* reset members to make debugging easier */ + a->dp = NULL; + a->alloc = a->used = 0; + a->sign = PSTM_ZPOS; + } +} + +/******************************************************************************/ +/** + Clears mp0 - mp7, stopping at the first NULL mp value. + @example pstm_clear_multi(a, b, c, d, NULL, NULL, NULL, NULL); + */ +void pstm_clear_multi(pstm_int *mp0, pstm_int *mp1, pstm_int *mp2, + pstm_int *mp3, pstm_int *mp4, pstm_int *mp5, + pstm_int *mp6, pstm_int *mp7) +{ + if (mp0) { + pstm_clear(mp0); + if (mp1) { + pstm_clear(mp1); + if (mp2) { + pstm_clear(mp2); + if (mp3) { + pstm_clear(mp3); + if (mp4) { + pstm_clear(mp4); + if (mp5) { + pstm_clear(mp5); + if (mp6) { + pstm_clear(mp6); + if (mp7) { + pstm_clear(mp7); + } + } + } + } + } + } + } + } +} + +/******************************************************************************/ +/** + Set to zero. + */ +void pstm_zero(pstm_int * a) +{ + uint16_t n; + pstm_digit *tmp; + + a->sign = PSTM_ZPOS; + a->used = 0; + + tmp = a->dp; + for (n = 0; n < a->alloc; n++) { + *tmp++ = 0; + } +} + +/******************************************************************************/ +/* + Compare maginitude of two ints (unsigned). + */ +int32_t pstm_cmp_mag(const pstm_int *a, const pstm_int *b) +{ + uint16_t n; + const pstm_digit *tmpa, *tmpb; + + /* compare based on # of non-zero digits */ + if (a->used > b->used) { + return PSTM_GT; + } else if (a->used < b->used) { + return PSTM_LT; + } + /* alias for a */ + tmpa = a->dp + (a->used - 1); + /* alias for b */ + tmpb = b->dp + (a->used - 1); + /* compare based on digits */ + for (n = 0; n < a->used; ++n, --tmpa, --tmpb) { + if (*tmpa > *tmpb) { + return PSTM_GT; + } else if (*tmpa < *tmpb) { + return PSTM_LT; + } + } + return PSTM_EQ; +} + +/******************************************************************************/ +/* + Compare two ints (signed) + */ +int32_t pstm_cmp(const pstm_int *a, const pstm_int *b) +{ + /* compare based on sign */ + if (a->sign != b->sign) { + if (a->sign == PSTM_NEG) { + return PSTM_LT; + } else { + return PSTM_GT; + } + } + /* compare digits */ + if (a->sign == PSTM_NEG) { + /* if negative compare opposite direction */ + return pstm_cmp_mag(b, a); + } else { + return pstm_cmp_mag(a, b); + } +} + +/******************************************************************************/ +/* + compare against a single digit +*/ +int32_t pstm_cmp_d(const pstm_int *a, pstm_digit b) +{ + /* compare based on sign */ + if ((b && a->used == 0) || a->sign == PSTM_NEG) { + return PSTM_LT; + } + /* compare based on magnitude */ + if (a->used > 1) { + return PSTM_GT; + } + /* compare the only digit of a to b */ + if (a->dp[0] > b) { + return PSTM_GT; + } else if (a->dp[0] < b) { + return PSTM_LT; + } else { + return PSTM_EQ; + } +} + +/******************************************************************************/ +/* + pstm_ints can be initialized more precisely when they will populated + using pstm_read_unsigned_bin since the length of the byte stream is known +*/ +int32_t pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a, uint16_t len) +{ + uint16_t size; +/* + Need to set this based on how many words max it will take to store the bin. + The magic + 2: + 1 to round up for the remainder of this integer math + 1 for the initial carry of '1' bits that fall between DIGIT_BIT and 8 +*/ + size = (((len / sizeof(pstm_digit)) * (sizeof(pstm_digit) * CHAR_BIT)) + / DIGIT_BIT) + 2; + return pstm_init_size(pool, a, size); +} + + +/******************************************************************************/ +/** + Reads a unsigned char array into pstm_int format. + + @param[in,out] a The allocated and initialized pstm_int + @param[in] b Pointer to a byte array of length 'c'. + @param[in] c Length in bytes of 'b'. + + @pre User should have called pstm_init_for_read_unsigned_bin first. + @note There is some grow logic here if the default pstm_init was used but we + don't really want to hit it. +*/ +int32_t pstm_read_unsigned_bin(pstm_int *a, const unsigned char *buf, uint16_t len) +{ + /* zero the int */ + pstm_zero (a); + +/* + If we know the endianness of this architecture, and we're using + 32-bit pstm_digits, we can optimize this + TODO Can optimize 64 bit case as well. +*/ +#if (defined(ENDIAN_LITTLE) || defined(ENDIAN_BIG)) && !defined(PSTM_64BIT) + /* But not for both simultaneously */ +#if defined(ENDIAN_LITTLE) && defined(ENDIAN_BIG) +#error Both ENDIAN_LITTLE and ENDIAN_BIG defined. +#endif + { + unsigned char *pd; + int16_t slen; + if ((unsigned)len > (PSTM_MAX_SIZE * sizeof(pstm_digit))) { + uint16_t excess = len - (PSTM_MAX_SIZE * sizeof(pstm_digit)); + len -= excess; + buf += excess; + } + a->used = (len + sizeof(pstm_digit) - 1) / sizeof(pstm_digit); + if (a->alloc < a->used) { + if (pstm_grow(a, a->used) != PSTM_OKAY) { + return PSTM_MEM; + } + } + pd = (unsigned char *)a->dp; + /* read the bytes in */ + /* these loops need len to go negative */ + slen = (int16_t)len; +#ifdef ENDIAN_BIG + { + /* Use Duff's device to unroll the loop. */ + uint16_t idx = (slen - 1) & ~3; + switch (slen % 4) { + case 0: do { pd[idx+0] = *buf++; + case 3: pd[idx+1] = *buf++; + case 2: pd[idx+2] = *buf++; + case 1: pd[idx+3] = *buf++; + idx -= 4; + } while ((slen -= 4) > 0); + } + } +#else + for (slen -= 1; slen >= 0; slen -= 1) { + pd[slen] = *buf++; + } +#endif + } +#else + /* Big enough based on the len? */ + a->used = (((len / sizeof(pstm_digit)) * (sizeof(pstm_digit) * CHAR_BIT)) + / DIGIT_BIT) + 2; + + if (a->alloc < a->used) { + if (pstm_grow(a, a->used) != PSTM_OKAY) { + return PSTM_MEM; + } + } + /* read the bytes in */ + for (; len > 0; len--) { + if (pstm_mul_2d (a, 8, a) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + a->dp[0] |= *buf++; + a->used += 1; + } +#endif + + pstm_clamp (a); + return PS_SUCCESS; +} + +/******************************************************************************/ +/** + Read a pstm_int from an ASN.1 formatted buffer. +*/ +int32_t pstm_read_asn(psPool_t *pool, const unsigned char **pp, uint16_t len, + pstm_int *a) +{ + const unsigned char *p = *pp; + uint16_t vlen; + + if (len < 1 || *(p++) != ASN_INTEGER || + getAsnLength(&p, len - 1, &vlen) < 0 || (len - 1) < vlen) { + return PS_PARSE_FAIL; + } + /* Make a smart size since we know the length */ + if (pstm_init_for_read_unsigned_bin(pool, a, vlen) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + if (pstm_read_unsigned_bin(a, p, vlen) != 0) { + pstm_clear(a); + psTraceCrypto("pstm_read_asn failed\n"); + return PS_PARSE_FAIL; + } + *pp = p + vlen; + return PS_SUCCESS; +} + +#ifdef USE_ECC + +#include /* toupper() */ + +/******************************************************************************/ +/** + Add a digit to an int. + c = a + b; + @param[in] pool Memory pool + @param[in] a Big integer operand + @param[in] b Big digit operand + @param[out] c Big integer result + @return < 0 on failure +*/ +int32_t pstm_add_d(psPool_t *pool, const pstm_int *a, pstm_digit b, pstm_int *c) +{ + pstm_int tmp; + int32_t res; + + if (pstm_init_size(pool, &tmp, sizeof(pstm_digit)) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + pstm_set(&tmp, b); + res = pstm_add(a, &tmp, c); + pstm_clear(&tmp); + return res; +} + +/* chars used in radix (base) conversions */ +const static unsigned char pstm_s_rmap[64] = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; + +/** + Read in data to a big integer from a given radix (base). + Typically the radix is 16 to read in hex data. + To read in binary data, use pstm_read_unsigned_bin(). + + @param[in] pool Memory pool + @param[out] a Big integer to load data into. + @param[in] buf ASCII buffer containing 'len' bytes of data to read. + @param[in] len Number of bytes to read from 'buf'. + @param[in] radix Base of data in each byte of buf. Typically 16. + @return < 0 on failure +*/ +int32_t pstm_read_radix(psPool_t *pool, pstm_int *a, + const char *buf, uint16_t len, uint8_t radix) +{ + int32_t y, neg; + unsigned char ch; + + /* make sure the radix is ok */ + if (radix < 2 || radix > 64) { + return PS_ARG_FAIL; + } + + /* if the leading digit is a minus set the sign to negative. */ + if (*buf == '-') { + ++buf; len--; + neg = PSTM_NEG; + } else { + neg = PSTM_ZPOS; + } + + /* set the integer to the default of zero */ + pstm_zero(a); + + /* process each digit of the string */ + while (len > 0) { + /* + if the radix < 36 the conversion is case insensitive this allows + numbers like 1AB and 1ab to represent the same value [e.g. in hex] + @note This casting avoids gcc -Wchar-subscripts compiler warnings + for toupper. The prototype for toupper() is strange because + the value must be in the range of unsigned char, and yet it + accepts and returns an int. + */ + ch = ((radix < 36) ? + (unsigned char)toupper((int)*buf) : (unsigned char)*buf); + for (y = 0; y < 64; y++) { + if (ch == pstm_s_rmap[y]) { + break; + } + } + + /* + if the char was found in the map and is less than the given + radix, add it to the number, otherwise exit the loop. + */ + if (y < radix) { + pstm_mul_d (a, (pstm_digit) radix, a); + pstm_add_d (pool, a, (pstm_digit) y, a); + } else { + break; + } + ++buf; len--; + } + + /* set the sign only if a != 0 */ + if (pstm_iszero(a) != PS_TRUE) { + a->sign = neg; + } + return PS_SUCCESS; +} +#endif /* USE_ECC */ + +/******************************************************************************/ + +uint16_t pstm_count_bits(const pstm_int * a) +{ + int16 r; + pstm_digit q; + + if (a->used == 0) { + return 0; + } + + /* get number of digits and add that */ + r = (a->used - 1) * DIGIT_BIT; + + /* take the last digit and count the bits in it */ + q = a->dp[a->used - 1]; + while (q > ((pstm_digit) 0)) { + ++r; + q >>= ((pstm_digit) 1); + } + return r; +} + +/******************************************************************************/ + +uint16_t pstm_unsigned_bin_size(const pstm_int *a) +{ + uint16_t size = pstm_count_bits (a); + return (size / 8 + ((size & 7) != 0 ? 1 : 0)); +} + +/******************************************************************************/ +/** + a = b, where b is a single digit. +*/ +void pstm_set(pstm_int *a, pstm_digit b) +{ + pstm_zero(a); + a->dp[0] = b; + a->used = a->dp[0] ? 1 : 0; +} + +/******************************************************************************/ +/** + Right shift 'a' by 'b' digits. + @note This is not a bit shift. +*/ +void pstm_rshd(pstm_int *a, uint16_t b) +{ + uint16_t y; + + /* too many digits just zero and return */ + if (b >= a->used) { + pstm_zero(a); + return; + } + /* shift */ + for (y = 0; y < a->used - b; y++) { + a->dp[y] = a->dp[y + b]; + } + /* zero the rest */ + for (; y < a->used; y++) { + a->dp[y] = 0; + } + /* decrement count */ + a->used -= b; + pstm_clamp(a); +} + +/******************************************************************************/ +/** + Left shift 'a' by 'b' digits. + This will grow 'a', and possibly cause a reallocation of memory. + @note This is not a bit shift. +*/ +int32_t pstm_lshd(pstm_int *a, uint16_t b) +{ + uint16_t x; + int32_t res; + + /* If its less than zero return. */ + if (b <= 0) { + return PSTM_OKAY; + } + /* Grow to fit the new digits. */ + if (a->alloc < a->used + b) { + if ((res = pstm_grow(a, a->used + b)) != PSTM_OKAY) { + return res; + } + } + + { + register pstm_digit *top, *bottom; + /* Increment the used by the shift amount then copy upwards. */ + a->used += b; + /* top */ + top = a->dp + a->used - 1; + /* base */ + bottom = a->dp + a->used - 1 - b; +/* + This is implemented using a sliding window except the window goes the + other way around. Copying from the bottom to the top. + */ + for (x = a->used - 1; x >= b; x--) { + *top-- = *bottom--; + } + /* zero the lower digits */ + top = a->dp; + for (x = 0; x < b; x++) { + *top++ = 0; + } + } + return PSTM_OKAY; +} + +/******************************************************************************/ +/** + a = 2**b. +*/ +int32_t pstm_2expt(pstm_int *a, int16_t b) +{ + uint16_t z; + + /* zero a as per default */ + pstm_zero (a); + + if (b < 0) { + return PSTM_OKAY; + } + + z = b / DIGIT_BIT; + if (z >= PSTM_MAX_SIZE) { + return PS_LIMIT_FAIL; + } + + /* set the used count of where the bit will go */ + a->used = z + 1; + + if (a->used > a->alloc) { + if (pstm_grow(a, a->used) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + + /* put the single bit in its place */ + a->dp[z] = ((pstm_digit)1) << (b % DIGIT_BIT); + return PSTM_OKAY; +} + +/******************************************************************************/ +/** + b = a * 2. + Implements multiplication as a left shift of all digits of 1 bit. +*/ +int32_t pstm_mul_2(const pstm_int *a, pstm_int * b) +{ + int32 res; + int16 x, oldused; + + /* grow to accomodate result */ + if (b->alloc < a->used + 1) { + if ((res = pstm_grow (b, a->used + 1)) != PSTM_OKAY) { + return res; + } + } + oldused = b->used; + b->used = a->used; + + { + register pstm_digit r, rr, *tmpa, *tmpb; + + /* alias for source */ + tmpa = a->dp; + + /* alias for dest */ + tmpb = b->dp; + + /* carry */ + r = 0; + for (x = 0; x < a->used; x++) { +/* + get what will be the *next* carry bit from the + MSB of the current digit +*/ + rr = *tmpa >> ((pstm_digit)(DIGIT_BIT - 1)); + /* now shift up this digit, add in the carry [from the previous] */ + *tmpb++ = ((*tmpa++ << ((pstm_digit)1)) | r); +/* + copy the carry that would be from the source + digit into the next iteration +*/ + r = rr; + } + + /* new leading digit? */ + if (r != 0 && b->used != (PSTM_MAX_SIZE-1)) { + /* add a MSB which is always 1 at this point */ + *tmpb = 1; + ++(b->used); + } + /* now zero any excess digits on the destination that we didn't write to */ + tmpb = b->dp + b->used; + for (x = b->used; x < oldused; x++) { + *tmpb++ = 0; + } + } + b->sign = a->sign; + return PSTM_OKAY; +} + +/******************************************************************************/ +/** + unsigned subtraction ||a|| must be >= ||b|| ALWAYS. + c = a - b. +*/ +int32_t s_pstm_sub(const pstm_int *a, const pstm_int *b, pstm_int *c) +{ + int16 oldbused, oldused; + int32 x; + pstm_word t; + + if (b->used > a->used) { + return PS_LIMIT_FAIL; + } + if (c->alloc < a->used) { + if ((x = pstm_grow(c, a->used)) != PSTM_OKAY) { + return x; + } + } + oldused = c->used; + oldbused = b->used; + c->used = a->used; + t = 0; + for (x = 0; x < oldbused; x++) { + t = ((pstm_word)a->dp[x]) - (((pstm_word)b->dp[x]) + t); + c->dp[x] = (pstm_digit)t; + t = (t >> DIGIT_BIT) & 1; + } + for (; x < a->used; x++) { + t = ((pstm_word)a->dp[x]) - t; + c->dp[x] = (pstm_digit)t; + t = (t >> DIGIT_BIT); + } + for (; x < oldused; x++) { + c->dp[x] = 0; + } + pstm_clamp(c); + return PSTM_OKAY; +} + +/******************************************************************************/ + +/** + Unsigned addition of two big integers. + c = a + b; + @param[in] pool Memory pool + @param[in] a Big integer operand + @param[in] b Big integer operand + @param[out] c Big integer result + @return < 0 on failure +*/ +static int32_t s_pstm_add(const pstm_int *a, const pstm_int *b, pstm_int *c) +{ + int16 x, y, oldused; + register pstm_word t, adp, bdp; + + y = a->used; + if (b->used > y) { + y = b->used; + } + oldused = c->used; + c->used = y; + + if (c->used > c->alloc) { + if (pstm_grow(c, c->used) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + + t = 0; + for (x = 0; x < y; x++) { + if (a->used <= x) { + adp = 0; + } else { + adp = (pstm_word)a->dp[x]; + } + if (b->used <= x) { + bdp = 0; + } else { + bdp = (pstm_word)b->dp[x]; + } + t += (adp) + (bdp); + c->dp[x] = (pstm_digit)t; + t >>= DIGIT_BIT; + } + if (t != 0 && x < PSTM_MAX_SIZE) { + if (c->used == c->alloc) { + if (pstm_grow(c, c->alloc + 1) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + c->dp[c->used++] = (pstm_digit)t; + ++x; + } + + c->used = x; + for (; x < oldused; x++) { + c->dp[x] = 0; + } + pstm_clamp(c); + return PSTM_OKAY; +} + + +/******************************************************************************/ +/** + Signed subtraction. a and b can be any value. + c = a - b. +*/ +int32_t pstm_sub(const pstm_int *a, const pstm_int *b, pstm_int *c) +{ + int32 res; + int16 sa, sb; + + sa = a->sign; + sb = b->sign; + + if (sa != sb) { +/* + subtract a negative from a positive, OR a positive from a negative. + For both, ADD their magnitudes, and use the sign of the first number. + */ + c->sign = sa; + if ((res = s_pstm_add (a, b, c)) != PSTM_OKAY) { + return res; + } + } else { +/* + subtract a positive from a positive, OR a negative from a negative. + First, take the difference between their magnitudes, then... + */ + if (pstm_cmp_mag (a, b) != PSTM_LT) { + /* Copy the sign from the first */ + c->sign = sa; + /* The first has a larger or equal magnitude */ + if ((res = s_pstm_sub (a, b, c)) != PSTM_OKAY) { + return res; + } + } else { + /* The result has the _opposite_ sign from the first number. */ + c->sign = (sa == PSTM_ZPOS) ? PSTM_NEG : PSTM_ZPOS; + /* The second has a larger magnitude */ + if ((res = s_pstm_sub (b, a, c)) != PSTM_OKAY) { + return res; + } + } + } + return PS_SUCCESS; +} + +/******************************************************************************/ +/** + Signed subtraction of a digit. + c = a - b, where b is a digit +*/ +int32_t pstm_sub_d(psPool_t *pool, const pstm_int *a, pstm_digit b, pstm_int *c) +{ + pstm_int tmp; + int32_t res; + + if (pstm_init_size(pool, &tmp, sizeof(pstm_digit)) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + pstm_set(&tmp, b); + res = pstm_sub(a, &tmp, c); + pstm_clear(&tmp); + return res; +} + +/******************************************************************************/ +/** + Sets up the montgomery reduction. + Fast inversion mod 2**k + Based on the fact that + XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n) + => 2*X*A - X*X*A*A = 1 + => 2*(1) - (1) = 1 + @param[in] a + @param[out] rho +*/ +int32_t pstm_montgomery_setup(const pstm_int *a, pstm_digit *rho) +{ + pstm_digit x, b; + + b = a->dp[0]; + + if ((b & 1) == 0) { + psTraceCrypto("pstm_montogomery_setup failure\n"); + return PS_ARG_FAIL; + } + + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ +#ifdef PSTM_64BIT + x *= 2 - b * x; /* here x*a==1 mod 2**64 */ +#endif + /* rho = -1/m mod b */ + *rho = (pstm_digit)(((pstm_word) 1 << ((pstm_word) DIGIT_BIT)) - + ((pstm_word)x)); + return PSTM_OKAY; +} + +/******************************************************************************/ +/** + a = B**n mod b, without division or multiplication. + Useful for normalizing numbers in a Montgomery system. + */ +int32_t pstm_montgomery_calc_normalization(pstm_int *a, const pstm_int *b) +{ + uint16_t x, bits; + + /* how many bits of last digit does b use */ + bits = pstm_count_bits(b) % DIGIT_BIT; + if (!bits) bits = DIGIT_BIT; + + /* compute A = B^(n-1) * 2^(bits-1) */ + if (b->used > 1) { + if ((x = pstm_2expt(a, (b->used - 1) * DIGIT_BIT + bits - 1)) != + PSTM_OKAY) { + return x; + } + } else { + pstm_set(a, 1); + bits = 1; + } + /* now compute C = A * B mod b */ + for (x = bits - 1; x < (uint16_t)DIGIT_BIT; x++) { + if (pstm_mul_2 (a, a) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + if (pstm_cmp_mag (a, b) != PSTM_LT) { + if (s_pstm_sub (a, b, a) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + } + return PSTM_OKAY; +} + +/******************************************************************************/ +/* + c = a * 2**d +*/ +static int32_t pstm_mul_2d(const pstm_int *a, int16_t b, pstm_int *c) +{ + pstm_digit carry, carrytmp, shift; + uint16_t x; + + /* copy it */ + if (pstm_copy(a, c) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + + /* handle whole digits */ + if (b >= DIGIT_BIT) { + if (pstm_lshd(c, b/DIGIT_BIT) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + b %= DIGIT_BIT; + + /* shift the digits */ + if (b != 0) { + carry = 0; + shift = DIGIT_BIT - b; + for (x = 0; x < c->used; x++) { + carrytmp = c->dp[x] >> shift; + c->dp[x] = (c->dp[x] << b) + carry; + carry = carrytmp; + } + /* store last carry if room */ + if (carry && x < PSTM_MAX_SIZE) { + if (c->used == c->alloc) { + if (pstm_grow(c, c->alloc + 1) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + c->dp[c->used++] = carry; + } + } + pstm_clamp(c); + return PSTM_OKAY; +} + +/******************************************************************************/ +/* + c = a mod 2**b +*/ +static int32_t pstm_mod_2d(const pstm_int *a, int16_t b, pstm_int *c) +{ + uint16_t x; + + /* zero if count less than or equal to zero */ + if (b <= 0) { + pstm_zero(c); + return PSTM_OKAY; + } + + /* get copy of input */ + if (pstm_copy(a, c) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + + /* if 2**d is larger than we just return */ + if (b >= (DIGIT_BIT * a->used)) { + return PSTM_OKAY; + } + + /* zero digits above the last digit of the modulus */ + for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) + { + c->dp[x] = 0; + } + /* clear the digit that is not completely outside/inside the modulus */ + c->dp[b / DIGIT_BIT] &= ~((pstm_digit)0) >> (DIGIT_BIT - b); + pstm_clamp (c); + return PSTM_OKAY; +} + + +/******************************************************************************/ +/* + c = a * b +*/ +int32_t pstm_mul_d(const pstm_int *a, const pstm_digit b, pstm_int *c) +{ + pstm_word w; + int32 res; + int16 x, oldused; + + if (c->alloc < a->used + 1) { + if ((res = pstm_grow (c, a->used + 1)) != PSTM_OKAY) { + return res; + } + } + oldused = c->used; + c->used = a->used; + c->sign = a->sign; + w = 0; + for (x = 0; x < a->used; x++) { + w = ((pstm_word)a->dp[x]) * ((pstm_word)b) + w; + c->dp[x] = (pstm_digit)w; + w = w >> DIGIT_BIT; + } + if (w != 0 && (a->used != PSTM_MAX_SIZE)) { + c->dp[c->used++] = (pstm_digit)w; + ++x; + } + for (; x < oldused; x++) { + c->dp[x] = 0; + } + pstm_clamp(c); + return PSTM_OKAY; +} + +/******************************************************************************/ +/** + c = a / 2**b, d = remainder. + @param[in] pool Memory pool + @param[in] a Numerator + @param[in] b Exponent of the denominator + @param[out] c The result + @param[out] d If non-NULL, the remainder of the division is stored here + @return < 0 on failure +*/ +int32_t pstm_div_2d(psPool_t *pool, const pstm_int *a, int16_t b, pstm_int *c, + pstm_int *d) +{ + pstm_digit D, r, rr; + int32 res; + int16 x; + + /* if the shift count is <= 0 then we do no work */ + if (b <= 0) { + if (pstm_copy (a, c) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + if (d != NULL) { + pstm_zero (d); + } + return PSTM_OKAY; + } + /* copy */ + if (pstm_copy(a, c) != PSTM_OKAY) { + res = PS_MEM_FAIL; + goto LBL_DONE; + } + + /* shift by as many digits in the bit count */ + if (b >= (int16_t)DIGIT_BIT) { + pstm_rshd (c, b / DIGIT_BIT); + } + + /* shift any bit count < DIGIT_BIT */ + D = (pstm_digit) (b % DIGIT_BIT); + if (D != 0) { + register pstm_digit *tmpc, mask, shift; + + /* mask */ + mask = (((pstm_digit)1) << D) - 1; + + /* shift for lsb */ + shift = DIGIT_BIT - D; + + /* alias */ + tmpc = c->dp + (c->used - 1); + + /* carry */ + r = 0; + for (x = c->used - 1; x >= 0; x--) { + /* get the lower bits of this word in a temp */ + rr = *tmpc & mask; + + /* shift the current word and mix in the carry bits from previous */ + *tmpc = (*tmpc >> D) | (r << shift); + --tmpc; + + /* set the carry to the carry bits of the current word above */ + r = rr; + } + } + pstm_clamp (c); + + res = PSTM_OKAY; +LBL_DONE: + /* set the remainder */ + if (d != NULL) { + if (pstm_mod_2d(a, b, d) != PSTM_OKAY) { + res = PS_MEM_FAIL; + } + } + return res; +} + +/******************************************************************************/ +/** + b = a / 2. + Implemented as a right shift of one bit. +*/ +int32_t pstm_div_2(const pstm_int *a, pstm_int *b) +{ + int16 x, oldused; + + if (b->alloc < a->used) { + if (pstm_grow(b, a->used) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + oldused = b->used; + b->used = a->used; + { + register pstm_digit r, rr, *tmpa, *tmpb; + + /* source alias */ + tmpa = a->dp + b->used - 1; + + /* dest alias */ + tmpb = b->dp + b->used - 1; + + /* carry */ + r = 0; + for (x = b->used - 1; x >= 0; x--) { + /* get the carry for the next iteration */ + rr = *tmpa & 1; + + /* shift the current digit, add in carry and store */ + *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); + + /* forward carry to next iteration */ + r = rr; + } + + /* zero excess digits */ + tmpb = b->dp + b->used; + for (x = b->used; x < oldused; x++) { + *tmpb++ = 0; + } + } + b->sign = a->sign; + pstm_clamp (b); + return PSTM_OKAY; +} + +/******************************************************************************/ +/* + Creates "a" then copies b into it + */ +int32_t pstm_init_copy(psPool_t *pool, pstm_int *a, const pstm_int *b, + uint8_t toSqr) +{ + int32_t res; + uint16_t x; + + if (a == b) { + return PSTM_OKAY; + } + x = b->alloc; + + if (toSqr) { +/* + Smart-size: Increasing size of a if b->used is roughly half + of b->alloc because usage has shown that a lot of these copies + go on to be squared and need these extra digits +*/ + if ((b->used * 2) + 2 >= x) { + x = (b->used * 2) + 3; + } + } + if ((res = pstm_init_size(pool, a, x)) != PSTM_OKAY) { + return res; + } + return pstm_copy(b, a); +} + +/******************************************************************************/ +/* + With some compilers, we have seen issues linking with the builtin + 64 bit division routine. The issues with either manifest in a failure + to find 'udivdi3' at link time, or a runtime invalid instruction fault + during an RSA operation. + The routine below divides a 64 bit unsigned int by a 32 bit unsigned int + explicitly, rather than using the division operation + The 64 bit result is placed in the 'numerator' parameter + The 32 bit mod (remainder) of the division is the return parameter + Based on implementations by: + Copyright (C) 2003 Bernardo Innocenti + Copyright (C) 1999 Hewlett-Packard Co + Copyright (C) 1999 David Mosberger-Tang +*/ +#if defined(USE_MATRIX_DIV64) && defined(PSTM_32BIT) +static uint32 psDiv64(uint64 *numerator, uint32 denominator) +{ + uint64 rem = *numerator; + uint64 b = denominator; + uint64 res = 0; + uint64 d = 1; + uint32 high = rem >> 32; + + if (high >= denominator) { + high /= denominator; + res = (uint64) high << 32; + rem -= (uint64) (high * denominator) << 32; + } + while ((int64)b > 0 && b < rem) { + b = b+b; + d = d+d; + } + do { + if (rem >= b) { + rem -= b; + res += d; + } + b >>= 1; + d >>= 1; + } while (d); + *numerator = res; + return rem; +} +#endif /* USE_MATRIX_DIV64 */ + +#if defined(USE_MATRIX_DIV128) && defined(PSTM_64BIT) +typedef unsigned long uint128 __attribute__ ((mode(TI))); +static uint64 psDiv128(uint128 *numerator, uint64 denominator) +{ + uint128 rem = *numerator; + uint128 b = denominator; + uint128 res = 0; + uint128 d = 1; + uint64 high = rem >> 64; + + if (high >= denominator) { + high /= denominator; + res = (uint128) high << 64; + rem -= (uint128) (high * denominator) << 64; + } + while ((uint128)b > 0 && b < rem) { + b = b+b; + d = d+d; + } + do { + if (rem >= b) { + rem -= b; + res += d; + } + b >>= 1; + d >>= 1; + } while (d); + *numerator = res; + return rem; +} +#endif /* USE_MATRIX_DIV128 */ + +/******************************************************************************/ +/** + c = a / b, d = remainder. + + @param[in] pool Memory pool + @param[in] a Numerator + @param[in] b Denominator + @param[out] c The result + @param[out] d If non-NULL, the remainder of the division is stored here + @return < 0 on failure + + a/b => cb + d == a +*/ +int32_t pstm_div(psPool_t *pool, const pstm_int *a, const pstm_int *b, pstm_int *c, + pstm_int *d) +{ + pstm_int q, x, y, t1, t2; + int32_t res; + int16 n, t, i, norm, neg; + + /* is divisor zero ? */ + if (pstm_iszero (b) == 1) { + return PS_LIMIT_FAIL; + } + + /* if a < b then q=0, r = a */ + if (pstm_cmp_mag (a, b) == PSTM_LT) { + if (d != NULL) { + if (pstm_copy(a, d) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + if (c != NULL) { + pstm_zero (c); + } + return PSTM_OKAY; + } + /* Smart-size inits */ + if ((res = pstm_init_size(pool, &t1, a->alloc)) != PSTM_OKAY) { + return res; + } + if ((res = pstm_init_size(pool, &t2, 3)) != PSTM_OKAY) { + goto LBL_T1; + } + if ((res = pstm_init_copy(pool, &x, a, 0)) != PSTM_OKAY) { + goto LBL_T2; + } + /* Used to be an init_copy on b but pstm_grow was always hit with triple size */ + if ((res = pstm_init_size(pool, &y, b->used * 3)) != PSTM_OKAY) { + goto LBL_X; + } + if ((res = pstm_copy(b, &y)) != PSTM_OKAY) { + goto LBL_Y; + } + + /* fix the sign */ + neg = (a->sign == b->sign) ? PSTM_ZPOS : PSTM_NEG; + x.sign = y.sign = PSTM_ZPOS; + + /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */ + norm = pstm_count_bits(&y) % DIGIT_BIT; + if (norm < (int16_t)(DIGIT_BIT-1)) { + norm = (DIGIT_BIT-1) - norm; + if ((res = pstm_mul_2d(&x, norm, &x)) != PSTM_OKAY) { + goto LBL_Y; + } + if ((res = pstm_mul_2d(&y, norm, &y)) != PSTM_OKAY) { + goto LBL_Y; + } + } else { + norm = 0; + } + + /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ + n = x.used - 1; + t = y.used - 1; + + if ((res = pstm_init_size(pool, &q, (n - t) + 1)) != PSTM_OKAY) { + goto LBL_Y; + } + q.used = (n - t) + 1; + + /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ + if ((res = pstm_lshd(&y, n - t)) != PSTM_OKAY) { /* y = y*b**{n-t} */ + goto LBL_Q; + } + + while (pstm_cmp(&x, &y) != PSTM_LT) { + ++(q.dp[n - t]); + if ((res = pstm_sub(&x, &y, &x)) != PSTM_OKAY) { + goto LBL_Q; + } + } + + /* reset y by shifting it back down */ + pstm_rshd (&y, n - t); + + /* step 3. for i from n down to (t + 1) */ + for (i = n; i >= (t + 1); i--) { + if (i > x.used) { + continue; + } + + /* step 3.1 if xi == yt then set q{i-t-1} to b-1, + * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ + if (x.dp[i] == y.dp[t]) { + q.dp[i - t - 1] = (pstm_digit)((((pstm_word)1) << DIGIT_BIT) - 1); + } else { + pstm_word tmp; + tmp = ((pstm_word) x.dp[i]) << ((pstm_word) DIGIT_BIT); + tmp |= ((pstm_word) x.dp[i - 1]); +#if defined(USE_MATRIX_DIV64) && defined(PSTM_32BIT) + psDiv64(&tmp, y.dp[t]); +#elif defined(USE_MATRIX_DIV128) && defined(PSTM_64BIT) + psDiv128(&tmp, y.dp[t]); +#else + tmp /= ((pstm_word) y.dp[t]); +#endif /* USE_MATRIX_DIV64 */ + q.dp[i - t - 1] = (pstm_digit) (tmp); + } + + /* while (q{i-t-1} * (yt * b + y{t-1})) > + xi * b**2 + xi-1 * b + xi-2 + + do q{i-t-1} -= 1; + */ + q.dp[i - t - 1] = (q.dp[i - t - 1] + 1); + do { + q.dp[i - t - 1] = (q.dp[i - t - 1] - 1); + + /* find left hand */ + pstm_zero (&t1); + t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1]; + t1.dp[1] = y.dp[t]; + t1.used = 2; + if ((res = pstm_mul_d (&t1, q.dp[i - t - 1], &t1)) != PSTM_OKAY) { + goto LBL_Q; + } + + /* find right hand */ + t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2]; + t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1]; + t2.dp[2] = x.dp[i]; + t2.used = 3; + } while (pstm_cmp_mag(&t1, &t2) == PSTM_GT); + + /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ + if ((res = pstm_mul_d(&y, q.dp[i - t - 1], &t1)) != PSTM_OKAY) { + goto LBL_Q; + } + + if ((res = pstm_lshd(&t1, i - t - 1)) != PSTM_OKAY) { + goto LBL_Q; + } + + if ((res = pstm_sub(&x, &t1, &x)) != PSTM_OKAY) { + goto LBL_Q; + } + + /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ + if (x.sign == PSTM_NEG) { + if ((res = pstm_copy(&y, &t1)) != PSTM_OKAY) { + goto LBL_Q; + } + if ((res = pstm_lshd (&t1, i - t - 1)) != PSTM_OKAY) { + goto LBL_Q; + } + if ((res = pstm_add (&x, &t1, &x)) != PSTM_OKAY) { + goto LBL_Q; + } + q.dp[i - t - 1] = q.dp[i - t - 1] - 1; + } + } +/* + now q is the quotient and x is the remainder (which we have to normalize) +*/ + /* get sign before writing to c */ + x.sign = x.used == 0 ? PSTM_ZPOS : a->sign; + + if (c != NULL) { + pstm_clamp (&q); + if (pstm_copy (&q, c) != PSTM_OKAY) { + res = PS_MEM_FAIL; + goto LBL_Q; + } + c->sign = neg; + } + + if (d != NULL) { + if ((res = pstm_div_2d (pool, &x, norm, &x, NULL)) != PSTM_OKAY) { + goto LBL_Q; + } +/* + the following is a kludge, essentially we were seeing the right + remainder but with excess digits that should have been zero + */ + for (i = b->used; i < x.used; i++) { + x.dp[i] = 0; + } + pstm_clamp(&x); + if (pstm_copy (&x, d) != PSTM_OKAY) { + res = PS_MEM_FAIL; + goto LBL_Q; + } + } + + res = PSTM_OKAY; + +LBL_Q:pstm_clear (&q); +LBL_Y:pstm_clear (&y); +LBL_X:pstm_clear (&x); +LBL_T2:pstm_clear (&t2); +LBL_T1:pstm_clear (&t1); + + return res; +} + +/******************************************************************************/ +/* + Swap the elements of two integers, for cases where you can't simply swap + the pstm_int pointers around +*/ +void pstm_exch(pstm_int * a, pstm_int * b) +{ + pstm_int t; + + t = *a; + *a = *b; + *b = t; +} + +/******************************************************************************/ +/* + c = a mod b, 0 <= c < b +*/ +int32_t pstm_mod(psPool_t *pool, const pstm_int *a, const pstm_int *b, pstm_int *c) +{ + pstm_int t; + int32_t err; + + /* Smart-size */ + if ((err = pstm_init_size(pool, &t, b->alloc)) != PSTM_OKAY) { + return err; + } + if ((err = pstm_div(pool, a, b, NULL, &t)) != PSTM_OKAY) { + pstm_clear(&t); + return err; + } + if (t.sign != b->sign) { + err = pstm_add(&t, b, c); + } else { + pstm_exch(&t, c); + } + pstm_clear(&t); + return err; +} + +/******************************************************************************/ +/* + d = a * b (mod c) +*/ +int32_t pstm_mulmod(psPool_t *pool, const pstm_int *a, const pstm_int *b, + const pstm_int *c, pstm_int *d) +{ + int32_t res; + uint16_t size; + pstm_int tmp; + +/* + Smart-size pstm_inits. d is an output that is influenced by this local 't' + so don't shrink 'd' if it wants to becuase this will lead to an pstm_grow + in RSA operations +*/ + size = a->used + b->used + 1; + if ((a == d) && (size < a->alloc)) { + size = a->alloc; + } + if ((res = pstm_init_size(pool, &tmp, size)) != PSTM_OKAY) { + return res; + } + if ((res = pstm_mul_comba(pool, a, b, &tmp, NULL, 0)) != PSTM_OKAY) { + pstm_clear(&tmp); + return res; + } + res = pstm_mod(pool, &tmp, c, d); + pstm_clear(&tmp); + return res; +} + +/******************************************************************************/ +/* + * y = g**x (mod b) + * Some restrictions... x must be positive and < b + */ +int32_t pstm_exptmod(psPool_t *pool, const pstm_int *G, const pstm_int *X, + const pstm_int *P, pstm_int *Y) +{ + pstm_int M[32], res; /* Keep this winsize based: (1 << max_winsize) */ + pstm_digit buf, mp; + pstm_digit *paD; + int32 err, bitbuf; + int16 bitcpy, bitcnt, mode, digidx, x, y, winsize; + uint32 paDlen; + + /* set window size from what user set as optimization */ + x = pstm_count_bits(X); + if (x < 50) { + winsize = 2; + } else { + winsize = PS_EXPTMOD_WINSIZE; + } + + /* now setup montgomery */ + if ((err = pstm_montgomery_setup (P, &mp)) != PSTM_OKAY) { + return err; + } + + /* setup result */ + if ((err = pstm_init_size(pool, &res, (P->used * 2) + 1)) != PSTM_OKAY) { + return err; + } +/* + create M table + The M table contains powers of the input base, e.g. M[x] = G^x mod P + The first half of the table is not computed though except for M[0] and M[1] + */ + /* now we need R mod m */ + if ((err = pstm_montgomery_calc_normalization (&res, P)) != PSTM_OKAY) { + goto LBL_RES; + } +/* + init M array + init first cell + */ + if ((err = pstm_init_size(pool, &M[1], res.used)) != PSTM_OKAY) { + goto LBL_RES; + } + + /* now set M[1] to G * R mod m */ + if (pstm_cmp_mag(P, G) != PSTM_GT) { + /* G > P so we reduce it first */ + if ((err = pstm_mod(pool, G, P, &M[1])) != PSTM_OKAY) { + goto LBL_M; + } + } else { + if ((err = pstm_copy(G, &M[1])) != PSTM_OKAY) { + goto LBL_M; + } + } + if ((err = pstm_mulmod (pool, &M[1], &res, P, &M[1])) != PSTM_OKAY) { + goto LBL_M; + } + /* Pre-allocated digit. Used for mul, sqr, AND reduce */ + paDlen = ((M[1].used + 3) * 2) * sizeof(pstm_digit); + if ((paD = psMalloc(pool, paDlen)) == NULL) { + err = PS_MEM_FAIL; + goto LBL_M; + } + /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ + if (pstm_init_copy(pool, &M[1 << (winsize - 1)], &M[1], 1) != PSTM_OKAY) { + err = PS_MEM_FAIL; + goto LBL_PAD; + } + for (x = 0; x < (winsize - 1); x++) { + if ((err = pstm_sqr_comba (pool, &M[1 << (winsize - 1)], + &M[1 << (winsize - 1)], paD, paDlen)) != PSTM_OKAY) { + goto LBL_PAD; + } + if ((err = pstm_montgomery_reduce(pool, &M[1 << (winsize - 1)], P, mp, + paD, paDlen)) != PSTM_OKAY) { + goto LBL_PAD; + } + } + /* now init the second half of the array */ + for (x = (1<<(winsize-1)) + 1; x < (1 << winsize); x++) { + if ((err = pstm_init_size(pool, &M[x], M[1<<(winsize-1)].alloc + 1)) + != PSTM_OKAY) { + for (y = 1<<(winsize-1); y < x; y++) { + pstm_clear(&M[y]); + } + goto LBL_PAD; + } + } + + /* create upper table */ + for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { + if ((err = pstm_mul_comba(pool, &M[x - 1], &M[1], &M[x], paD, paDlen)) + != PSTM_OKAY) { + goto LBL_MARRAY; + } + if ((err = pstm_montgomery_reduce(pool, &M[x], P, mp, paD, paDlen)) != + PSTM_OKAY) { + goto LBL_MARRAY; + } + } + + /* set initial mode and bit cnt */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = X->used - 1; + bitcpy = 0; + bitbuf = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits so break */ + if (digidx == -1) { + break; + } + /* read next digit and reset bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int32)DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (pstm_digit)(buf >> (DIGIT_BIT - 1)) & 1; + buf <<= (pstm_digit)1; +/* + If the bit is zero and mode == 0 then we ignore it. + These represent the leading zero bits before the first 1 bit + in the exponent. Technically this opt is not required but it + does lower the # of trivial squaring/reductions used +*/ + if (mode == 0 && y == 0) { + continue; + } + + /* if the bit is zero and mode == 1 then we square */ + if (mode == 1 && y == 0) { + if ((err = pstm_sqr_comba(pool, &res, &res, paD, paDlen)) != + PSTM_OKAY) { + goto LBL_MARRAY; + } + if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen)) + != PSTM_OKAY) { + goto LBL_MARRAY; + } + continue; + } + + /* else we add it to the window */ + bitbuf |= (y << (winsize - ++bitcpy)); + mode = 2; + + if (bitcpy == winsize) { + /* ok window is filled so square as required and mul square first */ + for (x = 0; x < winsize; x++) { + if ((err = pstm_sqr_comba(pool, &res, &res, paD, paDlen)) != + PSTM_OKAY) { + goto LBL_MARRAY; + } + if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, + paDlen)) != PSTM_OKAY) { + goto LBL_MARRAY; + } + } + + /* then multiply */ + if ((err = pstm_mul_comba(pool, &res, &M[bitbuf], &res, paD, + paDlen)) != PSTM_OKAY) { + goto LBL_MARRAY; + } + if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen)) + != PSTM_OKAY) { + goto LBL_MARRAY; + } + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then square/multiply */ + if (mode == 2 && bitcpy > 0) { + /* square then multiply if the bit is set */ + for (x = 0; x < bitcpy; x++) { + if ((err = pstm_sqr_comba(pool, &res, &res, paD, paDlen)) != + PSTM_OKAY) { + goto LBL_MARRAY; + } + if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen)) + != PSTM_OKAY) { + goto LBL_MARRAY; + } + + /* get next bit of the window */ + bitbuf <<= 1; + if ((bitbuf & (1 << winsize)) != 0) { + /* then multiply */ + if ((err = pstm_mul_comba(pool, &res, &M[1], &res, paD, paDlen)) + != PSTM_OKAY) { + goto LBL_MARRAY; + } + if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, + paDlen)) != PSTM_OKAY) { + goto LBL_MARRAY; + } + } + } + } +/* + Fix up result if Montgomery reduction is used recall that any value in a + Montgomery system is actually multiplied by R mod n. So we have to reduce + one more time to cancel out the factor of R. +*/ + if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen)) != + PSTM_OKAY) { + goto LBL_MARRAY; + } + /* swap res with Y */ + if ((err = pstm_copy (&res, Y)) != PSTM_OKAY) { + goto LBL_MARRAY; + } + err = PSTM_OKAY; +LBL_MARRAY: + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + pstm_clear(&M[x]); + } +LBL_PAD:psFree(paD, pool); +LBL_M: pstm_clear(&M[1]); +LBL_RES:pstm_clear(&res); + return err; +} + +/******************************************************************************/ +/** + c = a + b. +*/ +int32_t pstm_add(const pstm_int *a, const pstm_int *b, pstm_int *c) +{ + int32_t res; + uint8_t sa, sb; + + /* get sign of both inputs */ + sa = a->sign; + sb = b->sign; + + /* handle two cases, not four */ + if (sa == sb) { + /* both positive or both negative, add their mags, copy the sign */ + c->sign = sa; + if ((res = s_pstm_add (a, b, c)) != PSTM_OKAY) { + return res; + } + } else { +/* + one positive, the other negative + subtract the one with the greater magnitude from the one of the lesser + magnitude. The result gets the sign of the one with the greater mag. + */ + if (pstm_cmp_mag(a, b) == PSTM_LT) { + c->sign = sb; + if ((res = s_pstm_sub (b, a, c)) != PSTM_OKAY) { + return res; + } + } else { + c->sign = sa; + if ((res = s_pstm_sub (a, b, c)) != PSTM_OKAY) { + return res; + } + } + } + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + No reverse. Useful in some of the EIP-154 PKA stuff where special byte + order seems to come into play more often +*/ +int32_t pstm_to_unsigned_bin_nr(psPool_t *pool, const pstm_int *a, unsigned char *b) +{ + int32_t res; + uint16_t x; + pstm_int t = { 0 }; + + if ((res = pstm_init_copy(pool, &t, a, 0)) != PSTM_OKAY) { + return res; + } + + x = 0; + while (pstm_iszero (&t) == 0) { + b[x++] = (unsigned char) (t.dp[0] & 255); + if ((res = pstm_div_2d (pool, &t, 8, &t, NULL)) != PSTM_OKAY) { + pstm_clear(&t); + return res; + } + } + pstm_clear(&t); + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + reverse an array, used for unsigned bin code +*/ +static void pstm_reverse(unsigned char *s, uint16_t len) +{ + uint16_t ix, iy; + unsigned char t; + + ix = 0; + iy = len - 1; + while (ix < iy) { + t = s[ix]; + s[ix] = s[iy]; + s[iy] = t; + ++ix; + --iy; + } +} + +/******************************************************************************/ +/** + Write a pstm format integer to a raw binary format. + @return < 0 on failure. PS_SUCCESS on success. +*/ +int32_t pstm_to_unsigned_bin(psPool_t *pool, const pstm_int *a, unsigned char *b) + +{ + int32_t res; + uint16_t x; + pstm_int t = { 0 }; + + if ((res = pstm_init_copy(pool, &t, a, 0)) != PSTM_OKAY) { + return res; + } + x = 0; + while (pstm_iszero (&t) == 0) { + b[x++] = (unsigned char) (t.dp[0] & 255); + if ((res = pstm_div_2d (pool, &t, 8, &t, NULL)) != PSTM_OKAY) { + pstm_clear(&t); + return res; + } + } + pstm_reverse (b, x); + pstm_clear(&t); + return PS_SUCCESS; +} + +/******************************************************************************/ +/** + c = 1/a (mod b). + + @note Slow version supporting an even 'b'. Should call pstm_invmod() and let it + decide which to use. + + Need invmod for ECC and also private key loading for hardware crypto + in cases where dQ > dP. The values must be switched and a new qP must be + calculated using this function +*/ +static int32_t pstm_invmod_slow(psPool_t *pool, const pstm_int *a, + const pstm_int *b, pstm_int * c) +{ + pstm_int x, y, u, v, A, B, C, D; + int32 res; + + /* b cannot be negative */ + if (b->sign == PSTM_NEG || pstm_iszero(b) == 1) { + return PS_LIMIT_FAIL; + } + + /* init temps */ + if (pstm_init_size(pool, &x, b->used) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + + /* x = a, y = b */ + if ((res = pstm_mod(pool, a, b, &x)) != PSTM_OKAY) { + goto LBL_X; + } + + if (pstm_init_copy(pool, &y, b, 0) != PSTM_OKAY) { + goto LBL_X; + } + + /* 2. [modified] if x,y are both even then return an error! */ + if (pstm_iseven (&x) == 1 && pstm_iseven (&y) == 1) { + res = PS_FAILURE; + goto LBL_Y; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((res = pstm_init_copy(pool, &u, &x, 0)) != PSTM_OKAY) { + goto LBL_Y; + } + if ((res = pstm_init_copy(pool, &v, &y, 0)) != PSTM_OKAY) { + goto LBL_U; + } + + if ((res = pstm_init_size(pool, &A, sizeof(pstm_digit))) != PSTM_OKAY) { + goto LBL_V; + } + + if ((res = pstm_init_size(pool, &D, sizeof(pstm_digit))) != PSTM_OKAY) { + goto LBL_A; + } + pstm_set (&A, 1); + pstm_set (&D, 1); + + if ((res = pstm_init(pool, &B)) != PSTM_OKAY) { + goto LBL_D; + } + if ((res = pstm_init(pool, &C)) != PSTM_OKAY) { + goto LBL_B; + } + +top: + /* 4. while u is even do */ + while (pstm_iseven (&u) == 1) { + /* 4.1 u = u/2 */ + if ((res = pstm_div_2(&u, &u)) != PSTM_OKAY) { + goto LBL_C; + } + + /* 4.2 if A or B is odd then */ + if (pstm_isodd(&A) == 1 || pstm_isodd (&B) == 1) { + /* A = (A+y)/2, B = (B-x)/2 */ + if ((res = pstm_add(&A, &y, &A)) != PSTM_OKAY) { + goto LBL_C; + } + if ((res = pstm_sub(&B, &x, &B)) != PSTM_OKAY) { + goto LBL_C; + } + } + /* A = A/2, B = B/2 */ + if ((res = pstm_div_2(&A, &A)) != PSTM_OKAY) { + goto LBL_C; + } + if ((res = pstm_div_2(&B, &B)) != PSTM_OKAY) { + goto LBL_C; + } + } + + /* 5. while v is even do */ + while (pstm_iseven(&v) == 1) { + /* 5.1 v = v/2 */ + if ((res = pstm_div_2(&v, &v)) != PSTM_OKAY) { + goto LBL_C; + } + + /* 5.2 if C or D is odd then */ + if (pstm_isodd(&C) == 1 || pstm_isodd(&D) == 1) { + /* C = (C+y)/2, D = (D-x)/2 */ + if ((res = pstm_add(&C, &y, &C)) != PSTM_OKAY) { + goto LBL_C; + } + if ((res = pstm_sub(&D, &x, &D)) != PSTM_OKAY) { + goto LBL_C; + } + } + /* C = C/2, D = D/2 */ + if ((res = pstm_div_2(&C, &C)) != PSTM_OKAY) { + goto LBL_C; + } + if ((res = pstm_div_2(&D, &D)) != PSTM_OKAY) { + goto LBL_C; + } + } + + /* 6. if u >= v then */ + if (pstm_cmp(&u, &v) != PSTM_LT) { + /* u = u - v, A = A - C, B = B - D */ + if ((res = pstm_sub(&u, &v, &u)) != PSTM_OKAY) { + goto LBL_C; + } + if ((res = pstm_sub(&A, &C, &A)) != PSTM_OKAY) { + goto LBL_C; + } + if ((res = pstm_sub(&B, &D, &B)) != PSTM_OKAY) { + goto LBL_C; + } + } else { + /* v - v - u, C = C - A, D = D - B */ + if ((res = pstm_sub(&v, &u, &v)) != PSTM_OKAY) { + goto LBL_C; + } + if ((res = pstm_sub(&C, &A, &C)) != PSTM_OKAY) { + goto LBL_C; + } + if ((res = pstm_sub(&D, &B, &D)) != PSTM_OKAY) { + goto LBL_C; + } + } + + /* if not zero goto step 4 */ + if (pstm_iszero(&u) == 0) + goto top; + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (pstm_cmp_d(&v, 1) != PSTM_EQ) { + res = PS_FAILURE; + goto LBL_C; + } + + /* if its too low */ + while (pstm_cmp_d(&C, 0) == PSTM_LT) { + if ((res = pstm_add(&C, b, &C)) != PSTM_OKAY) { + goto LBL_C; + } + } + + /* too big */ + while (pstm_cmp_mag(&C, b) != PSTM_LT) { + if ((res = pstm_sub(&C, b, &C)) != PSTM_OKAY) { + goto LBL_C; + } + } + + /* C is now the inverse */ + if ((res = pstm_copy(&C, c)) != PSTM_OKAY) { + goto LBL_C; + } + res = PSTM_OKAY; + +LBL_C: pstm_clear(&C); +LBL_D: pstm_clear(&D); +LBL_B: pstm_clear(&B); +LBL_A: pstm_clear(&A); +LBL_V: pstm_clear(&v); +LBL_U: pstm_clear(&u); +LBL_Y: pstm_clear(&y); +LBL_X: pstm_clear(&x); + + return res; +} + +/** + c = 1/a (mod b). + This code is for for odd 'b'. pstm_invmod_slow() will be called if 'b' + is even. +*/ +int32_t pstm_invmod(psPool_t *pool, const pstm_int *a, const pstm_int *b, pstm_int *c) +{ + pstm_int x, y, u, v, B, D; + int32 res; + uint16 neg, sanity; + + /* 2. [modified] b must be odd */ + if (pstm_iseven (b) == 1) { + return pstm_invmod_slow(pool, a,b,c); + } + + /* x == modulus, y == value to invert */ + if ((res = pstm_init_copy(pool, &x, b, 0)) != PSTM_OKAY) { + return res; + } + + if ((res = pstm_init_size(pool, &y, a->alloc)) != PSTM_OKAY) { + goto LBL_X; + } + + /* we need y = |a| */ + pstm_abs(a, &y); + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((res = pstm_init_copy(pool, &u, &x, 0)) != PSTM_OKAY) { + goto LBL_Y; + } + if ((res = pstm_init_copy(pool, &v, &y, 0)) != PSTM_OKAY) { + goto LBL_U; + } + if ((res = pstm_init(pool, &B)) != PSTM_OKAY) { + goto LBL_V; + } + if ((res = pstm_init(pool, &D)) != PSTM_OKAY) { + goto LBL_B; + } + + pstm_set (&D, 1); + + sanity = 0; +top: + /* 4. while u is even do */ + while (pstm_iseven (&u) == 1) { + /* 4.1 u = u/2 */ + if ((res = pstm_div_2 (&u, &u)) != PSTM_OKAY) { + goto LBL_D; + } + + /* 4.2 if B is odd then */ + if (pstm_isodd (&B) == 1) { + if ((res = pstm_sub (&B, &x, &B)) != PSTM_OKAY) { + goto LBL_D; + } + } + /* B = B/2 */ + if ((res = pstm_div_2 (&B, &B)) != PSTM_OKAY) { + goto LBL_D; + } + } + + /* 5. while v is even do */ + while (pstm_iseven (&v) == 1) { + /* 5.1 v = v/2 */ + if ((res = pstm_div_2 (&v, &v)) != PSTM_OKAY) { + goto LBL_D; + } + /* 5.2 if D is odd then */ + if (pstm_isodd (&D) == 1) { + /* D = (D-x)/2 */ + if ((res = pstm_sub (&D, &x, &D)) != PSTM_OKAY) { + goto LBL_D; + } + } + /* D = D/2 */ + if ((res = pstm_div_2 (&D, &D)) != PSTM_OKAY) { + goto LBL_D; + } + } + + /* 6. if u >= v then */ + if (pstm_cmp(&u, &v) != PSTM_LT) { + /* u = u - v, B = B - D */ + if ((res = pstm_sub (&u, &v, &u)) != PSTM_OKAY) { + goto LBL_D; + } + if ((res = pstm_sub (&B, &D, &B)) != PSTM_OKAY) { + goto LBL_D; + } + } else { + /* v - v - u, D = D - B */ + if ((res = pstm_sub (&v, &u, &v)) != PSTM_OKAY) { + goto LBL_D; + } + if ((res = pstm_sub (&D, &B, &D)) != PSTM_OKAY) { + goto LBL_D; + } + } + + /* if not zero goto step 4 */ + if (sanity++ > 1000) { + res = PS_LIMIT_FAIL; + goto LBL_D; + } + if (pstm_iszero (&u) == 0) { + goto top; + } + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (pstm_cmp_d(&v, 1) != PSTM_EQ) { + res = PS_FAILURE; + goto LBL_D; + } + + /* b is now the inverse */ + neg = a->sign; + while (D.sign == PSTM_NEG) { + if ((res = pstm_add (&D, b, &D)) != PSTM_OKAY) { + goto LBL_D; + } + } + if ((res = pstm_copy (&D, c)) != PSTM_OKAY) { + goto LBL_D; + } + c->sign = neg; + res = PSTM_OKAY; + +LBL_D: pstm_clear(&D); +LBL_B: pstm_clear(&B); +LBL_V: pstm_clear(&v); +LBL_U: pstm_clear(&u); +LBL_Y: pstm_clear(&y); +LBL_X: pstm_clear(&x); + return res; +} + +/******************************************************************************/ + + +#endif /* USE_MATRIX_RSA || USE_CL_RSA || USE_MATRIX_ECC || USE_MATRIX_DH \ + || USE_CL_DH || USE_QUICK_ASSIST_RSA || USE_QUICK_ASSIST_ECC */ + +/******************************************************************************/ + diff --git a/crypto/math/pstm.h b/crypto/math/pstm.h new file mode 100644 index 0000000..ef30fc6 --- /dev/null +++ b/crypto/math/pstm.h @@ -0,0 +1,245 @@ +/** + * @file pstm.h + * @version $Format:%h%d$ + * + * multiple-precision integer library. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_PSTMATH +#define _h_PSTMATH + +#include "../cryptoApi.h" + +#if defined(USE_MATRIX_RSA) || defined(USE_CL_RSA) \ + || defined(USE_MATRIX_ECC) \ + || defined(USE_MATRIX_DH) || defined(USE_CL_DH) \ + || defined(USE_QUICK_ASSIST_RSA) || defined(USE_QUICK_ASSIST_ECC) + +#if defined(PS_PUBKEY_OPTIMIZE_FOR_FASTER_SPEED) && defined(PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM) +#error "May only enable either PS_PUBKEY_OPTIMIZE_FOR_FASTER_SPEED or PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM" +#endif + +#if !defined(PS_PUBKEY_OPTIMIZE_FOR_FASTER_SPEED) && !defined(PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM) +#define PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM +#endif + +#ifdef PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM +#define PS_EXPTMOD_WINSIZE 3 +#endif + +#ifdef PS_PUBKEY_OPTIMIZE_FOR_FASTER_SPEED +#define PS_EXPTMOD_WINSIZE 5 +#endif + +/******************************************************************************/ +/* Define this here to avoid including circular limits.h on some platforms */ +#ifndef CHAR_BIT + #define CHAR_BIT 8 +#endif + +/******************************************************************************/ +/* + If native 64 bit integers are not supported, we do not support 32x32->64 + in hardware, so we must set the 16 bit flag to produce 16x16->32 products. +*/ +#ifndef HAVE_NATIVE_INT64 + #define PSTM_16BIT +#endif /* ! HAVE_NATIVE_INT64 */ + +/******************************************************************************/ +/* + Some default configurations. + + pstm_word should be the largest value the processor can hold as the product + of a multiplication. Most platforms support a 32x32->64 MAC instruction, + so 64bits is the default pstm_word size. + pstm_digit should be half the size of pstm_word + */ +#ifdef PSTM_8BIT +/* 8-bit digits, 16-bit word products */ + typedef unsigned char pstm_digit; + typedef unsigned short pstm_word; + #define DIGIT_BIT 8 + +#elif defined(PSTM_16BIT) +/* 16-bit digits, 32-bit word products */ + typedef unsigned short pstm_digit; + typedef unsigned long pstm_word; + #define DIGIT_BIT 16 + +#elif defined(PSTM_64BIT) +/* 64-bit digits, 128-bit word products */ + #ifndef __GNUC__ + #error "64bit digits requires GCC" + #endif + typedef unsigned long pstm_digit; + typedef unsigned long pstm_word __attribute__ ((mode(TI))); + #define DIGIT_BIT 64 + +#else +/* This is the default case, 32-bit digits, 64-bit word products */ + typedef uint32 pstm_digit; + typedef uint64 pstm_word; + #define DIGIT_BIT 32 + #define PSTM_32BIT +#endif /* digit and word size */ + +#define PSTM_MASK (pstm_digit)(-1) +#define PSTM_DIGIT_MAX PSTM_MASK + +/******************************************************************************/ +/* + equalities + */ +#define PSTM_LT -1 /* less than */ +#define PSTM_EQ 0 /* equal to */ +#define PSTM_GT 1 /* greater than */ + +#define PSTM_ZPOS 0 /* pstm_int.sign positive */ +#define PSTM_NEG 1 /* pstm_int.sign negative */ + +#define PSTM_OKAY PS_SUCCESS +#define PSTM_MEM PS_MEM_FAIL + +/******************************************************************************/ +/* This is the maximum size that pstm_int.alloc can be for crypto operations. + Effectively, it is three times the size of the largest private key. */ +#define PSTM_MAX_SIZE ((4096 / DIGIT_BIT) * 3) + +typedef struct { + pstm_digit *dp; + psPool_t *pool; +#if defined (__GNUC__) || defined(__llvm__) + /* Save a little space with compilers we know will handle this right */ + uint32_t used:12, + alloc:12, + sign:1; +#else + uint16_t used; + uint16_t alloc; + uint8_t sign; +#endif +} pstm_int; + +/******************************************************************************/ +/* + Operations on large integers + */ +#define pstm_iszero(a) (((a)->used == 0) ? PS_TRUE : PS_FALSE) +#define pstm_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? PS_TRUE : PS_FALSE) +#define pstm_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? PS_TRUE : PS_FALSE) +#define pstm_abs(a, b) { pstm_copy(a, b); (b)->sign = 0; } + +extern void pstm_set(pstm_int *a, pstm_digit b); +extern void pstm_zero(pstm_int *a); + +extern int32_t pstm_init(psPool_t *pool, pstm_int *a); +extern int32_t pstm_init_size(psPool_t *pool, pstm_int *a, uint16_t size); +extern int32_t pstm_init_copy(psPool_t *pool, pstm_int *a, const pstm_int *b, + uint8_t toSqr); +extern int32_t pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a, + uint16_t len); + +extern int32_t pstm_grow(pstm_int *a, uint16_t size); +extern void pstm_clamp(pstm_int *a); + +extern int32_t pstm_copy(const pstm_int *a, pstm_int *b); +extern void pstm_exch(pstm_int *a, pstm_int *b); + +extern void pstm_clear(pstm_int *a); +extern void pstm_clear_multi( + pstm_int *mp0, pstm_int *mp1, pstm_int *mp2, pstm_int *mp3, + pstm_int *mp4, pstm_int *mp5, pstm_int *mp6, pstm_int *mp7); + +extern uint16_t pstm_unsigned_bin_size(const pstm_int *a); +extern uint16_t pstm_count_bits(const pstm_int *a); + +extern int32_t pstm_read_unsigned_bin(pstm_int *a, + const unsigned char *buf, uint16_t len); +extern int32_t pstm_read_asn(psPool_t *pool, const unsigned char **pp, uint16_t len, + pstm_int *a); +extern int32_t pstm_to_unsigned_bin(psPool_t *pool, const pstm_int *a, + unsigned char *b); +extern int32_t pstm_to_unsigned_bin_nr(psPool_t *pool, const pstm_int *a, + unsigned char *b); +#ifdef USE_ECC +extern int32_t pstm_read_radix(psPool_t *pool, pstm_int *a, + const char *buf, uint16_t len, uint8_t radix); +#endif + +extern int32_t pstm_cmp(const pstm_int *a, const pstm_int *b); +extern int32_t pstm_cmp_mag(const pstm_int *a, const pstm_int *b); +extern int32_t pstm_cmp_d(const pstm_int *a, pstm_digit b); + +extern void pstm_rshd(pstm_int *a, uint16_t b); +extern int32_t pstm_lshd(pstm_int *a, uint16_t b); + +extern int32_t pstm_add(const pstm_int *a, const pstm_int *b, pstm_int *c); +extern int32_t pstm_add_d(psPool_t *pool, const pstm_int *a, pstm_digit b, pstm_int *c); + +extern int32_t s_pstm_sub(const pstm_int *a, const pstm_int *b, pstm_int *c); +extern int32_t pstm_sub(const pstm_int *a, const pstm_int *b, pstm_int *c); +extern int32_t pstm_sub_d(psPool_t *pool, const pstm_int *a, pstm_digit b, pstm_int *c); + +extern int32_t pstm_div(psPool_t *pool, const pstm_int *a, const pstm_int *b, + pstm_int *c, pstm_int *d); +extern int32_t pstm_div_2d(psPool_t *pool, const pstm_int *a, int16_t b, + pstm_int *c, pstm_int *d); +extern int32_t pstm_div_2(const pstm_int *a, pstm_int *b); + +extern int32_t pstm_mod(psPool_t *pool, const pstm_int *a, const pstm_int *b, + pstm_int *c); +extern int32_t pstm_invmod(psPool_t *pool, const pstm_int *a, const pstm_int *b, + pstm_int *c); + +extern int32_t pstm_mul_2(const pstm_int *a, pstm_int *b); +extern int32_t pstm_mulmod(psPool_t *pool, const pstm_int *a, const pstm_int *b, + const pstm_int *c, pstm_int *d); +extern int32_t pstm_mul_comba(psPool_t *pool, const pstm_int *A, const pstm_int *B, + pstm_int *C, pstm_digit *paD, uint16_t paDlen); +extern int32_t pstm_mul_d(const pstm_int *a, const pstm_digit b, pstm_int *c); + +extern int32_t pstm_sqr_comba(psPool_t *pool, const pstm_int *A, pstm_int *B, + pstm_digit *paD, uint16_t paDlen); + +extern int32_t pstm_exptmod(psPool_t *pool, const pstm_int *G, const pstm_int *X, + const pstm_int *P, pstm_int *Y); +extern int32_t pstm_2expt(pstm_int *a, int16_t b); + +extern int32_t pstm_montgomery_setup(const pstm_int *a, pstm_digit *rho); +extern int32_t pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, const pstm_int *m, + pstm_digit mp, pstm_digit *paD, uint16_t paDlen); +extern int32_t pstm_montgomery_calc_normalization(pstm_int *a, const pstm_int *b); + + +#endif /* USE_MATRIX_RSA || USE_CL_RSA || USE_MATRIX_ECC || USE_MATRIX_DH \ + || USE_CL_DH || USE_QUICK_ASSIST_RSA || USE_QUICK_ASSIST_ECC */ +#endif /* _h_PSTMATH */ + diff --git a/crypto/math/pstm_montgomery_reduce.c b/crypto/math/pstm_montgomery_reduce.c new file mode 100644 index 0000000..0fd1466 --- /dev/null +++ b/crypto/math/pstm_montgomery_reduce.c @@ -0,0 +1,426 @@ +/** + * @file pstm_montgomery_reduce.c + * @version $Format:%h%d$ + * + * Multiprecision Montgomery Reduction. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#if defined(USE_MATRIX_RSA) || defined(USE_MATRIX_ECC) || defined(USE_MATRIX_DH) + +/******************************************************************************/ + +#if defined(PSTM_X86) +/* x86-32 optimized for 32 bit platforms. For 64 bit mode use X86_64 instead */ +#if !defined(__GNUC__) || !defined(__i386__) || !defined(PSTM_32BIT) +#error "PSTM_X86 option requires GCC and 32 bit mode x86 processor" +#endif +//#pragma message ("Using 32 bit x86 Assembly Optimizations") + +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ + mu = c[x] * mp + +#define INNERMUL \ +asm( \ + "movl %5,%%eax \n\t" \ + "mull %4 \n\t" \ + "addl %1,%%eax \n\t" \ + "adcl $0,%%edx \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl $0,%%edx \n\t" \ + "movl %%edx,%1 \n\t" \ +:"=g"(_c[LO]), "=r"(cy) \ +:"0"(_c[LO]), "1"(cy), "g"(mu), "g"(*tmpm++) \ +: "%eax", "%edx", "%cc") + +#define PROPCARRY \ +asm( \ + "addl %1,%0 \n\t" \ + "setb %%al \n\t" \ + "movzbl %%al,%1 \n\t" \ +:"=g"(_c[LO]), "=r"(cy) \ +:"0"(_c[LO]), "1"(cy) \ +: "%eax", "%cc") + +/******************************************************************************/ +#elif defined(PSTM_X86_64) +/* x86-64 optimized */ +#if !defined(__GNUC__) || !defined(__x86_64__) || !defined(PSTM_64BIT) +#error "PSTM_X86_64 option requires PSTM_64BIT, GCC and 64 bit mode x86 processor" +#endif +//#pragma message ("Using 64 bit x86_64 Assembly Optimizations") + +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ +mu = c[x] * mp + +#define INNERMUL \ +asm( \ + "movq %5,%%rax \n\t" \ + "mulq %4 \n\t" \ + "addq %1,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rdx,%1 \n\t" \ + :"=g"(_c[LO]), "=r"(cy) \ + :"0"(_c[LO]), "1"(cy), "r"(mu), "r"(*tmpm++) \ + : "%rax", "%rdx", "cc") + +#define INNERMUL8 \ +asm( \ + "movq 0(%5),%%rax \n\t" \ + "movq 0(%2),%%r10 \n\t" \ + "movq 0x8(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x8(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "movq 0x10(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x10(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x8(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "movq 0x18(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x18(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x10(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "movq 0x20(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x20(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x18(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "movq 0x28(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x28(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x20(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "movq 0x30(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x30(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x28(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "movq 0x38(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x38(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x30(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x38(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + :"=r"(_c), "=r"(cy) \ + : "0"(_c), "1"(cy), "g"(mu), "r"(tmpm)\ + : "%rax", "%rdx", "%r10", "%r11", "cc") + +#define PROPCARRY \ +asm( \ + "addq %1,%0 \n\t" \ + "setb %%al \n\t" \ + "movzbq %%al,%1 \n\t" \ + :"=g"(_c[LO]), "=r"(cy) \ + :"0"(_c[LO]), "1"(cy) \ + : "%rax", "cc") + +/******************************************************************************/ +#elif defined(PSTM_ARM) + +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ +mu = c[x] * mp + +#ifdef __thumb2__ +//#pragma message ("Using 32 bit ARM Thumb2 Assembly Optimizations") +#define INNERMUL \ +asm( \ + " LDR r0,%1 \n\t" \ + " ADDS r0,r0,%0 \n\t" \ + " ITE CS \n\t" \ + " MOVCS %0,#1 \n\t" \ + " MOVCC %0,#0 \n\t" \ + " UMLAL r0,%0,%3,%4 \n\t" \ + " STR r0,%1 \n\t" \ + :"=r"(cy),"=m"(_c[0])\ + :"0"(cy),"r"(mu),"r"(*tmpm++),"m"(_c[0])\ + :"r0","%cc"); +#define PROPCARRY \ +asm( \ + " LDR r0,%1 \n\t" \ + " ADDS r0,r0,%0 \n\t" \ + " STR r0,%1 \n\t" \ + " ITE CS \n\t" \ + " MOVCS %0,#1 \n\t" \ + " MOVCC %0,#0 \n\t" \ + :"=r"(cy),"=m"(_c[0])\ + :"0"(cy),"m"(_c[0])\ + :"r0","%cc"); +#else /* Non-Thumb2 code */ +//#pragma message ("Using 32 bit ARM Assembly Optimizations") +#define INNERMUL \ +asm( \ + " LDR r0,%1 \n\t" \ + " ADDS r0,r0,%0 \n\t" \ + " MOVCS %0,#1 \n\t" \ + " MOVCC %0,#0 \n\t" \ + " UMLAL r0,%0,%3,%4 \n\t" \ + " STR r0,%1 \n\t" \ + :"=r"(cy),"=m"(_c[0])\ + :"0"(cy),"r"(mu),"r"(*tmpm++),"m"(_c[0])\ + :"r0","%cc"); +#define PROPCARRY \ +asm( \ + " LDR r0,%1 \n\t" \ + " ADDS r0,r0,%0 \n\t" \ + " STR r0,%1 \n\t" \ + " MOVCS %0,#1 \n\t" \ + " MOVCC %0,#0 \n\t" \ + :"=r"(cy),"=m"(_c[0])\ + :"0"(cy),"m"(_c[0])\ + :"r0","%cc"); +#endif /* __thumb2__ */ + + +/******************************************************************************/ +#elif defined(PSTM_MIPS) +/* MIPS32 */ +//#pragma message ("Using 32 bit MIPS Assembly Optimizations") +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ +mu = c[x] * mp + +#define INNERMUL \ +asm( \ + " multu %3,%4 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + " addu $12,$12,%0 \n\t" \ + " sltu $10,$12,%0 \n\t" \ + " addu $13,$13,$10 \n\t" \ + " lw $10,%1 \n\t" \ + " addu $12,$12,$10 \n\t" \ + " sltu $10,$12,$10 \n\t" \ + " addu %0,$13,$10 \n\t" \ + " sw $12,%1 \n\t" \ + :"=r"(cy),"=m"(_c[0])\ + :"r"(cy),"r"(mu),"r"(tmpm[0]),"r"(_c[0])\ + :"$10","$12","$13")\ +; ++tmpm; + +#define PROPCARRY \ +asm( \ + " lw $10,%1 \n\t" \ + " addu $10,$10,%0 \n\t" \ + " sw $10,%1 \n\t" \ + " sltu %0,$10,%0 \n\t" \ + :"=r"(cy),"=m"(_c[0])\ + :"r"(cy),"r"(_c[0])\ + :"$10"); + + +/******************************************************************************/ +#else + +/* ISO C code */ +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ + mu = c[x] * mp + +#define INNERMUL \ + do { pstm_word t; \ + t = ((pstm_word)_c[0] + (pstm_word)cy) + \ + (((pstm_word)mu) * ((pstm_word)*tmpm++)); \ + _c[0] = (pstm_digit)t; \ + cy = (pstm_digit)(t >> DIGIT_BIT); \ + } while (0) + +#define PROPCARRY \ + do { pstm_digit t = _c[0] += cy; cy = (t < cy); } while (0) + +#endif + +/******************************************************************************/ + +#define LO 0 + +/** + computes x/R == x (mod N) via Montgomery Reduction. +*/ +int32_t pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, const pstm_int *m, + pstm_digit mp, pstm_digit *paD, uint16_t paDlen) +{ + pstm_digit *c, *_c, *tmpm, mu; + int32 oldused, x, y; + int16 pa; + uint32 cSize; + + pa = m->used; + if (pa > a->alloc) { + /* Sanity test for bad numbers. This will confirm no buffer overruns */ + return PS_LIMIT_FAIL; + } + + cSize = (2 * pa + 1) * sizeof(pstm_digit); + if (paD && paDlen >= cSize) { + c = paD; + memset(c, 0x0, paDlen); + } else { + c = psMalloc(pool, cSize); + if (c == NULL) { + return PS_MEM_FAIL; + } else { + memset(c, 0x0, cSize); + } + } + /* copy the input */ + oldused = a->used; + for (x = 0; x < oldused; x++) { + c[x] = a->dp[x]; + } + + MONT_START; + + for (x = 0; x < pa; x++) { + pstm_digit cy = 0; + /* get Mu for this round */ + LOOP_START; + _c = c + x; + tmpm = m->dp; + y = 0; +#ifdef PSTM_X86_64 + for (; y < (pa & ~7); y += 8) { + INNERMUL8; + _c += 8; + tmpm += 8; + } +#endif /* PSTM_X86_64 */ + for (; y < pa; y++) { + INNERMUL; + ++_c; + } + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + } + /* now copy out */ + _c = c + pa; + tmpm = a->dp; + for (x = 0; x < pa+1; x++) { + *tmpm++ = *_c++; + } + + for (; x < oldused; x++) { + *tmpm++ = 0; + } + + MONT_FINI; + + a->used = pa+1; + pstm_clamp(a); + + /* reuse x as return code */ + x = PSTM_OKAY; + + /* if A >= m then A = A - m */ + if (pstm_cmp_mag (a, m) != PSTM_LT) { + if (s_pstm_sub (a, m, a) != PSTM_OKAY) { + x = PS_MEM_FAIL; + } + } + if (paDlen < cSize) { + psFree(c, pool); + } + return x; +} + +#endif /* defined(USE_MATRIX_RSA) || defined(USE_MATRIX_ECC) */ + +/******************************************************************************/ + diff --git a/crypto/math/pstm_mul_comba.c b/crypto/math/pstm_mul_comba.c new file mode 100644 index 0000000..e7058ad --- /dev/null +++ b/crypto/math/pstm_mul_comba.c @@ -0,0 +1,776 @@ +/** + * @file pstm_mul_comba.c + * @version $Format:%h%d$ + * + * Multiprecision multiplication with Comba technique. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#if defined(USE_MATRIX_RSA) || defined(USE_MATRIX_ECC) || defined(USE_MATRIX_DH) + +/******************************************************************************/ +#if defined(PSTM_X86) +/* x86-32 optimized for 32 bit platforms. For 64 bit mode use X86_64 instead */ +#if !defined(__GNUC__) || !defined(__i386__) || !defined(PSTM_32BIT) +#error "PSTM_X86 option requires GCC and 32 bit mode x86 processor" +#endif +//#pragma message ("Using 32 bit x86 Assembly Optimizations") + +/* anything you need at the start */ +#define COMBA_START + +/* clear the chaining variables */ +#define COMBA_CLEAR \ + c0 = c1 = c2 = 0; + +/* forward the carry to the next digit */ +#define COMBA_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +/* store the first sum */ +#define COMBA_STORE(x) \ + x = c0; + +/* store the second sum [carry] */ +#define COMBA_STORE2(x) \ + x = c1; + +/* anything you need at the end */ +#define COMBA_FINI + +/* this should multiply i and j */ +#define MULADD(i, j) \ +asm( \ + "movl %6,%%eax \n\t" \ + "mull %7 \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl %%edx,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","%cc"); + +/******************************************************************************/ +#elif defined(PSTM_X86_64) +/* x86-64 optimized */ +#if !defined(__GNUC__) || !defined(__x86_64__) || !defined(PSTM_64BIT) +#error "PSTM_X86_64 option requires PSTM_64BIT, GCC and 64 bit mode x86 processor" +#endif +//#pragma message ("Using 64 bit x86_64 Assembly Optimizations") + +/* anything you need at the start */ +#define COMBA_START + +/* clear the chaining variables */ +#define COMBA_CLEAR \ +c0 = c1 = c2 = 0; + +/* forward the carry to the next digit */ +#define COMBA_FORWARD \ +do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +/* store the first sum */ +#define COMBA_STORE(x) \ +x = c0; + +/* store the second sum [carry] */ +#define COMBA_STORE2(x) \ +x = c1; + +/* anything you need at the end */ +#define COMBA_FINI + +/* this should multiply i and j */ +#define MULADD(i, j) \ +asm ( \ + "movq %6,%%rax \n\t" \ + "mulq %7 \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j) :"%rax","%rdx","cc"); + +/******************************************************************************/ +#elif defined(PSTM_ARM) +/* ARM code */ +//#pragma message ("Using 32 bit ARM Assembly Optimizations") + +#define COMBA_START + +#define COMBA_CLEAR \ +c0 = c1 = c2 = 0; + +#define COMBA_FORWARD \ +do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_STORE(x) \ +x = c0; + +#define COMBA_STORE2(x) \ +x = c1; + +#define COMBA_FINI + +#define MULADD(i, j) \ +asm( \ + " UMULL r0,r1,%6,%7 \n\t" \ + " ADDS %0,%0,r0 \n\t" \ + " ADCS %1,%1,r1 \n\t" \ + " ADC %2,%2,#0 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "%cc"); + +/******************************************************************************/ +#elif defined(PSTM_MIPS) +/* MIPS32 code */ +//#pragma message ("Using 32 bit MIPS Assembly Optimizations") + +#define COMBA_START + +#define COMBA_CLEAR \ +c0 = c1 = c2 = 0; + +#define COMBA_FORWARD \ +do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_STORE(x) \ +x = c0; + +#define COMBA_STORE2(x) \ +x = c1; + +#define COMBA_FINI + +#define MULADD(i, j) \ +asm( \ + " multu %6,%7 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + " addu %0,%0,$12 \n\t" \ + " sltu $12,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $13,%1,$13 \n\t" \ + " addu %1,%1,$12 \n\t" \ + " sltu $12,%1,$12 \n\t" \ + " addu %2,%2,$13 \n\t" \ + " addu %2,%2,$12 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12","$13"); + +/******************************************************************************/ +#else + +#define COMBA_START + +#define COMBA_CLEAR \ + c0 = c1 = c2 = 0; + +#define COMBA_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define COMBA_FINI + +#define MULADD(i, j) \ + do { pstm_word t; \ + t = (pstm_word)c0 + ((pstm_word)i) * ((pstm_word)j); c0 = (pstm_digit)t; \ + t = (pstm_word)c1 + (t >> DIGIT_BIT); \ + c1 = (pstm_digit)t; c2 += (pstm_digit)(t >> DIGIT_BIT); \ + } while (0); + +#endif + +/******************************************************************************/ +/* generic PxQ multiplier */ +static int32_t pstm_mul_comba_gen(psPool_t *pool, const pstm_int *A, + const pstm_int *B, pstm_int *C, + pstm_digit *paD, uint16_t paDlen) +{ + int16 paDfail, pa; + int32 ix, iy, iz, tx, ty; + pstm_digit c0, c1, c2, *tmpx, *tmpy, *dst; + + COMBA_START; + COMBA_CLEAR; + + paDfail = 0; + /* get size of output and trim */ + pa = A->used + B->used; + +/* + If c is not large enough grow it and continue +*/ + if (C->alloc < pa) { + if (pstm_grow(C, pa) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + if (paD != NULL) { + if (paDlen < (sizeof(pstm_digit) * pa)) { + paDfail = 1; /* have a paD but it's not large enough */ + if ((dst = psMalloc(pool, sizeof(pstm_digit) * pa)) == NULL) { + return PS_MEM_FAIL; + } + memset(dst, 0x0, sizeof(pstm_digit) * pa); + } else { + dst = paD; + memset(dst, 0x0, paDlen); + } + } else { + if ((dst = psMalloc(pool, sizeof(pstm_digit) * pa)) == NULL) { + return PS_MEM_FAIL; + } + memset(dst, 0x0, sizeof(pstm_digit) * pa); + } + + for (ix = 0; ix < pa; ix++) { + /* get offsets into the two bignums */ + ty = min(ix, B->used-1); + tx = ix - ty; + + /* setup temp aliases */ + tmpx = A->dp + tx; + tmpy = B->dp + ty; +/* + This is the number of times the loop will iterate, essentially it's + while (tx++ < a->used && ty-- >= 0) { ... } +*/ + iy = min(A->used-tx, ty+1); + + /* execute loop */ + COMBA_FORWARD; + for (iz = 0; iz < iy; ++iz) { + MULADD(*tmpx++, *tmpy--); + } + + /* store term */ + COMBA_STORE(dst[ix]); + } + COMBA_FINI; +/* + setup dest + */ + iy = C->used; + C->used = pa; + C->sign = A->sign ^ B->sign; + { + pstm_digit *tmpc; + tmpc = C->dp; + for (ix = 0; ix < pa; ix++) { + *tmpc++ = dst[ix]; + } +/* + clear unused digits [that existed in the old copy of c] + */ + for (; ix < iy; ix++) { + *tmpc++ = 0; + } + } + pstm_clamp(C); + + if ((paD == NULL) || (paDfail == 1)) { + psFree(dst, pool); + } + + return PS_SUCCESS; +} + +/******************************************************************************/ +#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS +static int32_t pstm_mul_comba16(const pstm_int *A, const pstm_int *B, pstm_int *C) +{ + pstm_digit c0, c1, c2, at[32]; + + if (C->alloc < 32) { + if (pstm_grow(C, 32) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + memcpy(at, A->dp, 16 * sizeof(pstm_digit)); + memcpy(at+16, B->dp, 16 * sizeof(pstm_digit)); + + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[16]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[17]); MULADD(at[1], at[16]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[18]); MULADD(at[1], at[17]); MULADD(at[2], at[16]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[19]); MULADD(at[1], at[18]); MULADD(at[2], at[17]); MULADD(at[3], at[16]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[20]); MULADD(at[1], at[19]); MULADD(at[2], at[18]); MULADD(at[3], at[17]); MULADD(at[4], at[16]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[21]); MULADD(at[1], at[20]); MULADD(at[2], at[19]); MULADD(at[3], at[18]); MULADD(at[4], at[17]); MULADD(at[5], at[16]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[22]); MULADD(at[1], at[21]); MULADD(at[2], at[20]); MULADD(at[3], at[19]); MULADD(at[4], at[18]); MULADD(at[5], at[17]); MULADD(at[6], at[16]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[23]); MULADD(at[1], at[22]); MULADD(at[2], at[21]); MULADD(at[3], at[20]); MULADD(at[4], at[19]); MULADD(at[5], at[18]); MULADD(at[6], at[17]); MULADD(at[7], at[16]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[24]); MULADD(at[1], at[23]); MULADD(at[2], at[22]); MULADD(at[3], at[21]); MULADD(at[4], at[20]); MULADD(at[5], at[19]); MULADD(at[6], at[18]); MULADD(at[7], at[17]); MULADD(at[8], at[16]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[25]); MULADD(at[1], at[24]); MULADD(at[2], at[23]); MULADD(at[3], at[22]); MULADD(at[4], at[21]); MULADD(at[5], at[20]); MULADD(at[6], at[19]); MULADD(at[7], at[18]); MULADD(at[8], at[17]); MULADD(at[9], at[16]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[26]); MULADD(at[1], at[25]); MULADD(at[2], at[24]); MULADD(at[3], at[23]); MULADD(at[4], at[22]); MULADD(at[5], at[21]); MULADD(at[6], at[20]); MULADD(at[7], at[19]); MULADD(at[8], at[18]); MULADD(at[9], at[17]); MULADD(at[10], at[16]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[27]); MULADD(at[1], at[26]); MULADD(at[2], at[25]); MULADD(at[3], at[24]); MULADD(at[4], at[23]); MULADD(at[5], at[22]); MULADD(at[6], at[21]); MULADD(at[7], at[20]); MULADD(at[8], at[19]); MULADD(at[9], at[18]); MULADD(at[10], at[17]); MULADD(at[11], at[16]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[0], at[28]); MULADD(at[1], at[27]); MULADD(at[2], at[26]); MULADD(at[3], at[25]); MULADD(at[4], at[24]); MULADD(at[5], at[23]); MULADD(at[6], at[22]); MULADD(at[7], at[21]); MULADD(at[8], at[20]); MULADD(at[9], at[19]); MULADD(at[10], at[18]); MULADD(at[11], at[17]); MULADD(at[12], at[16]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[0], at[29]); MULADD(at[1], at[28]); MULADD(at[2], at[27]); MULADD(at[3], at[26]); MULADD(at[4], at[25]); MULADD(at[5], at[24]); MULADD(at[6], at[23]); MULADD(at[7], at[22]); MULADD(at[8], at[21]); MULADD(at[9], at[20]); MULADD(at[10], at[19]); MULADD(at[11], at[18]); MULADD(at[12], at[17]); MULADD(at[13], at[16]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[0], at[30]); MULADD(at[1], at[29]); MULADD(at[2], at[28]); MULADD(at[3], at[27]); MULADD(at[4], at[26]); MULADD(at[5], at[25]); MULADD(at[6], at[24]); MULADD(at[7], at[23]); MULADD(at[8], at[22]); MULADD(at[9], at[21]); MULADD(at[10], at[20]); MULADD(at[11], at[19]); MULADD(at[12], at[18]); MULADD(at[13], at[17]); MULADD(at[14], at[16]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[0], at[31]); MULADD(at[1], at[30]); MULADD(at[2], at[29]); MULADD(at[3], at[28]); MULADD(at[4], at[27]); MULADD(at[5], at[26]); MULADD(at[6], at[25]); MULADD(at[7], at[24]); MULADD(at[8], at[23]); MULADD(at[9], at[22]); MULADD(at[10], at[21]); MULADD(at[11], at[20]); MULADD(at[12], at[19]); MULADD(at[13], at[18]); MULADD(at[14], at[17]); MULADD(at[15], at[16]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[1], at[31]); MULADD(at[2], at[30]); MULADD(at[3], at[29]); MULADD(at[4], at[28]); MULADD(at[5], at[27]); MULADD(at[6], at[26]); MULADD(at[7], at[25]); MULADD(at[8], at[24]); MULADD(at[9], at[23]); MULADD(at[10], at[22]); MULADD(at[11], at[21]); MULADD(at[12], at[20]); MULADD(at[13], at[19]); MULADD(at[14], at[18]); MULADD(at[15], at[17]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[2], at[31]); MULADD(at[3], at[30]); MULADD(at[4], at[29]); MULADD(at[5], at[28]); MULADD(at[6], at[27]); MULADD(at[7], at[26]); MULADD(at[8], at[25]); MULADD(at[9], at[24]); MULADD(at[10], at[23]); MULADD(at[11], at[22]); MULADD(at[12], at[21]); MULADD(at[13], at[20]); MULADD(at[14], at[19]); MULADD(at[15], at[18]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[3], at[31]); MULADD(at[4], at[30]); MULADD(at[5], at[29]); MULADD(at[6], at[28]); MULADD(at[7], at[27]); MULADD(at[8], at[26]); MULADD(at[9], at[25]); MULADD(at[10], at[24]); MULADD(at[11], at[23]); MULADD(at[12], at[22]); MULADD(at[13], at[21]); MULADD(at[14], at[20]); MULADD(at[15], at[19]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[4], at[31]); MULADD(at[5], at[30]); MULADD(at[6], at[29]); MULADD(at[7], at[28]); MULADD(at[8], at[27]); MULADD(at[9], at[26]); MULADD(at[10], at[25]); MULADD(at[11], at[24]); MULADD(at[12], at[23]); MULADD(at[13], at[22]); MULADD(at[14], at[21]); MULADD(at[15], at[20]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[5], at[31]); MULADD(at[6], at[30]); MULADD(at[7], at[29]); MULADD(at[8], at[28]); MULADD(at[9], at[27]); MULADD(at[10], at[26]); MULADD(at[11], at[25]); MULADD(at[12], at[24]); MULADD(at[13], at[23]); MULADD(at[14], at[22]); MULADD(at[15], at[21]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[6], at[31]); MULADD(at[7], at[30]); MULADD(at[8], at[29]); MULADD(at[9], at[28]); MULADD(at[10], at[27]); MULADD(at[11], at[26]); MULADD(at[12], at[25]); MULADD(at[13], at[24]); MULADD(at[14], at[23]); MULADD(at[15], at[22]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[7], at[31]); MULADD(at[8], at[30]); MULADD(at[9], at[29]); MULADD(at[10], at[28]); MULADD(at[11], at[27]); MULADD(at[12], at[26]); MULADD(at[13], at[25]); MULADD(at[14], at[24]); MULADD(at[15], at[23]); + COMBA_STORE(C->dp[22]); + /* 23 */ + COMBA_FORWARD; + MULADD(at[8], at[31]); MULADD(at[9], at[30]); MULADD(at[10], at[29]); MULADD(at[11], at[28]); MULADD(at[12], at[27]); MULADD(at[13], at[26]); MULADD(at[14], at[25]); MULADD(at[15], at[24]); + COMBA_STORE(C->dp[23]); + /* 24 */ + COMBA_FORWARD; + MULADD(at[9], at[31]); MULADD(at[10], at[30]); MULADD(at[11], at[29]); MULADD(at[12], at[28]); MULADD(at[13], at[27]); MULADD(at[14], at[26]); MULADD(at[15], at[25]); + COMBA_STORE(C->dp[24]); + /* 25 */ + COMBA_FORWARD; + MULADD(at[10], at[31]); MULADD(at[11], at[30]); MULADD(at[12], at[29]); MULADD(at[13], at[28]); MULADD(at[14], at[27]); MULADD(at[15], at[26]); + COMBA_STORE(C->dp[25]); + /* 26 */ + COMBA_FORWARD; + MULADD(at[11], at[31]); MULADD(at[12], at[30]); MULADD(at[13], at[29]); MULADD(at[14], at[28]); MULADD(at[15], at[27]); + COMBA_STORE(C->dp[26]); + /* 27 */ + COMBA_FORWARD; + MULADD(at[12], at[31]); MULADD(at[13], at[30]); MULADD(at[14], at[29]); MULADD(at[15], at[28]); + COMBA_STORE(C->dp[27]); + /* 28 */ + COMBA_FORWARD; + MULADD(at[13], at[31]); MULADD(at[14], at[30]); MULADD(at[15], at[29]); + COMBA_STORE(C->dp[28]); + /* 29 */ + COMBA_FORWARD; + MULADD(at[14], at[31]); MULADD(at[15], at[30]); + COMBA_STORE(C->dp[29]); + /* 30 */ + COMBA_FORWARD; + MULADD(at[15], at[31]); + COMBA_STORE(C->dp[30]); + COMBA_STORE2(C->dp[31]); + C->used = 32; + C->sign = A->sign ^ B->sign; + pstm_clamp(C); + COMBA_FINI; + return PSTM_OKAY; +} +#endif /* USE_1024_KEY_SPEED_OPTIMIZATIONS */ + + +#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS +static int32_t pstm_mul_comba32(const pstm_int *A, const pstm_int *B, pstm_int *C) +{ + pstm_digit c0, c1, c2, at[64]; + int32 out_size; + + if (C->alloc < 64) { + if (pstm_grow(C, 64) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + + out_size = A->used + B->used; + memcpy(at, A->dp, 32 * sizeof(pstm_digit)); + memcpy(at+32, B->dp, 32 * sizeof(pstm_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[32]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[33]); MULADD(at[1], at[32]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[34]); MULADD(at[1], at[33]); MULADD(at[2], at[32]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[35]); MULADD(at[1], at[34]); MULADD(at[2], at[33]); MULADD(at[3], at[32]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[36]); MULADD(at[1], at[35]); MULADD(at[2], at[34]); MULADD(at[3], at[33]); MULADD(at[4], at[32]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[37]); MULADD(at[1], at[36]); MULADD(at[2], at[35]); MULADD(at[3], at[34]); MULADD(at[4], at[33]); MULADD(at[5], at[32]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[38]); MULADD(at[1], at[37]); MULADD(at[2], at[36]); MULADD(at[3], at[35]); MULADD(at[4], at[34]); MULADD(at[5], at[33]); MULADD(at[6], at[32]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[39]); MULADD(at[1], at[38]); MULADD(at[2], at[37]); MULADD(at[3], at[36]); MULADD(at[4], at[35]); MULADD(at[5], at[34]); MULADD(at[6], at[33]); MULADD(at[7], at[32]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[40]); MULADD(at[1], at[39]); MULADD(at[2], at[38]); MULADD(at[3], at[37]); MULADD(at[4], at[36]); MULADD(at[5], at[35]); MULADD(at[6], at[34]); MULADD(at[7], at[33]); MULADD(at[8], at[32]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[41]); MULADD(at[1], at[40]); MULADD(at[2], at[39]); MULADD(at[3], at[38]); MULADD(at[4], at[37]); MULADD(at[5], at[36]); MULADD(at[6], at[35]); MULADD(at[7], at[34]); MULADD(at[8], at[33]); MULADD(at[9], at[32]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[42]); MULADD(at[1], at[41]); MULADD(at[2], at[40]); MULADD(at[3], at[39]); MULADD(at[4], at[38]); MULADD(at[5], at[37]); MULADD(at[6], at[36]); MULADD(at[7], at[35]); MULADD(at[8], at[34]); MULADD(at[9], at[33]); MULADD(at[10], at[32]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[43]); MULADD(at[1], at[42]); MULADD(at[2], at[41]); MULADD(at[3], at[40]); MULADD(at[4], at[39]); MULADD(at[5], at[38]); MULADD(at[6], at[37]); MULADD(at[7], at[36]); MULADD(at[8], at[35]); MULADD(at[9], at[34]); MULADD(at[10], at[33]); MULADD(at[11], at[32]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[0], at[44]); MULADD(at[1], at[43]); MULADD(at[2], at[42]); MULADD(at[3], at[41]); MULADD(at[4], at[40]); MULADD(at[5], at[39]); MULADD(at[6], at[38]); MULADD(at[7], at[37]); MULADD(at[8], at[36]); MULADD(at[9], at[35]); MULADD(at[10], at[34]); MULADD(at[11], at[33]); MULADD(at[12], at[32]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[0], at[45]); MULADD(at[1], at[44]); MULADD(at[2], at[43]); MULADD(at[3], at[42]); MULADD(at[4], at[41]); MULADD(at[5], at[40]); MULADD(at[6], at[39]); MULADD(at[7], at[38]); MULADD(at[8], at[37]); MULADD(at[9], at[36]); MULADD(at[10], at[35]); MULADD(at[11], at[34]); MULADD(at[12], at[33]); MULADD(at[13], at[32]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[0], at[46]); MULADD(at[1], at[45]); MULADD(at[2], at[44]); MULADD(at[3], at[43]); MULADD(at[4], at[42]); MULADD(at[5], at[41]); MULADD(at[6], at[40]); MULADD(at[7], at[39]); MULADD(at[8], at[38]); MULADD(at[9], at[37]); MULADD(at[10], at[36]); MULADD(at[11], at[35]); MULADD(at[12], at[34]); MULADD(at[13], at[33]); MULADD(at[14], at[32]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[0], at[47]); MULADD(at[1], at[46]); MULADD(at[2], at[45]); MULADD(at[3], at[44]); MULADD(at[4], at[43]); MULADD(at[5], at[42]); MULADD(at[6], at[41]); MULADD(at[7], at[40]); MULADD(at[8], at[39]); MULADD(at[9], at[38]); MULADD(at[10], at[37]); MULADD(at[11], at[36]); MULADD(at[12], at[35]); MULADD(at[13], at[34]); MULADD(at[14], at[33]); MULADD(at[15], at[32]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[0], at[48]); MULADD(at[1], at[47]); MULADD(at[2], at[46]); MULADD(at[3], at[45]); MULADD(at[4], at[44]); MULADD(at[5], at[43]); MULADD(at[6], at[42]); MULADD(at[7], at[41]); MULADD(at[8], at[40]); MULADD(at[9], at[39]); MULADD(at[10], at[38]); MULADD(at[11], at[37]); MULADD(at[12], at[36]); MULADD(at[13], at[35]); MULADD(at[14], at[34]); MULADD(at[15], at[33]); MULADD(at[16], at[32]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[0], at[49]); MULADD(at[1], at[48]); MULADD(at[2], at[47]); MULADD(at[3], at[46]); MULADD(at[4], at[45]); MULADD(at[5], at[44]); MULADD(at[6], at[43]); MULADD(at[7], at[42]); MULADD(at[8], at[41]); MULADD(at[9], at[40]); MULADD(at[10], at[39]); MULADD(at[11], at[38]); MULADD(at[12], at[37]); MULADD(at[13], at[36]); MULADD(at[14], at[35]); MULADD(at[15], at[34]); MULADD(at[16], at[33]); MULADD(at[17], at[32]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[0], at[50]); MULADD(at[1], at[49]); MULADD(at[2], at[48]); MULADD(at[3], at[47]); MULADD(at[4], at[46]); MULADD(at[5], at[45]); MULADD(at[6], at[44]); MULADD(at[7], at[43]); MULADD(at[8], at[42]); MULADD(at[9], at[41]); MULADD(at[10], at[40]); MULADD(at[11], at[39]); MULADD(at[12], at[38]); MULADD(at[13], at[37]); MULADD(at[14], at[36]); MULADD(at[15], at[35]); MULADD(at[16], at[34]); MULADD(at[17], at[33]); MULADD(at[18], at[32]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[0], at[51]); MULADD(at[1], at[50]); MULADD(at[2], at[49]); MULADD(at[3], at[48]); MULADD(at[4], at[47]); MULADD(at[5], at[46]); MULADD(at[6], at[45]); MULADD(at[7], at[44]); MULADD(at[8], at[43]); MULADD(at[9], at[42]); MULADD(at[10], at[41]); MULADD(at[11], at[40]); MULADD(at[12], at[39]); MULADD(at[13], at[38]); MULADD(at[14], at[37]); MULADD(at[15], at[36]); MULADD(at[16], at[35]); MULADD(at[17], at[34]); MULADD(at[18], at[33]); MULADD(at[19], at[32]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[0], at[52]); MULADD(at[1], at[51]); MULADD(at[2], at[50]); MULADD(at[3], at[49]); MULADD(at[4], at[48]); MULADD(at[5], at[47]); MULADD(at[6], at[46]); MULADD(at[7], at[45]); MULADD(at[8], at[44]); MULADD(at[9], at[43]); MULADD(at[10], at[42]); MULADD(at[11], at[41]); MULADD(at[12], at[40]); MULADD(at[13], at[39]); MULADD(at[14], at[38]); MULADD(at[15], at[37]); MULADD(at[16], at[36]); MULADD(at[17], at[35]); MULADD(at[18], at[34]); MULADD(at[19], at[33]); MULADD(at[20], at[32]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[0], at[53]); MULADD(at[1], at[52]); MULADD(at[2], at[51]); MULADD(at[3], at[50]); MULADD(at[4], at[49]); MULADD(at[5], at[48]); MULADD(at[6], at[47]); MULADD(at[7], at[46]); MULADD(at[8], at[45]); MULADD(at[9], at[44]); MULADD(at[10], at[43]); MULADD(at[11], at[42]); MULADD(at[12], at[41]); MULADD(at[13], at[40]); MULADD(at[14], at[39]); MULADD(at[15], at[38]); MULADD(at[16], at[37]); MULADD(at[17], at[36]); MULADD(at[18], at[35]); MULADD(at[19], at[34]); MULADD(at[20], at[33]); MULADD(at[21], at[32]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[0], at[54]); MULADD(at[1], at[53]); MULADD(at[2], at[52]); MULADD(at[3], at[51]); MULADD(at[4], at[50]); MULADD(at[5], at[49]); MULADD(at[6], at[48]); MULADD(at[7], at[47]); MULADD(at[8], at[46]); MULADD(at[9], at[45]); MULADD(at[10], at[44]); MULADD(at[11], at[43]); MULADD(at[12], at[42]); MULADD(at[13], at[41]); MULADD(at[14], at[40]); MULADD(at[15], at[39]); MULADD(at[16], at[38]); MULADD(at[17], at[37]); MULADD(at[18], at[36]); MULADD(at[19], at[35]); MULADD(at[20], at[34]); MULADD(at[21], at[33]); MULADD(at[22], at[32]); + COMBA_STORE(C->dp[22]); + /* 23 */ + COMBA_FORWARD; + MULADD(at[0], at[55]); MULADD(at[1], at[54]); MULADD(at[2], at[53]); MULADD(at[3], at[52]); MULADD(at[4], at[51]); MULADD(at[5], at[50]); MULADD(at[6], at[49]); MULADD(at[7], at[48]); MULADD(at[8], at[47]); MULADD(at[9], at[46]); MULADD(at[10], at[45]); MULADD(at[11], at[44]); MULADD(at[12], at[43]); MULADD(at[13], at[42]); MULADD(at[14], at[41]); MULADD(at[15], at[40]); MULADD(at[16], at[39]); MULADD(at[17], at[38]); MULADD(at[18], at[37]); MULADD(at[19], at[36]); MULADD(at[20], at[35]); MULADD(at[21], at[34]); MULADD(at[22], at[33]); MULADD(at[23], at[32]); + COMBA_STORE(C->dp[23]); + /* 24 */ + COMBA_FORWARD; + MULADD(at[0], at[56]); MULADD(at[1], at[55]); MULADD(at[2], at[54]); MULADD(at[3], at[53]); MULADD(at[4], at[52]); MULADD(at[5], at[51]); MULADD(at[6], at[50]); MULADD(at[7], at[49]); MULADD(at[8], at[48]); MULADD(at[9], at[47]); MULADD(at[10], at[46]); MULADD(at[11], at[45]); MULADD(at[12], at[44]); MULADD(at[13], at[43]); MULADD(at[14], at[42]); MULADD(at[15], at[41]); MULADD(at[16], at[40]); MULADD(at[17], at[39]); MULADD(at[18], at[38]); MULADD(at[19], at[37]); MULADD(at[20], at[36]); MULADD(at[21], at[35]); MULADD(at[22], at[34]); MULADD(at[23], at[33]); MULADD(at[24], at[32]); + COMBA_STORE(C->dp[24]); + /* 25 */ + COMBA_FORWARD; + MULADD(at[0], at[57]); MULADD(at[1], at[56]); MULADD(at[2], at[55]); MULADD(at[3], at[54]); MULADD(at[4], at[53]); MULADD(at[5], at[52]); MULADD(at[6], at[51]); MULADD(at[7], at[50]); MULADD(at[8], at[49]); MULADD(at[9], at[48]); MULADD(at[10], at[47]); MULADD(at[11], at[46]); MULADD(at[12], at[45]); MULADD(at[13], at[44]); MULADD(at[14], at[43]); MULADD(at[15], at[42]); MULADD(at[16], at[41]); MULADD(at[17], at[40]); MULADD(at[18], at[39]); MULADD(at[19], at[38]); MULADD(at[20], at[37]); MULADD(at[21], at[36]); MULADD(at[22], at[35]); MULADD(at[23], at[34]); MULADD(at[24], at[33]); MULADD(at[25], at[32]); + COMBA_STORE(C->dp[25]); + /* 26 */ + COMBA_FORWARD; + MULADD(at[0], at[58]); MULADD(at[1], at[57]); MULADD(at[2], at[56]); MULADD(at[3], at[55]); MULADD(at[4], at[54]); MULADD(at[5], at[53]); MULADD(at[6], at[52]); MULADD(at[7], at[51]); MULADD(at[8], at[50]); MULADD(at[9], at[49]); MULADD(at[10], at[48]); MULADD(at[11], at[47]); MULADD(at[12], at[46]); MULADD(at[13], at[45]); MULADD(at[14], at[44]); MULADD(at[15], at[43]); MULADD(at[16], at[42]); MULADD(at[17], at[41]); MULADD(at[18], at[40]); MULADD(at[19], at[39]); MULADD(at[20], at[38]); MULADD(at[21], at[37]); MULADD(at[22], at[36]); MULADD(at[23], at[35]); MULADD(at[24], at[34]); MULADD(at[25], at[33]); MULADD(at[26], at[32]); + COMBA_STORE(C->dp[26]); + /* 27 */ + COMBA_FORWARD; + MULADD(at[0], at[59]); MULADD(at[1], at[58]); MULADD(at[2], at[57]); MULADD(at[3], at[56]); MULADD(at[4], at[55]); MULADD(at[5], at[54]); MULADD(at[6], at[53]); MULADD(at[7], at[52]); MULADD(at[8], at[51]); MULADD(at[9], at[50]); MULADD(at[10], at[49]); MULADD(at[11], at[48]); MULADD(at[12], at[47]); MULADD(at[13], at[46]); MULADD(at[14], at[45]); MULADD(at[15], at[44]); MULADD(at[16], at[43]); MULADD(at[17], at[42]); MULADD(at[18], at[41]); MULADD(at[19], at[40]); MULADD(at[20], at[39]); MULADD(at[21], at[38]); MULADD(at[22], at[37]); MULADD(at[23], at[36]); MULADD(at[24], at[35]); MULADD(at[25], at[34]); MULADD(at[26], at[33]); MULADD(at[27], at[32]); + COMBA_STORE(C->dp[27]); + /* 28 */ + COMBA_FORWARD; + MULADD(at[0], at[60]); MULADD(at[1], at[59]); MULADD(at[2], at[58]); MULADD(at[3], at[57]); MULADD(at[4], at[56]); MULADD(at[5], at[55]); MULADD(at[6], at[54]); MULADD(at[7], at[53]); MULADD(at[8], at[52]); MULADD(at[9], at[51]); MULADD(at[10], at[50]); MULADD(at[11], at[49]); MULADD(at[12], at[48]); MULADD(at[13], at[47]); MULADD(at[14], at[46]); MULADD(at[15], at[45]); MULADD(at[16], at[44]); MULADD(at[17], at[43]); MULADD(at[18], at[42]); MULADD(at[19], at[41]); MULADD(at[20], at[40]); MULADD(at[21], at[39]); MULADD(at[22], at[38]); MULADD(at[23], at[37]); MULADD(at[24], at[36]); MULADD(at[25], at[35]); MULADD(at[26], at[34]); MULADD(at[27], at[33]); MULADD(at[28], at[32]); + COMBA_STORE(C->dp[28]); + /* 29 */ + COMBA_FORWARD; + MULADD(at[0], at[61]); MULADD(at[1], at[60]); MULADD(at[2], at[59]); MULADD(at[3], at[58]); MULADD(at[4], at[57]); MULADD(at[5], at[56]); MULADD(at[6], at[55]); MULADD(at[7], at[54]); MULADD(at[8], at[53]); MULADD(at[9], at[52]); MULADD(at[10], at[51]); MULADD(at[11], at[50]); MULADD(at[12], at[49]); MULADD(at[13], at[48]); MULADD(at[14], at[47]); MULADD(at[15], at[46]); MULADD(at[16], at[45]); MULADD(at[17], at[44]); MULADD(at[18], at[43]); MULADD(at[19], at[42]); MULADD(at[20], at[41]); MULADD(at[21], at[40]); MULADD(at[22], at[39]); MULADD(at[23], at[38]); MULADD(at[24], at[37]); MULADD(at[25], at[36]); MULADD(at[26], at[35]); MULADD(at[27], at[34]); MULADD(at[28], at[33]); MULADD(at[29], at[32]); + COMBA_STORE(C->dp[29]); + /* 30 */ + COMBA_FORWARD; + MULADD(at[0], at[62]); MULADD(at[1], at[61]); MULADD(at[2], at[60]); MULADD(at[3], at[59]); MULADD(at[4], at[58]); MULADD(at[5], at[57]); MULADD(at[6], at[56]); MULADD(at[7], at[55]); MULADD(at[8], at[54]); MULADD(at[9], at[53]); MULADD(at[10], at[52]); MULADD(at[11], at[51]); MULADD(at[12], at[50]); MULADD(at[13], at[49]); MULADD(at[14], at[48]); MULADD(at[15], at[47]); MULADD(at[16], at[46]); MULADD(at[17], at[45]); MULADD(at[18], at[44]); MULADD(at[19], at[43]); MULADD(at[20], at[42]); MULADD(at[21], at[41]); MULADD(at[22], at[40]); MULADD(at[23], at[39]); MULADD(at[24], at[38]); MULADD(at[25], at[37]); MULADD(at[26], at[36]); MULADD(at[27], at[35]); MULADD(at[28], at[34]); MULADD(at[29], at[33]); MULADD(at[30], at[32]); + COMBA_STORE(C->dp[30]); + /* 31 */ + COMBA_FORWARD; + MULADD(at[0], at[63]); MULADD(at[1], at[62]); MULADD(at[2], at[61]); MULADD(at[3], at[60]); MULADD(at[4], at[59]); MULADD(at[5], at[58]); MULADD(at[6], at[57]); MULADD(at[7], at[56]); MULADD(at[8], at[55]); MULADD(at[9], at[54]); MULADD(at[10], at[53]); MULADD(at[11], at[52]); MULADD(at[12], at[51]); MULADD(at[13], at[50]); MULADD(at[14], at[49]); MULADD(at[15], at[48]); MULADD(at[16], at[47]); MULADD(at[17], at[46]); MULADD(at[18], at[45]); MULADD(at[19], at[44]); MULADD(at[20], at[43]); MULADD(at[21], at[42]); MULADD(at[22], at[41]); MULADD(at[23], at[40]); MULADD(at[24], at[39]); MULADD(at[25], at[38]); MULADD(at[26], at[37]); MULADD(at[27], at[36]); MULADD(at[28], at[35]); MULADD(at[29], at[34]); MULADD(at[30], at[33]); MULADD(at[31], at[32]); + COMBA_STORE(C->dp[31]); + /* 32 */ + COMBA_FORWARD; + MULADD(at[1], at[63]); MULADD(at[2], at[62]); MULADD(at[3], at[61]); MULADD(at[4], at[60]); MULADD(at[5], at[59]); MULADD(at[6], at[58]); MULADD(at[7], at[57]); MULADD(at[8], at[56]); MULADD(at[9], at[55]); MULADD(at[10], at[54]); MULADD(at[11], at[53]); MULADD(at[12], at[52]); MULADD(at[13], at[51]); MULADD(at[14], at[50]); MULADD(at[15], at[49]); MULADD(at[16], at[48]); MULADD(at[17], at[47]); MULADD(at[18], at[46]); MULADD(at[19], at[45]); MULADD(at[20], at[44]); MULADD(at[21], at[43]); MULADD(at[22], at[42]); MULADD(at[23], at[41]); MULADD(at[24], at[40]); MULADD(at[25], at[39]); MULADD(at[26], at[38]); MULADD(at[27], at[37]); MULADD(at[28], at[36]); MULADD(at[29], at[35]); MULADD(at[30], at[34]); MULADD(at[31], at[33]); + COMBA_STORE(C->dp[32]); + /* 33 */ + COMBA_FORWARD; + MULADD(at[2], at[63]); MULADD(at[3], at[62]); MULADD(at[4], at[61]); MULADD(at[5], at[60]); MULADD(at[6], at[59]); MULADD(at[7], at[58]); MULADD(at[8], at[57]); MULADD(at[9], at[56]); MULADD(at[10], at[55]); MULADD(at[11], at[54]); MULADD(at[12], at[53]); MULADD(at[13], at[52]); MULADD(at[14], at[51]); MULADD(at[15], at[50]); MULADD(at[16], at[49]); MULADD(at[17], at[48]); MULADD(at[18], at[47]); MULADD(at[19], at[46]); MULADD(at[20], at[45]); MULADD(at[21], at[44]); MULADD(at[22], at[43]); MULADD(at[23], at[42]); MULADD(at[24], at[41]); MULADD(at[25], at[40]); MULADD(at[26], at[39]); MULADD(at[27], at[38]); MULADD(at[28], at[37]); MULADD(at[29], at[36]); MULADD(at[30], at[35]); MULADD(at[31], at[34]); + COMBA_STORE(C->dp[33]); + /* 34 */ + COMBA_FORWARD; + MULADD(at[3], at[63]); MULADD(at[4], at[62]); MULADD(at[5], at[61]); MULADD(at[6], at[60]); MULADD(at[7], at[59]); MULADD(at[8], at[58]); MULADD(at[9], at[57]); MULADD(at[10], at[56]); MULADD(at[11], at[55]); MULADD(at[12], at[54]); MULADD(at[13], at[53]); MULADD(at[14], at[52]); MULADD(at[15], at[51]); MULADD(at[16], at[50]); MULADD(at[17], at[49]); MULADD(at[18], at[48]); MULADD(at[19], at[47]); MULADD(at[20], at[46]); MULADD(at[21], at[45]); MULADD(at[22], at[44]); MULADD(at[23], at[43]); MULADD(at[24], at[42]); MULADD(at[25], at[41]); MULADD(at[26], at[40]); MULADD(at[27], at[39]); MULADD(at[28], at[38]); MULADD(at[29], at[37]); MULADD(at[30], at[36]); MULADD(at[31], at[35]); + COMBA_STORE(C->dp[34]); + /* 35 */ + COMBA_FORWARD; + MULADD(at[4], at[63]); MULADD(at[5], at[62]); MULADD(at[6], at[61]); MULADD(at[7], at[60]); MULADD(at[8], at[59]); MULADD(at[9], at[58]); MULADD(at[10], at[57]); MULADD(at[11], at[56]); MULADD(at[12], at[55]); MULADD(at[13], at[54]); MULADD(at[14], at[53]); MULADD(at[15], at[52]); MULADD(at[16], at[51]); MULADD(at[17], at[50]); MULADD(at[18], at[49]); MULADD(at[19], at[48]); MULADD(at[20], at[47]); MULADD(at[21], at[46]); MULADD(at[22], at[45]); MULADD(at[23], at[44]); MULADD(at[24], at[43]); MULADD(at[25], at[42]); MULADD(at[26], at[41]); MULADD(at[27], at[40]); MULADD(at[28], at[39]); MULADD(at[29], at[38]); MULADD(at[30], at[37]); MULADD(at[31], at[36]); + COMBA_STORE(C->dp[35]); + /* 36 */ + COMBA_FORWARD; + MULADD(at[5], at[63]); MULADD(at[6], at[62]); MULADD(at[7], at[61]); MULADD(at[8], at[60]); MULADD(at[9], at[59]); MULADD(at[10], at[58]); MULADD(at[11], at[57]); MULADD(at[12], at[56]); MULADD(at[13], at[55]); MULADD(at[14], at[54]); MULADD(at[15], at[53]); MULADD(at[16], at[52]); MULADD(at[17], at[51]); MULADD(at[18], at[50]); MULADD(at[19], at[49]); MULADD(at[20], at[48]); MULADD(at[21], at[47]); MULADD(at[22], at[46]); MULADD(at[23], at[45]); MULADD(at[24], at[44]); MULADD(at[25], at[43]); MULADD(at[26], at[42]); MULADD(at[27], at[41]); MULADD(at[28], at[40]); MULADD(at[29], at[39]); MULADD(at[30], at[38]); MULADD(at[31], at[37]); + COMBA_STORE(C->dp[36]); + /* 37 */ + COMBA_FORWARD; + MULADD(at[6], at[63]); MULADD(at[7], at[62]); MULADD(at[8], at[61]); MULADD(at[9], at[60]); MULADD(at[10], at[59]); MULADD(at[11], at[58]); MULADD(at[12], at[57]); MULADD(at[13], at[56]); MULADD(at[14], at[55]); MULADD(at[15], at[54]); MULADD(at[16], at[53]); MULADD(at[17], at[52]); MULADD(at[18], at[51]); MULADD(at[19], at[50]); MULADD(at[20], at[49]); MULADD(at[21], at[48]); MULADD(at[22], at[47]); MULADD(at[23], at[46]); MULADD(at[24], at[45]); MULADD(at[25], at[44]); MULADD(at[26], at[43]); MULADD(at[27], at[42]); MULADD(at[28], at[41]); MULADD(at[29], at[40]); MULADD(at[30], at[39]); MULADD(at[31], at[38]); + COMBA_STORE(C->dp[37]); + /* 38 */ + COMBA_FORWARD; + MULADD(at[7], at[63]); MULADD(at[8], at[62]); MULADD(at[9], at[61]); MULADD(at[10], at[60]); MULADD(at[11], at[59]); MULADD(at[12], at[58]); MULADD(at[13], at[57]); MULADD(at[14], at[56]); MULADD(at[15], at[55]); MULADD(at[16], at[54]); MULADD(at[17], at[53]); MULADD(at[18], at[52]); MULADD(at[19], at[51]); MULADD(at[20], at[50]); MULADD(at[21], at[49]); MULADD(at[22], at[48]); MULADD(at[23], at[47]); MULADD(at[24], at[46]); MULADD(at[25], at[45]); MULADD(at[26], at[44]); MULADD(at[27], at[43]); MULADD(at[28], at[42]); MULADD(at[29], at[41]); MULADD(at[30], at[40]); MULADD(at[31], at[39]); + COMBA_STORE(C->dp[38]); + + /* early out at 40 digits, 40*32==1280, or two 640 bit operands */ + if (out_size <= 40) { COMBA_STORE2(C->dp[39]); C->used = 40; C->sign = A->sign ^ B->sign; pstm_clamp(C); COMBA_FINI; return PSTM_OKAY; } + + /* 39 */ + COMBA_FORWARD; + MULADD(at[8], at[63]); MULADD(at[9], at[62]); MULADD(at[10], at[61]); MULADD(at[11], at[60]); MULADD(at[12], at[59]); MULADD(at[13], at[58]); MULADD(at[14], at[57]); MULADD(at[15], at[56]); MULADD(at[16], at[55]); MULADD(at[17], at[54]); MULADD(at[18], at[53]); MULADD(at[19], at[52]); MULADD(at[20], at[51]); MULADD(at[21], at[50]); MULADD(at[22], at[49]); MULADD(at[23], at[48]); MULADD(at[24], at[47]); MULADD(at[25], at[46]); MULADD(at[26], at[45]); MULADD(at[27], at[44]); MULADD(at[28], at[43]); MULADD(at[29], at[42]); MULADD(at[30], at[41]); MULADD(at[31], at[40]); + COMBA_STORE(C->dp[39]); + /* 40 */ + COMBA_FORWARD; + MULADD(at[9], at[63]); MULADD(at[10], at[62]); MULADD(at[11], at[61]); MULADD(at[12], at[60]); MULADD(at[13], at[59]); MULADD(at[14], at[58]); MULADD(at[15], at[57]); MULADD(at[16], at[56]); MULADD(at[17], at[55]); MULADD(at[18], at[54]); MULADD(at[19], at[53]); MULADD(at[20], at[52]); MULADD(at[21], at[51]); MULADD(at[22], at[50]); MULADD(at[23], at[49]); MULADD(at[24], at[48]); MULADD(at[25], at[47]); MULADD(at[26], at[46]); MULADD(at[27], at[45]); MULADD(at[28], at[44]); MULADD(at[29], at[43]); MULADD(at[30], at[42]); MULADD(at[31], at[41]); + COMBA_STORE(C->dp[40]); + /* 41 */ + COMBA_FORWARD; + MULADD(at[10], at[63]); MULADD(at[11], at[62]); MULADD(at[12], at[61]); MULADD(at[13], at[60]); MULADD(at[14], at[59]); MULADD(at[15], at[58]); MULADD(at[16], at[57]); MULADD(at[17], at[56]); MULADD(at[18], at[55]); MULADD(at[19], at[54]); MULADD(at[20], at[53]); MULADD(at[21], at[52]); MULADD(at[22], at[51]); MULADD(at[23], at[50]); MULADD(at[24], at[49]); MULADD(at[25], at[48]); MULADD(at[26], at[47]); MULADD(at[27], at[46]); MULADD(at[28], at[45]); MULADD(at[29], at[44]); MULADD(at[30], at[43]); MULADD(at[31], at[42]); + COMBA_STORE(C->dp[41]); + /* 42 */ + COMBA_FORWARD; + MULADD(at[11], at[63]); MULADD(at[12], at[62]); MULADD(at[13], at[61]); MULADD(at[14], at[60]); MULADD(at[15], at[59]); MULADD(at[16], at[58]); MULADD(at[17], at[57]); MULADD(at[18], at[56]); MULADD(at[19], at[55]); MULADD(at[20], at[54]); MULADD(at[21], at[53]); MULADD(at[22], at[52]); MULADD(at[23], at[51]); MULADD(at[24], at[50]); MULADD(at[25], at[49]); MULADD(at[26], at[48]); MULADD(at[27], at[47]); MULADD(at[28], at[46]); MULADD(at[29], at[45]); MULADD(at[30], at[44]); MULADD(at[31], at[43]); + COMBA_STORE(C->dp[42]); + /* 43 */ + COMBA_FORWARD; + MULADD(at[12], at[63]); MULADD(at[13], at[62]); MULADD(at[14], at[61]); MULADD(at[15], at[60]); MULADD(at[16], at[59]); MULADD(at[17], at[58]); MULADD(at[18], at[57]); MULADD(at[19], at[56]); MULADD(at[20], at[55]); MULADD(at[21], at[54]); MULADD(at[22], at[53]); MULADD(at[23], at[52]); MULADD(at[24], at[51]); MULADD(at[25], at[50]); MULADD(at[26], at[49]); MULADD(at[27], at[48]); MULADD(at[28], at[47]); MULADD(at[29], at[46]); MULADD(at[30], at[45]); MULADD(at[31], at[44]); + COMBA_STORE(C->dp[43]); + /* 44 */ + COMBA_FORWARD; + MULADD(at[13], at[63]); MULADD(at[14], at[62]); MULADD(at[15], at[61]); MULADD(at[16], at[60]); MULADD(at[17], at[59]); MULADD(at[18], at[58]); MULADD(at[19], at[57]); MULADD(at[20], at[56]); MULADD(at[21], at[55]); MULADD(at[22], at[54]); MULADD(at[23], at[53]); MULADD(at[24], at[52]); MULADD(at[25], at[51]); MULADD(at[26], at[50]); MULADD(at[27], at[49]); MULADD(at[28], at[48]); MULADD(at[29], at[47]); MULADD(at[30], at[46]); MULADD(at[31], at[45]); + COMBA_STORE(C->dp[44]); + /* 45 */ + COMBA_FORWARD; + MULADD(at[14], at[63]); MULADD(at[15], at[62]); MULADD(at[16], at[61]); MULADD(at[17], at[60]); MULADD(at[18], at[59]); MULADD(at[19], at[58]); MULADD(at[20], at[57]); MULADD(at[21], at[56]); MULADD(at[22], at[55]); MULADD(at[23], at[54]); MULADD(at[24], at[53]); MULADD(at[25], at[52]); MULADD(at[26], at[51]); MULADD(at[27], at[50]); MULADD(at[28], at[49]); MULADD(at[29], at[48]); MULADD(at[30], at[47]); MULADD(at[31], at[46]); + COMBA_STORE(C->dp[45]); + /* 46 */ + COMBA_FORWARD; + MULADD(at[15], at[63]); MULADD(at[16], at[62]); MULADD(at[17], at[61]); MULADD(at[18], at[60]); MULADD(at[19], at[59]); MULADD(at[20], at[58]); MULADD(at[21], at[57]); MULADD(at[22], at[56]); MULADD(at[23], at[55]); MULADD(at[24], at[54]); MULADD(at[25], at[53]); MULADD(at[26], at[52]); MULADD(at[27], at[51]); MULADD(at[28], at[50]); MULADD(at[29], at[49]); MULADD(at[30], at[48]); MULADD(at[31], at[47]); + COMBA_STORE(C->dp[46]); + + /* early out at 48 digits, 48*32==1536, or two 768 bit operands */ + if (out_size <= 48) { COMBA_STORE2(C->dp[47]); C->used = 48; C->sign = A->sign ^ B->sign; pstm_clamp(C); COMBA_FINI; return PSTM_OKAY; } + + /* 47 */ + COMBA_FORWARD; + MULADD(at[16], at[63]); MULADD(at[17], at[62]); MULADD(at[18], at[61]); MULADD(at[19], at[60]); MULADD(at[20], at[59]); MULADD(at[21], at[58]); MULADD(at[22], at[57]); MULADD(at[23], at[56]); MULADD(at[24], at[55]); MULADD(at[25], at[54]); MULADD(at[26], at[53]); MULADD(at[27], at[52]); MULADD(at[28], at[51]); MULADD(at[29], at[50]); MULADD(at[30], at[49]); MULADD(at[31], at[48]); + COMBA_STORE(C->dp[47]); + /* 48 */ + COMBA_FORWARD; + MULADD(at[17], at[63]); MULADD(at[18], at[62]); MULADD(at[19], at[61]); MULADD(at[20], at[60]); MULADD(at[21], at[59]); MULADD(at[22], at[58]); MULADD(at[23], at[57]); MULADD(at[24], at[56]); MULADD(at[25], at[55]); MULADD(at[26], at[54]); MULADD(at[27], at[53]); MULADD(at[28], at[52]); MULADD(at[29], at[51]); MULADD(at[30], at[50]); MULADD(at[31], at[49]); + COMBA_STORE(C->dp[48]); + /* 49 */ + COMBA_FORWARD; + MULADD(at[18], at[63]); MULADD(at[19], at[62]); MULADD(at[20], at[61]); MULADD(at[21], at[60]); MULADD(at[22], at[59]); MULADD(at[23], at[58]); MULADD(at[24], at[57]); MULADD(at[25], at[56]); MULADD(at[26], at[55]); MULADD(at[27], at[54]); MULADD(at[28], at[53]); MULADD(at[29], at[52]); MULADD(at[30], at[51]); MULADD(at[31], at[50]); + COMBA_STORE(C->dp[49]); + /* 50 */ + COMBA_FORWARD; + MULADD(at[19], at[63]); MULADD(at[20], at[62]); MULADD(at[21], at[61]); MULADD(at[22], at[60]); MULADD(at[23], at[59]); MULADD(at[24], at[58]); MULADD(at[25], at[57]); MULADD(at[26], at[56]); MULADD(at[27], at[55]); MULADD(at[28], at[54]); MULADD(at[29], at[53]); MULADD(at[30], at[52]); MULADD(at[31], at[51]); + COMBA_STORE(C->dp[50]); + /* 51 */ + COMBA_FORWARD; + MULADD(at[20], at[63]); MULADD(at[21], at[62]); MULADD(at[22], at[61]); MULADD(at[23], at[60]); MULADD(at[24], at[59]); MULADD(at[25], at[58]); MULADD(at[26], at[57]); MULADD(at[27], at[56]); MULADD(at[28], at[55]); MULADD(at[29], at[54]); MULADD(at[30], at[53]); MULADD(at[31], at[52]); + COMBA_STORE(C->dp[51]); + /* 52 */ + COMBA_FORWARD; + MULADD(at[21], at[63]); MULADD(at[22], at[62]); MULADD(at[23], at[61]); MULADD(at[24], at[60]); MULADD(at[25], at[59]); MULADD(at[26], at[58]); MULADD(at[27], at[57]); MULADD(at[28], at[56]); MULADD(at[29], at[55]); MULADD(at[30], at[54]); MULADD(at[31], at[53]); + COMBA_STORE(C->dp[52]); + /* 53 */ + COMBA_FORWARD; + MULADD(at[22], at[63]); MULADD(at[23], at[62]); MULADD(at[24], at[61]); MULADD(at[25], at[60]); MULADD(at[26], at[59]); MULADD(at[27], at[58]); MULADD(at[28], at[57]); MULADD(at[29], at[56]); MULADD(at[30], at[55]); MULADD(at[31], at[54]); + COMBA_STORE(C->dp[53]); + /* 54 */ + COMBA_FORWARD; + MULADD(at[23], at[63]); MULADD(at[24], at[62]); MULADD(at[25], at[61]); MULADD(at[26], at[60]); MULADD(at[27], at[59]); MULADD(at[28], at[58]); MULADD(at[29], at[57]); MULADD(at[30], at[56]); MULADD(at[31], at[55]); + COMBA_STORE(C->dp[54]); + + /* early out at 56 digits, 56*32==1792, or two 896 bit operands */ + if (out_size <= 56) { COMBA_STORE2(C->dp[55]); C->used = 56; C->sign = A->sign ^ B->sign; pstm_clamp(C); COMBA_FINI; return PSTM_OKAY; } + + /* 55 */ + COMBA_FORWARD; + MULADD(at[24], at[63]); MULADD(at[25], at[62]); MULADD(at[26], at[61]); MULADD(at[27], at[60]); MULADD(at[28], at[59]); MULADD(at[29], at[58]); MULADD(at[30], at[57]); MULADD(at[31], at[56]); + COMBA_STORE(C->dp[55]); + /* 56 */ + COMBA_FORWARD; + MULADD(at[25], at[63]); MULADD(at[26], at[62]); MULADD(at[27], at[61]); MULADD(at[28], at[60]); MULADD(at[29], at[59]); MULADD(at[30], at[58]); MULADD(at[31], at[57]); + COMBA_STORE(C->dp[56]); + /* 57 */ + COMBA_FORWARD; + MULADD(at[26], at[63]); MULADD(at[27], at[62]); MULADD(at[28], at[61]); MULADD(at[29], at[60]); MULADD(at[30], at[59]); MULADD(at[31], at[58]); + COMBA_STORE(C->dp[57]); + /* 58 */ + COMBA_FORWARD; + MULADD(at[27], at[63]); MULADD(at[28], at[62]); MULADD(at[29], at[61]); MULADD(at[30], at[60]); MULADD(at[31], at[59]); + COMBA_STORE(C->dp[58]); + /* 59 */ + COMBA_FORWARD; + MULADD(at[28], at[63]); MULADD(at[29], at[62]); MULADD(at[30], at[61]); MULADD(at[31], at[60]); + COMBA_STORE(C->dp[59]); + /* 60 */ + COMBA_FORWARD; + MULADD(at[29], at[63]); MULADD(at[30], at[62]); MULADD(at[31], at[61]); + COMBA_STORE(C->dp[60]); + /* 61 */ + COMBA_FORWARD; + MULADD(at[30], at[63]); MULADD(at[31], at[62]); + COMBA_STORE(C->dp[61]); + /* 62 */ + COMBA_FORWARD; + MULADD(at[31], at[63]); + COMBA_STORE(C->dp[62]); + COMBA_STORE2(C->dp[63]); + C->used = 64; + C->sign = A->sign ^ B->sign; + pstm_clamp(C); + COMBA_FINI; + return PSTM_OKAY; +} +#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */ + +/******************************************************************************/ + +int32 pstm_mul_comba(psPool_t *pool, const pstm_int *A, const pstm_int *B, pstm_int *C, + pstm_digit *paD, uint16_t paDlen) +{ +#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS + if (A->used == 16 && B->used == 16) { + return pstm_mul_comba16(A, B, C); + } else { +#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS + if (A->used == 32 && B->used == 32) { + return pstm_mul_comba32(A, B, C); + } +#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */ + return pstm_mul_comba_gen(pool, A, B, C, paD, paDlen); + } +#else +#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS + if (A->used == 32 && B->used == 32) { + return pstm_mul_comba32(A, B, C); + } +#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */ + return pstm_mul_comba_gen(pool, A, B, C, paD, paDlen); +#endif +} + +#endif /* defined(USE_MATRIX_RSA) || defined(USE_MATRIX_ECC) */ + +/******************************************************************************/ + diff --git a/crypto/math/pstm_sqr_comba.c b/crypto/math/pstm_sqr_comba.c new file mode 100644 index 0000000..2dd3dcb --- /dev/null +++ b/crypto/math/pstm_sqr_comba.c @@ -0,0 +1,1109 @@ +/** + * @file pstm_sqr_comba.c + * @version $Format:%h%d$ + * + * Multiprecision Squaring with Comba technique. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#if defined(USE_MATRIX_RSA) || defined(USE_MATRIX_ECC) || defined(USE_MATRIX_DH) + +/******************************************************************************/ +#if defined(PSTM_X86) +/* x86-32 optimized for 32 bit platforms. For 64 bit mode use X86_64 instead */ +#if !defined(__GNUC__) || !defined(__i386__) +#error "PSTM_X86 option requires GCC and 32 bit mode x86 processor" +#endif +//#pragma message ("Using 32 bit x86 Assembly Optimizations") + +#define COMBA_START + +#define CLEAR_CARRY \ + c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define CARRY_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +#define SQRADD(i, j) \ +asm( \ + "movl %6,%%eax \n\t" \ + "mull %%eax \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl %%edx,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","%edx","%cc"); + +#define SQRADD2(i, j) \ +asm( \ + "movl %6,%%eax \n\t" \ + "mull %7 \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl %%edx,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl %%edx,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","%cc"); + +#define SQRADDSC(i, j) \ +asm( \ + "movl %6,%%eax \n\t" \ + "mull %7 \n\t" \ + "movl %%eax,%0 \n\t" \ + "movl %%edx,%1 \n\t" \ + "xorl %2,%2 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","%cc"); + +#define SQRADDAC(i, j) \ +asm( \ + "movl %6,%%eax \n\t" \ + "mull %7 \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl %%edx,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","%cc"); + +#define SQRADDDB \ +asm( \ + "addl %6,%0 \n\t" \ + "adcl %7,%1 \n\t" \ + "adcl %8,%2 \n\t" \ + "addl %6,%0 \n\t" \ + "adcl %7,%1 \n\t" \ + "adcl %8,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "%cc"); + +/******************************************************************************/ +#elif defined(PSTM_X86_64) +/* x86-64 optimized */ +#if !defined(__GNUC__) || !defined(__x86_64__) || !defined(PSTM_64BIT) +#error "PSTM_X86_64 option requires PSTM_64BIT, GCC and 64 bit mode x86 processor" +#endif +//#pragma message ("Using 64 bit x86_64 Assembly Optimizations") + +#define COMBA_START + +#define CLEAR_CARRY \ +c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ +x = c0; + +#define COMBA_STORE2(x) \ +x = c1; + +#define CARRY_FORWARD \ +do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +#define SQRADD(i, j) \ +asm( \ + "movq %6,%%rax \n\t" \ + "mulq %%rax \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i) :"%rax","%rdx","cc"); + +#define SQRADD2(i, j) \ +asm( \ + "movq %6,%%rax \n\t" \ + "mulq %7 \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j) :"%rax","%rdx","cc"); + +#define SQRADDSC(i, j) \ +asm( \ + "movq %6,%%rax \n\t" \ + "mulq %7 \n\t" \ + "movq %%rax,%0 \n\t" \ + "movq %%rdx,%1 \n\t" \ + "xorq %2,%2 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%rax","%rdx","cc"); + +#define SQRADDAC(i, j) \ +asm( \ + "movq %6,%%rax \n\t" \ + "mulq %7 \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%rax","%rdx","cc"); + +#define SQRADDDB \ +asm( \ + "addq %6,%0 \n\t" \ + "adcq %7,%1 \n\t" \ + "adcq %8,%2 \n\t" \ + "addq %6,%0 \n\t" \ + "adcq %7,%1 \n\t" \ + "adcq %8,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "cc"); + +/******************************************************************************/ +#elif defined(PSTM_ARM) +/* ARM code */ +//#pragma message ("Using 32 bit ARM Assembly Optimizations") + +#define COMBA_START + +#define CLEAR_CARRY \ +c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ +x = c0; + +#define COMBA_STORE2(x) \ +x = c1; + +#define CARRY_FORWARD \ +do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +/* multiplies point i and j, updates carry "c1" and digit c2 */ +#define SQRADD(i, j) \ +asm( \ +" UMULL r0,r1,%6,%6 \n\t" \ +" ADDS %0,%0,r0 \n\t" \ +" ADCS %1,%1,r1 \n\t" \ +" ADC %2,%2,#0 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i) : "r0", "r1", "%cc"); + +/* for squaring some of the terms are doubled... */ +#define SQRADD2(i, j) \ +asm( \ +" UMULL r0,r1,%6,%7 \n\t" \ +" ADDS %0,%0,r0 \n\t" \ +" ADCS %1,%1,r1 \n\t" \ +" ADC %2,%2,#0 \n\t" \ +" ADDS %0,%0,r0 \n\t" \ +" ADCS %1,%1,r1 \n\t" \ +" ADC %2,%2,#0 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "%cc"); + +#define SQRADDSC(i, j) \ +asm( \ +" UMULL %0,%1,%6,%7 \n\t" \ +" SUB %2,%2,%2 \n\t" \ +:"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "%cc"); + +#define SQRADDAC(i, j) \ +asm( \ +" UMULL r0,r1,%6,%7 \n\t" \ +" ADDS %0,%0,r0 \n\t" \ +" ADCS %1,%1,r1 \n\t" \ +" ADC %2,%2,#0 \n\t" \ +:"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "r0", "r1", "%cc"); + +#define SQRADDDB \ +asm( \ +" ADDS %0,%0,%3 \n\t" \ +" ADCS %1,%1,%4 \n\t" \ +" ADC %2,%2,%5 \n\t" \ +" ADDS %0,%0,%3 \n\t" \ +" ADCS %1,%1,%4 \n\t" \ +" ADC %2,%2,%5 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "%cc"); + +/******************************************************************************/ +#elif defined(PSTM_MIPS) +/* MIPS32 */ +//#pragma message ("Using 32 bit MIPS Assembly Optimizations") + +#define COMBA_START + +#define CLEAR_CARRY \ +c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ +x = c0; + +#define COMBA_STORE2(x) \ +x = c1; + +#define CARRY_FORWARD \ +do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +/* multiplies point i and j, updates carry "c1" and digit c2 */ +#define SQRADD(i, j) \ +asm( \ + " multu %6,%6 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + " addu %0,%0,$12 \n\t" \ + " sltu $12,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $13,%1,$13 \n\t" \ + " addu %1,%1,$12 \n\t" \ + " sltu $12,%1,$12 \n\t" \ + " addu %2,%2,$13 \n\t" \ + " addu %2,%2,$12 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"$12","$13"); + +/* for squaring some of the terms are doubled... */ +#define SQRADD2(i, j) \ +asm( \ + " multu %6,%7 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + \ + " addu %0,%0,$12 \n\t" \ + " sltu $14,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $15,%1,$13 \n\t" \ + " addu %1,%1,$14 \n\t" \ + " sltu $14,%1,$14 \n\t" \ + " addu %2,%2,$15 \n\t" \ + " addu %2,%2,$14 \n\t" \ + \ + " addu %0,%0,$12 \n\t" \ + " sltu $14,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $15,%1,$13 \n\t" \ + " addu %1,%1,$14 \n\t" \ + " sltu $14,%1,$14 \n\t" \ + " addu %2,%2,$15 \n\t" \ + " addu %2,%2,$14 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12", "$13", "$14", "$15"); + +#define SQRADDSC(i, j) \ +asm( \ + " multu %6,%7 \n\t" \ + " mflo %0 \n\t" \ + " mfhi %1 \n\t" \ + " xor %2,%2,%2 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "%cc"); + +#define SQRADDAC(i, j) \ +asm( \ + " multu %6,%7 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + " addu %0,%0,$12 \n\t" \ + " sltu $12,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $13,%1,$13 \n\t" \ + " addu %1,%1,$12 \n\t" \ + " sltu $12,%1,$12 \n\t" \ + " addu %2,%2,$13 \n\t" \ + " addu %2,%2,$12 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"$12", "$13", "$14"); + +#define SQRADDDB \ +asm( \ + " addu %0,%0,%3 \n\t" \ + " sltu $10,%0,%3 \n\t" \ + " addu %1,%1,$10 \n\t" \ + " sltu $10,%1,$10 \n\t" \ + " addu %1,%1,%4 \n\t" \ + " sltu $11,%1,%4 \n\t" \ + " addu %2,%2,$10 \n\t" \ + " addu %2,%2,$11 \n\t" \ + " addu %2,%2,%5 \n\t" \ + \ + " addu %0,%0,%3 \n\t" \ + " sltu $10,%0,%3 \n\t" \ + " addu %1,%1,$10 \n\t" \ + " sltu $10,%1,$10 \n\t" \ + " addu %1,%1,%4 \n\t" \ + " sltu $11,%1,%4 \n\t" \ + " addu %2,%2,$10 \n\t" \ + " addu %2,%2,$11 \n\t" \ + " addu %2,%2,%5 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "$10", "$11"); + +#else +/******************************************************************************/ +#define PSTM_ISO +/* ISO C portable code */ + +#define COMBA_START + +#define CLEAR_CARRY \ + c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define CARRY_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +/* multiplies point i and j, updates carry "c1" and digit c2 */ +#define SQRADD(i, j) \ + do { pstm_word t; \ + t = c0 + ((pstm_word)i) * ((pstm_word)j); c0 = (pstm_digit)t; \ + t = c1 + (t >> DIGIT_BIT); \ + c1 = (pstm_digit)t; c2 += (pstm_digit)(t >> DIGIT_BIT); \ + } while (0); + + +/* for squaring some of the terms are doubled... */ +#define SQRADD2(i, j) \ + do { pstm_word t; \ + t = ((pstm_word)i) * ((pstm_word)j); \ + tt = (pstm_word)c0 + t; c0 = (pstm_digit)tt; \ + tt = (pstm_word)c1 + (tt >> DIGIT_BIT); \ + c1 = (pstm_digit)tt; c2 += (pstm_digit)(tt >> DIGIT_BIT); \ + tt = (pstm_word)c0 + t; c0 = (pstm_digit)tt; \ + tt = (pstm_word)c1 + (tt >> DIGIT_BIT); \ + c1 = (pstm_digit)tt; c2 += (pstm_digit)(tt >> DIGIT_BIT); \ + } while (0); + +#define SQRADDSC(i, j) \ + do { pstm_word t; \ + t = ((pstm_word)i) * ((pstm_word)j); \ + sc0 = (pstm_digit)t; sc1 = (pstm_digit)(t >> DIGIT_BIT); sc2 = 0; \ + } while (0); + +#define SQRADDAC(i, j) \ + do { pstm_word t; \ + t = ((pstm_word)sc0) + ((pstm_word)i) * ((pstm_word)j); \ + sc0 = (pstm_digit)t; \ + t = ((pstm_word)sc1) + (t >> DIGIT_BIT); sc1 = (pstm_digit)t; \ + sc2 += (pstm_digit)(t >> DIGIT_BIT); \ + } while (0); + +#define SQRADDDB \ + do { pstm_word t; \ + t = ((pstm_word)sc0) + ((pstm_word)sc0) + ((pstm_word)c0); \ + c0 = (pstm_digit)t; \ + t = ((pstm_word)sc1) + ((pstm_word)sc1) + c1 + (t >> DIGIT_BIT); \ + c1 = (pstm_digit)t; \ + c2 = c2 + sc2 + sc2 + (pstm_digit)(t >> DIGIT_BIT); \ + } while (0); + +#endif /* ISO_C */ + +/******************************************************************************/ +/* + Non-unrolled comba squarer + */ +static int32_t pstm_sqr_comba_gen(psPool_t *pool, const pstm_int *A, + pstm_int *B, pstm_digit *paD, uint16_t paDlen) +{ + int16 paDfail, pa; + int32 ix, iz; + pstm_digit c0, c1, c2, *dst; +#ifdef PSTM_ISO + pstm_word tt; +#endif + + paDfail = 0; + /* get size of output and trim */ + pa = A->used + A->used; + + /* number of output digits to produce */ + COMBA_START; + CLEAR_CARRY; +/* + If b is not large enough grow it and continue +*/ + if (B->alloc < pa) { + if (pstm_grow(B, pa) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + if (paD != NULL) { + if (paDlen < (sizeof(pstm_digit) * pa)) { + paDfail = 1; /* have a paD, but it's not big enough */ + if ((dst = psMalloc(pool, sizeof(pstm_digit) * pa)) == NULL) { + return PS_MEM_FAIL; + } + memset(dst, 0x0, sizeof(pstm_digit) * pa); + } else { + dst = paD; + memset(dst, 0x0, paDlen); + } + } else { + if ((dst = psMalloc(pool, sizeof(pstm_digit) * pa)) == NULL) { + return PS_MEM_FAIL; + } + memset(dst, 0x0, sizeof(pstm_digit) * pa); + } + + for (ix = 0; ix < pa; ix++) { + int32 tx, ty, iy; + pstm_digit *tmpy, *tmpx; + + /* get offsets into the two bignums */ + ty = min(A->used-1, ix); + tx = ix - ty; + + /* setup temp aliases */ + tmpx = A->dp + tx; + tmpy = A->dp + ty; +/* + This is the number of times the loop will iterate + while (tx++ < a->used && ty-- >= 0) { ... } +*/ + iy = min(A->used-tx, ty+1); +/* + now for squaring, tx can never equal ty. We halve the distance since + they approach at a rate of 2x and we have to round because odd cases + need to be executed +*/ + iy = min(iy, (ty-tx+1)>>1); + + /* forward carries */ + CARRY_FORWARD; + + /* execute loop */ + for (iz = 0; iz < iy; iz++) { + SQRADD2(*tmpx++, *tmpy--); + } + + /* even columns have the square term in them */ + if ((ix&1) == 0) { + SQRADD(A->dp[ix>>1], A->dp[ix>>1]); + } + + /* store it */ + COMBA_STORE(dst[ix]); + } + + COMBA_FINI; +/* + setup dest + */ + iz = B->used; + B->used = pa; + { + pstm_digit *tmpc; + tmpc = B->dp; + for (ix = 0; ix < pa; ix++) { + *tmpc++ = dst[ix]; + } + /* clear unused digits (that existed in the old copy of c) */ + for (; ix < iz; ix++) { + *tmpc++ = 0; + } + } + pstm_clamp(B); + + if ((paD == NULL) || paDfail == 1) { + psFree(dst, pool); + } + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Unrolled Comba loop for 1024 bit keys + */ +#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS +static int32_t pstm_sqr_comba16(const pstm_int *A, pstm_int *B) +{ + pstm_digit *a, b[32], c0, c1, c2, sc0, sc1, sc2; +#ifdef PSTM_ISO + pstm_word tt; +#endif + + if (B->alloc < 32) { + if (pstm_grow(B, 32) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + a = A->dp; + sc0 = sc1 = sc2 = 0; + + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADDSC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + + /* output 23 */ + CARRY_FORWARD; + SQRADDSC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; + COMBA_STORE(b[23]); + + /* output 24 */ + CARRY_FORWARD; + SQRADDSC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]); + COMBA_STORE(b[24]); + + /* output 25 */ + CARRY_FORWARD; + SQRADDSC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB; + COMBA_STORE(b[25]); + + /* output 26 */ + CARRY_FORWARD; + SQRADD2(a[11], a[15]); SQRADD2(a[12], a[14]); SQRADD(a[13], a[13]); + COMBA_STORE(b[26]); + + /* output 27 */ + CARRY_FORWARD; + SQRADD2(a[12], a[15]); SQRADD2(a[13], a[14]); + COMBA_STORE(b[27]); + + /* output 28 */ + CARRY_FORWARD; + SQRADD2(a[13], a[15]); SQRADD(a[14], a[14]); + COMBA_STORE(b[28]); + + /* output 29 */ + CARRY_FORWARD; + SQRADD2(a[14], a[15]); + COMBA_STORE(b[29]); + + /* output 30 */ + CARRY_FORWARD; + SQRADD(a[15], a[15]); + COMBA_STORE(b[30]); + COMBA_STORE2(b[31]); + COMBA_FINI; + + B->used = 32; + B->sign = PSTM_ZPOS; + memcpy(B->dp, b, 32 * sizeof(pstm_digit)); + pstm_clamp(B); + return PSTM_OKAY; +} +#endif /* USE_1024_KEY_SPEED_OPTIMIZATIONS */ + + +#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS +static int32_t pstm_sqr_comba32(const pstm_int *A, pstm_int *B) +{ + pstm_digit *a, b[64], c0, c1, c2, sc0, sc1, sc2; +#ifdef PSTM_ISO + pstm_word tt; +#endif + + if (B->alloc < 64) { + if (pstm_grow(B, 64) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + sc0 = sc1 = sc2 = 0; + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[20]); SQRADDAC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[21]); SQRADDAC(a[1], a[20]); SQRADDAC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[22]); SQRADDAC(a[1], a[21]); SQRADDAC(a[2], a[20]); SQRADDAC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + + /* output 23 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[23]); SQRADDAC(a[1], a[22]); SQRADDAC(a[2], a[21]); SQRADDAC(a[3], a[20]); SQRADDAC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; + COMBA_STORE(b[23]); + + /* output 24 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[24]); SQRADDAC(a[1], a[23]); SQRADDAC(a[2], a[22]); SQRADDAC(a[3], a[21]); SQRADDAC(a[4], a[20]); SQRADDAC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]); + COMBA_STORE(b[24]); + + /* output 25 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[25]); SQRADDAC(a[1], a[24]); SQRADDAC(a[2], a[23]); SQRADDAC(a[3], a[22]); SQRADDAC(a[4], a[21]); SQRADDAC(a[5], a[20]); SQRADDAC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB; + COMBA_STORE(b[25]); + + /* output 26 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[26]); SQRADDAC(a[1], a[25]); SQRADDAC(a[2], a[24]); SQRADDAC(a[3], a[23]); SQRADDAC(a[4], a[22]); SQRADDAC(a[5], a[21]); SQRADDAC(a[6], a[20]); SQRADDAC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]); + COMBA_STORE(b[26]); + + /* output 27 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[27]); SQRADDAC(a[1], a[26]); SQRADDAC(a[2], a[25]); SQRADDAC(a[3], a[24]); SQRADDAC(a[4], a[23]); SQRADDAC(a[5], a[22]); SQRADDAC(a[6], a[21]); SQRADDAC(a[7], a[20]); SQRADDAC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB; + COMBA_STORE(b[27]); + + /* output 28 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[28]); SQRADDAC(a[1], a[27]); SQRADDAC(a[2], a[26]); SQRADDAC(a[3], a[25]); SQRADDAC(a[4], a[24]); SQRADDAC(a[5], a[23]); SQRADDAC(a[6], a[22]); SQRADDAC(a[7], a[21]); SQRADDAC(a[8], a[20]); SQRADDAC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]); + COMBA_STORE(b[28]); + + /* output 29 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[29]); SQRADDAC(a[1], a[28]); SQRADDAC(a[2], a[27]); SQRADDAC(a[3], a[26]); SQRADDAC(a[4], a[25]); SQRADDAC(a[5], a[24]); SQRADDAC(a[6], a[23]); SQRADDAC(a[7], a[22]); SQRADDAC(a[8], a[21]); SQRADDAC(a[9], a[20]); SQRADDAC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB; + COMBA_STORE(b[29]); + + /* output 30 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[30]); SQRADDAC(a[1], a[29]); SQRADDAC(a[2], a[28]); SQRADDAC(a[3], a[27]); SQRADDAC(a[4], a[26]); SQRADDAC(a[5], a[25]); SQRADDAC(a[6], a[24]); SQRADDAC(a[7], a[23]); SQRADDAC(a[8], a[22]); SQRADDAC(a[9], a[21]); SQRADDAC(a[10], a[20]); SQRADDAC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]); + COMBA_STORE(b[30]); + + /* output 31 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[31]); SQRADDAC(a[1], a[30]); SQRADDAC(a[2], a[29]); SQRADDAC(a[3], a[28]); SQRADDAC(a[4], a[27]); SQRADDAC(a[5], a[26]); SQRADDAC(a[6], a[25]); SQRADDAC(a[7], a[24]); SQRADDAC(a[8], a[23]); SQRADDAC(a[9], a[22]); SQRADDAC(a[10], a[21]); SQRADDAC(a[11], a[20]); SQRADDAC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB; + COMBA_STORE(b[31]); + + /* output 32 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[31]); SQRADDAC(a[2], a[30]); SQRADDAC(a[3], a[29]); SQRADDAC(a[4], a[28]); SQRADDAC(a[5], a[27]); SQRADDAC(a[6], a[26]); SQRADDAC(a[7], a[25]); SQRADDAC(a[8], a[24]); SQRADDAC(a[9], a[23]); SQRADDAC(a[10], a[22]); SQRADDAC(a[11], a[21]); SQRADDAC(a[12], a[20]); SQRADDAC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]); + COMBA_STORE(b[32]); + + /* output 33 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[31]); SQRADDAC(a[3], a[30]); SQRADDAC(a[4], a[29]); SQRADDAC(a[5], a[28]); SQRADDAC(a[6], a[27]); SQRADDAC(a[7], a[26]); SQRADDAC(a[8], a[25]); SQRADDAC(a[9], a[24]); SQRADDAC(a[10], a[23]); SQRADDAC(a[11], a[22]); SQRADDAC(a[12], a[21]); SQRADDAC(a[13], a[20]); SQRADDAC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB; + COMBA_STORE(b[33]); + + /* output 34 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[31]); SQRADDAC(a[4], a[30]); SQRADDAC(a[5], a[29]); SQRADDAC(a[6], a[28]); SQRADDAC(a[7], a[27]); SQRADDAC(a[8], a[26]); SQRADDAC(a[9], a[25]); SQRADDAC(a[10], a[24]); SQRADDAC(a[11], a[23]); SQRADDAC(a[12], a[22]); SQRADDAC(a[13], a[21]); SQRADDAC(a[14], a[20]); SQRADDAC(a[15], a[19]); SQRADDAC(a[16], a[18]); SQRADDDB; SQRADD(a[17], a[17]); + COMBA_STORE(b[34]); + + /* output 35 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[31]); SQRADDAC(a[5], a[30]); SQRADDAC(a[6], a[29]); SQRADDAC(a[7], a[28]); SQRADDAC(a[8], a[27]); SQRADDAC(a[9], a[26]); SQRADDAC(a[10], a[25]); SQRADDAC(a[11], a[24]); SQRADDAC(a[12], a[23]); SQRADDAC(a[13], a[22]); SQRADDAC(a[14], a[21]); SQRADDAC(a[15], a[20]); SQRADDAC(a[16], a[19]); SQRADDAC(a[17], a[18]); SQRADDDB; + COMBA_STORE(b[35]); + + /* output 36 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[31]); SQRADDAC(a[6], a[30]); SQRADDAC(a[7], a[29]); SQRADDAC(a[8], a[28]); SQRADDAC(a[9], a[27]); SQRADDAC(a[10], a[26]); SQRADDAC(a[11], a[25]); SQRADDAC(a[12], a[24]); SQRADDAC(a[13], a[23]); SQRADDAC(a[14], a[22]); SQRADDAC(a[15], a[21]); SQRADDAC(a[16], a[20]); SQRADDAC(a[17], a[19]); SQRADDDB; SQRADD(a[18], a[18]); + COMBA_STORE(b[36]); + + /* output 37 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[31]); SQRADDAC(a[7], a[30]); SQRADDAC(a[8], a[29]); SQRADDAC(a[9], a[28]); SQRADDAC(a[10], a[27]); SQRADDAC(a[11], a[26]); SQRADDAC(a[12], a[25]); SQRADDAC(a[13], a[24]); SQRADDAC(a[14], a[23]); SQRADDAC(a[15], a[22]); SQRADDAC(a[16], a[21]); SQRADDAC(a[17], a[20]); SQRADDAC(a[18], a[19]); SQRADDDB; + COMBA_STORE(b[37]); + + /* output 38 */ + CARRY_FORWARD; + SQRADDSC(a[7], a[31]); SQRADDAC(a[8], a[30]); SQRADDAC(a[9], a[29]); SQRADDAC(a[10], a[28]); SQRADDAC(a[11], a[27]); SQRADDAC(a[12], a[26]); SQRADDAC(a[13], a[25]); SQRADDAC(a[14], a[24]); SQRADDAC(a[15], a[23]); SQRADDAC(a[16], a[22]); SQRADDAC(a[17], a[21]); SQRADDAC(a[18], a[20]); SQRADDDB; SQRADD(a[19], a[19]); + COMBA_STORE(b[38]); + + /* output 39 */ + CARRY_FORWARD; + SQRADDSC(a[8], a[31]); SQRADDAC(a[9], a[30]); SQRADDAC(a[10], a[29]); SQRADDAC(a[11], a[28]); SQRADDAC(a[12], a[27]); SQRADDAC(a[13], a[26]); SQRADDAC(a[14], a[25]); SQRADDAC(a[15], a[24]); SQRADDAC(a[16], a[23]); SQRADDAC(a[17], a[22]); SQRADDAC(a[18], a[21]); SQRADDAC(a[19], a[20]); SQRADDDB; + COMBA_STORE(b[39]); + + /* output 40 */ + CARRY_FORWARD; + SQRADDSC(a[9], a[31]); SQRADDAC(a[10], a[30]); SQRADDAC(a[11], a[29]); SQRADDAC(a[12], a[28]); SQRADDAC(a[13], a[27]); SQRADDAC(a[14], a[26]); SQRADDAC(a[15], a[25]); SQRADDAC(a[16], a[24]); SQRADDAC(a[17], a[23]); SQRADDAC(a[18], a[22]); SQRADDAC(a[19], a[21]); SQRADDDB; SQRADD(a[20], a[20]); + COMBA_STORE(b[40]); + + /* output 41 */ + CARRY_FORWARD; + SQRADDSC(a[10], a[31]); SQRADDAC(a[11], a[30]); SQRADDAC(a[12], a[29]); SQRADDAC(a[13], a[28]); SQRADDAC(a[14], a[27]); SQRADDAC(a[15], a[26]); SQRADDAC(a[16], a[25]); SQRADDAC(a[17], a[24]); SQRADDAC(a[18], a[23]); SQRADDAC(a[19], a[22]); SQRADDAC(a[20], a[21]); SQRADDDB; + COMBA_STORE(b[41]); + + /* output 42 */ + CARRY_FORWARD; + SQRADDSC(a[11], a[31]); SQRADDAC(a[12], a[30]); SQRADDAC(a[13], a[29]); SQRADDAC(a[14], a[28]); SQRADDAC(a[15], a[27]); SQRADDAC(a[16], a[26]); SQRADDAC(a[17], a[25]); SQRADDAC(a[18], a[24]); SQRADDAC(a[19], a[23]); SQRADDAC(a[20], a[22]); SQRADDDB; SQRADD(a[21], a[21]); + COMBA_STORE(b[42]); + + /* output 43 */ + CARRY_FORWARD; + SQRADDSC(a[12], a[31]); SQRADDAC(a[13], a[30]); SQRADDAC(a[14], a[29]); SQRADDAC(a[15], a[28]); SQRADDAC(a[16], a[27]); SQRADDAC(a[17], a[26]); SQRADDAC(a[18], a[25]); SQRADDAC(a[19], a[24]); SQRADDAC(a[20], a[23]); SQRADDAC(a[21], a[22]); SQRADDDB; + COMBA_STORE(b[43]); + + /* output 44 */ + CARRY_FORWARD; + SQRADDSC(a[13], a[31]); SQRADDAC(a[14], a[30]); SQRADDAC(a[15], a[29]); SQRADDAC(a[16], a[28]); SQRADDAC(a[17], a[27]); SQRADDAC(a[18], a[26]); SQRADDAC(a[19], a[25]); SQRADDAC(a[20], a[24]); SQRADDAC(a[21], a[23]); SQRADDDB; SQRADD(a[22], a[22]); + COMBA_STORE(b[44]); + + /* output 45 */ + CARRY_FORWARD; + SQRADDSC(a[14], a[31]); SQRADDAC(a[15], a[30]); SQRADDAC(a[16], a[29]); SQRADDAC(a[17], a[28]); SQRADDAC(a[18], a[27]); SQRADDAC(a[19], a[26]); SQRADDAC(a[20], a[25]); SQRADDAC(a[21], a[24]); SQRADDAC(a[22], a[23]); SQRADDDB; + COMBA_STORE(b[45]); + + /* output 46 */ + CARRY_FORWARD; + SQRADDSC(a[15], a[31]); SQRADDAC(a[16], a[30]); SQRADDAC(a[17], a[29]); SQRADDAC(a[18], a[28]); SQRADDAC(a[19], a[27]); SQRADDAC(a[20], a[26]); SQRADDAC(a[21], a[25]); SQRADDAC(a[22], a[24]); SQRADDDB; SQRADD(a[23], a[23]); + COMBA_STORE(b[46]); + + /* output 47 */ + CARRY_FORWARD; + SQRADDSC(a[16], a[31]); SQRADDAC(a[17], a[30]); SQRADDAC(a[18], a[29]); SQRADDAC(a[19], a[28]); SQRADDAC(a[20], a[27]); SQRADDAC(a[21], a[26]); SQRADDAC(a[22], a[25]); SQRADDAC(a[23], a[24]); SQRADDDB; + COMBA_STORE(b[47]); + + /* output 48 */ + CARRY_FORWARD; + SQRADDSC(a[17], a[31]); SQRADDAC(a[18], a[30]); SQRADDAC(a[19], a[29]); SQRADDAC(a[20], a[28]); SQRADDAC(a[21], a[27]); SQRADDAC(a[22], a[26]); SQRADDAC(a[23], a[25]); SQRADDDB; SQRADD(a[24], a[24]); + COMBA_STORE(b[48]); + + /* output 49 */ + CARRY_FORWARD; + SQRADDSC(a[18], a[31]); SQRADDAC(a[19], a[30]); SQRADDAC(a[20], a[29]); SQRADDAC(a[21], a[28]); SQRADDAC(a[22], a[27]); SQRADDAC(a[23], a[26]); SQRADDAC(a[24], a[25]); SQRADDDB; + COMBA_STORE(b[49]); + + /* output 50 */ + CARRY_FORWARD; + SQRADDSC(a[19], a[31]); SQRADDAC(a[20], a[30]); SQRADDAC(a[21], a[29]); SQRADDAC(a[22], a[28]); SQRADDAC(a[23], a[27]); SQRADDAC(a[24], a[26]); SQRADDDB; SQRADD(a[25], a[25]); + COMBA_STORE(b[50]); + + /* output 51 */ + CARRY_FORWARD; + SQRADDSC(a[20], a[31]); SQRADDAC(a[21], a[30]); SQRADDAC(a[22], a[29]); SQRADDAC(a[23], a[28]); SQRADDAC(a[24], a[27]); SQRADDAC(a[25], a[26]); SQRADDDB; + COMBA_STORE(b[51]); + + /* output 52 */ + CARRY_FORWARD; + SQRADDSC(a[21], a[31]); SQRADDAC(a[22], a[30]); SQRADDAC(a[23], a[29]); SQRADDAC(a[24], a[28]); SQRADDAC(a[25], a[27]); SQRADDDB; SQRADD(a[26], a[26]); + COMBA_STORE(b[52]); + + /* output 53 */ + CARRY_FORWARD; + SQRADDSC(a[22], a[31]); SQRADDAC(a[23], a[30]); SQRADDAC(a[24], a[29]); SQRADDAC(a[25], a[28]); SQRADDAC(a[26], a[27]); SQRADDDB; + COMBA_STORE(b[53]); + + /* output 54 */ + CARRY_FORWARD; + SQRADDSC(a[23], a[31]); SQRADDAC(a[24], a[30]); SQRADDAC(a[25], a[29]); SQRADDAC(a[26], a[28]); SQRADDDB; SQRADD(a[27], a[27]); + COMBA_STORE(b[54]); + + /* output 55 */ + CARRY_FORWARD; + SQRADDSC(a[24], a[31]); SQRADDAC(a[25], a[30]); SQRADDAC(a[26], a[29]); SQRADDAC(a[27], a[28]); SQRADDDB; + COMBA_STORE(b[55]); + + /* output 56 */ + CARRY_FORWARD; + SQRADDSC(a[25], a[31]); SQRADDAC(a[26], a[30]); SQRADDAC(a[27], a[29]); SQRADDDB; SQRADD(a[28], a[28]); + COMBA_STORE(b[56]); + + /* output 57 */ + CARRY_FORWARD; + SQRADDSC(a[26], a[31]); SQRADDAC(a[27], a[30]); SQRADDAC(a[28], a[29]); SQRADDDB; + COMBA_STORE(b[57]); + + /* output 58 */ + CARRY_FORWARD; + SQRADD2(a[27], a[31]); SQRADD2(a[28], a[30]); SQRADD(a[29], a[29]); + COMBA_STORE(b[58]); + + /* output 59 */ + CARRY_FORWARD; + SQRADD2(a[28], a[31]); SQRADD2(a[29], a[30]); + COMBA_STORE(b[59]); + + /* output 60 */ + CARRY_FORWARD; + SQRADD2(a[29], a[31]); SQRADD(a[30], a[30]); + COMBA_STORE(b[60]); + + /* output 61 */ + CARRY_FORWARD; + SQRADD2(a[30], a[31]); + COMBA_STORE(b[61]); + + /* output 62 */ + CARRY_FORWARD; + SQRADD(a[31], a[31]); + COMBA_STORE(b[62]); + COMBA_STORE2(b[63]); + COMBA_FINI; + + B->used = 64; + B->sign = PSTM_ZPOS; + memcpy(B->dp, b, 64 * sizeof(pstm_digit)); + pstm_clamp(B); + return PSTM_OKAY; +} +#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */ + +/******************************************************************************/ +/** + B = A**2. + @param[in] pool Memory pool + @param[in] A Base + @param[out] B Result + @param[in,out] paD Temporary storage + @param[in] paDlen Number of items pointed to by paD +*/ +int32_t pstm_sqr_comba(psPool_t *pool, const pstm_int *A, pstm_int *B, + pstm_digit *paD, uint16_t paDlen) +{ +#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS + if (A->used == 16) { + return pstm_sqr_comba16(A, B); + } else { +#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS + if (A->used == 32) { + return pstm_sqr_comba32(A, B); + } +#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */ + return pstm_sqr_comba_gen(pool, A, B, paD, paDlen); + } +#else +#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS + if (A->used == 32) { + return pstm_sqr_comba32(A, B); + } +#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */ + return pstm_sqr_comba_gen(pool, A, B, paD, paDlen); +#endif +} + +#endif /* defined(USE_MATRIX_RSA) || defined(USE_MATRIX_ECC) */ + +/******************************************************************************/ + diff --git a/crypto/prng/prng.c b/crypto/prng/prng.c new file mode 100644 index 0000000..8aba720 --- /dev/null +++ b/crypto/prng/prng.c @@ -0,0 +1,191 @@ +/** + * @file prng.c + * @version $Format:%h%d$ + * + * Psuedo random number generation. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_MATRIX_PRNG + +#ifdef USE_MULTITHREADING +static psMutex_t prngLock; +#endif + +static psRandom_t gMatrixPrng; +static short gPrngInit = 0; + +/******************************************************************************/ +/* One-time global prng lock creation and prng context */ +void psOpenPrng(void) +{ +#ifdef USE_MULTITHREADING + psCreateMutex(&prngLock); +#endif + /* NOTE: if a PRNG is enabled, the low level psGetEntropy call can't + have a useful userPtr context becuase there will be no session + context at this early stage */ + psInitPrng(&gMatrixPrng, NULL); + gPrngInit = 1; + return; +} + +/******************************************************************************/ +/* One-time global prng lock destruction */ +void psClosePrng(void) +{ +#ifdef USE_MULTITHREADING + psDestroyMutex(&prngLock); +#endif + return; +} + +/******************************************************************************/ +/* + Main PRNG retrieval API for Matrix based apps to lock all PRNG and entropy + fetches +*/ +int32_t matrixCryptoGetPrngData(unsigned char *bytes, uint16_t size, void *userPtr) +{ + int32_t rc; + + if (gPrngInit == 0) { + return PS_FAILURE; + } +#ifdef USE_MULTITHREADING + psLockMutex(&prngLock); +#endif /* USE_MULTITHREADING */ + rc = psGetPrng(&gMatrixPrng, bytes, size, userPtr); +#ifdef USE_MULTITHREADING + psUnlockMutex(&prngLock); +#endif /* USE_MULTITHREADING */ + return rc; +} + +/******************************************************************************/ +/* + Priority order of PRNG algorithms and then default GetEntropy if none. + Does an initial entropy source and reseeding +*/ +int32_t psInitPrng(psRandom_t *ctx, void *userPtr) +{ +#if defined(USE_FORTUNA) || defined(USE_YARROW) + unsigned char entropyBytes[RANDOM_ENTROPY_BYTES]; + int32 rc; +#endif + + ctx->bytecount = 0; + + +#if defined(USE_FORTUNA) || defined(USE_YARROW) + if ((rc = psGetEntropy(entropyBytes, RANDOM_ENTROPY_BYTES, userPtr)) < 0) { + return rc; + } +#endif + +#ifdef USE_YARROW + if ((rc = psYarrowStart(&ctx->yarrow)) < 0) { + return rc; + } + if ((rc = psYarrowAddEntropy(entropyBytes, RANDOM_ENTROPY_BYTES, + &ctx->yarrow)) < 0) { + return rc; + } + if ((rc = psYarrowReseed(&ctx->yarrow)) < 0) { + return rc; + } +#endif + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Performs the read +*/ +static int32_t readRandomData(psRandom_t *ctx, unsigned char *bytes, uint16_t size, + void *userPtr) +{ +#if defined(USE_FORTUNA) || defined(USE_YARROW) + unsigned char entropyBytes[RANDOM_ENTROPY_BYTES]; + int32 rc; +#endif +/* + Return random data. The defines above control how often to add + entropy and reseed the key. +*/ + ctx->bytecount += size; + + + +#ifdef USE_YARROW + if (ctx->bytecount >= RANDOM_BYTES_BEFORE_ENTROPY) { + ctx->bytecount = 0; + if ((rc = psGetEntropy(entropyBytes, RANDOM_ENTROPY_BYTES, userPtr)) + < 0) { + return rc; + } + if ((rc = psYarrowAddEntropy(entropyBytes, RANDOM_ENTROPY_BYTES, + &ctx->yarrow)) < 0) { + return rc; + } + if ((rc = psYarrowReseed(&ctx->yarrow)) < 0) { + return rc; + } + } + return psYarrowRead(bytes, size, &ctx->yarrow); +#endif +/* + If no PRNG algorithms defined, default to the low level GetEntropy function + for all the randomness +*/ + return psGetEntropy(bytes, size, userPtr); +} + +/******************************************************************************/ +/* + Allow NULL context if caller is just doing a single read +*/ +int32_t psGetPrng(psRandom_t *ctx, unsigned char *bytes, uint16_t size, + void *userPtr) +{ + psRandom_t lctx; + + if (ctx == NULL) { + psInitPrng(&lctx, userPtr); + return readRandomData(&lctx, bytes, size, userPtr); + } + return readRandomData(ctx, bytes, size, userPtr); +} + +#endif /* USE_MATRIX_PRNG */ + +/******************************************************************************/ + diff --git a/crypto/prng/prng.h b/crypto/prng/prng.h new file mode 100644 index 0000000..bb6b2b6 --- /dev/null +++ b/crypto/prng/prng.h @@ -0,0 +1,80 @@ +/** + * @file prng.h + * @version $Format:%h%d$ + * + * Pseudorandom Number Generator header. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_PS_PRNG +#define _h_PS_PRNG + + +#ifdef USE_YARROW +/* + AES SHA-1 implementation +*/ +#define CTR_COUNTER_LITTLE_ENDIAN 0x0000 +#define CTR_COUNTER_BIG_ENDIAN 0x1000 + +#define AESBLOCKSIZE 16 + +typedef struct { +#ifdef USE_SHA256 + unsigned char pool[SHA256_HASH_SIZE]; /* hash of entropy */ +#else + unsigned char pool[SHA1_HASH_SIZE]; /* hash of entropy */ +#endif + int32 mode; /** The mode (endianess) of the CTR, 0==little, 1==big */ + int32 ctrlen; /** counter width */ + int32 padlen; /** The padding offset */ + int32 blocklen; /** The AESBLOCKSIZE */ + unsigned char ctr[AESBLOCKSIZE]; /** The counter being encrypted */ + unsigned char pad[AESBLOCKSIZE]; /** The actual prn */ + psAesKey_t key; /** The scheduled key */ +} psYarrow_t; +#endif /* USE_YARROW */ + +/* + prng.c wrapper +*/ +#define RANDOM_BYTES_BEFORE_ENTROPY 1024 /* add entropy each time # bytes read */ +#define RANDOM_ENTROPY_BYTES 8 /* Bytes of entropy from source */ + +typedef struct { +#ifdef USE_YARROW + psYarrow_t yarrow; +#endif + uint32 bytecount; /* number of bytes read from this context */ +} psRandom_t; + + +/******************************************************************************/ +#endif /* _h_PS_PRNG */ + diff --git a/crypto/prng/yarrow.c b/crypto/prng/yarrow.c new file mode 100644 index 0000000..d8ec44f --- /dev/null +++ b/crypto/prng/yarrow.c @@ -0,0 +1,295 @@ +/** + * @file yarrow.c + * @version $Format:%h%d$ + * + * Yarrow PRNG implementation. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_YARROW +/******************************************************************************/ +/* + A basic yarrow implementation hardcoded to AES and SHA. Only one + pool is used. + + The sequence of calls to start getting PRN is to call psYarrowStart, + psYarrowAddEntropy, psYarrowReseed, and finally psYarrowRead. Throughout + the life of the application, psYarrowAddEntropy can be called when random + data is read from the platform. The psYarrowReseed function must be + called to incorporate that entropy into the new key. + + Warning: no mutex lock embedded in these calls +*/ + +/** + Doesn't do much, but sets the blocklen to AES to make it necessary to call +*/ +int32 psYarrowStart(psYarrow_t *ctx) +{ + if (ctx == NULL) { + return PS_ARG_FAIL; + } + /* zero the memory used */ + memset(ctx->pool, 0, sizeof(ctx->pool)); + ctx->blocklen = AESBLOCKSIZE; + + return PS_SUCCESS; +} + +/** + Add entropy to the PRNG state + @param in The data to add + @param inlen Length of the data to add + @param prng PRNG state to update +*/ +int32 psYarrowAddEntropy(unsigned char *in, uint32 inlen, psYarrow_t *prng) +{ + psDigestContext_t md; + int32 err; + + if (in == NULL || prng == NULL) { + return PS_ARG_FAIL; + } + +#ifdef USE_SHA256 + /* start the hash */ + psSha256Init(&md); + + /* hash the current pool */ + psSha256Update(&md, prng->pool, SHA256_HASH_SIZE); + + /* add the new entropy */ + psSha256Update(&md, in, inlen); + + /* store result */ + if ((err = psSha256Final(&md, prng->pool)) != SHA256_HASH_SIZE) { + return err; + } +#else + /* start the hash */ + psSha1Init(&md); + + /* hash the current pool */ + psSha1Update(&md, prng->pool, SHA1_HASH_SIZE); + + /* add the new entropy */ + psSha1Update(&md, in, inlen); + + /* store result */ + if ((err = psSha1Final(&md, prng->pool)) != SHA1_HASH_SIZE) { + return err; + } +#endif + return PS_SUCCESS; +} + + +/** + Make the PRNG ready to read from and to reseed when desired + @param prng The PRNG to seed +*/ +int32 psYarrowReseed(psYarrow_t *ctx) +{ + const unsigned char *IV; + int32 keylen, ctr_mode, x, err; + + IV = ctx->pool; + keylen = AESBLOCKSIZE; /* Can only use 16 bytes for the AES key */ + ctr_mode = CTR_COUNTER_LITTLE_ENDIAN; /* little endian counter */ + + /* ctrlen == counter width */ + ctx->ctrlen = (ctr_mode & 255) ? (ctr_mode & 255) : AESBLOCKSIZE; + if (ctx->ctrlen > AESBLOCKSIZE) { + return PS_ARG_FAIL; + } + + if ((ctr_mode & 0x1000) == CTR_COUNTER_BIG_ENDIAN) { + ctx->ctrlen = AESBLOCKSIZE - ctx->ctrlen; + } + + /* setup cipher */ + if ((err = psAesInitBlockKey(ctx->pool, keylen, &ctx->key)) != PS_SUCCESS) { + return err; + } + + /* copy ctr */ + ctx->padlen = 0; + ctx->mode = ctr_mode & 0x1000; + for (x = 0; x < ctx->blocklen; x++) { + ctx->ctr[x] = IV[x]; + } + + /* increment the IV */ + if (ctx->mode == CTR_COUNTER_LITTLE_ENDIAN) { + /* little-endian */ + for (x = 0; x < ctx->ctrlen; x++) { + ctx->ctr[x] = (ctx->ctr[x] + (unsigned char)1) & (unsigned char)255; + if (ctx->ctr[x] != (unsigned char)0) { + break; + } + } + } else { + /* big-endian */ + for (x = ctx->blocklen-1; x >= ctx->ctrlen; x--) { + ctx->ctr[x] = (ctx->ctr[x] + (unsigned char)1) & (unsigned char)255; + if (ctx->ctr[x] != (unsigned char)0) { + break; + } + } + } + + psAesEncryptBlock(ctx->ctr, ctx->pad, &ctx->key); + return PS_SUCCESS; +} + + +/** + Read from the PRNG + @param out Destination + @param outlen Length of output + @param ctx The active PRNG to read from + @return Number of octets read +*/ +uint32 psYarrowRead(unsigned char *out, uint32 outlen, psYarrow_t *ctx) +{ + unsigned char *pt, *ct; + int32 x; + uint32 len; + + /* put out in predictable state first */ + memset(out, 0x0, outlen); + + len = outlen; + pt = ct = out; + + /* is blocklen/padlen valid? */ + if (ctx->blocklen < 1 || ctx->blocklen > (int32)sizeof(ctx->ctr) || + ctx->padlen < 0 || ctx->padlen > (int32)sizeof(ctx->pad)) { + return 0; + } + + while (outlen) { + /* is the pad empty? */ + if (ctx->padlen == ctx->blocklen) { + /* increment counter */ + if (ctx->mode == CTR_COUNTER_LITTLE_ENDIAN) { + /* little-endian */ + for (x = 0; x < ctx->ctrlen; x++) { + ctx->ctr[x] = + (ctx->ctr[x] + (unsigned char)1) & (unsigned char)255; + if (ctx->ctr[x] != (unsigned char)0) { + break; + } + } + } else { + /* big-endian */ + for (x = ctx->blocklen-1; x >= ctx->ctrlen; x--) { + ctx->ctr[x] = + (ctx->ctr[x] + (unsigned char)1) & (unsigned char)255; + if (ctx->ctr[x] != (unsigned char)0) { + break; + } + } + } + + /* encrypt new pad and reset */ + psAesEncryptBlock(ctx->ctr, ctx->pad, &ctx->key); + ctx->padlen = 0; + } + *ct++ = *pt++ ^ ctx->pad[ctx->padlen++]; + --outlen; + } + return len; +} + + +/** + Terminate the PRNG +*/ +int32 psYarrowDone(psYarrow_t *ctx) +{ + return PS_SUCCESS; +} + + +/** + Export the PRNG state + @param out [out] Destination + @param outlen [in/out] Max size and resulting size of the state + @param prng The PRNG to export + @return CRYPT_OK if successful +*/ +int32 psYarrowExport(unsigned char *out, uint32 *outlen, psYarrow_t *ctx) +{ + /* we'll write 64 bytes for s&g's */ + if (*outlen < 64) { + *outlen = 64; + return PS_LIMIT_FAIL; + } + + if (psYarrowRead(out, 64, ctx) != 64) { + *outlen = 0; + return PS_FAILURE; + } + *outlen = 64; + + return PS_SUCCESS; +} + +/** + Import a PRNG state + @param in The PRNG state + @param inlen Size of the state + @param prng The PRNG to import + @return CRYPT_OK if successful +*/ +int32 psYarrowImport(unsigned char *in, uint32 inlen, psYarrow_t *ctx) +{ + int32 err; + + if (inlen != 64) { + return PS_ARG_FAIL; + } + + if ((err = psYarrowStart(ctx)) != PS_SUCCESS) { + return err; + } + if ((err = psYarrowAddEntropy(in, 64, ctx)) != PS_SUCCESS) { + return err; + } + if ((err = psYarrowReseed(ctx)) != PS_SUCCESS) { + return err; + } + return err; +} + + +#endif /* USE_YARROW */ diff --git a/crypto/pubkey/dh.c b/crypto/pubkey/dh.c new file mode 100644 index 0000000..e1cc9c7 --- /dev/null +++ b/crypto/pubkey/dh.c @@ -0,0 +1,447 @@ +/** + * @file dh.c + * @version $Format:%h%d$ + * + * Diffie-Hellman. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_MATRIX_DH + +/******************************************************************************/ + +void psDhClearKey(psDhKey_t *key) +{ + psAssert(key); + pstm_clear(&key->priv); + pstm_clear(&key->pub); + key->type = 0; +} + +uint16_t psDhSize(const psDhKey_t *key) +{ + return key->size; +} + +/******************************************************************************/ +/** + Parse ASN.1 encoded DH parameters. + + DHParameter ::= SEQUENCE { + prime INTEGER, -- p + base INTEGER, -- g + privateValueLength INTEGER OPTIONAL + } + @note privateValueLength field unsupported + + @param pool Memory pool + @param[in] dhBin Pointer to buffer containing ASN.1 format parameters + @param[in] dhBinLen Length in bytes of 'dhBin' + @param[in,out] params Allocated parameter structure to receive parsed + params. + @return < on error. + +*/ +int32_t pkcs3ParseDhParamBin(psPool_t *pool, const unsigned char *dhBin, + uint16_t dhBinLen, psDhParams_t *params) +{ + const unsigned char *c, *end; + uint16_t baseLen; + + if (!params || !dhBin) { + return PS_ARG_FAIL; + } + end = dhBin + dhBinLen; + c = dhBin; + + if (getAsnSequence(&c, (uint16_t)(end - c), &baseLen) < 0) { + return PS_PARSE_FAIL; + } + /* Parse the DH prime value and validate against minimum length */ + if (pstm_read_asn(pool, &c, (uint16_t)(end - c), ¶ms->p) < 0) { + goto L_ERR; + } + params->size = pstm_unsigned_bin_size(¶ms->p); + if (params->size < (MIN_DH_BITS / 8)) { + psTraceIntCrypto("Unsupported DH prime size %hu\n", params->size); + goto L_ERR; + } + /* The DH base parameter is typically small (usually value 2 or 5), + so we don't validate against a minimum length */ + if (pstm_read_asn(pool, &c, (uint16_t)(end - c), ¶ms->g) < 0) { + goto L_ERR; + } + if (end != c) { + psTraceCrypto("Unsupported DHParameter Format\n"); + goto L_ERR; + } + params->pool = pool; + return PS_SUCCESS; + +L_ERR: + pstm_clear(¶ms->g); + pstm_clear(¶ms->p); + params->pool = NULL; + params->size = 0; + return PS_PARSE_FAIL; +} + +/** + Clear DH params. + @param[out] params Pointer to allocated DH params to clear. + @note Caller is responsible for freeing memory associated with 'params', + if appropriate. +*/ +void pkcs3ClearDhParams(psDhParams_t *params) +{ + if (params == NULL) { + return; + } + pstm_clear(¶ms->g); + pstm_clear(¶ms->p); + params->size = 0; + params->pool = NULL; +} + +/** + Allocate and populate buffers for DH prime and base values. + + @param pool Memory pool + @param[in] params DH params to export + @param[out] pp On success, will point to an allocated memory buffer + containing the DH params prime value. + @param[out] pLen Pointer to value to receive length of 'pp' in bytes + @param[out] pg On success, will point to an allocated memory buffer + containing the DH params generator/base value. + @param[out] gLen Pointer to value to receive length of 'pg' in bytes + @return < 0 on failure + + @post On success, the buffers pointed to by 'pp' and 'pg' are allocated + by this API and must be freed by the caller. +*/ +int32_t psDhExportParameters(psPool_t *pool, + const psDhParams_t *params, + unsigned char **pp, uint16_t *pLen, + unsigned char **pg, uint16_t *gLen) +{ + uint16_t pl, gl; + unsigned char *p, *g; + + pl = pstm_unsigned_bin_size(¶ms->p); + gl = pstm_unsigned_bin_size(¶ms->g); + if ((p = psMalloc(pool, pl)) == NULL) { + psError("Memory allocation error in psDhExportParameters\n"); + return PS_MEM_FAIL; + } + if ((g = psMalloc(pool, gl)) == NULL) { + psError("Memory allocation error in psDhExportParameters\n"); + psFree(p, pool); + return PS_MEM_FAIL; + } + if (pstm_to_unsigned_bin(pool, ¶ms->p, p) < 0 || + pstm_to_unsigned_bin(pool, ¶ms->g, g) < 0) { + + psFree(p, pool); + psFree(g, pool); + return PS_FAIL; + } + *pLen = pl; + *gLen = gl; + *pp = p; + *pg = g; + return PS_SUCCESS; +} + +/******************************************************************************/ +/** + Import a public DH key in raw (wire) format to a psDhKey_t struct. + + @param pool Memory pool + @param[in] in Pointer to buffer containing raw public DH key + @param[in] inlen Length in bytes of 'in' + @param[out] key Pointer to allocated key to be initialized with raw + DH value from 'in'. + @return < on failure +*/ +int32_t psDhImportPubKey(psPool_t *pool, + const unsigned char *in, uint16_t inlen, + psDhKey_t *key) +{ + int32_t rc; + + memset(&key->priv, 0x0, sizeof(psDhKey_t)); + if ((rc = pstm_init_for_read_unsigned_bin(pool, &key->pub, inlen)) < 0) { + return rc; + } + if ((rc = pstm_read_unsigned_bin(&key->pub, in, inlen)) < 0) { + pstm_clear(&key->pub); + return rc; + } + key->size = inlen; + key->type = PS_PUBKEY; + return PS_SUCCESS; +} + +/** + Export a public psDhKey_t struct to a raw binary format. + + @param pool Memory pool + @param[in] key Pointer to DH key to export + @param[out] out Pointer to buffer to write raw public DH key + @param[in,out] outlen On input, the number of bytes available in 'out', + on successful return, the number of bytes written to 'out'. + @return < on failure +*/ +int32_t psDhExportPubKey(psPool_t *pool, const psDhKey_t *key, + unsigned char *out, uint16_t *outlen) +{ + unsigned char *c; + int16_t pad; + int32_t rc; + + if (*outlen < key->size) { + return PS_ARG_FAIL; + } + c = out; + pad = key->size - pstm_unsigned_bin_size(&key->pub); + if (pad > 0) { + memset(c, 0x0, pad); + c += pad; + } else if (pad < 0) { + return PS_FAIL; + } + if ((rc = pstm_to_unsigned_bin(pool, &key->pub, c)) < 0) { + return rc; + } + *outlen = key->size; + return PS_SUCCESS; +} + + +/******************************************************************************/ +/** + Generate a DH key given the parameters. + +*/ +int32_t psDhGenKey(psPool_t *pool, uint16_t keysize, + const unsigned char *pBin, uint16_t pLen, + const unsigned char *gBin, uint16_t gLen, + psDhKey_t *key, void *usrData) +{ + int32_t rc; + pstm_int p, g; + + /* Convert the p and g into ints and make keys */ + if ((rc = pstm_init_for_read_unsigned_bin(pool, &p, pLen)) != PS_SUCCESS) { + return rc; + } + if ((rc = pstm_init_for_read_unsigned_bin(pool, &g, gLen)) != PS_SUCCESS) { + pstm_clear(&p); + return rc; + } + + if ((rc = pstm_read_unsigned_bin(&p, pBin, pLen)) != PS_SUCCESS) { + goto error; + } + if ((rc = pstm_read_unsigned_bin(&g, gBin, gLen)) != PS_SUCCESS) { + goto error; + } + + rc = psDhGenKeyInts(pool, keysize, &p, &g, key, usrData); + +error: + pstm_clear(&p); + pstm_clear(&g); + return rc; +} + +/******************************************************************************/ +/** + Does the actual key generation given p and g. + +*/ +#define DH_KEYGEN_SANITY 256 +int32_t psDhGenKeyInts(psPool_t *pool, uint16_t keysize, + const pstm_int *p, const pstm_int *g, + psDhKey_t *key, void *usrData) +{ + unsigned char *buf = NULL; + int32_t err, i; + uint16_t privsize; + + if (key == NULL) { + return PS_ARG_FAIL; + } + privsize = keysize; +#ifndef USE_LARGE_DH_PRIVATE_KEYS +/* + The mapping between DH prime field size and key size follows + NIST SP 800-57 Part 1 for the common sizes, and for unusual + sizes the key size is intentionally rounded up. + The private key size must never be larger than prime size. +*/ + if (keysize >= 160 / 8 && keysize <= 1024 / 8) { + privsize = 160 / 8; + } else if (keysize > 1024 / 8 && keysize <= 2048 / 8) { + privsize = 224 / 8; + } else if (keysize > 2048 / 8 && keysize <= 3072 / 8) { + privsize = 256 / 8; + } else if (keysize > 3072 / 8 && keysize <= 7680 / 8) { + privsize = 384 / 8; + } else if (keysize > 7680 / 8 && keysize <= 15360 / 8) { + privsize = 256 / 8; + } +#endif /* USE_LARGE_DH_PRIVATE_KEYS */ + + key->size = keysize; + + buf = psMalloc(pool, privsize); + if (buf == NULL) { + psError("malloc error in psDhMakeKey\n"); + return PS_MEM_FAIL; + } + if ((err = pstm_init_for_read_unsigned_bin(pool, &key->priv, privsize)) + != PS_SUCCESS) { + goto error; + } + + for (i = 0; i < DH_KEYGEN_SANITY; i++) { + if ((err = matrixCryptoGetPrngData(buf, privsize, usrData)) < 0) { + goto error; + } + /* Load the random bytes as the private key */ + if ((err = pstm_read_unsigned_bin(&key->priv, buf, privsize)) + != PS_SUCCESS) { + goto error; + } + /* Test (1 < key < p), usually succeeds right away */ + if (pstm_cmp_d(&key->priv, 1) == PSTM_GT && + pstm_cmp(&key->priv, p) == PSTM_LT) { + break; /* found one */ + } + } + if (i == DH_KEYGEN_SANITY) { + psTraceCrypto("DH private key could not be generated\n"); + err = PS_PLATFORM_FAIL; + goto error; + } + /* Have the private key, now calculate the public part */ + if ((err = pstm_init_size(pool, &key->pub, (p->used * 2) + 1)) + != PS_SUCCESS) { + pstm_clear(&key->priv); + goto error; + } + if ((err = pstm_exptmod(pool, g, &key->priv, p, &key->pub)) != + PS_SUCCESS) { + goto error; + } + key->type = PS_PRIVKEY; + err = PS_SUCCESS; + goto done; +error: + pstm_clear(&key->priv); + pstm_clear(&key->pub); +done: + if (buf) { + memzero_s(buf, privsize); + psFree(buf, pool); + } + return err; +} + +/******************************************************************************/ +/** + Create the DH premaster secret. + @param[in] privKey The private DH key in the pair + @param[in] pubKey The public DH key in the pair + @param[in] pBin The DH Param Prime value + @param[in] pBinLen The length in bytes if 'pBin' + @param[out] out Buffer to write the shared secret + @param[in,out] outlen On input, the available space in 'out', on + successful return, the number of bytes written to 'out'. +*/ +int32_t psDhGenSharedSecret(psPool_t *pool, + const psDhKey_t *privKey, const psDhKey_t *pubKey, + const unsigned char *pBin, uint16_t pBinLen, + unsigned char *out, uint16_t *outlen, void *usrData) +{ + pstm_int tmp, p; + uint16_t x; + int32_t err; + + /* Verify the privKey is a private type. pubKey param can be either */ + if (privKey->type != PS_PRIVKEY) { + psTraceCrypto("Bad private key format for DH premaster\n"); + return PS_ARG_FAIL; + } + + + /* compute y^x mod p */ + if ((err = pstm_init(pool, &tmp)) != PS_SUCCESS) { + return err; + } + if ((err = pstm_init_for_read_unsigned_bin(pool, &p, pBinLen)) != PS_SUCCESS) { + return err; + } + + if ((err = pstm_read_unsigned_bin(&p, pBin, pBinLen)) != PS_SUCCESS) { + goto error; + } + if ((err = pstm_exptmod(pool, &pubKey->pub, &privKey->priv, &p, + &tmp)) != PS_SUCCESS) { + goto error; + } + + /* enough space for output? */ + x = (unsigned long)pstm_unsigned_bin_size(&tmp); + if (*outlen < x) { + psTraceCrypto("Overflow in DH premaster generation\n"); + err = PS_LIMIT_FAIL; + goto error; + } + + /* It is possible to have a key size smaller than we expect */ + *outlen = x; + if ((err = pstm_to_unsigned_bin(pool, &tmp, out)) < 0) { + goto error; + } + + err = PS_SUCCESS; +error: + pstm_clear(&p); + pstm_clear(&tmp); + return err; +} + +#endif /* USE_MATRIX_DH */ + +/******************************************************************************/ + diff --git a/crypto/pubkey/ecc.c b/crypto/pubkey/ecc.c new file mode 100644 index 0000000..5371562 --- /dev/null +++ b/crypto/pubkey/ecc.c @@ -0,0 +1,2695 @@ +/** + * @file ecc.c + * @version $Format:%h%d$ + * + * Implements ECC over Z/pZ for curve y^2 = x^3 + ax + b. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_MATRIX_ECC + +/******************************************************************************/ + +#define ECC_BUF_SIZE 256 + +static psEccPoint_t *eccNewPoint(psPool_t *pool, short size); +static void eccFreePoint(psEccPoint_t *p); + +static int32_t eccMulmod(psPool_t *pool, const pstm_int *k, const psEccPoint_t *G, + psEccPoint_t *R, pstm_int *modulus, uint8_t map, pstm_int *tmp_int); +static int32_t eccProjectiveAddPoint(psPool_t *pool, const psEccPoint_t *P, + const psEccPoint_t *Q, psEccPoint_t *R, const pstm_int *modulus, + const pstm_digit *mp, pstm_int *tmp_int); +static int32_t eccProjectiveDblPoint(psPool_t *pool, const psEccPoint_t *P, + psEccPoint_t *R, const pstm_int *modulus, const pstm_digit *mp, + const pstm_int *A); +static int32_t eccMap(psPool_t *pool, psEccPoint_t *P, const pstm_int *modulus, + const pstm_digit *mp); + +/* + This array holds the ecc curve settings. + + The recommended elliptic curve domain parameters over p have been given + nicknames to enable them to be easily identified. The nicknames were + chosen as follows. Each name begins with sec to denote ‘Standards for + Efficient Cryptography’, followed by a p to denote parameters over p, + followed by a number denoting the length in bits of the field size p, + followed by a k to denote parameters associated with a Koblitz curve or an + r to denote verifiably random parameters, followed by a sequence number. + + typedef struct { + uint8_t size; // The size of the curve in octets + uint16_t curveId; // IANA named curve id for TLS use + uint8_t isOptimized; // 1 if optimized with field parameter A=-3 + uint32_t OIDsum; // Internal Matrix OID + //Domain parameters + const char *name; // name of curve + const char *prime; // prime defining the field the curve is in (hex) + const char *A; // The fields A param (hex) + const char *B; // The fields B param (hex) + const char *order; // The order of the curve (hex) + const char *Gx; // The x co-ordinate of the base point on the curve (hex) + const char *Gy; // The y co-ordinate of the base point on the curve (hex) + } psEccCurve_t; +*/ +const static psEccCurve_t eccCurve[] = { +#ifdef USE_SECP521R1 + { + 66, + IANA_SECP521R1, + 1, /* isOptimized */ + 211, /* 43.129.4.0.35 */ + "secp521r1", + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", + "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", + "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", + "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", + }, +#endif +#ifdef USE_BRAIN512R1 + { + 64, /* size in octets */ + IANA_BRAIN512R1, + 0, /* isOptimized */ + 110, /* 1.3.36.3.3.2.8.1.1.13 */ + "brainpoolP512r1", + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", + "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", + "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", + "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", + "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", + }, +#endif +#ifdef USE_SECP384R1 + { + 48, + IANA_SECP384R1, + 1, /* isOptimized */ + 210, /* 43.129.4.0.34 */ + "secp384r1", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", + "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", + }, +#endif +#ifdef USE_BRAIN384R1 + { + 48, /* size in octets */ + IANA_BRAIN384R1, + 0, /* isOptimized */ + 108, /* 1.3.36.3.3.2.8.1.1.11 */ + "brainpoolP384r1", + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", + "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", + "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", + "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", + "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", + }, +#endif +#ifdef USE_SECP256R1 + { + 32, + IANA_SECP256R1, + 1, /* isOptimized */ + 526, /* 42.134.72.206.61.3.1.7 */ + "secp256r1", + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", + "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", + }, +#endif +#ifdef USE_BRAIN256R1 + { + 32, /* size in octets */ + IANA_BRAIN256R1, + 0, /* isOptimized */ + 104, /* 1.3.36.3.3.2.8.1.1.7 */ + "brainpoolP256r1", + "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", + "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", + "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", + "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", + "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", + "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", + }, +#endif +#ifdef USE_SECP224R1 + { + 28, + IANA_SECP224R1, + 1, /* isOptimized */ + 209, /* 43.129.4.0.33 */ + "secp224r1", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", + "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", + }, +#endif +#ifdef USE_BRAIN224R1 + { + 28, /* size in octets */ + IANA_BRAIN224R1, + 0, /* isOptimized */ + 102, /* 1.3.36.3.3.2.8.1.1.5 */ + "brainpoolP224r1", + "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", + "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", + "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", + "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", + "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D", + "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD" + }, +#endif +#ifdef USE_SECP192R1 + { + 24, /* size in octets */ + IANA_SECP192R1, /* IANA named curve ID */ + 1, /* isOptimized */ + 520, /* 42.134.72.206.61.3.1.1 */ + "secp192r1", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* A = -3 */ + "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", /* B */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", /* order */ + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", /* Gx */ + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", /* Gy */ + }, +#endif + { + 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL + } +}; + +/*****************************************************************************/ +/** + Initialize an ecc key, and assign the curve, if provided. + @param[in] pool Memory pool + @param[out] key Pointer to allocated ECC key to initialize + @param[in] curve Curve to assign, or NULL. + @return < 0 on failure, 0 on success. + @note To allocate and initialize a key, use psEccNewKey(). +*/ +int32_t psEccInitKey(psPool_t *pool, psEccKey_t *key, const psEccCurve_t *curve) +{ + if (!key) { + return PS_MEM_FAIL; + } + memset(key, 0x0, sizeof(psEccKey_t)); + key->pool = pool; + key->pubkey.pool = pool; + key->curve = curve; /* Curve can be NULL */ + /* key->type will be set by one of the key generate/import/read functions */ + return PS_SUCCESS; +} + +/** + Clear an ECC key. + @param[out] key Pointer to allocated ECC key to clear. + @note Caller is responsible for freeing memory associated with key structure, + if appropriate. +*/ +void psEccClearKey(psEccKey_t *key) +{ + psAssert(key); + /* Clear private k separately, since it may not be present */ + pstm_clear(&key->k); + pstm_clear_multi( + &key->pubkey.x, + &key->pubkey.y, + &key->pubkey.z, + NULL, NULL, NULL, NULL, NULL); + key->curve = NULL; + key->pool = NULL; + key->pubkey.pool = NULL; + key->type = 0; +} + +/** + Allocate memory for an ECC key and initialize it. + @param[in] pool Memory pool + @param[out] key Pointer to unallocated ECC key to initialize. Will + point to allocated and initialized key on successful return. + @param[in] curve Curve to assign, or NULL. + @return < 0 on failure, 0 on success. +*/ +int32_t psEccNewKey(psPool_t *pool, psEccKey_t **key, const psEccCurve_t *curve) +{ + psEccKey_t *k; + int32_t rc; + + if ((k = psMalloc(pool, sizeof(psEccKey_t))) == NULL) { + return PS_MEM_FAIL; + } + k->type = 0; + if ((rc = psEccInitKey(pool, k, curve)) < 0) { + psFree(k, pool); + return rc; + } + *key = k; + return PS_SUCCESS; +} + +/* 'to' digits will be allocated here */ +int32 psEccCopyKey(psEccKey_t *to, psEccKey_t *from) +{ + int32 rc; + + if (to->pool == NULL) { + to->pool = from->pool; + to->pubkey.pool = from->pubkey.pool; + } else { + to->pubkey.pool = to->pool; + } + to->curve = from->curve; + to->type = from->type; + + /* pubkey */ + if ((rc = pstm_init_copy(to->pool, &to->pubkey.x, &from->pubkey.x, 0)) + != PSTM_OKAY) { + goto error; + } + if ((rc = pstm_init_copy(to->pool, &to->pubkey.y, &from->pubkey.y, 0)) + != PSTM_OKAY) { + goto error; + } + if ((rc = pstm_init_copy(to->pool, &to->pubkey.z, &from->pubkey.z, 0)) + != PSTM_OKAY) { + goto error; + } + + /* privkey */ + if (to->type == PS_PRIVKEY) { + if ((rc = pstm_init_copy(to->pool, &to->k, &from->k, 0)) + != PSTM_OKAY) { + goto error; + } + } + +error: + if (rc < 0) { + psEccClearKey(from); + } + return rc; +} + +/** + Free memory for an ECC key and clear it. + @param[out] key Pointer to dynamically allocated ECC key to free. Pointer + will be cleared, freed and set to NULL on return. +*/ +void psEccDeleteKey(psEccKey_t **key) +{ + psEccKey_t *k = *key; + + psEccClearKey(k); + psFree(k, NULL); + *key = NULL; +} + +/** + ECC key size in bytes. + @return Public key size in bytes if key->type is public, otherwise private size. + @note ECC public keys are twice as many bytes as private keys. +*/ +uint8_t psEccSize(const psEccKey_t *key) +{ + if (key && key->curve) { + return key->curve->size * 2; + } + return 0; +} + +/*****************************************************************************/ +/* + Called from the cert parse. The initial bytes in this stream are + technically the EcpkParameters from the ECDSA pub key OBJECT IDENTIFIER + that name the curve. The asnGetAlgorithmIdentifier call right before + this just stripped out the OID +*/ +int32_t getEcPubKey(psPool_t *pool, const unsigned char **pp, uint16_t len, + psEccKey_t *pubKey, unsigned char sha1KeyHash[SHA1_HASH_SIZE]) +{ +#ifdef USE_SHA1 + psDigestContext_t dc; +#endif + const psEccCurve_t *eccCurve; + const unsigned char *p = *pp, *end; + int32_t oid; + uint16_t arcLen; + uint8_t ignore_bits; + + end = p + len; + if (len < 1 || + *(p++) != ASN_OID || + getAsnLength(&p, (uint16_t)(end - p), &arcLen) < 0 || + (uint16_t)(end - p) < arcLen) { + + psTraceCrypto("Only namedCurve types are supported in EC certs\n"); + return -1; + } +/* + NamedCurve OIDs + + ansi-x9-62 OBJECT IDENTIFER ::= { + iso(1) member-body(2) us(840) 10045 + } + + secp192r1 OBJECT IDENTIFIER ::= { ansi-x9-62 curves(3) prime(1) 1 } + 2a8648ce3d030101 -> sum = 520 + + secp256r1 OBJECT IDENTIFIER ::= { ansi-x9-62 curves(3) prime(1) 7 } + 2a8648ce3d030107 -> sum = 526 +*/ + /* Note arcLen could be zero here */ + oid = 0; + while (arcLen > 0) { + oid += *p++; + arcLen--; + } + /* Match the sum against our list of curves to make sure we got it */ + if (getEccParamByOid(oid, &eccCurve) < 0) { + psTraceCrypto("Cert named curve not found in eccCurve list\n"); + return -1; + } + + if ((uint16_t)(end - p) < 1 || (*(p++) != ASN_BIT_STRING) || + getAsnLength(&p, len - 1, &arcLen) < 0 || + (uint16_t)(end - p) < arcLen || + arcLen < 1) { + + psTraceCrypto("Unexpected ECC pubkey format\n"); + return -1; + } + ignore_bits = *p++; + arcLen--; + if (ignore_bits != 0) { + psTraceCrypto("Unexpected ECC pubkey format\n"); + } + +#ifdef USE_SHA1 + /* A public key hash is used in PKI tools (OCSP, Trusted CA indication). + Standard form - SHA-1 hash of the value of the BIT STRING + subjectPublicKey [excluding the tag, length, and number of unused + bits] */ + psSha1Init(&dc.sha1); + psSha1Update(&dc.sha1, p, arcLen); + psSha1Final(&dc.sha1, sha1KeyHash); +#endif + + + /* Note arcLen could again be zero here */ + if (psEccX963ImportKey(pool, p, arcLen, pubKey, eccCurve) < 0) { + psTraceCrypto("Unable to parse ECC pubkey from cert\n"); + return -1; + } + p += arcLen; + + *pp = p; + return 0; +} + + + +/** + Initialize an ECC key and generate a public/private keypair for the given + curve. + @param pool Memory pool + @param[out] key Uninitialized ECC key. This API will call psEccInitKey() on this key. + @param[in] curve ECC named curve to use for key. + @param[in] usrData User data pointer to pass to hardware implementations that use it. + @return < 0 on failure. +*/ +int32_t psEccGenKey(psPool_t *pool, psEccKey_t *key, const psEccCurve_t *curve, + void *usrData) +{ + int32_t err; + uint16_t keysize, slen; + psEccPoint_t *base; + pstm_int *A = NULL; + pstm_int prime, order, rand; + unsigned char *buf; + + if (!key || !curve) { + psTraceCrypto("Only named curves supported in psEccGenKey\n"); + return PS_UNSUPPORTED_FAIL; + } + + psEccInitKey(pool, key, curve); + keysize = curve->size; /* Note, curve is non-null */ + slen = keysize * 2; + + /* allocate ram */ + base = NULL; + buf = psMalloc(pool, ECC_MAXSIZE); + if (buf == NULL) { + psError("Memory allocation error in psEccGenKey\n"); + err = PS_MEM_FAIL; + goto ERR_KEY; + } + + /* Make sure random number is less than "order" */ + if (pstm_init_for_read_unsigned_bin(pool, &order, keysize) < 0) { + err = PS_MEM_FAIL; + goto ERR_BUF; + } + + if ((err = pstm_read_radix(pool, &order, key->curve->order, slen, 16)) + != PS_SUCCESS) { + pstm_clear(&order); + goto ERR_BUF; + } + + /* make up random string */ +RETRY_RAND: + if (matrixCryptoGetPrngData(buf, keysize, usrData) != keysize) { + err = PS_PLATFORM_FAIL; + pstm_clear(&order); + goto ERR_BUF; + } + + if (pstm_init_for_read_unsigned_bin(pool, &rand, keysize) < 0) { + err = PS_MEM_FAIL; + pstm_clear(&order); + goto ERR_BUF; + } + + if ((err = pstm_read_unsigned_bin(&rand, buf, keysize)) != PS_SUCCESS) { + pstm_clear(&order); + pstm_clear(&rand); + goto ERR_BUF; + } + + /* Make sure random number is less than "order" */ + if (pstm_cmp(&rand, &order) == PSTM_GT) { + pstm_clear(&rand); + goto RETRY_RAND; + } + pstm_clear(&rand); + pstm_clear(&order); + + if (key->curve->isOptimized == 0) { + if ((A = psMalloc(pool, sizeof(pstm_int))) == NULL) { + err = PS_MEM_FAIL; + goto ERR_BUF; + } + if (pstm_init_for_read_unsigned_bin(pool, A, keysize) < 0) { + err = PS_MEM_FAIL; + psFree(A, pool); + goto ERR_BUF; + } + if ((err = pstm_read_radix(pool, A, key->curve->A, slen, 16)) + != PS_SUCCESS) { + goto ERR_A; + } + } + + if (pstm_init_for_read_unsigned_bin(pool, &prime, keysize) < 0) { + err = PS_MEM_FAIL; + goto ERR_A; + } + + base = eccNewPoint(pool, prime.alloc); + if (base == NULL) { + err = PS_MEM_FAIL; + goto ERR_PRIME; + } + + /* read in the specs for this key */ + if ((err = pstm_read_radix(pool, &prime, key->curve->prime, slen, 16)) + != PS_SUCCESS) { + goto ERR_BASE; + } + if ((err = pstm_read_radix(pool, &base->x, key->curve->Gx, slen, 16)) + != PS_SUCCESS){ + goto ERR_BASE; + } + if ((err = pstm_read_radix(pool, &base->y, key->curve->Gy, slen, 16)) + != PS_SUCCESS){ + goto ERR_BASE; + } + pstm_set(&base->z, 1); + + if (pstm_init_for_read_unsigned_bin(pool, &key->k, keysize) < 0) { + err = PS_MEM_FAIL; + goto ERR_BASE; + } + if ((err = pstm_read_unsigned_bin(&key->k, buf, keysize)) + != PS_SUCCESS) { + goto ERR_BASE; + } + + + /* make the public key */ + if (pstm_init_size(pool, &key->pubkey.x, (key->k.used * 2) + 1) < 0) { + err = PS_MEM_FAIL; + goto ERR_BASE; + } + if (pstm_init_size(pool, &key->pubkey.y, (key->k.used * 2) + 1) < 0) { + err = PS_MEM_FAIL; + goto ERR_BASE; + } + if (pstm_init_size(pool, &key->pubkey.z, (key->k.used * 2) + 1) < 0) { + err = PS_MEM_FAIL; + goto ERR_BASE; + } + if ((err = eccMulmod(pool, &key->k, base, &key->pubkey, &prime, 1, A)) != + PS_SUCCESS) { + goto ERR_BASE; + } + + key->type = PS_PRIVKEY; + + /* frees for success */ + eccFreePoint(base); + pstm_clear(&prime); + if (A) { + pstm_clear(A); + psFree(A, pool); + } + psFree(buf, pool); + return PS_SUCCESS; + +ERR_BASE: + eccFreePoint(base); +ERR_PRIME: + pstm_clear(&prime); +ERR_A: + if (A) { + pstm_clear(A); + psFree(A, pool); + } +ERR_BUF: + psFree(buf, pool); +ERR_KEY: + psEccClearKey(key); + return err; +} + +#if defined(MATRIX_USE_FILE_SYSTEM) && defined(USE_PRIVATE_KEY_PARSING) +/******************************************************************************/ +/* + ECPrivateKey{CURVES:IOSet} ::= SEQUENCE { + version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + privateKey OCTET STRING, + parameters [0] Parameters{{IOSet}} OPTIONAL, + publicKey [1] BIT STRING OPTIONAL + } + +*/ +int32_t psEccParsePrivFile(psPool_t *pool, const char *fileName, + const char *password, psEccKey_t *key) +{ + unsigned char *DERout; + int32_t rc; + uint16_t DERlen; +#ifdef USE_PKCS8 + psPubKey_t pubkey; +#endif + + if ((rc = pkcs1DecodePrivFile(pool, fileName, password, &DERout, &DERlen)) < 0) { + return rc; + } + + if ((rc = psEccParsePrivKey(pool, DERout, DERlen, key, NULL)) < 0) { +#ifdef USE_PKCS8 + /* This logic works for processing PKCS#8 files becuase the above file + and bin decodes will always leave the unprocessed buffer intact and + the password protection is done in the internal ASN.1 encoding */ + if ((rc = pkcs8ParsePrivBin(pool, DERout, DERlen, (char*)password, + &pubkey)) < 0) { + psFree(DERout, pool); + return rc; + } + rc = psEccCopyKey(key, &pubkey.key.ecc); + psClearPubKey(&pubkey); +#else + psFree(DERout, pool); + return rc; +#endif + } + psFree(DERout, pool); + return PS_SUCCESS; +} +#endif /* MATRIX_USE_FILE_SYSTEM && USE_PRIVATE_KEY_PARSING */ + +int32_t psEccParsePrivKey(psPool_t *pool, + const unsigned char *keyBuf, uint16_t keyBufLen, + psEccKey_t *key, const psEccCurve_t *curve) +{ + const psEccCurve_t *eccCurve; + const unsigned char *buf, *end; + uint8_t ignore_bits; + uint32_t oid; + int32_t asnInt; + uint16_t len; + + buf = keyBuf; + end = buf + keyBufLen; + + if (getAsnSequence(&buf, (uint16_t)(end - buf), &len) < 0) { + psTraceCrypto("ECDSA subject signature parse failure 1\n"); + return PS_FAILURE; + } + if (getAsnInteger(&buf, (uint16_t)(end - buf), &asnInt) < 0 || + asnInt != 1) { + psTraceCrypto("Expecting private key flag\n"); + return PS_FAILURE; + } + /* Initial curve check */ + if ((*buf++ != ASN_OCTET_STRING) || + getAsnLength(&buf, (uint16_t)(end - buf), &len) < 0 || + (uint16_t)(end - buf) < len || + len < (MIN_ECC_BITS / 8)) { + psTraceCrypto("Expecting private key octet string\n"); + return PS_FAILURE; + } + psEccInitKey(pool, key, curve); + if (pstm_init_for_read_unsigned_bin(pool, &key->k, len) != PS_SUCCESS) { + goto L_FAIL; + } + /* Key material */ + if (pstm_read_unsigned_bin(&key->k, buf, len) != PS_SUCCESS) { + psTraceCrypto("Unable to read private key octet string\n"); + goto L_FAIL; + } + key->type = PS_PRIVKEY; + buf += len; + + if (*buf == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + + /* optional parameters are present */ + buf++; + if (getAsnLength(&buf, (uint16_t)(end - buf), &len) < 0 || + (uint16_t)(end - buf) < len || + len < 1) { + + psTraceCrypto("Bad private key format\n"); + goto L_FAIL; + } + if (*(buf++) != ASN_OID || + getAsnLength(&buf, (uint16_t)(end - buf), &len) < 0 || + (uint16_t)(end - buf) < len) { + + psTraceCrypto("Only namedCurves are supported in EC keys\n"); + goto L_FAIL; + } + /* Note len can be 0 here */ + oid = 0; + while (len > 0) { + oid += *buf++; + len--; + } + if (getEccParamByOid(oid, &eccCurve) < 0) { + psTraceCrypto("Cert named curve not found in eccCurve list\n"); + goto L_FAIL; + } + if (curve != NULL && curve != eccCurve) { + psTraceCrypto("PrivKey named curve doesn't match desired\n"); + goto L_FAIL; + } + key->curve = eccCurve; + + } else if (curve != NULL) { + key->curve = curve; + } else { + psTraceCrypto("No curve found in EC private key\n"); + goto L_FAIL; + } + + if (*buf == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) { + /* optional public key is present */ + buf++; + if (getAsnLength(&buf, (uint16_t)(end - buf), &len) < 0 || + (uint16_t)(end - buf) < len || + len < 1) { + + psTraceCrypto("Bad private key format\n"); + goto L_FAIL; + } + if (*(buf++) != ASN_BIT_STRING || + getAsnLength(&buf, (uint16_t)(end - buf), &len) < 0 || + (uint16_t)(end - buf) < len || + len < 1) { + + goto L_FAIL; + } + ignore_bits = *buf++; + len--; + if (ignore_bits != 0) { + psTraceCrypto("Unexpected ECC pubkey format\n"); + goto L_FAIL; + } + + /* Note len can be 0 here */ + if (psEccX963ImportKey(pool, buf, len, key, key->curve) < 0) { + psTraceCrypto("Unable to parse ECC pubkey from cert\n"); + goto L_FAIL; + } + buf += len; + } + /* Should be at the end */ + if (end != buf) { + /* If this stream came from an encrypted file, there could be + padding bytes on the end */ + len = (uint16_t)(end - buf); + while (buf < end) { + if (*buf != len) { + psTraceCrypto("Problem at end of private key parse\n"); + goto L_FAIL; + } + buf++; + } + } + return PS_SUCCESS; + +L_FAIL: + psEccClearKey(key); + return PS_FAIL; +} + +int32_t getEccParamById(uint16_t curveId, const psEccCurve_t **curve) +{ + int i = 0; + + /* A curveId of zero is asking for a default curver */ + if (curveId == 0) { + *curve = &eccCurve[0]; + return 0; + } + + *curve = NULL; + while (eccCurve[i].size > 0) { + if (curveId == eccCurve[i].curveId) { + *curve = &eccCurve[i]; + return 0; + } + i++; + } + return PS_FAIL; +} + +int32_t getEccParamByOid(uint32_t oid, const psEccCurve_t **curve) +{ + int i = 0; + + *curve = NULL; + while (eccCurve[i].size > 0) { + if (oid == eccCurve[i].OIDsum) { + *curve = &eccCurve[i]; + return 0; + } + i++; + } + return PS_FAIL; +} + +int32_t getEccParamByName(const char *curveName, + const psEccCurve_t **curve) +{ + int i = 0; + + *curve = NULL; + while (eccCurve[i].size > 0) { + if (strcmp(curveName, eccCurve[i].name) == 0) { + *curve = &eccCurve[i]; + return 0; + } + i++; + } + return PS_FAIL; +} + +/** + Return a list of all supported curves. + This method will put the largest bit strength first in the list, because + of their order in the eccCurve[] array. +*/ +void psGetEccCurveIdList(unsigned char *curveList, uint8_t *len) +{ + uint16_t listLen = 0, i = 0; + + while (eccCurve[i].size > 0) { + if (listLen < (*len - 2)) { + curveList[listLen++] = (eccCurve[i].curveId & 0xFF00) >> 8; + curveList[listLen++] = eccCurve[i].curveId & 0xFF; + } + i++; + } + *len = listLen; +} + +/** + User set list of curves they want to support. + This method will put the largest bit strength first in the list. + @param[in] curves Flags indicating which curves to use. +*/ +void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves) +{ + const psEccCurve_t *curve; + uint8_t listLen = 0; + + if (curves & IS_SECP521R1) { + if (getEccParamById(IANA_SECP521R1, &curve) == 0) { + if (listLen < (*len - 2)) { + curveList[listLen++] = (curve->curveId & 0xFF00) >> 8; + curveList[listLen++] = curve->curveId & 0xFF; + } + } + } + if (curves & IS_BRAIN512R1) { + if (getEccParamById(IANA_BRAIN512R1, &curve) == 0) { + if (listLen < (*len - 2)) { + curveList[listLen++] = (curve->curveId & 0xFF00) >> 8; + curveList[listLen++] = curve->curveId & 0xFF; + } + } + } + if (curves & IS_SECP384R1) { + if (getEccParamById(IANA_SECP384R1, &curve) == 0) { + if (listLen < (*len - 2)) { + curveList[listLen++] = (curve->curveId & 0xFF00) >> 8; + curveList[listLen++] = curve->curveId & 0xFF; + } + } + } + if (curves & IS_BRAIN384R1) { + if (getEccParamById(IANA_BRAIN384R1, &curve) == 0) { + if (listLen < (*len - 2)) { + curveList[listLen++] = (curve->curveId & 0xFF00) >> 8; + curveList[listLen++] = curve->curveId & 0xFF; + } + } + } + if (curves & IS_SECP256R1) { + if (getEccParamById(IANA_SECP256R1, &curve) == 0) { + if (listLen < (*len - 2)) { + curveList[listLen++] = (curve->curveId & 0xFF00) >> 8; + curveList[listLen++] = curve->curveId & 0xFF; + } + } + } + if (curves & IS_BRAIN256R1) { + if (getEccParamById(IANA_BRAIN256R1, &curve) == 0) { + if (listLen < (*len - 2)) { + curveList[listLen++] = (curve->curveId & 0xFF00) >> 8; + curveList[listLen++] = curve->curveId & 0xFF; + } + } + } + if (curves & IS_SECP224R1) { + if (getEccParamById(IANA_SECP224R1, &curve) == 0) { + if (listLen < (*len - 2)) { + curveList[listLen++] = (curve->curveId & 0xFF00) >> 8; + curveList[listLen++] = curve->curveId & 0xFF; + } + } + } + if (curves & IS_BRAIN224R1) { + if (getEccParamById(IANA_BRAIN224R1, &curve) == 0) { + if (listLen < (*len - 2)) { + curveList[listLen++] = (curve->curveId & 0xFF00) >> 8; + curveList[listLen++] = curve->curveId & 0xFF; + } + } + } + if (curves & IS_SECP192R1) { + if (getEccParamById(IANA_SECP192R1, &curve) == 0) { + if (listLen < (*len - 2)) { + curveList[listLen++] = (curve->curveId & 0xFF00) >> 8; + curveList[listLen++] = curve->curveId & 0xFF; + } + } + } + + *len = listLen; +} + +uint32_t compiledInEcFlags(void) +{ + uint32_t ecFlags = 0; + +#ifdef USE_SECP192R1 + ecFlags |= IS_SECP192R1; +#endif +#ifdef USE_SECP224R1 + ecFlags |= IS_SECP224R1; +#endif +#ifdef USE_SECP256R1 + ecFlags |= IS_SECP256R1; +#endif +#ifdef USE_SECP384R1 + ecFlags |= IS_SECP384R1; +#endif +#ifdef USE_SECP521R1 + ecFlags |= IS_SECP521R1; +#endif +#ifdef USE_BRAIN224R1 + ecFlags |= IS_BRAIN224R1; +#endif +#ifdef USE_BRAIN256R1 + ecFlags |= IS_BRAIN256R1; +#endif +#ifdef USE_BRAIN384R1 + ecFlags |= IS_BRAIN384R1; +#endif +#ifdef USE_BRAIN512R1 + ecFlags |= IS_BRAIN512R1; +#endif + + return ecFlags; +} + +/******************************************************************************/ + +static uint8_t get_digit_count(const pstm_int *a) +{ + return a->used; +} + +static pstm_digit get_digit(const pstm_int *a, uint8_t n) +{ + return (n >= a->used || n < 0) ? (pstm_digit)0 : a->dp[n]; +} + +/******************************************************************************/ +/** + Perform a point multiplication + @param[in] pool Memory pool + @param[in] k The scalar to multiply by + @param[in] G The base point + @param[out] R Destination for kG + @param modulus The modulus of the field the ECC curve is in + @param map Boolean whether to map back to affine or not (1==map) + @param[in,out] tmp_int Temporary scratch big integer (memory optimization) + @return PS_SUCCESS on success, < 0 on error +*/ +/* size of sliding window, don't change this! */ +#define ECC_MULMOD_WINSIZE 4 + +static int32_t eccMulmod(psPool_t *pool, const pstm_int *k, const psEccPoint_t *G, + psEccPoint_t *R, pstm_int *modulus, uint8_t map, pstm_int *tmp_int) +{ + psEccPoint_t *tG, *M[8]; /* @note large on stack */ + int32 i, j, err; + pstm_int mu; + pstm_digit mp; + unsigned long buf; + int32 first, bitbuf, bitcpy, bitcnt, mode, digidx; + + /* init montgomery reduction */ + if ((err = pstm_montgomery_setup(modulus, &mp)) != PS_SUCCESS) { + return err; + } + if ((err = pstm_init_size(pool, &mu, modulus->alloc)) != PS_SUCCESS) { + return err; + } + if ((err = pstm_montgomery_calc_normalization(&mu, modulus)) != PS_SUCCESS) { + pstm_clear(&mu); + return err; + } + + /* alloc ram for window temps */ + for (i = 0; i < 8; i++) { + M[i] = eccNewPoint(pool, (G->x.used * 2) + 1); + if (M[i] == NULL) { + for (j = 0; j < i; j++) { + eccFreePoint(M[j]); + } + pstm_clear(&mu); + return PS_MEM_FAIL; + } + } + + /* make a copy of G incase R==G */ + tG = eccNewPoint(pool, G->x.alloc); + if (tG == NULL) { + err = PS_MEM_FAIL; + goto done; + } + + /* tG = G and convert to montgomery */ + if (pstm_cmp_d(&mu, 1) == PSTM_EQ) { + if ((err = pstm_copy(&G->x, &tG->x)) != PS_SUCCESS) { goto done; } + if ((err = pstm_copy(&G->y, &tG->y)) != PS_SUCCESS) { goto done; } + if ((err = pstm_copy(&G->z, &tG->z)) != PS_SUCCESS) { goto done; } + } else { + if ((err = pstm_mulmod(pool, &G->x, &mu, modulus, &tG->x)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_mulmod(pool, &G->y, &mu, modulus, &tG->y)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_mulmod(pool, &G->z, &mu, modulus, &tG->z)) != PS_SUCCESS) { + goto done; + } + } + pstm_clear(&mu); + + /* calc the M tab, which holds kG for k==8..15 */ + /* M[0] == 8G */ + if ((err = eccProjectiveDblPoint(pool, tG, M[0], modulus, &mp, tmp_int)) != PS_SUCCESS) + { + goto done; + } + if ((err = eccProjectiveDblPoint(pool, M[0], M[0], modulus, &mp, tmp_int)) != + PS_SUCCESS) { + goto done; + } + if ((err = eccProjectiveDblPoint(pool, M[0], M[0], modulus, &mp, tmp_int)) != + PS_SUCCESS) { + goto done; + } + + /* now find (8+k)G for k=1..7 */ + for (j = 9; j < 16; j++) { + if ((err = eccProjectiveAddPoint(pool, M[j-9], tG, M[j-8], modulus, + &mp, tmp_int)) != PS_SUCCESS) { + goto done; + } + } + + /* setup sliding window */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = get_digit_count(k) - 1; + bitcpy = bitbuf = 0; + first = 1; + + /* perform ops */ + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + if (digidx == -1) { + break; + } + buf = get_digit(k, digidx); + bitcnt = DIGIT_BIT; + --digidx; + } + + /* grab the next msb from the ltiplicand */ + i = (buf >> (DIGIT_BIT - 1)) & 1; + buf <<= 1; + + /* skip leading zero bits */ + if (mode == 0 && i == 0) { + continue; + } + + /* if the bit is zero and mode == 1 then we double */ + if (mode == 1 && i == 0) { + if ((err = eccProjectiveDblPoint(pool, R, R, modulus, &mp, tmp_int)) != + PS_SUCCESS) { + goto done; + } + continue; + } + + /* else we add it to the window */ + bitbuf |= (i << (ECC_MULMOD_WINSIZE - ++bitcpy)); + mode = 2; + + if (bitcpy == ECC_MULMOD_WINSIZE) { + /* if this is the first window we do a simple copy */ + if (first == 1) { + /* R = kG [k = first window] */ + if ((err = pstm_copy(&M[bitbuf-8]->x, &R->x)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_copy(&M[bitbuf-8]->y, &R->y)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_copy(&M[bitbuf-8]->z, &R->z)) != PS_SUCCESS) { + goto done; + } + first = 0; + } else { + /* normal window */ + /* ok window is filled so double as required and add */ + /* double first */ + for (j = 0; j < ECC_MULMOD_WINSIZE; j++) { + if ((err = eccProjectiveDblPoint(pool, R, R, modulus, &mp, tmp_int)) + != PS_SUCCESS) { + goto done; + } + } + + /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */ + if ((err = eccProjectiveAddPoint(pool, R, M[bitbuf-8], R, + modulus, &mp, tmp_int)) != PS_SUCCESS) { + goto done; + } + } + /* empty window and reset */ + bitcpy = bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then double/add */ + if (mode == 2 && bitcpy > 0) { + /* double then add */ + for (j = 0; j < bitcpy; j++) { + /* only double if we have had at least one add first */ + if (first == 0) { + if ((err = eccProjectiveDblPoint(pool, R, R, modulus, &mp, tmp_int)) != + PS_SUCCESS) { + goto done; + } + } + + bitbuf <<= 1; + if ((bitbuf & (1 << ECC_MULMOD_WINSIZE)) != 0) { + if (first == 1){ + /* first add, so copy */ + if ((err = pstm_copy(&tG->x, &R->x)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_copy(&tG->y, &R->y)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_copy(&tG->z, &R->z)) != PS_SUCCESS) { + goto done; + } + first = 0; + } else { + /* then add */ + if ((err = eccProjectiveAddPoint(pool, R, tG, R, modulus, + &mp, tmp_int)) != PS_SUCCESS) { + goto done; + } + } + } + } + } + + /* map R back from projective space */ + if (map) { + err = eccMap(pool, R, modulus, &mp); + } else { + err = PS_SUCCESS; + } +done: + + pstm_clear(&mu); + eccFreePoint(tG); + for (i = 0; i < 8; i++) { + eccFreePoint(M[i]); + } + return err; +} + +static int32 eccTestPoint(psPool_t *pool, psEccPoint_t *P, pstm_int *prime, + pstm_int *b) +{ + pstm_int t1, t2; + uint32 paDlen; + pstm_digit *paD; + int32 err; + + if ((err = pstm_init(pool, &t1)) < 0) { + return err; + } + if ((err = pstm_init(pool, &t2)) < 0) { + pstm_clear(&t1); + return err; + } + /* Pre-allocated digit. TODO: haven't fully explored max paDlen */ + paDlen = (prime->used*2+1) * sizeof(pstm_digit); + if ((paD = psMalloc(pool, paDlen)) == NULL) { + pstm_clear(&t1); + pstm_clear(&t2); + return PS_MEM_FAIL; + } + + /* compute y^2 */ + if ((err = pstm_sqr_comba(pool, &P->y, &t1, paD, paDlen)) < 0) { + goto error; + } + + /* compute x^3 */ + if ((err = pstm_sqr_comba(pool, &P->x, &t2, paD, paDlen)) < 0) { + goto error; + } + if ((err = pstm_mod(pool, &t2, prime, &t2)) < 0) { + goto error; + } + + if ((err = pstm_mul_comba(pool, &P->x, &t2, &t2, paD, paDlen)) < 0) { + goto error; + } + + /* compute y^2 - x^3 */ + if ((err = pstm_sub(&t1, &t2, &t1)) < 0) { + goto error; + } + + /* compute y^2 - x^3 + 3x */ + if ((err = pstm_add(&t1, &P->x, &t1)) < 0) { + goto error; + } + if ((err = pstm_add(&t1, &P->x, &t1)) < 0) { + goto error; + } + if ((err = pstm_add(&t1, &P->x, &t1)) < 0) { + goto error; + } + if ((err = pstm_mod(pool, &t1, prime, &t1)) < 0) { + goto error; + } + while (pstm_cmp_d(&t1, 0) == PSTM_LT) { + if ((err = pstm_add(&t1, prime, &t1)) < 0) { + goto error; + } + } + while (pstm_cmp(&t1, prime) != PSTM_LT) { + if ((err = pstm_sub(&t1, prime, &t1)) < 0) { + goto error; + } + } + + /* compare to b */ + if (pstm_cmp(&t1, b) != PSTM_EQ) { + psTraceCrypto("Supplied EC public point not on curve\n"); + err = PS_LIMIT_FAIL; + } else { + err = PS_SUCCESS; + } + +error: + psFree(paD, pool); + pstm_clear(&t1); + pstm_clear(&t2); + return err; +} + +/******************************************************************************/ +/** + ANSI X9.62 or X9.63 (Section 4.3.7) uncompressed import. + This function imports the public ECC key elements (the x, y and z values). + If a private 'k' value is defined, the public elements are added to the + key. Otherwise, only the public elements are loaded and the key + marked public. + The format of import is ASN.1, and is used both within certificate + parsing and when parsing public keys passed on the wire in TLS. + + @param[in] pool Memory pool + @param[in] in ECC key data in uncompressed form + @param[in] inlen Length of destination and final output size + @param[in, out] key Key to import. Private keys types will not be + initialized, all others will. + @param[in] curve Curve parameters, may be NULL + @return PS_SUCCESS on success, < 0 on failure +*/ +int32_t psEccX963ImportKey(psPool_t *pool, + const unsigned char *in, uint16_t inlen, + psEccKey_t *key, const psEccCurve_t *curve) +{ + int32_t err; + pstm_int prime, b; + + /* Must be odd and minimal size */ + if (inlen < ((2 * (MIN_ECC_BITS / 8)) + 1) || (inlen & 1) == 0) { + return PS_ARG_FAIL; + } + + /* The key passed in may be a private key that is already initialized + and the 'k' parameter set. */ + if (key->type != PS_PRIVKEY) { + if (psEccInitKey(pool, key, curve) < 0) { + return PS_MEM_FAIL; + } + key->type = PS_PUBKEY; + } + if (pstm_init_for_read_unsigned_bin(pool, &key->pubkey.x, + (inlen - 1) >> 1) < 0) { + return PS_MEM_FAIL; + } + if (pstm_init_for_read_unsigned_bin(pool, &key->pubkey.y, + (inlen - 1) >> 1) < 0) { + pstm_clear(&key->pubkey.x); + return PS_MEM_FAIL; + } + if (pstm_init_size(pool, &key->pubkey.z, 1) < 0) { + pstm_clear(&key->pubkey.x); + pstm_clear(&key->pubkey.y); + return PS_MEM_FAIL; + } + + switch (*in) { + /* Standard, supported format */ + case ANSI_UNCOMPRESSED: + break; + /* Unsupported formats */ + case ANSI_COMPRESSED0: + case ANSI_COMPRESSED1: + case ANSI_HYBRID0: + case ANSI_HYBRID1: + psTraceCrypto("ERROR: ECC compressed/hybrid formats unsupported\n"); + default: + err = PS_UNSUPPORTED_FAIL; + goto error; + } + if ((err = pstm_read_unsigned_bin(&key->pubkey.x, (unsigned char *)in + 1, + (inlen - 1) >> 1)) != PS_SUCCESS) { + goto error; + } + if ((err = pstm_read_unsigned_bin(&key->pubkey.y, + (unsigned char *)in + 1 + ((inlen - 1) >> 1), + (inlen - 1) >> 1)) != PS_SUCCESS) { + goto error; + } + pstm_set(&key->pubkey.z, 1); + + /* Validate the point is on the curve */ + if (curve != NULL && curve->isOptimized) { + if ((err = pstm_init_for_read_unsigned_bin(pool, &prime, curve->size)) < 0) { + goto error; + } + if ((err = pstm_init_for_read_unsigned_bin(pool, &b, curve->size)) < 0) { + pstm_clear(&prime); + goto error; + } + if ((err = pstm_read_radix(pool, &prime, curve->prime, + curve->size * 2, 16)) < 0){ + pstm_clear(&prime); + pstm_clear(&b); + goto error; + } + + if ((err = pstm_read_radix(pool, &b, curve->B, curve->size * 2, 16)) < 0) { + pstm_clear(&prime); + pstm_clear(&b); + goto error; + } + if ((err = eccTestPoint(pool, &key->pubkey, &prime, &b)) < 0) { + pstm_clear(&prime); + pstm_clear(&b); + goto error; + } + pstm_clear(&prime); + pstm_clear(&b); + } else { + psTraceCrypto("WARNING: ECC public key not validated\n"); + } + + return PS_SUCCESS; + +error: + psEccClearKey(key); + return err; +} + +/******************************************************************************/ +/** + ANSI X9.62 or X9.63 (Sec. 4.3.6) uncompressed export. + @param[in] pool Memory pool + @param[in] key Key to export + @param[out] out [out] destination of export + @param[in, out] outlen Length of destination and final output size + @return PS_SUCCESS on success, < 0 on failure +*/ +int32_t psEccX963ExportKey(psPool_t *pool, const psEccKey_t *key, + unsigned char *out, uint16_t *outlen) +{ + unsigned char buf[ECC_BUF_SIZE]; + unsigned long numlen; + int32_t res; + + numlen = key->curve->size; + if (*outlen < (1 + 2 * numlen)) { + *outlen = 1 + 2 * numlen; + return PS_LIMIT_FAIL; + } + + out[0] = (unsigned char)ANSI_UNCOMPRESSED; + + /* pad and store x */ + memset(buf, 0, sizeof(buf)); + if ((res = pstm_to_unsigned_bin(pool, &key->pubkey.x, buf + + (numlen - pstm_unsigned_bin_size(&key->pubkey.x)))) != PSTM_OKAY) { + return res; + } + memcpy(out+1, buf, numlen); + + /* pad and store y */ + memset(buf, 0, sizeof(buf)); + if ((res = pstm_to_unsigned_bin(pool, &key->pubkey.y, buf + + (numlen - pstm_unsigned_bin_size(&key->pubkey.y)))) != PSTM_OKAY) { + return res; + } + memcpy(out+1+numlen, buf, numlen); + + *outlen = 1 + 2*numlen; + return PS_SUCCESS; +} + +/******************************************************************************/ +/** + Create an ECC shared secret between two keys. + @param[in] pool Memory pool + @param[in] private_key The private ECC key + @param[in] public_key The public key + @param[out] out Destination of the shared secret (Conforms to EC-DH from ANSI X9.63) + @param[in,out] outlen The max size and resulting size of the shared secret + @param[in,out] usrData Opaque usrData for hardware offload. + @return PS_SUCCESS if successful +*/ +int32_t psEccGenSharedSecret(psPool_t *pool, + const psEccKey_t *private_key, const psEccKey_t *public_key, + unsigned char *out, uint16_t *outlen, + void *usrData) +{ + uint16_t x; + psEccPoint_t *result; + pstm_int *A = NULL; + pstm_int prime; + int32_t err; + + /* type valid? */ + if (private_key->type != PS_PRIVKEY) { + return PS_ARG_FAIL; + } + if (public_key->curve != NULL) { + if (private_key->curve != public_key->curve) { + return PS_ARG_FAIL; + } + } + + /* make new point */ + result = eccNewPoint(pool, (private_key->k.used * 2) + 1); + if (result == NULL) { + return PS_MEM_FAIL; + } + + if (private_key->curve->isOptimized == 0) + { + if ((A = psMalloc(pool, sizeof(pstm_int))) == NULL) { + eccFreePoint(result); + return PS_MEM_FAIL; + } + + if (pstm_init_for_read_unsigned_bin(pool, A, private_key->curve->size) < 0) { + psFree(A, pool); + eccFreePoint(result); + return PS_MEM_FAIL; + } + + if ((err = pstm_read_radix(pool, A, private_key->curve->A, + private_key->curve->size * 2, 16)) + != PS_SUCCESS) { + pstm_clear(A); + psFree(A, pool); + eccFreePoint(result); + return err; + } + } + + if ((err = pstm_init_for_read_unsigned_bin(pool, &prime, + private_key->curve->size)) != PS_SUCCESS) { + if (A) { + pstm_clear(A); + psFree(A, pool); + } + eccFreePoint(result); + return err; + } + + if ((err = pstm_read_radix(pool, &prime, private_key->curve->prime, + private_key->curve->size * 2, 16)) != PS_SUCCESS){ + goto done; + } + if ((err = eccMulmod(pool, &private_key->k, &public_key->pubkey, result, + &prime, 1, A)) != PS_SUCCESS) { + goto done; + } + + x = pstm_unsigned_bin_size(&prime); + if (*outlen < x) { + *outlen = x; + err = PS_LIMIT_FAIL; + goto done; + } + memset(out, 0, x); + if ((err = pstm_to_unsigned_bin(pool, &result->x, + out + (x - pstm_unsigned_bin_size(&result->x)))) != PS_SUCCESS) { + goto done; + } + + err = PS_SUCCESS; + *outlen = x; +done: + if (A) { + pstm_clear(A); + psFree(A, pool); + } + pstm_clear(&prime); + eccFreePoint(result); + return err; +} + +/******************************************************************************/ +/** + Add two ECC points + @param P The point to add + @param Q The point to add + @param[out] R The destination of the double + @param modulus The modulus of the field the ECC curve is in + @param mp The "b" value from montgomery_setup() + @return PS_SUCCESS on success +*/ +static int32_t eccProjectiveAddPoint(psPool_t *pool, const psEccPoint_t *P, + const psEccPoint_t *Q, psEccPoint_t *R, + const pstm_int *modulus, const pstm_digit *mp, pstm_int *tmp_int) +{ + pstm_int t1, t2, x, y, z; + pstm_digit *paD; + int32 err; + uint32 paDlen; + + paD = NULL; + if (pstm_init_size(pool, &t1, P->x.alloc) < 0) { + return PS_MEM_FAIL; + } + err = PS_MEM_FAIL; + if (pstm_init_size(pool, &t2, P->x.alloc) < 0) { + goto ERR_T1; + } + if (pstm_init_size(pool, &x, P->x.alloc) < 0) { + goto ERR_T2; + } + if (pstm_init_size(pool, &y, P->y.alloc) < 0) { + goto ERR_X; + } + if (pstm_init_size(pool, &z, P->z.alloc) < 0) { + goto ERR_Y; + } + + /* should we dbl instead? */ + if ((err = pstm_sub(modulus, &Q->y, &t1)) != PS_SUCCESS) { goto done; } + + if ((pstm_cmp(&P->x, &Q->x) == PSTM_EQ) && + //(&Q->z != NULL && pstm_cmp(&P->z, &Q->z) == PSTM_EQ) && + (pstm_cmp(&P->z, &Q->z) == PSTM_EQ) && + (pstm_cmp(&P->y, &Q->y) == PSTM_EQ || + pstm_cmp(&P->y, &t1) == PSTM_EQ)) { + pstm_clear_multi(&t1, &t2, &x, &y, &z, NULL, NULL, NULL); + return eccProjectiveDblPoint(pool, P, R, modulus, mp, tmp_int); + } + + if ((err = pstm_copy(&P->x, &x)) != PS_SUCCESS) { goto done; } + if ((err = pstm_copy(&P->y, &y)) != PS_SUCCESS) { goto done; } + if ((err = pstm_copy(&P->z, &z)) != PS_SUCCESS) { goto done; } + +/* + Pre-allocated digit. Used for mul, sqr, AND reduce + TODO: haven't fully explored max paDlen +*/ + paDlen = (modulus->used * 2 + 1) * sizeof(pstm_digit); + if ((paD = psMalloc(pool, paDlen)) == NULL) { + err = PS_MEM_FAIL; + goto done; + } + + /* if Z is one then these are no-operations */ + if (pstm_cmp_d(&Q->z, 1) != PSTM_EQ) { + /* T1 = Z' * Z' */ + if ((err = pstm_sqr_comba(pool, &Q->z, &t1, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &t1, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + /* X = X * T1 */ + if ((err = pstm_mul_comba(pool, &t1, &x, &x, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &x, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + /* T1 = Z' * T1 */ + if ((err = pstm_mul_comba(pool, &Q->z, &t1, &t1, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &t1, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + /* Y = Y * T1 */ + if ((err = pstm_mul_comba(pool, &t1, &y, &y, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &y, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + } + + /* T1 = Z*Z */ + if ((err = pstm_sqr_comba(pool, &z, &t1, paD, paDlen)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &t1, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + /* T2 = X' * T1 */ + if ((err = pstm_mul_comba(pool, &Q->x, &t1, &t2, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &t2, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + /* T1 = Z * T1 */ + if ((err = pstm_mul_comba(pool, &z, &t1, &t1, paD, paDlen)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &t1, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + /* T1 = Y' * T1 */ + if ((err = pstm_mul_comba(pool, &Q->y, &t1, &t1, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &t1, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + + /* Y = Y - T1 */ + if ((err = pstm_sub(&y, &t1, &y)) != PS_SUCCESS) { goto done; } + if (pstm_cmp_d(&y, 0) == PSTM_LT) { + if ((err = pstm_add(&y, modulus, &y)) != PS_SUCCESS) { goto done; } + } + /* T1 = 2T1 */ + if ((err = pstm_add(&t1, &t1, &t1)) != PS_SUCCESS) { goto done; } + if (pstm_cmp(&t1, modulus) != PSTM_LT) { + if ((err = pstm_sub(&t1, modulus, &t1)) != PS_SUCCESS) { goto done; } + } + /* T1 = Y + T1 */ + if ((err = pstm_add(&t1, &y, &t1)) != PS_SUCCESS) { goto done; } + if (pstm_cmp(&t1, modulus) != PSTM_LT) { + if ((err = pstm_sub(&t1, modulus, &t1)) != PS_SUCCESS) { goto done; } + } + /* X = X - T2 */ + if ((err = pstm_sub(&x, &t2, &x)) != PS_SUCCESS) { goto done; } + if (pstm_cmp_d(&x, 0) == PSTM_LT) { + if ((err = pstm_add(&x, modulus, &x)) != PS_SUCCESS) { goto done; } + } + /* T2 = 2T2 */ + if ((err = pstm_add(&t2, &t2, &t2)) != PS_SUCCESS) { goto done; } + if (pstm_cmp(&t2, modulus) != PSTM_LT) { + if ((err = pstm_sub(&t2, modulus, &t2)) != PS_SUCCESS) { goto done; } + } + /* T2 = X + T2 */ + if ((err = pstm_add(&t2, &x, &t2)) != PS_SUCCESS) { goto done; } + if (pstm_cmp(&t2, modulus) != PSTM_LT) { + if ((err = pstm_sub(&t2, modulus, &t2)) != PS_SUCCESS) { goto done; } + } + + /* if Z' != 1 */ + if (pstm_cmp_d(&Q->z, 1) != PSTM_EQ) { + /* Z = Z * Z' */ + if ((err = pstm_mul_comba(pool, &z, &Q->z, &z, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &z, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + } + + /* Z = Z * X */ + if ((err = pstm_mul_comba(pool, &z, &x, &z, paD, paDlen)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &z, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + + /* T1 = T1 * X */ + if ((err = pstm_mul_comba(pool, &t1, &x, &t1, paD, paDlen)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &t1, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + /* X = X * X */ + if ((err = pstm_sqr_comba(pool, &x, &x, paD, paDlen)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &x, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + /* T2 = T2 * x */ + if ((err = pstm_mul_comba(pool, &t2, &x, &t2, paD, paDlen)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &t2, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + /* T1 = T1 * X */ + if ((err = pstm_mul_comba(pool, &t1, &x, &t1, paD, paDlen)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &t1, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + + /* X = Y*Y */ + if ((err = pstm_sqr_comba(pool, &y, &x, paD, paDlen)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &x, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + /* X = X - T2 */ + if ((err = pstm_sub(&x, &t2, &x)) != PS_SUCCESS) { goto done; } + if (pstm_cmp_d(&x, 0) == PSTM_LT) { + if ((err = pstm_add(&x, modulus, &x)) != PS_SUCCESS) { goto done; } + } + + /* T2 = T2 - X */ + if ((err = pstm_sub(&t2, &x, &t2)) != PS_SUCCESS) { goto done; } + if (pstm_cmp_d(&t2, 0) == PSTM_LT) { + if ((err = pstm_add(&t2, modulus, &t2)) != PS_SUCCESS) { goto done; } + } + /* T2 = T2 - X */ + if ((err = pstm_sub(&t2, &x, &t2)) != PS_SUCCESS) { goto done; } + if (pstm_cmp_d(&t2, 0) == PSTM_LT) { + if ((err = pstm_add(&t2, modulus, &t2)) != PS_SUCCESS) { goto done; } + } + /* T2 = T2 * Y */ + if ((err = pstm_mul_comba(pool, &t2, &y, &t2, paD, paDlen)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &t2, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + /* Y = T2 - T1 */ + if ((err = pstm_sub(&t2, &t1, &y)) != PS_SUCCESS) { goto done; } + if (pstm_cmp_d(&y, 0) == PSTM_LT) { + if ((err = pstm_add(&y, modulus, &y)) != PS_SUCCESS) { goto done; } + } + /* Y = Y/2 */ + if (pstm_isodd(&y)) { + if ((err = pstm_add(&y, modulus, &y)) != PS_SUCCESS) { goto done; } + } + if ((err = pstm_div_2(&y, &y)) != PS_SUCCESS) { goto done; } + + if ((err = pstm_copy(&x, &R->x)) != PS_SUCCESS) { goto done; } + if ((err = pstm_copy(&y, &R->y)) != PS_SUCCESS) { goto done; } + if ((err = pstm_copy(&z, &R->z)) != PS_SUCCESS) { goto done; } + + err = PS_SUCCESS; + +done: + pstm_clear(&z); +ERR_Y: + pstm_clear(&y); +ERR_X: + pstm_clear(&x); +ERR_T2: + pstm_clear(&t2); +ERR_T1: + pstm_clear(&t1); + if (paD) psFree(paD, pool); + return err; +} + + +/******************************************************************************/ +/** + Double an ECC point + @param[in] P The point to double + @param[out] R The destination of the double + @param[in] modulus The modulus of the field the ECC curve is in + @param[in] mp The "b" value from montgomery_setup() + @param[in] A The "A" of the field the ECC curve is in + @return PS_SUCCESS on success +*/ +static int32_t eccProjectiveDblPoint(psPool_t *pool, const psEccPoint_t *P, + psEccPoint_t *R, const pstm_int *modulus, const pstm_digit *mp, + const pstm_int *A) +{ + pstm_int t1, t2; + pstm_digit *paD; + uint32 paDlen; + int32 err, initSize; + + + if (P != R) { + if (pstm_copy(&P->x, &R->x) < 0) { return PS_MEM_FAIL; } + if (pstm_copy(&P->y, &R->y) < 0) { return PS_MEM_FAIL; } + if (pstm_copy(&P->z, &R->z) < 0) { return PS_MEM_FAIL; } + } + + initSize = R->x.used; + if (R->y.used > initSize) { initSize = R->y.used; } + if (R->z.used > initSize) { initSize = R->z.used; } + + if (pstm_init_size(pool, &t1, (initSize * 2) + 1) < 0) { + return PS_MEM_FAIL; + } + if (pstm_init_size(pool, &t2, (initSize * 2) + 1) < 0) { + pstm_clear(&t1); + return PS_MEM_FAIL; + } + +/* + Pre-allocated digit. Used for mul, sqr, AND reduce + TODO: haven't fully explored max possible paDlen +*/ + paDlen = (modulus->used*2+1) * sizeof(pstm_digit); + if ((paD = psMalloc(pool, paDlen)) == NULL) { + err = PS_MEM_FAIL; + goto done; + } + + /* t1 = Z * Z */ + if ((err = pstm_sqr_comba(pool, &R->z, &t1, paD, paDlen)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &t1, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + /* Z = Y * Z */ + if ((err = pstm_mul_comba(pool, &R->z, &R->y, &R->z, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &R->z, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + /* Z = 2Z */ + if ((err = pstm_add(&R->z, &R->z, &R->z)) != PS_SUCCESS) { goto done; } + if (pstm_cmp(&R->z, modulus) != PSTM_LT) { + if ((err = pstm_sub(&R->z, modulus, &R->z)) != PS_SUCCESS) { + goto done; + } + } + + // compute into T1 M=3(X+Z^2)(X-Z^2) + if (A == NULL) { + /* T2 = X - T1 */ + if ((err = pstm_sub(&R->x, &t1, &t2)) != PS_SUCCESS) { goto done; } + if (pstm_cmp_d(&t2, 0) == PSTM_LT) { + if ((err = pstm_add(&t2, modulus, &t2)) != PS_SUCCESS) { goto done; } + } + /* T1 = X + T1 */ + if ((err = pstm_add(&t1, &R->x, &t1)) != PS_SUCCESS) { goto done; } + if (pstm_cmp(&t1, modulus) != PSTM_LT) { + if ((err = pstm_sub(&t1, modulus, &t1)) != PS_SUCCESS) { goto done; } + } + /* T2 = T1 * T2 */ + if ((err = pstm_mul_comba(pool, &t1, &t2, &t2, paD, paDlen)) != PS_SUCCESS){ + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &t2, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + /* T1 = 2T2 */ + if ((err = pstm_add(&t2, &t2, &t1)) != PS_SUCCESS) { goto done; } + if (pstm_cmp(&t1, modulus) != PSTM_LT) { + if ((err = pstm_sub(&t1, modulus, &t1)) != PS_SUCCESS) { goto done; } + } + /* T1 = T1 + T2 */ + if ((err = pstm_add(&t1, &t2, &t1)) != PS_SUCCESS) { goto done; } + if (pstm_cmp(&t1, modulus) != PSTM_LT) { + if ((err = pstm_sub(&t1, modulus, &t1)) != PS_SUCCESS) { goto done; } + } + } else { + /* compute into T1 M=3X^2 + A Z^4 */ + pstm_int t3, t4; + + if (pstm_init_size(pool, &t3, (initSize * 2) + 1) < 0) { + return PS_MEM_FAIL; + } + if (pstm_init_size(pool, &t4, (initSize * 2) + 1) < 0) { + pstm_clear(&t3); + return PS_MEM_FAIL; + } + + /* T3 = X * X */ + if ((err = pstm_sqr_comba(pool, &R->x, &t3, paD, paDlen)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &t3, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + + /* T4 = 2T3 */ + if ((err = pstm_add(&t3, &t3, &t4)) != PS_SUCCESS) { goto done; } + if (pstm_cmp(&t4, modulus) != PSTM_LT) { + if ((err = pstm_sub(&t4, modulus, &t4)) != PS_SUCCESS) { goto done; } + } + + /* T3 = T3 + T4 */ + if ((err = pstm_add(&t3, &t4, &t3)) != PS_SUCCESS) { goto done; } + if (pstm_cmp(&t3, modulus) != PSTM_LT) { + if ((err = pstm_sub(&t3, modulus, &t3)) != PS_SUCCESS) { goto done; } + } + + /* T4 = T1 * T1 */ + if ((err = pstm_sqr_comba(pool, &t1, &t4, paD, paDlen)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_mod(pool, &t4, modulus, &t4)) != PS_SUCCESS) { goto done; } + + /* T4 = T4 * A */ + if ((err = pstm_mul_comba(pool, &t4, A, &t4, paD, paDlen)) != PS_SUCCESS){ + goto done; + } + + if ((err = pstm_montgomery_reduce(pool, &t4, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + + /* T1 = T3 + T4 */ + if ((err = pstm_add(&t3, &t4, &t1)) != PS_SUCCESS) { goto done; } + if (pstm_cmp(&t1, modulus) != PSTM_LT) { + if ((err = pstm_sub(&t1, modulus, &t1)) != PS_SUCCESS) { goto done; } + } + + pstm_clear_multi(&t3, &t4, NULL, NULL, NULL, NULL, NULL, NULL); + } + + /* Y = 2Y */ + if ((err = pstm_add(&R->y, &R->y, &R->y)) != PS_SUCCESS) { goto done; } + if (pstm_cmp(&R->y, modulus) != PSTM_LT) { + if ((err = pstm_sub(&R->y, modulus, &R->y)) != PS_SUCCESS) { goto done;} + } + /* Y = Y * Y */ + if ((err = pstm_sqr_comba(pool, &R->y, &R->y, paD, paDlen)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &R->y, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + /* T2 = Y * Y */ + if ((err = pstm_sqr_comba(pool, &R->y, &t2, paD, paDlen)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &t2, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + /* T2 = T2/2 */ + if (pstm_isodd(&t2)) { + if ((err = pstm_add(&t2, modulus, &t2)) != PS_SUCCESS) { goto done; } + } + if ((err = pstm_div_2(&t2, &t2)) != PS_SUCCESS) { goto done; } + /* Y = Y * X */ + if ((err = pstm_mul_comba(pool, &R->y, &R->x, &R->y, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &R->y, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + + /* X = T1 * T1 */ + if ((err = pstm_sqr_comba(pool, &t1, &R->x, paD, paDlen)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &R->x, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + /* X = X - Y */ + if ((err = pstm_sub(&R->x, &R->y, &R->x)) != PS_SUCCESS) { goto done; } + if (pstm_cmp_d(&R->x, 0) == PSTM_LT) { + if ((err = pstm_add(&R->x, modulus, &R->x)) != PS_SUCCESS) { goto done;} + } + /* X = X - Y */ + if ((err = pstm_sub(&R->x, &R->y, &R->x)) != PS_SUCCESS) { goto done; } + if (pstm_cmp_d(&R->x, 0) == PSTM_LT) { + if ((err = pstm_add(&R->x, modulus, &R->x)) != PS_SUCCESS) { goto done;} + } + + /* Y = Y - X */ + if ((err = pstm_sub(&R->y, &R->x, &R->y)) != PS_SUCCESS) { goto done; } + if (pstm_cmp_d(&R->y, 0) == PSTM_LT) { + if ((err = pstm_add(&R->y, modulus, &R->y)) != PS_SUCCESS) { goto done;} + } + /* Y = Y * T1 */ + if ((err = pstm_mul_comba(pool, &R->y, &t1, &R->y, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &R->y, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + /* Y = Y - T2 */ + if ((err = pstm_sub(&R->y, &t2, &R->y)) != PS_SUCCESS) { goto done; } + if (pstm_cmp_d(&R->y, 0) == PSTM_LT) { + if ((err = pstm_add(&R->y, modulus, &R->y)) != PS_SUCCESS) { goto done;} + } + + err = PS_SUCCESS; +done: + pstm_clear_multi(&t1, &t2, NULL, NULL, NULL, NULL, NULL, NULL); + if (paD) psFree(paD, pool); + return err; +} + + +/******************************************************************************/ +/** + Allocate a new ECC point. + @return A newly allocated point or NULL on error +*/ +static psEccPoint_t *eccNewPoint(psPool_t *pool, short size) +{ + psEccPoint_t *p = NULL; + + p = psMalloc(pool, sizeof(psEccPoint_t)); + if (p == NULL) { + return NULL; + } + p->pool = pool; + if (size == 0) { + if (pstm_init(pool, &p->x) != PSTM_OKAY) { + return NULL; + } + if (pstm_init(pool, &p->y) != PSTM_OKAY) { + pstm_clear(&p->x); + return NULL; + } + if (pstm_init(pool, &p->z) != PSTM_OKAY) { + pstm_clear(&p->x); + pstm_clear(&p->y); + return NULL; + } + } else { + if (pstm_init_size(pool, &p->x, size) != PSTM_OKAY) { + return NULL; + } + if (pstm_init_size(pool, &p->y, size) != PSTM_OKAY) { + pstm_clear(&p->x); + return NULL; + } + if (pstm_init_size(pool, &p->z, size) != PSTM_OKAY) { + pstm_clear(&p->x); + pstm_clear(&p->y); + return NULL; + } + } + return p; +} + +/** + Free an ECC point from memory. + @param p The point to free +*/ +static void eccFreePoint(psEccPoint_t *p) +{ + if (p != NULL) { + pstm_clear(&p->x); + pstm_clear(&p->y); + pstm_clear(&p->z); + psFree(p, p->pool); + } +} + +/** + Map a projective jacbobian point back to affine space + @param[in,out] P [in/out] The point to map + @param[in] modulus The modulus of the field the ECC curve is in + @param[in] mp The "b" value from montgomery_setup() + @return PS_SUCCESS on success + */ +static int32_t eccMap(psPool_t *pool, psEccPoint_t *P, const pstm_int *modulus, + const pstm_digit *mp) +{ + pstm_int t1, t2; + pstm_digit *paD; + int32 err; + uint32 paDlen; + + if (pstm_init_size(pool, &t1, P->x.alloc) < 0) { + return PS_MEM_FAIL; + } + if (pstm_init_size(pool, &t2, P->x.alloc) < 0) { + pstm_clear(&t1); + return PS_MEM_FAIL; + } + + /* Pre-allocated digit. Used for mul, sqr, AND reduce */ + paDlen = (modulus->used*2+1) * sizeof(pstm_digit); + if ((paD = psMalloc(pool, paDlen)) == NULL) { + err = PS_MEM_FAIL; + goto done; + } + + /* first map z back to normal */ + if ((err = pstm_montgomery_reduce(pool, &P->z, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + + /* get 1/z */ + if ((err = pstm_invmod(pool, &P->z, modulus, &t1)) != PS_SUCCESS) { + goto done; + } + + /* get 1/z^2 and 1/z^3 */ + if ((err = pstm_sqr_comba(pool, &t1, &t2, paD, paDlen)) != PS_SUCCESS) { + goto done; + } + if ((err = pstm_mod(pool, &t2, modulus, &t2)) != PS_SUCCESS) { goto done; } + if ((err = pstm_mul_comba(pool, &t1, &t2, &t1, paD, paDlen)) != PS_SUCCESS){ + goto done; + } + if ((err = pstm_mod(pool, &t1, modulus, &t1)) != PS_SUCCESS) { goto done; } + + /* multiply against x/y */ + if ((err = pstm_mul_comba(pool, &P->x, &t2, &P->x, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &P->x, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + if ((err = pstm_mul_comba(pool, &P->y, &t1, &P->y, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + if ((err = pstm_montgomery_reduce(pool, &P->y, modulus, *mp, paD, paDlen)) + != PS_SUCCESS) { + goto done; + } + pstm_set(&P->z, 1); + err = PS_SUCCESS; +done: + pstm_clear_multi(&t1, &t2, NULL, NULL, NULL, NULL, NULL, NULL); + if (paD) psFree(paD, pool); + return err; +} + +/******************************************************************************/ +/** + Verify an ECDSA signature. + + @param pool Memory pool + @param[in] key Public key to use for signature validation + @param[in] buf Data that is signed by private 'key' + @param[in] buflen Length in bytes of 'buf' + @param[in] sig Signature of 'buf' by the private key pair of 'key' + @param[in] siglen Length in bytes of 'sig' + @param[out] status Result of the signature check. 1 on success, -1 on + non-matching signature. + @param usrData Data used by some hardware crypto. Can be NULL. + @return < 0 on failure. Also 'status'. + */ +int32_t psEccDsaVerify(psPool_t *pool, const psEccKey_t *key, + const unsigned char *buf, uint16_t buflen, + const unsigned char *sig, uint16_t siglen, + int32_t *status, void *usrData) +{ + psEccPoint_t *mG, *mQ; + pstm_digit mp; + pstm_int *A = NULL; + pstm_int v, w, u1, u2, e, p, m, r, s; + const unsigned char *c, *end; + int32_t err, radlen; + uint16_t len; + + /* default to invalid signature */ + *status = -1; + + c = sig; + end = c + siglen; + + if ((err = getAsnSequence(&c, (uint16_t)(end - c), &len)) < 0) { + psTraceCrypto("ECDSA subject signature parse failure 1\n"); + return err; + } + if ((err = pstm_read_asn(pool, &c, (uint16_t)(end - c), &r)) < 0) { + psTraceCrypto("ECDSA subject signature parse failure 2\n"); + return err; + } + if ((err = pstm_read_asn(pool, &c, (uint16_t)(end - c), &s)) < 0) { + psTraceCrypto("ECDSA subject signature parse failure 3\n"); + pstm_clear(&r); + return err; + } + + + /* allocate ints */ + radlen = key->curve->size * 2; + if (pstm_init_for_read_unsigned_bin(pool, &p, key->curve->size) < 0) { + pstm_clear(&s); + pstm_clear(&r); + return PS_MEM_FAIL; + } + err = PS_MEM_FAIL; + if (pstm_init_for_read_unsigned_bin(pool, &m, key->curve->size) < 0) { + goto LBL_P; + } + if (pstm_init_size(pool, &v, key->pubkey.x.alloc) < 0) { + goto LBL_M; + } + if (pstm_init_size(pool, &w, s.alloc) < 0) { + goto LBL_V; + } + /* Shouldn't have signed more data than the key length. Truncate if so */ + if (buflen > key->curve->size) { + buflen = key->curve->size; + } + if (pstm_init_for_read_unsigned_bin(pool, &e, buflen) < 0) { + goto LBL_W; + } + if (pstm_init_size(pool, &u1, e.alloc + w.alloc) < 0) { + goto LBL_E; + } + if (pstm_init_size(pool, &u2, r.alloc + w.alloc) < 0) { + goto LBL_U1; + } + + /* allocate points */ + if ((mG = eccNewPoint(pool, key->pubkey.x.alloc * 2)) == NULL) { + goto LBL_U2; + } + if ((mQ = eccNewPoint(pool, key->pubkey.x.alloc * 2)) == NULL) { + goto LBL_MG; + } + + /* get the order */ + if ((err = pstm_read_radix(pool, &p, key->curve->order, radlen, 16)) + != PS_SUCCESS) { + goto error; + } + + /* get the modulus */ + if ((err = pstm_read_radix(pool, &m, key->curve->prime, radlen, 16)) + != PS_SUCCESS) { + goto error; + } + + /* check for zero */ + if (pstm_iszero(&r) || pstm_iszero(&s) || pstm_cmp(&r, &p) != PSTM_LT || + pstm_cmp(&s, &p) != PSTM_LT) { + err = PS_PARSE_FAIL; + goto error; + } + + /* read data */ + if ((err = pstm_read_unsigned_bin(&e, buf, buflen)) != PS_SUCCESS) { + goto error; + } + + /* w = s^-1 mod n */ + if ((err = pstm_invmod(pool, &s, &p, &w)) != PS_SUCCESS) { + goto error; + } + + /* u1 = ew */ + if ((err = pstm_mulmod(pool, &e, &w, &p, &u1)) != PS_SUCCESS) { + goto error; + } + + /* u2 = rw */ + if ((err = pstm_mulmod(pool, &r, &w, &p, &u2)) != PS_SUCCESS) { + goto error; + } + + /* find mG and mQ */ + if ((err = pstm_read_radix(pool, &mG->x, key->curve->Gx, radlen, 16)) + != PS_SUCCESS) { + goto error; + } + if ((err = pstm_read_radix(pool, &mG->y, key->curve->Gy, radlen, 16)) + != PS_SUCCESS) { + goto error; + } + pstm_set(&mG->z, 1); + + if ((err = pstm_copy(&key->pubkey.x, &mQ->x)) != PS_SUCCESS) { + goto error; + } + if ((err = pstm_copy(&key->pubkey.y, &mQ->y)) != PS_SUCCESS) { + goto error; + } + if ((err = pstm_copy(&key->pubkey.z, &mQ->z)) != PS_SUCCESS) { + goto error; + } + + if (key->curve->isOptimized == 0) + { + if ((A = psMalloc(pool, sizeof(pstm_int))) == NULL) { + goto error; + } + + if (pstm_init_for_read_unsigned_bin(pool, A, key->curve->size) < 0) { + goto error; + } + + if ((err = pstm_read_radix(pool, A, key->curve->A, + key->curve->size * 2, 16)) + != PS_SUCCESS) { + goto error; + } + } + + /* compute u1*mG + u2*mQ = mG */ + if ((err = eccMulmod(pool, &u1, mG, mG, &m, 0, A)) != PS_SUCCESS) { + goto error; + } + if ((err = eccMulmod(pool, &u2, mQ, mQ, &m, 0, A)) != PS_SUCCESS) { + goto error; + } + + /* find the montgomery mp */ + if ((err = pstm_montgomery_setup(&m, &mp)) != PS_SUCCESS) { + goto error; + } + + /* add them */ + if ((err = eccProjectiveAddPoint(pool, mQ, mG, mG, &m, &mp, A)) != PS_SUCCESS) { + goto error; + } + + /* reduce */ + if ((err = eccMap(pool, mG, &m, &mp)) != PS_SUCCESS) { + goto error; + } + + /* v = X_x1 mod n */ + if ((err = pstm_mod(pool, &mG->x, &p, &v)) != PS_SUCCESS) { + goto error; + } + + /* does v == r */ + if (pstm_cmp(&v, &r) == PSTM_EQ) { + *status = 1; + } + + /* clear up and return */ + err = PS_SUCCESS; + +error: + if (A) { + pstm_clear(A); + psFree(A, pool); + } + + eccFreePoint(mQ); +LBL_MG: + eccFreePoint(mG); +LBL_U2: + pstm_clear(&u2); +LBL_U1: + pstm_clear(&u1); +LBL_E: + pstm_clear(&e); +LBL_W: + pstm_clear(&w); +LBL_V: + pstm_clear(&v); +LBL_M: + pstm_clear(&m); +LBL_P: + pstm_clear(&p); + pstm_clear(&s); + pstm_clear(&r); + return err; +} + +/** + Sign a message digest. + @param pool Memory pool + @param[in] key Private ECC key + @param[in] in The data to sign + @param[in] inlen The length in bytes of 'in' + @param[out] out The destination for the signature + @param[in,out] outlen The max size and resulting size of the signature + @param[in] includeSize Pass 1 to include size prefix in output. + @param usrData Implementation specific data. Can pass NULL. + @return PS_SUCCESS if successful + + @note TLS does use the size prefix in output. +*/ +int32_t psEccDsaSign(psPool_t *pool, const psEccKey_t *privKey, + const unsigned char *buf, uint16_t buflen, + unsigned char *sig, uint16_t *siglen, + uint8_t includeSize, void *usrData) +{ + psEccKey_t pubKey; /* @note Large on the stack */ + pstm_int r, s; + pstm_int e, p; + uint16_t radlen; + int32_t err; + uint16_t olen, rLen, sLen; + uint32_t rflag, sflag, sanity; + unsigned char *negative; + + rflag = sflag = 0; + err = 0; + + /* is this a private key? */ + if (privKey->type != PS_PRIVKEY) { + return PS_ARG_FAIL; + } + + /* Can't sign more data than the key length. Truncate if so */ + if (buflen > privKey->curve->size) { + buflen = privKey->curve->size; + } + err = PS_MEM_FAIL; + + radlen = privKey->curve->size * 2; + if (pstm_init_for_read_unsigned_bin(pool, &p, privKey->curve->size) < 0) { + return PS_MEM_FAIL; + } + if (pstm_init_for_read_unsigned_bin(pool, &e, buflen) < 0) { + goto LBL_P; + } + if (pstm_init_size(pool, &r, p.alloc) < 0) { + goto LBL_E; + } + if (pstm_init_size(pool, &s, p.alloc) < 0) { + goto LBL_R; + } + + if ((err = pstm_read_radix(pool, &p, privKey->curve->order, radlen, + 16)) != PS_SUCCESS) { + goto errnokey; + } + if ((err = pstm_read_unsigned_bin(&e, buf, buflen)) != PS_SUCCESS) { + goto errnokey; + } + + /* make up a key and export the public copy */ + sanity = 0; + for (;;) { + if (sanity++ > 99) { + psTraceCrypto("ECC Signature sanity exceeded. Verify PRNG output.\n"); + err = PS_PLATFORM_FAIL; /* possible problem with prng */ + goto errnokey; + } + if ((err = psEccGenKey(pool, &pubKey, privKey->curve, usrData)) + != PS_SUCCESS) { + goto errnokey; + } + /* find r = x1 mod n */ + if ((err = pstm_mod(pool, &pubKey.pubkey.x, &p, &r)) != PS_SUCCESS) { + goto error; + } + + if (pstm_iszero(&r) == PS_TRUE) { + psEccClearKey(&pubKey); + } else { + /* find s = (e + xr)/k */ + if ((err = pstm_invmod(pool, &pubKey.k, &p, &pubKey.k)) != + PS_SUCCESS) { + goto error; /* k = 1/k */ + } + if ((err = pstm_mulmod(pool, &privKey->k, &r, &p, &s)) + != PS_SUCCESS) { + goto error; /* s = xr */ + } + if ((err = pstm_add(&e, &s, &s)) != PS_SUCCESS) { + goto error; /* s = e + xr */ + } + if ((err = pstm_mod(pool, &s, &p, &s)) != PS_SUCCESS) { + goto error; /* s = e + xr */ + } + if ((err = pstm_mulmod(pool, &s, &pubKey.k, &p, &s)) + != PS_SUCCESS) { + goto error; /* s = (e + xr)/k */ + } + psEccClearKey(&pubKey); + + rLen = pstm_unsigned_bin_size(&r); + sLen = pstm_unsigned_bin_size(&s); + + /* Signatures can be smaller than the keysize but keep it sane */ + if (((rLen + 2) >= privKey->curve->size) && + ((sLen + 2) >= privKey->curve->size)) { + if (pstm_iszero(&s) == PS_FALSE) { + break; + } + } + } + } + + /* If r or s has the high bit set, the ASN.1 encoding should include + a leading 0x0 byte to prevent it from being "negative". */ + negative = (unsigned char*)r.dp; + if (negative[rLen - 1] & 0x80) { + rLen++; + rflag = 1; + } + negative = (unsigned char*)s.dp; + if (negative[sLen - 1] & 0x80) { /* GOOD ONE */ + sLen++; + sflag = 1; + } + olen = 6 + rLen + sLen; + + /* Handle lengths longer than 128.. but still only handling up to 256 */ + if (olen - 3 >= 128) { + olen++; + } + + /* TLS uses a two byte length specifier. Others sometimes do not */ + if (includeSize) { + if (olen + 2 > *siglen) { + err = -1; + goto errnokey; + } + + *sig = olen >> 8 & 0xFF; sig++; + *sig = olen & 0xFF; sig++; + } else { + if (olen > *siglen) { + err = -1; + goto errnokey; + } + } + + *sig = ASN_CONSTRUCTED | ASN_SEQUENCE; sig++; + + if ((olen - 3) >= 128) { + *sig = 0x81; sig++; /* high bit to indicate 'long' and low for byte count */ + *sig = (olen & 0xFF) - 3; sig++; + *siglen = 1; + } else { + *sig = (olen & 0xFF) - 2; sig++; + *siglen = 0; + } + *sig = ASN_INTEGER; sig++; + *sig = rLen & 0xFF; sig++; + if (includeSize) { + *siglen += 6; + } else { + *siglen += 4; + } + if (rflag) { + *sig = 0x0; sig++; + } + if ((err = pstm_to_unsigned_bin(pool, &r, sig)) != PSTM_OKAY) { + goto errnokey; + } + sig += rLen - rflag; /* Moved forward rflag already */ + *siglen += rLen; + *sig = ASN_INTEGER; sig++; + *sig = sLen & 0xFF; sig++; + if (sflag) { + *sig = 0x0; sig++; + } + if ((err = pstm_to_unsigned_bin(pool, &s, sig)) != PSTM_OKAY) { + goto error; + } + sig += sLen - sflag; /* Moved forward sflag already */ + *siglen += sLen + 2; + + err = PS_SUCCESS; + goto errnokey; + +error: + psEccClearKey(&pubKey); +errnokey: + pstm_clear(&s); +LBL_R: + pstm_clear(&r); +LBL_E: + pstm_clear(&e); +LBL_P: + pstm_clear(&p); + return err; +} + + +#endif /* USE_MATRIX_ECC */ + diff --git a/crypto/pubkey/pubkey.c b/crypto/pubkey/pubkey.c new file mode 100644 index 0000000..75dd98a --- /dev/null +++ b/crypto/pubkey/pubkey.c @@ -0,0 +1,184 @@ +/** + * @file pubkey.c + * @version $Format:%h%d$ + * + * Public and Private key operations shared by crypto implementations. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#if defined(USE_RSA) || defined(USE_ECC) + +/******************************************************************************/ + +int32_t psInitPubKey(psPool_t *pool, psPubKey_t *key, uint8_t type) +{ + if (!key) { + return PS_ARG_FAIL; + } + switch (type) { +#ifdef USE_RSA + case PS_RSA: + psRsaInitKey(pool, &key->key.rsa); + break; +#endif +#ifdef USE_ECC + case PS_ECC: + psEccInitKey(pool, &key->key.ecc, NULL); + break; +#endif + default: + break; + } + key->pool = pool; + key->type = type; + key->keysize = 0; + return PS_SUCCESS; +} + +/******************************************************************************/ + +void psClearPubKey(psPubKey_t *key) +{ + if (!key) { + return; + } + switch (key->type) { +#ifdef USE_RSA + case PS_RSA: + psRsaClearKey(&key->key.rsa); + break; +#endif +#ifdef USE_ECC + case PS_ECC: + psEccClearKey(&key->key.ecc); + break; +#endif + default: + break; + } + key->pool = NULL; + key->keysize = 0; + key->type = 0; +} + +int32_t psNewPubKey(psPool_t *pool, uint8_t type, psPubKey_t **key) +{ + int32_t rc; + if ((*key = psMalloc(pool, sizeof(psPubKey_t))) == NULL) { + return PS_MEM_FAIL; + } + + if ((rc = psInitPubKey(pool, *key, type)) < 0) { + psFree(*key, pool); + } + return rc; +} + +void psDeletePubKey(psPubKey_t **key) +{ + psClearPubKey(*key); + psFree(*key, NULL); + *key = NULL; +} + +#ifdef MATRIX_USE_FILE_SYSTEM +#if defined(USE_ECC) && defined(USE_RSA) +/* Trial and error private key parse for when ECC or RSA is unknown. + + pemOrDer should be 1 if PEM + + Return codes: + 1 RSA key + 2 ECC key + -1 error +*/ +int32_t psParseUnknownPrivKey(psPool_t *pool, int pemOrDer, char *keyfile, + char *password, psPubKey_t *privkey) +{ + psRsaKey_t *rsakey; + psEccKey_t *ecckey; + int keytype; + unsigned char *keyBuf; + int32 keyBufLen; + + privkey->keysize = 0; + rsakey = &privkey->key.rsa; + ecckey = &privkey->key.ecc; + if (pemOrDer == 1) { + if (pkcs1ParsePrivFile(pool, keyfile, password, rsakey) + < PS_SUCCESS) { + if (psEccParsePrivFile(pool, keyfile, password, ecckey) + < PS_SUCCESS) { + psTraceStrCrypto("Unable to parse private key file %s\n", + keyfile); + return -1; + } + keytype = 2; + } else { + keytype = 1; + } + } else { + if (psGetFileBuf(pool, keyfile, &keyBuf, &keyBufLen) < PS_SUCCESS) { + psTraceStrCrypto("Unable to open private key file %s\n", keyfile); + return -1; + } + if (psRsaParsePkcs1PrivKey(pool, keyBuf, keyBufLen, rsakey) + < PS_SUCCESS) { + if (psEccParsePrivKey(pool, keyBuf, keyBufLen, ecckey, NULL) + < PS_SUCCESS) { + psTraceCrypto("Unable to parse private key\n"); + psFree(keyBuf, pool); + return -1; + } + keytype = 2; + } else { + keytype = 1; + } + psFree(keyBuf, pool); + } + + if (keytype == 1) { + privkey->type = PS_RSA; + privkey->keysize = psRsaSize(&privkey->key.rsa); + } else { + privkey->type = PS_ECC; + privkey->keysize = psEccSize(&privkey->key.ecc); + } + privkey->pool = pool; + return keytype; +} +#endif /* USE_ECC && USE_RSA */ +#endif /* MATRIX_USE_FILE_SYSTEM */ + +/******************************************************************************/ + +#endif /* USE_RSA || USE_ECC */ + diff --git a/crypto/pubkey/pubkey.h b/crypto/pubkey/pubkey.h new file mode 100644 index 0000000..5a57b91 --- /dev/null +++ b/crypto/pubkey/pubkey.h @@ -0,0 +1,208 @@ +/** + * @file pubkey.h + * @version $Format:%h%d$ + * + * Public and Private key header. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_PS_PUBKEY +#define _h_PS_PUBKEY + +/******************************************************************************/ + +#include "pubkey_matrix.h" +#ifdef USE_OPENSSL_CRYPTO +#include "pubkey_openssl.h" +#endif + +/******************************************************************************/ + +#ifdef USE_RSA +/** + The included pubkey_* header must define: + typedef ... psRsaKey_t; + and + PS_RSA_STATIC_INIT +*/ +#ifndef PS_RSA_STATIC_INIT +#define PS_RSA_STATIC_INIT { .size = NULL } +#endif + +#endif /* USE_RSA */ + +/******************************************************************************/ + +#ifdef USE_ECC + +#define ECC_MAXSIZE 132 /* max private key size */ + +/* NOTE: In MatrixSSL usage, the ecFlags are 24 bits only */ +#define IS_SECP192R1 0x00000001 +#define IS_SECP224R1 0x00000002 +#define IS_SECP256R1 0x00000004 +#define IS_SECP384R1 0x00000008 +#define IS_SECP521R1 0x00000010 +/* WARNING: Public points on Brainpool curves are not validated */ +#define IS_BRAIN224R1 0x00010000 +#define IS_BRAIN256R1 0x00020000 +#define IS_BRAIN384R1 0x00040000 +#define IS_BRAIN512R1 0x00080000 +/* TLS needs one bit of info (last bit) */ +#define IS_RECVD_EXT 0x00800000 + +/** + @see https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 +*/ +enum { + IANA_SECP192R1 = 19, + IANA_SECP224R1 = 21, + IANA_SECP256R1 = 23, + IANA_SECP384R1, + IANA_SECP521R1, + IANA_BRAIN256R1, + IANA_BRAIN384R1, + IANA_BRAIN512R1, + + IANA_BRAIN224R1 = 255 /**< @note this is not defined by IANA */ +}; + +/** + @see ANSI X9.62 or X9.63 +*/ +enum { + ANSI_INFINITY = 0, + ANSI_COMPRESSED0 = 2, + ANSI_COMPRESSED1, + ANSI_UNCOMPRESSED, + ANSI_HYBRID0 = 6, + ANSI_HYBRID1 +}; + +/** + The included pubkey_* header must define the following. + typedef ... psEccCurve_t; + typedef ... psEccPoint_t; + typedef ... psEccKey_t; + and + PS_ECC_STATIC_INIT + and implement the following functions. +*/ +#ifndef PS_ECC_STATIC_INIT +#define PS_ECC_STATIC_INIT { .type = 0 } +#endif +extern void psGetEccCurveIdList(unsigned char *curveList, uint8_t *len); +extern void userSuppliedEccList(unsigned char *curveList, uint8_t *len, + uint32_t curves); +extern uint32_t compiledInEcFlags(void); +extern int32_t getEcPubKey(psPool_t *pool, const unsigned char **pp, uint16_t len, + psEccKey_t *pubKey, unsigned char sha1KeyHash[SHA1_HASH_SIZE]); + +extern int32_t getEccParamById(uint16_t curveId, const psEccCurve_t **curve); +extern int32_t getEccParamByName(const char *curveName, + const psEccCurve_t **curve); +extern int32_t getEccParamByOid(uint32_t oid, const psEccCurve_t **curve); + +#endif + +/******************************************************************************/ + +#ifdef USE_DH +/** + The included pubkey_* header must define: + typedef ... psDhParams_t; + typedef ... psDhKey_t; + and + PS_DH_STATIC_INIT +*/ +#ifndef PS_DH_STATIC_INIT +#define PS_DH_STATIC_INIT { .type = 0 } +#endif + +#endif + +/******************************************************************************/ + +/** Public or private key */ +enum PACKED { + PS_PUBKEY = 1, + PS_PRIVKEY +}; + +/** Public Key types for psPubKey_t */ +enum PACKED { + PS_NONE = 0, + PS_RSA, + PS_ECC, + PS_DH +}; + +/** Signature types */ +enum PACKED { + RSA_TYPE_SIG = 5, + ECDSA_TYPE_SIG, + RSAPSS_TYPE_SIG +}; + +/** + Univeral public key type. + The pubKey name comes from the generic public-key crypto terminology and + does not mean these key are restricted to the public side only. These + may be private keys. +*/ +typedef struct { +#if defined(USE_RSA) || defined(USE_ECC) + union { +#ifdef USE_RSA + psRsaKey_t rsa; +#endif +#ifdef USE_ECC + psEccKey_t ecc; +#endif +#ifdef USE_DH + psDhKey_t dh; +#endif + } key; +#endif + psPool_t *pool; + uint16_t keysize; /* in bytes. 512 max for RSA 4096 */ + uint8_t type; /* PS_RSA, PS_ECC, PS_DH */ +} psPubKey_t; + +extern int32_t pkcs1Pad(const unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + uint8_t cryptType, void *userPtr); +extern int32_t pkcs1Unpad(const unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + uint8_t decryptType); + +/******************************************************************************/ + +#endif /* _h_PS_PUBKEY */ + diff --git a/crypto/pubkey/pubkey_matrix.h b/crypto/pubkey/pubkey_matrix.h new file mode 100644 index 0000000..83faabf --- /dev/null +++ b/crypto/pubkey/pubkey_matrix.h @@ -0,0 +1,117 @@ +/** + * @file pubkey_matrix.h + * @version $Format:%h%d$ + * + * MatrixSSL Crypto Implementation for RSA, DH and ECC. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_MATRIX_PUBKEY +#define _h_MATRIX_PUBKEY + +/******************************************************************************/ + +#ifdef USE_MATRIX_RSA + +typedef struct { + pstm_int e, d, N, qP, dP, dQ, p, q; + psPool_t *pool; + uint16_t size; /* Size of the key in bytes */ + uint8_t optimized; /* Set if optimized */ +} psRsaKey_t; + +#endif + +/******************************************************************************/ + +#ifdef USE_MATRIX_ECC + +/** + An ECC curve. + Including size, name, and domain parameters. +*/ +typedef struct { + uint8_t size; /**< The size of the curve in octets */ + uint16_t curveId; /**< IANA named curve id for TLS use */ + uint8_t isOptimized; /**< 1 if optimized with field param A=-3. */ + uint32_t OIDsum; /**< Internal Matrix OID */ + const char *name; /**< name of curve */ + /* These below constitute the domain parameters */ + const char *prime; /**< prime defining the curve field (ascii hex) */ + const char *A; /**< The field's A param (ascii hex) */ + const char *B; /**< The field's B param (ascii hex) */ + const char *order; /**< The order of the curve (ascii hex) */ + const char *Gx; /**< The x coordinate of the base point (ascii hex) */ + const char *Gy; /**< The y coordinate of the base point (ascii hex) */ +} psEccCurve_t; + +/** + A point on a ECC curve, stored in Jacbobian format such that + (x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine. +*/ +typedef struct { + pstm_int x; /* The x co-ordinate */ + pstm_int y; /* The y co-ordinate */ + pstm_int z; /* The z co-ordinate */ + psPool_t *pool; +} psEccPoint_t; + +typedef struct { + pstm_int k; /* The private key */ + psEccPoint_t pubkey; /* The public key */ + const psEccCurve_t *curve; /* pointer to named curve */ + psPool_t *pool; + uint8_t type; /* Type of key, PS_PRIVKEY or PS_PUBKEY */ +} psEccKey_t; + +#endif + +/******************************************************************************/ + +#ifdef USE_MATRIX_DH + +typedef struct { + pstm_int p; /* The Prime value */ + pstm_int g; /* The Generator/Base value */ + psPool_t *pool; + uint16_t size; /* Size of 'p' in bytes */ +} psDhParams_t; + +typedef struct { + pstm_int priv, pub; + uint16_t size; + uint8_t type; /* PS_PRIVKEY or PS_PUBKEY */ +} psDhKey_t; + +#endif + +/******************************************************************************/ + +#endif /* _h_MATRIX_PUBKEY */ + diff --git a/crypto/pubkey/pubkey_openssl.h b/crypto/pubkey/pubkey_openssl.h new file mode 100644 index 0000000..00b0d85 --- /dev/null +++ b/crypto/pubkey/pubkey_openssl.h @@ -0,0 +1,66 @@ +/** + * @file pubkey_openssl.h + * @version $Format:%h%d$ + * + * OpenSSL Layer for RSA, DH and ECC. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_OPENSSL_PUBKEY +#define _h_OPENSSL_PUBKEY + +/******************************************************************************/ +#ifdef USE_OPENSSL_RSA + + #include + +/* + typedef struct { + BIGNUM *n; // public modulus + BIGNUM *e; // public exponent + BIGNUM *d; // private exponent + BIGNUM *p; // secret prime factor + BIGNUM *q; // secret prime factor + BIGNUM *dmp1; // d mod (p-1) + BIGNUM *dmq1; // d mod (q-1) + BIGNUM *iqmp; // q^-1 mod p + // ... + } RSA; + */ + /** @note This type is a pointer, not the actual RSA structure */ + typedef RSA* psRsaKey_t; + + #define PS_RSA_STATIC_INIT NULL + +#endif + +/******************************************************************************/ + +#endif /* _h_OPENSSL_PUBKEY */ + diff --git a/crypto/pubkey/rsa.c b/crypto/pubkey/rsa.c new file mode 100644 index 0000000..7483715 --- /dev/null +++ b/crypto/pubkey/rsa.c @@ -0,0 +1,862 @@ +/** + * @file rsa.c + * @version $Format:%h%d$ + * + * RSA crypto. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +/******************************************************************************/ +/* TODO - the following functions are not implementation layer specific... + move to a common file? + + Matrix-specific starts at #ifdef USE_MATRIX_RSA +*/ + +#define ASN_OVERHEAD_LEN_RSA_SHA2 19 +#define ASN_OVERHEAD_LEN_RSA_SHA1 15 + +#ifdef USE_MATRIX_RSA +int32_t pubRsaDecryptSignedElement(psPool_t *pool, psRsaKey_t *key, + unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + void *data) +{ + unsigned char *c, *front, *end; + uint16_t outlenWithAsn, len, plen; + int32_t oi, rc; + + /* The issue here is that the standard RSA decryption routine requires + the user to know the output length (usually just a hash size). With + these "digitally signed elements" there is an algorithm + identifier surrounding the hash so we use the known magic numbers as + additional lengths of the wrapper since it is a defined ASN sequence, + ASN algorithm oid, and ASN octet string */ + if (outlen == SHA256_HASH_SIZE) { + outlenWithAsn = SHA256_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2; + } else if (outlen == SHA1_HASH_SIZE) { + outlenWithAsn = SHA1_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA1; + } else if (outlen == SHA384_HASH_SIZE) { + outlenWithAsn = SHA384_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2; + } else if (outlen == SHA512_HASH_SIZE) { + outlenWithAsn = SHA512_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2; + } else { + psTraceIntCrypto("Unsupported decryptSignedElement hash %d\n", outlen); + return PS_FAILURE; + } + + front = c = psMalloc(pool, outlenWithAsn); + if (front == NULL) { + return PS_MEM_FAIL; + } + + if ((rc = psRsaDecryptPub(pool, key, in, inlen, c, outlenWithAsn, data)) < 0) { + psFree(front, pool); + psTraceCrypto("Couldn't public decrypt signed element\n"); + return rc; + } + + /* Parse it */ + end = c + outlenWithAsn; + + /* @note Below we do a typecast to const to avoid a compiler warning, + although it should be fine to pass a non const pointer into an + api declaring it const, since it is just the API declaring the + contents will not be modified within the API. */ + if (getAsnSequence((const unsigned char **)&c, + (uint16_t)(end - c), &len) < 0) { + psTraceCrypto("Couldn't parse signed element sequence\n"); + psFree(front, pool); + return PS_FAILURE; + } + if (getAsnAlgorithmIdentifier((const unsigned char **)&c, + (uint16_t)(end - c), &oi, &plen) < 0) { + psTraceCrypto("Couldn't parse signed element octet string\n"); + psFree(front, pool); + return PS_FAILURE; + } + + if (oi == OID_SHA256_ALG) { + psAssert(outlen == SHA256_HASH_SIZE); + } else if (oi == OID_SHA1_ALG) { + psAssert(outlen == SHA1_HASH_SIZE); + } else if (oi == OID_SHA384_ALG) { + psAssert(outlen == SHA384_HASH_SIZE); + } else { + psAssert(outlen == SHA512_HASH_SIZE); + } + + /* Note the last test here requires the buffer to be exactly outlen bytes */ + if ((end - c) < 1 || (*c++ != ASN_OCTET_STRING) || + getAsnLength((const unsigned char **)&c, (uint16_t)(end - c), &len) < 0 || + (uint32_t)(end - c) != outlen) { + + psTraceCrypto("Couldn't parse signed element octet string\n"); + psFree(front, pool); + return PS_FAILURE; + } + /* Will finally be sitting at the hash now */ + memcpy(out, c, outlen); + psFree(front, pool); + return PS_SUCCESS; +} + +/* + ASN wrappers around standard hash signatures. These versions sign + a BER wrapped hash. Here are the well-defined wrappers: +*/ +static const unsigned char asn256dsWrap[] = {0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}; +#ifdef USE_SHA384 +static const unsigned char asn384dsWrap[] = {0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}; +#endif +static const unsigned char asn1dsWrap[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, + 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14}; + +int32_t privRsaEncryptSignedElement(psPool_t *pool, psRsaKey_t *key, + const unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + void *data) +{ + unsigned char c[MAX_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2]; + uint32_t inlenWithAsn; + + switch (inlen) { +#ifdef USE_SHA256 + case SHA256_HASH_SIZE: + inlenWithAsn = inlen + ASN_OVERHEAD_LEN_RSA_SHA2; + memcpy(c, asn256dsWrap, ASN_OVERHEAD_LEN_RSA_SHA2); + memcpy(c + ASN_OVERHEAD_LEN_RSA_SHA2, in, inlen); + break; +#endif +#ifdef USE_SHA1 + case SHA1_HASH_SIZE: + inlenWithAsn = inlen + ASN_OVERHEAD_LEN_RSA_SHA1; + memcpy(c, asn1dsWrap, ASN_OVERHEAD_LEN_RSA_SHA1); + memcpy(c + ASN_OVERHEAD_LEN_RSA_SHA1, in, inlen); + break; +#endif +#ifdef USE_SHA384 + case SHA384_HASH_SIZE: + inlenWithAsn = inlen + ASN_OVERHEAD_LEN_RSA_SHA2; + memcpy(c, asn384dsWrap, ASN_OVERHEAD_LEN_RSA_SHA2); + memcpy(c + ASN_OVERHEAD_LEN_RSA_SHA2, in, inlen); + break; +#endif + default: + return PS_UNSUPPORTED_FAIL; + } + if (psRsaEncryptPriv(pool, key, c, inlenWithAsn, + out, outlen, data) < 0) { + psTraceCrypto("privRsaEncryptSignedElement failed\n"); + memzero_s(c, sizeof(c)); + return PS_PLATFORM_FAIL; + } + memzero_s(c, sizeof(c)); + return PS_SUCCESS; +} + +/******************************************************************************/ +/** + Initialize an allocated RSA key. + + @note that in this case, a psRsaKey_t is a structure type. + This means that the caller must have statically or dynamically allocated + the structure before calling this Api. + + TODO, may not be necessary, since crypt apis also take pool. + @param[in] pool The pool to use to allocate any temporary working memory + beyond what is provided in the 'key' structure. + + @param[in,out] key A pointer to an allocated (statically or dynamically) + key structure to be initalized as a blank RSA keypair. +*/ +int32_t psRsaInitKey(psPool_t *pool, psRsaKey_t *key) +{ + if (!key) { + return PS_MEM_FAIL; + } + memset(key, 0x0, sizeof(psRsaKey_t)); + key->pool = pool; + return PS_SUCCESS; +} + +/* + Zero an RSA key. The caller is responsible for freeing 'key' if it is + allocated (or not if it is static, or stack based). + */ +void psRsaClearKey(psRsaKey_t *key) +{ + pstm_clear(&(key->N)); + pstm_clear(&(key->e)); + pstm_clear(&(key->d)); + pstm_clear(&(key->p)); + pstm_clear(&(key->q)); + pstm_clear(&(key->dP)); + pstm_clear(&(key->dQ)); + pstm_clear(&(key->qP)); + key->size = 0; + key->optimized = 0; + key->pool = NULL; +} + +/* 'to' key digits are allocated here */ +int32_t psRsaCopyKey(psRsaKey_t *to, const psRsaKey_t *from) +{ + int32_t err = 0; + if ((err = pstm_init_copy(from->pool, &to->N, &from->N, 0)) != PSTM_OKAY) { + goto error; } + if ((err = pstm_init_copy(from->pool, &to->e, &from->e, 0)) != PSTM_OKAY) { + goto error; } + if ((err = pstm_init_copy(from->pool, &to->d, &from->d, 0)) != PSTM_OKAY) { + goto error; } + if ((err = pstm_init_copy(from->pool, &to->p, &from->p, 0)) != PSTM_OKAY) { + goto error; } + if ((err = pstm_init_copy(from->pool, &to->q, &from->q, 0)) != PSTM_OKAY) { + goto error; } + if ((err = pstm_init_copy(from->pool, &to->dP, &from->dP, 0)) != PSTM_OKAY){ + goto error; } + if ((err = pstm_init_copy(from->pool, &to->dQ, &from->dQ, 0)) != PSTM_OKAY){ + goto error; } + if ((err = pstm_init_copy(from->pool, &to->qP, &from->qP, 0)) != PSTM_OKAY){ + goto error; } + to->size = from->size; + to->optimized = from->optimized; + to->pool = from->pool; +error: + if (err < 0) { + psRsaClearKey(to); + } + return err; +} +#endif /* USE_MATRIX_RSA */ + +#ifdef USE_RSA +/******************************************************************************/ +/** + Get the size in bytes of the RSA public exponent. + Eg. 128 for 1024 bit RSA keys, 256 for 2048 and 512 for 4096 bit keys. + @param[in] key RSA key + @return Number of bytes of public exponent. +*/ +uint16_t psRsaSize(const psRsaKey_t *key) +{ + return key->size; +} + +/******************************************************************************/ +/** + Compare if the public modulus and exponent is the same between two keys. + + @return < 0 on failure, >= 0 on success. +*/ +int32_t psRsaCmpPubKey(const psRsaKey_t *k1, const psRsaKey_t *k2) +{ + if ((pstm_cmp(&k1->N, &k2->N) == PSTM_EQ) && + (pstm_cmp(&k1->e, &k2->e) == PSTM_EQ)) { + return PS_SUCCESS; + } + return PS_FAIL; +} + +#ifdef OLD +/******************************************************************************/ +/* +*/ +static int32_t getBig(psPool_t *pool, const unsigned char **pp, uint16_t len, + pstm_int *big) +{ + const unsigned char *p = *pp; + uint16_t vlen; + + if (len < 1 || *(p++) != ASN_INTEGER || + getAsnLength(&p, len - 1, &vlen) < 0 || (len - 1) < vlen) { + return PS_PARSE_FAIL; + } + /* Make a smart size since we know the length */ + if (pstm_init_for_read_unsigned_bin(pool, big, vlen) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + if (pstm_read_unsigned_bin(big, p, vlen) != 0) { + pstm_clear(big); + psTraceCrypto("ASN getBig failed\n"); + return PS_PARSE_FAIL; + } + *pp = p + vlen; + return PS_SUCCESS; +} +#endif + +/******************************************************************************/ +/** + Parse an RSA public key from an ASN.1 byte stream. + @return < 0 on error, >= 0 on success. +*/ +int32_t psRsaParseAsnPubKey(psPool_t *pool, + const unsigned char **pp, uint16_t len, + psRsaKey_t *key, unsigned char sha1KeyHash[SHA1_HASH_SIZE]) +{ +#ifdef USE_SHA1 + psDigestContext_t dc; +#endif + const unsigned char *p = *pp; + uint16_t keylen, seqlen; + + if (len < 1 || (*(p++) != ASN_BIT_STRING) || + getAsnLength(&p, len - 1, &keylen) < 0 || + (len - 1) < keylen) { + goto L_FAIL; + } + if (*p++ != 0) { + goto L_FAIL; + } + +#ifdef USE_SHA1 + /* A public key hash is used in PKI tools (OCSP, Trusted CA indication). + Standard RSA form - SHA-1 hash of the value of the BIT STRING + subjectPublicKey [excluding the tag, length, and number of unused + bits] */ + psSha1Init(&dc.sha1); + psSha1Update(&dc.sha1, p, keylen - 1); + psSha1Final(&dc.sha1, sha1KeyHash); +#endif + + if (getAsnSequence(&p, keylen, &seqlen) < 0 || + pstm_read_asn(pool, &p, seqlen, &key->N) < 0 || + pstm_read_asn(pool, &p, seqlen, &key->e) < 0) { + + goto L_FAIL; + } + key->size = pstm_unsigned_bin_size(&key->N); + key->pool = pool; +#ifdef USE_TILERA_RSA +#ifdef USE_RSA_PUBLIC_NONBLOCKING + key->nonBlock = 1; +#else + key->nonBlock = 0; +#endif +#endif + *pp = p; + return PS_SUCCESS; +L_FAIL: + psTraceIntCrypto("psRsaReadAsnPubKey error on byte %d\n", p - *pp); + return PS_PARSE_FAIL; +} + +#ifdef USE_PRIVATE_KEY_PARSING +/******************************************************************************/ +/** + Parse a a private key structure in DER formatted ASN.1 + Per ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf + RSAPrivateKey ::= SEQUENCE { + version Version, + modulus INTEGER, -- n + publicExponent INTEGER, -- e + privateExponent INTEGER, -- d + prime1 INTEGER, -- p + prime2 INTEGER, -- q + exponent1 INTEGER, -- d mod (p-1) + exponent2 INTEGER, -- d mod (q-1) + coefficient INTEGER, -- (inverse of q) mod p + otherPrimeInfos OtherPrimeInfos OPTIONAL + } + Version ::= INTEGER { two-prime(0), multi(1) } + (CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --}) + + Which should look something like this in hex (pipe character + is used as a delimiter): + ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc + 30 Tag in binary: 00|1|10000 -> UNIVERSAL | CONSTRUCTED | SEQUENCE (16) + 82 Length in binary: 1 | 0000010 -> LONG LENGTH | LENGTH BYTES (2) + 04 A4 Length Bytes (1188) + 02 Tag in binary: 00|0|00010 -> UNIVERSAL | PRIMITIVE | INTEGER (2) + 01 Length in binary: 0|0000001 -> SHORT LENGTH | LENGTH (1) + 00 INTEGER value (0) - RSAPrivateKey.version + 02 Tag in binary: 00|0|00010 -> UNIVERSAL | PRIMITIVE | INTEGER (2) + 82 Length in binary: 1 | 0000010 -> LONG LENGTH | LENGTH BYTES (2) + 01 01 Length Bytes (257) + [] 257 Bytes of data - RSAPrivateKey.modulus (2048 bit key) + 02 Tag in binary: 00|0|00010 -> UNIVERSAL | PRIMITIVE | INTEGER (2) + 03 Length in binary: 0|0000011 -> SHORT LENGTH | LENGTH (3) + 01 00 01 INTEGER value (65537) - RSAPrivateKey.publicExponent + ... + + OtherPrimeInfos is not supported in this routine, and an error will be + returned if they are present + + @return < 0 on error, >= 0 on success. +*/ +int32_t psRsaParsePkcs1PrivKey(psPool_t *pool, + const unsigned char *p, uint16_t size, + psRsaKey_t *key) +{ + const unsigned char *end, *seq; + int32_t version; + uint16_t seqlen; + + if (psRsaInitKey(pool, key) < 0) { + return PS_MEM_FAIL; + } + end = p + size; + if (getAsnSequence(&p, size, &seqlen) < 0) { + psRsaClearKey(key); + return PS_PARSE_FAIL; + } + seq = p; + if (getAsnInteger(&p, (uint16_t)(end - p), &version) < 0 || version != 0 || + pstm_read_asn(pool, &p, (uint16_t)(end - p), &(key->N)) < 0 || + pstm_read_asn(pool, &p, (uint16_t)(end - p), &(key->e)) < 0 || + pstm_read_asn(pool, &p, (uint16_t)(end - p), &(key->d)) < 0 || + pstm_read_asn(pool, &p, (uint16_t)(end - p), &(key->p)) < 0 || + pstm_read_asn(pool, &p, (uint16_t)(end - p), &(key->q)) < 0 || + pstm_read_asn(pool, &p, (uint16_t)(end - p), &(key->dP)) < 0 || + pstm_read_asn(pool, &p, (uint16_t)(end - p), &(key->dQ)) < 0 || + pstm_read_asn(pool, &p, (uint16_t)(end - p), &(key->qP)) < 0 || + (uint16_t)(p - seq) != seqlen) { + + psTraceCrypto("ASN RSA private key extract parse error\n"); + psRsaClearKey(key); + return PS_PARSE_FAIL; + } + +#ifdef USE_TILERA_RSA + /* EIP-54 usage limitation that some operands must be larger than others. + If you are seeing RSA unpad failures after decryption, try toggling + this swap. It does seem to work 100% of the time by either performing + or not performing this swap. */ + /* EIP-24 requires dP > dQ. Swap and recalc qP */ + if (pstm_cmp_mag(&key->p, &key->q) == PSTM_LT) { + pstm_exch(&key->dP, &key->dQ); + pstm_exch(&key->p, &key->q); + pstm_zero(&key->qP); + pstm_invmod(pool, &key->q, &key->p, &key->qP); + } +#ifdef USE_RSA_PRIVATE_NONBLOCKING + key->nonBlock = 1; +#else + key->nonBlock = 0; +#endif +#endif /* USE_TILERA_RSA */ + +/* + If we made it here, the key is ready for optimized decryption + Set the key length of the key + */ + key->optimized = 1; + key->size = pstm_unsigned_bin_size(&key->N); + + /* Should be at the end */ + if (end != p) { + /* If this stream came from an encrypted file, there could be + padding bytes on the end */ + seqlen = (uint16_t)(end - p); + while (p < end) { + if (*p != seqlen) { + psTraceCrypto("Problem at end of private key parse\n"); + } + p++; + } + } + + return PS_SUCCESS; +} +#endif /* USE_PRIVATE_KEY_PARSING */ +#endif /* USE_RSA */ + +#ifdef USE_MATRIX_RSA +/******************************************************************************/ +/** + Primary RSA crypto routine, with either public or private key. + + @param[in] pool Pool to use for temporary memory allocation for this op. + @param[in] key RSA key to use for this operation. + @param[in] in Pointer to allocated buffer to encrypt. + @param[in] inlen Number of bytes pointed to by 'in' to encrypt. + @param[out] out Pointer to allocated buffer to store encrypted data. + @param[out] outlen Number of bytes written to 'out' buffer. + @param[in] type PS_PRIVKEY or PS_PUBKEY. + @param[in] data TODO Hardware context. + + @return 0 on success, < 0 on failure. + + @note 'out' and 'in' can be equal for in-situ operation. +*/ +int32_t psRsaCrypt(psPool_t *pool, psRsaKey_t *key, + const unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t *outlen, + uint8_t type, void *data) +{ + pstm_int tmp, tmpa, tmpb; + int32_t res; + uint32_t x; + + if (in == NULL || out == NULL || outlen == NULL || key == NULL) { + psTraceCrypto("NULL parameter error in psRsaCrypt\n"); + return PS_ARG_FAIL; + } + + tmp.dp = tmpa.dp = tmpb.dp = NULL; + + /* Init and copy into tmp */ + if (pstm_init_for_read_unsigned_bin(pool, &tmp, inlen + sizeof(pstm_digit)) + != PS_SUCCESS) { + return PS_FAILURE; + } + if (pstm_read_unsigned_bin(&tmp, (unsigned char *)in, inlen) != PS_SUCCESS){ + pstm_clear(&tmp); + return PS_FAILURE; + } + /* Sanity check on the input */ + if (pstm_cmp(&key->N, &tmp) == PSTM_LT) { + res = PS_LIMIT_FAIL; + goto done; + } + if (type == PS_PRIVKEY) { + if (key->optimized) { + if (pstm_init_size(pool, &tmpa, key->p.alloc) != PS_SUCCESS) { + res = PS_FAILURE; + goto done; + } + if (pstm_init_size(pool, &tmpb, key->q.alloc) != PS_SUCCESS) { + pstm_clear(&tmpa); + res = PS_FAILURE; + goto done; + } + if (pstm_exptmod(pool, &tmp, &key->dP, &key->p, &tmpa) != + PS_SUCCESS) { + psTraceCrypto("decrypt error: pstm_exptmod dP, p\n"); + goto error; + } + if (pstm_exptmod(pool, &tmp, &key->dQ, &key->q, &tmpb) != + PS_SUCCESS) { + psTraceCrypto("decrypt error: pstm_exptmod dQ, q\n"); + goto error; + } + if (pstm_sub(&tmpa, &tmpb, &tmp) != PS_SUCCESS) { + psTraceCrypto("decrypt error: sub tmpb, tmp\n"); + goto error; + } + if (pstm_mulmod(pool, &tmp, &key->qP, &key->p, &tmp) != PS_SUCCESS) { + psTraceCrypto("decrypt error: pstm_mulmod qP, p\n"); + goto error; + } + if (pstm_mul_comba(pool, &tmp, &key->q, &tmp, NULL, 0) + != PS_SUCCESS){ + psTraceCrypto("decrypt error: pstm_mul q \n"); + goto error; + } + if (pstm_add(&tmp, &tmpb, &tmp) != PS_SUCCESS) { + psTraceCrypto("decrypt error: pstm_add tmp \n"); + goto error; + } + } else { + if (pstm_exptmod(pool, &tmp, &key->d, &key->N, &tmp) != + PS_SUCCESS) { + psTraceCrypto("psRsaCrypt error: pstm_exptmod\n"); + goto error; + } + } + } else if (type == PS_PUBKEY) { + if (pstm_exptmod(pool, &tmp, &key->e, &key->N, &tmp) != PS_SUCCESS) { + psTraceCrypto("psRsaCrypt error: pstm_exptmod\n"); + goto error; + } + } else { + psTraceCrypto("psRsaCrypt error: invalid type param\n"); + goto error; + } + /* Read it back */ + x = pstm_unsigned_bin_size(&key->N); + + if ((uint32)x > *outlen) { + res = -1; + psTraceCrypto("psRsaCrypt error: pstm_unsigned_bin_size\n"); + goto done; + } + /* We want the encrypted value to always be the key size. Pad with 0x0 */ + while ((uint32)x < (unsigned long)key->size) { + *out++ = 0x0; + x++; + } + + *outlen = x; + /* Convert it */ + memset(out, 0x0, x); + + if (pstm_to_unsigned_bin(pool, &tmp, out+(x-pstm_unsigned_bin_size(&tmp))) + != PS_SUCCESS) { + psTraceCrypto("psRsaCrypt error: pstm_to_unsigned_bin\n"); + goto error; + } + /* Clean up and return */ + res = PS_SUCCESS; + goto done; +error: + res = PS_FAILURE; +done: + if (type == PS_PRIVKEY && key->optimized) { + pstm_clear_multi(&tmpa, &tmpb, NULL, NULL, NULL, NULL, NULL, NULL); + } + pstm_clear(&tmp); + return res; +} + +/******************************************************************************/ +/** + RSA private encryption. This is used by a private key holder to sign + data that can be verified by psRsaDecryptPub(). + + @param[in] pool Pool to use for temporary memory allocation for this op. + @param[in] key RSA key to use for this operation. + @param[in] in Pointer to allocated buffer to encrypt. + @param[in] inlen Number of bytes pointed to by 'in' to encrypt. + @param[out] out Pointer to allocated buffer to store encrypted data. + @param[out] outlen Number of bytes written to 'out' buffer. + @param[in] data TODO Hardware context. + + @return 0 on success, < 0 on failure. +*/ +int32_t psRsaEncryptPriv(psPool_t *pool, psRsaKey_t *key, + const unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + void *data) +{ + unsigned char *verify = NULL; + unsigned char *tmpout = NULL; + int32_t err; + uint16_t size, olen; + + size = key->size; + if (outlen < size) { + psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPriv\n"); + return PS_ARG_FAIL; + } + olen = outlen; /* Save in case we zero 'out' later */ + if ((err = pkcs1Pad(in, inlen, out, size, PS_PUBKEY, data)) < PS_SUCCESS){ + psTraceCrypto("Error padding psRsaEncryptPriv. Likely data too long\n"); + return err; + } + if ((err = psRsaCrypt(pool, key, out, size, out, &outlen, + PS_PRIVKEY, data)) < PS_SUCCESS) { + psTraceCrypto("Error performing psRsaEncryptPriv\n"); + return err; + } + if (outlen != size) { + goto L_FAIL; + } + + /** + @security Verify the signature we just made before it is used + by the caller. If the signature is invalid for some reason + (hardware or software error or memory overrun), it can + leak information on the private key. + */ + if ((verify = psMalloc(pool, inlen)) == NULL) { + goto L_FAIL; + } + /* psRsaDecryptPub overwrites the input, so duplicate it here */ + if ((tmpout = psMalloc(pool, outlen)) == NULL) { + goto L_FAIL; + } + memcpy(tmpout, out, outlen); + if (psRsaDecryptPub(pool, key, + tmpout, outlen, verify, inlen, data) < 0) { + goto L_FAIL; + } + if (memcmpct(in, verify, inlen) != 0) { + goto L_FAIL; + } + memzero_s(verify, inlen); + psFree(verify, pool); + memzero_s(tmpout, outlen); + psFree(tmpout, pool); + + return PS_SUCCESS; + +L_FAIL: + memzero_s(out, olen); /* Clear, to ensure bad result isn't used */ + if (tmpout) { + memzero_s(tmpout, outlen); + psFree(tmpout, pool); + } + if (verify) { + memzero_s(verify, inlen); + psFree(verify, pool); + } + psTraceCrypto("Signature mismatch in psRsaEncryptPriv\n"); + return PS_FAIL; +} + +/******************************************************************************/ +/** + RSA public encryption. This is used by a public key holder to do + key exchange with the private key holder, which can access the key using + psRsaDecryptPriv(). + + @param[in] pool Pool to use for temporary memory allocation for this op. + @param[in] key RSA key to use for this operation. + @param[in] in Pointer to allocated buffer to encrypt. + @param[in] inlen Number of bytes pointed to by 'in' to encrypt. + @param[out] out Pointer to allocated buffer to store encrypted data. + @param[in] expected output length + @param[in] data TODO Hardware context. + + @return 0 on success, < 0 on failure. +*/ +int32_t psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key, + const unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + void *data) +{ + int32_t err; + uint16_t size; + + size = key->size; + if (outlen < size) { + psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPub\n"); + return PS_ARG_FAIL; + } + + if ((err = pkcs1Pad(in, inlen, out, size, PS_PRIVKEY, data)) + < PS_SUCCESS) { + psTraceCrypto("Error padding psRsaEncryptPub. Likely data too long\n"); + return err; + } + if ((err = psRsaCrypt(pool, key, out, size, out, &outlen, + PS_PUBKEY, data)) < PS_SUCCESS) { + psTraceCrypto("Error performing psRsaEncryptPub\n"); + return err; + } + if (outlen != size) { + psTraceCrypto("Encrypted size error in psRsaEncryptPub\n"); + return PS_FAILURE; + } + return PS_SUCCESS; +} + +/******************************************************************************/ +/** + RSA private decryption. This is used by a private key holder to decrypt + a key exchange with the public key holder, which encodes the key using + psRsaEncryptPub(). + + @param[in] pool Pool to use for temporary memory allocation for this op. + @param[in] key RSA key to use for this operation. + @param[in,out] in Pointer to allocated buffer to encrypt. + @param[in] inlen Number of bytes pointed to by 'in' to encrypt. + @param[out] out Pointer to allocated buffer to store encrypted data. + @param[out] outlen Number of bytes written to 'out' buffer. + @param[in] data TODO Hardware context. + + @return 0 on success, < 0 on failure. + + TODO -fix + @note this function writes over the 'in' buffer +*/ +int32_t psRsaDecryptPriv(psPool_t *pool, psRsaKey_t *key, + unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + void *data) +{ + int32_t err; + uint16_t ptLen; + + if (inlen != key->size) { + psTraceCrypto("Error on bad inlen parameter to psRsaDecryptPriv\n"); + return PS_ARG_FAIL; + } + ptLen = inlen; + if ((err = psRsaCrypt(pool, key, in, inlen, in, &ptLen, + PS_PRIVKEY, data)) < PS_SUCCESS) { + psTraceCrypto("Error performing psRsaDecryptPriv\n"); + return err; + } + if (ptLen != inlen) { + psTraceCrypto("Decrypted size error in psRsaDecryptPriv\n"); + return PS_FAILURE; + } + err = pkcs1Unpad(in, inlen, out, outlen, PS_PRIVKEY); + memset(in, 0x0, inlen); + return err; +} + +/******************************************************************************/ +/** + RSA public decryption. This is used by a public key holder to verify + a signature by the private key holder, who signs using psRsaEncryptPriv(). + + @param[in] pool Pool to use for temporary memory allocation for this op. + @param[in] key RSA key to use for this operation. + @param[in,out] in Pointer to allocated buffer to encrypt. + @param[in] inlen Number of bytes pointed to by 'in' to encrypt. + @param[out] out Pointer to allocated buffer to store encrypted data. + @param[in] outlen length of expected output. + @param[in] data TODO Hardware context. + + @return 0 on success, < 0 on failure. + + TODO -fix + @note this function writes over the 'in' buffer +*/ +int32_t psRsaDecryptPub(psPool_t *pool, psRsaKey_t *key, + unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + void *data) +{ + int32_t err; + uint16_t ptLen; + + if (inlen != key->size) { + psTraceCrypto("Error on bad inlen parameter to psRsaDecryptPub\n"); + return PS_ARG_FAIL; + } + ptLen = inlen; + if ((err = psRsaCrypt(pool, key, in, inlen, in, &ptLen, + PS_PUBKEY, data)) < PS_SUCCESS) { + psTraceCrypto("Error performing psRsaDecryptPub\n"); + return err; + } + if (ptLen != inlen) { + psTraceIntCrypto("Decrypted size error in psRsaDecryptPub %d\n", ptLen); + return PS_FAILURE; + } + if ((err = pkcs1Unpad(in, inlen, out, outlen, PS_PUBKEY)) < 0) { + return err; + } + return PS_SUCCESS; +} + + +#endif /* USE_MATRIX_RSA */ + +/******************************************************************************/ + diff --git a/crypto/pubkey/rsa_openssl.c b/crypto/pubkey/rsa_openssl.c new file mode 100644 index 0000000..8cd83ff --- /dev/null +++ b/crypto/pubkey/rsa_openssl.c @@ -0,0 +1,345 @@ +/** + * @file rsa_openssl.c + * @version $Format:%h%d$ + * + * RSA compatibility layer between MatrixSSL and OpenSSL. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_OPENSSL_RSA +#include "openssl/bn.h" + +/** + @note It bears mention that the DER parsing functions + are defined in this header via macro: + + DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPublicKey) + DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPrivateKey) + + They are implemented in openssl/crypto/rsa/rsa_asn1.c: + ASN1_SEQUENCE_cb(RSAPrivateKey, rsa_cb) = { + ASN1_SIMPLE(RSA, version, LONG), + ASN1_SIMPLE(RSA, n, BIGNUM), + ASN1_SIMPLE(RSA, e, BIGNUM), + ASN1_SIMPLE(RSA, d, BIGNUM), + ASN1_SIMPLE(RSA, p, BIGNUM), + ASN1_SIMPLE(RSA, q, BIGNUM), + ASN1_SIMPLE(RSA, dmp1, BIGNUM), + ASN1_SIMPLE(RSA, dmq1, BIGNUM), + ASN1_SIMPLE(RSA, iqmp, BIGNUM) + } ASN1_SEQUENCE_END_cb(RSA, RSAPrivateKey) + + ASN1_SEQUENCE_cb(RSAPublicKey, rsa_cb) = { + ASN1_SIMPLE(RSA, n, BIGNUM), + ASN1_SIMPLE(RSA, e, BIGNUM), + } ASN1_SEQUENCE_END_cb(RSA, RSAPublicKey) + + In turn, the asn BIGNUM creation is in crypto/asn1/x_bignum.c +*/ + +#include "openssl/rsa.h" + +/** + Note that in this case psRsaKey_t is a pointer type, so 'key' is + effectively a double pointer. We just set it to NULL for now, the actual + key will be allocated by the parse functions below. + + @param[in] pool Unused in this implementation. + @param[in,out] key A pointer to an allocated (statically or dynamically) + psRsaKey_t, which in this case is just a pointer to an RSA structure. +*/ +int32_t psRsaInitKey(psPool_t *pool, psRsaKey_t *key) +{ + *key = NULL; + return PS_SUCCESS; +} + +/******************************************************************************/ +/** + RSA_free() frees and zeroes the RSA structure and associated BIGNUM values. + */ +void psRsaClearKey(psRsaKey_t *key) +{ + if (key && *key) { + RSA_free(*key); + *key = NULL; + } +} + +/******************************************************************************/ +/** + */ +int32_t psRsaCopyKey(psRsaKey_t *to, const psRsaKey_t *from) +{ + RSA *t = *to; + RSA *f = *from; + + if (!from || !f || !to) { + return PS_ARG_FAIL; + } + /* If to already contained a key, free it */ + if (t) { + RSA_free(t); + } + /* Allocate a new key */ + if ((t = RSA_new()) == NULL) { + return PS_MEM_FAIL; + } + /* Duplicate the parts that must always be present (n, e) */ + if ((t->n = BN_dup(f->n)) == NULL) { + RSA_free(t); + return PS_FAIL; + } + if ((t->e = BN_dup(f->e)) == NULL) { + RSA_free(t); + return PS_FAIL; + } + /* Duplicate the private/optimized parts. Ok if they are NULL */ + t->d = BN_dup(f->d); + t->p = BN_dup(f->p); + t->q = BN_dup(f->q); + t->dmp1 = BN_dup(f->dmp1); + t->dmq1 = BN_dup(f->dmq1); + t->iqmp = BN_dup(f->iqmp); + *to = t; + return PS_SUCCESS; +} + +/******************************************************************************/ +/** + Returns the size of the RSA public modulus in bytes. + @return 0 on uninitalized key, or >= for valid key + (eg. 128 for 1024 bit key, etc) +*/ +uint16_t psRsaSize(const psRsaKey_t *key) +{ + if (key && *key) { + return RSA_size(*key); + } + return 0; +} + +/******************************************************************************/ + +int32_t psRsaCmpPubKey(const psRsaKey_t *k1, const psRsaKey_t *k2) +{ + /* BN_cmp() returns -1 if a < b, 0 if a == b and 1 if a > b. */ + if ((BN_cmp((*k1)->n, (*k2)->n) == 0) && + (BN_cmp((*k1)->e, (*k2)->e) == 0)) { + return PS_SUCCESS; + } + return PS_FAIL; +} + +#ifndef USE_D2I +/******************************************************************************/ +/** + Convert big endian binary data to a native big number type. + BN_bin2bn() converts the positive integer in big-endian form of length len + at s into a BIGNUM and places it in ret. + If ret is NULL, a new BIGNUM is created. + BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); + */ +static int32_t getBig(const unsigned char **pp, uint16_t len, BIGNUM **big) +{ + const unsigned char *p = *pp; + uint16_t vlen; + BIGNUM *bn; + + if (len < 1 || *(p++) != ASN_INTEGER || + getAsnLength(&p, len - 1, &vlen) < 0 || (len - 1) < vlen) { + return PS_PARSE_FAIL; + } + if ((bn = BN_bin2bn(p, vlen, NULL)) == NULL) { + return PS_MEM_FAIL; + } + /* BN_print_fp(stdout, bn); */ + *big = bn; + *pp = p + vlen; + return PS_SUCCESS; +} +#endif +/******************************************************************************/ +/* + Parse DER encoded asn.1 RSA public key out of a certificate stream. + We reach here with 'pp' pointing to the byte after the algorithm identifier. +*/ +int32_t psRsaParseAsnPubKey(psPool_t *pool, + const unsigned char **pp, uint16_t len, + psRsaKey_t *key, unsigned char sha1KeyHash[SHA1_HASH_SIZE]) +{ +#ifdef USE_SHA1 + psDigestContext_t dc; +#endif + const unsigned char *p = *pp; + RSA *rsa; + uint16_t keylen; +#ifndef USE_D2I + uint16_t seqlen; +#endif + + if (len < 1 || (*(p++) != ASN_BIT_STRING) || + getAsnLength(&p, len - 1, &keylen)) { + goto L_FAIL; + } + /* ignored bits field should be zero */ + if (*p++ != 0) { + goto L_FAIL; + } + keylen--; +#ifdef USE_SHA1 + /* A public key hash is used in PKI tools (OCSP, Trusted CA indication). + Standard RSA form - SHA-1 hash of the value of the BIT STRING + subjectPublicKey [excluding the tag, length, and number of unused + bits] */ + psSha1Init(&dc.sha1); + psSha1Update(&dc.sha1, p, keylen); + psSha1Final(&dc.sha1, sha1KeyHash); +#endif + +#ifdef USE_D2I + /* OpenSSL expects to parse after the ignored bits field */ + if ((rsa = d2i_RSAPublicKey(NULL, &p, keylen)) == NULL) { + goto L_FAIL; + } +#else + /* We can manually create the structures as OpenSSL would */ + rsa = RSA_new(); + if (getAsnSequence(&p, keylen, &seqlen) < 0 || + getBig(&p, seqlen, &rsa->n) < 0 || + getBig(&p, seqlen, &rsa->e) < 0) { + + RSA_free(rsa); + goto L_FAIL; + } +#endif + /* RSA_print_fp(stdout, rsa, 0); */ + *pp = p; + *key = rsa; + return PS_SUCCESS; +L_FAIL: + psTraceIntCrypto("psRsaParseAsnPubKey error on byte %d\n", p - *pp); + return PS_PARSE_FAIL; +} + +#ifdef USE_PRIVATE_KEY_PARSING +/******************************************************************************/ +/** + Parse an RSA private key from a PKCS#1 byte stream. + @see ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf +*/ +int32_t psRsaParsePkcs1PrivKey(psPool_t *pool, + const unsigned char *p, uint16_t size, + psRsaKey_t *key) +{ + RSA *rsa; +#ifndef USE_D2I + const unsigned char *end, *seq; + int32_t version; + uint16_t seqlen; +#endif + +#ifdef USE_D2I + if ((rsa = d2i_RSAPrivateKey(NULL, &p, size)) == NULL) { + return PS_PARSE_FAIL; + } +#else + if ((rsa = RSA_new()) == NULL) { + return PS_MEM_FAIL; + } + end = p + size; + if (getAsnSequence(&p, size, &seqlen) < 0) { + RSA_free(rsa); + goto L_FAIL; + } + seq = p; + if (getAsnInteger(&p, (uint16_t)(end - p), &version) < 0 || version != 0 || + getBig(&p, (uint16_t)(end - p), &rsa->n) < 0 || + getBig(&p, (uint16_t)(end - p), &rsa->e) < 0 || + getBig(&p, (uint16_t)(end - p), &rsa->d) < 0 || + getBig(&p, (uint16_t)(end - p), &rsa->p) < 0 || + getBig(&p, (uint16_t)(end - p), &rsa->q) < 0 || + getBig(&p, (uint16_t)(end - p), &rsa->dmp1) < 0 || + getBig(&p, (uint16_t)(end - p), &rsa->dmq1) < 0 || + getBig(&p, (uint16_t)(end - p), &rsa->iqmp) < 0 || + (uint16_t)(p - seq) != seqlen) { + + RSA_free(rsa); + goto L_FAIL; + } + rsa->version = version; +#endif + /* RSA_print_fp(stdout, rsa, 0); */ + *key = rsa; + return PS_SUCCESS; +L_FAIL: + psTraceIntCrypto("psRsaParsePkcs1PrivKey error on byte %d\n", p - (end - size)); + return PS_PARSE_FAIL; +} +#endif /* USE_PRIVATE_KEY_PARSING */ + +/******************************************************************************/ + +int32_t psRsaEncryptPriv(psPool_t *pool, psRsaKey_t *key, + const unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + void *data) +{ + return RSA_private_encrypt(inlen, in, out, *key, RSA_PKCS1_PADDING); +} + +int32_t psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key, + const unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + void *data) +{ + return RSA_public_encrypt(inlen, in, out, *key, RSA_PKCS1_PADDING); +} + +int32_t psRsaDecryptPriv(psPool_t *pool, psRsaKey_t *key, + unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + void *data) +{ + return RSA_private_decrypt(inlen, in, out, *key, RSA_PKCS1_PADDING); +} + +int32_t psRsaDecryptPub(psPool_t *pool, psRsaKey_t *key, + unsigned char *in, uint16_t inlen, + unsigned char *out, uint16_t outlen, + void *data) +{ + return RSA_public_decrypt(inlen, in, out, *key, RSA_PKCS1_PADDING); +} + +#endif /* USE_OPENSSL_RSA */ +/******************************************************************************/ + diff --git a/crypto/symmetric/aes.c b/crypto/symmetric/aes.c new file mode 100644 index 0000000..2d29f45 --- /dev/null +++ b/crypto/symmetric/aes.c @@ -0,0 +1,1640 @@ +/** + * @file aes.c + * @version $Format:%h%d$ + * + * AES block cipher implementation. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_MATRIX_AES_BLOCK + +/******************************************************************************/ + +__inline static void invertKeySchedule(psAesKey_t *key); +static uint32 setup_mix(uint32 temp); + +static const uint32 rcon[] = { + 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, + 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, + 0x1B000000UL, 0x36000000UL + /* for 128-bit blocks, AES never uses more than 10 rcon values */ +}; + +#define byte(x, n) (((x) >> (8 * (n))) & 255) + +/******************************************************************************/ +/** + Initialize the key schedule of an AES (Rijndael) block cipher. + The initilaized key can be used only for encrypt or decrypt. + If the same key bytes need to be used for both, two psAesKey_t structures + should be initialized. + + @param[in,out] key Pointer to an allocated key structure to be initialized. + @param[in] ckey The symmetric key as bytes. + @param[in] keylen The number of bytes in 'ckey'. + @param[in] flags PS_AES_ENCRYPT or PS_AES_DECRYPT. + @return PS_SUCCESS on success, < 0 on failure. + + @security psAesClearBlockKey() should be called as soon as the key is no + longer needed. + @security If 'ckey' is no longer needed after this api call, it should be + cleared. +*/ +int32_t psAesInitBlockKey(psAesKey_t *key, + const unsigned char ckey[AES_MAXKEYLEN], uint8_t keylen, + uint32_t flags) +{ + int i; + uint32 temp, *rk; + +#ifdef CRYPTO_ASSERT + if (ckey == NULL || key == NULL || + !(flags & (PS_AES_ENCRYPT | PS_AES_DECRYPT))) { + + psTraceCrypto("Bad args to psAesInitBlockKey\n"); + return PS_ARG_FAIL; + } + if (keylen != AES128_KEYLEN && keylen != AES192_KEYLEN && + keylen != AES256_KEYLEN) { + psTraceCrypto("Invalid AES key length\n"); + return PS_ARG_FAIL; + } +#endif + /* + Setup the forward (encrypt) key schedule. If flags & PS_AES_DECRYPT we + will calculate the inverse (decrypt) key schedule from this forward + schedule and replace it. + */ + i = 0; + rk = key->skey; + LOAD32H(rk[0], ckey ); + LOAD32H(rk[1], ckey + 4); + LOAD32H(rk[2], ckey + 8); + LOAD32H(rk[3], ckey + 12); + switch (keylen) { + case 16: + key->rounds = 10; + for (;;) { + temp = rk[3]; + rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + break; + } + rk += 4; + } + break; + + case 24: + key->rounds = 12; + LOAD32H(rk[4], ckey + 16); + LOAD32H(rk[5], ckey + 20); + for (;;) { + #ifdef _MSC_VER + temp = key->skey[rk - key->skey + 5]; + #else + temp = rk[5]; + #endif /* _MSC_VER */ + rk[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) { + break; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + break; + + case 32: + key->rounds = 14; + LOAD32H(rk[4], ckey + 16); + LOAD32H(rk[5], ckey + 20); + LOAD32H(rk[6], ckey + 24); + LOAD32H(rk[7], ckey + 28); + for (;;) { + #ifdef _MSC_VER + temp = key->skey[rk - key->skey + 7]; + #else + temp = rk[7]; + #endif /* _MSC_VER */ + rk[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + break; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ setup_mix(ROR(temp, 8)); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + rk += 8; + } + break; + + default: + psTraceCrypto("Invalid AES key length\n"); + return CRYPT_INVALID_KEYSIZE; + } + + switch(flags) { + + case PS_AES_ENCRYPT: + key->type = PS_AES_ENCRYPT; + break; + + case PS_AES_DECRYPT: + key->type = PS_AES_DECRYPT; + /* Replace the key schedule with the inverse key schedule */ + invertKeySchedule(key); + break; + + default: + return PS_ARG_FAIL; + } + + return PS_SUCCESS; +} + +/******************************************************************************/ + +void psAesClearBlockKey(psAesKey_t *key) +{ + memset_s(key, sizeof(psAesKey_t), 0x0, sizeof(psAesKey_t)); +} + +/******************************************************************************/ +/* + AES constants +*/ + +/* The precomputed tables for AES */ +/* +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; +Te4[x] = S [x].[01, 01, 01, 01]; + +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +Td4[x] = Si[x].[01, 01, 01, 01]; +*/ + +static const uint32 TE0[] = { + 0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL, + 0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL, + 0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL, + 0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL, + 0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL, + 0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL, + 0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL, + 0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL, + 0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL, + 0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL, + 0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL, + 0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL, + 0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL, + 0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL, + 0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL, + 0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL, + 0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL, + 0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL, + 0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL, + 0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL, + 0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL, + 0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL, + 0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL, + 0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL, + 0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL, + 0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL, + 0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL, + 0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL, + 0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL, + 0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL, + 0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL, + 0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL, + 0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL, + 0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL, + 0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL, + 0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL, + 0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL, + 0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL, + 0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL, + 0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL, + 0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL, + 0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL, + 0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL, + 0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL, + 0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL, + 0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL, + 0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL, + 0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL, + 0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL, + 0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL, + 0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL, + 0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL, + 0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL, + 0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL, + 0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL, + 0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL, + 0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL, + 0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL, + 0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL, + 0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL, + 0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL, + 0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL, + 0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL, + 0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL, +}; + +#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE +static const uint32 Te4[] = { + 0x63636363UL, 0x7c7c7c7cUL, 0x77777777UL, 0x7b7b7b7bUL, + 0xf2f2f2f2UL, 0x6b6b6b6bUL, 0x6f6f6f6fUL, 0xc5c5c5c5UL, + 0x30303030UL, 0x01010101UL, 0x67676767UL, 0x2b2b2b2bUL, + 0xfefefefeUL, 0xd7d7d7d7UL, 0xababababUL, 0x76767676UL, + 0xcacacacaUL, 0x82828282UL, 0xc9c9c9c9UL, 0x7d7d7d7dUL, + 0xfafafafaUL, 0x59595959UL, 0x47474747UL, 0xf0f0f0f0UL, + 0xadadadadUL, 0xd4d4d4d4UL, 0xa2a2a2a2UL, 0xafafafafUL, + 0x9c9c9c9cUL, 0xa4a4a4a4UL, 0x72727272UL, 0xc0c0c0c0UL, + 0xb7b7b7b7UL, 0xfdfdfdfdUL, 0x93939393UL, 0x26262626UL, + 0x36363636UL, 0x3f3f3f3fUL, 0xf7f7f7f7UL, 0xccccccccUL, + 0x34343434UL, 0xa5a5a5a5UL, 0xe5e5e5e5UL, 0xf1f1f1f1UL, + 0x71717171UL, 0xd8d8d8d8UL, 0x31313131UL, 0x15151515UL, + 0x04040404UL, 0xc7c7c7c7UL, 0x23232323UL, 0xc3c3c3c3UL, + 0x18181818UL, 0x96969696UL, 0x05050505UL, 0x9a9a9a9aUL, + 0x07070707UL, 0x12121212UL, 0x80808080UL, 0xe2e2e2e2UL, + 0xebebebebUL, 0x27272727UL, 0xb2b2b2b2UL, 0x75757575UL, + 0x09090909UL, 0x83838383UL, 0x2c2c2c2cUL, 0x1a1a1a1aUL, + 0x1b1b1b1bUL, 0x6e6e6e6eUL, 0x5a5a5a5aUL, 0xa0a0a0a0UL, + 0x52525252UL, 0x3b3b3b3bUL, 0xd6d6d6d6UL, 0xb3b3b3b3UL, + 0x29292929UL, 0xe3e3e3e3UL, 0x2f2f2f2fUL, 0x84848484UL, + 0x53535353UL, 0xd1d1d1d1UL, 0x00000000UL, 0xededededUL, + 0x20202020UL, 0xfcfcfcfcUL, 0xb1b1b1b1UL, 0x5b5b5b5bUL, + 0x6a6a6a6aUL, 0xcbcbcbcbUL, 0xbebebebeUL, 0x39393939UL, + 0x4a4a4a4aUL, 0x4c4c4c4cUL, 0x58585858UL, 0xcfcfcfcfUL, + 0xd0d0d0d0UL, 0xefefefefUL, 0xaaaaaaaaUL, 0xfbfbfbfbUL, + 0x43434343UL, 0x4d4d4d4dUL, 0x33333333UL, 0x85858585UL, + 0x45454545UL, 0xf9f9f9f9UL, 0x02020202UL, 0x7f7f7f7fUL, + 0x50505050UL, 0x3c3c3c3cUL, 0x9f9f9f9fUL, 0xa8a8a8a8UL, + 0x51515151UL, 0xa3a3a3a3UL, 0x40404040UL, 0x8f8f8f8fUL, + 0x92929292UL, 0x9d9d9d9dUL, 0x38383838UL, 0xf5f5f5f5UL, + 0xbcbcbcbcUL, 0xb6b6b6b6UL, 0xdadadadaUL, 0x21212121UL, + 0x10101010UL, 0xffffffffUL, 0xf3f3f3f3UL, 0xd2d2d2d2UL, + 0xcdcdcdcdUL, 0x0c0c0c0cUL, 0x13131313UL, 0xececececUL, + 0x5f5f5f5fUL, 0x97979797UL, 0x44444444UL, 0x17171717UL, + 0xc4c4c4c4UL, 0xa7a7a7a7UL, 0x7e7e7e7eUL, 0x3d3d3d3dUL, + 0x64646464UL, 0x5d5d5d5dUL, 0x19191919UL, 0x73737373UL, + 0x60606060UL, 0x81818181UL, 0x4f4f4f4fUL, 0xdcdcdcdcUL, + 0x22222222UL, 0x2a2a2a2aUL, 0x90909090UL, 0x88888888UL, + 0x46464646UL, 0xeeeeeeeeUL, 0xb8b8b8b8UL, 0x14141414UL, + 0xdedededeUL, 0x5e5e5e5eUL, 0x0b0b0b0bUL, 0xdbdbdbdbUL, + 0xe0e0e0e0UL, 0x32323232UL, 0x3a3a3a3aUL, 0x0a0a0a0aUL, + 0x49494949UL, 0x06060606UL, 0x24242424UL, 0x5c5c5c5cUL, + 0xc2c2c2c2UL, 0xd3d3d3d3UL, 0xacacacacUL, 0x62626262UL, + 0x91919191UL, 0x95959595UL, 0xe4e4e4e4UL, 0x79797979UL, + 0xe7e7e7e7UL, 0xc8c8c8c8UL, 0x37373737UL, 0x6d6d6d6dUL, + 0x8d8d8d8dUL, 0xd5d5d5d5UL, 0x4e4e4e4eUL, 0xa9a9a9a9UL, + 0x6c6c6c6cUL, 0x56565656UL, 0xf4f4f4f4UL, 0xeaeaeaeaUL, + 0x65656565UL, 0x7a7a7a7aUL, 0xaeaeaeaeUL, 0x08080808UL, + 0xbabababaUL, 0x78787878UL, 0x25252525UL, 0x2e2e2e2eUL, + 0x1c1c1c1cUL, 0xa6a6a6a6UL, 0xb4b4b4b4UL, 0xc6c6c6c6UL, + 0xe8e8e8e8UL, 0xddddddddUL, 0x74747474UL, 0x1f1f1f1fUL, + 0x4b4b4b4bUL, 0xbdbdbdbdUL, 0x8b8b8b8bUL, 0x8a8a8a8aUL, + 0x70707070UL, 0x3e3e3e3eUL, 0xb5b5b5b5UL, 0x66666666UL, + 0x48484848UL, 0x03030303UL, 0xf6f6f6f6UL, 0x0e0e0e0eUL, + 0x61616161UL, 0x35353535UL, 0x57575757UL, 0xb9b9b9b9UL, + 0x86868686UL, 0xc1c1c1c1UL, 0x1d1d1d1dUL, 0x9e9e9e9eUL, + 0xe1e1e1e1UL, 0xf8f8f8f8UL, 0x98989898UL, 0x11111111UL, + 0x69696969UL, 0xd9d9d9d9UL, 0x8e8e8e8eUL, 0x94949494UL, + 0x9b9b9b9bUL, 0x1e1e1e1eUL, 0x87878787UL, 0xe9e9e9e9UL, + 0xcecececeUL, 0x55555555UL, 0x28282828UL, 0xdfdfdfdfUL, + 0x8c8c8c8cUL, 0xa1a1a1a1UL, 0x89898989UL, 0x0d0d0d0dUL, + 0xbfbfbfbfUL, 0xe6e6e6e6UL, 0x42424242UL, 0x68686868UL, + 0x41414141UL, 0x99999999UL, 0x2d2d2d2dUL, 0x0f0f0f0fUL, + 0xb0b0b0b0UL, 0x54545454UL, 0xbbbbbbbbUL, 0x16161616UL, +}; +#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ + +static const uint32 TD0[] = { + 0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL, + 0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL, + 0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL, + 0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL, + 0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL, + 0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL, + 0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL, + 0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL, + 0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL, + 0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL, + 0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL, + 0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL, + 0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL, + 0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL, + 0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL, + 0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL, + 0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL, + 0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL, + 0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL, + 0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL, + 0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL, + 0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL, + 0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL, + 0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL, + 0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL, + 0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL, + 0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL, + 0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL, + 0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL, + 0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL, + 0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL, + 0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL, + 0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL, + 0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL, + 0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL, + 0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL, + 0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL, + 0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL, + 0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL, + 0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL, + 0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL, + 0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL, + 0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL, + 0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL, + 0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL, + 0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL, + 0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL, + 0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL, + 0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL, + 0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL, + 0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL, + 0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL, + 0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL, + 0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL, + 0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL, + 0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL, + 0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL, + 0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL, + 0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL, + 0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL, + 0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL, + 0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL, + 0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL, + 0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL, +}; + +static const uint32 Td4[] = { + 0x52525252UL, 0x09090909UL, 0x6a6a6a6aUL, 0xd5d5d5d5UL, + 0x30303030UL, 0x36363636UL, 0xa5a5a5a5UL, 0x38383838UL, + 0xbfbfbfbfUL, 0x40404040UL, 0xa3a3a3a3UL, 0x9e9e9e9eUL, + 0x81818181UL, 0xf3f3f3f3UL, 0xd7d7d7d7UL, 0xfbfbfbfbUL, + 0x7c7c7c7cUL, 0xe3e3e3e3UL, 0x39393939UL, 0x82828282UL, + 0x9b9b9b9bUL, 0x2f2f2f2fUL, 0xffffffffUL, 0x87878787UL, + 0x34343434UL, 0x8e8e8e8eUL, 0x43434343UL, 0x44444444UL, + 0xc4c4c4c4UL, 0xdedededeUL, 0xe9e9e9e9UL, 0xcbcbcbcbUL, + 0x54545454UL, 0x7b7b7b7bUL, 0x94949494UL, 0x32323232UL, + 0xa6a6a6a6UL, 0xc2c2c2c2UL, 0x23232323UL, 0x3d3d3d3dUL, + 0xeeeeeeeeUL, 0x4c4c4c4cUL, 0x95959595UL, 0x0b0b0b0bUL, + 0x42424242UL, 0xfafafafaUL, 0xc3c3c3c3UL, 0x4e4e4e4eUL, + 0x08080808UL, 0x2e2e2e2eUL, 0xa1a1a1a1UL, 0x66666666UL, + 0x28282828UL, 0xd9d9d9d9UL, 0x24242424UL, 0xb2b2b2b2UL, + 0x76767676UL, 0x5b5b5b5bUL, 0xa2a2a2a2UL, 0x49494949UL, + 0x6d6d6d6dUL, 0x8b8b8b8bUL, 0xd1d1d1d1UL, 0x25252525UL, + 0x72727272UL, 0xf8f8f8f8UL, 0xf6f6f6f6UL, 0x64646464UL, + 0x86868686UL, 0x68686868UL, 0x98989898UL, 0x16161616UL, + 0xd4d4d4d4UL, 0xa4a4a4a4UL, 0x5c5c5c5cUL, 0xccccccccUL, + 0x5d5d5d5dUL, 0x65656565UL, 0xb6b6b6b6UL, 0x92929292UL, + 0x6c6c6c6cUL, 0x70707070UL, 0x48484848UL, 0x50505050UL, + 0xfdfdfdfdUL, 0xededededUL, 0xb9b9b9b9UL, 0xdadadadaUL, + 0x5e5e5e5eUL, 0x15151515UL, 0x46464646UL, 0x57575757UL, + 0xa7a7a7a7UL, 0x8d8d8d8dUL, 0x9d9d9d9dUL, 0x84848484UL, + 0x90909090UL, 0xd8d8d8d8UL, 0xababababUL, 0x00000000UL, + 0x8c8c8c8cUL, 0xbcbcbcbcUL, 0xd3d3d3d3UL, 0x0a0a0a0aUL, + 0xf7f7f7f7UL, 0xe4e4e4e4UL, 0x58585858UL, 0x05050505UL, + 0xb8b8b8b8UL, 0xb3b3b3b3UL, 0x45454545UL, 0x06060606UL, + 0xd0d0d0d0UL, 0x2c2c2c2cUL, 0x1e1e1e1eUL, 0x8f8f8f8fUL, + 0xcacacacaUL, 0x3f3f3f3fUL, 0x0f0f0f0fUL, 0x02020202UL, + 0xc1c1c1c1UL, 0xafafafafUL, 0xbdbdbdbdUL, 0x03030303UL, + 0x01010101UL, 0x13131313UL, 0x8a8a8a8aUL, 0x6b6b6b6bUL, + 0x3a3a3a3aUL, 0x91919191UL, 0x11111111UL, 0x41414141UL, + 0x4f4f4f4fUL, 0x67676767UL, 0xdcdcdcdcUL, 0xeaeaeaeaUL, + 0x97979797UL, 0xf2f2f2f2UL, 0xcfcfcfcfUL, 0xcecececeUL, + 0xf0f0f0f0UL, 0xb4b4b4b4UL, 0xe6e6e6e6UL, 0x73737373UL, + 0x96969696UL, 0xacacacacUL, 0x74747474UL, 0x22222222UL, + 0xe7e7e7e7UL, 0xadadadadUL, 0x35353535UL, 0x85858585UL, + 0xe2e2e2e2UL, 0xf9f9f9f9UL, 0x37373737UL, 0xe8e8e8e8UL, + 0x1c1c1c1cUL, 0x75757575UL, 0xdfdfdfdfUL, 0x6e6e6e6eUL, + 0x47474747UL, 0xf1f1f1f1UL, 0x1a1a1a1aUL, 0x71717171UL, + 0x1d1d1d1dUL, 0x29292929UL, 0xc5c5c5c5UL, 0x89898989UL, + 0x6f6f6f6fUL, 0xb7b7b7b7UL, 0x62626262UL, 0x0e0e0e0eUL, + 0xaaaaaaaaUL, 0x18181818UL, 0xbebebebeUL, 0x1b1b1b1bUL, + 0xfcfcfcfcUL, 0x56565656UL, 0x3e3e3e3eUL, 0x4b4b4b4bUL, + 0xc6c6c6c6UL, 0xd2d2d2d2UL, 0x79797979UL, 0x20202020UL, + 0x9a9a9a9aUL, 0xdbdbdbdbUL, 0xc0c0c0c0UL, 0xfefefefeUL, + 0x78787878UL, 0xcdcdcdcdUL, 0x5a5a5a5aUL, 0xf4f4f4f4UL, + 0x1f1f1f1fUL, 0xddddddddUL, 0xa8a8a8a8UL, 0x33333333UL, + 0x88888888UL, 0x07070707UL, 0xc7c7c7c7UL, 0x31313131UL, + 0xb1b1b1b1UL, 0x12121212UL, 0x10101010UL, 0x59595959UL, + 0x27272727UL, 0x80808080UL, 0xececececUL, 0x5f5f5f5fUL, + 0x60606060UL, 0x51515151UL, 0x7f7f7f7fUL, 0xa9a9a9a9UL, + 0x19191919UL, 0xb5b5b5b5UL, 0x4a4a4a4aUL, 0x0d0d0d0dUL, + 0x2d2d2d2dUL, 0xe5e5e5e5UL, 0x7a7a7a7aUL, 0x9f9f9f9fUL, + 0x93939393UL, 0xc9c9c9c9UL, 0x9c9c9c9cUL, 0xefefefefUL, + 0xa0a0a0a0UL, 0xe0e0e0e0UL, 0x3b3b3b3bUL, 0x4d4d4d4dUL, + 0xaeaeaeaeUL, 0x2a2a2a2aUL, 0xf5f5f5f5UL, 0xb0b0b0b0UL, + 0xc8c8c8c8UL, 0xebebebebUL, 0xbbbbbbbbUL, 0x3c3c3c3cUL, + 0x83838383UL, 0x53535353UL, 0x99999999UL, 0x61616161UL, + 0x17171717UL, 0x2b2b2b2bUL, 0x04040404UL, 0x7e7e7e7eUL, + 0xbabababaUL, 0x77777777UL, 0xd6d6d6d6UL, 0x26262626UL, + 0xe1e1e1e1UL, 0x69696969UL, 0x14141414UL, 0x63636363UL, + 0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL, + 0xe1f27f3aUL, 0xf5710fb0UL, 0xada0e5c4UL, 0x98e4c919UL +}; + +#ifdef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE + +static const uint32 TE1[256] = { + 0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL, + 0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL, + 0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL, + 0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL, + 0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL, + 0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL, + 0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL, + 0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL, + 0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL, + 0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL, + 0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL, + 0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL, + 0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL, + 0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL, + 0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL, + 0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL, + 0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL, + 0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL, + 0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL, + 0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL, + 0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL, + 0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL, + 0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL, + 0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL, + 0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL, + 0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL, + 0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL, + 0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL, + 0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL, + 0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL, + 0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL, + 0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL, + 0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL, + 0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL, + 0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL, + 0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL, + 0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL, + 0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL, + 0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL, + 0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL, + 0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL, + 0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL, + 0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL, + 0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL, + 0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL, + 0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL, + 0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL, + 0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL, + 0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL, + 0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL, + 0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL, + 0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL, + 0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL, + 0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL, + 0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL, + 0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL, + 0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL, + 0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL, + 0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL, + 0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL, + 0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL, + 0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL, + 0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL, + 0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL, +}; +static const uint32 TE2[256] = { + 0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL, + 0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL, + 0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL, + 0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL, + 0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL, + 0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL, + 0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL, + 0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL, + 0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL, + 0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL, + 0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL, + 0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL, + 0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL, + 0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL, + 0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL, + 0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL, + 0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL, + 0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL, + 0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL, + 0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL, + 0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL, + 0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL, + 0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL, + 0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL, + 0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL, + 0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL, + 0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL, + 0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL, + 0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL, + 0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL, + 0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL, + 0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL, + 0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL, + 0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL, + 0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL, + 0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL, + 0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL, + 0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL, + 0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL, + 0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL, + 0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL, + 0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL, + 0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL, + 0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL, + 0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL, + 0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL, + 0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL, + 0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL, + 0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL, + 0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL, + 0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL, + 0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL, + 0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL, + 0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL, + 0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL, + 0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL, + 0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL, + 0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL, + 0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL, + 0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL, + 0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL, + 0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL, + 0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL, + 0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL, +}; +static const uint32 TE3[256] = { + + 0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL, + 0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL, + 0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL, + 0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL, + 0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL, + 0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL, + 0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL, + 0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL, + 0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL, + 0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL, + 0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL, + 0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL, + 0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL, + 0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL, + 0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL, + 0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL, + 0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL, + 0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL, + 0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL, + 0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL, + 0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL, + 0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL, + 0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL, + 0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL, + 0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL, + 0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL, + 0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL, + 0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL, + 0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL, + 0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL, + 0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL, + 0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL, + 0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL, + 0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL, + 0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL, + 0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL, + 0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL, + 0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL, + 0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL, + 0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL, + 0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL, + 0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL, + 0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL, + 0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL, + 0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL, + 0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL, + 0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL, + 0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL, + 0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL, + 0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL, + 0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL, + 0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL, + 0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL, + 0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL, + 0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL, + 0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL, + 0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL, + 0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL, + 0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL, + 0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL, + 0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL, + 0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL, + 0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL, + 0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL, +}; + +static const uint32 Te4_0[] = { +0x00000063UL, 0x0000007cUL, 0x00000077UL, 0x0000007bUL, 0x000000f2UL, 0x0000006bUL, 0x0000006fUL, 0x000000c5UL, +0x00000030UL, 0x00000001UL, 0x00000067UL, 0x0000002bUL, 0x000000feUL, 0x000000d7UL, 0x000000abUL, 0x00000076UL, +0x000000caUL, 0x00000082UL, 0x000000c9UL, 0x0000007dUL, 0x000000faUL, 0x00000059UL, 0x00000047UL, 0x000000f0UL, +0x000000adUL, 0x000000d4UL, 0x000000a2UL, 0x000000afUL, 0x0000009cUL, 0x000000a4UL, 0x00000072UL, 0x000000c0UL, +0x000000b7UL, 0x000000fdUL, 0x00000093UL, 0x00000026UL, 0x00000036UL, 0x0000003fUL, 0x000000f7UL, 0x000000ccUL, +0x00000034UL, 0x000000a5UL, 0x000000e5UL, 0x000000f1UL, 0x00000071UL, 0x000000d8UL, 0x00000031UL, 0x00000015UL, +0x00000004UL, 0x000000c7UL, 0x00000023UL, 0x000000c3UL, 0x00000018UL, 0x00000096UL, 0x00000005UL, 0x0000009aUL, +0x00000007UL, 0x00000012UL, 0x00000080UL, 0x000000e2UL, 0x000000ebUL, 0x00000027UL, 0x000000b2UL, 0x00000075UL, +0x00000009UL, 0x00000083UL, 0x0000002cUL, 0x0000001aUL, 0x0000001bUL, 0x0000006eUL, 0x0000005aUL, 0x000000a0UL, +0x00000052UL, 0x0000003bUL, 0x000000d6UL, 0x000000b3UL, 0x00000029UL, 0x000000e3UL, 0x0000002fUL, 0x00000084UL, +0x00000053UL, 0x000000d1UL, 0x00000000UL, 0x000000edUL, 0x00000020UL, 0x000000fcUL, 0x000000b1UL, 0x0000005bUL, +0x0000006aUL, 0x000000cbUL, 0x000000beUL, 0x00000039UL, 0x0000004aUL, 0x0000004cUL, 0x00000058UL, 0x000000cfUL, +0x000000d0UL, 0x000000efUL, 0x000000aaUL, 0x000000fbUL, 0x00000043UL, 0x0000004dUL, 0x00000033UL, 0x00000085UL, +0x00000045UL, 0x000000f9UL, 0x00000002UL, 0x0000007fUL, 0x00000050UL, 0x0000003cUL, 0x0000009fUL, 0x000000a8UL, +0x00000051UL, 0x000000a3UL, 0x00000040UL, 0x0000008fUL, 0x00000092UL, 0x0000009dUL, 0x00000038UL, 0x000000f5UL, +0x000000bcUL, 0x000000b6UL, 0x000000daUL, 0x00000021UL, 0x00000010UL, 0x000000ffUL, 0x000000f3UL, 0x000000d2UL, +0x000000cdUL, 0x0000000cUL, 0x00000013UL, 0x000000ecUL, 0x0000005fUL, 0x00000097UL, 0x00000044UL, 0x00000017UL, +0x000000c4UL, 0x000000a7UL, 0x0000007eUL, 0x0000003dUL, 0x00000064UL, 0x0000005dUL, 0x00000019UL, 0x00000073UL, +0x00000060UL, 0x00000081UL, 0x0000004fUL, 0x000000dcUL, 0x00000022UL, 0x0000002aUL, 0x00000090UL, 0x00000088UL, +0x00000046UL, 0x000000eeUL, 0x000000b8UL, 0x00000014UL, 0x000000deUL, 0x0000005eUL, 0x0000000bUL, 0x000000dbUL, +0x000000e0UL, 0x00000032UL, 0x0000003aUL, 0x0000000aUL, 0x00000049UL, 0x00000006UL, 0x00000024UL, 0x0000005cUL, +0x000000c2UL, 0x000000d3UL, 0x000000acUL, 0x00000062UL, 0x00000091UL, 0x00000095UL, 0x000000e4UL, 0x00000079UL, +0x000000e7UL, 0x000000c8UL, 0x00000037UL, 0x0000006dUL, 0x0000008dUL, 0x000000d5UL, 0x0000004eUL, 0x000000a9UL, +0x0000006cUL, 0x00000056UL, 0x000000f4UL, 0x000000eaUL, 0x00000065UL, 0x0000007aUL, 0x000000aeUL, 0x00000008UL, +0x000000baUL, 0x00000078UL, 0x00000025UL, 0x0000002eUL, 0x0000001cUL, 0x000000a6UL, 0x000000b4UL, 0x000000c6UL, +0x000000e8UL, 0x000000ddUL, 0x00000074UL, 0x0000001fUL, 0x0000004bUL, 0x000000bdUL, 0x0000008bUL, 0x0000008aUL, +0x00000070UL, 0x0000003eUL, 0x000000b5UL, 0x00000066UL, 0x00000048UL, 0x00000003UL, 0x000000f6UL, 0x0000000eUL, +0x00000061UL, 0x00000035UL, 0x00000057UL, 0x000000b9UL, 0x00000086UL, 0x000000c1UL, 0x0000001dUL, 0x0000009eUL, +0x000000e1UL, 0x000000f8UL, 0x00000098UL, 0x00000011UL, 0x00000069UL, 0x000000d9UL, 0x0000008eUL, 0x00000094UL, +0x0000009bUL, 0x0000001eUL, 0x00000087UL, 0x000000e9UL, 0x000000ceUL, 0x00000055UL, 0x00000028UL, 0x000000dfUL, +0x0000008cUL, 0x000000a1UL, 0x00000089UL, 0x0000000dUL, 0x000000bfUL, 0x000000e6UL, 0x00000042UL, 0x00000068UL, +0x00000041UL, 0x00000099UL, 0x0000002dUL, 0x0000000fUL, 0x000000b0UL, 0x00000054UL, 0x000000bbUL, 0x00000016UL +}; + +static const uint32 Te4_1[] = { +0x00006300UL, 0x00007c00UL, 0x00007700UL, 0x00007b00UL, 0x0000f200UL, 0x00006b00UL, 0x00006f00UL, 0x0000c500UL, +0x00003000UL, 0x00000100UL, 0x00006700UL, 0x00002b00UL, 0x0000fe00UL, 0x0000d700UL, 0x0000ab00UL, 0x00007600UL, +0x0000ca00UL, 0x00008200UL, 0x0000c900UL, 0x00007d00UL, 0x0000fa00UL, 0x00005900UL, 0x00004700UL, 0x0000f000UL, +0x0000ad00UL, 0x0000d400UL, 0x0000a200UL, 0x0000af00UL, 0x00009c00UL, 0x0000a400UL, 0x00007200UL, 0x0000c000UL, +0x0000b700UL, 0x0000fd00UL, 0x00009300UL, 0x00002600UL, 0x00003600UL, 0x00003f00UL, 0x0000f700UL, 0x0000cc00UL, +0x00003400UL, 0x0000a500UL, 0x0000e500UL, 0x0000f100UL, 0x00007100UL, 0x0000d800UL, 0x00003100UL, 0x00001500UL, +0x00000400UL, 0x0000c700UL, 0x00002300UL, 0x0000c300UL, 0x00001800UL, 0x00009600UL, 0x00000500UL, 0x00009a00UL, +0x00000700UL, 0x00001200UL, 0x00008000UL, 0x0000e200UL, 0x0000eb00UL, 0x00002700UL, 0x0000b200UL, 0x00007500UL, +0x00000900UL, 0x00008300UL, 0x00002c00UL, 0x00001a00UL, 0x00001b00UL, 0x00006e00UL, 0x00005a00UL, 0x0000a000UL, +0x00005200UL, 0x00003b00UL, 0x0000d600UL, 0x0000b300UL, 0x00002900UL, 0x0000e300UL, 0x00002f00UL, 0x00008400UL, +0x00005300UL, 0x0000d100UL, 0x00000000UL, 0x0000ed00UL, 0x00002000UL, 0x0000fc00UL, 0x0000b100UL, 0x00005b00UL, +0x00006a00UL, 0x0000cb00UL, 0x0000be00UL, 0x00003900UL, 0x00004a00UL, 0x00004c00UL, 0x00005800UL, 0x0000cf00UL, +0x0000d000UL, 0x0000ef00UL, 0x0000aa00UL, 0x0000fb00UL, 0x00004300UL, 0x00004d00UL, 0x00003300UL, 0x00008500UL, +0x00004500UL, 0x0000f900UL, 0x00000200UL, 0x00007f00UL, 0x00005000UL, 0x00003c00UL, 0x00009f00UL, 0x0000a800UL, +0x00005100UL, 0x0000a300UL, 0x00004000UL, 0x00008f00UL, 0x00009200UL, 0x00009d00UL, 0x00003800UL, 0x0000f500UL, +0x0000bc00UL, 0x0000b600UL, 0x0000da00UL, 0x00002100UL, 0x00001000UL, 0x0000ff00UL, 0x0000f300UL, 0x0000d200UL, +0x0000cd00UL, 0x00000c00UL, 0x00001300UL, 0x0000ec00UL, 0x00005f00UL, 0x00009700UL, 0x00004400UL, 0x00001700UL, +0x0000c400UL, 0x0000a700UL, 0x00007e00UL, 0x00003d00UL, 0x00006400UL, 0x00005d00UL, 0x00001900UL, 0x00007300UL, +0x00006000UL, 0x00008100UL, 0x00004f00UL, 0x0000dc00UL, 0x00002200UL, 0x00002a00UL, 0x00009000UL, 0x00008800UL, +0x00004600UL, 0x0000ee00UL, 0x0000b800UL, 0x00001400UL, 0x0000de00UL, 0x00005e00UL, 0x00000b00UL, 0x0000db00UL, +0x0000e000UL, 0x00003200UL, 0x00003a00UL, 0x00000a00UL, 0x00004900UL, 0x00000600UL, 0x00002400UL, 0x00005c00UL, +0x0000c200UL, 0x0000d300UL, 0x0000ac00UL, 0x00006200UL, 0x00009100UL, 0x00009500UL, 0x0000e400UL, 0x00007900UL, +0x0000e700UL, 0x0000c800UL, 0x00003700UL, 0x00006d00UL, 0x00008d00UL, 0x0000d500UL, 0x00004e00UL, 0x0000a900UL, +0x00006c00UL, 0x00005600UL, 0x0000f400UL, 0x0000ea00UL, 0x00006500UL, 0x00007a00UL, 0x0000ae00UL, 0x00000800UL, +0x0000ba00UL, 0x00007800UL, 0x00002500UL, 0x00002e00UL, 0x00001c00UL, 0x0000a600UL, 0x0000b400UL, 0x0000c600UL, +0x0000e800UL, 0x0000dd00UL, 0x00007400UL, 0x00001f00UL, 0x00004b00UL, 0x0000bd00UL, 0x00008b00UL, 0x00008a00UL, +0x00007000UL, 0x00003e00UL, 0x0000b500UL, 0x00006600UL, 0x00004800UL, 0x00000300UL, 0x0000f600UL, 0x00000e00UL, +0x00006100UL, 0x00003500UL, 0x00005700UL, 0x0000b900UL, 0x00008600UL, 0x0000c100UL, 0x00001d00UL, 0x00009e00UL, +0x0000e100UL, 0x0000f800UL, 0x00009800UL, 0x00001100UL, 0x00006900UL, 0x0000d900UL, 0x00008e00UL, 0x00009400UL, +0x00009b00UL, 0x00001e00UL, 0x00008700UL, 0x0000e900UL, 0x0000ce00UL, 0x00005500UL, 0x00002800UL, 0x0000df00UL, +0x00008c00UL, 0x0000a100UL, 0x00008900UL, 0x00000d00UL, 0x0000bf00UL, 0x0000e600UL, 0x00004200UL, 0x00006800UL, +0x00004100UL, 0x00009900UL, 0x00002d00UL, 0x00000f00UL, 0x0000b000UL, 0x00005400UL, 0x0000bb00UL, 0x00001600UL +}; + +static const uint32 Te4_2[] = { +0x00630000UL, 0x007c0000UL, 0x00770000UL, 0x007b0000UL, 0x00f20000UL, 0x006b0000UL, 0x006f0000UL, 0x00c50000UL, +0x00300000UL, 0x00010000UL, 0x00670000UL, 0x002b0000UL, 0x00fe0000UL, 0x00d70000UL, 0x00ab0000UL, 0x00760000UL, +0x00ca0000UL, 0x00820000UL, 0x00c90000UL, 0x007d0000UL, 0x00fa0000UL, 0x00590000UL, 0x00470000UL, 0x00f00000UL, +0x00ad0000UL, 0x00d40000UL, 0x00a20000UL, 0x00af0000UL, 0x009c0000UL, 0x00a40000UL, 0x00720000UL, 0x00c00000UL, +0x00b70000UL, 0x00fd0000UL, 0x00930000UL, 0x00260000UL, 0x00360000UL, 0x003f0000UL, 0x00f70000UL, 0x00cc0000UL, +0x00340000UL, 0x00a50000UL, 0x00e50000UL, 0x00f10000UL, 0x00710000UL, 0x00d80000UL, 0x00310000UL, 0x00150000UL, +0x00040000UL, 0x00c70000UL, 0x00230000UL, 0x00c30000UL, 0x00180000UL, 0x00960000UL, 0x00050000UL, 0x009a0000UL, +0x00070000UL, 0x00120000UL, 0x00800000UL, 0x00e20000UL, 0x00eb0000UL, 0x00270000UL, 0x00b20000UL, 0x00750000UL, +0x00090000UL, 0x00830000UL, 0x002c0000UL, 0x001a0000UL, 0x001b0000UL, 0x006e0000UL, 0x005a0000UL, 0x00a00000UL, +0x00520000UL, 0x003b0000UL, 0x00d60000UL, 0x00b30000UL, 0x00290000UL, 0x00e30000UL, 0x002f0000UL, 0x00840000UL, +0x00530000UL, 0x00d10000UL, 0x00000000UL, 0x00ed0000UL, 0x00200000UL, 0x00fc0000UL, 0x00b10000UL, 0x005b0000UL, +0x006a0000UL, 0x00cb0000UL, 0x00be0000UL, 0x00390000UL, 0x004a0000UL, 0x004c0000UL, 0x00580000UL, 0x00cf0000UL, +0x00d00000UL, 0x00ef0000UL, 0x00aa0000UL, 0x00fb0000UL, 0x00430000UL, 0x004d0000UL, 0x00330000UL, 0x00850000UL, +0x00450000UL, 0x00f90000UL, 0x00020000UL, 0x007f0000UL, 0x00500000UL, 0x003c0000UL, 0x009f0000UL, 0x00a80000UL, +0x00510000UL, 0x00a30000UL, 0x00400000UL, 0x008f0000UL, 0x00920000UL, 0x009d0000UL, 0x00380000UL, 0x00f50000UL, +0x00bc0000UL, 0x00b60000UL, 0x00da0000UL, 0x00210000UL, 0x00100000UL, 0x00ff0000UL, 0x00f30000UL, 0x00d20000UL, +0x00cd0000UL, 0x000c0000UL, 0x00130000UL, 0x00ec0000UL, 0x005f0000UL, 0x00970000UL, 0x00440000UL, 0x00170000UL, +0x00c40000UL, 0x00a70000UL, 0x007e0000UL, 0x003d0000UL, 0x00640000UL, 0x005d0000UL, 0x00190000UL, 0x00730000UL, +0x00600000UL, 0x00810000UL, 0x004f0000UL, 0x00dc0000UL, 0x00220000UL, 0x002a0000UL, 0x00900000UL, 0x00880000UL, +0x00460000UL, 0x00ee0000UL, 0x00b80000UL, 0x00140000UL, 0x00de0000UL, 0x005e0000UL, 0x000b0000UL, 0x00db0000UL, +0x00e00000UL, 0x00320000UL, 0x003a0000UL, 0x000a0000UL, 0x00490000UL, 0x00060000UL, 0x00240000UL, 0x005c0000UL, +0x00c20000UL, 0x00d30000UL, 0x00ac0000UL, 0x00620000UL, 0x00910000UL, 0x00950000UL, 0x00e40000UL, 0x00790000UL, +0x00e70000UL, 0x00c80000UL, 0x00370000UL, 0x006d0000UL, 0x008d0000UL, 0x00d50000UL, 0x004e0000UL, 0x00a90000UL, +0x006c0000UL, 0x00560000UL, 0x00f40000UL, 0x00ea0000UL, 0x00650000UL, 0x007a0000UL, 0x00ae0000UL, 0x00080000UL, +0x00ba0000UL, 0x00780000UL, 0x00250000UL, 0x002e0000UL, 0x001c0000UL, 0x00a60000UL, 0x00b40000UL, 0x00c60000UL, +0x00e80000UL, 0x00dd0000UL, 0x00740000UL, 0x001f0000UL, 0x004b0000UL, 0x00bd0000UL, 0x008b0000UL, 0x008a0000UL, +0x00700000UL, 0x003e0000UL, 0x00b50000UL, 0x00660000UL, 0x00480000UL, 0x00030000UL, 0x00f60000UL, 0x000e0000UL, +0x00610000UL, 0x00350000UL, 0x00570000UL, 0x00b90000UL, 0x00860000UL, 0x00c10000UL, 0x001d0000UL, 0x009e0000UL, +0x00e10000UL, 0x00f80000UL, 0x00980000UL, 0x00110000UL, 0x00690000UL, 0x00d90000UL, 0x008e0000UL, 0x00940000UL, +0x009b0000UL, 0x001e0000UL, 0x00870000UL, 0x00e90000UL, 0x00ce0000UL, 0x00550000UL, 0x00280000UL, 0x00df0000UL, +0x008c0000UL, 0x00a10000UL, 0x00890000UL, 0x000d0000UL, 0x00bf0000UL, 0x00e60000UL, 0x00420000UL, 0x00680000UL, +0x00410000UL, 0x00990000UL, 0x002d0000UL, 0x000f0000UL, 0x00b00000UL, 0x00540000UL, 0x00bb0000UL, 0x00160000UL +}; + +static const uint32 Te4_3[] = { +0x63000000UL, 0x7c000000UL, 0x77000000UL, 0x7b000000UL, 0xf2000000UL, 0x6b000000UL, 0x6f000000UL, 0xc5000000UL, +0x30000000UL, 0x01000000UL, 0x67000000UL, 0x2b000000UL, 0xfe000000UL, 0xd7000000UL, 0xab000000UL, 0x76000000UL, +0xca000000UL, 0x82000000UL, 0xc9000000UL, 0x7d000000UL, 0xfa000000UL, 0x59000000UL, 0x47000000UL, 0xf0000000UL, +0xad000000UL, 0xd4000000UL, 0xa2000000UL, 0xaf000000UL, 0x9c000000UL, 0xa4000000UL, 0x72000000UL, 0xc0000000UL, +0xb7000000UL, 0xfd000000UL, 0x93000000UL, 0x26000000UL, 0x36000000UL, 0x3f000000UL, 0xf7000000UL, 0xcc000000UL, +0x34000000UL, 0xa5000000UL, 0xe5000000UL, 0xf1000000UL, 0x71000000UL, 0xd8000000UL, 0x31000000UL, 0x15000000UL, +0x04000000UL, 0xc7000000UL, 0x23000000UL, 0xc3000000UL, 0x18000000UL, 0x96000000UL, 0x05000000UL, 0x9a000000UL, +0x07000000UL, 0x12000000UL, 0x80000000UL, 0xe2000000UL, 0xeb000000UL, 0x27000000UL, 0xb2000000UL, 0x75000000UL, +0x09000000UL, 0x83000000UL, 0x2c000000UL, 0x1a000000UL, 0x1b000000UL, 0x6e000000UL, 0x5a000000UL, 0xa0000000UL, +0x52000000UL, 0x3b000000UL, 0xd6000000UL, 0xb3000000UL, 0x29000000UL, 0xe3000000UL, 0x2f000000UL, 0x84000000UL, +0x53000000UL, 0xd1000000UL, 0x00000000UL, 0xed000000UL, 0x20000000UL, 0xfc000000UL, 0xb1000000UL, 0x5b000000UL, +0x6a000000UL, 0xcb000000UL, 0xbe000000UL, 0x39000000UL, 0x4a000000UL, 0x4c000000UL, 0x58000000UL, 0xcf000000UL, +0xd0000000UL, 0xef000000UL, 0xaa000000UL, 0xfb000000UL, 0x43000000UL, 0x4d000000UL, 0x33000000UL, 0x85000000UL, +0x45000000UL, 0xf9000000UL, 0x02000000UL, 0x7f000000UL, 0x50000000UL, 0x3c000000UL, 0x9f000000UL, 0xa8000000UL, +0x51000000UL, 0xa3000000UL, 0x40000000UL, 0x8f000000UL, 0x92000000UL, 0x9d000000UL, 0x38000000UL, 0xf5000000UL, +0xbc000000UL, 0xb6000000UL, 0xda000000UL, 0x21000000UL, 0x10000000UL, 0xff000000UL, 0xf3000000UL, 0xd2000000UL, +0xcd000000UL, 0x0c000000UL, 0x13000000UL, 0xec000000UL, 0x5f000000UL, 0x97000000UL, 0x44000000UL, 0x17000000UL, +0xc4000000UL, 0xa7000000UL, 0x7e000000UL, 0x3d000000UL, 0x64000000UL, 0x5d000000UL, 0x19000000UL, 0x73000000UL, +0x60000000UL, 0x81000000UL, 0x4f000000UL, 0xdc000000UL, 0x22000000UL, 0x2a000000UL, 0x90000000UL, 0x88000000UL, +0x46000000UL, 0xee000000UL, 0xb8000000UL, 0x14000000UL, 0xde000000UL, 0x5e000000UL, 0x0b000000UL, 0xdb000000UL, +0xe0000000UL, 0x32000000UL, 0x3a000000UL, 0x0a000000UL, 0x49000000UL, 0x06000000UL, 0x24000000UL, 0x5c000000UL, +0xc2000000UL, 0xd3000000UL, 0xac000000UL, 0x62000000UL, 0x91000000UL, 0x95000000UL, 0xe4000000UL, 0x79000000UL, +0xe7000000UL, 0xc8000000UL, 0x37000000UL, 0x6d000000UL, 0x8d000000UL, 0xd5000000UL, 0x4e000000UL, 0xa9000000UL, +0x6c000000UL, 0x56000000UL, 0xf4000000UL, 0xea000000UL, 0x65000000UL, 0x7a000000UL, 0xae000000UL, 0x08000000UL, +0xba000000UL, 0x78000000UL, 0x25000000UL, 0x2e000000UL, 0x1c000000UL, 0xa6000000UL, 0xb4000000UL, 0xc6000000UL, +0xe8000000UL, 0xdd000000UL, 0x74000000UL, 0x1f000000UL, 0x4b000000UL, 0xbd000000UL, 0x8b000000UL, 0x8a000000UL, +0x70000000UL, 0x3e000000UL, 0xb5000000UL, 0x66000000UL, 0x48000000UL, 0x03000000UL, 0xf6000000UL, 0x0e000000UL, +0x61000000UL, 0x35000000UL, 0x57000000UL, 0xb9000000UL, 0x86000000UL, 0xc1000000UL, 0x1d000000UL, 0x9e000000UL, +0xe1000000UL, 0xf8000000UL, 0x98000000UL, 0x11000000UL, 0x69000000UL, 0xd9000000UL, 0x8e000000UL, 0x94000000UL, +0x9b000000UL, 0x1e000000UL, 0x87000000UL, 0xe9000000UL, 0xce000000UL, 0x55000000UL, 0x28000000UL, 0xdf000000UL, +0x8c000000UL, 0xa1000000UL, 0x89000000UL, 0x0d000000UL, 0xbf000000UL, 0xe6000000UL, 0x42000000UL, 0x68000000UL, +0x41000000UL, 0x99000000UL, 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 0x16000000UL +}; + +static const uint32 TD1[256] = { + 0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL, + 0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL, + 0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL, + 0xfc4fe5d7UL, 0xd7c52acbUL, 0x80263544UL, 0x8fb562a3UL, + 0x49deb15aUL, 0x6725ba1bUL, 0x9845ea0eUL, 0xe15dfec0UL, + 0x02c32f75UL, 0x12814cf0UL, 0xa38d4697UL, 0xc66bd3f9UL, + 0xe7038f5fUL, 0x9515929cUL, 0xebbf6d7aUL, 0xda955259UL, + 0x2dd4be83UL, 0xd3587421UL, 0x2949e069UL, 0x448ec9c8UL, + 0x6a75c289UL, 0x78f48e79UL, 0x6b99583eUL, 0xdd27b971UL, + 0xb6bee14fUL, 0x17f088adUL, 0x66c920acUL, 0xb47dce3aUL, + 0x1863df4aUL, 0x82e51a31UL, 0x60975133UL, 0x4562537fUL, + 0xe0b16477UL, 0x84bb6baeUL, 0x1cfe81a0UL, 0x94f9082bUL, + 0x58704868UL, 0x198f45fdUL, 0x8794de6cUL, 0xb7527bf8UL, + 0x23ab73d3UL, 0xe2724b02UL, 0x57e31f8fUL, 0x2a6655abUL, + 0x07b2eb28UL, 0x032fb5c2UL, 0x9a86c57bUL, 0xa5d33708UL, + 0xf2302887UL, 0xb223bfa5UL, 0xba02036aUL, 0x5ced1682UL, + 0x2b8acf1cUL, 0x92a779b4UL, 0xf0f307f2UL, 0xa14e69e2UL, + 0xcd65daf4UL, 0xd50605beUL, 0x1fd13462UL, 0x8ac4a6feUL, + 0x9d342e53UL, 0xa0a2f355UL, 0x32058ae1UL, 0x75a4f6ebUL, + 0x390b83ecUL, 0xaa4060efUL, 0x065e719fUL, 0x51bd6e10UL, + 0xf93e218aUL, 0x3d96dd06UL, 0xaedd3e05UL, 0x464de6bdUL, + 0xb591548dUL, 0x0571c45dUL, 0x6f0406d4UL, 0xff605015UL, + 0x241998fbUL, 0x97d6bde9UL, 0xcc894043UL, 0x7767d99eUL, + 0xbdb0e842UL, 0x8807898bUL, 0x38e7195bUL, 0xdb79c8eeUL, + 0x47a17c0aUL, 0xe97c420fUL, 0xc9f8841eUL, 0x00000000UL, + 0x83098086UL, 0x48322bedUL, 0xac1e1170UL, 0x4e6c5a72UL, + 0xfbfd0effUL, 0x560f8538UL, 0x1e3daed5UL, 0x27362d39UL, + 0x640a0fd9UL, 0x21685ca6UL, 0xd19b5b54UL, 0x3a24362eUL, + 0xb10c0a67UL, 0x0f9357e7UL, 0xd2b4ee96UL, 0x9e1b9b91UL, + 0x4f80c0c5UL, 0xa261dc20UL, 0x695a774bUL, 0x161c121aUL, + 0x0ae293baUL, 0xe5c0a02aUL, 0x433c22e0UL, 0x1d121b17UL, + 0x0b0e090dUL, 0xadf28bc7UL, 0xb92db6a8UL, 0xc8141ea9UL, + 0x8557f119UL, 0x4caf7507UL, 0xbbee99ddUL, 0xfda37f60UL, + 0x9ff70126UL, 0xbc5c72f5UL, 0xc544663bUL, 0x345bfb7eUL, + 0x768b4329UL, 0xdccb23c6UL, 0x68b6edfcUL, 0x63b8e4f1UL, + 0xcad731dcUL, 0x10426385UL, 0x40139722UL, 0x2084c611UL, + 0x7d854a24UL, 0xf8d2bb3dUL, 0x11aef932UL, 0x6dc729a1UL, + 0x4b1d9e2fUL, 0xf3dcb230UL, 0xec0d8652UL, 0xd077c1e3UL, + 0x6c2bb316UL, 0x99a970b9UL, 0xfa119448UL, 0x2247e964UL, + 0xc4a8fc8cUL, 0x1aa0f03fUL, 0xd8567d2cUL, 0xef223390UL, + 0xc787494eUL, 0xc1d938d1UL, 0xfe8ccaa2UL, 0x3698d40bUL, + 0xcfa6f581UL, 0x28a57adeUL, 0x26dab78eUL, 0xa43fadbfUL, + 0xe42c3a9dUL, 0x0d507892UL, 0x9b6a5fccUL, 0x62547e46UL, + 0xc2f68d13UL, 0xe890d8b8UL, 0x5e2e39f7UL, 0xf582c3afUL, + 0xbe9f5d80UL, 0x7c69d093UL, 0xa96fd52dUL, 0xb3cf2512UL, + 0x3bc8ac99UL, 0xa710187dUL, 0x6ee89c63UL, 0x7bdb3bbbUL, + 0x09cd2678UL, 0xf46e5918UL, 0x01ec9ab7UL, 0xa8834f9aUL, + 0x65e6956eUL, 0x7eaaffe6UL, 0x0821bccfUL, 0xe6ef15e8UL, + 0xd9bae79bUL, 0xce4a6f36UL, 0xd4ea9f09UL, 0xd629b07cUL, + 0xaf31a4b2UL, 0x312a3f23UL, 0x30c6a594UL, 0xc035a266UL, + 0x37744ebcUL, 0xa6fc82caUL, 0xb0e090d0UL, 0x1533a7d8UL, + 0x4af10498UL, 0xf741ecdaUL, 0x0e7fcd50UL, 0x2f1791f6UL, + 0x8d764dd6UL, 0x4d43efb0UL, 0x54ccaa4dUL, 0xdfe49604UL, + 0xe39ed1b5UL, 0x1b4c6a88UL, 0xb8c12c1fUL, 0x7f466551UL, + 0x049d5eeaUL, 0x5d018c35UL, 0x73fa8774UL, 0x2efb0b41UL, + 0x5ab3671dUL, 0x5292dbd2UL, 0x33e91056UL, 0x136dd647UL, + 0x8c9ad761UL, 0x7a37a10cUL, 0x8e59f814UL, 0x89eb133cUL, + 0xeecea927UL, 0x35b761c9UL, 0xede11ce5UL, 0x3c7a47b1UL, + 0x599cd2dfUL, 0x3f55f273UL, 0x791814ceUL, 0xbf73c737UL, + 0xea53f7cdUL, 0x5b5ffdaaUL, 0x14df3d6fUL, 0x867844dbUL, + 0x81caaff3UL, 0x3eb968c4UL, 0x2c382434UL, 0x5fc2a340UL, + 0x72161dc3UL, 0x0cbce225UL, 0x8b283c49UL, 0x41ff0d95UL, + 0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL, + 0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL, +}; +static const uint32 TD2[256] = { + 0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL, + 0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL, + 0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL, + 0xd7fc4fe5UL, 0xcbd7c52aUL, 0x44802635UL, 0xa38fb562UL, + 0x5a49deb1UL, 0x1b6725baUL, 0x0e9845eaUL, 0xc0e15dfeUL, + 0x7502c32fUL, 0xf012814cUL, 0x97a38d46UL, 0xf9c66bd3UL, + 0x5fe7038fUL, 0x9c951592UL, 0x7aebbf6dUL, 0x59da9552UL, + 0x832dd4beUL, 0x21d35874UL, 0x692949e0UL, 0xc8448ec9UL, + 0x896a75c2UL, 0x7978f48eUL, 0x3e6b9958UL, 0x71dd27b9UL, + 0x4fb6bee1UL, 0xad17f088UL, 0xac66c920UL, 0x3ab47dceUL, + 0x4a1863dfUL, 0x3182e51aUL, 0x33609751UL, 0x7f456253UL, + 0x77e0b164UL, 0xae84bb6bUL, 0xa01cfe81UL, 0x2b94f908UL, + 0x68587048UL, 0xfd198f45UL, 0x6c8794deUL, 0xf8b7527bUL, + 0xd323ab73UL, 0x02e2724bUL, 0x8f57e31fUL, 0xab2a6655UL, + 0x2807b2ebUL, 0xc2032fb5UL, 0x7b9a86c5UL, 0x08a5d337UL, + 0x87f23028UL, 0xa5b223bfUL, 0x6aba0203UL, 0x825ced16UL, + 0x1c2b8acfUL, 0xb492a779UL, 0xf2f0f307UL, 0xe2a14e69UL, + 0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL, + 0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL, + 0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL, + 0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL, + 0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL, + 0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL, + 0x42bdb0e8UL, 0x8b880789UL, 0x5b38e719UL, 0xeedb79c8UL, + 0x0a47a17cUL, 0x0fe97c42UL, 0x1ec9f884UL, 0x00000000UL, + 0x86830980UL, 0xed48322bUL, 0x70ac1e11UL, 0x724e6c5aUL, + 0xfffbfd0eUL, 0x38560f85UL, 0xd51e3daeUL, 0x3927362dUL, + 0xd9640a0fUL, 0xa621685cUL, 0x54d19b5bUL, 0x2e3a2436UL, + 0x67b10c0aUL, 0xe70f9357UL, 0x96d2b4eeUL, 0x919e1b9bUL, + 0xc54f80c0UL, 0x20a261dcUL, 0x4b695a77UL, 0x1a161c12UL, + 0xba0ae293UL, 0x2ae5c0a0UL, 0xe0433c22UL, 0x171d121bUL, + 0x0d0b0e09UL, 0xc7adf28bUL, 0xa8b92db6UL, 0xa9c8141eUL, + 0x198557f1UL, 0x074caf75UL, 0xddbbee99UL, 0x60fda37fUL, + 0x269ff701UL, 0xf5bc5c72UL, 0x3bc54466UL, 0x7e345bfbUL, + 0x29768b43UL, 0xc6dccb23UL, 0xfc68b6edUL, 0xf163b8e4UL, + 0xdccad731UL, 0x85104263UL, 0x22401397UL, 0x112084c6UL, + 0x247d854aUL, 0x3df8d2bbUL, 0x3211aef9UL, 0xa16dc729UL, + 0x2f4b1d9eUL, 0x30f3dcb2UL, 0x52ec0d86UL, 0xe3d077c1UL, + 0x166c2bb3UL, 0xb999a970UL, 0x48fa1194UL, 0x642247e9UL, + 0x8cc4a8fcUL, 0x3f1aa0f0UL, 0x2cd8567dUL, 0x90ef2233UL, + 0x4ec78749UL, 0xd1c1d938UL, 0xa2fe8ccaUL, 0x0b3698d4UL, + 0x81cfa6f5UL, 0xde28a57aUL, 0x8e26dab7UL, 0xbfa43fadUL, + 0x9de42c3aUL, 0x920d5078UL, 0xcc9b6a5fUL, 0x4662547eUL, + 0x13c2f68dUL, 0xb8e890d8UL, 0xf75e2e39UL, 0xaff582c3UL, + 0x80be9f5dUL, 0x937c69d0UL, 0x2da96fd5UL, 0x12b3cf25UL, + 0x993bc8acUL, 0x7da71018UL, 0x636ee89cUL, 0xbb7bdb3bUL, + 0x7809cd26UL, 0x18f46e59UL, 0xb701ec9aUL, 0x9aa8834fUL, + 0x6e65e695UL, 0xe67eaaffUL, 0xcf0821bcUL, 0xe8e6ef15UL, + 0x9bd9bae7UL, 0x36ce4a6fUL, 0x09d4ea9fUL, 0x7cd629b0UL, + 0xb2af31a4UL, 0x23312a3fUL, 0x9430c6a5UL, 0x66c035a2UL, + 0xbc37744eUL, 0xcaa6fc82UL, 0xd0b0e090UL, 0xd81533a7UL, + 0x984af104UL, 0xdaf741ecUL, 0x500e7fcdUL, 0xf62f1791UL, + 0xd68d764dUL, 0xb04d43efUL, 0x4d54ccaaUL, 0x04dfe496UL, + 0xb5e39ed1UL, 0x881b4c6aUL, 0x1fb8c12cUL, 0x517f4665UL, + 0xea049d5eUL, 0x355d018cUL, 0x7473fa87UL, 0x412efb0bUL, + 0x1d5ab367UL, 0xd25292dbUL, 0x5633e910UL, 0x47136dd6UL, + 0x618c9ad7UL, 0x0c7a37a1UL, 0x148e59f8UL, 0x3c89eb13UL, + 0x27eecea9UL, 0xc935b761UL, 0xe5ede11cUL, 0xb13c7a47UL, + 0xdf599cd2UL, 0x733f55f2UL, 0xce791814UL, 0x37bf73c7UL, + 0xcdea53f7UL, 0xaa5b5ffdUL, 0x6f14df3dUL, 0xdb867844UL, + 0xf381caafUL, 0xc43eb968UL, 0x342c3824UL, 0x405fc2a3UL, + 0xc372161dUL, 0x250cbce2UL, 0x498b283cUL, 0x9541ff0dUL, + 0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL, + 0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL, +}; +static const uint32 TD3[256] = { + 0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL, + 0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL, + 0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL, + 0xe5d7fc4fUL, 0x2acbd7c5UL, 0x35448026UL, 0x62a38fb5UL, + 0xb15a49deUL, 0xba1b6725UL, 0xea0e9845UL, 0xfec0e15dUL, + 0x2f7502c3UL, 0x4cf01281UL, 0x4697a38dUL, 0xd3f9c66bUL, + 0x8f5fe703UL, 0x929c9515UL, 0x6d7aebbfUL, 0x5259da95UL, + 0xbe832dd4UL, 0x7421d358UL, 0xe0692949UL, 0xc9c8448eUL, + 0xc2896a75UL, 0x8e7978f4UL, 0x583e6b99UL, 0xb971dd27UL, + 0xe14fb6beUL, 0x88ad17f0UL, 0x20ac66c9UL, 0xce3ab47dUL, + 0xdf4a1863UL, 0x1a3182e5UL, 0x51336097UL, 0x537f4562UL, + 0x6477e0b1UL, 0x6bae84bbUL, 0x81a01cfeUL, 0x082b94f9UL, + 0x48685870UL, 0x45fd198fUL, 0xde6c8794UL, 0x7bf8b752UL, + 0x73d323abUL, 0x4b02e272UL, 0x1f8f57e3UL, 0x55ab2a66UL, + 0xeb2807b2UL, 0xb5c2032fUL, 0xc57b9a86UL, 0x3708a5d3UL, + 0x2887f230UL, 0xbfa5b223UL, 0x036aba02UL, 0x16825cedUL, + 0xcf1c2b8aUL, 0x79b492a7UL, 0x07f2f0f3UL, 0x69e2a14eUL, + 0xdaf4cd65UL, 0x05bed506UL, 0x34621fd1UL, 0xa6fe8ac4UL, + 0x2e539d34UL, 0xf355a0a2UL, 0x8ae13205UL, 0xf6eb75a4UL, + 0x83ec390bUL, 0x60efaa40UL, 0x719f065eUL, 0x6e1051bdUL, + 0x218af93eUL, 0xdd063d96UL, 0x3e05aeddUL, 0xe6bd464dUL, + 0x548db591UL, 0xc45d0571UL, 0x06d46f04UL, 0x5015ff60UL, + 0x98fb2419UL, 0xbde997d6UL, 0x4043cc89UL, 0xd99e7767UL, + 0xe842bdb0UL, 0x898b8807UL, 0x195b38e7UL, 0xc8eedb79UL, + 0x7c0a47a1UL, 0x420fe97cUL, 0x841ec9f8UL, 0x00000000UL, + 0x80868309UL, 0x2bed4832UL, 0x1170ac1eUL, 0x5a724e6cUL, + 0x0efffbfdUL, 0x8538560fUL, 0xaed51e3dUL, 0x2d392736UL, + 0x0fd9640aUL, 0x5ca62168UL, 0x5b54d19bUL, 0x362e3a24UL, + 0x0a67b10cUL, 0x57e70f93UL, 0xee96d2b4UL, 0x9b919e1bUL, + 0xc0c54f80UL, 0xdc20a261UL, 0x774b695aUL, 0x121a161cUL, + 0x93ba0ae2UL, 0xa02ae5c0UL, 0x22e0433cUL, 0x1b171d12UL, + 0x090d0b0eUL, 0x8bc7adf2UL, 0xb6a8b92dUL, 0x1ea9c814UL, + 0xf1198557UL, 0x75074cafUL, 0x99ddbbeeUL, 0x7f60fda3UL, + 0x01269ff7UL, 0x72f5bc5cUL, 0x663bc544UL, 0xfb7e345bUL, + 0x4329768bUL, 0x23c6dccbUL, 0xedfc68b6UL, 0xe4f163b8UL, + 0x31dccad7UL, 0x63851042UL, 0x97224013UL, 0xc6112084UL, + 0x4a247d85UL, 0xbb3df8d2UL, 0xf93211aeUL, 0x29a16dc7UL, + 0x9e2f4b1dUL, 0xb230f3dcUL, 0x8652ec0dUL, 0xc1e3d077UL, + 0xb3166c2bUL, 0x70b999a9UL, 0x9448fa11UL, 0xe9642247UL, + 0xfc8cc4a8UL, 0xf03f1aa0UL, 0x7d2cd856UL, 0x3390ef22UL, + 0x494ec787UL, 0x38d1c1d9UL, 0xcaa2fe8cUL, 0xd40b3698UL, + 0xf581cfa6UL, 0x7ade28a5UL, 0xb78e26daUL, 0xadbfa43fUL, + 0x3a9de42cUL, 0x78920d50UL, 0x5fcc9b6aUL, 0x7e466254UL, + 0x8d13c2f6UL, 0xd8b8e890UL, 0x39f75e2eUL, 0xc3aff582UL, + 0x5d80be9fUL, 0xd0937c69UL, 0xd52da96fUL, 0x2512b3cfUL, + 0xac993bc8UL, 0x187da710UL, 0x9c636ee8UL, 0x3bbb7bdbUL, + 0x267809cdUL, 0x5918f46eUL, 0x9ab701ecUL, 0x4f9aa883UL, + 0x956e65e6UL, 0xffe67eaaUL, 0xbccf0821UL, 0x15e8e6efUL, + 0xe79bd9baUL, 0x6f36ce4aUL, 0x9f09d4eaUL, 0xb07cd629UL, + 0xa4b2af31UL, 0x3f23312aUL, 0xa59430c6UL, 0xa266c035UL, + 0x4ebc3774UL, 0x82caa6fcUL, 0x90d0b0e0UL, 0xa7d81533UL, + 0x04984af1UL, 0xecdaf741UL, 0xcd500e7fUL, 0x91f62f17UL, + 0x4dd68d76UL, 0xefb04d43UL, 0xaa4d54ccUL, 0x9604dfe4UL, + 0xd1b5e39eUL, 0x6a881b4cUL, 0x2c1fb8c1UL, 0x65517f46UL, + 0x5eea049dUL, 0x8c355d01UL, 0x877473faUL, 0x0b412efbUL, + 0x671d5ab3UL, 0xdbd25292UL, 0x105633e9UL, 0xd647136dUL, + 0xd7618c9aUL, 0xa10c7a37UL, 0xf8148e59UL, 0x133c89ebUL, + 0xa927eeceUL, 0x61c935b7UL, 0x1ce5ede1UL, 0x47b13c7aUL, + 0xd2df599cUL, 0xf2733f55UL, 0x14ce7918UL, 0xc737bf73UL, + 0xf7cdea53UL, 0xfdaa5b5fUL, 0x3d6f14dfUL, 0x44db8678UL, + 0xaff381caUL, 0x68c43eb9UL, 0x24342c38UL, 0xa3405fc2UL, + 0x1dc37216UL, 0xe2250cbcUL, 0x3c498b28UL, 0x0d9541ffUL, + 0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL, + 0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL, +}; + +static const uint32 Tks0[] = { +0x00000000UL, 0x0e090d0bUL, 0x1c121a16UL, 0x121b171dUL, 0x3824342cUL, 0x362d3927UL, 0x24362e3aUL, 0x2a3f2331UL, +0x70486858UL, 0x7e416553UL, 0x6c5a724eUL, 0x62537f45UL, 0x486c5c74UL, 0x4665517fUL, 0x547e4662UL, 0x5a774b69UL, +0xe090d0b0UL, 0xee99ddbbUL, 0xfc82caa6UL, 0xf28bc7adUL, 0xd8b4e49cUL, 0xd6bde997UL, 0xc4a6fe8aUL, 0xcaaff381UL, +0x90d8b8e8UL, 0x9ed1b5e3UL, 0x8ccaa2feUL, 0x82c3aff5UL, 0xa8fc8cc4UL, 0xa6f581cfUL, 0xb4ee96d2UL, 0xbae79bd9UL, +0xdb3bbb7bUL, 0xd532b670UL, 0xc729a16dUL, 0xc920ac66UL, 0xe31f8f57UL, 0xed16825cUL, 0xff0d9541UL, 0xf104984aUL, +0xab73d323UL, 0xa57ade28UL, 0xb761c935UL, 0xb968c43eUL, 0x9357e70fUL, 0x9d5eea04UL, 0x8f45fd19UL, 0x814cf012UL, +0x3bab6bcbUL, 0x35a266c0UL, 0x27b971ddUL, 0x29b07cd6UL, 0x038f5fe7UL, 0x0d8652ecUL, 0x1f9d45f1UL, 0x119448faUL, +0x4be30393UL, 0x45ea0e98UL, 0x57f11985UL, 0x59f8148eUL, 0x73c737bfUL, 0x7dce3ab4UL, 0x6fd52da9UL, 0x61dc20a2UL, +0xad766df6UL, 0xa37f60fdUL, 0xb16477e0UL, 0xbf6d7aebUL, 0x955259daUL, 0x9b5b54d1UL, 0x894043ccUL, 0x87494ec7UL, +0xdd3e05aeUL, 0xd33708a5UL, 0xc12c1fb8UL, 0xcf2512b3UL, 0xe51a3182UL, 0xeb133c89UL, 0xf9082b94UL, 0xf701269fUL, +0x4de6bd46UL, 0x43efb04dUL, 0x51f4a750UL, 0x5ffdaa5bUL, 0x75c2896aUL, 0x7bcb8461UL, 0x69d0937cUL, 0x67d99e77UL, +0x3daed51eUL, 0x33a7d815UL, 0x21bccf08UL, 0x2fb5c203UL, 0x058ae132UL, 0x0b83ec39UL, 0x1998fb24UL, 0x1791f62fUL, +0x764dd68dUL, 0x7844db86UL, 0x6a5fcc9bUL, 0x6456c190UL, 0x4e69e2a1UL, 0x4060efaaUL, 0x527bf8b7UL, 0x5c72f5bcUL, +0x0605bed5UL, 0x080cb3deUL, 0x1a17a4c3UL, 0x141ea9c8UL, 0x3e218af9UL, 0x302887f2UL, 0x223390efUL, 0x2c3a9de4UL, +0x96dd063dUL, 0x98d40b36UL, 0x8acf1c2bUL, 0x84c61120UL, 0xaef93211UL, 0xa0f03f1aUL, 0xb2eb2807UL, 0xbce2250cUL, +0xe6956e65UL, 0xe89c636eUL, 0xfa877473UL, 0xf48e7978UL, 0xdeb15a49UL, 0xd0b85742UL, 0xc2a3405fUL, 0xccaa4d54UL, +0x41ecdaf7UL, 0x4fe5d7fcUL, 0x5dfec0e1UL, 0x53f7cdeaUL, 0x79c8eedbUL, 0x77c1e3d0UL, 0x65daf4cdUL, 0x6bd3f9c6UL, +0x31a4b2afUL, 0x3fadbfa4UL, 0x2db6a8b9UL, 0x23bfa5b2UL, 0x09808683UL, 0x07898b88UL, 0x15929c95UL, 0x1b9b919eUL, +0xa17c0a47UL, 0xaf75074cUL, 0xbd6e1051UL, 0xb3671d5aUL, 0x99583e6bUL, 0x97513360UL, 0x854a247dUL, 0x8b432976UL, +0xd134621fUL, 0xdf3d6f14UL, 0xcd267809UL, 0xc32f7502UL, 0xe9105633UL, 0xe7195b38UL, 0xf5024c25UL, 0xfb0b412eUL, +0x9ad7618cUL, 0x94de6c87UL, 0x86c57b9aUL, 0x88cc7691UL, 0xa2f355a0UL, 0xacfa58abUL, 0xbee14fb6UL, 0xb0e842bdUL, +0xea9f09d4UL, 0xe49604dfUL, 0xf68d13c2UL, 0xf8841ec9UL, 0xd2bb3df8UL, 0xdcb230f3UL, 0xcea927eeUL, 0xc0a02ae5UL, +0x7a47b13cUL, 0x744ebc37UL, 0x6655ab2aUL, 0x685ca621UL, 0x42638510UL, 0x4c6a881bUL, 0x5e719f06UL, 0x5078920dUL, +0x0a0fd964UL, 0x0406d46fUL, 0x161dc372UL, 0x1814ce79UL, 0x322bed48UL, 0x3c22e043UL, 0x2e39f75eUL, 0x2030fa55UL, +0xec9ab701UL, 0xe293ba0aUL, 0xf088ad17UL, 0xfe81a01cUL, 0xd4be832dUL, 0xdab78e26UL, 0xc8ac993bUL, 0xc6a59430UL, +0x9cd2df59UL, 0x92dbd252UL, 0x80c0c54fUL, 0x8ec9c844UL, 0xa4f6eb75UL, 0xaaffe67eUL, 0xb8e4f163UL, 0xb6edfc68UL, +0x0c0a67b1UL, 0x02036abaUL, 0x10187da7UL, 0x1e1170acUL, 0x342e539dUL, 0x3a275e96UL, 0x283c498bUL, 0x26354480UL, +0x7c420fe9UL, 0x724b02e2UL, 0x605015ffUL, 0x6e5918f4UL, 0x44663bc5UL, 0x4a6f36ceUL, 0x587421d3UL, 0x567d2cd8UL, +0x37a10c7aUL, 0x39a80171UL, 0x2bb3166cUL, 0x25ba1b67UL, 0x0f853856UL, 0x018c355dUL, 0x13972240UL, 0x1d9e2f4bUL, +0x47e96422UL, 0x49e06929UL, 0x5bfb7e34UL, 0x55f2733fUL, 0x7fcd500eUL, 0x71c45d05UL, 0x63df4a18UL, 0x6dd64713UL, +0xd731dccaUL, 0xd938d1c1UL, 0xcb23c6dcUL, 0xc52acbd7UL, 0xef15e8e6UL, 0xe11ce5edUL, 0xf307f2f0UL, 0xfd0efffbUL, +0xa779b492UL, 0xa970b999UL, 0xbb6bae84UL, 0xb562a38fUL, 0x9f5d80beUL, 0x91548db5UL, 0x834f9aa8UL, 0x8d4697a3UL +}; + +static const uint32 Tks1[] = { +0x00000000UL, 0x0b0e090dUL, 0x161c121aUL, 0x1d121b17UL, 0x2c382434UL, 0x27362d39UL, 0x3a24362eUL, 0x312a3f23UL, +0x58704868UL, 0x537e4165UL, 0x4e6c5a72UL, 0x4562537fUL, 0x74486c5cUL, 0x7f466551UL, 0x62547e46UL, 0x695a774bUL, +0xb0e090d0UL, 0xbbee99ddUL, 0xa6fc82caUL, 0xadf28bc7UL, 0x9cd8b4e4UL, 0x97d6bde9UL, 0x8ac4a6feUL, 0x81caaff3UL, +0xe890d8b8UL, 0xe39ed1b5UL, 0xfe8ccaa2UL, 0xf582c3afUL, 0xc4a8fc8cUL, 0xcfa6f581UL, 0xd2b4ee96UL, 0xd9bae79bUL, +0x7bdb3bbbUL, 0x70d532b6UL, 0x6dc729a1UL, 0x66c920acUL, 0x57e31f8fUL, 0x5ced1682UL, 0x41ff0d95UL, 0x4af10498UL, +0x23ab73d3UL, 0x28a57adeUL, 0x35b761c9UL, 0x3eb968c4UL, 0x0f9357e7UL, 0x049d5eeaUL, 0x198f45fdUL, 0x12814cf0UL, +0xcb3bab6bUL, 0xc035a266UL, 0xdd27b971UL, 0xd629b07cUL, 0xe7038f5fUL, 0xec0d8652UL, 0xf11f9d45UL, 0xfa119448UL, +0x934be303UL, 0x9845ea0eUL, 0x8557f119UL, 0x8e59f814UL, 0xbf73c737UL, 0xb47dce3aUL, 0xa96fd52dUL, 0xa261dc20UL, +0xf6ad766dUL, 0xfda37f60UL, 0xe0b16477UL, 0xebbf6d7aUL, 0xda955259UL, 0xd19b5b54UL, 0xcc894043UL, 0xc787494eUL, +0xaedd3e05UL, 0xa5d33708UL, 0xb8c12c1fUL, 0xb3cf2512UL, 0x82e51a31UL, 0x89eb133cUL, 0x94f9082bUL, 0x9ff70126UL, +0x464de6bdUL, 0x4d43efb0UL, 0x5051f4a7UL, 0x5b5ffdaaUL, 0x6a75c289UL, 0x617bcb84UL, 0x7c69d093UL, 0x7767d99eUL, +0x1e3daed5UL, 0x1533a7d8UL, 0x0821bccfUL, 0x032fb5c2UL, 0x32058ae1UL, 0x390b83ecUL, 0x241998fbUL, 0x2f1791f6UL, +0x8d764dd6UL, 0x867844dbUL, 0x9b6a5fccUL, 0x906456c1UL, 0xa14e69e2UL, 0xaa4060efUL, 0xb7527bf8UL, 0xbc5c72f5UL, +0xd50605beUL, 0xde080cb3UL, 0xc31a17a4UL, 0xc8141ea9UL, 0xf93e218aUL, 0xf2302887UL, 0xef223390UL, 0xe42c3a9dUL, +0x3d96dd06UL, 0x3698d40bUL, 0x2b8acf1cUL, 0x2084c611UL, 0x11aef932UL, 0x1aa0f03fUL, 0x07b2eb28UL, 0x0cbce225UL, +0x65e6956eUL, 0x6ee89c63UL, 0x73fa8774UL, 0x78f48e79UL, 0x49deb15aUL, 0x42d0b857UL, 0x5fc2a340UL, 0x54ccaa4dUL, +0xf741ecdaUL, 0xfc4fe5d7UL, 0xe15dfec0UL, 0xea53f7cdUL, 0xdb79c8eeUL, 0xd077c1e3UL, 0xcd65daf4UL, 0xc66bd3f9UL, +0xaf31a4b2UL, 0xa43fadbfUL, 0xb92db6a8UL, 0xb223bfa5UL, 0x83098086UL, 0x8807898bUL, 0x9515929cUL, 0x9e1b9b91UL, +0x47a17c0aUL, 0x4caf7507UL, 0x51bd6e10UL, 0x5ab3671dUL, 0x6b99583eUL, 0x60975133UL, 0x7d854a24UL, 0x768b4329UL, +0x1fd13462UL, 0x14df3d6fUL, 0x09cd2678UL, 0x02c32f75UL, 0x33e91056UL, 0x38e7195bUL, 0x25f5024cUL, 0x2efb0b41UL, +0x8c9ad761UL, 0x8794de6cUL, 0x9a86c57bUL, 0x9188cc76UL, 0xa0a2f355UL, 0xabacfa58UL, 0xb6bee14fUL, 0xbdb0e842UL, +0xd4ea9f09UL, 0xdfe49604UL, 0xc2f68d13UL, 0xc9f8841eUL, 0xf8d2bb3dUL, 0xf3dcb230UL, 0xeecea927UL, 0xe5c0a02aUL, +0x3c7a47b1UL, 0x37744ebcUL, 0x2a6655abUL, 0x21685ca6UL, 0x10426385UL, 0x1b4c6a88UL, 0x065e719fUL, 0x0d507892UL, +0x640a0fd9UL, 0x6f0406d4UL, 0x72161dc3UL, 0x791814ceUL, 0x48322bedUL, 0x433c22e0UL, 0x5e2e39f7UL, 0x552030faUL, +0x01ec9ab7UL, 0x0ae293baUL, 0x17f088adUL, 0x1cfe81a0UL, 0x2dd4be83UL, 0x26dab78eUL, 0x3bc8ac99UL, 0x30c6a594UL, +0x599cd2dfUL, 0x5292dbd2UL, 0x4f80c0c5UL, 0x448ec9c8UL, 0x75a4f6ebUL, 0x7eaaffe6UL, 0x63b8e4f1UL, 0x68b6edfcUL, +0xb10c0a67UL, 0xba02036aUL, 0xa710187dUL, 0xac1e1170UL, 0x9d342e53UL, 0x963a275eUL, 0x8b283c49UL, 0x80263544UL, +0xe97c420fUL, 0xe2724b02UL, 0xff605015UL, 0xf46e5918UL, 0xc544663bUL, 0xce4a6f36UL, 0xd3587421UL, 0xd8567d2cUL, +0x7a37a10cUL, 0x7139a801UL, 0x6c2bb316UL, 0x6725ba1bUL, 0x560f8538UL, 0x5d018c35UL, 0x40139722UL, 0x4b1d9e2fUL, +0x2247e964UL, 0x2949e069UL, 0x345bfb7eUL, 0x3f55f273UL, 0x0e7fcd50UL, 0x0571c45dUL, 0x1863df4aUL, 0x136dd647UL, +0xcad731dcUL, 0xc1d938d1UL, 0xdccb23c6UL, 0xd7c52acbUL, 0xe6ef15e8UL, 0xede11ce5UL, 0xf0f307f2UL, 0xfbfd0effUL, +0x92a779b4UL, 0x99a970b9UL, 0x84bb6baeUL, 0x8fb562a3UL, 0xbe9f5d80UL, 0xb591548dUL, 0xa8834f9aUL, 0xa38d4697UL +}; + +static const uint32 Tks2[] = { +0x00000000UL, 0x0d0b0e09UL, 0x1a161c12UL, 0x171d121bUL, 0x342c3824UL, 0x3927362dUL, 0x2e3a2436UL, 0x23312a3fUL, +0x68587048UL, 0x65537e41UL, 0x724e6c5aUL, 0x7f456253UL, 0x5c74486cUL, 0x517f4665UL, 0x4662547eUL, 0x4b695a77UL, +0xd0b0e090UL, 0xddbbee99UL, 0xcaa6fc82UL, 0xc7adf28bUL, 0xe49cd8b4UL, 0xe997d6bdUL, 0xfe8ac4a6UL, 0xf381caafUL, +0xb8e890d8UL, 0xb5e39ed1UL, 0xa2fe8ccaUL, 0xaff582c3UL, 0x8cc4a8fcUL, 0x81cfa6f5UL, 0x96d2b4eeUL, 0x9bd9bae7UL, +0xbb7bdb3bUL, 0xb670d532UL, 0xa16dc729UL, 0xac66c920UL, 0x8f57e31fUL, 0x825ced16UL, 0x9541ff0dUL, 0x984af104UL, +0xd323ab73UL, 0xde28a57aUL, 0xc935b761UL, 0xc43eb968UL, 0xe70f9357UL, 0xea049d5eUL, 0xfd198f45UL, 0xf012814cUL, +0x6bcb3babUL, 0x66c035a2UL, 0x71dd27b9UL, 0x7cd629b0UL, 0x5fe7038fUL, 0x52ec0d86UL, 0x45f11f9dUL, 0x48fa1194UL, +0x03934be3UL, 0x0e9845eaUL, 0x198557f1UL, 0x148e59f8UL, 0x37bf73c7UL, 0x3ab47dceUL, 0x2da96fd5UL, 0x20a261dcUL, +0x6df6ad76UL, 0x60fda37fUL, 0x77e0b164UL, 0x7aebbf6dUL, 0x59da9552UL, 0x54d19b5bUL, 0x43cc8940UL, 0x4ec78749UL, +0x05aedd3eUL, 0x08a5d337UL, 0x1fb8c12cUL, 0x12b3cf25UL, 0x3182e51aUL, 0x3c89eb13UL, 0x2b94f908UL, 0x269ff701UL, +0xbd464de6UL, 0xb04d43efUL, 0xa75051f4UL, 0xaa5b5ffdUL, 0x896a75c2UL, 0x84617bcbUL, 0x937c69d0UL, 0x9e7767d9UL, +0xd51e3daeUL, 0xd81533a7UL, 0xcf0821bcUL, 0xc2032fb5UL, 0xe132058aUL, 0xec390b83UL, 0xfb241998UL, 0xf62f1791UL, +0xd68d764dUL, 0xdb867844UL, 0xcc9b6a5fUL, 0xc1906456UL, 0xe2a14e69UL, 0xefaa4060UL, 0xf8b7527bUL, 0xf5bc5c72UL, +0xbed50605UL, 0xb3de080cUL, 0xa4c31a17UL, 0xa9c8141eUL, 0x8af93e21UL, 0x87f23028UL, 0x90ef2233UL, 0x9de42c3aUL, +0x063d96ddUL, 0x0b3698d4UL, 0x1c2b8acfUL, 0x112084c6UL, 0x3211aef9UL, 0x3f1aa0f0UL, 0x2807b2ebUL, 0x250cbce2UL, +0x6e65e695UL, 0x636ee89cUL, 0x7473fa87UL, 0x7978f48eUL, 0x5a49deb1UL, 0x5742d0b8UL, 0x405fc2a3UL, 0x4d54ccaaUL, +0xdaf741ecUL, 0xd7fc4fe5UL, 0xc0e15dfeUL, 0xcdea53f7UL, 0xeedb79c8UL, 0xe3d077c1UL, 0xf4cd65daUL, 0xf9c66bd3UL, +0xb2af31a4UL, 0xbfa43fadUL, 0xa8b92db6UL, 0xa5b223bfUL, 0x86830980UL, 0x8b880789UL, 0x9c951592UL, 0x919e1b9bUL, +0x0a47a17cUL, 0x074caf75UL, 0x1051bd6eUL, 0x1d5ab367UL, 0x3e6b9958UL, 0x33609751UL, 0x247d854aUL, 0x29768b43UL, +0x621fd134UL, 0x6f14df3dUL, 0x7809cd26UL, 0x7502c32fUL, 0x5633e910UL, 0x5b38e719UL, 0x4c25f502UL, 0x412efb0bUL, +0x618c9ad7UL, 0x6c8794deUL, 0x7b9a86c5UL, 0x769188ccUL, 0x55a0a2f3UL, 0x58abacfaUL, 0x4fb6bee1UL, 0x42bdb0e8UL, +0x09d4ea9fUL, 0x04dfe496UL, 0x13c2f68dUL, 0x1ec9f884UL, 0x3df8d2bbUL, 0x30f3dcb2UL, 0x27eecea9UL, 0x2ae5c0a0UL, +0xb13c7a47UL, 0xbc37744eUL, 0xab2a6655UL, 0xa621685cUL, 0x85104263UL, 0x881b4c6aUL, 0x9f065e71UL, 0x920d5078UL, +0xd9640a0fUL, 0xd46f0406UL, 0xc372161dUL, 0xce791814UL, 0xed48322bUL, 0xe0433c22UL, 0xf75e2e39UL, 0xfa552030UL, +0xb701ec9aUL, 0xba0ae293UL, 0xad17f088UL, 0xa01cfe81UL, 0x832dd4beUL, 0x8e26dab7UL, 0x993bc8acUL, 0x9430c6a5UL, +0xdf599cd2UL, 0xd25292dbUL, 0xc54f80c0UL, 0xc8448ec9UL, 0xeb75a4f6UL, 0xe67eaaffUL, 0xf163b8e4UL, 0xfc68b6edUL, +0x67b10c0aUL, 0x6aba0203UL, 0x7da71018UL, 0x70ac1e11UL, 0x539d342eUL, 0x5e963a27UL, 0x498b283cUL, 0x44802635UL, +0x0fe97c42UL, 0x02e2724bUL, 0x15ff6050UL, 0x18f46e59UL, 0x3bc54466UL, 0x36ce4a6fUL, 0x21d35874UL, 0x2cd8567dUL, +0x0c7a37a1UL, 0x017139a8UL, 0x166c2bb3UL, 0x1b6725baUL, 0x38560f85UL, 0x355d018cUL, 0x22401397UL, 0x2f4b1d9eUL, +0x642247e9UL, 0x692949e0UL, 0x7e345bfbUL, 0x733f55f2UL, 0x500e7fcdUL, 0x5d0571c4UL, 0x4a1863dfUL, 0x47136dd6UL, +0xdccad731UL, 0xd1c1d938UL, 0xc6dccb23UL, 0xcbd7c52aUL, 0xe8e6ef15UL, 0xe5ede11cUL, 0xf2f0f307UL, 0xfffbfd0eUL, +0xb492a779UL, 0xb999a970UL, 0xae84bb6bUL, 0xa38fb562UL, 0x80be9f5dUL, 0x8db59154UL, 0x9aa8834fUL, 0x97a38d46UL +}; + +static const uint32 Tks3[] = { +0x00000000UL, 0x090d0b0eUL, 0x121a161cUL, 0x1b171d12UL, 0x24342c38UL, 0x2d392736UL, 0x362e3a24UL, 0x3f23312aUL, +0x48685870UL, 0x4165537eUL, 0x5a724e6cUL, 0x537f4562UL, 0x6c5c7448UL, 0x65517f46UL, 0x7e466254UL, 0x774b695aUL, +0x90d0b0e0UL, 0x99ddbbeeUL, 0x82caa6fcUL, 0x8bc7adf2UL, 0xb4e49cd8UL, 0xbde997d6UL, 0xa6fe8ac4UL, 0xaff381caUL, +0xd8b8e890UL, 0xd1b5e39eUL, 0xcaa2fe8cUL, 0xc3aff582UL, 0xfc8cc4a8UL, 0xf581cfa6UL, 0xee96d2b4UL, 0xe79bd9baUL, +0x3bbb7bdbUL, 0x32b670d5UL, 0x29a16dc7UL, 0x20ac66c9UL, 0x1f8f57e3UL, 0x16825cedUL, 0x0d9541ffUL, 0x04984af1UL, +0x73d323abUL, 0x7ade28a5UL, 0x61c935b7UL, 0x68c43eb9UL, 0x57e70f93UL, 0x5eea049dUL, 0x45fd198fUL, 0x4cf01281UL, +0xab6bcb3bUL, 0xa266c035UL, 0xb971dd27UL, 0xb07cd629UL, 0x8f5fe703UL, 0x8652ec0dUL, 0x9d45f11fUL, 0x9448fa11UL, +0xe303934bUL, 0xea0e9845UL, 0xf1198557UL, 0xf8148e59UL, 0xc737bf73UL, 0xce3ab47dUL, 0xd52da96fUL, 0xdc20a261UL, +0x766df6adUL, 0x7f60fda3UL, 0x6477e0b1UL, 0x6d7aebbfUL, 0x5259da95UL, 0x5b54d19bUL, 0x4043cc89UL, 0x494ec787UL, +0x3e05aeddUL, 0x3708a5d3UL, 0x2c1fb8c1UL, 0x2512b3cfUL, 0x1a3182e5UL, 0x133c89ebUL, 0x082b94f9UL, 0x01269ff7UL, +0xe6bd464dUL, 0xefb04d43UL, 0xf4a75051UL, 0xfdaa5b5fUL, 0xc2896a75UL, 0xcb84617bUL, 0xd0937c69UL, 0xd99e7767UL, +0xaed51e3dUL, 0xa7d81533UL, 0xbccf0821UL, 0xb5c2032fUL, 0x8ae13205UL, 0x83ec390bUL, 0x98fb2419UL, 0x91f62f17UL, +0x4dd68d76UL, 0x44db8678UL, 0x5fcc9b6aUL, 0x56c19064UL, 0x69e2a14eUL, 0x60efaa40UL, 0x7bf8b752UL, 0x72f5bc5cUL, +0x05bed506UL, 0x0cb3de08UL, 0x17a4c31aUL, 0x1ea9c814UL, 0x218af93eUL, 0x2887f230UL, 0x3390ef22UL, 0x3a9de42cUL, +0xdd063d96UL, 0xd40b3698UL, 0xcf1c2b8aUL, 0xc6112084UL, 0xf93211aeUL, 0xf03f1aa0UL, 0xeb2807b2UL, 0xe2250cbcUL, +0x956e65e6UL, 0x9c636ee8UL, 0x877473faUL, 0x8e7978f4UL, 0xb15a49deUL, 0xb85742d0UL, 0xa3405fc2UL, 0xaa4d54ccUL, +0xecdaf741UL, 0xe5d7fc4fUL, 0xfec0e15dUL, 0xf7cdea53UL, 0xc8eedb79UL, 0xc1e3d077UL, 0xdaf4cd65UL, 0xd3f9c66bUL, +0xa4b2af31UL, 0xadbfa43fUL, 0xb6a8b92dUL, 0xbfa5b223UL, 0x80868309UL, 0x898b8807UL, 0x929c9515UL, 0x9b919e1bUL, +0x7c0a47a1UL, 0x75074cafUL, 0x6e1051bdUL, 0x671d5ab3UL, 0x583e6b99UL, 0x51336097UL, 0x4a247d85UL, 0x4329768bUL, +0x34621fd1UL, 0x3d6f14dfUL, 0x267809cdUL, 0x2f7502c3UL, 0x105633e9UL, 0x195b38e7UL, 0x024c25f5UL, 0x0b412efbUL, +0xd7618c9aUL, 0xde6c8794UL, 0xc57b9a86UL, 0xcc769188UL, 0xf355a0a2UL, 0xfa58abacUL, 0xe14fb6beUL, 0xe842bdb0UL, +0x9f09d4eaUL, 0x9604dfe4UL, 0x8d13c2f6UL, 0x841ec9f8UL, 0xbb3df8d2UL, 0xb230f3dcUL, 0xa927eeceUL, 0xa02ae5c0UL, +0x47b13c7aUL, 0x4ebc3774UL, 0x55ab2a66UL, 0x5ca62168UL, 0x63851042UL, 0x6a881b4cUL, 0x719f065eUL, 0x78920d50UL, +0x0fd9640aUL, 0x06d46f04UL, 0x1dc37216UL, 0x14ce7918UL, 0x2bed4832UL, 0x22e0433cUL, 0x39f75e2eUL, 0x30fa5520UL, +0x9ab701ecUL, 0x93ba0ae2UL, 0x88ad17f0UL, 0x81a01cfeUL, 0xbe832dd4UL, 0xb78e26daUL, 0xac993bc8UL, 0xa59430c6UL, +0xd2df599cUL, 0xdbd25292UL, 0xc0c54f80UL, 0xc9c8448eUL, 0xf6eb75a4UL, 0xffe67eaaUL, 0xe4f163b8UL, 0xedfc68b6UL, +0x0a67b10cUL, 0x036aba02UL, 0x187da710UL, 0x1170ac1eUL, 0x2e539d34UL, 0x275e963aUL, 0x3c498b28UL, 0x35448026UL, +0x420fe97cUL, 0x4b02e272UL, 0x5015ff60UL, 0x5918f46eUL, 0x663bc544UL, 0x6f36ce4aUL, 0x7421d358UL, 0x7d2cd856UL, +0xa10c7a37UL, 0xa8017139UL, 0xb3166c2bUL, 0xba1b6725UL, 0x8538560fUL, 0x8c355d01UL, 0x97224013UL, 0x9e2f4b1dUL, +0xe9642247UL, 0xe0692949UL, 0xfb7e345bUL, 0xf2733f55UL, 0xcd500e7fUL, 0xc45d0571UL, 0xdf4a1863UL, 0xd647136dUL, +0x31dccad7UL, 0x38d1c1d9UL, 0x23c6dccbUL, 0x2acbd7c5UL, 0x15e8e6efUL, 0x1ce5ede1UL, 0x07f2f0f3UL, 0x0efffbfdUL, +0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL +}; + +#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ + +/******************************************************************************/ +/* Macros for above */ + +#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE +#define Te0(x) TE0[x] +#define Te1(x) ROR(TE0[x], 8) +#define Te2(x) ROR(TE0[x], 16) +#define Te3(x) ROR(TE0[x], 24) +#define Td0(x) TD0[x] +#define Td1(x) ROR(TD0[x], 8) +#define Td2(x) ROR(TD0[x], 16) +#define Td3(x) ROR(TD0[x], 24) +#define Te4_0 0x000000FF & Te4 +#define Te4_1 0x0000FF00 & Te4 +#define Te4_2 0x00FF0000 & Te4 +#define Te4_3 0xFF000000 & Te4 +#else +#define Te0(x) TE0[x] +#define Te1(x) TE1[x] +#define Te2(x) TE2[x] +#define Te3(x) TE3[x] +#define Td0(x) TD0[x] +#define Td1(x) TD1[x] +#define Td2(x) TD2[x] +#define Td3(x) TD3[x] +#endif + +/******************************************************************************/ +#ifdef USE_BURN_STACK +static void _aes_ecb_encrypt(psAesKey_t *key, const unsigned char *pt, + unsigned char *ct); +void psAesEncryptBlock(psAesKey_t *key, const unsigned char *pt, + unsigned char *ct) +{ + _aes_ecb_encrypt(key, pt, ct); + psBurnStack(sizeof(uint32)*8 + sizeof(uint32*) + sizeof(int32)*2); +} +static void _aes_ecb_encrypt(psAesKey_t *key, const unsigned char *pt, + unsigned char *ct) +#else +void psAesEncryptBlock(psAesKey_t *key, const unsigned char *pt, + unsigned char *ct) +#endif /* USE_BURN_STACK */ +{ + uint32_t s0, s1, s2, s3, t0, t1, t2, t3, *rk; + int Nr, r; + +#ifdef CRYPTO_ASSERT + if (pt == NULL || ct == NULL || key == NULL || key->type != PS_AES_ENCRYPT) { + return; + } +#endif + + Nr = key->rounds; + rk = key->skey; + + /* Map byte array block to cipher state and add initial round key */ + LOAD32H(s0, pt ); s0 ^= rk[0]; + LOAD32H(s1, pt + 4); s1 ^= rk[1]; + LOAD32H(s2, pt + 8); s2 ^= rk[2]; + LOAD32H(s3, pt + 12); s3 ^= rk[3]; + +#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE + for (r = 0; ; r++) { + rk += 4; + t0 = + Te0(byte(s0, 3)) ^ + Te1(byte(s1, 2)) ^ + Te2(byte(s2, 1)) ^ + Te3(byte(s3, 0)) ^ + rk[0]; + t1 = + Te0(byte(s1, 3)) ^ + Te1(byte(s2, 2)) ^ + Te2(byte(s3, 1)) ^ + Te3(byte(s0, 0)) ^ + rk[1]; + t2 = + Te0(byte(s2, 3)) ^ + Te1(byte(s3, 2)) ^ + Te2(byte(s0, 1)) ^ + Te3(byte(s1, 0)) ^ + rk[2]; + t3 = + Te0(byte(s3, 3)) ^ + Te1(byte(s0, 2)) ^ + Te2(byte(s1, 1)) ^ + Te3(byte(s2, 0)) ^ + rk[3]; + if (r == Nr - 2) { + break; + } + s0 = t0; s1 = t1; s2 = t2; s3 = t3; + } + rk += 4; +#else /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ + + /* Nr - 1 full rounds */ + r = Nr >> 1; + for (;;) { + + t0 = + Te0(byte(s0, 3)) ^ + Te1(byte(s1, 2)) ^ + Te2(byte(s2, 1)) ^ + Te3(byte(s3, 0)) ^ + rk[4]; + t1 = + Te0(byte(s1, 3)) ^ + Te1(byte(s2, 2)) ^ + Te2(byte(s3, 1)) ^ + Te3(byte(s0, 0)) ^ + rk[5]; + t2 = + Te0(byte(s2, 3)) ^ + Te1(byte(s3, 2)) ^ + Te2(byte(s0, 1)) ^ + Te3(byte(s1, 0)) ^ + rk[6]; + t3 = + Te0(byte(s3, 3)) ^ + Te1(byte(s0, 2)) ^ + Te2(byte(s1, 1)) ^ + Te3(byte(s2, 0)) ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te0(byte(t0, 3)) ^ + Te1(byte(t1, 2)) ^ + Te2(byte(t2, 1)) ^ + Te3(byte(t3, 0)) ^ + rk[0]; + s1 = + Te0(byte(t1, 3)) ^ + Te1(byte(t2, 2)) ^ + Te2(byte(t3, 1)) ^ + Te3(byte(t0, 0)) ^ + rk[1]; + s2 = + Te0(byte(t2, 3)) ^ + Te1(byte(t3, 2)) ^ + Te2(byte(t0, 1)) ^ + Te3(byte(t1, 0)) ^ + rk[2]; + s3 = + Te0(byte(t3, 3)) ^ + Te1(byte(t0, 2)) ^ + Te2(byte(t1, 1)) ^ + Te3(byte(t2, 0)) ^ + rk[3]; + } +#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ + + /* Apply last round and map cipher state to byte array block */ + s0 = + (Te4_3[byte(t0, 3)]) ^ + (Te4_2[byte(t1, 2)]) ^ + (Te4_1[byte(t2, 1)]) ^ + (Te4_0[byte(t3, 0)]) ^ + rk[0]; + STORE32H(s0, ct); + s1 = + (Te4_3[byte(t1, 3)]) ^ + (Te4_2[byte(t2, 2)]) ^ + (Te4_1[byte(t3, 1)]) ^ + (Te4_0[byte(t0, 0)]) ^ + rk[1]; + STORE32H(s1, ct+4); + s2 = + (Te4_3[byte(t2, 3)]) ^ + (Te4_2[byte(t3, 2)]) ^ + (Te4_1[byte(t0, 1)]) ^ + (Te4_0[byte(t1, 0)]) ^ + rk[2]; + STORE32H(s2, ct+8); + s3 = + (Te4_3[byte(t3, 3)]) ^ + (Te4_2[byte(t0, 2)]) ^ + (Te4_1[byte(t1, 1)]) ^ + (Te4_0[byte(t2, 0)]) ^ + rk[3]; + STORE32H(s3, ct+12); +} + +#ifdef USE_BURN_STACK +static void _aes_ecb_decrypt(psAesKey_t *key, const unsigned char *ct, + unsigned char *pt); +void psAesDecryptBlock(psAesKey_t *key, const unsigned char *ct, + unsigned char *pt) +{ + _aes_ecb_decrypt(key, ct, pt); + psBurnStack(sizeof(uint32)*8 + sizeof(uint32*) + sizeof(int32)*2); +} +static void _aes_ecb_decrypt(psAesKey_t *key, const unsigned char *ct, + unsigned char *pt) +#else +void psAesDecryptBlock(psAesKey_t *key, const unsigned char *ct, + unsigned char *pt) +#endif /* USE_BURN_STACK */ +{ + uint32 s0, s1, s2, s3, t0, t1, t2, t3, *rk; + int32 Nr, r; + +#ifdef CRYPTO_ASSERT + if (pt == NULL || ct == NULL || key == NULL || key->type != PS_AES_DECRYPT) { + return; + } +#endif + + Nr = key->rounds; + rk = key->skey; + + /* Map byte array block to cipher state and add initial round key */ + LOAD32H(s0, ct ); s0 ^= rk[0]; + LOAD32H(s1, ct + 4); s1 ^= rk[1]; + LOAD32H(s2, ct + 8); s2 ^= rk[2]; + LOAD32H(s3, ct + 12); s3 ^= rk[3]; + +#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE + for (r = 0; ; r++) { + rk += 4; + t0 = + Td0(byte(s0, 3)) ^ + Td1(byte(s3, 2)) ^ + Td2(byte(s2, 1)) ^ + Td3(byte(s1, 0)) ^ + rk[0]; + t1 = + Td0(byte(s1, 3)) ^ + Td1(byte(s0, 2)) ^ + Td2(byte(s3, 1)) ^ + Td3(byte(s2, 0)) ^ + rk[1]; + t2 = + Td0(byte(s2, 3)) ^ + Td1(byte(s1, 2)) ^ + Td2(byte(s0, 1)) ^ + Td3(byte(s3, 0)) ^ + rk[2]; + t3 = + Td0(byte(s3, 3)) ^ + Td1(byte(s2, 2)) ^ + Td2(byte(s1, 1)) ^ + Td3(byte(s0, 0)) ^ + rk[3]; + if (r == Nr - 2) { + break; + } + s0 = t0; s1 = t1; s2 = t2; s3 = t3; + } + rk += 4; + +#else /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ + + /* Nr - 1 full rounds */ + r = Nr >> 1; + for (;;) { + + t0 = + Td0(byte(s0, 3)) ^ + Td1(byte(s3, 2)) ^ + Td2(byte(s2, 1)) ^ + Td3(byte(s1, 0)) ^ + rk[4]; + t1 = + Td0(byte(s1, 3)) ^ + Td1(byte(s0, 2)) ^ + Td2(byte(s3, 1)) ^ + Td3(byte(s2, 0)) ^ + rk[5]; + t2 = + Td0(byte(s2, 3)) ^ + Td1(byte(s1, 2)) ^ + Td2(byte(s0, 1)) ^ + Td3(byte(s3, 0)) ^ + rk[6]; + t3 = + Td0(byte(s3, 3)) ^ + Td1(byte(s2, 2)) ^ + Td2(byte(s1, 1)) ^ + Td3(byte(s0, 0)) ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Td0(byte(t0, 3)) ^ + Td1(byte(t3, 2)) ^ + Td2(byte(t2, 1)) ^ + Td3(byte(t1, 0)) ^ + rk[0]; + s1 = + Td0(byte(t1, 3)) ^ + Td1(byte(t0, 2)) ^ + Td2(byte(t3, 1)) ^ + Td3(byte(t2, 0)) ^ + rk[1]; + s2 = + Td0(byte(t2, 3)) ^ + Td1(byte(t1, 2)) ^ + Td2(byte(t0, 1)) ^ + Td3(byte(t3, 0)) ^ + rk[2]; + s3 = + Td0(byte(t3, 3)) ^ + Td1(byte(t2, 2)) ^ + Td2(byte(t1, 1)) ^ + Td3(byte(t0, 0)) ^ + rk[3]; + } +#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ + + /* Apply last round and map cipher state to byte array block */ + s0 = + (Td4[byte(t0, 3)] & 0xff000000) ^ + (Td4[byte(t3, 2)] & 0x00ff0000) ^ + (Td4[byte(t2, 1)] & 0x0000ff00) ^ + (Td4[byte(t1, 0)] & 0x000000ff) ^ + rk[0]; + STORE32H(s0, pt); + s1 = + (Td4[byte(t1, 3)] & 0xff000000) ^ + (Td4[byte(t0, 2)] & 0x00ff0000) ^ + (Td4[byte(t3, 1)] & 0x0000ff00) ^ + (Td4[byte(t2, 0)] & 0x000000ff) ^ + rk[1]; + STORE32H(s1, pt+4); + s2 = + (Td4[byte(t2, 3)] & 0xff000000) ^ + (Td4[byte(t1, 2)] & 0x00ff0000) ^ + (Td4[byte(t0, 1)] & 0x0000ff00) ^ + (Td4[byte(t3, 0)] & 0x000000ff) ^ + rk[2]; + STORE32H(s2, pt+8); + s3 = + (Td4[byte(t3, 3)] & 0xff000000) ^ + (Td4[byte(t2, 2)] & 0x00ff0000) ^ + (Td4[byte(t1, 1)] & 0x0000ff00) ^ + (Td4[byte(t0, 0)] & 0x000000ff) ^ + rk[3]; + STORE32H(s3, pt+12); +} + +/******************************************************************************/ + +static uint32 setup_mix(uint32 temp) +{ + return (Te4_3[byte(temp, 2)]) ^ + (Te4_2[byte(temp, 1)]) ^ + (Te4_1[byte(temp, 0)]) ^ + (Te4_0[byte(temp, 3)]); +} + +#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE +static uint32 setup_mix2(uint32 temp) +{ + return Td0(255 & Te4[byte(temp, 3)]) ^ + Td1(255 & Te4[byte(temp, 2)]) ^ + Td2(255 & Te4[byte(temp, 1)]) ^ + Td3(255 & Te4[byte(temp, 0)]); +} +#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ + +/******************************************************************************/ +/** + Convert a forward (encrypt) key schedule into an inverse (decrypt) + key schedule. + @note Inline since it is only called from one internal function, and + it can save some stack memory. Compiler optimization would probably + inline this on its own anyway. +*/ +__inline static void invertKeySchedule(psAesKey_t *key) +{ + int i; + uint32 temp, *rk, *rrk; + uint32 ek[64]; + + /* Copy the current (encrypt key) to a temp buffer */ + memcpy(ek, key->skey, sizeof(ek)); + rk = key->skey; + switch (key->rounds) { + case 10: + rrk = ek + 40; + break; + case 12: + rrk = ek + 48; + break; + case 14: + rrk = ek + 56; + break; + default: + return; + } +/* + apply the inverse MixColumn transform to all round keys but + the first and the last: + */ + /* copy first */ + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk = *rrk; + rk -= 3; rrk -= 3; + + for (i = 1; i < key->rounds; i++) { + rrk -= 4; + rk += 4; +#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE + temp = rrk[0]; + rk[0] = setup_mix2(temp); + temp = rrk[1]; + rk[1] = setup_mix2(temp); + temp = rrk[2]; + rk[2] = setup_mix2(temp); + temp = rrk[3]; + rk[3] = setup_mix2(temp); +#else /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ + temp = rrk[0]; + rk[0] = + Tks0[byte(temp, 3)] ^ + Tks1[byte(temp, 2)] ^ + Tks2[byte(temp, 1)] ^ + Tks3[byte(temp, 0)]; + temp = rrk[1]; + rk[1] = + Tks0[byte(temp, 3)] ^ + Tks1[byte(temp, 2)] ^ + Tks2[byte(temp, 1)] ^ + Tks3[byte(temp, 0)]; + temp = rrk[2]; + rk[2] = + Tks0[byte(temp, 3)] ^ + Tks1[byte(temp, 2)] ^ + Tks2[byte(temp, 1)] ^ + Tks3[byte(temp, 0)]; + temp = rrk[3]; + rk[3] = + Tks0[byte(temp, 3)] ^ + Tks1[byte(temp, 2)] ^ + Tks2[byte(temp, 1)] ^ + Tks3[byte(temp, 0)]; +#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ + } + + /* copy last */ + rrk -= 4; + rk += 4; + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk = *rrk; + + memset_s(ek, sizeof(ek), 0x0, sizeof(ek)); +} + +#endif /* USE_MATRIX_AES_BLOCK */ + +/******************************************************************************/ + diff --git a/crypto/symmetric/aesCBC.c b/crypto/symmetric/aesCBC.c new file mode 100644 index 0000000..547ad10 --- /dev/null +++ b/crypto/symmetric/aesCBC.c @@ -0,0 +1,156 @@ +/** + * @file aesCBC.c + * @version $Format:%h%d$ + * + * AES CBC block cipher implementation. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_MATRIX_AES_CBC + +/******************************************************************************/ + +void psAesClearCBC(psAesCbc_t *ctx) +{ + /* Only need to clear block if it's implemented externally, Matrix block + is part of CipherContext and will be cleared below */ +#ifndef USE_MATRIX_AES_BLOCK + psAesClearBlockKey(&ctx->key); +#endif + memset_s(ctx, sizeof(psAesCbc_t), 0x0, sizeof(psAesCbc_t)); +} + +/******************************************************************************/ +/* + Software implementation of AES CBC APIs + */ +int32_t psAesInitCBC(psAesCbc_t *ctx, + const unsigned char IV[AES_IVLEN], + const unsigned char key[AES_MAXKEYLEN], uint8_t keylen, + uint32_t flags) +{ + int32_t x, err; + +#ifdef CRYPTO_ASSERT + if (IV == NULL || key == NULL || ctx == NULL || + !(flags & (PS_AES_ENCRYPT | PS_AES_DECRYPT))) { + + psTraceCrypto("psAesInitCBC arg fail\n"); + return PS_ARG_FAIL; + } +#endif + if ((err = psAesInitBlockKey(&ctx->key, key, keylen, flags)) != PS_SUCCESS) { + return err; + } + for (x = 0; x < AES_BLOCKLEN; x++) { + ctx->IV[x] = IV[x]; + } + return PS_SUCCESS; +} + +/******************************************************************************/ + +void psAesEncryptCBC(psAesCbc_t *ctx, + const unsigned char *pt, unsigned char *ct, + uint32_t len) +{ + uint32_t i, j; + unsigned char tmp[AES_BLOCKLEN]; + +#ifdef CRYPTO_ASSERT + if (pt == NULL || ct == NULL || ctx == NULL || (len & 0x7) != 0 || + ctx->key.type != PS_AES_ENCRYPT) { + + psTraceCrypto("Bad parameters to psAesEncryptCBC\n"); + return; + } +#endif + for (i = 0; i < len; i += AES_BLOCKLEN) { + /* xor IV against plaintext */ + for (j = 0; j < AES_BLOCKLEN; j++) { + tmp[j] = pt[j] ^ ctx->IV[j]; + } + + psAesEncryptBlock(&ctx->key, tmp, ct); + + /* store IV [ciphertext] for a future block */ + for (j = 0; j < AES_BLOCKLEN; j++) { + ctx->IV[j] = ct[j]; + } + ct += AES_BLOCKLEN; + pt += AES_BLOCKLEN; + } + + memset_s(tmp, sizeof(tmp), 0x0, sizeof(tmp)); +} + +/******************************************************************************/ + +void psAesDecryptCBC(psAesCbc_t *ctx, + const unsigned char *ct, unsigned char *pt, + uint32_t len) +{ + uint32_t i, j; + unsigned char tmp[AES_BLOCKLEN], tmp2[AES_BLOCKLEN]; + +#ifdef CRYPTO_ASSERT + if (pt == NULL || ct == NULL || ctx == NULL || (len & 0x7) != 0 || + ctx->key.type != PS_AES_DECRYPT) { + + psTraceCrypto("Bad parameters to psAesDecryptCBC\n"); + return; + } +#endif + + for (i = 0; i < len; i += AES_BLOCKLEN) { + psAesDecryptBlock(&ctx->key, ct, tmp); + /* xor IV against the plaintext of the previous step */ + for (j = 0; j < AES_BLOCKLEN; j++) { + /* copy CT in case ct == pt */ + tmp2[j] = ct[j]; + /* actually decrypt the byte */ + pt[j] = tmp[j] ^ ctx->IV[j]; + } + /* replace IV with this current ciphertext */ + for (j = 0; j < AES_BLOCKLEN; j++) { + ctx->IV[j] = tmp2[j]; + } + ct += AES_BLOCKLEN; + pt += AES_BLOCKLEN; + } + memset_s(tmp, sizeof(tmp), 0x0, sizeof(tmp)); + memset_s(tmp2, sizeof(tmp2), 0x0, sizeof(tmp2)); +} + +#endif /* USE_MATRIX_AES_CBC */ + +/******************************************************************************/ + diff --git a/crypto/symmetric/aesGCM.c b/crypto/symmetric/aesGCM.c new file mode 100644 index 0000000..ea79e34 --- /dev/null +++ b/crypto/symmetric/aesGCM.c @@ -0,0 +1,499 @@ +/** + * @file aesGCM.c + * @version $Format:%h%d$ + * + * AES GCM block cipher implementation. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_MATRIX_AES_GCM + +/******************************************************************************/ + +static void psGhashPad(psAesGcm_t *ctx); +static void psGhashInit(psAesGcm_t *ctx, + const unsigned char *GHASHKey_p); +static void psGhashUpdate(psAesGcm_t *ctx, const unsigned char *data, + uint32 dataLen, int dataType); +static void psGhashFinal(psAesGcm_t *ctx); + +#define GHASH_DATATYPE_AAD 0 +#define GHASH_DATATYPE_CIPHERTEXT 2 + +#define FL_GET_BE32(be) \ + (((uint32)((be).be_bytes[0]) << 24) | \ + ((uint32)((be).be_bytes[1]) << 16) | \ + ((uint32)((be).be_bytes[2]) << 8) | \ + (uint32)((be).be_bytes[3])) + +typedef struct { unsigned char be_bytes[4]; } FL_UInt32_BE_UNA_t; + +#define FLFBLOCKSIZE 128 /* Maximum block size of a hash function. */ + +/******************************************************************************/ +/* + Initialize an AES GCM context +*/ +int32_t psAesInitGCM(psAesGcm_t *ctx, + const unsigned char key[AES_MAXKEYLEN], uint8_t keylen) +{ + int32_t rc; + unsigned char blockIn[16] = { 0 }; + + memset(ctx, 0x0, sizeof(psAesGcm_t)); + /* GCM always uses AES in ENCRYPT block mode, even for decrypt */ + rc = psAesInitBlockKey(&ctx->key, key, keylen, PS_AES_ENCRYPT); + if (rc < 0) { + return rc; + } + psAesEncryptBlock(&ctx->key, blockIn, ctx->gInit); + return PS_SUCCESS; +} + +/******************************************************************************/ + +void psAesClearGCM(psAesGcm_t *ctx) +{ + /* Only need to clear block if it's implemented externally, Matrix block + is part of AesGcm_t and will be cleared below */ +#ifndef USE_MATRIX_AES_BLOCK + psAesClearBlockKey(&ctx->key); +#endif + memset_s(ctx, sizeof(psAesGcm_t), 0x0, sizeof(psAesGcm_t)); +} + +/******************************************************************************/ +/* + Specifiy the IV and additional data to an AES GCM context that was + created with psAesInitGCM +*/ +void psAesReadyGCM(psAesGcm_t *ctx, + const unsigned char IV[AES_IVLEN], + const unsigned char *aad, uint16_t aadLen) +{ + psGhashInit(ctx, ctx->gInit); + /* Save aside first counter for final use */ + memset(ctx->IV, 0, 16); + memcpy(ctx->IV, IV, 12); + ctx->IV[15] = 1; + + /* Set up crypto counter starting at nonce || 2 */ + memset(ctx->EncCtr, 0, 16); + memcpy(ctx->EncCtr, IV, 12); + ctx->EncCtr[15] = 2; + + psGhashUpdate(ctx, aad, aadLen, GHASH_DATATYPE_AAD); + psGhashPad(ctx); +} + +/******************************************************************************/ +/* + Internal gcm crypt function that uses direction to determine what gets + fed to the GHASH update +*/ +static void psAesEncryptGCMx(psAesGcm_t *ctx, + const unsigned char *pt, unsigned char *ct, + uint32_t len, int8_t direction) +{ + unsigned char *ctStart; + uint32_t outLen; + int x; /* Must be signed due to positive check below */ + + outLen = len; + ctStart = ct; + if (direction == 0) { + psGhashUpdate(ctx, pt, len, GHASH_DATATYPE_CIPHERTEXT); + } + while (len) { + if (ctx->OutputBufferCount == 0) { + ctx->OutputBufferCount = 16; + psAesEncryptBlock(&ctx->key, ctx->EncCtr, ctx->CtrBlock); + + /* CTR incr */ + for (x = (AES_BLOCKLEN - 1); x >= 0; x--) { + ctx->EncCtr[x] = (ctx->EncCtr[x] + + (unsigned char)1) & (unsigned char)255; + if (ctx->EncCtr[x] != (unsigned char)0) { + break; + } + } + } + + *(ct++) = *(pt++) ^ ctx->CtrBlock[16 - ctx->OutputBufferCount]; + len--; + ctx->OutputBufferCount--; + } + if (direction == 1) { + psGhashUpdate(ctx, ctStart, outLen, GHASH_DATATYPE_CIPHERTEXT); + } +} + +/******************************************************************************/ +/* + Public GCM encrypt function. This will just perform the encryption. The + tag should be fetched with psAesGetGCMTag +*/ +void psAesEncryptGCM(psAesGcm_t *ctx, + const unsigned char *pt, unsigned char *ct, + uint32_t len) +{ + psAesEncryptGCMx(ctx, pt, ct, len, 1); +} + +/******************************************************************************/ +/* + After encryption this function is used to retreive the authentication tag +*/ +void psAesGetGCMTag(psAesGcm_t *ctx, + uint8_t tagBytes, unsigned char tag[AES_BLOCKLEN]) +{ + unsigned char *pt, *ct; + + psGhashFinal(ctx); + + /* Encrypt authentication tag */ + ctx->OutputBufferCount = 0; + + ct = tag; + pt = (unsigned char*)ctx->TagTemp; + while (tagBytes) { + if (ctx->OutputBufferCount == 0) { + ctx->OutputBufferCount = 16; + /* Initial IV has been set aside in IV */ + psAesEncryptBlock(&ctx->key, ctx->IV, ctx->CtrBlock); + /* No need to increment since we know tag bytes will never be + larger than 16 */ + } + *(ct++) = *(pt++) ^ ctx->CtrBlock[16 - ctx->OutputBufferCount]; + tagBytes--; + ctx->OutputBufferCount--; + + } +} + +/* Just does the GCM decrypt portion. Doesn't expect the tag to be at the end + of the ct. User will invoke psAesGetGCMTag seperately */ +void psAesDecryptGCMtagless(psAesGcm_t *ctx, + const unsigned char *ct, unsigned char *pt, + uint32_t len) +{ + psAesEncryptGCMx(ctx, ct, pt, len, 0); +} + + +/******************************************************************************/ +/* + Decrypt will invoke GetGMCTag so the comparison can be done. ctLen + will include the appended tag length and ptLen is just the encrypted + portion +*/ +int32_t psAesDecryptGCM(psAesGcm_t *ctx, + const unsigned char *ct, uint32_t ctLen, + unsigned char *pt, uint32_t ptLen) +{ + uint16_t tagLen; + unsigned char tag[AES_BLOCKLEN]; + + if (ctLen > ptLen) { + tagLen = ctLen - ptLen; + } else { + return PS_ARG_FAIL; + } + + psAesEncryptGCMx(ctx, ct, pt, ptLen, 0); + psAesGetGCMTag(ctx, tagLen, tag); + + if (memcmpct(tag, ct + ptLen, tagLen) != 0) { + psTraceCrypto("GCM didn't authenticate\n"); + return PS_AUTH_FAIL; + } + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Ghash code taken from FL +*/ +static void FLA_GHASH_128_mul_base(uint32 *op, uint32 moduli) +{ + int carry_bit = op[3] & 0x1; + + op[3] = op[3] >> 1 | (op[2] & 0x1) << 31; + op[2] = op[2] >> 1 | (op[1] & 0x1) << 31; + op[1] = op[1] >> 1 | (op[0] & 0x1) << 31; + op[0] = op[0] >> 1; + + if (carry_bit) + op[0] ^= moduli; +} + +/* Multiplication of X by Y, storing the result to X. */ +static void FLA_GHASH_128_mul(uint32 *X, const uint32 *Y, uint32 moduli) +{ + uint32 t[4]; + int i; + + t[0] = X[0]; + t[1] = X[1]; + t[2] = X[2]; + t[3] = X[3]; + + X[0]= X[1] = X[2] = X[3] = 0; + + for (i = 0; i < 128; i++) + { + if (Y[i / 32] & (1 << (31 - i % 32))) + { + X[0] ^= t[0]; + X[1] ^= t[1]; + X[2] ^= t[2]; + X[3] ^= t[3]; + } + + FLA_GHASH_128_mul_base(t, moduli); + } +} + +static int FLFIncreaseCountBits(psAesGcm_t * ctx, unsigned int CounterId, + int32 NBits) +{ + int32 Lo, Hi; + int32 Temp; + + Lo = NBits; + Hi = 0; + + Temp = ctx->ProcessedBitCount[CounterId]; + ctx->ProcessedBitCount[CounterId] += Lo; + + if (Temp > (int32)ctx->ProcessedBitCount[CounterId]) + { + Hi += 1; + } + + if (Hi) + { + Temp = ctx->ProcessedBitCount[CounterId + 1]; + ctx->ProcessedBitCount[CounterId + 1] += Hi; + + /* Returns true if carry out of highest bits. */ + return (Temp > (int32)ctx->ProcessedBitCount[CounterId + 1]); + } + + /* No update of high order bits => No carry. */ + return 0; /* false */ +} + +static int increaseCountBytes(psAesGcm_t *ctx, int32 NBytes, + int CounterId) +{ + int carry; + + /* COVN: Test this code with > 2^31 bits. */ + + /* Process NBytes (assuming NBytes < 0x10000000) */ + carry = FLFIncreaseCountBits(ctx, CounterId, (NBytes & 0x0FFFFFFF) << 3); + + NBytes &= 0x0FFFFFFF; + + /* For unusually large values of NBytes, process the remaining bytes + to add 0x10000000 at time. This ensure the value of bytes, + once converted to bits, does not overflow 32-bit value. + + PORTN: It is assumed NBytes <= 2**61. This is true on 32-bit APIs as + FL_DataLen_t cannot represent such large value. */ + while(NBytes >= 0x10000000) + { + carry |= FLFIncreaseCountBits(ctx, CounterId, 0x10000000U * 8); + NBytes -= 0x10000000; + } + + return carry; +} + +static void FLAGcmProcessBlock(uint32 *H, FL_UInt32_BE_UNA_t *Buf_p, + uint32 *InOut) +{ + /* PORTN: Requires sizeof(FL_UInt32_BE_UNA_t) to be 4. + Some platforms may add padding to FL_UInt32_BE_UNA_t if + it is represented as a structure. */ + + InOut[0] ^= FL_GET_BE32(Buf_p[0]); + InOut[1] ^= FL_GET_BE32(Buf_p[1]); + InOut[2] ^= FL_GET_BE32(Buf_p[2]); + InOut[3] ^= FL_GET_BE32(Buf_p[3]); + + FLA_GHASH_128_mul(InOut, H, (1 << 31) + (1 << 30) + (1 << 29) + (1 << 24)); +} + +static void UpdateFunc(psAesGcm_t *ctx, const unsigned char *Buf_p, + int32 Size) +{ + while (Size >= 16) + { + FLAGcmProcessBlock((uint32*)ctx->Hash_SubKey, + (FL_UInt32_BE_UNA_t *) Buf_p, (uint32*)ctx->TagTemp); + Buf_p += 16; + Size -= 16; + } +} + +static void flf_blocker(psAesGcm_t *ctx, const unsigned char *Data_p, + uint32 DataCount) +{ + while (DataCount > 0) + { + if (ctx->InputBufferCount == FLFBLOCKSIZE) + { + UpdateFunc(ctx, + ctx->Input.Buffer, + ctx->InputBufferCount); + ctx->InputBufferCount = 0; + } + if (ctx->InputBufferCount < FLFBLOCKSIZE) + { + uint32 BytesProcess = min((uint32)DataCount, + FLFBLOCKSIZE - ctx->InputBufferCount); + + memcpy(ctx->Input.Buffer + + ctx->InputBufferCount, Data_p, BytesProcess); + DataCount -= BytesProcess; + ctx->InputBufferCount += BytesProcess; + Data_p += BytesProcess; + } + } + +} + +static void psGhashInit(psAesGcm_t *ctx, + const unsigned char *GHASHKey_p) +{ + uint32 *Key_p = (uint32*)ctx->Hash_SubKey; + + memset(&ctx->ProcessedBitCount, 0x0, + sizeof(ctx->ProcessedBitCount)); + ctx->InputBufferCount = 0; + Key_p[0] = FL_GET_BE32(*(FL_UInt32_BE_UNA_t *) GHASHKey_p); + Key_p[1] = FL_GET_BE32(*(FL_UInt32_BE_UNA_t *) (GHASHKey_p + 4)); + Key_p[2] = FL_GET_BE32(*(FL_UInt32_BE_UNA_t *) (GHASHKey_p + 8)); + Key_p[3] = FL_GET_BE32(*(FL_UInt32_BE_UNA_t *) (GHASHKey_p + 12)); + memset(ctx->TagTemp, 0x0, 16); +} + +static void psGhashUpdate(psAesGcm_t *ctx, const unsigned char *data, + uint32 dataLen, int dataType) +{ + increaseCountBytes(ctx, dataLen, dataType); + flf_blocker(ctx, data, dataLen); + +} + +static void psGhashPad(psAesGcm_t *ctx) +{ + while ((ctx->InputBufferCount & 15) != 0) + { + unsigned char z = 0; + flf_blocker(ctx, &z, 1); + } +} + +#ifndef ENDIAN_BIG +#ifdef ENDIAN_NEUTRAL +#warning ENDIAN_NEUTRAL untested for AES-GCM +#endif + +/* On little endian (and endian neutral untested), we need to reverse bytes + to big endian mode for GhashFinal */ +static uint32 FLM_ReverseBytes32(uint32 Value) +{ + Value = (((Value & 0xff00ff00UL) >> 8) | ((Value & 0x00ff00ffUL) << 8)); + return ((Value >> 16) | (Value << 16)); +} +static void FLF_ConvertToBE64(uint32 *Swap_p, uint32 num) +{ + uint32 tmp; + while(num) { + num--; + tmp = FLM_ReverseBytes32(Swap_p[num * 2]); + Swap_p[num * 2] = FLM_ReverseBytes32(Swap_p[num * 2 + 1]); + Swap_p[num * 2 + 1] = tmp; + } +} +static void FLF_ConvertToBE32(uint32 *Swap_p, uint32 num) +{ + /* PORTN: Byte order specific function. */ + while(num) + { + num--; + Swap_p[num] = FLM_ReverseBytes32(Swap_p[num]); + } +} + +#else + +/* On big endian, the 4 bytes in a uint32 are already in the right order! */ +static void FLF_ConvertToBE64(uint32 *Swap_p, uint32 num) +{ + uint32 tmp; + while(num) { + num--; + tmp = Swap_p[num * 2]; + Swap_p[num * 2] = Swap_p[num * 2 + 1]; + Swap_p[num * 2 + 1] = tmp; + } +} +#define FLF_ConvertToBE32(A, B) + +#endif /* !ENDIAN_BIG */ + +static void psGhashFinal(psAesGcm_t *ctx) +{ + psGhashPad(ctx); + + /* TODO COVN: Check GHASH with data > 2^32 bits for word swap logic. */ + /* Swap 32 bit words 0 & 1 and 2 & 3, on ENDIAN_LITTLE, swap bytes too */ + FLF_ConvertToBE64(&ctx->ProcessedBitCount[0], 2); + + UpdateFunc(ctx, ctx->Input.Buffer, + ctx->InputBufferCount); + ctx->InputBufferCount = 0; + + UpdateFunc(ctx, + (const unsigned char *) &ctx->ProcessedBitCount[0], 16); + + /* Convert temporary Tag Value to final Tag Value. NOOP on ENDIAN_BIG */ + FLF_ConvertToBE32(ctx->TagTemp, 4); +} + +#endif /* USE_MATRIX_AES_GCM */ + +/******************************************************************************/ + diff --git a/crypto/symmetric/aes_aesni.c b/crypto/symmetric/aes_aesni.c new file mode 100644 index 0000000..ee78a63 --- /dev/null +++ b/crypto/symmetric/aes_aesni.c @@ -0,0 +1,972 @@ +/** + * @file aes_aesni.c + * @version $Format:%h%d$ + * + * Support for AES-NI Hardware Crypto Instructions (x86-64 platforms). + */ +/* + * Copyright (c) 2014-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +/******************************************************************************/ + +#if defined(USE_AESNI_AES_BLOCK) || \ + defined(USE_AESNI_AES_CBC) || \ + defined(USE_AESNI_AES_GCM) + +#ifndef __AES__ +#error "'-maes' must be present in GCC compiler flags for AES-NI support" +#endif + +#include +#ifndef __APPLE__ +#include +#endif + +#define AESNI_192 /* AES-192 is not used in TLS ciphers, so make it optional */ + +#ifdef AESNI_192 +#include +#endif + +/* Encrypts aligned blocks */ +static void encryptBlock(__m128i *dst, __m128i *src, __m128i *round_keys, + uint32_t rounds) +{ + uint32_t i; + __m128i key_schedule[15]; + __m128i temp; + + for (i = 0; i <= rounds; i++) { +#ifdef PSTM_64BIT + key_schedule[i] = round_keys[i]; +#else + key_schedule[i] = _mm_loadu_si128(&round_keys[i]); +#endif + } + /* First round */ + temp = _mm_xor_si128(*src, key_schedule[0]); + /* Middle rounds */ + for (i = 1; i < rounds; i++) { + temp = _mm_aesenc_si128(temp, key_schedule[i]); + } + /* Last round */ + *dst = _mm_aesenclast_si128(temp, key_schedule[rounds]); +} + +/* Decrypts aligned blocks */ +static void decryptBlock(__m128i *dst, __m128i *src, __m128i *round_keys, + uint32_t rounds) +{ + unsigned int i; + __m128i key_schedule[15]; + __m128i temp; + + for (i = 0; i <= rounds; i++) { +#ifdef PSTM_64BIT + key_schedule[i] = round_keys[i]; +#else + key_schedule[i] = _mm_loadu_si128(&round_keys[i]); +#endif + } + /* First round */ + temp = _mm_xor_si128(*src, key_schedule[rounds]); + /* Middle rounds */ + for (i = 1; i < rounds; i++) { + temp = _mm_aesdec_si128(temp, key_schedule[rounds - i]); + } + /* Last round */ + *dst = _mm_aesdeclast_si128(temp, key_schedule[0]); +} +#endif /* BLOCK || CBC || GCM */ + +/******************************************************************************/ + +#ifdef USE_AESNI_AES_BLOCK + +static __m128i psAesKeygenAssist(__m128i temp, int i) +{ + /* Note that the second argument for _mm_aeskeygenassistant() + is required to be a compile-time constant. */ + switch (i) { + case 0: return _mm_aeskeygenassist_si128(temp, 0x01); + case 1: return _mm_aeskeygenassist_si128(temp, 0x02); + case 2: return _mm_aeskeygenassist_si128(temp, 0x04); + case 3: return _mm_aeskeygenassist_si128(temp, 0x08); + case 4: return _mm_aeskeygenassist_si128(temp, 0x10); + case 5: return _mm_aeskeygenassist_si128(temp, 0x20); + case 6: return _mm_aeskeygenassist_si128(temp, 0x40); + case 7: return _mm_aeskeygenassist_si128(temp, 0x80); + case 8: return _mm_aeskeygenassist_si128(temp, 0x1b); + case 9: return _mm_aeskeygenassist_si128(temp, 0x36); + case 10: return temp; + default: break; + } + return temp; +} + +/* psAesInitKey has set up the key for encryption, change it */ +__inline static void invertKeySchedule(psAesKey_t *key) +{ + __m128i temp; + int i; + + /* No change to key[0] */ + for (i = 1; i < key->rounds; i++) { +#ifdef PSTM_64BIT + temp = key->skey[i]; +#else + temp = _mm_loadu_si128(&key->skey[i]); +#endif + temp = _mm_aesimc_si128(temp); + +#ifdef PSTM_64BIT + key->skey[i] = temp; +#else + _mm_storeu_si128(&key->skey[i], temp); +#endif + } + /* No change to key[i] */ +} + +int32_t psAesInitBlockKey(psAesKey_t *key, + const unsigned char ckey[AES_MAXKEYLEN], uint8_t keylen, + uint32_t flags) +{ + __m128i temp1, temp2, temp3, temp4; + int i, offset; +#ifdef AESNI_192 + int kstemp[48]; +#endif + +#ifdef CRYPTO_ASSERT + if (key == NULL || ckey == NULL || !(flags & (PS_AES_ENCRYPT | PS_AES_DECRYPT))) { + psTraceCrypto("Bad args to psAesInitBlockKey\n"); + return PS_ARG_FAIL; + } + if (keylen != 16 && keylen != 24 && keylen != 32) { + psTraceCrypto("Invalid AES key length\n"); + return CRYPT_INVALID_KEYSIZE; + } +#endif + switch (keylen) { + case 16: + key->rounds = 10; + temp1 = _mm_loadu_si128((__m128i *)ckey); +#ifdef PSTM_64BIT + key->skey[0] = temp1; +#else + _mm_storeu_si128(&key->skey[0], temp1); +#endif + for (i = 0; i < 10; i++) { + temp2 = psAesKeygenAssist(temp1, i); + temp2 = _mm_shuffle_epi32(temp2, 0xff); + temp3 = _mm_slli_si128(temp1, 0x4); + temp1 = _mm_xor_si128(temp1, temp3); + temp3 = _mm_slli_si128(temp3, 0x4); + temp1 = _mm_xor_si128(temp1, temp3); + temp3 = _mm_slli_si128(temp3, 0x4); + temp1 = _mm_xor_si128(temp1, temp3); + temp1 = _mm_xor_si128(temp1, temp2); +#ifdef PSTM_64BIT + key->skey[i + 1] = temp1; +#else + _mm_storeu_si128(&key->skey[i + 1], temp1); +#endif + } + break; + +#ifdef AESNI_192 + case 24: + key->rounds = 12; + temp1 = _mm_loadu_si128((__m128i *)ckey); + temp3 = _mm_loadu_si128((__m128i *)(ckey + 16)); + key->skey[0] = temp1; + offset = 0; + for (i = 0; i < 8; i++) { + temp2 = psAesKeygenAssist(temp3, i); + temp2 = _mm_shuffle_epi32(temp2, 0x55); + temp4 = temp1; + temp4 = _mm_slli_si128(temp4, 0x4); + temp1 = _mm_xor_si128(temp1, temp4); + temp4 = _mm_slli_si128(temp4, 0x4); + temp1 = _mm_xor_si128(temp1, temp4); + temp4 = _mm_slli_si128(temp4, 0x4); + temp1 = _mm_xor_si128(temp1, temp4); + temp1 = _mm_xor_si128(temp1, temp2); + temp2 = _mm_shuffle_epi32(temp1, 0xff); + temp4 = temp3; + temp4 = _mm_slli_si128(temp4, 0x4); + temp3 = _mm_xor_si128(temp3, temp4); + temp3 = _mm_xor_si128(temp3, temp2); + + kstemp[offset++] = _mm_extract_epi32(temp1, 0); + kstemp[offset++] = _mm_extract_epi32(temp1, 1); + kstemp[offset++] = _mm_extract_epi32(temp1, 2); + kstemp[offset++] = _mm_extract_epi32(temp1, 3); + kstemp[offset++] = _mm_extract_epi32(temp3, 0); + kstemp[offset++] = _mm_extract_epi32(temp3, 1); + } + /* This loadu and extract could probably be done more optimally */ + temp3 = _mm_loadu_si128((__m128i *)(ckey + 16)); + key->skey[1] = _mm_set_epi32(kstemp[1], kstemp[0], + _mm_extract_epi32(temp3, 1), + _mm_extract_epi32(temp3, 0)); + for (i = 2; i < offset - 4; i += 4) { + key->skey[(i/4) + 2] = _mm_set_epi32(kstemp[i+3], + kstemp[i+2], kstemp[i+1], kstemp[i]); + } + break; +#endif + + case 32: + key->rounds = 14; + temp1 = _mm_loadu_si128((__m128i *)ckey); +#ifdef PSTM_64BIT + key->skey[0] = temp1; +#else + _mm_storeu_si128(&key->skey[0], temp1); +#endif + temp3 = _mm_loadu_si128((__m128i *)(ckey + 16)); +#ifdef PSTM_64BIT + key->skey[1] = temp3; +#else + _mm_storeu_si128(&key->skey[1], temp3); +#endif + offset = 2; + for (i = 0; i < 7; i++) { + temp2 = psAesKeygenAssist(temp3, i); + temp2 = _mm_shuffle_epi32(temp2, 0xff); + temp4 = temp1; + temp4 = _mm_slli_si128(temp4, 0x4); + temp1 = _mm_xor_si128(temp1, temp4); + temp4 = _mm_slli_si128(temp4, 0x4); + temp1 = _mm_xor_si128(temp1, temp4); + temp4 = _mm_slli_si128(temp4, 0x4); + temp1 = _mm_xor_si128(temp1, temp4); + temp1 = _mm_xor_si128(temp1, temp2); +#ifdef PSTM_64BIT + key->skey[offset] = temp1; +#else + _mm_storeu_si128(&key->skey[offset], temp1); +#endif + offset++; + if (offset == 15) { + break; + } + temp4 = _mm_aeskeygenassist_si128(temp1, 0x0); + temp2 = _mm_shuffle_epi32(temp4, 0xaa); + temp4 = temp3; + temp4 = _mm_slli_si128(temp4, 0x4); + temp3 = _mm_xor_si128(temp3, temp4); + temp4 = _mm_slli_si128(temp4, 0x4); + temp3 = _mm_xor_si128(temp3, temp4); + temp4 = _mm_slli_si128(temp4, 0x4); + temp3 = _mm_xor_si128(temp3, temp4); + temp3 = _mm_xor_si128(temp3, temp2); +#ifdef PSTM_64BIT + key->skey[offset] = temp3; +#else + _mm_storeu_si128(&key->skey[offset], temp3); +#endif + offset++; + } + break; + + default: + psTraceCrypto("Invalid AES key length\n"); + return CRYPT_INVALID_KEYSIZE; + } + + switch(flags) { + + case PS_AES_ENCRYPT: + key->type = PS_AES_ENCRYPT; + break; + + case PS_AES_DECRYPT: + key->type = PS_AES_DECRYPT; + /* Replace the key schedule with the inverse key schedule */ + invertKeySchedule(key); + break; + + default: + psTraceCrypto("Invalid AES flags\n"); + return PS_ARG_FAIL; + } + return PS_SUCCESS; +} + +void psAesClearBlockKey(psAesKey_t *key) +{ + memset_s(key, sizeof(psAesKey_t), 0x0, sizeof(psAesKey_t)); +} + +/* Encrypts blocks of unknown alignment */ +void psAesEncryptBlock(psAesKey_t *key, const unsigned char *pt, + unsigned char *ct) +{ + __m128i src, dst; + +#ifdef CRYPTO_ASSERT + psAssert(key->type == PS_AES_ENCRYPT); +#endif + src = _mm_loadu_si128((__m128i *)(pt)); + encryptBlock(&dst, &src, key->skey, key->rounds); + _mm_storeu_si128((void *)(ct), dst); +} + +/* Decrypts blocks of unknown alignment */ +void psAesDecryptBlock(psAesKey_t *key, const unsigned char *ct, + unsigned char *pt) +{ + __m128i src, dst; + +#ifdef CRYPTO_ASSERT + psAssert(key->type == PS_AES_DECRYPT); +#endif + src = _mm_loadu_si128((__m128i *)(ct)); + decryptBlock(&dst, &src, key->skey, key->rounds); + _mm_storeu_si128((void *)(pt), dst); +} + +#endif /* USE_AESNI_AES_BLOCK */ + +/******************************************************************************/ + +#ifdef USE_AESNI_AES_CBC + +void psAesClearCBC(psAesCbc_t *ctx) +{ +#ifndef USE_AESNI_AES_BLOCK + psAesClearBlockKey(&ctx->key); +#endif + memset_s(ctx, sizeof(psAesCbc_t), 0x0, sizeof(psAesCbc_t)); +} + +int32_t psAesInitCBC(psAesCbc_t *ctx, + const unsigned char IV[AES_IVLEN], + const unsigned char key[AES_MAXKEYLEN], uint8_t keylen, + uint32_t flags) +{ + int32 err; + uint32 idx = 1, a, b, c, d; + +#ifdef CRYPTO_ASSERT + if (IV == NULL || key == NULL || ctx == NULL || + !(flags & (PS_AES_ENCRYPT | PS_AES_DECRYPT))) { + psTraceCrypto("psAesInit arg fail\n"); + return PS_ARG_FAIL; + } +#endif + + /* Get the runtime CPU capabilities */ +#ifndef __APPLE__ + __cpuid(idx, a, b, c, d); +#else + asm volatile ( + "pushq %%rbx \n\t" + "cpuid \n\t" + "movl %%ebx ,%[ebx] \n\t" + "popq %%rbx \n\t" + : "=a"(a), [ebx] "=r"(b), "=c"(c), "=d"(d) + : "a"(idx)); +#endif + /* Check for AESNI: CPUID.01H:ECX.AESNI[bit 25] == 1 */ + if (!(c & 0x2000000)) { + psTraceCrypto("psAesInit aes-ni unsupported\n"); + return PS_PLATFORM_FAIL; + } + + if ((err = psAesInitBlockKey(&ctx->key, key, keylen, flags)) != PS_SUCCESS) { + return err; + } + for (a = 0; a < AES_BLOCKLEN; a++) { + ctx->IV[a] = IV[a]; + } + return PS_SUCCESS; +} + +/* Encrypt in CBC mode */ +void psAesEncryptCBC(psAesCbc_t *ctx, + const unsigned char *pt, unsigned char *ct, + uint32_t len) +{ + unsigned int b; + __m128i src_m128i, temp_m128i; + +#ifdef CRYPTO_ASSERT + if (ct == NULL || pt == NULL || ctx == NULL || (len & 0x7) != 0 || + ctx->key.type != PS_AES_ENCRYPT) { + psTraceCrypto("Bad parameters to AesCBC\n"); + return; + } +#endif + temp_m128i = _mm_loadu_si128((__m128i *)(ctx->IV)); + for (b = 0; b < len; b += AES_BLOCKLEN) { + src_m128i = _mm_loadu_si128((__m128i *)(pt + b)); + src_m128i = _mm_xor_si128(src_m128i, temp_m128i); + encryptBlock(&temp_m128i, &src_m128i, + ctx->key.skey, ctx->key.rounds); + _mm_storeu_si128((void *)(ct + b), temp_m128i); + } + _mm_storeu_si128((void *)(ctx->IV), temp_m128i); +} + +/* Decrypt in CBC mode */ +void psAesDecryptCBC(psAesCbc_t *ctx, + const unsigned char *ct, unsigned char *pt, + uint32_t len) +{ + unsigned int b; + __m128i temp_m128i, temp2_m128i, temp3_m128i; + __m128i src_m128i = { 0 }; + +#ifdef CRYPTO_ASSERT + if (ct == NULL || pt == NULL || ctx == NULL || (len & 0x7) != 0 || + ctx->key.type != PS_AES_DECRYPT) { + psTraceCrypto("Bad parameters to AesCBC\n"); + return; + } +#endif + temp3_m128i = temp_m128i = _mm_loadu_si128((__m128i *)(ctx->IV)); + for (b = 0; b < len; b += AES_BLOCKLEN) { + src_m128i = _mm_loadu_si128((__m128i *)(ct + b)); + decryptBlock(&temp2_m128i, &src_m128i, + ctx->key.skey, ctx->key.rounds); + temp_m128i = _mm_xor_si128(temp2_m128i, temp3_m128i); + temp3_m128i = src_m128i; + _mm_storeu_si128((void *)(pt + b), temp_m128i); + } + _mm_storeu_si128((void *)(ctx->IV), src_m128i); +} + +#endif /* USE_AESNI_AES_CBC */ + +/******************************************************************************/ + +#ifdef USE_AESNI_AES_GCM + +#include + +static __m128i flip_m128i(__m128i input_m128i); +static void galois_mul(__m128i a, __m128i b, __m128i *res); +static __m128i galois_hash(__m128i h_m128i, __m128i y_m128i, + const unsigned char *buffer, size_t len); +static void galois_counter(psAesGcm_t *ctx, unsigned char *dst, + const unsigned char *src, size_t len); +static void gcm_update(psAesGcm_t *ctx, const unsigned char *buffer, + size_t len); +static void gcm_transform(psAesGcm_t *ctx, unsigned char *dest, + const unsigned char *src, size_t len, + unsigned char *iv, uint32_t flags); +static void gcm_final(psAesGcm_t *ctx, unsigned char *digest); + +void psAesClearGCM(psAesGcm_t *ctx) +{ +#ifndef USE_AESNI_AES_BLOCK + psAesClearBlockKey(&ctx->key); +#endif + memset_s(ctx, sizeof(psAesGcm_t), 0x0, sizeof(psAesGcm_t)); +} + +/* Init cipher with key */ +int32_t psAesInitGCM(psAesGcm_t *ctx, + const unsigned char key[AES_MAXKEYLEN], uint8_t keylen) +{ + __m128i zero_m128i, h_m128i; + uint32 idx =1, a, b, c, d; + int32 err; + +#ifdef CRYPTO_ASSERT + if (key == NULL || ctx == NULL) { + psTraceCrypto("psAesInitGCM arg fail\n"); + return PS_ARG_FAIL; + } +#endif + + /* Get the runtime CPU capabilities */ +#ifndef __APPLE__ + __cpuid(idx, a, b, c, d); +#else + asm volatile ( + "pushq %%rbx \n\t" + "cpuid \n\t" + "movl %%ebx ,%[ebx] \n\t" + "popq %%rbx \n\t" + : "=a"(a), [ebx] "=r"(b), "=c"(c), "=d"(d) + : "a"(idx) + ); +#endif +/* + Check for AESNI: CPUID.01H:ECX.AESNI[bit 25] == 1 + and PCLMULQDQ: CPUID.01H:ECX.PCLMULQDQ[bit 1] == 1 +*/ + if (!(c & 0x2000001)) { + psTraceCrypto("psAesInitGCM aes-ni and pclmulqdq unsupported\n"); + return PS_PLATFORM_FAIL; + } + if ((err = psAesInitBlockKey(&ctx->key, key, keylen, PS_AES_ENCRYPT)) + != PS_SUCCESS) { + return err; + } + + /* Pre-calculate H */ + zero_m128i = _mm_setzero_si128(); + encryptBlock(&h_m128i, &zero_m128i, ctx->key.skey, ctx->key.rounds); + ctx->a_len = 0; + ctx->c_len = 0; + ctx->cipher_started = 0; +#ifdef PSTM_64BIT + ctx->y_m128i = zero_m128i; +#else + _mm_storeu_si128(&ctx->y_m128i, zero_m128i); +#endif + /* Pre-invert byte order in H */ +#ifdef PSTM_64BIT + ctx->h_m128i = flip_m128i(h_m128i); +#else + _mm_storeu_si128(&ctx->h_m128i, flip_m128i(h_m128i)); +#endif + + return PS_SUCCESS; +} + +/* + Assign the IV and init hash state with additional authenticated data (AAD) + AEAD Ciphers and AAD: + http://tools.ietf.org/html/rfc5116 + TLS 1.2 contents of AAD: + http://tools.ietf.org/html/rfc5246#section-6.2.3.3 + GCM Spec: + http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf +*/ +void psAesReadyGCM(psAesGcm_t *ctx, + const unsigned char IV[AES_IVLEN], + const unsigned char *aad, uint16_t aadLen) +{ +#ifdef PSTM_64BIT + ctx->y_m128i = _mm_setzero_si128(); +#else + _mm_storeu_si128(&ctx->y_m128i, _mm_setzero_si128()); +#endif + ctx->c_len = 0; + ctx->cipher_started = 0; + + memcpy(ctx->IV, IV, 12); + + /* The AAD is TLS 1.2 specific */ + gcm_update(ctx, aad, aadLen); + /* The a_len holds the number of bytes of AAD */ + ctx->a_len = aadLen; +} + +/* Encrypt pt to ct and update the internal hash state */ +void psAesEncryptGCM(psAesGcm_t *ctx, + const unsigned char *pt, unsigned char *ct, + uint32_t len) +{ + gcm_transform(ctx, ct, pt, len, ctx->IV, PS_AES_ENCRYPT); +} + +/* Output TagBytes of the hash state (digest) to tag. */ +void psAesGetGCMTag(psAesGcm_t *ctx, + uint8_t tagBytes, unsigned char tag[AES_BLOCKLEN]) +{ + unsigned char digest[AES_BLOCKLEN]; + +#ifdef CRYPTO_ASSERT + psAssert(tag && tagBytes <= AES_BLOCKLEN); +#endif + gcm_final(ctx, digest); + memcpy(tag, digest, tagBytes); +} + +/* Decrypt ct to pt and verify hash in ct */ +int32_t psAesDecryptGCM(psAesGcm_t *ctx, + const unsigned char *ct, uint32_t ctLen, + unsigned char *pt, uint32_t ptLen) +{ + int tlen; + unsigned char digest[16]; + + tlen = ctLen - ptLen; + gcm_transform(ctx, pt, ct, ptLen, ctx->IV, PS_AES_DECRYPT); + gcm_final(ctx, digest); + if (memcmpct(digest, ct + ptLen, tlen) != 0) { + return PS_AUTH_FAIL; + } + return PS_SUCCESS; +} + +/* Just does the GCM decrypt portion. Doesn't expect the tag to be at the end + of the ct. User will invoke psAesGetGCMTag seperately */ +void psAesDecryptGCMtagless(psAesGcm_t *ctx, + const unsigned char *ct, unsigned char *pt, + uint32_t ptLen) +{ + gcm_transform(ctx, pt, ct, ptLen, ctx->IV, PS_AES_DECRYPT); +} + +/******************************************************************************/ +/* Flip byte endian in an _m128 */ +static __m128i flip_m128i(__m128i input_m128i) +{ + __m128i output_m128i; + + output_m128i = _mm_set_epi8(_mm_extract_epi8(input_m128i, 0), + _mm_extract_epi8(input_m128i, 1), + _mm_extract_epi8(input_m128i, 2), + _mm_extract_epi8(input_m128i, 3), + _mm_extract_epi8(input_m128i, 4), + _mm_extract_epi8(input_m128i, 5), + _mm_extract_epi8(input_m128i, 6), + _mm_extract_epi8(input_m128i, 7), + _mm_extract_epi8(input_m128i, 8), + _mm_extract_epi8(input_m128i, 9), + _mm_extract_epi8(input_m128i, 10), + _mm_extract_epi8(input_m128i, 11), + _mm_extract_epi8(input_m128i, 12), + _mm_extract_epi8(input_m128i, 13), + _mm_extract_epi8(input_m128i, 14), + _mm_extract_epi8(input_m128i, 15)); + + return output_m128i; +} + +/* NIST Special Publication 800-38D: 6.5 */ +static void galois_counter(psAesGcm_t *ctx, unsigned char *dst, + const unsigned char *src, size_t len) +{ + unsigned int i, j, n, partial_len; + __m128i key_schedule[15]; + __m128i temp_m128i, src_m128i, icb_m128i, ricb_m128i; + __m128i bswap_m128i = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15); + __m128i incrementer_m128i = _mm_set_epi32(0, 0, 0, 1); + + if (len == 0) { + return; + } +#ifdef PSTM_64BIT + icb_m128i = ctx->icb_m128i; +#else + icb_m128i = _mm_loadu_si128(&ctx->icb_m128i); +#endif + ricb_m128i = _mm_shuffle_epi8(icb_m128i, bswap_m128i); + + for (i = 0; i <= ctx->key.rounds; i++) { +#ifdef PSTM_64BIT + key_schedule[i] = ctx->key.skey[i]; +#else + key_schedule[i] = _mm_loadu_si128(&ctx->key.skey[i]); +#endif + } + + n = len / 16; + partial_len = len % 16; + + /* Handle multiple of blocksize */ + for (i = 0; i < n; i++) { + /* First round */ + temp_m128i = _mm_xor_si128(icb_m128i, key_schedule[0]); + /* Middle rounds */ + for (j = 1; j < ctx->key.rounds; j++) { + temp_m128i = _mm_aesenc_si128(temp_m128i, key_schedule[j]); + } + /* Last round */ + temp_m128i = _mm_aesenclast_si128(temp_m128i, + key_schedule[ctx->key.rounds]); + /* Fetch source and XOR to dest */ + src_m128i = _mm_loadu_si128((__m128i *)(src + i * 16)); + temp_m128i = _mm_xor_si128(src_m128i, temp_m128i); + _mm_storeu_si128((void *)(dst + i * 16), temp_m128i); + + /* Increment and continue */ + ricb_m128i = _mm_add_epi64(ricb_m128i, incrementer_m128i); + icb_m128i = _mm_shuffle_epi8(ricb_m128i, bswap_m128i); + } + + /* Handle remainder */ + if (partial_len != 0) { + unsigned int partial[16]; + memset(partial, 0x00, 16); + memcpy(partial, src + (n * 16), partial_len); + + /* First round */ + temp_m128i = _mm_xor_si128(icb_m128i, key_schedule[0]); + /* Middle rounds */ + for (j = 1; j < ctx->key.rounds; j++) { + temp_m128i = _mm_aesenc_si128(temp_m128i, key_schedule[j]); + } + /* Last round */ + temp_m128i = _mm_aesenclast_si128(temp_m128i, + key_schedule[ctx->key.rounds]); + /* Fetch source and XOR to dest */ + src_m128i = _mm_loadu_si128((__m128i *)(partial)); + temp_m128i = _mm_xor_si128(src_m128i, temp_m128i); + _mm_storeu_si128((void *)(partial), temp_m128i); + + memcpy(dst + (n * 16), partial, partial_len); + } +#ifdef PSTM_64BIT + ctx->icb_m128i = icb_m128i; +#else + _mm_storeu_si128(&ctx->icb_m128i, icb_m128i); +#endif +} + +/* NIST Special Publication 800-38D: 6.3 */ +static void galois_mul(__m128i a, __m128i b, __m128i *res) +{ + __m128i tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9; + + /* Inputs and output in reverse byte order */ + + tmp3 = _mm_clmulepi64_si128(a, b, 0x00); + tmp4 = _mm_clmulepi64_si128(a, b, 0x10); + tmp5 = _mm_clmulepi64_si128(a, b, 0x01); + tmp6 = _mm_clmulepi64_si128(a, b, 0x11); + + tmp4 = _mm_xor_si128(tmp4, tmp5); + tmp5 = _mm_slli_si128(tmp4, 8); + tmp4 = _mm_srli_si128(tmp4, 8); + tmp3 = _mm_xor_si128(tmp3, tmp5); + tmp6 = _mm_xor_si128(tmp6, tmp4); + + tmp7 = _mm_srli_epi32(tmp3, 31); + tmp8 = _mm_srli_epi32(tmp6, 31); + tmp3 = _mm_slli_epi32(tmp3, 1); + tmp6 = _mm_slli_epi32(tmp6, 1); + + tmp9 = _mm_srli_si128(tmp7, 12); + tmp8 = _mm_slli_si128(tmp8, 4); + tmp7 = _mm_slli_si128(tmp7, 4); + tmp3 = _mm_or_si128(tmp3, tmp7); + tmp6 = _mm_or_si128(tmp6, tmp8); + tmp6 = _mm_or_si128(tmp6, tmp9); + + tmp7 = _mm_slli_epi32(tmp3, 31); + tmp8 = _mm_slli_epi32(tmp3, 30); + tmp9 = _mm_slli_epi32(tmp3, 25); + + tmp7 = _mm_xor_si128(tmp7, tmp8); + tmp7 = _mm_xor_si128(tmp7, tmp9); + tmp8 = _mm_srli_si128(tmp7, 4); + tmp7 = _mm_slli_si128(tmp7, 12); + tmp3 = _mm_xor_si128(tmp3, tmp7); + + tmp2 = _mm_srli_epi32(tmp3, 1); + tmp4 = _mm_srli_epi32(tmp3, 2); + tmp5 = _mm_srli_epi32(tmp3, 7); + tmp2 = _mm_xor_si128(tmp2, tmp4); + tmp2 = _mm_xor_si128(tmp2, tmp5); + tmp2 = _mm_xor_si128(tmp2, tmp8); + tmp3 = _mm_xor_si128(tmp3, tmp2); + tmp6 = _mm_xor_si128(tmp6, tmp3); + + *res = tmp6; +} + +/* NIST Special Publication 800-38D: 6.4 */ +static __m128i galois_hash(__m128i h_m128i, __m128i y_m128i, + const unsigned char *buffer, size_t len) +{ + __m128i x_m128i, temp_m128i, temp2_m128i; + int i; + +#ifdef CRYPTO_ASSERT + psAssert(len % 16 == 0); +#endif + temp2_m128i = _mm_setzero_si128(); + /* H is already stored in reversed byte order */ + temp_m128i = flip_m128i(y_m128i); + + for (i = 0; i < (int)len; i += AES_BLOCKLEN) { + x_m128i = _mm_set_epi8(*(buffer + i), + *(buffer + i + 1), + *(buffer + i + 2), + *(buffer + i + 3), + *(buffer + i + 4), + *(buffer + i + 5), + *(buffer + i + 6), + *(buffer + i + 7), + *(buffer + i + 8), + *(buffer + i + 9), + *(buffer + i + 10), + *(buffer + i + 11), + *(buffer + i + 12), + *(buffer + i + 13), + *(buffer + i + 14), + *(buffer + i + 15)); + + temp_m128i = _mm_xor_si128(temp_m128i, x_m128i); + galois_mul(h_m128i, temp_m128i, &temp2_m128i); + temp_m128i = temp2_m128i; + } + + return flip_m128i(temp2_m128i); +} + +/* + Update the GCM hash state (does not update a_len) + If just hashing data, but not encrypting, a_len should be incremented + by caller. +*/ +static void gcm_update(psAesGcm_t *ctx, const unsigned char *buffer, + size_t len) +{ +#ifndef PSTM_64BIT + __m128i temp, temp2; +#endif + unsigned char partial[AES_BLOCKLEN]; + uint32 partial_len; + + if (len == 0) { + return; + } + partial_len = len % AES_BLOCKLEN; + /* First multiples of blocksize */ + if (len >= AES_BLOCKLEN) { +#ifdef PSTM_64BIT + ctx->y_m128i = galois_hash(ctx->h_m128i, ctx->y_m128i, + buffer, len - partial_len); +#else + // need to allign galois_hash parameters before calling + temp = _mm_loadu_si128(&ctx->h_m128i); + temp2 = _mm_loadu_si128(&ctx->y_m128i); + _mm_storeu_si128(&ctx->y_m128i, galois_hash(temp, temp2, + buffer, len - partial_len)); +#endif + } + /* The last partial block */ + if (partial_len != 0) { + memset(partial, 0x0, AES_BLOCKLEN); + memcpy(partial, ((buffer + len) - partial_len), partial_len); +#ifdef PSTM_64BIT + ctx->y_m128i = galois_hash(ctx->h_m128i, ctx->y_m128i, partial, 16); +#else + temp = _mm_loadu_si128(&ctx->h_m128i); + temp2 = _mm_loadu_si128(&ctx->y_m128i); + _mm_storeu_si128(&ctx->y_m128i, galois_hash(temp, temp2, partial, 16)); +#endif + } +} + +#define GCM_PUT_32BIT(cp, value) do { \ + ((unsigned char *)(cp))[0] = (unsigned char)((value) >> 24); \ + ((unsigned char *)(cp))[1] = (unsigned char)((value) >> 16); \ + ((unsigned char *)(cp))[2] = (unsigned char)((value) >> 8); \ + ((unsigned char *)(cp))[3] = (unsigned char)(value); } while (0) + +static void gcm_final(psAesGcm_t *ctx, unsigned char *digest) +{ +#ifndef PSTM_64BIT + __m128i temp, temp2; +#endif + unsigned char len_buffer[16]; + unsigned char iv_full[16]; + unsigned char final_y[16]; + + memset(len_buffer, 0x00, 16); + /* Store the number of bytes of AAD and AEAD */ + GCM_PUT_32BIT(len_buffer + 4, ctx->a_len * 8); + GCM_PUT_32BIT(len_buffer + 12, ctx->c_len * 8); + + /* Create the final y */ +#ifdef PSTM_64BIT + ctx->y_m128i = galois_hash(ctx->h_m128i, ctx->y_m128i, + len_buffer, 16); + _mm_storeu_si128((void *)(final_y), ctx->y_m128i); +#else + temp = _mm_loadu_si128(&ctx->h_m128i); + temp2 = _mm_loadu_si128(&ctx->y_m128i); + _mm_storeu_si128(&ctx->y_m128i, galois_hash(temp, temp2, + len_buffer, 16)); + temp2 = _mm_loadu_si128(&ctx->y_m128i); + _mm_storeu_si128((void *)(final_y), temp2); +#endif + + /* Run through GCTR to get T, old icb is not needed anymore */ + memset(iv_full, 0x00, 16); + memcpy(iv_full, ctx->IV, 12); + iv_full[15] = 0x01; +#ifdef PSTM_64BIT + ctx->icb_m128i = _mm_loadu_si128((__m128i *)iv_full); +#else + temp2 = _mm_loadu_si128((__m128i *)iv_full); + _mm_storeu_si128(&ctx->icb_m128i, temp2); +#endif + + /* Create last ciphertext */ + galois_counter(ctx, digest, final_y, 16); +} + +static void gcm_transform(psAesGcm_t *ctx, unsigned char *dest, + const unsigned char *src, size_t len, + unsigned char *iv, uint32 flags) +{ + unsigned char iv_full[16]; + + if (len == 0) { + return; + } + memcpy(ctx->IV, iv, 12); + if (!ctx->cipher_started) { + /* Create IV */ + memset(iv_full, 0x00, 16); + memcpy(iv_full, iv, 12); + iv_full[15] = 0x02; +#ifdef PSTM_64BIT + ctx->icb_m128i = _mm_loadu_si128((__m128i *)iv_full); +#else + _mm_storeu_si128(&ctx->icb_m128i, _mm_loadu_si128((__m128i *)iv_full)); +#endif + ctx->cipher_started = 1; + } + + if (flags & PS_AES_ENCRYPT) { + /* Create ciphertext */ + galois_counter(ctx, dest, src, len); + /* Update auth tag */ + gcm_update(ctx, dest, len); + } else { + /* Update auth tag */ + gcm_update(ctx, src, len); + /* Create ciphertext */ + galois_counter(ctx, dest, src, len); + } + /* Update authenticated and encrypted (AEAD) len */ + ctx->c_len += len; +} + +#endif /* USE_AESNI_AES_GCM */ + +/******************************************************************************/ + diff --git a/crypto/symmetric/aes_aesni.h b/crypto/symmetric/aes_aesni.h new file mode 100644 index 0000000..9764cc7 --- /dev/null +++ b/crypto/symmetric/aes_aesni.h @@ -0,0 +1,80 @@ +/** + * @file aes_aesni.h + * @version $Format:%h%d$ + * + * Header for AES-NI Hardware Crypto Instructions. + */ +/* + * Copyright (c) 2014-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ + +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifndef _h_AESNI_CRYPTO +#define _h_AESNI_CRYPTO + +/******************************************************************************/ +/* + Intel Native Instructions for AES + http://en.wikipedia.org/wiki/AES_instruction_set + */ + +#ifdef USE_AESNI_AES_BLOCK +#include +#include +typedef struct __attribute__((aligned(16))) { + __m128i skey[15]; /* Key schedule (encrypt or decrypt) */ + uint16 rounds; /* Number of rounds */ + uint16 type; /* Encrypt or Decrypt */ +} psAesKey_t; +#endif + +#ifdef USE_AESNI_AES_CBC +typedef struct __attribute__((aligned(16))) { + psAesKey_t key; + unsigned char IV[16]; +} psAesCbc_t; +#endif + +#ifdef USE_AESNI_AES_GCM +#include +typedef struct __attribute__((aligned(16))) { + psAesKey_t key; + unsigned char IV[16]; + __m128i h_m128i; + __m128i y_m128i; + __m128i icb_m128i; + int cipher_started; + unsigned int a_len; + unsigned int c_len; +} psAesGcm_t; +#endif + +#endif /* _h_AESNI_CRYPTO */ +/******************************************************************************/ + diff --git a/crypto/symmetric/aes_matrix.h b/crypto/symmetric/aes_matrix.h new file mode 100644 index 0000000..5cb2d9c --- /dev/null +++ b/crypto/symmetric/aes_matrix.h @@ -0,0 +1,171 @@ +/** + * @file aes_matrix.h + * @version $Format:%h%d$ + * + * Header for internal symmetric key cryptography support. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_AES_MATRIX +#define _h_AES_MATRIX + +/******************************************************************************/ +/* + Cipher usage in SSL is that any given key is used only for either encryption + or decryption, not both. If the same key is to be used for both, two + key structures must be initialized. + The first use of the key is what marks the key's usage (for example if + psAesEncryptBlock() is called on the key first, it can only be used + in future calls to encrypt. +*/ + +#ifdef USE_MATRIX_RAW_KEY +typedef struct { + uint8_t len; + unsigned char *key; +} psRawKey_t; +#endif + +#ifdef USE_MATRIX_AES_BLOCK +typedef struct { + uint32_t skey[64]; /**< Key schedule (either encrypt or decrypt) */ + uint16_t rounds; /**< Number of rounds */ + uint16_t type; /**< PS_AES_ENCRYPT or PS_AES_DECRYPT (inverse) key */ +} psAesKey_t; +#endif + +#ifdef USE_MATRIX_AES_CBC +typedef struct { + psAesKey_t key; + unsigned char IV[AES_BLOCKLEN]; +} psAesCbc_t; +#endif + +#ifdef USE_MATRIX_AES_GCM +typedef struct { + psAesKey_t key; + unsigned char IV[AES_BLOCKLEN]; + unsigned char EncCtr[AES_BLOCKLEN]; + unsigned char CtrBlock[AES_BLOCKLEN]; + unsigned char gInit[AES_BLOCKLEN]; + uint32_t TagTemp[AES_BLOCKLEN / sizeof(uint32_t)]; + unsigned char Hash_SubKey[AES_BLOCKLEN]; + uint32_t ProcessedBitCount[AES_BLOCKLEN / sizeof(uint32_t)]; + uint32_t InputBufferCount; + uint32_t OutputBufferCount; + union { + unsigned char Buffer[128]; + uint32_t BufferAlignment; + } Input; +} psAesGcm_t; +#endif + + +/******************************************************************************/ + +#ifdef USE_MATRIX_3DES + +typedef struct { + uint32_t ek[3][32]; + uint32_t dk[3][32]; +} psDes3Key_t; + +typedef struct { + psDes3Key_t key; + unsigned char IV[DES3_BLOCKLEN]; +} psDes3_t; + +#endif + +/******************************************************************************/ + +#ifdef USE_MATRIX_IDEA + +typedef struct { + uint16_t key_schedule[52]; +} psIdeaKey_t; + +typedef struct { + psIdeaKey_t key; + uint32_t IV[2]; + uint32_t inverted; +} psIdea_t; + +#endif + +/******************************************************************************/ + +#ifdef USE_MATRIX_SEED + +typedef struct { + uint32_t K[32]; + uint32_t dK[32]; +} psSeedKey_t; + +typedef struct { + psSeedKey_t key; + unsigned char IV[SEED_BLOCKLEN]; +} psSeed_t; + +#endif + +/******************************************************************************/ + +#ifdef USE_MATRIX_ARC4 + +typedef struct { + unsigned char state[256]; + uint32_t byteCount; + unsigned char x; + unsigned char y; +} psArc4_t; + +#endif + +/******************************************************************************/ + +#ifdef USE_MATRIX_RC2 + +#define RC2_BLOCKLEN 8 + +typedef struct { + uint32_t xkey[64]; +} psRc2Key_t; + +typedef struct { + psRc2Key_t key; + unsigned char IV[RC2_BLOCKLEN]; +} psRc2Cbc_t; + +#endif + +#endif /* _h_AES_MATRIX */ + +/******************************************************************************/ + diff --git a/crypto/symmetric/arc4.c b/crypto/symmetric/arc4.c new file mode 100644 index 0000000..7b68c4a --- /dev/null +++ b/crypto/symmetric/arc4.c @@ -0,0 +1,125 @@ +/** + * @file arc4.c + * @version $Format:%h%d$ + * + * ARC4 stream cipher implementation. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_MATRIX_ARC4 + +/******************************************************************************/ +/* + SECURITY + Some accounts, such as O'Reilly's Secure Programming Cookbook say that no + more than 2^30 bytes should be processed without rekeying, so we + enforce that limit here. FYI, this is equal to 1GB of data transferred. +*/ +#define ARC4_MAX_BYTES 0x40000000 + +/******************************************************************************/ +/* + + */ +int32_t psArc4Init(psArc4_t *arc4, const unsigned char *key, uint8_t keylen) +{ + unsigned char index1, index2, tmp, *state; + short counter; + + arc4->byteCount = 0; + state = &arc4->state[0]; + + for (counter = 0; counter < 256; counter++) { + state[counter] = (unsigned char)counter; + } + arc4->x = 0; + arc4->y = 0; + index1 = 0; + index2 = 0; + + for (counter = 0; counter < 256; counter++) { + index2 = (key[index1] + state[counter] + index2) & 0xff; + + tmp = state[counter]; + state[counter] = state[index2]; + state[index2] = tmp; + + index1 = (index1 + 1) % keylen; + } + return PS_SUCCESS; +} + +/******************************************************************************/ + +void psArc4(psArc4_t *arc4, const unsigned char *in, + unsigned char *out, uint32_t len) +{ + unsigned char x, y, *state, xorIndex, tmp; + uint32_t counter; + + arc4->byteCount += len; + if (arc4->byteCount > ARC4_MAX_BYTES) { + psTraceCrypto("ARC4 byteCount overrun\n"); + psAssert(arc4->byteCount <= ARC4_MAX_BYTES); + memzero_s(arc4, sizeof(psArc4_t)); + return; + } + + x = arc4->x; + y = arc4->y; + state = &arc4->state[0]; + for (counter = 0; counter < len; counter++) { + x = (x + 1) & 0xff; + y = (state[x] + y) & 0xff; + + tmp = state[x]; + state[x] = state[y]; + state[y] = tmp; + + xorIndex = (state[x] + state[y]) & 0xff; + + tmp = in[counter]; + tmp ^= state[xorIndex]; + out[counter] = tmp; + } + arc4->x = x; + arc4->y = y; +} + +void psArc4Clear(psArc4_t *arc4) +{ + memzero_s(arc4, sizeof(psArc4_t)); +} + +#endif /* USE_MATRIX_ARC4 */ + +/******************************************************************************/ + diff --git a/crypto/symmetric/des3.c b/crypto/symmetric/des3.c new file mode 100644 index 0000000..322abde --- /dev/null +++ b/crypto/symmetric/des3.c @@ -0,0 +1,1676 @@ +/** + * @file des3.c + * @version $Format:%h%d$ + * + * 3DES (and single DES) block cipher implementation for low memory usage. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_MATRIX_3DES + +/******************************************************************************/ + +static int32_t psDes3InitKey(const unsigned char *key, + psDes3Key_t *skey); +static void psDes3EncryptBlock(const unsigned char *pt, unsigned char *ct, + psDes3Key_t *skey); +static void psDes3DecryptBlock(const unsigned char *ct, unsigned char *pt, + psDes3Key_t *skey); + +#define byte(x, n) (((x) >> (8 * (n))) & 255) + +#define EN0 0 +#define DE1 1 + +static const uint32 bytebit[8] = +{ + 0200, 0100, 040, 020, 010, 04, 02, 01 +}; + +static const uint32_t bigbyte[24] = +{ + 0x800000UL, 0x400000UL, 0x200000UL, 0x100000UL, + 0x80000UL, 0x40000UL, 0x20000UL, 0x10000UL, + 0x8000UL, 0x4000UL, 0x2000UL, 0x1000UL, + 0x800UL, 0x400UL, 0x200UL, 0x100UL, + 0x80UL, 0x40UL, 0x20UL, 0x10UL, + 0x8UL, 0x4UL, 0x2UL, 0x1L +}; + +static const unsigned char pc1[56] = { + 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, + 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, + 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, + 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 +}; + +static const unsigned char pc2[48] = { + 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, + 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, + 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, + 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 +}; + +static const unsigned char totrot[16] = { + 1, 2, 4, 6, + 8, 10, 12, 14, + 15, 17, 19, 21, + 23, 25, 27, 28 +}; + +static const uint32_t SP1[] = +{ + 0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL, + 0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL, + 0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL, + 0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL, + 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL, + 0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL, + 0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL, + 0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL, + 0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL, + 0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL, + 0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL, + 0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL, + 0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL, + 0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL, + 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL, + 0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL +}; + +static const uint32_t SP2[] = +{ + 0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL, + 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL, + 0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL, + 0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL, + 0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL, + 0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL, + 0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL, + 0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL, + 0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL, + 0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL, + 0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL, + 0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL, + 0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL, + 0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL, + 0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL, + 0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL +}; + +static const uint32_t SP3[] = +{ + 0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL, + 0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL, + 0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL, + 0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL, + 0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL, + 0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL, + 0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL, + 0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL, + 0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL, + 0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL, + 0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL, + 0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL, + 0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL, + 0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL, + 0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL, + 0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL +}; + +static const uint32_t SP4[] = +{ + 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, + 0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL, + 0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL, + 0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL, + 0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL, + 0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL, + 0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL, + 0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL, + 0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL, + 0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL, + 0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL, + 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, + 0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL, + 0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL, + 0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL, + 0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL +}; + +static const uint32_t SP5[] = +{ + 0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL, + 0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL, + 0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL, + 0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL, + 0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL, + 0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL, + 0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL, + 0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL, + 0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL, + 0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL, + 0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL, + 0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL, + 0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL, + 0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL, + 0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL, + 0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL +}; + +static const uint32_t SP6[] = +{ + 0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL, + 0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL, + 0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL, + 0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, + 0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL, + 0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL, + 0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL, + 0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL, + 0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL, + 0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL, + 0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, + 0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL, + 0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL, + 0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL, + 0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL, + 0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL +}; + +static const uint32_t SP7[] = +{ + 0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL, + 0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL, + 0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL, + 0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL, + 0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL, + 0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL, + 0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL, + 0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL, + 0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL, + 0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL, + 0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL, + 0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL, + 0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL, + 0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL, + 0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL, + 0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL +}; + +static const uint32_t SP8[] = +{ + 0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL, + 0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL, + 0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL, + 0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL, + 0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL, + 0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL, + 0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL, + 0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL, + 0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL, + 0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL, + 0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL, + 0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL, + 0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL, + 0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL, + 0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL, + 0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL, + 0xe1f27f3aUL, 0xf5710fb0UL, 0xada0e5c4UL, 0x98e4c919UL +}; + +#if defined(PS_3DES_IMPROVE_PERF_INCREASE_CODESIZE) && defined(HAVE_NATIVE_INT64) + +static const uint64 des_ip[8][256] = { + +{ CONST64(0x0000000000000000), CONST64(0x0000001000000000), CONST64(0x0000000000000010), CONST64(0x0000001000000010), + CONST64(0x0000100000000000), CONST64(0x0000101000000000), CONST64(0x0000100000000010), CONST64(0x0000101000000010), + CONST64(0x0000000000001000), CONST64(0x0000001000001000), CONST64(0x0000000000001010), CONST64(0x0000001000001010), + CONST64(0x0000100000001000), CONST64(0x0000101000001000), CONST64(0x0000100000001010), CONST64(0x0000101000001010), + CONST64(0x0010000000000000), CONST64(0x0010001000000000), CONST64(0x0010000000000010), CONST64(0x0010001000000010), + CONST64(0x0010100000000000), CONST64(0x0010101000000000), CONST64(0x0010100000000010), CONST64(0x0010101000000010), + CONST64(0x0010000000001000), CONST64(0x0010001000001000), CONST64(0x0010000000001010), CONST64(0x0010001000001010), + CONST64(0x0010100000001000), CONST64(0x0010101000001000), CONST64(0x0010100000001010), CONST64(0x0010101000001010), + CONST64(0x0000000000100000), CONST64(0x0000001000100000), CONST64(0x0000000000100010), CONST64(0x0000001000100010), + CONST64(0x0000100000100000), CONST64(0x0000101000100000), CONST64(0x0000100000100010), CONST64(0x0000101000100010), + CONST64(0x0000000000101000), CONST64(0x0000001000101000), CONST64(0x0000000000101010), CONST64(0x0000001000101010), + CONST64(0x0000100000101000), CONST64(0x0000101000101000), CONST64(0x0000100000101010), CONST64(0x0000101000101010), + CONST64(0x0010000000100000), CONST64(0x0010001000100000), CONST64(0x0010000000100010), CONST64(0x0010001000100010), + CONST64(0x0010100000100000), CONST64(0x0010101000100000), CONST64(0x0010100000100010), CONST64(0x0010101000100010), + CONST64(0x0010000000101000), CONST64(0x0010001000101000), CONST64(0x0010000000101010), CONST64(0x0010001000101010), + CONST64(0x0010100000101000), CONST64(0x0010101000101000), CONST64(0x0010100000101010), CONST64(0x0010101000101010), + CONST64(0x1000000000000000), CONST64(0x1000001000000000), CONST64(0x1000000000000010), CONST64(0x1000001000000010), + CONST64(0x1000100000000000), CONST64(0x1000101000000000), CONST64(0x1000100000000010), CONST64(0x1000101000000010), + CONST64(0x1000000000001000), CONST64(0x1000001000001000), CONST64(0x1000000000001010), CONST64(0x1000001000001010), + CONST64(0x1000100000001000), CONST64(0x1000101000001000), CONST64(0x1000100000001010), CONST64(0x1000101000001010), + CONST64(0x1010000000000000), CONST64(0x1010001000000000), CONST64(0x1010000000000010), CONST64(0x1010001000000010), + CONST64(0x1010100000000000), CONST64(0x1010101000000000), CONST64(0x1010100000000010), CONST64(0x1010101000000010), + CONST64(0x1010000000001000), CONST64(0x1010001000001000), CONST64(0x1010000000001010), CONST64(0x1010001000001010), + CONST64(0x1010100000001000), CONST64(0x1010101000001000), CONST64(0x1010100000001010), CONST64(0x1010101000001010), + CONST64(0x1000000000100000), CONST64(0x1000001000100000), CONST64(0x1000000000100010), CONST64(0x1000001000100010), + CONST64(0x1000100000100000), CONST64(0x1000101000100000), CONST64(0x1000100000100010), CONST64(0x1000101000100010), + CONST64(0x1000000000101000), CONST64(0x1000001000101000), CONST64(0x1000000000101010), CONST64(0x1000001000101010), + CONST64(0x1000100000101000), CONST64(0x1000101000101000), CONST64(0x1000100000101010), CONST64(0x1000101000101010), + CONST64(0x1010000000100000), CONST64(0x1010001000100000), CONST64(0x1010000000100010), CONST64(0x1010001000100010), + CONST64(0x1010100000100000), CONST64(0x1010101000100000), CONST64(0x1010100000100010), CONST64(0x1010101000100010), + CONST64(0x1010000000101000), CONST64(0x1010001000101000), CONST64(0x1010000000101010), CONST64(0x1010001000101010), + CONST64(0x1010100000101000), CONST64(0x1010101000101000), CONST64(0x1010100000101010), CONST64(0x1010101000101010), + CONST64(0x0000000010000000), CONST64(0x0000001010000000), CONST64(0x0000000010000010), CONST64(0x0000001010000010), + CONST64(0x0000100010000000), CONST64(0x0000101010000000), CONST64(0x0000100010000010), CONST64(0x0000101010000010), + CONST64(0x0000000010001000), CONST64(0x0000001010001000), CONST64(0x0000000010001010), CONST64(0x0000001010001010), + CONST64(0x0000100010001000), CONST64(0x0000101010001000), CONST64(0x0000100010001010), CONST64(0x0000101010001010), + CONST64(0x0010000010000000), CONST64(0x0010001010000000), CONST64(0x0010000010000010), CONST64(0x0010001010000010), + CONST64(0x0010100010000000), CONST64(0x0010101010000000), CONST64(0x0010100010000010), CONST64(0x0010101010000010), + CONST64(0x0010000010001000), CONST64(0x0010001010001000), CONST64(0x0010000010001010), CONST64(0x0010001010001010), + CONST64(0x0010100010001000), CONST64(0x0010101010001000), CONST64(0x0010100010001010), CONST64(0x0010101010001010), + CONST64(0x0000000010100000), CONST64(0x0000001010100000), CONST64(0x0000000010100010), CONST64(0x0000001010100010), + CONST64(0x0000100010100000), CONST64(0x0000101010100000), CONST64(0x0000100010100010), CONST64(0x0000101010100010), + CONST64(0x0000000010101000), CONST64(0x0000001010101000), CONST64(0x0000000010101010), CONST64(0x0000001010101010), + CONST64(0x0000100010101000), CONST64(0x0000101010101000), CONST64(0x0000100010101010), CONST64(0x0000101010101010), + CONST64(0x0010000010100000), CONST64(0x0010001010100000), CONST64(0x0010000010100010), CONST64(0x0010001010100010), + CONST64(0x0010100010100000), CONST64(0x0010101010100000), CONST64(0x0010100010100010), CONST64(0x0010101010100010), + CONST64(0x0010000010101000), CONST64(0x0010001010101000), CONST64(0x0010000010101010), CONST64(0x0010001010101010), + CONST64(0x0010100010101000), CONST64(0x0010101010101000), CONST64(0x0010100010101010), CONST64(0x0010101010101010), + CONST64(0x1000000010000000), CONST64(0x1000001010000000), CONST64(0x1000000010000010), CONST64(0x1000001010000010), + CONST64(0x1000100010000000), CONST64(0x1000101010000000), CONST64(0x1000100010000010), CONST64(0x1000101010000010), + CONST64(0x1000000010001000), CONST64(0x1000001010001000), CONST64(0x1000000010001010), CONST64(0x1000001010001010), + CONST64(0x1000100010001000), CONST64(0x1000101010001000), CONST64(0x1000100010001010), CONST64(0x1000101010001010), + CONST64(0x1010000010000000), CONST64(0x1010001010000000), CONST64(0x1010000010000010), CONST64(0x1010001010000010), + CONST64(0x1010100010000000), CONST64(0x1010101010000000), CONST64(0x1010100010000010), CONST64(0x1010101010000010), + CONST64(0x1010000010001000), CONST64(0x1010001010001000), CONST64(0x1010000010001010), CONST64(0x1010001010001010), + CONST64(0x1010100010001000), CONST64(0x1010101010001000), CONST64(0x1010100010001010), CONST64(0x1010101010001010), + CONST64(0x1000000010100000), CONST64(0x1000001010100000), CONST64(0x1000000010100010), CONST64(0x1000001010100010), + CONST64(0x1000100010100000), CONST64(0x1000101010100000), CONST64(0x1000100010100010), CONST64(0x1000101010100010), + CONST64(0x1000000010101000), CONST64(0x1000001010101000), CONST64(0x1000000010101010), CONST64(0x1000001010101010), + CONST64(0x1000100010101000), CONST64(0x1000101010101000), CONST64(0x1000100010101010), CONST64(0x1000101010101010), + CONST64(0x1010000010100000), CONST64(0x1010001010100000), CONST64(0x1010000010100010), CONST64(0x1010001010100010), + CONST64(0x1010100010100000), CONST64(0x1010101010100000), CONST64(0x1010100010100010), CONST64(0x1010101010100010), + CONST64(0x1010000010101000), CONST64(0x1010001010101000), CONST64(0x1010000010101010), CONST64(0x1010001010101010), + CONST64(0x1010100010101000), CONST64(0x1010101010101000), CONST64(0x1010100010101010), CONST64(0x1010101010101010) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000800000000), CONST64(0x0000000000000008), CONST64(0x0000000800000008), + CONST64(0x0000080000000000), CONST64(0x0000080800000000), CONST64(0x0000080000000008), CONST64(0x0000080800000008), + CONST64(0x0000000000000800), CONST64(0x0000000800000800), CONST64(0x0000000000000808), CONST64(0x0000000800000808), + CONST64(0x0000080000000800), CONST64(0x0000080800000800), CONST64(0x0000080000000808), CONST64(0x0000080800000808), + CONST64(0x0008000000000000), CONST64(0x0008000800000000), CONST64(0x0008000000000008), CONST64(0x0008000800000008), + CONST64(0x0008080000000000), CONST64(0x0008080800000000), CONST64(0x0008080000000008), CONST64(0x0008080800000008), + CONST64(0x0008000000000800), CONST64(0x0008000800000800), CONST64(0x0008000000000808), CONST64(0x0008000800000808), + CONST64(0x0008080000000800), CONST64(0x0008080800000800), CONST64(0x0008080000000808), CONST64(0x0008080800000808), + CONST64(0x0000000000080000), CONST64(0x0000000800080000), CONST64(0x0000000000080008), CONST64(0x0000000800080008), + CONST64(0x0000080000080000), CONST64(0x0000080800080000), CONST64(0x0000080000080008), CONST64(0x0000080800080008), + CONST64(0x0000000000080800), CONST64(0x0000000800080800), CONST64(0x0000000000080808), CONST64(0x0000000800080808), + CONST64(0x0000080000080800), CONST64(0x0000080800080800), CONST64(0x0000080000080808), CONST64(0x0000080800080808), + CONST64(0x0008000000080000), CONST64(0x0008000800080000), CONST64(0x0008000000080008), CONST64(0x0008000800080008), + CONST64(0x0008080000080000), CONST64(0x0008080800080000), CONST64(0x0008080000080008), CONST64(0x0008080800080008), + CONST64(0x0008000000080800), CONST64(0x0008000800080800), CONST64(0x0008000000080808), CONST64(0x0008000800080808), + CONST64(0x0008080000080800), CONST64(0x0008080800080800), CONST64(0x0008080000080808), CONST64(0x0008080800080808), + CONST64(0x0800000000000000), CONST64(0x0800000800000000), CONST64(0x0800000000000008), CONST64(0x0800000800000008), + CONST64(0x0800080000000000), CONST64(0x0800080800000000), CONST64(0x0800080000000008), CONST64(0x0800080800000008), + CONST64(0x0800000000000800), CONST64(0x0800000800000800), CONST64(0x0800000000000808), CONST64(0x0800000800000808), + CONST64(0x0800080000000800), CONST64(0x0800080800000800), CONST64(0x0800080000000808), CONST64(0x0800080800000808), + CONST64(0x0808000000000000), CONST64(0x0808000800000000), CONST64(0x0808000000000008), CONST64(0x0808000800000008), + CONST64(0x0808080000000000), CONST64(0x0808080800000000), CONST64(0x0808080000000008), CONST64(0x0808080800000008), + CONST64(0x0808000000000800), CONST64(0x0808000800000800), CONST64(0x0808000000000808), CONST64(0x0808000800000808), + CONST64(0x0808080000000800), CONST64(0x0808080800000800), CONST64(0x0808080000000808), CONST64(0x0808080800000808), + CONST64(0x0800000000080000), CONST64(0x0800000800080000), CONST64(0x0800000000080008), CONST64(0x0800000800080008), + CONST64(0x0800080000080000), CONST64(0x0800080800080000), CONST64(0x0800080000080008), CONST64(0x0800080800080008), + CONST64(0x0800000000080800), CONST64(0x0800000800080800), CONST64(0x0800000000080808), CONST64(0x0800000800080808), + CONST64(0x0800080000080800), CONST64(0x0800080800080800), CONST64(0x0800080000080808), CONST64(0x0800080800080808), + CONST64(0x0808000000080000), CONST64(0x0808000800080000), CONST64(0x0808000000080008), CONST64(0x0808000800080008), + CONST64(0x0808080000080000), CONST64(0x0808080800080000), CONST64(0x0808080000080008), CONST64(0x0808080800080008), + CONST64(0x0808000000080800), CONST64(0x0808000800080800), CONST64(0x0808000000080808), CONST64(0x0808000800080808), + CONST64(0x0808080000080800), CONST64(0x0808080800080800), CONST64(0x0808080000080808), CONST64(0x0808080800080808), + CONST64(0x0000000008000000), CONST64(0x0000000808000000), CONST64(0x0000000008000008), CONST64(0x0000000808000008), + CONST64(0x0000080008000000), CONST64(0x0000080808000000), CONST64(0x0000080008000008), CONST64(0x0000080808000008), + CONST64(0x0000000008000800), CONST64(0x0000000808000800), CONST64(0x0000000008000808), CONST64(0x0000000808000808), + CONST64(0x0000080008000800), CONST64(0x0000080808000800), CONST64(0x0000080008000808), CONST64(0x0000080808000808), + CONST64(0x0008000008000000), CONST64(0x0008000808000000), CONST64(0x0008000008000008), CONST64(0x0008000808000008), + CONST64(0x0008080008000000), CONST64(0x0008080808000000), CONST64(0x0008080008000008), CONST64(0x0008080808000008), + CONST64(0x0008000008000800), CONST64(0x0008000808000800), CONST64(0x0008000008000808), CONST64(0x0008000808000808), + CONST64(0x0008080008000800), CONST64(0x0008080808000800), CONST64(0x0008080008000808), CONST64(0x0008080808000808), + CONST64(0x0000000008080000), CONST64(0x0000000808080000), CONST64(0x0000000008080008), CONST64(0x0000000808080008), + CONST64(0x0000080008080000), CONST64(0x0000080808080000), CONST64(0x0000080008080008), CONST64(0x0000080808080008), + CONST64(0x0000000008080800), CONST64(0x0000000808080800), CONST64(0x0000000008080808), CONST64(0x0000000808080808), + CONST64(0x0000080008080800), CONST64(0x0000080808080800), CONST64(0x0000080008080808), CONST64(0x0000080808080808), + CONST64(0x0008000008080000), CONST64(0x0008000808080000), CONST64(0x0008000008080008), CONST64(0x0008000808080008), + CONST64(0x0008080008080000), CONST64(0x0008080808080000), CONST64(0x0008080008080008), CONST64(0x0008080808080008), + CONST64(0x0008000008080800), CONST64(0x0008000808080800), CONST64(0x0008000008080808), CONST64(0x0008000808080808), + CONST64(0x0008080008080800), CONST64(0x0008080808080800), CONST64(0x0008080008080808), CONST64(0x0008080808080808), + CONST64(0x0800000008000000), CONST64(0x0800000808000000), CONST64(0x0800000008000008), CONST64(0x0800000808000008), + CONST64(0x0800080008000000), CONST64(0x0800080808000000), CONST64(0x0800080008000008), CONST64(0x0800080808000008), + CONST64(0x0800000008000800), CONST64(0x0800000808000800), CONST64(0x0800000008000808), CONST64(0x0800000808000808), + CONST64(0x0800080008000800), CONST64(0x0800080808000800), CONST64(0x0800080008000808), CONST64(0x0800080808000808), + CONST64(0x0808000008000000), CONST64(0x0808000808000000), CONST64(0x0808000008000008), CONST64(0x0808000808000008), + CONST64(0x0808080008000000), CONST64(0x0808080808000000), CONST64(0x0808080008000008), CONST64(0x0808080808000008), + CONST64(0x0808000008000800), CONST64(0x0808000808000800), CONST64(0x0808000008000808), CONST64(0x0808000808000808), + CONST64(0x0808080008000800), CONST64(0x0808080808000800), CONST64(0x0808080008000808), CONST64(0x0808080808000808), + CONST64(0x0800000008080000), CONST64(0x0800000808080000), CONST64(0x0800000008080008), CONST64(0x0800000808080008), + CONST64(0x0800080008080000), CONST64(0x0800080808080000), CONST64(0x0800080008080008), CONST64(0x0800080808080008), + CONST64(0x0800000008080800), CONST64(0x0800000808080800), CONST64(0x0800000008080808), CONST64(0x0800000808080808), + CONST64(0x0800080008080800), CONST64(0x0800080808080800), CONST64(0x0800080008080808), CONST64(0x0800080808080808), + CONST64(0x0808000008080000), CONST64(0x0808000808080000), CONST64(0x0808000008080008), CONST64(0x0808000808080008), + CONST64(0x0808080008080000), CONST64(0x0808080808080000), CONST64(0x0808080008080008), CONST64(0x0808080808080008), + CONST64(0x0808000008080800), CONST64(0x0808000808080800), CONST64(0x0808000008080808), CONST64(0x0808000808080808), + CONST64(0x0808080008080800), CONST64(0x0808080808080800), CONST64(0x0808080008080808), CONST64(0x0808080808080808) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000400000000), CONST64(0x0000000000000004), CONST64(0x0000000400000004), + CONST64(0x0000040000000000), CONST64(0x0000040400000000), CONST64(0x0000040000000004), CONST64(0x0000040400000004), + CONST64(0x0000000000000400), CONST64(0x0000000400000400), CONST64(0x0000000000000404), CONST64(0x0000000400000404), + CONST64(0x0000040000000400), CONST64(0x0000040400000400), CONST64(0x0000040000000404), CONST64(0x0000040400000404), + CONST64(0x0004000000000000), CONST64(0x0004000400000000), CONST64(0x0004000000000004), CONST64(0x0004000400000004), + CONST64(0x0004040000000000), CONST64(0x0004040400000000), CONST64(0x0004040000000004), CONST64(0x0004040400000004), + CONST64(0x0004000000000400), CONST64(0x0004000400000400), CONST64(0x0004000000000404), CONST64(0x0004000400000404), + CONST64(0x0004040000000400), CONST64(0x0004040400000400), CONST64(0x0004040000000404), CONST64(0x0004040400000404), + CONST64(0x0000000000040000), CONST64(0x0000000400040000), CONST64(0x0000000000040004), CONST64(0x0000000400040004), + CONST64(0x0000040000040000), CONST64(0x0000040400040000), CONST64(0x0000040000040004), CONST64(0x0000040400040004), + CONST64(0x0000000000040400), CONST64(0x0000000400040400), CONST64(0x0000000000040404), CONST64(0x0000000400040404), + CONST64(0x0000040000040400), CONST64(0x0000040400040400), CONST64(0x0000040000040404), CONST64(0x0000040400040404), + CONST64(0x0004000000040000), CONST64(0x0004000400040000), CONST64(0x0004000000040004), CONST64(0x0004000400040004), + CONST64(0x0004040000040000), CONST64(0x0004040400040000), CONST64(0x0004040000040004), CONST64(0x0004040400040004), + CONST64(0x0004000000040400), CONST64(0x0004000400040400), CONST64(0x0004000000040404), CONST64(0x0004000400040404), + CONST64(0x0004040000040400), CONST64(0x0004040400040400), CONST64(0x0004040000040404), CONST64(0x0004040400040404), + CONST64(0x0400000000000000), CONST64(0x0400000400000000), CONST64(0x0400000000000004), CONST64(0x0400000400000004), + CONST64(0x0400040000000000), CONST64(0x0400040400000000), CONST64(0x0400040000000004), CONST64(0x0400040400000004), + CONST64(0x0400000000000400), CONST64(0x0400000400000400), CONST64(0x0400000000000404), CONST64(0x0400000400000404), + CONST64(0x0400040000000400), CONST64(0x0400040400000400), CONST64(0x0400040000000404), CONST64(0x0400040400000404), + CONST64(0x0404000000000000), CONST64(0x0404000400000000), CONST64(0x0404000000000004), CONST64(0x0404000400000004), + CONST64(0x0404040000000000), CONST64(0x0404040400000000), CONST64(0x0404040000000004), CONST64(0x0404040400000004), + CONST64(0x0404000000000400), CONST64(0x0404000400000400), CONST64(0x0404000000000404), CONST64(0x0404000400000404), + CONST64(0x0404040000000400), CONST64(0x0404040400000400), CONST64(0x0404040000000404), CONST64(0x0404040400000404), + CONST64(0x0400000000040000), CONST64(0x0400000400040000), CONST64(0x0400000000040004), CONST64(0x0400000400040004), + CONST64(0x0400040000040000), CONST64(0x0400040400040000), CONST64(0x0400040000040004), CONST64(0x0400040400040004), + CONST64(0x0400000000040400), CONST64(0x0400000400040400), CONST64(0x0400000000040404), CONST64(0x0400000400040404), + CONST64(0x0400040000040400), CONST64(0x0400040400040400), CONST64(0x0400040000040404), CONST64(0x0400040400040404), + CONST64(0x0404000000040000), CONST64(0x0404000400040000), CONST64(0x0404000000040004), CONST64(0x0404000400040004), + CONST64(0x0404040000040000), CONST64(0x0404040400040000), CONST64(0x0404040000040004), CONST64(0x0404040400040004), + CONST64(0x0404000000040400), CONST64(0x0404000400040400), CONST64(0x0404000000040404), CONST64(0x0404000400040404), + CONST64(0x0404040000040400), CONST64(0x0404040400040400), CONST64(0x0404040000040404), CONST64(0x0404040400040404), + CONST64(0x0000000004000000), CONST64(0x0000000404000000), CONST64(0x0000000004000004), CONST64(0x0000000404000004), + CONST64(0x0000040004000000), CONST64(0x0000040404000000), CONST64(0x0000040004000004), CONST64(0x0000040404000004), + CONST64(0x0000000004000400), CONST64(0x0000000404000400), CONST64(0x0000000004000404), CONST64(0x0000000404000404), + CONST64(0x0000040004000400), CONST64(0x0000040404000400), CONST64(0x0000040004000404), CONST64(0x0000040404000404), + CONST64(0x0004000004000000), CONST64(0x0004000404000000), CONST64(0x0004000004000004), CONST64(0x0004000404000004), + CONST64(0x0004040004000000), CONST64(0x0004040404000000), CONST64(0x0004040004000004), CONST64(0x0004040404000004), + CONST64(0x0004000004000400), CONST64(0x0004000404000400), CONST64(0x0004000004000404), CONST64(0x0004000404000404), + CONST64(0x0004040004000400), CONST64(0x0004040404000400), CONST64(0x0004040004000404), CONST64(0x0004040404000404), + CONST64(0x0000000004040000), CONST64(0x0000000404040000), CONST64(0x0000000004040004), CONST64(0x0000000404040004), + CONST64(0x0000040004040000), CONST64(0x0000040404040000), CONST64(0x0000040004040004), CONST64(0x0000040404040004), + CONST64(0x0000000004040400), CONST64(0x0000000404040400), CONST64(0x0000000004040404), CONST64(0x0000000404040404), + CONST64(0x0000040004040400), CONST64(0x0000040404040400), CONST64(0x0000040004040404), CONST64(0x0000040404040404), + CONST64(0x0004000004040000), CONST64(0x0004000404040000), CONST64(0x0004000004040004), CONST64(0x0004000404040004), + CONST64(0x0004040004040000), CONST64(0x0004040404040000), CONST64(0x0004040004040004), CONST64(0x0004040404040004), + CONST64(0x0004000004040400), CONST64(0x0004000404040400), CONST64(0x0004000004040404), CONST64(0x0004000404040404), + CONST64(0x0004040004040400), CONST64(0x0004040404040400), CONST64(0x0004040004040404), CONST64(0x0004040404040404), + CONST64(0x0400000004000000), CONST64(0x0400000404000000), CONST64(0x0400000004000004), CONST64(0x0400000404000004), + CONST64(0x0400040004000000), CONST64(0x0400040404000000), CONST64(0x0400040004000004), CONST64(0x0400040404000004), + CONST64(0x0400000004000400), CONST64(0x0400000404000400), CONST64(0x0400000004000404), CONST64(0x0400000404000404), + CONST64(0x0400040004000400), CONST64(0x0400040404000400), CONST64(0x0400040004000404), CONST64(0x0400040404000404), + CONST64(0x0404000004000000), CONST64(0x0404000404000000), CONST64(0x0404000004000004), CONST64(0x0404000404000004), + CONST64(0x0404040004000000), CONST64(0x0404040404000000), CONST64(0x0404040004000004), CONST64(0x0404040404000004), + CONST64(0x0404000004000400), CONST64(0x0404000404000400), CONST64(0x0404000004000404), CONST64(0x0404000404000404), + CONST64(0x0404040004000400), CONST64(0x0404040404000400), CONST64(0x0404040004000404), CONST64(0x0404040404000404), + CONST64(0x0400000004040000), CONST64(0x0400000404040000), CONST64(0x0400000004040004), CONST64(0x0400000404040004), + CONST64(0x0400040004040000), CONST64(0x0400040404040000), CONST64(0x0400040004040004), CONST64(0x0400040404040004), + CONST64(0x0400000004040400), CONST64(0x0400000404040400), CONST64(0x0400000004040404), CONST64(0x0400000404040404), + CONST64(0x0400040004040400), CONST64(0x0400040404040400), CONST64(0x0400040004040404), CONST64(0x0400040404040404), + CONST64(0x0404000004040000), CONST64(0x0404000404040000), CONST64(0x0404000004040004), CONST64(0x0404000404040004), + CONST64(0x0404040004040000), CONST64(0x0404040404040000), CONST64(0x0404040004040004), CONST64(0x0404040404040004), + CONST64(0x0404000004040400), CONST64(0x0404000404040400), CONST64(0x0404000004040404), CONST64(0x0404000404040404), + CONST64(0x0404040004040400), CONST64(0x0404040404040400), CONST64(0x0404040004040404), CONST64(0x0404040404040404) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000200000000), CONST64(0x0000000000000002), CONST64(0x0000000200000002), + CONST64(0x0000020000000000), CONST64(0x0000020200000000), CONST64(0x0000020000000002), CONST64(0x0000020200000002), + CONST64(0x0000000000000200), CONST64(0x0000000200000200), CONST64(0x0000000000000202), CONST64(0x0000000200000202), + CONST64(0x0000020000000200), CONST64(0x0000020200000200), CONST64(0x0000020000000202), CONST64(0x0000020200000202), + CONST64(0x0002000000000000), CONST64(0x0002000200000000), CONST64(0x0002000000000002), CONST64(0x0002000200000002), + CONST64(0x0002020000000000), CONST64(0x0002020200000000), CONST64(0x0002020000000002), CONST64(0x0002020200000002), + CONST64(0x0002000000000200), CONST64(0x0002000200000200), CONST64(0x0002000000000202), CONST64(0x0002000200000202), + CONST64(0x0002020000000200), CONST64(0x0002020200000200), CONST64(0x0002020000000202), CONST64(0x0002020200000202), + CONST64(0x0000000000020000), CONST64(0x0000000200020000), CONST64(0x0000000000020002), CONST64(0x0000000200020002), + CONST64(0x0000020000020000), CONST64(0x0000020200020000), CONST64(0x0000020000020002), CONST64(0x0000020200020002), + CONST64(0x0000000000020200), CONST64(0x0000000200020200), CONST64(0x0000000000020202), CONST64(0x0000000200020202), + CONST64(0x0000020000020200), CONST64(0x0000020200020200), CONST64(0x0000020000020202), CONST64(0x0000020200020202), + CONST64(0x0002000000020000), CONST64(0x0002000200020000), CONST64(0x0002000000020002), CONST64(0x0002000200020002), + CONST64(0x0002020000020000), CONST64(0x0002020200020000), CONST64(0x0002020000020002), CONST64(0x0002020200020002), + CONST64(0x0002000000020200), CONST64(0x0002000200020200), CONST64(0x0002000000020202), CONST64(0x0002000200020202), + CONST64(0x0002020000020200), CONST64(0x0002020200020200), CONST64(0x0002020000020202), CONST64(0x0002020200020202), + CONST64(0x0200000000000000), CONST64(0x0200000200000000), CONST64(0x0200000000000002), CONST64(0x0200000200000002), + CONST64(0x0200020000000000), CONST64(0x0200020200000000), CONST64(0x0200020000000002), CONST64(0x0200020200000002), + CONST64(0x0200000000000200), CONST64(0x0200000200000200), CONST64(0x0200000000000202), CONST64(0x0200000200000202), + CONST64(0x0200020000000200), CONST64(0x0200020200000200), CONST64(0x0200020000000202), CONST64(0x0200020200000202), + CONST64(0x0202000000000000), CONST64(0x0202000200000000), CONST64(0x0202000000000002), CONST64(0x0202000200000002), + CONST64(0x0202020000000000), CONST64(0x0202020200000000), CONST64(0x0202020000000002), CONST64(0x0202020200000002), + CONST64(0x0202000000000200), CONST64(0x0202000200000200), CONST64(0x0202000000000202), CONST64(0x0202000200000202), + CONST64(0x0202020000000200), CONST64(0x0202020200000200), CONST64(0x0202020000000202), CONST64(0x0202020200000202), + CONST64(0x0200000000020000), CONST64(0x0200000200020000), CONST64(0x0200000000020002), CONST64(0x0200000200020002), + CONST64(0x0200020000020000), CONST64(0x0200020200020000), CONST64(0x0200020000020002), CONST64(0x0200020200020002), + CONST64(0x0200000000020200), CONST64(0x0200000200020200), CONST64(0x0200000000020202), CONST64(0x0200000200020202), + CONST64(0x0200020000020200), CONST64(0x0200020200020200), CONST64(0x0200020000020202), CONST64(0x0200020200020202), + CONST64(0x0202000000020000), CONST64(0x0202000200020000), CONST64(0x0202000000020002), CONST64(0x0202000200020002), + CONST64(0x0202020000020000), CONST64(0x0202020200020000), CONST64(0x0202020000020002), CONST64(0x0202020200020002), + CONST64(0x0202000000020200), CONST64(0x0202000200020200), CONST64(0x0202000000020202), CONST64(0x0202000200020202), + CONST64(0x0202020000020200), CONST64(0x0202020200020200), CONST64(0x0202020000020202), CONST64(0x0202020200020202), + CONST64(0x0000000002000000), CONST64(0x0000000202000000), CONST64(0x0000000002000002), CONST64(0x0000000202000002), + CONST64(0x0000020002000000), CONST64(0x0000020202000000), CONST64(0x0000020002000002), CONST64(0x0000020202000002), + CONST64(0x0000000002000200), CONST64(0x0000000202000200), CONST64(0x0000000002000202), CONST64(0x0000000202000202), + CONST64(0x0000020002000200), CONST64(0x0000020202000200), CONST64(0x0000020002000202), CONST64(0x0000020202000202), + CONST64(0x0002000002000000), CONST64(0x0002000202000000), CONST64(0x0002000002000002), CONST64(0x0002000202000002), + CONST64(0x0002020002000000), CONST64(0x0002020202000000), CONST64(0x0002020002000002), CONST64(0x0002020202000002), + CONST64(0x0002000002000200), CONST64(0x0002000202000200), CONST64(0x0002000002000202), CONST64(0x0002000202000202), + CONST64(0x0002020002000200), CONST64(0x0002020202000200), CONST64(0x0002020002000202), CONST64(0x0002020202000202), + CONST64(0x0000000002020000), CONST64(0x0000000202020000), CONST64(0x0000000002020002), CONST64(0x0000000202020002), + CONST64(0x0000020002020000), CONST64(0x0000020202020000), CONST64(0x0000020002020002), CONST64(0x0000020202020002), + CONST64(0x0000000002020200), CONST64(0x0000000202020200), CONST64(0x0000000002020202), CONST64(0x0000000202020202), + CONST64(0x0000020002020200), CONST64(0x0000020202020200), CONST64(0x0000020002020202), CONST64(0x0000020202020202), + CONST64(0x0002000002020000), CONST64(0x0002000202020000), CONST64(0x0002000002020002), CONST64(0x0002000202020002), + CONST64(0x0002020002020000), CONST64(0x0002020202020000), CONST64(0x0002020002020002), CONST64(0x0002020202020002), + CONST64(0x0002000002020200), CONST64(0x0002000202020200), CONST64(0x0002000002020202), CONST64(0x0002000202020202), + CONST64(0x0002020002020200), CONST64(0x0002020202020200), CONST64(0x0002020002020202), CONST64(0x0002020202020202), + CONST64(0x0200000002000000), CONST64(0x0200000202000000), CONST64(0x0200000002000002), CONST64(0x0200000202000002), + CONST64(0x0200020002000000), CONST64(0x0200020202000000), CONST64(0x0200020002000002), CONST64(0x0200020202000002), + CONST64(0x0200000002000200), CONST64(0x0200000202000200), CONST64(0x0200000002000202), CONST64(0x0200000202000202), + CONST64(0x0200020002000200), CONST64(0x0200020202000200), CONST64(0x0200020002000202), CONST64(0x0200020202000202), + CONST64(0x0202000002000000), CONST64(0x0202000202000000), CONST64(0x0202000002000002), CONST64(0x0202000202000002), + CONST64(0x0202020002000000), CONST64(0x0202020202000000), CONST64(0x0202020002000002), CONST64(0x0202020202000002), + CONST64(0x0202000002000200), CONST64(0x0202000202000200), CONST64(0x0202000002000202), CONST64(0x0202000202000202), + CONST64(0x0202020002000200), CONST64(0x0202020202000200), CONST64(0x0202020002000202), CONST64(0x0202020202000202), + CONST64(0x0200000002020000), CONST64(0x0200000202020000), CONST64(0x0200000002020002), CONST64(0x0200000202020002), + CONST64(0x0200020002020000), CONST64(0x0200020202020000), CONST64(0x0200020002020002), CONST64(0x0200020202020002), + CONST64(0x0200000002020200), CONST64(0x0200000202020200), CONST64(0x0200000002020202), CONST64(0x0200000202020202), + CONST64(0x0200020002020200), CONST64(0x0200020202020200), CONST64(0x0200020002020202), CONST64(0x0200020202020202), + CONST64(0x0202000002020000), CONST64(0x0202000202020000), CONST64(0x0202000002020002), CONST64(0x0202000202020002), + CONST64(0x0202020002020000), CONST64(0x0202020202020000), CONST64(0x0202020002020002), CONST64(0x0202020202020002), + CONST64(0x0202000002020200), CONST64(0x0202000202020200), CONST64(0x0202000002020202), CONST64(0x0202000202020202), + CONST64(0x0202020002020200), CONST64(0x0202020202020200), CONST64(0x0202020002020202), CONST64(0x0202020202020202) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000010000000000), CONST64(0x0000000000000100), CONST64(0x0000010000000100), + CONST64(0x0001000000000000), CONST64(0x0001010000000000), CONST64(0x0001000000000100), CONST64(0x0001010000000100), + CONST64(0x0000000000010000), CONST64(0x0000010000010000), CONST64(0x0000000000010100), CONST64(0x0000010000010100), + CONST64(0x0001000000010000), CONST64(0x0001010000010000), CONST64(0x0001000000010100), CONST64(0x0001010000010100), + CONST64(0x0100000000000000), CONST64(0x0100010000000000), CONST64(0x0100000000000100), CONST64(0x0100010000000100), + CONST64(0x0101000000000000), CONST64(0x0101010000000000), CONST64(0x0101000000000100), CONST64(0x0101010000000100), + CONST64(0x0100000000010000), CONST64(0x0100010000010000), CONST64(0x0100000000010100), CONST64(0x0100010000010100), + CONST64(0x0101000000010000), CONST64(0x0101010000010000), CONST64(0x0101000000010100), CONST64(0x0101010000010100), + CONST64(0x0000000001000000), CONST64(0x0000010001000000), CONST64(0x0000000001000100), CONST64(0x0000010001000100), + CONST64(0x0001000001000000), CONST64(0x0001010001000000), CONST64(0x0001000001000100), CONST64(0x0001010001000100), + CONST64(0x0000000001010000), CONST64(0x0000010001010000), CONST64(0x0000000001010100), CONST64(0x0000010001010100), + CONST64(0x0001000001010000), CONST64(0x0001010001010000), CONST64(0x0001000001010100), CONST64(0x0001010001010100), + CONST64(0x0100000001000000), CONST64(0x0100010001000000), CONST64(0x0100000001000100), CONST64(0x0100010001000100), + CONST64(0x0101000001000000), CONST64(0x0101010001000000), CONST64(0x0101000001000100), CONST64(0x0101010001000100), + CONST64(0x0100000001010000), CONST64(0x0100010001010000), CONST64(0x0100000001010100), CONST64(0x0100010001010100), + CONST64(0x0101000001010000), CONST64(0x0101010001010000), CONST64(0x0101000001010100), CONST64(0x0101010001010100), + CONST64(0x0000000100000000), CONST64(0x0000010100000000), CONST64(0x0000000100000100), CONST64(0x0000010100000100), + CONST64(0x0001000100000000), CONST64(0x0001010100000000), CONST64(0x0001000100000100), CONST64(0x0001010100000100), + CONST64(0x0000000100010000), CONST64(0x0000010100010000), CONST64(0x0000000100010100), CONST64(0x0000010100010100), + CONST64(0x0001000100010000), CONST64(0x0001010100010000), CONST64(0x0001000100010100), CONST64(0x0001010100010100), + CONST64(0x0100000100000000), CONST64(0x0100010100000000), CONST64(0x0100000100000100), CONST64(0x0100010100000100), + CONST64(0x0101000100000000), CONST64(0x0101010100000000), CONST64(0x0101000100000100), CONST64(0x0101010100000100), + CONST64(0x0100000100010000), CONST64(0x0100010100010000), CONST64(0x0100000100010100), CONST64(0x0100010100010100), + CONST64(0x0101000100010000), CONST64(0x0101010100010000), CONST64(0x0101000100010100), CONST64(0x0101010100010100), + CONST64(0x0000000101000000), CONST64(0x0000010101000000), CONST64(0x0000000101000100), CONST64(0x0000010101000100), + CONST64(0x0001000101000000), CONST64(0x0001010101000000), CONST64(0x0001000101000100), CONST64(0x0001010101000100), + CONST64(0x0000000101010000), CONST64(0x0000010101010000), CONST64(0x0000000101010100), CONST64(0x0000010101010100), + CONST64(0x0001000101010000), CONST64(0x0001010101010000), CONST64(0x0001000101010100), CONST64(0x0001010101010100), + CONST64(0x0100000101000000), CONST64(0x0100010101000000), CONST64(0x0100000101000100), CONST64(0x0100010101000100), + CONST64(0x0101000101000000), CONST64(0x0101010101000000), CONST64(0x0101000101000100), CONST64(0x0101010101000100), + CONST64(0x0100000101010000), CONST64(0x0100010101010000), CONST64(0x0100000101010100), CONST64(0x0100010101010100), + CONST64(0x0101000101010000), CONST64(0x0101010101010000), CONST64(0x0101000101010100), CONST64(0x0101010101010100), + CONST64(0x0000000000000001), CONST64(0x0000010000000001), CONST64(0x0000000000000101), CONST64(0x0000010000000101), + CONST64(0x0001000000000001), CONST64(0x0001010000000001), CONST64(0x0001000000000101), CONST64(0x0001010000000101), + CONST64(0x0000000000010001), CONST64(0x0000010000010001), CONST64(0x0000000000010101), CONST64(0x0000010000010101), + CONST64(0x0001000000010001), CONST64(0x0001010000010001), CONST64(0x0001000000010101), CONST64(0x0001010000010101), + CONST64(0x0100000000000001), CONST64(0x0100010000000001), CONST64(0x0100000000000101), CONST64(0x0100010000000101), + CONST64(0x0101000000000001), CONST64(0x0101010000000001), CONST64(0x0101000000000101), CONST64(0x0101010000000101), + CONST64(0x0100000000010001), CONST64(0x0100010000010001), CONST64(0x0100000000010101), CONST64(0x0100010000010101), + CONST64(0x0101000000010001), CONST64(0x0101010000010001), CONST64(0x0101000000010101), CONST64(0x0101010000010101), + CONST64(0x0000000001000001), CONST64(0x0000010001000001), CONST64(0x0000000001000101), CONST64(0x0000010001000101), + CONST64(0x0001000001000001), CONST64(0x0001010001000001), CONST64(0x0001000001000101), CONST64(0x0001010001000101), + CONST64(0x0000000001010001), CONST64(0x0000010001010001), CONST64(0x0000000001010101), CONST64(0x0000010001010101), + CONST64(0x0001000001010001), CONST64(0x0001010001010001), CONST64(0x0001000001010101), CONST64(0x0001010001010101), + CONST64(0x0100000001000001), CONST64(0x0100010001000001), CONST64(0x0100000001000101), CONST64(0x0100010001000101), + CONST64(0x0101000001000001), CONST64(0x0101010001000001), CONST64(0x0101000001000101), CONST64(0x0101010001000101), + CONST64(0x0100000001010001), CONST64(0x0100010001010001), CONST64(0x0100000001010101), CONST64(0x0100010001010101), + CONST64(0x0101000001010001), CONST64(0x0101010001010001), CONST64(0x0101000001010101), CONST64(0x0101010001010101), + CONST64(0x0000000100000001), CONST64(0x0000010100000001), CONST64(0x0000000100000101), CONST64(0x0000010100000101), + CONST64(0x0001000100000001), CONST64(0x0001010100000001), CONST64(0x0001000100000101), CONST64(0x0001010100000101), + CONST64(0x0000000100010001), CONST64(0x0000010100010001), CONST64(0x0000000100010101), CONST64(0x0000010100010101), + CONST64(0x0001000100010001), CONST64(0x0001010100010001), CONST64(0x0001000100010101), CONST64(0x0001010100010101), + CONST64(0x0100000100000001), CONST64(0x0100010100000001), CONST64(0x0100000100000101), CONST64(0x0100010100000101), + CONST64(0x0101000100000001), CONST64(0x0101010100000001), CONST64(0x0101000100000101), CONST64(0x0101010100000101), + CONST64(0x0100000100010001), CONST64(0x0100010100010001), CONST64(0x0100000100010101), CONST64(0x0100010100010101), + CONST64(0x0101000100010001), CONST64(0x0101010100010001), CONST64(0x0101000100010101), CONST64(0x0101010100010101), + CONST64(0x0000000101000001), CONST64(0x0000010101000001), CONST64(0x0000000101000101), CONST64(0x0000010101000101), + CONST64(0x0001000101000001), CONST64(0x0001010101000001), CONST64(0x0001000101000101), CONST64(0x0001010101000101), + CONST64(0x0000000101010001), CONST64(0x0000010101010001), CONST64(0x0000000101010101), CONST64(0x0000010101010101), + CONST64(0x0001000101010001), CONST64(0x0001010101010001), CONST64(0x0001000101010101), CONST64(0x0001010101010101), + CONST64(0x0100000101000001), CONST64(0x0100010101000001), CONST64(0x0100000101000101), CONST64(0x0100010101000101), + CONST64(0x0101000101000001), CONST64(0x0101010101000001), CONST64(0x0101000101000101), CONST64(0x0101010101000101), + CONST64(0x0100000101010001), CONST64(0x0100010101010001), CONST64(0x0100000101010101), CONST64(0x0100010101010101), + CONST64(0x0101000101010001), CONST64(0x0101010101010001), CONST64(0x0101000101010101), CONST64(0x0101010101010101) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000008000000000), CONST64(0x0000000000000080), CONST64(0x0000008000000080), + CONST64(0x0000800000000000), CONST64(0x0000808000000000), CONST64(0x0000800000000080), CONST64(0x0000808000000080), + CONST64(0x0000000000008000), CONST64(0x0000008000008000), CONST64(0x0000000000008080), CONST64(0x0000008000008080), + CONST64(0x0000800000008000), CONST64(0x0000808000008000), CONST64(0x0000800000008080), CONST64(0x0000808000008080), + CONST64(0x0080000000000000), CONST64(0x0080008000000000), CONST64(0x0080000000000080), CONST64(0x0080008000000080), + CONST64(0x0080800000000000), CONST64(0x0080808000000000), CONST64(0x0080800000000080), CONST64(0x0080808000000080), + CONST64(0x0080000000008000), CONST64(0x0080008000008000), CONST64(0x0080000000008080), CONST64(0x0080008000008080), + CONST64(0x0080800000008000), CONST64(0x0080808000008000), CONST64(0x0080800000008080), CONST64(0x0080808000008080), + CONST64(0x0000000000800000), CONST64(0x0000008000800000), CONST64(0x0000000000800080), CONST64(0x0000008000800080), + CONST64(0x0000800000800000), CONST64(0x0000808000800000), CONST64(0x0000800000800080), CONST64(0x0000808000800080), + CONST64(0x0000000000808000), CONST64(0x0000008000808000), CONST64(0x0000000000808080), CONST64(0x0000008000808080), + CONST64(0x0000800000808000), CONST64(0x0000808000808000), CONST64(0x0000800000808080), CONST64(0x0000808000808080), + CONST64(0x0080000000800000), CONST64(0x0080008000800000), CONST64(0x0080000000800080), CONST64(0x0080008000800080), + CONST64(0x0080800000800000), CONST64(0x0080808000800000), CONST64(0x0080800000800080), CONST64(0x0080808000800080), + CONST64(0x0080000000808000), CONST64(0x0080008000808000), CONST64(0x0080000000808080), CONST64(0x0080008000808080), + CONST64(0x0080800000808000), CONST64(0x0080808000808000), CONST64(0x0080800000808080), CONST64(0x0080808000808080), + CONST64(0x8000000000000000), CONST64(0x8000008000000000), CONST64(0x8000000000000080), CONST64(0x8000008000000080), + CONST64(0x8000800000000000), CONST64(0x8000808000000000), CONST64(0x8000800000000080), CONST64(0x8000808000000080), + CONST64(0x8000000000008000), CONST64(0x8000008000008000), CONST64(0x8000000000008080), CONST64(0x8000008000008080), + CONST64(0x8000800000008000), CONST64(0x8000808000008000), CONST64(0x8000800000008080), CONST64(0x8000808000008080), + CONST64(0x8080000000000000), CONST64(0x8080008000000000), CONST64(0x8080000000000080), CONST64(0x8080008000000080), + CONST64(0x8080800000000000), CONST64(0x8080808000000000), CONST64(0x8080800000000080), CONST64(0x8080808000000080), + CONST64(0x8080000000008000), CONST64(0x8080008000008000), CONST64(0x8080000000008080), CONST64(0x8080008000008080), + CONST64(0x8080800000008000), CONST64(0x8080808000008000), CONST64(0x8080800000008080), CONST64(0x8080808000008080), + CONST64(0x8000000000800000), CONST64(0x8000008000800000), CONST64(0x8000000000800080), CONST64(0x8000008000800080), + CONST64(0x8000800000800000), CONST64(0x8000808000800000), CONST64(0x8000800000800080), CONST64(0x8000808000800080), + CONST64(0x8000000000808000), CONST64(0x8000008000808000), CONST64(0x8000000000808080), CONST64(0x8000008000808080), + CONST64(0x8000800000808000), CONST64(0x8000808000808000), CONST64(0x8000800000808080), CONST64(0x8000808000808080), + CONST64(0x8080000000800000), CONST64(0x8080008000800000), CONST64(0x8080000000800080), CONST64(0x8080008000800080), + CONST64(0x8080800000800000), CONST64(0x8080808000800000), CONST64(0x8080800000800080), CONST64(0x8080808000800080), + CONST64(0x8080000000808000), CONST64(0x8080008000808000), CONST64(0x8080000000808080), CONST64(0x8080008000808080), + CONST64(0x8080800000808000), CONST64(0x8080808000808000), CONST64(0x8080800000808080), CONST64(0x8080808000808080), + CONST64(0x0000000080000000), CONST64(0x0000008080000000), CONST64(0x0000000080000080), CONST64(0x0000008080000080), + CONST64(0x0000800080000000), CONST64(0x0000808080000000), CONST64(0x0000800080000080), CONST64(0x0000808080000080), + CONST64(0x0000000080008000), CONST64(0x0000008080008000), CONST64(0x0000000080008080), CONST64(0x0000008080008080), + CONST64(0x0000800080008000), CONST64(0x0000808080008000), CONST64(0x0000800080008080), CONST64(0x0000808080008080), + CONST64(0x0080000080000000), CONST64(0x0080008080000000), CONST64(0x0080000080000080), CONST64(0x0080008080000080), + CONST64(0x0080800080000000), CONST64(0x0080808080000000), CONST64(0x0080800080000080), CONST64(0x0080808080000080), + CONST64(0x0080000080008000), CONST64(0x0080008080008000), CONST64(0x0080000080008080), CONST64(0x0080008080008080), + CONST64(0x0080800080008000), CONST64(0x0080808080008000), CONST64(0x0080800080008080), CONST64(0x0080808080008080), + CONST64(0x0000000080800000), CONST64(0x0000008080800000), CONST64(0x0000000080800080), CONST64(0x0000008080800080), + CONST64(0x0000800080800000), CONST64(0x0000808080800000), CONST64(0x0000800080800080), CONST64(0x0000808080800080), + CONST64(0x0000000080808000), CONST64(0x0000008080808000), CONST64(0x0000000080808080), CONST64(0x0000008080808080), + CONST64(0x0000800080808000), CONST64(0x0000808080808000), CONST64(0x0000800080808080), CONST64(0x0000808080808080), + CONST64(0x0080000080800000), CONST64(0x0080008080800000), CONST64(0x0080000080800080), CONST64(0x0080008080800080), + CONST64(0x0080800080800000), CONST64(0x0080808080800000), CONST64(0x0080800080800080), CONST64(0x0080808080800080), + CONST64(0x0080000080808000), CONST64(0x0080008080808000), CONST64(0x0080000080808080), CONST64(0x0080008080808080), + CONST64(0x0080800080808000), CONST64(0x0080808080808000), CONST64(0x0080800080808080), CONST64(0x0080808080808080), + CONST64(0x8000000080000000), CONST64(0x8000008080000000), CONST64(0x8000000080000080), CONST64(0x8000008080000080), + CONST64(0x8000800080000000), CONST64(0x8000808080000000), CONST64(0x8000800080000080), CONST64(0x8000808080000080), + CONST64(0x8000000080008000), CONST64(0x8000008080008000), CONST64(0x8000000080008080), CONST64(0x8000008080008080), + CONST64(0x8000800080008000), CONST64(0x8000808080008000), CONST64(0x8000800080008080), CONST64(0x8000808080008080), + CONST64(0x8080000080000000), CONST64(0x8080008080000000), CONST64(0x8080000080000080), CONST64(0x8080008080000080), + CONST64(0x8080800080000000), CONST64(0x8080808080000000), CONST64(0x8080800080000080), CONST64(0x8080808080000080), + CONST64(0x8080000080008000), CONST64(0x8080008080008000), CONST64(0x8080000080008080), CONST64(0x8080008080008080), + CONST64(0x8080800080008000), CONST64(0x8080808080008000), CONST64(0x8080800080008080), CONST64(0x8080808080008080), + CONST64(0x8000000080800000), CONST64(0x8000008080800000), CONST64(0x8000000080800080), CONST64(0x8000008080800080), + CONST64(0x8000800080800000), CONST64(0x8000808080800000), CONST64(0x8000800080800080), CONST64(0x8000808080800080), + CONST64(0x8000000080808000), CONST64(0x8000008080808000), CONST64(0x8000000080808080), CONST64(0x8000008080808080), + CONST64(0x8000800080808000), CONST64(0x8000808080808000), CONST64(0x8000800080808080), CONST64(0x8000808080808080), + CONST64(0x8080000080800000), CONST64(0x8080008080800000), CONST64(0x8080000080800080), CONST64(0x8080008080800080), + CONST64(0x8080800080800000), CONST64(0x8080808080800000), CONST64(0x8080800080800080), CONST64(0x8080808080800080), + CONST64(0x8080000080808000), CONST64(0x8080008080808000), CONST64(0x8080000080808080), CONST64(0x8080008080808080), + CONST64(0x8080800080808000), CONST64(0x8080808080808000), CONST64(0x8080800080808080), CONST64(0x8080808080808080) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000004000000000), CONST64(0x0000000000000040), CONST64(0x0000004000000040), + CONST64(0x0000400000000000), CONST64(0x0000404000000000), CONST64(0x0000400000000040), CONST64(0x0000404000000040), + CONST64(0x0000000000004000), CONST64(0x0000004000004000), CONST64(0x0000000000004040), CONST64(0x0000004000004040), + CONST64(0x0000400000004000), CONST64(0x0000404000004000), CONST64(0x0000400000004040), CONST64(0x0000404000004040), + CONST64(0x0040000000000000), CONST64(0x0040004000000000), CONST64(0x0040000000000040), CONST64(0x0040004000000040), + CONST64(0x0040400000000000), CONST64(0x0040404000000000), CONST64(0x0040400000000040), CONST64(0x0040404000000040), + CONST64(0x0040000000004000), CONST64(0x0040004000004000), CONST64(0x0040000000004040), CONST64(0x0040004000004040), + CONST64(0x0040400000004000), CONST64(0x0040404000004000), CONST64(0x0040400000004040), CONST64(0x0040404000004040), + CONST64(0x0000000000400000), CONST64(0x0000004000400000), CONST64(0x0000000000400040), CONST64(0x0000004000400040), + CONST64(0x0000400000400000), CONST64(0x0000404000400000), CONST64(0x0000400000400040), CONST64(0x0000404000400040), + CONST64(0x0000000000404000), CONST64(0x0000004000404000), CONST64(0x0000000000404040), CONST64(0x0000004000404040), + CONST64(0x0000400000404000), CONST64(0x0000404000404000), CONST64(0x0000400000404040), CONST64(0x0000404000404040), + CONST64(0x0040000000400000), CONST64(0x0040004000400000), CONST64(0x0040000000400040), CONST64(0x0040004000400040), + CONST64(0x0040400000400000), CONST64(0x0040404000400000), CONST64(0x0040400000400040), CONST64(0x0040404000400040), + CONST64(0x0040000000404000), CONST64(0x0040004000404000), CONST64(0x0040000000404040), CONST64(0x0040004000404040), + CONST64(0x0040400000404000), CONST64(0x0040404000404000), CONST64(0x0040400000404040), CONST64(0x0040404000404040), + CONST64(0x4000000000000000), CONST64(0x4000004000000000), CONST64(0x4000000000000040), CONST64(0x4000004000000040), + CONST64(0x4000400000000000), CONST64(0x4000404000000000), CONST64(0x4000400000000040), CONST64(0x4000404000000040), + CONST64(0x4000000000004000), CONST64(0x4000004000004000), CONST64(0x4000000000004040), CONST64(0x4000004000004040), + CONST64(0x4000400000004000), CONST64(0x4000404000004000), CONST64(0x4000400000004040), CONST64(0x4000404000004040), + CONST64(0x4040000000000000), CONST64(0x4040004000000000), CONST64(0x4040000000000040), CONST64(0x4040004000000040), + CONST64(0x4040400000000000), CONST64(0x4040404000000000), CONST64(0x4040400000000040), CONST64(0x4040404000000040), + CONST64(0x4040000000004000), CONST64(0x4040004000004000), CONST64(0x4040000000004040), CONST64(0x4040004000004040), + CONST64(0x4040400000004000), CONST64(0x4040404000004000), CONST64(0x4040400000004040), CONST64(0x4040404000004040), + CONST64(0x4000000000400000), CONST64(0x4000004000400000), CONST64(0x4000000000400040), CONST64(0x4000004000400040), + CONST64(0x4000400000400000), CONST64(0x4000404000400000), CONST64(0x4000400000400040), CONST64(0x4000404000400040), + CONST64(0x4000000000404000), CONST64(0x4000004000404000), CONST64(0x4000000000404040), CONST64(0x4000004000404040), + CONST64(0x4000400000404000), CONST64(0x4000404000404000), CONST64(0x4000400000404040), CONST64(0x4000404000404040), + CONST64(0x4040000000400000), CONST64(0x4040004000400000), CONST64(0x4040000000400040), CONST64(0x4040004000400040), + CONST64(0x4040400000400000), CONST64(0x4040404000400000), CONST64(0x4040400000400040), CONST64(0x4040404000400040), + CONST64(0x4040000000404000), CONST64(0x4040004000404000), CONST64(0x4040000000404040), CONST64(0x4040004000404040), + CONST64(0x4040400000404000), CONST64(0x4040404000404000), CONST64(0x4040400000404040), CONST64(0x4040404000404040), + CONST64(0x0000000040000000), CONST64(0x0000004040000000), CONST64(0x0000000040000040), CONST64(0x0000004040000040), + CONST64(0x0000400040000000), CONST64(0x0000404040000000), CONST64(0x0000400040000040), CONST64(0x0000404040000040), + CONST64(0x0000000040004000), CONST64(0x0000004040004000), CONST64(0x0000000040004040), CONST64(0x0000004040004040), + CONST64(0x0000400040004000), CONST64(0x0000404040004000), CONST64(0x0000400040004040), CONST64(0x0000404040004040), + CONST64(0x0040000040000000), CONST64(0x0040004040000000), CONST64(0x0040000040000040), CONST64(0x0040004040000040), + CONST64(0x0040400040000000), CONST64(0x0040404040000000), CONST64(0x0040400040000040), CONST64(0x0040404040000040), + CONST64(0x0040000040004000), CONST64(0x0040004040004000), CONST64(0x0040000040004040), CONST64(0x0040004040004040), + CONST64(0x0040400040004000), CONST64(0x0040404040004000), CONST64(0x0040400040004040), CONST64(0x0040404040004040), + CONST64(0x0000000040400000), CONST64(0x0000004040400000), CONST64(0x0000000040400040), CONST64(0x0000004040400040), + CONST64(0x0000400040400000), CONST64(0x0000404040400000), CONST64(0x0000400040400040), CONST64(0x0000404040400040), + CONST64(0x0000000040404000), CONST64(0x0000004040404000), CONST64(0x0000000040404040), CONST64(0x0000004040404040), + CONST64(0x0000400040404000), CONST64(0x0000404040404000), CONST64(0x0000400040404040), CONST64(0x0000404040404040), + CONST64(0x0040000040400000), CONST64(0x0040004040400000), CONST64(0x0040000040400040), CONST64(0x0040004040400040), + CONST64(0x0040400040400000), CONST64(0x0040404040400000), CONST64(0x0040400040400040), CONST64(0x0040404040400040), + CONST64(0x0040000040404000), CONST64(0x0040004040404000), CONST64(0x0040000040404040), CONST64(0x0040004040404040), + CONST64(0x0040400040404000), CONST64(0x0040404040404000), CONST64(0x0040400040404040), CONST64(0x0040404040404040), + CONST64(0x4000000040000000), CONST64(0x4000004040000000), CONST64(0x4000000040000040), CONST64(0x4000004040000040), + CONST64(0x4000400040000000), CONST64(0x4000404040000000), CONST64(0x4000400040000040), CONST64(0x4000404040000040), + CONST64(0x4000000040004000), CONST64(0x4000004040004000), CONST64(0x4000000040004040), CONST64(0x4000004040004040), + CONST64(0x4000400040004000), CONST64(0x4000404040004000), CONST64(0x4000400040004040), CONST64(0x4000404040004040), + CONST64(0x4040000040000000), CONST64(0x4040004040000000), CONST64(0x4040000040000040), CONST64(0x4040004040000040), + CONST64(0x4040400040000000), CONST64(0x4040404040000000), CONST64(0x4040400040000040), CONST64(0x4040404040000040), + CONST64(0x4040000040004000), CONST64(0x4040004040004000), CONST64(0x4040000040004040), CONST64(0x4040004040004040), + CONST64(0x4040400040004000), CONST64(0x4040404040004000), CONST64(0x4040400040004040), CONST64(0x4040404040004040), + CONST64(0x4000000040400000), CONST64(0x4000004040400000), CONST64(0x4000000040400040), CONST64(0x4000004040400040), + CONST64(0x4000400040400000), CONST64(0x4000404040400000), CONST64(0x4000400040400040), CONST64(0x4000404040400040), + CONST64(0x4000000040404000), CONST64(0x4000004040404000), CONST64(0x4000000040404040), CONST64(0x4000004040404040), + CONST64(0x4000400040404000), CONST64(0x4000404040404000), CONST64(0x4000400040404040), CONST64(0x4000404040404040), + CONST64(0x4040000040400000), CONST64(0x4040004040400000), CONST64(0x4040000040400040), CONST64(0x4040004040400040), + CONST64(0x4040400040400000), CONST64(0x4040404040400000), CONST64(0x4040400040400040), CONST64(0x4040404040400040), + CONST64(0x4040000040404000), CONST64(0x4040004040404000), CONST64(0x4040000040404040), CONST64(0x4040004040404040), + CONST64(0x4040400040404000), CONST64(0x4040404040404000), CONST64(0x4040400040404040), CONST64(0x4040404040404040) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000002000000000), CONST64(0x0000000000000020), CONST64(0x0000002000000020), + CONST64(0x0000200000000000), CONST64(0x0000202000000000), CONST64(0x0000200000000020), CONST64(0x0000202000000020), + CONST64(0x0000000000002000), CONST64(0x0000002000002000), CONST64(0x0000000000002020), CONST64(0x0000002000002020), + CONST64(0x0000200000002000), CONST64(0x0000202000002000), CONST64(0x0000200000002020), CONST64(0x0000202000002020), + CONST64(0x0020000000000000), CONST64(0x0020002000000000), CONST64(0x0020000000000020), CONST64(0x0020002000000020), + CONST64(0x0020200000000000), CONST64(0x0020202000000000), CONST64(0x0020200000000020), CONST64(0x0020202000000020), + CONST64(0x0020000000002000), CONST64(0x0020002000002000), CONST64(0x0020000000002020), CONST64(0x0020002000002020), + CONST64(0x0020200000002000), CONST64(0x0020202000002000), CONST64(0x0020200000002020), CONST64(0x0020202000002020), + CONST64(0x0000000000200000), CONST64(0x0000002000200000), CONST64(0x0000000000200020), CONST64(0x0000002000200020), + CONST64(0x0000200000200000), CONST64(0x0000202000200000), CONST64(0x0000200000200020), CONST64(0x0000202000200020), + CONST64(0x0000000000202000), CONST64(0x0000002000202000), CONST64(0x0000000000202020), CONST64(0x0000002000202020), + CONST64(0x0000200000202000), CONST64(0x0000202000202000), CONST64(0x0000200000202020), CONST64(0x0000202000202020), + CONST64(0x0020000000200000), CONST64(0x0020002000200000), CONST64(0x0020000000200020), CONST64(0x0020002000200020), + CONST64(0x0020200000200000), CONST64(0x0020202000200000), CONST64(0x0020200000200020), CONST64(0x0020202000200020), + CONST64(0x0020000000202000), CONST64(0x0020002000202000), CONST64(0x0020000000202020), CONST64(0x0020002000202020), + CONST64(0x0020200000202000), CONST64(0x0020202000202000), CONST64(0x0020200000202020), CONST64(0x0020202000202020), + CONST64(0x2000000000000000), CONST64(0x2000002000000000), CONST64(0x2000000000000020), CONST64(0x2000002000000020), + CONST64(0x2000200000000000), CONST64(0x2000202000000000), CONST64(0x2000200000000020), CONST64(0x2000202000000020), + CONST64(0x2000000000002000), CONST64(0x2000002000002000), CONST64(0x2000000000002020), CONST64(0x2000002000002020), + CONST64(0x2000200000002000), CONST64(0x2000202000002000), CONST64(0x2000200000002020), CONST64(0x2000202000002020), + CONST64(0x2020000000000000), CONST64(0x2020002000000000), CONST64(0x2020000000000020), CONST64(0x2020002000000020), + CONST64(0x2020200000000000), CONST64(0x2020202000000000), CONST64(0x2020200000000020), CONST64(0x2020202000000020), + CONST64(0x2020000000002000), CONST64(0x2020002000002000), CONST64(0x2020000000002020), CONST64(0x2020002000002020), + CONST64(0x2020200000002000), CONST64(0x2020202000002000), CONST64(0x2020200000002020), CONST64(0x2020202000002020), + CONST64(0x2000000000200000), CONST64(0x2000002000200000), CONST64(0x2000000000200020), CONST64(0x2000002000200020), + CONST64(0x2000200000200000), CONST64(0x2000202000200000), CONST64(0x2000200000200020), CONST64(0x2000202000200020), + CONST64(0x2000000000202000), CONST64(0x2000002000202000), CONST64(0x2000000000202020), CONST64(0x2000002000202020), + CONST64(0x2000200000202000), CONST64(0x2000202000202000), CONST64(0x2000200000202020), CONST64(0x2000202000202020), + CONST64(0x2020000000200000), CONST64(0x2020002000200000), CONST64(0x2020000000200020), CONST64(0x2020002000200020), + CONST64(0x2020200000200000), CONST64(0x2020202000200000), CONST64(0x2020200000200020), CONST64(0x2020202000200020), + CONST64(0x2020000000202000), CONST64(0x2020002000202000), CONST64(0x2020000000202020), CONST64(0x2020002000202020), + CONST64(0x2020200000202000), CONST64(0x2020202000202000), CONST64(0x2020200000202020), CONST64(0x2020202000202020), + CONST64(0x0000000020000000), CONST64(0x0000002020000000), CONST64(0x0000000020000020), CONST64(0x0000002020000020), + CONST64(0x0000200020000000), CONST64(0x0000202020000000), CONST64(0x0000200020000020), CONST64(0x0000202020000020), + CONST64(0x0000000020002000), CONST64(0x0000002020002000), CONST64(0x0000000020002020), CONST64(0x0000002020002020), + CONST64(0x0000200020002000), CONST64(0x0000202020002000), CONST64(0x0000200020002020), CONST64(0x0000202020002020), + CONST64(0x0020000020000000), CONST64(0x0020002020000000), CONST64(0x0020000020000020), CONST64(0x0020002020000020), + CONST64(0x0020200020000000), CONST64(0x0020202020000000), CONST64(0x0020200020000020), CONST64(0x0020202020000020), + CONST64(0x0020000020002000), CONST64(0x0020002020002000), CONST64(0x0020000020002020), CONST64(0x0020002020002020), + CONST64(0x0020200020002000), CONST64(0x0020202020002000), CONST64(0x0020200020002020), CONST64(0x0020202020002020), + CONST64(0x0000000020200000), CONST64(0x0000002020200000), CONST64(0x0000000020200020), CONST64(0x0000002020200020), + CONST64(0x0000200020200000), CONST64(0x0000202020200000), CONST64(0x0000200020200020), CONST64(0x0000202020200020), + CONST64(0x0000000020202000), CONST64(0x0000002020202000), CONST64(0x0000000020202020), CONST64(0x0000002020202020), + CONST64(0x0000200020202000), CONST64(0x0000202020202000), CONST64(0x0000200020202020), CONST64(0x0000202020202020), + CONST64(0x0020000020200000), CONST64(0x0020002020200000), CONST64(0x0020000020200020), CONST64(0x0020002020200020), + CONST64(0x0020200020200000), CONST64(0x0020202020200000), CONST64(0x0020200020200020), CONST64(0x0020202020200020), + CONST64(0x0020000020202000), CONST64(0x0020002020202000), CONST64(0x0020000020202020), CONST64(0x0020002020202020), + CONST64(0x0020200020202000), CONST64(0x0020202020202000), CONST64(0x0020200020202020), CONST64(0x0020202020202020), + CONST64(0x2000000020000000), CONST64(0x2000002020000000), CONST64(0x2000000020000020), CONST64(0x2000002020000020), + CONST64(0x2000200020000000), CONST64(0x2000202020000000), CONST64(0x2000200020000020), CONST64(0x2000202020000020), + CONST64(0x2000000020002000), CONST64(0x2000002020002000), CONST64(0x2000000020002020), CONST64(0x2000002020002020), + CONST64(0x2000200020002000), CONST64(0x2000202020002000), CONST64(0x2000200020002020), CONST64(0x2000202020002020), + CONST64(0x2020000020000000), CONST64(0x2020002020000000), CONST64(0x2020000020000020), CONST64(0x2020002020000020), + CONST64(0x2020200020000000), CONST64(0x2020202020000000), CONST64(0x2020200020000020), CONST64(0x2020202020000020), + CONST64(0x2020000020002000), CONST64(0x2020002020002000), CONST64(0x2020000020002020), CONST64(0x2020002020002020), + CONST64(0x2020200020002000), CONST64(0x2020202020002000), CONST64(0x2020200020002020), CONST64(0x2020202020002020), + CONST64(0x2000000020200000), CONST64(0x2000002020200000), CONST64(0x2000000020200020), CONST64(0x2000002020200020), + CONST64(0x2000200020200000), CONST64(0x2000202020200000), CONST64(0x2000200020200020), CONST64(0x2000202020200020), + CONST64(0x2000000020202000), CONST64(0x2000002020202000), CONST64(0x2000000020202020), CONST64(0x2000002020202020), + CONST64(0x2000200020202000), CONST64(0x2000202020202000), CONST64(0x2000200020202020), CONST64(0x2000202020202020), + CONST64(0x2020000020200000), CONST64(0x2020002020200000), CONST64(0x2020000020200020), CONST64(0x2020002020200020), + CONST64(0x2020200020200000), CONST64(0x2020202020200000), CONST64(0x2020200020200020), CONST64(0x2020202020200020), + CONST64(0x2020000020202000), CONST64(0x2020002020202000), CONST64(0x2020000020202020), CONST64(0x2020002020202020), + CONST64(0x2020200020202000), CONST64(0x2020202020202000), CONST64(0x2020200020202020), CONST64(0x2020202020202020) + }}; + +static const uint64 des_fp[8][256] = { + +{ CONST64(0x0000000000000000), CONST64(0x0000008000000000), CONST64(0x0000000002000000), CONST64(0x0000008002000000), + CONST64(0x0000000000020000), CONST64(0x0000008000020000), CONST64(0x0000000002020000), CONST64(0x0000008002020000), + CONST64(0x0000000000000200), CONST64(0x0000008000000200), CONST64(0x0000000002000200), CONST64(0x0000008002000200), + CONST64(0x0000000000020200), CONST64(0x0000008000020200), CONST64(0x0000000002020200), CONST64(0x0000008002020200), + CONST64(0x0000000000000002), CONST64(0x0000008000000002), CONST64(0x0000000002000002), CONST64(0x0000008002000002), + CONST64(0x0000000000020002), CONST64(0x0000008000020002), CONST64(0x0000000002020002), CONST64(0x0000008002020002), + CONST64(0x0000000000000202), CONST64(0x0000008000000202), CONST64(0x0000000002000202), CONST64(0x0000008002000202), + CONST64(0x0000000000020202), CONST64(0x0000008000020202), CONST64(0x0000000002020202), CONST64(0x0000008002020202), + CONST64(0x0200000000000000), CONST64(0x0200008000000000), CONST64(0x0200000002000000), CONST64(0x0200008002000000), + CONST64(0x0200000000020000), CONST64(0x0200008000020000), CONST64(0x0200000002020000), CONST64(0x0200008002020000), + CONST64(0x0200000000000200), CONST64(0x0200008000000200), CONST64(0x0200000002000200), CONST64(0x0200008002000200), + CONST64(0x0200000000020200), CONST64(0x0200008000020200), CONST64(0x0200000002020200), CONST64(0x0200008002020200), + CONST64(0x0200000000000002), CONST64(0x0200008000000002), CONST64(0x0200000002000002), CONST64(0x0200008002000002), + CONST64(0x0200000000020002), CONST64(0x0200008000020002), CONST64(0x0200000002020002), CONST64(0x0200008002020002), + CONST64(0x0200000000000202), CONST64(0x0200008000000202), CONST64(0x0200000002000202), CONST64(0x0200008002000202), + CONST64(0x0200000000020202), CONST64(0x0200008000020202), CONST64(0x0200000002020202), CONST64(0x0200008002020202), + CONST64(0x0002000000000000), CONST64(0x0002008000000000), CONST64(0x0002000002000000), CONST64(0x0002008002000000), + CONST64(0x0002000000020000), CONST64(0x0002008000020000), CONST64(0x0002000002020000), CONST64(0x0002008002020000), + CONST64(0x0002000000000200), CONST64(0x0002008000000200), CONST64(0x0002000002000200), CONST64(0x0002008002000200), + CONST64(0x0002000000020200), CONST64(0x0002008000020200), CONST64(0x0002000002020200), CONST64(0x0002008002020200), + CONST64(0x0002000000000002), CONST64(0x0002008000000002), CONST64(0x0002000002000002), CONST64(0x0002008002000002), + CONST64(0x0002000000020002), CONST64(0x0002008000020002), CONST64(0x0002000002020002), CONST64(0x0002008002020002), + CONST64(0x0002000000000202), CONST64(0x0002008000000202), CONST64(0x0002000002000202), CONST64(0x0002008002000202), + CONST64(0x0002000000020202), CONST64(0x0002008000020202), CONST64(0x0002000002020202), CONST64(0x0002008002020202), + CONST64(0x0202000000000000), CONST64(0x0202008000000000), CONST64(0x0202000002000000), CONST64(0x0202008002000000), + CONST64(0x0202000000020000), CONST64(0x0202008000020000), CONST64(0x0202000002020000), CONST64(0x0202008002020000), + CONST64(0x0202000000000200), CONST64(0x0202008000000200), CONST64(0x0202000002000200), CONST64(0x0202008002000200), + CONST64(0x0202000000020200), CONST64(0x0202008000020200), CONST64(0x0202000002020200), CONST64(0x0202008002020200), + CONST64(0x0202000000000002), CONST64(0x0202008000000002), CONST64(0x0202000002000002), CONST64(0x0202008002000002), + CONST64(0x0202000000020002), CONST64(0x0202008000020002), CONST64(0x0202000002020002), CONST64(0x0202008002020002), + CONST64(0x0202000000000202), CONST64(0x0202008000000202), CONST64(0x0202000002000202), CONST64(0x0202008002000202), + CONST64(0x0202000000020202), CONST64(0x0202008000020202), CONST64(0x0202000002020202), CONST64(0x0202008002020202), + CONST64(0x0000020000000000), CONST64(0x0000028000000000), CONST64(0x0000020002000000), CONST64(0x0000028002000000), + CONST64(0x0000020000020000), CONST64(0x0000028000020000), CONST64(0x0000020002020000), CONST64(0x0000028002020000), + CONST64(0x0000020000000200), CONST64(0x0000028000000200), CONST64(0x0000020002000200), CONST64(0x0000028002000200), + CONST64(0x0000020000020200), CONST64(0x0000028000020200), CONST64(0x0000020002020200), CONST64(0x0000028002020200), + CONST64(0x0000020000000002), CONST64(0x0000028000000002), CONST64(0x0000020002000002), CONST64(0x0000028002000002), + CONST64(0x0000020000020002), CONST64(0x0000028000020002), CONST64(0x0000020002020002), CONST64(0x0000028002020002), + CONST64(0x0000020000000202), CONST64(0x0000028000000202), CONST64(0x0000020002000202), CONST64(0x0000028002000202), + CONST64(0x0000020000020202), CONST64(0x0000028000020202), CONST64(0x0000020002020202), CONST64(0x0000028002020202), + CONST64(0x0200020000000000), CONST64(0x0200028000000000), CONST64(0x0200020002000000), CONST64(0x0200028002000000), + CONST64(0x0200020000020000), CONST64(0x0200028000020000), CONST64(0x0200020002020000), CONST64(0x0200028002020000), + CONST64(0x0200020000000200), CONST64(0x0200028000000200), CONST64(0x0200020002000200), CONST64(0x0200028002000200), + CONST64(0x0200020000020200), CONST64(0x0200028000020200), CONST64(0x0200020002020200), CONST64(0x0200028002020200), + CONST64(0x0200020000000002), CONST64(0x0200028000000002), CONST64(0x0200020002000002), CONST64(0x0200028002000002), + CONST64(0x0200020000020002), CONST64(0x0200028000020002), CONST64(0x0200020002020002), CONST64(0x0200028002020002), + CONST64(0x0200020000000202), CONST64(0x0200028000000202), CONST64(0x0200020002000202), CONST64(0x0200028002000202), + CONST64(0x0200020000020202), CONST64(0x0200028000020202), CONST64(0x0200020002020202), CONST64(0x0200028002020202), + CONST64(0x0002020000000000), CONST64(0x0002028000000000), CONST64(0x0002020002000000), CONST64(0x0002028002000000), + CONST64(0x0002020000020000), CONST64(0x0002028000020000), CONST64(0x0002020002020000), CONST64(0x0002028002020000), + CONST64(0x0002020000000200), CONST64(0x0002028000000200), CONST64(0x0002020002000200), CONST64(0x0002028002000200), + CONST64(0x0002020000020200), CONST64(0x0002028000020200), CONST64(0x0002020002020200), CONST64(0x0002028002020200), + CONST64(0x0002020000000002), CONST64(0x0002028000000002), CONST64(0x0002020002000002), CONST64(0x0002028002000002), + CONST64(0x0002020000020002), CONST64(0x0002028000020002), CONST64(0x0002020002020002), CONST64(0x0002028002020002), + CONST64(0x0002020000000202), CONST64(0x0002028000000202), CONST64(0x0002020002000202), CONST64(0x0002028002000202), + CONST64(0x0002020000020202), CONST64(0x0002028000020202), CONST64(0x0002020002020202), CONST64(0x0002028002020202), + CONST64(0x0202020000000000), CONST64(0x0202028000000000), CONST64(0x0202020002000000), CONST64(0x0202028002000000), + CONST64(0x0202020000020000), CONST64(0x0202028000020000), CONST64(0x0202020002020000), CONST64(0x0202028002020000), + CONST64(0x0202020000000200), CONST64(0x0202028000000200), CONST64(0x0202020002000200), CONST64(0x0202028002000200), + CONST64(0x0202020000020200), CONST64(0x0202028000020200), CONST64(0x0202020002020200), CONST64(0x0202028002020200), + CONST64(0x0202020000000002), CONST64(0x0202028000000002), CONST64(0x0202020002000002), CONST64(0x0202028002000002), + CONST64(0x0202020000020002), CONST64(0x0202028000020002), CONST64(0x0202020002020002), CONST64(0x0202028002020002), + CONST64(0x0202020000000202), CONST64(0x0202028000000202), CONST64(0x0202020002000202), CONST64(0x0202028002000202), + CONST64(0x0202020000020202), CONST64(0x0202028000020202), CONST64(0x0202020002020202), CONST64(0x0202028002020202) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000200000000), CONST64(0x0000000008000000), CONST64(0x0000000208000000), + CONST64(0x0000000000080000), CONST64(0x0000000200080000), CONST64(0x0000000008080000), CONST64(0x0000000208080000), + CONST64(0x0000000000000800), CONST64(0x0000000200000800), CONST64(0x0000000008000800), CONST64(0x0000000208000800), + CONST64(0x0000000000080800), CONST64(0x0000000200080800), CONST64(0x0000000008080800), CONST64(0x0000000208080800), + CONST64(0x0000000000000008), CONST64(0x0000000200000008), CONST64(0x0000000008000008), CONST64(0x0000000208000008), + CONST64(0x0000000000080008), CONST64(0x0000000200080008), CONST64(0x0000000008080008), CONST64(0x0000000208080008), + CONST64(0x0000000000000808), CONST64(0x0000000200000808), CONST64(0x0000000008000808), CONST64(0x0000000208000808), + CONST64(0x0000000000080808), CONST64(0x0000000200080808), CONST64(0x0000000008080808), CONST64(0x0000000208080808), + CONST64(0x0800000000000000), CONST64(0x0800000200000000), CONST64(0x0800000008000000), CONST64(0x0800000208000000), + CONST64(0x0800000000080000), CONST64(0x0800000200080000), CONST64(0x0800000008080000), CONST64(0x0800000208080000), + CONST64(0x0800000000000800), CONST64(0x0800000200000800), CONST64(0x0800000008000800), CONST64(0x0800000208000800), + CONST64(0x0800000000080800), CONST64(0x0800000200080800), CONST64(0x0800000008080800), CONST64(0x0800000208080800), + CONST64(0x0800000000000008), CONST64(0x0800000200000008), CONST64(0x0800000008000008), CONST64(0x0800000208000008), + CONST64(0x0800000000080008), CONST64(0x0800000200080008), CONST64(0x0800000008080008), CONST64(0x0800000208080008), + CONST64(0x0800000000000808), CONST64(0x0800000200000808), CONST64(0x0800000008000808), CONST64(0x0800000208000808), + CONST64(0x0800000000080808), CONST64(0x0800000200080808), CONST64(0x0800000008080808), CONST64(0x0800000208080808), + CONST64(0x0008000000000000), CONST64(0x0008000200000000), CONST64(0x0008000008000000), CONST64(0x0008000208000000), + CONST64(0x0008000000080000), CONST64(0x0008000200080000), CONST64(0x0008000008080000), CONST64(0x0008000208080000), + CONST64(0x0008000000000800), CONST64(0x0008000200000800), CONST64(0x0008000008000800), CONST64(0x0008000208000800), + CONST64(0x0008000000080800), CONST64(0x0008000200080800), CONST64(0x0008000008080800), CONST64(0x0008000208080800), + CONST64(0x0008000000000008), CONST64(0x0008000200000008), CONST64(0x0008000008000008), CONST64(0x0008000208000008), + CONST64(0x0008000000080008), CONST64(0x0008000200080008), CONST64(0x0008000008080008), CONST64(0x0008000208080008), + CONST64(0x0008000000000808), CONST64(0x0008000200000808), CONST64(0x0008000008000808), CONST64(0x0008000208000808), + CONST64(0x0008000000080808), CONST64(0x0008000200080808), CONST64(0x0008000008080808), CONST64(0x0008000208080808), + CONST64(0x0808000000000000), CONST64(0x0808000200000000), CONST64(0x0808000008000000), CONST64(0x0808000208000000), + CONST64(0x0808000000080000), CONST64(0x0808000200080000), CONST64(0x0808000008080000), CONST64(0x0808000208080000), + CONST64(0x0808000000000800), CONST64(0x0808000200000800), CONST64(0x0808000008000800), CONST64(0x0808000208000800), + CONST64(0x0808000000080800), CONST64(0x0808000200080800), CONST64(0x0808000008080800), CONST64(0x0808000208080800), + CONST64(0x0808000000000008), CONST64(0x0808000200000008), CONST64(0x0808000008000008), CONST64(0x0808000208000008), + CONST64(0x0808000000080008), CONST64(0x0808000200080008), CONST64(0x0808000008080008), CONST64(0x0808000208080008), + CONST64(0x0808000000000808), CONST64(0x0808000200000808), CONST64(0x0808000008000808), CONST64(0x0808000208000808), + CONST64(0x0808000000080808), CONST64(0x0808000200080808), CONST64(0x0808000008080808), CONST64(0x0808000208080808), + CONST64(0x0000080000000000), CONST64(0x0000080200000000), CONST64(0x0000080008000000), CONST64(0x0000080208000000), + CONST64(0x0000080000080000), CONST64(0x0000080200080000), CONST64(0x0000080008080000), CONST64(0x0000080208080000), + CONST64(0x0000080000000800), CONST64(0x0000080200000800), CONST64(0x0000080008000800), CONST64(0x0000080208000800), + CONST64(0x0000080000080800), CONST64(0x0000080200080800), CONST64(0x0000080008080800), CONST64(0x0000080208080800), + CONST64(0x0000080000000008), CONST64(0x0000080200000008), CONST64(0x0000080008000008), CONST64(0x0000080208000008), + CONST64(0x0000080000080008), CONST64(0x0000080200080008), CONST64(0x0000080008080008), CONST64(0x0000080208080008), + CONST64(0x0000080000000808), CONST64(0x0000080200000808), CONST64(0x0000080008000808), CONST64(0x0000080208000808), + CONST64(0x0000080000080808), CONST64(0x0000080200080808), CONST64(0x0000080008080808), CONST64(0x0000080208080808), + CONST64(0x0800080000000000), CONST64(0x0800080200000000), CONST64(0x0800080008000000), CONST64(0x0800080208000000), + CONST64(0x0800080000080000), CONST64(0x0800080200080000), CONST64(0x0800080008080000), CONST64(0x0800080208080000), + CONST64(0x0800080000000800), CONST64(0x0800080200000800), CONST64(0x0800080008000800), CONST64(0x0800080208000800), + CONST64(0x0800080000080800), CONST64(0x0800080200080800), CONST64(0x0800080008080800), CONST64(0x0800080208080800), + CONST64(0x0800080000000008), CONST64(0x0800080200000008), CONST64(0x0800080008000008), CONST64(0x0800080208000008), + CONST64(0x0800080000080008), CONST64(0x0800080200080008), CONST64(0x0800080008080008), CONST64(0x0800080208080008), + CONST64(0x0800080000000808), CONST64(0x0800080200000808), CONST64(0x0800080008000808), CONST64(0x0800080208000808), + CONST64(0x0800080000080808), CONST64(0x0800080200080808), CONST64(0x0800080008080808), CONST64(0x0800080208080808), + CONST64(0x0008080000000000), CONST64(0x0008080200000000), CONST64(0x0008080008000000), CONST64(0x0008080208000000), + CONST64(0x0008080000080000), CONST64(0x0008080200080000), CONST64(0x0008080008080000), CONST64(0x0008080208080000), + CONST64(0x0008080000000800), CONST64(0x0008080200000800), CONST64(0x0008080008000800), CONST64(0x0008080208000800), + CONST64(0x0008080000080800), CONST64(0x0008080200080800), CONST64(0x0008080008080800), CONST64(0x0008080208080800), + CONST64(0x0008080000000008), CONST64(0x0008080200000008), CONST64(0x0008080008000008), CONST64(0x0008080208000008), + CONST64(0x0008080000080008), CONST64(0x0008080200080008), CONST64(0x0008080008080008), CONST64(0x0008080208080008), + CONST64(0x0008080000000808), CONST64(0x0008080200000808), CONST64(0x0008080008000808), CONST64(0x0008080208000808), + CONST64(0x0008080000080808), CONST64(0x0008080200080808), CONST64(0x0008080008080808), CONST64(0x0008080208080808), + CONST64(0x0808080000000000), CONST64(0x0808080200000000), CONST64(0x0808080008000000), CONST64(0x0808080208000000), + CONST64(0x0808080000080000), CONST64(0x0808080200080000), CONST64(0x0808080008080000), CONST64(0x0808080208080000), + CONST64(0x0808080000000800), CONST64(0x0808080200000800), CONST64(0x0808080008000800), CONST64(0x0808080208000800), + CONST64(0x0808080000080800), CONST64(0x0808080200080800), CONST64(0x0808080008080800), CONST64(0x0808080208080800), + CONST64(0x0808080000000008), CONST64(0x0808080200000008), CONST64(0x0808080008000008), CONST64(0x0808080208000008), + CONST64(0x0808080000080008), CONST64(0x0808080200080008), CONST64(0x0808080008080008), CONST64(0x0808080208080008), + CONST64(0x0808080000000808), CONST64(0x0808080200000808), CONST64(0x0808080008000808), CONST64(0x0808080208000808), + CONST64(0x0808080000080808), CONST64(0x0808080200080808), CONST64(0x0808080008080808), CONST64(0x0808080208080808) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000800000000), CONST64(0x0000000020000000), CONST64(0x0000000820000000), + CONST64(0x0000000000200000), CONST64(0x0000000800200000), CONST64(0x0000000020200000), CONST64(0x0000000820200000), + CONST64(0x0000000000002000), CONST64(0x0000000800002000), CONST64(0x0000000020002000), CONST64(0x0000000820002000), + CONST64(0x0000000000202000), CONST64(0x0000000800202000), CONST64(0x0000000020202000), CONST64(0x0000000820202000), + CONST64(0x0000000000000020), CONST64(0x0000000800000020), CONST64(0x0000000020000020), CONST64(0x0000000820000020), + CONST64(0x0000000000200020), CONST64(0x0000000800200020), CONST64(0x0000000020200020), CONST64(0x0000000820200020), + CONST64(0x0000000000002020), CONST64(0x0000000800002020), CONST64(0x0000000020002020), CONST64(0x0000000820002020), + CONST64(0x0000000000202020), CONST64(0x0000000800202020), CONST64(0x0000000020202020), CONST64(0x0000000820202020), + CONST64(0x2000000000000000), CONST64(0x2000000800000000), CONST64(0x2000000020000000), CONST64(0x2000000820000000), + CONST64(0x2000000000200000), CONST64(0x2000000800200000), CONST64(0x2000000020200000), CONST64(0x2000000820200000), + CONST64(0x2000000000002000), CONST64(0x2000000800002000), CONST64(0x2000000020002000), CONST64(0x2000000820002000), + CONST64(0x2000000000202000), CONST64(0x2000000800202000), CONST64(0x2000000020202000), CONST64(0x2000000820202000), + CONST64(0x2000000000000020), CONST64(0x2000000800000020), CONST64(0x2000000020000020), CONST64(0x2000000820000020), + CONST64(0x2000000000200020), CONST64(0x2000000800200020), CONST64(0x2000000020200020), CONST64(0x2000000820200020), + CONST64(0x2000000000002020), CONST64(0x2000000800002020), CONST64(0x2000000020002020), CONST64(0x2000000820002020), + CONST64(0x2000000000202020), CONST64(0x2000000800202020), CONST64(0x2000000020202020), CONST64(0x2000000820202020), + CONST64(0x0020000000000000), CONST64(0x0020000800000000), CONST64(0x0020000020000000), CONST64(0x0020000820000000), + CONST64(0x0020000000200000), CONST64(0x0020000800200000), CONST64(0x0020000020200000), CONST64(0x0020000820200000), + CONST64(0x0020000000002000), CONST64(0x0020000800002000), CONST64(0x0020000020002000), CONST64(0x0020000820002000), + CONST64(0x0020000000202000), CONST64(0x0020000800202000), CONST64(0x0020000020202000), CONST64(0x0020000820202000), + CONST64(0x0020000000000020), CONST64(0x0020000800000020), CONST64(0x0020000020000020), CONST64(0x0020000820000020), + CONST64(0x0020000000200020), CONST64(0x0020000800200020), CONST64(0x0020000020200020), CONST64(0x0020000820200020), + CONST64(0x0020000000002020), CONST64(0x0020000800002020), CONST64(0x0020000020002020), CONST64(0x0020000820002020), + CONST64(0x0020000000202020), CONST64(0x0020000800202020), CONST64(0x0020000020202020), CONST64(0x0020000820202020), + CONST64(0x2020000000000000), CONST64(0x2020000800000000), CONST64(0x2020000020000000), CONST64(0x2020000820000000), + CONST64(0x2020000000200000), CONST64(0x2020000800200000), CONST64(0x2020000020200000), CONST64(0x2020000820200000), + CONST64(0x2020000000002000), CONST64(0x2020000800002000), CONST64(0x2020000020002000), CONST64(0x2020000820002000), + CONST64(0x2020000000202000), CONST64(0x2020000800202000), CONST64(0x2020000020202000), CONST64(0x2020000820202000), + CONST64(0x2020000000000020), CONST64(0x2020000800000020), CONST64(0x2020000020000020), CONST64(0x2020000820000020), + CONST64(0x2020000000200020), CONST64(0x2020000800200020), CONST64(0x2020000020200020), CONST64(0x2020000820200020), + CONST64(0x2020000000002020), CONST64(0x2020000800002020), CONST64(0x2020000020002020), CONST64(0x2020000820002020), + CONST64(0x2020000000202020), CONST64(0x2020000800202020), CONST64(0x2020000020202020), CONST64(0x2020000820202020), + CONST64(0x0000200000000000), CONST64(0x0000200800000000), CONST64(0x0000200020000000), CONST64(0x0000200820000000), + CONST64(0x0000200000200000), CONST64(0x0000200800200000), CONST64(0x0000200020200000), CONST64(0x0000200820200000), + CONST64(0x0000200000002000), CONST64(0x0000200800002000), CONST64(0x0000200020002000), CONST64(0x0000200820002000), + CONST64(0x0000200000202000), CONST64(0x0000200800202000), CONST64(0x0000200020202000), CONST64(0x0000200820202000), + CONST64(0x0000200000000020), CONST64(0x0000200800000020), CONST64(0x0000200020000020), CONST64(0x0000200820000020), + CONST64(0x0000200000200020), CONST64(0x0000200800200020), CONST64(0x0000200020200020), CONST64(0x0000200820200020), + CONST64(0x0000200000002020), CONST64(0x0000200800002020), CONST64(0x0000200020002020), CONST64(0x0000200820002020), + CONST64(0x0000200000202020), CONST64(0x0000200800202020), CONST64(0x0000200020202020), CONST64(0x0000200820202020), + CONST64(0x2000200000000000), CONST64(0x2000200800000000), CONST64(0x2000200020000000), CONST64(0x2000200820000000), + CONST64(0x2000200000200000), CONST64(0x2000200800200000), CONST64(0x2000200020200000), CONST64(0x2000200820200000), + CONST64(0x2000200000002000), CONST64(0x2000200800002000), CONST64(0x2000200020002000), CONST64(0x2000200820002000), + CONST64(0x2000200000202000), CONST64(0x2000200800202000), CONST64(0x2000200020202000), CONST64(0x2000200820202000), + CONST64(0x2000200000000020), CONST64(0x2000200800000020), CONST64(0x2000200020000020), CONST64(0x2000200820000020), + CONST64(0x2000200000200020), CONST64(0x2000200800200020), CONST64(0x2000200020200020), CONST64(0x2000200820200020), + CONST64(0x2000200000002020), CONST64(0x2000200800002020), CONST64(0x2000200020002020), CONST64(0x2000200820002020), + CONST64(0x2000200000202020), CONST64(0x2000200800202020), CONST64(0x2000200020202020), CONST64(0x2000200820202020), + CONST64(0x0020200000000000), CONST64(0x0020200800000000), CONST64(0x0020200020000000), CONST64(0x0020200820000000), + CONST64(0x0020200000200000), CONST64(0x0020200800200000), CONST64(0x0020200020200000), CONST64(0x0020200820200000), + CONST64(0x0020200000002000), CONST64(0x0020200800002000), CONST64(0x0020200020002000), CONST64(0x0020200820002000), + CONST64(0x0020200000202000), CONST64(0x0020200800202000), CONST64(0x0020200020202000), CONST64(0x0020200820202000), + CONST64(0x0020200000000020), CONST64(0x0020200800000020), CONST64(0x0020200020000020), CONST64(0x0020200820000020), + CONST64(0x0020200000200020), CONST64(0x0020200800200020), CONST64(0x0020200020200020), CONST64(0x0020200820200020), + CONST64(0x0020200000002020), CONST64(0x0020200800002020), CONST64(0x0020200020002020), CONST64(0x0020200820002020), + CONST64(0x0020200000202020), CONST64(0x0020200800202020), CONST64(0x0020200020202020), CONST64(0x0020200820202020), + CONST64(0x2020200000000000), CONST64(0x2020200800000000), CONST64(0x2020200020000000), CONST64(0x2020200820000000), + CONST64(0x2020200000200000), CONST64(0x2020200800200000), CONST64(0x2020200020200000), CONST64(0x2020200820200000), + CONST64(0x2020200000002000), CONST64(0x2020200800002000), CONST64(0x2020200020002000), CONST64(0x2020200820002000), + CONST64(0x2020200000202000), CONST64(0x2020200800202000), CONST64(0x2020200020202000), CONST64(0x2020200820202000), + CONST64(0x2020200000000020), CONST64(0x2020200800000020), CONST64(0x2020200020000020), CONST64(0x2020200820000020), + CONST64(0x2020200000200020), CONST64(0x2020200800200020), CONST64(0x2020200020200020), CONST64(0x2020200820200020), + CONST64(0x2020200000002020), CONST64(0x2020200800002020), CONST64(0x2020200020002020), CONST64(0x2020200820002020), + CONST64(0x2020200000202020), CONST64(0x2020200800202020), CONST64(0x2020200020202020), CONST64(0x2020200820202020) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000002000000000), CONST64(0x0000000080000000), CONST64(0x0000002080000000), + CONST64(0x0000000000800000), CONST64(0x0000002000800000), CONST64(0x0000000080800000), CONST64(0x0000002080800000), + CONST64(0x0000000000008000), CONST64(0x0000002000008000), CONST64(0x0000000080008000), CONST64(0x0000002080008000), + CONST64(0x0000000000808000), CONST64(0x0000002000808000), CONST64(0x0000000080808000), CONST64(0x0000002080808000), + CONST64(0x0000000000000080), CONST64(0x0000002000000080), CONST64(0x0000000080000080), CONST64(0x0000002080000080), + CONST64(0x0000000000800080), CONST64(0x0000002000800080), CONST64(0x0000000080800080), CONST64(0x0000002080800080), + CONST64(0x0000000000008080), CONST64(0x0000002000008080), CONST64(0x0000000080008080), CONST64(0x0000002080008080), + CONST64(0x0000000000808080), CONST64(0x0000002000808080), CONST64(0x0000000080808080), CONST64(0x0000002080808080), + CONST64(0x8000000000000000), CONST64(0x8000002000000000), CONST64(0x8000000080000000), CONST64(0x8000002080000000), + CONST64(0x8000000000800000), CONST64(0x8000002000800000), CONST64(0x8000000080800000), CONST64(0x8000002080800000), + CONST64(0x8000000000008000), CONST64(0x8000002000008000), CONST64(0x8000000080008000), CONST64(0x8000002080008000), + CONST64(0x8000000000808000), CONST64(0x8000002000808000), CONST64(0x8000000080808000), CONST64(0x8000002080808000), + CONST64(0x8000000000000080), CONST64(0x8000002000000080), CONST64(0x8000000080000080), CONST64(0x8000002080000080), + CONST64(0x8000000000800080), CONST64(0x8000002000800080), CONST64(0x8000000080800080), CONST64(0x8000002080800080), + CONST64(0x8000000000008080), CONST64(0x8000002000008080), CONST64(0x8000000080008080), CONST64(0x8000002080008080), + CONST64(0x8000000000808080), CONST64(0x8000002000808080), CONST64(0x8000000080808080), CONST64(0x8000002080808080), + CONST64(0x0080000000000000), CONST64(0x0080002000000000), CONST64(0x0080000080000000), CONST64(0x0080002080000000), + CONST64(0x0080000000800000), CONST64(0x0080002000800000), CONST64(0x0080000080800000), CONST64(0x0080002080800000), + CONST64(0x0080000000008000), CONST64(0x0080002000008000), CONST64(0x0080000080008000), CONST64(0x0080002080008000), + CONST64(0x0080000000808000), CONST64(0x0080002000808000), CONST64(0x0080000080808000), CONST64(0x0080002080808000), + CONST64(0x0080000000000080), CONST64(0x0080002000000080), CONST64(0x0080000080000080), CONST64(0x0080002080000080), + CONST64(0x0080000000800080), CONST64(0x0080002000800080), CONST64(0x0080000080800080), CONST64(0x0080002080800080), + CONST64(0x0080000000008080), CONST64(0x0080002000008080), CONST64(0x0080000080008080), CONST64(0x0080002080008080), + CONST64(0x0080000000808080), CONST64(0x0080002000808080), CONST64(0x0080000080808080), CONST64(0x0080002080808080), + CONST64(0x8080000000000000), CONST64(0x8080002000000000), CONST64(0x8080000080000000), CONST64(0x8080002080000000), + CONST64(0x8080000000800000), CONST64(0x8080002000800000), CONST64(0x8080000080800000), CONST64(0x8080002080800000), + CONST64(0x8080000000008000), CONST64(0x8080002000008000), CONST64(0x8080000080008000), CONST64(0x8080002080008000), + CONST64(0x8080000000808000), CONST64(0x8080002000808000), CONST64(0x8080000080808000), CONST64(0x8080002080808000), + CONST64(0x8080000000000080), CONST64(0x8080002000000080), CONST64(0x8080000080000080), CONST64(0x8080002080000080), + CONST64(0x8080000000800080), CONST64(0x8080002000800080), CONST64(0x8080000080800080), CONST64(0x8080002080800080), + CONST64(0x8080000000008080), CONST64(0x8080002000008080), CONST64(0x8080000080008080), CONST64(0x8080002080008080), + CONST64(0x8080000000808080), CONST64(0x8080002000808080), CONST64(0x8080000080808080), CONST64(0x8080002080808080), + CONST64(0x0000800000000000), CONST64(0x0000802000000000), CONST64(0x0000800080000000), CONST64(0x0000802080000000), + CONST64(0x0000800000800000), CONST64(0x0000802000800000), CONST64(0x0000800080800000), CONST64(0x0000802080800000), + CONST64(0x0000800000008000), CONST64(0x0000802000008000), CONST64(0x0000800080008000), CONST64(0x0000802080008000), + CONST64(0x0000800000808000), CONST64(0x0000802000808000), CONST64(0x0000800080808000), CONST64(0x0000802080808000), + CONST64(0x0000800000000080), CONST64(0x0000802000000080), CONST64(0x0000800080000080), CONST64(0x0000802080000080), + CONST64(0x0000800000800080), CONST64(0x0000802000800080), CONST64(0x0000800080800080), CONST64(0x0000802080800080), + CONST64(0x0000800000008080), CONST64(0x0000802000008080), CONST64(0x0000800080008080), CONST64(0x0000802080008080), + CONST64(0x0000800000808080), CONST64(0x0000802000808080), CONST64(0x0000800080808080), CONST64(0x0000802080808080), + CONST64(0x8000800000000000), CONST64(0x8000802000000000), CONST64(0x8000800080000000), CONST64(0x8000802080000000), + CONST64(0x8000800000800000), CONST64(0x8000802000800000), CONST64(0x8000800080800000), CONST64(0x8000802080800000), + CONST64(0x8000800000008000), CONST64(0x8000802000008000), CONST64(0x8000800080008000), CONST64(0x8000802080008000), + CONST64(0x8000800000808000), CONST64(0x8000802000808000), CONST64(0x8000800080808000), CONST64(0x8000802080808000), + CONST64(0x8000800000000080), CONST64(0x8000802000000080), CONST64(0x8000800080000080), CONST64(0x8000802080000080), + CONST64(0x8000800000800080), CONST64(0x8000802000800080), CONST64(0x8000800080800080), CONST64(0x8000802080800080), + CONST64(0x8000800000008080), CONST64(0x8000802000008080), CONST64(0x8000800080008080), CONST64(0x8000802080008080), + CONST64(0x8000800000808080), CONST64(0x8000802000808080), CONST64(0x8000800080808080), CONST64(0x8000802080808080), + CONST64(0x0080800000000000), CONST64(0x0080802000000000), CONST64(0x0080800080000000), CONST64(0x0080802080000000), + CONST64(0x0080800000800000), CONST64(0x0080802000800000), CONST64(0x0080800080800000), CONST64(0x0080802080800000), + CONST64(0x0080800000008000), CONST64(0x0080802000008000), CONST64(0x0080800080008000), CONST64(0x0080802080008000), + CONST64(0x0080800000808000), CONST64(0x0080802000808000), CONST64(0x0080800080808000), CONST64(0x0080802080808000), + CONST64(0x0080800000000080), CONST64(0x0080802000000080), CONST64(0x0080800080000080), CONST64(0x0080802080000080), + CONST64(0x0080800000800080), CONST64(0x0080802000800080), CONST64(0x0080800080800080), CONST64(0x0080802080800080), + CONST64(0x0080800000008080), CONST64(0x0080802000008080), CONST64(0x0080800080008080), CONST64(0x0080802080008080), + CONST64(0x0080800000808080), CONST64(0x0080802000808080), CONST64(0x0080800080808080), CONST64(0x0080802080808080), + CONST64(0x8080800000000000), CONST64(0x8080802000000000), CONST64(0x8080800080000000), CONST64(0x8080802080000000), + CONST64(0x8080800000800000), CONST64(0x8080802000800000), CONST64(0x8080800080800000), CONST64(0x8080802080800000), + CONST64(0x8080800000008000), CONST64(0x8080802000008000), CONST64(0x8080800080008000), CONST64(0x8080802080008000), + CONST64(0x8080800000808000), CONST64(0x8080802000808000), CONST64(0x8080800080808000), CONST64(0x8080802080808000), + CONST64(0x8080800000000080), CONST64(0x8080802000000080), CONST64(0x8080800080000080), CONST64(0x8080802080000080), + CONST64(0x8080800000800080), CONST64(0x8080802000800080), CONST64(0x8080800080800080), CONST64(0x8080802080800080), + CONST64(0x8080800000008080), CONST64(0x8080802000008080), CONST64(0x8080800080008080), CONST64(0x8080802080008080), + CONST64(0x8080800000808080), CONST64(0x8080802000808080), CONST64(0x8080800080808080), CONST64(0x8080802080808080) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000004000000000), CONST64(0x0000000001000000), CONST64(0x0000004001000000), + CONST64(0x0000000000010000), CONST64(0x0000004000010000), CONST64(0x0000000001010000), CONST64(0x0000004001010000), + CONST64(0x0000000000000100), CONST64(0x0000004000000100), CONST64(0x0000000001000100), CONST64(0x0000004001000100), + CONST64(0x0000000000010100), CONST64(0x0000004000010100), CONST64(0x0000000001010100), CONST64(0x0000004001010100), + CONST64(0x0000000000000001), CONST64(0x0000004000000001), CONST64(0x0000000001000001), CONST64(0x0000004001000001), + CONST64(0x0000000000010001), CONST64(0x0000004000010001), CONST64(0x0000000001010001), CONST64(0x0000004001010001), + CONST64(0x0000000000000101), CONST64(0x0000004000000101), CONST64(0x0000000001000101), CONST64(0x0000004001000101), + CONST64(0x0000000000010101), CONST64(0x0000004000010101), CONST64(0x0000000001010101), CONST64(0x0000004001010101), + CONST64(0x0100000000000000), CONST64(0x0100004000000000), CONST64(0x0100000001000000), CONST64(0x0100004001000000), + CONST64(0x0100000000010000), CONST64(0x0100004000010000), CONST64(0x0100000001010000), CONST64(0x0100004001010000), + CONST64(0x0100000000000100), CONST64(0x0100004000000100), CONST64(0x0100000001000100), CONST64(0x0100004001000100), + CONST64(0x0100000000010100), CONST64(0x0100004000010100), CONST64(0x0100000001010100), CONST64(0x0100004001010100), + CONST64(0x0100000000000001), CONST64(0x0100004000000001), CONST64(0x0100000001000001), CONST64(0x0100004001000001), + CONST64(0x0100000000010001), CONST64(0x0100004000010001), CONST64(0x0100000001010001), CONST64(0x0100004001010001), + CONST64(0x0100000000000101), CONST64(0x0100004000000101), CONST64(0x0100000001000101), CONST64(0x0100004001000101), + CONST64(0x0100000000010101), CONST64(0x0100004000010101), CONST64(0x0100000001010101), CONST64(0x0100004001010101), + CONST64(0x0001000000000000), CONST64(0x0001004000000000), CONST64(0x0001000001000000), CONST64(0x0001004001000000), + CONST64(0x0001000000010000), CONST64(0x0001004000010000), CONST64(0x0001000001010000), CONST64(0x0001004001010000), + CONST64(0x0001000000000100), CONST64(0x0001004000000100), CONST64(0x0001000001000100), CONST64(0x0001004001000100), + CONST64(0x0001000000010100), CONST64(0x0001004000010100), CONST64(0x0001000001010100), CONST64(0x0001004001010100), + CONST64(0x0001000000000001), CONST64(0x0001004000000001), CONST64(0x0001000001000001), CONST64(0x0001004001000001), + CONST64(0x0001000000010001), CONST64(0x0001004000010001), CONST64(0x0001000001010001), CONST64(0x0001004001010001), + CONST64(0x0001000000000101), CONST64(0x0001004000000101), CONST64(0x0001000001000101), CONST64(0x0001004001000101), + CONST64(0x0001000000010101), CONST64(0x0001004000010101), CONST64(0x0001000001010101), CONST64(0x0001004001010101), + CONST64(0x0101000000000000), CONST64(0x0101004000000000), CONST64(0x0101000001000000), CONST64(0x0101004001000000), + CONST64(0x0101000000010000), CONST64(0x0101004000010000), CONST64(0x0101000001010000), CONST64(0x0101004001010000), + CONST64(0x0101000000000100), CONST64(0x0101004000000100), CONST64(0x0101000001000100), CONST64(0x0101004001000100), + CONST64(0x0101000000010100), CONST64(0x0101004000010100), CONST64(0x0101000001010100), CONST64(0x0101004001010100), + CONST64(0x0101000000000001), CONST64(0x0101004000000001), CONST64(0x0101000001000001), CONST64(0x0101004001000001), + CONST64(0x0101000000010001), CONST64(0x0101004000010001), CONST64(0x0101000001010001), CONST64(0x0101004001010001), + CONST64(0x0101000000000101), CONST64(0x0101004000000101), CONST64(0x0101000001000101), CONST64(0x0101004001000101), + CONST64(0x0101000000010101), CONST64(0x0101004000010101), CONST64(0x0101000001010101), CONST64(0x0101004001010101), + CONST64(0x0000010000000000), CONST64(0x0000014000000000), CONST64(0x0000010001000000), CONST64(0x0000014001000000), + CONST64(0x0000010000010000), CONST64(0x0000014000010000), CONST64(0x0000010001010000), CONST64(0x0000014001010000), + CONST64(0x0000010000000100), CONST64(0x0000014000000100), CONST64(0x0000010001000100), CONST64(0x0000014001000100), + CONST64(0x0000010000010100), CONST64(0x0000014000010100), CONST64(0x0000010001010100), CONST64(0x0000014001010100), + CONST64(0x0000010000000001), CONST64(0x0000014000000001), CONST64(0x0000010001000001), CONST64(0x0000014001000001), + CONST64(0x0000010000010001), CONST64(0x0000014000010001), CONST64(0x0000010001010001), CONST64(0x0000014001010001), + CONST64(0x0000010000000101), CONST64(0x0000014000000101), CONST64(0x0000010001000101), CONST64(0x0000014001000101), + CONST64(0x0000010000010101), CONST64(0x0000014000010101), CONST64(0x0000010001010101), CONST64(0x0000014001010101), + CONST64(0x0100010000000000), CONST64(0x0100014000000000), CONST64(0x0100010001000000), CONST64(0x0100014001000000), + CONST64(0x0100010000010000), CONST64(0x0100014000010000), CONST64(0x0100010001010000), CONST64(0x0100014001010000), + CONST64(0x0100010000000100), CONST64(0x0100014000000100), CONST64(0x0100010001000100), CONST64(0x0100014001000100), + CONST64(0x0100010000010100), CONST64(0x0100014000010100), CONST64(0x0100010001010100), CONST64(0x0100014001010100), + CONST64(0x0100010000000001), CONST64(0x0100014000000001), CONST64(0x0100010001000001), CONST64(0x0100014001000001), + CONST64(0x0100010000010001), CONST64(0x0100014000010001), CONST64(0x0100010001010001), CONST64(0x0100014001010001), + CONST64(0x0100010000000101), CONST64(0x0100014000000101), CONST64(0x0100010001000101), CONST64(0x0100014001000101), + CONST64(0x0100010000010101), CONST64(0x0100014000010101), CONST64(0x0100010001010101), CONST64(0x0100014001010101), + CONST64(0x0001010000000000), CONST64(0x0001014000000000), CONST64(0x0001010001000000), CONST64(0x0001014001000000), + CONST64(0x0001010000010000), CONST64(0x0001014000010000), CONST64(0x0001010001010000), CONST64(0x0001014001010000), + CONST64(0x0001010000000100), CONST64(0x0001014000000100), CONST64(0x0001010001000100), CONST64(0x0001014001000100), + CONST64(0x0001010000010100), CONST64(0x0001014000010100), CONST64(0x0001010001010100), CONST64(0x0001014001010100), + CONST64(0x0001010000000001), CONST64(0x0001014000000001), CONST64(0x0001010001000001), CONST64(0x0001014001000001), + CONST64(0x0001010000010001), CONST64(0x0001014000010001), CONST64(0x0001010001010001), CONST64(0x0001014001010001), + CONST64(0x0001010000000101), CONST64(0x0001014000000101), CONST64(0x0001010001000101), CONST64(0x0001014001000101), + CONST64(0x0001010000010101), CONST64(0x0001014000010101), CONST64(0x0001010001010101), CONST64(0x0001014001010101), + CONST64(0x0101010000000000), CONST64(0x0101014000000000), CONST64(0x0101010001000000), CONST64(0x0101014001000000), + CONST64(0x0101010000010000), CONST64(0x0101014000010000), CONST64(0x0101010001010000), CONST64(0x0101014001010000), + CONST64(0x0101010000000100), CONST64(0x0101014000000100), CONST64(0x0101010001000100), CONST64(0x0101014001000100), + CONST64(0x0101010000010100), CONST64(0x0101014000010100), CONST64(0x0101010001010100), CONST64(0x0101014001010100), + CONST64(0x0101010000000001), CONST64(0x0101014000000001), CONST64(0x0101010001000001), CONST64(0x0101014001000001), + CONST64(0x0101010000010001), CONST64(0x0101014000010001), CONST64(0x0101010001010001), CONST64(0x0101014001010001), + CONST64(0x0101010000000101), CONST64(0x0101014000000101), CONST64(0x0101010001000101), CONST64(0x0101014001000101), + CONST64(0x0101010000010101), CONST64(0x0101014000010101), CONST64(0x0101010001010101), CONST64(0x0101014001010101) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000100000000), CONST64(0x0000000004000000), CONST64(0x0000000104000000), + CONST64(0x0000000000040000), CONST64(0x0000000100040000), CONST64(0x0000000004040000), CONST64(0x0000000104040000), + CONST64(0x0000000000000400), CONST64(0x0000000100000400), CONST64(0x0000000004000400), CONST64(0x0000000104000400), + CONST64(0x0000000000040400), CONST64(0x0000000100040400), CONST64(0x0000000004040400), CONST64(0x0000000104040400), + CONST64(0x0000000000000004), CONST64(0x0000000100000004), CONST64(0x0000000004000004), CONST64(0x0000000104000004), + CONST64(0x0000000000040004), CONST64(0x0000000100040004), CONST64(0x0000000004040004), CONST64(0x0000000104040004), + CONST64(0x0000000000000404), CONST64(0x0000000100000404), CONST64(0x0000000004000404), CONST64(0x0000000104000404), + CONST64(0x0000000000040404), CONST64(0x0000000100040404), CONST64(0x0000000004040404), CONST64(0x0000000104040404), + CONST64(0x0400000000000000), CONST64(0x0400000100000000), CONST64(0x0400000004000000), CONST64(0x0400000104000000), + CONST64(0x0400000000040000), CONST64(0x0400000100040000), CONST64(0x0400000004040000), CONST64(0x0400000104040000), + CONST64(0x0400000000000400), CONST64(0x0400000100000400), CONST64(0x0400000004000400), CONST64(0x0400000104000400), + CONST64(0x0400000000040400), CONST64(0x0400000100040400), CONST64(0x0400000004040400), CONST64(0x0400000104040400), + CONST64(0x0400000000000004), CONST64(0x0400000100000004), CONST64(0x0400000004000004), CONST64(0x0400000104000004), + CONST64(0x0400000000040004), CONST64(0x0400000100040004), CONST64(0x0400000004040004), CONST64(0x0400000104040004), + CONST64(0x0400000000000404), CONST64(0x0400000100000404), CONST64(0x0400000004000404), CONST64(0x0400000104000404), + CONST64(0x0400000000040404), CONST64(0x0400000100040404), CONST64(0x0400000004040404), CONST64(0x0400000104040404), + CONST64(0x0004000000000000), CONST64(0x0004000100000000), CONST64(0x0004000004000000), CONST64(0x0004000104000000), + CONST64(0x0004000000040000), CONST64(0x0004000100040000), CONST64(0x0004000004040000), CONST64(0x0004000104040000), + CONST64(0x0004000000000400), CONST64(0x0004000100000400), CONST64(0x0004000004000400), CONST64(0x0004000104000400), + CONST64(0x0004000000040400), CONST64(0x0004000100040400), CONST64(0x0004000004040400), CONST64(0x0004000104040400), + CONST64(0x0004000000000004), CONST64(0x0004000100000004), CONST64(0x0004000004000004), CONST64(0x0004000104000004), + CONST64(0x0004000000040004), CONST64(0x0004000100040004), CONST64(0x0004000004040004), CONST64(0x0004000104040004), + CONST64(0x0004000000000404), CONST64(0x0004000100000404), CONST64(0x0004000004000404), CONST64(0x0004000104000404), + CONST64(0x0004000000040404), CONST64(0x0004000100040404), CONST64(0x0004000004040404), CONST64(0x0004000104040404), + CONST64(0x0404000000000000), CONST64(0x0404000100000000), CONST64(0x0404000004000000), CONST64(0x0404000104000000), + CONST64(0x0404000000040000), CONST64(0x0404000100040000), CONST64(0x0404000004040000), CONST64(0x0404000104040000), + CONST64(0x0404000000000400), CONST64(0x0404000100000400), CONST64(0x0404000004000400), CONST64(0x0404000104000400), + CONST64(0x0404000000040400), CONST64(0x0404000100040400), CONST64(0x0404000004040400), CONST64(0x0404000104040400), + CONST64(0x0404000000000004), CONST64(0x0404000100000004), CONST64(0x0404000004000004), CONST64(0x0404000104000004), + CONST64(0x0404000000040004), CONST64(0x0404000100040004), CONST64(0x0404000004040004), CONST64(0x0404000104040004), + CONST64(0x0404000000000404), CONST64(0x0404000100000404), CONST64(0x0404000004000404), CONST64(0x0404000104000404), + CONST64(0x0404000000040404), CONST64(0x0404000100040404), CONST64(0x0404000004040404), CONST64(0x0404000104040404), + CONST64(0x0000040000000000), CONST64(0x0000040100000000), CONST64(0x0000040004000000), CONST64(0x0000040104000000), + CONST64(0x0000040000040000), CONST64(0x0000040100040000), CONST64(0x0000040004040000), CONST64(0x0000040104040000), + CONST64(0x0000040000000400), CONST64(0x0000040100000400), CONST64(0x0000040004000400), CONST64(0x0000040104000400), + CONST64(0x0000040000040400), CONST64(0x0000040100040400), CONST64(0x0000040004040400), CONST64(0x0000040104040400), + CONST64(0x0000040000000004), CONST64(0x0000040100000004), CONST64(0x0000040004000004), CONST64(0x0000040104000004), + CONST64(0x0000040000040004), CONST64(0x0000040100040004), CONST64(0x0000040004040004), CONST64(0x0000040104040004), + CONST64(0x0000040000000404), CONST64(0x0000040100000404), CONST64(0x0000040004000404), CONST64(0x0000040104000404), + CONST64(0x0000040000040404), CONST64(0x0000040100040404), CONST64(0x0000040004040404), CONST64(0x0000040104040404), + CONST64(0x0400040000000000), CONST64(0x0400040100000000), CONST64(0x0400040004000000), CONST64(0x0400040104000000), + CONST64(0x0400040000040000), CONST64(0x0400040100040000), CONST64(0x0400040004040000), CONST64(0x0400040104040000), + CONST64(0x0400040000000400), CONST64(0x0400040100000400), CONST64(0x0400040004000400), CONST64(0x0400040104000400), + CONST64(0x0400040000040400), CONST64(0x0400040100040400), CONST64(0x0400040004040400), CONST64(0x0400040104040400), + CONST64(0x0400040000000004), CONST64(0x0400040100000004), CONST64(0x0400040004000004), CONST64(0x0400040104000004), + CONST64(0x0400040000040004), CONST64(0x0400040100040004), CONST64(0x0400040004040004), CONST64(0x0400040104040004), + CONST64(0x0400040000000404), CONST64(0x0400040100000404), CONST64(0x0400040004000404), CONST64(0x0400040104000404), + CONST64(0x0400040000040404), CONST64(0x0400040100040404), CONST64(0x0400040004040404), CONST64(0x0400040104040404), + CONST64(0x0004040000000000), CONST64(0x0004040100000000), CONST64(0x0004040004000000), CONST64(0x0004040104000000), + CONST64(0x0004040000040000), CONST64(0x0004040100040000), CONST64(0x0004040004040000), CONST64(0x0004040104040000), + CONST64(0x0004040000000400), CONST64(0x0004040100000400), CONST64(0x0004040004000400), CONST64(0x0004040104000400), + CONST64(0x0004040000040400), CONST64(0x0004040100040400), CONST64(0x0004040004040400), CONST64(0x0004040104040400), + CONST64(0x0004040000000004), CONST64(0x0004040100000004), CONST64(0x0004040004000004), CONST64(0x0004040104000004), + CONST64(0x0004040000040004), CONST64(0x0004040100040004), CONST64(0x0004040004040004), CONST64(0x0004040104040004), + CONST64(0x0004040000000404), CONST64(0x0004040100000404), CONST64(0x0004040004000404), CONST64(0x0004040104000404), + CONST64(0x0004040000040404), CONST64(0x0004040100040404), CONST64(0x0004040004040404), CONST64(0x0004040104040404), + CONST64(0x0404040000000000), CONST64(0x0404040100000000), CONST64(0x0404040004000000), CONST64(0x0404040104000000), + CONST64(0x0404040000040000), CONST64(0x0404040100040000), CONST64(0x0404040004040000), CONST64(0x0404040104040000), + CONST64(0x0404040000000400), CONST64(0x0404040100000400), CONST64(0x0404040004000400), CONST64(0x0404040104000400), + CONST64(0x0404040000040400), CONST64(0x0404040100040400), CONST64(0x0404040004040400), CONST64(0x0404040104040400), + CONST64(0x0404040000000004), CONST64(0x0404040100000004), CONST64(0x0404040004000004), CONST64(0x0404040104000004), + CONST64(0x0404040000040004), CONST64(0x0404040100040004), CONST64(0x0404040004040004), CONST64(0x0404040104040004), + CONST64(0x0404040000000404), CONST64(0x0404040100000404), CONST64(0x0404040004000404), CONST64(0x0404040104000404), + CONST64(0x0404040000040404), CONST64(0x0404040100040404), CONST64(0x0404040004040404), CONST64(0x0404040104040404) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000400000000), CONST64(0x0000000010000000), CONST64(0x0000000410000000), + CONST64(0x0000000000100000), CONST64(0x0000000400100000), CONST64(0x0000000010100000), CONST64(0x0000000410100000), + CONST64(0x0000000000001000), CONST64(0x0000000400001000), CONST64(0x0000000010001000), CONST64(0x0000000410001000), + CONST64(0x0000000000101000), CONST64(0x0000000400101000), CONST64(0x0000000010101000), CONST64(0x0000000410101000), + CONST64(0x0000000000000010), CONST64(0x0000000400000010), CONST64(0x0000000010000010), CONST64(0x0000000410000010), + CONST64(0x0000000000100010), CONST64(0x0000000400100010), CONST64(0x0000000010100010), CONST64(0x0000000410100010), + CONST64(0x0000000000001010), CONST64(0x0000000400001010), CONST64(0x0000000010001010), CONST64(0x0000000410001010), + CONST64(0x0000000000101010), CONST64(0x0000000400101010), CONST64(0x0000000010101010), CONST64(0x0000000410101010), + CONST64(0x1000000000000000), CONST64(0x1000000400000000), CONST64(0x1000000010000000), CONST64(0x1000000410000000), + CONST64(0x1000000000100000), CONST64(0x1000000400100000), CONST64(0x1000000010100000), CONST64(0x1000000410100000), + CONST64(0x1000000000001000), CONST64(0x1000000400001000), CONST64(0x1000000010001000), CONST64(0x1000000410001000), + CONST64(0x1000000000101000), CONST64(0x1000000400101000), CONST64(0x1000000010101000), CONST64(0x1000000410101000), + CONST64(0x1000000000000010), CONST64(0x1000000400000010), CONST64(0x1000000010000010), CONST64(0x1000000410000010), + CONST64(0x1000000000100010), CONST64(0x1000000400100010), CONST64(0x1000000010100010), CONST64(0x1000000410100010), + CONST64(0x1000000000001010), CONST64(0x1000000400001010), CONST64(0x1000000010001010), CONST64(0x1000000410001010), + CONST64(0x1000000000101010), CONST64(0x1000000400101010), CONST64(0x1000000010101010), CONST64(0x1000000410101010), + CONST64(0x0010000000000000), CONST64(0x0010000400000000), CONST64(0x0010000010000000), CONST64(0x0010000410000000), + CONST64(0x0010000000100000), CONST64(0x0010000400100000), CONST64(0x0010000010100000), CONST64(0x0010000410100000), + CONST64(0x0010000000001000), CONST64(0x0010000400001000), CONST64(0x0010000010001000), CONST64(0x0010000410001000), + CONST64(0x0010000000101000), CONST64(0x0010000400101000), CONST64(0x0010000010101000), CONST64(0x0010000410101000), + CONST64(0x0010000000000010), CONST64(0x0010000400000010), CONST64(0x0010000010000010), CONST64(0x0010000410000010), + CONST64(0x0010000000100010), CONST64(0x0010000400100010), CONST64(0x0010000010100010), CONST64(0x0010000410100010), + CONST64(0x0010000000001010), CONST64(0x0010000400001010), CONST64(0x0010000010001010), CONST64(0x0010000410001010), + CONST64(0x0010000000101010), CONST64(0x0010000400101010), CONST64(0x0010000010101010), CONST64(0x0010000410101010), + CONST64(0x1010000000000000), CONST64(0x1010000400000000), CONST64(0x1010000010000000), CONST64(0x1010000410000000), + CONST64(0x1010000000100000), CONST64(0x1010000400100000), CONST64(0x1010000010100000), CONST64(0x1010000410100000), + CONST64(0x1010000000001000), CONST64(0x1010000400001000), CONST64(0x1010000010001000), CONST64(0x1010000410001000), + CONST64(0x1010000000101000), CONST64(0x1010000400101000), CONST64(0x1010000010101000), CONST64(0x1010000410101000), + CONST64(0x1010000000000010), CONST64(0x1010000400000010), CONST64(0x1010000010000010), CONST64(0x1010000410000010), + CONST64(0x1010000000100010), CONST64(0x1010000400100010), CONST64(0x1010000010100010), CONST64(0x1010000410100010), + CONST64(0x1010000000001010), CONST64(0x1010000400001010), CONST64(0x1010000010001010), CONST64(0x1010000410001010), + CONST64(0x1010000000101010), CONST64(0x1010000400101010), CONST64(0x1010000010101010), CONST64(0x1010000410101010), + CONST64(0x0000100000000000), CONST64(0x0000100400000000), CONST64(0x0000100010000000), CONST64(0x0000100410000000), + CONST64(0x0000100000100000), CONST64(0x0000100400100000), CONST64(0x0000100010100000), CONST64(0x0000100410100000), + CONST64(0x0000100000001000), CONST64(0x0000100400001000), CONST64(0x0000100010001000), CONST64(0x0000100410001000), + CONST64(0x0000100000101000), CONST64(0x0000100400101000), CONST64(0x0000100010101000), CONST64(0x0000100410101000), + CONST64(0x0000100000000010), CONST64(0x0000100400000010), CONST64(0x0000100010000010), CONST64(0x0000100410000010), + CONST64(0x0000100000100010), CONST64(0x0000100400100010), CONST64(0x0000100010100010), CONST64(0x0000100410100010), + CONST64(0x0000100000001010), CONST64(0x0000100400001010), CONST64(0x0000100010001010), CONST64(0x0000100410001010), + CONST64(0x0000100000101010), CONST64(0x0000100400101010), CONST64(0x0000100010101010), CONST64(0x0000100410101010), + CONST64(0x1000100000000000), CONST64(0x1000100400000000), CONST64(0x1000100010000000), CONST64(0x1000100410000000), + CONST64(0x1000100000100000), CONST64(0x1000100400100000), CONST64(0x1000100010100000), CONST64(0x1000100410100000), + CONST64(0x1000100000001000), CONST64(0x1000100400001000), CONST64(0x1000100010001000), CONST64(0x1000100410001000), + CONST64(0x1000100000101000), CONST64(0x1000100400101000), CONST64(0x1000100010101000), CONST64(0x1000100410101000), + CONST64(0x1000100000000010), CONST64(0x1000100400000010), CONST64(0x1000100010000010), CONST64(0x1000100410000010), + CONST64(0x1000100000100010), CONST64(0x1000100400100010), CONST64(0x1000100010100010), CONST64(0x1000100410100010), + CONST64(0x1000100000001010), CONST64(0x1000100400001010), CONST64(0x1000100010001010), CONST64(0x1000100410001010), + CONST64(0x1000100000101010), CONST64(0x1000100400101010), CONST64(0x1000100010101010), CONST64(0x1000100410101010), + CONST64(0x0010100000000000), CONST64(0x0010100400000000), CONST64(0x0010100010000000), CONST64(0x0010100410000000), + CONST64(0x0010100000100000), CONST64(0x0010100400100000), CONST64(0x0010100010100000), CONST64(0x0010100410100000), + CONST64(0x0010100000001000), CONST64(0x0010100400001000), CONST64(0x0010100010001000), CONST64(0x0010100410001000), + CONST64(0x0010100000101000), CONST64(0x0010100400101000), CONST64(0x0010100010101000), CONST64(0x0010100410101000), + CONST64(0x0010100000000010), CONST64(0x0010100400000010), CONST64(0x0010100010000010), CONST64(0x0010100410000010), + CONST64(0x0010100000100010), CONST64(0x0010100400100010), CONST64(0x0010100010100010), CONST64(0x0010100410100010), + CONST64(0x0010100000001010), CONST64(0x0010100400001010), CONST64(0x0010100010001010), CONST64(0x0010100410001010), + CONST64(0x0010100000101010), CONST64(0x0010100400101010), CONST64(0x0010100010101010), CONST64(0x0010100410101010), + CONST64(0x1010100000000000), CONST64(0x1010100400000000), CONST64(0x1010100010000000), CONST64(0x1010100410000000), + CONST64(0x1010100000100000), CONST64(0x1010100400100000), CONST64(0x1010100010100000), CONST64(0x1010100410100000), + CONST64(0x1010100000001000), CONST64(0x1010100400001000), CONST64(0x1010100010001000), CONST64(0x1010100410001000), + CONST64(0x1010100000101000), CONST64(0x1010100400101000), CONST64(0x1010100010101000), CONST64(0x1010100410101000), + CONST64(0x1010100000000010), CONST64(0x1010100400000010), CONST64(0x1010100010000010), CONST64(0x1010100410000010), + CONST64(0x1010100000100010), CONST64(0x1010100400100010), CONST64(0x1010100010100010), CONST64(0x1010100410100010), + CONST64(0x1010100000001010), CONST64(0x1010100400001010), CONST64(0x1010100010001010), CONST64(0x1010100410001010), + CONST64(0x1010100000101010), CONST64(0x1010100400101010), CONST64(0x1010100010101010), CONST64(0x1010100410101010) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000001000000000), CONST64(0x0000000040000000), CONST64(0x0000001040000000), + CONST64(0x0000000000400000), CONST64(0x0000001000400000), CONST64(0x0000000040400000), CONST64(0x0000001040400000), + CONST64(0x0000000000004000), CONST64(0x0000001000004000), CONST64(0x0000000040004000), CONST64(0x0000001040004000), + CONST64(0x0000000000404000), CONST64(0x0000001000404000), CONST64(0x0000000040404000), CONST64(0x0000001040404000), + CONST64(0x0000000000000040), CONST64(0x0000001000000040), CONST64(0x0000000040000040), CONST64(0x0000001040000040), + CONST64(0x0000000000400040), CONST64(0x0000001000400040), CONST64(0x0000000040400040), CONST64(0x0000001040400040), + CONST64(0x0000000000004040), CONST64(0x0000001000004040), CONST64(0x0000000040004040), CONST64(0x0000001040004040), + CONST64(0x0000000000404040), CONST64(0x0000001000404040), CONST64(0x0000000040404040), CONST64(0x0000001040404040), + CONST64(0x4000000000000000), CONST64(0x4000001000000000), CONST64(0x4000000040000000), CONST64(0x4000001040000000), + CONST64(0x4000000000400000), CONST64(0x4000001000400000), CONST64(0x4000000040400000), CONST64(0x4000001040400000), + CONST64(0x4000000000004000), CONST64(0x4000001000004000), CONST64(0x4000000040004000), CONST64(0x4000001040004000), + CONST64(0x4000000000404000), CONST64(0x4000001000404000), CONST64(0x4000000040404000), CONST64(0x4000001040404000), + CONST64(0x4000000000000040), CONST64(0x4000001000000040), CONST64(0x4000000040000040), CONST64(0x4000001040000040), + CONST64(0x4000000000400040), CONST64(0x4000001000400040), CONST64(0x4000000040400040), CONST64(0x4000001040400040), + CONST64(0x4000000000004040), CONST64(0x4000001000004040), CONST64(0x4000000040004040), CONST64(0x4000001040004040), + CONST64(0x4000000000404040), CONST64(0x4000001000404040), CONST64(0x4000000040404040), CONST64(0x4000001040404040), + CONST64(0x0040000000000000), CONST64(0x0040001000000000), CONST64(0x0040000040000000), CONST64(0x0040001040000000), + CONST64(0x0040000000400000), CONST64(0x0040001000400000), CONST64(0x0040000040400000), CONST64(0x0040001040400000), + CONST64(0x0040000000004000), CONST64(0x0040001000004000), CONST64(0x0040000040004000), CONST64(0x0040001040004000), + CONST64(0x0040000000404000), CONST64(0x0040001000404000), CONST64(0x0040000040404000), CONST64(0x0040001040404000), + CONST64(0x0040000000000040), CONST64(0x0040001000000040), CONST64(0x0040000040000040), CONST64(0x0040001040000040), + CONST64(0x0040000000400040), CONST64(0x0040001000400040), CONST64(0x0040000040400040), CONST64(0x0040001040400040), + CONST64(0x0040000000004040), CONST64(0x0040001000004040), CONST64(0x0040000040004040), CONST64(0x0040001040004040), + CONST64(0x0040000000404040), CONST64(0x0040001000404040), CONST64(0x0040000040404040), CONST64(0x0040001040404040), + CONST64(0x4040000000000000), CONST64(0x4040001000000000), CONST64(0x4040000040000000), CONST64(0x4040001040000000), + CONST64(0x4040000000400000), CONST64(0x4040001000400000), CONST64(0x4040000040400000), CONST64(0x4040001040400000), + CONST64(0x4040000000004000), CONST64(0x4040001000004000), CONST64(0x4040000040004000), CONST64(0x4040001040004000), + CONST64(0x4040000000404000), CONST64(0x4040001000404000), CONST64(0x4040000040404000), CONST64(0x4040001040404000), + CONST64(0x4040000000000040), CONST64(0x4040001000000040), CONST64(0x4040000040000040), CONST64(0x4040001040000040), + CONST64(0x4040000000400040), CONST64(0x4040001000400040), CONST64(0x4040000040400040), CONST64(0x4040001040400040), + CONST64(0x4040000000004040), CONST64(0x4040001000004040), CONST64(0x4040000040004040), CONST64(0x4040001040004040), + CONST64(0x4040000000404040), CONST64(0x4040001000404040), CONST64(0x4040000040404040), CONST64(0x4040001040404040), + CONST64(0x0000400000000000), CONST64(0x0000401000000000), CONST64(0x0000400040000000), CONST64(0x0000401040000000), + CONST64(0x0000400000400000), CONST64(0x0000401000400000), CONST64(0x0000400040400000), CONST64(0x0000401040400000), + CONST64(0x0000400000004000), CONST64(0x0000401000004000), CONST64(0x0000400040004000), CONST64(0x0000401040004000), + CONST64(0x0000400000404000), CONST64(0x0000401000404000), CONST64(0x0000400040404000), CONST64(0x0000401040404000), + CONST64(0x0000400000000040), CONST64(0x0000401000000040), CONST64(0x0000400040000040), CONST64(0x0000401040000040), + CONST64(0x0000400000400040), CONST64(0x0000401000400040), CONST64(0x0000400040400040), CONST64(0x0000401040400040), + CONST64(0x0000400000004040), CONST64(0x0000401000004040), CONST64(0x0000400040004040), CONST64(0x0000401040004040), + CONST64(0x0000400000404040), CONST64(0x0000401000404040), CONST64(0x0000400040404040), CONST64(0x0000401040404040), + CONST64(0x4000400000000000), CONST64(0x4000401000000000), CONST64(0x4000400040000000), CONST64(0x4000401040000000), + CONST64(0x4000400000400000), CONST64(0x4000401000400000), CONST64(0x4000400040400000), CONST64(0x4000401040400000), + CONST64(0x4000400000004000), CONST64(0x4000401000004000), CONST64(0x4000400040004000), CONST64(0x4000401040004000), + CONST64(0x4000400000404000), CONST64(0x4000401000404000), CONST64(0x4000400040404000), CONST64(0x4000401040404000), + CONST64(0x4000400000000040), CONST64(0x4000401000000040), CONST64(0x4000400040000040), CONST64(0x4000401040000040), + CONST64(0x4000400000400040), CONST64(0x4000401000400040), CONST64(0x4000400040400040), CONST64(0x4000401040400040), + CONST64(0x4000400000004040), CONST64(0x4000401000004040), CONST64(0x4000400040004040), CONST64(0x4000401040004040), + CONST64(0x4000400000404040), CONST64(0x4000401000404040), CONST64(0x4000400040404040), CONST64(0x4000401040404040), + CONST64(0x0040400000000000), CONST64(0x0040401000000000), CONST64(0x0040400040000000), CONST64(0x0040401040000000), + CONST64(0x0040400000400000), CONST64(0x0040401000400000), CONST64(0x0040400040400000), CONST64(0x0040401040400000), + CONST64(0x0040400000004000), CONST64(0x0040401000004000), CONST64(0x0040400040004000), CONST64(0x0040401040004000), + CONST64(0x0040400000404000), CONST64(0x0040401000404000), CONST64(0x0040400040404000), CONST64(0x0040401040404000), + CONST64(0x0040400000000040), CONST64(0x0040401000000040), CONST64(0x0040400040000040), CONST64(0x0040401040000040), + CONST64(0x0040400000400040), CONST64(0x0040401000400040), CONST64(0x0040400040400040), CONST64(0x0040401040400040), + CONST64(0x0040400000004040), CONST64(0x0040401000004040), CONST64(0x0040400040004040), CONST64(0x0040401040004040), + CONST64(0x0040400000404040), CONST64(0x0040401000404040), CONST64(0x0040400040404040), CONST64(0x0040401040404040), + CONST64(0x4040400000000000), CONST64(0x4040401000000000), CONST64(0x4040400040000000), CONST64(0x4040401040000000), + CONST64(0x4040400000400000), CONST64(0x4040401000400000), CONST64(0x4040400040400000), CONST64(0x4040401040400000), + CONST64(0x4040400000004000), CONST64(0x4040401000004000), CONST64(0x4040400040004000), CONST64(0x4040401040004000), + CONST64(0x4040400000404000), CONST64(0x4040401000404000), CONST64(0x4040400040404000), CONST64(0x4040401040404000), + CONST64(0x4040400000000040), CONST64(0x4040401000000040), CONST64(0x4040400040000040), CONST64(0x4040401040000040), + CONST64(0x4040400000400040), CONST64(0x4040401000400040), CONST64(0x4040400040400040), CONST64(0x4040401040400040), + CONST64(0x4040400000004040), CONST64(0x4040401000004040), CONST64(0x4040400040004040), CONST64(0x4040401040004040), + CONST64(0x4040400000404040), CONST64(0x4040401000404040), CONST64(0x4040400040404040), CONST64(0x4040401040404040) + }}; + +#endif /* PS_3DES_IMPROVE_PERF_INCREASE_CODESIZE && HAVE_NATIVE_INT64 */ + +/******************************************************************************/ +/* + Common DES functions + */ +static void cookey(const uint32_t *raw1, uint32_t *keyout) +{ + uint32 *cook; + const uint32 *raw0; + uint32 dough[32]; + int32 i; + + cook = dough; + for(i=0; i < 16; i++, raw1++) { + raw0 = raw1++; + *cook = (*raw0 & 0x00fc0000L) << 6; + *cook |= (*raw0 & 0x00000fc0L) << 10; + *cook |= (*raw1 & 0x00fc0000L) >> 10; + *cook++ |= (*raw1 & 0x00000fc0L) >> 6; + *cook = (*raw0 & 0x0003f000L) << 12; + *cook |= (*raw0 & 0x0000003fL) << 16; + *cook |= (*raw1 & 0x0003f000L) >> 4; + *cook++ |= (*raw1 & 0x0000003fL); + } + + psMemcpy(keyout, dough, sizeof dough); +#ifdef USE_BURN_STACK + psBurnStack(sizeof(uint32 *) * 2 + sizeof(uint32)*32 + sizeof(int32)); +#endif /* USE_BURN_STACK */ +} + +static void deskey(const unsigned char *key, int32 edf, uint32_t *keyout) +{ + uint32_t i, j, l, m, n, kn[32]; + unsigned char pc1m[56], pcr[56]; + + for (j=0; j < 56; j++) { + l = (uint32)pc1[j]; + m = l & 7; + pc1m[j] = (unsigned char)((key[l >> 3U] & bytebit[m]) == + bytebit[m] ? 1 : 0); + } + + for (i=0; i < 16; i++) { + if (edf == DE1) { + m = (15 - i) << 1; + } else { + m = i << 1; + } + n = m + 1; + kn[m] = kn[n] = 0L; + for (j=0; j < 28; j++) { + l = j + (uint32)totrot[i]; + if (l < 28) { + pcr[j] = pc1m[l]; + } else { + pcr[j] = pc1m[l - 28]; + } + } + for (/*j = 28*/; j < 56; j++) { + l = j + (uint32)totrot[i]; + if (l < 56) { + pcr[j] = pc1m[l]; + } else { + pcr[j] = pc1m[l - 28]; + } + } + for (j=0; j < 24; j++) { + if ((int32)pcr[(int32)pc2[j]] != 0) { + kn[m] |= bigbyte[j]; + } + if ((int32)pcr[(int32)pc2[j+24]] != 0) { + kn[n] |= bigbyte[j]; + } + } + } + cookey(kn, keyout); +#ifdef USE_BURN_STACK + psBurnStack(sizeof(int32)*5 + sizeof(uint32)*32 + + sizeof(unsigned char)*112); +#endif /* USE_BURN_STACK */ +} + +static void desfunc(uint32 *block, const uint32 *keys) +{ + uint32 work, right, leftt; + int32 cur_round; + + leftt = block[0]; + right = block[1]; + +#if !defined(PS_3DES_IMPROVE_PERF_INCREASE_CODESIZE) || !defined(HAVE_NATIVE_INT64) + work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; + right ^= work; + leftt ^= (work << 4); + + work = ((leftt >> 16) ^ right) & 0x0000ffffL; + right ^= work; + leftt ^= (work << 16); + + work = ((right >> 2) ^ leftt) & 0x33333333L; + leftt ^= work; + right ^= (work << 2); + + work = ((right >> 8) ^ leftt) & 0x00ff00ffL; + leftt ^= work; + right ^= (work << 8); + + right = ROL(right, 1); + work = (leftt ^ right) & 0xaaaaaaaaL; + + leftt ^= work; + right ^= work; + leftt = ROL(leftt, 1); +#else /* !PS_3DES_IMPROVE_PERF_INCREASE_CODESIZE && HAVE_NATIVE_INT64*/ + { + uint64 tmp; + tmp = des_ip[0][byte(leftt, 0)] ^ + des_ip[1][byte(leftt, 1)] ^ + des_ip[2][byte(leftt, 2)] ^ + des_ip[3][byte(leftt, 3)] ^ + des_ip[4][byte(right, 0)] ^ + des_ip[5][byte(right, 1)] ^ + des_ip[6][byte(right, 2)] ^ + des_ip[7][byte(right, 3)]; + leftt = (uint32)(tmp >> 32); + right = (uint32)(tmp & 0xFFFFFFFFUL); + } +#endif /* SMALL CODE */ + + for (cur_round = 0; cur_round < 8; cur_round++) { + work = ROR(right, 4) ^ *keys++; + leftt ^= SP7[work & 0x3fL] + ^ SP5[(work >> 8) & 0x3fL] + ^ SP3[(work >> 16) & 0x3fL] + ^ SP1[(work >> 24) & 0x3fL]; + work = right ^ *keys++; + leftt ^= SP8[ work & 0x3fL] + ^ SP6[(work >> 8) & 0x3fL] + ^ SP4[(work >> 16) & 0x3fL] + ^ SP2[(work >> 24) & 0x3fL]; + + work = ROR(leftt, 4) ^ *keys++; + right ^= SP7[ work & 0x3fL] + ^ SP5[(work >> 8) & 0x3fL] + ^ SP3[(work >> 16) & 0x3fL] + ^ SP1[(work >> 24) & 0x3fL]; + work = leftt ^ *keys++; + right ^= SP8[ work & 0x3fL] + ^ SP6[(work >> 8) & 0x3fL] + ^ SP4[(work >> 16) & 0x3fL] + ^ SP2[(work >> 24) & 0x3fL]; + } + +#if !defined(PS_3DES_IMPROVE_PERF_INCREASE_CODESIZE) || !defined(HAVE_NATIVE_INT64) + right = ROR(right, 1); + work = (leftt ^ right) & 0xaaaaaaaaL; + leftt ^= work; + right ^= work; + leftt = ROR(leftt, 1); + work = ((leftt >> 8) ^ right) & 0x00ff00ffL; + right ^= work; + leftt ^= (work << 8); + + work = ((leftt >> 2) ^ right) & 0x33333333L; + right ^= work; + leftt ^= (work << 2); + work = ((right >> 16) ^ leftt) & 0x0000ffffL; + leftt ^= work; + right ^= (work << 16); + work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; + leftt ^= work; + right ^= (work << 4); +#else /* !PS_3DES_IMPROVE_PERF_INCREASE_CODESIZE && HAVE_NATIVE_INT64 */ + { + uint64 tmp; + tmp = des_fp[0][byte(leftt, 0)] ^ + des_fp[1][byte(leftt, 1)] ^ + des_fp[2][byte(leftt, 2)] ^ + des_fp[3][byte(leftt, 3)] ^ + des_fp[4][byte(right, 0)] ^ + des_fp[5][byte(right, 1)] ^ + des_fp[6][byte(right, 2)] ^ + des_fp[7][byte(right, 3)]; + leftt = (uint32)(tmp >> 32); + right = (uint32)(tmp & 0xFFFFFFFFUL); + } +#endif /* PS_3DES_IMPROVE_PERF_INCREASE_CODESIZE */ + + block[0] = right; + block[1] = leftt; +#ifdef USE_BURN_STACK + psBurnStack(sizeof(uint32) * 4 + sizeof(int32)); +#endif /* USE_BURN_STACK */ +} + +/******************************************************************************/ +/* + Init the 3DES block cipher context for CBC-EDE mode. + IV should point to 8 bytes of initialization vector + Key should point to 24 bytes of data +*/ +int32_t psDes3Init(psDes3_t *des3, const unsigned char IV[DES3_IVLEN], + const unsigned char key[DES3_KEYLEN]) +{ + int32_t x, err; + +#ifdef CRYPTO_ASSERT + if (IV == NULL || key == NULL || des3 == NULL) { + psTraceCrypto("Bad args to psDes3Init\n"); + return PS_ARG_FAIL; + } +#endif + memset(des3, 0x0, sizeof(psDes3_t)); + /* setup cipher */ + if ((err = psDes3InitKey(key, &des3->key)) != PS_SUCCESS) { + return err; + } + /* copy IV */ + for (x = 0; x < DES3_BLOCKLEN; x++) { + des3->IV[x] = IV[x]; + } + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Encrypt a buffer using 3DES-EDE-CBC + (Encrypt Decrypt Encrypt and Cipher Block Chaining) + len must be a multiple of blockLen (8 bytes) +*/ +void psDes3Encrypt(psDes3_t *des3, const unsigned char *pt, + unsigned char *ct, uint32_t len) +{ + uint32_t i, x; + unsigned char tmp[DES3_BLOCKLEN]; + +#ifdef CRYPTO_ASSERT + if (pt == NULL || ct == NULL || des3 == NULL || (len & 0x7) != 0) { + psTraceCrypto("Bad args to psDes3Encrypt\n"); + return; + } +#endif + + for (i = 0; i < len; i += DES3_BLOCKLEN) { + /* xor IV against plaintext */ + for (x = 0; x < DES3_BLOCKLEN; x++) { + tmp[x] = pt[x] ^ des3->IV[x]; + } + /* encrypt */ + psDes3EncryptBlock(tmp, ct, &des3->key); + + /* store IV [ciphertext] for a future block */ + for (x = 0; x < DES3_BLOCKLEN; x++) { + des3->IV[x] = ct[x]; + } + ct += DES3_BLOCKLEN; + pt += DES3_BLOCKLEN; + } + + memzero_s(tmp, sizeof(tmp)); +} + +/******************************************************************************/ +/* + Decrypt a buffer using 3DES-EDE-CBC + (Encrypt Decrypt Encrypt and Cipher Block Chaining) + len must be a multiple of blockLen (8 bytes) +*/ +void psDes3Decrypt(psDes3_t *des3, const unsigned char *ct, + unsigned char *pt, uint32_t len) +{ + uint32_t i, x; + unsigned char tmp[DES3_BLOCKLEN], tmp2[DES3_BLOCKLEN]; + +#ifdef CRYPTO_ASSERT + if (pt == NULL || ct == NULL || des3 == NULL || (len & 0x7) != 0) { + psTraceCrypto("Bad args to psDes3Decrypt\n"); + return; + } +#endif + + for (i = 0; i < len; i += DES3_BLOCKLEN) { + /* decrypt the block from ct into tmp */ + psDes3DecryptBlock(ct, tmp, &des3->key); + /* xor IV against the plaintext of the previous step */ + for (x = 0; x < DES3_BLOCKLEN; x++) { + /* copy CT in case ct == pt */ + tmp2[x] = ct[x]; + /* actually decrypt the byte */ + pt[x] = tmp[x] ^ des3->IV[x]; + } + /* replace IV with this current ciphertext */ + for (x = 0; x < DES3_BLOCKLEN; x++) { + des3->IV[x] = tmp2[x]; + } + ct += DES3_BLOCKLEN; + pt += DES3_BLOCKLEN; + } + memzero_s(tmp, sizeof(tmp)); + memzero_s(tmp2, sizeof(tmp2)); +} + +/******************************************************************************/ + +void psDes3Clear(psDes3_t *des3) +{ + memzero_s(des3, sizeof(psDes3_t)); +} + +/******************************************************************************/ +/* + We don't validate DES keys against the following known weak keys. + Astronomically small chances of randomly getting a weak key + with 3DES. http://www.rsasecurity.com/rsalabs/faq/3-2-4.html + + http://www.itl.nist.gov/fipspubs/fip74.htm + 1. E001E00lFl0lFl0l 11. 01E001E00lFl0lFl + 2. FElFFElFFEOEFEOE 12. 1FFElFFEOEFEOEFE + 3. E01FE01FF10EF10E 13. 1FE01FEOOEF10EF1 + 4. 01FE01FE01FE01FE 14. FE01FE01FE01FE01 + 5. 011F011F0l0E010E 15. 1F011F0l0E0l0E01 + 6. E0FEE0FEFlFEFlFE 16. FEE0FEE0FEFlFEF1 + 7. 0101010101010101 + 8. FEFEFEFEFEFEFEFE + 9. E0E0E0E0FlFlFlFl + 10. lFlFlFlF0E0E0E0E +*/ +static int32 psDes3InitKey(const unsigned char key[DES3_KEYLEN], psDes3Key_t *skey) +{ + if (key == NULL || skey == NULL) { + psTraceCrypto("Arg failure to psDes3InitKey\n"); + return PS_ARG_FAIL; + } + + deskey(key, EN0, skey->ek[0]); + deskey(key+8, DE1, skey->ek[1]); + deskey(key+16, EN0, skey->ek[2]); + + deskey(key, DE1, skey->dk[2]); + deskey(key+8, EN0, skey->dk[1]); + deskey(key+16, DE1, skey->dk[0]); + + return PS_SUCCESS; +} + +static void psDes3EncryptBlock(const unsigned char *pt, unsigned char *ct, + psDes3Key_t *key) +{ + uint32 work[2]; + + LOAD32H(work[0], pt+0); + LOAD32H(work[1], pt+4); + desfunc(work, key->ek[0]); + desfunc(work, key->ek[1]); + desfunc(work, key->ek[2]); + STORE32H(work[0],ct+0); + STORE32H(work[1],ct+4); +} + +static void psDes3DecryptBlock(const unsigned char *ct, unsigned char *pt, + psDes3Key_t *key) +{ + uint32 work[2]; + + LOAD32H(work[0], ct+0); + LOAD32H(work[1], ct+4); + desfunc(work, key->dk[0]); + desfunc(work, key->dk[1]); + desfunc(work, key->dk[2]); + STORE32H(work[0],pt+0); + STORE32H(work[1],pt+4); +} + +#endif /* USE_MATRIX_3DES */ + +/******************************************************************************/ + diff --git a/crypto/symmetric/idea.c b/crypto/symmetric/idea.c new file mode 100644 index 0000000..de268d9 --- /dev/null +++ b/crypto/symmetric/idea.c @@ -0,0 +1,319 @@ +/** + * @file idea.c + * @version $Format:%h%d$ + * + * IDEA-CBC. This code is based on Xuejia Lai: On the Design and Security of. + * Block Ciphers, ETH Series in Information Processing, vol. 1, + * Hartung-Gorre Verlag, Konstanz, Switzerland, 1992. Another source + * was Bruce Schneier: Applied Cryptography, John Wiley & Sons, 1994 + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_MATRIX_IDEA + +/******************************************************************************/ + +#define LOAD16H(x, y) { \ +x = ((uint16)((y)[0] & 255)<<8) | ((uint16)((y)[1] & 255)); \ +} + +/* Performs the "multiplication" operation of IDEA: returns a*b mod 65537, + where a and b are first converted to 65536 if they are zero, and result + 65536 is converted to zero. Both inputs should be less than 65536. + Only the lower 16 bits of result are significant; other bits are garbage. + */ + +static __inline uint32 idea_mulop(uint32 a, uint32 b) +{ + uint32 ab = a * b; + if (ab != 0) + { + uint32 lo = ab & 0xffff; + uint32 hi = (ab >> 16) & 0xffff; + return (lo - hi) + (lo < hi); + } + if (a == 0) + return 1 - b; + return 1 - a; +} + +/* Computes the multiplicative inverse of a modulo 65537. The algorithm + used is the Euclid's. */ + +static __inline uint32 idea_mulinv(uint32 a) +{ + long n1, n2, q, r, b1, b2, t; + if (a == 0) + return 0; + + n1 = 65537; n2 = (long)a; b2 = 1; b1 = 0; + do + { + r = n1 % n2; + q = (n1 - r) / n2; + if (r == 0) + { + if (b2 < 0) + b2 += 65537; + } + else + { + n1 = n2; + n2 = r; + t = b2; + b2 = b1 - q * b2; + b1 = t; + } + } + while (r != 0); + + return (uint32)b2; +} + +static void idea_transform(uint32 l, uint32 r, uint32 *output, + int for_encryption, psIdeaKey_t *c) +{ + unsigned int round; + uint16 *keys; + uint32 t1, t2, x1, x2, x3, x4; + + keys = c->key_schedule; + x1 = l >> 16; + x2 = l; + x3 = r >> 16; + x4 = r; + for (round = 0; round < 8; round++) + { + x1 = idea_mulop(x1 & 0xffff, keys[0]); + x3 = x3 + keys[2]; + x4 = idea_mulop(x4 & 0xffff, keys[3]); + x2 = x2 + keys[1]; + t1 = x1 ^ x3; + t2 = x2 ^ x4; + t1 = idea_mulop(t1 & 0xffff, keys[4]); + t2 = t1 + t2; + t2 = idea_mulop(t2 & 0xffff, keys[5]); + t1 = t1 + t2; + x1 = x1 ^ t2; + x4 = x4 ^ t1; + t1 = t1 ^ x2; + x2 = t2 ^ x3; + x3 = t1; + keys += 6; + } + x1 = idea_mulop(x1 & 0xffff, keys[0]); + x3 = (x2 + keys[2]) & 0xffff; + x2 = t1 + keys[1]; /* t1 == old x3 */ + x4 = idea_mulop(x4 & 0xffff, keys[3]); + output[0] = (x1 << 16) | (x2 & 0xffff); + output[1] = (x3 << 16) | (x4 & 0xffff); +} + +static int32_t psIdeaInitKey(const unsigned char key[IDEA_KEYLEN], + psIdeaKey_t *skey) +{ + int i; + uint16 *keys; + + /* Get pointer to the keys. */ + keys = skey->key_schedule; + + /* Keys for the first round are taken from the user-supplied key. */ + for (i = 0; i < 8; i++) { + LOAD16H(keys[i], key + 2 * i); + } + + /* Each round uses the key of the previous key, rotated to the left by 25 + bits. The last four keys (output transform) are the first four keys + from what would be the ninth round. */ + for (i = 8; i < 52; i++) { + if ((i & 7) == 0) { + keys += 8; + } + keys[i & 7] = ((keys[((i + 1) & 7) - 8] << 9) | + (keys[((i + 2) & 7) - 8] >> 7)) & 0xffff; + } + + return 0; +} + +/******************************************************************************/ +/* Sets idea key and IV for CBC crypto */ +int32_t psIdeaInit(psIdea_t *idea, const unsigned char IV[IDEA_IVLEN], + const unsigned char key[IDEA_KEYLEN]) +{ + int32_t err; + + if (IV == NULL || key == NULL || idea == NULL) { + psTraceCrypto("psIdeaInit arg fail\n"); + return PS_ARG_FAIL; + } + memset(idea, 0x0, sizeof(psIdea_t)); + /* setup cipher */ + if ((err = psIdeaInitKey(key, &idea->key)) + != PS_SUCCESS) { + return err; + } + /* copy IV */ + LOAD32H(idea->IV[0], IV); + LOAD32H(idea->IV[1], IV + 4); + return PS_SUCCESS; + +} + +/******************************************************************************/ + +void psIdeaDecrypt(psIdea_t *idea, const unsigned char *ct, + unsigned char *pt, uint32_t len) +{ + psIdeaKey_t *key; + uint16 *keys; + uint16 temp[52]; + uint32 tmp[2]; + uint32 l, r, iv[2], processed; + int i; + + + key = &idea->key; + processed = len; + iv[0] = idea->IV[0]; + iv[1] = idea->IV[1]; + + /* Our mechanism doesn't distinguish encrypt from decrypt at the init + stage so we wait until decrypt is called to invert the first time */ + if (idea->inverted == 0) { + keys = key->key_schedule; + +#define MULINV(x,y) temp[x] = idea_mulinv(keys[y]) +#define ADDINV(x,y) temp[x] = (65536 - keys[y]) & 0xFFFF; +#define STRAIG(x,y) temp[x] = keys[y] + + MULINV(0, 48); + ADDINV(1, 49); + ADDINV(2, 50); + MULINV(3, 51); + + STRAIG(4, 46); + STRAIG(5, 47); + + for (i = 6; i < 48; i += 6) { + MULINV(i, 48 - i); + ADDINV(i + 1, 48 - i + 2); + ADDINV(i + 2, 48 - i + 1); + MULINV(i + 3, 48 - i + 3); + STRAIG(i + 4, 42 - i + 4); + STRAIG(i + 5, 42 - i + 5); + } + + MULINV(48, 0); + ADDINV(49, 1); + ADDINV(50, 2); + MULINV(51, 3); + +#undef MULINV +#undef ADDINV +#undef STRAIG + + /* Copy the new key to replace the original and replace the + temporal data with zeros. */ + + memcpy(key->key_schedule, temp, sizeof(uint16) * 52); + memset(temp, 0, sizeof(uint16) * 52); + idea->inverted = 1; + } + + while (processed) { + LOAD32H(l, ct); + LOAD32H(r, ct + 4); + + idea_transform(l, r, tmp, 0, &idea->key); + + tmp[0] ^= iv[0]; + tmp[1] ^= iv[1]; + + STORE32H(tmp[0], pt); + pt += 4; + STORE32H(tmp[1], pt); + pt += 4; + + iv[0] = l; + iv[1] = r; + + ct += 8; + processed -= 8; + } + idea->IV[0] = iv[0]; + idea->IV[1] = iv[1]; +} + +/******************************************************************************/ + +void psIdeaEncrypt(psIdea_t *idea, const unsigned char *pt, + unsigned char *ct, uint32_t len) +{ + uint32 l, r, iv[2], processed; + + processed = len; + iv[0] = idea->IV[0]; + iv[1] = idea->IV[1]; + + while (processed) { + LOAD32H(l, pt); + l = l ^ iv[0]; + + LOAD32H(r, pt + 4); + r = r ^ iv[1]; + + idea_transform(l, r, iv, 1, &idea->key); + + STORE32H(iv[0], ct); + ct += 4; + STORE32H(iv[1], ct); + ct += 4; + + pt += 8; + processed -= 8; + } + + idea->IV[0] = iv[0]; + idea->IV[1] = iv[1]; +} + +/******************************************************************************/ + +void psIdeaClear(psIdea_t *idea) +{ + memzero_s(idea, sizeof(psIdea_t)); +} + +#endif /* USE_MATRIX_IDEA */ + +/******************************************************************************/ + diff --git a/crypto/symmetric/rc2.c b/crypto/symmetric/rc2.c new file mode 100644 index 0000000..5f8ba5e --- /dev/null +++ b/crypto/symmetric/rc2.c @@ -0,0 +1,320 @@ +/** + * @file rc2.c + * @version $Format:%h%d$ + * + * rc2 cipher implementation. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_MATRIX_RC2 + +/******************************************************************************/ + +static int32_t psRc2InitKey(const unsigned char *key, uint8_t keylen, + uint8_t rds, psRc2Key_t *skey); +static void psRc2EncryptBlock(const unsigned char *pt, unsigned char *ct, + psRc2Key_t *skey); +static void psRc2DecryptBlock(const unsigned char *ct, unsigned char *pt, + psRc2Key_t *skey); + +/* 256-entry permutation table, probably derived somehow from pi */ +static const unsigned char permute[256] = { + 217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157, + 198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162, + 23,154, 89,245,135,179, 79, 19, 97, 69,109,141, 9,129,125, 50, + 189,143, 64,235,134,183,123, 11,240,149, 33, 34, 92,107, 78,130, + 84,214,101,147,206, 96,178, 28,115, 86,192, 20,167,140,241,220, + 18,117,202, 31, 59,190,228,209, 66, 61,212, 48,163, 60,182, 38, + 111,191, 14,218, 70,105, 7, 87, 39,242, 29,155,188,148, 67, 3, + 248, 17,199,246,144,239, 62,231, 6,195,213, 47,200,102, 30,215, + 8,232,234,222,128, 82,238,247,132,170,114,172, 53, 77,106, 42, + 150, 26,210,113, 90, 21, 73,116, 75,159,208, 94, 4, 24,164,236, + 194,224, 65,110, 15, 81,203,204, 36,145,175, 80,161,244,112, 57, + 153,124, 58,133, 35,184,180,122,252, 2, 54, 91, 37, 85,151, 49, + 45, 93,250,152,227,138,146,174, 5,223, 41, 16,103,108,186,201, + 211, 0,230,207,225,158,168, 44, 99, 22, 1, 63, 88,226,137,169, + 13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46, + 197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173 +}; + +/******************************************************************************/ + +int32_t psRc2Init(psRc2Cbc_t *ctx, const unsigned char *IV, + const unsigned char *key, uint8_t keylen) +{ + int32 x, err; + + if (IV == NULL || key == NULL || ctx == NULL) { + psTraceCrypto("psRc2Init arg fail\n"); + return PS_ARG_FAIL; + } + /* setup cipher */ + if ((err = psRc2InitKey(key, keylen, 0, &ctx->key)) != PS_SUCCESS) { + return err; + } + /* copy IV */ + for (x = 0; x < RC2_BLOCKLEN; x++) { + ctx->IV[x] = IV[x]; + } + return PS_SUCCESS; +} + +/******************************************************************************/ + +int32_t psRc2Encrypt(psRc2Cbc_t *ctx, const unsigned char *pt, + unsigned char *ct, uint32_t len) +{ + int32 x; + uint32 i; + unsigned char tmp[RC2_BLOCKLEN]; + + if (pt == NULL || ct == NULL || ctx == NULL || (len & 0x7) != 0) { + psTraceCrypto("Bad parameters to psRc2Encrypt\n"); + return PS_ARG_FAIL; + } + + for (i = 0; i < len; i += RC2_BLOCKLEN) { + /* xor IV against plaintext */ + for (x = 0; x < RC2_BLOCKLEN; x++) { + tmp[x] = pt[x] ^ ctx->IV[x]; + } + /* encrypt */ + psRc2EncryptBlock(tmp, ct, &ctx->key); + /* store IV [ciphertext] for a future block */ + for (x = 0; x < RC2_BLOCKLEN; x++) { + ctx->IV[x] = ct[x]; + } + ct += RC2_BLOCKLEN; + pt += RC2_BLOCKLEN; + } + + memset(tmp, 0x0, sizeof(tmp)); + return len; +} + +/******************************************************************************/ + +int32_t psRc2Decrypt(psRc2Cbc_t *ctx, const unsigned char *ct, + unsigned char *pt, uint32_t len) +{ + int32 x; + uint32 i; + unsigned char tmp[RC2_BLOCKLEN], tmp2[RC2_BLOCKLEN]; + + if (pt == NULL || ct == NULL || ctx == NULL || (len & 0x7) != 0) { + psTraceCrypto("Bad parameters to psRc2Decrypt\n"); + return PS_ARG_FAIL; + } + for (i = 0; i < len; i += RC2_BLOCKLEN) { + /* decrypt the block from ct into tmp */ + psRc2DecryptBlock(ct, tmp, &ctx->key); + /* xor IV against the plaintext of the previous step */ + for (x = 0; x < RC2_BLOCKLEN; x++) { + /* copy CT in case ct == pt */ + tmp2[x] = ct[x]; + /* actually decrypt the byte */ + pt[x] = tmp[x] ^ ctx->IV[x]; + } + /* replace IV with this current ciphertext */ + for (x = 0; x < RC2_BLOCKLEN; x++) { + ctx->IV[x] = tmp2[x]; + } + ct += RC2_BLOCKLEN; + pt += RC2_BLOCKLEN; + } + memset(tmp, 0x0, sizeof(tmp)); + memset(tmp2, 0x0, sizeof(tmp2)); + + return len; +} + +/******************************************************************************/ +/** + Initialize the LTC_RC2 block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful +*/ +static int32_t psRc2InitKey(const unsigned char *key, uint8_t keylen, + uint8_t num_rounds, psRc2Key_t *ctx) +{ + unsigned char tmp[128]; + uint32_t *xkey; + uint32_t T8, TM; + int32_t i, bits; + + //if (keylen < 8 || keylen > 128) { + // return PS_ARG_FAIL; + //} + + if (num_rounds != 0 && num_rounds != 16) { + return PS_ARG_FAIL; + } + + xkey = ctx->xkey; + for (i = 0; i < (int32)keylen; i++) { + tmp[i] = key[i] & 255; + } + + /* Phase 1: Expand input key to 128 bytes */ + if (keylen < 128) { + for (i = keylen; i < 128; i++) { + tmp[i] = permute[(tmp[i - 1] + tmp[i - keylen]) & 255]; + } + } + + /* Phase 2 - reduce effective key size to "bits" */ + bits = keylen<<3; + T8 = (uint32_t)(bits+7)>>3; + TM = (255 >> (uint32_t)(7 & -bits)); + tmp[128 - T8] = permute[tmp[128 - T8] & TM]; + for (i = 127 - T8; i >= 0; i--) { + tmp[i] = permute[tmp[i + 1] ^ tmp[i + T8]]; + } + + /* Phase 3 - copy to xkey in little-endian order */ + for (i = 0; i < 64; i++) { + xkey[i] = (uint32_t)tmp[2*i] + ((uint32_t)tmp[2*i+1] << 8); + } + + return PS_SUCCESS; +} + +/******************************************************************************/ +/** + Encrypts a block of text with LTC_RC2 + @param pt The input plaintext (8 bytes) + @param ct The output ciphertext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +static void psRc2EncryptBlock(const unsigned char *pt, unsigned char *ct, + psRc2Key_t *ctx) +{ + uint32_t *xkey; + uint32_t x76, x54, x32, x10, i; + + xkey = ctx->xkey; + x76 = ((uint32_t)pt[7] << 8) + (uint32_t)pt[6]; + x54 = ((uint32_t)pt[5] << 8) + (uint32_t)pt[4]; + x32 = ((uint32_t)pt[3] << 8) + (uint32_t)pt[2]; + x10 = ((uint32_t)pt[1] << 8) + (uint32_t)pt[0]; + + for (i = 0; i < 16; i++) { + x10 = (x10 + (x32 & ~x76) + (x54 & x76) + xkey[4*i+0]) & 0xFFFF; + x10 = ((x10 << 1) | (x10 >> 15)); + + x32 = (x32 + (x54 & ~x10) + (x76 & x10) + xkey[4*i+1]) & 0xFFFF; + x32 = ((x32 << 2) | (x32 >> 14)); + + x54 = (x54 + (x76 & ~x32) + (x10 & x32) + xkey[4*i+2]) & 0xFFFF; + x54 = ((x54 << 3) | (x54 >> 13)); + + x76 = (x76 + (x10 & ~x54) + (x32 & x54) + xkey[4*i+3]) & 0xFFFF; + x76 = ((x76 << 5) | (x76 >> 11)); + + if (i == 4 || i == 10) { + x10 = (x10 + xkey[x76 & 63]) & 0xFFFF; + x32 = (x32 + xkey[x10 & 63]) & 0xFFFF; + x54 = (x54 + xkey[x32 & 63]) & 0xFFFF; + x76 = (x76 + xkey[x54 & 63]) & 0xFFFF; + } + } + + ct[0] = (unsigned char)x10; + ct[1] = (unsigned char)(x10 >> 8); + ct[2] = (unsigned char)x32; + ct[3] = (unsigned char)(x32 >> 8); + ct[4] = (unsigned char)x54; + ct[5] = (unsigned char)(x54 >> 8); + ct[6] = (unsigned char)x76; + ct[7] = (unsigned char)(x76 >> 8); +} + +/******************************************************************************/ +/** + Decrypts a block of text with LTC_RC2 + @param ct The input ciphertext (8 bytes) + @param pt The output plaintext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +static void psRc2DecryptBlock(const unsigned char *ct, unsigned char *pt, + psRc2Key_t *ctx) +{ + uint32_t x76, x54, x32, x10; + uint32_t *xkey; + int i; + + xkey = ctx->xkey; + + x76 = ((uint32_t)ct[7] << 8) + (uint32_t)ct[6]; + x54 = ((uint32_t)ct[5] << 8) + (uint32_t)ct[4]; + x32 = ((uint32_t)ct[3] << 8) + (uint32_t)ct[2]; + x10 = ((uint32_t)ct[1] << 8) + (uint32_t)ct[0]; + + for (i = 15; i >= 0; i--) { + if (i == 4 || i == 10) { + x76 = (x76 - xkey[x54 & 63]) & 0xFFFF; + x54 = (x54 - xkey[x32 & 63]) & 0xFFFF; + x32 = (x32 - xkey[x10 & 63]) & 0xFFFF; + x10 = (x10 - xkey[x76 & 63]) & 0xFFFF; + } + + x76 = ((x76 << 11) | (x76 >> 5)); + x76 = (x76 - ((x10 & ~x54) + (x32 & x54) + xkey[4*i+3])) & 0xFFFF; + + x54 = ((x54 << 13) | (x54 >> 3)); + x54 = (x54 - ((x76 & ~x32) + (x10 & x32) + xkey[4*i+2])) & 0xFFFF; + + x32 = ((x32 << 14) | (x32 >> 2)); + x32 = (x32 - ((x54 & ~x10) + (x76 & x10) + xkey[4*i+1])) & 0xFFFF; + + x10 = ((x10 << 15) | (x10 >> 1)); + x10 = (x10 - ((x32 & ~x76) + (x54 & x76) + xkey[4*i+0])) & 0xFFFF; + } + + pt[0] = (unsigned char)x10; + pt[1] = (unsigned char)(x10 >> 8); + pt[2] = (unsigned char)x32; + pt[3] = (unsigned char)(x32 >> 8); + pt[4] = (unsigned char)x54; + pt[5] = (unsigned char)(x54 >> 8); + pt[6] = (unsigned char)x76; + pt[7] = (unsigned char)(x76 >> 8); +} + +#endif /* USE_RC2 */ + +/******************************************************************************/ + diff --git a/crypto/symmetric/seed.c b/crypto/symmetric/seed.c new file mode 100644 index 0000000..61657c5 --- /dev/null +++ b/crypto/symmetric/seed.c @@ -0,0 +1,403 @@ +/** + * @file seed.c + * @version $Format:%h%d$ + * + * seed implementation of SEED derived from RFC4269. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +#ifdef USE_MATRIX_SEED + +/******************************************************************************/ + +static int32_t psSeedInitKey(const unsigned char key[SEED_KEYLEN], + psSeedKey_t *skey); +static void psSeedEncryptBlock(const unsigned char *pt, unsigned char *ct, + psSeedKey_t *skey); +static void psSeedDecryptBlock(const unsigned char *ct, unsigned char *pt, + psSeedKey_t *skey); + +static const uint32_t SS0[256] = { +0x2989A1A8UL,0x05858184UL,0x16C6D2D4UL,0x13C3D3D0UL,0x14445054UL,0x1D0D111CUL,0x2C8CA0ACUL,0x25052124UL, +0x1D4D515CUL,0x03434340UL,0x18081018UL,0x1E0E121CUL,0x11415150UL,0x3CCCF0FCUL,0x0ACAC2C8UL,0x23436360UL, +0x28082028UL,0x04444044UL,0x20002020UL,0x1D8D919CUL,0x20C0E0E0UL,0x22C2E2E0UL,0x08C8C0C8UL,0x17071314UL, +0x2585A1A4UL,0x0F8F838CUL,0x03030300UL,0x3B4B7378UL,0x3B8BB3B8UL,0x13031310UL,0x12C2D2D0UL,0x2ECEE2ECUL, +0x30407070UL,0x0C8C808CUL,0x3F0F333CUL,0x2888A0A8UL,0x32023230UL,0x1DCDD1DCUL,0x36C6F2F4UL,0x34447074UL, +0x2CCCE0ECUL,0x15859194UL,0x0B0B0308UL,0x17475354UL,0x1C4C505CUL,0x1B4B5358UL,0x3D8DB1BCUL,0x01010100UL, +0x24042024UL,0x1C0C101CUL,0x33437370UL,0x18889098UL,0x10001010UL,0x0CCCC0CCUL,0x32C2F2F0UL,0x19C9D1D8UL, +0x2C0C202CUL,0x27C7E3E4UL,0x32427270UL,0x03838380UL,0x1B8B9398UL,0x11C1D1D0UL,0x06868284UL,0x09C9C1C8UL, +0x20406060UL,0x10405050UL,0x2383A3A0UL,0x2BCBE3E8UL,0x0D0D010CUL,0x3686B2B4UL,0x1E8E929CUL,0x0F4F434CUL, +0x3787B3B4UL,0x1A4A5258UL,0x06C6C2C4UL,0x38487078UL,0x2686A2A4UL,0x12021210UL,0x2F8FA3ACUL,0x15C5D1D4UL, +0x21416160UL,0x03C3C3C0UL,0x3484B0B4UL,0x01414140UL,0x12425250UL,0x3D4D717CUL,0x0D8D818CUL,0x08080008UL, +0x1F0F131CUL,0x19899198UL,0x00000000UL,0x19091118UL,0x04040004UL,0x13435350UL,0x37C7F3F4UL,0x21C1E1E0UL, +0x3DCDF1FCUL,0x36467274UL,0x2F0F232CUL,0x27072324UL,0x3080B0B0UL,0x0B8B8388UL,0x0E0E020CUL,0x2B8BA3A8UL, +0x2282A2A0UL,0x2E4E626CUL,0x13839390UL,0x0D4D414CUL,0x29496168UL,0x3C4C707CUL,0x09090108UL,0x0A0A0208UL, +0x3F8FB3BCUL,0x2FCFE3ECUL,0x33C3F3F0UL,0x05C5C1C4UL,0x07878384UL,0x14041014UL,0x3ECEF2FCUL,0x24446064UL, +0x1ECED2DCUL,0x2E0E222CUL,0x0B4B4348UL,0x1A0A1218UL,0x06060204UL,0x21012120UL,0x2B4B6368UL,0x26466264UL, +0x02020200UL,0x35C5F1F4UL,0x12829290UL,0x0A8A8288UL,0x0C0C000CUL,0x3383B3B0UL,0x3E4E727CUL,0x10C0D0D0UL, +0x3A4A7278UL,0x07474344UL,0x16869294UL,0x25C5E1E4UL,0x26062224UL,0x00808080UL,0x2D8DA1ACUL,0x1FCFD3DCUL, +0x2181A1A0UL,0x30003030UL,0x37073334UL,0x2E8EA2ACUL,0x36063234UL,0x15051114UL,0x22022220UL,0x38083038UL, +0x34C4F0F4UL,0x2787A3A4UL,0x05454144UL,0x0C4C404CUL,0x01818180UL,0x29C9E1E8UL,0x04848084UL,0x17879394UL, +0x35053134UL,0x0BCBC3C8UL,0x0ECEC2CCUL,0x3C0C303CUL,0x31417170UL,0x11011110UL,0x07C7C3C4UL,0x09898188UL, +0x35457174UL,0x3BCBF3F8UL,0x1ACAD2D8UL,0x38C8F0F8UL,0x14849094UL,0x19495158UL,0x02828280UL,0x04C4C0C4UL, +0x3FCFF3FCUL,0x09494148UL,0x39093138UL,0x27476364UL,0x00C0C0C0UL,0x0FCFC3CCUL,0x17C7D3D4UL,0x3888B0B8UL, +0x0F0F030CUL,0x0E8E828CUL,0x02424240UL,0x23032320UL,0x11819190UL,0x2C4C606CUL,0x1BCBD3D8UL,0x2484A0A4UL, +0x34043034UL,0x31C1F1F0UL,0x08484048UL,0x02C2C2C0UL,0x2F4F636CUL,0x3D0D313CUL,0x2D0D212CUL,0x00404040UL, +0x3E8EB2BCUL,0x3E0E323CUL,0x3C8CB0BCUL,0x01C1C1C0UL,0x2A8AA2A8UL,0x3A8AB2B8UL,0x0E4E424CUL,0x15455154UL, +0x3B0B3338UL,0x1CCCD0DCUL,0x28486068UL,0x3F4F737CUL,0x1C8C909CUL,0x18C8D0D8UL,0x0A4A4248UL,0x16465254UL, +0x37477374UL,0x2080A0A0UL,0x2DCDE1ECUL,0x06464244UL,0x3585B1B4UL,0x2B0B2328UL,0x25456164UL,0x3ACAF2F8UL, +0x23C3E3E0UL,0x3989B1B8UL,0x3181B1B0UL,0x1F8F939CUL,0x1E4E525CUL,0x39C9F1F8UL,0x26C6E2E4UL,0x3282B2B0UL, +0x31013130UL,0x2ACAE2E8UL,0x2D4D616CUL,0x1F4F535CUL,0x24C4E0E4UL,0x30C0F0F0UL,0x0DCDC1CCUL,0x08888088UL, +0x16061214UL,0x3A0A3238UL,0x18485058UL,0x14C4D0D4UL,0x22426260UL,0x29092128UL,0x07070304UL,0x33033330UL, +0x28C8E0E8UL,0x1B0B1318UL,0x05050104UL,0x39497178UL,0x10809090UL,0x2A4A6268UL,0x2A0A2228UL,0x1A8A9298UL +}; + +static const uint32 SS1[256] = { +0x38380830UL,0xE828C8E0UL,0x2C2D0D21UL,0xA42686A2UL,0xCC0FCFC3UL,0xDC1ECED2UL,0xB03383B3UL,0xB83888B0UL, +0xAC2F8FA3UL,0x60204060UL,0x54154551UL,0xC407C7C3UL,0x44044440UL,0x6C2F4F63UL,0x682B4B63UL,0x581B4B53UL, +0xC003C3C3UL,0x60224262UL,0x30330333UL,0xB43585B1UL,0x28290921UL,0xA02080A0UL,0xE022C2E2UL,0xA42787A3UL, +0xD013C3D3UL,0x90118191UL,0x10110111UL,0x04060602UL,0x1C1C0C10UL,0xBC3C8CB0UL,0x34360632UL,0x480B4B43UL, +0xEC2FCFE3UL,0x88088880UL,0x6C2C4C60UL,0xA82888A0UL,0x14170713UL,0xC404C4C0UL,0x14160612UL,0xF434C4F0UL, +0xC002C2C2UL,0x44054541UL,0xE021C1E1UL,0xD416C6D2UL,0x3C3F0F33UL,0x3C3D0D31UL,0x8C0E8E82UL,0x98188890UL, +0x28280820UL,0x4C0E4E42UL,0xF436C6F2UL,0x3C3E0E32UL,0xA42585A1UL,0xF839C9F1UL,0x0C0D0D01UL,0xDC1FCFD3UL, +0xD818C8D0UL,0x282B0B23UL,0x64264662UL,0x783A4A72UL,0x24270723UL,0x2C2F0F23UL,0xF031C1F1UL,0x70324272UL, +0x40024242UL,0xD414C4D0UL,0x40014141UL,0xC000C0C0UL,0x70334373UL,0x64274763UL,0xAC2C8CA0UL,0x880B8B83UL, +0xF437C7F3UL,0xAC2D8DA1UL,0x80008080UL,0x1C1F0F13UL,0xC80ACAC2UL,0x2C2C0C20UL,0xA82A8AA2UL,0x34340430UL, +0xD012C2D2UL,0x080B0B03UL,0xEC2ECEE2UL,0xE829C9E1UL,0x5C1D4D51UL,0x94148490UL,0x18180810UL,0xF838C8F0UL, +0x54174753UL,0xAC2E8EA2UL,0x08080800UL,0xC405C5C1UL,0x10130313UL,0xCC0DCDC1UL,0x84068682UL,0xB83989B1UL, +0xFC3FCFF3UL,0x7C3D4D71UL,0xC001C1C1UL,0x30310131UL,0xF435C5F1UL,0x880A8A82UL,0x682A4A62UL,0xB03181B1UL, +0xD011C1D1UL,0x20200020UL,0xD417C7D3UL,0x00020202UL,0x20220222UL,0x04040400UL,0x68284860UL,0x70314171UL, +0x04070703UL,0xD81BCBD3UL,0x9C1D8D91UL,0x98198991UL,0x60214161UL,0xBC3E8EB2UL,0xE426C6E2UL,0x58194951UL, +0xDC1DCDD1UL,0x50114151UL,0x90108090UL,0xDC1CCCD0UL,0x981A8A92UL,0xA02383A3UL,0xA82B8BA3UL,0xD010C0D0UL, +0x80018181UL,0x0C0F0F03UL,0x44074743UL,0x181A0A12UL,0xE023C3E3UL,0xEC2CCCE0UL,0x8C0D8D81UL,0xBC3F8FB3UL, +0x94168692UL,0x783B4B73UL,0x5C1C4C50UL,0xA02282A2UL,0xA02181A1UL,0x60234363UL,0x20230323UL,0x4C0D4D41UL, +0xC808C8C0UL,0x9C1E8E92UL,0x9C1C8C90UL,0x383A0A32UL,0x0C0C0C00UL,0x2C2E0E22UL,0xB83A8AB2UL,0x6C2E4E62UL, +0x9C1F8F93UL,0x581A4A52UL,0xF032C2F2UL,0x90128292UL,0xF033C3F3UL,0x48094941UL,0x78384870UL,0xCC0CCCC0UL, +0x14150511UL,0xF83BCBF3UL,0x70304070UL,0x74354571UL,0x7C3F4F73UL,0x34350531UL,0x10100010UL,0x00030303UL, +0x64244460UL,0x6C2D4D61UL,0xC406C6C2UL,0x74344470UL,0xD415C5D1UL,0xB43484B0UL,0xE82ACAE2UL,0x08090901UL, +0x74364672UL,0x18190911UL,0xFC3ECEF2UL,0x40004040UL,0x10120212UL,0xE020C0E0UL,0xBC3D8DB1UL,0x04050501UL, +0xF83ACAF2UL,0x00010101UL,0xF030C0F0UL,0x282A0A22UL,0x5C1E4E52UL,0xA82989A1UL,0x54164652UL,0x40034343UL, +0x84058581UL,0x14140410UL,0x88098981UL,0x981B8B93UL,0xB03080B0UL,0xE425C5E1UL,0x48084840UL,0x78394971UL, +0x94178793UL,0xFC3CCCF0UL,0x1C1E0E12UL,0x80028282UL,0x20210121UL,0x8C0C8C80UL,0x181B0B13UL,0x5C1F4F53UL, +0x74374773UL,0x54144450UL,0xB03282B2UL,0x1C1D0D11UL,0x24250521UL,0x4C0F4F43UL,0x00000000UL,0x44064642UL, +0xEC2DCDE1UL,0x58184850UL,0x50124252UL,0xE82BCBE3UL,0x7C3E4E72UL,0xD81ACAD2UL,0xC809C9C1UL,0xFC3DCDF1UL, +0x30300030UL,0x94158591UL,0x64254561UL,0x3C3C0C30UL,0xB43686B2UL,0xE424C4E0UL,0xB83B8BB3UL,0x7C3C4C70UL, +0x0C0E0E02UL,0x50104050UL,0x38390931UL,0x24260622UL,0x30320232UL,0x84048480UL,0x68294961UL,0x90138393UL, +0x34370733UL,0xE427C7E3UL,0x24240420UL,0xA42484A0UL,0xC80BCBC3UL,0x50134353UL,0x080A0A02UL,0x84078783UL, +0xD819C9D1UL,0x4C0C4C40UL,0x80038383UL,0x8C0F8F83UL,0xCC0ECEC2UL,0x383B0B33UL,0x480A4A42UL,0xB43787B3UL +}; + +static const uint32 SS2[256] = { +0xA1A82989UL,0x81840585UL,0xD2D416C6UL,0xD3D013C3UL,0x50541444UL,0x111C1D0DUL,0xA0AC2C8CUL,0x21242505UL, +0x515C1D4DUL,0x43400343UL,0x10181808UL,0x121C1E0EUL,0x51501141UL,0xF0FC3CCCUL,0xC2C80ACAUL,0x63602343UL, +0x20282808UL,0x40440444UL,0x20202000UL,0x919C1D8DUL,0xE0E020C0UL,0xE2E022C2UL,0xC0C808C8UL,0x13141707UL, +0xA1A42585UL,0x838C0F8FUL,0x03000303UL,0x73783B4BUL,0xB3B83B8BUL,0x13101303UL,0xD2D012C2UL,0xE2EC2ECEUL, +0x70703040UL,0x808C0C8CUL,0x333C3F0FUL,0xA0A82888UL,0x32303202UL,0xD1DC1DCDUL,0xF2F436C6UL,0x70743444UL, +0xE0EC2CCCUL,0x91941585UL,0x03080B0BUL,0x53541747UL,0x505C1C4CUL,0x53581B4BUL,0xB1BC3D8DUL,0x01000101UL, +0x20242404UL,0x101C1C0CUL,0x73703343UL,0x90981888UL,0x10101000UL,0xC0CC0CCCUL,0xF2F032C2UL,0xD1D819C9UL, +0x202C2C0CUL,0xE3E427C7UL,0x72703242UL,0x83800383UL,0x93981B8BUL,0xD1D011C1UL,0x82840686UL,0xC1C809C9UL, +0x60602040UL,0x50501040UL,0xA3A02383UL,0xE3E82BCBUL,0x010C0D0DUL,0xB2B43686UL,0x929C1E8EUL,0x434C0F4FUL, +0xB3B43787UL,0x52581A4AUL,0xC2C406C6UL,0x70783848UL,0xA2A42686UL,0x12101202UL,0xA3AC2F8FUL,0xD1D415C5UL, +0x61602141UL,0xC3C003C3UL,0xB0B43484UL,0x41400141UL,0x52501242UL,0x717C3D4DUL,0x818C0D8DUL,0x00080808UL, +0x131C1F0FUL,0x91981989UL,0x00000000UL,0x11181909UL,0x00040404UL,0x53501343UL,0xF3F437C7UL,0xE1E021C1UL, +0xF1FC3DCDUL,0x72743646UL,0x232C2F0FUL,0x23242707UL,0xB0B03080UL,0x83880B8BUL,0x020C0E0EUL,0xA3A82B8BUL, +0xA2A02282UL,0x626C2E4EUL,0x93901383UL,0x414C0D4DUL,0x61682949UL,0x707C3C4CUL,0x01080909UL,0x02080A0AUL, +0xB3BC3F8FUL,0xE3EC2FCFUL,0xF3F033C3UL,0xC1C405C5UL,0x83840787UL,0x10141404UL,0xF2FC3ECEUL,0x60642444UL, +0xD2DC1ECEUL,0x222C2E0EUL,0x43480B4BUL,0x12181A0AUL,0x02040606UL,0x21202101UL,0x63682B4BUL,0x62642646UL, +0x02000202UL,0xF1F435C5UL,0x92901282UL,0x82880A8AUL,0x000C0C0CUL,0xB3B03383UL,0x727C3E4EUL,0xD0D010C0UL, +0x72783A4AUL,0x43440747UL,0x92941686UL,0xE1E425C5UL,0x22242606UL,0x80800080UL,0xA1AC2D8DUL,0xD3DC1FCFUL, +0xA1A02181UL,0x30303000UL,0x33343707UL,0xA2AC2E8EUL,0x32343606UL,0x11141505UL,0x22202202UL,0x30383808UL, +0xF0F434C4UL,0xA3A42787UL,0x41440545UL,0x404C0C4CUL,0x81800181UL,0xE1E829C9UL,0x80840484UL,0x93941787UL, +0x31343505UL,0xC3C80BCBUL,0xC2CC0ECEUL,0x303C3C0CUL,0x71703141UL,0x11101101UL,0xC3C407C7UL,0x81880989UL, +0x71743545UL,0xF3F83BCBUL,0xD2D81ACAUL,0xF0F838C8UL,0x90941484UL,0x51581949UL,0x82800282UL,0xC0C404C4UL, +0xF3FC3FCFUL,0x41480949UL,0x31383909UL,0x63642747UL,0xC0C000C0UL,0xC3CC0FCFUL,0xD3D417C7UL,0xB0B83888UL, +0x030C0F0FUL,0x828C0E8EUL,0x42400242UL,0x23202303UL,0x91901181UL,0x606C2C4CUL,0xD3D81BCBUL,0xA0A42484UL, +0x30343404UL,0xF1F031C1UL,0x40480848UL,0xC2C002C2UL,0x636C2F4FUL,0x313C3D0DUL,0x212C2D0DUL,0x40400040UL, +0xB2BC3E8EUL,0x323C3E0EUL,0xB0BC3C8CUL,0xC1C001C1UL,0xA2A82A8AUL,0xB2B83A8AUL,0x424C0E4EUL,0x51541545UL, +0x33383B0BUL,0xD0DC1CCCUL,0x60682848UL,0x737C3F4FUL,0x909C1C8CUL,0xD0D818C8UL,0x42480A4AUL,0x52541646UL, +0x73743747UL,0xA0A02080UL,0xE1EC2DCDUL,0x42440646UL,0xB1B43585UL,0x23282B0BUL,0x61642545UL,0xF2F83ACAUL, +0xE3E023C3UL,0xB1B83989UL,0xB1B03181UL,0x939C1F8FUL,0x525C1E4EUL,0xF1F839C9UL,0xE2E426C6UL,0xB2B03282UL, +0x31303101UL,0xE2E82ACAUL,0x616C2D4DUL,0x535C1F4FUL,0xE0E424C4UL,0xF0F030C0UL,0xC1CC0DCDUL,0x80880888UL, +0x12141606UL,0x32383A0AUL,0x50581848UL,0xD0D414C4UL,0x62602242UL,0x21282909UL,0x03040707UL,0x33303303UL, +0xE0E828C8UL,0x13181B0BUL,0x01040505UL,0x71783949UL,0x90901080UL,0x62682A4AUL,0x22282A0AUL,0x92981A8AUL +}; + +static const uint32 SS3[256] = { +0x08303838UL,0xC8E0E828UL,0x0D212C2DUL,0x86A2A426UL,0xCFC3CC0FUL,0xCED2DC1EUL,0x83B3B033UL,0x88B0B838UL, +0x8FA3AC2FUL,0x40606020UL,0x45515415UL,0xC7C3C407UL,0x44404404UL,0x4F636C2FUL,0x4B63682BUL,0x4B53581BUL, +0xC3C3C003UL,0x42626022UL,0x03333033UL,0x85B1B435UL,0x09212829UL,0x80A0A020UL,0xC2E2E022UL,0x87A3A427UL, +0xC3D3D013UL,0x81919011UL,0x01111011UL,0x06020406UL,0x0C101C1CUL,0x8CB0BC3CUL,0x06323436UL,0x4B43480BUL, +0xCFE3EC2FUL,0x88808808UL,0x4C606C2CUL,0x88A0A828UL,0x07131417UL,0xC4C0C404UL,0x06121416UL,0xC4F0F434UL, +0xC2C2C002UL,0x45414405UL,0xC1E1E021UL,0xC6D2D416UL,0x0F333C3FUL,0x0D313C3DUL,0x8E828C0EUL,0x88909818UL, +0x08202828UL,0x4E424C0EUL,0xC6F2F436UL,0x0E323C3EUL,0x85A1A425UL,0xC9F1F839UL,0x0D010C0DUL,0xCFD3DC1FUL, +0xC8D0D818UL,0x0B23282BUL,0x46626426UL,0x4A72783AUL,0x07232427UL,0x0F232C2FUL,0xC1F1F031UL,0x42727032UL, +0x42424002UL,0xC4D0D414UL,0x41414001UL,0xC0C0C000UL,0x43737033UL,0x47636427UL,0x8CA0AC2CUL,0x8B83880BUL, +0xC7F3F437UL,0x8DA1AC2DUL,0x80808000UL,0x0F131C1FUL,0xCAC2C80AUL,0x0C202C2CUL,0x8AA2A82AUL,0x04303434UL, +0xC2D2D012UL,0x0B03080BUL,0xCEE2EC2EUL,0xC9E1E829UL,0x4D515C1DUL,0x84909414UL,0x08101818UL,0xC8F0F838UL, +0x47535417UL,0x8EA2AC2EUL,0x08000808UL,0xC5C1C405UL,0x03131013UL,0xCDC1CC0DUL,0x86828406UL,0x89B1B839UL, +0xCFF3FC3FUL,0x4D717C3DUL,0xC1C1C001UL,0x01313031UL,0xC5F1F435UL,0x8A82880AUL,0x4A62682AUL,0x81B1B031UL, +0xC1D1D011UL,0x00202020UL,0xC7D3D417UL,0x02020002UL,0x02222022UL,0x04000404UL,0x48606828UL,0x41717031UL, +0x07030407UL,0xCBD3D81BUL,0x8D919C1DUL,0x89919819UL,0x41616021UL,0x8EB2BC3EUL,0xC6E2E426UL,0x49515819UL, +0xCDD1DC1DUL,0x41515011UL,0x80909010UL,0xCCD0DC1CUL,0x8A92981AUL,0x83A3A023UL,0x8BA3A82BUL,0xC0D0D010UL, +0x81818001UL,0x0F030C0FUL,0x47434407UL,0x0A12181AUL,0xC3E3E023UL,0xCCE0EC2CUL,0x8D818C0DUL,0x8FB3BC3FUL, +0x86929416UL,0x4B73783BUL,0x4C505C1CUL,0x82A2A022UL,0x81A1A021UL,0x43636023UL,0x03232023UL,0x4D414C0DUL, +0xC8C0C808UL,0x8E929C1EUL,0x8C909C1CUL,0x0A32383AUL,0x0C000C0CUL,0x0E222C2EUL,0x8AB2B83AUL,0x4E626C2EUL, +0x8F939C1FUL,0x4A52581AUL,0xC2F2F032UL,0x82929012UL,0xC3F3F033UL,0x49414809UL,0x48707838UL,0xCCC0CC0CUL, +0x05111415UL,0xCBF3F83BUL,0x40707030UL,0x45717435UL,0x4F737C3FUL,0x05313435UL,0x00101010UL,0x03030003UL, +0x44606424UL,0x4D616C2DUL,0xC6C2C406UL,0x44707434UL,0xC5D1D415UL,0x84B0B434UL,0xCAE2E82AUL,0x09010809UL, +0x46727436UL,0x09111819UL,0xCEF2FC3EUL,0x40404000UL,0x02121012UL,0xC0E0E020UL,0x8DB1BC3DUL,0x05010405UL, +0xCAF2F83AUL,0x01010001UL,0xC0F0F030UL,0x0A22282AUL,0x4E525C1EUL,0x89A1A829UL,0x46525416UL,0x43434003UL, +0x85818405UL,0x04101414UL,0x89818809UL,0x8B93981BUL,0x80B0B030UL,0xC5E1E425UL,0x48404808UL,0x49717839UL, +0x87939417UL,0xCCF0FC3CUL,0x0E121C1EUL,0x82828002UL,0x01212021UL,0x8C808C0CUL,0x0B13181BUL,0x4F535C1FUL, +0x47737437UL,0x44505414UL,0x82B2B032UL,0x0D111C1DUL,0x05212425UL,0x4F434C0FUL,0x00000000UL,0x46424406UL, +0xCDE1EC2DUL,0x48505818UL,0x42525012UL,0xCBE3E82BUL,0x4E727C3EUL,0xCAD2D81AUL,0xC9C1C809UL,0xCDF1FC3DUL, +0x00303030UL,0x85919415UL,0x45616425UL,0x0C303C3CUL,0x86B2B436UL,0xC4E0E424UL,0x8BB3B83BUL,0x4C707C3CUL, +0x0E020C0EUL,0x40505010UL,0x09313839UL,0x06222426UL,0x02323032UL,0x84808404UL,0x49616829UL,0x83939013UL, +0x07333437UL,0xC7E3E427UL,0x04202424UL,0x84A0A424UL,0xCBC3C80BUL,0x43535013UL,0x0A02080AUL,0x87838407UL, +0xC9D1D819UL,0x4C404C0CUL,0x83838003UL,0x8F838C0FUL,0xCEC2CC0EUL,0x0B33383BUL,0x4A42480AUL,0x87B3B437UL +}; + +static const uint32 KCi[16] = { +0x9E3779B9,0x3C6EF373, +0x78DDE6E6,0xF1BBCDCC, +0xE3779B99,0xC6EF3733, +0x8DDE6E67,0x1BBCDCCF, +0x3779B99E,0x6EF3733C, +0xDDE6E678,0xBBCDCCF1, +0x779B99E3,0xEF3733C6, +0xDE6E678D,0xBCDCCF1B +}; + +#define G(x) (SS3[((x)>>24)&255] ^ SS2[((x)>>16)&255] ^ SS1[((x)>>8)&255] ^ SS0[(x)&255]) + +#define F(L1, L2, R1, R2, K1, K2) \ + T2 = G((R1 ^ K1) ^ (R2 ^ K2)); \ + T = G( G(T2 + (R1 ^ K1)) + T2); \ + L2 ^= T; \ + L1 ^= (T + G(T2 + (R1 ^ K1))); \ + +/******************************************************************************/ +/* + Init the SEED block cipher context for CBC-EDE mode. + IV should point to 16 bytes of initialization vector + Key should point to 16 bytes of data +*/ +int32_t psSeedInit(psSeed_t *seed, const unsigned char IV[SEED_IVLEN], + const unsigned char key[SEED_KEYLEN]) +{ + int32_t err; + uint8_t x; + +#ifdef CRYPTO_ASSERT + if (IV == NULL || key == NULL || seed == NULL){ + psTraceCrypto("Bad parameter failure in psSeedInit\n"); + return PS_ARG_FAIL; + } +#endif + /* setup cipher */ + if ((err = psSeedInitKey(key, &seed->key)) != PS_SUCCESS) { + return err; + } + /* copy IV */ + for (x = 0; x < SEED_BLOCKLEN; x++) { + seed->IV[x] = IV[x]; + } + return PS_SUCCESS; +} + +/******************************************************************************/ + +void psSeedEncrypt(psSeed_t *seed, const unsigned char *pt, + unsigned char *ct, uint32_t len) +{ + uint8_t i, x; + unsigned char tmp[SEED_BLOCKLEN]; + +#ifdef CRYPTO_ASSERT + if (pt == NULL || ct == NULL || seed == NULL || (len & 0x7) != 0) { + psTraceCrypto("Bad parameters to psSeedEncrypt\n"); + return; + } +#endif + for (i = 0; i < len; i += SEED_BLOCKLEN) { + for (x = 0; x < SEED_BLOCKLEN; x++) { + tmp[x] = pt[x] ^ seed->IV[x]; + } + psSeedEncryptBlock(tmp, ct, &seed->key); + /* store IV [ciphertext] for a future block */ + for (x = 0; x < SEED_BLOCKLEN; x++) { + seed->IV[x] = ct[x]; + } + ct += SEED_BLOCKLEN; + pt += SEED_BLOCKLEN; + } + memzero_s(tmp, sizeof(tmp)); +} + +/******************************************************************************/ + +void psSeedDecrypt(psSeed_t *seed, const unsigned char *ct, + unsigned char *pt, uint32_t len) +{ + uint8_t i, x; + unsigned char tmp[SEED_BLOCKLEN], tmp2[SEED_BLOCKLEN]; + +#ifdef CRYPTO_ASSERT + if (pt == NULL || ct == NULL || seed == NULL || (len & 0x7) != 0) { + psTraceCrypto("Bad parameters to psSeedDecrypt\n"); + return; + } +#endif + for (i = 0; i < len; i += SEED_BLOCKLEN) { + /* decrypt the block from ct into tmp */ + psSeedDecryptBlock(ct, tmp, &seed->key); + /* xor IV against the plaintext of the previous step */ + for (x = 0; x < SEED_BLOCKLEN; x++) { + /* copy CT in case ct == pt */ + tmp2[x] = ct[x]; + /* actually decrypt the byte */ + pt[x] = tmp[x] ^ seed->IV[x]; + } + /* replace IV with this current ciphertext */ + for (x = 0; x < SEED_BLOCKLEN; x++) { + seed->IV[x] = tmp2[x]; + } + ct += SEED_BLOCKLEN; + pt += SEED_BLOCKLEN; + } + memzero_s(tmp, sizeof(tmp)); + memzero_s(tmp2, sizeof(tmp2)); +} + +/******************************************************************************/ + +void psSeedClear(psSeed_t *seed) +{ + memzero_s(seed, sizeof(psSeed_t)); +} + +/******************************************************************************/ +/** + Initialize the SEED block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param skey The key in as scheduled by this function. + */ +int32_t psSeedInitKey(const unsigned char *key, psSeedKey_t *skey) +{ + int32 i; + uint32 tmp, k1, k2, k3, k4; + + /* load key */ + LOAD32H(k1, key); + LOAD32H(k2, key+4); + LOAD32H(k3, key+8); + LOAD32H(k4, key+12); + + for (i = 0; i < 16; i++) { + skey->K[2*i+0] = G(k1 + k3 - KCi[i]); + skey->K[2*i+1] = G(k2 - k4 + KCi[i]); + if (i&1) { + tmp = k3; + k3 = ((k3 << 8) | (k4 >> 24)) & 0xFFFFFFFF; + k4 = ((k4 << 8) | (tmp >> 24)) & 0xFFFFFFFF; + } else { + tmp = k1; + k1 = ((k1 >> 8) | (k2 << 24)) & 0xFFFFFFFF; + k2 = ((k2 >> 8) | (tmp << 24)) & 0xFFFFFFFF; + } + /* reverse keys for decrypt */ + skey->dK[2*(15-i)+0] = skey->K[2*i+0]; + skey->dK[2*(15-i)+1] = skey->K[2*i+1]; + } + + return PS_SUCCESS; +} + +static void rounds(uint32 *P, uint32 *K) +{ + uint32 T, T2; + int32 i; + for (i = 0; i < 16; i += 2) { + F(P[0], P[1], P[2], P[3], K[0], K[1]); + F(P[2], P[3], P[0], P[1], K[2], K[3]); + K += 4; + } +} + +/******************************************************************************/ +/** + Encrypts a block of text with SEED + @param pt The input plaintext (16 bytes) + @param ct The output ciphertext (16 bytes) + @param skey The key as scheduled +*/ +static void psSeedEncryptBlock(const unsigned char *pt, unsigned char *ct, + psSeedKey_t *skey) +{ + uint32 P[4]; + LOAD32H(P[0], pt); + LOAD32H(P[1], pt+4); + LOAD32H(P[2], pt+8); + LOAD32H(P[3], pt+12); + rounds(P, skey->K); + STORE32H(P[2], ct); + STORE32H(P[3], ct+4); + STORE32H(P[0], ct+8); + STORE32H(P[1], ct+12); +} + +/******************************************************************************/ +/** + Decrypts a block of text with SEED + @param ct The input ciphertext (16 bytes) + @param pt The output plaintext (16 bytes) + @param skey The key as scheduled +*/ +static void psSeedDecryptBlock(const unsigned char *ct, unsigned char *pt, + psSeedKey_t *skey) +{ + uint32 P[4]; + LOAD32H(P[0], ct); + LOAD32H(P[1], ct+4); + LOAD32H(P[2], ct+8); + LOAD32H(P[3], ct+12); + rounds(P, skey->dK); + STORE32H(P[2], pt); + STORE32H(P[3], pt+4); + STORE32H(P[0], pt+8); + STORE32H(P[1], pt+12); +} + +#endif /* USE_MATRIX_SEED */ + +/******************************************************************************/ + diff --git a/crypto/symmetric/symmetric.h b/crypto/symmetric/symmetric.h new file mode 100644 index 0000000..8a2e9cb --- /dev/null +++ b/crypto/symmetric/symmetric.h @@ -0,0 +1,118 @@ +/** + * @file symmetric.h + * @version $Format:%h%d$ + * + * Header for symmetric key API implementations. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_MATRIX_SYMMETRIC +#define _h_MATRIX_SYMMETRIC + +/******************************************************************************/ +/* Forward declarations */ + +#define AES_BLOCKLEN 16 +#define AES_IVLEN AES_BLOCKLEN +#define AES128_KEYLEN 16 +#define AES192_KEYLEN 24 +#define AES256_KEYLEN 32 +#define DES3_BLOCKLEN 8 +#define DES3_IVLEN DES3_BLOCKLEN +#define DES3_KEYLEN 24 +#define IDEA_BLOCKLEN 8 +#define IDEA_IVLEN IDEA_BLOCKLEN +#define IDEA_KEYLEN 16 +#define SEED_BLOCKLEN 16 +#define SEED_IVLEN SEED_BLOCKLEN +#define SEED_KEYLEN 16 +#define CHACHA20POLY1305_IV_FIXED_LENGTH 12 +#define CHACHA20POLY1305_IETF /* Always use IETF mode */ + +#define MAX_IVLEN AES_IVLEN +#define MAX_KEYLEN AES256_KEYLEN +#define AES_MAXKEYLEN AES256_KEYLEN + + +/******************************************************************************/ +/* Layer includes */ + +#include "aes_aesni.h" +#include "aes_matrix.h" +#ifdef USE_OPENSSL_CRYPTO +#include "symmetric_openssl.h" +#endif +#ifdef USE_LIBSODIUM_CRYPTO +#include "symmetric_libsodium.h" +#endif + +/******************************************************************************/ +/* Universal types and defines */ +typedef union { +#ifdef USE_AES_GCM + psAesGcm_t aesgcm; +#endif +#ifdef USE_AES_CBC + psAesCbc_t aes; +#endif +#ifdef USE_CHACHA20_POLY1305 + psChacha20Poly1305_t chacha20poly1305; +#endif +#ifdef USE_MATRIX_RC2 + psRc2Cbc_t rc2; +#endif +#ifdef USE_MATRIX_ARC4 + psArc4_t arc4; +#endif +#if defined USE_MATRIX_3DES || defined USE_CL_3DES + psDes3_t des3; +#endif +#ifdef USE_MATRIX_IDEA + psIdea_t idea; +#endif +#ifdef USE_MATRIX_SEED + psSeed_t seed; +#endif +} psCipherContext_t; + +typedef uint32 CL_AnyAsset_t; + +typedef struct { + uint32 KeyLen; + struct { + CL_AnyAsset_t Asset_key; + CL_AnyAsset_t Asset_ke; + CL_AnyAsset_t Asset_state; + unsigned char IVend[8]; + } fips; +} psCipherGivContext_t; + +#endif /* _h_MATRIX_SYMMETRIC */ +/******************************************************************************/ + diff --git a/crypto/symmetric/symmetric_libsodium.c b/crypto/symmetric/symmetric_libsodium.c new file mode 100755 index 0000000..35721a9 --- /dev/null +++ b/crypto/symmetric/symmetric_libsodium.c @@ -0,0 +1,418 @@ +/** + * @file symmetric_libsodium.c + * @version $Format:%h%d$ + * + * Symmetric compatibility layer between MatrixSSL and libsodium. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +/******************************************************************************/ + +#ifdef USE_LIBSODIUM_AES_GCM + +/******************************************************************************/ +/* + Initialize an AES GCM context +*/ + +int32_t psAesInitGCM(psAesGcm_t *ctx, + const unsigned char key[AES_MAXKEYLEN], uint8_t keylen) +{ + // Check that structure is 16bytes aligned: + if (((uintptr_t)(const void *)(&(ctx->libSodiumCtx))) % 16 != 0) { + psTraceCrypto("\nFAIL: libsodium structure not 16bytes aligned"); + printf("FAIL: libsodium structure not 16bytes aligned %p",&(ctx->libSodiumCtx)); + psAssert(0); + return PS_FAIL; + } + + /* libsodium only supports aes256, not aes128 */ + if (keylen != crypto_aead_aes256gcm_KEYBYTES) { + psTraceCrypto("FAIL: libsodium-aes doesn't support this key length"); + psAssert(keylen == crypto_aead_aes256gcm_KEYBYTES); + return PS_FAIL; + } + + if (sodium_init() != 0) { + // libsodium is already initialized, no problem + } + + if (crypto_aead_aes256gcm_is_available() == 0) { + psTraceCrypto("FAIL: libsodium-aes not supported"); + psAssert(0); + return PS_FAIL; + } + + memset(ctx, 0x00, sizeof(psAesGcm_t)); + + if (crypto_aead_aes256gcm_beforenm(&(ctx->libSodiumCtx),key) != 0) { + psTraceCrypto("FAIL: libsodium-aes init"); + psAssert(0); + return PS_FAIL; + } + return PS_SUCCESS; +} + +/******************************************************************************/ + +void psAesClearGCM(psAesGcm_t *ctx) +{ + // Comment to add (todo) + memset_s(ctx, sizeof(psAesGcm_t), 0x0, sizeof(psAesGcm_t)); +} + +/******************************************************************************/ +/* + Specifiy the IV and additional data to an AES GCM context that was + created with psAesInitGCM +*/ +void psAesReadyGCM(psAesGcm_t *ctx, + const unsigned char IV[AES_IVLEN], + const unsigned char *aad, uint16_t aadLen) +{ + //--- Set up context structure ---// + + // Set up IV (nonce) + memset(ctx->IV, 0, 16); + memcpy(ctx->IV, IV, 12); + + if (aadLen>sizeof(ctx->Aad)) { + psTraceCrypto("FAIL: size issue"); + psAssert(0); + } + + // Set up additional data + memcpy(ctx->Aad, aad, aadLen); + ctx->AadLen = aadLen; +} + +/******************************************************************************/ +/* + Public GCM encrypt function. This will just perform the encryption. The + tag should be fetched with psAesGetGCMTag +*/ +void psAesEncryptGCM(psAesGcm_t *ctx,const unsigned char *pt, unsigned char *ct,uint32_t len) +{ + unsigned long long ciphertext_len; + unsigned char * resultEncryption; + + resultEncryption = psMalloc(NULL, len+sizeof(ctx->Tag)); + + // libsodium will put the (cipher text and the tag) in the result, + crypto_aead_aes256gcm_encrypt_afternm(resultEncryption,&ciphertext_len, + (const unsigned char *)pt, (unsigned long long)len, + (const unsigned char *)ctx->Aad, (unsigned long long)ctx->AadLen, + NULL, (const unsigned char *)ctx->IV, + (crypto_aead_aes256gcm_state *) &(ctx->libSodiumCtx)); + + // Copy the authentication tag in context to be able to retrieve it later + memcpy(ctx->Tag, (resultEncryption+len), sizeof(ctx->Tag)); + + // Copy the ciphertext in destination + memcpy(ct,resultEncryption,len); + + psFree(resultEncryption, NULL); +} + +/******************************************************************************/ +/* + After encryption this function is used to retreive the authentication tag +*/ +void psAesGetGCMTag(psAesGcm_t *ctx,uint8_t tagBytes, unsigned char tag[AES_BLOCKLEN]) +{ + memcpy(tag,ctx->Tag, tagBytes); +} + +/* Just does the GCM decrypt portion. Doesn't expect the tag to be at the end + of the ct. User will invoke psAesGetGCMTag seperately */ +void psAesDecryptGCMtagless(psAesGcm_t *ctx, + const unsigned char *ct, unsigned char *pt, + uint32_t len) +{ + // Not possible with libsodium ? + psAssert(0); +} + + +/******************************************************************************/ +/* + Decrypt from libsodium will perform itself the tag comparaison. + So ct is holding: cipher text || tag . The provided length (ctLen) must reflect this +*/ +int32_t psAesDecryptGCM(psAesGcm_t *ctx, + const unsigned char *ct, uint32_t ctLen, + unsigned char *pt, uint32_t ptLen) +{ + unsigned long long decrypted_len; + + if ((ctLen-ptLen) != crypto_aead_aes256gcm_ABYTES) { + psTraceCrypto("Cipher text must include the tag\n"); + return PS_ARG_FAIL; + } + + if (crypto_aead_aes256gcm_decrypt_afternm(pt, + &decrypted_len, + NULL, + ct, + (unsigned long long)ctLen, + (const unsigned char *)ctx->Aad, + (unsigned long long)ctx->AadLen, + (const unsigned char *)ctx->IV, + (crypto_aead_aes256gcm_state *)&(ctx->libSodiumCtx)) != 0) { + psTraceCrypto("GCM didn't authenticate\n"); + return PS_AUTH_FAIL; + + } + + if (decrypted_len != ptLen) { + psTraceCrypto("Problem during decryption\n"); + return PS_AUTH_FAIL; + } + + return PS_SUCCESS; +} + +#endif /* USE_LIBSODIUM_AES_GCM */ + +/******************************************************************************/ + +#ifdef USE_LIBSODIUM_CHACHA20_POLY1305 +/*********************************************************************************/ +/* chacha20-poly1305 AEAD low-level implementation, based on libsodium library */ +/* Refer to the following spec: */ +/* https://tools.ietf.org/html/rfc7539 $2.8 AEAD Construction */ +/* */ +/* !!! Note that if CHACHA20POLY1305_IETF is defined than the nonce must be */ +/* 96bits, if CHACHA20POLY1305_IETF not defined the nonce must be 64bits */ +/*********************************************************************************/ +/** + Initialize an chacha20 poly1305 context. Put the provided key in the context + structure + + @param ctx Pointer on the cipher context structure. This structure holds the key, nonce & aad... + @param key The algo's key + @param keylen The key's length + + @return PS_SUCCESS if success + PS_FAIL in case of key length problem + +*/ +int32_t psChacha20Poly1305Init(psChacha20Poly1305_t *ctx, + const unsigned char key[crypto_aead_chacha20poly1305_KEYBYTES], uint8_t keylen) +{ + if (keylen != crypto_aead_chacha20poly1305_KEYBYTES) { + psTraceCrypto("FAIL: libsodium-chacha20-poly1305 not supporting this key length"); + psAssert(0); + return PS_FAIL; + } + memset(ctx, 0x0, sizeof(psChacha20Poly1305_t)); + // Copy the key + memcpy(ctx->key, key, crypto_aead_chacha20poly1305_KEYBYTES); + + return PS_SUCCESS; +} + +/******************************************************************************/ +/** + Clear the provided context structure + @param ctx context structure +*/ +void psChacha20Poly1305Clear(psChacha20Poly1305_t *ctx) +{ + memset_s(ctx, sizeof(psChacha20Poly1305_t), 0x0, sizeof(psChacha20Poly1305_t)); +} + +/******************************************************************************/ +/** + Specifiy the IV and additional data to an chacha20 poly1305 context that was + created with psChacha20Poly1305Init. + + + @param ctx Pointer on the cipher context structure. This structure holds the key, nonce & aad... + @param IV pointer on the provided IV + (called nonce if referring to https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305-03) + @param aad pointer on buffer holding additional data, as specified in + +*/ +void psChacha20Poly1305Ready(psChacha20Poly1305_t *ctx, + const unsigned char *IV, + const unsigned char *aad, uint16_t aadLen) +{ + //--- Set up context structure ---// + + // Set up IV +#ifdef CHACHA20POLY1305_IETF + memset(ctx->IV, 0, crypto_aead_chacha20poly1305_IETF_NPUBBYTES); + memcpy(ctx->IV, IV, crypto_aead_chacha20poly1305_IETF_NPUBBYTES); +#else + memset(ctx->IV, 0, crypto_aead_chacha20poly1305_NPUBBYTES); + memcpy(ctx->IV, IV, crypto_aead_chacha20poly1305_NPUBBYTES); +#endif + + if (aadLen>sizeof(ctx->Aad)) { + psTraceCrypto("FAIL: size issue with libsodium-chacha20-poly1305 additionnal data"); + psAssert(0); + } + + // Set up additional data + memcpy(ctx->Aad, aad, aadLen); + ctx->AadLen = aadLen; +} + +/******************************************************************************/ +/* + Public chacha20 poly1305 encrypt function. + This will perform the encryption and compute the authentication tag at the + same time. In the output pointer (ct), only the encrypted text is present, the + tag should be fetched with psChacha20Poly1305GetTag + + @param ctx Pointer on the cipher context structure. This structure holds the key, nonce & aad... + @param pt pointer on the text to encrypt + @param ct pointer on encrypted text, output of this function + @param len length of the text to encrypt +*/ +void psChacha20Poly1305Encrypt(psChacha20Poly1305_t *ctx,const unsigned char *pt, unsigned char *ct,uint32_t len) +{ + unsigned long long ciphertext_len; + unsigned char * resultEncryption; + + // Allocate mem to store ciphertext and tag + resultEncryption = psMalloc(NULL, len+sizeof(ctx->Tag)); + + // libsodium will put the cipher text and the tag in the result. + // resultEncryption = cipherText || tag +#ifdef CHACHA20POLY1305_IETF + crypto_aead_chacha20poly1305_ietf_encrypt(resultEncryption, &ciphertext_len, + (const unsigned char *)pt, (unsigned long long)len, + (const unsigned char *)ctx->Aad, (unsigned long long)ctx->AadLen, + NULL, (const unsigned char *)ctx->IV, (const unsigned char *)ctx->key); +#else + crypto_aead_chacha20poly1305_encrypt(resultEncryption, &ciphertext_len, + (const unsigned char *)pt, (unsigned long long)len, + (const unsigned char *)ctx->Aad, (unsigned long long)ctx->AadLen, + NULL, (const unsigned char *)ctx->IV, (const unsigned char *)ctx->key); +#endif + + // Copy the authentication tag in context to be able to retrieve it later + memcpy(ctx->Tag, (resultEncryption+len), sizeof(ctx->Tag)); + + // Copy the ciphertext in destination + memcpy(ct,resultEncryption,len); + + psFree(resultEncryption, NULL); +} + +/************************************************************************************/ +/* + After encryption this function is used to retrieve the authentication tag + @param ctx Pointer on the cipher context structure. This structure holds the key, nonce & aad... + @param tagBytesLen length of tag to retrieve + @param tag the provided buffer to hold the AEAD' authentication tag +*/ +void psChacha20Poly1305GetTag(psChacha20Poly1305_t *ctx,uint8_t tagBytesLen, unsigned char tag[crypto_aead_chacha20poly1305_ABYTES]) +{ + memcpy(tag, ctx->Tag, tagBytesLen); +} + +/************************************************************************************/ +/* + Just does the chacha20 poly1305 decrypt portion. Doesn't expect the tag to be + at the end of the ct. User will invoke psChacha20Poly1305GetTag seperately + !!! Currently not available with libsodium !!!!! +*/ +void psChacha20Poly1305DecryptTagless(psChacha20Poly1305_t *ctx, + const unsigned char *ct, unsigned char *pt, + uint32_t len) +{ + // Not possible with libsodium. + psAssert(0); +} + +/******************************************************************************/ +/* + Decrypt function using libsodium library. This function will perform + itself the tag comparaison. + So the provided cipherText must hold: cipher text || tag . + The provided length (ctLen) must reflect this. + + @param ctx Pointer on the cipher context structure. This structure holds the key, nonce & aad... + @param ct pointer on: (cipherText || AEAD-Tag) + @param ctLen length of data pointed by ct (so encrypted data + tag) + @param pt pointer on decrypted data + @param ptLen length of encrypted data + + @return length of decrypted data in case of success. + PS_ARG_FAIL in case of parameter problem + PS_AUTH_FAIL in case of problem during tag's authentication check or + during decryption operation +*/ +int32_t psChacha20Poly1305Decrypt(psChacha20Poly1305_t *ctx, + const unsigned char *ct, uint32_t ctLen, + unsigned char *pt, uint32_t ptLen) +{ + unsigned long long decrypted_len; + + if ((ctLen-ptLen) != crypto_aead_chacha20poly1305_ABYTES) { + psTraceCrypto("FAIL: Cipher text must include the tag\n"); + return PS_ARG_FAIL; + } + +#ifdef CHACHA20POLY1305_IETF + if (crypto_aead_chacha20poly1305_ietf_decrypt(pt, &decrypted_len, NULL, + ct, (unsigned long long)ctLen, + (const unsigned char *)ctx->Aad, (unsigned long long)ctx->AadLen, + (const unsigned char *)ctx->IV, (const unsigned char *)ctx->key) != 0) { + + psTraceCrypto("chacha20 poly1305 AEAD didn't authenticate\n"); + return PS_AUTH_FAIL; + } +#else + if (crypto_aead_chacha20poly1305_decrypt(pt, &decrypted_len, NULL, + ct, (unsigned long long)ctLen, + (const unsigned char *)ctx->Aad, (unsigned long long)ctx->AadLen, + (const unsigned char *)ctx->IV, + (const unsigned char *)ctx->key) != 0) { + psTraceCrypto("chacha20 poly1305 AEAD didn't authenticate\n"); + return PS_AUTH_FAIL; + } +#endif + if (decrypted_len != ptLen) { + psTraceCrypto("Problem during chacha20 poly1305 AEAD decryption\n"); + return PS_AUTH_FAIL; + } + + return decrypted_len; +} + +/************************************************************************************/ + +#endif /* USE_LIBSODIUM_CHACHA20_POLY1305 */ + diff --git a/crypto/symmetric/symmetric_libsodium.h b/crypto/symmetric/symmetric_libsodium.h new file mode 100755 index 0000000..99507a6 --- /dev/null +++ b/crypto/symmetric/symmetric_libsodium.h @@ -0,0 +1,67 @@ +/** + * @file symmetric_libsodium.h + * @version $Format:%h%d$ + * + * Header for libsodium crypto layer. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ + +/******************************************************************************/ + +#ifndef _h_LIBSODIUM_SYMMETRIC +#define _h_LIBSODIUM_SYMMETRIC + +#include "../cryptoApi.h" +#include "sodium.h" + +/******************************************************************************/ + +#ifdef USE_LIBSODIUM_AES_GCM +typedef struct __attribute__((aligned(16))) { + crypto_aead_aes256gcm_state libSodiumCtx; + unsigned char IV[AES_BLOCKLEN]; + unsigned char Tag[AES_BLOCKLEN]; + unsigned char Aad[crypto_aead_aes256gcm_ABYTES]; //TODO change this length + uint32_t AadLen; +} psAesGcm_t; +#endif + +#ifdef USE_LIBSODIUM_CHACHA20_POLY1305 +typedef struct { + unsigned char key[crypto_aead_chacha20poly1305_KEYBYTES]; + unsigned char IV[crypto_aead_chacha20poly1305_IETF_NPUBBYTES]; + unsigned char Tag[crypto_aead_chacha20poly1305_ABYTES]; + unsigned char Aad[16]; + uint32_t AadLen; +} psChacha20Poly1305_t; +#endif + +/******************************************************************************/ + +#endif /* _h_LIBSODIUM_SYMMETRIC */ + diff --git a/crypto/symmetric/symmetric_openssl.c b/crypto/symmetric/symmetric_openssl.c new file mode 100644 index 0000000..ac20fdf --- /dev/null +++ b/crypto/symmetric/symmetric_openssl.c @@ -0,0 +1,113 @@ +/** + * @file symmetric_openssl.c + * @version $Format:%h%d$ + * + * Symmetric compatibility layer between MatrixSSL and OpenSSL. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "../cryptoApi.h" + +/******************************************************************************/ + +//TODO aesni_cbc_sha256_enc +#ifdef USE_OPENSSL_AES_CBC + +__inline static const EVP_CIPHER *EVP_aes_cbc(uint8_t keylen) +{ + switch(keylen) { + case AES128_KEYLEN: + return EVP_get_cipherbyname("aes-128-cbc"); +// return EVP_aes_128_cbc(); + case AES192_KEYLEN: + return EVP_get_cipherbyname("aes-192-cbc"); +// return EVP_aes_192_cbc(); + case AES256_KEYLEN: + return EVP_get_cipherbyname("aes-256-cbc"); +// return EVP_aes_256_cbc(); + } + return NULL; +} + +int32_t psAesInitCBC(psAesCbc_t *ctx, + const unsigned char IV[AES_IVLEN], + const unsigned char key[AES_MAXKEYLEN], uint8_t keylen, + uint32_t flags) +{ + OpenSSL_add_all_algorithms(); + EVP_CIPHER_CTX_init(ctx); + if (EVP_CipherInit_ex(ctx, EVP_aes_cbc(keylen), NULL, key, IV, + flags & PS_AES_ENCRYPT ? 1 : 0)) { + /* Turn off padding so all the encrypted/decrypted data will be + returned in the single call to Update. This will require that + all the incoming data be an exact block multiple (which is true + for TLS usage where all padding is accounted for) */ + EVP_CIPHER_CTX_set_padding(ctx, 0); + return PS_SUCCESS; + } + EVP_CIPHER_CTX_cleanup(ctx); + psAssert(0); + return PS_FAIL; +} + +void psAesClearCBC(psAesCbc_t *ctx) +{ + EVP_CIPHER_CTX_cleanup(ctx); +} + +void psAesDecryptCBC(psAesCbc_t *ctx, + const unsigned char *ct, unsigned char *pt, + uint32_t len) +{ + int outl = len; + + if (!EVP_DecryptUpdate(ctx, pt, &outl, ct, len)) { + EVP_CIPHER_CTX_cleanup(ctx); + psAssert(0); + } + psAssert(outl == len); +} + +void psAesEncryptCBC(psAesCbc_t *ctx, + const unsigned char *pt, unsigned char *ct, + uint32_t len) +{ + int outl = len; + + if (!EVP_EncryptUpdate(ctx, ct, &outl, pt, len)) { + EVP_CIPHER_CTX_cleanup(ctx); + psAssert(0); + } + psAssert(outl == len); +} + +#endif /* USE_OPENSSL_AES_CBC */ + +/******************************************************************************/ + diff --git a/crypto/symmetric/symmetric_openssl.h b/crypto/symmetric/symmetric_openssl.h new file mode 100644 index 0000000..65069fd --- /dev/null +++ b/crypto/symmetric/symmetric_openssl.h @@ -0,0 +1,62 @@ +/** + * @file symmetric_openssl.h + * @version $Format:%h%d$ + * + * Header for OpenSSL Crypto Layer. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ + +/******************************************************************************/ + +#ifndef _h_OPENSSL_SYMMETRIC +#define _h_OPENSSL_SYMMETRIC + +#include "../cryptoApi.h" + +/******************************************************************************/ + +#if defined(USE_OPENSSL_AES_CBC) || defined(USE_OPENSSL_AES_GCM) +/** + We use the EVP interface rather than the lower level calls so that + platform specific options will be used. + */ +#include +#endif + +#ifdef USE_OPENSSL_AES_CBC +typedef EVP_CIPHER_CTX psAesCbc_t; +#endif + +#ifdef USE_OPENSSL_AES_GCM +typedef EVP_CIPHER_CTX psAesGcm_t; +#endif + +/******************************************************************************/ + +#endif /* _h_OPENSSL_SYMMETRIC */ + diff --git a/crypto/test/Makefile b/crypto/test/Makefile new file mode 100755 index 0000000..ccb4780 --- /dev/null +++ b/crypto/test/Makefile @@ -0,0 +1,55 @@ +# +# Makefile for crypto testing +# 'make' builds debug (Default). +# 'make gold' builds optimized. +# +# Copyright (c) PeerSec Networks, 2002-2010. All Rights Reserved +# Copyright (c) 2013-2016 INSIDE Secure Corporation. All Rights Reserved. +# + +MATRIXSSL_ROOT:=../.. +VECTOR_SRC:=algorithmTest.c +SPEED_SRC:=throughputTest.c +SRC:=$(VECTOR_SRC) $(SPEED_SRC) + +include $(MATRIXSSL_ROOT)/common.mk + +# Generated files +VECTOR_EXE:=algorithmTest$(E) +SPEED_EXE:=throughputTest$(E) + +# Linked files +STATICS:=../libcrypt_s.a $(MATRIXSSL_ROOT)/core/libcore_s.a +#STATICS+=$(MATRIXSSL_ROOT)/matrixssl/libssl_s.a + +all: compile + +compile: $(OBJS) $(SPEED_EXE) $(VECTOR_EXE) + $(MAKE) --directory=rsaperf + $(MAKE) --directory=eccperf + $(MAKE) --directory=dhperf + +# Additional Dependencies +$(OBJS): $(MATRIXSSL_ROOT)/common.mk Makefile $(wildcard *.h) + +$(SPEED_EXE): $(SPEED_SRC:.c=.o) $(STATICS) + $(CC) -o $@ $^ $(LDFLAGS) + +$(VECTOR_EXE): $(VECTOR_SRC:.c=.o) $(STATICS) + $(CC) -o $@ $^ $(LDFLAGS) + + +ifneq (,$(findstring -octeon,$(CCARCH))) + SIM:=oct-sim + SIMFLAGS:=-quiet -numcores=1 -noperf +endif + +test: + $(SIM) ./$(VECTOR_EXE) $(SIMFLAGS) + +clean: + rm -f $(VECTOR_EXE) $(SPEED_EXE) $(OBJS) + $(MAKE) clean --directory=rsaperf + $(MAKE) clean --directory=eccperf + $(MAKE) clean --directory=dhperf + diff --git a/crypto/test/algorithmTest.c b/crypto/test/algorithmTest.c new file mode 100644 index 0000000..bfa35f0 --- /dev/null +++ b/crypto/test/algorithmTest.c @@ -0,0 +1,4728 @@ +/** + * @file algorithmTest.c + * @version $Format:%h%d$ + * + * Crypto harness to check algorithms against known inputs/outputs. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "crypto/cryptoApi.h" +#include "hmac_test_vectors.h" + +#ifndef USE_SERVER_SIDE_SSL +#define USE_SERVER_SIDE_SSL +#endif + +/******************************************************************************/ +static int32 psPrngTests(void) +{ + int32 res; + static unsigned char ch[70000]; + _psTrace(" PRNG small random generation... "); + + memset(ch, 0, sizeof(ch)); + res = matrixCryptoGetPrngData(ch, 3, NULL); + if (res != 3 || + ch[0] + ch[1] + ch[2] < 6 || /* Probabilistic test */ + ch[4] != 0 || + ch[5] != 0) + { + _psTrace("FAILED\n"); + res = PS_FAILURE; + } else { + _psTrace("PASSED\n"); + } + + if (res != PS_FAILURE) { + int i, sum; + + _psTrace(" PRNG large random generation... "); + + memset(ch, 0, sizeof(ch)); + sum = 0; + res = matrixCryptoGetPrngData(ch + 1, 65532, NULL); + res += matrixCryptoGetPrngData(ch + 1 + 65532, (69998-65532), NULL); + for(i = 0; i < 70000; i++) + sum += ch[i]; + if (res != 69998 || + sum < 5 * 70000 || /* Probabilistic test */ + sum > 250 * 70000 || /* Probabilistic test */ + ch[0] != 0 || + ch[69999] != 0) + { + _psTrace("FAILED\n"); + res = PS_FAILURE; + } else { + _psTrace("PASSED\n"); + } + } + + return res < 0 ? res : PS_SUCCESS; +} + + + + + + +/******************************************************************************/ +#ifdef USE_AES +#define AES_ITER 1000 /* For AES Block mode test */ +static int32 psAesTestBlock(void) +{ + int32 err, i, y; + psAesKey_t ekey, dkey; + unsigned char tmp[2][16]; + + static const struct { + int32 keylen; + unsigned char key[32], pt[16], ct[16]; + } tests[] = { + { 16, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, + 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a } + }, { + 24, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, + 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 } + }, { + 32, + { 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, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, + 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 } + } + }; + + for (i = 0; i < (int32)(sizeof(tests)/sizeof(tests[0])); i++) { + _psTraceInt(" AES-%d known vector test... ", tests[i].keylen * 8); + if ((err = psAesInitBlockKey(&ekey, tests[i].key, tests[i].keylen, PS_AES_ENCRYPT)) + != PS_SUCCESS) { + _psTraceInt("FAILED: psAesInitBlockKey returned %d\n", err); + return err; + } + if ((err = psAesInitBlockKey(&dkey, tests[i].key, tests[i].keylen, PS_AES_DECRYPT)) + != PS_SUCCESS) { + _psTraceInt("FAILED: psAesInitBlockKey returned %d\n", err); + psAesClearBlockKey(&ekey); + return err; + } + psAesEncryptBlock(&ekey, tests[i].pt, tmp[0]); + psAesDecryptBlock(&dkey, tmp[0], tmp[1]); + if (memcmp(tmp[0], tests[i].ct, 16) || memcmp(tmp[1], tests[i].pt, 16)) + { + _psTraceInt("FAILED: mem compare failed\n", i); + if (memcmp(tmp[0], tests[i].ct, 16)) { + psTraceCrypto("CT: "); + for (i = 0; i < 16; i++) { + _psTraceInt("%02x ", tmp[0][i]); + } + _psTrace("\n"); + } else { + _psTrace("PT: "); + for (i = 0; i < 16; i++) { + _psTraceInt("%02x ", tmp[1][i]); + } + _psTrace("\n"); + } + psAesClearBlockKey(&ekey); + psAesClearBlockKey(&dkey); + return -1; + } + _psTrace("PASSED\n"); +/* + Now see if we can encrypt all zero bytes 1000 times, + decrypt and come back where we started +*/ + _psTraceInt(" AES-%d wind/unwind test... ", tests[i].keylen * 8); + for (y = 0; y < 16; y++) tmp[0][y] = 0; + for (y = 0; y < AES_ITER; y++) psAesEncryptBlock(&ekey, tmp[0], tmp[0]); + for (y = 0; y < AES_ITER; y++) psAesDecryptBlock(&dkey, tmp[0], tmp[0]); + for (y = 0; y < 16; y++) { + if (tmp[0][y] != 0) { + _psTraceInt("FAILED: unable to unwind %d to zero\n", y); + psAesClearBlockKey(&ekey); + psAesClearBlockKey(&dkey); + return -1; + } + } + psAesClearBlockKey(&ekey); + psAesClearBlockKey(&dkey); + _psTrace("PASSED\n"); + } + return 0; +} + +/* + Known vector test - AES-CBC +*/ +static int32 psAesTestCBC(void) +{ + int32 err, i; + psAesCbc_t eCtx, dCtx; + unsigned char tmp[2][16]; + + static struct { + int32 keylen; + unsigned char key[32], iv[16], pt[16], ct[16]; + } tests[] = { + { 16, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, + 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, + 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a }, + { 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, + 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d } + }, { + 24, + { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, + 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, 0x62, 0xf8, 0xea, 0xd2, + 0x52, 0x2c, 0x6b, 0x7b }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, + 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a }, + { 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, 0x71, 0x78, + 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8 } + }, { + 32, + { 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 }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, + 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a }, + { 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, + 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6 } + } + }; + + + for (i = 0; i < (int32)(sizeof(tests)/sizeof(tests[0])); i++) { + _psTraceInt(" AES-CBC-%d known vector test... ", tests[i].keylen * 8); + if ((err = psAesInitCBC(&eCtx, tests[i].iv, tests[i].key, tests[i].keylen, + PS_AES_ENCRYPT)) != PS_SUCCESS) { + _psTraceInt("FAILED: psAesInitCBC returned %d\n", err); + return err; + } + if ((err = psAesInitCBC(&dCtx, tests[i].iv, tests[i].key, tests[i].keylen, + PS_AES_DECRYPT)) != PS_SUCCESS) { + _psTraceInt("FAILED: psAesInitCBC returned %d\n", err); + psAesClearCBC(&eCtx); + return err; + } + psAesEncryptCBC(&eCtx, tests[i].pt, tmp[0], 16); + psAesDecryptCBC(&dCtx, tmp[0], tmp[1], 16); + if (memcmp(tmp[0], tests[i].ct, 16) || memcmp(tmp[1], tests[i].pt, 16)) + { + _psTraceInt("FAILED: mem compare failed\n", i); + if (memcmp(tmp[0], tests[i].ct, 16)) { + psTraceCrypto("CT: "); + for (i = 0; i < 16; i++) { + _psTraceInt("%02x ", tmp[0][i]); + } + _psTrace("\n"); + } else { + _psTrace("PT: "); + for (i = 0; i < 16; i++) { + _psTraceInt("%02x ", tmp[1][i]); + } + _psTrace("\n"); + } + psAesClearCBC(&eCtx); + psAesClearCBC(&dCtx); + return -1; + } + psAesClearCBC(&eCtx); + psAesClearCBC(&dCtx); + _psTrace("PASSED\n"); + } + return 0; +} + +#ifdef USE_AES_GCM +int32 psAesTestGCM(void) +{ + int32 res = PS_SUCCESS; + int32 i, l; + psAesGcm_t eCtx; + psAesGcm_t dCtx; + unsigned char plaintext[4128]; + unsigned char ciphertext[4128]; +#ifndef USE_ONLY_DECRYPT_GCM_WITH_TAG + unsigned char tag[16]; +#endif + unsigned char ciphertext_with_tag[4144]; + static unsigned char taglen[3] = { 8, 12, 16 }; + static char *tagmsg[] = { + " AES-GCM-%d known vector decrypt (taglen=8) test... ", + " AES-GCM-%d known vector decrypt (taglen=12) test... ", + " AES-GCM-%d known vector decrypt (taglen=16) test... ", + }; + static char *tagmsg2[] = { + " AES-GCM-%d known vector decrypt (taglen=8 invalid) test... ", + " AES-GCM-%d known vector decrypt (taglen=12 invalid) test... ", + " AES-GCM-%d known vector decrypt (taglen=16 invalid) test... ", + }; + + static struct { + int32 keylen, ptlen, aadlen; + unsigned char key[32], iv[12], pt[4128], aad[32], ct[4128], tag[16]; + } tests[] = { +#ifndef USE_LIBSODIUM_AES_GCM + { 16, 16, 16, + { 0xc9, 0x39, 0xcc, 0x13, 0x39, 0x7c, 0x1d, 0x37, + 0xde, 0x6a, 0xe0, 0xe1, 0xcb, 0x7c, 0x42, 0x3c }, + { 0xb3, 0xd8, 0xcc, 0x01, 0x7c, 0xbb, 0x89, 0xb3, + 0x9e, 0x0f, 0x67, 0xe2 }, + { 0xc3, 0xb3, 0xc4, 0x1f, 0x11, 0x3a, 0x31, 0xb7, + 0x3d, 0x9a, 0x5c, 0xd4, 0x32, 0x10, 0x30, 0x69}, + { 0x24, 0x82, 0x56, 0x02, 0xbd, 0x12, 0xa9, 0x84, + 0xe0, 0x09, 0x2d, 0x3e, 0x44, 0x8e, 0xda, 0x5f}, + { 0x93, 0xfe, 0x7d, 0x9e, 0x9b, 0xfd, 0x10, 0x34, + 0x8a, 0x56, 0x06, 0xe5, 0xca, 0xfa, 0x73, 0x54}, + { 0x00, 0x32, 0xa1, 0xdc, 0x85, 0xf1, 0xc9, 0x78, + 0x69, 0x25, 0xa2, 0xe7, 0x1d, 0x82, 0x72, 0xdd} + }, + { 16, 4128, 16, + { 0xc9, 0x39, 0xcc, 0x13, 0x39, 0x7c, 0x1d, 0x37, + 0xde, 0x6a, 0xe0, 0xe1, 0xcb, 0x7c, 0x42, 0x3c }, + { 0xb3, 0xd8, 0xcc, 0x01, 0x7c, 0xbb, 0x89, 0xb3, + 0x9e, 0x0f, 0x67, 0xe2 }, + { 0x00, }, + { 0x24, 0x82, 0x56, 0x02, 0xbd, 0x12, 0xa9, 0x84, + 0xe0, 0x09, 0x2d, 0x3e, 0x44, 0x8e, 0xda, 0x5f}, + { 0x50, 0x4d, 0xb9, 0x81, 0x8a, 0xc7, 0x21, 0x83, 0xb7, 0xcc, + 0x5a, 0x31, 0xf8, 0xea, 0x43, 0x3d, 0x46, 0xb1, 0x85, 0x3f, + 0x8b, 0x9b, 0x8d, 0xd3, 0xfe, 0x06, 0x84, 0x42, 0xd9, 0x08, + 0x98, 0x43, 0xe7, 0xbd, 0x0b, 0x32, 0x02, 0x10, 0x39, 0xae, + 0x3b, 0xcb, 0x39, 0x5d, 0x76, 0x47, 0xd8, 0xc9, 0xac, 0xa1, + 0x72, 0xe7, 0x54, 0x98, 0xcf, 0x5f, 0x91, 0x56, 0x90, 0x51, + 0x79, 0x3a, 0xf3, 0x38, 0x4e, 0xb2, 0x8d, 0x1a, 0x27, 0x3c, + 0xa9, 0xdb, 0x8f, 0xcd, 0x48, 0x14, 0x97, 0xba, 0xd7, 0x4b, + 0x7c, 0x64, 0xc4, 0x78, 0xf7, 0x8f, 0x81, 0x22, 0x71, 0xa6, + 0x90, 0xf4, 0x30, 0x47, 0xd8, 0x7f, 0x96, 0xd9, 0x6c, 0x21, + 0xc0, 0x47, 0xfd, 0xc8, 0x45, 0xf8, 0x7d, 0xdf, 0x8c, 0x2b, + 0x1a, 0xe5, 0x73, 0x29, 0x7f, 0x26, 0x55, 0xb4, 0x11, 0x4a, + 0x08, 0x2d, 0x30, 0xab, 0x12, 0x58, 0x96, 0xf8, 0xfa, 0x99, + 0x75, 0x6a, 0x0c, 0x94, 0x5c, 0x71, 0x58, 0x3f, 0x9c, 0xca, + 0x96, 0x8e, 0xfd, 0x90, 0x88, 0xf6, 0x3a, 0x23, 0xdb, 0xf0, + 0xca, 0x5a, 0x4a, 0x8e, 0x29, 0x42, 0xdb, 0xa8, 0x87, 0x74, + 0xd4, 0xae, 0x9a, 0x6d, 0xf5, 0x6e, 0x00, 0xda, 0x0a, 0x03, + 0x17, 0xa3, 0x3a, 0xa5, 0xd1, 0x13, 0x9e, 0x81, 0xf2, 0xc8, + 0xf7, 0x07, 0xfa, 0xe8, 0x83, 0x1a, 0x00, 0x56, 0xd2, 0xf2, + 0x80, 0x6a, 0xe4, 0xf1, 0x4e, 0xda, 0x56, 0x66, 0xeb, 0xaf, + 0xad, 0x0c, 0x19, 0xe8, 0x30, 0xb3, 0x8b, 0x59, 0x9c, 0xbf, + 0x10, 0x38, 0xa7, 0xaf, 0x2a, 0xd3, 0x52, 0xae, 0xb0, 0x6e, + 0x3a, 0x01, 0x3f, 0xc9, 0x13, 0xdb, 0x99, 0xe5, 0xb5, 0x59, + 0x2b, 0x14, 0x48, 0xf3, 0xb5, 0x93, 0x38, 0xa8, 0x12, 0x98, + 0x6c, 0x83, 0x88, 0x32, 0x7a, 0x46, 0x46, 0xae, 0xed, 0x81, + 0x1c, 0xba, 0xab, 0xb3, 0x2e, 0xa0, 0x53, 0x57, 0x8c, 0x24, + 0x80, 0x7b, 0x9d, 0x74, 0xb9, 0xf5, 0x52, 0x01, 0x4f, 0x4c, + 0x51, 0x21, 0x1c, 0x4b, 0x6a, 0xe3, 0x00, 0x3e, 0x4c, 0xcb, + 0x40, 0xf8, 0xf4, 0x31, 0x8a, 0xa0, 0xbf, 0xf0, 0x4c, 0x02, + 0x7d, 0x47, 0x2d, 0x37, 0xe8, 0x6b, 0x20, 0xec, 0xef, 0xf1, + 0xb0, 0xaf, 0x87, 0x31, 0x06, 0x76, 0x1b, 0x59, 0x9a, 0x92, + 0xfa, 0x94, 0x7a, 0x76, 0xf5, 0x6f, 0x16, 0xde, 0x96, 0xb6, + 0x0e, 0xe0, 0x59, 0x09, 0x1e, 0x0f, 0xf7, 0x27, 0x59, 0xf5, + 0xe4, 0x01, 0x57, 0x88, 0x6c, 0x32, 0x73, 0x68, 0xbb, 0x63, + 0xe0, 0x3b, 0x57, 0xbd, 0xc5, 0x40, 0xbf, 0x5d, 0x8a, 0xd6, + 0x3c, 0x13, 0x40, 0x89, 0x74, 0x87, 0x82, 0xdb, 0x13, 0x90, + 0x0f, 0x42, 0x91, 0x8c, 0x35, 0xdf, 0x1f, 0x2a, 0xb1, 0x36, + 0x73, 0x49, 0x26, 0x40, 0x35, 0x5e, 0x60, 0xa8, 0x58, 0x23, + 0xe6, 0x14, 0x9d, 0x51, 0x61, 0x7c, 0x6f, 0x82, 0x88, 0x4f, + 0x96, 0xba, 0xe2, 0x7a, 0x14, 0x65, 0x26, 0xdb, 0xf5, 0xc2, + 0x8a, 0x07, 0xbc, 0x42, 0x2d, 0x33, 0x0f, 0x94, 0xfa, 0xdd, + 0x1a, 0xe7, 0x54, 0xda, 0x08, 0x1d, 0xdf, 0xb6, 0x03, 0x5c, + 0x51, 0x7e, 0xcf, 0xf8, 0x8f, 0x21, 0xd1, 0xad, 0x29, 0x6c, + 0x29, 0xee, 0x5a, 0x90, 0xf2, 0x0f, 0xd5, 0xe5, 0x29, 0x2e, + 0x98, 0x2e, 0x36, 0x0e, 0x97, 0x42, 0x73, 0x9c, 0xc1, 0x54, + 0x02, 0x2f, 0xde, 0xb1, 0x86, 0x3b, 0x69, 0x77, 0xe2, 0xc5, + 0xa8, 0x71, 0xc8, 0x11, 0x6e, 0x64, 0x33, 0x87, 0xa2, 0x17, + 0xfc, 0x84, 0x5e, 0x20, 0x0b, 0xc9, 0x25, 0x0c, 0xcb, 0x7f, + 0xe2, 0xfe, 0x18, 0x02, 0x59, 0x4a, 0x58, 0x41, 0xe1, 0x47, + 0xcc, 0xdf, 0x00, 0x51, 0x6d, 0x78, 0xa5, 0x81, 0x8b, 0x7b, + 0x24, 0x32, 0x7d, 0x39, 0x9a, 0xed, 0x4c, 0xc3, 0x7a, 0x8d, + 0x64, 0xe9, 0x6f, 0xdb, 0x24, 0x25, 0xa7, 0x99, 0x44, 0xca, + 0x99, 0x46, 0xa1, 0x48, 0x3b, 0x78, 0x31, 0xf8, 0x7d, 0x49, + 0x02, 0x4f, 0x07, 0x7d, 0x13, 0x9e, 0x16, 0x03, 0x3a, 0xec, + 0x32, 0x44, 0x6a, 0x8d, 0x9b, 0xbd, 0xf0, 0xf3, 0x01, 0xf2, + 0xa6, 0x3d, 0x84, 0x54, 0xb5, 0x8b, 0xe3, 0x84, 0xe3, 0xa5, + 0x15, 0xe3, 0x18, 0xef, 0x76, 0xd1, 0xd0, 0x02, 0x10, 0xfd, + 0x47, 0xdf, 0xe6, 0x32, 0x8f, 0xca, 0xa9, 0x0d, 0xa0, 0xa7, + 0x55, 0xaa, 0x4a, 0xee, 0x99, 0x8c, 0x8f, 0x52, 0x0e, 0xd3, + 0x24, 0xc7, 0x4f, 0x50, 0xc9, 0x4e, 0x69, 0xc8, 0x53, 0xc7, + 0xb1, 0x5f, 0x2e, 0x4f, 0xb3, 0xc5, 0x08, 0xfa, 0x9a, 0x29, + 0x30, 0x5e, 0x9c, 0x38, 0xcf, 0x83, 0xb9, 0xbf, 0x38, 0x4c, + 0x23, 0xe2, 0xc4, 0x1e, 0x7f, 0x96, 0x6c, 0xfc, 0x82, 0x50, + 0xb1, 0x9e, 0xbc, 0xe8, 0xcf, 0xa7, 0x3c, 0x16, 0x5f, 0x6f, + 0x8e, 0xda, 0xbc, 0x30, 0xc5, 0xbf, 0x78, 0xeb, 0xa8, 0xe7, + 0x4f, 0xd3, 0x12, 0x6a, 0xb2, 0xa3, 0xc1, 0x0b, 0x15, 0x3a, + 0xe0, 0x1d, 0x3e, 0x4e, 0xdd, 0x19, 0x6b, 0xfc, 0xca, 0x5c, + 0xdd, 0x48, 0xbf, 0xf1, 0x37, 0x02, 0x2d, 0x3c, 0xeb, 0xda, + 0x01, 0xb1, 0x60, 0x0c, 0x08, 0x99, 0xb5, 0x41, 0x10, 0x52, + 0x2b, 0x90, 0x50, 0xac, 0xe3, 0x48, 0x5a, 0xac, 0x6f, 0x5e, + 0x00, 0x2d, 0xeb, 0x78, 0x17, 0x36, 0xf8, 0x8f, 0x11, 0x9e, + 0x28, 0xe7, 0x58, 0x4f, 0x82, 0xcb, 0xce, 0x02, 0x57, 0x4e, + 0xee, 0xcc, 0xe9, 0x87, 0x69, 0x39, 0xe3, 0x2c, 0x2c, 0xdf, + 0xe4, 0xcd, 0xfc, 0x4e, 0xaf, 0xa8, 0xe5, 0x95, 0x20, 0x58, + 0x4f, 0x3c, 0x61, 0xe7, 0xba, 0xf3, 0xbe, 0x2a, 0x34, 0xd8, + 0x40, 0x16, 0xd3, 0xf7, 0x2d, 0xd6, 0x3f, 0x9a, 0x4e, 0x34, + 0x6b, 0x82, 0x6d, 0x47, 0x99, 0x14, 0x42, 0x9c, 0xc9, 0xea, + 0x3c, 0xfe, 0xaa, 0x12, 0x1f, 0xe2, 0x7f, 0xbd, 0x0d, 0x50, + 0x99, 0x9b, 0x49, 0x64, 0x04, 0x77, 0x86, 0x6d, 0xaa, 0xbd, + 0xa7, 0x83, 0xe7, 0x9d, 0x1a, 0xdd, 0x52, 0x1c, 0x5e, 0xbb, + 0x75, 0x04, 0x96, 0xca, 0xdc, 0xaa, 0x49, 0xe0, 0x66, 0x74, + 0x30, 0x8b, 0xe9, 0x35, 0x5d, 0xfc, 0x92, 0x9c, 0x0b, 0x38, + 0xcb, 0xbd, 0xff, 0x93, 0xe5, 0xc1, 0xeb, 0xcf, 0x87, 0x2a, + 0x17, 0x3e, 0xda, 0xc5, 0xa1, 0x12, 0xe5, 0x81, 0xd5, 0x20, + 0x31, 0x29, 0xe9, 0xd3, 0x31, 0x92, 0x1b, 0x20, 0x5a, 0x1d, + 0x65, 0xd3, 0xa8, 0x25, 0x68, 0xe8, 0xa2, 0x39, 0xc3, 0xfa, + 0xde, 0x6f, 0xfc, 0x04, 0x8b, 0x23, 0xa8, 0xf9, 0xd1, 0xee, + 0x54, 0x83, 0x82, 0xc6, 0x48, 0xa2, 0x59, 0x74, 0x80, 0xcf, + 0xb7, 0x9f, 0x4a, 0x01, 0x1e, 0xe5, 0x03, 0x30, 0x43, 0xb3, + 0x0c, 0x05, 0x14, 0x87, 0x7a, 0x04, 0x06, 0x8b, 0x5f, 0x92, + 0x36, 0x4b, 0x0b, 0xe9, 0x2c, 0x00, 0x08, 0x6f, 0xb9, 0x77, + 0xc3, 0x9c, 0x0e, 0xb8, 0x43, 0x01, 0x8f, 0xe9, 0x53, 0x8c, + 0x46, 0xdf, 0x94, 0x63, 0x87, 0x94, 0xee, 0xe2, 0xed, 0xab, + 0xf5, 0xf0, 0x70, 0xac, 0xad, 0x06, 0x53, 0x59, 0x8b, 0x0c, + 0x67, 0x47, 0xee, 0xb4, 0x26, 0x95, 0xe9, 0x46, 0x89, 0xe6, + 0x1c, 0xa2, 0x08, 0xe9, 0xc5, 0x06, 0xe1, 0x16, 0x39, 0xfd, + 0xb2, 0x46, 0xa3, 0x7e, 0x91, 0xc7, 0x56, 0x49, 0xda, 0xaa, + 0x32, 0x7a, 0xe9, 0x80, 0x3d, 0x8c, 0xe9, 0x41, 0x75, 0xe9, + 0xc6, 0x1f, 0xbb, 0xf7, 0x6e, 0xe9, 0x13, 0x74, 0x7b, 0x3f, + 0xd1, 0x68, 0xd1, 0xa1, 0x7a, 0x66, 0x66, 0x07, 0x0e, 0xa4, + 0x0e, 0xd3, 0xff, 0x9b, 0x75, 0x75, 0x34, 0xbe, 0xa8, 0x1c, + 0xb1, 0xc4, 0x00, 0x6e, 0x6e, 0x32, 0x2d, 0x49, 0xfe, 0xa0, + 0x14, 0xc6, 0x55, 0x4c, 0x36, 0x40, 0x79, 0x16, 0xd0, 0xd5, + 0x17, 0xb0, 0xfa, 0xf8, 0xe2, 0xed, 0xac, 0x12, 0x7d, 0x1e, + 0x27, 0xba, 0x89, 0x5a, 0xde, 0x9a, 0xeb, 0xf1, 0x2e, 0x3f, + 0x3f, 0x7f, 0xf7, 0x99, 0x70, 0xd7, 0x2d, 0xf2, 0xe2, 0xee, + 0x05, 0xd1, 0xd2, 0xd9, 0x7f, 0x70, 0xdc, 0x19, 0xc4, 0x6f, + 0x7a, 0x5c, 0xb0, 0x45, 0x17, 0x17, 0x57, 0x92, 0xf6, 0xab, + 0xbe, 0x28, 0x19, 0x48, 0x8f, 0x97, 0x76, 0xdf, 0xc4, 0x44, + 0x0a, 0x1b, 0xe7, 0xa5, 0xb2, 0x70, 0x92, 0x64, 0x15, 0x99, + 0x09, 0xbb, 0xbb, 0xe9, 0x02, 0x56, 0x54, 0xb0, 0xe8, 0x49, + 0xf6, 0x98, 0xcd, 0x58, 0x7a, 0xb2, 0x5f, 0xc4, 0x9d, 0x54, + 0xa4, 0x75, 0xfd, 0x49, 0x60, 0xf1, 0x8d, 0xbf, 0x2c, 0x23, + 0x13, 0xa6, 0xb9, 0x6c, 0x87, 0x5a, 0x2d, 0xb8, 0x42, 0xa6, + 0x84, 0x99, 0x55, 0x33, 0x2e, 0x15, 0x5e, 0xd4, 0xc9, 0xf3, + 0xd3, 0xb9, 0xe8, 0x71, 0xf6, 0xc6, 0x49, 0xac, 0x6d, 0x0c, + 0x63, 0xec, 0xf0, 0xf9, 0x48, 0x78, 0x45, 0xba, 0x50, 0xac, + 0xa8, 0xfe, 0x94, 0x3c, 0x53, 0x18, 0x8b, 0x2e, 0xc6, 0x9d, + 0x6c, 0x09, 0x13, 0xf1, 0x19, 0x4d, 0xcd, 0x0e, 0xb0, 0x75, + 0xc0, 0x48, 0x19, 0xaa, 0xb1, 0x13, 0x5f, 0xb8, 0x7f, 0xe9, + 0x8d, 0xe8, 0x1f, 0xd2, 0x6a, 0xf4, 0x80, 0x42, 0xd4, 0x9c, + 0x34, 0x10, 0xc2, 0xc4, 0xe2, 0x08, 0x1a, 0x6d, 0xbc, 0x2e, + 0x2a, 0x82, 0x36, 0x32, 0x95, 0x0d, 0x25, 0xaf, 0xed, 0xca, + 0x17, 0xb2, 0x42, 0x86, 0x76, 0x76, 0x40, 0x88, 0x56, 0x5d, + 0xe3, 0x41, 0x62, 0x8f, 0xc3, 0x64, 0xac, 0xe7, 0x8e, 0x39, + 0x0a, 0xe1, 0xc1, 0x9d, 0x4b, 0x01, 0x9c, 0xe9, 0xda, 0x67, + 0xef, 0x7f, 0x6c, 0xd3, 0xa0, 0x27, 0xc1, 0xab, 0xbe, 0xa6, + 0xa5, 0x19, 0x27, 0x5a, 0x55, 0x35, 0x70, 0xe7, 0xf5, 0xa0, + 0xfa, 0x0a, 0xce, 0x93, 0xea, 0xd4, 0xbf, 0xbd, 0x08, 0x20, + 0x01, 0x76, 0x1d, 0x65, 0x1e, 0x1d, 0x6e, 0x28, 0x0e, 0x1c, + 0x22, 0x43, 0xf3, 0x25, 0x77, 0x7c, 0xe4, 0x3b, 0x3a, 0x1f, + 0x04, 0x77, 0x19, 0x88, 0x57, 0xf1, 0x89, 0x14, 0xba, 0x05, + 0xf0, 0x38, 0x87, 0x48, 0xb3, 0x62, 0x5d, 0x8d, 0x79, 0xe7, + 0x7f, 0x07, 0x7c, 0x7f, 0xaf, 0x31, 0x86, 0x51, 0x8d, 0x89, + 0x2d, 0x50, 0x6f, 0xab, 0xf6, 0x41, 0xb1, 0xc9, 0x24, 0x6b, + 0x32, 0xf4, 0xe0, 0x89, 0xec, 0x4e, 0xbe, 0x9b, 0x15, 0xf4, + 0xa4, 0xd3, 0x0b, 0x49, 0x8c, 0xd4, 0x9a, 0x81, 0xa8, 0x03, + 0x79, 0x2d, 0xfe, 0xa7, 0x6d, 0x32, 0x22, 0x43, 0xcc, 0xa5, + 0xeb, 0x8b, 0xf5, 0x20, 0xc7, 0x73, 0x2d, 0xa0, 0xc8, 0x88, + 0x27, 0xe3, 0x1f, 0xa6, 0x03, 0x3a, 0x8f, 0xf6, 0x31, 0xda, + 0x31, 0x09, 0x5e, 0xd6, 0xe0, 0x7f, 0xc4, 0xa9, 0xa4, 0x58, + 0x50, 0xfe, 0xb9, 0x15, 0x78, 0xc6, 0xb3, 0x52, 0xeb, 0xe1, + 0x09, 0x21, 0x2d, 0xaf, 0x09, 0xf8, 0xea, 0xfa, 0xb2, 0x85, + 0x55, 0x8e, 0x2d, 0xc3, 0xc3, 0x3b, 0xd7, 0xa8, 0x97, 0x9d, + 0x16, 0x78, 0x50, 0x52, 0x86, 0x3a, 0xf3, 0xc6, 0xbe, 0xe6, + 0xbd, 0xdb, 0xa4, 0x9a, 0x24, 0x80, 0xb0, 0xc9, 0x70, 0x91, + 0x29, 0xe4, 0x52, 0xf5, 0xb5, 0x08, 0x7b, 0x54, 0x01, 0xd8, + 0x0e, 0x61, 0xe6, 0x6b, 0xf8, 0x55, 0xcf, 0x26, 0x53, 0xa4, + 0x61, 0x5b, 0xeb, 0x3d, 0x73, 0x88, 0x7e, 0x59, 0x3d, 0x8b, + 0x23, 0xae, 0x6c, 0x4b, 0xf5, 0x93, 0x5e, 0xc6, 0xf6, 0x2d, + 0x37, 0x9f, 0x62, 0x25, 0xf6, 0xcc, 0x85, 0x3c, 0x16, 0xc3, + 0x94, 0x66, 0xd8, 0xd8, 0x52, 0x6d, 0xa8, 0x69, 0x1e, 0x28, + 0xa6, 0xe1, 0x7d, 0xc7, 0x86, 0xa1, 0xe4, 0x5d, 0x01, 0xeb, + 0xb9, 0x09, 0xd8, 0xec, 0x2a, 0x6e, 0x21, 0xc9, 0x29, 0x1f, + 0xc8, 0x85, 0xc0, 0x7f, 0x43, 0xb6, 0x32, 0x3a, 0x69, 0xaf, + 0xc5, 0x0b, 0xa5, 0x86, 0xd8, 0x1b, 0xa3, 0x2a, 0xeb, 0x12, + 0x31, 0xdd, 0xe7, 0x54, 0xb7, 0xc5, 0x6d, 0x10, 0xcf, 0x83, + 0xdc, 0x38, 0x0a, 0x6c, 0xef, 0xa4, 0x90, 0xb3, 0x4a, 0x0e, + 0xd2, 0xdc, 0x69, 0xbb, 0x88, 0x58, 0x16, 0x2d, 0xb2, 0xfe, + 0xa1, 0x16, 0x74, 0x70, 0x31, 0x70, 0x25, 0x0e, 0x11, 0x2e, + 0x3e, 0x81, 0x35, 0xff, 0x39, 0x23, 0xb2, 0x7a, 0xb3, 0x2e, + 0x99, 0xd9, 0x2c, 0x6b, 0xd9, 0xce, 0x48, 0x22, 0x71, 0xb2, + 0x25, 0x66, 0x70, 0x17, 0x0a, 0xf1, 0x18, 0xeb, 0x70, 0x77, + 0x35, 0x9e, 0xbb, 0xe7, 0x16, 0xb9, 0x59, 0x90, 0xb3, 0x38, + 0x03, 0x8c, 0x17, 0x41, 0xdd, 0x74, 0x50, 0x2a, 0x17, 0x95, + 0x4b, 0xf1, 0x9b, 0xfe, 0xbe, 0x65, 0x89, 0xa1, 0x0a, 0xfe, + 0x47, 0xf5, 0xdb, 0xff, 0x4b, 0x35, 0x5a, 0x1e, 0xb4, 0x36, + 0x92, 0x98, 0x75, 0x99, 0x43, 0x99, 0x50, 0x27, 0xe1, 0x7a, + 0xcb, 0x03, 0x64, 0x55, 0x4f, 0x18, 0x10, 0x60, 0x14, 0x58, + 0x30, 0x18, 0x71, 0x10, 0xa2, 0xe3, 0x87, 0xb0, 0xb1, 0xe9, + 0xa0, 0xee, 0x51, 0x88, 0x08, 0x12, 0x24, 0xda, 0x83, 0xb9, + 0xb1, 0xab, 0xc9, 0x9d, 0x90, 0x6e, 0xb0, 0x21, 0xec, 0x80, + 0xfe, 0x11, 0x80, 0xda, 0x6f, 0xcb, 0xa7, 0x99, 0x3e, 0xc9, + 0x9b, 0x75, 0xbf, 0x33, 0x10, 0x06, 0xca, 0x01, 0xd0, 0x99, + 0x75, 0x63, 0x41, 0xed, 0x04, 0xfe, 0xf0, 0x6e, 0x3a, 0x0c, + 0x30, 0x64, 0xf7, 0x31, 0x9e, 0x19, 0x43, 0x7c, 0x3b, 0x52, + 0x30, 0x62, 0x7d, 0x07, 0xd1, 0xec, 0xa8, 0x50, 0x29, 0xaf, + 0x67, 0x46, 0x88, 0xf5, 0x5e, 0x7d, 0x22, 0xcc, 0xdc, 0x4b, + 0x9c, 0x31, 0x12, 0xa2, 0x18, 0xfc, 0xd3, 0x57, 0xc6, 0x60, + 0x5f, 0xad, 0x41, 0x49, 0x8c, 0xdb, 0x62, 0xe8, 0xda, 0x05, + 0x4e, 0x0f, 0x5a, 0x90, 0x3c, 0x6b, 0x06, 0x70, 0x18, 0xb0, + 0x8e, 0x43, 0x49, 0xf2, 0xa6, 0x34, 0x96, 0xdb, 0xa7, 0x9c, + 0xc2, 0xc3, 0xdf, 0xdd, 0x9f, 0x0b, 0x88, 0xcc, 0xb1, 0x4d, + 0x57, 0x8c, 0x51, 0x3b, 0xba, 0x20, 0x53, 0xd0, 0xf5, 0x83, + 0xf9, 0x7d, 0x4d, 0x7b, 0xae, 0x64, 0xc9, 0xc2, 0x09, 0x74, + 0xcf, 0x6e, 0x79, 0x6a, 0x8c, 0x92, 0x9c, 0x16, 0x73, 0xd0, + 0xaa, 0x0c, 0x8d, 0x3f, 0x00, 0xbb, 0x36, 0xd2, 0x8f, 0x7a, + 0xa9, 0x5c, 0x30, 0x3a, 0x51, 0x9c, 0xd1, 0x25, 0x2f, 0xee, + 0x16, 0x7d, 0xb1, 0x02, 0xa9, 0x5b, 0x2f, 0x18, 0x10, 0xc2, + 0x5b, 0xf6, 0x13, 0x6e, 0x77, 0xd8, 0x8b, 0xc8, 0x3a, 0x3b, + 0x75, 0x44, 0xb6, 0x9b, 0x8a, 0x31, 0x21, 0x4c, 0x25, 0x3f, + 0xcd, 0x4e, 0x50, 0x2b, 0xe0, 0xd5, 0x49, 0x3b, 0x0c, 0xc8, + 0x3b, 0xe0, 0x12, 0xb0, 0xf6, 0xff, 0xe1, 0xa9, 0xfd, 0xdb, + 0x19, 0x06, 0x2a, 0x4c, 0x83, 0xff, 0xb2, 0x63, 0x13, 0x85, + 0x06, 0xfc, 0xd5, 0x4c, 0x5a, 0x57, 0x34, 0x79, 0xe6, 0xc6, + 0x20, 0x9b, 0x21, 0x0e, 0x50, 0x7c, 0x9f, 0xb4, 0x10, 0xa9, + 0xa4, 0xa3, 0x3c, 0x43, 0x84, 0x16, 0x4c, 0x3d, 0xb3, 0x53, + 0xc2, 0x12, 0xfd, 0x21, 0x32, 0xf8, 0x42, 0x69, 0x64, 0x9e, + 0xd1, 0x42, 0x65, 0xbb, 0x86, 0x7c, 0x9b, 0xcb, 0xfd, 0xac, + 0xdc, 0xe5, 0xba, 0xd6, 0xa9, 0x84, 0xca, 0x8e, 0x39, 0x2a, + 0x9c, 0x69, 0x3e, 0x1a, 0x0d, 0xe7, 0xc9, 0xcd, 0xd0, 0x23, + 0x2e, 0xfb, 0xcd, 0xf8, 0x63, 0x56, 0x51, 0x13, 0x63, 0x9f, + 0xaa, 0x8c, 0x7e, 0x06, 0xc2, 0xdc, 0xff, 0x9d, 0x6a, 0x74, + 0x6a, 0xd5, 0x9b, 0xb5, 0x70, 0x4a, 0xda, 0xc4, 0x39, 0xda, + 0xa2, 0x31, 0x6e, 0x54, 0x38, 0xec, 0xd5, 0x82, 0xff, 0x78, + 0xae, 0x8b, 0x92, 0x84, 0xbf, 0x69, 0x1e, 0x4c, 0x7e, 0x05, + 0x31, 0x22, 0x8a, 0xcd, 0xd7, 0x93, 0xa6, 0x11, 0x34, 0xb9, + 0x6b, 0x57, 0xbd, 0xe2, 0xa2, 0x66, 0xd5, 0x6e, 0x0a, 0x4f, + 0xd4, 0x3b, 0xc6, 0x6c, 0x19, 0xcf, 0x6e, 0x4a, 0xeb, 0xbc, + 0x0d, 0x51, 0x36, 0x5d, 0xcb, 0x52, 0xe9, 0xb1, 0xa5, 0x18, + 0x2d, 0x90, 0x45, 0xfd, 0x94, 0x5a, 0x54, 0xa2, 0x5b, 0xbe, + 0xbd, 0xd6, 0x66, 0xcf, 0x69, 0xba, 0x58, 0x24, 0xda, 0x20, + 0x4d, 0x6b, 0x5f, 0x52, 0x5b, 0x35, 0x9e, 0xa8, 0x0b, 0x09, + 0x1d, 0x80, 0x3f, 0x23, 0xb5, 0x0c, 0x25, 0xa9, 0x2e, 0x89, + 0xf1, 0x42, 0x5a, 0xd1, 0x03, 0xbf, 0x79, 0xcf, 0x01, 0x8d, + 0xab, 0x4d, 0x94, 0x5a, 0xce, 0xc1, 0x7f, 0x4c, 0x6c, 0x96, + 0x34, 0xf5, 0x7c, 0xdb, 0x04, 0x15, 0xf3, 0x85, 0xa9, 0xd8, + 0xb4, 0x8a, 0x5f, 0x14, 0x32, 0x53, 0x35, 0x47, 0x57, 0xd7, + 0xa6, 0x95, 0x80, 0x50, 0x09, 0xcf, 0x90, 0x23, 0x4a, 0xd2, + 0x63, 0x09, 0x80, 0xa9, 0xe2, 0xf8, 0xc7, 0x0d, 0x02, 0x39, + 0xc1, 0xd1, 0x3a, 0x09, 0x04, 0x81, 0x10, 0x26, 0x0a, 0x6a, + 0x4e, 0x56, 0xe4, 0x29, 0xdf, 0x82, 0x66, 0x35, 0x0c, 0x0e, + 0x19, 0x17, 0x6f, 0x01, 0x24, 0x08, 0xf1, 0x0a, 0x81, 0x3b, + 0x89, 0x7e, 0x9c, 0x4a, 0xac, 0xb7, 0xbc, 0x59, 0x2a, 0x43, + 0xa9, 0x8a, 0xbd, 0x83, 0xdb, 0x89, 0x81, 0x57, 0xd7, 0x71, + 0x10, 0x17, 0x7e, 0x2a, 0x8a, 0x2e, 0x23, 0x66, 0x69, 0x71, + 0x3b, 0xad, 0x7c, 0x30, 0x82, 0x1e, 0xb5, 0xcc, 0xc6, 0xe7, + 0xf5, 0x29, 0x37, 0xdf, 0xf3, 0x26, 0x1a, 0x9f, 0x63, 0x72, + 0x91, 0x80, 0x10, 0x4e, 0x36, 0x1e, 0xf5, 0x3d, 0x05, 0xbd, + 0x1d, 0xac, 0x97, 0x34, 0xec, 0x95, 0x21, 0x92, 0x2f, 0x9d, + 0x1b, 0x0e, 0xfe, 0x60, 0x78, 0x78, 0x39, 0xf6, 0xe2, 0xad, + 0x58, 0x33, 0x0e, 0x1a, 0xe9, 0x2e, 0x13, 0x1d, 0xe5, 0x36, + 0xee, 0x8b, 0x25, 0x4d, 0x66, 0x3e, 0x71, 0x6e, 0x93, 0xcb, + 0x1f, 0x67, 0xe7, 0xdd, 0x25, 0x21, 0x48, 0xee, 0xc2, 0xed, + 0x2a, 0x3b, 0x68, 0x7b, 0x82, 0xb7, 0xea, 0xc2, 0xc0, 0xd4, + 0x3f, 0xa7, 0xdd, 0x67, 0x43, 0xb5, 0x7a, 0xe9, 0x08, 0xab, + 0x26, 0xa1, 0xae, 0xd1, 0x52, 0x3e, 0xd6, 0xee, 0x21, 0x09, + 0xb7, 0xe2, 0xb8, 0x30, 0xa9, 0x20, 0x7a, 0xd9, 0x26, 0xbc, + 0xe4, 0x60, 0xf1, 0x79, 0x1e, 0xea, 0xe8, 0xaa, 0xaf, 0x1e, + 0x09, 0x0f, 0x3b, 0x5e, 0x7b, 0x1f, 0x25, 0xae, 0x83, 0x3c, + 0x69, 0xb7, 0x8f, 0xed, 0x7e, 0x6d, 0xb5, 0xeb, 0x9c, 0x80, + 0xee, 0x01, 0x7c, 0x54, 0xa9, 0x12, 0x2f, 0x42, 0xe5, 0xc0, + 0x3a, 0x48, 0xa8, 0xa7, 0x00, 0x97, 0x8a, 0x1d, 0x03, 0x04, + 0x06, 0xb4, 0x30, 0x79, 0x77, 0x27, 0x89, 0x3a, 0x25, 0xac, + 0x8b, 0xde, 0x9b, 0x4f, 0x27, 0x3c, 0xa6, 0x70, 0x88, 0x61, + 0x76, 0x3a, 0xfe, 0x4e, 0xba, 0xeb, 0xcb, 0xc6, 0x67, 0xd7, + 0xb9, 0xed, 0xa5, 0x5e, 0x61, 0xe8, 0x50, 0x6f, 0x97, 0x73, + 0x5b, 0x07, 0xfb, 0xd7, 0xac, 0x8c, 0xde, 0xcf, 0xec, 0x73, + 0x7b, 0x8c, 0x84, 0xce, 0x35, 0x6a, 0x81, 0x54, 0xee, 0x2b, + 0x3b, 0x01, 0xea, 0x29, 0x35, 0x6c, 0x09, 0x27, 0x14, 0xc0, + 0x04, 0x93, 0xb4, 0x7e, 0x59, 0xd6, 0x8d, 0x00, 0xdd, 0x46, + 0xa3, 0x08, 0x4e, 0x9f, 0x89, 0x81, 0xd8, 0x1e, 0xf2, 0xbc, + 0x04, 0x4d, 0xa4, 0x41, 0xe7, 0xd7, 0x82, 0xa6, 0x90, 0x31, + 0xfa, 0x91, 0xf6, 0xa7, 0x19, 0x35, 0xea, 0x09, 0x0a, 0xd2, + 0x9c, 0x18, 0xd6, 0x3b, 0xb9, 0xfe, 0xfe, 0xcc, 0x9b, 0x69, + 0xbb, 0x14, 0x78, 0xc5, 0xef, 0xa4, 0x8d, 0xd9, 0x46, 0xef, + 0x47, 0x80, 0x1d, 0xf9, 0x3b, 0xd6, 0xc5, 0x0f, 0xee, 0xb5, + 0x93, 0x0a, 0x21, 0x10, 0x77, 0xd1, 0x27, 0x51, 0xc2, 0xa9, + 0xe7, 0x52, 0xa5, 0x1f, 0x66, 0x25, 0x80, 0xdb, 0x5d, 0x17, + 0x02, 0xbb, 0x34, 0x1e, 0x46, 0x42, 0x32, 0x96, 0xdd, 0x7f, + 0xa4, 0xac, 0xfc, 0x5a, 0xf5, 0x09, 0xe7, 0x92, 0x53, 0xeb, + 0x88, 0xdc, 0x33, 0x88, 0x53, 0x68, 0xf4, 0x5f, 0xd7, 0xed, + 0xa4, 0xb7, 0x88, 0x9f, 0x0c, 0x67, 0x86, 0xb9, 0x96, 0xc7, + 0x0a, 0xe5, 0x6b, 0xac, 0x89, 0xb0, 0x31, 0x68, 0x4c, 0x9c, + 0xf0, 0x55, 0xcb, 0x70, 0x53, 0x22, 0x8e, 0xca, 0xee, 0x33, + 0xc6, 0x43, 0xff, 0xde, 0xdf, 0xe3, 0x30, 0x8a, 0xbe, 0x7c, + 0x88, 0xf1, 0x3e, 0x29, 0xd6, 0x1b, 0x07, 0x43, 0xbd, 0x4b, + 0xc8, 0x51, 0xe6, 0x8e, 0x17, 0x45, 0x98, 0xb9, 0x1f, 0xf9, + 0xdb, 0xcd, 0x52, 0x52, 0xc2, 0x47, 0x12, 0xfc, 0x51, 0x57, + 0x63, 0x3a, 0xbf, 0x7c, 0x2e, 0xd4, 0xb1, 0x09, 0x69, 0x39, + 0x8d, 0xb7, 0x15, 0x2a, 0xcb, 0x89, 0xcb, 0x28, 0x67, 0xcf, + 0xa7, 0x4a, 0x0b, 0xb8, 0x3d, 0x10, 0x30, 0xd5, 0x4a, 0xd9, + 0xea, 0x42, 0x83, 0x4e, 0x2a, 0x8d, 0x38, 0xf9, 0xc8, 0xe8, + 0x33, 0xa1, 0x09, 0xd9, 0xf0, 0x75, 0xde, 0xe3, 0xc2, 0x42, + 0x8f, 0x49, 0xd8, 0x7c, 0x7f, 0x47, 0xfb, 0x0c, 0xc1, 0x2e, + 0x66, 0x01, 0x09, 0x96, 0x0c, 0x56, 0x72, 0x66, 0x3e, 0x38, + 0x4a, 0xb4, 0xcd, 0xc4, 0xd0, 0x4e, 0x82, 0xce, 0xac, 0x5f, + 0x40, 0x3b, 0x59, 0x80, 0x84, 0xc6, 0x9b, 0x43, 0xc4, 0x9b, + 0xd6, 0x4f, 0x91, 0x74, 0x3f, 0xdd, 0x78, 0xf0, 0xe5, 0xd8, + 0xbe, 0x71, 0x21, 0xb7, 0x11, 0x05, 0x09, 0x77, 0x87, 0xd9, + 0x06, 0xc9, 0x04, 0xc0, 0xb9, 0x2c, 0x59, 0xdb, 0x2b, 0xbc, + 0x22, 0x17, 0xcb, 0xef, 0x93, 0xe8, 0xfb, 0x5c, 0x2a, 0x74, + 0x70, 0x9f, 0x9d, 0x45, 0x0c, 0xe9, 0xec, 0xfe, 0x57, 0x44, + 0x22, 0x1a, 0xc8, 0xb5, 0x9d, 0xbc, 0x8b, 0x75, 0x5d, 0x8d, + 0x3d, 0xdb, 0xb1, 0x65, 0x01, 0x4c, 0x4a, 0xdd, 0x68, 0x06, + 0x39, 0x57, 0x15, 0x3c, 0x4a, 0x1c, 0x1a, 0x29, 0x88, 0xfa, + 0xe7, 0x68, 0x05, 0x9e, 0xc9, 0xc3, 0x95, 0x52, 0x51, 0x46, + 0xb9, 0xf3, 0x14, 0xb2, 0x21, 0x99, 0xd4, 0xbf, 0x5e, 0x64, + 0x58, 0xa9, 0x2f, 0x87, 0x84, 0x00, 0x4e, 0x8c, 0x6b, 0x86, + 0xa7, 0xb6, 0x72, 0x40, 0xab, 0x49, 0xa7, 0x8f, 0x37, 0xc0, + 0x3c, 0xbc, 0xc1, 0xb0, 0xce, 0x28, 0x2a, 0x40, 0xd7, 0x17, + 0xcd, 0x18, 0x29, 0xf7, 0x40, 0xa9, 0xd4, 0x2b, 0xe5, 0x38, + 0x59, 0xb7, 0xe2, 0xf3, 0xec, 0xe6, 0x3d, 0xa2, 0x2d, 0x70, + 0x92, 0x73, 0x41, 0x3b, 0x37, 0xe4, 0x21, 0x6c, 0x88, 0x1c, + 0xe3, 0xda, 0x08, 0x7d, 0xeb, 0xfb, 0xdb, 0x33, 0xaf, 0x0f, + 0xad, 0x72, 0x06, 0x8a, 0x60, 0x46, 0x3d, 0x30, 0x03, 0xe4, + 0x50, 0x8f, 0x2f, 0xf4, 0x33, 0xe3, 0x2b, 0x33, 0x2a, 0x31, + 0x70, 0x79, 0x07, 0xc0, 0x62, 0xca, 0xdc, 0xaa, 0xba, 0x74, + 0x9f, 0xac, 0xc0, 0xab, 0xa9, 0x5b, 0x8a, 0x2b, 0x40, 0xe9, + 0x34, 0x85, 0x12, 0x42, 0x24, 0xdf, 0x2c, 0xaa, 0x38, 0xc2, + 0x6f, 0x8c, 0x2c, 0x7a, 0x4c, 0x2e, 0xbd, 0x9c, 0x10, 0x5d, + 0x1a, 0x16, 0xf5, 0xce, 0x96, 0x17, 0xf4, 0x96, 0xa7, 0x30, + 0x05, 0xfa, 0x55, 0xfd, 0x31, 0xcc, 0xcc, 0xf0, 0x98, 0x51, + 0x18, 0x10, 0x06, 0x5c, 0x33, 0x4e, 0xde, 0xb3, 0xf6, 0x90, + 0x37, 0x6a, 0x03, 0x71, 0xe7, 0x3f, 0x21, 0x09, 0x10, 0x0f, + 0xaa, 0xa2, 0x23, 0x5b, 0xf9, 0x7a, 0x47, 0xfa, 0x68, 0xf3, + 0xcf, 0xae, 0xf2, 0x9a, 0x1d, 0xab, 0x8b, 0xac, 0x60, 0xe7, + 0xbd, 0xbc, 0x1f, 0xfa, 0x8c, 0x93, 0x26, 0x8a, 0x89, 0x58, + 0x4f, 0x0d, 0xf6, 0x70, 0x62, 0x96, 0xd5, 0x3b, 0x52, 0x53, + 0xa0, 0x44, 0x8f, 0x1a, 0x51, 0x56, 0x68, 0xc3, 0xf0, 0xc6, + 0xc3, 0x70, 0x64, 0xef, 0x92, 0x67, 0x42, 0x76, 0x96, 0xa1, + 0xec, 0x05, 0x7f, 0x34, 0x3b, 0x8f, 0x09, 0x4a, 0xe7, 0xc4, + 0x02, 0xcf, 0x51, 0xd4, 0x72, 0x5b, 0xa5, 0xae, 0xf6, 0xed, + 0xfa, 0xb9, 0xf8, 0xfd, 0xd7, 0xd4, 0x61, 0xb6, 0x54, 0x0e, + 0x9a, 0xbb, 0xc8, 0x94, 0x21, 0x67, 0x56, 0xe9, 0xbc, 0xcc, + 0x88, 0x5e, 0xd6, 0x93, 0xfd, 0xb8, 0xdd, 0x22, 0xea, 0x5f, + 0x4e, 0xdf, 0xf4, 0xf2, 0x8c, 0x9e, 0xa1, 0xf8, 0x49, 0x1f, + 0x42, 0x0e, 0x11, 0x83, 0xc6, 0x83, 0xa4, 0x23, 0xd6, 0x0d, + 0x14, 0x3e, 0x8b, 0x01, 0xc6, 0xec, 0xfb, 0x4b, 0xc8, 0xe2, + 0x51, 0xbf, 0x31, 0xcc, 0x2b, 0xfb, 0x16, 0x3f, 0x9e, 0x55, + 0x98, 0x95, 0x86, 0x65, 0xa4, 0x22, 0xe2, 0xc9, 0x72, 0x97, + 0x69, 0x0d, 0x2e, 0x5d, 0x87, 0x6a, 0x8e, 0x8a, 0x1b, 0xc3, + 0xbd, 0x19, 0xcd, 0xd2, 0xf9, 0x5b, 0xbf, 0xd1, 0x32, 0x11, + 0xdc, 0xdd, 0xd3, 0x9b, 0x41, 0x85, 0x7c, 0x38, 0x41, 0x6f, + 0x74, 0x4b, 0x0c, 0xc0, 0x17, 0x75, 0xee, 0x55, 0x5f, 0xeb, + 0x8e, 0xb7, 0x9d, 0xbf, 0x35, 0xda, 0xea, 0x07, 0x3c, 0xe5, + 0x7f, 0x22, 0x1c, 0x4d, 0x22, 0x1d, 0xe4, 0x4b, 0xc7, 0xe5, + 0x6a, 0x59, 0xdb, 0x9f, 0xb2, 0x79, 0xc1, 0xc9, 0x20, 0x97, + 0xe5, 0xcf, 0x2f, 0xc1, 0xb7, 0x5d, 0xb1, 0xbf, 0x6d, 0xca, + 0x7a, 0x34, 0x1d, 0x39, 0x88, 0x1c, 0x2d, 0x83, 0xd5, 0xf6, + 0xef, 0x4c, 0xce, 0xe7, 0x2e, 0x35, 0xcd, 0xab, 0x7d, 0x64, + 0xd6, 0x57, 0x93, 0x66, 0x7e, 0xab, 0x5b, 0xf2, 0xc9, 0x49, + 0xd8, 0x67, 0x97, 0x01, 0x72, 0x5a, 0xf2, 0xfa, 0x7d, 0x27, + 0x56, 0x88, 0x9f, 0xb0, 0xc1, 0x3c, 0x2c, 0x9d, 0x5a, 0x5f, + 0x96, 0x30, 0xee, 0x3a, 0x90, 0x74, 0xb0, 0x9f, 0x30, 0x9b, + 0x98, 0x86, 0xff, 0x15, 0x0e, 0xad, 0x55, 0x23, 0xbf, 0xc4, + 0xb3, 0x21, 0xfc, 0x1d, 0x45, 0x5c, 0x12, 0x78, 0xa4, 0x63, + 0xe2, 0x05, 0xda, 0x25, 0x82, 0xbb, 0x7f, 0xa3, 0x1f, 0xc7, + 0x2b, 0x1c, 0xbd, 0x6c, 0x34, 0xe0, 0xc9, 0xf1, 0x44, 0x70, + 0xec, 0x13, 0xb9, 0x73, 0x1c, 0x82, 0x45, 0x99, 0xe6, 0xb1, + 0xf0, 0x9f, 0xfa, 0x79, 0xa7, 0x6f, 0x3e, 0xf4, 0xd1, 0x18, + 0x90, 0x4b, 0xd2, 0xdb, 0x5a, 0x0f, 0x9f, 0x5d, 0x97, 0x67, + 0x52, 0x19, 0x19, 0x3c, 0x1c, 0x74, 0x40, 0x8c, 0x7b, 0xbf, + 0xfe, 0x02, 0x26, 0x66, 0x46, 0xab, 0x3f, 0x46, 0x94, 0x56, + 0x47, 0x87, 0x11, 0xa0, 0x3d, 0x46, 0xfa, 0xae, 0xc9, 0x78, + 0x95, 0x36, 0x99, 0x98, 0xff, 0xe1, 0x59, 0x74, 0xc8, 0xa2, + 0x79, 0x61, 0x7e, 0x42, 0xed, 0x9a, 0x2f, 0x13, 0x1b, 0x8e, + 0x6b, 0x25, 0x53, 0x4d, 0xbf, 0xf8, 0x6a, 0x40, 0x97, 0x5c, + 0x52, 0x6b, 0xe8, 0x09, 0x5f, 0x3d, 0x4f, 0xfe, 0x8f, 0xdf, + 0x66, 0x10, 0x49, 0xd7, 0x05, 0x56, 0x9e, 0x32, 0x74, 0x3c, + 0x01, 0x1e, 0x50, 0x7d, 0x1a, 0xae, 0xed, 0xcc, 0x07, 0x6f, + 0x9c, 0x3b, 0x37, 0x9e, 0x82, 0x0f, 0xa5, 0x6e, 0x1e, 0x18, + 0x89, 0xda, 0xaa, 0xdb, 0x1a, 0xd4, 0xc7, 0x30, 0xd1, 0x54, + 0x42, 0x48, 0x08, 0xeb, 0x2f, 0x26, 0xd2, 0x09, 0x11, 0xa7, + 0x56, 0x27, 0xb0, 0x91, 0x9d, 0x16, 0x54, 0x6c, 0x6c, 0x50, + 0x56, 0x7e, 0xd2, 0xd8, 0xf9, 0x83, 0xe8, 0xa3, 0x8d, 0x52, + 0x0e, 0x42, 0x2f, 0xb5, 0x87, 0xd7, 0x4b, 0x9a, 0xf5, 0x91, + 0xf9, 0x41, 0x89, 0x79, 0x55, 0xfe, 0x14, 0x7b, 0x0a, 0xd8, + 0xe3, 0x83, 0xad, 0x02, 0x26, 0x3c, 0x4d, 0x08, 0xe4, 0x47, + 0x41, 0xc9, 0x36, 0x12, 0xdc, 0xc3, 0x53, 0x7e, 0xb6, 0xf7, + 0xed, 0x6c, 0x3f, 0x4a, 0x97, 0x98, 0x1d, 0xbe, 0x4e, 0x12, + 0x58, 0xc3, 0x1c, 0x1b, 0xfb, 0xd2, 0xf5, 0x16, 0x80, 0xd4, + 0xa9, 0x0b, 0xab, 0x86, 0xa5, 0xd4, 0xd8, 0x7f, 0x3f, 0xc4, + 0x71, 0xbb, 0x69, 0xc6, 0xd9, 0x9b, 0x72, 0x95, 0x6d, 0xf9, + 0x79, 0x52, 0x6b, 0xde, 0x65, 0x97, 0xe5, 0x5e, 0xd1, 0xc1, + 0xbd, 0x94, 0x53, 0xed, 0xf4, 0x4e, 0x6c, 0xd4, 0x7f, 0x3e, + 0xca, 0xd4, 0x0e, 0xb9, 0x9a, 0x56, 0x73, 0x56, 0xb2, 0xde, + 0x4c, 0x3c, 0x1c, 0xdf, 0x26, 0x14, 0x67, 0xb4, 0x67, 0x35, + 0x54, 0x4c, 0x45, 0x5e, 0x37, 0x55, 0xfd, 0x3b, 0x65, 0x5d, + 0xc7, 0xdd, 0x4d, 0xd5, 0x8b, 0x32, 0x43, 0xf7, 0xfc, 0xd6, + 0xbb, 0xb5, 0x98, 0x3d, 0x49, 0xe1, 0xac, 0x40, 0xc9, 0xd1, + 0xf5, 0x7b, 0x5f, 0x6d, 0x46, 0xea, 0x15, 0xaf, 0x3d, 0x02, + 0xbb, 0xe4, 0x98, 0x47, 0xd3, 0x70, 0xc5, 0xa8, 0x72, 0x8e, + 0xae, 0xd8, 0x23, 0x2d, 0xcf, 0x50, 0x5e, 0xa6, 0x7d, 0xbd, + 0x81, 0xd4, 0x11, 0x12, 0xbf, 0x7f, 0x37, 0xee, 0x5d, 0x39, + 0x4c, 0x0f, 0x92, 0xb0, 0x7e, 0x20, 0x3c, 0x71, 0x4e, 0x92, + 0x33, 0x46, 0xd6, 0xb2, 0xbf, 0xa4, 0x57, 0xcb, 0x0d, 0x4e, + 0xe8, 0x54, 0x07, 0x5b, 0x01, 0x15, 0x46, 0x61, 0xcc, 0x7d, + 0x9f, 0xa5, 0xab, 0x27, 0x34, 0x16, 0x45, 0x9c, 0x82, 0x0e, + 0x60, 0x97, 0x44, 0x8b, 0x0e, 0x36, 0x29, 0x58, 0x10, 0x07, + 0x97, 0x83, 0x33, 0x78, 0x27, 0xff, 0xee, 0xa0, 0x73, 0x3f, + 0xf4, 0x06, 0xec, 0x56, 0x11, 0xfc, 0xff, 0xc6, 0xee, 0x81, + 0x0a, 0xd5, 0x93, 0xb0, 0x41, 0x4e, 0xd3, 0xbf, 0xf7, 0xb8, + 0xa5, 0x81, 0x4c, 0xee, 0x7f, 0xdb, 0x48, 0x39, 0xed, 0x98, + 0x4e, 0x8c, 0xb9, 0xc6, 0x72, 0x85, 0xa2, 0x91, 0x7d, 0x2d, + 0x74, 0x96, 0xae, 0x8d, 0x4d, 0x8a, 0x77, 0xf2, 0xe6, 0xcc, + 0x20, 0x7e, 0x40, 0x31, 0x8a, 0xd6, 0xd1, 0xc4, 0xef, 0x74, + 0x7a, 0x5b, 0x2c, 0x74, 0x02, 0x3b, 0xe1, 0x12, 0x23, 0x8b, + 0x22, 0x6b, 0xef, 0x99, 0x65, 0xa7, 0x62, 0x27, 0x11, 0xcd, + 0x7d, 0xc2, 0xf5, 0x23, 0x3b, 0xb4, 0xb2, 0x85, 0xab, 0x01, + 0x97, 0x51, 0x8e, 0xd6, 0x78, 0x23, 0xeb, 0x9c, 0x93, 0x0a, + 0xb6, 0xa0, 0x7f, 0x25, 0x37, 0x33, 0xc6, 0x42, 0x0c, 0x73, + 0x8d, 0xec, 0x34, 0x20, 0xa1, 0x01, 0x6c, 0xda, 0xe2, 0x3c, + 0xe4, 0x2a, 0xd9, 0xaf, 0xa6, 0xd7, 0x6d, 0x70, 0x33, 0x93, + 0xfa, 0x74, 0x39, 0xab, 0xa1, 0x4f, 0xfb, 0x0c, 0xa1, 0x9e, + 0x67, 0x53, 0x77, 0x95, 0x60, 0xde, 0x01, 0x8b, 0xb0, 0x60, + 0x95, 0x6d, 0x87, 0xa2, 0xc3, 0xbe, 0xb6, 0xbe, 0x97, 0xe9, + 0x71, 0x33, 0x5f, 0x44, 0x20, 0x15, 0x06, 0x89, 0x54, 0x8d, + 0x72, 0x2e, 0x93, 0x3b, 0x57, 0xd5, 0x15, 0x21, 0x1a, 0x00, + 0xc4, 0x7b, 0xec, 0xa0, 0x75, 0xcf, 0x1d, 0x15, 0x1a, 0x18, + 0x9b, 0xd8, 0xb1, 0xd8, 0xbf, 0x59, 0x4b, 0xf4, 0xe3, 0x37, + 0x93, 0x3a, 0xbe, 0x1f, 0x45, 0x0b, 0xc1, 0x5f, 0xbd, 0x6a, + 0x72, 0x78, 0x9d, 0xb7, 0x5a, 0xd4, 0xa7, 0xa5, 0xd9, 0x83, + 0x3d, 0xda, 0x48, 0x49, 0x20, 0x87, 0xd8, 0x5a, 0xbf, 0x08, + 0x6d, 0xc8, 0xc9, 0x96, 0x54, 0xc1, 0xc9, 0xc2, 0x27, 0xbb, + 0xbe, 0x08, 0xae, 0x22, 0xdd, 0xb2, 0xb6, 0x56, 0xa0, 0x78, + 0xb4, 0xa1, 0xe8, 0x27, 0xd5, 0x5f, 0x3a, 0xb4, 0xd5, 0xdf, + 0xc3, 0x01, 0x5b, 0x79, 0xd6, 0xee, 0x82, 0x43, 0x32, 0xfc, + 0x57, 0x2d, 0xd2, 0x61, 0xb3, 0xcd, 0xe6, 0xe6, 0x12, 0xd5, + 0xa9, 0x74, 0x63, 0x45, 0xa6, 0xac, 0x34, 0x6e, 0x4f, 0x7f, + 0x67, 0x5a, 0xda, 0x47, 0xec, 0x69, 0x13, 0xff, 0x78, 0x2b, + 0xc6, 0x93, 0xe8, 0x49, 0x8f, 0x00, 0xa9, 0x49, 0xfb, 0x34, + 0x06, 0xbb, 0x30, 0x47, 0x1d, 0x81, 0xbc, 0x24 }, + { 0x86, 0x44, 0x65, 0x48, 0x98, 0x02, 0x89, 0x94, 0xe2, 0xba, + 0xcd, 0xbd, 0x38, 0x31, 0xa1, 0xed }, + }, + { 24, 16, 20, + { 0x48, 0xb8, 0x2b, 0x72, 0xfc, 0x81, 0xbe, 0x86, + 0x86, 0x0f, 0x72, 0x06, 0x5e, 0xfa, 0x62, 0x18, + 0x6f, 0x9d, 0xa5, 0x96, 0xbd, 0xf9, 0x51, 0x58 }, + { 0x24, 0xda, 0x67, 0xae, 0xf7, 0x4b, 0xe3, 0x33, + 0x85, 0x89, 0xcc, 0xb6 }, + { 0xf8, 0x6a, 0x57, 0xa3, 0x0c, 0x06, 0xef, 0xb1, + 0x0e, 0xcb, 0xeb, 0x3d, 0x5a, 0x9d, 0x97, 0xb5}, + { 0xc1, 0xf7, 0xf5, 0xc8, 0xf8, 0xcc, 0x51, 0x37, + 0xa5, 0x39, 0x91, 0x94, 0x1f, 0x38, 0x8f, 0xfd, + 0x2b, 0x27, 0xf0, 0xdd}, + { 0x4b, 0xe5, 0x8c, 0xd0, 0x63, 0x78, 0xc0, 0x38, + 0x78, 0xd4, 0xf1, 0x65, 0x94, 0x43, 0xc5, 0xd1}, + { 0x84, 0xdd, 0x00, 0xb8, 0xb0, 0x3a, 0xcb, 0x92, + 0x19, 0xec, 0x51, 0x16, 0xe3, 0xde, 0x73, 0x62} + }, +#endif /* !USE_LIBSODIUM_AES_GCM */ + { 32, 32, 16, + { 0x27, 0x2d, 0x16, 0x49, 0xa3, 0xdd, 0x80, 0x4d, + 0xe0, 0x96, 0x2d, 0x3e, 0x07, 0x06, 0x4a, 0x70, + 0x54, 0xc0, 0x0a, 0x62, 0x34, 0xab, 0x1b, 0x0c, + 0xdc, 0xf6, 0x85, 0xab, 0x39, 0x48, 0x37, 0xe5}, + { 0x95, 0x5b, 0x58, 0x97, 0xf6, 0xb9, 0x80, 0x6b, + 0xbe, 0xc5, 0xc3, 0x3e}, + { 0x36, 0xe5, 0x7c, 0x29, 0xc0, 0x8c, 0x51, 0xad, + 0x7f, 0xa9, 0x1c, 0x04, 0x16, 0xf9, 0x76, 0xcf, + 0xd0, 0x11, 0x78, 0x0e, 0xb4, 0x4c, 0xc5, 0xab, + 0xd3, 0x4c, 0x7b, 0x43, 0x1b, 0x09, 0x3b, 0x8d}, + { 0x33, 0xe6, 0x18, 0xec, 0xbb, 0xe5, 0xeb, 0x05, + 0x66, 0xdf, 0x21, 0xc3, 0xc3, 0x4b, 0x7e, 0x25}, + { 0xcd, 0x6a, 0xeb, 0x34, 0x50, 0x81, 0xdc, 0x0b, + 0xb2, 0xc8, 0xb4, 0xd1, 0x9b, 0x28, 0x06, 0x58, + 0xfb, 0x87, 0xc0, 0xf2, 0xbd, 0x0f, 0x4c, 0x9d, + 0xa6, 0x94, 0xdc, 0x1f, 0xee, 0xb3, 0x2f, 0x4e}, + { 0xdd, 0x37, 0xea, 0xc6, 0xbd, 0x6a, 0x4d, 0x36, + 0x18, 0x24, 0x17, 0x38, 0x77, 0x97, 0x35, 0xd7} + } + }; +/* + Test GCM mode AES +*/ + for (i = 0; i < (int32)(sizeof(tests)/sizeof(tests[0])); i++) { +#ifndef USE_CL_GCM_GIV + if (tests[i].keylen * 8 == 192) + continue; /* Skip AES-192 as some impl do not support it. */ +#endif /* USE_CL_GCM_GIV */ + if (i == 1) { + _psTraceInt(" AES-GCM-%d long known vector encrypt test... ", tests[i].keylen * 8); + } else { + _psTraceInt(" AES-GCM-%d known vector encrypt test... ", tests[i].keylen * 8); + } + psAesInitGCM(&eCtx, tests[i].key, tests[i].keylen); + psAesReadyGCM(&eCtx, tests[i].iv, tests[i].aad, tests[i].aadlen); + psAesEncryptGCM(&eCtx, tests[i].pt, ciphertext, tests[i].ptlen); + psAesGetGCMTag(&eCtx, 16, tag); + if ((memcmp(ciphertext, tests[i].ct, tests[i].ptlen) != 0) || + (memcmp(tag, tests[i].tag, 16) != 0)) { + printf("FAILED: memcmp mismatch\n"); + res = PS_FAILURE; + } else { + printf("PASSED\n"); + } + +#ifndef USE_ONLY_DECRYPT_GCM_WITH_TAG + _psTraceInt(" AES-GCM-%d known vector decrypt (tagless) test... ", tests[i].keylen * 8); + psAesInitGCM(&dCtx, tests[i].key, tests[i].keylen); + psAesReadyGCM(&dCtx, tests[i].iv, tests[i].aad, tests[i].aadlen); +#ifdef USE_LIBSODIUM_AES_GCM + /* TODO - libsodium cipher text must include the tag */ + unsigned char * cipherTextAuthData; + cipherTextAuthData = psMalloc(NULL, tests[i].ptlen+16); + + memcpy(cipherTextAuthData,tests[i].ct,tests[i].ptlen); + memcpy(cipherTextAuthData+tests[i].ptlen,tests[i].tag,16); + + if (psAesDecryptGCM(&dCtx,cipherTextAuthData, tests[i].ptlen+16,plaintext,tests[i].ptlen) != PS_SUCCESS) { + printf("FAILED: authentication failed\n"); + } else if (memcmp(plaintext, tests[i].pt, tests[i].ptlen) != 0) { + printf("FAILED: data mismatch\n"); + } else { + printf("PASSED\n"); + } + psFree(cipherTextAuthData, NULL); +#else + psAesDecryptGCMtagless(&dCtx, tests[i].ct, plaintext, tests[i].ptlen); + memset(tag, 0x0, 16); + psAesGetGCMTag(&dCtx, 16, tag); + if ((memcmp(plaintext, tests[i].pt, tests[i].ptlen) != 0) || + (memcmp(tag, tests[i].tag, 16) != 0)) { + printf("FAILED: memcmp mismatch\n"); + res = PS_FAILURE; + } else { + printf("PASSED\n"); + } +#endif + psAesClearGCM(&dCtx); + memset(tag, 0x0, 16); + memset(plaintext, 0x0, 32); +#endif /* !defined USE_ONLY_DECRYPT_GCM_WITH_TAG */ + + for(l = 0; l < (int32) sizeof(taglen); l++) { + _psTraceInt(tagmsg[l], tests[i].keylen * 8); + memset(plaintext, 0x11, sizeof(plaintext)); + memset(ciphertext_with_tag, 0x22, sizeof(ciphertext_with_tag)); + memcpy(ciphertext_with_tag, tests[i].ct, tests[i].ptlen); + memcpy(ciphertext_with_tag + tests[i].ptlen, tests[i].tag, taglen[l]); + psAesInitGCM(&dCtx, tests[i].key, tests[i].keylen); + psAesReadyGCM(&dCtx, tests[i].iv, tests[i].aad, tests[i].aadlen); + if (psAesDecryptGCM(&dCtx, ciphertext_with_tag, tests[i].ptlen + taglen[l], + plaintext, tests[i].ptlen) == PS_SUCCESS) { + if (memcmp(plaintext, tests[i].pt, tests[i].ptlen) != 0) { + printf("FAILED: memcmp mismatch\n"); + res = PS_FAILURE; + } else { + printf("PASSED\n"); + } + } else { + printf("FAILED: tag verify failure\n"); + res = PS_FAILURE; + } + } + for(l = 0; l < (int32) sizeof(taglen); l++) { + _psTraceInt(tagmsg2[l], tests[i].keylen * 8); + memset(plaintext, 0x11, sizeof(plaintext)); + memset(ciphertext_with_tag, 0x22, sizeof(ciphertext_with_tag)); + memcpy(ciphertext_with_tag, tests[i].ct, tests[i].ptlen); + memcpy(ciphertext_with_tag + tests[i].ptlen, tests[i].tag, taglen[l]); + ciphertext_with_tag[tests[i].ptlen + taglen[l] - 1]++; + psAesInitGCM(&dCtx, tests[i].key, tests[i].keylen); + psAesReadyGCM(&dCtx, tests[i].iv, tests[i].aad, tests[i].aadlen); + if (psAesDecryptGCM(&dCtx, ciphertext_with_tag, tests[i].ptlen + taglen[l], + plaintext, tests[i].ptlen) != PS_SUCCESS) { + printf("PASSED\n"); + } else { + printf("FAILED: verify accepts invalid tag\n"); + res = PS_FAILURE; + } + } + } + return res; +} +#endif /* USE_AES_GCM */ + + + + + +#endif /* USE_AES */ + +#if 0 +static psAesHmacPerf(void) +{ +/* + Time AES-CBC encryption and decryption of AES_KB of data + */ + useHmac = 0; + aesTag = "AES-CBC"; +L_CBC_TIMING: +#ifdef USE_AESNI_CRYPTO + printf("Timing %s with %d KiB of data (aes-ni)\n", aesTag, AES_KB); +#else + printf("Timing %s with %d KiB of data\n", aesTag, AES_KB); +#endif + buf = psMalloc(pool, 1024 + 20); + for (keysize = 16; keysize <= 32; keysize += 16) { + _psTraceInt("AES-%d Key\n", keysize == 16 ? 128 : 256); + for (i = 0; i < 1024; i++) { + buf[i] = (unsigned char)(i & 0xFF); + } + memset(iv, 0x1, 16); + memset(cbckey, 0x2, keysize); + memset(plaintext, 0x3, 16); + memset(hmackey, 0x4, 20); + hmackeylen = 20; + psAesInit(&encryptCtx, iv, cbckey, keysize); + psGetTime(&start, NULL); + for (k = 0; k < AES_KB; k++) { + if (useHmac) psHmacSha1(hmackey, hmackeylen, buf, 1024, buf + 1024, + hmackey, &hmackeylen); + if (psAesEncrypt(&encryptCtx, buf, buf, 1024) != 1024) { +printf("ERROR LINE %d\n", __LINE__); + return PS_FAILURE; + } + } + psGetTime(&end, NULL); + printf("%s: encrypt %u msecs\n", aesTag, psDiffMsecs(start, end, NULL)); + if (buf[0] == 0 && buf[1] == 1 && buf[2] == 2 && buf[3] == 3) { + return PS_FAILURE; + } + psAesInit(&decryptCtx, iv, cbckey, keysize); + psGetTime(&start, NULL); + for (k = 0; k < AES_KB; k++) { + if (useHmac) psHmacSha1(hmackey, hmackeylen, buf, 1024, buf + 1024, + hmackey, &hmackeylen); + if (psAesDecrypt(&decryptCtx, buf, buf, 1024) != 1024) { + return PS_FAILURE; + } + } + psGetTime(&end, NULL); + printf("%s: decrypt %u msecs\n", aesTag, psDiffMsecs(start, end, NULL)); + } + psFree(buf, pool); + if (useHmac == 0) { + useHmac = 1; + aesTag = "AES-CBC-SHA-HMAC"; + goto L_CBC_TIMING; + } + + return PS_SUCCESS; +} +#endif /* 0 */ + +#ifdef USE_CHACHA20_POLY1305 +#define TEST_TEXT_MAXLEN 128 +#define TEST_AAD_MAXLEN 32 +#ifdef USE_LIBSODIUM_CHACHA20_POLY1305 + #define TEST_TAG_LEN crypto_aead_chacha20poly1305_ABYTES + #define TEST_KEY_LEN crypto_aead_chacha20poly1305_KEYBYTES + #ifdef CHACHA20POLY1305_IETF + #define TEST_IV_LEN crypto_aead_chacha20poly1305_IETF_NPUBBYTES + #else + #define TEST_IV_LEN crypto_aead_chacha20poly1305_NPUBBYTES + #endif +#else + #define TEST_TAG_LEN 16 + #define TEST_KEY_LEN 32 + #define TEST_IV_LEN 12 +#endif + +int32 psChacha20Poly1305Test(void) +{ + int32 i; + psChacha20Poly1305_t eCtx, dCtx; + unsigned char ciphertext[TEST_TEXT_MAXLEN]; + unsigned char plaintext[TEST_TEXT_MAXLEN]; + unsigned char tag[TEST_TAG_LEN]; + + static struct { + int32 keylen, ptlen, aadlen; + unsigned char key[TEST_KEY_LEN], iv[TEST_IV_LEN], pt[TEST_TEXT_MAXLEN], aad[TEST_AAD_MAXLEN], ct[TEST_TEXT_MAXLEN], tag[TEST_TAG_LEN]; + } tests[] = { + +#ifdef CHACHA20POLY1305_IETF + { TEST_KEY_LEN, 114, 12, + { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f}, + // IV + { 0x07, 0x00, 0x00, 0x00, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 }, + // pt + { 0x4c,0x61,0x64,0x69,0x65,0x73,0x20,0x61, + 0x6e,0x64,0x20,0x47,0x65,0x6e,0x74,0x6c, + 0x65,0x6d,0x65,0x6e,0x20,0x6f,0x66,0x20, + 0x74,0x68,0x65,0x20,0x63,0x6c,0x61,0x73, + 0x73,0x20,0x6f,0x66,0x20,0x27,0x39,0x39, + 0x3a,0x20,0x49,0x66,0x20,0x49,0x20,0x63, + 0x6f,0x75,0x6c,0x64,0x20,0x6f,0x66,0x66, + 0x65,0x72,0x20,0x79,0x6f,0x75,0x20,0x6f, + 0x6e,0x6c,0x79,0x20,0x6f,0x6e,0x65,0x20, + 0x74,0x69,0x70,0x20,0x66,0x6f,0x72,0x20, + 0x74,0x68,0x65,0x20,0x66,0x75,0x74,0x75, + 0x72,0x65,0x2c,0x20,0x73,0x75,0x6e,0x73, + 0x63,0x72,0x65,0x65,0x6e,0x20,0x77,0x6f, + 0x75,0x6c,0x64,0x20,0x62,0x65,0x20,0x69, + 0x74,0x2e}, + // aad + { 0x50, 0x51, 0x52, 0x53, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7}, + // ct + { 0xd3,0x1a,0x8d,0x34,0x64,0x8e,0x60,0xdb, + 0x7b,0x86,0xaf,0xbc,0x53,0xef,0x7e,0xc2, + 0xa4,0xad,0xed,0x51,0x29,0x6e,0x08,0xfe, + 0xa9,0xe2,0xb5,0xa7,0x36,0xee,0x62,0xd6, + 0x3d,0xbe,0xa4,0x5e,0x8c,0xa9,0x67,0x12, + 0x82,0xfa,0xfb,0x69,0xda,0x92,0x72,0x8b, + 0x1a,0x71,0xde,0x0a,0x9e,0x06,0x0b,0x29, + 0x05,0xd6,0xa5,0xb6,0x7e,0xcd,0x3b,0x36, + 0x92,0xdd,0xbd,0x7f,0x2d,0x77,0x8b,0x8c, + 0x98,0x03,0xae,0xe3,0x28,0x09,0x1b,0x58, + 0xfa,0xb3,0x24,0xe4,0xfa,0xd6,0x75,0x94, + 0x55,0x85,0x80,0x8b,0x48,0x31,0xd7,0xbc, + 0x3f,0xf4,0xde,0xf0,0x8e,0x4b,0x7a,0x9d, + 0xe5,0x76,0xd2,0x65,0x86,0xce,0xc6,0x4b, + 0x61,0x16}, + // tag + { 0x1a,0xe1,0x0b,0x59,0x4f,0x09,0xe2,0x6a, + 0x7e,0x90,0x2e,0xcb,0xd0,0x60,0x06,0x91} + }, + + { TEST_KEY_LEN, 114, 0, + { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f}, + // IV + { 0x07, 0x00, 0x00, 0x00, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 }, + // pt + { 0x4c,0x61,0x64,0x69,0x65,0x73,0x20,0x61, + 0x6e,0x64,0x20,0x47,0x65,0x6e,0x74,0x6c, + 0x65,0x6d,0x65,0x6e,0x20,0x6f,0x66,0x20, + 0x74,0x68,0x65,0x20,0x63,0x6c,0x61,0x73, + 0x73,0x20,0x6f,0x66,0x20,0x27,0x39,0x39, + 0x3a,0x20,0x49,0x66,0x20,0x49,0x20,0x63, + 0x6f,0x75,0x6c,0x64,0x20,0x6f,0x66,0x66, + 0x65,0x72,0x20,0x79,0x6f,0x75,0x20,0x6f, + 0x6e,0x6c,0x79,0x20,0x6f,0x6e,0x65,0x20, + 0x74,0x69,0x70,0x20,0x66,0x6f,0x72,0x20, + 0x74,0x68,0x65,0x20,0x66,0x75,0x74,0x75, + 0x72,0x65,0x2c,0x20,0x73,0x75,0x6e,0x73, + 0x63,0x72,0x65,0x65,0x6e,0x20,0x77,0x6f, + 0x75,0x6c,0x64,0x20,0x62,0x65,0x20,0x69, + 0x74,0x2e}, + // aad + {""}, + // ct + { 0xd3,0x1a,0x8d,0x34,0x64,0x8e,0x60,0xdb, + 0x7b,0x86,0xaf,0xbc,0x53,0xef,0x7e,0xc2, + 0xa4,0xad,0xed,0x51,0x29,0x6e,0x08,0xfe, + 0xa9,0xe2,0xb5,0xa7,0x36,0xee,0x62,0xd6, + 0x3d,0xbe,0xa4,0x5e,0x8c,0xa9,0x67,0x12, + 0x82,0xfa,0xfb,0x69,0xda,0x92,0x72,0x8b, + 0x1a,0x71,0xde,0x0a,0x9e,0x06,0x0b,0x29, + 0x05,0xd6,0xa5,0xb6,0x7e,0xcd,0x3b,0x36, + 0x92,0xdd,0xbd,0x7f,0x2d,0x77,0x8b,0x8c, + 0x98,0x03,0xae,0xe3,0x28,0x09,0x1b,0x58, + 0xfa,0xb3,0x24,0xe4,0xfa,0xd6,0x75,0x94, + 0x55,0x85,0x80,0x8b,0x48,0x31,0xd7,0xbc, + 0x3f,0xf4,0xde,0xf0,0x8e,0x4b,0x7a,0x9d, + 0xe5,0x76,0xd2,0x65,0x86,0xce,0xc6,0x4b, + 0x61,0x16}, + // tag + { 0x6a,0x23,0xa4,0x68,0x1f,0xd5,0x94,0x56, + 0xae,0xa1,0xd2,0x9f,0x82,0x47,0x72,0x16} + } +#else + { TEST_KEY_LEN, 16, 13, + { 0x70, 0xd5, 0xbd, 0x03, 0xc6, 0x17, 0x68, 0xb2, + 0xd5, 0xce, 0xb4, 0xa4, 0x15, 0xc6, 0xf8, 0x40, + 0xf5, 0xd4, 0xbf, 0x5e, 0x63, 0x2b, 0xb6, 0xf3, + 0x73, 0xaf, 0xcd, 0xd7, 0xbb, 0xba, 0x85, 0xa7 }, + // Nonce + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + // pt + { 0x14, 0x00, 0x00, 0x0c, + 0x9c, 0x49, 0x65, 0xfc, 0xeb, 0x2e, 0xfa, 0x01, 0xfc, 0xa1, 0x2a, 0xaf }, + // aad + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x16, 0x03, 0x03, 0x00, 0x10 }, + // ct + { 0x25, 0xd8, 0x3d, 0x53, 0xbd, 0x03, 0xdd, 0x69, + 0x5a, 0x44, 0x6f, 0xde, 0x0c, 0x3d, 0x87, 0x93}, + // tag + { 0x80, 0x53, 0x32, 0x2f, 0x5c, 0x27, 0x8f, 0x9d, + 0x78, 0xb5, 0x25, 0x3d, 0x5c, 0xc3, 0x8c, 0x9b } + } +#endif + }; + +/* Test AEAD CHACHA20-POLY1305 */ + + for (i = 0; i < (int32)(sizeof(tests)/sizeof(tests[0])); i++) { + _psTraceInt(" CHACHA20-POLY1305-%d " +#ifdef CHACHA20POLY1305_IETF + "IETF " +#endif + "known vector encrypt test... ", tests[i].keylen * 8); + + psChacha20Poly1305Init(&eCtx, tests[i].key, tests[i].keylen); + psChacha20Poly1305Ready(&eCtx, tests[i].iv, tests[i].aad, tests[i].aadlen); + psChacha20Poly1305Encrypt(&eCtx, tests[i].pt, ciphertext, tests[i].ptlen); + psChacha20Poly1305GetTag(&eCtx, TEST_TAG_LEN, tag); + + if ((memcmp(ciphertext, tests[i].ct, tests[i].ptlen) != 0) || + (memcmp(tag, tests[i].tag, TEST_TAG_LEN) != 0)) { + printf("FAILED: memcmp mismatch\n"); + } else { + printf("PASSED\n"); + } + psChacha20Poly1305Clear(&eCtx); + memset(tag, 0x0, TEST_TAG_LEN); + memset(ciphertext, 0x0, TEST_TEXT_MAXLEN); + + _psTraceInt(" CHACHA20-POLY1305-%d " +#ifdef CHACHA20POLY1305_IETF + "IETF " +#endif + "known vector decrypt test... ", tests[i].keylen * 8); + psChacha20Poly1305Init(&dCtx, tests[i].key, tests[i].keylen); + psChacha20Poly1305Ready(&dCtx, tests[i].iv, tests[i].aad, tests[i].aadlen); + + // Cipher text must include the tag + unsigned char * cipherTextAuthData; + cipherTextAuthData = psMalloc(NULL, tests[i].ptlen+TEST_TAG_LEN); + + memcpy(cipherTextAuthData,tests[i].ct,tests[i].ptlen); + memcpy(cipherTextAuthData+tests[i].ptlen,tests[i].tag,TEST_TAG_LEN); + + if (psChacha20Poly1305Decrypt(&dCtx,cipherTextAuthData, + tests[i].ptlen+TEST_TAG_LEN,plaintext,tests[i].ptlen) < 0) { + printf("FAILED: authentication failed\n"); + } else if (memcmp(plaintext, tests[i].pt, tests[i].ptlen) != 0) { + printf("FAILED: data mismatch\n"); + } else { + printf("PASSED\n"); + } + psFree(cipherTextAuthData, NULL); + psChacha20Poly1305Clear(&dCtx); + memset(tag, 0x0, TEST_TAG_LEN); + memset(plaintext, 0x0, TEST_TEXT_MAXLEN); + } + return PS_SUCCESS; +} +#endif /* USE_CHACHA20_POLY1305 */ + +/******************************************************************************/ +#ifdef USE_DES +#define DES_ITER 1000 +static int32 psDesTest(void) +{ + int32 err; + static const struct des_test_case { + int32 num, mode; /* mode 1 = encrypt */ + unsigned char key[8], txt[8], out[8]; + } cases[] = { + { 1, 1, { 0x10, 0x31, 0x6E, 0x02, 0x8C, 0x8F, 0x3B, 0x4A }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x82, 0xDC, 0xBA, 0xFB, 0xDE, 0xAB, 0x66, 0x02 } }, + { 2, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 }, + { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 4, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA }, + { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 5, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F }, + { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 6, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 }, + { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 7, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF }, + { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 8, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F }, + { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 9, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 }, + { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + {10, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A }, + { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + + { 1, 0, { 0x10, 0x31, 0x6E, 0x02, 0x8C, 0x8F, 0x3B, 0x4A }, + { 0x82, 0xDC, 0xBA, 0xFB, 0xDE, 0xAB, 0x66, 0x02 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 2, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 } }, + { 3, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 } }, + { 4, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA } }, + { 5, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F } }, + { 6, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 } }, + { 7, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF } }, + { 8, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F } }, + { 9, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 } }, + {10, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A } } + + }; + + int32 i, y; + unsigned char tmp[8]; + psDes3Key_t des; + + for(i=0; i < (int)(sizeof(cases)/sizeof(cases[0])); i++) + { + if ((err = psDesInitKey(cases[i].key, 8, &des)) != PS_SUCCESS) { + return err; + } + if (cases[i].mode != 0) { + _psTraceInt(" DES known vector encrypt test %d... ", cases[i].num); + psDesEncryptBlock(cases[i].txt, tmp, &des); + } else { + _psTraceInt(" DES known vector encrypt test %d... ", cases[i].num); + psDesDecryptBlock(cases[i].txt, tmp, &des); + } + + if (memcmp(cases[i].out, tmp, sizeof(tmp)) != 0) { + _psTrace("FAILED: memcmp\n"); + return -1; + } else { + _psTrace("PASSED\n"); + } + + /* now see if we can encrypt all zero bytes DES_ITER times, + decrypt and come back where we started */ + _psTrace(" DES wind/unwind test... "); + for (y = 0; y < 8; y++) tmp[y] = 0; + for (y = 0; y < DES_ITER; y++) psDesEncryptBlock(tmp, tmp, &des); + for (y = 0; y < DES_ITER; y++) psDesDecryptBlock(tmp, tmp, &des); + for (y = 0; y < 8; y++) { + if (tmp[y] != 0) { + _psTrace("FAILED: memcmp\n"); + return -1; + } + } + _psTrace("PASSED\n"); + } + + return PS_SUCCESS; +} +#endif /* DES */ + +#ifdef USE_PKCS5 +int32 psPBKDF2(void) +{ + int32 i; + unsigned char key[32]; + static struct { + int32 rounds, dkLen; + unsigned char *pass, *salt; + unsigned char output[32]; + } tests[] = { + { 1, 20, (unsigned char *)"password", (unsigned char *)"salt", + { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, 0xf3, 0xa9, 0xb5, + 0x24, 0xaf, 0x60, 0x12, 0x06, 0x2f, 0xe0, 0x37, 0xa6} + }, + { 4096, 20, (unsigned char *)"password", (unsigned char *)"salt", + { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, 0xbe, 0xad, 0x49, + 0xd9, 0x26, 0xf7, 0x21, 0xd0, 0x65, 0xa4, 0x29, 0xc1} + }, + { 4096, 25, (unsigned char *)"passwordPASSWORDpassword", + (unsigned char *)"saltSALTsaltSALTsaltSALTsaltSALTsalt", + { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, 0x80, 0xc8, 0xd8, + 0x36, 0x62, 0xc0, 0xe4, 0x4a, 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, + 0xf0, 0x70, 0x38} + } + }; + + for (i = 0; i < (int32)(sizeof(tests)/sizeof(tests[0])); i++) { + _psTraceInt(" PBKDF2 known vector test %d... ", i + 1); + pkcs5pbkdf2(tests[i].pass, (uint32)strlen((char*)tests[i].pass), + tests[i].salt, (uint32)strlen((char*)tests[i].salt), + tests[i].rounds, key, tests[i].dkLen); + if (memcmp(key, tests[i].output, tests[i].dkLen) != 0) { + _psTrace("FAILED\n"); + } else { + _psTrace("PASSED\n"); + } + } + return 0; +} +#endif /* PKCS5 */ + +/******************************************************************************/ +#ifdef USE_3DES +int32 psDes3Test(void) +{ + static struct { + unsigned char key[24], iv[8], pt[8], ct[8]; + } tests[] = { + { + { 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x95, 0xa8, 0xd7, 0x28, 0x13, 0xda, 0xa9, 0x4d } + }, + + { + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x95, 0xf8, 0xa5, 0xe5, 0xdd, 0x31, 0xd9, 0x00 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31, + 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31, + 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x88, 0xd5, 0x5e, 0x54, 0xf5, 0x4c, 0x97, 0xb4 } + } + }; + psDes3_t skey; + unsigned char ct[32]; + int32 i; + + for (i = 0; i < (int32)(sizeof(tests)/sizeof(tests[0])); i++) { + _psTraceInt(" 3DES CBC known vector test %d... ", i + 1); + if (psDes3Init(&skey, tests[i].iv, tests[i].key) < 0) { + return PS_FAILURE; + } + psDes3Encrypt(&skey, tests[i].pt, ct, DES3_BLOCKLEN); + if (memcmp(ct, tests[i].ct, DES3_BLOCKLEN) != 0) { + _psTrace("FAILED\n"); + } else { + _psTrace("PASSED\n"); + } + psDes3Clear(&skey); + } + return 0; +} +#endif /* USE_3DES */ +/******************************************************************************/ + +#ifdef USE_ARC4 +int32 psArc4Test(void) +{ + static struct { + int32 keylen, ptlen; + unsigned char key[24], pt[16], ct[16]; + } tests[] = { + { 5, 16, + { 0x01, 0x02, 0x03, 0x04, 0x05 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xb2, 0x39, 0x63, 0x05, 0xf0, 0x3d, 0xc0, 0x27, + 0xcc, 0xc3, 0x52, 0x4a, 0x0a, 0x11, 0x18, 0xa8 } + }, + { 8, 8, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 } + } + }; + psArc4_t skey; + unsigned char ct[32]; + int32 i; + + for (i = 0; i < (int32)(sizeof(tests)/sizeof(tests[0])); i++) { + _psTraceInt(" RC4 known vector test %d... ", i + 1); + if (psArc4Init(&skey, tests[i].key, tests[i].keylen) < 0) { + return PS_FAILURE; + } + psArc4(&skey, tests[i].pt, ct, tests[i].ptlen); + if (memcmp(ct, tests[i].ct, tests[i].ptlen) != 0) { + _psTrace("FAILED\n"); + } else { + _psTrace("PASSED\n"); + } + psArc4Clear(&skey); + } + return 0; +} +#endif /* USE_ARC4 */ + +#ifdef USE_IDEA +int32 psIdeaTest(void) +{ + int32 err, i; + psIdea_t eCtx, dCtx; + unsigned char tmp[2][IDEA_BLOCKLEN]; + + static struct { + unsigned char key[IDEA_KEYLEN], iv[IDEA_IVLEN], pt[16], ct[16]; + } tests[] = { + { + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, + 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, + { 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, + 0x64, 0x21, 0x21, 0x21, 0x21, 0x0a }, + { 0x57, 0x1c, 0xce, 0x5a, 0xea, 0xee, 0x81, 0x04, 0x87, 0x2a, + 0x5a, 0xa9, 0xe2, 0xdf, 0x64, 0xa9 } + } + }; + + + for (i = 0; i < (int32)(sizeof(tests)/sizeof(tests[0])); i++) { + _psTrace(" IDEA-CBC known vector test 1... "); + if ((err = psIdeaInit(&eCtx, tests[i].iv, tests[i].key)) + != PS_SUCCESS) { + _psTraceInt("FAILED: psIdeaInit returned %d\n", err); + return err; + } + if ((err = psIdeaInit(&dCtx, tests[i].iv, tests[i].key)) + != PS_SUCCESS) { + _psTraceInt("FAILED: psIdeaInit returned %d\n", err); + return err; + } + psIdeaEncrypt(&eCtx, tests[i].pt, tmp[0], 16); + //psTraceBytes("IDEA CT", tmp[0], 16); + if (memcmp(tmp[0], tests[i].ct, 16) != 0) { + _psTrace("FAILED\n"); + } else { + _psTrace("PASSED\n"); + } + _psTrace(" IDEA-CBC known vector test 2... "); + psIdeaDecrypt(&dCtx, tmp[0], tmp[1], 16); + //psTraceBytes("IDEA PT", tmp[1], 16); + if (memcmp(tmp[1], tests[i].pt, 16) != 0) { + _psTrace("FAILED\n"); + } else { + _psTrace("PASSED\n"); + } + + psIdeaClear(&eCtx); + psIdeaClear(&dCtx); + } + return 0; +} +#endif + +/******************************************************************************/ +#ifdef USE_SEED +/* + Performs a self-test of the SEED block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int32 psSeedTest(void) +{ +#if 0 + static const struct test { + unsigned char pt[16], ct[16], key[16]; + } tests[] = { + { + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }, + { 0x5E,0xBA,0xC6,0xE0,0x05,0x4E,0x16,0x68,0x19,0xAF,0xF1,0xCC,0x6D,0x34,0x6C,0xDB }, + { 0 }, + }, + + { + { 0 }, + { 0xC1,0x1F,0x22,0xF2,0x01,0x40,0x50,0x50,0x84,0x48,0x35,0x97,0xE4,0x37,0x0F,0x43 }, + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }, + }, + + { + { 0x83,0xA2,0xF8,0xA2,0x88,0x64,0x1F,0xB9,0xA4,0xE9,0xA5,0xCC,0x2F,0x13,0x1C,0x7D }, + { 0xEE,0x54,0xD1,0x3E,0xBC,0xAE,0x70,0x6D,0x22,0x6B,0xC3,0x14,0x2C,0xD4,0x0D,0x4A }, + { 0x47,0x06,0x48,0x08,0x51,0xE6,0x1B,0xE8,0x5D,0x74,0xBF,0xB3,0xFD,0x95,0x61,0x85 }, + }, + + { + { 0xB4,0x1E,0x6B,0xE2,0xEB,0xA8,0x4A,0x14,0x8E,0x2E,0xED,0x84,0x59,0x3C,0x5E,0xC7 }, + { 0x9B,0x9B,0x7B,0xFC,0xD1,0x81,0x3C,0xB9,0x5D,0x0B,0x36,0x18,0xF4,0x0F,0x51,0x22 }, + { 0x28,0xDB,0xC3,0xBC,0x49,0xFF,0xD8,0x7D,0xCF,0xA5,0x09,0xB1,0x1D,0x42,0x2B,0xE7 }, + } + }; + + int32 x; + unsigned char buf[2][16]; + psSeedKey_t skey; + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + psSeedInitKey(tests[x].key, 16, &skey); + psSeedEncryptBlock(tests[x].pt, buf[0], &skey); + psSeedDecryptBlock(buf[0], buf[1], &skey); + if (memcmp(buf[0], tests[x].ct, 16) || memcmp(buf[1], tests[x].pt, 16)){ + _psTraceInt("SEED failure: test %d failed\n", x); + return -1; + } + psSeedClear(&skey); + } +#endif + _psTrace(" SEED unimplemented\n"); + + return PS_SUCCESS; +} +#endif /* USE_SEED */ +/******************************************************************************/ + +/******************************************************************************/ +#ifdef USE_SHA1 +int32 psSha1Test(void) +{ + static const struct { + char *msg; + unsigned char hash[SHA1_HASHLEN]; + } tests[] = { + { "abc", + { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, + 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, + 0x9c, 0xd0, 0xd8, 0x9d } + }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, + 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, + 0xE5, 0x46, 0x70, 0xF1 } + }, + { "The quick brown fox jumps over the lazy dog", + { 0x2f, 0xd4, 0xe1, 0xc6, 0x7a, 0x2d, 0x28, 0xfc, 0xed, 0x84, 0x9e, + 0xe1, 0xbb, 0x76, 0xe7, 0x39, 0x1b, 0x93, 0xeb, 0x12 } + }, + { "adfkadsofijadlkjoaijeoadaoijealfkajeflakepoieuproeirupqoeiruadslfasdlfadfowifjadfaleifafoeafwdflaheadfalefaahfaefefaeofadflafefaefeaeorea", + { 0xb5, 0x6a, 0x92, 0x83, 0x2a, 0xb8, 0x98, 0xdf, 0x37, 0xf6, 0x4b, + 0x5b, 0x95, 0x9b, 0xfe, 0x9a, 0xb5, 0x9f, 0x36, 0x86} + } + }; + + int32 i; + unsigned char tmp[SHA1_HASHLEN]; + psSha1_t md; + + for (i = 0; i < (int32)(sizeof(tests) / sizeof(tests[0])); i++) { + _psTraceInt(" SHA-1 known vector test %d... ", i + 1); + psSha1Init(&md); + psSha1Update(&md, (unsigned char*)tests[i].msg, (uint32)strlen(tests[i].msg)); + psSha1Final(&md, tmp); + if (memcmp(tmp, tests[i].hash, SHA1_HASHLEN) != 0) { + _psTrace("FAILED: mem compare failure\n"); + return -1; + } else { + _psTrace("PASSED\n"); + } + } + return PS_SUCCESS; +} + +#endif /* USE_SHA1 */ +/******************************************************************************/ + +/******************************************************************************/ +#ifdef USE_SHA256 +int32 psSha256Test2(void) +{ + unsigned char hash[32]; + const unsigned char expect[32] = { + 0x1, 0xd, 0x0, 0xed, 0xa0, 0x5, 0xa3, 0x8c, 0xcb, 0x98, 0xc3, + 0x9b, 0x2d, 0xb1, 0x43, 0x2d, 0x59, 0x9, 0x8, 0x37, 0x40, 0x31, + 0x5e, 0x9b, 0x27, 0xec, 0x92, 0xf7, 0x2, 0xa7, 0x1c, 0x18 }; + const unsigned char expect2[32] = { + 0x5a, 0x31, 0xd2, 0xdf, 0x29, 0x5c, 0x83, 0x76, 0x92, 0x64, 0xae, + 0x53, 0xcd, 0xc8, 0xeb, 0x56, 0xfc, 0x55, 0x3, 0x6, 0x92, 0xe, 0x8b, + 0xab, 0x18, 0x7b, 0x47, 0xd1, 0xa2, 0x96, 0x31, 0xe }; + const unsigned char expect3[32] = { + 0xff, 0x16, 0x42, 0xc4, 0x77, 0x1, 0x1d, 0x25, 0xd, 0x48, 0xe4, 0x2d, + 0xba, 0xab, 0x4f, 0x14, 0x1e, 0xd5, 0x7f, 0xd6, 0x60, 0x9e, 0x51, + 0x91, 0xab, 0x4, 0xf9, 0xf6, 0xf6, 0x5d, 0x8f, 0x22 }; + unsigned char array[65536]; + unsigned char array2[65536]; + unsigned char array3[65536]; + psSha256_t md; + psSha256_t md2; + psSha256_t md3; + psSha256_t md4; + int i; + int blocksize; + int blocksize2; + int blocksize3; + + /* This test assumes there is 1 or 2 simultanous digest contexts in + underlying implementation of cryptography, as is the case with some + non-default crypto implementations. The test works with more than that, + but may not check of the implementation. */ + + /* Additional tests, using multiple simultaneous contexts, and + large data. */ + + /* First perform hashes with single blocks and serially. */ + for(i = 0; i < sizeof(array); i++) + { + array[i] = 7 + (i * 2048) % 127; + array2[i] = 17 + (i * 4096) % 197; + array3[i] = 21 + (i * 8192) % 227; + } + + memset(hash, 0, sizeof(hash)); + psSha256Init(&md); + psSha256Update(&md, array, 65536); + psSha256Final(&md, hash); + + if (memcmp(hash, expect, 32) != 0) { + abort(); + _psTrace("FAILED: memcmp\n"); + return -1; + } + + memset(hash, 0, sizeof(hash)); + psSha256Init(&md2); + psSha256Update(&md2, array2, 65536); + psSha256Final(&md2, hash); + + if (memcmp(hash, expect2, 32) != 0) { + abort(); + _psTrace("FAILED: memcmp\n"); + return -1; + } + + memset(hash, 0, sizeof(hash)); + psSha256Init(&md3); + psSha256Update(&md3, array3, 65536); + psSha256Final(&md3, hash); + + if (memcmp(hash, expect3, 32) != 0) { + abort(); + _psTrace("FAILED: memcmp\n"); + return -1; + } + + /* Then perform hashes with two blocks and serially, using same context. */ + memset(hash, 0, sizeof(hash)); + psSha256Init(&md); + psSha256Update(&md, array, 32768); + psSha256Update(&md, array + 32768, 32768); + psSha256Final(&md, hash); + + if (memcmp(hash, expect, 32) != 0) { + _psTrace("FAILED: memcmp (two part)\n"); + return -1; + } + + memset(hash, 0, sizeof(hash)); + psSha256Init(&md); + psSha256Update(&md, array2, 32768); + psSha256Update(&md, array2 + 32768, 32768); + psSha256Final(&md, hash); + + if (memcmp(hash, expect2, 32) != 0) { + _psTrace("FAILED: memcmp (two part)\n"); + return -1; + } + + memset(hash, 0, sizeof(hash)); + psSha256Init(&md); + psSha256Update(&md, array3, 32768); + psSha256Update(&md, array3 + 32768, 32768); + psSha256Final(&md, hash); + + if (memcmp(hash, expect3, 32) != 0) { + _psTrace("FAILED: memcmp (two part)\n"); + return -1; + } + + /* Try going back within the same context: First initialize and update + and then initialize and update again. */ + + memset(hash, 0, sizeof(hash)); + psSha256Init(&md); + psSha256Update(&md, array, 32768); + psSha256Init(&md); + psSha256Update(&md, array3, 32768); + psSha256Update(&md, array3 + 32768, 32768); + psSha256Final(&md, hash); + + if (memcmp(hash, expect3, 32) != 0) { + _psTrace("FAILED: memcmp (two part)\n"); + return -1; + } + + /* Do operations in parallel with three md contexts, single block. */ + psSha256Init(&md); + psSha256Init(&md2); + psSha256Init(&md3); + psSha256Update(&md, array, 65536); + psSha256Update(&md2, array2, 65536); + psSha256Update(&md3, array3, 65536); + + psSha256Final(&md, hash); + + if (memcmp(hash, expect, 32) != 0) { + _psTrace("FAILED: memcmp (single part; parallel contexts)\n"); + return -1; + } + + psSha256Final(&md2, hash); + + if (memcmp(hash, expect2, 32) != 0) { + _psTrace("FAILED: memcmp (single part; parallel contexts)\n"); + return -1; + } + + psSha256Final(&md3, hash); + + if (memcmp(hash, expect3, 32) != 0) { + _psTrace("FAILED: memcmp (single part; parallel contexts)\n"); + return -1; + } + + /* Do operations in parallel with three md contexts, multiple blocks. */ + blocksize = 256; + + psSha256Init(&md); + psSha256Init(&md2); + psSha256Init(&md3); + + for(i = 0; i < 65536; i += blocksize) { + psSha256Update(&md, &array[i], blocksize); + psSha256Update(&md2, &array2[i], blocksize); + psSha256Update(&md3, &array3[i], blocksize); + } + + psSha256Final(&md, hash); + + if (memcmp(hash, expect, 32) != 0) { + _psTrace("FAILED: memcmp (single part; parallel contexts)\n"); + return -1; + } + + psSha256Final(&md2, hash); + + if (memcmp(hash, expect2, 32) != 0) { + _psTrace("FAILED: memcmp (single part; parallel contexts)\n"); + return -1; + } + + psSha256Final(&md3, hash); + + if (memcmp(hash, expect3, 32) != 0) { + _psTrace("FAILED: memcmp (single part; parallel contexts)\n"); + return -1; + } + + /* Do operations in parallel with three md contexts, multiple blocks. + Different block sizes for different md contexts. */ + blocksize = 256; + blocksize2 = 512; + blocksize3 = 2048; + + psSha256Init(&md); + psSha256Init(&md2); + psSha256Init(&md3); + + for(i = 0; i < 65536; i += blocksize) { + psSha256Update(&md, &array[i], blocksize); + if ((i % blocksize2) != 0) + continue; + psSha256Update(&md2, &array2[i], blocksize2); + if ((i % blocksize3) != 0) + continue; + psSha256Update(&md3, &array3[i], blocksize3); + } + + psSha256Final(&md, hash); + + if (memcmp(hash, expect, 32) != 0) { + _psTrace("FAILED: memcmp (single part; parallel contexts)\n"); + return -1; + } + + psSha256Final(&md2, hash); + + if (memcmp(hash, expect2, 32) != 0) { + _psTrace("FAILED: memcmp (single part; parallel contexts)\n"); + return -1; + } + + psSha256Final(&md3, hash); + + if (memcmp(hash, expect3, 32) != 0) { + _psTrace("FAILED: memcmp (single part; parallel contexts)\n"); + return -1; + } + + /* Multipart with context transfer (using memory copy). */ + psSha256Init(&md); + psSha256Update(&md, array3, 32768); + psSha256Sync(&md, 0); /* Need to synchronize before it is allowed to + copy, zeroize or free md memory. */ + memcpy(&md3, &md, sizeof(md3)); + psSha256Update(&md3, array3 + 32768, 32768); + psSha256Final(&md3, hash); + + if (memcmp(hash, expect3, 32) != 0) { + _psTrace("FAILED: memcmp (single part; parallel contexts)\n"); + return -1; + } + + /* Multipart with context transfer (using state copying). */ + psSha256Init(&md); + psSha256Update(&md, array2, 32768); + psSha256Sync(&md, 0); /* Need to synchronize before it is allowed to + copy, zeroize or free md memory. */ + memcpy(&md3, &md, sizeof(md3)); + psSha256Update(&md3, array2 + 32768, 32768); + psSha256Final(&md3, hash); + + if (memcmp(hash, expect2, 32) != 0) { + _psTrace("FAILED: memcmp (single part; parallel contexts)\n"); + return -1; + } + + /* Multipart with context transfer (using state copying and memcpy). */ + psSha256Init(&md); + psSha256Update(&md, array2, 32768); + psSha256Cpy(&md3, &md); + psSha256Sync(&md3, 0); + psSha256Sync(&md, 0); /* Need to synchronize before it is allowed to + copy, zeroize or free md memory. */ + memcpy(&md3, &md, sizeof(md3)); + psSha256Update(&md3, array2 + 32768, 32768); + psSha256Final(&md3, hash); + + if (memcmp(hash, expect2, 32) != 0) { + _psTrace("FAILED: memcmp (single part; parallel contexts)\n"); + return -1; + } + + /* Multipart with context transfer (using state copying), when + state is likely not loaded (variants with different amount of + activity in between Update and Cpy. */ + psSha256Init(&md); + psSha256Update(&md, array2, 32768); + + psSha256Init(&md2); + psSha256Update(&md2, array, 32768); + psSha256Update(&md2, array, 32768); + psSha256Final(&md2, hash); + + psSha256Cpy(&md3, &md); + psSha256Update(&md3, array2 + 32768, 32768); + psSha256Final(&md3, hash); + + if (memcmp(hash, expect2, 32) != 0) { + _psTrace("FAILED: memcmp (multi part; parallel contexts)\n"); + return -1; + } + psSha256Init(&md); + psSha256Update(&md, array2, 32768); + + psSha256Init(&md2); + psSha256Update(&md2, array, 32768); + psSha256Update(&md2, array, 32768); + psSha256Init(&md3); + psSha256Update(&md3, array, 32768); + psSha256Update(&md3, array, 32768); + psSha256Final(&md2, hash); + psSha256Final(&md3, hash); + + psSha256Cpy(&md3, &md); + psSha256Update(&md3, array2 + 32768, 32768); + psSha256Final(&md3, hash); + + if (memcmp(hash, expect2, 32) != 0) { + _psTrace("FAILED: memcmp (multi part; parallel contexts)\n"); + return -1; + } + psSha256Init(&md); + psSha256Update(&md, array2, 32768); + + psSha256Init(&md2); + psSha256Update(&md2, array, 32768); + psSha256Update(&md2, array, 32768); + psSha256Init(&md3); + psSha256Update(&md3, array, 32768); + psSha256Update(&md3, array, 32768); + psSha256Init(&md4); + psSha256Update(&md4, array, 32768); + psSha256Update(&md4, array, 32768); + psSha256Final(&md2, hash); + psSha256Final(&md3, hash); + psSha256Final(&md4, hash); + + psSha256Cpy(&md3, &md); + psSha256Update(&md3, array2 + 32768, 32768); + psSha256Final(&md3, hash); + + if (memcmp(hash, expect2, 32) != 0) { + _psTrace("FAILED: memcmp (multi part; parallel contexts)\n"); + return -1; + } + + /* Zeroize of context. */ + psSha256Init(&md); + psSha256Update(&md, array, 32768); + psSha256Sync(&md, 0); /* Need to synchronize before it is allowed to + copy, zeroize or free md memory. */ + memset(&md, 0, sizeof(md)); + + /* Note: After memset it is needed to use some other contexts. */ + psSha256Init(&md2); + psSha256Update(&md2, array, 32768); + psSha256Update(&md2, array, 32768); + psSha256Init(&md3); + psSha256Update(&md3, array, 32768); + psSha256Update(&md3, array, 32768); + psSha256Init(&md4); + psSha256Update(&md4, array, 32768); + psSha256Update(&md4, array, 32768); + + psSha256Init(&md); + psSha256Update(&md, array, 65536); + psSha256Final(&md, hash); + + if (memcmp(hash, expect, 32) != 0) { + _psTrace("FAILED: memcmp (memset in between)\n"); + return -1; + } + + psSha256Final(&md2, hash); + psSha256Final(&md3, hash); + psSha256Final(&md4, hash); + + /* Sync is ok for zeroized memory not used as context and initialized + or finalized context. */ + memset(&md, 0, sizeof(md)); + psSha256Sync(&md, 0); + memset(&md, 0, sizeof(md)); + psSha256Init(&md); + psSha256Sync(&md, 0); + psSha256Init(&md); + psSha256Update(&md, array, 65536); + psSha256Final(&md, hash); + psSha256Sync(&md, 0); + + if (memcmp(hash, expect, 32) != 0) { + _psTrace("FAILED: memcmp\n"); + return -1; + } + + return PS_SUCCESS; +} + +int32 psSha256Test(void) +{ + static const struct { + char *msg; + char *moreMsg; + unsigned char hash[SHA256_HASHLEN]; + } tests[] = { + { "abc", NULL, + { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad } + }, + { "ab", "c", + { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad } + }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", NULL, + { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 } + }, + { "abcdbcdecd", "efdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 } + }, + { "The quick brown fox jumps over the lazy dog", NULL, + { 0xd7, 0xa8, 0xfb, 0xb3, 0x07, 0xd7, 0x80, 0x94, + 0x69, 0xca, 0x9a, 0xbc, 0xb0, 0x08, 0x2e, 0x4f, + 0x8d, 0x56, 0x51, 0xe4, 0x6d, 0x3c, 0xdb, 0x76, + 0x2d, 0x02, 0xd0, 0xbf, 0x37, 0xc9, 0xe5, 0x92 } + }, + { "The quick brow", "n fox jumps over the lazy dog", + { 0xd7, 0xa8, 0xfb, 0xb3, 0x07, 0xd7, 0x80, 0x94, + 0x69, 0xca, 0x9a, 0xbc, 0xb0, 0x08, 0x2e, 0x4f, + 0x8d, 0x56, 0x51, 0xe4, 0x6d, 0x3c, 0xdb, 0x76, + 0x2d, 0x02, 0xd0, 0xbf, 0x37, 0xc9, 0xe5, 0x92 } + }, + { "adfkadsofijadlkjoaijeoadaoijealfkajeflakepoieuproeirupqoeiruadslfasdlfadfowifjadfaleifafoeafwdflaheadfalefaahfaefefaeofadflafefaefeaeorea", NULL, + { 0xd9, 0xe0, 0xb1, 0xfb, 0x08, 0x8a, 0xe4, 0xb9, + 0xfe, 0xf0, 0xb2, 0xb8, 0x33, 0x9e, 0x0f, 0xea, + 0x59, 0xa7, 0x35, 0x7f, 0x5b, 0x65, 0xde, 0x42, + 0x7b, 0xaa, 0x28, 0x89, 0xfd, 0x5f, 0x49, 0xd0} + }, + { "adfkadsofijadlkjoaijeoadaoijealfkajeflakepoieuproeirupqoeiruadslfasdlfadfowifjadfaleifafoeafwdflaheadfalefaahfaefef", "aeofadflafefaefeaeorea", + { 0xd9, 0xe0, 0xb1, 0xfb, 0x08, 0x8a, 0xe4, 0xb9, + 0xfe, 0xf0, 0xb2, 0xb8, 0x33, 0x9e, 0x0f, 0xea, + 0x59, 0xa7, 0x35, 0x7f, 0x5b, 0x65, 0xde, 0x42, + 0x7b, 0xaa, 0x28, 0x89, 0xfd, 0x5f, 0x49, 0xd0} + } + }; + + int32 i; + unsigned char tmp[SHA256_HASHLEN]; + psSha256_t md; + + for (i = 0; i < (int32)(sizeof(tests) / sizeof(tests[0])); i++) { + _psTraceInt(" SHA-256 known vector test %d... ", i + 1); + psSha256Init(&md); + psSha256Update(&md, (unsigned char*)tests[i].msg, + (uint32)strlen(tests[i].msg)); + if (tests[i].moreMsg != NULL) { + psSha256Update(&md, (unsigned char*)tests[i].moreMsg, + (uint32)strlen(tests[i].moreMsg)); + } + psSha256Final(&md, tmp); + if (memcmp(tmp, tests[i].hash, SHA256_HASHLEN) != 0) { + _psTrace("FAILED: memcmp\n"); + return -1; + } else { + _psTrace("PASSED\n"); + } + } + + _psTrace(" SHA-256 robustness test... "); + if (psSha256Test2() == PS_SUCCESS) { + _psTrace("PASSED\n"); + } else { + return -1; + } + + return PS_SUCCESS; +} +#endif /* USE_SHA256 */ +/******************************************************************************/ + +#ifdef USE_SHA224 +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int32 psSha224Test(void) +{ + static const struct { + char *msg; + unsigned char hash[28]; + } tests[] = { + { "abc", + { 0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8, + 0x22, 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2, + 0x55, 0xb3, 0x2a, 0xad, 0xbc, 0xe4, 0xbd, + 0xa0, 0xb3, 0xf7, 0xe3, 0x6c, 0x9d, 0xa7 } + }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76, + 0xcc, 0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89, + 0x01, 0x50, 0xb0, 0xc6, 0x45, 0x5c, 0xb4, + 0xf5, 0x8b, 0x19, 0x52, 0x52, 0x25, 0x25 } + }, + }; + + int i; + unsigned char tmp[28]; + psDigestContext_t md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + _psTraceInt(" SHA-224 known vector test %d... ", i + 1); + psSha224Init(&md); + psSha224Update(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg)); + psSha224Final(&md, tmp); + if (memcmp(tmp, tests[i].hash, 28) != 0) { + _psTrace("FAILED: memcmp\n"); + return -1; + } else { + _psTrace("PASSED\n"); + } + } + return PS_SUCCESS; +} +#endif /* USE_SHA224 */ + +/******************************************************************************/ + +#ifdef USE_SHA512 +int32 psSha512Test(void) +{ + static const struct { + char *msg; + unsigned char hash[SHA512_HASHLEN]; + } tests[] = { + { "abc", + { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, + 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, + 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, + 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, + 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, + 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, + 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, + 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f } + }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, + 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, + 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, + 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, + 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, + 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, + 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, + 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 } + }, + }; + + int i; + unsigned char tmp[SHA512_HASHLEN]; + psSha512_t md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + _psTraceInt(" SHA-512 known vector test %d... ", i + 1); + psSha512Init(&md); + psSha512Update(&md, (unsigned char *)tests[i].msg, (uint32)strlen(tests[i].msg)); + psSha512Final(&md, tmp); + if (memcmp(tmp, tests[i].hash, SHA512_HASHLEN) != 0) { + _psTrace("FAILED: memcmp\n"); + return -1; + } + _psTrace("PASSED\n"); + } + return PS_SUCCESS; +} +#endif /* USE_SHA512 */ + +#ifdef USE_SHA384 +int32 psSha384Test(void) +{ + static const struct { + char *msg; + unsigned char hash[SHA384_HASHLEN]; + } tests[] = { + { "abc", + { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, + 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07, + 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, + 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, + 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23, + 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 } + }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8, + 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47, + 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2, + 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12, + 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9, + 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 } + }, + }; + + int i; + unsigned char tmp[SHA384_HASHLEN]; + psSha384_t md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + _psTraceInt(" SHA-384 known vector test %d... ", i + 1); + psSha384Init(&md); + psSha384Update(&md, (unsigned char*)tests[i].msg, (uint32)strlen(tests[i].msg)); + psSha384Final(&md, tmp); + if (memcmp(tmp, tests[i].hash, SHA384_HASHLEN) != 0) { + _psTrace("FAILED: memcmp\n"); + return -1; + } + _psTrace("PASSED\n"); + } + return PS_SUCCESS; +} +#endif /* USE_SHA384 */ + + +#ifdef USE_MD5SHA1 +int32 psMd5Sha1Test(void) +{ + static const struct { + char *msg; + unsigned char hash[36]; + } tests[] = { + { "abc", + { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, + 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72, + 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, + 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, + 0x9c, 0xd0, 0xd8, 0x9d } + }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x82, 0x15, 0xef, 0x07, 0x96, 0xa2, 0x0b, 0xca, + 0xaa, 0xe1, 0x16, 0xd3, 0x87, 0x6c, 0x66, 0x4a, + 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, + 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, + 0xE5, 0x46, 0x70, 0xF1 } + }, + { "The quick brown fox jumps over the lazy dog", + { 0x9e, 0x10, 0x7d, 0x9d, 0x37, 0x2b, 0xb6, 0x82, + 0x6b, 0xd8, 0x1d, 0x35, 0x42, 0xa4, 0x19, 0xd6, + 0x2f, 0xd4, 0xe1, 0xc6, 0x7a, 0x2d, 0x28, 0xfc, + 0xed, 0x84, 0x9e, 0xe1, 0xbb, 0x76, 0xe7, 0x39, + 0x1b, 0x93, 0xeb, 0x12 } + }, + { "adfkadsofijadlkjoaijeoadaoijealfkajeflakepoieuproeirupqoeiruadslfasdlfadfowifjadfaleifafoeafwdflaheadfalefaahfaefefaeofadflafefaefeaeorea", + { 0x1b, 0x92, 0x8a, 0x64, 0x43, 0xfd, 0xdf, 0xa2, + 0x17, 0x05, 0x3b, 0x25, 0x08, 0x20, 0x81, 0xe5, + 0xb5, 0x6a, 0x92, 0x83, 0x2a, 0xb8, 0x98, 0xdf, + 0x37, 0xf6, 0x4b, 0x5b, 0x95, 0x9b, 0xfe, 0x9a, + 0xb5, 0x9f, 0x36, 0x86} + }, + }; + + int32 i; + unsigned char tmp[36]; + psMd5Sha1_t md; + + for (i = 0; i < (int32)(sizeof(tests) / sizeof(tests[0])); i++) { + _psTraceInt(" MD5SHA1 known vector test %d... ", i + 1); + psMd5Sha1Init(&md); + psMd5Sha1Update(&md, (unsigned char*)tests[i].msg, (uint32)strlen(tests[i].msg)); + psMd5Sha1Final(&md, tmp); + if (memcmp(tmp, tests[i].hash, 36) != 0) { + _psTrace("FAILED: mem compare failure\n"); + return -1; + } else { + _psTrace("PASSED\n"); + } + } + return PS_SUCCESS; +} +#endif /* USE_MD5SHA1 */ +/******************************************************************************/ + +/******************************************************************************/ +#ifdef USE_MD5 +int32 psMd5Test(void) +{ + static const struct { + char *msg; + unsigned char hash[16]; + } tests[] = { + { "", + { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, + 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } }, + { "a", + {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, + 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } }, + { "abc", + { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, + 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } }, + { "message digest", + { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, + 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }, + { "abcdefghijklmnopqrstuvwxyz", + { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, + 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, + 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", + { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, + 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }, + { NULL, { 0 } } + }; + + int32 i; + unsigned char tmp[MD5_HASHLEN]; + psMd5_t md; + + for (i = 0; tests[i].msg != NULL; i++) { + _psTraceInt(" MD5 known vector test %d... ", i + 1); + psMd5Init(&md); + psMd5Update(&md, (unsigned char *)tests[i].msg, + (uint32)strlen(tests[i].msg)); + psMd5Final(&md, tmp); + if (memcmp(tmp, tests[i].hash, MD5_HASHLEN) != 0) { + _psTrace("FAILED: memcmp\n"); + return -1; + } + _psTrace("PASSED\n"); + } + return PS_SUCCESS; +} +#endif /* USE_MD5 */ +/******************************************************************************/ + +/******************************************************************************/ +#ifdef USE_MD4 +int32 psMd4Test(void) +{ + static const struct md4_test_case { + char *input; + unsigned char digest[16]; + } cases[] = { + { "", + {0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31, + 0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0} }, + { "a", + {0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46, + 0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24} }, + { "abc", + {0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52, + 0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d} }, + { "message digest", + {0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8, + 0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b} }, + { "abcdefghijklmnopqrstuvwxyz", + {0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd, + 0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9} }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + {0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35, + 0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4} }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", + {0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19, + 0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36} }, + }; + int32 i; + psMd4_t md; + unsigned char digest[16]; + + for(i = 0; i < (int32)(sizeof(cases) / sizeof(cases[0])); i++) { + _psTraceInt(" MD4 known vector test %d... ", i + 1); + psMd4Init(&md); + psMd4Update(&md, (unsigned char *)cases[i].input, + (uint32)strlen(cases[i].input)); + psMd4Final(&md, digest); + if (memcmp(digest, cases[i].digest, 16) != 0) { + _psTrace("FAILED: memcmp\n"); + return -1; + } + _psTrace("PASSED\n"); + } + return PS_SUCCESS; +} +#endif /* USE_MD4 */ +/******************************************************************************/ + +/******************************************************************************/ +#ifdef USE_MD2 +int32 psMd2Test(void) +{ + static const struct { + char *msg; + unsigned char md[16]; + } tests[] = { + { "", + {0x83,0x50,0xe5,0xa3,0xe2,0x4c,0x15,0x3d, + 0xf2,0x27,0x5c,0x9f,0x80,0x69,0x27,0x73} + }, + { "a", + {0x32,0xec,0x01,0xec,0x4a,0x6d,0xac,0x72, + 0xc0,0xab,0x96,0xfb,0x34,0xc0,0xb5,0xd1} + }, + { "message digest", + {0xab,0x4f,0x49,0x6b,0xfb,0x2a,0x53,0x0b, + 0x21,0x9f,0xf3,0x30,0x31,0xfe,0x06,0xb0} + }, + { "abcdefghijklmnopqrstuvwxyz", + {0x4e,0x8d,0xdf,0xf3,0x65,0x02,0x92,0xab, + 0x5a,0x41,0x08,0xc3,0xaa,0x47,0x94,0x0b} + }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + {0xda,0x33,0xde,0xf2,0xa4,0x2d,0xf1,0x39, + 0x75,0x35,0x28,0x46,0xc3,0x03,0x38,0xcd} + }, + { "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + {0xd5,0x97,0x6f,0x79,0xd8,0x3d,0x3a,0x0d, + 0xc9,0x80,0x6c,0x3c,0x66,0xf3,0xef,0xd8} + } + }; + int32 i; + psMd2_t md; + unsigned char buf[16]; + + for (i = 0; i < (int32)(sizeof(tests) / sizeof(tests[0])); i++) { + _psTraceInt(" MD2 known vector test %d... ", i + 1); + psMd2Init(&md); + psMd2Update(&md, (unsigned char*)tests[i].msg, + (uint32)strlen(tests[i].msg)); + psMd2Final(&md, buf); + if (memcmp(buf, tests[i].md, 16) != 0) { + _psTrace("FAILED: memcmp\n"); + return -1; + } + _psTrace("PASSED\n"); + } + return PS_SUCCESS; +} +#endif /* USE_MD2 */ +/******************************************************************************/ + + +/******************************************************************************/ +#ifdef USE_RSA + +typedef void pkaCmdInfo_t; + +/* Sample keys and certs in memory for RSA testing */ +#include "../../testkeys/RSA/1024_RSA.h" +#include "../../testkeys/RSA/1024_RSA_KEY.h" +#include "../../testkeys/RSA/2048_RSA.h" +#include "../../testkeys/RSA/2048_RSA_KEY.h" +#include "../../testkeys/RSA/3072_RSA.h" +#include "../../testkeys/RSA/3072_RSA_KEY.h" +#include "../../testkeys/RSA/4096_RSA.h" +#include "../../testkeys/RSA/4096_RSA_KEY.h" + +struct { + uint16_t size; /* Size of public key exponent in bytes */ + const unsigned char *key; /* PKCS#1 key string */ + const unsigned char *cert; /* X.509 cert string */ + uint16_t keysize; /* Length of PKCS#1 key string */ + uint16_t certsize; /* Length of X.509 cert string */ +} rsa[3] = { + { 128, RSA1024KEY, RSA1024, sizeof(RSA1024KEY), sizeof(RSA1024) }, + { 256, RSA2048KEY, RSA2048, sizeof(RSA2048KEY), sizeof(RSA2048) }, + { 512, RSA4096KEY, RSA4096, sizeof(RSA4096KEY), sizeof(RSA4096) } +}; + +static int32 psRsaEncryptTest(void) +{ + psPool_t *pool = NULL; + psRsaKey_t privkey; + pkaCmdInfo_t *pkaInfo; +#ifdef USE_CERT_PARSE + psX509Cert_t *cert; +#endif /* USE_CERT_PARSE */ + unsigned char out[512]; /* Large enough to hold 4096 bits of output */ + unsigned char in[] = "hello"; + unsigned char decrypted[6]; + int i; + + pkaInfo = NULL; + + for (i = 0; + i < sizeof(rsa)/sizeof(rsa[0]) && rsa[i].size >= (MIN_RSA_BITS / 8); + i++) { + _psTraceInt(" %d bit test...", rsa[i].size * 8); + + + /* Start with getting both key halfs from the same source */ + if (psRsaInitKey(pool, &privkey) < 0) { + return -1; + } + if (psRsaParsePkcs1PrivKey(pool, rsa[i].key, rsa[i].keysize, &privkey) < 0) { + return -1; + } + psRsaEncryptPub(pool, &privkey, in, sizeof(in), out, rsa[i].size, pkaInfo); + psRsaDecryptPriv(pool, &privkey, out, rsa[i].size, decrypted, + sizeof(decrypted), pkaInfo); + if (memcmp(decrypted, "hello", 5) != 0) { + _psTrace("RSA failure: mem compare failure 1\n"); + psRsaClearKey(&privkey); + continue; + } + psRsaClearKey(&privkey); + memset(decrypted, 0x0, sizeof(decrypted)); + memset(out, 0x0, sizeof(out)); + +#ifdef USE_CERT_PARSE + /* Get the public key from the cert */ + psRsaInitKey(pool, &privkey); + psRsaParsePkcs1PrivKey(pool, rsa[i].key, rsa[i].keysize, &privkey); + psX509ParseCert(pool, rsa[i].cert, rsa[i].certsize, &cert, 0); + psRsaEncryptPub(pool, &cert->publicKey.key.rsa, in, sizeof(in), out, + rsa[i].size, pkaInfo); + psRsaDecryptPriv(pool, &privkey, out, rsa[i].size, decrypted, + sizeof(decrypted), pkaInfo); + if (memcmp(decrypted, "hello", 5) != 0) { + psRsaClearKey(&privkey); + psX509FreeCert(cert); + _psTrace("RSA failure: mem compare failure 2\n"); + continue; + } + psRsaClearKey(&privkey); + psX509FreeCert(cert); + memset(decrypted, 0x0, sizeof(decrypted)); + memset(out, 0x0, sizeof(out)); +#endif /* USE_CERT_PARSE */ + + _psTrace(" PASSED\n"); + + } /* key loop */ + + + return PS_SUCCESS; +} + +/* Test RSA Signing, using RSA-2048 and SHA-256. */ +static int32 psRsaSignTest(void) +{ + psPool_t *pool = NULL; + unsigned char in[32] = "helloworldhelloworldhelloworld1"; + unsigned char out[512]; + unsigned char decrypted[32]; + psRsaKey_t privkey; + pkaCmdInfo_t *pkaInfo; + int32_t rc; + int i; + + pkaInfo = NULL; + + for (i = 0; + i < sizeof(rsa)/sizeof(rsa[0]) && rsa[i].size >= (MIN_RSA_BITS / 8); + i++) { + _psTraceInt(" %d bit test...", rsa[i].size * 8); + + + psRsaInitKey(pool, &privkey); + psRsaParsePkcs1PrivKey(pool, rsa[i].key, rsa[i].keysize, &privkey); + if (psRsaEncryptPriv(pool, &privkey, in, sizeof(in), out, rsa[i].size, + pkaInfo) < 0) { + psRsaClearKey(&privkey); + return PS_FAILURE; + } + + rc = psRsaDecryptPub(pool, &privkey, out, rsa[i].size, decrypted, + sizeof(decrypted), pkaInfo); + if (rc < 0) { + _psTraceInt(" psRsaDecryptPub failure (%d)\n", rc); + psRsaClearKey(&privkey); + return PS_FAILURE; + } + if (memcmp(decrypted, in, sizeof(in)) != 0) { + _psTraceStr("RSA failure: mem compare failure (%s)\n", + (const char*)decrypted); + psRsaClearKey(&privkey); + return PS_FAILURE; + } + + psRsaClearKey(&privkey); + _psTrace(" PASSED\n"); + + } /* key loop */ + + return PS_SUCCESS; +} + + +/******************************************************************************/ +#ifdef USE_PKCS1_OAEP +/* OAEP-VEC.TXT from RSA PKCS#1 web page */ +static unsigned char key1N[] = { + 0xa8, 0xb3, 0xb2, 0x84, 0xaf, 0x8e, 0xb5, 0x0b, 0x38, 0x70, 0x34, 0xa8, + 0x60, 0xf1, 0x46, 0xc4, 0x91, 0x9f, 0x31, 0x87, 0x63, 0xcd, 0x6c, 0x55, + 0x98, 0xc8, 0xae, 0x48, 0x11, 0xa1, 0xe0, 0xab, 0xc4, 0xc7, 0xe0, 0xb0, + 0x82, 0xd6, 0x93, 0xa5, 0xe7, 0xfc, 0xed, 0x67, 0x5c, 0xf4, 0x66, 0x85, + 0x12, 0x77, 0x2c, 0x0c, 0xbc, 0x64, 0xa7, 0x42, 0xc6, 0xc6, 0x30, 0xf5, + 0x33, 0xc8, 0xcc, 0x72, 0xf6, 0x2a, 0xe8, 0x33, 0xc4, 0x0b, 0xf2, 0x58, + 0x42, 0xe9, 0x84, 0xbb, 0x78, 0xbd, 0xbf, 0x97, 0xc0, 0x10, 0x7d, 0x55, + 0xbd, 0xb6, 0x62, 0xf5, 0xc4, 0xe0, 0xfa, 0xb9, 0x84, 0x5c, 0xb5, 0x14, + 0x8e, 0xf7, 0x39, 0x2d, 0xd3, 0xaa, 0xff, 0x93, 0xae, 0x1e, 0x6b, 0x66, + 0x7b, 0xb3, 0xd4, 0x24, 0x76, 0x16, 0xd4, 0xf5, 0xba, 0x10, 0xd4, 0xcf, + 0xd2, 0x26, 0xde, 0x88, 0xd3, 0x9f, 0x16, 0xfb +}; +static unsigned char key1e[] = {0x01, 0x00, 0x01}; + +static unsigned char key1d[] = { + 0x53, 0x33, 0x9c, 0xfd, 0xb7, 0x9f, 0xc8, 0x46, 0x6a, 0x65, 0x5c, 0x73, + 0x16, 0xac, 0xa8, 0x5c, 0x55, 0xfd, 0x8f, 0x6d, 0xd8, 0x98, 0xfd, 0xaf, + 0x11, 0x95, 0x17, 0xef, 0x4f, 0x52, 0xe8, 0xfd, 0x8e, 0x25, 0x8d, 0xf9, + 0x3f, 0xee, 0x18, 0x0f, 0xa0, 0xe4, 0xab, 0x29, 0x69, 0x3c, 0xd8, 0x3b, + 0x15, 0x2a, 0x55, 0x3d, 0x4a, 0xc4, 0xd1, 0x81, 0x2b, 0x8b, 0x9f, 0xa5, + 0xaf, 0x0e, 0x7f, 0x55, 0xfe, 0x73, 0x04, 0xdf, 0x41, 0x57, 0x09, 0x26, + 0xf3, 0x31, 0x1f, 0x15, 0xc4, 0xd6, 0x5a, 0x73, 0x2c, 0x48, 0x31, 0x16, + 0xee, 0x3d, 0x3d, 0x2d, 0x0a, 0xf3, 0x54, 0x9a, 0xd9, 0xbf, 0x7c, 0xbf, + 0xb7, 0x8a, 0xd8, 0x84, 0xf8, 0x4d, 0x5b, 0xeb, 0x04, 0x72, 0x4d, 0xc7, + 0x36, 0x9b, 0x31, 0xde, 0xf3, 0x7d, 0x0c, 0xf5, 0x39, 0xe9, 0xcf, 0xcd, + 0xd3, 0xde, 0x65, 0x37, 0x29, 0xea, 0xd5, 0xd1 +}; + +static unsigned char key1p[] = { + 0xd3, 0x27, 0x37, 0xe7, 0x26, 0x7f, 0xfe, 0x13, 0x41, 0xb2, 0xd5, 0xc0, + 0xd1, 0x50, 0xa8, 0x1b, 0x58, 0x6f, 0xb3, 0x13, 0x2b, 0xed, 0x2f, 0x8d, + 0x52, 0x62, 0x86, 0x4a, 0x9c, 0xb9, 0xf3, 0x0a, 0xf3, 0x8b, 0xe4, 0x48, + 0x59, 0x8d, 0x41, 0x3a, 0x17, 0x2e, 0xfb, 0x80, 0x2c, 0x21, 0xac, 0xf1, + 0xc1, 0x1c, 0x52, 0x0c, 0x2f, 0x26, 0xa4, 0x71, 0xdc, 0xad, 0x21, 0x2e, + 0xac, 0x7c, 0xa3, 0x9d +}; + +static unsigned char key1q[] = { + 0xcc, 0x88, 0x53, 0xd1, 0xd5, 0x4d, 0xa6, 0x30, 0xfa, 0xc0, 0x04, 0xf4, + 0x71, 0xf2, 0x81, 0xc7, 0xb8, 0x98, 0x2d, 0x82, 0x24, 0xa4, 0x90, 0xed, + 0xbe, 0xb3, 0x3d, 0x3e, 0x3d, 0x5c, 0xc9, 0x3c, 0x47, 0x65, 0x70, 0x3d, + 0x1d, 0xd7, 0x91, 0x64, 0x2f, 0x1f, 0x11, 0x6a, 0x0d, 0xd8, 0x52, 0xbe, + 0x24, 0x19, 0xb2, 0xaf, 0x72, 0xbf, 0xe9, 0xa0, 0x30, 0xe8, 0x60, 0xb0, + 0x28, 0x8b, 0x5d, 0x77 +}; + +static unsigned char key1dP[] = { + 0x0e, 0x12, 0xbf, 0x17, 0x18, 0xe9, 0xce, 0xf5, 0x59, 0x9b, 0xa1, 0xc3, + 0x88, 0x2f, 0xe8, 0x04, 0x6a, 0x90, 0x87, 0x4e, 0xef, 0xce, 0x8f, 0x2c, + 0xcc, 0x20, 0xe4, 0xf2, 0x74, 0x1f, 0xb0, 0xa3, 0x3a, 0x38, 0x48, 0xae, + 0xc9, 0xc9, 0x30, 0x5f, 0xbe, 0xcb, 0xd2, 0xd7, 0x68, 0x19, 0x96, 0x7d, + 0x46, 0x71, 0xac, 0xc6, 0x43, 0x1e, 0x40, 0x37, 0x96, 0x8d, 0xb3, 0x78, + 0x78, 0xe6, 0x95, 0xc1 +}; + +static unsigned char key1dQ[] = { + 0x95, 0x29, 0x7b, 0x0f, 0x95, 0xa2, 0xfa, 0x67, 0xd0, 0x07, 0x07, 0xd6, + 0x09, 0xdf, 0xd4, 0xfc, 0x05, 0xc8, 0x9d, 0xaf, 0xc2, 0xef, 0x6d, 0x6e, + 0xa5, 0x5b, 0xec, 0x77, 0x1e, 0xa3, 0x33, 0x73, 0x4d, 0x92, 0x51, 0xe7, + 0x90, 0x82, 0xec, 0xda, 0x86, 0x6e, 0xfe, 0xf1, 0x3c, 0x45, 0x9e, 0x1a, + 0x63, 0x13, 0x86, 0xb7, 0xe3, 0x54, 0xc8, 0x99, 0xf5, 0xf1, 0x12, 0xca, + 0x85, 0xd7, 0x15, 0x83 +}; + +static unsigned char key1qP[] = { + 0x4f, 0x45, 0x6c, 0x50, 0x24, 0x93, 0xbd, 0xc0, 0xed, 0x2a, 0xb7, 0x56, + 0xa3, 0xa6, 0xed, 0x4d, 0x67, 0x35, 0x2a, 0x69, 0x7d, 0x42, 0x16, 0xe9, + 0x32, 0x12, 0xb1, 0x27, 0xa6, 0x3d, 0x54, 0x11, 0xce, 0x6f, 0xa9, 0x8d, + 0x5d, 0xbe, 0xfd, 0x73, 0x26, 0x3e, 0x37, 0x28, 0x14, 0x27, 0x43, 0x81, + 0x81, 0x66, 0xed, 0x7d, 0xd6, 0x36, 0x87, 0xdd, 0x2a, 0x8c, 0xa1, 0xd2, + 0xf4, 0xfb, 0xd8, 0xe1 +}; + +static unsigned char key1TestMsg[] = { + 0x66, 0x28, 0x19, 0x4e, 0x12, 0x07, 0x3d, 0xb0, 0x3b, 0xa9, 0x4c, 0xda, + 0x9e, 0xf9, 0x53, 0x23, 0x97, 0xd5, 0x0d, 0xba, 0x79, 0xb9, 0x87, 0x00, + 0x4a, 0xfe, 0xfe, 0x34 +}; + +static unsigned char key1SeedPad[] = { + 0x18, 0xb7, 0x76, 0xea, 0x21, 0x06, 0x9d, 0x69, 0x77, 0x6a, 0x33, 0xe9, + 0x6b, 0xad, 0x48, 0xe1, 0xdd, 0xa0, 0xa5, 0xef +}; + +static unsigned char key1EncryptedResult[] = { + 0x35, 0x4f, 0xe6, 0x7b, 0x4a, 0x12, 0x6d, 0x5d, 0x35, 0xfe, 0x36, 0xc7, + 0x77, 0x79, 0x1a, 0x3f, 0x7b, 0xa1, 0x3d, 0xef, 0x48, 0x4e, 0x2d, 0x39, + 0x08, 0xaf, 0xf7, 0x22, 0xfa, 0xd4, 0x68, 0xfb, 0x21, 0x69, 0x6d, 0xe9, + 0x5d, 0x0b, 0xe9, 0x11, 0xc2, 0xd3, 0x17, 0x4f, 0x8a, 0xfc, 0xc2, 0x01, + 0x03, 0x5f, 0x7b, 0x6d, 0x8e, 0x69, 0x40, 0x2d, 0xe5, 0x45, 0x16, 0x18, + 0xc2, 0x1a, 0x53, 0x5f, 0xa9, 0xd7, 0xbf, 0xc5, 0xb8, 0xdd, 0x9f, 0xc2, + 0x43, 0xf8, 0xcf, 0x92, 0x7d, 0xb3, 0x13, 0x22, 0xd6, 0xe8, 0x81, 0xea, + 0xa9, 0x1a, 0x99, 0x61, 0x70, 0xe6, 0x57, 0xa0, 0x5a, 0x26, 0x64, 0x26, + 0xd9, 0x8c, 0x88, 0x00, 0x3f, 0x84, 0x77, 0xc1, 0x22, 0x70, 0x94, 0xa0, + 0xd9, 0xfa, 0x1e, 0x8c, 0x40, 0x24, 0x30, 0x9c, 0xe1, 0xec, 0xcc, 0xb5, + 0x21, 0x00, 0x35, 0xd4, 0x7a, 0xc7, 0x2e, 0x8a +}; + +static int32 psRsaOaepVectorTest(void) +{ + psPool_t *pool = NULL; + psRsaKey_t key1; + pstm_int mpN, mpe, mpd, mpp, mpq, mpdP, mpdQ, mpqP; + uint32 digSize; + uint16_t outLen; + unsigned char *outOaep, *outRsaE, *outRsaD; + int32 ret; + + outOaep = outRsaE = outRsaD = NULL; + digSize = sizeof(pstm_digit); + + if (pstm_init_for_read_unsigned_bin(pool, &mpN, sizeof(key1N) + digSize) + != PS_SUCCESS) { + return PS_FAILURE; + } + pstm_read_unsigned_bin(&mpN, key1N, sizeof(key1N)); + + if (pstm_init_for_read_unsigned_bin(pool, &mpe, sizeof(key1e) + digSize) + != PS_SUCCESS) { + return PS_FAILURE; + } + pstm_read_unsigned_bin(&mpe, key1e, sizeof(key1e)); + + if (pstm_init_for_read_unsigned_bin(pool, &mpd, sizeof(key1d) + digSize) + != PS_SUCCESS) { + return PS_FAILURE; + } + pstm_read_unsigned_bin(&mpd, key1d, sizeof(key1d)); + + if (pstm_init_for_read_unsigned_bin(pool, &mpp, sizeof(key1p) + digSize) + != PS_SUCCESS) { + return PS_FAILURE; + } + pstm_read_unsigned_bin(&mpp, key1p, sizeof(key1p)); + + if (pstm_init_for_read_unsigned_bin(NULL, &mpq, sizeof(key1q) + digSize) + != PS_SUCCESS) { + return PS_FAILURE; + } + pstm_read_unsigned_bin(&mpq, key1q, sizeof(key1q)); + + if (pstm_init_for_read_unsigned_bin(pool, &mpdP, sizeof(key1dP) + digSize) + != PS_SUCCESS) { + return PS_FAILURE; + } + pstm_read_unsigned_bin(&mpdP, key1dP, sizeof(key1dP)); + + if (pstm_init_for_read_unsigned_bin(pool, &mpdQ, sizeof(key1dQ) + digSize) + != PS_SUCCESS) { + return PS_FAILURE; + } + pstm_read_unsigned_bin(&mpdQ, key1dQ, sizeof(key1dQ)); + + if (pstm_init_for_read_unsigned_bin(pool, &mpqP, sizeof(key1qP) + digSize) + != PS_SUCCESS) { + return PS_FAILURE; + } + pstm_read_unsigned_bin(&mpqP, key1qP, sizeof(key1qP)); + + key1.e = mpe; + key1.N = mpN; + key1.d = mpd; + key1.p = mpp; + key1.q = mpq; + key1.dP = mpdP; + key1.dQ = mpdQ; + key1.qP = mpqP; + key1.optimized = 1; + outLen = key1.size = pstm_unsigned_bin_size(&mpN); + + outOaep = psMalloc(pool, outLen); + pkcs1OaepEncode(pool, key1TestMsg, sizeof(key1TestMsg), NULL, 0, + key1SeedPad, sizeof(key1SeedPad), key1.size * CHAR_BIT, 0, outOaep, + &outLen); + + outRsaE = psMalloc(pool, outLen); + psRsaCrypt(pool, &key1, outOaep, outLen, outRsaE, &outLen, PS_PUBKEY, NULL); + + if (memcmp(outRsaE, key1EncryptedResult, outLen) != 0) { + _psTrace("ERROR in encrypting key1 RSAES_OAEP vector test\n"); + ret = PS_FAILURE; + goto LBL_ERR; + } + + outRsaD = psMalloc(pool, outLen); + psRsaCrypt(pool, &key1, outRsaE, outLen, outRsaD, &outLen, PS_PRIVKEY, NULL); + + memset(outOaep, 0x0, key1.size); + pkcs1OaepDecode(pool, outRsaD, outLen, NULL, 0, key1.size * CHAR_BIT, 0, + outOaep, &outLen); + + if ((outLen != sizeof(key1TestMsg)) || (memcmp(outOaep, key1TestMsg, outLen) + != 0)) { + _psTrace("ERROR in decrypting key1 RSAES_OAEP vector test\n"); + ret = PS_FAILURE; + goto LBL_ERR; + } + +/* + Now just run a plaintext test of our choosing with the MD5 hash and label +*/ + outLen = key1.size; + if (pkcs1OaepEncode(pool, (const unsigned char*)"Hello", 5, + (const unsigned char*)"mylabel", 7, NULL, 0, + key1.size * CHAR_BIT, 1, outOaep, &outLen) < PS_SUCCESS) { + _psTrace("ERROR encoding standard RSAES_OAEP vector test\n"); + ret = PS_FAILURE; + goto LBL_ERR; + } + psRsaCrypt(pool, &key1, outOaep, outLen, outRsaE, &outLen, PS_PUBKEY, NULL); + + psRsaCrypt(pool, &key1, outRsaE, outLen, outRsaD, &outLen, PS_PRIVKEY, NULL); + pkcs1OaepDecode(pool, outRsaD, outLen, (const unsigned char*)"mylabel", 7, + key1.size * CHAR_BIT, 1, outOaep, &outLen); + + if (memcmp(outOaep, "Hello", outLen) != 0) { + _psTrace("ERROR in standard RSAES_OAEP vector test\n"); + ret = PS_FAILURE; + goto LBL_ERR; + } + + _psTrace(" PASSED\n"); + ret = PS_SUCCESS; +LBL_ERR: + pstm_clear(&key1.N); + pstm_clear(&key1.e); + pstm_clear(&key1.d); + pstm_clear(&key1.p); + pstm_clear(&key1.q); + pstm_clear(&key1.dP); + pstm_clear(&key1.dQ); + pstm_clear(&key1.qP); + psFree(outOaep, pool); + psFree(outRsaE, pool); + psFree(outRsaD, pool); + return ret; +} +#endif /* USE_PKCS1_OAEP */ + +/******************************************************************************/ +#ifdef USE_PKCS1_PSS +#ifndef USE_PKCS1_PSS_VERIFY_ONLY /* Because PSS signing is used in this test. */ +/* PSS-VEC.TXT from RSA PKCS#1 web page */ +static unsigned char key2N[] = { + 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51, 0x87, 0xdc, + 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e, 0x36, 0xad, 0x52, 0xa4, + 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a, 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, + 0xff, 0xed, 0xb1, 0x62, 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, + 0x94, 0xdf, 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab, + 0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d, 0x5b, 0x2b, + 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77, 0xc0, 0x92, 0x1c, 0xb2, + 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59, 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, + 0x05, 0xac, 0xc2, 0xd3, 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, + 0x6b, 0x6f, 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8, + 0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 +}; +static unsigned char key2e[] = {0x01, 0x00, 0x01}; + +static unsigned char key2d[] = { + 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51, 0xca, 0x9b, + 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf, 0x88, 0x43, 0x40, 0xae, + 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe, 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, + 0x3c, 0x56, 0x8c, 0x8f, 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, + 0xc6, 0xa3, 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44, + 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10, 0xce, 0x70, + 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27, 0xa3, 0x95, 0x74, 0x50, + 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c, 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, + 0x31, 0xb4, 0xbd, 0x2f, 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, + 0x4f, 0x9e, 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc, + 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 +}; + +static unsigned char key2p[] = { + 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73, 0xa3, 0x56, + 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa, 0x72, 0xd5, 0x5c, 0x6e, + 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96, 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, + 0xcc, 0xa7, 0xea, 0xcb, 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, + 0x53, 0x5b, 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e, + 0xda, 0x8e, 0x64, 0x43 +}; + +static unsigned char key2q[] = { + 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7, 0x5b, 0x90, + 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f, 0xd2, 0x70, 0x01, 0x80, + 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48, 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, + 0xf1, 0x9d, 0x85, 0xba, 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, + 0x72, 0x3e, 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26, + 0x9a, 0x67, 0x99, 0xfd +}; + +static unsigned char key2dP[] = { + 0x28, 0xfa, 0x13, 0x93, 0x86, 0x55, 0xbe, 0x1f, 0x8a, 0x15, 0x9c, 0xba, + 0xca, 0x5a, 0x72, 0xea, 0x19, 0x0c, 0x30, 0x08, 0x9e, 0x19, 0xcd, 0x27, + 0x4a, 0x55, 0x6f, 0x36, 0xc4, 0xf6, 0xe1, 0x9f, 0x55, 0x4b, 0x34, 0xc0, + 0x77, 0x79, 0x04, 0x27, 0xbb, 0xdd, 0x8d, 0xd3, 0xed, 0xe2, 0x44, 0x83, + 0x28, 0xf3, 0x85, 0xd8, 0x1b, 0x30, 0xe8, 0xe4, 0x3b, 0x2f, 0xff, 0xa0, + 0x27, 0x86, 0x19, 0x79 +}; + +static unsigned char key2dQ[] = { + 0x1a, 0x8b, 0x38, 0xf3, 0x98, 0xfa, 0x71, 0x20, 0x49, 0x89, 0x8d, 0x7f, + 0xb7, 0x9e, 0xe0, 0xa7, 0x76, 0x68, 0x79, 0x12, 0x99, 0xcd, 0xfa, 0x09, + 0xef, 0xc0, 0xe5, 0x07, 0xac, 0xb2, 0x1e, 0xd7, 0x43, 0x01, 0xef, 0x5b, + 0xfd, 0x48, 0xbe, 0x45, 0x5e, 0xae, 0xb6, 0xe1, 0x67, 0x82, 0x55, 0x82, + 0x75, 0x80, 0xa8, 0xe4, 0xe8, 0xe1, 0x41, 0x51, 0xd1, 0x51, 0x0a, 0x82, + 0xa3, 0xf2, 0xe7, 0x29 +}; + +static unsigned char key2qP[] = { + 0x27, 0x15, 0x6a, 0xba, 0x41, 0x26, 0xd2, 0x4a, 0x81, 0xf3, 0xa5, 0x28, + 0xcb, 0xfb, 0x27, 0xf5, 0x68, 0x86, 0xf8, 0x40, 0xa9, 0xf6, 0xe8, 0x6e, + 0x17, 0xa4, 0x4b, 0x94, 0xfe, 0x93, 0x19, 0x58, 0x4b, 0x8e, 0x22, 0xfd, + 0xde, 0x1e, 0x5a, 0x2e, 0x3b, 0xd8, 0xaa, 0x5b, 0xa8, 0xd8, 0x58, 0x41, + 0x94, 0xeb, 0x21, 0x90, 0xac, 0xf8, 0x32, 0xb8, 0x47, 0xf1, 0x3a, 0x3d, + 0x24, 0xa7, 0x9f, 0x4d +}; + +static unsigned char key2TestMsg[] = { + 0xcd, 0xc8, 0x7d, 0xa2, 0x23, 0xd7, 0x86, 0xdf, 0x3b, 0x45, 0xe0, 0xbb, + 0xbc, 0x72, 0x13, 0x26, 0xd1, 0xee, 0x2a, 0xf8, 0x06, 0xcc, 0x31, 0x54, + 0x75, 0xcc, 0x6f, 0x0d, 0x9c, 0x66, 0xe1, 0xb6, 0x23, 0x71, 0xd4, 0x5c, + 0xe2, 0x39, 0x2e, 0x1a, 0xc9, 0x28, 0x44, 0xc3, 0x10, 0x10, 0x2f, 0x15, + 0x6a, 0x0d, 0x8d, 0x52, 0xc1, 0xf4, 0xc4, 0x0b, 0xa3, 0xaa, 0x65, 0x09, + 0x57, 0x86, 0xcb, 0x76, 0x97, 0x57, 0xa6, 0x56, 0x3b, 0xa9, 0x58, 0xfe, + 0xd0, 0xbc, 0xc9, 0x84, 0xe8, 0xb5, 0x17, 0xa3, 0xd5, 0xf5, 0x15, 0xb2, + 0x3b, 0x8a, 0x41, 0xe7, 0x4a, 0xa8, 0x67, 0x69, 0x3f, 0x90, 0xdf, 0xb0, + 0x61, 0xa6, 0xe8, 0x6d, 0xfa, 0xae, 0xe6, 0x44, 0x72, 0xc0, 0x0e, 0x5f, + 0x20, 0x94, 0x57, 0x29, 0xcb, 0xeb, 0xe7, 0x7f, 0x06, 0xce, 0x78, 0xe0, + 0x8f, 0x40, 0x98, 0xfb, 0xa4, 0x1f, 0x9d, 0x61, 0x93, 0xc0, 0x31, 0x7e, + 0x8b, 0x60, 0xd4, 0xb6, 0x08, 0x4a, 0xcb, 0x42, 0xd2, 0x9e, 0x38, 0x08, + 0xa3, 0xbc, 0x37, 0x2d, 0x85, 0xe3, 0x31, 0x17, 0x0f, 0xcb, 0xf7, 0xcc, + 0x72, 0xd0, 0xb7, 0x1c, 0x29, 0x66, 0x48, 0xb3, 0xa4, 0xd1, 0x0f, 0x41, + 0x62, 0x95, 0xd0, 0x80, 0x7a, 0xa6, 0x25, 0xca, 0xb2, 0x74, 0x4f, 0xd9, + 0xea, 0x8f, 0xd2, 0x23, 0xc4, 0x25, 0x37, 0x02, 0x98, 0x28, 0xbd, 0x16, + 0xbe, 0x02, 0x54, 0x6f, 0x13, 0x0f, 0xd2, 0xe3, 0x3b, 0x93, 0x6d, 0x26, + 0x76, 0xe0, 0x8a, 0xed, 0x1b, 0x73, 0x31, 0x8b, 0x75, 0x0a, 0x01, 0x67, + 0xd0 +}; + +static unsigned char key2salt[] = { + 0xde, 0xe9, 0x59, 0xc7, 0xe0, 0x64, 0x11, 0x36, 0x14, 0x20, 0xff, 0x80, + 0x18, 0x5e, 0xd5, 0x7f, 0x3e, 0x67, 0x76, 0xaf +}; + +static unsigned char key2sig[] = { + 0x90, 0x74, 0x30, 0x8f, 0xb5, 0x98, 0xe9, 0x70, 0x1b, 0x22, 0x94, 0x38, + 0x8e, 0x52, 0xf9, 0x71, 0xfa, 0xac, 0x2b, 0x60, 0xa5, 0x14, 0x5a, 0xf1, + 0x85, 0xdf, 0x52, 0x87, 0xb5, 0xed, 0x28, 0x87, 0xe5, 0x7c, 0xe7, 0xfd, + 0x44, 0xdc, 0x86, 0x34, 0xe4, 0x07, 0xc8, 0xe0, 0xe4, 0x36, 0x0b, 0xc2, + 0x26, 0xf3, 0xec, 0x22, 0x7f, 0x9d, 0x9e, 0x54, 0x63, 0x8e, 0x8d, 0x31, + 0xf5, 0x05, 0x12, 0x15, 0xdf, 0x6e, 0xbb, 0x9c, 0x2f, 0x95, 0x79, 0xaa, + 0x77, 0x59, 0x8a, 0x38, 0xf9, 0x14, 0xb5, 0xb9, 0xc1, 0xbd, 0x83, 0xc4, + 0xe2, 0xf9, 0xf3, 0x82, 0xa0, 0xd0, 0xaa, 0x35, 0x42, 0xff, 0xee, 0x65, + 0x98, 0x4a, 0x60, 0x1b, 0xc6, 0x9e, 0xb2, 0x8d, 0xeb, 0x27, 0xdc, 0xa1, + 0x2c, 0x82, 0xc2, 0xd4, 0xc3, 0xf6, 0x6c, 0xd5, 0x00, 0xf1, 0xff, 0x2b, + 0x99, 0x4d, 0x8a, 0x4e, 0x30, 0xcb, 0xb3, 0x3c +}; + +static int32 psRsaPssVectorTest(void) +{ + psPool_t *pool = NULL; + psRsaKey_t key1; + pstm_int mpN, mpe, mpd, mpp, mpq, mpdP, mpdQ, mpqP; + uint32 digSize, outLen; + uint16_t outLen16; + unsigned char *outPss, *outRsaE, *outRsaD; + psSha1_t md; + unsigned char hash[SHA1_HASH_SIZE]; + int32 result, ret; + + outPss = outRsaE = outRsaD = NULL; + + digSize = sizeof(pstm_digit); + + if (pstm_init_for_read_unsigned_bin(pool, &mpN, sizeof(key2N) + digSize) + != PS_SUCCESS) { + return PS_FAILURE; + } + pstm_read_unsigned_bin(&mpN, key2N, sizeof(key2N)); + + if (pstm_init_for_read_unsigned_bin(pool, &mpe, sizeof(key2e) + digSize) + != PS_SUCCESS) { + return PS_FAILURE; + } + pstm_read_unsigned_bin(&mpe, key2e, sizeof(key2e)); + + if (pstm_init_for_read_unsigned_bin(pool, &mpd, sizeof(key2d) + digSize) + != PS_SUCCESS) { + return PS_FAILURE; + } + pstm_read_unsigned_bin(&mpd, key2d, sizeof(key2d)); + + if (pstm_init_for_read_unsigned_bin(pool, &mpp, sizeof(key2p) + digSize) + != PS_SUCCESS) { + return PS_FAILURE; + } + pstm_read_unsigned_bin(&mpp, key2p, sizeof(key2p)); + + if (pstm_init_for_read_unsigned_bin(pool, &mpq, sizeof(key2q) + digSize) + != PS_SUCCESS) { + return PS_FAILURE; + } + pstm_read_unsigned_bin(&mpq, key2q, sizeof(key2q)); + + if (pstm_init_for_read_unsigned_bin(pool, &mpdP, sizeof(key2dP) + digSize) + != PS_SUCCESS) { + return PS_FAILURE; + } + pstm_read_unsigned_bin(&mpdP, key2dP, sizeof(key2dP)); + + if (pstm_init_for_read_unsigned_bin(pool, &mpdQ, sizeof(key2dQ) + digSize) + != PS_SUCCESS) { + return PS_FAILURE; + } + pstm_read_unsigned_bin(&mpdQ, key2dQ, sizeof(key2dQ)); + + if (pstm_init_for_read_unsigned_bin(pool, &mpqP, sizeof(key2qP) + digSize) + != PS_SUCCESS) { + return PS_FAILURE; + } + pstm_read_unsigned_bin(&mpqP, key2qP, sizeof(key2qP)); + + key1.e = mpe; + key1.N = mpN; + key1.d = mpd; + key1.p = mpp; + key1.q = mpq; + key1.dP = mpdP; + key1.dQ = mpdQ; + key1.qP = mpqP; + key1.optimized = 1; + outLen = key1.size = pstm_unsigned_bin_size(&mpN); + + /* First take SHA-1 hash of test message */ + psSha1Init(&md); + psSha1Update(&md, key2TestMsg, sizeof(key2TestMsg)); + psSha1Final(&md, hash); + + /* Then PSS */ + outPss = psMalloc(pool, outLen); + outLen16 = (uint16_t) outLen; + pkcs1PssEncode(pool, hash, SHA1_HASH_SIZE, key2salt, sizeof(key2salt), + 0, key1.size * CHAR_BIT, outPss, &outLen16); + outLen = outLen16; + + outRsaE = psMalloc(pool, outLen); + /* Then sign */ + psRsaCrypt(pool, &key1, outPss, outLen, outRsaE, &outLen16, PS_PRIVKEY, + NULL); + outLen = outLen16; + + /* Check against vector */ + if (memcmp(outRsaE, key2sig, outLen) != 0) { + _psTrace("ERROR in encrypting key1 RSASSA_PSS vector test\n"); + ret = PS_FAILURE; + goto LBL_ERR; + } + /* Verify */ + outRsaD = psMalloc(pool, outLen); + /* Decrypt */ + outLen16 = (uint16_t) outLen; + psRsaCrypt(pool, &key1, outRsaE, outLen, outRsaD, &outLen16, PS_PUBKEY, NULL); + outLen = outLen16; + /* PSS decode */ + pkcs1PssDecode(pool, hash, SHA1_HASH_SIZE, outRsaD, outLen, + sizeof(key2salt), 0, key1.size * CHAR_BIT, &result); + + if (result != 1) { + _psTrace("ERROR in decrypting key1 RSASSA_PSS vector test\n"); + ret = PS_FAILURE; + goto LBL_ERR; + } + + _psTrace(" PASSED\n"); + ret = PS_SUCCESS; + +LBL_ERR: + pstm_clear(&key1.N); + pstm_clear(&key1.e); + pstm_clear(&key1.d); + pstm_clear(&key1.p); + pstm_clear(&key1.q); + pstm_clear(&key1.dP); + pstm_clear(&key1.dQ); + pstm_clear(&key1.qP); + psFree(outRsaD, pool); + psFree(outPss, pool); + psFree(outRsaE, pool); + return ret; +} +#endif /* USE_PKCS1_PSS_VERIFY_ONLY */ +#endif /* USE_PKCS1_PSS */ + +#endif /* USE_RSA */ + +#ifdef USE_HMAC +#ifdef USE_HMAC_TLS +static int nohmactls = 0; +#endif + +static int32 psHmacVectorTestSimple(void) +{ + unsigned char res[20]; + unsigned char res2[20]; + psHmacSha1_t ctx; + int32_t rv; + const char *data1 = "Hi There"; + + unsigned char key1[] = { + 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b + }; + const unsigned char res1[] = { + 0xb6, 0x17, 0x31, 0x86, + 0x55, 0x05, 0x72, 0x64, + 0xe2, 0x8b, 0xc0, 0xb6, + 0xfb, 0x37, 0x8c, 0x8e, + 0xf1, 0x46, 0xbe, 0x00 + }; + uint16_t keyLen = (uint16_t) sizeof(key1); + + _psTraceInt(" SHA-1 known vector test %d... ", 1); + + /* Try single-call */ + rv = psHmacSha1(key1, keyLen, (unsigned char *) data1, + (uint32_t) strlen(data1), res2, + key1, &keyLen); + if (rv != PS_SUCCESS) { + _psTraceInt("FAILED: Single-part HMAC KAT execution failure (rv=%d)\n", + (int)rv); + return PS_FAILURE; + } + if (memcmp(res1, res2, 20) != 0) { + _psTrace("FAILED: Single-part HMAC KAT mismatch\n"); + return PS_FAILURE; + } + +#ifdef USE_HMAC_TLS + /* Try single-call */ + memset(res2, 0, 20); + rv = psHmacSha1Tls(key1, keyLen, + (unsigned char *) data1, 2, + (unsigned char *) data1 + 2, 4, + (unsigned char *) data1 + 6, 2, 2, res2); + if (rv == PS_DISABLED_FEATURE_FAIL) { + nohmactls = 1; + } else if (rv != SHA1_HASH_SIZE) { + _psTraceInt("FAILED: Single-part HMAC KAT execution failure (rv=%d)\n", + (int)rv); + return PS_FAILURE; + } else if (memcmp(res1, res2, 20) != 0) { + _psTrace("FAILED: Single-part HMAC KAT mismatch\n"); + return PS_FAILURE; + } +#endif /* USE_HMAC_TLS */ + + /* Try init-update-finish */ + rv = psHmacSha1Init(&ctx, key1, keyLen); + psHmacSha1Update(&ctx, (unsigned char *) data1, (uint32_t) strlen(data1)); + (void)psHmacSha1Final(&ctx, res); + if (memcmp(res, res1, 20) != 0) { + _psTrace("FAILED: Init-Update-Finish HMAC KAT mismatch\n"); + } + _psTrace("PASSED\n"); + return PS_SUCCESS; +} + +static int test_hmac_vector_num_calls; + +static int test_hmac_vector(int32 size, + const unsigned char *key, + size_t key_len, + const unsigned char *din, + size_t din_len, + const unsigned char *dout, + size_t dout_len, + int32 should_succeed) +{ + unsigned char key_out[128]; + unsigned char md_res[64]; + uint16_t key_length = 0; + int equals; + int32 rv = PS_SUCCESS; + psHmacSha1_t hmac_sha1_ctx; + psHmacSha256_t hmac_sha256_ctx; + psHmacSha384_t hmac_sha384_ctx; + + ++test_hmac_vector_num_calls; + + /* Copy key, if it is short as short ones are not normally copied. */ + if (key_len <= 128) { + memcpy(key_out, key, key_len); + key = key_out; + } + key_length = (uint16_t)key_len; + + psAssert(size == 20 || size == 28 || size == 32 || + size == 48); + + if (size == 20) { + rv = psHmacSha1((unsigned char *) key, key_length, + din, din_len, + md_res, + key_out, &key_length); + } else if (size == 32) { + rv = psHmacSha256((unsigned char *) key, key_length, + din, din_len, + md_res, + key_out, &key_length); + } else if (size == 48) { + rv = psHmacSha384((unsigned char *) key, key_length, + din, din_len, + md_res, + key_out, &key_length); + } + + equals = (rv == PS_SUCCESS && memcmp(dout, md_res, size) == 0); + if (equals != should_succeed) + { + _psTraceInt("FAILED: HMAC vector with %d bit key\n", + 8 * (int) key_len); + return PS_FAILURE; + } + + memset(md_res, 0, sizeof(md_res)); + + if (size == 20) { + rv = psHmacSha1Init(&hmac_sha1_ctx, key_out, key_length); + psHmacSha1Update(&hmac_sha1_ctx, din, din_len); + psHmacSha1Final(&hmac_sha1_ctx, md_res); + } else if (size == 32) { + rv = psHmacSha256Init(&hmac_sha256_ctx, key_out, key_length); + psHmacSha256Update(&hmac_sha256_ctx, din, din_len); + psHmacSha256Final(&hmac_sha256_ctx, md_res); + } else if (size == 48) { + rv = psHmacSha384Init(&hmac_sha384_ctx, key_out, key_length); + psHmacSha384Update(&hmac_sha384_ctx, din, din_len); + psHmacSha384Final(&hmac_sha384_ctx, md_res); + } + + equals = (rv == PS_SUCCESS && memcmp(dout, md_res, size) == 0); + if (equals != should_succeed) + { + _psTraceInt("FAILED: HMAC vector with %d bit key (multipart op)\n", + 8 * (int) key_len); + return PS_FAILURE; + } + +#ifdef USE_HMAC_TLS + /* Try single-call if suitable vector size. */ + + if (size == 20 || din_len < 13 || key_len > 64 || nohmactls == 1) + return 1; + + memset(md_res, 0, sizeof(md_res)); + if (din_len < 64) + { + int i; + unsigned char tmp[164]; + memcpy(tmp, din, din_len); + + for(i = 0; i < 100; i++) { + rv = psHmacSha2Tls(key, key_len, + (unsigned char *) din, 8, + (unsigned char *) din + 8, 5, + (unsigned char *) din + 13, din_len - 13, + din_len - 13 + i, md_res, size); + + if (rv != size) { + _psTraceInt( + "FAILED: Single-part HMAC KAT execution failure (rv=%d)\n", + (int)rv); + return PS_FAILURE; + } + + if (memcmp(dout, md_res, size) != 0) { + _psTrace("FAILED: Single-part HMAC KAT mismatch\n"); + return PS_FAILURE; + } + } + } + else + { + rv = psHmacSha2Tls(key, key_len, + (unsigned char *) din, 8, + (unsigned char *) din + 8, 5, + (unsigned char *) din + 13, din_len - 13, + din_len - 13, md_res, size); + } + + if (rv != size) { + _psTraceInt("FAILED: Single-part HMAC KAT execution failure (rv=%d)\n", + (int)rv); + return PS_FAILURE; + } + if (memcmp(dout, md_res, size) != 0) { + _psTrace("FAILED: Single-part HMAC KAT mismatch\n"); + return PS_FAILURE; + } +#endif /* USE_HMAC_TLS */ + + return 1; +} + +static int32 psHmacVectorTestsShared(int algo) +{ + int32 md; + int32 e = 1; + int32 res = PS_SUCCESS; + int32 count = 0; + + /* SHA-1 */ + + if (algo != 20) + goto sha2_224; + + md = algo; + + /* key size: 14 bytes */ + count += test_hmac_vector(md, + hmac_sha1_vector14_key, + sizeof(hmac_sha1_vector14_key), + hmac_sha1_vector14_in, + sizeof(hmac_sha1_vector14_in), + hmac_sha1_vector14_out, + sizeof(hmac_sha1_vector14_out), + e); + + /* key size: 16 bytes */ + count += test_hmac_vector(md, + hmac_sha1_vector16_key, + sizeof(hmac_sha1_vector16_key), + hmac_sha1_vector16_in, + sizeof(hmac_sha1_vector16_in), + hmac_sha1_vector16_out, + sizeof(hmac_sha1_vector16_out), + e); + + /* key size: 20 bytes */ + count += test_hmac_vector(md, + hmac_sha1_vector20_key, + sizeof(hmac_sha1_vector20_key), + hmac_sha1_vector20_in, + sizeof(hmac_sha1_vector20_in), + hmac_sha1_vector20_out, + sizeof(hmac_sha1_vector20_out), + e); + + /* key size: 24 bytes */ + count += test_hmac_vector(md, + hmac_sha1_vector24_key, + sizeof(hmac_sha1_vector24_key), + hmac_sha1_vector24_in, + sizeof(hmac_sha1_vector24_in), + hmac_sha1_vector24_out, + sizeof(hmac_sha1_vector24_out), + e); + + /* key size: 28 bytes */ + count += test_hmac_vector(md, + hmac_sha1_vector28_key, + sizeof(hmac_sha1_vector28_key), + hmac_sha1_vector28_in, + sizeof(hmac_sha1_vector28_in), + hmac_sha1_vector28_out, + sizeof(hmac_sha1_vector28_out), + e); + + /* key size: 32 bytes */ + count += test_hmac_vector(md, + hmac_sha1_vector32_key, + sizeof(hmac_sha1_vector32_key), + hmac_sha1_vector32_in, + sizeof(hmac_sha1_vector32_in), + hmac_sha1_vector32_out, + sizeof(hmac_sha1_vector32_out), + e); + + /* key size: 48 bytes */ + count += test_hmac_vector(md, + hmac_sha1_vector48_key, + sizeof(hmac_sha1_vector48_key), + hmac_sha1_vector48_in, + sizeof(hmac_sha1_vector48_in), + hmac_sha1_vector48_out, + sizeof(hmac_sha1_vector48_out), + e); + + /* key size: 64 bytes */ + count += test_hmac_vector(md, + hmac_sha1_vector64_key, + sizeof(hmac_sha1_vector64_key), + hmac_sha1_vector64_in, + sizeof(hmac_sha1_vector64_in), + hmac_sha1_vector64_out, + sizeof(hmac_sha1_vector64_out), + e); + + /* key size: 128 bytes */ + count += test_hmac_vector(md, + hmac_sha1_vector128_key, + sizeof(hmac_sha1_vector128_key), + hmac_sha1_vector128_in, + sizeof(hmac_sha1_vector128_in), + hmac_sha1_vector128_out, + sizeof(hmac_sha1_vector128_out), + e); + + /* key size: 256 bytes */ + count += test_hmac_vector(md, + hmac_sha1_vector256_key, + sizeof(hmac_sha1_vector256_key), + hmac_sha1_vector256_in, + sizeof(hmac_sha1_vector256_in), + hmac_sha1_vector256_out, + sizeof(hmac_sha1_vector256_out), + e); + + /* key size: 512 bytes */ + count += test_hmac_vector(md, + hmac_sha1_vector512_key, + sizeof(hmac_sha1_vector512_key), + hmac_sha1_vector512_in, + sizeof(hmac_sha1_vector512_in), + hmac_sha1_vector512_out, + sizeof(hmac_sha1_vector512_out), + e); + + /* key size: 1024 bytes */ + count += test_hmac_vector(md, + hmac_sha1_vector1024_key, + sizeof(hmac_sha1_vector1024_key), + hmac_sha1_vector1024_in, + sizeof(hmac_sha1_vector1024_in), + hmac_sha1_vector1024_out, + sizeof(hmac_sha1_vector1024_out), + e); + + /* multiblock test */ + count += test_hmac_vector(md, + hmac_vector1024_multiblock_key, + sizeof(hmac_vector1024_multiblock_key), + hmac_vector1024_multiblock_in, + sizeof(hmac_vector1024_multiblock_in), + hmac_sha1_vector1024_multiblock_out, + sizeof(hmac_sha1_vector1024_multiblock_out), + e); + + /* SHA-224 */ +sha2_224: + + if (algo != 28) + goto sha2_256; + + md = algo; + + /* key size: 14 bytes */ + count += test_hmac_vector(md, + hmac_sha224_vector14_key, + sizeof(hmac_sha224_vector14_key), + hmac_sha224_vector14_in, + sizeof(hmac_sha224_vector14_in), + hmac_sha224_vector14_out, + sizeof(hmac_sha224_vector14_out), + e); + + /* key size: 16 bytes */ + count += test_hmac_vector(md, + hmac_sha224_vector16_key, + sizeof(hmac_sha224_vector16_key), + hmac_sha224_vector16_in, + sizeof(hmac_sha224_vector16_in), + hmac_sha224_vector16_out, + sizeof(hmac_sha224_vector16_out), + e); + + /* key size: 20 bytes */ + count += test_hmac_vector(md, + hmac_sha224_vector20_key, + sizeof(hmac_sha224_vector20_key), + hmac_sha224_vector20_in, + sizeof(hmac_sha224_vector20_in), + hmac_sha224_vector20_out, + sizeof(hmac_sha224_vector20_out), + e); + + /* key size: 24 bytes */ + count += test_hmac_vector(md, + hmac_sha224_vector24_key, + sizeof(hmac_sha224_vector24_key), + hmac_sha224_vector24_in, + sizeof(hmac_sha224_vector24_in), + hmac_sha224_vector24_out, + sizeof(hmac_sha224_vector24_out), + e); + + /* key size: 28 bytes */ + count += test_hmac_vector(md, + hmac_sha224_vector28_key, + sizeof(hmac_sha224_vector28_key), + hmac_sha224_vector28_in, + sizeof(hmac_sha224_vector28_in), + hmac_sha224_vector28_out, + sizeof(hmac_sha224_vector28_out), + e); + + /* key size: 32 bytes */ + count += test_hmac_vector(md, + hmac_sha224_vector32_key, + sizeof(hmac_sha224_vector32_key), + hmac_sha224_vector32_in, + sizeof(hmac_sha224_vector32_in), + hmac_sha224_vector32_out, + sizeof(hmac_sha224_vector32_out), + e); + + /* key size: 48 bytes */ + count += test_hmac_vector(md, + hmac_sha224_vector48_key, + sizeof(hmac_sha224_vector48_key), + hmac_sha224_vector48_in, + sizeof(hmac_sha224_vector48_in), + hmac_sha224_vector48_out, + sizeof(hmac_sha224_vector48_out), + e); + + /* key size: 64 bytes */ + count += test_hmac_vector(md, + hmac_sha224_vector64_key, + sizeof(hmac_sha224_vector64_key), + hmac_sha224_vector64_in, + sizeof(hmac_sha224_vector64_in), + hmac_sha224_vector64_out, + sizeof(hmac_sha224_vector64_out), + e); + + /* key size: 128 bytes */ + count += test_hmac_vector(md, + hmac_sha224_vector128_key, + sizeof(hmac_sha224_vector128_key), + hmac_sha224_vector128_in, + sizeof(hmac_sha224_vector128_in), + hmac_sha224_vector128_out, + sizeof(hmac_sha224_vector128_out), + e); + + /* key size: 256 bytes */ + count += test_hmac_vector(md, + hmac_sha224_vector256_key, + sizeof(hmac_sha224_vector256_key), + hmac_sha224_vector256_in, + sizeof(hmac_sha224_vector256_in), + hmac_sha224_vector256_out, + sizeof(hmac_sha224_vector256_out), + e); + + /* key size: 512 bytes */ + count += test_hmac_vector(md, + hmac_sha224_vector512_key, + sizeof(hmac_sha224_vector512_key), + hmac_sha224_vector512_in, + sizeof(hmac_sha224_vector512_in), + hmac_sha224_vector512_out, + sizeof(hmac_sha224_vector512_out), + e); + + /* key size: 1024 bytes */ + count += test_hmac_vector(md, + hmac_sha224_vector1024_key, + sizeof(hmac_sha224_vector1024_key), + hmac_sha224_vector1024_in, + sizeof(hmac_sha224_vector1024_in), + hmac_sha224_vector1024_out, + sizeof(hmac_sha224_vector1024_out), + e); + + /* multiblock test */ + count += test_hmac_vector(md, + hmac_vector1024_multiblock_key, + sizeof(hmac_vector1024_multiblock_key), + hmac_vector1024_multiblock_in, + sizeof(hmac_vector1024_multiblock_in), + hmac_sha224_vector1024_multiblock_out, + sizeof(hmac_sha224_vector1024_multiblock_out), + e); + + /* SHA-256 */ +sha2_256: + + if (algo != 32) + goto sha2_384; + + md = algo; + + /* key size: 14 bytes */ + count += test_hmac_vector(md, + hmac_sha256_vector14_key, + sizeof(hmac_sha256_vector14_key), + hmac_sha256_vector14_in, + sizeof(hmac_sha256_vector14_in), + hmac_sha256_vector14_out, + sizeof(hmac_sha256_vector14_out), + e); + + /* key size: 16 bytes */ + count += test_hmac_vector(md, + hmac_sha256_vector16_key, + sizeof(hmac_sha256_vector16_key), + hmac_sha256_vector16_in, + sizeof(hmac_sha256_vector16_in), + hmac_sha256_vector16_out, + sizeof(hmac_sha256_vector16_out), + e); + + /* key size: 20 bytes */ + count += test_hmac_vector(md, + hmac_sha256_vector20_key, + sizeof(hmac_sha256_vector20_key), + hmac_sha256_vector20_in, + sizeof(hmac_sha256_vector20_in), + hmac_sha256_vector20_out, + sizeof(hmac_sha256_vector20_out), + e); + + /* key size: 24 bytes */ + count += test_hmac_vector(md, + hmac_sha256_vector24_key, + sizeof(hmac_sha256_vector24_key), + hmac_sha256_vector24_in, + sizeof(hmac_sha256_vector24_in), + hmac_sha256_vector24_out, + sizeof(hmac_sha256_vector24_out), + e); + + /* key size: 28 bytes */ + count += test_hmac_vector(md, + hmac_sha256_vector28_key, + sizeof(hmac_sha256_vector28_key), + hmac_sha256_vector28_in, + sizeof(hmac_sha256_vector28_in), + hmac_sha256_vector28_out, + sizeof(hmac_sha256_vector28_out), + e); + + + /* key size: 32 bytes */ + count += test_hmac_vector(md, + hmac_sha256_vector32_key, + sizeof(hmac_sha256_vector32_key), + hmac_sha256_vector32_in, + sizeof(hmac_sha256_vector32_in), + hmac_sha256_vector32_out, + sizeof(hmac_sha256_vector32_out), + e); + + /* key size: 48 bytes */ + count += test_hmac_vector(md, + hmac_sha256_vector48_key, + sizeof(hmac_sha256_vector48_key), + hmac_sha256_vector48_in, + sizeof(hmac_sha256_vector48_in), + hmac_sha256_vector48_out, + sizeof(hmac_sha256_vector48_out), + e); + + /* key size: 64 bytes */ + count += test_hmac_vector(md, + hmac_sha256_vector64_key, + sizeof(hmac_sha256_vector64_key), + hmac_sha256_vector64_in, + sizeof(hmac_sha256_vector64_in), + hmac_sha256_vector64_out, + sizeof(hmac_sha256_vector64_out), + e); + + /* key size: 128 bytes */ + count += test_hmac_vector(md, + hmac_sha256_vector128_key, + sizeof(hmac_sha256_vector128_key), + hmac_sha256_vector128_in, + sizeof(hmac_sha256_vector128_in), + hmac_sha256_vector128_out, + sizeof(hmac_sha256_vector128_out), + e); + + /* key size: 256 bytes */ + count += test_hmac_vector(md, + hmac_sha256_vector256_key, + sizeof(hmac_sha256_vector256_key), + hmac_sha256_vector256_in, + sizeof(hmac_sha256_vector256_in), + hmac_sha256_vector256_out, + sizeof(hmac_sha256_vector256_out), + e); + + /* key size: 512 bytes */ + count += test_hmac_vector(md, + hmac_sha256_vector512_key, + sizeof(hmac_sha256_vector512_key), + hmac_sha256_vector512_in, + sizeof(hmac_sha256_vector512_in), + hmac_sha256_vector512_out, + sizeof(hmac_sha256_vector512_out), + e); + + /* key size: 1024 bytes */ + count += test_hmac_vector(md, + hmac_sha256_vector1024_key, + sizeof(hmac_sha256_vector1024_key), + hmac_sha256_vector1024_in, + sizeof(hmac_sha256_vector1024_in), + hmac_sha256_vector1024_out, + sizeof(hmac_sha256_vector1024_out), + e); + + /* multiblock test */ + count += test_hmac_vector(md, + hmac_vector1024_multiblock_key, + sizeof(hmac_vector1024_multiblock_key), + hmac_vector1024_multiblock_in, + sizeof(hmac_vector1024_multiblock_in), + hmac_sha256_vector1024_multiblock_out, + sizeof(hmac_sha256_vector1024_multiblock_out), + e); + + /* SHA-384 */ +sha2_384: + + if (algo != 48) + goto sha2_512; + + md = algo; + + /* key size: 14 bytes */ + count += test_hmac_vector(md, + hmac_sha384_vector14_key, + sizeof(hmac_sha384_vector14_key), + hmac_sha384_vector14_in, + sizeof(hmac_sha384_vector14_in), + hmac_sha384_vector14_out, + sizeof(hmac_sha384_vector14_out), + e); + + /* key size: 16 bytes */ + count += test_hmac_vector(md, + hmac_sha384_vector16_key, + sizeof(hmac_sha384_vector16_key), + hmac_sha384_vector16_in, + sizeof(hmac_sha384_vector16_in), + hmac_sha384_vector16_out, + sizeof(hmac_sha384_vector16_out), + e); + + /* key size: 20 bytes */ + count += test_hmac_vector(md, + hmac_sha384_vector20_key, + sizeof(hmac_sha384_vector20_key), + hmac_sha384_vector20_in, + sizeof(hmac_sha384_vector20_in), + hmac_sha384_vector20_out, + sizeof(hmac_sha384_vector20_out), + e); + + /* key size: 24 bytes */ + count += test_hmac_vector(md, + hmac_sha384_vector24_key, + sizeof(hmac_sha384_vector24_key), + hmac_sha384_vector24_in, + sizeof(hmac_sha384_vector24_in), + hmac_sha384_vector24_out, + sizeof(hmac_sha384_vector24_out), + e); + + /* key size: 28 bytes */ + count += test_hmac_vector(md, + hmac_sha384_vector28_key, + sizeof(hmac_sha384_vector28_key), + hmac_sha384_vector28_in, + sizeof(hmac_sha384_vector28_in), + hmac_sha384_vector28_out, + sizeof(hmac_sha384_vector28_out), + e); + + /* key size: 32 bytes */ + count += test_hmac_vector(md, + hmac_sha384_vector32_key, + sizeof(hmac_sha384_vector32_key), + hmac_sha384_vector32_in, + sizeof(hmac_sha384_vector32_in), + hmac_sha384_vector32_out, + sizeof(hmac_sha384_vector32_out), + e); + + /* key size: 48 bytes */ + count += test_hmac_vector(md, + hmac_sha384_vector48_key, + sizeof(hmac_sha384_vector48_key), + hmac_sha384_vector48_in, + sizeof(hmac_sha384_vector48_in), + hmac_sha384_vector48_out, + sizeof(hmac_sha384_vector48_out), + e); + + /* key size: 64 bytes */ + count += test_hmac_vector(md, + hmac_sha384_vector64_key, + sizeof(hmac_sha384_vector64_key), + hmac_sha384_vector64_in, + sizeof(hmac_sha384_vector64_in), + hmac_sha384_vector64_out, + sizeof(hmac_sha384_vector64_out), + e); + + /* key size: 128 bytes */ + count += test_hmac_vector(md, + hmac_sha384_vector128_key, + sizeof(hmac_sha384_vector128_key), + hmac_sha384_vector128_in, + sizeof(hmac_sha384_vector128_in), + hmac_sha384_vector128_out, + sizeof(hmac_sha384_vector128_out), + e); + + /* key size: 256 bytes */ + count += test_hmac_vector(md, + hmac_sha384_vector256_key, + sizeof(hmac_sha384_vector256_key), + hmac_sha384_vector256_in, + sizeof(hmac_sha384_vector256_in), + hmac_sha384_vector256_out, + sizeof(hmac_sha384_vector256_out), + e); + + /* key size: 512 bytes */ + count += test_hmac_vector(md, + hmac_sha384_vector512_key, + sizeof(hmac_sha384_vector512_key), + hmac_sha384_vector512_in, + sizeof(hmac_sha384_vector512_in), + hmac_sha384_vector512_out, + sizeof(hmac_sha384_vector512_out), + e); + + /* key size: 1024 bytes */ + count += test_hmac_vector(md, + hmac_sha384_vector1024_key, + sizeof(hmac_sha384_vector1024_key), + hmac_sha384_vector1024_in, + sizeof(hmac_sha384_vector1024_in), + hmac_sha384_vector1024_out, + sizeof(hmac_sha384_vector1024_out), + e); + + /* multiblock test */ + count += test_hmac_vector(md, + hmac_vector1024_multiblock_key, + sizeof(hmac_vector1024_multiblock_key), + hmac_vector1024_multiblock_in, + sizeof(hmac_vector1024_multiblock_in), + hmac_sha384_vector1024_multiblock_out, + sizeof(hmac_sha384_vector1024_multiblock_out), + e); + + /* SHA-512 */ +sha2_512: + + if (algo != 64) + goto sha_finish; + + md = algo; + + /* key size: 14 bytes */ + count += test_hmac_vector(md, + hmac_sha512_vector14_key, + sizeof(hmac_sha512_vector14_key), + hmac_sha512_vector14_in, + sizeof(hmac_sha512_vector14_in), + hmac_sha512_vector14_out, + sizeof(hmac_sha512_vector14_out), + e); + + /* key size: 16 bytes */ + count += test_hmac_vector(md, + hmac_sha512_vector16_key, + sizeof(hmac_sha512_vector16_key), + hmac_sha512_vector16_in, + sizeof(hmac_sha512_vector16_in), + hmac_sha512_vector16_out, + sizeof(hmac_sha512_vector16_out), + e); + + /* key size: 20 bytes */ + count += test_hmac_vector(md, + hmac_sha512_vector20_key, + sizeof(hmac_sha512_vector20_key), + hmac_sha512_vector20_in, + sizeof(hmac_sha512_vector20_in), + hmac_sha512_vector20_out, + sizeof(hmac_sha512_vector20_out), + e); + + /* key size: 24 bytes */ + count += test_hmac_vector(md, + hmac_sha512_vector24_key, + sizeof(hmac_sha512_vector24_key), + hmac_sha512_vector24_in, + sizeof(hmac_sha512_vector24_in), + hmac_sha512_vector24_out, + sizeof(hmac_sha512_vector24_out), + e); + + /* key size: 28 bytes */ + count += test_hmac_vector(md, + hmac_sha512_vector28_key, + sizeof(hmac_sha512_vector28_key), + hmac_sha512_vector28_in, + sizeof(hmac_sha512_vector28_in), + hmac_sha512_vector28_out, + sizeof(hmac_sha512_vector28_out), + e); + + /* key size: 32 bytes */ + count += test_hmac_vector(md, + hmac_sha512_vector32_key, + sizeof(hmac_sha512_vector32_key), + hmac_sha512_vector32_in, + sizeof(hmac_sha512_vector32_in), + hmac_sha512_vector32_out, + sizeof(hmac_sha512_vector32_out), + e); + + /* key size: 48 bytes */ + count += test_hmac_vector(md, + hmac_sha512_vector48_key, + sizeof(hmac_sha512_vector48_key), + hmac_sha512_vector48_in, + sizeof(hmac_sha512_vector48_in), + hmac_sha512_vector48_out, + sizeof(hmac_sha512_vector48_out), + e); + + /* key size: 64 bytes */ + count += test_hmac_vector(md, + hmac_sha512_vector64_key, + sizeof(hmac_sha512_vector64_key), + hmac_sha512_vector64_in, + sizeof(hmac_sha512_vector64_in), + hmac_sha512_vector64_out, + sizeof(hmac_sha512_vector64_out), + e); + + /* key size: 128 bytes */ + count += test_hmac_vector(md, + hmac_sha512_vector128_key, + sizeof(hmac_sha512_vector128_key), + hmac_sha512_vector128_in, + sizeof(hmac_sha512_vector128_in), + hmac_sha512_vector128_out, + sizeof(hmac_sha512_vector128_out), + e); + + /* key size: 256 bytes */ + count += test_hmac_vector(md, + hmac_sha512_vector256_key, + sizeof(hmac_sha512_vector256_key), + hmac_sha512_vector256_in, + sizeof(hmac_sha512_vector256_in), + hmac_sha512_vector256_out, + sizeof(hmac_sha512_vector256_out), + e); + + /* key size: 512 bytes */ + count += test_hmac_vector(md, + hmac_sha512_vector512_key, + sizeof(hmac_sha512_vector512_key), + hmac_sha512_vector512_in, + sizeof(hmac_sha512_vector512_in), + hmac_sha512_vector512_out, + sizeof(hmac_sha512_vector512_out), + e); + + /* key size: 1024 bytes */ + count += test_hmac_vector(md, + hmac_sha512_vector1024_key, + sizeof(hmac_sha512_vector1024_key), + hmac_sha512_vector1024_in, + sizeof(hmac_sha512_vector1024_in), + hmac_sha512_vector1024_out, + sizeof(hmac_sha512_vector1024_out), + e); + + /* multiblock test */ + count += test_hmac_vector(md, + hmac_vector1024_multiblock_key, + sizeof(hmac_vector1024_multiblock_key), + hmac_vector1024_multiblock_in, + sizeof(hmac_vector1024_multiblock_in), + hmac_sha512_vector1024_multiblock_out, + sizeof(hmac_sha512_vector1024_multiblock_out), + e); + +sha_finish: + if (count != test_hmac_vector_num_calls) { + res = PS_FAILURE; + _psTrace("FAILED: some of the tests failed.\n"); + } else { + _psTraceInt("PASSED (%d vectors)\n", count); + } + test_hmac_vector_num_calls = 0; + return res; +} + +static int32 psHmacVectorTestsSHA1(void) +{ + return psHmacVectorTestsShared(20); +} + +static int32 psHmacVectorTestsSHA256(void) +{ + return psHmacVectorTestsShared(32); +} + +static int32 psHmacVectorTestsSHA384(void) +{ + return psHmacVectorTestsShared(48); +} + + +static int32 psHmacVectorTestsSimultaneous(void) +{ + psHmacSha1_t ctx1; + psHmacSha1_t ctx2; + psHmacSha1_t ctx3; + int32 rv1; + int32 rv2; + int32 rv3; + unsigned char md1[20]; + unsigned char md2[20]; + unsigned char md3[20]; + + rv1 = psHmacSha1Init(&ctx1, (unsigned char *) hmac_sha1_vector14_key, + sizeof(hmac_sha1_vector14_key)); + rv2 = psHmacSha1Init(&ctx2, (unsigned char *) hmac_sha1_vector16_key, + sizeof(hmac_sha1_vector16_key)); + rv3 = psHmacSha1Init(&ctx3, (unsigned char *) hmac_sha1_vector20_key, + sizeof(hmac_sha1_vector20_key)); + + if (rv1 != PS_SUCCESS) { + _psTrace("FAILED (hmac_sha1_vector14)\n"); + } + if (rv2 != PS_SUCCESS) { + _psTrace("FAILED (hmac_sha1_vector16)\n"); + } + if (rv3 != PS_SUCCESS) { + _psTrace("FAILED (hmac_sha1_vector20)\n"); + } + + psHmacSha1Update(&ctx1, hmac_sha1_vector14_in, + sizeof(hmac_sha1_vector14_in)); + psHmacSha1Update(&ctx2, hmac_sha1_vector16_in, + sizeof(hmac_sha1_vector16_in)); + psHmacSha1Update(&ctx3, hmac_sha1_vector20_in, + sizeof(hmac_sha1_vector20_in)); + + psHmacSha1Final(&ctx1, md1); + psHmacSha1Final(&ctx2, md2); + psHmacSha1Final(&ctx3, md3); + + if (memcmp(md1, hmac_sha1_vector14_out, + sizeof(hmac_sha1_vector14_out)) != 0) { + _psTrace("FAILED (hmac_sha1_vector14)\n"); + return PS_FAILURE; + } + if (memcmp(md2, hmac_sha1_vector16_out, + sizeof(hmac_sha1_vector16_out)) != 0) { + _psTrace("FAILED (hmac_sha1_vector16)\n"); + return PS_FAILURE; + } + if (memcmp(md3, hmac_sha1_vector20_out, + sizeof(hmac_sha1_vector20_out)) != 0) { + _psTrace("FAILED (hmac_sha1_vector20)\n"); + return PS_FAILURE; + } + + _psTrace("PASSED\n"); + return PS_SUCCESS; +} + + +static int32 psHmacVectorTests(void) +{ + int32 res; + + res = psHmacVectorTestSimple(); + + _psTraceInt(" SHA-1 known vector test %d... ", 2); + res |= psHmacVectorTestsSHA1(); + + _psTraceInt(" SHA-256 known vector test %d... ", 1); + res |= psHmacVectorTestsSHA256(); + + _psTraceInt(" SHA-384 known vector test %d... ", 1); + res |= psHmacVectorTestsSHA384(); + + _psTrace(" Simultaneous hmac contexts... "); + res |= psHmacVectorTestsSimultaneous(); + + return res; +} + +#endif /* USE_HMAC */ + + +/******************************************************************************/ + +#ifdef USE_ECC + +#include "../../testkeys/EC/256_EC.h" +#include "../../testkeys/EC/256_EC_KEY.h" + +static int32_t ecdh_kat(unsigned char *alice_priv, + size_t alice_priv_len, + unsigned char *bob_pub, + size_t bob_pub_len, + unsigned char *expected_secret, + size_t expected_secret_len, + int curve_id) +{ + psPool_t *pool = NULL; + psEccKey_t privkey = PS_ECC_STATIC_INIT; + psEccKey_t pubkey_imported = PS_ECC_STATIC_INIT; + const psEccCurve_t *curve; + unsigned char got_secret[128] = {0}; + int32_t rc; + uint16_t secret_len; + + if (getEccParamById(curve_id, &curve) < 0) { + return PS_FAIL; + } + + rc = psEccParsePrivKey(pool, alice_priv, alice_priv_len, + &privkey, curve); + + if (rc != PS_SUCCESS) { + _psTrace("psEccParsePrivKey failed\n"); + rc = PS_FAIL; + goto L_FAIL; + } + + rc = psEccX963ImportKey(pool, bob_pub, bob_pub_len, + &pubkey_imported, curve); + + if (rc != PS_SUCCESS) { + _psTrace("psEccX963ImportKey failed\n"); + rc = PS_FAIL; + goto L_FAIL; + } + + secret_len = sizeof(got_secret); + rc = psEccGenSharedSecret(pool, &privkey, &pubkey_imported, + got_secret, &secret_len, NULL); + + if (rc != PS_SUCCESS) { + _psTrace("psEccGenSharedSecret failed\n"); + rc = PS_FAIL; + goto L_FAIL; + } + + if (secret_len != expected_secret_len) { + _psTrace("Unexpected shared secret size\n"); + rc = PS_FAIL; + goto L_FAIL; + } + + if (memcmp(got_secret, expected_secret, secret_len)) { + _psTrace("KAT failed\n"); + rc = PS_FAIL; + goto L_FAIL; + } + + rc = PS_SUCCESS; + _psTrace(" PASSED\n"); + + +L_FAIL: + psEccClearKey(&privkey); + psEccClearKey(&pubkey_imported); + + return rc; +} + +static int32_t ecdh_p256_kat(void) +{ + int32_t rc; + +/* A prime256v1 keypair and an ECDH shared secret generated with it. */ + unsigned char alice_priv[] = + { + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x2a, 0x50, 0x32, 0x9a, 0xa5, + 0x7e, 0x0d, 0xc0, 0x1f, 0xf9, 0xb1, 0xeb, 0xe4, 0x01, 0x4c, 0xc2, 0x87, + 0x78, 0x91, 0xe3, 0xb6, 0x53, 0x59, 0x77, 0x3c, 0x0e, 0x3c, 0x15, 0xa3, + 0xb5, 0x82, 0x96, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x42, 0x37, 0x6d, + 0xf6, 0x3e, 0x06, 0x70, 0x7f, 0xa2, 0x36, 0x8d, 0x37, 0x90, 0x92, 0x93, + 0xe5, 0xc3, 0x70, 0x94, 0x00, 0xd1, 0x09, 0xb2, 0xb5, 0x70, 0xa1, 0x82, + 0xfe, 0xa6, 0xb0, 0xfc, 0xfa, 0x18, 0xea, 0x5e, 0xff, 0x87, 0x0f, 0xbf, + 0xd5, 0xd6, 0x8b, 0x88, 0xb9, 0x1a, 0xcf, 0xf9, 0x53, 0xd2, 0xb0, 0x5c, + 0x7b, 0x2f, 0x71, 0xf5, 0x95, 0xb0, 0xa1, 0x3d, 0xd6, 0xa5, 0x59, 0x14, + 0x56 + }; + unsigned char bob_pub[] = + { + 0x04, 0x32, 0xee, 0xb1, 0x56, 0xf9, 0xb1, 0xc9, 0x80, 0x66, 0xa5, 0x7d, + 0x94, 0xff, 0xde, 0x61, 0xbd, 0x3f, 0x2d, 0xf0, 0x1f, 0xc0, 0xb5, 0x1e, + 0xc1, 0x05, 0x5b, 0x2b, 0xf9, 0x2a, 0x39, 0x6a, 0x94, 0x82, 0x6b, 0x77, + 0xd4, 0xb9, 0x07, 0x02, 0xdb, 0x73, 0x6f, 0x95, 0xe9, 0xc3, 0xbd, 0xd5, + 0x25, 0x5f, 0xea, 0x0b, 0xc4, 0xa6, 0x60, 0x83, 0x5c, 0xe4, 0x3a, 0xd9, + 0x08, 0xf9, 0x9b, 0x09, 0x8c + }; + unsigned char secret[] = + { + 0xb1, 0xe2, 0x6c, 0x88, 0xe7, 0x06, 0x12, 0x1e, 0x92, 0x0f, 0xc2, 0x89, + 0x35, 0x8d, 0x37, 0x36, 0x20, 0xfa, 0x81, 0x91, 0x53, 0x5d, 0x4c, 0xa1, + 0x71, 0x1f, 0x8c, 0x90, 0xa4, 0x7f, 0x8b, 0xf4 + }; + + _psTrace(" P-256 ECDH known-answer test..."); + rc = ecdh_kat(alice_priv, sizeof(alice_priv), + bob_pub, sizeof(bob_pub), + secret, sizeof(secret), + IANA_SECP256R1); + if (rc == PS_FAIL) + _psTrace("P-256 ECDH known-answer test failed\n"); + return rc; +} + +static int32_t ecdh_p384_kat(void) +{ + int32_t rc; +/* A secp384r1 keypair and an ECDH shared secret generated with it. */ + unsigned char alice_priv[] = + { + 0x30, 0x81, 0xa4, 0x02, 0x01, 0x01, 0x04, 0x30, 0xfc, 0x80, 0x44, 0xc5, + 0x86, 0xd4, 0x6a, 0x93, 0xa5, 0xd1, 0x33, 0xe0, 0x59, 0xe2, 0x5c, 0xca, + 0x04, 0x89, 0xc6, 0x0e, 0x45, 0xcb, 0x5a, 0x3b, 0x22, 0x07, 0x6d, 0xcc, + 0x1b, 0x49, 0xba, 0x80, 0xe9, 0x7f, 0x48, 0xb7, 0x7c, 0x9f, 0x49, 0x17, + 0xa0, 0x41, 0x81, 0x5e, 0xc0, 0x75, 0x2a, 0x9b, 0xa0, 0x07, 0x06, 0x05, + 0x2b, 0x81, 0x04, 0x00, 0x22, 0xa1, 0x64, 0x03, 0x62, 0x00, 0x04, 0x6c, + 0xc2, 0x05, 0x72, 0x70, 0x4b, 0x07, 0x2f, 0x36, 0x7c, 0x77, 0xa3, 0x04, + 0xbe, 0x18, 0x56, 0x3f, 0xc9, 0xfa, 0x50, 0xe9, 0x2e, 0x0a, 0x24, 0x74, + 0xa1, 0x0d, 0x48, 0x92, 0x71, 0x62, 0xb4, 0xd5, 0x69, 0xad, 0x8c, 0x31, + 0xf0, 0xfe, 0xa5, 0x00, 0x6c, 0x1e, 0x34, 0x58, 0x1a, 0xd3, 0x83, 0x5a, + 0x79, 0x81, 0xc9, 0xb5, 0x2b, 0x0f, 0x72, 0x6b, 0x5d, 0x20, 0x7b, 0xba, + 0xd3, 0x4c, 0x93, 0xbb, 0xe4, 0x58, 0x46, 0x06, 0x92, 0xab, 0x5d, 0x30, + 0xff, 0x03, 0xf6, 0xfe, 0x1c, 0x87, 0xfb, 0x5a, 0x00, 0xa5, 0x7e, 0x5e, + 0xbd, 0x53, 0x02, 0x38, 0xe7, 0xf8, 0x53, 0x58, 0x19, 0x77, 0x2c + }; + unsigned char bob_pub[] = + { + 0x04, 0xba, 0x84, 0x0b, 0xd0, 0xab, 0xfd, 0x2f, 0x4c, 0x49, 0x19, 0x8c, + 0xbf, 0x97, 0x55, 0x2d, 0xbc, 0x2d, 0x2a, 0xf0, 0x8b, 0x8f, 0xfc, 0x2b, + 0x85, 0xdb, 0x02, 0x83, 0x9b, 0x41, 0xdd, 0x91, 0xda, 0xad, 0x1e, 0x43, + 0x81, 0x18, 0xc9, 0xf7, 0xc2, 0x5a, 0x06, 0x05, 0xc5, 0x9b, 0x72, 0xf8, + 0x5c, 0xf7, 0x25, 0xb3, 0x50, 0x98, 0x5e, 0x31, 0xa0, 0x24, 0x0f, 0xc4, + 0x9a, 0x2f, 0xc9, 0x6d, 0x4e, 0x2a, 0xab, 0xdb, 0x9e, 0xa1, 0x73, 0x36, + 0x5b, 0x3f, 0x39, 0xcf, 0x5f, 0x45, 0x0f, 0xa5, 0xc8, 0xfc, 0x40, 0x57, + 0xaf, 0x96, 0x0d, 0x25, 0xd6, 0x7e, 0x0b, 0xe1, 0x6a, 0x4d, 0x09, 0x08, + 0xca + }; + unsigned char secret[] = + { + 0x1b, 0x74, 0x01, 0x47, 0x86, 0x9a, 0x79, 0x25, 0x43, 0x2a, 0x39, 0x3f, + 0xe5, 0x8c, 0x7c, 0xb6, 0x9b, 0xd3, 0x19, 0xb0, 0x3d, 0xc2, 0xa2, 0xb0, + 0x6a, 0xca, 0x33, 0x66, 0x82, 0xb2, 0x47, 0x84, 0x1e, 0xe8, 0x71, 0xeb, + 0x68, 0x88, 0xfa, 0xfd, 0x08, 0x52, 0xe3, 0x2e, 0x04, 0x59, 0xe7, 0xe7 + }; + + _psTrace(" P-384 ECDH known-answer test..."); + + rc = ecdh_kat(alice_priv, sizeof(alice_priv), + bob_pub, sizeof(bob_pub), + secret, sizeof(secret), + IANA_SECP384R1); + if (rc == PS_FAIL) { + _psTrace("P-384 ECDH known-answer test failed\n"); + return rc; + } + + return PS_SUCCESS; +} + +#ifdef USE_SECP521R1 +static int32_t ecdh_p521_kat(void) +{ + int32_t rc; +/* A secp521r1 keypair and an ECDH shared secret generated with it. */ + unsigned char alice_priv[] = + { + 0x30, 0x81, 0xdc, 0x02, 0x01, 0x01, 0x04, 0x42, 0x00, 0x0e, 0x21, 0x99, + 0x99, 0x28, 0xe5, 0x42, 0x2f, 0x6b, 0xbc, 0x7a, 0xb5, 0x50, 0xe4, 0x6a, + 0xbd, 0xdc, 0x5e, 0x90, 0xb0, 0x5c, 0xd3, 0x19, 0x9b, 0xee, 0xc4, 0xab, + 0x66, 0x5a, 0x02, 0xba, 0x65, 0xce, 0xf6, 0xb1, 0x32, 0xa9, 0xca, 0x1c, + 0x42, 0x02, 0x99, 0xda, 0xf7, 0xae, 0x3c, 0x12, 0x14, 0x59, 0x73, 0xf1, + 0x28, 0xef, 0x17, 0xd4, 0xc5, 0xd9, 0xa9, 0xec, 0x77, 0x74, 0x3c, 0x0a, + 0x3a, 0x46, 0xa0, 0x07, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23, 0xa1, + 0x81, 0x89, 0x03, 0x81, 0x86, 0x00, 0x04, 0x01, 0x1a, 0x21, 0x9b, 0x8c, + 0x59, 0x86, 0x25, 0x5f, 0xb3, 0x52, 0xd3, 0xa6, 0xaf, 0x06, 0x06, 0x1e, + 0x3c, 0x89, 0x0d, 0x5d, 0xf4, 0xb9, 0x92, 0xd5, 0x1b, 0xe4, 0xa5, 0x20, + 0x9d, 0xd6, 0x3d, 0x01, 0x80, 0xee, 0x4b, 0xd4, 0xea, 0x0a, 0xe6, 0xd3, + 0x4e, 0xfa, 0xe9, 0x7f, 0xf9, 0xf9, 0x94, 0x65, 0x0e, 0x85, 0x54, 0xdd, + 0xc7, 0xfe, 0xae, 0x97, 0xd1, 0x6a, 0xd3, 0x7b, 0x90, 0x1f, 0x50, 0xcc, + 0x6a, 0x01, 0x88, 0x18, 0x09, 0x27, 0x83, 0x70, 0x28, 0xe4, 0x05, 0x88, + 0x03, 0xe9, 0x1b, 0x0b, 0x93, 0x5a, 0x3b, 0xba, 0x2d, 0x91, 0xff, 0x20, + 0x6f, 0xb4, 0x86, 0x91, 0x30, 0xdb, 0xf0, 0xa3, 0x08, 0xb0, 0x23, 0x61, + 0xa8, 0x80, 0x91, 0x53, 0x64, 0x93, 0x9a, 0x3c, 0xca, 0x50, 0x18, 0x04, + 0xb4, 0x9c, 0x78, 0xae, 0x48, 0xd6, 0x01, 0x51, 0x30, 0xd2, 0xcd, 0x7c, + 0x59, 0xdc, 0xfe, 0x20, 0x7c, 0xa7, 0x88 + }; + unsigned char bob_pub[] = + { + 0x04, 0x01, 0xb4, 0xb3, 0x6a, 0x53, 0x35, 0x45, 0xbc, 0x72, 0xb7, 0x1c, + 0x34, 0x72, 0xb2, 0x24, 0x84, 0xb7, 0xe7, 0x1e, 0x67, 0x86, 0x8c, 0x2d, + 0xf8, 0x51, 0xb7, 0xe4, 0x06, 0xa5, 0x94, 0x8a, 0xfe, 0x27, 0xea, 0x82, + 0xd9, 0x14, 0x08, 0x73, 0xd7, 0xae, 0x16, 0xbf, 0x06, 0x4f, 0x3c, 0xf1, + 0x74, 0x60, 0x5e, 0x6e, 0xa2, 0xcc, 0x68, 0x67, 0xc0, 0x48, 0x50, 0xd2, + 0xfe, 0x24, 0x7d, 0xe4, 0x8e, 0x4b, 0xb6, 0x00, 0xce, 0x3a, 0xad, 0xdb, + 0x73, 0xb0, 0x39, 0x20, 0x6b, 0x19, 0x24, 0x33, 0x3f, 0x7a, 0xd8, 0xb5, + 0x59, 0x0a, 0x3a, 0x59, 0xc4, 0x49, 0xa3, 0x90, 0x6d, 0xc2, 0xa0, 0xf8, + 0x0d, 0xee, 0xd5, 0x00, 0x6b, 0x13, 0xb1, 0x08, 0x83, 0x7b, 0x3b, 0xda, + 0x16, 0x0f, 0x6b, 0x4c, 0x5e, 0xdb, 0xda, 0x94, 0xc7, 0x6c, 0xbc, 0xa3, + 0x2e, 0x13, 0xe2, 0xcf, 0x6a, 0xa2, 0x57, 0x46, 0x10, 0xd2, 0xab, 0x94, + 0x80 + }; + unsigned char secret[] = + { + 0x00, 0x26, 0x96, 0xe5, 0x2b, 0xe4, 0x56, 0xac, 0x90, 0x0e, 0x5f, 0x9e, + 0x49, 0xf2, 0xd0, 0x19, 0x48, 0xa2, 0xf1, 0x2e, 0xe8, 0x1a, 0x47, 0x5c, + 0x30, 0xc7, 0x83, 0x59, 0xd4, 0x60, 0x55, 0x28, 0x95, 0x99, 0xa0, 0x65, + 0xc1, 0xeb, 0x8d, 0x92, 0x75, 0x63, 0x55, 0xa7, 0x4d, 0xe8, 0xb1, 0xe5, + 0x96, 0x50, 0x24, 0x45, 0x8f, 0x3d, 0xd2, 0x69, 0xb7, 0xca, 0xd3, 0x15, + 0x5a, 0xf6, 0x5c, 0x20, 0x5f, 0x49 + }; + + _psTrace(" P-521 ECDH known-answer test..."); + + rc = ecdh_kat(alice_priv, sizeof(alice_priv), + bob_pub, sizeof(bob_pub), + secret, sizeof(secret), + IANA_SECP521R1); + if (rc == PS_FAIL) { + _psTrace("P-521 ECDH known-answer test failed\n"); + return rc; + } + + return PS_SUCCESS; +} +#endif /* USE_SECP521R1 */ + +static int32_t psEccPairwiseTest(void) +{ + psPool_t *pool = NULL; + psEccKey_t k1 = PS_ECC_STATIC_INIT; + psEccKey_t k1_imported = PS_ECC_STATIC_INIT; + psEccKey_t k2 = PS_ECC_STATIC_INIT; + psEccKey_t k2_imported = PS_ECC_STATIC_INIT; + psEccKey_t priv = PS_ECC_STATIC_INIT; + unsigned char k1_exported[256]; + unsigned char k2_exported[256]; + uint16_t k1len = sizeof(k1_exported); + uint16_t k2len = sizeof(k2_exported); + const psEccCurve_t *curve; + unsigned char sk1k2[128], sk2k1[128]; + unsigned char in[128], out[128]; + uint16_t secretlen, inlen, outlen; + int32_t status, rc = PS_FAIL; +#ifdef USE_CERT_PARSE + psX509Cert_t *cert = NULL; +#endif /* USE_CERT_PARSE */ + + if (getEccParamById(IANA_SECP256R1, &curve) < 0) { + goto L_FAIL; + } + _psTraceStr(" %s Key Exchange...", curve->name); + if (psEccGenKey(pool, &k1, curve, NULL) < 0) { + goto L_FAIL; + } + if (psEccGenKey(pool, &k2, curve, NULL) < 0) { + _psTrace("GenKey failed."); + goto L_FAIL; + } + + if (psEccX963ExportKey(pool, &k1, k1_exported, &k1len) < 0) { + _psTrace("psEccX963ExportKey 1 failed."); + goto L_FAIL; + } + if (psEccX963ExportKey(pool, &k2, k2_exported, &k2len) < 0) { + _psTrace("psEccX963ExportKey 2 failed."); + goto L_FAIL; + } + + if (psEccX963ImportKey(pool, k1_exported, k1len, &k1_imported, curve) < 0) { + _psTrace("psEccX963ImportKey 1 failed."); + goto L_FAIL; + } + if (psEccX963ImportKey(pool, k2_exported, k2len, &k2_imported, curve) < 0) { + _psTrace("psEccX963ImportKey 2 failed."); + goto L_FAIL; + } + + secretlen = sizeof(sk1k2); + if (psEccGenSharedSecret(pool, &k1, &k2_imported, sk1k2, &secretlen, NULL) < 0 || + secretlen != curve->size) { + _psTrace("GenSharedSecret K1 failed."); + goto L_FAIL; + } + + secretlen = sizeof(sk2k1); + if (psEccGenSharedSecret(pool, &k2, &k1_imported, sk2k1, &secretlen, NULL) < 0 || + secretlen != curve->size) { + _psTrace("GenSharedSecret K2 failed."); + goto L_FAIL; + } + + if (memcmpct(sk1k2, sk2k1, curve->size) != 0) { + _psTrace("Shared secret doesn't match."); + psTraceBytes("K1K2 Secret", sk1k2, secretlen); + psTraceBytes("K2K1 Secret", sk2k1, secretlen); + goto L_FAIL; + } + _psTrace(" PASSED\n"); + + _psTraceStr(" %s Signature Validation...", curve->name); + + /* Generate some random bytes to sign */ + if (psGetEntropy(in, curve->size, NULL) < 0) { + _psTrace("GetEntropy failed."); + goto L_FAIL; + } + inlen = secretlen; + + /* Sign and verify with generated key 1*/ + outlen = sizeof(out); + if (psEccDsaSign(pool, &k1, in, inlen, out, &outlen, 0, NULL) < 0) { + _psTrace("Sign K1 failed."); + goto L_FAIL; + } + + if (psEccDsaVerify(pool, &k1_imported, in, inlen, out, outlen, + &status, NULL) < 0 || status != 1) { + _psTrace("K1 signature didn't validate."); + goto L_FAIL; + } + + /* Sign and verify with generated key 2, asking for a length prefix + for TLS */ + outlen = sizeof(out); + if (psEccDsaSign(pool, &k2, in, inlen, out, &outlen, 1, NULL) < 0) { + _psTrace("Sign K2 failed."); + goto L_FAIL; + } + + /* Skip the first 2 bytes of length, as they are not the signature */ + if (psEccDsaVerify(pool, &k2_imported, in, inlen, out + 2, outlen - 2, + &status, NULL) < 0 || status != 1) { + _psTrace("K2 signature didn't validate."); + goto L_FAIL; + } + + /* Sign and verify with private key from header and corresponding public + key in certificate, or with the private key if not parsing certs. */ + if (psEccParsePrivKey(pool, EC256KEY, sizeof(EC256KEY), &priv, curve) < 0) { + _psTrace("ParsePrivKey failed."); + goto L_FAIL; + } +#ifdef USE_CERT_PARSE + if (psX509ParseCert(pool, EC256, sizeof(EC256), &cert, 0) < 0) { + _psTrace("ParseCert failed."); + goto L_FAIL; + } +#endif + outlen = sizeof(out); + if (psEccDsaSign(pool, &priv, in, inlen, out, &outlen, 1, NULL) < 0) { + _psTrace("Sign header key failed."); + goto L_FAIL; + } + if (psEccDsaVerify(pool, +#ifdef USE_CERT_PARSE + &cert->publicKey.key.ecc, +#else + &priv, +#endif + in, inlen, out + 2, outlen - 2, &status, NULL) < 0 || status != 1) { + _psTrace("Header key signature didn't validate."); + goto L_FAIL; + } + + rc = PS_SUCCESS; + _psTrace(" PASSED\n"); + +L_FAIL: + memzero_s(in, sizeof(in)); + memzero_s(out, sizeof(out)); + memzero_s(sk1k2, sizeof(sk1k2)); + memzero_s(sk2k1, sizeof(sk2k1)); + psEccClearKey(&k1); + psEccClearKey(&k1_imported); + psEccClearKey(&k2); + psEccClearKey(&k2_imported); + psEccClearKey(&priv); +#ifdef USE_CERT_PARSE + if (cert) psX509FreeCert(cert); +#endif + return rc; +} + +static int32_t psEccTest(void) +{ + int32_t rc; + + rc = ecdh_p256_kat(); + if (rc != PS_SUCCESS) + return rc; + + rc = ecdh_p384_kat(); + if (rc != PS_SUCCESS) + return rc; + +#ifdef USE_SECP521R1 + rc = ecdh_p521_kat(); + if (rc != PS_SUCCESS) + return rc; +#endif /* USE_SECP521R1 */ + + rc = psEccPairwiseTest(); + if (rc != PS_SUCCESS) + return rc; + + return PS_SUCCESS; +} +#endif /* USE_ECC */ + +/******************************************************************************/ + + +/******************************************************************************/ + +typedef struct { + int32 (*fn)(void); + char name[64]; +} test_t; + +static test_t tests[] = { +#ifdef USE_AES +#ifdef USE_AES_BLOCK +{psAesTestBlock, "***** AES BLOCK TESTS *****"}, +#endif +#ifdef USE_AES_CBC +{psAesTestCBC, "***** AES-CBC TESTS *****"}, +#endif +#ifdef USE_AES_GCM +{psAesTestGCM, "***** AES-GCM TESTS *****"}, +#endif +#else +{NULL, "AES"}, +#endif + +#ifdef USE_CHACHA20_POLY1305 +{psChacha20Poly1305Test, "***** CHACHA20_POLY1305 TESTS *****"}, +#endif + +#ifdef USE_PKCS5 +{psPBKDF2, "***** PBKDF2 TESTS *****"}, +#endif + +#ifdef USE_3DES +{psDes3Test +#else +{NULL +#endif +, "***** 3DES TESTS *****"}, + +#ifdef USE_SEED +{psSeedTest +#else +{NULL +#endif +, "***** SEED TESTS *****"}, + +#ifdef USE_ARC4 +{psArc4Test +#else +{NULL +#endif +, "***** RC4 TESTS *****"}, + +#ifdef USE_IDEA +{psIdeaTest +#else +{NULL +#endif +, "***** IDEA TESTS *****"}, + +#ifdef USE_SHA1 +{psSha1Test +#else +{NULL +#endif +, "***** SHA1 TESTS *****"}, + +#ifdef USE_SHA256 +{psSha256Test +#else +{NULL +#endif +, "***** SHA256 TESTS *****"}, + +#ifdef USE_SHA384 +{psSha384Test +#else +{NULL +#endif +, "***** SHA384 TESTS *****"}, + +#ifdef USE_SHA512 +{psSha512Test +#else +{NULL +#endif +, "***** SHA512 TESTS *****"}, + +#ifdef USE_MD5 +{psMd5Test +#else +{NULL +#endif +, "***** MD5 TESTS *****"}, + +#ifdef USE_MD5SHA1 +{psMd5Sha1Test +#else +{NULL +#endif +, "***** MD5SHA1 TESTS *****"}, + +#ifdef USE_MD4 +{psMd4Test +#else +{NULL +#endif +, "***** MD4 TESTS *****"}, + +#ifdef USE_MD2 +{psMd2Test +#else +{NULL +#endif +, "***** MD2 TESTS *****"}, + +#ifdef USE_HMAC +{psHmacVectorTests +#else +{NULL +#endif +, "***** HMAC TESTS *****"}, + +{psPrngTests +, "***** PRNG TESTS *****"}, + +#ifdef USE_RSA +{psRsaEncryptTest +#else +{NULL +#endif +, "***** RSA ENCRYPT TESTS *****"}, + +#ifdef USE_RSA +{psRsaSignTest +#else +{NULL +#endif +, "***** RSA SIGN TESTS *****"}, + +#if defined(USE_PKCS1_OAEP) && !defined(USE_HARDWARE_CRYPTO_PKA) +{psRsaOaepVectorTest +#else +{NULL +#endif +, "***** RSA RSAES_OAEP TESTS *****"}, + +#if defined(USE_PKCS1_PSS) && !defined(USE_PKCS1_PSS_VERIFY_ONLY) && !defined(USE_HARDWARE_CRYPTO_PKA) +{psRsaPssVectorTest +#else +{NULL +#endif +, "***** RSA RSASSA_PSS TESTS *****"}, + +#ifdef USE_ECC +{psEccTest +#else +{NULL +#endif +, "***** ECC TESTS *****"}, + +{NULL +, "***** PRF TESTS *****"}, + +{NULL +, "***** PRF2 TESTS *****"}, + + +{NULL, ""} +}; + +/******************************************************************************/ +/* + Main +*/ + +int main(int argc, char **argv) +{ + int32 i; + + if (psCryptoOpen(PSCRYPTO_CONFIG) < PS_SUCCESS) { + _psTrace("Failed to initialize library: psCryptoOpen failed\n"); + return -1; + } + + for (i = 0; *tests[i].name; i++) { + if (tests[i].fn) { + _psTraceStr("%s\n", tests[i].name); + tests[i].fn(); + } else { + _psTraceStr("%s: SKIPPED\n", tests[i].name); + } + } + printf("Finishing...\n"); + psCryptoClose(); + +#ifdef WIN32 + _psTrace("Press any key to close"); + getchar(); +#endif + + return 0; +} diff --git a/crypto/test/dhperf/Makefile b/crypto/test/dhperf/Makefile new file mode 100755 index 0000000..3d625e4 --- /dev/null +++ b/crypto/test/dhperf/Makefile @@ -0,0 +1,33 @@ +# +# Makefile for crypto testing +# +# Copyright (c) 2013-2016 INSIDE Secure Corporation. All Rights Reserved. +# + +# SRC and MATRIXSSL_ROOT must be defined before including common.mk +TEST_SRC:=dhperf.c +SRC:=$(TEST_SRC) +MATRIXSSL_ROOT:=../../.. +include $(MATRIXSSL_ROOT)/common.mk + +# Generated files +TEST_EXE:=dhperf + +# Linked files +STATIC:=\ + $(MATRIXSSL_ROOT)/crypto/libcrypt_s.a \ + $(MATRIXSSL_ROOT)/core/libcore_s.a + +all: compile + +compile: $(OBJS) $(TEST_EXE) + +# Additional Dependencies +$(OBJS): $(MATRIXSSL_ROOT)/common.mk Makefile $(wildcard *.h) + +$(TEST_EXE): $(TEST_SRC:.c=.o) $(STATIC) + $(CC) -o $@ $^ $(LDFLAGS) + +clean: + rm -f $(OBJS) $(TEST_EXE) + diff --git a/crypto/test/dhperf/dhperf.c b/crypto/test/dhperf/dhperf.c new file mode 100644 index 0000000..8e49141 --- /dev/null +++ b/crypto/test/dhperf/dhperf.c @@ -0,0 +1,228 @@ +/** + * @file dhperf.c + * @version $Format:%h%d$ + * + * DH performance testing . + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "crypto/cryptoApi.h" + +#ifdef USE_DH + +/******************************************************************************/ + +/* OPS TO PERFORM */ +#define DO_GEN_INTS +#define DO_GEN_SECRET + +/* DH SIZES */ +#define DO_1024 +#define DO_2048 +#define DO_4096 + +/* NUMBER OF OPERATIONS */ +#define ITER 30 + +#define PS_OH (sizeof(psPool_t) + 1024) //TODO - remove the 1024 overhead + +/* + Tuned to smallest K for each key size and optimization setting +*/ +#ifdef PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM +#define POOL_GEN_SECRET_1024 (3 * 1024) + PS_OH +#define POOL_GEN_INTS_1024 (3 * 1024) + PS_OH +#define POOL_MISC_1024 (4 * 1024) + PS_OH +#define POOL_GEN_SECRET_2048 (5 * 1024) + PS_OH +#define POOL_GEN_INTS_2048 (5 * 1024) + PS_OH +#define POOL_MISC_2048 (7 * 1024) + PS_OH +#define POOL_GEN_SECRET_4096 (8 * 1024) + PS_OH +#define POOL_GEN_INTS_4096 (8 * 1024) + PS_OH +#define POOL_MISC_4096 (10 * 1024) + PS_OH + +#else /* PS_PUBKEY_OPTIMIZE_FOR_FASTER_SPEED */ + +#define POOL_GEN_SECRET_1024 (6 * 1024) + PS_OH +#define POOL_GEN_INTS_1024 (6 * 1024) + PS_OH +#define POOL_MISC_1024 (7 * 1024) + PS_OH +#define POOL_GEN_SECRET_2048 (11 * 1024) + PS_OH +#define POOL_GEN_INTS_2048 (11 * 1024) + PS_OH +#define POOL_MISC_2048 (13 * 1024) + PS_OH +#define POOL_GEN_SECRET_4096 (20 * 1024) + PS_OH +#define POOL_GEN_INTS_4096 (20 * 1024) + PS_OH +#define POOL_MISC_4096 (24 * 1024) + PS_OH +#endif + +#ifdef DO_1024 +#include "testkeys/DH/1024_DH_PARAMS.h" +#endif +#ifdef DO_2048 +#include "testkeys/DH/2048_DH_PARAMS.h" +#endif +#ifdef DO_4096 +#include "testkeys/DH/4096_DH_PARAMS.h" +#endif + +typedef struct { + char *name; + const unsigned char *key; + uint32 len; + int32 iter; + int32 poolSecret; + int32 poolInts; + int32 poolMisc; +} keyList_t; + +#ifdef USE_HIGHRES_TIME + #define psDiffMsecs(A, B, C) psDiffUsecs(A, B) + #define TIME_UNITS " %lld usecs" +#else + #define TIME_UNITS " %d msecs" +#endif + +/* + Add an iteration count so we don't have to run the large keys so many times +*/ +static keyList_t keys[] = { +#ifdef DO_1024 + {"dh1024", DHPARAM1024, DHPARAM1024_SIZE, ITER, + POOL_GEN_SECRET_1024, POOL_GEN_INTS_1024, POOL_MISC_1024}, +#endif +#ifdef DO_2048 + {"dh2048", DHPARAM2048, DHPARAM2048_SIZE, ITER, + POOL_GEN_SECRET_2048, POOL_GEN_INTS_2048, POOL_MISC_2048}, +#endif +#ifdef DO_2048 + {"dh4096", DHPARAM4096, DHPARAM4096_SIZE, ITER, + POOL_GEN_SECRET_4096, POOL_GEN_INTS_4096, POOL_MISC_4096}, +#endif + { NULL } /* Terminate the list */ +}; + +/******************************************************************************/ +/* + Main +*/ + + +int main(int argc, char **argv) +{ + psPool_t *pool, *misc; + psDhParams_t dhParams; + psDhKey_t dhKeyPriv, dhKeyPub; + uint16_t pLen, gLen; + unsigned char *p, *g; + psTime_t start, end; + uint16_t iter, i = 0; + unsigned char out[512]; + uint16_t outLen = sizeof(out); + + pool = misc = NULL; + if (psCryptoOpen(PSCRYPTO_CONFIG) < PS_SUCCESS) { + _psTrace("Failed to initialize library: psCryptoOpen failed\n"); + return -1; + } + _psTraceStr("STARTING DHPERF\n", NULL); + + while (keys[i].key != NULL) { + _psTraceStr("Test %s...\n", keys[i].name); + pkcs3ParseDhParamBin(misc, (unsigned char*)keys[i].key, keys[i].len, + &dhParams); + + iter = 0; + +#ifdef DO_GEN_INTS + psGetTime(&start, NULL); + while (iter < keys[i].iter) { + if (psDhGenKeyInts(pool, dhParams.size, &dhParams.p, &dhParams.g, + &dhKeyPriv, NULL) < 0) { + _psTrace(" FAILED OPERATION\n"); + } + + psDhClearKey(&dhKeyPriv); + iter++; + } + psGetTime(&end, NULL); + _psTraceInt(TIME_UNITS " genInts\n", psDiffMsecs(start, end, NULL)); +#endif /* DO_GEN_INTS */ + +#ifdef DO_GEN_SECRET + psDhExportParameters(misc, &dhParams, &p, &pLen, &g, &gLen); + if (psDhGenKeyInts(misc, dhParams.size, &dhParams.p, &dhParams.g, + &dhKeyPriv, NULL) < 0) { + _psTrace(" FAILED OPERATION\n"); + } + if (psDhGenKeyInts(misc, dhParams.size, &dhParams.p, &dhParams.g, + &dhKeyPub, NULL) < 0) { + _psTrace(" FAILED OPERATION\n"); + } + iter = 0; + outLen = sizeof(out); + psGetTime(&start, NULL); + while (iter < keys[i].iter) { + if (psDhGenSharedSecret(pool, &dhKeyPriv, &dhKeyPub, p, pLen, + out, &outLen, NULL) < 0) { + _psTrace(" FAILED OPERATION\n"); + } + + iter++; + } + psGetTime(&end, NULL); + psDhClearKey(&dhKeyPriv); + psDhClearKey(&dhKeyPub); + _psTraceInt(TIME_UNITS " genSecret\n", psDiffMsecs(start, end, NULL)); +#endif /* DO_GEN_SECRET */ + + psFree(p, misc); + psFree(g, misc); + pkcs3ClearDhParams(&dhParams); + i++; + } + +#ifdef WIN32 + _psTrace("Press any key to close"); + getchar(); +#endif + _psTraceStr("FINISHED DHPERF\n", NULL); + psCryptoClose(); + return 0; +} + +#else + +/* Stub main */ +#include + +int main(int argc, char **argv) { + printf("USE_DH not defined.\n"); + return 0; +} + +#endif /* USE_DH */ + diff --git a/crypto/test/eccperf/Makefile b/crypto/test/eccperf/Makefile new file mode 100755 index 0000000..ff1364a --- /dev/null +++ b/crypto/test/eccperf/Makefile @@ -0,0 +1,33 @@ +# +# Makefile for crypto testing +# +# Copyright (c) 2013-2016 INSIDE Secure Corporation. All Rights Reserved. +# + +# SRC and MATRIXSSL_ROOT must be defined before including common.mk +TEST_SRC:=eccperf.c +SRC:=$(TEST_SRC) +MATRIXSSL_ROOT:=../../.. +include $(MATRIXSSL_ROOT)/common.mk + +# Generated files +TEST_EXE:=eccperf + +# Linked files +STATIC:=\ + $(MATRIXSSL_ROOT)/crypto/libcrypt_s.a \ + $(MATRIXSSL_ROOT)/core/libcore_s.a + +all: compile + +compile: $(OBJS) $(TEST_EXE) + +# Additional Dependencies +$(OBJS): $(MATRIXSSL_ROOT)/common.mk Makefile $(wildcard *.h) + +$(TEST_EXE): $(TEST_SRC:.c=.o) $(STATIC) + $(CC) -o $@ $^ $(LDFLAGS) + +clean: + rm -f $(OBJS) $(TEST_EXE) + diff --git a/crypto/test/eccperf/brainpoolp224r1.h b/crypto/test/eccperf/brainpoolp224r1.h new file mode 100644 index 0000000..8bc7fd0 --- /dev/null +++ b/crypto/test/eccperf/brainpoolp224r1.h @@ -0,0 +1,15 @@ +/** + * @file brainpoolp224r1.h + * @version $Format:%h%d$ + * + * Auto generated private key as binary DER. + */ +const static unsigned char brainpoolp224r1[110] = + "\x30\x6c\x02\x01\x01\x04\x1c\x3c\xdb\x51\x9d\x2c\x76\xf9\x44\xf6" + "\x43\x19\xeb\x4d\x5e\x8b\x08\xe3\xb3\xe9\x1e\x95\x43\xf8\xfd\x98" + "\xa7\x6c\x27\xa0\x0b\x06\x09\x2b\x24\x03\x03\x02\x08\x01\x01\x05" + "\xa1\x3c\x03\x3a\x00\x04\x80\x0b\x7a\x26\x8f\xf1\x51\xe8\x94\x11" + "\xa4\x53\x89\xe4\x20\x16\x83\x47\x40\x29\xac\xb8\x10\x53\x0c\x97" + "\xed\x88\xca\xa2\xbd\x45\xc0\xe6\x16\x20\xcc\x6e\xd9\xe5\xd9\x00" + "\xf2\xbf\xd0\x1d\x36\x4c\xab\x87\x58\xb3\x39\x43\xfa\xf1"; + diff --git a/crypto/test/eccperf/brainpoolp256r1.h b/crypto/test/eccperf/brainpoolp256r1.h new file mode 100644 index 0000000..a29bace --- /dev/null +++ b/crypto/test/eccperf/brainpoolp256r1.h @@ -0,0 +1,17 @@ +/** + * @file brainpoolp256r1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char brainpoolp256r1[] = { +48, 120, 2, 1, 1, 4, 32, 30, 250, 245, 173, 225, 235, +101, 49, 67, 79, 24, 99, 240, 87, 159, 128, 238, 167, 199, +194, 22, 11, 34, 124, 214, 224, 213, 47, 104, 46, 129, 41, +160, 11, 6, 9, 43, 36, 3, 3, 2, 8, 1, 1, 7, +161, 68, 3, 66, 0, 4, 61, 230, 81, 67, 91, 48, 236, +207, 73, 156, 185, 230, 5, 0, 104, 82, 170, 199, 237, 35, +45, 252, 189, 207, 39, 60, 161, 105, 209, 208, 90, 173, 78, +85, 81, 119, 6, 189, 230, 234, 203, 214, 227, 194, 121, 48, +150, 41, 153, 148, 194, 17, 195, 171, 142, 43, 242, 74, 183, +47, 153, 214, 141, 18}; diff --git a/crypto/test/eccperf/brainpoolp384r1.h b/crypto/test/eccperf/brainpoolp384r1.h new file mode 100644 index 0000000..e915f50 --- /dev/null +++ b/crypto/test/eccperf/brainpoolp384r1.h @@ -0,0 +1,21 @@ +/** + * @file brainpoolp384r1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char brainpoolp384r1[] = { +48, 129, 168, 2, 1, 1, 4, 48, 78, 236, 187, 223, 107, +43, 205, 83, 37, 68, 76, 145, 120, 81, 207, 81, 60, 66, +63, 240, 100, 89, 170, 9, 2, 101, 217, 56, 171, 89, 127, +139, 60, 206, 155, 32, 81, 255, 3, 43, 221, 245, 188, 147, +117, 74, 5, 162, 160, 11, 6, 9, 43, 36, 3, 3, 2, +8, 1, 1, 11, 161, 100, 3, 98, 0, 4, 107, 9, 194, +68, 23, 80, 20, 218, 8, 61, 218, 224, 77, 43, 90, 31, +141, 180, 78, 219, 148, 196, 101, 26, 131, 111, 254, 36, 9, +145, 109, 64, 245, 90, 179, 149, 81, 173, 66, 195, 98, 37, +196, 94, 169, 174, 58, 87, 102, 91, 36, 201, 7, 221, 117, +144, 49, 236, 121, 98, 120, 115, 96, 144, 235, 28, 51, 202, +231, 205, 222, 47, 223, 36, 186, 48, 107, 42, 52, 90, 16, +81, 133, 161, 161, 16, 247, 138, 242, 216, 55, 212, 64, 107, +42, 207}; diff --git a/crypto/test/eccperf/brainpoolp512r1.h b/crypto/test/eccperf/brainpoolp512r1.h new file mode 100644 index 0000000..81f0dd8 --- /dev/null +++ b/crypto/test/eccperf/brainpoolp512r1.h @@ -0,0 +1,25 @@ +/** + * @file brainpoolp512r1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char brainpoolp512r1[] = { +48, 129, 218, 2, 1, 1, 4, 64, 26, 74, 116, 238, 16, +55, 82, 21, 98, 192, 203, 116, 99, 70, 129, 62, 145, 63, +231, 124, 36, 164, 189, 238, 119, 167, 55, 157, 193, 108, 234, +175, 250, 119, 32, 126, 105, 171, 156, 249, 243, 148, 247, 252, +39, 187, 255, 48, 87, 115, 174, 115, 123, 171, 224, 247, 185, +54, 214, 198, 79, 55, 92, 167, 160, 11, 6, 9, 43, 36, +3, 3, 2, 8, 1, 1, 13, 161, 129, 133, 3, 129, 130, +0, 4, 80, 0, 147, 125, 251, 189, 72, 132, 180, 21, 38, +38, 170, 4, 75, 122, 173, 171, 1, 151, 243, 60, 205, 23, +20, 226, 245, 247, 109, 166, 78, 203, 4, 112, 226, 69, 39, +166, 206, 143, 28, 70, 95, 201, 50, 109, 6, 159, 138, 207, +124, 197, 133, 221, 122, 182, 129, 63, 203, 122, 64, 75, 14, +212, 118, 233, 85, 205, 111, 44, 251, 202, 71, 152, 30, 119, +55, 34, 84, 168, 172, 37, 95, 199, 212, 19, 130, 70, 127, +218, 99, 15, 87, 157, 94, 164, 131, 232, 44, 239, 34, 28, +60, 26, 168, 198, 134, 86, 3, 193, 200, 230, 69, 219, 17, +49, 131, 123, 174, 228, 119, 77, 58, 8, 237, 96, 106, 119 +}; diff --git a/crypto/test/eccperf/eccperf.c b/crypto/test/eccperf/eccperf.c new file mode 100644 index 0000000..9475a93 --- /dev/null +++ b/crypto/test/eccperf/eccperf.c @@ -0,0 +1,367 @@ +/** + * @file eccperf.c + * @version $Format:%h%d$ + * + * ECC performance testing . + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "crypto/cryptoApi.h" + +#ifdef USE_ECC + +/* OPERATIONS TO TEST */ +#define SIGN_OP /* Private encrypt operations */ +#define VERIFY_OP /* Public decrypt operations */ +#define MAKE_KEY_OP /* DH key gen operations */ +#define SHARED_SECRET_OP /* DH shared secret computation */ + +/* CURVES TO TEST */ +#ifdef USE_SECP192R1 + #define DO_SECP192R1 +#endif +#ifdef USE_SECP224R1 + #define DO_SECP224R1 +#endif +#ifdef USE_SECP256R1 + #define DO_SECP256R1 +#endif +#ifdef USE_SECP384R1 + #define DO_SECP384R1 +#endif +#ifdef USE_SECP521R1 + #define DO_SECP521R1 +#endif + +#ifdef USE_BRAIN224R1 + #define DO_BRAIN224R1 +#endif +#ifdef USE_BRAIN256R1 + #define DO_BRAIN256R1 +#endif +#ifdef USE_BRAIN384R1 + #define DO_BRAIN384R1 +#endif +#ifdef USE_BRAIN512R1 +//TODO not currently working +// #define DO_BRAIN512R1 +#endif + +/* NUMBER OF OPERATIONS */ +#define ITER 1 + +#define PS_OH sizeof(psPool_t) + +/* + TODO: Not tuned to smallest K for EACH key size. +*/ +#define POOL_SIGN_192 (8 * 1024) + PS_OH +#define POOL_VERIFY_192 (8 * 1024) + PS_OH +#define POOL_MAKE_KEY_192 (8 * 1024) + PS_OH +#define POOL_MISC_192 (8 * 1024) + PS_OH + +#define POOL_SIGN_224 (8 * 1024) + PS_OH +#define POOL_VERIFY_224 (8 * 1024) + PS_OH +#define POOL_MAKE_KEY_224 (8 * 1024) + PS_OH +#define POOL_MISC_224 (8 * 1024) + PS_OH + +#define POOL_SIGN_256 (8 * 1024) + PS_OH +#define POOL_VERIFY_256 (8 * 1024) + PS_OH +#define POOL_MAKE_KEY_256 (8 * 1024) + PS_OH +#define POOL_MISC_256 (8 * 1024) + PS_OH + +#define POOL_SIGN_384 (12 * 1024) + PS_OH +#define POOL_VERIFY_384 (12 * 1024) + PS_OH +#define POOL_MAKE_KEY_384 (12 * 1024) + PS_OH +#define POOL_MISC_384 (12 * 1024) + PS_OH + +#define POOL_SIGN_521 (12 * 1024) + PS_OH +#define POOL_VERIFY_521 (12 * 1024) + PS_OH +#define POOL_MAKE_KEY_521 (12 * 1024) + PS_OH +#define POOL_MISC_521 (12 * 1024) + PS_OH + +#ifdef DO_SECP192R1 +#include "testkeys/EC/192_EC_KEY.h" /* EC192KEY[] */ +#endif +#ifdef DO_SECP224R1 +#include "testkeys/EC/224_EC_KEY.h" /* EC224KEY[] */ +#endif +#ifdef DO_SECP256R1 +#include "testkeys/EC/256_EC_KEY.h" /* EC256KEY[] */ +#endif +#ifdef DO_SECP384R1 +#include "testkeys/EC/384_EC_KEY.h" /* EC384KEY[] */ +#endif +#ifdef DO_SECP521R1 +#include "testkeys/EC/521_EC_KEY.h" /* EC521KEY[] */ +#endif +#ifdef DO_BRAIN224R1 +#include "brainpoolp224r1.h" +#endif +#ifdef DO_BRAIN256R1 +#include "brainpoolp256r1.h" +#endif +#ifdef DO_BRAIN384R1 +#include "brainpoolp384r1.h" +#endif +#ifdef DO_BRAIN512R1 +#include "brainpoolp512r1.h" +#endif + +typedef struct { + char *name; + const unsigned char *key; + uint32 len; + int32 iter; + int32 poolSign; + int32 poolVerify; + int32 poolMakeKey; + int32 poolMisc; +} keyList_t; + +#ifdef USE_HIGHRES_TIME + #define psDiffMsecs(A, B, C) psDiffUsecs(A, B) + #define TIME_UNITS " %lld usecs" + #define PER_SEC(A) ((A) ? (1000000 / (A)) : 0) +#else + #define TIME_UNITS " %d msecs" + #define PER_SEC(A) ((A) ? (1000 / (A)) : 0) +#endif + +const static keyList_t keys[] = { +#ifdef DO_SECP192R1 + {"secp192r1", EC192KEY, EC192KEY_SIZE, ITER, POOL_SIGN_192, + POOL_VERIFY_192, POOL_MAKE_KEY_192, POOL_MISC_192}, +#endif +#ifdef DO_SECP224R1 + {"secp224r1", EC224KEY, EC224KEY_SIZE, ITER, POOL_SIGN_224, + POOL_VERIFY_224, POOL_MAKE_KEY_224, POOL_MISC_224}, +#endif +#ifdef DO_SECP256R1 + {"secp256r1", EC256KEY, EC256KEY_SIZE, ITER, POOL_SIGN_256, + POOL_VERIFY_256, POOL_MAKE_KEY_256, POOL_MISC_256}, +#endif +#ifdef DO_SECP384R1 + {"secp384r1", EC384KEY, EC384KEY_SIZE, ITER, POOL_SIGN_384, + POOL_VERIFY_384, POOL_MAKE_KEY_384, POOL_MISC_384}, +#endif +#ifdef DO_SECP521R1 + {"secp521r1", EC521KEY, EC521KEY_SIZE, ITER, POOL_SIGN_521, + POOL_VERIFY_521, POOL_MAKE_KEY_521, POOL_MISC_521}, +#endif +#ifdef DO_BRAIN224R1 + {"brainpoolp224r1", brainpoolp224r1, sizeof(brainpoolp224r1), + ITER, POOL_SIGN_224, POOL_VERIFY_224, POOL_MAKE_KEY_224, POOL_MISC_224}, +#endif +#ifdef DO_BRAIN256R1 + {"brainpoolp256r1", brainpoolp256r1, sizeof(brainpoolp256r1), + ITER, POOL_SIGN_256, POOL_VERIFY_256, POOL_MAKE_KEY_256, POOL_MISC_256}, +#endif +#ifdef DO_BRAIN384R1 + {"brainpoolp384r1", brainpoolp384r1, sizeof(brainpoolp384r1), + ITER, POOL_SIGN_384, POOL_VERIFY_384, POOL_MAKE_KEY_384, POOL_MISC_384}, +#endif +#ifdef DO_BRAIN512R1 + {"brainpoolp512r1", brainpoolp512r1, sizeof(brainpoolp512r1), + ITER, POOL_SIGN_521, POOL_VERIFY_521, POOL_MAKE_KEY_521, POOL_MISC_521}, +#endif + {NULL} +}; + +/******************************************************************************/ +/* + Main +*/ + + +#ifdef STATS + #include + #include +#ifdef USE_HIGHRES_TIME + #define TIME_STRING "\t%lld" +#else + #define TIME_STRING "\t%d" +#endif +#endif + +int main(int argc, char **argv) +{ + psPool_t *pool, *misc; + psEccKey_t privkey; + psEccKey_t eccKey; + unsigned char in[SHA256_HASHLEN]; + unsigned char *out; + psTime_t start, end; + uint32 iter, i = 0; + int32 t, validateStatus; + uint16_t signLen; +#ifdef STATS + FILE *sfd; +#endif + + pool = misc = NULL; + if (psCryptoOpen(PSCRYPTO_CONFIG) < PS_SUCCESS) { + _psTrace("Failed to initialize library: psCryptoOpen failed\n"); + return -1; + } + _psTraceStr("STARTING ECCPERF\n", NULL); +#ifdef STATS + if ((sfd = fopen("perfstat.txt", "w")) == NULL) { + return PS_FAILURE; + } +#ifdef USE_HIGHRES_TIME + fprintf(sfd, "Key\tSign(usec)\tVerify\tEncrypt\tDecrypt\n"); +#else + fprintf(sfd, "Key\tSign(msec)\tVerify\tEncrypt\tDecrypt\n"); +#endif +#endif /* STATS */ + + while (keys[i].key != NULL) { + _psTraceStr("Testing %s...\n", keys[i].name); +#ifdef STATS + fprintf(sfd, "%s", keys[i].name); +#endif + if (psEccParsePrivKey(misc, (unsigned char*)keys[i].key, keys[i].len, + &privkey, NULL) < 0) { + _psTrace(" FAILED OPERATION:ParsePriv\n"); + } + + /* Get random data to sign */ + psGetEntropy(in, sizeof(in), NULL); + + /* A signature is twice as long as the privKey, plus some overhead + for ASN.1 encoding. The definitive output size is not known until + the value is generated because of leading zero padding required for + ASN.1 for numbers with the high bit set */ + signLen = 2 * privkey.curve->size + 10; + out = psMalloc(misc, signLen); + +#ifdef MAKE_KEY_OP + psGetTime(&start, NULL); + for (iter = 0; iter < keys[i].iter; iter++) { + if (psEccGenKey(pool, &eccKey, privkey.curve, NULL) < 0) { + _psTrace(" FAILED OPERATION:GenKey\n"); + } else { + psEccClearKey(&eccKey); + } + } + psGetTime(&end, NULL); + t = psDiffMsecs(start, end, NULL) / keys[i].iter; + _psTraceInt(TIME_UNITS "/genkey ", t); + _psTraceInt("(%d per sec)\n", PER_SEC(t)); +#ifdef STATS + fprintf(sfd, TIME_STRING, t); +#endif +#endif /* MAKE_KEY_OP */ + +#ifdef SHARED_SECRET_OP + if (psEccGenKey(pool, &eccKey, privkey.curve, NULL) < 0) { + _psTrace(" FAILED OPERATION:GenKeySharedSecret\n"); + } + psGetTime(&start, NULL); + for (iter = 0; iter < keys[i].iter; iter++) { + signLen = privkey.curve->size; + if (psEccGenSharedSecret(pool, &privkey, &eccKey, + out, &signLen, NULL) < 0 || signLen != privkey.curve->size) { + _psTrace(" FAILED OPERATION:SharedSecret\n"); + } + } + psGetTime(&end, NULL); + psEccClearKey(&eccKey); + t = psDiffMsecs(start, end, NULL) / keys[i].iter; + _psTraceInt(TIME_UNITS "/sharedsecret ", t); + _psTraceInt("(%d per sec)\n", PER_SEC(t)); +#ifdef STATS + fprintf(sfd, TIME_STRING, t); +#endif +#endif /* SHARED_SECRET_OP */ + +#ifdef SIGN_OP + psGetTime(&start, NULL); + for (iter = 0; iter < keys[i].iter; iter++) { + signLen = 2 * privkey.curve->size + 10; + if (psEccDsaSign(pool, &privkey, + in, sizeof(in), out, &signLen, 1, NULL) < 0) { + _psTrace(" FAILED OPERATION: SignHash\n"); + } + } + psGetTime(&end, NULL); + t = psDiffMsecs(start, end, NULL) / keys[i].iter; + _psTraceInt(TIME_UNITS "/sign ", t); + _psTraceInt("(%d per sec)\n", PER_SEC(t)); +#ifdef STATS + fprintf(sfd, TIME_STRING, t); +#endif +#endif /* SIGN_OP */ + +#ifdef VERIFY_OP + psGetTime(&start, NULL); + for (iter = 0; iter < keys[i].iter; iter++) { + signLen = 2 * privkey.curve->size + 10; + if (psEccDsaVerify(pool, &privkey, + in, sizeof(in), + out + 2, signLen - 2, + &validateStatus, NULL) < 0 || validateStatus != 1) { + _psTrace(" FAILED OPERATION:VerifySignature\n"); + } + } + psGetTime(&end, NULL); + t = psDiffMsecs(start, end, NULL) / keys[i].iter; + _psTraceInt(TIME_UNITS "/verify ", t); + _psTraceInt("(%d per sec)\n", PER_SEC(t)); +#ifdef STATS + fprintf(sfd, TIME_STRING, t); +#endif +#endif /* VERIFY_OP */ + + memzero_s(in, sizeof(in)); + psFree(out, misc); + psEccClearKey(&privkey); + i++; + } + +#ifdef STATS + fclose(sfd); +#endif +#ifdef WIN32 + _psTrace("Press any key to close"); + getchar(); +#endif + _psTraceStr("FINISHED ECCPERF\n", NULL); + psCryptoClose(); + return 0; +} + +#else +int main(int argc, char **argv) { + printf("USE_ECC not defined.\n"); + return 0; +} +#endif /* USE_ECC */ + diff --git a/crypto/test/hmac_test_vectors.h b/crypto/test/hmac_test_vectors.h new file mode 100644 index 0000000..3cfe874 --- /dev/null +++ b/crypto/test/hmac_test_vectors.h @@ -0,0 +1,3721 @@ +/** + * @file hmac_test_vectors.h + * @version $Format:%h%d$ + * + * HMAC test vectors for crypto harness. + */ +/* + * Copyright (c) 2015 INSIDE Secure Corporation + * All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF INSIDE. + * + * Please do not edit this file without first consulting INSIDE support. + * Unauthorized changes to this file are not supported by INSIDE. + * + * The copyright notice above does not evidence any actual or intended + * publication of such source code. + * + * This Module contains Proprietary Information of INSIDE and should be + * treated as Confidential. + * + * The information in this file is provided for the exclusive use of the + * licensees of INSIDE. Such users have the right to use, modify, + * and incorporate this code into products for purposes authorized by the + * license agreement provided they include this notice and the associated + * copyright notice with any such product. + * + * The information in this file is provided "AS IS" without warranty. + */ +/******************************************************************************/ + +/* Test vectors for HMAC. This file is intended to be include to + algorithmTest.c. */ + +/* HMAC-PKEY Test Vectors with key length: 14 bytes */ +/* Test vector for HMAC-sha1 */ +static const unsigned char hmac_sha1_vector14_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42 +}; +static const unsigned char hmac_sha1_vector14_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha1_vector14_out[] = { + 0x29, 0xa0, 0x9d, 0x15, 0xf9, 0x4c, 0x52, 0xc8, 0x98, 0x8b, 0x99, 0xfa, + 0x22, 0x9e, 0xc5, 0xdc, 0x8c, 0x74, 0xec, 0xe8 +}; +/* Test vector for HMAC-sha224 */ +static const unsigned char hmac_sha224_vector14_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42 +}; +static const unsigned char hmac_sha224_vector14_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha224_vector14_out[] = { + 0x58, 0xcf, 0x42, 0xea, 0x85, 0x40, 0xd6, 0x86, 0xf3, 0x0c, 0xc9, 0xea, + 0x6d, 0x20, 0x52, 0x2a, 0x45, 0xa8, 0x6b, 0xce, 0x2d, 0x0b, 0x2e, 0x1f, + 0xf9, 0xd2, 0xa3, 0xfb +}; +/* Test vector for HMAC-sha256 */ +static const unsigned char hmac_sha256_vector14_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42 +}; +static const unsigned char hmac_sha256_vector14_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha256_vector14_out[] = { + 0x62, 0x99, 0xaf, 0xb4, 0xc0, 0x58, 0xdc, 0x9a, 0x80, 0x86, 0xe4, 0x0d, + 0x3d, 0xf8, 0xe8, 0x80, 0xe7, 0x12, 0x85, 0xd6, 0x6c, 0xf3, 0x02, 0x15, + 0xa7, 0x52, 0x84, 0x15, 0xda, 0xc6, 0x9e, 0xed +}; +/* Test vector for HMAC-sha384 */ +static const unsigned char hmac_sha384_vector14_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42 +}; +static const unsigned char hmac_sha384_vector14_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha384_vector14_out[] = { + 0x12, 0xca, 0x87, 0x17, 0x8b, 0x50, 0x2b, 0x9b, 0x31, 0xc2, 0x87, 0x0a, + 0x9d, 0x90, 0xc5, 0x77, 0x39, 0xf0, 0x2d, 0xa9, 0x8c, 0x39, 0x28, 0x3d, + 0x18, 0xea, 0x96, 0xa1, 0xd9, 0x46, 0x1b, 0xeb, 0x5a, 0x90, 0x20, 0xe7, + 0x56, 0x73, 0x7b, 0xe0, 0xb2, 0x93, 0xa2, 0x61, 0x89, 0x3f, 0xc2, 0xec +}; +/* Test vector for HMAC-sha512 */ +static const unsigned char hmac_sha512_vector14_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42 +}; +static const unsigned char hmac_sha512_vector14_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha512_vector14_out[] = { + 0xfb, 0x5a, 0x7f, 0x64, 0x7b, 0xa1, 0x53, 0xc0, 0xc9, 0xed, 0xe2, 0xab, + 0xa2, 0xa0, 0xa0, 0x4d, 0x20, 0x6d, 0xda, 0x1c, 0x27, 0x7f, 0x44, 0x56, + 0x80, 0xa2, 0xe7, 0x3f, 0xbc, 0x35, 0xdc, 0xd7, 0xe9, 0xe8, 0x8f, 0x6e, + 0xb3, 0x8c, 0x09, 0xc2, 0x8b, 0x8b, 0xaa, 0x6e, 0xa4, 0x44, 0x55, 0xda, + 0x2c, 0x71, 0xe6, 0x44, 0xc4, 0x98, 0xe0, 0xa3, 0x9c, 0xf8, 0x6a, 0xaa, + 0xca, 0xbe, 0x11, 0xbc +}; + +/* HMAC-PKEY Test Vectors with key length: 16 bytes */ +/* Test vector for HMAC-sha1 */ +static const unsigned char hmac_sha1_vector16_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha1_vector16_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha1_vector16_out[] = { + 0x85, 0xe2, 0x75, 0x14, 0xa1, 0x4b, 0xc6, 0xe1, 0x9c, 0x45, 0xe6, 0x3c, + 0xd1, 0x35, 0x2f, 0xae, 0x0c, 0xf4, 0x12, 0xda +}; +/* Test vector for HMAC-sha224 */ +static const unsigned char hmac_sha224_vector16_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha224_vector16_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha224_vector16_out[] = { + 0xe0, 0xdc, 0xa6, 0x72, 0x1c, 0x5f, 0xe4, 0x81, 0xe0, 0xff, 0xbc, 0x46, + 0x78, 0xec, 0xe8, 0x72, 0xee, 0x7f, 0x0f, 0x07, 0x8f, 0x6c, 0x8a, 0xc6, + 0x46, 0x51, 0x70, 0x29 +}; +/* Test vector for HMAC-sha256 */ +static const unsigned char hmac_sha256_vector16_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha256_vector16_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha256_vector16_out[] = { + 0xa0, 0xe0, 0xbe, 0x36, 0x7a, 0x4e, 0x12, 0x57, 0x60, 0x58, 0x9d, 0xda, + 0x97, 0x41, 0xcc, 0x13, 0x48, 0x42, 0x56, 0x73, 0xaa, 0x75, 0xed, 0x6f, + 0x58, 0x7c, 0x80, 0xdb, 0x40, 0x9a, 0xd7, 0x89 +}; +/* Test vector for HMAC-sha384 */ +static const unsigned char hmac_sha384_vector16_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha384_vector16_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha384_vector16_out[] = { + 0xf6, 0x17, 0x84, 0xb2, 0x87, 0xa4, 0x24, 0x8e, 0x63, 0x96, 0x9c, 0x72, + 0x44, 0x1e, 0xa4, 0x42, 0xb4, 0x73, 0xd4, 0xee, 0x87, 0xdf, 0x7a, 0xe2, + 0xca, 0x17, 0xbb, 0xb1, 0x29, 0x20, 0xcf, 0xcb, 0x7e, 0x6b, 0xe6, 0x1a, + 0xac, 0x7a, 0x30, 0x46, 0x02, 0x8c, 0x1d, 0x39, 0x4a, 0x2d, 0xa6, 0xa0 +}; +/* Test vector for HMAC-sha512 */ +static const unsigned char hmac_sha512_vector16_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha512_vector16_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha512_vector16_out[] = { + 0x91, 0x25, 0xfa, 0x98, 0xe6, 0xa9, 0x16, 0x1d, 0x7d, 0xfd, 0x50, 0x5a, + 0x40, 0xc4, 0x04, 0xc3, 0x61, 0x69, 0xfc, 0x63, 0xf9, 0x54, 0x45, 0x50, + 0x4e, 0xb8, 0xe3, 0xc3, 0xb3, 0x01, 0xdf, 0x2b, 0x12, 0x16, 0xba, 0x14, + 0xee, 0xb4, 0xea, 0xf7, 0x29, 0xe6, 0xe9, 0x62, 0xb6, 0xc5, 0x53, 0xf1, + 0xf5, 0xf0, 0xf6, 0xb8, 0x7e, 0xb6, 0xeb, 0x0f, 0x90, 0x98, 0x4f, 0x10, + 0x8a, 0x5a, 0xeb, 0x88 +}; + +/* HMAC-PKEY Test Vectors with key length: 20 bytes */ +/* Test vector for HMAC-sha1 */ +static const unsigned char hmac_sha1_vector20_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha1_vector20_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha1_vector20_out[] = { + 0x8b, 0x98, 0xf3, 0x66, 0xe4, 0xfd, 0x1f, 0xdc, 0xc1, 0xf6, 0x59, 0x70, + 0xa9, 0x97, 0xc9, 0x70, 0xad, 0x66, 0xf5, 0x91 +}; +/* Test vector for HMAC-sha224 */ +static const unsigned char hmac_sha224_vector20_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha224_vector20_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha224_vector20_out[] = { + 0xe2, 0x47, 0x0c, 0x87, 0x99, 0xce, 0x66, 0x97, 0x92, 0x74, 0xa3, 0x1a, + 0xb2, 0xaa, 0x00, 0x94, 0x26, 0xbc, 0x98, 0xb9, 0xb1, 0x43, 0xc8, 0x3e, + 0x94, 0x50, 0xa0, 0x68 +}; +/* Test vector for HMAC-sha256 */ +static const unsigned char hmac_sha256_vector20_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha256_vector20_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha256_vector20_out[] = { + 0x88, 0x22, 0x3a, 0x97, 0xe4, 0xb4, 0x00, 0x9e, 0xc8, 0x47, 0xd0, 0xa0, + 0x2a, 0x99, 0xf8, 0x83, 0x90, 0x9d, 0xe7, 0x56, 0x26, 0x7e, 0x66, 0x88, + 0xd3, 0xde, 0xbe, 0x0c, 0x30, 0x41, 0x0d, 0xc3 +}; +/* Test vector for HMAC-sha384 */ +static const unsigned char hmac_sha384_vector20_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha384_vector20_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha384_vector20_out[] = { + 0xd8, 0x07, 0x76, 0x25, 0xad, 0x6d, 0x78, 0xc3, 0x62, 0x2e, 0xed, 0xd3, + 0xa1, 0x83, 0xb2, 0xc5, 0xec, 0xe7, 0x0f, 0xc3, 0xd5, 0xfa, 0x48, 0x5a, + 0x87, 0x27, 0x19, 0xc4, 0xe9, 0xf0, 0xbc, 0x1f, 0xd3, 0x1a, 0x7c, 0xd7, + 0xb2, 0xc2, 0x8e, 0xf9, 0x9a, 0xcb, 0x9b, 0x42, 0x78, 0x3b, 0x7a, 0x30 +}; +/* Test vector for HMAC-sha512 */ +static const unsigned char hmac_sha512_vector20_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha512_vector20_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha512_vector20_out[] = { + 0xbd, 0xd3, 0xb0, 0xe1, 0xd2, 0x5a, 0x73, 0x59, 0xa2, 0x75, 0x10, 0x83, + 0x62, 0xda, 0x51, 0x29, 0xcc, 0x69, 0x6a, 0x89, 0xe8, 0x1b, 0xc6, 0x0c, + 0xe3, 0x01, 0x61, 0xdf, 0xf8, 0xe6, 0x13, 0x42, 0x85, 0xc2, 0x0c, 0x95, + 0xf4, 0xc6, 0xde, 0xcd, 0xd6, 0xf0, 0xf5, 0xa1, 0xff, 0x63, 0xd7, 0x81, + 0x67, 0xb5, 0x36, 0xe2, 0x17, 0xd6, 0xbd, 0xa6, 0xc6, 0x57, 0x42, 0x54, + 0x95, 0xb9, 0xb5, 0x9b +}; + +/* HMAC-PKEY Test Vectors with key length: 24 bytes */ +/* Test vector for HMAC-sha1 */ +static const unsigned char hmac_sha1_vector24_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha1_vector24_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha1_vector24_out[] = { + 0xc6, 0x12, 0xdb, 0x1d, 0x9a, 0xa8, 0x3d, 0x45, 0xe5, 0xa1, 0xfb, 0x86, + 0x41, 0x60, 0xc2, 0x11, 0x7b, 0x8d, 0x32, 0x5e +}; +/* Test vector for HMAC-sha224 */ +static const unsigned char hmac_sha224_vector24_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha224_vector24_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha224_vector24_out[] = { + 0xd8, 0x8a, 0x6f, 0x9d, 0x47, 0xd7, 0xb4, 0x71, 0x39, 0x19, 0xd9, 0x1e, + 0x8e, 0x4f, 0xfc, 0x6e, 0xb5, 0x9f, 0xaf, 0x25, 0x29, 0xfa, 0x33, 0x3a, + 0xb5, 0xb5, 0x19, 0x4a +}; +/* Test vector for HMAC-sha256 */ +static const unsigned char hmac_sha256_vector24_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha256_vector24_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha256_vector24_out[] = { + 0x6f, 0x43, 0x76, 0x65, 0xab, 0x0a, 0x65, 0xda, 0x27, 0x43, 0x39, 0xd1, + 0x07, 0xf6, 0xc9, 0x42, 0x28, 0x10, 0x0b, 0x01, 0xb5, 0x7f, 0x3a, 0xf6, + 0xa7, 0x3d, 0xa2, 0xf6, 0xe0, 0x40, 0x23, 0xbf +}; +/* Test vector for HMAC-sha384 */ +static const unsigned char hmac_sha384_vector24_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha384_vector24_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; + +static const unsigned char hmac_sha384_vector24_out[] = { + 0xa7, 0x64, 0xd8, 0xff, 0x14, 0x3b, 0x77, 0x77, 0x43, 0xa3, 0xe9, 0xbd, + 0xfa, 0x07, 0xd7, 0xc6, 0x23, 0x0f, 0xcb, 0x5b, 0x4c, 0xec, 0x54, 0x58, + 0x73, 0x27, 0xfc, 0xd2, 0x82, 0x69, 0xe6, 0xde, 0x0e, 0x3c, 0xd4, 0x33, + 0x16, 0x03, 0x88, 0x9f, 0xeb, 0x27, 0x40, 0xdb, 0xee, 0x6c, 0x34, 0x55 +}; +/* Test vector for HMAC-sha512 */ +static const unsigned char hmac_sha512_vector24_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha512_vector24_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha512_vector24_out[] = { + 0xab, 0x31, 0x5c, 0xc5, 0x32, 0x43, 0x6f, 0x14, 0x6a, 0x8b, 0x5c, 0x64, + 0xdf, 0x6c, 0xcf, 0x7d, 0xf0, 0xac, 0xa9, 0xca, 0xc8, 0xb3, 0xe4, 0x08, + 0x1d, 0x32, 0x9b, 0xfe, 0x3e, 0xe8, 0x39, 0x74, 0xba, 0xad, 0x9e, 0x9d, + 0x04, 0xbf, 0x71, 0xad, 0x12, 0x73, 0x7c, 0x94, 0xab, 0x91, 0x4a, 0xc4, + 0x2f, 0x9b, 0xf5, 0x4d, 0x95, 0x85, 0xd2, 0x41, 0x7d, 0x77, 0x5a, 0xa5, + 0x47, 0x13, 0x47, 0x82 +}; + +/* HMAC-PKEY Test Vectors with key length: 28 bytes */ +/* Test vector for HMAC-sha1 */ +static const unsigned char hmac_sha1_vector28_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha1_vector28_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha1_vector28_out[] = { + 0x97, 0x0c, 0xaa, 0x67, 0x2e, 0xe5, 0x69, 0xd5, 0x0f, 0xb5, 0x26, 0x4c, + 0xfe, 0x94, 0x06, 0xd8, 0x31, 0x9d, 0x23, 0xde +}; +/* Test vector for HMAC-sha224 */ +static const unsigned char hmac_sha224_vector28_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha224_vector28_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha224_vector28_out[] = { + 0x38, 0xe3, 0xbd, 0xbe, 0x4c, 0xf3, 0xe2, 0x4b, 0x39, 0x5a, 0xe1, 0x95, + 0x24, 0xb0, 0xee, 0xf5, 0x37, 0x84, 0x68, 0x50, 0x5f, 0xf0, 0x1b, 0x72, + 0xc3, 0xf0, 0x89, 0xb5 +}; +/* Test vector for HMAC-sha256 */ +static const unsigned char hmac_sha256_vector28_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha256_vector28_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha256_vector28_out[] = { + 0xa3, 0xd1, 0xee, 0x62, 0x93, 0x20, 0xbe, 0x53, 0x86, 0x04, 0x37, 0xff, + 0x5c, 0x5e, 0x1d, 0xf2, 0x01, 0xb7, 0x47, 0xeb, 0xda, 0x0e, 0xd7, 0x47, + 0x28, 0xa2, 0x41, 0x58, 0xcb, 0x61, 0x2a, 0x70 +}; +/* Test vector for HMAC-sha384 */ +static const unsigned char hmac_sha384_vector28_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha384_vector28_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha384_vector28_out[] = { + 0x8d, 0x92, 0x75, 0x26, 0x7f, 0x11, 0x0c, 0x5a, 0x9a, 0xfa, 0x4d, 0xaa, + 0xf2, 0xb3, 0xba, 0xf9, 0xf0, 0x0e, 0x45, 0x94, 0x4d, 0xca, 0x88, 0x29, + 0x77, 0xcb, 0x00, 0x2f, 0x2f, 0xde, 0xd6, 0x39, 0x80, 0x5f, 0x59, 0x32, + 0xaa, 0xa0, 0xff, 0x73, 0x90, 0x27, 0xcc, 0xe5, 0xa3, 0x28, 0xc5, 0x3c +}; +/* Test vector for HMAC-sha512 */ +static const unsigned char hmac_sha512_vector28_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha512_vector28_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha512_vector28_out[] = { + 0x2e, 0xa6, 0xed, 0x90, 0xed, 0xe8, 0x3e, 0x0c, 0xbb, 0x62, 0x35, 0xc1, + 0x4b, 0x66, 0xd7, 0xb1, 0xe0, 0x06, 0xfd, 0x4e, 0xb7, 0xa5, 0xa6, 0x4f, + 0x59, 0xf8, 0xc6, 0x3c, 0xe6, 0xdd, 0x83, 0x00, 0xde, 0xb1, 0x5b, 0xef, + 0xbc, 0xb9, 0xab, 0x4a, 0xb8, 0x7a, 0x55, 0xc8, 0xfa, 0xcd, 0x31, 0x08, + 0xbc, 0xae, 0xfd, 0x60, 0x68, 0x17, 0x6e, 0x52, 0xf5, 0xb2, 0xfa, 0x6f, + 0xf6, 0x88, 0x10, 0x86 +}; + +/* HMAC-PKEY Test Vectors with key length: 32 bytes */ +/* Test vector for HMAC-sha1 */ +static const unsigned char hmac_sha1_vector32_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha1_vector32_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha1_vector32_out[] = { + 0xcd, 0xd5, 0xf8, 0x2c, 0x22, 0x5d, 0x6f, 0xba, 0x3f, 0x02, 0xb5, 0x4f, + 0x09, 0x02, 0x61, 0x1f, 0x4e, 0x5c, 0x33, 0x79 +}; +/* Test vector for HMAC-sha224 */ +static const unsigned char hmac_sha224_vector32_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha224_vector32_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha224_vector32_out[] = { + 0x52, 0x2b, 0x4f, 0x66, 0x53, 0x29, 0x49, 0xe0, 0x2f, 0x9c, 0x5e, 0x3a, + 0x15, 0x21, 0x8e, 0x6d, 0x87, 0xe6, 0x09, 0x3a, 0x4f, 0x51, 0xfe, 0xf9, + 0x3b, 0xa4, 0xad, 0xb1 +}; +/* Test vector for HMAC-sha256 */ +static const unsigned char hmac_sha256_vector32_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha256_vector32_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha256_vector32_out[] = { + 0x12, 0x4a, 0xd2, 0x37, 0xeb, 0xfd, 0x55, 0x97, 0x2e, 0x8a, 0x24, 0x9f, + 0x07, 0x84, 0x83, 0x02, 0x06, 0x53, 0xbf, 0x87, 0x97, 0x28, 0x4a, 0xd9, + 0x7a, 0x17, 0x7f, 0x85, 0x33, 0xe1, 0x55, 0x0d +}; +/* Test vector for HMAC-sha384 */ +static const unsigned char hmac_sha384_vector32_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha384_vector32_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha384_vector32_out[] = { + 0xd1, 0x87, 0xdd, 0x93, 0xa2, 0xa2, 0x30, 0x3f, 0x9b, 0x70, 0x60, 0xd9, + 0x1f, 0x1b, 0x9f, 0x66, 0x4e, 0xf4, 0x94, 0xf0, 0xe6, 0xcf, 0x30, 0x85, + 0xc3, 0xb5, 0xb3, 0x75, 0x26, 0xbb, 0x79, 0xf6, 0xe6, 0x04, 0x93, 0x36, + 0x11, 0x55, 0x5f, 0x03, 0x48, 0xc6, 0x01, 0x9d, 0x21, 0x08, 0xcf, 0x8a +}; +/* Test vector for HMAC-sha512 */ +static const unsigned char hmac_sha512_vector32_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha512_vector32_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha512_vector32_out[] = { + 0x42, 0x7b, 0xbd, 0xf7, 0x56, 0xb1, 0x64, 0x5a, 0x9f, 0xbe, 0x22, 0x2d, + 0xae, 0x37, 0xe1, 0x78, 0xba, 0xd9, 0xd5, 0x16, 0x81, 0x5f, 0x7a, 0xa2, + 0x6b, 0xbe, 0xab, 0xe5, 0xc4, 0xef, 0x1c, 0x10, 0x47, 0xa5, 0xfe, 0x46, + 0x25, 0x9a, 0x66, 0xc2, 0xfc, 0xc0, 0x10, 0xcc, 0xbc, 0xb5, 0xf9, 0x7a, + 0xe7, 0xa4, 0x8d, 0x8f, 0x83, 0xf3, 0x28, 0xb5, 0x1d, 0xe8, 0xd7, 0x93, + 0x6c, 0x6e, 0x4e, 0x7f +}; + +/* HMAC-PKEY Test Vectors with key length: 48 bytes */ +/* Test vector for HMAC-sha1 */ +static const unsigned char hmac_sha1_vector48_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha1_vector48_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha1_vector48_out[] = { + 0x68, 0x49, 0x0f, 0x9b, 0x53, 0x3c, 0x6d, 0x3b, 0x17, 0xa6, 0x5c, 0x1f, + 0x1f, 0x25, 0x4f, 0x57, 0x5b, 0x46, 0xed, 0x5b +}; +/* Test vector for HMAC-sha224 */ +static const unsigned char hmac_sha224_vector48_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha224_vector48_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha224_vector48_out[] = { + 0xc1, 0xda, 0x16, 0xc7, 0xb3, 0x00, 0x7b, 0x4a, 0x61, 0xd7, 0x32, 0x36, + 0x11, 0x8a, 0x5e, 0x2c, 0x7a, 0xce, 0xeb, 0xd0, 0x8a, 0xde, 0x3a, 0x2a, + 0xc6, 0xbb, 0x05, 0x41 +}; +/* Test vector for HMAC-sha256 */ +static const unsigned char hmac_sha256_vector48_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha256_vector48_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha256_vector48_out[] = { + 0x24, 0xfa, 0xc8, 0xa8, 0x0e, 0xe7, 0xb9, 0x50, 0x8c, 0x76, 0x2d, 0x06, + 0x32, 0xbb, 0xf3, 0x03, 0x64, 0xd2, 0x4e, 0x5e, 0x6d, 0x82, 0x5c, 0x08, + 0x5f, 0x70, 0x7c, 0x10, 0x5f, 0x14, 0x38, 0x01 +}; +/* Test vector for HMAC-sha384 */ +static const unsigned char hmac_sha384_vector48_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha384_vector48_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha384_vector48_out[] = { + 0x38, 0x3a, 0x9d, 0x78, 0xc4, 0x38, 0xa7, 0xec, 0x4a, 0x42, 0x27, 0x81, + 0xa7, 0x09, 0x40, 0xa0, 0x21, 0x06, 0x69, 0x68, 0xf6, 0x25, 0x76, 0x1e, + 0xe4, 0xe5, 0x8e, 0xb5, 0x26, 0x5f, 0xe0, 0x91, 0xf5, 0xa0, 0xd5, 0x90, + 0xb5, 0xbf, 0xe1, 0xa7, 0xb1, 0x72, 0x92, 0xce, 0x33, 0x94, 0x59, 0xa8 +}; +/* Test vector for HMAC-sha512 */ +static const unsigned char hmac_sha512_vector48_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha512_vector48_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha512_vector48_out[] = { + 0xf1, 0x0a, 0x03, 0x16, 0x65, 0x7d, 0x46, 0x18, 0x3b, 0x63, 0xb4, 0x5f, + 0x64, 0x66, 0x32, 0x91, 0x80, 0x9d, 0xef, 0xca, 0x31, 0x20, 0x69, 0x94, + 0xbe, 0x5d, 0xd0, 0xfb, 0xe8, 0x2f, 0xc3, 0x8b, 0x73, 0x33, 0x81, 0x37, + 0x59, 0x1d, 0xc9, 0xfe, 0x55, 0x66, 0xfc, 0xfc, 0x56, 0xe7, 0x68, 0x6e, + 0x76, 0x49, 0x35, 0x9a, 0x01, 0xea, 0x7f, 0x49, 0x43, 0x32, 0x99, 0x50, + 0x42, 0x34, 0xc0, 0x5c +}; + +/* HMAC-PKEY Test Vectors with key length: 64 bytes */ +/* Test vector for HMAC-sha1 */ +static const unsigned char hmac_sha1_vector64_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 + }; +static const unsigned char hmac_sha1_vector64_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha1_vector64_out[] = { + 0x3b, 0x05, 0xc6, 0x5c, 0x69, 0x6e, 0x87, 0x79, 0x69, 0x29, 0x8f, 0x92, + 0x9a, 0x6e, 0xb1, 0x57, 0x1a, 0xa0, 0xde, 0x32 +}; +/* Test vector for HMAC-sha224 */ +static const unsigned char hmac_sha224_vector64_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 + }; +static const unsigned char hmac_sha224_vector64_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha224_vector64_out[] = { + 0x8e, 0xc4, 0xdf, 0x9c, 0xee, 0xf0, 0x2c, 0x60, 0x32, 0x10, 0x71, 0x13, + 0xae, 0x9e, 0x62, 0xde, 0x08, 0x3b, 0x6e, 0x19, 0x27, 0x29, 0xbb, 0xa6, + 0xcc, 0x9a, 0x0c, 0x1d +}; +/* Test vector for HMAC-sha256 */ +static const unsigned char hmac_sha256_vector64_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 + }; +static const unsigned char hmac_sha256_vector64_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha256_vector64_out[] = { + 0x3f, 0x5b, 0x90, 0xaa, 0x07, 0x41, 0xcd, 0x5d, 0x6d, 0x75, 0xbe, 0xe8, + 0x27, 0x53, 0x19, 0x88, 0x9d, 0x8a, 0x97, 0x21, 0x6a, 0xbf, 0x79, 0x56, + 0x48, 0x16, 0x6f, 0x4b, 0xe1, 0xfc, 0xca, 0x46 +}; +/* Test vector for HMAC-sha384 */ +static const unsigned char hmac_sha384_vector64_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha384_vector64_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha384_vector64_out[] = { + 0xf6, 0xd9, 0xde, 0xa8, 0x12, 0xb5, 0x24, 0xf4, 0xf9, 0x92, 0xb0, 0x21, + 0x6b, 0xe3, 0x9f, 0x75, 0xba, 0x13, 0x32, 0xdc, 0x7a, 0xb6, 0xb9, 0xb2, + 0xe2, 0x93, 0x16, 0x9e, 0x26, 0x66, 0x04, 0x11, 0x59, 0x27, 0xd6, 0x27, + 0x73, 0xf2, 0x03, 0xf9, 0x36, 0x26, 0x5f, 0x86, 0x39, 0x3d, 0xba, 0xb3 +}; +/* Test vector for HMAC-sha512 */ +static const unsigned char hmac_sha512_vector64_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha512_vector64_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha512_vector64_out[] = { + 0xdb, 0xd0, 0xb1, 0xa2, 0x1b, 0x17, 0x2e, 0xe5, 0x40, 0xac, 0xe0, 0xd7, + 0xdb, 0x9a, 0xd7, 0xf0, 0xa4, 0x36, 0x18, 0x22, 0xb0, 0x1f, 0xb2, 0x16, + 0x03, 0xac, 0x38, 0x8c, 0xb0, 0xff, 0x56, 0xcf, 0xbc, 0x28, 0xf6, 0x14, + 0xa7, 0x69, 0x11, 0xfc, 0xe6, 0xd0, 0x60, 0x34, 0x16, 0x0c, 0x09, 0xd1, + 0xea, 0xfc, 0x6a, 0x91, 0x0e, 0x73, 0xa2, 0x42, 0x46, 0x36, 0x00, 0x38, + 0xbe, 0x8e, 0x96, 0xac +}; + +/* HMAC-PKEY Test Vectors with key length: 128 bytes */ +/* Test vector for HMAC-sha1 */ +static const unsigned char hmac_sha1_vector128_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha1_vector128_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha1_vector128_out[] = { + 0xf1, 0xa7, 0xc0, 0xb5, 0x5e, 0x8f, 0x2d, 0xad, 0x8c, 0xef, 0x9b, 0xbb, + 0x25, 0x23, 0x8a, 0xde, 0x54, 0xbe, 0x64, 0x65 +}; +/* Test vector for HMAC-sha224 */ +static const unsigned char hmac_sha224_vector128_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha224_vector128_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha224_vector128_out[] = { + 0xfd, 0x61, 0xee, 0x9c, 0xa7, 0xdc, 0xff, 0xb4, 0xcd, 0xf7, 0x1b, 0x87, + 0x29, 0xad, 0x6f, 0x2e, 0x53, 0xf6, 0x0f, 0xda, 0xe2, 0xe9, 0x16, 0xfd, + 0x84, 0xe8, 0x33, 0xb3 +}; +/* Test vector for HMAC-sha256 */ +static const unsigned char hmac_sha256_vector128_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha256_vector128_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha256_vector128_out[] = { + 0xd7, 0x2c, 0xcf, 0x87, 0x8c, 0x82, 0x62, 0x04, 0xe1, 0x87, 0xd5, 0xec, + 0xf8, 0xb1, 0x68, 0x64, 0x84, 0xaa, 0x78, 0xf5, 0x2c, 0x19, 0x8d, 0x42, + 0x26, 0xcd, 0x32, 0xf8, 0x85, 0xf9, 0xe2, 0x47 +}; +/* Test vector for HMAC-sha384 */ +static const unsigned char hmac_sha384_vector128_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha384_vector128_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha384_vector128_out[] = { + 0xd7, 0xda, 0xc5, 0x9d, 0x11, 0x4c, 0x8b, 0x61, 0x1f, 0x11, 0xba, 0xd6, + 0xe7, 0xdd, 0x0f, 0x75, 0xb0, 0x92, 0x7c, 0x2d, 0x17, 0xa1, 0x0a, 0x25, + 0xeb, 0xf0, 0x34, 0xed, 0x03, 0x42, 0xba, 0xbc, 0xc4, 0xa8, 0xb9, 0xbf, + 0x7e, 0x5f, 0x86, 0x82, 0xfc, 0xee, 0xa9, 0xcf, 0x29, 0xc6, 0x6c, 0x43 +}; +/* Test vector for HMAC-sha512 */ +static const unsigned char hmac_sha512_vector128_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha512_vector128_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha512_vector128_out[] = { + 0xb9, 0x0a, 0x43, 0x58, 0x8b, 0xea, 0x02, 0xa2, 0xc9, 0xc2, 0xb3, 0x20, + 0x9d, 0xb1, 0x01, 0xa2, 0x75, 0x61, 0x59, 0xbb, 0xc8, 0x4c, 0x18, 0x61, + 0x7d, 0xb6, 0xbb, 0xd0, 0x39, 0x67, 0xde, 0x21, 0x90, 0x12, 0x58, 0x67, + 0x73, 0x4a, 0x16, 0x1c, 0xab, 0xed, 0x31, 0x88, 0xc8, 0xaf, 0x8a, 0x2a, + 0xa5, 0x2f, 0x85, 0xe5, 0x8a, 0xe6, 0x42, 0xdc, 0x42, 0xf6, 0xf8, 0x36, + 0x83, 0xce, 0x0d, 0x32 +}; + +/* HMAC-PKEY Test Vectors with key length: 256 bytes */ +/* Test vector for HMAC-sha1 */ +static const unsigned char hmac_sha1_vector256_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha1_vector256_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha1_vector256_out[] = { + 0x7e, 0x8d, 0x03, 0x1b, 0x6e, 0x37, 0x2d, 0xef, 0x51, 0x9e, 0x6f, 0x18, + 0x2c, 0xec, 0xe9, 0x03, 0x4b, 0xc5, 0x22, 0x95 +}; +/* Test vector for HMAC-sha224 */ +static const unsigned char hmac_sha224_vector256_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha224_vector256_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha224_vector256_out[] = { + 0x40, 0x95, 0x55, 0x06, 0x8b, 0x42, 0x58, 0x86, 0xf5, 0x1f, 0xdf, 0x64, + 0x55, 0x5a, 0xc1, 0x68, 0xd6, 0x18, 0x79, 0x8e, 0xd1, 0x1c, 0xca, 0x95, + 0xbe, 0x82, 0xbc, 0xe7 +}; +/* Test vector for HMAC-sha256 */ +static const unsigned char hmac_sha256_vector256_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha256_vector256_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha256_vector256_out[] = { + 0x5e, 0x4b, 0x29, 0xd6, 0x3d, 0x42, 0xb8, 0xd2, 0x8d, 0x1b, 0xcb, 0x13, + 0x54, 0xbe, 0xd8, 0x13, 0x3b, 0xd2, 0x7e, 0xc3, 0x4f, 0x51, 0x08, 0x10, + 0xf7, 0x8d, 0xed, 0xfe, 0x03, 0x7e, 0x4d, 0xfb +}; +/* Test vector for HMAC-sha384 */ +static const unsigned char hmac_sha384_vector256_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha384_vector256_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha384_vector256_out[] = { + 0xc6, 0xa8, 0x7b, 0xdd, 0x49, 0x91, 0x8f, 0x86, 0x22, 0x80, 0xe6, 0x22, + 0x12, 0x67, 0x79, 0x69, 0x49, 0x22, 0xdd, 0x83, 0x73, 0x29, 0xf5, 0x1b, + 0xd6, 0xf4, 0x98, 0x5f, 0xc7, 0xf4, 0x73, 0x99, 0x66, 0x8b, 0xa5, 0x86, + 0xef, 0xc0, 0xce, 0x67, 0xc7, 0x1a, 0xa6, 0x4f, 0xad, 0x1f, 0xff, 0xf1 +}; +/* Test vector for HMAC-sha512 */ +static const unsigned char hmac_sha512_vector256_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha512_vector256_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha512_vector256_out[] = { + 0x2b, 0x00, 0x7b, 0xbe, 0x5e, 0xab, 0xff, 0xb9, 0x41, 0x1b, 0x23, 0x8d, + 0x42, 0xe6, 0x7e, 0x39, 0xb1, 0xbf, 0xa8, 0xb7, 0x01, 0xc1, 0x23, 0x9e, + 0x77, 0x9a, 0x4a, 0x3c, 0x0c, 0xbd, 0x49, 0xa1, 0x98, 0x2e, 0x3e, 0x64, + 0xfc, 0x7e, 0xb8, 0x2e, 0x29, 0xb6, 0xe0, 0xd5, 0x44, 0x8c, 0x65, 0xb0, + 0xa6, 0xa2, 0x96, 0x61, 0xfc, 0x97, 0xad, 0x7e, 0x53, 0xeb, 0x78, 0xb8, + 0xb2, 0x25, 0x85, 0xe1 +}; + +/* HMAC-PKEY Test Vectors with key length: 512 bytes */ +/* Test vector for HMAC-sha1 */ +static const unsigned char hmac_sha1_vector512_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha1_vector512_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha1_vector512_out[] = { + 0x95, 0xfe, 0x1b, 0x69, 0x2f, 0x08, 0x39, 0x0f, 0x76, 0x4d, 0x80, 0x5a, + 0xaa, 0x53, 0x14, 0xff, 0x67, 0x2a, 0x27, 0x6a +}; +/* Test vector for HMAC-sha224 */ +static const unsigned char hmac_sha224_vector512_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha224_vector512_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha224_vector512_out[] = { + 0xfd, 0x32, 0x22, 0xc2, 0xb9, 0x4d, 0x7c, 0x9d, 0x5f, 0x25, 0x65, 0xb0, + 0xc1, 0x7f, 0xf5, 0x26, 0xbd, 0xa1, 0xfa, 0xe5, 0x41, 0x30, 0x71, 0x62, + 0xc2, 0xe7, 0x55, 0xc4 +}; +/* Test vector for HMAC-sha256 */ +static const unsigned char hmac_sha256_vector512_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha256_vector512_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha256_vector512_out[] = { + 0x18, 0xbc, 0x94, 0x22, 0xa9, 0xf2, 0xf2, 0x91, 0x10, 0xea, 0x66, 0xbe, + 0x40, 0x3b, 0xdd, 0xc8, 0x88, 0x81, 0x91, 0xf5, 0x41, 0xf3, 0x89, 0x12, + 0xb8, 0x72, 0xf8, 0xdd, 0x7e, 0x5f, 0x9b, 0x3c +}; +/* Test vector for HMAC-sha384 */ +static const unsigned char hmac_sha384_vector512_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha384_vector512_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha384_vector512_out[] = { + 0xe9, 0x4a, 0xfd, 0xf5, 0x7f, 0xcb, 0x07, 0x4c, 0xca, 0x04, 0x70, 0x8f, + 0x10, 0x36, 0xac, 0xca, 0x2b, 0x44, 0xf8, 0xd0, 0x34, 0x48, 0x43, 0x4d, + 0x50, 0x95, 0x99, 0x70, 0x01, 0xc0, 0xce, 0x89, 0x1e, 0x7d, 0x05, 0xd2, + 0x0c, 0xcc, 0xbc, 0x2c, 0xed, 0x12, 0x3c, 0x6e, 0xfe, 0x51, 0x08, 0xb1 +}; +/* Test vector for HMAC-sha512 */ +static const unsigned char hmac_sha512_vector512_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha512_vector512_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha512_vector512_out[] = { + 0x70, 0xd4, 0xd1, 0x7b, 0x54, 0x2d, 0xef, 0x0c, 0x5a, 0x3f, 0x33, 0x93, + 0xaf, 0x16, 0xa7, 0x1c, 0xa6, 0x1e, 0x8c, 0x7d, 0xfe, 0xc1, 0x56, 0xa3, + 0xee, 0x70, 0x07, 0x3f, 0xd2, 0xc1, 0xce, 0x50, 0x89, 0x94, 0x1a, 0xe4, + 0x14, 0x6a, 0xab, 0x9c, 0x2b, 0x78, 0xae, 0x26, 0xd5, 0xdb, 0x98, 0x02, + 0x7e, 0x10, 0x52, 0xbe, 0x6c, 0x3b, 0x72, 0x49, 0x80, 0xa9, 0x95, 0x77, + 0x3f, 0xc0, 0xa9, 0xa5 +}; + +/* HMAC-PKEY Test Vectors with key length: 1024 bytes */ +/* Test vector for HMAC-sha1 */ +static const unsigned char hmac_sha1_vector1024_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha1_vector1024_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha1_vector1024_out[] = { + 0x06, 0x1c, 0xf4, 0x3f, 0x2d, 0x88, 0x46, 0x09, 0x2b, 0xb9, 0x98, 0xdb, + 0x4d, 0x3c, 0x0c, 0x19, 0x52, 0xc4, 0xe8, 0xff +}; +/* Test vector for HMAC-sha224 */ +static const unsigned char hmac_sha224_vector1024_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha224_vector1024_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha224_vector1024_out[] = { + 0x73, 0xc3, 0x8b, 0x20, 0xd0, 0xb9, 0xec, 0x82, 0x3b, 0x3f, 0x01, 0x04, + 0xb9, 0x3f, 0xe9, 0x9d, 0xb4, 0x13, 0xe9, 0xa5, 0xed, 0x74, 0x05, 0xc6, + 0x2e, 0x0d, 0xb2, 0x33 +}; +/* Test vector for HMAC-sha256 */ +static const unsigned char hmac_sha256_vector1024_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha256_vector1024_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha256_vector1024_out[] = { + 0x70, 0xc5, 0x8a, 0x7e, 0xfc, 0xee, 0xc5, 0x11, 0xb7, 0x27, 0x53, 0xca, + 0x63, 0x45, 0x4a, 0x18, 0x92, 0xbe, 0x9d, 0x76, 0xb8, 0xbd, 0xff, 0x15, + 0xef, 0x7f, 0x60, 0x73, 0x41, 0x55, 0xbf, 0xba +}; +/* Test vector for HMAC-sha384 */ +static const unsigned char hmac_sha384_vector1024_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha384_vector1024_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha384_vector1024_out[] = { + 0xdc, 0xf9, 0xa1, 0xfe, 0x96, 0x88, 0xe3, 0xd5, 0x86, 0x1d, 0xa9, 0x2e, + 0x65, 0xbe, 0x5e, 0xa3, 0x22, 0xbb, 0x74, 0x15, 0x97, 0x64, 0xfe, 0x96, + 0x13, 0x4b, 0xdc, 0x16, 0x7d, 0x44, 0x00, 0x98, 0xd8, 0xc3, 0x4a, 0xfc, + 0x31, 0x89, 0x9b, 0xe6, 0x42, 0x8d, 0x77, 0x27, 0x48, 0xdc, 0x73, 0xcd +}; +/* Test vector for HMAC-sha512 */ +static const unsigned char hmac_sha512_vector1024_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_sha512_vector1024_in[] = { + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x74 +}; +static const unsigned char hmac_sha512_vector1024_out[] = { + 0x4b, 0xd1, 0x18, 0x1e, 0x8e, 0x68, 0x4a, 0xc6, 0xef, 0xc1, 0xeb, 0x89, + 0xe2, 0xf2, 0x18, 0xef, 0x47, 0xc8, 0xc0, 0xfd, 0xa0, 0x5d, 0x5e, 0x24, + 0xf1, 0x4f, 0x69, 0x40, 0xf9, 0xc4, 0x20, 0x47, 0xdb, 0x66, 0x22, 0xde, + 0x62, 0x21, 0xb1, 0x60, 0x50, 0x37, 0xae, 0xa9, 0x92, 0x2d, 0x36, 0x4a, + 0x6f, 0xcd, 0xb7, 0x9b, 0xf4, 0x46, 0x73, 0xb7, 0xb5, 0x25, 0x1e, 0x7b, + 0x5b, 0x75, 0x73, 0x89 +}; + +/* HMAC-PKEY Test Vectors for mulptipart with key length: 1024 bytes */ +/* Test vector for HMAC-sha1 */ +static const unsigned char hmac_vector1024_multiblock_key[] = { + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, + 0x41, 0x42, 0x43, 0x44 +}; +static const unsigned char hmac_vector1024_multiblock_in[] = { + 0x4d, 0x5a, 0x52, 0x54, 0x6f, 0x74, 0x6b, 0x4e, 0x72, 0x6b, 0x58, 0x4f, + 0x58, 0x38, 0x76, 0x58, 0x41, 0x77, 0x4e, 0x75, 0x0a, 0x6f, 0x37, 0x4a, + 0x32, 0x4d, 0x53, 0x68, 0x4c, 0x77, 0x71, 0x5a, 0x79, 0x77, 0x66, 0x62, + 0x52, 0x79, 0x45, 0x75, 0x46, 0x0a, 0x36, 0x34, 0x4f, 0x44, 0x74, 0x78, + 0x6e, 0x4b, 0x59, 0x50, 0x6b, 0x6b, 0x42, 0x67, 0x39, 0x52, 0x70, 0x39, + 0x62, 0x4d, 0x0a, 0x69, 0x47, 0x6f, 0x42, 0x6f, 0x36, 0x4d, 0x7a, 0x6a, + 0x47, 0x71, 0x78, 0x6d, 0x44, 0x4c, 0x35, 0x35, 0x5a, 0x51, 0x6e, 0x0a, + 0x61, 0x37, 0x62, 0x50, 0x64, 0x66, 0x4a, 0x63, 0x74, 0x77, 0x6a, 0x4e, + 0x65, 0x74, 0x4b, 0x77, 0x75, 0x71, 0x6c, 0x6c, 0x0a, 0x34, 0x4f, 0x76, + 0x51, 0x77, 0x6d, 0x30, 0x71, 0x4c, 0x67, 0x39, 0x4a, 0x75, 0x52, 0x30, + 0x64, 0x71, 0x65, 0x6e, 0x61, 0x0a, 0x66, 0x44, 0x69, 0x4e, 0x58, 0x71, + 0x47, 0x55, 0x76, 0x31, 0x6a, 0x65, 0x30, 0x39, 0x56, 0x4f, 0x6a, 0x32, + 0x45, 0x47, 0x0a, 0x69, 0x6e, 0x7a, 0x73, 0x4f, 0x70, 0x58, 0x37, 0x79, + 0x49, 0x6f, 0x4b, 0x4b, 0x52, 0x36, 0x47, 0x6d, 0x44, 0x35, 0x61, 0x0a, + 0x4e, 0x66, 0x67, 0x50, 0x31, 0x46, 0x70, 0x6b, 0x71, 0x4f, 0x53, 0x66, + 0x39, 0x71, 0x43, 0x31, 0x53, 0x37, 0x46, 0x52, 0x0a, 0x47, 0x41, 0x62, + 0x44, 0x61, 0x62, 0x7a, 0x66, 0x56, 0x36, 0x6b, 0x62, 0x47, 0x62, 0x5a, + 0x4d, 0x4b, 0x44, 0x6f, 0x70, 0x0a, 0x71, 0x70, 0x77, 0x78, 0x33, 0x4e, + 0x62, 0x48, 0x4b, 0x64, 0x6d, 0x68, 0x56, 0x71, 0x58, 0x62, 0x4d, 0x77, + 0x43, 0x35, 0x0a, 0x73, 0x72, 0x6b, 0x38, 0x6b, 0x4d, 0x45, 0x61, 0x75, + 0x63, 0x78, 0x47, 0x5a, 0x5a, 0x43, 0x6a, 0x4c, 0x41, 0x64, 0x46, 0x0a, + 0x43, 0x30, 0x64, 0x4b, 0x66, 0x33, 0x51, 0x65, 0x77, 0x6f, 0x36, 0x63, + 0x64, 0x43, 0x6f, 0x38, 0x54, 0x6a, 0x73, 0x74, 0x0a, 0x61, 0x6b, 0x46, + 0x50, 0x78, 0x4a, 0x74, 0x69, 0x70, 0x63, 0x54, 0x79, 0x72, 0x6e, 0x6a, + 0x4d, 0x57, 0x45, 0x6c, 0x36, 0x0a, 0x50, 0x50, 0x54, 0x6a, 0x6b, 0x32, + 0x66, 0x71, 0x32, 0x37, 0x52, 0x35, 0x57, 0x50, 0x75, 0x70, 0x71, 0x66, + 0x4c, 0x73, 0x0a, 0x6c, 0x58, 0x68, 0x34, 0x42, 0x43, 0x58, 0x7a, 0x7a, + 0x75, 0x56, 0x57, 0x57, 0x52, 0x31, 0x58, 0x6e, 0x46, 0x66, 0x77, 0x0a, + 0x6d, 0x42, 0x6c, 0x37, 0x52, 0x48, 0x35, 0x48, 0x42, 0x74, 0x6b, 0x78, + 0x32, 0x5a, 0x30, 0x57, 0x61, 0x58, 0x37, 0x33, 0x0a, 0x50, 0x48, 0x4c, + 0x59, 0x4c, 0x78, 0x5a, 0x43, 0x35, 0x4a, 0x34, 0x72, 0x31, 0x68, 0x5a, + 0x5a, 0x36, 0x4f, 0x34, 0x51, 0x0a, 0x48, 0x68, 0x42, 0x32, 0x75, 0x62, + 0x74, 0x70, 0x50, 0x65, 0x4a, 0x47, 0x76, 0x56, 0x6d, 0x67, 0x6e, 0x52, + 0x4d, 0x46, 0x0a, 0x75, 0x6f, 0x51, 0x7a, 0x6e, 0x63, 0x43, 0x32, 0x6f, + 0x4f, 0x47, 0x6a, 0x6e, 0x61, 0x71, 0x33, 0x46, 0x6e, 0x36, 0x64, 0x0a, + 0x46, 0x75, 0x52, 0x37, 0x6d, 0x66, 0x4a, 0x78, 0x6c, 0x79, 0x75, 0x73, + 0x46, 0x4c, 0x54, 0x4d, 0x37, 0x32, 0x62, 0x46, 0x0a, 0x43, 0x4f, 0x4c, + 0x47, 0x77, 0x6e, 0x73, 0x65, 0x6d, 0x42, 0x51, 0x59, 0x72, 0x61, 0x47, + 0x34, 0x34, 0x63, 0x32, 0x4e, 0x0a, 0x63, 0x44, 0x46, 0x4f, 0x74, 0x64, + 0x53, 0x36, 0x58, 0x75, 0x30, 0x61, 0x52, 0x55, 0x68, 0x51, 0x76, 0x70, + 0x4e, 0x37, 0x0a, 0x76, 0x4b, 0x31, 0x36, 0x56, 0x59, 0x69, 0x4f, 0x31, + 0x38, 0x68, 0x72, 0x6c, 0x6e, 0x75, 0x56, 0x67, 0x4f, 0x61, 0x50, 0x0a, + 0x6c, 0x47, 0x79, 0x53, 0x74, 0x63, 0x38, 0x6c, 0x41, 0x56, 0x31, 0x52, + 0x42, 0x68, 0x63, 0x6f, 0x65, 0x72, 0x38, 0x39, 0x0a, 0x51, 0x59, 0x6f, + 0x48, 0x71, 0x32, 0x6b, 0x53, 0x70, 0x6e, 0x78, 0x56, 0x61, 0x75, 0x41, + 0x52, 0x58, 0x36, 0x73, 0x54, 0x0a, 0x5a, 0x6c, 0x4c, 0x71, 0x32, 0x42, + 0x50, 0x69, 0x38, 0x70, 0x32, 0x69, 0x30, 0x31, 0x39, 0x44, 0x48, 0x59, + 0x6f, 0x52, 0x0a, 0x70, 0x4f, 0x58, 0x73, 0x72, 0x72, 0x46, 0x52, 0x43, + 0x65, 0x4c, 0x47, 0x4c, 0x48, 0x73, 0x53, 0x72, 0x66, 0x5a, 0x67, 0x0a, + 0x37, 0x64, 0x57, 0x6c, 0x73, 0x32, 0x67, 0x70, 0x71, 0x6a, 0x41, 0x70, + 0x30, 0x52, 0x56, 0x63, 0x71, 0x4c, 0x63, 0x63, 0x0a, 0x6f, 0x69, 0x66, + 0x48, 0x55, 0x33, 0x31, 0x61, 0x6e, 0x39, 0x41, 0x45, 0x48, 0x5a, 0x32, + 0x51, 0x48, 0x4f, 0x64, 0x65, 0x0a, 0x51, 0x73, 0x57, 0x48, 0x62, 0x74, + 0x77, 0x78, 0x6d, 0x74, 0x7a, 0x70, 0x45, 0x4a, 0x61, 0x67, 0x39, 0x45, + 0x73, 0x69, 0x0a, 0x50, 0x64, 0x32, 0x66, 0x54, 0x36, 0x75, 0x42, 0x30, + 0x6b, 0x64, 0x6a, 0x7a, 0x53, 0x47, 0x6a, 0x6f, 0x73, 0x6f, 0x63, 0x0a, + 0x57, 0x66, 0x44, 0x6a, 0x37, 0x4d, 0x75, 0x41, 0x31, 0x38, 0x70, 0x67, + 0x48, 0x65, 0x57, 0x65, 0x52, 0x35, 0x45, 0x51, 0x0a, 0x5a, 0x62, 0x6e, + 0x75, 0x4f, 0x77, 0x33, 0x63, 0x78, 0x4e, 0x73, 0x51, 0x39, 0x74, 0x58, + 0x56, 0x50, 0x46, 0x61, 0x50, 0x0a, 0x6d, 0x6f, 0x7a, 0x47, 0x61, 0x6c, + 0x53, 0x6e, 0x67, 0x31, 0x30, 0x34, 0x6d, 0x38, 0x6b, 0x33, 0x57, 0x75, + 0x45, 0x50, 0x0a, 0x79, 0x31, 0x76, 0x32, 0x33, 0x41, 0x78, 0x46, 0x78, + 0x43, 0x75, 0x44, 0x75, 0x53, 0x34, 0x57, 0x44, 0x31, 0x46, 0x4b, 0x0a, + 0x6b, 0x53, 0x36, 0x4f, 0x65, 0x49, 0x53, 0x6a, 0x53, 0x62, 0x7a, 0x34, + 0x53, 0x4b, 0x53, 0x65, 0x70, 0x33, 0x4d, 0x31, 0x0a, 0x6d, 0x52, 0x46, + 0x44, 0x42, 0x62, 0x65, 0x68, 0x73, 0x61, 0x42, 0x54, 0x5a, 0x55, 0x78, + 0x4f, 0x78, 0x78, 0x78, 0x32, 0x0a, 0x37, 0x38, 0x39, 0x6c, 0x6d, 0x74, + 0x75, 0x6f, 0x39, 0x75, 0x69, 0x33, 0x68, 0x46, 0x52, 0x65, 0x50, 0x78, + 0x4d, 0x36, 0x0a, 0x5a, 0x53, 0x6e, 0x48, 0x61, 0x34, 0x48, 0x4d, 0x45, + 0x69, 0x54, 0x62, 0x36, 0x71, 0x6c, 0x73, 0x64, 0x48, 0x76, 0x38, 0x0a, + 0x68, 0x50, 0x79, 0x7a, 0x51, 0x75, 0x6f, 0x74, 0x76, 0x34, 0x30, 0x4e, + 0x64, 0x33, 0x32, 0x34, 0x45, 0x6e, 0x56, 0x36, 0x0a, 0x30, 0x4f, 0x66, + 0x66, 0x56, 0x6a, 0x56, 0x55, 0x4b, 0x4f, 0x7a, 0x43, 0x32, 0x45, 0x54, + 0x76, 0x6e, 0x4d, 0x65, 0x79, 0x0a, 0x6c, 0x68, 0x32, 0x71, 0x73, 0x32, + 0x36, 0x48, 0x6b, 0x4c, 0x67, 0x4b, 0x4c, 0x61, 0x43, 0x64, 0x4c, 0x6c, + 0x34, 0x43, 0x0a, 0x58, 0x50, 0x74, 0x64, 0x63, 0x63, 0x36, 0x55, 0x4c, + 0x46, 0x4a, 0x4a, 0x58, 0x66, 0x42, 0x76, 0x66, 0x62, 0x72, 0x47, 0x0a, + 0x76, 0x71, 0x51, 0x57, 0x35, 0x57, 0x78, 0x63, 0x58, 0x70, 0x37, 0x47, + 0x47, 0x6d, 0x35, 0x76, 0x5a, 0x35, 0x31, 0x6e, 0x0a, 0x4e, 0x33, 0x42, + 0x34, 0x45, 0x49, 0x59, 0x68, 0x39, 0x43, 0x34, 0x52, 0x59, 0x77, 0x4f, + 0x46, 0x35, 0x45, 0x58, 0x50, 0x0a, 0x31, 0x4b, 0x6a, 0x56, 0x6e, 0x39, + 0x43, 0x6e, 0x41, 0x31, 0x6a, 0x37, 0x51, 0x35, 0x31, 0x77, 0x62, 0x55, + 0x53, 0x4c, 0x0a, 0x54, 0x43, 0x34, 0x73, 0x52, 0x59, 0x61, 0x37, 0x52, + 0x56, 0x49, 0x57, 0x5a, 0x32, 0x41, 0x39, 0x36, 0x31, 0x66, 0x75, 0x0a, + 0x66, 0x31, 0x46, 0x34, 0x36, 0x71, 0x75, 0x58, 0x63, 0x63, 0x4c, 0x6d, + 0x33, 0x41, 0x30, 0x68, 0x75, 0x6b, 0x45, 0x50, 0x0a, 0x36, 0x37, 0x61, + 0x32, 0x55, 0x54, 0x34, 0x71, 0x38, 0x64, 0x6a, 0x59, 0x70, 0x54, 0x6d, + 0x54, 0x64, 0x43, 0x56, 0x58, 0x0a, 0x31, 0x50, 0x4a, 0x65, 0x4e, 0x41, + 0x71, 0x6b, 0x68, 0x4a, 0x50, 0x49, 0x50, 0x6f, 0x47, 0x30, 0x37, 0x33, + 0x73, 0x42, 0x0a, 0x32, 0x52, 0x34, 0x6a, 0x75, 0x42, 0x54, 0x62, 0x56, + 0x79, 0x32, 0x47, 0x39, 0x63, 0x64, 0x78, 0x74, 0x55, 0x69, 0x41, 0x0a, + 0x54, 0x36, 0x76, 0x79, 0x35, 0x5a, 0x4e, 0x70, 0x59, 0x4f, 0x78, 0x44, + 0x59, 0x66, 0x48, 0x56, 0x6b, 0x45, 0x73, 0x72, 0x0a, 0x35, 0x32, 0x4d, + 0x36, 0x6e, 0x45, 0x30, 0x69, 0x72, 0x52, 0x50, 0x75, 0x58, 0x71, 0x67, + 0x69, 0x39, 0x61, 0x66, 0x35, 0x0a, 0x64, 0x74, 0x36, 0x7a, 0x49, 0x78, + 0x41, 0x46, 0x74, 0x46, 0x66, 0x79, 0x31, 0x56, 0x59, 0x49, 0x76, 0x6f, + 0x6f, 0x4e, 0x0a, 0x31, 0x6a, 0x57, 0x55, 0x77, 0x74, 0x72, 0x59, 0x61, + 0x44, 0x6a, 0x50, 0x64, 0x59, 0x32, 0x4e, 0x33, 0x71, 0x4b, 0x6f, 0x0a, + 0x4c, 0x35, 0x57, 0x46, 0x55, 0x51, 0x71, 0x33, 0x72, 0x46, 0x77, 0x5a, + 0x54, 0x71, 0x70, 0x42, 0x74, 0x77, 0x57, 0x31, 0x0a, 0x5a, 0x67, 0x47, + 0x4e, 0x70, 0x50, 0x53, 0x4a, 0x31, 0x48, 0x43, 0x6d, 0x34, 0x78, 0x6d, + 0x50, 0x44, 0x6a, 0x32, 0x74, 0x0a, 0x63, 0x32, 0x35, 0x6c, 0x32, 0x54, + 0x6b, 0x71, 0x79, 0x38, 0x38, 0x63, 0x37, 0x6f, 0x35, 0x54, 0x4c, 0x73, + 0x4d, 0x74, 0x0a, 0x61, 0x62, 0x72, 0x31, 0x72, 0x78, 0x76, 0x30, 0x61, + 0x4b, 0x65, 0x44, 0x75, 0x42, 0x77, 0x64, 0x62, 0x35, 0x6d, 0x42, 0x0a, + 0x68, 0x45, 0x35, 0x61, 0x76, 0x70, 0x55, 0x46, 0x44, 0x69, 0x42, 0x33, + 0x70, 0x35, 0x43, 0x63, 0x52, 0x48, 0x36, 0x41, 0x0a, 0x4f, 0x52, 0x67, + 0x63, 0x6f, 0x53, 0x4d, 0x45, 0x48, 0x67, 0x42, 0x32, 0x66, 0x43, 0x68, + 0x36, 0x43, 0x4b, 0x78, 0x47, 0x0a, 0x38, 0x5a, 0x4f, 0x46, 0x73, 0x76, + 0x67, 0x73, 0x4c, 0x76, 0x62, 0x32, 0x61, 0x34, 0x6e, 0x47, 0x68, 0x55, + 0x49, 0x51, 0x0a, 0x6c, 0x77, 0x73, 0x74, 0x41, 0x48, 0x78, 0x64, 0x69, + 0x54, 0x32, 0x78, 0x61, 0x61, 0x38, 0x4a, 0x68, 0x42, 0x62, 0x42, 0x0a, + 0x45, 0x48, 0x67, 0x52, 0x70, 0x55, 0x53, 0x4e, 0x58, 0x73, 0x35, 0x31, + 0x4c, 0x35, 0x4b, 0x32, 0x77, 0x6a, 0x49, 0x34, 0x0a, 0x45, 0x62, 0x66, + 0x4f, 0x42, 0x42, 0x46, 0x43, 0x33, 0x4a, 0x61, 0x7a, 0x77, 0x49, 0x4b, + 0x48, 0x77, 0x72, 0x64, 0x57, 0x0a, 0x39, 0x5a, 0x50, 0x5a, 0x34, 0x6e, + 0x4a, 0x50, 0x67, 0x58, 0x77, 0x31, 0x38, 0x64, 0x70, 0x52, 0x4e, 0x71, + 0x46, 0x43, 0x0a, 0x78, 0x53, 0x77, 0x34, 0x4a, 0x49, 0x46, 0x55, 0x6f, + 0x4d, 0x64, 0x77, 0x4a, 0x41, 0x61, 0x65, 0x42, 0x7a, 0x44, 0x70, 0x0a, + 0x4e, 0x4c, 0x6d, 0x35, 0x68, 0x33, 0x59, 0x77, 0x77, 0x57, 0x67, 0x4f, + 0x61, 0x6c, 0x47, 0x58, 0x59, 0x42, 0x73, 0x48, 0x0a, 0x54, 0x52, 0x4a, + 0x39, 0x6e, 0x35, 0x59, 0x65, 0x58, 0x73, 0x4f, 0x72, 0x54, 0x41, 0x78, + 0x37, 0x73, 0x79, 0x63, 0x54, 0x0a, 0x62, 0x64, 0x44, 0x71, 0x6c, 0x45, + 0x6f, 0x62, 0x4c, 0x39, 0x38, 0x35, 0x61, 0x72, 0x6b, 0x54, 0x65, 0x31, + 0x43, 0x4c, 0x0a, 0x68, 0x43, 0x62, 0x56, 0x5a, 0x35, 0x35, 0x74, 0x70, + 0x68, 0x48, 0x56, 0x42, 0x37, 0x37, 0x38, 0x6d, 0x6e, 0x43, 0x36, 0x0a, + 0x59, 0x6c, 0x6e, 0x5a, 0x43, 0x38, 0x52, 0x47, 0x56, 0x33, 0x35, 0x46, + 0x78, 0x56, 0x70, 0x54, 0x68, 0x6b, 0x43, 0x48, 0x0a, 0x64, 0x53, 0x39, + 0x49, 0x41, 0x6e, 0x41, 0x41, 0x61, 0x4f, 0x6d, 0x63, 0x61, 0x6b, 0x63, + 0x6c, 0x45, 0x47, 0x63, 0x35, 0x0a, 0x38, 0x54, 0x77, 0x52, 0x6d, 0x53, + 0x46, 0x41, 0x42, 0x34, 0x69, 0x35, 0x51, 0x65, 0x49, 0x41, 0x59, 0x45, + 0x42, 0x52, 0x0a, 0x6f, 0x4e, 0x4c, 0x37, 0x43, 0x34, 0x44, 0x6a, 0x35, + 0x38, 0x4b, 0x6f, 0x67, 0x54, 0x6f, 0x66, 0x32, 0x61, 0x30, 0x66, 0x0a, + 0x6b, 0x67, 0x34, 0x4f, 0x79, 0x51, 0x41, 0x30, 0x45, 0x5a, 0x49, 0x56, + 0x39, 0x31, 0x6f, 0x4a, 0x51, 0x46, 0x65, 0x48, 0x0a, 0x4b, 0x35, 0x48, + 0x77, 0x38, 0x44, 0x34, 0x4b, 0x62, 0x79, 0x4c, 0x50, 0x4d, 0x79, 0x4c, + 0x56, 0x53, 0x6f, 0x6d, 0x65, 0x0a, 0x42, 0x63, 0x46, 0x79, 0x38, 0x47, + 0x5a, 0x50, 0x78, 0x51, 0x78, 0x35, 0x5a, 0x61, 0x5a, 0x6c, 0x45, 0x4c, + 0x4b, 0x76, 0x0a, 0x6a, 0x4b, 0x4d, 0x56, 0x5a, 0x52, 0x62, 0x48, 0x55, + 0x77, 0x50, 0x47, 0x50, 0x62, 0x44, 0x43, 0x49, 0x63, 0x6b, 0x65, 0x0a, + 0x48, 0x64, 0x41, 0x78, 0x64, 0x76, 0x50, 0x71, 0x35, 0x4a, 0x43, 0x67, + 0x39, 0x59, 0x72, 0x57, 0x62, 0x48, 0x30, 0x4b, 0x0a, 0x6c, 0x6f, 0x67, + 0x33, 0x53, 0x70, 0x5a, 0x45, 0x59, 0x68, 0x57, 0x59, 0x6b, 0x62, 0x35, + 0x75, 0x65, 0x6c, 0x50, 0x59, 0x0a, 0x33, 0x52, 0x35, 0x46, 0x41, 0x51, + 0x6b, 0x42, 0x46, 0x4a, 0x46, 0x6c, 0x39, 0x47, 0x53, 0x4d, 0x6b, 0x53, + 0x4b, 0x6f, 0x0a, 0x55, 0x77, 0x57, 0x41, 0x32, 0x52, 0x49, 0x63, 0x36, + 0x4d, 0x71, 0x4a, 0x54, 0x46, 0x55, 0x4f, 0x56, 0x49, 0x42, 0x34, 0x0a, + 0x68, 0x5a, 0x34, 0x6b, 0x51, 0x64, 0x53, 0x4b, 0x71, 0x78, 0x4d, 0x58, + 0x45, 0x37, 0x79, 0x67, 0x44, 0x30, 0x6c, 0x55, 0x0a, 0x46, 0x6a, 0x67, + 0x7a, 0x6c, 0x47, 0x4e, 0x4d, 0x65, 0x71, 0x68, 0x7a, 0x44, 0x71, 0x57, + 0x4d, 0x34, 0x31, 0x38, 0x68, 0x0a, 0x43, 0x31, 0x59, 0x6d, 0x69, 0x38, + 0x77, 0x38, 0x6c, 0x69, 0x51, 0x64, 0x62, 0x42, 0x6a, 0x64, 0x62, 0x37, + 0x42, 0x33, 0x0a, 0x63, 0x6b, 0x54, 0x32, 0x75, 0x53, 0x66, 0x34, 0x4e, + 0x6a, 0x58, 0x43, 0x72, 0x5a, 0x35, 0x58, 0x6f, 0x35, 0x6e, 0x38, 0x0a, + 0x38, 0x67, 0x4b, 0x47, 0x72, 0x78, 0x4e, 0x56, 0x4f, 0x63, 0x35, 0x34, + 0x53, 0x48, 0x4a, 0x6b, 0x49, 0x30, 0x35, 0x66, 0x0a, 0x66, 0x36, 0x4f, + 0x69, 0x75, 0x51, 0x56, 0x6c, 0x4d, 0x46, 0x35, 0x65, 0x53, 0x37, 0x6c, + 0x42, 0x53, 0x4f, 0x63, 0x4e, 0x0a, 0x6a, 0x49, 0x39, 0x34, 0x49, 0x4a, + 0x32, 0x35, 0x42, 0x4c, 0x31, 0x4d, 0x66, 0x66, 0x4b, 0x78, 0x30, 0x51, + 0x72, 0x6c, 0x0a, 0x79, 0x57, 0x4c, 0x46, 0x4d, 0x50, 0x44, 0x4e, 0x52, + 0x51, 0x7a, 0x38, 0x6d, 0x56, 0x44, 0x58, 0x41, 0x76, 0x4e, 0x4d, 0x0a, + 0x65, 0x72, 0x50, 0x49, 0x41, 0x49, 0x44, 0x47, 0x4a, 0x64, 0x58, 0x61, + 0x33, 0x31, 0x71, 0x50, 0x32, 0x6d, 0x73, 0x56, 0x0a, 0x32, 0x78, 0x49, + 0x69, 0x52, 0x4c, 0x79, 0x64, 0x4f, 0x66, 0x49, 0x4f, 0x41, 0x31, 0x4b, + 0x6d, 0x70, 0x71, 0x79, 0x5a, 0x0a, 0x48, 0x77, 0x6f, 0x57, 0x70, 0x30, + 0x54, 0x37, 0x6e, 0x54, 0x42, 0x6f, 0x4b, 0x62, 0x77, 0x38, 0x62, 0x46, + 0x42, 0x32, 0x0a, 0x48, 0x5a, 0x75, 0x54, 0x36, 0x30, 0x77, 0x6e, 0x79, + 0x45, 0x5a, 0x54, 0x4a, 0x4d, 0x68, 0x67, 0x48, 0x4d, 0x69, 0x51, 0x0a, + 0x48, 0x34, 0x65, 0x58, 0x6e, 0x51, 0x6d, 0x6a, 0x41, 0x57, 0x4f, 0x42, + 0x34, 0x50, 0x44, 0x35, 0x44, 0x50, 0x66, 0x72, 0x0a, 0x46, 0x4b, 0x67, + 0x48, 0x35, 0x58, 0x34, 0x36, 0x72, 0x70, 0x42, 0x51, 0x65, 0x73, 0x51, + 0x41, 0x30, 0x50, 0x75, 0x33, 0x0a, 0x4a, 0x58, 0x59, 0x38, 0x72, 0x78, + 0x71, 0x6b, 0x63, 0x76, 0x34, 0x73, 0x58, 0x51, 0x63, 0x73, 0x6e, 0x57, + 0x52, 0x65, 0x0a, 0x4f, 0x6e, 0x43, 0x67, 0x73, 0x48, 0x59, 0x33, 0x54, + 0x50, 0x71, 0x72, 0x69, 0x6b, 0x74, 0x7a, 0x73, 0x64, 0x50, 0x54, 0x0a, + 0x44, 0x59, 0x4b, 0x52, 0x39, 0x34, 0x5a, 0x48, 0x49, 0x6f, 0x76, 0x32, + 0x6c, 0x55, 0x70, 0x65, 0x39, 0x65, 0x34, 0x42, 0x0a, 0x39, 0x59, 0x73, + 0x6d, 0x76, 0x42, 0x6d, 0x78, 0x49, 0x44, 0x43, 0x6f, 0x30, 0x54, 0x38, + 0x6c, 0x45, 0x49, 0x4b, 0x5a, 0x0a, 0x53, 0x45, 0x6d, 0x34, 0x72, 0x65, + 0x31, 0x39, 0x55, 0x37, 0x75, 0x41, 0x74, 0x51, 0x72, 0x62, 0x34, 0x45, + 0x78, 0x79, 0x0a, 0x65, 0x4a, 0x6e, 0x4b, 0x33, 0x61, 0x4d, 0x4a, 0x6e, + 0x70, 0x65, 0x4d, 0x61, 0x7a, 0x69, 0x72, 0x50, 0x73, 0x37, 0x6b, 0x0a, + 0x49, 0x59, 0x6a, 0x38, 0x37, 0x32, 0x45, 0x6f, 0x61, 0x49, 0x44, 0x45, + 0x6b, 0x4b, 0x59, 0x7a, 0x64, 0x34, 0x66, 0x51, 0x0a, 0x4f, 0x53, 0x71, + 0x6a, 0x55, 0x43, 0x58, 0x77, 0x37, 0x72, 0x76, 0x6f, 0x69, 0x30, 0x66, + 0x64, 0x4e, 0x69, 0x6f, 0x55, 0x0a, 0x41, 0x4f, 0x4f, 0x52, 0x78, 0x7a, + 0x49, 0x48, 0x6b, 0x64, 0x36, 0x76, 0x68, 0x61, 0x52, 0x5a, 0x4f, 0x48, + 0x50, 0x69, 0x0a, 0x4d, 0x78, 0x4e, 0x70, 0x66, 0x6a, 0x74, 0x4d, 0x4b, + 0x39, 0x67, 0x61, 0x6a, 0x35, 0x36, 0x61, 0x73, 0x67, 0x37, 0x55, 0x0a, + 0x35, 0x5a, 0x33, 0x37, 0x38, 0x51, 0x4f, 0x74, 0x79, 0x68, 0x57, 0x44, + 0x34, 0x31, 0x54, 0x68, 0x73, 0x49, 0x36, 0x69, 0x0a, 0x4a, 0x76, 0x53, + 0x7a, 0x6f, 0x53, 0x75, 0x62, 0x65, 0x55, 0x6d, 0x53, 0x63, 0x4d, 0x61, + 0x76, 0x6b, 0x4c, 0x55, 0x41, 0x0a, 0x51, 0x6e, 0x4c, 0x6d, 0x32, 0x79, + 0x7a, 0x4a, 0x45, 0x71, 0x6c, 0x78, 0x4c, 0x59, 0x54, 0x78, 0x79, 0x38, + 0x65, 0x39, 0x0a, 0x47, 0x6b, 0x64, 0x56, 0x6f, 0x4c, 0x38, 0x59, 0x6b, + 0x32, 0x30, 0x6d, 0x58, 0x62, 0x55, 0x49, 0x31, 0x57, 0x47, 0x77, 0x0a, + 0x66, 0x73, 0x30, 0x4b, 0x51, 0x75, 0x53, 0x31, 0x6f, 0x47, 0x41, 0x57, + 0x73, 0x69, 0x52, 0x6f, 0x34, 0x4c, 0x48, 0x74, 0x0a, 0x6f, 0x4c, 0x71, + 0x75, 0x32, 0x57, 0x61, 0x7a, 0x72, 0x69, 0x72, 0x4f, 0x49, 0x5a, 0x53, + 0x6a, 0x33, 0x36, 0x6f, 0x46, 0x0a, 0x38, 0x76, 0x52, 0x74, 0x77, 0x6b, + 0x66, 0x69, 0x42, 0x64, 0x79, 0x73, 0x76, 0x31, 0x4a, 0x4d, 0x56, 0x69, + 0x66, 0x44, 0x0a, 0x57, 0x69, 0x49, 0x46, 0x44, 0x38, 0x78, 0x41, 0x67, + 0x42, 0x79, 0x63, 0x6e, 0x68, 0x63, 0x66, 0x4c, 0x70, 0x5a, 0x4b, 0x0a, + 0x56, 0x45, 0x4c, 0x49, 0x42, 0x68, 0x57, 0x6c, 0x70, 0x79, 0x37, 0x78, + 0x76, 0x78, 0x66, 0x6b, 0x46, 0x32, 0x4a, 0x46, 0x0a, 0x73, 0x4f, 0x31, + 0x72, 0x78, 0x47, 0x73, 0x75, 0x74, 0x76, 0x65, 0x58, 0x77, 0x45, 0x76, + 0x47, 0x79, 0x34, 0x42, 0x6d, 0x0a, 0x73, 0x38, 0x6b, 0x6c, 0x5a, 0x35, + 0x4e, 0x53, 0x6e, 0x71, 0x6e, 0x58, 0x57, 0x65, 0x46, 0x53, 0x30, 0x64, + 0x56, 0x56, 0x0a, 0x4d, 0x69, 0x78, 0x55, 0x44, 0x51, 0x68, 0x54, 0x58, + 0x46, 0x45, 0x70, 0x48, 0x69, 0x4f, 0x39, 0x38, 0x68, 0x70, 0x6c, 0x0a, + 0x62, 0x48, 0x6b, 0x63, 0x69, 0x75, 0x6c, 0x65, 0x44, 0x6f, 0x49, 0x62, + 0x49, 0x38, 0x77, 0x4f, 0x58, 0x5a, 0x47, 0x58, 0x0a, 0x58, 0x7a, 0x4b, + 0x48, 0x44, 0x52, 0x34, 0x61, 0x38, 0x61, 0x64, 0x72, 0x38, 0x56, 0x43, + 0x45, 0x4b, 0x4f, 0x52, 0x6a, 0x0a, 0x38, 0x6f, 0x65, 0x58, 0x69, 0x7a, + 0x63, 0x46, 0x64, 0x73, 0x5a, 0x4d, 0x6c, 0x33, 0x64, 0x67, 0x53, 0x65, + 0x37, 0x44, 0x0a, 0x58, 0x76, 0x4f, 0x6c, 0x6f, 0x55, 0x73, 0x47, 0x76, + 0x6f, 0x6d, 0x77, 0x52, 0x67, 0x4b, 0x56, 0x61, 0x79, 0x64, 0x33, 0x0a, + 0x63, 0x37, 0x78, 0x50, 0x4d, 0x6b, 0x6c, 0x56, 0x32, 0x43, 0x4d, 0x4f, + 0x76, 0x37, 0x78, 0x44, 0x4f, 0x5a, 0x52, 0x4b, 0x0a, 0x70, 0x74, 0x6a, + 0x68, 0x37, 0x64, 0x48, 0x6f, 0x69, 0x6f, 0x61, 0x36, 0x33, 0x46, 0x4d, + 0x49, 0x47, 0x57, 0x49, 0x30, 0x0a, 0x62, 0x4f, 0x72, 0x70, 0x64, 0x33, + 0x39, 0x61, 0x36, 0x68, 0x31, 0x50, 0x4e, 0x62, 0x69, 0x49, 0x43, 0x6d, + 0x34, 0x76, 0x0a, 0x4a, 0x58, 0x78, 0x5a, 0x69, 0x33, 0x6a, 0x6c, 0x6d, + 0x71, 0x79, 0x4b, 0x4c, 0x4b, 0x49, 0x48, 0x36, 0x73, 0x6c, 0x6e, 0x0a, + 0x50, 0x71, 0x72, 0x62, 0x6c, 0x30, 0x79, 0x65, 0x6a, 0x33, 0x4a, 0x6d, + 0x70, 0x51, 0x50, 0x51, 0x71, 0x34, 0x73, 0x37, 0x0a, 0x4e, 0x48, 0x49, + 0x34, 0x6f, 0x39, 0x6a, 0x70, 0x42, 0x66, 0x72, 0x75, 0x46, 0x62, 0x71, + 0x79, 0x37, 0x45, 0x4a, 0x6d, 0x0a, 0x51, 0x66, 0x48, 0x66, 0x58, 0x31, + 0x57, 0x57, 0x55, 0x37, 0x67, 0x75, 0x69, 0x57, 0x31, 0x70, 0x48, 0x69, + 0x49, 0x49, 0x0a, 0x6f, 0x43, 0x37, 0x69, 0x69, 0x52, 0x39, 0x41, 0x54, + 0x37, 0x59, 0x74, 0x66, 0x6d, 0x53, 0x43, 0x68, 0x6b, 0x47, 0x33, 0x0a, + 0x78, 0x39, 0x50, 0x68, 0x30, 0x66, 0x6d, 0x63, 0x42, 0x4d, 0x31, 0x39, + 0x45, 0x70, 0x64, 0x34, 0x41, 0x38, 0x4d, 0x46, 0x0a, 0x57, 0x64, 0x57, + 0x37, 0x67, 0x6e, 0x69, 0x43, 0x58, 0x4c, 0x41, 0x75, 0x4e, 0x44, 0x69, + 0x71, 0x4d, 0x48, 0x6d, 0x6f, 0x0a, 0x4e, 0x4b, 0x44, 0x53, 0x79, 0x6a, + 0x66, 0x47, 0x47, 0x55, 0x55, 0x30, 0x69, 0x7a, 0x54, 0x44, 0x6f, 0x77, + 0x49, 0x4e, 0x0a, 0x6c, 0x4d, 0x35, 0x50, 0x50, 0x74, 0x42, 0x72, 0x71, + 0x56, 0x57, 0x37, 0x54, 0x77, 0x58, 0x50, 0x51, 0x4f, 0x70, 0x47, 0x0a, + 0x78, 0x35, 0x53, 0x45, 0x36, 0x79, 0x52, 0x65, 0x4c, 0x39, 0x5a, 0x76, + 0x62, 0x38, 0x4e, 0x57, 0x6a, 0x6f, 0x50, 0x30, 0x0a, 0x7a, 0x62, 0x57, + 0x6d, 0x79, 0x73, 0x6d, 0x56, 0x50, 0x72, 0x74, 0x65, 0x35, 0x49, 0x4a, + 0x51, 0x73, 0x31, 0x4b, 0x43, 0x0a, 0x73, 0x52, 0x72, 0x39, 0x62, 0x6f, + 0x6a, 0x30, 0x4d, 0x41, 0x4b, 0x70, 0x55, 0x76, 0x55, 0x51, 0x33, 0x65, + 0x75, 0x52, 0x0a, 0x68, 0x45, 0x62, 0x43, 0x38, 0x4d, 0x70, 0x30, 0x55, + 0x4b, 0x30, 0x4e, 0x44, 0x74, 0x75, 0x32, 0x53, 0x46, 0x64, 0x4b, 0x0a, + 0x78, 0x34, 0x67, 0x4c, 0x76, 0x35, 0x6c, 0x52, 0x57, 0x61, 0x4c, 0x6d, + 0x6f, 0x67, 0x5a, 0x4c, 0x30, 0x68, 0x48, 0x46, 0x0a, 0x76, 0x61, 0x32, + 0x43, 0x4a, 0x4e, 0x56, 0x5a, 0x4c, 0x38, 0x59, 0x66, 0x7a, 0x71, 0x36, + 0x78, 0x38, 0x76, 0x69, 0x6f, 0x0a, 0x36, 0x68, 0x30, 0x6b, 0x36, 0x41, + 0x4f, 0x31, 0x52, 0x6d, 0x76, 0x69, 0x73, 0x4e, 0x39, 0x6f, 0x52, 0x41, + 0x72, 0x55, 0x0a, 0x70, 0x53, 0x59, 0x35, 0x61, 0x41, 0x50, 0x6a, 0x50, + 0x75, 0x75, 0x58, 0x74, 0x59, 0x30, 0x55, 0x62, 0x45, 0x51, 0x7a, 0x0a, + 0x44, 0x30, 0x33, 0x67, 0x64, 0x6e, 0x7a, 0x5a, 0x41, 0x67, 0x52, 0x45, + 0x79, 0x54, 0x53, 0x4a, 0x78, 0x70, 0x67, 0x34, 0x0a, 0x35, 0x67, 0x43, + 0x35, 0x4d, 0x71, 0x6f, 0x34, 0x33, 0x4f, 0x70, 0x37, 0x33, 0x68, 0x31, + 0x6f, 0x61, 0x54, 0x32, 0x7a, 0x0a, 0x63, 0x58, 0x32, 0x57, 0x6b, 0x32, + 0x58, 0x30, 0x70, 0x4a, 0x51, 0x63, 0x5a, 0x67, 0x47, 0x4d, 0x39, 0x78, + 0x33, 0x76, 0x0a, 0x4a, 0x6c, 0x64, 0x67, 0x35, 0x61, 0x51, 0x57, 0x6f, + 0x36, 0x51, 0x38, 0x56, 0x78, 0x62, 0x37, 0x57, 0x42, 0x76, 0x6d, 0x0a, + 0x62, 0x61, 0x37, 0x56, 0x35, 0x30, 0x6f, 0x62, 0x4e, 0x77, 0x77, 0x54, + 0x51, 0x52, 0x41, 0x31, 0x61, 0x77, 0x79, 0x43, 0x0a, 0x76, 0x57, 0x54, + 0x37, 0x4a, 0x5a, 0x52, 0x69, 0x31, 0x30, 0x78, 0x31, 0x4d, 0x42, 0x78, + 0x4b, 0x53, 0x35, 0x65, 0x76, 0x0a, 0x42, 0x69, 0x43, 0x78, 0x65, 0x6e, + 0x4a, 0x75, 0x30, 0x67, 0x68, 0x30, 0x6c, 0x48, 0x4e, 0x76, 0x43, 0x50, + 0x6f, 0x6b, 0x0a, 0x33, 0x5a, 0x36, 0x62, 0x57, 0x74, 0x43, 0x43, 0x6a, + 0x69, 0x46, 0x74, 0x61, 0x72, 0x67, 0x62, 0x6c, 0x30, 0x36, 0x6f, 0x0a, + 0x74, 0x70, 0x51, 0x41, 0x50, 0x63, 0x43, 0x62, 0x63, 0x66, 0x57, 0x62, + 0x64, 0x63, 0x41, 0x45, 0x4c, 0x6a, 0x57, 0x51, 0x0a, 0x4b, 0x68, 0x49, + 0x7a, 0x31, 0x4a, 0x41, 0x58, 0x55, 0x69, 0x56, 0x54, 0x30, 0x4a, 0x6e, + 0x32, 0x42, 0x51, 0x4e, 0x71, 0x0a, 0x41, 0x6d, 0x52, 0x38, 0x47, 0x5a, + 0x33, 0x62, 0x78, 0x63, 0x34, 0x35, 0x37, 0x6c, 0x7a, 0x76, 0x67, 0x4f, + 0x6d, 0x66, 0x0a, 0x65, 0x61, 0x79, 0x32, 0x30, 0x31, 0x58, 0x74, 0x61, + 0x4f, 0x53, 0x66, 0x46, 0x4c, 0x30, 0x44, 0x49, 0x5a, 0x59, 0x6d, 0x0a, + 0x41, 0x39, 0x75, 0x4b, 0x58, 0x53, 0x74, 0x79, 0x6c, 0x63, 0x36, 0x30, + 0x50, 0x54, 0x6b, 0x37, 0x6e, 0x4d, 0x36, 0x57, 0x0a, 0x64, 0x67, 0x42, + 0x43, 0x73, 0x37, 0x57, 0x52, 0x66, 0x74, 0x59, 0x65, 0x32, 0x41, 0x6a, + 0x4e, 0x51, 0x53, 0x37, 0x79, 0x0a, 0x4d, 0x33, 0x45, 0x45, 0x59, 0x4c, + 0x76, 0x42, 0x76, 0x52, 0x71, 0x4a, 0x4d, 0x6c, 0x5a, 0x36, 0x65, 0x48, + 0x34, 0x65, 0x0a, 0x74, 0x6d, 0x66, 0x48, 0x76, 0x6e, 0x75, 0x41, 0x47, + 0x79, 0x31, 0x38, 0x33, 0x44, 0x50, 0x6b, 0x4c, 0x77, 0x49, 0x76, 0x0a, + 0x6c, 0x61, 0x6b, 0x45, 0x66, 0x44, 0x79, 0x66, 0x77, 0x39, 0x77, 0x37, + 0x42, 0x76, 0x31, 0x53, 0x65, 0x47, 0x76, 0x4d, 0x0a, 0x69, 0x48, 0x62, + 0x35, 0x6b, 0x51, 0x67, 0x62, 0x45, 0x47, 0x39, 0x45, 0x6d, 0x5a, 0x32, + 0x44, 0x73, 0x72, 0x37, 0x62, 0x0a, 0x32, 0x6e, 0x55, 0x36, 0x68, 0x4b, + 0x62, 0x43, 0x45, 0x34, 0x72, 0x37, 0x75, 0x55, 0x79, 0x56, 0x76, 0x73, + 0x41, 0x72, 0x0a, 0x73, 0x69, 0x6f, 0x57, 0x62, 0x54, 0x72, 0x67, 0x41, + 0x70, 0x75, 0x6b, 0x6f, 0x4c, 0x71, 0x6c, 0x43, 0x47, 0x6e, 0x49, 0x0a, + 0x70, 0x71, 0x33, 0x70, 0x74, 0x31, 0x42, 0x45, 0x39, 0x75, 0x53, 0x44, + 0x55, 0x6e, 0x4c, 0x4c, 0x4c, 0x46, 0x7a, 0x37, 0x0a, 0x6b, 0x4e, 0x45, + 0x68, 0x6c, 0x76, 0x33, 0x43, 0x55, 0x51, 0x6a, 0x71, 0x75, 0x48, 0x6f, + 0x51, 0x69, 0x69, 0x79, 0x56, 0x0a, 0x74, 0x6b, 0x53, 0x79, 0x52, 0x76, + 0x4d, 0x6a, 0x50, 0x6e, 0x7a, 0x7a, 0x6f, 0x79, 0x47, 0x49, 0x35, 0x55, + 0x67, 0x71, 0x0a, 0x75, 0x68, 0x34, 0x4b, 0x63, 0x59, 0x69, 0x56, 0x7a, + 0x79, 0x36, 0x37, 0x42, 0x33, 0x33, 0x69, 0x31, 0x51, 0x54, 0x6f, 0x0a, + 0x63, 0x62, 0x53, 0x4b, 0x4c, 0x32, 0x66, 0x4c, 0x64, 0x56, 0x41, 0x74, + 0x63, 0x56, 0x6c, 0x43, 0x6a, 0x4a, 0x58, 0x78, 0x0a, 0x71, 0x34, 0x75, + 0x6a, 0x45, 0x62, 0x47, 0x47, 0x4e, 0x37, 0x4d, 0x49, 0x31, 0x44, 0x47, + 0x6a, 0x4f, 0x76, 0x4f, 0x63, 0x0a, 0x63, 0x4d, 0x55, 0x54, 0x68, 0x71, + 0x4c, 0x70, 0x47, 0x36, 0x67, 0x6a, 0x32, 0x4e, 0x64, 0x52, 0x6d, 0x6b, + 0x6e, 0x37, 0x0a, 0x32, 0x65, 0x5a, 0x57, 0x79, 0x59, 0x33, 0x39, 0x37, + 0x49, 0x54, 0x50, 0x76, 0x71, 0x57, 0x4a, 0x69, 0x44, 0x76, 0x43, 0x0a, + 0x4e, 0x47, 0x71, 0x49, 0x6e, 0x6a, 0x6b, 0x6e, 0x67, 0x67, 0x68, 0x79, + 0x7a, 0x34, 0x64, 0x67, 0x52, 0x4b, 0x4b, 0x61, 0x0a, 0x31, 0x4e, 0x57, + 0x50, 0x6b, 0x74, 0x39, 0x55, 0x67, 0x62, 0x50, 0x35, 0x31, 0x30, 0x52, + 0x41, 0x4a, 0x6d, 0x49, 0x73, 0x0a, 0x59, 0x35, 0x55, 0x70, 0x6b, 0x6c, + 0x57, 0x61, 0x4a, 0x50, 0x66, 0x4f, 0x4c, 0x72, 0x69, 0x34, 0x75, 0x44, + 0x76, 0x61, 0x0a, 0x6c, 0x75, 0x7a, 0x36, 0x54, 0x76, 0x39, 0x4a, 0x58, + 0x61, 0x4f, 0x32, 0x46, 0x36, 0x6f, 0x50, 0x58, 0x58, 0x43, 0x51, 0x0a, + 0x5a, 0x32, 0x46, 0x38, 0x61, 0x51, 0x6f, 0x59, 0x7a, 0x43, 0x39, 0x6a, + 0x56, 0x72, 0x6d, 0x46, 0x63, 0x4e, 0x4e, 0x38, 0x0a, 0x6d, 0x59, 0x52, + 0x4c, 0x6c, 0x35, 0x64, 0x38, 0x76, 0x6e, 0x35, 0x54, 0x6e, 0x41, 0x6b, + 0x35, 0x6c, 0x7a, 0x77, 0x73, 0x0a, 0x66, 0x76, 0x50, 0x41, 0x69, 0x51, + 0x70, 0x53, 0x76, 0x57, 0x39, 0x76, 0x55, 0x63, 0x4b, 0x42, 0x34, 0x48, + 0x46, 0x6c, 0x0a, 0x30, 0x6f, 0x4c, 0x4f, 0x39, 0x37, 0x59, 0x6f, 0x55, + 0x4b, 0x7a, 0x4f, 0x38, 0x47, 0x45, 0x4a, 0x6e, 0x30, 0x79, 0x62, 0x0a, + 0x66, 0x45, 0x54, 0x68, 0x4a, 0x45, 0x68, 0x66, 0x55, 0x57, 0x53, 0x73, + 0x32, 0x4a, 0x58, 0x69, 0x68, 0x6a, 0x67, 0x5a, 0x0a, 0x43, 0x48, 0x50, + 0x32, 0x50, 0x52, 0x41, 0x30, 0x69, 0x52, 0x78, 0x6b, 0x52, 0x32, 0x6e, + 0x6a, 0x67, 0x5a, 0x70, 0x48, 0x0a, 0x5a, 0x42, 0x57, 0x39, 0x6e, 0x63, + 0x7a, 0x6e, 0x7a, 0x4a, 0x51, 0x49, 0x53, 0x6b, 0x59, 0x4c, 0x37, 0x39, + 0x73, 0x75, 0x0a, 0x78, 0x46, 0x4c, 0x66, 0x45, 0x38, 0x6f, 0x45, 0x44, + 0x34, 0x57, 0x4e, 0x33, 0x66, 0x65, 0x64, 0x6a, 0x72, 0x65, 0x76, 0x0a, + 0x41, 0x55, 0x4c, 0x63, 0x50, 0x6b, 0x4e, 0x76, 0x33, 0x34, 0x44, 0x41, + 0x4d, 0x39, 0x6e, 0x5a, 0x4d, 0x6f, 0x75, 0x66, 0x0a, 0x43, 0x31, 0x61, + 0x55, 0x56, 0x73, 0x76, 0x30, 0x72, 0x52, 0x57, 0x62, 0x46, 0x55, 0x39, + 0x49, 0x31, 0x51, 0x4a, 0x63, 0x0a, 0x50, 0x32, 0x42, 0x7a, 0x64, 0x59, + 0x39, 0x66, 0x78, 0x4e, 0x59, 0x67, 0x64, 0x4e, 0x6a, 0x75, 0x49, 0x4f, + 0x78, 0x35, 0x0a, 0x37, 0x70, 0x31, 0x4d, 0x6a, 0x58, 0x75, 0x4c, 0x55, + 0x4e, 0x59, 0x34, 0x35, 0x44, 0x6d, 0x58, 0x57, 0x36, 0x73, 0x4c, 0x0a, + 0x30, 0x4d, 0x6e, 0x49, 0x75, 0x62, 0x5a, 0x67, 0x6a, 0x61, 0x61, 0x53, + 0x68, 0x59, 0x45, 0x35, 0x48, 0x69, 0x62, 0x49, 0x0a, 0x48, 0x53, 0x48, + 0x64, 0x4c, 0x4d, 0x64, 0x72, 0x72, 0x59, 0x34, 0x65, 0x30, 0x73, 0x4e, + 0x57, 0x38, 0x44, 0x47, 0x76, 0x0a, 0x52, 0x35, 0x4d, 0x67, 0x54, 0x61, + 0x76, 0x62, 0x34, 0x78, 0x45, 0x55, 0x35, 0x64, 0x66, 0x50, 0x66, 0x69, + 0x65, 0x43, 0x0a, 0x37, 0x72, 0x76, 0x66, 0x46, 0x74, 0x67, 0x77, 0x53, + 0x51, 0x50, 0x42, 0x49, 0x57, 0x53, 0x61, 0x58, 0x6c, 0x5a, 0x69, 0x0a, + 0x42, 0x61, 0x48, 0x49, 0x54, 0x6b, 0x48, 0x41, 0x56, 0x49, 0x77, 0x65, + 0x31, 0x6d, 0x50, 0x4e, 0x33, 0x6c, 0x79, 0x62, 0x0a, 0x4a, 0x31, 0x41, + 0x53, 0x66, 0x34, 0x51, 0x6e, 0x56, 0x64, 0x68, 0x64, 0x49, 0x52, 0x30, + 0x54, 0x39, 0x57, 0x6f, 0x66, 0x0a, 0x52, 0x36, 0x34, 0x65, 0x52, 0x52, + 0x4f, 0x51, 0x4d, 0x43, 0x42, 0x66, 0x46, 0x51, 0x4f, 0x34, 0x32, 0x76, + 0x52, 0x6f, 0x0a, 0x41, 0x59, 0x65, 0x39, 0x4a, 0x49, 0x79, 0x4b, 0x31, + 0x64, 0x75, 0x4a, 0x6e, 0x6a, 0x4f, 0x4e, 0x44, 0x67, 0x61, 0x41, 0x0a, + 0x43, 0x38, 0x51, 0x5a, 0x52, 0x71, 0x37, 0x4c, 0x78, 0x63, 0x70, 0x6f, + 0x59, 0x34, 0x52, 0x43, 0x6c, 0x61, 0x32, 0x73, 0x0a, 0x55, 0x44, 0x72, + 0x46, 0x38, 0x52, 0x36, 0x32, 0x6b, 0x58, 0x35, 0x39, 0x33, 0x71, 0x31, + 0x6c, 0x47, 0x56, 0x64, 0x56, 0x0a, 0x58, 0x6c, 0x47, 0x62, 0x51, 0x59, + 0x45, 0x74, 0x6d, 0x38, 0x49, 0x30, 0x4c, 0x76, 0x61, 0x74, 0x71, 0x76, + 0x47, 0x79, 0x0a, 0x37, 0x77, 0x72, 0x36, 0x7a, 0x50, 0x6f, 0x76, 0x55, + 0x34, 0x45, 0x72, 0x72, 0x4c, 0x38, 0x53, 0x70, 0x6a, 0x51, 0x37, 0x0a, + 0x30, 0x67, 0x73, 0x6c, 0x35, 0x66, 0x71, 0x63, 0x62, 0x32, 0x55, 0x76, + 0x74, 0x55, 0x69, 0x58, 0x59, 0x38, 0x50, 0x56, 0x0a, 0x51, 0x67, 0x50, + 0x69, 0x67, 0x6a, 0x54, 0x79, 0x64, 0x48, 0x39, 0x32, 0x56, 0x56, 0x6e, + 0x6b, 0x5a, 0x74, 0x54, 0x55, 0x0a, 0x4c, 0x5a, 0x4c, 0x59, 0x69, 0x5a, + 0x74, 0x68, 0x4c, 0x42, 0x37, 0x35, 0x7a, 0x6e, 0x68, 0x38, 0x4b, 0x69, + 0x55, 0x6e, 0x0a, 0x58, 0x75, 0x51, 0x63, 0x4f, 0x37, 0x55, 0x75, 0x42, + 0x38, 0x58, 0x78, 0x51, 0x6a, 0x67, 0x4e, 0x38, 0x62, 0x42, 0x71, 0x0a, + 0x50, 0x52, 0x63, 0x71, 0x4d, 0x49, 0x43, 0x36, 0x38, 0x6f, 0x48, 0x39, + 0x6b, 0x36, 0x34, 0x75, 0x63, 0x6d, 0x33, 0x6c, 0x0a, 0x37, 0x44, 0x42, + 0x67, 0x34, 0x4c, 0x70, 0x63, 0x5a, 0x7a, 0x73, 0x31, 0x57, 0x79, 0x6b, + 0x61, 0x67, 0x56, 0x6c, 0x4e, 0x0a, 0x6a, 0x54, 0x6b, 0x65, 0x31, 0x51, + 0x31, 0x77, 0x49, 0x69, 0x4e, 0x50, 0x71, 0x71, 0x61, 0x76, 0x31, 0x6b, + 0x6f, 0x31, 0x0a, 0x45, 0x73, 0x74, 0x51, 0x30, 0x53, 0x53, 0x77, 0x6a, + 0x31, 0x59, 0x4c, 0x71, 0x64, 0x63, 0x32, 0x7a, 0x72, 0x54, 0x56, 0x0a, + 0x66, 0x71, 0x68, 0x78, 0x50, 0x4b, 0x44, 0x4a, 0x31, 0x48, 0x46, 0x36, + 0x62, 0x48, 0x6f, 0x4b, 0x46, 0x63, 0x53, 0x6e, 0x0a, 0x59, 0x55, 0x32, + 0x47, 0x7a, 0x50, 0x79, 0x50, 0x44, 0x35, 0x7a, 0x46, 0x69, 0x31, 0x74, + 0x39, 0x66, 0x79, 0x44, 0x39, 0x0a, 0x68, 0x62, 0x55, 0x39, 0x67, 0x77, + 0x67, 0x37, 0x5a, 0x68, 0x38, 0x69, 0x53, 0x4d, 0x32, 0x59, 0x54, 0x47, + 0x33, 0x76, 0x0a, 0x72, 0x6b, 0x48, 0x4d, 0x42, 0x73, 0x5a, 0x44, 0x44, + 0x49, 0x31, 0x44, 0x6d, 0x67, 0x5a, 0x52, 0x50, 0x63, 0x69, 0x48, 0x0a, + 0x76, 0x31, 0x44, 0x74, 0x58, 0x4a, 0x4d, 0x4c, 0x62, 0x45, 0x31, 0x54, + 0x62, 0x6b, 0x51, 0x61, 0x6c, 0x6b, 0x41, 0x59, 0x0a, 0x32, 0x4c, 0x69, + 0x78, 0x49, 0x71, 0x6b, 0x39, 0x31, 0x58, 0x6c, 0x71, 0x4a, 0x45, 0x69, + 0x31, 0x54, 0x31, 0x61, 0x72, 0x0a, 0x62, 0x7a, 0x6b, 0x59, 0x51, 0x77, + 0x4f, 0x51, 0x41, 0x79, 0x4f, 0x44, 0x61, 0x38, 0x6d, 0x46, 0x4a, 0x70, + 0x61, 0x4c, 0x0a, 0x6b, 0x56, 0x50, 0x45, 0x6d, 0x54, 0x64, 0x51, 0x5a, + 0x38, 0x72, 0x48, 0x71, 0x43, 0x53, 0x30, 0x6b, 0x4e, 0x65, 0x4b, 0x0a, + 0x57, 0x42, 0x6b, 0x6b, 0x7a, 0x55, 0x38, 0x4b, 0x79, 0x45, 0x31, 0x4d, + 0x66, 0x4e, 0x47, 0x71, 0x52, 0x58, 0x49, 0x52, 0x0a, 0x6c, 0x69, 0x75, + 0x4a, 0x62, 0x71, 0x6a, 0x30, 0x45, 0x4d, 0x72, 0x75, 0x76, 0x48, 0x4e, + 0x69, 0x30, 0x4d, 0x49, 0x36, 0x0a, 0x51, 0x32, 0x30, 0x30, 0x36, 0x45, + 0x78, 0x68, 0x62, 0x38, 0x71, 0x57, 0x43, 0x38, 0x6c, 0x56, 0x56, 0x46, + 0x46, 0x46, 0x0a, 0x35, 0x78, 0x35, 0x72, 0x67, 0x64, 0x66, 0x6c, 0x70, + 0x6f, 0x6c, 0x54, 0x63, 0x5a, 0x38, 0x50, 0x72, 0x61, 0x37, 0x6c, 0x0a, + 0x56, 0x37, 0x4b, 0x79, 0x58, 0x62, 0x6f, 0x62, 0x44, 0x4f, 0x63, 0x4b, + 0x73, 0x36, 0x41, 0x44, 0x63, 0x52, 0x52, 0x6e, 0x0a, 0x52, 0x39, 0x47, + 0x61, 0x33, 0x4c, 0x45, 0x6e, 0x4b, 0x46, 0x64, 0x46, 0x36, 0x35, 0x43, + 0x46, 0x6b, 0x64, 0x79, 0x6c, 0x0a, 0x47, 0x54, 0x68, 0x73, 0x30, 0x68, + 0x33, 0x4a, 0x71, 0x6e, 0x47, 0x36, 0x57, 0x44, 0x47, 0x77, 0x6a, 0x42, + 0x47, 0x75, 0x0a, 0x6e, 0x76, 0x5a, 0x75, 0x58, 0x62, 0x36, 0x67, 0x62, + 0x74, 0x61, 0x72, 0x68, 0x69, 0x58, 0x63, 0x49, 0x51, 0x43, 0x33, 0x0a, + 0x62, 0x33, 0x57, 0x37, 0x7a, 0x46, 0x6c, 0x67, 0x4a, 0x6c, 0x4f, 0x6d, + 0x73, 0x51, 0x56, 0x6d, 0x41, 0x61, 0x4e, 0x72, 0x0a, 0x4f, 0x54, 0x69, + 0x72, 0x6d, 0x64, 0x77, 0x76, 0x56, 0x52, 0x6e, 0x71, 0x31, 0x48, 0x45, + 0x65, 0x58, 0x43, 0x4c, 0x4e, 0x0a, 0x36, 0x6d, 0x63, 0x57, 0x6a, 0x79, + 0x4a, 0x69, 0x37, 0x59, 0x32, 0x50, 0x30, 0x79, 0x65, 0x4c, 0x64, 0x69, + 0x50, 0x36, 0x0a, 0x50, 0x42, 0x6b, 0x70, 0x5a, 0x6c, 0x4a, 0x65, 0x4d, + 0x61, 0x6b, 0x6e, 0x56, 0x31, 0x6d, 0x4a, 0x48, 0x62, 0x45, 0x38, 0x0a, + 0x59, 0x47, 0x55, 0x54, 0x6d, 0x51, 0x31, 0x43, 0x61, 0x33, 0x57, 0x61, + 0x5a, 0x63, 0x4e, 0x53, 0x32, 0x78, 0x61, 0x47, 0x0a, 0x32, 0x56, 0x78, + 0x35, 0x4e, 0x6f, 0x68, 0x57, 0x70, 0x56, 0x45, 0x6e, 0x4c, 0x61, 0x5a, + 0x68, 0x71, 0x55, 0x6b, 0x38, 0x0a, 0x59, 0x41, 0x32, 0x51, 0x4d, 0x6d, + 0x32, 0x64, 0x6c, 0x6e, 0x68, 0x54, 0x39, 0x75, 0x72, 0x37, 0x6a, 0x34, + 0x76, 0x30, 0x0a, 0x35, 0x4d, 0x4c, 0x31, 0x4e, 0x77, 0x68, 0x32, 0x49, + 0x72, 0x62, 0x61, 0x57, 0x6e, 0x71, 0x68, 0x4b, 0x62, 0x38, 0x4d, 0x0a, + 0x6f, 0x62, 0x74, 0x76, 0x42, 0x79, 0x50, 0x72, 0x7a, 0x49, 0x68, 0x62, + 0x76, 0x30, 0x55, 0x6f, 0x4f, 0x58, 0x53, 0x72, 0x0a, 0x54, 0x38, 0x46, + 0x68, 0x69, 0x6e, 0x7a, 0x74, 0x33, 0x59, 0x32, 0x49, 0x41, 0x58, 0x74, + 0x41, 0x33, 0x45, 0x57, 0x66, 0x0a, 0x36, 0x36, 0x52, 0x34, 0x34, 0x7a, + 0x4e, 0x64, 0x49, 0x30, 0x72, 0x55, 0x30, 0x47, 0x65, 0x6d, 0x61, 0x4f, + 0x57, 0x76, 0x0a, 0x77, 0x30, 0x67, 0x32, 0x4c, 0x36, 0x43, 0x48, 0x72, + 0x36, 0x64, 0x49, 0x6c, 0x53, 0x31, 0x43, 0x41, 0x42, 0x56, 0x39, 0x0a, + 0x63, 0x63, 0x68, 0x64, 0x58, 0x45, 0x6d, 0x63, 0x69, 0x36, 0x57, 0x67, + 0x78, 0x55, 0x76, 0x51, 0x37, 0x62, 0x6c, 0x79, 0x0a, 0x63, 0x65, 0x5a, + 0x38, 0x68, 0x30, 0x51, 0x4e, 0x79, 0x53, 0x56, 0x50, 0x63, 0x57, 0x49, + 0x46, 0x77, 0x4a, 0x51, 0x52, 0x0a, 0x46, 0x39, 0x32, 0x6d, 0x61, 0x4f, + 0x45, 0x34, 0x58, 0x74, 0x47, 0x34, 0x73, 0x53, 0x70, 0x68, 0x53, 0x68, + 0x38, 0x47, 0x0a, 0x68, 0x53, 0x74, 0x58, 0x62, 0x67, 0x47, 0x72, 0x69, + 0x30, 0x4f, 0x71, 0x33, 0x67, 0x52, 0x42, 0x4c, 0x78, 0x44, 0x50, 0x0a, + 0x37, 0x43, 0x6d, 0x79, 0x75, 0x65, 0x45, 0x43, 0x6f, 0x52, 0x59, 0x30, + 0x54, 0x39, 0x77, 0x43, 0x75, 0x66, 0x63, 0x6e, 0x0a, 0x51, 0x71, 0x75, + 0x36, 0x63, 0x34, 0x53, 0x57, 0x42, 0x75, 0x47, 0x55, 0x59, 0x48, 0x34, + 0x62, 0x58, 0x75, 0x54, 0x6d, 0x0a, 0x75, 0x53, 0x31, 0x38, 0x4f, 0x55, + 0x62, 0x71, 0x72, 0x6e, 0x71, 0x35, 0x66, 0x39, 0x44, 0x44, 0x46, 0x74, + 0x78, 0x33, 0x0a, 0x75, 0x43, 0x4f, 0x51, 0x34, 0x72, 0x67, 0x53, 0x59, + 0x72, 0x62, 0x34, 0x65, 0x43, 0x52, 0x6e, 0x48, 0x65, 0x42, 0x61, 0x0a, + 0x49, 0x72, 0x67, 0x34, 0x6b, 0x5a, 0x75, 0x6b, 0x54, 0x48, 0x77, 0x4e, + 0x51, 0x50, 0x78, 0x47, 0x4e, 0x64, 0x45, 0x6b, 0x0a, 0x37, 0x56, 0x4f, + 0x78, 0x70, 0x54, 0x78, 0x42, 0x65, 0x66, 0x4c, 0x6f, 0x35, 0x41, 0x34, + 0x76, 0x6a, 0x46, 0x54, 0x6d, 0x0a, 0x33, 0x53, 0x76, 0x33, 0x6c, 0x43, + 0x39, 0x62, 0x4f, 0x4a, 0x62, 0x53, 0x58, 0x4f, 0x4d, 0x47, 0x57, 0x37, + 0x48, 0x4f, 0x0a, 0x74, 0x46, 0x69, 0x45, 0x6f, 0x51, 0x56, 0x69, 0x33, + 0x35, 0x6a, 0x48, 0x51, 0x6d, 0x36, 0x46, 0x4c, 0x6d, 0x4b, 0x47, 0x0a, + 0x7a, 0x37, 0x48, 0x62, 0x34, 0x4d, 0x36, 0x75, 0x66, 0x7a, 0x67, 0x76, + 0x31, 0x55, 0x6a, 0x36, 0x55, 0x44, 0x6a, 0x6a, 0x0a, 0x57, 0x4c, 0x6a, + 0x31, 0x73, 0x49, 0x38, 0x6c, 0x56, 0x6c, 0x43, 0x48, 0x64, 0x4b, 0x72, + 0x44, 0x30, 0x52, 0x48, 0x72, 0x0a, 0x4a, 0x69, 0x33, 0x68, 0x36, 0x34, + 0x74, 0x68, 0x67, 0x59, 0x4c, 0x74, 0x59, 0x31, 0x67, 0x58, 0x61, 0x34, + 0x33, 0x56, 0x0a, 0x34, 0x6b, 0x6a, 0x41, 0x74, 0x66, 0x74, 0x67, 0x47, + 0x4e, 0x54, 0x51, 0x48, 0x61, 0x33, 0x72, 0x66, 0x31, 0x68, 0x39, 0x0a, + 0x71, 0x70, 0x52, 0x76, 0x77, 0x64, 0x6c, 0x77, 0x41, 0x31, 0x70, 0x79, + 0x65, 0x72, 0x44, 0x58, 0x33, 0x6c, 0x4f, 0x79, 0x0a, 0x4a, 0x47, 0x63, + 0x34, 0x55, 0x69, 0x72, 0x51, 0x70, 0x48, 0x55, 0x61, 0x6a, 0x4e, 0x6d, + 0x57, 0x71, 0x61, 0x62, 0x78, 0x0a, 0x39, 0x6f, 0x58, 0x4b, 0x42, 0x35, + 0x6e, 0x74, 0x52, 0x6b, 0x6b, 0x6d, 0x36, 0x77, 0x71, 0x4f, 0x30, 0x51, + 0x62, 0x45, 0x0a, 0x6e, 0x66, 0x4a, 0x49, 0x71, 0x65, 0x66, 0x55, 0x42, + 0x44, 0x75, 0x73, 0x53, 0x44, 0x64, 0x66, 0x6a, 0x61, 0x49, 0x6f, 0x0a, + 0x45, 0x54, 0x4c, 0x57, 0x43, 0x30, 0x74, 0x46, 0x4b, 0x34, 0x65, 0x75, + 0x5a, 0x47, 0x48, 0x73, 0x76, 0x30, 0x78, 0x55, 0x0a, 0x4b, 0x43, 0x5a, + 0x42, 0x79, 0x75, 0x48, 0x6e, 0x59, 0x61, 0x4b, 0x67, 0x6c, 0x63, 0x47, + 0x47, 0x79, 0x67, 0x41, 0x65, 0x0a, 0x49, 0x4b, 0x61, 0x6a, 0x6e, 0x4e, + 0x57, 0x4c, 0x75, 0x77, 0x6a, 0x64, 0x48, 0x33, 0x38, 0x38, 0x58, 0x69, + 0x67, 0x37, 0x0a, 0x51, 0x69, 0x61, 0x73, 0x38, 0x38, 0x30, 0x38, 0x72, + 0x57, 0x42, 0x77, 0x59, 0x31, 0x5a, 0x6a, 0x6d, 0x38, 0x43, 0x6f, 0x0a, + 0x4c, 0x31, 0x6a, 0x53, 0x6a, 0x6b, 0x56, 0x6b, 0x6a, 0x42, 0x42, 0x4e, + 0x46, 0x6d, 0x66, 0x6b, 0x6a, 0x31, 0x37, 0x41, 0x0a, 0x57, 0x6e, 0x41, + 0x4e, 0x6c, 0x37, 0x64, 0x55, 0x73, 0x35, 0x46, 0x47, 0x6b, 0x5a, 0x46, + 0x67, 0x52, 0x48, 0x39, 0x5a, 0x0a, 0x56, 0x41, 0x32, 0x41, 0x38, 0x36, + 0x30, 0x59, 0x57, 0x6b, 0x36, 0x63, 0x58, 0x63, 0x68, 0x63, 0x42, 0x4d, + 0x30, 0x4f, 0x0a, 0x35, 0x31, 0x47, 0x52, 0x44, 0x4f, 0x46, 0x79, 0x48, + 0x33, 0x56, 0x63, 0x31, 0x66, 0x50, 0x6f, 0x6a, 0x57, 0x79, 0x56, 0x0a, + 0x43, 0x50, 0x72, 0x4b, 0x53, 0x66, 0x58, 0x73, 0x4a, 0x73, 0x56, 0x77, + 0x4d, 0x4e, 0x34, 0x4b, 0x79, 0x6b, 0x65, 0x5a, 0x0a, 0x63, 0x71, 0x33, + 0x45, 0x6f, 0x50, 0x63, 0x58, 0x49, 0x4b, 0x59, 0x52, 0x63, 0x64, 0x6f, + 0x61, 0x43, 0x74, 0x70, 0x37, 0x0a, 0x65, 0x49, 0x33, 0x74, 0x65, 0x4d, + 0x62, 0x7a, 0x57, 0x47, 0x4b, 0x54, 0x75, 0x33, 0x46, 0x51, 0x52, 0x58, + 0x53, 0x57, 0x0a, 0x4b, 0x41, 0x55, 0x68, 0x56, 0x58, 0x35, 0x52, 0x65, + 0x6a, 0x77, 0x69, 0x45, 0x4c, 0x46, 0x4a, 0x6c, 0x69, 0x6b, 0x42, 0x0a, + 0x46, 0x4d, 0x79, 0x68, 0x66, 0x58, 0x4d, 0x69, 0x7a, 0x31, 0x67, 0x62, + 0x38, 0x32, 0x51, 0x54, 0x42, 0x30, 0x48, 0x39, 0x0a, 0x32, 0x73, 0x73, + 0x4f, 0x77, 0x75, 0x43, 0x63, 0x31, 0x63, 0x50, 0x38, 0x70, 0x53, 0x45, + 0x5a, 0x66, 0x77, 0x30, 0x31, 0x0a, 0x42, 0x6d, 0x77, 0x52, 0x69, 0x4f, + 0x52, 0x4f, 0x38, 0x72, 0x37, 0x6c, 0x4e, 0x63, 0x42, 0x64, 0x6d, 0x4a, + 0x6e, 0x64, 0x0a, 0x57, 0x4e, 0x66, 0x56, 0x55, 0x75, 0x61, 0x51, 0x38, + 0x59, 0x79, 0x67, 0x79, 0x6c, 0x47, 0x33, 0x68, 0x30, 0x6e, 0x4f, 0x0a, + 0x54, 0x44, 0x66, 0x56, 0x71, 0x33, 0x44, 0x4a, 0x52, 0x58, 0x42, 0x6d, + 0x30, 0x31, 0x68, 0x63, 0x34, 0x76, 0x67, 0x65, 0x0a, 0x63, 0x51, 0x30, + 0x6c, 0x63, 0x36, 0x73, 0x68, 0x51, 0x51, 0x57, 0x68, 0x72, 0x45, 0x79, + 0x50, 0x34, 0x58, 0x4b, 0x70, 0x0a, 0x65, 0x6d, 0x62, 0x58, 0x4d, 0x48, + 0x72, 0x4f, 0x31, 0x51, 0x70, 0x59, 0x32, 0x62, 0x4d, 0x41, 0x69, 0x47, + 0x48, 0x71, 0x0a, 0x6c, 0x5a, 0x6a, 0x75, 0x70, 0x54, 0x6a, 0x6d, 0x65, + 0x6f, 0x77, 0x63, 0x6c, 0x35, 0x65, 0x50, 0x75, 0x65, 0x6b, 0x4f, 0x0a, + 0x79, 0x6b, 0x79, 0x69, 0x52, 0x77, 0x35, 0x4d, 0x70, 0x53, 0x70, 0x50, + 0x69, 0x32, 0x68, 0x31, 0x65, 0x47, 0x7a, 0x4c, 0x0a, 0x54, 0x37, 0x33, + 0x53, 0x5a, 0x49, 0x47, 0x6d, 0x74, 0x72, 0x64, 0x48, 0x49, 0x59, 0x50, + 0x41, 0x44, 0x78, 0x65, 0x70, 0x0a, 0x67, 0x68, 0x68, 0x78, 0x36, 0x41, + 0x47, 0x55, 0x65, 0x65, 0x44, 0x33, 0x4c, 0x64, 0x42, 0x51, 0x4e, 0x34, + 0x30, 0x79, 0x0a, 0x6f, 0x41, 0x77, 0x6d, 0x5a, 0x66, 0x50, 0x6d, 0x45, + 0x58, 0x61, 0x47, 0x46, 0x35, 0x32, 0x4d, 0x62, 0x62, 0x72, 0x69, 0x0a, + 0x48, 0x4f, 0x4d, 0x36, 0x66, 0x33, 0x33, 0x38, 0x58, 0x74, 0x66, 0x42, + 0x38, 0x5a, 0x75, 0x72, 0x71, 0x4a, 0x37, 0x79, 0x0a, 0x34, 0x5a, 0x54, + 0x41, 0x32, 0x4e, 0x67, 0x31, 0x67, 0x4e, 0x6a, 0x47, 0x6c, 0x49, 0x33, + 0x51, 0x57, 0x50, 0x33, 0x61, 0x0a, 0x48, 0x72, 0x42, 0x65, 0x4d, 0x67, + 0x74, 0x75, 0x68, 0x6d, 0x45, 0x76, 0x64, 0x61, 0x57, 0x51, 0x62, 0x70, + 0x30, 0x43, 0x0a, 0x4e, 0x78, 0x45, 0x76, 0x47, 0x4b, 0x4f, 0x4b, 0x6a, + 0x6a, 0x53, 0x73, 0x5a, 0x44, 0x46, 0x35, 0x38, 0x78, 0x35, 0x42, 0x0a, + 0x44, 0x72, 0x48, 0x4a, 0x6a, 0x57, 0x43, 0x6c, 0x61, 0x63, 0x31, 0x51, + 0x77, 0x6e, 0x4e, 0x44, 0x50, 0x46, 0x34, 0x4b, 0x0a, 0x32, 0x31, 0x48, + 0x67, 0x4b, 0x46, 0x4c, 0x45, 0x68, 0x35, 0x55, 0x47, 0x64, 0x65, 0x4e, + 0x7a, 0x6d, 0x53, 0x4c, 0x31, 0x0a, 0x4e, 0x76, 0x44, 0x64, 0x53, 0x65, + 0x7a, 0x52, 0x79, 0x47, 0x6b, 0x64, 0x41, 0x52, 0x79, 0x58, 0x67, 0x66, + 0x5a, 0x73, 0x0a, 0x54, 0x43, 0x78, 0x59, 0x6b, 0x65, 0x4e, 0x78, 0x6e, + 0x6a, 0x47, 0x73, 0x4e, 0x68, 0x72, 0x6f, 0x75, 0x50, 0x43, 0x37, 0x0a, + 0x6d, 0x59, 0x47, 0x33, 0x67, 0x54, 0x6b, 0x71, 0x70, 0x35, 0x74, 0x52, + 0x67, 0x4c, 0x52, 0x4a, 0x6c, 0x35, 0x6c, 0x56, 0x0a, 0x4a, 0x4a, 0x34, + 0x50, 0x38, 0x64, 0x45, 0x71, 0x6e, 0x6b, 0x63, 0x6f, 0x4f, 0x72, 0x52, + 0x38, 0x73, 0x7a, 0x69, 0x72, 0x0a, 0x45, 0x6e, 0x6a, 0x63, 0x35, 0x70, + 0x56, 0x35, 0x4c, 0x38, 0x57, 0x77, 0x79, 0x45, 0x66, 0x46, 0x48, 0x49, + 0x76, 0x46, 0x0a, 0x34, 0x30, 0x50, 0x35, 0x56, 0x70, 0x70, 0x4c, 0x57, + 0x68, 0x4a, 0x4d, 0x6a, 0x30, 0x53, 0x53, 0x49, 0x79, 0x51, 0x63, 0x0a, + 0x70, 0x58, 0x6f, 0x31, 0x44, 0x76, 0x34, 0x68, 0x42, 0x44, 0x77, 0x4e, + 0x77, 0x31, 0x4d, 0x68, 0x31, 0x77, 0x65, 0x4b, 0x0a, 0x6c, 0x73, 0x55, + 0x39, 0x45, 0x57, 0x4f, 0x49, 0x51, 0x5a, 0x45, 0x6a, 0x33, 0x36, 0x34, + 0x34, 0x64, 0x63, 0x4e, 0x50, 0x0a, 0x64, 0x76, 0x43, 0x5a, 0x59, 0x71, + 0x47, 0x6a, 0x6d, 0x45, 0x66, 0x75, 0x4e, 0x6d, 0x71, 0x49, 0x30, 0x53, + 0x43, 0x4c, 0x0a, 0x4e, 0x6c, 0x45, 0x4d, 0x68, 0x56, 0x78, 0x79, 0x52, + 0x76, 0x6c, 0x50, 0x37, 0x78, 0x5a, 0x6d, 0x42, 0x57, 0x51, 0x76, 0x0a, + 0x57, 0x73, 0x6b, 0x79, 0x71, 0x69, 0x54, 0x70, 0x59, 0x49, 0x4a, 0x43, + 0x62, 0x79, 0x4a, 0x74, 0x6c, 0x77, 0x61, 0x46, 0x0a, 0x6f, 0x57, 0x79, + 0x72, 0x53, 0x68, 0x65, 0x69, 0x5a, 0x4a, 0x54, 0x6c, 0x4e, 0x5a, 0x47, + 0x50, 0x44, 0x49, 0x65, 0x5a, 0x0a, 0x51, 0x63, 0x62, 0x78, 0x57, 0x6f, + 0x38, 0x34, 0x67, 0x34, 0x44, 0x52, 0x75, 0x34, 0x71, 0x6a, 0x6b, 0x7a, + 0x48, 0x72, 0x0a, 0x57, 0x6a, 0x35, 0x4e, 0x35, 0x54, 0x55, 0x62, 0x6b, + 0x48, 0x48, 0x37, 0x30, 0x67, 0x52, 0x58, 0x74, 0x71, 0x30, 0x4b, 0x0a, + 0x4b, 0x6a, 0x4b, 0x31, 0x54, 0x55, 0x30, 0x41, 0x6f, 0x30, 0x31, 0x65, + 0x71, 0x42, 0x6b, 0x56, 0x79, 0x77, 0x64, 0x44, 0x0a, 0x68, 0x31, 0x6f, + 0x6f, 0x66, 0x49, 0x4f, 0x6f, 0x35, 0x39, 0x6e, 0x64, 0x72, 0x64, 0x53, + 0x74, 0x64, 0x57, 0x58, 0x63, 0x0a, 0x72, 0x50, 0x54, 0x39, 0x36, 0x4f, + 0x68, 0x36, 0x70, 0x6d, 0x38, 0x35, 0x50, 0x49, 0x30, 0x36, 0x54, 0x63, + 0x64, 0x67, 0x0a, 0x50, 0x6b, 0x37, 0x70, 0x42, 0x49, 0x38, 0x57, 0x47, + 0x39, 0x71, 0x4d, 0x50, 0x53, 0x76, 0x4e, 0x63, 0x36, 0x77, 0x4f, 0x0a, + 0x34, 0x5a, 0x69, 0x5a, 0x36, 0x6e, 0x7a, 0x44, 0x45, 0x42, 0x36, 0x30, + 0x69, 0x53, 0x73, 0x77, 0x4c, 0x72, 0x69, 0x30, 0x0a, 0x4a, 0x67, 0x4f, + 0x65, 0x74, 0x53, 0x33, 0x73, 0x69, 0x39, 0x41, 0x56, 0x32, 0x57, 0x77, + 0x72, 0x44, 0x6f, 0x6d, 0x37, 0x0a, 0x34, 0x41, 0x52, 0x43, 0x71, 0x35, + 0x51, 0x59, 0x62, 0x72, 0x54, 0x31, 0x51, 0x30, 0x51, 0x75, 0x6b, 0x38, + 0x70, 0x56, 0x0a, 0x38, 0x65, 0x4f, 0x78, 0x63, 0x6d, 0x65, 0x70, 0x45, + 0x35, 0x39, 0x70, 0x45, 0x6e, 0x57, 0x65, 0x66, 0x6d, 0x53, 0x79, 0x0a, + 0x67, 0x59, 0x72, 0x42, 0x33, 0x57, 0x37, 0x66, 0x4d, 0x45, 0x59, 0x55, + 0x69, 0x75, 0x31, 0x6c, 0x51, 0x50, 0x4e, 0x46, 0x0a, 0x4a, 0x72, 0x51, + 0x76, 0x49, 0x62, 0x4b, 0x4b, 0x52, 0x58, 0x76, 0x70, 0x78, 0x39, 0x52, + 0x42, 0x37, 0x4a, 0x59, 0x43, 0x0a, 0x54, 0x50, 0x75, 0x58, 0x61, 0x32, + 0x32, 0x6b, 0x51, 0x37, 0x5a, 0x4d, 0x66, 0x66, 0x69, 0x59, 0x74, 0x44, + 0x31, 0x46, 0x0a, 0x43, 0x75, 0x55, 0x49, 0x49, 0x56, 0x57, 0x75, 0x78, + 0x6e, 0x70, 0x66, 0x69, 0x6f, 0x51, 0x61, 0x79, 0x69, 0x62, 0x54, 0x0a, + 0x36, 0x48, 0x75, 0x4e, 0x42, 0x39, 0x64, 0x46, 0x56, 0x76, 0x42, 0x4b, + 0x6a, 0x68, 0x69, 0x5a, 0x7a, 0x77, 0x59, 0x74, 0x0a, 0x38, 0x62, 0x65, + 0x39, 0x4f, 0x31, 0x77, 0x4b, 0x4a, 0x39, 0x34, 0x35, 0x41, 0x6c, 0x56, + 0x67, 0x44, 0x34, 0x62, 0x39, 0x0a, 0x65, 0x6b, 0x56, 0x67, 0x41, 0x71, + 0x69, 0x34, 0x67, 0x6e, 0x48, 0x4b, 0x6c, 0x71, 0x79, 0x66, 0x42, 0x4d, + 0x33, 0x67, 0x0a, 0x39, 0x6a, 0x69, 0x34, 0x41, 0x57, 0x44, 0x49, 0x45, + 0x67, 0x6f, 0x32, 0x30, 0x45, 0x63, 0x49, 0x4d, 0x37, 0x42, 0x58, 0x0a, + 0x42, 0x64, 0x6d, 0x53, 0x6d, 0x46, 0x35, 0x55, 0x71, 0x48, 0x64, 0x4f, + 0x74, 0x59, 0x44, 0x55, 0x61, 0x72, 0x44, 0x6b, 0x0a, 0x77, 0x38, 0x59, + 0x78, 0x66, 0x5a, 0x53, 0x52, 0x61, 0x6e, 0x4b, 0x70, 0x37, 0x78, 0x67, + 0x53, 0x36, 0x67, 0x43, 0x74, 0x0a, 0x44, 0x56, 0x41, 0x76, 0x68, 0x61, + 0x72, 0x6e, 0x46, 0x32, 0x66, 0x59, 0x49, 0x70, 0x67, 0x73, 0x7a, 0x76, + 0x62, 0x4d, 0x0a, 0x34, 0x61, 0x6e, 0x64, 0x61, 0x39, 0x65, 0x68, 0x54, + 0x33, 0x77, 0x6a, 0x41, 0x66, 0x55, 0x67, 0x46, 0x6b, 0x31, 0x70, 0x0a, + 0x76, 0x39, 0x53, 0x6a, 0x56, 0x41, 0x4d, 0x6b, 0x7a, 0x71, 0x4c, 0x58, + 0x6a, 0x55, 0x30, 0x37, 0x32, 0x4f, 0x52, 0x45, 0x0a, 0x78, 0x71, 0x48, + 0x4c, 0x34, 0x69, 0x72, 0x69, 0x4c, 0x33, 0x38, 0x7a, 0x32, 0x72, 0x69, + 0x4a, 0x39, 0x49, 0x30, 0x70, 0x0a, 0x6b, 0x41, 0x50, 0x35, 0x6e, 0x76, + 0x43, 0x77, 0x63, 0x38, 0x52, 0x70, 0x6c, 0x53, 0x69, 0x41, 0x4b, 0x6f, + 0x63, 0x61, 0x0a, 0x31, 0x41, 0x4a, 0x74, 0x46, 0x6a, 0x58, 0x53, 0x72, + 0x54, 0x46, 0x55, 0x57, 0x49, 0x6e, 0x5a, 0x4a, 0x37, 0x4a, 0x56, 0x0a, + 0x32, 0x44, 0x44, 0x6e, 0x6b, 0x4c, 0x50, 0x43, 0x53, 0x6c, 0x5a, 0x4b, + 0x31, 0x6e, 0x6e, 0x45, 0x39, 0x45, 0x78, 0x6f, 0x0a, 0x46, 0x6c, 0x58, + 0x44, 0x73, 0x53, 0x68, 0x50, 0x6b, 0x42, 0x50, 0x68, 0x6e, 0x37, 0x71, + 0x37, 0x51, 0x4f, 0x33, 0x4d, 0x0a, 0x57, 0x75, 0x35, 0x4e, 0x5a, 0x71, + 0x4c, 0x6a, 0x42, 0x45, 0x4d, 0x66, 0x5a, 0x76, 0x62, 0x53, 0x70, 0x5a, + 0x63, 0x59, 0x0a, 0x76, 0x67, 0x34, 0x79, 0x61, 0x50, 0x73, 0x68, 0x32, + 0x6e, 0x4e, 0x6f, 0x73, 0x61, 0x6e, 0x6d, 0x64, 0x59, 0x67, 0x72, 0x0a, + 0x41, 0x38, 0x4a, 0x55, 0x43, 0x6b, 0x77, 0x6b, 0x6c, 0x32, 0x44, 0x55, + 0x6a, 0x34, 0x34, 0x66, 0x4d, 0x53, 0x31, 0x71, 0x0a, 0x6a, 0x6b, 0x50, + 0x48, 0x31, 0x38, 0x66, 0x79, 0x47, 0x47, 0x6d, 0x44, 0x42, 0x55, 0x53, + 0x4f, 0x6e, 0x56, 0x6a, 0x67, 0x0a, 0x66, 0x65, 0x31, 0x31, 0x36, 0x42, + 0x6b, 0x76, 0x4d, 0x68, 0x41, 0x51, 0x41, 0x72, 0x4f, 0x71, 0x44, 0x4b, + 0x4b, 0x68, 0x0a, 0x6d, 0x56, 0x34, 0x75, 0x4f, 0x7a, 0x62, 0x73, 0x41, + 0x75, 0x47, 0x33, 0x79, 0x53, 0x66, 0x31, 0x69, 0x4c, 0x31, 0x46, 0x0a, + 0x58, 0x45, 0x59, 0x39, 0x71, 0x4e, 0x49, 0x4a, 0x44, 0x49, 0x4b, 0x6c, + 0x57, 0x61, 0x37, 0x43, 0x59, 0x68, 0x6f, 0x73, 0x0a, 0x6f, 0x66, 0x75, + 0x56, 0x53, 0x31, 0x75, 0x51, 0x54, 0x51, 0x58, 0x32, 0x4f, 0x52, 0x76, + 0x43, 0x57, 0x6f, 0x74, 0x7a, 0x0a, 0x46, 0x6f, 0x72, 0x47, 0x57, 0x5a, + 0x64, 0x6b, 0x4f, 0x61, 0x67, 0x66, 0x36, 0x37, 0x6f, 0x42, 0x66, 0x57, + 0x4e, 0x34, 0x0a, 0x31, 0x6b, 0x74, 0x55, 0x41, 0x41, 0x69, 0x66, 0x6c, + 0x71, 0x61, 0x4d, 0x55, 0x6c, 0x65, 0x79, 0x4c, 0x4d, 0x52, 0x65, 0x0a, + 0x42, 0x55, 0x50, 0x67, 0x5a, 0x35, 0x4f, 0x7a, 0x58, 0x51, 0x69, 0x46, + 0x71, 0x34, 0x62, 0x4d, 0x4f, 0x46, 0x4b, 0x46, 0x0a, 0x77, 0x64, 0x66, + 0x64, 0x79, 0x66, 0x61, 0x65, 0x63, 0x54, 0x41, 0x6f, 0x6e, 0x6c, 0x47, + 0x56, 0x73, 0x30, 0x43, 0x4f, 0x0a, 0x63, 0x48, 0x50, 0x45, 0x45, 0x72, + 0x4d, 0x48, 0x51, 0x79, 0x64, 0x38, 0x66, 0x59, 0x4b, 0x32, 0x6c, 0x32, + 0x6e, 0x65, 0x0a, 0x48, 0x63, 0x35, 0x43, 0x58, 0x38, 0x64, 0x77, 0x47, + 0x6e, 0x46, 0x6e, 0x41, 0x38, 0x53, 0x66, 0x53, 0x30, 0x6d, 0x35, 0x0a, + 0x63, 0x77, 0x65, 0x6e, 0x35, 0x6c, 0x42, 0x72, 0x72, 0x57, 0x44, 0x44, + 0x30, 0x64, 0x78, 0x38, 0x4d, 0x39, 0x79, 0x4f, 0x0a, 0x72, 0x77, 0x64, + 0x4c, 0x73, 0x6e, 0x69, 0x6e, 0x74, 0x37, 0x37, 0x6b, 0x46, 0x76, 0x62, + 0x54, 0x34, 0x6d, 0x51, 0x70, 0x0a, 0x32, 0x36, 0x36, 0x69, 0x78, 0x39, + 0x36, 0x55, 0x76, 0x75, 0x4f, 0x45, 0x62, 0x34, 0x39, 0x4d, 0x51, 0x37, + 0x36, 0x73, 0x0a, 0x6c, 0x47, 0x4e, 0x38, 0x75, 0x75, 0x6c, 0x34, 0x42, + 0x44, 0x37, 0x76, 0x69, 0x33, 0x48, 0x6f, 0x38, 0x75, 0x4e, 0x61, 0x0a, + 0x57, 0x41, 0x59, 0x37, 0x62, 0x50, 0x74, 0x48, 0x6b, 0x6e, 0x42, 0x33, + 0x32, 0x69, 0x48, 0x76, 0x32, 0x6d, 0x51, 0x55, 0x0a, 0x42, 0x66, 0x45, + 0x45, 0x6e, 0x72, 0x35, 0x45, 0x50, 0x77, 0x73, 0x53, 0x75, 0x35, 0x65, + 0x45, 0x64, 0x74, 0x76, 0x73, 0x0a, 0x48, 0x74, 0x54, 0x49, 0x35, 0x69, + 0x76, 0x56, 0x69, 0x66, 0x4c, 0x71, 0x69, 0x6a, 0x4f, 0x5a, 0x79, 0x36, + 0x61, 0x72, 0x0a, 0x31, 0x49, 0x56, 0x71, 0x5a, 0x65, 0x6f, 0x45, 0x62, + 0x4d, 0x48, 0x66, 0x69, 0x59, 0x37, 0x39, 0x69, 0x50, 0x56, 0x61, 0x0a, + 0x52, 0x32, 0x34, 0x74, 0x4d, 0x52, 0x6c, 0x6e, 0x48, 0x43, 0x62, 0x6a, + 0x67, 0x4d, 0x54, 0x44, 0x38, 0x6c, 0x73, 0x4e, 0x0a, 0x37, 0x34, 0x4c, + 0x48, 0x68, 0x74, 0x4f, 0x41, 0x53, 0x5a, 0x4c, 0x72, 0x4c, 0x77, 0x6a, + 0x67, 0x59, 0x65, 0x37, 0x67, 0x0a, 0x49, 0x4f, 0x56, 0x4b, 0x47, 0x6b, + 0x36, 0x77, 0x30, 0x4a, 0x43, 0x61, 0x44, 0x73, 0x5a, 0x7a, 0x4b, 0x52, + 0x62, 0x37, 0x0a, 0x38, 0x44, 0x6a, 0x65, 0x4f, 0x39, 0x75, 0x48, 0x4c, + 0x61, 0x37, 0x6f, 0x73, 0x78, 0x41, 0x64, 0x34, 0x64, 0x77, 0x34, 0x0a, + 0x66, 0x38, 0x43, 0x6c, 0x43, 0x7a, 0x41, 0x50, 0x6e, 0x74, 0x71, 0x6b, + 0x53, 0x69, 0x66, 0x33, 0x70, 0x50, 0x37, 0x47, 0x0a, 0x4b, 0x65, 0x5a, + 0x68, 0x71, 0x35, 0x50, 0x5a, 0x50, 0x55, 0x55, 0x45, 0x71, 0x52, 0x66, + 0x41, 0x61, 0x69, 0x61, 0x70, 0x0a, 0x55, 0x6b, 0x49, 0x65, 0x6f, 0x58, + 0x58, 0x49, 0x71, 0x48, 0x51, 0x56, 0x61, 0x38, 0x67, 0x53, 0x6a, 0x71, + 0x58, 0x66, 0x0a, 0x4f, 0x74, 0x71, 0x55, 0x46, 0x39, 0x63, 0x66, 0x43, + 0x6a, 0x32, 0x49, 0x61, 0x7a, 0x4b, 0x45, 0x4f, 0x4f, 0x4b, 0x43, 0x0a, + 0x54, 0x44, 0x7a, 0x32, 0x39, 0x66, 0x33, 0x77, 0x6a, 0x70, 0x64, 0x57, + 0x75, 0x44, 0x4f, 0x6a, 0x45, 0x4a, 0x4b, 0x71, 0x0a, 0x34, 0x72, 0x75, + 0x37, 0x6a, 0x35, 0x39, 0x75, 0x46, 0x53, 0x67, 0x47, 0x42, 0x50, 0x73, + 0x74, 0x78, 0x68, 0x59, 0x4f, 0x0a, 0x7a, 0x78, 0x41, 0x4d, 0x6d, 0x67, + 0x74, 0x48, 0x33, 0x6e, 0x47, 0x6b, 0x77, 0x4d, 0x52, 0x32, 0x4c, 0x59, + 0x69, 0x47, 0x0a, 0x6b, 0x46, 0x38, 0x48, 0x30, 0x78, 0x55, 0x5a, 0x44, + 0x71, 0x78, 0x6f, 0x45, 0x61, 0x6f, 0x72, 0x35, 0x6b, 0x32, 0x6d, 0x0a, + 0x7a, 0x51, 0x43, 0x71, 0x65, 0x35, 0x66, 0x57, 0x58, 0x39, 0x4d, 0x51, + 0x51, 0x6c, 0x75, 0x39, 0x42, 0x4b, 0x67, 0x4b, 0x0a, 0x6d, 0x6e, 0x4a, + 0x33, 0x4d, 0x45, 0x75, 0x6c, 0x6d, 0x43, 0x47, 0x53, 0x78, 0x53, 0x36, + 0x43, 0x6e, 0x52, 0x50, 0x6f, 0x0a, 0x7a, 0x34, 0x34, 0x39, 0x45, 0x79, + 0x41, 0x63, 0x33, 0x75, 0x57, 0x38, 0x53, 0x51, 0x6c, 0x65, 0x48, 0x6c, + 0x65, 0x62, 0x0a, 0x73, 0x31, 0x50, 0x35, 0x70, 0x57, 0x41, 0x4b, 0x36, + 0x4b, 0x64, 0x4b, 0x6c, 0x36, 0x62, 0x65, 0x68, 0x65, 0x6e, 0x49, 0x0a, + 0x53, 0x34, 0x6a, 0x6b, 0x49, 0x6c, 0x42, 0x49, 0x62, 0x46, 0x72, 0x46, + 0x49, 0x35, 0x6a, 0x30, 0x31, 0x79, 0x54, 0x39, 0x0a, 0x77, 0x46, 0x56, + 0x6b, 0x71, 0x41, 0x57, 0x54, 0x5a, 0x4c, 0x41, 0x58, 0x4c, 0x51, 0x71, + 0x39, 0x62, 0x37, 0x7a, 0x68, 0x0a, 0x55, 0x53, 0x78, 0x72, 0x6e, 0x33, + 0x30, 0x33, 0x78, 0x54, 0x77, 0x5a, 0x68, 0x75, 0x32, 0x6f, 0x5a, 0x7a, + 0x48, 0x4c, 0x0a, 0x64, 0x38, 0x30, 0x6c, 0x42, 0x44, 0x4c, 0x7a, 0x6a, + 0x53, 0x4a, 0x66, 0x35, 0x47, 0x6c, 0x7a, 0x69, 0x4a, 0x72, 0x79, 0x0a, + 0x73, 0x79, 0x64, 0x6f, 0x43, 0x52, 0x59, 0x7a, 0x67, 0x38, 0x63, 0x51, + 0x48, 0x36, 0x4b, 0x41, 0x48, 0x78, 0x42, 0x4c, 0x0a, 0x74, 0x6f, 0x73, + 0x64, 0x6c, 0x53, 0x6e, 0x35, 0x62, 0x51, 0x78, 0x44, 0x52, 0x77, 0x75, + 0x59, 0x69, 0x6d, 0x6c, 0x35, 0x0a, 0x33, 0x35, 0x41, 0x45, 0x51, 0x6c, + 0x73, 0x73, 0x49, 0x42, 0x74, 0x66, 0x62, 0x4d, 0x6d, 0x35, 0x79, 0x49, + 0x49, 0x33, 0x0a, 0x51, 0x71, 0x48, 0x33, 0x63, 0x65, 0x38, 0x64, 0x7a, + 0x71, 0x4b, 0x4d, 0x71, 0x4a, 0x74, 0x65, 0x58, 0x46, 0x6a, 0x41, 0x0a, + 0x4a, 0x44, 0x62, 0x68, 0x33, 0x6d, 0x67, 0x53, 0x56, 0x44, 0x75, 0x71, + 0x46, 0x32, 0x71, 0x77, 0x78, 0x46, 0x63, 0x72, 0x0a, 0x74, 0x68, 0x52, + 0x39, 0x6f, 0x39, 0x35, 0x75, 0x59, 0x4c, 0x6b, 0x41, 0x47, 0x6d, 0x54, + 0x74, 0x54, 0x77, 0x48, 0x44, 0x0a, 0x4d, 0x50, 0x49, 0x6b, 0x6c, 0x45, + 0x79, 0x4d, 0x58, 0x4e, 0x47, 0x78, 0x63, 0x54, 0x66, 0x64, 0x50, 0x33, + 0x34, 0x76, 0x0a, 0x56, 0x54, 0x4e, 0x37, 0x6b, 0x59, 0x49, 0x43, 0x4d, + 0x34, 0x55, 0x4d, 0x47, 0x76, 0x39, 0x38, 0x55, 0x4a, 0x46, 0x66, 0x0a, + 0x61, 0x61, 0x47, 0x34, 0x52, 0x6f, 0x72, 0x6b, 0x6a, 0x77, 0x38, 0x46, + 0x66, 0x59, 0x59, 0x4d, 0x6d, 0x71, 0x5a, 0x33, 0x0a, 0x35, 0x7a, 0x47, + 0x75, 0x54, 0x4a, 0x79, 0x69, 0x6d, 0x57, 0x6c, 0x4c, 0x35, 0x4b, 0x4f, + 0x5a, 0x56, 0x49, 0x70, 0x38, 0x0a, 0x52, 0x4b, 0x32, 0x65, 0x76, 0x66, + 0x4c, 0x46, 0x6c, 0x49, 0x52, 0x30, 0x38, 0x32, 0x38, 0x36, 0x58, 0x54, + 0x4b, 0x55, 0x0a, 0x67, 0x57, 0x57, 0x36, 0x30, 0x35, 0x6f, 0x4d, 0x6e, + 0x6a, 0x75, 0x46, 0x33, 0x53, 0x41, 0x4b, 0x78, 0x69, 0x6e, 0x51, 0x0a, + 0x56, 0x75, 0x76, 0x78, 0x39, 0x39, 0x35, 0x32, 0x44, 0x72, 0x48, 0x4a, + 0x79, 0x4e, 0x6d, 0x65, 0x36, 0x72, 0x68, 0x53, 0x0a, 0x44, 0x4f, 0x4b, + 0x66, 0x30, 0x66, 0x65, 0x75, 0x6e, 0x59, 0x78, 0x4b, 0x4d, 0x46, 0x49, + 0x6e, 0x73, 0x39, 0x4f, 0x67, 0x0a, 0x44, 0x56, 0x62, 0x71, 0x6a, 0x34, + 0x44, 0x68, 0x5a, 0x35, 0x51, 0x4c, 0x31, 0x46, 0x4d, 0x6c, 0x41, 0x63, + 0x6b, 0x34, 0x0a, 0x4f, 0x68, 0x65, 0x6b, 0x77, 0x69, 0x5a, 0x4e, 0x56, + 0x79, 0x31, 0x66, 0x42, 0x6a, 0x71, 0x46, 0x7a, 0x34, 0x44, 0x79, 0x0a, + 0x52, 0x71, 0x76, 0x7a, 0x4f, 0x35, 0x6e, 0x31, 0x34, 0x36, 0x45, 0x6f, + 0x7a, 0x46, 0x77, 0x47, 0x71, 0x6b, 0x6e, 0x6d, 0x0a, 0x34, 0x36, 0x30, + 0x45, 0x74, 0x42, 0x34, 0x48, 0x4f, 0x35, 0x34, 0x69, 0x73, 0x34, 0x66, + 0x78, 0x72, 0x53, 0x73, 0x34, 0x0a, 0x47, 0x75, 0x61, 0x39, 0x44, 0x69, + 0x6b, 0x73, 0x48, 0x5a, 0x42, 0x46, 0x38, 0x69, 0x53, 0x54, 0x56, 0x6e, + 0x6f, 0x63, 0x0a, 0x69, 0x74, 0x4b, 0x43, 0x6a, 0x57, 0x32, 0x72, 0x79, + 0x6a, 0x34, 0x65, 0x52, 0x6d, 0x67, 0x35, 0x4f, 0x6f, 0x6f, 0x6b, 0x0a, + 0x6b, 0x4c, 0x65, 0x73, 0x69, 0x57, 0x53, 0x6a, 0x46, 0x39, 0x33, 0x4d, + 0x76, 0x4d, 0x41, 0x42, 0x50, 0x72, 0x74, 0x54, 0x0a, 0x37, 0x74, 0x72, + 0x4b, 0x4b, 0x56, 0x75, 0x65, 0x36, 0x73, 0x34, 0x6e, 0x77, 0x34, 0x4c, + 0x4d, 0x74, 0x6d, 0x39, 0x61, 0x0a, 0x45, 0x59, 0x52, 0x39, 0x36, 0x63, + 0x4c, 0x4e, 0x41, 0x55, 0x39, 0x47, 0x6f, 0x50, 0x56, 0x5a, 0x78, 0x61, + 0x69, 0x57, 0x0a, 0x79, 0x53, 0x52, 0x59, 0x34, 0x70, 0x47, 0x6b, 0x54, + 0x64, 0x42, 0x50, 0x41, 0x39, 0x57, 0x38, 0x46, 0x4d, 0x4c, 0x6f, 0x0a, + 0x75, 0x78, 0x6d, 0x71, 0x4f, 0x53, 0x50, 0x58, 0x70, 0x33, 0x4f, 0x41, + 0x4c, 0x75, 0x6a, 0x6a, 0x4c, 0x79, 0x54, 0x75, 0x0a, 0x39, 0x4c, 0x6a, + 0x44, 0x6e, 0x31, 0x79, 0x67, 0x44, 0x76, 0x63, 0x52, 0x6d, 0x75, 0x75, + 0x37, 0x76, 0x4c, 0x66, 0x42, 0x0a, 0x75, 0x50, 0x35, 0x75, 0x42, 0x76, + 0x6f, 0x48, 0x5a, 0x44, 0x39, 0x64, 0x44, 0x55, 0x77, 0x4a, 0x56, 0x63, + 0x7a, 0x76, 0x0a, 0x45, 0x6c, 0x47, 0x68, 0x4f, 0x70, 0x78, 0x52, 0x45, + 0x44, 0x5a, 0x4e, 0x37, 0x52, 0x52, 0x4a, 0x62, 0x4a, 0x44, 0x56, 0x0a, + 0x34, 0x35, 0x4c, 0x58, 0x48, 0x50, 0x6a, 0x75, 0x68, 0x6e, 0x63, 0x66, + 0x64, 0x71, 0x53, 0x74, 0x66, 0x30, 0x51, 0x7a, 0x0a, 0x71, 0x4c, 0x4c, + 0x5a, 0x6d, 0x67, 0x51, 0x49, 0x45, 0x71, 0x51, 0x5a, 0x43, 0x77, 0x33, + 0x45, 0x66, 0x39, 0x39, 0x58, 0x0a, 0x71, 0x6f, 0x69, 0x57, 0x51, 0x68, + 0x34, 0x4a, 0x68, 0x6d, 0x7a, 0x75, 0x33, 0x7a, 0x4b, 0x69, 0x45, 0x44, + 0x30, 0x50, 0x0a, 0x30, 0x6a, 0x46, 0x37, 0x69, 0x43, 0x47, 0x63, 0x67, + 0x75, 0x4b, 0x33, 0x63, 0x73, 0x7a, 0x4c, 0x57, 0x44, 0x51, 0x6a, 0x0a, + 0x58, 0x5a, 0x64, 0x4a, 0x49, 0x63, 0x74, 0x7a, 0x6d, 0x78, 0x58, 0x7a, + 0x6b, 0x56, 0x67, 0x4d, 0x56, 0x44, 0x38, 0x53, 0x0a, 0x77, 0x6b, 0x47, + 0x42, 0x69, 0x46, 0x63, 0x78, 0x4d, 0x70, 0x64, 0x64, 0x54, 0x34, 0x6c, + 0x36, 0x46, 0x48, 0x4e, 0x31, 0x0a, 0x48, 0x4c, 0x42, 0x6c, 0x41, 0x42, + 0x6e, 0x48, 0x71, 0x7a, 0x6d, 0x38, 0x4a, 0x74, 0x36, 0x6d, 0x49, 0x4d, + 0x51, 0x5a, 0x0a, 0x6f, 0x37, 0x4d, 0x33, 0x73, 0x50, 0x66, 0x50, 0x68, + 0x55, 0x44, 0x32, 0x32, 0x39, 0x66, 0x4c, 0x75, 0x5a, 0x37, 0x76, 0x0a, + 0x65, 0x42, 0x6d, 0x67, 0x37, 0x66, 0x51, 0x33, 0x61, 0x4b, 0x4a, 0x68, + 0x45, 0x44, 0x56, 0x46, 0x6a, 0x35, 0x53, 0x41, 0x0a, 0x51, 0x41, 0x41, + 0x4d, 0x6d, 0x31, 0x53, 0x39, 0x73, 0x46, 0x42, 0x34, 0x71, 0x62, 0x63, + 0x43, 0x79, 0x6f, 0x6d, 0x4f, 0x0a, 0x70, 0x70, 0x71, 0x6d, 0x53, 0x37, + 0x59, 0x52, 0x53, 0x51, 0x4d, 0x45, 0x76, 0x6b, 0x77, 0x4c, 0x68, 0x73, + 0x49, 0x4c, 0x0a, 0x63, 0x75, 0x50, 0x51, 0x36, 0x4b, 0x35, 0x75, 0x6f, + 0x4f, 0x75, 0x56, 0x55, 0x4b, 0x6f, 0x41, 0x63, 0x43, 0x44, 0x71, 0x0a, + 0x55, 0x58, 0x55, 0x69, 0x58, 0x37, 0x74, 0x4c, 0x6c, 0x56, 0x36, 0x31, + 0x79, 0x48, 0x58, 0x4f, 0x63, 0x6c, 0x6a, 0x6a, 0x0a, 0x46, 0x6d, 0x32, + 0x46, 0x58, 0x4b, 0x5a, 0x49, 0x72, 0x6f, 0x45, 0x4c, 0x79, 0x74, 0x36, + 0x77, 0x48, 0x50, 0x59, 0x68, 0x0a, 0x53, 0x32, 0x32, 0x41, 0x55, 0x57, + 0x52, 0x56, 0x36, 0x61, 0x67, 0x6e, 0x53, 0x6f, 0x43, 0x7a, 0x4b, 0x4e, + 0x62, 0x55, 0x0a, 0x67, 0x39, 0x63, 0x35, 0x35, 0x30, 0x6c, 0x73, 0x35, + 0x30, 0x69, 0x41, 0x55, 0x36, 0x31, 0x72, 0x56, 0x39, 0x4e, 0x67, 0x0a, + 0x33, 0x79, 0x31, 0x6c, 0x6e, 0x6c, 0x50, 0x67, 0x65, 0x7a, 0x55, 0x68, + 0x4a, 0x62, 0x5a, 0x56, 0x62, 0x6d, 0x54, 0x50, 0x0a, 0x64, 0x37, 0x43, + 0x52, 0x62, 0x66, 0x73, 0x58, 0x42, 0x70, 0x69, 0x39, 0x64, 0x32, 0x67, + 0x4b, 0x31, 0x73, 0x69, 0x6f, 0x0a, 0x75, 0x51, 0x62, 0x66, 0x35, 0x67, + 0x6c, 0x74, 0x66, 0x6b, 0x4b, 0x4f, 0x56, 0x64, 0x51, 0x49, 0x4a, 0x64, + 0x34, 0x6c, 0x0a, 0x76, 0x57, 0x4e, 0x53, 0x71, 0x30, 0x66, 0x6c, 0x49, + 0x4c, 0x57, 0x30, 0x78, 0x55, 0x4a, 0x78, 0x4d, 0x63, 0x31, 0x79, 0x0a, + 0x6d, 0x4c, 0x72, 0x38, 0x53, 0x56, 0x32, 0x73, 0x4b, 0x74, 0x41, 0x5a, + 0x4c, 0x52, 0x5a, 0x6c, 0x30, 0x65, 0x6e, 0x37, 0x0a, 0x78, 0x4d, 0x64, + 0x37, 0x41, 0x78, 0x39, 0x43, 0x70, 0x51, 0x48, 0x4d, 0x71, 0x6b, 0x32, + 0x44, 0x5a, 0x5a, 0x45, 0x74, 0x0a, 0x34, 0x35, 0x58, 0x65, 0x39, 0x48, + 0x49, 0x76, 0x6f, 0x74, 0x4a, 0x62, 0x33, 0x6f, 0x34, 0x68, 0x57, 0x39, + 0x68, 0x52, 0x0a, 0x57, 0x56, 0x4b, 0x74, 0x53, 0x47, 0x6f, 0x67, 0x4b, + 0x6f, 0x5a, 0x41, 0x52, 0x79, 0x70, 0x72, 0x43, 0x58, 0x48, 0x76, 0x0a, + 0x58, 0x50, 0x7a, 0x30, 0x37, 0x42, 0x63, 0x79, 0x32, 0x71, 0x43, 0x66, + 0x35, 0x41, 0x6d, 0x77, 0x77, 0x37, 0x39, 0x66, 0x0a, 0x6e, 0x41, 0x38, + 0x39, 0x7a, 0x43, 0x76, 0x50, 0x4b, 0x69, 0x6b, 0x6c, 0x50, 0x74, 0x50, + 0x61, 0x36, 0x50, 0x38, 0x47, 0x0a, 0x6a, 0x43, 0x52, 0x57, 0x4f, 0x7a, + 0x58, 0x4a, 0x33, 0x73, 0x5a, 0x7a, 0x33, 0x6a, 0x32, 0x31, 0x38, 0x4f, + 0x33, 0x5a, 0x0a, 0x63, 0x32, 0x52, 0x73, 0x45, 0x6a, 0x75, 0x4d, 0x30, + 0x49, 0x33, 0x71, 0x4a, 0x63, 0x49, 0x71, 0x51, 0x79, 0x51, 0x62, 0x0a, + 0x64, 0x65, 0x64, 0x30, 0x66, 0x51, 0x39, 0x7a, 0x66, 0x71, 0x34, 0x35, + 0x71, 0x48, 0x48, 0x65, 0x79, 0x72, 0x50, 0x71, 0x0a, 0x36, 0x70, 0x72, + 0x65, 0x57, 0x56, 0x47, 0x6f, 0x6a, 0x5a, 0x4d, 0x71, 0x6f, 0x56, 0x4b, + 0x6c, 0x71, 0x42, 0x58, 0x59, 0x0a, 0x72, 0x50, 0x33, 0x73, 0x67, 0x41, + 0x55, 0x4f, 0x6a, 0x54, 0x53, 0x6e, 0x37, 0x41, 0x36, 0x63, 0x34, 0x36, + 0x50, 0x48, 0x0a, 0x4e, 0x54, 0x6d, 0x7a, 0x34, 0x73, 0x6c, 0x52, 0x6b, + 0x50, 0x61, 0x5a, 0x51, 0x6a, 0x38, 0x71, 0x31, 0x4e, 0x63, 0x66, 0x0a, + 0x61, 0x38, 0x6f, 0x78, 0x52, 0x56, 0x49, 0x57, 0x77, 0x63, 0x66, 0x58, + 0x36, 0x73, 0x47, 0x4d, 0x61, 0x37, 0x49, 0x75, 0x0a, 0x6c, 0x78, 0x46, + 0x6c, 0x79, 0x6c, 0x6d, 0x75, 0x55, 0x76, 0x56, 0x69, 0x67, 0x4a, 0x53, + 0x56, 0x74, 0x4a, 0x35, 0x4a, 0x0a, 0x45, 0x65, 0x42, 0x64, 0x68, 0x78, + 0x79, 0x64, 0x49, 0x39, 0x56, 0x4a, 0x41, 0x70, 0x34, 0x68, 0x79, 0x4f, + 0x44, 0x37, 0x0a, 0x46, 0x4e, 0x4a, 0x67, 0x79, 0x39, 0x42, 0x77, 0x50, + 0x48, 0x4e, 0x68, 0x30, 0x47, 0x32, 0x52, 0x4f, 0x6e, 0x46, 0x78, 0x0a, + 0x51, 0x42, 0x4b, 0x63, 0x68, 0x67, 0x56, 0x67, 0x30, 0x59, 0x6d, 0x6e, + 0x4d, 0x64, 0x78, 0x67, 0x45, 0x6f, 0x6c, 0x67, 0x0a, 0x77, 0x70, 0x37, + 0x67, 0x6d, 0x61, 0x6f, 0x34, 0x30, 0x74, 0x74, 0x66, 0x43, 0x42, 0x6e, + 0x43, 0x62, 0x33, 0x6d, 0x59, 0x0a, 0x41, 0x72, 0x58, 0x6e, 0x61, 0x42, + 0x47, 0x53, 0x4d, 0x72, 0x6d, 0x41, 0x45, 0x36, 0x62, 0x53, 0x6d, 0x47, + 0x77, 0x71, 0x0a, 0x43, 0x6c, 0x74, 0x32, 0x30, 0x75, 0x31, 0x44, 0x76, + 0x34, 0x51, 0x4e, 0x4f, 0x44, 0x66, 0x52, 0x36, 0x70, 0x36, 0x44, 0x0a, + 0x50, 0x42, 0x70, 0x38, 0x4f, 0x55, 0x55, 0x69, 0x54, 0x30, 0x32, 0x55, + 0x75, 0x6e, 0x37, 0x4c, 0x6f, 0x33, 0x4c, 0x43, 0x0a, 0x72, 0x54, 0x65, + 0x4e, 0x44, 0x58, 0x69, 0x42, 0x6f, 0x67, 0x67, 0x4a, 0x79, 0x4c, 0x77, + 0x79, 0x52, 0x43, 0x45, 0x72, 0x0a, 0x6b, 0x61, 0x6d, 0x36, 0x46, 0x48, + 0x31, 0x4c, 0x30, 0x45, 0x78, 0x63, 0x61, 0x71, 0x73, 0x6e, 0x72, 0x78, + 0x48, 0x73, 0x0a, 0x4c, 0x71, 0x48, 0x42, 0x4b, 0x64, 0x30, 0x73, 0x32, + 0x38, 0x5a, 0x41, 0x6d, 0x35, 0x67, 0x39, 0x4b, 0x48, 0x36, 0x31, 0x0a, + 0x70, 0x72, 0x58, 0x45, 0x56, 0x56, 0x58, 0x30, 0x52, 0x37, 0x57, 0x35, + 0x49, 0x6d, 0x50, 0x77, 0x36, 0x5a, 0x63, 0x41, 0x0a, 0x70, 0x4f, 0x30, + 0x45, 0x49, 0x78, 0x73, 0x65, 0x32, 0x72, 0x74, 0x37, 0x77, 0x4a, 0x46, + 0x39, 0x34, 0x78, 0x34, 0x48, 0x0a, 0x4a, 0x59, 0x54, 0x75, 0x4b, 0x39, + 0x6c, 0x73, 0x33, 0x79, 0x57, 0x77, 0x32, 0x48, 0x55, 0x42, 0x53, 0x77, + 0x5a, 0x5a, 0x0a, 0x6a, 0x71, 0x66, 0x79, 0x77, 0x57, 0x46, 0x58, 0x48, + 0x4f, 0x7a, 0x74, 0x49, 0x4c, 0x54, 0x61, 0x54, 0x55, 0x55, 0x7a, 0x0a, + 0x4a, 0x72, 0x48, 0x56, 0x45, 0x4c, 0x37, 0x72, 0x35, 0x70, 0x36, 0x59, + 0x75, 0x64, 0x43, 0x58, 0x54, 0x71, 0x74, 0x4e, 0x0a, 0x4f, 0x4a, 0x6b, + 0x4c, 0x57, 0x52, 0x71, 0x47, 0x45, 0x67, 0x34, 0x58, 0x36, 0x63, 0x6d, + 0x44, 0x74, 0x44, 0x73, 0x39, 0x0a, 0x32, 0x63, 0x5a, 0x6d, 0x6f, 0x32, + 0x37, 0x77, 0x58, 0x55, 0x37, 0x59, 0x4e, 0x6a, 0x39, 0x33, 0x4f, 0x46, + 0x50, 0x4d, 0x0a, 0x30, 0x52, 0x75, 0x36, 0x53, 0x41, 0x73, 0x65, 0x75, + 0x6d, 0x35, 0x71, 0x42, 0x6c, 0x4e, 0x4f, 0x39, 0x30, 0x73, 0x51, 0x0a, + 0x34, 0x47, 0x44, 0x70, 0x64, 0x67, 0x48, 0x64, 0x38, 0x31, 0x73, 0x74, + 0x46, 0x45, 0x59, 0x70, 0x53, 0x41, 0x51, 0x63, 0x0a, 0x41, 0x6c, 0x39, + 0x75, 0x6b, 0x76, 0x6a, 0x51, 0x73, 0x75, 0x73, 0x58, 0x36, 0x67, 0x5a, + 0x4e, 0x4a, 0x35, 0x37, 0x50, 0x0a, 0x46, 0x71, 0x73, 0x50, 0x6c, 0x41, + 0x73, 0x64, 0x4e, 0x4e, 0x50, 0x55, 0x39, 0x62, 0x46, 0x51, 0x7a, 0x48, + 0x4c, 0x35, 0x0a, 0x47, 0x37, 0x5a, 0x72, 0x62, 0x42, 0x50, 0x48, 0x51, + 0x70, 0x76, 0x4a, 0x44, 0x6e, 0x36, 0x32, 0x32, 0x6e, 0x61, 0x59, 0x0a, + 0x46, 0x69, 0x33, 0x46, 0x53, 0x75, 0x62, 0x74, 0x62, 0x59, 0x6c, 0x44, + 0x51, 0x67, 0x6e, 0x64, 0x42, 0x4b, 0x4c, 0x4e, 0x0a, 0x31, 0x6d, 0x74, + 0x6a, 0x76, 0x7a, 0x39, 0x32, 0x50, 0x5a, 0x43, 0x6e, 0x57, 0x4a, 0x4e, + 0x62, 0x37, 0x79, 0x69, 0x6f, 0x0a, 0x48, 0x54, 0x6a, 0x5a, 0x50, 0x57, + 0x78, 0x73, 0x75, 0x5a, 0x71, 0x31, 0x65, 0x32, 0x67, 0x6a, 0x35, 0x7a, + 0x6a, 0x55, 0x0a, 0x52, 0x4a, 0x31, 0x75, 0x57, 0x62, 0x53, 0x77, 0x46, + 0x79, 0x33, 0x43, 0x46, 0x55, 0x63, 0x50, 0x63, 0x30, 0x49, 0x6f, 0x0a, + 0x35, 0x6e, 0x59, 0x76, 0x7a, 0x6a, 0x5a, 0x67, 0x48, 0x42, 0x74, 0x71, + 0x67, 0x73, 0x46, 0x52, 0x43, 0x66, 0x52, 0x4a, 0x0a, 0x78, 0x47, 0x68, + 0x32, 0x69, 0x76, 0x51, 0x50, 0x42, 0x46, 0x38, 0x69, 0x52, 0x6c, 0x4b, + 0x4f, 0x43, 0x7a, 0x6a, 0x55, 0x0a, 0x54, 0x59, 0x33, 0x7a, 0x64, 0x69, + 0x47, 0x75, 0x53, 0x74, 0x43, 0x6d, 0x7a, 0x4c, 0x36, 0x4a, 0x38, 0x34, + 0x6a, 0x39, 0x0a, 0x4b, 0x4c, 0x59, 0x33, 0x76, 0x69, 0x31, 0x31, 0x69, + 0x4a, 0x6c, 0x37, 0x62, 0x61, 0x79, 0x42, 0x47, 0x73, 0x7a, 0x7a, 0x0a, + 0x76, 0x57, 0x68, 0x46, 0x79, 0x78, 0x65, 0x4d, 0x79, 0x65, 0x64, 0x4c, + 0x6d, 0x4f, 0x76, 0x30, 0x41, 0x68, 0x65, 0x78, 0x0a, 0x41, 0x6c, 0x72, + 0x41, 0x53, 0x7a, 0x4f, 0x42, 0x61, 0x5a, 0x67, 0x38, 0x46, 0x49, 0x33, + 0x39, 0x4a, 0x37, 0x51, 0x68, 0x0a, 0x5a, 0x31, 0x49, 0x6f, 0x41, 0x69, + 0x41, 0x56, 0x63, 0x77, 0x62, 0x50, 0x44, 0x58, 0x72, 0x54, 0x42, 0x72, + 0x38, 0x30, 0x0a, 0x56, 0x47, 0x49, 0x58, 0x41, 0x7a, 0x46, 0x4f, 0x4c, + 0x36, 0x31, 0x67, 0x76, 0x42, 0x6b, 0x67, 0x78, 0x78, 0x59, 0x33, 0x0a, + 0x65, 0x34, 0x35, 0x75, 0x36, 0x64, 0x78, 0x45, 0x45, 0x59, 0x50, 0x45, + 0x6a, 0x49, 0x42, 0x57, 0x5a, 0x64, 0x38, 0x36, 0x0a, 0x6e, 0x77, 0x77, + 0x34, 0x4a, 0x45, 0x44, 0x57, 0x6a, 0x6d, 0x50, 0x5a, 0x75, 0x75, 0x62, + 0x79, 0x6e, 0x52, 0x41, 0x38, 0x0a, 0x7a, 0x33, 0x30, 0x42, 0x50, 0x6e, + 0x4b, 0x55, 0x55, 0x43, 0x39, 0x43, 0x45, 0x34, 0x36, 0x62, 0x4a, 0x57, + 0x76, 0x45, 0x0a, 0x37, 0x4d, 0x4c, 0x56, 0x6b, 0x76, 0x4d, 0x4f, 0x67, + 0x6b, 0x39, 0x37, 0x4b, 0x44, 0x79, 0x55, 0x47, 0x44, 0x68, 0x75, 0x0a, + 0x4e, 0x6c, 0x30, 0x4a, 0x4b, 0x36, 0x79, 0x74, 0x6e, 0x35, 0x49, 0x6c, + 0x42, 0x45, 0x31, 0x35, 0x70, 0x33, 0x59, 0x6d, 0x0a, 0x70, 0x58, 0x68, + 0x64, 0x49, 0x57, 0x6d, 0x4d, 0x70, 0x6a, 0x57, 0x69, 0x4c, 0x71, 0x38, + 0x35, 0x35, 0x38, 0x76, 0x4d, 0x0a, 0x66, 0x55, 0x66, 0x65, 0x43, 0x65, + 0x4b, 0x4c, 0x73, 0x55, 0x72, 0x5a, 0x54, 0x79, 0x64, 0x53, 0x76, 0x64, + 0x6b, 0x72, 0x0a, 0x78, 0x48, 0x4c, 0x4f, 0x70, 0x70, 0x46, 0x6b, 0x59, + 0x6b, 0x6a, 0x75, 0x4d, 0x70, 0x31, 0x6a, 0x32, 0x30, 0x6e, 0x59, 0x0a, + 0x75, 0x6c, 0x6f, 0x68, 0x4e, 0x72, 0x6f, 0x52, 0x36, 0x38, 0x30, 0x62, + 0x35, 0x43, 0x43, 0x6d, 0x49, 0x5a, 0x32, 0x4c, 0x0a, 0x35, 0x4d, 0x32, + 0x69, 0x7a, 0x79, 0x6d, 0x44, 0x6f, 0x67, 0x4c, 0x53, 0x6e, 0x36, 0x30, + 0x5a, 0x4c, 0x42, 0x50, 0x33, 0x0a, 0x32, 0x52, 0x45, 0x56, 0x30, 0x59, + 0x72, 0x4b, 0x35, 0x6f, 0x6c, 0x36, 0x65, 0x32, 0x6e, 0x75, 0x7a, 0x37, + 0x4e, 0x4b, 0x0a, 0x41, 0x54, 0x79, 0x5a, 0x50, 0x78, 0x4a, 0x54, 0x70, + 0x70, 0x5a, 0x62, 0x56, 0x6f, 0x35, 0x61, 0x5a, 0x6f, 0x68, 0x31, 0x0a, + 0x55, 0x75, 0x4e, 0x59, 0x52, 0x44, 0x31, 0x53, 0x6f, 0x75, 0x4d, 0x35, + 0x5a, 0x41, 0x6c, 0x7a, 0x49, 0x59, 0x32, 0x73, 0x0a, 0x6e, 0x43, 0x41, + 0x39, 0x43, 0x6b, 0x39, 0x6d, 0x78, 0x74, 0x46, 0x34, 0x79, 0x55, 0x38, + 0x48, 0x52, 0x6a, 0x61, 0x34, 0x0a, 0x4f, 0x63, 0x64, 0x41, 0x79, 0x37, + 0x7a, 0x66, 0x4f, 0x37, 0x74, 0x4f, 0x42, 0x33, 0x39, 0x37, 0x56, 0x4a, + 0x6c, 0x47, 0x0a, 0x34, 0x45, 0x63, 0x44, 0x64, 0x62, 0x77, 0x6d, 0x61, + 0x4d, 0x74, 0x6e, 0x44, 0x52, 0x58, 0x54, 0x30, 0x4d, 0x64, 0x6d, 0x0a, + 0x78, 0x65, 0x79, 0x66, 0x34, 0x78, 0x55, 0x36, 0x51, 0x69, 0x72, 0x51, + 0x66, 0x35, 0x50, 0x50, 0x5a, 0x75, 0x43, 0x33, 0x0a, 0x66, 0x33, 0x36, + 0x77, 0x7a, 0x39, 0x30, 0x76, 0x56, 0x36, 0x44, 0x4c, 0x41, 0x76, 0x49, + 0x65, 0x64, 0x37, 0x67, 0x70, 0x0a, 0x42, 0x65, 0x31, 0x6b, 0x59, 0x32, + 0x61, 0x4d, 0x6d, 0x61, 0x38, 0x32, 0x67, 0x6f, 0x66, 0x5a, 0x70, 0x6f, + 0x33, 0x67, 0x0a, 0x42, 0x7a, 0x45, 0x6d, 0x50, 0x78, 0x54, 0x71, 0x72, + 0x70, 0x57, 0x65, 0x6e, 0x4b, 0x37, 0x49, 0x67, 0x37, 0x78, 0x71, 0x0a, + 0x76, 0x79, 0x62, 0x6c, 0x72, 0x46, 0x5a, 0x4a, 0x71, 0x32, 0x6b, 0x6b, + 0x64, 0x46, 0x38, 0x4a, 0x31, 0x39, 0x59, 0x68, 0x0a, 0x77, 0x43, 0x78, + 0x6d, 0x47, 0x57, 0x4b, 0x43, 0x49, 0x33, 0x35, 0x68, 0x57, 0x45, 0x6e, + 0x30, 0x6e, 0x41, 0x49, 0x53, 0x0a, 0x41, 0x35, 0x34, 0x33, 0x6b, 0x67, + 0x53, 0x54, 0x38, 0x47, 0x33, 0x53, 0x59, 0x46, 0x52, 0x36, 0x34, 0x55, + 0x63, 0x7a, 0x0a, 0x56, 0x52, 0x44, 0x53, 0x38, 0x63, 0x41, 0x34, 0x6c, + 0x56, 0x45, 0x6e, 0x64, 0x33, 0x6e, 0x30, 0x6d, 0x7a, 0x7a, 0x4c, 0x0a, + 0x79, 0x55, 0x76, 0x47, 0x58, 0x6d, 0x70, 0x47, 0x42, 0x39, 0x72, 0x55, + 0x57, 0x6a, 0x37, 0x6c, 0x79, 0x5a, 0x76, 0x75, 0x0a, 0x4a, 0x61, 0x6d, + 0x71, 0x79, 0x4a, 0x78, 0x57, 0x63, 0x4a, 0x4c, 0x72, 0x48, 0x49, 0x43, + 0x43, 0x36, 0x57, 0x64, 0x62, 0x0a, 0x38, 0x35, 0x38, 0x6e, 0x52, 0x54, + 0x46, 0x38, 0x70, 0x53, 0x36, 0x6f, 0x44, 0x6b, 0x59, 0x52, 0x6a, 0x6d, + 0x47, 0x63, 0x0a, 0x39, 0x4a, 0x37, 0x62, 0x6d, 0x51, 0x64, 0x52, 0x77, + 0x6e, 0x78, 0x6f, 0x56, 0x50, 0x61, 0x65, 0x42, 0x6e, 0x4e, 0x57, 0x0a, + 0x45, 0x31, 0x79, 0x46, 0x65, 0x78, 0x69, 0x42, 0x47, 0x64, 0x35, 0x58, + 0x34, 0x7a, 0x72, 0x32, 0x6f, 0x68, 0x66, 0x39, 0x0a, 0x49, 0x6b, 0x73, + 0x35, 0x32, 0x49, 0x36, 0x79, 0x4b, 0x62, 0x30, 0x57, 0x37, 0x5a, 0x47, + 0x69, 0x67, 0x77, 0x43, 0x55, 0x0a, 0x55, 0x59, 0x37, 0x4a, 0x39, 0x50, + 0x77, 0x76, 0x59, 0x6c, 0x6f, 0x79, 0x55, 0x39, 0x4e, 0x6e, 0x53, 0x63, + 0x4d, 0x45, 0x0a, 0x36, 0x6e, 0x76, 0x59, 0x7a, 0x36, 0x69, 0x55, 0x4c, + 0x63, 0x78, 0x67, 0x74, 0x56, 0x76, 0x4c, 0x46, 0x62, 0x32, 0x58, 0x0a, + 0x48, 0x46, 0x35, 0x4a, 0x34, 0x55, 0x53, 0x62, 0x70, 0x30, 0x33, 0x36, + 0x71, 0x31, 0x63, 0x70, 0x58, 0x6c, 0x34, 0x6d, 0x0a, 0x33, 0x65, 0x34, + 0x39, 0x4b, 0x77, 0x65, 0x34, 0x4a, 0x34, 0x59, 0x6e, 0x41, 0x6f, 0x71, + 0x48, 0x41, 0x74, 0x4d, 0x45, 0x0a, 0x70, 0x71, 0x43, 0x65, 0x76, 0x74, + 0x79, 0x61, 0x62, 0x61, 0x31, 0x58, 0x4f, 0x4f, 0x62, 0x49, 0x43, 0x51, + 0x54, 0x50, 0x0a, 0x4c, 0x70, 0x45, 0x61, 0x49, 0x78, 0x47, 0x70, 0x6e, + 0x63, 0x43, 0x70, 0x77, 0x77, 0x73, 0x6e, 0x5a, 0x4b, 0x6e, 0x50, 0x0a, + 0x47, 0x5a, 0x79, 0x73, 0x46, 0x63, 0x41, 0x76, 0x41, 0x4f, 0x75, 0x41, + 0x37, 0x6c, 0x53, 0x65, 0x31, 0x78, 0x77, 0x46, 0x0a, 0x33, 0x65, 0x4a, + 0x51, 0x5a, 0x65, 0x48, 0x6f, 0x6d, 0x64, 0x6f, 0x4d, 0x57, 0x67, 0x78, + 0x75, 0x42, 0x4e, 0x6b, 0x6d, 0x0a, 0x41, 0x32, 0x34, 0x63, 0x43, 0x70, + 0x6a, 0x6d, 0x56, 0x4c, 0x42, 0x79, 0x36, 0x52, 0x33, 0x39, 0x42, 0x49, + 0x70, 0x32, 0x0a, 0x43, 0x73, 0x65, 0x64, 0x70, 0x76, 0x67, 0x6e, 0x32, + 0x77, 0x71, 0x56, 0x6d, 0x73, 0x48, 0x36, 0x4e, 0x5a, 0x47, 0x66, 0x0a, + 0x6e, 0x76, 0x36, 0x32, 0x55, 0x6f, 0x59, 0x69, 0x5a, 0x4d, 0x56, 0x69, + 0x7a, 0x44, 0x6c, 0x63, 0x4b, 0x41, 0x63, 0x72, 0x0a, 0x69, 0x59, 0x32, + 0x46, 0x6d, 0x39, 0x79, 0x4b, 0x34, 0x56, 0x77, 0x76, 0x6b, 0x4b, 0x52, + 0x6e, 0x33, 0x37, 0x37, 0x6a, 0x0a, 0x6d, 0x34, 0x74, 0x77, 0x68, 0x52, + 0x56, 0x78, 0x4c, 0x6a, 0x37, 0x74, 0x37, 0x36, 0x57, 0x6d, 0x5a, 0x37, + 0x6b, 0x68, 0x0a, 0x5a, 0x42, 0x31, 0x61, 0x78, 0x52, 0x41, 0x65, 0x75, + 0x45, 0x6b, 0x41, 0x6d, 0x4c, 0x37, 0x35, 0x43, 0x36, 0x41, 0x31, 0x0a, + 0x4b, 0x78, 0x66, 0x70, 0x55, 0x39, 0x4f, 0x54, 0x54, 0x56, 0x66, 0x4c, + 0x53, 0x6b, 0x65, 0x67, 0x31, 0x6a, 0x75, 0x50, 0x0a, 0x78, 0x4a, 0x67, + 0x7a, 0x4b, 0x62, 0x70, 0x57, 0x6a, 0x59, 0x4e, 0x49, 0x48, 0x43, 0x36, + 0x6d, 0x39, 0x44, 0x59, 0x66, 0x0a, 0x34, 0x43, 0x48, 0x66, 0x45, 0x46, + 0x6f, 0x4f, 0x30, 0x61, 0x6b, 0x61, 0x47, 0x55, 0x52, 0x5a, 0x6a, 0x72, + 0x72, 0x73, 0x0a, 0x6d, 0x76, 0x51, 0x39, 0x6d, 0x65, 0x43, 0x4d, 0x73, + 0x72, 0x74, 0x65, 0x55, 0x64, 0x77, 0x38, 0x73, 0x47, 0x62, 0x31, 0x0a, + 0x43, 0x53, 0x72, 0x6f, 0x68, 0x50, 0x38, 0x4a, 0x33, 0x59, 0x63, 0x6f, + 0x53, 0x77, 0x6d, 0x47, 0x72, 0x44, 0x53, 0x46, 0x0a, 0x4c, 0x75, 0x72, + 0x4e, 0x77, 0x46, 0x4e, 0x42, 0x4e, 0x66, 0x48, 0x75, 0x54, 0x52, 0x52, + 0x62, 0x75, 0x4b, 0x71, 0x67, 0x0a, 0x5a, 0x47, 0x65, 0x74, 0x53, 0x45, + 0x59, 0x54, 0x53, 0x6d, 0x54, 0x59, 0x66, 0x50, 0x4f, 0x63, 0x48, 0x39, + 0x6a, 0x72, 0x0a, 0x63, 0x61, 0x43, 0x54, 0x41, 0x45, 0x30, 0x31, 0x75, + 0x55, 0x57, 0x57, 0x64, 0x6f, 0x43, 0x41, 0x68, 0x6a, 0x56, 0x6d, 0x0a, + 0x6a, 0x70, 0x55, 0x79, 0x62, 0x76, 0x7a, 0x61, 0x4e, 0x66, 0x45, 0x6e, + 0x73, 0x47, 0x51, 0x4c, 0x67, 0x5a, 0x38, 0x70, 0x0a, 0x69, 0x63, 0x38, + 0x62, 0x58, 0x58, 0x34, 0x59, 0x69, 0x68, 0x53, 0x6f, 0x48, 0x71, 0x73, + 0x41, 0x59, 0x6d, 0x47, 0x30, 0x0a, 0x42, 0x4c, 0x4d, 0x42, 0x65, 0x43, + 0x74, 0x4d, 0x39, 0x56, 0x65, 0x37, 0x46, 0x51, 0x62, 0x6d, 0x33, 0x67, + 0x41, 0x51, 0x0a, 0x31, 0x78, 0x65, 0x70, 0x75, 0x75, 0x30, 0x77, 0x6b, + 0x4c, 0x62, 0x64, 0x52, 0x57, 0x47, 0x49, 0x64, 0x6b, 0x78, 0x75, 0x0a, + 0x53, 0x7a, 0x70, 0x73, 0x30, 0x35, 0x45, 0x4e, 0x7a, 0x68, 0x57, 0x59, + 0x4c, 0x59, 0x74, 0x65, 0x4b, 0x6a, 0x4d, 0x46, 0x0a, 0x47, 0x77, 0x62, + 0x37, 0x61, 0x5a, 0x62, 0x54, 0x45, 0x59, 0x79, 0x44, 0x6a, 0x73, 0x32, + 0x78, 0x4f, 0x4e, 0x37, 0x71, 0x0a, 0x37, 0x42, 0x56, 0x58, 0x33, 0x57, + 0x6a, 0x58, 0x38, 0x38, 0x77, 0x52, 0x31, 0x67, 0x39, 0x47, 0x62, 0x37, + 0x30, 0x6c, 0x0a, 0x6c, 0x70, 0x45, 0x34, 0x52, 0x68, 0x52, 0x4d, 0x55, + 0x44, 0x67, 0x44, 0x6a, 0x30, 0x4c, 0x53, 0x4e, 0x33, 0x58, 0x53, 0x0a, + 0x41, 0x54, 0x79, 0x6e, 0x53, 0x5a, 0x53, 0x39, 0x6f, 0x76, 0x4a, 0x6b, + 0x51, 0x74, 0x75, 0x37, 0x46, 0x6f, 0x54, 0x54, 0x0a, 0x42, 0x48, 0x49, + 0x72, 0x52, 0x55, 0x52, 0x35, 0x46, 0x59, 0x77, 0x57, 0x36, 0x6a, 0x73, + 0x30, 0x52, 0x39, 0x38, 0x42, 0x0a, 0x53, 0x31, 0x51, 0x6e, 0x34, 0x43, + 0x72, 0x54, 0x4f, 0x30, 0x67, 0x76, 0x4b, 0x42, 0x35, 0x54, 0x4b, 0x75, + 0x38, 0x77, 0x0a, 0x42, 0x39, 0x72, 0x41, 0x6a, 0x72, 0x54, 0x52, 0x71, + 0x4f, 0x65, 0x5a, 0x52, 0x73, 0x7a, 0x31, 0x36, 0x57, 0x51, 0x47, 0x0a, + 0x58, 0x75, 0x6f, 0x31, 0x42, 0x34, 0x6a, 0x58, 0x46, 0x42, 0x4c, 0x79, + 0x56, 0x41, 0x69, 0x31, 0x55, 0x43, 0x47, 0x76, 0x0a, 0x43, 0x45, 0x78, + 0x68, 0x6d, 0x6f, 0x78, 0x49, 0x6b, 0x79, 0x4f, 0x6f, 0x4c, 0x6d, 0x58, + 0x68, 0x30, 0x63, 0x4d, 0x55, 0x0a, 0x4d, 0x72, 0x69, 0x56, 0x6e, 0x6b, + 0x4f, 0x31, 0x53, 0x43, 0x65, 0x6a, 0x6e, 0x52, 0x44, 0x54, 0x66, 0x6f, + 0x47, 0x53, 0x0a, 0x6e, 0x33, 0x34, 0x43, 0x46, 0x59, 0x32, 0x6f, 0x71, + 0x70, 0x31, 0x65, 0x51, 0x4f, 0x4a, 0x57, 0x6b, 0x4a, 0x41, 0x5a, 0x0a, + 0x65, 0x65, 0x58, 0x39, 0x69, 0x65, 0x59, 0x45, 0x75, 0x6c, 0x4e, 0x4c, + 0x4e, 0x6f, 0x34, 0x71, 0x78, 0x76, 0x36, 0x51, 0x0a, 0x49, 0x53, 0x66, + 0x70, 0x69, 0x65, 0x39, 0x39, 0x52, 0x78, 0x4e, 0x54, 0x70, 0x4a, 0x31, + 0x43, 0x6f, 0x37, 0x75, 0x6f, 0x0a, 0x36, 0x61, 0x6a, 0x73, 0x46, 0x5a, + 0x43, 0x68, 0x75, 0x36, 0x4f, 0x55, 0x76, 0x68, 0x39, 0x52, 0x56, 0x73, + 0x37, 0x4f, 0x0a, 0x57, 0x6b, 0x4a, 0x77, 0x61, 0x71, 0x74, 0x43, 0x57, + 0x50, 0x4b, 0x64, 0x74, 0x46, 0x35, 0x73, 0x6c, 0x31, 0x6d, 0x68, 0x0a, + 0x56, 0x73, 0x6c, 0x63, 0x50, 0x6f, 0x48, 0x78, 0x58, 0x54, 0x41, 0x37, + 0x56, 0x54, 0x47, 0x48, 0x57, 0x74, 0x47, 0x76, 0x0a, 0x71, 0x6a, 0x7a, + 0x44, 0x38, 0x44, 0x59, 0x73, 0x4e, 0x63, 0x6b, 0x6f, 0x42, 0x47, 0x57, + 0x57, 0x30, 0x72, 0x57, 0x5a, 0x0a, 0x78, 0x30, 0x73, 0x32, 0x37, 0x6d, + 0x50, 0x6f, 0x6e, 0x33, 0x73, 0x57, 0x34, 0x4a, 0x64, 0x54, 0x6a, 0x74, + 0x47, 0x45, 0x0a, 0x4c, 0x55, 0x59, 0x4d, 0x65, 0x57, 0x76, 0x41, 0x70, + 0x56, 0x4d, 0x74, 0x6f, 0x39, 0x32, 0x6b, 0x63, 0x74, 0x36, 0x41, 0x0a, + 0x79, 0x37, 0x68, 0x70, 0x74, 0x42, 0x48, 0x68, 0x54, 0x43, 0x32, 0x6f, + 0x5a, 0x35, 0x32, 0x69, 0x55, 0x45, 0x31, 0x44, 0x0a, 0x57, 0x39, 0x54, + 0x66, 0x44, 0x6b, 0x69, 0x52, 0x43, 0x35, 0x36, 0x54, 0x76, 0x68, 0x70, + 0x59, 0x41, 0x66, 0x6f, 0x65, 0x0a, 0x41, 0x34, 0x47, 0x37, 0x6d, 0x7a, + 0x70, 0x62, 0x48, 0x61, 0x55, 0x68, 0x44, 0x34, 0x59, 0x4d, 0x6e, 0x71, + 0x69, 0x73, 0x0a, 0x64, 0x4a, 0x49, 0x54, 0x49, 0x33, 0x33, 0x6c, 0x42, + 0x48, 0x77, 0x67, 0x72, 0x75, 0x76, 0x45, 0x51, 0x6d, 0x4d, 0x67, 0x0a, + 0x51, 0x54, 0x69, 0x6f, 0x44, 0x69, 0x57, 0x49, 0x62, 0x35, 0x53, 0x6e, + 0x6d, 0x42, 0x4f, 0x78, 0x52, 0x4f, 0x6c, 0x47, 0x0a, 0x52, 0x56, 0x54, + 0x41, 0x37, 0x67, 0x37, 0x58, 0x43, 0x42, 0x68, 0x6a, 0x34, 0x76, 0x36, + 0x61, 0x78, 0x48, 0x68, 0x4a, 0x0a, 0x49, 0x32, 0x4b, 0x43, 0x30, 0x67, + 0x71, 0x33, 0x45, 0x30, 0x71, 0x6e, 0x6d, 0x56, 0x6b, 0x55, 0x5a, 0x79, + 0x6c, 0x37, 0x0a, 0x48, 0x74, 0x73, 0x39, 0x48, 0x31, 0x36, 0x47, 0x41, + 0x59, 0x37, 0x59, 0x75, 0x4b, 0x47, 0x53, 0x43, 0x6e, 0x62, 0x62, 0x0a, + 0x65, 0x53, 0x77, 0x4e, 0x4f, 0x69, 0x77, 0x53, 0x64, 0x49, 0x36, 0x34, + 0x38, 0x6c, 0x79, 0x47, 0x41, 0x75, 0x52, 0x58, 0x0a, 0x47, 0x48, 0x68, + 0x4b, 0x37, 0x33, 0x6e, 0x61, 0x78, 0x6c, 0x31, 0x49, 0x52, 0x4e, 0x44, + 0x52, 0x68, 0x6b, 0x55, 0x38, 0x0a, 0x6f, 0x45, 0x47, 0x57, 0x52, 0x53, + 0x75, 0x52, 0x49, 0x6f, 0x43, 0x34, 0x6d, 0x50, 0x43, 0x46, 0x37, 0x73, + 0x6b, 0x61, 0x0a, 0x41, 0x64, 0x4e, 0x4d, 0x6f, 0x4e, 0x79, 0x5a, 0x45, + 0x39, 0x6d, 0x54, 0x68, 0x49, 0x47, 0x4c, 0x57, 0x6e, 0x57, 0x72, 0x0a, + 0x30, 0x56, 0x31, 0x6d, 0x57, 0x46, 0x30, 0x34, 0x69, 0x6b, 0x68, 0x4c, + 0x56, 0x41, 0x4f, 0x37, 0x63, 0x35, 0x35, 0x30, 0x0a, 0x6b, 0x4a, 0x6c, + 0x4a, 0x75, 0x33, 0x68, 0x4d, 0x73, 0x56, 0x49, 0x31, 0x38, 0x58, 0x67, + 0x38, 0x61, 0x77, 0x62, 0x7a, 0x0a, 0x61, 0x79, 0x43, 0x33, 0x49, 0x41, + 0x43, 0x64, 0x4e, 0x6f, 0x49, 0x6f, 0x30, 0x6a, 0x35, 0x57, 0x54, 0x42, + 0x5a, 0x52, 0x0a, 0x48, 0x6d, 0x46, 0x78, 0x6b, 0x36, 0x4a, 0x73, 0x42, + 0x35, 0x30, 0x30, 0x51, 0x6d, 0x78, 0x71, 0x62, 0x51, 0x34, 0x6b, 0x0a, + 0x65, 0x4e, 0x77, 0x6e, 0x32, 0x30, 0x6b, 0x68, 0x4e, 0x75, 0x39, 0x56, + 0x75, 0x56, 0x57, 0x4f, 0x37, 0x70, 0x79, 0x43, 0x0a, 0x35, 0x6e, 0x35, + 0x65, 0x39, 0x6e, 0x4a, 0x39, 0x72, 0x4a, 0x4b, 0x65, 0x50, 0x7a, 0x4f, + 0x47, 0x36, 0x6d, 0x76, 0x30, 0x0a, 0x69, 0x68, 0x5a, 0x45, 0x30, 0x73, + 0x4f, 0x72, 0x51, 0x58, 0x41, 0x39, 0x63, 0x30, 0x6d, 0x77, 0x53, 0x34, + 0x45, 0x73, 0x0a, 0x4e, 0x71, 0x47, 0x75, 0x77, 0x51, 0x33, 0x69, 0x6c, + 0x6d, 0x4b, 0x4f, 0x78, 0x4d, 0x70, 0x4b, 0x64, 0x53, 0x78, 0x51, 0x0a, + 0x47, 0x6c, 0x79, 0x74, 0x59, 0x66, 0x70, 0x30, 0x68, 0x76, 0x70, 0x4c, + 0x4c, 0x47, 0x77, 0x64, 0x48, 0x6f, 0x79, 0x71, 0x0a, 0x31, 0x4f, 0x64, + 0x76, 0x52, 0x47, 0x4b, 0x41, 0x65, 0x67, 0x70, 0x37, 0x77, 0x4d, 0x64, + 0x56, 0x69, 0x6f, 0x51, 0x4f, 0x0a, 0x4c, 0x75, 0x44, 0x4e, 0x48, 0x31, + 0x61, 0x39, 0x44, 0x61, 0x56, 0x64, 0x4f, 0x6b, 0x36, 0x45, 0x58, 0x56, + 0x35, 0x71, 0x0a, 0x39, 0x79, 0x47, 0x44, 0x39, 0x67, 0x68, 0x53, 0x36, + 0x79, 0x49, 0x30, 0x70, 0x45, 0x39, 0x6a, 0x5a, 0x57, 0x4e, 0x47, 0x0a, + 0x71, 0x5a, 0x53, 0x38, 0x73, 0x42, 0x70, 0x39, 0x36, 0x42, 0x64, 0x63, + 0x49, 0x33, 0x32, 0x30, 0x78, 0x58, 0x51, 0x6d, 0x0a, 0x5a, 0x61, 0x36, + 0x6d, 0x62, 0x4b, 0x45, 0x57, 0x39, 0x48, 0x64, 0x4e, 0x71, 0x71, 0x48, + 0x73, 0x30, 0x42, 0x68, 0x55, 0x0a, 0x57, 0x43, 0x6c, 0x48, 0x56, 0x5a, + 0x71, 0x57, 0x59, 0x6e, 0x4f, 0x6f, 0x61, 0x4c, 0x63, 0x37, 0x47, 0x37, + 0x43, 0x4b, 0x0a, 0x75, 0x71, 0x6a, 0x4f, 0x6b, 0x56, 0x4a, 0x67, 0x58, + 0x4c, 0x72, 0x6b, 0x55, 0x6c, 0x6c, 0x39, 0x68, 0x6b, 0x6f, 0x72, 0x0a, + 0x56, 0x59, 0x68, 0x64, 0x30, 0x52, 0x4b, 0x79, 0x7a, 0x39, 0x52, 0x64, + 0x56, 0x6c, 0x53, 0x59, 0x32, 0x32, 0x49, 0x4c, 0x0a, 0x34, 0x6f, 0x63, + 0x44, 0x45, 0x4f, 0x32, 0x49, 0x41, 0x34, 0x54, 0x37, 0x6e, 0x33, 0x64, + 0x71, 0x64, 0x6f, 0x4a, 0x71, 0x0a, 0x75, 0x74, 0x46, 0x5a, 0x31, 0x76, + 0x51, 0x37, 0x50, 0x6c, 0x4b, 0x30, 0x44, 0x50, 0x55, 0x4e, 0x6a, 0x68, + 0x69, 0x6f, 0x0a, 0x59, 0x44, 0x6d, 0x6e, 0x6d, 0x36, 0x46, 0x74, 0x62, + 0x59, 0x74, 0x55, 0x38, 0x38, 0x45, 0x4e, 0x4a, 0x43, 0x63, 0x52, 0x0a, + 0x4a, 0x7a, 0x76, 0x65, 0x78, 0x44, 0x48, 0x50, 0x33, 0x5a, 0x50, 0x58, + 0x4c, 0x55, 0x53, 0x7a, 0x61, 0x53, 0x64, 0x58, 0x0a, 0x74, 0x75, 0x59, + 0x57, 0x50, 0x6a, 0x6a, 0x71, 0x45, 0x6d, 0x48, 0x6a, 0x76, 0x52, 0x66, + 0x31, 0x45, 0x56, 0x48, 0x38, 0x0a, 0x6d, 0x4d, 0x71, 0x5a, 0x41, 0x50, + 0x36, 0x53, 0x42, 0x6d, 0x39, 0x6f, 0x42, 0x75, 0x53, 0x58, 0x49, 0x6f, + 0x58, 0x67, 0x0a, 0x44, 0x69, 0x41, 0x38, 0x6b, 0x33, 0x76, 0x4c, 0x7a, + 0x4e, 0x58, 0x6b, 0x32, 0x6d, 0x6d, 0x51, 0x79, 0x76, 0x48, 0x4a, 0x0a, + 0x51, 0x63, 0x6f, 0x69, 0x4b, 0x71, 0x53, 0x30, 0x33, 0x34, 0x53, 0x59, + 0x47, 0x41, 0x70, 0x36, 0x44, 0x78, 0x64, 0x34, 0x0a, 0x55, 0x71, 0x6a, + 0x78, 0x53, 0x47, 0x45, 0x68, 0x68, 0x76, 0x59, 0x62, 0x53, 0x44, 0x42, + 0x67, 0x46, 0x34, 0x53, 0x46, 0x0a, 0x35, 0x45, 0x50, 0x30, 0x4d, 0x48, + 0x36, 0x6c, 0x4d, 0x38, 0x71, 0x72, 0x55, 0x48, 0x48, 0x71, 0x6d, 0x37, + 0x4d, 0x47, 0x0a, 0x77, 0x70, 0x6a, 0x33, 0x58, 0x49, 0x35, 0x34, 0x62, + 0x50, 0x44, 0x56, 0x38, 0x48, 0x4b, 0x74, 0x44, 0x71, 0x42, 0x49, 0x0a, + 0x4a, 0x39, 0x4a, 0x71, 0x45, 0x4c, 0x4e, 0x75, 0x42, 0x43, 0x43, 0x45, + 0x35, 0x31, 0x69, 0x78, 0x59, 0x43, 0x49, 0x53, 0x0a, 0x7a, 0x75, 0x54, + 0x79, 0x31, 0x57, 0x79, 0x4d, 0x61, 0x4a, 0x76, 0x64, 0x78, 0x65, 0x50, + 0x59, 0x7a, 0x41, 0x67, 0x77, 0x0a, 0x47, 0x66, 0x37, 0x47, 0x73, 0x4d, + 0x66, 0x78, 0x57, 0x50, 0x39, 0x6b, 0x63, 0x4e, 0x6c, 0x76, 0x5a, 0x58, + 0x36, 0x61, 0x0a, 0x56, 0x69, 0x6d, 0x72, 0x69, 0x50, 0x57, 0x5a, 0x59, + 0x71, 0x78, 0x77, 0x78, 0x63, 0x45, 0x44, 0x47, 0x54, 0x63, 0x50, 0x0a, + 0x79, 0x59, 0x7a, 0x34, 0x57, 0x6c, 0x7a, 0x5a, 0x46, 0x63, 0x73, 0x42, + 0x69, 0x42, 0x39, 0x6d, 0x74, 0x4c, 0x35, 0x32, 0x0a, 0x65, 0x43, 0x48, + 0x65, 0x50, 0x67, 0x4a, 0x72, 0x47, 0x62, 0x45, 0x35, 0x50, 0x61, 0x42, + 0x4a, 0x66, 0x49, 0x72, 0x59, 0x0a, 0x4e, 0x70, 0x56, 0x6d, 0x6c, 0x64, + 0x31, 0x75, 0x53, 0x76, 0x68, 0x6b, 0x64, 0x33, 0x72, 0x39, 0x50, 0x76, + 0x48, 0x47, 0x0a, 0x48, 0x4e, 0x41, 0x79, 0x46, 0x75, 0x6a, 0x78, 0x4a, + 0x69, 0x30, 0x49, 0x4a, 0x76, 0x6d, 0x73, 0x39, 0x50, 0x37, 0x5a, 0x0a, + 0x4b, 0x44, 0x31, 0x41, 0x76, 0x52, 0x77, 0x67, 0x74, 0x78, 0x41, 0x68, + 0x57, 0x68, 0x35, 0x7a, 0x6a, 0x77, 0x58, 0x67, 0x0a, 0x47, 0x6f, 0x61, + 0x46, 0x55, 0x6c, 0x6b, 0x34, 0x75, 0x32, 0x47, 0x59, 0x37, 0x65, 0x79, + 0x6b, 0x31, 0x70, 0x51, 0x30, 0x0a, 0x41, 0x48, 0x38, 0x55, 0x61, 0x73, + 0x7a, 0x4f, 0x58, 0x46, 0x5a, 0x6f, 0x45, 0x47, 0x53, 0x64, 0x55, 0x75, + 0x58, 0x62, 0x0a, 0x32, 0x45, 0x65, 0x47, 0x70, 0x67, 0x4b, 0x72, 0x46, + 0x4d, 0x31, 0x59, 0x48, 0x34, 0x59, 0x55, 0x4e, 0x61, 0x45, 0x51, 0x0a, + 0x59, 0x56, 0x63, 0x62, 0x59, 0x6d, 0x4f, 0x56, 0x4e, 0x30, 0x55, 0x45, + 0x63, 0x4f, 0x51, 0x42, 0x59, 0x71, 0x70, 0x54, 0x0a, 0x4c, 0x78, 0x5a, + 0x53, 0x76, 0x33, 0x4c, 0x68, 0x6b, 0x4f, 0x57, 0x6b, 0x6b, 0x62, 0x32, + 0x54, 0x69, 0x78, 0x62, 0x35, 0x0a, 0x39, 0x42, 0x67, 0x45, 0x71, 0x48, + 0x5a, 0x63, 0x47, 0x57, 0x71, 0x36, 0x6e, 0x53, 0x6a, 0x63, 0x41, 0x6e, + 0x6e, 0x38, 0x0a, 0x69, 0x57, 0x4a, 0x44, 0x76, 0x6e, 0x54, 0x51, 0x4c, + 0x64, 0x31, 0x75, 0x79, 0x6f, 0x4d, 0x56, 0x58, 0x69, 0x4c, 0x56, 0x0a, + 0x55, 0x74, 0x66, 0x4e, 0x73, 0x30, 0x59, 0x46, 0x49, 0x38, 0x5a, 0x67, + 0x4b, 0x48, 0x42, 0x58, 0x6e, 0x42, 0x52, 0x38, 0x0a, 0x72, 0x53, 0x51, + 0x51, 0x53, 0x41, 0x42, 0x51, 0x59, 0x4f, 0x47, 0x58, 0x67, 0x59, 0x6a, + 0x57, 0x76, 0x54, 0x54, 0x61, 0x0a, 0x33, 0x65, 0x55, 0x4f, 0x71, 0x31, + 0x49, 0x6b, 0x32, 0x76, 0x5a, 0x76, 0x64, 0x41, 0x31, 0x66, 0x44, 0x55, + 0x5a, 0x48, 0x0a, 0x56, 0x67, 0x69, 0x5a, 0x62, 0x52, 0x67, 0x38, 0x6d, + 0x79, 0x47, 0x79, 0x75, 0x39, 0x70, 0x6d, 0x4b, 0x38, 0x39, 0x70, 0x0a, + 0x61, 0x38, 0x6a, 0x55, 0x71, 0x70, 0x75, 0x30, 0x42, 0x46, 0x4f, 0x69, + 0x4f, 0x36, 0x33, 0x37, 0x71, 0x54, 0x6e, 0x72, 0x0a, 0x74, 0x71, 0x30, + 0x74, 0x75, 0x31, 0x4b, 0x44, 0x76, 0x65, 0x78, 0x74, 0x76, 0x31, 0x46, + 0x33, 0x63, 0x36, 0x4d, 0x7a, 0x0a, 0x77, 0x6b, 0x64, 0x42, 0x79, 0x4b, + 0x66, 0x55, 0x69, 0x65, 0x45, 0x4c, 0x4f, 0x79, 0x48, 0x46, 0x57, 0x66, + 0x6f, 0x4a, 0x0a, 0x44, 0x6d, 0x43, 0x55, 0x34, 0x70, 0x56, 0x76, 0x48, + 0x69, 0x45, 0x53, 0x6b, 0x53, 0x66, 0x53, 0x37, 0x48, 0x76, 0x30, 0x0a, + 0x50, 0x49, 0x70, 0x42, 0x59, 0x68, 0x63, 0x63, 0x52, 0x44, 0x73, 0x44, + 0x5a, 0x5a, 0x53, 0x56, 0x49, 0x4d, 0x48, 0x79, 0x0a, 0x52, 0x61, 0x56, + 0x38, 0x65, 0x71, 0x47, 0x33, 0x4d, 0x66, 0x4e, 0x58, 0x4e, 0x77, 0x44, + 0x75, 0x6d, 0x75, 0x66, 0x45, 0x0a, 0x4e, 0x79, 0x6b, 0x6e, 0x56, 0x57, + 0x70, 0x61, 0x32, 0x32, 0x4e, 0x6a, 0x4b, 0x63, 0x4b, 0x6d, 0x79, 0x72, + 0x63, 0x36, 0x0a, 0x6c, 0x59, 0x63, 0x6d, 0x47, 0x4d, 0x4b, 0x50, 0x76, + 0x63, 0x63, 0x61, 0x72, 0x57, 0x6d, 0x79, 0x4b, 0x70, 0x72, 0x6c, 0x0a, + 0x76, 0x58, 0x59, 0x50, 0x36, 0x53, 0x73, 0x39, 0x33, 0x55, 0x61, 0x61, + 0x42, 0x6d, 0x73, 0x7a, 0x6f, 0x52, 0x6d, 0x6e, 0x0a, 0x38, 0x47, 0x65, + 0x38, 0x50, 0x72, 0x58, 0x42, 0x4d, 0x31, 0x46, 0x6d, 0x33, 0x38, 0x36, + 0x54, 0x52, 0x63, 0x50, 0x76, 0x0a, 0x4f, 0x4a, 0x6c, 0x32, 0x4e, 0x32, + 0x32, 0x39, 0x6d, 0x31, 0x6a, 0x45, 0x52, 0x44, 0x4e, 0x70, 0x6d, 0x4f, + 0x4d, 0x41, 0x0a, 0x64, 0x74, 0x35, 0x45, 0x6a, 0x5a, 0x77, 0x38, 0x44, + 0x51, 0x77, 0x36, 0x59, 0x77, 0x79, 0x49, 0x76, 0x55, 0x73, 0x75, 0x0a, + 0x56, 0x4d, 0x5a, 0x4a, 0x65, 0x71, 0x34, 0x7a, 0x59, 0x54, 0x53, 0x67, + 0x4a, 0x68, 0x59, 0x51, 0x63, 0x74, 0x77, 0x51, 0x0a, 0x4e, 0x51, 0x32, + 0x66, 0x48, 0x30, 0x4c, 0x71, 0x55, 0x57, 0x37, 0x6c, 0x55, 0x41, 0x72, + 0x68, 0x52, 0x66, 0x55, 0x36, 0x0a, 0x73, 0x37, 0x53, 0x50, 0x73, 0x61, + 0x4d, 0x42, 0x32, 0x7a, 0x63, 0x54, 0x68, 0x4c, 0x62, 0x39, 0x54, 0x48, + 0x55, 0x50, 0x0a, 0x62, 0x6c, 0x46, 0x5a, 0x6a, 0x56, 0x33, 0x78, 0x77, + 0x4c, 0x4e, 0x6a, 0x45, 0x4d, 0x42, 0x70, 0x46, 0x65, 0x4b, 0x74, 0x0a, + 0x64, 0x50, 0x47, 0x79, 0x74, 0x4e, 0x36, 0x58, 0x59, 0x79, 0x46, 0x62, + 0x6a, 0x4c, 0x51, 0x55, 0x33, 0x57, 0x43, 0x57, 0x0a, 0x65, 0x66, 0x4c, + 0x35, 0x78, 0x66, 0x58, 0x63, 0x51, 0x6d, 0x62, 0x75, 0x34, 0x55, 0x6e, + 0x74, 0x5a, 0x43, 0x44, 0x79, 0x0a, 0x78, 0x33, 0x6b, 0x74, 0x67, 0x4d, + 0x4a, 0x78, 0x4c, 0x5a, 0x61, 0x53, 0x52, 0x58, 0x51, 0x46, 0x34, 0x45, + 0x7a, 0x45, 0x0a, 0x45, 0x44, 0x47, 0x36, 0x69, 0x35, 0x47, 0x4d, 0x70, + 0x42, 0x48, 0x69, 0x76, 0x61, 0x43, 0x5a, 0x56, 0x33, 0x77, 0x43, 0x0a, + 0x35, 0x36, 0x77, 0x6f, 0x74, 0x79, 0x36, 0x70, 0x37, 0x6c, 0x38, 0x63, + 0x52, 0x37, 0x4e, 0x4d, 0x6b, 0x59, 0x56, 0x6d, 0x0a, 0x69, 0x51, 0x5a, + 0x66, 0x50, 0x5a, 0x46, 0x54, 0x68, 0x70, 0x71, 0x6f, 0x42, 0x47, 0x5a, + 0x58, 0x56, 0x6b, 0x37, 0x32, 0x0a, 0x4d, 0x50, 0x51, 0x53, 0x39, 0x69, + 0x4d, 0x67, 0x44, 0x49, 0x6e, 0x47, 0x49, 0x47, 0x6f, 0x79, 0x62, 0x44, + 0x31, 0x78, 0x0a, 0x33, 0x4d, 0x37, 0x66, 0x39, 0x72, 0x79, 0x63, 0x5a, + 0x57, 0x63, 0x69, 0x34, 0x71, 0x73, 0x67, 0x6e, 0x35, 0x6e, 0x64, 0x0a, + 0x48, 0x6f, 0x30, 0x38, 0x41, 0x35, 0x5a, 0x73, 0x70, 0x71, 0x6a, 0x54, + 0x6a, 0x4e, 0x6d, 0x77, 0x66, 0x51, 0x59, 0x6a, 0x0a, 0x6a, 0x52, 0x42, + 0x61, 0x41, 0x37, 0x51, 0x56, 0x42, 0x4a, 0x44, 0x58, 0x75, 0x74, 0x4c, + 0x55, 0x4e, 0x62, 0x53, 0x65, 0x0a, 0x4a, 0x75, 0x34, 0x4c, 0x66, 0x7a, + 0x75, 0x53, 0x49, 0x54, 0x67, 0x41, 0x6d, 0x4d, 0x6a, 0x4c, 0x77, 0x61, + 0x4c, 0x38, 0x0a, 0x72, 0x79, 0x77, 0x58, 0x7a, 0x75, 0x75, 0x78, 0x4d, + 0x6c, 0x7a, 0x39, 0x6e, 0x65, 0x46, 0x58, 0x37, 0x48, 0x4c, 0x33, 0x0a, + 0x34, 0x4c, 0x6f, 0x69, 0x32, 0x78, 0x75, 0x4c, 0x49, 0x72, 0x35, 0x4a, + 0x69, 0x36, 0x4c, 0x68, 0x65, 0x4d, 0x68, 0x36, 0x0a, 0x76, 0x69, 0x7a, + 0x69, 0x50, 0x6e, 0x35, 0x45, 0x6e, 0x55, 0x48, 0x6e, 0x63, 0x34, 0x63, + 0x79, 0x39, 0x6a, 0x6b, 0x59, 0x0a, 0x70, 0x52, 0x6e, 0x36, 0x50, 0x79, + 0x70, 0x79, 0x37, 0x62, 0x31, 0x7a, 0x50, 0x61, 0x37, 0x58, 0x71, 0x57, + 0x6f, 0x38, 0x0a, 0x67, 0x63, 0x4e, 0x67, 0x55, 0x44, 0x48, 0x7a, 0x71, + 0x6c, 0x39, 0x47, 0x6a, 0x71, 0x4a, 0x41, 0x42, 0x37, 0x34, 0x65, 0x0a, + 0x30, 0x48, 0x79, 0x32, 0x6f, 0x31, 0x67, 0x43, 0x54, 0x52, 0x54, 0x55, + 0x72, 0x58, 0x45, 0x7a, 0x6d, 0x73, 0x4a, 0x7a, 0x0a, 0x70, 0x30, 0x6b, + 0x65, 0x53, 0x61, 0x71, 0x53, 0x7a, 0x56, 0x79, 0x42, 0x4f, 0x45, 0x77, + 0x47, 0x30, 0x73, 0x69, 0x64, 0x0a, 0x71, 0x44, 0x42, 0x37, 0x37, 0x6d, + 0x53, 0x36, 0x5a, 0x6f, 0x54, 0x30, 0x4f, 0x70, 0x66, 0x6b, 0x41, 0x63, + 0x31, 0x33, 0x0a, 0x42, 0x45, 0x6f, 0x4e, 0x45, 0x31, 0x37, 0x78, 0x6b, + 0x48, 0x62, 0x6a, 0x58, 0x6c, 0x79, 0x63, 0x53, 0x4d, 0x50, 0x7a, 0x0a, + 0x4d, 0x74, 0x32, 0x54, 0x41, 0x78, 0x39, 0x76, 0x35, 0x46, 0x73, 0x47, + 0x6a, 0x31, 0x42, 0x59, 0x6c, 0x69, 0x35, 0x76, 0x0a, 0x50, 0x4f, 0x6a, + 0x34, 0x63, 0x50, 0x6e, 0x7a, 0x46, 0x67, 0x74, 0x57, 0x6e, 0x4e, 0x49, + 0x4d, 0x4b, 0x42, 0x30, 0x51, 0x0a, 0x39, 0x41, 0x43, 0x31, 0x6a, 0x4d, + 0x63, 0x36, 0x52, 0x56, 0x4d, 0x5a, 0x55, 0x6a, 0x39, 0x36, 0x5a, 0x47, + 0x49, 0x73, 0x0a, 0x37, 0x44, 0x65, 0x42, 0x58, 0x46, 0x64, 0x39, 0x38, + 0x66, 0x73, 0x31, 0x77, 0x6f, 0x6b, 0x67, 0x71, 0x45, 0x4f, 0x51, 0x0a, + 0x54, 0x41, 0x38, 0x6d, 0x32, 0x6f, 0x35, 0x4e, 0x6d, 0x79, 0x34, 0x43, + 0x44, 0x6e, 0x67, 0x4f, 0x38, 0x32, 0x36, 0x5a, 0x0a, 0x30, 0x68, 0x62, + 0x44, 0x73, 0x38, 0x71, 0x72, 0x6f, 0x64, 0x4c, 0x63, 0x79, 0x75, 0x6d, + 0x61, 0x44, 0x7a, 0x6d, 0x4e, 0x0a, 0x4e, 0x39, 0x56, 0x61, 0x36, 0x48, + 0x68, 0x79, 0x32, 0x45, 0x78, 0x31, 0x6d, 0x47, 0x44, 0x38, 0x70, 0x76, + 0x36, 0x4a, 0x0a, 0x4f, 0x42, 0x43, 0x77, 0x6c, 0x77, 0x47, 0x36, 0x76, + 0x77, 0x51, 0x58, 0x69, 0x49, 0x4d, 0x4d, 0x47, 0x4a, 0x31, 0x71, 0x0a, + 0x5a, 0x4e, 0x66, 0x6e, 0x52, 0x38, 0x6d, 0x30, 0x78, 0x58, 0x58, 0x59, + 0x49, 0x70, 0x68, 0x53, 0x30, 0x38, 0x76, 0x45, 0x0a, 0x78, 0x57, 0x77, + 0x35, 0x6e, 0x44, 0x4e, 0x33, 0x4d, 0x73, 0x48, 0x43, 0x32, 0x73, 0x6c, + 0x46, 0x62, 0x51, 0x50, 0x34, 0x0a, 0x44, 0x63, 0x57, 0x6a, 0x68, 0x6a, + 0x75, 0x62, 0x4e, 0x33, 0x32, 0x76, 0x38, 0x32, 0x5a, 0x4b, 0x51, 0x31, + 0x73, 0x6c, 0x0a, 0x7a, 0x54, 0x69, 0x64, 0x33, 0x6d, 0x58, 0x6d, 0x6a, + 0x51, 0x76, 0x32, 0x37, 0x54, 0x54, 0x44, 0x48, 0x35, 0x50, 0x48, 0x0a, + 0x65, 0x76, 0x43, 0x38, 0x74, 0x58, 0x4c, 0x55, 0x4e, 0x4a, 0x4f, 0x50, + 0x53, 0x4b, 0x63, 0x51, 0x62, 0x63, 0x66, 0x48, 0x0a, 0x45, 0x36, 0x42, + 0x32, 0x4a, 0x58, 0x59, 0x6b, 0x7a, 0x66, 0x59, 0x4f, 0x63, 0x68, 0x69, + 0x4a, 0x74, 0x4f, 0x6c, 0x63, 0x0a, 0x76, 0x4c, 0x68, 0x54, 0x4f, 0x4c, + 0x66, 0x48, 0x66, 0x39, 0x62, 0x4d, 0x66, 0x6a, 0x68, 0x57, 0x6b, 0x4e, + 0x79, 0x39, 0x0a, 0x77, 0x68, 0x47, 0x4e, 0x75, 0x74, 0x6c, 0x7a, 0x6f, + 0x50, 0x35, 0x31, 0x50, 0x37, 0x69, 0x75, 0x75, 0x4f, 0x48, 0x38, 0x0a, + 0x63, 0x31, 0x6f, 0x7a, 0x30, 0x4e, 0x4e, 0x4e, 0x47, 0x37, 0x35, 0x41, + 0x6f, 0x53, 0x46, 0x56, 0x64, 0x30, 0x6d, 0x6e, 0x0a, 0x5a, 0x6f, 0x44, + 0x4f, 0x34, 0x62, 0x30, 0x78, 0x74, 0x73, 0x36, 0x79, 0x31, 0x6c, 0x76, + 0x50, 0x33, 0x33, 0x64, 0x63, 0x0a, 0x6c, 0x4f, 0x65, 0x49, 0x46, 0x49, + 0x4e, 0x6e, 0x50, 0x39, 0x33, 0x53, 0x32, 0x75, 0x49, 0x49, 0x58, 0x73, + 0x7a, 0x4e, 0x0a, 0x58, 0x46, 0x69, 0x68, 0x50, 0x43, 0x77, 0x47, 0x79, + 0x43, 0x42, 0x6c, 0x48, 0x30, 0x68, 0x32, 0x78, 0x73, 0x6f, 0x6c, 0x0a, + 0x4d, 0x32, 0x69, 0x33, 0x62, 0x58, 0x36, 0x46, 0x37, 0x64, 0x47, 0x46, + 0x78, 0x62, 0x4c, 0x57, 0x52, 0x74, 0x31, 0x53, 0x0a, 0x5a, 0x4b, 0x68, + 0x55, 0x6d, 0x42, 0x66, 0x4d, 0x73, 0x67, 0x41, 0x30, 0x6f, 0x37, 0x79, + 0x53, 0x59, 0x47, 0x48, 0x43, 0x0a, 0x49, 0x36, 0x65, 0x79, 0x39, 0x6c, + 0x6f, 0x4e, 0x76, 0x43, 0x48, 0x30, 0x4e, 0x4e, 0x32, 0x6c, 0x51, 0x70, + 0x32, 0x45, 0x0a, 0x6d, 0x42, 0x53, 0x79, 0x69, 0x54, 0x48, 0x53, 0x47, + 0x77, 0x6f, 0x32, 0x34, 0x4b, 0x46, 0x76, 0x31, 0x42, 0x36, 0x6c, 0x0a, + 0x4a, 0x5a, 0x32, 0x4d, 0x58, 0x58, 0x41, 0x30, 0x63, 0x49, 0x53, 0x32, + 0x65, 0x72, 0x4e, 0x6a, 0x4a, 0x4b, 0x38, 0x69, 0x0a, 0x35, 0x4b, 0x77, + 0x44, 0x65, 0x4d, 0x62, 0x6a, 0x39, 0x71, 0x55, 0x59, 0x55, 0x52, 0x70, + 0x52, 0x51, 0x6d, 0x4f, 0x33, 0x0a, 0x54, 0x74, 0x6d, 0x4e, 0x4e, 0x55, + 0x42, 0x66, 0x69, 0x4d, 0x73, 0x69, 0x6d, 0x30, 0x46, 0x50, 0x71, 0x59, + 0x6b, 0x73, 0x0a, 0x44, 0x72, 0x6f, 0x32, 0x42, 0x4f, 0x58, 0x78, 0x56, + 0x67, 0x4b, 0x54, 0x59, 0x54, 0x34, 0x6f, 0x53, 0x36, 0x4d, 0x37, 0x0a, + 0x37, 0x66, 0x67, 0x64, 0x4a, 0x7a, 0x63, 0x70, 0x59, 0x77, 0x53, 0x68, + 0x36, 0x57, 0x43, 0x36, 0x4c, 0x43, 0x69, 0x35, 0x0a, 0x42, 0x4c, 0x37, + 0x61, 0x6b, 0x35, 0x5a, 0x74, 0x38, 0x58, 0x48, 0x54, 0x73, 0x79, 0x54, + 0x48, 0x58, 0x58, 0x43, 0x34, 0x0a, 0x42, 0x70, 0x48, 0x55, 0x79, 0x65, + 0x7a, 0x4c, 0x64, 0x4e, 0x70, 0x39, 0x30, 0x69, 0x58, 0x59, 0x59, 0x6c, + 0x56, 0x6d, 0x0a, 0x56, 0x53, 0x64, 0x32, 0x72, 0x51, 0x30, 0x4f, 0x48, + 0x4a, 0x7a, 0x42, 0x55, 0x53, 0x68, 0x4e, 0x4b, 0x55, 0x58, 0x74, 0x0a, + 0x51, 0x6f, 0x56, 0x66, 0x41, 0x39, 0x67, 0x66, 0x6e, 0x4d, 0x75, 0x73, + 0x52, 0x63, 0x4d, 0x63, 0x6c, 0x7a, 0x34, 0x39, 0x0a, 0x70, 0x6f, 0x70, + 0x44, 0x31, 0x64, 0x6b, 0x35, 0x77, 0x6c, 0x61, 0x78, 0x57, 0x6c, 0x54, + 0x6e, 0x7a, 0x49, 0x50, 0x38, 0x0a, 0x50, 0x56, 0x72, 0x7a, 0x77, 0x4a, + 0x4f, 0x36, 0x52, 0x47, 0x70, 0x34, 0x52, 0x4c, 0x50, 0x79, 0x7a, 0x4d, + 0x59, 0x56, 0x0a, 0x67, 0x32, 0x6b, 0x51, 0x4a, 0x45, 0x69, 0x72, 0x4f, + 0x71, 0x73, 0x6f, 0x79, 0x48, 0x49, 0x41, 0x39, 0x61, 0x49, 0x55, 0x0a, + 0x49, 0x33, 0x59, 0x50, 0x35, 0x46, 0x4a, 0x72, 0x34, 0x6e, 0x70, 0x68, + 0x33, 0x49, 0x33, 0x38, 0x38, 0x5a, 0x4a, 0x38, 0x0a, 0x7a, 0x61, 0x6c, + 0x66, 0x75, 0x57, 0x71, 0x37, 0x63, 0x31, 0x69, 0x48, 0x6b, 0x6a, 0x41, + 0x6a, 0x38, 0x63, 0x75, 0x47, 0x0a, 0x56, 0x64, 0x34, 0x54, 0x36, 0x33, + 0x6e, 0x31, 0x6e, 0x51, 0x4d, 0x75, 0x6c, 0x37, 0x32, 0x46, 0x71, 0x69, + 0x76, 0x31, 0x0a, 0x78, 0x6c, 0x37, 0x4d, 0x53, 0x71, 0x4a, 0x48, 0x56, + 0x4b, 0x6e, 0x49, 0x54, 0x39, 0x4f, 0x33, 0x4e, 0x73, 0x4a, 0x33, 0x0a, + 0x30, 0x4d, 0x64, 0x52, 0x57, 0x32, 0x6a, 0x33, 0x56, 0x45, 0x49, 0x47, + 0x30, 0x38, 0x42, 0x47, 0x57, 0x44, 0x47, 0x42, 0x0a, 0x74, 0x6a, 0x4e, + 0x4f, 0x54, 0x42, 0x35, 0x62, 0x4d, 0x30, 0x45, 0x73, 0x30, 0x4d, 0x57, + 0x48, 0x75, 0x43, 0x49, 0x45, 0x0a, 0x52, 0x44, 0x4c, 0x64, 0x4e, 0x33, + 0x66, 0x32, 0x6c, 0x59, 0x70, 0x7a, 0x67, 0x30, 0x42, 0x4a, 0x6c, 0x31, + 0x58, 0x67, 0x0a, 0x32, 0x53, 0x68, 0x7a, 0x70, 0x65, 0x79, 0x62, 0x55, + 0x53, 0x30, 0x37, 0x70, 0x79, 0x46, 0x41, 0x72, 0x61, 0x66, 0x66, 0x0a, + 0x53, 0x33, 0x61, 0x38, 0x6f, 0x7a, 0x6b, 0x59, 0x43, 0x4f, 0x47, 0x7a, + 0x37, 0x57, 0x32, 0x43, 0x44, 0x72, 0x62, 0x57, 0x0a, 0x30, 0x4f, 0x31, + 0x33, 0x66, 0x42, 0x72, 0x63, 0x69, 0x50, 0x68, 0x6b, 0x53, 0x38, 0x73, + 0x49, 0x4e, 0x64, 0x59, 0x65, 0x0a, 0x61, 0x69, 0x75, 0x69, 0x4b, 0x53, + 0x41, 0x79, 0x6b, 0x72, 0x52, 0x43, 0x33, 0x63, 0x68, 0x36, 0x6b, 0x30, + 0x5a, 0x61, 0x0a, 0x57, 0x57, 0x30, 0x51, 0x76, 0x7a, 0x30, 0x79, 0x34, + 0x65, 0x71, 0x58, 0x32, 0x4f, 0x53, 0x37, 0x73, 0x49, 0x37, 0x78, 0x0a, + 0x77, 0x61, 0x55, 0x73, 0x47, 0x4c, 0x4a, 0x72, 0x36, 0x65, 0x50, 0x63, + 0x6c, 0x74, 0x73, 0x31, 0x69, 0x4d, 0x69, 0x6e, 0x0a, 0x7a, 0x5a, 0x32, + 0x34, 0x79, 0x71, 0x61, 0x50, 0x69, 0x78, 0x77, 0x46, 0x7a, 0x65, 0x66, + 0x56, 0x62, 0x35, 0x36, 0x6b, 0x0a, 0x48, 0x46, 0x42, 0x39, 0x30, 0x36, + 0x38, 0x56, 0x7a, 0x7a, 0x49, 0x6b, 0x4c, 0x61, 0x65, 0x73, 0x31, 0x6f, + 0x41, 0x79, 0x0a, 0x61, 0x4b, 0x53, 0x63, 0x30, 0x31, 0x6d, 0x30, 0x58, + 0x6e, 0x5a, 0x32, 0x35, 0x5a, 0x42, 0x36, 0x57, 0x47, 0x36, 0x64, 0x0a, + 0x57, 0x38, 0x69, 0x54, 0x6e, 0x50, 0x31, 0x65, 0x46, 0x67, 0x4e, 0x77, + 0x75, 0x73, 0x53, 0x33, 0x73, 0x4c, 0x35, 0x47, 0x0a, 0x34, 0x6f, 0x44, + 0x73, 0x74, 0x67, 0x6d, 0x6b, 0x30, 0x7a, 0x45, 0x43, 0x77, 0x66, 0x4f, + 0x33, 0x6a, 0x33, 0x33, 0x51, 0x0a, 0x35, 0x33, 0x4d, 0x6c, 0x6f, 0x65, + 0x59, 0x49, 0x53, 0x43, 0x68, 0x75, 0x73, 0x63, 0x77, 0x44, 0x6a, 0x65, + 0x31, 0x78, 0x0a, 0x4d, 0x6f, 0x4f, 0x35, 0x51, 0x4c, 0x74, 0x75, 0x49, + 0x75, 0x48, 0x42, 0x45, 0x59, 0x50, 0x79, 0x39, 0x4b, 0x73, 0x58, 0x0a, + 0x59, 0x34, 0x6e, 0x70, 0x39, 0x55, 0x52, 0x73, 0x31, 0x58, 0x64, 0x79, + 0x4f, 0x64, 0x5a, 0x4c, 0x38, 0x53, 0x71, 0x42, 0x0a, 0x6a, 0x38, 0x71, + 0x79, 0x36, 0x6d, 0x35, 0x42, 0x66, 0x54, 0x4f, 0x77, 0x66, 0x64, 0x34, + 0x31, 0x44, 0x42, 0x72, 0x70, 0x0a, 0x72, 0x42, 0x30, 0x30, 0x73, 0x64, + 0x48, 0x34, 0x71, 0x30, 0x48, 0x51, 0x4e, 0x37, 0x34, 0x68, 0x72, 0x54, + 0x74, 0x75, 0x0a, 0x6f, 0x6f, 0x46, 0x63, 0x33, 0x5a, 0x46, 0x66, 0x56, + 0x53, 0x42, 0x64, 0x52, 0x59, 0x69, 0x31, 0x4c, 0x54, 0x4c, 0x54, 0x0a, + 0x63, 0x68, 0x74, 0x50, 0x48, 0x42, 0x5a, 0x58, 0x68, 0x30, 0x58, 0x4b, + 0x68, 0x49, 0x73, 0x4b, 0x4c, 0x36, 0x54, 0x32, 0x0a, 0x4d, 0x53, 0x50, + 0x51, 0x78, 0x56, 0x54, 0x4a, 0x50, 0x61, 0x66, 0x66, 0x6a, 0x79, 0x39, + 0x36, 0x53, 0x37, 0x51, 0x37, 0x0a, 0x77, 0x72, 0x51, 0x71, 0x43, 0x35, + 0x38, 0x38, 0x66, 0x33, 0x4e, 0x37, 0x5a, 0x6c, 0x79, 0x6e, 0x32, 0x64, + 0x43, 0x6b, 0x0a, 0x4a, 0x4c, 0x33, 0x4a, 0x76, 0x59, 0x56, 0x68, 0x37, + 0x72, 0x59, 0x5a, 0x76, 0x55, 0x41, 0x48, 0x30, 0x44, 0x53, 0x44, 0x0a, + 0x31, 0x74, 0x6c, 0x4f, 0x72, 0x4e, 0x39, 0x68, 0x77, 0x42, 0x4f, 0x6a, + 0x4e, 0x47, 0x56, 0x43, 0x58, 0x6b, 0x35, 0x6a, 0x0a, 0x51, 0x4f, 0x31, + 0x6d, 0x45, 0x48, 0x4e, 0x4b, 0x70, 0x52, 0x38, 0x4c, 0x6c, 0x71, 0x4d, + 0x6f, 0x6d, 0x4d, 0x5a, 0x77, 0x0a, 0x6c, 0x57, 0x50, 0x65, 0x45, 0x6a, + 0x37, 0x7a, 0x4d, 0x6e, 0x45, 0x76, 0x43, 0x39, 0x4f, 0x47, 0x74, 0x65, + 0x61, 0x34, 0x0a, 0x76, 0x71, 0x4d, 0x68, 0x33, 0x64, 0x68, 0x35, 0x59, + 0x46, 0x4c, 0x66, 0x7a, 0x47, 0x74, 0x39, 0x7a, 0x78, 0x39, 0x61, 0x0a, + 0x33, 0x44, 0x76, 0x74, 0x37, 0x44, 0x62, 0x6d, 0x36, 0x76, 0x55, 0x48, + 0x34, 0x32, 0x54, 0x68, 0x6a, 0x5a, 0x36, 0x69, 0x0a, 0x57, 0x65, 0x68, + 0x37, 0x70, 0x51, 0x66, 0x57, 0x70, 0x61, 0x67, 0x54, 0x6f, 0x6a, 0x71, + 0x6b, 0x44, 0x47, 0x6e, 0x50, 0x0a, 0x66, 0x68, 0x33, 0x44, 0x56, 0x35, + 0x70, 0x67, 0x34, 0x79, 0x48, 0x32, 0x30, 0x30, 0x58, 0x64, 0x49, 0x74, + 0x51, 0x4d, 0x0a, 0x4e, 0x54, 0x77, 0x63, 0x32, 0x70, 0x33, 0x49, 0x44, + 0x31, 0x55, 0x57, 0x52, 0x36, 0x4c, 0x54, 0x46, 0x4a, 0x55, 0x70, 0x0a, + 0x78, 0x6e, 0x53, 0x4f, 0x4c, 0x6f, 0x49, 0x46, 0x4c, 0x66, 0x50, 0x4c, + 0x36, 0x54, 0x30, 0x49, 0x4b, 0x69, 0x5a, 0x4c, 0x0a, 0x74, 0x58, 0x63, + 0x4a, 0x7a, 0x33, 0x52, 0x75, 0x63, 0x65, 0x56, 0x55, 0x76, 0x58, 0x53, + 0x62, 0x6e, 0x76, 0x39, 0x59, 0x0a, 0x30, 0x53, 0x4c, 0x35, 0x76, 0x61, + 0x32, 0x31, 0x73, 0x6c, 0x43, 0x37, 0x6d, 0x71, 0x63, 0x42, 0x64, 0x64, + 0x76, 0x70, 0x0a, 0x54, 0x6e, 0x39, 0x6f, 0x6d, 0x66, 0x59, 0x43, 0x5a, + 0x4b, 0x74, 0x54, 0x53, 0x6e, 0x68, 0x50, 0x4f, 0x6c, 0x34, 0x4c, 0x0a, + 0x30, 0x47, 0x6f, 0x46, 0x32, 0x31, 0x4f, 0x6f, 0x50, 0x5a, 0x4b, 0x36, + 0x65, 0x71, 0x62, 0x76, 0x63, 0x75, 0x5a, 0x71, 0x0a, 0x44, 0x59, 0x41, + 0x37, 0x36, 0x45, 0x70, 0x66, 0x68, 0x73, 0x48, 0x41, 0x6e, 0x62, 0x59, + 0x42, 0x61, 0x4f, 0x55, 0x73, 0x0a, 0x77, 0x6f, 0x31, 0x34, 0x58, 0x64, + 0x4b, 0x55, 0x6c, 0x4b, 0x75, 0x65, 0x4d, 0x68, 0x6f, 0x35, 0x65, 0x33, + 0x48, 0x6b, 0x0a, 0x52, 0x62, 0x71, 0x4e, 0x45, 0x5a, 0x4b, 0x46, 0x61, + 0x71, 0x77, 0x36, 0x6b, 0x6f, 0x78, 0x74, 0x49, 0x72, 0x59, 0x78, 0x0a, + 0x6c, 0x30, 0x79, 0x69, 0x75, 0x36, 0x75, 0x73, 0x56, 0x4a, 0x48, 0x71, + 0x32, 0x73, 0x6f, 0x41, 0x38, 0x56, 0x54, 0x44, 0x0a, 0x56, 0x56, 0x74, + 0x45, 0x79, 0x77, 0x42, 0x6e, 0x62, 0x30, 0x43, 0x45, 0x4d, 0x75, 0x6c, + 0x78, 0x53, 0x69, 0x4f, 0x7a, 0x0a, 0x75, 0x59, 0x5a, 0x77, 0x43, 0x61, + 0x50, 0x66, 0x46, 0x63, 0x63, 0x34, 0x4c, 0x65, 0x41, 0x78, 0x38, 0x4a, + 0x30, 0x45, 0x0a, 0x48, 0x6d, 0x4c, 0x49, 0x74, 0x56, 0x50, 0x69, 0x73, + 0x6a, 0x37, 0x38, 0x6c, 0x54, 0x79, 0x56, 0x6a, 0x47, 0x36, 0x76, 0x0a, + 0x6c, 0x65, 0x42, 0x58, 0x6a, 0x74, 0x44, 0x77, 0x78, 0x56, 0x44, 0x76, + 0x6b, 0x61, 0x76, 0x6c, 0x6a, 0x30, 0x46, 0x35, 0x0a, 0x34, 0x61, 0x64, + 0x44, 0x74, 0x70, 0x58, 0x45, 0x33, 0x74, 0x6a, 0x45, 0x79, 0x57, 0x4c, + 0x6d, 0x43, 0x36, 0x4e, 0x5a, 0x0a, 0x63, 0x35, 0x43, 0x74, 0x38, 0x36, + 0x4b, 0x64, 0x4c, 0x41, 0x78, 0x57, 0x56, 0x55, 0x30, 0x32, 0x4f, 0x4b, + 0x33, 0x6a, 0x0a, 0x7a, 0x48, 0x49, 0x48, 0x4e, 0x50, 0x4e, 0x71, 0x63, + 0x44, 0x77, 0x69, 0x61, 0x6d, 0x47, 0x71, 0x36, 0x5a, 0x58, 0x4e, 0x0a, + 0x33, 0x65, 0x71, 0x77, 0x69, 0x71, 0x62, 0x50, 0x67, 0x6e, 0x41, 0x74, + 0x75, 0x76, 0x72, 0x55, 0x4d, 0x4e, 0x61, 0x4f, 0x0a, 0x41, 0x4d, 0x56, + 0x66, 0x63, 0x70, 0x6f, 0x30, 0x46, 0x4c, 0x6b, 0x71, 0x4f, 0x71, 0x53, + 0x37, 0x51, 0x79, 0x45, 0x75, 0x0a, 0x34, 0x6e, 0x35, 0x45, 0x78, 0x56, + 0x32, 0x49, 0x34, 0x76, 0x77, 0x39, 0x54, 0x49, 0x50, 0x4d, 0x45, 0x33, + 0x71, 0x33, 0x0a, 0x36, 0x53, 0x42, 0x64, 0x37, 0x32, 0x4b, 0x41, 0x36, + 0x6f, 0x6a, 0x77, 0x79, 0x63, 0x76, 0x63, 0x50, 0x46, 0x57, 0x4f, 0x0a, + 0x55, 0x64, 0x72, 0x59, 0x39, 0x56, 0x47, 0x68, 0x34, 0x70, 0x70, 0x65, + 0x31, 0x65, 0x78, 0x62, 0x30, 0x71, 0x73, 0x74, 0x0a, 0x79, 0x54, 0x59, + 0x68, 0x50, 0x73, 0x74, 0x54, 0x4c, 0x62, 0x38, 0x4f, 0x64, 0x61, 0x4b, + 0x71, 0x75, 0x66, 0x68, 0x75, 0x0a, 0x61, 0x63, 0x62, 0x36, 0x59, 0x52, + 0x64, 0x72, 0x4b, 0x70, 0x59, 0x58, 0x70, 0x58, 0x64, 0x71, 0x78, 0x31, + 0x53, 0x7a, 0x0a, 0x48, 0x36, 0x42, 0x6d, 0x4b, 0x41, 0x32, 0x45, 0x52, + 0x4e, 0x50, 0x68, 0x4f, 0x6e, 0x41, 0x64, 0x55, 0x44, 0x63, 0x53, 0x0a, + 0x7a, 0x43, 0x79, 0x47, 0x44, 0x77, 0x77, 0x62, 0x67, 0x72, 0x58, 0x51, + 0x57, 0x66, 0x51, 0x36, 0x46, 0x74, 0x36, 0x42, 0x0a, 0x57, 0x4a, 0x52, + 0x63, 0x4d, 0x4f, 0x79, 0x65, 0x4c, 0x39, 0x4b, 0x69, 0x7a, 0x56, 0x44, + 0x4d, 0x7a, 0x46, 0x71, 0x52, 0x0a, 0x69, 0x76, 0x6c, 0x4c, 0x74, 0x47, + 0x46, 0x44, 0x35, 0x75, 0x30, 0x75, 0x63, 0x46, 0x6c, 0x42, 0x6b, 0x63, + 0x39, 0x61, 0x0a, 0x63, 0x38, 0x7a, 0x4c, 0x6c, 0x79, 0x59, 0x4e, 0x52, + 0x34, 0x6d, 0x63, 0x43, 0x4a, 0x6e, 0x6d, 0x47, 0x4b, 0x72, 0x69, 0x0a, + 0x44, 0x76, 0x62, 0x59, 0x68, 0x50, 0x36, 0x48, 0x67, 0x6d, 0x4b, 0x37, + 0x57, 0x59, 0x53, 0x50, 0x72, 0x58, 0x62, 0x74, 0x0a, 0x43, 0x6b, 0x59, + 0x59, 0x6b, 0x55, 0x68, 0x63, 0x6e, 0x4c, 0x79, 0x55, 0x67, 0x6f, 0x55, + 0x38, 0x47, 0x6e, 0x47, 0x34, 0x0a, 0x53, 0x42, 0x48, 0x6e, 0x4e, 0x33, + 0x70, 0x52, 0x6d, 0x43, 0x68, 0x56, 0x34, 0x33, 0x65, 0x4c, 0x4f, 0x31, + 0x38, 0x35, 0x0a, 0x57, 0x4b, 0x64, 0x4b, 0x78, 0x4e, 0x33, 0x4d, 0x50, + 0x4b, 0x37, 0x6b, 0x4d, 0x32, 0x32, 0x50, 0x50, 0x41, 0x44, 0x78, 0x0a, + 0x6d, 0x72, 0x64, 0x74, 0x72, 0x54, 0x35, 0x71, 0x49, 0x6f, 0x30, 0x4f, + 0x38, 0x37, 0x37, 0x54, 0x4f, 0x4d, 0x43, 0x41, 0x0a, 0x4e, 0x56, 0x62, + 0x6f, 0x4a, 0x30, 0x48, 0x67, 0x6a, 0x48, 0x73, 0x59, 0x38, 0x79, 0x51, + 0x58, 0x38, 0x64, 0x4a, 0x48, 0x0a, 0x59, 0x4b, 0x30, 0x5a, 0x33, 0x79, + 0x42, 0x35, 0x77, 0x70, 0x6e, 0x52, 0x61, 0x78, 0x32, 0x32, 0x4f, 0x49, + 0x30, 0x65, 0x0a, 0x6f, 0x54, 0x67, 0x34, 0x31, 0x41, 0x6a, 0x61, 0x79, + 0x7a, 0x6a, 0x4c, 0x43, 0x4b, 0x61, 0x74, 0x6c, 0x6d, 0x68, 0x5a, 0x0a, + 0x53, 0x59, 0x57, 0x64, 0x33, 0x53, 0x58, 0x48, 0x36, 0x4c, 0x63, 0x6d, + 0x6e, 0x72, 0x41, 0x34, 0x71, 0x4d, 0x4f, 0x38, 0x0a, 0x35, 0x68, 0x4c, + 0x62, 0x6f, 0x47, 0x6f, 0x37, 0x6c, 0x68, 0x59, 0x7a, 0x4c, 0x49, 0x34, + 0x52, 0x79, 0x78, 0x38, 0x49, 0x0a, 0x6f, 0x4d, 0x33, 0x68, 0x51, 0x48, + 0x64, 0x31, 0x5a, 0x53, 0x48, 0x51, 0x75, 0x31, 0x6e, 0x45, 0x75, 0x34, + 0x58, 0x51, 0x0a, 0x6a, 0x30, 0x4a, 0x47, 0x31, 0x64, 0x30, 0x53, 0x70, + 0x54, 0x36, 0x76, 0x59, 0x4d, 0x69, 0x58, 0x5a, 0x59, 0x66, 0x4e, 0x0a, + 0x34, 0x4f, 0x4f, 0x75, 0x38, 0x55, 0x6b, 0x64, 0x57, 0x51, 0x56, 0x4c, + 0x64, 0x6e, 0x4c, 0x46, 0x5a, 0x59, 0x51, 0x67, 0x0a, 0x41, 0x66, 0x51, + 0x35, 0x75, 0x43, 0x66, 0x4a, 0x6b, 0x62, 0x74, 0x4b, 0x4b, 0x45, 0x64, + 0x49, 0x37, 0x72, 0x49, 0x51, 0x0a, 0x32, 0x41, 0x41, 0x75, 0x58, 0x56, + 0x63, 0x52, 0x54, 0x63, 0x4f, 0x6f, 0x49, 0x45, 0x74, 0x48, 0x75, 0x77, + 0x59, 0x33, 0x0a, 0x32, 0x7a, 0x6d, 0x36, 0x62, 0x41, 0x35, 0x4e, 0x30, + 0x70, 0x47, 0x31, 0x6c, 0x38, 0x67, 0x61, 0x50, 0x6d, 0x77, 0x79, 0x0a, + 0x6b, 0x55, 0x4c, 0x35, 0x6e, 0x4f, 0x6e, 0x43, 0x71, 0x72, 0x76, 0x53, + 0x56, 0x75, 0x38, 0x67, 0x6c, 0x43, 0x38, 0x71, 0x0a, 0x38, 0x6f, 0x65, + 0x56, 0x72, 0x56, 0x69, 0x42, 0x58, 0x57, 0x5a, 0x72, 0x62, 0x57, 0x4f, + 0x47, 0x32, 0x50, 0x54, 0x31, 0x0a, 0x5a, 0x45, 0x56, 0x66, 0x62, 0x67, + 0x39, 0x58, 0x54, 0x79, 0x64, 0x4f, 0x76, 0x34, 0x6d, 0x52, 0x6a, 0x47, + 0x61, 0x68, 0x0a, 0x79, 0x45, 0x47, 0x70, 0x68, 0x74, 0x4f, 0x68, 0x64, + 0x67, 0x68, 0x52, 0x5a, 0x63, 0x47, 0x38, 0x4a, 0x30, 0x59, 0x41, 0x0a, + 0x46, 0x36, 0x4b, 0x58, 0x69, 0x48, 0x35, 0x52, 0x68, 0x30, 0x4c, 0x46, + 0x78, 0x48, 0x49, 0x6e, 0x65, 0x50, 0x73, 0x48, 0x0a, 0x31, 0x4c, 0x5a, + 0x54, 0x68, 0x79, 0x33, 0x37, 0x71, 0x72, 0x77, 0x74, 0x6f, 0x71, 0x59, + 0x4e, 0x41, 0x51, 0x48, 0x75, 0x0a, 0x57, 0x4d, 0x42, 0x75, 0x6f, 0x35, + 0x46, 0x46, 0x6c, 0x68, 0x63, 0x4c, 0x59, 0x75, 0x32, 0x72, 0x4c, 0x68, + 0x4f, 0x30, 0x0a, 0x71, 0x52, 0x4c, 0x30, 0x58, 0x79, 0x54, 0x74, 0x38, + 0x37, 0x37, 0x35, 0x55, 0x34, 0x37, 0x79, 0x78, 0x45, 0x33, 0x62, 0x0a, + 0x6e, 0x68, 0x56, 0x51, 0x51, 0x4d, 0x6c, 0x31, 0x44, 0x75, 0x70, 0x36, + 0x42, 0x45, 0x55, 0x69, 0x44, 0x79, 0x70, 0x59, 0x0a, 0x45, 0x54, 0x75, + 0x30, 0x41, 0x36, 0x69, 0x47, 0x63, 0x42, 0x61, 0x36, 0x59, 0x67, 0x32, + 0x43, 0x4f, 0x4e, 0x55, 0x39, 0x0a, 0x4d, 0x51, 0x45, 0x68, 0x72, 0x4d, + 0x34, 0x62, 0x61, 0x33, 0x58, 0x64, 0x34, 0x72, 0x30, 0x54, 0x52, 0x6a, + 0x4a, 0x35, 0x0a, 0x44, 0x6e, 0x41, 0x34, 0x66, 0x7a, 0x70, 0x32, 0x63, + 0x59, 0x56, 0x51, 0x5a, 0x44, 0x47, 0x51, 0x43, 0x53, 0x42, 0x36, 0x0a, + 0x51, 0x46, 0x67, 0x34, 0x45, 0x61, 0x74, 0x47, 0x44, 0x63, 0x5a, 0x43, + 0x61, 0x46, 0x36, 0x49, 0x41, 0x77, 0x6a, 0x48, 0x0a, 0x6a, 0x7a, 0x58, + 0x50, 0x42, 0x38, 0x6e, 0x74, 0x7a, 0x57, 0x4e, 0x33, 0x65, 0x6b, 0x53, + 0x70, 0x6b, 0x58, 0x4a, 0x4b, 0x0a, 0x56, 0x54, 0x49, 0x57, 0x38, 0x39, + 0x4c, 0x37, 0x32, 0x67, 0x5a, 0x65, 0x73, 0x58, 0x41, 0x4c, 0x52, 0x44, + 0x36, 0x6c, 0x0a, 0x49, 0x55, 0x44, 0x7a, 0x42, 0x4e, 0x4e, 0x43, 0x4a, + 0x67, 0x35, 0x47, 0x68, 0x4b, 0x48, 0x34, 0x76, 0x47, 0x6b, 0x6b, 0x0a, + 0x57, 0x67, 0x44, 0x66, 0x33, 0x57, 0x67, 0x66, 0x65, 0x50, 0x32, 0x47, + 0x52, 0x4c, 0x43, 0x61, 0x4a, 0x45, 0x6a, 0x38, 0x0a, 0x71, 0x4d, 0x51, + 0x71, 0x64, 0x59, 0x33, 0x5a, 0x4b, 0x49, 0x76, 0x62, 0x4b, 0x52, 0x56, + 0x69, 0x49, 0x61, 0x38, 0x6d, 0x0a, 0x6a, 0x37, 0x41, 0x41, 0x4d, 0x4d, + 0x76, 0x37, 0x36, 0x79, 0x6e, 0x34, 0x30, 0x57, 0x65, 0x4e, 0x35, 0x30, + 0x32, 0x33, 0x0a, 0x6f, 0x65, 0x57, 0x58, 0x55, 0x57, 0x69, 0x68, 0x4c, + 0x38, 0x73, 0x55, 0x49, 0x4f, 0x78, 0x77, 0x61, 0x4e, 0x41, 0x56, 0x0a, + 0x47, 0x48, 0x47, 0x47, 0x71, 0x45, 0x54, 0x52, 0x41, 0x35, 0x51, 0x34, + 0x63, 0x51, 0x30, 0x62, 0x6d, 0x64, 0x79, 0x76, 0x0a, 0x75, 0x67, 0x33, + 0x31, 0x47, 0x71, 0x74, 0x69, 0x49, 0x59, 0x4a, 0x50, 0x75, 0x69, 0x34, + 0x32, 0x42, 0x6e, 0x7a, 0x67, 0x0a, 0x7a, 0x51, 0x79, 0x6c, 0x4e, 0x77, + 0x46, 0x63, 0x51, 0x5a, 0x46, 0x33, 0x37, 0x35, 0x35, 0x4a, 0x30, 0x47, + 0x6a, 0x67, 0x0a, 0x46, 0x43, 0x30, 0x54, 0x35, 0x4b, 0x30, 0x30, 0x33, + 0x75, 0x58, 0x73, 0x30, 0x7a, 0x6f, 0x4b, 0x56, 0x65, 0x59, 0x65, 0x0a, + 0x37, 0x79, 0x53, 0x74, 0x55, 0x76, 0x61, 0x38, 0x55, 0x6c, 0x4e, 0x43, + 0x65, 0x74, 0x66, 0x63, 0x75, 0x4a, 0x64, 0x71, 0x0a, 0x66, 0x52, 0x71, + 0x35, 0x46, 0x71, 0x41, 0x77, 0x32, 0x63, 0x5a, 0x30, 0x49, 0x53, 0x53, + 0x51, 0x67, 0x74, 0x33, 0x59, 0x0a, 0x51, 0x45, 0x37, 0x73, 0x30, 0x41, + 0x55, 0x5a, 0x38, 0x67, 0x56, 0x7a, 0x37, 0x33, 0x59, 0x31, 0x7a, 0x33, + 0x4f, 0x65, 0x0a, 0x57, 0x72, 0x62, 0x53, 0x34, 0x32, 0x6d, 0x51, 0x79, + 0x56, 0x4f, 0x64, 0x4e, 0x43, 0x72, 0x79, 0x75, 0x59, 0x5a, 0x76, 0x0a, + 0x46, 0x7a, 0x6f, 0x46, 0x66, 0x51, 0x41, 0x43, 0x57, 0x6d, 0x65, 0x51, + 0x34, 0x37, 0x32, 0x6b, 0x4f, 0x55, 0x32, 0x6b, 0x0a, 0x62, 0x62, 0x55, + 0x63, 0x65, 0x6c, 0x56, 0x56, 0x6d, 0x70, 0x57, 0x4e, 0x73, 0x62, 0x48, + 0x4d, 0x65, 0x64, 0x65, 0x41, 0x0a, 0x57, 0x58, 0x6e, 0x54, 0x71, 0x55, + 0x6b, 0x4a, 0x6c, 0x78, 0x58, 0x58, 0x6e, 0x36, 0x48, 0x33, 0x31, 0x34, + 0x4f, 0x35, 0x0a, 0x79, 0x7a, 0x70, 0x39, 0x41, 0x47, 0x54, 0x69, 0x6f, + 0x61, 0x31, 0x39, 0x56, 0x76, 0x65, 0x68, 0x46, 0x53, 0x6a, 0x68, 0x0a, + 0x4e, 0x6e, 0x73, 0x65, 0x7a, 0x35, 0x6c, 0x6a, 0x58, 0x77, 0x49, 0x56, + 0x7a, 0x61, 0x35, 0x69, 0x4b, 0x44, 0x64, 0x45, 0x0a, 0x6d, 0x4f, 0x48, + 0x33, 0x62, 0x5a, 0x39, 0x70, 0x74, 0x48, 0x4f, 0x4c, 0x65, 0x6e, 0x6a, + 0x78, 0x5a, 0x72, 0x77, 0x46, 0x0a, 0x45, 0x63, 0x57, 0x45, 0x71, 0x6c, + 0x4b, 0x67, 0x54, 0x63, 0x69, 0x50, 0x53, 0x77, 0x6f, 0x59, 0x56, 0x64, + 0x70, 0x4a, 0x0a, 0x37, 0x65, 0x48, 0x58, 0x72, 0x47, 0x75, 0x50, 0x38, + 0x6f, 0x33, 0x59, 0x33, 0x7a, 0x36, 0x31, 0x54, 0x73, 0x63, 0x45, 0x0a, + 0x54, 0x64, 0x72, 0x33, 0x73, 0x43, 0x36, 0x4b, 0x45, 0x6a, 0x76, 0x6a, + 0x68, 0x6a, 0x6b, 0x73, 0x67, 0x4e, 0x6e, 0x47, 0x0a, 0x57, 0x36, 0x5a, + 0x76, 0x51, 0x51, 0x46, 0x56, 0x69, 0x6a, 0x49, 0x4b, 0x59, 0x66, 0x71, + 0x57, 0x4b, 0x61, 0x67, 0x34, 0x0a, 0x58, 0x38, 0x71, 0x50, 0x62, 0x70, + 0x61, 0x44, 0x52, 0x52, 0x53, 0x64, 0x37, 0x59, 0x58, 0x32, 0x6e, 0x50, + 0x59, 0x55, 0x0a, 0x6f, 0x39, 0x6b, 0x34, 0x39, 0x57, 0x66, 0x48, 0x78, + 0x54, 0x59, 0x4b, 0x75, 0x45, 0x4f, 0x61, 0x61, 0x37, 0x6a, 0x41, 0x0a, + 0x63, 0x52, 0x47, 0x4a, 0x4d, 0x41, 0x62, 0x66, 0x35, 0x50, 0x67, 0x65, + 0x42, 0x62, 0x73, 0x6f, 0x4b, 0x56, 0x67, 0x35, 0x0a, 0x43, 0x69, 0x61, + 0x6b, 0x36, 0x71, 0x6a, 0x50, 0x4e, 0x4f, 0x42, 0x68, 0x72, 0x65, 0x73, + 0x65, 0x55, 0x70, 0x57, 0x79, 0x0a, 0x6c, 0x73, 0x37, 0x57, 0x68, 0x71, + 0x6c, 0x50, 0x41, 0x67, 0x43, 0x31, 0x49, 0x73, 0x4a, 0x72, 0x57, 0x36, + 0x32, 0x4e, 0x0a, 0x47, 0x63, 0x5a, 0x34, 0x75, 0x41, 0x78, 0x56, 0x66, + 0x39, 0x54, 0x30, 0x6a, 0x71, 0x34, 0x6f, 0x68, 0x7a, 0x61, 0x4c, 0x0a, + 0x61, 0x74, 0x6b, 0x46, 0x48, 0x6c, 0x66, 0x44, 0x61, 0x47, 0x43, 0x59, + 0x47, 0x37, 0x64, 0x59, 0x61, 0x30, 0x6b, 0x4d, 0x0a, 0x34, 0x59, 0x71, + 0x57, 0x65, 0x38, 0x37, 0x68, 0x35, 0x79, 0x70, 0x51, 0x67, 0x61, 0x46, + 0x54, 0x75, 0x4d, 0x33, 0x73, 0x0a, 0x74, 0x52, 0x71, 0x45, 0x33, 0x63, + 0x76, 0x63, 0x4b, 0x41, 0x66, 0x34, 0x4b, 0x73, 0x47, 0x7a, 0x61, 0x4d, + 0x74, 0x79, 0x0a, 0x59, 0x53, 0x36, 0x6b, 0x5a, 0x42, 0x50, 0x6f, 0x32, + 0x4c, 0x47, 0x61, 0x75, 0x53, 0x78, 0x39, 0x53, 0x43, 0x58, 0x54, 0x0a, + 0x64, 0x42, 0x4c, 0x38, 0x48, 0x7a, 0x76, 0x51, 0x45, 0x75, 0x53, 0x31, + 0x53, 0x45, 0x37, 0x4b, 0x47, 0x45, 0x79, 0x65, 0x0a, 0x76, 0x56, 0x58, + 0x34, 0x45, 0x76, 0x77, 0x30, 0x35, 0x4c, 0x48, 0x5a, 0x52, 0x49, 0x6a, + 0x68, 0x53, 0x4e, 0x37, 0x63, 0x0a, 0x30, 0x58, 0x46, 0x66, 0x4e, 0x4f, + 0x64, 0x43, 0x39, 0x32, 0x6d, 0x50, 0x66, 0x78, 0x31, 0x43, 0x58, 0x66, + 0x5a, 0x45, 0x0a, 0x45, 0x71, 0x49, 0x4e, 0x7a, 0x78, 0x65, 0x4f, 0x5a, + 0x57, 0x78, 0x7a, 0x42, 0x6c, 0x37, 0x75, 0x70, 0x6f, 0x66, 0x57, 0x0a, + 0x51, 0x71, 0x66, 0x55, 0x53, 0x46, 0x33, 0x48, 0x69, 0x73, 0x30, 0x79, + 0x4d, 0x51, 0x39, 0x74, 0x54, 0x4a, 0x78, 0x79, 0x0a, 0x4e, 0x4d, 0x49, + 0x31, 0x6d, 0x59, 0x69, 0x71, 0x37, 0x71, 0x52, 0x4f, 0x37, 0x39, 0x43, + 0x6a, 0x6f, 0x42, 0x64, 0x77, 0x0a, 0x7a, 0x6a, 0x73, 0x44, 0x6c, 0x4b, + 0x52, 0x42, 0x72, 0x78, 0x6d, 0x37, 0x33, 0x78, 0x35, 0x69, 0x45, 0x74, + 0x57, 0x38, 0x0a, 0x61, 0x54, 0x6c, 0x77, 0x55, 0x34, 0x4d, 0x76, 0x56, + 0x68, 0x46, 0x54, 0x59, 0x46, 0x73, 0x31, 0x75, 0x74, 0x35, 0x4d, 0x0a, + 0x7a, 0x5a, 0x63, 0x72, 0x7a, 0x54, 0x43, 0x58, 0x52, 0x45, 0x39, 0x45, + 0x74, 0x72, 0x54, 0x67, 0x78, 0x38, 0x6b, 0x52, 0x0a, 0x4c, 0x74, 0x37, + 0x41, 0x37, 0x79, 0x65, 0x71, 0x30, 0x56, 0x75, 0x58, 0x64, 0x33, 0x64, + 0x75, 0x6f, 0x68, 0x54, 0x76, 0x0a, 0x64, 0x68, 0x44, 0x44, 0x4a, 0x45, + 0x6d, 0x70, 0x71, 0x49, 0x4e, 0x39, 0x42, 0x56, 0x4f, 0x32, 0x56, 0x50, + 0x58, 0x4e, 0x0a, 0x65, 0x55, 0x54, 0x4f, 0x64, 0x4a, 0x72, 0x55, 0x76, + 0x66, 0x31, 0x4f, 0x6a, 0x79, 0x7a, 0x43, 0x63, 0x51, 0x44, 0x51, 0x0a, + 0x72, 0x4c, 0x34, 0x36, 0x64, 0x62, 0x63, 0x45, 0x58, 0x55, 0x65, 0x30, + 0x55, 0x75, 0x33, 0x75, 0x4a, 0x76, 0x6b, 0x41, 0x0a, 0x4d, 0x53, 0x76, + 0x4e, 0x41, 0x6f, 0x79, 0x66, 0x57, 0x6c, 0x35, 0x66, 0x62, 0x6b, 0x50, + 0x30, 0x32, 0x71, 0x55, 0x69, 0x0a, 0x55, 0x30, 0x49, 0x4a, 0x61, 0x61, + 0x41, 0x34, 0x52, 0x43, 0x71, 0x75, 0x6f, 0x50, 0x6f, 0x56, 0x66, 0x35, + 0x4b, 0x41, 0x0a, 0x74, 0x30, 0x56, 0x64, 0x31, 0x6f, 0x72, 0x32, 0x42, + 0x77, 0x71, 0x4b, 0x4e, 0x66, 0x6f, 0x4f, 0x61, 0x79, 0x73, 0x4a, 0x0a, + 0x63, 0x4d, 0x6d, 0x46, 0x59, 0x66, 0x77, 0x35, 0x72, 0x41, 0x73, 0x43, + 0x73, 0x4f, 0x75, 0x69, 0x73, 0x51, 0x33, 0x6c, 0x0a, 0x4c, 0x52, 0x73, + 0x78, 0x5a, 0x79, 0x77, 0x30, 0x78, 0x70, 0x46, 0x44, 0x67, 0x41, 0x79, + 0x38, 0x71, 0x46, 0x4c, 0x5a, 0x0a, 0x76, 0x52, 0x62, 0x31, 0x52, 0x31, + 0x64, 0x62, 0x70, 0x68, 0x59, 0x46, 0x53, 0x73, 0x32, 0x41, 0x74, 0x49, + 0x42, 0x57, 0x0a, 0x4d, 0x51, 0x75, 0x64, 0x74, 0x55, 0x54, 0x7a, 0x52, + 0x35, 0x58, 0x4c, 0x48, 0x62, 0x53, 0x64, 0x76, 0x58, 0x57, 0x73, 0x0a, + 0x6b, 0x64, 0x63, 0x76, 0x39, 0x50, 0x6a, 0x44, 0x6e, 0x67, 0x71, 0x4b, + 0x59, 0x6b, 0x39, 0x50, 0x4e, 0x70, 0x6b, 0x59, 0x0a, 0x73, 0x69, 0x49, + 0x4f, 0x75, 0x47, 0x59, 0x66, 0x7a, 0x67, 0x34, 0x44, 0x6e, 0x63, 0x6d, + 0x5a, 0x64, 0x47, 0x35, 0x5a, 0x0a, 0x68, 0x76, 0x4d, 0x46, 0x61, 0x34, + 0x4d, 0x6e, 0x65, 0x71, 0x6d, 0x54, 0x62, 0x4f, 0x6a, 0x57, 0x79, 0x6e, + 0x54, 0x44, 0x0a, 0x33, 0x4c, 0x64, 0x72, 0x39, 0x43, 0x70, 0x34, 0x4a, + 0x69, 0x35, 0x36, 0x56, 0x63, 0x77, 0x55, 0x49, 0x37, 0x61, 0x6b, 0x0a, + 0x4a, 0x6c, 0x73, 0x72, 0x4f, 0x4c, 0x51, 0x36, 0x30, 0x42, 0x4c, 0x6b, + 0x51, 0x4d, 0x43, 0x32, 0x34, 0x50, 0x51, 0x65, 0x0a, 0x78, 0x56, 0x75, + 0x6b, 0x4b, 0x47, 0x4b, 0x46, 0x36, 0x75, 0x6e, 0x64, 0x30, 0x47, 0x4e, + 0x32, 0x76, 0x69, 0x34, 0x32, 0x0a, 0x72, 0x53, 0x57, 0x39, 0x51, 0x4f, + 0x41, 0x53, 0x74, 0x44, 0x33, 0x33, 0x45, 0x51, 0x36, 0x47, 0x5a, 0x41, + 0x4f, 0x52, 0x0a, 0x66, 0x6b, 0x30, 0x32, 0x51, 0x74, 0x73, 0x6b, 0x55, + 0x79, 0x34, 0x36, 0x45, 0x75, 0x4b, 0x71, 0x54, 0x62, 0x68, 0x47, 0x0a, + 0x61, 0x6c, 0x55, 0x6d, 0x7a, 0x36, 0x38, 0x48, 0x79, 0x78, 0x56, 0x76, + 0x46, 0x68, 0x57, 0x44, 0x74, 0x69, 0x36, 0x59, 0x0a, 0x79, 0x70, 0x67, + 0x59, 0x54, 0x6c, 0x4a, 0x66, 0x32, 0x38, 0x71, 0x6b, 0x43, 0x55, 0x46, + 0x72, 0x41, 0x64, 0x35, 0x48, 0x0a, 0x66, 0x53, 0x30, 0x52, 0x57, 0x4f, + 0x48, 0x36, 0x75, 0x4c, 0x47, 0x6a, 0x61, 0x4b, 0x58, 0x56, 0x4c, 0x74, + 0x75, 0x6a, 0x0a, 0x74, 0x46, 0x6f, 0x4b, 0x36, 0x35, 0x45, 0x73, 0x52, + 0x35, 0x76, 0x53, 0x6c, 0x71, 0x31, 0x57, 0x4d, 0x78, 0x54, 0x49, 0x0a, + 0x63, 0x71, 0x35, 0x4a, 0x5a, 0x55, 0x5a, 0x4b, 0x45, 0x37, 0x66, 0x64, + 0x73, 0x78, 0x70, 0x45, 0x6b, 0x54, 0x54, 0x59, 0x0a, 0x36, 0x73, 0x44, + 0x79, 0x51, 0x44, 0x68, 0x71, 0x46, 0x63, 0x6a, 0x4d, 0x32, 0x37, 0x6b, + 0x49, 0x70, 0x43, 0x6a, 0x77, 0x0a, 0x43, 0x6c, 0x33, 0x41, 0x67, 0x59, + 0x34, 0x35, 0x58, 0x4a, 0x72, 0x61, 0x73, 0x73, 0x6e, 0x31, 0x63, 0x76, + 0x6f, 0x63, 0x0a, 0x6c, 0x45, 0x66, 0x5a, 0x45, 0x74, 0x6d, 0x74, 0x6d, + 0x71, 0x4a, 0x62, 0x70, 0x36, 0x63, 0x56, 0x63, 0x32, 0x6f, 0x62, 0x0a, + 0x30, 0x7a, 0x32, 0x43, 0x76, 0x4c, 0x30, 0x67, 0x39, 0x48, 0x46, 0x72, + 0x44, 0x70, 0x6f, 0x37, 0x51, 0x6c, 0x4a, 0x54, 0x0a, 0x63, 0x35, 0x77, + 0x64, 0x4c, 0x53, 0x54, 0x7a, 0x6d, 0x68, 0x6f, 0x55, 0x7a, 0x6c, 0x7a, + 0x54, 0x67, 0x67, 0x42, 0x49, 0x0a, 0x7a, 0x66, 0x76, 0x58, 0x37, 0x31, + 0x78, 0x53, 0x58, 0x44, 0x6b, 0x75, 0x65, 0x77, 0x61, 0x38, 0x56, 0x62, + 0x34, 0x34, 0x0a, 0x75, 0x43, 0x74, 0x6d, 0x4c, 0x79, 0x30, 0x42, 0x47, + 0x61, 0x43, 0x73, 0x56, 0x73, 0x36, 0x74, 0x54, 0x79, 0x67, 0x46, 0x0a, + 0x76, 0x50, 0x6f, 0x6c, 0x4c, 0x62, 0x6a, 0x47, 0x73, 0x56, 0x33, 0x32, + 0x6d, 0x66, 0x62, 0x31, 0x79, 0x4e, 0x6c, 0x6f, 0x0a, 0x45, 0x34, 0x4e, + 0x42, 0x78, 0x56, 0x42, 0x73, 0x7a, 0x42, 0x31, 0x4a, 0x78, 0x54, 0x44, + 0x74, 0x50, 0x6b, 0x77, 0x32, 0x0a, 0x42, 0x72, 0x7a, 0x59, 0x68, 0x6f, + 0x39, 0x30, 0x46, 0x49, 0x6b, 0x49, 0x42, 0x4c, 0x67, 0x76, 0x79, 0x46, + 0x79, 0x51, 0x0a, 0x70, 0x30, 0x6b, 0x6b, 0x75, 0x42, 0x6a, 0x31, 0x6f, + 0x52, 0x35, 0x30, 0x30, 0x32, 0x39, 0x4a, 0x4e, 0x6a, 0x79, 0x53, 0x0a, + 0x50, 0x7a, 0x48, 0x35, 0x7a, 0x6e, 0x73, 0x6a, 0x58, 0x78, 0x71, 0x45, + 0x79, 0x32, 0x79, 0x52, 0x56, 0x57, 0x6a, 0x5a, 0x0a, 0x66, 0x72, 0x4e, + 0x6e, 0x63, 0x6f, 0x58, 0x30, 0x43, 0x32, 0x33, 0x6b, 0x39, 0x4d, 0x6f, + 0x55, 0x6f, 0x36, 0x53, 0x62, 0x0a, 0x44, 0x69, 0x32, 0x46, 0x54, 0x32, + 0x4c, 0x63, 0x41, 0x4a, 0x48, 0x38, 0x57, 0x41, 0x35, 0x62, 0x6b, 0x31, + 0x39, 0x55, 0x0a, 0x42, 0x47, 0x66, 0x35, 0x77, 0x78, 0x68, 0x61, 0x43, + 0x44, 0x31, 0x5a, 0x70, 0x4f, 0x39, 0x46, 0x33, 0x56, 0x39, 0x32, 0x0a, + 0x51, 0x57, 0x36, 0x49, 0x59, 0x6b, 0x35, 0x55, 0x64, 0x62, 0x65, 0x6f, + 0x4b, 0x69, 0x51, 0x42, 0x66, 0x70, 0x31, 0x4f, 0x0a, 0x42, 0x51, 0x41, + 0x75, 0x75, 0x30, 0x47, 0x32, 0x62, 0x4a, 0x75, 0x43, 0x62, 0x31, 0x33, + 0x46, 0x45, 0x55, 0x50, 0x4b, 0x0a, 0x57, 0x6c, 0x69, 0x38, 0x74, 0x7a, + 0x4b, 0x4e, 0x79, 0x43, 0x38, 0x51, 0x34, 0x4a, 0x56, 0x47, 0x68, 0x70, + 0x36, 0x4f, 0x0a, 0x67, 0x44, 0x42, 0x58, 0x63, 0x55, 0x41, 0x48, 0x46, + 0x46, 0x4c, 0x56, 0x6d, 0x59, 0x35, 0x66, 0x72, 0x4b, 0x71, 0x32, 0x0a, + 0x78, 0x6c, 0x34, 0x34, 0x30, 0x4f, 0x66, 0x56, 0x4f, 0x4e, 0x74, 0x61, + 0x6f, 0x73, 0x72, 0x7a, 0x68, 0x68, 0x56, 0x71, 0x0a, 0x64, 0x39, 0x59, + 0x78, 0x34, 0x61, 0x54, 0x61, 0x45, 0x49, 0x6a, 0x4c, 0x43, 0x61, 0x74, + 0x48, 0x35, 0x30, 0x6c, 0x54, 0x0a, 0x56, 0x4e, 0x70, 0x31, 0x30, 0x43, + 0x4e, 0x49, 0x63, 0x54, 0x5a, 0x52, 0x6c, 0x31, 0x54, 0x52, 0x4a, 0x4f, + 0x50, 0x74, 0x0a, 0x5a, 0x47, 0x49, 0x55, 0x69, 0x4b, 0x61, 0x6c, 0x58, + 0x4f, 0x72, 0x6a, 0x30, 0x7a, 0x35, 0x76, 0x30, 0x32, 0x33, 0x6e, 0x0a, + 0x57, 0x62, 0x55, 0x36, 0x42, 0x45, 0x48, 0x4f, 0x4a, 0x4d, 0x31, 0x43, + 0x32, 0x50, 0x4f, 0x71, 0x6f, 0x79, 0x4d, 0x66, 0x0a, 0x64, 0x79, 0x39, + 0x66, 0x32, 0x30, 0x34, 0x44, 0x62, 0x43, 0x79, 0x57, 0x59, 0x74, 0x46, + 0x56, 0x4c, 0x79, 0x52, 0x6f, 0x0a, 0x4b, 0x35, 0x71, 0x55, 0x44, 0x4b, + 0x4e, 0x56, 0x64, 0x68, 0x72, 0x50, 0x7a, 0x63, 0x6e, 0x48, 0x73, 0x4d, + 0x51, 0x75, 0x0a, 0x64, 0x39, 0x65, 0x33, 0x53, 0x4e, 0x77, 0x37, 0x73, + 0x37, 0x72, 0x53, 0x57, 0x33, 0x67, 0x56, 0x68, 0x37, 0x33, 0x7a, 0x0a, + 0x49, 0x56, 0x45, 0x43, 0x79, 0x32, 0x54, 0x47, 0x50, 0x52, 0x62, 0x65, + 0x58, 0x48, 0x45, 0x39, 0x66, 0x69, 0x4c, 0x73, 0x0a, 0x6a, 0x43, 0x75, + 0x4e, 0x33, 0x41, 0x61, 0x63, 0x6d, 0x64, 0x78, 0x32, 0x46, 0x79, 0x48, + 0x4d, 0x45, 0x31, 0x42, 0x69, 0x0a, 0x68, 0x32, 0x4b, 0x30, 0x76, 0x42, + 0x6a, 0x56, 0x64, 0x46, 0x72, 0x6b, 0x62, 0x6b, 0x51, 0x65, 0x45, 0x4b, + 0x6f, 0x34, 0x0a, 0x6f, 0x49, 0x72, 0x77, 0x31, 0x58, 0x4e, 0x66, 0x48, + 0x69, 0x35, 0x7a, 0x69, 0x69, 0x7a, 0x73, 0x59, 0x62, 0x67, 0x48, 0x0a, + 0x68, 0x52, 0x37, 0x66, 0x36, 0x61, 0x78, 0x69, 0x6c, 0x69, 0x41, 0x32, + 0x4b, 0x6f, 0x54, 0x78, 0x65, 0x74, 0x39, 0x68, 0x0a, 0x79, 0x59, 0x36, + 0x48, 0x6d, 0x68, 0x38, 0x64, 0x4f, 0x42, 0x39, 0x35, 0x42, 0x32, 0x6c, + 0x6a, 0x6d, 0x4d, 0x56, 0x46, 0x0a, 0x4b, 0x48, 0x63, 0x6a, 0x46, 0x4d, + 0x62, 0x4b, 0x49, 0x78, 0x5a, 0x43, 0x35, 0x7a, 0x73, 0x71, 0x54, 0x41, + 0x71, 0x34, 0x0a, 0x4b, 0x5a, 0x45, 0x5a, 0x55, 0x54, 0x6f, 0x6c, 0x71, + 0x62, 0x62, 0x6f, 0x63, 0x54, 0x57, 0x44, 0x70, 0x79, 0x77, 0x65, 0x0a, + 0x33, 0x79, 0x67, 0x64, 0x38, 0x74, 0x6e, 0x6f, 0x51, 0x30, 0x4d, 0x71, + 0x72, 0x51, 0x4e, 0x69, 0x50, 0x42, 0x77, 0x6c, 0x0a, 0x74, 0x44, 0x47, + 0x49, 0x51, 0x67, 0x4f, 0x37, 0x56, 0x4e, 0x7a, 0x52, 0x48, 0x43, 0x33, + 0x5a, 0x76, 0x75, 0x4c, 0x45, 0x0a, 0x6f, 0x50, 0x6f, 0x68, 0x41, 0x36, + 0x56, 0x72, 0x52, 0x38, 0x53, 0x4c, 0x79, 0x55, 0x55, 0x6f, 0x46, 0x6b, + 0x4b, 0x73, 0x0a, 0x51, 0x58, 0x56, 0x72, 0x77, 0x4b, 0x67, 0x34, 0x36, + 0x74, 0x48, 0x38, 0x35, 0x67, 0x66, 0x42, 0x34, 0x49, 0x79, 0x6a, 0x0a, + 0x68, 0x54, 0x56, 0x68, 0x45, 0x75, 0x49, 0x73, 0x4b, 0x31, 0x62, 0x57, + 0x6d, 0x6c, 0x79, 0x51, 0x38, 0x7a, 0x42, 0x70, 0x0a, 0x55, 0x37, 0x52, + 0x50, 0x65, 0x37, 0x54, 0x4d, 0x74, 0x6e, 0x33, 0x4e, 0x6d, 0x77, 0x6d, + 0x70, 0x6e, 0x35, 0x36, 0x62, 0x0a, 0x55, 0x50, 0x39, 0x78, 0x6a, 0x50, + 0x6c, 0x77, 0x42, 0x53, 0x44, 0x46, 0x35, 0x43, 0x68, 0x31, 0x50, 0x53, + 0x42, 0x68, 0x0a, 0x43, 0x4e, 0x4c, 0x61, 0x38, 0x57, 0x54, 0x43, 0x6e, + 0x37, 0x6a, 0x45, 0x59, 0x66, 0x45, 0x5a, 0x4b, 0x38, 0x75, 0x38, 0x0a, + 0x67, 0x50, 0x46, 0x52, 0x4f, 0x6c, 0x6f, 0x46, 0x37, 0x77, 0x49, 0x51, + 0x32, 0x75, 0x70, 0x41, 0x44, 0x74, 0x47, 0x75, 0x0a, 0x55, 0x6d, 0x64, + 0x36, 0x47, 0x45, 0x4a, 0x46, 0x79, 0x4a, 0x64, 0x79, 0x62, 0x61, 0x57, + 0x33, 0x6a, 0x55, 0x4e, 0x6b, 0x0a, 0x44, 0x36, 0x54, 0x56, 0x4e, 0x45, + 0x34, 0x74, 0x33, 0x75, 0x43, 0x6b, 0x79, 0x74, 0x76, 0x4b, 0x43, 0x7a, + 0x39, 0x32, 0x0a, 0x62, 0x39, 0x56, 0x68, 0x44, 0x4c, 0x48, 0x64, 0x74, + 0x4a, 0x76, 0x4e, 0x38, 0x34, 0x57, 0x71, 0x46, 0x4e, 0x71, 0x6f, 0x0a, + 0x34, 0x51, 0x30, 0x4c, 0x77, 0x6e, 0x4e, 0x52, 0x50, 0x50, 0x77, 0x62, + 0x36, 0x72, 0x4c, 0x6b, 0x61, 0x34, 0x4f, 0x7a, 0x0a, 0x50, 0x66, 0x53, + 0x79, 0x49, 0x79, 0x75, 0x73, 0x33, 0x42, 0x33, 0x35, 0x4f, 0x55, 0x6e, + 0x50, 0x4c, 0x74, 0x46, 0x78, 0x0a, 0x67, 0x71, 0x6d, 0x6e, 0x68, 0x50, + 0x67, 0x70, 0x49, 0x50, 0x32, 0x70, 0x46, 0x39, 0x69, 0x4a, 0x6c, 0x51, + 0x62, 0x47, 0x0a, 0x76, 0x55, 0x64, 0x45, 0x6f, 0x57, 0x75, 0x43, 0x37, + 0x56, 0x36, 0x49, 0x71, 0x33, 0x6a, 0x52, 0x30, 0x33, 0x4b, 0x51, 0x0a, + 0x63, 0x45, 0x70, 0x4d, 0x66, 0x4d, 0x52, 0x58, 0x51, 0x62, 0x73, 0x32, + 0x52, 0x46, 0x54, 0x61, 0x4e, 0x4c, 0x76, 0x59, 0x0a, 0x42, 0x48, 0x35, + 0x57, 0x42, 0x4b, 0x52, 0x61, 0x36, 0x77, 0x68, 0x35, 0x35, 0x56, 0x6c, + 0x6e, 0x4e, 0x79, 0x7a, 0x77, 0x0a, 0x70, 0x4f, 0x38, 0x71, 0x45, 0x46, + 0x69, 0x70, 0x39, 0x46, 0x53, 0x61, 0x70, 0x46, 0x53, 0x50, 0x6e, 0x46, + 0x44, 0x71, 0x0a, 0x52, 0x58, 0x64, 0x44, 0x4b, 0x37, 0x31, 0x72, 0x71, + 0x48, 0x63, 0x71, 0x39, 0x77, 0x64, 0x64, 0x37, 0x6b, 0x6d, 0x52, 0x0a, + 0x4f, 0x45, 0x32, 0x37, 0x48, 0x6a, 0x6d, 0x51, 0x73, 0x6f, 0x72, 0x57, + 0x79, 0x54, 0x65, 0x6a, 0x67, 0x39, 0x54, 0x38, 0x0a, 0x63, 0x46, 0x49, + 0x36, 0x50, 0x61, 0x69, 0x64, 0x4d, 0x70, 0x4b, 0x43, 0x61, 0x45, 0x6e, + 0x76, 0x6c, 0x61, 0x71, 0x4e, 0x0a, 0x45, 0x72, 0x51, 0x6e, 0x37, 0x59, + 0x63, 0x6b, 0x45, 0x59, 0x56, 0x4a, 0x46, 0x49, 0x30, 0x63, 0x75, 0x59, + 0x56, 0x4a, 0x0a, 0x47, 0x36, 0x53, 0x6f, 0x37, 0x78, 0x34, 0x52, 0x68, + 0x4e, 0x6c, 0x4b, 0x44, 0x66, 0x66, 0x45, 0x7a, 0x74, 0x70, 0x57, 0x0a, + 0x4d, 0x69, 0x7a, 0x36, 0x61, 0x4d, 0x6b, 0x38, 0x62, 0x45, 0x57, 0x6c, + 0x76, 0x5a, 0x41, 0x50, 0x55, 0x58, 0x41, 0x6c, 0x0a, 0x78, 0x67, 0x33, + 0x42, 0x71, 0x70, 0x55, 0x39, 0x6b, 0x71, 0x33, 0x48, 0x32, 0x6b, 0x61, + 0x76, 0x48, 0x38, 0x67, 0x6e, 0x0a, 0x35, 0x4c, 0x65, 0x42, 0x39, 0x6b, + 0x49, 0x68, 0x35, 0x36, 0x39, 0x31, 0x43, 0x46, 0x37, 0x49, 0x34, 0x76, + 0x45, 0x70, 0x0a, 0x76, 0x57, 0x6f, 0x43, 0x6b, 0x71, 0x69, 0x70, 0x61, + 0x46, 0x39, 0x69, 0x50, 0x62, 0x63, 0x38, 0x75, 0x36, 0x46, 0x71, 0x0a, + 0x74, 0x66, 0x6d, 0x78, 0x4f, 0x4a, 0x34, 0x4a, 0x30, 0x76, 0x72, 0x6c, + 0x54, 0x33, 0x37, 0x77, 0x67, 0x4e, 0x7a, 0x61, 0x0a, 0x61, 0x64, 0x4e, + 0x39, 0x63, 0x41, 0x63, 0x34, 0x30, 0x70, 0x54, 0x63, 0x76, 0x37, 0x59, + 0x5a, 0x6e, 0x30, 0x4d, 0x4a, 0x0a, 0x71, 0x43, 0x39, 0x71, 0x44, 0x79, + 0x69, 0x33, 0x30, 0x46, 0x61, 0x78, 0x59, 0x6a, 0x36, 0x67, 0x76, 0x77, + 0x71, 0x78, 0x0a, 0x74, 0x76, 0x36, 0x69, 0x6a, 0x39, 0x64, 0x71, 0x4f, + 0x59, 0x4f, 0x79, 0x4d, 0x51, 0x53, 0x77, 0x45, 0x39, 0x4d, 0x62, 0x0a, + 0x49, 0x79, 0x4a, 0x4c, 0x32, 0x78, 0x43, 0x4d, 0x4f, 0x6c, 0x67, 0x42, + 0x4c, 0x72, 0x76, 0x67, 0x34, 0x6e, 0x4f, 0x76, 0x0a, 0x69, 0x74, 0x44, + 0x50, 0x34, 0x6f, 0x42, 0x56, 0x31, 0x30, 0x6e, 0x43, 0x4c, 0x56, 0x35, + 0x6a, 0x51, 0x6d, 0x77, 0x46, 0x0a, 0x6a, 0x77, 0x74, 0x58, 0x62, 0x78, + 0x67, 0x74, 0x31, 0x49, 0x43, 0x53, 0x48, 0x4e, 0x32, 0x49, 0x61, 0x62, + 0x35, 0x4a, 0x0a, 0x44, 0x6c, 0x4a, 0x52, 0x44, 0x4e, 0x71, 0x54, 0x38, + 0x67, 0x51, 0x46, 0x4a, 0x4c, 0x36, 0x31, 0x47, 0x52, 0x38, 0x64, 0x0a, + 0x76, 0x46, 0x58, 0x66, 0x6a, 0x44, 0x52, 0x61, 0x37, 0x31, 0x62, 0x37, + 0x62, 0x4a, 0x55, 0x59, 0x74, 0x4e, 0x43, 0x44, 0x0a, 0x33, 0x78, 0x56, + 0x56, 0x71, 0x41, 0x62, 0x54, 0x43, 0x52, 0x59, 0x7a, 0x52, 0x4f, 0x38, + 0x6d, 0x46, 0x46, 0x71, 0x51, 0x0a, 0x49, 0x6f, 0x6b, 0x33, 0x56, 0x54, + 0x6b, 0x7a, 0x70, 0x59, 0x75, 0x59, 0x53, 0x78, 0x31, 0x4b, 0x4c, 0x77, + 0x57, 0x59, 0x0a, 0x68, 0x71, 0x34, 0x62, 0x70, 0x7a, 0x71, 0x4f, 0x66, + 0x54, 0x51, 0x72, 0x54, 0x51, 0x77, 0x54, 0x43, 0x44, 0x6f, 0x72, 0x0a, + 0x31, 0x36, 0x6c, 0x78, 0x57, 0x6d, 0x30, 0x72, 0x76, 0x6d, 0x5a, 0x48, + 0x36, 0x54, 0x6b, 0x64, 0x6b, 0x71, 0x41, 0x72, 0x0a, 0x4d, 0x66, 0x47, + 0x32, 0x32, 0x4b, 0x66, 0x59, 0x50, 0x68, 0x43, 0x4a, 0x49, 0x57, 0x47, + 0x39, 0x52, 0x74, 0x59, 0x36, 0x0a, 0x77, 0x6c, 0x50, 0x39, 0x33, 0x74, + 0x4d, 0x31, 0x47, 0x4d, 0x55, 0x74, 0x6a, 0x77, 0x67, 0x69, 0x36, 0x65, + 0x65, 0x4e, 0x0a, 0x68, 0x4d, 0x31, 0x51, 0x6d, 0x71, 0x41, 0x44, 0x37, + 0x48, 0x74, 0x68, 0x4a, 0x6d, 0x41, 0x72, 0x64, 0x7a, 0x32, 0x71, 0x0a, + 0x58, 0x52, 0x58, 0x48, 0x38, 0x4a, 0x69, 0x55, 0x36, 0x6f, 0x74, 0x58, + 0x4f, 0x68, 0x63, 0x70, 0x38, 0x55, 0x79, 0x41, 0x0a, 0x61, 0x45, 0x50, + 0x38, 0x43, 0x76, 0x77, 0x47, 0x33, 0x74, 0x71, 0x30, 0x71, 0x65, 0x55, + 0x6e, 0x59, 0x56, 0x7a, 0x67, 0x0a, 0x6a, 0x53, 0x30, 0x49, 0x76, 0x77, + 0x53, 0x32, 0x65, 0x41, 0x44, 0x4e, 0x59, 0x61, 0x4d, 0x52, 0x36, 0x47, + 0x4c, 0x56, 0x0a, 0x39, 0x70, 0x53, 0x41, 0x48, 0x43, 0x57, 0x5a, 0x63, + 0x34, 0x61, 0x61, 0x79, 0x55, 0x6a, 0x61, 0x73, 0x74, 0x41, 0x42, 0x0a, + 0x4b, 0x6f, 0x76, 0x78, 0x50, 0x64, 0x77, 0x73, 0x42, 0x33, 0x31, 0x64, + 0x72, 0x41, 0x6d, 0x76, 0x68, 0x6e, 0x6f, 0x44, 0x0a, 0x79, 0x4f, 0x66, + 0x72, 0x55, 0x33, 0x57, 0x58, 0x48, 0x5a, 0x33, 0x4d, 0x62, 0x53, 0x31, + 0x4c, 0x66, 0x41, 0x72, 0x74, 0x0a, 0x69, 0x49, 0x4e, 0x76, 0x42, 0x55, + 0x41, 0x73, 0x58, 0x4e, 0x66, 0x7a, 0x61, 0x4e, 0x79, 0x44, 0x65, 0x62, + 0x35, 0x42, 0x0a, 0x35, 0x49, 0x55, 0x6f, 0x70, 0x44, 0x66, 0x4b, 0x50, + 0x5a, 0x35, 0x65, 0x54, 0x44, 0x71, 0x6e, 0x68, 0x58, 0x75, 0x4a, 0x0a, + 0x4f, 0x46, 0x34, 0x6a, 0x4d, 0x73, 0x45, 0x5a, 0x5a, 0x4a, 0x30, 0x49, + 0x33, 0x32, 0x4d, 0x64, 0x4e, 0x4c, 0x59, 0x4d, 0x0a, 0x54, 0x55, 0x4e, + 0x76, 0x7a, 0x5a, 0x43, 0x69, 0x4a, 0x73, 0x50, 0x4f, 0x31, 0x6f, 0x66, + 0x46, 0x65, 0x37, 0x45, 0x63, 0x0a, 0x37, 0x4f, 0x4b, 0x30, 0x30, 0x52, + 0x36, 0x4d, 0x33, 0x68, 0x6e, 0x72, 0x58, 0x39, 0x5a, 0x4d, 0x45, 0x6a, + 0x65, 0x33, 0x0a, 0x6b, 0x62, 0x43, 0x51, 0x65, 0x57, 0x6f, 0x43, 0x48, + 0x64, 0x50, 0x44, 0x66, 0x77, 0x72, 0x58, 0x6a, 0x79, 0x64, 0x4c, 0x0a, + 0x4e, 0x6b, 0x6d, 0x71, 0x30, 0x68, 0x33, 0x68, 0x4a, 0x4d, 0x77, 0x4b, + 0x66, 0x52, 0x47, 0x55, 0x6a, 0x4c, 0x6a, 0x32, 0x0a, 0x54, 0x5a, 0x61, + 0x71, 0x6f, 0x34, 0x49, 0x47, 0x4f, 0x66, 0x54, 0x30, 0x68, 0x4e, 0x4c, + 0x4f, 0x43, 0x75, 0x53, 0x77, 0x0a, 0x65, 0x6e, 0x68, 0x33, 0x42, 0x66, + 0x57, 0x4e, 0x49, 0x43, 0x33, 0x48, 0x50, 0x35, 0x65, 0x38, 0x39, 0x30, + 0x41, 0x66, 0x0a, 0x78, 0x64, 0x76, 0x75, 0x44, 0x31, 0x33, 0x47, 0x34, + 0x6f, 0x4d, 0x78, 0x7a, 0x32, 0x79, 0x67, 0x6e, 0x56, 0x5a, 0x32, 0x0a, + 0x58, 0x55, 0x46, 0x35, 0x31, 0x79, 0x34, 0x4c, 0x45, 0x4d, 0x67, 0x69, + 0x57, 0x50, 0x56, 0x63, 0x49, 0x53, 0x38, 0x77, 0x0a, 0x71, 0x64, 0x6b, + 0x4a, 0x35, 0x6f, 0x4c, 0x6e, 0x70, 0x68, 0x6a, 0x7a, 0x49, 0x31, 0x6f, + 0x69, 0x64, 0x7a, 0x34, 0x41, 0x0a, 0x79, 0x39, 0x65, 0x76, 0x34, 0x5a, + 0x64, 0x6f, 0x6e, 0x70, 0x38, 0x31, 0x79, 0x4d, 0x34, 0x38, 0x4b, 0x4b, + 0x78, 0x32, 0x0a, 0x76, 0x44, 0x4a, 0x57, 0x48, 0x4e, 0x67, 0x31, 0x46, + 0x68, 0x53, 0x7a, 0x4c, 0x68, 0x48, 0x50, 0x51, 0x57, 0x59, 0x75, 0x0a, + 0x74, 0x67, 0x4c, 0x42, 0x44, 0x49, 0x31, 0x66, 0x54, 0x6c, 0x65, 0x61, + 0x6b, 0x49, 0x72, 0x35, 0x54, 0x39, 0x4b, 0x4b, 0x0a, 0x53, 0x73, 0x42, + 0x77, 0x34, 0x30, 0x66, 0x68, 0x49, 0x47, 0x58, 0x43, 0x72, 0x50, 0x61, + 0x6c, 0x73, 0x4d, 0x4b, 0x6d, 0x0a, 0x71, 0x54, 0x58, 0x6b, 0x69, 0x48, + 0x48, 0x50, 0x4c, 0x50, 0x66, 0x63, 0x68, 0x64, 0x67, 0x34, 0x7a, 0x79, + 0x57, 0x6a, 0x0a, 0x76, 0x59, 0x44, 0x34, 0x6e, 0x4c, 0x44, 0x57, 0x64, + 0x49, 0x4a, 0x77, 0x6a, 0x39, 0x65, 0x36, 0x64, 0x52, 0x39, 0x62, 0x0a, + 0x65, 0x6b, 0x56, 0x72, 0x6d, 0x61, 0x56, 0x32, 0x6a, 0x42, 0x77, 0x54, + 0x51, 0x4c, 0x68, 0x45, 0x56, 0x46, 0x79, 0x4b, 0x0a, 0x30, 0x59, 0x38, + 0x6f, 0x30, 0x34, 0x41, 0x4d, 0x78, 0x44, 0x6d, 0x56, 0x50, 0x64, 0x4e, + 0x77, 0x66, 0x78, 0x37, 0x36, 0x0a, 0x32, 0x49, 0x4e, 0x39, 0x6d, 0x46, + 0x4c, 0x43, 0x33, 0x58, 0x6e, 0x6c, 0x58, 0x4b, 0x76, 0x37, 0x79, 0x53, + 0x6c, 0x69, 0x0a, 0x6d, 0x30, 0x6d, 0x61, 0x61, 0x6f, 0x4f, 0x6d, 0x36, + 0x59, 0x70, 0x43, 0x55, 0x72, 0x44, 0x69, 0x71, 0x68, 0x4e, 0x7a, 0x0a, + 0x74, 0x76, 0x42, 0x70, 0x69, 0x6d, 0x51, 0x33, 0x48, 0x6d, 0x77, 0x79, + 0x50, 0x48, 0x6c, 0x33, 0x6b, 0x68, 0x68, 0x78, 0x0a, 0x63, 0x64, 0x77, + 0x6f, 0x39, 0x62, 0x5a, 0x50, 0x5a, 0x70, 0x54, 0x59, 0x59, 0x50, 0x71, + 0x6f, 0x53, 0x59, 0x44, 0x70, 0x0a, 0x35, 0x39, 0x5a, 0x4d, 0x32, 0x78, + 0x66, 0x31, 0x55, 0x33, 0x34, 0x45, 0x47, 0x37, 0x55, 0x6d, 0x64, 0x6e, + 0x72, 0x4f, 0x0a, 0x74, 0x78, 0x48, 0x57, 0x61, 0x33, 0x6a, 0x6c, 0x56, + 0x4b, 0x55, 0x64, 0x53, 0x4f, 0x52, 0x4f, 0x6a, 0x63, 0x38, 0x50, 0x0a, + 0x4a, 0x6f, 0x53, 0x4b, 0x6b, 0x73, 0x43, 0x4e, 0x79, 0x33, 0x42, 0x6a, + 0x77, 0x47, 0x4a, 0x4e, 0x55, 0x55, 0x45, 0x74, 0x0a, 0x4a, 0x30, 0x51, + 0x67, 0x68, 0x68, 0x55, 0x41, 0x65, 0x4b, 0x7a, 0x4f, 0x43, 0x69, 0x4f, + 0x55, 0x51, 0x48, 0x49, 0x30, 0x0a, 0x52, 0x68, 0x37, 0x6f, 0x35, 0x57, + 0x30, 0x46, 0x66, 0x55, 0x48, 0x50, 0x50, 0x47, 0x6a, 0x59, 0x4b, 0x59, + 0x35, 0x64, 0x0a, 0x64, 0x51, 0x43, 0x34, 0x49, 0x52, 0x37, 0x78, 0x39, + 0x64, 0x49, 0x32, 0x63, 0x38, 0x70, 0x58, 0x68, 0x6e, 0x30, 0x79, 0x0a, + 0x46, 0x7a, 0x47, 0x33, 0x37, 0x48, 0x6f, 0x46, 0x35, 0x7a, 0x57, 0x42, + 0x4e, 0x6f, 0x4f, 0x57, 0x56, 0x6b, 0x4f, 0x72, 0x0a, 0x32, 0x4c, 0x59, + 0x69, 0x46, 0x6e, 0x38, 0x52, 0x58, 0x61, 0x32, 0x6e, 0x6a, 0x47, 0x31, + 0x6f, 0x6e, 0x77, 0x4e, 0x71, 0x0a, 0x69, 0x53, 0x30, 0x30, 0x68, 0x63, + 0x57, 0x63, 0x4f, 0x43, 0x67, 0x4a, 0x4f, 0x46, 0x67, 0x61, 0x42, 0x4e, + 0x67, 0x4f, 0x0a, 0x64, 0x50, 0x72, 0x68, 0x64, 0x32, 0x69, 0x4b, 0x61, + 0x56, 0x33, 0x4c, 0x66, 0x5a, 0x4b, 0x36, 0x59, 0x34, 0x33, 0x65, 0x0a, + 0x6e, 0x31, 0x47, 0x4d, 0x46, 0x68, 0x6a, 0x4e, 0x56, 0x53, 0x32, 0x7a, + 0x79, 0x55, 0x73, 0x73, 0x34, 0x36, 0x71, 0x51, 0x0a, 0x44, 0x45, 0x45, + 0x42, 0x44, 0x53, 0x45, 0x6c, 0x61, 0x31, 0x52, 0x6d, 0x6d, 0x6a, 0x74, + 0x59, 0x6b, 0x6c, 0x78, 0x74, 0x0a, 0x68, 0x33, 0x61, 0x70, 0x36, 0x4a, + 0x75, 0x31, 0x4f, 0x51, 0x75, 0x6b, 0x33, 0x46, 0x33, 0x53, 0x72, 0x47, + 0x78, 0x70, 0x0a, 0x4a, 0x68, 0x65, 0x69, 0x66, 0x6b, 0x6a, 0x68, 0x6e, + 0x65, 0x4a, 0x39, 0x56, 0x63, 0x65, 0x68, 0x56, 0x4d, 0x4f, 0x44, 0x0a, + 0x6f, 0x59, 0x78, 0x31, 0x49, 0x42, 0x4e, 0x79, 0x4a, 0x73, 0x33, 0x63, + 0x45, 0x6d, 0x53, 0x37, 0x4b, 0x76, 0x59, 0x72, 0x0a, 0x59, 0x49, 0x76, + 0x35, 0x30, 0x57, 0x44, 0x41, 0x47, 0x70, 0x49, 0x68, 0x64, 0x76, 0x39, + 0x31, 0x79, 0x42, 0x58, 0x44, 0x0a, 0x4a, 0x52, 0x49, 0x4c, 0x46, 0x72, + 0x48, 0x5a, 0x33, 0x4a, 0x63, 0x78, 0x55, 0x75, 0x58, 0x56, 0x49, 0x72, + 0x77, 0x55, 0x0a, 0x4e, 0x34, 0x50, 0x36, 0x4e, 0x44, 0x4f, 0x44, 0x68, + 0x45, 0x72, 0x55, 0x52, 0x4d, 0x6b, 0x72, 0x58, 0x48, 0x59, 0x58, 0x0a, + 0x6f, 0x76, 0x32, 0x79, 0x6b, 0x6c, 0x73, 0x5a, 0x49, 0x4e, 0x50, 0x59, + 0x48, 0x6b, 0x77, 0x6e, 0x54, 0x53, 0x72, 0x69, 0x0a, 0x69, 0x64, 0x78, + 0x45, 0x31, 0x57, 0x42, 0x39, 0x6f, 0x59, 0x49, 0x53, 0x33, 0x4a, 0x57, + 0x4d, 0x6e, 0x6d, 0x38, 0x45, 0x0a, 0x41, 0x50, 0x77, 0x41, 0x5a, 0x53, + 0x63, 0x43, 0x48, 0x73, 0x6e, 0x61, 0x38, 0x61, 0x67, 0x70, 0x79, 0x31, + 0x4c, 0x64, 0x0a, 0x6e, 0x65, 0x48, 0x42, 0x44, 0x6b, 0x54, 0x5a, 0x67, + 0x4a, 0x70, 0x41, 0x55, 0x33, 0x70, 0x57, 0x30, 0x71, 0x4e, 0x4c, 0x0a, + 0x72, 0x41, 0x78, 0x78, 0x55, 0x44, 0x50, 0x35, 0x46, 0x34, 0x55, 0x73, + 0x77, 0x50, 0x55, 0x52, 0x34, 0x78, 0x6a, 0x4f, 0x0a, 0x73, 0x4c, 0x55, + 0x5a, 0x57, 0x5a, 0x33, 0x69, 0x39, 0x67, 0x72, 0x46, 0x45, 0x64, 0x62, + 0x4b, 0x35, 0x64, 0x41, 0x66, 0x0a, 0x6c, 0x56, 0x56, 0x5a, 0x56, 0x36, + 0x61, 0x7a, 0x55, 0x4c, 0x56, 0x75, 0x69, 0x75, 0x52, 0x4c, 0x78, 0x73, + 0x55, 0x73, 0x0a, 0x44, 0x55, 0x74, 0x6a, 0x4e, 0x53, 0x75, 0x46, 0x43, + 0x77, 0x30, 0x47, 0x66, 0x62, 0x68, 0x35, 0x70, 0x35, 0x76, 0x34, 0x0a, + 0x36, 0x64, 0x57, 0x49, 0x67, 0x7a, 0x69, 0x57, 0x4d, 0x72, 0x4e, 0x65, + 0x47, 0x73, 0x79, 0x69, 0x33, 0x57, 0x34, 0x30, 0x0a, 0x6c, 0x35, 0x37, + 0x36, 0x4c, 0x74, 0x37, 0x52, 0x55, 0x68, 0x49, 0x75, 0x38, 0x53, 0x53, + 0x78, 0x62, 0x44, 0x47, 0x68, 0x0a, 0x42, 0x49, 0x78, 0x5a, 0x7a, 0x62, + 0x77, 0x64, 0x6d, 0x38, 0x79, 0x62, 0x75, 0x67, 0x74, 0x46, 0x4a, 0x42, + 0x64, 0x37, 0x0a, 0x41, 0x4d, 0x51, 0x72, 0x66, 0x79, 0x48, 0x69, 0x41, + 0x73, 0x54, 0x61, 0x32, 0x43, 0x33, 0x4f, 0x7a, 0x69, 0x37, 0x50, 0x0a, + 0x7a, 0x4e, 0x34, 0x5a, 0x6d, 0x46, 0x52, 0x7a, 0x72, 0x51, 0x33, 0x62, + 0x44, 0x73, 0x68, 0x46, 0x35, 0x49, 0x45, 0x72, 0x0a, 0x47, 0x34, 0x73, + 0x72, 0x32, 0x67, 0x76, 0x48, 0x66, 0x4b, 0x50, 0x49, 0x45, 0x74, 0x4f, + 0x47, 0x52, 0x6e, 0x34, 0x4d, 0x0a, 0x68, 0x41, 0x39, 0x6f, 0x72, 0x68, + 0x50, 0x53, 0x73, 0x57, 0x55, 0x65, 0x76, 0x65, 0x32, 0x33, 0x62, 0x69, + 0x62, 0x41, 0x0a, 0x6a, 0x53, 0x54, 0x69, 0x73, 0x4d, 0x64, 0x53, 0x74, + 0x63, 0x61, 0x54, 0x4d, 0x64, 0x4c, 0x56, 0x4b, 0x61, 0x74, 0x63, 0x0a, + 0x49, 0x6b, 0x44, 0x62, 0x33, 0x46, 0x42, 0x66, 0x58, 0x6b, 0x42, 0x6f, + 0x61, 0x55, 0x31, 0x47, 0x62, 0x37, 0x74, 0x34, 0x0a, 0x37, 0x37, 0x54, + 0x4b, 0x64, 0x59, 0x6a, 0x58, 0x6f, 0x38, 0x52, 0x77, 0x54, 0x34, 0x6b, + 0x44, 0x56, 0x34, 0x51, 0x47, 0x0a, 0x32, 0x4c, 0x31, 0x42, 0x41, 0x4c, + 0x68, 0x48, 0x73, 0x6a, 0x54, 0x52, 0x6c, 0x49, 0x65, 0x7a, 0x39, 0x51, + 0x43, 0x4c, 0x0a, 0x4b, 0x45, 0x5a, 0x72, 0x4f, 0x5a, 0x45, 0x74, 0x5a, + 0x65, 0x46, 0x6b, 0x4c, 0x6f, 0x51, 0x6e, 0x78, 0x76, 0x50, 0x6d, 0x0a, + 0x7a, 0x6d, 0x63, 0x66, 0x76, 0x78, 0x75, 0x5a, 0x6f, 0x53, 0x76, 0x63, + 0x36, 0x76, 0x72, 0x39, 0x79, 0x6f, 0x43, 0x70, 0x0a, 0x50, 0x64, 0x38, + 0x53, 0x74, 0x35, 0x58, 0x52, 0x79, 0x34, 0x4b, 0x31, 0x68, 0x33, 0x57, + 0x51, 0x43, 0x56, 0x74, 0x47, 0x0a, 0x36, 0x72, 0x4f, 0x63, 0x52, 0x38, + 0x55, 0x6b, 0x69, 0x4d, 0x38, 0x6f, 0x6c, 0x55, 0x31, 0x76, 0x54, 0x4c, + 0x33, 0x68, 0x0a, 0x66, 0x71, 0x68, 0x77, 0x39, 0x4a, 0x4e, 0x73, 0x6b, + 0x5a, 0x4e, 0x67, 0x66, 0x79, 0x75, 0x5a, 0x62, 0x43, 0x77, 0x41, 0x0a, + 0x41, 0x43, 0x4e, 0x51, 0x53, 0x58, 0x4e, 0x36, 0x45, 0x73, 0x63, 0x6a, + 0x66, 0x7a, 0x4f, 0x73, 0x79, 0x51, 0x61, 0x5a, 0x0a, 0x32, 0x7a, 0x33, + 0x71, 0x46, 0x6c, 0x68, 0x47, 0x38, 0x6e, 0x58, 0x47, 0x53, 0x4a, 0x48, + 0x4b, 0x61, 0x39, 0x69, 0x73, 0x0a, 0x78, 0x50, 0x78, 0x51, 0x74, 0x7a, + 0x68, 0x6f, 0x6d, 0x6a, 0x51, 0x39, 0x68, 0x45, 0x35, 0x74, 0x7a, 0x4a, + 0x51, 0x44, 0x0a, 0x32, 0x61, 0x51, 0x6f, 0x78, 0x64, 0x54, 0x47, 0x65, + 0x79, 0x6c, 0x41, 0x47, 0x30, 0x55, 0x33, 0x50, 0x57, 0x53, 0x6e, 0x0a, + 0x34, 0x35, 0x56, 0x4f, 0x74, 0x68, 0x43, 0x56, 0x4e, 0x4f, 0x65, 0x46, + 0x32, 0x53, 0x47, 0x73, 0x36, 0x70, 0x62, 0x7a, 0x0a, 0x68, 0x4c, 0x62, + 0x56, 0x64, 0x4d, 0x77, 0x53, 0x73, 0x7a, 0x78, 0x4a, 0x32, 0x36, 0x39, + 0x77, 0x44, 0x72, 0x52, 0x48, 0x0a, 0x65, 0x59, 0x37, 0x45, 0x34, 0x39, + 0x65, 0x71, 0x6f, 0x36, 0x78, 0x6e, 0x35, 0x7a, 0x6f, 0x4f, 0x48, 0x49, + 0x34, 0x6e, 0x0a, 0x47, 0x44, 0x51, 0x72, 0x48, 0x64, 0x49, 0x78, 0x53, + 0x46, 0x4e, 0x37, 0x76, 0x6f, 0x43, 0x4f, 0x5a, 0x56, 0x39, 0x6a, 0x0a, + 0x57, 0x30, 0x6a, 0x43, 0x34, 0x51, 0x71, 0x4d, 0x43, 0x7a, 0x4a, 0x71, + 0x67, 0x54, 0x6d, 0x68, 0x56, 0x59, 0x62, 0x53, 0x0a, 0x31, 0x34, 0x4e, + 0x6c, 0x77, 0x77, 0x6b, 0x41, 0x61, 0x33, 0x4a, 0x77, 0x4b, 0x66, 0x47, + 0x48, 0x78, 0x4e, 0x4e, 0x76, 0x0a, 0x68, 0x4b, 0x74, 0x70, 0x6a, 0x7a, + 0x58, 0x43, 0x43, 0x43, 0x56, 0x51, 0x41, 0x65, 0x7a, 0x59, 0x6d, 0x5a, + 0x66, 0x71, 0x0a, 0x63, 0x73, 0x74, 0x35, 0x30, 0x5a, 0x4b, 0x4d, 0x61, + 0x5a, 0x62, 0x7a, 0x71, 0x66, 0x58, 0x72, 0x74, 0x63, 0x76, 0x31, 0x0a, + 0x34, 0x6a, 0x6f, 0x49, 0x34, 0x77, 0x4a, 0x6d, 0x52, 0x6e, 0x4b, 0x4d, + 0x4a, 0x61, 0x48, 0x65, 0x42, 0x47, 0x75, 0x36, 0x0a, 0x79, 0x44, 0x4d, + 0x69, 0x30, 0x30, 0x39, 0x70, 0x31, 0x4e, 0x72, 0x51, 0x4f, 0x57, 0x61, + 0x51, 0x71, 0x4a, 0x78, 0x54, 0x0a, 0x66, 0x4a, 0x69, 0x76, 0x67, 0x52, + 0x4f, 0x51, 0x76, 0x30, 0x43, 0x61, 0x64, 0x62, 0x69, 0x6e, 0x78, 0x38, + 0x37, 0x5a, 0x0a, 0x4c, 0x55, 0x47, 0x58, 0x31, 0x44, 0x39, 0x51, 0x42, + 0x72, 0x6f, 0x66, 0x56, 0x74, 0x6e, 0x44, 0x55, 0x34, 0x56, 0x45, 0x0a, + 0x46, 0x58, 0x51, 0x78, 0x6b, 0x32, 0x58, 0x49, 0x45, 0x55, 0x58, 0x74, + 0x6a, 0x6a, 0x32, 0x6a, 0x33, 0x66, 0x4f, 0x6c, 0x0a, 0x49, 0x76, 0x78, + 0x76, 0x71, 0x34, 0x5a, 0x42, 0x65, 0x6a, 0x46, 0x7a, 0x55, 0x57, 0x34, + 0x4b, 0x58, 0x48, 0x58, 0x42, 0x0a, 0x59, 0x65, 0x47, 0x73, 0x5a, 0x68, + 0x33, 0x4d, 0x6d, 0x72, 0x4b, 0x6a, 0x70, 0x59, 0x39, 0x4d, 0x45, 0x36, + 0x74, 0x72, 0x0a, 0x50, 0x49, 0x33, 0x6d, 0x38, 0x71, 0x36, 0x31, 0x65, + 0x62, 0x46, 0x6a, 0x6e, 0x45, 0x68, 0x61, 0x77, 0x75, 0x6b, 0x32, 0x0a, + 0x59, 0x77, 0x55, 0x4b, 0x76, 0x46, 0x43, 0x31, 0x44, 0x56, 0x51, 0x79, + 0x47, 0x6e, 0x32, 0x52, 0x6b, 0x46, 0x54, 0x5a, 0x0a, 0x42, 0x39, 0x4f, + 0x67, 0x4e, 0x38, 0x47, 0x56, 0x74, 0x55, 0x46, 0x30, 0x61, 0x56, 0x37, + 0x31, 0x6e, 0x72, 0x51, 0x6d, 0x0a, 0x41, 0x73, 0x63, 0x43, 0x59, 0x56, + 0x65, 0x39, 0x36, 0x5a, 0x39, 0x55, 0x64, 0x56, 0x4f, 0x49, 0x65, 0x58, + 0x4f, 0x37, 0x0a, 0x32, 0x72, 0x31, 0x68, 0x4a, 0x76, 0x59, 0x74, 0x50, + 0x69, 0x42, 0x5a, 0x5a, 0x4b, 0x76, 0x62, 0x6a, 0x4a, 0x63, 0x54, 0x0a, + 0x76, 0x52, 0x4b, 0x79, 0x67, 0x49, 0x4f, 0x34, 0x77, 0x55, 0x33, 0x73, + 0x39, 0x50, 0x48, 0x69, 0x78, 0x6f, 0x39, 0x4e, 0x0a, 0x49, 0x69, 0x35, + 0x4e, 0x52, 0x6e, 0x51, 0x6f, 0x4e, 0x52, 0x71, 0x33, 0x6e, 0x56, 0x52, + 0x4a, 0x38, 0x48, 0x78, 0x6a, 0x0a, 0x4b, 0x6b, 0x4e, 0x62, 0x43, 0x69, + 0x65, 0x70, 0x70, 0x70, 0x37, 0x4d, 0x56, 0x47, 0x72, 0x79, 0x33, 0x34, + 0x38, 0x42, 0x0a, 0x51, 0x4e, 0x53, 0x33, 0x75, 0x6d, 0x5a, 0x45, 0x68, + 0x4a, 0x71, 0x7a, 0x54, 0x79, 0x58, 0x30, 0x6a, 0x6b, 0x75, 0x57, 0x0a, + 0x65, 0x69, 0x61, 0x79, 0x37, 0x66, 0x72, 0x4a, 0x56, 0x6d, 0x74, 0x45, + 0x37, 0x67, 0x74, 0x49, 0x79, 0x6c, 0x4a, 0x41, 0x0a, 0x36, 0x74, 0x55, + 0x4d, 0x72, 0x6a, 0x70, 0x34, 0x4d, 0x70, 0x72, 0x41, 0x79, 0x6c, 0x62, + 0x61, 0x61, 0x38, 0x79, 0x52, 0x0a, 0x59, 0x69, 0x6b, 0x58, 0x37, 0x48, + 0x6e, 0x38, 0x42, 0x76, 0x74, 0x4f, 0x4c, 0x59, 0x56, 0x30, 0x56, 0x73, + 0x46, 0x61, 0x0a, 0x51, 0x62, 0x30, 0x33, 0x64, 0x70, 0x76, 0x61, 0x52, + 0x66, 0x45, 0x46, 0x55, 0x72, 0x77, 0x50, 0x64, 0x4b, 0x6f, 0x7a, 0x0a, + 0x30, 0x71, 0x55, 0x69, 0x56, 0x6f, 0x41, 0x42, 0x44, 0x36, 0x45, 0x73, + 0x62, 0x48, 0x46, 0x49, 0x77, 0x58, 0x38, 0x44, 0x0a, 0x69, 0x72, 0x6c, + 0x6e, 0x7a, 0x70, 0x77, 0x72, 0x6d, 0x4a, 0x4c, 0x70, 0x32, 0x42, 0x32, + 0x79, 0x34, 0x42, 0x59, 0x59, 0x0a, 0x53, 0x73, 0x72, 0x73, 0x54, 0x4a, + 0x49, 0x4e, 0x35, 0x59, 0x65, 0x52, 0x71, 0x52, 0x65, 0x58, 0x73, 0x48, + 0x30, 0x76, 0x0a, 0x32, 0x31, 0x5a, 0x34, 0x48, 0x69, 0x57, 0x70, 0x71, + 0x64, 0x4f, 0x47, 0x44, 0x6c, 0x76, 0x76, 0x73, 0x72, 0x79, 0x36, 0x0a, + 0x4e, 0x67, 0x42, 0x38, 0x4e, 0x64, 0x55, 0x47, 0x47, 0x61, 0x52, 0x77, + 0x38, 0x52, 0x6a, 0x7a, 0x49, 0x48, 0x4f, 0x57, 0x0a, 0x39, 0x76, 0x6a, + 0x76, 0x59, 0x4d, 0x31, 0x37, 0x53, 0x30, 0x6d, 0x34, 0x65, 0x79, 0x54, + 0x67, 0x4e, 0x6f, 0x6e, 0x55, 0x0a, 0x78, 0x76, 0x66, 0x59, 0x78, 0x55, + 0x77, 0x34, 0x52, 0x51, 0x6e, 0x6b, 0x44, 0x74, 0x74, 0x50, 0x6c, 0x6e, + 0x74, 0x62, 0x0a, 0x76, 0x72, 0x35, 0x69, 0x6a, 0x68, 0x79, 0x50, 0x6a, + 0x47, 0x48, 0x76, 0x52, 0x6c, 0x33, 0x31, 0x50, 0x37, 0x4e, 0x59 +}; +static const unsigned char hmac_sha1_vector1024_multiblock_out[] = { + 0xea, 0x99, 0xd8, 0x40, 0x7d, 0xbe, 0xea, 0x3f, 0xc2, 0x81, 0xe9, 0xfe, + 0x99, 0x7d, 0xb4, 0x41, 0x52, 0x56, 0x05, 0xa3 +}; +/* Test vector for HMAC-sha224 */ +static const unsigned char hmac_sha224_vector1024_multiblock_out[] = { + 0xb1, 0xd0, 0xcc, 0x79, 0xca, 0xc1, 0x21, 0x6e, 0x8e, 0x9b, 0xa1, 0xe9, + 0xde, 0x60, 0x3a, 0xcc, 0xd9, 0x87, 0xc6, 0x3d, 0xb0, 0xcb, 0x34, 0x66, + 0xd1, 0x90, 0x10, 0xd8 +}; +/* Test vector for HMAC-sha256 */ +static const unsigned char hmac_sha256_vector1024_multiblock_out[] = { + 0xbd, 0x90, 0x11, 0x66, 0x29, 0xd5, 0xde, 0x19, 0x5d, 0x67, 0x70, 0xb8, + 0x13, 0x5c, 0x2e, 0x0d, 0x97, 0x9e, 0xd2, 0x0d, 0x77, 0x17, 0x74, 0x5a, + 0x73, 0x93, 0x5c, 0x99, 0x2c, 0xe5, 0x74, 0x58 +}; +/* Test vector for HMAC-sha384 */ +static const unsigned char hmac_sha384_vector1024_multiblock_out[] = { + 0xfb, 0x32, 0xe4, 0x56, 0x6c, 0xdf, 0x54, 0xca, 0xec, 0xd7, 0x3c, 0xb8, + 0xb4, 0x15, 0x5d, 0xf4, 0xe5, 0x77, 0x6e, 0xda, 0x72, 0xb7, 0x6b, 0xe0, + 0x91, 0x96, 0x72, 0xcf, 0x2b, 0xdc, 0x34, 0x19, 0xe9, 0xee, 0xf0, 0x35, + 0xc9, 0x33, 0x08, 0x28, 0x31, 0xef, 0x58, 0xbb, 0x0a, 0x5d, 0x8b, 0x02 +}; +/* Test vector for HMAC-sha512 */ +static const unsigned char hmac_sha512_vector1024_multiblock_out[] = { + 0x84, 0x11, 0x55, 0x1e, 0x9f, 0xf3, 0x93, 0xbd, 0xdc, 0x69, 0x33, 0x30, + 0x23, 0x7b, 0x9a, 0xe6, 0x55, 0x34, 0xc0, 0x7c, 0x10, 0xad, 0x52, 0x49, + 0xb6, 0x8b, 0x0d, 0x5e, 0x63, 0x76, 0xda, 0x30, 0x36, 0x45, 0xce, 0x87, + 0x4f, 0xa6, 0xda, 0x29, 0xa5, 0xbb, 0x52, 0x7e, 0x32, 0x50, 0x56, 0xb5, + 0x40, 0x48, 0x4b, 0x2d, 0xc1, 0x1f, 0x2b, 0x47, 0x5e, 0xc8, 0xa1, 0xc1, + 0x1e, 0x42, 0x9d, 0x68 +}; diff --git a/crypto/test/rsaperf/Makefile b/crypto/test/rsaperf/Makefile new file mode 100755 index 0000000..b34fb47 --- /dev/null +++ b/crypto/test/rsaperf/Makefile @@ -0,0 +1,33 @@ +# +# Makefile for crypto testing +# +# Copyright (c) 2013-2016 INSIDE Secure Corporation. All Rights Reserved. +# + +# SRC and MATRIXSSL_ROOT must be defined before including common.mk +TEST_SRC:=rsaperf.c +SRC:=$(TEST_SRC) +MATRIXSSL_ROOT:=../../.. +include $(MATRIXSSL_ROOT)/common.mk + +# Generated files +TEST_EXE:=rsaperf + +# Linked files +STATIC:=\ + $(MATRIXSSL_ROOT)/crypto/libcrypt_s.a \ + $(MATRIXSSL_ROOT)/core/libcore_s.a + +all: compile + +compile: $(OBJS) $(TEST_EXE) + +# Additional Dependencies +$(OBJS): $(MATRIXSSL_ROOT)/common.mk Makefile $(wildcard *.h) + +$(TEST_EXE): $(TEST_SRC:.c=.o) $(STATIC) + $(CC) -o $@ $^ $(LDFLAGS) + +clean: + rm -f $(OBJS) $(TEST_EXE) + diff --git a/crypto/test/rsaperf/rsa17e1024.h b/crypto/test/rsaperf/rsa17e1024.h new file mode 100644 index 0000000..b8e8197 --- /dev/null +++ b/crypto/test/rsaperf/rsa17e1024.h @@ -0,0 +1,55 @@ +/** + * @file rsa17e1024.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa17e1024[] = { +48, 130, 2, 91, 2, 1, 0, 2, 129, 129, 0, 186, 66, +23, 2, 3, 171, 99, 26, 138, 64, 202, 52, 202, 58, 104, +254, 99, 222, 7, 140, 110, 50, 17, 4, 41, 149, 197, 127, +115, 199, 140, 90, 96, 74, 106, 110, 34, 135, 124, 28, 131, +127, 147, 211, 247, 97, 141, 4, 76, 25, 152, 6, 196, 162, +38, 83, 206, 47, 113, 13, 123, 167, 171, 47, 16, 185, 251, +127, 5, 229, 177, 198, 213, 37, 111, 244, 127, 8, 184, 142, +140, 12, 72, 163, 86, 68, 10, 226, 230, 205, 179, 102, 221, +188, 190, 222, 221, 53, 49, 99, 232, 174, 228, 254, 213, 197, +32, 33, 175, 191, 189, 149, 213, 11, 75, 76, 131, 10, 251, +50, 110, 209, 192, 27, 109, 180, 111, 131, 2, 1, 17, 2, +129, 128, 16, 111, 62, 67, 241, 67, 212, 9, 223, 5, 183, +125, 32, 231, 9, 67, 159, 102, 106, 19, 235, 155, 1, 128, +94, 5, 175, 139, 62, 235, 245, 203, 189, 51, 190, 24, 198, +207, 184, 32, 162, 48, 231, 101, 134, 196, 215, 188, 157, 77, +141, 106, 2, 74, 138, 233, 70, 230, 17, 129, 48, 142, 203, +86, 211, 103, 91, 212, 90, 75, 125, 202, 93, 77, 57, 34, +246, 212, 61, 58, 125, 235, 67, 195, 131, 111, 201, 110, 119, +201, 27, 227, 247, 87, 254, 26, 39, 106, 18, 249, 161, 168, +246, 97, 233, 242, 152, 184, 205, 119, 225, 42, 209, 99, 200, +106, 127, 19, 255, 1, 146, 40, 76, 117, 139, 99, 162, 153, +2, 65, 0, 213, 232, 36, 213, 96, 66, 159, 1, 135, 69, +239, 131, 65, 42, 97, 208, 0, 63, 18, 238, 220, 105, 131, +66, 108, 58, 154, 165, 63, 216, 176, 216, 242, 199, 218, 136, +48, 254, 250, 30, 90, 173, 215, 228, 123, 233, 0, 17, 53, +227, 238, 45, 47, 230, 150, 117, 194, 205, 242, 236, 155, 237, +7, 25, 2, 65, 0, 222, 233, 27, 66, 251, 160, 214, 122, +129, 201, 163, 143, 165, 206, 75, 124, 248, 184, 53, 183, 82, +231, 156, 188, 130, 86, 135, 84, 170, 169, 120, 221, 129, 16, +127, 206, 143, 138, 87, 224, 31, 175, 48, 14, 197, 221, 112, +74, 4, 188, 125, 189, 178, 236, 112, 0, 51, 144, 106, 165, +80, 179, 138, 251, 2, 64, 125, 211, 217, 110, 116, 219, 229, +15, 245, 56, 50, 137, 113, 160, 117, 197, 165, 202, 191, 215, +204, 242, 197, 174, 154, 4, 90, 247, 203, 52, 43, 202, 233, +42, 68, 80, 28, 210, 56, 198, 143, 177, 142, 13, 238, 137, +15, 25, 46, 194, 79, 222, 88, 105, 133, 174, 174, 211, 127, +214, 121, 214, 184, 225, 2, 65, 0, 209, 204, 85, 228, 176, +151, 96, 115, 76, 250, 3, 90, 5, 118, 221, 162, 203, 248, +171, 6, 228, 157, 192, 177, 107, 156, 187, 154, 250, 249, 219, +42, 211, 211, 75, 28, 195, 85, 7, 105, 135, 59, 120, 134, +95, 223, 120, 190, 34, 147, 73, 43, 2, 192, 105, 105, 153, +241, 85, 80, 75, 244, 70, 145, 2, 65, 0, 206, 173, 131, +11, 77, 16, 62, 215, 6, 239, 83, 254, 147, 236, 131, 155, +114, 72, 118, 34, 117, 56, 245, 166, 102, 13, 29, 215, 100, +71, 195, 125, 142, 107, 106, 85, 181, 26, 46, 30, 200, 91, +24, 34, 116, 163, 8, 74, 66, 69, 25, 183, 113, 21, 198, +93, 247, 20, 146, 71, 172, 61, 0, 97, 1}; + diff --git a/crypto/test/rsaperf/rsa17e1024.pem b/crypto/test/rsaperf/rsa17e1024.pem new file mode 100644 index 0000000..edd8786 --- /dev/null +++ b/crypto/test/rsaperf/rsa17e1024.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,C3B5CB2347618043 + +HFTuP2xZImKDq33B8OxA8iNtdUl+Plu+vTkrKWJ3PIkq6LoiyHsFwRiDFTnsCBMt +M5K15GLb8qKuYyIoUT4aMHESq5or2UD09ZDtq0VHThMGQgYlNGPLlN7IgoD7W27m +VUUyiMYJyslvOykFjWxhU6yW9P88S56HN34ybRPk0+C3VHUSQIJdFfhEyNkUEkT3 +flADRBx7X+tdnH62MXkFC4GZ2mUBDBnYI39s4JinHpAkvwVMJIF0PMjeIiQeZnFx +nRtGMSzVx8eUytsHFvZmZHJ9kHs3okz4/4a//FHcQtP0v7K3W1Af9tEgMde79ONf +QoxKOxTEhrQ4Of7/6c7gmOunvIf+Of5qRqHvB7xmPUkcon8SXzl8F5N64Odw72Bt +5fSwx1dDNWFNVbhrrrSheILC9+idr0fGWb0T84APSA1w0Y3Szi/YxxwwZHw4+bV0 +Hmd8CNefURtwF6w2mjp/DLa7326Cjh/ZdZWFWr5CcdFGji7JI0D6r98yOwRW11jL +ntM/4IkXf4Chnngffhgbym/gNUuWL8MMpwgsewHskgfXJHK0A2tducBEF1Eboyt7 +jTS8Q5pOdDIWFohZlLbrXDXWgnPwuDPbX5U6MhQdQ46P7KLbimbdc1KTX/P/M1Fi +VktxX2iNoFkoDtYzko7TJlxAXI+ykGYvr1yoFB4lRjKLf74aCSlt4iLFtRYo6l2O +h7AtT9HhtJXDJSdUjMGRDJNVfM2bLVnfImtkhR+T2v9UQNZPzfFFr9U9DEvnehH2 +eANZavbHcGF7+lfXmc2EhDOCeHAfamNbe1L/yvrBpp4= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa17e1024_1.h b/crypto/test/rsaperf/rsa17e1024_1.h new file mode 100644 index 0000000..669e542 --- /dev/null +++ b/crypto/test/rsaperf/rsa17e1024_1.h @@ -0,0 +1,55 @@ +/** + * @file rsa17e1024_1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa17e10241[] = { +48, 130, 2, 90, 2, 1, 0, 2, 129, 129, 0, 192, 223, +124, 181, 34, 146, 49, 61, 225, 195, 65, 243, 32, 203, 182, +172, 248, 219, 114, 13, 25, 127, 246, 52, 95, 38, 224, 48, +239, 89, 190, 14, 166, 16, 0, 109, 85, 129, 12, 93, 123, +175, 151, 242, 119, 29, 2, 189, 94, 109, 191, 69, 203, 218, +239, 244, 204, 24, 29, 179, 247, 116, 175, 179, 59, 137, 233, +199, 109, 200, 56, 67, 140, 74, 245, 150, 231, 79, 25, 153, +186, 243, 61, 6, 46, 44, 126, 151, 162, 85, 24, 222, 95, +82, 235, 190, 16, 135, 44, 189, 23, 14, 55, 16, 25, 7, +223, 67, 134, 221, 129, 178, 115, 156, 159, 176, 79, 133, 231, +230, 172, 197, 203, 4, 147, 243, 27, 41, 2, 1, 17, 2, +129, 128, 3, 38, 201, 252, 68, 84, 96, 45, 89, 219, 222, +198, 230, 153, 234, 185, 52, 150, 211, 217, 186, 250, 143, 188, +65, 34, 239, 149, 182, 241, 146, 42, 17, 197, 179, 10, 39, +11, 79, 173, 222, 12, 18, 96, 211, 24, 188, 71, 178, 16, +218, 33, 196, 149, 251, 142, 10, 7, 22, 60, 170, 134, 237, +30, 130, 9, 149, 169, 212, 9, 247, 194, 41, 238, 246, 150, +65, 92, 216, 242, 168, 146, 35, 155, 16, 123, 10, 49, 190, +39, 109, 62, 51, 196, 29, 96, 8, 144, 97, 235, 35, 171, +17, 180, 24, 153, 104, 29, 58, 16, 146, 54, 125, 66, 102, +250, 163, 145, 167, 54, 119, 165, 251, 119, 15, 91, 229, 11, +2, 65, 0, 200, 32, 234, 199, 247, 38, 160, 27, 31, 38, +132, 178, 226, 84, 177, 91, 67, 13, 210, 211, 248, 228, 250, +167, 179, 190, 119, 194, 237, 230, 223, 17, 56, 2, 71, 116, +189, 16, 165, 196, 185, 204, 168, 98, 169, 202, 131, 171, 190, +31, 217, 28, 134, 97, 96, 176, 227, 47, 181, 232, 131, 43, +85, 235, 2, 65, 0, 246, 184, 4, 101, 249, 12, 93, 87, +51, 157, 125, 197, 49, 148, 241, 110, 248, 40, 231, 32, 68, +170, 71, 62, 223, 144, 29, 9, 119, 189, 6, 234, 204, 103, +22, 69, 6, 75, 85, 215, 23, 91, 134, 74, 149, 28, 214, +153, 144, 105, 193, 219, 225, 236, 39, 99, 149, 129, 145, 11, +254, 105, 106, 59, 2, 64, 94, 45, 155, 169, 101, 63, 90, +103, 29, 183, 197, 249, 211, 235, 158, 193, 136, 247, 114, 69, +162, 77, 163, 33, 189, 255, 71, 106, 202, 78, 135, 23, 41, +106, 123, 250, 179, 83, 32, 213, 12, 36, 19, 1, 64, 215, +197, 125, 255, 30, 11, 209, 48, 45, 211, 38, 16, 142, 236, +49, 46, 170, 251, 65, 2, 65, 0, 145, 32, 243, 135, 71, +52, 115, 36, 60, 122, 194, 115, 255, 12, 81, 200, 206, 54, +45, 154, 130, 190, 132, 67, 26, 24, 137, 141, 25, 66, 4, +17, 165, 105, 208, 221, 78, 255, 35, 111, 119, 38, 199, 119, +42, 137, 111, 45, 39, 197, 189, 84, 42, 138, 233, 254, 87, +241, 220, 217, 224, 242, 182, 245, 2, 64, 54, 61, 198, 154, +121, 153, 6, 93, 176, 140, 107, 184, 247, 130, 74, 215, 250, +120, 164, 15, 101, 25, 127, 164, 44, 33, 100, 198, 59, 240, +81, 80, 156, 121, 63, 179, 63, 11, 201, 163, 55, 13, 163, +80, 162, 114, 207, 89, 255, 158, 225, 148, 227, 128, 158, 232, +172, 58, 63, 148, 156, 15, 151, 216, 2, 2}; + diff --git a/crypto/test/rsaperf/rsa17e1024_1.pem b/crypto/test/rsaperf/rsa17e1024_1.pem new file mode 100644 index 0000000..1380ffb --- /dev/null +++ b/crypto/test/rsaperf/rsa17e1024_1.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,E54BF5F5176BDFE8 + +/IOkoKFSHxp23MLhg36mNOGQ1vlNWXSFOALuVPJ8hcpLJg2G7SCnX0UJhGWnbAmL +9Z1pqMD21bBej67duvyt7hs+BWAfqu4iz3Nmy4lFiAqCynQGv5WlVAlgVExxl/66 +PTvPAdG6yCjNHeFYRP32oxEOs6LL6QiHDkwMD9dLp1nJhT6YPwuTymx5JFqjhuRJ +iPxEqWlIqjyYC8++0XTknbCKdWtyLq5B/OX1BsegUPoYK5TVt8LPOMdV/C5wO8P+ +zliCMH/6YhMduPyOV16XJW2NMheByFiFeI8L/692GJuE7PxJXQOdbOddxNMatZeS +nSR2XYDKKoUSvfN2mn5zV0KNn7sW2aAUyDoyFgJ259dk5VN2+5jP3nh2sTRF3JW6 +sRGjhLj2nPx3K1zXk6S/WrMjUj9taFCQwWwFPEzewjHI0bYcX9i2//pGAy+kG7Qe +OtxvdaUPj+2QeHQdoOwyeGYouQE5+mcgtjpUwCewqSgqNzQUoRVfNOGKoq/HpA+k +21B4TVRhWFfyMiI1V1Cr5Oue0WGruz1Mwtng3vFvMR/+3iHq5cAzhA6StztnIGpj +vsDZXz4cZMVhk57CZE8/srgX3VBjnDUXywtIavDgO41oH+way1WqowXLA9Xr3sTc +PADrhqbaFhbdWWegCWwToGkWkAtldXnEVyMqHyaHZnHqadf01rsL0LhCNfIt8Qzy +fiAinKbIX8XFzOJrmBSNw5WsDvDWwo38/Nu8rzsXSVmH0lVwRVFEu03gAg2O+tDl +0gvF1j6LxLewCm6SNwxiuksS4ip1ujGChSEiEw+o4F0= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa17e2048.h b/crypto/test/rsaperf/rsa17e2048.h new file mode 100644 index 0000000..56c799e --- /dev/null +++ b/crypto/test/rsaperf/rsa17e2048.h @@ -0,0 +1,100 @@ +/** + * @file rsa17e2048.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa17e2048[] = { +48, 130, 4, 161, 2, 1, 0, 2, 130, 1, 1, 0, 195, +185, 75, 176, 248, 148, 133, 80, 194, 24, 125, 78, 91, 148, +193, 119, 17, 144, 6, 54, 204, 255, 194, 98, 121, 187, 33, +146, 197, 115, 93, 116, 77, 55, 1, 103, 196, 62, 246, 243, +129, 245, 173, 221, 95, 236, 106, 156, 236, 12, 173, 67, 115, +82, 159, 173, 92, 56, 157, 202, 156, 128, 202, 32, 27, 12, +73, 201, 191, 161, 203, 222, 67, 232, 199, 13, 146, 111, 18, +122, 194, 142, 50, 55, 226, 215, 12, 125, 28, 14, 246, 143, +199, 218, 198, 186, 45, 220, 156, 223, 225, 131, 138, 106, 123, +208, 56, 144, 181, 75, 61, 95, 3, 202, 163, 87, 42, 78, +167, 127, 56, 78, 162, 99, 152, 138, 234, 211, 209, 102, 119, +149, 230, 31, 99, 72, 76, 124, 146, 37, 97, 237, 235, 241, +152, 213, 106, 83, 214, 162, 160, 183, 61, 202, 199, 197, 65, +132, 53, 79, 200, 252, 72, 97, 25, 59, 96, 57, 241, 104, +201, 48, 114, 159, 140, 69, 138, 239, 241, 25, 224, 238, 99, +233, 237, 3, 8, 21, 97, 110, 16, 104, 7, 146, 28, 216, +216, 11, 120, 246, 80, 242, 227, 127, 26, 67, 146, 90, 205, +170, 138, 243, 23, 164, 38, 93, 110, 228, 11, 140, 77, 101, +95, 245, 232, 11, 49, 38, 231, 137, 154, 135, 144, 218, 130, +95, 23, 52, 54, 147, 103, 159, 204, 59, 125, 240, 108, 234, +201, 0, 123, 205, 223, 38, 133, 231, 2, 1, 17, 2, 130, +1, 0, 30, 179, 167, 123, 33, 249, 46, 2, 160, 244, 200, +92, 154, 234, 40, 98, 253, 188, 61, 53, 197, 205, 196, 35, +134, 139, 201, 7, 246, 208, 215, 113, 157, 174, 70, 126, 181, +95, 53, 203, 216, 38, 137, 180, 75, 72, 56, 225, 102, 72, +67, 85, 223, 228, 205, 192, 215, 64, 24, 192, 104, 220, 252, +145, 149, 207, 187, 66, 200, 186, 1, 220, 151, 51, 146, 172, +203, 173, 7, 235, 25, 127, 183, 144, 75, 189, 87, 74, 215, +57, 144, 22, 141, 199, 247, 4, 27, 69, 190, 65, 60, 121, +6, 167, 74, 163, 44, 2, 158, 242, 180, 75, 35, 187, 100, +234, 137, 37, 111, 155, 124, 72, 145, 241, 129, 87, 11, 188, +142, 228, 108, 118, 23, 84, 157, 76, 172, 47, 157, 108, 43, +31, 160, 79, 148, 14, 166, 174, 212, 234, 204, 185, 166, 84, +239, 95, 89, 149, 50, 251, 214, 223, 131, 110, 21, 85, 186, +152, 248, 217, 203, 242, 9, 47, 108, 65, 100, 211, 148, 17, +37, 129, 237, 102, 159, 170, 123, 122, 197, 117, 243, 115, 85, +174, 237, 164, 161, 190, 228, 137, 189, 63, 207, 80, 150, 178, +125, 151, 72, 177, 203, 214, 144, 115, 128, 163, 23, 222, 74, +142, 115, 154, 170, 80, 208, 88, 96, 195, 110, 114, 254, 216, +179, 193, 128, 108, 196, 73, 121, 60, 6, 57, 139, 187, 57, +223, 133, 23, 94, 184, 125, 45, 226, 13, 177, 49, 2, 129, +129, 0, 250, 52, 124, 162, 180, 224, 27, 53, 0, 241, 166, +156, 202, 171, 172, 201, 18, 43, 5, 176, 149, 27, 50, 223, +116, 18, 231, 167, 25, 22, 211, 99, 85, 176, 177, 227, 50, +136, 102, 41, 66, 92, 147, 1, 37, 135, 154, 22, 172, 92, +126, 87, 216, 125, 217, 240, 58, 90, 174, 140, 123, 113, 72, +160, 106, 43, 243, 188, 197, 9, 150, 19, 215, 35, 197, 18, +18, 20, 145, 86, 158, 27, 197, 202, 51, 226, 160, 81, 232, +65, 149, 176, 194, 240, 65, 84, 33, 9, 31, 121, 106, 0, +31, 133, 45, 78, 99, 67, 85, 184, 73, 48, 77, 69, 26, +232, 135, 138, 70, 193, 208, 48, 4, 161, 31, 203, 125, 205, +2, 129, 129, 0, 200, 65, 199, 130, 92, 131, 221, 74, 129, +219, 95, 247, 4, 88, 161, 45, 54, 204, 254, 8, 180, 46, +148, 184, 69, 90, 106, 30, 77, 86, 60, 230, 249, 122, 176, +160, 30, 176, 116, 129, 124, 159, 194, 8, 82, 137, 160, 13, +251, 206, 162, 212, 185, 84, 64, 139, 120, 201, 134, 90, 59, +44, 215, 200, 91, 42, 254, 34, 139, 224, 241, 244, 99, 88, +84, 203, 71, 125, 32, 95, 192, 33, 81, 177, 10, 225, 49, +251, 206, 121, 90, 143, 105, 123, 32, 222, 150, 206, 168, 207, +157, 108, 98, 92, 233, 154, 140, 102, 94, 39, 136, 132, 114, +171, 214, 137, 101, 117, 53, 179, 252, 248, 89, 40, 62, 67, +190, 131, 2, 129, 128, 117, 190, 88, 197, 9, 210, 223, 160, +120, 234, 48, 73, 200, 201, 66, 64, 129, 5, 47, 218, 160, +133, 69, 29, 220, 69, 33, 184, 11, 206, 129, 152, 40, 83, +38, 137, 8, 184, 168, 139, 226, 254, 99, 75, 213, 108, 253, +55, 216, 163, 255, 56, 101, 224, 223, 7, 162, 253, 127, 81, +43, 8, 34, 45, 95, 35, 189, 254, 122, 215, 85, 174, 251, +212, 152, 249, 113, 235, 143, 176, 74, 103, 108, 34, 235, 61, +120, 159, 3, 226, 160, 203, 167, 7, 166, 69, 181, 49, 120, +57, 34, 210, 225, 168, 21, 82, 16, 152, 40, 86, 185, 7, +171, 228, 72, 229, 229, 110, 63, 106, 67, 218, 92, 136, 14, +246, 89, 81, 2, 129, 129, 0, 129, 147, 249, 144, 150, 55, +52, 213, 219, 141, 242, 205, 2, 207, 239, 209, 246, 72, 104, +35, 191, 225, 231, 194, 135, 58, 128, 230, 110, 70, 220, 28, +251, 199, 219, 178, 230, 174, 105, 128, 246, 73, 65, 80, 173, +224, 148, 189, 193, 13, 60, 47, 74, 190, 11, 165, 138, 100, +71, 224, 8, 44, 19, 39, 74, 12, 194, 142, 210, 250, 246, +233, 109, 117, 100, 11, 16, 35, 201, 167, 94, 51, 173, 84, +112, 115, 152, 208, 28, 48, 103, 198, 53, 49, 141, 189, 52, +103, 154, 104, 56, 175, 138, 240, 211, 100, 0, 126, 121, 40, +163, 160, 254, 231, 168, 239, 125, 226, 110, 11, 13, 25, 42, +161, 145, 179, 93, 39, 2, 129, 128, 91, 121, 209, 144, 28, +170, 33, 214, 186, 93, 18, 186, 211, 244, 92, 152, 64, 230, +30, 135, 101, 177, 82, 208, 91, 65, 234, 135, 194, 50, 174, +27, 175, 28, 105, 49, 182, 171, 191, 33, 155, 118, 252, 0, +36, 82, 185, 50, 99, 32, 152, 205, 100, 191, 136, 242, 156, +21, 59, 14, 229, 13, 198, 88, 85, 245, 173, 44, 212, 146, +110, 164, 192, 85, 49, 29, 58, 32, 24, 92, 116, 150, 106, +169, 45, 105, 243, 6, 138, 12, 119, 253, 217, 127, 163, 49, +127, 213, 207, 117, 231, 225, 255, 181, 104, 203, 251, 12, 171, +232, 49, 12, 78, 28, 4, 119, 70, 136, 132, 231, 217, 76, +70, 184, 210, 232, 236, 177, 3, 3, 3}; + diff --git a/crypto/test/rsaperf/rsa17e2048.pem b/crypto/test/rsaperf/rsa17e2048.pem new file mode 100644 index 0000000..12aecb1 --- /dev/null +++ b/crypto/test/rsaperf/rsa17e2048.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,B8B37C196F2DF063 + +n1XrxQSe03bHoDVtUsZAC3Sx8tgP5O0snCNS37jPWyzsMpEJbJPoQhAV+K41maLG +3AhYpeCtp/4ANuHRlVv6D7KjoN0ppE3o1XTSeKbKZjr+SxJBcwcgbXgIcQXCueJy +pj7sGE7JM7FE4AxWixRsKevWW7soBBVC53D4o2I9fy+FnKALIOeZb2tOLFk2f4+u +DDbriF0AQfVFKyIDh7RkAXWKdnryrIhPkdOqhTu7N6l53tNIDAchIJFMk8mZP3Pd +9Lu4yZjpkkm3rSJUiXGoYRW8AndnzeBV5kRzhjQiY5tD/0skSISNu5Td9oaaMNAl +8MIR12pACAKI4AH5FbRkV512cNF83ThSpB/civPprndzWpHljzsPt4dbwmvOVNz4 +aWuUa8dRbplbaxeEPuxgZa4N/Dfw0II+lzGuZKJeAWWNVeLXS1koErAGU6GP7jCv +kH8VVkgjhfu8zJy7c24ZSuZXI34UzLHDlU5f5Jlcg64h8uNw4GlZo/6rH5DLJCid +AHk+eIVPXUZ5/HimtJ9m+/t4rcgaL8Eoyv7PlENQeb8vQT104RW+SKl0JsJUShAW +6Z2xt2+uo+tNBj74s015kUk2ngn1p+4kL8JbzBJcszWqVyxPgg5a85YhKp5B7ojA +RdBssA7Dxc5+m9eKsgYDPij491iIZSi8M/e8ndtb5xwAcyYr+iBtBcws9oyi1or3 +VESNOCbD3Jfl+sAetn1t78IvZekj5eeEtI8mz/wKczJ/oWrA7aE1ZX+ahFB0OsUT +YdjcnJ17cmkMXAj1w/I1UzZ2j+TGgMtGK8KQ5SqWeHpow21LD/+gWsSKsy1cibho +9EH7iMnzhJwpEoN42q61dqU9OhwNL+TV4WpiVXxtW4ODxYduNKRtJ6vMEn++mMIY +XSm5QzW1hkgz8o3DhcXP61pF5lHGuAKvxUCrDCv/gEyrf9HaWnJ77b4Keue/EUfu +Ah+6z8QoPWTCqvjx6YVz27CKdJJzSJxA11DP6lSK4GY5IxRPwpdwmuKrns01GU75 +CUMTARJqGrnblzi7iJXXkW9I5n3maT30y7stcaEXel5OnMgJhpGIKMxkJDXpuqCU +Mzc86rJ86GD9/XDsW6Jj4LDKtM82JjA93UY0OPl8UXalt9gdBETs4WekjMzo2x8P +U+WQpI8YoauMRuZGxKVdyxObHJm3aZzr5yv1uEamtnA2y6sz3KVd86plAh4Gg2A/ +2/BuJY0S4R2NXOgO2BuzB9xnWsBg1dQxjjV7VrlQF23tV2S0P4kdCiX3XrGkqhSG +9W56AVC8QLZOLAfOcKM3XSqMEWdDXbxyLBGFZB1wpt7BoByO/JLSg56J4VvGvZfC +wxzRL9gUsKNnJZo9nPqA+FHS7GSyQop3zdyz6C7B93ZN/61rybKhCLkD2pwldkuQ +d6ZkaJ0/UD5p1TgckMfXt7w3LR0/6jV5Gp0PsaEPBlZfFTxoMOxt1ghL0+Mq/0vB +fUdhDGBhXP7DpxAk7U20M0CdlFj9v2soccIINRbY4IWFPR6YeXtlLlBUkbME/V5p ++r5094jrAyt6H/wUNFeDKYoRRzAhQgBo4E0oFhwwfQov2NffKeE/fg== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa17e2048_1.h b/crypto/test/rsaperf/rsa17e2048_1.h new file mode 100644 index 0000000..310406a --- /dev/null +++ b/crypto/test/rsaperf/rsa17e2048_1.h @@ -0,0 +1,100 @@ +/** + * @file rsa17e2048_1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa17e20481[] = { +48, 130, 4, 162, 2, 1, 0, 2, 130, 1, 1, 0, 218, +91, 199, 115, 202, 110, 105, 73, 89, 122, 157, 76, 14, 67, +206, 162, 89, 59, 0, 16, 21, 152, 217, 104, 248, 172, 135, +128, 192, 16, 230, 191, 133, 229, 78, 253, 157, 152, 146, 81, +226, 21, 70, 73, 166, 15, 98, 188, 112, 181, 38, 234, 141, +80, 133, 84, 147, 54, 149, 247, 16, 171, 172, 40, 144, 219, +209, 2, 175, 151, 66, 248, 163, 8, 213, 39, 112, 212, 216, +136, 53, 32, 233, 58, 176, 112, 188, 253, 155, 228, 230, 1, +168, 90, 13, 225, 12, 4, 136, 197, 227, 148, 195, 161, 57, +192, 105, 15, 40, 44, 136, 125, 56, 25, 210, 231, 202, 48, +61, 211, 36, 189, 75, 248, 217, 152, 215, 174, 20, 186, 46, +45, 182, 19, 65, 90, 192, 129, 102, 89, 107, 49, 138, 24, +99, 62, 74, 37, 13, 192, 176, 193, 75, 212, 121, 2, 251, +114, 38, 136, 239, 187, 21, 39, 52, 219, 103, 13, 137, 27, +182, 3, 67, 96, 173, 90, 122, 136, 29, 62, 14, 149, 108, +162, 3, 95, 243, 237, 70, 138, 109, 197, 34, 11, 156, 51, +182, 36, 115, 151, 216, 166, 120, 221, 157, 181, 139, 142, 171, +250, 80, 135, 111, 81, 134, 182, 1, 29, 67, 103, 127, 93, +59, 0, 119, 0, 239, 105, 90, 135, 13, 154, 206, 5, 246, +63, 116, 137, 23, 148, 11, 247, 166, 42, 33, 10, 1, 53, +198, 136, 92, 196, 123, 66, 249, 51, 2, 1, 17, 2, 130, +1, 0, 19, 68, 85, 93, 10, 85, 9, 74, 60, 153, 224, +179, 227, 36, 25, 195, 7, 223, 143, 16, 122, 96, 79, 107, +37, 0, 42, 18, 227, 197, 65, 137, 94, 163, 74, 188, 6, +96, 73, 37, 87, 182, 149, 66, 187, 212, 46, 91, 235, 211, +191, 171, 72, 180, 71, 255, 238, 223, 43, 89, 144, 135, 158, +63, 208, 139, 221, 188, 120, 231, 179, 21, 240, 68, 139, 71, +62, 169, 94, 102, 95, 10, 110, 238, 151, 25, 1, 157, 232, +27, 185, 241, 22, 98, 76, 132, 204, 90, 192, 198, 42, 171, +62, 112, 27, 175, 24, 84, 41, 49, 27, 26, 27, 137, 206, +216, 55, 124, 186, 41, 55, 242, 149, 195, 34, 66, 49, 37, +201, 11, 252, 83, 31, 34, 36, 143, 95, 47, 229, 203, 62, +55, 184, 175, 162, 139, 127, 12, 29, 160, 169, 124, 49, 114, +142, 243, 174, 141, 103, 204, 250, 248, 198, 56, 189, 81, 92, +112, 23, 70, 39, 212, 150, 48, 167, 122, 146, 130, 43, 39, +156, 159, 10, 131, 29, 57, 227, 183, 24, 85, 56, 240, 74, +110, 147, 99, 129, 71, 80, 213, 228, 64, 225, 152, 21, 196, +228, 174, 202, 118, 41, 20, 180, 190, 108, 13, 29, 128, 53, +135, 173, 208, 9, 235, 65, 193, 232, 96, 104, 131, 16, 116, +207, 226, 115, 28, 106, 228, 14, 100, 135, 234, 101, 203, 227, +255, 35, 0, 81, 110, 93, 205, 66, 229, 173, 85, 2, 129, +129, 0, 236, 209, 217, 80, 40, 32, 82, 2, 207, 76, 249, +80, 181, 144, 83, 92, 127, 127, 116, 65, 57, 192, 200, 85, +38, 110, 223, 254, 81, 248, 218, 2, 147, 102, 92, 225, 165, +207, 25, 184, 129, 219, 237, 201, 128, 209, 209, 87, 129, 51, +106, 148, 209, 198, 119, 225, 163, 209, 106, 73, 134, 126, 253, +123, 178, 188, 35, 207, 129, 41, 69, 185, 142, 25, 110, 237, +242, 94, 91, 43, 222, 70, 4, 78, 130, 73, 136, 90, 154, +113, 98, 252, 98, 143, 241, 9, 167, 48, 113, 102, 248, 72, +103, 116, 227, 226, 122, 173, 78, 171, 146, 147, 9, 250, 95, +35, 242, 77, 182, 203, 87, 97, 129, 66, 36, 217, 166, 101, +2, 129, 129, 0, 236, 11, 41, 47, 130, 111, 251, 169, 186, +106, 235, 94, 159, 41, 180, 74, 177, 145, 224, 175, 217, 141, +188, 236, 159, 168, 154, 58, 239, 54, 180, 29, 234, 166, 156, +109, 45, 114, 53, 179, 255, 122, 4, 208, 113, 188, 199, 64, +124, 230, 201, 146, 248, 111, 40, 71, 190, 254, 116, 222, 1, +154, 234, 251, 121, 20, 241, 252, 123, 210, 239, 16, 218, 88, +98, 137, 95, 74, 101, 251, 44, 121, 37, 78, 65, 239, 53, +198, 194, 254, 215, 20, 21, 151, 132, 55, 59, 229, 137, 189, +193, 198, 150, 79, 96, 199, 184, 80, 21, 26, 55, 56, 82, +242, 26, 170, 22, 198, 19, 17, 126, 238, 180, 108, 10, 232, +251, 183, 2, 129, 129, 0, 181, 24, 241, 121, 136, 24, 183, +47, 83, 58, 220, 197, 63, 140, 123, 251, 112, 142, 164, 49, +224, 222, 183, 80, 44, 114, 231, 134, 62, 175, 61, 77, 67, +138, 131, 67, 36, 113, 49, 201, 84, 62, 196, 229, 98, 130, +84, 202, 113, 220, 6, 53, 145, 91, 136, 217, 185, 130, 5, +251, 253, 112, 43, 64, 121, 158, 238, 53, 68, 167, 23, 51, +138, 200, 39, 166, 230, 132, 99, 214, 64, 143, 229, 44, 250, +56, 59, 24, 27, 192, 30, 132, 195, 215, 124, 22, 112, 202, +177, 18, 129, 160, 199, 149, 159, 52, 184, 42, 45, 25, 202, +112, 113, 10, 193, 57, 155, 44, 94, 155, 127, 14, 83, 201, +43, 61, 6, 197, 2, 129, 129, 0, 152, 187, 237, 121, 24, +42, 87, 139, 241, 24, 1, 181, 178, 72, 41, 93, 129, 244, +250, 204, 35, 91, 182, 122, 253, 229, 144, 248, 245, 35, 101, +124, 197, 2, 101, 55, 149, 224, 125, 26, 29, 199, 108, 134, +224, 46, 219, 71, 216, 89, 25, 4, 190, 222, 131, 121, 183, +209, 211, 38, 61, 70, 31, 147, 168, 179, 51, 42, 230, 181, +169, 191, 156, 87, 78, 209, 91, 198, 186, 117, 89, 3, 24, +35, 148, 19, 64, 234, 5, 179, 244, 148, 134, 113, 25, 80, +234, 133, 119, 62, 140, 113, 112, 81, 122, 219, 149, 96, 254, +152, 126, 21, 98, 216, 228, 19, 180, 98, 12, 86, 157, 109, +71, 145, 52, 60, 102, 163, 2, 129, 128, 25, 235, 215, 78, +66, 7, 114, 179, 76, 162, 231, 98, 39, 137, 97, 81, 92, +198, 195, 151, 227, 249, 172, 116, 138, 198, 175, 198, 98, 205, +201, 137, 113, 164, 229, 178, 171, 56, 35, 222, 98, 17, 122, +223, 10, 125, 51, 113, 86, 184, 106, 13, 82, 238, 121, 250, +207, 53, 224, 120, 201, 7, 252, 131, 11, 21, 57, 45, 252, +202, 240, 84, 145, 220, 94, 160, 115, 12, 198, 12, 117, 242, +77, 15, 140, 224, 187, 51, 124, 167, 212, 185, 213, 94, 50, +9, 9, 93, 166, 252, 250, 144, 35, 235, 10, 40, 25, 34, +2, 162, 66, 119, 103, 181, 55, 3, 121, 62, 28, 69, 17, +121, 141, 146, 29, 211, 9, 4, 2, 2}; + diff --git a/crypto/test/rsaperf/rsa17e2048_1.pem b/crypto/test/rsaperf/rsa17e2048_1.pem new file mode 100644 index 0000000..a2b4803 --- /dev/null +++ b/crypto/test/rsaperf/rsa17e2048_1.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,21D304636651AAFE + +zI7fx+a7SFYUx4v+wP7hyl5HpeMAC7ZM4dGMjPAaTj0keOtF/tmOj+8qVqm4+fXL +6MBB3Mx8tC3QUstx0xdVSo3URDwvoSoLbJfk48EkeKosqEs6bbMU304375zyAiXd +GAf7/LrUyoX39LiRb5RbgYsRVaAJ9nemFPySHL9R1kdcMohG7eJtd/U9Ts59p3HB +bV2scnx5d0gzGOaBkb88v/sZeNQmMAX1g7xWTu6+MM8MvnFW/ddgcvO+hztilU/L +/Hu3LlSsli/UM2rihuHTFZajCROJVUn5wrL5u12EJPAWFel5fRdeWPlojx1NfivO +887tcmQl76wdrlpGfSJBQO2WD77gfQ3gLpfhFYc6ATGR7xSKpFpBp9LNR/oHeI4V +djy7piKl/ItoF9KzLmpRywLyU/NL53D3v/aNAndnDOxDh+4h11IfpzMLTgAs4tN2 +VC5HpbGzel3ATJwowJ47q9W2Fuoy4BUYB88eBQDEUzWy+aCRZnituPvNFLvXnQr7 +0jGKxy+JcR5wKHpGhBqtZQwSd6XI6FSd3Ok3WapL5DhcIABGl6Z7Cq4A8PG6q+t0 +sEvTDN+fplG8UdUNexEYz5liwURrEO26HGszbW+N3pMzefqNPc7AtHpm70pYljdE +oZhwuhmgTAOv26EHU2WJwdVA0Q3cmVwTzlrwNToCnAQOYqEXAYOfIVTjXfJQDOGm +UPY6IqcfMeAKbx66vafFEM3XoThiu75jzCMaCD4M/6aVAms1Tp7P858uwiTSfhcy +GgBQR9cgbq843SC7ErSRavaFYJX6j0zrhYCq/3S0NHPASE44bvZbAFNbwI9T+f63 +IeeUZs9+BueKzZnf4ENE5sH6bZQGLW1i+GnImnjGUqrEGIM6Q37T/4t/k0Mor7Zp +RfxB+ZDQIWyOrkBlmtlp/+86HkQ8xz/gi+NlBvKYoqiKFafYQ3N8vnR0juZ7AJCn +6KUeLBSra4++TtrSRWUnQm8TuzHDXjU1vhm9ED1zzcewtFb7CtWfM1qIg/y9sBPI +7KObGtlcmoX95rOreFR0WuoDIBVSSThD1jT4DicEIKq4NedTnU+0Vs2JWjbyPyZ1 +EubDUlTpjrilnUm7QD0zaxq+8lNSupMFfZI9aO3hvD3RAXB8YPUJGi8AIjpPD8ep +TZmN9uLbFt7PVijowcNvnW903iPOT24US6Sgnxq2C3nPovFDygTGd7UsxUC9yMfh +Hq7ptGT39MCXOzWiUk5C5v5FxE8zyNfAN+HvH0xioFPrTU8fUVvXrSUn1EKvKlBC +mfO96VfczpoJM72NwzAIOS7GWce5po+kjP8pFsszRnftApe+XOmFUCdp8Ubl9Zmy +9iM9QZyKduEE8Ed3ncxU6r0UUig5+PS73Zt1I0dNBTRuvLHJM+1RBarxNzuex0BU +EBGWTZwA10XAMPIWfVCRl7adf3jEPs4GxTBDejj2Uq+H/wZr3OCDzuzQOnfMykCC +fqd8p3aaAYZ7MyGEv5pQiEDVFJ2ANDJMiWg4L+sUu6WW+W71SIezq40SHRtPKRHo +q8Lm2shJAMA/5o3lULiy5qteICLO5TW+YYAfFc13VhGNBnCBnKVsKQ== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa17e4096.h b/crypto/test/rsaperf/rsa17e4096.h new file mode 100644 index 0000000..83075e8 --- /dev/null +++ b/crypto/test/rsaperf/rsa17e4096.h @@ -0,0 +1,189 @@ +/** + * @file rsa17e4096.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa17e4096[] = { +48, 130, 9, 37, 2, 1, 0, 2, 130, 2, 1, 0, 224, +156, 16, 147, 24, 222, 171, 90, 137, 196, 170, 175, 226, 124, +222, 6, 244, 206, 19, 40, 249, 90, 113, 231, 137, 13, 1, +169, 160, 240, 69, 211, 242, 208, 2, 231, 173, 247, 12, 234, +118, 212, 122, 241, 186, 229, 40, 31, 241, 12, 62, 220, 61, +17, 238, 58, 164, 227, 116, 126, 81, 12, 78, 179, 89, 60, +43, 188, 232, 31, 146, 129, 215, 253, 76, 46, 134, 178, 109, +76, 39, 120, 26, 159, 78, 154, 42, 4, 90, 120, 127, 2, +216, 148, 200, 154, 124, 52, 95, 175, 233, 60, 156, 55, 88, +44, 156, 148, 24, 187, 232, 208, 140, 193, 184, 20, 252, 132, +105, 232, 89, 249, 195, 69, 199, 192, 209, 241, 183, 199, 247, +83, 77, 92, 248, 127, 158, 6, 211, 78, 130, 201, 194, 81, +113, 132, 148, 86, 169, 151, 10, 116, 98, 196, 117, 130, 199, +251, 157, 85, 209, 105, 128, 226, 127, 56, 197, 167, 105, 170, +192, 220, 248, 244, 90, 208, 220, 99, 163, 149, 181, 50, 150, +52, 92, 208, 217, 100, 75, 245, 57, 55, 181, 183, 239, 152, +59, 113, 233, 158, 19, 110, 131, 2, 156, 140, 32, 86, 77, +255, 186, 84, 59, 46, 2, 25, 214, 160, 163, 150, 42, 17, +243, 191, 99, 100, 112, 103, 179, 175, 158, 156, 20, 217, 109, +15, 46, 72, 75, 85, 92, 179, 212, 210, 162, 41, 134, 95, +221, 64, 95, 161, 218, 230, 250, 115, 121, 9, 22, 249, 0, +83, 101, 243, 21, 32, 71, 233, 159, 156, 106, 177, 23, 209, +123, 191, 50, 131, 92, 153, 115, 128, 202, 94, 160, 38, 145, +58, 185, 0, 218, 178, 223, 134, 127, 94, 248, 32, 235, 209, +194, 222, 80, 111, 159, 81, 10, 160, 152, 33, 168, 208, 62, +172, 190, 76, 43, 223, 3, 197, 146, 132, 220, 151, 107, 187, +40, 69, 7, 149, 239, 110, 63, 162, 176, 160, 153, 249, 9, +6, 153, 8, 145, 99, 221, 134, 45, 166, 16, 122, 36, 200, +37, 171, 109, 220, 150, 105, 245, 184, 253, 128, 9, 131, 150, +198, 73, 238, 124, 196, 127, 184, 158, 199, 87, 221, 76, 55, +156, 140, 172, 96, 104, 140, 66, 77, 144, 196, 21, 148, 186, +27, 144, 231, 98, 209, 229, 171, 77, 244, 0, 190, 187, 203, +135, 133, 126, 77, 142, 221, 179, 164, 195, 254, 93, 136, 137, +182, 199, 215, 27, 172, 142, 203, 187, 236, 217, 122, 235, 38, +242, 107, 54, 240, 94, 154, 34, 136, 136, 60, 37, 191, 66, +228, 255, 247, 14, 24, 166, 47, 30, 66, 138, 127, 35, 131, +143, 220, 126, 160, 160, 147, 176, 81, 184, 142, 38, 113, 180, +197, 20, 7, 175, 211, 25, 200, 162, 39, 127, 192, 192, 139, +96, 75, 247, 30, 228, 134, 121, 141, 4, 13, 244, 63, 192, +135, 60, 133, 244, 200, 30, 136, 226, 21, 151, 94, 97, 175, +205, 188, 149, 97, 2, 1, 17, 2, 130, 2, 0, 36, 85, +123, 38, 218, 156, 125, 153, 240, 163, 148, 20, 236, 42, 201, +144, 47, 33, 85, 236, 70, 116, 71, 33, 176, 133, 222, 98, +248, 38, 222, 30, 133, 101, 105, 225, 182, 126, 141, 98, 41, +207, 140, 91, 207, 44, 153, 80, 118, 13, 70, 103, 100, 59, +95, 1, 245, 6, 173, 50, 141, 28, 88, 6, 108, 141, 127, +139, 188, 35, 57, 149, 1, 14, 159, 37, 164, 217, 25, 53, +187, 23, 49, 123, 167, 17, 104, 173, 225, 117, 95, 215, 12, +114, 107, 190, 163, 38, 151, 2, 26, 111, 115, 159, 138, 127, +175, 234, 199, 196, 11, 78, 233, 151, 206, 184, 25, 202, 32, +48, 225, 96, 223, 150, 149, 4, 214, 170, 221, 186, 179, 77, +121, 176, 235, 246, 134, 189, 86, 227, 73, 220, 223, 111, 14, +153, 54, 29, 19, 231, 125, 237, 46, 24, 64, 47, 130, 59, +134, 160, 180, 178, 242, 247, 118, 118, 92, 53, 111, 53, 249, +141, 40, 69, 165, 71, 110, 242, 0, 27, 251, 109, 212, 136, +120, 109, 20, 27, 132, 194, 5, 125, 183, 191, 162, 254, 69, +217, 244, 217, 146, 51, 194, 94, 138, 67, 216, 13, 246, 7, +124, 66, 84, 222, 7, 222, 136, 93, 192, 28, 14, 85, 186, +64, 215, 155, 138, 167, 93, 17, 29, 108, 18, 110, 119, 73, +252, 49, 87, 122, 252, 44, 38, 49, 33, 194, 243, 218, 205, +51, 211, 60, 16, 150, 78, 40, 246, 240, 159, 60, 72, 124, +231, 81, 177, 18, 247, 118, 6, 180, 213, 187, 44, 179, 147, +87, 155, 109, 165, 187, 48, 58, 197, 219, 153, 33, 113, 63, +94, 62, 104, 85, 33, 198, 9, 165, 220, 115, 106, 53, 196, +13, 75, 174, 124, 3, 217, 238, 92, 38, 111, 16, 0, 38, +88, 191, 158, 8, 149, 245, 54, 28, 212, 77, 239, 165, 70, +115, 37, 216, 85, 92, 126, 224, 228, 207, 195, 108, 21, 40, +105, 251, 220, 2, 176, 115, 152, 242, 159, 222, 160, 78, 251, +37, 250, 145, 197, 45, 54, 153, 163, 87, 68, 240, 250, 168, +126, 75, 170, 103, 122, 245, 171, 227, 169, 200, 151, 59, 240, +14, 113, 20, 139, 3, 78, 44, 203, 228, 8, 200, 85, 61, +58, 65, 156, 31, 145, 245, 232, 192, 255, 231, 119, 11, 240, +67, 49, 218, 195, 135, 87, 146, 41, 87, 239, 84, 103, 100, +7, 243, 242, 23, 197, 133, 76, 18, 76, 60, 136, 72, 64, +188, 140, 157, 62, 185, 96, 231, 13, 158, 230, 72, 226, 138, +117, 113, 21, 192, 112, 229, 23, 185, 78, 136, 178, 206, 38, +195, 202, 201, 181, 80, 178, 17, 106, 117, 107, 70, 228, 195, +203, 202, 14, 228, 244, 72, 70, 22, 205, 132, 105, 180, 84, +217, 98, 75, 197, 62, 198, 183, 81, 23, 115, 175, 180, 63, +160, 237, 19, 107, 121, 153, 133, 198, 63, 6, 161, 169, 96, +250, 246, 181, 2, 130, 1, 1, 0, 240, 234, 122, 24, 122, +104, 12, 20, 218, 1, 135, 182, 126, 84, 253, 54, 176, 98, +54, 132, 157, 114, 180, 201, 204, 130, 86, 183, 216, 240, 98, +40, 45, 70, 49, 178, 14, 248, 31, 62, 119, 46, 221, 104, +118, 227, 5, 246, 31, 2, 248, 44, 168, 35, 151, 38, 85, +162, 40, 105, 135, 224, 203, 81, 213, 45, 175, 177, 123, 67, +227, 185, 46, 181, 201, 137, 203, 94, 138, 171, 103, 193, 232, +121, 86, 9, 77, 14, 95, 95, 78, 120, 189, 238, 179, 75, +47, 231, 195, 215, 39, 98, 3, 113, 197, 66, 91, 61, 124, +111, 180, 216, 11, 123, 37, 73, 214, 235, 25, 254, 199, 118, +25, 161, 95, 228, 174, 79, 8, 230, 127, 81, 36, 154, 176, +238, 43, 90, 32, 127, 186, 169, 169, 98, 178, 224, 236, 7, +44, 183, 114, 153, 99, 56, 253, 135, 175, 243, 86, 188, 31, +128, 61, 83, 235, 20, 30, 239, 121, 197, 85, 81, 202, 238, +112, 89, 163, 120, 122, 106, 252, 22, 177, 6, 168, 38, 149, +71, 135, 150, 154, 216, 50, 61, 81, 3, 252, 128, 233, 199, +134, 88, 133, 191, 198, 133, 53, 7, 246, 70, 66, 64, 147, +36, 108, 199, 18, 206, 231, 43, 113, 55, 25, 191, 152, 200, +42, 46, 46, 109, 227, 234, 70, 199, 12, 152, 200, 109, 195, +212, 38, 205, 148, 91, 32, 147, 182, 87, 233, 242, 4, 84, +222, 59, 200, 157, 2, 130, 1, 1, 0, 238, 172, 56, 224, +58, 45, 9, 182, 174, 169, 128, 159, 84, 233, 138, 12, 152, +234, 159, 29, 2, 199, 237, 27, 241, 54, 9, 159, 20, 149, +254, 162, 22, 149, 245, 126, 46, 81, 199, 100, 255, 156, 242, +52, 50, 238, 234, 253, 13, 77, 137, 108, 159, 16, 122, 94, +69, 52, 206, 89, 94, 177, 223, 66, 17, 188, 59, 4, 39, +5, 51, 242, 145, 213, 92, 5, 193, 4, 112, 240, 215, 61, +227, 147, 110, 1, 151, 45, 152, 115, 138, 197, 211, 89, 193, +9, 19, 193, 157, 11, 241, 240, 114, 52, 93, 197, 27, 93, +36, 22, 113, 20, 37, 85, 75, 11, 184, 139, 106, 29, 198, +148, 206, 52, 238, 136, 94, 226, 249, 12, 83, 148, 47, 12, +87, 85, 206, 224, 101, 236, 25, 17, 122, 22, 194, 210, 146, +192, 95, 0, 29, 84, 138, 49, 129, 126, 67, 2, 179, 171, +95, 111, 19, 135, 227, 168, 101, 1, 84, 159, 33, 62, 143, +238, 55, 178, 139, 78, 189, 134, 160, 221, 131, 2, 28, 144, +76, 116, 22, 188, 166, 247, 232, 152, 35, 80, 168, 130, 162, +147, 25, 224, 228, 188, 28, 27, 162, 222, 24, 230, 100, 76, +85, 160, 117, 165, 88, 55, 6, 175, 220, 192, 134, 206, 154, +81, 41, 152, 35, 57, 177, 163, 195, 112, 2, 42, 3, 147, +208, 251, 50, 231, 139, 72, 246, 250, 77, 220, 225, 253, 141, +67, 221, 206, 122, 149, 2, 130, 1, 0, 127, 139, 49, 148, +125, 9, 232, 71, 70, 61, 11, 156, 217, 120, 73, 209, 168, +172, 119, 55, 38, 45, 171, 1, 108, 69, 0, 187, 175, 21, +217, 156, 204, 172, 176, 229, 203, 176, 137, 2, 243, 205, 132, +70, 93, 14, 198, 235, 182, 16, 161, 129, 13, 184, 125, 50, +105, 146, 21, 101, 11, 179, 62, 118, 158, 9, 32, 199, 95, +96, 45, 67, 235, 141, 106, 178, 92, 155, 118, 150, 250, 177, +243, 139, 135, 230, 206, 113, 5, 80, 146, 244, 160, 201, 170, +54, 221, 32, 88, 159, 20, 217, 137, 90, 89, 95, 93, 122, +231, 134, 110, 204, 186, 200, 185, 99, 83, 169, 164, 89, 180, +228, 43, 175, 201, 90, 242, 222, 140, 61, 202, 238, 185, 6, +153, 231, 128, 92, 228, 7, 98, 210, 74, 157, 169, 254, 155, +18, 219, 112, 45, 156, 127, 210, 224, 147, 32, 234, 60, 250, +46, 203, 107, 195, 3, 251, 151, 232, 49, 104, 120, 118, 152, +156, 89, 152, 222, 18, 155, 41, 148, 132, 123, 214, 89, 5, +94, 22, 207, 79, 187, 99, 101, 228, 57, 243, 13, 53, 48, +120, 176, 137, 55, 191, 225, 145, 208, 199, 250, 217, 230, 214, +228, 124, 178, 15, 9, 245, 16, 248, 225, 149, 164, 56, 65, +211, 97, 159, 250, 118, 105, 154, 37, 120, 112, 20, 166, 88, +58, 127, 95, 214, 63, 123, 137, 183, 156, 197, 33, 128, 32, +105, 42, 91, 226, 173, 2, 130, 1, 0, 42, 30, 100, 99, +206, 7, 242, 167, 196, 120, 67, 223, 225, 206, 220, 32, 87, +56, 118, 110, 136, 5, 41, 215, 193, 39, 167, 88, 78, 237, +75, 13, 139, 131, 224, 7, 53, 89, 185, 198, 135, 118, 12, +159, 204, 192, 192, 14, 137, 224, 129, 169, 193, 183, 157, 31, +177, 220, 36, 106, 31, 197, 9, 71, 229, 3, 25, 121, 52, +15, 250, 27, 191, 97, 227, 16, 19, 0, 200, 162, 248, 206, +175, 176, 154, 241, 56, 203, 207, 155, 235, 80, 22, 61, 3, +242, 139, 4, 12, 167, 193, 72, 140, 159, 212, 79, 245, 197, +36, 124, 110, 78, 217, 105, 103, 152, 168, 24, 154, 65, 125, +101, 141, 205, 27, 9, 1, 175, 149, 92, 135, 56, 68, 137, +181, 15, 36, 129, 243, 222, 94, 198, 217, 79, 79, 142, 146, +94, 46, 225, 231, 14, 235, 53, 233, 172, 222, 166, 31, 180, +212, 155, 33, 144, 115, 120, 17, 211, 14, 238, 231, 191, 191, +11, 235, 182, 24, 149, 108, 189, 103, 174, 158, 166, 5, 10, +103, 216, 64, 63, 104, 194, 86, 56, 247, 44, 89, 248, 239, +131, 94, 235, 115, 168, 185, 170, 134, 39, 49, 146, 17, 179, +30, 43, 96, 14, 30, 160, 76, 121, 99, 49, 8, 187, 12, +44, 112, 192, 126, 175, 212, 13, 215, 49, 226, 67, 166, 71, +66, 255, 39, 25, 205, 73, 28, 134, 134, 54, 9, 195, 85, +42, 24, 21, 96, 237, 2, 130, 1, 0, 72, 170, 117, 219, +203, 232, 205, 121, 240, 13, 190, 214, 57, 0, 123, 28, 92, +53, 189, 77, 134, 144, 94, 37, 31, 6, 216, 245, 39, 35, +107, 53, 166, 42, 16, 240, 193, 213, 135, 202, 161, 198, 252, +32, 144, 27, 232, 11, 138, 232, 126, 134, 146, 217, 100, 92, +80, 246, 158, 239, 116, 11, 177, 204, 198, 191, 211, 30, 217, +105, 98, 24, 129, 167, 250, 65, 163, 161, 193, 69, 67, 1, +240, 131, 176, 34, 200, 61, 188, 117, 192, 229, 35, 232, 189, +28, 38, 45, 28, 186, 61, 229, 90, 33, 33, 233, 42, 62, +155, 54, 234, 117, 105, 124, 28, 33, 122, 207, 96, 237, 80, +65, 5, 9, 91, 149, 149, 119, 220, 241, 178, 117, 243, 129, +10, 119, 6, 199, 112, 73, 49, 80, 219, 145, 191, 38, 122, +101, 37, 125, 93, 68, 85, 172, 208, 89, 137, 208, 116, 68, +182, 158, 214, 88, 250, 82, 148, 27, 98, 139, 114, 107, 37, +247, 164, 44, 99, 182, 53, 125, 213, 13, 167, 83, 230, 116, +84, 229, 168, 65, 210, 186, 23, 62, 23, 196, 202, 30, 107, +247, 210, 62, 100, 73, 143, 49, 6, 124, 25, 105, 84, 95, +50, 4, 151, 102, 215, 202, 252, 120, 47, 151, 204, 64, 211, +89, 167, 169, 106, 144, 254, 115, 195, 117, 142, 99, 45, 235, +83, 155, 134, 57, 206, 119, 16, 54, 85, 99, 227, 110, 174, +140, 160, 114, 0, 152, 7, 7, 7, 7, 7, 7, 7}; + diff --git a/crypto/test/rsaperf/rsa17e4096.pem b/crypto/test/rsaperf/rsa17e4096.pem new file mode 100644 index 0000000..1b814c7 --- /dev/null +++ b/crypto/test/rsaperf/rsa17e4096.pem @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,0E7C75C1776F3DA1 + +4TXnbNznNMKwK84uGNMOxXLdjShkEExWCcbcbqBGm1HVANGLm6/WLpmt1a4KenlZ +ICD9HXuvgts+SwSpEFG7LSsAlpJBsDlLDEa1i1UnGpA2B5FCHh6CvYorlHsnJAPg +uGkuVA70iAgXTiyoPOn10Vb8J9IEHRCSm0g6G1tfltmjR3CyrOIwKsHwHuti7Y38 +qNV+UB/4pFrSgumKEeIF6iJgZvQrbrHpg7bQAqNv3XE4P7jgwABx2608PGu7CqHP +3MbmatEIzuGVy/tq5T7saVlvHceEfIFEyq8I1SpStdtDAg1zq+/fjZ7jV0lcIDEL +hdInb/27D4+5VdHJv40P9u7w2xJM1x6OPBbq5WSvTQ6V+qD7ynL4TEEeY5j7hWCf +FNiFpqEWGvtxe2JGRmztvdHpejLnzCcNyMU1vXMzHwGrEV9HFlAbuHot7sen6XqU +z/tuHjj8UPqf7mffUdT80OKwjMfP0rojrLmrpFr53YE762YKz4F1nHRi1q/h3S7H +U+0eEXpXr0LQ6emnhHSNvkoD4VRNxsm9MdOLLGxD+k7qNdPa4/0l3TV5qxJyvcoo +SAHTtUUxVzAEpL6X3skpXVG0/uDdBxMw2ZosPbGUBoiNDNpMOaqooYcwj+3QA/gD +bCkkcMYXcBXTPI3rqsSJ/niPSjW6p28PplMfBlmqqqTGfYbe4Q/ViY83SOGzIkN6 +RXb11YkgefDYbvzJT5Q7/JfcOsgmyzSsmSeHI22KjmE9iImib6UADw4pZxyNgd7s +DmQjH/TxGvfS5oib8vnySVHY8OHwdpP1jACAFAqr2XPTK3k4buosF4OJaZqWhj1t +ghk/xIv6AO2BTe0P65I3GPdMoIt/mlmT9onn7rBfodTRXQZ5YvwnZZy7uP/CtgtQ +sJLI8cBcypmDcVNqpumGNjMjxYt5vNRdsr/A1cMiICk5TwlexbZEjgeedxGQV//v +iP6C/xI5aR+EJjjnDOjAyJDSxBI79jgcQDpgXJfu/XpAkQSkCrlzxw7ld5GzXE+F +vKeIiJrExIBeSPm2F0B6rWdd+v5CScL6YLlT+PwX4cMbs9ARrD2boQj2tPF/oMpF +lGNxBmeFToZrYY9byZlitmopaxxagAOeSRd8/2Y8kuDLKNYjRFLyvPU9i7G7cIvS +PR6q6JV9Ifwc1HP+ARvc2iRrqAXXSDZn2tsmvSuFfpTWpO4LG3P6SBGPkNJZjeC/ +UO6gOfREPoyZRsIO3yWqAuPKqtHxbRbx1cFvtc0TqdSFSdcjmVrBgb9GWcORre/j +jOW+PidKkHabMKJ3tzquBCM53tnpBvFcGIA0TBgHBSSAHSLykTR+4zXZ5SIYpJ4a +dztQLBWXUd2azqs+rOrZOjNg/qUWSa6FbeXiXVdCH01DXi2u0Zl0WzW6RN+kJJ6R +Qq+MR/czG2McbOoxJv9E/2W3MOTs4STKuD+BdpiCa+QNGBF7kodEvsLcvxxAL4RQ +geQwddC0o4KvNh1OMSYm5/u7r+DzqMaE8wAUytswQx39kZVo3C0uT8enoQTZOR4n +fMA2WSfBmIbJOyyaUDZXXQZHVTYscuuI7PP5Fu4B53aqI3YiBrOGCPqVZkPss+47 +J9ZjHc67da8TIIBy0MOkbtVtdjC8rsscWKH+CM8S+OLnvb3ZrDlv5F/dhR8jXXJK +WC+zxE4aYBnLBLF+1TZoQpgKsgkZC9ySByQ2SSh6HjDBQMKosVEgd1uMaxbCN0kd +1LKT4N3gh248V0v7A6YAI05zzCckpXCrAZyppSOeiDUu+M5gAOxvN9mxgfcQctjs +V9pIrKqos6krGrNdipsD3FJaylvmIwwq/tUGvrWv3Whj6RKSIufNdo74Ap7Fm3DK +t2DbSii1j7dPMNDQZrgqnwl2PpnMw5nJPsRJYMp1b3F49cYGpSVX+YoRJg2l8AAD +hxdyc5x4R4BHYenavDLUGyEGH5XGc2vQkfq3jF0EWgWTcvGSwLxt1ORgg1MuU4eD +WPmlaDEq2Wj6FsKMJRecc9FYGIT5s0roRa5OoZyB4BoYsqnIBCE55VZwfuOCXRBz +ZG+CRkED5VkvVIZGCkmhPVdpkPivf4jwAlGv8KRbb94RbdCxa8yrPe6lF84LEsEh ++mIjpj+J67uwUnxclH3pqX06kUFI4Y21ysXjS0aupZGyjw90Dp2Wtmeiy7lyeUZP +8QAILAepTT/M/g6Tyd2P42zdHctMhSwKc/69bjMd7VZfTOBOwlK4vf3442Qhx9kq +hZJE9t6apKPAAea4rVO8Nc3Q/tiMzp46fJ1320pItL5nJAHSixWdSHmW7px3l5bc +QYCxfh3IpMd7YdwpoyWerGk+XHTrw9n99bt+dCnLHWnBOCHrNAJyVR4SdiOcPomO +xBHZ6nbwQlwvp0VYPMQHQ11Nh46HVFlw57USnASs9ff5gSORsqFb/7ECyePnGX8P +YeEW3jY27oD161+tjw0cJVL0WVTtuu7B3rQhntGMbBNB95DsJcbLSIFDKfdhaWlj +sbY34oGE/FRUt04x2GPstyU1scyQ4+6uguE42sTxyDt3IbFz8dSY06ZGfZIXLyfV +tUb+pK7zZZlcmpUqktouKFvj6ROHxrtryKoAlN9CKo+MhAtPZvSn8/T0EXM5xEEu +BwxANgmJfwEzn4dgGEGrYHpcNEP+UyGx26S96RpIbrUcukktXMe654YcuNjDqjcR +JzHqovS4+2UqcwcAoSVkEzD4qiq99ifkPhVrhzDRwqaIx07DbHRpYYRMyV0K38/K +tfUOlGXtqj1Cxul6wtQw7E7ex3AjoSdD8DmcG4EJx5h0vzflHa//zZeMO0JR3nGx +pa2Vw/nExlkw2OiHeS+FqQ4/hBZEEK3g0XXe0WvmnBldO9syp/b3VXuqfcANEAvK +DkK1/nYphQibiJgyWkg0UZAZ2OTy5pFAoHexbDbJwvUdesuzQBrdqG6fwSAiR5yp +4ZJsbMFNeXh4rYJgQo/m7qpOqFFRRq3G50HN9cLewTp71wwvraBhVDRKmDI9r7oy +W5TUy5BhLYsn6u+tPDnLyW5S8Lv08Gxkh8MQJsqB/KTdFnQzCMtV6D6bGwXl1txL +nD1jwtj03u7yTfIzNoVjeR/1u92oKqpOnEQ26x1MJ23SKEvMZrTF++tDAjdQNeBL +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa17e4096_1.h b/crypto/test/rsaperf/rsa17e4096_1.h new file mode 100644 index 0000000..065b56b --- /dev/null +++ b/crypto/test/rsaperf/rsa17e4096_1.h @@ -0,0 +1,189 @@ +/** + * @file rsa17e4096_1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa17e40961[] = { +48, 130, 9, 39, 2, 1, 0, 2, 130, 2, 1, 0, 197, +160, 253, 115, 243, 117, 56, 11, 204, 67, 240, 233, 51, 77, +144, 135, 19, 209, 3, 165, 124, 12, 202, 97, 94, 29, 56, +47, 247, 179, 169, 42, 52, 99, 195, 87, 223, 48, 148, 191, +72, 54, 189, 153, 243, 121, 56, 120, 154, 65, 175, 96, 227, +246, 83, 251, 173, 87, 152, 205, 82, 224, 4, 107, 186, 26, +203, 94, 149, 37, 176, 178, 137, 89, 169, 65, 241, 253, 52, +222, 10, 73, 9, 128, 29, 124, 116, 104, 172, 56, 17, 95, +85, 53, 9, 232, 43, 177, 78, 156, 89, 69, 133, 19, 213, +71, 201, 72, 146, 32, 100, 153, 216, 98, 179, 178, 246, 51, +210, 34, 217, 2, 178, 91, 92, 28, 103, 137, 191, 183, 185, +57, 186, 226, 92, 16, 226, 163, 31, 100, 25, 121, 189, 131, +33, 86, 48, 53, 137, 247, 236, 13, 42, 123, 207, 31, 93, +135, 67, 61, 225, 229, 40, 147, 89, 67, 205, 152, 230, 134, +117, 8, 63, 187, 148, 179, 93, 240, 226, 221, 110, 149, 76, +158, 149, 87, 128, 7, 72, 163, 179, 118, 76, 17, 252, 91, +14, 223, 26, 145, 205, 151, 204, 167, 145, 241, 161, 170, 68, +211, 135, 208, 142, 97, 218, 114, 62, 218, 30, 241, 141, 147, +215, 204, 75, 235, 222, 173, 11, 147, 160, 158, 0, 94, 19, +25, 239, 231, 160, 237, 25, 120, 236, 122, 244, 151, 135, 16, +215, 69, 236, 144, 61, 232, 200, 3, 223, 198, 11, 84, 59, +160, 42, 93, 37, 241, 91, 157, 217, 217, 235, 8, 106, 250, +239, 246, 193, 39, 100, 55, 233, 109, 67, 212, 69, 31, 243, +18, 106, 129, 92, 122, 173, 132, 95, 213, 95, 147, 132, 3, +76, 6, 210, 45, 37, 247, 10, 201, 1, 127, 135, 36, 106, +247, 241, 238, 28, 147, 29, 150, 199, 79, 135, 222, 141, 51, +139, 55, 126, 141, 242, 205, 34, 92, 28, 94, 240, 91, 208, +92, 191, 81, 253, 58, 217, 200, 64, 30, 3, 89, 227, 226, +64, 13, 103, 123, 30, 61, 109, 161, 90, 250, 42, 7, 108, +254, 86, 8, 193, 158, 201, 187, 41, 250, 176, 229, 84, 155, +110, 200, 176, 14, 190, 199, 146, 47, 250, 141, 85, 150, 70, +56, 93, 51, 9, 55, 30, 176, 34, 135, 75, 57, 52, 247, +56, 107, 117, 183, 132, 238, 249, 64, 117, 157, 250, 195, 179, +134, 170, 150, 199, 104, 209, 206, 144, 241, 195, 29, 178, 27, +128, 241, 141, 23, 74, 243, 243, 4, 69, 248, 56, 45, 11, +155, 181, 88, 133, 167, 181, 216, 135, 69, 83, 202, 188, 170, +247, 52, 27, 224, 106, 122, 15, 65, 198, 40, 30, 102, 118, +24, 180, 151, 56, 207, 196, 19, 212, 132, 136, 26, 207, 180, +215, 78, 167, 102, 107, 22, 62, 187, 166, 242, 223, 251, 204, +57, 150, 146, 91, 100, 16, 146, 98, 24, 199, 176, 213, 66, +167, 193, 170, 237, 2, 1, 17, 2, 130, 2, 0, 58, 32, +74, 139, 131, 215, 46, 154, 14, 230, 206, 98, 180, 188, 117, +205, 96, 46, 106, 123, 247, 79, 14, 88, 223, 114, 1, 119, +133, 22, 185, 72, 165, 255, 57, 116, 50, 149, 209, 101, 111, +151, 161, 45, 71, 156, 31, 171, 0, 49, 111, 209, 51, 253, +39, 194, 126, 70, 240, 180, 220, 35, 197, 16, 160, 37, 255, +148, 73, 252, 6, 203, 25, 86, 155, 49, 131, 104, 151, 20, +33, 36, 138, 82, 219, 126, 245, 15, 186, 46, 155, 178, 160, +151, 33, 8, 12, 217, 203, 211, 161, 201, 39, 35, 243, 111, +119, 111, 178, 129, 255, 120, 138, 239, 218, 127, 238, 15, 61, +206, 3, 151, 97, 162, 102, 98, 181, 10, 101, 144, 99, 167, +145, 81, 162, 155, 141, 243, 189, 240, 67, 186, 100, 234, 85, +25, 89, 121, 40, 148, 54, 94, 57, 171, 241, 159, 208, 54, +215, 138, 171, 217, 252, 224, 11, 50, 15, 75, 22, 160, 4, +77, 184, 100, 88, 233, 117, 251, 142, 4, 228, 74, 7, 121, +239, 176, 82, 212, 247, 63, 52, 200, 112, 185, 254, 237, 154, +246, 83, 27, 211, 14, 135, 124, 148, 86, 32, 125, 95, 137, +130, 76, 102, 28, 199, 199, 63, 169, 144, 161, 101, 224, 48, +105, 67, 129, 155, 216, 138, 239, 47, 61, 135, 163, 50, 203, +100, 173, 137, 175, 37, 156, 9, 81, 86, 255, 99, 245, 228, +246, 114, 193, 3, 38, 88, 241, 143, 247, 30, 58, 80, 233, +152, 189, 211, 186, 111, 113, 33, 238, 72, 191, 134, 175, 155, +148, 209, 163, 21, 226, 36, 176, 247, 195, 15, 128, 138, 210, +60, 61, 178, 141, 33, 203, 86, 34, 64, 197, 190, 243, 168, +244, 9, 146, 205, 81, 139, 178, 82, 151, 237, 177, 13, 173, +110, 247, 173, 206, 248, 62, 192, 166, 135, 5, 152, 201, 108, +98, 249, 181, 199, 155, 236, 31, 8, 71, 213, 142, 213, 89, +110, 192, 208, 34, 79, 36, 213, 71, 168, 50, 195, 69, 37, +210, 42, 63, 98, 253, 89, 117, 177, 171, 185, 119, 200, 205, +122, 69, 4, 26, 32, 101, 92, 203, 90, 205, 62, 71, 94, +153, 112, 69, 7, 80, 220, 181, 193, 43, 142, 124, 159, 32, +60, 127, 51, 217, 126, 148, 126, 7, 23, 35, 220, 121, 231, +11, 153, 161, 235, 101, 242, 120, 120, 220, 56, 83, 205, 113, +237, 185, 115, 163, 72, 71, 221, 237, 6, 44, 216, 49, 3, +122, 64, 173, 158, 187, 13, 95, 54, 180, 168, 21, 76, 21, +228, 12, 212, 153, 81, 144, 159, 253, 156, 145, 158, 68, 141, +96, 140, 169, 251, 198, 179, 157, 91, 109, 133, 2, 66, 253, +18, 230, 38, 146, 135, 208, 227, 216, 107, 172, 207, 105, 105, +57, 174, 65, 73, 0, 129, 218, 208, 106, 247, 190, 240, 126, +92, 195, 177, 21, 8, 125, 4, 134, 73, 205, 222, 231, 158, +144, 143, 221, 2, 130, 1, 1, 0, 242, 55, 106, 231, 197, +159, 183, 145, 136, 81, 47, 57, 184, 68, 63, 65, 116, 194, +176, 195, 26, 194, 159, 64, 79, 101, 189, 203, 47, 52, 221, +129, 122, 136, 70, 70, 52, 97, 69, 195, 251, 177, 164, 54, +50, 249, 79, 239, 4, 87, 111, 24, 241, 0, 106, 216, 122, +175, 167, 85, 180, 6, 184, 46, 76, 86, 64, 106, 75, 254, +192, 224, 141, 201, 191, 121, 86, 140, 33, 189, 248, 9, 58, +132, 50, 156, 105, 123, 90, 131, 174, 232, 30, 220, 119, 83, +206, 177, 99, 170, 126, 31, 194, 18, 62, 123, 223, 113, 60, +79, 188, 19, 214, 233, 149, 35, 127, 161, 84, 177, 77, 20, +130, 4, 87, 104, 167, 211, 207, 185, 184, 4, 167, 180, 57, +45, 87, 247, 85, 220, 105, 20, 18, 27, 151, 13, 67, 116, +148, 105, 136, 8, 171, 136, 7, 206, 107, 24, 22, 216, 46, +76, 65, 235, 106, 145, 149, 72, 198, 191, 214, 117, 201, 69, +33, 17, 215, 165, 182, 61, 246, 78, 173, 80, 158, 203, 155, +115, 206, 49, 193, 207, 247, 87, 182, 176, 100, 116, 226, 151, +145, 79, 132, 9, 149, 131, 217, 58, 140, 103, 88, 123, 64, +123, 184, 140, 48, 133, 117, 156, 97, 171, 51, 45, 1, 24, +14, 216, 92, 214, 4, 68, 103, 51, 59, 150, 74, 186, 107, +160, 162, 255, 229, 215, 84, 19, 200, 18, 136, 66, 187, 90, +178, 212, 210, 251, 2, 130, 1, 1, 0, 208, 224, 6, 114, +252, 127, 209, 223, 205, 191, 228, 176, 71, 209, 231, 162, 44, +73, 148, 160, 16, 211, 224, 246, 182, 225, 8, 113, 225, 54, +10, 95, 188, 192, 234, 84, 159, 214, 40, 105, 186, 219, 35, +93, 116, 54, 46, 126, 52, 87, 39, 30, 145, 71, 90, 139, +142, 148, 55, 180, 179, 51, 25, 95, 235, 246, 73, 46, 6, +135, 243, 108, 210, 243, 191, 219, 66, 153, 171, 70, 85, 108, +243, 168, 122, 140, 105, 177, 62, 250, 136, 219, 219, 208, 212, +163, 87, 43, 13, 197, 233, 38, 174, 152, 141, 54, 109, 152, +133, 243, 250, 61, 118, 92, 96, 11, 213, 63, 141, 224, 154, +45, 222, 84, 65, 84, 254, 20, 7, 63, 126, 142, 47, 211, +240, 3, 209, 36, 207, 221, 160, 214, 99, 237, 50, 75, 157, +125, 197, 167, 73, 187, 133, 217, 31, 114, 9, 50, 190, 1, +202, 183, 13, 52, 211, 172, 19, 145, 113, 63, 62, 15, 112, +47, 186, 115, 63, 240, 18, 160, 104, 216, 69, 14, 42, 178, +160, 170, 70, 46, 87, 104, 15, 149, 23, 3, 116, 153, 243, +42, 82, 2, 185, 148, 227, 82, 160, 35, 105, 76, 104, 22, +184, 64, 136, 150, 30, 190, 128, 177, 56, 249, 128, 111, 13, +105, 149, 229, 96, 127, 59, 105, 183, 160, 115, 138, 126, 30, +149, 81, 184, 44, 78, 171, 159, 162, 87, 112, 222, 24, 138, +110, 13, 1, 85, 55, 2, 130, 1, 1, 0, 156, 186, 114, +89, 188, 28, 13, 94, 43, 7, 90, 202, 254, 194, 191, 132, +180, 246, 114, 96, 32, 95, 208, 116, 232, 20, 167, 251, 241, +94, 113, 53, 169, 163, 120, 196, 3, 198, 120, 111, 192, 250, +121, 80, 63, 25, 202, 79, 93, 41, 132, 31, 50, 135, 204, +170, 49, 68, 123, 85, 146, 154, 239, 165, 124, 176, 71, 204, +79, 74, 124, 205, 136, 235, 244, 93, 146, 90, 172, 107, 220, +186, 173, 100, 153, 56, 8, 4, 133, 220, 188, 120, 19, 248, +16, 249, 254, 54, 139, 200, 171, 246, 110, 132, 70, 140, 99, +103, 99, 66, 166, 223, 169, 45, 186, 218, 187, 254, 250, 144, +215, 133, 189, 138, 86, 173, 33, 76, 209, 180, 104, 3, 3, +26, 67, 29, 87, 9, 115, 202, 218, 148, 132, 47, 248, 83, +224, 90, 126, 38, 42, 216, 110, 253, 170, 178, 189, 196, 75, +4, 90, 49, 87, 212, 144, 64, 21, 77, 53, 78, 244, 46, +24, 210, 96, 177, 49, 46, 253, 115, 99, 35, 217, 142, 132, +222, 25, 74, 238, 212, 230, 209, 220, 71, 208, 144, 65, 0, +86, 98, 18, 186, 251, 21, 66, 160, 155, 158, 90, 217, 117, +124, 237, 125, 59, 45, 136, 206, 211, 161, 108, 95, 183, 179, +181, 105, 235, 124, 240, 198, 183, 119, 142, 18, 23, 127, 93, +135, 175, 13, 150, 165, 148, 184, 129, 178, 114, 102, 88, 43, +45, 239, 100, 167, 211, 207, 2, 130, 1, 1, 0, 184, 77, +50, 221, 237, 218, 49, 167, 91, 48, 216, 215, 198, 230, 98, +248, 129, 110, 25, 186, 105, 51, 108, 36, 251, 183, 127, 236, +2, 243, 114, 144, 181, 155, 41, 29, 125, 249, 50, 183, 164, +223, 121, 142, 177, 213, 116, 81, 61, 61, 215, 57, 22, 198, +125, 17, 186, 10, 79, 69, 22, 150, 127, 205, 27, 126, 245, +70, 186, 119, 244, 231, 140, 245, 48, 208, 134, 15, 30, 167, +120, 141, 79, 118, 138, 63, 168, 141, 85, 175, 226, 43, 103, +154, 37, 8, 152, 53, 12, 39, 25, 4, 3, 119, 139, 168, +126, 209, 223, 155, 9, 249, 255, 6, 54, 161, 7, 116, 80, +2, 105, 236, 60, 164, 178, 29, 209, 32, 187, 25, 232, 35, +27, 36, 106, 93, 184, 137, 228, 150, 96, 189, 42, 254, 119, +172, 33, 141, 23, 207, 215, 165, 118, 25, 238, 145, 203, 225, +122, 122, 13, 56, 26, 182, 36, 46, 107, 158, 114, 251, 145, +28, 174, 72, 59, 26, 101, 151, 151, 246, 243, 25, 45, 223, +82, 217, 217, 14, 182, 101, 31, 242, 104, 26, 35, 93, 102, +226, 48, 233, 27, 47, 148, 176, 140, 87, 246, 181, 213, 97, +137, 4, 252, 237, 165, 177, 162, 168, 23, 50, 246, 9, 83, +52, 207, 153, 102, 36, 190, 142, 97, 153, 131, 231, 237, 122, +51, 11, 237, 41, 252, 219, 204, 241, 201, 22, 197, 159, 211, +6, 152, 66, 252, 106, 150, 123, 2, 130, 1, 0, 76, 198, +36, 19, 239, 90, 75, 91, 160, 117, 103, 61, 44, 99, 93, +87, 102, 167, 199, 222, 23, 228, 151, 169, 160, 32, 50, 28, +239, 92, 169, 217, 68, 134, 33, 207, 13, 191, 65, 108, 102, +65, 149, 9, 172, 39, 123, 188, 239, 91, 151, 94, 31, 164, +235, 43, 90, 141, 30, 125, 189, 254, 79, 245, 239, 7, 202, +70, 202, 205, 183, 9, 18, 138, 34, 153, 38, 230, 178, 93, +42, 145, 193, 218, 130, 100, 69, 10, 55, 136, 164, 234, 112, +87, 220, 195, 216, 71, 229, 173, 110, 196, 230, 41, 31, 138, +20, 136, 248, 61, 187, 162, 199, 215, 158, 106, 80, 203, 76, +242, 19, 194, 235, 71, 212, 16, 152, 19, 230, 148, 57, 145, +183, 110, 9, 70, 176, 213, 130, 248, 185, 120, 12, 173, 147, +187, 194, 65, 144, 30, 121, 189, 18, 98, 111, 138, 196, 48, +51, 0, 96, 70, 104, 41, 146, 223, 255, 211, 183, 180, 124, +138, 146, 143, 28, 242, 223, 48, 135, 118, 241, 241, 255, 70, +132, 64, 67, 126, 128, 215, 183, 225, 31, 80, 170, 122, 190, +116, 79, 133, 8, 70, 93, 162, 9, 60, 112, 48, 206, 213, +48, 175, 26, 127, 198, 227, 16, 130, 109, 246, 98, 250, 67, +8, 90, 234, 178, 42, 94, 185, 85, 113, 179, 29, 68, 63, +143, 222, 3, 219, 80, 129, 17, 94, 225, 221, 65, 34, 229, +62, 111, 162, 159, 113, 111, 64, 5, 5, 5, 5, 5}; + diff --git a/crypto/test/rsaperf/rsa17e4096_1.pem b/crypto/test/rsaperf/rsa17e4096_1.pem new file mode 100644 index 0000000..b4a081b --- /dev/null +++ b/crypto/test/rsaperf/rsa17e4096_1.pem @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,46DAD570A1917E7D + +bssleTS02xgzztUifrxMTHOxyiV/1qx4SlSpEnN5/a2OsRGzuklKMdOnEdjkVDnK +o4xcbdZIPOtb3ZAqLkNZzU4KgL7NGXnobXncgSh1YjVrO6EyLAB116MZu9FifNwM +o5HU7slnXvQW7zz9NeSlBU4FkMZ2JPEg5pCmQdkc55jr8AJeFC61lrmLz3xKiCFY ++0mdMZ5HtTYnZz7LWHa2d10lmtgCIOAAk3R3oZoccDIc5Tf7Y5ozX1o545hmTZO1 +8AYy4/Ihk5pn1NPA5wjvvbt4+2bHZ5t7uXCZaiBPZBrCVtmOmTkZ0k4maPXe2YoY +JKxjIjxPZFb1P6/51TcgA0ZdLvaaJ9pPiO4qOwfJne02p9BFggT/YJVb55zDeIh8 +V4O5PbR8WIeo3GSR81jLPdstu5tNaqH5dzvynZulwQtIFaZjFCOoCEI/IOtTnRNn +J3kvAQKH11gJftHOMqeM5Q8ANt4PqkSjsYAFUiZkLAon2JclcxO46E+zDugNfgqr +B4LluBY+hUZAdwqKhkssRzDf5r0CJbtMUDVglgb25j5enHiMBzye4oz/KquIxnb3 +NICLqsm5qgVAmU5q1ddoa7PRUs/dRXOkdxF7G+EzGORjHflhW6ACuFiTdDpYiMro +XGgQa8Vpkzgg5KmSRywWKlBDW88PWTlE05UCCoHwaO7TMS9n8UJO+bLFmD4ntt6M +0C82CJ0JnaELnVW/tFTB25AMrVTx8hhvYAGnJDcmL27HJShDsKp+YK+cysvjhu6C +ChcTooVA/B7dOvY+wdVwCYWbFNe1YfEnlYsexuavXjPoawn32t5AvXF+cZqeUCzF +sBvmOCsZDFUBVy8steeRso/MYyMm/MkmFhRmc4lwKIQbbaqOaaiegSzDClULQ3wE +QE0yZv+C+zUdq38o/duq0c3TRRS7j5rcE6H/wbbKp8S4Qc2NiyI8AVXLRDvmwlny +lVkXSUpXzmQf6fLe0zualxFUUWhf9VRZp8hqh+xFRZrJCgrWdAgqSUw/5QZMvF3Y +hFMAZihQH1ZU7lm8ktgBlQxQP3DXRMADFtINDcUDbasSZ5XIOAtHncu4ClVjX+E2 +c1wdsG8r2/nggjMpPHLn8XkeyAxrLw+pmMq9ugKxFhFcRWmvsFIO5YL2qXXTsBFQ +8geJEsBYqVw2Ncn97XwNG88+a0m+UTkGVwQebSyGXnDT7xgIqr3mi+eO102DzoBo +iRoQQGHhXMBErAjc+5fYuNXbY54+nhNRoydtR4YiNawd9QFhgZMhpcDuVAsnvxT/ +4P+EMVHzDsdIqlcs3AnYHQqhKn8BXd0cC9ECwqltt/VzWka+kQbUlxZZLLEFLaRc +o1+I7FS2eoBqJQispqmKX0tDYmgKkD1jLBZy9Ndh+dY8m3pIoOV0GCl6N1uK2z86 +LDAFNj2agO0/MrzpvMR0RtjwTU10pM3CvFYhBWcnLw0bv/2pJill+fcmWZpVpsM0 +xlZGutFJIWVmojOcW2EWvvrPWUL+ZNTkUh/3rOdtRAsWrSAG/ZKWqrJ6uz1seUUn +GueF4brfAS8eUGu33fjafwOhemvvXyxLzJte20z7u7eFol0ISn9VjQ9Mqt9sI6yK +L+eL1jQaI03xS0k/PhtIypJ3v+uxpjMZjgjuwR7atTe9YQcJ6xMIQLv25NdpSu5d +9c4xDJTFUG/ppDxYevoKNMetjRGtBfA+4qZmWxARIVLoHyGEl9gBWi8/AWI4fe5k +CR1WN2DJjg4z+kO0tmtcKaV0dXaY26NAIg4rtE5xm2llFN2F7znIjgFLPPv29GO3 +iLKq3LZg11P25yr/CQqhqCXBF46jxNHwmKSrwdJEyFmDUB4+a+UJu5+xu+yoZ6Rp +ma+WTVzxhlfdBQk3u2m9jKu5tzQn125wclGzxHBNnMg/tlOthHP2912T/Ezvlje9 +IMQB7Q/uj3BcyJ3+mszNJsoUxqCCpUksdru8zSnN7g9hUGrsdROnyfBbyRSM3SvQ +lpV7b7HhNT1eUOQSEz8hxJQyNOfYotKBZtMQHNRF2oW0c1wTBVqdtsXfukS6swFY +QtbZE9W07VFhHPLlmVw+Q8lzoMzS4Or8uE/ihvFhweuS0YI5W+N8y01wHE4JiPeP +uKavtqe/FR7yMrPzUOswz4NfJFOany2qTaFh31V6sWuwZsLjWGUN1vaokVSLAoGQ +jIKRt0FpCzGO1hZJQGbLGepDCsME9MvIT2WSl7cl08AzZKchQggKFAhfdYqhTrUv +geT9T7BDDcR9pzhJyCLKZSRFeXxJtZ2Fodp+WVH3LN9gmubfe/C2cHkBSleiWm+U +JXq/jyo1pVytoXK4IGRJKHx62yFhGQ0j93+qCQA360+leiveDGmFYHeOHRMxO56/ +YiWtQNmjBXwus8J1E0QGcxRR0Gl3o7qkbIa7+PaC9GGKQyMbuB19kEpO/p36hBoe +3Uk2O8m16gDQ4UnufXG7PienYKu7so86IriXRminUyXlYdUCL3+mXumRxZIXEQWT +L+mjXYXLHRbs6zf/TTYQTekSvr12j4ZjkmPIRM4oHFM/4qMpGA1Kv7hzjy6Wn+HX +QczHsFKZtHMI3Y8INrWdSEQGvQySx7AXft1WQwFbZMpo8QI7QNL5OPXzv0xQSm0a ++AoRJl+4RC7/dy6+YtwRd9aTGw6bVVJ/kwISjo1C7znUc7llpKwepXeJoKgS+X97 +shZ6Y0LjawlLT9fp+t5N0QhflDZfWX8yIpTJlIesHxxMGCLqLYpWoqnVxi6im5Qz +4fAwoQzNbmgQ3rzRErTbKDapS65Ypkm/DsMoHrYU52zXgEMatw8xxxWXSy2WPNk3 +ltkFVj43cVMwUvKIc6E/n8tRD+nvF9ycQw8L9LREJacwtu5OyL+vONiWVpRdz7A4 +a5+wU2XTwTLkmOSl4qvPQFyfa7jfNT9EOvBnA6aE1lCoDkkk1MQyJ17YDfJngkbR +hhEk2URQ3u6Z8aC9Qz0DRIH7m6vfR8Tou3kMqjAlkuZ7lV+Ojkc4da4rQErVPW9X +MDLl9q6yR3dKx9XRVNVz3IBN+2jXLg95WgSWj05fgjozN9MJZ4gX9rjB+k9V6ggt +X1hRfkt9qf0OiWTI7Zr35/p012yKqA123hDMvt72UMHNfvKS8Evu4Tvq19+RSpa0 +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa17e512.h b/crypto/test/rsaperf/rsa17e512.h new file mode 100644 index 0000000..f8342f1 --- /dev/null +++ b/crypto/test/rsaperf/rsa17e512.h @@ -0,0 +1,33 @@ +/** + * @file rsa17e512.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa17e512[] = { +48, 130, 1, 57, 2, 1, 0, 2, 65, 0, 194, 99, 87, +157, 182, 161, 87, 67, 100, 245, 97, 184, 19, 149, 38, 180, +213, 135, 111, 195, 210, 229, 118, 132, 48, 48, 229, 217, 82, +74, 9, 137, 109, 55, 216, 46, 66, 38, 41, 105, 80, 228, +74, 4, 236, 155, 76, 245, 71, 28, 167, 254, 135, 66, 150, +56, 46, 162, 63, 217, 148, 153, 71, 253, 2, 1, 17, 2, +64, 45, 189, 5, 142, 133, 83, 35, 151, 99, 12, 143, 118, +155, 50, 39, 57, 155, 167, 101, 151, 124, 234, 178, 121, 116, +192, 54, 21, 4, 77, 167, 227, 176, 184, 67, 62, 10, 7, +215, 212, 41, 41, 92, 241, 190, 60, 15, 47, 26, 159, 2, +163, 248, 13, 51, 29, 220, 17, 2, 205, 227, 214, 76, 113, +2, 33, 0, 224, 37, 242, 197, 138, 144, 12, 37, 157, 77, +16, 229, 67, 157, 96, 245, 124, 244, 94, 159, 142, 102, 217, +138, 69, 146, 191, 69, 152, 108, 28, 165, 2, 33, 0, 222, +2, 199, 161, 12, 244, 199, 254, 4, 167, 110, 28, 64, 126, +171, 119, 153, 4, 126, 38, 26, 163, 163, 111, 1, 199, 52, +168, 243, 222, 102, 121, 2, 33, 0, 184, 151, 184, 222, 234, +148, 190, 181, 144, 153, 209, 173, 191, 54, 79, 217, 57, 186, +47, 206, 177, 129, 224, 83, 192, 211, 52, 27, 50, 58, 234, +105, 2, 32, 91, 106, 142, 111, 125, 206, 52, 59, 107, 84, +0, 41, 192, 52, 40, 124, 138, 77, 36, 226, 131, 112, 142, +151, 30, 217, 142, 39, 115, 121, 177, 185, 2, 33, 0, 149, +56, 71, 153, 153, 182, 200, 86, 5, 225, 69, 48, 73, 108, +73, 112, 39, 175, 82, 25, 167, 216, 2, 77, 241, 217, 223, +11, 30, 250, 98, 90, 3, 3, 3}; + diff --git a/crypto/test/rsaperf/rsa17e512.pem b/crypto/test/rsaperf/rsa17e512.pem new file mode 100644 index 0000000..da70a82 --- /dev/null +++ b/crypto/test/rsaperf/rsa17e512.pem @@ -0,0 +1,12 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,7B66CDAAD1AA0CC2 + +xi+OjzM7BxrrIrO2r7dpF6BwP7ToaO/Q0gNosKF20S9ii2EGNQJ95XPv6zmCyYiE +PzDDRuQ7HAPDdFZzhyDATaz4cZHhhGLzWtepk+TCPPr+9rx+J2SwkVFhe7fFAWUo +mOIqRj+bxhr9jCPA/QRMEIjsCFLsRWvpHLnis9toha17RFn24FvRO3tOUZ0p08wE +znCjs79pbb9KaQ9wxHajEx6dlI8JoLRlAe86WFnNA0AVZRuPSLqNWQZJWKJruZ8R +p+W0lHRq2u19AOVa/0aNt6qC+FQc7J3nhZ6Vh9PMOXSn+UM3lGHjnYOBJh7EeYeD +WqjQAS2G3iW4P8/ZwQdEnRrUzcWnF0ThLgCqHXy4HKxkbvBCMplPJhVEjny2TJUg +Vhf0RcHAly756OrUbVveseIYObFZGEThBmHI8cBKukA= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa17e512_1.h b/crypto/test/rsaperf/rsa17e512_1.h new file mode 100644 index 0000000..cf8ee53 --- /dev/null +++ b/crypto/test/rsaperf/rsa17e512_1.h @@ -0,0 +1,33 @@ +/** + * @file rsa17e512_1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa17e5121[] = { +48, 130, 1, 57, 2, 1, 0, 2, 65, 0, 195, 175, 250, +96, 180, 62, 205, 52, 75, 109, 155, 164, 64, 129, 134, 189, +94, 180, 102, 84, 102, 174, 176, 191, 215, 214, 41, 29, 89, +251, 129, 29, 111, 135, 137, 194, 233, 21, 109, 210, 33, 110, +14, 1, 9, 158, 43, 18, 135, 148, 242, 54, 49, 146, 253, +157, 59, 85, 43, 5, 172, 62, 30, 177, 2, 1, 17, 2, +64, 23, 5, 164, 252, 81, 112, 204, 216, 249, 208, 168, 230, +37, 180, 226, 172, 221, 247, 27, 24, 253, 5, 126, 52, 175, +251, 19, 229, 85, 225, 90, 123, 186, 86, 162, 81, 234, 26, +75, 117, 63, 53, 245, 167, 194, 70, 7, 71, 40, 36, 211, +141, 182, 160, 25, 100, 212, 54, 238, 200, 70, 148, 212, 89, +2, 33, 0, 222, 78, 187, 107, 188, 2, 5, 83, 168, 126, +255, 32, 24, 103, 179, 210, 43, 50, 37, 189, 22, 29, 87, +73, 169, 239, 181, 131, 70, 101, 92, 51, 2, 33, 0, 225, +88, 106, 158, 231, 51, 231, 25, 223, 164, 102, 206, 253, 227, +57, 99, 135, 41, 198, 68, 139, 36, 206, 122, 133, 146, 135, +220, 13, 231, 181, 139, 2, 33, 0, 169, 255, 248, 187, 204, +1, 139, 154, 83, 172, 104, 190, 48, 199, 197, 190, 213, 188, +239, 174, 182, 142, 232, 101, 129, 243, 138, 205, 204, 107, 160, +219, 2, 32, 119, 76, 237, 38, 242, 223, 62, 28, 193, 177, +99, 154, 194, 165, 120, 188, 56, 127, 135, 21, 58, 155, 3, +230, 130, 243, 56, 221, 233, 62, 111, 43, 2, 33, 0, 183, +176, 102, 44, 52, 55, 249, 118, 90, 73, 230, 41, 88, 161, +238, 76, 42, 235, 32, 99, 97, 91, 73, 175, 225, 159, 99, +56, 155, 38, 210, 212, 3, 3, 3}; + diff --git a/crypto/test/rsaperf/rsa17e512_1.pem b/crypto/test/rsaperf/rsa17e512_1.pem new file mode 100644 index 0000000..d89a030 --- /dev/null +++ b/crypto/test/rsaperf/rsa17e512_1.pem @@ -0,0 +1,12 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,3F24C2CFAF1228FF + +SrG82OrZOr2/g4joBANVGyU35A2XM0lFwHjBiAwcCRVfcDosh4OjPXqoVybFkCde +WfVZSveBwXfLalW8LlJkUVlG9eKdMXpMPWCG94v+eevxX+QkY9rFjS1WncDhTT3y +fz+0vo2VdzJgsZpAyPsNXR21erJJUWn1YPznQjl0cHCBcQ1hmtra781+a8DL+u6D +QcDtTDcUhch/r8UIlD4guoqHRTFQqyD6erOtHHxEKs/6niHAGUUT37Oiabtp3Woq +i0KdN0HQi2PR8i+TV9o3/FZwwM9OPOvP7IIy+wqFIiT/bWgIisEBSGF2mY9Km1UG +rTtxgsap60h9M97juTFDFWuk59pE+wmc95l2dtXQQsJrarPWkfmPjG8pJvC+qmvX +9eBL/dmlpsEAgq5SNBHrZ+PTYgkB/Hr4niT2vRBU+S4= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa257e1024.h b/crypto/test/rsaperf/rsa257e1024.h new file mode 100644 index 0000000..73682d4 --- /dev/null +++ b/crypto/test/rsaperf/rsa257e1024.h @@ -0,0 +1,55 @@ +/** + * @file rsa257e1024.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa257e1024[] = { +48, 130, 2, 91, 2, 1, 0, 2, 129, 129, 0, 212, 143, +200, 247, 151, 67, 139, 66, 19, 140, 156, 51, 88, 34, 142, +167, 143, 87, 243, 76, 106, 24, 164, 70, 151, 132, 133, 26, +130, 159, 48, 244, 32, 159, 42, 154, 101, 15, 212, 4, 112, +54, 248, 161, 236, 252, 160, 246, 218, 48, 100, 167, 65, 8, +159, 173, 185, 245, 112, 159, 238, 127, 42, 58, 198, 63, 162, +109, 222, 8, 106, 32, 2, 221, 43, 146, 180, 239, 216, 180, +124, 63, 102, 240, 201, 247, 240, 37, 29, 75, 210, 69, 233, +249, 70, 26, 220, 112, 124, 141, 169, 55, 236, 216, 84, 49, +171, 177, 125, 161, 30, 128, 5, 178, 209, 212, 58, 94, 139, +232, 251, 114, 59, 228, 84, 248, 178, 247, 2, 2, 1, 1, +2, 129, 128, 31, 109, 233, 234, 213, 158, 104, 67, 139, 91, +131, 171, 243, 33, 255, 45, 177, 149, 120, 164, 179, 12, 155, +198, 179, 201, 225, 224, 15, 84, 76, 247, 69, 146, 14, 68, +166, 89, 255, 121, 47, 120, 176, 55, 209, 92, 35, 192, 227, +127, 175, 65, 146, 21, 50, 129, 72, 82, 28, 155, 34, 68, +155, 168, 203, 45, 11, 150, 131, 167, 177, 131, 95, 215, 110, +209, 210, 22, 117, 92, 105, 239, 92, 53, 56, 187, 8, 251, +12, 121, 208, 21, 253, 25, 112, 248, 169, 45, 200, 146, 71, +58, 207, 216, 79, 5, 240, 131, 237, 36, 14, 243, 188, 138, +16, 203, 153, 74, 105, 99, 129, 142, 209, 162, 150, 154, 250, +161, 2, 65, 0, 251, 240, 109, 14, 71, 184, 141, 241, 3, +121, 236, 153, 242, 76, 50, 145, 112, 107, 127, 162, 234, 107, +229, 19, 216, 102, 108, 44, 225, 247, 153, 181, 102, 105, 122, +126, 136, 49, 221, 159, 170, 38, 26, 207, 218, 117, 109, 166, +43, 245, 234, 196, 45, 107, 60, 86, 254, 188, 42, 134, 21, +72, 174, 127, 2, 65, 0, 215, 252, 224, 67, 243, 124, 171, +162, 72, 9, 209, 123, 47, 11, 194, 76, 252, 1, 18, 162, +143, 6, 226, 138, 85, 146, 156, 172, 189, 78, 223, 130, 226, +229, 147, 224, 251, 234, 212, 230, 201, 126, 87, 236, 34, 183, +210, 118, 229, 90, 130, 242, 114, 191, 107, 220, 205, 31, 81, +173, 149, 246, 47, 137, 2, 64, 122, 137, 219, 100, 148, 112, +172, 162, 12, 165, 226, 164, 134, 200, 108, 68, 191, 37, 87, +250, 145, 228, 202, 16, 160, 9, 248, 217, 17, 68, 161, 108, +38, 218, 166, 41, 158, 225, 119, 191, 54, 221, 189, 90, 35, +135, 206, 187, 104, 15, 4, 157, 45, 0, 92, 26, 96, 1, +222, 228, 147, 208, 172, 135, 2, 64, 101, 176, 213, 42, 243, +34, 202, 85, 94, 173, 246, 13, 44, 16, 126, 88, 11, 17, +112, 94, 119, 35, 29, 245, 109, 5, 70, 198, 222, 155, 171, +248, 228, 90, 40, 188, 154, 119, 135, 25, 251, 65, 118, 24, +131, 228, 253, 124, 181, 178, 21, 206, 201, 115, 6, 244, 104, +139, 66, 88, 179, 46, 46, 73, 2, 65, 0, 165, 22, 179, +165, 48, 229, 209, 42, 159, 81, 132, 135, 43, 23, 139, 54, +174, 21, 48, 61, 201, 165, 213, 19, 216, 26, 118, 166, 42, +68, 136, 96, 80, 15, 217, 69, 20, 137, 212, 201, 35, 166, +41, 113, 30, 175, 139, 207, 66, 68, 20, 16, 148, 64, 211, +99, 188, 83, 240, 206, 135, 69, 165, 198, 1}; + diff --git a/crypto/test/rsaperf/rsa257e1024.pem b/crypto/test/rsaperf/rsa257e1024.pem new file mode 100644 index 0000000..5c06e2a --- /dev/null +++ b/crypto/test/rsaperf/rsa257e1024.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,A02253BBC6E665CD + +xMSK6SBbphWAUHW0tIfcM81O/PEcmpn3LDR1ceIDK8G7qtvRK8YC1rM6in//I6Lv +IMJf2tURvrxDCbc/cZtHUQ3hS8Y+ZsxdhVjdoJwUu+uJWniYnEKOUSEHOygGRzIt +hLNAwaCha3+rMn17DLU5hn/QHPMSWiF7im95b51UhYRHlWp3l4gsLUtjSaoHetk7 +NgIuI0vlNU8TTCWAripyyTvFIDy3ffDM8lYmd7Mo4hYzFc9OfYL+rrfAcvA7r++i +g01+3C9Hi9SVwmzUJCIphEdRSe76XTlButu6iMk+YnprenLZRig529k66SzOi77g +PcdcHxBT0nzRTzb6qnLZ86b90D6YgvIQnxRLCrxvR1Dbah33+wF1juJ/JRuWutn+ +yaNt1x2CKgyU1LX/WVoRedGG4SzJlt1nZ1pI5AbTgroJjZdrqwY2gaezdbdrKK9P +8qnI9AXnFZg/qgAz64345xP93YCG0+v6EA8rXGBq4JsCTij8kB9YExGSIKbq4SOf +5Mw71YWQpdihJHosNdE5621rdgcFToL7YTCeEaUNpHqjSdJy8PIYDzbrpPvbh8Ag +q2udLLYzN3ToMXR5SzudoS8XEbZlrEIxlS7z3+OekctkHr3ovsQbKkuAglGLUmCE +O+pNdzhDDghFgUUxfKM83YGpSsZnKJpEerytrAc613ey2IblabgZIX9EYDPC2kTZ +DpQ/jEakALMKj9i/g9ZAfhu9XIqwVoos/6TC8w/ZryGNiR8q7DjlqznPaa17bWg0 +4nMv0h3ejliSpfxKmI0h3Hi7o8f74o2Vh5jpHLtHcF4= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa257e1024_1.h b/crypto/test/rsaperf/rsa257e1024_1.h new file mode 100644 index 0000000..3ab2a9b --- /dev/null +++ b/crypto/test/rsaperf/rsa257e1024_1.h @@ -0,0 +1,55 @@ +/** + * @file rsa257e1024_1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa257e10241[] = { +48, 130, 2, 90, 2, 1, 0, 2, 129, 129, 0, 165, 131, +88, 41, 106, 76, 237, 137, 222, 172, 97, 213, 231, 163, 239, +2, 208, 126, 94, 20, 60, 43, 124, 29, 226, 54, 6, 50, +82, 64, 52, 221, 122, 177, 123, 203, 161, 17, 62, 124, 192, +176, 110, 28, 17, 135, 80, 76, 113, 135, 138, 217, 224, 111, +219, 20, 115, 34, 172, 75, 147, 12, 125, 145, 150, 25, 59, +232, 19, 29, 4, 49, 82, 227, 230, 246, 213, 170, 1, 254, +111, 98, 29, 194, 95, 205, 177, 238, 219, 95, 58, 78, 75, +40, 169, 177, 253, 125, 166, 171, 6, 105, 27, 163, 252, 106, +101, 134, 82, 19, 54, 120, 24, 125, 232, 158, 75, 132, 242, +44, 65, 164, 245, 162, 244, 109, 58, 31, 2, 2, 1, 1, +2, 129, 128, 40, 64, 80, 181, 103, 12, 187, 66, 229, 247, +30, 195, 245, 24, 109, 108, 195, 35, 182, 65, 175, 1, 156, +49, 26, 159, 144, 242, 86, 189, 238, 249, 25, 90, 249, 191, +119, 91, 90, 103, 13, 253, 21, 204, 14, 57, 79, 202, 222, +216, 190, 167, 137, 193, 141, 111, 15, 12, 234, 38, 77, 25, +115, 52, 114, 6, 22, 114, 51, 220, 148, 243, 48, 183, 76, +29, 159, 199, 211, 249, 210, 234, 190, 108, 250, 125, 64, 136, +87, 176, 237, 201, 76, 113, 247, 197, 245, 177, 155, 195, 224, +202, 255, 223, 77, 100, 194, 11, 209, 64, 113, 192, 84, 156, +102, 37, 36, 47, 234, 11, 252, 78, 244, 175, 179, 136, 49, +177, 2, 65, 0, 218, 11, 93, 193, 129, 44, 237, 64, 2, +101, 5, 243, 79, 9, 127, 168, 213, 148, 14, 163, 56, 229, +130, 73, 248, 182, 56, 234, 213, 163, 126, 90, 68, 231, 254, +181, 191, 82, 247, 32, 11, 141, 123, 90, 226, 76, 76, 76, +201, 232, 39, 164, 217, 72, 92, 237, 234, 18, 96, 163, 25, +243, 68, 47, 2, 65, 0, 194, 83, 11, 17, 123, 37, 145, +177, 64, 126, 211, 8, 175, 250, 45, 31, 31, 252, 129, 29, +127, 26, 101, 198, 42, 51, 199, 41, 196, 100, 193, 232, 44, +177, 23, 17, 92, 233, 239, 202, 231, 222, 87, 132, 15, 60, +229, 69, 152, 141, 133, 102, 221, 111, 94, 27, 100, 180, 80, +213, 78, 65, 189, 17, 2, 64, 110, 75, 122, 34, 33, 119, +89, 33, 95, 215, 117, 143, 254, 36, 174, 37, 150, 222, 81, +29, 197, 31, 108, 188, 211, 121, 15, 215, 105, 19, 242, 55, +159, 94, 112, 231, 99, 196, 93, 33, 36, 185, 31, 132, 162, +72, 118, 72, 181, 210, 18, 15, 166, 176, 15, 33, 175, 46, +38, 235, 231, 70, 66, 93, 2, 64, 33, 69, 0, 230, 27, +15, 101, 164, 210, 67, 136, 188, 193, 125, 130, 63, 26, 101, +1, 47, 225, 246, 146, 235, 36, 28, 201, 113, 188, 5, 76, +7, 223, 206, 161, 85, 166, 81, 227, 83, 140, 77, 233, 33, +145, 13, 105, 253, 248, 64, 18, 218, 211, 59, 232, 68, 112, +222, 31, 196, 228, 142, 189, 193, 2, 64, 52, 34, 239, 191, +226, 102, 250, 185, 15, 206, 135, 125, 224, 105, 155, 157, 73, +37, 187, 111, 79, 141, 36, 69, 2, 237, 91, 144, 18, 89, +204, 15, 128, 15, 191, 32, 119, 191, 167, 116, 66, 33, 169, +1, 89, 157, 56, 184, 61, 34, 18, 101, 128, 106, 142, 242, +3, 221, 101, 168, 119, 231, 250, 45, 2, 2}; + diff --git a/crypto/test/rsaperf/rsa257e1024_1.pem b/crypto/test/rsaperf/rsa257e1024_1.pem new file mode 100644 index 0000000..1168725 --- /dev/null +++ b/crypto/test/rsaperf/rsa257e1024_1.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,3401E0146D7A3394 + +3BKinfvvIoqRSI3vaXfxJfUkfpTGryLWaSMqTRva66xq5jTVkPReR9pQnOZic8J7 +FtQOBXOLAF5K4VO8q7wb+VNcp8A4XzJEQ0yINLQ8piwvGgM7kjmUn+zqZO/P49Y7 +IzmctuYJDxNbTs8HgW84pmBFi9fdX44d+XwmkzfvBWVSPpSazgZtKvNkkJUeaENA +9rXd/LhuFfmHnQXfT7Y4CHZyLcKXtQysQW9qvy3eZfKvsEUt0hPbF1SY9WeMQF+H +B1c6OXGGOmnSkBb+H1lnTg0Yz2ajFplu60dXneCBcpWk/dGBagH9NobKAyMdhCQF +Ez+YXRA6vmSoi+EaE0IpvYufywlbZReAU5GLcIPE1UJYgPNFXQY1h1pra06cJ0Rc +84dv54U5WpcRckZqYBXGWjzgWKmGbOHyPzJ4nS0G7KCnxFhqWMsgKrSn5pfIU1l6 +U0UjnTxznp0xEOHdVZ+ASiPXIsFmkmka50ghdKdXnwfzJCpdtbKLtXv99uQ4qbvY +ST+G+ucEFNLA056bemyGhotpgg8mG2omtC2bIW6s0tbzm72rG+zFSWl/azdGR1H5 +xkiOCWN+DJUXM3C4y1kcR7q467quq4DEgiaqt8OW3SnrZEWnFae3LvEOF5VX6lHv +Ymhu5EzAkCpZBKRBZ2tcw0NKRruXTgZp3YFc2Ewo7G2h1Eb+7xRyjFylSO9MuGIP +dHftJrTqhHFn8JZkA63XzfntKoFPvOu3mLDjqdSDaNB6HZTqLmp3XCTA94vvgqyQ +lxGxezdZsrTleJ4v8T15iv9xqW/2ngxVZ8qXvhsqwJk= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa257e2048.h b/crypto/test/rsaperf/rsa257e2048.h new file mode 100644 index 0000000..1e4dd7e --- /dev/null +++ b/crypto/test/rsaperf/rsa257e2048.h @@ -0,0 +1,100 @@ +/** + * @file rsa257e2048.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa257e2048[] = { +48, 130, 4, 162, 2, 1, 0, 2, 130, 1, 1, 0, 189, +78, 164, 81, 69, 48, 115, 72, 80, 1, 174, 78, 43, 232, +38, 210, 235, 65, 125, 196, 88, 143, 61, 26, 66, 173, 9, +183, 41, 70, 34, 146, 209, 151, 115, 55, 208, 184, 0, 172, +220, 58, 203, 75, 137, 80, 91, 226, 98, 41, 68, 13, 70, +147, 32, 197, 229, 118, 67, 215, 73, 167, 210, 56, 55, 237, +183, 201, 248, 102, 90, 159, 50, 114, 129, 205, 104, 117, 65, +237, 6, 39, 247, 37, 247, 43, 251, 165, 239, 191, 155, 254, +39, 28, 84, 236, 1, 209, 47, 63, 158, 110, 81, 138, 64, +48, 4, 67, 102, 241, 88, 184, 99, 2, 78, 229, 4, 12, +56, 186, 61, 112, 48, 115, 219, 52, 39, 20, 188, 191, 180, +237, 38, 24, 132, 25, 54, 170, 194, 202, 52, 130, 131, 164, +206, 160, 187, 122, 197, 16, 130, 46, 139, 48, 24, 151, 88, +3, 15, 106, 178, 53, 220, 32, 154, 106, 233, 32, 170, 230, +187, 106, 255, 115, 240, 99, 162, 149, 244, 70, 115, 179, 135, +234, 104, 35, 193, 10, 12, 42, 80, 86, 236, 161, 97, 144, +39, 34, 207, 120, 53, 130, 25, 156, 190, 212, 68, 170, 201, +37, 200, 183, 154, 50, 124, 65, 177, 83, 72, 135, 246, 177, +53, 238, 120, 144, 60, 137, 194, 96, 186, 116, 16, 158, 139, +103, 89, 92, 226, 160, 90, 42, 110, 121, 42, 157, 188, 124, +221, 81, 172, 230, 194, 255, 216, 133, 2, 2, 1, 1, 2, +130, 1, 0, 21, 233, 249, 158, 210, 247, 105, 251, 171, 160, +145, 112, 37, 116, 197, 189, 69, 145, 75, 18, 126, 203, 217, +128, 76, 242, 169, 55, 209, 58, 171, 216, 183, 36, 53, 110, +78, 51, 46, 229, 49, 102, 110, 177, 85, 223, 55, 118, 24, +207, 124, 44, 94, 149, 4, 10, 244, 118, 8, 89, 234, 228, +92, 81, 182, 201, 23, 4, 179, 233, 251, 12, 243, 41, 164, +240, 174, 53, 106, 254, 77, 41, 250, 253, 171, 205, 142, 239, +153, 3, 128, 223, 233, 34, 104, 117, 247, 62, 208, 109, 55, +113, 224, 25, 183, 62, 86, 40, 172, 138, 2, 13, 96, 33, +99, 71, 213, 99, 8, 143, 21, 142, 59, 102, 16, 168, 166, +227, 146, 49, 189, 201, 61, 148, 137, 203, 184, 99, 168, 109, +227, 22, 48, 159, 131, 174, 69, 13, 168, 121, 195, 237, 113, +161, 215, 103, 235, 123, 55, 180, 120, 46, 52, 219, 249, 232, +37, 184, 253, 72, 46, 206, 63, 174, 29, 174, 151, 36, 104, +0, 178, 99, 121, 29, 175, 227, 104, 83, 126, 94, 196, 85, +254, 168, 146, 95, 26, 98, 159, 40, 108, 116, 153, 49, 242, +250, 100, 121, 213, 103, 46, 204, 103, 5, 97, 200, 238, 181, +1, 60, 25, 64, 177, 241, 94, 105, 74, 26, 226, 138, 135, +75, 31, 38, 167, 63, 209, 64, 137, 136, 21, 250, 168, 57, +28, 181, 2, 142, 176, 82, 223, 75, 44, 152, 35, 233, 2, +129, 129, 0, 217, 156, 236, 36, 190, 79, 114, 223, 77, 77, +19, 72, 138, 251, 72, 217, 113, 232, 5, 233, 4, 57, 206, +114, 6, 176, 212, 248, 76, 207, 85, 165, 11, 150, 72, 118, +217, 168, 198, 33, 181, 222, 162, 228, 219, 10, 222, 56, 133, +185, 190, 152, 218, 203, 206, 191, 76, 144, 59, 205, 15, 32, +161, 103, 168, 83, 134, 84, 229, 4, 149, 206, 96, 101, 193, +125, 77, 181, 133, 76, 91, 144, 245, 97, 150, 158, 114, 16, +154, 123, 116, 32, 8, 113, 17, 137, 166, 211, 83, 136, 152, +205, 237, 58, 183, 20, 235, 175, 67, 25, 23, 126, 254, 42, +65, 254, 12, 105, 247, 89, 168, 203, 239, 247, 190, 175, 170, +125, 2, 129, 129, 0, 222, 179, 120, 243, 51, 139, 207, 247, +21, 153, 131, 187, 44, 251, 43, 49, 112, 142, 28, 51, 109, +240, 152, 67, 0, 157, 155, 216, 121, 196, 76, 185, 100, 203, +147, 24, 226, 8, 169, 126, 53, 98, 192, 107, 219, 225, 37, +30, 3, 49, 215, 206, 76, 224, 78, 253, 121, 149, 70, 254, +0, 92, 103, 14, 215, 108, 36, 220, 210, 90, 102, 149, 196, +240, 218, 249, 161, 18, 244, 33, 174, 59, 226, 142, 94, 151, +6, 154, 200, 50, 130, 191, 106, 38, 198, 179, 226, 176, 109, +35, 171, 73, 15, 75, 74, 72, 158, 103, 234, 164, 67, 2, +59, 44, 45, 130, 253, 86, 121, 67, 129, 220, 64, 226, 98, +207, 60, 169, 2, 129, 129, 0, 209, 254, 6, 188, 219, 129, +117, 210, 128, 98, 72, 101, 224, 194, 171, 230, 191, 153, 44, +141, 46, 233, 22, 231, 142, 236, 97, 238, 155, 205, 13, 233, +249, 64, 85, 221, 69, 149, 234, 6, 161, 142, 31, 174, 6, +44, 90, 235, 213, 182, 58, 105, 170, 75, 37, 36, 45, 253, +188, 50, 116, 51, 104, 243, 119, 153, 80, 209, 108, 112, 1, +30, 206, 147, 255, 113, 241, 86, 130, 159, 89, 91, 18, 163, +230, 3, 123, 5, 16, 151, 1, 125, 138, 162, 230, 23, 66, +90, 94, 141, 198, 65, 60, 148, 77, 15, 53, 28, 172, 83, +250, 200, 61, 250, 244, 249, 34, 227, 195, 219, 0, 133, 11, +108, 148, 38, 7, 33, 2, 129, 128, 33, 203, 139, 225, 43, +174, 158, 16, 147, 182, 172, 101, 30, 187, 136, 12, 123, 169, +252, 79, 134, 57, 109, 196, 112, 167, 91, 98, 151, 244, 242, +189, 128, 218, 41, 63, 138, 228, 109, 100, 213, 76, 190, 145, +220, 162, 169, 253, 148, 231, 176, 48, 61, 120, 179, 85, 72, +61, 128, 80, 97, 172, 103, 75, 246, 218, 158, 254, 165, 102, +95, 65, 143, 113, 64, 27, 235, 158, 68, 236, 53, 85, 201, +185, 246, 114, 143, 114, 34, 93, 84, 150, 146, 153, 78, 246, +113, 23, 200, 215, 151, 128, 160, 179, 196, 140, 131, 158, 54, +136, 125, 183, 159, 100, 86, 152, 92, 59, 240, 136, 192, 8, +133, 93, 31, 237, 164, 153, 2, 129, 128, 96, 115, 238, 34, +212, 252, 91, 131, 202, 94, 176, 197, 17, 206, 185, 171, 100, +159, 35, 239, 242, 1, 206, 81, 130, 157, 169, 213, 4, 32, +79, 219, 71, 85, 122, 125, 210, 160, 127, 80, 40, 168, 156, +181, 81, 20, 174, 70, 103, 30, 173, 119, 16, 234, 114, 155, +18, 86, 221, 231, 212, 196, 220, 69, 69, 11, 211, 45, 148, +154, 105, 230, 230, 126, 37, 182, 118, 36, 30, 19, 230, 45, +249, 190, 206, 60, 106, 127, 187, 220, 204, 175, 169, 226, 32, +160, 86, 216, 231, 8, 205, 62, 127, 154, 154, 135, 173, 229, +219, 244, 170, 53, 68, 137, 196, 189, 212, 117, 194, 44, 211, +3, 0, 220, 237, 250, 60, 229, 2, 2}; + diff --git a/crypto/test/rsaperf/rsa257e2048.pem b/crypto/test/rsaperf/rsa257e2048.pem new file mode 100644 index 0000000..8f8dece --- /dev/null +++ b/crypto/test/rsaperf/rsa257e2048.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,4E2CA2DCEF526B45 + +rB/GVln+Ffhuzo/lzXq1AXRE6/LdNnTZg2FBx7sXnxov9OIL9tQOkg1xkhsDMx5G +9LBxB3ElSuvkYNQagHuWe2VAgHtbva+XCisTxnaR+/aS1jPY8Lji6wLG1PXYZt2F +EKVGZoPEvu7lu5mFw45pC8i7kzYwSP6tAyCDSrVQXLd3c/FNwCFWr3j4XrMnta6E +yue1vuW+wA1QErnd3K1MTKiDt3ojWqXQgbDMrxiEmkM+2oqZ5QfcuW9rbQSEagov +bylBtrD4rSnWmdocCVtpp+3ppLFn1zFu6PE6ZiHUwwxhUr5SqFuGI2LMMKIp3ATS +bf4ynq2Wd9VzESwu7pK9s2vRW6wQHTX/ge1iJQhvBS4RD01iN423uWKWfX6D0XuW +0lP7DgDE25TZgp04rjDLykfOfBA6NfC4V3E0xmN6jBOMoPFiqiD/fO80gbujHoyg +lt4fXSto+nzknjNgPXxhTS4UyjVAVk5oGMjGxE6z6RMJ8JOl/0eBEbfFhDxdkDoT +RhcbBdORvqchZml8XPeOtniF9KtvY5jux0gV2ryi0EXdCI1zuxpfyhDJNZUvybPh +pq0TxRB7EZ2KY1i1Wsz3VSr+w4bmvUHuXV9xFXpskEMdANwPhz5f1KraFhMZahJx +8+LGBr0d4eqs4gbvVWJIJUxju7uo/lmIqNl29FwxzxjMDkiLonoQOPAOEuH2NdAB +Qfdwf+kC6+s6c2zPZchpKdsxvR5pRW/WbDCGH9NcskLqKIl+HmCyKl9zvGx5IRGw +IklXaxO1qVjDhrCK0nlvlA3sw6q2NhFlZlGddYTa1zeXTS7qV/SJDp+ChXneYgbG +ytBYTrdFXlRL6ggjRDL3J+rOFKcPrUSgpnoVOnC5Gb6E07KJQNMfggwrf/KOPc5d +Xn8tfrp7Pe/ipvr0yWK+U1ZXJCTAeMVTKLYy9mVZ26pmPHRRpjo498gmWLPODh84 +e8iAYdCBSsn6sSdnOpBseyvFwenjIf4lR5jNveJXJkg3t89D7FiOtrsVtUZWKIDL +F6wwuEIyGTzsK5fVhWF3fvGpKKOgp6d8WxitSqDEOLS0k0kBSUr/4qMcqJoGQaXP +H408SIoD3yukfNMZI8W0LeHUHYklP6iGigdPh7ZiyuSb4UEBKAWOQGFyz1uFACnB +8BGQUPr25yDlcgDCwI0pR1sn2Tgsx//gbNIUYF8xFs7IKj0HXaKmrQG3pIniW6Ax +jLcBqAceVZDUSFvJFk+BImeZ9ALCz7js1CX/kaOMlgpN5lVM8l0YMU7cF2NoGmvj +dTmeDuvbGJenb5MJbYaq3AqmpjSBT5kKWnwOe/cvNDAOzW8BCc0kbwi6hG8hwMwR +oPMWA3dVYOgupKxygkINXJE9lV2OwZiPvwpt/6cV/7GV+EHTJqLxnVMONsfBTE4C +tndOZrznU4t4NYw6rhMLjQuULHLzAKs4wC12YA4Wuh9I6TsTBeFrlCNo8WWsp7lV +UIxX7KiRFR3uLp6u82BQ0JbGT9h0/yc46+a2mLsFpckvGMGD9h+vuwPIjcWbL9Ku +qUxrSvticjJh92nLDoIf2l0Uwoe5fAK8tHP3BSQVUgSs+s59QG4ojQ== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa257e2048_1.h b/crypto/test/rsaperf/rsa257e2048_1.h new file mode 100644 index 0000000..8c327d3 --- /dev/null +++ b/crypto/test/rsaperf/rsa257e2048_1.h @@ -0,0 +1,100 @@ +/** + * @file rsa257e2048_1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa257e20481[] = { +48, 130, 4, 163, 2, 1, 0, 2, 130, 1, 1, 0, 219, +164, 125, 95, 154, 95, 57, 95, 156, 142, 157, 205, 173, 99, +130, 195, 197, 105, 192, 30, 210, 110, 193, 44, 160, 91, 34, +30, 142, 59, 119, 72, 153, 8, 197, 217, 171, 7, 27, 215, +101, 179, 182, 12, 232, 197, 68, 11, 147, 152, 172, 239, 198, +193, 231, 84, 139, 185, 191, 237, 155, 143, 191, 126, 13, 19, +171, 143, 112, 181, 83, 59, 151, 189, 187, 50, 60, 136, 180, +134, 158, 43, 138, 77, 28, 43, 52, 40, 32, 117, 226, 158, +168, 217, 248, 5, 100, 46, 207, 34, 211, 56, 169, 128, 103, +52, 159, 164, 194, 44, 178, 232, 0, 53, 252, 108, 63, 104, +169, 199, 151, 153, 39, 206, 28, 202, 111, 159, 131, 80, 136, +114, 45, 143, 111, 25, 184, 79, 227, 209, 255, 9, 189, 183, +245, 217, 113, 61, 59, 219, 101, 13, 30, 254, 232, 171, 11, +171, 121, 100, 13, 253, 2, 119, 209, 235, 101, 252, 184, 122, +27, 74, 122, 216, 55, 124, 137, 162, 157, 105, 183, 124, 88, +65, 152, 116, 202, 127, 57, 190, 15, 239, 122, 112, 160, 161, +240, 178, 135, 127, 145, 44, 96, 228, 139, 56, 96, 211, 211, +199, 9, 184, 161, 254, 157, 37, 23, 25, 215, 27, 215, 13, +73, 222, 56, 126, 18, 50, 99, 137, 98, 165, 70, 116, 32, +244, 8, 39, 83, 195, 181, 159, 208, 215, 150, 159, 11, 249, +168, 183, 182, 94, 63, 62, 191, 247, 2, 2, 1, 1, 2, +130, 1, 0, 10, 96, 181, 206, 222, 152, 126, 22, 5, 67, +55, 105, 88, 42, 105, 92, 199, 222, 110, 210, 163, 160, 196, +174, 38, 153, 39, 45, 251, 231, 197, 190, 33, 33, 36, 207, +240, 226, 188, 185, 235, 85, 85, 113, 189, 77, 50, 190, 96, +123, 48, 113, 55, 127, 33, 33, 6, 44, 199, 83, 59, 37, +208, 68, 254, 196, 151, 248, 249, 95, 58, 147, 137, 59, 159, +175, 32, 153, 226, 27, 180, 167, 105, 74, 166, 211, 203, 27, +239, 227, 106, 231, 49, 172, 24, 98, 40, 115, 123, 197, 42, +217, 250, 161, 227, 2, 51, 168, 4, 13, 54, 33, 186, 217, +254, 177, 76, 144, 211, 204, 25, 60, 44, 36, 235, 4, 222, +108, 232, 244, 215, 183, 196, 234, 70, 0, 27, 172, 17, 103, +8, 122, 30, 184, 113, 91, 147, 174, 0, 106, 237, 236, 77, +153, 249, 236, 236, 48, 107, 32, 46, 6, 14, 130, 163, 192, +177, 177, 0, 90, 62, 36, 1, 137, 205, 99, 10, 85, 96, +139, 53, 225, 31, 200, 204, 244, 254, 206, 132, 103, 159, 121, +93, 79, 87, 158, 184, 63, 74, 60, 189, 198, 74, 82, 191, +142, 84, 141, 86, 243, 241, 212, 101, 167, 203, 232, 239, 220, +178, 59, 89, 36, 79, 93, 69, 60, 83, 86, 200, 195, 108, +247, 133, 149, 138, 246, 32, 33, 248, 166, 94, 212, 166, 52, +144, 26, 19, 146, 255, 4, 104, 211, 43, 151, 77, 217, 2, +129, 129, 0, 230, 45, 251, 241, 113, 214, 136, 2, 61, 182, +212, 98, 69, 125, 184, 249, 225, 52, 83, 164, 199, 195, 241, +89, 244, 177, 159, 221, 6, 247, 33, 184, 111, 72, 247, 150, +70, 144, 246, 99, 52, 218, 130, 42, 71, 187, 222, 254, 254, +221, 131, 89, 219, 47, 182, 41, 10, 28, 244, 52, 111, 14, +246, 166, 122, 244, 59, 98, 28, 26, 135, 247, 229, 134, 68, +54, 186, 87, 3, 182, 87, 211, 185, 144, 242, 59, 236, 221, +33, 152, 237, 186, 200, 166, 55, 208, 112, 39, 212, 115, 106, +146, 66, 95, 208, 193, 101, 125, 120, 234, 125, 118, 131, 31, +56, 62, 183, 234, 248, 118, 64, 158, 146, 6, 33, 251, 36, +59, 2, 129, 129, 0, 244, 71, 234, 25, 25, 183, 240, 96, +124, 56, 35, 162, 198, 226, 209, 228, 205, 142, 102, 126, 10, +223, 242, 75, 2, 37, 255, 148, 252, 83, 52, 26, 163, 115, +26, 8, 140, 29, 208, 226, 63, 237, 102, 224, 223, 90, 111, +155, 176, 16, 121, 24, 13, 154, 221, 63, 108, 76, 203, 104, +26, 162, 119, 157, 184, 11, 65, 231, 89, 206, 238, 99, 251, +32, 57, 232, 139, 56, 23, 79, 244, 70, 202, 95, 36, 28, +140, 78, 50, 246, 165, 160, 31, 45, 91, 45, 147, 128, 159, +43, 207, 77, 126, 101, 82, 85, 179, 216, 29, 94, 201, 52, +172, 193, 197, 211, 247, 215, 120, 62, 40, 145, 166, 238, 205, +247, 131, 117, 2, 129, 129, 0, 166, 150, 210, 59, 49, 132, +90, 119, 41, 173, 41, 38, 64, 61, 27, 74, 67, 92, 168, +29, 155, 136, 212, 134, 212, 244, 26, 12, 138, 133, 9, 118, +138, 80, 179, 47, 255, 70, 12, 247, 29, 73, 121, 25, 158, +128, 0, 5, 63, 237, 4, 106, 222, 98, 72, 17, 191, 153, +111, 254, 26, 150, 72, 236, 9, 76, 38, 254, 74, 33, 37, +164, 120, 75, 66, 77, 117, 237, 75, 103, 20, 187, 25, 185, +150, 105, 32, 247, 178, 182, 102, 83, 98, 102, 94, 47, 66, +58, 181, 166, 53, 57, 11, 46, 111, 61, 70, 118, 179, 39, +55, 240, 43, 25, 149, 72, 73, 87, 97, 36, 198, 45, 9, +15, 101, 75, 45, 37, 2, 129, 129, 0, 239, 135, 67, 45, +135, 201, 71, 87, 162, 164, 158, 117, 198, 1, 69, 87, 226, +117, 183, 44, 229, 206, 163, 221, 248, 37, 66, 84, 84, 13, +217, 112, 200, 29, 48, 111, 249, 243, 102, 56, 126, 111, 66, +3, 88, 132, 129, 91, 229, 106, 204, 103, 70, 30, 83, 118, +247, 163, 244, 70, 52, 3, 233, 213, 107, 191, 85, 138, 50, +53, 125, 45, 61, 245, 195, 61, 171, 95, 215, 27, 152, 220, +210, 99, 68, 71, 210, 74, 175, 123, 79, 185, 228, 203, 217, +230, 246, 60, 96, 78, 209, 63, 9, 98, 90, 177, 171, 93, +95, 137, 196, 75, 142, 128, 62, 126, 41, 206, 76, 17, 30, +208, 143, 195, 79, 112, 53, 49, 2, 129, 128, 80, 90, 189, +41, 156, 134, 115, 50, 199, 34, 231, 20, 105, 124, 34, 107, +243, 129, 83, 240, 184, 220, 229, 163, 239, 167, 21, 61, 57, +60, 168, 242, 182, 173, 240, 146, 252, 200, 130, 4, 97, 255, +44, 181, 189, 104, 57, 188, 139, 117, 127, 161, 170, 221, 110, +230, 220, 171, 62, 8, 148, 5, 102, 101, 249, 99, 33, 61, +36, 168, 82, 225, 179, 191, 59, 42, 144, 95, 78, 66, 121, +91, 9, 156, 121, 165, 73, 228, 170, 144, 27, 168, 115, 87, +147, 189, 0, 82, 26, 172, 111, 127, 120, 21, 177, 167, 225, +200, 8, 52, 133, 62, 251, 72, 19, 192, 254, 4, 89, 90, +100, 85, 228, 163, 33, 49, 38, 140, 1}; + diff --git a/crypto/test/rsaperf/rsa257e2048_1.pem b/crypto/test/rsaperf/rsa257e2048_1.pem new file mode 100644 index 0000000..dd2b0c6 --- /dev/null +++ b/crypto/test/rsaperf/rsa257e2048_1.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,013871620331CDFD + +ilbNFoOWsWoB0AUF572ySr5fZqhZnqHaC/8/Tk83vs/lV2qBWcQvzJKas3s/qzlW +tSgov2pHbLIH6CshIYQSuQGZZQG9HK7LzRQeAC9T2Dvb0iFDYFuVwZ6KJB0/JQNg +/UzIi978zd0+K7lr66+dwbqEwBJkxQ5CLD8PEOqHzseVWfz7N2Q0mMKkTBIdL9iI +m95kB3llessK8VbSPLAdx9D8KLKgEF0iog1DGAQk2bB83HYRfDsOKqdTbH7OSe1m +WF+eibGe2q0mReLwv/c3hM3e2hS5Kf6nmb4j45zKYIEz1SQnBuMDYkyqhLGjJmbM +t0LTXUvdJWkYrHXmQZxIVTgQ3B3Sia1iW3BBDPwLC9Jm1YAiJtEL+VP+p8uwiLFb +Gt05O1dUQhrT9HBp1GhyfaSpp8XRqRc2Ru32gyh617gpthXthhQwNA5MNAvvv3LX ++PW1BhxGLe9T8Hj4eJTBJW5nUG9UPR6loykW355+yMpeGSVc8kd1OrAzJE7qsw9m +BRFD0ereeyhpGFiylfinPl74DyTBRfSvdGu/SFQYiIqJIGLd0FMH3BMZHzMzqJU3 +/Z+bu2xao/IMq+NlZUWy5FQS5H+NiGCgQ5DIPwz3uzexcGQKpEbWacoi/LS9uZIu +e4mtIL1dI2MonJrU9qtejSjGeQqZ23JzsEvHDWxPCngcPng2RaBsjolmvazQop2s +lYlRAy/vo7HpkWn/YYS37Ch6BayQgt+o0RAqM+Z8ovzkyfBlWu18hzDg5Jm2/Ssu +9AEpFBOwps5+8TmfIUkUheV0ULpG2LiG4TxrIcoX/+1SXqtdTWCqC4BgzeepvSFN +9fjQed/Fv1kHRhmuYhSXhTt/JCyIe/NoqY7bxCf1LwY3D43YcLJBmwVzl7o48YLZ +SzHBOf8eGItkltybpSpOTjWKIqdoGe0m6WP8kfkzYu8BMURTeyiIIhcn7sZNIiSk +oNjeVn06rCo7NiynEO739eVFHwzMj2iO7MtXNpwhfdJmxPIVHxJMqY/UhJSg4ftG +PR4NTT/kv8qlAeB4yPujcrFSPWrfBXaW0e+n0srFJZJTh5h5j/mKOyK/mtK5khoq +z6cLfEuKOQM8wqx/z9hRlwY0+uLUDKxaf9PcUh7nn4kBrisBI9bRRkuRy9LXhNFR +bB94QAmurH8sZJWdmonY1f9boCk9XExCOVuUtzKSs5WmWR7w3VPgCxMtdOavFkyu +0qXdAxuHM8aN8Jc/lkxrZgEIxG/ox7P/yg6Wrhh1ctIM8h79wa5PqDToGXquF7Mb +vrXQHIgWFBxffuqKi0m8XtpkMLxEew2EcKKBplj9qHBujzQ/E4lGseAyyzjBQ56v +AN6rKWQup04s4q/ujD1Sr1MgNd4v78IVD1fFV8TU2pl13qO0XKpavHo8IlcCLYke +G5tl1SvwY1oCS7h/U9X1ieQw6BaGoFvTPltnE706JIBbq0TbTHQNXTInUOSsROZ1 +LJMCxXr/xYooBnBX3UvhljSyE5Mu14zEPcsfmWhz3Uv5XancN3k6c+vIHWc+eKbw +1ukOjtd/Zyz5b1aSFnTYSNalxosJexGFXVdKPB6DVsvvnTnZUWcyPg== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa257e4096.h b/crypto/test/rsaperf/rsa257e4096.h new file mode 100644 index 0000000..8e600a8 --- /dev/null +++ b/crypto/test/rsaperf/rsa257e4096.h @@ -0,0 +1,189 @@ +/** + * @file rsa257e4096.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa257e4096[] = { +48, 130, 9, 38, 2, 1, 0, 2, 130, 2, 1, 0, 168, +63, 120, 159, 155, 91, 89, 177, 180, 88, 144, 186, 187, 232, +193, 233, 125, 65, 229, 36, 82, 176, 128, 186, 156, 185, 162, +36, 66, 100, 169, 102, 124, 149, 93, 132, 207, 4, 186, 57, +226, 111, 208, 32, 11, 60, 106, 44, 211, 119, 224, 96, 59, +199, 137, 17, 218, 31, 151, 223, 127, 103, 113, 235, 252, 188, +168, 12, 108, 254, 187, 6, 11, 142, 74, 45, 207, 221, 82, +162, 187, 210, 165, 6, 41, 45, 122, 71, 50, 187, 226, 77, +183, 184, 7, 122, 47, 116, 10, 130, 54, 225, 29, 146, 128, +58, 83, 65, 157, 89, 250, 236, 120, 165, 64, 198, 201, 217, +34, 76, 228, 176, 105, 16, 45, 195, 89, 40, 197, 165, 27, +242, 115, 29, 156, 246, 12, 154, 225, 78, 66, 3, 191, 198, +117, 184, 10, 176, 80, 43, 157, 158, 193, 210, 213, 65, 152, +93, 131, 189, 184, 45, 199, 109, 24, 98, 228, 66, 12, 36, +148, 47, 44, 111, 26, 232, 102, 4, 231, 53, 86, 7, 145, +8, 88, 18, 31, 193, 114, 51, 205, 201, 245, 239, 75, 163, +252, 250, 171, 222, 75, 250, 167, 117, 93, 254, 19, 165, 161, +198, 204, 57, 220, 220, 40, 126, 139, 167, 138, 143, 140, 128, +207, 248, 91, 47, 134, 63, 190, 6, 27, 104, 244, 15, 20, +106, 236, 134, 25, 95, 239, 34, 111, 211, 121, 166, 223, 204, +220, 38, 95, 216, 179, 179, 0, 16, 193, 149, 106, 210, 222, +102, 51, 224, 218, 182, 39, 253, 153, 133, 109, 127, 255, 66, +102, 49, 10, 95, 165, 120, 156, 215, 8, 61, 197, 151, 136, +78, 133, 124, 73, 245, 33, 35, 86, 165, 228, 3, 138, 26, +173, 22, 183, 151, 188, 168, 175, 37, 242, 53, 122, 129, 105, +185, 125, 102, 118, 234, 185, 251, 233, 230, 160, 47, 188, 112, +12, 128, 125, 159, 185, 244, 206, 244, 247, 195, 253, 162, 0, +29, 181, 43, 140, 40, 164, 13, 57, 141, 46, 180, 181, 50, +108, 118, 130, 19, 49, 191, 193, 203, 133, 178, 193, 229, 2, +66, 190, 239, 209, 31, 158, 42, 94, 127, 5, 31, 47, 118, +220, 13, 133, 42, 211, 15, 50, 49, 139, 9, 160, 87, 6, +211, 13, 229, 16, 123, 48, 244, 249, 227, 62, 133, 65, 28, +235, 169, 154, 218, 126, 163, 90, 20, 245, 182, 31, 231, 224, +57, 149, 95, 253, 96, 103, 254, 24, 41, 4, 110, 27, 230, +90, 18, 154, 112, 249, 245, 88, 13, 181, 222, 204, 233, 3, +183, 80, 166, 4, 221, 193, 79, 66, 132, 8, 137, 5, 230, +124, 254, 66, 56, 171, 63, 107, 116, 198, 226, 194, 174, 22, +51, 228, 125, 77, 70, 64, 99, 130, 222, 69, 141, 23, 120, +19, 80, 228, 186, 26, 249, 51, 9, 155, 235, 142, 21, 244, +42, 18, 167, 41, 242, 50, 17, 178, 55, 204, 170, 129, 223, +76, 17, 144, 139, 2, 2, 1, 1, 2, 130, 2, 0, 11, +5, 39, 71, 55, 127, 172, 185, 32, 229, 151, 236, 91, 0, +35, 71, 146, 212, 86, 58, 253, 199, 126, 77, 247, 86, 221, +246, 22, 241, 87, 203, 198, 191, 189, 62, 82, 159, 133, 100, +20, 249, 96, 206, 162, 27, 8, 157, 85, 61, 36, 198, 226, +97, 61, 155, 17, 112, 248, 47, 3, 50, 197, 56, 118, 167, +191, 247, 132, 81, 25, 136, 8, 100, 203, 191, 152, 231, 123, +115, 149, 25, 234, 153, 248, 103, 107, 116, 58, 70, 105, 162, +121, 197, 126, 254, 223, 63, 140, 121, 192, 218, 242, 127, 77, +118, 95, 111, 97, 34, 72, 98, 42, 111, 25, 83, 190, 135, +63, 214, 226, 39, 114, 33, 25, 232, 111, 236, 236, 18, 243, +14, 13, 217, 67, 227, 159, 137, 250, 128, 207, 50, 183, 15, +210, 64, 174, 175, 232, 8, 43, 92, 147, 213, 135, 126, 81, +221, 157, 225, 24, 131, 212, 30, 56, 225, 159, 13, 244, 130, +143, 217, 64, 213, 205, 204, 123, 143, 24, 197, 230, 150, 232, +118, 64, 222, 252, 196, 115, 227, 217, 131, 238, 104, 41, 79, +248, 127, 81, 166, 34, 135, 30, 227, 254, 90, 133, 26, 243, +218, 13, 181, 109, 237, 55, 114, 53, 78, 224, 17, 180, 9, +25, 232, 65, 189, 56, 27, 191, 233, 125, 80, 22, 160, 93, +122, 56, 85, 38, 217, 159, 238, 212, 218, 226, 72, 48, 219, +199, 93, 40, 207, 69, 224, 100, 198, 226, 128, 92, 78, 127, +135, 25, 7, 167, 167, 241, 101, 199, 78, 37, 54, 157, 198, +194, 141, 52, 170, 68, 66, 34, 14, 81, 162, 175, 56, 0, +124, 215, 124, 184, 248, 103, 101, 184, 156, 95, 150, 187, 233, +136, 107, 65, 99, 92, 33, 155, 112, 120, 32, 56, 1, 174, +198, 27, 87, 11, 115, 152, 216, 15, 140, 187, 52, 149, 2, +101, 164, 224, 123, 80, 168, 221, 27, 171, 3, 230, 246, 114, +49, 92, 67, 225, 170, 90, 138, 29, 167, 167, 72, 161, 78, +6, 164, 76, 67, 156, 90, 126, 32, 54, 241, 238, 87, 136, +5, 181, 167, 32, 111, 38, 119, 105, 18, 79, 229, 29, 204, +189, 5, 98, 132, 133, 59, 190, 13, 119, 104, 91, 20, 36, +37, 96, 203, 9, 173, 227, 183, 238, 161, 9, 33, 139, 248, +180, 146, 136, 207, 128, 93, 121, 128, 140, 233, 40, 78, 203, +100, 213, 177, 243, 49, 16, 88, 180, 85, 30, 111, 52, 185, +170, 221, 152, 218, 159, 190, 31, 26, 62, 149, 118, 229, 145, +195, 156, 59, 212, 197, 3, 217, 93, 187, 207, 226, 135, 126, +191, 123, 144, 226, 209, 255, 37, 114, 211, 239, 165, 139, 78, +118, 238, 203, 215, 33, 245, 157, 187, 184, 3, 184, 175, 28, +131, 231, 99, 39, 233, 204, 32, 228, 158, 6, 230, 109, 180, +72, 145, 218, 152, 4, 124, 165, 42, 211, 158, 94, 92, 172, +229, 151, 71, 65, 2, 130, 1, 1, 0, 195, 97, 204, 241, +138, 242, 40, 181, 4, 152, 41, 225, 91, 239, 97, 249, 194, +177, 158, 84, 124, 167, 169, 230, 229, 140, 65, 53, 114, 138, +251, 61, 3, 126, 124, 95, 248, 234, 73, 207, 56, 61, 196, +186, 212, 94, 61, 225, 82, 128, 203, 99, 61, 4, 36, 183, +87, 81, 134, 224, 241, 236, 231, 109, 57, 4, 110, 210, 113, +60, 238, 231, 96, 30, 252, 178, 173, 176, 77, 68, 79, 193, +252, 4, 200, 9, 196, 74, 130, 111, 53, 73, 251, 102, 207, +165, 154, 52, 181, 238, 110, 242, 133, 79, 53, 97, 46, 233, +142, 211, 68, 63, 64, 118, 29, 66, 220, 59, 54, 142, 160, +229, 107, 25, 183, 47, 44, 184, 9, 92, 240, 3, 239, 87, +35, 31, 186, 49, 98, 195, 88, 54, 103, 34, 109, 197, 112, +84, 84, 16, 231, 175, 187, 61, 149, 186, 153, 252, 225, 101, +47, 177, 50, 188, 6, 68, 138, 189, 153, 164, 133, 70, 207, +235, 140, 112, 132, 82, 78, 128, 154, 77, 45, 123, 227, 50, +66, 17, 130, 218, 212, 87, 23, 70, 205, 235, 68, 52, 60, +24, 75, 50, 215, 119, 250, 152, 112, 179, 89, 230, 110, 138, +23, 75, 124, 42, 210, 216, 75, 227, 183, 54, 121, 253, 149, +34, 214, 37, 242, 61, 170, 88, 51, 219, 38, 160, 166, 85, +231, 49, 61, 138, 176, 113, 94, 7, 207, 96, 110, 150, 91, +164, 39, 80, 86, 193, 2, 130, 1, 1, 0, 220, 114, 140, +33, 32, 93, 219, 155, 21, 210, 251, 119, 88, 49, 104, 235, +173, 184, 200, 49, 90, 116, 149, 205, 170, 71, 156, 163, 36, +92, 214, 187, 99, 164, 111, 102, 233, 88, 50, 225, 12, 170, +12, 167, 166, 194, 127, 34, 42, 236, 128, 51, 159, 120, 34, +52, 46, 242, 166, 56, 178, 171, 249, 121, 83, 244, 187, 50, +230, 245, 44, 46, 87, 106, 123, 189, 249, 36, 149, 248, 16, +63, 47, 155, 235, 56, 229, 145, 205, 16, 63, 130, 242, 91, +225, 120, 149, 104, 187, 254, 28, 14, 241, 45, 161, 136, 175, +200, 38, 148, 129, 217, 240, 13, 155, 2, 186, 77, 46, 68, +88, 20, 169, 214, 210, 0, 35, 191, 114, 235, 32, 189, 63, +239, 223, 85, 45, 156, 231, 63, 172, 3, 64, 182, 180, 222, +15, 223, 63, 186, 143, 129, 68, 40, 214, 114, 231, 184, 52, +230, 133, 28, 252, 204, 217, 18, 232, 192, 252, 176, 83, 65, +11, 31, 235, 139, 215, 127, 82, 60, 130, 149, 60, 108, 81, +54, 1, 2, 246, 47, 150, 234, 65, 164, 221, 136, 221, 55, +173, 141, 170, 124, 26, 95, 197, 45, 173, 70, 23, 220, 167, +106, 179, 208, 159, 34, 198, 225, 38, 10, 244, 240, 73, 61, +77, 174, 143, 129, 196, 52, 106, 228, 6, 117, 69, 121, 163, +98, 200, 185, 41, 234, 147, 176, 235, 96, 97, 170, 147, 128, +42, 187, 80, 7, 166, 75, 2, 130, 1, 0, 119, 91, 159, +17, 17, 37, 93, 153, 106, 102, 234, 196, 112, 240, 222, 55, +244, 114, 123, 158, 50, 64, 146, 159, 250, 204, 55, 198, 1, +61, 254, 22, 84, 207, 194, 132, 87, 80, 94, 229, 48, 77, +148, 18, 129, 188, 15, 227, 76, 76, 176, 11, 208, 154, 239, +148, 219, 177, 78, 105, 138, 211, 118, 119, 132, 115, 68, 178, +93, 21, 73, 58, 171, 71, 185, 64, 84, 48, 238, 116, 112, +121, 126, 16, 221, 208, 45, 52, 125, 128, 178, 251, 99, 202, +67, 21, 122, 24, 59, 87, 226, 40, 147, 46, 101, 87, 66, +130, 185, 221, 179, 39, 162, 229, 138, 103, 153, 118, 217, 155, +220, 207, 226, 203, 249, 94, 143, 221, 0, 189, 65, 240, 121, +79, 33, 105, 12, 36, 37, 108, 96, 184, 164, 155, 129, 208, +69, 158, 25, 116, 233, 45, 152, 60, 136, 75, 37, 74, 203, +111, 158, 161, 11, 18, 61, 154, 110, 167, 159, 154, 75, 112, +252, 134, 238, 50, 206, 88, 34, 2, 219, 197, 143, 85, 164, +177, 33, 99, 89, 230, 77, 235, 125, 200, 163, 165, 163, 48, +216, 2, 227, 58, 243, 49, 99, 76, 48, 237, 17, 17, 64, +138, 38, 35, 39, 254, 69, 9, 156, 237, 185, 162, 198, 10, +121, 252, 96, 244, 81, 62, 146, 229, 50, 154, 203, 228, 161, +97, 77, 123, 183, 7, 7, 46, 88, 82, 119, 182, 109, 100, +209, 98, 73, 210, 114, 193, 2, 130, 1, 0, 39, 117, 32, +13, 229, 234, 242, 131, 90, 145, 87, 215, 154, 62, 162, 56, +33, 22, 29, 219, 3, 61, 181, 53, 190, 218, 4, 33, 47, +89, 85, 64, 107, 124, 15, 244, 137, 100, 116, 175, 192, 134, +8, 61, 226, 20, 221, 250, 41, 140, 242, 23, 47, 120, 30, +7, 89, 22, 131, 90, 213, 69, 161, 50, 154, 123, 126, 37, +0, 127, 142, 97, 241, 195, 94, 221, 69, 127, 19, 222, 180, +55, 35, 106, 153, 170, 142, 177, 129, 87, 147, 213, 177, 218, +167, 219, 207, 9, 199, 255, 169, 97, 78, 8, 42, 219, 179, +226, 20, 217, 213, 127, 169, 120, 248, 225, 155, 222, 0, 79, +247, 219, 218, 169, 239, 204, 58, 50, 52, 113, 206, 19, 237, +143, 138, 150, 183, 122, 182, 214, 154, 78, 71, 89, 123, 4, +225, 248, 37, 78, 55, 145, 168, 150, 191, 200, 220, 198, 83, +46, 61, 173, 135, 228, 234, 23, 78, 132, 41, 62, 112, 133, +42, 212, 231, 107, 181, 3, 220, 233, 245, 129, 79, 139, 234, +173, 7, 39, 96, 219, 177, 108, 171, 32, 127, 79, 72, 119, +137, 165, 206, 211, 121, 67, 241, 124, 184, 106, 46, 27, 138, +138, 161, 173, 206, 201, 118, 70, 46, 167, 80, 178, 122, 174, +85, 159, 190, 11, 69, 251, 111, 197, 51, 245, 29, 94, 124, +222, 225, 48, 21, 114, 179, 213, 244, 86, 250, 146, 20, 108, +155, 18, 149, 203, 148, 77, 2, 130, 1, 0, 114, 210, 206, +8, 173, 34, 173, 47, 82, 24, 155, 132, 128, 19, 6, 28, +34, 86, 87, 206, 14, 56, 134, 224, 29, 253, 133, 129, 35, +209, 199, 66, 218, 242, 196, 151, 120, 222, 233, 222, 190, 49, +117, 26, 132, 106, 255, 93, 13, 5, 50, 210, 22, 156, 186, +109, 208, 147, 73, 126, 142, 136, 120, 111, 159, 38, 210, 39, +163, 242, 119, 238, 198, 214, 209, 147, 116, 110, 226, 63, 74, +66, 240, 34, 245, 92, 207, 66, 44, 164, 54, 250, 40, 82, +210, 230, 250, 240, 1, 73, 38, 50, 66, 230, 121, 16, 87, +38, 255, 86, 216, 197, 25, 178, 188, 54, 208, 24, 90, 90, +183, 45, 139, 11, 21, 29, 41, 254, 4, 231, 169, 101, 79, +90, 128, 223, 240, 254, 42, 150, 35, 7, 175, 27, 155, 117, +148, 234, 60, 254, 100, 198, 134, 69, 215, 202, 118, 25, 131, +17, 138, 210, 212, 216, 163, 5, 159, 89, 162, 59, 212, 142, +139, 129, 37, 5, 106, 13, 208, 37, 108, 127, 97, 127, 57, +174, 200, 87, 140, 28, 32, 74, 158, 117, 237, 240, 152, 105, +45, 126, 0, 248, 213, 89, 211, 95, 224, 47, 0, 19, 125, +226, 214, 15, 73, 182, 200, 46, 1, 31, 84, 145, 204, 98, +94, 177, 28, 208, 215, 113, 93, 219, 250, 242, 94, 201, 109, +123, 9, 153, 120, 33, 167, 226, 233, 232, 92, 161, 84, 200, +206, 157, 132, 130, 188, 46, 6, 6, 6, 6, 6, 6}; + diff --git a/crypto/test/rsaperf/rsa257e4096.pem b/crypto/test/rsaperf/rsa257e4096.pem new file mode 100644 index 0000000..96b906d --- /dev/null +++ b/crypto/test/rsaperf/rsa257e4096.pem @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,17E4EAE39FEF6FD5 + +l3ddL8AdchlrmtkgUSaGa/BLwilRMs8neOkQ75Zl+PnzR2mEjIfMF8z77zar/pci +ZlpNphvD9nSuRNh94MqwRRQk7SXhgqeIpktNDTrSKNq1+ur/Dv4ztKEumxgTtw2A +o63hBcMk2+5tLHaJDAiTB7zhCn86HWC6XIMdys5TaqTTDXURo6LkdURIMThBJ4s/ +FkBd2uEQcgGaZgg/eMBH6VL5bLxWOgzIJr0pBCwTR79ZAHFe9EEFYuzkOaaIszYc +aXzLfRTSB98ESjb6gA4f0lWp+w9bLcnzd8w50752XtDPSP9kCIrdKXc7UtxG3Q3R +3aKJlvq4cRKYgA6fmJjM7OEx8wEb45pGPimoS07AHwb7QUsCnnrQeH43uxGAfF5f +BAYsSIY/U25A2tk+4FkiRdkZ2PASX+LPvqYacxkYxl5NzeYuZz/dYii9qqhm/z+o ++lAjKQ3aRCntwi79Vytfape/19qDpRTPnNA8sKS6lRJTHf5uzE36zMvn/6gIzXW2 +dIOr2Fbng6pqjPdY1W/GLb9D7+CuDE6aSfr26LAQXGuendCzvXNORk7E85jjNKWv +ngQqi0zDA9KCP2sAiajqwKXZgjMqEhk9dMrxUOxeFOIVZ3LwFqnOVDYfC3hY69Cz +U9qanJ6jvnMZnHRA9xSlO1YNuXm7DIeK55ObU3DI4M/mbiHlMBoqK7UsIp3JYEHj +mdv+vBc659JBn0es97GylM35oIp9IN4YovzphAfxkKTMbXJJUNmOyS4GuIgOutMQ +ra4QLsGG9DChTXSsCeOmPJ7qMrAw7qU4U1UjwBcKHXq/GeylLJB7H7NDNkIrTv1B +GQmTDN7VUib8vjBv0Q6mV8WblCnlBx7YtHcKbBm9dmnQvzTlf/r+nPuF6v/tqgWx +sDfc2JHojY9b/xMxYf+7zgSvFbeATODJT3FVNiBMSBda/oaOqZWbKBPSLp0JjFa0 +E2a88OAm1rpJLCI24wa1iLKgm9Z9Rf+JtZPDb1gVnyRzlA4aNx7j7xEqdoYMlWx4 ++gHQz2GmYhAIQMPY795UTxsEfD9bjxdxvM0Is0PU7cogdLV4/Ku8yM+PGL1+F7jY +uJKxFbcFb2MIJrSlEDxKfMbgIqP3a/xvpPuLImCaI8VFJLZ3rOomoKLbDvh4C5Ll +hpoMjJeqUQGOX00kzO6JrdNJ4xA6Eiw2d0gCY8/jxcX5t9Wum0ctvQNHdI4psgD4 +PtnWiFJ/bDZ2id5pLFM2dihgR1Ac7BOcxzf/ZZA6lEa4kiq8njUaQXNCOy0SHSol ++zEooAAg0XrTPK1fQ95Q7cAjU+Dlmkxi96oswVJn0tXtcygCh3MR6VH8FTVzu7vJ +HCnioNKMkNOPU7Cl4z44utngj1daJmqeUFYIP7F0qs9+Xjgt7AnJBePtnN+4BB1h +8+HUJUS1G6XBeGxukct4af/ayUL/HI0A4oqWSt+kkJGS0bkSBf6LW8kI3n429J/O +kAGgExAPFJnzxnkNH5I0BTVL+W5wBDOKM9CrAbDTbbC7FjhCejX/ixcbDeyjB0Fn +7P5tJOUBZmS9nGW4mYiaBkZWGxVkSyIr0Iwp/dJ9pV2zGhUqEdsNey8tXDT6Q/ez +aXt4OH4nPA2cCCHCk/awVrZGA8TNc0juTHgKqLidImUS3kC7/INm8sb4OxKSQIit +KQS1udFqMJDIFgG4VSc75JxyGA3ZVokU+gH87jfm/O1qD85xeXU/sG0fySCYHRjP +PGrbDfUr2zIhfsOGxXSHjtpU2Z1Oc0tianz3WVk1DZluOLKiqXUpXf+vt4Sg7kWI +N+Sst20r+2Imocyr1WFkuz9F04C6WmlzbZvUYelBrBx4FAvLvS0vwMa5zCIoMCJ8 +DVACS0ov7B+3jMixJkXbBJCqRJEO2rrz0OW0xRI6crZBzUBz/iELJGzkwtRFX5EB +jkBOnSYzoTLhoO9+V5Fx+hciQ3yTaOttk72tMhmmA8vjsWdAlcJS3r4YMOw+OrV5 +gfsOKbgVD+eaThA5t5GDF0q975M/cOPIOBsTagMpUU+4y/QSbrKZysh0ElKkWRax +qS8vUsrloqY7EIOHS0Nq3Hxbg2yLHajGmwHztV7VNzd087U1Dbsc0dqmoJkP4HXp +muT1YH4tKYe3Ij8oX7LPjZVvsffzIEsTPihPRtopuAz7WlDI35eavSjtQdN1IWAv +4xpsqpWj6p/Ztw/Vcj0OMSos2SYVOEhC3VZuxpbG15/gUWDoW8ksG+B198Onq3Xz +LmCDLHFl9Yn21SoDnkg4XiPTQQQ/ZBOuT3UbuSxsPw5QDhmH94SIGbyqhGKQK3u+ +25cuXX4toA8KR6lRwkzlP07wpb0IQ/UxUrlvzbKChdTDirILCs8D2QxYCWAFhaSw +KMbudOFpd94OCvAdKkE8/GApK9GsCCZY/JSTQbcb5x5cv/RG+sX/flCkECGDHl5f +7aLZSo16/6CW7c07vlETpdsW77ae9xirLEZRAdPjMa8sgGeIH0Ov6q3zyWYcgohr +WsdfxnZXzsdQb7WLsmr0v3RM7n6Cj14yVqzFEOOzzmaepQ642wUGDyBOcPqHvzku +9+Iq/ZDDVzcZ/mrwlYKw5o0x5RZFLHlVuibH+EOAo5tdNoL3wsZ3Sqj3nnRWLpnc +4zD4TqBTi2F3FI8VhfLRoJ1RAtW/vS4ZpIou+urAhYkjXRKT4sXDti1a9H2+G6HL +6MgyF0jAII7flnFznCGchQtlkhSa0hhqGserzj3Zeq8s4Hj3zqe7FmipAhcwmg4t +EEPOjR+ktcQfgpF3LBchHImKcEP9LVMYotjE4V77AQ5M2w+oESwwP6XDmxk9bx34 +Hkmnrb69I3vyt0vth9Pdbr8mTKHwREgAVvWlP4uqSJ2rgTBRrz36hlNDNEc3Xbx8 +PcIjzxa5W81WJ6Xltsv0D8fSLNmNyANQvAokLdyQrUrITu3R/UkPdLf4QmlxpbLo +iqDvrbi1KfmMt4ZafRC65Z90i1eSD8vCkUMIAjySJ/IjMz99WP7UhofSQv1yyY5a +M90RPdD6gWSTerxjiB8wKF6Ln9jJGiU2ZRexEBsDwG+yyrC2PUsSo4wJ36K+k8bY +shOnpN0U9OPOilok50HN0fWOMAXSjDop1oDdXSMiYHKVhYGRkbYQo5l5AsT/SoUk +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa257e4096_1.h b/crypto/test/rsaperf/rsa257e4096_1.h new file mode 100644 index 0000000..9b0876c --- /dev/null +++ b/crypto/test/rsaperf/rsa257e4096_1.h @@ -0,0 +1,189 @@ +/** + * @file rsa257e4096_1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa257e40961[] = { +48, 130, 9, 40, 2, 1, 0, 2, 130, 2, 1, 0, 189, +88, 91, 135, 70, 32, 118, 182, 210, 114, 81, 7, 107, 112, +129, 37, 214, 4, 175, 136, 170, 180, 177, 233, 95, 162, 192, +161, 42, 130, 43, 147, 80, 66, 127, 119, 21, 1, 101, 108, +242, 93, 9, 205, 237, 54, 3, 142, 151, 84, 146, 201, 109, +20, 183, 35, 242, 44, 89, 159, 128, 157, 216, 177, 22, 199, +214, 214, 9, 231, 224, 194, 113, 109, 134, 18, 196, 14, 224, +236, 89, 149, 17, 100, 215, 69, 201, 155, 86, 113, 156, 72, +75, 73, 73, 2, 167, 12, 205, 101, 135, 152, 152, 132, 97, +211, 219, 171, 62, 234, 163, 144, 138, 84, 98, 174, 13, 86, +220, 70, 178, 134, 40, 189, 194, 9, 97, 245, 243, 79, 120, +61, 94, 38, 49, 63, 202, 57, 159, 40, 139, 70, 132, 30, +239, 39, 194, 253, 45, 219, 234, 188, 238, 205, 120, 239, 36, +221, 180, 213, 88, 20, 5, 167, 111, 232, 239, 239, 81, 25, +46, 185, 66, 114, 52, 14, 205, 65, 117, 50, 78, 217, 198, +119, 187, 241, 31, 163, 155, 14, 31, 254, 157, 134, 190, 46, +40, 205, 133, 19, 199, 189, 157, 139, 150, 119, 189, 46, 151, +244, 21, 111, 202, 243, 8, 248, 72, 117, 59, 234, 2, 254, +182, 201, 251, 199, 94, 49, 4, 38, 172, 4, 48, 173, 7, +175, 50, 25, 111, 97, 149, 4, 142, 206, 172, 184, 114, 174, +141, 225, 67, 51, 73, 239, 157, 214, 81, 62, 89, 50, 130, +213, 173, 114, 251, 163, 112, 11, 9, 54, 80, 85, 167, 54, +201, 151, 220, 165, 18, 84, 77, 188, 115, 229, 139, 203, 232, +150, 118, 108, 153, 53, 128, 109, 9, 25, 150, 213, 243, 115, +97, 55, 101, 60, 9, 89, 136, 33, 116, 235, 85, 182, 56, +156, 118, 51, 48, 63, 85, 66, 30, 74, 253, 237, 68, 153, +179, 7, 148, 178, 229, 180, 224, 1, 142, 127, 130, 202, 40, +247, 231, 207, 254, 61, 16, 84, 99, 172, 21, 208, 253, 113, +123, 57, 222, 243, 27, 32, 203, 97, 83, 105, 198, 122, 97, +184, 66, 48, 16, 252, 225, 9, 74, 207, 166, 249, 202, 191, +5, 74, 114, 241, 179, 53, 115, 249, 156, 206, 172, 81, 221, +247, 143, 172, 19, 142, 60, 56, 219, 27, 171, 196, 172, 240, +42, 10, 220, 195, 104, 151, 195, 120, 180, 43, 116, 107, 70, +130, 102, 222, 125, 40, 117, 115, 152, 183, 223, 138, 207, 232, +39, 60, 246, 118, 29, 214, 126, 64, 187, 201, 255, 13, 146, +116, 36, 103, 178, 155, 255, 247, 165, 165, 191, 18, 158, 73, +94, 24, 81, 178, 93, 141, 50, 220, 69, 107, 115, 255, 220, +103, 68, 199, 226, 227, 101, 30, 52, 215, 101, 24, 76, 57, +4, 245, 83, 107, 114, 215, 112, 110, 128, 193, 33, 255, 248, +92, 84, 14, 169, 244, 202, 202, 46, 81, 226, 160, 137, 66, +86, 8, 100, 13, 2, 2, 1, 1, 2, 130, 2, 0, 2, +22, 99, 244, 181, 60, 31, 219, 42, 212, 26, 117, 201, 230, +130, 235, 0, 51, 132, 108, 235, 162, 178, 154, 207, 191, 56, +147, 223, 110, 87, 206, 83, 16, 86, 189, 20, 81, 220, 194, +156, 188, 160, 80, 203, 254, 196, 239, 206, 221, 231, 14, 44, +136, 135, 127, 102, 114, 96, 157, 81, 69, 206, 193, 222, 140, +169, 140, 124, 159, 113, 139, 70, 80, 101, 235, 73, 225, 157, +223, 104, 234, 60, 31, 211, 57, 97, 174, 222, 150, 86, 57, +232, 66, 98, 150, 240, 147, 102, 53, 21, 64, 69, 106, 183, +8, 207, 116, 70, 65, 87, 119, 246, 230, 94, 14, 222, 71, +131, 236, 49, 115, 9, 21, 4, 161, 36, 28, 28, 191, 76, +136, 37, 186, 92, 132, 91, 12, 150, 172, 70, 153, 89, 29, +58, 107, 48, 34, 255, 172, 236, 214, 235, 14, 225, 244, 176, +226, 60, 153, 24, 182, 45, 56, 34, 69, 121, 46, 162, 25, +3, 171, 97, 133, 104, 213, 84, 155, 157, 216, 224, 84, 105, +243, 10, 222, 246, 226, 194, 31, 221, 125, 41, 148, 190, 92, +123, 162, 163, 170, 183, 253, 240, 163, 19, 23, 60, 6, 168, +6, 130, 101, 2, 103, 73, 80, 26, 8, 152, 230, 48, 215, +164, 182, 133, 195, 155, 238, 241, 69, 40, 105, 162, 61, 2, +147, 50, 134, 23, 78, 240, 54, 1, 147, 11, 221, 130, 109, +44, 16, 152, 80, 192, 144, 235, 83, 219, 213, 106, 135, 31, +222, 72, 91, 244, 73, 221, 175, 242, 230, 202, 64, 233, 197, +219, 137, 153, 111, 198, 189, 49, 214, 65, 175, 156, 69, 86, +240, 32, 11, 82, 48, 22, 120, 120, 125, 142, 186, 182, 239, +150, 205, 109, 205, 227, 32, 156, 35, 68, 89, 230, 179, 48, +174, 255, 253, 169, 164, 142, 243, 74, 93, 172, 91, 85, 67, +208, 39, 247, 122, 51, 229, 76, 149, 211, 255, 101, 2, 137, +63, 8, 196, 29, 86, 201, 157, 192, 37, 38, 176, 155, 160, +22, 130, 199, 75, 144, 83, 193, 79, 222, 13, 53, 194, 215, +247, 38, 126, 92, 49, 58, 22, 154, 229, 1, 182, 22, 239, +253, 79, 47, 43, 15, 123, 232, 140, 133, 230, 29, 78, 220, +104, 86, 58, 107, 152, 31, 90, 76, 16, 138, 141, 134, 215, +186, 16, 139, 123, 250, 234, 8, 39, 237, 241, 243, 65, 210, +61, 65, 46, 174, 97, 73, 85, 8, 153, 153, 12, 208, 232, +23, 79, 56, 215, 91, 230, 215, 234, 96, 66, 179, 54, 214, +156, 31, 79, 67, 248, 79, 188, 63, 146, 121, 21, 242, 140, +122, 137, 179, 156, 60, 25, 210, 254, 242, 37, 95, 215, 127, +37, 98, 141, 210, 157, 54, 212, 5, 166, 243, 87, 112, 110, +41, 0, 31, 174, 196, 116, 247, 205, 27, 184, 233, 42, 90, +221, 45, 143, 84, 71, 157, 110, 240, 93, 190, 50, 13, 123, +164, 14, 92, 81, 2, 130, 1, 1, 0, 219, 87, 118, 45, +150, 158, 109, 215, 67, 30, 88, 24, 141, 28, 196, 162, 217, +173, 192, 87, 220, 238, 171, 88, 173, 193, 31, 181, 22, 65, +151, 120, 25, 130, 189, 44, 161, 188, 241, 150, 163, 27, 40, +124, 123, 215, 67, 65, 247, 135, 75, 255, 41, 219, 180, 73, +242, 134, 195, 22, 221, 40, 78, 175, 183, 10, 169, 149, 224, +151, 88, 45, 219, 10, 117, 11, 130, 145, 173, 202, 74, 139, +250, 126, 107, 74, 183, 213, 141, 88, 253, 37, 31, 84, 25, +222, 21, 27, 83, 196, 171, 177, 164, 43, 35, 16, 236, 183, +209, 214, 228, 172, 98, 95, 169, 189, 44, 2, 242, 207, 100, +240, 160, 164, 232, 25, 248, 33, 50, 14, 229, 197, 206, 133, +68, 222, 16, 10, 13, 174, 96, 21, 108, 251, 145, 165, 11, +51, 103, 69, 201, 204, 18, 104, 174, 77, 167, 210, 26, 165, +122, 126, 159, 204, 174, 212, 132, 69, 204, 244, 174, 143, 201, +48, 170, 45, 211, 173, 178, 213, 230, 154, 109, 14, 130, 23, +25, 219, 220, 220, 238, 230, 70, 175, 253, 10, 245, 86, 174, +35, 224, 144, 111, 154, 76, 65, 251, 22, 178, 138, 96, 70, +29, 23, 127, 71, 72, 239, 171, 26, 255, 76, 26, 46, 21, +186, 250, 149, 252, 249, 217, 150, 195, 231, 154, 2, 145, 65, +179, 147, 200, 204, 87, 248, 190, 156, 66, 36, 222, 76, 25, +83, 33, 232, 112, 25, 2, 130, 1, 1, 0, 220, 253, 126, +171, 221, 207, 65, 217, 192, 179, 94, 109, 182, 204, 0, 58, +83, 80, 18, 187, 41, 163, 41, 91, 247, 122, 104, 112, 7, +203, 161, 115, 2, 80, 98, 194, 202, 91, 11, 247, 22, 11, +38, 199, 118, 180, 163, 127, 91, 203, 218, 118, 49, 83, 46, +223, 156, 200, 225, 29, 130, 200, 156, 94, 134, 75, 217, 40, +30, 236, 63, 131, 85, 76, 224, 61, 103, 225, 29, 160, 215, +118, 66, 35, 232, 234, 104, 182, 109, 142, 247, 123, 65, 22, +176, 98, 2, 215, 57, 59, 45, 254, 78, 83, 40, 155, 145, +19, 115, 245, 5, 54, 139, 194, 162, 88, 196, 123, 70, 30, +69, 62, 103, 196, 61, 210, 32, 120, 84, 213, 39, 128, 33, +8, 158, 244, 91, 163, 170, 53, 177, 52, 2, 37, 153, 39, +128, 92, 32, 232, 91, 160, 50, 142, 79, 125, 174, 68, 176, +115, 108, 49, 129, 120, 125, 129, 34, 178, 101, 86, 246, 112, +137, 48, 43, 177, 239, 227, 128, 159, 37, 230, 81, 115, 192, +241, 185, 131, 77, 177, 38, 231, 150, 238, 199, 226, 0, 169, +225, 110, 78, 219, 167, 203, 182, 187, 102, 37, 48, 57, 150, +200, 88, 16, 187, 245, 39, 48, 106, 227, 143, 54, 184, 13, +21, 27, 131, 99, 43, 178, 87, 206, 253, 158, 35, 58, 17, +98, 18, 226, 223, 46, 57, 20, 158, 102, 163, 110, 115, 77, +18, 92, 124, 175, 2, 21, 2, 130, 1, 0, 117, 199, 94, +86, 60, 244, 114, 195, 70, 231, 116, 9, 50, 222, 163, 92, +108, 234, 190, 240, 108, 171, 252, 97, 108, 61, 221, 58, 99, +155, 191, 230, 214, 233, 144, 105, 165, 138, 79, 235, 72, 163, +255, 211, 71, 122, 143, 177, 221, 145, 93, 153, 242, 157, 209, +94, 126, 62, 102, 195, 143, 168, 18, 88, 96, 75, 115, 246, +212, 61, 88, 48, 135, 140, 23, 1, 51, 47, 88, 86, 181, +121, 251, 13, 24, 189, 137, 143, 142, 163, 85, 32, 226, 1, +84, 157, 26, 70, 116, 179, 81, 60, 133, 249, 71, 159, 128, +26, 252, 33, 181, 143, 93, 169, 231, 152, 97, 88, 62, 165, +39, 66, 116, 36, 192, 93, 162, 31, 197, 54, 209, 11, 149, +190, 25, 6, 173, 247, 115, 236, 19, 183, 212, 234, 177, 209, +38, 226, 210, 216, 198, 1, 255, 236, 129, 116, 104, 15, 51, +42, 9, 254, 67, 224, 117, 200, 198, 135, 25, 98, 131, 149, +236, 135, 180, 8, 171, 112, 50, 53, 25, 54, 8, 193, 17, +15, 100, 139, 249, 22, 2, 197, 92, 190, 32, 71, 160, 160, +25, 197, 145, 124, 95, 201, 99, 183, 217, 128, 187, 131, 20, +208, 250, 179, 246, 165, 199, 137, 168, 147, 249, 165, 96, 188, +27, 155, 47, 228, 245, 105, 70, 5, 64, 90, 126, 134, 219, +113, 248, 212, 213, 104, 190, 173, 105, 86, 228, 195, 28, 184, +77, 89, 118, 208, 123, 241, 2, 130, 1, 1, 0, 131, 143, +240, 195, 243, 157, 65, 26, 10, 33, 18, 93, 53, 10, 225, +65, 154, 48, 170, 135, 84, 141, 245, 194, 52, 179, 116, 245, +254, 170, 9, 116, 72, 25, 241, 21, 85, 154, 207, 87, 84, +215, 210, 90, 219, 22, 222, 216, 69, 151, 62, 82, 81, 41, +141, 118, 46, 133, 137, 1, 161, 136, 93, 23, 102, 220, 120, +80, 169, 209, 96, 148, 233, 17, 224, 36, 142, 135, 3, 177, +111, 86, 87, 48, 69, 238, 42, 106, 156, 221, 148, 84, 85, +144, 254, 108, 39, 139, 22, 30, 64, 60, 192, 15, 163, 161, +88, 92, 68, 9, 102, 182, 226, 164, 174, 88, 180, 184, 243, +244, 35, 63, 12, 247, 81, 160, 244, 115, 119, 60, 40, 115, +32, 157, 137, 118, 148, 48, 160, 25, 252, 235, 42, 30, 90, +46, 109, 73, 197, 228, 249, 200, 245, 65, 203, 182, 102, 192, +77, 39, 211, 213, 192, 160, 98, 159, 142, 46, 112, 32, 216, +112, 209, 44, 157, 127, 216, 134, 113, 109, 175, 246, 175, 254, +48, 32, 87, 135, 241, 125, 98, 221, 139, 169, 12, 105, 168, +188, 202, 239, 253, 36, 35, 37, 154, 155, 100, 167, 146, 64, +42, 242, 201, 216, 40, 45, 87, 20, 219, 6, 249, 158, 21, +233, 231, 181, 187, 202, 122, 162, 243, 135, 46, 101, 29, 239, +196, 158, 254, 75, 76, 22, 137, 147, 190, 236, 107, 65, 193, +39, 232, 17, 53, 79, 72, 245, 2, 130, 1, 1, 0, 208, +191, 181, 32, 111, 82, 141, 88, 116, 145, 102, 190, 211, 180, +191, 59, 6, 53, 114, 162, 32, 24, 14, 143, 237, 237, 247, +185, 148, 17, 170, 11, 103, 211, 10, 25, 14, 31, 124, 209, +18, 32, 183, 63, 22, 221, 220, 14, 100, 245, 8, 109, 167, +66, 194, 210, 41, 141, 182, 161, 142, 82, 115, 166, 188, 224, +220, 215, 47, 112, 20, 81, 122, 42, 73, 81, 49, 232, 28, +68, 95, 201, 45, 97, 46, 99, 76, 83, 37, 236, 109, 145, +23, 95, 4, 102, 9, 195, 78, 31, 209, 131, 201, 37, 133, +70, 136, 239, 58, 187, 216, 192, 161, 106, 8, 56, 244, 215, +42, 170, 226, 208, 66, 119, 45, 84, 38, 68, 96, 38, 210, +20, 232, 88, 94, 210, 225, 154, 210, 47, 226, 134, 242, 141, +149, 126, 231, 72, 243, 33, 75, 18, 113, 105, 220, 83, 105, +254, 193, 243, 220, 58, 232, 240, 73, 106, 171, 108, 4, 241, +176, 83, 60, 142, 124, 148, 43, 214, 156, 204, 89, 181, 4, +52, 120, 61, 156, 249, 196, 189, 248, 143, 0, 106, 42, 199, +45, 247, 196, 179, 24, 17, 98, 104, 24, 239, 172, 183, 87, +178, 135, 141, 72, 201, 241, 158, 155, 205, 116, 90, 56, 59, +69, 84, 109, 194, 244, 229, 122, 156, 214, 102, 130, 175, 112, +207, 27, 170, 244, 116, 119, 108, 40, 188, 218, 131, 14, 65, +156, 200, 243, 46, 216, 25, 54, 8, 4, 4, 4, 4}; + diff --git a/crypto/test/rsaperf/rsa257e4096_1.pem b/crypto/test/rsaperf/rsa257e4096_1.pem new file mode 100644 index 0000000..6fa3de2 --- /dev/null +++ b/crypto/test/rsaperf/rsa257e4096_1.pem @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,1B23D989D4F48555 + +3R977Fxnj5WbOnpqNf+2Tu3lYLMTIBEgRb41DB9EwNqWSLhHXStl7/H1a6PPvs7z +cEUOtk4+xenxkbgqgBjEeGYzoLiLDxqfee/teYXzJE9hu+Hq5PE6AkM71HtA1E+3 +zI5U/D8KD5zGAxllG/oLCK1uWPqznrYvFoe/zx71sILeiEpcs1WWvBpU9PQdoJlx +P7jqGr2jrVidSG+qne9LG6fJDu/fnvWdFDBsD0ED1bXvyQdePYhUNHROIHBoLGIs +wEz6KZzMcWmSExpEEJtOVT47l4z1lVBamSMXTePj9i/E2f2dO/UYwBcHdvGKFatf +8ji4PSliDhJ+uzN/vO65ruEliL+IMu5Vum5BSgyp+ibaf76YhUAgy0MCc7bKaWDS +cLNWEYnP/JgIn35tUG9QKExsNlMBfI/JgJOUK4hrO4sDbBU4zlDEbyFNH2pu8XVc +w7LPgyb+X0MhtDs1LgK8/oXqFUDlhj/7icjHZYEqxEgnCaFyOJaYpaw3bm15eKHv +zchOaiHG0Tm2OldQ20fxu760rAqnP1UbqZrSznTw3a5Rx1Slk7ZUWkEYtE++Ic+d +d1Ngmf74vU2z5bmZLh1L0UHx1w/2A5JeYyfGkm8ppDCFQf7pJaEu1LtshAUyD2xq +49czuS0MOWkmoqoI1lmFLSiYcNgoVDRHamYqTG2JHO8E9cCKxD2jHoETMdO/1brx ++4Gflg/pPzRinh2vlRMHMQUm9P9cYvwNb1KoHbTzuMY7L4TtIwRVumYbHjyDbZ+0 +Gv+AeE/vqysEcSg34rxzGd4jxcOyWFJkn/wcOOa8SORifxPxu5XUZFUNDkKP2798 +jjvYVeTZDplGmq2sHSRj7xQrIvL6pZGW/z58i/GCLBTRnv6xKdsedXllmPET7ih9 +kGFfxbJ4+SGoZKfi7pVU4R7O0Of46uPlTacBplSvQH1eCK24tOLNr1WuVFKaFAPp +c9yq+sF38zBzLgYw89lNQwGN1fvK03dhwbAv5tcAgbWke4/EULKmt5bSl8ZKY91n +FLAE4sctP2IJ7SPFIrokMMis0X96ZkdbH4K6FMNC1nOMaBCgSGvOqBUxdDlAJy3m +dsmRy8x9XsvyB5DWBSyfBOPzYnZHRig9ajbZ4f28MONQvzYNc2L2Y6ZXZnQ7Y4Xy +Zh2X9WgqhGNGbExOTtmO9j0P1tvzN1cx4cRlLmlOhjZM2YdkduHr/K4p07613j6b +wVQbWkaH87cxPLTpbtsc0JOr7OfhEQ78L21tjWaO26VAVyXr5hyvik/Y0hfRh0K+ +X569apwBLNywNCizyK8N+amojJ9K6by9cB9uOncO5Y7qJWkICFAMLSSVpr8nlnfw +ctGlUuh5falCRCp9tnv4nPgC/Yb/a/Xjnk74QUoN1xeoPNK09RDNfvFJOzWKXuAf +2QscsT5yiD52/6pjQuszp4yj9e6U975im0/QY7plzNIPjMjJKZ+kL8LwkgHTuUJU +IciNSJEGscKyTUYvI8rGtBzfk9D4NAsGYEDVEMB0yN/erbOISF75qtjonJZKmTd6 +z8Uk2d5BOi1ejsbv+SPvobxMzXEdHyz+KGuQCKTOZ43M8HyWrShw2Kg8fgnSCgLI +NZBXudeaBBvP1ThDtVXM3qx5EeXHKuGr94ot1S0+WW8jYZ4/Fgvd1HQ5vNrqTquC +T/tgiQuQF95vjO29XYDyh2hRG/n25M5D6haY/hcvWzDZZ1DiKvYPJW27GRaEn6Ls +z4Yl1qrgsM6+/7aJ87reXH+fYpf3fK1kc+hzS5hsmIq3nQt46OGPYji1GzyN/6jQ +DZSNyQcJZqFdE8JcE2YUhKG7xlYH3VudLLLA+qwHfg0Y9JiqALyZvYASe014hMtW +7whtbuqLvs77JvyssDJbxGXI0mBW9Rs4tFvTwx37zR5YjjEE/njWE+0MooSwBldH +IAtDLdTk50CErBnVuiFkebaoSe8kch96Z8SMHqgmPVrqCE7iSRHT9h1My1UJmK1r +r5bTSmrRYNr8gD13ktEa8hXtiJUW4LgV3Xiqyma0jwmb6m4nJUY9HlSodG43Keds +K5DIcX3MNOjUdUGZe++VfKyVoYsBsaVEVr7niBQug0Cauo7hMFEtJ2Swk3nRE4sZ +GagWv/LK0ezjbP36thqDGF7XiK+JdhEHYnhCPCTNpNJ3A7avYNspacXY8UtGAlCx +iABH6cY4BCkuz8j4HQlhLhQwY446cqudNaXTP1hdjYYUfYRaMrpR+x5BymXSFLxF +M1Gh1xU/+wODsKkS63Q4UM0aw4V5xM5+LtWmgAr04q+rjsafalnrT7Ni4paNi09n +eXzEBJrK/Qnr+l32cuiiPJGUrcY1HjOswnGbmMGoODjXPV8ymdpvHitNAiFlAW/H +zq+L3Sfj8GlYEANVEpOFii6y+Oe2rXAbQZitlDXiLrUjyyF5oD9N7bAOqGL2b66l +WvdgHstY8Cuq7a7jBbkQTM6rRnU2YUNf98qmOI8tNpywwL8TaBXqatoqZQR7A3yh +SioAg6tXF1Q1R84MrVE5wL0/o5Fth7YgzNnk130fvfSnXmryKnhfCQ+/i8Wt83gq +/W0h+6cQ4L90lwTNtukYo2HcTP8JK/Rnd8rScbRbeeDEINwwt933OqJt0xDMDlVh +9RU/OUhMiSd3ZP4K5NWP6+z8Y0t5Q4kCB4U6mHQYZcD3AToNU/fP7FX9WVziOPFH +CrOTvKmRom4PDcyvRKJTJaxoBH2BS2k45/cOuvOUxLd9i7FuwnCOE2ExCzjuR+A6 +5+pXy+UeCRyunH2TofOpWxaIFiTsB1Ba/+K2xK+SFQrgQtB2AIVgwcoGw6ZZXIXu +dUQvBcWp1GTFEqlGgxgj87s3q+pYN8Pd/QmHXMv4MWhSHUe6NTI2PHyKJxA0LAJE +Q2ueahAeZq07QKytZr9OkT0K7BkzH3cjpc00xzjMtneprMlEwPQBnMpY1ovMqgiI +USfP8Z+1FOPRTTJWS15SQ+iYq9K1aQyKG/VWwv0013+4nJs/sLF6f3g/MaHMaDZx +MDjCHDj5Efm47r/87BRE1hSAxJa6k15MipHmOSaMyR9URQoWwW/aUbYQTnfe7QfF +DJD/wQNM7GfJi4Zy2cg7h7L86O4f/L+r0VuZI4/PQBhObUnImKqSnck2gzhn8NC3 +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa257e512.h b/crypto/test/rsaperf/rsa257e512.h new file mode 100644 index 0000000..7a08ca1 --- /dev/null +++ b/crypto/test/rsaperf/rsa257e512.h @@ -0,0 +1,33 @@ +/** + * @file rsa257e512.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa257e512[] = { +48, 130, 1, 57, 2, 1, 0, 2, 65, 0, 219, 251, 69, +198, 203, 203, 250, 235, 246, 177, 9, 58, 231, 40, 225, 54, +7, 136, 20, 28, 178, 232, 225, 117, 136, 68, 94, 209, 148, +234, 192, 171, 215, 20, 50, 95, 116, 65, 112, 232, 66, 237, +179, 9, 244, 39, 112, 147, 157, 86, 238, 250, 65, 34, 200, +122, 47, 117, 11, 36, 5, 231, 40, 33, 2, 2, 1, 1, +2, 64, 1, 75, 187, 85, 105, 82, 80, 181, 210, 244, 73, +128, 234, 9, 63, 78, 134, 210, 204, 252, 33, 24, 107, 176, +189, 162, 111, 188, 65, 7, 134, 135, 206, 221, 33, 216, 48, +238, 100, 118, 209, 49, 156, 63, 224, 42, 109, 22, 62, 44, +24, 105, 18, 182, 131, 125, 41, 141, 5, 171, 63, 96, 215, +185, 2, 33, 0, 245, 158, 190, 118, 52, 112, 0, 169, 181, +71, 24, 47, 238, 137, 248, 131, 62, 242, 183, 187, 70, 92, +99, 152, 203, 241, 40, 186, 66, 3, 225, 89, 2, 33, 0, +229, 71, 39, 255, 104, 49, 4, 249, 217, 77, 152, 182, 195, +231, 47, 103, 223, 212, 82, 115, 21, 143, 163, 220, 244, 79, +156, 133, 249, 194, 156, 9, 2, 32, 30, 149, 66, 140, 58, +83, 172, 104, 205, 219, 7, 253, 255, 209, 109, 162, 197, 25, +61, 185, 175, 28, 112, 3, 22, 103, 189, 89, 238, 82, 42, +1, 2, 33, 0, 189, 33, 203, 84, 46, 26, 125, 161, 70, +173, 148, 226, 119, 195, 175, 146, 114, 232, 235, 91, 241, 233, +10, 168, 81, 255, 237, 177, 65, 147, 149, 161, 2, 32, 50, +202, 130, 122, 214, 104, 145, 215, 30, 153, 45, 203, 179, 132, +61, 229, 238, 88, 164, 208, 189, 131, 84, 205, 229, 101, 7, +235, 187, 18, 69, 139, 3, 3, 3}; + diff --git a/crypto/test/rsaperf/rsa257e512.pem b/crypto/test/rsaperf/rsa257e512.pem new file mode 100644 index 0000000..cc736db --- /dev/null +++ b/crypto/test/rsaperf/rsa257e512.pem @@ -0,0 +1,12 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,955BBFCA9F29DD9D + +sZB95BJJWehTLks/q+kUPpYO4B6h3E3H2H9deixuOfLY7pZPBQ//yv2pVjZsGy9r +I15RhYJGRVmaleZNTVuqTQeoxtdiI++1frQsoOwhErb17mJUyLakINqn2VK0KJNW +A2YcSx+1ajQ2KFefaRskxX/SLNILdidZLJc6391Ieq55G933PcDEZqeqIREDrn4r +At3o61foMo2k77eWGqmrI0BFPYsu3vgidwdoJOdjpEqsRdssfWQPwtMm8e+UUOnt +cHHr5pKGvLAJaB3I4Dq8Vf4A4HM4ba1O631pH2dlyhD4RwhaR1WNl4CmljlEK++V +gRJc4cpGOp1OUmK88RtlOwWU440h9GoPEYYD8ykac6ZDXd84D380HkO6D5vhN1yy +46SJxTQeta9dTuIjwfkiHR2KO35NTJXkLnUprYVl0kU= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa257e512_1.h b/crypto/test/rsaperf/rsa257e512_1.h new file mode 100644 index 0000000..5c453f6 --- /dev/null +++ b/crypto/test/rsaperf/rsa257e512_1.h @@ -0,0 +1,33 @@ +/** + * @file rsa257e512_1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa257e5121[] = { +48, 130, 1, 58, 2, 1, 0, 2, 65, 0, 162, 163, 199, +251, 185, 88, 101, 223, 22, 141, 65, 87, 237, 29, 226, 24, +130, 135, 80, 68, 175, 224, 117, 87, 141, 27, 203, 209, 152, +251, 149, 230, 202, 236, 132, 121, 222, 43, 130, 223, 35, 231, +248, 122, 9, 137, 153, 25, 78, 62, 73, 227, 199, 232, 98, +125, 10, 125, 133, 26, 5, 249, 32, 177, 2, 2, 1, 1, +2, 64, 62, 247, 176, 137, 204, 189, 30, 121, 187, 136, 94, +135, 37, 131, 153, 198, 191, 251, 156, 22, 155, 191, 253, 157, +233, 110, 222, 217, 29, 215, 240, 209, 195, 98, 105, 181, 42, +113, 121, 224, 81, 46, 17, 38, 145, 102, 1, 202, 158, 90, +169, 239, 251, 209, 252, 192, 204, 177, 234, 66, 45, 147, 11, +87, 2, 33, 0, 196, 173, 139, 156, 130, 224, 203, 165, 245, +224, 230, 123, 74, 30, 154, 160, 89, 130, 107, 13, 173, 156, +138, 217, 214, 15, 57, 151, 159, 123, 160, 235, 2, 33, 0, +211, 177, 252, 105, 231, 59, 124, 109, 109, 18, 3, 72, 204, +94, 95, 121, 47, 250, 220, 0, 194, 9, 113, 100, 8, 180, +195, 252, 198, 82, 189, 211, 2, 32, 123, 53, 238, 222, 143, +191, 160, 114, 236, 181, 187, 56, 81, 75, 243, 75, 140, 190, +71, 12, 141, 161, 209, 129, 126, 33, 113, 198, 148, 184, 8, +43, 2, 33, 0, 134, 68, 15, 167, 198, 116, 107, 205, 222, +147, 228, 51, 38, 249, 29, 172, 125, 15, 170, 106, 17, 122, +136, 170, 7, 131, 149, 52, 189, 137, 37, 183, 2, 33, 0, +137, 37, 231, 24, 225, 192, 77, 102, 210, 61, 114, 224, 192, +175, 114, 249, 124, 114, 196, 221, 250, 91, 80, 113, 107, 68, +25, 4, 148, 79, 141, 252, 2, 2}; + diff --git a/crypto/test/rsaperf/rsa257e512_1.pem b/crypto/test/rsaperf/rsa257e512_1.pem new file mode 100644 index 0000000..a21acd1 --- /dev/null +++ b/crypto/test/rsaperf/rsa257e512_1.pem @@ -0,0 +1,12 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,CFDD7B377960C07B + ++6WFlrMi+EYyBPEeIVJEIjvKMyKZ9o1g3hbPK98T4uCS+bFFw6mJrvLfibSBfzu/ +QzqJEn3b47p9YMUDxQECWk7Jt1Cnf95zvcGRwqgLberkU/dPAaUbSNfD6GGST0G9 +ErSiustIHrzy2/QzD4/ViYmUMOehVDx07R0ZGjpXMwqEIlAmkzoIWEY5dB47Sp0i +t3hgUL9rF8qWo8ecQXwtc8j16JQ9UvA4TWImmBze5xOA82CvqRUCKLwksZIX9UQ9 +KOhNC5gCEk+6SakgnBQFbbCTF2HyCz3fnIpZQw+II8+x08qj+0ZnGaawEh0n3YsN +vUHBG0rPXVOVRSaHXJI5gPh/NWQp+K6gn7FPhPne6R9QW4eSPIVltN5bR9H/JBp4 +jzRImVP1yquhUeccY8miCn01itw6xG+3+ltZQl5Wfr4= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa3e1024.h b/crypto/test/rsaperf/rsa3e1024.h new file mode 100644 index 0000000..0d1bfd9 --- /dev/null +++ b/crypto/test/rsaperf/rsa3e1024.h @@ -0,0 +1,55 @@ +/** + * @file rsa3e1024.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa3e1024[] = { +48, 130, 2, 91, 2, 1, 0, 2, 129, 129, 0, 199, 38, +213, 1, 105, 92, 239, 236, 208, 212, 56, 70, 161, 51, 144, +66, 50, 247, 62, 176, 204, 240, 237, 118, 44, 124, 187, 74, +111, 207, 47, 78, 249, 137, 149, 16, 146, 75, 183, 232, 155, +8, 104, 230, 154, 185, 9, 49, 193, 181, 255, 229, 222, 180, +5, 98, 101, 153, 24, 129, 53, 199, 56, 173, 70, 83, 117, +119, 168, 169, 210, 200, 140, 34, 244, 137, 142, 71, 142, 181, +187, 54, 149, 15, 86, 28, 107, 44, 34, 3, 252, 7, 43, +179, 35, 27, 129, 166, 19, 68, 4, 113, 43, 234, 23, 53, +52, 180, 51, 176, 55, 191, 183, 239, 8, 153, 195, 90, 97, +64, 247, 104, 249, 44, 217, 86, 38, 95, 2, 1, 3, 2, +129, 128, 33, 49, 35, 128, 60, 58, 39, 252, 205, 120, 180, +11, 197, 136, 152, 11, 8, 126, 138, 114, 204, 210, 210, 62, +92, 191, 116, 140, 103, 247, 221, 55, 212, 65, 152, 216, 24, +97, 243, 252, 25, 214, 188, 38, 111, 30, 214, 221, 160, 72, +255, 251, 165, 30, 0, 229, 187, 153, 132, 21, 136, 246, 137, +113, 234, 231, 225, 34, 157, 95, 105, 93, 205, 150, 229, 254, +120, 244, 130, 8, 10, 89, 168, 52, 186, 255, 10, 209, 93, +100, 215, 186, 178, 71, 80, 67, 75, 182, 221, 26, 179, 60, +90, 48, 62, 244, 114, 18, 8, 224, 23, 85, 233, 187, 39, +72, 120, 253, 86, 93, 28, 239, 29, 84, 193, 54, 46, 7, +2, 65, 0, 243, 157, 156, 22, 47, 87, 221, 158, 20, 167, +152, 69, 77, 90, 185, 110, 8, 220, 106, 203, 185, 61, 205, +187, 73, 135, 209, 178, 231, 102, 173, 123, 95, 135, 46, 132, +73, 190, 207, 188, 198, 41, 33, 185, 191, 40, 218, 229, 210, +2, 90, 78, 105, 127, 34, 199, 211, 253, 22, 195, 210, 9, +4, 227, 2, 65, 0, 209, 70, 146, 145, 201, 21, 124, 247, +165, 241, 248, 77, 107, 49, 201, 23, 116, 64, 57, 7, 58, +228, 92, 136, 168, 31, 27, 244, 22, 160, 148, 12, 91, 213, +182, 31, 135, 72, 63, 11, 215, 81, 102, 142, 63, 70, 208, +214, 107, 137, 194, 152, 131, 235, 56, 74, 117, 209, 50, 108, +128, 8, 13, 85, 2, 65, 0, 162, 105, 18, 185, 116, 229, +62, 105, 99, 26, 101, 131, 136, 231, 38, 73, 91, 61, 156, +135, 208, 211, 222, 124, 219, 175, 225, 33, 239, 153, 200, 252, +234, 90, 31, 2, 219, 212, 138, 125, 217, 112, 193, 38, 127, +112, 145, 238, 140, 1, 145, 137, 155, 170, 23, 47, 226, 168, +185, 215, 225, 91, 88, 151, 2, 65, 0, 139, 132, 97, 182, +134, 14, 83, 79, 195, 246, 165, 136, 242, 33, 48, 186, 77, +128, 38, 4, 209, 237, 147, 5, 197, 106, 18, 162, 185, 192, +98, 178, 231, 227, 206, 191, 175, 133, 127, 93, 58, 54, 68, +94, 212, 217, 224, 142, 242, 91, 215, 16, 87, 242, 37, 134, +249, 54, 33, 157, 170, 176, 8, 227, 2, 64, 13, 53, 65, +217, 126, 47, 14, 23, 178, 0, 135, 173, 228, 1, 51, 226, +6, 185, 185, 58, 13, 43, 94, 232, 231, 189, 38, 252, 97, +210, 209, 133, 198, 122, 2, 202, 237, 26, 188, 41, 204, 253, +91, 133, 16, 33, 140, 37, 25, 131, 101, 6, 149, 58, 240, +107, 253, 150, 120, 192, 66, 41, 97, 130, 1}; + diff --git a/crypto/test/rsaperf/rsa3e1024.pem b/crypto/test/rsaperf/rsa3e1024.pem new file mode 100644 index 0000000..0ec9dfa --- /dev/null +++ b/crypto/test/rsaperf/rsa3e1024.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,4DE639CC4DD25E50 + +EE/a9PhI61Ki1d3ubnW/fhESbqKyN/Y4okaQJ5NYnNCH0p4KQbaScHYeo4yKQQeI +LLlxTTo1tPKu5+j5EYA1mWJw+ly65yCkLcJP4WtJUgepVdWKPHU8kXpTuwPFPdcW +h0HtKmr0AA1JueusvHW+diitou8mp653S90MnENWCW8GsFx/eKuh/TkdnuR/FDD2 +J6Ig7IWjrHiYhChLsQkrjwcQ5ag3J9m4obtVFn9ugcIhu1m/V15+fVNbA8LsnwhC +zNVMnooOr40LLB2IAUo9eGJ4BtSUWB1oBswdklZgJ6uYkh9tgGTtAg3C5cZnLu5f +U4Q1qRpWS7pt0XT76rh9pBbXC+ksj32EM+evgyDUX9eau6tPZWf8LZJzZ7BO97aG +n8UuemmQOCEZNaEUJ1QqDgDf/mjWdmcLAm8KISqbfbLWVukxRhslD2hkx1x05fyh +U8a8BLSNkA00ji+cpxcYnTEG0nNfQADtR7lQhj5qKmdJrI3XtcushE5X7C/hWgPI +vTG1eRdbaRyCv8NEV5HdKJUJh6Ah5iZb045mQMfvqTEi4CKkOYJ7YoGHtwVvpE/c +p5TRxG3PXgSTrUUjbfsgVakR7alZ37rLRkJrVfvqUxGnXgbLzehxOg9DudiQnXda +q24Zf72QnrvRWVjWldM1P1hlReVbeOs8bdwbS8Ij14DE4MQAWYBNTQMGTSAhF4qK +H7sA3gLGbriT5wPON6rZ3zgsYj5/FrPpWa6OBMXjTKnEzv2tIi6I406MMUq0q44f +ViUnYgcVLYUkp4SLT1RVGIsy7om1TJB8lqq0W52qI/M= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa3e1024_1.h b/crypto/test/rsaperf/rsa3e1024_1.h new file mode 100644 index 0000000..facea14 --- /dev/null +++ b/crypto/test/rsaperf/rsa3e1024_1.h @@ -0,0 +1,55 @@ +/** + * @file rsa3e1024_1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa3e10241[] = { +48, 130, 2, 91, 2, 1, 0, 2, 129, 129, 0, 178, 168, +23, 146, 109, 42, 90, 180, 56, 194, 99, 107, 36, 185, 17, +201, 84, 225, 185, 38, 139, 17, 12, 54, 136, 224, 30, 173, +104, 100, 9, 95, 145, 194, 203, 234, 222, 120, 209, 77, 187, +180, 240, 233, 51, 214, 17, 33, 211, 85, 19, 244, 18, 113, +252, 163, 133, 198, 219, 111, 98, 185, 48, 199, 101, 104, 240, +34, 125, 23, 223, 1, 120, 188, 130, 242, 1, 2, 142, 227, +172, 220, 17, 151, 102, 253, 142, 135, 89, 122, 64, 132, 60, +88, 184, 203, 203, 248, 152, 9, 230, 244, 70, 252, 13, 231, +3, 113, 215, 185, 103, 110, 98, 33, 63, 12, 64, 176, 127, +60, 12, 199, 108, 70, 152, 63, 27, 91, 2, 1, 3, 2, +129, 128, 29, 198, 174, 152, 103, 135, 15, 30, 9, 117, 187, +60, 134, 30, 216, 76, 56, 208, 73, 134, 108, 130, 215, 94, +108, 37, 90, 114, 60, 16, 172, 58, 152, 75, 33, 252, 122, +105, 120, 55, 159, 72, 210, 209, 136, 163, 173, 133, 163, 56, +216, 168, 173, 189, 170, 27, 64, 246, 121, 231, 229, 201, 136, +32, 244, 69, 117, 17, 130, 19, 126, 219, 77, 65, 162, 44, +10, 212, 194, 18, 53, 70, 232, 83, 145, 68, 122, 82, 103, +224, 110, 48, 0, 171, 67, 154, 247, 103, 141, 41, 106, 77, +145, 227, 42, 149, 135, 50, 175, 245, 23, 228, 157, 57, 148, +161, 220, 174, 165, 6, 181, 194, 123, 145, 3, 189, 4, 51, +2, 65, 0, 217, 136, 164, 132, 103, 7, 35, 204, 138, 181, +172, 12, 160, 92, 207, 19, 197, 207, 142, 187, 124, 232, 156, +117, 74, 234, 94, 237, 27, 31, 192, 75, 190, 20, 12, 117, +67, 133, 180, 213, 30, 106, 34, 7, 53, 131, 169, 133, 95, +191, 226, 249, 71, 253, 201, 92, 185, 136, 77, 117, 146, 136, +86, 217, 2, 65, 0, 210, 63, 141, 53, 9, 155, 194, 17, +30, 125, 9, 221, 31, 169, 51, 98, 167, 99, 16, 230, 130, +122, 20, 35, 159, 77, 76, 119, 29, 53, 98, 222, 65, 119, +60, 156, 37, 157, 38, 211, 239, 251, 182, 58, 130, 119, 46, +141, 83, 7, 224, 71, 204, 154, 215, 183, 16, 176, 57, 106, +239, 72, 171, 83, 2, 65, 0, 145, 5, 195, 2, 239, 90, +23, 221, 177, 206, 114, 179, 21, 147, 52, 183, 217, 53, 9, +210, 83, 69, 189, 163, 135, 70, 233, 243, 103, 106, 128, 50, +126, 184, 8, 78, 45, 3, 205, 227, 105, 156, 22, 175, 121, +2, 113, 3, 149, 42, 151, 80, 218, 169, 48, 232, 123, 176, +51, 163, 183, 5, 143, 59, 2, 65, 0, 140, 42, 94, 35, +91, 189, 44, 11, 105, 168, 177, 62, 21, 27, 119, 151, 26, +66, 11, 68, 86, 252, 13, 109, 20, 222, 50, 250, 19, 120, +236, 148, 43, 164, 211, 18, 195, 190, 25, 226, 159, 253, 36, +39, 1, 164, 201, 179, 140, 175, 234, 218, 136, 103, 58, 122, +11, 32, 38, 71, 74, 48, 114, 55, 2, 64, 82, 163, 191, +226, 168, 80, 36, 150, 246, 35, 100, 54, 204, 152, 130, 70, +73, 246, 89, 144, 51, 244, 132, 236, 171, 44, 60, 162, 227, +130, 213, 5, 88, 98, 1, 189, 72, 2, 229, 235, 20, 195, +227, 129, 10, 200, 251, 185, 182, 249, 196, 128, 22, 229, 220, +15, 125, 20, 19, 249, 26, 45, 182, 36, 1}; + diff --git a/crypto/test/rsaperf/rsa3e1024_1.pem b/crypto/test/rsaperf/rsa3e1024_1.pem new file mode 100644 index 0000000..ac1d083 --- /dev/null +++ b/crypto/test/rsaperf/rsa3e1024_1.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,22364A543361E546 + +MRGo0c3dP3x2gHE0tujpRAzp7bv9kvksWULhehezQwDRMLwt3DjOTXihnfU83WYS +5YqYOseFKjnbIDti5t/Pd1neFY2BLr2u1fz5ZNWoKCoyAFnn9nC2EhdR2m2OOyE6 +gNQPwekPI3FgFqzgj9LXns5LNi0m30wo6XEEuvcB7d9Ss3pP7X58J6QqtCCI72ZE +CT2LvFRfgF7hkNDLfcOoxIOHhfgP6y/iHh58GUbhCTT1wn83BSLiaTqTkda/OFg7 +ey3MuoKTDmTTOEYmbfTkUW7tDQ71v9KJVwwcsdZGRRpoM6n6DjInKTJsx/M599Hk +XpcdT+lmpY5S+mO1TrMZpzUenKWeiMVZjEPC4lZ0jWRG4MqRZu0MwjNiAa4QGXO1 +gWPrPjfXXOIEVCviTpytqlKfVfTEWfDkMaYUekNomPfbZ4iPOjMa4H28Agm+lpjP +8AlHzi0scemqhTQKtPBsGY5cYz8raFMUK0I4jh9KJHzZmHsHUsNFlwpJMOEYL/kA +YrDZdvVm05IYEU0wseQXQaQiornXztDyyrpN6FJH1iTNwxZsC4E+pVzlDYpiJiLf +8R7yD92sR/guoPfIQWHqrIX+uH8TO5xqb89EC3hFitsAkVSb+oQ3pLFj525JXWTK +BFgm2SZfud8nIB03BZLqM0rEFIyMUoD2lFNzOZTTlkGLoY0r4KXHdcjYgVk3iElI +2YDqWepkFZ/hiuQ1bpbEDaeyBnAoP5yd4/CEiuIrJBMbp3dqBulRyzAEud765Kem +3u5Jlu7YS/nMZt6plVWxvckgwdXg2A0CGbZy+AXN99w= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa3e2048.h b/crypto/test/rsaperf/rsa3e2048.h new file mode 100644 index 0000000..5cbbce8 --- /dev/null +++ b/crypto/test/rsaperf/rsa3e2048.h @@ -0,0 +1,100 @@ +/** + * @file rsa3e2048.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa3e2048[] = { +48, 130, 4, 163, 2, 1, 0, 2, 130, 1, 1, 0, 202, +12, 238, 181, 62, 219, 118, 211, 196, 201, 19, 101, 11, 192, +110, 167, 234, 177, 252, 77, 64, 40, 137, 192, 26, 94, 152, +145, 80, 155, 57, 143, 197, 51, 209, 119, 124, 138, 97, 252, +220, 129, 201, 72, 3, 190, 177, 6, 223, 91, 179, 116, 84, +137, 144, 137, 73, 224, 112, 8, 165, 139, 239, 13, 88, 48, +89, 180, 21, 93, 41, 208, 130, 77, 236, 126, 87, 164, 84, +39, 251, 60, 137, 112, 37, 52, 200, 58, 186, 224, 81, 152, +23, 156, 63, 126, 31, 127, 31, 168, 231, 137, 254, 254, 46, +88, 108, 254, 252, 155, 212, 127, 149, 98, 244, 18, 228, 226, +156, 210, 59, 187, 77, 165, 228, 233, 79, 108, 70, 162, 248, +130, 222, 178, 200, 223, 174, 224, 26, 236, 83, 5, 202, 81, +188, 50, 169, 126, 131, 186, 134, 92, 238, 94, 245, 162, 228, +65, 241, 121, 140, 183, 80, 225, 4, 9, 202, 106, 74, 143, +23, 159, 12, 76, 132, 178, 168, 72, 129, 100, 119, 129, 112, +88, 246, 124, 61, 127, 125, 161, 138, 63, 163, 179, 125, 85, +224, 36, 107, 17, 57, 2, 66, 243, 138, 183, 115, 136, 227, +216, 255, 49, 244, 136, 244, 238, 215, 158, 37, 127, 198, 117, +75, 28, 45, 79, 204, 121, 162, 1, 59, 104, 32, 159, 218, +178, 152, 3, 63, 210, 89, 12, 219, 165, 144, 92, 200, 15, +161, 92, 159, 197, 70, 90, 101, 201, 2, 1, 3, 2, 130, +1, 0, 33, 172, 210, 115, 138, 121, 233, 35, 75, 118, 216, +144, 215, 74, 189, 27, 252, 114, 255, 98, 53, 92, 22, 245, +89, 186, 110, 194, 226, 196, 137, 151, 246, 51, 77, 147, 234, +23, 16, 84, 207, 106, 246, 225, 85, 245, 29, 129, 37, 57, +243, 62, 14, 22, 237, 108, 54, 250, 189, 86, 198, 65, 253, +44, 228, 8, 14, 243, 88, 228, 220, 77, 107, 12, 252, 191, +185, 70, 14, 6, 169, 223, 108, 61, 91, 136, 204, 9, 201, +208, 13, 153, 89, 68, 181, 63, 175, 234, 133, 70, 209, 65, +170, 127, 178, 100, 18, 42, 127, 111, 78, 21, 67, 144, 126, +3, 38, 37, 196, 205, 180, 159, 55, 155, 166, 38, 226, 145, +191, 206, 134, 2, 147, 197, 73, 46, 202, 0, 194, 136, 75, +116, 138, 58, 157, 44, 124, 184, 155, 152, 216, 162, 237, 182, +22, 135, 178, 207, 120, 64, 103, 186, 111, 100, 190, 228, 128, +69, 100, 188, 239, 212, 205, 69, 131, 52, 243, 90, 243, 237, +253, 176, 26, 144, 173, 174, 115, 93, 137, 210, 13, 196, 170, +140, 147, 174, 73, 88, 141, 221, 206, 46, 229, 25, 125, 115, +245, 140, 170, 119, 35, 171, 247, 84, 156, 162, 198, 153, 78, +232, 201, 174, 102, 5, 85, 120, 240, 60, 44, 37, 67, 240, +175, 163, 141, 146, 239, 254, 147, 191, 1, 81, 116, 236, 99, +94, 31, 155, 135, 12, 141, 187, 51, 79, 221, 217, 2, 129, +129, 0, 242, 122, 185, 110, 30, 138, 180, 213, 182, 159, 226, +164, 189, 193, 223, 31, 114, 213, 73, 194, 58, 19, 162, 218, +187, 196, 124, 203, 91, 26, 198, 127, 147, 111, 214, 208, 109, +191, 182, 150, 166, 28, 201, 222, 146, 38, 188, 175, 128, 188, +60, 254, 120, 250, 123, 209, 43, 136, 212, 36, 246, 126, 132, +233, 108, 105, 199, 17, 164, 100, 70, 42, 239, 102, 11, 250, +207, 146, 255, 161, 224, 210, 61, 110, 255, 103, 122, 152, 161, +195, 92, 246, 240, 209, 130, 188, 137, 184, 204, 175, 66, 174, +175, 26, 52, 121, 96, 136, 160, 144, 132, 84, 88, 245, 221, +223, 46, 232, 155, 64, 219, 150, 57, 62, 253, 233, 137, 79, +2, 129, 129, 0, 213, 81, 27, 5, 73, 136, 92, 241, 60, +59, 169, 21, 208, 136, 173, 210, 154, 82, 115, 104, 164, 17, +207, 176, 160, 85, 241, 169, 88, 74, 89, 119, 138, 232, 221, +180, 28, 239, 18, 51, 72, 4, 174, 195, 170, 132, 180, 197, +115, 106, 140, 210, 12, 102, 85, 35, 184, 220, 181, 41, 76, +54, 178, 186, 55, 254, 64, 46, 131, 172, 209, 179, 116, 130, +216, 95, 202, 108, 178, 155, 4, 59, 235, 187, 41, 37, 206, +133, 142, 66, 239, 20, 27, 141, 100, 63, 162, 193, 94, 97, +86, 114, 244, 169, 206, 81, 40, 184, 87, 123, 69, 3, 248, +46, 64, 60, 13, 63, 111, 41, 155, 123, 20, 35, 20, 145, +169, 103, 2, 129, 129, 0, 161, 167, 38, 73, 105, 177, 205, +227, 207, 21, 65, 195, 41, 43, 234, 20, 247, 56, 219, 214, +209, 98, 108, 145, 210, 130, 253, 220, 231, 103, 46, 255, 183, +159, 228, 138, 243, 213, 36, 100, 110, 189, 219, 233, 182, 196, +125, 202, 85, 210, 211, 84, 80, 166, 253, 54, 29, 5, 226, +195, 78, 255, 3, 70, 72, 70, 132, 182, 109, 152, 46, 199, +74, 68, 7, 252, 138, 97, 255, 193, 64, 140, 40, 244, 170, +68, 252, 101, 193, 44, 232, 164, 160, 139, 172, 125, 177, 37, +221, 202, 44, 116, 116, 188, 34, 251, 149, 176, 107, 11, 2, +226, 229, 249, 62, 148, 201, 240, 103, 128, 146, 100, 38, 41, +254, 155, 176, 223, 2, 129, 129, 0, 142, 54, 18, 3, 134, +90, 232, 160, 210, 210, 112, 185, 53, 176, 115, 225, 188, 54, +247, 155, 24, 11, 223, 203, 21, 142, 161, 27, 144, 49, 144, +250, 92, 155, 62, 120, 19, 74, 12, 34, 48, 3, 31, 45, +28, 88, 120, 131, 162, 71, 8, 140, 8, 68, 56, 194, 123, +61, 206, 27, 136, 36, 119, 38, 207, 254, 213, 116, 87, 200, +139, 204, 248, 87, 58, 234, 134, 243, 33, 188, 173, 125, 71, +210, 27, 110, 137, 174, 94, 215, 74, 13, 103, 179, 152, 42, +108, 128, 233, 150, 57, 161, 248, 113, 52, 54, 27, 37, 143, +167, 131, 87, 250, 201, 128, 40, 8, 212, 244, 198, 103, 167, +98, 194, 13, 182, 112, 239, 2, 129, 129, 0, 170, 174, 216, +164, 124, 150, 183, 46, 246, 226, 84, 81, 211, 251, 216, 225, +72, 138, 130, 139, 4, 77, 106, 29, 242, 65, 184, 29, 3, +137, 253, 213, 175, 113, 62, 62, 241, 104, 7, 101, 4, 117, +239, 176, 65, 146, 175, 154, 129, 233, 206, 26, 39, 86, 141, +82, 234, 232, 240, 81, 245, 5, 148, 10, 115, 23, 82, 10, +108, 106, 158, 130, 131, 40, 207, 71, 234, 90, 64, 161, 141, +63, 89, 234, 52, 96, 84, 173, 148, 160, 67, 29, 11, 61, +174, 252, 86, 7, 146, 134, 88, 60, 152, 170, 68, 122, 39, +18, 70, 251, 160, 153, 225, 216, 143, 57, 225, 116, 80, 226, +108, 42, 179, 58, 87, 14, 11, 183, 1}; + diff --git a/crypto/test/rsaperf/rsa3e2048.pem b/crypto/test/rsaperf/rsa3e2048.pem new file mode 100644 index 0000000..606a5a5 --- /dev/null +++ b/crypto/test/rsaperf/rsa3e2048.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,E1BD4E5D3FE84DA3 + +6cIqhhnC450CZzsZxQdVvf7bBpLmyU7ra5nu1XTX+D4kIgLtl1fEGyKFWekCMsw9 +nCN81h8N1xaz6SSObf126wWRrXpAAvu/asmZke2LqkM24mbtsuHHS5egrXyaMOAK +D8QVw9vAnASg3uQ60hMbfT/tJAwvXoxUgK8OEy0473lx2D0JXGYN8pZo6vxIBnyS +YNR+vtlFplaR2g7HLNBv/xq04jvM1ND8j/hw2Dt83o04qFg7NvVupnlWTqz1Tmq4 +iSrFaGYM5Cc2fbI6k5+h4Mi6hGAVXVMGMAFzskU4oEm/ofo+4Z+3sC7/ufx9vqxH +KkMFtwTlUIvGi/HSPQA1I3knKCxcxkJO4AVXv66S2hdTihkmR4WfooBuARNnpWx3 +pZd79KkMeSto7Qcd2d+3heS0BuaQISXhPHqfAvh1Q2g9Q5na1EMZzYQnWf2rfD26 +kccyrh+GgIs1AipkAwRI+/MEu8/eoXd7gz656Zj17qH8J/wOLtGzEWikTzNbsGFK +S+vJyET5x0cWRh2sVdEcmpG1MW6AR2SHP3QuLeLpBea02lBYRkVlqdf8BLqdayli +w4tUPsEGHBdL6NIkWr/phyTH3npHlts9ZcgNjhkX+wfOoRE8/z4Bp5q2PWUPgMZ5 +EAyIVhnjqWuBcqjie881J99oTQyVh5GrX3W62PRmexcFxXER95uB4YseJhyzy6qe +6fIPRLHOtSYu++d+DST54/FPCYvhpftDsbh5PrWaSNKOr5dH3OYWuiNo2dRVwEHR +zIFv51dXmA282i7l5kwOi08ucEmG00XChL/hWpELtNfaulz/hd77WU4jsS0t9VM9 +1P//idTsdaalKRBbKKsh+4YXlnj/Qz50e9sN0biMGTzJK2Utjchp9Eb9+TpycYhn +MB61mM2SjJDoGjkQZ4PEIQGKKYs7A21ACUn4VZe+UTNU5FnL/TIyaLTKRAptxYky +/DR5RTJR+O0nAwIcORi8DAPJyUtioVOdSy8A5a/dKfURxIfURbWTwCe2Yf9ESGTd +vxjLX7Us212gYggyEdREAX5Ek6W5aO2A3arI8dzwAXSfpjM9BFDz6Hj4UvAp6K1M +iqq2iKfaqhTMhEKf24eCDRsl0kBplmVQXKANy/9n0md3sDVjrt21xhlwkeOIObnc +N2Qz7fV1qXPwXkdy5j+RjhnnumNIreAgU5Gnk2ZqjWfTcApFhkOrvINJ5vDGQEbc +iF6UrDNWwUEYUaaolLtqV5DPuFONGljLlXlddGF8A0hUNt/xpYHrYSQTLTLe1XGU +6PHkrTeP0WQWBibVfaH2A4yrc/OYiebTpU1Dj3WGGtFLdOcTdJgETqiJX1WhFP/H +i9w+FZP5SSS4j62bdcNL1jnMRGOcjt5BPnTFdgjS+v73Et3P3rw5IEr3lW+PTcYQ +gwlAYu3P8QV4mJMMSl3EzEz4UGbnm6cuGWRP1so2bzvuSOWEhrr7O4/fbkZzVYmj +Hq4j9GiOmC/tVTS0AQQj9p4FGzXa+Tao/Cz/RaCPdTyGRvihfj7784NQhCPsm9KO +YL5ZhEWQuLa/0H+LDqYbP3abAmM+nGFUzkKHM3MV6RovWWDMe+efvw== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa3e2048_1.h b/crypto/test/rsaperf/rsa3e2048_1.h new file mode 100644 index 0000000..0d5e4c1 --- /dev/null +++ b/crypto/test/rsaperf/rsa3e2048_1.h @@ -0,0 +1,100 @@ +/** + * @file rsa3e2048_1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa3e20481[] = { +48, 130, 4, 162, 2, 1, 0, 2, 130, 1, 1, 0, 212, +218, 193, 171, 17, 75, 188, 25, 31, 152, 125, 179, 203, 167, +157, 160, 213, 68, 200, 166, 148, 88, 78, 93, 232, 159, 80, +214, 254, 213, 245, 73, 100, 171, 183, 147, 27, 106, 33, 35, +13, 132, 20, 19, 142, 206, 253, 185, 222, 81, 53, 125, 201, +182, 98, 240, 219, 240, 1, 76, 214, 108, 12, 192, 78, 240, +163, 93, 116, 144, 51, 250, 12, 9, 30, 54, 101, 38, 0, +194, 33, 120, 112, 50, 180, 20, 162, 33, 186, 165, 1, 190, +134, 93, 100, 22, 208, 210, 118, 80, 134, 41, 158, 185, 238, +216, 209, 42, 160, 7, 30, 250, 67, 13, 190, 241, 225, 246, +103, 116, 34, 222, 230, 249, 166, 231, 170, 230, 33, 1, 70, +201, 145, 113, 129, 73, 23, 105, 89, 84, 118, 132, 223, 238, +125, 50, 253, 137, 22, 43, 187, 73, 207, 12, 53, 129, 77, +165, 124, 61, 255, 4, 190, 219, 28, 20, 48, 230, 4, 207, +11, 33, 219, 2, 208, 247, 95, 215, 181, 90, 218, 176, 240, +61, 88, 55, 217, 164, 192, 110, 136, 26, 25, 36, 159, 39, +242, 38, 227, 63, 94, 192, 96, 238, 144, 27, 99, 50, 205, +116, 10, 199, 111, 176, 199, 0, 64, 31, 94, 227, 246, 212, +155, 154, 231, 67, 214, 30, 107, 204, 58, 9, 9, 128, 134, +19, 41, 179, 67, 63, 157, 2, 96, 136, 177, 91, 184, 29, +22, 157, 50, 56, 96, 134, 107, 39, 2, 1, 3, 2, 130, +1, 0, 35, 121, 202, 241, 216, 55, 74, 4, 47, 238, 191, +157, 247, 70, 154, 69, 120, 224, 204, 27, 195, 100, 13, 15, +166, 197, 56, 35, 213, 35, 168, 225, 144, 199, 73, 67, 47, +60, 90, 219, 44, 235, 88, 173, 237, 34, 127, 158, 250, 98, +222, 63, 161, 158, 101, 210, 207, 82, 170, 226, 35, 188, 172, +202, 183, 210, 197, 228, 232, 194, 179, 84, 87, 86, 218, 94, +102, 49, 0, 32, 90, 233, 104, 8, 115, 88, 197, 176, 73, +198, 42, 245, 22, 100, 230, 3, 205, 120, 105, 13, 107, 177, +154, 116, 82, 121, 120, 49, 197, 86, 133, 41, 181, 215, 159, +210, 250, 254, 102, 147, 91, 37, 38, 126, 241, 38, 156, 123, +98, 36, 19, 11, 169, 60, 167, 107, 162, 232, 234, 189, 182, +154, 88, 152, 182, 249, 59, 77, 15, 9, 240, 109, 94, 34, +110, 183, 32, 94, 231, 119, 178, 165, 85, 60, 54, 15, 88, +234, 216, 163, 239, 233, 34, 139, 128, 113, 115, 221, 6, 138, +99, 172, 169, 217, 187, 149, 172, 198, 129, 189, 116, 10, 237, +185, 193, 101, 124, 68, 115, 119, 60, 192, 94, 216, 39, 179, +167, 129, 34, 240, 136, 4, 2, 130, 45, 56, 35, 142, 42, +9, 174, 46, 91, 123, 189, 156, 227, 180, 163, 107, 232, 68, +50, 232, 67, 112, 5, 159, 60, 61, 58, 91, 19, 186, 245, +162, 208, 50, 123, 130, 127, 82, 136, 19, 182, 23, 2, 129, +129, 0, 216, 175, 103, 149, 115, 195, 159, 52, 217, 83, 42, +100, 132, 30, 85, 234, 127, 173, 187, 148, 187, 209, 156, 173, +136, 255, 70, 235, 240, 96, 100, 75, 47, 205, 209, 29, 129, +237, 120, 248, 119, 15, 238, 120, 122, 35, 0, 162, 54, 193, +229, 145, 252, 163, 179, 10, 68, 100, 114, 255, 226, 219, 8, +177, 237, 253, 244, 171, 36, 126, 213, 156, 39, 31, 233, 209, +209, 89, 126, 46, 30, 170, 117, 109, 45, 122, 19, 210, 140, +70, 6, 213, 38, 224, 162, 146, 190, 134, 177, 22, 31, 60, +178, 204, 141, 184, 158, 219, 173, 183, 58, 79, 185, 144, 116, +46, 213, 8, 212, 25, 83, 135, 48, 252, 168, 13, 74, 181, +2, 129, 129, 0, 251, 121, 108, 238, 38, 65, 245, 142, 108, +160, 174, 125, 170, 200, 118, 111, 179, 173, 222, 38, 0, 30, +124, 12, 17, 62, 86, 74, 155, 11, 171, 36, 159, 86, 238, +84, 85, 202, 162, 108, 121, 231, 125, 50, 145, 154, 205, 172, +113, 231, 168, 138, 136, 1, 66, 24, 174, 81, 89, 253, 211, +34, 199, 38, 152, 204, 34, 27, 228, 13, 88, 215, 203, 30, +62, 11, 208, 139, 247, 253, 221, 38, 101, 66, 51, 41, 163, +220, 222, 132, 91, 212, 186, 221, 212, 33, 183, 15, 206, 204, +120, 8, 21, 163, 74, 86, 82, 151, 90, 64, 159, 128, 133, +79, 117, 248, 26, 130, 2, 212, 222, 7, 5, 76, 136, 2, +219, 235, 2, 129, 129, 0, 144, 116, 239, 184, 247, 215, 191, +120, 144, 226, 28, 67, 2, 190, 227, 241, 170, 115, 210, 99, +39, 225, 19, 30, 91, 84, 217, 242, 160, 64, 66, 220, 202, +137, 54, 19, 171, 243, 165, 250, 250, 10, 158, 250, 252, 23, +85, 193, 121, 214, 153, 11, 253, 194, 119, 92, 45, 152, 76, +170, 151, 60, 176, 118, 158, 169, 77, 199, 109, 169, 227, 189, +111, 106, 155, 225, 54, 59, 169, 116, 20, 113, 163, 158, 30, +81, 98, 140, 93, 132, 4, 142, 25, 235, 23, 12, 127, 4, +118, 14, 191, 125, 204, 136, 94, 123, 20, 146, 115, 207, 124, +53, 38, 96, 77, 116, 142, 5, 226, 187, 141, 4, 203, 83, +26, 179, 135, 35, 2, 129, 129, 0, 167, 166, 72, 158, 196, +43, 249, 9, 157, 192, 116, 83, 199, 48, 78, 245, 34, 115, +233, 110, 170, 190, 253, 93, 96, 212, 57, 135, 18, 7, 199, +109, 191, 143, 73, 141, 142, 135, 22, 242, 251, 239, 168, 204, +97, 17, 222, 114, 246, 154, 112, 92, 90, 171, 129, 101, 201, +139, 145, 83, 226, 23, 47, 111, 16, 136, 22, 189, 66, 179, +144, 143, 220, 190, 212, 7, 224, 93, 79, 254, 147, 110, 238, +44, 34, 27, 194, 147, 63, 2, 231, 227, 39, 62, 141, 107, +207, 95, 223, 50, 250, 176, 14, 108, 220, 57, 140, 100, 230, +213, 191, 171, 3, 138, 78, 165, 103, 1, 87, 56, 148, 4, +174, 51, 5, 87, 61, 71, 2, 129, 128, 1, 220, 219, 121, +40, 111, 208, 225, 206, 96, 40, 224, 176, 218, 244, 153, 228, +34, 230, 83, 53, 37, 104, 40, 45, 198, 160, 178, 46, 215, +154, 99, 54, 232, 254, 15, 235, 74, 85, 54, 145, 23, 118, +45, 71, 221, 24, 186, 28, 214, 73, 162, 12, 204, 57, 228, +8, 246, 6, 216, 170, 157, 219, 99, 102, 152, 188, 47, 153, +34, 205, 235, 204, 255, 51, 168, 136, 163, 240, 48, 143, 186, +48, 84, 199, 137, 38, 42, 167, 222, 88, 252, 239, 234, 213, +58, 95, 217, 118, 225, 108, 155, 221, 15, 193, 40, 214, 164, +170, 75, 189, 213, 145, 216, 128, 12, 7, 138, 111, 68, 82, +165, 36, 106, 189, 251, 83, 216, 2, 2}; + diff --git a/crypto/test/rsaperf/rsa3e2048_1.pem b/crypto/test/rsaperf/rsa3e2048_1.pem new file mode 100644 index 0000000..78fc1c1 --- /dev/null +++ b/crypto/test/rsaperf/rsa3e2048_1.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,B90CE61B43365E59 + +j7MlE1go5Q9AqkwwrybeJE30B4jFbspvLR7YRdepi9SqJAagbR8ZKEjLRxXNyLTC +bNRJaP/Sz04kmtJkmYAlhbyHQvVnuSsqi4SNXLX5KxTVaX05FvHpU15VZX4xMM6f +ct0yBqo99grMtOGCeGsA+9EZACbc077usjcF6Ea7/EAzHliNugWO0JXP1DBsyeVD +1OX5l+vvx3UfZKkanU2E8Qns8B+PBAO85DM+s3T6UStFYbOEjs1wEQhn0bKyugUY +AQ9a3tLD1nmn6IzR3uCJW7d+5SDZHdJH0hjcNSfyniGMZFmjC14g4K9qsf+Sp9nE +RplC/CmhWhd2W3lSbD/z+uFO8JEKLbMM39vqOLXOJaQICQ1rlqY8laqiuNKdcjW1 +KlxyrGpmYNGbbdLvxHK53jfnMUVD8seR5Hu/hMfq5in8VoTyL68J5O/imA9WaP1J +lCrvUGmaOFYijH0NtZec9rcKsh8hIuOEcQHiUmDvKx7jE2qo1iUySDsBqHVXx66p +txnHQWb2msFI+x/JMdlIVSsISuONOLTMgp0/mX2cViJHFxPm8oo3OkAAumuMqROW +OBr5gFAiHBoxLJNpaTkDPPe/Ft8vJP9WXmApWqRjo4fcrCAp9dmLDmzO7qjzy0c+ +dFjlF+cZV7T/gNEsxFrAxEd2GVchSWhrPnrVQAJF4Aa0o4kq3zibkD6H9PHGeJu/ +EkZIFez63HiClXfkUwYCdMH03EE83VVKdgHk76CBHpeoZ44V7aJR67IOCYZcfAh6 +QH514o5STDSrd5LUWQAVUj6qUWKZ6PGV2nOJhG5V0p+Z8xop6y2HpYCMzGFfJQ+h +K0l5s2gm5XekPECU21EKs3sIYosJ9/H8NJFVedoUS2Cbjg/3oZkB2pamXdD1kqXk +8gn2fgL+FsVOoLcmLIv+1iYpb3GYZT8FcaNnguCrXOwMv000q86jbLg5C4Lb/FHr +uTIJXRnJCckoTfOJTVynokrUUQfPlgb0z7U+Slm6wL1M9+VilytY7FLSjgUalIf0 +YdUiqpoOqzrjmVJLD4esCI2V2GLhst7WBRuycSEDZ3g9Abpp1FyleiVfNmvSpNGs +6Om1ybFMwJpqJYnqgAVO8IhkIYwaN1/JLf6XLaba3nYSMixQjxfYZyoEdxM5fU49 +VRxY6WvqekLxgaoXTwzb+3l69ip4EhLVSVvh8+S1ur1r/+b+LSUbrBMj5P6doZJr +ortR7iRgy+O92aIrwcdNGm07hgZfDqGzrB+wtFJfhvbGwCMjGUZoB6et9y6ZaKKS +LBHK2UFrkF1/e2GA1eENAEhJVDerWHRZlCufC2Aug967epdW8k/SQQ7E7Wrrg4rs +fcjL0m1vqHZj9yjqdOPkKzLYvB4d9WNCfAgC0xu3Cl1+2o6WAxEhSHABreuDjYuw +BA56WAtVuW0WWhRqDDnUfX51HCyR5QKHzliAxXkNJQktJnqsZn7L/veovD4vxtqs +M07pxEsQHXzruAHUs3lHm8DPX17K9hcKOxf2mTfEvzRrrkKkG8/OpzJeUVYezPb4 +HyaRXdGfqyvIH2fu5I6xGbpRuTNsMrHVNcSbUNKpJJDFhuFW15ZcYw== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa3e4096.h b/crypto/test/rsaperf/rsa3e4096.h new file mode 100644 index 0000000..c36d3a5 --- /dev/null +++ b/crypto/test/rsaperf/rsa3e4096.h @@ -0,0 +1,189 @@ +/** + * @file rsa3e4096.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa3e4096[] = { +48, 130, 9, 40, 2, 1, 0, 2, 130, 2, 1, 0, 196, +10, 79, 182, 61, 203, 67, 111, 134, 91, 248, 85, 91, 192, +90, 81, 105, 70, 156, 255, 105, 54, 177, 207, 78, 202, 64, +102, 243, 91, 223, 46, 121, 53, 113, 206, 233, 161, 166, 205, +14, 25, 49, 4, 152, 185, 111, 159, 219, 255, 210, 125, 145, +71, 82, 122, 211, 45, 19, 114, 246, 15, 184, 77, 77, 127, +206, 55, 82, 55, 56, 195, 43, 143, 19, 191, 94, 247, 97, +155, 150, 41, 152, 176, 37, 101, 12, 189, 148, 252, 0, 163, +31, 239, 137, 227, 123, 87, 214, 209, 212, 49, 15, 61, 240, +101, 55, 251, 198, 194, 172, 243, 76, 63, 55, 177, 157, 119, +119, 68, 214, 239, 242, 211, 192, 120, 108, 11, 229, 142, 73, +254, 25, 187, 195, 24, 125, 111, 127, 87, 207, 230, 223, 93, +84, 186, 70, 8, 177, 130, 252, 185, 163, 151, 123, 176, 246, +37, 30, 84, 45, 189, 139, 3, 141, 107, 172, 119, 115, 82, +93, 6, 6, 142, 222, 56, 67, 144, 98, 178, 225, 22, 98, +213, 24, 85, 230, 40, 176, 215, 237, 8, 155, 211, 165, 192, +152, 90, 153, 199, 72, 61, 166, 132, 126, 6, 236, 217, 125, +57, 165, 234, 6, 178, 97, 131, 166, 123, 133, 116, 11, 244, +8, 95, 24, 88, 149, 20, 136, 66, 215, 117, 87, 89, 40, +104, 173, 111, 9, 19, 117, 244, 203, 126, 228, 248, 97, 100, +60, 60, 9, 119, 166, 179, 11, 106, 215, 204, 115, 80, 51, +135, 174, 210, 219, 238, 16, 101, 78, 83, 195, 215, 76, 75, +193, 170, 237, 83, 71, 142, 229, 103, 140, 163, 231, 97, 101, +99, 28, 216, 65, 235, 194, 0, 118, 217, 170, 172, 57, 200, +71, 31, 118, 200, 17, 14, 217, 223, 16, 111, 117, 98, 242, +103, 54, 173, 94, 37, 113, 64, 16, 182, 215, 216, 190, 70, +246, 166, 141, 163, 61, 19, 93, 232, 229, 114, 200, 30, 117, +70, 91, 206, 250, 197, 51, 68, 106, 14, 123, 115, 53, 47, +254, 163, 145, 188, 117, 141, 17, 233, 249, 137, 145, 30, 185, +171, 154, 72, 70, 131, 60, 43, 72, 95, 90, 47, 59, 98, +77, 217, 231, 135, 74, 248, 165, 139, 87, 44, 158, 243, 67, +15, 222, 154, 254, 47, 97, 12, 96, 222, 196, 172, 132, 174, +14, 211, 232, 140, 186, 157, 62, 144, 147, 135, 165, 82, 228, +211, 103, 242, 79, 217, 242, 157, 110, 22, 27, 23, 149, 57, +208, 28, 230, 124, 23, 240, 44, 68, 101, 138, 93, 107, 95, +103, 92, 149, 127, 40, 1, 57, 16, 13, 116, 142, 148, 15, +174, 22, 59, 164, 112, 224, 229, 125, 103, 164, 3, 221, 211, +232, 158, 1, 205, 140, 66, 123, 47, 243, 41, 155, 176, 142, +214, 133, 172, 176, 72, 184, 207, 124, 90, 74, 3, 102, 251, +77, 183, 177, 186, 59, 117, 81, 155, 20, 249, 196, 81, 232, +73, 49, 132, 205, 2, 1, 3, 2, 130, 2, 0, 32, 172, +98, 158, 95, 161, 224, 146, 150, 100, 169, 99, 143, 74, 185, +184, 60, 54, 111, 127, 230, 222, 114, 247, 226, 119, 10, 187, +211, 57, 250, 135, 190, 222, 61, 162, 124, 69, 155, 204, 215, +174, 221, 128, 196, 30, 231, 239, 249, 255, 248, 106, 66, 225, +56, 105, 205, 220, 216, 147, 41, 2, 158, 183, 140, 234, 162, +94, 141, 179, 222, 203, 49, 237, 45, 245, 58, 126, 144, 68, +153, 6, 238, 200, 6, 59, 130, 31, 152, 212, 170, 197, 218, +167, 236, 80, 148, 142, 163, 205, 163, 93, 130, 138, 82, 187, +137, 84, 161, 32, 114, 40, 140, 181, 51, 242, 239, 147, 233, +54, 35, 210, 168, 120, 160, 20, 18, 1, 251, 151, 182, 255, +174, 244, 160, 132, 20, 231, 234, 142, 162, 166, 122, 143, 142, +31, 11, 172, 29, 149, 212, 201, 155, 67, 233, 242, 211, 176, +218, 99, 92, 244, 236, 128, 151, 145, 242, 19, 232, 141, 186, +43, 171, 194, 122, 94, 181, 237, 101, 200, 122, 217, 16, 120, +217, 99, 166, 92, 29, 121, 82, 44, 25, 248, 155, 160, 25, +100, 110, 246, 140, 10, 70, 107, 106, 86, 124, 206, 234, 52, +70, 81, 171, 200, 101, 149, 241, 20, 150, 62, 1, 254, 1, +101, 46, 185, 110, 46, 22, 181, 206, 147, 142, 142, 220, 17, +114, 61, 44, 45, 232, 254, 33, 234, 123, 126, 186, 230, 10, +10, 1, 147, 241, 29, 215, 60, 46, 141, 188, 60, 229, 181, +32, 30, 101, 61, 174, 238, 138, 216, 38, 131, 62, 205, 144, +116, 238, 20, 194, 190, 27, 237, 138, 11, 176, 71, 253, 41, +228, 130, 242, 19, 114, 45, 126, 230, 37, 113, 149, 245, 172, +203, 101, 232, 185, 119, 79, 161, 17, 113, 250, 207, 169, 12, +88, 230, 225, 156, 72, 230, 251, 82, 94, 241, 9, 11, 48, +161, 243, 121, 18, 241, 243, 246, 194, 73, 221, 221, 5, 108, +185, 212, 125, 103, 146, 165, 10, 23, 183, 2, 192, 121, 74, +94, 156, 247, 113, 62, 172, 91, 197, 125, 40, 192, 251, 201, +63, 32, 52, 225, 220, 154, 246, 58, 199, 118, 214, 155, 128, +98, 62, 100, 73, 155, 222, 72, 30, 5, 51, 190, 198, 60, +138, 103, 190, 79, 36, 69, 253, 9, 148, 0, 224, 171, 84, +128, 86, 208, 78, 186, 189, 187, 199, 242, 24, 78, 244, 173, +51, 29, 210, 89, 2, 189, 107, 70, 100, 139, 226, 48, 84, +220, 96, 44, 235, 142, 41, 101, 227, 218, 235, 229, 125, 121, +185, 112, 34, 116, 241, 98, 139, 186, 242, 189, 50, 81, 136, +232, 144, 51, 70, 210, 26, 210, 235, 45, 2, 36, 147, 244, +62, 240, 93, 223, 58, 135, 192, 169, 93, 158, 63, 124, 7, +217, 100, 10, 111, 216, 125, 38, 58, 197, 20, 241, 117, 206, +58, 232, 39, 132, 145, 166, 97, 244, 8, 97, 189, 200, 2, +78, 237, 11, 2, 130, 1, 1, 0, 214, 105, 214, 101, 192, +224, 6, 131, 183, 239, 75, 224, 61, 56, 234, 46, 107, 12, +81, 164, 44, 163, 156, 154, 25, 244, 155, 134, 95, 152, 134, +192, 40, 167, 47, 119, 48, 228, 38, 127, 27, 178, 134, 18, +223, 205, 235, 242, 105, 190, 166, 158, 142, 107, 99, 203, 235, +123, 223, 137, 44, 38, 253, 167, 35, 66, 30, 116, 225, 54, +223, 126, 51, 98, 172, 215, 11, 131, 93, 68, 186, 40, 77, +174, 224, 254, 174, 186, 157, 160, 89, 182, 199, 184, 207, 75, +122, 218, 20, 245, 51, 163, 37, 179, 189, 19, 240, 19, 179, +244, 152, 140, 80, 132, 108, 54, 157, 7, 118, 252, 229, 146, +110, 32, 129, 74, 167, 140, 251, 61, 55, 117, 20, 152, 161, +122, 174, 211, 108, 62, 20, 65, 37, 106, 72, 40, 236, 109, +218, 179, 235, 199, 97, 81, 70, 41, 90, 207, 248, 62, 76, +56, 8, 4, 48, 134, 57, 109, 204, 44, 71, 193, 105, 232, +94, 17, 2, 124, 221, 25, 16, 25, 61, 230, 102, 168, 45, +97, 195, 108, 211, 40, 176, 225, 194, 168, 191, 53, 61, 152, +223, 38, 145, 84, 233, 238, 26, 120, 226, 188, 58, 248, 134, +100, 14, 194, 253, 32, 154, 81, 59, 75, 148, 112, 82, 226, +31, 2, 70, 193, 88, 26, 201, 116, 189, 199, 22, 246, 120, +205, 105, 214, 150, 34, 46, 159, 43, 78, 249, 73, 187, 3, +56, 100, 60, 157, 2, 130, 1, 1, 0, 234, 16, 51, 125, +16, 104, 231, 152, 196, 140, 170, 237, 208, 9, 242, 149, 104, +110, 13, 73, 44, 51, 26, 128, 35, 225, 180, 215, 102, 24, +239, 167, 153, 31, 101, 255, 228, 11, 86, 245, 174, 80, 47, +243, 90, 141, 39, 97, 78, 132, 85, 122, 25, 88, 48, 185, +16, 161, 65, 186, 232, 84, 190, 47, 9, 134, 127, 189, 166, +204, 243, 92, 165, 106, 30, 144, 154, 156, 250, 114, 218, 200, +7, 11, 31, 213, 91, 157, 37, 197, 211, 201, 105, 169, 227, +12, 197, 145, 206, 250, 154, 113, 226, 15, 155, 134, 172, 133, +30, 255, 134, 250, 184, 179, 164, 82, 229, 247, 54, 105, 78, +42, 221, 107, 239, 226, 233, 196, 116, 157, 107, 152, 83, 225, +252, 41, 241, 89, 28, 22, 115, 39, 77, 59, 4, 126, 84, +60, 57, 29, 243, 227, 128, 235, 134, 0, 137, 11, 27, 58, +220, 140, 45, 59, 49, 61, 168, 191, 30, 67, 120, 14, 222, +47, 116, 225, 162, 241, 181, 130, 35, 199, 208, 130, 111, 98, +65, 43, 64, 135, 221, 65, 168, 8, 7, 3, 4, 234, 40, +141, 153, 124, 73, 27, 222, 6, 42, 19, 1, 217, 188, 9, +213, 203, 21, 156, 157, 48, 72, 251, 112, 175, 99, 117, 224, +196, 136, 107, 13, 176, 81, 139, 23, 34, 59, 228, 110, 199, +191, 170, 236, 106, 54, 253, 220, 204, 36, 13, 206, 48, 36, +53, 2, 243, 185, 241, 2, 130, 1, 1, 0, 142, 241, 57, +153, 43, 64, 4, 87, 207, 244, 221, 64, 40, 208, 156, 30, +242, 8, 54, 109, 115, 23, 189, 188, 17, 77, 189, 4, 63, +187, 4, 128, 27, 26, 31, 164, 203, 66, 196, 84, 189, 33, +174, 183, 63, 222, 157, 76, 70, 127, 25, 191, 9, 156, 237, +50, 156, 253, 63, 176, 200, 25, 254, 111, 108, 214, 190, 248, +150, 36, 148, 254, 204, 236, 115, 58, 7, 172, 232, 216, 124, +26, 222, 116, 149, 255, 31, 39, 19, 192, 59, 207, 47, 208, +138, 50, 81, 230, 184, 163, 119, 194, 25, 34, 126, 13, 74, +183, 205, 77, 187, 8, 53, 173, 157, 121, 190, 4, 249, 253, +238, 97, 158, 192, 86, 49, 197, 8, 167, 126, 36, 248, 184, +101, 192, 252, 116, 140, 242, 212, 13, 128, 195, 156, 48, 27, +72, 73, 60, 119, 242, 132, 235, 139, 132, 27, 145, 223, 250, +212, 50, 208, 5, 88, 32, 89, 123, 158, 136, 29, 133, 43, +155, 240, 62, 182, 1, 168, 147, 102, 10, 187, 126, 153, 153, +197, 115, 150, 130, 72, 140, 197, 203, 65, 44, 112, 127, 120, +211, 187, 63, 111, 11, 141, 241, 73, 102, 251, 65, 210, 209, +251, 4, 66, 180, 129, 254, 21, 188, 54, 39, 135, 184, 74, +225, 236, 20, 172, 47, 43, 144, 17, 219, 163, 41, 47, 100, +164, 80, 136, 241, 57, 185, 108, 31, 20, 199, 137, 251, 134, +124, 172, 208, 66, 211, 19, 2, 130, 1, 1, 0, 156, 10, +204, 254, 10, 240, 154, 101, 216, 93, 199, 73, 53, 91, 247, +14, 69, 158, 179, 134, 29, 119, 103, 0, 23, 235, 205, 228, +238, 187, 74, 111, 187, 106, 67, 255, 237, 92, 228, 163, 201, +138, 202, 162, 60, 94, 26, 64, 223, 2, 227, 166, 187, 144, +32, 123, 96, 107, 129, 39, 69, 141, 212, 31, 91, 174, 255, +211, 196, 136, 162, 61, 195, 156, 20, 96, 103, 19, 81, 161, +231, 48, 4, 178, 21, 56, 231, 190, 25, 46, 141, 48, 241, +27, 236, 179, 46, 97, 52, 167, 17, 161, 65, 95, 189, 4, +115, 3, 105, 255, 175, 81, 208, 119, 194, 225, 238, 164, 206, +240, 222, 199, 62, 71, 245, 65, 241, 45, 163, 19, 157, 16, +55, 235, 253, 113, 75, 144, 189, 100, 76, 196, 222, 39, 88, +84, 56, 40, 38, 19, 247, 237, 0, 157, 4, 0, 91, 92, +188, 209, 232, 93, 115, 124, 203, 126, 112, 127, 105, 130, 80, +9, 233, 116, 248, 150, 108, 161, 35, 172, 23, 218, 139, 1, +159, 150, 214, 28, 213, 175, 232, 214, 112, 5, 90, 2, 3, +70, 197, 179, 187, 168, 48, 189, 62, 174, 198, 183, 86, 145, +40, 6, 142, 135, 99, 189, 190, 32, 48, 167, 160, 116, 236, +249, 64, 131, 5, 156, 179, 202, 225, 7, 100, 193, 125, 66, +244, 133, 42, 113, 242, 241, 121, 254, 147, 50, 194, 179, 222, +202, 194, 206, 1, 247, 209, 75, 2, 130, 1, 1, 0, 178, +7, 156, 185, 173, 64, 76, 149, 109, 113, 73, 170, 62, 188, +221, 7, 226, 161, 226, 35, 150, 199, 85, 124, 252, 137, 213, +46, 171, 210, 141, 56, 236, 208, 46, 164, 191, 175, 179, 109, +13, 81, 99, 229, 181, 189, 223, 109, 168, 91, 135, 38, 135, +168, 28, 194, 6, 19, 158, 254, 224, 242, 65, 184, 121, 95, +198, 104, 4, 88, 108, 16, 69, 40, 218, 196, 228, 174, 93, +195, 253, 47, 221, 63, 75, 177, 102, 136, 30, 93, 254, 212, +86, 244, 177, 188, 32, 130, 194, 118, 202, 174, 142, 148, 59, +201, 53, 116, 105, 193, 166, 125, 11, 23, 35, 218, 209, 245, +254, 114, 88, 65, 123, 129, 103, 149, 80, 41, 149, 116, 234, +44, 10, 6, 111, 144, 175, 235, 228, 213, 146, 197, 198, 220, +101, 166, 193, 6, 156, 147, 177, 203, 248, 85, 143, 58, 97, +58, 54, 14, 141, 61, 31, 81, 73, 7, 164, 126, 135, 184, +236, 64, 200, 171, 230, 231, 216, 88, 148, 85, 218, 220, 250, +247, 80, 166, 24, 161, 153, 171, 183, 201, 116, 250, 96, 220, +248, 191, 216, 135, 134, 0, 158, 183, 208, 178, 73, 28, 193, +80, 154, 218, 116, 234, 10, 110, 241, 2, 204, 168, 121, 47, +26, 126, 142, 167, 200, 84, 31, 21, 21, 179, 127, 27, 28, +235, 167, 156, 208, 191, 187, 55, 125, 30, 38, 75, 183, 28, +190, 33, 193, 58, 67, 217, 81, 161}; + diff --git a/crypto/test/rsaperf/rsa3e4096.pem b/crypto/test/rsaperf/rsa3e4096.pem new file mode 100644 index 0000000..74eaaf8 --- /dev/null +++ b/crypto/test/rsaperf/rsa3e4096.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKAIBAAKCAgEAxApPtj3LQ2+GW/hVW8BaUWlGnP9pNrHPTspAZvNb3y55NXHO +6aGmzQ4ZMQSYuW+f2//SfZFHUnrTLRNy9g+4TU1/zjdSNzjDK48Tv173YZuWKZiw +JWUMvZT8AKMf74nje1fW0dQxDz3wZTf7xsKs80w/N7Gdd3dE1u/y08B4bAvljkn+ +GbvDGH1vf1fP5t9dVLpGCLGC/Lmjl3uw9iUeVC29iwONa6x3c1JdBgaO3jhDkGKy +4RZi1RhV5iiw1+0Im9OlwJhamcdIPaaEfgbs2X05peoGsmGDpnuFdAv0CF8YWJUU +iELXdVdZKGitbwkTdfTLfuT4YWQ8PAl3prMLatfMc1Azh67S2+4QZU5Tw9dMS8Gq +7VNHjuVnjKPnYWVjHNhB68IAdtmqrDnIRx92yBEO2d8Qb3Vi8mc2rV4lcUAQttfY +vkb2po2jPRNd6OVyyB51RlvO+sUzRGoOe3M1L/6jkbx1jRHp+YmRHrmrmkhGgzwr +SF9aLztiTdnnh0r4pYtXLJ7zQw/emv4vYQxg3sSshK4O0+iMup0+kJOHpVLk02fy +T9nynW4WGxeVOdAc5nwX8CxEZYpda19nXJV/KAE5EA10jpQPrhY7pHDg5X1npAPd +0+ieAc2MQnsv8ymbsI7WhaywSLjPfFpKA2b7Tbexujt1UZsU+cRR6EkxhM0CAQMC +ggIAIKxinl+h4JKWZKljj0q5uDw2b3/m3nL34ncKu9M5+oe+3j2ifEWbzNeu3YDE +Hufv+f/4akLhOGnN3NiTKQKet4zqol6Ns97LMe0t9Tp+kESZBu7IBjuCH5jUqsXa +p+xQlI6jzaNdgopSu4lUoSByKIy1M/Lvk+k2I9KoeKAUEgH7l7b/rvSghBTn6o6i +pnqPjh8LrB2V1MmbQ+ny07DaY1z07ICXkfIT6I26K6vCel617WXIetkQeNljplwd +eVIsGfiboBlkbvaMCkZralZ8zuo0RlGryGWV8RSWPgH+AWUuuW4uFrXOk46O3BFy +PSwt6P4h6nt+uuYKCgGT8R3XPC6NvDzltSAeZT2u7orYJoM+zZB07hTCvhvtiguw +R/0p5ILyE3ItfuYlcZX1rMtl6Ll3T6ERcfrPqQxY5uGcSOb7Ul7xCQswofN5EvHz +9sJJ3d0FbLnUfWeSpQoXtwLAeUpenPdxPqxbxX0owPvJPyA04dya9jrHdtabgGI+ +ZEmb3kgeBTO+xjyKZ75PJEX9CZQA4KtUgFbQTrq9u8fyGE70rTMd0lkCvWtGZIvi +MFTcYCzrjill49rr5X15uXAidPFii7ryvTJRiOiQM0bSGtLrLQIkk/Q+8F3fOofA +qV2eP3wH2WQKb9h9JjrFFPF1zjroJ4SRpmH0CGG9yAJO7QsCggEBANZp1mXA4AaD +t+9L4D046i5rDFGkLKOcmhn0m4ZfmIbAKKcvdzDkJn8bsoYS383r8mm+pp6Oa2PL +63vfiSwm/acjQh504TbffjNirNcLg11EuihNruD+rrqdoFm2x7jPS3raFPUzoyWz +vRPwE7P0mIxQhGw2nQd2/OWSbiCBSqeM+z03dRSYoXqu02w+FEElakgo7G3as+vH +YVFGKVrP+D5MOAgEMIY5bcwsR8Fp6F4RAnzdGRAZPeZmqC1hw2zTKLDhwqi/NT2Y +3yaRVOnuGnjivDr4hmQOwv0gmlE7S5RwUuIfAkbBWBrJdL3HFvZ4zWnWliIunytO ++Um7AzhkPJ0CggEBAOoQM30QaOeYxIyq7dAJ8pVobg1JLDMagCPhtNdmGO+nmR9l +/+QLVvWuUC/zWo0nYU6EVXoZWDC5EKFBuuhUvi8Jhn+9pszzXKVqHpCanPpy2sgH +Cx/VW50lxdPJaanjDMWRzvqaceIPm4ashR7/hvq4s6RS5fc2aU4q3Wvv4unEdJ1r +mFPh/CnxWRwWcydNOwR+VDw5HfPjgOuGAIkLGzrcjC07MT2ovx5DeA7eL3ThovG1 +giPH0IJvYkErQIfdQagIBwME6iiNmXxJG94GKhMB2bwJ1csVnJ0wSPtwr2N14MSI +aw2wUYsXIjvkbse/quxqNv3czCQNzjAkNQLzufECggEBAI7xOZkrQARXz/TdQCjQ +nB7yCDZtcxe9vBFNvQQ/uwSAGxofpMtCxFS9Ia63P96dTEZ/Gb8JnO0ynP0/sMgZ +/m9s1r74liSU/szsczoHrOjYfBredJX/HycTwDvPL9CKMlHmuKN3whkifg1Kt81N +uwg1rZ15vgT5/e5hnsBWMcUIp34k+LhlwPx0jPLUDYDDnDAbSEk8d/KE64uEG5Hf ++tQy0AVYIFl7nogdhSub8D62AaiTZgq7fpmZxXOWgkiMxctBLHB/eNO7P28LjfFJ +ZvtB0tH7BEK0gf4VvDYnh7hK4ewUrC8rkBHboykvZKRQiPE5uWwfFMeJ+4Z8rNBC +0xMCggEBAJwKzP4K8Jpl2F3HSTVb9w5FnrOGHXdnABfrzeTuu0pvu2pD/+1c5KPJ +isqiPF4aQN8C46a7kCB7YGuBJ0WN1B9brv/TxIiiPcOcFGBnE1Gh5zAEshU4574Z +Lo0w8Rvssy5hNKcRoUFfvQRzA2n/r1HQd8Lh7qTO8N7HPkf1QfEtoxOdEDfr/XFL +kL1kTMTeJ1hUOCgmE/ftAJ0EAFtcvNHoXXN8y35wf2mCUAnpdPiWbKEjrBfaiwGf +ltYc1a/o1nAFWgIDRsWzu6gwvT6uxrdWkSgGjodjvb4gMKegdOz5QIMFnLPK4Qdk +wX1C9IUqcfLxef6TMsKz3srCzgH30UsCggEBALIHnLmtQEyVbXFJqj683QfioeIj +lsdVfPyJ1S6r0o047NAupL+vs20NUWPltb3fbahbhyaHqBzCBhOe/uDyQbh5X8Zo +BFhsEEUo2sTkrl3D/S/dP0uxZogeXf7UVvSxvCCCwnbKro6UO8k1dGnBpn0LFyPa +0fX+clhBe4FnlVAplXTqLAoGb5Cv6+TVksXG3GWmwQack7HL+FWPOmE6Ng6NPR9R +SQekfoe47EDIq+bn2FiUVdrc+vdQphihmau3yXT6YNz4v9iHhgCet9CySRzBUJra +dOoKbvECzKh5Lxp+jqfIVB8VFbN/Gxzrp5zQv7s3fR4mS7ccviHBOkPZUaE= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa3e4096_1.h b/crypto/test/rsaperf/rsa3e4096_1.h new file mode 100644 index 0000000..766d1fb --- /dev/null +++ b/crypto/test/rsaperf/rsa3e4096_1.h @@ -0,0 +1,189 @@ +/** + * @file rsa3e4096_1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa3e40961[] = { +48, 130, 9, 40, 2, 1, 0, 2, 130, 2, 1, 0, 185, +105, 144, 146, 32, 122, 51, 27, 227, 27, 31, 129, 225, 75, +134, 134, 215, 122, 217, 162, 33, 164, 190, 222, 205, 106, 205, +62, 117, 24, 37, 128, 194, 184, 251, 219, 91, 37, 239, 200, +162, 30, 220, 88, 156, 91, 67, 22, 115, 74, 207, 6, 66, +193, 76, 172, 87, 244, 174, 189, 224, 49, 147, 47, 205, 146, +232, 163, 216, 25, 8, 19, 8, 50, 66, 22, 43, 100, 53, +242, 155, 237, 241, 75, 85, 6, 176, 71, 23, 60, 19, 227, +100, 100, 145, 54, 165, 81, 40, 23, 193, 57, 181, 193, 63, +56, 219, 55, 86, 236, 106, 142, 70, 217, 138, 165, 143, 243, +173, 161, 182, 31, 210, 238, 135, 8, 51, 195, 149, 77, 100, +162, 76, 57, 138, 219, 255, 167, 70, 167, 234, 123, 154, 238, +27, 237, 48, 22, 193, 145, 247, 238, 233, 131, 13, 71, 242, +216, 10, 54, 44, 53, 112, 71, 253, 107, 90, 166, 78, 103, +217, 177, 184, 205, 200, 140, 244, 84, 121, 230, 139, 137, 206, +129, 146, 64, 196, 238, 5, 66, 4, 130, 135, 79, 13, 41, +124, 165, 188, 119, 14, 84, 146, 77, 143, 99, 171, 10, 6, +79, 214, 169, 16, 44, 126, 245, 41, 81, 5, 202, 221, 41, +178, 21, 115, 166, 57, 77, 57, 54, 95, 132, 41, 69, 209, +91, 86, 115, 69, 219, 124, 120, 102, 226, 202, 120, 218, 48, +80, 114, 156, 246, 22, 47, 175, 74, 57, 70, 82, 19, 37, +62, 92, 213, 44, 220, 11, 166, 33, 200, 205, 213, 221, 197, +12, 180, 77, 47, 77, 157, 171, 25, 136, 64, 49, 134, 134, +1, 4, 118, 148, 36, 5, 223, 89, 187, 103, 117, 143, 86, +137, 160, 38, 166, 254, 89, 96, 132, 76, 74, 242, 116, 4, +196, 46, 203, 103, 173, 168, 199, 134, 64, 46, 18, 102, 244, +138, 139, 202, 196, 156, 64, 156, 139, 156, 130, 208, 109, 97, +129, 182, 73, 51, 189, 193, 1, 12, 194, 146, 242, 227, 57, +110, 107, 1, 14, 183, 234, 222, 131, 63, 95, 193, 34, 161, +86, 220, 155, 226, 138, 96, 239, 26, 160, 137, 10, 229, 228, +246, 26, 72, 100, 88, 85, 236, 229, 235, 220, 50, 189, 97, +210, 111, 42, 106, 17, 88, 54, 243, 108, 36, 203, 127, 41, +14, 130, 157, 247, 72, 37, 243, 75, 252, 55, 2, 138, 98, +128, 35, 111, 244, 251, 38, 2, 160, 55, 219, 238, 247, 74, +172, 9, 151, 21, 34, 87, 150, 147, 231, 158, 113, 240, 39, +171, 69, 38, 144, 243, 30, 106, 243, 82, 157, 115, 25, 167, +249, 23, 166, 172, 72, 6, 17, 36, 184, 101, 142, 94, 38, +116, 116, 22, 212, 54, 214, 219, 210, 50, 19, 76, 12, 245, +102, 39, 47, 73, 35, 205, 116, 233, 113, 130, 84, 243, 203, +31, 94, 209, 95, 4, 20, 102, 216, 2, 6, 56, 106, 245, +237, 158, 85, 175, 2, 1, 3, 2, 130, 2, 0, 30, 230, +237, 109, 176, 20, 93, 217, 251, 47, 47, 234, 250, 225, 235, +193, 35, 233, 206, 240, 90, 240, 202, 122, 119, 145, 204, 223, +190, 46, 176, 234, 203, 30, 212, 164, 143, 48, 253, 76, 27, +5, 36, 185, 111, 100, 139, 46, 104, 140, 119, 214, 96, 117, +140, 199, 99, 254, 29, 31, 165, 93, 152, 135, 247, 152, 124, +27, 78, 174, 214, 173, 214, 179, 11, 3, 177, 230, 8, 253, +196, 167, 168, 55, 56, 214, 114, 182, 131, 223, 88, 165, 230, +16, 194, 222, 112, 226, 220, 3, 245, 137, 158, 74, 223, 222, +207, 51, 227, 210, 17, 194, 97, 36, 65, 198, 66, 168, 156, +240, 73, 5, 77, 210, 107, 214, 179, 75, 67, 140, 230, 27, +12, 180, 65, 207, 85, 70, 139, 198, 167, 20, 153, 210, 89, +252, 221, 89, 32, 66, 254, 167, 209, 149, 215, 139, 253, 206, +172, 94, 92, 179, 146, 182, 170, 60, 143, 27, 183, 187, 249, +157, 158, 204, 246, 194, 40, 184, 190, 251, 193, 236, 77, 21, +152, 96, 32, 210, 86, 53, 171, 107, 22, 141, 44, 220, 63, +112, 244, 190, 130, 99, 109, 183, 151, 229, 241, 215, 1, 13, +78, 113, 130, 178, 21, 40, 220, 56, 43, 161, 207, 134, 243, +3, 147, 70, 94, 226, 52, 51, 186, 150, 6, 224, 248, 57, +227, 189, 224, 249, 234, 20, 17, 37, 204, 105, 121, 178, 184, +19, 26, 41, 3, 178, 157, 54, 192, 198, 18, 169, 195, 155, +132, 47, 179, 212, 156, 221, 44, 158, 49, 129, 174, 113, 176, +202, 177, 179, 252, 249, 226, 58, 208, 151, 183, 51, 17, 19, +80, 134, 94, 212, 150, 225, 125, 127, 162, 252, 114, 141, 253, +6, 30, 91, 129, 109, 73, 32, 138, 183, 36, 238, 224, 158, +206, 21, 182, 16, 67, 13, 229, 242, 106, 210, 159, 186, 49, +185, 241, 90, 224, 105, 151, 14, 253, 170, 140, 250, 211, 153, +124, 64, 7, 134, 17, 62, 98, 83, 218, 139, 27, 130, 2, +101, 214, 13, 45, 171, 234, 228, 49, 163, 208, 78, 215, 196, +82, 40, 93, 15, 218, 97, 243, 226, 219, 217, 244, 156, 27, +42, 55, 135, 12, 160, 146, 234, 225, 175, 12, 205, 203, 189, +171, 4, 160, 205, 58, 102, 186, 68, 124, 185, 101, 39, 34, +46, 60, 177, 69, 83, 126, 165, 207, 243, 243, 86, 188, 153, +200, 154, 38, 130, 65, 127, 43, 115, 21, 74, 180, 99, 5, +168, 150, 161, 208, 167, 82, 6, 3, 98, 92, 89, 134, 152, +105, 136, 43, 70, 219, 44, 141, 218, 144, 246, 112, 112, 103, +78, 227, 63, 166, 143, 32, 52, 182, 176, 230, 98, 56, 79, +74, 14, 33, 33, 199, 30, 116, 11, 38, 202, 20, 172, 33, +174, 75, 183, 245, 171, 205, 65, 240, 123, 107, 8, 178, 36, +237, 165, 32, 207, 46, 159, 248, 173, 15, 217, 213, 1, 55, +200, 65, 139, 2, 130, 1, 1, 0, 232, 84, 126, 210, 174, +247, 251, 105, 204, 68, 114, 68, 116, 75, 236, 255, 194, 250, +218, 155, 41, 67, 106, 174, 218, 70, 107, 232, 81, 124, 123, +153, 111, 73, 92, 223, 135, 174, 193, 141, 142, 45, 165, 149, +74, 4, 98, 15, 2, 163, 116, 134, 78, 11, 184, 133, 251, +73, 244, 198, 118, 234, 42, 35, 230, 3, 230, 98, 42, 22, +188, 121, 163, 165, 21, 146, 204, 137, 148, 13, 72, 203, 22, +94, 173, 128, 127, 97, 85, 233, 14, 64, 131, 190, 80, 106, +159, 67, 133, 31, 208, 243, 239, 109, 171, 52, 64, 181, 39, +227, 97, 43, 71, 210, 14, 186, 233, 115, 82, 132, 201, 249, +177, 67, 177, 90, 217, 84, 119, 157, 14, 235, 127, 148, 44, +32, 23, 106, 201, 119, 84, 253, 44, 97, 98, 228, 3, 254, +221, 21, 224, 126, 97, 249, 118, 92, 247, 160, 139, 3, 82, +72, 55, 27, 220, 232, 84, 170, 234, 168, 194, 249, 155, 222, +54, 16, 239, 180, 78, 54, 176, 3, 10, 142, 140, 140, 69, +89, 58, 219, 190, 204, 97, 162, 152, 132, 65, 156, 184, 233, +199, 200, 92, 62, 212, 165, 229, 249, 182, 150, 1, 117, 145, +96, 158, 41, 191, 195, 144, 30, 23, 38, 214, 233, 112, 99, +79, 11, 68, 37, 48, 42, 123, 87, 164, 39, 217, 188, 82, +118, 85, 251, 130, 102, 244, 29, 197, 46, 159, 109, 224, 86, +44, 251, 78, 97, 2, 130, 1, 1, 0, 204, 77, 99, 69, +224, 161, 72, 77, 41, 155, 236, 50, 161, 199, 183, 204, 4, +32, 13, 88, 249, 179, 245, 19, 131, 114, 56, 201, 148, 215, +163, 243, 178, 6, 254, 72, 244, 231, 167, 48, 7, 93, 58, +109, 81, 119, 14, 114, 243, 38, 53, 58, 189, 244, 92, 84, +197, 193, 101, 130, 172, 97, 236, 80, 60, 141, 198, 192, 126, +128, 163, 182, 126, 254, 68, 52, 69, 168, 22, 118, 57, 193, +85, 138, 31, 72, 135, 56, 3, 161, 176, 138, 239, 241, 237, +194, 192, 196, 119, 159, 212, 239, 109, 188, 106, 84, 158, 148, +106, 217, 142, 126, 108, 89, 51, 232, 121, 220, 15, 106, 96, +66, 161, 217, 73, 223, 51, 62, 3, 199, 146, 214, 102, 86, +111, 64, 85, 163, 219, 202, 164, 209, 105, 111, 213, 143, 28, +63, 100, 87, 81, 81, 70, 55, 133, 12, 36, 222, 195, 126, +164, 157, 56, 183, 49, 5, 72, 92, 176, 220, 153, 53, 33, +26, 84, 5, 31, 149, 240, 52, 250, 108, 200, 193, 187, 74, +186, 191, 145, 25, 206, 125, 153, 189, 7, 174, 246, 15, 190, +27, 197, 117, 246, 239, 140, 5, 105, 238, 185, 170, 38, 155, +67, 56, 25, 152, 77, 168, 156, 7, 2, 200, 83, 166, 32, +137, 77, 6, 36, 212, 49, 156, 42, 6, 42, 117, 249, 3, +75, 203, 118, 247, 23, 194, 8, 137, 62, 197, 7, 175, 140, +152, 113, 241, 126, 15, 2, 130, 1, 1, 0, 154, 226, 255, +55, 31, 79, 252, 241, 50, 216, 76, 45, 162, 221, 72, 170, +129, 252, 145, 188, 198, 44, 241, 201, 230, 217, 157, 69, 139, +168, 82, 102, 74, 48, 232, 149, 5, 31, 43, 179, 180, 30, +110, 99, 134, 173, 150, 180, 172, 108, 248, 89, 137, 93, 37, +174, 167, 134, 163, 46, 249, 241, 113, 109, 68, 2, 153, 150, +198, 185, 210, 251, 194, 110, 14, 97, 221, 177, 13, 94, 48, +135, 100, 63, 30, 85, 170, 64, 227, 240, 180, 43, 2, 126, +224, 71, 20, 215, 174, 21, 53, 247, 244, 243, 199, 120, 43, +35, 111, 236, 235, 114, 47, 225, 95, 39, 70, 76, 225, 173, +219, 251, 203, 130, 118, 60, 144, 226, 250, 104, 180, 156, 255, +184, 29, 106, 186, 71, 48, 250, 56, 168, 200, 64, 236, 152, +2, 169, 232, 185, 64, 84, 65, 80, 249, 147, 79, 192, 92, +172, 225, 133, 122, 18, 147, 69, 141, 199, 71, 27, 44, 166, +103, 233, 121, 96, 159, 205, 137, 121, 202, 172, 177, 180, 93, +178, 216, 230, 39, 61, 41, 221, 150, 108, 101, 173, 129, 19, +37, 241, 47, 218, 232, 41, 227, 25, 67, 251, 207, 14, 171, +163, 182, 64, 105, 113, 42, 130, 96, 20, 15, 111, 57, 240, +245, 151, 138, 7, 130, 195, 117, 113, 167, 143, 194, 197, 59, +210, 225, 164, 57, 82, 86, 239, 77, 105, 46, 31, 20, 243, +234, 228, 29, 252, 222, 235, 2, 130, 1, 1, 0, 136, 51, +151, 131, 235, 22, 48, 51, 113, 18, 157, 119, 22, 133, 37, +50, 173, 106, 179, 144, 166, 119, 248, 183, 172, 246, 208, 134, +99, 58, 109, 77, 33, 89, 254, 219, 77, 239, 196, 202, 175, +147, 124, 72, 224, 250, 9, 161, 247, 110, 206, 39, 41, 77, +146, 227, 46, 128, 238, 87, 29, 150, 157, 138, 211, 9, 47, +42, 255, 0, 109, 36, 84, 169, 130, 205, 131, 197, 100, 78, +209, 43, 142, 92, 20, 219, 4, 208, 2, 107, 203, 7, 74, +161, 73, 44, 128, 130, 250, 106, 141, 244, 243, 210, 241, 141, +191, 13, 156, 145, 9, 169, 157, 144, 205, 69, 166, 146, 180, +241, 149, 129, 193, 59, 134, 148, 204, 212, 2, 133, 12, 142, +238, 228, 74, 42, 227, 194, 146, 135, 24, 139, 155, 159, 227, +180, 189, 127, 152, 58, 54, 54, 46, 207, 174, 8, 24, 148, +130, 84, 109, 190, 37, 207, 118, 3, 133, 147, 32, 147, 16, +206, 22, 17, 141, 88, 191, 185, 74, 205, 252, 72, 133, 214, +124, 220, 124, 127, 182, 17, 52, 83, 187, 211, 90, 116, 164, +10, 126, 189, 46, 78, 164, 159, 178, 174, 70, 159, 38, 113, +111, 18, 44, 208, 17, 16, 51, 197, 189, 90, 1, 218, 226, +110, 192, 91, 136, 174, 195, 56, 33, 18, 198, 174, 198, 249, +80, 172, 221, 50, 79, 79, 101, 44, 5, 176, 212, 131, 90, +117, 8, 101, 161, 75, 169, 95, 2, 130, 1, 1, 0, 137, +194, 197, 195, 168, 48, 55, 24, 89, 160, 121, 246, 165, 19, +235, 53, 8, 4, 209, 166, 238, 24, 144, 69, 53, 204, 151, +109, 217, 174, 9, 84, 51, 186, 80, 207, 146, 120, 39, 83, +183, 146, 103, 133, 0, 81, 73, 35, 122, 205, 72, 34, 190, +25, 208, 203, 248, 253, 75, 111, 186, 113, 40, 249, 215, 21, +204, 137, 16, 96, 45, 220, 108, 154, 233, 179, 110, 246, 233, +178, 77, 25, 225, 52, 165, 138, 12, 179, 211, 251, 193, 107, +61, 201, 170, 33, 101, 87, 132, 238, 103, 252, 1, 229, 128, +168, 18, 223, 135, 73, 48, 8, 155, 159, 109, 141, 105, 47, +80, 244, 160, 119, 19, 166, 140, 63, 203, 55, 41, 46, 219, +172, 96, 240, 112, 71, 127, 94, 155, 20, 29, 104, 35, 198, +8, 158, 66, 159, 226, 194, 189, 235, 173, 0, 46, 187, 101, +133, 2, 132, 235, 250, 82, 56, 181, 48, 190, 236, 42, 65, +47, 47, 39, 1, 113, 178, 167, 74, 17, 87, 105, 52, 89, +76, 39, 46, 55, 180, 183, 110, 108, 143, 17, 74, 128, 166, +21, 47, 138, 90, 151, 1, 146, 161, 27, 158, 158, 95, 124, +134, 121, 176, 191, 111, 149, 135, 46, 121, 223, 195, 110, 187, +51, 96, 207, 143, 110, 15, 150, 55, 10, 4, 173, 156, 179, +220, 53, 147, 39, 247, 245, 238, 192, 249, 181, 62, 136, 122, +36, 229, 118, 227, 124, 79, 6, 58}; + diff --git a/crypto/test/rsaperf/rsa3e4096_1.pem b/crypto/test/rsaperf/rsa3e4096_1.pem new file mode 100644 index 0000000..5bf019f --- /dev/null +++ b/crypto/test/rsaperf/rsa3e4096_1.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKAIBAAKCAgEAuWmQkiB6MxvjGx+B4UuGhtd62aIhpL7ezWrNPnUYJYDCuPvb +WyXvyKIe3FicW0MWc0rPBkLBTKxX9K694DGTL82S6KPYGQgTCDJCFitkNfKb7fFL +VQawRxc8E+NkZJE2pVEoF8E5tcE/ONs3VuxqjkbZiqWP862hth/S7ocIM8OVTWSi +TDmK2/+nRqfqe5ruG+0wFsGR9+7pgw1H8tgKNiw1cEf9a1qmTmfZsbjNyIz0VHnm +i4nOgZJAxO4FQgSCh08NKXylvHcOVJJNj2OrCgZP1qkQLH71KVEFyt0pshVzpjlN +OTZfhClF0VtWc0XbfHhm4sp42jBQcpz2Fi+vSjlGUhMlPlzVLNwLpiHIzdXdxQy0 +TS9NnasZiEAxhoYBBHaUJAXfWbtndY9WiaAmpv5ZYIRMSvJ0BMQuy2etqMeGQC4S +ZvSKi8rEnECci5yC0G1hgbZJM73BAQzCkvLjOW5rAQ636t6DP1/BIqFW3JviimDv +GqCJCuXk9hpIZFhV7OXr3DK9YdJvKmoRWDbzbCTLfykOgp33SCXzS/w3AopigCNv +9PsmAqA32+73SqwJlxUiV5aT555x8CerRSaQ8x5q81Kdcxmn+RemrEgGESS4ZY5e +JnR0FtQ21tvSMhNMDPVmJy9JI8106XGCVPPLH17RXwQUZtgCBjhq9e2eVa8CAQMC +ggIAHubtbbAUXdn7Ly/q+uHrwSPpzvBa8Mp6d5HM374usOrLHtSkjzD9TBsFJLlv +ZIsuaIx31mB1jMdj/h0fpV2Yh/eYfBtOrtat1rMLA7HmCP3Ep6g3ONZytoPfWKXm +EMLecOLcA/WJnkrf3s8z49IRwmEkQcZCqJzwSQVN0mvWs0tDjOYbDLRBz1VGi8an +FJnSWfzdWSBC/qfRldeL/c6sXlyzkraqPI8bt7v5nZ7M9sIouL77wexNFZhgINJW +NatrFo0s3D9w9L6CY223l+Xx1wENTnGCshUo3Dgroc+G8wOTRl7iNDO6lgbg+Dnj +veD56hQRJcxpebK4ExopA7KdNsDGEqnDm4Qvs9Sc3SyeMYGucbDKsbP8+eI60Je3 +MxETUIZe1JbhfX+i/HKN/QYeW4FtSSCKtyTu4J7OFbYQQw3l8mrSn7oxufFa4GmX +Dv2qjPrTmXxAB4YRPmJT2osbggJl1g0tq+rkMaPQTtfEUihdD9ph8+Lb2fScGyo3 +hwygkurhrwzNy72rBKDNOma6RHy5ZSciLjyxRVN+pc/z81a8mciaJoJBfytzFUq0 +YwWolqHQp1IGA2JcWYaYaYgrRtssjdqQ9nBwZ07jP6aPIDS2sOZiOE9KDiEhxx50 +CybKFKwhrku39avNQfB7awiyJO2lIM8un/itD9nVATfIQYsCggEBAOhUftKu9/tp +zERyRHRL7P/C+tqbKUNqrtpGa+hRfHuZb0lc34euwY2OLaWVSgRiDwKjdIZOC7iF ++0n0xnbqKiPmA+ZiKha8eaOlFZLMiZQNSMsWXq2Af2FV6Q5Ag75Qap9DhR/Q8+9t +qzRAtSfjYStH0g666XNShMn5sUOxWtlUd50O63+ULCAXasl3VP0sYWLkA/7dFeB+ +Yfl2XPegiwNSSDcb3OhUquqowvmb3jYQ77RONrADCo6MjEVZOtu+zGGimIRBnLjp +x8hcPtSl5fm2lgF1kWCeKb/DkB4XJtbpcGNPC0QlMCp7V6Qn2bxSdlX7gmb0HcUu +n23gViz7TmECggEBAMxNY0XgoUhNKZvsMqHHt8wEIA1Y+bP1E4NyOMmU16Pzsgb+ +SPTnpzAHXTptUXcOcvMmNTq99FxUxcFlgqxh7FA8jcbAfoCjtn7+RDRFqBZ2OcFV +ih9IhzgDobCK7/HtwsDEd5/U7228alSelGrZjn5sWTPoedwPamBCodlJ3zM+A8eS +1mZWb0BVo9vKpNFpb9WPHD9kV1FRRjeFDCTew36knTi3MQVIXLDcmTUhGlQFH5Xw +NPpsyMG7Srq/kRnOfZm9B672D74bxXX274wFae65qiabQzgZmE2onAcCyFOmIIlN +BiTUMZwqBip1+QNLy3b3F8IIiT7FB6+MmHHxfg8CggEBAJri/zcfT/zxMthMLaLd +SKqB/JG8xizxyebZnUWLqFJmSjDolQUfK7O0Hm5jhq2WtKxs+FmJXSWup4ajLvnx +cW1EApmWxrnS+8JuDmHdsQ1eMIdkPx5VqkDj8LQrAn7gRxTXrhU19/Tzx3grI2/s +63Iv4V8nRkzhrdv7y4J2PJDi+mi0nP+4HWq6RzD6OKjIQOyYAqnouUBUQVD5k0/A +XKzhhXoSk0WNx0cbLKZn6Xlgn82JecqssbRdstjmJz0p3ZZsZa2BEyXxL9roKeMZ +Q/vPDqujtkBpcSqCYBQPbznw9ZeKB4LDdXGnj8LFO9LhpDlSVu9NaS4fFPPq5B38 +3usCggEBAIgzl4PrFjAzcRKddxaFJTKtarOQpnf4t6z20IZjOm1NIVn+203vxMqv +k3xI4PoJofduzicpTZLjLoDuVx2WnYrTCS8q/wBtJFSpgs2DxWRO0SuOXBTbBNAC +a8sHSqFJLICC+mqN9PPS8Y2/DZyRCamdkM1FppK08ZWBwTuGlMzUAoUMju7kSirj +wpKHGIubn+O0vX+YOjY2Ls+uCBiUglRtviXPdgOFkyCTEM4WEY1Yv7lKzfxIhdZ8 +3Hx/thE0U7vTWnSkCn69Lk6kn7KuRp8mcW8SLNAREDPFvVoB2uJuwFuIrsM4IRLG +rsb5UKzdMk9PZSwFsNSDWnUIZaFLqV8CggEBAInCxcOoMDcYWaB59qUT6zUIBNGm +7hiQRTXMl23ZrglUM7pQz5J4J1O3kmeFAFFJI3rNSCK+GdDL+P1Lb7pxKPnXFcyJ +EGAt3Gya6bNu9umyTRnhNKWKDLPT+8FrPcmqIWVXhO5n/AHlgKgS34dJMAibn22N +aS9Q9KB3E6aMP8s3KS7brGDwcEd/XpsUHWgjxgieQp/iwr3rrQAuu2WFAoTr+lI4 +tTC+7CpBLy8nAXGyp0oRV2k0WUwnLje0t25sjxFKgKYVL4palwGSoRuenl98hnmw +v2+Vhy5538NuuzNgz49uD5Y3CgStnLPcNZMn9/XuwPm1Poh6JOV243xPBjo= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa3e512.h b/crypto/test/rsaperf/rsa3e512.h new file mode 100644 index 0000000..4cb0520 --- /dev/null +++ b/crypto/test/rsaperf/rsa3e512.h @@ -0,0 +1,33 @@ +/** + * @file rsa3e512.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa3e512[] = { +48, 130, 1, 57, 2, 1, 0, 2, 65, 0, 194, 148, 101, +47, 178, 107, 202, 86, 90, 18, 88, 6, 8, 176, 98, 10, +141, 177, 149, 218, 200, 83, 144, 240, 185, 90, 18, 83, 3, +12, 105, 95, 27, 101, 211, 116, 208, 148, 12, 42, 39, 214, +223, 93, 28, 113, 15, 33, 195, 182, 233, 220, 218, 149, 114, +214, 98, 30, 103, 127, 237, 149, 182, 119, 2, 1, 3, 2, +64, 32, 110, 16, 221, 72, 103, 76, 99, 185, 173, 185, 86, +86, 200, 16, 87, 23, 157, 152, 249, 204, 13, 237, 125, 116, +57, 173, 184, 128, 130, 17, 143, 142, 228, 33, 74, 164, 188, +1, 6, 159, 72, 42, 219, 113, 182, 239, 31, 248, 124, 60, +185, 236, 45, 16, 112, 229, 70, 242, 215, 38, 200, 203, 231, +2, 33, 0, 253, 187, 108, 108, 12, 138, 164, 133, 206, 48, +119, 26, 87, 177, 208, 141, 94, 227, 117, 171, 4, 211, 169, +63, 60, 189, 219, 79, 88, 238, 199, 43, 2, 33, 0, 196, +81, 159, 72, 231, 161, 97, 124, 157, 245, 103, 30, 26, 117, +163, 212, 145, 234, 7, 214, 76, 179, 102, 241, 197, 182, 219, +37, 171, 242, 39, 229, 2, 33, 0, 169, 39, 157, 157, 93, +177, 195, 3, 222, 202, 250, 17, 143, 203, 224, 94, 63, 66, +78, 114, 3, 55, 198, 42, 40, 126, 146, 52, 229, 244, 132, +199, 2, 33, 0, 130, 225, 20, 219, 69, 22, 64, 253, 190, +163, 154, 20, 17, 163, 194, 141, 182, 156, 5, 57, 136, 119, +153, 246, 131, 207, 60, 195, 199, 246, 197, 67, 2, 32, 69, +212, 136, 239, 121, 226, 228, 217, 128, 96, 251, 43, 228, 194, +242, 6, 161, 255, 97, 16, 86, 113, 184, 213, 202, 149, 79, +174, 230, 145, 169, 195, 3, 3, 3}; + diff --git a/crypto/test/rsaperf/rsa3e512.pem b/crypto/test/rsaperf/rsa3e512.pem new file mode 100644 index 0000000..2ad3716 --- /dev/null +++ b/crypto/test/rsaperf/rsa3e512.pem @@ -0,0 +1,12 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,5F7B632F69D00726 + +mlML8IQw0t8aUMmVuAVML+Zcj7PNB+cXYWR2xGrY9cU6hG3e8f/sVJ7wwtvpkLdk +CP5IvwZxjHd0rX6mxhLHjb9Vap9J95Ikv5jxTnwcw8JicVRmwhVNaxnF/TvbBoZw +nu3yrZGTgwJF9xRAIc8TOFWohD4ko62mxfjeOTu7x+AbWn6kwKDLrL6uVOg0B3Pw +YQVX9jgYk0t5NBcMZzk/XtPwY06Ygq6pVHsHZBv5BB9mK3JWo1E9gzA/kNjIH2U6 +20c4vU6NonQXePPw8DFd13lTFYk4OP7pdWA8xChrcytlrYNTEwoFgm1L+lH5Gdn1 +CnCOjAF9BpjQDtN9jmagkAUqnBUGAPfsjr/gqdpnMISUhtAleDNAR+N4HiKt9kEi +q+n6c+z4wkc9+IznwpKEEifes+0XOeY8NlCHqaIrI40= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa3e512_1.h b/crypto/test/rsaperf/rsa3e512_1.h new file mode 100644 index 0000000..30fc026 --- /dev/null +++ b/crypto/test/rsaperf/rsa3e512_1.h @@ -0,0 +1,33 @@ +/** + * @file rsa3e512_1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa3e5121[] = { +48, 130, 1, 58, 2, 1, 0, 2, 65, 0, 230, 5, 47, +17, 96, 79, 91, 114, 80, 95, 155, 30, 211, 10, 248, 254, +226, 232, 144, 233, 113, 249, 83, 89, 191, 98, 60, 147, 164, +190, 226, 181, 240, 239, 31, 170, 14, 112, 221, 11, 115, 96, +24, 108, 219, 86, 251, 46, 8, 189, 142, 88, 111, 32, 48, +207, 147, 33, 123, 47, 43, 76, 30, 247, 2, 1, 3, 2, +64, 38, 86, 50, 130, 229, 98, 143, 61, 184, 15, 239, 47, +205, 215, 41, 127, 208, 124, 24, 38, 232, 84, 56, 142, 245, +59, 10, 24, 155, 117, 37, 200, 172, 138, 29, 0, 5, 159, +154, 36, 67, 2, 214, 81, 118, 16, 105, 189, 207, 16, 107, +9, 173, 95, 83, 60, 144, 214, 228, 104, 17, 216, 39, 203, +2, 33, 0, 252, 88, 214, 111, 250, 37, 95, 70, 180, 100, +223, 131, 73, 205, 84, 241, 216, 145, 117, 13, 137, 241, 220, +53, 0, 92, 228, 116, 203, 92, 174, 23, 2, 33, 0, 233, +89, 155, 57, 242, 141, 224, 235, 44, 234, 51, 0, 205, 39, +43, 201, 85, 201, 151, 16, 212, 242, 97, 47, 45, 187, 60, +73, 244, 222, 130, 33, 2, 33, 0, 168, 59, 57, 159, 252, +24, 234, 47, 34, 237, 234, 87, 134, 136, 227, 75, 229, 182, +78, 9, 6, 161, 61, 120, 170, 232, 152, 77, 220, 232, 116, +15, 2, 33, 0, 155, 145, 18, 38, 161, 179, 235, 71, 115, +70, 204, 171, 51, 111, 114, 134, 57, 49, 15, 96, 141, 246, +235, 116, 201, 39, 125, 134, 163, 63, 1, 107, 2, 33, 0, +134, 58, 212, 248, 136, 117, 103, 51, 3, 4, 181, 103, 151, +73, 46, 196, 10, 33, 73, 74, 68, 79, 110, 13, 213, 253, +3, 122, 49, 4, 28, 86, 2, 2}; + diff --git a/crypto/test/rsaperf/rsa3e512_1.pem b/crypto/test/rsaperf/rsa3e512_1.pem new file mode 100644 index 0000000..7f53c61 --- /dev/null +++ b/crypto/test/rsaperf/rsa3e512_1.pem @@ -0,0 +1,12 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,3C2EF4A8DB3DC24B + +Yx8WvQsTSgbM9m5Qc+GRoq/qx68teUCPbOj7n1Oi0sdk610yLw46VPnCZMW3GKgv +o5AfxwkC9v8lBUcXsMLHO8UB5cewojmQBc9lc1qE4YN6sad/ettxMB7zLVzHl5y9 +7QUQvk1J7Cl7iQF1tL0Dg4KNSA4fwwafoXBF2WSVJep17EeC/PhIgdCMxta+/sXe +rOjvmnpXkb5v5rJ2Xiu7UEMm/hnudqZGqPf659mZ3bFd+LCSmjr6fkJdK7UuAyAu +r6iQ7zIM80PwNN8cXYfY6iyp4UmlMB/2qwo1Q2Q4z6oGL0FbFvT8VG5R7vnwv202 +/IndbDvbiRia77HPTKJH8CseCaNT0VSG82z6wdMqsUgi0I3JYRfkUDgMH6wrSE8T +y7wRWK3RgulP40b6dgesyT/Tbjvz5VlCnA2y3LWKDa8= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa65537e1024.h b/crypto/test/rsaperf/rsa65537e1024.h new file mode 100644 index 0000000..3ec10f2 --- /dev/null +++ b/crypto/test/rsaperf/rsa65537e1024.h @@ -0,0 +1,56 @@ +/** + * @file rsa65537e1024.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa65537e1024[] = { +48, 130, 2, 93, 2, 1, 0, 2, 129, 129, 0, 217, 172, +105, 85, 16, 181, 171, 123, 182, 188, 31, 172, 81, 167, 48, +138, 84, 147, 88, 194, 44, 51, 7, 185, 29, 141, 2, 4, +246, 71, 237, 216, 77, 152, 148, 114, 175, 74, 74, 52, 86, +60, 171, 100, 79, 187, 23, 23, 160, 4, 110, 237, 221, 51, +2, 111, 90, 58, 24, 223, 214, 178, 54, 34, 97, 81, 111, +230, 175, 164, 244, 16, 89, 18, 179, 253, 67, 102, 158, 197, +244, 240, 114, 199, 23, 49, 217, 253, 141, 233, 171, 212, 100, +47, 162, 218, 3, 107, 124, 3, 26, 30, 117, 161, 202, 120, +249, 88, 152, 174, 27, 46, 4, 44, 144, 32, 176, 111, 44, +77, 251, 65, 130, 37, 214, 223, 255, 253, 2, 3, 1, 0, +1, 2, 129, 128, 44, 92, 66, 171, 31, 88, 166, 181, 243, +171, 171, 24, 199, 27, 55, 125, 57, 119, 61, 227, 116, 118, +129, 224, 107, 241, 76, 180, 14, 44, 226, 127, 238, 112, 101, +240, 105, 96, 206, 118, 148, 12, 145, 49, 68, 62, 112, 154, +83, 246, 19, 85, 78, 123, 18, 199, 246, 175, 88, 90, 101, +186, 179, 229, 53, 75, 169, 242, 116, 11, 114, 123, 56, 220, +151, 188, 246, 94, 147, 41, 23, 228, 44, 3, 86, 42, 113, +15, 45, 231, 30, 121, 252, 228, 164, 168, 97, 64, 55, 155, +112, 24, 187, 209, 172, 94, 172, 224, 83, 136, 135, 129, 214, +202, 193, 64, 51, 14, 240, 205, 70, 219, 131, 163, 88, 196, +192, 81, 2, 65, 0, 254, 102, 225, 92, 32, 130, 205, 145, +97, 17, 75, 32, 70, 220, 137, 38, 161, 213, 13, 239, 98, +97, 127, 33, 77, 100, 127, 142, 251, 113, 26, 96, 5, 118, +85, 93, 146, 2, 127, 209, 229, 234, 187, 21, 232, 4, 236, +116, 35, 105, 124, 71, 204, 121, 115, 104, 133, 237, 128, 209, +131, 60, 158, 15, 2, 65, 0, 219, 10, 119, 69, 14, 231, +193, 159, 203, 197, 74, 3, 32, 168, 224, 87, 226, 253, 224, +192, 12, 223, 140, 229, 3, 35, 242, 211, 7, 180, 235, 111, +253, 6, 177, 30, 94, 101, 203, 113, 189, 36, 8, 38, 159, +2, 172, 166, 33, 58, 213, 176, 44, 70, 156, 134, 61, 186, +60, 20, 135, 158, 77, 51, 2, 65, 0, 211, 91, 69, 255, +244, 66, 183, 231, 0, 110, 13, 172, 83, 51, 5, 255, 66, +148, 111, 111, 98, 156, 253, 177, 253, 74, 113, 111, 169, 22, +222, 130, 200, 6, 248, 5, 53, 57, 62, 88, 116, 91, 255, +242, 195, 64, 211, 241, 233, 57, 202, 55, 28, 122, 10, 151, +220, 44, 229, 201, 42, 239, 65, 161, 2, 64, 22, 229, 210, +48, 10, 237, 217, 68, 222, 37, 98, 166, 79, 12, 184, 95, +23, 160, 152, 149, 27, 3, 103, 148, 45, 46, 221, 220, 135, +170, 183, 13, 254, 242, 107, 35, 148, 148, 169, 158, 219, 57, +224, 12, 65, 133, 35, 13, 62, 222, 10, 166, 159, 10, 70, +164, 149, 225, 89, 20, 128, 84, 225, 23, 2, 65, 0, 137, +197, 241, 127, 98, 31, 173, 154, 194, 68, 187, 186, 116, 109, +160, 178, 30, 72, 154, 206, 5, 4, 234, 143, 175, 231, 83, +175, 3, 229, 44, 249, 47, 197, 105, 45, 12, 211, 108, 21, +153, 61, 131, 192, 89, 193, 112, 78, 128, 1, 190, 237, 85, +121, 111, 253, 2, 36, 161, 119, 52, 240, 41, 3, 7, 7, +7, 7, 7, 7, 7}; + diff --git a/crypto/test/rsaperf/rsa65537e1024.pem b/crypto/test/rsaperf/rsa65537e1024.pem new file mode 100644 index 0000000..c167133 --- /dev/null +++ b/crypto/test/rsaperf/rsa65537e1024.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,1CF438763080D598 + +HE/dIEO78dQidpNZ9KUGcjhO8Jf4jupfpAUPbRZ0Se4Gg/SHCnW21JXLzZn6rh/1 +k3alHVLaf2F0V2PvZH1GBhwFpx8y3u4wHXApaMqbyAVedYj/wtuPyf1FXmNJBLhh +3VFhuE0oxcyBIbIclH5XKAx4YMxoCSMhieRAOJjIT2nb0cwesnKIKY6XsdxOlD6Y +ifoty3o8xpq80YS3zWNBj34XR36FLWkj/rdihTvvRuLSz1N7D4vOjBuj6ga5bb68 +mvYvfr1RKsfTM6fZ6dkjmI0P6Kk2mmKUNxE+W8H+PD8ICR9NG+PSma8PRhHOw4ut +YlWWTO9hBpyVGdhPL2O59b7wZcqTCYONRHnxgvIFpkbM2xN0c+jtmalen/C+6ZNr +JkvhRRWiQtJGS2WeDOH4ZSpDe1/9bK/9rQxD5TVUpwUCwVX8ETMaRkk0bhO4TaDc +21sJUwkmRMqgZjkE8WI0LUjzIkS1ofJHaxkur5jdvLHbAbhtSc2VZXc1amRfPVEG +KLp3ugbKnj2WuHUADUUig+xIu4ZhmNeCKXbOp+0a6MC/6t7mN+/lmxUFJtXvNdUt +Exjr4lX+B2gvHbU0qqiO680VVyU/bD2TjVCn9gye5xuHbY7UXQKDhWteIQXT/Xxd +xW16k8J6K+xwBJf6G5BKMZtAvoHr1QVumGTijumpaGMIrO1VBPnl7yzv69lFfuVQ +SDRekfKAM5hyKQHWACsNskSBCQKkZQfmDxobOS87kbL4uHfOKW+wcEpLQOWuYBG9 +TeE8udtk9yKtEFKoi9MjflIK/VmIK6pMAdXZhNjUwso5waqjmzApBg== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa65537e1024_1.h b/crypto/test/rsaperf/rsa65537e1024_1.h new file mode 100644 index 0000000..fee74dc --- /dev/null +++ b/crypto/test/rsaperf/rsa65537e1024_1.h @@ -0,0 +1,56 @@ +/** + * @file rsa65537e1024_1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa65537e10241[] = { +48, 130, 2, 93, 2, 1, 0, 2, 129, 129, 0, 203, 209, +207, 45, 18, 48, 206, 161, 51, 133, 186, 107, 44, 178, 132, +253, 112, 159, 237, 145, 78, 143, 8, 119, 134, 223, 182, 128, +81, 159, 176, 229, 201, 63, 9, 5, 3, 80, 120, 24, 2, +180, 139, 238, 133, 105, 44, 13, 166, 232, 234, 39, 25, 232, +12, 114, 100, 177, 238, 193, 253, 231, 167, 128, 211, 204, 200, +196, 57, 132, 1, 6, 24, 198, 43, 251, 16, 33, 17, 125, +250, 177, 208, 162, 216, 66, 41, 150, 218, 178, 125, 187, 10, +231, 182, 197, 213, 184, 246, 154, 230, 18, 110, 251, 9, 216, +178, 73, 197, 158, 34, 83, 207, 156, 208, 242, 102, 132, 102, +65, 240, 83, 206, 237, 223, 183, 1, 185, 2, 3, 1, 0, +1, 2, 129, 128, 22, 101, 34, 79, 128, 125, 46, 103, 22, +3, 46, 157, 146, 22, 183, 120, 37, 132, 221, 20, 167, 62, +30, 31, 12, 9, 206, 194, 192, 181, 60, 57, 179, 104, 34, +180, 147, 77, 167, 52, 116, 47, 164, 100, 123, 242, 55, 109, +244, 150, 9, 12, 108, 211, 75, 114, 210, 79, 158, 189, 96, +9, 177, 36, 203, 106, 105, 117, 234, 146, 159, 137, 20, 250, +180, 159, 255, 189, 112, 227, 130, 0, 37, 129, 204, 3, 5, +51, 41, 86, 72, 250, 50, 28, 17, 248, 196, 85, 173, 255, +203, 56, 181, 160, 30, 218, 75, 166, 93, 1, 134, 35, 20, +175, 174, 51, 215, 223, 132, 151, 251, 159, 216, 108, 174, 166, +95, 1, 2, 65, 0, 234, 16, 217, 133, 218, 85, 243, 22, +79, 109, 252, 15, 37, 126, 222, 236, 221, 60, 114, 140, 87, +22, 16, 101, 68, 169, 187, 53, 206, 70, 159, 85, 205, 231, +180, 183, 87, 111, 205, 234, 47, 36, 33, 197, 12, 65, 96, +165, 41, 186, 210, 242, 187, 237, 172, 162, 18, 241, 76, 210, +88, 236, 26, 161, 2, 65, 0, 222, 235, 93, 12, 62, 134, +119, 8, 231, 9, 107, 204, 158, 119, 240, 232, 28, 130, 201, +161, 106, 254, 195, 139, 185, 45, 139, 38, 171, 73, 244, 63, +144, 108, 44, 211, 122, 254, 81, 212, 93, 159, 155, 122, 236, +161, 93, 58, 239, 223, 66, 60, 189, 88, 190, 103, 239, 151, +194, 229, 197, 119, 104, 25, 2, 65, 0, 168, 208, 124, 66, +56, 229, 146, 140, 61, 191, 98, 114, 254, 37, 17, 221, 29, +247, 49, 218, 156, 24, 178, 188, 135, 24, 47, 136, 175, 252, +105, 128, 182, 31, 238, 75, 233, 73, 30, 231, 79, 22, 173, +48, 116, 21, 87, 1, 232, 37, 241, 108, 214, 51, 166, 53, +194, 153, 188, 65, 93, 150, 243, 225, 2, 65, 0, 168, 119, +71, 2, 145, 222, 28, 231, 101, 115, 1, 60, 202, 37, 234, +177, 255, 153, 247, 183, 61, 156, 251, 59, 4, 223, 30, 98, +66, 224, 200, 237, 160, 191, 159, 192, 211, 26, 143, 204, 230, +84, 80, 180, 61, 80, 85, 156, 204, 218, 244, 187, 226, 124, +198, 168, 213, 176, 227, 97, 178, 49, 227, 65, 2, 64, 60, +98, 231, 40, 254, 163, 4, 196, 164, 23, 159, 48, 213, 223, +62, 61, 162, 74, 62, 155, 113, 140, 117, 31, 6, 5, 253, +137, 139, 220, 199, 160, 39, 201, 188, 58, 89, 74, 241, 40, +105, 140, 113, 218, 16, 114, 233, 199, 252, 228, 241, 65, 42, +121, 112, 63, 250, 62, 249, 73, 219, 69, 98, 217, 7, 7, +7, 7, 7, 7, 7}; + diff --git a/crypto/test/rsaperf/rsa65537e1024_1.pem b/crypto/test/rsaperf/rsa65537e1024_1.pem new file mode 100644 index 0000000..9d6f2fb --- /dev/null +++ b/crypto/test/rsaperf/rsa65537e1024_1.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,E03540787D97C273 + +d4d5qrIDt+nqDPq+y/fgdeXnDrfauCb1GqUzb5Vf8uA/MwvDISAcH39tLCiitO2Z +P524gHelB+gOHesQua79Eyj2nRtXyHoYlrPbofuZuMh+qidFzqgYgm89wyAeEfqn +uwRL28qup2NkQuSjrC9RnEIr90rdW6hCo97idfG57rZv0SIbwRgwwkLvXweyn5xN +ETW/CGv6g9GA9uuXJluOZbsoBXEsjOjmMpXy81xas+uNgrAA3JJgtka8p9oKs0yK +s8qWje/fm175cXnCQrAmO7Lnut1yXuDzfJqtGjq8xVBOl3DLLhvum3PYGOcjVb/t +WdMvPHjCy9mEH+b0sOXb5GUAScg5tcaf6xCDWMdX79+yL2AW9SDOb+/ufrzglaSN +jIH1lBOM7TDoqX5tStuf4N1trN089FeC/gViw8ivV3xqro4+xRZ49nSGtumtUCW6 +px7lP8JdYP4D/Dg+Qny1WJ3DyMa9TliF3X5LN6tf9yNoluDNFAiHlACAjy51hr1k +O+/RNv92c8U1eu01wPEX1ttZvzIs04nZq0gyQm8YuBvWjliUvmN/qg1M+N7ahF5G +U+vGvBlfkqZxhG1vH1Mj2dQ3xNxerJv4VU4D/D/i6u4hjyhYdZTKWnPaz2+8hH8k +KA0d1Y3zBR38SMgOMiIT3zqVyCECZM1SIAQC1iPDjmYNjg8uXBFJ3wbk5S09GkFG +IbyK1PkWxYESwT16SShPSHifr09CoVy4r2Uh4yYNqp1Y+t3D/lXzahjWCJv0wFzQ +7YZ2WnClhx2af2RUotUCQd8O2F7OSaxtTQbnXk6JgpllS6hD0X3qrg== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa65537e2048.h b/crypto/test/rsaperf/rsa65537e2048.h new file mode 100644 index 0000000..cd4216e --- /dev/null +++ b/crypto/test/rsaperf/rsa65537e2048.h @@ -0,0 +1,100 @@ +/** + * @file rsa65537e2048.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa65537e2048[] = { +48, 130, 4, 161, 2, 1, 0, 2, 130, 1, 1, 0, 217, +246, 96, 222, 142, 78, 245, 244, 98, 173, 72, 35, 98, 117, +206, 215, 55, 15, 121, 116, 78, 118, 121, 66, 254, 172, 225, +252, 189, 189, 92, 160, 94, 186, 175, 153, 60, 239, 1, 135, +175, 209, 218, 31, 212, 190, 28, 200, 115, 39, 195, 229, 28, +78, 84, 127, 189, 70, 70, 225, 48, 118, 33, 79, 219, 196, +82, 247, 229, 29, 126, 249, 223, 50, 48, 254, 2, 88, 137, +237, 119, 142, 93, 11, 58, 199, 157, 109, 240, 183, 207, 200, +97, 4, 246, 43, 98, 44, 216, 186, 64, 78, 170, 27, 38, +70, 163, 57, 213, 140, 60, 216, 135, 216, 142, 23, 199, 86, +161, 200, 218, 62, 254, 201, 2, 46, 187, 109, 148, 226, 56, +149, 135, 229, 147, 237, 167, 245, 104, 72, 2, 51, 108, 167, +3, 58, 18, 143, 38, 231, 42, 176, 193, 17, 116, 83, 169, +107, 141, 10, 216, 248, 175, 214, 60, 252, 251, 46, 83, 156, +31, 170, 77, 194, 11, 70, 216, 73, 187, 180, 38, 254, 208, +208, 250, 241, 77, 174, 7, 191, 103, 210, 19, 155, 1, 52, +83, 238, 180, 148, 55, 38, 186, 48, 63, 145, 249, 82, 230, +202, 103, 135, 8, 201, 143, 18, 233, 6, 114, 232, 237, 96, +149, 194, 70, 249, 35, 132, 95, 176, 50, 51, 127, 189, 96, +79, 244, 17, 215, 223, 26, 222, 78, 213, 180, 192, 91, 56, +2, 213, 150, 145, 186, 96, 35, 123, 2, 3, 1, 0, 1, +2, 130, 1, 0, 30, 39, 171, 17, 63, 105, 7, 56, 47, +106, 191, 223, 61, 97, 5, 35, 219, 87, 69, 187, 100, 155, +153, 125, 62, 84, 214, 211, 43, 193, 6, 14, 157, 236, 128, +28, 216, 68, 76, 214, 227, 233, 73, 159, 59, 196, 173, 160, +193, 229, 207, 129, 100, 32, 38, 42, 162, 26, 21, 246, 83, +201, 20, 36, 195, 71, 239, 30, 162, 209, 40, 223, 19, 21, +19, 152, 32, 228, 244, 248, 40, 161, 70, 152, 38, 34, 181, +210, 31, 10, 159, 49, 158, 210, 155, 232, 54, 165, 243, 186, +24, 233, 137, 57, 70, 91, 97, 123, 191, 226, 174, 12, 91, +7, 7, 233, 156, 71, 141, 12, 135, 189, 77, 108, 171, 227, +161, 68, 111, 111, 181, 252, 153, 226, 64, 249, 153, 92, 235, +90, 83, 33, 234, 152, 229, 16, 89, 73, 249, 164, 213, 50, +77, 149, 192, 53, 159, 138, 94, 51, 17, 155, 203, 105, 178, +85, 53, 75, 67, 196, 206, 2, 211, 36, 180, 214, 48, 207, +28, 202, 228, 122, 10, 14, 134, 96, 128, 223, 91, 86, 12, +72, 191, 59, 251, 147, 39, 44, 253, 225, 114, 202, 140, 152, +143, 36, 108, 33, 162, 150, 88, 158, 46, 86, 225, 56, 94, +96, 77, 100, 129, 40, 40, 141, 100, 50, 26, 109, 42, 139, +158, 37, 152, 113, 90, 171, 59, 82, 119, 206, 39, 88, 63, +222, 169, 160, 0, 242, 76, 95, 169, 137, 102, 237, 254, 81, +2, 129, 129, 0, 224, 14, 164, 36, 124, 214, 249, 144, 81, +200, 125, 32, 65, 37, 114, 195, 182, 207, 245, 235, 22, 39, +133, 27, 145, 123, 121, 250, 247, 48, 112, 64, 220, 29, 81, +111, 87, 137, 225, 177, 91, 226, 88, 90, 250, 80, 149, 21, +164, 196, 230, 67, 72, 226, 51, 101, 44, 215, 107, 122, 186, +112, 250, 167, 229, 188, 159, 250, 92, 43, 11, 216, 70, 125, +148, 108, 115, 231, 181, 45, 175, 211, 53, 88, 66, 158, 141, +129, 178, 4, 28, 146, 142, 178, 162, 46, 60, 123, 177, 52, +201, 119, 132, 248, 198, 19, 117, 157, 130, 131, 183, 65, 211, +42, 210, 40, 32, 171, 162, 231, 255, 91, 233, 161, 11, 40, +208, 185, 2, 129, 129, 0, 249, 9, 76, 53, 164, 88, 76, +98, 191, 128, 185, 210, 186, 33, 97, 116, 219, 12, 13, 185, +91, 31, 129, 177, 116, 92, 236, 27, 24, 155, 203, 60, 116, +110, 206, 180, 53, 119, 218, 123, 243, 16, 169, 93, 32, 205, +223, 123, 11, 56, 84, 133, 236, 59, 23, 197, 191, 70, 254, +177, 85, 116, 98, 76, 228, 134, 17, 132, 109, 185, 17, 214, +125, 82, 232, 191, 94, 196, 30, 252, 202, 139, 237, 164, 174, +122, 76, 227, 164, 94, 164, 61, 187, 235, 36, 176, 187, 237, +168, 254, 55, 106, 183, 106, 123, 32, 83, 254, 136, 255, 131, +56, 21, 146, 237, 71, 91, 65, 58, 176, 152, 11, 137, 71, +75, 65, 115, 211, 2, 129, 129, 0, 196, 253, 154, 107, 74, +39, 103, 251, 239, 43, 170, 119, 117, 79, 139, 123, 111, 123, +159, 231, 52, 239, 66, 36, 94, 224, 132, 250, 149, 226, 76, +143, 121, 247, 124, 229, 187, 189, 74, 101, 57, 55, 228, 30, +248, 253, 104, 86, 67, 43, 170, 151, 117, 185, 11, 30, 229, +49, 241, 25, 82, 90, 138, 198, 155, 66, 32, 21, 106, 123, +158, 74, 100, 143, 124, 179, 109, 164, 70, 179, 8, 103, 85, +251, 103, 119, 39, 74, 228, 76, 161, 34, 105, 187, 188, 195, +146, 1, 222, 103, 94, 202, 106, 106, 159, 27, 244, 200, 171, +59, 75, 31, 224, 157, 65, 112, 110, 104, 249, 45, 168, 98, +19, 34, 184, 65, 6, 97, 2, 129, 128, 123, 168, 80, 61, +58, 147, 213, 170, 26, 233, 50, 92, 30, 172, 64, 150, 35, +198, 130, 114, 13, 123, 65, 140, 249, 248, 194, 12, 90, 85, +209, 190, 253, 25, 160, 109, 255, 54, 186, 56, 93, 227, 98, +21, 170, 26, 79, 227, 235, 24, 87, 112, 0, 114, 255, 68, +227, 203, 190, 224, 19, 76, 173, 26, 253, 70, 77, 32, 114, +211, 56, 182, 70, 152, 138, 149, 171, 218, 186, 128, 79, 154, +215, 175, 180, 43, 106, 78, 134, 233, 175, 168, 47, 205, 124, +244, 124, 252, 111, 179, 123, 148, 243, 234, 93, 165, 25, 208, +3, 250, 204, 15, 103, 55, 3, 183, 48, 234, 220, 215, 159, +71, 235, 44, 137, 131, 192, 157, 2, 127, 9, 211, 1, 163, +237, 199, 111, 135, 167, 201, 190, 32, 64, 27, 209, 34, 28, +9, 197, 229, 228, 125, 93, 48, 52, 189, 222, 37, 195, 251, +159, 68, 243, 162, 157, 7, 45, 158, 26, 209, 85, 254, 197, +249, 37, 121, 35, 127, 23, 119, 100, 108, 248, 168, 86, 161, +68, 231, 237, 17, 113, 100, 197, 254, 231, 56, 34, 76, 86, +223, 55, 111, 152, 12, 145, 182, 65, 191, 132, 207, 147, 28, +46, 225, 174, 120, 187, 230, 29, 237, 99, 55, 146, 71, 194, +35, 38, 27, 214, 50, 121, 243, 238, 197, 221, 48, 124, 215, +52, 13, 77, 131, 210, 45, 160, 89, 86, 156, 158, 156, 17, +106, 130, 95, 16, 144, 210, 3, 3, 3}; + diff --git a/crypto/test/rsaperf/rsa65537e2048.pem b/crypto/test/rsaperf/rsa65537e2048.pem new file mode 100644 index 0000000..454f77d --- /dev/null +++ b/crypto/test/rsaperf/rsa65537e2048.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,AEAE2FCC50C33552 + +RINoy07R3jreHejPVUV45+OjU6DxDEwrA4idW/9oVJ29qpxWjUJ1+ALvXyYwOprg +X2YxiENML0Kh5MQTnvoNS+h3u194lz4WU3ElI1KuICn7rW2Jg8be0qD3hZJZ9wCl +MJZJQV3wUNjI0xjRDW1Olmu7lgg6mLaprMf4vUIlvTi649WpiFftQ2EnWUuv8cJS +fvSkzAYi6i6uhGC8n3O301FSFwtfffpGu8DJtMfUlkkjsppV3a8EmlnSMpw1QCyi +0SwfrSxO2cjc1paBMLODQ4RQblOPjKc53NFs3tnEBJkKWxQN6s+xydmiLt1bD3Mp +XQctFNbXSh4R9R4Z6RvgwqBLWfjLhKlw6ZjJMYttW6O+dxJSL9B8YPRCQAfWKB4+ +3Wkh7FHvRU0eJnBdHwImdAyia06lpCczmsgTDq6/pLk81460Rzi25mtMyggI7wkx +35YfjT7mKgdhaLpL/0fB+RCimkF2SvFV8HRFXwuOra4LZFglJK4hMr+z9k23Z0Zs +MkqK90+G7NOCtWbUMykPwp2yAR6th5rSYSnhu1XSGhIsqQaVTZd74L0AA/5wIwrq +j2LDrdMv079plot20uPf5QQ2ISEZkOwZ494/JLI2Jh/ocYQn9N179T/K2SrM/VRH +Ndr16EvpeMRrcMLmJRPLtfh54R8NQmA+lEBPBFlWd2a7/6r7jtxA1h/aXujCT4ZS +hOgaQ9PrB8afEzHzlHNzzSgbpsLlf2VaERMGmaM5Vf4/+KZRlVdqd+it4lMU7Zw8 +YrNJ14W5CgRiVtCXY/qXCdB/skl/RsFJcwqxsGlXBVUDpBi4lrBvSlGDuOO1NK90 +XLo3ErPKPHuHKzE5Y86XOAYXLi8cmNuE+PEEhi7Eg8pUDxuVGQhDRedfY8oFVTUc +gwcat/IbZ19DG7CVl2PKmkIJ2bXxjt6Y5Ns8u86Tyc5XcK9dMRqLKbEgt7pYhr1d +c1ug/AkLZEh8YPrwY0bVqXxBS4xEUsBFe6CGYP11VeLELF16XSXiYUKPNZ1PaXkN +Za4qu1IR53bohZznn5Og0Y7VNbDGMY4dSlSyXNeiStU8l7CvOM25DIb9NGIr5DSh +WnUMaXI2220eDemVZOJzQt3y+xFgKPLmTprhmfCxHwuUdS77OFKBJj/W9igfyWH9 +YamqYxyhCGYxS7moDDeGRGBsCBd0D2IK6vI9H2KhRYsd4xT3PlEPFkdu5CB7zNmF +MimwgqnWA2YFvv6+wGvT8tCiseTVZjeeai4oGGxXJzbNOt+s/612lvZP7sHpNwOl +/nsmTBBvylzy+cXSLIaEZZaHhABjb/xfdVBDhlZqWzlpToxyeAG3kc67PQrZrKHy +x34hvzHPd/+sFi+O4zflkFmsI5Gp446gL5U56R0B1vm7EJBML2iRDSyPJYlBm05d +1p39sTnlF1DgJCZ23ZGwyXtVUdKEwJ5pBoHu3bKB6voXcuE4lt9IH5JH6qc1gu7s +1tXeCyH8O/Hz7sEFVb7Yv1VQIH0Xc1w356WlU7QulHaLpUjVsym2E1isObMLEA2K +yNkIgMA8f9iDIbFJxJwG/SmjfVUlPaYksdAPexkodCWxV1b/3Fw1uw== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa65537e2048_1.h b/crypto/test/rsaperf/rsa65537e2048_1.h new file mode 100644 index 0000000..33bfffa --- /dev/null +++ b/crypto/test/rsaperf/rsa65537e2048_1.h @@ -0,0 +1,100 @@ +/** + * @file rsa65537e2048_1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa65537e20481[] = { +48, 130, 4, 163, 2, 1, 0, 2, 130, 1, 1, 0, 221, +61, 227, 89, 17, 131, 119, 233, 234, 212, 30, 82, 132, 59, +210, 47, 14, 244, 31, 7, 0, 77, 105, 201, 124, 70, 22, +119, 228, 12, 178, 90, 174, 222, 38, 36, 251, 177, 167, 125, +83, 13, 246, 197, 65, 79, 204, 158, 228, 22, 59, 128, 169, +194, 25, 8, 160, 147, 113, 40, 153, 195, 239, 47, 100, 126, +164, 198, 226, 40, 78, 229, 214, 216, 75, 94, 51, 50, 243, +207, 81, 234, 83, 228, 193, 166, 189, 190, 42, 12, 131, 122, +36, 244, 165, 107, 245, 128, 35, 240, 58, 183, 71, 206, 188, +227, 146, 36, 128, 175, 154, 104, 50, 167, 76, 140, 136, 8, +76, 125, 91, 211, 138, 163, 43, 24, 198, 2, 6, 9, 213, +145, 60, 6, 28, 211, 115, 99, 233, 144, 112, 138, 126, 106, +17, 45, 184, 145, 87, 58, 11, 84, 127, 184, 224, 24, 141, +235, 51, 72, 141, 94, 97, 162, 2, 124, 19, 10, 7, 137, +227, 147, 72, 47, 54, 135, 11, 243, 73, 153, 197, 92, 198, +67, 6, 37, 173, 187, 136, 49, 249, 128, 28, 111, 17, 125, +243, 180, 145, 137, 245, 210, 217, 156, 157, 207, 195, 169, 37, +196, 213, 165, 76, 182, 148, 63, 51, 107, 200, 99, 172, 224, +229, 167, 166, 5, 6, 77, 177, 110, 104, 33, 78, 101, 226, +197, 255, 203, 43, 85, 199, 153, 34, 255, 175, 189, 90, 162, +37, 130, 20, 65, 159, 21, 152, 37, 2, 3, 1, 0, 1, +2, 130, 1, 0, 55, 37, 198, 21, 221, 151, 183, 188, 71, +28, 184, 178, 56, 227, 240, 112, 106, 121, 207, 130, 31, 65, +44, 173, 92, 156, 219, 220, 230, 171, 131, 137, 183, 45, 8, +181, 15, 72, 41, 71, 195, 252, 39, 22, 228, 64, 207, 240, +139, 74, 63, 106, 194, 229, 238, 247, 135, 143, 57, 21, 181, +190, 113, 80, 142, 236, 66, 134, 144, 185, 27, 113, 143, 44, +59, 29, 48, 5, 243, 96, 42, 59, 14, 206, 102, 182, 249, +116, 253, 102, 65, 31, 161, 54, 154, 69, 94, 220, 162, 24, +175, 138, 32, 12, 24, 105, 97, 116, 87, 223, 109, 205, 171, +82, 168, 114, 31, 54, 114, 90, 141, 25, 29, 229, 174, 72, +110, 146, 123, 232, 107, 149, 74, 196, 247, 233, 255, 191, 143, +11, 34, 188, 138, 203, 138, 143, 6, 20, 200, 192, 61, 102, +207, 133, 9, 92, 190, 79, 95, 102, 249, 123, 182, 38, 240, +205, 70, 80, 196, 75, 68, 128, 239, 97, 114, 20, 46, 188, +137, 197, 196, 199, 160, 88, 107, 26, 39, 217, 50, 209, 156, +186, 187, 34, 45, 5, 193, 174, 165, 93, 49, 232, 51, 55, +244, 146, 250, 221, 249, 193, 25, 243, 221, 146, 1, 11, 113, +50, 132, 75, 25, 132, 157, 109, 78, 80, 251, 22, 15, 10, +205, 14, 34, 176, 108, 21, 32, 184, 44, 75, 104, 208, 165, +242, 236, 243, 236, 116, 81, 87, 107, 70, 54, 183, 110, 1, +2, 129, 129, 0, 240, 53, 98, 44, 168, 164, 134, 68, 75, +94, 149, 250, 45, 145, 64, 91, 244, 116, 238, 95, 142, 132, +19, 110, 151, 187, 250, 154, 138, 86, 27, 20, 228, 133, 186, +82, 69, 133, 124, 119, 103, 105, 217, 21, 86, 130, 143, 59, +7, 57, 126, 205, 203, 138, 229, 100, 40, 239, 161, 108, 25, +234, 21, 144, 191, 243, 66, 233, 4, 84, 214, 14, 29, 108, +57, 117, 17, 40, 70, 213, 140, 101, 65, 219, 121, 126, 121, +84, 244, 84, 124, 61, 167, 182, 214, 232, 191, 47, 233, 219, +140, 191, 148, 114, 133, 81, 230, 29, 107, 30, 51, 114, 110, +211, 115, 148, 25, 179, 70, 143, 177, 171, 161, 5, 140, 228, +38, 41, 2, 129, 129, 0, 235, 201, 77, 16, 251, 70, 119, +123, 250, 253, 82, 106, 155, 28, 162, 121, 23, 138, 165, 6, +173, 13, 32, 168, 70, 20, 19, 89, 73, 88, 244, 63, 78, +9, 205, 161, 222, 191, 16, 117, 224, 31, 231, 50, 169, 173, +33, 209, 101, 127, 125, 8, 108, 242, 164, 241, 189, 148, 6, +254, 6, 142, 218, 247, 66, 245, 8, 224, 237, 140, 193, 16, +170, 238, 241, 228, 58, 254, 128, 82, 101, 252, 186, 211, 60, +47, 89, 227, 177, 53, 12, 127, 209, 68, 70, 161, 33, 135, +252, 254, 101, 91, 229, 24, 25, 21, 194, 231, 16, 84, 129, +124, 54, 252, 29, 47, 157, 116, 62, 16, 251, 141, 73, 230, +138, 20, 201, 157, 2, 129, 128, 79, 119, 73, 168, 62, 142, +87, 64, 230, 178, 62, 233, 138, 3, 160, 136, 11, 66, 87, +205, 211, 7, 12, 170, 172, 149, 234, 157, 15, 160, 214, 202, +189, 163, 35, 245, 173, 188, 48, 102, 12, 23, 47, 82, 232, +208, 190, 115, 167, 187, 52, 160, 254, 114, 79, 219, 39, 211, +198, 210, 77, 108, 108, 127, 251, 144, 141, 149, 42, 242, 169, +241, 247, 119, 227, 54, 64, 91, 211, 187, 55, 252, 19, 162, +120, 250, 7, 71, 188, 160, 234, 141, 55, 27, 188, 211, 56, +212, 176, 8, 10, 243, 34, 56, 20, 180, 248, 108, 201, 16, +47, 178, 238, 201, 19, 86, 110, 126, 41, 156, 198, 9, 98, +118, 196, 154, 129, 169, 2, 129, 129, 0, 146, 105, 42, 96, +172, 23, 66, 164, 138, 226, 248, 101, 88, 49, 252, 181, 130, +167, 197, 247, 146, 71, 127, 138, 222, 17, 35, 62, 163, 44, +8, 102, 178, 215, 165, 135, 169, 32, 45, 97, 116, 173, 122, +203, 219, 206, 181, 28, 40, 145, 116, 155, 97, 195, 126, 38, +218, 24, 108, 11, 27, 25, 99, 224, 124, 4, 89, 226, 9, +192, 8, 54, 136, 93, 221, 120, 98, 37, 156, 155, 13, 215, +84, 79, 76, 164, 254, 133, 67, 137, 116, 92, 126, 30, 142, +89, 9, 208, 62, 137, 221, 120, 165, 150, 68, 37, 94, 36, +74, 224, 158, 146, 250, 53, 173, 13, 223, 16, 202, 101, 147, +62, 85, 176, 64, 247, 205, 133, 2, 129, 128, 93, 111, 166, +226, 237, 116, 180, 163, 62, 51, 12, 69, 54, 52, 229, 10, +198, 74, 184, 125, 51, 20, 35, 211, 130, 234, 93, 62, 93, +130, 39, 101, 148, 126, 152, 139, 42, 140, 174, 194, 155, 177, +119, 192, 13, 186, 227, 239, 154, 52, 3, 112, 80, 169, 116, +47, 172, 44, 216, 161, 43, 98, 113, 81, 22, 47, 39, 121, +19, 122, 80, 160, 65, 65, 23, 77, 20, 48, 131, 69, 203, +222, 105, 254, 5, 8, 130, 148, 142, 163, 72, 202, 70, 195, +245, 226, 192, 7, 38, 74, 51, 112, 85, 173, 229, 88, 168, +56, 198, 72, 132, 124, 154, 249, 46, 204, 90, 95, 87, 60, +181, 242, 6, 31, 32, 51, 208, 161, 1}; + diff --git a/crypto/test/rsaperf/rsa65537e2048_1.pem b/crypto/test/rsaperf/rsa65537e2048_1.pem new file mode 100644 index 0000000..49a04a1 --- /dev/null +++ b/crypto/test/rsaperf/rsa65537e2048_1.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,67197D189DF0745B + +M96kcoWchS2BYEzYOWmrYsRtK9kVrqr6tOaQdr53MM7mngSifLsgt1CuUg9WkCU6 +M7yRAucvUnPMAqLEpEX5a3QrgruaRO5AdcWSaHQl+rvkwsPwkaRVHk/fHZGoTOzY +nI8EgL9lcigPoLbXQjrJLbIBa1fCUs9gsoMp0nuiSWUSgI4G/aiqc5PF8qyFudWY +hJ8eRvYhKkmHk+EGepuTYG2Uwy6Day/kLwBtXCFyC2e7kMQmla6Q6tCn6m013R/M +EsT7ehjf1Ka5qk6oRs21YBfdlGMJrKrbPlDbJdWA7oV5g98lxTN9kI3IfonFXt0+ +rSRV2hraVyggOpIMHbsw50H3MAnlsuQ4sTb2MKHr2mqSmJ6zsCIcN5rTbbhUmYsL +LQpDY+Y6CPDk6W3bEBCgFxQmptxElnH4QoL9vNA/6XgvJ3MncdoJbI1IlkSuhxM8 +Frh3PEoQ4HxmdQ1AdgEIpXvfRKNIorl5AaQLcSlgNoHjYs7HdFNuzHgIWIjSeOWP +oWGNMPaOJ9rNfS1WSeo82/SZt1Iza2ZEnQ/NWDi8aIeMaJFVySPByJ3dQiuUg2Jg +0AbAxgFSmbOJMOTlRAv+1cUE47QZCmhOE38+nD8QeN8bOVcjyPReS2xklnys9F8+ +sBDR3XfaVywxK0ManM2l4jsLxl6ana5dl8D0XSBdxRJcge63wfO1kz4zJ5cZUdQx +wcp1dtZxciSyKFIldzINADP11s6VTYv4ij+n71E8mXnuPrKfUXxRn2Vy0xh13drn +G4lKFmVm3Nk4A41z7QffXCQiMhzAvOXpJTs1DTtaUtgPelU+otWnrWTsv2fop723 +2y8hBEH79Q/Ejq7RXV1szAJTGW7C6Phs6QIBr1t32eX1kbgX2nVd96xTqBcnzmIt +1W0dKyRRhRsQRNCrY71C0Cz5xmhM647Ts5GVAfEHF/P4Uc2fTQiYcpbDSA5PPzQH +QTpkzU6IBGGGRMEedp2mL9fN7bKp/zixw4he3r6TNpveMeD2t+NmF4xGROubtGfb +AWRBtvnEWeZ7wZpAdIn/ONz4LBHSw3izZpJBK9T+z5FBhWIsFX+qwWURwK+yCaWs +OzQIfZ2xqh0ZMvq6cAc9OJxHyT/2QrMo2OYOdFhoF0LslslgUcUa2nLlIGoGgne9 +RhPtuNC94apY+INAaZ9BKrFdvSYU3lIvF0ONfHrARRCAISL8GPlVPsifL09u0jR4 +l1B206soSCoubQQmqa7h2gTbLeI0UzeZs2Gf8TkCjXIBn+JseLbDrScRxf/mbkQg +jC0iLTtIJ7V+lXykMPRp0nG4V2JK+QocL9JREbaSeXGU7n0lrANhRtuxVJErEYGH +bv4W7hXTvCN4+JCDGvd3aaGg5YiELWmL5lL8dEabogTnlzn20h91xChus0mXsZ21 +erTnSP92DoUInuC9Y7/5ItQQ42lumptSyX5teLDlMZLZ1Ii+c+RqFZjYIMxqxbuB +F8KQWR9Wb8mt1Fst1Mpl9Ti8nQ/OZy+CSEKqd/KpaHqit7LhtfkfbbAUG7Ef3jDp +gDdDY9ho8zTH25sb++5gHgbs/4eTbsagjI/jL+JSgoZc8Le2fvljtg== +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa65537e4096.h b/crypto/test/rsaperf/rsa65537e4096.h new file mode 100644 index 0000000..6c068e7 --- /dev/null +++ b/crypto/test/rsaperf/rsa65537e4096.h @@ -0,0 +1,189 @@ +/** + * @file rsa65537e4096.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa65537e4096[] = { +48, 130, 9, 41, 2, 1, 0, 2, 130, 2, 1, 0, 245, +60, 240, 206, 128, 207, 101, 214, 156, 101, 113, 143, 223, 27, +224, 166, 122, 85, 10, 48, 198, 232, 167, 88, 198, 194, 87, +63, 34, 153, 102, 180, 120, 37, 73, 243, 247, 78, 143, 85, +240, 232, 74, 208, 123, 187, 93, 39, 202, 35, 1, 7, 209, +43, 41, 65, 175, 51, 101, 17, 12, 11, 80, 191, 44, 161, +41, 130, 163, 49, 124, 169, 177, 9, 99, 176, 226, 81, 103, +54, 3, 146, 128, 238, 151, 144, 189, 194, 84, 226, 232, 145, +104, 38, 52, 139, 218, 116, 0, 41, 53, 16, 218, 27, 219, +183, 22, 106, 87, 217, 49, 59, 152, 184, 109, 104, 135, 123, +114, 173, 153, 203, 242, 66, 160, 209, 149, 56, 177, 176, 127, +63, 143, 145, 106, 253, 212, 26, 226, 178, 108, 48, 97, 188, +115, 28, 140, 101, 234, 51, 86, 30, 148, 167, 93, 140, 217, +188, 161, 62, 64, 24, 137, 134, 198, 214, 20, 46, 219, 126, +204, 191, 51, 49, 70, 201, 18, 232, 178, 27, 83, 36, 244, +157, 86, 173, 124, 8, 50, 96, 45, 27, 181, 223, 251, 188, +95, 81, 90, 91, 226, 157, 188, 228, 37, 16, 149, 184, 34, +2, 205, 173, 83, 144, 194, 222, 68, 152, 160, 35, 106, 26, +242, 91, 114, 106, 169, 30, 155, 94, 67, 220, 3, 198, 227, +254, 149, 35, 29, 218, 88, 172, 208, 222, 83, 15, 94, 244, +81, 181, 200, 95, 88, 8, 227, 84, 242, 23, 115, 220, 155, +238, 131, 165, 124, 40, 6, 249, 112, 51, 91, 52, 13, 205, +161, 124, 86, 107, 180, 188, 180, 120, 149, 240, 101, 65, 94, +73, 175, 156, 41, 34, 197, 74, 14, 243, 192, 233, 147, 234, +16, 50, 250, 45, 40, 160, 32, 232, 140, 70, 104, 147, 61, +192, 173, 246, 32, 2, 183, 26, 175, 229, 89, 24, 33, 178, +115, 108, 102, 76, 90, 173, 12, 31, 208, 242, 113, 221, 103, +103, 108, 80, 39, 39, 14, 180, 67, 251, 122, 248, 233, 235, +152, 0, 8, 44, 177, 246, 129, 254, 102, 245, 231, 187, 216, +217, 10, 66, 35, 131, 135, 241, 147, 209, 92, 120, 34, 52, +55, 118, 184, 185, 53, 185, 200, 235, 137, 89, 133, 223, 192, +66, 91, 4, 128, 209, 34, 254, 80, 216, 80, 25, 143, 173, +3, 6, 137, 41, 113, 57, 125, 117, 210, 250, 235, 102, 37, +122, 32, 81, 54, 184, 191, 253, 97, 45, 66, 45, 21, 222, +23, 134, 13, 12, 76, 40, 90, 43, 176, 141, 153, 5, 100, +243, 140, 14, 88, 223, 114, 53, 35, 190, 195, 153, 226, 147, +20, 145, 200, 203, 115, 177, 217, 169, 160, 174, 221, 73, 96, +53, 213, 225, 233, 9, 213, 6, 7, 146, 5, 144, 172, 104, +120, 17, 98, 247, 84, 79, 45, 1, 59, 35, 24, 169, 31, +222, 21, 191, 200, 21, 178, 28, 111, 166, 168, 103, 205, 176, +71, 96, 162, 73, 2, 3, 1, 0, 1, 2, 130, 2, 0, +6, 101, 23, 54, 155, 253, 92, 132, 216, 238, 241, 195, 241, +159, 210, 47, 17, 40, 168, 200, 211, 191, 173, 198, 118, 231, +96, 48, 247, 81, 11, 251, 50, 131, 89, 105, 202, 128, 173, +78, 237, 113, 103, 64, 92, 192, 245, 57, 116, 47, 249, 188, +114, 18, 151, 174, 7, 109, 214, 9, 184, 141, 163, 209, 69, +14, 94, 77, 7, 190, 77, 124, 219, 121, 152, 212, 134, 218, +243, 207, 171, 121, 66, 188, 176, 173, 218, 68, 61, 121, 173, +199, 112, 145, 114, 36, 106, 161, 196, 169, 35, 193, 187, 136, +71, 90, 255, 104, 174, 63, 88, 90, 155, 29, 112, 98, 152, +137, 127, 152, 151, 54, 142, 54, 142, 124, 236, 155, 131, 81, +172, 136, 116, 38, 83, 165, 136, 102, 48, 233, 102, 192, 190, +100, 95, 64, 60, 51, 215, 164, 97, 250, 15, 64, 97, 46, +213, 138, 49, 163, 180, 54, 66, 65, 123, 107, 159, 112, 49, +221, 39, 207, 189, 102, 96, 109, 30, 72, 103, 5, 145, 248, +173, 154, 198, 143, 164, 163, 120, 233, 209, 9, 249, 188, 177, +157, 129, 194, 247, 7, 49, 242, 38, 77, 70, 52, 167, 247, +122, 177, 59, 69, 180, 233, 239, 170, 67, 92, 104, 172, 242, +103, 148, 101, 227, 81, 31, 74, 197, 167, 40, 42, 152, 198, +200, 123, 163, 56, 177, 254, 204, 186, 19, 237, 20, 228, 207, +236, 198, 121, 48, 169, 224, 208, 217, 132, 88, 175, 227, 165, +61, 193, 171, 98, 36, 50, 250, 225, 196, 114, 78, 103, 148, +177, 105, 5, 156, 187, 105, 81, 226, 205, 154, 44, 145, 34, +171, 241, 210, 114, 47, 139, 156, 54, 8, 249, 95, 152, 214, +210, 204, 159, 144, 48, 178, 79, 47, 153, 60, 164, 60, 109, +11, 231, 36, 195, 181, 3, 175, 70, 111, 36, 223, 50, 233, +39, 4, 30, 230, 96, 131, 242, 158, 245, 62, 138, 5, 79, +133, 149, 139, 243, 119, 96, 128, 119, 195, 211, 203, 149, 64, +128, 59, 63, 225, 149, 107, 14, 158, 241, 145, 200, 185, 114, +79, 88, 185, 101, 49, 2, 246, 1, 104, 130, 145, 216, 21, +61, 115, 142, 121, 71, 133, 36, 29, 83, 165, 12, 117, 78, +49, 123, 178, 72, 253, 24, 192, 117, 193, 72, 26, 116, 225, +205, 129, 93, 174, 73, 182, 251, 108, 12, 60, 48, 63, 184, +48, 252, 34, 211, 102, 30, 185, 120, 212, 162, 20, 218, 157, +117, 166, 12, 27, 223, 245, 184, 31, 12, 131, 25, 89, 160, +139, 213, 197, 192, 158, 60, 230, 55, 170, 211, 55, 11, 214, +226, 239, 67, 136, 159, 223, 119, 220, 218, 180, 0, 89, 48, +168, 128, 205, 50, 133, 219, 61, 178, 105, 249, 230, 105, 95, +36, 63, 130, 80, 138, 230, 25, 143, 67, 161, 247, 83, 162, +128, 2, 76, 25, 89, 115, 102, 24, 209, 55, 108, 141, 236, +144, 179, 2, 124, 241, 2, 130, 1, 1, 0, 246, 175, 200, +205, 85, 235, 144, 60, 42, 54, 196, 51, 132, 116, 107, 85, +255, 145, 115, 30, 26, 245, 25, 183, 26, 93, 154, 119, 201, +18, 228, 99, 118, 138, 16, 212, 223, 149, 87, 162, 210, 111, +68, 68, 115, 36, 245, 26, 255, 158, 40, 131, 46, 108, 108, +158, 97, 248, 176, 116, 190, 106, 109, 68, 178, 10, 78, 228, +218, 115, 31, 150, 100, 138, 114, 192, 14, 226, 251, 135, 185, +229, 153, 162, 85, 129, 56, 244, 154, 133, 102, 125, 223, 70, +75, 180, 62, 161, 233, 162, 85, 110, 245, 173, 16, 49, 76, +6, 221, 100, 172, 138, 3, 133, 137, 156, 250, 160, 174, 166, +126, 253, 254, 9, 4, 15, 31, 232, 125, 44, 8, 226, 163, +173, 120, 73, 200, 37, 161, 135, 65, 234, 92, 168, 240, 106, +155, 156, 185, 214, 160, 67, 81, 19, 44, 233, 84, 243, 57, +58, 216, 111, 28, 116, 92, 244, 122, 111, 169, 204, 226, 106, +196, 239, 0, 88, 31, 162, 50, 146, 161, 91, 132, 125, 14, +162, 56, 80, 110, 245, 205, 101, 142, 104, 223, 192, 248, 87, +54, 138, 174, 91, 26, 162, 47, 138, 19, 160, 45, 86, 104, +205, 107, 32, 30, 70, 72, 146, 0, 250, 227, 246, 106, 56, +68, 64, 171, 31, 159, 180, 184, 253, 162, 159, 204, 125, 127, +26, 75, 211, 16, 201, 214, 169, 227, 182, 210, 230, 149, 110, +131, 189, 147, 44, 175, 81, 2, 130, 1, 1, 0, 254, 127, +39, 208, 250, 99, 147, 57, 165, 143, 218, 190, 148, 219, 147, +189, 66, 143, 86, 84, 110, 173, 177, 74, 135, 73, 231, 106, +155, 130, 88, 101, 46, 109, 116, 110, 16, 205, 31, 208, 134, +73, 41, 254, 214, 212, 60, 228, 254, 243, 87, 92, 124, 123, +177, 198, 181, 106, 173, 141, 204, 55, 203, 22, 153, 38, 180, +159, 113, 96, 116, 92, 115, 161, 54, 177, 122, 29, 123, 129, +12, 117, 236, 218, 249, 34, 59, 93, 243, 48, 246, 60, 99, +245, 144, 199, 206, 24, 17, 211, 60, 121, 17, 68, 84, 24, +164, 93, 124, 173, 8, 243, 179, 227, 179, 131, 86, 237, 26, +166, 93, 65, 192, 122, 40, 72, 250, 64, 205, 13, 229, 128, +50, 255, 22, 124, 56, 29, 92, 191, 30, 153, 190, 132, 15, +210, 247, 83, 125, 53, 71, 139, 51, 111, 59, 34, 158, 38, +222, 48, 16, 91, 77, 238, 216, 220, 164, 215, 165, 32, 108, +163, 36, 105, 17, 201, 23, 221, 171, 11, 205, 237, 100, 87, +73, 98, 76, 202, 57, 23, 236, 16, 5, 27, 15, 70, 8, +248, 43, 109, 72, 246, 192, 108, 249, 82, 12, 184, 57, 155, +236, 87, 77, 119, 71, 248, 190, 101, 2, 16, 145, 126, 147, +59, 246, 74, 88, 21, 236, 216, 234, 46, 109, 69, 167, 90, +17, 63, 137, 199, 136, 3, 66, 238, 65, 82, 156, 11, 217, +185, 51, 98, 134, 22, 53, 121, 2, 130, 1, 1, 0, 136, +128, 44, 116, 178, 158, 110, 105, 92, 82, 129, 174, 160, 20, +107, 112, 98, 194, 113, 24, 175, 130, 0, 128, 185, 46, 34, +83, 54, 8, 38, 40, 131, 103, 82, 120, 248, 95, 2, 231, +45, 218, 51, 196, 76, 146, 158, 174, 25, 211, 194, 71, 20, +97, 26, 153, 105, 76, 219, 23, 62, 102, 85, 160, 53, 132, +78, 179, 131, 205, 64, 37, 79, 236, 236, 34, 42, 26, 159, +100, 51, 17, 65, 57, 250, 102, 78, 197, 202, 219, 22, 35, +128, 112, 189, 99, 55, 101, 16, 138, 171, 11, 131, 22, 8, +103, 190, 209, 237, 159, 207, 121, 111, 9, 109, 100, 87, 170, +161, 249, 175, 59, 140, 94, 32, 200, 221, 183, 31, 204, 69, +254, 98, 227, 146, 52, 1, 116, 17, 53, 110, 219, 231, 249, +243, 78, 138, 92, 230, 216, 68, 69, 251, 142, 200, 195, 52, +38, 129, 252, 117, 214, 197, 191, 253, 207, 170, 16, 47, 189, +23, 108, 77, 28, 146, 236, 48, 84, 231, 247, 11, 34, 64, +229, 146, 59, 97, 61, 224, 168, 82, 199, 103, 77, 208, 194, +78, 168, 179, 157, 121, 109, 32, 7, 174, 150, 144, 213, 137, +64, 207, 45, 27, 161, 226, 30, 177, 249, 88, 97, 123, 210, +214, 99, 220, 32, 140, 144, 43, 39, 45, 85, 235, 174, 208, +208, 128, 140, 100, 120, 158, 73, 145, 102, 224, 130, 65, 161, +37, 254, 201, 23, 21, 97, 28, 129, 2, 130, 1, 1, 0, +182, 223, 190, 71, 191, 181, 15, 213, 11, 176, 60, 90, 88, +115, 20, 77, 154, 103, 143, 124, 106, 111, 171, 135, 71, 130, +6, 165, 167, 139, 89, 99, 147, 162, 25, 89, 1, 255, 180, +13, 206, 129, 2, 137, 89, 235, 246, 186, 2, 173, 239, 167, +200, 215, 197, 158, 105, 60, 119, 235, 253, 196, 85, 206, 46, +77, 14, 219, 199, 199, 172, 181, 198, 109, 32, 245, 21, 47, +220, 80, 150, 24, 163, 19, 146, 148, 83, 158, 166, 35, 23, +189, 187, 130, 120, 255, 234, 139, 135, 59, 136, 39, 227, 13, +123, 116, 157, 159, 131, 248, 127, 7, 71, 203, 166, 114, 9, +99, 165, 147, 200, 77, 120, 55, 15, 125, 169, 62, 41, 91, +4, 0, 68, 36, 227, 14, 109, 240, 67, 118, 30, 82, 18, +1, 169, 177, 74, 2, 23, 101, 210, 188, 39, 64, 149, 120, +193, 182, 98, 80, 157, 96, 78, 183, 3, 228, 65, 27, 168, +79, 141, 97, 9, 199, 234, 124, 219, 6, 113, 99, 177, 29, +21, 206, 87, 48, 40, 199, 227, 144, 218, 19, 132, 231, 181, +232, 248, 135, 4, 5, 170, 185, 140, 250, 129, 137, 193, 20, +28, 105, 123, 194, 28, 43, 75, 111, 101, 185, 5, 107, 204, +112, 236, 241, 216, 128, 1, 157, 247, 172, 195, 82, 139, 56, +211, 17, 184, 117, 52, 215, 73, 88, 54, 159, 40, 23, 105, +132, 102, 118, 91, 131, 63, 160, 243, 217, 2, 130, 1, 0, +56, 108, 4, 181, 147, 118, 238, 183, 50, 78, 138, 54, 146, +138, 224, 193, 108, 203, 241, 176, 253, 161, 226, 255, 255, 170, +97, 58, 175, 37, 173, 10, 190, 124, 153, 51, 167, 93, 130, +71, 192, 9, 177, 26, 159, 131, 154, 157, 113, 94, 54, 217, +68, 41, 243, 92, 57, 59, 27, 120, 78, 107, 154, 45, 91, +22, 55, 101, 196, 56, 122, 4, 167, 102, 25, 158, 238, 74, +173, 15, 115, 111, 56, 4, 111, 42, 241, 169, 170, 240, 43, +245, 88, 202, 12, 4, 181, 62, 116, 227, 36, 71, 150, 120, +172, 14, 186, 194, 35, 23, 208, 226, 88, 112, 207, 39, 91, +14, 98, 31, 108, 247, 232, 151, 149, 169, 229, 50, 175, 251, +158, 60, 119, 236, 204, 202, 143, 255, 24, 6, 18, 165, 102, +29, 125, 209, 99, 48, 182, 10, 251, 246, 154, 65, 172, 246, +242, 91, 215, 133, 29, 185, 252, 145, 166, 7, 31, 166, 70, +242, 16, 157, 145, 200, 215, 181, 226, 203, 181, 78, 110, 116, +68, 128, 22, 216, 183, 11, 234, 195, 145, 18, 97, 93, 98, +230, 236, 122, 18, 197, 236, 97, 244, 171, 147, 127, 21, 125, +216, 216, 84, 254, 197, 115, 53, 51, 146, 151, 205, 166, 73, +229, 196, 136, 189, 71, 100, 246, 211, 83, 237, 198, 164, 244, +21, 23, 155, 182, 188, 50, 129, 33, 169, 124, 28, 243, 161, +192, 36, 33, 29, 61, 118, 144, 247, 136, 3, 3, 3}; + diff --git a/crypto/test/rsaperf/rsa65537e4096.pem b/crypto/test/rsaperf/rsa65537e4096.pem new file mode 100644 index 0000000..fffbbd2 --- /dev/null +++ b/crypto/test/rsaperf/rsa65537e4096.pem @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,1439DA8FBC84289C + +T7uBMCKl3craDck/o9+QZY1cllfmO4q1EtAFmSMSUWomm+i3TxdoFmu9YRu5hWOv +RAufHOdFpXvFNrqDDn3RG5DCrTrPm/APf/tmBkj2W9LR18NntkabfsEIKYmAitWw +Q1t7LirSDQQSqJyL2K/wVfsjrlTeUbCE0W2vbrF7240XS6uZaWoa5pmoycYqQ5sV +iYefupgsXjtaDz0Iw3diRjw78RHwnsbGeOnGRG8BmjFqpUxal9qIXgS1RsgZA8LY +8V2eP1TuYaWTQowJpHt8IBNlzzr+qBMIEQ9tteFY1dm3tQuhMaj1Vylzr7C0fwdx +xBxCn6H4AOe3NwTEp03ExzgKI3Dz2LD4OCOvjAZ5DEnlXAko3V8i9zoiJrvUvXoG +35TVwTgmszTJwJUpXY3mC3LoB9vY/0Exgg1R1odY1LVj93R3RNpA+0kw5qDVfDff +tWarqLQyZB/BAOXgVlp0/jczw3vMIZRLwa3T+Gj2ji21nZ6JuLRMzuLMiMXSP0g6 +W6TNm/ggYJm0O5PN9OBwoFjJ8L7Y7D5VuIHkh0uvb1c/Eqp08SVhCPaUbbWttn1o +hksbsoZvV7z4AgffnxlPIJI/nqBRXMINIGlGfD04bHC+kvvhrY7efDZepUeYgjyH +nOojTVoyYoc7i0Mja/2S0LFm4k2c3ynuE6+v+wJ+VWw+zdIAqbkgnWLLM74WjO5Z +JZ5J9riBFdnuZq1LiioVEDaDXcIyXS5KcdN2EQE/pAPZv/ujcOtMXJEEHf9LqnE2 +oTyCVL5CjNBL0M8orniu6+4yqyQdZodcQ0qUPOwOBX9kk4NakL/h/Iviwx+1V6tq +Asl5jhY18GV9BXSdrqeqZIdbBdRVKVTpY2KCpfpghmm2B0Mkmo10WJuLeTZW9OC+ +kHcwaUUmyOWeUQmoxRRJDblZf3whk/ajbMKrPB/jvNqrYWbQRvyb25FOFhOc8dbz +QKeG0yPmCJGl9SmBzIESSQwPZd52E0i1t5Ns9XqgRO3HaNdtnlENOCTgFwcpUvdE +/2u4fJIKYRN3qq/+y/lPMZ7p74gXIIXhoeGXktVwyh6Xx6O7W1/nxCpextClwX2u +ygnsM+fx71YPFT2LZVEb3EtwP61H5YpmEE8Fxc+gnXY4gymVAG7rGu4Anrc49JQ8 +YXko9mreRnntmfeoS94FNRISWcnolQm5mhWbMr+5LUCEmMTGj+/NvjpIBdexIYgx +BxkYZ9A0IdnxeCsOzBq2uOiizHCYHLckMbYquKG68tW9uOeNtCVV0zUeJGvxkKHV +DyPPWC5/YKE+qCQ+zlVWqDzjKbufw7W1NMH4UOebR0Wp8bWBvBqPtuuPJN5r6Kf5 +mjj2cqYsNhpI+ECGoJarpngQ4HxJHcgkQrwcm2cdeZbNT5nhk3lGNLJ3+J3+8mdN +nQ0uGLcE1eCvEYIEHel+zdVuNviK8fS8qbDoZf2myw+X+RO0LzOK01NrxRlrh2PC +/64sHRO2DLyfEkhYjlY5lvSRBwWvnLpd2uaQfBZvQTOwIILKnFedaQvblyErSjA4 +wIC2L0KKCGjH3gjjESMk+K1bhdogdRVtGJX41matRxgsWK1bJz1Y4Ch6DDJM53l/ +NytyQul8xiA2CRKBRdwpyd1V8jyeJTzWhsNh4v03feMoKfFN5MqTROWh+LNDccft +0n16+GTbhiMRyQUV0jWCQPAEuEM6u8tbL2Xg8o6xHWQwvNl6H50RPAdeuaF6cq8E +tj5rgzuXsyatMeI4RIHSdklVwEGPySTZTvMmZT1EWOWVdycC0bGkVDuwl9XwVpwh +aRwRMl6E6y9E3T7+R3pv7ZtGhRjASdVVD9qfbiStwpPuaG9h8RLBLDaTZgOWgFAW +jGRx7IZzuRCpQOvPT+7hcA0HRFevVSah4IOx8ut7YS7eg725V+Tic3zotGGBLVQf +/u9ZdexuOsycGEO+2I6WaXbr47kojMl4yP1rJaiPcDN4+G1eGbfN6qUcYDE5+IE5 +aqsEKF/7XBrq35STrf2CmJc4VU7JQ/q0wIp9SWwGTuBo0ua2SO2VmcWh8zkNztQZ +MnQRpBPg4+pAi0YQOUMiZBmer2cuBQ7bV9tRgVlzNk5X9hPYSueX6npX2cqKY+39 +XKimxGJ7HigU+/N3g75AT7uCPkZYWlTH8PNGLLnoGht1kXkdebVZFo+1/qDQROb8 +YacaxpXMW58kSuJyxifrMTY5N1/xiUlgrp/xH8DBBoCXpWvINeasnum1hc3SIrfA +7FBlvWbuBBvL56B/BFSndpKUo+ZVAtchlItSFMq+3VhNrxM0dK7l2nS+svlcCu82 +OsyGtHhgBZrF/TMG6zlOF/cnWjR8vU+y8CjkNYtOtPCdDPYIZdNNEzchjf2hMb2a +fiyolE/9FHepK3pnP7TnBp6TDrUYBZYo5oIp7MjFx5JzvREutLSv8YeqqMZ9Q3ky +/PXnZOnHIh9Q1iHwogHdzFj8KjZboC2hskXjMW2hp7oKC/qFmF2HZuxD44WZ0u0o +1WV3B2slnccWymYu9cv/vfwj0JV5br7egcBIr9Sgj62/wOs34AJ73hhbv47qJYxi +5pIP0jKtWqKhsi9nOdNwJ3cWIVcM7uLkJy2zxENn/77rYcSE2HS6ZBWJA6W9dZoH +cATse4CTCLYgZ+kURL0peL1ZXfZQfOQZQ9jdgWxTIBgiJ68yCwhz1DIw4N6i8Hdh +bDDBJsKgNtDqkReq4NNCHZbpLA15y9HnrwyRMZR+FqrD0SHCeHB4dX91xutwwHgp +DLkN+N69PszwGiZMjLw1ZR/Kz9b1aevqs3SysbbMt1pHKW1/Zmj35YfkcUUFEoGV +JuHuQM7e7O8dsPY05IWNfFQTHWsT1+WN9t3WGM8LNrNsl6sppzySDEsIh7lL3oKU +YD4Q+FrV+0eMvdQhuVTzSUC/l73NH13gXbjcngm5K3zrrVbk4tT8V1Tagrh06sqy +xoEVX9U/U4SF7/NR82RgCsvbPhogBfuAIOR0yf2HDtpuIkVnEJ3NCHTVddG05rnq +Fxl1047ZjXIHQXTPwixbdQJAJxXo/iJrP5v8OQBjEgxOs8yCZxJLu0iRPIMMLXMB +PKXPQK1gpenUQnDyfa5TM0vs6/HLojHjUsjItyCM2+VEiFyKcAJtA4ludim40Z93 +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa65537e4096_1.h b/crypto/test/rsaperf/rsa65537e4096_1.h new file mode 100644 index 0000000..946ac98 --- /dev/null +++ b/crypto/test/rsaperf/rsa65537e4096_1.h @@ -0,0 +1,189 @@ +/** + * @file rsa65537e4096_1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa65537e40961[] = { +48, 130, 9, 41, 2, 1, 0, 2, 130, 2, 1, 0, 155, +95, 182, 139, 151, 108, 102, 42, 15, 181, 184, 132, 6, 139, +245, 203, 198, 99, 13, 72, 151, 128, 255, 202, 226, 71, 234, +193, 175, 168, 170, 95, 13, 143, 138, 12, 176, 62, 89, 185, +173, 85, 93, 185, 253, 25, 162, 233, 57, 222, 195, 87, 30, +137, 224, 232, 113, 101, 69, 252, 215, 109, 30, 67, 150, 248, +205, 219, 166, 25, 114, 86, 49, 43, 34, 40, 232, 77, 221, +81, 115, 156, 88, 243, 72, 181, 101, 212, 253, 19, 69, 164, +19, 11, 92, 219, 220, 69, 210, 145, 184, 160, 138, 220, 163, +34, 38, 202, 223, 115, 115, 87, 223, 83, 250, 109, 159, 193, +82, 172, 165, 29, 10, 12, 33, 32, 110, 103, 84, 197, 96, +5, 181, 152, 96, 37, 162, 211, 219, 171, 140, 9, 169, 241, +143, 4, 213, 148, 220, 135, 186, 59, 203, 97, 242, 51, 61, +211, 137, 25, 154, 216, 152, 172, 6, 251, 30, 94, 122, 171, +47, 145, 126, 203, 19, 155, 231, 235, 106, 40, 184, 66, 59, +82, 182, 14, 95, 137, 248, 95, 209, 170, 65, 217, 90, 221, +245, 73, 56, 109, 135, 140, 37, 255, 107, 70, 228, 19, 196, +26, 221, 2, 216, 67, 119, 191, 250, 155, 36, 228, 145, 72, +180, 29, 106, 149, 220, 247, 22, 83, 105, 203, 233, 19, 132, +158, 118, 4, 176, 156, 164, 30, 143, 189, 157, 180, 182, 30, +197, 227, 221, 158, 69, 147, 215, 31, 184, 146, 21, 160, 17, +221, 14, 111, 193, 151, 195, 73, 228, 7, 42, 164, 196, 23, +179, 32, 26, 190, 134, 239, 98, 52, 244, 162, 61, 249, 91, +207, 225, 71, 52, 213, 17, 199, 71, 164, 112, 71, 10, 45, +74, 54, 191, 37, 18, 106, 115, 15, 142, 212, 31, 64, 54, +132, 176, 23, 28, 90, 242, 249, 249, 22, 182, 10, 2, 136, +190, 15, 226, 123, 246, 39, 252, 72, 253, 180, 192, 158, 156, +126, 133, 146, 246, 92, 115, 209, 179, 143, 94, 224, 1, 115, +105, 15, 143, 180, 112, 130, 204, 209, 134, 205, 40, 200, 105, +12, 110, 72, 89, 52, 175, 67, 153, 14, 147, 141, 227, 228, +164, 102, 171, 81, 208, 244, 248, 198, 60, 9, 11, 238, 237, +7, 92, 181, 231, 64, 43, 194, 70, 83, 220, 80, 37, 35, +4, 164, 71, 141, 12, 222, 88, 74, 239, 109, 76, 88, 179, +112, 205, 26, 188, 211, 219, 41, 85, 16, 74, 126, 226, 22, +168, 192, 194, 90, 159, 120, 231, 55, 118, 219, 169, 253, 91, +218, 140, 152, 191, 95, 49, 157, 85, 54, 145, 234, 146, 100, +68, 231, 35, 178, 183, 14, 65, 12, 38, 164, 123, 108, 170, +38, 187, 165, 95, 27, 215, 163, 241, 181, 230, 253, 14, 200, +221, 22, 53, 66, 130, 224, 3, 64, 100, 0, 230, 7, 129, +112, 44, 18, 168, 16, 125, 150, 148, 82, 61, 82, 125, 241, +204, 148, 170, 7, 2, 3, 1, 0, 1, 2, 130, 2, 0, +24, 164, 161, 36, 217, 194, 249, 31, 65, 183, 158, 72, 222, +106, 243, 116, 187, 5, 249, 212, 226, 38, 181, 43, 94, 33, +110, 244, 2, 98, 219, 134, 208, 245, 75, 189, 128, 116, 155, +49, 142, 114, 228, 55, 60, 20, 5, 89, 61, 114, 254, 3, +130, 213, 246, 132, 151, 123, 171, 18, 147, 174, 124, 102, 214, +250, 166, 87, 232, 171, 207, 141, 41, 38, 64, 184, 65, 68, +28, 78, 175, 106, 4, 87, 173, 216, 11, 139, 49, 10, 141, +248, 156, 134, 168, 87, 60, 196, 28, 70, 61, 132, 197, 17, +130, 148, 71, 151, 212, 194, 16, 112, 198, 252, 160, 83, 35, +203, 251, 75, 99, 178, 203, 229, 169, 153, 101, 185, 96, 226, +31, 61, 56, 148, 174, 231, 57, 64, 165, 238, 58, 251, 75, +103, 131, 58, 14, 144, 26, 60, 50, 199, 10, 22, 130, 94, +43, 55, 178, 94, 139, 199, 63, 203, 197, 29, 174, 46, 233, +0, 222, 190, 18, 96, 174, 63, 3, 149, 60, 148, 177, 200, +219, 116, 222, 104, 64, 49, 247, 97, 103, 53, 60, 85, 119, +138, 141, 189, 107, 196, 63, 131, 244, 128, 226, 232, 111, 3, +77, 142, 191, 48, 20, 209, 250, 155, 201, 233, 50, 124, 72, +40, 194, 92, 138, 11, 179, 236, 194, 175, 63, 47, 246, 203, +64, 53, 11, 221, 233, 143, 38, 158, 172, 72, 180, 75, 53, +185, 130, 196, 133, 225, 117, 2, 162, 83, 103, 227, 195, 19, +224, 67, 25, 147, 177, 54, 186, 38, 171, 167, 52, 97, 100, +86, 248, 234, 215, 191, 9, 191, 192, 38, 13, 199, 190, 148, +212, 242, 59, 1, 145, 246, 192, 16, 187, 28, 77, 99, 49, +95, 139, 31, 207, 57, 173, 93, 192, 134, 88, 84, 141, 15, +204, 59, 77, 46, 151, 163, 151, 128, 215, 208, 239, 230, 167, +137, 189, 255, 65, 225, 131, 103, 178, 34, 3, 8, 106, 195, +36, 18, 57, 15, 16, 201, 58, 138, 79, 241, 25, 3, 183, +113, 254, 135, 160, 229, 108, 25, 48, 190, 23, 94, 248, 23, +9, 211, 122, 84, 157, 83, 133, 8, 147, 233, 77, 145, 144, +230, 118, 143, 191, 53, 147, 88, 96, 202, 211, 50, 250, 108, +49, 255, 122, 56, 30, 241, 145, 63, 158, 103, 193, 138, 99, +35, 189, 80, 117, 150, 206, 224, 121, 183, 51, 227, 102, 229, +25, 32, 250, 202, 123, 204, 155, 160, 192, 32, 152, 5, 236, +169, 18, 32, 177, 70, 0, 35, 163, 167, 33, 172, 170, 48, +139, 212, 211, 167, 156, 211, 202, 218, 60, 29, 213, 154, 223, +230, 54, 19, 186, 49, 69, 63, 9, 19, 46, 32, 236, 18, +11, 223, 0, 55, 202, 204, 1, 144, 82, 234, 87, 158, 197, +195, 202, 169, 242, 180, 98, 66, 25, 83, 119, 226, 86, 18, +229, 87, 153, 104, 87, 253, 184, 244, 126, 112, 32, 37, 197, +11, 71, 21, 231, 1, 2, 130, 1, 1, 0, 201, 91, 4, +35, 44, 22, 87, 91, 92, 176, 112, 60, 127, 94, 30, 171, +195, 105, 134, 194, 184, 24, 248, 112, 255, 147, 38, 249, 83, +155, 155, 101, 55, 103, 59, 228, 159, 136, 251, 235, 51, 154, +157, 11, 36, 148, 107, 138, 71, 130, 211, 69, 193, 22, 107, +141, 95, 197, 170, 202, 122, 16, 178, 221, 85, 238, 186, 48, +253, 47, 59, 146, 132, 79, 144, 67, 47, 255, 64, 199, 54, +100, 146, 70, 129, 52, 82, 105, 143, 99, 108, 118, 189, 2, +51, 150, 158, 46, 161, 85, 101, 103, 74, 159, 136, 138, 113, +150, 239, 55, 221, 139, 66, 209, 146, 6, 67, 1, 255, 17, +219, 123, 232, 198, 44, 214, 47, 2, 198, 232, 137, 28, 9, +146, 164, 6, 230, 161, 75, 244, 80, 27, 172, 107, 23, 175, +213, 156, 206, 42, 175, 75, 173, 213, 141, 46, 47, 130, 38, +29, 160, 26, 223, 119, 187, 158, 140, 65, 116, 133, 197, 5, +250, 13, 201, 85, 123, 16, 129, 238, 204, 136, 90, 81, 43, +239, 167, 12, 199, 122, 52, 212, 234, 151, 231, 24, 201, 48, +124, 186, 27, 243, 213, 76, 177, 165, 95, 49, 237, 212, 198, +102, 2, 54, 132, 115, 111, 11, 59, 240, 105, 175, 197, 164, +212, 222, 177, 1, 113, 128, 251, 129, 50, 71, 51, 66, 240, +172, 84, 92, 168, 182, 39, 39, 215, 217, 76, 57, 198, 234, +133, 188, 150, 47, 27, 7, 2, 130, 1, 1, 0, 197, 138, +42, 85, 164, 209, 195, 212, 121, 237, 10, 162, 143, 91, 84, +188, 35, 243, 155, 85, 39, 201, 169, 119, 141, 172, 205, 59, +218, 28, 13, 254, 158, 178, 209, 36, 231, 112, 38, 212, 84, +11, 199, 245, 7, 31, 132, 56, 178, 4, 255, 9, 73, 118, +226, 183, 203, 84, 22, 22, 18, 249, 8, 229, 133, 253, 63, +134, 59, 231, 116, 102, 251, 208, 46, 165, 166, 90, 236, 175, +34, 248, 126, 217, 153, 209, 241, 48, 69, 68, 199, 127, 167, +108, 185, 74, 228, 248, 43, 124, 67, 223, 135, 174, 52, 43, +179, 137, 39, 180, 221, 97, 68, 213, 66, 14, 129, 174, 105, +238, 9, 220, 137, 97, 58, 181, 189, 243, 32, 149, 140, 218, +234, 169, 231, 79, 24, 43, 129, 205, 32, 183, 113, 120, 244, +216, 89, 32, 80, 90, 195, 41, 237, 2, 152, 218, 136, 156, +229, 221, 74, 58, 255, 195, 159, 113, 137, 238, 101, 185, 26, +48, 195, 231, 167, 123, 64, 159, 110, 43, 96, 77, 71, 133, +199, 134, 246, 182, 105, 9, 1, 10, 197, 143, 177, 222, 13, +120, 209, 185, 160, 143, 78, 234, 111, 241, 213, 57, 157, 115, +236, 169, 143, 227, 53, 169, 48, 42, 79, 182, 235, 19, 71, +236, 21, 241, 128, 59, 0, 230, 111, 116, 228, 194, 187, 87, +220, 197, 115, 33, 193, 39, 201, 247, 162, 152, 11, 205, 97, +118, 85, 228, 166, 87, 57, 1, 2, 130, 1, 1, 0, 147, +136, 135, 192, 137, 166, 24, 253, 205, 45, 78, 31, 85, 167, +141, 203, 134, 147, 196, 116, 217, 213, 25, 252, 25, 151, 37, +96, 91, 221, 80, 255, 217, 151, 95, 112, 5, 96, 166, 76, +208, 115, 194, 11, 143, 18, 220, 180, 229, 238, 186, 132, 138, +148, 181, 219, 81, 72, 16, 250, 232, 115, 97, 203, 1, 18, +185, 3, 250, 14, 232, 148, 83, 51, 196, 221, 37, 198, 222, +28, 217, 2, 217, 150, 165, 70, 195, 247, 170, 99, 75, 238, +184, 80, 107, 162, 57, 102, 171, 57, 89, 226, 83, 240, 14, +104, 122, 16, 0, 89, 43, 143, 197, 54, 174, 202, 189, 192, +49, 183, 80, 221, 58, 82, 50, 58, 1, 26, 4, 202, 14, +228, 39, 51, 117, 209, 196, 156, 124, 125, 151, 80, 159, 133, +156, 70, 110, 186, 196, 232, 203, 166, 36, 201, 170, 247, 35, +66, 54, 81, 80, 165, 64, 5, 135, 200, 4, 182, 84, 253, +74, 190, 53, 88, 114, 163, 154, 87, 31, 12, 236, 122, 31, +203, 7, 233, 65, 186, 0, 82, 207, 113, 14, 46, 156, 218, +49, 87, 192, 155, 208, 173, 89, 37, 39, 168, 166, 214, 123, +143, 130, 138, 237, 166, 42, 104, 53, 253, 194, 62, 70, 1, +207, 76, 21, 216, 209, 82, 224, 106, 132, 93, 70, 140, 154, +199, 186, 118, 90, 29, 198, 84, 40, 222, 109, 174, 62, 198, +186, 179, 205, 167, 191, 86, 230, 115, 2, 130, 1, 0, 91, +27, 253, 168, 160, 171, 75, 42, 45, 206, 33, 176, 150, 116, +38, 97, 220, 39, 24, 134, 175, 34, 56, 242, 118, 58, 180, +50, 29, 200, 0, 192, 102, 75, 205, 96, 187, 10, 36, 46, +156, 81, 14, 185, 185, 190, 84, 138, 157, 184, 230, 52, 79, +88, 240, 250, 154, 98, 63, 9, 145, 88, 161, 60, 211, 142, +217, 132, 189, 14, 100, 198, 182, 239, 239, 3, 225, 245, 95, +226, 235, 59, 55, 174, 127, 94, 176, 98, 118, 32, 97, 239, +67, 182, 70, 195, 255, 85, 99, 33, 30, 96, 243, 192, 106, +57, 153, 197, 241, 181, 94, 193, 229, 48, 131, 22, 19, 195, +241, 1, 164, 52, 190, 124, 68, 202, 220, 64, 77, 208, 12, +54, 80, 51, 107, 7, 52, 251, 164, 19, 139, 58, 112, 176, +188, 37, 40, 254, 89, 113, 115, 64, 92, 27, 109, 138, 165, +165, 207, 243, 63, 176, 116, 148, 178, 110, 120, 146, 167, 2, +55, 205, 52, 30, 29, 70, 32, 169, 39, 244, 3, 167, 193, +12, 55, 217, 204, 226, 151, 17, 91, 20, 175, 200, 53, 222, +87, 210, 88, 208, 199, 248, 49, 10, 185, 245, 13, 70, 84, +147, 202, 28, 238, 203, 121, 205, 125, 244, 149, 237, 165, 0, +176, 148, 120, 14, 121, 249, 60, 210, 11, 168, 27, 118, 161, +87, 197, 240, 159, 200, 122, 193, 50, 74, 240, 8, 54, 177, +84, 121, 114, 230, 81, 190, 59, 1, 2, 130, 1, 1, 0, +182, 111, 70, 223, 179, 35, 48, 120, 127, 43, 87, 127, 14, +188, 252, 37, 44, 131, 228, 111, 72, 169, 63, 145, 25, 247, +185, 184, 125, 254, 83, 162, 205, 251, 178, 38, 124, 57, 251, +56, 121, 8, 249, 153, 25, 41, 214, 180, 40, 221, 213, 20, +225, 187, 48, 252, 5, 72, 47, 108, 233, 139, 85, 27, 230, +144, 169, 235, 154, 26, 15, 112, 173, 98, 106, 5, 212, 4, +130, 64, 207, 80, 179, 0, 95, 88, 28, 144, 78, 12, 144, +166, 150, 181, 66, 81, 50, 45, 143, 226, 157, 120, 104, 146, +169, 51, 23, 7, 79, 147, 67, 21, 55, 62, 236, 52, 32, +81, 163, 123, 194, 93, 175, 24, 17, 121, 42, 2, 185, 170, +198, 9, 19, 179, 38, 218, 22, 15, 12, 172, 23, 251, 80, +140, 3, 205, 73, 49, 6, 145, 86, 11, 213, 77, 100, 26, +254, 104, 32, 171, 250, 34, 187, 200, 163, 209, 102, 96, 224, +142, 150, 11, 187, 118, 9, 134, 193, 114, 227, 175, 184, 30, +129, 104, 173, 31, 119, 45, 9, 187, 34, 126, 250, 42, 117, +121, 198, 111, 235, 125, 48, 172, 193, 141, 73, 120, 194, 0, +229, 154, 205, 28, 190, 210, 67, 164, 125, 137, 50, 162, 222, +157, 127, 88, 122, 103, 44, 172, 157, 225, 131, 49, 111, 62, +209, 148, 90, 141, 245, 136, 171, 205, 103, 4, 68, 118, 238, +43, 166, 174, 157, 108, 44, 41, 104, 210, 3, 3, 3}; + diff --git a/crypto/test/rsaperf/rsa65537e4096_1.pem b/crypto/test/rsaperf/rsa65537e4096_1.pem new file mode 100644 index 0000000..e3fb096 --- /dev/null +++ b/crypto/test/rsaperf/rsa65537e4096_1.pem @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,6AC224C2E0E050D1 + +i7Fm0F+lKVKeNkvYx12z2UwsVuGKpLvMTnSeIafBW+1B7BiLPXk2mMy0V/+PSYV2 +1xVL+oeq1sUEms2/51MZ5x4ggUu56XP/RiYgkrTPEmQTmI+KBYrZHX4z7riTXhJC +UIDMJ9bt0o9GJ8kfT5Toon2EwU0ODi7yykKls7bvH2bmseSLRKST9S6nSYLti3lG +4YRiuW5RJKBtnFS95pYn3GL5y0VVy6hWytPM/d7gw1b+5CQ9G0HCu1LxVQ5ARabw +FTNaSMpAJW/s2C91NpITQmu6QpV5MGua4vH2UwIincB3enjz2X4TpuhJd1BtPUez +aR9TEZXOgw/p4kdHQVbzD5/T8Y834gegDUi3z8X+wCt2rZKzijBtrPfgdKbJ3zyk +v929Q90DWWScTgR6g5Dw2zehZ0oLGSpZIXEqblPE9ps3p0WP23N5BFPlRi/4WSca +nBdRMV9InASVsjhNmUJZ5xj+U4L02YatKMeTJUxE33MrbB9EgGdqIwHT5XaX/4Wp +l4UrXYn/JdFPbvcM1MFEDc8YM+bVOpyrLiPT9DbsPqdIhcBVbIQ3iqj08VskooTS +clHRgNa2YXaZvXsj88Vt3oLX3759lsvY3WAIf6IzSaz9JeWJKLoa96XC+jLlcEqs +h72s8ElTyF7jjs0WASNnheZmgCshod3gzpoYeEPvLrHmieaOiHQpSkiOqgGbVgIM +kHlLxifXdt+ta6f3ngtTE3FT2dC8VRbsy4BNYL+UVa2qzF1QgSxVzNDx4dIYk3eo +Ws8lyIXTtBO2h45YA9qvGoIdc3Pwj7VjbosSYdFswpcVG5IlEPSWD84JUq+7D/5C +1FnJlGHd28Aks9hYkK0hzKELjwOhaE4f3ZziDB1bdwdd3S5cLnPRmuwvFUoWXzen +JvukZIuvPdx9PJAZXwUvkDbq9OrtL1LgV10KgwhJ5TYeEAgVeJKh0q1kq/rh3QEH +Kn8Kja77VqPwezP4juyk0lPqoBE5+rncWpLlo9kirYiPSdUlJtv6dCQUsJFfvLe4 +nHCE6KUTUkGmJFxYqiH0AaQr1Lsm4/aLvGEUMo/u9JtNTtKBtqik0g8NyLtiX2Kh +uJKtKi6ljpgnJQDaBhWu/EJnj36h20LJsfwTPe3M2m8/PPowe9oEYb6WN5gsmZeG +l5AqC5Oxk8ca20MaEV5pA3ad44xXTDLzZLc3rLMjr9qTEA9HNFkskGFhkB3qlFBp +cIELMu20uGi++ce9A4hdwwxj4BXWtp7vMgvxjtfhXmHOTFsRyVqXkejLMkDuyoU0 +ENVJmAPKC9EEvJvtHnRqU7a+h2hiKLm7FWWd0SRDoh7A+6BBSg6DQZvpIFcNC8YY +vKr5tug1NXDNIG6K+7BG/MuriW5wmzs0SpxFLXTA+/IspDrmPtUu3ehscV7wrk3Q +XiXGJbav2SCpJJ4jK7hlCPhdMOJzxiv9Qhk+T/rk2j5xxGSzjYc2t0boRgsekhuK +m03Pc+oeSXYFI1hUs+CYlh+9k8AuHKevb4v3cNHj2NM8doKh1GXdvvKMM7ulCLMl +xhNlB3sLI3T6GoFdL+iC7y602T4e0sayZ+VJoHRbwm6cxPpMtAQ/hN3gXGC5XqYG +KGTBRGmycrf8pwqTa2qoCYvE5v5PLAkv5phVJlhoraus+HeJ94qrFbHwqqULXNPC +kr3/b+npHcbBsJiKcbDA8JjGkO/5ZDQ9Q7akkzvxEa7AIYmOf4fSoXiharnpXnmN +k0zBGpGq1T7X8VjDpykuLA3H5+vkXMnIMFilEh8+B94jNZPF7zYowmHIxT+oqxX2 +HNbzlRLDKCSWBhF+zLZwvbmUBVSF24hPRn01G4XPPfzm7eNBJ0LLDYXcVcQCENle +ei8XHzPQB0d6Q+wX7xcBGk7XUD46mlHOUxjD0FgNIJffSg9LvmeXVwogMspBrjU3 +hmjRmFu3zM1zTA3EAoN0e/tmFskMzz1yH2jPcriBqZlp5pY5t6BPK3Kbic5uYgmd +4m2Lz9dJse543lrFxMJpNxcDwGHCEhIdfBKqLxoTGZhgj0GV2AsPrUP3NoNp+CQ3 +JvXvLEJr73Biug7wRVjuNmf0909grEOPBqDOdr7b3ZDHB/8bG5NHQdjmIyp82kY2 +Z1M3FpY1E+KYZfT1h/RRsfvfv8qZa5VRK4AEBtgPCmWPHe7EMBss/3i0WL/TfqgQ +7Fqml4fM1dEjw3YMBspVYK3FEjtZ5+Sur+k041MKWH/JaUm4hniMNDESS51dJdhf +RGklRhN5XQCZJ47rfYhzFqKhifzuKYaj1DdnQc8zmL9H9kRjzRvvx2z8TTv46rlm +vQqzkGhFV5BQ02xYP2Xhhow5rfIG1baZd1KUzCQscm7+B6awAjR7UByNSEV4/62B +xQ027V+VUSbbrcfi8lajmbMDjBvYD+Yu42ar0XXN5Gz5FQMYR3YaQmbGoGasQxUO +0BK/OsClrt8moJIt6iZMWx5Q5V4SXBwc/2uaj75vbJOXgFL1hrkAUhHianGQMLc+ +Hd3u0y23oU43vuFQ2c2XdEP+hxXdaKaCnRCn8cyKeASk/JYihaXb5mnHHWbQ/2JG +NNv8z3FsfgVgdrF/bOnJYgBe/YZmMjzandqgi5+ES8UuBuIr9yS/otfmk1edXUFu +Ke7w8Cd6Yq0wRiJ3xXJiu62oZhIcOXXriV3S+KzJ4YBfzEJpBW80ihdSbLN/9+ay +l6LP0/zy5DU2YR8cJX0Q6QggnQBO+wNKd2f53QKO5adiE2w9bsOwvrfxvXdXGzQa +L2yvrks2efsqhMQGVvzH8HGfjlMlqksIK+D1mDLi4JRFdgL6niiADo8quM6rsU2y +pF2fANCaIjyRmTOr+pD9N/b6j2WStv7bGB/FP5fiwVQsaaX8DFVue65PPdca8R1b +tkMFf+Grpz9v0uE0O4ReAcGxL8S6ppOqjMj45re6oH3pIDTMlbuTBTNc3F6NIzzU +iDYNBThBj5Iggi758lT/6of7TKf+bNa31iA/pFhzkNGrA2nbzSk52KbgsBKxsDau +IFg3Jqo2mmi8MiZIPaYhOiqP+iejyxITprcvazNGtbvKJaPUXoaj5yxw8Bj4Q5jI +yXk5gqVrJ0dNXpFvMEnNgO03B8k3I4aov6J7tyNoWIduGYJr0bNwMOgc8Lfg+0Q6 +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa65537e512.h b/crypto/test/rsaperf/rsa65537e512.h new file mode 100644 index 0000000..3699d09 --- /dev/null +++ b/crypto/test/rsaperf/rsa65537e512.h @@ -0,0 +1,33 @@ +/** + * @file rsa65537e512.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa65537e512[] = { +48, 130, 1, 59, 2, 1, 0, 2, 65, 0, 190, 215, 203, +192, 64, 100, 80, 206, 204, 217, 85, 230, 102, 81, 171, 137, +20, 38, 226, 17, 177, 19, 173, 118, 81, 145, 61, 35, 143, +30, 245, 95, 124, 98, 128, 169, 127, 64, 102, 197, 22, 231, +45, 168, 109, 137, 169, 135, 44, 152, 186, 121, 206, 97, 191, +62, 220, 129, 238, 48, 187, 64, 110, 183, 2, 3, 1, 0, +1, 2, 64, 94, 44, 118, 235, 3, 219, 124, 212, 207, 217, +95, 190, 54, 55, 143, 2, 49, 227, 142, 35, 84, 210, 117, +2, 177, 245, 141, 202, 2, 82, 48, 154, 119, 79, 0, 81, +140, 127, 54, 236, 239, 17, 138, 101, 122, 203, 13, 245, 25, +179, 18, 155, 69, 23, 188, 139, 51, 134, 137, 29, 166, 10, +9, 33, 2, 33, 0, 236, 104, 233, 182, 239, 95, 105, 95, +196, 14, 15, 180, 117, 184, 81, 164, 173, 114, 243, 67, 135, +190, 164, 185, 227, 6, 16, 48, 110, 121, 177, 133, 2, 33, +0, 206, 168, 63, 181, 194, 242, 56, 41, 134, 234, 68, 94, +97, 64, 211, 38, 90, 187, 171, 205, 242, 99, 98, 46, 184, +240, 146, 245, 0, 176, 246, 11, 2, 33, 0, 210, 145, 59, +162, 66, 33, 100, 148, 244, 230, 101, 92, 162, 1, 211, 78, +111, 99, 84, 131, 144, 179, 224, 186, 229, 23, 240, 113, 130, +229, 7, 149, 2, 33, 0, 181, 14, 63, 83, 53, 203, 21, +93, 124, 176, 126, 217, 217, 134, 251, 247, 156, 130, 212, 17, +9, 141, 253, 21, 70, 62, 175, 226, 43, 138, 222, 229, 2, +32, 1, 192, 224, 213, 149, 37, 212, 99, 203, 136, 14, 68, +107, 12, 63, 208, 182, 30, 121, 79, 248, 102, 114, 42, 198, +158, 66, 164, 9, 45, 98, 59, 1}; + diff --git a/crypto/test/rsaperf/rsa65537e512.pem b/crypto/test/rsaperf/rsa65537e512.pem new file mode 100644 index 0000000..5151696 --- /dev/null +++ b/crypto/test/rsaperf/rsa65537e512.pem @@ -0,0 +1,12 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,A0F71413BEDB9FA4 + +TbQ9pUwemtXYKBbhT6c5UrlIeel2R1hUmx63Ruc8q3OTGKUnO96/8+kKem/zwsSL +zBOaQf9qhtDp8ghNSCJCG9TotTNhqTXGouzKX8kAGe2jw/CxQEERebojRQY8308o +jw9opxGvTIDfcR2WJiomqdI5gX4YQTLjTqi+BxRihVivedSFR3L7KPND09gu+Z4t +EryyOKt8QauVmeWpA2UpA7OVIFxHfuUzvcktRFH6BypKgiCAsIA7ORuzD8JVvQMA +qwpy27xAzjkqyOIbfJ5TMFywRPDT2RybYNLIGcc6fWYpUpVDpab7A7Hjo02Dxwtb +1QtKX3DpP/lKcoo5QABXEXZVhZPPdn+DuZ522EF1GSx8oNBwiU+4e8bKEBW3YvXb +6EFKUPa27FRPWCmYfNfeMrUc58YaMW55KSVz7AtGy9o= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsa65537e512_1.h b/crypto/test/rsaperf/rsa65537e512_1.h new file mode 100644 index 0000000..3c8a2e5 --- /dev/null +++ b/crypto/test/rsaperf/rsa65537e512_1.h @@ -0,0 +1,33 @@ +/** + * @file rsa65537e512_1.h + * @version $Format:%h%d$ + * + * Summary. + */ +const unsigned char rsa65537e5121[] = { +48, 130, 1, 59, 2, 1, 0, 2, 65, 0, 220, 191, 214, +139, 83, 143, 217, 73, 171, 252, 27, 158, 192, 45, 211, 179, +169, 115, 57, 66, 225, 153, 41, 198, 187, 113, 122, 78, 38, +31, 119, 245, 149, 179, 157, 135, 27, 84, 250, 246, 242, 223, +98, 47, 60, 160, 48, 218, 249, 52, 47, 84, 179, 184, 115, +188, 10, 139, 0, 220, 79, 14, 206, 221, 2, 3, 1, 0, +1, 2, 64, 65, 146, 46, 93, 102, 109, 229, 66, 79, 246, +236, 17, 100, 206, 120, 2, 247, 3, 133, 239, 202, 233, 95, +18, 108, 29, 82, 18, 34, 154, 216, 91, 170, 43, 61, 172, +94, 8, 216, 60, 35, 56, 202, 185, 158, 184, 116, 22, 221, +135, 72, 47, 75, 219, 59, 85, 48, 118, 81, 132, 166, 45, +145, 245, 2, 33, 0, 252, 4, 19, 166, 238, 96, 195, 11, +40, 23, 117, 114, 126, 43, 206, 215, 223, 178, 92, 229, 55, +77, 18, 88, 18, 207, 62, 200, 249, 248, 222, 27, 2, 33, +0, 224, 61, 57, 68, 189, 178, 195, 218, 247, 119, 150, 219, +255, 42, 196, 226, 223, 117, 132, 87, 40, 57, 40, 5, 204, +202, 94, 87, 197, 119, 118, 103, 2, 33, 0, 200, 15, 140, +114, 70, 102, 118, 47, 147, 34, 28, 80, 73, 173, 9, 69, +2, 6, 28, 12, 178, 187, 242, 70, 12, 152, 141, 37, 10, +155, 239, 229, 2, 32, 22, 71, 30, 220, 108, 120, 73, 43, +4, 240, 245, 164, 239, 169, 225, 27, 165, 21, 184, 203, 43, +236, 217, 196, 17, 191, 125, 53, 253, 33, 76, 59, 2, 33, +0, 166, 97, 225, 6, 191, 172, 71, 97, 22, 196, 165, 194, +29, 180, 138, 116, 199, 74, 165, 160, 170, 57, 121, 219, 227, +133, 142, 125, 185, 101, 90, 157, 1}; + diff --git a/crypto/test/rsaperf/rsa65537e512_1.pem b/crypto/test/rsaperf/rsa65537e512_1.pem new file mode 100644 index 0000000..d803b85 --- /dev/null +++ b/crypto/test/rsaperf/rsa65537e512_1.pem @@ -0,0 +1,12 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,B5CA9A4FE8E80700 + +4JJz6d4ubZzt7TmbcRFQWfK/A8sG1lv5o6J65QAlMX2AeJ4kif1oCCvrJkrqqcTG +40dHPtD7a8mruNmOmn/M1MoN67HftfSjT75Ps01LGIUIQdheJw/kafr52TeIbuo7 +A88ONjQAIKMUKV1iIwHKmwosWhXlSM6uRI8G24Q4z9Z2tl/7D53vkUj/J27J4GzC +yfA9C5x5ud8FMzTydXCyE7oIzo2zsSvq2mPIVSDntOtLiXYW7bF16xPaLCweRsf9 +olL81c+QYISuiiLmBHdVp6//qpoNQ6taTCqgECaTsG2TiK/0W11tcZIo2WeOOHVi +By+4LSx5fpX+kZLbAkEYF6tUsqwE9SSIsAGylo8qODkPX1YdUDLghauVbA6YSg1U +6Y2RQKZnsiM5/YAEE1LrKKTy+RkaH20YzH70ZME6yK4= +-----END RSA PRIVATE KEY----- diff --git a/crypto/test/rsaperf/rsaperf.c b/crypto/test/rsaperf/rsaperf.c new file mode 100644 index 0000000..4d92a02 --- /dev/null +++ b/crypto/test/rsaperf/rsaperf.c @@ -0,0 +1,552 @@ +/** + * @file rsaperf.c + * @version $Format:%h%d$ + * + * RSA performance testing . + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include /* sleep */ +#include "crypto/cryptoApi.h" + +typedef void pkaCmdInfo_t; + +/* OPERATIONS TO TEST */ +#define SIGN_OP /* Private encrypt operations */ +#define VERIFY_OP /* Public decrypt operations */ + +#define ENCRYPT_OP /* Public encrypt operations */ +#define DECRYPT_OP /* Private decrypt operations */ + +/* KEY SIZES TO TEST */ +#if (MIN_RSA_BITS <= 512) +#define DO_512 +#endif +#if (MIN_RSA_BITS <= 1024) +#define DO_1024 +#endif +#if (MIN_RSA_BITS <= 2048) +#define DO_2048 +#endif +#if (MIN_RSA_BITS <= 4096) +#define DO_4096 +#endif + +/* NUMBER OF ENCRYPTION OPERATIONS TO AVERAGE FOR EACH KEY LEN */ +#if defined(PSTM_64BIT) +#define ITER_512 512 +#define ITER_1024 256 +#define ITER_2048 128 +#define ITER_4096 64 +#elif defined(PSTM_32BIT) +#define ITER_512 256 +#define ITER_1024 128 +#define ITER_2048 64 +#define ITER_4096 32 +#else +#define ITER_512 16 +#define ITER_1024 8 +#define ITER_2048 4 +#define ITER_4096 2 +#endif + +/* Another pass with different keys */ +//#define INCLUDE_SECOND_SET + +#define PS_OH (sizeof(psPool_t)) + +/* + Tuned to smallest K for each key size and optimization setting. + Private key operations take about 1/2 the RAM when optimized for size +*/ +#ifdef PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM +#define POOL_SIGN_512 (1 * 1024) + PS_OH +#define POOL_VERIFY_512 (2 * 1024) + PS_OH +#define POOL_ENCRYPT_512 (2 * 1024) + PS_OH +#define POOL_DECRYPT_512 (1 * 1024) + PS_OH +#define POOL_MISC_512 (3 * 1024) + PS_OH + +#define POOL_SIGN_1024 (2 * 1024) + PS_OH +#define POOL_VERIFY_1024 (3 * 1024) + PS_OH +#define POOL_ENCRYPT_1024 (3 * 1024) + PS_OH +#define POOL_DECRYPT_1024 (2 * 1024) + PS_OH +#define POOL_MISC_1024 (4 * 1024) + PS_OH + +#define POOL_SIGN_2048 (3 * 1024) + PS_OH +#define POOL_VERIFY_2048 (5 * 1024) + PS_OH +#define POOL_ENCRYPT_2048 (5 * 1024) + PS_OH +#define POOL_DECRYPT_2048 (3 * 1024) + PS_OH +#define POOL_MISC_2048 (7 * 1024) + PS_OH + +#define POOL_SIGN_4096 (6 * 1024) + PS_OH +#define POOL_VERIFY_4096 (8 * 1024) + PS_OH +#define POOL_ENCRYPT_4096 (8 * 1024) + PS_OH +#define POOL_DECRYPT_4096 (6 * 1024) + PS_OH +#define POOL_MISC_4096 (12 * 1024) + PS_OH + +#else /* PS_PUBKEY_OPTIMIZE_FOR_FASTER_SPEED */ + +#define POOL_SIGN_512 (3 * 1024) + PS_OH +#define POOL_VERIFY_512 (2 * 1024) + PS_OH +#define POOL_ENCRYPT_512 (2 * 1024) + PS_OH +#define POOL_DECRYPT_512 (3 * 1024) + PS_OH +#define POOL_MISC_512 (4 * 1024) + PS_OH + +#define POOL_SIGN_1024 (5 * 1024) + PS_OH +#define POOL_VERIFY_1024 (3 * 1024) + PS_OH +#define POOL_ENCRYPT_1024 (3 * 1024) + PS_OH +#define POOL_DECRYPT_1024 (5 * 1024) + PS_OH +#define POOL_MISC_1024 (6 * 1024) + PS_OH + +#define POOL_SIGN_2048 (7 * 1024) + PS_OH +#define POOL_VERIFY_2048 (5 * 1024) + PS_OH +#define POOL_ENCRYPT_2048 (5 * 1024) + PS_OH +#define POOL_DECRYPT_2048 (7 * 1024) + PS_OH +#define POOL_MISC_2048 (9 * 1024) + PS_OH + +#define POOL_SIGN_4096 (13 * 1024) + PS_OH +#define POOL_VERIFY_4096 ( 8 * 1024) + PS_OH +#define POOL_ENCRYPT_4096 ( 8 * 1024) + PS_OH +#define POOL_DECRYPT_4096 (13 * 1024) + PS_OH +#define POOL_MISC_4096 (16 * 1024) + PS_OH +#endif + +#ifdef DO_512 +#include "rsa3e512.h" +#include "rsa17e512.h" +#include "rsa257e512.h" +#include "rsa65537e512.h" +#endif /* DO_512 */ + +#ifdef DO_1024 +#include "rsa3e1024.h" +#include "rsa17e1024.h" +#include "rsa257e1024.h" +#include "rsa65537e1024.h" +#endif /* DO_1024 */ + +#ifdef DO_2048 +#include "rsa3e2048.h" +#include "rsa17e2048.h" +#include "rsa257e2048.h" +#include "rsa65537e2048.h" +#endif /* DO_2048 */ + +#ifdef DO_4096 +#include "rsa3e4096.h" +#include "rsa17e4096.h" +#include "rsa257e4096.h" +#include "rsa65537e4096.h" +#endif /* DO_4096 */ + +#ifdef INCLUDE_SECOND_SET +#ifdef DO_512 +#include "rsa3e512_1.h" +#include "rsa17e512_1.h" +#include "rsa257e512_1.h" +#include "rsa65537e512_1.h" +#endif /* DO_512 */ + +#ifdef DO_1024 +#include "rsa3e1024_1.h" +#include "rsa17e1024_1.h" +#include "rsa257e1024_1.h" +#include "rsa65537e1024_1.h" +#endif /* DO_1024 */ + +#ifdef DO_2048 +#include "rsa3e2048_1.h" +#include "rsa17e2048_1.h" +#include "rsa257e2048_1.h" +#include "rsa65537e2048_1.h" +#endif /* DO_2048 */ + +#ifdef DO_4096 +#include "rsa3e4096_1.h" +#include "rsa17e4096_1.h" +#include "rsa257e4096_1.h" +#include "rsa65537e4096_1.h" +#endif /* DO_4096 */ +#endif /* INCLUDE_SECOND_SET */ + +typedef struct { + char *name; + const unsigned char *key; + uint32 len; + int32 iter; + int32 poolSign; + int32 poolVerify; + int32 poolEncrypt; + int32 poolDecrypt; + int32 poolMisc; +} keyList_t; + +#ifdef USE_HIGHRES_TIME + #define psDiffMsecs(A, B, C) (unsigned long long)psDiffUsecs(A, B) + #define TIME_UNITS " %lld usecs" + #define PER_SEC(A) ((A) ? (1000000 / (A)) : 0) +#else + #define TIME_UNITS " %d msecs" + #define PER_SEC(A) ((A) ? (1000 / (A)) : 0) +#endif + +/* + Add an iteration count so we don't have to run the large keys so many times +*/ +static keyList_t keys[] = { +#ifdef DO_512 + {"rsa3e512", rsa3e512, sizeof(rsa3e512), ITER_512, POOL_SIGN_512, + POOL_VERIFY_512, POOL_ENCRYPT_512, POOL_DECRYPT_512, POOL_MISC_512}, + {"rsa17e512", rsa17e512, sizeof(rsa17e512), ITER_512,POOL_SIGN_512, + POOL_VERIFY_512, POOL_ENCRYPT_512, POOL_DECRYPT_512, POOL_MISC_512}, + {"rsa257e512", rsa257e512, sizeof(rsa257e512), ITER_512, POOL_SIGN_512, + POOL_VERIFY_512, POOL_ENCRYPT_512, POOL_DECRYPT_512, POOL_MISC_512}, + {"rsa65537e512", rsa65537e512, sizeof(rsa65537e512), ITER_512, + POOL_SIGN_512, POOL_VERIFY_512, POOL_ENCRYPT_512, POOL_DECRYPT_512, + POOL_MISC_512}, +#endif +#ifdef DO_1024 + {"rsa3e1024", rsa3e1024, sizeof(rsa3e1024), ITER_1024, POOL_SIGN_1024, + POOL_VERIFY_1024, POOL_ENCRYPT_1024, POOL_DECRYPT_1024, + POOL_MISC_1024}, + {"rsa17e1024", rsa17e1024, sizeof(rsa17e1024), ITER_1024, POOL_SIGN_1024, + POOL_VERIFY_1024, POOL_ENCRYPT_1024, POOL_DECRYPT_1024, + POOL_MISC_1024}, + {"rsa257e1024", rsa257e1024, sizeof(rsa257e1024), ITER_1024, POOL_SIGN_1024, + POOL_VERIFY_1024, POOL_ENCRYPT_1024, POOL_DECRYPT_1024, + POOL_MISC_1024}, + {"rsa65537e1024", rsa65537e1024, sizeof(rsa65537e1024), ITER_1024, + POOL_SIGN_1024, POOL_VERIFY_1024, POOL_ENCRYPT_1024, POOL_DECRYPT_1024, + POOL_MISC_1024}, +#endif +#ifdef DO_2048 + {"rsa3e2048", rsa3e2048, sizeof(rsa3e2048), ITER_2048, POOL_SIGN_2048, + POOL_VERIFY_2048, POOL_ENCRYPT_2048, POOL_DECRYPT_2048, + POOL_MISC_2048}, + {"rsa17e2048", rsa17e2048, sizeof(rsa17e2048), ITER_2048, POOL_SIGN_2048, + POOL_VERIFY_2048, POOL_ENCRYPT_2048, POOL_DECRYPT_2048, + POOL_MISC_2048}, + {"rsa257e2048", rsa257e2048, sizeof(rsa257e2048), ITER_2048, POOL_SIGN_2048, + POOL_VERIFY_2048, POOL_ENCRYPT_2048, POOL_DECRYPT_2048, + POOL_MISC_2048}, + {"rsa65537e2048", rsa65537e2048, sizeof(rsa65537e2048), ITER_2048, + POOL_SIGN_2048, POOL_VERIFY_2048, POOL_ENCRYPT_2048, POOL_DECRYPT_2048, + POOL_MISC_2048}, +#endif +#ifdef DO_4096 + {"rsa3e4096", rsa3e4096, sizeof(rsa3e4096), ITER_4096, POOL_SIGN_4096, + POOL_VERIFY_4096, POOL_ENCRYPT_4096, POOL_DECRYPT_4096, + POOL_MISC_4096}, + {"rsa17e4096", rsa17e4096, sizeof(rsa17e4096), ITER_4096, POOL_SIGN_4096, + POOL_VERIFY_4096, POOL_ENCRYPT_4096, POOL_DECRYPT_4096, + POOL_MISC_4096}, + {"rsa257e4096", rsa257e4096, sizeof(rsa257e4096), ITER_4096, POOL_SIGN_4096, + POOL_VERIFY_4096, POOL_ENCRYPT_4096, POOL_DECRYPT_4096, + POOL_MISC_4096}, + {"rsa65537e4096", rsa65537e4096, sizeof(rsa65537e4096), ITER_4096, + POOL_SIGN_4096, POOL_VERIFY_4096, POOL_ENCRYPT_4096, POOL_DECRYPT_4096, + POOL_MISC_4096}, +#endif +#ifdef INCLUDE_SECOND_SET +#ifdef DO_512 + {"rsa3e512_1", rsa3e5121, sizeof(rsa3e5121), ITER_512, POOL_SIGN_512, + POOL_VERIFY_512, POOL_ENCRYPT_512, POOL_DECRYPT_512, POOL_MISC_512}, + {"rsa17e512_1", rsa17e5121, sizeof(rsa17e5121), ITER_512, POOL_SIGN_512, + POOL_VERIFY_512, POOL_ENCRYPT_512, POOL_DECRYPT_512, POOL_MISC_512}, + {"rsa257e512_1", rsa257e5121, sizeof(rsa257e5121), ITER_512, POOL_SIGN_512, + POOL_VERIFY_512, POOL_ENCRYPT_512, POOL_DECRYPT_512, POOL_MISC_512}, + {"rsa65537e512_1", rsa65537e5121, sizeof(rsa65537e5121), ITER_512, + POOL_SIGN_512, POOL_VERIFY_512, POOL_ENCRYPT_512, POOL_DECRYPT_512, + POOL_MISC_512}, +#endif +#ifdef DO_1024 + {"rsa3e1024_1", rsa3e10241, sizeof(rsa3e10241), ITER_1024, POOL_SIGN_1024, + POOL_VERIFY_1024, POOL_ENCRYPT_1024, POOL_DECRYPT_1024, + POOL_MISC_1024}, + {"rsa17e1024_1", rsa17e10241, sizeof(rsa17e10241), ITER_1024, + POOL_SIGN_1024, POOL_VERIFY_1024, POOL_ENCRYPT_1024, POOL_DECRYPT_1024, + POOL_MISC_1024}, + {"rsa257e1024_1", rsa257e10241, sizeof(rsa257e10241), ITER_1024, + POOL_SIGN_1024, POOL_VERIFY_1024, POOL_ENCRYPT_1024, POOL_DECRYPT_1024, + POOL_MISC_1024}, + {"rsa65537e1024_1", rsa65537e10241, sizeof(rsa65537e10241), ITER_1024, + POOL_SIGN_1024, POOL_VERIFY_1024, POOL_ENCRYPT_1024, POOL_DECRYPT_1024, + POOL_MISC_1024}, +#endif +#ifdef DO_2048 + {"rsa3e2048_1", rsa3e20481, sizeof(rsa3e20481), ITER_2048, POOL_SIGN_2048, + POOL_VERIFY_2048, POOL_ENCRYPT_2048, POOL_DECRYPT_2048, + POOL_MISC_2048}, + {"rsa17e2048_1", rsa17e20481, sizeof(rsa17e20481), ITER_2048, + POOL_SIGN_2048, POOL_VERIFY_2048, POOL_ENCRYPT_2048, POOL_DECRYPT_2048, + POOL_MISC_2048}, + {"rsa257e2048_1", rsa257e20481, sizeof(rsa257e20481), ITER_2048, + POOL_SIGN_2048, POOL_VERIFY_2048, POOL_ENCRYPT_2048, POOL_DECRYPT_2048, + POOL_MISC_2048}, + {"rsa65537e2048_1", rsa65537e20481, sizeof(rsa65537e20481), ITER_2048, + POOL_SIGN_2048, POOL_VERIFY_2048, POOL_ENCRYPT_2048, POOL_DECRYPT_2048, + POOL_MISC_2048}, +#endif +#ifdef DO_4096 + {"rsa3e4096_1", rsa3e40961, sizeof(rsa3e40961), ITER_4096, POOL_SIGN_4096, + POOL_VERIFY_4096, POOL_ENCRYPT_4096, POOL_DECRYPT_4096, + POOL_MISC_4096}, + {"rsa17e4096_1", rsa17e40961, sizeof(rsa17e40961), ITER_4096, + POOL_SIGN_4096, POOL_VERIFY_4096, POOL_ENCRYPT_4096, POOL_DECRYPT_4096, + POOL_MISC_4096}, + {"rsa257e4096_1", rsa257e40961, sizeof(rsa257e40961), ITER_4096, + POOL_SIGN_4096, POOL_VERIFY_4096, POOL_ENCRYPT_4096, POOL_DECRYPT_4096, + POOL_MISC_4096}, + {"rsa65537e4096_1", rsa65537e40961, sizeof(rsa65537e40961), ITER_4096, + POOL_SIGN_4096, POOL_VERIFY_4096, POOL_ENCRYPT_4096, POOL_DECRYPT_4096, + POOL_MISC_4096}, +#endif +#endif /* INCLUDE_SECOND_SET */ + {NULL, NULL, 0} +}; + +/******************************************************************************/ +/* + Main +*/ + + +#ifdef STATS + #include +#ifdef USE_HIGHRES_TIME + #define TIME_STRING "\t%lld" +#else + #define TIME_STRING "\t%d" +#endif +#endif + +int main(int argc, char **argv) +{ + psPool_t *pool, *misc; + psRsaKey_t privkey; + uint16_t keysize; + unsigned char *in, *out, *savein, *saveout; + psTime_t start, end; + uint32 iter, i = 0; + int32 t; + pkaCmdInfo_t *pkaInfo; +#ifdef STATS + FILE *sfd; +#endif + + pool = misc = NULL; + if(psCryptoOpen(PSCRYPTO_CONFIG) < PS_SUCCESS) { + _psTrace("Failed to initialize library: psCryptoOpen failed\n"); + return -1; + } + + pkaInfo = NULL; + + /* Verify time sanity */ + psGetTime(&start, NULL); + sleep(1); + psGetTime(&end, NULL); + printf("Time sanity, 1 second = " TIME_UNITS "\n", psDiffMsecs(start, end, NULL)); + + _psTraceStr("STARTING RSAPERF\n", NULL); +#ifdef STATS + if ((sfd = fopen("perfstat.txt", "w")) == NULL) { + return PS_FAILURE; + } +#ifdef USE_HIGHRES_TIME + fprintf(sfd, "Key\tSign(usec)\tVerify\tEncrypt\tDecrypt\n"); +#else + fprintf(sfd, "Key\tSign(msec)\tVerify\tEncrypt\tDecrypt\n"); +#endif +#endif /* STATS */ + + while (keys[i].key != NULL) { + _psTraceStr("Test %s...\n", keys[i].name); +#ifdef STATS + fprintf(sfd, "%s", keys[i].name); +#endif + psRsaInitKey(misc, &privkey); + if (psRsaParsePkcs1PrivKey(misc, keys[i].key, keys[i].len, &privkey) < 0) { + _psTrace(" FAILED TO PARSE PRIVATE KEY\n"); + continue; + } + //psRsaParsePkcs1PrivKeyOld(misc, keys[i].key, keys[i].len, &privkey); + keysize = psRsaSize(&privkey); + savein = in = psMalloc(misc, keysize); + psGetEntropy(in, keysize, NULL); + saveout = out = psMalloc(misc, keysize); + +#ifdef SIGN_OP + iter = 0; + psGetTime(&start, NULL); + while (iter < keys[i].iter) { + if (psRsaEncryptPriv(pool, &privkey, in, keysize - 16, + out, keysize, pkaInfo) < 0){ + _psTrace(" FAILED SIGNATURE OPERATION\n"); + } +/* + The idea here is that I wanted the encryption to happen over + an ever-changing value without adding any timing overhead by + going out and getting more random data (or whatever). So just + passing the output as the basis for the input each time. +*/ + in = out; +/* + TODO: The reason the out pointer switches back and forth is because + if the same addr is used for in and out, there is no change to + the data (after the first time?) even though the encryption + seems to happen. WHY IS THIS? +*/ + if (iter % 2) { + out = saveout; + } else { + out = savein; + } + iter++; + } + psGetTime(&end, NULL); + + _psTraceInt(TIME_UNITS "/sig ", + t = psDiffMsecs(start, end, NULL)/keys[i].iter); + _psTraceInt("(%d per sec)\n", PER_SEC(t)); + +#ifdef STATS + fprintf(sfd, TIME_STRING, t); +#endif +#endif /* SIGN_OP */ + +#ifdef VERIFY_OP + /* TODO: find a good way to time more than a single decrypt */ + memset(in, 0x0, keysize); + memcpy(in, "hello", 5); + if (psRsaEncryptPriv(misc, &privkey, in, 5, out, keysize, pkaInfo) < 0) { + _psTrace(" FAILED VERIFY PREP\n"); + } + memset(in, 0x0, keysize); + + psGetTime(&start, NULL); + if (psRsaDecryptPub(pool, &privkey, out, keysize, in, 5, pkaInfo) < 0) { + _psTrace(" FAILED VERIFY OPERATION\n"); + } + psGetTime(&end, NULL); + if (memcmp(in, "hello", 5) != 0) { + _psTrace(" FAILED VERIFY VERIFY\n"); + } + _psTraceInt(TIME_UNITS "/verify ", t = psDiffMsecs(start, end, NULL)); + _psTraceInt("(%d per sec)\n", PER_SEC(t)); +#ifdef STATS + fprintf(sfd, TIME_STRING, t); +#endif +#endif /* VERIFY_OP */ + +#ifdef ENCRYPT_OP + iter = 0; + psGetEntropy(in, keysize, NULL); + psGetTime(&start, NULL); + while (iter < keys[i].iter) { + if (psRsaEncryptPub(pool, &privkey, in, keysize - 16, + out, keysize, pkaInfo) < 0) { + _psTrace(" FAILED ENCRYPT OPERATION\n"); + } +/* + The idea here is that we wanted the encryption to happen over + an ever-changing value without adding any timing overhead by + going out and getting more random data (or whatever). So just + passing the output as the basis for the input each time. +*/ + in = out; +/* + TODO: The reason the out pointer switches back and forth is because + if the same addr is used for in and out, there is no change to + the data (after the first time?) even though the encryption + seems to happen. WHY IS THIS? +*/ + if (iter % 2) { + out = saveout; + } else { + out = savein; + } + iter++; + } + psGetTime(&end, NULL); + _psTraceInt(TIME_UNITS "/encrypt ", + t = psDiffMsecs(start, end, NULL)/keys[i].iter); + _psTraceInt("(%d per sec)\n", PER_SEC(t)); +#ifdef STATS + fprintf(sfd, TIME_STRING, t); +#endif +#endif /* ENCRYPT_OP */ + +#ifdef DECRYPT_OP +/* + TODO: find a good way to time more than a single decrypt +*/ + if (in == out) { + out = saveout; + } + memset(in, 0x0, keysize); + memcpy(in, "hello", 5); + if (psRsaEncryptPub(misc, &privkey, in, 5, out, keysize, pkaInfo) < 0) { + _psTrace(" FAILED VERIFY PREP\n"); + } + memset(in, 0x0, keysize); + + psGetTime(&start, NULL); + if (psRsaDecryptPriv(pool, &privkey, out, keysize, in, 5, pkaInfo) < 0) { + _psTrace(" FAILED DECRYPT OPERATION\n"); + } + psGetTime(&end, NULL); + if (memcmp(in, "hello", 5) != 0) { + _psTrace(" FAILED DECRYPT VERIFY\n"); + } + _psTraceInt(TIME_UNITS "/decrypt ", t = psDiffMsecs(start, end, NULL)); + _psTraceInt("(%d per sec)\n", PER_SEC(t)); +#ifdef STATS + fprintf(sfd, TIME_STRING "\n", t); +#endif +#endif /* DECRYPT_OP */ + + psFree(savein, misc); + psFree(saveout, misc); + psRsaClearKey(&privkey); + i++; + } + + +#ifdef STATS + fclose(sfd); +#endif +#ifdef WIN32 + _psTrace("Press any key to close"); + getchar(); +#endif + _psTraceStr("FINISHED RSAPERF\n", NULL); + psCryptoClose(); + return 0; +} diff --git a/crypto/test/throughputTest.c b/crypto/test/throughputTest.c new file mode 100644 index 0000000..d1ebe56 --- /dev/null +++ b/crypto/test/throughputTest.c @@ -0,0 +1,893 @@ +/** + * @file throughputTest.c + * @version $Format:%h%d$ + * + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "crypto/cryptoApi.h" + +#define DATABYTES_AMOUNT 100 * 1048576 /* # x 1MB (1024-byte variety) */ + +#define TINY_CHUNKS 16 +#define SMALL_CHUNKS 256 +#define MEDIUM_CHUNKS 1024 +#define LARGE_CHUNKS 4096 +#define HUGE_CHUNKS 16 * 1024 + +static unsigned char iv[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; + +static unsigned char key[32] = {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 }; + + +enum { + AES_ENC_ALG = 1, + AES_DEC_ALG, + AES_GCM_ALG, + ARC4_ALG, + DES3_ALG, + SEED_ALG, + IDEA_ALG, + + AES_HMAC_ALG, + AES_HMAC256_ALG, + + SHA1_ALG, + SHA256_ALG, + SHA384_ALG, + SHA512_ALG, + MD5_ALG +}; + +#if defined(USE_HMAC_SHA1) || defined(USE_HMAC_SHA256) +static void runWithHmac(psCipherContext_t *ctx, psHmac_t *hmac, + int32 hashSize, int32 chunk, int32 alg) +{ + psTime_t start, end; + unsigned char *dataChunk; + int32 bytesSent, bytesToSend, round; + unsigned char mac[MAX_HASH_SIZE]; +#ifdef USE_HIGHRES_TIME + int32 mod; + int64 diffu; +#else + int32 diffm; +#endif + + dataChunk = psMalloc(NULL, chunk); + memset(dataChunk, 0x0, chunk); + bytesToSend = (DATABYTES_AMOUNT / chunk) * chunk; + bytesSent = 0; + + switch (alg) { +#ifdef USE_AES +#ifdef USE_HMAC_SHA1 + case AES_HMAC_ALG: + psGetTime(&start, NULL); + while (bytesSent < bytesToSend) { +#ifdef USE_HMAC_TLS + static unsigned char hmacKey[64] = { 0, }; + unsigned char mac[20]; + psHmacSha1Tls(hmacKey, 20, dataChunk, chunk, + NULL, 0, NULL, 0, 0, mac); +#else + psHmacSha1Update(&hmac->u.sha1, dataChunk, chunk); +#endif + psAesEncryptCBC(&ctx->aes, dataChunk, dataChunk, chunk); + bytesSent += chunk; + } + psHmacSha1Final(&hmac->u.sha1, mac); + psGetTime(&end, NULL); + break; +#endif +#ifdef USE_HMAC_SHA256 + case AES_HMAC256_ALG: + psGetTime(&start, NULL); + while (bytesSent < bytesToSend) { +#ifdef USE_HMAC_TLS + static unsigned char hmacKey[64] = { 0, }; + unsigned char mac[32]; + psHmacSha2Tls(hmacKey, 32, dataChunk, chunk, + NULL, 0, NULL, 0, 0, mac, 32); +#else + psHmacSha256Update(&hmac->u.sha256, dataChunk, chunk); +#endif + psAesEncryptCBC(&ctx->aes, dataChunk, dataChunk, chunk); + bytesSent += chunk; + } + psHmacSha256Final(&hmac->u.sha256, mac); + psGetTime(&end, NULL); + break; +#endif +#endif + default: + printf("Skipping HMAC Test\n"); + return; + } + +#ifdef USE_HIGHRES_TIME + diffu = psDiffUsecs(start, end); + round = (bytesToSend / diffu); + mod = (bytesToSend % diffu); + printf("%d byte chunks in %lld usecs total for rate of %d.%d MB/sec\n", + chunk, (unsigned long long)diffu, round, mod); +#else + diffm = psDiffMsecs(start, end, NULL); + round = (bytesToSend / diffm) / 1000; + printf("%d byte chunks in %d msecs total for rate of %d MB/sec\n", + chunk, diffm, round); +#endif +} +#endif /* USE_HMAC */ + +static void runTime(psCipherContext_t *ctx, psCipherGivContext_t *ctx_giv, + int32 chunk, int32 alg) +{ + psTime_t start, end; + unsigned char *dataChunk; + int32 bytesSent, bytesToSend, round; +#ifdef USE_HIGHRES_TIME + int32 mod; + int64 diffu; +#else + int32 diffm; +#endif + + dataChunk = psMalloc(NULL, chunk + 16); + memset(dataChunk, 0x0, chunk); + bytesToSend = (DATABYTES_AMOUNT / chunk) * chunk; + bytesSent = 0; + + switch(alg) { +#ifdef USE_AES_CBC + case AES_ENC_ALG: + printf("Encrypt "); + psGetTime(&start, NULL); + while (bytesSent < bytesToSend) { + psAesEncryptCBC(&ctx->aes, dataChunk, dataChunk, chunk); + bytesSent += chunk; + } + psGetTime(&end, NULL); + break; + case AES_DEC_ALG: + printf("Decrypt "); + psGetTime(&start, NULL); + while (bytesSent < bytesToSend) { + psAesDecryptCBC(&ctx->aes, dataChunk, dataChunk, chunk); + bytesSent += chunk; + } + psGetTime(&end, NULL); + break; +#endif +#ifdef USE_AES_GCM + case AES_GCM_ALG: + psGetTime(&start, NULL); + while (bytesSent < bytesToSend) { + psAesEncryptGCM(&ctx->aesgcm, dataChunk, dataChunk, chunk); + bytesSent += chunk; + } + psAesGetGCMTag(&ctx->aesgcm, 16, dataChunk); + psGetTime(&end, NULL); + break; +#endif +#ifdef USE_ARC4 + case ARC4_ALG: + psGetTime(&start, NULL); + while (bytesSent < bytesToSend) { + psArc4(&ctx->arc4, dataChunk, dataChunk, chunk); + bytesSent += chunk; + } + psGetTime(&end, NULL); + break; +#endif +#ifdef USE_3DES + case DES3_ALG: + psGetTime(&start, NULL); + while (bytesSent < bytesToSend) { + psDes3Encrypt(&ctx->des3, dataChunk, dataChunk, chunk); + bytesSent += chunk; + } + psGetTime(&end, NULL); + break; +#endif +#ifdef USE_SEED + case SEED_ALG: + psGetTime(&start, NULL); + while (bytesSent < bytesToSend) { + psSeedEncrypt(&ctx->seed, dataChunk, dataChunk, chunk); + bytesSent += chunk; + } + psGetTime(&end, NULL); + break; +#endif +#ifdef USE_IDEA + case IDEA_ALG: + psGetTime(&start, NULL); + while (bytesSent < bytesToSend) { + psIdeaEncrypt(&ctx->idea, dataChunk, dataChunk, chunk); + bytesSent += chunk; + } + psGetTime(&end, NULL); + break; +#endif + default: + return; + } + + psFree(dataChunk, NULL); + +#ifdef USE_HIGHRES_TIME + diffu = psDiffUsecs(start, end); + round = (bytesToSend / diffu); + mod = (bytesToSend % diffu); + printf("%d byte chunks in %lld usecs total for rate of %d.%d MB/sec\n", + chunk, (unsigned long long)diffu, round, mod); +#else + diffm = psDiffMsecs(start, end, NULL); + round = (bytesToSend / diffm) / 1000; + printf("%d byte chunks in %d msecs total for rate of %d MB/sec\n", + chunk, diffm, round); +#endif + +} + +/******************************************************************************/ +#ifdef USE_AES_CBC +static int32 psAesTestCBC(void) +{ + int32 err; + psCipherContext_t eCtx; + +#if defined(USE_MATRIX_AES_CBC) && !defined(PS_AES_IMPROVE_PERF_INCREASE_CODESIZE) + _psTrace("##########\n#\n# "); + _psTrace("AES speeds can be improved by enabling\n# "); + _psTrace("PS_AES_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); + _psTrace("#\n#\n#########\n"); +#endif + + _psTrace("***** AES-128 CBC *****\n"); + if ((err = psAesInitCBC(&eCtx.aes, iv, key, 16, PS_AES_ENCRYPT)) != PS_SUCCESS) { + _psTraceInt("FAILED: returned %d\n", err); + return err; + } + runTime(&eCtx, NULL, TINY_CHUNKS, AES_ENC_ALG); + runTime(&eCtx, NULL, SMALL_CHUNKS, AES_ENC_ALG); + runTime(&eCtx, NULL, MEDIUM_CHUNKS, AES_ENC_ALG); + runTime(&eCtx, NULL, LARGE_CHUNKS, AES_ENC_ALG); + runTime(&eCtx, NULL, LARGE_CHUNKS, AES_DEC_ALG); + runTime(&eCtx, NULL, HUGE_CHUNKS, AES_ENC_ALG); + runTime(&eCtx, NULL, HUGE_CHUNKS, AES_DEC_ALG); + psAesClearCBC(&eCtx.aes); + + _psTrace("***** AES-192 CBC *****\n"); + if ((err = psAesInitCBC(&eCtx.aes, iv, key, 24, PS_AES_ENCRYPT)) != PS_SUCCESS) { + _psTraceInt("FAILED: returned %d\n", err); + return err; + } + runTime(&eCtx, NULL, TINY_CHUNKS, AES_ENC_ALG); + runTime(&eCtx, NULL, SMALL_CHUNKS, AES_ENC_ALG); + runTime(&eCtx, NULL, MEDIUM_CHUNKS, AES_ENC_ALG); + runTime(&eCtx, NULL, LARGE_CHUNKS, AES_ENC_ALG); + runTime(&eCtx, NULL, LARGE_CHUNKS, AES_DEC_ALG); + runTime(&eCtx, NULL, HUGE_CHUNKS, AES_ENC_ALG); + runTime(&eCtx, NULL, HUGE_CHUNKS, AES_DEC_ALG); + psAesClearCBC(&eCtx.aes); + + _psTrace("***** AES-256 CBC *****\n"); + if ((err = psAesInitCBC(&eCtx.aes, iv, key, 32, PS_AES_ENCRYPT)) != PS_SUCCESS) { + _psTraceInt("FAILED: returned %d\n", err); + return err; + } + runTime(&eCtx, NULL, TINY_CHUNKS, AES_ENC_ALG); + runTime(&eCtx, NULL, SMALL_CHUNKS, AES_ENC_ALG); + runTime(&eCtx, NULL, MEDIUM_CHUNKS, AES_ENC_ALG); + runTime(&eCtx, NULL, LARGE_CHUNKS, AES_ENC_ALG); + runTime(&eCtx, NULL, LARGE_CHUNKS, AES_DEC_ALG); + runTime(&eCtx, NULL, HUGE_CHUNKS, AES_ENC_ALG); + runTime(&eCtx, NULL, HUGE_CHUNKS, AES_DEC_ALG); + psAesClearCBC(&eCtx.aes); + + return 0; +} + +#if defined(USE_HMAC_SHA1) || defined(USE_HMAC_SHA256) +static int32 psAesTestCBCHmac(void) +{ + int32 err; + psCipherContext_t eCtx; + psHmac_t hCtx; + +#if defined(USE_MATRIX_AES_CBC) && !defined(PS_AES_IMPROVE_PERF_INCREASE_CODESIZE) + _psTrace("##########\n#\n# "); + _psTrace("AES speeds can be improved by enabling\n# "); + _psTrace("PS_AES_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); + _psTrace("#\n#\n#########\n"); +#endif + +#ifdef USE_HMAC_SHA1 + _psTrace("***** AES-128 CBC + SHA1-HMAC *****\n"); + if ((err = psAesInitCBC(&eCtx.aes, iv, key, 16, PS_AES_ENCRYPT)) != PS_SUCCESS) { + _psTraceInt("FAILED: returned %d\n", err); + return err; + } + psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); + runWithHmac(&eCtx, &hCtx, 0, TINY_CHUNKS, AES_HMAC_ALG); + psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); + runWithHmac(&eCtx, &hCtx, 0, SMALL_CHUNKS, AES_HMAC_ALG); + psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); + runWithHmac(&eCtx, &hCtx, 0, MEDIUM_CHUNKS, AES_HMAC_ALG); + psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); + runWithHmac(&eCtx, &hCtx, 0, LARGE_CHUNKS, AES_HMAC_ALG); + psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); + runWithHmac(&eCtx, &hCtx, 0, HUGE_CHUNKS, AES_HMAC_ALG); + psAesClearCBC(&eCtx.aes); + + _psTrace("***** AES-256 CBC + SHA1-HMAC *****\n"); + if ((err = psAesInitCBC(&eCtx.aes, iv, key, 32, PS_AES_ENCRYPT)) != PS_SUCCESS) { + _psTraceInt("FAILED: returned %d\n", err); + return err; + } + psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); + runWithHmac(&eCtx, &hCtx, 0, TINY_CHUNKS, AES_HMAC_ALG); + psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); + runWithHmac(&eCtx, &hCtx, 0, SMALL_CHUNKS, AES_HMAC_ALG); + psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); + runWithHmac(&eCtx, &hCtx, 0, MEDIUM_CHUNKS, AES_HMAC_ALG); + psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); + runWithHmac(&eCtx, &hCtx, 0, LARGE_CHUNKS, AES_HMAC_ALG); + psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); + runWithHmac(&eCtx, &hCtx, 0, HUGE_CHUNKS, AES_HMAC_ALG); + psAesClearCBC(&eCtx.aes); +#endif + +#ifdef USE_HMAC_SHA256 + _psTrace("***** AES-128 CBC + SHA256-HMAC *****\n"); + if ((err = psAesInitCBC(&eCtx.aes, iv, key, 16, PS_AES_ENCRYPT)) != PS_SUCCESS) { + _psTraceInt("FAILED: returned %d\n", err); + return err; + } + psHmacSha256Init(&hCtx.u.sha256, key, 32); + runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, TINY_CHUNKS, AES_HMAC256_ALG); + psHmacSha256Init(&hCtx.u.sha256, key, 32); + runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, SMALL_CHUNKS, AES_HMAC256_ALG); + psHmacSha256Init(&hCtx.u.sha256, key, 32); + runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, MEDIUM_CHUNKS, AES_HMAC256_ALG); + psHmacSha256Init(&hCtx.u.sha256, key, 32); + runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, LARGE_CHUNKS, AES_HMAC256_ALG); + psHmacSha256Init(&hCtx.u.sha256, key, 32); + runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, HUGE_CHUNKS, AES_HMAC256_ALG); + psAesClearCBC(&eCtx.aes); + + _psTrace("***** AES-256 CBC + SHA256-HMAC *****\n"); + if ((err = psAesInitCBC(&eCtx.aes, iv, key, 32, PS_AES_ENCRYPT)) != PS_SUCCESS) { + _psTraceInt("FAILED: returned %d\n", err); + return err; + } + psHmacSha256Init(&hCtx.u.sha256, key, 32); + runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, TINY_CHUNKS, AES_HMAC256_ALG); + psHmacSha256Init(&hCtx.u.sha256, key, 32); + runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, SMALL_CHUNKS, AES_HMAC256_ALG); + psHmacSha256Init(&hCtx.u.sha256, key, 32); + runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, MEDIUM_CHUNKS, AES_HMAC256_ALG); + psHmacSha256Init(&hCtx.u.sha256, key, 32); + runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, LARGE_CHUNKS, AES_HMAC256_ALG); + psHmacSha256Init(&hCtx.u.sha256, key, 32); + runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, HUGE_CHUNKS, AES_HMAC256_ALG); + psHmacSha256Init(&hCtx.u.sha256, key, 32); + psAesClearCBC(&eCtx.aes); +#endif + + return 0; +} +#endif /* USE_HMAC */ + +/******************************************************************************/ + +#ifdef USE_AES_GCM +int32 psAesTestGCM(void) +{ + int32 err; + psCipherContext_t eCtx; + psCipherGivContext_t eCtxGiv; + + memset(&eCtxGiv, 0, sizeof(eCtxGiv)); + +#ifndef USE_LIBSODIUM_AES_GCM + _psTrace("***** AES-GCM-128 *****\n"); + if ((err = psAesInitGCM(&eCtx.aesgcm, key, 16)) != PS_SUCCESS) { + _psTraceInt("FAILED: psAesInitGCM returned %d\n", err); + return err; + } + psAesReadyGCM(&eCtx.aesgcm, iv, iv, 16); + runTime(&eCtx, &eCtxGiv, TINY_CHUNKS, AES_GCM_ALG); + runTime(&eCtx, &eCtxGiv, SMALL_CHUNKS, AES_GCM_ALG); + runTime(&eCtx, &eCtxGiv, MEDIUM_CHUNKS, AES_GCM_ALG); + runTime(&eCtx, &eCtxGiv, LARGE_CHUNKS, AES_GCM_ALG); + runTime(&eCtx, &eCtxGiv, HUGE_CHUNKS, AES_GCM_ALG); +#else + _psTrace("***** Skipping AES-GCM-128 *****\n"); +#endif /* !USE_LIBSODIUM */ + + _psTrace("***** AES-GCM-256 *****\n"); + if ((err = psAesInitGCM(&eCtx.aesgcm, key, 32)) != PS_SUCCESS) { + _psTraceInt("FAILED: psAesInitGCM returned %d\n", err); + return err; + } + psAesReadyGCM(&eCtx.aesgcm, iv, iv, 16); + runTime(&eCtx, &eCtxGiv, TINY_CHUNKS, AES_GCM_ALG); + runTime(&eCtx, &eCtxGiv, SMALL_CHUNKS, AES_GCM_ALG); + runTime(&eCtx, &eCtxGiv, MEDIUM_CHUNKS, AES_GCM_ALG); + runTime(&eCtx, &eCtxGiv, LARGE_CHUNKS, AES_GCM_ALG); + runTime(&eCtx, &eCtxGiv, HUGE_CHUNKS, AES_GCM_ALG); + + psAesClearGCM(&eCtx.aesgcm); + + return PS_SUCCESS; +} +#endif /* USE_AES_GCM */ + +#endif /* USE_AES */ + +/******************************************************************************/ +#ifdef USE_3DES +int32 psDes3Test(void) +{ + psCipherContext_t eCtx; + +#if defined(USE_MATRIX_3DES) && !defined(PS_3DES_IMPROVE_PERF_INCREASE_CODESIZE) + _psTrace("##########\n#\n# "); + _psTrace("3DES speeds can be improved by enabling\n# "); + _psTrace("PS_3DES_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); + _psTrace("#\n#\n#########\n"); +#endif + + psDes3Init(&eCtx.des3, iv, key); + + runTime(&eCtx, NULL, TINY_CHUNKS, DES3_ALG); + runTime(&eCtx, NULL, SMALL_CHUNKS, DES3_ALG); + runTime(&eCtx, NULL, MEDIUM_CHUNKS, DES3_ALG); + runTime(&eCtx, NULL, LARGE_CHUNKS, DES3_ALG); + runTime(&eCtx, NULL, HUGE_CHUNKS, DES3_ALG); + + psDes3Clear(&eCtx.des3); + + return 0; +} +#endif /* USE_3DES */ +/******************************************************************************/ + +#ifdef USE_ARC4 +int32 psArc4Test(void) +{ + psCipherContext_t eCtx; + + psArc4Init(&eCtx.arc4, key, 16); + + runTime(&eCtx, NULL, TINY_CHUNKS, ARC4_ALG); + runTime(&eCtx, NULL, SMALL_CHUNKS, ARC4_ALG); + runTime(&eCtx, NULL, MEDIUM_CHUNKS, ARC4_ALG); + runTime(&eCtx, NULL, LARGE_CHUNKS, ARC4_ALG); + runTime(&eCtx, NULL, HUGE_CHUNKS, ARC4_ALG); + + psArc4Clear(&eCtx.arc4); + + return 0; +} +#endif /* USE_ARC4 */ + + +/******************************************************************************/ +#ifdef USE_SEED +int32 psSeedTest(void) +{ + psCipherContext_t eCtx; + + psSeedInit(&eCtx.seed, iv, key); + + runTime(&eCtx, NULL, TINY_CHUNKS, SEED_ALG); + runTime(&eCtx, NULL, SMALL_CHUNKS, SEED_ALG); + runTime(&eCtx, NULL, MEDIUM_CHUNKS, SEED_ALG); + runTime(&eCtx, NULL, LARGE_CHUNKS, SEED_ALG); + runTime(&eCtx, NULL, HUGE_CHUNKS, SEED_ALG); + + psSeedClear(&eCtx.seed); + + return PS_SUCCESS; +} +#endif /* USE_SEED */ +/******************************************************************************/ +#ifdef USE_IDEA +int32 psIdeaTest(void) +{ + psCipherContext_t eCtx; + + psIdeaInit(&eCtx.idea, iv, key); + + runTime(&eCtx, NULL, TINY_CHUNKS, IDEA_ALG); + runTime(&eCtx, NULL, SMALL_CHUNKS, IDEA_ALG); + runTime(&eCtx, NULL, MEDIUM_CHUNKS, IDEA_ALG); + runTime(&eCtx, NULL, LARGE_CHUNKS, IDEA_ALG); + runTime(&eCtx, NULL, HUGE_CHUNKS, IDEA_ALG); + + psIdeaClear(&eCtx.idea); + + return PS_SUCCESS; +} +#endif /* USE_IDEA */ +/******************************************************************************/ + +void runDigestTime(psDigestContext_t *ctx, int32 chunk, int32 alg) +{ + psTime_t start, end; + unsigned char *dataChunk; + unsigned char hashout[64]; + int32 bytesSent, bytesToSend, round; +#ifdef USE_HIGHRES_TIME + int32 mod; + int64 diffu; +#else + int32 diffm; +#endif + + dataChunk = psMalloc(NULL, chunk); + bytesToSend = (DATABYTES_AMOUNT / chunk) * chunk; + bytesSent = 0; + + switch (alg) { +#ifdef USE_SHA1 + case SHA1_ALG: + psGetTime(&start, NULL); + while (bytesSent < bytesToSend) { + psSha1Update(&ctx->sha1, dataChunk, chunk); + bytesSent += chunk; + } + psSha1Final(&ctx->sha1, hashout); + psGetTime(&end, NULL); + break; +#endif +#ifdef USE_SHA256 + case SHA256_ALG: + psGetTime(&start, NULL); + while (bytesSent < bytesToSend) { + psSha256Update(&ctx->sha256, dataChunk, chunk); + bytesSent += chunk; + } + psSha256Final(&ctx->sha256, hashout); + psGetTime(&end, NULL); + break; +#endif +#ifdef USE_SHA384 + case SHA384_ALG: + psGetTime(&start, NULL); + while (bytesSent < bytesToSend) { + psSha384Update(&ctx->sha384, dataChunk, chunk); + bytesSent += chunk; + } + psSha384Final(&ctx->sha384, hashout); + psGetTime(&end, NULL); + break; +#endif +#ifdef USE_SHA512 + case SHA512_ALG: + psGetTime(&start, NULL); + while (bytesSent < bytesToSend) { + psSha512Update(&ctx->sha512, dataChunk, chunk); + bytesSent += chunk; + } + psSha512Final(&ctx->sha512, hashout); + psGetTime(&end, NULL); + break; +#endif +#ifdef USE_MD5 + case MD5_ALG: + psGetTime(&start, NULL); + while (bytesSent < bytesToSend) { + psMd5Update(&ctx->md5, dataChunk, chunk); + bytesSent += chunk; + } + psMd5Final(&ctx->md5, hashout); + psGetTime(&end, NULL); + break; +#endif + default: + printf("Skipping Digest Tests\n"); + return; + } + +#ifdef USE_HIGHRES_TIME + diffu = psDiffUsecs(start, end); + round = (bytesToSend / diffu); + mod = (bytesToSend % diffu); + printf("%d byte chunks in %lld usecs total for rate of %d.%d MB/sec\n", + chunk, (unsigned long long)diffu, round, mod); +#else + diffm = psDiffMsecs(start, end, NULL); + round = (bytesToSend / diffm) / 1000; + printf("%d byte chunks in %d msecs total for rate of %d MB/sec\n", + chunk, diffm, round); +#endif + +} + +/******************************************************************************/ +#ifdef USE_SHA1 +int32 psSha1Test(void) +{ + psDigestContext_t ctx; +#if defined(USE_MATRIX_SHA1) && !defined(PS_SHA1_IMPROVE_PERF_INCREASE_CODESIZE) + _psTrace("##########\n#\n# "); + _psTrace("SHA-1 speeds can be improved by enabling\n# "); + _psTrace("PS_SHA1_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); + _psTrace("#\n#\n#########\n"); +#endif + + + psSha1Init(&ctx.sha1); + runDigestTime(&ctx, TINY_CHUNKS, SHA1_ALG); + runDigestTime(&ctx, SMALL_CHUNKS, SHA1_ALG); + runDigestTime(&ctx, MEDIUM_CHUNKS, SHA1_ALG); + runDigestTime(&ctx, LARGE_CHUNKS, SHA1_ALG); + runDigestTime(&ctx, HUGE_CHUNKS, SHA1_ALG); + + return PS_SUCCESS; +} + +#endif /* USE_SHA1 */ +/******************************************************************************/ + +/******************************************************************************/ +#ifdef USE_SHA256 +int32 psSha256Test(void) +{ + psDigestContext_t ctx; + + psSha256Init(&ctx.sha256); + runDigestTime(&ctx, TINY_CHUNKS, SHA256_ALG); + runDigestTime(&ctx, SMALL_CHUNKS, SHA256_ALG); + runDigestTime(&ctx, MEDIUM_CHUNKS, SHA256_ALG); + runDigestTime(&ctx, LARGE_CHUNKS, SHA256_ALG); + runDigestTime(&ctx, HUGE_CHUNKS, SHA256_ALG); + + return PS_SUCCESS; +} +#endif /* USE_SHA256 */ +/******************************************************************************/ + +#ifdef USE_SHA384 +int32 psSha384Test(void) +{ + psDigestContext_t ctx; + + psSha384Init(&ctx.sha384); + runDigestTime(&ctx, TINY_CHUNKS, SHA384_ALG); + runDigestTime(&ctx, SMALL_CHUNKS, SHA384_ALG); + runDigestTime(&ctx, MEDIUM_CHUNKS, SHA384_ALG); + runDigestTime(&ctx, LARGE_CHUNKS, SHA384_ALG); + runDigestTime(&ctx, HUGE_CHUNKS, SHA384_ALG); + + return PS_SUCCESS; +} +#endif /* USE_SHA384 */ + + +#ifdef USE_SHA512 +int32 psSha512Test(void) +{ + psDigestContext_t ctx; + + psSha512Init(&ctx.sha512); + runDigestTime(&ctx, TINY_CHUNKS, SHA512_ALG); + runDigestTime(&ctx, SMALL_CHUNKS, SHA512_ALG); + runDigestTime(&ctx, MEDIUM_CHUNKS, SHA512_ALG); + runDigestTime(&ctx, LARGE_CHUNKS, SHA512_ALG); + runDigestTime(&ctx, HUGE_CHUNKS, SHA512_ALG); + + return PS_SUCCESS; +} +#endif /* USE_SHA512 */ + + +/******************************************************************************/ +#ifdef USE_MD5 +int32 psMd5Test(void) +{ + psDigestContext_t ctx; +#if defined(USE_MATRIX_MD5) && !defined(PS_MD5_IMPROVE_PERF_INCREASE_CODESIZE) + _psTrace("##########\n#\n# "); + _psTrace("MD5 speeds can be improved by enabling\n# "); + _psTrace("PS_MD5_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); + _psTrace("#\n#\n#########\n"); +#endif + + psMd5Init(&ctx.md5); + runDigestTime(&ctx, TINY_CHUNKS, MD5_ALG); + runDigestTime(&ctx, SMALL_CHUNKS, MD5_ALG); + runDigestTime(&ctx, MEDIUM_CHUNKS, MD5_ALG); + runDigestTime(&ctx, LARGE_CHUNKS, MD5_ALG); + runDigestTime(&ctx, HUGE_CHUNKS, MD5_ALG); + + return PS_SUCCESS; +} +#endif /* USE_MD5 */ +/******************************************************************************/ + +/******************************************************************************/ +#ifdef USE_MD4 +int32 psMd4Test(void) +{ + return PS_SUCCESS; +} +#endif /* USE_MD4 */ +/******************************************************************************/ + +/******************************************************************************/ +#ifdef USE_MD2 +int32 psMd2Test(void) +{ + return PS_SUCCESS; +} +#endif /* USE_MD2 */ +/******************************************************************************/ + +/******************************************************************************/ + +typedef struct { + int32 (*fn)(void); + char name[64]; +} test_t; + +static test_t tests[] = { +#ifdef USE_AES +{psAesTestCBC, "***** AES-CBC TESTS *****"}, +#if defined(USE_HMAC_SHA1) || defined(USE_HMAC_SHA256) +{psAesTestCBCHmac, "***** AES-CBC + HMAC TESTS *****"}, +#endif +#ifdef USE_AES_GCM +{psAesTestGCM, "***** AES-GCM TESTS *****"}, +#endif +#else +{NULL, "AES"}, +#endif + +#ifdef USE_3DES +{psDes3Test +#else +{NULL +#endif +, "***** 3DES TESTS *****"}, + +#ifdef USE_SEED +{psSeedTest +#else +{NULL +#endif +, "***** SEED TESTS *****"}, + +#ifdef USE_IDEA +{psIdeaTest +#else +{NULL +#endif +, "***** IDEA TESTS *****"}, + +#ifdef USE_ARC4 +{psArc4Test +#else +{NULL +#endif +, "***** RC4 TESTS *****"}, + + +#ifdef USE_SHA1 +{psSha1Test +#else +{NULL +#endif +, "***** SHA1 TESTS *****"}, + +#ifdef USE_SHA256 +{psSha256Test +#else +{NULL +#endif +, "***** SHA256 TESTS *****"}, + +#ifdef USE_SHA384 +{psSha384Test +#else +{NULL +#endif +, "***** SHA384 TESTS *****"}, + +#ifdef USE_SHA512 +{psSha512Test +#else +{NULL +#endif +, "***** SHA512 TESTS *****"}, + +#ifdef USE_MD5 +{psMd5Test +#else +{NULL +#endif +, "***** MD5 TESTS *****"}, + +#ifdef USE_MD4 +{psMd4Test +#else +{NULL +#endif +, "***** MD4 TESTS *****"}, + +#ifdef USE_MD2 +{psMd2Test +#else +{NULL +#endif +, "***** MD2 TESTS *****"}, + +{NULL, ""} +}; + +/******************************************************************************/ +/* + Main +*/ + +int main(int argc, char **argv) +{ + int32 i; + + if (psCryptoOpen(PSCRYPTO_CONFIG) < PS_SUCCESS) { + _psTrace("Failed to initialize library: psCryptoOpen failed\n"); + return -1; + } + + for (i = 0; *tests[i].name; i++) { + if (tests[i].fn) { + _psTraceStr("%s\n", tests[i].name); + tests[i].fn(); + } else { + _psTraceStr("%s: SKIPPED\n", tests[i].name); + } + } + psCryptoClose(); + +#ifdef WIN32 + _psTrace("Press any key to close"); + getchar(); +#endif + + return 0; +} diff --git a/matrixssl/Makefile b/matrixssl/Makefile new file mode 100755 index 0000000..9bf56ec --- /dev/null +++ b/matrixssl/Makefile @@ -0,0 +1,46 @@ +# +# Makefile for MatrixSSL static library +# 'make' builds debug (Default). +# 'make gold' builds optimized. +# +# Copyright (c) 2013-2016 INSIDE Secure Corporation. All Rights Reserved. +# + +MATRIXSSL_ROOT:=.. +include $(MATRIXSSL_ROOT)/common.mk + +SRC:=\ + cipherSuite.c \ + extDecode.c \ + hsDecode.c \ + hsHash.c \ + matrixssl.c \ + matrixsslApi.c \ + prf.c \ + psk.c \ + sslDecode.c \ + sslEncode.c \ + sslv3.c \ + tls.c +#DTLS +SRC+=dtls.c +#DTLS + +# Generated files +STATIC:=libssl_s.a + +all: compile + +compile: $(OBJS) $(STATIC) + +# Additional Dependencies +$(OBJS): $(MATRIXSSL_ROOT)/common.mk Makefile *.h + +# Build the static library +# Redirect stderr to null so we don't see the 'empty file' warnings +$(STATIC): $(OBJS) + $(AR) -rcuv $@ $^ 2>/dev/null + +clean: + rm -f $(STATIC) $(OBJS) + diff --git a/matrixssl/cipherSuite.c b/matrixssl/cipherSuite.c new file mode 100644 index 0000000..7e1fa93 --- /dev/null +++ b/matrixssl/cipherSuite.c @@ -0,0 +1,2792 @@ +/** + * @file cipherSuite.c + * @version $Format:%h%d$ + * + * Wrappers for the various cipher suites.. + * Enable specific suites at compile time in matrixsslConfig.h + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "matrixsslApi.h" + +/******************************************************************************/ +/* Symmetric cipher initializtion wrappers for cipher suites */ +/******************************************************************************/ +/* + SSL_NULL_WITH_NULL_NULL cipher functions + Used in handshaking before SSL_RECORD_TYPE_CHANGE_CIPHER_SPEC message +*/ +static int32 csNullInit(sslSec_t *sec, int32 type, uint32 keysize) +{ + return 0; +} + +/******************************************************************************/ +#if defined(USE_ARC4) && defined(USE_ARC4_CIPHER_SUITE) +/******************************************************************************/ +static int32 csArc4Init(sslSec_t *sec, int32 type, uint32 keysize) +{ + if (type == INIT_ENCRYPT_CIPHER) { + psArc4Init(&(sec->encryptCtx.arc4), sec->writeKey, keysize); + } else { + psArc4Init(&(sec->decryptCtx.arc4), sec->readKey, keysize); + } + return PS_SUCCESS; +} +int32 csArc4Encrypt(void *ssl, unsigned char *pt, + unsigned char *ct, uint32 len) +{ + ssl_t *lssl = ssl; + psArc4_t *ctx = &lssl->sec.encryptCtx.arc4; + + psArc4(ctx, pt, ct, len); + return len; +} +int32 csArc4Decrypt(void *ssl, unsigned char *ct, + unsigned char *pt, uint32 len) +{ + ssl_t *lssl = ssl; + psArc4_t *ctx = &lssl->sec.decryptCtx.arc4; + + psArc4(ctx, ct, pt, len); + return len; +} + +#endif /* USE_ARC4_CIPHER_SUITE */ +/******************************************************************************/ + +/******************************************************************************/ +#if defined(USE_3DES) && defined (USE_3DES_CIPHER_SUITE) +/******************************************************************************/ +static int32 csDes3Init(sslSec_t *sec, int32 type, uint32 keysize) +{ + int32 err; + + psAssert(keysize == DES3_KEYLEN); + + if (type == INIT_ENCRYPT_CIPHER) { + if ((err = psDes3Init(&(sec->encryptCtx.des3), sec->writeIV, sec->writeKey)) < 0) { + return err; + } + } else { + if ((err = psDes3Init(&(sec->decryptCtx.des3), sec->readIV, sec->readKey)) < 0) { + return err; + } + } + return PS_SUCCESS; +} + +int32 csDes3Encrypt(void *ssl, unsigned char *pt, + unsigned char *ct, uint32 len) +{ + ssl_t *lssl = ssl; + psDes3_t *ctx = &lssl->sec.encryptCtx.des3; + + psDes3Encrypt(ctx, pt, ct, len); + return len; +} + +int32 csDes3Decrypt(void *ssl, unsigned char *ct, + unsigned char *pt, uint32 len) +{ + ssl_t *lssl = ssl; + psDes3_t *ctx = &lssl->sec.decryptCtx.des3; + + psDes3Decrypt(ctx, ct, pt, len); + return len; +} + +#endif /* USE_3DES_CIPHER_SUITE */ +/******************************************************************************/ + +#ifdef USE_AES_CIPHER_SUITE +#ifdef USE_TLS_1_2 +#ifdef USE_AES_GCM +int32 csAesGcmInit(sslSec_t *sec, int32 type, uint32 keysize) +{ + int32 err; + + if (type == INIT_ENCRYPT_CIPHER) { + memset(&sec->encryptCtx.aesgcm, 0, sizeof(psAesGcm_t)); + if ((err = psAesInitGCM(&sec->encryptCtx.aesgcm, sec->writeKey, + keysize)) < 0) { + return err; + } + } else { + memset(&sec->decryptCtx.aesgcm, 0, sizeof(psAesGcm_t)); + if ((err = psAesInitGCM(&sec->decryptCtx.aesgcm, sec->readKey, + keysize)) < 0) { + return err; + } + } + return 0; +} + +int32 csAesGcmEncrypt(void *ssl, unsigned char *pt, + unsigned char *ct, uint32 len) +{ + ssl_t *lssl = ssl; + psAesGcm_t *ctx; + unsigned char nonce[12]; + unsigned char aad[TLS_GCM_AAD_LEN]; + int32 i, ptLen, seqNotDone; + + if (len == 0) { + return PS_SUCCESS; + } + + if (len < 16 + 1) { + return PS_LIMIT_FAIL; + } + ptLen = len - TLS_GCM_TAG_LEN; + + ctx = &lssl->sec.encryptCtx.aesgcm; + + memcpy(nonce, lssl->sec.writeIV, 4); + + seqNotDone = 1; + /* Each value of the nonce_explicit MUST be distinct for each distinct + invocation of the GCM encrypt function for any fixed key. Failure to + meet this uniqueness requirement can significantly degrade security. + The nonce_explicit MAY be the 64-bit sequence number. */ +#ifdef USE_DTLS + if (lssl->flags & SSL_FLAGS_DTLS) { + memcpy(nonce + 4, lssl->epoch, 2); + memcpy(nonce + 4 + 2, lssl->rsn, 6); + /* In the case of DTLS the counter is formed from the concatenation of + the 16-bit epoch with the 48-bit sequence number.*/ + memcpy(aad, lssl->epoch, 2); + memcpy(aad + 2, lssl->rsn, 6); + seqNotDone = 0; + } +#endif + + if (seqNotDone) { + memcpy(nonce + 4, lssl->sec.seq, TLS_EXPLICIT_NONCE_LEN); + memcpy(aad, lssl->sec.seq, 8); + } + aad[8] = lssl->outRecType; + aad[9] = lssl->majVer; + aad[10] = lssl->minVer; + aad[11] = ptLen >> 8 & 0xFF; + aad[12] = ptLen & 0xFF; + + psAesReadyGCM(ctx, nonce, aad, TLS_GCM_AAD_LEN); + psAesEncryptGCM(ctx, pt, ct, ptLen); + psAesGetGCMTag(ctx, 16, ct + ptLen); + +#ifdef USE_DTLS + if (lssl->flags & SSL_FLAGS_DTLS) { + return len; + } +#endif + + /* Normally HMAC would increment the sequence */ + for (i = 7; i >= 0; i--) { + lssl->sec.seq[i]++; + if (lssl->sec.seq[i] != 0) { + break; + } + } + return len; +} + +int32 csAesGcmDecrypt(void *ssl, unsigned char *ct, + unsigned char *pt, uint32 len) +{ + ssl_t *lssl = ssl; + psAesGcm_t *ctx; + int32 i, ctLen, bytes, seqNotDone; + unsigned char nonce[12]; + unsigned char aad[TLS_GCM_AAD_LEN]; + + ctx = &lssl->sec.decryptCtx.aesgcm; + + seqNotDone = 1; + memcpy(nonce, lssl->sec.readIV, 4); + memcpy(nonce + 4, ct, TLS_EXPLICIT_NONCE_LEN); + ct += TLS_EXPLICIT_NONCE_LEN; + len -= TLS_EXPLICIT_NONCE_LEN; + +#ifdef USE_DTLS + if (lssl->flags & SSL_FLAGS_DTLS) { + /* In the case of DTLS the counter is formed from the concatenation of + the 16-bit epoch with the 48-bit sequence number. */ + memcpy(aad, lssl->rec.epoch, 2); + memcpy(aad + 2, lssl->rec.rsn, 6); + seqNotDone = 0; + } +#endif + + if (seqNotDone) { + memcpy(aad, lssl->sec.remSeq, 8); + } + ctLen = len - TLS_GCM_TAG_LEN; + aad[8] = lssl->rec.type; + aad[9] = lssl->majVer; + aad[10] = lssl->minVer; + aad[11] = ctLen >> 8 & 0xFF; + aad[12] = ctLen & 0xFF; + + psAesReadyGCM(ctx, nonce, aad, TLS_GCM_AAD_LEN); + + if ((bytes = psAesDecryptGCM(ctx, ct, len, pt, len - TLS_GCM_TAG_LEN)) < 0){ + return -1; + } + for (i = 7; i >= 0; i--) { + lssl->sec.remSeq[i]++; + if (lssl->sec.remSeq[i] != 0) { + break; + } + } + return bytes; +} +#endif /* USE_AES_GCM */ +#endif /* USE_TLS_1_2 */ + +#ifdef USE_AES_CBC +/******************************************************************************/ +int32 csAesInit(sslSec_t *sec, int32 type, uint32 keysize) +{ + int32 err; + + if (type == INIT_ENCRYPT_CIPHER) { + memset(&(sec->encryptCtx), 0, sizeof(psAesCbc_t)); + if ((err = psAesInitCBC(&sec->encryptCtx.aes, sec->writeIV, sec->writeKey, + keysize, PS_AES_ENCRYPT)) < 0) { + return err; + } + } else { /* Init for decrypt */ + memset(&(sec->decryptCtx), 0, sizeof(psAesCbc_t)); + if ((err = psAesInitCBC(&sec->decryptCtx.aes, sec->readIV, sec->readKey, + keysize, PS_AES_DECRYPT)) < 0) { + return err; + } + } + return PS_SUCCESS; +} + +int32 csAesEncrypt(void *ssl, unsigned char *pt, + unsigned char *ct, uint32 len) +{ + ssl_t *lssl = ssl; + psAesCbc_t *ctx = &lssl->sec.encryptCtx.aes; + + psAesEncryptCBC(ctx, pt, ct, len); + return len; +} + +int32 csAesDecrypt(void *ssl, unsigned char *ct, + unsigned char *pt, uint32 len) +{ + ssl_t *lssl = ssl; + psAesCbc_t *ctx = &lssl->sec.decryptCtx.aes; + psAesDecryptCBC(ctx, ct, pt, len); + return len; +} +#endif /*USE_AES_CBC */ +#endif /* USE_AES_CIPHER_SUITE */ + +/******************************************************************************/ + +//#define DEBUG_CHACHA20_POLY1305_CIPHER_SUITE +#ifdef USE_CHACHA20_POLY1305_CIPHER_SUITE +int32 csChacha20Poly1305Init(sslSec_t *sec, int32 type, uint32 keysize) +{ + int32 err; + + if (type == INIT_ENCRYPT_CIPHER) { +#ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE + psTraceInfo("Entering csChacha20Poly1305Init encrypt\n"); + psTraceBytes("sec->writeKey", sec->writeKey, keysize); +#endif + memset(&sec->encryptCtx.chacha20poly1305, 0, sizeof(psChacha20Poly1305_t)); + if ((err = psChacha20Poly1305Init(&sec->encryptCtx.chacha20poly1305, sec->writeKey, + keysize)) < 0) { + return err; + } + } else { +#ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE + psTraceInfo("Entering csChacha20Poly1305Init decrypt\n"); + psTraceBytes("sec->readKey", sec->readKey, keysize); +#endif + memset(&sec->decryptCtx.chacha20poly1305, 0, sizeof(psChacha20Poly1305_t)); + if ((err = psChacha20Poly1305Init(&sec->decryptCtx.chacha20poly1305, sec->readKey, + keysize)) < 0) { + return err; + } + } + return 0; +} + +int32 csChacha20Poly1305Encrypt(void *ssl, unsigned char *pt, + unsigned char *ct, uint32 len) +{ + ssl_t *lssl = ssl; + psChacha20Poly1305_t *ctx; + unsigned char nonce[TLS_AEAD_NONCE_MAXLEN]; + unsigned char aad[TLS_CHACHA20_POLY1305_AAD_LEN]; + int32 i, ptLen; + + if (len == 0) { + return PS_SUCCESS; + } + if (len < 16 + 1) { + return PS_LIMIT_FAIL; + } + ptLen = len - TLS_CHACHA20_POLY1305_TAG_LEN; + ctx = &lssl->sec.encryptCtx.chacha20poly1305; + + memset(nonce, 0, TLS_AEAD_NONCE_MAXLEN); + memset(aad, 0, TLS_CHACHA20_POLY1305_AAD_LEN); + +#ifdef CHACHA20POLY1305_IETF +#ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE + psTraceInfo("Entering csChacha20Poly1305Encrypt IETF\n"); +#endif + if (sizeof(lssl->sec.writeIV) < CHACHA20POLY1305_IV_FIXED_LENGTH) return PS_LIMIT_FAIL; + if (sizeof(nonce) < CHACHA20POLY1305_IV_FIXED_LENGTH) return PS_LIMIT_FAIL; + + // The nonce is built according to: https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305 + + memcpy(nonce + (CHACHA20POLY1305_IV_FIXED_LENGTH-TLS_AEAD_SEQNB_LEN), lssl->sec.seq, TLS_AEAD_SEQNB_LEN); + + for (i = 0; i < CHACHA20POLY1305_IV_FIXED_LENGTH; i++) { + nonce[i] ^= lssl->sec.writeIV[i]; + } +#else +#ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE + psTraceInfo("Entering csChacha20Poly1305Encrypt\n"); +#endif + +/* + The nonce is just the sequence number, as explained in + https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-5 AEAD construction +*/ + memcpy(nonce, lssl->sec.seq, TLS_AEAD_SEQNB_LEN); +#endif + //--- Fill Additional data ---// + memcpy(aad, lssl->sec.seq, TLS_AEAD_SEQNB_LEN); + i = TLS_AEAD_SEQNB_LEN; + + aad[i++] = lssl->outRecType; + aad[i++] = lssl->majVer; + aad[i++] = lssl->minVer; + aad[i++] = ptLen >> 8 & 0xFF; + aad[i++] = ptLen & 0xFF; + +#ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE + psTraceBytes("nonce", nonce, CHACHA20POLY1305_IV_FIXED_LENGTH); + psTraceBytes("aad", aad, TLS_CHACHA20_POLY1305_AAD_LEN); + psTraceBytes("pt", pt, ptLen); +#endif + + /* Perform encryption and authentication tag computation */ + psChacha20Poly1305Ready(ctx, nonce, aad, TLS_CHACHA20_POLY1305_AAD_LEN); + psChacha20Poly1305Encrypt(ctx, pt, ct, ptLen); + psChacha20Poly1305GetTag(ctx,TLS_CHACHA20_POLY1305_TAG_LEN, ct + ptLen); + +#ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE + psTraceBytes("ct", ct, ptLen); + psTraceBytes("tag", ct+ptLen, TLS_CHACHA20_POLY1305_TAG_LEN); +#endif + + /* Normally HMAC would increment the sequence */ + for (i = (TLS_AEAD_SEQNB_LEN - 1); i >= 0; i--) { + lssl->sec.seq[i]++; + if (lssl->sec.seq[i] != 0) { + break; + } + } + return len; +} + +int32 csChacha20Poly1305Decrypt(void *ssl, unsigned char *ct, + unsigned char *pt, uint32 len) +{ + ssl_t *lssl = ssl; + psChacha20Poly1305_t *ctx; + int32 i, ctLen, bytes; + + unsigned char nonce[TLS_AEAD_NONCE_MAXLEN]; + unsigned char aad[TLS_CHACHA20_POLY1305_AAD_LEN]; + + ctx = &lssl->sec.decryptCtx.chacha20poly1305; + + memset(nonce, 0, TLS_AEAD_NONCE_MAXLEN); + memset(aad, 0, TLS_CHACHA20_POLY1305_AAD_LEN); + +#ifdef CHACHA20POLY1305_IETF + // Check https://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-06 + +#ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE + psTraceInfo("Entering csChacha20Poly1305Decrypt IETF\n"); +#endif + + if (sizeof(lssl->sec.readIV) < CHACHA20POLY1305_IV_FIXED_LENGTH) return PS_LIMIT_FAIL; + if (sizeof(nonce) < CHACHA20POLY1305_IV_FIXED_LENGTH) return PS_LIMIT_FAIL; + + // The nonce is built according to: https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305 + + memcpy(nonce + (CHACHA20POLY1305_IV_FIXED_LENGTH-TLS_AEAD_SEQNB_LEN), lssl->sec.remSeq, TLS_AEAD_SEQNB_LEN); + + for (i = 0; i < CHACHA20POLY1305_IV_FIXED_LENGTH; i++) { + nonce[i] ^= lssl->sec.readIV[i]; + } + +#else +#ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE + psTraceInfo("Entering csChacha20Poly1305Decrypt\n"); +#endif + memcpy(nonce, lssl->sec.remSeq, TLS_AEAD_SEQNB_LEN); +#endif + + //--- Fill Additional data ---// + memcpy(aad, lssl->sec.remSeq, TLS_AEAD_SEQNB_LEN); + i = TLS_AEAD_SEQNB_LEN; + + // Update length of encrypted data: we have to remove tag's length + if (len < TLS_CHACHA20_POLY1305_TAG_LEN) { + return PS_LIMIT_FAIL; + } + ctLen = len - TLS_CHACHA20_POLY1305_TAG_LEN; + + aad[i++] = lssl->rec.type; + aad[i++] = lssl->majVer; + aad[i++] = lssl->minVer; + aad[i++] = ctLen >> 8 & 0xFF; + aad[i++] = ctLen & 0xFF; + +#ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE + psTraceBytes("nonce", nonce, CHACHA20POLY1305_IV_FIXED_LENGTH); + psTraceBytes("aad", aad, TLS_CHACHA20_POLY1305_AAD_LEN); + psTraceBytes("ct", ct, ctLen); + psTraceBytes("tag", ct+ctLen, TLS_CHACHA20_POLY1305_TAG_LEN); +#endif + + //--- Check authentication tag and decrypt data ---// + psChacha20Poly1305Ready(ctx, nonce, aad, TLS_CHACHA20_POLY1305_AAD_LEN); + + if ((bytes = psChacha20Poly1305Decrypt(ctx, ct, len, pt, ctLen)) < 0){ +#ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE + psTraceInfo("Decrypt NOK\n"); +#endif + return -1; + } + + for (i = (TLS_AEAD_SEQNB_LEN - 1); i >= 0; i--) { + lssl->sec.remSeq[i]++; + if (lssl->sec.remSeq[i] != 0) { + break; + } + } + + return bytes; +} +#endif /* USE_CHACHA20_POLY1305_CIPHER_SUITE */ + +/******************************************************************************/ + +#if defined(USE_IDEA) && defined(USE_IDEA_CIPHER_SUITE) +int32 csIdeaInit(sslSec_t *sec, int32 type, uint32 keysize) +{ + int32 err; + + if (type == INIT_ENCRYPT_CIPHER) { + memset(&(sec->encryptCtx), 0, sizeof(psCipherContext_t)); + if ((err = psIdeaInit(&(sec->encryptCtx.idea), sec->writeIV, sec->writeKey)) < 0) { + return err; + } + } else { /* Init for decrypt */ + memset(&(sec->decryptCtx), 0, sizeof(psCipherContext_t)); + if ((err = psIdeaInit(&(sec->decryptCtx.idea), sec->readIV, sec->readKey)) < 0) { + return err; + } + } + return PS_SUCCESS; +} + +int32 csIdeaEncrypt(void *ssl, unsigned char *pt, + unsigned char *ct, uint32 len) +{ + ssl_t *lssl = ssl; + psIdea_t *ctx = &lssl->sec.encryptCtx.idea; + + psIdeaEncrypt(ctx, pt, ct, len); + return len; +} + +int32 csIdeaDecrypt(void *ssl, unsigned char *ct, + unsigned char *pt, uint32 len) +{ + ssl_t *lssl = ssl; + psIdea_t *ctx = &lssl->sec.encryptCtx.idea; + + psIdeaDecrypt(ctx, ct, pt, len); + return len; +} +#endif /* USE_IDEA_CIPHER_SUITE */ + +/******************************************************************************/ +#if defined(USE_SEED) && defined(USE_SEED_CIPHER_SUITE) +/******************************************************************************/ +static int32 csSeedInit(sslSec_t *sec, int32 type, uint32 keysize) +{ + int32 err; + + psAssert(keysize == SEED_KEYLEN); + + if (type == INIT_ENCRYPT_CIPHER) { + memset(&(sec->encryptCtx), 0, sizeof(psSeed_t)); + if ((err = psSeedInit(&(sec->encryptCtx.seed), sec->writeIV, sec->writeKey)) < 0) { + return err; + } + } else { + memset(&(sec->decryptCtx), 0, sizeof(psSeed_t)); + if ((err = psSeedInit(&(sec->decryptCtx.seed), sec->readIV, sec->readKey)) < 0) { + return err; + } + } + return 0; +} +int32 csSeedEncrypt(void *ssl, unsigned char *pt, + unsigned char *ct, uint32 len) +{ + ssl_t *lssl = ssl; + psSeed_t *ctx = &lssl->sec.encryptCtx.seed; + + psSeedEncrypt(ctx, pt, ct, len); + return len; +} + +int32 csSeedDecrypt(void *ssl, unsigned char *ct, + unsigned char *pt, uint32 len) +{ + ssl_t *lssl = ssl; + psSeed_t *ctx = &lssl->sec.encryptCtx.seed; + + psSeedDecrypt(ctx, ct, pt, len); + return len; +} + +#endif /* USE_SEED_CIPHER_SUITE */ +/******************************************************************************/ + + +/******************************************************************************/ +/* Null cipher crypto */ +/******************************************************************************/ +static int32 csNullEncrypt(void *ctx, unsigned char *in, + unsigned char *out, uint32 len) +{ + if (out != in) { + memcpy(out, in, len); + } + return len; +} + +static int32 csNullDecrypt(void *ctx, unsigned char *in, + unsigned char *out, uint32 len) +{ + if (out != in) { + memmove(out, in, len); + } + return len; +} + +/******************************************************************************/ +/* HMAC wrappers for cipher suites */ +/******************************************************************************/ +static int32 csNullGenerateMac(void *ssl, unsigned char type, + unsigned char *data, uint32 len, unsigned char *mac) +{ + return 0; +} + +static int32 csNullVerifyMac(void *ssl, unsigned char type, + unsigned char *data, uint32 len, unsigned char *mac) +{ + return 0; +} + +#ifdef USE_SHA_MAC +/******************************************************************************/ +static int32 csShaGenerateMac(void *sslv, unsigned char type, + unsigned char *data, uint32 len, unsigned char *macOut) +{ + ssl_t *ssl = (ssl_t*)sslv; + unsigned char mac[MAX_HASH_SIZE]; + +#ifdef USE_TLS + if (ssl->flags & SSL_FLAGS_TLS) { +#ifdef USE_SHA256 + if (ssl->nativeEnMacSize == SHA256_HASH_SIZE || + ssl->nativeEnMacSize == SHA384_HASH_SIZE) { + tlsHMACSha2(ssl, HMAC_CREATE, type, data, len, mac, + ssl->nativeEnMacSize); + } else { +#endif +#ifdef USE_SHA1 + tlsHMACSha1(ssl, HMAC_CREATE, type, data, len, mac); +#endif +#ifdef USE_SHA256 + } +#endif + } else { +#endif /* USE_TLS */ +#ifndef DISABLE_SSLV3 + ssl3HMACSha1(ssl->sec.writeMAC, ssl->sec.seq, type, data, + len, mac); +#else + return PS_ARG_FAIL; +#endif /* DISABLE_SSLV3 */ +#ifdef USE_TLS + } +#endif /* USE_TLS */ + + memcpy(macOut, mac, ssl->enMacSize); + return ssl->enMacSize; +} + +static int32 csShaVerifyMac(void *sslv, unsigned char type, + unsigned char *data, uint32 len, unsigned char *mac) +{ + unsigned char buf[MAX_HASH_SIZE]; + ssl_t *ssl = (ssl_t*)sslv; + +#ifdef USE_TLS + if (ssl->flags & SSL_FLAGS_TLS) { +#ifdef USE_SHA256 + if (ssl->nativeDeMacSize == SHA256_HASH_SIZE || + ssl->nativeDeMacSize == SHA384_HASH_SIZE) { + tlsHMACSha2(ssl, HMAC_VERIFY, type, data, len, buf, + ssl->nativeDeMacSize); + } else { +#endif +#ifdef USE_SHA1 + tlsHMACSha1(ssl, HMAC_VERIFY, type, data, len, buf); +#endif +#ifdef USE_SHA256 + } +#endif + } else { +#endif /* USE_TLS */ +#ifndef DISABLE_SSLV3 + ssl3HMACSha1(ssl->sec.readMAC, ssl->sec.remSeq, type, data, len, buf); +#endif /* DISABLE_SSLV3 */ +#ifdef USE_TLS + } +#endif /* USE_TLS */ + if (memcmpct(buf, mac, ssl->deMacSize) == 0) { + return PS_SUCCESS; + } + return PS_FAILURE; +} +#endif /* USE_SHA_MAC */ +/******************************************************************************/ + +/******************************************************************************/ +#if defined(USE_MD5) && defined(USE_MD5_MAC) +/******************************************************************************/ +static int32 csMd5GenerateMac(void *sslv, unsigned char type, + unsigned char *data, uint32 len, unsigned char *macOut) +{ + unsigned char mac[MD5_HASH_SIZE]; + ssl_t *ssl = (ssl_t*)sslv; +#ifdef USE_TLS + if (ssl->flags & SSL_FLAGS_TLS) { + tlsHMACMd5(ssl, HMAC_CREATE, type, data, len, mac); + } else { +#endif /* USE_TLS */ +#ifndef DISABLE_SSLV3 + ssl3HMACMd5(ssl->sec.writeMAC, ssl->sec.seq, type, data, + len, mac); +#else + return PS_ARG_FAIL; +#endif /* DISABLE_SSLV3 */ +#ifdef USE_TLS + } +#endif /* USE_TLS */ + memcpy(macOut, mac, ssl->enMacSize); + return ssl->enMacSize; +} + +static int32 csMd5VerifyMac(void *sslv, unsigned char type, unsigned char *data, + uint32 len, unsigned char *mac) +{ + unsigned char buf[MD5_HASH_SIZE]; + ssl_t *ssl = (ssl_t*)sslv; + +#ifdef USE_TLS + if (ssl->flags & SSL_FLAGS_TLS) { + tlsHMACMd5(ssl, HMAC_VERIFY, type, data, len, buf); + } else { +#endif /* USE_TLS */ +#ifndef DISABLE_SSLV3 + ssl3HMACMd5(ssl->sec.readMAC, ssl->sec.remSeq, type, data, len, buf); +#endif /* DISABLE_SSLV3 */ +#ifdef USE_TLS + } +#endif /* USE_TLS */ + if (memcmpct(buf, mac, ssl->deMacSize) == 0) { + return PS_SUCCESS; + } + return PS_FAILURE; +} +#endif /* USE_MD5_MAC */ + +/******************************************************************************/ + +/* Set of bits corresponding to supported cipher ordinal. If set, it is + globally disabled */ +static uint32_t disabledCipherFlags[8] = { 0 }; /* Supports up to 256 ciphers */ + +const static sslCipherSpec_t supportedCiphers[] = { +/* + New ciphers should be added here, similar to the ones below + + Ciphers are listed in order of greater security at top... this generally + means the slower ones are on top as well. + + 256 ciphers max. + + The ordering of the ciphers is grouped and sub-grouped by the following: + 1. Non-deprecated + 2. Ephemeral + 3. Authentication Method (PKI > PSK > anon) + 4. Hash Strength (SHA384 > SHA256 > SHA > MD5) + 5. Cipher Strength (AES256 > AES128 > 3DES > ARC4 > SEED > IDEA > NULL) + 6. PKI Key Exchange (DHE > ECDHE > ECDH > RSA > PSK) + 7. Cipher Mode (GCM > CBC) + 8. PKI Authentication Method (ECDSA > RSA > PSK) +*/ + +/* Ephemeral ciphersuites */ +#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + CS_ECDHE_ECDSA, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_SHA3, + 0, /* macSize */ + 32, /* keySize */ + 4, /* ivSize */ + 0, /* blocksize */ + csAesGcmInit, + csAesGcmEncrypt, + csAesGcmDecrypt, + NULL, + NULL}, +#endif /* USE_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 */ + +#ifdef USE_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + CS_ECDHE_RSA, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_SHA3, + 0, /* macSize */ + 32, /* keySize */ + 4, /* ivSize */ + 0, /* blocksize */ + csAesGcmInit, + csAesGcmEncrypt, + csAesGcmDecrypt, + NULL, + NULL}, +#endif /* USE_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 */ + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + {TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + CS_ECDHE_ECDSA, + CRYPTO_FLAGS_CHACHA | CRYPTO_FLAGS_SHA2, + 0, /* macSize */ + 32, /* keySize */ + CHACHA20POLY1305_IV_FIXED_LENGTH, /* ivSize */ + 0, /* blocksize */ + csChacha20Poly1305Init, + csChacha20Poly1305Encrypt, + csChacha20Poly1305Decrypt, + NULL, + NULL}, +#endif /* USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 */ + +#ifdef USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + CS_ECDHE_RSA, + CRYPTO_FLAGS_CHACHA | CRYPTO_FLAGS_SHA2, + 0, /* macSize */ + 32, /* keySize */ + CHACHA20POLY1305_IV_FIXED_LENGTH, /* ivSize */ + 0, /* blocksize */ + csChacha20Poly1305Init, + csChacha20Poly1305Encrypt, + csChacha20Poly1305Decrypt, + NULL, + NULL }, +#endif /* USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */ + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + CS_ECDHE_ECDSA, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_SHA3, + 48, /* macSize */ + 32, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 */ + +#ifdef USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + CS_ECDHE_RSA, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_SHA3, + 48, /* macSize */ + 32, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 */ + +#ifdef USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + {TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + CS_DHE_RSA, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_SHA2, + 32, /* macSize */ + 32, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 */ + +#ifdef USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + {TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + CS_DHE_RSA, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_SHA2, + 32, /* macSize */ + 16, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 */ + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + CS_ECDHE_ECDSA, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_SHA2, + 0, /* macSize */ + 16, /* keySize */ + 4, /* ivSize */ + 0, /* blocksize */ + csAesGcmInit, + csAesGcmEncrypt, + csAesGcmDecrypt, + NULL, + NULL}, +#endif /* USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 */ + +#ifdef USE_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + CS_ECDHE_RSA, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_SHA2, + 0, /* macSize */ + 16, /* keySize */ + 4, /* ivSize */ + 0, /* blocksize */ + csAesGcmInit, + csAesGcmEncrypt, + csAesGcmDecrypt, + NULL, + NULL}, +#endif /* USE_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 */ + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + CS_ECDHE_ECDSA, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_SHA2, + 32, /* macSize */ + 16, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 */ + +#ifdef USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + CS_ECDHE_RSA, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_SHA2, + 32, /* macSize */ + 16, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 */ + +#ifdef USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + {TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + CS_DHE_RSA, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 32, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA */ + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + CS_ECDHE_ECDSA, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 32, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA */ + +#ifdef USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + CS_ECDHE_RSA, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 32, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA */ + +#ifdef USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + {TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + CS_DHE_RSA, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 16, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA */ + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + CS_ECDHE_ECDSA, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 16, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA */ + +#ifdef USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + CS_ECDHE_RSA, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 16, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA */ + +#ifdef USE_SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA + {SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + CS_DHE_RSA, + CRYPTO_FLAGS_3DES | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 24, /* keySize */ + 8, /* ivSize */ + 8, /* blocksize */ + csDes3Init, + csDes3Encrypt, + csDes3Decrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA */ + +#ifdef USE_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + CS_ECDHE_RSA, + CRYPTO_FLAGS_3DES | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 24, /* keySize */ + 8, /* ivSize */ + 8, /* blocksize */ + csDes3Init, + csDes3Encrypt, + csDes3Decrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA */ + +#ifdef USE_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + {TLS_DHE_PSK_WITH_AES_256_CBC_SHA, + CS_DHE_PSK, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 32, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_DHE_PSK_WITH_AES_256_CBC_SHA */ + +#ifdef USE_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + {TLS_DHE_PSK_WITH_AES_128_CBC_SHA, + CS_DHE_PSK, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 16, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_DHE_PSK_WITH_AES_128_CBC_SHA */ + +/* Non-ephemeral ciphersuites */ + +#ifdef USE_TLS_RSA_WITH_AES_256_GCM_SHA384 + {TLS_RSA_WITH_AES_256_GCM_SHA384, + CS_RSA, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_SHA3, + 0, /* macSize */ + 32, /* keySize */ + 4, /* ivSize */ + 0, /* blocksize */ + csAesGcmInit, + csAesGcmEncrypt, + csAesGcmDecrypt, + NULL, + NULL}, +#endif + +#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + {TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, + CS_ECDH_ECDSA, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_SHA3, + 0, /* macSize */ + 32, /* keySize */ + 4, /* ivSize */ + 0, /* blocksize */ + csAesGcmInit, + csAesGcmEncrypt, + csAesGcmDecrypt, + NULL, + NULL}, +#endif /* USE_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 */ + +#ifdef USE_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + {TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, + CS_ECDH_RSA, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_SHA3, + 0, /* macSize */ + 32, /* keySize */ + 4, /* ivSize */ + 0, /* blocksize */ + csAesGcmInit, + csAesGcmEncrypt, + csAesGcmDecrypt, + NULL, + NULL}, +#endif /* USE_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 */ + +#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + {TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, + CS_ECDH_ECDSA, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_SHA3, + 48, /* macSize */ + 32, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 */ + +#ifdef USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + {TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, + CS_ECDH_RSA, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_SHA3, + 48, /* macSize */ + 32, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 */ + +#ifdef USE_TLS_RSA_WITH_AES_256_CBC_SHA256 + {TLS_RSA_WITH_AES_256_CBC_SHA256, + CS_RSA, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_SHA2, + 32, /* macSize */ + 32, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif + +#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + {TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, + CS_ECDH_ECDSA, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_SHA2, + 0, /* macSize */ + 16, /* keySize */ + 4, /* ivSize */ + 0, /* blocksize */ + csAesGcmInit, + csAesGcmEncrypt, + csAesGcmDecrypt, + NULL, + NULL}, +#endif /* USE_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 */ + +#ifdef USE_TLS_RSA_WITH_AES_128_GCM_SHA256 + {TLS_RSA_WITH_AES_128_GCM_SHA256, + CS_RSA, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_SHA2, + 0, /* macSize */ + 16, /* keySize */ + 4, /* ivSize */ + 0, /* blocksize */ + csAesGcmInit, + csAesGcmEncrypt, + csAesGcmDecrypt, + NULL, + NULL}, +#endif + +#ifdef USE_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + {TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, + CS_ECDH_RSA, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_SHA2, + 0, /* macSize */ + 16, /* keySize */ + 4, /* ivSize */ + 0, /* blocksize */ + csAesGcmInit, + csAesGcmEncrypt, + csAesGcmDecrypt, + NULL, + NULL}, +#endif /* USE_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 */ + +#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + {TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + CS_ECDH_ECDSA, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_SHA2, + 32, /* macSize */ + 16, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 */ + +#ifdef USE_TLS_RSA_WITH_AES_128_CBC_SHA256 + {TLS_RSA_WITH_AES_128_CBC_SHA256, + CS_RSA, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_SHA2, + 32, /* macSize */ + 16, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif + +#ifdef USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + {TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, + CS_ECDH_RSA, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_SHA2, + 32, /* macSize */ + 16, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 */ + +#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + {TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + CS_ECDH_ECDSA, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 32, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA */ + +#ifdef USE_TLS_RSA_WITH_AES_256_CBC_SHA + {TLS_RSA_WITH_AES_256_CBC_SHA, + CS_RSA, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 32, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_RSA_WITH_AES_256_CBC_SHA */ + +#ifdef USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + {TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + CS_ECDH_RSA, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 32, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA */ + +#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + {TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + CS_ECDH_ECDSA, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 16, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA */ + +#ifdef USE_TLS_RSA_WITH_AES_128_CBC_SHA + {TLS_RSA_WITH_AES_128_CBC_SHA, + CS_RSA, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 16, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_RSA_WITH_AES_128_CBC_SHA */ + +#ifdef USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + {TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + CS_ECDH_RSA, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 16, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA */ + +#ifdef USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA + {SSL_RSA_WITH_3DES_EDE_CBC_SHA, + CS_RSA, + CRYPTO_FLAGS_3DES | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 24, /* keySize */ + 8, /* ivSize */ + 8, /* blocksize */ + csDes3Init, + csDes3Encrypt, + csDes3Decrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA */ + +#ifdef USE_TLS_PSK_WITH_AES_256_CBC_SHA384 + {TLS_PSK_WITH_AES_256_CBC_SHA384, + CS_PSK, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_SHA3, + 48, /* macSize */ + 32, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_PSK_WITH_AES_256_CBC_SHA384 */ + +#ifdef USE_TLS_PSK_WITH_AES_128_CBC_SHA256 + {TLS_PSK_WITH_AES_128_CBC_SHA256, + CS_PSK, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_SHA2, + 32, /* macSize */ + 16, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_PSK_WITH_AES_128_CBC_SHA256 */ + +#ifdef USE_TLS_PSK_WITH_AES_256_CBC_SHA + {TLS_PSK_WITH_AES_256_CBC_SHA, + CS_PSK, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 32, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_PSK_WITH_AES_256_CBC_SHA */ + +#ifdef USE_TLS_PSK_WITH_AES_128_CBC_SHA + {TLS_PSK_WITH_AES_128_CBC_SHA, + CS_PSK, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 16, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_PSK_WITH_AES_128_CBC_SHA */ + +/* @security Deprecated weak ciphers */ + +#ifdef USE_SSL_RSA_WITH_RC4_128_SHA + {SSL_RSA_WITH_RC4_128_SHA, + CS_RSA, + CRYPTO_FLAGS_ARC4 | CRYPTO_FLAGS_ARC4INITE | CRYPTO_FLAGS_ARC4INITD | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 16, /* keySize */ + 0, /* ivSize */ + 1, /* blocksize */ + csArc4Init, + csArc4Encrypt, + csArc4Decrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_SSL_RSA_WITH_RC4_128_SHA */ + +#ifdef USE_TLS_RSA_WITH_SEED_CBC_SHA + {TLS_RSA_WITH_SEED_CBC_SHA, + CS_RSA, + CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 16, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csSeedInit, + csSeedEncrypt, + csSeedDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_SSL_RSA_WITH_SEED_CBC_SHA */ + +#ifdef USE_TLS_RSA_WITH_IDEA_CBC_SHA + {TLS_RSA_WITH_IDEA_CBC_SHA, + CS_RSA, + CRYPTO_FLAGS_IDEA | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 16, /* keySize */ + 8, /* ivSize */ + 8, /* blocksize */ + csIdeaInit, + csIdeaEncrypt, + csIdeaDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_SSL_RSA_WITH_IDEA_CBC_SHA */ + +#ifdef USE_SSL_RSA_WITH_RC4_128_MD5 + {SSL_RSA_WITH_RC4_128_MD5, + CS_RSA, + CRYPTO_FLAGS_ARC4 | CRYPTO_FLAGS_ARC4INITE | CRYPTO_FLAGS_ARC4INITD | CRYPTO_FLAGS_MD5, + 16, /* macSize */ + 16, /* keySize */ + 0, /* ivSize */ + 1, /* blocksize */ + csArc4Init, + csArc4Encrypt, + csArc4Decrypt, + csMd5GenerateMac, + csMd5VerifyMac}, +#endif /* USE_SSL_RSA_WITH_RC4_128_MD5 */ + +/* @security Deprecated unencrypted ciphers */ + +#ifdef USE_SSL_RSA_WITH_NULL_SHA + {SSL_RSA_WITH_NULL_SHA, + CS_RSA, + CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 0, /* keySize */ + 0, /* ivSize */ + 0, /* blocksize */ + csNullInit, + csNullEncrypt, + csNullDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_SSL_RSA_WITH_NULL_SHA */ + +#ifdef USE_SSL_RSA_WITH_NULL_MD5 + {SSL_RSA_WITH_NULL_MD5, + CS_RSA, + CRYPTO_FLAGS_MD5, + 16, /* macSize */ + 0, /* keySize */ + 0, /* ivSize */ + 0, /* blocksize */ + csNullInit, + csNullEncrypt, + csNullDecrypt, + csMd5GenerateMac, + csMd5VerifyMac}, +#endif /* USE_SSL_RSA_WITH_NULL_MD5 */ + +/* @security Deprecated unauthenticated ciphers */ + +#ifdef USE_TLS_DH_anon_WITH_AES_256_CBC_SHA + {TLS_DH_anon_WITH_AES_256_CBC_SHA, + CS_DH_ANON, + CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 32, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_DH_anon_WITH_AES_256_CBC_SHA */ + +#ifdef USE_TLS_DH_anon_WITH_AES_128_CBC_SHA + {TLS_DH_anon_WITH_AES_128_CBC_SHA, + CS_DH_ANON, + CRYPTO_FLAGS_AES | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 16, /* keySize */ + 16, /* ivSize */ + 16, /* blocksize */ + csAesInit, + csAesEncrypt, + csAesDecrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_TLS_DH_anon_WITH_AES_128_CBC_SHA */ + +#ifdef USE_SSL_DH_anon_WITH_3DES_EDE_CBC_SHA + {SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, + CS_DH_ANON, + CRYPTO_FLAGS_3DES | CRYPTO_FLAGS_SHA1, + 20, /* macSize */ + 24, /* keySize */ + 8, /* ivSize */ + 8, /* blocksize */ + csDes3Init, + csDes3Encrypt, + csDes3Decrypt, + csShaGenerateMac, + csShaVerifyMac}, +#endif /* USE_SSL_DH_anon_WITH_3DES_EDE_CBC_SHA */ + +#ifdef USE_SSL_DH_anon_WITH_RC4_128_MD5 + {SSL_DH_anon_WITH_RC4_128_MD5, + CS_DH_ANON, + CRYPTO_FLAGS_ARC4INITE | CRYPTO_FLAGS_ARC4INITD | CRYPTO_FLAGS_MD5, + 16, /* macSize */ + 16, /* keySize */ + 0, /* ivSize */ + 1, /* blocksize */ + csArc4Init, + csArc4Encrypt, + csArc4Decrypt, + csMd5GenerateMac, + csMd5VerifyMac}, +#endif /* USE_SSL_DH_anon_WITH_RC4_128_MD5 */ + +/* + The NULL Cipher suite must exist and be the last in this list +*/ + {SSL_NULL_WITH_NULL_NULL, + CS_NULL, + 0, + 0, + 0, + 0, + 0, + csNullInit, + csNullEncrypt, + csNullDecrypt, + csNullGenerateMac, + csNullVerifyMac} +}; + +#ifdef USE_SERVER_SIDE_SSL +/******************************************************************************/ +/* + Disable and re-enable ciphers suites on a global or per-session level. + This is only a server-side feature because the client is always able to + nominate the specific cipher it wishes to use. Servers may want to disable + specific ciphers for a given session (or globally without having to + rebuild the library). + + This function must be called immediately after matrixSslNewServerSession + + If ssl is NULL, the setting will be global. If a cipher is globally + disabled, the per-session setting will be ignored. + + flags: + PS_TRUE to reenable (always enabled by default if compiled in) + PS_FALSE to disable cipher suite +*/ +int32_t matrixSslSetCipherSuiteEnabledStatus(ssl_t *ssl, uint16_t cipherId, + uint32_t flags) +{ + uint8_t i, j; + + if (ssl && !(ssl->flags & SSL_FLAGS_SERVER)) { + return PS_UNSUPPORTED_FAIL; + } + if (flags != PS_TRUE && flags != PS_FALSE) { + return PS_ARG_FAIL; + } + for (i = 0; supportedCiphers[i].ident != SSL_NULL_WITH_NULL_NULL; i++) { + if (supportedCiphers[i].ident == cipherId) { + if (ssl == NULL) { +/* + Global status of cipher suite. Disabled status takes + precident over session setting +*/ + if (flags == PS_TRUE) { + /* Unset the disabled bit */ + disabledCipherFlags[i >> 5] &= ~(1 < (i & 31)); + } else { + /* Set the disabled bit */ + disabledCipherFlags[i >> 5] |= 1 < (i & 31); + } + return PS_SUCCESS; + } else { + /* Status of this suite for a specific session */ + for (j = 0; j < SSL_MAX_DISABLED_CIPHERS; j++) { + if (flags == PS_FALSE) { + /* Find first empty spot to add disabled cipher */ + if (ssl->disabledCiphers[j] == 0x0 || + ssl->disabledCiphers[j] == cipherId) { + ssl->disabledCiphers[j] = cipherId; + return PS_SUCCESS; + } + } else { + if (ssl->disabledCiphers[j] == cipherId) { + ssl->disabledCiphers[j] = 0x0; + return PS_SUCCESS; + } + } + } + if (flags == PS_FALSE) { + return PS_LIMIT_FAIL; /* No empty spot in disabledCiphers */ + } else { + /* Tried to re-enabled a cipher that wasn't disabled */ + return PS_SUCCESS; + } + } + } + } + return PS_FAILURE; /* Cipher not found */ +} +/* + Convert the cipher suite "type" into what public key signature algorithm is + required. Return values are from the sigAlgorithm of psX509_t: + + RSA_TYPE_SIG (User must also test for RSAPSS_TYPE_SIG!!) + ECDSA_TYPE_SIG + + CS_NULL (0) if no public key signatures needed (PSK and DH_anon) + + The dhParamsRequired return paramater must hold whether standard DH + is used in the suite. The caller will have to load some during + the callback if so + + The ecKeyExchange is to identify RSA signatures but EC key exchange +*/ + +static uint16 getKeyTypeFromCipherType(uint16 type, uint16 *dhParamsRequired, + uint16 *ecKeyExchange) +{ + *dhParamsRequired = *ecKeyExchange = 0; + switch (type) { + case CS_RSA: + return RSA_TYPE_SIG; + + case CS_DHE_RSA: + *dhParamsRequired = 1; + return RSA_TYPE_SIG; + + case CS_DH_ANON: + case CS_DHE_PSK: + *dhParamsRequired = 1; + return CS_NULL; + + case CS_ECDHE_ECDSA: + case CS_ECDH_ECDSA: + return ECDSA_TYPE_SIG; + + case CS_ECDHE_RSA: + case CS_ECDH_RSA: + *ecKeyExchange = 1; + return RSA_TYPE_SIG; + + default: /* CS_NULL or CS_PSK type */ + return CS_NULL; /* a cipher suite with no pub key or DH */ + } +} +#endif /* USE_SERVER_SIDE_SSL */ + +#ifdef VALIDATE_KEY_MATERIAL +#define KEY_ALG_ANY 1 +#define KEY_ALG_FIRST 2 +/* + anyOrFirst is basically a determination of whether we are looking through + a collection of CA files for an algorithm (ANY) or a cert chain where + we really only care about the child most cert because that is the one + that ultimately determines the authentication algorithm (FIRST) +*/ +static int32 haveCorrectKeyAlg(psX509Cert_t *cert, int32 keyAlg, int anyOrFirst) +{ + while (cert) { + if (cert->pubKeyAlgorithm == keyAlg) { + return PS_SUCCESS; + } + if (anyOrFirst == KEY_ALG_FIRST) { + return PS_FAILURE; + } + cert = cert->next; + } + return PS_FAILURE; +} + +#ifdef USE_SERVER_SIDE_SSL +/* If using TLS 1.2 we need to test agains the sigHashAlg and eccParams */ +static int32_t validateKeyForExtensions(ssl_t *ssl, const sslCipherSpec_t *spec, + sslKeys_t *givenKey) +{ +#ifdef USE_TLS_1_2 + psX509Cert_t *crt; +#endif + + /* Can immediately weed out PSK suites and anon suites that don't use + sigHashAlg or EC curves */ + if (spec->type == CS_PSK || spec->type == CS_DHE_PSK || + spec->type == CS_DH_ANON) { + return PS_SUCCESS; + } + +#ifdef USE_TLS_1_2 + /* hash and sig alg is a TLS 1.2 only extension */ + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + + /* Walk through each cert and confirm the client will be able to + deal with them based on the algorithms provided in the extension */ + crt = givenKey->cert; + while (crt) { + +#ifdef USE_DHE_CIPHER_SUITE + /* Have to look out for the case where the public key alg doesn't + match the sig algorithm. This is only a concern for DHE based + suites where we'll be sending a signature in the + SeverKeyExchange message */ + if (spec->type == CS_DHE_RSA || spec->type == CS_ECDHE_RSA || + spec->type == CS_ECDHE_ECDSA) { + if (crt->pubKeyAlgorithm == OID_RSA_KEY_ALG) { + if ( +#ifdef USE_SHA1 + !(ssl->hashSigAlg & HASH_SIG_SHA1_RSA_MASK) && +#endif +#ifdef USE_SHA384 + !(ssl->hashSigAlg & HASH_SIG_SHA384_RSA_MASK) && +#endif +#ifdef USE_SHA512 + !(ssl->hashSigAlg & HASH_SIG_SHA512_RSA_MASK) && +#endif + !(ssl->hashSigAlg & HASH_SIG_SHA256_RSA_MASK)) { + return PS_UNSUPPORTED_FAIL; + } + } +#ifdef USE_ECC + if (crt->pubKeyAlgorithm == OID_ECDSA_KEY_ALG) { + if ( +#ifdef USE_SHA1 + !(ssl->hashSigAlg & HASH_SIG_SHA1_ECDSA_MASK) && +#endif +#ifdef USE_SHA384 + !(ssl->hashSigAlg & HASH_SIG_SHA384_ECDSA_MASK) && +#endif +#ifdef USE_SHA512 + !(ssl->hashSigAlg & HASH_SIG_SHA512_ECDSA_MASK) && +#endif + !(ssl->hashSigAlg & HASH_SIG_SHA256_ECDSA_MASK)) { + return PS_UNSUPPORTED_FAIL; + } + } +#endif /* USE_ECC */ + } +#endif /* USE_DHE_CIPHER_SUITE */ + + /* Now look for the specific pubkey/hash combo is supported */ + switch (crt->sigAlgorithm) { +#ifdef USE_RSA_CIPHER_SUITE + case OID_SHA256_RSA_SIG: + if (!(ssl->hashSigAlg & HASH_SIG_SHA256_RSA_MASK)) { + return PS_UNSUPPORTED_FAIL; + } + break; +#ifdef USE_SHA1 + case OID_SHA1_RSA_SIG: + if (!(ssl->hashSigAlg & HASH_SIG_SHA1_RSA_MASK)) { + return PS_UNSUPPORTED_FAIL; + } + break; +#endif +#ifdef USE_SHA384 + case OID_SHA384_RSA_SIG: + if (!(ssl->hashSigAlg & HASH_SIG_SHA384_RSA_MASK)) { + return PS_UNSUPPORTED_FAIL; + } + break; +#endif +#endif /* USE_RSA_CIPHER_SUITE */ +#ifdef USE_ECC_CIPHER_SUITE + case OID_SHA256_ECDSA_SIG: + if (!(ssl->hashSigAlg & HASH_SIG_SHA256_ECDSA_MASK)) { + return PS_UNSUPPORTED_FAIL; + } + break; +#ifdef USE_SHA1 + case OID_SHA1_ECDSA_SIG: + if (!(ssl->hashSigAlg & HASH_SIG_SHA1_ECDSA_MASK)) { + return PS_UNSUPPORTED_FAIL; + } + break; +#endif +#ifdef USE_SHA384 + case OID_SHA384_ECDSA_SIG: + if (!(ssl->hashSigAlg & HASH_SIG_SHA384_ECDSA_MASK)) { + return PS_UNSUPPORTED_FAIL; + } + break; +#endif +#endif /* USE_ECC */ + default: + psTraceInfo("Don't share ANY sig/hash algorithms with peer\n"); + return PS_UNSUPPORTED_FAIL; + } + +#ifdef USE_ECC + /* EC suites have the added check of specific curves. Just + checking DH suites because the curve comes from the cert. + ECDHE suites negotiate key exchange curve elsewhere */ + if (spec->type == CS_ECDH_ECDSA || spec->type == CS_ECDH_RSA) { + if (ssl->ecInfo.ecFlags) { + /* Do negotiated curves work with our signatures */ + if (psTestUserEcID(crt->publicKey.key.ecc.curve->curveId, + ssl->ecInfo.ecFlags) < 0) { + return PS_UNSUPPORTED_FAIL; + } + } else { + psTraceInfo("Don't share ANY EC curves with peer\n"); + return PS_UNSUPPORTED_FAIL; + } + } +#endif + crt = crt->next; + } + } + + +#endif /* USE_TLS_1_2 */ + + /* Must be good */ + return PS_SUCCESS; +} + +/* + This is the signature algorithm that the client will be using to encrypt + the key material based on what the cipher suite says it should be. + Only looking at child most cert +*/ +static int32 haveCorrectSigAlg(psX509Cert_t *cert, int32 sigType) +{ + if (sigType == RSA_TYPE_SIG) { + if (cert->sigAlgorithm == OID_SHA1_RSA_SIG || + cert->sigAlgorithm == OID_SHA256_RSA_SIG || + cert->sigAlgorithm == OID_SHA384_RSA_SIG || + cert->sigAlgorithm == OID_SHA512_RSA_SIG || + cert->sigAlgorithm == OID_MD5_RSA_SIG || + cert->sigAlgorithm == OID_MD2_RSA_SIG || + cert->sigAlgorithm == OID_RSASSA_PSS) { + return PS_SUCCESS; + } + } else if (sigType == ECDSA_TYPE_SIG) { + if (cert->sigAlgorithm == OID_SHA1_ECDSA_SIG || + cert->sigAlgorithm == OID_SHA224_ECDSA_SIG || + cert->sigAlgorithm == OID_SHA256_ECDSA_SIG || + cert->sigAlgorithm == OID_SHA384_ECDSA_SIG || + cert->sigAlgorithm == OID_SHA512_ECDSA_SIG) { + return PS_SUCCESS; + } + } + + return PS_FAILURE; +} +#endif /* USE_SERVER_SIDE_SSL */ + +/******************************************************************************/ +/* + Don't report a matching cipher suite if the user hasn't loaded the + proper public key material to support it. We do not check the client + auth side of the algorithms because that authentication mechanism is + negotiated within the handshake itself + + The annoying #ifdef USE_SERVER_SIDE and CLIENT_SIDE are because the + structure members only exist one one side or the other and so are used + for compiling. You can't actually get into the wrong area of the + SSL_FLAGS_SERVER test so no #else cases should be needed + */ +int32_t haveKeyMaterial(const ssl_t *ssl, int32 cipherType, short reallyTest) +{ + +#ifdef USE_SERVER_SIDE_SSL + /* If the user has a ServerNameIndication callback registered we're + going to skip the first test because they may not have loaded the + final key material yet */ + if (ssl->sni_cb && reallyTest == 0) { + return PS_SUCCESS; + } +#endif + +#ifndef USE_ONLY_PSK_CIPHER_SUITE + + /* To start, capture all the cipherTypes where servers must have an + identity and clients have a CA so we don't repeat them everywhere */ + if (cipherType == CS_RSA || cipherType == CS_DHE_RSA || + cipherType == CS_ECDHE_RSA || cipherType == CS_ECDH_RSA || + cipherType == CS_ECDHE_ECDSA || cipherType == CS_ECDH_ECDSA) { + if (ssl->flags & SSL_FLAGS_SERVER) { +#ifdef USE_SERVER_SIDE_SSL + if (ssl->keys == NULL || ssl->keys->cert == NULL) { + return PS_FAILURE; + } +#endif +#ifdef USE_CLIENT_SIDE_SSL + } else { + if (ssl->keys == NULL || ssl->keys->CAcerts == NULL) { + return PS_FAILURE; + } +#endif + } + } + + /* Standard RSA ciphers types - auth and exchange */ + if (cipherType == CS_RSA) { + if (ssl->flags & SSL_FLAGS_SERVER) { +#ifdef USE_SERVER_SIDE_SSL + if (haveCorrectKeyAlg(ssl->keys->cert, OID_RSA_KEY_ALG, + KEY_ALG_FIRST) < 0) { + return PS_FAILURE; + } + if (haveCorrectSigAlg(ssl->keys->cert, RSA_TYPE_SIG) < 0) { + return PS_FAILURE; + } +#endif +#ifdef USE_CLIENT_SIDE_SSL + } else { /* Client */ + + if (haveCorrectKeyAlg(ssl->keys->CAcerts, OID_RSA_KEY_ALG, + KEY_ALG_ANY) < 0) { + return PS_FAILURE; + } +#endif + } + } + +#ifdef USE_DHE_CIPHER_SUITE +/* + DHE_RSA ciphers types +*/ + if (cipherType == CS_DHE_RSA) { + if (ssl->flags & SSL_FLAGS_SERVER) { +#ifdef REQUIRE_DH_PARAMS + if (ssl->keys->dhParams.size == 0) { + return PS_FAILURE; + } +#endif +#ifdef USE_SERVER_SIDE_SSL + if (haveCorrectKeyAlg(ssl->keys->cert, OID_RSA_KEY_ALG, + KEY_ALG_FIRST) < 0) { + return PS_FAILURE; + } +#endif +#ifdef USE_CLIENT_SIDE_SSL + } else { + if (haveCorrectKeyAlg(ssl->keys->CAcerts, OID_RSA_KEY_ALG, + KEY_ALG_ANY) < 0) { + return PS_FAILURE; + } +#endif + } + } + +#ifdef REQUIRE_DH_PARAMS +/* + Anon DH ciphers don't need much +*/ + if (cipherType == CS_DH_ANON) { + if (ssl->flags & SSL_FLAGS_SERVER) { + if (ssl->keys == NULL || ssl->keys->dhParams.size == 0) { + return PS_FAILURE; + } + } + } +#endif + +#ifdef USE_PSK_CIPHER_SUITE + if (cipherType == CS_DHE_PSK) { +#ifdef REQUIRE_DH_PARAMS + if (ssl->flags & SSL_FLAGS_SERVER) { + if (ssl->keys == NULL || ssl->keys->dhParams.size == 0) { + return PS_FAILURE; + } + } +#endif + /* Only using these for clients at the moment */ + if (!(ssl->flags & SSL_FLAGS_SERVER)) { + if (ssl->keys == NULL || ssl->keys->pskKeys == NULL) { + return PS_FAILURE; + } + } + } +#endif /* USE_PSK_CIPHER_SUITE */ +#endif /* USE_DHE_CIPHER_SUITE */ + +#ifdef USE_ECC_CIPHER_SUITE /* key exchange */ +/* + ECDHE_RSA ciphers use RSA keys +*/ + if (cipherType == CS_ECDHE_RSA) { + if (ssl->flags & SSL_FLAGS_SERVER) { +#ifdef USE_SERVER_SIDE_SSL + if (haveCorrectKeyAlg(ssl->keys->cert, OID_RSA_KEY_ALG, + KEY_ALG_FIRST) < 0) { + return PS_FAILURE; + } + if (haveCorrectSigAlg(ssl->keys->cert, RSA_TYPE_SIG) < 0) { + return PS_FAILURE; + } +#endif +#ifdef USE_CLIENT_SIDE_SSL + } else { + if (haveCorrectKeyAlg(ssl->keys->CAcerts, OID_RSA_KEY_ALG, + KEY_ALG_ANY) < 0) { + return PS_FAILURE; + } +#endif + } + } + +/* + ECDH_RSA ciphers use ECDSA key exhange and RSA auth. +*/ + if (cipherType == CS_ECDH_RSA) { + if (ssl->flags & SSL_FLAGS_SERVER) { +#ifdef USE_SERVER_SIDE_SSL + if (haveCorrectKeyAlg(ssl->keys->cert, OID_ECDSA_KEY_ALG, + KEY_ALG_FIRST) < 0) { + return PS_FAILURE; + } + if (haveCorrectSigAlg(ssl->keys->cert, RSA_TYPE_SIG) < 0) { + return PS_FAILURE; + } +#endif +#ifdef USE_CLIENT_SIDE_SSL + } else { + if (haveCorrectKeyAlg(ssl->keys->CAcerts, OID_RSA_KEY_ALG, + KEY_ALG_ANY) < 0) { + return PS_FAILURE; + } +#endif + } + } + + +/* + ECDHE_ECDSA and ECDH_ECDSA ciphers must have ECDSA keys +*/ + if (cipherType == CS_ECDHE_ECDSA || cipherType == CS_ECDH_ECDSA) { + if (ssl->flags & SSL_FLAGS_SERVER) { +#ifdef USE_SERVER_SIDE_SSL + if (haveCorrectKeyAlg(ssl->keys->cert, OID_ECDSA_KEY_ALG, + KEY_ALG_FIRST) < 0) { + return PS_FAILURE; + } + if (haveCorrectSigAlg(ssl->keys->cert, ECDSA_TYPE_SIG) < 0) { + return PS_FAILURE; + } +#endif +#ifdef USE_CLIENT_SIDE_SSL + } else { + if (haveCorrectKeyAlg(ssl->keys->CAcerts, OID_ECDSA_KEY_ALG, + KEY_ALG_ANY) < 0) { + return PS_FAILURE; + } +#endif + } + } +#endif /* USE_ECC_CIPHER_SUITE */ +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ + +#ifdef USE_PSK_CIPHER_SUITE + if (cipherType == CS_PSK) { + if (ssl->keys == NULL || ssl->keys->pskKeys == NULL) { + return PS_FAILURE; + } + } +#endif /* USE_PSK_CIPHER_SUITE */ + + return PS_SUCCESS; +} +#endif /* VALIDATE_KEY_MATERIAL */ + + +/* 0 return is a key was found + <0 is no luck +*/ +#ifdef USE_SERVER_SIDE_SSL +int32 chooseCipherSuite(ssl_t *ssl, unsigned char *listStart, int32 listLen) +{ + const sslCipherSpec_t *spec; + unsigned char *c = listStart; + unsigned char *end; + uint16 ecKeyExchange; + uint32 cipher; + sslPubkeyId_t wantKey; + sslKeys_t *givenKey = NULL; + + end = c + listLen; + while (c < end) { + + if (ssl->rec.majVer > SSL2_MAJ_VER) { + cipher = *c << 8; c++; + cipher += *c; c++; + } else { + /* Deal with an SSLv2 hello message. Ciphers are 3 bytes long */ + cipher = *c << 16; c++; + cipher += *c << 8; c++; + cipher += *c; c++; + } + + /* Checks if this cipher suite compiled into the library. + ALSO, in the cases of static server keys (ssl->keys not NULL) + the haveKeyMaterial function will be run */ + if ((spec = sslGetCipherSpec(ssl, cipher)) == NULL) { + continue; + } + + if (ssl->keys == NULL) { + /* Populate the sslPubkeyId_t struct to pass to user callback */ + wantKey.keyType = getKeyTypeFromCipherType(spec->type, + &wantKey.dhParamsRequired, &ecKeyExchange); + /* If this is a ECDHE_RSA or ECDH_RSA suite, there are going to + need to be some indications for that */ + psTraceInfo("ecKeyExchange must be incorporated into the user callback.\n"); + + /* If this a pure PSK cipher with no DH then we assign that suite + immediately and never invoke the user callback. This server has + already indicated its willingness to use PSK if compiled in and + the client has sent the suites in priority order so we use it */ + if (wantKey.keyType == CS_NULL && wantKey.dhParamsRequired == 0) { + ssl->cipher = spec; + return PS_SUCCESS; + } + + /* ssl->expectedName is populated with the optional + SNI extension value. + + In this flexible server case, the SNI callback function is + NOT USED. + + TODO: To comply with spec the server SHALL include an SNI + extension if it was used to help select keys. Maybe just + always send it in this flexible case? */ + wantKey.serverName = ssl->expectedName; +#ifdef USE_TLS_1_2 + wantKey.hashAlg = ssl->hashSigAlg; +#else + /* TODO: WHAT DO WE DO FOR NON TLS 1.2? */ + wantKey.hashAlg = 0; +#endif +#ifdef USE_ECC_CIPHER_SUITE + /* At this point ssl->ecInfo.ecFlags carries the shared curves */ + wantKey.curveFlags = ssl->ecInfo.ecFlags; +#else + wantKey.curveFlags = 0; +#endif + +#ifndef USE_ONLY_PSK_CIPHER_SUITE + /* TODO: This was wrapped for compile-time purposes */ + /* Invoke the user's callback */ + givenKey = (ssl->sec.pubkeyCb)(ssl, &wantKey); +#endif + + if (givenKey == NULL) { + /* User didn't have a match. Keep looking through suites */ + continue; + } + +#ifdef VALIDATE_KEY_MATERIAL + /* We want to double check this. Temporarily assign their keys as + ssl->keys for haveKeyMaterial to find */ + ssl->keys = givenKey; + if (haveKeyMaterial(ssl, spec->type, 1) < 0) { + ssl->keys = NULL; + /* We're still looping through cipher suites above so this + isn't really fatal. It just means the user gave us keys + that don't match the suite we wanted */ + psTraceInfo("WARNING: server didn't load proper keys for "); + psTraceIntInfo("cipher suite %d during pubkey callback\n", + spec->ident); + continue; + } + /* Reset. One final test below before we can set ssl->keys */ + ssl->keys = NULL; +#endif + } else { + if (ssl->expectedName) { + /* The SNI callback is no longer invoked in the middle of the + parse. Now is the time to call it for pre-loaded keys */ + if (matrixServerSetKeysSNI(ssl, ssl->expectedName, + strlen(ssl->expectedName)) < 0) { + psTraceInfo("Server didn't load SNI keys\n"); + ssl->err = SSL_ALERT_UNRECOGNIZED_NAME; + return MATRIXSSL_ERROR; + } + } + /* This is here becuase it still could be useful to support the + old mechanism where the server just loads the single known + ID key at new session and never looks back */ + givenKey = ssl->keys; + } + +#ifdef VALIDATE_KEY_MATERIAL + /* Validate key for any sigHashAlg and eccParam hello extensions */ + if (validateKeyForExtensions(ssl, spec, givenKey) < 0){ + givenKey = NULL; + } else { +#endif + ssl->cipher = spec; + ssl->keys = givenKey; + return PS_SUCCESS; +#ifdef VALIDATE_KEY_MATERIAL + } +#endif + } + + psAssert(givenKey == NULL); + return PS_UNSUPPORTED_FAIL; /* Server can't match anything */ +} +#endif /* USE_SERVER_SIDE */ + + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#ifdef USE_ECC_CIPHER_SUITE +/* + See if any of the EC suites are supported. Needed by client very early on + to know whether or not to add the EC client hello extensions +*/ +int32_t eccSuitesSupported(const ssl_t *ssl, + const uint16_t cipherSpecs[], uint8_t cipherSpecLen) +{ + int32 i = 0; + + if (cipherSpecLen == 0) { + if (sslGetCipherSpec(ssl, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) || + sslGetCipherSpec(ssl, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) || + sslGetCipherSpec(ssl, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) || + sslGetCipherSpec(ssl, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) || + sslGetCipherSpec(ssl, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) || + sslGetCipherSpec(ssl, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) || + sslGetCipherSpec(ssl, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) || + sslGetCipherSpec(ssl, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) || +#ifdef USE_TLS_1_2 + sslGetCipherSpec(ssl, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256)|| + sslGetCipherSpec(ssl, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384)|| + sslGetCipherSpec(ssl, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) || + sslGetCipherSpec(ssl, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) || + sslGetCipherSpec(ssl, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256) || + sslGetCipherSpec(ssl, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384) || + sslGetCipherSpec(ssl, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)|| + sslGetCipherSpec(ssl, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)|| + sslGetCipherSpec(ssl, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) || + sslGetCipherSpec(ssl, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) || + sslGetCipherSpec(ssl, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) || + sslGetCipherSpec(ssl, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) || + sslGetCipherSpec(ssl, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) || + sslGetCipherSpec(ssl, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) || + sslGetCipherSpec(ssl, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) || + sslGetCipherSpec(ssl, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) || + sslGetCipherSpec(ssl, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) || + sslGetCipherSpec(ssl, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) || +#endif + sslGetCipherSpec(ssl, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA)) { + return 1; + } + } else { + while (i < cipherSpecLen) { + if (cipherSpecs[i] == TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA || + cipherSpecs[i] == TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA || + cipherSpecs[i] == TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA || + cipherSpecs[i] == TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA || + cipherSpecs[i] == TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA || + cipherSpecs[i] == TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA || + cipherSpecs[i] == TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA || + cipherSpecs[i] == TLS_ECDH_RSA_WITH_AES_256_CBC_SHA || +#ifdef USE_TLS_1_2 + cipherSpecs[i] == TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 || + cipherSpecs[i] == TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 || + cipherSpecs[i] == TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 || + cipherSpecs[i] == TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 || + cipherSpecs[i] == TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 || + cipherSpecs[i] == TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 || + cipherSpecs[i] == TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 || + cipherSpecs[i] == TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 || + cipherSpecs[i] == TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 || + cipherSpecs[i] == TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 || + cipherSpecs[i] == TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 || + cipherSpecs[i] == TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 || + cipherSpecs[i] == TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 || + cipherSpecs[i] == TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 || + cipherSpecs[i] == TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 || + cipherSpecs[i] == TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 || + cipherSpecs[i] == TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 || + cipherSpecs[i] == TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 || +#endif + cipherSpecs[i] == TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) { + return 1; + } + i++; + } + } + return 0; +} +#endif /* USE_ECC_CIPHER_SUITE */ + +#ifdef USE_CLIENT_SIDE_SSL +/* Test if agreed upon cipher suite authentication is being adhered to */ +int32 csCheckCertAgainstCipherSuite(int32 pubKey, int32 cipherType) +{ + if (pubKey == PS_RSA) { + if (cipherType == CS_DHE_RSA || cipherType == CS_RSA || + cipherType == CS_ECDHE_RSA) { + return 1; + } + } + if (pubKey == PS_ECC) { + if (cipherType == CS_ECDHE_ECDSA || cipherType == CS_ECDH_ECDSA || + cipherType == CS_ECDH_RSA) { + return 1; + } + + } + return 0; /* no match */ +} +#endif /* USE_CLIENT_SIDE_SSL */ +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ + +/******************************************************************************/ +/** + Lookup the given cipher spec ID. + @param[in] id The official ciphersuite id to find. + @return A pointer to the cipher suite structure, if configured in build. + If not defined, return NULL. +*/ +const sslCipherSpec_t *sslGetDefinedCipherSpec(uint16_t id) +{ + uint8_t i; + + for (i = 0; supportedCiphers[i].ident != SSL_NULL_WITH_NULL_NULL; i++) { + if (supportedCiphers[i].ident == id) { + return &supportedCiphers[i]; + } + } + return NULL; +} + +/******************************************************************************/ +/** + Lookup and validate the given cipher spec ID. + Return a pointer to the structure if found and meeting constraints in 'ssl'. + This is used when negotiating security, to find out what suites we support. + @param[in] id The official ciphersuite id to find. + @return A pointer to the cipher suite structure, if configured in build + and appropriate for the constraints in 'ssl'. + If not defined or apprppriate, return NULL. +*/ +const sslCipherSpec_t *sslGetCipherSpec(const ssl_t *ssl, uint16_t id) +{ + uint8_t i; +#ifdef USE_SERVER_SIDE_SSL + uint8_t j; +#endif /* USE_SERVER_SIDE_SSL */ + + i = 0; + do { + if (supportedCiphers[i].ident == id) { + /* Double check we support the requsted hash algorithm */ +#ifndef USE_MD5 + if (supportedCiphers[i].flags & CRYPTO_FLAGS_MD5) { + return NULL; + } +#endif +#ifndef USE_SHA1 + if (supportedCiphers[i].flags & CRYPTO_FLAGS_SHA1) { + return NULL; + } +#endif +#if !defined(USE_SHA256) && !defined(USE_SHA384) + if (supportedCiphers[i].flags & CRYPTO_FLAGS_SHA2) { + return NULL; + } +#endif + /* Double check we support the requsted weak cipher algorithm */ +#ifndef USE_ARC4 + if (supportedCiphers[i].flags & + (CRYPTO_FLAGS_ARC4INITE | CRYPTO_FLAGS_ARC4INITD)) { + return NULL; + } +#endif +#ifndef USE_3DES + if (supportedCiphers[i].flags & CRYPTO_FLAGS_3DES) { + return NULL; + } +#endif +#ifdef USE_SERVER_SIDE_SSL + /* Globally disabled? */ + if (disabledCipherFlags[i >> 5] & (1 < (i & 31))) { + psTraceIntInfo("Matched cipher suite %d but disabled by user\n", + id); + return NULL; + } + /* Disabled for session? */ + if (id != 0) { /* Disable NULL_WITH_NULL_NULL not possible */ + for (j = 0; j < SSL_MAX_DISABLED_CIPHERS; j++) { + if (ssl->disabledCiphers[j] == id) { + psTraceIntInfo("Matched cipher suite %d but disabled by user\n", + id); + return NULL; + } + } + } +#endif /* USE_SERVER_SIDE_SSL */ +#ifdef USE_TLS_1_2 + /* Unusable because protocol doesn't allow? */ +#ifdef USE_DTLS + if (ssl->majVer == DTLS_MAJ_VER && + ssl->minVer != DTLS_1_2_MIN_VER) { + if (supportedCiphers[i].flags & CRYPTO_FLAGS_SHA3 || + supportedCiphers[i].flags & CRYPTO_FLAGS_SHA2) { + psTraceIntInfo("Matched cipher suite %d but only allowed in DTLS 1.2\n", + id); + return NULL; + } + } + if (!(ssl->flags & SSL_FLAGS_DTLS)) { +#endif + if (ssl->minVer != TLS_1_2_MIN_VER) { + if (supportedCiphers[i].flags & CRYPTO_FLAGS_SHA3 || + supportedCiphers[i].flags & CRYPTO_FLAGS_SHA2) { + psTraceIntInfo("Matched cipher suite %d but only allowed in TLS 1.2\n", + id); + return NULL; + } + } + + if (ssl->minVer == TLS_1_2_MIN_VER) { + if (supportedCiphers[i].flags & CRYPTO_FLAGS_MD5) { + psTraceIntInfo("Not allowing MD5 suite %d in TLS 1.2\n", + id); + return NULL; + } + } +#ifdef USE_DTLS + } +#endif +#endif /* TLS_1_2 */ + + /* The suite is available. Want to reject if current key material + does not support? */ +#ifdef VALIDATE_KEY_MATERIAL + if (ssl->keys != NULL) { + if (haveKeyMaterial(ssl, supportedCiphers[i].type, 0) + == PS_SUCCESS) { + return &supportedCiphers[i]; + } + psTraceIntInfo("Matched cipher suite %d but no supporting keys\n", + id); + } else { + return &supportedCiphers[i]; + } +#else + return &supportedCiphers[i]; +#endif /* VALIDATE_KEY_MATERIAL */ + } + } while (supportedCiphers[i++].ident != SSL_NULL_WITH_NULL_NULL) ; + + return NULL; +} + + +/******************************************************************************/ +/* + Write out a list of the supported cipher suites to the caller's buffer + First 2 bytes are the number of cipher suite bytes, the remaining bytes are + the cipher suites, as two byte, network byte order values. +*/ +int32_t sslGetCipherSpecList(ssl_t *ssl, unsigned char *c, int32 len, + int32 addScsv) +{ + unsigned char *end, *p; + unsigned short i; + int32 ignored; + + if (len < 4) { + return -1; + } + end = c + len; + p = c; c += 2; + + ignored = 0; + for (i = 0; supportedCiphers[i].ident != SSL_NULL_WITH_NULL_NULL; i++) { + if (end - c < 2) { + return PS_MEM_FAIL; + } +#ifdef USE_TLS_1_2 + /* The SHA-2 based cipher suites are TLS 1.2 only so don't send + those if the user has requested a lower protocol in + NewClientSession */ +#ifdef USE_DTLS + if (ssl->majVer == DTLS_MAJ_VER && ssl->minVer != DTLS_1_2_MIN_VER) { + if (supportedCiphers[i].flags & CRYPTO_FLAGS_SHA3 || + supportedCiphers[i].flags & CRYPTO_FLAGS_SHA2) { + ignored += 2; + continue; + } + } + if (!(ssl->flags & SSL_FLAGS_DTLS)) { +#endif + if (ssl->minVer != TLS_1_2_MIN_VER) { + if (supportedCiphers[i].flags & CRYPTO_FLAGS_SHA3 || + supportedCiphers[i].flags & CRYPTO_FLAGS_SHA2) { + ignored += 2; + continue; + } + } +#ifdef USE_DTLS + } +#endif +#endif /* TLS_1_2 */ +#ifdef VALIDATE_KEY_MATERIAL + if (haveKeyMaterial(ssl, supportedCiphers[i].type, 0) != PS_SUCCESS) { + ignored += 2; + continue; + } +#endif + *c = (unsigned char)((supportedCiphers[i].ident & 0xFF00) >> 8); c++; + *c = (unsigned char)(supportedCiphers[i].ident & 0xFF); c++; + } + i *= 2; + i -= (unsigned short)ignored; +#ifdef ENABLE_SECURE_REHANDSHAKES + if (addScsv == 1) { +#ifdef USE_CLIENT_SIDE_SSL + ssl->extFlags.req_renegotiation_info = 1; +#endif + if (end - c < 2) { + return PS_MEM_FAIL; + } + *c = ((TLS_EMPTY_RENEGOTIATION_INFO_SCSV & 0xFF00) >> 8); c++; + *c = TLS_EMPTY_RENEGOTIATION_INFO_SCSV & 0xFF; c++; + i += 2; + } +#endif + +#ifdef USE_CLIENT_SIDE_SSL + /* This flag is set in EncodeClientHello based on sslSessOpts_t.fallbackScsv */ + if (ssl->extFlags.req_fallback_scsv) { + /** Add the fallback signalling ciphersuite. + @see https://tools.ietf.org/html/rfc7507 */ + if (end - c < 2) { + return PS_MEM_FAIL; + } + *c = (TLS_FALLBACK_SCSV >> 8) & 0xFF; c++; + *c = TLS_FALLBACK_SCSV & 0xFF; c++; + i += 2; + } +#endif + + *p = (unsigned char)(i >> 8); p++; + *p = (unsigned char)(i & 0xFF); + return i + 2; +} + +/******************************************************************************/ +/* + Return the length of the cipher spec list, including initial length bytes, + (minus any suites that we don't have the key material to support) +*/ +int32_t sslGetCipherSpecListLen(const ssl_t *ssl) +{ + int32 i, ignored; + + ignored = 0; + for (i = 0; supportedCiphers[i].ident != SSL_NULL_WITH_NULL_NULL; i++) { +#ifdef USE_TLS_1_2 + /* The SHA-2 based cipher suites are TLS 1.2 only so don't send + those if the user has requested a lower protocol in + NewClientSession */ +#ifdef USE_DTLS + if (ssl->majVer == DTLS_MAJ_VER && ssl->minVer != DTLS_1_2_MIN_VER) { + if (supportedCiphers[i].flags & CRYPTO_FLAGS_SHA3 || + supportedCiphers[i].flags & CRYPTO_FLAGS_SHA2) { + ignored += 2; + continue; + } + } + if (!(ssl->flags & SSL_FLAGS_DTLS)) { +#endif + if (ssl->minVer != TLS_1_2_MIN_VER) { + if (supportedCiphers[i].flags & CRYPTO_FLAGS_SHA3 || + supportedCiphers[i].flags & CRYPTO_FLAGS_SHA2) { + ignored += 2; + continue; + } + } +#ifdef USE_DTLS + } +#endif +#endif /* USE_TLS_1_2 */ +#ifdef VALIDATE_KEY_MATERIAL + if (haveKeyMaterial(ssl, supportedCiphers[i].type, 0) != PS_SUCCESS) { + ignored += 2; + } +#endif + } + return (i * 2) + 2 - ignored; +} + +/******************************************************************************/ +/* + Flag the session based on the agreed upon cipher suite + NOTE: sslResetContext will have cleared these flags for re-handshakes +*/ +void matrixSslSetKexFlags(ssl_t *ssl) +{ + +#ifdef USE_DHE_CIPHER_SUITE +/* + Flag the specific DH ciphers so the correct key exchange + mechanisms can be used. And because DH changes the handshake + messages as well. +*/ + if (ssl->cipher->type == CS_DHE_RSA) { + ssl->flags |= SSL_FLAGS_DHE_KEY_EXCH; + ssl->flags |= SSL_FLAGS_DHE_WITH_RSA; + } + +#ifdef USE_PSK_CIPHER_SUITE +/* + Set the PSK flags and DH kex. + NOTE: Although this isn't technically a DH_anon cipher, the handshake + message order for DHE_PSK are identical and we can nicely piggy back + on the handshake logic that already exists. +*/ + if (ssl->cipher->type == CS_DHE_PSK) { + ssl->flags |= SSL_FLAGS_DHE_KEY_EXCH; + ssl->flags |= SSL_FLAGS_ANON_CIPHER; + ssl->flags |= SSL_FLAGS_PSK_CIPHER; +#ifdef USE_CLIENT_AUTH + if (ssl->flags & SSL_FLAGS_SERVER) { + if (ssl->flags & SSL_FLAGS_CLIENT_AUTH) { + psTraceInfo("No client auth TLS mode for DHE_PSK ciphers"); + psTraceInfo(". Disabling CLIENT_AUTH.\n"); + ssl->flags &= ~SSL_FLAGS_CLIENT_AUTH; + } + } +#endif /* USE_CLIENT_AUTH */ + } +#endif /* USE_PSK_CIPHER_SUITE */ + +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->cipher->type == CS_ECDHE_RSA) { + ssl->flags |= SSL_FLAGS_ECC_CIPHER; + ssl->flags |= SSL_FLAGS_DHE_KEY_EXCH; + ssl->flags |= SSL_FLAGS_DHE_WITH_RSA; + } + if (ssl->cipher->type == CS_ECDHE_ECDSA) { + ssl->flags |= SSL_FLAGS_ECC_CIPHER; + ssl->flags |= SSL_FLAGS_DHE_KEY_EXCH; + ssl->flags |= SSL_FLAGS_DHE_WITH_DSA; + } +#endif /* USE_ECC_CIPHER_SUITE */ + +#ifdef USE_ANON_DH_CIPHER_SUITE + if (ssl->cipher->type == CS_DH_ANON) { + ssl->flags |= SSL_FLAGS_DHE_KEY_EXCH; + ssl->flags |= SSL_FLAGS_ANON_CIPHER; + ssl->sec.anon = 1; + } +#endif /* USE_ANON_DH_CIPHER_SUITE */ +#endif /* USE_DHE_CIPHER_SUITE */ + +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->cipher->type == CS_ECDH_ECDSA) { + ssl->flags |= SSL_FLAGS_ECC_CIPHER; + } + if (ssl->cipher->type == CS_ECDH_RSA) { + ssl->flags |= SSL_FLAGS_ECC_CIPHER; + } +#endif /* USE_ECC_CIPHER_SUITE */ + +#ifdef USE_PSK_CIPHER_SUITE + if (ssl->cipher->type == CS_PSK) { + ssl->flags |= SSL_FLAGS_PSK_CIPHER; +#ifdef USE_CLIENT_AUTH + if (ssl->flags & SSL_FLAGS_SERVER) { + if (ssl->flags & SSL_FLAGS_CLIENT_AUTH) { + psTraceInfo("No client auth TLS mode for basic PSK ciphers"); + psTraceInfo(". Disabling CLIENT_AUTH.\n"); + ssl->flags &= ~SSL_FLAGS_CLIENT_AUTH; + } + } +#endif /* USE_CLIENT_AUTH */ + } +#endif /* USE_PSK_CIPHER_SUITE */ + + return; +} +/******************************************************************************/ + diff --git a/matrixssl/dtls.c b/matrixssl/dtls.c new file mode 100644 index 0000000..766c3ce --- /dev/null +++ b/matrixssl/dtls.c @@ -0,0 +1,1113 @@ +/** + * @file dtls.c + * @version $Format:%h%d$ + * + * DTLS specific code. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "matrixsslApi.h" + +#ifdef USE_DTLS +/******************************************************************************/ + +static int32 globalPmtu; + +#ifdef USE_SERVER_SIDE_SSL + +#ifndef DTLS_COOKIE_KEY_SIZE +#define DTLS_COOKIE_KEY_SIZE 32 +#endif /* DTLS_COOKIE_KEY_SIZE */ + +#if DTLS_COOKIE_KEY_SIZE < 16 +#error "DTLS_COOKIE_KEY_SIZE too small (recommended 32 or more)." +#endif /* DTLS_COOKIE_KEY_SIZE */ + +/* The cookie key is generated once on startup. */ +static unsigned char cookie_key[DTLS_COOKIE_KEY_SIZE] = { 0 }; + +int32 dtlsGenCookieSecret(void) +{ + int i; + int32 res; + + /* Check if cookie_key appears ok from first octets. + Retry at most three times if values appear not ok (too many zeroes). */ + for(i = 0; i < 4; i++) { + res = matrixCryptoGetPrngData(cookie_key, DTLS_COOKIE_KEY_SIZE, + NULL); + if ((cookie_key[0] | cookie_key[1] | cookie_key[2] | + cookie_key[3]) != 0) + return res; + } + return PS_FAILURE; /* Unable to get cookie_key from RNG. */ +} + +int32_t dtlsComputeCookie(ssl_t *ssl, unsigned char *helloBytes, int32 helloLen) +{ + unsigned char hmacKey[SHA256_HASHLEN]; + unsigned char out[SHA256_HASHLEN]; + uint16_t hmacKeyLen; + int32_t rc; + + /* Ensure cookie_key has been initialized. + (Initialization at dtlsGenCookieSecret() makes sure one of first + four bytes is non-zero if initialization succeeded. */ + if ((cookie_key[0] | cookie_key[1] | cookie_key[2] | cookie_key[3]) == 0) + { + return PS_FAIL; + } +#ifdef USE_HMAC_SHA256 + #if DTLS_COOKIE_SIZE > SHA256_HASHLEN + #error "DTLS_COOKIE_SIZE too large" + #endif + rc = psHmacSha256(cookie_key, DTLS_COOKIE_KEY_SIZE, helloBytes, helloLen, + out, hmacKey, &hmacKeyLen); +#elif defined (USE_HMAC_SHA1) + #if DTLS_COOKIE_SIZE > SHA1_HASHLEN + #error "DTLS_COOKIE_SIZE too large" + #endif + rc = psHmacSha1(cookie_key, DTLS_COOKIE_KEY_SIZE, helloBytes, helloLen, + out, hmacKey, &hmacKeyLen); +#else + #error Must define HMAC_SHA256 or HMAC_SHA1 with DTLS +#endif + if (rc >= 0) { + /* Truncate hash output if necessary */ + memcpy(ssl->srvCookie, out, DTLS_COOKIE_SIZE); + } + memzero_s(out, DTLS_COOKIE_SIZE); + return rc; +} +#endif /* USE_SERVER_SIDE_SSL */ + +/******************************************************************************/ +/* + The PS_MIN_PMTU value is enforced to keep all handshake messages other + than CERTIFIATE to contained within a single datagram +*/ +int32 matrixDtlsSetPmtu(int32 pmtu) +{ + if (pmtu < 0) { + globalPmtu = DTLS_PMTU; + } else { + globalPmtu = pmtu; + } + if (globalPmtu < PS_MIN_PMTU) { + psTraceIntDtls("PMTU set too small. Defaulting to %d\n", PS_MIN_PMTU); + globalPmtu = PS_MIN_PMTU; + } + return globalPmtu; +} + +int32 matrixDtlsGetPmtu(void) +{ + return globalPmtu; +} + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) +static int32 fragmentHSMessage(ssl_t *ssl, unsigned char *msg, int32 msgLen, + int32 hsType, unsigned char *c); +static int32 postponeEncryptFragRecord(ssl_t *ssl, int32 padLen, + int32 fragCount, int32 fragLen, int32 msgLen, int32 type, + int32 hsMsg, unsigned char *encryptStart, unsigned char **c); +#endif +/******************************************************************************/ +/* + The certificate message spans records +*/ +int32 dtlsWriteCertificate(ssl_t *ssl, int32 certLen, int32 lsize, + unsigned char *c) +{ +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) + psX509Cert_t *cert; + unsigned char *tmp, *tmpStart; + int32 tmpLen, wLen; +/* + DTLS fragmented writes are done backwards. The message info is written + to a temp buffer and the hs header and record header are wrapped around + that as the fragmentation is done. +*/ + tmpLen = certLen + lsize; + tmpStart = tmp = psMalloc(NULL, tmpLen); + if (tmpStart == NULL) { + return SSL_MEM_ERROR; + } + + *tmp = (unsigned char)(((certLen + (lsize - 3)) & 0xFF0000) >> 16); tmp++; + *tmp = ((certLen + (lsize - 3)) & 0xFF00) >> 8; tmp++; + *tmp = ((certLen + (lsize - 3)) & 0xFF); tmp++; + + if (certLen > 0) { + cert = ssl->keys->cert; + while (cert) { + certLen = cert->binLen; + if (certLen > 0) { + *tmp = (unsigned char)((certLen & 0xFF0000) >> 16); tmp++; + *tmp = (certLen & 0xFF00) >> 8; tmp++; + *tmp = (certLen & 0xFF); tmp++; + memcpy(tmp, cert->unparsedBin, certLen); + tmp += certLen; + } + cert = cert->next; + } + } + +/* + Fragment it +*/ + wLen = fragmentHSMessage(ssl, tmpStart, tmpLen, SSL_HS_CERTIFICATE, c); + psFree(tmpStart, NULL); + return wLen; +#else + /* Wrapping in defines here to keep sslEncode a bit more clear. Need + this because 'cert' is not available on straight USE_CLIENT_SIDE + and no danger here at all because an empty CERTIFICATE message will + never need fragmentation. This is just a compile issue */ + return 0; +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ +} + + +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) +/******************************************************************************/ +/* + The certificate_request message spans records +*/ +int32 dtlsWriteCertificateRequest(psPool_t *pool, ssl_t *ssl, int32 certLen, + int32 certCount, int32 sigHashLen, unsigned char *c) +{ + psX509Cert_t *cert; + unsigned char *tmp, *tmpStart; + int32 tmpLen, wLen; + +/* + DTLS fragmented writes are done backwards. The message info is written + to a temp buffer and the hs header and record header are wrapped around + that as the fragmentation is done. +*/ + tmpLen = certLen + 4 + (certCount * 2) + sigHashLen; +#ifdef USE_ECC + tmpLen++; +#endif + tmpStart = tmp = psMalloc(pool, tmpLen); + if (tmpStart == NULL) { + return SSL_MEM_ERROR; + } + +#ifdef USE_ECC + *tmp++ = 2; + *tmp++ = ECDSA_SIGN; +#else + *tmp++ = 1; +#endif + *tmp++ = RSA_SIGN; +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + /* RFC: "The interaction of the certificate_types and + supported_signature_algorithms fields is somewhat complicated. + certificate_types has been present in TLS since SSLv3, but was + somewhat underspecified. Much of its functionality is superseded + by supported_signature_algorithms." + + The spec says the cert must support the hash/sig algorithm but + it's a bit confusing what this means for the hash portion. + Just going to use SHA1, SHA256, and SHA384 support. + + We're just sending the raw list of all sig algorithms that are + compiled into the library. It might be smart to look through the + individual CA files here only send the pub key operations that + they use but the CA info is sent explicitly anyway so the client + can confirm they have a proper match. + + If a new algorithm is added here it will require additions to + messageSize directly above in this function and in the flight + calculation in sslEncodeResponse */ + *tmp++ = 0x0; + *tmp++ = sigHashLen - 2; +#ifdef USE_ECC +#ifdef USE_SHA384 + *tmp++ = 0x5; /* SHA384 */ + *tmp++ = 0x3; /* ECDSA */ + *tmp++ = 0x4; /* SHA256 */ + *tmp++ = 0x3; /* ECDSA */ + *tmp++ = 0x2; /* SHA1 */ + *tmp++ = 0x3; /* ECDSA */ +#else + *tmp++ = 0x4; /* SHA256 */ + *tmp++ = 0x3; /* ECDSA */ + *tmp++ = 0x2; /* SHA1 */ + *tmp++ = 0x3; /* ECDSA */ +#endif +#endif + +#ifdef USE_RSA +#ifdef USE_SHA384 + *tmp++ = 0x5; /* SHA384 */ + *tmp++ = 0x1; /* RSA */ + *tmp++ = 0x4; /* SHA256 */ + *tmp++ = 0x1; /* RSA */ + *tmp++ = 0x2; /* SHA1 */ + *tmp++ = 0x1; /* RSA */ +#else + *tmp++ = 0x4; /* SHA256 */ + *tmp++ = 0x1; /* RSA */ + *tmp++ = 0x2; /* SHA1 */ + *tmp++ = 0x1; /* RSA */ +#endif +#endif /* USE_RSA */ + } +#endif /* TLS_1_2 */ + +#if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH) + cert = ssl->keys->CAcerts; +#else + cert = NULL; +#endif + if (cert) { + *tmp = ((certLen + (certCount * 2))& 0xFF00) >> 8; tmp++; + *tmp = (certLen + (certCount * 2)) & 0xFF; tmp++; + while (cert) { + *tmp = (cert->subject.dnencLen & 0xFF00) >> 8; tmp++; + *tmp = cert->subject.dnencLen & 0xFF; tmp++; + memcpy(tmp, cert->subject.dnenc, cert->subject.dnencLen); + tmp += cert->subject.dnencLen; + cert = cert->next; + } + } else { + *tmp++ = 0; /* Cert len */ + *tmp++ = 0; + } + +/* + Fragment it +*/ + wLen = fragmentHSMessage(ssl, tmpStart, tmpLen, SSL_HS_CERTIFICATE_REQUEST, + c); + psFree(tmpStart, pool); + return wLen; +} + +/******************************************************************************/ +/* + Given the data message and lengths, chunk up the message into a + multi-record handshake message +*/ +static int32 fragmentHSMessage(ssl_t *ssl, unsigned char *msg, int32 msgLen, + int32 hsType, unsigned char *c) +{ + unsigned char *msgStart, *encryptStart; + int32 tmpLen, recordLen, fragLen, offset, fragCount, + padLen, overhead, secureOverhead; + + offset = fragCount = padLen = secureOverhead = 0; + msgStart = c; + tmpLen = msgLen; + + overhead = ssl->recordHeadLen + ssl->hshakeHeadLen; + + if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) && (ssl->enBlockSize > 1)) { + secureOverhead = ssl->enMacSize + /* handshake msg hash */ + (ssl->enBlockSize * 2); /* explictIV and max pad */ + + } + if (ssl->flags & SSL_FLAGS_AEAD_W) { + secureOverhead += AEAD_TAG_LEN(ssl) + AEAD_NONCE_LEN(ssl); + } + + while (tmpLen > 0) { + if (tmpLen >= (ssl->pmtu - overhead - secureOverhead)) { + recordLen = ssl->pmtu - ssl->recordHeadLen; + fragLen = ssl->pmtu - overhead - secureOverhead; + } else { + recordLen = tmpLen + ssl->hshakeHeadLen; + fragLen = tmpLen; + } + + /* Make secure adjustments */ + if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) && (ssl->enBlockSize > 1)) { + recordLen = fragLen + ssl->hshakeHeadLen + ssl->enMacSize + + ssl->enBlockSize; + padLen = psPadLenPwr2(recordLen, ssl->enBlockSize); + recordLen += padLen; + } + /* Make secure adjustments for final fragment */ + if (ssl->flags & SSL_FLAGS_AEAD_W) { + recordLen = fragLen + ssl->hshakeHeadLen + secureOverhead; + } + + c += psWriteRecordInfo(ssl, SSL_RECORD_TYPE_HANDSHAKE, recordLen, c, + hsType); + encryptStart = c; + + if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) && (ssl->enBlockSize > 1)) { + if (matrixCryptoGetPrngData(c, ssl->enBlockSize, ssl->userPtr) < 0){ + psTraceDtls("WARNING: matrixCryptoGetPrngData failed\n"); + } + c += ssl->enBlockSize; + } + c += psWriteHandshakeHeader(ssl, (unsigned char)hsType, msgLen, + ssl->msn, offset, fragLen, c); + + memcpy(c, msg, fragLen); + msg += fragLen; + c += fragLen; + offset += fragLen; + tmpLen -= fragLen; + + postponeEncryptFragRecord(ssl, padLen, fragCount, fragLen, + msgLen, SSL_RECORD_TYPE_HANDSHAKE, hsType, encryptStart, &c); + + fragCount++; + } +/* + Can now safely increment the MSN now that all fragments are written +*/ + ssl->msn++; + +/* + In theory, there is no reason the sender of the fragmented messages + should care how many fragments it used but we should warn if + MAX_FRAGMENTS has been exceeded because if the DTLS peer was also + linked with the same MatrixSSL library, there will be a problem on + that side when parsing +*/ + if (fragCount > MAX_FRAGMENTS) { + psTraceIntDtls("Warning: MAX_FRAGMENTS exceeded %d\n", + MAX_FRAGMENTS); + } + return (int32)(c - msgStart); +} + +static int32 postponeEncryptFragRecord(ssl_t *ssl, int32 padLen, + int32 fragCount, int32 fragLen, int32 msgLen, int32 type, + int32 hsMsg, unsigned char *encryptStart, unsigned char **c) +{ + flightEncode_t *flight, *prev; + + if ((flight = psMalloc(ssl->flightPool, sizeof(flightEncode_t))) == NULL) { + return PS_MEM_FAIL; + } + memset(flight, 0x0, sizeof(flightEncode_t)); + if (ssl->flightEncode == NULL) { + ssl->flightEncode = flight; + } else { + prev = ssl->flightEncode; + while (prev->next) { + prev = prev->next; + } + prev->next = flight; + } + + flight->start = encryptStart; + flight->len = fragLen; + flight->type = type; + flight->padLen = padLen; + flight->messageSize = msgLen; + flight->hsMsg = hsMsg; + flight->seqDelay = ssl->seqDelay; + flight->fragCount = ++fragCount; /* Add one to differentiate from 0 based */ + + *c += ssl->enMacSize; + *c += padLen; + + if (hsMsg == SSL_HS_FINISHED) { + if (ssl->cipher->flags & (CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_CHACHA | CRYPTO_FLAGS_CCM)) { + *c += AEAD_TAG_LEN(ssl); + } + } else if (ssl->flags & SSL_FLAGS_AEAD_W) { + *c += AEAD_TAG_LEN(ssl); /* c is tracking end of record here and the + tag has not yet been accounted for */ + } + + return PS_SUCCESS; +} + + +int32 dtlsEncryptFragRecord(ssl_t *ssl, flightEncode_t *msg, + sslBuf_t *out, unsigned char **c) +{ + unsigned char *updateHash, *encryptStart; + unsigned char fakeHeader[SSL3_HANDSHAKE_HEADER_LEN + DTLS_HEADER_ADD_LEN]; + + encryptStart = out->end + ssl->recordHeadLen; + + updateHash = msg->start; + if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) && (ssl->enBlockSize > 1)) { + updateHash += ssl->enBlockSize; + /* The data has already been bypassed in c at this point, FYI */ + *c += ssl->enBlockSize; + } + + if (msg->fragCount == 1) { + /* + Can snapshot hs hash now. A bit tricky because we have to treat + the message as if there is no fragmentation at all. This means + we actually are hashing a header format that isn't really + sent at all. We deal with this by flaging the first fragment + and manually tweaking the fragLen value. +*/ + memcpy(fakeHeader, updateHash, ssl->hshakeHeadLen); +/* + A bit ugly. The fragLen is the final three bytes of the header +*/ + fakeHeader[ssl->hshakeHeadLen - 3] = + (unsigned char)((msg->messageSize & 0xFF0000) >> 16); + fakeHeader[ssl->hshakeHeadLen - 2] = (msg->messageSize & 0xFF00) >> 8; + fakeHeader[ssl->hshakeHeadLen - 1] = (msg->messageSize & 0xFF); + sslUpdateHSHash(ssl, fakeHeader, ssl->hshakeHeadLen); + } + sslUpdateHSHash(ssl, updateHash + ssl->hshakeHeadLen, msg->len); + *c += ssl->hshakeHeadLen; + + if (ssl->flags & SSL_FLAGS_AEAD_W) { + encryptStart += AEAD_NONCE_LEN(ssl); + ssl->outRecType = (unsigned char)msg->type; + } + + if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) && (ssl->enBlockSize > 1)) { + *c += ssl->generateMac(ssl, (unsigned char)msg->type, + encryptStart + ssl->enBlockSize, + (int32)(*c - encryptStart) - ssl->enBlockSize, *c); + } + *c += sslWritePad(*c, (unsigned char)msg->padLen); + + if (ssl->flags & SSL_FLAGS_AEAD_W) { + *c += AEAD_TAG_LEN(ssl); /* c is tracking end of record here and the + tag has not yet been accounted for */ + } + + if (ssl->encrypt(ssl, encryptStart, encryptStart, + (int32)(*c - encryptStart)) < 0) { + psTraceStrInfo("Error encrypting message for write\n", NULL); + return PS_FAILURE; + } + + dtlsIncrRsn(ssl); + + return 0; +} +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ +#endif /* !USE_ONLY_PSK_CIPHER_SUITES */ + +/******************************************************************************/ +/* + Have all the fragments and their headers. Feed them through the + UpdateHSHash routine in the order they were on the other side +*/ +int32 dtlsHsHashFragMsg(ssl_t *ssl) +{ + unsigned char fakeHeader[SSL3_HANDSHAKE_HEADER_LEN + DTLS_HEADER_ADD_LEN]; + int32 i, nextOffset, headLen, totalLen; +/* + Construct the message from the fragments (may be out of order) +*/ + nextOffset = i = totalLen = 0; + while(i < MAX_FRAGMENTS) { + if (ssl->fragHeaders[i].offset == nextOffset) { +/* + We must send this message through the handshake hash mechanism + as if there was no fragmentation at all. A nextOffset value + of 0 will always mean this is the first fragment. This header + has everything correct except the fragLen value. This must + be manually changed to be the full 'len' value. The remainder + of the fragment headers are not used. +*/ + if (nextOffset == 0) { + headLen = SSL3_HANDSHAKE_HEADER_LEN + DTLS_HEADER_ADD_LEN; + memcpy(fakeHeader, ssl->fragHeaders[i].hsHeader, headLen); +/* + First byte is 'type'. Next three are total length. Final + three are fragLen. +*/ + fakeHeader[headLen - 3] = fakeHeader[1]; + fakeHeader[headLen - 2] = fakeHeader[2]; + fakeHeader[headLen - 1] = fakeHeader[3]; + + sslUpdateHSHash(ssl, fakeHeader, headLen); +/* + Also grabbing the total length so we can make a smart loop exit +*/ + totalLen = fakeHeader[1] << 16; + totalLen += fakeHeader[2] << 8; + totalLen += fakeHeader[3]; + } +/* + The remainder of the UpdateHS hash is simply the data from each frag +*/ + + sslUpdateHSHash(ssl, ssl->fragMessage + ssl->fragHeaders[i].offset, + ssl->fragHeaders[i].fragLen); + + nextOffset += ssl->fragHeaders[i].fragLen; + i = 0; + } else { + if (nextOffset != 0 && nextOffset == totalLen) { + break; + } + i++; + } + } + return 0; +} + +/******************************************************************************/ +/* + * Replay detection, per IPSec + * http://www.faqs.org/rfcs/rfc2401.html Appendix C + * Returns 0 if packet disallowed, 1 if packet permitted + */ +enum { + ReplayWindowSize = 32 +}; +int32 dtlsChkReplayWindow(ssl_t *ssl, unsigned char *seq64) +{ + unsigned long diff, seq, lastSeq; + unsigned char *ls64; + +/* + TODO DTLS - We truncate 48 bit sequence to 32bits to make it simpler here +*/ + seq = (seq64[2] << 24) + (seq64[3] << 16) + (seq64[4] << 8) + seq64[5]; + ls64 = ssl->lastRsn; + lastSeq = (ls64[2] << 24) + (ls64[3] << 16) + (ls64[4] << 8) + ls64[5]; + + if (seq == 0) { + /* Need to differentiate between initial, duplicate, and epoch shift */ + if (lastSeq == 0 && ssl->rec.epoch[0] == 0 && ssl->rec.epoch[1] == 0) { + ssl->dtlsBitmap = 0; + return 1; /* initial one */ + } + if (dtlsCompareEpoch(ssl->rec.epoch, ssl->resendEpoch) == 1 && + lastSeq > 0) { + ssl->dtlsBitmap = 0; + return 1; /* epoch shift */ + } + if (lastSeq == 0xFFFFFFF) { + ssl->dtlsBitmap = 0; + return 1; /* wrapped */ + } + return 0; /* duplicate */ + } + + if (seq > lastSeq) { /* new larger sequence number */ + diff = seq - lastSeq; + if (diff < ReplayWindowSize) { /* In window */ + ssl->dtlsBitmap <<= diff; + ssl->dtlsBitmap |= 1; /* set bit for this packet */ + } else { + ssl->lastRsn[0] = 1; /* This packet has a "way larger" */ + } + memcpy(ssl->lastRsn, seq64, 6); + return 1; /* larger is good */ + } + diff = lastSeq - seq; + if (diff >= ReplayWindowSize) { + return 0; /* too old or wrapped */ + } + if (ssl->dtlsBitmap & ((int32)1 << diff)) { + return 0; /* already seen */ + } + ssl->dtlsBitmap |= ((unsigned long)1 << diff); /* mark as seen */ + return 1; /* out of order but good */ +} + +/******************************************************************************/ +/* + Init ssl_t fragment members +*/ +void dtlsInitFrag(ssl_t *ssl) +{ + int32 i; +/* + This is also used for re-init so there may be memory to free here. +*/ + ssl->fragTotal = 0; + for (i = 0; i < MAX_FRAGMENTS; i++) { + ssl->fragHeaders[i].offset = -1; + if (ssl->fragHeaders[i].hsHeader != NULL) { + psFree(ssl->fragHeaders[i].hsHeader, ssl->hsPool); + ssl->fragHeaders[i].hsHeader = NULL; + } + } +} + +/******************************************************************************/ +/* + Return 1 if this fragment has been seen before. Just reads the + fragHeaders member. Does not update. +*/ +int32 dtlsSeenFrag(ssl_t *ssl, int32 fragOffset, int32 *hdrIndex) +{ + int32 i; + + for (i = 0; i < MAX_FRAGMENTS; i++) { + if (ssl->fragHeaders[i].offset == -1) { + *hdrIndex = i; + return 0; + } + if (ssl->fragHeaders[i].offset == fragOffset) { + return 1; + } + } +/* + Max fragments exceeded error +*/ + return -1; +} + +/******************************************************************************/ +/* + Treating this unsigned char array as a 48bit uint +*/ +void dtlsIncrRsn(ssl_t *ssl) +{ + int32 i; + + for (i = 5; i >= 0; i--) { + if ((int)ssl->rsn[i] < 0xFF) { + ssl->rsn[i]++; + if (ssl->rsn[i] > ssl->largestRsn[i]) { + ssl->largestRsn[i] = ssl->rsn[i]; + } + break; + } + ssl->rsn[i] = 0; + } +} + +/* + Treating this 2 byte unsigned char array as a uint16 +*/ +void incrTwoByte(ssl_t *ssl, unsigned char *c, int sending) +{ + int32 i; + + if (sending) { + c[0] = ssl->largestEpoch[0]; + c[1] = ssl->largestEpoch[1]; + } + + for (i = 1; i >= 0; i--) { + if ((int)c[i] < 0xFF) { + c[i]++; + if (sending) { + if (c[i] > ssl->largestEpoch[i]) { + ssl->largestEpoch[i] = c[i]; + } + } + break; + } + c[i] = 0; + } +} + +void zeroTwoByte(unsigned char *c) +{ + c[0] = 0; + c[1] = 0; +} + +void zeroSixByte(unsigned char *c) +{ + int32 i; + + for (i = 5; i >= 0; i--) { + c[i] = 0; + } +} + +int32 dtlsCompareEpoch(unsigned char *incoming, unsigned char *expected) +{ + int32 i; + + for (i = 0; i < 2; i++) { + if (incoming[i] < expected[i]) { + return -1; + } + if (incoming[i] > expected[i]) { + return 1; + } + } + return 0; +} + +/******************************************************************************/ +/* + Rewinding our context +*/ +static int32 dtlsRevertWriteCipher(ssl_t *ssl) +{ + ssl->encrypt = ssl->oencrypt; + ssl->generateMac = ssl->ogenerateMac; + ssl->enMacSize = ssl->oenMacSize; + ssl->nativeEnMacSize = ssl->oenNativeHmacSize; + ssl->enIvSize = ssl->oenIvSize; + ssl->enBlockSize = ssl->oenBlockSize; + memcpy(ssl->sec.writeIV, ssl->owriteIV, ssl->oenIvSize); + memcpy(ssl->sec.writeMAC, ssl->owriteMAC, ssl->oenMacSize); + memcpy(&ssl->sec.encryptCtx, &ssl->oencryptCtx, + sizeof(psCipherContext_t)); +#ifdef ENABLE_SECURE_REHANDSHAKES + memcpy(ssl->myVerifyData, ssl->omyVerifyData, ssl->omyVerifyDataLen); + ssl->myVerifyDataLen = ssl->omyVerifyDataLen; +#endif /* ENABLE_SECURE_REHANDSHAKES */ + +/* + If the old versions of the write state indicate that we were in an + unencrypted state, remove the SECURE_WRITE flags. Block, MAC, and IV are + sufficient tests for all potential cipher suites since only block ciphers + are allowed for DTLS +*/ + if (ssl->oenMacSize == 0 && ssl->oenBlockSize == 0 && ssl->oenIvSize == 0) { + ssl->flags &= ~SSL_FLAGS_WRITE_SECURE; +#ifdef USE_TLS_1_2 + ssl->flags &= ~SSL_FLAGS_AEAD_W; + ssl->flags &= ~SSL_FLAGS_NONCE_W; +#endif /* USE_TLS_1_2 */ + } + /* Case where moved to GCM on write FINISHED from CBC-SHA and need to get + back to CBC-SHA */ + if (ssl->flags & SSL_FLAGS_AEAD_W && ssl->oenMacSize > 0) { + ssl->flags &= ~SSL_FLAGS_AEAD_W; + ssl->flags &= ~SSL_FLAGS_NONCE_W; + } + /* Case where moved to CBC-SHA on write FINISHED from GCM and need to get + back to GCM */ + if (!(ssl->flags & SSL_FLAGS_AEAD_W) && ssl->oenMacSize == 0 && + ssl->oenIvSize > 0) { + ssl->flags |= SSL_FLAGS_AEAD_W; + ssl->flags |= SSL_FLAGS_NONCE_W; + } + +/* + Toggle flag to reset the logic for determing HANDSHAKE_COMPLETE in + the top level APIs +*/ + ssl->bFlags &= ~BFLAG_HS_COMPLETE; + return 0; +} + +/******************************************************************************/ +/* + + */ +static int32 dtlsResendFlight(ssl_t *ssl, psBuf_t *out) +{ + int32 rc; + uint32 requiredLen = 0; /* only added so far to get to compile */ +/* + Reset to the MSN and epoch of the first message in the current flight +*/ + ssl->msn = ssl->resendMsn; + rc = dtlsCompareEpoch(ssl->epoch, ssl->resendEpoch); + if (rc != 0) { +/* + We are dealing with a CHANGE_CIPHER_SPEC flight resend so we must + revert to the old write cipher +*/ + dtlsRevertWriteCipher(ssl); +/* + It is also necessary to make sure rsn is updated to the largest + previously sent record number because if this flight is a resend that + includes the CHANGE_CIPHER_SPEC message so the rsn has been reset +*/ + ssl->rsn[0] = ssl->largestRsn[0]; + ssl->rsn[1] = ssl->largestRsn[1]; + ssl->rsn[2] = ssl->largestRsn[2]; + ssl->rsn[3] = ssl->largestRsn[3]; + ssl->rsn[4] = ssl->largestRsn[4]; + ssl->rsn[5] = ssl->largestRsn[5]; + } + ssl->epoch[0] = ssl->resendEpoch[0]; + ssl->epoch[1] = ssl->resendEpoch[1]; + + +encode: + ssl->retransmit = 1; + rc = sslEncodeResponse(ssl, out, &requiredLen); + ssl->retransmit = 0; + + if (rc == PS_SUCCESS) { + if (ssl->err != SSL_ALERT_NONE) { + ssl->flags |= SSL_FLAGS_ERROR; + return PS_FAILURE; + } + } + + if (rc == SSL_FULL) { + psFree(out->buf, ssl->bufferPool); + if ((out->buf = psMalloc(ssl->bufferPool, requiredLen)) == NULL) { + return PS_MEM_FAIL; + } + out->start = out->end = out->buf; + out->size = requiredLen; + goto encode; + } + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Takes a 'flight' of records and returns the length of how many full + records from the front of the buffer can fit in a single pmtu. Used + by the sockets layer to send out an already fragmented flight with + the proper byte lengths. +*/ +static int32 dtlsGetNextRecordLen(ssl_t *ssl, int32 pmtu, sslBuf_t *out, + int32 *recordLen) +{ + int32 tlen, len; + unsigned char *newend; + + newend = out->start; + tlen = len = 0; +/* + If pmtu is <= 0 the user wants a single record regardless +*/ + if (pmtu <= 0) { + newend += ssl->recordHeadLen - 2; /* Find the last two bytes of len */ + len += (int32)*newend << 8; newend++; + len += (int32)*newend; newend++; + newend += len; + len += ssl->recordHeadLen; /* add record header length to the total */ + *recordLen = len; + return 0; + } + +/* + Could be called for non-fragmented cases as well. Check to see if the + whole thing will fit in a mtu and return that info if so +*/ + if ((out->end - out->start) < pmtu) { + *recordLen = (int32)(out->end - out->start); + return 0; + } + +/* + Otherwise, send as much as will fit +*/ + while (out->end > newend) { + newend += ssl->recordHeadLen - 2; /* Find the last two bytes of len */ + len = (int32)*newend << 8; newend++; + len += (int32)*newend; newend++; + newend += len; + len += ssl->recordHeadLen; /* add record header length to the total */ +/* + See if more records can fit in this single write. Just storing + current length in temps and reading off the next one. If it doesn't + fit, just go with the temps. +*/ + if ((len + tlen) <= pmtu) { + tlen += len; + continue; + } + break; + } + *recordLen = tlen; + + return 0; +} + +/******************************************************************************/ +/* + Manages the DTLS flight buffer to make sure each call will return data + that is less than the PMTU (dtlsGetNextRecordLen). Also, plays a role + in determining whether a flight resend needs to happen. Basically, if there + is no data in outbuf and this is the first call to this function under + that condition, we assume this is the standard processing loop and return + 0 to indicate we are done with the flight. Subsequent calls to this + function in which no outdata exists (and not in an explicit app data mode) + will rebuild the last handshake flight and start feeding it out again + + NOTE: This function must be called in a loop with a corresponding + matrixDtlsSentData until this routine returns 0. +*/ +int32 matrixDtlsGetOutdata(ssl_t *ssl, unsigned char **buf) +{ + psBuf_t tmp; + int32 bytesToSend, rc; + int16 safeToResend; + + if (!ssl || !buf) { + return PS_ARG_FAIL; + } + + tmp.buf = tmp.start = ssl->outbuf; + tmp.end = tmp.buf + ssl->outlen; + tmp.size = ssl->outsize; + +/* + First test is just to see if we are already in an app data mode with + nothing in the outbuffer to send. Don't want to resend a handshake flight +*/ + if ((tmp.end == tmp.start) && (ssl->appDataExch == 1)) { + *buf = NULL; + return 0; + } + +/* + Next, if ssl->outbuf is empty and flightDone is set, this is the mechansim + for the handshake loop to know the full flight has been sent. Return + 0 and flag the flight as needing a resend for the cases in which we + come back in here with a zero buffer (a timeout happen and resend needed) +*/ + if ((tmp.end == tmp.start) && (ssl->flightDone == 1)) { + ssl->flightDone = 0; + *buf = NULL; + return 0; + } + +/* + If ssl->outbuf is empty and not in appDataExch mode this is a flight resend +*/ + if ((tmp.end == tmp.start) && (ssl->appDataExch == 0)) { + + /* And now the ugly part. If we have been receiving records that + are sent individually and we are successfully midway through an + incomming flight, we don't want to resend our previous flight. We + are still just waiting for the remainder of the flight from the peer. + The only way to figure this out is to test our specific state to + make sure we are on a flight boundary. This gets somewhat complicated + simply due to the different types of handshakes (standard, resumed, + and client auth) having different flight boundaries. + + The state is always the handshake message you expect to be receiving + from the peer. + */ + safeToResend = 0; + + if (ssl->flags & SSL_FLAGS_SERVER) { + if (ssl->hsState == SSL_HS_CLIENT_HELLO) { + safeToResend = 1; /* any handshake type */ + } + if (!(ssl->flags & SSL_FLAGS_RESUMED)) { + if (ssl->hsState == SSL_HS_DONE) { + safeToResend = 1; /* DONE set on parse of peer FINISHED */ + } + } + +#ifdef USE_CLIENT_AUTH + /* Different client auth boundary for second flight */ + if (ssl->flags & SSL_FLAGS_CLIENT_AUTH) { + if (ssl->hsState == SSL_HS_CERTIFICATE) { + safeToResend = 1; + } + } else { +#endif /* USE_CLIENT_AUTH */ + if (ssl->hsState == SSL_HS_CLIENT_KEY_EXCHANGE) { + safeToResend = 1; + } +#ifdef USE_CLIENT_AUTH + } +#endif /* USE_CLIENT_AUTH */ + + if (ssl->flags & SSL_FLAGS_RESUMED) { + if (ssl->hsState == SSL_HS_FINISHED) { + safeToResend = 1; + } + } + + } else { + /* Client tests */ + if (ssl->hsState == SSL_HS_SERVER_HELLO) { + safeToResend = 1; + } + if (!(ssl->flags & SSL_FLAGS_RESUMED)) { + if (ssl->hsState == SSL_HS_FINISHED) { + safeToResend = 1; + } + } + if (ssl->hsState == SSL_HS_DONE) { + safeToResend = 1; /* Done is set on parse of peer FINISHED */ + } + + } + + if (safeToResend == 0) { + psTraceIntDtls("Refused a resend due to state %d\n", ssl->hsState); + *buf = NULL; + return 0; + } + + /* A true flight resend is needed */ + if ((rc = dtlsResendFlight(ssl, &tmp)) < 0) { + return rc; + } + ssl->outbuf = tmp.buf; + ssl->outlen = tmp.end - tmp.start; + ssl->outsize = tmp.size; + } + +/* + Sending records individually is more of a test mode for being able to + drop more packets to test re-ordering and resend logic. In either case, + PMTU size will always be adhered to. +*/ +#ifdef DTLS_SEND_RECORDS_INDIVIDUALLY + dtlsGetNextRecordLen(ssl, 0, &tmp, &bytesToSend); +#else + dtlsGetNextRecordLen(ssl, matrixDtlsGetPmtu(), &tmp, &bytesToSend); +#endif + + *buf = ssl->outbuf; + return bytesToSend; +} + +/******************************************************************************/ +/* + Plays the other half in determining flight resends. If this send ate all + the bytes in outbuf AND we are known not to be in a appDataExch state, we + flag flightDone so the next call to matrixDtlsGetOutdata will know to + return 0 instead of resending the flight. + + NOTE: If this peer ONLY sends app data and never receives any in return it + is possible to get into a state where flightDone is set after each app + data send since appDataExch will never be flagged. The consequence of this + scenario would be that the ChangeCipherSpec and Finished message will be + sent if matrixDtlsGetOutdata is called with no application data to send. + Not really a big deal, actually, since it should be ignored by the peer +*/ +int32 matrixDtlsSentData(ssl_t *ssl, uint32 bytes) +{ + int32 rc; + + rc = matrixSslSentData(ssl, bytes); +/* + NOTE: appDataExch only gets set on the receipt of an application data +*/ + if (ssl->outlen == 0 && ssl->appDataExch == 0) { + ssl->flightDone = 1; + } + return rc; +} + +#endif /* USE_DTLS */ + diff --git a/matrixssl/extDecode.c b/matrixssl/extDecode.c new file mode 100644 index 0000000..a9ae8db --- /dev/null +++ b/matrixssl/extDecode.c @@ -0,0 +1,1051 @@ +/** + * @file extDecode.c + * @version $Format:%h%d$ + * + * CLIENT_HELLO and SERVER_HELLO extension parsing + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "matrixsslApi.h" + +/******************************************************************************/ + +#ifdef USE_SERVER_SIDE_SSL +static int ClientHelloExt(ssl_t *ssl, unsigned short extType, + unsigned short extLen, const unsigned char *c); +#endif +#ifdef USE_CLIENT_SIDE_SSL +static int ServerHelloExt(ssl_t *ssl, unsigned short extType, + unsigned short extLen, const unsigned char *c); +#endif +#ifdef USE_ALPN +static int dealWithAlpnExt(ssl_t *ssl, const unsigned char *c, + unsigned short extLen); +#endif + +#ifdef USE_SERVER_SIDE_SSL +/******************************************************************************/ +/* + Parse the ClientHello extension list. +*/ +int32 parseClientHelloExtensions(ssl_t *ssl, unsigned char **cp, unsigned short len) +{ + unsigned short extLen, extType; + unsigned char *c, *end; + int rc; +#ifdef ENABLE_SECURE_REHANDSHAKES + unsigned short renegotiationExtSent = 0; +#endif + + c = *cp; + end = c + len; + + /* Clear extFlags in case of rehandshakes */ + ssl->extFlags.truncated_hmac = 0; + ssl->extFlags.sni = 0; + ssl->extFlags.session_id = 0; + ssl->extFlags.session_ticket = 0; + ssl->extFlags.extended_master_secret = 0; + ssl->extFlags.status_request = 0; + + /* There could be extension data to parse here: + Two byte length and extension info. + http://www.faqs.org/rfcs/rfc3546.html + + NOTE: This c != end test is only safe because ClientHello is the + only record/message in the flight of supported handshake protocols. */ + if (c != end) { + if (end - c < 2) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid extension header len\n"); + return MATRIXSSL_ERROR; + } + extLen = *c << 8; c++; /* Total length of list, in bytes */ + extLen += *c; c++; + /* extLen must be minimum 2 b type 2 b len and 0 b value */ + if ((uint32)(end - c) < extLen || extLen < 4) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid extension header len\n"); + return MATRIXSSL_ERROR; + } + +#ifdef USE_TLS_1_2 + ssl->hashSigAlg = 0; +#endif + while (c != end) { + extType = *c << 8; c++; /* Individual hello ext */ + extType += *c; c++; + if (end - c < 2) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid extension header len\n"); + return MATRIXSSL_ERROR; + } + extLen = *c << 8; c++; /* length of one extension */ + extLen += *c; c++; + /* Minimum extension value len is 0 bytes */ + if ((uint32)(end - c) < extLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid extension header len\n"); + return MATRIXSSL_ERROR; + } +#ifdef ENABLE_SECURE_REHANDSHAKES + if (extType == EXT_RENEGOTIATION_INFO) { + renegotiationExtSent = 1; + } +#endif + /* Parse incoming client extensions we support. */ + if ((rc = ClientHelloExt(ssl, extType, extLen, c)) < 0) { + /* On error, ssl->error will have been set */ + return rc; + } + c += extLen; + } + } + + /* Handle the extensions that were missing or not what we wanted */ + if (ssl->extFlags.require_extended_master_secret == 1 && + ssl->extFlags.extended_master_secret == 0) { + psTraceInfo("Client doesn't support extended master secret\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + +#if defined(USE_TLS_1_2) && defined(USE_CERT_PARSE) + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + if (!ssl->hashSigAlg) { +#ifdef USE_SHA1 + /* Client didn't send the extension at all. Unfortunately, spec says we + have to assume SHA1 in this case, even though both peers are + already calculating a SHA256 based handshake hash. */ +#ifdef USE_RSA_CIPHER_SUITE + ssl->hashSigAlg |= HASH_SIG_SHA1_RSA_MASK; +#endif +#ifdef USE_ECC_CIPHER_SUITE + ssl->hashSigAlg |= HASH_SIG_SHA1_ECDSA_MASK; +#endif +#else + if (ssl->flags & SSL_FLAGS_CLIENT_AUTH) { + psTraceInfo("Client didn't provide hashSigAlg and sha1 not supported\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } +#endif /* USE_SHA1 */ + } + } +#endif /* USE_TLS_1_2 */ + +#ifdef USE_STATELESS_SESSION_TICKETS + /* If session ID was sent that we didn't like AND no ticket was sent + then we can forget we ever received a sessionID now */ + if (ssl->extFlags.session_id == 1) { + memset(ssl->sessionId, 0, SSL_MAX_SESSION_ID_SIZE); + ssl->sessionIdLen = 0; + } + ssl->extFlags.session_id = 0; + ssl->extFlags.session_ticket = 0; +#endif + +#ifdef ENABLE_SECURE_REHANDSHAKES + if (!renegotiationExtSent) { +#ifdef REQUIRE_SECURE_REHANDSHAKES + /* Check if SCSV was sent instead */ + if (ssl->secureRenegotiationFlag == PS_FALSE && + ssl->myVerifyDataLen == 0) { + psTraceInfo("Client doesn't support renegotiation hello\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } +#endif /* REQUIRE_SECURE_REHANDSHAKES */ + if (ssl->secureRenegotiationFlag == PS_TRUE && + ssl->myVerifyDataLen > 0) { + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + psTraceInfo("Cln missing renegotiationInfo on re-hndshk\n"); + return MATRIXSSL_ERROR; + } +#ifndef ENABLE_INSECURE_REHANDSHAKES + if (ssl->secureRenegotiationFlag == PS_FALSE && + ssl->myVerifyDataLen > 0) { + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + psTraceInfo("Cln attempting insecure handshake\n"); + return MATRIXSSL_ERROR; + } +#endif /* !ENABLE_INSECURE_REHANDSHAKES */ + } +#endif /* ENABLE_SECURE_REHANDSHAKES */ + + *cp = c; + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Parse a single client extension +*/ +static int ClientHelloExt(ssl_t *ssl, unsigned short extType, unsigned short extLen, + const unsigned char *c) +{ + int i; +#ifdef USE_ECC_CIPHER_SUITE + unsigned short dataLen, curveId; + uint32 ecFlags; +#endif /* USE_ECC_CIPHER_SUITE */ +#ifdef USE_TLS_1_2 + unsigned short tmpLen; +#endif + + switch (extType) { + + /**************************************************************************/ + + case EXT_TRUNCATED_HMAC: + if (extLen != 0) { + psTraceInfo("Bad truncated HMAC extension\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + /* User could have disabled for this session */ + if (!ssl->extFlags.deny_truncated_hmac) { + ssl->extFlags.truncated_hmac = 1; + } + break; + + case EXT_EXTENDED_MASTER_SECRET: + if (extLen != 0) { + psTraceInfo("Bad extended master secret extension\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + /* TODO: User can disable? */ + ssl->extFlags.extended_master_secret = 1; + break; + + /**************************************************************************/ + + case EXT_MAX_FRAGMENT_LEN: + if (extLen != 1) { + psTraceInfo("Invalid frag len ext len\n"); + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + return MATRIXSSL_ERROR; + } + /* User could have disabled for this session using + the session options */ + if (!ssl->extFlags.deny_max_fragment_len) { + if (*c == 0x1) { + ssl->maxPtFrag = 0x200; + } else if (*c == 0x2) { + ssl->maxPtFrag = 0x400; + } else if (*c == 0x3) { + ssl->maxPtFrag = 0x800; + } else if (*c == 0x4) { + ssl->maxPtFrag = 0x1000; + } else { + psTraceInfo("Client sent bad frag len value\n"); + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + return MATRIXSSL_ERROR; + } + } + break; + + /**************************************************************************/ + + case EXT_SNI: + /* Must hold (2 b len + 1 b zero) + 2 b len */ + if (extLen < 5) { + psTraceInfo("Invalid server name ext len\n"); + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + return MATRIXSSL_ERROR; + } + /* Two length bytes. May seem odd to ignore but + the inner length is repeated right below after + the expected 0x0 bytes */ + i = *c << 8; c++; + i += *c; c++; + if (*c++ != 0x0) { + psTraceInfo("Expected host_name in SNI ext\n"); + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + return MATRIXSSL_ERROR; + } + extLen -= 3; + i = *c << 8; c++; + i += *c; c++; + extLen -= 2; /* Length check covered above */ + /* Arbitrary length cap between 1 and min(extlen,255) */ + if ((int32)extLen < i || i > 255 || i <= 0) { + psTraceInfo("Invalid host name ext len\n"); + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + return MATRIXSSL_ERROR; + } + if (ssl->expectedName) { + psFree(ssl->expectedName, ssl->sPool); + } + if ((ssl->expectedName = psMalloc(ssl->sPool, i + 1)) == NULL) { + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + memcpy(ssl->expectedName, c, i); + ssl->expectedName[i] = '\0'; + break; + +#ifdef USE_ALPN + /**************************************************************************/ + + case EXT_ALPN: + /* Must hold 2 b len 1 b zero 2 b len */ + if (extLen < 2) { + psTraceInfo("Invalid ALPN ext len\n"); + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + return MATRIXSSL_ERROR; + } + /* Skip extension if server didn't register callback */ + if (ssl->srv_alpn_cb) { + int rc; + if ((rc = dealWithAlpnExt(ssl, c, extLen)) < 0) { + if (rc == PS_PROTOCOL_FAIL) { + /* This is a user space rejection */ + psTraceInfo("User rejects ALPN ext\n"); + ssl->err = SSL_ALERT_NO_APP_PROTOCOL; + return MATRIXSSL_ERROR; + } + psTraceInfo("Invalid ALPN ext\n"); + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + return MATRIXSSL_ERROR; + } + } + break; +#endif + +#ifdef ENABLE_SECURE_REHANDSHAKES + /**************************************************************************/ + + case EXT_RENEGOTIATION_INFO: + if (ssl->secureRenegotiationFlag == PS_FALSE && + ssl->myVerifyDataLen == 0) { + if (extLen == 1 && *c == '\0') { + ssl->secureRenegotiationFlag = PS_TRUE; + } else { + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + psTraceInfo("Cln sent bad renegotiationInfo\n"); + return MATRIXSSL_ERROR; + } + } else if ((extLen == ssl->peerVerifyDataLen + 1) && + (ssl->secureRenegotiationFlag == PS_TRUE)) { + if (*c != ssl->peerVerifyDataLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid renegotiation encoding\n"); + return MATRIXSSL_ERROR; + } + if (memcmpct(c + 1, ssl->peerVerifyData, + ssl->peerVerifyDataLen) != 0) { + psTraceInfo("Cli verify renegotiation fail\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + } else { + psTraceInfo("Bad state/len of renegotiation ext\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + break; +#endif /* ENABLE_SECURE_REHANDSHAKES */ + +#ifdef USE_TLS_1_2 + /**************************************************************************/ + + case EXT_SIGNATURE_ALGORITHMS: + /* This extension is responsible for telling the server which + sig algorithms it accepts so here we are saving them + aside for when user chooses identity certificate. + https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */ + + /* Minimum length of 2 b type, 2 b alg */ + /* Arbitrary Max of 16 suites */ + if (extLen > (2 + 32) || extLen < 4 || (extLen & 1)) { + psTraceInfo("Malformed sig_alg len\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + + tmpLen = *c << 8; c++; + tmpLen |= *c; c++; + extLen -= 2; + + if ((uint32)tmpLen > extLen || tmpLen < 2 || (tmpLen & 1)) { + psTraceInfo("Malformed sig_alg extension\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + /* list of 2 byte pairs in a hash/sig format that + need to be searched to find match with server + cert sigAlgorithm + Test if client will be able to accept our sigs + based on what our idenity certificate is */ + while (tmpLen >= 2 && extLen >= 2) { + ssl->hashSigAlg |= HASH_SIG_MASK(c[0], c[1]); + c += 2; + tmpLen -= 2; + extLen -= 2; + } + break; +#endif /* USE_TLS_1_2 */ + +#ifdef USE_STATELESS_SESSION_TICKETS + /**************************************************************************/ + + case EXT_SESSION_TICKET: + /* Have a handy place to store this info. Tickets are + the only way a server will make use of 'sid'. + Could already exist if rehandshake case here */ + if (ssl->sid == NULL) { + /* Server just needs a spot to manage the state + of the negotiation. Uses the sessionTicketState + of this structure */ + ssl->sid = psMalloc(ssl->sPool, sizeof(sslSessionId_t)); + if (ssl->sid == NULL) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + return MATRIXSSL_ERROR; + } + memset(ssl->sid, 0x0, sizeof(sslSessionId_t)); + ssl->sid->pool = ssl->sPool; + } + if (extLen > 0) { /* received a ticket */ + ssl->extFlags.session_ticket = 1; + + if (matrixUnlockSessionTicket(ssl, (unsigned char*)c, extLen) == + PS_SUCCESS) { + /* Understood the token */ + ssl->flags |= SSL_FLAGS_RESUMED; + ssl->sid->sessionTicketState = SESS_TICKET_STATE_USING_TICKET; + memcpy(ssl->sec.masterSecret, ssl->sid->masterSecret, + SSL_HS_MASTER_SIZE); +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, RESUMPTIONS_STAT, 1); +#endif + } else { + /* If client sent a sessionId in the hello, + we can ignore that here now */ + if (ssl->sessionIdLen > 0) { + memset(ssl->sessionId, 0, SSL_MAX_SESSION_ID_SIZE); + ssl->sessionIdLen = 0; + } + /* Issue another one if we have any keys */ + if (ssl->keys && ssl->keys->sessTickets) { + ssl->sid->sessionTicketState = SESS_TICKET_STATE_RECVD_EXT; + } else { + ssl->sid->sessionTicketState = SESS_TICKET_STATE_INIT; + } +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, FAILED_RESUMPTIONS_STAT, 1); +#endif + } + } else { + /* Request for session ticket. Can we honor? */ + if (ssl->keys && ssl->keys->sessTickets) { + ssl->sid->sessionTicketState = SESS_TICKET_STATE_RECVD_EXT; + } else { + ssl->sid->sessionTicketState = SESS_TICKET_STATE_INIT; + } + } + break; +#endif /* USE_STATELESS_SESSION_TICKETS */ + +#ifdef USE_ECC_CIPHER_SUITE + /**************************************************************************/ + + case EXT_ELLIPTIC_CURVE: + /* Minimum is 2 b dataLen and 2 b cipher */ + if (extLen < 4) { + psTraceInfo("Invalid ECC Curve len\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + dataLen = *c << 8; c++; + dataLen += *c; c++; + extLen -= 2; + if (dataLen > extLen || dataLen < 2 || (dataLen & 1)) { + psTraceInfo("Malformed ECC Curve extension\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + /* Matching EC curve logic */ + ecFlags = IS_RECVD_EXT; /* Flag if we got it */ + ssl->ecInfo.ecCurveId = 0; + while (dataLen >= 2 && extLen >= 2) { + curveId = *c << 8; c++; + curveId += *c; c++; + dataLen -= 2; + extLen -= 2; +/* + Find the curves that are in common between client and server. + ssl->ecInfo.ecFlags defaults to all curves compiled into the library. +*/ + if (psTestUserEcID(curveId, ssl->ecInfo.ecFlags) == 0) { +/* + Client sends curves in priority order, so choose the first + one we have in common. If ECDHE, it will be used after + this CLIENT_HELLO parse as the ephemeral key gen curve. + If ECDH, it will be used to find a matching cert, and for + key exchange. +*/ + if (ecFlags == IS_RECVD_EXT) { + ssl->ecInfo.ecCurveId = curveId; + } + ecFlags |= curveIdToFlag(curveId); + } + } + ssl->ecInfo.ecFlags = ecFlags; + break; + + /**************************************************************************/ + + case EXT_ELLIPTIC_POINTS: + if (extLen < 1) { + psTraceInfo("Invaid ECC Points len\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + dataLen = *c; c++; /* single byte data len */ + extLen -= 1; + if (dataLen > extLen || dataLen < 1) { + psTraceInfo("Malformed ECC Points extension\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + /* One of them has to be a zero (uncompressed) and that + is all we are looking for at the moment */ + if (memchr(c, '\0', dataLen) == NULL) { + psTraceInfo("ECC Uncommpressed Points missing\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + break; +#endif /* USE_ECC_CIPHER_SUITE */ + +#ifdef USE_OCSP + case EXT_STATUS_REQUEST: + /* Validation of minimum size and status_type of 1 (ocsp) */ + if (extLen < 5 || *c != 0x1) { + psTraceIntInfo("Bad cert_status_request extension: %d\n", extType); + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + return MATRIXSSL_ERROR; + } + c++; extLen--; /* checked status type above */ + /* Skipping the ResponderIDs */ + dataLen = *c << 8; c++; extLen--; + dataLen += *c; c++; extLen--; + if (dataLen + 2 > extLen) { + psTraceIntInfo("Bad cert_status_request extension: \n", extType); + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + return MATRIXSSL_ERROR; + } + c += dataLen; + /* Skipping the Extensions */ + dataLen = *c << 8; c++; extLen--; + dataLen += *c; c++; extLen--; + if (dataLen > extLen) { + psTraceIntInfo("Bad cert_status_request extension: \n", extType); + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + return MATRIXSSL_ERROR; + } + c += dataLen; + /* Currently, the OCSPResponse must be loaded into the key material + so we check if that exists to determine if we will reply with + the extension and CERTIFICATE_STATUS handshake message */ + if (ssl->keys->OCSPResponseBufLen > 0 && + ssl->keys->OCSPResponseBuf != NULL) { + ssl->extFlags.status_request = 1; + } else { + psTraceInfo("Client requesting OCSP but we have no response\n"); + } + + break; +#endif + + + + + /**************************************************************************/ + + default: + psTraceIntInfo("Ignoring unknown extension: %d\n", extType); + break; + } + return PS_SUCCESS; +} + +#ifdef USE_ALPN + /**************************************************************************/ +/* + Parse Application Layer Protocol extension and invoke callback. No need + to advance any buffer pointers, caller is managing. +*/ +static int dealWithAlpnExt(ssl_t *ssl, const unsigned char *c, unsigned short extLen) +{ + int32 totLen, i, userChoice; + unsigned char *end; + char *proto[MAX_PROTO_EXT]; + int32 protoLen[MAX_PROTO_EXT]; + + end = (unsigned char*)c + extLen; + + totLen = *c << 8; c++; + totLen += *c; c++; + if (totLen != extLen - 2) { + return PS_PARSE_FAIL; + } + + for (i = 0; totLen > 0; i++) { + if (i + 1 > MAX_PROTO_EXT) { + i--; + break; + } + protoLen[i] = *c; c++; totLen--; + if (protoLen[i] > totLen) { + while (i > 0) { + psFree(proto[i - 1], ssl->sPool); + i--; + } + return PS_PARSE_FAIL; + } + if ((proto[i] = psMalloc(ssl->sPool, protoLen[i])) == NULL) { + while (i > 0) { + psFree(proto[i - 1], ssl->sPool); + i--; + } + return PS_MEM_FAIL; + } + memcpy(proto[i], c, protoLen[i]); + totLen -= protoLen[i]; + c += protoLen[i]; + } + + /* see if they touch it. Using a value outside the range to gauge */ + userChoice = MAX_PROTO_EXT; + + /* Already tested if callback exists */ + (*ssl->srv_alpn_cb)((void*)ssl, (short)i, proto, protoLen, &userChoice); + + if (userChoice == MAX_PROTO_EXT) { + /* User chose to completely ignore. No reply extension will be sent */ + while (i > 0) { + psFree(proto[i - 1], ssl->sPool); + i--; + } + return PS_SUCCESS; + } + if (userChoice >= i) { + /* User chose something completely unreasonable */ + while (i > 0) { + psFree(proto[i - 1], ssl->sPool); + i--; + } + return PS_LIMIT_FAIL; + } + + if (userChoice < 0) { + /* They actually rejected these completely. Returning the + no-application-protocol alert per the spec */ + while (i > 0) { + psFree(proto[i - 1], ssl->sPool); + i--; + } + return PS_PROTOCOL_FAIL; + } + + /* Allocated to session pool so fine to point to it and just skip + freeing it while cleaning up here */ + ssl->alpn = proto[userChoice]; + ssl->alpnLen = protoLen[userChoice]; + + while (i > 0) { + if (i - 1 != userChoice) { + psFree(proto[i - 1], ssl->sPool); + } + i--; + } + + return PS_SUCCESS; +} +#endif /* USE_ALPN */ + +#endif /* USE_SERVER_SIDE_SSL */ + +#ifdef USE_CLIENT_SIDE_SSL +/******************************************************************************/ +/* + Parse the ServerHello extension list. +*/ +int32 parseServerHelloExtensions(ssl_t *ssl, int32 hsLen, + unsigned char *extData, unsigned char **cp, + unsigned short len) +{ + unsigned short extLen, extType; + int32 rc; + unsigned char *c, *end; +#ifdef ENABLE_SECURE_REHANDSHAKES + unsigned short renegotiationExtSent = 0; +#endif + + rc = PS_SUCCESS; + c = *cp; + end = c + len; + + if (end - c < 2) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid extension header len\n"); + return MATRIXSSL_ERROR; + } + extLen = *c << 8; c++; /* Total length of list */ + extLen += *c; c++; + if ((uint32)(end - c) < extLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid extension header len\n"); + return MATRIXSSL_ERROR; + } + while ((int32)hsLen > (c - extData)) { + extType = *c << 8; c++; /* Individual hello ext */ + extType += *c; c++; + if (end - c < 2) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid extension header len\n"); + return MATRIXSSL_ERROR; + } + extLen = *c << 8; c++; /* Length of individual extension */ + extLen += *c; c++; + if ((uint32)(end - c) < extLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid extension header len\n"); + return MATRIXSSL_ERROR; + } +#ifdef ENABLE_SECURE_REHANDSHAKES + if (extType == EXT_RENEGOTIATION_INFO) { + renegotiationExtSent = 1; + } +#endif + if ((rc = ServerHelloExt(ssl, extType, extLen, c)) < 0) { + /* On error, ssl->error will have been set */ + return rc; + } + c += extLen; + } + + /* Enforce the rules for extensions that require the server to send + something back to us */ + + if (ssl->extFlags.req_extended_master_secret == 1) { + /* The req_extended_master_secret is reset to 0 when the server sends + one so this case means the server doesn't support it */ + if (ssl->extFlags.require_extended_master_secret == 1) { + psTraceInfo("Server doesn't support extended master secret\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + } + +#ifdef USE_OCSP_MUST_STAPLE + if (ssl->extFlags.req_status_request == 1) { + if (ssl->extFlags.status_request == 0) { + psTraceInfo("Server doesn't support OCSP stapling\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + } +#endif + +#ifdef ENABLE_SECURE_REHANDSHAKES + if (!renegotiationExtSent) { +#ifdef REQUIRE_SECURE_REHANDSHAKES + /* Check if SCSV was sent instead */ + if (ssl->secureRenegotiationFlag == PS_FALSE && + ssl->myVerifyDataLen == 0) { + psTraceInfo("Server doesn't support renegotiation hello\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } +#endif /* REQUIRE_SECURE_REHANDSHAKES */ + if (ssl->secureRenegotiationFlag == PS_TRUE && + ssl->myVerifyDataLen > 0) { + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + psTraceInfo("Server missing renegotiationInfo on re-hndshk\n"); + return MATRIXSSL_ERROR; + } +#ifndef ENABLE_INSECURE_REHANDSHAKES + if (ssl->secureRenegotiationFlag == PS_FALSE && + ssl->myVerifyDataLen > 0) { + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + psTraceInfo("Server attempting insecure handshake\n"); + return MATRIXSSL_ERROR; + } +#endif /* !ENABLE_INSECURE_REHANDSHAKES */ + } +#endif /* ENABLE_SECURE_REHANDSHAKES */ + + *cp = c; + return rc; +} + +/******************************************************************************/ +/* + Parse the ServerHello extension list. +*/ +static int ServerHelloExt(ssl_t *ssl, unsigned short extType, unsigned short extLen, + const unsigned char *c) +{ + int rc; + + /* Verify the server only responds with an extension the client requested. + Zero the value once seen so that it will catch the error if sent twice */ + rc = -1; + switch (extType) { + + /**************************************************************************/ + + case EXT_SNI: + if (ssl->extFlags.req_sni) { + ssl->extFlags.req_sni = 0; + if (ssl->extCb) { + rc = (*ssl->extCb)(ssl, extType, extLen, (void *)c); + } else { + rc = 0; + } + } + break; + + /**************************************************************************/ + + case EXT_MAX_FRAGMENT_LEN: + if (ssl->extFlags.req_max_fragment_len) { + ssl->extFlags.req_max_fragment_len = 0; + rc = 0; + } + if (!(ssl->maxPtFrag & 0x10000)) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Server sent unexpected MAX_FRAG ext\n"); + return MATRIXSSL_ERROR; + } + if (extLen != 1) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Server sent bad MAX_FRAG ext\n"); + return MATRIXSSL_ERROR; + } + /* Confirm it's the same size we requested and strip + off 0x10000 from maxPtrFrag */ + if (*c == 0x01 && + (ssl->maxPtFrag & 0x200)) { + ssl->maxPtFrag = 0x200; + } else if (*c == 0x02 && + (ssl->maxPtFrag & 0x400)) { + ssl->maxPtFrag = 0x400; + } else if (*c == 0x03 && + (ssl->maxPtFrag & 0x800)) { + ssl->maxPtFrag = 0x800; + } else if (*c == 0x04 && + (ssl->maxPtFrag & 0x1000)) { + ssl->maxPtFrag = 0x1000; + } else { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Server sent mismatched MAX_FRAG ext\n"); + return MATRIXSSL_ERROR; + } + c++; extLen--; + break; + + /**************************************************************************/ + + case EXT_TRUNCATED_HMAC: + if (ssl->extFlags.req_truncated_hmac) { + ssl->extFlags.req_truncated_hmac = 0; + rc = 0; + } + if (extLen != 0) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Server sent bad truncated hmac ext\n"); + return MATRIXSSL_ERROR; + } + ssl->extFlags.truncated_hmac = 1; + break; + + case EXT_EXTENDED_MASTER_SECRET: + if (ssl->extFlags.req_extended_master_secret) { + ssl->extFlags.req_extended_master_secret = 0; + rc = 0; + } + if (extLen != 0) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Server sent bad extended master secret ext\n"); + return MATRIXSSL_ERROR; + } + ssl->extFlags.extended_master_secret = 1; + break; + +#ifdef USE_ECC_CIPHER_SUITE + /**************************************************************************/ + + case EXT_ELLIPTIC_CURVE: + /* @note we do not allow EXT_ELLIPTIC_CURVE from server */ + break; + + /**************************************************************************/ + + case EXT_ELLIPTIC_POINTS: + if (ssl->extFlags.req_elliptic_points) { + ssl->extFlags.req_elliptic_points = 0; + rc = 0; + } + if (*c++ != (extLen - 1)) { + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + psTraceInfo("Server sent bad ECPointFormatList\n"); + return MATRIXSSL_ERROR; + } + extLen--; /* TODO: check that one of these bytes is 0 + (uncompressed point support) */ + break; +#endif /* USE_ECC_CIPHER_SUITE */ + + /**************************************************************************/ + + case EXT_SIGNATURE_ALGORITHMS: + /* @note we do not allow EXT_SIGNATURE_ALGORITHMS from server */ + break; + + /**************************************************************************/ + + case EXT_ALPN: + if (ssl->extFlags.req_alpn) { + ssl->extFlags.req_alpn = 0; + if (ssl->extCb) { + rc = (*ssl->extCb)(ssl, extType, extLen, (void *)c); + } else { + rc = 0; + } + } + break; + +#ifdef USE_STATELESS_SESSION_TICKETS + /**************************************************************************/ + + case EXT_SESSION_TICKET: + if (ssl->extFlags.req_session_ticket) { + ssl->extFlags.req_session_ticket = 0; + rc = 0; + } + if (ssl->sid && ssl->sid->sessionTicketState == + SESS_TICKET_STATE_SENT_EMPTY) { + ssl->sid->sessionTicketState = + SESS_TICKET_STATE_RECVD_EXT; /* expecting ticket */ + } else if (ssl->sid && ssl->sid->sessionTicketState == + SESS_TICKET_STATE_SENT_TICKET) { + ssl->sid->sessionTicketState = + SESS_TICKET_STATE_RECVD_EXT; /* expecting ticket */ + } else { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Server sent unexpected SESSION_TICKET\n"); + return MATRIXSSL_ERROR; + } + break; +#endif /* USE_STATELESS_SESSION_TICKETS */ + +#ifdef ENABLE_SECURE_REHANDSHAKES + /**************************************************************************/ + + case EXT_RENEGOTIATION_INFO: + if (ssl->extFlags.req_renegotiation_info) { + ssl->extFlags.req_renegotiation_info = 0; + rc = 0; + } + if (ssl->secureRenegotiationFlag == PS_FALSE && + ssl->myVerifyDataLen == 0) { + if (extLen == 1 && *c == '\0') { + ssl->secureRenegotiationFlag = PS_TRUE; + } else { + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + psTraceInfo("Server sent bad renegotiationInfo\n"); + return MATRIXSSL_ERROR; + } + } else if (ssl->secureRenegotiationFlag == PS_TRUE && + extLen == ((ssl->myVerifyDataLen * 2) + 1)) { + c++; extLen--; + if (memcmpct(c, ssl->myVerifyData, + ssl->myVerifyDataLen) != 0) { + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + psTraceInfo("Srv had bad my renegotiationInfo\n"); + return MATRIXSSL_ERROR; + } + if (memcmpct(c + ssl->myVerifyDataLen,ssl->peerVerifyData, + ssl->peerVerifyDataLen) != 0) { + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + psTraceInfo("Srv had bad peer renegotiationInfo\n"); + return MATRIXSSL_ERROR; + } + } else { + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + psTraceInfo("Server sent bad renegotiationInfo\n"); + return MATRIXSSL_ERROR; + } + break; +#endif /* ENABLE_SECURE_REHANDSHAKES */ + + + case EXT_STATUS_REQUEST: + if (ssl->extFlags.req_status_request) { + /* Weed out the unsolicited status_request */ + ssl->extFlags.status_request = 1; + rc = 0; + } + break; + + + /**************************************************************************/ + + default: + /* We don't recognize the extension, maybe the callback will */ + if (ssl->extCb) { + rc = (*ssl->extCb)(ssl, extType, extLen, (void *)c); + } + break; + } + + if (rc < 0) { + if (ssl->minVer >= TLS_1_2_MIN_VER) { + /* This alert was added only in 1.2 */ + ssl->err = SSL_ALERT_UNSUPPORTED_EXTENSION; + } else { + /* Use a generic alert for older versions */ + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + } + psTraceIntInfo("Server sent unsolicited or duplicate ext %d\n", + extType); + return MATRIXSSL_ERROR; + } + return rc; +} +#endif + + + /**************************************************************************/ + diff --git a/matrixssl/hsDecode.c b/matrixssl/hsDecode.c new file mode 100644 index 0000000..5fc0633 --- /dev/null +++ b/matrixssl/hsDecode.c @@ -0,0 +1,3106 @@ +/** + * @file hsDecode.c + * @version $Format:%h%d$ + * + * SSL/TLS handshake message parsing + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "matrixsslApi.h" + +#define USE_ECC_EPHEMERAL_KEY_CACHE + +/* Errors from these routines must either be MATRIXSSL_ERROR or PS_MEM_FAIL */ + +/******************************************************************************/ + +#ifdef USE_SERVER_SIDE_SSL +int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end) +{ + unsigned char *suiteStart, *suiteEnd; + unsigned char compareMin, compareMaj, suiteLen, compLen, serverHighestMinor; + uint32 resumptionOnTrack, cipher = 0; + int32 rc; + unsigned char *c; +#ifdef USE_ECC_CIPHER_SUITE + const psEccCurve_t *curve; +#endif +#if defined(USE_ECC) || defined(REQUIRE_DH_PARAMS) + void *pkiData = ssl->userPtr; +#endif + + + c = *cp; + + /* First two bytes are the highest supported major and minor SSL versions */ + psTraceHs(">>> Server parsing CLIENT_HELLO\n"); + +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, CH_RECV_STAT, 1); +#endif + if (end - c < 2) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ssl header version length\n"); + return MATRIXSSL_ERROR; + } + + ssl->reqMajVer = *c; c++; + ssl->reqMinVer = *c; c++; + + /* Client should always be sending highest supported protocol. Server + will reply with a match or a lower version if enabled (or forced). */ + if (ssl->majVer != 0) { + /* If our forced server version is a later protocol than their + request, we have to exit */ + if (ssl->reqMinVer < ssl->minVer) { + ssl->err = SSL_ALERT_PROTOCOL_VERSION; + psTraceInfo("Won't support client's SSL version\n"); + return MATRIXSSL_ERROR; + } +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + /* DTLS specfication somehow assigned minimum version of DTLS 1.0 + as 255 so there was nowhere to go but down in DTLS 1.1 so + that is 253 and requires the opposite test from above */ + if (ssl->reqMinVer > ssl->minVer) { + ssl->err = SSL_ALERT_PROTOCOL_VERSION; + psTraceInfo("Won't support client's DTLS version\n"); + return MATRIXSSL_ERROR; + } + } +#endif + /* Otherwise we just set our forced version to act like it was + what the client wanted in order to move through the standard + negotiation. */ + compareMin = ssl->minVer; + compareMaj = ssl->majVer; + /* Set the highest version to the version explicitly set */ + serverHighestMinor = ssl->minVer; + } else { + compareMin = ssl->reqMinVer; + compareMaj = ssl->reqMajVer; + /* If no explicit version was set for the server, use the highest supported */ + serverHighestMinor = TLS_HIGHEST_MINOR; + } + + if (compareMaj >= SSL3_MAJ_VER) { + ssl->majVer = compareMaj; +#ifdef USE_TLS + if (compareMin >= TLS_MIN_VER) { +#ifndef DISABLE_TLS_1_0 + ssl->minVer = TLS_MIN_VER; + ssl->flags |= SSL_FLAGS_TLS; +#endif +#ifdef USE_TLS_1_1 /* TLS_1_1 */ + if (compareMin >= TLS_1_1_MIN_VER) { +#ifndef DISABLE_TLS_1_1 + ssl->minVer = TLS_1_1_MIN_VER; + ssl->flags |= SSL_FLAGS_TLS_1_1 | SSL_FLAGS_TLS; +#endif + } +#ifdef USE_TLS_1_2 + if (compareMin == TLS_1_2_MIN_VER) { + ssl->minVer = TLS_1_2_MIN_VER; + ssl->flags |= SSL_FLAGS_TLS_1_2 | SSL_FLAGS_TLS_1_1 | SSL_FLAGS_TLS; + } +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (compareMin == DTLS_1_2_MIN_VER) { + ssl->minVer = DTLS_1_2_MIN_VER; + } + } +#endif +#endif /* USE_TLS_1_2 */ +#endif /* USE_TLS_1_1 */ + if (ssl->minVer == 0) { + /* TLS versions are disabled. Go SSLv3 if available. */ +#ifdef DISABLE_SSLV3 + ssl->err = SSL_ALERT_PROTOCOL_VERSION; + psTraceInfo("Can't support client's SSL version\n"); + return MATRIXSSL_ERROR; +#endif + ssl->minVer = SSL3_MIN_VER; + } + } else if (compareMin == 0) { +#ifdef DISABLE_SSLV3 + ssl->err = SSL_ALERT_PROTOCOL_VERSION; + psTraceInfo("Client wanted to talk SSLv3 but it's disabled\n"); + return MATRIXSSL_ERROR; +#else + ssl->minVer = SSL3_MIN_VER; +#endif /* DISABLE_SSLV3 */ + } +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (compareMin < DTLS_1_2_MIN_VER) { + ssl->err = SSL_ALERT_PROTOCOL_VERSION; + psTraceInfo("Error: incorrect DTLS required version\n"); + return MATRIXSSL_ERROR; + } + ssl->minVer = DTLS_MIN_VER; +#ifdef USE_TLS_1_2 + if (compareMin == DTLS_1_2_MIN_VER) { + ssl->flags |= SSL_FLAGS_TLS_1_2 | SSL_FLAGS_TLS_1_1 | SSL_FLAGS_TLS; + ssl->minVer = DTLS_1_2_MIN_VER; + } +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (compareMin == DTLS_1_2_MIN_VER) { + ssl->minVer = DTLS_1_2_MIN_VER; + } + } +#endif /* USE_DTLS */ +#endif /* USE_TLS_1_2 */ + + } +#endif /* USE_DTLS */ +#else + ssl->minVer = SSL3_MIN_VER; + +#endif /* USE_TLS */ + + } else { + ssl->err = SSL_ALERT_PROTOCOL_VERSION; + psTraceIntInfo("Unsupported ssl version: %d\n", compareMaj); + return MATRIXSSL_ERROR; + } + + if (ssl->rec.majVer > SSL2_MAJ_VER) { + /* Next is a 32 bytes of random data for key generation + and a single byte with the session ID length */ + if (end - c < SSL_HS_RANDOM_SIZE + 1) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceIntInfo("Invalid length of random data %d\n", + (int32)(end - c)); + return MATRIXSSL_ERROR; + } + memcpy(ssl->sec.clientRandom, c, SSL_HS_RANDOM_SIZE); + c += SSL_HS_RANDOM_SIZE; + ssl->sessionIdLen = *c; c++; /* length verified with + 1 above */ + /* If a session length was specified, the client is asking to + resume a previously established session to speed up the handshake */ + if (ssl->sessionIdLen > 0) { + if (ssl->sessionIdLen > SSL_MAX_SESSION_ID_SIZE || + end - c < ssl->sessionIdLen) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, FAILED_RESUMPTIONS_STAT, 1); +#endif + return MATRIXSSL_ERROR; + } + memcpy(ssl->sessionId, c, ssl->sessionIdLen); + c += ssl->sessionIdLen; + } else { + /* Always clear the RESUMED flag if no client session id + It may be re-enabled if a client session ticket extension is recvd */ + ssl->flags &= ~SSL_FLAGS_RESUMED; + } +#ifdef USE_DTLS + /* If DTLS is enabled, make sure we received a valid cookie in the + CLIENT_HELLO message. */ + if (ssl->flags & SSL_FLAGS_DTLS) { + uint16_t cookie_len; + /* Next field is the cookie length */ + if (end - c < 1) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Cookie length not provided\n"); + return MATRIXSSL_ERROR; + } + /** Calculate what we expect the cookie should be by hashing the + client_hello data up to this point: + + 2 byte version + 1 byte session_id_len + + session_id + client_random + + @future The creation of the cookie should ideally take some + IP Tuple information about the client into account. + @impl MatrixSSL sends a zero length cookie on re-handshake, but + other implementations may not, so this allows either + to be supported. + */ + cookie_len = 3 + ssl->sessionIdLen + SSL_HS_RANDOM_SIZE; + if (dtlsComputeCookie(ssl, c - cookie_len, cookie_len) < 0) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + psTraceInfo("Invalid cookie length\n"); + return MATRIXSSL_ERROR; + } + cookie_len = *c++; + if (cookie_len > 0) { + if (end - c < cookie_len || cookie_len != DTLS_COOKIE_SIZE) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Invalid cookie length\n"); + return MATRIXSSL_ERROR; + } + if (memcmpct(c, ssl->srvCookie, DTLS_COOKIE_SIZE) != 0) { + /* Cookie mismatch. Error to avoid possible DOS */ + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Cookie mismatch\n"); + return MATRIXSSL_ERROR; + } + c += DTLS_COOKIE_SIZE; + } else { + /* If client sent an empty cookie, and we're not secure + yet, set the hsState to encode a HELLO_VERIFY message to + the client, which will provide a new cookie. */ + if (!(ssl->flags & SSL_FLAGS_READ_SECURE)) { + ssl->hsState = SSL_HS_CLIENT_HELLO; + c = end; + *cp = c; + /* Clear session so it will be found again when the cookie + clientHello message comes in next */ + if (ssl->flags & SSL_FLAGS_RESUMED) { + matrixClearSession(ssl, 0); + } + /* Will cause HELLO_VERIFY to be encoded */ + return SSL_PROCESS_DATA; + } + /** No cookie provided on already secure connection. + @impl This is a re-handshake case. MatrixSSL lets it slide + since we're already authenticated. */ + } + } +#endif /* USE_DTLS */ + /* Next is the two byte cipher suite list length, network byte order. + It must not be zero, and must be a multiple of two. */ + if (end - c < 2) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid cipher suite list length\n"); + return MATRIXSSL_ERROR; + } + suiteLen = *c << 8; c++; + suiteLen += *c; c++; + /* Save aside. We're going to come back after extensions are + parsed and choose a cipher suite */ + suiteStart = c; + + if (suiteLen <= 0 || suiteLen & 1) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceIntInfo("Unable to parse cipher suite list: %d\n", + suiteLen); + return MATRIXSSL_ERROR; + } + /* Now is 'suiteLen' bytes of the supported cipher suite list, + listed in order of preference. Loop through and find the + first cipher suite we support. */ + if (end - c < suiteLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Malformed clientHello message\n"); + return MATRIXSSL_ERROR; + } + + /* Do want to make one entire pass of the cipher suites now + to search for SCSV if secure rehandshakes are on */ + suiteEnd = c + suiteLen; + while (c < suiteEnd) { + cipher = *c << 8; c++; + cipher += *c; c++; +#ifdef ENABLE_SECURE_REHANDSHAKES + if (ssl->myVerifyDataLen == 0) { + if (cipher == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) { + ssl->secureRenegotiationFlag = PS_TRUE; + } + } +#endif + /** If TLS_FALLBACK_SCSV appears in ClientHello.cipher_suites and the + highest protocol version supported by the server is higher than + the version indicated in ClientHello.client_version, the server + MUST respond with a fatal inappropriate_fallback alert. + @see https://tools.ietf.org/html/rfc7507#section-3 */ + if (cipher == TLS_FALLBACK_SCSV) { + if (ssl->reqMinVer < serverHighestMinor) { + ssl->err = SSL_ALERT_INAPPROPRIATE_FALLBACK; + psTraceInfo("Inappropriate version fallback\n"); + return MATRIXSSL_ERROR; + } + } + } + + /* Compression parameters */ + if (end - c < 1) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid compression header length\n"); + return MATRIXSSL_ERROR; + } + compLen = *c++; + if ((uint32)(end - c) < compLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid compression header length\n"); + return MATRIXSSL_ERROR; + } +#ifdef USE_ZLIB_COMPRESSION + while (compLen > 0) { + /* Client wants it and we have it. Enable if we're not already + in a compression state. FUTURE: Could be re-handshake */ + if (ssl->compression == 0) { + if (*c++ == 0x01) { + ssl->inflate.zalloc = NULL; + ssl->inflate.zfree = NULL; + ssl->inflate.opaque = NULL; + ssl->inflate.avail_in = 0; + ssl->inflate.next_in = NULL; + if (inflateInit(&ssl->inflate) != Z_OK) { + psTraceInfo("inflateInit fail. No compression\n"); + } else { + ssl->deflate.zalloc = Z_NULL; + ssl->deflate.zfree = Z_NULL; + ssl->deflate.opaque = Z_NULL; + if (deflateInit(&ssl->deflate, + Z_DEFAULT_COMPRESSION) != Z_OK) { + psTraceInfo("deflateInit fail. No compression\n"); + inflateEnd(&ssl->inflate); + } else { + /* Init good. Let's enable it */ + ssl->compression = 1; + } + } + } + compLen--; + } else { + c++; + compLen--; + } + } +#else + c += compLen; +#endif + rc = parseClientHelloExtensions(ssl, &c, end - c); + if (rc < 0) { + /* Alerts are set by the extension parse */ + return rc; + } + } else { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("SSLV2 CLIENT_HELLO not supported.\n"); + return MATRIXSSL_ERROR; + } + + /* ClientHello should be the only one in the record. */ + if (c != end) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Invalid final client hello length\n"); + return MATRIXSSL_ERROR; + } + + /* Look up the session id for ssl session resumption. If found, we + load the pre-negotiated masterSecret and cipher. + A resumed request must meet the following restrictions: + The id must be present in the lookup table + The requested version must match the original version + The cipher suite list must contain the original cipher suite + */ + if (ssl->sessionIdLen > 0) { + /* Check if we are resuming on a session ticket first. It is + legal for a client to send both a session ID and a ticket. If + the ticket is used, the session ID should not be used at all */ +#ifdef USE_STATELESS_SESSION_TICKETS + if ((ssl->flags & SSL_FLAGS_RESUMED) && (ssl->sid) && + (ssl->sid->sessionTicketState == SESS_TICKET_STATE_USING_TICKET)){ + goto SKIP_STANDARD_RESUMPTION; + } +#endif + + if (matrixResumeSession(ssl) >= 0) { + ssl->flags &= ~SSL_FLAGS_CLIENT_AUTH; + ssl->flags |= SSL_FLAGS_RESUMED; +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, RESUMPTIONS_STAT, 1); +#endif + } else { + ssl->flags &= ~SSL_FLAGS_RESUMED; +#ifdef USE_STATELESS_SESSION_TICKETS + /* Client MAY generate and include a Session ID in the + TLS ClientHello. If the server accepts the ticket + and the Session ID is not empty, then it MUST respond + with the same Session ID present in the ClientHello. Check + if client is even using the mechanism though */ + if (ssl->sid) { + if (ssl->sid->sessionTicketState == SESS_TICKET_STATE_INIT) { + memset(ssl->sessionId, 0, SSL_MAX_SESSION_ID_SIZE); + ssl->sessionIdLen = 0; + } else { + /* This flag means we received a session we can't resume + but we have to send it back if we also get a ticket + later that we like */ + ssl->extFlags.session_id = 1; + } + } else { + memset(ssl->sessionId, 0, SSL_MAX_SESSION_ID_SIZE); + ssl->sessionIdLen = 0; + } +#else + memset(ssl->sessionId, 0, SSL_MAX_SESSION_ID_SIZE); + ssl->sessionIdLen = 0; +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, FAILED_RESUMPTIONS_STAT, 1); +#endif +#endif + } + } + +#ifdef USE_STATELESS_SESSION_TICKETS +SKIP_STANDARD_RESUMPTION: +#endif + + /* If resumed, confirm the cipher suite was sent. Otherwise, choose + the cipher suite based on what the user has loaded or what the user + sends in the pubkey callback */ + if (ssl->flags & SSL_FLAGS_RESUMED) { + /* Have to rewalk ciphers and see if they sent the cipher. Can + move suiteStart safely since we'll be the last to use it */ + suiteEnd = suiteStart + suiteLen; + resumptionOnTrack = 0; + while (suiteStart < suiteEnd) { + if (ssl->rec.majVer > SSL2_MAJ_VER) { + cipher = *suiteStart << 8; suiteStart++; + cipher += *suiteStart; suiteStart++; + } else { + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + psTraceInfo("SSLV2 not supported.\n"); + return MATRIXSSL_ERROR; + } + if (cipher == ssl->cipher->ident) { + resumptionOnTrack = 1; + } + } + if (resumptionOnTrack == 0) { + /* Previous cipher suite wasn't sent for resumption. This is an + error according to the specs */ + psTraceIntInfo("Client didn't send cipher %d for resumption\n", + ssl->cipher->ident); + ssl->cipher = sslGetCipherSpec(ssl, SSL_NULL_WITH_NULL_NULL); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + } else { + /* User helps pick the cipher based on the key material. Successful + end result will be assignment of ssl->cipher */ + if (chooseCipherSuite(ssl, suiteStart, suiteLen) < 0) { + psTraceInfo("Server could not support any client cipher suites\n"); + ssl->cipher = sslGetCipherSpec(ssl, SSL_NULL_WITH_NULL_NULL); + if (ssl->err != SSL_ALERT_UNRECOGNIZED_NAME) { + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + } + return MATRIXSSL_ERROR; + } + if (ssl->cipher->ident == 0) { + psTraceInfo("Client attempting SSL_NULL_WITH_NULL_NULL conn\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + } + + + matrixSslSetKexFlags(ssl); + + /* If we're resuming a handshake, then the next handshake message we + expect is the finished message. Otherwise we do the full handshake */ + if (ssl->flags & SSL_FLAGS_RESUMED) { + ssl->hsState = SSL_HS_FINISHED; + } else { +#ifdef USE_DHE_CIPHER_SUITE + /* If we are DH key exchange we need to generate some keys. The + FLAGS_DHE_KEY_EXCH will eventually drive the state matchine to + the ServerKeyExchange path, but ECDH_ suites need the key gen now */ + if (ssl->flags & SSL_FLAGS_DHE_KEY_EXCH) { + +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ECC_CIPHER) { + /* If ecCurveId is zero and we received the extension, then + we really couldn't match and can't continue. */ + if (ssl->ecInfo.ecCurveId == 0 && + (ssl->ecInfo.ecFlags & IS_RECVD_EXT)) { + psTraceInfo("Did not share any EC curves with client\n"); + /* Don't see any particular alert for this case */ + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + /* A ecCurveId of zero (with no extension) will return a + default which is fine according to spec */ + if (getEccParamById(ssl->ecInfo.ecCurveId, &curve) < 0) { + return MATRIXSSL_ERROR; + } + if (psEccNewKey(ssl->hsPool, &ssl->sec.eccKeyPriv, curve) < 0) { + return PS_MEM_FAIL; + } +#ifdef USE_ECC_EPHEMERAL_KEY_CACHE + if ((rc = matrixSslGenEphemeralEcKey(ssl->keys, + ssl->sec.eccKeyPriv, curve, pkiData)) < 0) { +#else + if ((rc = psEccGenKey(ssl->hsPool, ssl->sec.eccKeyPriv, + curve, pkiData)) < 0) { + +#endif + psEccDeleteKey(&ssl->sec.eccKeyPriv); + psTraceInfo("GenEphemeralEcc failed\n"); + ssl->err = SSL_ALERT_INTERNAL_ERROR; + return rc; + } + } else { +#endif /* USE_ECC_CIPHER_SUITE */ +#ifdef REQUIRE_DH_PARAMS + /* Servers using DH suites know DH key sizes when handshake + pool is created so that has been accounted for here */ + if ((ssl->sec.dhKeyPriv = psMalloc(ssl->hsPool, + sizeof(psDhKey_t))) == NULL) { + return MATRIXSSL_ERROR; + } + if ((rc = psDhGenKeyInts(ssl->hsPool, ssl->keys->dhParams.size, + &ssl->keys->dhParams.p, &ssl->keys->dhParams.g, + ssl->sec.dhKeyPriv, pkiData)) < 0) { + psFree(ssl->sec.dhKeyPriv, ssl->hsPool); + ssl->sec.dhKeyPriv = NULL; + psTraceInfo("Error generating DH keys\n"); + ssl->err = SSL_ALERT_INTERNAL_ERROR; + return MATRIXSSL_ERROR; + } +#endif +#ifdef USE_ECC_CIPHER_SUITE + } +#endif /* USE_ECC_CIPHER_SUITE */ + } +#endif /* USE_DHE_CIPHER_SUITE */ + + ssl->hsState = SSL_HS_CLIENT_KEY_EXCHANGE; +#ifdef USE_CLIENT_AUTH + /* Next state in client authentication case is to receive the cert */ + if (ssl->flags & SSL_FLAGS_CLIENT_AUTH) { +#ifdef USE_ANON_DH_CIPHER_SUITE + /* However, what if the server has called for client auth and + the client is requesting an 'anon' cipher suite? + + SECURITY: Options are to default to what the + client wants, what the server wants, or error out. The + current implementation does what the client wants. */ + if (ssl->flags & SSL_FLAGS_ANON_CIPHER) { + psTraceIntInfo( + "Anon cipher %d negotiated. Disabling client auth\n", + ssl->cipher->ident); + ssl->flags &= ~SSL_FLAGS_CLIENT_AUTH; + } else { +#endif /* USE_ANON_DH_CIPHER_SUITE */ + ssl->hsState = SSL_HS_CERTIFICATE; +#ifdef USE_ANON_DH_CIPHER_SUITE + } +#endif /* USE_ANON_DH_CIPHER_SUITE */ + } +#endif /* USE_CLIENT_AUTH */ + } + /* Now that we've parsed the ClientHello, we need to tell the caller that + we have a handshake response to write out. + The caller should call sslWrite upon receiving this return code. */ + *cp = c; + ssl->decState = SSL_HS_CLIENT_HELLO; + return SSL_PROCESS_DATA; +} + +/******************************************************************************/ + +int32 parseClientKeyExchange(ssl_t *ssl, int32 hsLen, unsigned char **cp, + unsigned char *end) +{ + int32 rc, pubKeyLen; + unsigned char *c; +#ifdef USE_RSA_CIPHER_SUITE + unsigned char R[SSL_HS_RSA_PREMASTER_SIZE - 2]; + psPool_t *ckepkiPool = NULL; +#endif +#ifdef USE_PSK_CIPHER_SUITE + uint8_t pskLen; + unsigned char *pskKey = NULL; +#endif + void *pkiData = ssl->userPtr; + + + c = *cp; + + /* RSA: This message contains the premaster secret encrypted with the + server's public key (from the Certificate). The premaster + secret is 48 bytes of random data, but the message may be longer + than that because the 48 bytes are padded before encryption + according to PKCS#1v1.5. After encryption, we should have the + correct length. */ + psTraceHs(">>> Server parsing CLIENT_KEY_EXCHANGE\n"); + if ((int32)(end - c) < hsLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ClientKeyExchange length 1\n"); + return MATRIXSSL_ERROR; + } + + pubKeyLen = hsLen; +#ifdef USE_TLS + /* TLS - Two byte length is explicit. */ + if (ssl->majVer >= TLS_MAJ_VER && ssl->minVer >= TLS_MIN_VER) { + if (end - c < 2) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ClientKeyExchange length 2\n"); + return MATRIXSSL_ERROR; + } +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ECC_CIPHER) { + pubKeyLen = *c; c++; + } else { +#endif /* USE_ECC_CIPHER_SUITE */ + pubKeyLen = *c << 8; c++; + pubKeyLen += *c; c++; +#ifdef USE_ECC_CIPHER_SUITE + } +#endif /* USE_ECC_CIPHER_SUITE */ + if ((int32)(end - c) < pubKeyLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ClientKeyExchange length 3\n"); + return MATRIXSSL_ERROR; + } + } +#endif /* USE_TLS */ + + +#ifdef USE_DHE_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_DHE_KEY_EXCH) { + if (ssl->majVer == SSL3_MAJ_VER && ssl->minVer == SSL3_MIN_VER) { +#ifdef USE_ECC_CIPHER_SUITE + /* Support ECC ciphers in SSLv3. This isn't really a desirable + combination and it's a fuzzy area in the specs but it works */ + if (!(ssl->flags & SSL_FLAGS_ECC_CIPHER)) { +#endif + /* DH cipher suites use the ClientDiffieHellmanPublic format + which always includes the explicit key length regardless + of protocol. If TLS, we already stripped it out above. */ + if (end - c < 2) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ClientKeyExchange length 4\n"); + return MATRIXSSL_ERROR; + } + pubKeyLen = *c << 8; c++; + pubKeyLen += *c; c++; + if ((int32)(end - c) < pubKeyLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ClientKeyExchange length 5\n"); + return MATRIXSSL_ERROR; + } +#ifdef USE_ECC_CIPHER_SUITE + } else { + pubKeyLen = *c; c++; + } +#endif + } +#ifdef USE_PSK_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + /* That initial pubKeyLen we read off the top was actually the + length of the PSK id that we need to find a key for */ + if ((uint32)(end - c) < pubKeyLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ClientKeyExchange PSK length\n"); + return MATRIXSSL_ERROR; + } + + /* If there are PSKs loaded, look at those. Otherwise see if + there is a callback. */ + if (ssl->keys && ssl->keys->pskKeys) { + matrixSslPskGetKey(ssl, c, pubKeyLen, &pskKey, &pskLen); + } else if (ssl->sec.pskCb) { + (ssl->sec.pskCb)(ssl, c, pubKeyLen, &pskKey, &pskLen); + } + if (pskKey == NULL) { + psTraceInfo("Server doesn't not have matching pre-shared key\n"); + ssl->err = SSL_ALERT_UNKNOWN_PSK_IDENTITY; + return MATRIXSSL_ERROR; + } + c += pubKeyLen; + /* This is the DH pub key now */ + pubKeyLen = *c << 8; c++; + pubKeyLen += *c; c++; + if ((uint32)(end - c) < pubKeyLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ClientKeyExchange length\n"); + return MATRIXSSL_ERROR; + } + } +#endif /* USE_PSK_CIPHER_SUITE */ + +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ECC_CIPHER) { + if (psEccNewKey(ssl->hsPool, &ssl->sec.eccKeyPub, + ssl->sec.eccKeyPriv->curve) < 0) { + return SSL_MEM_ERROR; + } + if (psEccX963ImportKey(ssl->hsPool, c, pubKeyLen, + ssl->sec.eccKeyPub, ssl->sec.eccKeyPriv->curve) < 0) { + ssl->err = SSL_ALERT_DECODE_ERROR; + return MATRIXSSL_ERROR; + } + /* BUG FIX after 3.8.1a release. This increment is done later + in the function. So in cases where multiple handshake messages + were put in a single record, we are moving pubKeyLen farther + than we want which could still be in the valid buffer. + The error would be an "unexpected handshake message" when + the next message parse was attempted */ + //c += pubKeyLen; + + ssl->sec.premasterSize = ssl->sec.eccKeyPriv->curve->size; + ssl->sec.premaster = psMalloc(ssl->hsPool, + ssl->sec.premasterSize); + if (ssl->sec.premaster == NULL) { + return SSL_MEM_ERROR; + } + if ((rc = psEccGenSharedSecret(ssl->hsPool, ssl->sec.eccKeyPriv, + ssl->sec.eccKeyPub, ssl->sec.premaster, + &ssl->sec.premasterSize, pkiData)) < 0) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + psFree(ssl->sec.premaster, ssl->hsPool); + ssl->sec.premaster = NULL; + return MATRIXSSL_ERROR; + } + psEccDeleteKey(&ssl->sec.eccKeyPub); + psEccDeleteKey(&ssl->sec.eccKeyPriv); + } else { +#endif /* USE_ECC_CIPHER_SUITE */ +#ifdef REQUIRE_DH_PARAMS + if ((ssl->sec.dhKeyPub = psMalloc(ssl->hsPool, sizeof(psDhKey_t))) == NULL) { + return MATRIXSSL_ERROR; + } + if (psDhImportPubKey(ssl->hsPool, c, pubKeyLen, + ssl->sec.dhKeyPub) < 0) { + psFree(ssl->sec.dhKeyPub, ssl->hsPool); + ssl->sec.dhKeyPub = NULL; + return MATRIXSSL_ERROR; + } +/* + Now know the premaster details. Create it. + + A Diffie-Hellman shared secret has, at maximum, the same number of + bytes as the prime. Use this number as our max buffer size that + will be into psDhGenSecret. +*/ + ssl->sec.premasterSize = ssl->sec.dhPLen; + +#ifdef USE_PSK_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { +/* + Premaster is appended with the PSK. Account for that length + here to avoid a realloc after the standard DH premaster is + created below. +*/ + ssl->sec.premasterSize += pskLen + 4; /* uint16 len heads */ + } +#endif /* USE_PSK_CIPHER_SUITE */ + + ssl->sec.premaster = psMalloc(ssl->hsPool, ssl->sec.premasterSize); + if (ssl->sec.premaster == NULL) { + return SSL_MEM_ERROR; + } + if ((rc = psDhGenSharedSecret(ssl->hsPool, ssl->sec.dhKeyPriv, + ssl->sec.dhKeyPub, ssl->sec.dhP, ssl->sec.dhPLen, + ssl->sec.premaster, + &ssl->sec.premasterSize, pkiData)) < 0) { + return MATRIXSSL_ERROR; + } + psFree(ssl->sec.dhP, ssl->hsPool); + ssl->sec.dhP = NULL; ssl->sec.dhPLen = 0; + psFree(ssl->sec.dhG, ssl->hsPool); + ssl->sec.dhG = NULL; ssl->sec.dhGLen = 0; + psDhClearKey(ssl->sec.dhKeyPub); + psFree(ssl->sec.dhKeyPub, ssl->hsPool); + ssl->sec.dhKeyPub = NULL; + psDhClearKey(ssl->sec.dhKeyPriv); + psFree(ssl->sec.dhKeyPriv, ssl->hsPool); + ssl->sec.dhKeyPriv = NULL; +#ifdef USE_PSK_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { +/* + Need to prepend a uint16 length to the premaster key. +*/ + memmove(&ssl->sec.premaster[2], ssl->sec.premaster, + ssl->sec.premasterSize); + ssl->sec.premaster[0] = (ssl->sec.premasterSize & 0xFF00) >> 8; + ssl->sec.premaster[1] = (ssl->sec.premasterSize & 0xFF); +/* + Next, uint16 length of PSK and key itself +*/ + ssl->sec.premaster[ssl->sec.premasterSize + 2] = + (pskLen & 0xFF00) >> 8; + ssl->sec.premaster[ssl->sec.premasterSize + 3] =(pskLen & 0xFF); + memcpy(&ssl->sec.premaster[ssl->sec.premasterSize + 4], pskKey, + pskLen); +/* + Lastly, adjust the premasterSize +*/ + ssl->sec.premasterSize += pskLen + 4; + } +#endif /* USE_PSK_CIPHER_SUITE */ +#endif /* REQUIRE_DH_PARAMS */ +#ifdef USE_ECC_CIPHER_SUITE + } +#endif /* USE_ECC_CIPHER_SUITE */ + } else { +#endif /* USE_DHE_CIPHER_SUITE */ +#ifdef USE_PSK_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + + if (ssl->majVer == SSL3_MAJ_VER && ssl->minVer == SSL3_MIN_VER){ + /* SSLv3 for basic PSK suites will not have read off + pubKeyLen at this point */ + pubKeyLen = *c << 8; c++; + pubKeyLen += *c; c++; + } + /* If there are PSKs loaded, look at those. Otherwise see if + there is a callback. */ + if (ssl->keys && ssl->keys->pskKeys) { + matrixSslPskGetKey(ssl, c, pubKeyLen, &pskKey, + &pskLen); + } else if (ssl->sec.pskCb) { + if ((ssl->sec.pskCb)(ssl, c, pubKeyLen, &pskKey, &pskLen) + < 0) { + psTraceInfo("User couldn't find pre-shared key\n"); + ssl->err = SSL_ALERT_UNKNOWN_PSK_IDENTITY; + return MATRIXSSL_ERROR; + } + } + if (pskKey == NULL) { + psTraceInfo("Server doesn't have matching pre-shared key\n"); + ssl->err = SSL_ALERT_UNKNOWN_PSK_IDENTITY; + return MATRIXSSL_ERROR; + } + ssl->sec.premasterSize = (pskLen * 2) + 4; + ssl->sec.premaster = psMalloc(ssl->hsPool, + ssl->sec.premasterSize); + if (ssl->sec.premaster == NULL) { + return SSL_MEM_ERROR; + } + memset(ssl->sec.premaster, 0, ssl->sec.premasterSize); + ssl->sec.premaster[0] = (pskLen & 0xFF00) >> 8; + ssl->sec.premaster[1] = (pskLen & 0xFF); + /* memset to 0 handled middle portion */ + ssl->sec.premaster[2 + pskLen] = (pskLen & 0xFF00) >> 8; + ssl->sec.premaster[3 + pskLen] = (pskLen & 0xFF); + memcpy(&ssl->sec.premaster[4 + pskLen], pskKey, pskLen); + } else { +#endif +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->cipher->type == CS_ECDH_ECDSA || + ssl->cipher->type == CS_ECDH_RSA) { + if (ssl->majVer == SSL3_MAJ_VER && + ssl->minVer == SSL3_MIN_VER) { + /* Support ECC ciphers in SSLv3. This isn't really a + desirable combination and it's a fuzzy area in the + specs but it works */ + pubKeyLen = *c; c++; + } + if (ssl->keys == NULL) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + return MATRIXSSL_ERROR; + } + if (psEccNewKey(ssl->hsPool, &ssl->sec.eccKeyPub, + ssl->keys->privKey.key.ecc.curve) < 0) { + return SSL_MEM_ERROR; + } + if (psEccX963ImportKey(ssl->hsPool, c, pubKeyLen, + ssl->sec.eccKeyPub, ssl->keys->privKey.key.ecc.curve) + < 0) { + ssl->err = SSL_ALERT_DECODE_ERROR; + return MATRIXSSL_ERROR; + } + /* BUG FIX after 3.8.1a release. This increment is done + later in the function. So in cases where multiple + handshake messages were put in a single record, we are + moving pubKeyLen farther than we want which could still + be in the valid buffer. The error would be an + "unexpected handshake message" when the next message + parse was attempted */ + //c += pubKeyLen; + + ssl->sec.premasterSize = + ssl->keys->privKey.key.ecc.curve->size; + ssl->sec.premaster = psMalloc(ssl->hsPool, + ssl->sec.premasterSize); + if (ssl->sec.premaster == NULL) { + return SSL_MEM_ERROR; + } + if ((rc = psEccGenSharedSecret(ssl->hsPool, + &ssl->keys->privKey.key.ecc, ssl->sec.eccKeyPub, + ssl->sec.premaster, &ssl->sec.premasterSize, + pkiData)) < 0) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + psFree(ssl->sec.premaster, ssl->hsPool); + ssl->sec.premaster = NULL; + return MATRIXSSL_ERROR; + } + psEccDeleteKey(&ssl->sec.eccKeyPub); + } else { +#endif /* USE_ECC_CIPHER_SUITE */ + +#ifdef USE_RSA_CIPHER_SUITE + if (ssl->keys == NULL) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + return MATRIXSSL_ERROR; + } + /* Standard RSA suite. Now have a handshake pool to allocate + the premaster storage */ + ssl->sec.premasterSize = SSL_HS_RSA_PREMASTER_SIZE; + ssl->sec.premaster = psMalloc(ssl->hsPool, + SSL_HS_RSA_PREMASTER_SIZE); + if (ssl->sec.premaster == NULL) { + return SSL_MEM_ERROR; + } + + /** + @security Caution - the results of an RSA private key + decryption should never have any bearing on timing or response, + otherwise we can be vulnerable to a side channel attack. + @see http://web-in-security.blogspot.co.at/2014/08/old-attacks-on-new-tls-implementations.html + @see https://tools.ietf.org/html/rfc5246#section-7.4.7.1 + "In any case, a TLS server MUST NOT generate an alert if processing an + RSA-encrypted premaster secret message fails, or the version number + is not as expected. Instead, it MUST continue the handshake with a + randomly generated premaster secret. It may be useful to log the + real cause of failure for troubleshooting purposes; however, care + must be taken to avoid leaking the information to an attacker + (through, e.g., timing, log files, or other channels.)" +*/ + rc = psRsaDecryptPriv(ckepkiPool, &ssl->keys->privKey.key.rsa, c, + pubKeyLen, ssl->sec.premaster, ssl->sec.premasterSize, + pkiData); + + /* Step 1 of Bleichenbacher attack mitigation. We do it here + after the RSA op, but regardless of the result of the op. */ + if (matrixCryptoGetPrngData(R, sizeof(R), ssl->userPtr) < 0) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + return MATRIXSSL_ERROR; + } + + /* Step 3 + If the PKCS#1 padding is not correct, or the length of message + M is not exactly 48 bytes: + pre_master_secret = ClientHello.client_version || R + else + pre_master_secret = ClientHello.client_version || M[2..47] + Note that explicitly constructing the pre_master_secret with the + client_version produces an invalid master_secret if the + client has sent the wrong version in the original pre_master_secret. + + Note: The version number in the PreMasterSecret is the version + offered by the client in the ClientHello.client_version, not the + version negotiated for the connection. This feature is designed to + prevent rollback attacks. Unfortunately, some old implementations + use the negotiated version instead, and therefore checking the + version number may lead to failure to interoperate with such + incorrect client implementations. This is known in OpenSSL as the + SSL_OP_TLS_ROLLBACK_BUG. MatrixSSL doesn't support these + incorrect implementations. + */ + ssl->sec.premaster[0] = ssl->reqMajVer; + ssl->sec.premaster[1] = ssl->reqMinVer; + if (rc < 0) { + memcpy(ssl->sec.premaster + 2, R, sizeof(R)); + } else { + /* Not necessary, but keep timing similar */ + memcpy(R, ssl->sec.premaster + 2, sizeof(R)); + } + + /* R may contain sensitive data, eg. premaster */ + memzero_s(R, sizeof(R)); + +#else /* RSA is the 'default' so if that didn't get hit there is a problem */ + psTraceInfo("There is no handler for ClientKeyExchange parse. ERROR\n"); + return MATRIXSSL_ERROR; +#endif /* USE_RSA_CIPHER_SUITE */ +#ifdef USE_ECC_CIPHER_SUITE + } +#endif /* USE_ECC_CIPHER_SUITE */ +#ifdef USE_PSK_CIPHER_SUITE + } +#endif /* USE_PSK_CIPHER_SUITE */ +#ifdef USE_DHE_CIPHER_SUITE + } +#endif /* USE_DHE_CIPHER_SUITE */ + + /* Now that we've got the premaster secret, derive the various + symmetric keys using it and the client and server random values. + Update the cached session (if found) with the masterSecret and + negotiated cipher. */ + if (ssl->extFlags.extended_master_secret == 1) { + if (tlsExtendedDeriveKeys(ssl) < 0) { + return MATRIXSSL_ERROR; + } + } else { + if (sslCreateKeys(ssl) < 0) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + return MATRIXSSL_ERROR; + } + } + matrixUpdateSession(ssl); + + c += pubKeyLen; + ssl->hsState = SSL_HS_FINISHED; + +#ifdef USE_DTLS + /* The freeing of premaster and cert were not done at the normal time + because of the retransmit scenarios. This is server side */ + if (ssl->sec.premaster) { + psFree(ssl->sec.premaster, ssl->hsPool); ssl->sec.premaster = NULL; + ssl->sec.premasterSize = 0; + } +#endif /* USE_DTLS */ + +#ifdef USE_CLIENT_AUTH + /* In the non client auth case, we are done with the handshake pool */ + if (!(ssl->flags & SSL_FLAGS_CLIENT_AUTH)) { +#ifdef USE_DTLS +#ifndef USE_ONLY_PSK_CIPHER_SUITE + if (ssl->sec.cert) { + psFree(ssl->sec.cert, NULL); ssl->sec.cert = NULL; + } +#endif + if (ssl->ckeMsg != NULL) { + psFree(ssl->ckeMsg, ssl->hsPool); ssl->ckeMsg = NULL; + } +#endif /* USE_DTLS */ + ssl->hsPool = NULL; + } +#else /* CLIENT_AUTH */ +#ifdef USE_DTLS + if (ssl->ckeMsg != NULL) { + psFree(ssl->ckeMsg, ssl->hsPool); ssl->ckeMsg = NULL; + } +#endif /* USE_DTLS */ + ssl->hsPool = NULL; +#endif + + +#ifdef USE_CLIENT_AUTH + /* Tweak the state here for client authentication case */ + if (ssl->flags & SSL_FLAGS_CLIENT_AUTH) { + ssl->hsState = SSL_HS_CERTIFICATE_VERIFY; + } +#endif /* USE_CLIENT_AUTH */ + + *cp = c; + ssl->decState = SSL_HS_CLIENT_KEY_EXCHANGE; + return PS_SUCCESS; +} + +/******************************************************************************/ + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#ifdef USE_CLIENT_AUTH +int32 parseCertificateVerify(ssl_t *ssl, + unsigned char hsMsgHash[SHA512_HASH_SIZE], + unsigned char **cp, unsigned char *end) +{ + uint32 certVerifyLen, pubKeyLen; + int32 rc, i; + +#ifdef USE_RSA + unsigned char certVerify[SHA512_HASH_SIZE]; +#endif /* USE_RSA */ + unsigned char *c; + psPool_t *cvpkiPool = NULL; + void *pkiData = ssl->userPtr; + + + c = *cp; + rc = 0; + + psTraceHs(">>> Server parsing CERTIFICATE_VERIFY message\n"); + +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + uint32_t hashSigAlg; + + if ((uint32)(end - c) < 2) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid Certificate Verify message\n"); + return MATRIXSSL_ERROR; + } + hashSigAlg = HASH_SIG_MASK(c[0], c[1]); + + /* The server-sent algorithms has to be one of the ones we sent in + our ClientHello extension */ + if (!(ssl->hashSigAlg & hashSigAlg)) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid SigHash\n"); + return MATRIXSSL_ERROR; + } + + switch (c[0]) { + + case HASH_SIG_SHA256: + certVerifyLen = SHA256_HASH_SIZE; + break; + +#ifdef USE_SHA384 + case HASH_SIG_SHA384: + /* The one-off grab of SHA-384 handshake hash */ + sslSha384RetrieveHSHash(ssl, hsMsgHash); + certVerifyLen = SHA384_HASH_SIZE; + break; +#endif + +#ifdef USE_SHA512 + case HASH_SIG_SHA512: + /* The one-off grab of SHA-512 handshake hash */ + sslSha512RetrieveHSHash(ssl, hsMsgHash); + certVerifyLen = SHA512_HASH_SIZE; + break; +#endif + +#ifdef USE_SHA1 + case HASH_SIG_SHA1: + /* The one-off grab of SHA-1 handshake hash */ + sslSha1RetrieveHSHash(ssl, hsMsgHash); + certVerifyLen = SHA1_HASH_SIZE; + break; +#endif + default: + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid Certificate Verify message\n"); + return MATRIXSSL_ERROR; + } + c += 2; + } else { + certVerifyLen = MD5_HASH_SIZE + SHA1_HASH_SIZE; + } +#else + certVerifyLen = MD5_HASH_SIZE + SHA1_HASH_SIZE; +#endif /* USE_TLS_1_2 */ + + + if ((uint32)(end - c) < 2) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid Certificate Verify message\n"); + return MATRIXSSL_ERROR; + } + pubKeyLen = *c << 8; c++; + pubKeyLen |= *c; c++; + if ((uint32)(end - c) < pubKeyLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid Certificate Verify message\n"); + return MATRIXSSL_ERROR; + } + /* The server side verification of client identity. If we can match + the signature we know the client has possesion of the private key. */ +#ifdef USE_ECC + /* Need to read sig algorithm type out of cert itself */ + if (ssl->sec.cert->pubKeyAlgorithm == OID_ECDSA_KEY_ALG) { + rc = 0; + +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + if ((i = psEccDsaVerify(cvpkiPool, + &ssl->sec.cert->publicKey.key.ecc, + hsMsgHash, certVerifyLen, + c, pubKeyLen, &rc, pkiData)) != 0) { + psTraceInfo("ECDSA signature validation failed\n"); + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + return MATRIXSSL_ERROR; + } + } else { + certVerifyLen = SHA1_HASH_SIZE; /* per spec */ + if ((i = psEccDsaVerify(cvpkiPool, + &ssl->sec.cert->publicKey.key.ecc, + hsMsgHash + MD5_HASH_SIZE, certVerifyLen, + c, pubKeyLen, + &rc, pkiData)) != 0) { + psTraceInfo("ECDSA signature validation failed\n"); + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + return MATRIXSSL_ERROR; + } + } +#else + certVerifyLen = SHA1_HASH_SIZE; /* per spec */ + if ((i = psEccDsaVerify(cvpkiPool, + &ssl->sec.cert->publicKey.key.ecc, + hsMsgHash + MD5_HASH_SIZE, certVerifyLen, + c, pubKeyLen, + &rc, pkiData)) != 0) { + psTraceInfo("ECDSA signature validation failed\n"); + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + return MATRIXSSL_ERROR; + } +#endif + if (rc != 1) { + psTraceInfo("Can't verify certVerify sig\n"); + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + return MATRIXSSL_ERROR; + } + rc = MATRIXSSL_SUCCESS; /* done using rc as a temp */ + } else { +#endif /* USE_ECC */ +#ifdef USE_RSA + + + +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + if ((i = pubRsaDecryptSignedElement(cvpkiPool, + &ssl->sec.cert->publicKey.key.rsa, c, pubKeyLen, certVerify, + certVerifyLen, pkiData)) < 0) { + psTraceInfo("Unable to decrypt CertVerify digital element\n"); + return MATRIXSSL_ERROR; + } + } else { + if ((i = psRsaDecryptPub(cvpkiPool, &ssl->sec.cert->publicKey.key.rsa, c, + pubKeyLen, certVerify, certVerifyLen, pkiData)) < 0) { + psTraceInfo("Unable to publicly decrypt Certificate Verify message\n"); + return MATRIXSSL_ERROR; + } + } +#else /* !USE_TLS_1_2 */ + if ((i = psRsaDecryptPub(cvpkiPool, &ssl->sec.cert->publicKey.key.rsa, c, + pubKeyLen, certVerify, certVerifyLen, pkiData)) < 0) { + psTraceInfo("Unable to publicly decrypt Certificate Verify message\n"); + return MATRIXSSL_ERROR; + } +#endif /* USE_TLS_1_2 */ + + if (memcmpct(certVerify, hsMsgHash, certVerifyLen) != 0) { + psTraceInfo("Unable to verify client certificate signature\n"); + return MATRIXSSL_ERROR; + } +#else /* RSA is 'default' so if that didn't get hit there is a problem */ + psTraceInfo("There is no handler for CertificateVerify parse. ERROR\n"); + return MATRIXSSL_ERROR; +#endif /* USE_RSA */ +#ifdef USE_ECC + } +#endif /* USE_ECC*/ + + c += pubKeyLen; + ssl->hsState = SSL_HS_FINISHED; + + *cp = c; + ssl->decState = SSL_HS_CERTIFICATE_VERIFY; + return PS_SUCCESS; +} +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ +#endif /* USE_SERVER_SIDE_SSL */ + +/******************************************************************************/ + +#ifdef USE_CLIENT_SIDE_SSL +int32 parseServerHello(ssl_t *ssl, int32 hsLen, unsigned char **cp, + unsigned char *end) +{ + uint32 sessionIdLen, cipher = 0; + int32 rc; + unsigned char *extData; + unsigned char *c; + + c = *cp; + + psTraceHs(">>> Client parsing SERVER_HELLO message\n"); +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, SH_RECV_STAT, 1); +#endif + /* Need to track hsLen because there is no explict way to tell if + hello extensions are appended so it isn't clear if the record data + after the compression parameters are a new message or extension data */ + extData = c; + +#ifdef USE_DTLS + /* Know now that the allocated members that were helping with the + HELLO_VERIFY_REQUEST exchange have finished serving their purpose */ + if (ssl->cookie) { + psFree(ssl->cookie, ssl->hsPool); ssl->cookie = NULL; + ssl->cookieLen = 0; ssl->haveCookie = 0; + } + if (ssl->helloExt) { + psFree(ssl->helloExt, ssl->hsPool); ssl->helloExt = NULL; + ssl->helloExtLen = 0; + } +#endif /* USE_DTLS */ + + /* First two bytes are the negotiated SSL version */ + if (end - c < 2) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ssl header version length\n"); + return MATRIXSSL_ERROR; + } + ssl->reqMajVer = *c; c++; + ssl->reqMinVer = *c; c++; + if (ssl->reqMajVer != ssl->majVer) { + ssl->err = SSL_ALERT_PROTOCOL_VERSION; + psTraceIntInfo("Unsupported ssl version: %d\n", ssl->reqMajVer); + return MATRIXSSL_ERROR; + } + +#ifdef USE_TLS + /* See if the protocol is being downgraded */ + if (ssl->reqMinVer != ssl->minVer) { + if (ssl->reqMinVer == SSL3_MIN_VER && ssl->minVer >= TLS_MIN_VER) { +#ifdef DISABLE_SSLV3 + ssl->err = SSL_ALERT_PROTOCOL_VERSION; + psTraceInfo("Server wants to talk SSLv3 but it's disabled\n"); + return MATRIXSSL_ERROR; +#else + /* Server minVer now becomes OUR initial requested version. + This is used during the creation of the premaster where + this initial requested version is part of the calculation. + The RFC actually says to use the original requested version + but no implemenations seem to follow that and just use the + agreed upon one. */ + ssl->reqMinVer = ssl->minVer; + ssl->minVer = SSL3_MIN_VER; + ssl->flags &= ~SSL_FLAGS_TLS; +#ifdef USE_TLS_1_1 + ssl->flags &= ~SSL_FLAGS_TLS_1_1; +#endif /* USE_TLS_1_1 */ +#ifdef USE_TLS_1_2 + ssl->flags &= ~SSL_FLAGS_TLS_1_2; +#endif /* USE_TLS_1_2 */ +#endif /* DISABLE_SSLV3 */ + } else { +#ifdef USE_TLS_1_1 +#ifdef USE_TLS_1_2 + /* Step down one at a time */ + if (ssl->reqMinVer < TLS_1_2_MIN_VER && + (ssl->flags & SSL_FLAGS_TLS_1_2)) { + ssl->flags &= ~SSL_FLAGS_TLS_1_2; + if (ssl->reqMinVer == TLS_1_1_MIN_VER) { +#ifdef DISABLE_TLS_1_1 + ssl->err = SSL_ALERT_PROTOCOL_VERSION; + psTraceInfo("Server wants to talk TLS1.1 but it's disabled\n"); + return MATRIXSSL_ERROR; +#endif + ssl->reqMinVer = ssl->minVer; + ssl->minVer = TLS_1_1_MIN_VER; + goto PROTOCOL_DETERMINED; + } + } +#endif /* USE_TLS_1_2 */ + if (ssl->reqMinVer == TLS_MIN_VER && + ssl->minVer <= TLS_1_2_MIN_VER) { +#ifdef DISABLE_TLS_1_0 + ssl->err = SSL_ALERT_PROTOCOL_VERSION; + psTraceInfo("Server wants to talk TLS1.0 but it's disabled\n"); + return MATRIXSSL_ERROR; +#endif + ssl->reqMinVer = ssl->minVer; + ssl->minVer = TLS_MIN_VER; + ssl->flags &= ~SSL_FLAGS_TLS_1_1; + } else { +#endif/* USE_TLS_1_1 */ +#ifdef USE_DTLS + /* Tests for DTLS downgrades */ + if (ssl->flags & SSL_FLAGS_DTLS) { + if (ssl->reqMinVer == DTLS_MIN_VER && + ssl->minVer == DTLS_1_2_MIN_VER) { + ssl->reqMinVer = ssl->minVer; + ssl->minVer = DTLS_MIN_VER; + ssl->flags &= ~SSL_FLAGS_TLS_1_2; + goto PROTOCOL_DETERMINED; + } + } +#endif + /* Wasn't able to settle on a common protocol */ + ssl->err = SSL_ALERT_PROTOCOL_VERSION; + psTraceIntInfo("Unsupported ssl version: %d\n", + ssl->reqMajVer); + return MATRIXSSL_ERROR; +#ifdef USE_TLS_1_1 + } +#endif /* USE_TLS_1_1 */ + } + } +#endif /* USE_TLS */ + +#if defined (USE_TLS_1_2) || defined (USE_DTLS) +PROTOCOL_DETERMINED: +#endif /* USE_TLS_1_2 || USE_DTLS */ + + /* Next is a 32 bytes of random data for key generation + and a single byte with the session ID length */ + if (end - c < SSL_HS_RANDOM_SIZE + 1) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid length of random data\n"); + return MATRIXSSL_ERROR; + } + memcpy(ssl->sec.serverRandom, c, SSL_HS_RANDOM_SIZE); + c += SSL_HS_RANDOM_SIZE; + sessionIdLen = *c; c++; + if (sessionIdLen > SSL_MAX_SESSION_ID_SIZE || + (uint32)(end - c) < sessionIdLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + return MATRIXSSL_ERROR; + } + /* If a session length was specified, the server has sent us a + session Id. We may have requested a specific session, and the + server may or may not agree to use that session. */ + if (sessionIdLen > 0) { + if (ssl->sessionIdLen > 0) { + if (memcmp(ssl->sessionId, c, sessionIdLen) == 0) { + ssl->flags |= SSL_FLAGS_RESUMED; + } else { + ssl->cipher = sslGetCipherSpec(ssl,SSL_NULL_WITH_NULL_NULL); + memset(ssl->sec.masterSecret, 0x0, SSL_HS_MASTER_SIZE); + ssl->sessionIdLen = (unsigned char)sessionIdLen; + memcpy(ssl->sessionId, c, sessionIdLen); + ssl->flags &= ~SSL_FLAGS_RESUMED; +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, FAILED_RESUMPTIONS_STAT, 1); +#endif + } + } else { + ssl->sessionIdLen = (unsigned char)sessionIdLen; + memcpy(ssl->sessionId, c, sessionIdLen); + } + c += sessionIdLen; + } else { + if (ssl->sessionIdLen > 0) { + ssl->cipher = sslGetCipherSpec(ssl, SSL_NULL_WITH_NULL_NULL); + memset(ssl->sec.masterSecret, 0x0, SSL_HS_MASTER_SIZE); + ssl->sessionIdLen = 0; + memset(ssl->sessionId, 0x0, SSL_MAX_SESSION_ID_SIZE); + ssl->flags &= ~SSL_FLAGS_RESUMED; +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, FAILED_RESUMPTIONS_STAT, 1); +#endif + } + } + /* Next is the two byte cipher suite */ + if (end - c < 2) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid cipher suite length\n"); + return MATRIXSSL_ERROR; + } + cipher = *c << 8; c++; + cipher += *c; c++; + + /* A resumed session can only match the cipher originally + negotiated. Otherwise, match the first cipher that we support */ + if (ssl->flags & SSL_FLAGS_RESUMED) { + psAssert(ssl->cipher != NULL); + if (ssl->cipher->ident != cipher) { + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + psTraceInfo("Can't support resumed cipher\n"); + return MATRIXSSL_ERROR; + } + } else { + if ((ssl->cipher = sslGetCipherSpec(ssl, cipher)) == NULL) { + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + psTraceIntInfo("Can't support requested cipher: %d\n", cipher); + return MATRIXSSL_ERROR; + } + } + matrixSslSetKexFlags(ssl); + + /* Decode the compression parameter byte. */ +#define COMPRESSION_METHOD_NULL 0x0 +#define COMPRESSION_METHOD_DEFLATE 0x1 + if (end - c < 1) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Expected compression value\n"); + return MATRIXSSL_ERROR; + } + switch (*c) { + case COMPRESSION_METHOD_NULL: + /* No compression */ + break; +#ifdef USE_ZLIB_COMPRESSION + case COMPRESSION_METHOD_DEFLATE: + ssl->inflate.zalloc = NULL; + ssl->inflate.zfree = NULL; + ssl->inflate.opaque = NULL; + ssl->inflate.avail_in = 0; + ssl->inflate.next_in = NULL; + if (inflateInit(&ssl->inflate) != Z_OK) { + psTraceInfo("inflateInit fail. No compression\n"); + } else { + ssl->deflate.zalloc = Z_NULL; + ssl->deflate.zfree = Z_NULL; + ssl->deflate.opaque = Z_NULL; + if (deflateInit(&ssl->deflate, Z_DEFAULT_COMPRESSION) != Z_OK) { + psTraceInfo("deflateInit fail. No compression\n"); + inflateEnd(&ssl->inflate); + } else { + ssl->compression = 1; /* Both contexts initialized */ + } + } + break; +#endif /* USE_ZLIB_COMPRESSION */ + default: + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("zlib compression not enabled.\n"); + return MATRIXSSL_ERROR; + } + /* At this point, if we're resumed, we have all the required info + to derive keys. The next handshake message we expect is + the Finished message. + After incrementing c below, we will either be pointing at 'end' + with no more data in the message, or at the first byte of an optional + extension. */ + c++; + + /* If our sent ClientHello had an extension there could be extension data + to parse here: http://www.faqs.org/rfcs/rfc3546.html + + The explict test on hsLen is necessary for TLS 1.0 and 1.1 because + there is no good way to tell if the remaining record data is the + next handshake message or if it is extension data */ + if (c != end && ((int32)hsLen > (c - extData))) { + rc = parseServerHelloExtensions(ssl, hsLen, extData, &c, c - end); + if (rc < 0) { + /* Alerts will already have been set inside */ + return rc; + } + } + +#ifdef USE_OCSP_MUST_STAPLE + /* Will catch cases where a server does not send any extensions at all */ + if (ssl->extFlags.req_status_request == 1) { + if (ssl->extFlags.status_request == 0) { + psTraceInfo("Server doesn't support OCSP stapling\n"); + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + return MATRIXSSL_ERROR; + } + } +#endif + + if (ssl->maxPtFrag & 0x10000 || ssl->extFlags.req_max_fragment_len) { + /* Server didn't respond to our MAX_FRAG request. Reset default */ + psTraceInfo("Server ignored max fragment length ext request\n"); + ssl->maxPtFrag = SSL_MAX_PLAINTEXT_LEN; + } + + if (ssl->extFlags.req_sni) { + psTraceInfo("Server ignored SNI ext request\n"); + } + +#ifdef USE_STATELESS_SESSION_TICKETS + if (ssl->sid && + ssl->sid->sessionTicketState == SESS_TICKET_STATE_SENT_TICKET) { + /* + Server did not send an extension reply to our populated ticket. + + From the updated RFC 5077: + + "It is also permissible to have an exchange using the + abbreviated handshake defined in Figure 2 of RFC 4346, where + the client uses the SessionTicket extension to resume the + session, but the server does not wish to issue a new ticket, + and therefore does not send a SessionTicket extension." + + Lame. We don't get an indication that the server accepted or + rejected our ticket until we see the next handshake message. + If they accepted it we'll see a ChangeCipherSpec message and + if they rejected it we'll see a Certificate message. Let's + flag this case of a non-response and handle it in the CCS parse. + + TODO - could also send a sessionId and see if it is returned here. + Spec requires the same sessionId to be returned if ticket is accepted. + */ + ssl->sid->sessionTicketState = SESS_TICKET_STATE_IN_LIMBO; + } +#endif /* USE_STATELESS_SESSION_TICKETS */ + + +#if 0 //TODO moved to extDecode:parseServerHelloExtensions +#ifdef ENABLE_SECURE_REHANDSHAKES + if (renegotiationExt == 0) { +#ifdef REQUIRE_SECURE_REHANDSHAKES + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + psTraceInfo("Srv doesn't support renegotiationInfo\n"); + return MATRIXSSL_ERROR; +#else + if (ssl->secureRenegotiationFlag == PS_TRUE) { + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + psTraceInfo("Srv didn't send renegotiationInfo on re-hndshk\n"); + return MATRIXSSL_ERROR; + } +#ifndef ENABLE_INSECURE_REHANDSHAKES + /* This case can only be hit if ENABLE_SECURE is on because otherwise + we wouldn't even have got this far because both would be off. */ + if (ssl->secureRenegotiationFlag == PS_FALSE && + ssl->myVerifyDataLen > 0) { + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + psTraceInfo("Srv attempting insecure renegotiation\n"); + return MATRIXSSL_ERROR; + } +#endif /* !ENABLE_SECURE_REHANDSHAKES */ +#endif /* REQUIRE_SECURE_REHANDSHAKES */ + } +#endif /* ENABLE_SECURE_REHANDSHAKES */ +#endif + + if (ssl->flags & SSL_FLAGS_RESUMED) { + if (sslCreateKeys(ssl) < 0) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + return MATRIXSSL_ERROR; + } + ssl->hsState = SSL_HS_FINISHED; + } else { + ssl->hsState = SSL_HS_CERTIFICATE; +#ifdef USE_ANON_DH_CIPHER_SUITE + /* Anonymous DH uses SERVER_KEY_EXCHANGE message to send key params */ + if (ssl->flags & SSL_FLAGS_ANON_CIPHER) { + ssl->hsState = SSL_HS_SERVER_KEY_EXCHANGE; + } +#endif /* USE_ANON_DH_CIPHER_SUITE */ +#ifdef USE_PSK_CIPHER_SUITE + /* PSK ciphers never send a CERTIFICATE message. */ + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + ssl->hsState = SSL_HS_SERVER_KEY_EXCHANGE; + } +#endif /* USE_PSK_CIPHER_SUITE */ + } + + *cp = c; + ssl->decState = SSL_HS_SERVER_HELLO; + return PS_SUCCESS; +} + +/******************************************************************************/ + +int32 parseServerKeyExchange(ssl_t *ssl, + unsigned char hsMsgHash[SHA384_HASH_SIZE], + unsigned char **cp, unsigned char *end) +{ + unsigned char *c; +#ifdef USE_DHE_CIPHER_SUITE + int32 i; + uint32 pubDhLen, hashSize; + psPool_t *skepkiPool = NULL; +#ifndef USE_ONLY_PSK_CIPHER_SUITE + psDigestContext_t digestCtx; + unsigned char *sigStart = NULL, *sigStop = NULL; +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ +#ifdef USE_TLS_1_2 + uint32 skeHashSigAlg; +#endif +#ifdef USE_RSA_CIPHER_SUITE + unsigned char sigOut[SHA384_HASH_SIZE]; +#endif +#ifdef USE_ECC_CIPHER_SUITE + uint32 res; + const psEccCurve_t *curve; +#endif + void *pkiData = ssl->userPtr; + +#endif /* USE_DHE_CIPHER_SUITE */ + + c = *cp; + + psTraceHs(">>> Client parsing SERVER_KEY_EXCHANGE message\n"); +#ifdef USE_DHE_CIPHER_SUITE + /* Check the DH status. Could also be a PSK_DHE suite */ + if (ssl->flags & SSL_FLAGS_DHE_KEY_EXCH) { + + +#ifdef USE_PSK_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + /* Using the value of MAX_HINT_SIZE to know if the user is + expecting a hint. The PSK specification ONLY allows these + hints if the "application profile specification" says to + include them. + + Contact Support if you require assistance here */ + if (SSL_PSK_MAX_HINT_SIZE > 0) { + if ((end - c) < 2) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid PSK Hint Len\n"); + return MATRIXSSL_ERROR; + } + ssl->sec.hintLen = *c << 8; c++; + ssl->sec.hintLen |= *c; c++; + if (ssl->sec.hintLen > 0) { + if ((unsigned short)(end - c) < ssl->sec.hintLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid PSK Hint\n"); + return MATRIXSSL_ERROR; + } + ssl->sec.hint = psMalloc(ssl->hsPool, ssl->sec.hintLen); + if (ssl->sec.hint == NULL) { + return SSL_MEM_ERROR; + } + memcpy(ssl->sec.hint, c, ssl->sec.hintLen); + c += ssl->sec.hintLen; + } + } + } +#endif /* USE_PSK_CIPHER_SUITE */ +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ECC_CIPHER) { + /* Entry point for ECDHE SKE parsing */ + sigStart = c; + if ((end - c) < 4) { /* ECCurveType, NamedCurve, ECPoint len */ + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ServerKeyExchange message\n"); + return MATRIXSSL_ERROR; + } +/* + Only named curves are currently supported + + enum { explicit_prime (1), explicit_char2 (2), + named_curve (3), reserved(248..255) } ECCurveType; +*/ + if ((int32)*c != 3) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceIntInfo("Unsupported ECCurveType message %d\n", + (int32)*c); + return MATRIXSSL_ERROR; + } + c++; + + /* Next is curveId */ + i = *c << 8; c++; + i |= *c; c++; + + /* Return -1 if this isn't a curve we specified in client hello */ + if (getEccParamById(i, &curve) < 0) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceIntInfo("Error: Could not match EC curve: %d\n", i); + return MATRIXSSL_ERROR; + } +/* + struct { + opaque point <1..2^8-1>; + } ECPoint; + + RFC4492 + This is the byte string representation of an elliptic curve + point following the conversion routine in Section 4.3.6 of ANSI + X9.62. This byte string may represent an elliptic curve point + in uncompressed or compressed format; it MUST conform to what + client has requested through a Supported Point Formats Extension + if this extension was used. +*/ + i = *c; c++; + if ((end - c) < i) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ServerKeyExchange message\n"); + return MATRIXSSL_ERROR; + } + if (psEccNewKey(ssl->hsPool, &ssl->sec.eccKeyPub, curve) < 0) { + return SSL_MEM_ERROR; + } + if (psEccX963ImportKey(ssl->hsPool, c, i, + ssl->sec.eccKeyPub, curve) < 0) { + ssl->err = SSL_ALERT_DECODE_ERROR; + return MATRIXSSL_ERROR; + } + c += i; + sigStop = c; + + } else { +#endif /* USE_ECC_CIPHER_SUITE */ +#ifdef REQUIRE_DH_PARAMS + /* Entry point for standard DH SKE parsing */ + if ((end - c) < 2) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ServerKeyExchange message\n"); + return MATRIXSSL_ERROR; + } +#ifndef USE_ONLY_PSK_CIPHER_SUITE + sigStart = c; +#endif + ssl->sec.dhPLen = *c << 8; c++; + ssl->sec.dhPLen |= *c; c++; + if ((uint32)(end - c) < ssl->sec.dhPLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ServerKeyExchange message\n"); + return MATRIXSSL_ERROR; + } + ssl->sec.dhP = psMalloc(ssl->hsPool, ssl->sec.dhPLen); + if (ssl->sec.dhP == NULL) { + return SSL_MEM_ERROR; + } + memcpy(ssl->sec.dhP, c, ssl->sec.dhPLen); + c += ssl->sec.dhPLen; + + ssl->sec.dhGLen = *c << 8; c++; + ssl->sec.dhGLen |= *c; c++; + if ((uint32)(end - c) < ssl->sec.dhGLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ServerKeyExchange message\n"); + return MATRIXSSL_ERROR; + } + ssl->sec.dhG = psMalloc(ssl->hsPool, ssl->sec.dhGLen); + if (ssl->sec.dhG == NULL) { + return SSL_MEM_ERROR; + } + memcpy(ssl->sec.dhG, c, ssl->sec.dhGLen); + c += ssl->sec.dhGLen; + + pubDhLen = *c << 8; c++; + pubDhLen |= *c; c++; + + if ((uint32)(end - c) < pubDhLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ServerKeyExchange message\n"); + return MATRIXSSL_ERROR; + } +/* + The next bit on the wire is the public key. Assign to + the session in structure format +*/ + if ((ssl->sec.dhKeyPub = psMalloc(ssl->hsPool, sizeof(psDhKey_t))) == NULL) { + return MATRIXSSL_ERROR; + } + if (psDhImportPubKey(ssl->hsPool, c, pubDhLen, + ssl->sec.dhKeyPub) < 0) { + psFree(ssl->sec.dhKeyPub, ssl->hsPool); + ssl->sec.dhKeyPub = NULL; + return MATRIXSSL_ERROR; + } + c += pubDhLen; +#ifndef USE_ONLY_PSK_CIPHER_SUITE + sigStop = c; +#endif +/* + Key size is now known for premaster storage. The extra byte + is to account for the cases where the pubkey length ends + up being a byte less than the premaster. The premaster size + is adjusted accordingly when the actual secret is generated. +*/ + ssl->sec.premasterSize = ssl->sec.dhPLen; +#ifdef USE_PSK_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { +/* + In the PSK case, the true premaster size is still unknown + but didn't want to change the allocation logic so just + make sure the size is large enough for the additional + PSK and length bytes +*/ + ssl->sec.premasterSize += SSL_PSK_MAX_KEY_SIZE + 4; + } +#endif /* USE_PSK_CIPHER_SUITE */ + ssl->sec.premaster = psMalloc(ssl->hsPool, ssl->sec.premasterSize); + if (ssl->sec.premaster == NULL) { + return SSL_MEM_ERROR; + } +#ifdef USE_ANON_DH_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ANON_CIPHER) { +/* + In the anonymous case, there is no signature to follow +*/ + ssl->hsState = SSL_HS_SERVER_HELLO_DONE; + *cp = c; + ssl->decState = SSL_HS_SERVER_KEY_EXCHANGE; + return PS_SUCCESS; + } +#endif /* USE_ANON_DH_CIPHER_SUITE */ +#endif /* REQUIRE_DH_PARAMS */ +#ifdef USE_ECC_CIPHER_SUITE + } +#endif /* USE_ECC_CIPHER_SUITE */ +/* + This layer of authentation is at the key exchange level. + The server has sent a signature of the key material that + the client can validate here. +*/ + if ((end - c) < 2) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ServerKeyExchange message\n"); + return MATRIXSSL_ERROR; + } + +#ifdef USE_TLS_1_2 + hashSize = 0; + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + skeHashSigAlg = *c << 8; c++; + skeHashSigAlg += *c; c++; + if ((skeHashSigAlg >> 8) == 0x4) { + hashSize = SHA256_HASH_SIZE; + } else if ((skeHashSigAlg >> 8) == 0x5) { + hashSize = SHA384_HASH_SIZE; + } else if ((skeHashSigAlg >> 8) == 0x6) { + hashSize = SHA512_HASH_SIZE; + } else if ((skeHashSigAlg >> 8) == 0x2) { + hashSize = SHA1_HASH_SIZE; + } else { + psTraceIntInfo("Unsupported hashAlg SKE parse: %d\n", + skeHashSigAlg); + return MATRIXSSL_ERROR; + } + } +#endif /* USE_TLS_1_2 */ + pubDhLen = *c << 8; c++; /* Reusing variable */ + pubDhLen |= *c; c++; + + if ((uint32)(end - c) < pubDhLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ServerKeyExchange message\n"); + return MATRIXSSL_ERROR; + } + +#ifdef USE_RSA_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_DHE_WITH_RSA) { +/* + We are using the public key provided by the server during the + CERTIFICATE message. That cert has already been authenticated + by this point so this signature is to ensure that entity is also + the one negotiating keys with us. +*/ +#ifdef USE_TLS_1_2 + /* TLS 1.2 uses single hashes everywhere */ + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + if (hashSize == SHA256_HASH_SIZE) { + psSha256Init(&digestCtx.sha256); + psSha256Update(&digestCtx.sha256, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha256Update(&digestCtx.sha256, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha256Update(&digestCtx.sha256, sigStart, + (uint32)(sigStop - sigStart)); + psSha256Final(&digestCtx.sha256, hsMsgHash); +#ifdef USE_SHA384 + } else if (hashSize == SHA384_HASH_SIZE) { + psSha384Init(&digestCtx.sha384); + psSha384Update(&digestCtx.sha384, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha384Update(&digestCtx.sha384, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha384Update(&digestCtx.sha384, sigStart, + (uint32)(sigStop - sigStart)); + psSha384Final(&digestCtx.sha384, hsMsgHash); +#endif /* USE_SHA384 */ +#ifdef USE_SHA512 + } else if (hashSize == SHA512_HASH_SIZE) { + psSha512Init(&digestCtx.sha512); + psSha512Update(&digestCtx.sha512, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha512Update(&digestCtx.sha512, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha512Update(&digestCtx.sha512, sigStart, + (uint32)(sigStop - sigStart)); + psSha512Final(&digestCtx.sha512, hsMsgHash); +#endif /* USE_SHA512 */ +#ifdef USE_SHA1 + } else if (hashSize == SHA1_HASH_SIZE) { + psSha1Init(&digestCtx.sha1); + psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, sigStart, + (uint32)(sigStop - sigStart)); + psSha1Final(&digestCtx.sha1, hsMsgHash); +#endif + } else { + return MATRIXSSL_ERROR; + } + + } else { +#ifdef USE_MD5 + psMd5Init(&digestCtx.md5); + psMd5Update(&digestCtx.md5, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psMd5Update(&digestCtx.md5, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psMd5Update(&digestCtx.md5, sigStart, + (uint32)(sigStop - sigStart)); + psMd5Final(&digestCtx.md5, hsMsgHash); + + psSha1Init(&digestCtx.sha1); + psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, sigStart, + (uint32)(sigStop - sigStart)); + psSha1Final(&digestCtx.sha1, hsMsgHash + MD5_HASH_SIZE); +#else + return MATRIXSSL_ERROR; +#endif + } +#else /* USE_TLS_1_2 */ +/* + The signature portion is an MD5 and SHA1 concat of the randoms + and the contents of this server key exchange message. +*/ + psMd5Init(&digestCtx.md5); + psMd5Update(&digestCtx.md5, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psMd5Update(&digestCtx.md5, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psMd5Update(&digestCtx.md5, sigStart, + (uint32)(sigStop - sigStart)); + psMd5Final(&digestCtx.md5, hsMsgHash); + + psSha1Init(&digestCtx.sha1); + psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, sigStart, + (uint32)(sigStop - sigStart)); + psSha1Final(&digestCtx.sha1, hsMsgHash + MD5_HASH_SIZE); +#endif /* USE_TLS_1_2 */ + + + + + + +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + /* TLS 1.2 doesn't just sign the straight hash so we can't + pass it through the normal public decryption becuase + that expects an output length of a known size. These + signatures are done on elements with some ASN.1 + wrapping so a special decryption with parse is needed */ + if ((i = pubRsaDecryptSignedElement(skepkiPool, + &ssl->sec.cert->publicKey.key.rsa, c, pubDhLen, sigOut, + hashSize, pkiData)) < 0) { + + psTraceInfo("Can't decrypt serverKeyExchange sig\n"); + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + return MATRIXSSL_ERROR; + } + + } else { + hashSize = MD5_HASH_SIZE + SHA1_HASH_SIZE; + + if ((i = psRsaDecryptPub(skepkiPool, + &ssl->sec.cert->publicKey.key.rsa, c, pubDhLen, sigOut, + hashSize, pkiData)) < 0) { + psTraceInfo("Can't decrypt server key exchange sig\n"); + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + return MATRIXSSL_ERROR; + } + } +#else /* ! USE_TLS_1_2 */ + hashSize = MD5_HASH_SIZE + SHA1_HASH_SIZE; + if ((i = psRsaDecryptPub(skepkiPool, &ssl->sec.cert->publicKey.key.rsa, + c, pubDhLen, sigOut, hashSize, pkiData)) < 0) { + psTraceInfo("Unable to decrypt server key exchange sig\n"); + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + return MATRIXSSL_ERROR; + } +#endif /* USE_TLS_1_2 */ + + /* Now have hash from the server. Create ours and check match */ + c += pubDhLen; + + if (memcmpct(sigOut, hsMsgHash, hashSize) != 0) { + psTraceInfo("Fail to verify serverKeyExchange sig\n"); + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + return MATRIXSSL_ERROR; + } + } +#endif /* USE_RSA_CIPHER_SUITE */ +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_DHE_WITH_DSA) { +/* + RFC4492: The default hash function is SHA-1, and sha_size is 20. +*/ +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2 && + (hashSize == SHA256_HASH_SIZE)) { + psSha256Init(&digestCtx.sha256); + psSha256Update(&digestCtx.sha256, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha256Update(&digestCtx.sha256, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha256Update(&digestCtx.sha256, sigStart, + (int32)(sigStop - sigStart)); + psSha256Final(&digestCtx.sha256, hsMsgHash); +#ifdef USE_SHA384 + } else if (ssl->flags & SSL_FLAGS_TLS_1_2 && + (hashSize == SHA384_HASH_SIZE)) { + psSha384Init(&digestCtx.sha384); + psSha384Update(&digestCtx.sha384, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha384Update(&digestCtx.sha384, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha384Update(&digestCtx.sha384, sigStart, + (int32)(sigStop - sigStart)); + psSha384Final(&digestCtx.sha384, hsMsgHash); +#endif +#ifdef USE_SHA512 + } else if (hashSize == SHA512_HASH_SIZE) { + psSha512Init(&digestCtx.sha512); + psSha512Update(&digestCtx.sha512, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha512Update(&digestCtx.sha512, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha512Update(&digestCtx.sha512, sigStart, + (uint32)(sigStop - sigStart)); + psSha512Final(&digestCtx.sha512, hsMsgHash); +#endif /* USE_SHA512 */ +#ifdef USE_SHA1 + } else if (ssl->minVer < TLS_1_2_MIN_VER || +#ifdef USE_DTLS + ssl->minVer == DTLS_MIN_VER || +#endif + ((ssl->flags & SSL_FLAGS_TLS_1_2) && + (hashSize == SHA1_HASH_SIZE))) { + hashSize = SHA1_HASH_SIZE; + psSha1Init(&digestCtx.sha1); + psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, sigStart, + (int32)(sigStop - sigStart)); + psSha1Final(&digestCtx.sha1, hsMsgHash); +#endif + } else { + return MATRIXSSL_ERROR; + } +#else /* USE_TLS_1_2 */ + hashSize = SHA1_HASH_SIZE; + psSha1Init(&digestCtx.sha1); + psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, sigStart, + (int32)(sigStop - sigStart)); + psSha1Final(&digestCtx.sha1, hsMsgHash); +#endif /* USE_TLS_1_2 */ + + i = 0; + + if ((res = psEccDsaVerify(skepkiPool, + &ssl->sec.cert->publicKey.key.ecc, + hsMsgHash, hashSize, + c, pubDhLen, + &i, pkiData)) != 0) { + psTraceInfo("ECDSA signature validation failed\n"); + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + return MATRIXSSL_ERROR; + } + c += pubDhLen; +/* + The validation code comes out of the final parameter +*/ + if (i != 1) { + psTraceInfo("Can't verify serverKeyExchange sig\n"); + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + return MATRIXSSL_ERROR; + + } + } +#endif /* USE_ECC_CIPHER_SUITE */ + + ssl->hsState = SSL_HS_SERVER_HELLO_DONE; + + } +#endif /* USE_DHE_CIPHER_SUITE */ +#ifdef USE_PSK_CIPHER_SUITE +/* + Entry point for basic PSK ciphers (not DHE or RSA) parsing SKE message +*/ + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + if ((end - c) < 2) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ServerKeyExchange message\n"); + return MATRIXSSL_ERROR; + } + ssl->sec.hintLen = *c << 8; c++; + ssl->sec.hintLen |= *c; c++; + if ((uint32)(end - c) < ssl->sec.hintLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid ServerKeyExchange message\n"); + return MATRIXSSL_ERROR; + } + if (ssl->sec.hintLen > 0) { + ssl->sec.hint = psMalloc(ssl->hsPool, ssl->sec.hintLen); + if (ssl->sec.hint == NULL) { + return SSL_MEM_ERROR; + } + memcpy(ssl->sec.hint, c, ssl->sec.hintLen); + c += ssl->sec.hintLen; + } + ssl->hsState = SSL_HS_SERVER_HELLO_DONE; + } +#endif /* USE_PSK_CIPHER_SUITE */ + + *cp = c; + ssl->decState = SSL_HS_SERVER_KEY_EXCHANGE; + return PS_SUCCESS; +} + +#ifdef USE_OCSP +int32 parseCertificateStatus(ssl_t *ssl, int32 hsLen, unsigned char **cp, + unsigned char *end) +{ + unsigned char *c; + int32_t responseLen, rc; + mOCSPResponse_t response; + + /* + struct { + CertificateStatusType status_type; + select (status_type) { + case ocsp: OCSPResponse; + } response; + } CertificateStatus; + + enum { ocsp(1), (255) } CertificateStatusType; + opaque OCSPResponse<1..2^24-1>; + + An "ocsp_response" contains a complete, DER-encoded OCSP response + (using the ASN.1 type OCSPResponse defined in [RFC6960]). Only one + OCSP response may be sent. + */ + c = *cp; + if ((end - c) < 4) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid CertificateStatus length\n"); + return MATRIXSSL_ERROR; + } + + if (*c != 0x1) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Invalid status_type in certificateStatus message\n"); + return MATRIXSSL_ERROR; + } + c++; + + responseLen = *c << 16; c++; + responseLen |= *c << 8; c++; + responseLen |= *c; c++; + + if (responseLen > (end - c)) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Malformed CertificateStatus message\n"); + return MATRIXSSL_ERROR; + } + memset(&response, 0x0, sizeof(mOCSPResponse_t)); + if ((rc = parseOCSPResponse(ssl->hsPool, responseLen, &c, end, &response)) + < 0) { + /* Couldn't parse or no good responses in stream */ + psX509FreeCert(response.OCSPResponseCert); + ssl->err = SSL_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE; + psTraceInfo("Unable to parse OCSPResponse\n"); + return MATRIXSSL_ERROR; + } + *cp = c; + + /* Authenticate the parsed response based on the registered CA files + AND passing through the server chain as well because some real + world examples we have seen use the intermediate cert as the + OCSP responder */ + if ((rc = validateOCSPResponse(ssl->hsPool, ssl->keys->CAcerts, + ssl->sec.cert, &response)) < 0) { + /* Couldn't validate */ + psX509FreeCert(response.OCSPResponseCert); + ssl->err = SSL_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE; + psTraceInfo("Unable to validate OCSPResponse\n"); + return MATRIXSSL_ERROR; + } + psX509FreeCert(response.OCSPResponseCert); + + /* Same logic to determine next state as in end of SSL_HS_CERTIFICATE */ + ssl->hsState = SSL_HS_SERVER_HELLO_DONE; +#ifdef USE_DHE_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_DHE_KEY_EXCH) { + ssl->hsState = SSL_HS_SERVER_KEY_EXCHANGE; + } +#endif /* USE_DHE_CIPHER_SUITE */ + ssl->decState = SSL_HS_CERTIFICATE_STATUS; + return PS_SUCCESS; +} +#endif /* USE_OCSP */ + +/******************************************************************************/ + +int32 parseServerHelloDone(ssl_t *ssl, int32 hsLen, unsigned char **cp, + unsigned char *end) +{ + unsigned char *c; +#if defined(USE_DHE_CIPHER_SUITE) || defined(REQUIRE_DH_PARAMS) + int32 rc; + void *pkiData = ssl->userPtr; + +#endif /* DH */ + + c = *cp; + + psTraceHs(">>> Client parsing SERVER_HELLO_DONE message\n"); + if (hsLen != 0) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Invalid ServerHelloDone message\n"); + return MATRIXSSL_ERROR; + } + +#ifdef USE_DHE_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_DHE_KEY_EXCH) { +#ifdef USE_ECC_CIPHER_SUITE + + if (ssl->flags & SSL_FLAGS_ECC_CIPHER) { + /* Set up our private side of the ECC key based on the agreed + upon curve */ + if (psEccNewKey(ssl->sec.eccDhKeyPool, &ssl->sec.eccKeyPriv, + ssl->sec.eccKeyPub->curve) < 0) { + return PS_MEM_FAIL; + } + if ((rc = matrixSslGenEphemeralEcKey(ssl->keys, + ssl->sec.eccKeyPriv, ssl->sec.eccKeyPub->curve, + pkiData)) < 0) { + psEccDeleteKey(&ssl->sec.eccKeyPriv); + psTraceInfo("GenEphemeralEcc failed\n"); + ssl->err = SSL_ALERT_INTERNAL_ERROR; + return MATRIXSSL_ERROR; + } + } else { +#endif +#ifdef REQUIRE_DH_PARAMS + /* Can safely set up our ssl->sec.dhKeyPriv with DH keys + based on the parameters passed over from the server. + Storing these in a client specific DH pool because at + handshake pool creation, the size for PKI was not known */ + if ((ssl->sec.dhKeyPriv = psMalloc(ssl->sec.dhKeyPool, + sizeof(psDhKey_t))) == NULL) { + return MATRIXSSL_ERROR; + } + if ((rc = psDhGenKey(ssl->sec.dhKeyPool, ssl->sec.dhPLen, + ssl->sec.dhP, ssl->sec.dhPLen, ssl->sec.dhG, + ssl->sec.dhGLen, ssl->sec.dhKeyPriv, pkiData)) < 0) { + psFree(ssl->sec.dhKeyPriv, ssl->sec.dhKeyPool); + ssl->sec.dhKeyPriv = NULL; + return MATRIXSSL_ERROR; + } + /* Freeing as we go. No more need for G */ + psFree(ssl->sec.dhG, ssl->hsPool); ssl->sec.dhG = NULL; +#endif /* REQUIRE_DH_PARAMS */ +#ifdef USE_ECC_CIPHER_SUITE + } +#endif /* USE_ECC_CIPHER_SUITE */ + } +#endif /* USE_DHE_CIPHER_SUITE */ + + ssl->hsState = SSL_HS_FINISHED; + + *cp = c; + ssl->decState = SSL_HS_SERVER_HELLO_DONE; + return SSL_PROCESS_DATA; +} + +/******************************************************************************/ + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +int32 parseCertificateRequest(ssl_t *ssl, int32 hsLen, unsigned char **cp, + unsigned char *end) +{ +#ifdef USE_CLIENT_AUTH + psX509Cert_t *cert; + int32 i; +#endif + int32 certTypeLen, certChainLen; + uint32 certLen; +#ifdef USE_TLS_1_2 + uint32 sigAlgMatch; +#ifdef USE_CLIENT_AUTH + uint32 hashSigAlg; +#endif +#endif + unsigned char *c; + + c = *cp; + + psTraceHs(">>> Client parsing CERTIFICATE_REQUEST message\n"); + if (hsLen < 4) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Invalid Certificate Request message\n"); + return MATRIXSSL_ERROR; + } + /* Currently ignoring the authentication type request because it was + underspecified up to TLS 1.1 and TLS 1.2 is now taking care of this + with the supported_signature_algorithms handling */ + certTypeLen = *c++; + if (end - c < certTypeLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid Certificate Request message\n"); + return MATRIXSSL_ERROR; + } + c += certTypeLen; /* Skipping (RSA_SIGN etc.) */ +#ifdef USE_TLS_1_2 + sigAlgMatch = 0; + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + /* supported_signature_algorithms field + enum {none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), + sha512(6), (255) } HashAlgorithm; + + enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } SigAlg */ + if (end - c < 2) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid SigHash in Certificate Request message\n"); + return MATRIXSSL_ERROR; + } + certChainLen = *c << 8; c++; /* just borrowing this variable */ + certChainLen |= *c; c++; + if (end - c < certChainLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid SigHash in Certificate Request message\n"); + return MATRIXSSL_ERROR; + } +#ifdef USE_CLIENT_AUTH + /* Going to adhere to this supported_signature_algorithm to + be compliant with the spec. This is now the first line + of testing about what certificates the server will accept. + If any of our certs do not use a signature algorithm + that the server supports we will flag that here which will + ultimately result in an empty CERTIFICATE message and + no CERTIFICATE_VERIFY message. We're going to convert + MD5 to use SHA1 instead though. + + Start by building a bitmap of supported algs */ + hashSigAlg = 0; + while (certChainLen >= 2) { + i = HASH_SIG_MASK(c[0], c[1]); + /* Our own ssl->hashSigAlg is the list we support. So choose + from those only */ + if (ssl->hashSigAlg & i) { + hashSigAlg |= i; + } + c += 2; + certChainLen -= 2; + } + /* RFC: The end-entity certificate provided by the client MUST + contain a key that is compatible with certificate_types. + If the key is a signature key, it MUST be usable with some + hash/signature algorithm pair in supported_signature_algorithms. + + So not only do we have to check the signature algorithm, we + have to check the pub key type as well. */ + sigAlgMatch = 1; /* de-flag if we hit unsupported one */ + if (ssl->keys == NULL || ssl->keys->cert == NULL) { + sigAlgMatch = 0; + } else { + cert = ssl->keys->cert; + while (cert) { + if (cert->pubKeyAlgorithm == OID_RSA_KEY_ALG) { + if (!(hashSigAlg & HASH_SIG_SHA1_RSA_MASK) && +#ifdef USE_SHA384 + !(hashSigAlg & HASH_SIG_SHA384_RSA_MASK) && +#endif + !(hashSigAlg & HASH_SIG_SHA256_RSA_MASK) && + !(hashSigAlg & HASH_SIG_MD5_RSA_MASK)) { + sigAlgMatch = 0; + } + } + if (cert->sigAlgorithm == OID_SHA1_RSA_SIG || + cert->sigAlgorithm == OID_MD5_RSA_SIG) { + if (!(hashSigAlg & HASH_SIG_SHA1_RSA_MASK)) { + sigAlgMatch = 0; + } + } + if (cert->sigAlgorithm == OID_SHA256_RSA_SIG) { + if (!(hashSigAlg & HASH_SIG_SHA256_RSA_MASK)) { + sigAlgMatch = 0; + } + } +#ifdef USE_SHA384 + if (cert->sigAlgorithm == OID_SHA384_RSA_SIG) { + if (!(hashSigAlg & HASH_SIG_SHA384_RSA_MASK)) { + sigAlgMatch = 0; + } + } +#endif +#ifdef USE_SHA512 + if (cert->sigAlgorithm == OID_SHA512_RSA_SIG) { + if (!(hashSigAlg & HASH_SIG_SHA512_RSA_MASK)) { + sigAlgMatch = 0; + } + } +#endif +#ifdef USE_ECC + if (cert->pubKeyAlgorithm == OID_ECDSA_KEY_ALG) { + if (!(hashSigAlg & HASH_SIG_SHA1_ECDSA_MASK) && +#ifdef USE_SHA384 + !(hashSigAlg & HASH_SIG_SHA384_ECDSA_MASK) && +#endif +#ifdef USE_SHA512 + !(hashSigAlg & HASH_SIG_SHA512_ECDSA_MASK) && +#endif + !(hashSigAlg & HASH_SIG_SHA256_ECDSA_MASK) && + !(hashSigAlg & HASH_SIG_SHA1_ECDSA_MASK)) { + sigAlgMatch = 0; + } + } + if (cert->sigAlgorithm == OID_SHA1_ECDSA_SIG) { + if (!(hashSigAlg & HASH_SIG_SHA1_ECDSA_MASK)) { + sigAlgMatch = 0; + } + } + if (cert->sigAlgorithm == OID_SHA256_ECDSA_SIG) { + if (!(hashSigAlg & HASH_SIG_SHA256_ECDSA_MASK)) { + sigAlgMatch = 0; + } + } +#ifdef USE_SHA384 + if (cert->sigAlgorithm == OID_SHA384_ECDSA_SIG) { + if (!(hashSigAlg & HASH_SIG_SHA384_ECDSA_MASK)) { + sigAlgMatch = 0; + } + } +#endif +#ifdef USE_SHA512 + if (cert->sigAlgorithm == OID_SHA512_ECDSA_SIG) { + if (!(hashSigAlg & HASH_SIG_SHA512_ECDSA_MASK)) { + sigAlgMatch = 0; + } + } +#endif +#endif /* USE_ECC */ + cert = cert->next; + } + } +#endif /* USE_CLIENT_AUTH */ + c += certChainLen; + } +#endif /* TLS_1_2 */ + + certChainLen = 0; + if (end - c >= 2) { + certChainLen = *c << 8; c++; + certChainLen |= *c; c++; + if (end - c < certChainLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid Certificate Request message\n"); + return MATRIXSSL_ERROR; + } + } + /* Check the passed in DNs against our cert issuer to see if they match. + Only supporting a single cert on the client side. */ + ssl->sec.certMatch = 0; + +#ifdef USE_CLIENT_AUTH + /* If the user has actually gone to the trouble to load a certificate + to reply with, we flag that here so there is some flexibility as + to whether we want to reply with something (even if it doesn't match) + just in case the server is willing to do a custom test of the cert */ + if (ssl->keys != NULL && ssl->keys->cert) { + ssl->sec.certMatch = SSL_ALLOW_ANON_CONNECTION; + } +#endif /* USE_CLIENT_AUTH */ + while (certChainLen > 2) { + certLen = *c << 8; c++; + certLen |= *c; c++; + if ((uint32)(end - c) < certLen || certLen <= 0 || + (int32)certLen > certChainLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid CertificateRequest message\n"); + return MATRIXSSL_ERROR; + } + certChainLen -= 2; +#ifdef USE_CLIENT_AUTH + /* Can parse the message, but will not look for a match. The + setting of certMatch to 1 will trigger the correct response + in sslEncode */ + if (ssl->keys != NULL && ssl->keys->cert) { + /* Flag a match if the hash of the DN issuer is identical */ + if (ssl->keys->cert->issuer.dnencLen == certLen) { + if (memcmp(ssl->keys->cert->issuer.dnenc, c, certLen) == 0){ + ssl->sec.certMatch = 1; + } + } + } +#endif /* USE_CLIENT_AUTH */ + c += certLen; + certChainLen -= certLen; + } +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + /* We let the DN parse complete but if we didn't get a sigAlgMatch + from the previous test we're going to adhere to that for spec + compliance. So here goes */ + if (sigAlgMatch == 0) { + ssl->sec.certMatch = 0; + } + } +#endif + ssl->hsState = SSL_HS_SERVER_HELLO_DONE; + + *cp = c; + ssl->decState = SSL_HS_CERTIFICATE_REQUEST; + return PS_SUCCESS; +} +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ +#endif /* USE_CLIENT_SIDE_SSL */ + +/******************************************************************************/ + +int32 parseFinished(ssl_t *ssl, int32 hsLen, + unsigned char hsMsgHash[SHA384_HASH_SIZE], + unsigned char **cp, + unsigned char *end) +{ + int32 rc; + unsigned char *c; + + rc = PS_SUCCESS; + c = *cp; + + /* Before the finished handshake message, we should have seen the + CHANGE_CIPHER_SPEC message come through in the record layer, which + would have activated the read cipher, and set the READ_SECURE flag. + This is the first handshake message that was sent securely. */ + psTraceStrHs(">>> %s parsing FINISHED message\n", + (ssl->flags & SSL_FLAGS_SERVER) ? "Server" : "Client"); + if (!(ssl->flags & SSL_FLAGS_READ_SECURE)) { + ssl->err = SSL_ALERT_UNEXPECTED_MESSAGE; + psTraceInfo("Finished before ChangeCipherSpec\n"); + return MATRIXSSL_ERROR; + } + /* The contents of the finished message is a 16 byte MD5 hash followed + by a 20 byte sha1 hash of all the handshake messages so far, to verify + that nothing has been tampered with while we were still insecure. + Compare the message to the value we calculated at the beginning of + this function. */ +#ifdef USE_TLS + if (ssl->flags & SSL_FLAGS_TLS) { + if (hsLen != TLS_HS_FINISHED_SIZE) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid Finished length\n"); + return MATRIXSSL_ERROR; + } + } else { +#endif /* USE_TLS */ + if (hsLen != MD5_HASH_SIZE + SHA1_HASH_SIZE) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid Finished length\n"); + return MATRIXSSL_ERROR; + } +#ifdef USE_TLS + } +#endif /* USE_TLS */ + if ((int32)(end - c) < hsLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid Finished length\n"); + return MATRIXSSL_ERROR; + } + if (memcmpct(c, hsMsgHash, hsLen) != 0) { + ssl->err = SSL_ALERT_DECRYPT_ERROR; + psTraceInfo("Invalid handshake msg hash\n"); + return MATRIXSSL_ERROR; + } +#ifdef ENABLE_SECURE_REHANDSHAKES + /* Got the peer verify_data for secure renegotiations */ + memcpy(ssl->peerVerifyData, c, hsLen); + ssl->peerVerifyDataLen = hsLen; +#endif /* ENABLE_SECURE_REHANDSHAKES */ + c += hsLen; + ssl->hsState = SSL_HS_DONE; + /* Now that we've parsed the Finished message, if we're a resumed + connection, we're done with handshaking, otherwise, we return + SSL_PROCESS_DATA to get our own cipher spec and finished messages + sent out by the caller. */ + if (ssl->flags & SSL_FLAGS_SERVER) { + if (!(ssl->flags & SSL_FLAGS_RESUMED)) { + rc = SSL_PROCESS_DATA; + } else { +#ifdef USE_SSL_INFORMATIONAL_TRACE + /* Server side resumed completion */ + matrixSslPrintHSDetails(ssl); +#endif + } + } else { +#ifdef USE_STATELESS_SESSION_TICKETS + /* Now that FINISHED is verified, we can mark the ticket as + valid to conform to section 3.3 of the 5077 RFC */ + if (ssl->sid && ssl->sid->sessionTicketLen > 0) { + ssl->sid->sessionTicketState = SESS_TICKET_STATE_USING_TICKET; + } +#endif + if (ssl->flags & SSL_FLAGS_RESUMED) { + rc = SSL_PROCESS_DATA; + } else { +#ifdef USE_SSL_INFORMATIONAL_TRACE + /* Client side standard completion */ + matrixSslPrintHSDetails(ssl); +#endif + } + } +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH) + /* There is also an attempt to free the cert during + the sending of the finished message to deal with client + and server and differing handshake types. Both cases are + attempted keep the lifespan of this allocation as short as possible. */ + if (ssl->sec.cert) { + psX509FreeCert(ssl->sec.cert); + ssl->sec.cert = NULL; + } +#endif /* USE_CLIENT_SIDE_SSL || USE_CLIENT_AUTH */ +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + /* A successful parse of the FINISHED message means the record sequence + numbers have been reset so we need to clear out our replay detector */ + zeroSixByte(ssl->lastRsn); + + /* This will just be set between CCS parse and FINISHED parse */ + ssl->parsedCCS = 1; + + /* Look at the comment in the fragment parsing code to see the + justification of placing this free here. Bascially, this + is the best place to do it because we know there can be no + further fragmented messages. More importantly, the + hanshake pool is being freed here! */ + if (ssl->fragMessage != NULL) { + psFree(ssl->fragMessage, ssl->hsPool); + ssl->fragMessage = NULL; + } + } + /* Premaster was not freed at the usual spot becasue of retransmit cases */ + if (ssl->sec.premaster) { + psFree(ssl->sec.premaster, ssl->hsPool); ssl->sec.premaster = NULL; + } + if (ssl->ckeMsg) { + psFree(ssl->ckeMsg, ssl->hsPool); ssl->ckeMsg = NULL; + } + if (ssl->certVerifyMsg) { + psFree(ssl->certVerifyMsg, ssl->hsPool); ssl->certVerifyMsg = NULL; + } +#if defined(USE_PSK_CIPHER_SUITE) && defined(USE_CLIENT_SIDE_SSL) + if (ssl->sec.hint) { + psFree(ssl->sec.hint, ssl->hsPool); ssl->sec.hint = NULL; + } +#endif +#endif /* USE_DTLS */ + ssl->hsPool = NULL; + + *cp = c; + ssl->decState = SSL_HS_FINISHED; + return rc; +} + +/******************************************************************************/ + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH) +int32 parseCertificate(ssl_t *ssl, unsigned char **cp, unsigned char *end) +{ + psX509Cert_t *currentCert, *cert, *foundIssuer; + unsigned char *c; + uint32 certLen; + int32 rc, i, certChainLen, parseLen = 0; + void *pkiData = ssl->userPtr; + + + psTraceStrHs(">>> %s parsing CERTIFICATE message\n", + (ssl->flags & SSL_FLAGS_SERVER) ? "Server" : "Client"); + + c = *cp; + +#ifdef USE_CERT_CHAIN_PARSING + if (ssl->rec.partial) { + /* The test for a first pass is against the record header length */ + if (ssl->rec.hsBytesParsed == ssl->recordHeadLen) { + /* Account for the one-time header portion parsed above + and the 3 byte cert chain length about to be parsed below. + The minimum length tests have already been performed. */ + ssl->rec.hsBytesParsed += ssl->hshakeHeadLen + 3; + } else { + goto SKIP_CERT_CHAIN_INIT; + } + } +#endif + if (end - c < 3) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid Certificate message\n"); + return MATRIXSSL_ERROR; + } + certChainLen = *c << 16; c++; + certChainLen |= *c << 8; c++; + certChainLen |= *c; c++; + if (certChainLen == 0) { +#ifdef SERVER_WILL_ACCEPT_EMPTY_CLIENT_CERT_MSG + if (ssl->flags & SSL_FLAGS_SERVER) { + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + ssl->flags &= ~SSL_FLAGS_CLIENT_AUTH; + goto STRAIGHT_TO_USER_CALLBACK; + } +#endif + if (ssl->majVer == SSL3_MAJ_VER && ssl->minVer == SSL3_MIN_VER) { + ssl->err = SSL_ALERT_NO_CERTIFICATE; + } else { + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + } + psTraceInfo("No certificate sent to verify\n"); + return MATRIXSSL_ERROR; + } + if (end - c < 3) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid Certificate message\n"); + return MATRIXSSL_ERROR; + } + +#ifdef USE_CERT_CHAIN_PARSING +SKIP_CERT_CHAIN_INIT: + if (ssl->rec.partial) { + /* It is possible to activate the CERT_STREAM_PARSE feature and not + receive a cert chain in multiple buffers. If we are not flagged + for 'partial' parsing, we can drop into the standard parse case */ + while (end - c > 0) { + certLen = *c << 16; c++; + certLen |= *c << 8; c++; + certLen |= *c; c++; + if ((parseLen = parseSingleCert(ssl, c, end, certLen)) < 0 ) { + return parseLen; + } + ssl->rec.hsBytesParsed += parseLen + 3; /* 3 for certLen */ + c += parseLen; + } + if (ssl->rec.hsBytesParsed < ssl->rec.trueLen) { + *cp = c; + return MATRIXSSL_SUCCESS; + } + + psAssert(ssl->rec.hsBytesParsed == ssl->rec.trueLen); + /* Got it all. Disable the stream mechanism. */ + ssl->rec.partial = 0x0; + ssl->rec.hsBytesParsed = 0; + ssl->rec.hsBytesHashed = 0; + } else { + psAssert(certChainLen > 0); +#endif /* USE_CERT_CHAIN_PARSING */ + i = 0; + currentCert = NULL; + + /* Chain must be at least 3 b certLen */ + while (certChainLen >= 3) { + certLen = *c << 16; c++; + certLen |= *c << 8; c++; + certLen |= *c; c++; + certChainLen -= 3; + + if ((uint32)(end - c) < certLen || (int32)certLen > certChainLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid certificate length\n"); + return MATRIXSSL_ERROR; + } +/* + Extract the binary cert message into the cert structure +*/ + if ((parseLen = psX509ParseCert(ssl->hsPool, c, certLen, &cert, 0)) + < 0) { + psX509FreeCert(cert); + if (parseLen == PS_MEM_FAIL) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + } else { + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + } + return MATRIXSSL_ERROR; + } + c += parseLen; + + if (i++ == 0) { + ssl->sec.cert = cert; + currentCert = ssl->sec.cert; + } else { + currentCert->next = cert; + currentCert = currentCert->next; + } + certChainLen -= certLen; + } +#ifdef USE_CERT_CHAIN_PARSING + } +#endif /* USE_CERT_CHAIN_PARSING */ + +#ifdef USE_CLIENT_SIDE_SSL + /* Now want to test to see if supplied child-most cert is the appropriate + pubkey algorithm for the chosen cipher suite. Have seen test + cases with OpenSSL where an RSA cert will be sent for an ECDHE_ECDSA + suite, for example. Just testing on the client side because client + auth is a bit more flexible on the algorithm choices. */ + if (!(ssl->flags & SSL_FLAGS_SERVER)) { + if (csCheckCertAgainstCipherSuite(ssl->sec.cert->publicKey.type, + ssl->cipher->type) == 0) { + psTraceIntInfo("Server sent bad pubkey type for cipher suite %d\n", + ssl->cipher->type); + ssl->err = SSL_ALERT_UNSUPPORTED_CERTIFICATE; + return MATRIXSSL_ERROR; + } + } +#endif + + /* Time to authenticate the supplied cert against our CAs */ + + rc = matrixValidateCerts(ssl->hsPool, ssl->sec.cert, + ssl->keys == NULL ? NULL : ssl->keys->CAcerts, ssl->expectedName, + &foundIssuer, pkiData, ssl->memAllocPtr); + + + if (rc == PS_MEM_FAIL) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + return MATRIXSSL_ERROR; + } + /* Now walk the subject certs and convert any parse or authentication error + into an SSL alert. The alerts SHOULD be read by the user callback + to determine whether they are fatal or not. If no user callback, + the first alert will be considered fatal. */ + cert = ssl->sec.cert; + while (cert) { + if (ssl->err != SSL_ALERT_NONE) { + break; /* The first alert is the logical one to send */ + } + switch (cert->authStatus) { + case PS_CERT_AUTH_FAIL_SIG: + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + break; + case PS_CERT_AUTH_FAIL_REVOKED: + ssl->err = SSL_ALERT_CERTIFICATE_REVOKED; + break; + case PS_CERT_AUTH_FAIL_AUTHKEY: + case PS_CERT_AUTH_FAIL_PATH_LEN: + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + break; + case PS_CERT_AUTH_FAIL_EXTENSION: + /* The math and basic constraints matched. This case is + for X.509 extension mayhem */ + if (cert->authFailFlags & PS_CERT_AUTH_FAIL_DATE_FLAG) { + ssl->err = SSL_ALERT_CERTIFICATE_EXPIRED; + } else if(cert->authFailFlags & PS_CERT_AUTH_FAIL_SUBJECT_FLAG){ + /* expectedName was giving to NewSession but couldn't + match what the peer gave us */ + ssl->err = SSL_ALERT_CERTIFICATE_UNKNOWN; + } else if (cert->next != NULL) { + /* This is an extension problem in the chain. + Even if it's minor, we are shutting it down */ + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + } else { + /* This is the case where we did successfully find the + correct CA to validate the cert and the math passed + but the extensions had a problem. Give app a + different message in this case */ + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + } + break; + case PS_CERT_AUTH_FAIL_BC: + case PS_CERT_AUTH_FAIL_DN: + /* These two are pre-math tests. If this was a problem in the + middle of the chain it means the chain couldn't even + validate itself. If it is at the end it means a matching + CA could not be found */ + if (cert->next != NULL) { + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + } else { + ssl->err = SSL_ALERT_UNKNOWN_CA; + } + break; + + default: + break; + } + cert = cert->next; + } + + /* The last thing we want to check before passing the certificates to + the user callback is the case in which we don't have any + CA files loaded but we were passed a valid chain that was + terminated with a self-signed cert. The fact that a CA on this + peer has not validated the chain should result in an UNKNOWN_CA alert + + NOTE: This case should only ever get hit if VALIDATE_KEY_MATERIAL + has been disabled in matrixssllib.h */ + + if (ssl->err == SSL_ALERT_NONE && + (ssl->keys == NULL || ssl->keys->CAcerts == NULL)) { + ssl->err = SSL_ALERT_UNKNOWN_CA; + psTraceInfo("WARNING: Valid self-signed cert or cert chain but no local authentication\n"); + rc = -1; /* Force the check on existence of user callback */ + } + + if (rc < 0) { + psTraceInfo("WARNING: cert did not pass internal validation test\n"); + /* Cert auth failed. If there is no user callback issue fatal alert + because there will be no intervention to give it a second look. */ + if (ssl->sec.validateCert == NULL) { + /* ssl->err should have been set correctly above but catch + any missed cases with the generic BAD_CERTIFICATE alert */ + if (ssl->err == SSL_ALERT_NONE) { + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + } + return MATRIXSSL_ERROR; + } + } + +#ifdef SERVER_WILL_ACCEPT_EMPTY_CLIENT_CERT_MSG +STRAIGHT_TO_USER_CALLBACK: +#endif + + /* Return from user validation space with knowledge that there is a fatal + alert or that this is an ANONYMOUS connection. */ + rc = matrixUserCertValidator(ssl, ssl->err, ssl->sec.cert, + ssl->sec.validateCert); + /* Test what the user callback returned. */ + ssl->sec.anon = 0; + if (rc == SSL_ALLOW_ANON_CONNECTION) { + ssl->sec.anon = 1; + } else if (rc > 0) { + /* User returned an alert. May or may not be the alert that was + determined above */ + psTraceIntInfo("Certificate authentication alert %d\n", rc); + ssl->err = rc; + return MATRIXSSL_ERROR; + } else if (rc < 0) { + psTraceIntInfo("User certificate callback had an internal error\n", rc); + ssl->err = SSL_ALERT_INTERNAL_ERROR; + return MATRIXSSL_ERROR; + } + + /* User callback returned 0 (continue on). Did they determine the alert + was not fatal after all? */ + if (ssl->err != SSL_ALERT_NONE) { + psTraceIntInfo("User certificate callback determined alert %d was NOT fatal\n", + ssl->err); + ssl->err = SSL_ALERT_NONE; + } + + /* Either a client or server could have been processing the cert as part of + the authentication process. If server, we move to the client key + exchange state. */ + if (ssl->flags & SSL_FLAGS_SERVER) { + ssl->hsState = SSL_HS_CLIENT_KEY_EXCHANGE; + } else { + ssl->hsState = SSL_HS_SERVER_HELLO_DONE; +#ifdef USE_DHE_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_DHE_KEY_EXCH) { + ssl->hsState = SSL_HS_SERVER_KEY_EXCHANGE; + } +#endif /* USE_DHE_CIPHER_SUITE */ +#ifdef USE_OCSP + /* State management for OCSP use. Testing if we received a + status_request from the server to set next expected state */ + if (ssl->extFlags.status_request || ssl->extFlags.status_request_v2) { + /* Why do they allow an ambiguous state here?! From RFC 6066: + + Note that a server MAY also choose not to send a + "CertificateStatus" message, even if has received a + "status_request" extension in the client hello message and has + sent a "status_request" extension in the server hello message */ + ssl->hsState = SSL_HS_CERTIFICATE_STATUS; + } +#endif + } + *cp = c; + ssl->decState = SSL_HS_CERTIFICATE; + return MATRIXSSL_SUCCESS; +} +#endif /* USE_CLIENT_SIDE_SSL || USE_CLIENT_AUTH */ +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + +/******************************************************************************/ + diff --git a/matrixssl/hsHash.c b/matrixssl/hsHash.c new file mode 100644 index 0000000..a88c071 --- /dev/null +++ b/matrixssl/hsHash.c @@ -0,0 +1,471 @@ +/** + * @file hsHash.c + * @version $Format:%h%d$ + * + * "Native" handshake hash. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ + +#include "matrixsslApi.h" + + +#define FINISHED_LABEL_SIZE 15 +#define LABEL_CLIENT "client finished" +#define LABEL_SERVER "server finished" +/******************************************************************************/ +/** + Initialize the SHA1 and MD5 hash contexts for the handshake messages. + The handshake hashes are used in 3 messages in TLS: + ClientFinished, ServerFinished and ClientCertificateVerify. + The version of TLS affects which hashes are used for the Finished messages. + TLS 1.2 allows a different hash algorithm for the CertificatVerify message + than is used by the Finished messages, determined by the + Signature Algorithms extension. + Multiple handshake hash contexts must be maintained until the handshake has + progressed enough to determine the negotiated TLS version and whether or + not Client Authentication is to be performed. Also, if USE_ONLY_TLS_1_2 is + defined at compile time, or USE_CLIENT_AUTH is undefined at compile time, + the potential runtime combinations are reduced. + The various algorithms are used as follows (+ means concatenation): + Client and Server Finished messages + < TLS 1.2 - MD5+SHA1 + TLS 1.2 - SHA256 + Client CertificateVerify message. + < TLS 1.2 - MD5+SHA1 + TLS 1.2 - One of the hashes present in the union of the + SignatureAlgorithms Client extension and the CertificateRequest + message from the server. At most this is the set + {SHA1,SHA256,SHA384,SHA512}. + @return < 0 on failure. + @param[in,out] ssl TLS context +*/ +int32_t sslInitHSHash(ssl_t *ssl) +{ +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + /* Don't allow CLIENT_HELLO message retransmit to reset hash */ + if (ssl->retransmit) { + return 0; + } + } +#endif /* USE_DTLS */ + +#ifndef USE_ONLY_TLS_1_2 + psMd5Sha1Init(&ssl->sec.msgHashMd5Sha1); +#endif + +#ifdef USE_TLS_1_2 + psSha256Init(&ssl->sec.msgHashSha256); + #ifdef USE_SHA1 + psSha1Init(&ssl->sec.msgHashSha1); + #endif + #ifdef USE_SHA384 + psSha384Init(&ssl->sec.msgHashSha384); + #endif + #ifdef USE_SHA512 + psSha512Init(&ssl->sec.msgHashSha512); + #endif +#endif + + return 0; +} + +/******************************************************************************/ +/** + Add the given data to the running hash of the handshake messages. + @param[in,out] ssl TLS context + @param[in] in Pointer to handshake data to hash. + @param[in] len Number of bytes of handshake data to hash. + @return < 0 on failure. +*/ +int32_t sslUpdateHSHash(ssl_t *ssl, const unsigned char *in, uint16_t len) +{ + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + /* Don't update handshake hashes on resends. Already been through here */ + if (ssl->retransmit) { + return 0; + } + } +#endif /* USE_DTLS */ + +#ifdef USE_TLS_1_2 + /* Keep a running total of each for greatest RFC support when it comes + to the CertificateVerify message. Although, trying to be smart + about MD5 and SHA-2 based on protocol version. */ + if ((ssl->majVer == 0 && ssl->minVer == 0) || +#ifdef USE_DTLS + ssl->minVer == DTLS_1_2_MIN_VER || +#endif + ssl->minVer == TLS_1_2_MIN_VER) { + psSha256Update(&ssl->sec.msgHashSha256, in, len); + #ifdef USE_SHA1 + psSha1Update(&ssl->sec.msgHashSha1, in, len); + #endif + #ifdef USE_SHA384 + psSha384Update(&ssl->sec.msgHashSha384, in, len); + #endif + #ifdef USE_SHA512 + psSha512Update(&ssl->sec.msgHashSha512, in, len); + #endif + } +#endif + +#ifndef USE_ONLY_TLS_1_2 + /* Below TLS 1.2, the hash is always the md5sha1 hash. If we negotiate + to TLS 1.2 and need sha1, we use just that part of the md5Sha1. */ +//TODO if (ssl->reqMinVer == 0 || ssl->minVer != TLS_1_2_MIN_VER) { + psMd5Sha1Update(&ssl->sec.msgHashMd5Sha1, in, len); + +#endif + + return 0; +} + +#ifdef USE_TLS_1_2 +/* Functions necessary to deal with needing to keep track of both SHA-1 + and SHA-256 handshake hash states. FINISHED message will always be + SHA-256 but client might be sending SHA-1 CertificateVerify message */ + #if defined(USE_SERVER_SIDE_SSL) && defined(USE_CLIENT_AUTH) + #ifdef USE_SHA1 +int32 sslSha1RetrieveHSHash(ssl_t *ssl, unsigned char *out) +{ + memcpy(out, ssl->sec.sha1Snapshot, SHA1_HASH_SIZE); + return SHA1_HASH_SIZE; +} + #endif + #ifdef USE_SHA384 +int32 sslSha384RetrieveHSHash(ssl_t *ssl, unsigned char *out) +{ + memcpy(out, ssl->sec.sha384Snapshot, SHA384_HASH_SIZE); + return SHA384_HASH_SIZE; +} + #endif + #ifdef USE_SHA512 +int32 sslSha512RetrieveHSHash(ssl_t *ssl, unsigned char *out) +{ + memcpy(out, ssl->sec.sha512Snapshot, SHA512_HASH_SIZE); + return SHA512_HASH_SIZE; +} + #endif + #endif /* USE_SERVER_SIDE_SSL && USE_CLIENT_AUTH */ + + #if defined(USE_CLIENT_SIDE_SSL) && defined(USE_CLIENT_AUTH) + #ifdef USE_SHA1 +/* It is possible the certificate verify message wants a non-SHA256 hash */ +void sslSha1SnapshotHSHash(ssl_t *ssl, unsigned char *out) +{ + psSha1Final(&ssl->sec.msgHashSha1, out); +} + #endif + #ifdef USE_SHA384 +void sslSha384SnapshotHSHash(ssl_t *ssl, unsigned char *out) +{ + psSha384_t sha384; + + /* SHA384 must copy the context because it could be needed again for + final handshake hash. SHA1 doesn't need this because it will + not ever be used again after this client auth one-off */ + psSha384Sync(&ssl->sec.msgHashSha384, 0); + sha384 = ssl->sec.msgHashSha384; + psSha384Final(&sha384, out); +} + #endif + #ifdef USE_SHA512 +void sslSha512SnapshotHSHash(ssl_t *ssl, unsigned char *out) +{ + psSha512_t sha512; + + /* SHA512 must copy the context because it could be needed again for + final handshake hash. SHA1 doesn't need this because it will + not ever be used again after this client auth one-off */ + psSha512Sync(&ssl->sec.msgHashSha512, 0); + sha512 = ssl->sec.msgHashSha512; + psSha512Final(&sha512, out); +} + #endif + #endif /* USE_CLIENT_SIDE_SSL && USE_CLIENT_AUTH */ +#endif /* USE_TLS_1_2 */ + +#ifdef USE_TLS +/******************************************************************************/ +/* + TLS handshake hash computation +*/ +static int32_t tlsGenerateFinishedHash(ssl_t *ssl, + #ifndef USE_ONLY_TLS_1_2 + psMd5Sha1_t *md5sha1, + #endif + #ifdef USE_TLS_1_2 + #ifdef USE_SHA1 + psSha1_t *sha1, + #endif + #ifdef USE_SHA256 + psSha256_t *sha256, + #endif + #ifdef USE_SHA384 + psSha384_t *sha384, + #endif + #ifdef USE_SHA512 + psSha512_t *sha512, + #endif + #endif /* USE_TLS_1_2 */ + unsigned char *masterSecret, + unsigned char *out, int32 senderFlag) +{ + unsigned char tmp[FINISHED_LABEL_SIZE + SHA384_HASH_SIZE]; + +#ifndef USE_ONLY_TLS_1_2 + psMd5Sha1_t md5sha1_backup; +#endif +#ifdef USE_SHA1 + psSha1_t sha1_backup; +#endif +#ifdef USE_SHA256 + psSha256_t sha256_backup; +#endif +#ifdef USE_SHA384 + psSha384_t sha384_backup; +#endif +#ifdef USE_SHA512 + psSha512_t sha512_backup; +#endif +/* + In each branch: Use a backup of the message hash-to-date because we don't + want to destroy the state of the handshaking until truly complete +*/ + + if (senderFlag >= 0) { + memcpy(tmp, (senderFlag & SSL_FLAGS_SERVER) ? LABEL_SERVER : LABEL_CLIENT, + FINISHED_LABEL_SIZE); + #ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + if (ssl->cipher->flags & CRYPTO_FLAGS_SHA3) { + #ifdef USE_SHA384 + psSha384Cpy(&sha384_backup, sha384); + psSha384Final(&sha384_backup, tmp + FINISHED_LABEL_SIZE); + return prf2(masterSecret, SSL_HS_MASTER_SIZE, tmp, + FINISHED_LABEL_SIZE + SHA384_HASH_SIZE, out, + TLS_HS_FINISHED_SIZE, CRYPTO_FLAGS_SHA3); + #endif + } else { + psSha256Cpy(&sha256_backup, sha256); + psSha256Final(&sha256_backup, tmp + FINISHED_LABEL_SIZE); + return prf2(masterSecret, SSL_HS_MASTER_SIZE, tmp, + FINISHED_LABEL_SIZE + SHA256_HASH_SIZE, out, + TLS_HS_FINISHED_SIZE, CRYPTO_FLAGS_SHA2); + } + #ifndef USE_ONLY_TLS_1_2 + } else { + psMd5Sha1Cpy(&md5sha1_backup, md5sha1); + psMd5Sha1Final(&md5sha1_backup, tmp + FINISHED_LABEL_SIZE); + return prf(masterSecret, SSL_HS_MASTER_SIZE, tmp, + FINISHED_LABEL_SIZE + MD5SHA1_HASHLEN, + out, TLS_HS_FINISHED_SIZE); + #endif + } + #else + psMd5Sha1Cpy(&md5sha1_backup, md5sha1); + psMd5Sha1Final(&md5sha1_backup, tmp + FINISHED_LABEL_SIZE); + return prf(masterSecret, SSL_HS_MASTER_SIZE, tmp, + FINISHED_LABEL_SIZE + MD5SHA1_HASHLEN, + out, TLS_HS_FINISHED_SIZE); + #endif + } else { + /* Overloading this function to handle the client auth needs of + handshake hashing. */ + #ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + psSha256Cpy(&sha256_backup, sha256); + psSha256Final(&sha256_backup, out); + #if defined(USE_SERVER_SIDE_SSL) && defined(USE_CLIENT_AUTH) + /* Check to make sure we are a server because clients come + through here as well and they do not need to snapshot any + hashes because they are in a write state during the + CERTIFICATE_VERIFY creation. So if they detect a non-default + in digest, they just run the sslSha384SnapshotHSHash family + of functions. Servers really do have to save aside the + snapshots beause the CERTIFICATE_VERIFY is a parse and so the + handshake hash is being set aside for all possible combos + here so the sslSha384RetrieveHSHash can fetch. Previous + versions were not testing for SERVER here so clients were + running digest operations that were not needed in client auth */ + if (ssl->flags & SSL_FLAGS_SERVER) { + #ifdef USE_SHA384 + psSha384Cpy(&sha384_backup, sha384); + psSha384Final(&sha384_backup, ssl->sec.sha384Snapshot); + #endif + #ifdef USE_SHA512 + psSha512Cpy(&sha512_backup, sha512); + psSha512Final(&sha512_backup, ssl->sec.sha512Snapshot); + #endif + #ifdef USE_SHA1 + psSha1Cpy(&sha1_backup, sha1); + psSha1Final(&sha1_backup, ssl->sec.sha1Snapshot); + #endif + } + #endif + return SHA256_HASH_SIZE; + #ifndef USE_ONLY_TLS_1_2 + } else { + psMd5Sha1Cpy(&md5sha1_backup, md5sha1); + psMd5Sha1Final(&md5sha1_backup, out); + return MD5SHA1_HASHLEN; + #endif + } + #else +/* + The handshake snapshot for client authentication is simply the + appended MD5 and SHA1 hashes +*/ + psMd5Sha1Cpy(&md5sha1_backup, md5sha1); + psMd5Sha1Final(&md5sha1_backup, out); + return MD5SHA1_HASHLEN; + #endif /* USE_TLS_1_2 */ + } + return PS_FAILURE; /* Should not reach this */ +} +#endif /* USE_TLS */ + + +/* The extended master secret computation uses a handshake hash */ +int32_t extMasterSecretSnapshotHSHash(ssl_t *ssl, unsigned char *out, + uint32 *outLen) +{ +#ifndef USE_ONLY_TLS_1_2 + psMd5Sha1_t md5sha1; +#endif +#ifdef USE_SHA256 + psSha256_t sha256; +#endif +#ifdef USE_SHA384 + psSha384_t sha384; +#endif + +/* + Use a backup of the message hash-to-date because we don't want + to destroy the state of the handshaking until truly complete +*/ + + *outLen = 0; + +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + if (ssl->cipher->flags & CRYPTO_FLAGS_SHA3) { +#ifdef USE_SHA384 + psSha384Cpy(&sha384, &ssl->sec.msgHashSha384); + psSha384Final(&sha384, out); + *outLen = SHA384_HASH_SIZE; +#endif + } else { + psSha256Cpy(&sha256, &ssl->sec.msgHashSha256); + psSha256Final(&sha256, out); + *outLen = SHA256_HASH_SIZE; + } +#ifndef USE_ONLY_TLS_1_2 + } else { + psMd5Sha1Cpy(&md5sha1, &ssl->sec.msgHashMd5Sha1); + psMd5Sha1Final(&md5sha1, out); + *outLen = MD5SHA1_HASHLEN; +#endif + } +#else /* no TLS 1.2 */ + psMd5Sha1Cpy(&md5sha1, &ssl->sec.msgHashMd5Sha1); + psMd5Sha1Final(&md5sha1, out); + *outLen = MD5SHA1_HASHLEN; +#endif + + return *outLen; +} + + +/******************************************************************************/ +/* + Snapshot is called by the receiver of the finished message to produce + a hash of the preceeding handshake messages for comparison to incoming + message. +*/ +int32_t sslSnapshotHSHash(ssl_t *ssl, unsigned char *out, int32 senderFlag) +{ + int32 len = PS_FAILURE; + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + /* Don't allow FINISHED message retransmit to re-calc hash */ + if (ssl->retransmit) { + memcpy(out, ssl->hsSnapshot, ssl->hsSnapshotLen); + return ssl->hsSnapshotLen; + } + } +#endif /* USE_DTLS */ + +#ifdef USE_TLS + if (ssl->flags & SSL_FLAGS_TLS) { + len = tlsGenerateFinishedHash(ssl, + #ifndef USE_ONLY_TLS_1_2 + &ssl->sec.msgHashMd5Sha1, + #endif + #ifdef USE_TLS_1_2 + #ifdef USE_SHA1 + &ssl->sec.msgHashSha1, + #endif + #ifdef USE_SHA256 + &ssl->sec.msgHashSha256, + #endif + #ifdef USE_SHA384 + &ssl->sec.msgHashSha384, + #endif + #ifdef USE_SHA512 + &ssl->sec.msgHashSha512, + #endif + #endif /* USE_TLS_1_2 */ + ssl->sec.masterSecret, out, senderFlag); + + #ifndef DISABLE_SSLV3 + } else { + len = sslGenerateFinishedHash(&ssl->sec.msgHashMd5Sha1, + ssl->sec.masterSecret, out, senderFlag); + #endif /* DISABLE_SSLV3 */ + } +#endif /* USE_TLS */ + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (len > 0) { + memcpy(ssl->hsSnapshot, out, len); + ssl->hsSnapshotLen = len; + } + } +#endif /* USE_DTLS */ + return len; +} + + +/******************************************************************************/ + diff --git a/matrixssl/matrixssl.c b/matrixssl/matrixssl.c new file mode 100644 index 0000000..6796d1c --- /dev/null +++ b/matrixssl/matrixssl.c @@ -0,0 +1,3049 @@ +/** + * @file matrixssl.c + * @version $Format:%h%d$ + * + * The session and authentication management portions of the MatrixSSL library. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "matrixsslApi.h" +/******************************************************************************/ + +static const char copyright[] = +"Copyright Inside Secure Corporation. All rights reserved."; + +#if defined(USE_RSA) || defined(USE_ECC) +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) +static int32 verifyReadKeys(psPool_t *pool, sslKeys_t *keys, void *poolUserPtr); +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ +#endif /* USE_RSA || USE_ECC */ + + +#ifdef USE_SERVER_SIDE_SSL + +#ifndef SSL_SESSION_TICKET_LIST_LEN +#define SSL_SESSION_TICKET_LIST_LEN 32 +#endif /* SSL_SESSION_TICKET_LIST_LEN */ + +/* + Static session table for session cache and lock for multithreaded env +*/ +#ifdef USE_MULTITHREADING +static psMutex_t sessionTableLock; +#ifdef USE_STATELESS_SESSION_TICKETS +static psMutex_t g_sessTicketLock; +#endif +#endif /* USE_MULTITHREADING */ + +static sslSessionEntry_t sessionTable[SSL_SESSION_TABLE_SIZE]; +static DLListEntry sessionChronList; +static void initSessionEntryChronList(void); + +#endif /* USE_SERVER_SIDE_SSL */ + +#if defined(USE_RSA) || defined(USE_ECC) +#ifdef MATRIX_USE_FILE_SYSTEM +static int32 matrixSslLoadKeyMaterial(sslKeys_t *keys, const char *certFile, + const char *privFile, const char *privPass, const char *CAfile, + int32 privKeyType); +#endif +static int32 matrixSslLoadKeyMaterialMem(sslKeys_t *keys, + const unsigned char *certBuf, int32 certLen, + const unsigned char *privBuf, + int32 privLen, const unsigned char *CAbuf, int32 CAlen, + int32 privKeyType); +#endif /* USE_RSA || USE_ECC */ + + +/******************************************************************************/ +/* + Open and close the SSL module. These routines are called once in the + lifetime of the application and initialize and clean up the library + respectively. + The config param should always be passed as: + MATRIXSSL_CONFIG +*/ +static char g_config[32] = "N"; + +int32 matrixSslOpenWithConfig(const char *config) +{ + unsigned long clen; + + /* Use copyright to avoid compiler warning about it being unused */ + if (*copyright != 'C') { + return PS_FAILURE; + } + if (*g_config == 'Y') { + return PS_SUCCESS; /* Function has been called previously */ + } + /* config parameter is matrixconfig + cryptoconfig + coreconfig */ + strncpy(g_config, MATRIXSSL_CONFIG, sizeof(g_config) - 1); + clen = strlen(MATRIXSSL_CONFIG) - strlen(PSCRYPTO_CONFIG); + if (strncmp(g_config, config, clen) != 0) { + psErrorStr( "MatrixSSL config mismatch.\n" \ + "Library: " MATRIXSSL_CONFIG \ + "\nCurrent: %s\n", config); + return -1; + } + if (psCryptoOpen(config + clen) < 0) { + psError("pscrypto open failure\n"); + return PS_FAILURE; + } + + + +#ifdef USE_SERVER_SIDE_SSL + memset(sessionTable, 0x0, + sizeof(sslSessionEntry_t) * SSL_SESSION_TABLE_SIZE); + + initSessionEntryChronList(); +#ifdef USE_MULTITHREADING + psCreateMutex(&sessionTableLock); +#ifdef USE_STATELESS_SESSION_TICKETS + psCreateMutex(&g_sessTicketLock); +#endif /* USE_STATELESS_SESSION_TICKETS */ +#endif /* USE_MULTITHREADING */ +#endif /* USE_SERVER_SIDE_SSL */ + +#ifdef USE_DTLS + matrixDtlsSetPmtu(-1); +#ifdef USE_SERVER_SIDE_SSL + dtlsGenCookieSecret(); +#endif +#endif /* USE_DTLS */ + + return PS_SUCCESS; +} + + +/* + matrixSslClose +*/ +void matrixSslClose(void) +{ +#ifdef USE_SERVER_SIDE_SSL + int32 i; + +#ifdef USE_MULTITHREADING + psLockMutex(&sessionTableLock); +#endif /* USE_MULTITHREADING */ + for (i = 0; i < SSL_SESSION_TABLE_SIZE; i++) { + if (sessionTable[i].inUse > 1) { + psTraceInfo("Warning: closing while session still in use\n"); + } + } + memset(sessionTable, 0x0, + sizeof(sslSessionEntry_t) * SSL_SESSION_TABLE_SIZE); +#ifdef USE_MULTITHREADING + psUnlockMutex(&sessionTableLock); + psDestroyMutex(&sessionTableLock); +#endif /* USE_MULTITHREADING */ +#endif /* USE_SERVER_SIDE_SSL */ + + psCryptoClose(); + *g_config = 'N'; +} + +/******************************************************************************/ +/* + Must call to allocate the key structure now. After which, LoadRsaKeys, + LoadDhParams and/or LoadPskKey can be called + + Memory info: + Caller must free keys with matrixSslDeleteKeys on function success + Caller does not need to free keys on function failure +*/ +int32_t matrixSslNewKeys(sslKeys_t **keys, void *memAllocUserPtr) +{ + psPool_t *pool = NULL; + sslKeys_t *lkeys; + int32_t rc; + + + lkeys = psMalloc(pool, sizeof(sslKeys_t)); + if (lkeys == NULL) { + return PS_MEM_FAIL; + } + memset(lkeys, 0x0, sizeof(sslKeys_t)); + lkeys->pool = pool; + lkeys->poolUserPtr = memAllocUserPtr; + +#if defined(USE_ECC) || defined(REQUIRE_DH_PARAMS) + rc = psCreateMutex(&lkeys->cache.lock); + if (rc < 0) { + psFree(lkeys, pool); + return rc; + } +#endif + *keys = lkeys; + return PS_SUCCESS; +} + +#ifdef USE_ECC +/* User is specifying EC curves that are supported so check that against the + keys they are supporting */ +int32 psTestUserEcID(int32 id, int32 ecFlags) +{ + if (id == 19) { + if (!(ecFlags & IS_SECP192R1)) { + return PS_FAILURE; + } + } else if (id == 21) { + if (!(ecFlags & IS_SECP224R1)) { + return PS_FAILURE; + } + } else if (id == 23) { + if (!(ecFlags & IS_SECP256R1)) { + return PS_FAILURE; + } + } else if (id == 24) { + if (!(ecFlags & IS_SECP384R1)) { + return PS_FAILURE; + } + } else if (id == 25) { + if (!(ecFlags & IS_SECP521R1)) { + return PS_FAILURE; + } + } else if (id == 255) { + if (!(ecFlags & IS_BRAIN224R1)) { + return PS_FAILURE; + } + } else if (id == 26) { + if (!(ecFlags & IS_BRAIN256R1)) { + return PS_FAILURE; + } + } else if (id == 27) { + if (!(ecFlags & IS_BRAIN384R1)) { + return PS_FAILURE; + } + } else if (id == 28) { + if (!(ecFlags & IS_BRAIN512R1)) { + return PS_FAILURE; + } + } else { + return PS_UNSUPPORTED_FAIL; + } + return PS_SUCCESS; +} + +int32 curveIdToFlag(int32 id) +{ + if (id == 19) { + return IS_SECP192R1; + } else if (id == 21) { + return IS_SECP224R1; + } else if (id == 23) { + return IS_SECP256R1; + } else if (id == 24) { + return IS_SECP384R1; + } else if (id == 25) { + return IS_SECP521R1; + } else if (id == 255) { + return IS_BRAIN224R1; + } else if (id == 26) { + return IS_BRAIN256R1; + } else if (id == 27) { + return IS_BRAIN384R1; + } else if (id == 28) { + return IS_BRAIN512R1; + } + return 0; +} + +static int32 testUserEc(int32 ecFlags, const sslKeys_t *keys) +{ + const psEccKey_t *eccKey; + psX509Cert_t *cert; + +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) + if (keys->privKey.type == PS_ECC) { + eccKey = &keys->privKey.key.ecc; + if (psTestUserEcID(eccKey->curve->curveId, ecFlags) < 0) { + return PS_FAILURE; + } + } + + cert = keys->cert; + while (cert) { + if (cert->publicKey.type == PS_ECC) { + eccKey = &cert->publicKey.key.ecc; + if (psTestUserEcID(eccKey->curve->curveId, ecFlags) < 0) { + return PS_FAILURE; + } + } + cert = cert->next; + } +#endif + +#if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH) + cert = keys->CAcerts; + while (cert) { + if (cert->publicKey.type == PS_ECC) { + eccKey = &cert->publicKey.key.ecc; + if (psTestUserEcID(eccKey->curve->curveId, ecFlags) < 0) { + return PS_FAILURE; + } + } + cert = cert->next; + } +#endif + + return PS_SUCCESS; +} +#endif /* USE_ECC */ + + +#ifdef MATRIX_USE_FILE_SYSTEM +#ifdef USE_PKCS12 + +/* Have seen cases where the PKCS#12 files are not in a child-to-parent order */ +static void ReorderCertChain(psX509Cert_t *a_cert) +{ + psX509Cert_t* prevCert = NULL; + psX509Cert_t* nextCert = NULL; + psX509Cert_t* currCert = a_cert; + + while (currCert) { + nextCert = currCert->next; + while (nextCert && memcmp(currCert->issuer.hash, nextCert->subject.hash, + SHA1_HASH_SIZE) != 0) { + prevCert = nextCert; + nextCert = nextCert->next; + + if (nextCert && memcmp(currCert->issuer.hash, + nextCert->subject.hash, SHA1_HASH_SIZE) == 0) { + prevCert->next = nextCert->next; + nextCert->next = currCert->next; + currCert->next = nextCert; + break; + } + } + currCert = currCert->next; + } +} + +/******************************************************************************/ +/* + File should be a binary .p12 or .pfx +*/ +int32 matrixSslLoadPkcs12(sslKeys_t *keys, const unsigned char *certFile, + const unsigned char *importPass, int32 ipasslen, + const unsigned char *macPass, int32 mpasslen, int32 flags) +{ + unsigned char *mPass; + psPool_t *pool; + int32 rc; + + if (keys == NULL) { + return PS_ARG_FAIL; + } + pool = keys->pool; + + if (macPass == NULL) { + mPass = (unsigned char*)importPass; + mpasslen = ipasslen; + } else { + mPass = (unsigned char*)macPass; + } + + if ((rc = psPkcs12Parse(pool, &keys->cert, &keys->privKey, certFile, flags, + (unsigned char*)importPass, ipasslen, mPass, mpasslen)) < 0) { + if (keys->cert) { + psX509FreeCert(keys->cert); + keys->cert = NULL; + } + psClearPubKey(&keys->privKey); + return rc; + } + ReorderCertChain(keys->cert); +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) + if (verifyReadKeys(pool, keys, keys->poolUserPtr) < PS_SUCCESS) { + psTraceInfo("PKCS#12 parse success but material didn't validate\n"); + psX509FreeCert(keys->cert); + psClearPubKey(&keys->privKey); + keys->cert = NULL; + return PS_CERT_AUTH_FAIL; + } +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ + return PS_SUCCESS; +} +#endif /* USE_PKCS12 */ + +/******************************************************************************/ + +#ifdef USE_RSA +int32 matrixSslLoadRsaKeys(sslKeys_t *keys, const char *certFile, + const char *privFile, const char *privPass, const char *CAfile) +{ + return matrixSslLoadKeyMaterial(keys, certFile, privFile, privPass, CAfile, + PS_RSA); + +} +#endif /* USE_RSA */ + +/******************************************************************************/ + +#ifdef USE_ECC +/** + Generate and cache an ephemeral ECC key for later use in ECDHE key exchange. + @param[out] keys Keys structure to hold ephemeral keys + @param[in] curve ECC curve to generate key on, or NULL to generate for all + supported curves. + @param[in] hwCtx Context for hardware crypto. +*/ +int32_t matrixSslGenEphemeralEcKey(sslKeys_t *keys, psEccKey_t *ecc, + const psEccCurve_t *curve, void *hwCtx) +{ +#if ECC_EPHEMERAL_CACHE_USAGE > 0 + psTime_t t; +#endif + int32_t rc; + + psAssert(keys && curve); +#if ECC_EPHEMERAL_CACHE_USAGE > 0 + psGetTime(&t, keys->poolUserPtr); + (void)psLockMutex(&keys->cache.lock); + if (keys->cache.eccPrivKey.curve != curve) { + psTraceStrInfo("Generating ephemeral %s key (new curve)\n", + curve->name); + goto L_REGEN; + } + if (keys->cache.eccPrivKeyUse > ECC_EPHEMERAL_CACHE_USAGE) { + psTraceStrInfo("Generating ephemeral %s key (usage exceeded)\n", + curve->name); + goto L_REGEN; + } + if (psDiffMsecs(keys->cache.eccPrivKeyTime, t, keys->poolUserPtr) > + (1000 * ECC_EPHEMERAL_CACHE_SECONDS)) { + psTraceStrInfo("Generating ephemeral %s key (time exceeded)\n", + curve->name); + goto L_REGEN; + } + keys->cache.eccPrivKeyUse++; + rc = PS_SUCCESS; + if (ecc) { + rc = psEccCopyKey(ecc, &keys->cache.eccPrivKey); + } + (void)psUnlockMutex(&keys->cache.lock); + return rc; +L_REGEN: + if (keys->cache.eccPrivKeyUse) { + /* We use eccPrivKeyUse == 0 as a flag to note the key not allocated */ + psEccClearKey(&keys->cache.eccPrivKey); + keys->cache.eccPrivKeyUse = 0; + } + rc = psEccGenKey(keys->pool, &keys->cache.eccPrivKey, curve, hwCtx); + if (rc < 0) { + (void)psUnlockMutex(&keys->cache.lock); + return rc; + } + keys->cache.eccPrivKeyTime = t; + keys->cache.eccPrivKeyUse = 1; + rc = PS_SUCCESS; + if (ecc) { + rc = psEccCopyKey(ecc, &keys->cache.eccPrivKey); + } + (void)psUnlockMutex(&keys->cache.lock); + return rc; +#else + /* Not using ephemeral caching. */ + if (ecc) { + rc = psEccGenKey(keys->pool, ecc, curve, hwCtx); + return rc; + } + rc = PS_SUCCESS; + return rc; +#endif /* ECC_EPHEMERAL_CACHE_USAGE > 0 */ +} + +/******************************************************************************/ + +int32 matrixSslLoadEcKeys(sslKeys_t *keys, const char *certFile, + const char *privFile, const char *privPass, const char *CAfile) +{ + return matrixSslLoadKeyMaterial(keys, certFile, privFile, privPass, CAfile, + PS_ECC); + +} +#endif /* USE_ECC */ + +#if defined(USE_RSA) || defined(USE_ECC) +static int32 matrixSslLoadKeyMaterial(sslKeys_t *keys, const char *certFile, + const char *privFile, const char *privPass, const char *CAfile, + int32 privKeyType) +{ + psPool_t *pool; + int32 err, flags; + + if (keys == NULL) { + return PS_ARG_FAIL; + } + pool = keys->pool; + +/* + Setting flags to store raw ASN.1 stream for SSL CERTIFICATE message use +*/ + flags = CERT_STORE_UNPARSED_BUFFER; + +#ifdef USE_CLIENT_AUTH +/* + If the CERTIFICATE_REQUEST message will possibly be needed we must + save aside the Distiguished Name portion of the certs for that message. +*/ + flags |= CERT_STORE_DN_BUFFER; +#endif /* USE_CLIENT_AUTH */ + + if (certFile) { +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) + if (keys->cert != NULL) { + return PS_UNSUPPORTED_FAIL; + } + if ((err = psX509ParseCertFile(pool, (char *)certFile, + &keys->cert, flags)) < 0) { + return err; + } + if (keys->cert->authFailFlags) { + psAssert(keys->cert->authFailFlags == PS_CERT_AUTH_FAIL_DATE_FLAG); +#ifdef POSIX /* TODO - implement date check on WIN32, etc. */ + psX509FreeCert(keys->cert); + keys->cert = NULL; + return PS_CERT_AUTH_FAIL_EXTENSION; +#endif + } +#else + psTraceStrInfo("Ignoring %s certFile in matrixSslReadKeys\n", + (char *)certFile); +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ + } +/* + Parse the private key file +*/ + if (privFile) { +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) + /* See if private key already exists */ + if (keys->privKey.keysize > 0) { + if (keys->cert) { + psX509FreeCert(keys->cert); + keys->cert = NULL; + return PS_UNSUPPORTED_FAIL; + } + } +#ifdef USE_RSA + if (privKeyType == PS_RSA) { + psInitPubKey(pool, &keys->privKey, PS_RSA); + if ((err = pkcs1ParsePrivFile(pool, (char *)privFile, + (char *)privPass, &keys->privKey.key.rsa)) < 0) { + if (keys->cert) { + psX509FreeCert(keys->cert); + keys->cert = NULL; + } + return err; + } + keys->privKey.keysize = psRsaSize(&keys->privKey.key.rsa); + } +#endif /* USE_RSA */ +#ifdef USE_ECC + if (privKeyType == PS_ECC) { + psInitPubKey(pool, &keys->privKey, PS_ECC); + if ((err = psEccParsePrivFile(pool, (char *)privFile, + (char *)privPass, &keys->privKey.key.ecc)) < 0) { + if (keys->cert) { + psX509FreeCert(keys->cert); + keys->cert = NULL; + } + return err; + } + keys->privKey.keysize = psEccSize(&keys->privKey.key.ecc); + } +#endif /* USE_ECC */ +#else + psTraceStrInfo("Ignoring %s privFile in matrixSslReadKeys\n", + (char *)privFile); +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ + } + +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) + if (verifyReadKeys(pool, keys, keys->poolUserPtr) < PS_SUCCESS) { + psTraceInfo("Cert parse success but material didn't validate\n"); + psX509FreeCert(keys->cert); + psClearPubKey(&keys->privKey); + keys->cert = NULL; + return PS_CERT_AUTH_FAIL; + } +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ + + /* Not necessary to store binary representations of CA certs */ + flags &= ~CERT_STORE_UNPARSED_BUFFER; + + if (CAfile) { +#if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH) + if (keys->CAcerts != NULL) { + return PS_UNSUPPORTED_FAIL; + } + err = psX509ParseCertFile(pool, (char*)CAfile, &keys->CAcerts, flags); + if (err >= 0) { + if (keys->CAcerts->authFailFlags) { + /* This should be the only no err, FailFlags case currently */ + psAssert(keys->CAcerts->authFailFlags == + PS_CERT_AUTH_FAIL_DATE_FLAG); +#ifdef POSIX /* TODO - implement date check on WIN32, etc. */ + psX509FreeCert(keys->CAcerts); + keys->CAcerts = NULL; + err = PS_CERT_AUTH_FAIL_EXTENSION; +#endif + } + } + if (err < 0) { +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) + if (keys->cert) { + psX509FreeCert(keys->cert); + keys->cert = NULL; + } + psClearPubKey(&keys->privKey); +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ + return err; + } +#else + psTraceStrInfo("Ignoring %s CAfile in matrixSslReadKeys\n", (char*)CAfile); +#endif /* USE_CLIENT_SIDE_SSL || USE_CLIENT_AUTH */ + } + + return PS_SUCCESS; +} + +#endif /* USE_RSA || USE_ECC */ +#endif /* MATRIX_USE_FILE_SYSTEM */ + +/******************************************************************************/ +/* + Memory buffer versions of ReadKeys + + This function supports cert chains and multiple CAs. Just need to + string them together and let psX509ParseCert handle it +*/ +#ifdef USE_RSA +int32 matrixSslLoadRsaKeysMem(sslKeys_t *keys, const unsigned char *certBuf, + int32 certLen, const unsigned char *privBuf, int32 privLen, + const unsigned char *CAbuf, int32 CAlen) +{ + return matrixSslLoadKeyMaterialMem(keys, certBuf, certLen, privBuf, privLen, + CAbuf, CAlen, PS_RSA); + +} +#endif /* USE_RSA */ + +#ifdef USE_ECC +int32 matrixSslLoadEcKeysMem(sslKeys_t *keys, const unsigned char *certBuf, + int32 certLen, const unsigned char *privBuf, int32 privLen, + const unsigned char *CAbuf, int32 CAlen) +{ + return matrixSslLoadKeyMaterialMem(keys, certBuf, certLen, privBuf, privLen, + CAbuf, CAlen, PS_ECC); + +} + +#endif /* USE_ECC */ + +#if defined(USE_RSA) || defined(USE_ECC) +static int32 matrixSslLoadKeyMaterialMem(sslKeys_t *keys, + const unsigned char *certBuf, int32 certLen, + const unsigned char *privBuf, + int32 privLen, const unsigned char *CAbuf, int32 CAlen, + int32 privKeyType) +{ + psPool_t *pool; + int32 err, flags = 0; + + if (keys == NULL) { + return PS_ARG_FAIL; + } + pool = keys->pool; + +/* + Setting flags to store raw ASN.1 stream for SSL CERTIFICATE message use +*/ + flags = CERT_STORE_UNPARSED_BUFFER; + +#ifdef USE_CLIENT_AUTH +/* + Setting flag to store raw ASN.1 DN stream for CERTIFICATE_REQUEST +*/ + flags |= CERT_STORE_DN_BUFFER; +#endif /* USE_CLIENT_AUTH */ + + if (certBuf) { +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) + if (keys->cert != NULL) { + psTraceInfo("WARNING: An identity certificate already exists\n"); + return PS_UNSUPPORTED_FAIL; + } + if ((err = psX509ParseCert(pool, (unsigned char *)certBuf, + (uint32)certLen, &keys->cert, flags)) < 0) { + psX509FreeCert(keys->cert); + keys->cert = NULL; + return err; + } +#else + psTraceInfo("Ignoring certBuf in matrixSslReadKeysMem\n"); +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ + } + + if (privBuf) { +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) +#ifdef USE_RSA + if (privKeyType == PS_RSA) { + psInitPubKey(pool, &keys->privKey, PS_RSA); + if ((err = psRsaParsePkcs1PrivKey(pool, privBuf, + privLen, &keys->privKey.key.rsa)) < 0) { +#ifdef USE_PKCS8 + /* Attempt a PKCS#8 but mem parse doesn't take password */ + if ((err = pkcs8ParsePrivBin(pool, (unsigned char*)privBuf, + (uint32)privLen, NULL, &keys->privKey)) < 0) { + psX509FreeCert(keys->cert); keys->cert = NULL; + return err; + } +#else + psX509FreeCert(keys->cert); keys->cert = NULL; + return err; +#endif + } + keys->privKey.keysize = psRsaSize(&keys->privKey.key.rsa); + } +#endif /* USE_RSA */ +#ifdef USE_ECC + if (privKeyType == PS_ECC) { + psInitPubKey(pool, &keys->privKey, PS_ECC); + if ((err = psEccParsePrivKey(pool, (unsigned char*)privBuf, + (uint32)privLen, &keys->privKey.key.ecc, NULL)) < 0) { +#ifdef USE_PKCS8 + /* Attempt a PKCS#8 but mem parse doesn't take password */ + if ((err = pkcs8ParsePrivBin(pool, (unsigned char*)privBuf, + (uint32)privLen, NULL, &keys->privKey)) < 0) { + psX509FreeCert(keys->cert); keys->cert = NULL; + return err; + } +#else + psX509FreeCert(keys->cert); keys->cert = NULL; + return err; +#endif + } + keys->privKey.keysize = psEccSize(&keys->privKey.key.ecc); + } +#endif /* USE_ECC */ +#else + psTraceInfo("Ignoring privBuf in matrixSslReadKeysMem\n"); +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ + } + +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) + if (verifyReadKeys(pool, keys, keys->poolUserPtr) < PS_SUCCESS) { + psX509FreeCert(keys->cert); + psClearPubKey(&keys->privKey); + keys->cert = NULL; + return PS_CERT_AUTH_FAIL; + } +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ + +/* + Not necessary to store binary representations of CA certs +*/ + flags &= ~CERT_STORE_UNPARSED_BUFFER; + + if (CAbuf) { +#if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH) + if (keys->CAcerts != NULL) { + return PS_UNSUPPORTED_FAIL; + } + if ((err = psX509ParseCert(pool, (unsigned char*)CAbuf, (uint32)CAlen, + &keys->CAcerts, flags)) < 0) { +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) + psClearPubKey(&keys->privKey); + psX509FreeCert(keys->cert); + psX509FreeCert(keys->CAcerts); + keys->cert = keys->CAcerts = NULL; +#endif + return err; + } +#else + psTraceInfo("Ignoring CAbuf in matrixSslReadKeysMem\n"); +#endif /* USE_CLIENT_SIDE_SSL || USE_CLIENT_AUTH */ + } + + return PS_SUCCESS; +} +#endif /* USE_RSA || USE_ECC */ + + +#if defined(USE_OCSP) && defined(USE_SERVER_SIDE_SSL) +int32_t matrixSslLoadOCSPResponse(sslKeys_t *keys, + const unsigned char *OCSPResponseBuf, uint16_t OCSPResponseBufLen) +{ + psPool_t *pool; + + if (keys == NULL || OCSPResponseBuf == NULL || OCSPResponseBufLen == 0) { + return PS_ARG_FAIL; + } + pool = keys->pool; + + /* Overwrite/Update any response being set */ + if (keys->OCSPResponseBuf != NULL) { + psFree(keys->OCSPResponseBuf, pool); + keys->OCSPResponseBufLen = 0; + } + + keys->OCSPResponseBufLen = OCSPResponseBufLen; + if ((keys->OCSPResponseBuf = psMalloc(pool, OCSPResponseBufLen)) == NULL) { + return PS_MEM_FAIL; + } + + memcpy(keys->OCSPResponseBuf, OCSPResponseBuf, OCSPResponseBufLen); + return PS_SUCCESS; +} +#endif /* USE_OCSP && USE_SERVER_SIDE_SSL */ + +/******************************************************************************/ +/* + This will free the struct and any key material that was loaded via: + matrixSslLoadRsaKeys + matrixSslLoadEcKeys + matrixSslLoadDhParams + matrixSslLoadPsk + matrixSslLoadOCSPResponse +*/ +void matrixSslDeleteKeys(sslKeys_t *keys) +{ +#ifdef USE_PSK_CIPHER_SUITE + psPsk_t *psk, *next; +#endif /* USE_PSK_CIPHER_SUITE */ +#if defined(USE_STATELESS_SESSION_TICKETS) && defined(USE_SERVER_SIDE_SSL) + psSessionTicketKeys_t *tick, *nextTick; +#endif + + if (keys == NULL) { + return; + } +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) + if (keys->cert) { + psX509FreeCert(keys->cert); + } + + psClearPubKey(&keys->privKey); +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ + +#if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH) + if (keys->CAcerts) { + psX509FreeCert(keys->CAcerts); + } +#endif /* USE_CLIENT_SIDE_SSL || USE_CLIENT_AUTH */ +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + +#ifdef REQUIRE_DH_PARAMS + pkcs3ClearDhParams(&keys->dhParams); +#endif /* REQUIRE_DH_PARAMS */ + +#ifdef USE_PSK_CIPHER_SUITE + if (keys->pskKeys) { + psk = keys->pskKeys; + while (psk) { + psFree(psk->pskKey, keys->pool); + psFree(psk->pskId, keys->pool); + next = psk->next; + psFree(psk, keys->pool); + psk = next; + } + } +#endif /* USE_PSK_CIPHER_SUITE */ + +#if defined(USE_STATELESS_SESSION_TICKETS) && defined(USE_SERVER_SIDE_SSL) + if (keys->sessTickets) { + tick = keys->sessTickets; + while (tick) { + nextTick = tick->next; + psFree(tick, keys->pool); + tick = nextTick; + } + } +#endif + +#if defined(USE_ECC) || defined(REQUIRE_DH_PARAMS) + psDestroyMutex(&keys->cache.lock); +#ifdef USE_ECC + if (keys->cache.eccPrivKeyUse > 0) { + psEccClearKey(&keys->cache.eccPrivKey); + psEccClearKey(&keys->cache.eccPubKey); + } +#endif + /* Remainder of structure is cleared below */ +#endif + +#if defined(USE_OCSP) && defined(USE_SERVER_SIDE_SSL) + if (keys->OCSPResponseBuf != NULL) { + psFree(keys->OCSPResponseBuf, keys->pool); + keys->OCSPResponseBufLen = 0; + } +#endif + + memzero_s(keys, sizeof(sslKeys_t)); + psFree(keys, NULL); +} + +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) +#if defined(USE_RSA) || defined(USE_ECC) +/* + Validate the cert chain and the private key for the material passed + to matrixSslReadKeys. Good to catch any user certifiate errors as + soon as possible +*/ +static int32 verifyReadKeys(psPool_t *pool, sslKeys_t *keys, void *poolUserPtr) +{ +#ifdef USE_CERT_PARSE + psX509Cert_t *tmp, *found; +#endif + + if (keys->cert == NULL && keys->privKey.type == 0) { + return PS_SUCCESS; + } +/* + Not allowed to have a certficate with no matching private key or + private key with no cert to match with +*/ + if (keys->cert != NULL && keys->privKey.type == 0) { + psTraceInfo("No private key given to matrixSslReadKeys cert\n"); + return PS_CERT_AUTH_FAIL; + } + if (keys->privKey.type != 0 && keys->cert == NULL) { + psTraceInfo("No cert given with private key to matrixSslReadKeys\n"); + return PS_CERT_AUTH_FAIL; + } +#ifdef USE_CERT_PARSE +/* + If this is a chain, we can validate it here with psX509AuthenticateCert + Don't check the error return code from this call because the chaining + usage restrictions will test parent-most cert for self-signed. + + But we can look at 'authStatus' on all but the final cert to see + if the rest looks good +*/ + if (keys->cert != NULL && keys->cert->next != NULL) { + found = NULL; + psX509AuthenticateCert(pool, keys->cert, NULL, &found, NULL, + poolUserPtr); + tmp = keys->cert; + while (tmp->next != NULL) { + if (tmp->authStatus != PS_TRUE) { + psTraceInfo("Failed to authenticate cert chain\n"); + return PS_CERT_AUTH_FAIL; + } + tmp = tmp->next; + } + } + +#ifdef USE_RSA + if (keys->privKey.type == PS_RSA) { + if (psRsaCmpPubKey(&keys->privKey.key.rsa, + &keys->cert->publicKey.key.rsa) < 0) { + psTraceInfo("Private key doesn't match cert\n"); + return PS_CERT_AUTH_FAIL; + } + } +#endif /* USE_RSA */ +#endif /* USE_CERT_PARSE */ + return PS_SUCCESS; +} +#endif /* USE_RSA || USE_ECC */ +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ +/******************************************************************************/ + +#ifdef REQUIRE_DH_PARAMS +/******************************************************************************/ +/* + User level API to assign the DH parameter file to the server application. +*/ +#ifdef MATRIX_USE_FILE_SYSTEM +int32 matrixSslLoadDhParams(sslKeys_t *keys, const char *paramFile) +{ + if (keys == NULL) { + return PS_ARG_FAIL; + } + return pkcs3ParseDhParamFile(keys->pool, (char*)paramFile, &keys->dhParams); +} +#endif /* MATRIX_USE_FILE_SYSTEM */ + +/******************************************************************************/ +int32 matrixSslLoadDhParamsMem(sslKeys_t *keys, const unsigned char *dhBin, + int32 dhBinLen) +{ + if (keys == NULL) { + return PS_ARG_FAIL; + } + return pkcs3ParseDhParamBin(keys->pool, (unsigned char*)dhBin, dhBinLen, + &keys->dhParams); +} +#endif /* REQUIRE_DH_PARAMS */ + +/******************************************************************************/ +/* + New SSL protocol context + This structure is associated with a single SSL connection. Each socket + using SSL should be associated with a new SSL context. + + certBuf and privKey ARE NOT duplicated within the server context, in order + to minimize memory usage with multiple simultaneous requests. They must + not be deleted by caller until all server contexts using them are deleted. +*/ +int32 matrixSslNewSession(ssl_t **ssl, const sslKeys_t *keys, + sslSessionId_t *session, sslSessOpts_t *options) +{ + psPool_t *pool = NULL; + ssl_t *lssl; + int32_t specificVersion, flags; +#ifdef USE_STATELESS_SESSION_TICKETS + uint32_t i; +#endif + + /* SERVER_SIDE and CLIENT_AUTH and others will have been added to + versionFlag by callers */ + flags = options->versionFlag; + +/* + First API level chance to make sure a user is not attempting to use + client or server support that was not built into this library compile +*/ +#ifndef USE_SERVER_SIDE_SSL + if (flags & SSL_FLAGS_SERVER) { + psTraceInfo("SSL_FLAGS_SERVER passed to matrixSslNewSession but MatrixSSL lib was not compiled with server support\n"); + return PS_ARG_FAIL; + } +#endif + +#ifndef USE_CLIENT_SIDE_SSL + if (!(flags & SSL_FLAGS_SERVER)) { + psTraceInfo("SSL_FLAGS_SERVER was not passed to matrixSslNewSession but MatrixSSL was not compiled with client support\n"); + return PS_ARG_FAIL; + } +#endif + +#ifndef USE_CLIENT_AUTH + if (flags & SSL_FLAGS_CLIENT_AUTH) { + psTraceInfo("SSL_FLAGS_CLIENT_AUTH passed to matrixSslNewSession but MatrixSSL was not compiled with USE_CLIENT_AUTH enabled\n"); + return PS_ARG_FAIL; + } +#endif + + if (flags & SSL_FLAGS_SERVER) { +#ifndef USE_PSK_CIPHER_SUITE + if (keys == NULL) { + /* TODO: test not correct if coming from matrixSslNewServer */ + psTraceInfo("NULL keys parameter passed to matrixSslNewSession\n"); + return PS_ARG_FAIL; + } +#endif /* USE_PSK_CIPHER_SUITE */ + if (session != NULL) { + psTraceInfo("Ignoring session parameter to matrixSslNewSession\n"); + } + } + + if (flags & SSL_FLAGS_INTERCEPTOR) { + psTraceInfo("SSL_FLAGS_INTERCEPTOR not supported\n"); + return PS_ARG_FAIL; + } + + + lssl = psMalloc(pool, sizeof(ssl_t)); + if (lssl == NULL) { + psTraceInfo("Out of memory for ssl_t in matrixSslNewSession\n"); + return PS_MEM_FAIL; + } + memset(lssl, 0x0, sizeof(ssl_t)); + lssl->memAllocPtr = options->memAllocPtr; + +#ifdef USE_ECC + /* If user specified EC curves they support, let's check that against + the key material they provided so there are no conflicts. Don't + need to test against default compiled-in curves because the keys + would not have loaded at all */ + if (options->ecFlags) { + if (testUserEc(options->ecFlags, keys) < 0) { + psTraceIntInfo("ERROR: Only EC 0x%x specified in options.ecFlags ", + options->ecFlags); + psTraceInfo("but other curves were found in key material\n"); + psFree(lssl, pool); + return PS_ARG_FAIL; + } + lssl->ecInfo.ecFlags = options->ecFlags; + } else { + lssl->ecInfo.ecFlags = compiledInEcFlags(); + } +#endif + + +/* + Data buffers +*/ + lssl->bufferPool = options->bufferPool; + lssl->outsize = SSL_DEFAULT_OUT_BUF_SIZE; +#ifdef USE_DTLS + if (flags & SSL_FLAGS_DTLS) { + lssl->outsize = matrixDtlsGetPmtu(); + } +#endif /* USE_DTLS */ + + /* Standard software implementation */ + lssl->outbuf = psMalloc(lssl->bufferPool, lssl->outsize); + + if (lssl->outbuf == NULL) { + psTraceInfo("Buffer pool is too small\n"); + psFree(lssl, pool); + return PS_MEM_FAIL; + } + lssl->insize = SSL_DEFAULT_IN_BUF_SIZE; +#ifdef USE_DTLS + if (flags & SSL_FLAGS_DTLS) { + lssl->insize = matrixDtlsGetPmtu(); + } +#endif /* USE_DTLS */ + lssl->inbuf = psMalloc(lssl->bufferPool, lssl->insize); + if (lssl->inbuf == NULL) { + psTraceInfo("Buffer pool is too small\n"); + psFree(lssl->outbuf, lssl->bufferPool); + psFree(lssl, pool); + return PS_MEM_FAIL; + } + + lssl->sPool = pool; + lssl->keys = (sslKeys_t*)keys; + lssl->cipher = sslGetCipherSpec(lssl, SSL_NULL_WITH_NULL_NULL); + sslActivateReadCipher(lssl); + sslActivateWriteCipher(lssl); + + lssl->recordHeadLen = SSL3_HEADER_LEN; + lssl->hshakeHeadLen = SSL3_HANDSHAKE_HEADER_LEN; + +#ifdef SSL_REHANDSHAKES_ENABLED + lssl->rehandshakeCount = DEFAULT_RH_CREDITS; +#endif /* SSL_REHANDSHAKES_ENABLED */ + +#ifdef USE_DTLS + if (flags & SSL_FLAGS_DTLS) { + lssl->flags |= SSL_FLAGS_DTLS; + lssl->recordHeadLen += DTLS_HEADER_ADD_LEN; + lssl->hshakeHeadLen += DTLS_HEADER_ADD_LEN; + lssl->pmtu = matrixDtlsGetPmtu(); +#ifdef USE_CLIENT_SIDE_SSL + lssl->haveCookie = 0; +#endif + lssl->flightDone = 0; + lssl->appDataExch = 0; + lssl->lastMsn = -1; + dtlsInitFrag(lssl); + } +#endif /* USE_DTLS */ + + + if (flags & SSL_FLAGS_SERVER) { + lssl->flags |= SSL_FLAGS_SERVER; +/* + Client auth can only be requested by server, not set by client +*/ + if (flags & SSL_FLAGS_CLIENT_AUTH) { + lssl->flags |= SSL_FLAGS_CLIENT_AUTH; + } + lssl->hsState = SSL_HS_CLIENT_HELLO; + + /* Is caller requesting specific protocol version for this client? + Make sure it's enabled and use specificVersion var for err */ + specificVersion = 0; + if (flags & SSL_FLAGS_SSLV3) { +#ifndef DISABLE_SSLV3 + lssl->majVer = SSL3_MAJ_VER; + lssl->minVer = SSL3_MIN_VER; +#else + specificVersion = 1; +#endif + } + + if (flags & SSL_FLAGS_TLS_1_0) { +#ifdef USE_TLS +#ifndef DISABLE_TLS_1_0 + lssl->majVer = TLS_MAJ_VER; + lssl->minVer = TLS_MIN_VER; +#else + specificVersion = 1; /* TLS enabled but TLS_1_0 disabled */ +#endif +#else + specificVersion = 1; /* TLS not even enabled */ +#endif + } + + if (flags & SSL_FLAGS_TLS_1_1) { +#ifdef USE_TLS_1_1 +#ifndef DISABLE_TLS_1_1 + lssl->majVer = TLS_MAJ_VER; + lssl->minVer = TLS_1_1_MIN_VER; +#else + specificVersion = 1; /* TLS_1_1 enabled but TLS_1_1 disabled */ +#endif +#else + specificVersion = 1; /* TLS not even enabled */ +#endif + } + + if (flags & SSL_FLAGS_TLS_1_2) { +#ifdef USE_TLS_1_2 + lssl->majVer = TLS_MAJ_VER; + lssl->minVer = TLS_1_2_MIN_VER; +#else + specificVersion = 1; /* TLS_1_2 disabled */ +#endif + } + + if (specificVersion) { + psTraceInfo("ERROR: protocol version isn't compiled into matrix\n"); + matrixSslDeleteSession(lssl); + return PS_ARG_FAIL; + } + +#ifdef USE_DTLS + /* FLAGS_DTLS used in conjuction with specific 1.1 or 1.2 protocol */ + if (flags & SSL_FLAGS_DTLS) { + if (lssl->majVer) { + if (lssl->minVer == SSL3_MIN_VER || lssl->minVer == TLS_MIN_VER) + { + psTraceInfo("ERROR: Can't use SSLv3 or TLS1.0 with DTLS\n"); + matrixSslDeleteSession(lssl); + return PS_ARG_FAIL; + } + lssl->majVer = DTLS_MAJ_VER; + if (lssl->minVer == TLS_1_2_MIN_VER) { + lssl->minVer = DTLS_1_2_MIN_VER; + } else if (lssl->minVer == TLS_1_1_MIN_VER) { + lssl->minVer = DTLS_MIN_VER; + } else { + psTraceInfo("ERROR: Protocol version parse error\n"); + matrixSslDeleteSession(lssl); + return PS_ARG_FAIL; + } + } + } +#endif + + } else { +/* + Client is first to set protocol version information based on + compile and/or the 'flags' parameter so header information in + the handshake messages will be correctly set. + + Look for specific version first... but still have to make sure library + has been compiled to support it +*/ + specificVersion = 0; + + if (flags & SSL_FLAGS_SSLV3) { +#ifndef DISABLE_SSLV3 + lssl->majVer = SSL3_MAJ_VER; + lssl->minVer = SSL3_MIN_VER; + specificVersion = 1; +#else + specificVersion = 2; +#endif + } + + if (flags & SSL_FLAGS_TLS_1_0) { +#ifdef USE_TLS +#ifndef DISABLE_TLS_1_0 + lssl->majVer = TLS_MAJ_VER; + lssl->minVer = TLS_MIN_VER; + lssl->flags |= SSL_FLAGS_TLS; + specificVersion = 1; +#else + specificVersion = 2; /* TLS enabled but TLS_1_0 disabled */ +#endif +#else + specificVersion = 2; /* TLS not even enabled */ +#endif + } + + if (flags & SSL_FLAGS_TLS_1_1) { +#ifdef USE_TLS_1_1 +#ifndef DISABLE_TLS_1_1 + lssl->majVer = TLS_MAJ_VER; + lssl->minVer = TLS_1_1_MIN_VER; + lssl->flags |= SSL_FLAGS_TLS | SSL_FLAGS_TLS_1_1; + specificVersion = 1; +#else + specificVersion = 2; /* TLS_1_1 enabled but TLS_1_1 disabled */ +#endif +#else + specificVersion = 2; /* TLS not even enabled */ +#endif + } + + if (flags & SSL_FLAGS_TLS_1_2) { +#ifdef USE_TLS_1_2 + lssl->majVer = TLS_MAJ_VER; + lssl->minVer = TLS_1_2_MIN_VER; + lssl->flags |= SSL_FLAGS_TLS | SSL_FLAGS_TLS_1_1 | SSL_FLAGS_TLS_1_2; + specificVersion = 1; +#else + specificVersion = 2; /* TLS_1_2 disabled */ +#endif + } + + if (specificVersion == 2) { + psTraceInfo("ERROR: protocol version isn't compiled into matrix\n"); + matrixSslDeleteSession(lssl); + return PS_ARG_FAIL; + } + + if (specificVersion == 0) { + /* Highest available if not specified (or not legal value) */ +#ifdef USE_TLS +#ifndef DISABLE_TLS_1_0 + lssl->majVer = TLS_MAJ_VER; + lssl->minVer = TLS_MIN_VER; +#endif +#if defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1) + lssl->majVer = TLS_MAJ_VER; + lssl->minVer = TLS_1_1_MIN_VER; + lssl->flags |= SSL_FLAGS_TLS_1_1; +#endif /* USE_TLS_1_1 */ +#ifdef USE_TLS_1_2 + lssl->majVer = TLS_MAJ_VER; + lssl->minVer = TLS_1_2_MIN_VER; + lssl->flags |= SSL_FLAGS_TLS_1_2 | SSL_FLAGS_TLS_1_1; +#endif + if (lssl->majVer == 0) { + /* USE_TLS enabled but all DISABLE_TLS versions are enabled so + use SSLv3. Compile time tests would catch if no versions + are enabled at all */ + lssl->majVer = SSL3_MAJ_VER; + lssl->minVer = SSL3_MIN_VER; + } else { + lssl->flags |= SSL_FLAGS_TLS; + } + +#ifdef USE_DTLS + /* ssl->flags will have already been set above. Just set version */ + if (flags & SSL_FLAGS_DTLS) { + lssl->minVer = DTLS_MIN_VER; + lssl->majVer = DTLS_MAJ_VER; +#ifdef USE_TLS_1_2 + lssl->minVer = DTLS_1_2_MIN_VER; +#endif + } +#endif /* USE_DTLS */ + +#else /* USE_TLS */ + lssl->majVer = SSL3_MAJ_VER; + lssl->minVer = SSL3_MIN_VER; +#endif /* USE_TLS */ + } /* end non-specific version */ + +#ifdef USE_DTLS + if (flags & SSL_FLAGS_DTLS && specificVersion == 1) { + lssl->majVer = DTLS_MAJ_VER; + if (lssl->minVer == TLS_1_2_MIN_VER) { + lssl->minVer = DTLS_1_2_MIN_VER; + } else if (lssl->minVer == TLS_1_1_MIN_VER) { + lssl->minVer = DTLS_MIN_VER; + } else { + psTraceInfo("ERROR: DTLS must be TLS 1.1 or TLS 1.2\n"); + matrixSslDeleteSession(lssl); + return PS_ARG_FAIL; + } + } +#endif + + lssl->hsState = SSL_HS_SERVER_HELLO; + if (session != NULL && session->cipherId != SSL_NULL_WITH_NULL_NULL) { + lssl->cipher = sslGetCipherSpec(lssl, session->cipherId); + if (lssl->cipher == NULL) { + psTraceInfo("Invalid session id to matrixSslNewSession\n"); + } else { + memcpy(lssl->sec.masterSecret, session->masterSecret, + SSL_HS_MASTER_SIZE); + lssl->sessionIdLen = SSL_MAX_SESSION_ID_SIZE; + memcpy(lssl->sessionId, session->id, SSL_MAX_SESSION_ID_SIZE); +#ifdef USE_STATELESS_SESSION_TICKETS + /* Possible no sessionId here at all if tickets used instead. + Will know if all 0s */ + lssl->sessionIdLen = 0; + for (i = 0; i < SSL_MAX_SESSION_ID_SIZE; i++) { + if (session->id[i] != 0x0) { + lssl->sessionIdLen = SSL_MAX_SESSION_ID_SIZE; + break; + } + } +#endif + } + } + lssl->sid = session; + } + /* Clear these to minimize damage on a protocol parsing bug */ + memset(lssl->inbuf, 0x0, lssl->insize); + memset(lssl->outbuf, 0x0, lssl->outsize); + lssl->err = SSL_ALERT_NONE; + lssl->encState = SSL_HS_NONE; + lssl->decState = SSL_HS_NONE; + *ssl = lssl; + return PS_SUCCESS; +} + + +/******************************************************************************/ +/* + Delete an SSL session. Some information on the session may stay around + in the session resumption cache. + SECURITY - We memset relevant values to zero before freeing to reduce + the risk of our keys floating around in memory after we're done. +*/ +void matrixSslDeleteSession(ssl_t *ssl) +{ + + if (ssl == NULL) { + return; + } + + + ssl->flags |= SSL_FLAGS_CLOSED; + + /* Synchronize all digests, in case some of them have been updated, but + not finished. */ +#ifdef USE_TLS_1_2 + psSha256Sync(NULL, 1); +#else /* !USE_TLS_1_2 */ + psSha1Sync(NULL, 1); +#endif /* USE_TLS_1_2 */ + + +/* + If we have a sessionId, for servers we need to clear the inUse flag in + the session cache so the ID can be replaced if needed. In the client case + the caller should have called matrixSslGetSessionId already to copy the + master secret and sessionId, so free it now. + + In all cases except a successful updateSession call on the server, the + master secret must be freed. +*/ +#ifdef USE_SERVER_SIDE_SSL + if (ssl->sessionIdLen > 0 && (ssl->flags & SSL_FLAGS_SERVER)) { + matrixUpdateSession(ssl); + } +#ifdef USE_STATELESS_SESSION_TICKETS + if ((ssl->flags & SSL_FLAGS_SERVER) && ssl->sid) { + psFree(ssl->sid, ssl->sPool); + ssl->sid = NULL; + } +#endif +#endif /* USE_SERVER_SIDE_SSL */ + + ssl->sessionIdLen = 0; + + if (ssl->expectedName) { + psFree(ssl->expectedName, ssl->sPool); + } +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH) + if (ssl->sec.cert) { + psX509FreeCert(ssl->sec.cert); + ssl->sec.cert = NULL; + } + +#endif /* USE_CLIENT_SIDE_SSL || USE_CLIENT_AUTH */ +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + +#ifdef REQUIRE_DH_PARAMS + if (ssl->sec.dhP) { + psFree(ssl->sec.dhP, ssl->hsPool); ssl->sec.dhP = NULL; + } + if (ssl->sec.dhG) { + psFree(ssl->sec.dhG, ssl->hsPool); ssl->sec.dhG = NULL; + } + if (ssl->sec.dhKeyPub) { + psDhClearKey(ssl->sec.dhKeyPub); + psFree(ssl->sec.dhKeyPub, ssl->hsPool); + ssl->sec.dhKeyPub = NULL; + } + if (ssl->sec.dhKeyPriv) { + psDhClearKey(ssl->sec.dhKeyPriv); + psFree(ssl->sec.dhKeyPriv, ssl->hsPool); + ssl->sec.dhKeyPriv = NULL; + } +#endif /* REQUIRE_DH_PARAMS */ + +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->sec.eccKeyPub) psEccDeleteKey(&ssl->sec.eccKeyPub); + if (ssl->sec.eccKeyPriv) psEccDeleteKey(&ssl->sec.eccKeyPriv); +#endif /* USE_ECC_CIPHER_SUITE */ + +/* + Premaster could also be allocated if this DeleteSession is the result + of a failed handshake. This test is fine since all frees will NULL pointer +*/ + if (ssl->sec.premaster) { + psFree(ssl->sec.premaster, ssl->hsPool); + } + if (ssl->fragMessage) { + psFree(ssl->fragMessage, ssl->hsPool); + } + +#ifdef USE_DTLS +#ifdef USE_CLIENT_SIDE_SSL + if (ssl->cookie) { + psFree(ssl->cookie, ssl->hsPool); + } +#endif + if (ssl->helloExt) { + psFree(ssl->helloExt, ssl->hsPool); + } + dtlsInitFrag(ssl); + if (ssl->ckeMsg) { + psFree(ssl->ckeMsg, ssl->hsPool); + } + if (ssl->certVerifyMsg) { + psFree(ssl->certVerifyMsg, ssl->hsPool); + } +#if defined(USE_PSK_CIPHER_SUITE) && defined(USE_CLIENT_SIDE_SSL) + if (ssl->sec.hint) { + psFree(ssl->sec.hint, ssl->hsPool); + } +#endif +#endif /* USE_DTLS */ + + + +/* + Free the data buffers, clear any remaining user data +*/ + memset(ssl->inbuf, 0x0, ssl->insize); + memset(ssl->outbuf, 0x0, ssl->outsize); + psFree(ssl->outbuf, ssl->bufferPool); + psFree(ssl->inbuf, ssl->bufferPool); + + + freePkaAfter(ssl); + clearFlightList(ssl); + +#ifdef USE_ALPN + if (ssl->alpn) { + psFree(ssl->alpn, ssl->sPool); ssl->alpn = NULL; + } +#endif +/* + The cipher and mac contexts are inline in the ssl structure, so + clearing the structure clears those states as well. +*/ + memset(ssl, 0x0, sizeof(ssl_t)); + psFree(ssl, pool); +} + + +/******************************************************************************/ +/* + Generic session option control for changing already connected sessions. + (ie. rehandshake control). arg param is future for options that may + require a value. +*/ +void matrixSslSetSessionOption(ssl_t *ssl, int32 option, void *arg) +{ + if (option == SSL_OPTION_FULL_HANDSHAKE) { +#ifdef USE_SERVER_SIDE_SSL + if (ssl->flags & SSL_FLAGS_SERVER) { + matrixClearSession(ssl, 1); + } +#endif /* USE_SERVER_SIDE_SSL */ + ssl->sessionIdLen = 0; + memset(ssl->sessionId, 0x0, SSL_MAX_SESSION_ID_SIZE); + } + +#ifdef SSL_REHANDSHAKES_ENABLED + if (option == SSL_OPTION_DISABLE_REHANDSHAKES) { + ssl->rehandshakeCount = -1; + } + /* Get one credit if re-enabling */ + if (option == SSL_OPTION_REENABLE_REHANDSHAKES) { + ssl->rehandshakeCount = 1; + } +#endif + +#if defined(USE_CLIENT_AUTH) && defined(USE_SERVER_SIDE_SSL) + if (ssl->flags & SSL_FLAGS_SERVER) { + if (option == SSL_OPTION_DISABLE_CLIENT_AUTH) { + ssl->flags &= ~SSL_FLAGS_CLIENT_AUTH; + } else if (option == SSL_OPTION_ENABLE_CLIENT_AUTH) { + ssl->flags |= SSL_FLAGS_CLIENT_AUTH; + matrixClearSession(ssl, 1); + } + } +#endif /* USE_CLIENT_AUTH && USE_SERVER_SIDE_SSL */ +} + +/******************************************************************************/ +/* + Will be true if the cipher suite is an 'anon' variety OR if the + user certificate callback returned SSL_ALLOW_ANON_CONNECTION +*/ +void matrixSslGetAnonStatus(ssl_t *ssl, int32 *certArg) +{ + *certArg = ssl->sec.anon; +} + + +#ifdef USE_SSL_INFORMATIONAL_TRACE +void matrixSslPrintHSDetails(ssl_t *ssl) +{ + if (ssl->hsState == SSL_HS_DONE) { + psTraceInfo("\n"); + if (ssl->minVer == SSL3_MIN_VER) { + psTraceInfo("SSL 3.0 "); + } else if (ssl->minVer == TLS_MIN_VER) { + psTraceInfo("TLS 1.0 "); + } else if (ssl->minVer == TLS_1_1_MIN_VER) { + psTraceInfo("TLS 1.1 "); + } else if (ssl->minVer == TLS_1_2_MIN_VER) { + psTraceInfo("TLS 1.2 "); + } +#ifdef USE_DTLS + else if (ssl->minVer == DTLS_1_2_MIN_VER) { + psTraceInfo("DTLS 1.2 "); + } else if (ssl->minVer == DTLS_MIN_VER) { + psTraceInfo("DTLS 1.0 "); + } +#endif + psTraceInfo("connection established: "); + switch (ssl->cipher->ident) { + case SSL_RSA_WITH_NULL_MD5: + psTraceInfo("SSL_RSA_WITH_NULL_MD5\n"); + break; + case SSL_RSA_WITH_NULL_SHA: + psTraceInfo("SSL_RSA_WITH_NULL_SHA\n"); + break; + case SSL_RSA_WITH_RC4_128_MD5: + psTraceInfo("SSL_RSA_WITH_RC4_128_MD5\n"); + break; + case SSL_RSA_WITH_RC4_128_SHA: + psTraceInfo("SSL_RSA_WITH_RC4_128_SHA\n"); + break; + case SSL_RSA_WITH_3DES_EDE_CBC_SHA: + psTraceInfo("SSL_RSA_WITH_3DES_EDE_CBC_SHA\n"); + break; + case TLS_RSA_WITH_AES_128_CBC_SHA: + psTraceInfo("TLS_RSA_WITH_AES_128_CBC_SHA\n"); + break; + case TLS_RSA_WITH_AES_256_CBC_SHA: + psTraceInfo("TLS_RSA_WITH_AES_256_CBC_SHA\n"); + break; + case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + psTraceInfo("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA\n"); + break; + case SSL_DH_anon_WITH_RC4_128_MD5: + psTraceInfo("SSL_DH_anon_WITH_RC4_128_MD5\n"); + break; + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: + psTraceInfo("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA\n"); + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + psTraceInfo("TLS_DHE_RSA_WITH_AES_128_CBC_SHA\n"); + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + psTraceInfo("TLS_DHE_RSA_WITH_AES_256_CBC_SHA\n"); + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: + psTraceInfo("TLS_DHE_RSA_WITH_AES_128_CBC_SHA256\n"); + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: + psTraceInfo("TLS_DHE_RSA_WITH_AES_256_CBC_SHA256\n"); + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + psTraceInfo("TLS_DH_anon_WITH_AES_128_CBC_SHA\n"); + break; + case TLS_DH_anon_WITH_AES_256_CBC_SHA: + psTraceInfo("TLS_DH_anon_WITH_AES_256_CBC_SHA\n"); + break; + case TLS_RSA_WITH_AES_128_CBC_SHA256: + psTraceInfo("TLS_RSA_WITH_AES_128_CBC_SHA256\n"); + break; + case TLS_RSA_WITH_AES_256_CBC_SHA256: + psTraceInfo("TLS_RSA_WITH_AES_256_CBC_SHA256\n"); + break; + case TLS_RSA_WITH_SEED_CBC_SHA: + psTraceInfo("TLS_RSA_WITH_SEED_CBC_SHA\n"); + break; + case TLS_RSA_WITH_IDEA_CBC_SHA: + psTraceInfo("TLS_RSA_WITH_IDEA_CBC_SHA\n"); + break; + case TLS_PSK_WITH_AES_128_CBC_SHA: + psTraceInfo("TLS_PSK_WITH_AES_128_CBC_SHA\n"); + break; + case TLS_PSK_WITH_AES_128_CBC_SHA256: + psTraceInfo("TLS_PSK_WITH_AES_128_CBC_SHA256\n"); + break; + case TLS_PSK_WITH_AES_256_CBC_SHA384: + psTraceInfo("TLS_PSK_WITH_AES_256_CBC_SHA384\n"); + break; + case TLS_PSK_WITH_AES_256_CBC_SHA: + psTraceInfo("TLS_PSK_WITH_AES_256_CBC_SHA\n"); + break; + case TLS_DHE_PSK_WITH_AES_128_CBC_SHA: + psTraceInfo("TLS_DHE_PSK_WITH_AES_128_CBC_SHA\n"); + break; + case TLS_DHE_PSK_WITH_AES_256_CBC_SHA: + psTraceInfo("TLS_DHE_PSK_WITH_AES_256_CBC_SHA\n"); + break; + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + psTraceInfo("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA\n"); + break; + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + psTraceInfo("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA\n"); + break; + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + psTraceInfo("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA\n"); + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + psTraceInfo("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA\n"); + break; + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + psTraceInfo("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA\n"); + break; + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + psTraceInfo("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA\n"); + break; + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + psTraceInfo("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256\n"); + break; + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + psTraceInfo("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384\n"); + break; + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + psTraceInfo("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA\n"); + break; + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + psTraceInfo("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\n"); + break; + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + psTraceInfo("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\n"); + break; + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + psTraceInfo("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA\n"); + break; + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + psTraceInfo("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256\n"); + break; + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + psTraceInfo("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384\n"); + break; + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + psTraceInfo("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256\n"); + break; + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + psTraceInfo("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384\n"); + break; + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + psTraceInfo("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA\n"); + break; + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + psTraceInfo("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256\n"); + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + psTraceInfo("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384\n"); + break; + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + psTraceInfo("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256\n"); + break; + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + psTraceInfo("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384\n"); + break; + case TLS_RSA_WITH_AES_128_GCM_SHA256: + psTraceInfo("TLS_RSA_WITH_AES_128_GCM_SHA256\n"); + break; + case TLS_RSA_WITH_AES_256_GCM_SHA384: + psTraceInfo("TLS_RSA_WITH_AES_256_GCM_SHA384\n"); + break; + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + psTraceInfo("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\n"); + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + psTraceInfo("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\n"); + break; + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + psTraceInfo("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256\n"); + break; + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + psTraceInfo("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384\n"); + break; + case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + psTraceInfo("TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256\n"); + break; + case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + psTraceInfo("TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256\n"); + break; + default: + psTraceIntInfo("!!!! DEFINE ME %d !!!!\n", ssl->cipher->ident); + } + } + return; +} +#endif + +/******************************************************************************/ +/** + @return PS_TRUE if we've completed the SSL handshake. PS_FALSE otherwise. +*/ +int32_t matrixSslHandshakeIsComplete(const ssl_t *ssl) +{ + return (ssl->hsState == SSL_HS_DONE) ? PS_TRUE : PS_FALSE; +} + +#if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH) +/******************************************************************************/ +/* + Set a custom callback to receive the certificate being presented to the + session to perform custom authentication if needed + + NOTE: Must define either USE_CLIENT_SIDE_SSL or USE_CLIENT_AUTH + in matrixConfig.h +*/ +void matrixSslSetCertValidator(ssl_t *ssl, sslCertCb_t certValidator) +{ + if ((ssl != NULL) && (certValidator != NULL)) { +#ifndef USE_ONLY_PSK_CIPHER_SUITE + ssl->sec.validateCert = certValidator; +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + } +} +#endif /* USE_CLIENT_SIDE_SSL || USE_CLIENT_AUTH */ + +#ifdef USE_SERVER_SIDE_SSL +/******************************************************************************/ +/* + Initialize the session table. +*/ +static void initSessionEntryChronList(void) +{ + uint32 i; + DLListInit(&sessionChronList); + /* Assign every session table entry with their ID from the start */ + for (i = 0; i < SSL_SESSION_TABLE_SIZE; i++) { + DLListInsertTail(&sessionChronList, &sessionTable[i].chronList); + sessionTable[i].id[0] = (unsigned char)(i & 0xFF); + sessionTable[i].id[1] = (unsigned char)((i & 0xFF00) >> 8); + sessionTable[i].id[2] = (unsigned char)((i & 0xFF0000) >> 16); + sessionTable[i].id[3] = (unsigned char)((i & 0xFF000000) >> 24); + } +} + +/******************************************************************************/ +/* + Register a session in the session resumption cache. If successful (rc >=0), + the ssl sessionId and sessionIdLength fields will be non-NULL upon + return. +*/ +int32 matrixRegisterSession(ssl_t *ssl) +{ + uint32 i; + sslSessionEntry_t *sess; + DLListEntry *pList; + unsigned char *id; + + if (!(ssl->flags & SSL_FLAGS_SERVER)) { + return PS_FAILURE; + } + +#ifdef USE_STATELESS_SESSION_TICKETS + /* Tickets override the other resumption mechanism */ + if (ssl->sid && + (ssl->sid->sessionTicketState == SESS_TICKET_STATE_RECVD_EXT)) { + /* Have recieved new ticket usage request by client */ + return PS_SUCCESS; + } +#endif + +#ifdef USE_DTLS +/* + Don't reassign a new sessionId if we already have one or we blow the + handshake hash + */ + if ((ssl->flags & SSL_FLAGS_DTLS) && ssl->sessionIdLen > 0) { + /* This is a retransmit case */ + return PS_SUCCESS; + } +#endif + +/* + Iterate the session table, looking for an empty entry (cipher null), or + the oldest entry that is not in use +*/ +#ifdef USE_MULTITHREADING + psLockMutex(&sessionTableLock); +#endif /* USE_MULTITHREADING */ + + if (DLListIsEmpty(&sessionChronList)) { + /* All in use */ +#ifdef USE_MULTITHREADING + psUnlockMutex(&sessionTableLock); +#endif /* USE_MULTITHREADING */ + return PS_LIMIT_FAIL; + + } + /* GetHead Detaches */ + pList = DLListGetHead(&sessionChronList); + sess = DLListGetContainer(pList, sslSessionEntry_t, chronList); + id = sess->id; + i = (id[3] << 24) + (id[2] << 16) + (id[1] << 8) + id[0]; + if (i >= SSL_SESSION_TABLE_SIZE) { +#ifdef USE_MULTITHREADING + psUnlockMutex(&sessionTableLock); +#endif /* USE_MULTITHREADING */ + return PS_LIMIT_FAIL; + } + +/* + Register the incoming masterSecret and cipher, which could still be null, + depending on when we're called. +*/ + memcpy(sessionTable[i].masterSecret, ssl->sec.masterSecret, + SSL_HS_MASTER_SIZE); + sessionTable[i].cipher = ssl->cipher; + sessionTable[i].inUse += 1; +/* + The sessionId is the current serverRandom value, with the first 4 bytes + replaced with the current cache index value for quick lookup later. + FUTURE SECURITY - Should generate more random bytes here for the session + id. We re-use the server random as the ID, which is OK, since it is + sent plaintext on the network, but an attacker listening to a resumed + connection will also be able to determine part of the original server + random used to generate the master key, even if he had not seen it + initially. +*/ + memcpy(sessionTable[i].id + 4, ssl->sec.serverRandom, + min(SSL_HS_RANDOM_SIZE, SSL_MAX_SESSION_ID_SIZE) - 4); + ssl->sessionIdLen = SSL_MAX_SESSION_ID_SIZE; + + memcpy(ssl->sessionId, sessionTable[i].id, SSL_MAX_SESSION_ID_SIZE); +/* + startTime is used to check expiry of the entry + + The versions are stored, because a cached session must be reused + with same SSL version. +*/ + psGetTime(&sessionTable[i].startTime, ssl->userPtr); + sessionTable[i].majVer = ssl->majVer; + sessionTable[i].minVer = ssl->minVer; + + sessionTable[i].extendedMasterSecret = ssl->extFlags.extended_master_secret; + +#ifdef USE_MULTITHREADING + psUnlockMutex(&sessionTableLock); +#endif /* USE_MULTITHREADING */ + return i; +} + +/******************************************************************************/ +/* + Decrement inUse to keep the reference count meaningful +*/ +int32 matrixClearSession(ssl_t *ssl, int32 remove) +{ + unsigned char *id; + uint32 i; + + if (ssl->sessionIdLen <= 0) { + return PS_ARG_FAIL; + } + id = ssl->sessionId; + + i = (id[3] << 24) + (id[2] << 16) + (id[1] << 8) + id[0]; + if (i >= SSL_SESSION_TABLE_SIZE) { + return PS_LIMIT_FAIL; + } +#ifdef USE_MULTITHREADING + psLockMutex(&sessionTableLock); +#endif /* USE_MULTITHREADING */ + sessionTable[i].inUse -= 1; + if (sessionTable[i].inUse == 0) { + DLListInsertTail(&sessionChronList, &sessionTable[i].chronList); + } + +/* + If this is a full removal, actually delete the entry. Also need to + clear any RESUME flag on the ssl connection so a new session + will be correctly registered. +*/ + if (remove) { + memset(ssl->sessionId, 0x0, SSL_MAX_SESSION_ID_SIZE); + ssl->sessionIdLen = 0; + ssl->flags &= ~SSL_FLAGS_RESUMED; + /* Always preserve the id for chronList */ + memset(sessionTable[i].id + 4, 0x0, SSL_MAX_SESSION_ID_SIZE - 4); + memset(sessionTable[i].masterSecret, 0x0, SSL_HS_MASTER_SIZE); + sessionTable[i].extendedMasterSecret = 0; + sessionTable[i].cipher = NULL; + } +#ifdef USE_MULTITHREADING + psUnlockMutex(&sessionTableLock); +#endif /* USE_MULTITHREADING */ + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Look up a session ID in the cache. If found, set the ssl masterSecret + and cipher to the pre-negotiated values +*/ +int32 matrixResumeSession(ssl_t *ssl) +{ + psTime_t accessTime; + unsigned char *id; + uint32 i; + + if (!(ssl->flags & SSL_FLAGS_SERVER)) { + return PS_ARG_FAIL; + } + if (ssl->sessionIdLen <= 0) { + return PS_ARG_FAIL; + } + id = ssl->sessionId; + + i = (id[3] << 24) + (id[2] << 16) + (id[1] << 8) + id[0]; +#ifdef USE_MULTITHREADING + psLockMutex(&sessionTableLock); +#endif /* USE_MULTITHREADING */ + if (i >= SSL_SESSION_TABLE_SIZE || sessionTable[i].cipher == NULL) { +#ifdef USE_MULTITHREADING + psUnlockMutex(&sessionTableLock); +#endif /* USE_MULTITHREADING */ + return PS_LIMIT_FAIL; + } +/* + Id looks valid. Update the access time for expiration check. + Expiration is done on daily basis (86400 seconds) +*/ + psGetTime(&accessTime, ssl->userPtr); + if ((memcmp(sessionTable[i].id, id, + (uint32)min(ssl->sessionIdLen, SSL_MAX_SESSION_ID_SIZE)) != 0) || + (psDiffMsecs(sessionTable[i].startTime, accessTime, ssl->userPtr) > + SSL_SESSION_ENTRY_LIFE) || (sessionTable[i].majVer != ssl->majVer) + || (sessionTable[i].minVer != ssl->minVer)) { +#ifdef USE_MULTITHREADING + psUnlockMutex(&sessionTableLock); +#endif /* USE_MULTITHREADING */ + return PS_FAILURE; + } + + /* Enforce the RFC 7627 rules for resumpion and extended master secret. + Essentially, a resumption must use (or not use) the extended master + secret extension in step with the orginal connection */ + if (sessionTable[i].extendedMasterSecret == 0 && + ssl->extFlags.extended_master_secret == 1) { +#ifdef USE_MULTITHREADING + psUnlockMutex(&sessionTableLock); +#endif /* USE_MULTITHREADING */ + return PS_FAILURE; + } + if (sessionTable[i].extendedMasterSecret == 1 && + ssl->extFlags.extended_master_secret == 0) { +#ifdef USE_MULTITHREADING + psUnlockMutex(&sessionTableLock); +#endif /* USE_MULTITHREADING */ + return PS_FAILURE; + } + + /* Looks good */ + memcpy(ssl->sec.masterSecret, sessionTable[i].masterSecret, + SSL_HS_MASTER_SIZE); + ssl->cipher = sessionTable[i].cipher; + sessionTable[i].inUse += 1; + if (sessionTable[i].inUse == 1) { + DLListRemove(&sessionTable[i].chronList); + } +#ifdef USE_MULTITHREADING + psUnlockMutex(&sessionTableLock); +#endif /* USE_MULTITHREADING */ + + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Update session information in the cache. + This is called when we've determined the master secret and when we're + closing the connection to update various values in the cache. +*/ +int32 matrixUpdateSession(ssl_t *ssl) +{ + unsigned char *id; + uint32 i; + + if (!(ssl->flags & SSL_FLAGS_SERVER)) { + return PS_ARG_FAIL; + } + if (ssl->sessionIdLen == 0) { + /* No table entry. matrixRegisterSession was full of inUse entries */ + return PS_LIMIT_FAIL; + } + id = ssl->sessionId; + i = (id[3] << 24) + (id[2] << 16) + (id[1] << 8) + id[0]; + if (i >= SSL_SESSION_TABLE_SIZE) { + return PS_LIMIT_FAIL; + } +/* + If there is an error on the session, invalidate for any future use +*/ +#ifdef USE_MULTITHREADING + psLockMutex(&sessionTableLock); +#endif /* USE_MULTITHREADING */ + sessionTable[i].inUse += ssl->flags & SSL_FLAGS_CLOSED ? -1 : 0; + if (sessionTable[i].inUse == 0) { + /* End of the line */ + DLListInsertTail(&sessionChronList, &sessionTable[i].chronList); + } + if (ssl->flags & SSL_FLAGS_ERROR) { + memset(sessionTable[i].masterSecret, 0x0, SSL_HS_MASTER_SIZE); + sessionTable[i].cipher = NULL; +#ifdef USE_MULTITHREADING + psUnlockMutex(&sessionTableLock); +#endif /* USE_MULTITHREADING */ + return PS_FAILURE; + } + memcpy(sessionTable[i].masterSecret, ssl->sec.masterSecret, + SSL_HS_MASTER_SIZE); + sessionTable[i].cipher = ssl->cipher; +#ifdef USE_MULTITHREADING + psUnlockMutex(&sessionTableLock); +#endif /* USE_MULTITHREADING */ + return PS_SUCCESS; +} + + +#ifdef USE_STATELESS_SESSION_TICKETS +/* This implementation supports AES-128/256_CBC and HMAC-SHA1/256 */ + +/******************************************************************************/ +/* + Remove a named key from the list. + + NOTE: If this list can get very large the faster DLList API should be + used instead of this single linked list. +*/ +int32 matrixSslDeleteSessionTicketKey(sslKeys_t *keys, unsigned char name[16]) +{ + psSessionTicketKeys_t *lkey, *prev; + +#ifdef USE_MULTITHREADING + psLockMutex(&g_sessTicketLock); +#endif + lkey = keys->sessTickets; + prev = NULL; + while (lkey) { + if (lkey->inUse == 0 && (memcmp(lkey->name, name, 16) == 0)) { + if (prev == NULL) { + /* removing the first in the list */ + if (lkey->next == NULL) { + /* no more list == no more session ticket support */ + psFree(lkey, keys->pool); + keys->sessTickets = NULL; +#ifdef USE_MULTITHREADING + psUnlockMutex(&g_sessTicketLock); +#endif + return PS_SUCCESS; + } + /* first in list but not alone */ + keys->sessTickets = lkey->next; + psFree(lkey, keys->pool); +#ifdef USE_MULTITHREADING + psUnlockMutex(&g_sessTicketLock); +#endif + return PS_SUCCESS; + } + /* Middle of list. Join previous with our next */ + prev->next = lkey->next; + psFree(lkey, keys->pool); +#ifdef USE_MULTITHREADING + psUnlockMutex(&g_sessTicketLock); +#endif + return PS_SUCCESS; + } + prev = lkey; + lkey = lkey->next; + } +#ifdef USE_MULTITHREADING + psUnlockMutex(&g_sessTicketLock); +#endif + return PS_FAILURE; /* not found */ + +} + +/******************************************************************************/ +/* + This will be called on ticket decryption if the named key is not + in the current local list +*/ +void matrixSslSetSessionTicketCallback(sslKeys_t *keys, + int32 (*ticket_cb)(void *, unsigned char[16], short)) +{ + keys->ticket_cb = ticket_cb; +} + +/******************************************************************************/ +/* + The first in the list will be the one used for all newly issued tickets +*/ +int32 matrixSslLoadSessionTicketKeys(sslKeys_t *keys, + const unsigned char name[16], const unsigned char *symkey, + short symkeyLen, const unsigned char *hashkey, short hashkeyLen) +{ + psSessionTicketKeys_t *keylist, *prev; + int32 i = 0; + + /* AES-128 or AES-256 */ + if (symkeyLen != 16 && symkeyLen != 32) { + return PS_LIMIT_FAIL; + } + /* SHA256 only */ + if (hashkeyLen != 32) { + return PS_LIMIT_FAIL; + } + +#ifdef USE_MULTITHREADING + psLockMutex(&g_sessTicketLock); +#endif + if (keys->sessTickets == NULL) { + /* first one */ + keys->sessTickets = psMalloc(keys->pool, sizeof(psSessionTicketKeys_t)); + if (keys->sessTickets == NULL) { +#ifdef USE_MULTITHREADING + psUnlockMutex(&g_sessTicketLock); +#endif + return PS_MEM_FAIL; + } + keylist = keys->sessTickets; + } else { + /* append */ + keylist = keys->sessTickets; + while (keylist) { + prev = keylist; + keylist = keylist->next; + i++; + } + if (i > SSL_SESSION_TICKET_LIST_LEN) { + psTraceInfo("Session ticket list > SSL_SESSION_TICKET_LIST_LEN\n"); +#ifdef USE_MULTITHREADING + psUnlockMutex(&g_sessTicketLock); +#endif + return PS_LIMIT_FAIL; + } + keylist = psMalloc(keys->pool, sizeof(psSessionTicketKeys_t)); + if (keylist == NULL) { +#ifdef USE_MULTITHREADING + psUnlockMutex(&g_sessTicketLock); +#endif + return PS_MEM_FAIL; + } + prev->next = keylist; + } + + memset(keylist, 0x0, sizeof(psSessionTicketKeys_t)); + keylist->hashkeyLen = hashkeyLen; + keylist->symkeyLen = symkeyLen; + memcpy(keylist->name, name, 16); + memcpy(keylist->hashkey, hashkey, hashkeyLen); + memcpy(keylist->symkey, symkey, symkeyLen); +#ifdef USE_MULTITHREADING + psUnlockMutex(&g_sessTicketLock); +#endif + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Size of encrypted session ticket using 16-byte block cipher and SHA-256 +*/ +int32 matrixSessionTicketLen(void) +{ + int32 len = 0; + + /* Master secret, 2 version, 2 cipher suite, 4 timestamp, + 1 extended master secret flag are encypted */ + len += SSL_HS_MASTER_SIZE + 2 + 2 + 4 + 1; + len += psPadLenPwr2(len, 16); + /* Name, IV and MAC plaintext */ + len += 16 + 16 + SHA256_HASH_SIZE; + return len; +} + +/******************************************************************************/ +/* Plaintext Format: + 4 bytes lifetime hint + 2 bytes length of following: + 16 bytes name + 16 bytes IV + + 2 bytes protocol version + 2 bytes cipher suite + 1 byte extended master secret flag + 48 bytes master secret + 4 bytes timestamp + + 32 byte HMAC starting at 'name' +*/ +int32 matrixCreateSessionTicket(ssl_t *ssl, unsigned char *out, int32 *outLen) +{ + int32 len, ticketLen, pad; + uint32 timeSecs; + psTime_t t; + psAesCbc_t ctx; +#ifdef USE_HMAC_SHA256 + psHmacSha256_t dgst; +#else + psHmacSha1_t dgst; +#endif + psSessionTicketKeys_t *keys; + unsigned char *enc, *c = out; + unsigned char randno[AES_IVLEN]; + + ticketLen = matrixSessionTicketLen(); + if ((ticketLen + 6) > *outLen) { + return PS_LIMIT_FAIL; + } + + /* Lifetime hint taken from define in matrixsslConfig.h */ + timeSecs = SSL_SESSION_ENTRY_LIFE / 1000; /* it's in milliseconds */ + *c = (unsigned char)((timeSecs & 0xFF000000) >> 24); c++; + *c = (unsigned char)((timeSecs & 0xFF0000) >> 16); c++; + *c = (unsigned char)((timeSecs & 0xFF00) >> 8); c++; + *c = (unsigned char)(timeSecs & 0xFF); c++; + + /* Len of ticket */ + *c = (ticketLen & 0xFF00) >> 8; c++; + *c = ticketLen & 0xFF; c++; + + /* Do the heavier CPU stuff outside lock */ + timeSecs = psGetTime(&t, ssl->userPtr); + + if (matrixCryptoGetPrngData(randno, AES_IVLEN, ssl->userPtr) < 0) { + psTraceInfo("WARNING: matrixCryptoGetPrngData failed\n"); + } + +#ifdef USE_MULTITHREADING + psLockMutex(&g_sessTicketLock); +#endif + /* Ticket itself */ + keys = ssl->keys->sessTickets; + /* name */ + memcpy(c, keys->name, 16); + c += 16; + memcpy(c, randno, AES_IVLEN); + c += AES_IVLEN; + enc = c; /* encrypt start */ + *c = ssl->majVer; c++; + *c = ssl->minVer; c++; + *c = (ssl->cipher->ident & 0xFF00) >> 8; c++; + *c = ssl->cipher->ident & 0xFF; c++; + /* Need to track if original handshake used extended master secret */ + *c = ssl->extFlags.extended_master_secret; c++; + + memcpy(c, ssl->sec.masterSecret, SSL_HS_MASTER_SIZE); + c += SSL_HS_MASTER_SIZE; + + *c = (unsigned char)((timeSecs & 0xFF000000) >> 24); c++; + *c = (unsigned char)((timeSecs & 0xFF0000) >> 16); c++; + *c = (unsigned char)((timeSecs & 0xFF00) >> 8); c++; + *c = (unsigned char)(timeSecs & 0xFF); c++; + + /* 4 time stamp, 2 version, 2 cipher, 1 extended master secret */ + len = SSL_HS_MASTER_SIZE + 4 + 2 + 2 + 1; + + pad = psPadLenPwr2(len, AES_BLOCKLEN); + c += sslWritePad(c, (unsigned char)pad); len += pad; + /* out + 6 + 16 (name) is pointing at IV */ + psAesInitCBC(&ctx, out + 6 + 16, keys->symkey, keys->symkeyLen, PS_AES_ENCRYPT); + psAesEncryptCBC(&ctx, enc, enc, len); + psAesClearCBC(&ctx); + + /* HMAC starting from the Name */ +#ifdef USE_HMAC_SHA256 + psHmacSha256Init(&dgst, keys->hashkey, keys->hashkeyLen); + psHmacSha256Update(&dgst, out + 6, len + 16 + 16); + psHmacSha256Final(&dgst, c); + *outLen = len + SHA256_HASHLEN + 16 + 16 + 6; +#else + psHmacSha1Init(&dgst, keys->hashkey, keys->hashkeyLen); + psHmacSha1Update(&dgst, out + 6, len + 16 + 16); + psHmacSha1Final(&dgst, c); + *outLen = len + SHA1_HASHLEN + 16 + 16 + 6; +#endif +#ifdef USE_MULTITHREADING + psUnlockMutex(&g_sessTicketLock); +#endif + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + @note careful, this function assumes the lock is on so must relock before + leaving if SUCCESS case. Failure assumes it's unlocked +*/ +static int32 getTicketKeys(ssl_t *ssl, unsigned char *c, + psSessionTicketKeys_t **keys) +{ + psSessionTicketKeys_t *lkey; + unsigned char name[16]; + short cachedTicket = 0; + + /* First 16 bytes are the key name */ + memcpy(name, c, 16); + + *keys = NULL; + /* check our cached list beginning with our own encryption key */ + lkey = ssl->keys->sessTickets; + while (lkey) { + if (memcmp(lkey->name, name, 16) == 0) { + lkey->inUse = 1; + *keys = lkey; + /* Have the key. Invoke callback with SUCCESS */ + if (ssl->keys->ticket_cb) { + cachedTicket++; + break; + } else { + return PS_SUCCESS; + } + } + lkey = lkey->next; + } + /* didn't find it. Ask user */ + if (ssl->keys->ticket_cb) { +#ifdef USE_MULTITHREADING + /* Unlock. Cback will likely call matrixSslLoadSessionTicketKeys */ + psUnlockMutex(&g_sessTicketLock); +#endif + if (ssl->keys->ticket_cb((struct sslKeys_t*)ssl->keys, name, + cachedTicket) < 0) { + lkey->inUse = 0; /* inUse could be set in the odd case where we + found the cached key but the user didn't want to use it. */ + return PS_FAILURE; /* user couldn't find it either */ + } else { + /* found it */ +#ifdef USE_MULTITHREADING + psLockMutex(&g_sessTicketLock); +#endif + if (cachedTicket == 0) { + /* it's been found and added at end of list. confirm this */ + lkey = ssl->keys->sessTickets; + if (lkey == NULL) { +#ifdef USE_MULTITHREADING + psUnlockMutex(&g_sessTicketLock); +#endif + return PS_FAILURE; /* user claims they added, but empty */ + } + while (lkey->next) { + lkey = lkey->next; + } + if (memcmp(lkey->name, c, 16) != 0) { +#ifdef USE_MULTITHREADING + psUnlockMutex(&g_sessTicketLock); +#endif + return PS_FAILURE; /* user claims to have added, but... */ + } + lkey->inUse = 1; + *keys = lkey; + } + return PS_SUCCESS; + } + } + return PS_FAILURE; /* not in list and no callback registered */ +} + +/******************************************************************************/ + +int32 matrixUnlockSessionTicket(ssl_t *ssl, unsigned char *in, int32 inLen) +{ + unsigned char *c, *enc; + unsigned char name[16]; + psSessionTicketKeys_t *keys; +#ifdef USE_HMAC_SHA256 + psHmacSha256_t dgst; + #define L_HASHLEN SHA256_HASHLEN +#else + psHmacSha1_t dgst; + #define L_HASHLEN SHA1_HASHLEN +#endif + unsigned char hash[L_HASHLEN]; + psAesCbc_t ctx; + int32 len; + psTime_t t; + uint32 majVer, minVer, cipherSuite, time, now; + + /* Validate that the incoming ticket is the length we expect */ + if (inLen != matrixSessionTicketLen()) { + return PS_FAILURE; + } + c = in; + len = inLen; +#ifdef USE_MULTITHREADING + psLockMutex(&g_sessTicketLock); +#endif + if (getTicketKeys(ssl, c, &keys) < 0) { + psTraceInfo("No key found for session ticket\n"); + /* We've been unlocked in getTicketKeys */ + return PS_FAILURE; + } + + /* Mac is over the name, IV and encrypted data */ +#ifdef USE_HMAC_SHA256 + psHmacSha256Init(&dgst, keys->hashkey, keys->hashkeyLen); + psHmacSha256Update(&dgst, c, len - L_HASHLEN); + psHmacSha256Final(&dgst, hash); +#else + psHmacSha1Init(&dgst, keys->hashkey, keys->hashkeyLen); + psHmacSha1Update(&dgst, c, len - L_HASHLEN); + psHmacSha1Final(&dgst, hash); +#endif + + memcpy(name, c, 16); + c += 16; + + /* out is pointing at IV */ + psAesInitCBC(&ctx, c, keys->symkey, keys->symkeyLen, PS_AES_DECRYPT); + psAesDecryptCBC(&ctx, c + 16, c + 16, len - 16 - 16 - L_HASHLEN); + psAesClearCBC(&ctx); + keys->inUse = 0; +#ifdef USE_MULTITHREADING + psUnlockMutex(&g_sessTicketLock); +#endif + + /* decrypted marker */ + enc = c + 16; + + c+= (len - 16 - L_HASHLEN); /* already moved past name */ + + if (memcmp(hash, c, L_HASHLEN) != 0) { + psTraceInfo("HMAC check failure on session ticket\n"); + return PS_FAILURE; + } +#undef L_HASHLEN + + majVer = *enc; enc++; + minVer = *enc; enc++; + + /* Match protcol version */ + if (majVer != ssl->majVer || minVer != ssl->minVer) { + psTraceInfo("Protocol check failure on session ticket\n"); + return PS_FAILURE; + } + + cipherSuite = *enc << 8; enc++; + cipherSuite += *enc; enc++; + + /* Force cipher suite */ + if ((ssl->cipher = sslGetCipherSpec(ssl, cipherSuite)) == NULL) { + psTraceInfo("Cipher suite check failure on session ticket\n"); + return PS_FAILURE; + } + + /* Did the initial connection use extended master secret? */ + /* First round of "require" testing can be done here. If server is + set to require extended master secret and this ticket DOES NOT have it + then we can stop resumption right now */ + if (*enc == 0x0 && ssl->extFlags.require_extended_master_secret == 1) { + psTraceInfo("Ticket and master secret derivation methods differ\n"); + return PS_FAILURE; + } + ssl->extFlags.require_extended_master_secret = *enc; enc++; + + /* Set aside masterSecret */ + memcpy(ssl->sid->masterSecret, enc, SSL_HS_MASTER_SIZE); + enc += SSL_HS_MASTER_SIZE; + + /* Check lifetime */ + time = *enc << 24; enc++; + time += *enc << 16; enc++; + time += *enc << 8; enc++; + time += *enc; enc++; + + now = psGetTime(&t, ssl->userPtr); + + if ((now - time) > (SSL_SESSION_ENTRY_LIFE / 1000)) { + /* Expired session ticket. New one will be issued */ + psTraceInfo("Session ticket was expired\n"); + return PS_FAILURE; + } + ssl->sid->cipherId = cipherSuite; + + return PS_SUCCESS; +} +#endif /* USE_STATELESS_SESSION_TICKETS */ +#endif /* USE_SERVER_SIDE_SSL */ + +#ifdef USE_CLIENT_SIDE_SSL +/******************************************************************************/ +/* + Get session information from the ssl structure and populate the given + session structure. Session will contain a copy of the relevant session + information, suitable for creating a new, resumed session. + + NOTE: Must define USE_CLIENT_SIDE_SSL in matrixConfig.h + + sslSessionId_t myClientSession; + + ...&myClientSession +*/ +int32 matrixSslGetSessionId(ssl_t *ssl, sslSessionId_t *session) +{ + + if (ssl == NULL || ssl->flags & SSL_FLAGS_SERVER || session == NULL) { + return PS_ARG_FAIL; + } + + if (ssl->cipher != NULL && ssl->cipher->ident != SSL_NULL_WITH_NULL_NULL && + ssl->sessionIdLen == SSL_MAX_SESSION_ID_SIZE) { + +#ifdef USE_STATELESS_SESSION_TICKETS + /* There is only one sessionId_t structure for any given session and + it is possible a re-handshake on a session ticket connection will + agree on using standard resumption and so the old master secret + for the session ticket will be overwritten. Check for this case + here and do not update our session if a ticket is in use */ + if (session->sessionTicket != NULL && session->sessionTicketLen > 0) { + return PS_SUCCESS; + } +#endif + session->cipherId = ssl->cipher->ident; + memcpy(session->id, ssl->sessionId, ssl->sessionIdLen); + memcpy(session->masterSecret, ssl->sec.masterSecret, + SSL_HS_MASTER_SIZE); + return PS_SUCCESS; + } +#ifdef USE_STATELESS_SESSION_TICKETS + if (ssl->cipher != NULL && ssl->cipher->ident != SSL_NULL_WITH_NULL_NULL && + session->sessionTicket != NULL && session->sessionTicketLen > 0) { + session->cipherId = ssl->cipher->ident; + memcpy(session->masterSecret, ssl->sec.masterSecret, + SSL_HS_MASTER_SIZE); + return PS_SUCCESS; + } +#endif + + return PS_FAILURE; +} + +#ifdef USE_ALPN +/******************************************************************************/ + +int32 matrixSslCreateALPNext(psPool_t *pool, int32 protoCount, + unsigned char *proto[MAX_PROTO_EXT], int32 protoLen[MAX_PROTO_EXT], + unsigned char **extOut, int32 *extLen) +{ + int32 i, len; + unsigned char *c; + + if (protoCount > MAX_PROTO_EXT) { + psTraceIntInfo("Must increase MAX_PROTO_EXT to %d\n", protoCount); + return PS_ARG_FAIL; + } + len = 2; /* overall len is 2 bytes */ + for (i = 0; i < protoCount; i++) { + if (protoLen[i] <= 0 || protoLen[i] > 255) { + return PS_ARG_FAIL; + } + len += protoLen[i] + 1; /* each string has 1 byte len */ + } + if ((c = psMalloc(pool, len)) == NULL) { + return PS_MEM_FAIL; + } + memset(c, 0, len); + *extOut = c; + *extLen = len; + + *c = ((len - 2) & 0xFF00) >> 8; c++; /* don't include ourself */ + *c = (len - 2) & 0xFF; c++; + for (i = 0; i < protoCount; i++) { + *c = protoLen[i]; c++; + memcpy(c, proto[i], protoLen[i]); + c += protoLen[i]; + } + return PS_SUCCESS; +} +#endif + +/******************************************************************************/ + +int32 matrixSslCreateSNIext(psPool_t *pool, unsigned char *host, int32 hostLen, + unsigned char **extOut, int32 *extLen) +{ + unsigned char *c; + + *extLen = hostLen + 5; + if ((c = psMalloc(pool, *extLen)) == NULL) { + return PS_MEM_FAIL; + } + memset(c, 0, *extLen); + *extOut = c; + + *c = ((hostLen + 3) & 0xFF00) >> 8; c++; + *c = (hostLen + 3) & 0xFF; c++; + c++; /* host_name enum */ + *c = (hostLen & 0xFF00) >> 8; c++; + *c = hostLen & 0xFF; c++; + memcpy(c, host, hostLen); + return PS_SUCCESS; +} +#endif /* USE_CLIENT_SIDE_SSL */ + +#ifdef USE_SERVER_SIDE_SSL +/******************************************************************************/ +/* + If client sent a ServerNameIndication extension, see if we have those + keys to load +*/ +int32 matrixServerSetKeysSNI(ssl_t *ssl, char *host, int32 hostLen) +{ + sslKeys_t *keys; + + if (ssl->sni_cb) { + ssl->extFlags.sni = 1; /* extension was actually handled */ + keys = NULL; + (ssl->sni_cb)((void*)ssl, host, hostLen, &keys) ; + if (keys) { + ssl->keys = keys; + return 0; + } + return PS_UNSUPPORTED_FAIL; /* callback didn't provide keys */ + } + + return 0; /* No callback registered. Go with default */ +} +#endif /* USE_SERVER_SIDE_SSL */ + +/******************************************************************************/ +/* + Rehandshake. Free any allocated sec members that will be repopulated +*/ +void sslResetContext(ssl_t *ssl) +{ +#ifdef USE_CLIENT_SIDE_SSL + if (!(ssl->flags & SSL_FLAGS_SERVER)) { + ssl->anonBk = ssl->sec.anon; + ssl->flagsBk = ssl->flags; + ssl->bFlagsBk = ssl->bFlags; + } +#endif + ssl->sec.anon = 0; +#ifdef USE_SERVER_SIDE_SSL + if (ssl->flags & SSL_FLAGS_SERVER) { + matrixClearSession(ssl, 0); + } +#endif /* USE_SERVER_SIDE_SSL */ + +#ifdef USE_DHE_CIPHER_SUITE + ssl->flags &= ~SSL_FLAGS_DHE_KEY_EXCH; + ssl->flags &= ~SSL_FLAGS_DHE_WITH_RSA; +#ifdef USE_ANON_DH_CIPHER_SUITE + ssl->flags &= ~SSL_FLAGS_ANON_CIPHER; +#endif /* USE_ANON_DH_CIPHER_SUITE */ +#ifdef USE_ECC_CIPHER_SUITE + ssl->flags &= ~SSL_FLAGS_ECC_CIPHER; + ssl->flags &= ~SSL_FLAGS_DHE_WITH_RSA; + ssl->flags &= ~SSL_FLAGS_DHE_WITH_DSA; +#endif /* USE_ECC_CIPHER_SUITE */ +#endif /* USE_DHE_CIPHER_SUITE */ + +#ifdef USE_PSK_CIPHER_SUITE + ssl->flags &= ~SSL_FLAGS_PSK_CIPHER; +#endif /* USE_PSK_CIPHER_SUITE */ + +#ifdef USE_DTLS +/* + This flag is used in conjuction with flightDone in the buffer + management API set to determine whether we are still in a handshake + state for attempting flight resends. If we are resetting context we + know a handshake phase is starting up again +*/ + if (ssl->flags & SSL_FLAGS_DTLS) { + ssl->appDataExch = 0; + } +#endif + ssl->bFlags = 0; /* Reset buffer control */ +} + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH) + +static int wildcardMatch(char *wild, char *s) +{ + char *c, *e; + + c = wild; + if (*c == '*') { + c++; + //TODO - this is actually a parse error + if (*c != '.') return -1; + if (strchr(s, '@')) return -1; + if ((e = strchr(s, '.')) == NULL) return -1; + if (strcasecmp(c, e) == 0) return 0; + } else if (*c == '.') { + //TODO - this is actually a parse error + return -1; + } else if (strcasecmp(c, s) == 0) { + return 0; + } + return -1; +} + +/******************************************************************************/ +/* + Subject certs is the leaf first chain of certs from the peer + Issuer certs is a flat list of trusted CAs loaded by LoadKeys +*/ +int32 matrixValidateCerts(psPool_t *pool, psX509Cert_t *subjectCerts, + psX509Cert_t *issuerCerts, char *expectedName, + psX509Cert_t **foundIssuer, void *hwCtx, + void *poolUserPtr) +{ + psX509Cert_t *ic, *sc; + x509GeneralName_t *n; + x509v3extensions_t *ext; + char ip[16]; + int32 rc, pathLen = 0; + + *foundIssuer = NULL; +/* + Case #1 is no issuing cert. Going to want to check that the final + subject cert presented is a SelfSigned CA +*/ + if (issuerCerts == NULL) { + return psX509AuthenticateCert(pool, subjectCerts, NULL, foundIssuer, + hwCtx, poolUserPtr); + } +/* + Case #2 is an issuing cert AND possibly a chain of subjectCerts. + */ + sc = subjectCerts; + if ((ic = sc->next) != NULL) { +/* + We do have a chain. Authenticate the chain before even looking + to our issuer CAs. +*/ + while (ic->next != NULL) { + if ((rc = psX509AuthenticateCert(pool, sc, ic, foundIssuer, hwCtx, + poolUserPtr)) < PS_SUCCESS) { + return rc; + } + if (ic->extensions.bc.pathLenConstraint >= 0) { + /* Make sure the pathLen is not exceeded */ + if (ic->extensions.bc.pathLenConstraint < pathLen) { + psTraceInfo("Authentication failed due to X.509 pathLen\n"); + sc->authStatus = PS_CERT_AUTH_FAIL_PATH_LEN; + return PS_CERT_AUTH_FAIL_PATH_LEN; + } + } + pathLen++; + sc = sc->next; + ic = sc->next; + } +/* + Test using the parent-most in chain as the subject +*/ + if ((rc = psX509AuthenticateCert(pool, sc, ic, foundIssuer, hwCtx, + poolUserPtr)) < PS_SUCCESS) { + return rc; + } + if (ic->extensions.bc.pathLenConstraint >= 0) { + /* Make sure the pathLen is not exceeded */ + if (ic->extensions.bc.pathLenConstraint < pathLen) { + psTraceInfo("Authentication failed due to X.509 pathLen\n"); + sc->authStatus = PS_CERT_AUTH_FAIL_PATH_LEN; + return PS_CERT_AUTH_FAIL_PATH_LEN; + } + } + pathLen++; +/* + Lastly, set subject to the final cert for the real issuer test below +*/ + sc = sc->next; + } +/* + Now loop through the issuer certs and see if we can authenticate this chain + + If subject cert was a chain, that has already been authenticated above so + we only need to pass in the single parent-most cert to be tested against +*/ + *foundIssuer = NULL; + ic = issuerCerts; + while (ic != NULL) { + sc->authStatus = PS_FALSE; + if ((rc = psX509AuthenticateCert(pool, sc, ic, foundIssuer, hwCtx, + poolUserPtr)) == PS_SUCCESS) { + if (ic->extensions.bc.pathLenConstraint >= 0) { + /* Make sure the pathLen is not exceeded. If the sc and ic + are the same CA at this point, this means the peer + included the root CA in the chain it sent. It's not good + practice to do this but implementations seem to allow it. + Subtract one from pathLen in this case since one got + added when it was truly just self-authenticating */ + if (ic->signatureLen == sc->signatureLen && + (memcmp(ic->signature, sc->signature, + sc->signatureLen) == 0)) { + if (pathLen > 0) pathLen--; + } + if (ic->extensions.bc.pathLenConstraint < pathLen) { + psTraceInfo("Authentication failed due to X.509 pathLen\n"); + rc = sc->authStatus = PS_CERT_AUTH_FAIL_PATH_LEN; + return rc; + } + } + + /* Validate extensions of leaf certificate */ + ext = &subjectCerts->extensions; + + /* Validate extended key usage */ + if (ext->critFlags & EXT_CRIT_FLAG(OID_ENUM(id_ce_extKeyUsage))) { + if (!(ext->ekuFlags & (EXT_KEY_USAGE_TLS_SERVER_AUTH | + EXT_KEY_USAGE_TLS_CLIENT_AUTH))) { + _psTrace("End-entity certificate not for TLS usage!\n"); + subjectCerts->authFailFlags |= PS_CERT_AUTH_FAIL_EKU_FLAG; + rc = subjectCerts->authStatus = PS_CERT_AUTH_FAIL_EXTENSION; + } + } + + /* Check the subject/altSubject. Should match requested domain */ + if (expectedName == NULL) { + return rc; + } + if (wildcardMatch(subjectCerts->subject.commonName, + expectedName) == 0) { + return rc; + } + for (n = ext->san; n != NULL; n = n->next) { + if (n->id == GN_DNS) { + if (wildcardMatch((char *)n->data, expectedName) == 0) { + return rc; + } + } else if (n->id == GN_EMAIL) { + /* Email doesn't have wildcards */ + if (strcasecmp((char *)n->data, expectedName) == 0) { + return rc; + } + } else if (n->id == GN_IP) { + snprintf(ip, 15, "%u.%u.%u.%u", + (unsigned char)(n->data[0]), + (unsigned char )(n->data[1]), + (unsigned char )(n->data[2]), + (unsigned char )(n->data[3])); + ip[15] = '\0'; + if (strcmp(ip, expectedName) == 0) { + return rc; + } + } + } + psTraceInfo("Authentication failed: no matching subject\n"); + subjectCerts->authFailFlags |= PS_CERT_AUTH_FAIL_SUBJECT_FLAG; + rc = subjectCerts->authStatus = PS_CERT_AUTH_FAIL_EXTENSION; + return rc; + } else if (rc == PS_MEM_FAIL) { +/* + OK to fail on the authentication because there may be a list here + but MEM failures prevent us from continuing at all. +*/ + return rc; + } + ic = ic->next; + } +/* + Success would have returned if it happen +*/ + return PS_CERT_AUTH_FAIL; +} +#endif /* USE_CLIENT_SIDE_SSL || USE_CLIENT_AUTH */ + +/******************************************************************************/ +/* + Calls a user defined callback to allow for manual validation of the + certificate. +*/ +int32 matrixUserCertValidator(ssl_t *ssl, int32 alert, + psX509Cert_t *subjectCert, sslCertCb_t certValidator) +{ + int32 status; + +/* + If there is no callback, return PS_SUCCESS because there has already been + a test for the case where the certificate did NOT PASS pubkey test + and a callback does not exist to manually handle. + + It is highly recommended that the user manually verify, but the cert + material has internally authenticated and the user has implied that + is sufficient enough. +*/ + if (certValidator == NULL) { + psTraceInfo("Internal cert auth passed. No user callback registered\n"); + return PS_SUCCESS; + } + +/* + Finally, let the user know what the alert status is and + give them the cert material to access. Any non-zero value in alert + indicates there is a pending fatal alert. + + The user can look at authStatus members if they want to examine the cert + that did not pass. +*/ + if (alert == SSL_ALERT_NONE) { + status = 0; + } else { + status = alert; + } + +/* + The user callback +*/ + return certValidator(ssl, subjectCert, status); +} +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + + +/******************************************************************************/ +#ifdef USE_MATRIXSSL_STATS +void matrixSslRegisterStatCallback(ssl_t *ssl, void (*stat_cb)(void *ssl, + void *stats_ptr, int32 type, int32 value), void *stats_ptr) +{ + ssl->statCb = stat_cb; + ssl->statsPtr = stats_ptr; +} + +void matrixsslUpdateStat(ssl_t *ssl, int32 type, int32 value) +{ + if (ssl->statCb) { + (ssl->statCb)(ssl, ssl->statsPtr, type, value); + } +} + +#endif /* USE_MATRIXSSL_STATS */ +/******************************************************************************/ + diff --git a/matrixssl/matrixsslApi.c b/matrixssl/matrixsslApi.c new file mode 100644 index 0000000..7dddb69 --- /dev/null +++ b/matrixssl/matrixsslApi.c @@ -0,0 +1,1593 @@ +/** + * @file matrixsslApi.c + * @version $Format:%h%d$ + * + * MatrixSSL Public API Layer. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "matrixsslApi.h" + +/******************************************************************************/ +/* + Create a new client SSL session + This creates internal SSL buffers and cipher structures + Clients initiate the connection with a 'HelloRequest', and this data + is placed in the outgoing buffer for the caller to send. + + ssl The ssl_t session structure is returned using this value, on success + + keys Keys structure initialized with matrixSslReadKeys + + sid A pointer to storage for a session ID. If there is not yet session + cache information, the sid.cipherId should be set to + SSL_NULL_WITH_NULL_NULL. After a successful connection to a server, + this sid structure will be populated with session cache credentials + and for subsequent connections should be used without modification + of the cipherId. + + cipherSpec Array of requested ciphers to negotiate to (0 for server's choice) + If non-zero, and server doesn't have it, conn will fail + + certCb Optional callback to call when validating cert + + expectedName Optional certificate subject name to validate in the remote + certificate. Typically a client would specify the hostname or + IP address it is connecting to. + + extensions Optional TLS extensions (usually NULL) + + extCb TLS reply extensions from the server + + flags TODO out of date + + Return MATRIXSSL_REQUEST_SEND on success + < 0 on error. Do not need to call DeleteSession on failure + */ + +#ifdef USE_CLIENT_SIDE_SSL +int32_t matrixSslNewClientSession(ssl_t **ssl, const sslKeys_t *keys, + sslSessionId_t *sid, + const uint16_t cipherSpec[], uint8_t cipherSpecLen, + sslCertCb_t certCb, + const char *expectedName, tlsExtension_t *extensions, + sslExtCb_t extCb, + sslSessOpts_t *options) +{ + ssl_t *lssl; + psBuf_t tmp; + uint32 len; + int32 rc, i; + + if (!ssl) { + return PS_ARG_FAIL; + } + if (cipherSpecLen > 0 && (cipherSpec == NULL || cipherSpec[0] == 0)) { + return PS_ARG_FAIL; + } + if (options == NULL) { + return PS_ARG_FAIL; + } + + *ssl = NULL; + lssl = NULL; + + /* Give priority to cipher suite if session id is provided and doesn't match */ + if (cipherSpec != NULL && cipherSpec[0] != 0 && sid != NULL && + sid->cipherId != 0) { + rc = 1; + for (i = 0; i < cipherSpecLen; i++) { + if (cipherSpec[i] == sid->cipherId) { + rc = 0; + } + } + if (rc) { + psTraceInfo("Explicit cipher suite will override session cache\n"); + memset(sid->id, 0, SSL_MAX_SESSION_ID_SIZE); + memset(sid->masterSecret, 0, SSL_HS_MASTER_SIZE); + sid->cipherId = 0; + } + } + + if ((rc = matrixSslNewSession(&lssl, keys, sid, options)) < 0) { + return rc; + } + lssl->userPtr = options->userPtr; + +#ifndef USE_ONLY_PSK_CIPHER_SUITE + if (expectedName) { + if (psX509ValidateGeneralName((char*)expectedName) < 0) { + matrixSslDeleteSession(lssl); + return rc; + } + rc = strlen(expectedName); + lssl->expectedName = psMalloc(lssl->sPool, rc + 1); + strcpy(lssl->expectedName, expectedName); + } + if (certCb) { + matrixSslSetCertValidator(lssl, certCb); + } +#endif + if (extCb) { + lssl->extCb = extCb; + } +RETRY_HELLO: + tmp.size = lssl->outsize; + tmp.buf = tmp.start = tmp.end = lssl->outbuf; + if ((rc = matrixSslEncodeClientHello(lssl, &tmp, cipherSpec, cipherSpecLen, + &len, extensions, options)) < 0) { + if (rc == SSL_FULL) { + if ((tmp.buf = psRealloc(lssl->outbuf, len, lssl->bufferPool)) + == NULL) { + matrixSslDeleteSession(lssl); + return PS_MEM_FAIL; + } + lssl->outbuf = tmp.buf; + lssl->outsize = len; + goto RETRY_HELLO; + } else { + matrixSslDeleteSession(lssl); + return rc; + } + } + psAssert(tmp.start == tmp.buf); + lssl->outlen = tmp.end - tmp.start; + *ssl = lssl; + return MATRIXSSL_REQUEST_SEND; +} + +/* SessionID management functions for clients that wish to perform + session resumption. This structure handles both the traditional resumption + mechanism and the server-stateless session ticket mechanism +*/ +int32 matrixSslNewSessionId(sslSessionId_t **sess, void *poolUserPtr) +{ + sslSessionId_t *ses; + psPool_t *pool = NULL; + + if ((ses = psMalloc(pool, sizeof(sslSessionId_t))) == NULL) { + return PS_MEM_FAIL; + } + memset(ses, 0x0, sizeof(sslSessionId_t)); + ses->pool = pool; + *sess = ses; + return PS_SUCCESS; +} + +void matrixSslClearSessionId(sslSessionId_t *sess) +{ + psPool_t *pool; + + pool = sess->pool; + memset(sess, 0x0, sizeof(sslSessionId_t)); + sess->pool = pool; +} + +void matrixSslDeleteSessionId(sslSessionId_t *sess) +{ + + if (sess == NULL) { + return; + } +#ifdef USE_STATELESS_SESSION_TICKETS + if (sess->sessionTicket) { + psFree(sess->sessionTicket, sess->pool); + } +#endif + + memset(sess, 0x0, sizeof(sslSessionId_t)); + psFree(sess, NULL); +} + +#endif /* USE_CLIENT_SIDE_SSL */ + +#ifdef USE_SERVER_SIDE_SSL +/******************************************************************************/ +/* + Create a new server SSL session + This creates internal SSL buffers and cipher structures + Internal SSL state is set to expect an incoming 'HelloRequest' + + Return MATRIXSSL_SUCCESS on success + < 0 on error + */ + +int32 matrixSslNewServer(ssl_t **ssl, + pubkeyCb_t pubkeyCb, pskCb_t pskCb, sslCertCb_t certCb, + sslSessOpts_t *options) +{ + int32 rc; + + if ((rc = matrixSslNewServerSession(ssl, NULL, certCb, options)) < 0) { + return rc; + } + + (*ssl)->sec.pskCb = (pskCb_t)pskCb; +#ifndef USE_ONLY_PSK_CIPHER_SUITE + (*ssl)->sec.pubkeyCb = (pubkeyCb_t)pubkeyCb; +#endif + return MATRIXSSL_SUCCESS; +} + +int32 matrixSslNewServerSession(ssl_t **ssl, const sslKeys_t *keys, + sslCertCb_t certCb, + sslSessOpts_t *options) +{ + ssl_t *lssl; + + if (!ssl) { + return PS_ARG_FAIL; + } + if (options == NULL) { + return PS_ARG_FAIL; + } + + /* Add SERVER_FLAGS to versionFlag member of options */ + options->versionFlag |= SSL_FLAGS_SERVER; + *ssl = NULL; + lssl = NULL; + +#ifdef USE_CLIENT_AUTH + if (certCb) { + options->versionFlag |= SSL_FLAGS_CLIENT_AUTH; + if (matrixSslNewSession(&lssl, keys, NULL, options) < 0) { + goto NEW_SVR_ERROR; + } + matrixSslSetCertValidator(lssl, (sslCertCb_t)certCb); + } else if (matrixSslNewSession(&lssl, keys, NULL, options) < 0) { + goto NEW_SVR_ERROR; + } +#else + psAssert(certCb == NULL); + if (matrixSslNewSession(&lssl, keys, NULL, options) < 0) { + goto NEW_SVR_ERROR; + } +#endif /* USE_CLIENT_AUTH */ + + lssl->userPtr = options->userPtr; + if (options->maxFragLen < 0) { + /* User wants to deny a client request for changing max frag len */ + lssl->extFlags.deny_max_fragment_len = 1; + } + lssl->maxPtFrag = SSL_MAX_PLAINTEXT_LEN; + + if (options->truncHmac < 0) { + lssl->extFlags.deny_truncated_hmac = 1; + } + + /* Extended master secret is enabled by default. If user sets to 1 this + is a flag to REQUIRE its use */ + if (options->extendedMasterSecret > 0) { + lssl->extFlags.require_extended_master_secret = 1; + } + + *ssl = lssl; + return MATRIXSSL_SUCCESS; + +NEW_SVR_ERROR: + if (lssl) matrixSslDeleteSession(lssl); + return PS_FAILURE; +} + +void matrixSslRegisterSNICallback(ssl_t *ssl, void (*sni_cb)(void *ssl, + char *hostname, int32 hostnameLen, sslKeys_t **newKeys)) +{ + ssl->sni_cb = sni_cb; +} + +#ifdef USE_ALPN +void matrixSslRegisterALPNCallback(ssl_t *ssl, + void (*srv_alpn_cb)(void *ssl, short protoCount, + char *proto[MAX_PROTO_EXT], int32 protoLen[MAX_PROTO_EXT], + int32 *index)) +{ + ssl->srv_alpn_cb = srv_alpn_cb; +} +#endif + +#endif /* USE_SERVER_SIDE_SSL */ + + + +/******************************************************************************/ +/* + Caller is asking for allocated buffer storage to recv data into + + buf Populated with a transient area where data can be read into + + Return > 0, size of 'buf' in bytes + <= 0 on error + */ +int32 matrixSslGetReadbuf(ssl_t *ssl, unsigned char **buf) +{ + if (!ssl || !buf) { + return PS_ARG_FAIL; + } + psAssert(ssl && ssl->insize > 0 && ssl->inbuf != NULL); + /* If there's unprocessed data in inbuf, have caller append to it */ + *buf = ssl->inbuf + ssl->inlen; + return ssl->insize - ssl->inlen; +} + +/* If the required size is known, grow the buffer here so the caller doesn't + have to go through the REQUEST_RECV logic of matrixSslReceivedData + + The return value MAY be larger than the requested size if the inbuf + is already larger than what was requested. +*/ +int32 matrixSslGetReadbufOfSize(ssl_t *ssl, int32 size, unsigned char **buf) +{ + unsigned char *p; + + if (!ssl || !buf) { + return PS_ARG_FAIL; + } + psAssert(ssl && ssl->insize > 0 && ssl->inbuf != NULL); + + if ((ssl->insize - ssl->inlen) >= size) { + /* Already enough room in current buffer */ + return matrixSslGetReadbuf(ssl, buf); + } + + /* Going to have to grow... but do we have to realloc to save data? */ + if (ssl->inlen == 0) { + /* buffer is empty anyway so can free before alloc and help keep high + water mark down */ + psFree(ssl->inbuf, ssl->bufferPool); + ssl->inbuf = NULL; + if ((ssl->inbuf = psMalloc(ssl->bufferPool, size)) == NULL) { + ssl->insize = 0; + return PS_MEM_FAIL; + } + ssl->insize = size; + *buf = ssl->inbuf; + return ssl->insize; + } else { + /* realloc with: total size = current size + requested size */ + if ((p = psRealloc(ssl->inbuf, ssl->inlen + size, ssl->bufferPool)) + == NULL) { + ssl->inbuf = NULL; ssl->insize = 0; ssl->inlen = 0; + return PS_MEM_FAIL; + } + ssl->inbuf = p; + ssl->insize = ssl->inlen + size; + *buf = ssl->inbuf + ssl->inlen; + return size; + } + return PS_FAILURE; /* can't hit */ +} + +/******************************************************************************/ +/* + Caller is asking if there is any encoded, outgoing SSL data that should be + sent out the transport layer. + + buf if provided, is updated to point to the data to be sent + + Return > 0, the number of bytes to send + 0 if there is no pending data + < 0 on error + */ +int32 matrixSslGetOutdata(ssl_t *ssl, unsigned char **buf) +{ + if (!ssl) { + return PS_ARG_FAIL; + } + psAssert(ssl->outsize > 0 && ssl->outbuf != NULL); + if (buf) { + *buf = ssl->outbuf; + } + return ssl->outlen; /* Can be 0 */ +} + +/******************************************************************************/ +/* + Caller is asking for an allocated buffer to write plaintext into. + That plaintext will then be encoded when the caller subsequently calls + matrixSslEncodeWritebuf() + + This is also explicitly called by matrixSslEncodeToOutdata + + ssl SSL session context + + buf The data storage to write into will be populated here on success + + requestedLen The amount of buffer space the caller would like to use + + Return > 0, success returns # bytes available for plaintext at buf + PS_MEM_FAIL if requiredLen too large for current memory + <= 0 on error + */ +int32 matrixSslGetWritebuf(ssl_t *ssl, unsigned char **buf, uint32 requestedLen) +{ + uint32 requiredLen, sz, overhead; +#ifdef USE_DTLS + int32 pmtu; +#endif + unsigned char *p; + + if (!ssl || !buf) { + return PS_ARG_FAIL; + } + psAssert(ssl->outsize > 0 && ssl->outbuf != NULL); + + +#ifdef USE_BEAST_WORKAROUND + /* This is a client-only feature */ + if (!(ssl->flags & SSL_FLAGS_SERVER)) { + /* Not a problem at all beginning in TLS 1.1 (version 3.2) and never + a problem on stream ciphers */ + if ((ssl->majVer == SSL3_MAJ_VER) && (ssl->minVer <= TLS_MIN_VER) + && (ssl->enBlockSize > 1) && (requestedLen > 1) && + !(ssl->bFlags & BFLAG_STOP_BEAST)) { + ssl->bFlags |= BFLAG_STOP_BEAST; + } + } +#endif + +/* + First thing is to ensure under the maximum allowed plaintext len according + to the SSL specification (or the negotiated max). If not, set it to the + max for the calculations and make sure that exact max is returned to the + caller. The responsibilty for fragmenting the message is left to them +*/ + if (requestedLen > (uint32)ssl->maxPtFrag) { + requestedLen = ssl->maxPtFrag; + } + +/* + What is the total encoded size for a plaintext requestedLen. The overhead + includes leading header as well as trailing MAC and pad + + We want to tweak the overhead an extra block to account for a + padding miscalculation in matrixSslGetEncodedSize. If that call was + made on an exact-sized message and the user decides to use a + different record size than requested, we'll need to make sure + there is enough available room for any potential padding length. +*/ + requiredLen = matrixSslGetEncodedSize(ssl, requestedLen + ssl->enBlockSize); + + psAssert(requiredLen >= requestedLen); + overhead = requiredLen - requestedLen; + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + pmtu = matrixDtlsGetPmtu(); + if (requiredLen > (uint32)pmtu) { + overhead = matrixSslGetEncodedSize(ssl, 0) + ssl->enBlockSize; + requiredLen = matrixSslGetEncodedSize(ssl, pmtu - overhead); + } + } +#endif + +/* + Get current available space in outbuf +*/ + if (ssl->outsize < ssl->outlen) { + return PS_FAILURE; + } + sz = ssl->outsize - ssl->outlen; + +/* + If not enough free space for requiredLen, grow the buffer +*/ + if (sz < requiredLen) { + if ((p = psRealloc(ssl->outbuf, ssl->outsize + + (requiredLen - sz), ssl->bufferPool)) == NULL) { + return PS_MEM_FAIL; + } + ssl->outbuf = p; + ssl->outsize = ssl->outsize + (requiredLen - sz); +/* + Recalculate available free space +*/ + if (ssl->outsize < ssl->outlen) { + return PS_FAILURE; + } + sz = ssl->outsize - ssl->outlen; + } + +/* + Now that requiredLen has been confirmed/created, return number of available + plaintext bytes +*/ + if (requestedLen < (uint32)ssl->maxPtFrag) { + requestedLen = sz - overhead; + if (requestedLen > (uint32)ssl->maxPtFrag) { + requestedLen = ssl->maxPtFrag; + } + } + +/* + Now return the pointer that has skipped past the record header +*/ +#ifdef USE_TLS_1_1 +/* + If a block cipher is being used TLS 1.1 requires the use + of an explicit IV. This is an extra random block of data + prepended to the plaintext before encryption. Account for + that extra length here. +*/ + if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) && + (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1)) { + *buf = ssl->outbuf + ssl->outlen + ssl->recordHeadLen + ssl->enBlockSize; + return requestedLen; /* may not be what was passed in */ + } + /* GCM mode will need to save room for the nonce */ + if (ssl->flags & SSL_FLAGS_AEAD_W) { + *buf = ssl->outbuf + ssl->outlen + ssl->recordHeadLen + + AEAD_NONCE_LEN(ssl); + return requestedLen; /* may not be what was passed in */ + } +#endif /* USE_TLS_1_1 */ + +#ifdef USE_BEAST_WORKAROUND + if (ssl->bFlags & BFLAG_STOP_BEAST) { + /* The reserved space accounts for a full encoding of a 1 byte record. + The final -1 is so that when the second encrypt arrives it will + land as an in-situ */ + overhead = ((ssl->enMacSize + 1) % ssl->enBlockSize) ? + ssl->enBlockSize : 0; + *buf = ssl->outbuf + ssl->outlen + (2 * ssl->recordHeadLen) + overhead + + (ssl->enBlockSize * ((ssl->enMacSize + 1)/ssl->enBlockSize)) - 1; + } else { + *buf = ssl->outbuf + ssl->outlen + ssl->recordHeadLen; + } +#else + *buf = ssl->outbuf + ssl->outlen + ssl->recordHeadLen; +#endif + return requestedLen; /* may not be what was passed in */ +} + +/******************************************************************************/ +/* + ptBuf = plaintext buffer + ptLen = length of plaintext in bytes + ctBuf = allocated ciphertext destination buffer + ctLen = INPUT ctBuf buffer size and OUTPUT is length of ciphertext + + Return value = SUCCESS is > 0 and FAILURE is < 0 +*/ +int32 matrixSslEncodeToUserBuf(ssl_t *ssl, unsigned char *ptBuf, uint32 ptLen, + unsigned char *ctBuf, uint32 *ctLen) +{ + int32 rc; + rc = matrixSslEncode(ssl, ctBuf, *ctLen, ptBuf, &ptLen); + if (rc > 0) { + *ctLen = ptLen; + } + return rc; +} + +/******************************************************************************/ +/* + Encode (encrypt) 'len' bytes of plaintext data that has been placed into + the buffer given by matrixSslGetWritebuf(). This is an in-situ encode. + + CAN ONLY BE CALLED AFTER A PREVIOUS CALL TO matrixSslGetWritebuf + + len >= 0.If len is zero, we send out a blank ssl record + len must be <= size returned by matrixSslGetWritebuf() + + Returns < 0 on error, total #bytes in outgoing data buf on success + */ +int32 matrixSslEncodeWritebuf(ssl_t *ssl, uint32 len) +{ + unsigned char *origbuf; + int32 rc, reserved; + + if (!ssl || ((int32)len < 0)) { + return PS_ARG_FAIL; + } + if (ssl->bFlags & BFLAG_CLOSE_AFTER_SENT) { + return PS_PROTOCOL_FAIL; + } + psAssert(ssl->outsize > 0 && ssl->outbuf != NULL); + /* Caller was given proper locations and lengths in GetWritebuf() */ + origbuf = ssl->outbuf + ssl->outlen; + if (ssl->outbuf == NULL || (ssl->outsize - ssl->outlen) < (int32)len) { + return PS_FAILURE; + } + + reserved = ssl->recordHeadLen; +#ifdef USE_BEAST_WORKAROUND + if (ssl->bFlags & BFLAG_STOP_BEAST) { + rc = ((ssl->enMacSize + 1) % ssl->enBlockSize) ? ssl->enBlockSize : 0; + reserved += ssl->recordHeadLen + rc + + (ssl->enBlockSize * ((ssl->enMacSize + 1)/ssl->enBlockSize)) - 1; + } +#endif + +#ifdef USE_TLS_1_1 +/* + If a block cipher is being used TLS 1.1 requires the use + of an explicit IV. This is an extra random block of data + prepended to the plaintext before encryption. Account for + that extra length here. +*/ + if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) && + (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1)) { + reserved += ssl->enBlockSize; + } + if (ssl->flags & SSL_FLAGS_AEAD_W) { + reserved += AEAD_NONCE_LEN(ssl); + } +#endif /* USE_TLS_1_1 */ + + rc = matrixSslEncode(ssl, origbuf, (ssl->outsize - ssl->outlen), + origbuf + reserved, &len); + if (rc < 0) { + psAssert(rc != SSL_FULL); /* should not happen */ + return PS_FAILURE; + } +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, APP_DATA_SENT_STAT, len); +#endif + ssl->outlen += len; + return ssl->outlen; +} + +/******************************************************************************/ +/* + This public API allows the user to encrypt the plaintext buffer of their + choice into the internal outbuf that is retrieved when matrixSslGetOutdata + is called. This is non-in-situ support and will leave the callers + plaintext buffer intact + + ptBuf The plaintext buffer to be converted into an SSL application data + record. + len The length, in bytes, of the ptBuf plaintext data + + Returns < 0 on error, total #bytes in outgoing data buf on success +*/ +int32 matrixSslEncodeToOutdata(ssl_t *ssl, unsigned char *ptBuf, uint32 len) +{ + unsigned char *internalBuf; + int32 rc, fragLen, recLen, index; + + if (!ssl || !ptBuf) { + return PS_ARG_FAIL; + } + if (ssl->bFlags & BFLAG_CLOSE_AFTER_SENT) { + return PS_PROTOCOL_FAIL; + } + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + rc = matrixSslGetEncodedSize(ssl, len); + if (rc > matrixDtlsGetPmtu()) { + return PS_LIMIT_FAIL; + } + } +#endif + + /* Fragmentation support */ + index = 0; + while (len > 0) { + /* We just call matrixSslGetWritebuf to prepare the buffer */ + if ((rc = matrixSslGetWritebuf(ssl, &internalBuf, len)) < 0) { + psTraceIntInfo("matrixSslEncodeToOutbuf allocation error: %d\n", + rc); + return rc; + } + recLen = fragLen = min((uint32)rc, len); + psAssert(ssl->outsize > 0 && ssl->outbuf != NULL); + + if (ssl->outbuf == NULL || + (ssl->outsize - ssl->outlen) < (int32)fragLen) { + return PS_FAILURE; + } + internalBuf = ssl->outbuf + ssl->outlen; + + rc = matrixSslEncode(ssl, internalBuf, (ssl->outsize - ssl->outlen), + ptBuf + index, (uint32*)&fragLen); + if (rc < 0) { + psAssert(rc != SSL_FULL); /* should not happen */ + return PS_FAILURE; + } + index += recLen; + len -= recLen; +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, APP_DATA_SENT_STAT, fragLen); +#endif + ssl->outlen += fragLen; + } + return ssl->outlen; +} + +/******************************************************************************/ +/* + Helper to shrink buffers down to default size +*/ +#define SSL_INBUF 0 +#define SSL_OUTBUF 1 + +static void revertToDefaultBufsize(ssl_t *ssl, uint16 inOrOut) +{ + int32 defaultSize; + unsigned char *p; + + if (inOrOut == SSL_INBUF) { +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + defaultSize = matrixDtlsGetPmtu(); + } else { + defaultSize = SSL_DEFAULT_IN_BUF_SIZE; + } +#else + defaultSize = SSL_DEFAULT_IN_BUF_SIZE; +#endif + if (ssl->insize > defaultSize && ssl->inlen < defaultSize) { + /* It's not fatal if we can't realloc it smaller */ + if ((p = psRealloc(ssl->inbuf, defaultSize, ssl->bufferPool)) + != NULL) { + ssl->inbuf = p; + ssl->insize = defaultSize; + } + } + } else { +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + defaultSize = matrixDtlsGetPmtu(); + } else { + defaultSize = SSL_DEFAULT_OUT_BUF_SIZE; + } +#else + defaultSize = SSL_DEFAULT_OUT_BUF_SIZE; +#endif + if (ssl->outsize > defaultSize && ssl->outlen < defaultSize) { + /* It's not fatal if we can't realloc it smaller */ + if ((p = psRealloc(ssl->outbuf, defaultSize, ssl->bufferPool)) + != NULL) { + ssl->outbuf = p; + ssl->outsize = defaultSize; + } + } + } +} + +/******************************************************************************/ +/* + Caller has received data from the network and is notifying the SSL layer + */ +int32 matrixSslReceivedData(ssl_t *ssl, uint32 bytes, unsigned char **ptbuf, + uint32 *ptlen) +{ + unsigned char *buf, *prevBuf; + int32 rc, decodeRet, size, sanity, decodeErr; + uint32 processed, start, len, reqLen; + unsigned char alertLevel, alertDesc; + unsigned char *p; + + if (!ssl || !ptbuf || !ptlen) { + return PS_ARG_FAIL; + } + + psAssert(ssl->outsize > 0 && ssl->outbuf != NULL); + psAssert(ssl->insize > 0 && ssl->inbuf != NULL); + *ptbuf = NULL; + *ptlen = 0; + ssl->inlen += bytes; + if (ssl->inlen == 0) { + return PS_SUCCESS; /* Nothing to do. Basically a poll */ + } + /* This is outside the loop b/c we may want to parse within inbuf later */ + buf = ssl->inbuf; +DECODE_MORE: + /* Parameterized sanity check to avoid infinite loops */ + if (matrixSslHandshakeIsComplete(ssl)) { + /* Minimum possible record size once negotiated */ + sanity = ssl->inlen / (SSL3_HEADER_LEN + MD5_HASH_SIZE); + } else { + /* Even with an SSLv2 hello, the sanity check will let 1 pass through */ + sanity = ssl->inlen / (SSL3_HEADER_LEN + SSL3_HANDSHAKE_HEADER_LEN); + } + if (sanity-- < 0) { + return PS_PROTOCOL_FAIL; /* We've tried to decode too many times */ + } + len = ssl->inlen; + size = ssl->insize - (buf - ssl->inbuf); + prevBuf = buf; + decodeRet = matrixSslDecode(ssl, &buf, &len, size, &start, &reqLen, + &decodeErr, &alertLevel, &alertDesc); + +/* + Convenience for the cases that expect buf to have moved + - calculate the number of encoded bytes that were decoded +*/ + processed = buf - prevBuf; + rc = PS_PROTOCOL_FAIL; + switch (decodeRet) { + + case MATRIXSSL_SUCCESS: + + ssl->inlen -= processed; + if (ssl->inlen > 0) { + psAssert(buf > ssl->inbuf); +/* + Pack ssl->inbuf so there is immediate maximum room for potential + outgoing data that needs to be written +*/ + memmove(ssl->inbuf, buf, ssl->inlen); + buf = ssl->inbuf; + goto DECODE_MORE; /* More data in buffer to process */ + } +/* + In this case, we've parsed a finished message and no additional data is + available to parse. We let the client know the handshake is complete, + which can be used as a trigger to begin for example a HTTP request. +*/ + if (!(ssl->bFlags & BFLAG_HS_COMPLETE)) { + if (matrixSslHandshakeIsComplete(ssl)) { + ssl->bFlags |= BFLAG_HS_COMPLETE; +#ifdef USE_CLIENT_SIDE_SSL + matrixSslGetSessionId(ssl, ssl->sid); +#endif /* USE_CLIENT_SIDE_SSL */ + rc = MATRIXSSL_HANDSHAKE_COMPLETE; + } else { + rc = MATRIXSSL_REQUEST_RECV; /* Need to recv more handshake data */ + } + } else { +#ifdef USE_DTLS + rc = MATRIXSSL_REQUEST_RECV; /* Got FINISHED without CCS */ +#else + /* This is an error - we shouldn't get here */ +#endif + } + break; + +#ifdef USE_DTLS + case DTLS_RETRANSMIT: + /* Only request a resend if last record in buffer */ + ssl->inlen -= processed; + if (ssl->inlen > 0) { + psAssert(buf > ssl->inbuf); +/* + Pack ssl->inbuf so there is immediate maximum room for potential + outgoing data that needs to be written +*/ + memmove(ssl->inbuf, buf, ssl->inlen); + buf = ssl->inbuf; + goto DECODE_MORE; /* More data in buffer to process */ + } + + /* Flight will be rebuilt when matrixDtlsGetOutdata is called while + outbuf is empty. This is the return case where we are actually + seeing a repeat handshake message so we know something was lost in + flight. */ + return MATRIXSSL_REQUEST_SEND; +#endif + + case SSL_SEND_RESPONSE: +#ifdef ENABLE_FALSE_START + /* + If FALSE START is supported, there may be APPLICATION_DATA directly + following the FINISHED message, even though we haven't sent our + CHANGE_CIPHER_SPEC or FINISHED message. This is signalled by buf + having been moved forward, and our response being put directly into + ssl->outbuf, rather than in buf (ssl->inbuf). Return a REQUEST_SEND + so that the data in outbuf is flushed before the remaining data in + ssl->inbuf is parsed. + */ + if ((ssl->flags & SSL_FLAGS_FALSE_START) && buf != prevBuf) { + ssl->inlen -= processed; + psAssert(ssl->inlen > 0); + psAssert((uint32)ssl->inlen == start); + psAssert(buf > ssl->inbuf); + memmove(ssl->inbuf, buf, ssl->inlen); /* Pack ssl->inbuf */ + buf = ssl->inbuf; + return MATRIXSSL_REQUEST_SEND; + } +#endif + /* + This must be handshake data (or alert) or we'd be in PROCESS_DATA + so there is no way there is anything left inside inbuf to process. + ...so processed isn't valid because the output params are outbuf + related and we simply reset inlen + */ + ssl->inlen = 0; + + /* If alert, close connection after sending */ + if (alertDesc != SSL_ALERT_NONE) { + ssl->bFlags |= BFLAG_CLOSE_AFTER_SENT; + } + psAssert(prevBuf == buf); + psAssert(ssl->insize >= (int32)len); + psAssert(start == 0); + psAssert(buf == ssl->inbuf); + if (ssl->outlen > 0) { + /* If data's in outbuf, append inbuf. This is a corner case that + can happen if application data is queued but then incoming data + is processed and discovered to be a re-handshake request. + matrixSslDecode will have constructed the response flight but + we don't want to forget about the app data we haven't sent */ + if (ssl->outlen + (int32)len > ssl->outsize) { + if ((p = psRealloc(ssl->outbuf, ssl->outlen + len, + ssl->bufferPool)) == NULL) { + return PS_MEM_FAIL; + } + ssl->outbuf = p; + ssl->outsize = ssl->outlen + len; + } + memcpy(ssl->outbuf + ssl->outlen, ssl->inbuf, len); + ssl->outlen += len; + } else { /* otherwise, swap inbuf and outbuf */ + buf = ssl->outbuf; ssl->outbuf = ssl->inbuf; ssl->inbuf = buf; + ssl->outlen = len; + len = ssl->outsize; ssl->outsize = ssl->insize; ssl->insize = len; + buf = ssl->inbuf; + len = ssl->outlen; + } + rc = MATRIXSSL_REQUEST_SEND; /* We queued data to send out */ + break; + + case MATRIXSSL_ERROR: + if (decodeErr >= 0) { + //printf("THIS SHOULD BE A NEGATIVE VALUE?\n"); + } + return decodeErr; /* Will be a negative value */ + + case SSL_ALERT: + if (alertLevel == SSL_ALERT_LEVEL_FATAL) { + psTraceIntInfo("Received FATAL alert %d.\n", alertDesc); + } else { + /* Closure notify is the normal case */ + if (alertDesc == SSL_ALERT_CLOSE_NOTIFY) { + psTraceInfo("Normal SSL closure alert\n"); + } else { + psTraceIntInfo("Received WARNING alert %d\n", alertDesc); + } + } + /* Let caller access the 2 data bytes (severity and description) */ +#ifdef USE_TLS_1_1 + /* Been ignoring the explicit IV up to this final return point. */ + if ((ssl->flags & SSL_FLAGS_READ_SECURE) && + (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1)) { + prevBuf += ssl->enBlockSize; + } +#endif /* USE_TLS_1_1 */ + psAssert(len == 2); + *ptbuf = prevBuf; + *ptlen = len; + ssl->inlen -= processed; + return MATRIXSSL_RECEIVED_ALERT; + + case SSL_PARTIAL: + if (reqLen > SSL_MAX_BUF_SIZE) { + return PS_MEM_FAIL; + } + if (reqLen > (uint32)ssl->insize) { + if ((p = psRealloc(ssl->inbuf, reqLen, ssl->bufferPool)) == NULL) { + return PS_MEM_FAIL; + } + ssl->inbuf = p; + ssl->insize = reqLen; + buf = ssl->inbuf; + /* Don't need to change inlen */ + } + + + rc = MATRIXSSL_REQUEST_RECV; /* Expecting more data */ + break; + + /* We've got outgoing data that's larger than our buffer */ + case SSL_FULL: + if (reqLen > SSL_MAX_BUF_SIZE) { + return PS_MEM_FAIL; + } + /* We balk if we get a large handshake message */ + if (reqLen > SSL_MAX_PLAINTEXT_LEN && + !matrixSslHandshakeIsComplete(ssl)) { + if (reqLen > SSL_MAX_PLAINTEXT_LEN) { + return PS_MEM_FAIL; + } + } + /* + Can't envision any possible case where there is remaining data + in inbuf to process and are getting SSL_FULL. + */ + ssl->inlen = 0; + + /* Grow inbuf */ + if (reqLen > (uint32)ssl->insize) { + len = ssl->inbuf - buf; + if ((p = psRealloc(ssl->inbuf, reqLen, ssl->bufferPool)) == NULL) { + return PS_MEM_FAIL; + } + ssl->inbuf = p; + ssl->insize = reqLen; + buf = ssl->inbuf + len; + /* Note we leave inlen untouched here */ + } else { + psTraceInfo("Encoding error. Possible wrong flight messagSize\n"); + return PS_PROTOCOL_FAIL; /* error in our encoding */ + } + goto DECODE_MORE; + + case SSL_PROCESS_DATA: +/* + Possible we received a finished message and app data in the same + flight. In this case, the caller is not notified that the handshake + is complete, but rather is notified that there is application data to + process. + */ + if (!(ssl->bFlags & BFLAG_HS_COMPLETE) && + matrixSslHandshakeIsComplete(ssl)) { + ssl->bFlags |= BFLAG_HS_COMPLETE; +#ifdef USE_CLIENT_SIDE_SSL + matrixSslGetSessionId(ssl, ssl->sid); +#endif /* USE_CLIENT_SIDE_SSL */ + } +/* + . prevbuf points to start of unencrypted data + . buf points to start of any remaining unencrypted data + . start is length of remaining encrypted data yet to decode + . len is length of unencrypted data ready for user processing + */ + ssl->inlen -= processed; + psAssert((uint32)ssl->inlen == start); + + /* Call user plaintext data handler */ +#ifdef USE_TLS_1_1 + /* Been ignoring the explicit IV up to this final return point. */ + /* NOTE: This test has been on enBlockSize for a very long time but + it looks like it should be on deBlockSize since this a decryption. + Changed and added an assert to see if these ever don't match */ + psAssert(ssl->enBlockSize == ssl->deBlockSize); + if ((ssl->flags & SSL_FLAGS_READ_SECURE) && + (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->deBlockSize > 1)) { + len -= ssl->deBlockSize; + prevBuf += ssl->deBlockSize; + } + /* END enBlockSize to deBlockSize change */ +#endif /* USE_TLS_1_1 */ + *ptbuf = prevBuf; + *ptlen = len; +#ifdef USE_DTLS +/* + This flag is used in conjuction with flightDone in the buffer + management API set to determine whether we are still in a handshake + state for attempting flight resends. If we are getting app data we + know for certain we are out of the hs states. Testing HandshakeComplete + is not enough because you never know if the other side got FINISHED. +*/ + if (ssl->flags & SSL_FLAGS_DTLS) { + ssl->appDataExch = 1; + } +#endif +#ifdef USE_ZLIB_COMPRESSION + if (ssl->compression > 0) { + return MATRIXSSL_APP_DATA_COMPRESSED; + } +#endif + return MATRIXSSL_APP_DATA; + } /* switch decodeRet */ + + if (ssl->inlen > 0 && (buf != ssl->inbuf)) { + psAssert(0); + } +/* + Shrink inbuf to default size once inlen < default size, and we aren't + expecting any more data in the buffer. If SSL_PARTIAL, don't shrink the + buffer, since we expect to fill it up shortly. +*/ + if (decodeRet != SSL_PARTIAL) { + revertToDefaultBufsize(ssl, SSL_INBUF); + } + + return rc; +} + +/******************************************************************************/ +/* + Plaintext data has been processed as a response to MATRIXSSL_APP_DATA or + MATRIXSSL_RECEIVED_ALERT return codes from matrixSslReceivedData() + Return: + < 0 on error + 0 if there is no more incoming ssl data in the buffer + Caller should take whatever action is appropriate to the specific + protocol implementation, eg. read for more data, close, etc. + > 0 error code is same meaning as from matrixSslReceivedData() + In this case, ptbuf and ptlen will be modified and caller should + handle return code identically as from matrixSslReceivedData() + This is the case when more than one SSL record is in the buffer + */ +int32 matrixSslProcessedData(ssl_t *ssl, unsigned char **ptbuf, uint32 *ptlen) +{ + uint32 ctlen; + + if (!ssl || !ptbuf || !ptlen) { + return PS_ARG_FAIL; + } + *ptbuf = NULL; + *ptlen = 0; + + psAssert(ssl->insize > 0 && ssl->inbuf != NULL); + /* Move any remaining data to the beginning of the buffer */ + if (ssl->inlen > 0) { + ctlen = ssl->rec.len + ssl->recordHeadLen; + if (ssl->flags & SSL_FLAGS_AEAD_R) { + /* This overhead was removed from rec.len after the decryption + to keep buffer logic working. */ + /* TODO: This is for checking async or not. If async, this length + tweak never happens. Need a more generic way to look for + blocking or not */ + ctlen += AEAD_TAG_LEN(ssl) + AEAD_NONCE_LEN(ssl); + } + memmove(ssl->inbuf, ssl->inbuf + ctlen, ssl->inlen); + } + /* Shrink inbuf to default size once inlen < default size */ + revertToDefaultBufsize(ssl, SSL_INBUF); + + /* If there's more data, try to decode it here and return that code */ + if (ssl->inlen > 0) { + /* NOTE: ReceivedData cannot return 0 */ + return matrixSslReceivedData(ssl, 0, ptbuf, ptlen); + } + return MATRIXSSL_SUCCESS; +} + + +/******************************************************************************/ +/* + Returns < 0 on error + */ +int32 matrixSslEncodeClosureAlert(ssl_t *ssl) +{ + sslBuf_t sbuf; + int32 rc; + uint32 reqLen, newLen; + unsigned char *p; + + if (!ssl) { + return PS_ARG_FAIL; + } + psAssert(ssl->outsize > 0 && ssl->outbuf != NULL); +/* + Only encode the closure alert if we aren't already flagged for close + If we are flagged, we do not want to send any more data + */ + newLen = 0; + if (!(ssl->bFlags & BFLAG_CLOSE_AFTER_SENT)) { + ssl->bFlags |= BFLAG_CLOSE_AFTER_SENT; +L_CLOSUREALERT: + sbuf.buf = sbuf.start = sbuf.end = ssl->outbuf + ssl->outlen; + sbuf.size = ssl->outsize - ssl->outlen; + rc = sslEncodeClosureAlert(ssl, &sbuf, &reqLen); + if (rc == SSL_FULL && newLen == 0) { + newLen = ssl->outlen + reqLen; + if ((p = psRealloc(ssl->outbuf, newLen, ssl->bufferPool)) == NULL) { + return PS_MEM_FAIL; + } + ssl->outbuf = p; + ssl->outsize = newLen; + goto L_CLOSUREALERT; /* Try one more time */ + } else if (rc != PS_SUCCESS) { + return rc; + } + ssl->outlen += sbuf.end - sbuf.start; + } + return MATRIXSSL_SUCCESS; +} + +#ifdef SSL_REHANDSHAKES_ENABLED +/******************************************************************************/ +/* + Encode a CLIENT_HELLO or HELLO_REQUEST to re-handshake an existing + connection. + + Can't "downgrade" the re-handshake. This means if keys or certCb are + NULL we stick with whatever the session already has loaded. + + keys should be NULL if no change in key material is being made + + cipherSpec is only used by clients + */ +int32_t matrixSslEncodeRehandshake(ssl_t *ssl, sslKeys_t *keys, + int32 (*certCb)(ssl_t *ssl, psX509Cert_t *cert, int32 alert), + uint32 sessionOption, + const uint16_t cipherSpec[], uint8_t cipherSpecLen) +{ + sslBuf_t sbuf; + int32 rc, i; + uint32 reqLen, newLen; + unsigned char *p; + sslSessOpts_t options; + + /* Clear extFlags for rehandshakes */ + ssl->extFlags.truncated_hmac = 0; + ssl->extFlags.sni = 0; + + if (!ssl) { + return PS_ARG_FAIL; + } + if (cipherSpecLen > 0 && (cipherSpec == NULL || cipherSpec[0] == 0)) { + return PS_ARG_FAIL; + } + if (ssl->bFlags & BFLAG_CLOSE_AFTER_SENT) { + return PS_PROTOCOL_FAIL; + } + psAssert(ssl->outsize > 0 && ssl->outbuf != NULL); + +#ifdef DISABLE_DTLS_CLIENT_CHANGE_CIPHER_FROM_GCM_TO_GCM +#endif /* DISABLE_DTLS_CLIENT_CHANGE_CIPHER_FROM_GCM_TO_GCM */ + +#ifdef USE_ZLIB_COMPRESSION + /* Re-handshakes are not currently supported for compressed sessions. */ + if (ssl->compression > 0) { + psTraceInfo("Re-handshakes not supported for compressed sessions\n"); + return PS_UNSUPPORTED_FAIL; + } +#endif +/* + The only explicit option that can be passsed in is + SSL_OPTION_FULL_HANDSHAKE to indicate no resumption is allowed +*/ + if (sessionOption == SSL_OPTION_FULL_HANDSHAKE) { + matrixSslSetSessionOption(ssl, sessionOption, NULL); + } +/* + If the key material or cert callback are provided we have to assume it + was intentional to "upgrade" the re-handshake and we force full handshake + No big overhead calling SetSessionOption with FULL_HS multiple times. +*/ + if (keys != NULL) { + ssl->keys = keys; + matrixSslSetSessionOption(ssl, SSL_OPTION_FULL_HANDSHAKE, NULL); + } + +#ifndef USE_ONLY_PSK_CIPHER_SUITE + if (certCb != NULL) { + matrixSslSetSessionOption(ssl, SSL_OPTION_FULL_HANDSHAKE, NULL); +#if defined(USE_CLIENT_AUTH) || defined(USE_CLIENT_SIDE_SSL) + matrixSslSetCertValidator(ssl, certCb); +#endif /* USE_CLIENT_AUTH || USE_CLIENT_SIDE_SSL */ +#if defined(USE_CLIENT_AUTH) && defined(USE_SERVER_SIDE_SSL) +/* + If server, a certCb is an explicit flag to set client auth just as + it is in matrixSslNewServerSession +*/ + if (ssl->flags & SSL_FLAGS_SERVER) { + matrixSslSetSessionOption(ssl, SSL_OPTION_ENABLE_CLIENT_AUTH, NULL); + } +#endif /* USE_CLIENT_AUTH && USE_SERVER_SIDE_SSL */ + } +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + +/* + If cipher spec is explicitly different from current, force a full handshake +*/ + if (!(ssl->flags & SSL_FLAGS_SERVER)) { + rc = 0; + if (cipherSpecLen > 0) { + rc = 1; + for (i = 0; i < cipherSpecLen; i++) { + if (cipherSpec[i] == ssl->cipher->ident) { + rc = 0; + } + } + } + if (rc) { + matrixSslSetSessionOption(ssl, SSL_OPTION_FULL_HANDSHAKE, NULL); + } + } +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + /* Resend epoch should be brought up-to-date with new epoch */ + ssl->resendEpoch[0] = ssl->epoch[0]; + ssl->resendEpoch[1] = ssl->epoch[1]; + + ssl->msn = ssl->resendMsn = 0; + } +#endif /* USE_DTLS */ +/* + Options are set. Encode the HELLO message +*/ + newLen = 0; +L_REHANDSHAKE: + if (ssl->flags & SSL_FLAGS_SERVER) { + sbuf.buf = sbuf.start = sbuf.end = ssl->outbuf + ssl->outlen; + sbuf.size = ssl->outsize - ssl->outlen; + if ((rc = matrixSslEncodeHelloRequest(ssl, &sbuf, &reqLen)) < 0) { + if (rc == SSL_FULL && newLen == 0) { + newLen = ssl->outlen + reqLen; + if (newLen < SSL_MAX_BUF_SIZE) { + if ((p = psRealloc(ssl->outbuf, newLen, ssl->bufferPool)) + == NULL){ + return PS_MEM_FAIL; + } + ssl->outbuf = p; + ssl->outsize = newLen; + goto L_REHANDSHAKE; + } + } + return rc; + } + } else { + sbuf.buf = sbuf.start = sbuf.end = ssl->outbuf + ssl->outlen; + sbuf.size = ssl->outsize - ssl->outlen; + memset(&options, 0x0, sizeof(sslSessOpts_t)); +#ifdef USE_ECC_CIPHER_SUITE + options.ecFlags = ssl->ecInfo.ecFlags; +#endif + /* Use extended master secret if original connection used it */ + if (ssl->extFlags.extended_master_secret == 1) { + options.extendedMasterSecret = 1; + ssl->extFlags.extended_master_secret = 0; + } else { + options.extendedMasterSecret = -1; + } + + if ((rc = matrixSslEncodeClientHello(ssl, &sbuf, cipherSpec, + cipherSpecLen, &reqLen, NULL, &options)) < 0) { + if (rc == SSL_FULL && newLen == 0) { + newLen = ssl->outlen + reqLen; + if (newLen < SSL_MAX_BUF_SIZE) { + if ((p = psRealloc(ssl->outbuf, newLen, ssl->bufferPool)) + == NULL) { + return PS_MEM_FAIL; + } + ssl->outbuf = p; + ssl->outsize = newLen; + goto L_REHANDSHAKE; + } + } + return rc; + } + } + ssl->outlen += sbuf.end - sbuf.start; + return MATRIXSSL_SUCCESS; +} + +/* Disabling and re-enabling of re-handshakes is a receive feature. In other + words, a NO_RENEGOTIATION alert will be sent if a request is sent from the + peer. */ +int32 matrixSslDisableRehandshakes(ssl_t *ssl) +{ + if (ssl == NULL) { + return PS_ARG_FAIL; + } + matrixSslSetSessionOption(ssl, SSL_OPTION_DISABLE_REHANDSHAKES, NULL); + return PS_SUCCESS; +} + +int32 matrixSslReEnableRehandshakes(ssl_t *ssl) +{ + if (ssl == NULL) { + return PS_ARG_FAIL; + } + matrixSslSetSessionOption(ssl, SSL_OPTION_REENABLE_REHANDSHAKES, NULL); + return PS_SUCCESS; +} + +/* Undocumented helper functions to manage rehandshake credits for testing */ +int32 matrixSslGetRehandshakeCredits(ssl_t *ssl) +{ + if (ssl) { + return ssl->rehandshakeCount; + } + return -1; +} + +void matrixSslAddRehandshakeCredits(ssl_t *ssl, int32 credits) +{ + if (ssl) { + /* User must re-enable rehandshaking before adding credits */ + if (ssl->rehandshakeCount >= 0) { + if ((ssl->rehandshakeCount + credits) < 0x8000) { + ssl->rehandshakeCount += credits; + } + } + } +} + +#else /* !SSL_REHANDSHAKES_ENABLED */ +int32_t matrixSslEncodeRehandshake(ssl_t *ssl, sslKeys_t *keys, + int32 (*certCb)(ssl_t *ssl, psX509Cert_t *cert, int32 alert), + uint32_t sessionOption, + const uint16_t cipherSpec[], uint8_t cipherSpecLen) +{ + psTraceInfo("Rehandshaking is disabled. matrixSslEncodeRehandshake off\n"); + return PS_FAILURE; +} +int32 matrixSslDisableRehandshakes(ssl_t *ssl) +{ + psTraceInfo("Rehandshaking is not compiled into library at all.\n"); + return PS_FAILURE; +} + +int32 matrixSslReEnableRehandshakes(ssl_t *ssl) +{ + psTraceInfo("Rehandshaking is not compiled into library at all.\n"); + return PS_FAILURE; +} +#endif /* SSL_REHANDSHAKES_ENABLED */ + +/******************************************************************************/ +/* + Caller is indicating 'bytes' of data was written + */ +int32 matrixSslSentData(ssl_t *ssl, uint32 bytes) +{ + int32 rc; + + if (!ssl) { + return PS_ARG_FAIL; + } + if (bytes == 0) { + if (ssl->outlen > 0) { + return MATRIXSSL_REQUEST_SEND; + } else { + return MATRIXSSL_SUCCESS; /* Nothing to do */ + } + } + psAssert(ssl->outsize > 0 && ssl->outbuf != NULL); + ssl->outlen -= bytes; + + rc = MATRIXSSL_SUCCESS; + if (ssl->outlen > 0) { + memmove(ssl->outbuf, ssl->outbuf + bytes, ssl->outlen); + /* This was changed during 3.7.1 DTLS work. The line below used to be: + rc = MATRIXSSL_REQUEST_SEND; and it was possible for it to be + overridden with HANDSHAKE_COMPLETE below. This was a problem + if only the ChangeCipherSpec portion of the final flight was + just set becuase matrixSslHandshakeIsComplete would return 1 + because the state looks right. However, there would still be a + FINISHED message sitting in outbuf when COMPLETE is returned. + + This seemed like a bigger problem than just the DTLS test case + that caught it. If the transport layer of straight TLS sent off + only the CCS message for some reason, this would cause the same + odd combo of COMPLETE but with a FINISHED message that hasn't + been sent. + + It seems fine to return REQUEST_SEND whenever there is data left + in the outgoing buffer but it is suspecious it wasn't written + this way to begin with so maybe there was another corner case + the COMPLETE was solving. Hope not. + + In any case, it looks safe to make this a global change but if you + are reading this because you are trying to track down a change in + behavior in matrixSslSentData, maybe this documentation will help. + */ + return MATRIXSSL_REQUEST_SEND; + } + /* If there's nothing left to flush, reallocate the buffer smaller. */ + if ((ssl->outlen == 0) && (ssl->bFlags & BFLAG_CLOSE_AFTER_SENT)) { + /* We want to close the connection now */ + rc = MATRIXSSL_REQUEST_CLOSE; + } else { + revertToDefaultBufsize(ssl, SSL_OUTBUF); + } + /* Indicate the handshake is complete, in this case, the finished message + is being/has been just sent. Occurs in session resumption. */ + if (!(ssl->bFlags & BFLAG_HS_COMPLETE) && + matrixSslHandshakeIsComplete(ssl)) { + ssl->bFlags |= BFLAG_HS_COMPLETE; +#ifdef USE_CLIENT_SIDE_SSL + matrixSslGetSessionId(ssl, ssl->sid); +#endif /* USE_CLIENT_SIDE_SSL */ + rc = MATRIXSSL_HANDSHAKE_COMPLETE; +#ifdef USE_SSL_INFORMATIONAL_TRACE + /* Client side resumed completion or server standard completion */ + matrixSslPrintHSDetails(ssl); +#endif + } + return rc; +} + +#ifdef USE_ZLIB_COMPRESSION +int32 matrixSslIsSessionCompressionOn(ssl_t *ssl) +{ + if (ssl->compression > 0) { + return PS_TRUE; + } + return PS_FALSE; +} +#endif + + +#ifdef USE_CRL +/* + Called after key load if CRL location is expected to be embedded in the CA. + The user callback will be invoked with the URL and the responsibility of + the callback is to fetch the CRL and load it to the CA with matrixSslLoadCRL + + The numLoaded parameter indicates how many successful CRLs were loaded + if there are multiple CA files being processed here. + + Return codes: + < 0 - Error loading a CRL. numLoaded indicates if some success + 0 - No errors encountered. numLoaded could be 0 if no CRLs found +*/ +int32 matrixSslGetCRL(sslKeys_t *keys, int32 (*crlCb)(psPool_t *pool, + psX509Cert_t *CA, int append, char *url, uint32 urlLen), + int32 *numLoaded) +{ + psX509Cert_t *CA; + x509GeneralName_t *gn; + unsigned char *crlURI; + int32 rc, crlURILen; + + if (keys->CAcerts == NULL || crlCb == NULL) { + return PS_ARG_FAIL; + } + CA = keys->CAcerts; + + *numLoaded = rc = 0; + while (CA) { + if (CA->extensions.bc.cA > 0 && CA->extensions.crlDist != NULL) { + gn = CA->extensions.crlDist; + while (gn) { + if (gn->id == 6) { /* Only pass on URI types */ + crlURI = gn->data; + crlURILen = gn->dataLen; + /* Invoke user callback to go fetch and load the CRL. + Do not use the append flag. The specification says + that multiple names must be mechanims to access the + same CRL. */ + if (crlCb(keys->pool, CA, 0, (char*)crlURI, + crlURILen) < 0) { + rc = -1; + } + (*numLoaded)++; /* Callback successfully loaded this CRL */ + } else { + psTraceIntInfo("Unsupported CRL distro point format %d\n", + gn->id); + } + gn = gn->next; + } + } + CA = CA->next; + } + return rc; +} + +/* + If user already has a CRL buffer handy or call from the callback to load + a fetched one + + Return codes: + < 0 - Error loading CRL + >= 0 - Success +*/ +int32 matrixSslLoadCRL(psPool_t *pool, psX509Cert_t *CA, int append, + const char *CRLbin, int32 CRLbinLen, void *poolUserPtr) +{ + if (CA == NULL) { + return PS_ARG_FAIL; + } + + return psX509ParseCrl(pool, CA, append, (unsigned char*)CRLbin, CRLbinLen, + poolUserPtr); +} +#endif + +/******************************************************************************/ + diff --git a/matrixssl/matrixsslApi.h b/matrixssl/matrixsslApi.h new file mode 100644 index 0000000..b64890d --- /dev/null +++ b/matrixssl/matrixsslApi.h @@ -0,0 +1,308 @@ +/** + * @file matrixsslApi.h + * @version $Format:%h%d$ + * + * Public header file for MatrixSSL. + * Implementations interacting with the matrixssl library should + * only use the APIs and definitions used in this file. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_MATRIXSSL +#define _h_MATRIXSSL + +#ifdef __cplusplus +extern "C" { +#endif + +#include "core/coreApi.h" +#include "crypto/cryptoApi.h" + +#include "matrixsslConfig.h" +#include "matrixssllib.h" +#include "version.h" + +#ifdef USE_MATRIX_OPENSSL_LAYER +#include "opensslApi.h" +#endif + +/******************************************************************************/ +/* + Public return codes +*/ +#define MATRIXSSL_SUCCESS PS_SUCCESS /* Generic success */ +#define MATRIXSSL_ERROR PS_PROTOCOL_FAIL /* Generic SSL error */ +#define MATRIXSSL_REQUEST_SEND 1 /* API produced data to be sent */ +#define MATRIXSSL_REQUEST_RECV 2 /* API requres more data to continue */ +#define MATRIXSSL_REQUEST_CLOSE 3 /* API indicates clean close is req'd */ +#define MATRIXSSL_APP_DATA 4 /* App data is avail. to caller */ +#define MATRIXSSL_HANDSHAKE_COMPLETE 5 /* Handshake completed */ +#define MATRIXSSL_RECEIVED_ALERT 6 /* An alert was received */ +#define MATRIXSSL_APP_DATA_COMPRESSED 7 /* App data must be inflated */ + +/******************************************************************************/ +/* + Build the configuration string with the relevant build options for + runtime validation of compile-time configuration. +*/ + #define HW_CONFIG_STR "N" + +#define MATRIXSSL_CONFIG \ + "Y" \ + HW_CONFIG_STR \ + PSCRYPTO_CONFIG + +/******************************************************************************/ +/* + * Library init and close + */ +#define matrixSslOpen() matrixSslOpenWithConfig(MATRIXSSL_CONFIG) +PSPUBLIC int32 matrixSslOpenWithConfig(const char *config); +PSPUBLIC void matrixSslClose(void); + +/******************************************************************************/ +/* + * Certificate and key material loading + */ +PSPUBLIC int32 matrixSslNewKeys(sslKeys_t **keys, void *poolUserPtr); +PSPUBLIC void matrixSslDeleteKeys(sslKeys_t *keys); +#ifdef USE_RSA +PSPUBLIC int32 matrixSslLoadRsaKeys(sslKeys_t *keys, const char *certFile, + const char *privFile, const char *privPass, + const char *trustedCAFile); + +PSPUBLIC int32 matrixSslLoadRsaKeysMem(sslKeys_t *keys, + const unsigned char *certBuf, int32 certLen, + const unsigned char *privBuf, int32 privLen, + const unsigned char *trustedCABuf, int32 trustedCALen); +#endif /* USE_RSA */ +PSPUBLIC int32 matrixSslLoadPkcs12(sslKeys_t *keys, + const unsigned char *p12File, + const unsigned char *importPass, int32 ipasslen, + const unsigned char *macPass, int32 mpasslen, + int32 flags); +#ifdef USE_CRL +PSPUBLIC int32 matrixSslGetCRL(sslKeys_t *keys, + int32 (*crlCb)(psPool_t *pool, psX509Cert_t *CA, + int append, char *url, uint32 urlLen), + int32 *numLoaded); +/* memAllcocUserPtr is for TMP_PKI */ +PSPUBLIC int32 matrixSslLoadCRL(psPool_t *pool, psX509Cert_t *CA, int append, + const char *CRLbin, int32 CRLbinLen, + void *poolUserPtr); +#endif +#if defined(USE_OCSP) && defined(USE_SERVER_SIDE_SSL) +PSPUBLIC int32_t matrixSslLoadOCSPResponse(sslKeys_t *keys, + const unsigned char *OCSPResponseBuf, + uint16_t OCSPResponseBufLen); +#endif + +/******************************************************************************/ +/* + * Essential public APIs + */ +PSPUBLIC int32 matrixSslGetReadbuf(ssl_t *ssl, unsigned char **buf); +PSPUBLIC int32 matrixSslGetReadbufOfSize(ssl_t *ssl, int32 size, + unsigned char **buf); +PSPUBLIC int32 matrixSslGetOutdata(ssl_t *ssl, unsigned char **buf); +PSPUBLIC int32 matrixSslGetWritebuf(ssl_t *ssl, unsigned char **buf, + uint32 reqLen); +PSPUBLIC int32 matrixSslEncodeWritebuf(ssl_t *ssl, uint32 len); +PSPUBLIC int32 matrixSslEncodeToOutdata(ssl_t *ssl, unsigned char *buf, + uint32 len); +PSPUBLIC int32 matrixSslEncodeToUserBuf(ssl_t *ssl, unsigned char *ptBuf, + uint32 ptLen, unsigned char *ctBuf, uint32 *ctLen); +PSPUBLIC int32 matrixSslSentData(ssl_t *ssl, uint32 bytes); +PSPUBLIC int32 matrixSslReceivedData(ssl_t *ssl, uint32 bytes, + unsigned char **ptbuf, uint32 *ptlen); +PSPUBLIC int32 matrixSslProcessedData(ssl_t *ssl, + unsigned char **ptbuf, uint32 *ptlen); +PSPUBLIC int32 matrixSslEncodeClosureAlert(ssl_t *ssl); +PSPUBLIC void matrixSslDeleteSession(ssl_t *ssl); + +/******************************************************************************/ +/* + Advanced feature public APIS + */ +PSPUBLIC void matrixSslGetAnonStatus(ssl_t *ssl, int32 *anonArg); +PSPUBLIC int32_t matrixSslEncodeRehandshake(ssl_t *ssl, sslKeys_t *keys, + int32 (*certCb)(ssl_t *ssl, psX509Cert_t *cert, int32 alert), + uint32_t sessionOption, + const uint16_t cipherSpec[], uint8_t cSpecLen); +PSPUBLIC int32 matrixSslDisableRehandshakes(ssl_t *ssl); +PSPUBLIC int32 matrixSslReEnableRehandshakes(ssl_t *ssl); + +#ifdef USE_CLIENT_SIDE_SSL +/******************************************************************************/ +/* + Client side APIs +*/ +PSPUBLIC int32 matrixSslNewSessionId(sslSessionId_t **sid, void *poolUserPtr); +PSPUBLIC void matrixSslClearSessionId(sslSessionId_t *sess); +PSPUBLIC void matrixSslDeleteSessionId(sslSessionId_t *sid); +PSPUBLIC int32_t matrixSslNewClientSession(ssl_t **ssl, const sslKeys_t *keys, + sslSessionId_t *sid, + const uint16_t cipherSpec[], uint8_t cSpecLen, + sslCertCb_t certCb, + const char *expectedName, tlsExtension_t *extensions, + sslExtCb_t extCb, + sslSessOpts_t *options); +/* Hello extension support. RFC 3546 */ +PSPUBLIC int32 matrixSslNewHelloExtension(tlsExtension_t **extension, + void *poolUserPtr); +PSPUBLIC int32 matrixSslLoadHelloExtension(tlsExtension_t *extension, + unsigned char *extData, uint32 length, uint32 extType); +PSPUBLIC void matrixSslDeleteHelloExtension(tlsExtension_t *extension); +PSPUBLIC int32 matrixSslCreateSNIext(psPool_t *pool, unsigned char *host, + int32 hostLen, unsigned char **extOut, int32 *extLen); +#ifdef USE_ALPN +PSPUBLIC int32 matrixSslCreateALPNext(psPool_t *pool, int32 protoCount, + unsigned char *proto[], int32 protoLen[], + unsigned char **extOut, int32 *extLen); +#endif +#endif /* USE_CLIENT_SIDE_SSL */ +/******************************************************************************/ + +#ifdef USE_SERVER_SIDE_SSL +/******************************************************************************/ +/* + Server side APIs +*/ +PSPUBLIC int32_t matrixSslNewServerSession(ssl_t **ssl, const sslKeys_t *keys, + sslCertCb_t certCb, sslSessOpts_t *options); +PSPUBLIC int32_t matrixSslNewServer(ssl_t **ssl, + pubkeyCb_t pubkeyCb, pskCb_t pskCb, sslCertCb_t certCb, + sslSessOpts_t *options); +PSPUBLIC int32 matrixSslSetCipherSuiteEnabledStatus(ssl_t *ssl, uint16 cipherId, + uint32 status); +PSPUBLIC void matrixSslRegisterSNICallback(ssl_t *ssl, + void (*sni_cb)(void *ssl, char *hostname, int32 hostnameLen, + sslKeys_t **newKeys)); + +#ifdef USE_ALPN +PSPUBLIC void matrixSslRegisterALPNCallback(ssl_t *ssl, + void (*srv_alpn_cb)(void *ssl, short protoCount, + char *proto[MAX_PROTO_EXT], int32 protoLen[MAX_PROTO_EXT], + int32 *index)); +#endif + +#ifdef USE_STATELESS_SESSION_TICKETS +PSPUBLIC void matrixSslSetSessionTicketCallback(sslKeys_t *keys, + int32 (*ticket_cb)(void *, unsigned char[16], short)); +PSPUBLIC int32 matrixSslLoadSessionTicketKeys(sslKeys_t *keys, + const unsigned char name[16], const unsigned char *symkey, + short symkeyLen, const unsigned char *hashkey, short hashkeyLen); +PSPUBLIC int32 matrixSslDeleteSessionTicketKey(sslKeys_t *keys, + unsigned char name[16]); +#endif +#endif /* USE_SERVER_SIDE_SSL */ + + + +#ifdef USE_DTLS +/******************************************************************************/ +/* + DTLS +*/ +PSPUBLIC int32 matrixDtlsSentData(ssl_t *ssl, uint32 bytes); +PSPUBLIC int32 matrixDtlsGetOutdata(ssl_t *ssl, unsigned char **buf); +PSPUBLIC int32 matrixDtlsSetPmtu(int32 pmtu); +PSPUBLIC int32 matrixDtlsGetPmtu(void); +#endif /* USE_DTLS */ +/******************************************************************************/ + +#ifdef REQUIRE_DH_PARAMS +/******************************************************************************/ +/* + Diffie-Helloman +*/ +PSPUBLIC int32 matrixSslLoadDhParams(sslKeys_t *keys, const char *paramFile); +PSPUBLIC int32 matrixSslLoadDhParamsMem(sslKeys_t *keys, + const unsigned char *dhBin, int32 dhBinLen); +#endif /* REQUIRE_DH_PARAMS */ +/******************************************************************************/ + +#ifdef USE_PSK_CIPHER_SUITE +/******************************************************************************/ +/* + Pre-shared Keys +*/ +PSPUBLIC int32_t matrixSslLoadPsk(sslKeys_t *keys, + const unsigned char key[SSL_PSK_MAX_KEY_SIZE], uint8_t keyLen, + const unsigned char id[SSL_PSK_MAX_ID_SIZE], uint8_t idLen); +#endif /* USE_PSK_CIPHER_SUITE */ +/******************************************************************************/ + +#ifdef USE_ECC +/******************************************************************************/ +/* + Elliptic Curve Suites +*/ +PSPUBLIC int32 matrixSslLoadEcKeys(sslKeys_t *keys, const char *certFile, + const char *privFile, const char *privPass, const char *CAfile); +PSPUBLIC int32 matrixSslLoadEcKeysMem(sslKeys_t *keys, + const unsigned char *certBuf, int32 certLen, + const unsigned char *privBuf, int32 privLen, + const unsigned char *CAbuf, int32 CAlen); +PSPUBLIC int32_t matrixSslGenEphemeralEcKey(sslKeys_t *keys, + psEccKey_t *ecc, const psEccCurve_t *curve, void *hwCtx); +#endif /* USE_ECC */ + +/******************************************************************************/ + +#ifdef USE_MATRIXSSL_STATS + +enum { + STAT_CH_RECV = 1, /**< Count of ClientHellos recvd */ + STAT_CH_SENT, /**< Count of ClientHellos sent */ + STAT_SH_RECV, /**< Count of ServerHellos recvd */ + STAT_SH_SENT, /**< Count of ServerHellos sent */ + STAT_ALERT_SENT, /**< Count of Alerts sent */ + STAT_RESUMPTIONS, /**< Count of Resumptions */ + STAT_FAILED_RESUMPTIONS, /**< Count of attempted but rejected resumptions */ + STAT_APP_DATA_RECV, /**< Bytes of encoded appdata received (incl hdr/mac) */ + STAT_APP_DATA_SENT, /**< Bytes of encoded appdata sent (incl hdr/mac) */ + STAT_PT_DATA_RECV, /**< Bytes of plaintext appdata received */ +}; + +PSPUBLIC void matrixSslRegisterStatCallback(ssl_t *ssl, + void (*stat_cb)(void *ssl, void *stat_ptr, int32 type, int32 value), + void *stats); + +#endif +/******************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* _h_MATRIXSSL */ + +/******************************************************************************/ + diff --git a/matrixssl/matrixsslCheck.h b/matrixssl/matrixsslCheck.h new file mode 100644 index 0000000..2a87702 --- /dev/null +++ b/matrixssl/matrixsslCheck.h @@ -0,0 +1,1107 @@ +/** + * @file matrixsslCheck.h + * @version $Format:%h%d$ + * + * Configuration validation/sanity checks. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_MATRIXSSLCHECK +#define _h_MATRIXSSLCHECK + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ +/* + Start with compile-time checks for the necessary proto and crypto support. +*/ +#if !defined(USE_TLS) && defined(DISABLE_SSLV3) +#error "Must enable a protocol: USE_TLS enabled or DISABLE_SSLV3 disabled" +#endif + +#ifdef USE_DTLS +#ifndef USE_TLS_1_1 +#error "Must enable USE_TLS_1_1 (at a minimum) for DTLS support" +#endif +#define DTLS_MAJ_VER 0xFE +#define DTLS_MIN_VER 0xFF +#define DTLS_1_2_MIN_VER 0xFD /* DTLS 1.2 */ +#endif /* USE_DTLS */ + +#if defined(USE_TLS_1_1) && !defined(USE_TLS) +#error "Must define USE_TLS if defining USE_TLS_1_1" +#endif + +#ifdef USE_TLS +#if !defined(USE_TLS_1_2) && defined(DISABLE_TLS_1_0) && defined(DISABLE_TLS_1_1) && defined(DISABLE_SSLV3) +#error "Bad combination of USE_TLS and DISABLE_TLS" +#endif +#endif + + + +/******************************************************************************/ +/* + SHA1 and MD5 are essential elements for SSL key derivation during protocol +*/ +#if !defined USE_MD5 || !defined USE_SHA1 + #if defined(USE_TLS_1_2) && defined(DISABLE_TLS_1_0) && defined(DISABLE_TLS_1_1) \ + && defined(DISABLE_SSLV3) + #define USE_ONLY_TLS_1_2 + #else + #error "Must enable both USE_MD5 and USE_SHA1 in cryptoConfig.h for < TLS 1.2" + #endif +#endif + +#if !defined USE_CLIENT_SIDE_SSL && !defined USE_SERVER_SIDE_SSL +#error "Must enable either USE_CLIENT_SIDE_SSL or USE_SERVER_SIDE_SSL (or both)" +#endif + +#ifdef USE_TLS + #ifdef USE_HMAC_SHA256 //TODO +// #error "Must enable USE_HMAC in cryptoConfig.h for TLS protocol support" + #endif +#endif + +/* + Handle the various combos of REHANDSHAKES defines +*/ +#if defined(ENABLE_INSECURE_REHANDSHAKES) && defined(REQUIRE_SECURE_REHANDSHAKES) +#error "Can't enable both ENABLE_INSECURE_REHANDSHAKES and REQUIRE_SECURE_REHANDSHAKES" +#endif + +#if defined(ENABLE_INSECURE_REHANDSHAKES) || defined(ENABLE_SECURE_REHANDSHAKES) +#define SSL_REHANDSHAKES_ENABLED +#endif + +#if defined(REQUIRE_SECURE_REHANDSHAKES) && !defined(ENABLE_SECURE_REHANDSHAKES) +#define SSL_REHANDSHAKES_ENABLED +#define ENABLE_SECURE_REHANDSHAKES +#endif + +#ifdef USE_STATELESS_SESSION_TICKETS +#ifndef USE_HMAC_SHA256 +#error "Must enable USE_HMAC for USE_STATELESS_SESSION_TICKETS" +#endif +#ifndef USE_SHA256 +#error "Must enable USE_SHA256 for USE_STATELESS_SESSION_TICKETS" +#endif +#ifndef USE_AES +#error "Must enable USE_AES for USE_STATELESS_SESSION_TICKETS" +#endif +#endif + +/******************************************************************************/ +/* + Test specific crypto features based on which cipher suites are enabled +*/ +/** @note This cipher is deprecated from matrixsslConfig.h */ +#ifdef USE_SSL_RSA_WITH_NULL_MD5 + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for SSL_RSA_WITH_NULL_MD5 suite" + #endif + #define USE_MD5_MAC + #define USE_RSA_CIPHER_SUITE +#endif + +/** @note This cipher is deprecated from matrixsslConfig.h */ +#ifdef USE_SSL_RSA_WITH_NULL_SHA + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for SSL_RSA_WITH_NULL_SHA suite" + #endif + #define USE_SHA_MAC + #define USE_RSA_CIPHER_SUITE +#endif + +/** @note This cipher is deprecated from matrixsslConfig.h */ +#ifdef USE_SSL_RSA_WITH_RC4_128_SHA + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for SSL_RSA_WITH_RC4_128_SHA suite" + #endif + #ifndef USE_ARC4 + #error "Enable USE_ARC4 in cryptoConfig.h for SSL_RSA_WITH_RC4_128_SHA suite" + #endif + #define USE_SHA_MAC + #define USE_RSA_CIPHER_SUITE + #define USE_ARC4_CIPHER_SUITE +#endif + +/** @note This cipher is deprecated from matrixsslConfig.h */ +#ifdef USE_SSL_RSA_WITH_RC4_128_MD5 + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for SSL_RSA_WITH_RC4_128_MD5 suite" + #endif + #ifndef USE_ARC4 + #error "Enable USE_ARC4 in cryptoConfig.h for SSL_RSA_WITH_RC4_128_MD5 suite" + #endif + #define USE_MD5_MAC + #define USE_RSA_CIPHER_SUITE + #define USE_ARC4_CIPHER_SUITE +#endif + +#ifdef USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for SSL_RSA_WITH_3DES_EDE_CBC_SHA" + #endif + #ifndef USE_3DES + #error "Enable USE_3DES in cryptoConfig.h for SSL_RSA_WITH_3DES_EDE_CBC_SHA" + #endif + #define USE_SHA_MAC + #define USE_RSA_CIPHER_SUITE + #define USE_3DES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_RSA_WITH_AES_128_CBC_SHA + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_RSA_WITH_AES_128_CBC_SHA" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_RSA_WITH_AES_128_CBC_SHA" + #endif + #define USE_SHA_MAC + #define USE_AES_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE +#endif + +#ifdef USE_TLS_RSA_WITH_AES_256_CBC_SHA + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_RSA_WITH_AES_256_CBC_SHA" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_RSA_WITH_AES_256_CBC_SHA" + #endif + #define USE_SHA_MAC + #define USE_AES_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE +#endif + +/******************************************************************************/ +/* + Notes on DHE-related defines + USE_DHE_CIPHER_SUITE is used for SSL state control for ECC or DH ciphers + USE_ECC_CIPHER_SUITE is a subset of DHE_CIPHER to determine ECC key + REQUIRE_DH_PARAMS is a subset of DHE_CIPHER to use 'normal' dh params +*/ +#ifdef USE_TLS_1_2 +#ifndef USE_TLS_1_1 +#error "Enable USE_TLS_1_1 in matrixsslConfig.h for TLS_1_2 support" +#endif +#ifndef USE_SHA256 +#error "Enable USE_SHA256 in matrixsslConfig.h for TLS_1_2 support" +#endif + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + #ifndef USE_CHACHA20_POLY1305 + #error "Enable USE_CHACHA20_POLY1305 in cryptoConfig.h for USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" + #endif + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" + #endif + #define USE_DHE_CIPHER_SUITE + #define USE_ECDSA_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_CHACHA20_POLY1305_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" + #endif + #ifndef USE_CHACHA20_POLY1305 + #error "Enable USE_CHACHA20_POLY1305 in cryptoConfig.h for USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" + #endif + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" + #endif + #define USE_DHE_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_CHACHA20_POLY1305_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + #ifndef USE_AES_GCM + #error "Enable USE_AES_GCM in cryptoConfig.h for USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" + #endif + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" + #endif + #define USE_DHE_CIPHER_SUITE + #define USE_ECDSA_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + #ifndef USE_AES_GCM + #error "Enable USE_AES_GCM in cryptoConfig.h for USE_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" + #endif + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for USE_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for USE_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" + #endif + #ifndef USE_SHA384 + #error "Enable USE_SHA384 in cryptoConfig.h for USE_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" + #endif + #define USE_DHE_CIPHER_SUITE + #define USE_ECDSA_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_RSA_WITH_AES_128_CBC_SHA256 + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_RSA_WITH_AES_128_CBC_SHA256" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_RSA_WITH_AES_128_CBC_SHA256" + #endif + #define USE_SHA_MAC + #define USE_AES_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE +#endif + +#ifdef USE_TLS_RSA_WITH_AES_256_CBC_SHA256 + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_RSA_WITH_AES_256_CBC_SHA256" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_RSA_WITH_AES_256_CBC_SHA256" + #endif + #define USE_SHA_MAC + #define USE_AES_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE +#endif + +#ifdef USE_TLS_RSA_WITH_AES_256_GCM_SHA384 + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_RSA_WITH_AES_256_GCM_SHA384" + #endif + #ifndef USE_AES_GCM + #error "Enable USE_AES_GCM in cryptoConfig.h for TLS_RSA_WITH_AES_256_GCM_SHA384" + #endif + #ifndef USE_SHA384 + #error "Enable USE_SHA384 in cryptoConfig.h for TLS_RSA_WITH_AES_256_GCM_SHA384" + #endif + #define USE_AES_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE +#endif + +#ifdef USE_TLS_RSA_WITH_AES_128_GCM_SHA256 + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_RSA_WITH_AES_128_GCM_SHA256" + #endif + #ifndef USE_AES_GCM + #error "Enable USE_AES_GCM in cryptoConfig.h for TLS_RSA_WITH_AES_128_GCM_SHA256" + #endif + #define USE_AES_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE +#endif + +#ifdef USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_DHE_RSA_WITH_AES_128_CBC_SHA256" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_DHE_RSA_WITH_AES_128_CBC_SHA256" + #endif + #ifndef USE_DH + #error "Enable USE_DH in cryptoConfig.h for TLS_DHE_RSA_WITH_AES_128_CBC_SHA256" + #endif + #define REQUIRE_DH_PARAMS + #define USE_SHA_MAC + #define USE_DHE_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE +#endif + +#ifdef USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_DHE_RSA_WITH_AES_256_CBC_SHA256" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_DHE_RSA_WITH_AES_256_CBC_SHA256" + #endif + #ifndef USE_DH + #error "Enable USE_DH in cryptoConfig.h for TLS_DHE_RSA_WITH_AES_256_CBC_SHA256" + #endif + #define REQUIRE_DH_PARAMS + #define USE_SHA_MAC + #define USE_DHE_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256" + #endif + #define USE_SHA_MAC + #define USE_DHE_CIPHER_SUITE + #define USE_ECDSA_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384" + #endif + #ifndef USE_SHA384 + #error "Enable USE_SHA384 in cryptoConfig.h for TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384" + #endif + #define USE_SHA_MAC + #define USE_DHE_CIPHER_SUITE + #define USE_ECDSA_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384" + #endif + #ifndef USE_SHA384 + #error "Enable USE_SHA384 in cryptoConfig.h for USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384" + #endif + #define USE_SHA_MAC + #define USE_DH_CIPHER_SUITE + #define USE_ECDSA_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256" + #endif + #define USE_SHA_MAC + #define USE_DH_CIPHER_SUITE + #define USE_ECDSA_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + #ifndef USE_AES_GCM + #error "Enable USE_AES_GCM in cryptoConfig.h for TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256" + #endif + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256" + #endif + #define USE_DH_CIPHER_SUITE + #define USE_ECDSA_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + #ifndef USE_AES_GCM + #error "Enable USE_AES_GCM in cryptoConfig.h for TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384" + #endif + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384" + #endif + #ifndef USE_SHA384 + #error "Enable USE_SHA384 in cryptoConfig.h for TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384" + #endif + #define USE_DH_CIPHER_SUITE + #define USE_ECDSA_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" + #endif + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" + #endif + #define USE_SHA_MAC + #define USE_DHE_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" + #endif + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" + #endif + #ifndef USE_SHA384 + #error "Enable USE_SHA384 in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" + #endif + #define USE_SHA_MAC + #define USE_DHE_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + #ifndef USE_AES_GCM + #error "Enable USE_AES_GCM in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + #endif + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + #endif + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + #endif + #define USE_DHE_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + #ifndef USE_AES_GCM + #error "Enable USE_AES_GCM in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" + #endif + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" + #endif + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" + #endif + #ifndef USE_SHA384 + #error "Enable USE_SHA384 in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" + #endif + #define USE_DHE_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384" + #endif + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384" + #endif + #ifndef USE_AES_GCM + #error "Enable USE_AES_GCM in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384" + #endif + #ifndef USE_SHA384 + #error "Enable USE_SHA384 in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384" + #endif + #define USE_DH_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256" + #endif + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256" + #endif + #ifndef USE_AES_GCM + #error "Enable USE_AES_GCM in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256" + #endif + #define USE_DH_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384" + #endif + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384" + #endif + #ifndef USE_SHA384 + #error "Enable USE_SHA384 in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384" + #endif + #define USE_SHA_MAC + #define USE_DH_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256" + #endif + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256" + #endif + #define USE_SHA_MAC + #define USE_DH_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif +#endif /* USE_TLS_1_2 */ + +#ifdef USE_TLS_1_1 + #ifndef USE_TLS + #error "Enable USE_TLS in matrixsslConfig.h for TLS_1_1 support" + #endif +#endif + +#ifndef USE_TLS_1_2 + #if defined(USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) || \ + defined(USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for CHACHA20_POLY1305 cipher suites" + #endif + #ifdef USE_TLS_RSA_WITH_AES_128_CBC_SHA256 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_RSA_WITH_AES_128_CBC_SHA256" + #endif + #ifdef USE_TLS_RSA_WITH_AES_256_CBC_SHA256 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_RSA_WITH_AES_256_CBC_SHA256" + #endif + #ifdef USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_DHE_RSA_WITH_AES_128_CBC_SHA256" + #endif + #ifdef USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_DHE_RSA_WITH_AES_256_CBC_SHA256" + #endif + #ifdef USE_TLS_RSA_WITH_AES_128_GCM_SHA256 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_RSA_WITH_AES_128_GCM_SHA256" + #endif + #ifdef USE_TLS_RSA_WITH_AES_256_GCM_SHA384 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_RSA_WITH_AES_256_GCM_SHA384" + #endif + #ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" + #endif + #ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" + #endif + #ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256" + #endif + #ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384" + #endif + #ifdef USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" + #endif + #ifdef USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" + #endif + #ifdef USE_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" + #endif + #ifdef USE_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + #endif + #ifdef USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256" + #endif + #ifdef USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384" + #endif + #ifdef USE_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256" + #endif + #ifdef USE_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384" + #endif + #ifdef USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384" + #endif + #ifdef USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256" + #endif + #ifdef USE_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384" + #endif + #ifdef USE_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + #error "Enable USE_TLS_1_2 in matrixsslConfig.h for TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 " + #endif +#endif /* ! TLS_1_2 */ + +/** @note This cipher is deprecated from matrixsslConfig.h */ +#ifdef USE_SSL_DH_anon_WITH_3DES_EDE_CBC_SHA + #ifndef USE_3DES + #error "Enable USE_3DES in cryptoConfig.h for SSL_DH_anon_WITH_3DES_EDE_CBC_SHA" + #endif + #ifndef USE_DH + #error "Enable USE_DH in cryptoConfig.h for SSL_DH_anon_WITH_3DES_EDE_CBC_SHA" + #endif + #define REQUIRE_DH_PARAMS + #define USE_ANON_DH_CIPHER_SUITE + #define USE_DHE_CIPHER_SUITE + #define USE_3DES_CIPHER_SUITE + #define USE_SHA_MAC +#endif + +/** @note This cipher is deprecated from matrixsslConfig.h */ +#ifdef USE_SSL_DH_anon_WITH_RC4_128_MD5 + #ifndef USE_ARC4 + #error "Enable USE_ARC4 in cryptoConfig.h for SSL_DH_anon_WITH_RC4_128_MD5" + #endif + #ifndef USE_DH + #error "Enable USE_DH in cryptoConfig.h for SSL_DH_anon_WITH_RC4_128_MD5" + #endif + #define REQUIRE_DH_PARAMS + #define USE_ANON_DH_CIPHER_SUITE + #define USE_DHE_CIPHER_SUITE + #define USE_ARC4_CIPHER_SUITE + #define USE_MD5_MAC +#endif + +#ifdef USE_SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA" + #endif + #ifndef USE_3DES + #error "Enable USE_3DES in cryptoConfig.h for SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA" + #endif + #ifndef USE_DH + #error "Enable USE_DH in cryptoConfig.h for SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA" + #endif + #define REQUIRE_DH_PARAMS + #define USE_SHA_MAC + #define USE_DHE_CIPHER_SUITE + #define USE_3DES_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE +#endif + +#ifdef USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_DHE_RSA_WITH_AES_128_CBC_SHA" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_DHE_RSA_WITH_AES_128_CBC_SHA" + #endif + #ifndef USE_DH + #error "Enable USE_DH in cryptoConfig.h for TLS_DHE_RSA_WITH_AES_128_CBC_SHA" + #endif + #define REQUIRE_DH_PARAMS + #define USE_SHA_MAC + #define USE_DHE_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE +#endif + +#ifdef USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_DHE_RSA_WITH_AES_256_CBC_SHA" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_DHE_RSA_WITH_AES_256_CBC_SHA" + #endif + #ifndef USE_DH + #error "Enable USE_DH in cryptoConfig.h for TLS_DHE_RSA_WITH_AES_256_CBC_SHA" + #endif + #define REQUIRE_DH_PARAMS + #define USE_SHA_MAC + #define USE_DHE_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE +#endif + +#ifdef USE_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_DHE_PSK_WITH_AES_128_CBC_SHA" + #endif + #ifndef USE_DH + #error "Enable USE_DH in cryptoConfig.h for TLS_DHE_PSK_WITH_AES_128_CBC_SHA" + #endif + #if !defined(USE_TLS) && !defined(USE_DTLS) + #error "Enable USE_TLS in matrixsslConfig.h for TLS_DHE_PSK_WITH_AES_128_CBC_SHA" + #endif + #define REQUIRE_DH_PARAMS + #define USE_SHA_MAC + #define USE_ANON_DH_CIPHER_SUITE + #define USE_DHE_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE + #define USE_PSK_CIPHER_SUITE + #define USE_DHE_PSK_CIPHER_SUITE +#endif + +#ifdef USE_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_DHE_PSK_WITH_AES_256_CBC_SHA" + #endif + #ifndef USE_DH + #error "Enable USE_DH in cryptoConfig.h for TLS_DHE_PSK_WITH_AES_256_CBC_SHA" + #endif + #if !defined(USE_TLS) && !defined(USE_DTLS) + #error "Enable USE_TLS in matrixsslConfig.h for TLS_DHE_PSK_WITH_AES_256_CBC_SHA" + #endif + #define REQUIRE_DH_PARAMS + #define USE_SHA_MAC + #define USE_ANON_DH_CIPHER_SUITE + #define USE_DHE_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE + #define USE_PSK_CIPHER_SUITE + #define USE_DHE_PSK_CIPHER_SUITE +#endif + +#ifdef USE_TLS_PSK_WITH_AES_256_CBC_SHA + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_PSK_WITH_AES_256_CBC_SHA" + #endif + #if !defined(USE_TLS) && !defined(USE_DTLS) + #error "Enable USE_TLS in matrixsslConfig.h for TLS_PSK_WITH_AES_256_CBC_SHA" + #endif + #define USE_SHA_MAC + #define USE_AES_CIPHER_SUITE + #define USE_PSK_CIPHER_SUITE +#endif + +#ifdef USE_TLS_PSK_WITH_AES_128_CBC_SHA + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_PSK_WITH_AES_128_CBC_SHA" + #endif + #if !defined(USE_TLS) && !defined(USE_DTLS) + #error "Enable USE_TLS in matrixsslConfig.h for TLS_PSK_WITH_AES_128_CBC_SHA" + #endif + #define USE_SHA_MAC + #define USE_AES_CIPHER_SUITE + #define USE_PSK_CIPHER_SUITE +#endif + +#ifdef USE_TLS_PSK_WITH_AES_128_CBC_SHA256 + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_PSK_WITH_AES_128_CBC_SHA256" + #endif + #if !defined(USE_TLS) && !defined(USE_DTLS) + #error "Enable USE_TLS in matrixsslConfig.h for TLS_PSK_WITH_AES_128_CBC_SHA256" + #endif + #ifndef USE_SHA256 + #error "Enable USE_SHA256 in cryptoConfig.h for TLS_PSK_WITH_AES_128_CBC_SHA256" + #endif + #define USE_SHA_MAC + #define USE_AES_CIPHER_SUITE + #define USE_PSK_CIPHER_SUITE +#endif + +#ifdef USE_TLS_PSK_WITH_AES_256_CBC_SHA384 + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_PSK_WITH_AES_256_CBC_SHA384" + #endif + #if !defined(USE_TLS) && !defined(USE_DTLS) + #error "Enable USE_TLS in matrixsslConfig.h for TLS_PSK_WITH_AES_256_CBC_SHA384" + #endif + #ifndef USE_SHA384 + #error "Enable USE_SHA384 in cryptoConfig.h for TLS_PSK_WITH_AES_256_CBC_SHA384" + #endif + #define USE_SHA_MAC + #define USE_AES_CIPHER_SUITE + #define USE_PSK_CIPHER_SUITE +#endif + +/** @note This cipher is deprecated from matrixsslConfig.h */ +#ifdef USE_TLS_DH_anon_WITH_AES_128_CBC_SHA + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_DH_anon_WITH_AES_128_CBC_SHA" + #endif + #ifndef USE_DH + #error "Enable USE_DH in cryptoConfig.h for TLS_DH_anon_WITH_AES_128_CBC_SHA" + #endif + #define REQUIRE_DH_PARAMS + #define USE_SHA_MAC + #define USE_ANON_DH_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE + #define USE_DHE_CIPHER_SUITE +#endif + +/** @note This cipher is deprecated from matrixsslConfig.h */ +#ifdef USE_TLS_DH_anon_WITH_AES_256_CBC_SHA + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_DH_anon_WITH_AES_256_CBC_SHA" + #endif + #ifndef USE_DH + #error "Enable USE_DH in cryptoConfig.h for TLS_DH_anon_WITH_AES_256_CBC_SHA" + #endif + #define REQUIRE_DH_PARAMS + #define USE_SHA_MAC + #define USE_ANON_DH_CIPHER_SUITE + #define USE_DHE_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +/** @note This cipher is deprecated from matrixsslConfig.h */ +#ifdef USE_TLS_RSA_WITH_SEED_CBC_SHA + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_RSA_WITH_SEED_CBC_SHA" + #endif + #ifndef USE_SEED + #error "Enable USE_SEED in cryptoConfig.h for TLS_RSA_WITH_SEED_CBC_SHA" + #endif + #define USE_SHA_MAC + #define USE_RSA_CIPHER_SUITE + #define USE_SEED_CIPHER_SUITE +#endif + +/** @note This cipher is deprecated from matrixsslConfig.h */ +#ifdef USE_TLS_RSA_WITH_IDEA_CBC_SHA + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_RSA_WITH_IDEA_CBC_SHA" + #endif + #ifndef USE_IDEA + #error "Enable USE_IDEA in cryptoConfig.h for TLS_RSA_WITH_IDEA_CBC_SHA" + #endif + #define USE_SHA_MAC + #define USE_IDEA_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA" + #endif + #define USE_SHA_MAC + #define USE_DH_CIPHER_SUITE + #define USE_ECDSA_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA" + #endif + #define USE_SHA_MAC + #define USE_DH_CIPHER_SUITE + #define USE_ECDSA_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA" + #endif + #define USE_SHA_MAC + #define USE_DHE_CIPHER_SUITE + #define USE_ECDSA_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA" + #endif + #define USE_SHA_MAC + #define USE_DHE_CIPHER_SUITE + #define USE_ECDSA_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA" + #endif + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA" + #endif + #define USE_SHA_MAC + #define USE_DHE_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" + #endif + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" + #endif + #define USE_SHA_MAC + #define USE_DHE_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA" + #endif + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA" + #endif + #ifndef USE_3DES + #error "Enable USE_3DES in cryptoConfig.h for TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA" + #endif + #define USE_SHA_MAC + #define USE_DHE_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE + #define USE_3DES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_256_CBC_SHA" + #endif + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_256_CBC_SHA" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_256_CBC_SHA" + #endif + #define USE_SHA_MAC + #define USE_DH_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +#ifdef USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + #ifndef USE_ECC + #error "Enable USE_ECC in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_128_CBC_SHA" + #endif + #ifndef USE_RSA + #error "Enable USE_RSA in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_128_CBC_SHA" + #endif + #ifndef USE_AES + #error "Enable USE_AES in cryptoConfig.h for TLS_ECDH_RSA_WITH_AES_128_CBC_SHA" + #endif + #define USE_SHA_MAC + #define USE_DH_CIPHER_SUITE + #define USE_ECC_CIPHER_SUITE + #define USE_RSA_CIPHER_SUITE + #define USE_AES_CIPHER_SUITE +#endif + +/******************************************************************************/ +/* + If only PSK suites have been enabled (non-DHE), flip on the USE_ONLY_PSK + define to create the smallest version of the library. If this is hit, the + user can disable USE_X509, USE_RSA, USE_ECC, and USE_PRIVATE_KEY_PARSING in + cryptoConfig.h. +*/ +#if !defined(USE_RSA_CIPHER_SUITE) && !defined(USE_DHE_CIPHER_SUITE) && \ + !defined(USE_DH_CIPHER_SUITE) +#define USE_ONLY_PSK_CIPHER_SUITE +#ifndef USE_X509 +typedef int32 psX509Cert_t; +#endif +#endif /* !RSA && !DH */ + +#if !defined(USE_RSA_CIPHER_SUITE) && !defined(USE_DH_CIPHER_SUITE) && \ + defined(USE_DHE_PSK_CIPHER_SUITE) +#define USE_ONLY_PSK_CIPHER_SUITE +#ifndef USE_X509 +typedef int32 psX509Cert_t; +#endif +#endif /* DHE_PSK only */ + +#if !defined(USE_CERT_PARSE) && !defined(USE_ONLY_PSK_CIPHER_SUITE) +#ifdef USE_CLIENT_SIDE_SSL +#error "Must enable USE_CERT_PARSE if building client with USE_CLIENT_SIDE_SSL" +#endif +#ifdef USE_CLIENT_AUTH +#error "Must enable USE_CERT_PARSE if client auth (USE_CLIENT_AUTH) is needed" +#endif +#endif + +#ifdef USE_TRUSTED_CA_INDICATION + #ifndef ENABLE_CA_CERT_HASH + #error "Define ENABLE_CA_CERT_HASH in cryptoConfig.h for Trusted CA Indication" + #endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _h_MATRIXSSLCHECK */ + +/******************************************************************************/ + diff --git a/matrixssl/matrixsslConfig.h b/matrixssl/matrixsslConfig.h new file mode 100644 index 0000000..1d3b18e --- /dev/null +++ b/matrixssl/matrixsslConfig.h @@ -0,0 +1,335 @@ +/** + * @file matrixsslConfig.h + * @version $Format:%h%d$ + * + * Configuration settings for building the MatrixSSL library. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_MATRIXSSLCONFIG +#define _h_MATRIXSSLCONFIG + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + NIST SP 800-52 Rev 1 Conformance. + Guidelines for the Selection, Configuration, and Use of Transport Layer + Security (TLS) Implementations + The key words "shall", "shall not", "should", "should not" and "may" + are used as references to the NIST SP 800-52 Rev 1. Algorithms marked as + "shall" must not be disabled unless NIST SP 800-52 Rev 1 compatibility + is not relevant. + @see http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-52r1.pdf +*/ + +/******************************************************************************/ +/** + Show which SSL messages are created and parsed +*/ +//#define USE_SSL_HANDSHAKE_MSG_TRACE + +/** + Informational trace that could help pinpoint problems with SSL connections +*/ +//#define USE_SSL_INFORMATIONAL_TRACE +//#define USE_DTLS_DEBUG_TRACE + +/******************************************************************************/ +/** + Recommended cipher suites. + Define the following to enable various cipher suites + At least one of these must be defined. If multiple are defined, + the handshake negotiation will determine which is best for the connection. + @note Ephemeral ciphersuites offer perfect forward security (PFS) + at the cost of a slower TLS handshake. +*/ + +/** Ephemeral ECC DH keys, ECC DSA certificates */ +#define USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA /**< @security NIST_SHOULD */ +#define USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA /**< @security NIST_MAY */ +/* TLS 1.2 ciphers */ +#define USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 /**< @security NIST_SHOULD */ +#define USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 /**< @security NIST_MAY */ +#define USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 /**< @security NIST_SHOULD */ +#define USE_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 /**< @security NIST_SHOULD */ +//#define USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + +/** Ephemeral ECC DH keys, RSA certificates */ +#define USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA /**< @security NIST_SHOULD */ +#define USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +/* TLS 1.2 ciphers */ +#define USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 /**< @security NIST_SHOULD */ +#define USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 /**< @security NIST_MAY */ +#define USE_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 /**< @security NIST_SHOULD */ +#define USE_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 /**< @security NIST_SHOULD */ +//#define USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + +/** Ephemeral Diffie-Hellman ciphersuites, with RSA certificates */ +//#define USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA +//#define USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA +/* TLS 1.2 ciphers */ +//#define USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 +//#define USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + +/** Non-Ephemeral RSA keys/certificates */ +#define USE_TLS_RSA_WITH_AES_128_CBC_SHA /**< @security NIST_SHALL */ +#define USE_TLS_RSA_WITH_AES_256_CBC_SHA /**< @security NIST_SHOULD */ +/* TLS 1.2 ciphers */ +#define USE_TLS_RSA_WITH_AES_128_CBC_SHA256 /**< @security NIST_MAY */ +#define USE_TLS_RSA_WITH_AES_256_CBC_SHA256 /**< @security NIST_MAY */ +#define USE_TLS_RSA_WITH_AES_128_GCM_SHA256 /**< @security NIST_SHALL */ +#define USE_TLS_RSA_WITH_AES_256_GCM_SHA384 /**< @security NIST_SHOULD */ + +/******************************************************************************/ +/** + These cipher suites are secure, but not widely deployed. +*/ + +/** Ephemeral Diffie-Hellman ciphersuites, with RSA certificates */ +//#define USE_SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA + +/** Ephemeral Diffie-Hellman ciphersuites, with PSK authentication */ +//#define USE_TLS_DHE_PSK_WITH_AES_128_CBC_SHA /**< @security NIST_SHOULD_NOT */ +//#define USE_TLS_DHE_PSK_WITH_AES_256_CBC_SHA /**< @security NIST_SHOULD_NOT */ + +/** Ephemeral ECC DH keys, RSA certificates */ +//#define USE_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA /**< @security NIST_SHOULD */ + +/** Pre-Shared Key Ciphers. + NIST SP 800-52 Rev 1 recommends against using PSK unless neccessary + See NIST SP 800-52 Rev 1 Appendix C */ +//#define USE_TLS_PSK_WITH_AES_128_CBC_SHA /**< @security NIST_SHOULD_NOT */ +//#define USE_TLS_PSK_WITH_AES_256_CBC_SHA /**< @security NIST_SHOULD_NOT */ +/* TLS 1.2 ciphers */ +//#define USE_TLS_PSK_WITH_AES_128_CBC_SHA256 /**< @security NIST_SHOULD_NOT */ +//#define USE_TLS_PSK_WITH_AES_256_CBC_SHA384 /**< @security NIST_SHOULD_NOT */ + +/** Non-Ephemeral ECC DH keys, ECC DSA certificates */ +//#define USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA /**< @security NIST_MAY */ +//#define USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA /**< @security NIST_MAY */ +/* TLS 1.2 ciphers */ +//#define USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 /**< @security NIST_MAY */ +//#define USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 /**< @security NIST_MAY */ +//#define USE_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 /**< @security NIST_MAY */ +//#define USE_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 /**< @security NIST_MAY */ + +/** Non-Ephemeral ECC DH keys, RSA certificates */ +//#define USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA +//#define USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA +/* TLS 1.2 ciphers */ +//#define USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 +//#define USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 +//#define USE_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 +//#define USE_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + +/** Non-Ephemeral RSA keys/certificates */ +//#define USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA /**< @security NIST_SHALL */ + +/** @note Some of (non-mandatory) cipher suites mentioned in NIST SP 800-52 + Rev 1 are not supported by the MatrixSSL / MatrixDTLS. + ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA (NIST SP 800-52 Rev 1 "should") + is rarely used cipher suite and is not supported. + Also (NIST SP 800-52 Rev 1 "may") TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + TLS_DHE_DSS_WITH_* and TLS_RSA_WITH_AES_*_CCM cipher suites cannot be + enabled as they are not supported. */ + +/******************************************************************************/ +/** + Ephemeral key cache support. + If not using cache, new key exchange keys are created for each TLS session. + If using cache, keys are generated initially, and re-used in each + subsequent TLS connection within a given time frame and usage count. + @see ECC_EPHEMERAL_CACHE_SECONDS and ECC_EPHEMERAL_CACHE_USAGE + + @security Do not cache Ephemeral ECC keys as it is against some standards, + including NIST SP 800-56A. +*/ +#ifdef USE_NIST_GUIDELINES +#define NO_ECC_EPHEMERAL_CACHE /**< @security NIST_SHALL */ +#endif + +/******************************************************************************/ +/** + Configure Support for TLS protocol versions. + Define one of: + USE_TLS_1_2_AND_ABOVE + USE_TLS_1_1_AND_ABOVE + USE_TLS_1_0_AND_ABOVE + @note There is no option for enabling SSL3.0 at this level +*/ +#define USE_TLS_1_1_AND_ABOVE /**< @security default 1_1_AND_ABOVE */ + +/******************************************************************************/ +/** + Datagram TLS support. + Enables DTLS in addition to TLS. + @pre TLS_1_1 +*/ +//#define USE_DTLS + +/******************************************************************************/ +/** + Compile time support for server or client side SSL +*/ +#define USE_CLIENT_SIDE_SSL +#define USE_SERVER_SIDE_SSL + +/******************************************************************************/ +/** + Client certifiate authentication +*/ +#define USE_CLIENT_AUTH + +/** + Enable if the server should send an empty CertificateRequest message if + no CA files have been loaded +*/ +//#define SERVER_CAN_SEND_EMPTY_CERT_REQUEST + +/** + Enabling this define will allow the server to "downgrade" a client auth + handshake to a standard handshake if the client replies to a + CERTIFICATE_REQUEST with an empty CERTIFICATE message. The user callback + will be called with a NULL cert in this case and the user can determine if + the handshake should continue in a non-client auth state. +*/ +//#define SERVER_WILL_ACCEPT_EMPTY_CLIENT_CERT_MSG + +/******************************************************************************/ +/** + Enable the Application Layer Protocol Negotiation extension. + Servers and Clients will still have to use the required public API to + set protocols and register application callbacks to negotiate the + protocol that will be tunneled over TLS. + @see ALPN section in the developer's guide for information. + */ +//#define USE_ALPN + +/******************************************************************************/ +/** + Enable the Trusted CA Indication CLIENT_HELLO extension. Will send the + sha1 hash of each CA file to the server for help in server selection. + This extra level of define is to help isolate the SHA1 requirement +*/ +//#define USE_TRUSTED_CA_INDICATION /**< @security NIST_SHOULD */ + +/******************************************************************************/ +/** + A client side configuration that requires a server to provide an OCSP + response if the client uses the certitificate status request extension. + The "must staple" terminology is typically associated with certificates + at the X.509 layer but it is a good description of what is being required + of the server at the TLS level. + @pre USE_OCSP must be enbled at the crypto level and the client application + must use the OCSPstapling session option at run time for this setting to + have any effect +*/ +#ifdef USE_OCSP +#define USE_OCSP_MUST_STAPLE /**< @security NIST_SHALL */ +#endif + +/******************************************************************************/ +/** + Rehandshaking support. + + Enabling USE_REHANDSHAKING will allow secure-rehandshakes using the + protocol defined in RFC 5748 which fixed a critical exploit in + the standard TLS specification. + + @security Looking towards TLS 1.3, which removes re-handshaking, this + feature is disabled by default. +*/ +//#define USE_REHANDSHAKING + +/******************************************************************************/ +/** + If SERVER you may define the number of sessions to cache and how + long a session will remain valid in the cache from first access. + Session caching enables very fast "session resumption handshakes". + + SSL_SESSION_TABLE_SIZE minimum value is 1 + SSL_SESSION_ENTRY_LIFE is in milliseconds, minimum 0 + + @note Session caching can be disabled by setting SSL_SESSION_ENTRY_LIFE to 0 + however, this will also immediately expire SESSION_TICKETS below. +*/ +#ifdef USE_SERVER_SIDE_SSL +#define SSL_SESSION_TABLE_SIZE 32 +#define SSL_SESSION_ENTRY_LIFE (86400*1000) /* one day, in milliseconds */ +#endif + +/******************************************************************************/ +/** + Use RFC 5077 session resumption mechanism. The SSL_SESSION_ENTRY_LIFE + define applies to this method as well as the standard method. The + SSL_SESSION_TICKET_LIST_LEN is the max size of the server key list. +*/ +#define USE_STATELESS_SESSION_TICKETS + +/******************************************************************************/ +/** + The initial buffer sizes for send and receive buffers in each ssl_t session. + Buffers are internally grown if more incoming or outgoing data storage is + needed, up to a maximum of SSL_MAX_BUF_SIZE. Once the memory used by the + buffer again drops below SSL_DEFAULT_X_BUF_SIZE, the buffer will be reduced + to this size. Most standard SSL handshakes require on the order of 1024 B. + + SSL_DEFAULT_x_BUF_SIZE value in bytes, maximum SSL_MAX_BUF_SIZE + */ +#ifndef USE_DTLS +#define SSL_DEFAULT_IN_BUF_SIZE 1500 /* Base recv buf size, bytes */ +#define SSL_DEFAULT_OUT_BUF_SIZE 1500 /* Base send buf size, bytes */ +#else +/******************************************************************************/ +/** + The Path Maximum Transmission Unit is the largest datagram that can be + sent or recieved. It is beyond the scope of DTLS to negotiate this value + so make sure both sides have agreed on this value. This is an enforced + limitation in MatrixDTLS so connections will not succeed if a peer has a + PTMU set larger than this value. +*/ +#define DTLS_PMTU 1500 /* 1500 Default/Maximum datagram len */ +#define SSL_DEFAULT_IN_BUF_SIZE DTLS_PMTU /* See PMTU comments above */ +#define SSL_DEFAULT_OUT_BUF_SIZE DTLS_PMTU /* See PMTU comments above */ + +//#define DTLS_SEND_RECORDS_INDIVIDUALLY /* Max one record per datagram */ +#endif + + + +#ifdef __cplusplus +} +#endif + +#endif /* _h_MATRIXCONFIG */ +/******************************************************************************/ + diff --git a/matrixssl/matrixssllib.h b/matrixssl/matrixssllib.h new file mode 100644 index 0000000..21b0f59 --- /dev/null +++ b/matrixssl/matrixssllib.h @@ -0,0 +1,1705 @@ +/** + * @file matrixssllib.h + * @version $Format:%h%d$ + * + * Internal header file used for the MatrixSSL implementation.. + * Only modifiers of the library should be intersted in this file + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_MATRIXSSLLIB +#define _h_MATRIXSSLLIB + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************/ +/** + Additional 'hidden' TLS configuration here for deprecated support. + @security These options allow enabling/disabling features that have been + found to generally considered weak and should not be changed except for + compatibility with older software that cannot be changed. + @security The default value for strongest security is indicated for each + option. +*/ +/** Deprecated cipher suites. */ +#ifndef USE_DTLS +//#define USE_SSL_RSA_WITH_RC4_128_MD5 /**< @security OFF */ +//#define USE_SSL_RSA_WITH_RC4_128_SHA /**< @security OFF */ +//#define USE_TLS_RSA_WITH_SEED_CBC_SHA /**< @security OFF */ +//#define USE_TLS_RSA_WITH_IDEA_CBC_SHA /**< @security OFF */ +#endif + +/** Anonymous, non authenticated ciphers. */ +//#define USE_TLS_DH_anon_WITH_AES_128_CBC_SHA /**< @security OFF */ +//#define USE_TLS_DH_anon_WITH_AES_256_CBC_SHA /**< @security OFF */ +//#define USE_SSL_DH_anon_WITH_3DES_EDE_CBC_SHA /**< @security OFF */ +#ifndef USE_DTLS +//#define USE_SSL_DH_anon_WITH_RC4_128_MD5 /**< @security OFF */ +#endif + +/** Authenticated but not encrypted ciphers. */ +//#define USE_SSL_RSA_WITH_NULL_SHA /**< @security OFF */ +//#define USE_SSL_RSA_WITH_NULL_MD5 /**< @security OFF */ + +/** + False Start support for Chrome browser. + @see http://tools.ietf.org/html/draft-bmoeller-tls-falsestart-00 + + @note April 2012: Google has announced this feature will be removed in + version 20 of their browser due to industry compatibility issues. + + @note November 2016: An official IETF draft is in process for this + functionality to become standardized. + @see https://datatracker.ietf.org/doc/draft-ietf-tls-falsestart/ +*/ +//#define ENABLE_FALSE_START /**< @security OFF */ + +/** + zlib compression support. + @security The CRIME attack on HTTPS has shown that compression at the + TLS layer can introduce vulnerabilities in higher level protocols. It is + recommended to NOT use compression features at the TLS level. +*/ +//#define USE_ZLIB_COMPRESSION /**< @security OFF NIST_SHOULD_NOT */ + + +/******************************************************************************/ +/** + Rehandshaking support. + In late 2009 An "authentication gap" exploit was discovered in the + SSL re-handshaking protocol. The fix to the exploit was introduced + in RFC 5746 and is referred to here as SECURE_REHANDSHAKES. + + ENABLE_SECURE_REHANDSHAKES implements RFC 5746 and will securely + renegotiate with any implementations that support it. It is + recommended to leave this disabled unless there is a specific requirement + to support it. + + By enabling REQUIRE_SECURE_REHANDSHAKES, the library will test that each + communicating peer that is attempting to connect has implemented + RFC 5746 and will terminate handshakes with any that have not. + + If working with SSL peers that have not implemented RFC 5746 and + rehandshakes are required, you may enable ENABLE_INSECURE_REHANDSHAKES + but it is NOT RECOMMENDED + + It is a conflict to enable both ENABLE_INSECURE_REHANDSHAKES and + REQUIRE_SECURE_REHANDSHAKES and a compile error will occur + + To completely disable rehandshaking comment out all three of these defines + + @security Disabling handshaking altogether is the most secure. If it must + be enabled, only secure rehandshakes should be allowed. Other modes below + are provided only for compatibility with old TLS/SSL libraries. +*/ +#ifdef USE_REHANDSHAKING +//#define ENABLE_SECURE_REHANDSHAKES /**< @security OFF NIST_SHALL */ +#define REQUIRE_SECURE_REHANDSHAKES /**< @security ON NIST_SHALL */ +//#define ENABLE_INSECURE_REHANDSHAKES /** @security OFF NIST_SHALL_NOT */ +#endif + +/******************************************************************************/ +/** + Beast Mode. + In Sept. 2011 security researchers demonstrated how a previously known + CBC encryption weakness could be used to decrypt HTTP data over SSL. + The attack was named BEAST (Browser Exploit Against SSL/TLS). + + This issue only affects TLS 1.0 (and SSL) and only if the cipher suite + is using a symmetric CBC block cipher. Enable USE_TLS_1_1 above to + completely negate this workaround if TLS 1.1 is also supported by peers. + + As with previous SSL vulnerabilities, the attack is generally considered + a very low risk for individual browsers as it requires the attacker + to have control over the network to become a MITM. They will also have + to have knowledge of the first couple blocks of underlying plaintext + in order to mount the attack. + + A zero length record proceeding a data record has been a known fix to this + problem for years and MatrixSSL has always supported the handling of empty + records. So alternatively, an implementation could always encode a zero + length record before each record encode. Some old SSL implementations do + not handle decoding zero length records, however. + + This BEAST fix is on the client side and moves the implementation down to + the SSL library level so users do not need to manually send zero length + records. This fix uses the same IV obfuscation logic as a zero length + record by breaking up each application data record in two. Because some + implementations don't handle zero-length records, the the first record + is the first byte of the plaintext message, and the second record + contains the remainder of the message. + + This fix is based on the workaround implemented in Google Chrome: + http://src.chromium.org/viewvc/chrome?view=rev&revision=97269 + + This workaround adds approximagely 53 bytes to the encoded length of each + SSL3.0 or TLS1.0 record that is encoded, due to the additional header, + padding and MAC of the second record. + + @security This mode should always be enabled unless explicit compatibility + with old TLS 1.0 and SSL 3.0 libraries is required. +*/ +#define USE_BEAST_WORKAROUND /**< @security ON */ + +/******************************************************************************/ +/** + Enable certificate chain message "stream" parsing. This allows single + certificates to be parsed on-the-fly without having to wait for the entire + certificate chain to be recieved in the buffer. This is a memory saving + feature for the application buffer but will add a small amount of code + size for the parsing and structure overhead. + + This feature will only save memory if the CERTIFICATE message is the + only message in the record, and multiple certs are present in the chain. + + @note This features is deprecated and should be enabled only if + processing long certificate chains with very low memory. +*/ +//#define USE_CERT_CHAIN_PARSING /**< @note Setting does not affect security */ + +/******************************************************************************/ +/** + - USE_TLS versions must 'stack' for compiling purposes + - must enable TLS if enabling TLS 1.1 + - must enable TLS 1.1 if enabling TLS 1.2 + - Use the DISABLE_TLS_ defines to disallow specific protocols at runtime + that have been enabled via USE_TLS_. + - There is no DISABLE_TLS_ for the latest version of the protocol. If + you don't want to use that version disable the USE_TLS_ define instead + The USE_TLS_1_x_AND_ABOVE simplifies this configuration. + @security To enable SSL3.0, see below. +*/ +#define USE_TLS /**< DO NOT DISABLE @security NIST_MAY */ +#define USE_TLS_1_1 /**< DO NOT DISABLE @security NIST_SHALL */ +#define USE_TLS_1_2 /**< DO NOT DISABLE @security NIST_SHOULD */ +#define DISABLE_SSLV3 /**< DO NOT DISABLE, undef below if required + @security NIST_SHALL_NOT */ + + +#if defined USE_TLS_1_2_AND_ABOVE + #define DISABLE_TLS_1_1 + #define DISABLE_TLS_1_0 +#elif defined USE_TLS_1_1_AND_ABOVE + #define DISABLE_TLS_1_0 +#elif defined USE_TLS_1_0_AND_ABOVE + /** @security undef DISABLE_SSLV3 here if required */ +#else + #error Must define USE_TLS_1_x_AND_ABOVE +#endif + + +#ifdef USE_DTLS +/******************************************************************************/ + /** DTLS definitions */ + #define DTLS_COOKIE_SIZE 16 +#endif /* USE_DTLS */ + +/******************************************************************************/ +/** + Include matrixssl external crypto provider layer headers. +*/ + +#ifdef USE_ZLIB_COMPRESSION + #include "zlib.h" +#endif + + +#if defined(USE_AES_GCM) || defined(USE_AES_CCM) || defined(USE_CHACHA20_POLY1305) + #define USE_AEAD_CIPHER +#endif + +/* PKCS11 is set in crypto. Use all modes of it if enabled */ +#define USE_NATIVE_TLS_ALGS +#define USE_NATIVE_TLS_HS_HASH +#define USE_NATIVE_SYMMETRIC + +/******************************************************************************/ +/** + Do sanity checks on configuration. +*/ +#include "matrixsslCheck.h" + +/******************************************************************************/ +/* + Leave this enabled for run-time check of sslKeys_t content when a cipher + suite is matched. Disable only if you need to manage key material yourself. + Always conditional on whether certificate parsing is enabled because it + looks at members that only exist if certificates have been parsed +*/ +#ifdef USE_CERT_PARSE +#define VALIDATE_KEY_MATERIAL +#endif /* USE_CERT_PARSE */ + +/******************************************************************************/ +/** + SSL protocol and MatrixSSL defines. + @see https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml +*/ + +/* + Maximum SSL record size, per specification +*/ +#define SSL_MAX_PLAINTEXT_LEN 0x4000 /* 16KB */ +#define SSL_MAX_RECORD_LEN SSL_MAX_PLAINTEXT_LEN + 2048 +#define SSL_MAX_BUF_SIZE SSL_MAX_RECORD_LEN + 0x5 +#define SSL_MAX_DISABLED_CIPHERS 8 +/* + Maximum buffer sizes for static SSL array types +*/ +#define SSL_MAX_MAC_SIZE 48 /* SHA384 */ +#define SSL_MAX_IV_SIZE 16 +#define SSL_MAX_BLOCK_SIZE 16 +#define SSL_MAX_SYM_KEY_SIZE 32 + +/* + Negative return codes must be between -50 and -69 in the MatrixSSL module +*/ +#define SSL_FULL -50 /* must call sslRead before decoding */ +#define SSL_PARTIAL -51 /* more data reqired to parse full msg */ +#define SSL_SEND_RESPONSE -52 /* decode produced output data */ +#define SSL_PROCESS_DATA -53 /* succesfully decoded application data */ +#define SSL_ALERT -54 /* we've decoded an alert */ +#define SSL_FILE_NOT_FOUND -55 /* File not found */ +#define SSL_MEM_ERROR PS_MEM_FAIL /* Memory allocation failure */ +#ifdef USE_DTLS +#define DTLS_MUST_FRAG -60 /* Message must be fragmented */ +#define DTLS_RETRANSMIT -61 /* Received a duplicate hs msg from peer */ +#endif /* USE_DTLS */ + + +/* + Magic numbers for handshake header lengths +*/ +#define SSL2_HEADER_LEN 2 +#define SSL3_HEADER_LEN 5 +#define SSL3_HANDSHAKE_HEADER_LEN 4 +#ifdef USE_DTLS + #define DTLS_HEADER_ADD_LEN 8 +#endif + +#define TLS_CHACHA20_POLY1305_AAD_LEN 13 +#define TLS_GCM_AAD_LEN 13 +#define TLS_AEAD_SEQNB_LEN 8 + +#define TLS_GCM_TAG_LEN 16 +#define TLS_CHACHA20_POLY1305_TAG_LEN 16 +#define TLS_CCM_TAG_LEN 16 +#define TLS_CCM8_TAG_LEN 8 + +#define TLS_AEAD_NONCE_MAXLEN 12 /* Maximum length for an AEAD's nonce */ +#define TLS_EXPLICIT_NONCE_LEN 8 +#define TLS_CHACHA20_POLY1305_NONCE_LEN 0 + +#define AEAD_NONCE_LEN(SSL) ((SSL->flags & SSL_FLAGS_NONCE_W) ? TLS_EXPLICIT_NONCE_LEN : 0) +#define AEAD_TAG_LEN(SSL) ((SSL->cipher->flags & CRYPTO_FLAGS_CCM8) ? 8 : 16) + +/* + matrixSslSetSessionOption defines +*/ +#define SSL_OPTION_FULL_HANDSHAKE 1 +#ifdef USE_CLIENT_AUTH +#define SSL_OPTION_DISABLE_CLIENT_AUTH 2 +#define SSL_OPTION_ENABLE_CLIENT_AUTH 3 +#endif /* USE_CLIENT_AUTH */ +#define SSL_OPTION_DISABLE_REHANDSHAKES 4 +#define SSL_OPTION_REENABLE_REHANDSHAKES 5 + +/* + SSL Alert levels and descriptions + This implementation treats all alerts that are not related to + certificate validation as fatal +*/ +#define SSL_ALERT_LEVEL_WARNING 1 +#define SSL_ALERT_LEVEL_FATAL 2 + +#define SSL_ALERT_CLOSE_NOTIFY 0 +#define SSL_ALERT_UNEXPECTED_MESSAGE 10 +#define SSL_ALERT_BAD_RECORD_MAC 20 +#define SSL_ALERT_DECRYPTION_FAILED 21 /* Do not use, per RFC 5246 */ +#define SSL_ALERT_RECORD_OVERFLOW 22 +#define SSL_ALERT_DECOMPRESSION_FAILURE 30 +#define SSL_ALERT_HANDSHAKE_FAILURE 40 +#define SSL_ALERT_NO_CERTIFICATE 41 +#define SSL_ALERT_BAD_CERTIFICATE 42 +#define SSL_ALERT_UNSUPPORTED_CERTIFICATE 43 +#define SSL_ALERT_CERTIFICATE_REVOKED 44 +#define SSL_ALERT_CERTIFICATE_EXPIRED 45 +#define SSL_ALERT_CERTIFICATE_UNKNOWN 46 +#define SSL_ALERT_ILLEGAL_PARAMETER 47 +#define SSL_ALERT_UNKNOWN_CA 48 +#define SSL_ALERT_ACCESS_DENIED 49 +#define SSL_ALERT_DECODE_ERROR 50 +#define SSL_ALERT_DECRYPT_ERROR 51 +#define SSL_ALERT_PROTOCOL_VERSION 70 +#define SSL_ALERT_INSUFFICIENT_SECURITY 71 +#define SSL_ALERT_INTERNAL_ERROR 80 +#define SSL_ALERT_INAPPROPRIATE_FALLBACK 86 +#define SSL_ALERT_NO_RENEGOTIATION 100 +#define SSL_ALERT_UNSUPPORTED_EXTENSION 110 +#define SSL_ALERT_UNRECOGNIZED_NAME 112 +#define SSL_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE 113 +#define SSL_ALERT_UNKNOWN_PSK_IDENTITY 115 +#define SSL_ALERT_NO_APP_PROTOCOL 120 + +/* + Use as return code in user validation callback to allow + anonymous connections to proceed. + MUST NOT OVERLAP WITH ANY OF THE ALERT CODES ABOVE +*/ +#define SSL_ALLOW_ANON_CONNECTION 254 + +/* Internal values for ssl_t.flags */ +#define SSL_FLAGS_SERVER (1<< 0) +#define SSL_FLAGS_READ_SECURE (1<< 1) +#define SSL_FLAGS_WRITE_SECURE (1<< 2) +#define SSL_FLAGS_RESUMED (1<< 3) +#define SSL_FLAGS_CLOSED (1<< 4) +#define SSL_FLAGS_NEED_ENCODE (1<< 5) +#define SSL_FLAGS_ERROR (1<< 6) +#define SSL_FLAGS_CLIENT_AUTH (1<< 7) +#define SSL_FLAGS_ANON_CIPHER (1<< 8) +#define SSL_FLAGS_FALSE_START (1<< 9) +#define SSL_FLAGS_SSLV3 (1<<10) +#define SSL_FLAGS_TLS (1<<11) +#define SSL_FLAGS_TLS_1_0 SSL_FLAGS_TLS /* For naming consistency */ +#define SSL_FLAGS_TLS_1_1 (1<<12) +#define SSL_FLAGS_TLS_1_2 (1<<13) +#define SSL_FLAGS_DTLS (1<<14) +#define SSL_FLAGS_DHE_WITH_RSA (1<<15) +#define SSL_FLAGS_DHE_WITH_DSA (1<<16) +#define SSL_FLAGS_DHE_KEY_EXCH (1<<17) +#define SSL_FLAGS_PSK_CIPHER (1<<18) +#define SSL_FLAGS_ECC_CIPHER (1<<19) +#define SSL_FLAGS_AEAD_W (1<<20) +#define SSL_FLAGS_AEAD_R (1<<21) +#define SSL_FLAGS_NONCE_W (1<<22) +#define SSL_FLAGS_NONCE_R (1<<23) + +#define SSL_FLAGS_INTERCEPTOR (1<<30) +#define SSL_FLAGS_EAP_FAST (1<<31) + +/* Internal flags for ssl_t.hwflags */ +#define SSL_HWFLAGS_HW (1<<0) /* Use HW for decode/encode */ +#define SSL_HWFLAGS_HW_SW (1<<1) /* Use HW & SW in parallel (debug) */ +#define SSL_HWFLAGS_NONBLOCK (1<<2) /* Use async HW for decode/encode */ +#define SSL_HWFLAGS_PENDING_R (1<<3) /* Non-blocking app record read */ +#define SSL_HWFLAGS_PENDING_W (1<<4) /* Non-blocking app record write */ +#define SSL_HWFLAGS_PENDING_FLIGHT_W (1<<5) /* mid encryptFlight (hshake) */ +#define SSL_HWFLAGS_PENDING_PKA_R (1<<6) /* Non-blocking public key op */ +#define SSL_HWFLAGS_PENDING_PKA_W (1<<7) /* Non-blocking public key op */ +#define SSL_HWFLAGS_EAGAIN (1<<8) /* Not submitted. Skip hsHash */ +#define SSL_HWFLAGS_HW_BAD (1<<9) /* Bad hardware result,go software */ + +/* Buffer flags (ssl->bFlags) */ +#define BFLAG_CLOSE_AFTER_SENT (1<<0) +#define BFLAG_HS_COMPLETE (1<<1) +#define BFLAG_STOP_BEAST (1<<2) + +/* + Number of bytes server must send before creating a re-handshake credit +*/ +#define DEFAULT_RH_CREDITS 1 /* Allow for one rehandshake by default */ +#define BYTES_BEFORE_RH_CREDIT 20 * 1024 * 1024 + +#ifdef USE_ECC +/* EC flags for sslSessOpts_t */ +#define SSL_OPT_SECP192R1 IS_SECP192R1 +#define SSL_OPT_SECP224R1 IS_SECP224R1 +#define SSL_OPT_SECP256R1 IS_SECP256R1 +#define SSL_OPT_SECP384R1 IS_SECP384R1 +#define SSL_OPT_SECP521R1 IS_SECP521R1 +/* WARNING: Public points on Brainpool curves are not validated */ +#define SSL_OPT_BRAIN224R1 IS_BRAIN224R1 +#define SSL_OPT_BRAIN256R1 IS_BRAIN256R1 +#define SSL_OPT_BRAIN384R1 IS_BRAIN384R1 +#define SSL_OPT_BRAIN512R1 IS_BRAIN512R1 +#endif + +/* Cipher types (internal for CipherSpec_t.type) */ +enum PACKED { + CS_NULL = 0, + CS_RSA, + CS_DHE_RSA, + CS_DH_ANON, + CS_DHE_PSK, + CS_PSK, + CS_ECDHE_ECDSA, + CS_ECDHE_RSA, + CS_ECDH_ECDSA, + CS_ECDH_RSA +}; + +/* + These are defines rather than enums because we want to store them as char, + not int32 (enum size) +*/ +#define SSL_RECORD_TYPE_CHANGE_CIPHER_SPEC (uint8_t)20 +#define SSL_RECORD_TYPE_ALERT (uint8_t)21 +#define SSL_RECORD_TYPE_HANDSHAKE (uint8_t)22 +#define SSL_RECORD_TYPE_APPLICATION_DATA (uint8_t)23 +#define SSL_RECORD_TYPE_HANDSHAKE_FIRST_FRAG (uint8_t)90 /* internal */ +#define SSL_RECORD_TYPE_HANDSHAKE_FRAG (uint8_t)91 /* non-standard types */ + +#define SSL_HS_HELLO_REQUEST (uint8_t)0 +#define SSL_HS_CLIENT_HELLO (uint8_t)1 +#define SSL_HS_SERVER_HELLO (uint8_t)2 +#define SSL_HS_HELLO_VERIFY_REQUEST (uint8_t)3 +#define SSL_HS_NEW_SESSION_TICKET (uint8_t)4 +#define SSL_HS_CERTIFICATE (uint8_t)11 +#define SSL_HS_SERVER_KEY_EXCHANGE (uint8_t)12 +#define SSL_HS_CERTIFICATE_REQUEST (uint8_t)13 +#define SSL_HS_SERVER_HELLO_DONE (uint8_t)14 +#define SSL_HS_CERTIFICATE_VERIFY (uint8_t)15 +#define SSL_HS_CLIENT_KEY_EXCHANGE (uint8_t)16 +#define SSL_HS_FINISHED (uint8_t)20 +#define SSL_HS_CERTIFICATE_STATUS (uint8_t)22 +#define SSL_HS_ALERT (uint8_t)252 /* ChangeCipherSuite (internal) */ +#define SSL_HS_CCC (uint8_t)253 /* ChangeCipherSuite (internal) */ +#define SSL_HS_NONE (uint8_t)254 /* No recorded state (internal) */ +#define SSL_HS_DONE (uint8_t)255 /* Handshake complete (internal) */ + +#define INIT_ENCRYPT_CIPHER 0 +#define INIT_DECRYPT_CIPHER 1 + +#define HMAC_CREATE 1 +#define HMAC_VERIFY 2 + +#ifdef USE_TLS_1_2 +/** +enum { + none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), sha512(6), (255) +} HashAlgorithm; +enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } SigAlgorithm; +*/ +enum PACKED { + HASH_SIG_MD5 = 1, + HASH_SIG_SHA1, + HASH_SIG_SHA256 = 4, + HASH_SIG_SHA384, + HASH_SIG_SHA512 +}; + +enum PACKED { + HASH_SIG_RSA = 1, + HASH_SIG_ECDSA = 3 /* This 3 is correct for hashSigAlg */ +}; + +/* Internal flag format for algorithms */ +enum PACKED { + /* For RSA we set a bit in the low byte */ + HASH_SIG_MD5_RSA_MASK = 1 << HASH_SIG_MD5, + HASH_SIG_SHA1_RSA_MASK = 1 << HASH_SIG_SHA1, + HASH_SIG_SHA256_RSA_MASK = 1 << HASH_SIG_SHA256, + HASH_SIG_SHA384_RSA_MASK = 1 << HASH_SIG_SHA384, + HASH_SIG_SHA512_RSA_MASK = 1 << HASH_SIG_SHA512, + /* For ECDSA we set a bit in the high byte */ + HASH_SIG_SHA1_ECDSA_MASK = 0x100 << HASH_SIG_SHA1, + HASH_SIG_SHA256_ECDSA_MASK = 0x100 << HASH_SIG_SHA256, + HASH_SIG_SHA384_ECDSA_MASK = 0x100 << HASH_SIG_SHA384, + HASH_SIG_SHA512_ECDSA_MASK = 0x100 << HASH_SIG_SHA512, +}; + +/** Return a unique flag for the given HASH_SIG_ALG. */ +static __inline uint16_t HASH_SIG_MASK(uint8_t hash, uint8_t sig) +{ + //TODO - do better validation on hash and sig + hash = 1 << (hash & 0x7); + return (sig == HASH_SIG_RSA ? hash : ((uint16_t)hash << 8)); +} +#endif /* USE_TLS_1_2 */ + +/* Additional ssl alert value, indicating no error has ocurred. */ +#define SSL_ALERT_NONE 255 /* No error */ + +/* SSL/TLS protocol message sizes */ +#define SSL_HS_RANDOM_SIZE 32 +#define SSL_HS_RSA_PREMASTER_SIZE 48 +#ifdef USE_TLS +#define TLS_HS_FINISHED_SIZE 12 +#endif /* USE_TLS */ + +/* Major and minor (not minimum!) version numbers for TLS */ +#define SSL2_MAJ_VER 2 + +#define SSL3_MAJ_VER 3 +#define SSL3_MIN_VER 0 + +#define TLS_MAJ_VER SSL3_MAJ_VER +#define TLS_MIN_VER 1 +#define TLS_1_0_MIN_VER TLS_MIN_VER +#define TLS_1_1_MIN_VER 2 +#define TLS_1_2_MIN_VER 3 + +/* Based on settings, define the highest TLS version available */ +#if defined(USE_TLS_1_2) && !defined(DISABLE_TLS_1_2) + #define TLS_HIGHEST_MINOR TLS_1_2_MIN_VER +#elif defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1) + #define TLS_HIGHEST_MINOR TLS_1_1_MIN_VER +#elif defined(USE_TLS) && !defined(DISABLE_TLS_1_0) + #define TLS_HIGHEST_MINOR TLS_1_0_MIN_VER +#elif !defined(DISABLE_SSLV3) + #define TLS_HIGHEST_MINOR SSL3_MIN_VER +#else + #error Unexpected TLS Version +#endif + +/* Cipher suite specification IDs, in numerical order. */ +#define SSL_NULL_WITH_NULL_NULL 0x0000 +#define SSL_RSA_WITH_NULL_MD5 0x0001 +#define SSL_RSA_WITH_NULL_SHA 0x0002 +#define SSL_RSA_WITH_RC4_128_MD5 0x0004 +#define SSL_RSA_WITH_RC4_128_SHA 0x0005 +#define TLS_RSA_WITH_IDEA_CBC_SHA 0x0007 +#define SSL_RSA_WITH_3DES_EDE_CBC_SHA 0x000A /* 10 */ +#define SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016 /* 22 */ +#define SSL_DH_anon_WITH_RC4_128_MD5 0x0018 /* 24 */ +#define SSL_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B /* 27 */ +#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F /* 47 */ +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033 /* 51 */ +#define TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034 /* 52 */ +#define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 /* 53 */ +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 /* 57 */ +#define TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A /* 58 */ +#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C /* 60 */ +#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D /* 61 */ +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067 /* 103 */ +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B /* 107 */ +#define TLS_RSA_WITH_SEED_CBC_SHA 0x0096 /* 150 */ +#define TLS_PSK_WITH_AES_128_CBC_SHA 0x008C /* 140 */ +#define TLS_PSK_WITH_AES_128_CBC_SHA256 0x00AE /* 174 */ +#define TLS_PSK_WITH_AES_256_CBC_SHA384 0x00AF /* 175 */ +#define TLS_PSK_WITH_AES_256_CBC_SHA 0x008D /* 141 */ +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x0090 /* 144 */ +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x0091 /* 145 */ +#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C /* 156 */ +#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D /* 157 */ + +#define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00FF /**< @see RFC 5746 */ +#define TLS_FALLBACK_SCSV 0x5600 /**< @see RFC 7507 */ + +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /* 49156 */ +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /* 49157 */ +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /* 49161 */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /* 49162 */ +#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /* 49170 */ +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /* 49171 */ +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /* 49172 */ +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /* 49166 */ +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /* 49167 */ +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /* 49187 */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /* 49188 */ +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /* 49189 */ +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /* 49190 */ +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /* 49191 */ +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /* 49192 */ +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /* 49193 */ +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /* 49194 */ +#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /* 49195 */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /* 49196 */ +#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /* 49197 */ +#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /* 49198 */ +#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /* 49199 */ +#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /* 49200 */ +#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /* 49201 */ +#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /* 49202 */ +#ifdef CHACHA20POLY1305_IETF +/* Defined in https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305 */ +#define TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 /* 52392 */ +#define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /* 52393 */ +#else +/* Defined in https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305 */ +#define TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCC13 /* 52243 */ +#define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCC14 /* 52244 */ +#endif + +/* + Supported HELLO extensions + Extension status stored by bitfield in ssl_t.extFlags + @see https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml +*/ +#define EXT_SNI 0 +#define EXT_MAX_FRAGMENT_LEN 1 +#define EXT_TRUSTED_CA_KEYS 3 +#define EXT_TRUNCATED_HMAC 4 +#define EXT_STATUS_REQUEST 5 /* TODO: rm interceptor dup */ +#define EXT_ELLIPTIC_CURVE 10 /* Client-send only */ +#define EXT_ELLIPTIC_POINTS 11 +#define EXT_SIGNATURE_ALGORITHMS 13 +#define EXT_ALPN 16 +#define EXT_EXTENDED_MASTER_SECRET 23 +#define EXT_SESSION_TICKET 35 +#define EXT_RENEGOTIATION_INFO 0xFF01 + + +/* How large the ALPN extension arrary is. Number of protos client can talk */ +#define MAX_PROTO_EXT 8 + + +/* + Maximum key block size for any defined cipher + This must be validated if new ciphers are added + Value is largest total among all cipher suites for + 2*macSize + 2*keySize + 2*ivSize + Rounded up to nearest PRF block length. We aren't really + rounding, but just adding another block length for simplicity. +*/ +#ifdef USE_TLS_1_2 +#define SSL_MAX_KEY_BLOCK_SIZE ((2 * 48) + (2 * 32) + (2 * 16) + \ + SHA256_HASH_SIZE) +#else +#define SSL_MAX_KEY_BLOCK_SIZE ((2 * 48) + (2 * 32) + (2 * 16) + \ + SHA1_HASH_SIZE) +#endif + +/* + Master secret is 48 bytes, sessionId is 32 bytes max +*/ +#define SSL_HS_MASTER_SIZE 48 +#define SSL_MAX_SESSION_ID_SIZE 32 + +/* + TLS implementations supporting these ciphersuites MUST support + arbitrary PSK identities up to 128 octets in length, and arbitrary + PSKs up to 64 octets in length. Supporting longer identities and + keys is RECOMMENDED. +*/ +#define SSL_PSK_MAX_KEY_SIZE 64 /* Must be < 256 due to 'idLen' */ +#define SSL_PSK_MAX_ID_SIZE 128 /* Must be < 256 due to 'idLen' */ +#define SSL_PSK_MAX_HINT_SIZE 32 /* ServerKeyExchange hint is non-standard */ + +#ifdef USE_DTLS +#define MAX_FRAGMENTS 8 +#define PS_MIN_PMTU 256 + +typedef struct { + int32 offset; + int32 fragLen; + char *hsHeader; +} dtlsFragHdr_t; + +#ifndef USE_DTLS_DEBUG_TRACE +#define psTraceDtls(x) +#define psTraceIntDtls(x, y) +#define psTraceStrDtls(x, y) +#else +#define psTraceDtls(x) _psTrace(x) +#define psTraceIntDtls(x, y) _psTraceInt(x, y) +#define psTraceStrDtls(x, y) _psTraceStr(x, y) +#endif /* USE_DTLS_DEBUG_TRACE */ + +#endif /* USE_DTLS */ + + +#ifndef USE_SSL_HANDSHAKE_MSG_TRACE +#define psTraceHs(x) +#define psTraceStrHs(x, y) +#else +#define psTraceHs(x) _psTrace(x) +#define psTraceStrHs(x, y) _psTraceStr(x, y) +#endif /* USE_SSL_HANDSHAKE_MSG_TRACE */ + +#ifndef USE_SSL_INFORMATIONAL_TRACE +#define psTraceInfo(x) +#define psTraceStrInfo(x, y) +#define psTraceIntInfo(x, y) +#else +#define psTraceInfo(x) _psTrace(x) +#define psTraceStrInfo(x, y) _psTraceStr(x, y) +#define psTraceIntInfo(x, y) _psTraceInt(x, y) +#endif /* USE_SSL_INFORMATIONAL_TRACE */ + +/******************************************************************************/ + +struct ssl; + +typedef psBuf_t sslBuf_t; + +/******************************************************************************/ + +#ifdef USE_PSK_CIPHER_SUITE +typedef struct psPsk { + unsigned char *pskKey; + uint8_t pskLen; + unsigned char *pskId; + uint8_t pskIdLen; + struct psPsk *next; +} psPsk_t; +#endif /* USE_PSK_CIPHER_SUITE */ + +typedef int32_t (*pskCb_t)(struct ssl *ssl, + const unsigned char pskId[SSL_PSK_MAX_ID_SIZE], uint8_t pskIdLen, + unsigned char *psk[SSL_PSK_MAX_KEY_SIZE], uint8_t *pskLen); + +#if defined(USE_SERVER_SIDE_SSL) && defined(USE_STATELESS_SESSION_TICKETS) +typedef int32 (*sslSessTicketCb_t)(void *keys, unsigned char[16], short); + +typedef struct sessTicketKey { + unsigned char name[16]; + unsigned char symkey[32]; + unsigned char hashkey[32]; + short nameLen, symkeyLen, hashkeyLen, inUse; + struct sessTicketKey *next; +} psSessionTicketKeys_t; +#endif + +/******************************************************************************/ +/* + TLS authentication keys structures +*/ +#if defined(USE_ECC) || defined(REQUIRE_DH_PARAMS) +#define ECC_EPHEMERAL_CACHE_SECONDS (2 * 60 * 60) /**< Max lifetime in sec */ +#ifdef NO_ECC_EPHEMERAL_CACHE +#define ECC_EPHEMERAL_CACHE_USAGE 0 /**< Cache not used */ +#else +#define ECC_EPHEMERAL_CACHE_USAGE 1000 /**< Maximum use count of key */ +#endif +typedef struct { +#ifdef USE_MULTITHREADING + psMutex_t lock; +#endif +#ifdef USE_ECC + psEccKey_t eccPrivKey; /**< Cached ephemeral key */ + psEccKey_t eccPubKey; /**< Cached remote ephemeral pub key */ + psTime_t eccPrivKeyTime; /**< Time key was generated */ + uint16_t eccPrivKeyUse; /**< Use count */ + uint16_t eccPubKeyCurveId; /**< Curve the point is on */ + unsigned char eccPubKeyRaw[132]; /**< Max size of secp521r1 */ +#endif +#ifdef REQUIRE_DH_PARAMS +#endif +} ephemeralKeyCache_t; +#endif /* defined(USE_ECC) || defined(REQUIRE_DH_PARAMS) */ + +typedef struct { + psPool_t *pool; +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) + //TODO - verify that the public part of the privKey is equal to the pubkey + //in the cert + psPubKey_t privKey; + psX509Cert_t *cert; +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ +#if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH) + psX509Cert_t *CAcerts; +#endif /* USE_CLIENT_SIDE_SSL || USE_CLIENT_AUTH */ +#ifdef REQUIRE_DH_PARAMS + psDhParams_t dhParams; +#endif /* REQUIRE_DH_PARAMS */ +#ifdef USE_PSK_CIPHER_SUITE + psPsk_t *pskKeys; +#endif /* USE_PSK_CIPHER_SUITE */ +#if defined(USE_SERVER_SIDE_SSL) && defined(USE_STATELESS_SESSION_TICKETS) + psSessionTicketKeys_t *sessTickets; + sslSessTicketCb_t ticket_cb; +#endif +#if defined(USE_OCSP) && defined(USE_SERVER_SIDE_SSL) + unsigned char *OCSPResponseBuf; + uint16_t OCSPResponseBufLen; +#endif + void *poolUserPtr; /* Data that will be given to psOpenPool + for any operations involving these keys */ +#if defined(USE_ECC) || defined(REQUIRE_DH_PARAMS) + ephemeralKeyCache_t cache; +#endif +} sslKeys_t; + +/******************************************************************************/ +/* Type to pass optional features to NewSession calls */ +typedef struct { + short ticketResumption; /* Client: 1 to use. Server N/A */ + short maxFragLen; /* Client: 512 etc.. Server: -1 to disable */ + short truncHmac; /* Client: 1 to use. Server: -1 to disable */ + short extendedMasterSecret; /* On by default. -1 to disable */ + short trustedCAindication; /* Client: 1 to use */ + short fallbackScsv; /* Client: 1 to use */ +#ifdef USE_OCSP + short OCSPstapling; /* Client: 1 to send status_request */ +#endif +#ifdef USE_ECC + int32 ecFlags; /* Elliptic curve set (SSL_OPT_SECP192R1 etc.) */ +#endif + int32 versionFlag; /* The SSL_FLAGS_TLS_ version (+ DTLS flag here) */ + void *userPtr; /* Initial value of ssl->userPtr during NewSession */ + void *memAllocPtr; /* Will be passed to psOpenPool for each call + related to this session */ + psPool_t *bufferPool; /* Optional mem pool for inbuf and outbuf */ +} sslSessOpts_t; + +typedef struct { + unsigned short keyType; + unsigned short hashAlg; + unsigned short curveFlags; + unsigned short dhParamsRequired; + char *serverName; +} sslPubkeyId_t; + +typedef sslKeys_t *(*pubkeyCb_t)(struct ssl *ssl, const sslPubkeyId_t *keyId); +typedef int32_t (*sslExtCb_t)(struct ssl *ssl, uint16_t extType, uint8_t extLen, + void *e); +typedef int32_t (*sslCertCb_t)(struct ssl *ssl, psX509Cert_t *cert, int32_t alert); + +#ifdef USE_OCSP +typedef int32_t (*ocspCb_t)(struct ssl *ssl, mOCSPResponse_t *response, + psX509Cert_t *cert, int32_t status); +#endif + +/******************************************************************************/ +/* + SSL record and session structures +*/ +typedef struct { + unsigned short len; + unsigned char majVer; + unsigned char minVer; +#ifdef USE_DTLS + unsigned char epoch[2]; /* incoming epoch number */ + unsigned char rsn[6]; /* incoming record sequence number */ +#endif /* USE_DTLS */ +#ifdef USE_CERT_CHAIN_PARSING + unsigned short hsBytesHashed; + unsigned short hsBytesParsed; + unsigned short trueLen; + unsigned char partial; + unsigned char certPad; +#endif + unsigned char type; + unsigned char pad[3]; /* Padding for 64 bit compat */ +} sslRec_t; + +typedef struct { + unsigned char clientRandom[SSL_HS_RANDOM_SIZE]; /* From ClientHello */ + unsigned char serverRandom[SSL_HS_RANDOM_SIZE]; /* From ServerHello */ + unsigned char masterSecret[SSL_HS_MASTER_SIZE]; + unsigned char *premaster; /* variable size */ + uint16_t premasterSize; + + unsigned char keyBlock[SSL_MAX_KEY_BLOCK_SIZE]; /* Storage for 'ptr' */ + unsigned char *wMACptr; + unsigned char *rMACptr; + unsigned char *wKeyptr; + unsigned char *rKeyptr; + + /* All maximum sizes for current cipher suites */ + unsigned char writeMAC[SSL_MAX_MAC_SIZE]; + unsigned char readMAC[SSL_MAX_MAC_SIZE]; + unsigned char writeKey[SSL_MAX_SYM_KEY_SIZE]; + unsigned char readKey[SSL_MAX_SYM_KEY_SIZE]; + unsigned char *wIVptr; + unsigned char *rIVptr; + unsigned char writeIV[SSL_MAX_IV_SIZE]; + unsigned char readIV[SSL_MAX_IV_SIZE]; + + unsigned char seq[8]; + unsigned char remSeq[8]; + + pskCb_t pskCb; + +#ifndef USE_ONLY_PSK_CIPHER_SUITE + pubkeyCb_t pubkeyCb; +#if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH) + psX509Cert_t *cert; + sslCertCb_t validateCert; +#endif /* USE_CLIENT_SIDE_SSL || USE_CLIENT_AUTH */ +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ + +#ifdef USE_CLIENT_SIDE_SSL + int32 certMatch; +#endif /* USE_CLIENT_SIDE_SSL */ + + psCipherContext_t encryptCtx; + psCipherContext_t decryptCtx; + + +#ifndef USE_ONLY_TLS_1_2 + psMd5Sha1_t msgHashMd5Sha1; +#endif + +#ifdef USE_TLS_1_2 + psSha256_t msgHashSha256; + +#ifdef USE_SHA1 + psSha1_t msgHashSha1; +#endif +#ifdef USE_SHA384 + psSha384_t msgHashSha384; +#endif +#ifdef USE_SHA512 + psSha512_t msgHashSha512; +#endif +#endif /* USE_TLS_1_2 */ + + + +#if defined(USE_SERVER_SIDE_SSL) && defined(USE_CLIENT_AUTH) + unsigned char sha1Snapshot[SHA1_HASH_SIZE]; + unsigned char sha384Snapshot[SHA384_HASH_SIZE]; /* HW crypto uses + outside TLS 1.2 */ + unsigned char sha512Snapshot[SHA512_HASH_SIZE]; +#endif + +#if defined(USE_PSK_CIPHER_SUITE) && defined(USE_CLIENT_SIDE_SSL) + unsigned char *hint; + uint8_t hintLen; +#endif /* USE_PSK_CIPHER_SUITE && USE_CLIENT_SIDE_SSL */ + +#ifdef REQUIRE_DH_PARAMS + unsigned char *dhP; /* prime/modulus */ + unsigned char *dhG; /* base/generator */ + uint16_t dhPLen; + uint16_t dhGLen; + psDhKey_t *dhKeyPub; /* remote key */ + psDhKey_t *dhKeyPriv; /* local key */ + psPool_t *dhKeyPool; /* handshake-scope pool for clients */ +#endif + +#ifdef USE_ECC_CIPHER_SUITE + psEccKey_t *eccKeyPriv; /* local key */ + psEccKey_t *eccKeyPub; /* remote key */ + psPool_t *eccDhKeyPool; /* handshake-scope pool for clients */ +#endif + + int32 anon; +} sslSec_t; + +typedef struct { + uint16_t ident; /* Official cipher ID */ + uint16_t type; /* Key exchange method */ + uint32_t flags; /* from CRYPTO_FLAGS_* */ + uint8_t macSize; + uint8_t keySize; + uint8_t ivSize; + uint8_t blockSize; + /* Init function */ + int32 (*init)(sslSec_t *sec, int32 type, uint32 keysize); + /* Cipher functions */ + int32 (*encrypt)(void *ssl, unsigned char *in, + unsigned char *out, uint32 len); + int32 (*decrypt)(void *ssl, unsigned char *in, + unsigned char *out, uint32 len); + int32 (*generateMac)(void *ssl, unsigned char type, unsigned char *data, + uint32 len, unsigned char *mac); + int32 (*verifyMac)(void *ssl, unsigned char type, unsigned char *data, + uint32 len, unsigned char *mac); +} sslCipherSpec_t; + + +#ifdef USE_STATELESS_SESSION_TICKETS +enum sessionTicketState_e { + SESS_TICKET_STATE_INIT = 0, + SESS_TICKET_STATE_SENT_EMPTY, + SESS_TICKET_STATE_SENT_TICKET, + SESS_TICKET_STATE_RECVD_EXT, + SESS_TICKET_STATE_IN_LIMBO, + SESS_TICKET_STATE_USING_TICKET +}; +#endif + +/* Used by user code to store cached session info after the ssl_t is closed */ +typedef struct { + psPool_t *pool; + unsigned char id[SSL_MAX_SESSION_ID_SIZE]; + unsigned char masterSecret[SSL_HS_MASTER_SIZE]; + uint32 cipherId; +#ifdef USE_STATELESS_SESSION_TICKETS + unsigned char *sessionTicket; /* Duplicated into 'pool' */ + uint16 sessionTicketState; /* Not an enum to ensure 2 bytes */ + uint16 sessionTicketLen; /* Max 32767 */ + uint32 sessionTicketLifetimeHint; +#endif +} sslSessionId_t; + +/* Used internally by the session cache table to store session parameters */ +typedef struct { + unsigned char id[SSL_MAX_SESSION_ID_SIZE]; + unsigned char masterSecret[SSL_HS_MASTER_SIZE]; + const sslCipherSpec_t *cipher; + unsigned char majVer; + unsigned char minVer; + short extendedMasterSecret; /* was the extension used? */ + psTime_t startTime; + int32 inUse; + DLListEntry chronList; +} sslSessionEntry_t; + +/* Used by user code to define custom hello extensions */ +typedef struct tlsHelloExt { + psPool_t *pool; + int32 extType; + uint32 extLen; + unsigned char *extData; + struct tlsHelloExt *next; +} tlsExtension_t; + + +/* Hold the info needed to perform a public key operation for flight writes + until the very end. This is an architectural change that was added to aid + the integration of non-blocking hardware acceleration */ +enum { + PKA_AFTER_RSA_SIG_GEN_ELEMENT = 1, + PKA_AFTER_RSA_SIG_GEN, + PKA_AFTER_ECDSA_SIG_GEN, + PKA_AFTER_RSA_ENCRYPT, /* standard RSA CKE operation */ + PKA_AFTER_ECDH_KEY_GEN, /* ECDH CKE operation. makeKey */ + PKA_AFTER_ECDH_SECRET_GEN, /* GenSecret */ + PKA_AFTER_ECDH_SECRET_GEN_DONE, /* Control for single-pass op */ + PKA_AFTER_DH_KEY_GEN /* DH CKE operation */ +}; + +typedef struct { + unsigned char *inbuf; /* allocated to handshake pool */ + unsigned char *outbuf; + void *data; /* hw pkiData */ + uint16_t inlen; + uint16_t type; /* one of PKA_AFTER_* */ + uint16_t user; /* user size */ + psPool_t *pool; +} pkaAfter_t; + +typedef struct nextMsgInFlight { + unsigned char *start; + unsigned char *seqDelay; + int32 len; + int32 type; + int32 messageSize; + int32 padLen; + int32 hsMsg; +#ifdef USE_DTLS + int32 fragCount; +#endif + struct nextMsgInFlight *next; +} flightEncode_t; + +struct ssl { + sslRec_t rec; /* Current SSL record information*/ + + sslSec_t sec; /* Security structure */ + +//TODO +// tlsSessionKeys_t skeys; + + sslKeys_t *keys; /* SSL public and private keys */ + + pkaAfter_t pkaAfter[2]; /* Cli-side cli-auth = two PKA in flight */ + flightEncode_t *flightEncode; + unsigned char *delayHsHash; + unsigned char *seqDelay; /* tmp until flightEncode_t is built */ + + psPool_t *bufferPool; /* If user passed options.bufferPool to + NewSession, this is inbuf and outbuf pool */ + psPool_t *sPool; /* SSL session pool */ + psPool_t *hsPool; /* Full session handshake pool */ + psPool_t *flightPool; /* Small but handy */ + + unsigned char sessionIdLen; + unsigned char sessionId[SSL_MAX_SESSION_ID_SIZE]; + sslSessionId_t *sid; + char *expectedName; /* Clients: The expected cert subject name + passed to NewClient Session + Servers: Holds SNI value */ +#ifdef USE_SERVER_SIDE_SSL + uint16 disabledCiphers[SSL_MAX_DISABLED_CIPHERS]; + void (*sni_cb)(void *ssl, char *hostname, int32 hostnameLen, + sslKeys_t **newKeys); +#ifdef USE_ALPN + void (*srv_alpn_cb)(void *ssl, short protoCount, + char *proto[MAX_PROTO_EXT], + int32 protoLen[MAX_PROTO_EXT], int32 *index); + char *alpn; /* proto user has agreed to use */ + int32 alpnLen; +#endif /* USE_ALPN */ +#endif /* USE_SERVER_SIDE_SSL */ +#ifdef USE_CLIENT_SIDE_SSL + /* Just to handle corner case of app data tacked on HELLO_REQUEST */ + int32 anonBk; + int32 flagsBk; + uint32 bFlagsBk; +#endif /* USE_CLIENT_SIDE_SSL */ + + + unsigned char *inbuf; + unsigned char *outbuf; + int32 inlen; /* Bytes unprocessed in inbuf */ + int32 outlen; /* Bytes unsent in outbuf */ + int32 insize; /* Total allocated size of inbuf */ + int32 outsize; /* Total allocated size of outbuf */ + uint32 bFlags; /* Buffer related flags */ + + int32 maxPtFrag; /* 16K by default - SSL_MAX_PLAINTEXT_LEN */ + unsigned char *fragMessage; /* holds the constructed fragmented message */ + uint32 fragIndex; /* How much data has been written to msg */ + uint32 fragTotal; /* Total length of fragmented message */ + + /* Pointer to the negotiated cipher information */ + const sslCipherSpec_t *cipher; + + /* Symmetric cipher callbacks + + We duplicate these here from 'cipher' because we need to set the + various callbacks at different times in the handshake protocol + Also, there are 64 bit alignment issues in using the function pointers + within 'cipher' directly + */ + int32 (*encrypt)(void *ctx, unsigned char *in, + unsigned char *out, uint32 len); + int32 (*decrypt)(void *ctx, unsigned char *in, + unsigned char *out, uint32 len); + /* Message Authentication Codes */ + int32 (*generateMac)(void *ssl, unsigned char type, unsigned char *data, + uint32 len, unsigned char *mac); + int32 (*verifyMac)(void *ssl, unsigned char type, unsigned char *data, + uint32 len, unsigned char *mac); + + /* Current encryption/decryption parameters */ + unsigned char enMacSize; + unsigned char nativeEnMacSize; /* truncated hmac support */ + unsigned char enIvSize; + unsigned char enBlockSize; + unsigned char deMacSize; + unsigned char nativeDeMacSize; /* truncated hmac support */ + unsigned char deIvSize; + unsigned char deBlockSize; + + uint32_t flags; /* SSL_FLAGS_ */ + int32_t err; /* SSL errno of last api call */ + int32_t ignoredMessageCount; + + uint8_t hsState; /* Next expected SSL_HS_ message type */ + uint8_t decState; /* Most recent encoded SSL_HS_ message */ + uint8_t encState; /* Most recent decoded SSL_HS_ message */ + uint8_t reqMajVer; + uint8_t reqMinVer; + uint8_t majVer; + uint8_t minVer; + uint8_t outRecType; + +#ifdef ENABLE_SECURE_REHANDSHAKES + unsigned char myVerifyData[SHA384_HASH_SIZE]; /*SSLv3 max*/ + unsigned char peerVerifyData[SHA384_HASH_SIZE]; + uint32 myVerifyDataLen; + uint32 peerVerifyDataLen; + int32 secureRenegotiationFlag; +#endif /* ENABLE_SECURE_REHANDSHAKES */ +#ifdef SSL_REHANDSHAKES_ENABLED + int32 rehandshakeCount; /* Make this an internal define of 1 */ + int32 rehandshakeBytes; /* Make this an internal define of 10MB */ +#endif /* SSL_REHANDSHAKES_ENABLED */ + + sslExtCb_t extCb; +#ifdef USE_ECC + struct { + uint32 ecFlags:24; + uint32 ecCurveId:8; + } ecInfo; +#endif +#ifdef USE_TLS_1_2 + uint16_t hashSigAlg; +#endif + +#ifdef USE_DTLS +#ifdef USE_SERVER_SIDE_SSL + unsigned char srvCookie[DTLS_COOKIE_SIZE]; /* server can avoid allocs */ +#endif +#ifdef USE_CLIENT_SIDE_SSL + unsigned char *cookie; /* hello_verify_request cookie */ + int32 cookieLen; /* cookie length */ + int32 haveCookie; /* boolean for cookie existence */ +#endif + unsigned char *helloExt; /* need to save the original client hello ext */ + int32 helloExtLen; + unsigned char hsSnapshot[SHA512_HASH_SIZE]; /*SSLv3 max*/ + int32 hsSnapshotLen; + uint16_t cipherSpec[8]; /* also needed for the cookie client hello */ + uint8_t cipherSpecLen; + unsigned char epoch[2]; /* Current epoch number to send with msg */ + unsigned char resendEpoch[2]; /* Starting epoch to use for resends */ + unsigned char expectedEpoch[2]; /* Expected incoming epoch */ + unsigned char largestEpoch[2]; /* FINISH resends need to incr epoch */ + unsigned char rsn[6]; /* Last Record Sequence Number sent */ + unsigned char largestRsn[6]; /* Needed for resends of CCS flight */ + unsigned char lastRsn[6]; /* Last RSN received (for replay detection) */ + unsigned long dtlsBitmap; /* Record replay helper */ + int32 parsedCCS; /* Set between CCS parse and FINISHED parse */ + int32 msn; /* Current Message Sequence Number to send */ + int32 resendMsn; /* Starting MSN to use for resends */ + int32 lastMsn; /* Last MSN successfully parsed from peer */ + int32 pmtu; /* path maximum trasmission unit */ + int32 retransmit; /* Flag to know not to update handshake hash */ + uint16 flightDone; /* BOOL to flag when entire hs flight sent */ + uint16 appDataExch; /* BOOL to flag if in application data mode */ + int32 fragMsn; /* fragment MSN */ + dtlsFragHdr_t fragHeaders[MAX_FRAGMENTS]; /* header storage for hash */ + int32 (*oencrypt)(void *ctx, unsigned char *in, + unsigned char *out, uint32 len); + int32 (*ogenerateMac)(void *ssl, unsigned char type, unsigned char *data, + uint32 len, unsigned char *mac); + unsigned char oenMacSize; + unsigned char oenNativeHmacSize; + unsigned char oenIvSize; + unsigned char oenBlockSize; + unsigned char owriteIV[16]; /* GCM uses this in the nonce */ + unsigned char owriteMAC[SSL_MAX_MAC_SIZE]; + psCipherContext_t oencryptCtx; +#ifdef ENABLE_SECURE_REHANDSHAKES + unsigned char omyVerifyData[SHA384_HASH_SIZE]; + uint32 omyVerifyDataLen; +#endif /* ENABLE_SECURE_REHANDSHAKES */ + uint32 ckeSize; + unsigned char *ckeMsg; + unsigned char *certVerifyMsg; + int32 certVerifyMsgLen; + int ecdsaSizeChange; /* retransmits for ECDSA sig */ +#endif /* USE_DTLS */ + +#ifdef USE_ZLIB_COMPRESSION + int32 compression; + z_stream inflate; + z_stream deflate; + unsigned char *zlibBuffer; /* scratch pad for inflate/deflate data */ +#endif + + struct { +#ifdef USE_CLIENT_SIDE_SSL + /* Did the client request the extension? */ + uint32 req_sni: 1; + uint32 req_max_fragment_len: 1; + uint32 req_truncated_hmac: 1; + uint32 req_extended_master_secret: 1; + uint32 req_elliptic_curve: 1; + uint32 req_elliptic_points: 1; + uint32 req_signature_algorithms: 1; + uint32 req_alpn: 1; + uint32 req_session_ticket: 1; + uint32 req_renegotiation_info: 1; + uint32 req_fallback_scsv: 1; + uint32 req_status_request: 1; +#endif +#ifdef USE_SERVER_SIDE_SSL + /* Whether the server will deny the extension */ + uint32 deny_truncated_hmac: 1; + uint32 deny_max_fragment_len: 1; + uint32 deny_session_ticket: 1; +#endif + /* Set if the extension was negotiated successfully */ + uint32 sni: 1; + uint32 truncated_hmac: 1; + uint32 extended_master_secret: 1; + uint32 session_id: 1; + uint32 session_ticket: 1; + uint32 status_request: 1; /* received EXT_STATUS_REQUEST */ + uint32 status_request_v2: 1; /* received EXT_STATUS_REQUEST_V2 */ + uint32 require_extended_master_secret: 1; /* peer may require */ + } extFlags; /**< Extension flags */ + +#ifdef USE_MATRIX_OPENSSL_LAYER + int (*verify_callback)(int alert, psX509Cert_t *data); +#endif + int32 recordHeadLen; + int32 hshakeHeadLen; +#ifdef USE_MATRIXSSL_STATS + void (*statCb)(void *ssl, void *stats_ptr, int32 type, int32 value); + void *statsPtr; +#endif + void *memAllocPtr; /* Will be passed to psOpenPool for each call + related to this session */ + void *userPtr; +}; + +typedef struct ssl ssl_t; + +/******************************************************************************/ +/* + Former public APIS in 1.x and 2.x. Now deprecated in 3.x + These functions are still heavily used internally, just no longer publically + supported. + */ +extern int32 matrixSslDecode(ssl_t *ssl, unsigned char **buf, uint32 *len, + uint32 size, uint32 *remaining, uint32 *requiredLen, + int32 *error, unsigned char *alertLevel, + unsigned char *alertDescription); +extern int32 matrixSslEncode(ssl_t *ssl, unsigned char *buf, uint32 size, + unsigned char *ptBuf, uint32 *len); +extern int32 matrixSslGetEncodedSize(ssl_t *ssl, uint32 len); +extern void matrixSslSetCertValidator(ssl_t *ssl, sslCertCb_t certValidator); +extern int32 matrixSslNewSession(ssl_t **ssl, const sslKeys_t *keys, + sslSessionId_t *session, sslSessOpts_t *options); +extern void matrixSslSetSessionOption(ssl_t *ssl, int32 option, void *arg); +extern int32_t matrixSslHandshakeIsComplete(const ssl_t *ssl); + +/* This used to be prefixed with 'matrix' */ +extern int32 sslEncodeClosureAlert(ssl_t *ssl, sslBuf_t *out, + uint32 *reqLen); + +extern int32 matrixSslEncodeHelloRequest(ssl_t *ssl, sslBuf_t *out, + uint32 *reqLen); +extern int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out, + const uint16_t cipherSpec[], uint8_t cipherSpecLen, + uint32 *requiredLen, tlsExtension_t *userExt, + sslSessOpts_t *options); + +#ifdef USE_CLIENT_SIDE_SSL +extern int32 matrixSslGetSessionId(ssl_t *ssl, sslSessionId_t *sessionId); +#endif /* USE_CLIENT_SIDE_SSL */ + +#ifdef USE_SSL_INFORMATIONAL_TRACE +extern void matrixSslPrintHSDetails(ssl_t *ssl); +#endif /* USE_SSL_INFORMATIONAL_TRACE */ + +#ifdef SSL_REHANDSHAKES_ENABLED +PSPUBLIC int32 matrixSslGetRehandshakeCredits(ssl_t *ssl); +PSPUBLIC void matrixSslAddRehandshakeCredits(ssl_t *ssl, int32 credits); +#endif + +#ifdef USE_ZLIB_COMPRESSION +PSPUBLIC int32 matrixSslIsSessionCompressionOn(ssl_t *ssl); +#endif + +/******************************************************************************/ +/* + MatrixSSL internal cert functions +*/ + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +extern int32 matrixValidateCerts(psPool_t *pool, psX509Cert_t *subjectCerts, + psX509Cert_t *issuerCerts, char *expectedName, + psX509Cert_t **foundIssuer, void *pkiData, void *userPoolPtr); +extern int32 matrixUserCertValidator(ssl_t *ssl, int32 alert, + psX509Cert_t *subjectCert, sslCertCb_t certCb); +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ + + +/******************************************************************************/ +/* + handshakeDecode.c and extensionDecode.c +*/ +#ifdef USE_SERVER_SIDE_SSL +extern int32 parseClientHello(ssl_t *ssl, unsigned char **cp, + unsigned char *end); +extern int32 parseClientHelloExtensions(ssl_t *ssl, unsigned char **cp, + unsigned short len); +extern int32 parseClientKeyExchange(ssl_t *ssl, int32 hsLen, unsigned char **cp, + unsigned char *end); +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#ifdef USE_CLIENT_AUTH +extern int32 parseCertificateVerify(ssl_t *ssl, + unsigned char hsMsgHash[SHA512_HASH_SIZE], unsigned char **cp, + unsigned char *end); +#endif /* USE_CLIENT_AUTH */ +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ +#endif /* USE_SERVER_SIDE_SSL */ + +#ifdef USE_CLIENT_SIDE_SSL +extern int32 parseServerHello(ssl_t *ssl, int32 hsLen, unsigned char **cp, + unsigned char *end); +extern int32 parseServerHelloExtensions(ssl_t *ssl, int32 hsLen, + unsigned char *extData, unsigned char **cp, + unsigned short len); +extern int32 parseServerHelloDone(ssl_t *ssl, int32 hsLen, unsigned char **cp, + unsigned char *end); +extern int32 parseServerKeyExchange(ssl_t *ssl, + unsigned char hsMsgHash[SHA384_HASH_SIZE], + unsigned char **cp, unsigned char *end); +#ifdef USE_OCSP +extern int32 parseCertificateStatus(ssl_t *ssl, int32 hsLen, unsigned char **cp, + unsigned char *end); +#endif +#ifndef USE_ONLY_PSK_CIPHER_SUITE +extern int32 parseCertificateRequest(ssl_t *ssl, int32 hsLen, + unsigned char **cp, unsigned char *end); +#endif +#endif /* USE_CLIENT_SIDE_SSL */ + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH) +extern int32 parseCertificate(ssl_t *ssl, unsigned char **cp, + unsigned char *end); +#endif +#endif + +extern int32 parseFinished(ssl_t *ssl, int32 hsLen, + unsigned char hsMsgHash[SHA384_HASH_SIZE], unsigned char **cp, + unsigned char *end); + +/******************************************************************************/ +/* + sslEncode.c and sslDecode.c +*/ +extern int32 psWriteRecordInfo(ssl_t *ssl, unsigned char type, int32 len, + unsigned char *c, int32 hsType); +extern int32 psWriteHandshakeHeader(ssl_t *ssl, unsigned char type, int32 len, + int32 seq, int32 fragOffset, int32 fragLen, + unsigned char *c); +extern int32 sslEncodeResponse(ssl_t *ssl, psBuf_t *out, uint32 *requiredLen); +extern int32 sslActivateReadCipher(ssl_t *ssl); +extern int32 sslActivateWriteCipher(ssl_t *ssl); +extern int32_t sslUpdateHSHash(ssl_t *ssl, const unsigned char *in, uint16_t len); +extern int32 sslInitHSHash(ssl_t *ssl); +extern int32 sslSnapshotHSHash(ssl_t *ssl, unsigned char *out, int32 senderFlag); +extern int32 sslWritePad(unsigned char *p, unsigned char padLen); +extern int32 sslCreateKeys(ssl_t *ssl); +extern void sslResetContext(ssl_t *ssl); +extern void clearPkaAfter(ssl_t *ssl); +extern pkaAfter_t *getPkaAfter(ssl_t *ssl); +extern void freePkaAfter(ssl_t *ssl); +extern void clearFlightList(ssl_t *ssl); + +#ifdef USE_SERVER_SIDE_SSL +extern int32 matrixRegisterSession(ssl_t *ssl); +extern int32 matrixResumeSession(ssl_t *ssl); +extern int32 matrixClearSession(ssl_t *ssl, int32 remove); +extern int32 matrixUpdateSession(ssl_t *ssl); +extern int32 matrixServerSetKeysSNI(ssl_t *ssl, char *host, int32 hostLen); + +#ifdef USE_STATELESS_SESSION_TICKETS +extern int32 matrixSessionTicketLen(void); +extern int32 matrixCreateSessionTicket(ssl_t *ssl, unsigned char *out, + int32 *outLen); +extern int32 matrixUnlockSessionTicket(ssl_t *ssl, unsigned char *in, + int32 inLen); +extern int32 matrixSessionTicketLen(void); +#endif +#endif /* USE_SERVER_SIDE_SSL */ + +#ifdef USE_DTLS +extern int32 dtlsChkReplayWindow(ssl_t *ssl, unsigned char *seq64); +extern int32 dtlsWriteCertificate(ssl_t *ssl, int32 certLen, + int32 lsize, unsigned char *c); +extern int32 dtlsWriteCertificateRequest(psPool_t *pool, ssl_t *ssl, int32 certLen, + int32 certCount, int32 sigHashLen, unsigned char *c); +extern int32 dtlsComputeCookie(ssl_t *ssl, unsigned char *helloBytes, + int32 helloLen); +extern void dtlsInitFrag(ssl_t *ssl); +extern int32 dtlsSeenFrag(ssl_t *ssl, int32 fragOffset, int32 *hdrIndex); +extern int32 dtlsHsHashFragMsg(ssl_t *ssl); +extern int32 dtlsCompareEpoch(unsigned char *incoming, unsigned char *expected); +extern void incrTwoByte(ssl_t *ssl, unsigned char *c, int sending); +extern void zeroTwoByte(unsigned char *c); +extern void dtlsIncrRsn(ssl_t *ssl); +extern void zeroSixByte(unsigned char *c); +extern int32 dtlsGenCookieSecret(void); +extern int32 dtlsEncryptFragRecord(ssl_t *ssl, flightEncode_t *msg, + sslBuf_t *out, unsigned char **c); +#endif /* USE_DTLS */ + + +/* + cipherSuite.c +*/ +extern int32 chooseCipherSuite(ssl_t *ssl, unsigned char *listStart, + int32 listLen); +extern const sslCipherSpec_t *sslGetDefinedCipherSpec(uint16_t id); +extern const sslCipherSpec_t *sslGetCipherSpec(const ssl_t *ssl, uint16_t id); +extern int32_t sslGetCipherSpecListLen(const ssl_t *ssl); +extern int32_t sslGetCipherSpecList(ssl_t *ssl, unsigned char *c, int32 len, + int32 addScsv); +extern int32_t haveKeyMaterial(const ssl_t *ssl, int32 cipherType, short reallyTest); +#ifdef USE_CLIENT_SIDE_SSL +int32 csCheckCertAgainstCipherSuite(int32 sigAlg, int32 cipherType); +#endif +extern void matrixSslSetKexFlags(ssl_t *ssl); + +#ifndef DISABLE_SSLV3 +/******************************************************************************/ +/* + sslv3.c +*/ +extern int32_t sslGenerateFinishedHash(psMd5Sha1_t *md, + const unsigned char *masterSecret, + unsigned char *out, int32 senderFlag); + +extern int32_t sslDeriveKeys(ssl_t *ssl); + +#ifdef USE_SHA_MAC +extern int32 ssl3HMACSha1(unsigned char *key, unsigned char *seq, + unsigned char type, unsigned char *data, uint32 len, + unsigned char *mac); +#endif /* USE_SHA_MAC */ + +#ifdef USE_MD5_MAC +extern int32 ssl3HMACMd5(unsigned char *key, unsigned char *seq, + unsigned char type, unsigned char *data, uint32 len, + unsigned char *mac); +#endif /* USE_MD5_MAC */ +#endif /* DISABLE_SSLV3 */ + +#ifdef USE_TLS +/******************************************************************************/ +/* + tls.c +*/ +extern int32 tlsDeriveKeys(ssl_t *ssl); +extern int32 tlsExtendedDeriveKeys(ssl_t *ssl); +extern int32 tlsHMACSha1(ssl_t *ssl, int32 mode, unsigned char type, + unsigned char *data, uint32 len, unsigned char *mac); + +extern int32 tlsHMACMd5(ssl_t *ssl, int32 mode, unsigned char type, + unsigned char *data, uint32 len, unsigned char *mac); +#ifdef USE_SHA256 +extern int32 tlsHMACSha2(ssl_t *ssl, int32 mode, unsigned char type, + unsigned char *data, uint32 len, unsigned char *mac, + int32 hashSize); +#endif + +/******************************************************************************/ + +#ifdef USE_TLS_1_2 +#if defined(USE_SERVER_SIDE_SSL) && defined(USE_CLIENT_AUTH) +extern int32 sslSha1RetrieveHSHash(ssl_t *ssl, unsigned char *out); +#ifdef USE_SHA384 +extern int32 sslSha384RetrieveHSHash(ssl_t *ssl, unsigned char *out); +#endif +#ifdef USE_SHA512 +extern int32 sslSha512RetrieveHSHash(ssl_t *ssl, unsigned char *out); +#endif +#endif +#ifdef USE_CLIENT_SIDE_SSL +extern void sslSha1SnapshotHSHash(ssl_t *ssl, unsigned char *out); +#ifdef USE_SHA384 +extern void sslSha384SnapshotHSHash(ssl_t *ssl, unsigned char *out); +#endif +#ifdef USE_SHA512 +extern void sslSha512SnapshotHSHash(ssl_t *ssl, unsigned char *out); +#endif +#endif +#endif /* USE_TLS_1_2 */ + +extern int32_t extMasterSecretSnapshotHSHash(ssl_t *ssl, unsigned char *out, + uint32 *outLen); + + +/******************************************************************************/ +/* + prf.c +*/ +extern int32_t prf(const unsigned char *sec, uint16_t secLen, + const unsigned char *seed, uint16_t seedLen, + unsigned char *out, uint16_t outLen); +#ifdef USE_TLS_1_2 +extern int32_t prf2(const unsigned char *sec, uint16_t secLen, + const unsigned char *seed, uint16_t seedLen, + unsigned char *out, uint16_t outLen, uint32_t flags); +#endif /* USE_TLS_1_2 */ +#endif /* USE_TLS */ + +#ifdef USE_AES_CIPHER_SUITE +extern int32 csAesInit(sslSec_t *sec, int32 type, uint32 keysize); +extern int32 csAesEncrypt(void *ssl, unsigned char *pt, + unsigned char *ct, uint32 len); +extern int32 csAesDecrypt(void *ssl, unsigned char *ct, + unsigned char *pt, uint32 len); +#ifdef USE_AES_GCM +extern int32 csAesGcmInit(sslSec_t *sec, int32 type, uint32 keysize); +extern int32 csAesGcmEncrypt(void *ssl, unsigned char *pt, + unsigned char *ct, uint32 len); +extern int32 csAesGcmDecrypt(void *ssl, unsigned char *ct, + unsigned char *pt, uint32 len); +#endif +#endif /* USE_AES_CIPHER_SUITE */ +#ifdef USE_3DES_CIPHER_SUITE +extern int32 csDes3Encrypt(void *ssl, unsigned char *pt, + unsigned char *ct, uint32 len); +extern int32 csDes3Decrypt(void *ssl, unsigned char *ct, + unsigned char *pt, uint32 len); +#endif /* USE_3DES_CIPHER_SUITE */ +#ifdef USE_ARC4_CIPHER_SUITE +extern int32 csArc4Encrypt(void *ssl, unsigned char *pt,unsigned char *ct, + uint32 len); +extern int32 csArc4Decrypt(void *ssl, unsigned char *pt,unsigned char *ct, + uint32 len); +#endif /* USE_ARC4_CIPHER_SUITE */ +#ifdef USE_SEED_CIPHER_SUITE +extern int32 csSeedEncrypt(void *ssl, unsigned char *pt, + unsigned char *ct, uint32 len); +extern int32 csSeedDecrypt(void *ssl, unsigned char *ct, + unsigned char *pt, uint32 len); +#endif /* USE_SEED_CIPHER_SUITE */ + +#ifdef USE_IDEA_CIPHER_SUITE +extern int32 csIdeaInit(sslSec_t *sec, int32 type, uint32 keysize); +extern int32 csIdeaEncrypt(void *ssl, unsigned char *pt, + unsigned char *ct, uint32 len); +extern int32 csIdeaDecrypt(void *ssl, unsigned char *ct, + unsigned char *pt, uint32 len); +#endif /* USE_IDEA_CIPHER_SUITE */ + +#ifdef USE_PSK_CIPHER_SUITE + +extern int32_t matrixSslPskGetKey(ssl_t *ssl, + const unsigned char id[SSL_PSK_MAX_ID_SIZE], uint8_t idLen, + unsigned char *key[SSL_PSK_MAX_KEY_SIZE], uint8_t *keyLen); +extern int32_t matrixSslPskGetKeyId(ssl_t *ssl, + unsigned char *id[SSL_PSK_MAX_ID_SIZE], uint8_t *idLen, + const unsigned char hint[SSL_PSK_MAX_HINT_SIZE], uint8_t hintLen); +extern int32_t matrixPskGetHint(ssl_t *ssl, + unsigned char *hint[SSL_PSK_MAX_HINT_SIZE], uint8_t *hintLen); +#endif /* USE_PSK_CIPHER_SUITE */ + +#ifdef USE_ECC +extern int32 psTestUserEcID(int32 id, int32 ecFlags); +extern int32 curveIdToFlag(int32 id); +#endif + +#ifdef USE_ECC_CIPHER_SUITE +extern int32_t eccSuitesSupported(const ssl_t *ssl, + const uint16_t cipherSpecs[], uint8_t cipherSpecLen); +#endif /* USE_ECC_CIPHER_SUITE */ + + + + +/******************************************************************************/ +/* Deprected defines for compatibility */ +#define CH_RECV_STAT 1 +#define CH_SENT_STAT 2 +#define SH_RECV_STAT 3 +#define SH_SENT_STAT 4 +#define ALERT_SENT_STAT 5 +#define RESUMPTIONS_STAT 6 +#define FAILED_RESUMPTIONS_STAT 7 +#define APP_DATA_RECV_STAT 8 +#define APP_DATA_SENT_STAT 9 + +#ifdef USE_MATRIXSSL_STATS +extern void matrixsslUpdateStat(ssl_t *ssl, int32_t type, int32_t value); +#else +static __inline +void matrixsslUpdateStat(ssl_t *ssl, int32_t type, int32_t value) +{ +} +#endif /* USE_MATRIXSSL_STATS */ + + +#ifdef __cplusplus +} +#endif + +#endif /* _h_MATRIXSSLLIB */ + +/******************************************************************************/ + diff --git a/matrixssl/opensslApi.c b/matrixssl/opensslApi.c new file mode 100644 index 0000000..a2b02d7 --- /dev/null +++ b/matrixssl/opensslApi.c @@ -0,0 +1,1608 @@ +/** + * @file opensslApi.c + * @version $Format:%h%d$ + * + * An OpenSSL interface to MatrixSSL. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include +#include +#include "matrixsslApi.h" + +#ifdef USE_MATRIX_OPENSSL_LAYER + + +/******************************************************************************/ +/* Always returns 1 */ +int SSL_library_init(void) +{ + eeTrace("Enter SSL_library_init\n"); + if (matrixSslOpen() < 0) { + psTraceInfo("Error opening MatrixSSL library via SSL_library_init\n"); + } + eeTrace("Exit SSL_library_init\n"); + return 1; +} + + + +/******************************************************************************/ +/* SSL is an sslConn_t of which SSL_CTX (ssl_t) is a member */ +SSL *SSL_new(SSL_CTX *ctx) +{ + SSL *cp; + eeTrace("Enter SSL_new\n"); + + if ((cp = psMalloc(MATRIX_NO_POOL, sizeof(SSL))) == NULL) { + psTraceInfo("Memory allocation error in SSL_new\n"); + return NULL; + } + memset(cp, 0x0, sizeof(SSL)); + + cp->ctx = ctx; + eeTrace("Exit SSL_new\n"); + return cp; +} + +/******************************************************************************/ +/* Counterpart to SSL_new */ +void SSL_free(SSL *cp) +{ + SSL_CTX *ctx; + eeTrace("Enter SSL_free\n"); + ctx = cp->ctx; + if (ctx->ssl) { + matrixSslDeleteSession(ctx->ssl); + ctx->ssl = NULL; + } + psFree(cp, MATRIX_NO_POOL); + memset(cp, 0x0, sizeof(SSL)); + eeTrace("Exit SSL_free\n"); +} + +/******************************************************************************/ +/* A SSL_CTX is an ssl_t */ +SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) +{ + SSL_CTX *ctx; + + eeTrace("Enter SSL_CTX_new\n"); + if ((ctx = psMalloc(MATRIX_NO_POOL, sizeof(SSL_CTX))) == NULL) { + psTraceInfo("Memory allocation error in SSL_CTX_new\n"); + return NULL; + } + memset(ctx, 0x0, sizeof(SSL_CTX)); + if (matrixSslNewKeys(&ctx->keys, NULL) < 0) { + psTraceInfo("matrixSslNewKeys error in SSL_CTX_new\n"); + psFree(ctx, MATRIX_NO_POOL); + return NULL; + } + eeTrace("Exit SSL_CTX_new\n"); + return ctx; +} + +/******************************************************************************/ +void SSL_CTX_free(SSL_CTX *ctx) +{ + eeTrace("Enter SSL_CTX_free\n"); + matrixSslDeleteKeys(ctx->keys); + if (ctx->ssl) { + psTraceInfo("ERROR: ssl_t session not deleted prior to SSL_CTX_free\n"); + } + psFree(ctx, MATRIX_NO_POOL); + eeTrace("Exit SSL_CTX_free\n"); +} + +/* SSL_CTX_set_options() and SSL_set_options() return the new options + bitmask after adding options. */ +long SSL_CTX_set_options(SSL_CTX *ctx, long options) +{ + uTrace("TODO: SSL_CTX_set_options\n"); + return options; +} + +/* SSL_CTX_set_cipher_list() and SSL_set_cipher_list() return 1 if any + cipher could be selected and 0 on complete failure. */ +int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) +{ + uTrace("TODO: SSL_CTX_set_cipher_list\n"); + return 1; +} + +/* SSL_CTX_load_verify_locations() specifies the locations for ctx, at which + CA certificates for verification purposes are located. The certificates + available via CAfile and CApath are trusted. +*/ +int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath) +{ + uTrace("TODO: SSL_CTX_load_verify_locations\n"); + /* 0 on failure. 1 on success */ + return 0; +} + +/******************************************************************************/ +/* + 0 is failure. 1 is good +*/ +int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) +{ + uTrace("TODO: SSL_CTX_use_certificate_file\n"); + return 1; +} + +X509 *SSL_get_certificate(SSL *ssl) +{ + SSL_CTX *ctx = ssl->ctx; + + eeTrace("Enter SSL_get_certificate\n"); + if (ctx == NULL || ctx->keys == NULL) { + return NULL; + } + eeTrace("Exit SSL_get_certificate\n"); + return ctx->keys->cert; +} + +EVP_PKEY *X509_get_pubkey(X509 *cert) +{ + eeTrace("Enter X509_get_pubkey\n"); + eeTrace("Exit X509_get_pubkey\n"); + return &cert->publicKey; +} + +int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) +{ + uTrace("TODO: EVP_PKEY_copy_parameters\n"); + /* "returns 1 for success and 0 for failure." */ + return 0; +} + +EVP_PKEY *EVP_PKEY_new(void) +{ + psPubKey_t *pubKey; + eeTrace("Enter EVP_PKEY_new\n"); + eeTrace("Exit EVP_PKEY_new\n"); + if (psNewPubKey(NULL, PS_NONE, &pubKey) == PS_SUCCESS) { + return pubKey; + } else { + return NULL; + } +} + +void EVP_PKEY_free(EVP_PKEY *key) +{ + eeTrace("Enter EVP_PKEY_free\n"); + psClearPubKey(key); + psFree(key, NULL); + eeTrace("Exit EVP_PKEY_free\n"); +} + +EVP_PKEY *SSL_get_privatekey(SSL *ssl) +{ + SSL_CTX *ctx = ssl->ctx; + eeTrace("Enter SSL_get_privatekey\n"); + if (ctx == NULL || ctx->keys == NULL) { + return NULL; + } + eeTrace("Exit SSL_get_privatekey\n"); + return &ctx->keys->privKey; +} + +#ifdef USE_RSA +/******************************************************************************/ +/* + MADE THIS FUNCTION UP! + 0 is failure. 1 is good +*/ +int SSL_CTX_load_rsa_key_material(SSL_CTX *ctx, const char *cert, + const char *privkey, const char *CAfile) +{ +#ifdef MATRIX_USE_FILE_SYSTEM + eeTrace("Enter SSL_CTX_load_rsa_key_material\n"); + if (matrixSslLoadRsaKeys(ctx->keys, cert, privkey, NULL, CAfile) != 0) { + psTraceInfo("matrixSslLoadRsaKeys error in openssl module\n"); + return 0; + } + eeTrace("Exit SSL_CTX_load_rsa_key_material\n"); + return 1; +#else + uTrace("TODO: SSL_CTX_load_rsa_key_material\n"); + return 0; +#endif +} +#endif /* REQUIRE_RSA */ + +/******************************************************************************/ +/* FUTURE */ +int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) +{ + uTrace("TODO: SSL_CTX_use_PrivateKey_file\n"); + return 1; +} + +int SSL_CTX_check_private_key(const SSL_CTX *ctx) +{ + uTrace("TODO: SSL_CTX_check_private_key\n"); + return 1; +} + + +/******************************************************************************/ +/* FUTURE */ +void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, int (*pem_password_cb)(char*, + int, int, void*)) +{ + uTrace("TODO: SSL_CTX_set_default_passwd_cb\n"); +} + +/******************************************************************************/ +/* FUTURE */ +int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) +{ + uTrace("TODO: SSL_CTX_use_certificate_chain_file\n"); + return 1; +} + +void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, + int (*verify_callback)(int, X509_STORE_CTX *)) +{ + eeTrace("Enter SSL_CTX_set_verify\n"); + ctx->verify_callback = verify_callback; + eeTrace("Exit SSL_CTX_set_verify\n"); +} + +X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx) +{ + eeTrace("Enter SSL_CTX_get_cert_store\n"); + if (ctx->keys == NULL) { + return NULL; + } + eeTrace("Exit SSL_CTX_get_cert_store\n"); + return ctx->keys->cert; +} + + +/******************************************************************************/ +void SSL_load_error_strings(void) +{ + uTrace("TODO: SSL_load_error_strings\n"); +} +/******************************************************************************/ +void *SSLv23_server_method(void) +{ + uTrace("TODO: SSLv23_server_method\n"); + return NULL; +} +/******************************************************************************/ +void *SSLv23_client_method(void) +{ + uTrace("TODO: SSLv23_client_method\n"); + return NULL; +} +void *SSLv2_client_method(void) +{ + uTrace("DEPRECATED\n"); + return NULL; +} +void *SSLv3_client_method(void) +{ + uTrace("TODO: SSLv3_client_method\n"); + return NULL; +} + +/******************************************************************************/ +int SSL_set_fd(SSL *cp, int fd) +{ + eeTrace("Enter SSL_set_fd\n"); + cp->fd = fd; + eeTrace("Exit SSL_set_fd\n"); + return 1; +} + +/******************************************************************************/ +/* + 1 - The TLS/SSL handshake was successfully completed, a TLS/SSL connection + has been established. + 0 - The TLS/SSL handshake was not successful but was shut down controlled + and by the specifications of the TLS/SSL protocol. Call SSL_get_error() + with the return value ret to find out the reason. + <0 - The TLS/SSL handshake was not successful, because a fatal error + occurred either at the protocol level or a connection failure occurred. + The shutdown was not clean. +*/ +int SSL_do_handshake(SSL *cp) +{ + int32 rc, transferred, len, done; + ssl_t *ssl; + unsigned char *buf; + + eeTrace("Enter SSL_do_handshake\n"); + +// BK HACK + printf("CHANGING SOCKET TO BLOCKING MODE\n"); + setSocketBlock(cp->fd); +// END BK HACK + + ssl = cp->ctx->ssl; + done = 0; + +WRITE_MORE: + while ((len = matrixSslGetOutdata(ssl, &buf)) > 0) { + transferred = socketWrite(cp->fd, buf, len); + if (transferred <= 0) { + psTraceInfo("Socket send failed... exiting\n"); + rc = transferred; + goto L_CLOSE_ERR; + } else { + /* Indicate that we've written > 0 bytes of data */ + if ((rc = matrixSslSentData(ssl, transferred)) < 0) { + goto L_CLOSE_ERR; + } + if (rc == MATRIXSSL_REQUEST_CLOSE) { + /* We've sent an alert that we are closing */ + eeTrace("Exit SSL_do_handshake 1\n"); + return 0; /* Controlled disconnect */ + } + if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) { + /* Client - resumed handshake success + Server - standard handshake success */ + if (ssl->outlen > 0) { + /* Issue here is that SentData returns HANDSHAKE_COMPLETE + when any part of FINISHED message is sent. If this + was a partial send of the FINISHED message we'll need + another pass (or two) to send the remainder */ + done = 1; + } else { + eeTrace("Exit SSL_do_handshake 2\n"); + return 1; + } + } + if (rc == MATRIXSSL_SUCCESS && done == 1 && ssl->outlen == 0) { + eeTrace("Exit SSL_do_handshake 3\n"); + return 1; + } + /* SSL_REQUEST_SEND and SSL_SUCCESS are handled by loop logic */ + } + } +READ_MORE: + if ((len = matrixSslGetReadbuf(ssl, &buf)) <= 0) { + rc = len; + goto L_CLOSE_ERR; + } + if ((transferred = socketRead(cp->fd, buf, len)) < 0) { + psTraceInfo("Socket recv failed... exiting\n"); + rc = transferred; + goto L_CLOSE_ERR; + } + /* If EOF, remote socket closed */ + if (transferred == 0) { + rc = 0; /* Consider this a clean shutdown from client perspective */ + goto L_CLOSE_ERR; + } + if ((rc = matrixSslReceivedData(ssl, (int32)transferred, &buf, + (uint32*)&len)) < 0) { + psTraceInfo("matrixSslReceivedData failure... exiting\n"); + goto L_CLOSE_ERR; + } + +PROCESS_MORE: + switch (rc) { + case MATRIXSSL_HANDSHAKE_COMPLETE: + eeTrace("Exit SSL_do_handshake 4\n"); + return 1; /* Normal handshake success */ + case MATRIXSSL_APP_DATA: + if (!(ssl->flags & SSL_FLAGS_SERVER)) { + /* Client should never see any app data during connection */ + psTraceInfo("Got app data during handshake.. exiting\n"); + rc = PS_UNSUPPORTED_FAIL; + goto L_CLOSE_ERR; + } + /* Case of session resumption with immediate application data + tacked on the end of the client's FINISHED message */ + cp->resumedAppDataLen = len; + cp->appRecLen = len; +#ifdef USE_TLS_1_1 + if (ssl->flags & SSL_FLAGS_TLS_1_1) { + /* ReceivedData is giving good lengths and pointers of the + record itself but we need to add the explicit IV back + in beause we're processing this later */ + cp->outBufOffset = ssl->enBlockSize; + cp->resumedAppDataLen += ssl->enBlockSize; + cp->appRecLen += ssl->enBlockSize; + } +#endif + eeTrace("Exit SSL_do_handshake 5\n"); + return 1; + case MATRIXSSL_REQUEST_SEND: + goto WRITE_MORE; + case MATRIXSSL_REQUEST_RECV: + goto READ_MORE; + case MATRIXSSL_RECEIVED_ALERT: + /* The first byte of the buffer is the level */ + /* The second byte is the description */ + if (*buf == SSL_ALERT_LEVEL_FATAL) { + psTraceIntInfo("Fatal SSL alert: %d, closing connection\n", + *(buf + 1)); + rc = 0; /* Consider it a clean disconnect */ + goto L_CLOSE_ERR; + } + /* Closure alert is normal (and best) way to close */ + if (*(buf + 1) == SSL_ALERT_CLOSE_NOTIFY) { + rc = 0; /* A truly graceful disconnect */ + goto L_CLOSE_ERR; + } + psTraceIntInfo("Warning alert: %d\n", *(buf + 1)); + if ((rc = matrixSslProcessedData(ssl, &buf, (uint32*)&len)) == 0) { + /* No more data in buffer. Might as well read for more. */ + goto READ_MORE; + } + goto PROCESS_MORE; + default: + /* Will never be hit due to rc < 0 test at ReceivedData level */ + goto L_CLOSE_ERR; + } + +L_CLOSE_ERR: + matrixSslDeleteSession(ssl); + cp->ctx->ssl = NULL; + eeTrace("Exit SSL_do_handshake 6\n"); + return rc; +} + +#ifdef USE_SERVER_SIDE_SSL +/******************************************************************************/ +/* + Server side. Accept an incomming SSL connection request. +*/ +int32 SSL_accept(SSL *cp) +{ + ssl_t *ssl; + int32 rc; + sslSessOpts_t options; + + eeTrace("Enter SSL_accept\n"); + memset(&options, 0x0, sizeof(sslSessOpts_t)); +#ifdef USE_CLIENT_AUTH + if ((rc = matrixSslNewServerSession(&ssl, cp->ctx->keys, SSL_cert_auth, + &options)) < 0){ + psTraceIntInfo("matrixSslNewServerSession failed: %d\n", rc); + return rc; + } + ssl->verify_callback = cp->ctx->verify_callback; +#else + if ((rc = matrixSslNewServerSession(&ssl, cp->ctx->keys, NULL, &options)) + < 0){ + psTraceIntInfo("matrixSslNewServerSession failed: %d\n", rc); + return rc; + } +#endif + + cp->ctx->ssl = ssl; + rc = SSL_do_handshake(cp); + eeTrace("Exit SSL_accept\n"); + return rc; +} +#endif + + +#ifdef USE_CLIENT_SIDE_SSL +/******************************************************************************/ +/* + Client side SSL handshake + + OpenSSL return codes: + + 1 - The TLS/SSL handshake was successfully completed, a TLS/SSL connection + has been established. + 0 - The TLS/SSL handshake was not successful but was shut down controlled + and by the specifications of the TLS/SSL protocol. Call SSL_get_error() + with the return value ret to find out the reason. + <0 - The TLS/SSL handshake was not successful, because a fatal error + occurred either at the protocol level or a connection failure occurred. + The shutdown was not clean. +*/ +int32 SSL_connect(SSL *cp) +{ + int32 rc; + ssl_t *ssl; + sslSessOpts_t options; + + eeTrace("Enter SSL_connect\n"); + if (cp->ctx->ssl != NULL) { + if (matrixSslHandshakeIsComplete(cp->ctx->ssl)) { + if (matrixSslEncodeRehandshake(cp->ctx->ssl, NULL, NULL, 0, 0, 0) + < 0) { + psTraceInfo("matrixSslEncodeRehandshake failed\n"); + return -1; + } + } else { + psTraceInfo("ERROR: SSL_connect called on existing SSL\n"); + return -1; + } + } else { +/* HACK - If no keys yet, load some defaults */ + if (cp->ctx->keys->CAcerts == NULL) { + printf("YEAH, DIDN'T HAVE ANY CA CERTS\n"); + SSL_CTX_load_rsa_key_material(cp->ctx, NULL, NULL, + "testkeys/RSA/1024_RSA_CA.pem"); + } else { + printf("HMMMM... why do we have keys\n"); + } +/* END HACK */ + memset(&options, 0x0, sizeof(sslSessOpts_t)); + rc = matrixSslNewClientSession(&ssl, cp->ctx->keys, NULL, NULL, 0, + SSL_cert_auth, NULL, NULL, NULL, &options); + if (rc != MATRIXSSL_REQUEST_SEND) { + psTraceInfo("New client session failed... exiting\n"); + return 0; + } + cp->ctx->ssl = ssl; + } + + if ((rc = SSL_do_handshake(cp)) <= 0) { + cp->ctx->ssl = NULL; + } + eeTrace("Exit SSL_connect\n"); + return rc; + +} +#endif + +/******************************************************************************/ +/* + OpenSSL return codes + + >0 The read operation was successful; the return value is the number + of bytes actually read from the TLS/SSL connection. + + 0 The read operation was not successful. The reason may either be a clean + shutdown due to a ``close notify'' alert sent by the peer. It is also + possible, that the peer simply shut down the underlying transport and + the shutdown is incomplete. + + <0 The read operation was not successful, because either an error occurred + or action must be taken by the calling process. +*/ +int32 SSL_get_data(SSL *cp, unsigned char **ptBuf, int *ptBufLen) +{ + ssl_t *ssl; + unsigned char *ctBuf; + int32 readLen, rc; + int transferred; + + eeTrace("Enter SSL_get_data\n"); + ssl = cp->ctx->ssl; +/* + There are a few ways data might already be available to read for a + server here. They are triggered on whether there is any length for + incoming data. +*/ + if (ssl->inlen > 0) { + if (cp->resumedAppDataLen) { + /* This case is when a session resumption handshake takes place + and the client sends application data in the same flight as + the FINISHED message. In this case, the application data has + already been decrypted and is just waiting to be picked off */ + *ptBuf = ssl->inbuf; + *ptBufLen = ssl->inlen; + ssl->inlen = 0; + cp->resumedAppDataLen = 0; + eeTrace("Exit SSL_get_data 1\n"); + return *ptBufLen; + } else if (ssl->fragTotal) { + goto READ_MORE; /* ALLOW_STREAMING_APP_DATA_DECRYPT */ + } else { + /* This case is the Chrome false start where application data has + been sent in the middle of the handshake. MatrixSSL has not + yet decrypted the data in this case so we do that now. */ + rc = matrixSslReceivedData(ssl, 0, ptBuf, (uint32*)ptBufLen); + goto PROCESS_MORE; + } + } + +READ_MORE: + if ((readLen = matrixSslGetReadbuf(ssl, &ctBuf)) <= 0) { + return readLen; + } + if ((transferred = socketRead(cp->fd, ctBuf, readLen)) < 0) { + psTraceInfo("Socket recv failed... exiting\n"); + return transferred; + } + /* If EOF, remote socket closed */ + if (transferred == 0) { + psTraceInfo("Server disconnected\n"); + eeTrace("Exit SSL_get_data 2\n"); + return 0; /* Consider this a clean shutdown from client perspective */ + } + if ((rc = matrixSslReceivedData(ssl, (int32)transferred, ptBuf, + (uint32*)ptBufLen)) < 0) { + psTraceInfo("matrixSslReceivedData failure... exiting\n"); + return rc; + } + +PROCESS_MORE: + switch (rc) { + case MATRIXSSL_APP_DATA: + if (*ptBufLen == 0) { + /* Eat any zero length records that come across. OpenSSL server + is likely sending some */ + rc = matrixSslProcessedData(ssl, ptBuf, (uint32*)ptBufLen); + goto PROCESS_MORE; + } + eeTrace("Exit SSL_get_data 3\n"); + return *ptBufLen; + case MATRIXSSL_REQUEST_SEND: + SSL_do_handshake(cp); + psTraceInfo("Peer requested a re-handshake\n"); + goto READ_MORE; + case MATRIXSSL_REQUEST_RECV: + goto READ_MORE; + case MATRIXSSL_RECEIVED_ALERT: + /* The first byte of the buffer is the level */ + /* The second byte is the description */ + if (**ptBuf == SSL_ALERT_LEVEL_FATAL) { + psTraceIntInfo("Fatal SSL alert: %d, closing connection\n", + *(*ptBuf + 1)); + eeTrace("Exit SSL_get_data 4\n"); + return 0; /* Actually a clean disconnect */ + } + /* Closure alert is normal (and best) way to close */ + if (*(*ptBuf + 1) == SSL_ALERT_CLOSE_NOTIFY) { + eeTrace("Exit SSL_get_data 5\n"); + return 0; /* Graceful disconnect */ + } + psTraceIntInfo("Warning alert: %d\n", *(*ptBuf + 1)); + if ((rc = matrixSslProcessedData(ssl, ptBuf, (uint32*)ptBufLen)) + == 0) { + /* No more data in buffer. Might as well read for more. */ + goto READ_MORE; + } + goto PROCESS_MORE; + default: + /* MATRIXSSL_HANDSHAKE_COMPLETE */ + /* Will never be hit due to rc < 0 test at ReceivedData level */ + return -1; + } + + eeTrace("Exit SSL_get_data 6\n"); + return -1; /* How to get here? */ +} + +/******************************************************************************/ +/* Not an OpenSSL function */ +/* TODO: return codes. <0 is failure */ +int SSL_processed_data(SSL *cp, unsigned char **ptBuf, int *ptBufLen) +{ + int32 rc; + + eeTrace("Enter SSL_processed_data\n"); + rc = matrixSslProcessedData(cp->ctx->ssl, ptBuf, (uint32*)ptBufLen); + +PROCESS_MORE: + /* MATRIXSSL_SUCCESS or MATRIXSSL_APP_DATA are expected */ + if (rc == MATRIXSSL_RECEIVED_ALERT) { + if (*(*ptBuf + 1) == SSL_ALERT_CLOSE_NOTIFY) { + psTraceInfo("Received close_notify alert from server\n"); + } else { + psTraceInfo("Received unexpected alert from server\n"); + } + rc = matrixSslProcessedData(cp->ctx->ssl, ptBuf, (uint32*)ptBufLen); + goto PROCESS_MORE; + } else if (rc == MATRIXSSL_REQUEST_RECV) { + if (SSL_get_data(cp, ptBuf, ptBufLen) <= 0) { + psTraceInfo("Unable to get next record\n"); + return PS_FAILURE; + } + if (ptBuf == NULL) { + /* always expecting a full record out of here */ + psTraceInfo("Is this a possible case??\n"); + } + } else if (rc != MATRIXSSL_SUCCESS && rc != MATRIXSSL_APP_DATA) { + psTraceIntInfo("!!!!!! Handle this case %d !!!!!! \n", rc); + return PS_UNSUPPORTED_FAIL; + } + eeTrace("Exit SSL_processed_data\n"); + return *ptBufLen; +} + +/* Test if SSL_read has buffered data */ +int SSL_pending(const SSL *ssl) +{ + eeTrace("Enter SSL_pending\n"); + /* Three places data could be waiting */ + /* Anything in the ssl_t inlen means there is data */ + if (ssl->ctx->ssl->inlen > 0) { + eeTrace("Exit SSL_pending 1\n"); + return ssl->ctx->ssl->inlen; + } + /* Corner case of app data following a FINISHED message that doesn't + get pulled out in SSL_do_handshake */ + if (ssl->resumedAppDataLen > 0) { + eeTrace("Exit SSL_pending 2\n"); + return ssl->resumedAppDataLen; + } + /* Partial record still sitting in inbuf */ + eeTrace("Exit SSL_pending 3\n"); + return ssl->appRecLen - ssl->outBufOffset; +} + +/******************************************************************************/ +/* + OpenSSL return codes + + >0 The read operation was successful; the return value is the number + of bytes actually read from the TLS/SSL connection. + + 0 The read operation was not successful. The reason may either be a clean + shutdown due to a ``close notify'' alert sent by the peer. It is also + possible, that the peer simply shut down the underlying transport and + the shutdown is incomplete. + + <0 The read operation was not successful, because either an error occurred + or action must be taken by the calling process. +*/ +int32 SSL_read(SSL *cp, void *userBufPtr, int userBufLen) +{ + ssl_t *ssl; + unsigned char *readBuf, *ptBuf, *userBuf; + int32 readLen, leftover, bytes, rc; + uint32 nextRecLen, ptBufLen; + int transferred; + + eeTrace("Enter SSL_read\n"); + ssl = cp->ctx->ssl; + userBuf = (unsigned char*)userBufPtr; + +/* + There are a few ways data might already be available to read for a + server here. Two are triggered on whether there is any length for + incoming data. +*/ + if (ssl->inlen > 0) { + if (cp->resumedAppDataLen) { + /* This case is when a session resumption handshake takes place + and the client sends application data in the same flight as + the FINISHED message. In this case, the application data has + already been decrypted and is just waiting to be picked off. + The ssl->inlen > 0 indicates the is also more unencrypted + data after this decrypted record. Seen to happen in TLS 1.0 + when 1 byte BEAST workaround record is sent */ + cp->appRecLen = cp->resumedAppDataLen; + cp->outBufOffset = 0; + cp->resumedAppDataLen = 0; + } else { + /* This case is the Chrome false start where application data has + been sent in the middle of the handshake. MatrixSSL has not + yet decrypted the data in this case so we do that now. */ + rc = matrixSslReceivedData(ssl, 0, &ptBuf, &ptBufLen); + goto PROCESS_MORE; + } + } + +/* + Always send any remainder first +*/ + leftover = cp->appRecLen - cp->outBufOffset; + if (leftover > 0) { + bytes = (int32)min(userBufLen, leftover); + memcpy(userBuf, ssl->inbuf + cp->outBufOffset, bytes); + cp->outBufOffset += bytes; + if (cp->outBufOffset == cp->appRecLen) { + cp->outBufOffset = cp->appRecLen = 0; + SSL_processed_data(cp, &ptBuf, (int*)&ptBufLen); + if (ptBufLen > 0) { + /* Make this the next 'leftover' */ + cp->appRecLen = ptBufLen; + } + } + eeTrace("Exit SSL_read 1\n"); + return bytes; + } + + +READ_MORE: + if ((readLen = matrixSslGetReadbuf(ssl, &readBuf)) <= 0) { + return readLen; + } + if ((transferred = socketRead(cp->fd, readBuf, readLen)) < 0) { + psTraceInfo("Socket recv failed... exiting\n"); + return transferred; + } + /* If EOF, remote socket closed */ + if (transferred == 0) { + psTraceInfo("Server disconnected\n"); + eeTrace("Exit SSL_read 2\n"); + return 0; /* Consider this a clean shutdown from client perspective */ + } + if ((rc = matrixSslReceivedData(ssl, (int32)transferred, &ptBuf, + &ptBufLen)) < 0) { + psTraceInfo("matrixSslReceivedData failure... exiting\n"); + return rc; + } + +PROCESS_MORE: + switch (rc) { + case MATRIXSSL_APP_DATA: + + if (ptBufLen == 0) { + /* Eat any zero length records that come across. OpenSSL server + is likely sending some */ + rc = matrixSslProcessedData(ssl, &ptBuf, &ptBufLen); + goto PROCESS_MORE; + } + /* Always a full app data record here but need to know if user + can accept the whole thing in one pass */ + if (ptBufLen <= userBufLen) { + memcpy(userBuf, ptBuf, ptBufLen); + /* Have a full record so update that it's processed */ + SSL_processed_data(cp, &ptBuf, (int*)&nextRecLen); + if (nextRecLen > 0) { + cp->appRecLen = nextRecLen; + } + eeTrace("Exit SSL_read 3\n"); + return ptBufLen; + } else { + cp->appRecLen = ptBufLen; + memcpy(userBuf, ptBuf, userBufLen); + cp->outBufOffset += userBufLen; + eeTrace("Exit SSL_read 4\n"); + return userBufLen; + } + case MATRIXSSL_REQUEST_SEND: + /* If the library is telling us there is data to send, this must + be a re-handshake. (this could also be an alert that is being + sent but SSL_do_handshake will handle this scenario as well) */ + if (SSL_do_handshake(cp) <= 0) { + return -1; + } + goto READ_MORE; + case MATRIXSSL_REQUEST_RECV: + goto READ_MORE; + case MATRIXSSL_RECEIVED_ALERT: + /* The first byte of the buffer is the level */ + /* The second byte is the description */ + if (*ptBuf == SSL_ALERT_LEVEL_FATAL) { + psTraceIntInfo("Fatal SSL alert: %d, closing connection\n", + *(ptBuf + 1)); + eeTrace("Exit SSL_read 5\n"); + return 0; /* Actually a clean disconnect */ + } + /* Closure alert is normal (and best) way to close */ + if (*(ptBuf + 1) == SSL_ALERT_CLOSE_NOTIFY) { + eeTrace("Exit SSL_read 6\n"); + return 0; /* Graceful disconnect */ + } + psTraceIntInfo("Warning alert: %d\n", *(ptBuf + 1)); + if ((rc = matrixSslProcessedData(ssl, &ptBuf, &ptBufLen)) == 0){ + /* No more data in buffer. Might as well read for more. */ + goto READ_MORE; + } + goto PROCESS_MORE; + default: + /* MATRIXSSL_HANDSHAKE_COMPLETE */ + /* Will never be hit due to rc < 0 test at ReceivedData level */ + return -1; + } + + eeTrace("Exit SSL_read 7\n"); + return -1; /* How to get here? */ +} + + +/******************************************************************************/ +/* + OpenSSL return codes + + >0 The write operation was successful, the return value is the number of + bytes actually written to the TLS/SSL connection. + 0 The write operation was not successful. Probably the underlying + connection was closed + <0 The write operation was not successful, because either an error + occurred or action must be taken by the calling process. +*/ +int32 SSL_write(SSL *cp, const void *inbufPtr, int32 inlen) +{ + ssl_t *ssl; + unsigned char *buf; + int transferred; + const char *inbuf; + int32 len, bytesSent = 0; + + eeTrace("Enter SSL_write\n"); + inbuf = (char*)inbufPtr; + ssl = cp->ctx->ssl; + + if (inbuf != NULL) { /* A NULL inbuf means internal buffer needs to flush */ + /* Test if inbuf falls without our buffer to determine + what option they have choosen */ + if (((int32)inbuf >= (int32)ssl->outbuf) && + ((int32)inbuf < (int32)(ssl->outbuf + ssl->outsize))) { + matrixSslEncodeWritebuf(ssl, inlen); + + } else { + matrixSslEncodeToOutdata(ssl, (unsigned char*)inbuf, inlen); + } + } + + while ((len = matrixSslGetOutdata(ssl, &buf)) > 0) { + transferred = socketWrite(cp->fd, buf, len); + if (transferred <= 0) { + psTraceInfo("Socket send failed... exiting\n"); + return transferred; + } else { + bytesSent += transferred; + /* Indicate that we've written > 0 bytes of data */ + if (matrixSslSentData(ssl, transferred) < 0) { + return -1; + } + /* SSL_REQUEST_SEND and SSL_SUCCESS are handled by loop logic */ + } + } + eeTrace("Exit SSL_write\n"); + return bytesSent; +} + + +/******************************************************************************/ +/* + Send a CLOSE_NOTIFY alert and delete a session that was opened with + SSL_accept or SSL_connect +*/ +void SSL_shutdown(SSL *cp) +{ + ssl_t *ssl; + unsigned char *buf; + int32 len; + + eeTrace("Enter SSL_shutdown\n"); + ssl = cp->ctx->ssl; + + if ((ssl != NULL) && (cp->fd > 0)) { + + setSocketNonblock(cp->fd); + /* Quick attempt to send a closure alert, don't worry about failure */ + if (matrixSslEncodeClosureAlert(ssl) >= 0) { + if ((len = matrixSslGetOutdata(ssl, &buf)) > 0) { + if ((len = socketWrite(cp->fd, buf, len)) > 0) { + matrixSslSentData(ssl, len); + } + } + } + matrixSslDeleteSession(ssl); + cp->ctx->ssl = NULL; + } + cp->fd = 0; + eeTrace("Exit SSL_shutdown\n"); +} + +/* "SSL_peek - Copy the data in the SSL buffer into the buffer + passed to this API" */ +int SSL_peek(SSL *s, void *buf, int num) +{ + uTrace("TODO: SSL_peek\n"); + return 0; +} + +/* "SSL_set_connect_state() sets ssl to work in client mode. + + SSL_set_accept_state() sets ssl to work in server mode." */ +void SSL_set_connect_state(SSL *ssl) +{ + uTrace("TODO: SSL_set_connect_state\n"); + return; +} + +/* SSL_set_session() sets session to be used when the TLS/SSL connection is + to be established. SSL_set_session() is only useful for TLS/SSL clients. + When the session is set, the reference count of session is incremented by + 1. If the session is not reused, the reference count is decremented again + during SSL_connect(). Whether the session was reused can be queried with + the SSL_session_reused call. + + If there is already a session set inside ssl (because it was set with + SSL_set_session() before or because the same ssl was already used for a + connection), SSL_SESSION_free() will be called for that session. */ +int SSL_set_session(SSL *ssl, SSL_SESSION *session) +{ + uTrace("TODO: SSL_set_session\n"); + /* 0 is failure. 1 is success */ + return 1; +} + +void SSL_SESSION_free(SSL_SESSION *session) +{ + uTrace("TODO: SSL_SESSION_free\n"); + return; +} + +SSL_SESSION *SSL_get_session(const SSL *ssl) +{ + eeTrace("Enter SSL_get_session\n"); + eeTrace("Exit SSL_get_session\n"); + return ssl; +} + +SSL_CIPHER *SSL_get_cipher(const SSL *ssl) +{ + ssl_t *lssl = ssl->ctx->ssl; + eeTrace("Enter SSL_get_cipher\n"); + if (lssl == NULL) { + return NULL; + } + eeTrace("Exit SSL_get_cipher\n"); + return lssl->cipher; +} + +X509 *SSL_get_peer_cert_chain(const SSL *s) +{ + ssl_t *lssl = s->ctx->ssl; + eeTrace("Enter SSL_get_peer_cert_chain\n"); + if (lssl == NULL) { + return NULL; + } + eeTrace("Exit SSL_get_peer_cert_chain\n"); + return lssl->sec.cert; +} + +X509 *SSL_get_peer_certificate(const SSL *s) +{ + ssl_t *lssl = s->ctx->ssl; + eeTrace("Enter SSL_get_peer_certificate\n"); + if (lssl == NULL) { + return NULL; + } + eeTrace("Exit SSL_get_peer_certificate\n"); + return lssl->sec.cert; +} + +/* SSL_get_verify_result() returns the result of the verification of the X509 + certificate presented by the peer, if any. */ +long SSL_get_verify_result(const SSL *ssl) +{ + ssl_t *lssl = ssl->ctx->ssl; + eeTrace("Enter SSL_get_verify_result\n"); + + /* X509_V_OK if verification succeeded or no peer cert presented */ + + eeTrace("Exit SSL_get_verify_result\n"); + return lssl->sec.cert->authStatus; +} + +/* X509_verify_cert_error_string() returns a human readable error string for + verification error n. */ +const char *X509_verify_cert_error_string(long n) +{ + /* Return string of authStatus (n) */ + uTrace("TODO: X509_verify_cert_error_string\n"); + return NULL; +} + +int SSL_version(SSL *ssl) +{ + ssl_t *lssl = ssl->ctx->ssl; + eeTrace("Enter SSL_version\n"); + eeTrace("Exit SSL_version\n"); + if (lssl->minVer == SSL3_MIN_VER) { + return SSL3_VERSION; + } else if (lssl->minVer == TLS_MIN_VER) { + return TLS1_VERSION; + } else if (lssl->minVer == TLS_1_1_MIN_VER) { + return TLS1_1_VERSION; + } else if (lssl->minVer == TLS_1_2_MIN_VER) { + return TLS1_2_VERSION; + } else { + return SSL2_VERSION; + } + +} +/******************************************************************************/ +/* + MatrixSSL err + + "SSL_get_error() returns a result code (suitable for the C "switch" + statement) for a preceding call to SSL_connect(), SSL_accept(), + SSL_do_handshake(), SSL_read(), SSL_peek(), or SSL_write() on ssl. The + value returned by that TLS/SSL I/O function must be passed to + SSL_get_error() in parameter ret. + + In addition to ssl and ret, SSL_get_error() inspects the current thread's + OpenSSL error queue. Thus, SSL_get_error() must be used in the same thread + that performed the TLS/SSL I/O operation, and no other OpenSSL function + calls should appear in between. The current thread's error queue must be + empty before the TLS/SSL I/O operation is attempted, or SSL_get_error() + will not work reliably." + + These are what callers will be expecting!! + + #define SSL_ERROR_NONE 0 + #define SSL_ERROR_SSL 1 + #define SSL_ERROR_WANT_READ 2 + #define SSL_ERROR_WANT_WRITE 3 + #define SSL_ERROR_WANT_X509_LOOKUP 4 + #define SSL_ERROR_SYSCALL 5 + #define SSL_ERROR_ZERO_RETURN 6 + #define SSL_ERROR_WANT_CONNECT 7 + #define SSL_ERROR_WANT_ACCEPT 8 +*/ +int SSL_get_error(const SSL *cp, int ret) +{ + eeTrace("Enter SSL_get_error\n"); + if (cp->ctx->ssl) { + eeTrace("Exit SSL_get_error\n"); + return cp->ctx->ssl->err; + } + return 0; +} + + +/* Invoke the users registered callback if exists */ +int32 SSL_cert_auth(ssl_t *ssl, psX509Cert_t *cert, int32 alert) +{ + eeTrace("Enter SSL_cert_auth\n"); + if (ssl->verify_callback) { + alert = ssl->verify_callback(alert, cert); + } + eeTrace("Exit SSL_cert_auth\n"); + + printf("HARD CODE SUCCESS RETURN FROM CERT CBACK\n"); + return 0; + //return alert; +} + + +/******************************************************************************/ +/* Mongoose web server wants */ + +int CRYPTO_num_locks(void) +{ + uTrace("TODO: CRYPTO_num_locks\n"); + return 1; +} + +void CRYPTO_set_locking_callback(void (*cb)(int, int, const char *, int)) +{ + uTrace("TODO: CRYPTO_set_locking_callback\n"); +} + +extern void CRYPTO_set_id_callback(unsigned long (*cb)(void)) +{ + uTrace("TODO: CRYPTO_set_id_callback\n"); +} + +unsigned long ERR_get_error(void) +{ + uTrace("TODO: ERR_get_error\n"); + return 0; +} + +char *ERR_error_string(unsigned long x, char *y) +{ + uTrace("TODO: ERR_error_string\n"); + return "unimplemented"; +} +/* End Mongoose */ + +void ERR_free_strings(void) +{ + uTrace("TODO: ERR_free_strings\n"); + return; +} + +void ERR_remove_state(unsigned long pid) +{ + uTrace("TODO: ERR_remove_state\n"); + return; +} + +void ERR_clear_error(void) +{ + uTrace("TODO: ERR_clear_error\n"); + return; +} + +unsigned long ERR_peek_error(void) +{ + uTrace("TODO: ERR_peek_error\n"); + return 0; +} + +/******************************************************************************/ +/* cURL wants */ + +/* Uses 'max_bytes' from the file to add to the PRNG. There is no context + parameter here so we'd need to create a global one if this family of + APIs are implemented. It looks like maybe RAND_set_rand_engine could be + used as an initialization point, but it looks like there is also a default + RAND engine so couldn't rely on that necessarily */ +int RAND_load_file(const char *filename, long max_bytes) +{ + uTrace("TODO: RAND_load_file\n"); + return (int)max_bytes; +} + +void RAND_add(const void *buf, int num, int entropy) +{ + uTrace("TODO: RAND_add\n"); +} + +/* "generates a default path for the random seed file. buf points to a buffer + of size num in which to store the filename. The seed file is $RANDFILE if + that environment variable is set, $HOME/.rnd otherwise. If $HOME is not + set either, or num is too small for the path name, an error occurs. */ +const char *RAND_file_name(char *buf, size_t num) +{ + uTrace("TODO: RAND_file_name\n"); + return NULL; +} + +int RAND_status(void) +{ + uTrace("TODO: RAND_status\n"); + return 1; +} + +int RAND_bytes(unsigned char *buf, int num) +{ + int rc; + eeTrace("Enter RAND_bytes\n"); + rc = (int)psGetEntropy(buf, (int)num, NULL); + eeTrace("Exit RAND_bytes\n"); + return rc; +} + +/* + typedef struct { + sslBuf_t *buf; + int type; + } BIO_METHOD; + + typedef struct { + BIO_METHOD *method; + } BIO; +*/ + +BIO *BIO_new(BIO_METHOD *type) +{ + BIO *new; + + eeTrace("Enter BIO_new\n"); + new = psMalloc(NULL, sizeof(BIO)); + if (new == NULL) { + return NULL; + } + new->method = type; + eeTrace("Exit BIO_new\n"); + return new; +} + +int BIO_free(BIO *a) +{ + BIO_METHOD *method; + + eeTrace("Enter BIO_free\n"); + if (a == NULL) { + return 0; + } + method = a->method; + if (method->buf) { + if (method->buf->buf) { + psFree(method->buf->buf, NULL); + } + psFree(method->buf, NULL); + } + psFree(method, NULL); + memset_s(method, sizeof(BIO), 0x0, sizeof(BIO_METHOD)); + + psFree(a, NULL); + eeTrace("Exit BIO_free\n"); + return 1; +} + +BIO_METHOD *BIO_s_mem(void) +{ + BIO_METHOD *new; + psBuf_t *buf; + + eeTrace("Enter BIO_s_mem\n"); + + new = psMalloc(NULL, sizeof(BIO_METHOD)); + if (new == NULL) { + return NULL; + } + buf = psMalloc(NULL, sizeof(psBuf_t)); + if (buf == NULL) { + psFree(new, NULL); + return NULL; + } + buf->start = buf->end = buf->buf = psMalloc(NULL, DEFAULT_BIO_BUF_LEN); + if (buf->start == NULL) { + psFree(new, NULL); + psFree(buf, NULL); + return NULL; + } + buf->size = DEFAULT_BIO_BUF_LEN; + + new->type = BIO_S_MEM_TYPE; + new->buf = buf; + eeTrace("Exit BIO_s_mem\n"); + return new; +} + + +void BIO_get_mem_ptr(BIO *b, BUF_MEM **pp) +{ + eeTrace("Enter BIO_get_mem_ptr\n"); + *pp = NULL; + if (b == NULL) { + return; + } + (*pp)->data = b->method->buf->start; + (*pp)->length = (b->method->buf->end - b->method->buf->start); + eeTrace("Exit BIO_get_mem_ptr\n"); +} + +int PEM_write_bio_X509(BIO *bp, X509 *x) +{ + /* Copy x.509 to BIO */ + uTrace("TODO: PEM_write_bio_X509\n"); + return 0; +} + +int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, unsigned long flags) +{ + /* Copy x.509 name to BIO */ + uTrace("TODO: X509_NAME_print_ex\n"); + return 0; +} + +X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx) +{ + eeTrace("Enter X509_STORE_CTX_get_current_cert\n"); + eeTrace("Exit X509_STORE_CTX_get_current_cert\n"); + return ctx; +} + +X509_NAME * X509_get_subject_name(X509 *a) +{ + eeTrace("Enter X509_get_subject_name\n"); + eeTrace("Exit X509_get_subject_name\n"); + return &a->subject; +} + +char * X509_NAME_oneline(X509_NAME *a,char *buf,int size) +{ + uTrace("TODO: X509_NAME_oneline\n"); + return NULL; +} + +int sk_X509_num(X509 *certs) +{ + eeTrace("Enter sk_X509_num\n"); + X509 *next = certs; + int i = 1; + + while (next->next) { + i++; + next = next->next; + } + eeTrace("Exit sk_X509_num\n"); + return i; +} + +X509 *sk_X509_value(X509 *cert, int i) +{ + X509 *cur = cert; + + eeTrace("Enter sk_X509_value\n"); + /* TODO: this is using a zero based count */ + while (i > 0) { + cur = cur->next; + i++; + } + eeTrace("Exit sk_X509_value\n"); + return cur; +} + +/* Related to STACK_OF. Our extension structure isn't a list. It's just + one big struct that holds all the ones we care about */ +int sk_X509_EXTENSION_num(X509_EXTENSION *ext) +{ + uTrace("TODO: sk_X509_EXTENSION_num\n"); + return 1; /* Never a list */ +} + +X509_EXTENSION *sk_X509_EXTENSION_value(X509_EXTENSION *ext, int i) +{ + uTrace("TODO: sk_X509_EXTENSION_value\n"); + return ext; +} + +ASN1_OBJECT * X509_EXTENSION_get_object(X509_EXTENSION *ex) +{ + /* Hmm... how would we map our current extension to an "object" */ + uTrace("TODO: X509_EXTENSION_get_object\n"); + return NULL; +} + +int X509_EXTENSION_get_critical(X509_EXTENSION *ex) +{ + eeTrace("Enter X509_EXTENSION_get_critical\n"); + eeTrace("Exit X509_EXTENSION_get_critical\n"); + return ex->critFlags; +} + +int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, + int indent) +{ + uTrace("TODO: X509V3_EXT_print\n"); + return 0; +} + +/********/ +void OPENSSL_load_builtin_modules(void) +{ + uTrace("TODO: OPENSSL_load_builtin_modules\n"); + return; +} + + +int CONF_modules_load_file(const char *filename, const char *appname, + unsigned long flags) +{ + psTraceInfo("There is no configuration file for MatrixSSL\n"); + return 0; +} + +void EVP_cleanup(void) +{ + uTrace("TODO: EVP_cleanup\n"); + return; +} + +void *X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx) +{ + uTrace("TODO: X509_get_ext_d2i\n"); + return NULL; +} + +/* X509_NAME_get_index_by_NID() and X509_NAME_get_index_by_OBJ() retrieve the + next index matching nid or obj after lastpos. lastpos should initially be + set to -1. If there are no more entries -1 is returned. */ +int X509_NAME_get_index_by_NID(X509_NAME *name,int nid,int lastpos) +{ + /* NID_commonName is nid */ + uTrace("TODO: X509_NAME_get_index_by_NID\n"); + return 0; +} + +X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc) +{ + uTrace("TODO: X509_NAME_get_entry\n"); + return NULL; +} + +ASN1_STRING * X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne) +{ + uTrace("TODO: X509_NAME_ENTRY_get_data\n"); + return NULL; +} + +X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) +{ + uTrace("TODO: X509_STORE_add_lookup\n"); + return NULL; +} + +X509_LOOKUP_METHOD *X509_LOOKUP_file(void) +{ + uTrace("TODO: X509_LOOKUP_file\n"); + return NULL; +} + +int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags) +{ + uTrace("TODO: X509_STORE_set_flags\n"); + return 0; +} + +int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type) +{ + uTrace("TODO: X509_load_crl_file\n"); + return 0; +} + + +void GENERAL_NAMES_free(GENERAL_NAME *name) +{ + uTrace("TODO: GENERAL_NAMES_free\n"); + return; +} + +const GENERAL_NAME *sk_GENERAL_NAME_value(GENERAL_NAME *altnames, int i) +{ + uTrace("TODO: sk_GENERAL_NAME_value\n"); + return NULL; +} + +int sk_GENERAL_NAME_num(GENERAL_NAME *names) +{ + uTrace("TODO: sk_GENERAL_NAME_num\n"); + return 0; +} + +unsigned char * ASN1_STRING_data(ASN1_STRING *x) +{ + eeTrace("Enter ASN1_STRING_data\n"); + eeTrace("Exit ASN1_STRING_data\n"); + return x->data; +} + +size_t ASN1_STRING_length(ASN1_STRING *x) +{ + eeTrace("Enter ASN1_STRING_length\n"); + eeTrace("Exit ASN1_STRING_length\n"); + return x->length; +} + +int ASN1_STRING_type(ASN1_STRING *x) +{ + eeTrace("Enter ASN1_STRING_type\n"); + eeTrace("Exit ASN1_STRING_type\n"); + return x->type; +} + +int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in) +{ + eeTrace("Enter ASN1_STRING_to_UTF8\n"); + eeTrace("Exit ASN1_STRING_to_UTF8\n"); + *out = in->data; + return 0; +} + +int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v) +{ + uTrace("TODO: ASN1_STRING_print\n"); + return 0; +} + +/* i2t_ASN1_OBJECT tries to find the LN (long name) associated with the + ASN1_OBJECT a and puts it in the buffer buf, or up to buf_len bytes of it, + at any rate. If no LN can be found, then the OID (a->data) is written out + into buf instead, in "##.##.##" format, where the ## are digits. If there + is room, the string written into buf is null-termnated. The number of + bytes written into buf is returned. */ +int i2t_ASN1_OBJECT(char *buf,int buf_len,ASN1_OBJECT *a) +{ + uTrace("TODO: i2t_ASN1_OBJECT\n"); + memcpy(buf, a, buf_len); + return buf_len; +} + +#endif /* USE_MATRIX_OPENSSL_LAYER */ diff --git a/matrixssl/opensslApi.h b/matrixssl/opensslApi.h new file mode 100644 index 0000000..5d8d6db --- /dev/null +++ b/matrixssl/opensslApi.h @@ -0,0 +1,399 @@ +/** + * @file opensslApi.h + * @version $Format:%h%d$ + * + * An OpenSSL interface to MatrixSSL. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ + +/******************************************************************************/ + +#ifndef _h_SSLAPI +#define _h_SSLAPI + +#ifdef __cplusplus +extern "C" { +#endif + +#include "opensslSocket.h" + +#ifdef USE_MATRIX_OPENSSL_LAYER + +#define ENABLE_ENTRY_EXIT_TRACE +#define ENABLE_UNIMPLEMENTED_TRACE + +#ifdef ENABLE_ENTRY_EXIT_TRACE +#define eeTrace _psTrace +#else +#define eeTrace +#endif + +#ifdef ENABLE_UNIMPLEMENTED_TRACE +#define uTrace _psTrace +#else +#define uTrace +#endif + + +typedef psX509Cert_t X509_STORE_CTX; +typedef psX509Cert_t X509_STORE; +typedef psX509Cert_t X509; +typedef x509DNattributes_t X509_NAME; +typedef psPubKey_t EVP_PKEY; +typedef void X509_LOOKUP; +typedef x509v3extensions_t X509_EXTENSION; + +/* Lookup CRLs */ +#define X509_V_FLAG_CRL_CHECK 0x4 +/* Lookup CRLs for whole chain */ +#define X509_V_FLAG_CRL_CHECK_ALL 0x8 + +typedef struct { + sslCertCb_t method; +} X509_LOOKUP_METHOD; + +typedef struct { + psX509Cert_t *cert_info; +} X509_CINF; /* cert info */ + +#define X509_FILETYPE_PEM 1 +#define X509_V_OK 0 + +typedef struct { + sslKeys_t *keys; + int (*verify_callback)(int, X509_STORE_CTX *); + ssl_t *ssl; +} SSL_CTX; + +typedef struct { + SSL_CTX *ctx; + sslSessionId_t *resume; +// sslKeys_t *keys; + int32 fd; + int32 outBufOffset; + int32 appRecLen; + int32 resumedAppDataLen; +} SSL; + +typedef sslCipherSpec_t SSL_CIPHER; + +/***/ + +#define STACK_OF(x) x + + +/*** BIO ***/ + +typedef struct { + sslBuf_t *buf; + int type; +} BIO_METHOD; + +typedef struct { + BIO_METHOD *method; +} BIO; + +#define BIO_S_MEM_TYPE 1 + +typedef struct { + int length; + unsigned char *data; +} BUF_MEM; + +typedef SSL SSL_SESSION; +typedef void SSL_METHOD; +#define SSL_METHOD_QUAL + +/* use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 2 options + * are 'ored' with SSL_VERIFY_PEER if they are desired */ +#define SSL_VERIFY_NONE 0x00 +#define SSL_VERIFY_PEER 0x01 +#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02 +#define SSL_VERIFY_CLIENT_ONCE 0x04 + +#define SSL_FILETYPE_PEM 1 +#define SSL_FILETYPE_ASN1 2 +#define SSL_FILETYPE_ENGINE 3 +#define SSL_FILETYPE_PKCS12 4 + +/* CONF_MFLAGS_IGNORE_MISSING_FILE if set will make CONF_load_modules_file() + ignore missing configuration files. Normally a missing configuration file + return an error. */ +#define CONF_MFLAGS_IGNORE_MISSING_FILE 1 + +/* The options XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_CPLUS_SPC, + XN_FLAG_SEP_SPLUS_SPC and XN_FLAG_SEP_MULTILINE determine the field + separators to use. Two distinct separators are used between distinct + RelativeDistinguishedName components and separate values in the same RDN + for a multi-valued RDN. Multi-valued RDNs are currently very rare so the + second separator will hardly ever be used */ +#define XN_FLAG_SEP_COMMA_PLUS 1 +#define XN_FLAG_SEP_CPLUS_SPC 2 +#define XN_FLAG_SEP_SPLUS_SPC 3 +#define XN_FLAG_SEP_MULTILINE 4 + + +#define SSL_ERROR_NONE 0 +#define SSL_ERROR_SSL 1 +#define SSL_ERROR_WANT_READ 2 +#define SSL_ERROR_WANT_WRITE 3 +#define SSL_ERROR_WANT_X509_LOOKUP 4 +#define SSL_ERROR_SYSCALL 5 +#define SSL_ERROR_ZERO_RETURN 6 +#define SSL_ERROR_WANT_CONNECT 7 +#define SSL_ERROR_WANT_ACCEPT 8 + +#define SSL2_VERSION 0x0002 +#define SSL3_VERSION 0x0300 +#define TLS1_VERSION 0x0301 +#define TLS1_1_VERSION 0x0302 +#define TLS1_2_VERSION 0x0303 + +#define NID_subject_alt_name 85 +#define NID_commonName 13 + +#define SSL_OP_ALL 0x80000BFFL +#define SSL_OP_NO_SSLv2 0x01000000L +#define SSL_OP_NO_SSLv3 0x02000000L +#define SSL_OP_NO_TLSv1 0x04000000L +#define SSL_OP_NO_TLSv1_2 0x08000000L +#define SSL_OP_NO_TLSv1_1 0x10000000L + + +typedef struct asn1_string_st +{ + int length; + int type; + unsigned char *data; +} ASN1_STRING; + +typedef unsigned char* ASN1_OBJECT; +typedef ASN1_STRING ASN1_UTCTIME; +typedef ASN1_STRING ASN1_INTEGER; +typedef ASN1_STRING ASN1_TIME; +#define V_ASN1_UTF8STRING ASN_UTF8STRING + +typedef struct GENERAL_NAME_st { + +#define GEN_OTHERNAME 0 +#define GEN_EMAIL 1 +#define GEN_DNS 2 +#define GEN_X400 3 +#define GEN_DIRNAME 4 +#define GEN_EDIPARTY 5 +#define GEN_URI 6 +#define GEN_IPADD 7 +#define GEN_RID 8 + +int type; +union { + ASN1_STRING *ptr; + ASN1_STRING *otherName; /* otherName */ + ASN1_STRING *rfc822Name; + ASN1_STRING *dNSName; + ASN1_STRING *x400Address; + ASN1_STRING *directoryName; + ASN1_STRING *ediPartyName; + ASN1_STRING *uniformResourceIdentifier; + ASN1_STRING *iPAddress; + ASN1_STRING *registeredID; + + /* Old names */ + ASN1_STRING *ip; /* iPAddress */ + ASN1_STRING *dirn; /* dirn */ + ASN1_STRING *ia5;/* rfc822Name, dNSName, uniformResourceIdentifier */ + ASN1_STRING *rid; /* registeredID */ + ASN1_STRING *other; /* x400Address */ +} d; +} GENERAL_NAME; + + + + + /* OpenSSL API */ +int SSL_library_init(void); +#define OpenSSL_add_ssl_algorithms() SSL_library_init() +#define SSLeay_add_ssl_algorithms() SSL_library_init() +#define OpenSSL_add_all_algorithms() SSL_library_init() +void SSL_load_error_strings(void); +void ERR_free_strings(void); +void ERR_remove_state(unsigned long pid); +void ERR_clear_error(void); +unsigned long ERR_peek_error(void); +int CONF_modules_load_file(const char *filename, const char *appname, + unsigned long flags); +void EVP_cleanup(void); + +long SSL_CTX_set_options(SSL_CTX *ctx, long options); +int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str); +int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath); +int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type); +int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); +int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type); +int SSL_CTX_check_private_key(const SSL_CTX *ctx); +X509 *SSL_get_certificate(SSL *ssl); +EVP_PKEY *X509_get_pubkey(X509 *cert); +EVP_PKEY *SSL_get_privatekey(SSL *s); +long SSL_get_verify_result(const SSL *ssl); +int SSL_get_error(const SSL *cp, int ret); +SSL_CIPHER *SSL_get_cipher(const SSL *ssl); +X509 *SSL_get_peer_cert_chain(const SSL *s); +X509 *SSL_get_peer_certificate(const SSL *s); + +EVP_PKEY *EVP_PKEY_new(void); +void EVP_PKEY_free(EVP_PKEY *key); +int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from); + +void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, + int (*pem_password_cb)(char*, int, int, void*)); +int SSL_CTX_load_rsa_key_material(SSL_CTX *ctx, const char *cert, + const char *privkey, const char *CAfile); /* not openssl */ +void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, + int (*verify_callback)(int, X509_STORE_CTX *)); +X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx); + +SSL *SSL_new(SSL_CTX *ctx); +void SSL_free(SSL *cp); +SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth); +void SSL_CTX_free(SSL_CTX *ctx); + +void SSL_SESSION_free(SSL_SESSION *session); + +void *SSLv23_server_method(void); +void *SSLv23_client_method(void); +void *SSLv2_client_method(void); +void *SSLv3_client_method(void); +int SSL_set_fd(SSL *cp, int fd); + +int SSL_accept(SSL *cp); +int SSL_connect(SSL *cp); +int SSL_do_handshake(SSL *cp); + +int SSL_get_data(SSL *cp, unsigned char **ptBuf, int *ptBufLen); +int SSL_processed_data(SSL *cp, unsigned char **ptBuf, int *ptBufLen); + +int SSL_pending(const SSL *ssl); +int SSL_read(SSL *cp, void *userBuf, int userBufLen); +int SSL_write(SSL *cp, const void *inbuf, int32 inlen); +void SSL_shutdown(SSL *cp); + +int32 SSL_cert_auth(ssl_t *ssl, psX509Cert_t *cert, int32 alert); + +int SSL_peek(SSL *s, void *buf, int num); +void SSL_set_connect_state(SSL *ssl); +int SSL_set_session(SSL *ssl, SSL_SESSION *session); +SSL_SESSION *SSL_get_session(const SSL *ssl); + + +int SSL_version(SSL *ssl); + +#define DEFAULT_BIO_BUF_LEN 1024 +BIO *BIO_new(BIO_METHOD *type); +int BIO_free(BIO *a); +BIO_METHOD *BIO_s_mem(void); +void BIO_get_mem_ptr(BIO *b,BUF_MEM **pp); + +typedef psDigestContext_t MD5_CTX; +#define MD5_Init psMd5Init +#define MD5_Update psMd5Update +#define MD5_Final(a, b) psMd5Final(b, a) + + + +int PEM_write_bio_X509(BIO *bp, X509 *x); + + +typedef x509DNattributes_t X509_NAME_ENTRY; +int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, unsigned long flags); +int X509_NAME_get_index_by_NID(X509_NAME *name,int nid,int lastpos); +X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc); +ASN1_STRING * X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne); +X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx); +X509_NAME * X509_get_subject_name(X509 *a); +char * X509_NAME_oneline(X509_NAME *a,char *buf,int size); +X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m); +int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags); +X509_LOOKUP_METHOD *X509_LOOKUP_file(void); +int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type); +int sk_X509_EXTENSION_num(X509_EXTENSION *ext); +int sk_X509_num(X509 *certs); +X509_EXTENSION *sk_X509_EXTENSION_value(X509_EXTENSION *ext, int i); +ASN1_OBJECT * X509_EXTENSION_get_object(X509_EXTENSION *ex); +int X509_EXTENSION_get_critical(X509_EXTENSION *ex); +int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, + int indent); +X509 *sk_X509_value(X509 *cert, int i); + +const char *X509_verify_cert_error_string(long n); + +void OPENSSL_load_builtin_modules(void); + + +/* Mongoose web server no-ops */ +int CRYPTO_num_locks(void); +void CRYPTO_set_locking_callback(void (*cb)(int, int, const char *, int)); +void CRYPTO_set_id_callback(unsigned long (*cb)(void)); +unsigned long ERR_get_error(void); +char *ERR_error_string(unsigned long x, char *y); + + +/* cURL no-ops */ +int RAND_load_file(const char *filename, long max_bytes); +void RAND_add(const void *buf, int num, int entropy); +int RAND_status(void); +const char *RAND_file_name(char *buf, size_t num); +int RAND_bytes(unsigned char *buf, int num); + + + + +void * X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx); +const GENERAL_NAME *sk_GENERAL_NAME_value(GENERAL_NAME *altnames, int i); +int sk_GENERAL_NAME_num(GENERAL_NAME *names); +void GENERAL_NAMES_free(GENERAL_NAME *name); + + +unsigned char * ASN1_STRING_data(ASN1_STRING *x); +size_t ASN1_STRING_length(ASN1_STRING *x); +int ASN1_STRING_type(ASN1_STRING *x); +int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in); +int i2t_ASN1_OBJECT(char *buf,int buf_len,ASN1_OBJECT *a); +int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v); + + +#define OPENSSL_malloc(x) psMalloc(NULL, x) +#define OPENSSL_free(x) psFree(x, NULL) +#ifdef __cplusplus +} +#endif + +#endif /* USE_MATRIX_OPENSSL_LAYER */ +#endif /* _h_SSLAPI */ + +/******************************************************************************/ diff --git a/matrixssl/opensslSocket.c b/matrixssl/opensslSocket.c new file mode 100644 index 0000000..3c8331d --- /dev/null +++ b/matrixssl/opensslSocket.c @@ -0,0 +1,315 @@ +/** + * @file opensslSocket.c + * @version $Format:%h%d$ + * + * BSD socket implementation for supporting SSL_read, SSL_write, etc.... + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include +#include + +#include "opensslSocket.h" + +#ifdef USE_MATRIX_OPENSSL_LAYER +/******************************************************************************/ +/* + Client side. Open a socket connection to a remote ip and port. + This code is not specific to SSL. +*/ +int socketConnect(char *ip, short port, int *err) +{ + struct sockaddr_in addr; + int fd, rc; + + eeTrace("Enter socketConnect\n"); + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + psTraceInfo("Error creating socket\n"); + *err = getSocketError(); + return SOCKET_ERROR; + } +/* + Make sure the socket is not inherited by exec'd processes + Set the REUSEADDR flag to minimize the number of sockets in TIME_WAIT +*/ + fcntl(fd, F_SETFD, FD_CLOEXEC); + rc = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc)); + setSocketNodelay(fd); +/* + Turn on blocking mode for the connecting socket +*/ + setSocketBlock(fd); + + memset((char *) &addr, 0x0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = inet_addr(ip); + rc = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); +#if WIN + if (rc != 0) { +#else + if (rc < 0) { +#endif + *err = getSocketError(); + return SOCKET_ERROR; + } + eeTrace("Exit socketConnect\n"); + return fd; +} + +/******************************************************************************/ +/* + Server side. Set up a listen socket. This code is not specific to SSL. +*/ +int socketListen(short port, int *err) +{ + struct sockaddr_in addr; + int fd; + int32 rc; + + eeTrace("Enter socketListen\n"); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = INADDR_ANY; + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + psTraceInfo("Error creating listen socket\n"); + *err = getSocketError(); + return SOCKET_ERROR; + } +/* + Make sure the socket is not inherited by exec'd processes + Set the REUSE flag to minimize the number of sockets in TIME_WAIT +*/ + fcntl(fd, F_SETFD, FD_CLOEXEC); + rc = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc)); + + if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + psTraceInfo("Can't bind socket. Port in use or insufficient privilege\n"); + *err = getSocketError(); + return SOCKET_ERROR; + } + if (listen(fd, SOMAXCONN) < 0) { + psTraceInfo("Error listening on socket\n"); + *err = getSocketError(); + return SOCKET_ERROR; + } + printf("Listening for SSL connections on port %d\n", port); + eeTrace("Exit socketListen\n"); + return fd; +} + +/******************************************************************************/ +/* + Server side. Accept a new socket connection off our listen socket. + This code is not specific to SSL. +*/ +int socketAccept(int listenfd, int32 *err) +{ + struct sockaddr_in addr; + int fd; + unsigned int len; + + eeTrace("Enter socketAccept\n"); +/* + Wait(blocking)/poll(non-blocking) for an incoming connection +*/ + len = sizeof(addr); + if ((fd = accept(listenfd, (struct sockaddr *)&addr, &len)) + == SOCKET_ERROR) { + *err = getSocketError(); + if (*err != WOULD_BLOCK) { + psTraceIntInfo("Error %d accepting new socket\n", (int)*err); + } + return SOCKET_ERROR; + } +/* + fd is the newly accepted socket. Disable Nagle on this socket. + Set blocking mode as default +*/ +/* fprintf(stdout, "Connection received from %d.%d.%d.%d\n", + addr.sin_addr.S_un.S_un_b.s_b1, + addr.sin_addr.S_un.S_un_b.s_b2, + addr.sin_addr.S_un.S_un_b.s_b3, + addr.sin_addr.S_un.S_un_b.s_b4); +*/ + setSocketNodelay(fd); + setSocketBlock(fd); + eeTrace("Exit socketAccept\n"); + return fd; +} + +/******************************************************************************/ +/* + Set the socket to non blocking mode and perform a few extra tricks + to make sure the socket closes down cross platform +*/ +void socketClose(int sock) +{ + char buf[32]; + + eeTrace("Enter socketClose\n"); + if (sock != SOCKET_ERROR) { + setSocketNonblock(sock); + if (shutdown(sock, 1) >= 0) { + while (recv(sock, buf, sizeof(buf), 0) > 0); + } + close(sock); + } + eeTrace("Exit socketClose\n"); +} + +//#define FRAG_TEST +#ifdef FRAG_TEST +/******************************************************************************/ +/* + INTERNAL FUNCTION + Randomly send less than the requested number of bytes + Simulates a slow or congested network interface that may fragment records + */ +static int32 fragSend(int fd, unsigned char *buf, int32 len, int32 flags) +{ + unsigned char c; + int32 nlen; + struct timespec rqtp; + + rqtp.tv_sec = 0; + rqtp.tv_nsec = 1000000000 >> 4; /* 1/16 second */ + nlen = len; + if (nlen > 10) { + psGetEntropy(&c, 1, NULL); + nlen = (int32)c; + if (nlen == 0) { + nlen++; + } else if (nlen > len) { + //nlen = (unsigned char)len; + nlen = 10; + } + } + printf("sending fragment %d/%d bytes\n", nlen, len); + len = send(fd, buf, nlen, flags); + /* Sleep to give time for network to flush */ + nanosleep(&rqtp, NULL); + return len; +} +#endif /* TEST */ + +/******************************************************************************/ +/* + Perform a blocking write of data to a socket +*/ +int socketWrite(int sock, unsigned char *out, int len) +{ + ssize_t bytes; + + eeTrace("Enter socketWrite\n"); + printf("Trying to write %d bytes on sock %d\n", len, sock); +#ifdef FRAG_TEST + bytes = fragSend(sock, out, len, MSG_NOSIGNAL); +#else + bytes = send(sock, out, len, MSG_NOSIGNAL); +#endif + if (bytes == SOCKET_ERROR) { + return -1; + } + printf("send return code %d\n", (int)bytes); + eeTrace("Exit socketWrite\n"); + + return (int)bytes; +} + +/******************************************************************************/ +/* + Perform a blocking socket read +*/ +int socketRead(int sock, unsigned char *in, int available) +{ + ssize_t bytes; + + eeTrace("Enter socketRead\n"); + bytes = recv(sock, in, available, MSG_NOSIGNAL); + if (bytes == SOCKET_ERROR) { + return -1; + } + eeTrace("Exit socketRead\n"); + return (int)bytes; +} + +/******************************************************************************/ +/* + Turn on socket blocking mode (and set CLOEXEC on LINUX for kicks). +*/ +void setSocketBlock(int sock) +{ +#ifdef WIN32 + int32 block = 0; + ioctlsocket(sock, FIONBIO, &block); +#endif +#ifdef POSIX + fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) & ~O_NONBLOCK); + fcntl(sock, F_SETFD, FD_CLOEXEC); +#endif +} + +/******************************************************************************/ +/* + Turn off socket blocking mode. +*/ +void setSocketNonblock(int sock) +{ +#ifdef WIN32 + int32 block = 1; + ioctlsocket(sock, FIONBIO, &block); +#endif +#ifdef POSIX + fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK); +#endif +} + +/******************************************************************************/ +/* + Disable the Nagle algorithm for less latency in RPC + http://www.faqs.org/rfcs/rfc896.html + http://www.w3.org/Protocols/HTTP/Performance/Nagle/ +*/ +void setSocketNodelay(int sock) +{ +#ifdef WIN32 + BOOL tmp = TRUE; +#endif +#ifdef POSIX + int32 tmp = 1; +#endif /* WIN32 */ + setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&tmp, sizeof(tmp)); +} + +#endif /* USE_MATRIX_OPENSSL_LAYER */ +/******************************************************************************/ + diff --git a/matrixssl/opensslSocket.h b/matrixssl/opensslSocket.h new file mode 100644 index 0000000..eaeddbd --- /dev/null +++ b/matrixssl/opensslSocket.h @@ -0,0 +1,117 @@ +/** + * @file opensslSocket.h + * @version $Format:%h%d$ + * + * BSD socket implementation for openssl layer to MatrixSSL. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ +#ifndef _h_SSLSOCKET +#define _h_SSLSOCKET + +#ifdef __cplusplus +extern "C" { +#endif + +#include "matrixsslApi.h" + +#ifdef USE_MATRIX_OPENSSL_LAYER + +#include +#include +#include +#include + +/* + OS specific includes and macros +*/ +#ifdef WIN32 + #include + #include + #define fcntl(A, B, C) + #define MSG_NOSIGNAL 0 + #define WOULD_BLOCK WSAEWOULDBLOCK + #define getSocketError() WSAGetLastError() +#else + typedef int WSADATA; + #define WSAStartup(A, B) + #define WSACleanup() + #define getSocketError() errno +#endif + +#ifdef POSIX + #include + #include + #include + #include +#ifdef OSX + #include + #define MSG_NOSIGNAL 0 +#endif /* OSX */ +#endif /* POSIX */ + +#define SOCKET_ERROR -1 +#define WOULD_BLOCK EAGAIN + +#ifdef NEEDED + #define MAKEWORD(A, B) + #define SOCKET_ERRORCKET -1 +#endif /* old stuff */ + +/* + sslRead and sslWrite status values +*/ +#define SSLSOCKET_EOF 0x1 +#define SSLSOCKET_CLOSE_NOTIFY 0x2 + +/* + Socket apis +*/ + +extern void socketClose(int sock); +extern int socketWrite(int sock, unsigned char *out, int len); +extern int socketRead(int sock, unsigned char *in, int available); + +extern int socketListen(short port, int *err); +extern int socketAccept(int listenfd, int *err); +extern int socketConnect(char *ip, short port, int *err); +extern void socketShutdown(int sock); + +extern void setSocketBlock(int sock); +extern void setSocketNonblock(int sock); +extern void setSocketNodelay(int sock); + + +#ifdef __cplusplus +} +#endif + +#endif /* USE_MATRIX_OPENSSL_LAYER */ +#endif /* _h_SSLSOCKET */ + +/******************************************************************************/ diff --git a/matrixssl/prf.c b/matrixssl/prf.c new file mode 100644 index 0000000..c2fb31e --- /dev/null +++ b/matrixssl/prf.c @@ -0,0 +1,357 @@ +/** + * @file prf.c + * @version $Format:%h%d$ + * + * "Native" Pseudo Random Function. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "matrixsslApi.h" + +#if defined(USE_TLS_PRF) || defined(USE_TLS_PRF2) + +#ifdef USE_TLS_PRF +int32_t prf(const unsigned char *sec, uint16_t secLen, + const unsigned char *seed, uint16_t seedLen, + unsigned char *out, uint16_t outLen) +{ + return psPrf(sec, secLen, seed, seedLen, out, outLen); +} +#endif + +#ifdef USE_TLS_PRF2 +int32_t prf2(const unsigned char *sec, uint16_t secLen, + const unsigned char *seed, uint16_t seedLen, + unsigned char *out, uint16_t outLen, uint32_t flags) +{ + return psPrf2(sec, secLen, seed, seedLen, out, outLen, + (flags & CRYPTO_FLAGS_SHA3) ? + SHA384_HASH_SIZE : SHA256_HASH_SIZE); +} +#endif + +#else + +#ifdef USE_TLS +#ifndef USE_ONLY_TLS_1_2 +/******************************************************************************/ +/* + MD5 portions of the prf +*/ +__inline static int32_t pMd5(const unsigned char *key, uint16_t keyLen, + const unsigned char *text, uint16_t textLen, + unsigned char *out, uint16_t outLen) +{ + psHmacMd5_t ctx; + unsigned char a[MD5_HASH_SIZE]; + unsigned char mac[MD5_HASH_SIZE]; + unsigned char hmacKey[MD5_HASH_SIZE]; + int32_t rc = PS_FAIL; + uint16_t hmacKeyLen, i, keyIter; + + for (keyIter = 1; (uint16_t)(MD5_HASH_SIZE * keyIter) < outLen;) { + keyIter++; + } + if ((rc = psHmacMd5(key, keyLen, text, textLen, a, + hmacKey, &hmacKeyLen)) < 0) { + goto L_RETURN; + } + if (hmacKeyLen != keyLen) { +/* + Support for keys larger than 64 bytes. Must take the hash of + the original key in these cases which is indicated by different + outgoing values from the passed in key and keyLen values +*/ + psAssert(keyLen > 64); + /* Typecast is OK, we don't update key below */ + key = (const unsigned char *)hmacKey; + keyLen = hmacKeyLen; + } + for (i = 0; i < keyIter; i++) { + if ((rc = psHmacMd5Init(&ctx, key, keyLen)) < 0) { + goto L_RETURN; + } + psHmacMd5Update(&ctx, a, MD5_HASH_SIZE); + psHmacMd5Update(&ctx, text, textLen); + psHmacMd5Final(&ctx, mac); + if (i == keyIter - 1) { + memcpy(out + (MD5_HASH_SIZE*i), mac, outLen - (MD5_HASH_SIZE*i)); + } else { + memcpy(out + (MD5_HASH_SIZE * i), mac, MD5_HASH_SIZE); + if ((rc = psHmacMd5(key, keyLen, a, MD5_HASH_SIZE, a, + hmacKey, &hmacKeyLen)) < 0) { + goto L_RETURN; + } + } + } + rc = PS_SUCCESS; +L_RETURN: + memzero_s(a, MD5_HASH_SIZE); + memzero_s(mac, MD5_HASH_SIZE); + memzero_s(hmacKey, MD5_HASH_SIZE); + if (rc < 0) { + memzero_s(out, outLen); /* zero any partial result on error */ + } + return rc; +} + +/******************************************************************************/ +/* + SHA1 portion of the prf +*/ +__inline static int32_t pSha1(const unsigned char *key, uint16_t keyLen, + const unsigned char *text, uint16_t textLen, + unsigned char *out, uint16_t outLen) +{ + psHmacSha1_t ctx; + unsigned char a[SHA1_HASH_SIZE]; + unsigned char mac[SHA1_HASH_SIZE]; + unsigned char hmacKey[SHA1_HASH_SIZE]; + int32_t rc = PS_FAIL; + uint16_t hmacKeyLen, i, keyIter; + + for (keyIter = 1; (uint16_t)(SHA1_HASH_SIZE * keyIter) < outLen;) { + keyIter++; + } + if ((rc = psHmacSha1(key, keyLen, text, textLen, a, + hmacKey, &hmacKeyLen)) < 0) { + goto L_RETURN; + } + if (hmacKeyLen != keyLen) { +/* + Support for keys larger than 64 bytes. Must take the hash of + the original key in these cases which is indicated by different + outgoing values from the passed in key and keyLen values +*/ + psAssert(keyLen > 64); + /* Typecast is OK, we don't update key below */ + key = (const unsigned char *)hmacKey; + keyLen = hmacKeyLen; + } + for (i = 0; i < keyIter; i++) { + if ((rc = psHmacSha1Init(&ctx, key, keyLen)) < 0) { + goto L_RETURN; + } + psHmacSha1Update(&ctx, a, SHA1_HASH_SIZE); + psHmacSha1Update(&ctx, text, textLen); + psHmacSha1Final(&ctx, mac); + if (i == keyIter - 1) { + memcpy(out + (SHA1_HASH_SIZE * i), mac, + outLen - (SHA1_HASH_SIZE * i)); + } else { + memcpy(out + (SHA1_HASH_SIZE * i), mac, SHA1_HASH_SIZE); + if ((rc = psHmacSha1(key, keyLen, a, SHA1_HASH_SIZE, a, + hmacKey, &hmacKeyLen)) < 0) { + goto L_RETURN; + } + } + } + rc = PS_SUCCESS; +L_RETURN: + memzero_s(a, SHA1_HASH_SIZE); + memzero_s(mac, SHA1_HASH_SIZE); + memzero_s(hmacKey, SHA1_HASH_SIZE); + if (rc < 0) { + memzero_s(out, outLen); /* zero any partial result on error */ + } + return rc; +} + +/******************************************************************************/ +/* + Psuedo-random function. TLS uses this for key generation and hashing +*/ +int32_t prf(const unsigned char *sec, uint16_t secLen, + const unsigned char *seed, uint16_t seedLen, + unsigned char *out, uint16_t outLen) +{ + const unsigned char *s1, *s2; + unsigned char md5out[SSL_MAX_KEY_BLOCK_SIZE]; + unsigned char sha1out[SSL_MAX_KEY_BLOCK_SIZE]; + int32_t rc = PS_FAIL; + uint16_t sLen, i; + + psAssert(outLen <= SSL_MAX_KEY_BLOCK_SIZE); + + sLen = (secLen / 2) + (secLen % 2); + s1 = sec; + s2 = (sec + sLen) - (secLen % 2); + if ((rc = pMd5(s1, sLen, seed, seedLen, md5out, outLen)) < 0) { + goto L_RETURN; + } + if ((rc = pSha1(s2, sLen, seed, seedLen, sha1out, outLen)) < 0) { + goto L_RETURN; + } + for (i = 0; i < outLen; i++) { + out[i] = md5out[i] ^ sha1out[i]; + } + rc = outLen; +L_RETURN: + memzero_s(md5out, SSL_MAX_KEY_BLOCK_SIZE); + memzero_s(sha1out, SSL_MAX_KEY_BLOCK_SIZE); + return rc; +} + +#endif /* !USE_ONLY_TLS_1_2 */ + +#ifdef USE_TLS_1_2 +/******************************************************************************/ +/* + SHA2 prf +*/ +__inline static int32_t pSha2(const unsigned char *key, uint16_t keyLen, + const unsigned char *text, uint16_t textLen, + unsigned char *out, uint16_t outLen, uint32_t flags) +{ + /* Use a union to save a bit of stack space */ + union { +#ifdef USE_SHA384 + psHmacSha384_t sha384; +#endif + psHmacSha256_t sha256; + } u; + unsigned char a[SHA384_HASH_SIZE]; + unsigned char mac[SHA384_HASH_SIZE]; + unsigned char hmacKey[SHA384_HASH_SIZE]; + int32_t rc = PS_FAIL; + uint16_t hashSize, hmacKeyLen, i, keyIter; + +#ifdef USE_SHA384 + if (flags & CRYPTO_FLAGS_SHA3) { + hashSize = SHA384_HASH_SIZE; + if ((rc = psHmacSha384(key, keyLen, text, textLen, a, + hmacKey, &hmacKeyLen)) < 0) { + goto L_RETURN; + } + } else +#endif + { + + hashSize = SHA256_HASH_SIZE; + if ((rc = psHmacSha256(key, keyLen, text, textLen, a, + hmacKey, &hmacKeyLen)) < 0) { + goto L_RETURN; + } + } + for (keyIter = 1; (uint16_t)(hashSize * keyIter) < outLen;) { + keyIter++; + } + if (hmacKeyLen != keyLen) { +/* + Support for keys larger than 64 bytes. Must take the hash of + the original key in these cases which is indicated by different + outgoing values from the passed in key and keyLen values +*/ + psAssert(keyLen > 64); + /* Typecast is OK, we don't update key below */ + key = (const unsigned char *)hmacKey; + keyLen = hmacKeyLen; + } + for (i = 0; i < keyIter; i++) { +#ifdef USE_SHA384 + if (flags & CRYPTO_FLAGS_SHA3) { + if ((rc = psHmacSha384Init(&u.sha384, key, keyLen)) < 0) { + goto L_RETURN; + } + psHmacSha384Update(&u.sha384, a, hashSize); + psHmacSha384Update(&u.sha384, text, textLen); + psHmacSha384Final(&u.sha384, mac); + } else +#endif + { + if ((rc = psHmacSha256Init(&u.sha256, key, keyLen)) < 0) { + goto L_RETURN; + } + psHmacSha256Update(&u.sha256, a, hashSize); + psHmacSha256Update(&u.sha256, text, textLen); + psHmacSha256Final(&u.sha256, mac); + } + if (i == keyIter - 1) { + memcpy(out + (hashSize * i), mac, + outLen - (hashSize * i)); + } else { + memcpy(out + (hashSize * i), mac, hashSize); +#ifdef USE_SHA384 + if (flags & CRYPTO_FLAGS_SHA3) { + if ((rc = psHmacSha384(key, keyLen, a, hashSize, a, + hmacKey, &hmacKeyLen)) < 0) { + goto L_RETURN; + } + } else +#endif + { + if ((rc = psHmacSha256(key, keyLen, a, hashSize, a, + hmacKey, &hmacKeyLen)) < 0) { + goto L_RETURN; + } + } + } + } + rc = PS_SUCCESS; +L_RETURN: + memzero_s(a, SHA384_HASH_SIZE); + memzero_s(mac, SHA384_HASH_SIZE); + memzero_s(hmacKey, SHA384_HASH_SIZE); + if (rc < 0) { + memzero_s(out, outLen); /* zero any partial result on error */ + } + return rc; +} + +/******************************************************************************/ +/* + Psuedo-random function. TLS uses this for key generation and hashing +*/ +int32_t prf2(const unsigned char *sec, uint16_t secLen, + const unsigned char *seed, uint16_t seedLen, + unsigned char *out, uint16_t outLen, uint32_t flags) +{ + unsigned char sha2out[SSL_MAX_KEY_BLOCK_SIZE]; + int32_t rc; + uint16_t i; + + psAssert(outLen <= SSL_MAX_KEY_BLOCK_SIZE); + + if ((rc = pSha2(sec, secLen, seed, seedLen, sha2out, outLen, flags)) < 0) { + return rc; + } + /* Copy out of tmp buffer because outLen typically less than multiple of + prf block size */ + for (i = 0; i < outLen; i++) { + out[i] = sha2out[i]; + } + memzero_s(sha2out, SSL_MAX_KEY_BLOCK_SIZE); + return outLen; +} +#endif /* USE_TLS_1_2 */ + +#endif /* USE_TLS */ +#endif /* USE_TLS_PRF || USE_TLS_PRF2 */ +/******************************************************************************/ + diff --git a/matrixssl/psk.c b/matrixssl/psk.c new file mode 100644 index 0000000..d6a2580 --- /dev/null +++ b/matrixssl/psk.c @@ -0,0 +1,191 @@ +/** + * @file psk.c + * @version $Format:%h%d$ + * + * Pre-Shared Key cipher suite support. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "matrixsslApi.h" + +#ifdef USE_PSK_CIPHER_SUITE + +/******************************************************************************/ +/* + Add a pre-shared key and ID to the static table in the first NULL spot +*/ +int32_t matrixSslLoadPsk(sslKeys_t *keys, + const unsigned char key[SSL_PSK_MAX_KEY_SIZE], uint8_t keyLen, + const unsigned char id[SSL_PSK_MAX_ID_SIZE], uint8_t idLen) +{ + psPsk_t *psk, *list; + + if (keys == NULL || key == NULL || id == NULL) { + return PS_ARG_FAIL; + } + if (keyLen > SSL_PSK_MAX_KEY_SIZE) { + psTraceIntInfo("Can't add PSK. Key too large: %d\n", keyLen); + return PS_ARG_FAIL; + } + + if (idLen > SSL_PSK_MAX_ID_SIZE) { + psTraceIntInfo("Can't add PSK. Key ID too large: %d\n", idLen); + return PS_ARG_FAIL; + } + + if (keyLen < 1 || idLen < 1) { + psTraceInfo("Can't add PSK. Both key and identity length must be >0\n"); + return PS_ARG_FAIL; + } + + if ((psk = psMalloc(keys->pool, sizeof(psPsk_t))) == NULL) { + return PS_MEM_FAIL; + } + memset(psk, 0, sizeof(psPsk_t)); + + if ((psk->pskKey = psMalloc(keys->pool, keyLen)) == NULL) { + psFree(psk, keys->pool); + return PS_MEM_FAIL; + } + if ((psk->pskId = psMalloc(keys->pool, idLen)) == NULL) { + psFree(psk->pskKey, keys->pool); + psFree(psk, keys->pool); + return PS_MEM_FAIL; + } + memcpy(psk->pskKey, key, keyLen); + psk->pskLen = keyLen; + + memcpy(psk->pskId, id, idLen); + psk->pskIdLen = idLen; + + if (keys->pskKeys == NULL) { + keys->pskKeys = psk; + } else { + list = keys->pskKeys; + while (list->next != NULL) { + list = list->next; + } + list->next = psk; + } + + return 0; +} + + +/******************************************************************************/ +/* + The ServerKeyExchange message passes an optional 'hint' to the client about + which PSK it might want to use. +*/ +int32_t matrixPskGetHint(ssl_t *ssl, + unsigned char *hint[SSL_PSK_MAX_HINT_SIZE], uint8_t *hintLen) +{ +/* + RFC4279: In the absence of an application profile specification specifying + otherwise, servers SHOULD NOT provide an identity hint and clients + MUST ignore the identity hint field. Applications that do use this + field MUST specify its contents, how the value is chosen by the TLS + server, and what the TLS client is expected to do with the value. + + NOTE: If you are adding support for a hint, make sure to also modify the + SSL_PSK_MAX_HINT_SIZE define in matrixInternal.h so that messsageSize + checks will work inside sslEncode.c +*/ + *hint = NULL; + *hintLen = 0; + return 0; +} + +/******************************************************************************/ +/* + Get the id from the pre-shared key table based on given SSL session + hint and hintLen are not currently used for the lookup +*/ +int32_t matrixSslPskGetKeyId(ssl_t *ssl, + unsigned char *id[SSL_PSK_MAX_ID_SIZE], uint8_t *idLen, + const unsigned char hint[SSL_PSK_MAX_HINT_SIZE], uint8_t hintLen) +{ + psPsk_t *psk; + + psk = ssl->keys->pskKeys; + + if (psk == NULL) { + psTraceInfo("No pre-shared keys loaded\n"); + return PS_FAILURE; + } + + *id = psk->pskId; + *idLen = psk->pskIdLen; + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Get the key from the pre-shared list based on id +*/ +int32_t matrixSslPskGetKey(ssl_t *ssl, + const unsigned char id[SSL_PSK_MAX_ID_SIZE], uint8_t idLen, + unsigned char *key[SSL_PSK_MAX_KEY_SIZE], uint8_t *keyLen) +{ + psPsk_t *psk; + + *key = NULL; + + psk = ssl->keys->pskKeys; + + if (psk == NULL) { + psTraceInfo("No pre-shared keys loaded\n"); + return PS_FAILURE; + } + + if (idLen <= 0) { + psTraceIntInfo("Bad PSK identity length: %d\n", idLen); + return PS_ARG_FAIL; + } + +/* + Make sure the length matches as well +*/ + while (psk) { + if (psk->pskIdLen == idLen) { + if (memcmp(psk->pskId, id, idLen) == 0) { + *key = psk->pskKey; + *keyLen = psk->pskLen; + return PS_SUCCESS; + } + } + psk = psk->next; + } + + psTraceInfo("Can't find PSK key from id\n"); + return PS_SUCCESS; +} +#endif /* USE_PSK_CIPHER_SUITE */ + +/******************************************************************************/ diff --git a/matrixssl/sslDecode.c b/matrixssl/sslDecode.c new file mode 100644 index 0000000..37c345a --- /dev/null +++ b/matrixssl/sslDecode.c @@ -0,0 +1,2462 @@ +/** + * @file sslDecode.c + * @version $Format:%h%d$ + * + * Secure Sockets Layer protocol message decoding portion of MatrixSSL. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "matrixsslApi.h" + +/******************************************************************************/ + + #define LUCKY13 + +#define SSL_MAX_IGNORED_MESSAGE_COUNT 1024 + +static int32 parseSSLHandshake(ssl_t *ssl, char *inbuf, uint32 len); + +#ifdef USE_CERT_CHAIN_PARSING +static int32 parseSingleCert(ssl_t *ssl, unsigned char *c, unsigned char *end, + int32 certLen); +#endif /* USE_CERT_CHAIN_PARSING */ + +#ifdef LUCKY13 +static int32 addCompressCount(ssl_t *ssl, int32 padLen); +#endif + +#ifdef USE_ZLIB_COMPRESSION +/* Does not need to be a large value because we're only inflating the 16 + byte FINISHED message. In fact, compression will grow 16 bytes but + this is a good reminder that FUTURE support will need to account for + likely data growth here */ +#define MATRIX_INFLATE_FINISHED_OH 128 +#endif + +/******************************************************************************/ +/* + Parse incoming data per http://wp.netscape.com/eng/ssl3 + + Input parameters to decode: + . buf points to the start of data to decode + . len points to the length in bytes of data to decode + . size is the number of allocated bytes that follow buf + + + + Meaningful parameters after the call to decode: + MATRIXSSL_SUCCESS + . buf will point to the first undecoded byte (could==inbuf or inbuf+inlen) + . remaining will indicate how many more bytes of undecoded data remain + * call again if more to decode or return if handshake is complete + + SSL_PARTIAL + . buf will not have moved (because partials start parse over) + . reqLen will indicate how many bytes the entire full record is + * get more data from peer and call again + + SSL_FULL (implies decode completed fully but couldn't fit response) + . buf will not have moved (it is reset to the front of final record) + . len will be 0 to indicate no remaining unprocessed data + . reqLen will inform how large buf should be grown before re-invoking + * realloc the buf to the reqLen size and call again + + SSL_SEND_RESPONSE + . buf will point to the encoded handshake data to send + . len will be length of data to send (from start offset) + * pass the buf to the transport layer for sending to peer + + SSL_ALERT + . buf will point to start of received alert (2 bytes alert level and desc) + . len will be length of alert data (should be 2) + . alertLevel will be 1 (warning) or 2 (fatal) + . alertDesc will be SSL specified alert code + + MATRIXSSL_ERROR (unrecoverable failure) + . decodeErr is internal parse err code + + SSL_PROCESS_DATA (ONLY CASE WITH DECRYPTED DATA AND POSSIBLE UNENCRYPTED) + . unencrypted user data ready for processing is at prevBuf + . buf points to start of any remaining unencrypted data + . remaining is length of remaining encrypted data yet to decode + . len is length of unencrypted data ready for user processing + * pass unencypted data to application level + * call decode again if more encrypted data remaining + +*/ +int32 matrixSslDecode(ssl_t *ssl, unsigned char **buf, uint32 *len, + uint32 size, uint32 *remaining, uint32 *requiredLen, + int32 *error, unsigned char *alertLevel, + unsigned char *alertDescription) +{ + unsigned char *c, *p, *end, *pend, *ctStart, *origbuf; + unsigned char *mac, macError; + int32 rc; + unsigned char padLen; +#ifdef USE_CLIENT_SIDE_SSL + sslSessOpts_t options; +#endif + psBuf_t tmpout; +#ifdef USE_CERT_CHAIN_PARSING + int32 certlen, i, nextCertLen; +#endif /* USE_CERT_CHAIN_PARSING */ +#ifdef USE_ZLIB_COMPRESSION + int32 preInflateLen, postInflateLen, currLen; + int zret; +#endif +/* + If we've had a protocol error, don't allow further use of the session +*/ + *error = PS_SUCCESS; + if (ssl->flags & SSL_FLAGS_ERROR || ssl->flags & SSL_FLAGS_CLOSED) { + psTraceInfo("Can't use matrixSslDecode on closed/error-flagged sess\n"); + *error = PS_PROTOCOL_FAIL; + return MATRIXSSL_ERROR; + } + + origbuf = *buf; /* Save the original buffer location */ + + p = pend = mac = ctStart = NULL; + padLen = 0; + + +/* + This flag is set if the previous call to this routine returned an SSL_FULL + error from encodeResponse, indicating that there is data to be encoded, + but the out buffer was not big enough to handle it. If we fall in this + case, the user has increased the out buffer size and is re-calling this + routine +*/ + if (ssl->flags & SSL_FLAGS_NEED_ENCODE) { + ssl->flags &= ~SSL_FLAGS_NEED_ENCODE; + goto encodeResponse; + } + *requiredLen = 0; + c = *buf; /* c is record parse pointer */ + end = *buf + *len; + +/* + Processing the SSL Record header. + If the high bit of the first byte is set and this is the first + message we've seen, we parse the request as an SSLv2 request + @see http://wp.netscape.com/eng/security/SSL_2.html + SSLv2 also supports a 3 byte header when padding is used, but this should + not be required for the initial plaintext message, so we don't support it. + + @security SSLV2 ClientHello is deprecated and no longer supported. + + v2 Header: + 2 bytes length (ignore high bit) + v3 Header: + 1 byte type + 1 byte major version + 1 byte minor version + 2 bytes length +*/ +#ifdef USE_DTLS +decodeMore: +#endif + if (end - c == 0) { +/* + This case could happen if change cipher spec was last + message in the buffer or if there is a zero-length record + at the end of a multi-record application data buffer. +*/ + return MATRIXSSL_SUCCESS; + } + /* Even for SSLv2, we want at least 5 bytes in the record to continue */ + if (end - c < SSL3_HEADER_LEN) { + *requiredLen = SSL3_HEADER_LEN; + return SSL_PARTIAL; + } +#ifdef USE_CERT_CHAIN_PARSING +/* + If we're in process of parsing a partial record, then skip the + usual record header parse. Currently we're only supporting + partial parsing for the certificate messages since they are the + largest in size. +*/ + if (ssl->rec.partial != 0x0) { + psAssert(ssl->rec.type == SSL_RECORD_TYPE_HANDSHAKE); + psAssert(ssl->hsState == SSL_HS_CERTIFICATE); +/* + Get this next record length based on the certificate size, + which will always be the first three bytes of a partial here +*/ + ssl->rec.len = c[0] << 16; + ssl->rec.len |= c[1] << 8; + ssl->rec.len |= c[2]; + ssl->rec.len += 3; + goto SKIP_RECORD_PARSE; + } +#endif /* USE_CERT_CHAIN_PARSING */ + + if (ssl->majVer != 0 || (*c & 0x80) == 0) { + if (end - c < ssl->recordHeadLen) { + *requiredLen = ssl->recordHeadLen; + return SSL_PARTIAL; + } + ssl->rec.type = *c; c++; + ssl->rec.majVer = *c; c++; + ssl->rec.minVer = *c; c++; +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (ssl->rec.majVer == DTLS_MAJ_VER && + ssl->rec.minVer >= DTLS_1_2_MIN_VER) { + ssl->rec.epoch[0] = *c++; + ssl->rec.epoch[1] = *c++; + ssl->rec.rsn[0] = *c++; + ssl->rec.rsn[1] = *c++; + ssl->rec.rsn[2] = *c++; + ssl->rec.rsn[3] = *c++; + ssl->rec.rsn[4] = *c++; + ssl->rec.rsn[5] = *c++; + } else { + psTraceIntDtls("Expecting DTLS record version. Got %d\n", + ssl->rec.majVer); + *error = PS_PROTOCOL_FAIL; + return MATRIXSSL_ERROR; + } + } +#endif /* USE_DTLS */ + ssl->rec.len = *c << 8; c++; + ssl->rec.len += *c; c++; + } else { + /* OpenSSL 0.9.8 will send a SSLv2 CLIENT_HELLO. Use the -no_ssl2 + option when running a 0.9.8 client to prevent this */ + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("SSLv2 records not supported\n"); + goto encodeResponse; + } +/* + Validate the various record headers. The type must be valid, + the major and minor versions must match the negotiated versions (if we're + past ClientHello) and the length must be < 16K and > 0 +*/ + switch (ssl->rec.type) { + case SSL_RECORD_TYPE_CHANGE_CIPHER_SPEC: + case SSL_RECORD_TYPE_ALERT: + case SSL_RECORD_TYPE_HANDSHAKE: + case SSL_RECORD_TYPE_APPLICATION_DATA: + break; + /* Any other case is unrecognized */ + default: + ssl->err = SSL_ALERT_UNEXPECTED_MESSAGE; + psTraceIntInfo("Record header type not valid: %d\n", ssl->rec.type); + goto encodeResponse; + } + +/* + Verify the record version numbers unless this is the first record we're + reading. +*/ + if (ssl->hsState != SSL_HS_SERVER_HELLO && + ssl->hsState != SSL_HS_CLIENT_HELLO) { + if (ssl->rec.majVer != ssl->majVer || ssl->rec.minVer != ssl->minVer) { +#ifdef SSL_REHANDSHAKES_ENABLED + /* If in DONE state and this version doesn't match the previously + negotiated one that can be OK because a CLIENT_HELLO for a + rehandshake might be acting like a first time send and using + a lower version to get to the parsing phase. Unsupported + versions will be weeded out at CLIENT_HELLO parse time */ + if (ssl->hsState != SSL_HS_DONE || + ssl->rec.type != SSL_RECORD_TYPE_HANDSHAKE) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Record header version not valid\n"); + goto encodeResponse; + } +#else + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Record header version not valid\n"); + goto encodeResponse; +#endif + } + } +/* + Verify max and min record lengths +*/ + if (ssl->rec.len > SSL_MAX_RECORD_LEN || ssl->rec.len == 0) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceIntInfo("Record header length not valid: %d\n", ssl->rec.len); + goto encodeResponse; + } +/* + This implementation requires the entire SSL record to be in the 'in' buffer + before we parse it. This is because we need to MAC the entire record before + allowing it to be used by the caller. +*/ +#ifdef USE_CERT_CHAIN_PARSING +SKIP_RECORD_PARSE: + if ((end - c < ssl->rec.len) || ssl->rec.partial) { +/* + This feature will only work if the CERTIFICATE message is sent in a + different record from the SERVER_HELLO message. +*/ + if (ssl->hsState != SSL_HS_CERTIFICATE) { + ssl->rec.partial = 0x0; + *requiredLen = ssl->rec.len + ssl->recordHeadLen; + return SSL_PARTIAL; + } +/* + Not supporting cert stream parsing for re-handshake. This is + important because the block cipher assumes a single pass is a record + and will use explicit IV each pass +*/ + if (ssl->flags & SSL_FLAGS_READ_SECURE) { + ssl->rec.partial = 0x0; + *requiredLen = ssl->rec.len + ssl->recordHeadLen; + return SSL_PARTIAL; + } +/* + Manipulate the rec.len for partial handling +*/ + i = 0; + if (ssl->rec.partial == 0x0) { +/* + Initialization for partial parse counters +*/ + ssl->rec.hsBytesHashed = 0; + ssl->rec.hsBytesParsed = 0; + ssl->rec.partial = 0x1; + ssl->rec.trueLen = ssl->rec.len + ssl->recordHeadLen; + ssl->rec.len = 0; +/* + Best to identify and isolate full certificate boundaries + ASAP to keep parsing logic as high level as possible. + + Current state of record buffer: pointer at start of HS record + which begins with 4 bytes of hsType(1) and hsLen(3). After + the header are 3 bytes of certchainlen and 3 bytes of first + cert len. Make sure we have at least one full cert here before + allowing the partial parse. +*/ + if (end - c < (ssl->hshakeHeadLen + 6)) { /* 3*2 cert chain len */ + ssl->rec.partial = 0x0; /* Unusable. Reset */ + *requiredLen = ssl->hshakeHeadLen + 6; + return SSL_PARTIAL; + } + ssl->rec.len += (ssl->hshakeHeadLen + 3); + i = ssl->hshakeHeadLen; + certlen = c[i] << 16; i++; + certlen |= c[i] << 8; i++; + certlen |= c[i]; i++; +/* + This feature only works if the CERTIFICATE message is the only + message in the record. Test this by seeing that trueLen doesn't + claim there is more to follow +*/ + if (ssl->rec.trueLen != (certlen + 3 + ssl->hshakeHeadLen + + ssl->recordHeadLen)) { + ssl->rec.partial = 0x0; /* Unusable. Reset */ + *requiredLen = ssl->rec.trueLen; + return SSL_PARTIAL; + } + /* First cert length */ + ssl->rec.len += 3; + certlen = c[i] << 16; i++; + certlen |= c[i] << 8; i++; + certlen |= c[i]; + ssl->rec.len += certlen; + } + + /* One complete cert? */ + if (end - c < ssl->rec.len) { +/* + If there isn't a full cert in the first partial, we reset and + handle as the standard SSL_PARTIAL case. +*/ + if (ssl->rec.hsBytesParsed == 0) { + ssl->rec.partial = 0x0; /* Unusable. Reset */ + *requiredLen = ssl->rec.len + ssl->recordHeadLen; + } else { + /* Record header has already been parsed */ + *requiredLen = ssl->rec.len; + } + return SSL_PARTIAL; /* Standard partial case */ + } + + /* More than one complete cert? */ + while (end - c > ssl->rec.len) + { + if (ssl->rec.len + ssl->rec.hsBytesParsed == ssl->rec.trueLen) { +/* + Don't try to read another cert if the total of already parsed + record and the length of the current record match the 'trueLen'. + If they are equal, we know we are on the final cert and don't + need to look for more +*/ + break; + } + psAssert(ssl->rec.len + ssl->rec.hsBytesParsed <= ssl->rec.trueLen); + nextCertLen = c[ssl->rec.len] << 16; + nextCertLen |= c[ssl->rec.len + 1] << 8; + nextCertLen |= c[ssl->rec.len + 2]; + if (end - c > (ssl->rec.len + nextCertLen + 3)) { + ssl->rec.len += (nextCertLen + 3); + } else { + break; + } + } + } +#else + if (end - c < ssl->rec.len) { +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + psTraceInfo("DTLS error: Received PARTIAL record from peer.\n"); + psTraceInfo("This indicates a PMTU mismatch\n"); + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + goto encodeResponse; + } +#endif /* USE_DTLS */ + *requiredLen = ssl->rec.len + ssl->recordHeadLen; + return SSL_PARTIAL; + + } +#endif + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + + /* Epoch and RSN validation. Silently ignore most mismatches (SUCCESS) */ + rc = dtlsCompareEpoch(ssl->rec.epoch, ssl->expectedEpoch); + /* These cases have become pretty complex due to a code change in which + the epoch is always incremented when CCS is sent. We used to + reset the FINISHED epoch back to +1 of the current epoch when + resending the FINISHED flight but a customer had a problem with this + because they thought every single message must be unique for epoch + and sequence number. They were probably correct but now it's a + real mess trying to keep the expectedEpoch up-to-date when we can't + possibly know how many epoch increments the peer has made before we + receive a FINISHED message or an APPLICATION DATA record */ + if (rc == 1 && ssl->rec.type == SSL_RECORD_TYPE_HANDSHAKE && + ssl->hsState == SSL_HS_FINISHED) { + /* Special handlers for these CCS/Finished cases because epoch + could be larger for a good reason */ + + /* This is the case where we are getting a finished without having + seen a CCS. Preumably they will be trying again since this is + an indication that they are aware they are the senders */ + if (ssl->parsedCCS == 0) { + c += ssl->rec.len; + *buf = c; + return MATRIXSSL_SUCCESS; + } + + /* This is the case where we didn't receive a combo CCS/FINISHED + flight from the peer and they have resent with a larger epoch + for the resent FINISHED message (so as not to send a epoch/seqNo + duplicate on this resend). Make the expected epoch the new one + to reset the test for any future rehandshakes */ + ssl->expectedEpoch[0] = ssl->rec.epoch[0]; + ssl->expectedEpoch[1] = ssl->rec.epoch[1]; + } else if (rc != 0) { + psTraceIntDtls("Epoch mismatch %d ", ssl->rec.epoch[1]); + psTraceIntDtls("on a record type of %d\n", ssl->rec.type); + + /* Another corner case where the peer has sent repeat FINISHED + messages when we are in the state where we are finished. + Need to keep the expectedEpoch up-to-date then because when + the peer finally gets around to sending application data it + will be sending it on the last epoch it sent for the final + FINISHED. */ + if (rc == 1 && ssl->rec.type == SSL_RECORD_TYPE_HANDSHAKE && + ssl->hsState == SSL_HS_DONE) { + ssl->expectedEpoch[0] = ssl->rec.epoch[0]; + ssl->expectedEpoch[1] = ssl->rec.epoch[1]; + } + + /* Yet another corner case where we are receiving application data + that has an epoch larger than we were expecting. This could + happen if the peer has been sending "duplicate" FINISHED + messages in which we have already parsed an earlier one and we + are in the done state. If we didn't receive those duplicate + FINISHED messages and are now getting an APPLICATION record, + let's just try to decrypt it and get this communication going */ + if (rc == 1 && ssl->rec.type == SSL_RECORD_TYPE_APPLICATION_DATA && + ssl->hsState == SSL_HS_DONE) { + ssl->expectedEpoch[0] = ssl->rec.epoch[0]; + ssl->expectedEpoch[1] = ssl->rec.epoch[1]; + goto ADVANCE_TO_APP_DATA; + } + + /* Now just skip the record as a duplicate */ + + c += ssl->rec.len; + *buf = c; + /* If this is a ChangeCipherSpec message from the peer + and we have never received encypted application data this is + probably the 'endgame' problem in which the peer never received + our final handshake flight. Trigger a resend in this specific + case */ + if ((ssl->rec.type == SSL_RECORD_TYPE_CHANGE_CIPHER_SPEC) && + (ssl->appDataExch == 0)) { + /* Need to make sure we mark the rest of this buffer as read. + The CCS message can be passed in here with the FINISHED tacked + on. OpenSSL sends them separately but most wouldn't */ + if (end != c) { + psAssert(*c == SSL_RECORD_TYPE_HANDSHAKE); /* Finished */ + c += 11; /* Skip type, version, epoch to get to length */ + /* borrow rc since we will be leaving here anyway */ + rc = *c << 8; c++; + rc += *c; c++; + c += rc; /* Skip FINISHED message we've already accepted */ + *buf = c; + } + return DTLS_RETRANSMIT; + } + if (end - c > 0) { + goto decodeMore; + } + + /* Next, check if this is a record on a session that the server + has already closed. Server timed out this client completely and then + the client decides to send a new encoded client hello or app data + on an epoch that it thinks is fine. If we are getting an epoch + greater than ours and we don't even have a state for this client, + an error should be returned so the ssl session can be deleted */ + if (rc == 1 && ssl->flags & SSL_FLAGS_SERVER && + ssl->hsState == SSL_HS_CLIENT_HELLO) { + *buf = origbuf; + ssl->err = SSL_ALERT_UNEXPECTED_MESSAGE; + psTraceDtls("Client sending record on closed session\n"); + goto encodeResponse; + } + + /* If getting epoch that is less than expected, we'll resend */ + if (rc == -1) { + return DTLS_RETRANSMIT; + } + /* Got FINISHED message without ever getting a change cipher spec */ + return MATRIXSSL_SUCCESS; + } + + if (dtlsChkReplayWindow(ssl, ssl->rec.rsn) != 1) { + psTraceIntDtls("Seen this record before %d\n", ssl->rec.rsn[5]); + c += ssl->rec.len; + *buf = c; + if (end - c > 0) { + goto decodeMore; + } + return MATRIXSSL_SUCCESS; + } + } +ADVANCE_TO_APP_DATA: +#endif /* USE_DTLS */ + +#ifdef USE_MATRIXSSL_STATS + if (ssl->rec.type == SSL_RECORD_TYPE_APPLICATION_DATA) { + matrixsslUpdateStat(ssl, APP_DATA_RECV_STAT, ssl->rec.len + + ssl->recordHeadLen); + } +#endif + +/* + Decrypt the entire record contents. The record length should be + a multiple of block size, or decrypt will return an error + If we're still handshaking and sending plaintext, the decryption + callback will point to a null provider that passes the data unchanged +*/ + + ctStart = origbuf; /* Clear-text start. Decrypt to the front */ + + /* Sanity check ct len. Step 1 of Lucky 13 MEE-TLS-CBC decryption. + max{b, t + 1} is always "t + 1" because largest possible blocksize + is 16 and smallest possible tag len is 16. Multiple of block size test + is done in decrypt */ + if ((ssl->flags & SSL_FLAGS_READ_SECURE) && (ssl->deBlockSize > 1) && + !(ssl->flags & SSL_FLAGS_AEAD_R)) { +#ifdef USE_TLS_1_1 + if (ssl->flags & SSL_FLAGS_TLS_1_1) { + if (ssl->rec.len < (ssl->deMacSize + 1 + ssl->deBlockSize)) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Ciphertext length failed sanity\n"); + goto encodeResponse; + } + } else { + if (ssl->rec.len < (ssl->deMacSize + 1)) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Ciphertext length failed sanity\n"); + goto encodeResponse; + } + } +#else + if (ssl->rec.len < (ssl->deMacSize + 1)) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Ciphertext length failed sanity\n"); + goto encodeResponse; + } +#endif /* USE_TLS_1_1 */ + } + + /* CT to PT */ + if (ssl->decrypt(ssl, c, ctStart, ssl->rec.len) < 0) { + ssl->err = SSL_ALERT_DECRYPT_ERROR; + psTraceInfo("Couldn't decrypt record data 2\n"); + goto encodeResponse; + } + + c += ssl->rec.len; + + if (ssl->flags & SSL_FLAGS_AEAD_R) { + /* AEAD needs a bit of manual length manipulation for buffer mgmnt */ + ssl->rec.len -= AEAD_TAG_LEN(ssl); + if (ssl->flags & SSL_FLAGS_NONCE_R) { + ssl->rec.len -= TLS_EXPLICIT_NONCE_LEN; + } + } +/* + If we're reading a secure message, we need to validate the MAC and + padding (if using a block cipher). Insecure messages do not have + a trailing MAC or any padding. + + SECURITY - There are several vulnerabilities in block cipher padding + that we handle in the below code. For more information see: + http://www.openssl.org/~bodo/tls-cbc.txt +*/ + if (ssl->flags & SSL_FLAGS_READ_SECURE && !(ssl->flags & SSL_FLAGS_AEAD_R)){ +/* + Start tracking MAC errors, rather then immediately catching them to + stop timing and alert description attacks that differentiate between + a padding error and a MAC error. +*/ + macError = 0; +/* + Decode padding only if blocksize is > 0 (we're using a block cipher), + otherwise no padding will be present, and the mac is the last + macSize bytes of the record. +*/ + if (ssl->deBlockSize <= 1) { + mac = ctStart + ssl->rec.len - ssl->deMacSize; + } else { +/* + The goal from here through completion of ssl->verifyMac call is a + constant processing time for a given record length. Going to + follow the suggestions of the Lucky 13 research paper section + "Careful implementation of MEE-TLS-CBC decryption". + http://www.isg.rhul.ac.uk/tls/TLStiming.pdf + + Consistent timing is still a "goal" here. This implementation + accounts for the largest timing discrepencies but is not a + strict "clock cycles" equalizer. The complexity of the attack + circumstances and plaintext recovery possibilities using these + techniques is almost entirely in the academic realm. Improvements + to this code will be an ongoing process as research uncovers + more practical plaintext recovery threats. + + Verify the pad data for block ciphers + c points within the cipher text, p points within the plaintext + The last byte of the record is the pad length +*/ + p = ctStart + ssl->rec.len; + padLen = *(p - 1); +/* + SSL3.0 requires the pad length to be less than blockSize + TLS can have a pad length up to 255 for obfuscating the data len +*/ + if (ssl->majVer == SSL3_MAJ_VER && ssl->minVer == SSL3_MIN_VER && + padLen >= ssl->deBlockSize) { + macError = 1; + } +/* + The minimum record length is the size of the mac, plus pad bytes + plus one length byte, plus explicit IV if TLS 1.1 or above +*/ + if (ssl->flags & SSL_FLAGS_TLS_1_1) { + if (ssl->rec.len < ssl->deMacSize + padLen + 1 + ssl->deBlockSize) { + macError = 2; + } + } else { + if (ssl->rec.len < ssl->deMacSize + padLen + 1) { + macError = 3; + } + } + if (macError) { + /* Step 3 of Lucky 13 MEE-TLS-CBC decryption: Run a loop as + if there were 256 bytes of padding, with a dummy check + in each iteration*/ + for (rc = 255; rc >= 0; rc--) { + /* make the test a moving target so it doesn't get + optimized out at compile. The loop is written + this way so the macError assignment will be done + only once */ + if ((unsigned char)rc == padLen) { + macError = 1; /* No incr to avoid any wraps */ + } + } + } +#ifdef USE_TLS +/* + TLS specifies that all pad bytes must have the same value + as the final pad length byte. Some SSL3 implementations also + do this by convention, but some just fill with random bytes. + (We're just overloading the 'mac' ptr here, this has nothing to + do with real MAC.) +*/ + if (!macError && ssl->majVer == TLS_MAJ_VER && + ssl->minVer >= TLS_MIN_VER) { + for (mac = p - padLen - 1; mac < p; mac++) { + if (*mac != padLen) { + macError = 1; + } + } + /* Lucky 13 step 4. If this fails, then run a loop as if there + were 256 - padlen - 1 bytes of padding, with a dummy + check in each iteration */ + if (macError) { + for (rc = 256 - padLen - 1; rc > 0; rc--) { + /* make the test a moving target so it doesn't get + optimized out at compile. Again, make it so + the loop condition doesn't get hit more than + once. */ + if ((unsigned char)rc == padLen) { + macError = 2; /* change value for smart compilers */ + } + } + } + } +#endif /* USE_TLS */ +/* + The mac starts macSize bytes before the padding and length byte. + If we have a macError, just fake the mac as the last macSize bytes + of the record, so we are sure to have enough bytes to verify + against, we'll fail anyway, so the actual contents don't matter. +*/ + if (!macError) { + /* No padding errors */ + mac = p - padLen - 1 - ssl->deMacSize; + /* Lucky 13 step 5: Otherwise (the padding is now correctly + formatted) run a loop as if there were 256 - padlen - 1 + bytes of padding, doing a dummy check in each iteration */ + for (rc = (256 - padLen) - 1; rc > 0; rc--) { + /* make this test look like the others */ + if ((unsigned char)rc == padLen) { + macError = 1; /* not really an error. reset below */ + } + } + macError = 0; + } else { + /* Lucky 13 step 3 and 4 condition: Then let P' denote the first + plen - t bytes of P, compute a MAC on SQN||HDR||P' and do a + constant-time comparison of the computed MAC with the + last t bytes of P. Return fatal error. */ + mac = origbuf + ssl->rec.len - ssl->deMacSize; + } + } +/* + Verify the MAC of the message by calculating our own MAC of the message + and comparing it to the one in the message. We do this step regardless + of whether or not we've already set macError to stop timing attacks. + Clear the mac in the callers buffer if we're successful +*/ +#ifdef USE_TLS_1_1 + if ((ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->deBlockSize > 1)) { + ctStart += ssl->deBlockSize; /* skip explicit IV */ + } +#endif + +#ifdef LUCKY13 + /* + Lucky 13 Step 5. If using a block cipher, blind the mac operation. + Doing this extra MAC compression here rather + than inside the real verify to keep this code patch at the + protocol level. + The Sha Update calls are with an exact state size for the + hash, so the compress function will be called 1:1 with the Update. + */ + if (ssl->deBlockSize > 1) { + /* Run this helper regardless of error status thus far */ + rc = addCompressCount(ssl, padLen); + if (macError == 0) { +#ifndef USE_CL_DIGESTS + psDigestContext_t md; + unsigned char tmp[128]; + switch (ssl->deMacSize) { +#ifdef USE_SHA256 + case SHA256_HASH_SIZE: + psSha256Init(&md.sha256); + while (rc > 0) { + psSha256Update(&md.sha256, tmp, 64); + rc--; + } + psSha256Final(&md.sha256, tmp); + break; +#endif +#ifdef USE_SHA384 + case SHA384_HASH_SIZE: + psSha384Init(&md.sha384); + while (rc > 0) { + psSha384Update(&md.sha384, tmp, 128); + rc--; + } + psSha384Final(&md.sha384, tmp); + break; +#endif +#ifdef USE_SHA1 + case SHA1_HASH_SIZE: + psSha1Init(&md.sha1); + while (rc > 0) { + psSha1Update(&md.sha1, tmp, 64); + rc--; + } + psSha1Final(&md.sha1, tmp); + break; +#endif + default: + psAssert(0); + break; + } +#else + /* With FIPS implementation, + psHmacSha*Tls functions shall be used to + mitigate Lucky13. */ +#endif /* USE_CL_DIGESTS */ + } + } +#endif /* LUCKY13 */ + + if (ssl->verifyMac(ssl, ssl->rec.type, ctStart, + (uint32)(mac - ctStart), mac) < 0 || macError) { + ssl->err = SSL_ALERT_BAD_RECORD_MAC; + psTraceInfo("Couldn't verify MAC or pad of record data\n"); + goto encodeResponse; + } + + memset(mac, 0x0, ssl->deMacSize); + + /* Record data starts at ctStart and ends at mac */ + p = ctStart; + pend = mac; + } else { +/* + The record data is the entire record as there is no MAC or padding +*/ + p = ctStart; + pend = mac = ctStart + ssl->rec.len; + } + +#ifdef USE_ZLIB_COMPRESSION + /* Currently only supporting compression of FINISHED message. + Compressed application data is handled outside MatrixSSL. + Re-handshakes are not allowed with compression and we've + incremented ssl->compression if we've already been through here + so we'll know */ + if (ssl->compression == 2 && ssl->flags & SSL_FLAGS_READ_SECURE && + ssl->rec.type == SSL_RECORD_TYPE_HANDSHAKE) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + psTraceInfo("Re-handshakes not supported on compressed sessions\n"); + goto encodeResponse; + } + if (ssl->compression && ssl->flags & SSL_FLAGS_READ_SECURE && + ssl->rec.type == SSL_RECORD_TYPE_HANDSHAKE) { + /* TODO - handle the cases below where the buffer has to grow */ + currLen = ssl->inflate.total_out; + preInflateLen = (int32)(pend - p); + ssl->zlibBuffer = psMalloc(ssl->bufferPool, preInflateLen + + MATRIX_INFLATE_FINISHED_OH); + if (ssl->zlibBuffer == NULL) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + psTraceInfo("Couldn't allocate compressed scratch pad\n"); + goto encodeResponse; + } + memset(ssl->zlibBuffer, 0, preInflateLen + MATRIX_INFLATE_FINISHED_OH); + if (preInflateLen > 0) { /* zero length record possible */ + /* psTraceBytes("pre inflate", ctStart, preInflateLen); */ + ssl->inflate.next_in = ctStart; + ssl->inflate.avail_in = preInflateLen; + ssl->inflate.next_out = ssl->zlibBuffer; + ssl->inflate.avail_out = SSL_MAX_PLAINTEXT_LEN; + if ((zret = inflate(&ssl->inflate, Z_SYNC_FLUSH)) != Z_OK) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + psFree(ssl->zlibBuffer, ssl->bufferPool); ssl->zlibBuffer =NULL; + inflateEnd(&ssl->inflate); + psTraceIntInfo("ZLIB inflate failed %d\n", zret); + goto encodeResponse; + } + if (ssl->inflate.avail_in != 0) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + psFree(ssl->zlibBuffer, ssl->bufferPool); ssl->zlibBuffer =NULL; + inflateEnd(&ssl->inflate); + psTraceInfo("ZLIB inflate didn't work in one pass\n"); + goto encodeResponse; + } + postInflateLen = ssl->inflate.total_out - currLen; + + /* psTraceBytes("post inflate", ssl->zlibBuffer, + postInflateLen); */ + + if (postInflateLen <= preInflateLen) { + /* Easy case where compressed data was actually larger. + Don't need to update c or inlen because the next + good data is already correctly being pointed to */ + memcpy(p, ssl->zlibBuffer, postInflateLen); + mac = p + postInflateLen; + pend = mac; + } else { + /* Data expanded. Fit it in the buffer and update all + the associated lengths and pointers + + Add back in the MAC and pad to preInflate so we're + looking at the useful boundaries of the buffers */ + preInflateLen += (int32)(c - mac); + /* reusing currLen var. Now the difference in lengths */ + currLen = postInflateLen - preInflateLen; + if ((int32)(c - ssl->inbuf) == ssl->inlen) { + /* Good, this was the only data in the buffer. Just + check there is room to append */ + if ((ssl->insize - ssl->inlen) >= postInflateLen) { + memcpy(p, ssl->zlibBuffer, postInflateLen); + c += currLen; + mac = p + postInflateLen; + pend = mac; + } else { + /* Only one here but not enough room to store it */ + ssl->err = SSL_ALERT_INTERNAL_ERROR; + psFree(ssl->zlibBuffer, ssl->bufferPool); + ssl->zlibBuffer = NULL; + inflateEnd(&ssl->inflate); + psTraceInfo("ZLIB buffer management needed\n"); + goto encodeResponse; + } + } else { + /* Push any existing data further back in the buffer to + make room for this uncompressed length. c pointing + to start of next record that needs to be pushed + back. currLen is how far to push back. + p pointing to where zlibBuffer should copy + to. postInflateLen is amount to copy there. */ + if (currLen < (ssl->insize - ssl->inlen)) { + /* Good, fits in current buffer. Move all valid + data back currLen */ + memmove(c + currLen, c, + ssl->inlen - (int32)(c - ssl->inbuf)); + c += currLen; + memcpy(p, ssl->zlibBuffer, postInflateLen); + mac = p + postInflateLen; + pend = mac; + } else { + /* Need to realloc more space AND push the records + back */ + ssl->err = SSL_ALERT_INTERNAL_ERROR; + psFree(ssl->zlibBuffer, ssl->bufferPool); + ssl->zlibBuffer = NULL; + inflateEnd(&ssl->inflate); + psTraceInfo("ZLIB buffer management needed\n"); + goto encodeResponse; + } + } + /* Finally increase inlen and *len to account for it now */ + ssl->inlen += currLen; + *len += currLen; + ssl->rec.len += currLen; + } + } + psFree(ssl->zlibBuffer, ssl->bufferPool); ssl->zlibBuffer = NULL; + /* Will not need the context any longer since FINISHED is the only + supported message */ + inflateEnd(&ssl->inflate); + ssl->compression = 2; + } +#endif /* USE_ZLIB_COMPRESSION */ + + /* Check now for maximum plaintext length of 16kb. */ + if (ssl->maxPtFrag == 0xFF) { /* Still negotiating size */ + if ((int32)(pend - p) > SSL_MAX_PLAINTEXT_LEN) { + ssl->err = SSL_ALERT_RECORD_OVERFLOW; + psTraceInfo("Record overflow\n"); + goto encodeResponse; + } + } else { + if ((int32)(pend - p) > ssl->maxPtFrag) { + ssl->err = SSL_ALERT_RECORD_OVERFLOW; + psTraceInfo("Record overflow\n"); + goto encodeResponse; + } + } + +/* + Take action based on the actual record type we're dealing with + 'p' points to the start of the data, and 'pend' points to the end +*/ + switch (ssl->rec.type) { + case SSL_RECORD_TYPE_CHANGE_CIPHER_SPEC: + psTraceStrHs(">>> %s parsing CHANGE_CIPHER_SPEC message\n", + (ssl->flags & SSL_FLAGS_SERVER) ? "Server" : "Client"); +/* + Body is single byte with value 1 to indicate that the next message + will be encrypted using the negotiated cipher suite +*/ + if (pend - p < 1) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Invalid length for CipherSpec\n"); + goto encodeResponse; + } + if (*p == 1) { + p++; + } else { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Invalid value for CipherSpec\n"); + goto encodeResponse; + } + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (ssl->hsState != SSL_HS_FINISHED) { + /* Possible to get the changeCipherSpec message out of order */ + psTraceIntInfo("Got out of order CCS: state %d\n", ssl->hsState); + *buf = c; + goto decodeMore; + } + /* The epoch corner cases surrounding the CHANGE_CIPHER_SPEC + message are complex. Let's just finally create a clear signal + that the CCS was parsed. The general problem is that our + state machine is FINISHED when expecting either the CCS or + the FINISHED message (probably goes back to CCS having some + special record type in the specs). This will just be set + between CCS parse and FINISHED parse */ + ssl->parsedCCS = 1; + } +/* + Expect epoch to increment after successful CCS parse +*/ + incrTwoByte(ssl, ssl->expectedEpoch, 0); +#endif /* USE_DTLS */ + + *remaining = *len - (c - origbuf); + *buf = c; +/* + If we're expecting finished, then this is the right place to get + this record. It is really part of the handshake but it has its + own record type. + Activate the read cipher callbacks, so we will decrypt incoming + data from now on. +*/ + if (ssl->hsState == SSL_HS_FINISHED) { + if (sslActivateReadCipher(ssl) < 0) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + goto encodeResponse; + } + } else { +#ifdef USE_STATELESS_SESSION_TICKETS + /* RFC 5077 allows the server to not acknowlege whether or not it + accepted our session ticket in the SERVER_HELLO extension so + there was no place prior to recieving this CCS to find out. + Different cipher suites types will be in different states */ + if (ssl->hsState == SSL_HS_CERTIFICATE && ssl->sid && + ssl->sid->sessionTicketState == SESS_TICKET_STATE_IN_LIMBO) { + /* Do all the things that should have been done earlier */ + ssl->flags |= SSL_FLAGS_RESUMED; +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, RESUMPTIONS_STAT, 1); +#endif + if (sslCreateKeys(ssl) < 0) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + goto encodeResponse; + } + ssl->hsState = SSL_HS_FINISHED; + if (sslActivateReadCipher(ssl) < 0) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + goto encodeResponse; + } + ssl->sid->sessionTicketState = SESS_TICKET_STATE_INIT; +#ifdef USE_ANON_DH_CIPHER_SUITE + /* Anon DH could be in SERVER_KEY_EXCHANGE state */ + } else if ((ssl->flags & SSL_FLAGS_ANON_CIPHER) && + (ssl->hsState == SSL_HS_SERVER_KEY_EXCHANGE) && ssl->sid && + ssl->sid->sessionTicketState == SESS_TICKET_STATE_IN_LIMBO) { + /* Do all the things that should have been done earlier */ + ssl->flags |= SSL_FLAGS_RESUMED; +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, RESUMPTIONS_STAT, 1); +#endif + if (sslCreateKeys(ssl) < 0) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + goto encodeResponse; + } + ssl->hsState = SSL_HS_FINISHED; + if (sslActivateReadCipher(ssl) < 0) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + goto encodeResponse; + } + ssl->sid->sessionTicketState = SESS_TICKET_STATE_INIT; +#endif /* USE_ANON_DH_CIPHER_SUITE */ +#ifdef USE_PSK_CIPHER_SUITE + /* PSK could be in SERVER_KEY_EXCHANGE state */ + } else if ((ssl->flags & SSL_FLAGS_PSK_CIPHER) && + (ssl->hsState == SSL_HS_SERVER_KEY_EXCHANGE) && ssl->sid && + ssl->sid->sessionTicketState == SESS_TICKET_STATE_IN_LIMBO) { + /* Do all the things that should have been done earlier */ + ssl->flags |= SSL_FLAGS_RESUMED; +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, RESUMPTIONS_STAT, 1); +#endif + if (sslCreateKeys(ssl) < 0) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + goto encodeResponse; + } + ssl->hsState = SSL_HS_FINISHED; + if (sslActivateReadCipher(ssl) < 0) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + goto encodeResponse; + } + ssl->sid->sessionTicketState = SESS_TICKET_STATE_INIT; +#endif /* USE_PSK_CIPHER_SUITE */ + } else { + ssl->err = SSL_ALERT_UNEXPECTED_MESSAGE; + psTraceIntInfo("Invalid CipherSpec order: %d\n", ssl->hsState); + goto encodeResponse; + } +#else + ssl->err = SSL_ALERT_UNEXPECTED_MESSAGE; + psTraceIntInfo("Invalid CipherSpec order: %d\n", ssl->hsState); + goto encodeResponse; +#endif + } + ssl->decState = SSL_HS_CCC; + return MATRIXSSL_SUCCESS; + + case SSL_RECORD_TYPE_ALERT: +/* + Decoded an alert + 1 byte alert level (warning or fatal) + 1 byte alert description corresponding to SSL_ALERT_* +*/ + if (pend - p < 2) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Error in length of alert record\n"); + goto encodeResponse; + } + *alertLevel = *p; p++; + *alertDescription = *p; p++; + *len = 2; + psTraceIntInfo("Received alert %d\n", (int32)(*alertDescription)); +/* + If the alert is fatal, or is a close message (usually a warning), + flag the session with ERROR so it cannot be used anymore. + Caller can decide whether or not to close on other warnings. +*/ + if (*alertLevel == SSL_ALERT_LEVEL_FATAL) { + ssl->flags |= SSL_FLAGS_ERROR; + } + if (*alertDescription == SSL_ALERT_CLOSE_NOTIFY) { + ssl->flags |= SSL_FLAGS_CLOSED; + } + *buf = c; + ssl->decState = SSL_HS_ALERT; + return SSL_ALERT; + + case SSL_RECORD_TYPE_HANDSHAKE: +/* + We've got one or more handshake messages in the record data. + The handshake parsing function will take care of all messages + and return an error if there is any problem. + If there is a response to be sent (either a return handshake + or an error alert, send it). If the message was parsed, but no + response is needed, loop up and try to parse another message +*/ +#ifdef USE_CERT_CHAIN_PARSING + if (ssl->rec.partial) { + if (ssl->rec.hsBytesParsed == 0) { +/* + Account for the SSL record header for first pass +*/ + ssl->rec.hsBytesParsed = ssl->recordHeadLen; + } + } +#endif + rc = parseSSLHandshake(ssl, (char*)p, (uint32)(pend - p)); + /* If the entire fragment is present, the parse has occured */ + if (ssl->fragMessage != NULL) { + if (ssl->fragIndex == ssl->fragTotal) { + psFree(ssl->fragMessage, ssl->hsPool); + ssl->fragMessage = NULL; + ssl->fragIndex = ssl->fragTotal = 0; + } + } + switch (rc) { + case MATRIXSSL_SUCCESS: + *remaining = *len - (c - origbuf); + *buf = c; + return MATRIXSSL_SUCCESS; + +#ifdef USE_DTLS + case DTLS_RETRANSMIT: + /* The idea here is to only return retransmit if + we are seeing the final message in the inbuf as repeat. Otherwise + the next msg right in this flight might be able to move our state + forward without a resend. */ + *remaining = *len - (c - origbuf); + *buf = c; + if (*remaining == 0) { + return DTLS_RETRANSMIT; + } else { + return MATRIXSSL_SUCCESS; + } +#endif /* USE_DTLS */ + + case SSL_PROCESS_DATA: + /* + We're here when we've processed an SSL header that requires + a response. In all cases (except FALSE START), we would not + expect to have any data remaining in the incoming buffer, since + the peer would be waiting for our response. + */ +#ifdef ENABLE_FALSE_START + if (c < origbuf + *len) { + /* + If there's still incoming data in the buffer, it could be + FALSE START app data immediately after the FINISHED message, + and before we've had a chance to encode and send our + CHANGE_CIPHER_SPEC and FINISHED message. We hack around + some values to support this case. + http://tools.ietf.org/html/draft-bmoeller-tls-falsestart-00 + */ + if (*c == SSL_RECORD_TYPE_APPLICATION_DATA && + ssl->hsState == SSL_HS_DONE && + (ssl->flags & SSL_FLAGS_SERVER)) { + psTraceHs(">>> Server buffering FALSE START APPLICATION_DATA\n"); + ssl->flags |= SSL_FLAGS_FALSE_START; + *remaining = *len - (c - origbuf); + *buf = c; + } else { + /* + Implies successful parse of supposed last message in + flight so check for the corner cases and reset the + buffer to start to write response + */ +#endif + if (*c == SSL_RECORD_TYPE_APPLICATION_DATA && + ssl->hsState == SSL_HS_DONE && + (ssl->flags & SSL_FLAGS_SERVER)) { + /* If this asserts, try defining ENABLE_FALSE_START */ + psAssert(origbuf + *len == c); + *buf = origbuf; + } else if (*c == SSL_RECORD_TYPE_APPLICATION_DATA && + ssl->hsState == SSL_HS_HELLO_REQUEST && + (c < (origbuf + *len))) { + /* message tacked on to end of HELLO_REQUEST. Very + complicated scenario for the state machine and + API so we're going to ignore the HELLO_REQUEST + (fine by the specification) and give precedence to + the app data. This backup flag data was set aside + in sslResetContext when the HELLO_REQUEST was + received */ + *buf = c; +#ifdef USE_CLIENT_SIDE_SSL + ssl->sec.anon = ssl->anonBk; + ssl->flags = ssl->flagsBk; + ssl->bFlags = ssl->bFlagsBk; +#endif + ssl->hsState = SSL_HS_DONE; + return MATRIXSSL_SUCCESS; + } else { + /* If this asserts, please report the values of the + *c byte and ssl->hsState to support */ + psAssert(origbuf + *len == c); + *buf = origbuf; + } +#ifdef ENABLE_FALSE_START + } + } else { + *buf = origbuf; + } +#endif + goto encodeResponse; + + case MATRIXSSL_ERROR: + case SSL_MEM_ERROR: + if (ssl->err == SSL_ALERT_NONE) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + } + goto encodeResponse; + default: + psTraceIntInfo("Unknown return %d from parseSSLHandshake!\n", rc); + if (ssl->err == SSL_ALERT_NONE) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + } + goto encodeResponse; + } + break; + + case SSL_RECORD_TYPE_APPLICATION_DATA: +/* + Data is in the out buffer, let user handle it + Don't allow application data until handshake is complete, and we are + secure. It is ok to let application data through on the client + if we are in the SERVER_HELLO state because this could mean that + the client has sent a CLIENT_HELLO message for a rehandshake + and is awaiting reply. +*/ + if ((ssl->hsState != SSL_HS_DONE && ssl->hsState != SSL_HS_SERVER_HELLO) + || !(ssl->flags & SSL_FLAGS_READ_SECURE)) { + ssl->err = SSL_ALERT_UNEXPECTED_MESSAGE; + psTraceIntInfo("Incomplete handshake: %d\n", ssl->hsState); + goto encodeResponse; + } +/* + Insitu for application data is more tricky than it is for SSL handshake + messages. This is because there is never going to be any 'out' data + for handshake messages until the final record of a flight is parsed. + Whereas application data necessarily has an 'out' for every 'in' + record because it is the decrypted data of the 'in'. So, the managed + cases result anytime there is more than 1 app record in the 'in' buffer + where the insitu must hold BOTH a decrypted buffer and the next + encrypted record. + + Create so that: + . buf points to start of any remaining unencrypted data + . start is length of remaining encrypted data yet to decode + . len is length of unencrypted data ready for user processing + +*/ + *buf = c; + *remaining = *len - (c - origbuf); + *len = mac - origbuf; +/* + SECURITY - If the mac is at the current out->end, then there is no data + in the record. These records are valid, but are usually not sent by + the application layer protocol. Rather, they are initiated within the + remote SSL protocol implementation to avoid some types of attacks when + using block ciphers. For more information see: + http://www.openssl.org/~bodo/tls-cbc.txt + + SECURITY - Returning blank messages has the potential + for denial of service, because we are not changing the state of the + system in any way when processing these messages, (although the upper + level protocol may). To counteract this, we maintain a counter + that we share with other types of ignored messages. If too many in a + row occur, an alert will be sent and the connection closed. + We implement this as a leaky bucket, so if a non-blank message comes + in, the ignored message count is decremented, ensuring that we only + error on a large number of consecutive blanks. +*/ + if (ctStart == mac) { + if (ssl->ignoredMessageCount++ >= SSL_MAX_IGNORED_MESSAGE_COUNT) { + ssl->err = SSL_ALERT_UNEXPECTED_MESSAGE; + psTraceIntInfo("Exceeded limit on ignored messages: %d\n", + SSL_MAX_IGNORED_MESSAGE_COUNT); + goto encodeResponse; + } + } else if (ssl->ignoredMessageCount > 0) { + ssl->ignoredMessageCount--; + } +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, STAT_PT_DATA_RECV, *len); +#endif + ssl->decState = SSL_HS_DONE; + return SSL_PROCESS_DATA; + + + default: + /* Falls to error below */ + break; + } +/* + Should not get here under normal operation +*/ + psTraceIntInfo("Invalid record type in matrixSslDecode: %d\n", + ssl->rec.type); + *error = PS_PROTOCOL_FAIL; + return MATRIXSSL_ERROR; + +encodeResponse: +/* + We decoded a record that needs a response, either a handshake response + or an alert if we've detected an error. +*/ +#ifdef ENABLE_FALSE_START + if ((ssl->flags & SSL_FLAGS_FALSE_START) && *buf != origbuf) { + /* + Encode the output into ssl->outbuf in this case, rather than back + into origbuf, since there is still valid data in origbuf that + needs to be decoded later. + Other places in this function we do not reference the ssl inbuf + or outbuf directly, but this was the cleanest way for this hack. + Caller must test to see if *buf has been modified if + ssl->flags & SSL_FLAGS_FALSE_START + */ + tmpout.buf = tmpout.start = tmpout.end = ssl->outbuf + ssl->outlen; + tmpout.size = ssl->outsize - ssl->outlen; + memset(origbuf, 0x0, (*buf - origbuf)); /* SECURITY (see below) */ + } else { +#endif + psAssert(origbuf == *buf); + tmpout.buf = tmpout.end = tmpout.start = origbuf; + tmpout.size = size; + +/* + SECURITY - Clear the decoded incoming record from outbuf before encoding + the response into outbuf. +*/ + memset(tmpout.buf, 0x0, tmpout.size); + +#ifdef ENABLE_FALSE_START + } +#endif + +#ifdef USE_CLIENT_SIDE_SSL + if (ssl->hsState == SSL_HS_HELLO_REQUEST) { + memset(&options, 0x0, sizeof(sslSessOpts_t)); +/* + Don't clear the session info. If receiving a HELLO_REQUEST from a + MatrixSSL enabled server the determination on whether to reuse the + session is made on that side, so always send the current session +*/ + rc = matrixSslEncodeClientHello(ssl, &tmpout, 0, 0, requiredLen, NULL, + &options); + } else { +#endif /* USE_CLIENT_SIDE_SSL */ + rc = sslEncodeResponse(ssl, &tmpout, requiredLen); +#ifdef USE_CLIENT_SIDE_SSL + } +#endif /* USE_CLIENT_SIDE_SSL */ + *alertDescription = SSL_ALERT_NONE; + if (rc == MATRIXSSL_SUCCESS) { + if (ssl->err != SSL_ALERT_NONE) { + /* We know this is always a fatal alert due to an error in + message parsing or creation so flag this session as error */ + ssl->flags |= SSL_FLAGS_ERROR; +/* + If tmpbuf has data, it is an alert that needs to be sent so let + it fall through. Not sure how we would ever not have data in tmpout +*/ + if (tmpout.buf == tmpout.end) { + psTraceInfo("Unexpected data\n"); + *error = PS_PROTOCOL_FAIL; + return MATRIXSSL_ERROR; + } + *alertDescription = (unsigned char)ssl->err; + *alertLevel = SSL_ALERT_LEVEL_FATAL; + } +#ifdef ENABLE_FALSE_START + if ((ssl->flags & SSL_FLAGS_FALSE_START) && *buf != origbuf) { + /* Update outlen with the data we added */ + ssl->outlen += tmpout.end - tmpout.buf; + } else { +#endif + *remaining = 0; + *len = tmpout.end - tmpout.buf; +#ifdef ENABLE_FALSE_START + } +#endif + return SSL_SEND_RESPONSE; + } + if (rc == SSL_FULL) { +#ifdef ENABLE_FALSE_START + /* We don't support growing outbuf in the false start case */ + if (*buf != origbuf) { + psAssert(rc != SSL_FULL); + *error = rc; + return MATRIXSSL_ERROR; + } +#endif + ssl->flags |= SSL_FLAGS_NEED_ENCODE; + *len = 0; /* No data left to decode */ + /* requiredLen is set by sslEncode Response or ClientHello above */ + return SSL_FULL; + } + psAssert(rc < 0); + *error = rc; + return MATRIXSSL_ERROR; +} + +#ifdef LUCKY13 +/* Return the number of additional MAC compressions that are needed to blind + the padding/hmac logic for thwarting Lucky 13 style attacks +*/ +static int32 addCompressCount(ssl_t *ssl, int32 padLen) +{ + int32 l1, l2, c1, c2, len; + + c1 = c2 = 0; + len = ssl->rec.len; + +#ifdef USE_TLS_1_1 + if (ssl->flags & SSL_FLAGS_TLS_1_1) { + len -= ssl->deBlockSize; /* skip explicit IV */ + } +#endif + l1 = 13 + len - ssl->deMacSize; + l2 = 13 + len - padLen - 1 - ssl->deMacSize; + + if (ssl->deMacSize == SHA1_HASH_SIZE || ssl->deMacSize == SHA256_HASH_SIZE){ + while (l1 > 64) { + c1++; l1 -= 64; + } + if (l1 > 56) { + c1++; + } + while (l2 > 64) { + c2++; l2 -= 64; + } + if (l2 > 56) { + c2++; + } +#ifdef USE_SHA384 + } else if (ssl->deMacSize == SHA384_HASH_SIZE) { + while (l1 > 128) { + c1++; l1 -= 128; + } + if (l1 > 112) { + c1++; + } + while (l2 > 128) { + c2++; l2 -= 128; + } + if (l2 > 112) { + c2++; + } + +#endif + } + + return c1 - c2; +} +#endif /* LUCKY13 */ + +/******************************************************************************/ +/* + The workhorse for parsing handshake messages. Also enforces the state + machine for proper ordering of handshake messages. + Parameters: + ssl - ssl context + inbuf - buffer to read handshake message from + len - data length for the current ssl record. The ssl record + can contain multiple handshake messages, so we may need to parse + them all here. + Return: + MATRIXSSL_SUCCESS + SSL_PROCESS_DATA + MATRIXSSL_ERROR - see ssl->err for details + MEM_FAIL + -MATRIXSSL_ERROR and MEM_FAIL will be caught and an alert sent. If you + want to specifiy the alert the set ss->err. Otherwise it will + be an INTERNAL_ERROR +*/ +static int32 parseSSLHandshake(ssl_t *ssl, char *inbuf, uint32 len) +{ + unsigned char *c, *end; + unsigned char hsType; + int32 rc; + uint32 hsLen; + unsigned char hsMsgHash[SHA512_HASH_SIZE]; + + +#ifdef USE_DTLS + uint32 fragLen; + int32 msn, fragOffset, j; +#ifdef USE_CLIENT_SIDE_SSL + int32 hvreqMinVer, hvreqMajVer; +#endif +#endif /* USE_DTLS */ + + + rc = MATRIXSSL_SUCCESS; + c = (unsigned char*)inbuf; + end = (unsigned char*)(inbuf + len); + + /* Immediately check if we are working with a fragmented message. */ +#ifdef USE_DTLS + /* This is the non-DTLS fragmentation handler */ + if (!(ssl->flags & SSL_FLAGS_DTLS)) { +#endif + if (ssl->fragMessage != NULL) { + /* Just borrowing hsLen variable. Is the rest here or do we still + need more? */ + hsLen = min((uint32)(end - c), ssl->fragTotal - ssl->fragIndex); + memcpy(ssl->fragMessage + ssl->fragIndex, c, hsLen); + ssl->fragIndex += hsLen; + c += hsLen; + + if (ssl->fragIndex == ssl->fragTotal) { + c = ssl->fragMessage + ssl->hshakeHeadLen; + end = ssl->fragMessage + ssl->fragTotal; + hsLen = ssl->fragTotal - ssl->hshakeHeadLen; + goto SKIP_HSHEADER_PARSE; + } else { + return MATRIXSSL_SUCCESS; + } + } +#ifdef USE_DTLS + } +#endif + +#ifdef USE_CERT_CHAIN_PARSING + if (ssl->rec.partial && (ssl->rec.hsBytesParsed > ssl->recordHeadLen)) { + goto SKIP_HSHEADER_PARSE; + } +#endif /* USE_CERT_CHAIN_PARSING */ + +parseHandshake: + if (end - c < 1) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid length of handshake message 1\n"); + psTraceIntInfo("%d\n", (int32)(end - c)); + return MATRIXSSL_ERROR; + } + hsType = *c; c++; + +#ifndef SSL_REHANDSHAKES_ENABLED +/* + If all rehandshaking is disabled, just catch that here and alert. +*/ + if (ssl->flags & SSL_FLAGS_SERVER) { + if (hsType == SSL_HS_CLIENT_HELLO && ssl->hsState == SSL_HS_DONE) { + psTraceInfo("Closing conn with client. Rehandshake is disabled\n"); + ssl->err = SSL_ALERT_NO_RENEGOTIATION; + return MATRIXSSL_ERROR; + } + } else { + if (hsType == SSL_HS_HELLO_REQUEST && ssl->hsState == SSL_HS_DONE) { + psTraceInfo("Closing conn with server. Rehandshake is disabled\n"); + ssl->err = SSL_ALERT_NO_RENEGOTIATION; + return MATRIXSSL_ERROR; + } + } +#endif /* SSL_REHANDSHAKES_ENABLED */ + +#ifdef USE_DTLS +/* + The MSN helpes keep the state machine sane prior to passing through to + the hsType exceptions because if they are received out-of-order it could + choose the wrong handshake type (client auth, rehandshake, or standard) + + It is mostly important to deal with future messages here because those + are the ones that may bypass us to the wrong handshake type. Duplicates + are handled below. +*/ + if (ssl->flags & SSL_FLAGS_DTLS) { + if (end - c < 5) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid length of handshake message\n"); + return MATRIXSSL_ERROR; + } + msn = c[3] << 8; + msn += c[4]; + if (msn > (ssl->lastMsn + 1)) { + psTraceIntDtls("Ignoring future handshake msg %d\n", hsType); + return MATRIXSSL_SUCCESS; + } else if (msn != 0 && ssl->lastMsn >= msn) { + psTraceIntDtls("Ignoring already seen handshake msg %d\n", hsType); + return DTLS_RETRANSMIT; + } + } +#endif /* USE_DTLS */ + +/* + hsType is the received handshake type and ssl->hsState is the expected + handshake type. If it doesn't match, there are some possible cases + that are not errors. These are checked here. +*/ + if (hsType != ssl->hsState && + (hsType != SSL_HS_CLIENT_HELLO || ssl->hsState != SSL_HS_DONE)) { + +/* + A mismatch is possible in the client authentication case. + The optional CERTIFICATE_REQUEST may be appearing instead of + SERVER_HELLO_DONE. +*/ + if ((hsType == SSL_HS_CERTIFICATE_REQUEST) && + (ssl->hsState == SSL_HS_SERVER_HELLO_DONE)) { +/* + This is where the client is first aware of requested client + authentication so we set the flag here. + +*/ + ssl->flags |= SSL_FLAGS_CLIENT_AUTH; + ssl->hsState = SSL_HS_CERTIFICATE_REQUEST; + goto hsStateDetermined; + } +/* + Another possible mismatch allowed is for a HELLO_REQEST message. + Indicates a rehandshake initiated from the server. +*/ + if ((hsType == SSL_HS_HELLO_REQUEST) && + (ssl->hsState == SSL_HS_DONE) && + !(ssl->flags & SSL_FLAGS_SERVER)) { + sslResetContext(ssl); + ssl->hsState = hsType; + goto hsStateDetermined; + } + + /* Another possible mismatch is HELLO_REQUEST right after we sent + a re-handshake CLIENT_HELLO. Will ignore the request and + assume this was a timing issue and that the server will reply + to our CLIENT_HELLO when it is received */ + if ((hsType == SSL_HS_HELLO_REQUEST) && + (ssl->hsState == SSL_HS_SERVER_HELLO) && + (ssl->flags & SSL_FLAGS_READ_SECURE) && + (ssl->flags & SSL_FLAGS_WRITE_SECURE) && + !(ssl->flags & SSL_FLAGS_SERVER)) { + /* There is no body to the message. Confirm this and exit happily + without changing state */ + if (end - c < 3) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid length of handshake message 2\n"); + psTraceIntInfo("%d\n", (int32)(end - c)); + return MATRIXSSL_ERROR; + } + hsLen = *c << 16; c++; + hsLen += *c << 8; c++; + hsLen += *c; c++; +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (end - c < 8) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid length of handshake message\n"); + return MATRIXSSL_ERROR; + } + c += 8; + } +#endif +#ifdef SSL_REHANDSHAKES_ENABLED + if (ssl->rehandshakeCount <= 0) { + ssl->err = SSL_ALERT_NO_RENEGOTIATION; + psTraceInfo("Server re-handshaking denied. Out of credits.\n"); + return MATRIXSSL_ERROR; + } + ssl->rehandshakeCount--; +#endif + if (hsLen == 0) { + return MATRIXSSL_SUCCESS; + } else { + return MATRIXSSL_ERROR; + } + } + +#ifdef USE_STATELESS_SESSION_TICKETS + /* Another possible mismatch allowed is for a + SSL_HS_NEW_SESSION_TICKET message. */ + if ((hsType == SSL_HS_NEW_SESSION_TICKET) && + (ssl->hsState == SSL_HS_FINISHED) && ssl->sid && + (ssl->sid->sessionTicketState == SESS_TICKET_STATE_RECVD_EXT) && + !(ssl->flags & SSL_FLAGS_SERVER)) { + ssl->hsState = hsType; + goto hsStateDetermined; + } + +#endif /* USE_STATELESS_SESSION_TICKETS */ + +#ifdef USE_OCSP + /* Another possible mismatch is server didn't send the optional + CERTIFICATE_STATUS message. Unfortunate this was not specified + to be strictly handled in the status_request extensions */ + if (ssl->hsState == SSL_HS_CERTIFICATE_STATUS) { + /* The two valid states from here are identical + checking of the next state calculation at the end of the + SSL_HS_CERTIFICATE message handling. + (But in reverse order due to the precedence of DHE mode.) + */ +#ifdef USE_OCSP_MUST_STAPLE + /* This is the case where the server sent a reply to our + status_request extension but didn't actually send the + handshake message. If we are in a MUST state, time to fail */ + psTraceInfo("Expecting CERTIFICATE_STATUS message\n"); + ssl->err = SSL_ALERT_UNEXPECTED_MESSAGE; + return MATRIXSSL_ERROR; +#endif + +#ifdef USE_DHE_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_DHE_KEY_EXCH && + hsType == SSL_HS_SERVER_KEY_EXCHANGE) { + ssl->hsState = hsType; + goto hsStateDetermined; + } +#endif /* USE_DHE_CIPHER_SUITE */ + if (hsType == SSL_HS_SERVER_HELLO_DONE) { + ssl->hsState = hsType; + goto hsStateDetermined; + } + } +#endif /* USE_OCSP */ + +#ifdef USE_PSK_CIPHER_SUITE +/* + PSK suites are probably not including SERVER_KEY_EXCHANGE message +*/ + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + if ((hsType == SSL_HS_SERVER_HELLO_DONE) && + (ssl->hsState == SSL_HS_SERVER_KEY_EXCHANGE)) { +#ifdef USE_DHE_CIPHER_SUITE +/* + DH kex suites must be sending a SERVER_KEY_EXCHANGE message +*/ + if (ssl->flags & SSL_FLAGS_DHE_KEY_EXCH) { + psTraceIntInfo("Expecting SKE message: %d\n", hsType); + ssl->err = SSL_ALERT_UNEXPECTED_MESSAGE; + return MATRIXSSL_ERROR; + } +#endif /* USE_DHE_CIPHER_SUITE */ + ssl->hsState = hsType; + goto hsStateDetermined; + } + } +#endif /* USE_PSK_CIPHER_SUITE */ + +#ifdef USE_DTLS +/* + DTLS inserts an optional VERIFY_REQUEST back to clients +*/ + if (ssl->flags & SSL_FLAGS_DTLS) { +#ifdef USE_CLIENT_SIDE_SSL + if ((hsType == SSL_HS_HELLO_VERIFY_REQUEST) && + (ssl->hsState == SSL_HS_SERVER_HELLO)) { + /* However, if this is a retransmit and we've already parsed + the HELLO_VERIFY_REQUEST we can safely skip it */ + if (ssl->haveCookie == 0) { + ssl->hsState = hsType; + goto hsStateDetermined; + } + } +#endif +/* + A final MSN sanity test and handling of duplicate hello messages +*/ + if ((ssl->lastMsn + 1) == msn) { + ssl->err = SSL_ALERT_UNEXPECTED_MESSAGE; + psTraceIntDtls("Correct MSN %d on unexpected HS msg ", msn); + psTraceIntDtls(" %d\n", hsType); + return MATRIXSSL_ERROR; + } else if (ssl->lastMsn >= msn) { + psTraceDtls("IGNORING ALREADY SEEN HELLO HANDSHAKE MSG\n"); + return DTLS_RETRANSMIT; + } + } +#endif /* USE_DTLS */ + + + + ssl->err = SSL_ALERT_UNEXPECTED_MESSAGE; + psTraceIntInfo("Out-of-order handshake message: %d\n", hsType); + psTraceIntInfo("Wanted: %d\n", ssl->hsState); + return MATRIXSSL_ERROR; + } + +hsStateDetermined: + if (hsType == SSL_HS_CLIENT_HELLO) { + sslInitHSHash(ssl); + if (ssl->hsState == SSL_HS_DONE) { +#ifdef SSL_REHANDSHAKES_ENABLED + /* This is a 'leaky bucket' mechanism where each X bytes of data transfer gains + you a re-handshake credit. Prevents the DOS attack of repeat + re-handshake requests */ + if (ssl->rehandshakeCount <= 0) { + ssl->err = SSL_ALERT_NO_RENEGOTIATION; + psTraceInfo("Client re-handshaking denied\n"); + return MATRIXSSL_ERROR; + } + ssl->rehandshakeBytes = 0; /* reset */ + ssl->rehandshakeCount--; +#endif /* SSL_REHANDSHAKES_ENABLED */ + /* Rehandshake. Server receiving client hello on existing connection */ + sslResetContext(ssl); + ssl->hsState = hsType; + } + } + +/* + We need to get a copy of the message hashes to compare to those sent + in the finished message (which does not include a hash of itself) + before we update the handshake hashes +*/ + if (ssl->hsState == SSL_HS_FINISHED) { + if (sslSnapshotHSHash(ssl, hsMsgHash, + (ssl->flags & SSL_FLAGS_SERVER) ? 0 : SSL_FLAGS_SERVER) <= 0) { + psTraceInfo("Error snapshotting HS hash\n"); + ssl->err = SSL_ALERT_INTERNAL_ERROR; + return MATRIXSSL_ERROR; + } + } +#ifdef USE_CLIENT_AUTH + if (ssl->hsState == SSL_HS_CERTIFICATE_VERIFY) { + /* Same issue as above for client auth. Need a handshake snapshot + that doesn't include this message we are about to process */ + if (sslSnapshotHSHash(ssl, hsMsgHash, -1) <= 0) { + psTraceInfo("Error snapshotting HS hash\n"); + ssl->err = SSL_ALERT_INTERNAL_ERROR; + return MATRIXSSL_ERROR; + } + } +#endif /* USE_CLIENT_AUTH */ + +/* + Process the handshake header and update the ongoing handshake hash + SSLv3: + 1 byte type + 3 bytes length + SSLv2: + 1 byte type +*/ + if (ssl->rec.majVer >= SSL3_MAJ_VER) { + if (end - c < 3) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid length of handshake message 2\n"); + psTraceIntInfo("%d\n", (int32)(end - c)); + return MATRIXSSL_ERROR; + } + hsLen = *c << 16; c++; + hsLen += *c << 8; c++; + hsLen += *c; c++; +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (end - c < 8) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid length of handshake message\n"); + return MATRIXSSL_ERROR; + } + msn = *c << 8; c++; + msn += *c; c++; + fragOffset = *c << 16; c++; + fragOffset += *c << 8; c++; + fragOffset += *c; c++; + fragLen = *c << 16; c++; + fragLen += *c << 8; c++; + fragLen += *c; c++; + if (fragLen != hsLen) { +/* + Have a fragmented message here. Allocate if first time + seen and assign msn. Can only deal with single fragmented + message at a time. +*/ + if (ssl->fragTotal == 0) { +/* + When all the fragments are received, this allocated pointer + becomes the 'c' parsing pointer. With all the potential + exit points in the parse code from all the different + messages it is not easy to free this on the fly. So, what + happens here is that each first message fragment that is + encountered will free the previous message if it exists + (not NULL). + + The final test for freeing this pointer will be in the + encoding (client) and decoding (server) of the Finished + message. At this point we know we can't possibly be + recieving any more fragments since the CCS and Finished + messages will never be so large that they would require + fragmenting. Also, the handshake pool is freed during + the encoding of Finished. +*/ + if (ssl->fragMessage != NULL ) { + psFree(ssl->fragMessage, ssl->hsPool); + ssl->fragMessage = NULL; + } + ssl->fragMessage = psMalloc(ssl->hsPool, hsLen); + if (ssl->fragMessage == NULL) { + return SSL_MEM_ERROR; + } + ssl->fragMsn = msn; + } + + if (ssl->fragMsn != msn) { +/* + Got a fragment from a different msg. Ignore +*/ + return MATRIXSSL_SUCCESS; + } +/* + Still could be a duplicate fragment. Make sure we haven't + seen it before. If we haven't this routine also returns + the next open fragment header index for use below. +*/ + if ((rc = dtlsSeenFrag(ssl, fragOffset, &j)) == 1) { + return MATRIXSSL_SUCCESS; + } else if (rc == -1) { /* MAX_FRAGMENTS exceeded */ + dtlsInitFrag(ssl); /* init will free memory */ + if (ssl->fragMessage != NULL) { + psFree(ssl->fragMessage, ssl->hsPool); + ssl->fragMessage = NULL; + } + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceIntDtls("Max fragment limit exceeded: %d\n", + MAX_FRAGMENTS); + return PS_LIMIT_FAIL; + } +/* + Need to save the hs header info aside as well so that we may + pass the fragments through the handshake hash mechanism in + the correct order. This list also keeps track of the fragment + offsets and lengths for the same reason. +*/ + ssl->fragHeaders[j].hsHeader = psMalloc(ssl->hsPool, + ssl->hshakeHeadLen); + if (ssl->fragHeaders[j].hsHeader == NULL) { + dtlsInitFrag(ssl); /* init to free */ + return SSL_MEM_ERROR; + } + memcpy(ssl->fragHeaders[j].hsHeader, c - ssl->hshakeHeadLen, + ssl->hshakeHeadLen); + ssl->fragHeaders[j].offset = fragOffset; + ssl->fragHeaders[j].fragLen = fragLen; + + ssl->fragTotal += fragLen; + memcpy(ssl->fragMessage + fragOffset, c, fragLen); + if (ssl->fragTotal != hsLen) { + + /* Don't have all the fragments yet */ + return MATRIXSSL_SUCCESS; + } + c = ssl->fragMessage; + end = ssl->fragMessage + hsLen; + } + } +#endif /* USE_DTLS */ +#ifdef USE_CERT_CHAIN_PARSING + if (((uint32)(end - c) < hsLen) && !ssl->rec.partial) { +#else + if ((uint32)(end - c) < hsLen) { +#endif + /* Support for fragmented handshake messages - non-DTLS */ + if (ssl->fragMessage == NULL) { + /* Initial indication there is a fragmented message */ + ssl->fragTotal = hsLen + ssl->hshakeHeadLen; + ssl->fragMessage = psMalloc(ssl->hsPool, ssl->fragTotal); + if (ssl->fragMessage == NULL) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + psTraceInfo("Memory allocation error\n"); + return MATRIXSSL_ERROR; + } + ssl->fragIndex = (uint32)(end - c) + ssl->hshakeHeadLen; + memcpy(ssl->fragMessage, c - ssl->hshakeHeadLen, + ssl->fragIndex); + return MATRIXSSL_SUCCESS; + } else { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid handshake length\n"); + return MATRIXSSL_ERROR; + } + } +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (ssl->fragTotal > 0) { + /* Run the UpdateHash over the fragmented message */ + dtlsHsHashFragMsg(ssl); + dtlsInitFrag(ssl); + } else { +/* + The DTLS case in which the message was not fragmented. + Not at all unusual to hit this +*/ + sslUpdateHSHash(ssl, c - ssl->hshakeHeadLen, + hsLen + ssl->hshakeHeadLen); + } + + } else { +#endif /* USE_DTLS */ +SKIP_HSHEADER_PARSE: + +#ifdef USE_CERT_CHAIN_PARSING + if (ssl->rec.partial) { +/* + Length of partial certificate records are being managed + manually with ssl->rec.len. The first pass will need to + include the record header in the hash. +*/ + if (ssl->rec.hsBytesHashed == 0) { + sslUpdateHSHash(ssl, c - ssl->hshakeHeadLen, ssl->rec.len); + } else { + sslUpdateHSHash(ssl, c, ssl->rec.len); + } + ssl->rec.hsBytesHashed += ssl->rec.len; + } else { + sslUpdateHSHash(ssl, c - ssl->hshakeHeadLen, + hsLen + ssl->hshakeHeadLen); + } +#else + sslUpdateHSHash(ssl, c - ssl->hshakeHeadLen, + hsLen + ssl->hshakeHeadLen); + +#endif +#ifdef USE_DTLS + } +#endif /* USE_DTLS */ + + } else if (ssl->rec.majVer == SSL2_MAJ_VER) { +/* + Assume that the handshake len is the same as the incoming ssl record + length minus 1 byte (type), this is verified in SSL_HS_CLIENT_HELLO +*/ + hsLen = len - 1; + sslUpdateHSHash(ssl, (unsigned char*)inbuf, len); + } else { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceIntInfo("Invalid record version: %d\n", ssl->rec.majVer); + return MATRIXSSL_ERROR; + } + +/******************************************************************************/ +/* + Finished with header. Process each type of handshake message. +*/ + switch (ssl->hsState) { + +/******************************************************************************/ + +#ifdef USE_SERVER_SIDE_SSL + case SSL_HS_CLIENT_HELLO: + psAssert(rc == 0); /* checking to see if this is the correct default */ + rc = parseClientHello(ssl, &c, end); + /* SSL_PROCESS_DATA is a valid code to indicate the end of a flight */ + if (rc < 0 && rc != SSL_PROCESS_DATA) { + return rc; + } + break; + +/******************************************************************************/ + + case SSL_HS_CLIENT_KEY_EXCHANGE: + psAssert(rc == 0); /* checking to see if this is the correct default */ + rc = parseClientKeyExchange(ssl, hsLen, &c, end); + if (rc < 0) { + return rc; + } + break; +#endif /* USE_SERVER_SIDE_SSL */ + +/******************************************************************************/ + + case SSL_HS_FINISHED: + psAssert(rc == 0); /* checking to see if this is the correct default */ + rc = parseFinished(ssl, hsLen, hsMsgHash, &c, end); + /* SSL_PROCESS_DATA is a valid code to indicate the end of a flight */ + if (rc < 0 && rc != SSL_PROCESS_DATA) { + return rc; + } + break; + +/******************************************************************************/ +#ifdef USE_CLIENT_SIDE_SSL + case SSL_HS_HELLO_REQUEST: + /* No body message and the only one in record flight */ + psTraceHs(">>> Client parsing HELLO_REQUEST message\n"); + if (end - c != 0) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Invalid hello request message\n"); + return MATRIXSSL_ERROR; + } +#ifdef SSL_REHANDSHAKES_ENABLED + if (ssl->rehandshakeCount <= 0) { + ssl->err = SSL_ALERT_NO_RENEGOTIATION; + psTraceInfo("Server re-handshaking denied\n"); + /* Reset the state to done */ + ssl->hsState = SSL_HS_DONE; + return MATRIXSSL_ERROR; + } + ssl->rehandshakeCount--; +#endif + /* Intentionally not changing state here to SERVER_HELLO. The + encodeResponse case this will fall into needs to distinguish + between calling the normal sslEncodeResponse or encodeClientHello. + The HELLO_REQUEST state is used to make that determination and the + writing of CLIENT_HELLO will properly move the state along itself */ + ssl->decState = SSL_HS_HELLO_REQUEST; + rc = SSL_PROCESS_DATA; + break; + +/******************************************************************************/ + + case SSL_HS_SERVER_HELLO: + + psAssert(rc == 0); /* checking to see if this is the correct default */ + rc = parseServerHello(ssl, hsLen, &c, end); + if (rc < 0) { + return rc; + } + break; + +#endif /* USE_CLIENT_SIDE_SSL */ + +/******************************************************************************/ + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH) + + case SSL_HS_CERTIFICATE: + psAssert(rc == 0); /* checking to see if this is the correct default */ + rc = parseCertificate(ssl, &c, end); + if (rc < 0) { + return rc; + } + break; + +#endif /* USE_CLIENT_SIDE_SSL || USE_CLIENT_AUTH */ +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + +#ifdef USE_CLIENT_SIDE_SSL +/******************************************************************************/ +#ifdef USE_OCSP + case SSL_HS_CERTIFICATE_STATUS: + psTraceHs(">>> Client parsing CERTIFICATE_STATUS message\n"); + rc = parseCertificateStatus(ssl, hsLen, &c, end); + if (rc < 0) { + return rc; + } + break; +#endif /* USE_OCSP */ + +/******************************************************************************/ + + +#ifdef USE_STATELESS_SESSION_TICKETS + case SSL_HS_NEW_SESSION_TICKET: + + psTraceHs(">>> Client parsing NEW_SESSION_TICKET message\n"); + if (hsLen < 6) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Invalid NewSessionTicket message\n"); + return MATRIXSSL_ERROR; + } + ssl->sid->sessionTicketLifetimeHint = *c << 24; c++; + ssl->sid->sessionTicketLifetimeHint |= *c << 16; c++; + ssl->sid->sessionTicketLifetimeHint |= *c << 8; c++; + ssl->sid->sessionTicketLifetimeHint |= *c; c++; + /* Reusing hsLen here */ + hsLen = *c << 8; c++; + hsLen |= *c; c++; + + if ((uint32)(end - c) < hsLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid NewSessionTicket message\n"); + return MATRIXSSL_ERROR; + } + if (ssl->sid->sessionTicketLen == 0) { + /* First time receiving a session ticket */ + ssl->sid->sessionTicketLen = hsLen; + /* This client has a dedicated SessionId pool to draw from. */ + if ((ssl->sid->sessionTicket = psMalloc(ssl->sid->pool, + ssl->sid->sessionTicketLen)) != NULL) { + memcpy(ssl->sid->sessionTicket, c, ssl->sid->sessionTicketLen); + c += ssl->sid->sessionTicketLen; + } else { + /* Don't fail on alloc error. Just won't have the ticket for + next time */ + c += ssl->sid->sessionTicketLen; + ssl->sid->sessionTicketLen = 0; + } + } else { + /* Updated (or duplicate) ticket */ + psAssert(ssl->sid->sessionTicket); /* exists from previous hs */ + if (hsLen == ssl->sid->sessionTicketLen && + (memcmp(c, ssl->sid->sessionTicket, hsLen) == 0)) { + /* server not updating the ticket */ + c += ssl->sid->sessionTicketLen; + } else { + ssl->sid->sessionTicketLen = hsLen; + psFree(ssl->sid->sessionTicket, ssl->sid->pool); + if ((ssl->sid->sessionTicket = psMalloc(ssl->sid->pool, + ssl->sid->sessionTicketLen)) != NULL) { + memcpy(ssl->sid->sessionTicket, c, + ssl->sid->sessionTicketLen); + c += ssl->sid->sessionTicketLen; + } else { + /* Don't fail on alloc error. Just won't have the ticket + for next time */ + c += ssl->sid->sessionTicketLen; + ssl->sid->sessionTicketLen = 0; + } + } + } + ssl->sid->sessionTicketState = SESS_TICKET_STATE_INIT; + ssl->hsState = SSL_HS_FINISHED; + ssl->decState = SSL_HS_NEW_SESSION_TICKET; + break; +#endif /* USE_STATELESS_SESSION_TICKETS */ + +/******************************************************************************/ + + case SSL_HS_SERVER_HELLO_DONE: + + psAssert(rc == 0); /* checking to see if this is the correct default */ + rc = parseServerHelloDone(ssl, hsLen, &c, end); + if (rc < 0 && rc != SSL_PROCESS_DATA) { + return rc; + } + break; + + +/******************************************************************************/ + +#ifndef USE_ONLY_PSK_CIPHER_SUITE + case SSL_HS_CERTIFICATE_REQUEST: + + psAssert(rc == 0); /* checking to see if this is the correct default */ + rc = parseCertificateRequest(ssl, hsLen, &c, end); + if (rc < 0) { + return rc; + } + break; +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ +#endif /* USE_CLIENT_SIDE_SSL */ + +/******************************************************************************/ + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#if defined(USE_CLIENT_AUTH) && defined(USE_SERVER_SIDE_SSL) + case SSL_HS_CERTIFICATE_VERIFY: + + psAssert(rc == 0); /* checking to see if this is the correct default */ + rc = parseCertificateVerify(ssl, hsMsgHash, &c, end); + if (rc < 0) { + return rc; + } + + break; +#endif /* USE_SERVER_SIDE_SSL && USE_CLIENT_AUTH */ +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + +/******************************************************************************/ + + case SSL_HS_SERVER_KEY_EXCHANGE: +#ifdef USE_CLIENT_SIDE_SSL + psAssert(rc == 0); /* checking to see if this is the correct default */ + rc = parseServerKeyExchange(ssl, hsMsgHash, &c, end); + if (rc < 0) { + return rc; + } +#else /* USE_CLIENT_SIDE_SSL */ + ssl->err = SSL_ALERT_UNEXPECTED_MESSAGE; + return MATRIXSSL_ERROR; +#endif /* USE_CLIENT_SIDE_SSL */ + break; + +/******************************************************************************/ + +#ifdef USE_DTLS +#ifdef USE_CLIENT_SIDE_SSL + case SSL_HS_HELLO_VERIFY_REQUEST: + psTraceHs(">>> Client parsing HELLO_VERIFY_REQUEST message\n"); +/* + Format for message is two byte version specifier, 1 byte length, and + the cookie itself +*/ + if ((end - c) < 3) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid HelloVerifyRequest message\n"); + return MATRIXSSL_ERROR; + } + hvreqMajVer = *c; c++; + hvreqMinVer = *c; c++; + (void)hvreqMajVer; /* Silence a 'set but not used' warning. */ + (void)hvreqMinVer; + ssl->cookieLen = *c; c++; + if (ssl->cookieLen > 0) { + if ((end -c) < ssl->cookieLen) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid HelloVerifyRequest message\n"); + return MATRIXSSL_ERROR; + } +/* + The handshake pool does exists at this point. For DTLS handshakes + the client created the pool during the ClientHello write in order + to store the initial message in case the Server asks for cookie + (which is exactly what is happening right here). +*/ + if (ssl->haveCookie) { + /* retransmit. should match what we already have */ + if (memcmpct(ssl->cookie, c, ssl->cookieLen) != 0) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Cookie has changed on retransmit\n"); + return MATRIXSSL_ERROR; + } + c += ssl->cookieLen; + } else { + ssl->cookie = psMalloc(ssl->hsPool, ssl->cookieLen); + if (ssl->cookie == NULL) { + return SSL_MEM_ERROR; + } + memcpy(ssl->cookie, c, ssl->cookieLen); + c += ssl->cookieLen; + } + } + ssl->haveCookie++; + ssl->hsState = SSL_HS_SERVER_HELLO; + ssl->decState = SSL_HS_HELLO_VERIFY_REQUEST; + rc = SSL_PROCESS_DATA; + break; +#endif /* USE_CLIENT_SIDE_SSL */ +#endif /* USE_DTLS */ + +/******************************************************************************/ + + default: + ssl->err = SSL_ALERT_UNEXPECTED_MESSAGE; + return MATRIXSSL_ERROR; + } + +#ifdef USE_DTLS + ssl->lastMsn = msn; /* MSN of last message sucessfully parsed */ +#endif /* USE_DTLS */ + + +/* + if we've got more data in the record, the sender has packed + multiple handshake messages in one record. Parse the next one. +*/ + if (c < end) { + goto parseHandshake; + } + return rc; +} + +/******************************************************************************/ +#if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH) +#ifdef USE_CERT_CHAIN_PARSING +static int32 parseSingleCert(ssl_t *ssl, unsigned char *c, unsigned char *end, + int32 certLen) +{ + int32 parseLen; + psX509Cert_t *cert, *p; + +/* + Extract the binary cert message into the cert structure +*/ + if ((parseLen = psX509ParseCert(ssl->hsPool, c, certLen, &cert, 0)) < 0) { + psX509FreeCert(cert); + if (parseLen == PS_MEM_FAIL) { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + } else { + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + } + return MATRIXSSL_ERROR; + } + if (ssl->sec.cert == NULL) { + ssl->sec.cert = cert; + } else { + p = ssl->sec.cert; + while (p->next != NULL) { + p = p->next; + } + p->next = cert; + } + return parseLen; +} +#endif /* USE_CERT_CHAIN_PARSING */ +#endif /* USE_CLIENT_SIDE_SSL || USE_CLIENT_AUTH */ + + +/******************************************************************************/ + diff --git a/matrixssl/sslEncode.c b/matrixssl/sslEncode.c new file mode 100644 index 0000000..133e5d8 --- /dev/null +++ b/matrixssl/sslEncode.c @@ -0,0 +1,7004 @@ +/** + * @file sslEncode.c + * @version $Format:%h%d$ + * + * Secure Sockets Layer protocol message encoding portion of MatrixSSL. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "matrixsslApi.h" + +/******************************************************************************/ + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +static int32 writeCertificate(ssl_t *ssl, sslBuf_t *out, int32 notEmpty); +#if defined(USE_OCSP) && defined(USE_SERVER_SIDE_SSL) +static int32 writeCertificateStatus(ssl_t *ssl, sslBuf_t *out); +#endif +#endif +static int32 writeChangeCipherSpec(ssl_t *ssl, sslBuf_t *out); +static int32 writeFinished(ssl_t *ssl, sslBuf_t *out); +static int32 writeAlert(ssl_t *ssl, unsigned char level, + unsigned char description, sslBuf_t *out, uint32 *requiredLen); +static int32_t writeRecordHeader(ssl_t *ssl, uint8_t type, uint8_t hsType, + uint16_t *messageSize, uint8_t *padLen, + unsigned char **encryptStart, + const unsigned char *end, unsigned char **c); +#ifdef USE_DTLS +#ifdef USE_SERVER_SIDE_SSL +static int32 writeHelloVerifyRequest(ssl_t *ssl, sslBuf_t *out); +#endif +#endif /* USE_DTLS */ + +static int32 encryptRecord(ssl_t *ssl, int32 type, int32 hsMsgType, + int32 messageSize, int32 padLen, unsigned char *pt, + sslBuf_t *out, unsigned char **c); + +#ifdef USE_CLIENT_SIDE_SSL +static int32 writeClientKeyExchange(ssl_t *ssl, sslBuf_t *out); +#endif /* USE_CLIENT_SIDE_SSL */ + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#if defined(USE_SERVER_SIDE_SSL) && defined(USE_CLIENT_AUTH) +static int32 writeCertificateRequest(ssl_t *ssl, sslBuf_t *out, int32 certLen, + int32 certCount); +static int32 writeMultiRecordCertRequest(ssl_t *ssl, sslBuf_t *out, + int32 certLen, int32 certCount, int32 sigHashLen); +#endif +#if defined(USE_CLIENT_SIDE_SSL) && defined(USE_CLIENT_AUTH) +static int32 writeCertificateVerify(ssl_t *ssl, sslBuf_t *out); +static int32 nowDoCvPka(ssl_t *ssl, psBuf_t *out); +#endif +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + +#ifdef USE_SERVER_SIDE_SSL +static int32 writeServerHello(ssl_t *ssl, sslBuf_t *out); +static int32 writeServerHelloDone(ssl_t *ssl, sslBuf_t *out); +#ifdef USE_PSK_CIPHER_SUITE +static int32 writePskServerKeyExchange(ssl_t *ssl, sslBuf_t *out); +#endif /* USE_PSK_CIPHER_SUITE */ +#ifdef USE_DHE_CIPHER_SUITE +static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen, + unsigned char *p, uint32 gLen, unsigned char *g); +#endif /* USE_DHE_CIPHER_SUITE */ +#ifdef USE_STATELESS_SESSION_TICKETS /* Already inside a USE_SERVER_SIDE block */ +static int32 writeNewSessionTicket(ssl_t *ssl, sslBuf_t *out); +#endif +#endif /* USE_SERVER_SIDE_SSL */ + +static int32 secureWriteAdditions(ssl_t *ssl, int32 numRecs); +static int32 encryptFlight(ssl_t *ssl, unsigned char **end); + +#ifdef USE_ZLIB_COMPRESSION +#define MAX_ZLIB_COMPRESSED_OH 128 /* Only FINISHED message supported */ +#endif +/******************************************************************************/ +/* + This works for both in-situ and external buf + + buf in Start of allocated buffer (header bytes beyond are overwritten) + out Start of encrypted data on function success + + size in Total size of the allocated buffer + + ptBuf in Pointer to front of the plain text data to be encrypted + + len in Length of incoming plain text + out Length of encypted text on function success + out Length of required 'size' on SSL_FULL +*/ +int32 matrixSslEncode(ssl_t *ssl, unsigned char *buf, uint32 size, + unsigned char *ptBuf, uint32 *len) +{ + unsigned char *c, *end, *encryptStart; + uint8_t padLen; + uint16_t messageSize; + int32_t rc; + psBuf_t tmpout; + + /* If we've had a protocol error, don't allow further use of the session + Also, don't allow a application data record to be encoded unless the + handshake is complete. + */ + if (ssl->flags & SSL_FLAGS_ERROR || ssl->hsState != SSL_HS_DONE || + ssl->flags & SSL_FLAGS_CLOSED) { + psTraceInfo("Bad SSL state for matrixSslEncode call attempt: "); + psTraceIntInfo(" flags %d,", ssl->flags); + psTraceIntInfo(" state %d\n", ssl->hsState); + return MATRIXSSL_ERROR; + } + + c = buf; + end = buf + size; + +#ifdef USE_BEAST_WORKAROUND + if (ssl->bFlags & BFLAG_STOP_BEAST) { + messageSize = ssl->recordHeadLen + 1; /* single byte is the fix */ + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_APPLICATION_DATA, 0, + &messageSize, &padLen, &encryptStart, end, &c)) < 0) { + if (rc == SSL_FULL) { + *len = messageSize; + } + return rc; + } + psAssert(encryptStart == buf + ssl->recordHeadLen); + c += 1; + *len -= 1; + + tmpout.buf = tmpout.start = tmpout.end = buf; + tmpout.size = size; + if ((rc = encryptRecord(ssl, SSL_RECORD_TYPE_APPLICATION_DATA, 0, + messageSize, padLen, ptBuf, &tmpout, &c)) < 0) { + return rc; + } + ptBuf += 1; + tmpout.end = tmpout.end + (c - buf); + + } +#endif +/* + writeRecordHeader will determine SSL_FULL cases. The expected + messageSize to writeRecored header is the plain text length plus the + record header length + */ + messageSize = ssl->recordHeadLen + *len; + + if (messageSize > SSL_MAX_BUF_SIZE) { + psTraceIntInfo("Message too large for matrixSslEncode: %d\n", + messageSize); + return PS_MEM_FAIL; + } + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_APPLICATION_DATA, 0, + &messageSize, &padLen, &encryptStart, end, &c)) < 0) { + if (rc == SSL_FULL) { + *len = messageSize; + } + return rc; + } + + c += *len; +#ifdef USE_BEAST_WORKAROUND + if (ssl->bFlags & BFLAG_STOP_BEAST) { + /* The tmpout buf already contains the single byte record and has + updated pointers for current location. Disable at this time */ + ssl->bFlags &= ~BFLAG_STOP_BEAST; + } else { + tmpout.buf = tmpout.start = tmpout.end = buf; + tmpout.size = size; + } +#else + tmpout.buf = tmpout.start = tmpout.end = buf; + tmpout.size = size; +#endif + + if ((rc = encryptRecord(ssl, SSL_RECORD_TYPE_APPLICATION_DATA, 0, + messageSize, padLen, ptBuf, &tmpout, &c)) < 0) { + return rc; + } + *len = (int32)(c - buf); + +#ifdef SSL_REHANDSHAKES_ENABLED + ssl->rehandshakeBytes += *len; + if (ssl->rehandshakeBytes >= BYTES_BEFORE_RH_CREDIT) { + if (ssl->rehandshakeCount < 0x8000) { + /* Don't increment if disabled (-1) */ + if (ssl->rehandshakeCount >= 0) { + ssl->rehandshakeCount++; + } + } + ssl->rehandshakeBytes = 0; + } +#endif /* SSL_REHANDSHAKES_ENABLED */ + return *len; +} + +/******************************************************************************/ +/* + A helper function for matrixSslGetWritebuf to determine the correct + destination size before allocating an output buffer. + */ +int32 matrixSslGetEncodedSize(ssl_t *ssl, uint32 len) +{ + len += ssl->recordHeadLen; + if (ssl->flags & SSL_FLAGS_WRITE_SECURE) { + len += ssl->enMacSize; +#ifdef USE_TLS_1_1 +/* + If a block cipher is being used TLS 1.1 requires the use + of an explicit IV. This is an extra random block of data + prepended to the plaintext before encryption. Account for + that extra length here. +*/ + if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) && + (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1)) { + len += ssl->enBlockSize; + } + if (ssl->flags & SSL_FLAGS_AEAD_W) { + len += AEAD_TAG_LEN(ssl) + AEAD_NONCE_LEN(ssl); + } +#endif /* USE_TLS_1_1 */ + +#ifdef USE_BEAST_WORKAROUND + if (ssl->bFlags & BFLAG_STOP_BEAST) { + /* Original message less one */ + len += psPadLenPwr2(len - 1 - ssl->recordHeadLen, ssl->enBlockSize); + /* The single byte record overhead */ + len += ssl->recordHeadLen + ssl->enMacSize; + len += psPadLenPwr2(1 + ssl->enMacSize, ssl->enBlockSize); + } else { + len += psPadLenPwr2(len - ssl->recordHeadLen, ssl->enBlockSize); + } +#else + len += psPadLenPwr2(len - ssl->recordHeadLen, ssl->enBlockSize); +#endif + } + return len; +} + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) +/* Second parameter includes handshake header length */ +static int32 addCertFragOverhead(ssl_t *ssl, int32 totalCertLen) +{ + int32 oh = 0; + + /* For each additional record, we'll need a record header and + secureWriteAdditions. Borrowing ssl->fragIndex and ssl->fragTotal */ + ssl->fragTotal = totalCertLen; + ssl->fragIndex = 0; + while (ssl->fragTotal > 0) { + if (ssl->fragIndex == 0) { + /* First one is accounted for below as normal */ + ssl->fragTotal -= ssl->maxPtFrag; + ssl->fragIndex++; + } else { + /* Remember this stage is simply for SSL_FULL test + so just incr totalCertLen to add overhead */ + oh += secureWriteAdditions(ssl, 1); + oh += ssl->recordHeadLen; + if (ssl->fragTotal > (uint32)ssl->maxPtFrag) { + ssl->fragTotal -= ssl->maxPtFrag; + } else { + ssl->fragTotal = 0; + } + } + } + return oh; +} +#endif /* SERVER || CLIENT_AUTH */ +#endif /* ! ONLY_PSK */ + +#ifdef USE_ECC +/* ECDSA signature is two DER INTEGER values. Either integer could result + in the high bit being set which is interpreted as a negative number + unless proceeded by a 0x0 byte. MatrixSSL predicts one of the two will + be negative when creating the empty buffer spot where the signature + will be written. If this guess isn't correct, this function is called + to correct the buffer size */ +static int accountForEcdsaSizeChange(ssl_t *ssl, pkaAfter_t *pka, int real, + unsigned char *sig, psBuf_t *out, int hsMsg) +{ + flightEncode_t *flightMsg; + unsigned char *whereToMoveFrom, *whereToMoveTo, *msgLenLoc; + int howMuchToMove, howFarToMove, msgLen, addOrSub; + int sigSizeChange, newPadLen; + + if (real > pka->user) { + /* ECDSA SIGNATURE IS LONGER THAN DEFAULT */ + addOrSub = 1; + /* Push outbuf backwards */ + sigSizeChange = real - pka->user; + } else { + /* ECDSA SIGNATURE IS SHORTER THAN DEFAULT */ + addOrSub = 0; + /* Pull outbuf forward */ + sigSizeChange = pka->user - real; + } +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + /* Needed somewhere to store the size change for DTLS retransmits */ + ssl->ecdsaSizeChange = real - pka->user; + } +#endif + if (sigSizeChange > 12) { + /* Sanity */ + psTraceIntInfo("ECDSA sig length change too big: %d\n", sigSizeChange); + return MATRIXSSL_ERROR; + } + /* Get the flightEncode for this message early because the + distance to shift things could depend on the padding bytes in + addition to the basic ECDSA mismatch if we are rehandshaking */ + flightMsg = ssl->flightEncode; + while (flightMsg != NULL && flightMsg->hsMsg != hsMsg) { + flightMsg = flightMsg->next; + } + if (flightMsg == NULL) { + return MATRIXSSL_ERROR; + } + + if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) && (ssl->enBlockSize > 1)) { + /* rehandshaking with block cipher */ + msgLen = (flightMsg->messageSize - ssl->recordHeadLen) - + flightMsg->padLen; + if (addOrSub) { + msgLen += sigSizeChange; + } else { + msgLen -= sigSizeChange; + } + newPadLen = psPadLenPwr2(msgLen, ssl->enBlockSize); + flightMsg->padLen = newPadLen; + msgLen += newPadLen + ssl->recordHeadLen; + + if (flightMsg->messageSize >= msgLen) { + howFarToMove = flightMsg->messageSize - msgLen; + } else { + howFarToMove = msgLen - flightMsg->messageSize; + } + } else { + howFarToMove = sigSizeChange; + } + + howMuchToMove = out->end - (pka->outbuf + pka->user); + whereToMoveFrom = pka->outbuf + pka->user; + + if (addOrSub) { + whereToMoveTo = whereToMoveFrom + howFarToMove; + /* enough room to push into? Extra two bytes should already + have been accounted for but this is still nice for sanity */ + if (((out->start + out->size) - out->end) < howFarToMove) { + return MATRIXSSL_ERROR; + } + } else { + whereToMoveTo = whereToMoveFrom - howFarToMove; + } + memmove(whereToMoveTo, whereToMoveFrom, howMuchToMove); + if (addOrSub) { + out->end += howFarToMove; + flightMsg->len += sigSizeChange; + flightMsg->messageSize += howFarToMove; + } else { + out->end -= howFarToMove; + flightMsg->len -= sigSizeChange; + flightMsg->messageSize -= howFarToMove; + } + /* Now put in ECDSA sig */ + memcpy(pka->outbuf, sig, real); + + /* Now update the record message length - We can use the + flightEncode entry to help us find the handshake header + start. The record header len is only 2 bytes behind here... + subtract nonce for AEAD */ + msgLenLoc = flightMsg->start - 2; + msgLen = flightMsg->messageSize - ssl->recordHeadLen; + + if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) && + (ssl->flags & SSL_FLAGS_AEAD_W)) { + msgLenLoc -= AEAD_NONCE_LEN(ssl); + } + + msgLenLoc[0] = msgLen >> 8; + msgLenLoc[1] = msgLen; + + /* Now update the handshake header length with same techique. */ + msgLenLoc = flightMsg->start + 1; /* Skip hsType byte */ + msgLen = flightMsg->len - ssl->hshakeHeadLen; +#ifdef USE_TLS_1_1 + /* Account for explicit IV in TLS_1_1 and above. */ + if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) && + (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1)) { + msgLen -= ssl->enBlockSize; + msgLenLoc += ssl->enBlockSize; + } +#endif + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + /* Will also be a fragment length to update in handshake header. + Only supporting if there is no fragmentation here. The magic + 5 is skipping over the 3 byte length iteself, 2 byte sequence + and 3 byte offset */ + if (memcmp(msgLenLoc, msgLenLoc + 8, 3) != 0) { + psTraceInfo("ERROR: ECDSA SKE DTLS fragmentation unsupported\n"); + return MATRIXSSL_ERROR; + } + } +#endif + + msgLenLoc[0] = msgLen >> 16; + msgLenLoc[1] = msgLen >> 8; + msgLenLoc[2] = msgLen; + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + /* Update the fragLen as well. Sanity test was performed above */ + msgLenLoc[8] = msgLen >> 16; + msgLenLoc[9] = msgLen >> 8; + msgLenLoc[10] = msgLen; + } +#endif + + /* All messages that follow in the flight have to be updated now */ + flightMsg = flightMsg->next; + while (flightMsg != NULL) { + if (addOrSub) { + flightMsg->start += howFarToMove; + if (flightMsg->seqDelay) { + flightMsg->seqDelay += howFarToMove; + } + } else { + flightMsg->start -= howFarToMove; + if (flightMsg->seqDelay) { + flightMsg->seqDelay -= howFarToMove; + } + } + if (flightMsg->hsMsg == SSL_HS_FINISHED) { + /* The finished message has set aside a pointer as well */ + if (addOrSub) { + ssl->delayHsHash += howFarToMove; + } else { + ssl->delayHsHash -= howFarToMove; + } + } + flightMsg = flightMsg->next; + } + return PS_SUCCESS; +} +#endif /* USE_ECC */ + + +#ifdef USE_SERVER_SIDE_SSL +/* The ServerKeyExchange delayed PKA op */ +static int32 nowDoSkePka(ssl_t *ssl, psBuf_t *out) +{ + int32_t rc = PS_SUCCESS; +#ifndef USE_ONLY_PSK_CIPHER_SUITE + pkaAfter_t *pka; +#if defined(USE_ECC_CIPHER_SUITE) || defined(USE_RSA_CIPHER_SUITE) + psPool_t *pkiPool = NULL; +#endif /* USE_ECC_CIPHER_SUITE || USE_RSA_CIPHER_SUITE */ + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (ssl->retransmit) { + /* Was already copied out in writeServerKeyExchange */ + /* Would not expect to see this because pkaAfter.type should + never be set */ + return PS_SUCCESS; + } + } +#endif /* USE_DTLS */ + + /* Always first one. clearPkaAfter will move 1 to 0 if needed */ + pka = &ssl->pkaAfter[0]; + +#ifdef USE_RSA_CIPHER_SUITE + if (pka->type == PKA_AFTER_RSA_SIG_GEN_ELEMENT || + pka->type == PKA_AFTER_RSA_SIG_GEN) { + +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + if ((rc = privRsaEncryptSignedElement(pkiPool, + &ssl->keys->privKey.key.rsa, + pka->inbuf, pka->inlen, pka->outbuf, + ssl->keys->privKey.keysize, pka->data)) < 0) { + if (rc != PS_PENDING) { + psTraceIntInfo("Unable to sign SKE digital element %d\n", + rc); + return MATRIXSSL_ERROR; + } + /* If the result is going directly inline to the output + buffer we unflag 'type' so this function isn't called + again on the way back around. Also, we can safely + free inbuf because it has been copied out */ + psFree(pka->inbuf, ssl->hsPool); pka->inbuf = NULL; + pka->type = 0; + return PS_PENDING; + } + } else { + if ((rc = psRsaEncryptPriv(pkiPool, &ssl->keys->privKey.key.rsa, pka->inbuf, + pka->inlen, pka->outbuf, ssl->keys->privKey.keysize, + pka->data)) < 0) { + if (rc != PS_PENDING) { + psTraceInfo("Unable to sign SERVER_KEY_EXCHANGE message\n"); + return MATRIXSSL_ERROR; + } + /* If the result is going directly inline to the output + buffer we unflag 'type' so this function isn't called + again on the way back around. Also, we can safely free + inbuf becuase it has been copied out */ + psFree(pka->inbuf, ssl->hsPool); pka->inbuf = NULL; + pka->type = 0; + return PS_PENDING; + } + } +#else /* !USE_TLS_1_2 */ + if ((rc = psRsaEncryptPriv(pkiPool, &ssl->keys->privKey.key.rsa, pka->inbuf, + pka->inlen, pka->outbuf, ssl->keys->privKey.keysize, + pka->data)) < 0) { + if (rc != PS_PENDING) { + psTraceInfo("Unable to sign SERVER_KEY_EXCHANGE message\n"); + return MATRIXSSL_ERROR; + } + /* If the result is going directly inline to the output + buffer we unflag 'type' so this function isn't called + again on the way back around */ + psFree(pka->inbuf, ssl->hsPool); pka->inbuf = NULL; + pka->type = 0; + return PS_PENDING; + } +#endif /* USE_TLS_1_2 */ + + +#ifdef USE_DTLS + if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 0)) { + /* Using existing ckeMsg and ckeSize that clients are using but + this should be totally fine on the server side because it is + freed at FINISHED parse */ + ssl->ckeSize = ssl->keys->privKey.keysize; + if ((ssl->ckeMsg = psMalloc(ssl->hsPool, ssl->ckeSize)) == NULL) { + psTraceInfo("Memory allocation error ckeMsg\n"); + return PS_MEM_FAIL; + } + memcpy(ssl->ckeMsg, pka->outbuf, ssl->ckeSize); + } +#endif /* USE_DTLS */ + + clearPkaAfter(ssl); /* Blocking success case */ + } +#endif /* USE_RSA_CIPHER_SUITE */ + +#ifdef USE_ECC_CIPHER_SUITE + if (pka->type == PKA_AFTER_ECDSA_SIG_GEN) { + + int32_t err; + uint16_t len; + /* New temp location for ECDSA sig which can be one len byte different + than what we originally calculated (pka->user is holding) */ + unsigned char *tmpEcdsa; + + /* Only need to allocate 1 larger because 1 has already been added + at creation */ + if ((tmpEcdsa = psMalloc(ssl->hsPool, pka->user + 1)) == NULL) { + return PS_MEM_FAIL; + } + + len = pka->user + 1; + +#ifdef USE_DTLS + ssl->ecdsaSizeChange = 0; +#endif + if ((err = psEccDsaSign(pkiPool, &ssl->keys->privKey.key.ecc, + pka->inbuf, pka->inlen, tmpEcdsa, &len, 1, pka->data)) != 0) { + /* DO NOT close pool (unless failed). It is kept around in + pkaCmdInfo for result until finished and is closed there */ + if (err != PS_PENDING) { + psFree(tmpEcdsa, ssl->hsPool); + return MATRIXSSL_ERROR; + } + + /* ASYNC: tmpEcdsa is not saved as output location so correct to + free here */ + psFree(tmpEcdsa, ssl->hsPool); + return PS_PENDING; + } + if (len != pka->user) { + /* Confirmed ECDSA is not default size */ + if (accountForEcdsaSizeChange(ssl, pka, len, tmpEcdsa, out, + SSL_HS_SERVER_KEY_EXCHANGE) < 0) { + clearPkaAfter(ssl); + psFree(tmpEcdsa, ssl->hsPool); + return MATRIXSSL_ERROR; + } + } else { + memcpy(pka->outbuf, tmpEcdsa, pka->user); + } + psFree(tmpEcdsa, ssl->hsPool); + +#ifdef USE_DTLS + if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 0)) { + /* ECC signatures have random bytes so need to save aside for + retransmit cases. Using existing ckeMsg and ckeSize that + clients are using but this should be totally fine on the + server side because it is freed at FINISHED parse */ + ssl->ckeSize = len; + if ((ssl->ckeMsg = psMalloc(ssl->hsPool, ssl->ckeSize)) == NULL) { + psTraceInfo("Memory allocation error ckeMsg\n"); + return PS_MEM_FAIL; + } + memcpy(ssl->ckeMsg, pka->outbuf, ssl->ckeSize); + } +#endif /* USE_DTLS */ + + clearPkaAfter(ssl); + } +#endif /* USE_ECC_CIPHER_SUITE */ +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + return rc; +} +#endif /* USE_SERVER_SIDE_SSL */ + + +#ifdef USE_CLIENT_SIDE_SSL + +/*********/ +/* A test feature to allow clients to reuse the CKE RSA encryption output + for each connection to remove the CPU overhead of pubkey operation when + testing against high performance servers. The same premaster must be + used each time as well though. */ +//#define REUSE_CKE +#ifdef REUSE_CKE +#pragma message("!! DO NOT USE REUSE_CKE IN PRODUCTION !!") +static char g_reusePremaster[SSL_HS_RSA_PREMASTER_SIZE] = { 0 }; +static int16 g_reusePreLen = 0; +static char g_reuseRSAEncrypt[512] = { 0 }; /* Encrypted pre-master */ +static int16 g_reuseRSALen = 0; +static psRsaKey_t g_reuseRSAKey; +#endif +/*********/ + +/* The ClientKeyExchange delayed PKA ops */ +static int32 nowDoCkePka(ssl_t *ssl) +{ + int32 rc = PS_FAIL; + pkaAfter_t *pka; +#ifdef REQUIRE_DH_PARAMS + uint8_t cleared = 0; +#endif + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (ssl->retransmit) { + /* Was already copied out in writeClientKeyExchange */ + /* In fact, would not expect to hit this because pkaAfter.type + should never be set to re-enter this routine */ + psAssert(0); + return PS_SUCCESS; + } + } +#endif /* USE_DTLS */ + + /* Always the first one. clearPkaAfter will move 1 to 0 if needed */ + pka = &ssl->pkaAfter[0]; + + /* The flags logic is used for the cipher type and then the pkaAfter.type + value is validated */ +#ifdef USE_DHE_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_DHE_KEY_EXCH) { + + #ifdef USE_ECC_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ECC_CIPHER) { + /* ECDHE suite */ + psAssert(pka->outbuf == ssl->sec.premaster); + if (pka->type == PKA_AFTER_ECDH_SECRET_GEN) { + if ((rc = psEccGenSharedSecret(ssl->sec.eccDhKeyPool, + ssl->sec.eccKeyPriv, ssl->sec.eccKeyPub, + ssl->sec.premaster, &ssl->sec.premasterSize, + pka->data)) < 0) { + if (rc != PS_PENDING) { + psFree(ssl->sec.premaster, ssl->hsPool); + ssl->sec.premaster = NULL; + return MATRIXSSL_ERROR; + } + pka->type = PKA_AFTER_ECDH_SECRET_GEN_DONE; /* Bypass next*/ + return rc; + } + } + clearPkaAfter(ssl); + psEccDeleteKey(&ssl->sec.eccKeyPub); + psEccDeleteKey(&ssl->sec.eccKeyPriv); + } else { + #endif /* USE_ECC_CIPHER_SUITE */ + + #ifdef REQUIRE_DH_PARAMS + + psAssert(pka->outbuf == ssl->sec.premaster); + psAssert(pka->type == PKA_AFTER_DH_KEY_GEN); + + if ((rc = psDhGenSharedSecret(ssl->sec.dhKeyPool, + ssl->sec.dhKeyPriv, ssl->sec.dhKeyPub, ssl->sec.dhP, + ssl->sec.dhPLen, ssl->sec.premaster, + &ssl->sec.premasterSize, pka->data)) < 0) { + + if (rc != PS_PENDING) { + return MATRIXSSL_ERROR; + } + return rc; + } + + #ifdef USE_PSK_CIPHER_SUITE + /* DHE PSK ciphers make dual use of the pkaAfter storage */ + if (!(ssl->flags & SSL_FLAGS_PSK_CIPHER)) { + if (cleared == 0) { + clearPkaAfter(ssl); cleared = 1; + } + } + #else + if (cleared == 0) { + clearPkaAfter(ssl); cleared = 1; + } + #endif + + psFree(ssl->sec.dhP, ssl->hsPool); + ssl->sec.dhP = NULL; ssl->sec.dhPLen = 0; + psDhClearKey(ssl->sec.dhKeyPub); + psFree(ssl->sec.dhKeyPub, ssl->hsPool); + ssl->sec.dhKeyPub = NULL; + psDhClearKey(ssl->sec.dhKeyPriv); + psFree(ssl->sec.dhKeyPriv, ssl->sec.dhKeyPool); + ssl->sec.dhKeyPriv = NULL; + + #ifdef USE_PSK_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + + unsigned char *pskKey; + uint8_t pskIdLen; + + /* RFC4279: The premaster secret is formed as follows. + First, perform the Diffie-Hellman computation in the same way + as for other Diffie-Hellman-based ciphersuites. Let Z be the + value produced by this computation. Concatenate a uint16 + containing the length of Z (in octets), Z itself, a uint16 + containing the length of the PSK (in octets), and the PSK itself. + + The pskId is held in the pkaAfter inbuf */ + matrixSslPskGetKey(ssl, pka->inbuf, pka->inlen, &pskKey, + &pskIdLen); + if (pskKey == NULL) { + psFree(ssl->sec.premaster, ssl->hsPool); + ssl->sec.premaster = NULL; + return MATRIXSSL_ERROR; + } + /* Need to prepend a uint16 length to the premaster key. */ + memmove(&ssl->sec.premaster[2], ssl->sec.premaster, + ssl->sec.premasterSize); + ssl->sec.premaster[0] = (ssl->sec.premasterSize & 0xFF00) >> 8; + ssl->sec.premaster[1] = (ssl->sec.premasterSize & 0xFF); + /* Next, uint16 length of PSK and key itself */ + ssl->sec.premaster[ssl->sec.premasterSize + 2] = + (pskIdLen & 0xFF00) >> 8; + ssl->sec.premaster[ssl->sec.premasterSize + 3] = + (pskIdLen & 0xFF); + memcpy(&ssl->sec.premaster[ssl->sec.premasterSize + 4], pskKey, + pskIdLen); + /* Lastly, adjust the premasterSize */ + ssl->sec.premasterSize += pskIdLen + 4; + } + if (cleared == 0) { + clearPkaAfter(ssl); cleared = 1; /* Standard and PSK DHE */ + } + #else + if (cleared == 0) { + clearPkaAfter(ssl); cleared = 1; /* Standard DHE, PSK disabled*/ + } + #endif /* PSK */ + + #endif /* REQUIRE_DH_PARAMS */ + + #ifdef USE_ECC_CIPHER_SUITE + } + #endif /* USE_ECC_CIPHER_SUITE */ + + } else { +#endif /* USE_DHE_CIPHER_SUITE */ + + /* Else case for non-DHE, which still could mean ECDH static or + standard RSA */ + #ifdef USE_ECC_CIPHER_SUITE + if (ssl->cipher->type == CS_ECDH_ECDSA || + ssl->cipher->type == CS_ECDH_RSA) { + + /* This case is unique becuase it has two PKA ops for a single CKE + message. The key generation is done and then secret is + generated. The 'type' will change after the first one */ + + if (pka->type == PKA_AFTER_ECDH_KEY_GEN) { + if (psEccNewKey(pka->pool, &ssl->sec.eccKeyPriv, + ssl->sec.cert->publicKey.key.ecc.curve) < 0) { + return PS_MEM_FAIL; + } + if ((rc = matrixSslGenEphemeralEcKey(ssl->keys, + ssl->sec.eccKeyPriv, + ssl->sec.cert->publicKey.key.ecc.curve, + pka->data)) < 0) { + + if (rc == PS_PENDING) { + return rc; + } + psEccDeleteKey(&ssl->sec.eccKeyPriv); + psTraceInfo("GenEphemeralEcc failed\n"); + ssl->err = SSL_ALERT_INTERNAL_ERROR; + return MATRIXSSL_ERROR; + } + + /* key len must be valid */ + if (psEccX963ExportKey(ssl->hsPool, ssl->sec.eccKeyPriv, + pka->outbuf, &pka->user) < 0) { + psTraceInfo("psEccX963ExportKey in CKE failed\n"); + return MATRIXSSL_ERROR; + } + /* Does written len equal stated len? */ + psAssert(pka->user == (int32)*(pka->outbuf - 1)); + + #ifdef USE_DTLS + /* Save aside for retransmits */ + if (ssl->flags & SSL_FLAGS_DTLS) { + ssl->ckeSize = pka->user + 1; /* The size is wrote first */ + ssl->ckeMsg = psMalloc(ssl->hsPool, ssl->ckeSize); + if (ssl->ckeMsg == NULL) { + return SSL_MEM_ERROR; + } + ssl->ckeMsg[0] = pka->user & 0xFF; + memcpy(ssl->ckeMsg + 1, pka->outbuf, ssl->ckeSize - 1); + } + #endif /* USE_DTLS */ + + /* NOTE: Do not clearPkaAfter. We will just use the current + context since there is no special state data required + for this next EccGenSharedSecret call. We don't clear + because the certificateVerify info might be sitting in the + second pkaAfter slot */ + /* Set for the next operation now using same pkaAfter slot */ + pka->type = PKA_AFTER_ECDH_SECRET_GEN; + } + + /* Second PKA operation */ + if (pka->type == PKA_AFTER_ECDH_SECRET_GEN) { + + if ((rc = psEccGenSharedSecret(pka->pool, + ssl->sec.eccKeyPriv, &ssl->sec.cert->publicKey.key.ecc, + ssl->sec.premaster, &ssl->sec.premasterSize, + pka->data)) < 0) { + if (rc == PS_PENDING) { + pka->type = PKA_AFTER_ECDH_SECRET_GEN_DONE; /* Bypass */ + return rc; + } + psFree(ssl->sec.premaster, ssl->hsPool); + ssl->sec.premaster = NULL; + return MATRIXSSL_ERROR; + } + } + /* Successfully completed both PKA operations and key write */ + psEccDeleteKey(&ssl->sec.eccKeyPriv); + clearPkaAfter(ssl); + + } else { + #endif /* USE_ECC_CIPHER_SUITE */ + + #ifdef USE_RSA_CIPHER_SUITE + /* Standard RSA suite entry point */ + psAssert(pka->type == PKA_AFTER_RSA_ENCRYPT); + + #ifdef REUSE_CKE + if (g_reusePreLen) { + if (psRsaCmpPubKey(&g_reuseRSAKey, &ssl->sec.cert->publicKey.key.rsa) == 0) { + memcpy(ssl->sec.premaster, g_reusePremaster, g_reusePreLen); + memcpy(pka->outbuf, g_reuseRSAEncrypt, g_reuseRSALen); + } else { + memzero_s(g_reusePremaster, g_reusePreLen); + g_reusePreLen = 0; + memzero_s(g_reuseRSAEncrypt, g_reuseRSALen); + g_reuseRSALen = 0; + psRsaClearKey(&g_reuseRSAKey); + } + } else { + #endif + /* pkaAfter.user is buffer len */ + if ((rc = psRsaEncryptPub(pka->pool, + &ssl->sec.cert->publicKey.key.rsa, + ssl->sec.premaster, ssl->sec.premasterSize, pka->outbuf, + pka->user, pka->data)) < 0) { + if (rc == PS_PENDING) { + /* For these ClientKeyExchange paths, we do want to come + back through nowDoCkePka for a double pass so each + case can manage its own pkaAfter and to make sure + psX509FreeCert and sslCreateKeys() are hit below. */ + return rc; + } + psTraceIntInfo("psRsaEncryptPub in CKE failed %d\n", rc); + return MATRIXSSL_ERROR; + } + #ifdef REUSE_CKE + } + if (g_reusePreLen == 0) { + printf("REUSE_CKE ENABLED!! NOT FOR PRODUCTION USE\n"); + g_reusePreLen = ssl->sec.premasterSize; + g_reuseRSALen = psRsaSize(&ssl->sec.cert->publicKey.key.rsa); + memcpy(g_reusePremaster, ssl->sec.premaster, g_reusePreLen); + memcpy(g_reuseRSAEncrypt, pka->outbuf, g_reuseRSALen); + /* TODO this key is allocated once and leaked */ + if (psRsaCopyKey(&g_reuseRSAKey, &ssl->sec.cert->publicKey.key.rsa) < 0) { + return MATRIXSSL_ERROR; + } + } + #endif + /* RSA closed the pool on second pass */ + /* CHANGE NOTE: This comment looks specific to async and this + pool is not being closed in clearPkaAfter if set to NULL here + on the normal case. So commenting this line out for now */ + //pka->pool = NULL; + #ifdef USE_DTLS + /* This was first pass for DH ckex so set it aside */ + + if (ssl->flags & SSL_FLAGS_DTLS) { + + ssl->ckeMsg = psMalloc(ssl->hsPool, pka->user); + if (ssl->ckeMsg == NULL) { + return SSL_MEM_ERROR; + } + ssl->ckeSize = pka->user; + memcpy(ssl->ckeMsg, pka->outbuf, pka->user); + } + #endif /* USE_DTLS */ + clearPkaAfter(ssl); +#else /* RSA is the 'default' so if that didn't get hit there is a problem */ + psTraceInfo("There is no handler for writeClientKeyExchange. ERROR\n"); + return MATRIXSSL_ERROR; +#endif /* USE_RSA_CIPHER_SUITE */ + + + #ifdef USE_ECC_CIPHER_SUITE + } + #endif /* USE_ECC_CIPHER_SUITE */ + +#ifdef USE_DHE_CIPHER_SUITE + } +#endif /* USE_DHE_CIPHER_SUITE */ + +/* + Now that we've got the premaster secret, derive the various symmetric + keys using it and the client and server random values. + + However, if extended_master_secret is being used we must delay the + master secret creation until the CKE handshake message has been added + to the rolling handshake hash. Key generation will be done in encryptRecord +*/ + if (ssl->extFlags.extended_master_secret == 0) { + if ((rc = sslCreateKeys(ssl)) < 0) { + return rc; + } + } + +#ifdef USE_DTLS + /* Can't free cert in DTLS in case of retransmit */ + if (ssl->flags & SSL_FLAGS_DTLS) { + return rc; + } +#endif + +#ifndef USE_ONLY_PSK_CIPHER_SUITE + /* This used to be freed in writeFinished but had to stay around longer + for key material in PKA after ops */ + if (ssl->sec.cert) { + psX509FreeCert(ssl->sec.cert); + ssl->sec.cert = NULL; + } +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + + return rc; +} +#endif /* USE_CLIENT_SIDE_SSL */ + +/******************************************************************************/ +/* + We indicate to the caller through return codes in sslDecode when we need + to write internal data to the remote host. The caller will call this + function to generate a message appropriate to our state. +*/ +int32 sslEncodeResponse(ssl_t *ssl, psBuf_t *out, uint32 *requiredLen) +{ + int32 messageSize; + int32 rc = MATRIXSSL_ERROR; + uint32 alertReqLen; +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) + int32 i; +#ifndef USE_ONLY_PSK_CIPHER_SUITE + psX509Cert_t *cert; +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ +#endif /* USE_SERVER_SIDE_SSL */ + +#if defined(USE_SERVER_SIDE_SSL) + int32 extSize; + int32 stotalCertLen; +#endif + +#ifdef USE_CLIENT_SIDE_SSL + int32 ckeSize; +#ifdef USE_CLIENT_AUTH + int32 ctotalCertLen; +#endif +#endif /* USE_CLIENT_SIDE_SSL */ + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#if defined(USE_SERVER_SIDE_SSL) && defined(USE_CLIENT_AUTH) + psX509Cert_t *CAcert; + int32 certCount = 0, certReqLen = 0, CAcertLen = 0; +#endif /* USE_SERVER_SIDE_SSL && USE_CLIENT_AUTH */ +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ +#if defined(USE_SERVER_SIDE_SSL) && defined(USE_DHE_CIPHER_SUITE) + int32 srvKeyExLen; +#endif /* USE_SERVER_SIDE_SSL && USE_DHE_CIPHER_SUITE */ + +#ifdef USE_DTLS + sslSessOpts_t options; + memset(&options, 0x0, sizeof(sslSessOpts_t)); +#endif + +/* + We may be trying to encode an alert response if there is an error marked + on the connection. +*/ + if (ssl->err != SSL_ALERT_NONE) { + rc = writeAlert(ssl, SSL_ALERT_LEVEL_FATAL, (unsigned char)ssl->err, + out, requiredLen); + if (rc == MATRIXSSL_ERROR) { + /* We'll be returning an error code from this call so the typical + alert SEND_RESPONSE handler will not be hit to set this error + flag for us. We do it ourself to prevent further session use + and the result of this error will be that the connection is + silently closed rather than this alert making it out */ + ssl->flags |= SSL_FLAGS_ERROR; + } +#ifdef USE_SERVER_SIDE_SSL +/* + Writing a fatal alert on this session. Let's remove this client from + the session table as a precaution. Additionally, if this alert is + happening mid-handshake the master secret might not even be valid +*/ + if (ssl->flags & SSL_FLAGS_SERVER) { + matrixClearSession(ssl, 1); + } +#endif /* USE_SERVER_SIDE_SSL */ + return rc; + } + + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + /* This function takes care of writing out entire flights so we know + to capture the current MSN and Epoch as the resends so that a + resend of this flight will contain the identical MSN and Epoch + for each resent message. */ + ssl->resendMsn = ssl->msn; + ssl->resendEpoch[0] = ssl->epoch[0]; + ssl->resendEpoch[1] = ssl->epoch[1]; + } +#endif /* USE_DTLS */ + +/* + We encode a set of response messages based on our current state + We have to pre-verify the size of the outgoing buffer against + all the messages to make the routine transactional. If the first + write succeeds and the second fails because of size, we cannot + rollback the state of the cipher and MAC. +*/ + switch (ssl->hsState) { +/* + If we're waiting for the ClientKeyExchange message, then we need to + send the messages that would prompt that result on the client +*/ +#ifdef USE_SERVER_SIDE_SSL + case SSL_HS_CLIENT_KEY_EXCHANGE: +#ifdef USE_CLIENT_AUTH +/* + This message is also suitable for the client authentication case + where the server is in the CERTIFICATE state. +*/ + case SSL_HS_CERTIFICATE: +/* + Account for the certificateRequest message if client auth is on. + First two bytes are the certificate_types member (rsa_sign (1) and + ecdsa_sign (64) are supported). Remainder of length is the + list of BER encoded distinguished names this server is + willing to accept children certificates of. If there + are no valid CAs to work with, client auth can't be done. +*/ +#ifndef USE_ONLY_PSK_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_CLIENT_AUTH) { + CAcert = ssl->keys->CAcerts; + certCount = certReqLen = CAcertLen = 0; +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + /* TLS 1.2 has a SigAndHashAlgorithm member in certRequest */ + certReqLen += 2; +#ifdef USE_ECC +#ifdef USE_SHA384 + certReqLen += 6; +#else + certReqLen += 4; +#endif /* USE_SHA */ +#endif /* USE_ECC */ +#ifdef USE_RSA +#ifdef USE_SHA384 + certReqLen += 6; +#else + certReqLen += 4; +#endif /* USE_SHA */ +#endif /* USE_RSA */ + } +#endif /* USE_TLS_1_2 */ + + if (CAcert) { + certReqLen += 4 + ssl->recordHeadLen + ssl->hshakeHeadLen; +#ifdef USE_ECC + certReqLen += 1; /* Add on ECDSA_SIGN support */ +#endif /* USE_ECC */ + while (CAcert) { + certReqLen += 2; /* 2 bytes for specifying each cert len */ + CAcertLen += CAcert->subject.dnencLen; + CAcert = CAcert->next; + certCount++; + } +#ifdef USE_DTLS + //if (ssl->flags & SSL_FLAGS_DTLS) { + // if (certReqLen + CAcertLen > ssl->pmtu) { + // /* Decrease the CA count or contact support if a + // needed requirement */ + // psTraceDtls("ERROR: No fragmentation support for "); + // psTraceDtls("CERTIFICATE_REQUEST message/n"); + // return MATRIXSSL_ERROR; + // } + //} +#endif + } else { +#ifdef SERVER_CAN_SEND_EMPTY_CERT_REQUEST + certReqLen += 4 + ssl->recordHeadLen + ssl->hshakeHeadLen; +#ifdef USE_ECC + certReqLen += 1; /* Add on ECDSA_SIGN support */ +#endif /* USE_ECC */ +#else + psTraceInfo("No server CAs loaded for client authentication\n"); + return MATRIXSSL_ERROR; +#endif + } + } +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ +#endif /* USE_CLIENT_AUTH */ + +#ifdef USE_DHE_CIPHER_SUITE + srvKeyExLen = 0; + if (ssl->flags & SSL_FLAGS_DHE_KEY_EXCH) { +#ifdef USE_ECC_CIPHER_SUITE + if (!(ssl->flags & SSL_FLAGS_ECC_CIPHER)) { +#endif /* USE_ECC_CIPHER_SUITE */ +#ifdef REQUIRE_DH_PARAMS +/* + Extract p and g parameters from key to session context. Going + to send these in the SERVER_KEY_EXCHANGE message. This is + wrapped in a test of whether or not the values have already + been extracted because an SSL_FULL scenario below will cause + this code to be executed again with a larger buffer. +*/ + if (ssl->sec.dhPLen == 0 && ssl->sec.dhP == NULL) { + if (psDhExportParameters(ssl->hsPool, &ssl->keys->dhParams, + &ssl->sec.dhP, &ssl->sec.dhPLen, + &ssl->sec.dhG, &ssl->sec.dhGLen) < 0) { + return MATRIXSSL_ERROR; + } + } +#endif +#ifdef USE_ECC_CIPHER_SUITE + } +#endif /* USE_ECC_CIPHER_SUITE */ +#ifdef USE_ANON_DH_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ANON_CIPHER) { +/* + If we are an anonymous cipher, we don't send the certificate. + The messages are simply SERVER_HELLO, SERVER_KEY_EXCHANGE, + and SERVER_HELLO_DONE +*/ + stotalCertLen = 0; + + srvKeyExLen = ssl->sec.dhPLen + 2 + ssl->sec.dhGLen + 2 + + ssl->sec.dhKeyPriv->size + 2; + +#ifdef USE_PSK_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { +/* + * struct { + * select (KeyExchangeAlgorithm) { + * case diffie_hellman_psk: * NEW * + * opaque psk_identity_hint<0..2^16-1>; + * ServerDHParams params; + * }; + * } ServerKeyExchange; + */ + if (SSL_PSK_MAX_HINT_SIZE > 0) { + srvKeyExLen += SSL_PSK_MAX_HINT_SIZE + 2; + } + } +#endif /* USE_PSK_CIPHER_SUITE */ + + messageSize = + 3 * ssl->recordHeadLen + + 3 * ssl->hshakeHeadLen + + 38 + SSL_MAX_SESSION_ID_SIZE + /* server hello */ + srvKeyExLen; /* server key exchange */ + + messageSize += secureWriteAdditions(ssl, 3); + } else { +#endif /* USE_ANON_DH_CIPHER_SUITE */ + +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ECC_CIPHER) { + if (ssl->flags & SSL_FLAGS_DHE_WITH_RSA) { +/* + Magic 7: 1byte ECCurveType named, 2bytes NamedCurve id + 1 byte pub key len, 2 byte privkeysize len, + 1 byte 0x04 inside the eccKey itself +*/ + srvKeyExLen = (ssl->sec.eccKeyPriv->curve->size * 2) + 7 + + ssl->keys->privKey.keysize; + } else if (ssl->flags & SSL_FLAGS_DHE_WITH_DSA) { + /* ExportKey plus signature */ + srvKeyExLen = (ssl->sec.eccKeyPriv->curve->size * 2) + 7 + + 6 + /* 6 = 2 ASN_SEQ, 4 ASN_BIG */ + ssl->keys->privKey.keysize; + if (ssl->keys->privKey.keysize >= 128) { + srvKeyExLen += 1; /* Extra len byte in ASN.1 sig */ + } + /* NEGATIVE ECDSA - For purposes of SSL_FULL we + add 2 extra bytes to account for the two possible + 0x0 bytes in signature */ + srvKeyExLen += 2; + } +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + srvKeyExLen += 2; /* hashSigAlg */ + } +#endif /* USE_TLS_1_2 */ + } else { +#endif /* USE_ECC_CIPHER_SUITE */ +#ifdef REQUIRE_DH_PARAMS +/* + The AUTH versions of the DHE cipher suites include a + signature value in the SERVER_KEY_EXCHANGE message. + Account for that length here. Also, the CERTIFICATE + message is sent in this flight as well for normal + authentication. +*/ + srvKeyExLen = ssl->sec.dhPLen + 2 + ssl->sec.dhGLen + 2 + + ssl->sec.dhKeyPriv->size + 2 + + ssl->keys->privKey.keysize + 2; +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + srvKeyExLen += 2; /* hashSigAlg */ + } +#endif /* USE_TLS_1_2 */ + +#endif /* REQUIRE_DH_PARAMS */ +#ifdef USE_ECC_CIPHER_SUITE + } +#endif /* USE_ECC_CIPHER_SUITE */ + stotalCertLen = i = 0; +#ifndef USE_ONLY_PSK_CIPHER_SUITE + cert = ssl->keys->cert; + for (i = 0; cert != NULL; i++) { + stotalCertLen += cert->binLen; + cert = cert->next; + } + /* Are we going to have to fragment the CERTIFICATE message? */ + if ((stotalCertLen + 3 + (i * 3) + ssl->hshakeHeadLen) > + ssl->maxPtFrag) { + stotalCertLen += addCertFragOverhead(ssl, + stotalCertLen + 3 + (i * 3) + ssl->hshakeHeadLen); + } +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ + messageSize = + 4 * ssl->recordHeadLen + + 4 * ssl->hshakeHeadLen + + 38 + SSL_MAX_SESSION_ID_SIZE + /* server hello */ + srvKeyExLen + /* server key exchange */ + 3 + (i * 3) + stotalCertLen; /* certificate */ +#ifdef USE_CLIENT_AUTH +#ifndef USE_ONLY_PSK_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_CLIENT_AUTH) { + /* Are we going to have to fragment the + CERTIFICATE_REQUEST message? */ + if (certReqLen + CAcertLen > ssl->maxPtFrag) { + certReqLen += addCertFragOverhead(ssl, + certReqLen + CAcertLen); + } + /* Account for the CertificateRequest message */ + messageSize += certReqLen + CAcertLen; + messageSize += secureWriteAdditions(ssl, 1); + } +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ +#endif /* USE_CLIENT_AUTH */ + messageSize += secureWriteAdditions(ssl, 4); +#ifdef USE_ANON_DH_CIPHER_SUITE + } +#endif /* USE_ANON_DH_CIPHER_SUITE */ + } else { +#endif /* USE_DHE_CIPHER_SUITE */ +/* + This is the entry point for a server encoding the first flight + of a non-DH, non-client-auth handshake. +*/ + messageSize = stotalCertLen = 0; +#ifdef USE_PSK_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { +/* + Omit the CERTIFICATE message but (possibly) including the + SERVER_KEY_EXCHANGE. +*/ + messageSize = + 2 * ssl->recordHeadLen + + 2 * ssl->hshakeHeadLen + + 38 + SSL_MAX_SESSION_ID_SIZE; /* server hello */ + if (SSL_PSK_MAX_HINT_SIZE > 0) { + messageSize += 2 + SSL_PSK_MAX_HINT_SIZE + /* SKE */ + ssl->recordHeadLen + ssl->hshakeHeadLen; + } else { +/* + Assuming 3 messages below when only two are going to exist +*/ + messageSize -= secureWriteAdditions(ssl, 1); + } + } else { +#endif +#ifndef USE_ONLY_PSK_CIPHER_SUITE + cert = ssl->keys->cert; + for (i = 0; cert != NULL; i++) { + psAssert(cert->unparsedBin != NULL); + stotalCertLen += cert->binLen; + cert = cert->next; + } + /* Are we going to have to fragment the CERTIFICATE message? */ + if ((stotalCertLen + 3 + (i * 3) + ssl->hshakeHeadLen) > + ssl->maxPtFrag) { + stotalCertLen += addCertFragOverhead(ssl, + stotalCertLen + 3 + (i * 3) + ssl->hshakeHeadLen); + } + messageSize = + 3 * ssl->recordHeadLen + + 3 * ssl->hshakeHeadLen + + 38 + SSL_MAX_SESSION_ID_SIZE + /* server hello */ + 3 + (i * 3) + stotalCertLen; /* certificate */ +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ +#ifdef USE_PSK_CIPHER_SUITE + } +#endif /* USE_PSK_CIPHER_SUITE */ + +#ifdef USE_CLIENT_AUTH +#ifndef USE_ONLY_PSK_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_CLIENT_AUTH) { + /* Are we going to have to fragment the CERTIFICATE_REQUEST + message? This is the SSL fragment level */ + if (certReqLen + CAcertLen > ssl->maxPtFrag) { + certReqLen += addCertFragOverhead(ssl, + certReqLen + CAcertLen); + } + messageSize += certReqLen + CAcertLen; /* certificate request */ + messageSize += secureWriteAdditions(ssl, 1); +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + /* DTLS pmtu CERTIFICATE_REQUEST */ + messageSize += (MAX_FRAGMENTS - 1) * + (ssl->recordHeadLen + ssl->hshakeHeadLen); + if (ssl->flags & SSL_FLAGS_WRITE_SECURE) { + messageSize += secureWriteAdditions(ssl, + MAX_FRAGMENTS - 1); + } + } +#endif /* USE_DTLS */ + } +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ +#endif /* USE_CLIENT_AUTH */ + + messageSize += secureWriteAdditions(ssl, 3); + +#ifdef USE_DHE_CIPHER_SUITE + } +#endif /* USE_DHE_CIPHER_SUITE */ + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { +/* + If DTLS, make sure the max fragment overhead is accounted for + on any flight containing the CERTIFICATE message. If + SSL_FULL is hit mid-flight creation, the updates that happen + on the handshake hash on that first pass will really mess us up +*/ + messageSize += (MAX_FRAGMENTS - 1) * + (ssl->recordHeadLen + ssl->hshakeHeadLen); + if (ssl->flags & SSL_FLAGS_WRITE_SECURE) { + messageSize += secureWriteAdditions(ssl, MAX_FRAGMENTS - 1); + } + } +#endif /* USE_DTLS */ + +/* + Add extensions +*/ + extSize = 0; /* Two byte total length for all extensions */ + if (ssl->maxPtFrag < SSL_MAX_PLAINTEXT_LEN) { + extSize = 2; + messageSize += 5; /* 2 type, 2 length, 1 value */ + } + + if (ssl->extFlags.truncated_hmac) { + extSize = 2; + messageSize += 4; /* 2 type, 2 length, 0 value */ + } + + if (ssl->extFlags.extended_master_secret) { + extSize = 2; + messageSize += 4; /* 2 type, 2 length, 0 value */ + } + +#ifdef USE_OCSP + /* If we are sending the OCSP status_request extension, we are also + sending the CERTIFICATE_STATUS handshake message */ + if (ssl->extFlags.status_request) { + extSize = 2; + messageSize += 4; /* 2 type, 2 length, 0 value */ + + /* And the handshake message oh. 1 type, 3 len, x OCSPResponse + The status_request flag will only have been set if a + ssl->keys->OCSPResponseBuf was present during extension parse */ + messageSize += ssl->hshakeHeadLen + ssl->recordHeadLen + 4 + + ssl->keys->OCSPResponseBufLen; + messageSize += secureWriteAdditions(ssl, 1); + } +#endif + +#ifdef USE_STATELESS_SESSION_TICKETS + if (ssl->sid && + ssl->sid->sessionTicketState == SESS_TICKET_STATE_RECVD_EXT) { + extSize = 2; + messageSize += 4; /* 2 type, 2 length, 0 value */ + } +#endif + if (ssl->extFlags.sni) { + extSize = 2; + messageSize += 4; + } + +#ifdef USE_ALPN + if (ssl->alpnLen) { + extSize = 2; + messageSize += 6 + 1 + ssl->alpnLen; /* 6 type/len + 1 len + data */ + } +#endif + + +#ifdef ENABLE_SECURE_REHANDSHAKES +/* + The RenegotiationInfo extension lengths are well known +*/ + if (ssl->secureRenegotiationFlag == PS_TRUE && + ssl->myVerifyDataLen == 0) { + extSize = 2; + messageSize += 5; /* ff 01 00 01 00 */ + } else if (ssl->secureRenegotiationFlag == PS_TRUE && + ssl->myVerifyDataLen > 0) { + extSize = 2; + messageSize += 5 + ssl->myVerifyDataLen + + ssl->peerVerifyDataLen; /* 2 for total len, 5 for type+len */ + } +#endif /* ENABLE_SECURE_REHANDSHAKES */ + +#ifdef USE_ECC_CIPHER_SUITE +/* + Server Hello ECC extension +*/ + if (ssl->flags & SSL_FLAGS_ECC_CIPHER) { + extSize = 2; + /* EXT_ELLIPTIC_POINTS - hardcoded to 'uncompressed' support */ + messageSize += 6; /* 00 0B 00 02 01 00 */ + } +#endif /* USE_ECC_CIPHER_SUITE */ +/* + Done with extensions. If had some, add the two byte total length +*/ + messageSize += extSize; + + if ((out->buf + out->size) - out->end < messageSize) { + *requiredLen = messageSize; + return SSL_FULL; + } +/* + Message size complete. Begin the flight write +*/ + rc = writeServerHello(ssl, out); + +#ifdef USE_DHE_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_DHE_KEY_EXCH) { +#ifndef USE_ONLY_PSK_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_DHE_WITH_RSA || + ssl->flags & SSL_FLAGS_DHE_WITH_DSA) { + if (rc == MATRIXSSL_SUCCESS) { + rc = writeCertificate(ssl, out, 1); + } +#ifdef USE_OCSP + if (rc == MATRIXSSL_SUCCESS) { + rc = writeCertificateStatus(ssl, out); + } +#endif + } +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + if (rc == MATRIXSSL_SUCCESS) { +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ECC_CIPHER) { + rc = writeServerKeyExchange(ssl, out, 0, NULL, 0, NULL); + } else { +#endif /* USE_ECC_CIPHER_SUITE */ +#ifdef REQUIRE_DH_PARAMS + rc = writeServerKeyExchange(ssl, out, ssl->sec.dhPLen, + ssl->sec.dhP, ssl->sec.dhGLen, ssl->sec.dhG); +#endif /* REQUIRE_DH_PARAMS */ +#ifdef USE_ECC_CIPHER_SUITE + } +#endif /* USE_ECC_CIPHER_SUITE */ + } + } else { +#endif /* USE_DHE_CIPHER_SUITE */ +#ifdef USE_PSK_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + if (rc == MATRIXSSL_SUCCESS) { + rc = writePskServerKeyExchange(ssl, out); + } + } else { +#endif /* USE_PSK_CIPHER_SUITE */ +#ifndef USE_ONLY_PSK_CIPHER_SUITE + if (rc == MATRIXSSL_SUCCESS) { + rc = writeCertificate(ssl, out, 1); + } +#ifdef USE_OCSP + if (rc == MATRIXSSL_SUCCESS) { + rc = writeCertificateStatus(ssl, out); + } +#endif +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ +#ifdef USE_PSK_CIPHER_SUITE + } +#endif /* USE_PSK_CIPHER_SUITE */ +#ifdef USE_DHE_CIPHER_SUITE + } +#endif /* USE_DHE_CIPHER_SUITE */ + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#ifdef USE_CLIENT_AUTH + if (ssl->flags & SSL_FLAGS_CLIENT_AUTH) { + if (rc == MATRIXSSL_SUCCESS) { + rc = writeCertificateRequest(ssl, out, CAcertLen, certCount); + } + } +#endif /* USE_CLIENT_AUTH */ +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + + if (rc == MATRIXSSL_SUCCESS) { + rc = writeServerHelloDone(ssl, out); + } + if (rc == SSL_FULL) { + psTraceInfo("Bad flight messageSize calculation"); + ssl->err = SSL_ALERT_INTERNAL_ERROR; + out->end = out->start; + alertReqLen = out->size; + /* Going recursive */ + return sslEncodeResponse(ssl, out, &alertReqLen); + } + break; + +#ifdef USE_DTLS +/* + Got a cookie-less CLIENT_HELLO, need a HELLO_VERIFY_REQUEST message +*/ + case SSL_HS_CLIENT_HELLO: + messageSize = ssl->recordHeadLen + ssl->hshakeHeadLen + + DTLS_COOKIE_SIZE + 3; + messageSize += secureWriteAdditions(ssl, 1); + + if ((out->buf + out->size) - out->end < messageSize) { + *requiredLen = messageSize; + return SSL_FULL; + } + rc = writeHelloVerifyRequest(ssl, out); + break; +#endif /* USE_DTLS */ +#endif /* USE_SERVER_SIDE_SSL */ + +/* + If we're not waiting for any message from client, then we need to + send our finished message +*/ + case SSL_HS_DONE: + messageSize = 2 * ssl->recordHeadLen + + ssl->hshakeHeadLen + + 1 + /* change cipher spec */ + MD5_HASH_SIZE + SHA1_HASH_SIZE; /* finished */ +/* + Account for possible overhead in CCS message with secureWriteAdditions + then always account for the encryption overhead on FINISHED message. + Correct to use ssl->cipher values for mac and block since those will + be the ones used when encrypting FINISHED +*/ + messageSize += secureWriteAdditions(ssl, 1); + messageSize += ssl->cipher->macSize + ssl->cipher->blockSize; + +#if defined(USE_STATELESS_SESSION_TICKETS) && defined(USE_SERVER_SIDE_SSL) + if (ssl->flags & SSL_FLAGS_SERVER) { + if (ssl->sid && + (ssl->sid->sessionTicketState == SESS_TICKET_STATE_RECVD_EXT)) { + messageSize += ssl->recordHeadLen + + ssl->hshakeHeadLen + matrixSessionTicketLen() + 6; + } + } +#endif + +#ifdef USE_TLS +/* + Account for the smaller finished message size for TLS. +*/ + if (ssl->flags & SSL_FLAGS_TLS) { + messageSize += TLS_HS_FINISHED_SIZE - + (MD5_HASH_SIZE + SHA1_HASH_SIZE); + } +#endif /* USE_TLS */ +#ifdef USE_TLS_1_1 +/* + Adds explict IV overhead to the FINISHED message +*/ + if (ssl->flags & SSL_FLAGS_TLS_1_1) { + if (ssl->flags & SSL_FLAGS_AEAD_W) { + /* The magic 1 back into messageSize is because the + macSize + blockSize above ends up subtracting one on AEAD */ + messageSize += AEAD_TAG_LEN(ssl) + AEAD_NONCE_LEN(ssl) + 1; + } else { + messageSize += ssl->cipher->blockSize; + } + } +#endif /* USE_TLS_1_1 */ + +#ifdef USE_ZLIB_COMPRESSION + /* Lastly, add the zlib overhead for the FINISHED message */ + if (ssl->compression) { + messageSize += MAX_ZLIB_COMPRESSED_OH; + } +#endif + if ((out->buf + out->size) - out->end < messageSize) { + *requiredLen = messageSize; + return SSL_FULL; + } + rc = MATRIXSSL_SUCCESS; + +#if defined(USE_STATELESS_SESSION_TICKETS) && defined(USE_SERVER_SIDE_SSL) + if (ssl->flags & SSL_FLAGS_SERVER) { + if (ssl->sid && + (ssl->sid->sessionTicketState == SESS_TICKET_STATE_RECVD_EXT)) { + rc = writeNewSessionTicket(ssl, out); + } + } +#endif + if (rc == MATRIXSSL_SUCCESS) { + rc = writeChangeCipherSpec(ssl, out); + } + if (rc == MATRIXSSL_SUCCESS) { + rc = writeFinished(ssl, out); + } + + if (rc == SSL_FULL) { + psTraceInfo("Bad flight messageSize calculation"); + ssl->err = SSL_ALERT_INTERNAL_ERROR; + out->end = out->start; + alertReqLen = out->size; + /* Going recursive */ + return sslEncodeResponse(ssl, out, &alertReqLen); + } + break; +/* + If we're expecting a Finished message, as a server we're doing + session resumption. As a client, we're completing a normal + handshake +*/ + case SSL_HS_FINISHED: +#ifdef USE_SERVER_SIDE_SSL + if (ssl->flags & SSL_FLAGS_SERVER) { + messageSize = + 3 * ssl->recordHeadLen + + 2 * ssl->hshakeHeadLen + + 38 + SSL_MAX_SESSION_ID_SIZE + /* server hello */ + 1 + /* change cipher spec */ + MD5_HASH_SIZE + SHA1_HASH_SIZE; /* finished */ +/* + Account for possible overhead with secureWriteAdditions + then always account for the encrypted FINISHED message. Correct + to use the ssl->cipher values for mac and block since those will + always be the values used to encrypt the FINISHED message +*/ + messageSize += secureWriteAdditions(ssl, 2); + messageSize += ssl->cipher->macSize + ssl->cipher->blockSize; +#ifdef ENABLE_SECURE_REHANDSHAKES +/* + The RenegotiationInfo extension lengths are well known +*/ + if (ssl->secureRenegotiationFlag == PS_TRUE && + ssl->myVerifyDataLen == 0) { + messageSize += 7; /* 00 05 ff 01 00 01 00 */ + } else if (ssl->secureRenegotiationFlag == PS_TRUE && + ssl->myVerifyDataLen > 0) { + messageSize += 2 + 5 + ssl->myVerifyDataLen + + ssl->peerVerifyDataLen; /* 2 for tot len, 5 for type+len */ + } +#endif /* ENABLE_SECURE_REHANDSHAKES */ + +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ECC_CIPHER) { +#ifndef ENABLE_SECURE_REHANDSHAKES + messageSize += 2; /* ext 2 byte len has not been included */ +#endif /* ENABLE_SECURE_REHANDSHAKES */ + /* EXT_ELLIPTIC_POINTS - hardcoded to 'uncompressed' support */ + messageSize += 6; /* 00 0B 00 02 01 00 */ + } +#endif /* USE_ECC_CIPHER_SUITE */ + +#ifdef USE_TLS +/* + Account for the smaller finished message size for TLS. + The MD5+SHA1 is SSLv3. TLS is 12 bytes. +*/ + if (ssl->flags & SSL_FLAGS_TLS) { + messageSize += TLS_HS_FINISHED_SIZE - + (MD5_HASH_SIZE + SHA1_HASH_SIZE); + } +#endif /* USE_TLS */ +#ifdef USE_TLS_1_1 +/* + Adds explict IV overhead to the FINISHED message. Always added + because FINISHED is never accounted for in secureWriteAdditions +*/ + if (ssl->flags & SSL_FLAGS_TLS_1_1) { + if (ssl->cipher->flags & + (CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_CCM)) { + /* The magic 1 back into messageSize is because the + blockSize -1 above ends up subtracting one on AEAD */ + messageSize += AEAD_TAG_LEN(ssl) + TLS_EXPLICIT_NONCE_LEN + 1; + } else if (ssl->cipher->flags & CRYPTO_FLAGS_CHACHA) { + messageSize += AEAD_TAG_LEN(ssl) + 1; + } else { + messageSize += ssl->cipher->blockSize; /* explicitIV */ + } + } +#endif /* USE_TLS_1_1 */ + +#ifdef USE_ZLIB_COMPRESSION + /* Lastly, add the zlib overhead for the FINISHED message */ + if (ssl->compression) { + messageSize += MAX_ZLIB_COMPRESSED_OH; + } +#endif + if ((out->buf + out->size) - out->end < messageSize) { + *requiredLen = messageSize; + return SSL_FULL; + } + rc = writeServerHello(ssl, out); + if (rc == MATRIXSSL_SUCCESS) { + rc = writeChangeCipherSpec(ssl, out); + } + if (rc == MATRIXSSL_SUCCESS) { + rc = writeFinished(ssl, out); + } + } +#endif /* USE_SERVER_SIDE_SSL */ +#ifdef USE_CLIENT_SIDE_SSL +/* + Encode entry point for client side final flight encodes. + First task here is to find out size of ClientKeyExchange message +*/ + if (!(ssl->flags & SSL_FLAGS_SERVER)) { + ckeSize = 0; +#ifdef USE_DHE_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_DHE_KEY_EXCH) { +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS && ssl->retransmit == 1) { + ckeSize = ssl->ckeSize; /* Keys have been freed */ + } else { +#endif /* USE_DTLS */ +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ECC_CIPHER) { + ckeSize = (ssl->sec.eccKeyPriv->curve->size * 2) + 2; + } else { +#endif /* USE_ECC_CIPHER_SUITE */ +#ifdef REQUIRE_DH_PARAMS + ckeSize = ssl->sec.dhKeyPriv->size; +#endif /* REQUIRE_DH_PARAMS */ +#ifdef USE_ECC_CIPHER_SUITE + } +#endif /* USE_ECC_CIPHER_SUITE */ +#ifdef USE_DTLS + } +#endif /* USE_DTLS */ +#ifdef USE_PSK_CIPHER_SUITE +/* + This is the DHE_PSK suite case. + PSK suites add the key identity with uint16 size +*/ + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + ckeSize += SSL_PSK_MAX_ID_SIZE + 2; + } +#endif /* USE_PSK_CIPHER_SUITE */ + } else { +#endif /* USE_DHE_CIPHER_SUITE */ +#ifdef USE_PSK_CIPHER_SUITE +/* + This is the basic PSK case + PSK suites add the key identity with uint16 size +*/ + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + ckeSize += SSL_PSK_MAX_ID_SIZE + 2; + } else { +#endif /* USE_PSK_CIPHER_SUITE */ +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->cipher->type == CS_ECDH_ECDSA || + ssl->cipher->type == CS_ECDH_RSA) { + ckeSize = (ssl->sec.cert->publicKey.key.ecc.curve->size + * 2) + 2; + } else { +#endif /* USE_ECC_CIPHER_SUITE */ +/* + Normal RSA auth cipher suite case +*/ + if (ssl->sec.cert == NULL) { + ssl->flags |= SSL_FLAGS_ERROR; + return MATRIXSSL_ERROR; + } + ckeSize = ssl->sec.cert->publicKey.keysize; + +#ifdef USE_ECC_CIPHER_SUITE + } +#endif /* USE_ECC_CIPHER_SUITE */ +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ +#ifdef USE_PSK_CIPHER_SUITE + } +#endif /* USE_PSK_CIPHER_SUITE */ +#ifdef USE_DHE_CIPHER_SUITE + } +#endif /* USE_DHE_CIPHER_SUITE */ + + messageSize = 0; + + if (ssl->flags & SSL_FLAGS_CLIENT_AUTH) { +/* + Client authentication requires the client to send a CERTIFICATE + and CERTIFICATE_VERIFY message. Account for the length. It + is possible the client didn't have a match for the requested cert. + Send an empty certificate message in that case (or alert for SSLv3) +*/ +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#ifdef USE_CLIENT_AUTH + if (ssl->sec.certMatch > 0) { +/* + Account for the certificate and certificateVerify messages +*/ + cert = ssl->keys->cert; + ctotalCertLen = 0; + for (i = 0; cert != NULL; i++) { + ctotalCertLen += cert->binLen; + cert = cert->next; + } + /* Are we going to have to fragment the CERT message? */ + if ((ctotalCertLen + 3 + (i * 3) + ssl->hshakeHeadLen) > + ssl->maxPtFrag) { + ctotalCertLen += addCertFragOverhead(ssl, + ctotalCertLen + 3 + (i * 3) + ssl->hshakeHeadLen); + } + messageSize += (2 * ssl->recordHeadLen) + 3 + (i * 3) + + (2 * ssl->hshakeHeadLen) + ctotalCertLen + + 2 + ssl->keys->privKey.keysize; + +#ifdef USE_ECC + /* Overhead ASN.1 in psEccSignHash */ + if (ssl->keys->cert->pubKeyAlgorithm == OID_ECDSA_KEY_ALG) { + /* NEGATIVE ECDSA - For purposes of SSL_FULL we + add 2 extra bytes to account for the two 0x0 + bytes in signature */ + messageSize += 6 + 2; + if (ssl->keys->privKey.keysize >= 128) { + messageSize += 1; /* Extra len byte in ASN.1 sig */ + } + } +#endif /* USE_ECC */ + } else { +#endif /* USE_CLIENT_AUTH */ +/* + SSLv3 sends a no_certificate warning alert for no match +*/ + if (ssl->majVer == SSL3_MAJ_VER + && ssl->minVer == SSL3_MIN_VER) { + messageSize += 2 + ssl->recordHeadLen; + } else { +/* + TLS just sends an empty certificate message +*/ + messageSize += 3 + ssl->recordHeadLen + + ssl->hshakeHeadLen; + } +#ifdef USE_CLIENT_AUTH + } +#endif /* USE_CLIENT_AUTH */ +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ + } +/* + Account for the header and message size for all records. The + finished message will always be encrypted, so account for one + largest possible MAC size and block size. The finished message is + not accounted for in the writeSecureAddition calls below since it + is accounted for here. +*/ + messageSize += + 3 * ssl->recordHeadLen + + 2 * ssl->hshakeHeadLen + /* change cipher has no hsHead */ + ckeSize + /* client key exchange */ + 1 + /* change cipher spec */ + MD5_HASH_SIZE + SHA1_HASH_SIZE + /* SSLv3 finished payload */ + ssl->cipher->macSize + + ssl->cipher->blockSize; /* finished overhead */ +#ifdef USE_TLS +/* + Must add the 2 bytes key size length to the client key exchange + message. Also, at this time we can account for the smaller finished + message size for TLS. The MD5+SHA1 is SSLv3. TLS is 12 bytes. +*/ + if (ssl->flags & SSL_FLAGS_TLS) { + messageSize += 2 - MD5_HASH_SIZE - SHA1_HASH_SIZE + + TLS_HS_FINISHED_SIZE; + } +#endif /* USE_TLS */ + if (ssl->flags & SSL_FLAGS_CLIENT_AUTH) { +/* + Secure write for ClientKeyExchange, ChangeCipherSpec, + Certificate, and CertificateVerify. Don't account for + Certificate and/or CertificateVerify message if no auth cert. + This will also cover the NO_CERTIFICATE alert sent in + replacement of the NULL certificate message in SSLv3. +*/ + if (ssl->sec.certMatch > 0) { +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + messageSize += 2; /* hashSigAlg in CertificateVerify */ + } +#endif + messageSize += secureWriteAdditions(ssl, 4); + } else { + messageSize += secureWriteAdditions(ssl, 3); + } + } else { + messageSize += secureWriteAdditions(ssl, 2); + } + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { +/* + If DTLS, make sure the max fragment overhead is accounted for + on any flight containing the CERTIFICATE message. If + SSL_FULL is hit mid-flight creation, the updates that happen + on the handshake hash on that first pass will really mess us up +*/ + messageSize += (MAX_FRAGMENTS - 1) * + (ssl->recordHeadLen + ssl->hshakeHeadLen); + if (ssl->flags & SSL_FLAGS_WRITE_SECURE) { + messageSize += secureWriteAdditions(ssl, MAX_FRAGMENTS - 1); + } + } +#endif /* USE_DTLS */ +#ifdef USE_TLS_1_1 +/* + Adds explict IV overhead to the FINISHED message. Always added + because FINISHED is never accounted for in secureWriteAdditions +*/ + if (ssl->flags & SSL_FLAGS_TLS_1_1) { + if (ssl->cipher->flags & + (CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_CCM)) { + /* The magic 1 back into messageSize is because the + blockSize -1 above ends up subtracting one on AEAD */ + messageSize += AEAD_TAG_LEN(ssl) + TLS_EXPLICIT_NONCE_LEN + 1; + } else if (ssl->cipher->flags & CRYPTO_FLAGS_CHACHA) { + messageSize += AEAD_TAG_LEN(ssl) + 1; + } else { + messageSize += ssl->cipher->blockSize; /* explicitIV */ + } + } +#endif /* USE_TLS_1_1 */ +#ifdef USE_ZLIB_COMPRESSION + /* Lastly, add the zlib overhead for the FINISHED message */ + if (ssl->compression) { + messageSize += MAX_ZLIB_COMPRESSED_OH; + } +#endif +/* + The actual buffer size test to hold this flight +*/ + if ((out->buf + out->size) - out->end < messageSize) { + *requiredLen = messageSize; + return SSL_FULL; + } + rc = MATRIXSSL_SUCCESS; + +#ifndef USE_ONLY_PSK_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_CLIENT_AUTH) { +/* + The TLS RFC is fairly clear that an empty certificate message + be sent if there is no certificate match. SSLv3 tends to lean + toward a NO_CERTIFIATE warning alert message +*/ + if (ssl->sec.certMatch == 0 && ssl->majVer == SSL3_MAJ_VER + && ssl->minVer == SSL3_MIN_VER) { + rc = writeAlert(ssl, SSL_ALERT_LEVEL_WARNING, + SSL_ALERT_NO_CERTIFICATE, out, requiredLen); + } else { + rc = writeCertificate(ssl, out, ssl->sec.certMatch); + } + } +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + + if (rc == MATRIXSSL_SUCCESS) { + rc = writeClientKeyExchange(ssl, out); + } +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#ifdef USE_CLIENT_AUTH + if (ssl->flags & SSL_FLAGS_CLIENT_AUTH) { + if (rc == MATRIXSSL_SUCCESS && ssl->sec.certMatch > 0) { + rc = writeCertificateVerify(ssl, out); + } + } +#endif /* USE_CLIENT_AUTH */ +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + + if (rc == MATRIXSSL_SUCCESS) { + rc = writeChangeCipherSpec(ssl, out); + } + if (rc == MATRIXSSL_SUCCESS) { + rc = writeFinished(ssl, out); + } + } +#endif /* USE_CLIENT_SIDE_SSL */ + if (rc == SSL_FULL) { + psTraceInfo("Bad flight messageSize calculation"); + ssl->err = SSL_ALERT_INTERNAL_ERROR; + out->end = out->start; + alertReqLen = out->size; + /* Going recursive */ + return sslEncodeResponse(ssl, out, &alertReqLen); + } + break; +#ifdef USE_DTLS +/* + If we a client being invoked from here in the HS_SERVER_HELLO state, + we are being asked for a CLIENT_HELLO with a cookie. It's already + been parsed out of the server HELLO_VERIFY_REQUEST message, so + we can simply call matrixSslEncodeClientHello again and essentially + start over again. +*/ + case SSL_HS_SERVER_HELLO: + rc = matrixSslEncodeClientHello(ssl, out, ssl->cipherSpec, + ssl->cipherSpecLen, requiredLen, NULL, &options); + break; +#endif /* USE_DTLS */ + } + + if (rc < MATRIXSSL_SUCCESS && rc != SSL_FULL) { + /* Indication one of the message creations failed and setting the flag to + prevent other API calls from working. We want to send a fatal + internal error alert in this case. Make sure to write to front of + buffer since we can't trust the data in there due to the creation + failure. */ + psTraceIntInfo("ERROR: Handshake flight creation failed %d\n", rc); + if (rc == PS_UNSUPPORTED_FAIL) { + /* Single out this particular error as a handshake failure + because there are combinations of cipher negotiations where + we don't know until handshake creation that we can't support. + For example, the server key material test will be bypassed + if an SNI callback is registered. We won't know until SKE + creation that we can't support the requested cipher. This is + a user error so don't report an INTERNAL_ERROR */ + ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; + } else { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + } + out->end = out->start; + alertReqLen = out->size; + /* Going recursive */ + return sslEncodeResponse(ssl, out, &alertReqLen); + } + + +#ifdef USE_SERVER_SIDE_SSL + /* Post-flight write PKA operation. Support is for the signature + generation during ServerKeyExchange write. */ + if (ssl->flags & SSL_FLAGS_SERVER) { + if (ssl->pkaAfter[0].type > 0) { + if ((rc = nowDoSkePka(ssl, out)) < 0) { + return rc; + } + } + } +#endif + +#ifdef USE_CLIENT_SIDE_SSL + /* Post-flight write PKA operation. Support is for the operations during + ClientKeyExchange write. */ + if (!(ssl->flags & SSL_FLAGS_SERVER)) { + if (ssl->pkaAfter[0].type > 0) { + if ((rc = nowDoCkePka(ssl)) < 0) { + return rc; + } + } + } +#endif + + /* Encrypt Flight */ + if (ssl->flightEncode) { + if ((rc = encryptFlight(ssl, &out->end)) < 0) { + return rc; + } + } + + return rc; +} + +void clearFlightList(ssl_t *ssl) +{ + flightEncode_t *msg, *next; + + next = msg = ssl->flightEncode; + while (msg) { + next = msg->next; + psFree(msg, ssl->flightPool); + msg = next; + } + ssl->flightEncode = NULL; +} + +static int32 encryptFlight(ssl_t *ssl, unsigned char **end) +{ + flightEncode_t *msg, *remove; + sslBuf_t out; +#if defined(USE_CLIENT_SIDE_SSL) && defined(USE_CLIENT_AUTH) + sslBuf_t cvFlight; +#endif + unsigned char *c, *origEnd; + int32 rc; + + /* NEGATIVE ECDSA - save the end of the flight buffer */ + origEnd = *end; + + msg = ssl->flightEncode; + while (msg) { + c = msg->start + msg->len; +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (msg->hsMsg == SSL_HS_FINISHED) { + /* Epoch is incremented and the sequence numbers are reset for + this message */ + incrTwoByte(ssl, ssl->epoch, 1); + zeroSixByte(ssl->rsn); + } + psTraceIntDtls("RSN %d, ", ssl->rsn[5]); + psTraceIntDtls("MSN %d, ", ssl->msn); + psTraceIntDtls("Epoch %d\n", ssl->epoch[1]); + *msg->seqDelay = ssl->epoch[0]; msg->seqDelay++; + *msg->seqDelay = ssl->epoch[1]; msg->seqDelay++; + *msg->seqDelay = ssl->rsn[0]; msg->seqDelay++; + *msg->seqDelay = ssl->rsn[1]; msg->seqDelay++; + *msg->seqDelay = ssl->rsn[2]; msg->seqDelay++; + *msg->seqDelay = ssl->rsn[3]; msg->seqDelay++; + *msg->seqDelay = ssl->rsn[4]; msg->seqDelay++; + *msg->seqDelay = ssl->rsn[5]; msg->seqDelay++; + msg->seqDelay++; + msg->seqDelay++; /* Last two incremements skipped recLen */ + } +#endif + if (msg->hsMsg == SSL_HS_FINISHED) { + /* If it was just a ChangeCipherSpec message that was encoded we can + activate the write cipher */ + if ((rc = sslActivateWriteCipher(ssl)) < 0) { + psTraceInfo("Error Activating Write Cipher\n"); + clearFlightList(ssl); + return rc; + } + + /* The finished message had to hold off snapshoting the handshake + hash because those updates are done in the encryptRecord call + below for each message. THAT was done because of a possible + delay in a PKA op */ + rc = sslSnapshotHSHash(ssl, ssl->delayHsHash, + ssl->flags & SSL_FLAGS_SERVER); + if (rc <= 0) { + psTraceIntInfo("Error snapshotting HS hash flight %d\n", rc); + clearFlightList(ssl); + return rc; + } + +#ifdef ENABLE_SECURE_REHANDSHAKES + /* The rehandshake verify data is the previous handshake msg hash */ +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (ssl->myVerifyDataLen > 0) { + memcpy(ssl->omyVerifyData, ssl->myVerifyData, + ssl->myVerifyDataLen); + ssl->omyVerifyDataLen = ssl->myVerifyDataLen; + } + } +#endif /* USE_DTLS */ + memcpy(ssl->myVerifyData, ssl->delayHsHash, rc); + ssl->myVerifyDataLen = rc; +#endif /* ENABLE_SECURE_REHANDSHAKES */ + } + + if (ssl->flags & SSL_FLAGS_NONCE_W) { + /* TODO: what about app data records? delayed seq needed? */ + out.start = out.buf = out.end = msg->start - ssl->recordHeadLen - + TLS_EXPLICIT_NONCE_LEN; +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + /* nonce */ + *msg->seqDelay = ssl->epoch[0]; msg->seqDelay++; + *msg->seqDelay = ssl->epoch[1]; msg->seqDelay++; + *msg->seqDelay = ssl->rsn[0]; msg->seqDelay++; + *msg->seqDelay = ssl->rsn[1]; msg->seqDelay++; + *msg->seqDelay = ssl->rsn[2]; msg->seqDelay++; + *msg->seqDelay = ssl->rsn[3]; msg->seqDelay++; + *msg->seqDelay = ssl->rsn[4]; msg->seqDelay++; + *msg->seqDelay = ssl->rsn[5]; msg->seqDelay++; + } else { +#endif + *msg->seqDelay = ssl->sec.seq[0]; msg->seqDelay++; + *msg->seqDelay = ssl->sec.seq[1]; msg->seqDelay++; + *msg->seqDelay = ssl->sec.seq[2]; msg->seqDelay++; + *msg->seqDelay = ssl->sec.seq[3]; msg->seqDelay++; + *msg->seqDelay = ssl->sec.seq[4]; msg->seqDelay++; + *msg->seqDelay = ssl->sec.seq[5]; msg->seqDelay++; + *msg->seqDelay = ssl->sec.seq[6]; msg->seqDelay++; + *msg->seqDelay = ssl->sec.seq[7]; +#ifdef USE_DTLS + } +#endif + } else { + out.start = out.buf = out.end = msg->start - ssl->recordHeadLen; + } + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#if defined(USE_CLIENT_SIDE_SSL) && defined(USE_CLIENT_AUTH) + if (msg->hsMsg == SSL_HS_CERTIFICATE_VERIFY) { + /* This delayed PKA op has to be done mid flight encode because + the contents of the signature is the hash of the handshake + messages. This can theoretically return PENDING too */ + /* NEGATIVE ECDSA - Need psBuf_t to work in */ + cvFlight.start = cvFlight.buf = out.start; + cvFlight.end = origEnd; + cvFlight.size = ssl->insize - (cvFlight.end - cvFlight.buf); + nowDoCvPka(ssl, &cvFlight); + /* NEGATIVE ECDSA - account for message may have changed size */ + c = msg->start + msg->len; + if (ssl->flags & SSL_FLAGS_AEAD_W) { + out.start = out.buf = out.end = + (msg->start - ssl->recordHeadLen) - AEAD_NONCE_LEN(ssl); + } else { + out.start = out.buf = out.end = msg->start - ssl->recordHeadLen; + } + } +#endif /* Client */ +#endif /* !PSK_ONLY */ + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS && msg->fragCount > 0) { +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) + rc = dtlsEncryptFragRecord(ssl, msg, &out, &c); +#endif /* SERVER || CLIENT_AUTH */ +#endif /* PSK_ONLY */ + } else { + rc = encryptRecord(ssl, msg->type, msg->hsMsg, msg->messageSize, + msg->padLen, msg->start, &out, &c); + } +#else + rc = encryptRecord(ssl, msg->type, msg->hsMsg, msg->messageSize, msg->padLen, + msg->start, &out, &c); +#endif /* DTLS */ + + *end = c; + if (rc == PS_PENDING) { + /* Eat this message from flight encode, moving next to the front */ + /* Save how far along we are to be picked up next time */ + *end = msg->start + msg->messageSize - ssl->recordHeadLen; + if (ssl->flags & SSL_FLAGS_AEAD_W) { + *end -= AEAD_NONCE_LEN(ssl); + } + ssl->flightEncode = msg->next; + psFree(msg, ssl->flightPool); + return rc; + } + if (rc < 0) { + psTraceIntInfo("Error encrypting record from flight %d\n", rc); + clearFlightList(ssl); + return rc; + } + remove = msg; + ssl->flightEncode = msg = msg->next; + psFree(remove, ssl->flightPool); + } + clearFlightList(ssl); + return PS_SUCCESS; +} + +/* One message flight requires 2 PKA "after" operations so need to store both */ +pkaAfter_t *getPkaAfter(ssl_t *ssl) +{ + if (ssl->pkaAfter[0].type == 0) { + return &ssl->pkaAfter[0]; + } else if (ssl->pkaAfter[1].type == 0) { + return &ssl->pkaAfter[1]; + } else { + return NULL; + } +} + +void freePkaAfter(ssl_t *ssl) +{ + /* Just call clear twice */ + clearPkaAfter(ssl); + clearPkaAfter(ssl); +} + + +/* Clear pkaAfter[0] and move pkaAfter[1] to [0]. Will be zeroed if no [1] */ +void clearPkaAfter(ssl_t *ssl) +{ + if (ssl->pkaAfter[0].inbuf) { + /* If it was a TMP_PKI pool with PENDING, it will have been saved + aside in the pkaAfter.pool. Otherwise, it's in handshake pool */ + if (ssl->pkaAfter[0].pool) { + psFree(ssl->pkaAfter[0].inbuf, ssl->pkaAfter[0].pool); + } else { + psFree(ssl->pkaAfter[0].inbuf, ssl->hsPool); + } + ssl->pkaAfter[0].inbuf = NULL; + } + if (ssl->pkaAfter[0].pool) { + } + ssl->pkaAfter[0].type = 0; + ssl->pkaAfter[0].outbuf = NULL; + ssl->pkaAfter[0].data = NULL; + ssl->pkaAfter[0].inlen = 0; + ssl->pkaAfter[0].user = 0; + + if (ssl->pkaAfter[1].type != 0) { + ssl->pkaAfter[0].type = ssl->pkaAfter[1].type; + ssl->pkaAfter[0].outbuf = ssl->pkaAfter[1].outbuf; + ssl->pkaAfter[0].data = ssl->pkaAfter[1].data; + ssl->pkaAfter[0].inlen = ssl->pkaAfter[1].inlen; + ssl->pkaAfter[0].user = ssl->pkaAfter[1].user; + + ssl->pkaAfter[1].type = 0; + ssl->pkaAfter[1].outbuf = NULL; + ssl->pkaAfter[1].data = NULL; + ssl->pkaAfter[1].inlen = 0; + ssl->pkaAfter[1].user = 0; + } +} + +/******************************************************************************/ +/* + Message size must account for any additional length a secure-write + would add to the message. It would be too late to check length in + the writeRecordHeader() call since some of the handshake hashing could + have already taken place and we can't rewind those hashes. +*/ +static int32 secureWriteAdditions(ssl_t *ssl, int32 numRecs) +{ + int32 add = 0; +/* + There is a slim chance for a false FULL message due to the fact that + the maximum padding is being calculated rather than the actual number. + Caller must simply grow buffer and try again. Not subtracting 1 for + the padding overhead to support NULL ciphers that will have 0 enBlockSize +*/ + if (ssl->flags & SSL_FLAGS_WRITE_SECURE) { + add += (numRecs * ssl->enMacSize) + /* handshake msg hash */ + (numRecs * (ssl->enBlockSize)); /* padding */ +#ifdef USE_TLS_1_1 +/* + Checks here for TLS1.1 with block cipher for explict IV additions. + */ + if ((ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1)) { + add += (numRecs * ssl->enBlockSize); /* explicitIV */ + } +#endif /* USE_TLS_1_1 */ + if (ssl->flags & SSL_FLAGS_AEAD_W) { + add += (numRecs * (AEAD_TAG_LEN(ssl) + AEAD_NONCE_LEN(ssl))); + } + } + return add; +} + +/******************************************************************************/ +/* + Write out a closure alert message (the only user initiated alert message) + The user would call this when about to initate a socket close + NOTICE: This is the internal function, there is a similarly named public + API called matrixSslEncodeClosureAlert +*/ +int32 sslEncodeClosureAlert(ssl_t *ssl, sslBuf_t *out, uint32 *reqLen) +{ +/* + If we've had a protocol error, don't allow further use of the session +*/ + if (ssl->flags & SSL_FLAGS_ERROR) { + return MATRIXSSL_ERROR; + } + return writeAlert(ssl, SSL_ALERT_LEVEL_WARNING, SSL_ALERT_CLOSE_NOTIFY, + out, reqLen); +} + +/******************************************************************************/ +/* + Generic record header construction for alerts, handshake messages, and + change cipher spec. Determines message length for encryption and + writes out to buffer up to the real message data. + + The FINISHED message is given special treatment here to move through the + encrypted stages because the postponed flight encoding mechanism will + not have moved to the SECURE_WRITE state until the CHANGE_CIPHER_SPEC + has been encoded. This means we have to look at the hsType and the + ssl->cipher profile to see what is needed. + + Incoming messageSize is the plaintext message length plus the header + lengths. +*/ +static int32_t writeRecordHeader(ssl_t *ssl, uint8_t type, uint8_t hsType, + uint16_t *messageSize, uint8_t *padLen, + unsigned char **encryptStart, const unsigned char *end, + unsigned char **c) +{ + int32 messageData, msn; + + messageData = *messageSize - ssl->recordHeadLen; + if (type == SSL_RECORD_TYPE_HANDSHAKE) { + messageData -= ssl->hshakeHeadLen; + } + if (type == SSL_RECORD_TYPE_HANDSHAKE_FIRST_FRAG) { + messageData -= ssl->hshakeHeadLen; + *messageSize = ssl->maxPtFrag + ssl->recordHeadLen; + type = SSL_RECORD_TYPE_HANDSHAKE; + } + +#ifdef USE_TLS_1_1 +/* + If a block cipher is being used TLS 1.1 requires the use + of an explicit IV. This is an extra random block of data + prepended to the plaintext before encryption. Account for + that extra length here. */ + if (hsType == SSL_HS_FINISHED && (ssl->flags & SSL_FLAGS_TLS_1_1)) { + if (ssl->cipher->blockSize > 1) { + *messageSize += ssl->cipher->blockSize; + } + } else if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) && + (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1)) { + *messageSize += ssl->enBlockSize; + } +#endif /* USE_TLS_1_1 */ + + /* This is to catch the FINISHED write for the postponed encode */ + if (hsType == SSL_HS_FINISHED) { + if (ssl->cipher->flags & + (CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_CCM)) { + *messageSize += AEAD_TAG_LEN(ssl) + TLS_EXPLICIT_NONCE_LEN; + } else if (ssl->cipher->flags & CRYPTO_FLAGS_CHACHA) { + *messageSize += AEAD_TAG_LEN(ssl); + } + } else if (ssl->flags & SSL_FLAGS_AEAD_W) { + *messageSize += (AEAD_TAG_LEN(ssl) + AEAD_NONCE_LEN(ssl)); + } +/* + If this session is already in a secure-write state, determine padding. + Again, the FINISHED message is explicitly checked due to the delay + of the ActivateWriteCipher for flight encodings. In this case, cipher + sizes are taken from ssl->cipher rather than the active values +*/ + *padLen = 0; + if (hsType == SSL_HS_FINISHED) { + if (ssl->cipher->macSize > 0) { + if (ssl->extFlags.truncated_hmac) { + *messageSize += 10; + } else { + *messageSize += ssl->cipher->macSize; + } + } + *padLen = psPadLenPwr2(*messageSize - ssl->recordHeadLen, + ssl->cipher->blockSize); + *messageSize += *padLen; + } else if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) && + !(ssl->flags & SSL_FLAGS_AEAD_W)) { + *messageSize += ssl->enMacSize; + *padLen = psPadLenPwr2(*messageSize - ssl->recordHeadLen, + ssl->enBlockSize); + *messageSize += *padLen; + } + + if (end - *c < *messageSize) { +/* + Callers other than sslEncodeResponse do not necessarily check for + FULL before calling. We do it here for them. +*/ + return SSL_FULL; + } + +#ifdef USE_DTLS +/* + This routine does not deal with DTLS fragmented messages, but it was + necessary to call for all the length computations to happen in here. +*/ + if (ssl->flags & SSL_FLAGS_DTLS) { + if (*messageSize > ssl->pmtu) { + psTraceIntDtls("Datagram size %d ", ssl->pmtu); + psTraceIntDtls("too small for message: %d\n", *messageSize); + return DTLS_MUST_FRAG; + } + } +#endif /* USE_DTLS */ + + *c += psWriteRecordInfo(ssl, (unsigned char)type, + *messageSize - ssl->recordHeadLen, *c, hsType); + +/* + All data written after this point is to be encrypted (if secure-write) +*/ + *encryptStart = *c; + msn = 0; + +#ifdef USE_TLS_1_1 +/* + Explicit IV notes taken from TLS 1.1 ietf draft. + + Generate a cryptographically strong random number R of + length CipherSpec.block_length and prepend it to the plaintext + prior to encryption. In this case either: + + The CBC residue from the previous record may be used + as the mask. This preserves maximum code compatibility + with TLS 1.0 and SSL 3. It also has the advantage that + it does not require the ability to quickly reset the IV, + which is known to be a problem on some systems. + + The data (R || data) is fed into the encryption process. + The first cipher block containing E(mask XOR R) is placed + in the IV field. The first block of content contains + E(IV XOR data) +*/ + + if (hsType == SSL_HS_FINISHED) { + if ((ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->cipher->blockSize > 1)) { + if (matrixCryptoGetPrngData(*c, ssl->cipher->blockSize, + ssl->userPtr) < 0) { + psTraceInfo("WARNING: matrixCryptoGetPrngData failed\n"); + } + *c += ssl->cipher->blockSize; + } + } else if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) && + (ssl->flags & SSL_FLAGS_TLS_1_1) && + (ssl->enBlockSize > 1)) { + if (matrixCryptoGetPrngData(*c, ssl->enBlockSize, ssl->userPtr) < 0) { + psTraceInfo("WARNING: matrixCryptoGetPrngData failed\n"); + } + *c += ssl->enBlockSize; + } +#endif /* USE_TLS_1_1 */ + +/* + Handshake records have another header layer to write here +*/ + if (type == SSL_RECORD_TYPE_HANDSHAKE) { +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { +/* + A message sequence number is unique for each handshake message. It + is not incremented on a resend; that is the record sequence number. +*/ + msn = ssl->msn; + ssl->msn++; + /* These aren't useful anymore because of the seqDelay mechanism */ + //psTraceIntDtls("RSN %d, ", ssl->rsn[5]); + //psTraceIntDtls("MSN %d, ", msn); + //psTraceIntDtls("Epoch %d\n", ssl->epoch[1]); + } +#endif /* USE_DTLS */ + *c += psWriteHandshakeHeader(ssl, (unsigned char)hsType, messageData, + msn, 0, messageData, *c); + } + + return PS_SUCCESS; +} + + +#ifdef USE_ZLIB_COMPRESSION +static int32 encryptCompressedRecord(ssl_t *ssl, int32 type, int32 messageSize, + unsigned char *pt, sslBuf_t *out, unsigned char **c) +{ + unsigned char *encryptStart, *dataToMacAndEncrypt; + int32 rc, ptLen, divLen, modLen, dataToMacAndEncryptLen; + int32 zret, ztmp; + int32 padLen; + + + encryptStart = out->end + ssl->recordHeadLen; + if (ssl->flags & SSL_FLAGS_AEAD_W) { + encryptStart += AEAD_NONCE_LEN(ssl); /* Move past the plaintext nonce */ + ssl->outRecType = (unsigned char) type; + } + ptLen = *c - encryptStart; + +#ifdef USE_TLS_1_1 + if ((ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1)) { + /* Do not compress IV */ + if (type == SSL_RECORD_TYPE_APPLICATION_DATA) { + /* FUTURE: Application data is passed in with real pt from user but + with the length of the explict IV added already. Can just + encrypt IV in-siture now since the rest of the encypts will be + coming from zlibBuffer */ + rc = ssl->encrypt(ssl, encryptStart, encryptStart, + ssl->enBlockSize); + if (rc < 0) { + psTraceIntInfo("Error encrypting IV: %d\n", rc); + return MATRIXSSL_ERROR; + } + ptLen -= ssl->enBlockSize; + encryptStart += ssl->enBlockSize; + } else { + /* Handshake messages have been passed in with plaintext that + begins with the explicit IV and size included. Can just + encrypt IV in-situ now since the rest of the encypts will be + coming from zlibBuffer */ + rc = ssl->encrypt(ssl, pt, pt, ssl->enBlockSize); + if (rc < 0) { + psTraceIntInfo("Error encrypting IV: %d\n", rc); + return MATRIXSSL_ERROR; + } + pt += ssl->enBlockSize; + ptLen -= ssl->enBlockSize; + encryptStart += ssl->enBlockSize; + } + } +#endif + + /* Compression is done only on the data itself so the prior work that + was just put into message size calcuations and padding length will + need to be done again after deflate */ + ssl->zlibBuffer = psMalloc(ssl->bufferPool, ptLen + MAX_ZLIB_COMPRESSED_OH); + memset(ssl->zlibBuffer, 0, ptLen + MAX_ZLIB_COMPRESSED_OH); + if (ssl->zlibBuffer == NULL) { + psTraceInfo("Error allocating compression buffer\n"); + return MATRIXSSL_ERROR; + } + dataToMacAndEncrypt = ssl->zlibBuffer; + dataToMacAndEncryptLen = ssl->deflate.total_out; /* tmp for later */ + /* psTraceBytes("pre deflate", pt, ptLen); */ + ssl->deflate.avail_out = ptLen + MAX_ZLIB_COMPRESSED_OH; + ssl->deflate.next_out = dataToMacAndEncrypt; + ssl->deflate.avail_in = ztmp = ptLen; + ssl->deflate.next_in = pt; + + /* FUTURE: Deflate would need to be in a smarter loop if large amounts + of data are ever passed through here */ + if ((zret = deflate(&ssl->deflate, Z_SYNC_FLUSH)) != Z_OK) { + psTraceIntInfo("ZLIB deflate error %d\n", zret); + psFree(ssl->zlibBuffer, ssl->bufferPool); ssl->zlibBuffer = NULL; + return MATRIXSSL_ERROR; + } + if (ssl->deflate.avail_in != 0) { + psTraceIntInfo("ZLIB didn't deflate %d bytes in single pass\n", ptLen); + psFree(ssl->zlibBuffer, ssl->bufferPool); ssl->zlibBuffer = NULL; + deflateEnd(&ssl->deflate); + return MATRIXSSL_ERROR; + } + + dataToMacAndEncryptLen = ssl->deflate.total_out - dataToMacAndEncryptLen; + /* psTraceBytes("post deflate", dataToMacAndEncrypt, + dataToMacAndEncryptLen); */ + if (dataToMacAndEncryptLen > ztmp) { + /* Case where compression grew the data. Push out end */ + *c += dataToMacAndEncryptLen - ztmp; + } else { + /* Compression did good job to shrink. Pull back in */ + *c -= ztmp - dataToMacAndEncryptLen; + } + + /* Can now calculate new padding length */ + padLen = psPadLenPwr2(dataToMacAndEncryptLen + ssl->enMacSize, + ssl->enBlockSize); + + /* Now see how this has changed the data lengths */ + ztmp = dataToMacAndEncryptLen + ssl->recordHeadLen + ssl->enMacSize +padLen; + +#ifdef USE_TLS_1_1 + if ((ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1)) { + ztmp += ssl->enBlockSize; + } +#endif + + if (ssl->flags & SSL_FLAGS_AEAD_W) { + psAssert(padLen == 0); + /* This += works fine because padLen will be zero because enBlockSize + and enMacSize are 0 */ + ztmp += AEAD_TAG_LEN(ssl) + AEAD_NONCE_LEN(ssl); + + } + + /* Possible the length hasn't changed if compression didn't do much */ + if (messageSize != ztmp) { + messageSize = ztmp; + ztmp -= ssl->recordHeadLen; + out->end[3] = (ztmp & 0xFF00) >> 8; + out->end[4] = ztmp & 0xFF; + } + + if (type == SSL_RECORD_TYPE_HANDSHAKE) { + sslUpdateHSHash(ssl, pt, ptLen); + } + + if (ssl->generateMac) { + *c += ssl->generateMac(ssl, (unsigned char)type, + dataToMacAndEncrypt, dataToMacAndEncryptLen, *c); + } + + *c += sslWritePad(*c, (unsigned char)padLen); + + if (ssl->flags & SSL_FLAGS_AEAD_W) { + *c += AEAD_TAG_LEN(ssl); /* c is tracking end of record here and the + tag has not yet been accounted for */ + } + + /* Will always be non-insitu since the compressed data is in zlibBuffer. + Requres two encrypts, one for plaintext and one for the + any < blockSize remainder of the plaintext and the mac and pad */ + if (ssl->cipher->blockSize > 1) { + divLen = dataToMacAndEncryptLen & ~(ssl->cipher->blockSize - 1); + modLen = dataToMacAndEncryptLen & (ssl->cipher->blockSize - 1); + } else { + if (ssl->flags & SSL_FLAGS_AEAD_W) { + divLen = dataToMacAndEncryptLen + AEAD_TAG_LEN(ssl); + modLen = 0; + } else { + divLen = dataToMacAndEncryptLen; + modLen = 0; + } + } + if (divLen > 0) { + rc = ssl->encrypt(ssl, dataToMacAndEncrypt, encryptStart, + divLen); + if (rc < 0) { + psFree(ssl->zlibBuffer, ssl->bufferPool); ssl->zlibBuffer = NULL; + deflateEnd(&ssl->deflate); + psTraceIntInfo("Error encrypting 2: %d\n", rc); + return MATRIXSSL_ERROR; + } + } + if (modLen > 0) { + memcpy(encryptStart + divLen, dataToMacAndEncrypt + divLen, + modLen); + } + rc = ssl->encrypt(ssl, encryptStart + divLen, + encryptStart + divLen, modLen + ssl->enMacSize + padLen); + + if (rc < 0 || (*c - out->end != messageSize)) { + psFree(ssl->zlibBuffer, ssl->bufferPool); ssl->zlibBuffer = NULL; + deflateEnd(&ssl->deflate); + psTraceIntInfo("Error encrypting 3: %d\n", rc); + return MATRIXSSL_ERROR; + } + psFree(ssl->zlibBuffer, ssl->bufferPool); ssl->zlibBuffer = NULL; + /* Will not need the context any longer since FINISHED is the only + supported message */ + deflateEnd(&ssl->deflate); + +#ifdef USE_DTLS +/* + Waited to increment record sequence number until completely finished + with the encoding because the HMAC in DTLS uses the rsn of current record +*/ + if (ssl->flags & SSL_FLAGS_DTLS) { + dtlsIncrRsn(ssl); + } +#endif /* USE_DTLS */ + + return MATRIXSSL_SUCCESS; +} +#endif /* USE_ZLIB_COMPRESSION */ + + +/******************************************************************************/ +/* + Flights are encypted after they are fully written so this function + just moves the buffer forward to account for the encryption overhead that + will be filled in later +*/ +static int32 postponeEncryptRecord(ssl_t *ssl, int32 type, int32 hsMsg, + int32 messageSize, int32 padLen, unsigned char *pt, + sslBuf_t *out, unsigned char **c) +{ + flightEncode_t *flight, *prev; + unsigned char *encryptStart; + int32 ptLen; + + if ((flight = psMalloc(ssl->flightPool, sizeof(flightEncode_t))) == NULL) { + return PS_MEM_FAIL; + } + memset(flight, 0x0, sizeof(flightEncode_t)); + if (ssl->flightEncode == NULL) { + ssl->flightEncode = flight; + } else { + prev = ssl->flightEncode; + while (prev->next) { + prev = prev->next; + } + prev->next = flight; + } + encryptStart = out->end + ssl->recordHeadLen; + + if (hsMsg == SSL_HS_FINISHED) { + if (ssl->cipher->flags & (CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_CCM)) { + encryptStart += TLS_EXPLICIT_NONCE_LEN; + } + } else if (ssl->flags & SSL_FLAGS_AEAD_W) { + encryptStart += AEAD_NONCE_LEN(ssl); /* Move past the plaintext nonce */ + } + + ptLen = (int32)(*c - encryptStart); + + flight->start = pt; + flight->len = ptLen; + flight->type = type; + flight->padLen = padLen; + flight->messageSize = messageSize; + flight->hsMsg = hsMsg; + flight->seqDelay = ssl->seqDelay; + + if (hsMsg == SSL_HS_FINISHED) { + if (!(ssl->cipher->flags & + (CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_CHACHA | CRYPTO_FLAGS_CCM))) { + if (ssl->extFlags.truncated_hmac) { + *c += 10; + } else { + *c += ssl->cipher->macSize; + } + } else { + *c += ssl->cipher->macSize; + } + } else { + *c += ssl->enMacSize; + } + *c += padLen; + + if (hsMsg == SSL_HS_FINISHED) { + if (ssl->cipher->flags & + (CRYPTO_FLAGS_GCM| CRYPTO_FLAGS_CHACHA | CRYPTO_FLAGS_CCM)) { + *c += AEAD_TAG_LEN(ssl); + } + } else if (ssl->flags & SSL_FLAGS_AEAD_W) { + *c += AEAD_TAG_LEN(ssl); /* c is tracking end of record here and the + tag has not yet been accounted for */ + } + +#ifdef USE_TLS_1_1 +#endif /* USE_TLS_1_1 */ + + if (*c - out->end != messageSize) { + psTraceIntInfo("postponeEncryptRecord length test failed: wanted %d ", + messageSize); + psTraceIntInfo("but generated %d\n", (int32)(*c - out->end)); + return MATRIXSSL_ERROR; + } + return MATRIXSSL_SUCCESS; +} + +/******************************************************************************/ +/* + Encrypt the message using the current cipher. This call is used in + conjunction with the writeRecordHeader() function above to finish writing + an SSL record. Updates handshake hash if necessary, generates message + MAC, writes the padding, and does the encryption. + + messageSize is the final size, with header, mac and padding of the output + messageSize - 5 = ssl.recLen + *c - encryptStart = plaintext length +*/ +static int32 encryptRecord(ssl_t *ssl, int32 type, int32 hsMsgType, + int32 messageSize, int32 padLen, unsigned char *pt, + sslBuf_t *out, unsigned char **c) +{ + unsigned char *encryptStart; + int32 rc, ptLen, divLen, modLen; + +#ifdef USE_ZLIB_COMPRESSION + /* In the current implementation, MatrixSSL will only internally handle + the compression and decompression of the FINISHED message. Application + data will be compressed and decompressed by the caller. + Re-handshakes are not supported and this would have been caught + earlier in the state machine so if the record type is HANDSHAKE we + can be sure this is the FINISHED message + + This should allow compatibility with SSL implementations that support + ZLIB compression */ + if (ssl->flags & SSL_FLAGS_WRITE_SECURE && ssl->compression && + type == SSL_RECORD_TYPE_HANDSHAKE) { + return encryptCompressedRecord(ssl, type, messageSize, pt, out, c); + } +#endif + + encryptStart = out->end + ssl->recordHeadLen; + + if (ssl->flags & SSL_FLAGS_AEAD_W) { + encryptStart += AEAD_NONCE_LEN(ssl); /* Move past the plaintext nonce */ + ssl->outRecType = (unsigned char) type; + } + + ptLen = (int32)(*c - encryptStart); +#ifdef USE_TLS +#ifdef USE_TLS_1_1 + if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) && + (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1)) { +/* + Don't add the random bytes into the hash of the message. Makes + things very easy on the other side to simply discard the randoms +*/ + if (type == SSL_RECORD_TYPE_HANDSHAKE) { + sslUpdateHSHash(ssl, pt + ssl->enBlockSize, + ptLen - ssl->enBlockSize); + if (hsMsgType == SSL_HS_CLIENT_KEY_EXCHANGE && + ssl->extFlags.extended_master_secret == 1) { + if (tlsExtendedDeriveKeys(ssl) < 0) { + return MATRIXSSL_ERROR; + } + } + } + if (type == SSL_RECORD_TYPE_APPLICATION_DATA) { + /* Application data is passed in with real pt from user but + with the length of the explict IV added already */ + *c += ssl->generateMac(ssl, (unsigned char)type, + pt, ptLen - ssl->enBlockSize, *c); + /* While we are in here, let's see if this is an in-situ case */ + if (encryptStart + ssl->enBlockSize == pt) { + pt = encryptStart; + } else { + /* Not in-situ. Encrypt the explict IV now */ + if ((rc = ssl->encrypt(ssl, encryptStart, + encryptStart, ssl->enBlockSize)) < 0) { + psTraceIntInfo("Error encrypting explicit IV: %d\n", rc); + return MATRIXSSL_ERROR; + } + encryptStart += ssl->enBlockSize; + ptLen -= ssl->enBlockSize; + } + } else { + /* Handshake messages have been passed in with plaintext that + begins with the explicit IV and size included */ + *c += ssl->generateMac(ssl, (unsigned char)type, + pt + ssl->enBlockSize, ptLen - ssl->enBlockSize, *c); + } + } else { +#endif /* USE_TLS_1_1 */ + if (type == SSL_RECORD_TYPE_HANDSHAKE) { + if ((rc = sslUpdateHSHash(ssl, pt, ptLen)) < 0) { + return rc; + } + /* Explicit state test for peforming the extended master secret + calculation. The sslUpdateHsHash immediately above has just + ran the ClientKeyExchange message through the hash so now + we can snapshot and create the key block */ + if (hsMsgType == SSL_HS_CLIENT_KEY_EXCHANGE && + ssl->extFlags.extended_master_secret == 1) { + if (tlsExtendedDeriveKeys(ssl) < 0) { + return MATRIXSSL_ERROR; + } + } + } + if (ssl->generateMac) { + *c += ssl->generateMac(ssl, (unsigned char)type, pt, ptLen, *c); + } +#ifdef USE_TLS_1_1 + } +#endif /* USE_TLS_1_1 */ +#else /* USE_TLS */ + if (type == SSL_RECORD_TYPE_HANDSHAKE) { + sslUpdateHSHash(ssl, pt, ptLen); + } + *c += ssl->generateMac(ssl, (unsigned char)type, pt, + ptLen, *c); +#endif /* USE_TLS */ + + *c += sslWritePad(*c, (unsigned char)padLen); + + if (ssl->flags & SSL_FLAGS_AEAD_W) { + *c += AEAD_TAG_LEN(ssl); /* c is tracking end of record here and the + tag has not yet been accounted for */ + } + + if (pt == encryptStart) { + /* In-situ encode */ + if ((rc = ssl->encrypt(ssl, pt, encryptStart, + (uint32)(*c - encryptStart))) < 0 || + *c - out->end != messageSize) { + psTraceIntInfo("Error encrypting 1: %d\n", rc); + psTraceIntInfo("messageSize is %d\n", messageSize); + psTraceIntInfo("pointer diff %d\n", *c - out->end); + psTraceIntInfo("cipher suite %d\n", ssl->cipher->ident); + return MATRIXSSL_ERROR; + } + } else { + /* + Non-insitu requres two encrypts, one for plaintext and one for the + any < blockSize remainder of the plaintext and the mac and pad + */ + if (ssl->flags & SSL_FLAGS_WRITE_SECURE) { + if (ssl->cipher->blockSize > 1) { + divLen = ptLen & ~(ssl->cipher->blockSize - 1); + modLen = ptLen & (ssl->cipher->blockSize - 1); + } else { + if (ssl->flags & SSL_FLAGS_AEAD_W) { + divLen = ptLen + AEAD_TAG_LEN(ssl); + modLen = 0; + } else { + divLen = ptLen; + modLen = 0; + } + } + if (divLen > 0) { + rc = ssl->encrypt(ssl, pt, encryptStart, divLen); + if (rc < 0) { + psTraceIntInfo("Error encrypting 2: %d\n", rc); + return MATRIXSSL_ERROR; + } + } + if (modLen > 0) { + memcpy(encryptStart + divLen, pt + divLen, modLen); + } + rc = ssl->encrypt(ssl, encryptStart + divLen, + encryptStart + divLen, modLen + ssl->enMacSize + padLen); + } else { + rc = ssl->encrypt(ssl, pt, encryptStart, + (uint32)(*c - encryptStart)); + } + if (rc < 0 || (*c - out->end != messageSize)) { + psTraceIntInfo("Error encrypting 3: %d\n", rc); + return MATRIXSSL_ERROR; + } + } +#ifdef USE_DTLS +/* + Waited to increment record sequence number until completely finished + with the encoding because the HMAC in DTLS uses the rsn of current record +*/ + if (ssl->flags & SSL_FLAGS_DTLS) { + dtlsIncrRsn(ssl); + } +#endif /* USE_DTLS */ + + if (*c - out->end != messageSize) { + psTraceInfo("encryptRecord length sanity test failed\n"); + return MATRIXSSL_ERROR; + } + return MATRIXSSL_SUCCESS; +} + +#ifdef USE_SERVER_SIDE_SSL +/******************************************************************************/ +/* + Write out the ServerHello message +*/ +static int32 writeServerHello(ssl_t *ssl, sslBuf_t *out) +{ + unsigned char *c, *end, *encryptStart; + uint16_t messageSize; + uint8_t padLen; + int32 t, rc, extLen = 0; + + psTraceHs("<<< Server creating SERVER_HELLO message\n"); + c = out->end; + end = out->buf + out->size; +/* + Calculate the size of the message up front, and verify we have room + We assume there will be a sessionId in the message, and make adjustments + below if there is no sessionId. +*/ + messageSize = + ssl->recordHeadLen + + ssl->hshakeHeadLen + + 38 + SSL_MAX_SESSION_ID_SIZE; + +#ifdef ENABLE_SECURE_REHANDSHAKES +#ifdef USE_DTLS +/* + Can run into a problem if doing a new resumed handshake because the flight + is SERVER_HELLO, CCS, and FINISHED which will populate myVerifyData + which will confuse the resend logic here that we are doing a rehandshake. + If peerVerifyData isn't available and we're doing a retransmit we know + this is the problematic case so forget we have a myVerifyData +*/ + if (ssl->flags & SSL_FLAGS_DTLS) { + if ((ssl->secureRenegotiationFlag == PS_TRUE) && (ssl->retransmit == 1) + && (ssl->myVerifyDataLen > 0) && (ssl->peerVerifyDataLen == 0)) + { + ssl->myVerifyDataLen = 0; + } + } +#endif +/* + The RenegotiationInfo extension lengths are well known +*/ + if (ssl->secureRenegotiationFlag == PS_TRUE && ssl->myVerifyDataLen == 0) { + extLen = 7; /* 00 05 ff 01 00 01 00 */ + } else if (ssl->secureRenegotiationFlag == PS_TRUE && + ssl->myVerifyDataLen > 0) { + extLen = 2 + 5 + ssl->myVerifyDataLen + ssl->peerVerifyDataLen; + } +#endif /* ENABLE_SECURE_REHANDSHAKES */ + +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ECC_CIPHER) { + if (extLen == 0) { + extLen = 2; /* if first extension, add two byte total len */ + } + /* EXT_ELLIPTIC_POINTS - hardcoded to 'uncompressed' support */ + extLen += 6; /* 00 0B 00 02 01 00 */ + } +#endif /* USE_ECC_CIPHER_SUITE */ + + if (ssl->maxPtFrag < SSL_MAX_PLAINTEXT_LEN) { + if (extLen == 0) { + extLen = 2; + } + extLen += 5; + } + + if (ssl->extFlags.truncated_hmac) { + if (extLen == 0) { + extLen = 2; + } + extLen += 4; + } + + if (ssl->extFlags.extended_master_secret) { + if (extLen == 0) { + extLen = 2; + } + extLen += 4; + } + + +#ifdef USE_STATELESS_SESSION_TICKETS + if (ssl->sid && ssl->sid->sessionTicketState == SESS_TICKET_STATE_RECVD_EXT) { + if (extLen == 0) { + extLen = 2; + } + extLen += 4; + } +#endif + + if (ssl->extFlags.sni) { + if (extLen == 0) { + extLen = 2; + } + extLen += 4; + } +#ifdef USE_OCSP + if (ssl->extFlags.status_request) { + if (extLen == 0) { + extLen = 2; + } + extLen += 4; + } +#endif + +#ifdef USE_ALPN + if (ssl->alpnLen) { + if (extLen == 0) { + extLen = 2; + } + extLen += 6 + 1 + ssl->alpnLen; /* 6 type/len + 1 len + data */ + } +#endif + + messageSize += extLen; + t = 1; +#ifdef USE_DTLS + if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 1)) { +/* + All retransmits must generate identical handshake messages as the + original. This is to ensure both sides are running the same material + through the handshake hash +*/ + t = 0; + } +#endif /* USE_DTLS */ + + if (t) { + /** @security RFC says to set the first 4 bytes to time, but best common practice is + to use full 32 bytes of random. This is forward looking to TLS 1.3, and also works + better for embedded platforms and FIPS secret key material. + @see https://www.ietf.org/mail-archive/web/tls/current/msg09861.html */ +#ifdef SEND_HELLO_RANDOM_TIME + /* First 4 bytes of the serverRandom are the unix time to prevent replay + attacks, the rest are random */ + t = psGetTime(NULL, ssl->userPtr); + ssl->sec.serverRandom[0] = (unsigned char)((t & 0xFF000000) >> 24); + ssl->sec.serverRandom[1] = (unsigned char)((t & 0xFF0000) >> 16); + ssl->sec.serverRandom[2] = (unsigned char)((t & 0xFF00) >> 8); + ssl->sec.serverRandom[3] = (unsigned char)(t & 0xFF); + if (matrixCryptoGetPrngData(ssl->sec.serverRandom + 4, + SSL_HS_RANDOM_SIZE - 4, ssl->userPtr) < 0) { + return MATRIXSSL_ERROR; + } +#else + if (matrixCryptoGetPrngData(ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE , ssl->userPtr) < 0) { + return MATRIXSSL_ERROR; + } +#endif + } + +/* + We register session here because at this point the serverRandom value is + populated. If we are able to register the session, the sessionID and + sessionIdLen fields will be non-NULL, otherwise the session couldn't + be registered. +*/ + if (!(ssl->flags & SSL_FLAGS_RESUMED)) { + matrixRegisterSession(ssl); + } + messageSize -= (SSL_MAX_SESSION_ID_SIZE - ssl->sessionIdLen); + + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_SERVER_HELLO, &messageSize, &padLen, &encryptStart, + end, &c)) < 0) { + return rc; + } +/* + First two fields in the ServerHello message are the major and minor + SSL protocol versions we agree to talk with +*/ + *c = ssl->majVer; c++; + *c = ssl->minVer; c++; + +/* + The next 32 bytes are the server's random value, to be combined with + the client random and premaster for key generation later +*/ + memcpy(c, ssl->sec.serverRandom, SSL_HS_RANDOM_SIZE); + c += SSL_HS_RANDOM_SIZE; +/* + The next data is a single byte containing the session ID length, + and up to 32 bytes containing the session id. + First register the session, which will give us a session id and length + if not all session slots in the table are used +*/ + *c = (unsigned char)ssl->sessionIdLen; c++; + if (ssl->sessionIdLen > 0) { + memcpy(c, ssl->sessionId, ssl->sessionIdLen); + c += ssl->sessionIdLen; + } +/* + Two byte cipher suite we've chosen based on the list sent by the client + and what we support. + One byte compression method (always zero) +*/ + *c = (ssl->cipher->ident & 0xFF00) >> 8; c++; + *c = ssl->cipher->ident & 0xFF; c++; +#ifdef USE_ZLIB_COMPRESSION + if (ssl->compression) { + *c = 1; c++; + } else { + *c = 0; c++; + } +#else + *c = 0; c++; +#endif + + if (extLen != 0) { + extLen -= 2; /* Don't add self to total extension len */ + *c = (extLen & 0xFF00) >> 8; c++; + *c = extLen & 0xFF; c++; + + if (ssl->maxPtFrag < SSL_MAX_PLAINTEXT_LEN) { + *c = 0x0; c++; + *c = 0x1; c++; + *c = 0x0; c++; + *c = 0x1; c++; + + if (ssl->maxPtFrag == 0x200) { + *c = 0x1; c++; + } + if (ssl->maxPtFrag == 0x400) { + *c = 0x2; c++; + } + if (ssl->maxPtFrag == 0x800) { + *c = 0x3; c++; + } + if (ssl->maxPtFrag == 0x1000) { + *c = 0x4; c++; + } + } + if (ssl->extFlags.truncated_hmac) { + *c = (EXT_TRUNCATED_HMAC & 0xFF00) >> 8; c++; + *c = EXT_TRUNCATED_HMAC & 0xFF; c++; + *c = 0; c++; + *c = 0; c++; + } + if (ssl->extFlags.extended_master_secret) { + *c = (EXT_EXTENDED_MASTER_SECRET & 0xFF00) >> 8; c++; + *c = EXT_EXTENDED_MASTER_SECRET & 0xFF; c++; + *c = 0; c++; + *c = 0; c++; + } + + +#ifdef USE_STATELESS_SESSION_TICKETS + if (ssl->sid && + ssl->sid->sessionTicketState == SESS_TICKET_STATE_RECVD_EXT) { + /* This empty extension is ALWAYS an indication to the client that + a NewSessionTicket handshake message will be sent */ + *c = (EXT_SESSION_TICKET & 0xFF00) >> 8; c++; + *c = EXT_SESSION_TICKET & 0xFF; c++; + *c = 0; c++; + *c = 0; c++; + } +#endif + + if (ssl->extFlags.sni) { + *c = (EXT_SNI & 0xFF00) >> 8; c++; + *c = EXT_SNI & 0xFF; c++; + *c = 0; c++; + *c = 0; c++; + } +#ifdef USE_OCSP + if (ssl->extFlags.status_request) { + *c = (EXT_STATUS_REQUEST & 0xFF00) >> 8; c++; + *c = EXT_STATUS_REQUEST & 0xFF; c++; + *c = 0; c++; + *c = 0; c++; + } +#endif + +#ifdef USE_ALPN + if (ssl->alpnLen) { + *c = (EXT_ALPN & 0xFF00) >> 8; c++; + *c = EXT_ALPN & 0xFF; c++; + /* Total ext len can be hardcoded +3 because only one proto reply */ + *c = ((ssl->alpnLen + 3) & 0xFF00) >> 8; c++; + *c = (ssl->alpnLen + 3) & 0xFF; c++; + /* Can only ever be a reply of one proto so explict len +1 works */ + *c = ((ssl->alpnLen + 1) & 0xFF00) >> 8; c++; + *c = (ssl->alpnLen + 1) & 0xFF; c++; + *c = ssl->alpnLen; c++; + memcpy(c, ssl->alpn, ssl->alpnLen); + c += ssl->alpnLen; + psFree(ssl->alpn, ssl->sPool); ssl->alpn = NULL; /* app must store if needed */ + ssl->alpnLen = 0; + } +#endif + +#ifdef ENABLE_SECURE_REHANDSHAKES + if (ssl->secureRenegotiationFlag == PS_TRUE) { + /* RenegotiationInfo*/ + *c = (EXT_RENEGOTIATION_INFO & 0xFF00) >> 8; c++; + *c = EXT_RENEGOTIATION_INFO & 0xFF; c++; + if (ssl->myVerifyDataLen == 0) { + *c = 0; c++; + *c = 1; c++; + *c = 0; c++; + } else { + *c =((ssl->myVerifyDataLen+ssl->peerVerifyDataLen+1)&0xFF00)>>8; + c++; + *c = (ssl->myVerifyDataLen + ssl->peerVerifyDataLen + 1) & 0xFF; + c++; + *c = (ssl->myVerifyDataLen + ssl->peerVerifyDataLen) & 0xFF;c++; + memcpy(c, ssl->peerVerifyData, ssl->peerVerifyDataLen); + c += ssl->peerVerifyDataLen; + memcpy(c, ssl->myVerifyData, ssl->myVerifyDataLen); + c += ssl->myVerifyDataLen; + } + } +#endif /* ENABLE_SECURE_REHANDSHAKES */ + +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ECC_CIPHER) { + *c = (EXT_ELLIPTIC_POINTS & 0xFF00) >> 8; c++; + *c = EXT_ELLIPTIC_POINTS & 0xFF; c++; + *c = 0x00; c++; + *c = 0x02; c++; + *c = 0x01; c++; + *c = 0x00; c++; + } +#endif /* USE_ECC_CIPHER_SUITE */ + } + + if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_SERVER_HELLO, messageSize, padLen, encryptStart, out, &c)) + < 0) { + return rc; + } +/* + If we're resuming a session, we now have the clientRandom, master and + serverRandom, so we can derive keys which we'll be using shortly. +*/ + if (ssl->flags & SSL_FLAGS_RESUMED) { + if ((rc = sslCreateKeys(ssl)) < 0) { + return rc; + } + } + out->end = c; + +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, SH_SENT_STAT, 1); +#endif + return MATRIXSSL_SUCCESS; +} + +/******************************************************************************/ +/* + ServerHelloDone message is a blank handshake message +*/ +static int32 writeServerHelloDone(ssl_t *ssl, sslBuf_t *out) +{ + unsigned char *c, *end, *encryptStart; + uint8_t padLen; + uint16_t messageSize; + int32_t rc; + + psTraceHs("<<< Server creating SERVER_HELLO_DONE message\n"); + c = out->end; + end = out->buf + out->size; + messageSize = + ssl->recordHeadLen + + ssl->hshakeHeadLen; + + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_SERVER_HELLO_DONE, &messageSize, &padLen, + &encryptStart, end, &c)) < 0) { + return rc; + } + + if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_SERVER_HELLO_DONE, messageSize, padLen, encryptStart, out, + &c)) < 0) { + return rc; + } + out->end = c; + return MATRIXSSL_SUCCESS; +} +#ifdef USE_PSK_CIPHER_SUITE +/******************************************************************************/ +/* + The PSK cipher version of ServerKeyExchange. Was able to single this + message out with a dedicated write simply due to the flight + logic of DH ciphers. The ClientKeyExchange message for PSK was rolled + into the generic function, for example. +*/ +static int32 writePskServerKeyExchange(ssl_t *ssl, sslBuf_t *out) +{ + unsigned char *c, *end, *encryptStart; + unsigned char *hint; + uint16_t messageSize; + uint8_t padLen, hintLen; + int32_t rc; + + psTraceHs("<<< Server creating SERVER_KEY_EXCHANGE message\n"); +#ifdef USE_DHE_CIPHER_SUITE +/* + This test prevents a second ServerKeyExchange from being written if a + PSK_DHE cipher was choosen. This is an ugly side-effect of the many + combinations of cipher suites being supported in the 'flight' based + state machine model +*/ + if (ssl->flags & SSL_FLAGS_DHE_KEY_EXCH) { + return MATRIXSSL_SUCCESS; + } +#endif /* USE_DHE_CIPHER_SUITE */ + + if (matrixPskGetHint(ssl, &hint, &hintLen) < 0) { + return MATRIXSSL_ERROR; + } + if (hint == NULL || hintLen == 0) { + return MATRIXSSL_SUCCESS; + } + + c = out->end; + end = out->buf + out->size; + + messageSize = ssl->recordHeadLen + ssl->hshakeHeadLen + hintLen + 2; + + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_SERVER_KEY_EXCHANGE, &messageSize, &padLen, + &encryptStart, end, &c)) < 0) { + return rc; + } + + *c = (hintLen & 0xFF00) >> 8; c++; + *c = (hintLen & 0xFF); c++; + memcpy(c, hint, hintLen); + c += hintLen; + + if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_SERVER_KEY_EXCHANGE, messageSize, padLen, encryptStart, + out, &c)) < 0) { + return rc; + } + out->end = c; + return MATRIXSSL_SUCCESS; +} +#endif /* USE_PSK_CIPHER_SUITE */ + +#ifdef USE_STATELESS_SESSION_TICKETS /* Already inside a USE_SERVER_SIDE block */ +static int32 writeNewSessionTicket(ssl_t *ssl, sslBuf_t *out) +{ + unsigned char *c, *end, *encryptStart; + uint8_t padLen; + uint16_t messageSize; + int32_t rc; + + psTraceHs("<<< Server creating NEW_SESSION_TICKET message\n"); + c = out->end; + end = out->buf + out->size; + + /* magic 6 is 4 bytes lifetime hint and 2 bytes len */ + messageSize = ssl->recordHeadLen + ssl->hshakeHeadLen + + matrixSessionTicketLen() + 6; + + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_NEW_SESSION_TICKET, &messageSize, &padLen, + &encryptStart, end, &c)) < 0) { + return rc; + } + + rc = (int32)(end - c); + if (matrixCreateSessionTicket(ssl, c, &rc) < 0) { + psTraceInfo("Error generating session ticket\n"); + return MATRIXSSL_ERROR; + } + c += rc; + + if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_NEW_SESSION_TICKET, messageSize, padLen, encryptStart, out, + &c)) < 0) { + return rc; + } + out->end = c; + + ssl->sid->sessionTicketState = SESS_TICKET_STATE_USING_TICKET; + + return PS_SUCCESS; +} +#endif /* USE_STATELESS_SESSION_TICKETS */ + +#ifdef USE_DHE_CIPHER_SUITE /* Already inside a USE_SERVER_SIDE block */ +/******************************************************************************/ +/* + Write out the ServerKeyExchange message. +*/ +static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen, + unsigned char *p, uint32 gLen, unsigned char *g) +{ + unsigned char *c, *end, *encryptStart; + uint8_t padLen; + uint16_t messageSize = 0; + int32_t rc; +#ifndef USE_ONLY_PSK_CIPHER_SUITE + uint16_t hashSize; + unsigned char *hsMsgHash, *sigStart; + psDigestContext_t digestCtx; + pkaAfter_t *pkaAfter; + void *pkiData = ssl->userPtr; +#endif + +#if defined(USE_PSK_CIPHER_SUITE) && defined(USE_ANON_DH_CIPHER_SUITE) + unsigned char *hint; + uint8_t hintLen; +#endif /* USE_PSK_CIPHER_SUITE && USE_ANON_DH_CIPHER_SUITE */ +#ifdef USE_ECC_CIPHER_SUITE + uint16_t eccPubKeyLen; +#endif /* USE_ECC_CIPHER_SUITE */ + + psTraceHs("<<< Server creating SERVER_KEY_EXCHANGE message\n"); + c = out->end; + end = out->buf + out->size; + +/* + Calculate the size of the message up front, and verify we have room +*/ +#ifdef USE_ANON_DH_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ANON_CIPHER) { + messageSize = ssl->recordHeadLen + ssl->hshakeHeadLen + + 6 + pLen + gLen + ssl->sec.dhKeyPriv->size; + #ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + messageSize -= 2; /* hashSigAlg not going to be needed */ + } + #endif + + #ifdef USE_PSK_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + if (matrixPskGetHint(ssl, &hint, &hintLen) < 0) { + return MATRIXSSL_ERROR; + } +/* + * RFC4279: In the absence of an application profile specification + * specifying otherwise, servers SHOULD NOT provide an identity hint + * and clients MUST ignore the identity hint field. Applications that + * do use this field MUST specify its contents, how the value is + * chosen by the TLS server, and what the TLS client is expected to do + * with the value. + * @note Unlike pure PSK cipher which will omit the ServerKeyExchange + * message if the hint is NULL, the DHE_PSK exchange simply puts + * two zero bytes in this case, since the message must still be sent + * to exchange the DHE public key. + */ + messageSize += 2; /* length of hint (even if zero) */ + if (hintLen != 0 && hint != NULL) { + messageSize += hintLen; + } + } + #endif /* USE_PSK_CIPHER_SUITE */ + } else { +#endif /* USE_ANON_DH_CIPHER_SUITE */ + #ifdef USE_ECC_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ECC_CIPHER) { + /* ExportKey portion */ + eccPubKeyLen = (ssl->sec.eccKeyPriv->curve->size * 2) + 1; + + if (ssl->flags & SSL_FLAGS_DHE_WITH_RSA) { + messageSize = ssl->recordHeadLen + ssl->hshakeHeadLen + + eccPubKeyLen + 4 + ssl->keys->privKey.keysize + 2; + } else if (ssl->flags & SSL_FLAGS_DHE_WITH_DSA) { + messageSize = ssl->recordHeadLen + ssl->hshakeHeadLen + 6 + + eccPubKeyLen; + /* NEGATIVE ECDSA - Adding ONE spot for a 0x0 byte in the + ECDSA signature. This will allow us to be right ~50% of + the time and not require any manual manipulation + + However, if this is a 521 curve there is no chance + the final byte could be negative if the full 66 + bytes are needed because there can only be a single + low bit for that sig size. So subtract that byte + back out to stay around the 50% no-move goal */ + if (ssl->keys->privKey.keysize != 132) { + messageSize += 1; + } + messageSize += ssl->keys->privKey.keysize; + /* Signature portion */ + messageSize += 6; /* 6 = 2 ASN_SEQ, 4 ASN_BIG */ + /* BIG EC KEY. The sig is 2 bytes len, 1 byte SEQ, + 1 byte length (+1 OPTIONAL byte if length is >=128), + 1 byte INT, 1 byte rLen, r, 1 byte INT, 1 byte sLen, s. + So the +4 here are the 2 INT and 2 rLen/sLen bytes on + top of the keysize */ + if (ssl->keys->privKey.keysize + 4 >= 128) { + messageSize++; /* Extra byte for 'long' asn.1 encode */ + } +#ifdef USE_DTLS + if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 1)) { + /* We already know if this signature got resized */ + messageSize += ssl->ecdsaSizeChange; + } +#endif + } + } else { + #endif /* USE_ECC_CIPHER_SUITE */ + #ifdef REQUIRE_DH_PARAMS + messageSize = ssl->recordHeadLen + ssl->hshakeHeadLen + + 8 + pLen + gLen + ssl->sec.dhKeyPriv->size + + ssl->keys->privKey.keysize; + #endif /* REQUIRE_DH_PARAMS */ + #ifdef USE_ECC_CIPHER_SUITE + } + #endif /* USE_ECC_CIPHER_SUITE */ +#ifdef USE_ANON_DH_CIPHER_SUITE + } +#endif /* USE_ANON_DH_CIPHER_SUITE */ + + if (messageSize == 0) { + /* This api was called without DHE, PSK and ECC enabled */ + return MATRIXSSL_ERROR; + } +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + messageSize += 2; /* hashSigAlg */ + } +#endif + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_SERVER_KEY_EXCHANGE, &messageSize, &padLen, + &encryptStart, end, &c)) < 0) { + return rc; + } +#ifndef USE_ONLY_PSK_CIPHER_SUITE + sigStart = c; +#endif + +#if defined(USE_PSK_CIPHER_SUITE) && defined(USE_ANON_DH_CIPHER_SUITE) + /* PSK suites have a leading PSK identity hint (may be zero length) */ + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + *c = (hintLen & 0xFF00) >> 8; c++; + *c = (hintLen & 0xFF); c++; + if (hintLen != 0 && hint != NULL) { + memcpy(c, hint, hintLen); + c += hintLen; + } + } +#endif /* USE_PSK_CIPHER_SUITE && USE_ANON_DH_CIPHER_SUITE */ + +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ECC_CIPHER) { +/* + 1 byte - ECCurveType (NamedCurve enum is 3) + 2 byte - NamedCurve id +*/ + *c = 3; c++; /* NamedCurve enum */ + *c = (ssl->sec.eccKeyPriv->curve->curveId & 0xFF00) >> 8; c++; + *c = (ssl->sec.eccKeyPriv->curve->curveId & 0xFF); c++; + *c = eccPubKeyLen & 0xFF; c++; + if (psEccX963ExportKey(ssl->hsPool, ssl->sec.eccKeyPriv, c, + &eccPubKeyLen) != 0) { + return MATRIXSSL_ERROR; + } + c += eccPubKeyLen; + + } else { +#endif +#ifdef REQUIRE_DH_PARAMS +/* + The message itself; + 2 bytes p len, p, 2 bytes g len, g, 2 bytes pubKeyLen, pubKey + + Size tests have all ready been taken care of a level up from this +*/ + *c = (pLen & 0xFF00) >> 8; c++; + *c = pLen & 0xFF; c++; + memcpy(c, p, pLen); + c += pLen; + *c = (gLen & 0xFF00) >> 8; c++; + *c = gLen & 0xFF; c++; + memcpy(c, g, gLen); + c += gLen; + *c = (ssl->sec.dhKeyPriv->size & 0xFF00) >> 8; c++; + *c = ssl->sec.dhKeyPriv->size & 0xFF; c++; + { + uint16_t dhLen = end - c; + if (psDhExportPubKey(ssl->hsPool, ssl->sec.dhKeyPriv, c, &dhLen) < 0) { + return MATRIXSSL_ERROR; + } + psAssert(dhLen == ssl->sec.dhKeyPriv->size); + } + c += ssl->sec.dhKeyPriv->size; +#endif /* REQUIRE_DH_PARAMS */ +#ifdef USE_ECC_CIPHER_SUITE + } +#endif /* USE_ECC_CIPHER_SUITE */ + + /* RFC 5246 - 7.4.3. Server Key Exchange Message + In addition, the hash and signature algorithms MUST be compatible + with the key in the server's end-entity certificate. RSA keys MAY be + used with any permitted hash algorithm, subject to restrictions in + the certificate, if any. */ + +#ifdef USE_RSA_CIPHER_SUITE +/* + RSA authentication requires an additional signature portion to the message +*/ + if (ssl->flags & SSL_FLAGS_DHE_WITH_RSA) { +#ifndef USE_ONLY_PSK_CIPHER_SUITE + /* Saved aside for pkaAfter_t */ + if ((hsMsgHash = psMalloc(ssl->hsPool, SHA384_HASH_SIZE)) == NULL) { + return PS_MEM_FAIL; + } +#endif +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + /* Using the algorithm from the certificate */ + if (ssl->keys->cert->sigAlgorithm == OID_SHA256_RSA_SIG) { + hashSize = SHA256_HASH_SIZE; + psSha256Init(&digestCtx.sha256); + psSha256Update(&digestCtx.sha256, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha256Update(&digestCtx.sha256, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha256Update(&digestCtx.sha256, sigStart, + (uint32)(c - sigStart)); + psSha256Final(&digestCtx.sha256, hsMsgHash); + *c++ = 0x4; + *c++ = 0x1; +#ifdef USE_SHA384 + } else if (ssl->keys->cert->sigAlgorithm == OID_SHA384_RSA_SIG) { + hashSize = SHA384_HASH_SIZE; + psSha384Init(&digestCtx.sha384); + psSha384Update(&digestCtx.sha384, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha384Update(&digestCtx.sha384, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha384Update(&digestCtx.sha384, sigStart, + (uint32)(c - sigStart)); + psSha384Final(&digestCtx.sha384, hsMsgHash); + *c++ = 0x5; + *c++ = 0x1; +#endif /* USE_SHA384 */ + /* If MD5, just send a SHA1. Don't want to contribute to any + longevity of MD5 */ +#ifdef USE_SHA1 + } else if (ssl->keys->cert->sigAlgorithm == OID_SHA1_RSA_SIG || + ssl->keys->cert->sigAlgorithm == OID_MD5_RSA_SIG) { + hashSize = SHA1_HASH_SIZE; + psSha1Init(&digestCtx.sha1); + psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, sigStart, (uint32)(c - sigStart)); + psSha1Final(&digestCtx.sha1, hsMsgHash); + *c++ = 0x2; + *c++ = 0x1; +#endif + } else { + psTraceIntInfo("Unavailable sigAlgorithm for SKE write: %d\n", + ssl->keys->cert->sigAlgorithm); + psFree(hsMsgHash, ssl->hsPool); + return PS_UNSUPPORTED_FAIL; + } + } else { +#if defined(USE_SHA1) && defined(USE_MD5) + hashSize = MD5_HASH_SIZE + SHA1_HASH_SIZE; + psMd5Init(&digestCtx.md5); + psMd5Update(&digestCtx.md5, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psMd5Update(&digestCtx.md5, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psMd5Update(&digestCtx.md5, sigStart, (uint32)(c - sigStart)); + psMd5Final(&digestCtx.md5, hsMsgHash); + + psSha1Init(&digestCtx.sha1); + psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, sigStart, (uint32)(c - sigStart)); + psSha1Final(&digestCtx.sha1, hsMsgHash + MD5_HASH_SIZE); +#else + psTraceIntInfo("Unavailable sigAlgorithm for SKE write: %d\n", + ssl->keys->cert->sigAlgorithm); + psFree(hsMsgHash, ssl->hsPool); + return PS_UNSUPPORTED_FAIL; +#endif + } +#else /* USE_TLS_1_2 */ + hashSize = MD5_HASH_SIZE + SHA1_HASH_SIZE; + psMd5Init(&digestCtx.md5); + psMd5Update(&digestCtx.md5, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); + psMd5Update(&digestCtx.md5, ssl->sec.serverRandom, SSL_HS_RANDOM_SIZE); + psMd5Update(&digestCtx.md5, sigStart, (uint32)(c - sigStart)); + psMd5Final(&digestCtx.md5, hsMsgHash); + + psSha1Init(&digestCtx.sha1); + psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom, SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, sigStart, (uint32)(c - sigStart)); + psSha1Final(&digestCtx.sha1, hsMsgHash + MD5_HASH_SIZE); +#endif /* USE_TLS_1_2 */ + + *c = (ssl->keys->privKey.keysize & 0xFF00) >> 8; c++; + *c = ssl->keys->privKey.keysize & 0xFF; c++; + + +#ifdef USE_DTLS + if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 1)) { + /* It is not optimal to have run through the above digest updates + again on a retransmit just to free the hash here but the + saved message is ONLY the signature portion done in nowDoSke + so the few hashSigAlg bytes and keysize done above during the + hash are important to rewrite */ + psFree(hsMsgHash, ssl->hsPool); + memcpy(c, ssl->ckeMsg, ssl->ckeSize); + c += ssl->ckeSize; + } else { /* closed below */ +#endif /* USE_DTLS */ + pkaAfter = getPkaAfter(ssl); +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + pkaAfter->type = PKA_AFTER_RSA_SIG_GEN_ELEMENT; + } else { + pkaAfter->type = PKA_AFTER_RSA_SIG_GEN; + } +#else /* !USE_TLS_1_2 */ + pkaAfter->type = PKA_AFTER_RSA_SIG_GEN; +#endif /* USE_TLS_1_2 */ + + pkaAfter->inbuf = hsMsgHash; + pkaAfter->outbuf = c; + pkaAfter->data = pkiData; + pkaAfter->inlen = hashSize; + c += ssl->keys->privKey.keysize; +#ifdef USE_DTLS + } +#endif /* USE_DTLS */ + } +#endif /* USE_RSA_CIPHER_SUITE */ + +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_DHE_WITH_DSA) { +#ifndef USE_ONLY_PSK_CIPHER_SUITE + /* Saved aside for pkaAfter_t */ + if ((hsMsgHash = psMalloc(ssl->hsPool, SHA384_HASH_SIZE)) == NULL) { + return PS_MEM_FAIL; + } +#endif +#ifdef USE_TLS_1_2 + if ((ssl->flags & SSL_FLAGS_TLS_1_2) && + (ssl->keys->cert->sigAlgorithm == OID_SHA256_ECDSA_SIG)) { + hashSize = SHA256_HASH_SIZE; + psSha256Init(&digestCtx.sha256); + psSha256Update(&digestCtx.sha256, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha256Update(&digestCtx.sha256, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha256Update(&digestCtx.sha256, sigStart, (int32)(c - sigStart)); + psSha256Final(&digestCtx.sha256, hsMsgHash); + *c++ = 0x4; /* SHA256 */ + *c++ = 0x3; /* ECDSA */ +#ifdef USE_SHA384 + } else if ((ssl->flags & SSL_FLAGS_TLS_1_2) && + (ssl->keys->cert->sigAlgorithm == OID_SHA384_ECDSA_SIG)) { + hashSize = SHA384_HASH_SIZE; + psSha384Init(&digestCtx.sha384); + psSha384Update(&digestCtx.sha384, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha384Update(&digestCtx.sha384, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha384Update(&digestCtx.sha384, sigStart, (int32)(c - sigStart)); + psSha384Final(&digestCtx.sha384, hsMsgHash); + *c++ = 0x5; /* SHA384 */ + *c++ = 0x3; /* ECDSA */ +#endif +#ifdef USE_SHA1 + } else if (ssl->minVer < TLS_1_2_MIN_VER || +#ifdef USE_DTLS + /* DTLS 1.0 is same at TLS 1.1 */ + ssl->minVer == DTLS_MIN_VER || +#endif + ((ssl->flags & SSL_FLAGS_TLS_1_2) && + (ssl->keys->cert->sigAlgorithm == OID_SHA1_ECDSA_SIG))) { + hashSize = SHA1_HASH_SIZE; + psSha1Init(&digestCtx.sha1); + psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, sigStart, (int32)(c - sigStart)); + psSha1Final(&digestCtx.sha1, hsMsgHash); + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + *c++ = 0x2; /* SHA1 */ + *c++ = 0x3; /* ECDSA */ + } +#endif + } else { + psFree(hsMsgHash, ssl->hsPool); + return PS_UNSUPPORTED_FAIL; + } +#else + hashSize = SHA1_HASH_SIZE; + psSha1Init(&digestCtx.sha1); + psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, sigStart, (int32)(c - sigStart)); + psSha1Final(&digestCtx.sha1, hsMsgHash); +#endif + +#ifdef USE_DTLS + if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 1)) { + /* It is not optimal to have run through the above digest updates + again on a retransmit just to free the hash here but the + saved message is ONLY the signature portion done in nowDoSke + so the few hashSigAlg bytes and keysize done above during the + hash are important to rewrite */ + psFree(hsMsgHash, ssl->hsPool); + memcpy(c, ssl->ckeMsg, ssl->ckeSize); + c += ssl->ckeSize; + } else { /* closed below */ +#endif /* USE_DTLS */ + + if ((pkaAfter = getPkaAfter(ssl)) == NULL) { + psTraceInfo("getPkaAfter error\n"); + return PS_PLATFORM_FAIL; + } + pkaAfter->inbuf = hsMsgHash; + pkaAfter->outbuf = c; + pkaAfter->data = pkiData; + pkaAfter->inlen = hashSize; + pkaAfter->type = PKA_AFTER_ECDSA_SIG_GEN; + rc = ssl->keys->privKey.keysize + 8; + /* NEGATIVE ECDSA - Adding spot for ONE 0x0 byte in ECDSA so we'll + be right 50% of the time... 521 curve doesn't need */ + if (ssl->keys->privKey.keysize != 132) { + rc += 1; + } + /* Above we added in the 8 bytes of overhead (2 sigLen, 1 SEQ, + 1 len (possibly 2!), 1 INT, 1 rLen, 1 INT, 1 sLen) and now + subtract the first 3 bytes to see if the 1 len needs to be 2 */ + if (rc - 3 >= 128) { + rc++; + } + pkaAfter->user = rc; /* outlen for later */ + c += rc; +#ifdef USE_DTLS + } +#endif /* USE_DTLS */ + } +#endif /* USE_ECC_CIPHER_SUITE */ + + if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_SERVER_KEY_EXCHANGE, messageSize, padLen, encryptStart, out, + &c)) < 0) { + return rc; + } + out->end = c; + return MATRIXSSL_SUCCESS; +} +#endif /* USE_DHE_CIPHER_SUITE */ + +/******************************************************************************/ +/* + Server initiated rehandshake public API call. +*/ +int32 matrixSslEncodeHelloRequest(ssl_t *ssl, sslBuf_t *out, + uint32 *requiredLen) +{ + unsigned char *c, *end, *encryptStart; + uint8_t padLen; + uint16_t messageSize; + int32_t rc; + + *requiredLen = 0; + psTraceHs("<<< Server creating HELLO_REQUEST message\n"); + if (ssl->flags & SSL_FLAGS_ERROR || ssl->flags & SSL_FLAGS_CLOSED) { + psTraceInfo("SSL flag error in matrixSslEncodeHelloRequest\n"); + return MATRIXSSL_ERROR; + } + if (!(ssl->flags & SSL_FLAGS_SERVER) || (ssl->hsState != SSL_HS_DONE)) { + psTraceInfo("SSL state error in matrixSslEncodeHelloRequest\n"); + return MATRIXSSL_ERROR; + } + + c = out->end; + end = out->buf + out->size; + messageSize = ssl->recordHeadLen + ssl->hshakeHeadLen; + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_HELLO_REQUEST, &messageSize, &padLen, + &encryptStart, end, &c)) < 0) { + *requiredLen = messageSize; + return rc; + } + + if ((rc = encryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, 0, messageSize, + padLen, encryptStart, out, &c)) < 0) { + return rc; + } + out->end = c; + + return MATRIXSSL_SUCCESS; +} +#else /* USE_SERVER_SIDE_SSL */ +int32 matrixSslEncodeHelloRequest(ssl_t *ssl, sslBuf_t *out, + uint32 *requiredLen) +{ + psTraceInfo("Library not built with USE_SERVER_SIDE_SSL\n"); + return PS_UNSUPPORTED_FAIL; +} +#endif /* USE_SERVER_SIDE_SSL */ + + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) +/* + A fragmented write of the CERTIFICATE handhshake message. This is the + only handshake message that supports fragmentation because it is the only + message where the 512byte plaintext max of the max_fragment extension can + be exceeded. +*/ +static int32 writeMultiRecordCertificate(ssl_t *ssl, sslBuf_t *out, + int32 notEmpty, int32 totalClen, int32 lsize) +{ + psX509Cert_t *cert, *future; + unsigned char *c, *end, *encryptStart; + uint8_t padLen; + uint16_t messageSize, certLen; + int32_t rc; + int32 midWrite, midSizeWrite, countDown, firstOne = 1; + + c = out->end; + end = out->buf + out->size; + + midSizeWrite = midWrite = certLen = 0; + cert = NULL; + + while (totalClen > 0) { + if (firstOne) { + firstOne = 0; + countDown = ssl->maxPtFrag; + messageSize = totalClen + lsize + ssl->recordHeadLen + ssl->hshakeHeadLen; + if ((rc = writeRecordHeader(ssl, + SSL_RECORD_TYPE_HANDSHAKE_FIRST_FRAG, SSL_HS_CERTIFICATE, + &messageSize, &padLen, &encryptStart, end, &c)) < 0) { + return rc; + } + /* Write out the certs */ + *c = (unsigned char)(((totalClen + (lsize - 3)) & 0xFF0000) >> 16); + c++; + *c = ((totalClen + (lsize - 3)) & 0xFF00) >> 8; c++; + *c = ((totalClen + (lsize - 3)) & 0xFF); c++; + countDown -= ssl->hshakeHeadLen + 3; + + if (notEmpty) { + cert = ssl->keys->cert; + while (cert) { + psAssert(cert->unparsedBin != NULL); + certLen = cert->binLen; + midWrite = 0; + if (certLen > 0) { + if (countDown < 3) { + /* Fragment falls right on cert len write. Has + to be at least one byte or countDown would have + been 0 and got us out of here already*/ + *c = (unsigned char)((certLen & 0xFF0000) >> 16); + c++; countDown--; + midSizeWrite = 2; + if (countDown != 0) { + *c = (certLen & 0xFF00) >> 8; c++; countDown--; + midSizeWrite = 1; + if (countDown != 0) { + *c = (certLen & 0xFF); c++; countDown--; + midSizeWrite = 0; + } + } + break; + } else { + *c = (unsigned char)((certLen & 0xFF0000) >> 16); + c++; + *c = (certLen & 0xFF00) >> 8; c++; + *c = (certLen & 0xFF); c++; + countDown -= 3; + } + midWrite = min(certLen, countDown); + memcpy(c, cert->unparsedBin, midWrite); + certLen -= midWrite; + c += midWrite; + totalClen -= midWrite; + countDown -= midWrite; + if (countDown == 0) { + break; + } + } + cert = cert->next; + } + } + if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_CERTIFICATE, messageSize, padLen, encryptStart, out, + &c)) < 0) { + return rc; + } + out->end = c; + } else { +/* + Not-first fragments +*/ + if (midSizeWrite > 0) { + messageSize = midSizeWrite; + } else { + messageSize = 0; + } + if ((certLen + messageSize) > ssl->maxPtFrag) { + messageSize += ssl->maxPtFrag; + } else { + messageSize += certLen; + if (cert->next != NULL) { + future = cert->next; + while (future != NULL) { + if (messageSize + future->binLen + 3 > + (uint32)ssl->maxPtFrag) { + messageSize = ssl->maxPtFrag; + future = NULL; + } else { + messageSize += 3 + future->binLen; + future = future->next; + } + + } + } + } + + countDown = messageSize; + messageSize += ssl->recordHeadLen; + /* Second, etc... */ + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE_FRAG, + SSL_HS_CERTIFICATE, &messageSize, &padLen, &encryptStart, + end, &c)) < 0) { + return rc; + } + + if (midSizeWrite > 0) { + if (midSizeWrite == 2) { + *c = (certLen & 0xFF00) >> 8; c++; + *c = (certLen & 0xFF); c++; + countDown -= 2; + } else { + *c = (certLen & 0xFF); c++; + countDown -= 1; + } + midSizeWrite = 0; + } + + if (countDown < certLen) { + memcpy(c, cert->unparsedBin + midWrite, countDown); + certLen -= countDown; + c += countDown; + totalClen -= countDown; + midWrite += countDown; + countDown = 0; + } else { + memcpy(c, cert->unparsedBin + midWrite, certLen); + c += certLen; + totalClen -= certLen; + countDown -= certLen; + certLen -= certLen; + } + + while (countDown > 0) { + cert = cert->next; + certLen = cert->binLen; + midWrite = 0; + if (countDown < 3) { + /* Fragment falls right on cert len write */ + *c = (unsigned char)((certLen & 0xFF0000) >> 16); + c++; countDown--; + midSizeWrite = 2; + if (countDown != 0) { + *c = (certLen & 0xFF00) >> 8; c++; countDown--; + midSizeWrite = 1; + if (countDown != 0) { + *c = (certLen & 0xFF); c++; countDown--; + midSizeWrite = 0; + } + } + break; + } else { + *c = (unsigned char)((certLen & 0xFF0000) >> 16); + c++; + *c = (certLen & 0xFF00) >> 8; c++; + *c = (certLen & 0xFF); c++; + countDown -= 3; + } + midWrite = min(certLen, countDown); + memcpy(c, cert->unparsedBin, midWrite); + certLen -= midWrite; + c += midWrite; + totalClen -= midWrite; + countDown -= midWrite; + if (countDown == 0) { + break; + } + + } + if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_CERTIFICATE, messageSize, padLen, encryptStart, out, + &c)) < 0) { + return rc; + } + out->end = c; + } + } + + out->end = c; + return MATRIXSSL_SUCCESS; +} +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ + + +#if defined(USE_OCSP) && defined(USE_SERVER_SIDE_SSL) +static int32 writeCertificateStatus(ssl_t *ssl, sslBuf_t *out) +{ + unsigned char *c, *end, *encryptStart; + uint8_t padLen; + int32 rc; + uint16_t messageSize, ocspLen; + + + /* Easier to exclude this message internally rather than futher muddy the + numerous #ifdef and ssl_t tests in the caller */ + if (ssl->extFlags.status_request == 0) { + return MATRIXSSL_SUCCESS; + } + + psTraceHs("<<< Server creating CERTIFICATE_STATUS message\n"); + + c = out->end; + end = out->buf + out->size; + + ocspLen = ssl->keys->OCSPResponseBufLen; + messageSize = ssl->recordHeadLen + ssl->hshakeHeadLen + 4 + ocspLen; + + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_CERTIFICATE_STATUS, &messageSize, &padLen, &encryptStart, + end, &c)) < 0) { + return rc; + } + /* struct { + CertificateStatusType status_type; + select (status_type) { + case ocsp: OCSPResponse; + } response; + } CertificateStatus; */ + *c = 0x1; c++; + *c = (unsigned char)((ocspLen & 0xFF0000) >> 16); c++; + *c = (ocspLen & 0xFF00) >> 8; c++; + *c = (ocspLen & 0xFF); c++; + memcpy(c, ssl->keys->OCSPResponseBuf, ocspLen); + c += ocspLen; + + if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_CERTIFICATE_STATUS, messageSize, padLen, encryptStart, out, + &c)) < 0) { + return rc; + } + out->end = c; + return MATRIXSSL_SUCCESS; + +} +#endif /* OCSP && SERVER_SIDE_SSL */ + +/******************************************************************************/ +/* + Write a Certificate message. + The encoding of the message is as follows: + 3 byte length of certificate data (network byte order) + If there is no certificate, + 3 bytes of 0 + If there is one certificate, + 3 byte length of certificate + 3 + 3 byte length of certificate + certificate data + For more than one certificate: + 3 byte length of all certificate data + 3 byte length of first certificate + first certificate data + 3 byte length of second certificate + second certificate data + Certificate data is the base64 section of an X.509 certificate file + in PEM format decoded to binary. No additional interpretation is required. +*/ +static int32 writeCertificate(ssl_t *ssl, sslBuf_t *out, int32 notEmpty) +{ +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) + psX509Cert_t *cert; + uint32 certLen; +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ + + unsigned char *c, *end, *encryptStart; + uint8_t padLen; + int32 totalCertLen, lsize, i, rc; + uint16_t messageSize; + + psTraceStrHs("<<< %s creating CERTIFICATE message\n", + (ssl->flags & SSL_FLAGS_SERVER) ? "Server" : "Client"); + +#ifdef USE_PSK_CIPHER_SUITE +/* + Easier to exclude this message internally rather than futher muddy the + numerous #ifdef and ssl->flags tests for DH, CLIENT_AUTH, and PSK states. + A PSK or DHE_PSK cipher will never send this message +*/ + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + return MATRIXSSL_SUCCESS; + } +#endif /* USE_PSK_CIPHER_SUITE */ + + c = out->end; + end = out->buf + out->size; + +/* + Determine total length of certs +*/ + totalCertLen = i = 0; + if (notEmpty) { +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) + cert = ssl->keys->cert; + for (; cert != NULL; i++) { + psAssert(cert->unparsedBin != NULL); + totalCertLen += cert->binLen; + cert = cert->next; + } +#else + return PS_DISABLED_FEATURE_FAIL; +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ + } + +/* + Account for the 3 bytes of certChain len for each cert and get messageSize +*/ + lsize = 3 + (i * 3); + + /* TODO DTLS: Make sure this maxPtFrag is consistent with the fragment + extension and is not interfering with DTLS notions of fragmentation */ + if ((totalCertLen + lsize + ssl->hshakeHeadLen) > ssl->maxPtFrag) { +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) + return writeMultiRecordCertificate(ssl, out, notEmpty, + totalCertLen, lsize); +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ + } else { + messageSize = + ssl->recordHeadLen + + ssl->hshakeHeadLen + + lsize + totalCertLen; + + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_CERTIFICATE, &messageSize, &padLen, &encryptStart, + end, &c)) < 0) { +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { +/* + Is this the fragment case? +*/ + if (rc == DTLS_MUST_FRAG) { + rc = dtlsWriteCertificate(ssl, totalCertLen, lsize, c); + if (rc < 0) { + return rc; + } + c += rc; + out->end = c; + return MATRIXSSL_SUCCESS; + } + } +#endif /* USE_DTLS */ + return rc; + } + +/* + Write out the certs +*/ + *c = (unsigned char)(((totalCertLen + (lsize - 3)) & 0xFF0000) >> 16); + c++; + *c = ((totalCertLen + (lsize - 3)) & 0xFF00) >> 8; c++; + *c = ((totalCertLen + (lsize - 3)) & 0xFF); c++; + +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) + if (notEmpty) { + cert = ssl->keys->cert; + while (cert) { + psAssert(cert->unparsedBin != NULL); + certLen = cert->binLen; + if (certLen > 0) { + *c = (unsigned char)((certLen & 0xFF0000) >> 16); c++; + *c = (certLen & 0xFF00) >> 8; c++; + *c = (certLen & 0xFF); c++; + memcpy(c, cert->unparsedBin, certLen); + c += certLen; + } + cert = cert->next; + } + } +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ + + if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_CERTIFICATE, messageSize, padLen, encryptStart, out, + &c)) < 0) { + return rc; + } + out->end = c; + } + return MATRIXSSL_SUCCESS; +} +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ + +/******************************************************************************/ +/* + Write the ChangeCipherSpec message. It has its own message type + and contains just one byte of value one. It is not a handshake + message, so it isn't included in the handshake hash. +*/ +static int32_t writeChangeCipherSpec(ssl_t *ssl, sslBuf_t *out) +{ + unsigned char *c, *end, *encryptStart; + uint8_t padLen; + uint16_t messageSize; + int32_t rc; + + psTraceStrHs("<<< %s creating CHANGE_CIPHER_SPEC message\n", + (ssl->flags & SSL_FLAGS_SERVER) ? "Server" : "Client"); + + c = out->end; + end = out->buf + out->size; + messageSize = ssl->recordHeadLen + 1; + + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_CHANGE_CIPHER_SPEC, 0, + &messageSize, &padLen, &encryptStart, end, &c)) < 0) { + return rc; + } + *c = 1; c++; + + if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_CHANGE_CIPHER_SPEC, + 0, messageSize, padLen, encryptStart, out, &c)) < 0) { + return rc; + } + out->end = c; + + return MATRIXSSL_SUCCESS; +} + +static int32 postponeSnapshotHSHash(ssl_t *ssl, unsigned char *c, int32 sender) +{ + ssl->delayHsHash = c; +#ifdef USE_TLS + if (ssl->flags & SSL_FLAGS_TLS) { + return TLS_HS_FINISHED_SIZE; + } else { +#endif /* USE_TLS */ + return MD5_HASH_SIZE + SHA1_HASH_SIZE; +#ifdef USE_TLS + } +#endif /* USE_TLS */ + +} + +/******************************************************************************/ +/* + Write the Finished message + The message contains the 36 bytes, the 16 byte MD5 and 20 byte SHA1 hash + of all the handshake messages so far (excluding this one!) +*/ +static int32 writeFinished(ssl_t *ssl, sslBuf_t *out) +{ + unsigned char *c, *end, *encryptStart; + uint8_t padLen; + uint16_t messageSize, verifyLen; + int32_t rc; + + psTraceStrHs("<<< %s creating FINISHED message\n", + (ssl->flags & SSL_FLAGS_SERVER) ? "Server" : "Client"); + + c = out->end; + end = out->buf + out->size; + + verifyLen = MD5_HASH_SIZE + SHA1_HASH_SIZE; +#ifdef USE_TLS + if (ssl->flags & SSL_FLAGS_TLS) { + verifyLen = TLS_HS_FINISHED_SIZE; + } +#endif /* USE_TLS */ + messageSize = ssl->recordHeadLen + ssl->hshakeHeadLen + verifyLen; + + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE, SSL_HS_FINISHED, + &messageSize, &padLen, &encryptStart, end, &c)) < 0) { + return rc; + } +/* + Output the hash of messages we've been collecting so far into the buffer +*/ + c += postponeSnapshotHSHash(ssl, c, ssl->flags & SSL_FLAGS_SERVER); + + if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_FINISHED, messageSize, padLen, encryptStart, out, &c)) < 0) { + return rc; + } + out->end = c; + + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { +/* + Can't free the sec.cert buffer or close the handshake pool if + using DTLS as we may be coming back around through this flight on + a retransmit. These frees are only taken care of once DTLS is + positive the handshake has completed. +*/ + return MATRIXSSL_SUCCESS; + } +#endif /* USE_DTLS */ + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH) + /* In client cases, there will be an outstanding PKA operation that + could require the key from the cert so we can't free it yet */ + if (ssl->pkaAfter[0].type == 0) { + if (ssl->sec.cert) { + psX509FreeCert(ssl->sec.cert); + ssl->sec.cert = NULL; + } + } +#endif /* USE_CLIENT_SIDE_SSL || USE_CLIENT_AUTH */ +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + return MATRIXSSL_SUCCESS; +} + +/******************************************************************************/ +/* + Write an Alert message + The message contains two bytes: AlertLevel and AlertDescription +*/ +static int32 writeAlert(ssl_t *ssl, unsigned char level, + unsigned char description, sslBuf_t *out, + uint32 *requiredLen) +{ + unsigned char *c, *end, *encryptStart; + uint8_t padLen; + uint16_t messageSize; + int32_t rc; + + c = out->end; + end = out->buf + out->size; + messageSize = 2 + ssl->recordHeadLen; + + /* Force the alert to WARNING if the spec says the alert MUST be that */ + if (description == (unsigned char)SSL_ALERT_NO_RENEGOTIATION) { + level = (unsigned char)SSL_ALERT_LEVEL_WARNING; + ssl->err = SSL_ALERT_NONE; + } + + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_ALERT, 0, &messageSize, + &padLen, &encryptStart, end, &c)) < 0) { + *requiredLen = messageSize; + return rc; + } + *c = level; c++; + *c = description; c++; + + if ((rc = encryptRecord(ssl, SSL_RECORD_TYPE_ALERT, 0, messageSize, + padLen, encryptStart, out, &c)) < 0) { + *requiredLen = messageSize; + return rc; + } + out->end = c; +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, ALERT_SENT_STAT, (int32)(description)); +#endif + return MATRIXSSL_SUCCESS; +} + + +#ifdef USE_CLIENT_SIDE_SSL +#ifdef USE_TRUSTED_CA_INDICATION +static int32_t trustedCAindicationExtLen(psX509Cert_t *certs) +{ + psX509Cert_t *next; + int32_t len; + + len = 0; + /* Using the cert_sha1_hash identifier_type */ + next = certs; + while (next) { + len += 21; /* 1 id_type, 20 hash */ + next = next->next; + } + return len; +} + +static void writeTrustedCAindication(psX509Cert_t *certs, unsigned char **pp) +{ + psX509Cert_t *next; + int32_t len; + unsigned char *p = *pp; + + len = trustedCAindicationExtLen(certs); + *p = (len & 0xFF00) >> 8; p++; + *p = len & 0xFF; p++; + + next = certs; + while (next) { + *p = 0x3; p++; /* cert_sha1_hash */ + memcpy(p, next->sha1CertHash, 20); + p += 20; + next = next->next; + } + psAssert((p - *pp) == (len + 2)); + *pp = p; +} +#endif /* USE_TRUSTED_CA_INDICATION */ + +/******************************************************************************/ +/* + Write out the ClientHello message to a buffer +*/ +int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out, + const uint16_t cipherSpecs[], uint8_t cipherSpecLen, + uint32 *requiredLen, tlsExtension_t *userExt, sslSessOpts_t *options) +{ + unsigned char *c, *end, *encryptStart; + uint8_t padLen; + int32 rc, t; + uint16_t messageSize, cipherLen, cookieLen, addRenegotiationScsv; + tlsExtension_t *ext; + uint32 extLen; + const sslCipherSpec_t *cipherDetails; + short i, useTicket; +#ifdef USE_TLS_1_2 + uint16_t sigHashLen, sigHashFlags; + unsigned char sigHash[18]; /* 2b len + 2b * 8 sig hash combos */ +#endif +#ifdef USE_ECC_CIPHER_SUITE + unsigned char eccCurveList[32]; + uint8_t curveListLen; +#endif /* USE_ECC_CIPHER_SUITE */ +#ifdef USE_DTLS + unsigned char *extStart = NULL; + int cipherCount; +#endif + + psTraceHs("<<< Client creating CLIENT_HELLO message\n"); + *requiredLen = 0; + if (out == NULL || out->buf == NULL || ssl == NULL || options == NULL) { + return PS_ARG_FAIL; + } + if (cipherSpecLen > 0 && (cipherSpecs == NULL || cipherSpecs[0] == 0)) { + return PS_ARG_FAIL; + } + if (ssl->flags & SSL_FLAGS_ERROR || ssl->flags & SSL_FLAGS_CLOSED) { + psTraceInfo("SSL flag error in matrixSslEncodeClientHello\n"); + return MATRIXSSL_ERROR; + } + if (ssl->flags & SSL_FLAGS_SERVER || (ssl->hsState != SSL_HS_SERVER_HELLO && + ssl->hsState != SSL_HS_DONE && + ssl->hsState != SSL_HS_HELLO_REQUEST )) { + psTraceInfo("SSL state error in matrixSslEncodeClientHello\n"); + return MATRIXSSL_ERROR; + } + + sslInitHSHash(ssl); + + + cookieLen = 0; +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { +/* + TODO: DTLS make sure a block cipher suite is being used +*/ + if (ssl->haveCookie) { + cookieLen = ssl->cookieLen + 1; /* account for length byte */ + } else { + cookieLen = 1; /* Always send the length (0) even if no cookie */ + } + /* save for next time called for VERIFY_REQUEST response */ + ssl->cipherSpecLen = min(8, cipherSpecLen); /* 8 is arbitrary limit */ + for (cipherCount = 0; cipherCount < ssl->cipherSpecLen; cipherCount++) { + ssl->cipherSpec[cipherCount] = cipherSpecs[cipherCount]; + } + } +#endif + /* If no resumption, clear the RESUMED flag in case the caller is + attempting to bypass matrixSslEncodeRehandshake. */ + if (ssl->sessionIdLen <= 0) { + ssl->flags &= ~SSL_FLAGS_RESUMED; + } + + if (cipherSpecLen == 0 || cipherSpecs == NULL || cipherSpecs[0] == 0) { + if ((cipherLen = sslGetCipherSpecListLen(ssl)) == 2) { + psTraceInfo("No cipher suites enabled (or no key material)\n"); + return MATRIXSSL_ERROR; + } + } else { + /* If ciphers are specified it is two bytes length and two bytes data */ + cipherLen = 2; + for (i = 0; i < cipherSpecLen; i++) { + if ((cipherDetails = sslGetCipherSpec(ssl, cipherSpecs[i])) + == NULL) { + psTraceIntInfo("Cipher suite not supported: %d\n", + cipherSpecs[i]); + return PS_UNSUPPORTED_FAIL; + } + cipherLen += 2; + } + } + + addRenegotiationScsv = 0; +#ifdef ENABLE_SECURE_REHANDSHAKES + /* Initial CLIENT_HELLO will use the SCSV mechanism for greatest compat */ + if (ssl->myVerifyDataLen == 0) { + cipherLen += 2; /* signalling cipher id 0x00FF */ + addRenegotiationScsv = 1; + } +#endif + if (options->fallbackScsv) { + if (ssl->minVer == TLS_HIGHEST_MINOR) { + /** If a client sets ClientHello.client_version to its highest + supported protocol version, it MUST NOT include TLS_FALLBACK_SCSV. + @see https://tools.ietf.org/html/rfc7507#section-4 */ + psTraceInfo("Cannot set fallbackScsv if using maximum supported TLS version.\n"); + return MATRIXSSL_ERROR; + } + if (ssl->sessionIdLen > 0) { + /** when a client intends to resume a session and sets ClientHello.client_version + to the protocol version negotiated for that session, it MUST NOT include + TLS_FALLBACK_SCSV. + @see https://tools.ietf.org/html/rfc7507#section-4 */ + psTraceInfo("Cannot set fallbackScsv if attempting to resume a connection.\n"); + return MATRIXSSL_ERROR; + } + cipherLen += 2; /* signalling cipher id 0x5600 */ + ssl->extFlags.req_fallback_scsv = 1; + } else { + /** If a client sends a ClientHello.client_version containing a lower + value than the latest (highest-valued) version supported by the + client, it SHOULD include the TLS_FALLBACK_SCSV. + @see https://tools.ietf.org/html/rfc7507#section-4 + We warn because this is a SHOULD not a MUST. + @security The only reason (outside testing) that we should propose a TLS version + lower than what we support is if we had already tried to negotiate the highest + version but the server did not support it. In that case, the fallbackScsv + option should have been specified to mitigate version rollback attacks. + */ + if (ssl->minVer < TLS_HIGHEST_MINOR) { + psTraceInfo("Warning, if this is a fallback connection, set fallbackScsv?\n"); + } + } + + /* Calculate the size of the message up front, and write header */ + messageSize = ssl->recordHeadLen + ssl->hshakeHeadLen + + 5 + SSL_HS_RANDOM_SIZE + ssl->sessionIdLen + cipherLen + cookieLen; + +#ifdef USE_ZLIB_COMPRESSION + messageSize += 1; +#endif + + /* Extension lengths */ + extLen = 0; + + /* Max Fragment extension request */ + ssl->maxPtFrag = SSL_MAX_PLAINTEXT_LEN; + if (ssl->minVer > 0 && (options->maxFragLen > 0) && + (options->maxFragLen < SSL_MAX_PLAINTEXT_LEN)) { + if (options->maxFragLen == 0x200 || + options->maxFragLen == 0x400 || + options->maxFragLen == 0x800 || + options->maxFragLen == 0x1000) { + extLen = 2 + 5; /* 2 for total ext len + 5 for ourselves */ + ssl->maxPtFrag = options->maxFragLen; + /* Also indicate that we're requesting a different plaintext size */ + ssl->maxPtFrag |= 0x10000; + } else { + psTraceInfo("Unsupported maxFragLen value to session options\n"); + return PS_ARG_FAIL; + } + } + + if (options->truncHmac) { + if (extLen == 0) { + extLen = 2; /* First extension found so total len */ + } + extLen += 4; /* empty "extension_data" */ + } + + if (options->extendedMasterSecret >= 0) { + if (extLen == 0) { + extLen = 2; /* First extension found so total len */ + } + extLen += 4; /* empty extension */ + } + +#ifdef USE_TRUSTED_CA_INDICATION + if (options->trustedCAindication) { + if (extLen == 0) { + extLen = 2; /* First extension found so total len */ + } + /* Magic 4 is extension id and length as usual */ + extLen += trustedCAindicationExtLen(ssl->keys->CAcerts) + 4; + } +#endif + + +#ifdef ENABLE_SECURE_REHANDSHAKES + /* Subsequent CLIENT_HELLOs must use a populated RenegotiationInfo extension */ + if (ssl->myVerifyDataLen != 0) { + if (extLen == 0) { + extLen = 2; /* First extension found so total len */ + } + extLen += ssl->myVerifyDataLen + 5; /* 5 type/len/len */ + } +#endif /* ENABLE_SECURE_REHANDSHAKES */ + +#ifdef USE_ECC_CIPHER_SUITE + curveListLen = 0; + if (eccSuitesSupported(ssl, cipherSpecs, cipherSpecLen)) { + /* Getting the curve list from crypto directly */ + curveListLen = sizeof(eccCurveList); + if (options->ecFlags) { + userSuppliedEccList(eccCurveList, &curveListLen, options->ecFlags); + } else { + /* Use all that are enabled */ + psGetEccCurveIdList(eccCurveList, &curveListLen); + } + if (curveListLen > 0) { + if (extLen == 0) { + extLen = 2; /* First extension found so total len */ + } + /* EXT_ELLIPTIC_CURVE */ + extLen += curveListLen + 6; /* 2 id, 2 for ext len, 2 len */ + /* EXT_ELLIPTIC_POINTS - hardcoded to 'uncompressed' support */ + extLen += 6; /* 00 0B 00 02 01 00 */ + } + } +#endif /* USE_ECC_CIPHER_SUITE */ + + useTicket = 0; +#ifdef USE_STATELESS_SESSION_TICKETS + if (options && options->ticketResumption == 1) { + useTicket = 1; + } + if (useTicket && ssl->sid) { + if (extLen == 0) { + extLen = 2; /* First extension found so total len */ + } + extLen += 4; /* 2 type, 2 length */ + if (ssl->sid->sessionTicketLen > 0 && + ssl->sid->sessionTicketState == SESS_TICKET_STATE_USING_TICKET) { + extLen += ssl->sid->sessionTicketLen; + } + } +#endif + +#ifdef USE_OCSP + if (options && options->OCSPstapling == 1) { + if (extLen == 0) { + extLen = 2; /* First extension found so total len */ + } + /* Currently only supporting an empty status_request extension */ + extLen += 9; + } +#endif + +#ifdef USE_TLS_1_2 + /* + TLS 1.2 clients must add the SignatureAndHashAlgorithm extension, + (although not sending them implies SHA-1, and it's unused for + non-certificate based ciphers like PSK). + Sending all the algorithms that are enabled at compile time. + Always sends SHA256 since it must be enabled for TLS 1.2 + + enum { + none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), + sha512(6), (255) + } HashAlgorithm; + enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } SigAlgorithm; + */ + +#define ADD_SIG_HASH(A,B) \ +{\ + sigHashFlags |= HASH_SIG_MASK(A,B);\ + sigHash[sigHashLen] = A; \ + sigHash[sigHashLen + 1] = B; \ + sigHashLen += 2; \ +} + sigHashFlags = 0; + sigHashLen = 2; /* Length of buffer, Start with 2b len */ + +#ifdef USE_ECC + /* Always support SHA256 */ + ADD_SIG_HASH(HASH_SIG_SHA256, HASH_SIG_ECDSA); + +#ifdef USE_SHA512 + ADD_SIG_HASH(HASH_SIG_SHA512, HASH_SIG_ECDSA); +#endif +#ifdef USE_SHA384 + ADD_SIG_HASH(HASH_SIG_SHA384, HASH_SIG_ECDSA); +#endif +#ifdef USE_SHA1 + ADD_SIG_HASH(HASH_SIG_SHA1, HASH_SIG_ECDSA); +#endif +#endif /* USE_ECC */ + +#ifdef USE_RSA + /* Always support SHA256 */ + ADD_SIG_HASH(HASH_SIG_SHA256, HASH_SIG_RSA); + +#ifdef USE_SHA512 + ADD_SIG_HASH(HASH_SIG_SHA512, HASH_SIG_RSA); +#endif +#ifdef USE_SHA384 + ADD_SIG_HASH(HASH_SIG_SHA384, HASH_SIG_RSA); +#endif +#ifdef USE_SHA1 + ADD_SIG_HASH(HASH_SIG_SHA1, HASH_SIG_RSA); +#endif +#endif /* USE_RSA */ + +#ifdef USE_ONLY_PSK_CIPHER_SUITE + /* Have to pass something */ + ADD_SIG_HASH(HASH_SIG_SHA1, HASH_SIG_RSA); +#endif + +#undef ADD_SIG_HASH + + /* First two bytes is the byte count of remaining data */ + /* Note that in PSK mode, there will be no supported sig alg hashes */ + sigHash[0] = 0x0; + sigHash[1] = sigHashLen - 2; /* 2 b len*/ + + if (extLen == 0) { + extLen = 2; /* First extension found so total len */ + } + extLen += 2 + 2 + sigHashLen; /* 2 ext type, 2 ext length */ + + /* On the client side, the value is set to the algorithms offered */ + ssl->hashSigAlg = sigHashFlags; + +#endif /* USE_TLS_1_2 */ + + /* Add any user-provided extensions */ + ext = userExt; + if (ext && extLen == 0) { + extLen = 2; /* Start with the initial len */ + } + while (ext) { + extLen += ext->extLen + 4; /* +4 for type and length of each */ + ext = ext->next; + } + +#ifdef USE_DTLS + if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->helloExtLen > 0)) { + /* Override all the extension calculations and just grab what was + sent the first time. Can't rebuild because there is no good line + between the extensions we add and the extensions the user adds and + no user extensions will have been passed in here on a retransmit */ + extLen = ssl->helloExtLen; + } +#endif + messageSize += extLen; + + c = out->end; + end = out->buf + out->size; + + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_CLIENT_HELLO, &messageSize, &padLen, &encryptStart, + end, &c)) < 0) { + *requiredLen = messageSize; + return rc; + } + + t = 1; +#ifdef USE_DTLS +/* + Test if this is DTLS response to the HelloVerify server message. + If so, we use the exact same one (+cookie) as before to prove to the + server we are legit. The only thing that should change in this message + is the client random so we make sure to use the original one + + struct { + ProtocolVersion client_version; + Random random; + SessionID session_id; + opaque cookie<0..32>; // New field + CipherSuite cipher_suites<2..2^16-1>; + CompressionMethod compression_methods<1..2^8-1>; + } ClientHello; +*/ + if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->haveCookie)) { + t = 0; + } + /* Also test for retransmit */ + if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 1)) { + t = 0; + } +#endif + + if (t) { + /** @security RFC says to set the first 4 bytes to time, but best common practice is + to use full 32 bytes of random. This is forward looking to TLS 1.3, and also works + better for embedded platforms and FIPS secret key material. + @see https://www.ietf.org/mail-archive/web/tls/current/msg09861.html */ +#ifdef SEND_HELLO_RANDOM_TIME + /* First 4 bytes of the serverRandom are the unix time to prevent + replay attacks, the rest are random */ + t = psGetTime(NULL, ssl->userPtr); + ssl->sec.clientRandom[0] = (unsigned char)((t & 0xFF000000) >> 24); + ssl->sec.clientRandom[1] = (unsigned char)((t & 0xFF0000) >> 16); + ssl->sec.clientRandom[2] = (unsigned char)((t & 0xFF00) >> 8); + ssl->sec.clientRandom[3] = (unsigned char)(t & 0xFF); + if ((rc = matrixCryptoGetPrngData(ssl->sec.clientRandom + 4, + SSL_HS_RANDOM_SIZE - 4, ssl->userPtr)) < PS_SUCCESS) { + return rc; + } +#else + if ((rc = matrixCryptoGetPrngData(ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE, ssl->userPtr)) < PS_SUCCESS) { + return rc; + } +#endif + } +/* + First two fields in the ClientHello message are the maximum major + and minor SSL protocol versions we support. +*/ + *c = ssl->majVer; c++; + *c = ssl->minVer; c++; + +/* + The next 32 bytes are the server's random value, to be combined with + the client random and premaster for key generation later +*/ + memcpy(c, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); + c += SSL_HS_RANDOM_SIZE; +/* + The next data is a single byte containing the session ID length, + and up to 32 bytes containing the session id. + If we are asking to resume a session, then the sessionId would have + been set at session creation time. +*/ + *c = (unsigned char)ssl->sessionIdLen; c++; + if (ssl->sessionIdLen > 0) { + memcpy(c, ssl->sessionId, ssl->sessionIdLen); + c += ssl->sessionIdLen; +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, RESUMPTIONS_STAT, 1); +#endif + } +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (ssl->haveCookie) { + *c = (unsigned char)ssl->cookieLen; c++; + memcpy(c, ssl->cookie, ssl->cookieLen); + c += ssl->cookieLen; + } else { + /* This condition is an empty cookie client hello. Still must + send a zero length specifier. */ + *c = 0; c++; + } + } +#endif +/* + Write out the length and ciphers we support + Client can request a single specific cipher in the cipherSpec param +*/ + if (cipherSpecLen == 0 || cipherSpecs == NULL || cipherSpecs[0] == 0) { + if ((rc = sslGetCipherSpecList(ssl, c, (int32)(end - c), addRenegotiationScsv)) < 0){ + return SSL_FULL; + } + c += rc; + } else { + if ((int32)(end - c) < cipherLen) { + return SSL_FULL; + } + cipherLen -= 2; /* don't include yourself */ + *c = (cipherLen & 0xFF00) >> 8; c++; + *c = cipherLen & 0xFF; c++; + /* Safe to include all cipher suites in the list because they were + checked above */ + for (i = 0; i < cipherSpecLen; i++) { + *c = (cipherSpecs[i] & 0xFF00) >> 8; c++; + *c = cipherSpecs[i] & 0xFF; c++; + } +#ifdef ENABLE_SECURE_REHANDSHAKES + if (addRenegotiationScsv == 1) { + ssl->extFlags.req_renegotiation_info = 1; + *c = ((TLS_EMPTY_RENEGOTIATION_INFO_SCSV & 0xFF00) >> 8); c++; + *c = TLS_EMPTY_RENEGOTIATION_INFO_SCSV & 0xFF; c++; + } +#endif + if (ssl->extFlags.req_fallback_scsv) { + *c = (TLS_FALLBACK_SCSV >> 8) & 0xFF; c++; + *c = TLS_FALLBACK_SCSV & 0xFF; c++; + } + } +/* + Compression. Length byte and 0 for 'none' and possibly 1 for zlib +*/ +#ifdef USE_ZLIB_COMPRESSION + *c = 2; c++; + *c = 0; c++; + *c = 1; c++; +#else + *c = 1; c++; + *c = 0; c++; +#endif + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + /* Need to save aside (or recall) extensions because the resend + path doesn't go back to the user to rebuild them. */ + extStart = c; + } +#endif +/* + Extensions +*/ + if (extLen > 0) { + extLen -= 2; /* Don't include yourself in the length */ + *c = (extLen & 0xFF00) >> 8; c++; /* Total list length */ + *c = extLen & 0xFF; c++; + + /* User-provided extensions. Do them first in case something + like a ServerNameIndication is here that will influence a + later extension such as the sigHashAlgs */ + if (userExt) { + ext = userExt; + while (ext) { + switch (ext->extType) { + case EXT_SNI: + ssl->extFlags.req_sni = 1; + break; + case EXT_ALPN: + ssl->extFlags.req_alpn = 1; +#ifdef USE_ALPN + if (ssl->extCb == NULL) { + psTraceInfo("WARNING: Providing ALPN extension without " + "registering extension callback to receive server reply\n"); + } +#endif + break; + default: + break; + } + *c = (ext->extType & 0xFF00) >> 8; c++; + *c = ext->extType & 0xFF; c++; + + *c = (ext->extLen & 0xFF00) >> 8; c++; + *c = ext->extLen & 0xFF; c++; + if (ext->extLen == 1 && ext->extData == NULL) { + memset(c, 0x0, 1); + } else { + memcpy(c, ext->extData, ext->extLen); + } + c += ext->extLen; + ext = ext->next; + } + } + + /* Max fragment extension */ + if (ssl->maxPtFrag & 0x10000) { + ssl->extFlags.req_max_fragment_len= 1; + *c = 0x00; c++; + *c = 0x01; c++; + *c = 0x00; c++; + *c = 0x01; c++; + if (options->maxFragLen == 0x200) { + *c = 0x01; c++; + } else if (options->maxFragLen == 0x400) { + *c = 0x02; c++; + } else if (options->maxFragLen == 0x800) { + *c = 0x03; c++; + } else if (options->maxFragLen == 0x1000) { + *c = 0x04; c++; + } + } +#ifdef ENABLE_SECURE_REHANDSHAKES +/* + Populated RenegotiationInfo extension +*/ + if (ssl->myVerifyDataLen > 0) { + ssl->extFlags.req_renegotiation_info = 1; + *c = (EXT_RENEGOTIATION_INFO & 0xFF00) >> 8; c++; + *c = EXT_RENEGOTIATION_INFO & 0xFF; c++; + *c = ((ssl->myVerifyDataLen + 1) & 0xFF00) >> 8; c++; + *c = (ssl->myVerifyDataLen + 1) & 0xFF; c++; + *c = ssl->myVerifyDataLen & 0xFF; c++; + memcpy(c, ssl->myVerifyData, ssl->myVerifyDataLen); + c += ssl->myVerifyDataLen; + } +#endif /* ENABLE_SECURE_REHANDSHAKES */ + +#ifdef USE_ECC_CIPHER_SUITE + if (curveListLen > 0) { + ssl->extFlags.req_elliptic_curve = 1; + *c = (EXT_ELLIPTIC_CURVE & 0xFF00) >> 8; c++; + *c = EXT_ELLIPTIC_CURVE & 0xFF; c++; + *c = ((curveListLen + 2) & 0xFF00) >> 8; c++; + *c = (curveListLen + 2) & 0xFF; c++; + *c = (curveListLen & 0xFF00) >> 8; c++; + *c = curveListLen & 0xFF; c++; + memcpy(c, eccCurveList, curveListLen); + c += curveListLen; + + ssl->extFlags.req_elliptic_points = 1; + *c = (EXT_ELLIPTIC_POINTS & 0xFF00) >> 8; c++; + *c = EXT_ELLIPTIC_POINTS & 0xFF; c++; + *c = 0x00; c++; + *c = 0x02; c++; + *c = 0x01; c++; + *c = 0x00; c++; + } +#endif /* USE_ECC_CIPHER_SUITE */ + +#ifdef USE_TLS_1_2 + /* Will always exist in some form if TLS 1.2 is enabled */ + ssl->extFlags.req_signature_algorithms = 1; + *c = (EXT_SIGNATURE_ALGORITHMS & 0xFF00) >> 8; c++; + *c = EXT_SIGNATURE_ALGORITHMS & 0xFF; c++; + *c = (sigHashLen & 0xFF00) >> 8; c++; + *c = sigHashLen & 0xFF; c++; + memcpy(c, sigHash, sigHashLen); + c += sigHashLen; +#endif + +#ifdef USE_STATELESS_SESSION_TICKETS + /* If ticket exists and is marked "USING" then it can be used */ + if (useTicket && ssl->sid) { + if (ssl->sid->sessionTicketLen == 0 || + ssl->sid->sessionTicketState != SESS_TICKET_STATE_USING_TICKET) { + + ssl->extFlags.req_session_ticket = 1; + *c = (EXT_SESSION_TICKET & 0xFF00) >> 8; c++; + *c = EXT_SESSION_TICKET & 0xFF; c++; + *c = 0x00; c++; + *c = 0x00; c++; + ssl->sid->sessionTicketState = SESS_TICKET_STATE_SENT_EMPTY; + } else { + ssl->extFlags.req_session_ticket = 1; + *c = (EXT_SESSION_TICKET & 0xFF00) >> 8; c++; + *c = EXT_SESSION_TICKET & 0xFF; c++; + *c = (ssl->sid->sessionTicketLen & 0xFF00) >> 8; c++; + *c = ssl->sid->sessionTicketLen & 0xFF; c++; + memcpy(c, ssl->sid->sessionTicket, ssl->sid->sessionTicketLen); + c += ssl->sid->sessionTicketLen; + ssl->sid->sessionTicketState = SESS_TICKET_STATE_SENT_TICKET; +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, RESUMPTIONS_STAT, 1); +#endif + } + } +#endif /* USE_STATELESS_SESSION_TICKETS */ + +#ifdef USE_OCSP + if (options->OCSPstapling) { + ssl->extFlags.req_status_request = 1; + *c = (EXT_STATUS_REQUEST & 0xFF00) >> 8; c++; + *c = EXT_STATUS_REQUEST & 0xFF; c++; + *c = 0x00; c++; + *c = 0x05; c++; + *c = 0x01; c++; + *c = 0x00; c++; + *c = 0x00; c++; + *c = 0x00; c++; + *c = 0x00; c++; + } +#endif + +#ifdef USE_TRUSTED_CA_INDICATION + if (options->trustedCAindication) { + *c = (EXT_TRUSTED_CA_KEYS & 0xFF00) >> 8; c++; + *c = EXT_TRUSTED_CA_KEYS & 0xFF; c++; + writeTrustedCAindication(ssl->keys->CAcerts, &c); + } +#endif + if (options->truncHmac) { + ssl->extFlags.req_truncated_hmac = 1; + *c = (EXT_TRUNCATED_HMAC & 0xFF00) >> 8; c++; + *c = EXT_TRUNCATED_HMAC & 0xFF; c++; + *c = 0x00; c++; + *c = 0x00; c++; + } + + if (options->extendedMasterSecret >= 0) { + if (options->extendedMasterSecret > 0) { + /* User is REQUIRING the server to support it */ + ssl->extFlags.require_extended_master_secret = 1; + } + ssl->extFlags.req_extended_master_secret = 1; + *c = (EXT_EXTENDED_MASTER_SECRET & 0xFF00) >> 8; c++; + *c = EXT_EXTENDED_MASTER_SECRET & 0xFF; c++; + *c = 0x00; c++; + *c = 0x00; c++; + } + + } + +#ifdef USE_DTLS + if ((ssl->flags & SSL_FLAGS_DTLS) && (extLen > 0)) { + if (ssl->helloExtLen == 0) { + ssl->helloExtLen = (int32)(c - extStart); + ssl->helloExt = psMalloc(ssl->hsPool, ssl->helloExtLen); + if (ssl->helloExt == NULL) { + return SSL_MEM_ERROR; + } + memcpy(ssl->helloExt, extStart, ssl->helloExtLen); + } else { + /* Forget the extensions we wrote above and use the saved ones */ + c = extStart; + memcpy(c, ssl->helloExt, ssl->helloExtLen); + c+= ssl->helloExtLen; + } + } +#endif /* USE_DTLS */ + + if ((rc = encryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, 0, messageSize, + padLen, encryptStart, out, &c)) < 0) { + return rc; + } + out->end = c; + +/* + Could be a rehandshake so clean up old context if necessary. + Always explicitly set state to beginning. +*/ + if (ssl->hsState == SSL_HS_DONE) { + sslResetContext(ssl); + } + +/* + Could be a rehandshake on a previous connection that used client auth. + Reset our local client auth state as the server is always the one + responsible for initiating it. +*/ + ssl->flags &= ~SSL_FLAGS_CLIENT_AUTH; + ssl->hsState = SSL_HS_SERVER_HELLO; + +#ifdef USE_MATRIXSSL_STATS + matrixsslUpdateStat(ssl, CH_SENT_STAT, 1); +#endif + return MATRIXSSL_SUCCESS; + +} + +/******************************************************************************/ +/* + Write a ClientKeyExchange message. +*/ +static int32 writeClientKeyExchange(ssl_t *ssl, sslBuf_t *out) +{ + unsigned char *c, *end, *encryptStart; + uint8_t padLen; + uint16_t keyLen, messageSize, explicitLen; + int32_t rc; + pkaAfter_t *pkaAfter; +#ifdef USE_PSK_CIPHER_SUITE + unsigned char *pskId, *pskKey; + uint8_t pskIdLen; +#endif /* USE_PSK_CIPHER_SUITE */ + void *pkiData = ssl->userPtr; +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#if defined(USE_ECC_CIPHER_SUITE) || defined(USE_RSA_CIPHER_SUITE) + psPool_t *pkiPool = NULL; +#endif /* USE_ECC_CIPHER_SUITE || USE_RSA_CIPHER_SUITE */ +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + + psTraceHs("<<< Client creating CLIENT_KEY_EXCHANGE message\n"); + + c = out->end; + end = out->buf + out->size; + messageSize = keyLen = 0; + + if ((pkaAfter = getPkaAfter(ssl)) == NULL) { + return PS_PLATFORM_FAIL; + } + + +#ifdef USE_PSK_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + /* Get the key id to send in the clientKeyExchange message. */ + if (matrixSslPskGetKeyId(ssl, &pskId, &pskIdLen, + ssl->sec.hint, ssl->sec.hintLen) < 0) { + psFree(ssl->sec.hint, ssl->hsPool); ssl->sec.hint = NULL; + return MATRIXSSL_ERROR; + } +#ifdef USE_DTLS + /* Need to save for retransmit? */ + if (!(ssl->flags & SSL_FLAGS_DTLS)) { + psFree(ssl->sec.hint, ssl->hsPool); ssl->sec.hint = NULL; + } +#else + psFree(ssl->sec.hint, ssl->hsPool); ssl->sec.hint = NULL; +#endif + + } +#endif /* USE_PSK_CIPHER_SUITE */ + +/* + Determine messageSize for the record header +*/ +#ifdef USE_DHE_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_DHE_KEY_EXCH) { +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS && ssl->retransmit == 1) { + keyLen = ssl->ckeSize; + } else { +#endif +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ECC_CIPHER) { + keyLen = (ssl->sec.eccKeyPriv->curve->size * 2) + 2; + } else { +#endif /* USE_ECC_CIPHER_SUITE */ +#ifdef REQUIRE_DH_PARAMS + keyLen += ssl->sec.dhKeyPriv->size; +#endif /* REQUIRE_DH_PARAMS */ +#ifdef USE_ECC_CIPHER_SUITE + } +#endif /* USE_ECC_CIPHER_SUITE */ +#ifdef USE_DTLS + } +#endif +#ifdef USE_PSK_CIPHER_SUITE +/* + Leave keyLen as the native DH or RSA key to keep the write + logic untouched below. Just directly increment the messageSize + for the PSK id information +*/ + /* DHE_PSK suites */ + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + messageSize += pskIdLen + 2; + } +#endif /* USE_PSK_CIPHER_SUITE */ + } else { +#endif /* USE_DHE_CIPHER_SUITE */ +#ifdef USE_PSK_CIPHER_SUITE + /* basic PSK suites */ + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + messageSize += pskIdLen; /* don't need the +2 */ + } else { +#endif /* USE_PSK_CIPHER_SUITE */ +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->cipher->type == CS_ECDH_ECDSA || + ssl->cipher->type == CS_ECDH_RSA) { + keyLen = (ssl->sec.cert->publicKey.key.ecc.curve->size * 2) + 2; + } else { +#endif /* USE_ECC_CIPHER_SUITE */ + /* Standard RSA auth suites */ + keyLen = ssl->sec.cert->publicKey.keysize; +#ifdef USE_ECC_CIPHER_SUITE + } +#endif /* USE_ECC_CIPHER_SUITE */ +#endif /* !USE_PSK_CIPHER_SUITE */ +#ifdef USE_PSK_CIPHER_SUITE + } +#endif /* USE_PSK_CIPHER_SUITE */ +#ifdef USE_DHE_CIPHER_SUITE + } +#endif /* USE_DHE_CIPHER_SUITE */ + + messageSize += ssl->recordHeadLen + ssl->hshakeHeadLen + keyLen; + explicitLen = 0; +#ifdef USE_TLS + /* Must always add the key size length to the message */ + if (ssl->flags & SSL_FLAGS_TLS) { + messageSize += 2; + explicitLen = 1; + } +#endif /* USE_TLS */ + +#ifdef USE_DHE_CIPHER_SUITE + /* DHE must include the explicit key size regardless of protocol */ + if (ssl->flags & SSL_FLAGS_DHE_KEY_EXCH) { + if (explicitLen == 0) { + messageSize += 2; + explicitLen = 1; + } + } +#endif /* USE_DHE_CIPHER_SUITE */ + +#ifdef USE_PSK_CIPHER_SUITE + /* Standard PSK suite in SSLv3 will not have accounted for +2 yet */ + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + if (explicitLen == 0) { + messageSize += 2; + explicitLen = 1; + } + } +#endif + +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ECC_CIPHER) { + if (explicitLen == 1) { + messageSize -= 2; /* For some reason, ECC CKE doesn't use 2 len */ + explicitLen = 0; + } + } +#endif /* USE_ECC_CIPHER_SUITE */ + + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_CLIENT_KEY_EXCHANGE, &messageSize, &padLen, + &encryptStart, end, &c)) < 0) { + return rc; + } + +/* + ClientKeyExchange message contains the encrypted premaster secret. + The base premaster is the original SSL protocol version we asked for + followed by 46 bytes of random data. + These 48 bytes are padded to the current RSA key length and encrypted + with the RSA key. +*/ + if (explicitLen == 1) { +#ifdef USE_PSK_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + *c = (pskIdLen & 0xFF00) >> 8; c++; + *c = (pskIdLen & 0xFF); c++; +/* + The cke message begins with the ID of the desired key +*/ + memcpy(c, pskId, pskIdLen); + c += pskIdLen; + } +#endif /* USE_PSK_CIPHER_SUITE */ +/* + Add the two bytes of key length +*/ + if (keyLen > 0) { + *c = (keyLen & 0xFF00) >> 8; c++; + *c = (keyLen & 0xFF); c++; + } + } + + +#ifdef USE_DTLS + if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 1)) { +/* + Retransmit case. Must use the cached encrypted msg from + the first flight to keep handshake hash same +*/ + memcpy(c, ssl->ckeMsg, ssl->ckeSize); + c += ssl->ckeSize; + } else { +#endif /* USE_DTLS */ + +#ifdef USE_DHE_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_DHE_KEY_EXCH) { + /* For DHE, the clientKeyExchange message is simply the public + key for this client. No public/private encryption here + because there is no authentication (so not necessary or + meaningful to activate public cipher). Just check ECDHE or DHE */ +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->flags & SSL_FLAGS_ECC_CIPHER) { + keyLen--; + *c = keyLen & 0xFF; c++; + if (psEccX963ExportKey(ssl->hsPool, ssl->sec.eccKeyPriv, c, + &keyLen) < 0) { + return MATRIXSSL_ERROR; + } + psAssert(keyLen == (uint32)*(c - 1)); +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + /* Set aside retransmit for this case here since there is + nothing happening in nowDoCke related to the handshake + message output */ + ssl->ckeSize = keyLen + 1; + ssl->ckeMsg = psMalloc(ssl->hsPool, ssl->ckeSize); + if (ssl->ckeMsg == NULL) { + return SSL_MEM_ERROR; + } + memcpy(ssl->ckeMsg, c - 1, ssl->ckeSize); + } +#endif + c += keyLen; +/* + Generate premaster and free ECC key material +*/ + ssl->sec.premasterSize = ssl->sec.eccKeyPriv->curve->size; + ssl->sec.premaster = psMalloc(ssl->hsPool, ssl->sec.premasterSize); + if (ssl->sec.premaster == NULL) { + return SSL_MEM_ERROR; + } + + /* Schedule EC secret generation */ + pkaAfter->type = PKA_AFTER_ECDH_SECRET_GEN; + pkaAfter->inbuf = NULL; + pkaAfter->inlen = 0; + pkaAfter->outbuf = ssl->sec.premaster; + pkaAfter->data = pkiData; + + } else { +#endif /* USE_ECC_CIPHER_SUITE */ +#ifdef REQUIRE_DH_PARAMS + { + uint16_t dhLen = end - c; + /* Write out the public key part of our private key */ + if (psDhExportPubKey(ssl->hsPool, ssl->sec.dhKeyPriv, c, &dhLen) < 0) { + return MATRIXSSL_ERROR; + } + psAssert(dhLen == keyLen); + } +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + /* Set aside retransmit for this case here since there is + nothing happening in nowDoCke related to the handshake + message output */ + ssl->ckeSize = keyLen; + ssl->ckeMsg = psMalloc(ssl->hsPool, ssl->ckeSize); + if (ssl->ckeMsg == NULL) { + return SSL_MEM_ERROR; + } + memcpy(ssl->ckeMsg, c, ssl->ckeSize); + } +#endif + c += keyLen; + + /* Schedule DH secret gen.*/ + pkaAfter->type = PKA_AFTER_DH_KEY_GEN; + pkaAfter->inbuf = NULL; + pkaAfter->inlen = 0; +#ifdef USE_PSK_CIPHER_SUITE + /* Borrowing the inbuf and inlen params to hold pskId information */ + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { + pkaAfter->inlen = pskIdLen; + if ((pkaAfter->inbuf = psMalloc(ssl->hsPool, pskIdLen)) == NULL) { + return PS_MEM_FAIL; + } + memcpy(pkaAfter->inbuf, pskId, pskIdLen); + } +#endif + pkaAfter->outbuf = ssl->sec.premaster; + pkaAfter->user = ssl->sec.premasterSize; + pkaAfter->data = pkiData; + +#endif /* REQUIRE_DH_PARAMS */ +#ifdef USE_ECC_CIPHER_SUITE + } +#endif /* USE_ECC_CIPHER_SUITE */ + + } else { +#endif /* USE_DHE_CIPHER_SUITE */ +#ifdef USE_PSK_CIPHER_SUITE +/* + Create the premaster for basic PSK suites +*/ + if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { +/* + RFC4279: The premaster secret is formed as follows: if the PSK is + N octets long, concatenate a uint16 with the value N, N zero octets, + a second uint16 with the value N, and the PSK itself. + @note pskIdLen will contain the length of pskKey after this call. +*/ + matrixSslPskGetKey(ssl, pskId, pskIdLen, &pskKey, &pskIdLen); + if (pskKey == NULL) { + return MATRIXSSL_ERROR; + } + ssl->sec.premasterSize = (pskIdLen * 2) + 4; + ssl->sec.premaster = psMalloc(ssl->hsPool, ssl->sec.premasterSize); + if (ssl->sec.premaster == NULL) { + return SSL_MEM_ERROR; + } + memset(ssl->sec.premaster, 0, ssl->sec.premasterSize); + ssl->sec.premaster[0] = (pskIdLen & 0xFF00) >> 8; + ssl->sec.premaster[1] = (pskIdLen & 0xFF); + /* memset to 0 handled middle portion */ + ssl->sec.premaster[2 + pskIdLen] = (pskIdLen & 0xFF00) >> 8; + ssl->sec.premaster[3 + pskIdLen] = (pskIdLen & 0xFF); + memcpy(&ssl->sec.premaster[4 + pskIdLen], pskKey, pskIdLen); + /* Now that we've got the premaster secret, derive the various + symmetrics. Correct this is only a PSK requirement here because + there is no pkaAfter to call it later + + However, if extended_master_secret is being used we must delay + the master secret creation until the CKE handshake message has + been added to the rolling handshake hash. Key generation will + be done in encryptRecord */ + if (ssl->extFlags.extended_master_secret == 0) { + if ((rc = sslCreateKeys(ssl)) < 0) { + return rc; + } + } + + } else { +#endif /* USE_PSK_CIPHER_SUITE */ +#ifndef USE_ONLY_PSK_CIPHER_SUITE + /* Non-DHE cases below */ +#ifdef USE_ECC_CIPHER_SUITE + if (ssl->cipher->type == CS_ECDH_ECDSA || + ssl->cipher->type == CS_ECDH_RSA) { + + /* Write key len */ + keyLen--; + *c = keyLen & 0xFF; c++; + + /* Tricky case where a key generation, public key write, and + then secret generation are needed. Schedule the key gen. + The combination of the cipher suite type and the pkaAfter + type will be used to locate this case */ + pkaAfter->type = PKA_AFTER_ECDH_KEY_GEN; + pkaAfter->outbuf = c; /* Where the public key will be written */ + pkaAfter->pool = pkiPool; + pkaAfter->data = pkiData; + pkaAfter->user = keyLen; + + c += keyLen; + + /* Allocate premaster and free ECC key material */ + + ssl->sec.premasterSize = + ssl->sec.cert->publicKey.key.ecc.curve->size; + ssl->sec.premaster = psMalloc(ssl->hsPool, + ssl->sec.premasterSize); + if (ssl->sec.premaster == NULL) { + return SSL_MEM_ERROR; + } + + } else { +#endif /* USE_ECC_CIPHER_SUITE */ +#ifdef USE_RSA_CIPHER_SUITE +/* + Standard RSA suite +*/ + ssl->sec.premasterSize = SSL_HS_RSA_PREMASTER_SIZE; + ssl->sec.premaster = psMalloc(ssl->hsPool, + SSL_HS_RSA_PREMASTER_SIZE); + if (ssl->sec.premaster == NULL) { + return SSL_MEM_ERROR; + } + + ssl->sec.premaster[0] = ssl->reqMajVer; + ssl->sec.premaster[1] = ssl->reqMinVer; + if (matrixCryptoGetPrngData(ssl->sec.premaster + 2, + SSL_HS_RSA_PREMASTER_SIZE - 2, ssl->userPtr) < 0) { + return MATRIXSSL_ERROR; + } + + /* Shedule RSA encryption. Put tmp pool under control of After */ + pkaAfter->type = PKA_AFTER_RSA_ENCRYPT; + pkaAfter->outbuf = c; + pkaAfter->data = pkiData; + pkaAfter->pool = pkiPool; + pkaAfter->user = keyLen; /* Available space */ + + c += keyLen; +#else /* RSA is the 'default' so if that didn't get hit there is a problem */ + psTraceInfo("There is no handler for writeClientKeyExchange. ERROR\n"); + return MATRIXSSL_ERROR; +#endif /* USE_RSA_CIPHER_SUITE */ +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + +#ifdef USE_ECC_CIPHER_SUITE + } +#endif /* USE_ECC_CIPHER_SUITE */ +#ifdef USE_PSK_CIPHER_SUITE + } +#endif /* USE_PSK_CIPHER_SUITE */ +#ifdef USE_DHE_CIPHER_SUITE + } +#endif /* USE_DHE_CIPHER_SUITE */ + +#ifdef USE_DTLS + } +#endif /* USE_DTLS */ + + if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_CLIENT_KEY_EXCHANGE, messageSize, padLen, encryptStart, out, + &c)) < 0) { + return rc; + } + + out->end = c; + return MATRIXSSL_SUCCESS; +} + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#ifdef USE_CLIENT_AUTH +/******************************************************************************/ +/* Postponed CERTIFICATE_VERIFY PKA operation */ +static int32 nowDoCvPka(ssl_t *ssl, psBuf_t *out) +{ + pkaAfter_t *pka; + unsigned char msgHash[SHA512_HASH_SIZE]; +#ifdef USE_DTLS + int32 saveSize; +#endif /* USE_DTLS */ + psPool_t *pkiPool = NULL; + + pka = &ssl->pkaAfter[0]; + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (ssl->retransmit) { + /* This call is not gated on pkaAfter.type so we test for + retransmits manaully. The retransmit will have already been + written in writeCertifiateVerify if true */ + return PS_SUCCESS; + } + } +#endif /* USE_DTLS */ + + /* Does a smart default hash automatically for us */ + if (sslSnapshotHSHash(ssl, msgHash, -1) <= 0) { + psTraceInfo("Internal error: handshake hash failed\n"); + return MATRIXSSL_ERROR; + } + +#ifdef USE_ECC + if (pka->type == PKA_AFTER_ECDSA_SIG_GEN) { + /* NEGATIVE ECDSA - New temp location for ECDSA sig which can be + two bytes larger MAX than what we originally calculated + (pka->user is holding). */ + unsigned char *tmpEcdsa; + uint16_t len; + + /* Only need to allocate 1 larger because 1 has already been added */ + if ((tmpEcdsa = psMalloc(ssl->hsPool, pka->user + 1)) == NULL) { + return PS_MEM_FAIL; + } + + +#ifdef USE_TLS_1_2 + /* Tweak if needed */ + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + if (pka->inlen == SHA1_HASH_SIZE) { + sslSha1SnapshotHSHash(ssl, msgHash); + } else if (pka->inlen == SHA384_HASH_SIZE) { + sslSha384SnapshotHSHash(ssl, msgHash); + } else if (pka->inlen == SHA512_HASH_SIZE) { + sslSha512SnapshotHSHash(ssl, msgHash); + } +#ifdef USE_DTLS + ssl->ecdsaSizeChange = 0; +#endif + /* NEGATIVE ECDSA - 5th output param is now tmp instead of + pka->outbuf. Length of outbuf is increased by 1 */ + len = pka->user + 1; + if (psEccDsaSign(pkiPool, &ssl->keys->privKey.key.ecc, + msgHash, pka->inlen, tmpEcdsa, &len, 1, pka->data) != 0) { + psFree(tmpEcdsa, ssl->hsPool); + return MATRIXSSL_ERROR; + } + } else { +#ifdef USE_DTLS + ssl->ecdsaSizeChange = 0; +#endif + len = pka->user + 1; + if (psEccDsaSign(pkiPool, &ssl->keys->privKey.key.ecc, + msgHash + MD5_HASH_SIZE, SHA1_HASH_SIZE, + tmpEcdsa, &len, 1, pka->data) != 0) { + psFree(tmpEcdsa, ssl->hsPool); + return MATRIXSSL_ERROR; + } + } +#else /* USE_TLS_1_2 */ + + len = pka->user + 1; +#ifdef USE_DTLS + ssl->ecdsaSizeChange = 0; +#endif + /* The ECDSA signature is always done over a SHA1 hash so we need + to skip over the first 16 bytes of MD5 that the SSL hash stores */ + if (psEccDsaSign(pkiPool, &ssl->keys->privKey.key.ecc, + msgHash + MD5_HASH_SIZE, SHA1_HASH_SIZE, + tmpEcdsa, &len, 1, pka->data) != 0) { + psFree(tmpEcdsa, ssl->hsPool); + return MATRIXSSL_ERROR; + } +#endif /* USE_TLS_1_2 */ + + if (len != pka->user) { + /* int accountForEcdsaSizeChange(ssl_t *ssl, pkaAfter_t *pka, int real, + unsigned char *sig, psBuf_t *out); */ + if (accountForEcdsaSizeChange(ssl, pka, len, tmpEcdsa, out, + SSL_HS_CERTIFICATE_VERIFY) < 0) { + clearPkaAfter(ssl); + psFree(tmpEcdsa, ssl->hsPool); + return MATRIXSSL_ERROR; + } + } else { + memcpy(pka->outbuf, tmpEcdsa, pka->user); + } + psFree(tmpEcdsa, ssl->hsPool); +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + saveSize = len; + + ssl->certVerifyMsgLen = saveSize; + ssl->certVerifyMsg = psMalloc(ssl->hsPool, saveSize); + if (ssl->certVerifyMsg == NULL) { + return SSL_MEM_ERROR; + } + memcpy(ssl->certVerifyMsg, pka->outbuf, saveSize); + } +#endif /* USE_DTLS */ + clearPkaAfter(ssl); + + + } else { +#endif /* USE_ECC */ + +#ifdef USE_RSA +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + /* RFC: "The hash and signature algorithms used in the + signature MUST be one of those present in the + supported_signature_algorithms field of the + CertificateRequest message. In addition, the hash and + signature algorithms MUST be compatible with the key in the + client's end-entity certificate. + + We've done the above tests in the parse of the + CertificateRequest message and wouldn't be here if our + certs didn't match the sigAlgs. However, we do have + to test for both sig algorithm types here to find the + hash strength because the sig alg might not match the + pubkey alg. This was also already confirmed in + CertRequest parse so wouldn't be here if not allowed */ + if (pka->inlen == SHA1_HASH_SIZE) { + sslSha1SnapshotHSHash(ssl, msgHash); + } else if (pka->inlen == SHA256_HASH_SIZE) { +#ifdef USE_SHA384 + } else if (pka->inlen == SHA384_HASH_SIZE) { + sslSha384SnapshotHSHash(ssl, msgHash); +#endif /* USE_SHA384 */ +#ifdef USE_SHA512 + } else if (pka->inlen == SHA512_HASH_SIZE) { + sslSha512SnapshotHSHash(ssl, msgHash); +#endif /* USE_SHA512 */ + } + + /* The signed element is not the straight hash */ + if (privRsaEncryptSignedElement(pkiPool, &ssl->keys->privKey.key.rsa, + msgHash, pka->inlen, pka->outbuf, + ssl->keys->privKey.keysize, pka->data) < 0) { + return MATRIXSSL_ERROR; + } + } else { + if (psRsaEncryptPriv(pkiPool, &ssl->keys->privKey.key.rsa, msgHash, + pka->inlen, pka->outbuf, ssl->keys->privKey.keysize, + pka->data) < 0) { + return MATRIXSSL_ERROR; + + } + } +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + saveSize = ssl->keys->privKey.keysize; + + ssl->certVerifyMsgLen = saveSize; + ssl->certVerifyMsg = psMalloc(ssl->hsPool, saveSize); + if (ssl->certVerifyMsg == NULL) { + return SSL_MEM_ERROR; + } + memcpy(ssl->certVerifyMsg, pka->outbuf, saveSize); + } +#endif /* USE_DTLS */ + clearPkaAfter(ssl); + +#else /* ! USE_TLS_1_2 */ + if (psRsaEncryptPriv(pkiPool, &ssl->keys->privKey.key.rsa, msgHash, + pka->inlen, pka->outbuf, ssl->keys->privKey.keysize, + pka->data) < 0) { + return MATRIXSSL_ERROR; + } +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + saveSize = ssl->keys->privKey.keysize; + + ssl->certVerifyMsgLen = saveSize; + ssl->certVerifyMsg = psMalloc(ssl->hsPool, saveSize); + if (ssl->certVerifyMsg == NULL) { + return SSL_MEM_ERROR; + } + memcpy(ssl->certVerifyMsg, pka->outbuf, saveSize); + } +#endif /* USE_DTLS */ + clearPkaAfter(ssl); +#endif /* USE_TLS_1_2 */ + + + +#else /* RSA is the 'default' so if that didn't get hit there is a problem */ + psTraceInfo("There is no handler for writeCertificateVerify. ERROR\n"); + return MATRIXSSL_ERROR; +#endif /* USE_RSA */ +#ifdef USE_ECC + } /* Closing type test */ +#endif /* USE_ECC */ + + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Write the CertificateVerify message (client auth only) + The message contains the signed hash of the handshake messages. + + The PKA operation is delayed +*/ +static int32 writeCertificateVerify(ssl_t *ssl, sslBuf_t *out) +{ + unsigned char *c, *end, *encryptStart; + uint8_t padLen; + uint16_t messageSize, hashSize; + int32_t rc; + pkaAfter_t *pkaAfter; + void *pkiData = ssl->userPtr; + + psTraceHs("<<< Client creating CERTIFICATE_VERIFY message\n"); + c = out->end; + end = out->buf + out->size; + + + if ((pkaAfter = getPkaAfter(ssl)) == NULL) { + psTraceInfo("getPkaAfter error for certVerify\n"); + return MATRIXSSL_ERROR; + } + + messageSize = ssl->recordHeadLen + ssl->hshakeHeadLen + + 2 + ssl->keys->privKey.keysize; + +#ifdef USE_ECC + /* Additional ASN.1 overhead from psEccSignHash */ + if (ssl->keys->cert->pubKeyAlgorithm == OID_ECDSA_KEY_ALG) { + messageSize += 6; + /* NEGATIVE ECDSA - Adding ONE spot for a 0x0 byte in the + ECDSA signature. This will allow us to be right ~50% of + the time and not require any manual manipulation + + However, if this is a 521 curve there is no chance + the final byte could be negative if the full 66 + bytes are needed because there can only be a single + low bit for that sig size. So subtract that byte + back out to stay around the 50% no-move goal */ + if (ssl->keys->privKey.keysize != 132) { + messageSize += 1; + } + /* BIG EC KEY. The sig is 2 bytes len, 1 byte SEQ, + 1 byte length (+1 OPTIONAL byte if length is >=128), + 1 byte INT, 1 byte rLen, r, 1 byte INT, 1 byte sLen, s. + So the +4 here are the 2 INT and 2 rLen/sLen bytes on + top of the keysize */ + if (ssl->keys->privKey.keysize + 4 >= 128) { + messageSize++; /* Extra byte for 'long' asn.1 encode */ + } +#ifdef USE_DTLS + if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 1)) { + /* We already know if this signature got resized */ + messageSize += ssl->ecdsaSizeChange; + } +#endif + } +#endif /* USE_ECC */ + +#ifdef USE_TLS_1_2 +/* RFC: "This is the concatenation of all the + Handshake structures (as defined in Section 7.4) exchanged thus + far. Note that this requires both sides to either buffer the + messages or compute running hashes for all potential hash + algorithms up to the time of the CertificateVerify computation. + Servers can minimize this computation cost by offering a + restricted set of digest algorithms in the CertificateRequest + message." + + We're certainly not going to buffer the messages so the + handshake hash update and snapshot functions have to keep the + running total. Not a huge deal for the updating but + the current snapshot framework didn't support this so there + are one-off algorithm specific snapshots where needed. */ + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + messageSize += 2; /* hashSigAlg */ + } +#endif + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_CERTIFICATE_VERIFY, &messageSize, &padLen, + &encryptStart, end, &c)) < 0) { + return rc; + } + +/* + Correct to be looking at the child-most cert here because that is the + one associated with the private key. +*/ +#ifdef USE_ECC + if (ssl->keys->cert->pubKeyAlgorithm == OID_ECDSA_KEY_ALG) { + hashSize = MD5_HASH_SIZE + SHA1_HASH_SIZE; +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + /* RFC: "The hash and signature algorithms used in the + signature MUST be one of those present in the + supported_signature_algorithms field of the + CertificateRequest message. In addition, the hash and + signature algorithms MUST be compatible with the key in the + client's end-entity certificate." + + We've done the above tests in the parse of the + CertificateRequest message and wouldn't be here if our + certs didn't match the sigAlgs. However, we do have + to test for both sig algorithm types here to find the + hash strength because the sig alg might not match the + pubkey alg. This was also already confirmed in + CertRequest parse so wouldn't be here if not allowed */ + if ((ssl->keys->cert->sigAlgorithm == OID_SHA1_ECDSA_SIG) || + (ssl->keys->cert->sigAlgorithm == OID_SHA1_RSA_SIG)) { + *c = 0x2; c++; /* SHA1 */ + *c = 0x3; c++; /* ECDSA */ + hashSize = SHA1_HASH_SIZE; + } else if ((ssl->keys->cert->sigAlgorithm == + OID_SHA256_ECDSA_SIG) || (ssl->keys->cert->sigAlgorithm + == OID_SHA256_RSA_SIG)) { + *c = 0x4; c++; /* SHA256 */ + *c = 0x3; c++; /* ECDSA */ + hashSize = SHA256_HASH_SIZE; +#ifdef USE_SHA384 + } else if ((ssl->keys->cert->sigAlgorithm == + OID_SHA384_ECDSA_SIG) || (ssl->keys->cert->sigAlgorithm + == OID_SHA384_RSA_SIG)) { + *c = 0x5; c++; /* SHA384 */ + *c = 0x3; c++; /* ECDSA */ + hashSize = SHA384_HASH_SIZE; +#endif +#ifdef USE_SHA512 + } else if ((ssl->keys->cert->sigAlgorithm == + OID_SHA512_ECDSA_SIG) || (ssl->keys->cert->sigAlgorithm + == OID_SHA512_RSA_SIG)) { + *c = 0x6; c++; /* SHA512 */ + *c = 0x3; c++; /* ECDSA */ + hashSize = SHA512_HASH_SIZE; +#endif + } else { + psTraceInfo("Need more hash support for certVerify\n"); + return MATRIXSSL_ERROR; + } + } +#endif /* USE_TLS_1_2 */ + + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS && ssl->retransmit) { + memcpy(c, ssl->certVerifyMsg, ssl->certVerifyMsgLen); + c += ssl->certVerifyMsgLen; + } else { +#endif + + pkaAfter->inlen = hashSize; + pkaAfter->type = PKA_AFTER_ECDSA_SIG_GEN; + pkaAfter->data = pkiData; + pkaAfter->outbuf = c; + rc = ssl->keys->privKey.keysize + 8; + /* NEGATIVE ECDSA - Adding spot for ONE 0x0 byte in ECDSA so we'll + be right 50% of the time. 521 curve doesn't need */ + if (ssl->keys->privKey.keysize != 132) { + rc += 1; + } + /* Above we added in the 8 bytes of overhead (2 sigLen, 1 SEQ, + 1 len (possibly 2!), 1 INT, 1 rLen, 1 INT, 1 sLen) and now + subtract the first 3 bytes to see if the 1 len needs to be 2 */ + if (rc - 3 >= 128) { + rc++; + } + pkaAfter->user = rc; + c += rc; +#ifdef USE_DTLS + } +#endif + } else { +#endif /* USE_ECC */ + +#ifdef USE_RSA + hashSize = MD5_HASH_SIZE + SHA1_HASH_SIZE; +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + /* RFC: "The hash and signature algorithms used in the + signature MUST be one of those present in the + supported_signature_algorithms field of the + CertificateRequest message. In addition, the hash and + signature algorithms MUST be compatible with the key in the + client's end-entity certificate. + + We've done the above tests in the parse of the + CertificateRequest message and wouldn't be here if our + certs didn't match the sigAlgs. However, we do have + to test for both sig algorithm types here to find the + hash strength because the sig alg might not match the + pubkey alg. This was also already confirmed in + CertRequest parse so wouldn't be here if not allowed */ + if (ssl->keys->cert->sigAlgorithm == OID_SHA1_RSA_SIG || + ssl->keys->cert->sigAlgorithm == OID_MD5_RSA_SIG || + ssl->keys->cert->sigAlgorithm == OID_SHA1_ECDSA_SIG) { + *c = 0x2; c++; /* SHA1 */ + *c = 0x1; c++; /* RSA */ + hashSize = SHA1_HASH_SIZE; + } else if (ssl->keys->cert->sigAlgorithm == OID_SHA256_RSA_SIG || + ssl->keys->cert->sigAlgorithm == OID_SHA256_ECDSA_SIG) { + *c = 0x4; c++; /* SHA256 */ + *c = 0x1; c++; /* RSA */ + /* Normal handshake hash uses SHA256 and has been done above */ + hashSize = SHA256_HASH_SIZE; +#ifdef USE_SHA384 + } else if (ssl->keys->cert->sigAlgorithm == OID_SHA384_RSA_SIG || + ssl->keys->cert->sigAlgorithm == OID_SHA384_ECDSA_SIG) { + *c = 0x5; c++; /* SHA384 */ + *c = 0x1; c++; /* RSA */ + hashSize = SHA384_HASH_SIZE; +#endif /* USE_SHA384 */ +#ifdef USE_SHA512 + } else if (ssl->keys->cert->sigAlgorithm == OID_SHA512_RSA_SIG || + ssl->keys->cert->sigAlgorithm == OID_SHA512_ECDSA_SIG) { + *c = 0x6; c++; /* SHA512 */ + *c = 0x1; c++; /* RSA */ + hashSize = SHA512_HASH_SIZE; +#endif /* USE_SHA512 */ +#ifdef USE_PKCS1_PSS + } else if (ssl->keys->cert->sigAlgorithm == OID_RSASSA_PSS) { + if (ssl->keys->cert->pssHash == PKCS1_SHA1_ID || + ssl->keys->cert->pssHash == PKCS1_MD5_ID) { + *c = 0x2; c++; + hashSize = SHA1_HASH_SIZE; + } else if (ssl->keys->cert->pssHash == PKCS1_SHA256_ID) { + *c = 0x4; c++; + hashSize = SHA256_HASH_SIZE; +#ifdef USE_SHA384 + } else if (ssl->keys->cert->pssHash == PKCS1_SHA384_ID) { + *c = 0x5; c++; + hashSize = SHA384_HASH_SIZE; +#endif +#ifdef USE_SHA512 + } else if (ssl->keys->cert->pssHash == PKCS1_SHA512_ID) { + *c = 0x6; c++; + hashSize = SHA512_HASH_SIZE; +#endif + } else { + psTraceInfo("Need additional hash support for certVerify\n"); + return MATRIXSSL_ERROR; + } + *c = 0x1; c++; /* RSA */ +#endif + } else { + psTraceInfo("Need additional hash support for certVerify\n"); + return MATRIXSSL_ERROR; + } + + pkaAfter->type = PKA_AFTER_RSA_SIG_GEN_ELEMENT; /* this one */ + } else { + pkaAfter->type = PKA_AFTER_RSA_SIG_GEN; + } +#else /* ! USE_TLS_1_2 */ + pkaAfter->type = PKA_AFTER_RSA_SIG_GEN; +#endif /* USE_TLS_1_2 */ + + *c = (ssl->keys->privKey.keysize & 0xFF00) >> 8; c++; + *c = (ssl->keys->privKey.keysize & 0xFF); c++; + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS && ssl->retransmit) { + pkaAfter->type = 0; /* reset so AFTER logic doesn't trigger */ + memcpy(c, ssl->certVerifyMsg, ssl->certVerifyMsgLen); + c += ssl->certVerifyMsgLen; + } else { +#endif + pkaAfter->data = pkiData; + pkaAfter->inlen = hashSize; + pkaAfter->outbuf = c; + c += ssl->keys->privKey.keysize; +#ifdef USE_DTLS + } +#endif + +#else /* RSA is the 'default' so if that didn't get hit there is a problem */ + psTraceInfo("There is no handler for writeCertificateVerify. ERROR\n"); + return MATRIXSSL_ERROR; +#endif /* USE_RSA */ +#ifdef USE_ECC + } /* Closing sigAlgorithm test */ +#endif /* USE_ECC */ + + if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_CERTIFICATE_VERIFY, messageSize, padLen, encryptStart, out, + &c)) < 0) { + return rc; + } + out->end = c; + return MATRIXSSL_SUCCESS; +} +#endif /* USE_CLIENT_AUTH */ +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + + +#else /* USE_CLIENT_SIDE_SSL */ +/******************************************************************************/ +/* + Stub out this function rather than ifdef it out in the public header +*/ +int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out, + const uint16_t cipherSpec[], uint8_t cipherSpecLen, + uint32 *requiredLen, tlsExtension_t *userExt, + sslSessOpts_t *options) +{ + psTraceInfo("Library not built with USE_CLIENT_SIDE_SSL\n"); + return PS_UNSUPPORTED_FAIL; +} +#endif /* USE_CLIENT_SIDE_SSL */ + + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +#if defined(USE_SERVER_SIDE_SSL) && defined(USE_CLIENT_AUTH) +/******************************************************************************/ +/* + Write the CertificateRequest message (client auth only) + The message contains the list of CAs the server is willing to accept + children certificates of from the client. +*/ +static int32 writeCertificateRequest(ssl_t *ssl, sslBuf_t *out, int32 certLen, + int32 certCount) +{ + unsigned char *c, *end, *encryptStart; + psX509Cert_t *cert; + uint8_t padLen; + uint16_t messageSize, sigHashLen = 0; + int32_t rc; + + psTraceHs("<<< Server creating CERTIFICATE_REQUEST message\n"); + c = out->end; + end = out->buf + out->size; + + messageSize = ssl->recordHeadLen + ssl->hshakeHeadLen + + 4 + (certCount * 2) + certLen; +#ifdef USE_ECC + messageSize += 1; /* Adding ECDSA_SIGN type */ +#endif /* USE_ECC */ + +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + /* TLS 1.2 has a SignatureAndHashAlgorithm type after CertType */ + sigHashLen = 2; +#ifdef USE_ECC +#ifdef USE_SHA384 + sigHashLen += 6; +#else + sigHashLen += 4; +#endif /* USE_SHA */ +#endif /* USE_ECC */ +#ifdef USE_RSA +#ifdef USE_SHA384 + sigHashLen += 6; +#else + sigHashLen += 4; +#endif /* USE_SHA */ +#endif /* USE_RSA */ + messageSize += sigHashLen; + } +#endif /* TLS_1_2 */ + + if ((messageSize - ssl->recordHeadLen) > ssl->maxPtFrag) { + return writeMultiRecordCertRequest(ssl, out, certLen, certCount, + sigHashLen); + } + + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_CERTIFICATE_REQUEST, &messageSize, &padLen, + &encryptStart, end, &c)) < 0) { +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { +/* + Is this the fragment case? +*/ + if (rc == DTLS_MUST_FRAG) { + rc = dtlsWriteCertificateRequest(ssl->hsPool, ssl, + certLen, certCount, sigHashLen, c); + if (rc < 0) { + return rc; + } + c += rc; + out->end = c; + return MATRIXSSL_SUCCESS; + } + } +#endif /* USE_DTLS */ + return rc; + } + +#ifdef USE_ECC + *c++ = 2; + *c++ = ECDSA_SIGN; +#else + *c++ = 1; +#endif + *c++ = RSA_SIGN; +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + /* RFC: "The interaction of the certificate_types and + supported_signature_algorithms fields is somewhat complicated. + certificate_types has been present in TLS since SSLv3, but was + somewhat underspecified. Much of its functionality is superseded + by supported_signature_algorithms." + + The spec says the cert must support the hash/sig algorithm but + it's a bit confusing what this means for the hash portion. + Just going to use SHA1, SHA256, and SHA384 support. + + We're just sending the raw list of all sig algorithms that are + compiled into the library. It might be smart to look through the + individual CA files here only send the pub key operations that + they use but the CA info is sent explicitly anyway so the client + can confirm they have a proper match. + + If a new algorithm is added here it will require additions to + messageSize directly above in this function and in the flight + calculation in sslEncodeResponse */ + *c++ = 0x0; + *c++ = sigHashLen - 2; +#ifdef USE_ECC +#ifdef USE_SHA384 + *c++ = 0x5; /* SHA384 */ + *c++ = 0x3; /* ECDSA */ + *c++ = 0x4; /* SHA256 */ + *c++ = 0x3; /* ECDSA */ + *c++ = 0x2; /* SHA1 */ + *c++ = 0x3; /* ECDSA */ +#else + *c++ = 0x4; /* SHA256 */ + *c++ = 0x3; /* ECDSA */ + *c++ = 0x2; /* SHA1 */ + *c++ = 0x3; /* ECDSA */ +#endif +#endif + +#ifdef USE_RSA +#ifdef USE_SHA384 + *c++ = 0x5; /* SHA384 */ + *c++ = 0x1; /* RSA */ + *c++ = 0x4; /* SHA256 */ + *c++ = 0x1; /* RSA */ + *c++ = 0x2; /* SHA1 */ + *c++ = 0x1; /* RSA */ +#else + *c++ = 0x4; /* SHA256 */ + *c++ = 0x1; /* RSA */ + *c++ = 0x2; /* SHA1 */ + *c++ = 0x1; /* RSA */ +#endif +#endif /* USE_RSA */ + } +#endif /* TLS_1_2 */ + + cert = ssl->keys->CAcerts; + if (cert) { + *c = ((certLen + (certCount * 2))& 0xFF00) >> 8; c++; + *c = (certLen + (certCount * 2)) & 0xFF; c++; + while (cert) { + *c = (cert->subject.dnencLen & 0xFF00) >> 8; c++; + *c = cert->subject.dnencLen & 0xFF; c++; + memcpy(c, cert->subject.dnenc, cert->subject.dnencLen); + c += cert->subject.dnencLen; + cert = cert->next; + } + } else { + *c++ = 0; /* Cert len */ + *c++ = 0; + } + if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_CERTIFICATE_REQUEST, messageSize, padLen, encryptStart, out, + &c)) < 0) { + return rc; + } + out->end = c; + return MATRIXSSL_SUCCESS; +} + + + +static int32 writeMultiRecordCertRequest(ssl_t *ssl, sslBuf_t *out, + int32 certLen, int32 certCount, int32 sigHashLen) +{ + psX509Cert_t *cert, *future; + unsigned char *c, *end, *encryptStart; + uint8_t padLen; + uint16_t messageSize, dnencLen; + int32 midWrite, midSizeWrite, countDown, firstOne = 1; + int32_t rc; + + c = out->end; + end = out->buf + out->size; + + midSizeWrite = midWrite = 0; + + while (certLen > 0) { + if (firstOne){ + firstOne = 0; + countDown = ssl->maxPtFrag; + messageSize = ssl->recordHeadLen + ssl->hshakeHeadLen + + 4 + (certCount * 2) + certLen + sigHashLen; +#ifdef USE_ECC + messageSize += 1; /* Adding ECDSA_SIGN type */ +#endif /* USE_ECC */ + if ((rc = writeRecordHeader(ssl, + SSL_RECORD_TYPE_HANDSHAKE_FIRST_FRAG, + SSL_HS_CERTIFICATE_REQUEST, &messageSize, &padLen, + &encryptStart, end, &c)) < 0) { + return rc; + } +#ifdef USE_ECC + *c++ = 2; + *c++ = ECDSA_SIGN; + countDown -= 2; +#else + *c++ = 1; + countDown--; +#endif + *c++ = RSA_SIGN; + countDown--; +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + *c++ = 0x0; + *c++ = sigHashLen - 2; +#ifdef USE_ECC +#ifdef USE_SHA384 + *c++ = 0x5; /* SHA384 */ + *c++ = 0x3; /* ECDSA */ + *c++ = 0x4; /* SHA256 */ + *c++ = 0x3; /* ECDSA */ + *c++ = 0x2; /* SHA1 */ + *c++ = 0x3; /* ECDSA */ +#else + *c++ = 0x4; /* SHA256 */ + *c++ = 0x3; /* ECDSA */ + *c++ = 0x2; /* SHA1 */ + *c++ = 0x3; /* ECDSA */ +#endif +#endif + +#ifdef USE_RSA +#ifdef USE_SHA384 + *c++ = 0x5; /* SHA384 */ + *c++ = 0x1; /* RSA */ + *c++ = 0x4; /* SHA256 */ + *c++ = 0x1; /* RSA */ + *c++ = 0x2; /* SHA1 */ + *c++ = 0x1; /* RSA */ +#else + *c++ = 0x4; /* SHA256 */ + *c++ = 0x1; /* RSA */ + *c++ = 0x2; /* SHA1 */ + *c++ = 0x1; /* RSA */ +#endif +#endif /* USE_RSA */ + countDown -= sigHashLen; + } +#endif /* TLS_1_2 */ + cert = ssl->keys->CAcerts; + *c = ((certLen + (certCount * 2))& 0xFF00) >> 8; c++; + *c = (certLen + (certCount * 2)) & 0xFF; c++; + countDown -= ssl->hshakeHeadLen + 2; + while (cert) { + midWrite = 0; + dnencLen = cert->subject.dnencLen; + if (dnencLen > 0) { + if (countDown < 2) { + /* Fragment falls right on dn len write. Has + to be at least one byte or countDown would have + been 0 and got us out of here already*/ + *c = (cert->subject.dnencLen & 0xFF00) >> 8; c++; + midSizeWrite = 1; + break; + } else { + *c = (cert->subject.dnencLen & 0xFF00) >> 8; c++; + *c = cert->subject.dnencLen & 0xFF; c++; + countDown -= 2; + } + midWrite = min(dnencLen, countDown); + memcpy(c, cert->subject.dnenc, midWrite); + dnencLen -= midWrite; + c += midWrite; + certLen -= midWrite; + countDown -= midWrite; + if (countDown == 0) { + break; + } + } + cert = cert->next; + } + if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_CERTIFICATE_REQUEST, messageSize, padLen, + encryptStart, out, &c)) < 0) { + return rc; + } + out->end = c; + } else { + /* Not-first fragments */ + if (midSizeWrite > 0) { + messageSize = midSizeWrite; + } else { + messageSize = 0; + } + if ((certLen + messageSize) > ssl->maxPtFrag) { + messageSize += ssl->maxPtFrag; + } else { + messageSize += dnencLen; + if (cert->next != NULL) { + future = cert->next; + while (future != NULL) { + if (messageSize + future->subject.dnencLen + 2 > + (uint32)ssl->maxPtFrag) { + messageSize = ssl->maxPtFrag; + future = NULL; + } else { + messageSize += 2 + future->subject.dnencLen; + future = future->next; + } + + } + } + } + countDown = messageSize; + messageSize += ssl->recordHeadLen; + /* Second, etc... */ + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE_FRAG, + SSL_HS_CERTIFICATE_REQUEST, &messageSize, &padLen, + &encryptStart, end, &c)) < 0) { + return rc; + } + if (midSizeWrite > 0) { + *c = (dnencLen & 0xFF); c++; + countDown -= 1; + } + midSizeWrite = 0; + if (countDown < dnencLen) { + memcpy(c, cert->subject.dnenc + midWrite, countDown); + dnencLen -= countDown; + c += countDown; + certLen -= countDown; + midWrite += countDown; + countDown = 0; + } else { + memcpy(c, cert->subject.dnenc + midWrite, dnencLen); + c += dnencLen; + certLen -= dnencLen; + countDown -= dnencLen; + dnencLen -= dnencLen; + } + while (countDown > 0) { + cert = cert->next; + dnencLen = cert->subject.dnencLen; + midWrite = 0; + if (countDown < 2) { + /* Fragment falls right on cert len write */ + *c = (unsigned char)((dnencLen & 0xFF00) >> 8); + c++; countDown--; + midSizeWrite = 1; + break; + } else { + *c = (unsigned char)((dnencLen & 0xFF00) >> 8); c++; + *c = (dnencLen & 0xFF); c++; + countDown -= 2; + } + midWrite = min(dnencLen, countDown); + memcpy(c, cert->subject.dnenc, midWrite); + dnencLen -= midWrite; + c += midWrite; + certLen -= midWrite; + countDown -= midWrite; + if (countDown == 0) { + break; + } + + } + if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_CERTIFICATE_REQUEST, messageSize, padLen, + encryptStart, out, &c)) < 0) { + return rc; + } + out->end = c; + + } + + } + out->end = c; + return MATRIXSSL_SUCCESS; +} + +#endif /* USE_SERVER_SIDE && USE_CLIENT_AUTH */ +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + + +#ifdef USE_DTLS +#ifdef USE_SERVER_SIDE_SSL +/******************************************************************************/ +/* + DTLS specific handshake message to verify client existence +*/ +static int32 writeHelloVerifyRequest(ssl_t *ssl, sslBuf_t *out) +{ + unsigned char *c, *end, *encryptStart; + uint8_t padLen; + uint16_t messageSize; + int32_t rc; + + psTraceHs("<<< Server creating HELLO_VERIFY_REQUEST message\n"); + c = out->end; + end = out->buf + out->size; +/* + The magic 3 bytes consist of the 2 byte TLS version and the 1 byte length +*/ + messageSize = ssl->recordHeadLen + ssl->hshakeHeadLen + + DTLS_COOKIE_SIZE + 3; + +/* + Always have to reset msn to zero because we don't know if this is a + resend to a cookie-less CLIENT_HELLO that never receieved our verify + request +*/ + ssl->msn = 0; + + if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_HELLO_VERIFY_REQUEST, &messageSize, &padLen, + &encryptStart, end, &c)) < 0) { + return rc; + } + +/* + Message content is version, cookie length, and cookie itself +*/ + *c++ = ssl->rec.majVer; + *c++ = ssl->rec.minVer; + *c++ = DTLS_COOKIE_SIZE; + memcpy(c, ssl->srvCookie, DTLS_COOKIE_SIZE); + c += DTLS_COOKIE_SIZE; + + if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, + SSL_HS_HELLO_VERIFY_REQUEST, messageSize, padLen, encryptStart, + out, &c)) < 0) { + return rc; + } + out->end = c; + return MATRIXSSL_SUCCESS; +} +#endif /* USE_SERVER_SIDE_SSL */ +#endif /* USE_DTLS */ + +/******************************************************************************/ +/* + Write out a SSLv3 record header. + Assumes 'c' points to a buffer of at least SSL3_HEADER_LEN bytes + 1 byte type (SSL_RECORD_TYPE_*) + 1 byte major version + 1 byte minor version + 2 bytes length (network byte order) + Returns the number of bytes written +*/ +int32 psWriteRecordInfo(ssl_t *ssl, unsigned char type, int32 len, + unsigned char *c, int32 hsType) +{ + int32 explicitNonce = 0; + + if (type == SSL_RECORD_TYPE_HANDSHAKE_FRAG) { + type = SSL_RECORD_TYPE_HANDSHAKE; + } + *c = type; c++; + *c = ssl->majVer; c++; + *c = ssl->minVer; c++; +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + ssl->seqDelay = c; + *c = ssl->epoch[0]; c++; + *c = ssl->epoch[1]; c++; + *c = ssl->rsn[0]; c++; + *c = ssl->rsn[1]; c++; + *c = ssl->rsn[2]; c++; + *c = ssl->rsn[3]; c++; + *c = ssl->rsn[4]; c++; + *c = ssl->rsn[5]; c++; + } +#endif /* USE_DTLS */ + *c = (len & 0xFF00) >> 8; c++; + *c = (len & 0xFF); + + if (hsType == SSL_HS_FINISHED) { + if (ssl->cipher->flags & (CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_CCM)) { + explicitNonce++; + } + } else if (ssl->flags & SSL_FLAGS_NONCE_W) { + explicitNonce++; + } + if (explicitNonce) { +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + c++; + *c = ssl->epoch[0]; c++; + *c = ssl->epoch[1]; c++; + *c = ssl->rsn[0]; c++; + *c = ssl->rsn[1]; c++; + *c = ssl->rsn[2]; c++; + *c = ssl->rsn[3]; c++; + *c = ssl->rsn[4]; c++; + *c = ssl->rsn[5]; c++; + } else { +#endif /* USE_DTLS */ + c++; + ssl->seqDelay = c; /* not being incremented in postpone mechanism */ + *c = ssl->sec.seq[0]; c++; + *c = ssl->sec.seq[1]; c++; + *c = ssl->sec.seq[2]; c++; + *c = ssl->sec.seq[3]; c++; + *c = ssl->sec.seq[4]; c++; + *c = ssl->sec.seq[5]; c++; + *c = ssl->sec.seq[6]; c++; + *c = ssl->sec.seq[7]; +#ifdef USE_DTLS + } +#endif + return ssl->recordHeadLen + TLS_EXPLICIT_NONCE_LEN; + } + + return ssl->recordHeadLen; +} + +/******************************************************************************/ +/* + Write out an ssl handshake message header. + Assumes 'c' points to a buffer of at least ssl->hshakeHeadLen bytes + 1 byte type (SSL_HS_*) + 3 bytes length (network byte order) + Returns the number of bytes written +*/ +int32 psWriteHandshakeHeader(ssl_t *ssl, unsigned char type, int32 len, + int32 seq, int32 fragOffset, int32 fragLen, + unsigned char *c) +{ + *c = type; c++; + *c = (unsigned char)((len & 0xFF0000) >> 16); c++; + *c = (len & 0xFF00) >> 8; c++; +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + *c = (len & 0xFF); c++; + *c = (seq & 0xFF00) >> 8; c++; + *c = (seq & 0xFF); c++; + *c = (unsigned char)((fragOffset & 0xFF0000) >> 16); c++; + *c = (fragOffset & 0xFF00) >> 8; c++; + *c = (fragOffset & 0xFF); c++; + *c = (unsigned char)((fragLen & 0xFF0000) >> 16); c++; + *c = (fragLen & 0xFF00) >> 8; c++; + *c = (fragLen & 0xFF); + } else { + *c = (len & 0xFF); + } +#else + *c = (len & 0xFF); +#endif /* USE_DTLS */ + + ssl->encState = type; + return ssl->hshakeHeadLen; +} + +/******************************************************************************/ +/* + Write pad bytes and pad length per the TLS spec. Most block cipher + padding fills each byte with the number of padding bytes, but SSL/TLS + pretends one of these bytes is a pad length, and the remaining bytes are + filled with that length. The end result is that the padding is identical + to standard padding except the values are one less. For SSLv3 we are not + required to have any specific pad values, but they don't hurt. + + PadLen Result + 0 + 1 00 + 2 01 01 + 3 02 02 02 + 4 03 03 03 03 + 5 04 04 04 04 04 + 6 05 05 05 05 05 05 + 7 06 06 06 06 06 06 06 + 8 07 07 07 07 07 07 07 07 + 9 08 08 08 08 08 08 08 08 08 + ... + 15 ... + + We calculate the length of padding required for a record using + psPadLenPwr2() +*/ +int32 sslWritePad(unsigned char *p, unsigned char padLen) +{ + unsigned char c = padLen; + + while (c > 0) { + *p++ = padLen - 1; + c--; + } + return padLen; +} + +/******************************************************************************/ + diff --git a/matrixssl/sslv3.c b/matrixssl/sslv3.c new file mode 100644 index 0000000..b2b027f --- /dev/null +++ b/matrixssl/sslv3.c @@ -0,0 +1,382 @@ +/** + * @file sslv3.c + * @version $Format:%h%d$ + * + * SSLv3.0 specific code per http://wp.netscape.com/eng/ssl3.. + * Primarily dealing with secret generation, message authentication codes + * and handshake hashing. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "matrixsslApi.h" + +#ifndef DISABLE_SSLV3 +/******************************************************************************/ +/* + Constants used for key generation +*/ +static const unsigned char SENDER_CLIENT[5] = "CLNT"; /* 0x434C4E54 */ +static const unsigned char SENDER_SERVER[5] = "SRVR"; /* 0x53525652 */ + +static const unsigned char pad1[48]={ + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36 +}; + +static const unsigned char pad2[48]={ + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c +}; + +static const unsigned char *salt[10]={ + (const unsigned char *)"A", + (const unsigned char *)"BB", + (const unsigned char *)"CCC", + (const unsigned char *)"DDDD", + (const unsigned char *)"EEEEE", + (const unsigned char *)"FFFFFF", + (const unsigned char *)"GGGGGGG", + (const unsigned char *)"HHHHHHHH", + (const unsigned char *)"IIIIIIIII", + (const unsigned char *)"JJJJJJJJJJ" +}; + +/******************************************************************************/ + +static int32_t createKeyBlock(ssl_t *ssl, + const unsigned char *clientRandom, + const unsigned char *serverRandom, + const unsigned char *masterSecret); + +/******************************************************************************/ +/* + * Generates all key material. + */ +int32_t sslDeriveKeys(ssl_t *ssl) +{ + psMd5_t md5Ctx; + psSha1_t sha1Ctx; + unsigned char buf[MD5SHA1_HASHLEN]; + unsigned char *tmp; + uint8_t i; + +/* + If this session is resumed, we want to reuse the master secret to + regenerate the key block with the new random values. +*/ + if (ssl->flags & SSL_FLAGS_RESUMED) { + goto skipPremaster; + } +/* + master_secret[48] = + MD5(pre_master_secret + SHA('A' + pre_master_secret + + ClientHello.random + ServerHello.random)) + + MD5(pre_master_secret + SHA('BB' + pre_master_secret + + ClientHello.random + ServerHello.random)) + + MD5(pre_master_secret + SHA('CCC' + pre_master_secret + + ClientHello.random + ServerHello.random)); +*/ + tmp = ssl->sec.masterSecret; + for (i = 0; i < 3; i++) { + psSha1Init(&sha1Ctx); + psSha1Update(&sha1Ctx, salt[i], i + 1); + psSha1Update(&sha1Ctx, ssl->sec.premaster, ssl->sec.premasterSize); + psSha1Update(&sha1Ctx, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); + psSha1Update(&sha1Ctx, ssl->sec.serverRandom, SSL_HS_RANDOM_SIZE); + psSha1Final(&sha1Ctx, buf); + + psMd5Init(&md5Ctx); + psMd5Update(&md5Ctx, ssl->sec.premaster, ssl->sec.premasterSize); + psMd5Update(&md5Ctx, buf, SHA1_HASH_SIZE); + psMd5Final(&md5Ctx, tmp); + tmp += MD5_HASH_SIZE; + } + memzero_s(buf, MD5SHA1_HASHLEN); + + /* premaster is now allocated for DH reasons. Can free here */ + psFree(ssl->sec.premaster, ssl->hsPool); + ssl->sec.premaster = NULL; + ssl->sec.premasterSize = 0; + +skipPremaster: + if (createKeyBlock(ssl, ssl->sec.clientRandom, ssl->sec.serverRandom, + ssl->sec.masterSecret) < 0) { + psTraceInfo("Unable to create key block\n"); + return PS_FAILURE; + } + + return SSL_HS_MASTER_SIZE; +} + +/******************************************************************************/ +/* + Generate the key block as follows. '+' indicates concatination. + key_block = + MD5(master_secret + SHA(`A' + master_secret + + ServerHello.random + ClientHello.random)) + + MD5(master_secret + SHA(`BB' + master_secret + + ServerHello.random + ClientHello.random)) + + MD5(master_secret + SHA(`CCC' + master_secret + + ServerHello.random + ClientHello.random)) + + [...]; +*/ +static int32_t createKeyBlock(ssl_t *ssl, + const unsigned char *clientRandom, + const unsigned char *serverRandom, + const unsigned char *masterSecret) +{ + psMd5_t md5Ctx; + psSha1_t sha1Ctx; + unsigned char buf[MD5SHA1_HASHLEN]; + unsigned char *tmp; + int32 ret = 0; + uint32 i, keyIter, reqKeyLen; + + /* We must generate enough key material to fill the various keys */ + reqKeyLen = 2 * ssl->cipher->macSize + + 2 * ssl->cipher->keySize + + 2 * ssl->cipher->ivSize; + + /* Find the right number of iterations to make the requested length key block */ + keyIter = 1; + while (MD5_HASH_SIZE * keyIter < reqKeyLen) { + keyIter++; + } + if (keyIter > sizeof(salt)/sizeof(char*)) { + psTraceIntInfo("Error: Not enough salt for key length %d\n", reqKeyLen); + return PS_FAILURE; + } + + tmp = ssl->sec.keyBlock; + for (i = 0; i < keyIter; i++) { + psSha1Init(&sha1Ctx); + psSha1Update(&sha1Ctx, salt[i], i + 1); + psSha1Update(&sha1Ctx, masterSecret, SSL_HS_MASTER_SIZE); + psSha1Update(&sha1Ctx, serverRandom, SSL_HS_RANDOM_SIZE); + psSha1Update(&sha1Ctx, clientRandom, SSL_HS_RANDOM_SIZE); + psSha1Final(&sha1Ctx, buf); + + psMd5Init(&md5Ctx); + psMd5Update(&md5Ctx, masterSecret, SSL_HS_MASTER_SIZE); + psMd5Update(&md5Ctx, buf, SHA1_HASH_SIZE); + psMd5Final(&md5Ctx, tmp); + tmp += MD5_HASH_SIZE; + ret += MD5_HASH_SIZE; + } + memzero_s(buf, MD5SHA1_HASHLEN); +/* + Client and server use different read/write values, with the Client + write value being the server read value. +*/ + if (ssl->flags & SSL_FLAGS_SERVER) { + ssl->sec.rMACptr = ssl->sec.keyBlock; + ssl->sec.wMACptr = ssl->sec.rMACptr + ssl->cipher->macSize; + ssl->sec.rKeyptr = ssl->sec.wMACptr + ssl->cipher->macSize; + ssl->sec.wKeyptr = ssl->sec.rKeyptr + ssl->cipher->keySize; + ssl->sec.rIVptr = ssl->sec.wKeyptr + ssl->cipher->keySize; + ssl->sec.wIVptr = ssl->sec.rIVptr + ssl->cipher->ivSize; + } else { + ssl->sec.wMACptr = ssl->sec.keyBlock; + ssl->sec.rMACptr = ssl->sec.wMACptr + ssl->cipher->macSize; + ssl->sec.wKeyptr = ssl->sec.rMACptr + ssl->cipher->macSize; + ssl->sec.rKeyptr = ssl->sec.wKeyptr + ssl->cipher->keySize; + ssl->sec.wIVptr = ssl->sec.rKeyptr + ssl->cipher->keySize; + ssl->sec.rIVptr = ssl->sec.wIVptr + ssl->cipher->ivSize; + } + + return ret; +} + +/******************************************************************************/ +/* + Combine the running hash of the handshake mesages with some constants + and mix them up a bit more. Output the result to the given buffer. + This data will be part of the Finished handshake message. +*/ +int32_t sslGenerateFinishedHash(psMd5Sha1_t *md, + const unsigned char *masterSecret, + unsigned char *out, int32 senderFlags) +{ + psMd5_t omd5; + psSha1_t osha1; + unsigned char ihash[SHA1_HASH_SIZE]; + +/* + md5Hash = MD5(master_secret + pad2 + + MD5(handshake_messages + sender + master_secret + pad1)); +*/ + if (senderFlags >= 0) { + psMd5Update(&md->md5, + (senderFlags & SSL_FLAGS_SERVER) ? SENDER_SERVER : SENDER_CLIENT, 4); + } + psMd5Update(&md->md5, masterSecret, SSL_HS_MASTER_SIZE); + psMd5Update(&md->md5, pad1, sizeof(pad1)); + psMd5Final(&md->md5, ihash); + + psMd5Init(&omd5); + psMd5Update(&omd5, masterSecret, SSL_HS_MASTER_SIZE); + psMd5Update(&omd5, pad2, sizeof(pad2)); + psMd5Update(&omd5, ihash, MD5_HASH_SIZE); + psMd5Final(&omd5, out); +/* + The SHA1 hash is generated in the same way, except only 40 bytes + of pad1 and pad2 are used due to a mistake in the original SSL3 spec. + For this reason, we have to use the individual md5 and sha1 primitives, + rather than the combined hash for the inner hash calculation. + sha1Hash = SHA1(master_secret + pad2 + + SHA1(handshake_messages + sender + master_secret + pad1)); +*/ + if (senderFlags >= 0) { + psSha1Update(&md->sha1, + (senderFlags & SSL_FLAGS_SERVER) ? SENDER_SERVER : SENDER_CLIENT, 4); + } + psSha1Update(&md->sha1, masterSecret, SSL_HS_MASTER_SIZE); + psSha1Update(&md->sha1, pad1, 40); + psSha1Final(&md->sha1, ihash); + + psSha1Init(&osha1); + psSha1Update(&osha1, masterSecret, SSL_HS_MASTER_SIZE); + psSha1Update(&osha1, pad2, 40); + psSha1Update(&osha1, ihash, SHA1_HASH_SIZE); + psSha1Final(&osha1, out + MD5_HASH_SIZE); + + return MD5SHA1_HASHLEN; +} + +#ifdef USE_SHA_MAC +/******************************************************************************/ +/* + SSLv3 uses a method similar to HMAC to generate the SHA1 message MAC. + For SHA1, 40 bytes of the pad are used. + + SHA1(MAC_write_secret + pad2 + + SHA1(MAC_write_secret + pad1 + seq_num + length + content)); +*/ +int32 ssl3HMACSha1(unsigned char *key, unsigned char *seq, + unsigned char type, unsigned char *data, uint32 len, + unsigned char *mac) +{ + psSha1_t sha1; + unsigned char ihash[SHA1_HASH_SIZE]; + int32 i; + + /* Sanity */ + if (key == NULL) { + return PS_FAILURE; + } + psSha1Init(&sha1); + psSha1Update(&sha1, key, SHA1_HASH_SIZE); + psSha1Update(&sha1, pad1, 40); + psSha1Update(&sha1, seq, 8); + ihash[0] = type; + ihash[1] = (len & 0xFF00) >> 8; + ihash[2] = len & 0xFF; + psSha1Update(&sha1, ihash, 3); + psSha1Update(&sha1, data, len); + psSha1Final(&sha1, ihash); + + psSha1Init(&sha1); + psSha1Update(&sha1, key, SHA1_HASH_SIZE); + psSha1Update(&sha1, pad2, 40); + psSha1Update(&sha1, ihash, SHA1_HASH_SIZE); + psSha1Final(&sha1, mac); + +/* + Increment sequence number +*/ + for (i = 7; i >= 0; i--) { + seq[i]++; + if (seq[i] != 0) { + break; + } + } + return SHA1_HASH_SIZE; +} +#endif /* USE_SHA_MAC */ + +#ifdef USE_MD5_MAC +/******************************************************************************/ +/* + SSLv3 uses a method similar to HMAC to generate the MD5 message MAC. + For MD5, 48 bytes of the pad are used. + + MD5(MAC_write_secret + pad2 + + MD5(MAC_write_secret + pad1 + seq_num + length + content)); +*/ +int32 ssl3HMACMd5(unsigned char *key, unsigned char *seq, + unsigned char type, unsigned char *data, uint32 len, + unsigned char *mac) +{ + psMd5_t md5; + unsigned char ihash[MD5_HASH_SIZE]; + int8_t i; + + psMd5Init(&md5); + psMd5Update(&md5, key, MD5_HASH_SIZE); + psMd5Update(&md5, pad1, 48); + psMd5Update(&md5, seq, 8); + ihash[0] = type; + ihash[1] = (len & 0xFF00) >> 8; + ihash[2] = len & 0xFF; + psMd5Update(&md5, ihash, 3); + psMd5Update(&md5, data, len); + psMd5Final(&md5, ihash); + + psMd5Init(&md5); + psMd5Update(&md5, key, MD5_HASH_SIZE); + psMd5Update(&md5, pad2, 48); + psMd5Update(&md5, ihash, MD5_HASH_SIZE); + psMd5Final(&md5, mac); + +/* + Increment sequence number +*/ + for (i = 7; i >= 0; i--) { + seq[i]++; + if (seq[i] != 0) { + break; + } + } + return MD5_HASH_SIZE; +} + +#endif /* USE_MD5_MAC */ + +#endif /* DISABLE_SSLV3 */ +/******************************************************************************/ + + diff --git a/matrixssl/test/Makefile b/matrixssl/test/Makefile new file mode 100755 index 0000000..21d304f --- /dev/null +++ b/matrixssl/test/Makefile @@ -0,0 +1,56 @@ +# +# Makefile for MatrixSSL testing +# +# Copyright (c) 2013-2016 INSIDE Secure Corporation. All Rights Reserved. +# + +MATRIXSSL_ROOT:=../.. +TEST_SRC:=sslTest.c +CERT_SRC:=certValidate.c +SRC:=$(TEST_SRC) $(CERT_SRC) + +include $(MATRIXSSL_ROOT)/common.mk + +# Generated files +CERT_EXE:=certValidate$(E) +TEST_EXE:=sslTest$(E) + +# Linked files +STATIC:=../libssl_s.a $(MATRIXSSL_ROOT)/crypto/libcrypt_s.a $(MATRIXSSL_ROOT)/core/libcore_s.a + + +# Generate map file with sections and C source reference for sslTest +ifndef MATRIX_DEBUG +ifeq (,$(findstring -apple,$(CCARCH))) +LDFLAGS += \ + -Wl,--cref \ + -Wl,-s \ + -Wl,-Map="$@.map" +endif +endif + + +all: compile + +compile: $(OBJS) $(CERT_EXE) $(TEST_EXE) + +# Additional Dependencies +$(OBJS): $(MATRIXSSL_ROOT)/common.mk Makefile $(wildcard *.h) + +$(TEST_EXE): $(TEST_SRC:.c=.o) $(STATIC) + $(CC) -o $@ $^ $(LDFLAGS) + +$(CERT_EXE):$(CERT_SRC:.c=.o) $(STATIC) + $(CC) -o $@ $^ $(LDFLAGS) + +ifneq (,$(findstring -octeon,$(CCARCH))) + SIM:=oct-sim + SIMFLAGS:=-quiet -numcores=1 -noperf +endif + +test: + $(SIM) ./$(TEST_EXE) $(SIMFLAGS) + +clean: + rm -f $(TEST_EXE) $(CERT_EXE) $(OBJS) + diff --git a/matrixssl/test/certValidate.c b/matrixssl/test/certValidate.c new file mode 100644 index 0000000..af6a401 --- /dev/null +++ b/matrixssl/test/certValidate.c @@ -0,0 +1,245 @@ +/** + * @file certValidate.c + * @version $Format:%h%d$ + * + * Standalone certificate parsing and chain validation test. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "matrixssl/matrixsslApi.h" + +/****************************** Local Functions *******************************/ + +#if ((!defined USE_ONLY_PSK_CIPHER_SUITE) && (defined MATRIX_USE_FILE_SYSTEM)) + +static void usage(void) +{ + printf("usage: certValidate \n" + " PEM file containing one or more trusted root certs\n" + " If specified as NULL, no root certs will be loaded\n" + " PEM file containing cert chain to validate\n" + " Name (usually DNS name) to match to certchain subject\n" + " If specified as NULL, subject will not be validated\n" +); +} + +static char *flagstostr(int flags) +{ + static char f[80]; /* Not reentrant, but good enough for this test */ + char *s = f; + + if (flags) { + s += sprintf(s, " ("); + if (flags & PS_CERT_AUTH_FAIL_KEY_USAGE_FLAG) { + s += sprintf(s, "KEY_USAGE "); + } + if (flags & PS_CERT_AUTH_FAIL_EKU_FLAG) { + s += sprintf(s, "EXTENDED_KEY_USAGE "); + } + if (flags & PS_CERT_AUTH_FAIL_SUBJECT_FLAG) { + s += sprintf(s, "SUBJECT "); + } + if (flags & PS_CERT_AUTH_FAIL_DATE_FLAG) { + s += sprintf(s, "DATE "); + } + s += sprintf(s, ")"); + return f; + } + return ""; +} + +static char *errtostr(int rc) +{ + static char e[80]; /* Not reentrant, but good enough for this test */ + + switch (rc) { + case 0: + case PS_CERT_AUTH_PASS: + return "PASS"; + break; + case PS_CERT_AUTH_FAIL_BC: + return "FAIL Basic Constraints"; + break; + case PS_CERT_AUTH_FAIL_DN: + return "FAIL Distinguished Name Match"; + break; + case PS_CERT_AUTH_FAIL_SIG: + return "FAIL Signature Validation"; + break; + case PS_CERT_AUTH_FAIL_REVOKED: + return "FAIL Certificate Revoked"; + break; + case PS_CERT_AUTH_FAIL: + return "FAIL Authentication Fail"; + break; + case PS_CERT_AUTH_FAIL_EXTENSION: + return "FAIL Extension"; + break; + case PS_CERT_AUTH_FAIL_PATH_LEN: + return "FAIL Path Length"; + break; + case PS_CERT_AUTH_FAIL_AUTHKEY: + return "FAIL Auth Key / Subject Key Match"; + break; + default: + sprintf(e, "FAIL %d", rc); + return e; + } +} + +/******************************************************************************/ +/* + Certificate validation test + */ +int32 main(int32 argc, char **argv) +{ + psX509Cert_t *trusted, *chain, *cert; + psPool_t *pool; + int32 rc, i; + uint32 faildate, flags, depth; + + rc = -1; + faildate = 0; + pool = NULL; + trusted = chain = NULL; + + if (argc != 4) { + usage(); + return -1; + } + + if ((rc = matrixSslOpen()) < 0) { + _psTrace("MatrixSSL library init failure. Exiting\n"); + return rc; + } + + if (strcmp(argv[1], "NULL") != 0) { + if ((rc = psX509ParseCertFile(pool, argv[1], &trusted, 0)) < 0) { + if (rc == PS_PLATFORM_FAIL) { + printf("FAIL open file %s %d\n", argv[1], rc); + } else { + printf("FAIL parse %s %d\n", argv[1], rc); + } + goto L_EXIT; + } + printf(" Loaded root file %s\n", argv[1]); + for (cert = trusted, i = 0; cert != NULL; cert = cert->next, i++) { + printf(" [%d]:%s\n", i, cert->subject.commonName); + psAssert(cert->authStatus == 0); + faildate |= cert->authFailFlags & PS_CERT_AUTH_FAIL_DATE_FLAG; + psAssert((cert->authFailFlags & ~faildate) == 0); + } + } + + if ((rc = psX509ParseCertFile(pool, argv[2], &chain, 0)) < 0) { + if (rc == PS_PLATFORM_FAIL) { + printf("FAIL open file %s %d\n", argv[2], rc); + } else { + printf("FAIL parse %s %d\n", argv[2], rc); + } + goto L_EXIT; + } + printf(" Loaded chain file %s\n", argv[2]); + for (cert = chain, i = 0; cert != NULL; cert = cert->next, i++) { + printf(" [%d]:%s\n", i, cert->subject.commonName); + psAssert(cert->authStatus == 0); + faildate |= cert->authFailFlags & PS_CERT_AUTH_FAIL_DATE_FLAG; + psAssert((cert->authFailFlags & ~faildate) == 0); + } + + if (strcmp(argv[3], "NULL") != 0) { + if (psX509ValidateGeneralName(argv[3]) < 0) { + printf("FAIL validate general name %s\n", argv[3]); + goto L_EXIT; + } + rc = matrixValidateCerts(pool, chain, trusted, argv[3], &cert, NULL, + NULL); + } else { + printf("WARN subject not validated\n"); + rc = matrixValidateCerts(pool, chain, trusted, NULL, &cert, NULL, NULL); + } + if (rc < 0) { + printf("%s\n", errtostr(rc)); + for (cert = chain, i = 0; cert != NULL; cert = cert->next, i++) { + printf(" Validate:%s[%d]:%s FAIL %d, status=%d, flags=%u\n", + argv[2], i, cert->subject.commonName, rc, + cert->authStatus, cert->authFailFlags); + if (cert->authStatus != PS_CERT_AUTH_PASS) { + printf(" authStatus %s\n", errtostr(cert->authStatus)); + } + if (cert->authFailFlags) { + printf(" authFailFlags %s\n", flagstostr(cert->authFailFlags)); + } + } + goto L_EXIT; + } + /* If faildate is set and we don't have an error in rc... */ + psAssert(faildate == 0); + + flags = depth = 0; + printf(" Validate %s:%s rc %d\n", argv[2], cert->subject.commonName, rc); + for (cert = chain, i = 0; cert != NULL; cert = cert->next, i++) { + printf(" [%d] authStatus=%d, authFailFlags=%u\n", + i, cert->authStatus, cert->authFailFlags); + if (cert->authStatus != PS_CERT_AUTH_PASS) { + depth = i; + rc = cert->authStatus; + flags |= cert->authFailFlags; + } else { + psAssert(cert->authFailFlags == 0); + } + } + if (rc < 0) { + printf("%s%s in %s[%d]\n", errtostr(rc), flagstostr(flags), + argv[2], depth); + goto L_EXIT; + } + printf("PASS\n"); + rc = 0; + +L_EXIT: + if (trusted) psX509FreeCert(trusted); + if (chain) psX509FreeCert(chain); + matrixSslClose(); + + return rc; +} + +#else + +int32 main(int32 argc, char **argv) +{ + printf("Not applicable when USE_ONLY_PSK_CIPHER_SUITE defined\n"); + return 0; +} + +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ + +/******************************************************************************/ + diff --git a/matrixssl/test/sslTest.c b/matrixssl/test/sslTest.c new file mode 100644 index 0000000..b50ea4f --- /dev/null +++ b/matrixssl/test/sslTest.c @@ -0,0 +1,2250 @@ +/** + * @file sslTest_nonfips.c + * @version $Format:%h%d$ + * + * Self-test of the MatrixSSL handshake protocol and encrypted data exchange.. + * Each enabled cipher suite is run through all configured SSL handshake paths + * This version of the test is for native crypto library. + */ +/* + * Copyright (c) 2014-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "matrixssl/matrixsslApi.h" + +#ifdef USE_PSK_CIPHER_SUITE +#include "testkeys/PSK/psk.h" +#endif /* USE_PSK_CIPHER_SUITE */ + +/* + This test application can also run in a mode that measures the time of + SSL connections. If USE_HIGHRES time is disabled the granularity is + milliseconds so most non-embedded platforms will report 0 msecs/conn for + most stats. + + Standard handshakes and client-auth handshakes (commercial only) are timed + for each enabled cipher suite. The other handshake types will still run + but will not be timed +*/ +//#define ENABLE_PERF_TIMING + +#if !defined(POSIX) && !defined(WIN32) +#define EMBEDDED +#endif + +#ifndef EMBEDDED + #define DELIM "\t" + #if defined(__x86_64__) && defined(ENABLE_PERF_TIMING) + #define CONN_ITER 10 /* number of connections per type of hs */ + #elif defined(__arm__) && defined(ENABLE_PERF_TIMING) + #define CONN_ITER 2 /* number of connections per type of hs */ + #else + #define CONN_ITER 1 /* number of connections per type of hs */ + #endif +#else + #define DELIM "," + #define CONN_ITER 1 /* number of connections per type of hs */ +#endif + +#define CLI_APP_DATA 128 +#define SVR_APP_DATA 2048 + +#define THROUGHPUT_NREC 100 +#define THROUGHPUT_RECSIZE SSL_MAX_PLAINTEXT_LEN + +#define BYTES_PER_MB 1048576 +#ifdef ENABLE_PERF_TIMING +#define testTrace(x) +#ifdef USE_HIGHRES_TIME +#define psDiffMsecs(A, B, C) psDiffUsecs(A, B) +#define TIME_UNITS "usecs/connection\n" +#define TIME_SCALE 1000000 +#else /* !USE_HIGHRES_TIME */ +#define TIME_UNITS "msecs/connection\n" +#define TIME_SCALE 1000 +#endif /* USE_HIGHRES_TIME */ +#else /* !ENABLE_PERF_TIMING */ +#define testTrace(x) _psTrace(x) +#endif /* ENABLE_PERF_TIMING */ +#define CPS(A) ((A) != 0 ? (TIME_SCALE/(A)): 0) +#define MBS(A) ((A) != 0 ? (uint32_t)(((uint64_t)THROUGHPUT_NREC * THROUGHPUT_RECSIZE * TIME_SCALE / BYTES_PER_MB) / (A)) : 0) + +#ifdef USE_MATRIXSSL_STATS +static void statCback(void *ssl, void *stat_ptr, int32 type, int32 value); +#endif + +//#define TEST_RESUMPTIONS_WITH_SESSION_TICKETS + +/******************************************************************************/ +/* + Must define in matrixConfig.h: + USE_SERVER_SIDE_SSL + USE_CLIENT_SIDE_SSL + USE_CLIENT_AUTH (commercial only) +*/ +#if !defined(USE_SERVER_SIDE_SSL) || !defined(USE_CLIENT_SIDE_SSL) +#warning "Must enable both USE_SERVER_SIDE_SSL and USE_CLIENT_SIDE_SSL to run" +#endif + +#ifdef USE_ONLY_PSK_CIPHER_SUITE + #ifdef USE_CLIENT_AUTH + #error "Disable client auth if using only PSK ciphers" + #endif +#endif + +typedef struct { + ssl_t *ssl; + sslKeys_t *keys; +#ifdef ENABLE_PERF_TIMING + uint32 hsTime; + uint32 appTime; +#endif +} sslConn_t; + +enum { + TLS_TEST_SKIP = 1, + TLS_TEST_PASS, + TLS_TEST_FAIL, +}; + +enum { + STANDARD_HANDSHAKE, + RE_HANDSHAKE_TEST_CLIENT_INITIATED, + RESUMED_HANDSHAKE_TEST_NEW_CONNECTION, + RE_HANDSHAKE_TEST_SERVER_INITIATED, + RESUMED_RE_HANDSHAKE_TEST_CLIENT_INITIATED, + SECOND_PASS_RESUMED_RE_HANDSHAKE_TEST, + RESUMED_RE_HANDSHAKE_TEST_SERVER_INITIATED, + UPGRADE_CERT_CALLBACK_RE_HANDSHAKE, + UPGRADE_KEYS_RE_HANDSHAKE, + CHANGE_CIPHER_SUITE_RE_HANDSHAKE_TEST, + STANDARD_CLIENT_AUTH_HANDSHAKE, + RESUMED_CLIENT_AUTH_HANDSHAKE, + REHANDSHAKE_ADDING_CLIENT_AUTHENTICATION_TEST +}; + +typedef struct { + uint32_t c_hs; + uint32_t s_hs; + uint32_t c_rhs; + uint32_t s_rhs; + uint32_t c_resume; + uint32_t s_resume; + uint32_t c_cauth; + uint32_t s_cauth; + uint32_t c_app; + uint32_t s_app; + uint16_t keysize; /* Pubkey size for key exchange */ + uint16_t authsize; /* Pubkey size for auth */ + uint8_t cid; /* Array index of testCipherSpec_t */ + uint8_t ver; /* TLS version */ +} testResult_t; + +#ifdef ENABLE_PERF_TIMING +static testResult_t g_results[4 * 3 * 48]; /* 4 versions, 3 keysizes, 48 ciphers */ +#endif + +typedef struct { + const char name[64]; + uint16_t id; +} testCipherSpec_t; + +#ifndef USE_ONLY_PSK_CIPHER_SUITE +static sslSessionId_t *clientSessionId; +#endif + +/******************************************************************************/ +/* + Key loading. The header files are a bit easier to work with because + it is better to get a compile error that a header isn't found rather + than a run-time error that a .pem file isn't found +*/ +#define USE_HEADER_KEYS /* comment out this line to test with .pem files */ + +#if defined(MATRIX_USE_FILE_SYSTEM) && !defined(USE_HEADER_KEYS) +#ifdef USE_RSA +static char svrKeyFile[] = "../../testkeys/RSA/1024_RSA_KEY.pem"; +static char svrCertFile[] = "../../testkeys/RSA/1024_RSA.pem"; +static char svrCAfile[] = "../../testkeys/RSA/1024_RSA_CA.pem"; +static char clnCAfile[] = "../../testkeys/RSA/2048_RSA_CA.pem"; +static char clnKeyFile[] = "../../testkeys/RSA/2048_RSA_KEY.pem"; +static char clnCertFile[] = "../../testkeys/RSA/2048_RSA.pem"; +#endif /* USE_RSA */ +#ifdef USE_ECC +static char svrEcKeyFile[] = "../../testkeys/EC/192_EC_KEY.pem"; +static char svrEcCertFile[] = "../../testkeys/EC/192_EC.pem"; +static char svrEcCAfile[] = "../../testkeys/EC/192_EC_CA.pem"; +static char clnEcKeyFile[] = "../../testkeys/EC/224_EC_KEY.pem"; +static char clnEcCertFile[] = "../../testkeys/EC/224_EC.pem"; +static char clnEcCAfile[] = "../../testkeys/EC/224_EC_CA.pem"; +/* ECDH_RSA certs */ +static char svrEcRsaKeyFile[] = "../../testkeys/ECDH_RSA/192_ECDH-RSA_KEY.pem"; +static char svrEcRsaCertFile[] = "../../testkeys/ECDH_RSA/192_ECDH-RSA.pem"; +static char svrEcRsaCAfile[] = "../../testkeys/ECDH_RSA/1024_ECDH-RSA_CA.pem"; +static char clnEcRsaKeyFile[] = "../../testkeys/ECDH_RSA/256_ECDH-RSA_KEY.pem"; +static char clnEcRsaCertFile[] = "../../testkeys/ECDH_RSA/256_ECDH-RSA.pem"; +static char clnEcRsaCAfile[] = "../../testkeys/ECDH_RSA/2048_ECDH-RSA_CA.pem"; +#endif /* USE_ECC */ +#ifdef REQUIRE_DH_PARAMS +static char dhParamFile[] = "../../testkeys/DH/1024_DH_PARAMS.pem"; +#endif /* REQUIRE_DH_PARAMS */ +#endif /* MATRIX_USE_FILE_SYSTEM && !USE_HEADER_KEYS */ + +#ifdef USE_HEADER_KEYS + +#ifdef USE_RSA +#include "testkeys/RSA/1024_RSA_KEY.h" +#include "testkeys/RSA/1024_RSA.h" +#include "testkeys/RSA/1024_RSA_CA.h" +#include "testkeys/RSA/2048_RSA_KEY.h" +#include "testkeys/RSA/2048_RSA.h" +#include "testkeys/RSA/2048_RSA_CA.h" +#include "testkeys/RSA/4096_RSA_KEY.h" +#include "testkeys/RSA/4096_RSA.h" +#include "testkeys/RSA/4096_RSA_CA.h" +static const unsigned char *RSAKEY, *RSACERT, *RSACA; +static uint32_t RSAKEY_SIZE, RSA_SIZE, RSACA_SIZE; +#endif /* USE_RSA */ + +#ifdef USE_ECC +#include "testkeys/EC/192_EC_KEY.h" +#include "testkeys/EC/192_EC.h" +#include "testkeys/EC/192_EC_CA.h" +#include "testkeys/EC/224_EC_KEY.h" +#include "testkeys/EC/224_EC.h" +#include "testkeys/EC/224_EC_CA.h" +#include "testkeys/EC/256_EC_KEY.h" +#include "testkeys/EC/256_EC.h" +#include "testkeys/EC/256_EC_CA.h" +#include "testkeys/EC/384_EC_KEY.h" +#include "testkeys/EC/384_EC.h" +#include "testkeys/EC/384_EC_CA.h" +#include "testkeys/EC/521_EC_KEY.h" +#include "testkeys/EC/521_EC.h" +#include "testkeys/EC/521_EC_CA.h" +static const unsigned char *ECCKEY, *ECC, *ECCCA; +static uint32_t ECCKEY_SIZE, ECC_SIZE, ECCCA_SIZE; + +#include "testkeys/ECDH_RSA/256_ECDH-RSA_KEY.h" +#include "testkeys/ECDH_RSA/256_ECDH-RSA.h" +#include "testkeys/ECDH_RSA/1024_ECDH-RSA_CA.h" +#include "testkeys/ECDH_RSA/521_ECDH-RSA_KEY.h" +#include "testkeys/ECDH_RSA/521_ECDH-RSA.h" +#include "testkeys/ECDH_RSA/2048_ECDH-RSA_CA.h" +static uint32_t ECDHRSA_SIZE; +#endif /* USE_ECC */ + +#ifdef REQUIRE_DH_PARAMS +#include "testkeys/DH/1024_DH_PARAMS.h" +#include "testkeys/DH/2048_DH_PARAMS.h" +#include "testkeys/DH/4096_DH_PARAMS.h" +static const unsigned char *DHPARAM; +static uint32_t DH_SIZE; +#endif /* REQUIRE_DH_PARAMS */ + +#endif /* USE_HEADER_KEYS */ + +/******************************************************************************/ + +int sslTest(void); + +static void freeSessionAndConnection(sslConn_t *cpp); + +static int32 initializeServer(sslConn_t *svrConn, uint16_t cipher); +static int32 initializeClient(sslConn_t *clnConn, uint16_t cipher, + sslSessionId_t *sid); + +static int32 initializeHandshake(sslConn_t *clnConn, sslConn_t *svrConn, + uint16_t cipherSuite, + sslSessionId_t *sid); + +static int32 initializeResumedHandshake(sslConn_t *clnConn, sslConn_t *svrConn, + uint16_t cipherSuite); + +#ifdef SSL_REHANDSHAKES_ENABLED +static int32 initializeReHandshake(sslConn_t *clnConn, sslConn_t *svrConn, + uint16_t cipherSuite); + +static int32 initializeResumedReHandshake(sslConn_t *clnConn, + sslConn_t *svrConn, uint16_t cipherSuite); +static int32 initializeServerInitiatedReHandshake(sslConn_t *clnConn, + sslConn_t *svrConn, uint16_t cipherSuite); +static int32 initializeServerInitiatedResumedReHandshake(sslConn_t *clnConn, + sslConn_t *svrConn, uint16_t cipherSuite); +static int32 initializeUpgradeCertCbackReHandshake(sslConn_t *clnConn, + sslConn_t *svrConn, uint16_t cipherSuite); +static int32 initializeUpgradeKeysReHandshake(sslConn_t *clnConn, + sslConn_t *svrConn, uint16_t cipherSuite); +static int32 initializeChangeCipherReHandshake(sslConn_t *clnConn, + sslConn_t *svrConn, uint16_t cipherSuite); +#ifdef USE_CLIENT_AUTH +static int32 initializeReHandshakeClientAuth(sslConn_t *clnConn, + sslConn_t *svrConn, uint16_t cipherSuite); +#endif /* USE_CLIENT_AUTH */ +#endif /* SSL_REHANDSHAKES_ENABLED */ + +#ifdef USE_CLIENT_AUTH +static int32 initializeClientAuthHandshake(sslConn_t *clnConn, + sslConn_t *svrConn, uint16_t cipherSuite, + sslSessionId_t *sid); +#endif /* USE_CLIENT_AUTH */ + +static int32 performHandshake(sslConn_t *sendingSide, sslConn_t *receivingSide); +static int32 exchangeAppData(sslConn_t *sendingSide, sslConn_t *receivingSide, uint32_t bytes); +#ifdef ENABLE_PERF_TIMING +static int32_t throughputTest(sslConn_t *s, sslConn_t *r, uint16_t nrec, uint16_t reclen); +static void print_throughput(void); +#endif + +/* + Client-authentication. Callback that is registered to receive client + certificate information for custom validation +*/ +static int32 clnCertChecker(ssl_t *ssl, psX509Cert_t *cert, int32 alert); + +#ifdef SSL_REHANDSHAKES_ENABLED +static int32 clnCertCheckerUpdate(ssl_t *ssl, psX509Cert_t *cert, int32 alert); +#endif + +#ifdef USE_CLIENT_AUTH +static int32 svrCertChecker(ssl_t *ssl, psX509Cert_t *cert, int32 alert); +#endif /* USE_CLIENT_AUTH */ + +/******************************************************************************/ + +static uint32_t g_versionFlag= 0; + +/* Protocol versions to test for each suite */ +const static uint32_t g_versions[] = { +#if defined(USE_TLS_1_2) + SSL_FLAGS_TLS_1_2, +#endif +#if defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1) + SSL_FLAGS_TLS_1_1, +#endif +#if defined(USE_TLS) && !defined(DISABLE_TLS_1_0) + SSL_FLAGS_TLS_1_0, +#endif +#if !defined(DISABLE_SSLV3) + SSL_FLAGS_SSLV3, +#endif +#if defined(USE_DTLS) && defined(USE_TLS_1_2) + SSL_FLAGS_TLS_1_2 | SSL_FLAGS_DTLS, +#endif +#if defined(USE_DTLS) && defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1) + SSL_FLAGS_TLS_1_1 | SSL_FLAGS_DTLS, +#endif + 0 /* 0 Must be last to terminate list */ +}; + +#ifdef ENABLE_PERF_TIMING +const static char *g_version_str[] = { +#if defined(USE_TLS_1_2) + "TLS 1.2", +#endif +#if defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1) + "TLS 1.1", +#endif +#if defined(USE_TLS) && !defined(DISABLE_TLS_1_0) + "TLS 1.0", +#endif +#if !defined(DISABLE_SSLV3) + "SSL 3.0", +#endif +#if defined(USE_TLS) && defined(USE_TLS_1_2) + "DTLS 1.2", +#endif +#if defined(USE_DTLS) && defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1) + "DTLS 1.0", /* There is no DTLS 1.1 */ +#endif + 0 /* 0 Must be last to terminate list */ +}; +#endif + +/* Ciphersuites to test */ + +#define CS(A) { #A, A } + +const static testCipherSpec_t ciphers[] = { + +/* RSA */ +#ifdef USE_TLS_RSA_WITH_AES_128_CBC_SHA + CS(TLS_RSA_WITH_AES_128_CBC_SHA), +#endif + +#ifdef USE_TLS_RSA_WITH_AES_256_CBC_SHA + CS(TLS_RSA_WITH_AES_256_CBC_SHA), +#endif + +#ifdef USE_TLS_RSA_WITH_AES_128_CBC_SHA256 + CS(TLS_RSA_WITH_AES_128_CBC_SHA256), +#endif + +#ifdef USE_TLS_RSA_WITH_AES_256_CBC_SHA256 + CS(TLS_RSA_WITH_AES_256_CBC_SHA256), +#endif + +#ifdef USE_TLS_RSA_WITH_AES_128_GCM_SHA256 + CS(TLS_RSA_WITH_AES_128_GCM_SHA256), +#endif + +#ifdef USE_TLS_RSA_WITH_AES_256_GCM_SHA384 + CS(TLS_RSA_WITH_AES_256_GCM_SHA384), +#endif + +#ifdef USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA + CS(SSL_RSA_WITH_3DES_EDE_CBC_SHA), +#endif + +/* ECDHE-ECDSA */ + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA), +#endif + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + CS(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA), +#endif + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256), +#endif + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + CS(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384), +#endif + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + CS(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), +#endif + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + CS(TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), +#endif + +#ifdef USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + CS(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), +#endif + +/* ECDH-ECDSA */ + +#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + CS(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256), +#endif + +#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + CS(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384), +#endif + +#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + CS(TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256), +#endif + +#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + CS(TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384), +#endif + +#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + CS(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA), +#endif + +#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + CS(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA), +#endif + +/* ECDHE-RSA */ + +#ifdef USE_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + CS(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), +#endif + +#ifdef USE_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + CS(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384), +#endif + +#ifdef USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + CS(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), +#endif + +#ifdef USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + CS(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256), +#endif + +#ifdef USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + CS(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384), +#endif + +#ifdef USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + CS(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA), +#endif + +#ifdef USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + CS(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA), +#endif + +#ifdef USE_TLS_ECDHE_RSA_WITH_3DES_EDE_SHA + CS(TLS_ECDHE_RSA_WITH_3DES_EDE_SHA), +#endif + +/* ECDH-RSA */ + +#ifdef USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + CS(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256), +#endif + +#ifdef USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + CS(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384), +#endif + +#ifdef USE_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + CS(TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256), +#endif + +#ifdef USE_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + CS(TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384), +#endif + +#ifdef USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + CS(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA), +#endif + +#ifdef USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + CS(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA), +#endif + +/* DHE-RSA */ + +#ifdef USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA), +#endif + +#ifdef USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA), +#endif + +#ifdef USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256), +#endif + +#ifdef USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256), +#endif + +#ifdef USE_SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA + CS(SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA), +#endif + +/* PSK */ + +#ifdef USE_TLS_PSK_WITH_AES_128_CBC_SHA + CS(TLS_PSK_WITH_AES_128_CBC_SHA), +#endif + +#ifdef USE_TLS_PSK_WITH_AES_256_CBC_SHA + CS(TLS_PSK_WITH_AES_256_CBC_SHA), +#endif + +#ifdef USE_TLS_PSK_WITH_AES_128_CBC_SHA256 + CS(TLS_PSK_WITH_AES_128_CBC_SHA256), +#endif + +#ifdef USE_TLS_PSK_WITH_AES_256_CBC_SHA384 + CS(TLS_PSK_WITH_AES_256_CBC_SHA384), +#endif + +/* DHE-PSK */ + +#ifdef USE_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + CS(TLS_DHE_PSK_WITH_AES_128_CBC_SHA), +#endif + +#ifdef USE_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + CS(TLS_DHE_PSK_WITH_AES_256_CBC_SHA), +#endif + +/* Deprecated / Weak ciphers */ + +#ifdef USE_SSL_RSA_WITH_RC4_128_SHA + CS(SSL_RSA_WITH_RC4_128_SHA), +#endif + +#ifdef USE_SSL_RSA_WITH_RC4_128_MD5 + CS(SSL_RSA_WITH_RC4_128_MD5), +#endif + +#ifdef USE_TLS_RSA_WITH_SEED_CBC_SHA + CS(TLS_RSA_WITH_SEED_CBC_SHA), +#endif + +#ifdef USE_TLS_RSA_WITH_IDEA_CBC_SHA + CS(TLS_RSA_WITH_IDEA_CBC_SHA), +#endif + +/* DH-anon */ + +#ifdef USE_TLS_DH_anon_WITH_AES_128_CBC_SHA + CS(TLS_DH_anon_WITH_AES_128_CBC_SHA), +#endif + +#ifdef USE_TLS_DH_anon_WITH_AES_256_CBC_SHA + CS(TLS_DH_anon_WITH_AES_256_CBC_SHA), +#endif + +#ifdef USE_SSL_DH_anon_WITH_3DES_EDE_CBC_SHA + CS(SSL_DH_anon_WITH_3DES_EDE_CBC_SHA), +#endif + +#ifdef USE_SSL_DH_anon_WITH_RC4_128_MD5 + CS(SSL_DH_anon_WITH_RC4_128_MD5), +#endif + +/* RSA-NULL */ + +#ifdef USE_SSL_RSA_WITH_NULL_SHA + CS(SSL_RSA_WITH_NULL_SHA), +#endif + +#ifdef USE_SSL_RSA_WITH_NULL_MD5 + CS(SSL_RSA_WITH_NULL_MD5), +#endif + + {"NULL", 0} /* must be last */ +}; + +#ifdef SSL_REHANDSHAKES_ENABLED +static const char *cipher_name(uint16_t cid) +{ + int id; + for (id = 0; ciphers[id].id > 0; id++) { + if (ciphers[id].id == cid) { + break; + } + } + return ciphers[id].name; +} +#endif /* !SSL_REHANDSHAKES_ENABLED */ + +/******************************************************************************/ +/* + This test application will exercise the SSL/TLS handshake and app + data exchange for every eligible cipher. +*/ + +#ifndef EMBEDDED +int main(int argc, char **argv) +{ + return sslTest(); +} +#endif + +int sslTest(void) +{ + sslConn_t *svrConn, *clnConn; + const sslCipherSpec_t *spec; + uint8_t id, v; + uint16_t keysize = 0, authsize = 0; +#ifdef ENABLE_PERF_TIMING + int32 perfIter; + uint32 clnTime, svrTime; + testResult_t *result = g_results; +#endif /* ENABLE_PERF_TIMING */ + + + if (matrixSslOpen() < 0) { + fprintf(stderr, "matrixSslOpen failed, exiting...\n"); + return -1; + } + + + svrConn = psMalloc(MATRIX_NO_POOL, sizeof(sslConn_t)); + clnConn = psMalloc(MATRIX_NO_POOL, sizeof(sslConn_t)); + memset(svrConn, 0, sizeof(sslConn_t)); + memset(clnConn, 0, sizeof(sslConn_t)); + +#ifdef USE_RSA + RSA_SIZE = 0; +#endif +#ifdef USE_ECC + ECC_SIZE = ECDHRSA_SIZE = 0; +#endif +#ifdef REQUIRE_DH_PARAMS + DH_SIZE = 0; +#endif + for (id = 0; ciphers[id].id > 0; id++) { + + if ((spec = sslGetDefinedCipherSpec(ciphers[id].id)) == NULL) { + _psTrace(" FAILED: cipher spec lookup\n"); + goto LBL_FREE; + } + keysize = authsize = 0; +#ifdef USE_RSA +L_NEXT_RSA: + if (spec->type == CS_RSA) { + switch (RSA_SIZE) { + case 0: + RSAKEY = RSA1024KEY; RSAKEY_SIZE = RSA1024KEY_SIZE; + RSACERT = RSA1024; RSA_SIZE = RSA1024_SIZE; + RSACA = RSA1024CA; RSACA_SIZE = RSA1024CA_SIZE; + keysize = authsize = 1024; + break; + case RSA1024_SIZE: + RSAKEY = RSA2048KEY; RSAKEY_SIZE = RSA2048KEY_SIZE; + RSACERT = RSA2048; RSA_SIZE = RSA2048_SIZE; + RSACA = RSA2048CA; RSACA_SIZE = RSA2048CA_SIZE; + keysize = authsize = 2048; + break; + case RSA2048_SIZE: +#ifndef EMBEDDED + RSAKEY = RSA4096KEY; RSAKEY_SIZE = RSA4096KEY_SIZE; + RSACERT = RSA4096; RSA_SIZE = RSA4096_SIZE; + RSACA = RSA4096CA; RSACA_SIZE = RSA4096CA_SIZE; + keysize = authsize = 4096; + break; + case RSA4096_SIZE: +#endif + RSA_SIZE = 0; + break; + } + if (RSA_SIZE == 0) { + continue; /* Next cipher suite */ + } + } + /* For other ciphersuites that use RSA for auth only, default to 1024 */ + if (spec->type == CS_DHE_RSA || + spec->type == CS_ECDH_RSA || spec->type == CS_ECDHE_RSA) { + RSAKEY = RSA1024KEY; RSAKEY_SIZE = RSA1024KEY_SIZE; + RSACERT = RSA1024; RSA_SIZE = RSA1024_SIZE; + RSACA = RSA1024CA; RSACA_SIZE = RSA1024CA_SIZE; + authsize = 1024; +#ifdef USE_ECC + ECCKEY = EC256KEY; ECCKEY_SIZE = EC256KEY_SIZE; + ECC = EC256; ECC_SIZE = EC256_SIZE; + ECCCA = EC256CA; ECCCA_SIZE = EC256CA_SIZE; + keysize = 256; +#endif + } +#endif /* USE_RSA */ + +#ifdef USE_ECC +L_NEXT_ECC: + if (spec->type == CS_ECDH_ECDSA || spec->type == CS_ECDHE_ECDSA) { + switch (ECC_SIZE) { + case 0: + ECCKEY = EC192KEY; ECCKEY_SIZE = EC192KEY_SIZE; + ECC = EC192; ECC_SIZE = EC192_SIZE; + ECCCA = EC192CA; ECCCA_SIZE = EC192CA_SIZE; + keysize = authsize = 192; + break; + case EC192_SIZE: + ECCKEY = EC224KEY; ECCKEY_SIZE = EC224KEY_SIZE; + ECC = EC224; ECC_SIZE = EC224_SIZE; + ECCCA = EC224CA; ECCCA_SIZE = EC224CA_SIZE; + keysize = authsize = 224; + break; + case EC224_SIZE: + ECCKEY = EC256KEY; ECCKEY_SIZE = EC256KEY_SIZE; + ECC = EC256; ECC_SIZE = EC256_SIZE; + ECCCA = EC256CA; ECCCA_SIZE = EC256CA_SIZE; + keysize = authsize = 256; + break; + case EC256_SIZE: +#ifndef EMBEDDED + ECCKEY = EC384KEY; ECCKEY_SIZE = EC384KEY_SIZE; + ECC = EC384; ECC_SIZE = EC384_SIZE; + ECCCA = EC384CA; ECCCA_SIZE = EC384CA_SIZE; + keysize = authsize = 384; + break; + case EC384_SIZE: + ECCKEY = EC521KEY; ECCKEY_SIZE = EC521KEY_SIZE; + ECC = EC521; ECC_SIZE = EC521_SIZE; + ECCCA = EC521CA; ECCCA_SIZE = EC521CA_SIZE; + keysize = authsize = 521; + break; + case EC521_SIZE: +#endif + ECC_SIZE = 0; + break; + } + if (ECC_SIZE == 0) { + continue; /* Next cipher suite */ + } + } +#endif /* USE_ECC */ + +#ifdef REQUIRE_DH_PARAMS +L_NEXT_DH: + if (spec->type == CS_DHE_RSA || spec->type == CS_DHE_PSK) { + switch (DH_SIZE) { + case 0: + DHPARAM = DHPARAM1024; DH_SIZE = DHPARAM1024_SIZE; + keysize = 1024; + break; + case DHPARAM1024_SIZE: + DHPARAM = DHPARAM2048; DH_SIZE = DHPARAM2048_SIZE; + keysize = 2048; + break; + case DHPARAM2048_SIZE: +#ifndef EMBEDDED + DHPARAM = DHPARAM4096; DH_SIZE = DHPARAM4096_SIZE; + keysize = 4096; + break; + case DHPARAM4096_SIZE: +#endif + DH_SIZE = 0; + break; + } + if (DH_SIZE == 0) { + continue; /* Next cipher suite */ + } + } +#endif +#ifdef USE_PSK_CIPHER_SUITE + if (spec->type == CS_PSK) { + keysize = authsize = sizeof(PSK_HEADER_TABLE[0].key) * 8; + } + if (spec->type == CS_DHE_PSK) { + authsize = sizeof(PSK_HEADER_TABLE[0].key) * 8; + } +#endif + + /* Loop through each defined version (note: not indented) */ + for (v = 0; g_versions[v] != 0; v++) { + + g_versionFlag = g_versions[v]; + +#ifdef ENABLE_PERF_TIMING + result->keysize = keysize; + result->authsize = authsize; +#endif + /* Some ciphers are not supported in some versions of TLS */ + if (spec->flags & (CRYPTO_FLAGS_SHA2 | CRYPTO_FLAGS_SHA3)) { + if (!(g_versionFlag & SSL_FLAGS_TLS_1_2)) { + _psTraceStr("Skipping %s < TLS 1.2\n\n", (char *)ciphers[id].name); + continue; + } + } else if (spec->flags & CRYPTO_FLAGS_MD5) { + if (g_versionFlag & SSL_FLAGS_TLS_1_2) { + _psTraceStr("Skipping %s TLS 1.2\n\n", (char *)ciphers[id].name); + continue; + } + } +#ifdef USE_LIBSODIUM_AES_GCM + /* Libsodium supports only aes256-gcm, not 128 */ + if ((spec->flags & CRYPTO_FLAGS_AES) && (spec->flags & CRYPTO_FLAGS_GCM)) { + _psTraceStr("Skipping %s libsodium\n\n", (char *)ciphers[id].name); + continue; + } +#endif +#ifndef USE_ONLY_PSK_CIPHER_SUITE + matrixSslNewSessionId(&clientSessionId, NULL); +#endif + switch(g_versions[v]) { + case SSL_FLAGS_SSLV3: + _psTraceStr("Testing %s SSL 3.0 ", (char *)ciphers[id].name); + break; + case SSL_FLAGS_TLS_1_0: + _psTraceStr("Testing %s TLS 1.0 ", (char *)ciphers[id].name); + break; + case SSL_FLAGS_TLS_1_1: + _psTraceStr("Testing %s TLS 1.1 ", (char *)ciphers[id].name); + break; + case SSL_FLAGS_TLS_1_2: + _psTraceStr("Testing %s TLS 1.2 ", (char *)ciphers[id].name); + break; + case SSL_FLAGS_TLS_1_1 | SSL_FLAGS_DTLS: + _psTraceStr("Testing %s DTLS 1.0 ", (char *)ciphers[id].name); + break; + case SSL_FLAGS_TLS_1_2 | SSL_FLAGS_DTLS: + _psTraceStr("Testing %s DTLS 1.2 ", (char *)ciphers[id].name); + break; + } + _psTraceInt("KeySize %hu ", keysize); + _psTraceInt("AuthSize %hu\n", authsize); + + /* Standard Handshake */ + _psTrace(" Standard handshake test\n"); +#ifdef ENABLE_PERF_TIMING +/* + Each matrixSsl call in the handshake is wrapped by a timer. Data + exchange is NOT included in the timer +*/ + result->cid = id; + result->ver = v; + clnTime = svrTime = 0; + _psTraceInt(" %d connections\n", (int32)CONN_ITER); + for (perfIter = 0; perfIter < CONN_ITER; perfIter++) { +#endif /* ENABLE_PERF_TIMING */ +#ifndef USE_ONLY_PSK_CIPHER_SUITE + if (initializeHandshake(clnConn, svrConn, ciphers[id].id, clientSessionId) < 0) { +#else + if (initializeHandshake(clnConn, svrConn, ciphers[id].id, NULL) < 0) { +#endif + _psTrace(" FAILED: initializing Standard handshake\n"); + goto LBL_FREE; + } +#ifdef USE_MATRIXSSL_STATS + matrixSslRegisterStatCallback(clnConn->ssl, statCback, NULL); + matrixSslRegisterStatCallback(svrConn->ssl, statCback, NULL); +#endif + if (performHandshake(clnConn, svrConn) < 0) { + _psTrace(" FAILED: Standard handshake\n"); + goto LBL_FREE; + } else { + testTrace(" PASSED: Standard handshake"); + if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 || + exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) { + _psTrace(" but FAILED to exchange application data\n"); + goto LBL_FREE; + } else { + testTrace("\n"); + } +#ifdef ENABLE_PERF_TIMING + if (throughputTest(clnConn, svrConn, THROUGHPUT_NREC, THROUGHPUT_RECSIZE) < 0) { + _psTrace(" but FAILED throughputTest\n"); + goto LBL_FREE; + } + result->c_app = clnConn->appTime; + result->s_app = svrConn->appTime; +#endif + } + +#ifdef ENABLE_PERF_TIMING + clnTime += clnConn->hsTime; + svrTime += svrConn->hsTime; + /* Have to reset conn for full handshake... except last time through */ + if (perfIter + 1 != CONN_ITER) { + matrixSslDeleteSession(clnConn->ssl); + matrixSslDeleteSession(svrConn->ssl); +#ifndef USE_ONLY_PSK_CIPHER_SUITE + matrixSslClearSessionId(clientSessionId); +#endif + } + } /* iteration loop close */ + result->c_hs = clnTime/CONN_ITER; + result->s_hs = svrTime/CONN_ITER; + _psTraceInt(" CLIENT: %d " TIME_UNITS, (int32)clnTime/CONN_ITER); + _psTraceInt(" SERVER: %d " TIME_UNITS, (int32)svrTime/CONN_ITER); + _psTrace("\n"); +#endif /* ENABLE_PERF_TIMING */ + +#if defined(SSL_REHANDSHAKES_ENABLED) && !defined(USE_ZLIB_COMPRESSION) + /* Re-Handshake (full handshake over existing connection) */ + testTrace(" Re-handshake test (client-initiated)\n"); + if (initializeReHandshake(clnConn, svrConn, ciphers[id].id) < 0) { + _psTrace(" FAILED: initializing Re-handshake\n"); + goto LBL_FREE; + } + if (performHandshake(clnConn, svrConn) < 0) { + _psTrace(" FAILED: Re-handshake\n"); + goto LBL_FREE; + } else { + testTrace(" PASSED: Re-handshake"); + if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 || + exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) { + _psTrace(" but FAILED to exchange application data\n"); + goto LBL_FREE; + } else { + testTrace("\n"); + } + } +#else + _psTrace(" Re-handshake tests are disabled (ENABLE_SECURE_REHANDSHAKES)\n"); +#endif + +#ifndef USE_ONLY_PSK_CIPHER_SUITE + /* Resumed handshake (fast handshake over new connection) */ + testTrace(" Resumed handshake test (new connection)\n"); + if (initializeResumedHandshake(clnConn, svrConn, + ciphers[id].id) < 0) { + _psTrace(" FAILED: initializing Resumed handshake\n"); + goto LBL_FREE; + } + if (performHandshake(clnConn, svrConn) < 0) { + _psTrace(" FAILED: Resumed handshake\n"); + goto LBL_FREE; + } else { + testTrace(" PASSED: Resumed handshake"); + if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 || + exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) { + _psTrace(" but FAILED to exchange application data\n"); + goto LBL_FREE; + } else { + testTrace("\n"); + } + } +#else + _psTrace(" Session resumption tests are disabled (USE_ONLY_PSK_CIPHER_SUITE)\n"); +#endif + +#if defined(SSL_REHANDSHAKES_ENABLED) && !defined(USE_ZLIB_COMPRESSION) +/* + Re-handshake initiated by server (full handshake over existing conn) + Cipher Suite negotiations can get a little fuzzy on the server + initiated rehandshakes based on what is enabled in matrixsslConfig.h + because the client will send the entire cipher suite list. In theory, + the server could disable specific suites to force desired ones but + we're not doing that here so the cipher suite might be changing + underneath us now. +*/ + testTrace(" Re-handshake test (server initiated)\n"); + if (initializeServerInitiatedReHandshake(clnConn, svrConn, + ciphers[id].id) < 0) { + _psTrace(" FAILED: initializing Re-handshake\n"); + goto LBL_FREE; + } + if (performHandshake(svrConn, clnConn) < 0) { + _psTrace(" FAILED: Re-handshake\n"); + goto LBL_FREE; + } else { + if (ciphers[id].id != clnConn->ssl->cipher->ident) { + _psTraceStr(" (new cipher %s)\n", + cipher_name(clnConn->ssl->cipher->ident)); + } + testTrace(" PASSED: Re-handshake"); + if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 || + exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) { + _psTrace(" but FAILED to exchange application data\n"); + goto LBL_FREE; + } else { + testTrace("\n"); + } + } + + /* Testing 6 more re-handshake paths. Add some credits */ + matrixSslAddRehandshakeCredits(svrConn->ssl, 6); + matrixSslAddRehandshakeCredits(clnConn->ssl, 6); +/* + Resumed re-handshake (fast handshake over existing connection) + If the above handshake test did change cipher suites this next test + will not take a resumption path because the client is specifying the + specific cipher which will not match the current. So, we'll run this + test twice to make sure we reset the cipher on the first one and are + sure to hit the resumed re-handshake test on the second. +*/ + testTrace(" Resumed Re-handshake test (client initiated)\n"); + if (initializeResumedReHandshake(clnConn, svrConn, + ciphers[id].id) < 0) { + _psTrace(" FAILED: initializing Resumed Re-handshake\n"); + goto LBL_FREE; + } + if (performHandshake(clnConn, svrConn) < 0) { + _psTrace(" FAILED: Resumed Re-handshake\n"); + goto LBL_FREE; + } else { + testTrace(" PASSED: Resumed Re-handshake"); + if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 || + exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) { + _psTrace(" but FAILED to exchange application data\n"); + goto LBL_FREE; + } else { + testTrace("\n"); + } + } + testTrace(" Second Pass Resumed Re-handshake test\n"); + if (initializeResumedReHandshake(clnConn, svrConn, + ciphers[id].id) < 0) { + _psTrace(" FAILED: initializing Resumed Re-handshake\n"); + goto LBL_FREE; + } + if (performHandshake(clnConn, svrConn) < 0) { + _psTrace(" FAILED: Second Pass Resumed Re-handshake\n"); + goto LBL_FREE; + } else { + testTrace(" PASSED: Second Pass Resumed Re-handshake"); + if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 || + exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) { + _psTrace(" but FAILED to exchange application data\n"); + goto LBL_FREE; + } else { + testTrace("\n"); + } + } + + /* Resumed re-handshake initiated by server (fast handshake over conn) */ + testTrace(" Resumed Re-handshake test (server initiated)\n"); + if (initializeServerInitiatedResumedReHandshake(clnConn, svrConn, + ciphers[id].id) < 0) { + _psTrace(" FAILED: initializing Resumed Re-handshake\n"); + goto LBL_FREE; + } + if (performHandshake(svrConn, clnConn) < 0) { + _psTrace(" FAILED: Resumed Re-handshake\n"); + goto LBL_FREE; + } else { + testTrace(" PASSED: Resumed Re-handshake"); + if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 || + exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) { + _psTrace(" but FAILED to exchange application data\n"); + goto LBL_FREE; + } else { + testTrace("\n"); + } + } + + /* Re-handshaking with "upgraded" parameters */ + testTrace(" Change cert callback Re-handshake test\n"); + if (initializeUpgradeCertCbackReHandshake(clnConn, svrConn, + ciphers[id].id) < 0) { + _psTrace(" FAILED: init upgrade certCback Re-handshake\n"); + goto LBL_FREE; + } + if (performHandshake(clnConn, svrConn) < 0) { + _psTrace(" FAILED: Upgrade cert callback Re-handshake\n"); + goto LBL_FREE; + } else { + testTrace(" PASSED: Upgrade cert callback Re-handshake"); + if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 || + exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) { + _psTrace(" but FAILED to exchange application data\n"); + goto LBL_FREE; + } else { + testTrace("\n"); + } + } + + /* Upgraded keys */ + testTrace(" Change keys Re-handshake test\n"); + if (initializeUpgradeKeysReHandshake(clnConn, svrConn, + ciphers[id].id) < 0) { + _psTrace(" FAILED: init upgrade keys Re-handshake\n"); + goto LBL_FREE; + } + if (performHandshake(clnConn, svrConn) < 0) { + _psTrace(" FAILED: Upgrade keys Re-handshake\n"); + goto LBL_FREE; + } else { + testTrace(" PASSED: Upgrade keys Re-handshake"); + if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 || + exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) { + _psTrace(" but FAILED to exchange application data\n"); + goto LBL_FREE; + } else { + testTrace("\n"); + } + } +/* + Change cipher spec test. Changing to a hardcoded RSA suite so this + will not work on suites that don't have RSA material loaded +*/ + if (spec->type == CS_RSA || spec->type == CS_DHE_RSA || + spec->type == CS_ECDH_RSA || spec->type == CS_ECDHE_RSA) { + testTrace(" Change cipher suite Re-handshake test\n"); + if (initializeChangeCipherReHandshake(clnConn, svrConn, + ciphers[id].id) < 0) { + _psTrace(" FAILED: init change cipher Re-handshake\n"); + goto LBL_FREE; + } + if (performHandshake(clnConn, svrConn) < 0) { + _psTrace(" FAILED: Change cipher suite Re-handshake\n"); + goto LBL_FREE; + } else { + testTrace(" PASSED: Change cipher suite Re-handshake"); + if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 || + exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) { + _psTrace(" but FAILED to exchange application data\n"); + goto LBL_FREE; + } else { + testTrace("\n"); + } + } + } +#endif /* !SSL_REHANDSHAKES_ENABLED */ + +#ifdef USE_CLIENT_AUTH + /* Client Authentication handshakes */ + if (spec->type != CS_PSK && spec->type != CS_DHE_PSK) { + _psTrace(" Standard Client Authentication test\n"); +#ifdef ENABLE_PERF_TIMING + clnTime = svrTime = 0; + _psTraceInt(" %d connections\n", (int32)CONN_ITER); + for (perfIter = 0; perfIter < CONN_ITER; perfIter++) { +#endif /* ENABLE_PERF_TIMING */ + matrixSslClearSessionId(clientSessionId); + if (initializeClientAuthHandshake(clnConn, svrConn, + ciphers[id].id, clientSessionId) < 0) { + _psTrace(" FAILED: initializing Standard Client Auth handshake\n"); + goto LBL_FREE; + } + if (performHandshake(clnConn, svrConn) < 0) { + _psTrace(" FAILED: Standard Client Auth handshake\n"); + goto LBL_FREE; + } else { + testTrace(" PASSED: Standard Client Auth handshake"); + if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 || + exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) { + _psTrace(" but FAILED to exchange application data\n"); + goto LBL_FREE; + } else { + testTrace("\n"); + } + } +#ifdef ENABLE_PERF_TIMING + clnTime += clnConn->hsTime; + svrTime += svrConn->hsTime; + } /* iteration loop */ + result->c_cauth = clnTime/CONN_ITER; + result->s_cauth = svrTime/CONN_ITER; + _psTraceInt(" CLIENT: %d " TIME_UNITS, (int32)clnTime/CONN_ITER); + _psTraceInt(" SERVER: %d " TIME_UNITS, (int32)svrTime/CONN_ITER); + _psTrace("\n==========\n"); +#endif /* ENABLE_PERF_TIMING */ + + + testTrace(" Resumed client authentication test\n"); + if (initializeResumedHandshake(clnConn, svrConn, ciphers[id].id) < 0) { + _psTrace(" FAILED: initializing resumed Client Auth handshake\n"); + goto LBL_FREE; + } + if (performHandshake(clnConn, svrConn) < 0) { + _psTrace(" FAILED: Resumed Client Auth handshake\n"); + goto LBL_FREE; + } else { + testTrace(" PASSED: Resumed Client Auth handshake"); + if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 || + exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) { + _psTrace(" but FAILED to exchange application data\n"); + goto LBL_FREE; + } else { + testTrace("\n"); + } + } +#if defined(SSL_REHANDSHAKES_ENABLED) && !defined(USE_ZLIB_COMPRESSION) + testTrace(" Rehandshake adding client authentication test\n"); + if (initializeReHandshakeClientAuth(clnConn, svrConn, + ciphers[id].id) < 0) { + _psTrace(" FAILED: initializing reshandshke Client Auth handshake\n"); + goto LBL_FREE; + } + /* Must be server initiatated if client auth is being turned on */ + if (performHandshake(svrConn, clnConn) < 0) { + _psTrace(" FAILED: Rehandshake Client Auth handshake\n"); + goto LBL_FREE; + } else { + if (ciphers[id].id != clnConn->ssl->cipher->ident) { + _psTraceStr(" (new cipher %s)\n", + cipher_name(clnConn->ssl->cipher->ident)); + } + testTrace(" PASSED: Rehandshake Client Auth handshake"); + if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 || + exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) { + _psTrace(" but FAILED to exchange application data\n"); + goto LBL_FREE; + } else { + testTrace("\n"); + } + } +#endif /* SSL_REHANDSHAKES_ENABLED */ + } +#endif /* USE_CLIENT_AUTH */ + + freeSessionAndConnection(svrConn); + freeSessionAndConnection(clnConn); +#ifndef USE_ONLY_PSK_CIPHER_SUITE + matrixSslDeleteSessionId(clientSessionId); +#endif +#ifdef ENABLE_PERF_TIMING + result++; +#endif + + continue; /* Next version */ + +LBL_FREE: + _psTrace("EXITING ON ERROR\n"); + freeSessionAndConnection(svrConn); + freeSessionAndConnection(clnConn); +#ifndef USE_ONLY_PSK_CIPHER_SUITE + matrixSslDeleteSessionId(clientSessionId); +#endif + break; + + } /* End version loop (unindented) */ +#ifdef USE_RSA + if (spec->type == CS_RSA) { + goto L_NEXT_RSA; + } +#endif +#ifdef USE_ECC + if (spec->type == CS_ECDH_ECDSA || spec->type == CS_ECDHE_ECDSA) { + goto L_NEXT_ECC; + } +#endif +#ifdef REQUIRE_DH_PARAMS + if (spec->type == CS_DHE_RSA || spec->type == CS_DHE_PSK) { + goto L_NEXT_DH; + } +#endif + + } /* End cipher suite loop */ + +#ifdef ENABLE_PERF_TIMING + printf("Ciphersuite" DELIM "Keysize" DELIM "Authsize" DELIM + "Version" DELIM "CliHS" DELIM "SvrHs" DELIM "CliAHS" DELIM "SvrAHS" DELIM + "MiBs" "\n"); + do { + result--; + printf("%s" DELIM "%hu" DELIM "%hu" DELIM + "%s" DELIM "%u" DELIM "%u" DELIM "%u" DELIM "%u" DELIM + "%u" "\n", + ciphers[result->cid].name, + result->keysize, + result->authsize, + g_version_str[result->ver], + CPS(result->c_hs), CPS(result->s_hs), + CPS(result->c_cauth), CPS(result->s_cauth), + MBS(result->c_app) + ); + } while (result != g_results); + print_throughput(); +#endif + + psFree(svrConn, NULL); + psFree(clnConn, NULL); + matrixSslClose(); + +#ifdef WIN32 + _psTrace("Press any key to close"); + getchar(); +#endif + + return PS_SUCCESS; +} + +static int32 initializeHandshake(sslConn_t *clnConn, sslConn_t *svrConn, + uint16_t cipherSuite, sslSessionId_t *sid) +{ + int32 rc; + + if ((rc = initializeServer(svrConn, cipherSuite)) < 0) { + return rc; + } + return initializeClient(clnConn, cipherSuite, sid); + +} + +#ifdef SSL_REHANDSHAKES_ENABLED +static int32 initializeReHandshake(sslConn_t *clnConn, sslConn_t *svrConn, + uint16_t cipherSuite) +{ + return matrixSslEncodeRehandshake(clnConn->ssl, NULL, NULL, + SSL_OPTION_FULL_HANDSHAKE, &cipherSuite, 1); +} + +static int32 initializeServerInitiatedReHandshake(sslConn_t *clnConn, + sslConn_t *svrConn, uint16_t cipherSuite) +{ + return matrixSslEncodeRehandshake(svrConn->ssl, NULL, NULL, + SSL_OPTION_FULL_HANDSHAKE, &cipherSuite, 1); +} + +static int32 initializeServerInitiatedResumedReHandshake(sslConn_t *clnConn, + sslConn_t *svrConn, uint16_t cipherSuite) +{ + return matrixSslEncodeRehandshake(svrConn->ssl, NULL, NULL, 0, &cipherSuite, + 1); + +} + +static int32 initializeResumedReHandshake(sslConn_t *clnConn, + sslConn_t *svrConn, uint16_t cipherSuite) +{ + return matrixSslEncodeRehandshake(clnConn->ssl, NULL, NULL, 0, &cipherSuite, + 1); +} + +static int32 initializeUpgradeCertCbackReHandshake(sslConn_t *clnConn, + sslConn_t *svrConn, uint16_t cipherSuite) +{ + return matrixSslEncodeRehandshake(clnConn->ssl, NULL, clnCertCheckerUpdate, + 0, &cipherSuite, 1); +} + +static int32 initializeUpgradeKeysReHandshake(sslConn_t *clnConn, + sslConn_t *svrConn, uint16_t cipherSuite) +{ +/* + Not really changing the keys but this still tests that passing a + valid arg will force a full handshake +*/ + return matrixSslEncodeRehandshake(clnConn->ssl, clnConn->ssl->keys, NULL, + 0, &cipherSuite, 1); +} + +static int32 initializeChangeCipherReHandshake(sslConn_t *clnConn, + sslConn_t *svrConn, uint16_t cipherSuite) +{ +/* + Just picking the most common suite +*/ +#ifdef USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA + uint16_t suite; + suite = SSL_RSA_WITH_3DES_EDE_CBC_SHA; + return matrixSslEncodeRehandshake(clnConn->ssl, NULL, NULL, + 0, &suite, 1); +#else + return matrixSslEncodeRehandshake(clnConn->ssl, NULL, NULL, 0, 0, 0); +#endif +} + +#ifdef USE_CLIENT_AUTH +static int32 initializeReHandshakeClientAuth(sslConn_t *clnConn, + sslConn_t *svrConn, uint16_t cipherSuite) +{ + return matrixSslEncodeRehandshake(svrConn->ssl, NULL, svrCertChecker, 0, + &cipherSuite, 1); +} +#endif /* USE_CLIENT_AUTH */ +#endif /* SSL_REHANDSHAKES_ENABLED */ + +static int32 initializeResumedHandshake(sslConn_t *clnConn, sslConn_t *svrConn, + uint16_t cipherSuite) +{ + sslSessionId_t *sessionId; + sslSessOpts_t options; +#ifdef ENABLE_PERF_TIMING + psTime_t start, end; +#endif /* ENABLE_PERF_TIMING */ + + sessionId = clnConn->ssl->sid; + + memset(&options, 0x0, sizeof(sslSessOpts_t)); + options.versionFlag = g_versionFlag; +#ifdef USE_ECC_CIPHER_SUITE + options.ecFlags = clnConn->ssl->ecInfo.ecFlags; +#endif +#ifdef TEST_RESUMPTIONS_WITH_SESSION_TICKETS + options.ticketResumption = 1; +#endif + + matrixSslDeleteSession(clnConn->ssl); + +#ifdef ENABLE_PERF_TIMING + clnConn->hsTime = 0; + psGetTime(&start, NULL); +#endif /* ENABLE_PERF_TIMING */ + if (matrixSslNewClientSession(&clnConn->ssl, clnConn->keys, sessionId, + &cipherSuite, 1, clnCertChecker, "localhost", NULL, NULL, + &options) + < 0) { + return PS_FAILURE; + } +#ifdef ENABLE_PERF_TIMING + psGetTime(&end, NULL); + clnConn->hsTime += psDiffMsecs(start, end, NULL); +#endif /* ENABLE_PERF_TIMING */ + + matrixSslDeleteSession(svrConn->ssl); +#ifdef ENABLE_PERF_TIMING + svrConn->hsTime = 0; + psGetTime(&start, NULL); +#endif /* ENABLE_PERF_TIMING */ +#ifdef USE_SERVER_SIDE_SSL + if (matrixSslNewServerSession(&svrConn->ssl, svrConn->keys, NULL, + &options) < 0) { + return PS_FAILURE; + } +#endif +#ifdef ENABLE_PERF_TIMING + psGetTime(&end, NULL); + svrConn->hsTime += psDiffMsecs(start, end, NULL); +#endif /* ENABLE_PERF_TIMING */ + return PS_SUCCESS; +} + +#ifdef USE_CLIENT_AUTH +static int32 initializeClientAuthHandshake(sslConn_t *clnConn, + sslConn_t *svrConn, uint16_t cipherSuite, sslSessionId_t *sid) +{ + sslSessOpts_t options; +#ifdef ENABLE_PERF_TIMING + psTime_t start, end; +#endif /* ENABLE_PERF_TIMING */ + + memset(&options, 0x0, sizeof(sslSessOpts_t)); + options.versionFlag = g_versionFlag; +#ifdef USE_ECC_CIPHER_SUITE + options.ecFlags = clnConn->ssl->ecInfo.ecFlags; +#endif +#ifdef TEST_RESUMPTIONS_WITH_SESSION_TICKETS + options.ticketResumption = 1; +#endif + + matrixSslDeleteSession(clnConn->ssl); + +#ifdef ENABLE_PERF_TIMING + clnConn->hsTime = 0; + psGetTime(&start, NULL); +#endif /* ENABLE_PERF_TIMING */ + if (matrixSslNewClientSession(&clnConn->ssl, clnConn->keys, sid, + &cipherSuite, 1, clnCertChecker, "localhost", NULL, NULL, + &options) < 0) { + return PS_FAILURE; + } +#ifdef ENABLE_PERF_TIMING + psGetTime(&end, NULL); + clnConn->hsTime += psDiffMsecs(start, end, NULL); +#endif /* ENABLE_PERF_TIMING */ + + matrixSslDeleteSession(svrConn->ssl); +#ifdef ENABLE_PERF_TIMING + svrConn->hsTime = 0; + psGetTime(&start, NULL); +#endif /* ENABLE_PERF_TIMING */ +#ifdef USE_SERVER_SIDE_SSL + if (matrixSslNewServerSession(&svrConn->ssl, svrConn->keys, svrCertChecker, + &options) < 0) { + return PS_FAILURE; + } +#endif +#ifdef ENABLE_PERF_TIMING + psGetTime(&end, NULL); + svrConn->hsTime += psDiffMsecs(start, end, NULL); +#endif /* ENABLE_PERF_TIMING */ + return PS_SUCCESS; +} +#endif /* USE_CLIENT_AUTH */ + +/* + Recursive handshake +*/ +static int32 performHandshake(sslConn_t *sendingSide, sslConn_t *receivingSide) +{ + unsigned char *inbuf, *outbuf, *plaintextBuf; + int32 inbufLen, outbufLen, rc, dataSent; + uint32 ptLen; +#ifdef ENABLE_PERF_TIMING + psTime_t start, end; +#endif /* ENABLE_PERF_TIMING */ + +/* + Sending side will have outdata ready +*/ +#ifdef ENABLE_PERF_TIMING + psGetTime(&start, NULL); +#endif /* ENABLE_PERF_TIMING */ +#ifdef USE_DTLS + if (sendingSide->ssl->flags & SSL_FLAGS_DTLS) { + outbufLen = matrixDtlsGetOutdata(sendingSide->ssl, &outbuf); + } else { + outbufLen = matrixSslGetOutdata(sendingSide->ssl, &outbuf); + } +#else + outbufLen = matrixSslGetOutdata(sendingSide->ssl, &outbuf); +#endif +#ifdef ENABLE_PERF_TIMING + psGetTime(&end, NULL); + sendingSide->hsTime += psDiffMsecs(start, end, NULL); +#endif /* ENABLE_PERF_TIMING */ + +/* + Receiving side must ask for storage space to receive data into +*/ +#ifdef ENABLE_PERF_TIMING + psGetTime(&start, NULL); +#endif /* ENABLE_PERF_TIMING */ + inbufLen = matrixSslGetReadbuf(receivingSide->ssl, &inbuf); +#ifdef ENABLE_PERF_TIMING + psGetTime(&end, NULL); + receivingSide->hsTime += psDiffMsecs(start, end, NULL); +#endif /* ENABLE_PERF_TIMING */ + +/* + The indata is the outdata from the sending side. copy it over +*/ + dataSent = min(outbufLen, inbufLen); + memcpy(inbuf, outbuf, dataSent); + +/* + Now update the sending side that data has been "sent" +*/ +#ifdef ENABLE_PERF_TIMING + psGetTime(&start, NULL); +#endif /* ENABLE_PERF_TIMING */ +#ifdef USE_DTLS + if (sendingSide->ssl->flags & SSL_FLAGS_DTLS) { + matrixDtlsSentData(sendingSide->ssl, dataSent); + } else { + matrixSslSentData(sendingSide->ssl, dataSent); + } +#else + matrixSslSentData(sendingSide->ssl, dataSent); +#endif +#ifdef ENABLE_PERF_TIMING + psGetTime(&end, NULL); + sendingSide->hsTime += psDiffMsecs(start, end, NULL); +#endif /* ENABLE_PERF_TIMING */ + +/* + Received data +*/ +#ifdef ENABLE_PERF_TIMING + psGetTime(&start, NULL); +#endif /* ENABLE_PERF_TIMING */ + rc = matrixSslReceivedData(receivingSide->ssl, dataSent, &plaintextBuf, + &ptLen); +#ifdef ENABLE_PERF_TIMING + psGetTime(&end, NULL); + receivingSide->hsTime += psDiffMsecs(start, end, NULL); +#endif /* ENABLE_PERF_TIMING */ + + if (rc == MATRIXSSL_REQUEST_SEND) { +/* + Success case. Switch roles and continue +*/ + return performHandshake(receivingSide, sendingSide); + + } else if (rc == MATRIXSSL_REQUEST_RECV) { +/* + This pass didn't take care of it all. Don't switch roles and + try again +*/ + return performHandshake(sendingSide, receivingSide); + + } else if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) { + return PS_SUCCESS; + + } else if (rc == MATRIXSSL_RECEIVED_ALERT) { +/* + Just continue if warning level alert +*/ + if (plaintextBuf[0] == SSL_ALERT_LEVEL_WARNING) { + if (matrixSslProcessedData(receivingSide->ssl, &plaintextBuf, + &ptLen) != 0) { + return PS_FAILURE; + } + return performHandshake(sendingSide, receivingSide); + } else { + return PS_FAILURE; + } + + } else { + printf("Unexpected error in performHandshake: %d\n", rc); + return PS_FAILURE; + } + return PS_FAILURE; /* can't get here */ +} + +#ifdef ENABLE_PERF_TIMING +static void ciphername(uint32_t flags, char s[32]) +{ + s[0] = '\0'; + if (flags & CRYPTO_FLAGS_AES) { + strcat(s, "AES"); + } else if (flags & CRYPTO_FLAGS_AES256) { + strcat(s, "AES256"); + } else if (flags & CRYPTO_FLAGS_3DES) { + strcat(s, "3DES"); + } else if (flags & CRYPTO_FLAGS_ARC4) { + strcat(s, "RC4"); + } else if (flags & CRYPTO_FLAGS_SEED) { + strcat(s, "SEED"); + } else if (flags & CRYPTO_FLAGS_IDEA) { + strcat(s, "IDEA"); + } + if (flags & CRYPTO_FLAGS_GCM) { + strcat(s, "_GCM"); + } else if (flags & CRYPTO_FLAGS_SHA1) { + strcat(s, "_SHA"); + } else if (flags & CRYPTO_FLAGS_SHA2) { + strcat(s, "_SHA256"); + } else if (flags & CRYPTO_FLAGS_SHA3) { + strcat(s, "_SHA384"); + } else if (flags & CRYPTO_FLAGS_MD5) { + strcat(s, "_MD5"); + } +} + +static uint32_t g_ttest[64]; +static uint32_t g_ttest_val[64]; +static uint16_t g_ttest_count = 0; + +static void print_throughput(void) +{ + char name[32]; + int i; + + printf("Cipher" DELIM "MiB/s\n"); + for (i = 0; i < g_ttest_count; i++) { + ciphername(g_ttest[i], name); + printf("%s" DELIM "%u\n", name, MBS(g_ttest_val[i])); + } +} + +static int32_t throughputTest(sslConn_t *s, sslConn_t *r, uint16_t nrec, uint16_t reclen) +{ + uint32_t i, len, flags; + int32_t rc, buflen; + unsigned char *rb, *wb, *pt; + char name[32]; + + psTime_t start, end; +#ifndef USE_HIGHRES_TIME + psTime_t tstart; +#endif + +#ifdef USE_DTLS + if (s->ssl->flags & SSL_FLAGS_DTLS) { + return PS_SUCCESS; + } +#endif + flags = s->ssl->cipher->flags; + for (i = 0; i < g_ttest_count; i++) { + if (g_ttest[i] == flags) { + s->appTime = r->appTime = g_ttest_val[i]; + return PS_SUCCESS; + } + } + s->appTime = r->appTime = 0; + ciphername(flags, name); + printf("%s throughput test for %hu byte records (%u bytes total)\n", + name, reclen, nrec * reclen); + +#ifndef USE_HIGHRES_TIME + psGetTime(&tstart, NULL); +#endif + for (i = 0; i < nrec; i++) { + buflen = matrixSslGetWritebuf(s->ssl, &wb, reclen); + if (buflen < reclen) { + return PS_FAIL; + } + psGetTime(&start, NULL); + buflen = matrixSslEncodeWritebuf(s->ssl, reclen); + if (buflen < 0) { + return buflen; + } +#ifdef USE_DTLS + if (flags & SSL_FLAGS_DTLS) { + buflen = matrixDtlsGetOutdata(s->ssl, &wb); + } else { + buflen = matrixSslGetOutdata(s->ssl, &wb); + } +#else + buflen = matrixSslGetOutdata(s->ssl, &wb); +#endif + psGetTime(&end, NULL); + s->appTime += psDiffMsecs(start, end, NULL); + + len = matrixSslGetReadbufOfSize(r->ssl, buflen, &rb); + if (len < buflen) { + return PS_FAIL; + } + memcpy(rb, wb, buflen); + + psGetTime(&start, NULL); +#ifdef USE_DTLS + if (flags & SSL_FLAGS_DTLS) { + rc = matrixDtlsSentData(s->ssl, buflen); + } else { + rc = matrixSslSentData(s->ssl, buflen); + } +#else + rc = matrixSslSentData(s->ssl, buflen); +#endif + psGetTime(&end, NULL); + s->appTime += psDiffMsecs(start, end, NULL); + if (rc < 0) { + return rc; + } + psGetTime(&start, NULL); + rc = matrixSslReceivedData(r->ssl, buflen, &pt, &len); + if (rc != MATRIXSSL_APP_DATA) { + return rc; + } + /* This is a loop, since with BEAST mode, 2 records may result from one encode */ + while (rc == MATRIXSSL_APP_DATA) { + rc = matrixSslProcessedData(r->ssl, &pt, &len); + } + psGetTime(&end, NULL); + r->appTime += psDiffMsecs(start, end, NULL); + if (rc != 0) { + return PS_FAIL; + } + } +#ifndef USE_HIGHRES_TIME + s->appTime = psDiffMsecs(tstart, end, NULL) / 2; + r->appTime = s->appTime; +#endif + printf(" throughput send %u MiB/s\n", MBS(s->appTime)); + printf(" throughput recv %u MiB/s\n", MBS(r->appTime)); + g_ttest[g_ttest_count] = flags; + g_ttest_val[g_ttest_count] = s->appTime; + g_ttest_count++; + return PS_SUCCESS; +} +#endif + +/* + If bytes == 0, does not exchange data. + return 0 on successful encryption/decryption communication + return -1 on failed comm +*/ +static int32 exchangeAppData(sslConn_t *sendingSide, sslConn_t *receivingSide, uint32_t bytes) +{ + int32 writeBufLen, inBufLen, dataSent, rc, sentRc; + uint32 ptLen, requestedLen, copyLen, halfReqLen; + unsigned char *writeBuf, *inBuf, *plaintextBuf; + unsigned char copyByte; + + if (bytes == 0) { + return PS_SUCCESS; + } + requestedLen = bytes; + copyByte = 0x1; +/* + Split the data into two records sends. Exercises the API a bit more + having the extra buffer management for multiple records +*/ + while (requestedLen > 1) { + copyByte++; + halfReqLen = requestedLen / 2; + writeBufLen = matrixSslGetWritebuf(sendingSide->ssl, &writeBuf, halfReqLen); + if (writeBufLen <= 0) { + return PS_FAILURE; + } + copyLen = min(halfReqLen, (uint32)writeBufLen); + //memset(writeBuf, copyByte, copyLen); + requestedLen -= copyLen; + //psTraceBytes("sending", writeBuf, copyLen); + + writeBufLen = matrixSslEncodeWritebuf(sendingSide->ssl, copyLen); + if (writeBufLen < 0) { + return PS_FAILURE; + } + copyByte++; + writeBufLen = matrixSslGetWritebuf(sendingSide->ssl, &writeBuf, + halfReqLen); + if (writeBufLen <= 0) { + return PS_FAILURE; + } + copyLen = min(halfReqLen, (uint32)writeBufLen); + //memset(writeBuf, copyByte, copyLen); + requestedLen -= copyLen; + //psTraceBytes("sending", writeBuf, copyLen); + + writeBufLen = matrixSslEncodeWritebuf(sendingSide->ssl, copyLen); + if (writeBufLen < 0) { + return PS_FAILURE; + } + } + +SEND_MORE: +#ifdef USE_DTLS + if (sendingSide->ssl->flags & SSL_FLAGS_DTLS) { + writeBufLen = matrixDtlsGetOutdata(sendingSide->ssl, &writeBuf); + } else { + writeBufLen = matrixSslGetOutdata(sendingSide->ssl, &writeBuf); + } +#else + writeBufLen = matrixSslGetOutdata(sendingSide->ssl, &writeBuf); +#endif + +/* + Receiving side must ask for storage space to receive data into. + + A good optimization of the buffer management can be seen here if a + second pass was required: the inBufLen should exactly match the + writeBufLen because when matrixSslReceivedData was called below the + record length was parsed off and the buffer was reallocated to the + exact necessary length +*/ + inBufLen = matrixSslGetReadbuf(receivingSide->ssl, &inBuf); + + dataSent = min(writeBufLen, inBufLen); + memcpy(inBuf, writeBuf, dataSent); + + /* Now update the sending side that data has been "sent" */ +#ifdef USE_DTLS + if (sendingSide->ssl->flags & SSL_FLAGS_DTLS) { + sentRc = matrixDtlsSentData(sendingSide->ssl, dataSent); + } else { + sentRc = matrixSslSentData(sendingSide->ssl, dataSent); + } +#else + sentRc = matrixSslSentData(sendingSide->ssl, dataSent); +#endif + + /* Received data */ + rc = matrixSslReceivedData(receivingSide->ssl, dataSent, &plaintextBuf, + &ptLen); + + if (rc == MATRIXSSL_REQUEST_RECV) { + goto SEND_MORE; + } else if (rc == MATRIXSSL_APP_DATA || rc == MATRIXSSL_APP_DATA_COMPRESSED){ + while (rc == MATRIXSSL_APP_DATA || rc == MATRIXSSL_APP_DATA_COMPRESSED){ + //psTraceBytes("received", plaintextBuf, ptLen); + if ((rc = matrixSslProcessedData(receivingSide->ssl, &plaintextBuf, + &ptLen)) != 0) { + if (rc == MATRIXSSL_APP_DATA || + rc == MATRIXSSL_APP_DATA_COMPRESSED) { + continue; + } else if (rc == MATRIXSSL_REQUEST_RECV) { + goto SEND_MORE; + } else { + return PS_FAILURE; + } + } + } + if (sentRc == MATRIXSSL_REQUEST_SEND) { + goto SEND_MORE; + } + } else { + printf("Unexpected error in exchangeAppData: %d\n", rc); + return PS_FAILURE; + } + + return PS_SUCCESS; +} + + +static int32 initializeServer(sslConn_t *conn, uint16_t cipherSuite) +{ + sslKeys_t *keys = NULL; + ssl_t *ssl = NULL; +#ifdef ENABLE_PERF_TIMING + psTime_t start, end; +#endif /* ENABLE_PERF_TIMING */ + sslSessOpts_t options; + const sslCipherSpec_t *spec; + + memset(&options, 0x0, sizeof(sslSessOpts_t)); + options.versionFlag = g_versionFlag; + + if (conn->keys == NULL) { + if ((spec = sslGetDefinedCipherSpec(cipherSuite)) == NULL) { + return PS_FAIL; + } + if (matrixSslNewKeys(&keys, NULL) < PS_SUCCESS) { + return PS_MEM_FAIL; + } + conn->keys = keys; + + +#ifdef USE_ECC +#ifndef USE_ONLY_PSK_CIPHER_SUITE + if (spec->type == CS_ECDH_ECDSA || spec->type == CS_ECDHE_ECDSA) { +#if defined(MATRIX_USE_FILE_SYSTEM) && !defined(USE_HEADER_KEYS) + if (matrixSslLoadEcKeys(keys, svrEcCertFile, svrEcKeyFile, NULL, + clnEcCAfile) < 0) { + return PS_FAILURE; + } +#endif /* MATRIX_USE_FILE_SYSTEM && !USE_HEADER_KEYS */ + +#ifdef USE_HEADER_KEYS + if (matrixSslLoadEcKeysMem(keys, ECC, ECC_SIZE, + ECCKEY, ECCKEY_SIZE, + ECCCA, ECCCA_SIZE) < 0) { + return PS_FAILURE; + } +#endif /* USE_HEADER_KEYS */ + } + + /* ECDH_RSA suites have a different cert pair */ + if (spec->type == CS_ECDH_RSA) { +#if defined(MATRIX_USE_FILE_SYSTEM) && !defined(USE_HEADER_KEYS) + if (matrixSslLoadEcKeys(keys, svrEcRsaCertFile, svrEcRsaKeyFile, + NULL, clnEcRsaCAfile) < 0) { + return PS_FAILURE; + } +#endif /* MATRIX_USE_FILE_SYSTEM && !USE_HEADER_KEYS */ + +#ifdef USE_HEADER_KEYS + if (matrixSslLoadEcKeysMem(keys, ECDHRSA256, sizeof(ECDHRSA256), + ECDHRSA256KEY, sizeof(ECDHRSA256KEY), + ECDHRSA2048CA, sizeof(ECDHRSA2048CA)) < 0) { + return PS_FAILURE; + } +#endif /* USE_HEADER_KEYS */ + } +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ +#endif /* USE_ECC */ + + +#ifdef USE_RSA +#ifndef USE_ONLY_PSK_CIPHER_SUITE + if (spec->type == CS_RSA || spec->type == CS_DHE_RSA || + spec->type == CS_ECDHE_RSA) { +#if defined(MATRIX_USE_FILE_SYSTEM) && !defined(USE_HEADER_KEYS) + if (matrixSslLoadRsaKeys(keys, svrCertFile, svrKeyFile, NULL, + clnCAfile) < 0) { + return PS_FAILURE; + } +#endif /* MATRIX_USE_FILE_SYSTEM && !USE_HEADER_KEYS */ + +#ifdef USE_HEADER_KEYS + if (matrixSslLoadRsaKeysMem(keys, (unsigned char *)RSACERT, RSA_SIZE, + (unsigned char *)RSAKEY, RSAKEY_SIZE, + (unsigned char *)RSACA, RSACA_SIZE) < 0) { + return PS_FAILURE; + } +#endif /* USE_HEADER_KEYS */ + } +#endif /* !USE_ONLY_PSK_CIPHER_SUITE */ +#endif /* USE_RSA */ + +#ifdef REQUIRE_DH_PARAMS + if (spec->type == CS_DHE_RSA || spec->type == CS_DH_ANON || + spec->type == CS_DHE_PSK) { +#if defined(MATRIX_USE_FILE_SYSTEM) && !defined(USE_HEADER_KEYS) + matrixSslLoadDhParams(keys, dhParamFile); +#endif +#ifdef USE_HEADER_KEYS + matrixSslLoadDhParamsMem(keys, DHPARAM, DH_SIZE); +#endif + } +#endif /* REQUIRE_DH_PARAMS */ + +#ifdef USE_PSK_CIPHER_SUITE + if (spec->type == CS_PSK || spec->type == CS_DHE_PSK) { + int rc; + for (rc = 0; rc < PSK_HEADER_TABLE_COUNT; rc++) { + matrixSslLoadPsk(keys, + PSK_HEADER_TABLE[rc].key, sizeof(PSK_HEADER_TABLE[rc].key), + PSK_HEADER_TABLE[rc].id, sizeof(PSK_HEADER_TABLE[rc].id)); + } + } +#endif /* USE_PSK_CIPHER_SUITE */ + } +#ifdef ENABLE_PERF_TIMING + conn->hsTime = 0; + psGetTime(&start, NULL); +#endif /* ENABLE_PERF_TIMING */ +/* + Create a new SSL session for the new socket and register the + user certificate validator. No client auth first time through +*/ +#ifdef USE_SERVER_SIDE_SSL + if (matrixSslNewServerSession(&ssl, conn->keys, NULL, &options) < 0) { + return PS_FAILURE; + } +#endif + +#ifdef ENABLE_PERF_TIMING + psGetTime(&end, NULL); + conn->hsTime += psDiffMsecs(start, end, NULL); +#endif /* ENABLE_PERF_TIMING */ + conn->ssl = ssl; + + return PS_SUCCESS; +} + + +static int32 initializeClient(sslConn_t *conn, uint16_t cipherSuite, + sslSessionId_t *sid) +{ + ssl_t *ssl; + sslKeys_t *keys; +#ifdef ENABLE_PERF_TIMING + psTime_t start, end; +#endif /* ENABLE_PERF_TIMING */ + sslSessOpts_t options; + const sslCipherSpec_t *spec; + + memset(&options, 0x0, sizeof(sslSessOpts_t)); + options.versionFlag = g_versionFlag; +#ifdef TEST_RESUMPTIONS_WITH_SESSION_TICKETS + options.ticketResumption = 1; +#endif + + if (conn->keys == NULL) { + if ((spec = sslGetDefinedCipherSpec(cipherSuite)) == NULL) { + return PS_FAIL; + } + if (matrixSslNewKeys(&keys, NULL) < PS_SUCCESS) { + return PS_MEM_FAIL; + } + conn->keys = keys; + +#ifdef USE_ECC_CIPHER_SUITE + if (spec->type == CS_ECDHE_ECDSA || spec->type == CS_ECDHE_RSA) { + /* For ephemeral ECC keys, define the ephemeral size here, + otherwise it will default to the largest. We choose the size + based on the size set for the ECDSA key (even in RSA case). */ + switch (ECC_SIZE) { + case EC192_SIZE: + options.ecFlags = SSL_OPT_SECP192R1; + break; + case EC224_SIZE: + options.ecFlags = SSL_OPT_SECP224R1; + break; + case EC256_SIZE: + options.ecFlags = SSL_OPT_SECP256R1; + break; + case EC384_SIZE: + options.ecFlags = SSL_OPT_SECP384R1; + break; + case EC521_SIZE: + options.ecFlags = SSL_OPT_SECP521R1; + break; + } + } +#ifndef USE_ONLY_PSK_CIPHER_SUITE + if (spec->type == CS_ECDH_ECDSA || spec->type == CS_ECDHE_ECDSA) { +#if defined(MATRIX_USE_FILE_SYSTEM) && !defined(USE_HEADER_KEYS) + if (matrixSslLoadEcKeys(keys, clnEcCertFile, clnEcKeyFile, NULL, + svrEcCAfile) < 0) { + return PS_FAILURE; + } +#endif /* MATRIX_USE_FILE_SYSTEM && !USE_HEADER_KEYS */ + +#ifdef USE_HEADER_KEYS + if (matrixSslLoadEcKeysMem(keys, ECC, ECC_SIZE, + ECCKEY, ECCKEY_SIZE, + ECCCA, ECCCA_SIZE) < 0) { + return PS_FAILURE; + } +#endif /* USE_HEADER_KEYS */ + } + +#ifdef USE_RSA + /* ECDH_RSA suites have different cert pair. */ + if (spec->type == CS_ECDH_RSA) { +#if defined(MATRIX_USE_FILE_SYSTEM) && !defined(USE_HEADER_KEYS) + if (matrixSslLoadEcKeys(keys, clnEcRsaCertFile, clnEcRsaKeyFile, + NULL, svrEcRsaCAfile) < 0) { + return PS_FAILURE; + } +#endif /* MATRIX_USE_FILE_SYSTEM && !USE_HEADER_KEYS */ + +#ifdef USE_HEADER_KEYS +#if 0 + if (matrixSslLoadEcKeysMem(keys, ECDHRSA521, sizeof(ECDHRSA521), + ECDHRSA521KEY, sizeof(ECDHRSA521KEY), + ECDHRSA1024CA, sizeof(ECDHRSA1024CA)) < 0) { + return PS_FAILURE; + } +#endif +#endif /* USE_HEADER_KEYS */ + } +#endif /* USE_RSA */ +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ +#endif /* USE_ECC */ + +#ifdef USE_RSA +#ifndef USE_ONLY_PSK_CIPHER_SUITE + if (spec->type == CS_RSA || spec->type == CS_DHE_RSA || + spec->type == CS_ECDHE_RSA) { +#if defined(MATRIX_USE_FILE_SYSTEM) && !defined(USE_HEADER_KEYS) + if (matrixSslLoadRsaKeys(keys, clnCertFile, clnKeyFile, NULL, + svrCAfile) < 0) { + return PS_FAILURE; + } +#endif /* MATRIX_USE_FILE_SYSTEM && !USE_HEADER_KEYS */ + +#ifdef USE_HEADER_KEYS + if (matrixSslLoadRsaKeysMem(keys, RSACERT, RSA_SIZE, + RSAKEY, RSAKEY_SIZE, (unsigned char *)RSACA, + RSACA_SIZE) < 0) { + return PS_FAILURE; + } +#endif /* USE_HEADER_KEYS */ + } +#endif /* USE_ONLY_PSK_CIPHER_SUITE */ +#endif /* USE_RSA */ + +#ifdef USE_PSK_CIPHER_SUITE + if (spec->type == CS_PSK || spec->type == CS_DHE_PSK) { + matrixSslLoadPsk(keys, + PSK_HEADER_TABLE[0].key, sizeof(PSK_HEADER_TABLE[0].key), + PSK_HEADER_TABLE[0].id, sizeof(PSK_HEADER_TABLE[0].id)); + } +#endif /* USE_PSK_CIPHER_SUITE */ + } + + conn->ssl = NULL; +#ifdef ENABLE_PERF_TIMING + conn->hsTime = 0; + psGetTime(&start, NULL); +#endif /* ENABLE_PERF_TIMING */ + + if (matrixSslNewClientSession(&ssl, conn->keys, sid, &cipherSuite, + 1, clnCertChecker, "localhost", NULL, NULL, &options) < 0) { + return PS_FAILURE; + } + +#ifdef ENABLE_PERF_TIMING + psGetTime(&end, NULL); + conn->hsTime += psDiffMsecs(start, end, NULL); +#endif /* ENABLE_PERF_TIMING */ + + conn->ssl = ssl; + + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Delete session and connection + */ +static void freeSessionAndConnection(sslConn_t *conn) +{ + if (conn->ssl != NULL) { + matrixSslDeleteSession(conn->ssl); + } + matrixSslDeleteKeys(conn->keys); + conn->ssl = NULL; + conn->keys = NULL; +} + +/* Ignoring the CERTIFICATE_EXPIRED alert in the test because it will + always fail on Windows because there is no implementation for that */ +static int32_t clnCertChecker(ssl_t *ssl, psX509Cert_t *cert, int32_t alert) +{ + if (alert == SSL_ALERT_CERTIFICATE_EXPIRED) { + return 0; + } + return alert; +} + +#ifdef SSL_REHANDSHAKES_ENABLED +static int32 clnCertCheckerUpdate(ssl_t *ssl, psX509Cert_t *cert, int32 alert) +{ + if (alert == SSL_ALERT_CERTIFICATE_EXPIRED) { + return 0; + } + return alert; +} +#endif /* SSL_REHANDSHAKES_ENABLED */ + +#ifdef USE_CLIENT_AUTH +static int32 svrCertChecker(ssl_t *ssl, psX509Cert_t *cert, int32 alert) +{ + if (alert == SSL_ALERT_CERTIFICATE_EXPIRED) { + return 0; + } + return alert; +} +#endif /* USE_CLIENT_AUTH */ + + +#ifdef USE_MATRIXSSL_STATS +static void statCback(void *ssl, void *stat_ptr, int32 type, int32 value) +{ + //printf("Got stat event %d with value %d\n", type, value); +} +#endif +/******************************************************************************/ + + diff --git a/matrixssl/tls.c b/matrixssl/tls.c new file mode 100644 index 0000000..02fd8a7 --- /dev/null +++ b/matrixssl/tls.c @@ -0,0 +1,820 @@ +/** + * @file tls.c + * @version $Format:%h%d$ + * + * TLS (SSLv3.1+) specific code. + * http://www.faqs.org/rfcs/rfc2246.html + * Primarily dealing with secret generation, message authentication codes + * and handshake hashing. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; 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 General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#include "matrixsslApi.h" + +/******************************************************************************/ +#ifdef USE_TLS +/******************************************************************************/ + +#define LABEL_SIZE 13 +#define LABEL_MASTERSEC "master secret" +#define LABEL_KEY_BLOCK "key expansion" + +#define LABEL_EXT_SIZE 22 +#define LABEL_EXT_MASTERSEC "extended master secret" + + +static int32_t genKeyBlock(ssl_t *ssl) +{ + unsigned char msSeed[SSL_HS_RANDOM_SIZE * 2 + LABEL_SIZE]; + uint32 reqKeyLen; + int32_t rc = PS_FAIL; + + memcpy(msSeed, LABEL_KEY_BLOCK, LABEL_SIZE); + memcpy(msSeed + LABEL_SIZE, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + memcpy(msSeed + LABEL_SIZE + SSL_HS_RANDOM_SIZE, + ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); + + /* We must generate enough key material to fill the various keys */ + reqKeyLen = 2 * ssl->cipher->macSize + + 2 * ssl->cipher->keySize + + 2 * ssl->cipher->ivSize; + + /* Ensure there's enough room */ + if (reqKeyLen > SSL_MAX_KEY_BLOCK_SIZE) { + rc = PS_MEM_FAIL; + goto L_RETURN; + } + +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + if ((rc = prf2(ssl->sec.masterSecret, SSL_HS_MASTER_SIZE, msSeed, + (SSL_HS_RANDOM_SIZE * 2) + LABEL_SIZE, ssl->sec.keyBlock, + reqKeyLen, ssl->cipher->flags)) < 0) { + goto L_RETURN; + } + } +#ifndef USE_ONLY_TLS_1_2 + else { + if ((rc = prf(ssl->sec.masterSecret, SSL_HS_MASTER_SIZE, msSeed, + (SSL_HS_RANDOM_SIZE * 2) + LABEL_SIZE, ssl->sec.keyBlock, + reqKeyLen)) < 0) { + goto L_RETURN; + } + } +#endif +#else + if ((rc = prf(ssl->sec.masterSecret, SSL_HS_MASTER_SIZE, msSeed, + (SSL_HS_RANDOM_SIZE * 2) + LABEL_SIZE, ssl->sec.keyBlock, + reqKeyLen)) < 0) { + goto L_RETURN; + } +#endif + if (ssl->flags & SSL_FLAGS_SERVER) { + ssl->sec.rMACptr = ssl->sec.keyBlock; + ssl->sec.wMACptr = ssl->sec.rMACptr + ssl->cipher->macSize; + ssl->sec.rKeyptr = ssl->sec.wMACptr + ssl->cipher->macSize; + ssl->sec.wKeyptr = ssl->sec.rKeyptr + ssl->cipher->keySize; + ssl->sec.rIVptr = ssl->sec.wKeyptr + ssl->cipher->keySize; + ssl->sec.wIVptr = ssl->sec.rIVptr + ssl->cipher->ivSize; + } else { + ssl->sec.wMACptr = ssl->sec.keyBlock; + ssl->sec.rMACptr = ssl->sec.wMACptr + ssl->cipher->macSize; + ssl->sec.wKeyptr = ssl->sec.rMACptr + ssl->cipher->macSize; + ssl->sec.rKeyptr = ssl->sec.wKeyptr + ssl->cipher->keySize; + ssl->sec.wIVptr = ssl->sec.rKeyptr + ssl->cipher->keySize; + ssl->sec.rIVptr = ssl->sec.wIVptr + ssl->cipher->ivSize; + } + + rc = SSL_HS_MASTER_SIZE; + +L_RETURN: + memzero_s(msSeed, sizeof(msSeed)); + if (rc < 0) { + memzero_s(ssl->sec.masterSecret, SSL_HS_MASTER_SIZE); + memzero_s(ssl->sec.keyBlock, SSL_MAX_KEY_BLOCK_SIZE); + } + return rc; +} + +/******************************************************************************/ +/* + * Generates all key material. + */ +int32_t tlsDeriveKeys(ssl_t *ssl) +{ + unsigned char msSeed[SSL_HS_RANDOM_SIZE * 2 + LABEL_SIZE]; + int32_t rc = PS_FAIL; + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS && ssl->retransmit == 1) { + /* The keyblock is still valid from the first pass */ + return SSL_HS_MASTER_SIZE; + } +#endif +/* + If this session is resumed, we want to reuse the master secret to + regenerate the key block with the new random values. +*/ + if (ssl->flags & SSL_FLAGS_RESUMED) { + return genKeyBlock(ssl); + } + +/* + master_secret = PRF(pre_master_secret, "master secret", + client_random + server_random); +*/ + memcpy(msSeed, LABEL_MASTERSEC, LABEL_SIZE); + memcpy(msSeed + LABEL_SIZE, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + memcpy(msSeed + LABEL_SIZE + SSL_HS_RANDOM_SIZE, + ssl->sec.serverRandom, SSL_HS_RANDOM_SIZE); + +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + if ((rc = prf2(ssl->sec.premaster, ssl->sec.premasterSize, msSeed, + (SSL_HS_RANDOM_SIZE * 2) + LABEL_SIZE, ssl->sec.masterSecret, + SSL_HS_MASTER_SIZE, ssl->cipher->flags)) < 0) { + return rc; + } +#ifndef USE_ONLY_TLS_1_2 + } else { + if ((rc = prf(ssl->sec.premaster, ssl->sec.premasterSize, msSeed, + (SSL_HS_RANDOM_SIZE * 2) + LABEL_SIZE, ssl->sec.masterSecret, + SSL_HS_MASTER_SIZE)) < 0) { + return rc; + } +#endif + } +#else + if ((rc = prf(ssl->sec.premaster, ssl->sec.premasterSize, msSeed, + (SSL_HS_RANDOM_SIZE * 2) + LABEL_SIZE, ssl->sec.masterSecret, + SSL_HS_MASTER_SIZE)) < 0) { + return rc; + } +#endif + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { +/* + May need premaster for retransmits. DTLS will free this when handshake + is known to be complete +*/ + return genKeyBlock(ssl); + } +#endif /* USE_DTLS */ +/* + premaster is now allocated for DH reasons. Can free here +*/ + psFree(ssl->sec.premaster, ssl->hsPool); + ssl->sec.premaster = NULL; + ssl->sec.premasterSize = 0; + + return genKeyBlock(ssl); +} + +/* Master secret generation if extended_master_secret extension is used */ +int32_t tlsExtendedDeriveKeys(ssl_t *ssl) +{ + unsigned char msSeed[SHA384_HASHLEN + LABEL_EXT_SIZE]; + unsigned char hash[SHA384_HASHLEN]; + uint32_t outLen; + int32_t rc = PS_FAIL; + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS && ssl->retransmit == 1) { + /* The keyblock is still valid from the first pass */ + return SSL_HS_MASTER_SIZE; + } +#endif +/* + If this session is resumed, we should reuse the master_secret to + regenerate the key block with the new random values. We should not + be here regenerating the master_secret! +*/ + if (ssl->extFlags.extended_master_secret == 0 || + ssl->flags & SSL_FLAGS_RESUMED) { + psTraceInfo("Invalid invokation of extended key derivation.\n"); + return PS_FAIL; + } + + extMasterSecretSnapshotHSHash(ssl, hash, &outLen); +/* + master_secret = PRF(pre_master_secret, "extended master secret", + session_hash); +*/ + memcpy(msSeed, LABEL_EXT_MASTERSEC, LABEL_EXT_SIZE); + memcpy(msSeed + LABEL_EXT_SIZE, hash, outLen); + +#ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) { + if ((rc = prf2(ssl->sec.premaster, ssl->sec.premasterSize, msSeed, + outLen + LABEL_EXT_SIZE, ssl->sec.masterSecret, + SSL_HS_MASTER_SIZE, ssl->cipher->flags)) < 0) { + return rc; + } +#ifndef USE_ONLY_TLS_1_2 + } else { + if ((rc = prf(ssl->sec.premaster, ssl->sec.premasterSize, msSeed, + outLen + LABEL_EXT_SIZE, ssl->sec.masterSecret, + SSL_HS_MASTER_SIZE)) < 0) { + return rc; + } +#endif + } +#else + if ((rc = prf(ssl->sec.premaster, ssl->sec.premasterSize, msSeed, + outLen + LABEL_EXT_SIZE, ssl->sec.masterSecret, + SSL_HS_MASTER_SIZE)) < 0) { + return rc; + } +#endif + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { +/* + May need premaster for retransmits. DTLS will free this when handshake + is known to be complete +*/ + return genKeyBlock(ssl); + } +#endif /* USE_DTLS */ +/* + premaster is now allocated for DH reasons. Can free here +*/ + psFree(ssl->sec.premaster, ssl->hsPool); + ssl->sec.premaster = NULL; + ssl->sec.premasterSize = 0; + + return genKeyBlock(ssl); +} + +#ifdef USE_SHA_MAC +#ifdef USE_SHA1 +/******************************************************************************/ +/* + TLS sha1 HMAC generate/verify +*/ +int32_t tlsHMACSha1(ssl_t *ssl, int32 mode, unsigned char type, + unsigned char *data, uint32 len, unsigned char *mac) +{ +#ifndef USE_HMAC_TLS + psHmacSha1_t ctx; +#endif + unsigned char *key, *seq; + unsigned char majVer, minVer, tmp[5]; + int32 i; +#ifdef USE_DTLS + unsigned char dtls_seq[8]; +#endif /* USE_DTLS */ +#ifdef USE_HMAC_TLS + uint32 alt_len; +#endif /* USE_HMAC_TLS */ + + majVer = ssl->majVer; + minVer = ssl->minVer; + + if (mode == HMAC_CREATE) { + key = ssl->sec.writeMAC; + seq = ssl->sec.seq; + } else { /* HMAC_VERIFY */ + key = ssl->sec.readMAC; + seq = ssl->sec.remSeq; + } + + /* Sanity */ + if (key == NULL) { + return PS_FAILURE; + } + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (mode == HMAC_CREATE) { + seq = dtls_seq; + memcpy(dtls_seq, ssl->epoch, 2); + memcpy(dtls_seq + 2, ssl->rsn, 6); + } else { /* HMAC_VERIFY */ + seq = dtls_seq; + memcpy(dtls_seq, ssl->rec.epoch, 2); + memcpy(dtls_seq + 2, ssl->rec.rsn, 6); + } + } +#endif /* USE_DTLS */ + + tmp[0] = type; + tmp[1] = majVer; + tmp[2] = minVer; + tmp[3] = (len & 0xFF00) >> 8; + tmp[4] = len & 0xFF; +#ifdef USE_HMAC_TLS +#ifdef USE_HMAC_TLS_LUCKY13_COUNTERMEASURE + alt_len = mode == HMAC_CREATE ? len : ssl->rec.len; +#else + alt_len = len; +#endif + (void)psHmacSha1Tls(key, SHA1_HASH_SIZE, + seq, 8, + tmp, 5, + data, len, alt_len, + mac); +#else + if (psHmacSha1Init(&ctx, key, SHA1_HASH_SIZE) < 0) { + return PS_FAIL; + } + psHmacSha1Update(&ctx, seq, 8); + psHmacSha1Update(&ctx, tmp, 5); + psHmacSha1Update(&ctx, data, len); + psHmacSha1Final(&ctx, mac); +#endif + /* Update seq (only for normal TLS) */ + for (i = 7; i >= 0; i--) { + seq[i]++; + if (seq[i] != 0) { + break; + } + } + return PS_SUCCESS; +} +#endif /* USE_SHA1 */ + +#if defined(USE_HMAC_SHA256) || defined(USE_HMAC_SHA384) +/******************************************************************************/ +/* + TLS sha256/sha384 HMAC generate/verify +*/ +int32_t tlsHMACSha2(ssl_t *ssl, int32 mode, unsigned char type, + unsigned char *data, uint32 len, unsigned char *mac, int32 hashLen) +{ +#ifndef USE_HMAC_TLS + psHmac_t ctx; +#endif + unsigned char *key, *seq; + unsigned char majVer, minVer, tmp[5]; + int32 i; +#ifdef USE_DTLS + unsigned char dtls_seq[8]; +#endif /* USE_DTLS */ +#ifdef USE_HMAC_TLS + uint32 alt_len; +#endif /* USE_HMAC_TLS */ + + majVer = ssl->majVer; + minVer = ssl->minVer; + + if (mode == HMAC_CREATE) { + key = ssl->sec.writeMAC; + seq = ssl->sec.seq; + } else { /* HMAC_VERIFY */ + key = ssl->sec.readMAC; + seq = ssl->sec.remSeq; + } + /* Sanity */ + if (key == NULL) { + return PS_FAILURE; + } + +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (mode == HMAC_CREATE) { + seq = dtls_seq; + memcpy(dtls_seq, ssl->epoch, 2); + memcpy(dtls_seq + 2, ssl->rsn, 6); + } else { /* HMAC_VERIFY */ + seq = dtls_seq; + memcpy(dtls_seq, ssl->rec.epoch, 2); + memcpy(dtls_seq + 2, ssl->rec.rsn, 6); + } + } +#endif /* USE_DTLS */ + + tmp[0] = type; + tmp[1] = majVer; + tmp[2] = minVer; + tmp[3] = (len & 0xFF00) >> 8; + tmp[4] = len & 0xFF; + +#ifdef USE_HMAC_TLS +#ifdef USE_HMAC_TLS_LUCKY13_COUNTERMEASURE + alt_len = mode == HMAC_CREATE ? len : ssl->rec.len; +#else + alt_len = len; +#endif + (void)psHmacSha2Tls(key, hashLen, + seq, 8, + tmp, 5, + data, len, alt_len, + mac, hashLen); +#else + switch(hashLen) { + case SHA256_HASHLEN: + if (psHmacInit(&ctx, HMAC_SHA256, key, hashLen) < 0) { + return PS_FAIL; + } + break; + case SHA384_HASHLEN: + if (psHmacInit(&ctx, HMAC_SHA384, key, hashLen) < 0) { + return PS_FAIL; + } + break; + default: + return PS_FAIL; + } + psHmacUpdate(&ctx, seq, 8); + psHmacUpdate(&ctx, tmp, 5); + psHmacUpdate(&ctx, data, len); + psHmacFinal(&ctx, mac); +#endif + /* Update seq (only for normal TLS) */ + for (i = 7; i >= 0; i--) { + seq[i]++; + if (seq[i] != 0) { + break; + } + } + return PS_SUCCESS; +} +#endif /* USE_SHA256 || USE_SHA384 */ +#endif /* USE_SHA_MAC */ + +#ifdef USE_MD5 +#ifdef USE_MD5_MAC +/******************************************************************************/ +/* + TLS MD5 HMAC generate/verify +*/ +int32_t tlsHMACMd5(ssl_t *ssl, int32 mode, unsigned char type, + unsigned char *data, uint32 len, unsigned char *mac) +{ + psHmacMd5_t ctx; + unsigned char *key, *seq; + unsigned char majVer, minVer, tmp[5]; + int32 i; + + majVer = ssl->majVer; + minVer = ssl->minVer; + + if (mode == HMAC_CREATE) { + key = ssl->sec.writeMAC; + seq = ssl->sec.seq; + } else { /* HMAC_VERIFY */ + key = ssl->sec.readMAC; + seq = ssl->sec.remSeq; + } + /* Sanity */ + if (key == NULL) { + return PS_FAILURE; + } + + if (psHmacMd5Init(&ctx, key, MD5_HASH_SIZE) < 0) { + return PS_FAIL; + } +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (mode == HMAC_CREATE) { + psHmacMd5Update(&ctx, ssl->epoch, 2); + psHmacMd5Update(&ctx, ssl->rsn, 6); + } else { /* HMAC_VERIFY */ + psHmacMd5Update(&ctx, ssl->rec.epoch, 2); + psHmacMd5Update(&ctx, ssl->rec.rsn, 6); + } + } else { +#endif /* USE_DTLS */ + psHmacMd5Update(&ctx, seq, 8); + for (i = 7; i >= 0; i--) { + seq[i]++; + if (seq[i] != 0) { + break; + } + } +#ifdef USE_DTLS + } +#endif /* USE_DTLS */ + + tmp[0] = type; + tmp[1] = majVer; + tmp[2] = minVer; + tmp[3] = (len & 0xFF00) >> 8; + tmp[4] = len & 0xFF; + psHmacMd5Update(&ctx, tmp, 5); + psHmacMd5Update(&ctx, data, len); + psHmacMd5Final(&ctx, mac); + + return PS_SUCCESS; +} +#endif /* USE_MD5_MAC */ +#endif /* USE_MD5 */ +#endif /* USE_TLS */ + +int32 sslCreateKeys(ssl_t *ssl) +{ +#ifdef USE_TLS + if (ssl->flags & SSL_FLAGS_TLS) { + return tlsDeriveKeys(ssl); + } else { +#ifndef DISABLE_SSLV3 + return sslDeriveKeys(ssl); +#else + return PS_ARG_FAIL; +#endif /* DISABLE_SSLV3 */ + } +#else /* SSLv3 only below */ +#ifndef DISABLE_SSLV3 + return sslDeriveKeys(ssl); +#endif /* DISABLE_SSLV3 */ +#endif /* USE_TLS */ +} + +/******************************************************************************/ +/* + Cipher suites are chosen before they are activated with the + ChangeCipherSuite message. Additionally, the read and write cipher suites + are activated at different times in the handshake process. The following + APIs activate the selected cipher suite callback functions. +*/ +int32 sslActivateReadCipher(ssl_t *ssl) +{ + + ssl->decrypt = ssl->cipher->decrypt; + ssl->verifyMac = ssl->cipher->verifyMac; + ssl->nativeDeMacSize = ssl->cipher->macSize; + if (ssl->extFlags.truncated_hmac) { + if (ssl->cipher->macSize > 0) { /* Only for HMAC-based ciphers */ + ssl->deMacSize = 10; + } else { + ssl->deMacSize = ssl->cipher->macSize; + } + } else { + ssl->deMacSize = ssl->cipher->macSize; + } + ssl->deBlockSize = ssl->cipher->blockSize; + ssl->deIvSize = ssl->cipher->ivSize; +/* + Reset the expected incoming sequence number for the new suite +*/ + memset(ssl->sec.remSeq, 0x0, sizeof(ssl->sec.remSeq)); + + if (ssl->cipher->ident != SSL_NULL_WITH_NULL_NULL) { + /* Sanity */ + if (ssl->sec.rMACptr == NULL) { + psTraceInfo("sslActivateReadCipher sanity fail\n"); + return PS_FAILURE; + } + ssl->flags |= SSL_FLAGS_READ_SECURE; + +#ifdef USE_TLS_1_2 + if (ssl->deMacSize == 0) { + /* Need a concept for AEAD read and write start times for the + cases surrounding changeCipherSpec if moving from one suite + to another */ + ssl->flags |= SSL_FLAGS_AEAD_R; + if (ssl->cipher->flags & CRYPTO_FLAGS_CHACHA) { + ssl->flags &= ~SSL_FLAGS_NONCE_R; + } else { + ssl->flags |= SSL_FLAGS_NONCE_R; + } + } else { + ssl->flags &= ~SSL_FLAGS_AEAD_R; + ssl->flags &= ~SSL_FLAGS_NONCE_R; + } +#endif +/* + Copy the newly activated read keys into the live buffers +*/ + memcpy(ssl->sec.readMAC, ssl->sec.rMACptr, ssl->deMacSize); + memcpy(ssl->sec.readKey, ssl->sec.rKeyptr, ssl->cipher->keySize); + memcpy(ssl->sec.readIV, ssl->sec.rIVptr, ssl->cipher->ivSize); +/* + set up decrypt contexts +*/ + if (ssl->cipher->init) { + if (ssl->cipher->init(&(ssl->sec), INIT_DECRYPT_CIPHER, + ssl->cipher->keySize) < 0) { + psTraceInfo("Unable to initialize read cipher suite\n"); + return PS_FAILURE; + } + } + + } + return PS_SUCCESS; +} + +int32 sslActivateWriteCipher(ssl_t *ssl) +{ +#ifdef USE_DTLS + if (ssl->flags & SSL_FLAGS_DTLS) { + if (ssl->retransmit == 0) { + ssl->oencrypt = ssl->encrypt; + ssl->ogenerateMac = ssl->generateMac; + ssl->oenMacSize = ssl->enMacSize; + ssl->oenNativeHmacSize = ssl->nativeEnMacSize; + ssl->oenBlockSize = ssl->enBlockSize; + ssl->oenIvSize = ssl->enIvSize; + memcpy(ssl->owriteMAC, ssl->sec.writeMAC, ssl->enMacSize); + memcpy(&ssl->oencryptCtx, &ssl->sec.encryptCtx, + sizeof(psCipherContext_t)); + memcpy(ssl->owriteIV, ssl->sec.writeIV, ssl->cipher->ivSize); + } + } +#endif /* USE_DTLS */ + + ssl->encrypt = ssl->cipher->encrypt; + ssl->generateMac = ssl->cipher->generateMac; + ssl->nativeEnMacSize = ssl->cipher->macSize; + if (ssl->extFlags.truncated_hmac) { + if (ssl->cipher->macSize > 0) { /* Only for HMAC-based ciphers */ + ssl->enMacSize = 10; + } else { + ssl->enMacSize = ssl->cipher->macSize; + } + } else { + ssl->enMacSize = ssl->cipher->macSize; + } + ssl->enBlockSize = ssl->cipher->blockSize; + ssl->enIvSize = ssl->cipher->ivSize; +/* + Reset the outgoing sequence number for the new suite +*/ + memset(ssl->sec.seq, 0x0, sizeof(ssl->sec.seq)); + if (ssl->cipher->ident != SSL_NULL_WITH_NULL_NULL) { + ssl->flags |= SSL_FLAGS_WRITE_SECURE; + +#ifdef USE_TLS_1_2 + if (ssl->enMacSize == 0) { + /* Need a concept for AEAD read and write start times for the + cases surrounding changeCipherSpec if moving from one suite + to another */ + ssl->flags |= SSL_FLAGS_AEAD_W; + if (ssl->cipher->flags & CRYPTO_FLAGS_CHACHA) { + ssl->flags &= ~SSL_FLAGS_NONCE_W; + } else { + ssl->flags |= SSL_FLAGS_NONCE_W; + } + } else { + ssl->flags &= ~SSL_FLAGS_AEAD_W; + ssl->flags &= ~SSL_FLAGS_NONCE_W; + } +#endif + +/* + Copy the newly activated write keys into the live buffers +*/ + memcpy(ssl->sec.writeMAC, ssl->sec.wMACptr, ssl->enMacSize); + memcpy(ssl->sec.writeKey, ssl->sec.wKeyptr, ssl->cipher->keySize); + memcpy(ssl->sec.writeIV, ssl->sec.wIVptr, ssl->cipher->ivSize); +/* + set up encrypt contexts + */ + if (ssl->cipher->init) { + if (ssl->cipher->init(&(ssl->sec), INIT_ENCRYPT_CIPHER, + ssl->cipher->keySize) < 0) { + psTraceInfo("Unable to init write cipher suite\n"); + return PS_FAILURE; + } + } + } + return PS_SUCCESS; +} + +/******************************************************************************/ + + +#ifdef USE_CLIENT_SIDE_SSL +/******************************************************************************/ +/* + Allocate a tlsExtension_t structure +*/ +int32 matrixSslNewHelloExtension(tlsExtension_t **extension, void *userPoolPtr) +{ + psPool_t *pool = NULL; + tlsExtension_t *ext; + + + ext = psMalloc(pool, sizeof(tlsExtension_t)); + if (ext == NULL) { + return PS_MEM_FAIL; + } + memset(ext, 0x0, sizeof(tlsExtension_t)); + ext->pool = pool; + + *extension = ext; + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Free a tlsExtension_t structure and any extensions that have been loaded +*/ +void matrixSslDeleteHelloExtension(tlsExtension_t *extension) +{ + tlsExtension_t *next, *ext; + + if (extension == NULL) { + return; + } + ext = extension; + /* Free first one */ + if (ext->extData) { + psFree(ext->extData, ext->pool); + } + next = ext->next; + psFree(ext, ext->pool); + /* Free others */ + while (next) { + ext = next; + next = ext->next; + if (ext->extData) { + psFree(ext->extData, ext->pool); + } + psFree(ext, ext->pool); + } + return; +} + +/*****************************************************************************/ +/* + Add an outgoing CLIENT_HELLO extension to a tlsExtension_t structure + that was previously allocated with matrixSslNewHelloExtension +*/ +int32 matrixSslLoadHelloExtension(tlsExtension_t *ext, + unsigned char *extension, uint32 length, uint32 extType) +{ + tlsExtension_t *current, *new; + + if (ext == NULL || (length > 0 && extension == NULL)) { + return PS_ARG_FAIL; + } +/* + Find first empty spot in ext. This is determined by extLen since even + an empty extension will have a length of 1 for the 0 +*/ + current = ext; + while (current->extLen != 0) { + if (current->next != NULL) { + current = current->next; + continue; + } + new = psMalloc(ext->pool, sizeof(tlsExtension_t)); + if (new == NULL) { + return PS_MEM_FAIL; + } + memset(new, 0, sizeof(tlsExtension_t)); + new->pool = ext->pool; + current->next = new; + current = new; + } +/* + Supports an empty extension which is really a one byte 00: + ff 01 00 01 00 (two byte type, two byte len, one byte 00) + + This will either be passed in as a NULL 'extension' with a 0 length - OR - + A pointer to a one byte 0x0 and a length of 1. In either case, the + structure will identify the ext with a length of 1 and a NULL data ptr +*/ + current->extType = extType; + if (length > 0) { + current->extLen = length; + if (length == 1 && extension[0] == '\0') { + current->extLen = 1; + } else { + current->extData = psMalloc(ext->pool, length); + if (current->extData == NULL) { + return PS_MEM_FAIL; + } + memcpy(current->extData, extension, length); + } + } else if (length == 0) { + current->extLen = 1; + } + + return PS_SUCCESS; +} +#endif /* USE_CLIENT_SIDE_SSL */ + +/******************************************************************************/ + diff --git a/matrixssl/version.h b/matrixssl/version.h new file mode 100644 index 0000000..22cbfcb --- /dev/null +++ b/matrixssl/version.h @@ -0,0 +1,26 @@ +/** + * @file version.h + * @version + * + * Autogenerated version file. + */ +/* + Copyright 2016 INSIDE Secure Corporation +*/ +#ifndef _h_MATRIXSSL_VERSION +#define _h_MATRIXSSL_VERSION +#ifdef __cplusplus +extern "C" { +#endif + +#define MATRIXSSL_VERSION "3.8.3-OPEN" +#define MATRIXSSL_VERSION_MAJOR 3 +#define MATRIXSSL_VERSION_MINOR 8 +#define MATRIXSSL_VERSION_PATCH 3 +#define MATRIXSSL_VERSION_CODE "OPEN" + +#ifdef __cplusplus +} +#endif +#endif /* _h_MATRIXSSL_VERSION */ + diff --git a/testkeys/DH/1024_DH_PARAMS.h b/testkeys/DH/1024_DH_PARAMS.h new file mode 100644 index 0000000..ac328a6 --- /dev/null +++ b/testkeys/DH/1024_DH_PARAMS.h @@ -0,0 +1,40 @@ +/** + * @file 1024_DH_PARAMS.h + * @version $Format:%h%d$ + * + * Summary. + */ +/******************************************************************************/ +/* + In-Memory version of the PEM file 1024_DH_PARAMS.pem + + PKCS#3 DH Parameters: (1024 bit) + prime: + 00:97:f6:42:61:ca:b5:05:dd:28:28:e1:3f:1d:68: + b6:d3:db:d0:f3:13:04:7f:40:e8:56:da:58:cb:13: + b8:a1:bf:2b:78:3a:4c:6d:59:d5:f9:2a:fc:6c:ff: + 3d:69:3f:78:b2:3d:4f:31:60:a9:50:2e:3e:fa:f7: + ab:5e:1a:d5:a6:5e:55:43:13:82:8d:a8:3b:9f:f2: + d9:41:de:e9:56:89:fa:da:ea:09:36:ad:df:19:71: + fe:63:5b:20:af:47:03:64:60:3c:2d:e0:59:f5:4b: + 65:0a:d8:fa:0c:f7:01:21:c7:47:99:d7:58:71:32: + be:9b:99:9b:b9:b7:87:e8:ab + generator: 2 (0x2) +-----BEGIN DH PARAMETERS----- +MIGHAoGBAJf2QmHKtQXdKCjhPx1ottPb0PMTBH9A6FbaWMsTuKG/K3g6TG1Z1fkq +/Gz/PWk/eLI9TzFgqVAuPvr3q14a1aZeVUMTgo2oO5/y2UHe6VaJ+trqCTat3xlx +/mNbIK9HA2RgPC3gWfVLZQrY+gz3ASHHR5nXWHEyvpuZm7m3h+irAgEC +-----END DH PARAMETERS----- +*/ +#define DHPARAM1024_SIZE 138 +static const unsigned char DHPARAM1024[DHPARAM1024_SIZE] = + "\x30\x81\x87\x02\x81\x81\x00\x97\xf6\x42\x61\xca\xb5\x05\xdd\x28" + "\x28\xe1\x3f\x1d\x68\xb6\xd3\xdb\xd0\xf3\x13\x04\x7f\x40\xe8\x56" + "\xda\x58\xcb\x13\xb8\xa1\xbf\x2b\x78\x3a\x4c\x6d\x59\xd5\xf9\x2a" + "\xfc\x6c\xff\x3d\x69\x3f\x78\xb2\x3d\x4f\x31\x60\xa9\x50\x2e\x3e" + "\xfa\xf7\xab\x5e\x1a\xd5\xa6\x5e\x55\x43\x13\x82\x8d\xa8\x3b\x9f" + "\xf2\xd9\x41\xde\xe9\x56\x89\xfa\xda\xea\x09\x36\xad\xdf\x19\x71" + "\xfe\x63\x5b\x20\xaf\x47\x03\x64\x60\x3c\x2d\xe0\x59\xf5\x4b\x65" + "\x0a\xd8\xfa\x0c\xf7\x01\x21\xc7\x47\x99\xd7\x58\x71\x32\xbe\x9b" + "\x99\x9b\xb9\xb7\x87\xe8\xab\x02\x01\x02"; + diff --git a/testkeys/DH/1024_DH_PARAMS.pem b/testkeys/DH/1024_DH_PARAMS.pem new file mode 100644 index 0000000..81d43f6 --- /dev/null +++ b/testkeys/DH/1024_DH_PARAMS.pem @@ -0,0 +1,5 @@ +-----BEGIN DH PARAMETERS----- +MIGHAoGBAJf2QmHKtQXdKCjhPx1ottPb0PMTBH9A6FbaWMsTuKG/K3g6TG1Z1fkq +/Gz/PWk/eLI9TzFgqVAuPvr3q14a1aZeVUMTgo2oO5/y2UHe6VaJ+trqCTat3xlx +/mNbIK9HA2RgPC3gWfVLZQrY+gz3ASHHR5nXWHEyvpuZm7m3h+irAgEC +-----END DH PARAMETERS----- diff --git a/testkeys/DH/2048_DH_PARAMS.h b/testkeys/DH/2048_DH_PARAMS.h new file mode 100644 index 0000000..f45a1ef --- /dev/null +++ b/testkeys/DH/2048_DH_PARAMS.h @@ -0,0 +1,60 @@ +/** + * @file 2048_DH_PARAMS.h + * @version $Format:%h%d$ + * + * Summary. + */ +/******************************************************************************/ +/* + In-Memory version of the PEM file 2048_DH_PARAMS.pem + + PKCS#3 DH Parameters: (2048 bit) + prime: + 00:b9:bc:28:91:c7:08:c9:12:9b:7b:25:61:a9:4c: + a3:a1:45:10:76:ed:80:db:a9:bf:c5:7e:86:ff:8b: + f3:89:ff:79:ef:9d:d1:76:9b:ce:29:2f:c0:e4:a2: + f5:c2:c5:25:99:35:0c:a8:8b:9c:ec:e2:11:7b:17: + cd:ad:4f:fc:88:17:17:d8:65:12:ef:08:5a:62:a6: + 6f:06:b3:97:88:61:6d:32:55:97:ff:b6:80:9f:55: + 23:10:7d:2f:8a:2b:f9:9a:35:1f:cd:ab:98:2c:09: + 13:a1:1f:31:25:b8:09:a2:66:99:ff:5c:3b:15:58: + 85:d3:75:eb:ba:0c:c4:43:ef:58:f1:92:7c:c4:d7: + 37:00:8c:02:97:3f:49:c1:bc:9f:31:34:e0:d4:7a: + 3b:96:10:dc:4c:65:f6:7b:3a:15:f5:c0:8a:31:bc: + c6:6a:f4:61:02:1f:5f:a2:70:8d:aa:a7:0c:e4:f1: + aa:38:be:d2:87:d8:e4:a6:ff:a7:26:d6:28:36:87: + 01:13:7e:0c:52:2a:8f:9f:3b:3b:9e:66:28:c3:80: + d1:0e:4e:fb:f7:be:2e:6b:11:15:5d:85:a3:36:11: + 46:dc:7c:41:84:6c:fc:75:88:39:00:ea:b6:c8:5e: + fe:78:a9:92:f3:25:4a:08:e3:9c:93:fa:a9:3f:5f: + 7d:47 + generator: 5 (0x5) +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEAubwokccIyRKbeyVhqUyjoUUQdu2A26m/xX6G/4vzif95753RdpvO +KS/A5KL1wsUlmTUMqIuc7OIRexfNrU/8iBcX2GUS7whaYqZvBrOXiGFtMlWX/7aA +n1UjEH0viiv5mjUfzauYLAkToR8xJbgJomaZ/1w7FViF03XrugzEQ+9Y8ZJ8xNc3 +AIwClz9JwbyfMTTg1Ho7lhDcTGX2ezoV9cCKMbzGavRhAh9fonCNqqcM5PGqOL7S +h9jkpv+nJtYoNocBE34MUiqPnzs7nmYow4DRDk77974uaxEVXYWjNhFG3HxBhGz8 +dYg5AOq2yF7+eKmS8yVKCOOck/qpP199RwIBBQ== +-----END DH PARAMETERS----- +*/ +#define DHPARAM2048_SIZE 268 +static const unsigned char DHPARAM2048[DHPARAM2048_SIZE] = + "\x30\x82\x01\x08\x02\x82\x01\x01\x00\xb9\xbc\x28\x91\xc7\x08\xc9" + "\x12\x9b\x7b\x25\x61\xa9\x4c\xa3\xa1\x45\x10\x76\xed\x80\xdb\xa9" + "\xbf\xc5\x7e\x86\xff\x8b\xf3\x89\xff\x79\xef\x9d\xd1\x76\x9b\xce" + "\x29\x2f\xc0\xe4\xa2\xf5\xc2\xc5\x25\x99\x35\x0c\xa8\x8b\x9c\xec" + "\xe2\x11\x7b\x17\xcd\xad\x4f\xfc\x88\x17\x17\xd8\x65\x12\xef\x08" + "\x5a\x62\xa6\x6f\x06\xb3\x97\x88\x61\x6d\x32\x55\x97\xff\xb6\x80" + "\x9f\x55\x23\x10\x7d\x2f\x8a\x2b\xf9\x9a\x35\x1f\xcd\xab\x98\x2c" + "\x09\x13\xa1\x1f\x31\x25\xb8\x09\xa2\x66\x99\xff\x5c\x3b\x15\x58" + "\x85\xd3\x75\xeb\xba\x0c\xc4\x43\xef\x58\xf1\x92\x7c\xc4\xd7\x37" + "\x00\x8c\x02\x97\x3f\x49\xc1\xbc\x9f\x31\x34\xe0\xd4\x7a\x3b\x96" + "\x10\xdc\x4c\x65\xf6\x7b\x3a\x15\xf5\xc0\x8a\x31\xbc\xc6\x6a\xf4" + "\x61\x02\x1f\x5f\xa2\x70\x8d\xaa\xa7\x0c\xe4\xf1\xaa\x38\xbe\xd2" + "\x87\xd8\xe4\xa6\xff\xa7\x26\xd6\x28\x36\x87\x01\x13\x7e\x0c\x52" + "\x2a\x8f\x9f\x3b\x3b\x9e\x66\x28\xc3\x80\xd1\x0e\x4e\xfb\xf7\xbe" + "\x2e\x6b\x11\x15\x5d\x85\xa3\x36\x11\x46\xdc\x7c\x41\x84\x6c\xfc" + "\x75\x88\x39\x00\xea\xb6\xc8\x5e\xfe\x78\xa9\x92\xf3\x25\x4a\x08" + "\xe3\x9c\x93\xfa\xa9\x3f\x5f\x7d\x47\x02\x01\x05"; + diff --git a/testkeys/DH/2048_DH_PARAMS.pem b/testkeys/DH/2048_DH_PARAMS.pem new file mode 100644 index 0000000..05583f8 --- /dev/null +++ b/testkeys/DH/2048_DH_PARAMS.pem @@ -0,0 +1,8 @@ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEAubwokccIyRKbeyVhqUyjoUUQdu2A26m/xX6G/4vzif95753RdpvO +KS/A5KL1wsUlmTUMqIuc7OIRexfNrU/8iBcX2GUS7whaYqZvBrOXiGFtMlWX/7aA +n1UjEH0viiv5mjUfzauYLAkToR8xJbgJomaZ/1w7FViF03XrugzEQ+9Y8ZJ8xNc3 +AIwClz9JwbyfMTTg1Ho7lhDcTGX2ezoV9cCKMbzGavRhAh9fonCNqqcM5PGqOL7S +h9jkpv+nJtYoNocBE34MUiqPnzs7nmYow4DRDk77974uaxEVXYWjNhFG3HxBhGz8 +dYg5AOq2yF7+eKmS8yVKCOOck/qpP199RwIBBQ== +-----END DH PARAMETERS----- diff --git a/testkeys/DH/3072_DH_PARAMS.h b/testkeys/DH/3072_DH_PARAMS.h new file mode 100644 index 0000000..0e0665f --- /dev/null +++ b/testkeys/DH/3072_DH_PARAMS.h @@ -0,0 +1,47 @@ +/** + * @file dh3072.h + * @version $Format:%h%d$ + * + * Summary. + */ +/******************************************************************************/ +/* + In-Memory version of the PEM file dh3072.pem +*/ + +#define DHPARAM3072_SIZE 396 +static const unsigned char DHPARAM3072[DHPARAM3072_SIZE] = { + 0x30, 0x82, 0x01, 0x88, 0x02, 0x82, 0x01, 0x81, 0x00, 0xe3, 0x56, 0xbe, + 0x69, 0xb4, 0x3d, 0xfd, 0x5c, 0x15, 0x46, 0x45, 0x8a, 0x4f, 0x44, 0xbd, + 0x0c, 0x92, 0x52, 0x88, 0x24, 0xfd, 0x02, 0xdb, 0xa0, 0x64, 0x03, 0x02, + 0x17, 0x2e, 0xa5, 0xeb, 0x94, 0x71, 0x72, 0x54, 0x48, 0x5c, 0xa3, 0x7d, + 0x36, 0x3b, 0x6c, 0xeb, 0xf8, 0x39, 0x99, 0xb1, 0xd1, 0x80, 0xaf, 0xaf, + 0x56, 0xbe, 0xa0, 0x85, 0xdf, 0x79, 0x62, 0xd4, 0xf7, 0xc4, 0xe7, 0x32, + 0xb4, 0x79, 0x68, 0x44, 0xbc, 0xe7, 0x0e, 0x31, 0xd5, 0xc2, 0x58, 0x9e, + 0x31, 0xd9, 0xb8, 0x9a, 0xc9, 0xae, 0x09, 0xd5, 0x62, 0x5d, 0x7c, 0xff, + 0x4b, 0xd7, 0xcc, 0xc7, 0xca, 0x90, 0xf4, 0x9b, 0x23, 0x87, 0x46, 0xcd, + 0x28, 0x74, 0xd8, 0x7f, 0xfb, 0xc3, 0x21, 0xd0, 0x90, 0xd8, 0x1b, 0x3f, + 0xcc, 0x9c, 0x33, 0xdb, 0xb2, 0x27, 0x34, 0x0b, 0x84, 0xa7, 0x22, 0x0f, + 0x54, 0x8d, 0xfc, 0x78, 0x05, 0x0e, 0x35, 0x39, 0x2b, 0xc4, 0x62, 0xee, + 0xae, 0x27, 0xb0, 0xe9, 0xb2, 0xcd, 0x98, 0xbd, 0xba, 0xb9, 0x09, 0x99, + 0x02, 0xf7, 0xdf, 0x05, 0x85, 0x52, 0x57, 0x04, 0x41, 0xce, 0x97, 0x38, + 0xd2, 0x4f, 0xd0, 0xed, 0x1a, 0x1f, 0x2d, 0x44, 0x1a, 0x49, 0xfe, 0x3d, + 0xe3, 0xd2, 0x4f, 0x03, 0x26, 0xa9, 0x62, 0xa3, 0x52, 0x99, 0x0b, 0xad, + 0xac, 0xc1, 0x5b, 0x8a, 0xf4, 0xa2, 0xe5, 0x19, 0x84, 0xdd, 0xc5, 0x1b, + 0x64, 0x94, 0x6f, 0xa9, 0xca, 0x91, 0xa2, 0x20, 0x6a, 0x84, 0xb4, 0xac, + 0x75, 0xfe, 0x25, 0x2c, 0x6b, 0x5a, 0xc8, 0x47, 0x9b, 0xbe, 0x5f, 0x35, + 0xf7, 0x69, 0x76, 0xeb, 0xe6, 0x6c, 0x02, 0xce, 0x73, 0xff, 0x5c, 0x19, + 0xe8, 0x6a, 0xc3, 0x90, 0xcb, 0x88, 0x19, 0xd5, 0xe1, 0xb0, 0x6c, 0xaa, + 0xc0, 0x9b, 0x66, 0x9d, 0xf7, 0xb2, 0x59, 0x35, 0x4b, 0xad, 0x52, 0xfb, + 0x05, 0xe6, 0x2c, 0xbb, 0xa6, 0x1b, 0x2f, 0x83, 0x14, 0xba, 0x37, 0x61, + 0x14, 0xd5, 0x72, 0x2c, 0x94, 0x57, 0x3e, 0x60, 0xd4, 0x5c, 0x1f, 0xca, + 0x97, 0x8f, 0xd2, 0xe8, 0x47, 0xa8, 0x8b, 0x19, 0x26, 0xe0, 0xc2, 0xff, + 0xc4, 0x29, 0x60, 0xea, 0x5d, 0xc0, 0x10, 0x50, 0x4e, 0xb1, 0x2e, 0x2a, + 0xcf, 0xe2, 0x8c, 0xd8, 0x78, 0xe6, 0xab, 0x88, 0xa1, 0x1b, 0x72, 0xf5, + 0x3f, 0x9b, 0x7e, 0x0c, 0xaa, 0x8d, 0x1c, 0x35, 0xe9, 0x2b, 0x3e, 0x3e, + 0x77, 0x87, 0x40, 0x44, 0x97, 0xb0, 0xf4, 0x8d, 0x68, 0x77, 0xb6, 0x00, + 0x79, 0x34, 0xa3, 0x4a, 0x8a, 0xad, 0xf3, 0xc6, 0x67, 0x66, 0x5f, 0xb1, + 0x73, 0x2f, 0x8a, 0x30, 0x77, 0x62, 0x0d, 0x35, 0xb0, 0x89, 0x66, 0x3b, + 0xb1, 0x17, 0x43, 0x0a, 0x56, 0x80, 0x1f, 0x1a, 0xf3, 0xe3, 0x00, 0x9e, + 0xcd, 0x49, 0xbb, 0x5b, 0x08, 0xc4, 0x3a, 0x60, 0x73, 0x02, 0x01, 0x02 + }; diff --git a/testkeys/DH/3072_DH_PARAMS.pem b/testkeys/DH/3072_DH_PARAMS.pem new file mode 100644 index 0000000..cb97ba7 --- /dev/null +++ b/testkeys/DH/3072_DH_PARAMS.pem @@ -0,0 +1,11 @@ +-----BEGIN DH PARAMETERS----- +MIIBiAKCAYEA41a+abQ9/VwVRkWKT0S9DJJSiCT9AtugZAMCFy6l65RxclRIXKN9 +Njts6/g5mbHRgK+vVr6ghd95YtT3xOcytHloRLznDjHVwlieMdm4msmuCdViXXz/ +S9fMx8qQ9Jsjh0bNKHTYf/vDIdCQ2Bs/zJwz27InNAuEpyIPVI38eAUONTkrxGLu +riew6bLNmL26uQmZAvffBYVSVwRBzpc40k/Q7RofLUQaSf4949JPAyapYqNSmQut +rMFbivSi5RmE3cUbZJRvqcqRoiBqhLSsdf4lLGtayEebvl8192l26+ZsAs5z/1wZ +6GrDkMuIGdXhsGyqwJtmnfeyWTVLrVL7BeYsu6YbL4MUujdhFNVyLJRXPmDUXB/K +l4/S6Eeoixkm4ML/xClg6l3AEFBOsS4qz+KM2Hjmq4ihG3L1P5t+DKqNHDXpKz4+ +d4dARJew9I1od7YAeTSjSoqt88ZnZl+xcy+KMHdiDTWwiWY7sRdDClaAHxrz4wCe +zUm7WwjEOmBzAgEC +-----END DH PARAMETERS----- diff --git a/testkeys/DH/4096_DH_PARAMS.h b/testkeys/DH/4096_DH_PARAMS.h new file mode 100644 index 0000000..ab63292 --- /dev/null +++ b/testkeys/DH/4096_DH_PARAMS.h @@ -0,0 +1,98 @@ +/** + * @file 4096_DH_PARAMS.h + * @version $Format:%h%d$ + * + * Summary. + */ +/******************************************************************************/ +/* + In-Memory version of the PEM file 4096_DH_PARAMS.pem + + PKCS#3 DH Parameters: (4096 bit) + prime: + 00:d7:c5:a2:23:9e:04:e3:81:63:51:70:6b:25:b3: + d6:2b:28:33:2e:7a:9b:ae:36:90:24:e7:d2:85:26: + 95:e2:e7:3a:68:fb:6f:4c:c3:94:30:aa:65:33:8c: + 71:f5:d7:5a:31:61:0b:8d:f5:c4:a3:98:31:61:d5: + 8f:f3:4a:40:41:bc:ac:cf:02:4e:96:61:8e:f1:38: + d4:e0:7a:b0:40:a9:fc:ce:25:57:e2:8d:d3:c1:50: + 7b:d4:d6:cb:90:9a:89:ca:03:09:ea:fd:5a:d9:97: + 2b:d4:40:b6:a5:7d:2d:f7:08:fe:bb:3e:cb:8c:27: + f9:ce:c8:c8:4f:6a:4c:64:65:ed:0e:9e:ee:9e:5c: + a2:fd:e8:c0:08:27:96:23:44:18:32:4a:f4:c5:c6: + 44:41:24:ff:bd:e2:e5:a5:b2:a6:1b:5b:fa:b6:14: + b5:5b:35:4b:8b:50:51:2f:5d:0e:ef:6e:62:4d:dc: + 14:e0:f0:4a:1d:2a:b7:27:41:dd:f2:1c:53:d6:d2: + 65:cf:57:c1:cc:2d:7d:dc:c6:72:b2:0c:2e:bb:10: + 7e:5a:53:16:1a:ee:24:bd:41:53:3c:e3:5a:a7:9a: + 70:36:3a:e7:dc:28:bd:d7:85:63:ca:7b:81:50:71: + bf:c9:5d:e7:70:6b:58:f4:4e:fd:d6:f7:df:76:5f: + 77:03:73:66:07:90:bb:62:3a:e8:43:da:d3:fd:f0: + 3c:14:eb:03:01:1e:d6:e5:af:a1:7a:11:e4:72:08: + 53:86:f0:49:7c:95:1d:ac:d2:ec:33:e2:b5:23:67: + 5c:a3:df:83:6c:70:99:66:92:22:75:fb:6d:26:c9: + 9e:88:33:ae:ee:12:cf:dd:e3:3f:12:5f:5c:35:11: + fc:91:e4:4b:d8:4c:b1:b5:d4:e9:a4:df:dd:e9:ff: + 68:a7:12:ff:04:6a:97:7c:9e:20:6c:5b:0c:09:4e: + 94:47:dc:7d:e4:32:74:8b:05:c7:e9:0e:5b:a8:62: + d0:c5:72:1b:9a:53:ed:1d:e2:8a:98:fd:ba:d5:d7: + 75:45:3f:6d:14:67:b2:9a:eb:83:fc:88:d0:30:8e: + e8:79:60:b7:0e:b1:19:9e:4a:ee:61:c6:87:0f:f6: + e6:f9:0c:d9:d8:b7:74:2f:27:6c:06:ca:02:8c:4f: + 76:5c:ee:ca:fc:9e:63:0b:2e:b9:64:9f:5b:35:d5: + 8b:2d:0a:21:24:db:2b:09:df:50:d4:8b:6c:e4:fa: + 99:ce:7c:79:d7:e8:17:aa:a8:7d:42:b0:cc:d2:8b: + 8d:4d:0d:c3:5d:e1:21:a6:6d:fb:b4:12:35:8e:f3: + 8e:9c:69:2b:34:39:f9:3c:d7:7b:49:df:43:0a:a9: + 24:b2:23 + generator: 2 (0x2) +-----BEGIN DH PARAMETERS----- +MIICCAKCAgEA18WiI54E44FjUXBrJbPWKygzLnqbrjaQJOfShSaV4uc6aPtvTMOU +MKplM4xx9ddaMWELjfXEo5gxYdWP80pAQbyszwJOlmGO8TjU4HqwQKn8ziVX4o3T +wVB71NbLkJqJygMJ6v1a2Zcr1EC2pX0t9wj+uz7LjCf5zsjIT2pMZGXtDp7unlyi +/ejACCeWI0QYMkr0xcZEQST/veLlpbKmG1v6thS1WzVLi1BRL10O725iTdwU4PBK +HSq3J0Hd8hxT1tJlz1fBzC193MZysgwuuxB+WlMWGu4kvUFTPONap5pwNjrn3Ci9 +14VjynuBUHG/yV3ncGtY9E791vffdl93A3NmB5C7YjroQ9rT/fA8FOsDAR7W5a+h +ehHkcghThvBJfJUdrNLsM+K1I2dco9+DbHCZZpIidfttJsmeiDOu7hLP3eM/El9c +NRH8keRL2EyxtdTppN/d6f9opxL/BGqXfJ4gbFsMCU6UR9x95DJ0iwXH6Q5bqGLQ +xXIbmlPtHeKKmP261dd1RT9tFGeymuuD/IjQMI7oeWC3DrEZnkruYcaHD/bm+QzZ +2Ld0LydsBsoCjE92XO7K/J5jCy65ZJ9bNdWLLQohJNsrCd9Q1Its5PqZznx51+gX +qqh9QrDM0ouNTQ3DXeEhpm37tBI1jvOOnGkrNDn5PNd7Sd9DCqkksiMCAQI= +-----END DH PARAMETERS----- +*/ +#define DHPARAM4096_SIZE 524 +static const unsigned char DHPARAM4096[DHPARAM4096_SIZE] = + "\x30\x82\x02\x08\x02\x82\x02\x01\x00\xd7\xc5\xa2\x23\x9e\x04\xe3" + "\x81\x63\x51\x70\x6b\x25\xb3\xd6\x2b\x28\x33\x2e\x7a\x9b\xae\x36" + "\x90\x24\xe7\xd2\x85\x26\x95\xe2\xe7\x3a\x68\xfb\x6f\x4c\xc3\x94" + "\x30\xaa\x65\x33\x8c\x71\xf5\xd7\x5a\x31\x61\x0b\x8d\xf5\xc4\xa3" + "\x98\x31\x61\xd5\x8f\xf3\x4a\x40\x41\xbc\xac\xcf\x02\x4e\x96\x61" + "\x8e\xf1\x38\xd4\xe0\x7a\xb0\x40\xa9\xfc\xce\x25\x57\xe2\x8d\xd3" + "\xc1\x50\x7b\xd4\xd6\xcb\x90\x9a\x89\xca\x03\x09\xea\xfd\x5a\xd9" + "\x97\x2b\xd4\x40\xb6\xa5\x7d\x2d\xf7\x08\xfe\xbb\x3e\xcb\x8c\x27" + "\xf9\xce\xc8\xc8\x4f\x6a\x4c\x64\x65\xed\x0e\x9e\xee\x9e\x5c\xa2" + "\xfd\xe8\xc0\x08\x27\x96\x23\x44\x18\x32\x4a\xf4\xc5\xc6\x44\x41" + "\x24\xff\xbd\xe2\xe5\xa5\xb2\xa6\x1b\x5b\xfa\xb6\x14\xb5\x5b\x35" + "\x4b\x8b\x50\x51\x2f\x5d\x0e\xef\x6e\x62\x4d\xdc\x14\xe0\xf0\x4a" + "\x1d\x2a\xb7\x27\x41\xdd\xf2\x1c\x53\xd6\xd2\x65\xcf\x57\xc1\xcc" + "\x2d\x7d\xdc\xc6\x72\xb2\x0c\x2e\xbb\x10\x7e\x5a\x53\x16\x1a\xee" + "\x24\xbd\x41\x53\x3c\xe3\x5a\xa7\x9a\x70\x36\x3a\xe7\xdc\x28\xbd" + "\xd7\x85\x63\xca\x7b\x81\x50\x71\xbf\xc9\x5d\xe7\x70\x6b\x58\xf4" + "\x4e\xfd\xd6\xf7\xdf\x76\x5f\x77\x03\x73\x66\x07\x90\xbb\x62\x3a" + "\xe8\x43\xda\xd3\xfd\xf0\x3c\x14\xeb\x03\x01\x1e\xd6\xe5\xaf\xa1" + "\x7a\x11\xe4\x72\x08\x53\x86\xf0\x49\x7c\x95\x1d\xac\xd2\xec\x33" + "\xe2\xb5\x23\x67\x5c\xa3\xdf\x83\x6c\x70\x99\x66\x92\x22\x75\xfb" + "\x6d\x26\xc9\x9e\x88\x33\xae\xee\x12\xcf\xdd\xe3\x3f\x12\x5f\x5c" + "\x35\x11\xfc\x91\xe4\x4b\xd8\x4c\xb1\xb5\xd4\xe9\xa4\xdf\xdd\xe9" + "\xff\x68\xa7\x12\xff\x04\x6a\x97\x7c\x9e\x20\x6c\x5b\x0c\x09\x4e" + "\x94\x47\xdc\x7d\xe4\x32\x74\x8b\x05\xc7\xe9\x0e\x5b\xa8\x62\xd0" + "\xc5\x72\x1b\x9a\x53\xed\x1d\xe2\x8a\x98\xfd\xba\xd5\xd7\x75\x45" + "\x3f\x6d\x14\x67\xb2\x9a\xeb\x83\xfc\x88\xd0\x30\x8e\xe8\x79\x60" + "\xb7\x0e\xb1\x19\x9e\x4a\xee\x61\xc6\x87\x0f\xf6\xe6\xf9\x0c\xd9" + "\xd8\xb7\x74\x2f\x27\x6c\x06\xca\x02\x8c\x4f\x76\x5c\xee\xca\xfc" + "\x9e\x63\x0b\x2e\xb9\x64\x9f\x5b\x35\xd5\x8b\x2d\x0a\x21\x24\xdb" + "\x2b\x09\xdf\x50\xd4\x8b\x6c\xe4\xfa\x99\xce\x7c\x79\xd7\xe8\x17" + "\xaa\xa8\x7d\x42\xb0\xcc\xd2\x8b\x8d\x4d\x0d\xc3\x5d\xe1\x21\xa6" + "\x6d\xfb\xb4\x12\x35\x8e\xf3\x8e\x9c\x69\x2b\x34\x39\xf9\x3c\xd7" + "\x7b\x49\xdf\x43\x0a\xa9\x24\xb2\x23\x02\x01\x02"; + diff --git a/testkeys/DH/4096_DH_PARAMS.pem b/testkeys/DH/4096_DH_PARAMS.pem new file mode 100644 index 0000000..ecc8211 --- /dev/null +++ b/testkeys/DH/4096_DH_PARAMS.pem @@ -0,0 +1,13 @@ +-----BEGIN DH PARAMETERS----- +MIICCAKCAgEA18WiI54E44FjUXBrJbPWKygzLnqbrjaQJOfShSaV4uc6aPtvTMOU +MKplM4xx9ddaMWELjfXEo5gxYdWP80pAQbyszwJOlmGO8TjU4HqwQKn8ziVX4o3T +wVB71NbLkJqJygMJ6v1a2Zcr1EC2pX0t9wj+uz7LjCf5zsjIT2pMZGXtDp7unlyi +/ejACCeWI0QYMkr0xcZEQST/veLlpbKmG1v6thS1WzVLi1BRL10O725iTdwU4PBK +HSq3J0Hd8hxT1tJlz1fBzC193MZysgwuuxB+WlMWGu4kvUFTPONap5pwNjrn3Ci9 +14VjynuBUHG/yV3ncGtY9E791vffdl93A3NmB5C7YjroQ9rT/fA8FOsDAR7W5a+h +ehHkcghThvBJfJUdrNLsM+K1I2dco9+DbHCZZpIidfttJsmeiDOu7hLP3eM/El9c +NRH8keRL2EyxtdTppN/d6f9opxL/BGqXfJ4gbFsMCU6UR9x95DJ0iwXH6Q5bqGLQ +xXIbmlPtHeKKmP261dd1RT9tFGeymuuD/IjQMI7oeWC3DrEZnkruYcaHD/bm+QzZ +2Ld0LydsBsoCjE92XO7K/J5jCy65ZJ9bNdWLLQohJNsrCd9Q1Its5PqZznx51+gX +qqh9QrDM0ouNTQ3DXeEhpm37tBI1jvOOnGkrNDn5PNd7Sd9DCqkksiMCAQI= +-----END DH PARAMETERS----- diff --git a/testkeys/DH/dh1024.h b/testkeys/DH/dh1024.h new file mode 100644 index 0000000..dcb4ac8 --- /dev/null +++ b/testkeys/DH/dh1024.h @@ -0,0 +1,22 @@ +/** + * @file dh1024.h + * @version $Format:%h%d$ + * + * Summary. + */ +/******************************************************************************/ +/* + In-Memory version of the PEM file dh1024.pem +*/ +unsigned char dhParamBuf1024[] = {0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x97, +0xf6, 0x42, 0x61, 0xca, 0xb5, 0x05, 0xdd, 0x28, 0x28, 0xe1, 0x3f, 0x1d, 0x68, +0xb6, 0xd3, 0xdb, 0xd0, 0xf3, 0x13, 0x04, 0x7f, 0x40, 0xe8, 0x56, 0xda, 0x58, +0xcb, 0x13, 0xb8, 0xa1, 0xbf, 0x2b, 0x78, 0x3a, 0x4c, 0x6d, 0x59, 0xd5, 0xf9, +0x2a, 0xfc, 0x6c, 0xff, 0x3d, 0x69, 0x3f, 0x78, 0xb2, 0x3d, 0x4f, 0x31, 0x60, +0xa9, 0x50, 0x2e, 0x3e, 0xfa, 0xf7, 0xab, 0x5e, 0x1a, 0xd5, 0xa6, 0x5e, 0x55, +0x43, 0x13, 0x82, 0x8d, 0xa8, 0x3b, 0x9f, 0xf2, 0xd9, 0x41, 0xde, 0xe9, 0x56, +0x89, 0xfa, 0xda, 0xea, 0x09, 0x36, 0xad, 0xdf, 0x19, 0x71, 0xfe, 0x63, 0x5b, +0x20, 0xaf, 0x47, 0x03, 0x64, 0x60, 0x3c, 0x2d, 0xe0, 0x59, 0xf5, 0x4b, 0x65, +0x0a, 0xd8, 0xfa, 0x0c, 0xf7, 0x01, 0x21, 0xc7, 0x47, 0x99, 0xd7, 0x58, 0x71, +0x32, 0xbe, 0x9b, 0x99, 0x9b, 0xb9, 0xb7, 0x87, 0xe8, 0xab, 0x02, 0x01, 0x02}; + diff --git a/testkeys/DH/dh1024.pem b/testkeys/DH/dh1024.pem new file mode 100644 index 0000000..81d43f6 --- /dev/null +++ b/testkeys/DH/dh1024.pem @@ -0,0 +1,5 @@ +-----BEGIN DH PARAMETERS----- +MIGHAoGBAJf2QmHKtQXdKCjhPx1ottPb0PMTBH9A6FbaWMsTuKG/K3g6TG1Z1fkq +/Gz/PWk/eLI9TzFgqVAuPvr3q14a1aZeVUMTgo2oO5/y2UHe6VaJ+trqCTat3xlx +/mNbIK9HA2RgPC3gWfVLZQrY+gz3ASHHR5nXWHEyvpuZm7m3h+irAgEC +-----END DH PARAMETERS----- diff --git a/testkeys/DH/dh2048.h b/testkeys/DH/dh2048.h new file mode 100644 index 0000000..743ca60 --- /dev/null +++ b/testkeys/DH/dh2048.h @@ -0,0 +1,32 @@ +/** + * @file dh2048.h + * @version $Format:%h%d$ + * + * Summary. + */ +/******************************************************************************/ +/* + In-Memory version of the PEM file dh2048.pem +*/ +unsigned char dhParamBuf2048[] = {0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, +0x00, 0xb9, 0xbc, 0x28, 0x91, 0xc7, 0x08, 0xc9, 0x12, 0x9b, 0x7b, 0x25, 0x61, +0xa9, 0x4c, 0xa3, 0xa1, 0x45, 0x10, 0x76, 0xed, 0x80, 0xdb, 0xa9, 0xbf, 0xc5, +0x7e, 0x86, 0xff, 0x8b, 0xf3, 0x89, 0xff, 0x79, 0xef, 0x9d, 0xd1, 0x76, 0x9b, +0xce, 0x29, 0x2f, 0xc0, 0xe4, 0xa2, 0xf5, 0xc2, 0xc5, 0x25, 0x99, 0x35, 0x0c, +0xa8, 0x8b, 0x9c, 0xec, 0xe2, 0x11, 0x7b, 0x17, 0xcd, 0xad, 0x4f, 0xfc, 0x88, +0x17, 0x17, 0xd8, 0x65, 0x12, 0xef, 0x08, 0x5a, 0x62, 0xa6, 0x6f, 0x06, 0xb3, +0x97, 0x88, 0x61, 0x6d, 0x32, 0x55, 0x97, 0xff, 0xb6, 0x80, 0x9f, 0x55, 0x23, +0x10, 0x7d, 0x2f, 0x8a, 0x2b, 0xf9, 0x9a, 0x35, 0x1f, 0xcd, 0xab, 0x98, 0x2c, +0x09, 0x13, 0xa1, 0x1f, 0x31, 0x25, 0xb8, 0x09, 0xa2, 0x66, 0x99, 0xff, 0x5c, +0x3b, 0x15, 0x58, 0x85, 0xd3, 0x75, 0xeb, 0xba, 0x0c, 0xc4, 0x43, 0xef, 0x58, +0xf1, 0x92, 0x7c, 0xc4, 0xd7, 0x37, 0x00, 0x8c, 0x02, 0x97, 0x3f, 0x49, 0xc1, +0xbc, 0x9f, 0x31, 0x34, 0xe0, 0xd4, 0x7a, 0x3b, 0x96, 0x10, 0xdc, 0x4c, 0x65, +0xf6, 0x7b, 0x3a, 0x15, 0xf5, 0xc0, 0x8a, 0x31, 0xbc, 0xc6, 0x6a, 0xf4, 0x61, +0x02, 0x1f, 0x5f, 0xa2, 0x70, 0x8d, 0xaa, 0xa7, 0x0c, 0xe4, 0xf1, 0xaa, 0x38, +0xbe, 0xd2, 0x87, 0xd8, 0xe4, 0xa6, 0xff, 0xa7, 0x26, 0xd6, 0x28, 0x36, 0x87, +0x01, 0x13, 0x7e, 0x0c, 0x52, 0x2a, 0x8f, 0x9f, 0x3b, 0x3b, 0x9e, 0x66, 0x28, +0xc3, 0x80, 0xd1, 0x0e, 0x4e, 0xfb, 0xf7, 0xbe, 0x2e, 0x6b, 0x11, 0x15, 0x5d, +0x85, 0xa3, 0x36, 0x11, 0x46, 0xdc, 0x7c, 0x41, 0x84, 0x6c, 0xfc, 0x75, 0x88, +0x39, 0x00, 0xea, 0xb6, 0xc8, 0x5e, 0xfe, 0x78, 0xa9, 0x92, 0xf3, 0x25, 0x4a, +0x08, 0xe3, 0x9c, 0x93, 0xfa, 0xa9, 0x3f, 0x5f, 0x7d, 0x47, 0x02, 0x01, 0x05}; + diff --git a/testkeys/DH/dh2048.pem b/testkeys/DH/dh2048.pem new file mode 100644 index 0000000..05583f8 --- /dev/null +++ b/testkeys/DH/dh2048.pem @@ -0,0 +1,8 @@ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEAubwokccIyRKbeyVhqUyjoUUQdu2A26m/xX6G/4vzif95753RdpvO +KS/A5KL1wsUlmTUMqIuc7OIRexfNrU/8iBcX2GUS7whaYqZvBrOXiGFtMlWX/7aA +n1UjEH0viiv5mjUfzauYLAkToR8xJbgJomaZ/1w7FViF03XrugzEQ+9Y8ZJ8xNc3 +AIwClz9JwbyfMTTg1Ho7lhDcTGX2ezoV9cCKMbzGavRhAh9fonCNqqcM5PGqOL7S +h9jkpv+nJtYoNocBE34MUiqPnzs7nmYow4DRDk77974uaxEVXYWjNhFG3HxBhGz8 +dYg5AOq2yF7+eKmS8yVKCOOck/qpP199RwIBBQ== +-----END DH PARAMETERS----- diff --git a/testkeys/DH/dh2048_2.pem b/testkeys/DH/dh2048_2.pem new file mode 100644 index 0000000..b344231 --- /dev/null +++ b/testkeys/DH/dh2048_2.pem @@ -0,0 +1,8 @@ +-----BEGIN DH PARAMETERS----- +MIIBCwKCAQEAubwokccIyRKbeyVhqUyjoUUQdu2A26m/xX6G/4vzif95753RdpvO +KS/A5KL1wsUlmTUMqIuc7OIRexfNrU/8iBcX2GUS7whaYqZvBrOXiGFtMlWX/7aA +n1UjEH0viiv5mjUfzauYLAkToR8xJbgJomaZ/1w7FViF03XrugzEQ+9Y8ZJ8xNc3 +AIwClz9JwbyfMTTg1Ho7lhDcTGX2ezoV9cCKMbzGavRhAh9fonCNqqcM5PGqOL7S +h9jkpv+nJtYoNocBE34MUiqPnzs7nmYow4DRDk77974uaxEVXYWjNhFG3HxBhGz8 +dYg5AOq2yF7+eKmS8yVKCOOck/qpP199RwIEf////w== +-----END DH PARAMETERS----- diff --git a/testkeys/DH/dh3072.h b/testkeys/DH/dh3072.h new file mode 100644 index 0000000..d0de69b --- /dev/null +++ b/testkeys/DH/dh3072.h @@ -0,0 +1,45 @@ +/** + * @file dh3072.h + * @version $Format:%h%d$ + * + * Summary. + */ +/******************************************************************************/ +/* + In-Memory version of the PEM file dh3072.pem +*/ +static const unsigned char dhParamBuf3072[] = { + 0x30, 0x82, 0x01, 0x88, 0x02, 0x82, 0x01, 0x81, 0x00, 0xe3, 0x56, 0xbe, + 0x69, 0xb4, 0x3d, 0xfd, 0x5c, 0x15, 0x46, 0x45, 0x8a, 0x4f, 0x44, 0xbd, + 0x0c, 0x92, 0x52, 0x88, 0x24, 0xfd, 0x02, 0xdb, 0xa0, 0x64, 0x03, 0x02, + 0x17, 0x2e, 0xa5, 0xeb, 0x94, 0x71, 0x72, 0x54, 0x48, 0x5c, 0xa3, 0x7d, + 0x36, 0x3b, 0x6c, 0xeb, 0xf8, 0x39, 0x99, 0xb1, 0xd1, 0x80, 0xaf, 0xaf, + 0x56, 0xbe, 0xa0, 0x85, 0xdf, 0x79, 0x62, 0xd4, 0xf7, 0xc4, 0xe7, 0x32, + 0xb4, 0x79, 0x68, 0x44, 0xbc, 0xe7, 0x0e, 0x31, 0xd5, 0xc2, 0x58, 0x9e, + 0x31, 0xd9, 0xb8, 0x9a, 0xc9, 0xae, 0x09, 0xd5, 0x62, 0x5d, 0x7c, 0xff, + 0x4b, 0xd7, 0xcc, 0xc7, 0xca, 0x90, 0xf4, 0x9b, 0x23, 0x87, 0x46, 0xcd, + 0x28, 0x74, 0xd8, 0x7f, 0xfb, 0xc3, 0x21, 0xd0, 0x90, 0xd8, 0x1b, 0x3f, + 0xcc, 0x9c, 0x33, 0xdb, 0xb2, 0x27, 0x34, 0x0b, 0x84, 0xa7, 0x22, 0x0f, + 0x54, 0x8d, 0xfc, 0x78, 0x05, 0x0e, 0x35, 0x39, 0x2b, 0xc4, 0x62, 0xee, + 0xae, 0x27, 0xb0, 0xe9, 0xb2, 0xcd, 0x98, 0xbd, 0xba, 0xb9, 0x09, 0x99, + 0x02, 0xf7, 0xdf, 0x05, 0x85, 0x52, 0x57, 0x04, 0x41, 0xce, 0x97, 0x38, + 0xd2, 0x4f, 0xd0, 0xed, 0x1a, 0x1f, 0x2d, 0x44, 0x1a, 0x49, 0xfe, 0x3d, + 0xe3, 0xd2, 0x4f, 0x03, 0x26, 0xa9, 0x62, 0xa3, 0x52, 0x99, 0x0b, 0xad, + 0xac, 0xc1, 0x5b, 0x8a, 0xf4, 0xa2, 0xe5, 0x19, 0x84, 0xdd, 0xc5, 0x1b, + 0x64, 0x94, 0x6f, 0xa9, 0xca, 0x91, 0xa2, 0x20, 0x6a, 0x84, 0xb4, 0xac, + 0x75, 0xfe, 0x25, 0x2c, 0x6b, 0x5a, 0xc8, 0x47, 0x9b, 0xbe, 0x5f, 0x35, + 0xf7, 0x69, 0x76, 0xeb, 0xe6, 0x6c, 0x02, 0xce, 0x73, 0xff, 0x5c, 0x19, + 0xe8, 0x6a, 0xc3, 0x90, 0xcb, 0x88, 0x19, 0xd5, 0xe1, 0xb0, 0x6c, 0xaa, + 0xc0, 0x9b, 0x66, 0x9d, 0xf7, 0xb2, 0x59, 0x35, 0x4b, 0xad, 0x52, 0xfb, + 0x05, 0xe6, 0x2c, 0xbb, 0xa6, 0x1b, 0x2f, 0x83, 0x14, 0xba, 0x37, 0x61, + 0x14, 0xd5, 0x72, 0x2c, 0x94, 0x57, 0x3e, 0x60, 0xd4, 0x5c, 0x1f, 0xca, + 0x97, 0x8f, 0xd2, 0xe8, 0x47, 0xa8, 0x8b, 0x19, 0x26, 0xe0, 0xc2, 0xff, + 0xc4, 0x29, 0x60, 0xea, 0x5d, 0xc0, 0x10, 0x50, 0x4e, 0xb1, 0x2e, 0x2a, + 0xcf, 0xe2, 0x8c, 0xd8, 0x78, 0xe6, 0xab, 0x88, 0xa1, 0x1b, 0x72, 0xf5, + 0x3f, 0x9b, 0x7e, 0x0c, 0xaa, 0x8d, 0x1c, 0x35, 0xe9, 0x2b, 0x3e, 0x3e, + 0x77, 0x87, 0x40, 0x44, 0x97, 0xb0, 0xf4, 0x8d, 0x68, 0x77, 0xb6, 0x00, + 0x79, 0x34, 0xa3, 0x4a, 0x8a, 0xad, 0xf3, 0xc6, 0x67, 0x66, 0x5f, 0xb1, + 0x73, 0x2f, 0x8a, 0x30, 0x77, 0x62, 0x0d, 0x35, 0xb0, 0x89, 0x66, 0x3b, + 0xb1, 0x17, 0x43, 0x0a, 0x56, 0x80, 0x1f, 0x1a, 0xf3, 0xe3, 0x00, 0x9e, + 0xcd, 0x49, 0xbb, 0x5b, 0x08, 0xc4, 0x3a, 0x60, 0x73, 0x02, 0x01, 0x02 + }; diff --git a/testkeys/DH/dh3072.pem b/testkeys/DH/dh3072.pem new file mode 100644 index 0000000..cb97ba7 --- /dev/null +++ b/testkeys/DH/dh3072.pem @@ -0,0 +1,11 @@ +-----BEGIN DH PARAMETERS----- +MIIBiAKCAYEA41a+abQ9/VwVRkWKT0S9DJJSiCT9AtugZAMCFy6l65RxclRIXKN9 +Njts6/g5mbHRgK+vVr6ghd95YtT3xOcytHloRLznDjHVwlieMdm4msmuCdViXXz/ +S9fMx8qQ9Jsjh0bNKHTYf/vDIdCQ2Bs/zJwz27InNAuEpyIPVI38eAUONTkrxGLu +riew6bLNmL26uQmZAvffBYVSVwRBzpc40k/Q7RofLUQaSf4949JPAyapYqNSmQut +rMFbivSi5RmE3cUbZJRvqcqRoiBqhLSsdf4lLGtayEebvl8192l26+ZsAs5z/1wZ +6GrDkMuIGdXhsGyqwJtmnfeyWTVLrVL7BeYsu6YbL4MUujdhFNVyLJRXPmDUXB/K +l4/S6Eeoixkm4ML/xClg6l3AEFBOsS4qz+KM2Hjmq4ihG3L1P5t+DKqNHDXpKz4+ +d4dARJew9I1od7YAeTSjSoqt88ZnZl+xcy+KMHdiDTWwiWY7sRdDClaAHxrz4wCe +zUm7WwjEOmBzAgEC +-----END DH PARAMETERS----- diff --git a/testkeys/DH/dh512.h b/testkeys/DH/dh512.h new file mode 100644 index 0000000..ae24818 --- /dev/null +++ b/testkeys/DH/dh512.h @@ -0,0 +1,17 @@ +/** + * @file dh512.h + * @version $Format:%h%d$ + * + * Summary. + */ +/******************************************************************************/ +/* + In-Memory version of the PEM file dh512.pem +*/ +unsigned char dhParamBuf512[] = {0x30, 0x46, 0x02, 0x41, 0x00, 0xf1, 0x52, 0xab, +0xcb, 0x74, 0x04, 0x7e, 0x3f, 0x24, 0xa3, 0x87, 0x2b, 0x68, 0xb5, 0xd0, 0xef, +0xd5, 0x43, 0xb6, 0x06, 0x00, 0x0a, 0xc1, 0x94, 0x52, 0x7e, 0x7d, 0xb9, 0xcc, +0x29, 0x82, 0x5d, 0xd4, 0x7e, 0x59, 0x58, 0x02, 0xfa, 0xc7, 0x25, 0x23, 0x54, +0x70, 0x8b, 0x9e, 0x02, 0x41, 0x37, 0x26, 0xb3, 0x89, 0xe0, 0xc8, 0xe9, 0x0b, +0x45, 0xd2, 0xfb, 0xdd, 0x53, 0x3b, 0xff, 0x53, 0x57, 0x02, 0x01, 0x05}; + diff --git a/testkeys/DH/dh512.pem b/testkeys/DH/dh512.pem new file mode 100644 index 0000000..f1089bc --- /dev/null +++ b/testkeys/DH/dh512.pem @@ -0,0 +1,4 @@ +-----BEGIN DH PARAMETERS----- +MEYCQQDxUqvLdAR+PySjhytotdDv1UO2BgAKwZRSfn25zCmCXdR+WVgC+sclI1Rw +i54CQTcms4ngyOkLRdL73VM7/1NXAgEF +-----END DH PARAMETERS----- diff --git a/testkeys/EC/192_EC.h b/testkeys/EC/192_EC.h new file mode 100644 index 0000000..d9f6c0e --- /dev/null +++ b/testkeys/EC/192_EC.h @@ -0,0 +1,94 @@ +/** + * @file testkeys/EC/192_EC.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated X.509 certificate as binary DER. +Certificate: + Data: + Version: 3 + Serial Number: + 1b:bc + Issuer: CN=MatrixSSL Sample CA (Elliptic curve prime192v1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation., OU=Test + Validity: + Not Before: 2014/03/17 + Not After : 2017/03/16 + Subject: CN=MatrixSSL Sample Cert (Elliptic curve prime192v1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation, OU=Test + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (192 bit) + pub: + ca:e2:9c:75:aa:63:72:2b:76:87:3d:9a:af:b6:b4:c6: + 69:7a:0c:b8:77:e7:30:f5 + 8f:4e:78:b3:03:68:91:f6:32:58:c5:15:70:9a:f8:db: + d7:4b:a3:64:83:69:e6:d1 + ASN1 OID: secp192r1 + X509v3 extensions: + X509v3 Subject Alternative Name: DNS + localhost + X509v3 Subject Alternative Name: iPAddress + 127.0.0.1 + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: 0x0 + X509v3 Extended Key Usage: 0x6 + TLS WWW server authentication + TLS WWW client authentication + X509v3 Subject Key Identifier: + 43:79:2b:cd:64:5e:70:7e:35:05:72:c9:5c:d2:4a:a0: + f4:b9:da:05 + X509v3 Authority Key Identifier: + 93:3f:b3:5a:38:55:dd:b4:d6:6e:84:cc:66:ce:8c:26: + 5b:1c:17:20 + Signature Algorithm: ecdsa-with-SHA256 + 30:34:02:18:78:76:4a:89:88:85:21:30:ff:3a:91:7a: + ae:50:83:46:77:59:ea:fb:b1:af:13:bb:02:18:05:a1: + 90:96:0c:94:30:b7:c1:64:a5:96:b1:67:3b:a8:7a:92: + 87:7e:7b:4a:0d:38 +*/ +#define EC192_SIZE 660 +const static unsigned char EC192[EC192_SIZE] = + "\x30\x82\x02\x90\x30\x82\x02\x47\xa0\x03\x02\x01\x02\x02\x02\x1b" + "\xbc\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x81\x9a" + "\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30" + "\x09\x06\x03\x55\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03" + "\x55\x04\x07\x0c\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x23\x30\x21" + "\x06\x03\x55\x04\x0a\x0c\x1a\x49\x6e\x73\x69\x64\x65\x20\x53\x65" + "\x63\x75\x72\x65\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e" + "\x2e\x31\x0d\x30\x0b\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74" + "\x31\x38\x30\x36\x06\x03\x55\x04\x03\x0c\x2f\x4d\x61\x74\x72\x69" + "\x78\x53\x53\x4c\x20\x53\x61\x6d\x70\x6c\x65\x20\x43\x41\x20\x28" + "\x45\x6c\x6c\x69\x70\x74\x69\x63\x20\x63\x75\x72\x76\x65\x20\x70" + "\x72\x69\x6d\x65\x31\x39\x32\x76\x31\x29\x30\x1e\x17\x0d\x31\x34" + "\x30\x33\x31\x37\x32\x31\x33\x37\x30\x37\x5a\x17\x0d\x31\x37\x30" + "\x33\x31\x36\x32\x31\x33\x37\x30\x37\x5a\x30\x81\x9b\x31\x0b\x30" + "\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03" + "\x55\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07" + "\x0c\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06\x03\x55" + "\x04\x0a\x0c\x19\x49\x6e\x73\x69\x64\x65\x20\x53\x65\x63\x75\x72" + "\x65\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30" + "\x0b\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x31\x3a\x30\x38" + "\x06\x03\x55\x04\x03\x0c\x31\x4d\x61\x74\x72\x69\x78\x53\x53\x4c" + "\x20\x53\x61\x6d\x70\x6c\x65\x20\x43\x65\x72\x74\x20\x28\x45\x6c" + "\x6c\x69\x70\x74\x69\x63\x20\x63\x75\x72\x76\x65\x20\x70\x72\x69" + "\x6d\x65\x31\x39\x32\x76\x31\x29\x30\x49\x30\x13\x06\x07\x2a\x86" + "\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x01\x03" + "\x32\x00\x04\xca\xe2\x9c\x75\xaa\x63\x72\x2b\x76\x87\x3d\x9a\xaf" + "\xb6\xb4\xc6\x69\x7a\x0c\xb8\x77\xe7\x30\xf5\x8f\x4e\x78\xb3\x03" + "\x68\x91\xf6\x32\x58\xc5\x15\x70\x9a\xf8\xdb\xd7\x4b\xa3\x64\x83" + "\x69\xe6\xd1\xa3\x81\x89\x30\x81\x86\x30\x09\x06\x03\x55\x1d\x13" + "\x04\x02\x30\x00\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x43" + "\x79\x2b\xcd\x64\x5e\x70\x7e\x35\x05\x72\xc9\x5c\xd2\x4a\xa0\xf4" + "\xb9\xda\x05\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14" + "\x93\x3f\xb3\x5a\x38\x55\xdd\xb4\xd6\x6e\x84\xcc\x66\xce\x8c\x26" + "\x5b\x1c\x17\x20\x30\x1d\x06\x03\x55\x1d\x25\x04\x16\x30\x14\x06" + "\x08\x2b\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2b\x06\x01\x05\x05" + "\x07\x03\x02\x30\x1a\x06\x03\x55\x1d\x11\x04\x13\x30\x11\x82\x09" + "\x6c\x6f\x63\x61\x6c\x68\x6f\x73\x74\x87\x04\x7f\x00\x00\x01\x30" + "\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x37\x00\x30\x34" + "\x02\x18\x78\x76\x4a\x89\x88\x85\x21\x30\xff\x3a\x91\x7a\xae\x50" + "\x83\x46\x77\x59\xea\xfb\xb1\xaf\x13\xbb\x02\x18\x05\xa1\x90\x96" + "\x0c\x94\x30\xb7\xc1\x64\xa5\x96\xb1\x67\x3b\xa8\x7a\x92\x87\x7e" + "\x7b\x4a\x0d\x38"; diff --git a/testkeys/EC/192_EC.pem b/testkeys/EC/192_EC.pem new file mode 100644 index 0000000..343d135 --- /dev/null +++ b/testkeys/EC/192_EC.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICkDCCAkegAwIBAgICG7wwCgYIKoZIzj0EAwIwgZoxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEjMCEGA1UECgwaSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbi4xDTALBgNVBAsMBFRlc3QxODA2BgNVBAMML01hdHJp +eFNTTCBTYW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHByaW1lMTkydjEpMB4XDTE0 +MDMxNzIxMzcwN1oXDTE3MDMxNjIxMzcwN1owgZsxCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNlY3Vy +ZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE6MDgGA1UEAwwxTWF0cml4U1NM +IFNhbXBsZSBDZXJ0IChFbGxpcHRpYyBjdXJ2ZSBwcmltZTE5MnYxKTBJMBMGByqG +SM49AgEGCCqGSM49AwEBAzIABMrinHWqY3Irdoc9mq+2tMZpegy4d+cw9Y9OeLMD +aJH2MljFFXCa+NvXS6Nkg2nm0aOBiTCBhjAJBgNVHRMEAjAAMB0GA1UdDgQWBBRD +eSvNZF5wfjUFcslc0kqg9LnaBTAfBgNVHSMEGDAWgBSTP7NaOFXdtNZuhMxmzowm +WxwXIDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGgYDVR0RBBMwEYIJ +bG9jYWxob3N0hwR/AAABMAoGCCqGSM49BAMCAzcAMDQCGHh2SomIhSEw/zqReq5Q +g0Z3Wer7sa8TuwIYBaGQlgyUMLfBZKWWsWc7qHqSh357Sg04 +-----END CERTIFICATE----- diff --git a/testkeys/EC/192_EC_CA.h b/testkeys/EC/192_EC_CA.h new file mode 100644 index 0000000..6c4d4fe --- /dev/null +++ b/testkeys/EC/192_EC_CA.h @@ -0,0 +1,85 @@ +/** + * @file testkeys/EC/192_EC_CA.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated X.509 certificate as binary DER. +Certificate: + Data: + Version: 3 + Serial Number: + 1b:58 + Issuer: CN=MatrixSSL Sample CA (Elliptic curve prime192v1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation., OU=Test + Validity: + Not Before: 2014/03/17 + Not After : 2017/03/16 + Subject: CN=MatrixSSL Sample CA (Elliptic curve prime192v1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation., OU=Test + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (192 bit) + pub: + 59:ee:a1:5d:bb:9e:32:82:7c:98:5a:b8:70:63:07:af: + f2:0d:b3:15:27:8c:01:76 + 41:b6:6a:9a:a1:45:88:23:fb:0b:e6:3d:80:d6:0a:cc: + fb:00:57:ee:18:93:64:e0 + ASN1 OID: secp192r1 + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: 0x8004 + X509v3 Extended Key Usage: 0x0 + X509v3 Subject Key Identifier: + 93:3f:b3:5a:38:55:dd:b4:d6:6e:84:cc:66:ce:8c:26: + 5b:1c:17:20 + X509v3 Authority Key Identifier: + 93:3f:b3:5a:38:55:dd:b4:d6:6e:84:cc:66:ce:8c:26: + 5b:1c:17:20 + Signature Algorithm: ecdsa-with-SHA256 + 30:34:02:18:78:d0:b2:50:8e:3e:2b:ec:bf:f9:25:ee: + 0f:b9:ad:c6:ec:66:93:76:1d:cd:29:1b:02:18:63:fa: + 37:aa:45:4d:17:46:af:a4:23:84:fc:ef:d6:f5:1c:ce: + 5e:32:1b:1b:42:07 +*/ +#define EC192CA_SIZE 615 +const static unsigned char EC192CA[EC192CA_SIZE] = + "\x30\x82\x02\x63\x30\x82\x02\x1a\xa0\x03\x02\x01\x02\x02\x02\x1b" + "\x58\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x81\x9a" + "\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30" + "\x09\x06\x03\x55\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03" + "\x55\x04\x07\x0c\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x23\x30\x21" + "\x06\x03\x55\x04\x0a\x0c\x1a\x49\x6e\x73\x69\x64\x65\x20\x53\x65" + "\x63\x75\x72\x65\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e" + "\x2e\x31\x0d\x30\x0b\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74" + "\x31\x38\x30\x36\x06\x03\x55\x04\x03\x0c\x2f\x4d\x61\x74\x72\x69" + "\x78\x53\x53\x4c\x20\x53\x61\x6d\x70\x6c\x65\x20\x43\x41\x20\x28" + "\x45\x6c\x6c\x69\x70\x74\x69\x63\x20\x63\x75\x72\x76\x65\x20\x70" + "\x72\x69\x6d\x65\x31\x39\x32\x76\x31\x29\x30\x1e\x17\x0d\x31\x34" + "\x30\x33\x31\x37\x32\x31\x33\x37\x30\x37\x5a\x17\x0d\x31\x37\x30" + "\x33\x31\x36\x32\x31\x33\x37\x30\x37\x5a\x30\x81\x9a\x31\x0b\x30" + "\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03" + "\x55\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07" + "\x0c\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x23\x30\x21\x06\x03\x55" + "\x04\x0a\x0c\x1a\x49\x6e\x73\x69\x64\x65\x20\x53\x65\x63\x75\x72" + "\x65\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x2e\x31\x0d" + "\x30\x0b\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x31\x38\x30" + "\x36\x06\x03\x55\x04\x03\x0c\x2f\x4d\x61\x74\x72\x69\x78\x53\x53" + "\x4c\x20\x53\x61\x6d\x70\x6c\x65\x20\x43\x41\x20\x28\x45\x6c\x6c" + "\x69\x70\x74\x69\x63\x20\x63\x75\x72\x76\x65\x20\x70\x72\x69\x6d" + "\x65\x31\x39\x32\x76\x31\x29\x30\x49\x30\x13\x06\x07\x2a\x86\x48" + "\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x01\x03\x32" + "\x00\x04\x59\xee\xa1\x5d\xbb\x9e\x32\x82\x7c\x98\x5a\xb8\x70\x63" + "\x07\xaf\xf2\x0d\xb3\x15\x27\x8c\x01\x76\x41\xb6\x6a\x9a\xa1\x45" + "\x88\x23\xfb\x0b\xe6\x3d\x80\xd6\x0a\xcc\xfb\x00\x57\xee\x18\x93" + "\x64\xe0\xa3\x5e\x30\x5c\x30\x0c\x06\x03\x55\x1d\x0f\x04\x05\x03" + "\x03\x07\x04\x80\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x93" + "\x3f\xb3\x5a\x38\x55\xdd\xb4\xd6\x6e\x84\xcc\x66\xce\x8c\x26\x5b" + "\x1c\x17\x20\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14" + "\x93\x3f\xb3\x5a\x38\x55\xdd\xb4\xd6\x6e\x84\xcc\x66\xce\x8c\x26" + "\x5b\x1c\x17\x20\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01" + "\x01\xff\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x37" + "\x00\x30\x34\x02\x18\x78\xd0\xb2\x50\x8e\x3e\x2b\xec\xbf\xf9\x25" + "\xee\x0f\xb9\xad\xc6\xec\x66\x93\x76\x1d\xcd\x29\x1b\x02\x18\x63" + "\xfa\x37\xaa\x45\x4d\x17\x46\xaf\xa4\x23\x84\xfc\xef\xd6\xf5\x1c" + "\xce\x5e\x32\x1b\x1b\x42\x07"; diff --git a/testkeys/EC/192_EC_CA.pem b/testkeys/EC/192_EC_CA.pem new file mode 100644 index 0000000..91fa4da --- /dev/null +++ b/testkeys/EC/192_EC_CA.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICYzCCAhqgAwIBAgICG1gwCgYIKoZIzj0EAwIwgZoxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEjMCEGA1UECgwaSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbi4xDTALBgNVBAsMBFRlc3QxODA2BgNVBAMML01hdHJp +eFNTTCBTYW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHByaW1lMTkydjEpMB4XDTE0 +MDMxNzIxMzcwN1oXDTE3MDMxNjIxMzcwN1owgZoxCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEjMCEGA1UECgwaSW5zaWRlIFNlY3Vy +ZSBDb3Jwb3JhdGlvbi4xDTALBgNVBAsMBFRlc3QxODA2BgNVBAMML01hdHJpeFNT +TCBTYW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHByaW1lMTkydjEpMEkwEwYHKoZI +zj0CAQYIKoZIzj0DAQEDMgAEWe6hXbueMoJ8mFq4cGMHr/INsxUnjAF2QbZqmqFF +iCP7C+Y9gNYKzPsAV+4Yk2Tgo14wXDAMBgNVHQ8EBQMDBwSAMB0GA1UdDgQWBBST +P7NaOFXdtNZuhMxmzowmWxwXIDAfBgNVHSMEGDAWgBSTP7NaOFXdtNZuhMxmzowm +WxwXIDAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCAzcAMDQCGHjQslCOPivsv/kl +7g+5rcbsZpN2Hc0pGwIYY/o3qkVNF0avpCOE/O/W9RzOXjIbG0IH +-----END CERTIFICATE----- diff --git a/testkeys/EC/192_EC_CA_KEY.pem b/testkeys/EC/192_EC_CA_KEY.pem new file mode 100644 index 0000000..20dde9b --- /dev/null +++ b/testkeys/EC/192_EC_CA_KEY.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBAQ== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MF8CAQEEGNk48GAkuZyLHnsGuLrNgHCZ4FF9gWLboqAKBggqhkjOPQMBAaE0AzIA +BFnuoV27njKCfJhauHBjB6/yDbMVJ4wBdkG2apqhRYgj+wvmPYDWCsz7AFfuGJNk +4A== +-----END EC PRIVATE KEY----- diff --git a/testkeys/EC/192_EC_KEY.h b/testkeys/EC/192_EC_KEY.h new file mode 100644 index 0000000..288b5ff --- /dev/null +++ b/testkeys/EC/192_EC_KEY.h @@ -0,0 +1,18 @@ +/** + * @file testkeys/EC/192_EC_KEY.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated private key as binary DER. +*/ +#define EC192KEY_SIZE 97 +const static unsigned char EC192KEY[EC192KEY_SIZE] = + "\x30\x5f\x02\x01\x01\x04\x18\x94\x09\x7f\x22\x4f\xdf\xd3\x8e\x2d" + "\xcc\x37\x76\x6f\xa6\x32\xcf\xb4\x60\x27\x79\x12\x82\x6c\x54\xa0" + "\x0a\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x01\xa1\x34\x03\x32\x00" + "\x04\xca\xe2\x9c\x75\xaa\x63\x72\x2b\x76\x87\x3d\x9a\xaf\xb6\xb4" + "\xc6\x69\x7a\x0c\xb8\x77\xe7\x30\xf5\x8f\x4e\x78\xb3\x03\x68\x91" + "\xf6\x32\x58\xc5\x15\x70\x9a\xf8\xdb\xd7\x4b\xa3\x64\x83\x69\xe6" + "\xd1"; diff --git a/testkeys/EC/192_EC_KEY.pem b/testkeys/EC/192_EC_KEY.pem new file mode 100644 index 0000000..7159c61 --- /dev/null +++ b/testkeys/EC/192_EC_KEY.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBAQ== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MF8CAQEEGJQJfyJP39OOLcw3dm+mMs+0YCd5EoJsVKAKBggqhkjOPQMBAaE0AzIA +BMrinHWqY3Irdoc9mq+2tMZpegy4d+cw9Y9OeLMDaJH2MljFFXCa+NvXS6Nkg2nm +0Q== +-----END EC PRIVATE KEY----- diff --git a/testkeys/EC/224_EC.h b/testkeys/EC/224_EC.h new file mode 100644 index 0000000..2485a7d --- /dev/null +++ b/testkeys/EC/224_EC.h @@ -0,0 +1,94 @@ +/** + * @file testkeys/EC/224_EC.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated X.509 certificate as binary DER. +Certificate: + Data: + Version: 3 + Serial Number: + 21:34 + Issuer: CN=MatrixSSL Sample CA (Elliptic curve secp224r1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation, OU=Test + Validity: + Not Before: 2014/03/13 + Not After : 2017/03/12 + Subject: CN=MatrixSSL Sample Cert (Elliptic curve secp224r1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation, OU=Test + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (224 bit) + pub: + 4b:f5:2a:c4:6e:b9:22:8c:a5:77:16:74:74:56:26:b8: + c8:0b:18:0e:2c:a0:3f:45:bf:3f:91:20 + bc:f0:bb:8d:9d:d9:40:7a:3e:96:e8:31:81:1a:da:45: + bd:4b:cc:ea:6b:11:5f:bf:f3:32:cf:fa + ASN1 OID: secp224r1 + X509v3 extensions: + X509v3 Subject Alternative Name: DNS + localhost + X509v3 Subject Alternative Name: iPAddress + 127.0.0.1 + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: 0x0 + X509v3 Extended Key Usage: 0x6 + TLS WWW server authentication + TLS WWW client authentication + X509v3 Subject Key Identifier: + 5a:bb:e1:b6:b6:1f:fe:66:27:b7:51:42:40:6a:d8:21: + bc:e5:8f:b3 + X509v3 Authority Key Identifier: + c1:2f:ad:c4:d5:01:f8:91:e2:cf:c1:be:e6:0b:22:e7: + 2d:3b:5b:d8 + Signature Algorithm: ecdsa-with-SHA256 + 30:3d:02:1d:00:da:df:02:3f:bb:3d:e8:40:d8:91:0e: + a8:b7:bc:af:98:24:9e:91:7a:7c:67:6b:fb:b3:04:68: + a7:02:1c:50:1d:81:1d:57:92:46:d3:04:f1:2d:a2:25: + 00:43:74:7b:68:57:53:85:f3:be:32:91:c7:70:b0 +*/ +#define EC224_SIZE 671 +const static unsigned char EC224[EC224_SIZE] = + "\x30\x82\x02\x9b\x30\x82\x02\x49\xa0\x03\x02\x01\x02\x02\x02\x21" + "\x34\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x81\x98" + "\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30" + "\x09\x06\x03\x55\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03" + "\x55\x04\x07\x0c\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20" + "\x06\x03\x55\x04\x0a\x0c\x19\x49\x6e\x73\x69\x64\x65\x20\x53\x65" + "\x63\x75\x72\x65\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e" + "\x31\x0d\x30\x0b\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x31" + "\x37\x30\x35\x06\x03\x55\x04\x03\x0c\x2e\x4d\x61\x74\x72\x69\x78" + "\x53\x53\x4c\x20\x53\x61\x6d\x70\x6c\x65\x20\x43\x41\x20\x28\x45" + "\x6c\x6c\x69\x70\x74\x69\x63\x20\x63\x75\x72\x76\x65\x20\x73\x65" + "\x63\x70\x32\x32\x34\x72\x31\x29\x30\x1e\x17\x0d\x31\x34\x30\x33" + "\x31\x33\x32\x33\x32\x30\x34\x30\x5a\x17\x0d\x31\x37\x30\x33\x31" + "\x32\x32\x33\x32\x30\x34\x30\x5a\x30\x81\x9a\x31\x0b\x30\x09\x06" + "\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04" + "\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c\x07" + "\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06\x03\x55\x04\x0a" + "\x0c\x19\x49\x6e\x73\x69\x64\x65\x20\x53\x65\x63\x75\x72\x65\x20" + "\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30\x0b\x06" + "\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x31\x39\x30\x37\x06\x03" + "\x55\x04\x03\x0c\x30\x4d\x61\x74\x72\x69\x78\x53\x53\x4c\x20\x53" + "\x61\x6d\x70\x6c\x65\x20\x43\x65\x72\x74\x20\x28\x45\x6c\x6c\x69" + "\x70\x74\x69\x63\x20\x63\x75\x72\x76\x65\x20\x73\x65\x63\x70\x32" + "\x32\x34\x72\x31\x29\x30\x4e\x30\x10\x06\x07\x2a\x86\x48\xce\x3d" + "\x02\x01\x06\x05\x2b\x81\x04\x00\x21\x03\x3a\x00\x04\x4b\xf5\x2a" + "\xc4\x6e\xb9\x22\x8c\xa5\x77\x16\x74\x74\x56\x26\xb8\xc8\x0b\x18" + "\x0e\x2c\xa0\x3f\x45\xbf\x3f\x91\x20\xbc\xf0\xbb\x8d\x9d\xd9\x40" + "\x7a\x3e\x96\xe8\x31\x81\x1a\xda\x45\xbd\x4b\xcc\xea\x6b\x11\x5f" + "\xbf\xf3\x32\xcf\xfa\xa3\x81\x89\x30\x81\x86\x30\x09\x06\x03\x55" + "\x1d\x13\x04\x02\x30\x00\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04" + "\x14\x5a\xbb\xe1\xb6\xb6\x1f\xfe\x66\x27\xb7\x51\x42\x40\x6a\xd8" + "\x21\xbc\xe5\x8f\xb3\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16" + "\x80\x14\xc1\x2f\xad\xc4\xd5\x01\xf8\x91\xe2\xcf\xc1\xbe\xe6\x0b" + "\x22\xe7\x2d\x3b\x5b\xd8\x30\x1d\x06\x03\x55\x1d\x25\x04\x16\x30" + "\x14\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2b\x06\x01" + "\x05\x05\x07\x03\x02\x30\x1a\x06\x03\x55\x1d\x11\x04\x13\x30\x11" + "\x82\x09\x6c\x6f\x63\x61\x6c\x68\x6f\x73\x74\x87\x04\x7f\x00\x00" + "\x01\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x40\x00" + "\x30\x3d\x02\x1d\x00\xda\xdf\x02\x3f\xbb\x3d\xe8\x40\xd8\x91\x0e" + "\xa8\xb7\xbc\xaf\x98\x24\x9e\x91\x7a\x7c\x67\x6b\xfb\xb3\x04\x68" + "\xa7\x02\x1c\x50\x1d\x81\x1d\x57\x92\x46\xd3\x04\xf1\x2d\xa2\x25" + "\x00\x43\x74\x7b\x68\x57\x53\x85\xf3\xbe\x32\x91\xc7\x70\xb0"; diff --git a/testkeys/EC/224_EC.pem b/testkeys/EC/224_EC.pem new file mode 100644 index 0000000..8bbbcaf --- /dev/null +++ b/testkeys/EC/224_EC.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICmzCCAkmgAwIBAgICITQwCgYIKoZIzj0EAwIwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDIyNHIxKTAeFw0xNDAz +MTMyMzIwNDBaFw0xNzAzMTIyMzIwNDBaMIGaMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxOTA3BgNVBAMMME1hdHJpeFNTTCBT +YW1wbGUgQ2VydCAoRWxsaXB0aWMgY3VydmUgc2VjcDIyNHIxKTBOMBAGByqGSM49 +AgEGBSuBBAAhAzoABEv1KsRuuSKMpXcWdHRWJrjICxgOLKA/Rb8/kSC88LuNndlA +ej6W6DGBGtpFvUvM6msRX7/zMs/6o4GJMIGGMAkGA1UdEwQCMAAwHQYDVR0OBBYE +FFq74ba2H/5mJ7dRQkBq2CG85Y+zMB8GA1UdIwQYMBaAFMEvrcTVAfiR4s/BvuYL +IuctO1vYMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAaBgNVHREEEzAR +gglsb2NhbGhvc3SHBH8AAAEwCgYIKoZIzj0EAwIDQAAwPQIdANrfAj+7PehA2JEO +qLe8r5gknpF6fGdr+7MEaKcCHFAdgR1XkkbTBPEtoiUAQ3R7aFdThfO+MpHHcLA= +-----END CERTIFICATE----- diff --git a/testkeys/EC/224_EC_CA.h b/testkeys/EC/224_EC_CA.h new file mode 100644 index 0000000..53343d5 --- /dev/null +++ b/testkeys/EC/224_EC_CA.h @@ -0,0 +1,85 @@ +/** + * @file testkeys/EC/224_EC_CA.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated X.509 certificate as binary DER. +Certificate: + Data: + Version: 3 + Serial Number: + 1f:40 + Issuer: CN=MatrixSSL Sample CA (Elliptic curve secp224r1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation, OU=Test + Validity: + Not Before: 2014/03/13 + Not After : 2017/03/12 + Subject: CN=MatrixSSL Sample CA (Elliptic curve secp224r1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation, OU=Test + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (224 bit) + pub: + fd:0b:b3:75:25:35:5e:75:a3:83:8b:51:7e:ff:b8:1e: + 2a:8c:5b:8e:ce:d7:e1:c3:9a:50:25:8d + ca:0c:2b:9f:fa:3e:53:ac:31:52:7f:67:a6:92:a6:a3: + db:a8:94:4b:22:33:1d:5f:5f:cf:48:21 + ASN1 OID: secp224r1 + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: 0x4 + X509v3 Extended Key Usage: 0x0 + X509v3 Subject Key Identifier: + c1:2f:ad:c4:d5:01:f8:91:e2:cf:c1:be:e6:0b:22:e7: + 2d:3b:5b:d8 + X509v3 Authority Key Identifier: + c1:2f:ad:c4:d5:01:f8:91:e2:cf:c1:be:e6:0b:22:e7: + 2d:3b:5b:d8 + Signature Algorithm: ecdsa-with-SHA256 + 30:3d:02:1d:00:fe:1c:56:b3:a3:b9:d5:b8:72:9c:22: + d6:80:97:5f:87:02:22:17:1a:f2:44:f9:b6:eb:17:42: + 33:02:1c:44:a7:43:3b:7d:c3:47:15:a2:01:71:5b:6f: + f0:36:a5:9b:db:0b:e0:13:96:47:06:2f:4f:fb:49 +*/ +#define EC224CA_SIZE 624 +const static unsigned char EC224CA[EC224CA_SIZE] = + "\x30\x82\x02\x6c\x30\x82\x02\x1a\xa0\x03\x02\x01\x02\x02\x02\x1f" + "\x40\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x81\x98" + "\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30" + "\x09\x06\x03\x55\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03" + "\x55\x04\x07\x0c\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20" + "\x06\x03\x55\x04\x0a\x0c\x19\x49\x6e\x73\x69\x64\x65\x20\x53\x65" + "\x63\x75\x72\x65\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e" + "\x31\x0d\x30\x0b\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x31" + "\x37\x30\x35\x06\x03\x55\x04\x03\x0c\x2e\x4d\x61\x74\x72\x69\x78" + "\x53\x53\x4c\x20\x53\x61\x6d\x70\x6c\x65\x20\x43\x41\x20\x28\x45" + "\x6c\x6c\x69\x70\x74\x69\x63\x20\x63\x75\x72\x76\x65\x20\x73\x65" + "\x63\x70\x32\x32\x34\x72\x31\x29\x30\x1e\x17\x0d\x31\x34\x30\x33" + "\x31\x33\x32\x33\x32\x30\x34\x30\x5a\x17\x0d\x31\x37\x30\x33\x31" + "\x32\x32\x33\x32\x30\x34\x30\x5a\x30\x81\x98\x31\x0b\x30\x09\x06" + "\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04" + "\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c\x07" + "\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06\x03\x55\x04\x0a" + "\x0c\x19\x49\x6e\x73\x69\x64\x65\x20\x53\x65\x63\x75\x72\x65\x20" + "\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30\x0b\x06" + "\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x31\x37\x30\x35\x06\x03" + "\x55\x04\x03\x0c\x2e\x4d\x61\x74\x72\x69\x78\x53\x53\x4c\x20\x53" + "\x61\x6d\x70\x6c\x65\x20\x43\x41\x20\x28\x45\x6c\x6c\x69\x70\x74" + "\x69\x63\x20\x63\x75\x72\x76\x65\x20\x73\x65\x63\x70\x32\x32\x34" + "\x72\x31\x29\x30\x4e\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01" + "\x06\x05\x2b\x81\x04\x00\x21\x03\x3a\x00\x04\xfd\x0b\xb3\x75\x25" + "\x35\x5e\x75\xa3\x83\x8b\x51\x7e\xff\xb8\x1e\x2a\x8c\x5b\x8e\xce" + "\xd7\xe1\xc3\x9a\x50\x25\x8d\xca\x0c\x2b\x9f\xfa\x3e\x53\xac\x31" + "\x52\x7f\x67\xa6\x92\xa6\xa3\xdb\xa8\x94\x4b\x22\x33\x1d\x5f\x5f" + "\xcf\x48\x21\xa3\x5d\x30\x5b\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04" + "\x03\x02\x02\x04\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xc1" + "\x2f\xad\xc4\xd5\x01\xf8\x91\xe2\xcf\xc1\xbe\xe6\x0b\x22\xe7\x2d" + "\x3b\x5b\xd8\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14" + "\xc1\x2f\xad\xc4\xd5\x01\xf8\x91\xe2\xcf\xc1\xbe\xe6\x0b\x22\xe7" + "\x2d\x3b\x5b\xd8\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01" + "\x01\xff\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x40" + "\x00\x30\x3d\x02\x1d\x00\xfe\x1c\x56\xb3\xa3\xb9\xd5\xb8\x72\x9c" + "\x22\xd6\x80\x97\x5f\x87\x02\x22\x17\x1a\xf2\x44\xf9\xb6\xeb\x17" + "\x42\x33\x02\x1c\x44\xa7\x43\x3b\x7d\xc3\x47\x15\xa2\x01\x71\x5b" + "\x6f\xf0\x36\xa5\x9b\xdb\x0b\xe0\x13\x96\x47\x06\x2f\x4f\xfb\x49"; diff --git a/testkeys/EC/224_EC_CA.pem b/testkeys/EC/224_EC_CA.pem new file mode 100644 index 0000000..558cfc5 --- /dev/null +++ b/testkeys/EC/224_EC_CA.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICbDCCAhqgAwIBAgICH0AwCgYIKoZIzj0EAwIwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDIyNHIxKTAeFw0xNDAz +MTMyMzIwNDBaFw0xNzAzMTIyMzIwNDBaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3AyMjRyMSkwTjAQBgcqhkjOPQIB +BgUrgQQAIQM6AAT9C7N1JTVedaODi1F+/7geKoxbjs7X4cOaUCWNygwrn/o+U6wx +Un9nppKmo9uolEsiMx1fX89IIaNdMFswCwYDVR0PBAQDAgIEMB0GA1UdDgQWBBTB +L63E1QH4keLPwb7mCyLnLTtb2DAfBgNVHSMEGDAWgBTBL63E1QH4keLPwb7mCyLn +LTtb2DAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0AAMD0CHQD+HFazo7nVuHKc +ItaAl1+HAiIXGvJE+bbrF0IzAhxEp0M7fcNHFaIBcVtv8Dalm9sL4BOWRwYvT/tJ +-----END CERTIFICATE----- diff --git a/testkeys/EC/224_EC_CA_KEY.pem b/testkeys/EC/224_EC_CA_KEY.pem new file mode 100644 index 0000000..42fdefe --- /dev/null +++ b/testkeys/EC/224_EC_CA_KEY.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQAIQ== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MGgCAQEEHC1oEP6csX31x9nUREAvYVR/XwEYadNE+79tnOGgBwYFK4EEACGhPAM6 +AAT9C7N1JTVedaODi1F+/7geKoxbjs7X4cOaUCWNygwrn/o+U6wxUn9nppKmo9uo +lEsiMx1fX89IIQ== +-----END EC PRIVATE KEY----- diff --git a/testkeys/EC/224_EC_KEY.h b/testkeys/EC/224_EC_KEY.h new file mode 100644 index 0000000..8ff9ce7 --- /dev/null +++ b/testkeys/EC/224_EC_KEY.h @@ -0,0 +1,18 @@ +/** + * @file testkeys/EC/224_EC_KEY.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated private key as binary DER. +*/ +#define EC224KEY_SIZE 106 +const static unsigned char EC224KEY[EC224KEY_SIZE] = + "\x30\x68\x02\x01\x01\x04\x1c\x70\x64\x7b\xcd\xdf\x13\x08\xac\x9f" + "\xd6\x84\xb7\x1d\x09\x23\x95\xf9\xb3\x75\x68\x13\xbf\x4a\xf2\xf2" + "\xc1\x41\x07\xa0\x07\x06\x05\x2b\x81\x04\x00\x21\xa1\x3c\x03\x3a" + "\x00\x04\x4b\xf5\x2a\xc4\x6e\xb9\x22\x8c\xa5\x77\x16\x74\x74\x56" + "\x26\xb8\xc8\x0b\x18\x0e\x2c\xa0\x3f\x45\xbf\x3f\x91\x20\xbc\xf0" + "\xbb\x8d\x9d\xd9\x40\x7a\x3e\x96\xe8\x31\x81\x1a\xda\x45\xbd\x4b" + "\xcc\xea\x6b\x11\x5f\xbf\xf3\x32\xcf\xfa"; diff --git a/testkeys/EC/224_EC_KEY.pem b/testkeys/EC/224_EC_KEY.pem new file mode 100644 index 0000000..cc75131 --- /dev/null +++ b/testkeys/EC/224_EC_KEY.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQAIQ== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MGgCAQEEHHBke83fEwisn9aEtx0JI5X5s3VoE79K8vLBQQegBwYFK4EEACGhPAM6 +AARL9SrEbrkijKV3FnR0Via4yAsYDiygP0W/P5EgvPC7jZ3ZQHo+lugxgRraRb1L +zOprEV+/8zLP+g== +-----END EC PRIVATE KEY----- diff --git a/testkeys/EC/256_EC.h b/testkeys/EC/256_EC.h new file mode 100644 index 0000000..858ea40 --- /dev/null +++ b/testkeys/EC/256_EC.h @@ -0,0 +1,97 @@ +/** + * @file testkeys/EC/256_EC.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated X.509 certificate as binary DER. +Certificate: + Data: + Version: 3 + Serial Number: + 02 + Issuer: CN=MatrixSSL Sample CA (Elliptic curve prime256v1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation, OU=Test + Validity: + Not Before: 2014/03/13 + Not After : 2017/03/12 + Subject: CN=MatrixSSL Sample Cert (Elliptic curve prime256v1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation, OU=Test + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 5f:ad:62:02:42:48:ba:fb:e2:88:d8:7f:b9:72:cb:28: + ae:c3:8a:1e:c3:0e:9c:7d:7a:a4:b5:7f:da:bd:46:5a + b9:95:39:e0:44:51:71:ba:e3:b3:40:f2:54:fd:23:84: + b2:ea:2a:84:a3:4f:d7:b0:08:ba:6e:80:c3:eb:df:2f + ASN1 OID: secp256r1 + X509v3 extensions: + X509v3 Subject Alternative Name: DNS + localhost + X509v3 Subject Alternative Name: iPAddress + 127.0.0.1 + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: 0x0 + X509v3 Extended Key Usage: 0x6 + TLS WWW server authentication + TLS WWW client authentication + X509v3 Subject Key Identifier: + 1f:80:75:53:ad:c9:7d:eb:09:78:26:ab:80:18:09:1c: + 68:d4:b8:83 + X509v3 Authority Key Identifier: + 69:0e:fa:47:3e:6d:40:f9:29:7f:f7:6f:66:86:b8:7a: + 34:bb:25:eb + Signature Algorithm: ecdsa-with-SHA256 + 30:45:02:21:00:d0:78:0f:a8:7c:ab:a6:78:1d:a9:57: + cd:4f:d8:04:d8:b3:90:36:94:e0:01:dc:20:49:6a:de: + d5:53:8c:08:12:02:20:24:9b:f0:37:e4:da:42:4c:6d: + d3:c3:d4:a6:3f:47:d4:ad:99:5c:ae:47:a7:0c:83:24: + c4:a1:fc:dc:77:f3:a9 +*/ +#define EC256_SIZE 691 +const static unsigned char EC256[EC256_SIZE] = + "\x30\x82\x02\xaf\x30\x82\x02\x55\xa0\x03\x02\x01\x02\x02\x01\x02" + "\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x81\x99\x31" + "\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09" + "\x06\x03\x55\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55" + "\x04\x07\x0c\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06" + "\x03\x55\x04\x0a\x0c\x19\x49\x6e\x73\x69\x64\x65\x20\x53\x65\x63" + "\x75\x72\x65\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31" + "\x0d\x30\x0b\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x31\x38" + "\x30\x36\x06\x03\x55\x04\x03\x0c\x2f\x4d\x61\x74\x72\x69\x78\x53" + "\x53\x4c\x20\x53\x61\x6d\x70\x6c\x65\x20\x43\x41\x20\x28\x45\x6c" + "\x6c\x69\x70\x74\x69\x63\x20\x63\x75\x72\x76\x65\x20\x70\x72\x69" + "\x6d\x65\x32\x35\x36\x76\x31\x29\x30\x1e\x17\x0d\x31\x34\x30\x33" + "\x31\x33\x32\x33\x32\x31\x32\x33\x5a\x17\x0d\x31\x37\x30\x33\x31" + "\x32\x32\x33\x32\x31\x32\x33\x5a\x30\x81\x9b\x31\x0b\x30\x09\x06" + "\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04" + "\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c\x07" + "\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06\x03\x55\x04\x0a" + "\x0c\x19\x49\x6e\x73\x69\x64\x65\x20\x53\x65\x63\x75\x72\x65\x20" + "\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30\x0b\x06" + "\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x31\x3a\x30\x38\x06\x03" + "\x55\x04\x03\x0c\x31\x4d\x61\x74\x72\x69\x78\x53\x53\x4c\x20\x53" + "\x61\x6d\x70\x6c\x65\x20\x43\x65\x72\x74\x20\x28\x45\x6c\x6c\x69" + "\x70\x74\x69\x63\x20\x63\x75\x72\x76\x65\x20\x70\x72\x69\x6d\x65" + "\x32\x35\x36\x76\x31\x29\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce" + "\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00" + "\x04\x5f\xad\x62\x02\x42\x48\xba\xfb\xe2\x88\xd8\x7f\xb9\x72\xcb" + "\x28\xae\xc3\x8a\x1e\xc3\x0e\x9c\x7d\x7a\xa4\xb5\x7f\xda\xbd\x46" + "\x5a\xb9\x95\x39\xe0\x44\x51\x71\xba\xe3\xb3\x40\xf2\x54\xfd\x23" + "\x84\xb2\xea\x2a\x84\xa3\x4f\xd7\xb0\x08\xba\x6e\x80\xc3\xeb\xdf" + "\x2f\xa3\x81\x89\x30\x81\x86\x30\x09\x06\x03\x55\x1d\x13\x04\x02" + "\x30\x00\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x1f\x80\x75" + "\x53\xad\xc9\x7d\xeb\x09\x78\x26\xab\x80\x18\x09\x1c\x68\xd4\xb8" + "\x83\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x69\x0e" + "\xfa\x47\x3e\x6d\x40\xf9\x29\x7f\xf7\x6f\x66\x86\xb8\x7a\x34\xbb" + "\x25\xeb\x30\x1d\x06\x03\x55\x1d\x25\x04\x16\x30\x14\x06\x08\x2b" + "\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2b\x06\x01\x05\x05\x07\x03" + "\x02\x30\x1a\x06\x03\x55\x1d\x11\x04\x13\x30\x11\x82\x09\x6c\x6f" + "\x63\x61\x6c\x68\x6f\x73\x74\x87\x04\x7f\x00\x00\x01\x30\x0a\x06" + "\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x48\x00\x30\x45\x02\x21" + "\x00\xd0\x78\x0f\xa8\x7c\xab\xa6\x78\x1d\xa9\x57\xcd\x4f\xd8\x04" + "\xd8\xb3\x90\x36\x94\xe0\x01\xdc\x20\x49\x6a\xde\xd5\x53\x8c\x08" + "\x12\x02\x20\x24\x9b\xf0\x37\xe4\xda\x42\x4c\x6d\xd3\xc3\xd4\xa6" + "\x3f\x47\xd4\xad\x99\x5c\xae\x47\xa7\x0c\x83\x24\xc4\xa1\xfc\xdc" + "\x77\xf3\xa9"; diff --git a/testkeys/EC/256_EC.pem b/testkeys/EC/256_EC.pem new file mode 100644 index 0000000..1e2eecd --- /dev/null +++ b/testkeys/EC/256_EC.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICrzCCAlWgAwIBAgIBAjAKBggqhkjOPQQDAjCBmTELMAkGA1UEBhMCVVMxCzAJ +BgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMSIwIAYDVQQKDBlJbnNpZGUgU2Vj +dXJlIENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MTgwNgYDVQQDDC9NYXRyaXhT +U0wgU2FtcGxlIENBIChFbGxpcHRpYyBjdXJ2ZSBwcmltZTI1NnYxKTAeFw0xNDAz +MTMyMzIxMjNaFw0xNzAzMTIyMzIxMjNaMIGbMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxOjA4BgNVBAMMMU1hdHJpeFNTTCBT +YW1wbGUgQ2VydCAoRWxsaXB0aWMgY3VydmUgcHJpbWUyNTZ2MSkwWTATBgcqhkjO +PQIBBggqhkjOPQMBBwNCAARfrWICQki6++KI2H+5cssorsOKHsMOnH16pLV/2r1G +WrmVOeBEUXG647NA8lT9I4Sy6iqEo0/XsAi6boDD698vo4GJMIGGMAkGA1UdEwQC +MAAwHQYDVR0OBBYEFB+AdVOtyX3rCXgmq4AYCRxo1LiDMB8GA1UdIwQYMBaAFGkO ++kc+bUD5KX/3b2aGuHo0uyXrMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD +AjAaBgNVHREEEzARgglsb2NhbGhvc3SHBH8AAAEwCgYIKoZIzj0EAwIDSAAwRQIh +ANB4D6h8q6Z4HalXzU/YBNizkDaU4AHcIElq3tVTjAgSAiAkm/A35NpCTG3Tw9Sm +P0fUrZlcrkenDIMkxKH83HfzqQ== +-----END CERTIFICATE----- diff --git a/testkeys/EC/256_EC_CA.h b/testkeys/EC/256_EC_CA.h new file mode 100644 index 0000000..ca478e4 --- /dev/null +++ b/testkeys/EC/256_EC_CA.h @@ -0,0 +1,88 @@ +/** + * @file testkeys/EC/256_EC_CA.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated X.509 certificate as binary DER. +Certificate: + Data: + Version: 3 + Serial Number: + 01 + Issuer: CN=MatrixSSL Sample CA (Elliptic curve prime256v1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation, OU=Test + Validity: + Not Before: 2014/03/13 + Not After : 2017/03/12 + Subject: CN=MatrixSSL Sample CA (Elliptic curve prime256v1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation, OU=Test + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + d3:5a:de:56:14:08:e2:45:d1:0b:a9:77:8a:70:5f:87: + 8c:b4:5b:2f:cd:69:7c:05:61:7f:e9:e3:66:bf:80:3f + 94:88:19:aa:8a:ff:b4:28:f6:0e:bb:14:7a:39:65:4b: + 2b:7d:52:44:9c:5c:5b:09:69:98:16:31:92:da:cc:58 + ASN1 OID: secp256r1 + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: 0x4 + X509v3 Extended Key Usage: 0x0 + X509v3 Subject Key Identifier: + 69:0e:fa:47:3e:6d:40:f9:29:7f:f7:6f:66:86:b8:7a: + 34:bb:25:eb + X509v3 Authority Key Identifier: + 69:0e:fa:47:3e:6d:40:f9:29:7f:f7:6f:66:86:b8:7a: + 34:bb:25:eb + Signature Algorithm: ecdsa-with-SHA256 + 30:45:02:20:42:69:bf:41:62:c9:a6:51:b2:0e:d9:39: + 0c:0c:55:4c:c3:62:17:aa:e9:f3:8b:ba:0c:f9:e3:09: + b2:9d:ea:d8:02:21:00:82:03:21:fd:7e:bc:44:b7:09: + 8a:25:ce:5a:66:8e:79:72:5a:b4:10:b5:16:ce:67:02: + 8f:91:5e:1c:5d:ef:a3 +*/ +#define EC256CA_SIZE 644 +const static unsigned char EC256CA[EC256CA_SIZE] = + "\x30\x82\x02\x80\x30\x82\x02\x26\xa0\x03\x02\x01\x02\x02\x01\x01" + "\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x81\x99\x31" + "\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09" + "\x06\x03\x55\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55" + "\x04\x07\x0c\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06" + "\x03\x55\x04\x0a\x0c\x19\x49\x6e\x73\x69\x64\x65\x20\x53\x65\x63" + "\x75\x72\x65\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31" + "\x0d\x30\x0b\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x31\x38" + "\x30\x36\x06\x03\x55\x04\x03\x0c\x2f\x4d\x61\x74\x72\x69\x78\x53" + "\x53\x4c\x20\x53\x61\x6d\x70\x6c\x65\x20\x43\x41\x20\x28\x45\x6c" + "\x6c\x69\x70\x74\x69\x63\x20\x63\x75\x72\x76\x65\x20\x70\x72\x69" + "\x6d\x65\x32\x35\x36\x76\x31\x29\x30\x1e\x17\x0d\x31\x34\x30\x33" + "\x31\x33\x32\x33\x32\x31\x32\x33\x5a\x17\x0d\x31\x37\x30\x33\x31" + "\x32\x32\x33\x32\x31\x32\x33\x5a\x30\x81\x99\x31\x0b\x30\x09\x06" + "\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04" + "\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c\x07" + "\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06\x03\x55\x04\x0a" + "\x0c\x19\x49\x6e\x73\x69\x64\x65\x20\x53\x65\x63\x75\x72\x65\x20" + "\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30\x0b\x06" + "\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x31\x38\x30\x36\x06\x03" + "\x55\x04\x03\x0c\x2f\x4d\x61\x74\x72\x69\x78\x53\x53\x4c\x20\x53" + "\x61\x6d\x70\x6c\x65\x20\x43\x41\x20\x28\x45\x6c\x6c\x69\x70\x74" + "\x69\x63\x20\x63\x75\x72\x76\x65\x20\x70\x72\x69\x6d\x65\x32\x35" + "\x36\x76\x31\x29\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02" + "\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xd3" + "\x5a\xde\x56\x14\x08\xe2\x45\xd1\x0b\xa9\x77\x8a\x70\x5f\x87\x8c" + "\xb4\x5b\x2f\xcd\x69\x7c\x05\x61\x7f\xe9\xe3\x66\xbf\x80\x3f\x94" + "\x88\x19\xaa\x8a\xff\xb4\x28\xf6\x0e\xbb\x14\x7a\x39\x65\x4b\x2b" + "\x7d\x52\x44\x9c\x5c\x5b\x09\x69\x98\x16\x31\x92\xda\xcc\x58\xa3" + "\x5d\x30\x5b\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x02\x04" + "\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x69\x0e\xfa\x47\x3e" + "\x6d\x40\xf9\x29\x7f\xf7\x6f\x66\x86\xb8\x7a\x34\xbb\x25\xeb\x30" + "\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x69\x0e\xfa\x47" + "\x3e\x6d\x40\xf9\x29\x7f\xf7\x6f\x66\x86\xb8\x7a\x34\xbb\x25\xeb" + "\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0a" + "\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x48\x00\x30\x45\x02" + "\x20\x42\x69\xbf\x41\x62\xc9\xa6\x51\xb2\x0e\xd9\x39\x0c\x0c\x55" + "\x4c\xc3\x62\x17\xaa\xe9\xf3\x8b\xba\x0c\xf9\xe3\x09\xb2\x9d\xea" + "\xd8\x02\x21\x00\x82\x03\x21\xfd\x7e\xbc\x44\xb7\x09\x8a\x25\xce" + "\x5a\x66\x8e\x79\x72\x5a\xb4\x10\xb5\x16\xce\x67\x02\x8f\x91\x5e" + "\x1c\x5d\xef\xa3"; diff --git a/testkeys/EC/256_EC_CA.pem b/testkeys/EC/256_EC_CA.pem new file mode 100644 index 0000000..c54fadf --- /dev/null +++ b/testkeys/EC/256_EC_CA.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICgDCCAiagAwIBAgIBATAKBggqhkjOPQQDAjCBmTELMAkGA1UEBhMCVVMxCzAJ +BgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMSIwIAYDVQQKDBlJbnNpZGUgU2Vj +dXJlIENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MTgwNgYDVQQDDC9NYXRyaXhT +U0wgU2FtcGxlIENBIChFbGxpcHRpYyBjdXJ2ZSBwcmltZTI1NnYxKTAeFw0xNDAz +MTMyMzIxMjNaFw0xNzAzMTIyMzIxMjNaMIGZMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxODA2BgNVBAMML01hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHByaW1lMjU2djEpMFkwEwYHKoZIzj0C +AQYIKoZIzj0DAQcDQgAE01reVhQI4kXRC6l3inBfh4y0Wy/NaXwFYX/p42a/gD+U +iBmqiv+0KPYOuxR6OWVLK31SRJxcWwlpmBYxktrMWKNdMFswCwYDVR0PBAQDAgIE +MB0GA1UdDgQWBBRpDvpHPm1A+Sl/929mhrh6NLsl6zAfBgNVHSMEGDAWgBRpDvpH +Pm1A+Sl/929mhrh6NLsl6zAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0gAMEUC +IEJpv0FiyaZRsg7ZOQwMVUzDYheq6fOLugz54wmynerYAiEAggMh/X68RLcJiiXO +WmaOeXJatBC1Fs5nAo+RXhxd76M= +-----END CERTIFICATE----- diff --git a/testkeys/EC/256_EC_CA_KEY.pem b/testkeys/EC/256_EC_CA_KEY.pem new file mode 100644 index 0000000..b3bdf21 --- /dev/null +++ b/testkeys/EC/256_EC_CA_KEY.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEILde+sxlIzqLlxauABe4Hqc1qLSrxuwDpRYluYivKq4IoAoGCCqGSM49 +AwEHoUQDQgAE01reVhQI4kXRC6l3inBfh4y0Wy/NaXwFYX/p42a/gD+UiBmqiv+0 +KPYOuxR6OWVLK31SRJxcWwlpmBYxktrMWA== +-----END EC PRIVATE KEY----- diff --git a/testkeys/EC/256_EC_KEY.h b/testkeys/EC/256_EC_KEY.h new file mode 100644 index 0000000..1c96100 --- /dev/null +++ b/testkeys/EC/256_EC_KEY.h @@ -0,0 +1,19 @@ +/** + * @file testkeys/EC/256_EC_KEY.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated private key as binary DER. +*/ +#define EC256KEY_SIZE 121 +const static unsigned char EC256KEY[EC256KEY_SIZE] = + "\x30\x77\x02\x01\x01\x04\x20\x5c\xe9\x89\xc5\xb1\x53\xa0\x02\x3c" + "\x90\xbe\x3a\x2a\x73\xb2\x08\x16\xc3\xed\xbc\xd5\xd6\x67\x26\x10" + "\x4e\xec\x79\x28\x0f\xbf\xcb\xa0\x0a\x06\x08\x2a\x86\x48\xce\x3d" + "\x03\x01\x07\xa1\x44\x03\x42\x00\x04\x5f\xad\x62\x02\x42\x48\xba" + "\xfb\xe2\x88\xd8\x7f\xb9\x72\xcb\x28\xae\xc3\x8a\x1e\xc3\x0e\x9c" + "\x7d\x7a\xa4\xb5\x7f\xda\xbd\x46\x5a\xb9\x95\x39\xe0\x44\x51\x71" + "\xba\xe3\xb3\x40\xf2\x54\xfd\x23\x84\xb2\xea\x2a\x84\xa3\x4f\xd7" + "\xb0\x08\xba\x6e\x80\xc3\xeb\xdf\x2f"; diff --git a/testkeys/EC/256_EC_KEY.pem b/testkeys/EC/256_EC_KEY.pem new file mode 100644 index 0000000..9189b02 --- /dev/null +++ b/testkeys/EC/256_EC_KEY.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIFzpicWxU6ACPJC+OipzsggWw+281dZnJhBO7HkoD7/LoAoGCCqGSM49 +AwEHoUQDQgAEX61iAkJIuvviiNh/uXLLKK7Dih7DDpx9eqS1f9q9Rlq5lTngRFFx +uuOzQPJU/SOEsuoqhKNP17AIum6Aw+vfLw== +-----END EC PRIVATE KEY----- diff --git a/testkeys/EC/384_EC.h b/testkeys/EC/384_EC.h new file mode 100644 index 0000000..150ae70 --- /dev/null +++ b/testkeys/EC/384_EC.h @@ -0,0 +1,104 @@ +/** + * @file testkeys/EC/384_EC.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated X.509 certificate as binary DER. +Certificate: + Data: + Version: 3 + Serial Number: + 23:8c + Issuer: CN=MatrixSSL Sample CA (Elliptic curve secp384r1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation, OU=Test + Validity: + Not Before: 2014/03/13 + Not After : 2017/03/12 + Subject: CN=MatrixSSL Sample Cert (Elliptic curve secp384r1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation, OU=Test + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 4b:01:73:c0:92:b5:50:aa:7f:00:21:de:6e:70:1b:97: + 70:71:fc:94:93:7b:5f:09:78:57:6b:43:55:43:19:21: + 10:92:79:57:cb:44:29:50:df:c9:72:04:da:c0:43:37 + e5:cd:08:6c:98:ed:fb:95:71:f8:a5:88:b7:12:27:51: + b8:10:7b:14:fd:29:23:e8:45:10:3f:81:84:f8:f6:a7: + c8:2a:6b:a8:2f:8b:9e:29:6e:fc:15:f1:23:e5:23:4b + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Subject Alternative Name: DNS + localhost + X509v3 Subject Alternative Name: iPAddress + 127.0.0.1 + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: 0x0 + X509v3 Extended Key Usage: 0x6 + TLS WWW server authentication + TLS WWW client authentication + X509v3 Subject Key Identifier: + a3:37:0f:e5:90:82:27:a3:9e:a4:99:09:8b:e8:6e:5a: + 11:94:ad:b1 + X509v3 Authority Key Identifier: + 44:ed:fc:8b:17:42:6e:61:f6:35:93:3d:3f:81:97:6f: + 67:68:5a:1b + Signature Algorithm: ecdsa-with-SHA384 + 30:64:02:30:6e:b2:3a:3d:ee:20:f3:67:ff:53:b8:e5: + 1e:77:7b:c8:02:c8:05:83:34:60:d6:70:04:31:1a:fc: + 32:e1:ec:8c:1a:a1:dd:97:09:cc:e7:5d:42:22:77:a9: + 9d:b3:70:a1:02:30:07:36:1d:2c:b7:19:1c:51:ca:40: + 8c:a5:ec:45:fd:85:3f:14:e6:b8:eb:cd:d3:fd:5f:10: + 80:62:a6:a8:ae:f6:c3:e9:0c:ca:da:3c:88:c3:82:b1: + 7f:58:5b:7a:25:19 +*/ +#define EC384_SIZE 750 +const static unsigned char EC384[EC384_SIZE] = + "\x30\x82\x02\xea\x30\x82\x02\x71\xa0\x03\x02\x01\x02\x02\x02\x23" + "\x8c\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x03\x30\x81\x98" + "\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30" + "\x09\x06\x03\x55\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03" + "\x55\x04\x07\x0c\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20" + "\x06\x03\x55\x04\x0a\x0c\x19\x49\x6e\x73\x69\x64\x65\x20\x53\x65" + "\x63\x75\x72\x65\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e" + "\x31\x0d\x30\x0b\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x31" + "\x37\x30\x35\x06\x03\x55\x04\x03\x0c\x2e\x4d\x61\x74\x72\x69\x78" + "\x53\x53\x4c\x20\x53\x61\x6d\x70\x6c\x65\x20\x43\x41\x20\x28\x45" + "\x6c\x6c\x69\x70\x74\x69\x63\x20\x63\x75\x72\x76\x65\x20\x73\x65" + "\x63\x70\x33\x38\x34\x72\x31\x29\x30\x1e\x17\x0d\x31\x34\x30\x33" + "\x31\x33\x32\x33\x32\x31\x32\x37\x5a\x17\x0d\x31\x37\x30\x33\x31" + "\x32\x32\x33\x32\x31\x32\x37\x5a\x30\x81\x9a\x31\x0b\x30\x09\x06" + "\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04" + "\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c\x07" + "\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06\x03\x55\x04\x0a" + "\x0c\x19\x49\x6e\x73\x69\x64\x65\x20\x53\x65\x63\x75\x72\x65\x20" + "\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30\x0b\x06" + "\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x31\x39\x30\x37\x06\x03" + "\x55\x04\x03\x0c\x30\x4d\x61\x74\x72\x69\x78\x53\x53\x4c\x20\x53" + "\x61\x6d\x70\x6c\x65\x20\x43\x65\x72\x74\x20\x28\x45\x6c\x6c\x69" + "\x70\x74\x69\x63\x20\x63\x75\x72\x76\x65\x20\x73\x65\x63\x70\x33" + "\x38\x34\x72\x31\x29\x30\x76\x30\x10\x06\x07\x2a\x86\x48\xce\x3d" + "\x02\x01\x06\x05\x2b\x81\x04\x00\x22\x03\x62\x00\x04\x4b\x01\x73" + "\xc0\x92\xb5\x50\xaa\x7f\x00\x21\xde\x6e\x70\x1b\x97\x70\x71\xfc" + "\x94\x93\x7b\x5f\x09\x78\x57\x6b\x43\x55\x43\x19\x21\x10\x92\x79" + "\x57\xcb\x44\x29\x50\xdf\xc9\x72\x04\xda\xc0\x43\x37\xe5\xcd\x08" + "\x6c\x98\xed\xfb\x95\x71\xf8\xa5\x88\xb7\x12\x27\x51\xb8\x10\x7b" + "\x14\xfd\x29\x23\xe8\x45\x10\x3f\x81\x84\xf8\xf6\xa7\xc8\x2a\x6b" + "\xa8\x2f\x8b\x9e\x29\x6e\xfc\x15\xf1\x23\xe5\x23\x4b\xa3\x81\x89" + "\x30\x81\x86\x30\x09\x06\x03\x55\x1d\x13\x04\x02\x30\x00\x30\x1d" + "\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xa3\x37\x0f\xe5\x90\x82\x27" + "\xa3\x9e\xa4\x99\x09\x8b\xe8\x6e\x5a\x11\x94\xad\xb1\x30\x1f\x06" + "\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x44\xed\xfc\x8b\x17\x42" + "\x6e\x61\xf6\x35\x93\x3d\x3f\x81\x97\x6f\x67\x68\x5a\x1b\x30\x1d" + "\x06\x03\x55\x1d\x25\x04\x16\x30\x14\x06\x08\x2b\x06\x01\x05\x05" + "\x07\x03\x01\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x02\x30\x1a\x06" + "\x03\x55\x1d\x11\x04\x13\x30\x11\x82\x09\x6c\x6f\x63\x61\x6c\x68" + "\x6f\x73\x74\x87\x04\x7f\x00\x00\x01\x30\x0a\x06\x08\x2a\x86\x48" + "\xce\x3d\x04\x03\x03\x03\x67\x00\x30\x64\x02\x30\x6e\xb2\x3a\x3d" + "\xee\x20\xf3\x67\xff\x53\xb8\xe5\x1e\x77\x7b\xc8\x02\xc8\x05\x83" + "\x34\x60\xd6\x70\x04\x31\x1a\xfc\x32\xe1\xec\x8c\x1a\xa1\xdd\x97" + "\x09\xcc\xe7\x5d\x42\x22\x77\xa9\x9d\xb3\x70\xa1\x02\x30\x07\x36" + "\x1d\x2c\xb7\x19\x1c\x51\xca\x40\x8c\xa5\xec\x45\xfd\x85\x3f\x14" + "\xe6\xb8\xeb\xcd\xd3\xfd\x5f\x10\x80\x62\xa6\xa8\xae\xf6\xc3\xe9" + "\x0c\xca\xda\x3c\x88\xc3\x82\xb1\x7f\x58\x5b\x7a\x25\x19"; diff --git a/testkeys/EC/384_EC.pem b/testkeys/EC/384_EC.pem new file mode 100644 index 0000000..a20b213 --- /dev/null +++ b/testkeys/EC/384_EC.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC6jCCAnGgAwIBAgICI4wwCgYIKoZIzj0EAwMwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDM4NHIxKTAeFw0xNDAz +MTMyMzIxMjdaFw0xNzAzMTIyMzIxMjdaMIGaMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxOTA3BgNVBAMMME1hdHJpeFNTTCBT +YW1wbGUgQ2VydCAoRWxsaXB0aWMgY3VydmUgc2VjcDM4NHIxKTB2MBAGByqGSM49 +AgEGBSuBBAAiA2IABEsBc8CStVCqfwAh3m5wG5dwcfyUk3tfCXhXa0NVQxkhEJJ5 +V8tEKVDfyXIE2sBDN+XNCGyY7fuVcfiliLcSJ1G4EHsU/Skj6EUQP4GE+PanyCpr +qC+Lnilu/BXxI+UjS6OBiTCBhjAJBgNVHRMEAjAAMB0GA1UdDgQWBBSjNw/lkIIn +o56kmQmL6G5aEZStsTAfBgNVHSMEGDAWgBRE7fyLF0JuYfY1kz0/gZdvZ2haGzAd +BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGgYDVR0RBBMwEYIJbG9jYWxo +b3N0hwR/AAABMAoGCCqGSM49BAMDA2cAMGQCMG6yOj3uIPNn/1O45R53e8gCyAWD +NGDWcAQxGvwy4eyMGqHdlwnM511CInepnbNwoQIwBzYdLLcZHFHKQIyl7EX9hT8U +5rjrzdP9XxCAYqaorvbD6QzK2jyIw4Kxf1hbeiUZ +-----END CERTIFICATE----- diff --git a/testkeys/EC/384_EC_CA.h b/testkeys/EC/384_EC_CA.h new file mode 100644 index 0000000..01ef80e --- /dev/null +++ b/testkeys/EC/384_EC_CA.h @@ -0,0 +1,95 @@ +/** + * @file testkeys/EC/384_EC_CA.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated X.509 certificate as binary DER. +Certificate: + Data: + Version: 3 + Serial Number: + 23:28 + Issuer: CN=MatrixSSL Sample CA (Elliptic curve secp384r1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation, OU=Test + Validity: + Not Before: 2014/03/13 + Not After : 2017/03/12 + Subject: CN=MatrixSSL Sample CA (Elliptic curve secp384r1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation, OU=Test + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 9e:04:34:99:ef:8a:25:1d:84:f2:f2:40:c4:d5:d1:53: + 7d:54:ec:20:36:df:1a:e2:e4:70:f8:d3:39:a0:39:18: + 3d:b1:fa:2d:ec:a2:c1:46:df:6d:94:8f:de:dc:d2:3d + 19:2f:16:ec:52:58:3a:80:c1:c3:bf:85:27:16:42:07: + e0:02:f1:d7:95:c9:10:ec:b0:a0:98:8a:42:b5:51:e8: + 21:fb:29:af:f9:45:a8:b2:76:10:46:ef:e4:ec:df:c1 + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: 0x4 + X509v3 Extended Key Usage: 0x0 + X509v3 Subject Key Identifier: + 44:ed:fc:8b:17:42:6e:61:f6:35:93:3d:3f:81:97:6f: + 67:68:5a:1b + X509v3 Authority Key Identifier: + 44:ed:fc:8b:17:42:6e:61:f6:35:93:3d:3f:81:97:6f: + 67:68:5a:1b + Signature Algorithm: ecdsa-with-SHA384 + 30:65:02:31:00:d4:64:ae:1c:db:14:f8:91:c8:17:d4: + ef:d0:8b:36:6e:f6:47:65:e5:b6:e8:ed:e4:b5:6d:44: + b8:70:60:a1:bb:bb:68:19:29:82:a4:fa:d5:e7:9f:0f: + b4:f9:a4:db:95:02:30:3e:b6:30:06:6d:ad:f0:25:08: + b6:30:fa:ce:84:33:2b:d6:c2:ae:6c:85:cc:42:cc:02: + 19:0c:18:7b:55:7b:17:3c:e7:ce:14:4f:74:80:29:cd: + 98:87:4d:46:58:a4:de +*/ +#define EC384CA_SIZE 704 +const static unsigned char EC384CA[EC384CA_SIZE] = + "\x30\x82\x02\xbc\x30\x82\x02\x42\xa0\x03\x02\x01\x02\x02\x02\x23" + "\x28\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x03\x30\x81\x98" + "\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30" + "\x09\x06\x03\x55\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03" + "\x55\x04\x07\x0c\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20" + "\x06\x03\x55\x04\x0a\x0c\x19\x49\x6e\x73\x69\x64\x65\x20\x53\x65" + "\x63\x75\x72\x65\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e" + "\x31\x0d\x30\x0b\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x31" + "\x37\x30\x35\x06\x03\x55\x04\x03\x0c\x2e\x4d\x61\x74\x72\x69\x78" + "\x53\x53\x4c\x20\x53\x61\x6d\x70\x6c\x65\x20\x43\x41\x20\x28\x45" + "\x6c\x6c\x69\x70\x74\x69\x63\x20\x63\x75\x72\x76\x65\x20\x73\x65" + "\x63\x70\x33\x38\x34\x72\x31\x29\x30\x1e\x17\x0d\x31\x34\x30\x33" + "\x31\x33\x32\x33\x32\x31\x32\x37\x5a\x17\x0d\x31\x37\x30\x33\x31" + "\x32\x32\x33\x32\x31\x32\x37\x5a\x30\x81\x98\x31\x0b\x30\x09\x06" + "\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04" + "\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c\x07" + "\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06\x03\x55\x04\x0a" + "\x0c\x19\x49\x6e\x73\x69\x64\x65\x20\x53\x65\x63\x75\x72\x65\x20" + "\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30\x0b\x06" + "\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x31\x37\x30\x35\x06\x03" + "\x55\x04\x03\x0c\x2e\x4d\x61\x74\x72\x69\x78\x53\x53\x4c\x20\x53" + "\x61\x6d\x70\x6c\x65\x20\x43\x41\x20\x28\x45\x6c\x6c\x69\x70\x74" + "\x69\x63\x20\x63\x75\x72\x76\x65\x20\x73\x65\x63\x70\x33\x38\x34" + "\x72\x31\x29\x30\x76\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01" + "\x06\x05\x2b\x81\x04\x00\x22\x03\x62\x00\x04\x9e\x04\x34\x99\xef" + "\x8a\x25\x1d\x84\xf2\xf2\x40\xc4\xd5\xd1\x53\x7d\x54\xec\x20\x36" + "\xdf\x1a\xe2\xe4\x70\xf8\xd3\x39\xa0\x39\x18\x3d\xb1\xfa\x2d\xec" + "\xa2\xc1\x46\xdf\x6d\x94\x8f\xde\xdc\xd2\x3d\x19\x2f\x16\xec\x52" + "\x58\x3a\x80\xc1\xc3\xbf\x85\x27\x16\x42\x07\xe0\x02\xf1\xd7\x95" + "\xc9\x10\xec\xb0\xa0\x98\x8a\x42\xb5\x51\xe8\x21\xfb\x29\xaf\xf9" + "\x45\xa8\xb2\x76\x10\x46\xef\xe4\xec\xdf\xc1\xa3\x5d\x30\x5b\x30" + "\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x02\x04\x30\x1d\x06\x03" + "\x55\x1d\x0e\x04\x16\x04\x14\x44\xed\xfc\x8b\x17\x42\x6e\x61\xf6" + "\x35\x93\x3d\x3f\x81\x97\x6f\x67\x68\x5a\x1b\x30\x1f\x06\x03\x55" + "\x1d\x23\x04\x18\x30\x16\x80\x14\x44\xed\xfc\x8b\x17\x42\x6e\x61" + "\xf6\x35\x93\x3d\x3f\x81\x97\x6f\x67\x68\x5a\x1b\x30\x0c\x06\x03" + "\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0a\x06\x08\x2a\x86" + "\x48\xce\x3d\x04\x03\x03\x03\x68\x00\x30\x65\x02\x31\x00\xd4\x64" + "\xae\x1c\xdb\x14\xf8\x91\xc8\x17\xd4\xef\xd0\x8b\x36\x6e\xf6\x47" + "\x65\xe5\xb6\xe8\xed\xe4\xb5\x6d\x44\xb8\x70\x60\xa1\xbb\xbb\x68" + "\x19\x29\x82\xa4\xfa\xd5\xe7\x9f\x0f\xb4\xf9\xa4\xdb\x95\x02\x30" + "\x3e\xb6\x30\x06\x6d\xad\xf0\x25\x08\xb6\x30\xfa\xce\x84\x33\x2b" + "\xd6\xc2\xae\x6c\x85\xcc\x42\xcc\x02\x19\x0c\x18\x7b\x55\x7b\x17" + "\x3c\xe7\xce\x14\x4f\x74\x80\x29\xcd\x98\x87\x4d\x46\x58\xa4\xde"; diff --git a/testkeys/EC/384_EC_CA.pem b/testkeys/EC/384_EC_CA.pem new file mode 100644 index 0000000..6240d6b --- /dev/null +++ b/testkeys/EC/384_EC_CA.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICvDCCAkKgAwIBAgICIygwCgYIKoZIzj0EAwMwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDM4NHIxKTAeFw0xNDAz +MTMyMzIxMjdaFw0xNzAzMTIyMzIxMjdaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3AzODRyMSkwdjAQBgcqhkjOPQIB +BgUrgQQAIgNiAASeBDSZ74olHYTy8kDE1dFTfVTsIDbfGuLkcPjTOaA5GD2x+i3s +osFG322Uj97c0j0ZLxbsUlg6gMHDv4UnFkIH4ALx15XJEOywoJiKQrVR6CH7Ka/5 +RaiydhBG7+Ts38GjXTBbMAsGA1UdDwQEAwICBDAdBgNVHQ4EFgQURO38ixdCbmH2 +NZM9P4GXb2doWhswHwYDVR0jBBgwFoAURO38ixdCbmH2NZM9P4GXb2doWhswDAYD +VR0TBAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA1GSuHNsU+JHIF9Tv0Is2bvZH +ZeW26O3ktW1EuHBgobu7aBkpgqT61eefD7T5pNuVAjA+tjAGba3wJQi2MPrOhDMr +1sKubIXMQswCGQwYe1V7FzznzhRPdIApzZiHTUZYpN4= +-----END CERTIFICATE----- diff --git a/testkeys/EC/384_EC_CA_KEY.pem b/testkeys/EC/384_EC_CA_KEY.pem new file mode 100644 index 0000000..87beb1f --- /dev/null +++ b/testkeys/EC/384_EC_CA_KEY.pem @@ -0,0 +1,9 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQAIg== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDC48uMEcK4oK2JhdRe+Ms/fNrA/IaGr3IDVfE+BB673+/7LOIa0GewO +CF92Dx4N9eWgBwYFK4EEACKhZANiAASeBDSZ74olHYTy8kDE1dFTfVTsIDbfGuLk +cPjTOaA5GD2x+i3sosFG322Uj97c0j0ZLxbsUlg6gMHDv4UnFkIH4ALx15XJEOyw +oJiKQrVR6CH7Ka/5RaiydhBG7+Ts38E= +-----END EC PRIVATE KEY----- diff --git a/testkeys/EC/384_EC_KEY.h b/testkeys/EC/384_EC_KEY.h new file mode 100644 index 0000000..54960e2 --- /dev/null +++ b/testkeys/EC/384_EC_KEY.h @@ -0,0 +1,22 @@ +/** + * @file testkeys/EC/384_EC_KEY.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated private key as binary DER. +*/ +#define EC384KEY_SIZE 167 +const static unsigned char EC384KEY[EC384KEY_SIZE] = + "\x30\x81\xa4\x02\x01\x01\x04\x30\x67\xef\xed\xab\x17\x57\x04\x57" + "\xca\xc0\xba\xe8\xf4\x44\x52\xa2\x40\xc1\x2c\x62\x2b\x53\x15\x7c" + "\xda\x77\xb2\x6b\x03\xd0\x31\x23\x9b\x10\xc0\x49\x35\xd6\x6b\x1a" + "\xae\xe7\x5d\xe1\x21\x87\x04\x1a\xa0\x07\x06\x05\x2b\x81\x04\x00" + "\x22\xa1\x64\x03\x62\x00\x04\x4b\x01\x73\xc0\x92\xb5\x50\xaa\x7f" + "\x00\x21\xde\x6e\x70\x1b\x97\x70\x71\xfc\x94\x93\x7b\x5f\x09\x78" + "\x57\x6b\x43\x55\x43\x19\x21\x10\x92\x79\x57\xcb\x44\x29\x50\xdf" + "\xc9\x72\x04\xda\xc0\x43\x37\xe5\xcd\x08\x6c\x98\xed\xfb\x95\x71" + "\xf8\xa5\x88\xb7\x12\x27\x51\xb8\x10\x7b\x14\xfd\x29\x23\xe8\x45" + "\x10\x3f\x81\x84\xf8\xf6\xa7\xc8\x2a\x6b\xa8\x2f\x8b\x9e\x29\x6e" + "\xfc\x15\xf1\x23\xe5\x23\x4b"; diff --git a/testkeys/EC/384_EC_KEY.pem b/testkeys/EC/384_EC_KEY.pem new file mode 100644 index 0000000..7ac5f92 --- /dev/null +++ b/testkeys/EC/384_EC_KEY.pem @@ -0,0 +1,9 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQAIg== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDBn7+2rF1cEV8rAuuj0RFKiQMEsYitTFXzad7JrA9AxI5sQwEk11msa +rudd4SGHBBqgBwYFK4EEACKhZANiAARLAXPAkrVQqn8AId5ucBuXcHH8lJN7Xwl4 +V2tDVUMZIRCSeVfLRClQ38lyBNrAQzflzQhsmO37lXH4pYi3EidRuBB7FP0pI+hF +ED+BhPj2p8gqa6gvi54pbvwV8SPlI0s= +-----END EC PRIVATE KEY----- diff --git a/testkeys/EC/521_EC.h b/testkeys/EC/521_EC.h new file mode 100644 index 0000000..b3b8023 --- /dev/null +++ b/testkeys/EC/521_EC.h @@ -0,0 +1,115 @@ +/** + * @file testkeys/EC/521_EC.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated X.509 certificate as binary DER. +Certificate: + Data: + Version: 3 + Serial Number: + 24:54 + Issuer: CN=MatrixSSL Sample CA (Elliptic curve secp521r1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation, OU=Test + Validity: + Not Before: 2014/03/13 + Not After : 2017/03/12 + Subject: CN=MatrixSSL Sample Cert (Elliptic curve secp521r1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation, OU=Test + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (528 bit) + pub: + 0a:5a:3b:b8:c6:16:85:2e:87:67:a6:7b:5c:6e:29:8a: + 5e:e2:11:03:83:28:20:58:3e:d3:5a:b5:68:d9:b7:ef: + ec:16:95:c1:e8:7d:b8:07:f4:16:50:3d:30:61:78:95: + 75:eb:68:0a:0b:ff:5e:08:5d:75:66:01:af:29:1f:d5: + 5d + c5:f3:4d:5a:63:ef:07:49:ae:89:75:b2:9a:a0:6b:45: + 6f:4f:d5:b3:47:a3:cc:7c:ac:11:24:89:9a:5d:63:ba: + 85:c2:cf:c3:7b:43:d2:ce:fd:dc:ea:96:76:ad:a4:61: + 8a:a3:fb:a6:26:68:50:2e:80:82:ad:71:c5:f8:cb:20: + ee + ASN1 OID: secp521r1 + X509v3 extensions: + X509v3 Subject Alternative Name: DNS + localhost + X509v3 Subject Alternative Name: iPAddress + 127.0.0.1 + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: 0x0 + X509v3 Extended Key Usage: 0x6 + TLS WWW server authentication + TLS WWW client authentication + X509v3 Subject Key Identifier: + 26:3b:12:bd:2f:a1:9f:3f:d8:35:e3:d1:83:23:21:eb: + 35:da:d7:86 + X509v3 Authority Key Identifier: + 19:b0:be:a4:9d:8b:3c:44:e5:86:b5:17:a1:d6:0d:ba: + 42:1d:b8:a9 + Signature Algorithm: ecdsa-with-SHA384 + 30:81:87:02:42:01:e9:f2:13:2d:1e:a1:ca:18:1b:52: + 56:ad:b3:c3:25:cd:8b:1c:e5:7b:0c:a7:9b:23:9d:15: + ee:b4:65:e9:b0:87:de:cc:22:be:76:43:4e:45:cc:23: + 78:23:d7:bc:44:7d:4c:fd:6c:8c:93:32:03:ad:f8:9e: + 1a:9e:56:26:bb:68:bb:02:41:01:7b:37:74:e9:ba:77: + c6:c1:a5:00:46:05:42:06:80:c0:66:7f:1b:9d:2f:eb: + b4:6f:de:98:31:de:66:6e:f3:c9:aa:58:15:02:64:27: + e6:db:36:49:b5:16:29:b6:8f:ba:1a:9e:0a:7b:06:62: + 98:60:fb:8c:22:e8:ee:91:9e:02 +*/ +#define EC521_SIZE 825 +const static unsigned char EC521[EC521_SIZE] = + "\x30\x82\x03\x35\x30\x82\x02\x97\xa0\x03\x02\x01\x02\x02\x02\x24" + "\x54\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x03\x30\x81\x98" + "\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30" + "\x09\x06\x03\x55\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03" + "\x55\x04\x07\x0c\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20" + "\x06\x03\x55\x04\x0a\x0c\x19\x49\x6e\x73\x69\x64\x65\x20\x53\x65" + "\x63\x75\x72\x65\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e" + "\x31\x0d\x30\x0b\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x31" + "\x37\x30\x35\x06\x03\x55\x04\x03\x0c\x2e\x4d\x61\x74\x72\x69\x78" + "\x53\x53\x4c\x20\x53\x61\x6d\x70\x6c\x65\x20\x43\x41\x20\x28\x45" + "\x6c\x6c\x69\x70\x74\x69\x63\x20\x63\x75\x72\x76\x65\x20\x73\x65" + "\x63\x70\x35\x32\x31\x72\x31\x29\x30\x1e\x17\x0d\x31\x34\x30\x33" + "\x31\x33\x32\x33\x32\x31\x33\x31\x5a\x17\x0d\x31\x37\x30\x33\x31" + "\x32\x32\x33\x32\x31\x33\x31\x5a\x30\x81\x9a\x31\x0b\x30\x09\x06" + "\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04" + "\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c\x07" + "\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06\x03\x55\x04\x0a" + "\x0c\x19\x49\x6e\x73\x69\x64\x65\x20\x53\x65\x63\x75\x72\x65\x20" + "\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30\x0b\x06" + "\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x31\x39\x30\x37\x06\x03" + "\x55\x04\x03\x0c\x30\x4d\x61\x74\x72\x69\x78\x53\x53\x4c\x20\x53" + "\x61\x6d\x70\x6c\x65\x20\x43\x65\x72\x74\x20\x28\x45\x6c\x6c\x69" + "\x70\x74\x69\x63\x20\x63\x75\x72\x76\x65\x20\x73\x65\x63\x70\x35" + "\x32\x31\x72\x31\x29\x30\x81\x9b\x30\x10\x06\x07\x2a\x86\x48\xce" + "\x3d\x02\x01\x06\x05\x2b\x81\x04\x00\x23\x03\x81\x86\x00\x04\x00" + "\x0a\x5a\x3b\xb8\xc6\x16\x85\x2e\x87\x67\xa6\x7b\x5c\x6e\x29\x8a" + "\x5e\xe2\x11\x03\x83\x28\x20\x58\x3e\xd3\x5a\xb5\x68\xd9\xb7\xef" + "\xec\x16\x95\xc1\xe8\x7d\xb8\x07\xf4\x16\x50\x3d\x30\x61\x78\x95" + "\x75\xeb\x68\x0a\x0b\xff\x5e\x08\x5d\x75\x66\x01\xaf\x29\x1f\xd5" + "\x5d\x00\xc5\xf3\x4d\x5a\x63\xef\x07\x49\xae\x89\x75\xb2\x9a\xa0" + "\x6b\x45\x6f\x4f\xd5\xb3\x47\xa3\xcc\x7c\xac\x11\x24\x89\x9a\x5d" + "\x63\xba\x85\xc2\xcf\xc3\x7b\x43\xd2\xce\xfd\xdc\xea\x96\x76\xad" + "\xa4\x61\x8a\xa3\xfb\xa6\x26\x68\x50\x2e\x80\x82\xad\x71\xc5\xf8" + "\xcb\x20\xee\xa3\x81\x89\x30\x81\x86\x30\x09\x06\x03\x55\x1d\x13" + "\x04\x02\x30\x00\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x26" + "\x3b\x12\xbd\x2f\xa1\x9f\x3f\xd8\x35\xe3\xd1\x83\x23\x21\xeb\x35" + "\xda\xd7\x86\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14" + "\x19\xb0\xbe\xa4\x9d\x8b\x3c\x44\xe5\x86\xb5\x17\xa1\xd6\x0d\xba" + "\x42\x1d\xb8\xa9\x30\x1d\x06\x03\x55\x1d\x25\x04\x16\x30\x14\x06" + "\x08\x2b\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2b\x06\x01\x05\x05" + "\x07\x03\x02\x30\x1a\x06\x03\x55\x1d\x11\x04\x13\x30\x11\x82\x09" + "\x6c\x6f\x63\x61\x6c\x68\x6f\x73\x74\x87\x04\x7f\x00\x00\x01\x30" + "\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x03\x03\x81\x8b\x00\x30" + "\x81\x87\x02\x42\x01\xe9\xf2\x13\x2d\x1e\xa1\xca\x18\x1b\x52\x56" + "\xad\xb3\xc3\x25\xcd\x8b\x1c\xe5\x7b\x0c\xa7\x9b\x23\x9d\x15\xee" + "\xb4\x65\xe9\xb0\x87\xde\xcc\x22\xbe\x76\x43\x4e\x45\xcc\x23\x78" + "\x23\xd7\xbc\x44\x7d\x4c\xfd\x6c\x8c\x93\x32\x03\xad\xf8\x9e\x1a" + "\x9e\x56\x26\xbb\x68\xbb\x02\x41\x01\x7b\x37\x74\xe9\xba\x77\xc6" + "\xc1\xa5\x00\x46\x05\x42\x06\x80\xc0\x66\x7f\x1b\x9d\x2f\xeb\xb4" + "\x6f\xde\x98\x31\xde\x66\x6e\xf3\xc9\xaa\x58\x15\x02\x64\x27\xe6" + "\xdb\x36\x49\xb5\x16\x29\xb6\x8f\xba\x1a\x9e\x0a\x7b\x06\x62\x98" + "\x60\xfb\x8c\x22\xe8\xee\x91\x9e\x02"; diff --git a/testkeys/EC/521_EC.pem b/testkeys/EC/521_EC.pem new file mode 100644 index 0000000..e4043af --- /dev/null +++ b/testkeys/EC/521_EC.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDNTCCApegAwIBAgICJFQwCgYIKoZIzj0EAwMwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDUyMXIxKTAeFw0xNDAz +MTMyMzIxMzFaFw0xNzAzMTIyMzIxMzFaMIGaMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxOTA3BgNVBAMMME1hdHJpeFNTTCBT +YW1wbGUgQ2VydCAoRWxsaXB0aWMgY3VydmUgc2VjcDUyMXIxKTCBmzAQBgcqhkjO +PQIBBgUrgQQAIwOBhgAEAApaO7jGFoUuh2eme1xuKYpe4hEDgyggWD7TWrVo2bfv +7BaVweh9uAf0FlA9MGF4lXXraAoL/14IXXVmAa8pH9VdAMXzTVpj7wdJrol1spqg +a0VvT9WzR6PMfKwRJImaXWO6hcLPw3tD0s793OqWdq2kYYqj+6YmaFAugIKtccX4 +yyDuo4GJMIGGMAkGA1UdEwQCMAAwHQYDVR0OBBYEFCY7Er0voZ8/2DXj0YMjIes1 +2teGMB8GA1UdIwQYMBaAFBmwvqSdizxE5Ya1F6HWDbpCHbipMB0GA1UdJQQWMBQG +CCsGAQUFBwMBBggrBgEFBQcDAjAaBgNVHREEEzARgglsb2NhbGhvc3SHBH8AAAEw +CgYIKoZIzj0EAwMDgYsAMIGHAkIB6fITLR6hyhgbUlats8MlzYsc5XsMp5sjnRXu +tGXpsIfezCK+dkNORcwjeCPXvER9TP1sjJMyA634nhqeVia7aLsCQQF7N3TpunfG +waUARgVCBoDAZn8bnS/rtG/emDHeZm7zyapYFQJkJ+bbNkm1Fim2j7oangp7BmKY +YPuMIujukZ4C +-----END CERTIFICATE----- diff --git a/testkeys/EC/521_EC_CA.h b/testkeys/EC/521_EC_CA.h new file mode 100644 index 0000000..7008a81 --- /dev/null +++ b/testkeys/EC/521_EC_CA.h @@ -0,0 +1,106 @@ +/** + * @file testkeys/EC/521_EC_CA.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated X.509 certificate as binary DER. +Certificate: + Data: + Version: 3 + Serial Number: + 23:f0 + Issuer: CN=MatrixSSL Sample CA (Elliptic curve secp521r1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation, OU=Test + Validity: + Not Before: 2014/03/13 + Not After : 2017/03/12 + Subject: CN=MatrixSSL Sample CA (Elliptic curve secp521r1), C=US, ST=WA, L=Seattle, O=Inside Secure Corporation, OU=Test + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (528 bit) + pub: + 01:2b:43:d8:8d:9f:d5:2f:9d:55:0b:fe:72:0b:32:d7: + 8e:42:c4:02:97:b3:cd:77:15:a1:ea:f6:64:35:72:72: + 67:b3:5f:77:26:6d:6f:77:2b:4b:a1:9a:db:8c:76:c4: + dc:9d:60:2d:3b:5e:07:f1:a5:75:11:22:7a:f5:ef:99: + 77:44 + c4:2d:a7:13:c0:c7:8b:d5:96:92:6d:ae:84:95:25:1f: + b0:68:7b:89:75:bf:46:b6:9e:a2:ac:70:f6:ec:17:6e: + 98:2e:0b:ac:13:78:5f:54:8c:00:bd:3a:8c:5c:d7:a4: + 86:b5:9c:04:67:75:e0:dc:4d:8a:42:46:ec:e4:5d:f1: + aa + ASN1 OID: secp521r1 + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: 0x4 + X509v3 Extended Key Usage: 0x0 + X509v3 Subject Key Identifier: + 19:b0:be:a4:9d:8b:3c:44:e5:86:b5:17:a1:d6:0d:ba: + 42:1d:b8:a9 + X509v3 Authority Key Identifier: + 19:b0:be:a4:9d:8b:3c:44:e5:86:b5:17:a1:d6:0d:ba: + 42:1d:b8:a9 + Signature Algorithm: ecdsa-with-SHA384 + 30:81:87:02:42:01:37:98:68:a0:6b:b3:92:d3:cb:6b: + 50:ae:79:c1:87:43:00:ed:2b:33:0c:6e:1c:ed:b8:89: + ea:39:03:4f:a0:80:85:71:0b:28:aa:50:12:c1:f9:96: + f5:3a:90:9e:c4:4c:7a:64:47:e8:1e:9e:9f:e4:a2:13: + 4d:44:13:3a:72:f7:a4:02:41:33:88:ef:6a:d3:51:23: + d0:64:41:2a:de:75:da:46:b5:ac:9d:70:6e:6c:e9:51: + 62:66:b5:87:7d:31:ac:a7:a9:11:f1:17:9f:c1:85:3b: + a6:86:65:e9:90:d6:6b:3c:a8:9e:90:43:2e:38:8b:45: + 32:b0:5b:cd:68:77:0f:c3:37:7e +*/ +#define EC521CA_SIZE 778 +const static unsigned char EC521CA[EC521CA_SIZE] = + "\x30\x82\x03\x06\x30\x82\x02\x68\xa0\x03\x02\x01\x02\x02\x02\x23" + "\xf0\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x03\x30\x81\x98" + "\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30" + "\x09\x06\x03\x55\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03" + "\x55\x04\x07\x0c\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20" + "\x06\x03\x55\x04\x0a\x0c\x19\x49\x6e\x73\x69\x64\x65\x20\x53\x65" + "\x63\x75\x72\x65\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e" + "\x31\x0d\x30\x0b\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x31" + "\x37\x30\x35\x06\x03\x55\x04\x03\x0c\x2e\x4d\x61\x74\x72\x69\x78" + "\x53\x53\x4c\x20\x53\x61\x6d\x70\x6c\x65\x20\x43\x41\x20\x28\x45" + "\x6c\x6c\x69\x70\x74\x69\x63\x20\x63\x75\x72\x76\x65\x20\x73\x65" + "\x63\x70\x35\x32\x31\x72\x31\x29\x30\x1e\x17\x0d\x31\x34\x30\x33" + "\x31\x33\x32\x33\x32\x31\x33\x31\x5a\x17\x0d\x31\x37\x30\x33\x31" + "\x32\x32\x33\x32\x31\x33\x31\x5a\x30\x81\x98\x31\x0b\x30\x09\x06" + "\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04" + "\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c\x07" + "\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06\x03\x55\x04\x0a" + "\x0c\x19\x49\x6e\x73\x69\x64\x65\x20\x53\x65\x63\x75\x72\x65\x20" + "\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30\x0b\x06" + "\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x31\x37\x30\x35\x06\x03" + "\x55\x04\x03\x0c\x2e\x4d\x61\x74\x72\x69\x78\x53\x53\x4c\x20\x53" + "\x61\x6d\x70\x6c\x65\x20\x43\x41\x20\x28\x45\x6c\x6c\x69\x70\x74" + "\x69\x63\x20\x63\x75\x72\x76\x65\x20\x73\x65\x63\x70\x35\x32\x31" + "\x72\x31\x29\x30\x81\x9b\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02" + "\x01\x06\x05\x2b\x81\x04\x00\x23\x03\x81\x86\x00\x04\x01\x2b\x43" + "\xd8\x8d\x9f\xd5\x2f\x9d\x55\x0b\xfe\x72\x0b\x32\xd7\x8e\x42\xc4" + "\x02\x97\xb3\xcd\x77\x15\xa1\xea\xf6\x64\x35\x72\x72\x67\xb3\x5f" + "\x77\x26\x6d\x6f\x77\x2b\x4b\xa1\x9a\xdb\x8c\x76\xc4\xdc\x9d\x60" + "\x2d\x3b\x5e\x07\xf1\xa5\x75\x11\x22\x7a\xf5\xef\x99\x77\x44\x00" + "\xc4\x2d\xa7\x13\xc0\xc7\x8b\xd5\x96\x92\x6d\xae\x84\x95\x25\x1f" + "\xb0\x68\x7b\x89\x75\xbf\x46\xb6\x9e\xa2\xac\x70\xf6\xec\x17\x6e" + "\x98\x2e\x0b\xac\x13\x78\x5f\x54\x8c\x00\xbd\x3a\x8c\x5c\xd7\xa4" + "\x86\xb5\x9c\x04\x67\x75\xe0\xdc\x4d\x8a\x42\x46\xec\xe4\x5d\xf1" + "\xaa\xa3\x5d\x30\x5b\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02" + "\x02\x04\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x19\xb0\xbe" + "\xa4\x9d\x8b\x3c\x44\xe5\x86\xb5\x17\xa1\xd6\x0d\xba\x42\x1d\xb8" + "\xa9\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x19\xb0" + "\xbe\xa4\x9d\x8b\x3c\x44\xe5\x86\xb5\x17\xa1\xd6\x0d\xba\x42\x1d" + "\xb8\xa9\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff" + "\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x03\x03\x81\x8b\x00" + "\x30\x81\x87\x02\x42\x01\x37\x98\x68\xa0\x6b\xb3\x92\xd3\xcb\x6b" + "\x50\xae\x79\xc1\x87\x43\x00\xed\x2b\x33\x0c\x6e\x1c\xed\xb8\x89" + "\xea\x39\x03\x4f\xa0\x80\x85\x71\x0b\x28\xaa\x50\x12\xc1\xf9\x96" + "\xf5\x3a\x90\x9e\xc4\x4c\x7a\x64\x47\xe8\x1e\x9e\x9f\xe4\xa2\x13" + "\x4d\x44\x13\x3a\x72\xf7\xa4\x02\x41\x33\x88\xef\x6a\xd3\x51\x23" + "\xd0\x64\x41\x2a\xde\x75\xda\x46\xb5\xac\x9d\x70\x6e\x6c\xe9\x51" + "\x62\x66\xb5\x87\x7d\x31\xac\xa7\xa9\x11\xf1\x17\x9f\xc1\x85\x3b" + "\xa6\x86\x65\xe9\x90\xd6\x6b\x3c\xa8\x9e\x90\x43\x2e\x38\x8b\x45" + "\x32\xb0\x5b\xcd\x68\x77\x0f\xc3\x37\x7e"; diff --git a/testkeys/EC/521_EC_CA.pem b/testkeys/EC/521_EC_CA.pem new file mode 100644 index 0000000..c85911e --- /dev/null +++ b/testkeys/EC/521_EC_CA.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBjCCAmigAwIBAgICI/AwCgYIKoZIzj0EAwMwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDUyMXIxKTAeFw0xNDAz +MTMyMzIxMzFaFw0xNzAzMTIyMzIxMzFaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3A1MjFyMSkwgZswEAYHKoZIzj0C +AQYFK4EEACMDgYYABAErQ9iNn9UvnVUL/nILMteOQsQCl7PNdxWh6vZkNXJyZ7Nf +dyZtb3crS6Ga24x2xNydYC07XgfxpXURInr175l3RADELacTwMeL1ZaSba6ElSUf +sGh7iXW/Rraeoqxw9uwXbpguC6wTeF9UjAC9Ooxc16SGtZwEZ3Xg3E2KQkbs5F3x +qqNdMFswCwYDVR0PBAQDAgIEMB0GA1UdDgQWBBQZsL6knYs8ROWGtReh1g26Qh24 +qTAfBgNVHSMEGDAWgBQZsL6knYs8ROWGtReh1g26Qh24qTAMBgNVHRMEBTADAQH/ +MAoGCCqGSM49BAMDA4GLADCBhwJCATeYaKBrs5LTy2tQrnnBh0MA7SszDG4c7biJ +6jkDT6CAhXELKKpQEsH5lvU6kJ7ETHpkR+genp/kohNNRBM6cvekAkEziO9q01Ej +0GRBKt512ka1rJ1wbmzpUWJmtYd9MaynqRHxF5/BhTumhmXpkNZrPKiekEMuOItF +MrBbzWh3D8M3fg== +-----END CERTIFICATE----- diff --git a/testkeys/EC/521_EC_CA_KEY.pem b/testkeys/EC/521_EC_CA_KEY.pem new file mode 100644 index 0000000..d7f184a --- /dev/null +++ b/testkeys/EC/521_EC_CA_KEY.pem @@ -0,0 +1,10 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQAIw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MIHcAgEBBEIBPbiFyZPxeyJdqSuWy5gGY7YKybu1ALGWbdeWNSEZR7W7x+9gsP8p +l28EFtOSvxYM3pRypLUqjOFd+OMWXcEEd9ygBwYFK4EEACOhgYkDgYYABAErQ9iN +n9UvnVUL/nILMteOQsQCl7PNdxWh6vZkNXJyZ7NfdyZtb3crS6Ga24x2xNydYC07 +XgfxpXURInr175l3RADELacTwMeL1ZaSba6ElSUfsGh7iXW/Rraeoqxw9uwXbpgu +C6wTeF9UjAC9Ooxc16SGtZwEZ3Xg3E2KQkbs5F3xqg== +-----END EC PRIVATE KEY----- diff --git a/testkeys/EC/521_EC_KEY.h b/testkeys/EC/521_EC_KEY.h new file mode 100644 index 0000000..9bf6d1a --- /dev/null +++ b/testkeys/EC/521_EC_KEY.h @@ -0,0 +1,25 @@ +/** + * @file testkeys/EC/521_EC_KEY.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated private key as binary DER. +*/ +#define EC521KEY_SIZE 223 +const static unsigned char EC521KEY[EC521KEY_SIZE] = + "\x30\x81\xdc\x02\x01\x01\x04\x42\x01\x3d\xb2\x6e\x9f\xc0\xe3\x98" + "\x53\xa6\x37\x6d\x84\x18\xa6\x08\xb6\xc2\x3f\xb6\x01\x2a\xe6\xed" + "\x46\xf6\xbf\x9f\x42\x09\x76\xfe\x06\x2f\xdd\xee\x81\xd5\x38\x0f" + "\x23\x21\x91\xce\xbb\x13\x7a\xa2\x02\x12\xa3\xfb\xde\x3c\x76\xec" + "\x61\x42\x92\x25\xc0\x84\x10\xc8\x75\x4f\xa0\x07\x06\x05\x2b\x81" + "\x04\x00\x23\xa1\x81\x89\x03\x81\x86\x00\x04\x00\x0a\x5a\x3b\xb8" + "\xc6\x16\x85\x2e\x87\x67\xa6\x7b\x5c\x6e\x29\x8a\x5e\xe2\x11\x03" + "\x83\x28\x20\x58\x3e\xd3\x5a\xb5\x68\xd9\xb7\xef\xec\x16\x95\xc1" + "\xe8\x7d\xb8\x07\xf4\x16\x50\x3d\x30\x61\x78\x95\x75\xeb\x68\x0a" + "\x0b\xff\x5e\x08\x5d\x75\x66\x01\xaf\x29\x1f\xd5\x5d\x00\xc5\xf3" + "\x4d\x5a\x63\xef\x07\x49\xae\x89\x75\xb2\x9a\xa0\x6b\x45\x6f\x4f" + "\xd5\xb3\x47\xa3\xcc\x7c\xac\x11\x24\x89\x9a\x5d\x63\xba\x85\xc2" + "\xcf\xc3\x7b\x43\xd2\xce\xfd\xdc\xea\x96\x76\xad\xa4\x61\x8a\xa3" + "\xfb\xa6\x26\x68\x50\x2e\x80\x82\xad\x71\xc5\xf8\xcb\x20\xee"; diff --git a/testkeys/EC/521_EC_KEY.pem b/testkeys/EC/521_EC_KEY.pem new file mode 100644 index 0000000..1ae8208 --- /dev/null +++ b/testkeys/EC/521_EC_KEY.pem @@ -0,0 +1,10 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQAIw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MIHcAgEBBEIBPbJun8DjmFOmN22EGKYItsI/tgEq5u1G9r+fQgl2/gYv3e6B1TgP +IyGRzrsTeqICEqP73jx27GFCkiXAhBDIdU+gBwYFK4EEACOhgYkDgYYABAAKWju4 +xhaFLodnpntcbimKXuIRA4MoIFg+01q1aNm37+wWlcHofbgH9BZQPTBheJV162gK +C/9eCF11ZgGvKR/VXQDF801aY+8HSa6JdbKaoGtFb0/Vs0ejzHysESSJml1juoXC +z8N7Q9LO/dzqlnatpGGKo/umJmhQLoCCrXHF+Msg7g== +-----END EC PRIVATE KEY----- diff --git a/testkeys/EC/ALL_EC_CAS.h b/testkeys/EC/ALL_EC_CAS.h new file mode 100644 index 0000000..05ac46c --- /dev/null +++ b/testkeys/EC/ALL_EC_CAS.h @@ -0,0 +1,268 @@ +/** + * @file ALL_EC_CAS.h + * @version $Format:%h%d$ + * + * Summary. + */ +unsigned char ECCAS[] = { +48, 130, 2, 99, 48, 130, 2, 25, 160, 3, 2, 1, 2, +2, 2, 27, 88, 48, 10, 6, 8, 42, 134, 72, 206, 61, +4, 3, 2, 48, 129, 154, 49, 11, 48, 9, 6, 3, 85, +4, 6, 19, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, +4, 8, 12, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, +4, 7, 12, 7, 83, 101, 97, 116, 116, 108, 101, 49, 35, +48, 33, 6, 3, 85, 4, 10, 12, 26, 73, 110, 115, 105, +100, 101, 32, 83, 101, 99, 117, 114, 101, 32, 67, 111, 114, +112, 111, 114, 97, 116, 105, 111, 110, 46, 49, 13, 48, 11, +6, 3, 85, 4, 11, 12, 4, 84, 101, 115, 116, 49, 56, +48, 54, 6, 3, 85, 4, 3, 12, 47, 77, 97, 116, 114, +105, 120, 83, 83, 76, 32, 83, 97, 109, 112, 108, 101, 32, +67, 65, 32, 40, 69, 108, 108, 105, 112, 116, 105, 99, 32, +99, 117, 114, 118, 101, 32, 112, 114, 105, 109, 101, 49, 57, +50, 118, 49, 41, 48, 30, 23, 13, 49, 52, 48, 51, 49, +51, 50, 51, 49, 56, 50, 53, 90, 23, 13, 49, 55, 48, +51, 49, 50, 50, 51, 49, 56, 50, 53, 90, 48, 129, 154, +49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, +49, 11, 48, 9, 6, 3, 85, 4, 8, 12, 2, 87, 65, +49, 16, 48, 14, 6, 3, 85, 4, 7, 12, 7, 83, 101, +97, 116, 116, 108, 101, 49, 35, 48, 33, 6, 3, 85, 4, +10, 12, 26, 73, 110, 115, 105, 100, 101, 32, 83, 101, 99, +117, 114, 101, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, +111, 110, 46, 49, 13, 48, 11, 6, 3, 85, 4, 11, 12, +4, 84, 101, 115, 116, 49, 56, 48, 54, 6, 3, 85, 4, +3, 12, 47, 77, 97, 116, 114, 105, 120, 83, 83, 76, 32, +83, 97, 109, 112, 108, 101, 32, 67, 65, 32, 40, 69, 108, +108, 105, 112, 116, 105, 99, 32, 99, 117, 114, 118, 101, 32, +112, 114, 105, 109, 101, 49, 57, 50, 118, 49, 41, 48, 73, +48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, +42, 134, 72, 206, 61, 3, 1, 1, 3, 50, 0, 4, 89, +238, 161, 93, 187, 158, 50, 130, 124, 152, 90, 184, 112, 99, +7, 175, 242, 13, 179, 21, 39, 140, 1, 118, 65, 182, 106, +154, 161, 69, 136, 35, 251, 11, 230, 61, 128, 214, 10, 204, +251, 0, 87, 238, 24, 147, 100, 224, 163, 93, 48, 91, 48, +11, 6, 3, 85, 29, 15, 4, 4, 3, 2, 2, 4, 48, +29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 147, 63, 179, +90, 56, 85, 221, 180, 214, 110, 132, 204, 102, 206, 140, 38, +91, 28, 23, 32, 48, 31, 6, 3, 85, 29, 35, 4, 24, +48, 22, 128, 20, 147, 63, 179, 90, 56, 85, 221, 180, 214, +110, 132, 204, 102, 206, 140, 38, 91, 28, 23, 32, 48, 12, +6, 3, 85, 29, 19, 4, 5, 48, 3, 1, 1, 255, 48, +10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 3, 56, +0, 48, 53, 2, 25, 0, 236, 147, 226, 123, 177, 108, 244, +138, 40, 188, 46, 217, 183, 64, 111, 103, 228, 53, 209, 162, +153, 204, 1, 241, 2, 24, 113, 66, 191, 252, 72, 191, 162, +239, 217, 191, 233, 227, 165, 46, 71, 62, 19, 253, 197, 225, +197, 9, 7, 114, +48, 130, 2, 108, 48, 130, 2, 26, 160, 3, 2, 1, 2, +2, 2, 31, 64, 48, 10, 6, 8, 42, 134, 72, 206, 61, +4, 3, 2, 48, 129, 152, 49, 11, 48, 9, 6, 3, 85, +4, 6, 19, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, +4, 8, 12, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, +4, 7, 12, 7, 83, 101, 97, 116, 116, 108, 101, 49, 34, +48, 32, 6, 3, 85, 4, 10, 12, 25, 73, 110, 115, 105, +100, 101, 32, 83, 101, 99, 117, 114, 101, 32, 67, 111, 114, +112, 111, 114, 97, 116, 105, 111, 110, 49, 13, 48, 11, 6, +3, 85, 4, 11, 12, 4, 84, 101, 115, 116, 49, 55, 48, +53, 6, 3, 85, 4, 3, 12, 46, 77, 97, 116, 114, 105, +120, 83, 83, 76, 32, 83, 97, 109, 112, 108, 101, 32, 67, +65, 32, 40, 69, 108, 108, 105, 112, 116, 105, 99, 32, 99, +117, 114, 118, 101, 32, 115, 101, 99, 112, 50, 50, 52, 114, +49, 41, 48, 30, 23, 13, 49, 52, 48, 51, 49, 51, 50, +51, 50, 48, 52, 48, 90, 23, 13, 49, 55, 48, 51, 49, +50, 50, 51, 50, 48, 52, 48, 90, 48, 129, 152, 49, 11, +48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 11, +48, 9, 6, 3, 85, 4, 8, 12, 2, 87, 65, 49, 16, +48, 14, 6, 3, 85, 4, 7, 12, 7, 83, 101, 97, 116, +116, 108, 101, 49, 34, 48, 32, 6, 3, 85, 4, 10, 12, +25, 73, 110, 115, 105, 100, 101, 32, 83, 101, 99, 117, 114, +101, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, +49, 13, 48, 11, 6, 3, 85, 4, 11, 12, 4, 84, 101, +115, 116, 49, 55, 48, 53, 6, 3, 85, 4, 3, 12, 46, +77, 97, 116, 114, 105, 120, 83, 83, 76, 32, 83, 97, 109, +112, 108, 101, 32, 67, 65, 32, 40, 69, 108, 108, 105, 112, +116, 105, 99, 32, 99, 117, 114, 118, 101, 32, 115, 101, 99, +112, 50, 50, 52, 114, 49, 41, 48, 78, 48, 16, 6, 7, +42, 134, 72, 206, 61, 2, 1, 6, 5, 43, 129, 4, 0, +33, 3, 58, 0, 4, 253, 11, 179, 117, 37, 53, 94, 117, +163, 131, 139, 81, 126, 255, 184, 30, 42, 140, 91, 142, 206, +215, 225, 195, 154, 80, 37, 141, 202, 12, 43, 159, 250, 62, +83, 172, 49, 82, 127, 103, 166, 146, 166, 163, 219, 168, 148, +75, 34, 51, 29, 95, 95, 207, 72, 33, 163, 93, 48, 91, +48, 11, 6, 3, 85, 29, 15, 4, 4, 3, 2, 2, 4, +48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 193, 47, +173, 196, 213, 1, 248, 145, 226, 207, 193, 190, 230, 11, 34, +231, 45, 59, 91, 216, 48, 31, 6, 3, 85, 29, 35, 4, +24, 48, 22, 128, 20, 193, 47, 173, 196, 213, 1, 248, 145, +226, 207, 193, 190, 230, 11, 34, 231, 45, 59, 91, 216, 48, +12, 6, 3, 85, 29, 19, 4, 5, 48, 3, 1, 1, 255, +48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 3, +64, 0, 48, 61, 2, 29, 0, 254, 28, 86, 179, 163, 185, +213, 184, 114, 156, 34, 214, 128, 151, 95, 135, 2, 34, 23, +26, 242, 68, 249, 182, 235, 23, 66, 51, 2, 28, 68, 167, +67, 59, 125, 195, 71, 21, 162, 1, 113, 91, 111, 240, 54, +165, 155, 219, 11, 224, 19, 150, 71, 6, 47, 79, 251, 73, +48, 130, 2, 128, 48, 130, 2, 38, 160, 3, 2, 1, 2, +2, 1, 1, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, +3, 2, 48, 129, 153, 49, 11, 48, 9, 6, 3, 85, 4, +6, 19, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, 4, +8, 12, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, 4, +7, 12, 7, 83, 101, 97, 116, 116, 108, 101, 49, 34, 48, +32, 6, 3, 85, 4, 10, 12, 25, 73, 110, 115, 105, 100, +101, 32, 83, 101, 99, 117, 114, 101, 32, 67, 111, 114, 112, +111, 114, 97, 116, 105, 111, 110, 49, 13, 48, 11, 6, 3, +85, 4, 11, 12, 4, 84, 101, 115, 116, 49, 56, 48, 54, +6, 3, 85, 4, 3, 12, 47, 77, 97, 116, 114, 105, 120, +83, 83, 76, 32, 83, 97, 109, 112, 108, 101, 32, 67, 65, +32, 40, 69, 108, 108, 105, 112, 116, 105, 99, 32, 99, 117, +114, 118, 101, 32, 112, 114, 105, 109, 101, 50, 53, 54, 118, +49, 41, 48, 30, 23, 13, 49, 52, 48, 51, 49, 51, 50, +51, 50, 49, 50, 51, 90, 23, 13, 49, 55, 48, 51, 49, +50, 50, 51, 50, 49, 50, 51, 90, 48, 129, 153, 49, 11, +48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 11, +48, 9, 6, 3, 85, 4, 8, 12, 2, 87, 65, 49, 16, +48, 14, 6, 3, 85, 4, 7, 12, 7, 83, 101, 97, 116, +116, 108, 101, 49, 34, 48, 32, 6, 3, 85, 4, 10, 12, +25, 73, 110, 115, 105, 100, 101, 32, 83, 101, 99, 117, 114, +101, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, +49, 13, 48, 11, 6, 3, 85, 4, 11, 12, 4, 84, 101, +115, 116, 49, 56, 48, 54, 6, 3, 85, 4, 3, 12, 47, +77, 97, 116, 114, 105, 120, 83, 83, 76, 32, 83, 97, 109, +112, 108, 101, 32, 67, 65, 32, 40, 69, 108, 108, 105, 112, +116, 105, 99, 32, 99, 117, 114, 118, 101, 32, 112, 114, 105, +109, 101, 50, 53, 54, 118, 49, 41, 48, 89, 48, 19, 6, +7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 134, 72, +206, 61, 3, 1, 7, 3, 66, 0, 4, 211, 90, 222, 86, +20, 8, 226, 69, 209, 11, 169, 119, 138, 112, 95, 135, 140, +180, 91, 47, 205, 105, 124, 5, 97, 127, 233, 227, 102, 191, +128, 63, 148, 136, 25, 170, 138, 255, 180, 40, 246, 14, 187, +20, 122, 57, 101, 75, 43, 125, 82, 68, 156, 92, 91, 9, +105, 152, 22, 49, 146, 218, 204, 88, 163, 93, 48, 91, 48, +11, 6, 3, 85, 29, 15, 4, 4, 3, 2, 2, 4, 48, +29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 105, 14, 250, +71, 62, 109, 64, 249, 41, 127, 247, 111, 102, 134, 184, 122, +52, 187, 37, 235, 48, 31, 6, 3, 85, 29, 35, 4, 24, +48, 22, 128, 20, 105, 14, 250, 71, 62, 109, 64, 249, 41, +127, 247, 111, 102, 134, 184, 122, 52, 187, 37, 235, 48, 12, +6, 3, 85, 29, 19, 4, 5, 48, 3, 1, 1, 255, 48, +10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 3, 72, +0, 48, 69, 2, 32, 66, 105, 191, 65, 98, 201, 166, 81, +178, 14, 217, 57, 12, 12, 85, 76, 195, 98, 23, 170, 233, +243, 139, 186, 12, 249, 227, 9, 178, 157, 234, 216, 2, 33, +0, 130, 3, 33, 253, 126, 188, 68, 183, 9, 138, 37, 206, +90, 102, 142, 121, 114, 90, 180, 16, 181, 22, 206, 103, 2, +143, 145, 94, 28, 93, 239, 163, +48, 130, 2, 188, 48, 130, 2, 66, 160, 3, 2, 1, 2, +2, 2, 35, 40, 48, 10, 6, 8, 42, 134, 72, 206, 61, +4, 3, 3, 48, 129, 152, 49, 11, 48, 9, 6, 3, 85, +4, 6, 19, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, +4, 8, 12, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, +4, 7, 12, 7, 83, 101, 97, 116, 116, 108, 101, 49, 34, +48, 32, 6, 3, 85, 4, 10, 12, 25, 73, 110, 115, 105, +100, 101, 32, 83, 101, 99, 117, 114, 101, 32, 67, 111, 114, +112, 111, 114, 97, 116, 105, 111, 110, 49, 13, 48, 11, 6, +3, 85, 4, 11, 12, 4, 84, 101, 115, 116, 49, 55, 48, +53, 6, 3, 85, 4, 3, 12, 46, 77, 97, 116, 114, 105, +120, 83, 83, 76, 32, 83, 97, 109, 112, 108, 101, 32, 67, +65, 32, 40, 69, 108, 108, 105, 112, 116, 105, 99, 32, 99, +117, 114, 118, 101, 32, 115, 101, 99, 112, 51, 56, 52, 114, +49, 41, 48, 30, 23, 13, 49, 52, 48, 51, 49, 51, 50, +51, 50, 49, 50, 55, 90, 23, 13, 49, 55, 48, 51, 49, +50, 50, 51, 50, 49, 50, 55, 90, 48, 129, 152, 49, 11, +48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 11, +48, 9, 6, 3, 85, 4, 8, 12, 2, 87, 65, 49, 16, +48, 14, 6, 3, 85, 4, 7, 12, 7, 83, 101, 97, 116, +116, 108, 101, 49, 34, 48, 32, 6, 3, 85, 4, 10, 12, +25, 73, 110, 115, 105, 100, 101, 32, 83, 101, 99, 117, 114, +101, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, +49, 13, 48, 11, 6, 3, 85, 4, 11, 12, 4, 84, 101, +115, 116, 49, 55, 48, 53, 6, 3, 85, 4, 3, 12, 46, +77, 97, 116, 114, 105, 120, 83, 83, 76, 32, 83, 97, 109, +112, 108, 101, 32, 67, 65, 32, 40, 69, 108, 108, 105, 112, +116, 105, 99, 32, 99, 117, 114, 118, 101, 32, 115, 101, 99, +112, 51, 56, 52, 114, 49, 41, 48, 118, 48, 16, 6, 7, +42, 134, 72, 206, 61, 2, 1, 6, 5, 43, 129, 4, 0, +34, 3, 98, 0, 4, 158, 4, 52, 153, 239, 138, 37, 29, +132, 242, 242, 64, 196, 213, 209, 83, 125, 84, 236, 32, 54, +223, 26, 226, 228, 112, 248, 211, 57, 160, 57, 24, 61, 177, +250, 45, 236, 162, 193, 70, 223, 109, 148, 143, 222, 220, 210, +61, 25, 47, 22, 236, 82, 88, 58, 128, 193, 195, 191, 133, +39, 22, 66, 7, 224, 2, 241, 215, 149, 201, 16, 236, 176, +160, 152, 138, 66, 181, 81, 232, 33, 251, 41, 175, 249, 69, +168, 178, 118, 16, 70, 239, 228, 236, 223, 193, 163, 93, 48, +91, 48, 11, 6, 3, 85, 29, 15, 4, 4, 3, 2, 2, +4, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 68, +237, 252, 139, 23, 66, 110, 97, 246, 53, 147, 61, 63, 129, +151, 111, 103, 104, 90, 27, 48, 31, 6, 3, 85, 29, 35, +4, 24, 48, 22, 128, 20, 68, 237, 252, 139, 23, 66, 110, +97, 246, 53, 147, 61, 63, 129, 151, 111, 103, 104, 90, 27, +48, 12, 6, 3, 85, 29, 19, 4, 5, 48, 3, 1, 1, +255, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 3, +3, 104, 0, 48, 101, 2, 49, 0, 212, 100, 174, 28, 219, +20, 248, 145, 200, 23, 212, 239, 208, 139, 54, 110, 246, 71, +101, 229, 182, 232, 237, 228, 181, 109, 68, 184, 112, 96, 161, +187, 187, 104, 25, 41, 130, 164, 250, 213, 231, 159, 15, 180, +249, 164, 219, 149, 2, 48, 62, 182, 48, 6, 109, 173, 240, +37, 8, 182, 48, 250, 206, 132, 51, 43, 214, 194, 174, 108, +133, 204, 66, 204, 2, 25, 12, 24, 123, 85, 123, 23, 60, +231, 206, 20, 79, 116, 128, 41, 205, 152, 135, 77, 70, 88, +164, 222, +48, 130, 3, 6, 48, 130, 2, 104, 160, 3, 2, 1, 2, +2, 2, 35, 240, 48, 10, 6, 8, 42, 134, 72, 206, 61, +4, 3, 3, 48, 129, 152, 49, 11, 48, 9, 6, 3, 85, +4, 6, 19, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, +4, 8, 12, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, +4, 7, 12, 7, 83, 101, 97, 116, 116, 108, 101, 49, 34, +48, 32, 6, 3, 85, 4, 10, 12, 25, 73, 110, 115, 105, +100, 101, 32, 83, 101, 99, 117, 114, 101, 32, 67, 111, 114, +112, 111, 114, 97, 116, 105, 111, 110, 49, 13, 48, 11, 6, +3, 85, 4, 11, 12, 4, 84, 101, 115, 116, 49, 55, 48, +53, 6, 3, 85, 4, 3, 12, 46, 77, 97, 116, 114, 105, +120, 83, 83, 76, 32, 83, 97, 109, 112, 108, 101, 32, 67, +65, 32, 40, 69, 108, 108, 105, 112, 116, 105, 99, 32, 99, +117, 114, 118, 101, 32, 115, 101, 99, 112, 53, 50, 49, 114, +49, 41, 48, 30, 23, 13, 49, 52, 48, 51, 49, 51, 50, +51, 50, 49, 51, 49, 90, 23, 13, 49, 55, 48, 51, 49, +50, 50, 51, 50, 49, 51, 49, 90, 48, 129, 152, 49, 11, +48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 11, +48, 9, 6, 3, 85, 4, 8, 12, 2, 87, 65, 49, 16, +48, 14, 6, 3, 85, 4, 7, 12, 7, 83, 101, 97, 116, +116, 108, 101, 49, 34, 48, 32, 6, 3, 85, 4, 10, 12, +25, 73, 110, 115, 105, 100, 101, 32, 83, 101, 99, 117, 114, +101, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, +49, 13, 48, 11, 6, 3, 85, 4, 11, 12, 4, 84, 101, +115, 116, 49, 55, 48, 53, 6, 3, 85, 4, 3, 12, 46, +77, 97, 116, 114, 105, 120, 83, 83, 76, 32, 83, 97, 109, +112, 108, 101, 32, 67, 65, 32, 40, 69, 108, 108, 105, 112, +116, 105, 99, 32, 99, 117, 114, 118, 101, 32, 115, 101, 99, +112, 53, 50, 49, 114, 49, 41, 48, 129, 155, 48, 16, 6, +7, 42, 134, 72, 206, 61, 2, 1, 6, 5, 43, 129, 4, +0, 35, 3, 129, 134, 0, 4, 1, 43, 67, 216, 141, 159, +213, 47, 157, 85, 11, 254, 114, 11, 50, 215, 142, 66, 196, +2, 151, 179, 205, 119, 21, 161, 234, 246, 100, 53, 114, 114, +103, 179, 95, 119, 38, 109, 111, 119, 43, 75, 161, 154, 219, +140, 118, 196, 220, 157, 96, 45, 59, 94, 7, 241, 165, 117, +17, 34, 122, 245, 239, 153, 119, 68, 0, 196, 45, 167, 19, +192, 199, 139, 213, 150, 146, 109, 174, 132, 149, 37, 31, 176, +104, 123, 137, 117, 191, 70, 182, 158, 162, 172, 112, 246, 236, +23, 110, 152, 46, 11, 172, 19, 120, 95, 84, 140, 0, 189, +58, 140, 92, 215, 164, 134, 181, 156, 4, 103, 117, 224, 220, +77, 138, 66, 70, 236, 228, 93, 241, 170, 163, 93, 48, 91, +48, 11, 6, 3, 85, 29, 15, 4, 4, 3, 2, 2, 4, +48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 25, 176, +190, 164, 157, 139, 60, 68, 229, 134, 181, 23, 161, 214, 13, +186, 66, 29, 184, 169, 48, 31, 6, 3, 85, 29, 35, 4, +24, 48, 22, 128, 20, 25, 176, 190, 164, 157, 139, 60, 68, +229, 134, 181, 23, 161, 214, 13, 186, 66, 29, 184, 169, 48, +12, 6, 3, 85, 29, 19, 4, 5, 48, 3, 1, 1, 255, +48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 3, 3, +129, 139, 0, 48, 129, 135, 2, 66, 1, 55, 152, 104, 160, +107, 179, 146, 211, 203, 107, 80, 174, 121, 193, 135, 67, 0, +237, 43, 51, 12, 110, 28, 237, 184, 137, 234, 57, 3, 79, +160, 128, 133, 113, 11, 40, 170, 80, 18, 193, 249, 150, 245, +58, 144, 158, 196, 76, 122, 100, 71, 232, 30, 158, 159, 228, +162, 19, 77, 68, 19, 58, 114, 247, 164, 2, 65, 51, 136, +239, 106, 211, 81, 35, 208, 100, 65, 42, 222, 117, 218, 70, +181, 172, 157, 112, 110, 108, 233, 81, 98, 102, 181, 135, 125, +49, 172, 167, 169, 17, 241, 23, 159, 193, 133, 59, 166, 134, +101, 233, 144, 214, 107, 60, 168, 158, 144, 67, 46, 56, 139, +69, 50, 176, 91, 205, 104, 119, 15, 195, 55, 126}; diff --git a/testkeys/EC/ALL_EC_CAS.pem b/testkeys/EC/ALL_EC_CAS.pem new file mode 100644 index 0000000..53755b5 --- /dev/null +++ b/testkeys/EC/ALL_EC_CAS.pem @@ -0,0 +1,82 @@ +-----BEGIN CERTIFICATE----- +MIICYzCCAhmgAwIBAgICG1gwCgYIKoZIzj0EAwIwgZoxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEjMCEGA1UECgwaSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbi4xDTALBgNVBAsMBFRlc3QxODA2BgNVBAMML01hdHJp +eFNTTCBTYW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHByaW1lMTkydjEpMB4XDTE0 +MDMxMzIzMTgyNVoXDTE3MDMxMjIzMTgyNVowgZoxCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEjMCEGA1UECgwaSW5zaWRlIFNlY3Vy +ZSBDb3Jwb3JhdGlvbi4xDTALBgNVBAsMBFRlc3QxODA2BgNVBAMML01hdHJpeFNT +TCBTYW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHByaW1lMTkydjEpMEkwEwYHKoZI +zj0CAQYIKoZIzj0DAQEDMgAEWe6hXbueMoJ8mFq4cGMHr/INsxUnjAF2QbZqmqFF +iCP7C+Y9gNYKzPsAV+4Yk2Tgo10wWzALBgNVHQ8EBAMCAgQwHQYDVR0OBBYEFJM/ +s1o4Vd201m6EzGbOjCZbHBcgMB8GA1UdIwQYMBaAFJM/s1o4Vd201m6EzGbOjCZb +HBcgMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDOAAwNQIZAOyT4nuxbPSKKLwu +2bdAb2fkNdGimcwB8QIYcUK//Ei/ou/Zv+njpS5HPhP9xeHFCQdy +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICbDCCAhqgAwIBAgICH0AwCgYIKoZIzj0EAwIwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDIyNHIxKTAeFw0xNDAz +MTMyMzIwNDBaFw0xNzAzMTIyMzIwNDBaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3AyMjRyMSkwTjAQBgcqhkjOPQIB +BgUrgQQAIQM6AAT9C7N1JTVedaODi1F+/7geKoxbjs7X4cOaUCWNygwrn/o+U6wx +Un9nppKmo9uolEsiMx1fX89IIaNdMFswCwYDVR0PBAQDAgIEMB0GA1UdDgQWBBTB +L63E1QH4keLPwb7mCyLnLTtb2DAfBgNVHSMEGDAWgBTBL63E1QH4keLPwb7mCyLn +LTtb2DAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0AAMD0CHQD+HFazo7nVuHKc +ItaAl1+HAiIXGvJE+bbrF0IzAhxEp0M7fcNHFaIBcVtv8Dalm9sL4BOWRwYvT/tJ +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICgDCCAiagAwIBAgIBATAKBggqhkjOPQQDAjCBmTELMAkGA1UEBhMCVVMxCzAJ +BgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMSIwIAYDVQQKDBlJbnNpZGUgU2Vj +dXJlIENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MTgwNgYDVQQDDC9NYXRyaXhT +U0wgU2FtcGxlIENBIChFbGxpcHRpYyBjdXJ2ZSBwcmltZTI1NnYxKTAeFw0xNDAz +MTMyMzIxMjNaFw0xNzAzMTIyMzIxMjNaMIGZMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxODA2BgNVBAMML01hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHByaW1lMjU2djEpMFkwEwYHKoZIzj0C +AQYIKoZIzj0DAQcDQgAE01reVhQI4kXRC6l3inBfh4y0Wy/NaXwFYX/p42a/gD+U +iBmqiv+0KPYOuxR6OWVLK31SRJxcWwlpmBYxktrMWKNdMFswCwYDVR0PBAQDAgIE +MB0GA1UdDgQWBBRpDvpHPm1A+Sl/929mhrh6NLsl6zAfBgNVHSMEGDAWgBRpDvpH +Pm1A+Sl/929mhrh6NLsl6zAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0gAMEUC +IEJpv0FiyaZRsg7ZOQwMVUzDYheq6fOLugz54wmynerYAiEAggMh/X68RLcJiiXO +WmaOeXJatBC1Fs5nAo+RXhxd76M= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICvDCCAkKgAwIBAgICIygwCgYIKoZIzj0EAwMwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDM4NHIxKTAeFw0xNDAz +MTMyMzIxMjdaFw0xNzAzMTIyMzIxMjdaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3AzODRyMSkwdjAQBgcqhkjOPQIB +BgUrgQQAIgNiAASeBDSZ74olHYTy8kDE1dFTfVTsIDbfGuLkcPjTOaA5GD2x+i3s +osFG322Uj97c0j0ZLxbsUlg6gMHDv4UnFkIH4ALx15XJEOywoJiKQrVR6CH7Ka/5 +RaiydhBG7+Ts38GjXTBbMAsGA1UdDwQEAwICBDAdBgNVHQ4EFgQURO38ixdCbmH2 +NZM9P4GXb2doWhswHwYDVR0jBBgwFoAURO38ixdCbmH2NZM9P4GXb2doWhswDAYD +VR0TBAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA1GSuHNsU+JHIF9Tv0Is2bvZH +ZeW26O3ktW1EuHBgobu7aBkpgqT61eefD7T5pNuVAjA+tjAGba3wJQi2MPrOhDMr +1sKubIXMQswCGQwYe1V7FzznzhRPdIApzZiHTUZYpN4= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDBjCCAmigAwIBAgICI/AwCgYIKoZIzj0EAwMwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDUyMXIxKTAeFw0xNDAz +MTMyMzIxMzFaFw0xNzAzMTIyMzIxMzFaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3A1MjFyMSkwgZswEAYHKoZIzj0C +AQYFK4EEACMDgYYABAErQ9iNn9UvnVUL/nILMteOQsQCl7PNdxWh6vZkNXJyZ7Nf +dyZtb3crS6Ga24x2xNydYC07XgfxpXURInr175l3RADELacTwMeL1ZaSba6ElSUf +sGh7iXW/Rraeoqxw9uwXbpguC6wTeF9UjAC9Ooxc16SGtZwEZ3Xg3E2KQkbs5F3x +qqNdMFswCwYDVR0PBAQDAgIEMB0GA1UdDgQWBBQZsL6knYs8ROWGtReh1g26Qh24 +qTAfBgNVHSMEGDAWgBQZsL6knYs8ROWGtReh1g26Qh24qTAMBgNVHRMEBTADAQH/ +MAoGCCqGSM49BAMDA4GLADCBhwJCATeYaKBrs5LTy2tQrnnBh0MA7SszDG4c7biJ +6jkDT6CAhXELKKpQEsH5lvU6kJ7ETHpkR+genp/kohNNRBM6cvekAkEziO9q01Ej +0GRBKt512ka1rJ1wbmzpUWJmtYd9MaynqRHxF5/BhTumhmXpkNZrPKiekEMuOItF +MrBbzWh3D8M3fg== +-----END CERTIFICATE----- diff --git a/testkeys/EC/ALL_EC_CAS_EXCEPT_P192.h b/testkeys/EC/ALL_EC_CAS_EXCEPT_P192.h new file mode 100644 index 0000000..a8c943d --- /dev/null +++ b/testkeys/EC/ALL_EC_CAS_EXCEPT_P192.h @@ -0,0 +1,232 @@ +const static unsigned char ECCAS[] = { + 0x30, 0x82, 0x02, 0x6c, 0x30, 0x82, 0x02, 0x1a, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x02, 0x1f, 0x40, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, + 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, + 0x74, 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, + 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x37, 0x30, 0x35, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, + 0x53, 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, + 0x41, 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, + 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, 0x63, 0x70, 0x32, 0x32, + 0x34, 0x72, 0x31, 0x29, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, + 0x31, 0x33, 0x32, 0x33, 0x32, 0x30, 0x34, 0x30, 0x5a, 0x17, 0x0d, 0x31, + 0x37, 0x30, 0x33, 0x31, 0x32, 0x32, 0x33, 0x32, 0x30, 0x34, 0x30, 0x5a, + 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, + 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, + 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, + 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, + 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, + 0x73, 0x74, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x2e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, + 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, + 0x20, 0x73, 0x65, 0x63, 0x70, 0x32, 0x32, 0x34, 0x72, 0x31, 0x29, 0x30, + 0x4e, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, + 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x21, 0x03, 0x3a, 0x00, 0x04, 0xfd, + 0x0b, 0xb3, 0x75, 0x25, 0x35, 0x5e, 0x75, 0xa3, 0x83, 0x8b, 0x51, 0x7e, + 0xff, 0xb8, 0x1e, 0x2a, 0x8c, 0x5b, 0x8e, 0xce, 0xd7, 0xe1, 0xc3, 0x9a, + 0x50, 0x25, 0x8d, 0xca, 0x0c, 0x2b, 0x9f, 0xfa, 0x3e, 0x53, 0xac, 0x31, + 0x52, 0x7f, 0x67, 0xa6, 0x92, 0xa6, 0xa3, 0xdb, 0xa8, 0x94, 0x4b, 0x22, + 0x33, 0x1d, 0x5f, 0x5f, 0xcf, 0x48, 0x21, 0xa3, 0x5d, 0x30, 0x5b, 0x30, + 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xc1, + 0x2f, 0xad, 0xc4, 0xd5, 0x01, 0xf8, 0x91, 0xe2, 0xcf, 0xc1, 0xbe, 0xe6, + 0x0b, 0x22, 0xe7, 0x2d, 0x3b, 0x5b, 0xd8, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xc1, 0x2f, 0xad, 0xc4, + 0xd5, 0x01, 0xf8, 0x91, 0xe2, 0xcf, 0xc1, 0xbe, 0xe6, 0x0b, 0x22, 0xe7, + 0x2d, 0x3b, 0x5b, 0xd8, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x40, 0x00, 0x30, 0x3d, 0x02, + 0x1d, 0x00, 0xfe, 0x1c, 0x56, 0xb3, 0xa3, 0xb9, 0xd5, 0xb8, 0x72, 0x9c, + 0x22, 0xd6, 0x80, 0x97, 0x5f, 0x87, 0x02, 0x22, 0x17, 0x1a, 0xf2, 0x44, + 0xf9, 0xb6, 0xeb, 0x17, 0x42, 0x33, 0x02, 0x1c, 0x44, 0xa7, 0x43, 0x3b, + 0x7d, 0xc3, 0x47, 0x15, 0xa2, 0x01, 0x71, 0x5b, 0x6f, 0xf0, 0x36, 0xa5, + 0x9b, 0xdb, 0x0b, 0xe0, 0x13, 0x96, 0x47, 0x06, 0x2f, 0x4f, 0xfb, 0x49, + 0x30, 0x82, 0x02, 0x80, 0x30, 0x82, 0x02, 0x26, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0x99, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, + 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, + 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, + 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, + 0x75, 0x72, 0x76, 0x65, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x32, 0x35, + 0x36, 0x76, 0x31, 0x29, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, + 0x31, 0x33, 0x32, 0x33, 0x32, 0x31, 0x32, 0x33, 0x5a, 0x17, 0x0d, 0x31, + 0x37, 0x30, 0x33, 0x31, 0x32, 0x32, 0x33, 0x32, 0x31, 0x32, 0x33, 0x5a, + 0x30, 0x81, 0x99, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, + 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, + 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, + 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, + 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, + 0x73, 0x74, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x2f, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, + 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, + 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x32, 0x35, 0x36, 0x76, 0x31, 0x29, + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0xd3, 0x5a, 0xde, 0x56, 0x14, 0x08, 0xe2, 0x45, 0xd1, + 0x0b, 0xa9, 0x77, 0x8a, 0x70, 0x5f, 0x87, 0x8c, 0xb4, 0x5b, 0x2f, 0xcd, + 0x69, 0x7c, 0x05, 0x61, 0x7f, 0xe9, 0xe3, 0x66, 0xbf, 0x80, 0x3f, 0x94, + 0x88, 0x19, 0xaa, 0x8a, 0xff, 0xb4, 0x28, 0xf6, 0x0e, 0xbb, 0x14, 0x7a, + 0x39, 0x65, 0x4b, 0x2b, 0x7d, 0x52, 0x44, 0x9c, 0x5c, 0x5b, 0x09, 0x69, + 0x98, 0x16, 0x31, 0x92, 0xda, 0xcc, 0x58, 0xa3, 0x5d, 0x30, 0x5b, 0x30, + 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x69, + 0x0e, 0xfa, 0x47, 0x3e, 0x6d, 0x40, 0xf9, 0x29, 0x7f, 0xf7, 0x6f, 0x66, + 0x86, 0xb8, 0x7a, 0x34, 0xbb, 0x25, 0xeb, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x69, 0x0e, 0xfa, 0x47, + 0x3e, 0x6d, 0x40, 0xf9, 0x29, 0x7f, 0xf7, 0x6f, 0x66, 0x86, 0xb8, 0x7a, + 0x34, 0xbb, 0x25, 0xeb, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, + 0x20, 0x42, 0x69, 0xbf, 0x41, 0x62, 0xc9, 0xa6, 0x51, 0xb2, 0x0e, 0xd9, + 0x39, 0x0c, 0x0c, 0x55, 0x4c, 0xc3, 0x62, 0x17, 0xaa, 0xe9, 0xf3, 0x8b, + 0xba, 0x0c, 0xf9, 0xe3, 0x09, 0xb2, 0x9d, 0xea, 0xd8, 0x02, 0x21, 0x00, + 0x82, 0x03, 0x21, 0xfd, 0x7e, 0xbc, 0x44, 0xb7, 0x09, 0x8a, 0x25, 0xce, + 0x5a, 0x66, 0x8e, 0x79, 0x72, 0x5a, 0xb4, 0x10, 0xb5, 0x16, 0xce, 0x67, + 0x02, 0x8f, 0x91, 0x5e, 0x1c, 0x5d, 0xef, 0xa3, 0x30, 0x82, 0x02, 0xbc, + 0x30, 0x82, 0x02, 0x42, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x23, + 0x28, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, + 0x03, 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, + 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, + 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, + 0x65, 0x73, 0x74, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x2e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, + 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, + 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, + 0x65, 0x20, 0x73, 0x65, 0x63, 0x70, 0x33, 0x38, 0x34, 0x72, 0x31, 0x29, + 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x33, 0x32, 0x33, + 0x32, 0x31, 0x32, 0x37, 0x5a, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, + 0x32, 0x32, 0x33, 0x32, 0x31, 0x32, 0x37, 0x5a, 0x30, 0x81, 0x98, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, + 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, + 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, + 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, + 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, + 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x37, + 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2e, 0x4d, 0x61, 0x74, + 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, + 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, 0x63, + 0x70, 0x33, 0x38, 0x34, 0x72, 0x31, 0x29, 0x30, 0x76, 0x30, 0x10, 0x06, + 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, + 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0x9e, 0x04, 0x34, 0x99, 0xef, + 0x8a, 0x25, 0x1d, 0x84, 0xf2, 0xf2, 0x40, 0xc4, 0xd5, 0xd1, 0x53, 0x7d, + 0x54, 0xec, 0x20, 0x36, 0xdf, 0x1a, 0xe2, 0xe4, 0x70, 0xf8, 0xd3, 0x39, + 0xa0, 0x39, 0x18, 0x3d, 0xb1, 0xfa, 0x2d, 0xec, 0xa2, 0xc1, 0x46, 0xdf, + 0x6d, 0x94, 0x8f, 0xde, 0xdc, 0xd2, 0x3d, 0x19, 0x2f, 0x16, 0xec, 0x52, + 0x58, 0x3a, 0x80, 0xc1, 0xc3, 0xbf, 0x85, 0x27, 0x16, 0x42, 0x07, 0xe0, + 0x02, 0xf1, 0xd7, 0x95, 0xc9, 0x10, 0xec, 0xb0, 0xa0, 0x98, 0x8a, 0x42, + 0xb5, 0x51, 0xe8, 0x21, 0xfb, 0x29, 0xaf, 0xf9, 0x45, 0xa8, 0xb2, 0x76, + 0x10, 0x46, 0xef, 0xe4, 0xec, 0xdf, 0xc1, 0xa3, 0x5d, 0x30, 0x5b, 0x30, + 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x44, + 0xed, 0xfc, 0x8b, 0x17, 0x42, 0x6e, 0x61, 0xf6, 0x35, 0x93, 0x3d, 0x3f, + 0x81, 0x97, 0x6f, 0x67, 0x68, 0x5a, 0x1b, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x44, 0xed, 0xfc, 0x8b, + 0x17, 0x42, 0x6e, 0x61, 0xf6, 0x35, 0x93, 0x3d, 0x3f, 0x81, 0x97, 0x6f, + 0x67, 0x68, 0x5a, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, + 0x31, 0x00, 0xd4, 0x64, 0xae, 0x1c, 0xdb, 0x14, 0xf8, 0x91, 0xc8, 0x17, + 0xd4, 0xef, 0xd0, 0x8b, 0x36, 0x6e, 0xf6, 0x47, 0x65, 0xe5, 0xb6, 0xe8, + 0xed, 0xe4, 0xb5, 0x6d, 0x44, 0xb8, 0x70, 0x60, 0xa1, 0xbb, 0xbb, 0x68, + 0x19, 0x29, 0x82, 0xa4, 0xfa, 0xd5, 0xe7, 0x9f, 0x0f, 0xb4, 0xf9, 0xa4, + 0xdb, 0x95, 0x02, 0x30, 0x3e, 0xb6, 0x30, 0x06, 0x6d, 0xad, 0xf0, 0x25, + 0x08, 0xb6, 0x30, 0xfa, 0xce, 0x84, 0x33, 0x2b, 0xd6, 0xc2, 0xae, 0x6c, + 0x85, 0xcc, 0x42, 0xcc, 0x02, 0x19, 0x0c, 0x18, 0x7b, 0x55, 0x7b, 0x17, + 0x3c, 0xe7, 0xce, 0x14, 0x4f, 0x74, 0x80, 0x29, 0xcd, 0x98, 0x87, 0x4d, + 0x46, 0x58, 0xa4, 0xde, 0x30, 0x82, 0x03, 0x06, 0x30, 0x82, 0x02, 0x68, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x23, 0xf0, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x81, 0x98, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, + 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, + 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, + 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, + 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, + 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, + 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2e, 0x4d, 0x61, + 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, + 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, + 0x63, 0x70, 0x35, 0x32, 0x31, 0x72, 0x31, 0x29, 0x30, 0x1e, 0x17, 0x0d, + 0x31, 0x34, 0x30, 0x33, 0x31, 0x33, 0x32, 0x33, 0x32, 0x31, 0x33, 0x31, + 0x5a, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x32, 0x32, 0x33, 0x32, + 0x31, 0x33, 0x31, 0x5a, 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, + 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x2e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, + 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, + 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, + 0x75, 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, 0x63, 0x70, 0x35, 0x32, 0x31, + 0x72, 0x31, 0x29, 0x30, 0x81, 0x9b, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23, + 0x03, 0x81, 0x86, 0x00, 0x04, 0x01, 0x2b, 0x43, 0xd8, 0x8d, 0x9f, 0xd5, + 0x2f, 0x9d, 0x55, 0x0b, 0xfe, 0x72, 0x0b, 0x32, 0xd7, 0x8e, 0x42, 0xc4, + 0x02, 0x97, 0xb3, 0xcd, 0x77, 0x15, 0xa1, 0xea, 0xf6, 0x64, 0x35, 0x72, + 0x72, 0x67, 0xb3, 0x5f, 0x77, 0x26, 0x6d, 0x6f, 0x77, 0x2b, 0x4b, 0xa1, + 0x9a, 0xdb, 0x8c, 0x76, 0xc4, 0xdc, 0x9d, 0x60, 0x2d, 0x3b, 0x5e, 0x07, + 0xf1, 0xa5, 0x75, 0x11, 0x22, 0x7a, 0xf5, 0xef, 0x99, 0x77, 0x44, 0x00, + 0xc4, 0x2d, 0xa7, 0x13, 0xc0, 0xc7, 0x8b, 0xd5, 0x96, 0x92, 0x6d, 0xae, + 0x84, 0x95, 0x25, 0x1f, 0xb0, 0x68, 0x7b, 0x89, 0x75, 0xbf, 0x46, 0xb6, + 0x9e, 0xa2, 0xac, 0x70, 0xf6, 0xec, 0x17, 0x6e, 0x98, 0x2e, 0x0b, 0xac, + 0x13, 0x78, 0x5f, 0x54, 0x8c, 0x00, 0xbd, 0x3a, 0x8c, 0x5c, 0xd7, 0xa4, + 0x86, 0xb5, 0x9c, 0x04, 0x67, 0x75, 0xe0, 0xdc, 0x4d, 0x8a, 0x42, 0x46, + 0xec, 0xe4, 0x5d, 0xf1, 0xaa, 0xa3, 0x5d, 0x30, 0x5b, 0x30, 0x0b, 0x06, + 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x1d, + 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x19, 0xb0, 0xbe, + 0xa4, 0x9d, 0x8b, 0x3c, 0x44, 0xe5, 0x86, 0xb5, 0x17, 0xa1, 0xd6, 0x0d, + 0xba, 0x42, 0x1d, 0xb8, 0xa9, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, + 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x19, 0xb0, 0xbe, 0xa4, 0x9d, 0x8b, + 0x3c, 0x44, 0xe5, 0x86, 0xb5, 0x17, 0xa1, 0xd6, 0x0d, 0xba, 0x42, 0x1d, + 0xb8, 0xa9, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x03, 0x03, 0x81, 0x8b, 0x00, 0x30, 0x81, 0x87, 0x02, + 0x42, 0x01, 0x37, 0x98, 0x68, 0xa0, 0x6b, 0xb3, 0x92, 0xd3, 0xcb, 0x6b, + 0x50, 0xae, 0x79, 0xc1, 0x87, 0x43, 0x00, 0xed, 0x2b, 0x33, 0x0c, 0x6e, + 0x1c, 0xed, 0xb8, 0x89, 0xea, 0x39, 0x03, 0x4f, 0xa0, 0x80, 0x85, 0x71, + 0x0b, 0x28, 0xaa, 0x50, 0x12, 0xc1, 0xf9, 0x96, 0xf5, 0x3a, 0x90, 0x9e, + 0xc4, 0x4c, 0x7a, 0x64, 0x47, 0xe8, 0x1e, 0x9e, 0x9f, 0xe4, 0xa2, 0x13, + 0x4d, 0x44, 0x13, 0x3a, 0x72, 0xf7, 0xa4, 0x02, 0x41, 0x33, 0x88, 0xef, + 0x6a, 0xd3, 0x51, 0x23, 0xd0, 0x64, 0x41, 0x2a, 0xde, 0x75, 0xda, 0x46, + 0xb5, 0xac, 0x9d, 0x70, 0x6e, 0x6c, 0xe9, 0x51, 0x62, 0x66, 0xb5, 0x87, + 0x7d, 0x31, 0xac, 0xa7, 0xa9, 0x11, 0xf1, 0x17, 0x9f, 0xc1, 0x85, 0x3b, + 0xa6, 0x86, 0x65, 0xe9, 0x90, 0xd6, 0x6b, 0x3c, 0xa8, 0x9e, 0x90, 0x43, + 0x2e, 0x38, 0x8b, 0x45, 0x32, 0xb0, 0x5b, 0xcd, 0x68, 0x77, 0x0f, 0xc3, + 0x37, 0x7e +}; diff --git a/testkeys/EC/ALL_EC_CAS_EXCEPT_P192.pem b/testkeys/EC/ALL_EC_CAS_EXCEPT_P192.pem new file mode 100644 index 0000000..0bbf3df --- /dev/null +++ b/testkeys/EC/ALL_EC_CAS_EXCEPT_P192.pem @@ -0,0 +1,67 @@ +-----BEGIN CERTIFICATE----- +MIICbDCCAhqgAwIBAgICH0AwCgYIKoZIzj0EAwIwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDIyNHIxKTAeFw0xNDAz +MTMyMzIwNDBaFw0xNzAzMTIyMzIwNDBaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3AyMjRyMSkwTjAQBgcqhkjOPQIB +BgUrgQQAIQM6AAT9C7N1JTVedaODi1F+/7geKoxbjs7X4cOaUCWNygwrn/o+U6wx +Un9nppKmo9uolEsiMx1fX89IIaNdMFswCwYDVR0PBAQDAgIEMB0GA1UdDgQWBBTB +L63E1QH4keLPwb7mCyLnLTtb2DAfBgNVHSMEGDAWgBTBL63E1QH4keLPwb7mCyLn +LTtb2DAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0AAMD0CHQD+HFazo7nVuHKc +ItaAl1+HAiIXGvJE+bbrF0IzAhxEp0M7fcNHFaIBcVtv8Dalm9sL4BOWRwYvT/tJ +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICgDCCAiagAwIBAgIBATAKBggqhkjOPQQDAjCBmTELMAkGA1UEBhMCVVMxCzAJ +BgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMSIwIAYDVQQKDBlJbnNpZGUgU2Vj +dXJlIENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MTgwNgYDVQQDDC9NYXRyaXhT +U0wgU2FtcGxlIENBIChFbGxpcHRpYyBjdXJ2ZSBwcmltZTI1NnYxKTAeFw0xNDAz +MTMyMzIxMjNaFw0xNzAzMTIyMzIxMjNaMIGZMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxODA2BgNVBAMML01hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHByaW1lMjU2djEpMFkwEwYHKoZIzj0C +AQYIKoZIzj0DAQcDQgAE01reVhQI4kXRC6l3inBfh4y0Wy/NaXwFYX/p42a/gD+U +iBmqiv+0KPYOuxR6OWVLK31SRJxcWwlpmBYxktrMWKNdMFswCwYDVR0PBAQDAgIE +MB0GA1UdDgQWBBRpDvpHPm1A+Sl/929mhrh6NLsl6zAfBgNVHSMEGDAWgBRpDvpH +Pm1A+Sl/929mhrh6NLsl6zAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0gAMEUC +IEJpv0FiyaZRsg7ZOQwMVUzDYheq6fOLugz54wmynerYAiEAggMh/X68RLcJiiXO +WmaOeXJatBC1Fs5nAo+RXhxd76M= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICvDCCAkKgAwIBAgICIygwCgYIKoZIzj0EAwMwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDM4NHIxKTAeFw0xNDAz +MTMyMzIxMjdaFw0xNzAzMTIyMzIxMjdaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3AzODRyMSkwdjAQBgcqhkjOPQIB +BgUrgQQAIgNiAASeBDSZ74olHYTy8kDE1dFTfVTsIDbfGuLkcPjTOaA5GD2x+i3s +osFG322Uj97c0j0ZLxbsUlg6gMHDv4UnFkIH4ALx15XJEOywoJiKQrVR6CH7Ka/5 +RaiydhBG7+Ts38GjXTBbMAsGA1UdDwQEAwICBDAdBgNVHQ4EFgQURO38ixdCbmH2 +NZM9P4GXb2doWhswHwYDVR0jBBgwFoAURO38ixdCbmH2NZM9P4GXb2doWhswDAYD +VR0TBAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA1GSuHNsU+JHIF9Tv0Is2bvZH +ZeW26O3ktW1EuHBgobu7aBkpgqT61eefD7T5pNuVAjA+tjAGba3wJQi2MPrOhDMr +1sKubIXMQswCGQwYe1V7FzznzhRPdIApzZiHTUZYpN4= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDBjCCAmigAwIBAgICI/AwCgYIKoZIzj0EAwMwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDUyMXIxKTAeFw0xNDAz +MTMyMzIxMzFaFw0xNzAzMTIyMzIxMzFaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3A1MjFyMSkwgZswEAYHKoZIzj0C +AQYFK4EEACMDgYYABAErQ9iNn9UvnVUL/nILMteOQsQCl7PNdxWh6vZkNXJyZ7Nf +dyZtb3crS6Ga24x2xNydYC07XgfxpXURInr175l3RADELacTwMeL1ZaSba6ElSUf +sGh7iXW/Rraeoqxw9uwXbpguC6wTeF9UjAC9Ooxc16SGtZwEZ3Xg3E2KQkbs5F3x +qqNdMFswCwYDVR0PBAQDAgIEMB0GA1UdDgQWBBQZsL6knYs8ROWGtReh1g26Qh24 +qTAfBgNVHSMEGDAWgBQZsL6knYs8ROWGtReh1g26Qh24qTAMBgNVHRMEBTADAQH/ +MAoGCCqGSM49BAMDA4GLADCBhwJCATeYaKBrs5LTy2tQrnnBh0MA7SszDG4c7biJ +6jkDT6CAhXELKKpQEsH5lvU6kJ7ETHpkR+genp/kohNNRBM6cvekAkEziO9q01Ej +0GRBKt512ka1rJ1wbmzpUWJmtYd9MaynqRHxF5/BhTumhmXpkNZrPKiekEMuOItF +MrBbzWh3D8M3fg== +-----END CERTIFICATE----- diff --git a/testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P224.h b/testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P224.h new file mode 100644 index 0000000..755305a --- /dev/null +++ b/testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P224.h @@ -0,0 +1,180 @@ +const static unsigned char ECCAS[] = { + 0x30, 0x82, 0x02, 0x80, 0x30, 0x82, 0x02, 0x26, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0x99, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, + 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, + 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, + 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, + 0x75, 0x72, 0x76, 0x65, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x32, 0x35, + 0x36, 0x76, 0x31, 0x29, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, + 0x31, 0x33, 0x32, 0x33, 0x32, 0x31, 0x32, 0x33, 0x5a, 0x17, 0x0d, 0x31, + 0x37, 0x30, 0x33, 0x31, 0x32, 0x32, 0x33, 0x32, 0x31, 0x32, 0x33, 0x5a, + 0x30, 0x81, 0x99, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, + 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, + 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, + 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, + 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, + 0x73, 0x74, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x2f, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, + 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, + 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x32, 0x35, 0x36, 0x76, 0x31, 0x29, + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0xd3, 0x5a, 0xde, 0x56, 0x14, 0x08, 0xe2, 0x45, 0xd1, + 0x0b, 0xa9, 0x77, 0x8a, 0x70, 0x5f, 0x87, 0x8c, 0xb4, 0x5b, 0x2f, 0xcd, + 0x69, 0x7c, 0x05, 0x61, 0x7f, 0xe9, 0xe3, 0x66, 0xbf, 0x80, 0x3f, 0x94, + 0x88, 0x19, 0xaa, 0x8a, 0xff, 0xb4, 0x28, 0xf6, 0x0e, 0xbb, 0x14, 0x7a, + 0x39, 0x65, 0x4b, 0x2b, 0x7d, 0x52, 0x44, 0x9c, 0x5c, 0x5b, 0x09, 0x69, + 0x98, 0x16, 0x31, 0x92, 0xda, 0xcc, 0x58, 0xa3, 0x5d, 0x30, 0x5b, 0x30, + 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x69, + 0x0e, 0xfa, 0x47, 0x3e, 0x6d, 0x40, 0xf9, 0x29, 0x7f, 0xf7, 0x6f, 0x66, + 0x86, 0xb8, 0x7a, 0x34, 0xbb, 0x25, 0xeb, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x69, 0x0e, 0xfa, 0x47, + 0x3e, 0x6d, 0x40, 0xf9, 0x29, 0x7f, 0xf7, 0x6f, 0x66, 0x86, 0xb8, 0x7a, + 0x34, 0xbb, 0x25, 0xeb, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, + 0x20, 0x42, 0x69, 0xbf, 0x41, 0x62, 0xc9, 0xa6, 0x51, 0xb2, 0x0e, 0xd9, + 0x39, 0x0c, 0x0c, 0x55, 0x4c, 0xc3, 0x62, 0x17, 0xaa, 0xe9, 0xf3, 0x8b, + 0xba, 0x0c, 0xf9, 0xe3, 0x09, 0xb2, 0x9d, 0xea, 0xd8, 0x02, 0x21, 0x00, + 0x82, 0x03, 0x21, 0xfd, 0x7e, 0xbc, 0x44, 0xb7, 0x09, 0x8a, 0x25, 0xce, + 0x5a, 0x66, 0x8e, 0x79, 0x72, 0x5a, 0xb4, 0x10, 0xb5, 0x16, 0xce, 0x67, + 0x02, 0x8f, 0x91, 0x5e, 0x1c, 0x5d, 0xef, 0xa3, 0x30, 0x82, 0x02, 0xbc, + 0x30, 0x82, 0x02, 0x42, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x23, + 0x28, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, + 0x03, 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, + 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, + 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, + 0x65, 0x73, 0x74, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x2e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, + 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, + 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, + 0x65, 0x20, 0x73, 0x65, 0x63, 0x70, 0x33, 0x38, 0x34, 0x72, 0x31, 0x29, + 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x33, 0x32, 0x33, + 0x32, 0x31, 0x32, 0x37, 0x5a, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, + 0x32, 0x32, 0x33, 0x32, 0x31, 0x32, 0x37, 0x5a, 0x30, 0x81, 0x98, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, + 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, + 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, + 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, + 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, + 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x37, + 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2e, 0x4d, 0x61, 0x74, + 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, + 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, 0x63, + 0x70, 0x33, 0x38, 0x34, 0x72, 0x31, 0x29, 0x30, 0x76, 0x30, 0x10, 0x06, + 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, + 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0x9e, 0x04, 0x34, 0x99, 0xef, + 0x8a, 0x25, 0x1d, 0x84, 0xf2, 0xf2, 0x40, 0xc4, 0xd5, 0xd1, 0x53, 0x7d, + 0x54, 0xec, 0x20, 0x36, 0xdf, 0x1a, 0xe2, 0xe4, 0x70, 0xf8, 0xd3, 0x39, + 0xa0, 0x39, 0x18, 0x3d, 0xb1, 0xfa, 0x2d, 0xec, 0xa2, 0xc1, 0x46, 0xdf, + 0x6d, 0x94, 0x8f, 0xde, 0xdc, 0xd2, 0x3d, 0x19, 0x2f, 0x16, 0xec, 0x52, + 0x58, 0x3a, 0x80, 0xc1, 0xc3, 0xbf, 0x85, 0x27, 0x16, 0x42, 0x07, 0xe0, + 0x02, 0xf1, 0xd7, 0x95, 0xc9, 0x10, 0xec, 0xb0, 0xa0, 0x98, 0x8a, 0x42, + 0xb5, 0x51, 0xe8, 0x21, 0xfb, 0x29, 0xaf, 0xf9, 0x45, 0xa8, 0xb2, 0x76, + 0x10, 0x46, 0xef, 0xe4, 0xec, 0xdf, 0xc1, 0xa3, 0x5d, 0x30, 0x5b, 0x30, + 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x44, + 0xed, 0xfc, 0x8b, 0x17, 0x42, 0x6e, 0x61, 0xf6, 0x35, 0x93, 0x3d, 0x3f, + 0x81, 0x97, 0x6f, 0x67, 0x68, 0x5a, 0x1b, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x44, 0xed, 0xfc, 0x8b, + 0x17, 0x42, 0x6e, 0x61, 0xf6, 0x35, 0x93, 0x3d, 0x3f, 0x81, 0x97, 0x6f, + 0x67, 0x68, 0x5a, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, + 0x31, 0x00, 0xd4, 0x64, 0xae, 0x1c, 0xdb, 0x14, 0xf8, 0x91, 0xc8, 0x17, + 0xd4, 0xef, 0xd0, 0x8b, 0x36, 0x6e, 0xf6, 0x47, 0x65, 0xe5, 0xb6, 0xe8, + 0xed, 0xe4, 0xb5, 0x6d, 0x44, 0xb8, 0x70, 0x60, 0xa1, 0xbb, 0xbb, 0x68, + 0x19, 0x29, 0x82, 0xa4, 0xfa, 0xd5, 0xe7, 0x9f, 0x0f, 0xb4, 0xf9, 0xa4, + 0xdb, 0x95, 0x02, 0x30, 0x3e, 0xb6, 0x30, 0x06, 0x6d, 0xad, 0xf0, 0x25, + 0x08, 0xb6, 0x30, 0xfa, 0xce, 0x84, 0x33, 0x2b, 0xd6, 0xc2, 0xae, 0x6c, + 0x85, 0xcc, 0x42, 0xcc, 0x02, 0x19, 0x0c, 0x18, 0x7b, 0x55, 0x7b, 0x17, + 0x3c, 0xe7, 0xce, 0x14, 0x4f, 0x74, 0x80, 0x29, 0xcd, 0x98, 0x87, 0x4d, + 0x46, 0x58, 0xa4, 0xde, 0x30, 0x82, 0x03, 0x06, 0x30, 0x82, 0x02, 0x68, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x23, 0xf0, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x81, 0x98, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, + 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, + 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, + 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, + 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, + 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, + 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2e, 0x4d, 0x61, + 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, + 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, + 0x63, 0x70, 0x35, 0x32, 0x31, 0x72, 0x31, 0x29, 0x30, 0x1e, 0x17, 0x0d, + 0x31, 0x34, 0x30, 0x33, 0x31, 0x33, 0x32, 0x33, 0x32, 0x31, 0x33, 0x31, + 0x5a, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x32, 0x32, 0x33, 0x32, + 0x31, 0x33, 0x31, 0x5a, 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, + 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x2e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, + 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, + 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, + 0x75, 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, 0x63, 0x70, 0x35, 0x32, 0x31, + 0x72, 0x31, 0x29, 0x30, 0x81, 0x9b, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23, + 0x03, 0x81, 0x86, 0x00, 0x04, 0x01, 0x2b, 0x43, 0xd8, 0x8d, 0x9f, 0xd5, + 0x2f, 0x9d, 0x55, 0x0b, 0xfe, 0x72, 0x0b, 0x32, 0xd7, 0x8e, 0x42, 0xc4, + 0x02, 0x97, 0xb3, 0xcd, 0x77, 0x15, 0xa1, 0xea, 0xf6, 0x64, 0x35, 0x72, + 0x72, 0x67, 0xb3, 0x5f, 0x77, 0x26, 0x6d, 0x6f, 0x77, 0x2b, 0x4b, 0xa1, + 0x9a, 0xdb, 0x8c, 0x76, 0xc4, 0xdc, 0x9d, 0x60, 0x2d, 0x3b, 0x5e, 0x07, + 0xf1, 0xa5, 0x75, 0x11, 0x22, 0x7a, 0xf5, 0xef, 0x99, 0x77, 0x44, 0x00, + 0xc4, 0x2d, 0xa7, 0x13, 0xc0, 0xc7, 0x8b, 0xd5, 0x96, 0x92, 0x6d, 0xae, + 0x84, 0x95, 0x25, 0x1f, 0xb0, 0x68, 0x7b, 0x89, 0x75, 0xbf, 0x46, 0xb6, + 0x9e, 0xa2, 0xac, 0x70, 0xf6, 0xec, 0x17, 0x6e, 0x98, 0x2e, 0x0b, 0xac, + 0x13, 0x78, 0x5f, 0x54, 0x8c, 0x00, 0xbd, 0x3a, 0x8c, 0x5c, 0xd7, 0xa4, + 0x86, 0xb5, 0x9c, 0x04, 0x67, 0x75, 0xe0, 0xdc, 0x4d, 0x8a, 0x42, 0x46, + 0xec, 0xe4, 0x5d, 0xf1, 0xaa, 0xa3, 0x5d, 0x30, 0x5b, 0x30, 0x0b, 0x06, + 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x1d, + 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x19, 0xb0, 0xbe, + 0xa4, 0x9d, 0x8b, 0x3c, 0x44, 0xe5, 0x86, 0xb5, 0x17, 0xa1, 0xd6, 0x0d, + 0xba, 0x42, 0x1d, 0xb8, 0xa9, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, + 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x19, 0xb0, 0xbe, 0xa4, 0x9d, 0x8b, + 0x3c, 0x44, 0xe5, 0x86, 0xb5, 0x17, 0xa1, 0xd6, 0x0d, 0xba, 0x42, 0x1d, + 0xb8, 0xa9, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x03, 0x03, 0x81, 0x8b, 0x00, 0x30, 0x81, 0x87, 0x02, + 0x42, 0x01, 0x37, 0x98, 0x68, 0xa0, 0x6b, 0xb3, 0x92, 0xd3, 0xcb, 0x6b, + 0x50, 0xae, 0x79, 0xc1, 0x87, 0x43, 0x00, 0xed, 0x2b, 0x33, 0x0c, 0x6e, + 0x1c, 0xed, 0xb8, 0x89, 0xea, 0x39, 0x03, 0x4f, 0xa0, 0x80, 0x85, 0x71, + 0x0b, 0x28, 0xaa, 0x50, 0x12, 0xc1, 0xf9, 0x96, 0xf5, 0x3a, 0x90, 0x9e, + 0xc4, 0x4c, 0x7a, 0x64, 0x47, 0xe8, 0x1e, 0x9e, 0x9f, 0xe4, 0xa2, 0x13, + 0x4d, 0x44, 0x13, 0x3a, 0x72, 0xf7, 0xa4, 0x02, 0x41, 0x33, 0x88, 0xef, + 0x6a, 0xd3, 0x51, 0x23, 0xd0, 0x64, 0x41, 0x2a, 0xde, 0x75, 0xda, 0x46, + 0xb5, 0xac, 0x9d, 0x70, 0x6e, 0x6c, 0xe9, 0x51, 0x62, 0x66, 0xb5, 0x87, + 0x7d, 0x31, 0xac, 0xa7, 0xa9, 0x11, 0xf1, 0x17, 0x9f, 0xc1, 0x85, 0x3b, + 0xa6, 0x86, 0x65, 0xe9, 0x90, 0xd6, 0x6b, 0x3c, 0xa8, 0x9e, 0x90, 0x43, + 0x2e, 0x38, 0x8b, 0x45, 0x32, 0xb0, 0x5b, 0xcd, 0x68, 0x77, 0x0f, 0xc3, + 0x37, 0x7e +}; diff --git a/testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P224.pem b/testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P224.pem new file mode 100644 index 0000000..17e9c0f --- /dev/null +++ b/testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P224.pem @@ -0,0 +1,52 @@ +-----BEGIN CERTIFICATE----- +MIICgDCCAiagAwIBAgIBATAKBggqhkjOPQQDAjCBmTELMAkGA1UEBhMCVVMxCzAJ +BgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMSIwIAYDVQQKDBlJbnNpZGUgU2Vj +dXJlIENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MTgwNgYDVQQDDC9NYXRyaXhT +U0wgU2FtcGxlIENBIChFbGxpcHRpYyBjdXJ2ZSBwcmltZTI1NnYxKTAeFw0xNDAz +MTMyMzIxMjNaFw0xNzAzMTIyMzIxMjNaMIGZMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxODA2BgNVBAMML01hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHByaW1lMjU2djEpMFkwEwYHKoZIzj0C +AQYIKoZIzj0DAQcDQgAE01reVhQI4kXRC6l3inBfh4y0Wy/NaXwFYX/p42a/gD+U +iBmqiv+0KPYOuxR6OWVLK31SRJxcWwlpmBYxktrMWKNdMFswCwYDVR0PBAQDAgIE +MB0GA1UdDgQWBBRpDvpHPm1A+Sl/929mhrh6NLsl6zAfBgNVHSMEGDAWgBRpDvpH +Pm1A+Sl/929mhrh6NLsl6zAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0gAMEUC +IEJpv0FiyaZRsg7ZOQwMVUzDYheq6fOLugz54wmynerYAiEAggMh/X68RLcJiiXO +WmaOeXJatBC1Fs5nAo+RXhxd76M= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICvDCCAkKgAwIBAgICIygwCgYIKoZIzj0EAwMwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDM4NHIxKTAeFw0xNDAz +MTMyMzIxMjdaFw0xNzAzMTIyMzIxMjdaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3AzODRyMSkwdjAQBgcqhkjOPQIB +BgUrgQQAIgNiAASeBDSZ74olHYTy8kDE1dFTfVTsIDbfGuLkcPjTOaA5GD2x+i3s +osFG322Uj97c0j0ZLxbsUlg6gMHDv4UnFkIH4ALx15XJEOywoJiKQrVR6CH7Ka/5 +RaiydhBG7+Ts38GjXTBbMAsGA1UdDwQEAwICBDAdBgNVHQ4EFgQURO38ixdCbmH2 +NZM9P4GXb2doWhswHwYDVR0jBBgwFoAURO38ixdCbmH2NZM9P4GXb2doWhswDAYD +VR0TBAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA1GSuHNsU+JHIF9Tv0Is2bvZH +ZeW26O3ktW1EuHBgobu7aBkpgqT61eefD7T5pNuVAjA+tjAGba3wJQi2MPrOhDMr +1sKubIXMQswCGQwYe1V7FzznzhRPdIApzZiHTUZYpN4= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDBjCCAmigAwIBAgICI/AwCgYIKoZIzj0EAwMwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDUyMXIxKTAeFw0xNDAz +MTMyMzIxMzFaFw0xNzAzMTIyMzIxMzFaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3A1MjFyMSkwgZswEAYHKoZIzj0C +AQYFK4EEACMDgYYABAErQ9iNn9UvnVUL/nILMteOQsQCl7PNdxWh6vZkNXJyZ7Nf +dyZtb3crS6Ga24x2xNydYC07XgfxpXURInr175l3RADELacTwMeL1ZaSba6ElSUf +sGh7iXW/Rraeoqxw9uwXbpguC6wTeF9UjAC9Ooxc16SGtZwEZ3Xg3E2KQkbs5F3x +qqNdMFswCwYDVR0PBAQDAgIEMB0GA1UdDgQWBBQZsL6knYs8ROWGtReh1g26Qh24 +qTAfBgNVHSMEGDAWgBQZsL6knYs8ROWGtReh1g26Qh24qTAMBgNVHRMEBTADAQH/ +MAoGCCqGSM49BAMDA4GLADCBhwJCATeYaKBrs5LTy2tQrnnBh0MA7SszDG4c7biJ +6jkDT6CAhXELKKpQEsH5lvU6kJ7ETHpkR+genp/kohNNRBM6cvekAkEziO9q01Ej +0GRBKt512ka1rJ1wbmzpUWJmtYd9MaynqRHxF5/BhTumhmXpkNZrPKiekEMuOItF +MrBbzWh3D8M3fg== +-----END CERTIFICATE----- diff --git a/testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P521.h b/testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P521.h new file mode 100644 index 0000000..971d53e --- /dev/null +++ b/testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P521.h @@ -0,0 +1,167 @@ +const static unsigned char ECCAS[] = { + 0x30, 0x82, 0x02, 0x6c, 0x30, 0x82, 0x02, 0x1a, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x02, 0x1f, 0x40, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, + 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, + 0x74, 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, + 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x37, 0x30, 0x35, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, + 0x53, 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, + 0x41, 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, + 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, 0x63, 0x70, 0x32, 0x32, + 0x34, 0x72, 0x31, 0x29, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, + 0x31, 0x33, 0x32, 0x33, 0x32, 0x30, 0x34, 0x30, 0x5a, 0x17, 0x0d, 0x31, + 0x37, 0x30, 0x33, 0x31, 0x32, 0x32, 0x33, 0x32, 0x30, 0x34, 0x30, 0x5a, + 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, + 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, + 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, + 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, + 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, + 0x73, 0x74, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x2e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, + 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, + 0x20, 0x73, 0x65, 0x63, 0x70, 0x32, 0x32, 0x34, 0x72, 0x31, 0x29, 0x30, + 0x4e, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, + 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x21, 0x03, 0x3a, 0x00, 0x04, 0xfd, + 0x0b, 0xb3, 0x75, 0x25, 0x35, 0x5e, 0x75, 0xa3, 0x83, 0x8b, 0x51, 0x7e, + 0xff, 0xb8, 0x1e, 0x2a, 0x8c, 0x5b, 0x8e, 0xce, 0xd7, 0xe1, 0xc3, 0x9a, + 0x50, 0x25, 0x8d, 0xca, 0x0c, 0x2b, 0x9f, 0xfa, 0x3e, 0x53, 0xac, 0x31, + 0x52, 0x7f, 0x67, 0xa6, 0x92, 0xa6, 0xa3, 0xdb, 0xa8, 0x94, 0x4b, 0x22, + 0x33, 0x1d, 0x5f, 0x5f, 0xcf, 0x48, 0x21, 0xa3, 0x5d, 0x30, 0x5b, 0x30, + 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xc1, + 0x2f, 0xad, 0xc4, 0xd5, 0x01, 0xf8, 0x91, 0xe2, 0xcf, 0xc1, 0xbe, 0xe6, + 0x0b, 0x22, 0xe7, 0x2d, 0x3b, 0x5b, 0xd8, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xc1, 0x2f, 0xad, 0xc4, + 0xd5, 0x01, 0xf8, 0x91, 0xe2, 0xcf, 0xc1, 0xbe, 0xe6, 0x0b, 0x22, 0xe7, + 0x2d, 0x3b, 0x5b, 0xd8, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x40, 0x00, 0x30, 0x3d, 0x02, + 0x1d, 0x00, 0xfe, 0x1c, 0x56, 0xb3, 0xa3, 0xb9, 0xd5, 0xb8, 0x72, 0x9c, + 0x22, 0xd6, 0x80, 0x97, 0x5f, 0x87, 0x02, 0x22, 0x17, 0x1a, 0xf2, 0x44, + 0xf9, 0xb6, 0xeb, 0x17, 0x42, 0x33, 0x02, 0x1c, 0x44, 0xa7, 0x43, 0x3b, + 0x7d, 0xc3, 0x47, 0x15, 0xa2, 0x01, 0x71, 0x5b, 0x6f, 0xf0, 0x36, 0xa5, + 0x9b, 0xdb, 0x0b, 0xe0, 0x13, 0x96, 0x47, 0x06, 0x2f, 0x4f, 0xfb, 0x49, + 0x30, 0x82, 0x02, 0x80, 0x30, 0x82, 0x02, 0x26, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0x99, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, + 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, + 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, + 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, + 0x75, 0x72, 0x76, 0x65, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x32, 0x35, + 0x36, 0x76, 0x31, 0x29, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, + 0x31, 0x33, 0x32, 0x33, 0x32, 0x31, 0x32, 0x33, 0x5a, 0x17, 0x0d, 0x31, + 0x37, 0x30, 0x33, 0x31, 0x32, 0x32, 0x33, 0x32, 0x31, 0x32, 0x33, 0x5a, + 0x30, 0x81, 0x99, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, + 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, + 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, + 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, + 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, + 0x73, 0x74, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x2f, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, + 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, + 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x32, 0x35, 0x36, 0x76, 0x31, 0x29, + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0xd3, 0x5a, 0xde, 0x56, 0x14, 0x08, 0xe2, 0x45, 0xd1, + 0x0b, 0xa9, 0x77, 0x8a, 0x70, 0x5f, 0x87, 0x8c, 0xb4, 0x5b, 0x2f, 0xcd, + 0x69, 0x7c, 0x05, 0x61, 0x7f, 0xe9, 0xe3, 0x66, 0xbf, 0x80, 0x3f, 0x94, + 0x88, 0x19, 0xaa, 0x8a, 0xff, 0xb4, 0x28, 0xf6, 0x0e, 0xbb, 0x14, 0x7a, + 0x39, 0x65, 0x4b, 0x2b, 0x7d, 0x52, 0x44, 0x9c, 0x5c, 0x5b, 0x09, 0x69, + 0x98, 0x16, 0x31, 0x92, 0xda, 0xcc, 0x58, 0xa3, 0x5d, 0x30, 0x5b, 0x30, + 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x69, + 0x0e, 0xfa, 0x47, 0x3e, 0x6d, 0x40, 0xf9, 0x29, 0x7f, 0xf7, 0x6f, 0x66, + 0x86, 0xb8, 0x7a, 0x34, 0xbb, 0x25, 0xeb, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x69, 0x0e, 0xfa, 0x47, + 0x3e, 0x6d, 0x40, 0xf9, 0x29, 0x7f, 0xf7, 0x6f, 0x66, 0x86, 0xb8, 0x7a, + 0x34, 0xbb, 0x25, 0xeb, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, + 0x20, 0x42, 0x69, 0xbf, 0x41, 0x62, 0xc9, 0xa6, 0x51, 0xb2, 0x0e, 0xd9, + 0x39, 0x0c, 0x0c, 0x55, 0x4c, 0xc3, 0x62, 0x17, 0xaa, 0xe9, 0xf3, 0x8b, + 0xba, 0x0c, 0xf9, 0xe3, 0x09, 0xb2, 0x9d, 0xea, 0xd8, 0x02, 0x21, 0x00, + 0x82, 0x03, 0x21, 0xfd, 0x7e, 0xbc, 0x44, 0xb7, 0x09, 0x8a, 0x25, 0xce, + 0x5a, 0x66, 0x8e, 0x79, 0x72, 0x5a, 0xb4, 0x10, 0xb5, 0x16, 0xce, 0x67, + 0x02, 0x8f, 0x91, 0x5e, 0x1c, 0x5d, 0xef, 0xa3, 0x30, 0x82, 0x02, 0xbc, + 0x30, 0x82, 0x02, 0x42, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x23, + 0x28, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, + 0x03, 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, + 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, + 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, + 0x65, 0x73, 0x74, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x2e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, + 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, + 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, + 0x65, 0x20, 0x73, 0x65, 0x63, 0x70, 0x33, 0x38, 0x34, 0x72, 0x31, 0x29, + 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x33, 0x32, 0x33, + 0x32, 0x31, 0x32, 0x37, 0x5a, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, + 0x32, 0x32, 0x33, 0x32, 0x31, 0x32, 0x37, 0x5a, 0x30, 0x81, 0x98, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, + 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, + 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, + 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, + 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, + 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x37, + 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2e, 0x4d, 0x61, 0x74, + 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, + 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, 0x63, + 0x70, 0x33, 0x38, 0x34, 0x72, 0x31, 0x29, 0x30, 0x76, 0x30, 0x10, 0x06, + 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, + 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0x9e, 0x04, 0x34, 0x99, 0xef, + 0x8a, 0x25, 0x1d, 0x84, 0xf2, 0xf2, 0x40, 0xc4, 0xd5, 0xd1, 0x53, 0x7d, + 0x54, 0xec, 0x20, 0x36, 0xdf, 0x1a, 0xe2, 0xe4, 0x70, 0xf8, 0xd3, 0x39, + 0xa0, 0x39, 0x18, 0x3d, 0xb1, 0xfa, 0x2d, 0xec, 0xa2, 0xc1, 0x46, 0xdf, + 0x6d, 0x94, 0x8f, 0xde, 0xdc, 0xd2, 0x3d, 0x19, 0x2f, 0x16, 0xec, 0x52, + 0x58, 0x3a, 0x80, 0xc1, 0xc3, 0xbf, 0x85, 0x27, 0x16, 0x42, 0x07, 0xe0, + 0x02, 0xf1, 0xd7, 0x95, 0xc9, 0x10, 0xec, 0xb0, 0xa0, 0x98, 0x8a, 0x42, + 0xb5, 0x51, 0xe8, 0x21, 0xfb, 0x29, 0xaf, 0xf9, 0x45, 0xa8, 0xb2, 0x76, + 0x10, 0x46, 0xef, 0xe4, 0xec, 0xdf, 0xc1, 0xa3, 0x5d, 0x30, 0x5b, 0x30, + 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x44, + 0xed, 0xfc, 0x8b, 0x17, 0x42, 0x6e, 0x61, 0xf6, 0x35, 0x93, 0x3d, 0x3f, + 0x81, 0x97, 0x6f, 0x67, 0x68, 0x5a, 0x1b, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x44, 0xed, 0xfc, 0x8b, + 0x17, 0x42, 0x6e, 0x61, 0xf6, 0x35, 0x93, 0x3d, 0x3f, 0x81, 0x97, 0x6f, + 0x67, 0x68, 0x5a, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, + 0x31, 0x00, 0xd4, 0x64, 0xae, 0x1c, 0xdb, 0x14, 0xf8, 0x91, 0xc8, 0x17, + 0xd4, 0xef, 0xd0, 0x8b, 0x36, 0x6e, 0xf6, 0x47, 0x65, 0xe5, 0xb6, 0xe8, + 0xed, 0xe4, 0xb5, 0x6d, 0x44, 0xb8, 0x70, 0x60, 0xa1, 0xbb, 0xbb, 0x68, + 0x19, 0x29, 0x82, 0xa4, 0xfa, 0xd5, 0xe7, 0x9f, 0x0f, 0xb4, 0xf9, 0xa4, + 0xdb, 0x95, 0x02, 0x30, 0x3e, 0xb6, 0x30, 0x06, 0x6d, 0xad, 0xf0, 0x25, + 0x08, 0xb6, 0x30, 0xfa, 0xce, 0x84, 0x33, 0x2b, 0xd6, 0xc2, 0xae, 0x6c, + 0x85, 0xcc, 0x42, 0xcc, 0x02, 0x19, 0x0c, 0x18, 0x7b, 0x55, 0x7b, 0x17, + 0x3c, 0xe7, 0xce, 0x14, 0x4f, 0x74, 0x80, 0x29, 0xcd, 0x98, 0x87, 0x4d, + 0x46, 0x58, 0xa4, 0xde +}; diff --git a/testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P521.pem b/testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P521.pem new file mode 100644 index 0000000..1e36667 --- /dev/null +++ b/testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P521.pem @@ -0,0 +1,48 @@ +-----BEGIN CERTIFICATE----- +MIICbDCCAhqgAwIBAgICH0AwCgYIKoZIzj0EAwIwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDIyNHIxKTAeFw0xNDAz +MTMyMzIwNDBaFw0xNzAzMTIyMzIwNDBaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3AyMjRyMSkwTjAQBgcqhkjOPQIB +BgUrgQQAIQM6AAT9C7N1JTVedaODi1F+/7geKoxbjs7X4cOaUCWNygwrn/o+U6wx +Un9nppKmo9uolEsiMx1fX89IIaNdMFswCwYDVR0PBAQDAgIEMB0GA1UdDgQWBBTB +L63E1QH4keLPwb7mCyLnLTtb2DAfBgNVHSMEGDAWgBTBL63E1QH4keLPwb7mCyLn +LTtb2DAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0AAMD0CHQD+HFazo7nVuHKc +ItaAl1+HAiIXGvJE+bbrF0IzAhxEp0M7fcNHFaIBcVtv8Dalm9sL4BOWRwYvT/tJ +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICgDCCAiagAwIBAgIBATAKBggqhkjOPQQDAjCBmTELMAkGA1UEBhMCVVMxCzAJ +BgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMSIwIAYDVQQKDBlJbnNpZGUgU2Vj +dXJlIENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MTgwNgYDVQQDDC9NYXRyaXhT +U0wgU2FtcGxlIENBIChFbGxpcHRpYyBjdXJ2ZSBwcmltZTI1NnYxKTAeFw0xNDAz +MTMyMzIxMjNaFw0xNzAzMTIyMzIxMjNaMIGZMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxODA2BgNVBAMML01hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHByaW1lMjU2djEpMFkwEwYHKoZIzj0C +AQYIKoZIzj0DAQcDQgAE01reVhQI4kXRC6l3inBfh4y0Wy/NaXwFYX/p42a/gD+U +iBmqiv+0KPYOuxR6OWVLK31SRJxcWwlpmBYxktrMWKNdMFswCwYDVR0PBAQDAgIE +MB0GA1UdDgQWBBRpDvpHPm1A+Sl/929mhrh6NLsl6zAfBgNVHSMEGDAWgBRpDvpH +Pm1A+Sl/929mhrh6NLsl6zAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0gAMEUC +IEJpv0FiyaZRsg7ZOQwMVUzDYheq6fOLugz54wmynerYAiEAggMh/X68RLcJiiXO +WmaOeXJatBC1Fs5nAo+RXhxd76M= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICvDCCAkKgAwIBAgICIygwCgYIKoZIzj0EAwMwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDM4NHIxKTAeFw0xNDAz +MTMyMzIxMjdaFw0xNzAzMTIyMzIxMjdaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3AzODRyMSkwdjAQBgcqhkjOPQIB +BgUrgQQAIgNiAASeBDSZ74olHYTy8kDE1dFTfVTsIDbfGuLkcPjTOaA5GD2x+i3s +osFG322Uj97c0j0ZLxbsUlg6gMHDv4UnFkIH4ALx15XJEOywoJiKQrVR6CH7Ka/5 +RaiydhBG7+Ts38GjXTBbMAsGA1UdDwQEAwICBDAdBgNVHQ4EFgQURO38ixdCbmH2 +NZM9P4GXb2doWhswHwYDVR0jBBgwFoAURO38ixdCbmH2NZM9P4GXb2doWhswDAYD +VR0TBAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA1GSuHNsU+JHIF9Tv0Is2bvZH +ZeW26O3ktW1EuHBgobu7aBkpgqT61eefD7T5pNuVAjA+tjAGba3wJQi2MPrOhDMr +1sKubIXMQswCGQwYe1V7FzznzhRPdIApzZiHTUZYpN4= +-----END CERTIFICATE----- diff --git a/testkeys/EC/ALL_EC_CAS_EXCEPT_P192_P224_AND_P521.h b/testkeys/EC/ALL_EC_CAS_EXCEPT_P192_P224_AND_P521.h new file mode 100644 index 0000000..05c78e4 --- /dev/null +++ b/testkeys/EC/ALL_EC_CAS_EXCEPT_P192_P224_AND_P521.h @@ -0,0 +1,115 @@ +const static unsigned char ECCAS[] = { + 0x30, 0x82, 0x02, 0x80, 0x30, 0x82, 0x02, 0x26, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0x99, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, + 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, + 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, + 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, + 0x75, 0x72, 0x76, 0x65, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x32, 0x35, + 0x36, 0x76, 0x31, 0x29, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, + 0x31, 0x33, 0x32, 0x33, 0x32, 0x31, 0x32, 0x33, 0x5a, 0x17, 0x0d, 0x31, + 0x37, 0x30, 0x33, 0x31, 0x32, 0x32, 0x33, 0x32, 0x31, 0x32, 0x33, 0x5a, + 0x30, 0x81, 0x99, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, + 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, + 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, + 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, + 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, + 0x73, 0x74, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x2f, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, + 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, + 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x32, 0x35, 0x36, 0x76, 0x31, 0x29, + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0xd3, 0x5a, 0xde, 0x56, 0x14, 0x08, 0xe2, 0x45, 0xd1, + 0x0b, 0xa9, 0x77, 0x8a, 0x70, 0x5f, 0x87, 0x8c, 0xb4, 0x5b, 0x2f, 0xcd, + 0x69, 0x7c, 0x05, 0x61, 0x7f, 0xe9, 0xe3, 0x66, 0xbf, 0x80, 0x3f, 0x94, + 0x88, 0x19, 0xaa, 0x8a, 0xff, 0xb4, 0x28, 0xf6, 0x0e, 0xbb, 0x14, 0x7a, + 0x39, 0x65, 0x4b, 0x2b, 0x7d, 0x52, 0x44, 0x9c, 0x5c, 0x5b, 0x09, 0x69, + 0x98, 0x16, 0x31, 0x92, 0xda, 0xcc, 0x58, 0xa3, 0x5d, 0x30, 0x5b, 0x30, + 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x69, + 0x0e, 0xfa, 0x47, 0x3e, 0x6d, 0x40, 0xf9, 0x29, 0x7f, 0xf7, 0x6f, 0x66, + 0x86, 0xb8, 0x7a, 0x34, 0xbb, 0x25, 0xeb, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x69, 0x0e, 0xfa, 0x47, + 0x3e, 0x6d, 0x40, 0xf9, 0x29, 0x7f, 0xf7, 0x6f, 0x66, 0x86, 0xb8, 0x7a, + 0x34, 0xbb, 0x25, 0xeb, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, + 0x20, 0x42, 0x69, 0xbf, 0x41, 0x62, 0xc9, 0xa6, 0x51, 0xb2, 0x0e, 0xd9, + 0x39, 0x0c, 0x0c, 0x55, 0x4c, 0xc3, 0x62, 0x17, 0xaa, 0xe9, 0xf3, 0x8b, + 0xba, 0x0c, 0xf9, 0xe3, 0x09, 0xb2, 0x9d, 0xea, 0xd8, 0x02, 0x21, 0x00, + 0x82, 0x03, 0x21, 0xfd, 0x7e, 0xbc, 0x44, 0xb7, 0x09, 0x8a, 0x25, 0xce, + 0x5a, 0x66, 0x8e, 0x79, 0x72, 0x5a, 0xb4, 0x10, 0xb5, 0x16, 0xce, 0x67, + 0x02, 0x8f, 0x91, 0x5e, 0x1c, 0x5d, 0xef, 0xa3, 0x30, 0x82, 0x02, 0xbc, + 0x30, 0x82, 0x02, 0x42, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x23, + 0x28, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, + 0x03, 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, + 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, + 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, + 0x65, 0x73, 0x74, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x2e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, + 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, + 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, + 0x65, 0x20, 0x73, 0x65, 0x63, 0x70, 0x33, 0x38, 0x34, 0x72, 0x31, 0x29, + 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x33, 0x32, 0x33, + 0x32, 0x31, 0x32, 0x37, 0x5a, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, + 0x32, 0x32, 0x33, 0x32, 0x31, 0x32, 0x37, 0x5a, 0x30, 0x81, 0x98, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, + 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, + 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, + 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, + 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, + 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x37, + 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2e, 0x4d, 0x61, 0x74, + 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, + 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, 0x63, + 0x70, 0x33, 0x38, 0x34, 0x72, 0x31, 0x29, 0x30, 0x76, 0x30, 0x10, 0x06, + 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, + 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0x9e, 0x04, 0x34, 0x99, 0xef, + 0x8a, 0x25, 0x1d, 0x84, 0xf2, 0xf2, 0x40, 0xc4, 0xd5, 0xd1, 0x53, 0x7d, + 0x54, 0xec, 0x20, 0x36, 0xdf, 0x1a, 0xe2, 0xe4, 0x70, 0xf8, 0xd3, 0x39, + 0xa0, 0x39, 0x18, 0x3d, 0xb1, 0xfa, 0x2d, 0xec, 0xa2, 0xc1, 0x46, 0xdf, + 0x6d, 0x94, 0x8f, 0xde, 0xdc, 0xd2, 0x3d, 0x19, 0x2f, 0x16, 0xec, 0x52, + 0x58, 0x3a, 0x80, 0xc1, 0xc3, 0xbf, 0x85, 0x27, 0x16, 0x42, 0x07, 0xe0, + 0x02, 0xf1, 0xd7, 0x95, 0xc9, 0x10, 0xec, 0xb0, 0xa0, 0x98, 0x8a, 0x42, + 0xb5, 0x51, 0xe8, 0x21, 0xfb, 0x29, 0xaf, 0xf9, 0x45, 0xa8, 0xb2, 0x76, + 0x10, 0x46, 0xef, 0xe4, 0xec, 0xdf, 0xc1, 0xa3, 0x5d, 0x30, 0x5b, 0x30, + 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x44, + 0xed, 0xfc, 0x8b, 0x17, 0x42, 0x6e, 0x61, 0xf6, 0x35, 0x93, 0x3d, 0x3f, + 0x81, 0x97, 0x6f, 0x67, 0x68, 0x5a, 0x1b, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x44, 0xed, 0xfc, 0x8b, + 0x17, 0x42, 0x6e, 0x61, 0xf6, 0x35, 0x93, 0x3d, 0x3f, 0x81, 0x97, 0x6f, + 0x67, 0x68, 0x5a, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, + 0x31, 0x00, 0xd4, 0x64, 0xae, 0x1c, 0xdb, 0x14, 0xf8, 0x91, 0xc8, 0x17, + 0xd4, 0xef, 0xd0, 0x8b, 0x36, 0x6e, 0xf6, 0x47, 0x65, 0xe5, 0xb6, 0xe8, + 0xed, 0xe4, 0xb5, 0x6d, 0x44, 0xb8, 0x70, 0x60, 0xa1, 0xbb, 0xbb, 0x68, + 0x19, 0x29, 0x82, 0xa4, 0xfa, 0xd5, 0xe7, 0x9f, 0x0f, 0xb4, 0xf9, 0xa4, + 0xdb, 0x95, 0x02, 0x30, 0x3e, 0xb6, 0x30, 0x06, 0x6d, 0xad, 0xf0, 0x25, + 0x08, 0xb6, 0x30, 0xfa, 0xce, 0x84, 0x33, 0x2b, 0xd6, 0xc2, 0xae, 0x6c, + 0x85, 0xcc, 0x42, 0xcc, 0x02, 0x19, 0x0c, 0x18, 0x7b, 0x55, 0x7b, 0x17, + 0x3c, 0xe7, 0xce, 0x14, 0x4f, 0x74, 0x80, 0x29, 0xcd, 0x98, 0x87, 0x4d, + 0x46, 0x58, 0xa4, 0xde +}; diff --git a/testkeys/EC/ALL_EC_CAS_EXCEPT_P192_P224_AND_P521.pem b/testkeys/EC/ALL_EC_CAS_EXCEPT_P192_P224_AND_P521.pem new file mode 100644 index 0000000..9ceaaf4 --- /dev/null +++ b/testkeys/EC/ALL_EC_CAS_EXCEPT_P192_P224_AND_P521.pem @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIICgDCCAiagAwIBAgIBATAKBggqhkjOPQQDAjCBmTELMAkGA1UEBhMCVVMxCzAJ +BgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMSIwIAYDVQQKDBlJbnNpZGUgU2Vj +dXJlIENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MTgwNgYDVQQDDC9NYXRyaXhT +U0wgU2FtcGxlIENBIChFbGxpcHRpYyBjdXJ2ZSBwcmltZTI1NnYxKTAeFw0xNDAz +MTMyMzIxMjNaFw0xNzAzMTIyMzIxMjNaMIGZMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxODA2BgNVBAMML01hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHByaW1lMjU2djEpMFkwEwYHKoZIzj0C +AQYIKoZIzj0DAQcDQgAE01reVhQI4kXRC6l3inBfh4y0Wy/NaXwFYX/p42a/gD+U +iBmqiv+0KPYOuxR6OWVLK31SRJxcWwlpmBYxktrMWKNdMFswCwYDVR0PBAQDAgIE +MB0GA1UdDgQWBBRpDvpHPm1A+Sl/929mhrh6NLsl6zAfBgNVHSMEGDAWgBRpDvpH +Pm1A+Sl/929mhrh6NLsl6zAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0gAMEUC +IEJpv0FiyaZRsg7ZOQwMVUzDYheq6fOLugz54wmynerYAiEAggMh/X68RLcJiiXO +WmaOeXJatBC1Fs5nAo+RXhxd76M= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICvDCCAkKgAwIBAgICIygwCgYIKoZIzj0EAwMwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDM4NHIxKTAeFw0xNDAz +MTMyMzIxMjdaFw0xNzAzMTIyMzIxMjdaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3AzODRyMSkwdjAQBgcqhkjOPQIB +BgUrgQQAIgNiAASeBDSZ74olHYTy8kDE1dFTfVTsIDbfGuLkcPjTOaA5GD2x+i3s +osFG322Uj97c0j0ZLxbsUlg6gMHDv4UnFkIH4ALx15XJEOywoJiKQrVR6CH7Ka/5 +RaiydhBG7+Ts38GjXTBbMAsGA1UdDwQEAwICBDAdBgNVHQ4EFgQURO38ixdCbmH2 +NZM9P4GXb2doWhswHwYDVR0jBBgwFoAURO38ixdCbmH2NZM9P4GXb2doWhswDAYD +VR0TBAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA1GSuHNsU+JHIF9Tv0Is2bvZH +ZeW26O3ktW1EuHBgobu7aBkpgqT61eefD7T5pNuVAjA+tjAGba3wJQi2MPrOhDMr +1sKubIXMQswCGQwYe1V7FzznzhRPdIApzZiHTUZYpN4= +-----END CERTIFICATE----- diff --git a/testkeys/EC/ALL_EC_CAS_EXCEPT_P224.h b/testkeys/EC/ALL_EC_CAS_EXCEPT_P224.h new file mode 100644 index 0000000..755305a --- /dev/null +++ b/testkeys/EC/ALL_EC_CAS_EXCEPT_P224.h @@ -0,0 +1,180 @@ +const static unsigned char ECCAS[] = { + 0x30, 0x82, 0x02, 0x80, 0x30, 0x82, 0x02, 0x26, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0x99, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, + 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, + 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, + 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, + 0x75, 0x72, 0x76, 0x65, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x32, 0x35, + 0x36, 0x76, 0x31, 0x29, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, + 0x31, 0x33, 0x32, 0x33, 0x32, 0x31, 0x32, 0x33, 0x5a, 0x17, 0x0d, 0x31, + 0x37, 0x30, 0x33, 0x31, 0x32, 0x32, 0x33, 0x32, 0x31, 0x32, 0x33, 0x5a, + 0x30, 0x81, 0x99, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, + 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, + 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, + 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, + 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, + 0x73, 0x74, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x2f, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, + 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, + 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x32, 0x35, 0x36, 0x76, 0x31, 0x29, + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0xd3, 0x5a, 0xde, 0x56, 0x14, 0x08, 0xe2, 0x45, 0xd1, + 0x0b, 0xa9, 0x77, 0x8a, 0x70, 0x5f, 0x87, 0x8c, 0xb4, 0x5b, 0x2f, 0xcd, + 0x69, 0x7c, 0x05, 0x61, 0x7f, 0xe9, 0xe3, 0x66, 0xbf, 0x80, 0x3f, 0x94, + 0x88, 0x19, 0xaa, 0x8a, 0xff, 0xb4, 0x28, 0xf6, 0x0e, 0xbb, 0x14, 0x7a, + 0x39, 0x65, 0x4b, 0x2b, 0x7d, 0x52, 0x44, 0x9c, 0x5c, 0x5b, 0x09, 0x69, + 0x98, 0x16, 0x31, 0x92, 0xda, 0xcc, 0x58, 0xa3, 0x5d, 0x30, 0x5b, 0x30, + 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x69, + 0x0e, 0xfa, 0x47, 0x3e, 0x6d, 0x40, 0xf9, 0x29, 0x7f, 0xf7, 0x6f, 0x66, + 0x86, 0xb8, 0x7a, 0x34, 0xbb, 0x25, 0xeb, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x69, 0x0e, 0xfa, 0x47, + 0x3e, 0x6d, 0x40, 0xf9, 0x29, 0x7f, 0xf7, 0x6f, 0x66, 0x86, 0xb8, 0x7a, + 0x34, 0xbb, 0x25, 0xeb, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, + 0x20, 0x42, 0x69, 0xbf, 0x41, 0x62, 0xc9, 0xa6, 0x51, 0xb2, 0x0e, 0xd9, + 0x39, 0x0c, 0x0c, 0x55, 0x4c, 0xc3, 0x62, 0x17, 0xaa, 0xe9, 0xf3, 0x8b, + 0xba, 0x0c, 0xf9, 0xe3, 0x09, 0xb2, 0x9d, 0xea, 0xd8, 0x02, 0x21, 0x00, + 0x82, 0x03, 0x21, 0xfd, 0x7e, 0xbc, 0x44, 0xb7, 0x09, 0x8a, 0x25, 0xce, + 0x5a, 0x66, 0x8e, 0x79, 0x72, 0x5a, 0xb4, 0x10, 0xb5, 0x16, 0xce, 0x67, + 0x02, 0x8f, 0x91, 0x5e, 0x1c, 0x5d, 0xef, 0xa3, 0x30, 0x82, 0x02, 0xbc, + 0x30, 0x82, 0x02, 0x42, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x23, + 0x28, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, + 0x03, 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, + 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, + 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, + 0x65, 0x73, 0x74, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x2e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, + 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, + 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, + 0x65, 0x20, 0x73, 0x65, 0x63, 0x70, 0x33, 0x38, 0x34, 0x72, 0x31, 0x29, + 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x33, 0x32, 0x33, + 0x32, 0x31, 0x32, 0x37, 0x5a, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, + 0x32, 0x32, 0x33, 0x32, 0x31, 0x32, 0x37, 0x5a, 0x30, 0x81, 0x98, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, + 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, + 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, + 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, + 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, + 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x37, + 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2e, 0x4d, 0x61, 0x74, + 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, + 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, 0x63, + 0x70, 0x33, 0x38, 0x34, 0x72, 0x31, 0x29, 0x30, 0x76, 0x30, 0x10, 0x06, + 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, + 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0x9e, 0x04, 0x34, 0x99, 0xef, + 0x8a, 0x25, 0x1d, 0x84, 0xf2, 0xf2, 0x40, 0xc4, 0xd5, 0xd1, 0x53, 0x7d, + 0x54, 0xec, 0x20, 0x36, 0xdf, 0x1a, 0xe2, 0xe4, 0x70, 0xf8, 0xd3, 0x39, + 0xa0, 0x39, 0x18, 0x3d, 0xb1, 0xfa, 0x2d, 0xec, 0xa2, 0xc1, 0x46, 0xdf, + 0x6d, 0x94, 0x8f, 0xde, 0xdc, 0xd2, 0x3d, 0x19, 0x2f, 0x16, 0xec, 0x52, + 0x58, 0x3a, 0x80, 0xc1, 0xc3, 0xbf, 0x85, 0x27, 0x16, 0x42, 0x07, 0xe0, + 0x02, 0xf1, 0xd7, 0x95, 0xc9, 0x10, 0xec, 0xb0, 0xa0, 0x98, 0x8a, 0x42, + 0xb5, 0x51, 0xe8, 0x21, 0xfb, 0x29, 0xaf, 0xf9, 0x45, 0xa8, 0xb2, 0x76, + 0x10, 0x46, 0xef, 0xe4, 0xec, 0xdf, 0xc1, 0xa3, 0x5d, 0x30, 0x5b, 0x30, + 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x44, + 0xed, 0xfc, 0x8b, 0x17, 0x42, 0x6e, 0x61, 0xf6, 0x35, 0x93, 0x3d, 0x3f, + 0x81, 0x97, 0x6f, 0x67, 0x68, 0x5a, 0x1b, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x44, 0xed, 0xfc, 0x8b, + 0x17, 0x42, 0x6e, 0x61, 0xf6, 0x35, 0x93, 0x3d, 0x3f, 0x81, 0x97, 0x6f, + 0x67, 0x68, 0x5a, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, + 0x31, 0x00, 0xd4, 0x64, 0xae, 0x1c, 0xdb, 0x14, 0xf8, 0x91, 0xc8, 0x17, + 0xd4, 0xef, 0xd0, 0x8b, 0x36, 0x6e, 0xf6, 0x47, 0x65, 0xe5, 0xb6, 0xe8, + 0xed, 0xe4, 0xb5, 0x6d, 0x44, 0xb8, 0x70, 0x60, 0xa1, 0xbb, 0xbb, 0x68, + 0x19, 0x29, 0x82, 0xa4, 0xfa, 0xd5, 0xe7, 0x9f, 0x0f, 0xb4, 0xf9, 0xa4, + 0xdb, 0x95, 0x02, 0x30, 0x3e, 0xb6, 0x30, 0x06, 0x6d, 0xad, 0xf0, 0x25, + 0x08, 0xb6, 0x30, 0xfa, 0xce, 0x84, 0x33, 0x2b, 0xd6, 0xc2, 0xae, 0x6c, + 0x85, 0xcc, 0x42, 0xcc, 0x02, 0x19, 0x0c, 0x18, 0x7b, 0x55, 0x7b, 0x17, + 0x3c, 0xe7, 0xce, 0x14, 0x4f, 0x74, 0x80, 0x29, 0xcd, 0x98, 0x87, 0x4d, + 0x46, 0x58, 0xa4, 0xde, 0x30, 0x82, 0x03, 0x06, 0x30, 0x82, 0x02, 0x68, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x23, 0xf0, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x81, 0x98, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, + 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, + 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, + 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, + 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, + 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, + 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2e, 0x4d, 0x61, + 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, + 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, + 0x63, 0x70, 0x35, 0x32, 0x31, 0x72, 0x31, 0x29, 0x30, 0x1e, 0x17, 0x0d, + 0x31, 0x34, 0x30, 0x33, 0x31, 0x33, 0x32, 0x33, 0x32, 0x31, 0x33, 0x31, + 0x5a, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x32, 0x32, 0x33, 0x32, + 0x31, 0x33, 0x31, 0x5a, 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, + 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x2e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, + 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, + 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, + 0x75, 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, 0x63, 0x70, 0x35, 0x32, 0x31, + 0x72, 0x31, 0x29, 0x30, 0x81, 0x9b, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23, + 0x03, 0x81, 0x86, 0x00, 0x04, 0x01, 0x2b, 0x43, 0xd8, 0x8d, 0x9f, 0xd5, + 0x2f, 0x9d, 0x55, 0x0b, 0xfe, 0x72, 0x0b, 0x32, 0xd7, 0x8e, 0x42, 0xc4, + 0x02, 0x97, 0xb3, 0xcd, 0x77, 0x15, 0xa1, 0xea, 0xf6, 0x64, 0x35, 0x72, + 0x72, 0x67, 0xb3, 0x5f, 0x77, 0x26, 0x6d, 0x6f, 0x77, 0x2b, 0x4b, 0xa1, + 0x9a, 0xdb, 0x8c, 0x76, 0xc4, 0xdc, 0x9d, 0x60, 0x2d, 0x3b, 0x5e, 0x07, + 0xf1, 0xa5, 0x75, 0x11, 0x22, 0x7a, 0xf5, 0xef, 0x99, 0x77, 0x44, 0x00, + 0xc4, 0x2d, 0xa7, 0x13, 0xc0, 0xc7, 0x8b, 0xd5, 0x96, 0x92, 0x6d, 0xae, + 0x84, 0x95, 0x25, 0x1f, 0xb0, 0x68, 0x7b, 0x89, 0x75, 0xbf, 0x46, 0xb6, + 0x9e, 0xa2, 0xac, 0x70, 0xf6, 0xec, 0x17, 0x6e, 0x98, 0x2e, 0x0b, 0xac, + 0x13, 0x78, 0x5f, 0x54, 0x8c, 0x00, 0xbd, 0x3a, 0x8c, 0x5c, 0xd7, 0xa4, + 0x86, 0xb5, 0x9c, 0x04, 0x67, 0x75, 0xe0, 0xdc, 0x4d, 0x8a, 0x42, 0x46, + 0xec, 0xe4, 0x5d, 0xf1, 0xaa, 0xa3, 0x5d, 0x30, 0x5b, 0x30, 0x0b, 0x06, + 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x1d, + 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x19, 0xb0, 0xbe, + 0xa4, 0x9d, 0x8b, 0x3c, 0x44, 0xe5, 0x86, 0xb5, 0x17, 0xa1, 0xd6, 0x0d, + 0xba, 0x42, 0x1d, 0xb8, 0xa9, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, + 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x19, 0xb0, 0xbe, 0xa4, 0x9d, 0x8b, + 0x3c, 0x44, 0xe5, 0x86, 0xb5, 0x17, 0xa1, 0xd6, 0x0d, 0xba, 0x42, 0x1d, + 0xb8, 0xa9, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x03, 0x03, 0x81, 0x8b, 0x00, 0x30, 0x81, 0x87, 0x02, + 0x42, 0x01, 0x37, 0x98, 0x68, 0xa0, 0x6b, 0xb3, 0x92, 0xd3, 0xcb, 0x6b, + 0x50, 0xae, 0x79, 0xc1, 0x87, 0x43, 0x00, 0xed, 0x2b, 0x33, 0x0c, 0x6e, + 0x1c, 0xed, 0xb8, 0x89, 0xea, 0x39, 0x03, 0x4f, 0xa0, 0x80, 0x85, 0x71, + 0x0b, 0x28, 0xaa, 0x50, 0x12, 0xc1, 0xf9, 0x96, 0xf5, 0x3a, 0x90, 0x9e, + 0xc4, 0x4c, 0x7a, 0x64, 0x47, 0xe8, 0x1e, 0x9e, 0x9f, 0xe4, 0xa2, 0x13, + 0x4d, 0x44, 0x13, 0x3a, 0x72, 0xf7, 0xa4, 0x02, 0x41, 0x33, 0x88, 0xef, + 0x6a, 0xd3, 0x51, 0x23, 0xd0, 0x64, 0x41, 0x2a, 0xde, 0x75, 0xda, 0x46, + 0xb5, 0xac, 0x9d, 0x70, 0x6e, 0x6c, 0xe9, 0x51, 0x62, 0x66, 0xb5, 0x87, + 0x7d, 0x31, 0xac, 0xa7, 0xa9, 0x11, 0xf1, 0x17, 0x9f, 0xc1, 0x85, 0x3b, + 0xa6, 0x86, 0x65, 0xe9, 0x90, 0xd6, 0x6b, 0x3c, 0xa8, 0x9e, 0x90, 0x43, + 0x2e, 0x38, 0x8b, 0x45, 0x32, 0xb0, 0x5b, 0xcd, 0x68, 0x77, 0x0f, 0xc3, + 0x37, 0x7e +}; diff --git a/testkeys/EC/ALL_EC_CAS_EXCEPT_P224.pem b/testkeys/EC/ALL_EC_CAS_EXCEPT_P224.pem new file mode 100644 index 0000000..17e9c0f --- /dev/null +++ b/testkeys/EC/ALL_EC_CAS_EXCEPT_P224.pem @@ -0,0 +1,52 @@ +-----BEGIN CERTIFICATE----- +MIICgDCCAiagAwIBAgIBATAKBggqhkjOPQQDAjCBmTELMAkGA1UEBhMCVVMxCzAJ +BgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMSIwIAYDVQQKDBlJbnNpZGUgU2Vj +dXJlIENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MTgwNgYDVQQDDC9NYXRyaXhT +U0wgU2FtcGxlIENBIChFbGxpcHRpYyBjdXJ2ZSBwcmltZTI1NnYxKTAeFw0xNDAz +MTMyMzIxMjNaFw0xNzAzMTIyMzIxMjNaMIGZMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxODA2BgNVBAMML01hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHByaW1lMjU2djEpMFkwEwYHKoZIzj0C +AQYIKoZIzj0DAQcDQgAE01reVhQI4kXRC6l3inBfh4y0Wy/NaXwFYX/p42a/gD+U +iBmqiv+0KPYOuxR6OWVLK31SRJxcWwlpmBYxktrMWKNdMFswCwYDVR0PBAQDAgIE +MB0GA1UdDgQWBBRpDvpHPm1A+Sl/929mhrh6NLsl6zAfBgNVHSMEGDAWgBRpDvpH +Pm1A+Sl/929mhrh6NLsl6zAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0gAMEUC +IEJpv0FiyaZRsg7ZOQwMVUzDYheq6fOLugz54wmynerYAiEAggMh/X68RLcJiiXO +WmaOeXJatBC1Fs5nAo+RXhxd76M= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICvDCCAkKgAwIBAgICIygwCgYIKoZIzj0EAwMwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDM4NHIxKTAeFw0xNDAz +MTMyMzIxMjdaFw0xNzAzMTIyMzIxMjdaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3AzODRyMSkwdjAQBgcqhkjOPQIB +BgUrgQQAIgNiAASeBDSZ74olHYTy8kDE1dFTfVTsIDbfGuLkcPjTOaA5GD2x+i3s +osFG322Uj97c0j0ZLxbsUlg6gMHDv4UnFkIH4ALx15XJEOywoJiKQrVR6CH7Ka/5 +RaiydhBG7+Ts38GjXTBbMAsGA1UdDwQEAwICBDAdBgNVHQ4EFgQURO38ixdCbmH2 +NZM9P4GXb2doWhswHwYDVR0jBBgwFoAURO38ixdCbmH2NZM9P4GXb2doWhswDAYD +VR0TBAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA1GSuHNsU+JHIF9Tv0Is2bvZH +ZeW26O3ktW1EuHBgobu7aBkpgqT61eefD7T5pNuVAjA+tjAGba3wJQi2MPrOhDMr +1sKubIXMQswCGQwYe1V7FzznzhRPdIApzZiHTUZYpN4= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDBjCCAmigAwIBAgICI/AwCgYIKoZIzj0EAwMwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDUyMXIxKTAeFw0xNDAz +MTMyMzIxMzFaFw0xNzAzMTIyMzIxMzFaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3A1MjFyMSkwgZswEAYHKoZIzj0C +AQYFK4EEACMDgYYABAErQ9iNn9UvnVUL/nILMteOQsQCl7PNdxWh6vZkNXJyZ7Nf +dyZtb3crS6Ga24x2xNydYC07XgfxpXURInr175l3RADELacTwMeL1ZaSba6ElSUf +sGh7iXW/Rraeoqxw9uwXbpguC6wTeF9UjAC9Ooxc16SGtZwEZ3Xg3E2KQkbs5F3x +qqNdMFswCwYDVR0PBAQDAgIEMB0GA1UdDgQWBBQZsL6knYs8ROWGtReh1g26Qh24 +qTAfBgNVHSMEGDAWgBQZsL6knYs8ROWGtReh1g26Qh24qTAMBgNVHRMEBTADAQH/ +MAoGCCqGSM49BAMDA4GLADCBhwJCATeYaKBrs5LTy2tQrnnBh0MA7SszDG4c7biJ +6jkDT6CAhXELKKpQEsH5lvU6kJ7ETHpkR+genp/kohNNRBM6cvekAkEziO9q01Ej +0GRBKt512ka1rJ1wbmzpUWJmtYd9MaynqRHxF5/BhTumhmXpkNZrPKiekEMuOItF +MrBbzWh3D8M3fg== +-----END CERTIFICATE----- diff --git a/testkeys/EC/ALL_EC_CAS_EXCEPT_P224_AND_P521.h b/testkeys/EC/ALL_EC_CAS_EXCEPT_P224_AND_P521.h new file mode 100644 index 0000000..f3d08dc --- /dev/null +++ b/testkeys/EC/ALL_EC_CAS_EXCEPT_P224_AND_P521.h @@ -0,0 +1,166 @@ +const static unsigned char ECCAS[] = { + 0x30, 0x82, 0x02, 0x63, 0x30, 0x82, 0x02, 0x1a, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x02, 0x1b, 0x58, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0x9a, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, + 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, + 0x74, 0x74, 0x6c, 0x65, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x1a, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, + 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x38, 0x30, 0x36, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x4d, 0x61, 0x74, 0x72, 0x69, + 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, + 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, + 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, + 0x31, 0x39, 0x32, 0x76, 0x31, 0x29, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, + 0x30, 0x33, 0x31, 0x37, 0x32, 0x31, 0x33, 0x37, 0x30, 0x37, 0x5a, 0x17, + 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x36, 0x32, 0x31, 0x33, 0x37, 0x30, + 0x37, 0x5a, 0x30, 0x81, 0x9a, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, + 0x65, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x1a, + 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x2e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, + 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x2f, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, + 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, + 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, + 0x72, 0x76, 0x65, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x31, 0x39, 0x32, + 0x76, 0x31, 0x29, 0x30, 0x49, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, + 0x01, 0x01, 0x03, 0x32, 0x00, 0x04, 0x59, 0xee, 0xa1, 0x5d, 0xbb, 0x9e, + 0x32, 0x82, 0x7c, 0x98, 0x5a, 0xb8, 0x70, 0x63, 0x07, 0xaf, 0xf2, 0x0d, + 0xb3, 0x15, 0x27, 0x8c, 0x01, 0x76, 0x41, 0xb6, 0x6a, 0x9a, 0xa1, 0x45, + 0x88, 0x23, 0xfb, 0x0b, 0xe6, 0x3d, 0x80, 0xd6, 0x0a, 0xcc, 0xfb, 0x00, + 0x57, 0xee, 0x18, 0x93, 0x64, 0xe0, 0xa3, 0x5e, 0x30, 0x5c, 0x30, 0x0c, + 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x05, 0x03, 0x03, 0x07, 0x04, 0x80, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x93, + 0x3f, 0xb3, 0x5a, 0x38, 0x55, 0xdd, 0xb4, 0xd6, 0x6e, 0x84, 0xcc, 0x66, + 0xce, 0x8c, 0x26, 0x5b, 0x1c, 0x17, 0x20, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x93, 0x3f, 0xb3, 0x5a, + 0x38, 0x55, 0xdd, 0xb4, 0xd6, 0x6e, 0x84, 0xcc, 0x66, 0xce, 0x8c, 0x26, + 0x5b, 0x1c, 0x17, 0x20, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x37, 0x00, 0x30, 0x34, 0x02, + 0x18, 0x78, 0xd0, 0xb2, 0x50, 0x8e, 0x3e, 0x2b, 0xec, 0xbf, 0xf9, 0x25, + 0xee, 0x0f, 0xb9, 0xad, 0xc6, 0xec, 0x66, 0x93, 0x76, 0x1d, 0xcd, 0x29, + 0x1b, 0x02, 0x18, 0x63, 0xfa, 0x37, 0xaa, 0x45, 0x4d, 0x17, 0x46, 0xaf, + 0xa4, 0x23, 0x84, 0xfc, 0xef, 0xd6, 0xf5, 0x1c, 0xce, 0x5e, 0x32, 0x1b, + 0x1b, 0x42, 0x07, 0x30, 0x82, 0x02, 0x80, 0x30, 0x82, 0x02, 0x26, 0xa0, + 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0x99, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, + 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, + 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x38, 0x30, + 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x4d, 0x61, 0x74, 0x72, + 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, + 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, + 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, 0x70, 0x72, 0x69, 0x6d, + 0x65, 0x32, 0x35, 0x36, 0x76, 0x31, 0x29, 0x30, 0x1e, 0x17, 0x0d, 0x31, + 0x34, 0x30, 0x33, 0x31, 0x33, 0x32, 0x33, 0x32, 0x31, 0x32, 0x33, 0x5a, + 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x32, 0x32, 0x33, 0x32, 0x31, + 0x32, 0x33, 0x5a, 0x30, 0x81, 0x99, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, + 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, + 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, + 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x2f, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, + 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, + 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, + 0x72, 0x76, 0x65, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x32, 0x35, 0x36, + 0x76, 0x31, 0x29, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, + 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xd3, 0x5a, 0xde, 0x56, 0x14, 0x08, + 0xe2, 0x45, 0xd1, 0x0b, 0xa9, 0x77, 0x8a, 0x70, 0x5f, 0x87, 0x8c, 0xb4, + 0x5b, 0x2f, 0xcd, 0x69, 0x7c, 0x05, 0x61, 0x7f, 0xe9, 0xe3, 0x66, 0xbf, + 0x80, 0x3f, 0x94, 0x88, 0x19, 0xaa, 0x8a, 0xff, 0xb4, 0x28, 0xf6, 0x0e, + 0xbb, 0x14, 0x7a, 0x39, 0x65, 0x4b, 0x2b, 0x7d, 0x52, 0x44, 0x9c, 0x5c, + 0x5b, 0x09, 0x69, 0x98, 0x16, 0x31, 0x92, 0xda, 0xcc, 0x58, 0xa3, 0x5d, + 0x30, 0x5b, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, + 0x02, 0x02, 0x04, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, + 0x04, 0x14, 0x69, 0x0e, 0xfa, 0x47, 0x3e, 0x6d, 0x40, 0xf9, 0x29, 0x7f, + 0xf7, 0x6f, 0x66, 0x86, 0xb8, 0x7a, 0x34, 0xbb, 0x25, 0xeb, 0x30, 0x1f, + 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x69, + 0x0e, 0xfa, 0x47, 0x3e, 0x6d, 0x40, 0xf9, 0x29, 0x7f, 0xf7, 0x6f, 0x66, + 0x86, 0xb8, 0x7a, 0x34, 0xbb, 0x25, 0xeb, 0x30, 0x0c, 0x06, 0x03, 0x55, + 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, + 0x30, 0x45, 0x02, 0x20, 0x42, 0x69, 0xbf, 0x41, 0x62, 0xc9, 0xa6, 0x51, + 0xb2, 0x0e, 0xd9, 0x39, 0x0c, 0x0c, 0x55, 0x4c, 0xc3, 0x62, 0x17, 0xaa, + 0xe9, 0xf3, 0x8b, 0xba, 0x0c, 0xf9, 0xe3, 0x09, 0xb2, 0x9d, 0xea, 0xd8, + 0x02, 0x21, 0x00, 0x82, 0x03, 0x21, 0xfd, 0x7e, 0xbc, 0x44, 0xb7, 0x09, + 0x8a, 0x25, 0xce, 0x5a, 0x66, 0x8e, 0x79, 0x72, 0x5a, 0xb4, 0x10, 0xb5, + 0x16, 0xce, 0x67, 0x02, 0x8f, 0x91, 0x5e, 0x1c, 0x5d, 0xef, 0xa3, 0x30, + 0x82, 0x02, 0xbc, 0x30, 0x82, 0x02, 0x42, 0xa0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x02, 0x23, 0x28, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x03, 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, + 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x2e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, + 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, + 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, + 0x75, 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, 0x63, 0x70, 0x33, 0x38, 0x34, + 0x72, 0x31, 0x29, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, + 0x33, 0x32, 0x33, 0x32, 0x31, 0x32, 0x37, 0x5a, 0x17, 0x0d, 0x31, 0x37, + 0x30, 0x33, 0x31, 0x32, 0x32, 0x33, 0x32, 0x31, 0x32, 0x37, 0x5a, 0x30, + 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x22, + 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, 0x73, + 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, + 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, + 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, + 0x74, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2e, + 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, 0x6c, + 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, + 0x73, 0x65, 0x63, 0x70, 0x33, 0x38, 0x34, 0x72, 0x31, 0x29, 0x30, 0x76, + 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, + 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0x9e, 0x04, + 0x34, 0x99, 0xef, 0x8a, 0x25, 0x1d, 0x84, 0xf2, 0xf2, 0x40, 0xc4, 0xd5, + 0xd1, 0x53, 0x7d, 0x54, 0xec, 0x20, 0x36, 0xdf, 0x1a, 0xe2, 0xe4, 0x70, + 0xf8, 0xd3, 0x39, 0xa0, 0x39, 0x18, 0x3d, 0xb1, 0xfa, 0x2d, 0xec, 0xa2, + 0xc1, 0x46, 0xdf, 0x6d, 0x94, 0x8f, 0xde, 0xdc, 0xd2, 0x3d, 0x19, 0x2f, + 0x16, 0xec, 0x52, 0x58, 0x3a, 0x80, 0xc1, 0xc3, 0xbf, 0x85, 0x27, 0x16, + 0x42, 0x07, 0xe0, 0x02, 0xf1, 0xd7, 0x95, 0xc9, 0x10, 0xec, 0xb0, 0xa0, + 0x98, 0x8a, 0x42, 0xb5, 0x51, 0xe8, 0x21, 0xfb, 0x29, 0xaf, 0xf9, 0x45, + 0xa8, 0xb2, 0x76, 0x10, 0x46, 0xef, 0xe4, 0xec, 0xdf, 0xc1, 0xa3, 0x5d, + 0x30, 0x5b, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, + 0x02, 0x02, 0x04, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, + 0x04, 0x14, 0x44, 0xed, 0xfc, 0x8b, 0x17, 0x42, 0x6e, 0x61, 0xf6, 0x35, + 0x93, 0x3d, 0x3f, 0x81, 0x97, 0x6f, 0x67, 0x68, 0x5a, 0x1b, 0x30, 0x1f, + 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x44, + 0xed, 0xfc, 0x8b, 0x17, 0x42, 0x6e, 0x61, 0xf6, 0x35, 0x93, 0x3d, 0x3f, + 0x81, 0x97, 0x6f, 0x67, 0x68, 0x5a, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, + 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x68, 0x00, + 0x30, 0x65, 0x02, 0x31, 0x00, 0xd4, 0x64, 0xae, 0x1c, 0xdb, 0x14, 0xf8, + 0x91, 0xc8, 0x17, 0xd4, 0xef, 0xd0, 0x8b, 0x36, 0x6e, 0xf6, 0x47, 0x65, + 0xe5, 0xb6, 0xe8, 0xed, 0xe4, 0xb5, 0x6d, 0x44, 0xb8, 0x70, 0x60, 0xa1, + 0xbb, 0xbb, 0x68, 0x19, 0x29, 0x82, 0xa4, 0xfa, 0xd5, 0xe7, 0x9f, 0x0f, + 0xb4, 0xf9, 0xa4, 0xdb, 0x95, 0x02, 0x30, 0x3e, 0xb6, 0x30, 0x06, 0x6d, + 0xad, 0xf0, 0x25, 0x08, 0xb6, 0x30, 0xfa, 0xce, 0x84, 0x33, 0x2b, 0xd6, + 0xc2, 0xae, 0x6c, 0x85, 0xcc, 0x42, 0xcc, 0x02, 0x19, 0x0c, 0x18, 0x7b, + 0x55, 0x7b, 0x17, 0x3c, 0xe7, 0xce, 0x14, 0x4f, 0x74, 0x80, 0x29, 0xcd, + 0x98, 0x87, 0x4d, 0x46, 0x58, 0xa4, 0xde +}; diff --git a/testkeys/EC/ALL_EC_CAS_EXCEPT_P224_AND_P521.pem b/testkeys/EC/ALL_EC_CAS_EXCEPT_P224_AND_P521.pem new file mode 100644 index 0000000..8fdd511 --- /dev/null +++ b/testkeys/EC/ALL_EC_CAS_EXCEPT_P224_AND_P521.pem @@ -0,0 +1,48 @@ +-----BEGIN CERTIFICATE----- +MIICYzCCAhqgAwIBAgICG1gwCgYIKoZIzj0EAwIwgZoxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEjMCEGA1UECgwaSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbi4xDTALBgNVBAsMBFRlc3QxODA2BgNVBAMML01hdHJp +eFNTTCBTYW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHByaW1lMTkydjEpMB4XDTE0 +MDMxNzIxMzcwN1oXDTE3MDMxNjIxMzcwN1owgZoxCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEjMCEGA1UECgwaSW5zaWRlIFNlY3Vy +ZSBDb3Jwb3JhdGlvbi4xDTALBgNVBAsMBFRlc3QxODA2BgNVBAMML01hdHJpeFNT +TCBTYW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHByaW1lMTkydjEpMEkwEwYHKoZI +zj0CAQYIKoZIzj0DAQEDMgAEWe6hXbueMoJ8mFq4cGMHr/INsxUnjAF2QbZqmqFF +iCP7C+Y9gNYKzPsAV+4Yk2Tgo14wXDAMBgNVHQ8EBQMDBwSAMB0GA1UdDgQWBBST +P7NaOFXdtNZuhMxmzowmWxwXIDAfBgNVHSMEGDAWgBSTP7NaOFXdtNZuhMxmzowm +WxwXIDAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCAzcAMDQCGHjQslCOPivsv/kl +7g+5rcbsZpN2Hc0pGwIYY/o3qkVNF0avpCOE/O/W9RzOXjIbG0IH +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICgDCCAiagAwIBAgIBATAKBggqhkjOPQQDAjCBmTELMAkGA1UEBhMCVVMxCzAJ +BgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMSIwIAYDVQQKDBlJbnNpZGUgU2Vj +dXJlIENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MTgwNgYDVQQDDC9NYXRyaXhT +U0wgU2FtcGxlIENBIChFbGxpcHRpYyBjdXJ2ZSBwcmltZTI1NnYxKTAeFw0xNDAz +MTMyMzIxMjNaFw0xNzAzMTIyMzIxMjNaMIGZMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxODA2BgNVBAMML01hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHByaW1lMjU2djEpMFkwEwYHKoZIzj0C +AQYIKoZIzj0DAQcDQgAE01reVhQI4kXRC6l3inBfh4y0Wy/NaXwFYX/p42a/gD+U +iBmqiv+0KPYOuxR6OWVLK31SRJxcWwlpmBYxktrMWKNdMFswCwYDVR0PBAQDAgIE +MB0GA1UdDgQWBBRpDvpHPm1A+Sl/929mhrh6NLsl6zAfBgNVHSMEGDAWgBRpDvpH +Pm1A+Sl/929mhrh6NLsl6zAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0gAMEUC +IEJpv0FiyaZRsg7ZOQwMVUzDYheq6fOLugz54wmynerYAiEAggMh/X68RLcJiiXO +WmaOeXJatBC1Fs5nAo+RXhxd76M= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICvDCCAkKgAwIBAgICIygwCgYIKoZIzj0EAwMwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDM4NHIxKTAeFw0xNDAz +MTMyMzIxMjdaFw0xNzAzMTIyMzIxMjdaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3AzODRyMSkwdjAQBgcqhkjOPQIB +BgUrgQQAIgNiAASeBDSZ74olHYTy8kDE1dFTfVTsIDbfGuLkcPjTOaA5GD2x+i3s +osFG322Uj97c0j0ZLxbsUlg6gMHDv4UnFkIH4ALx15XJEOywoJiKQrVR6CH7Ka/5 +RaiydhBG7+Ts38GjXTBbMAsGA1UdDwQEAwICBDAdBgNVHQ4EFgQURO38ixdCbmH2 +NZM9P4GXb2doWhswHwYDVR0jBBgwFoAURO38ixdCbmH2NZM9P4GXb2doWhswDAYD +VR0TBAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA1GSuHNsU+JHIF9Tv0Is2bvZH +ZeW26O3ktW1EuHBgobu7aBkpgqT61eefD7T5pNuVAjA+tjAGba3wJQi2MPrOhDMr +1sKubIXMQswCGQwYe1V7FzznzhRPdIApzZiHTUZYpN4= +-----END CERTIFICATE----- diff --git a/testkeys/EC/ALL_EC_CAS_EXCEPT_P521.h b/testkeys/EC/ALL_EC_CAS_EXCEPT_P521.h new file mode 100644 index 0000000..3effbc7 --- /dev/null +++ b/testkeys/EC/ALL_EC_CAS_EXCEPT_P521.h @@ -0,0 +1,218 @@ +const static unsigned char ECCAS[] = { + 0x30, 0x82, 0x02, 0x63, 0x30, 0x82, 0x02, 0x1a, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x02, 0x1b, 0x58, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0x9a, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, + 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, + 0x74, 0x74, 0x6c, 0x65, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x1a, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, + 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x38, 0x30, 0x36, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x4d, 0x61, 0x74, 0x72, 0x69, + 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, + 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, + 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, + 0x31, 0x39, 0x32, 0x76, 0x31, 0x29, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, + 0x30, 0x33, 0x31, 0x37, 0x32, 0x31, 0x33, 0x37, 0x30, 0x37, 0x5a, 0x17, + 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x36, 0x32, 0x31, 0x33, 0x37, 0x30, + 0x37, 0x5a, 0x30, 0x81, 0x9a, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, + 0x65, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x1a, + 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x2e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, + 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x2f, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, + 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, + 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, + 0x72, 0x76, 0x65, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x31, 0x39, 0x32, + 0x76, 0x31, 0x29, 0x30, 0x49, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, + 0x01, 0x01, 0x03, 0x32, 0x00, 0x04, 0x59, 0xee, 0xa1, 0x5d, 0xbb, 0x9e, + 0x32, 0x82, 0x7c, 0x98, 0x5a, 0xb8, 0x70, 0x63, 0x07, 0xaf, 0xf2, 0x0d, + 0xb3, 0x15, 0x27, 0x8c, 0x01, 0x76, 0x41, 0xb6, 0x6a, 0x9a, 0xa1, 0x45, + 0x88, 0x23, 0xfb, 0x0b, 0xe6, 0x3d, 0x80, 0xd6, 0x0a, 0xcc, 0xfb, 0x00, + 0x57, 0xee, 0x18, 0x93, 0x64, 0xe0, 0xa3, 0x5e, 0x30, 0x5c, 0x30, 0x0c, + 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x05, 0x03, 0x03, 0x07, 0x04, 0x80, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x93, + 0x3f, 0xb3, 0x5a, 0x38, 0x55, 0xdd, 0xb4, 0xd6, 0x6e, 0x84, 0xcc, 0x66, + 0xce, 0x8c, 0x26, 0x5b, 0x1c, 0x17, 0x20, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x93, 0x3f, 0xb3, 0x5a, + 0x38, 0x55, 0xdd, 0xb4, 0xd6, 0x6e, 0x84, 0xcc, 0x66, 0xce, 0x8c, 0x26, + 0x5b, 0x1c, 0x17, 0x20, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x37, 0x00, 0x30, 0x34, 0x02, + 0x18, 0x78, 0xd0, 0xb2, 0x50, 0x8e, 0x3e, 0x2b, 0xec, 0xbf, 0xf9, 0x25, + 0xee, 0x0f, 0xb9, 0xad, 0xc6, 0xec, 0x66, 0x93, 0x76, 0x1d, 0xcd, 0x29, + 0x1b, 0x02, 0x18, 0x63, 0xfa, 0x37, 0xaa, 0x45, 0x4d, 0x17, 0x46, 0xaf, + 0xa4, 0x23, 0x84, 0xfc, 0xef, 0xd6, 0xf5, 0x1c, 0xce, 0x5e, 0x32, 0x1b, + 0x1b, 0x42, 0x07, 0x30, 0x82, 0x02, 0x6c, 0x30, 0x82, 0x02, 0x1a, 0xa0, + 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x1f, 0x40, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0x98, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, + 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, + 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, + 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, + 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, + 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x37, + 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2e, 0x4d, 0x61, 0x74, + 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, + 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, 0x63, + 0x70, 0x32, 0x32, 0x34, 0x72, 0x31, 0x29, 0x30, 0x1e, 0x17, 0x0d, 0x31, + 0x34, 0x30, 0x33, 0x31, 0x33, 0x32, 0x33, 0x32, 0x30, 0x34, 0x30, 0x5a, + 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x32, 0x32, 0x33, 0x32, 0x30, + 0x34, 0x30, 0x5a, 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, + 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, + 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, + 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x2e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, + 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, + 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, + 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, 0x63, 0x70, 0x32, 0x32, 0x34, 0x72, + 0x31, 0x29, 0x30, 0x4e, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x21, 0x03, 0x3a, + 0x00, 0x04, 0xfd, 0x0b, 0xb3, 0x75, 0x25, 0x35, 0x5e, 0x75, 0xa3, 0x83, + 0x8b, 0x51, 0x7e, 0xff, 0xb8, 0x1e, 0x2a, 0x8c, 0x5b, 0x8e, 0xce, 0xd7, + 0xe1, 0xc3, 0x9a, 0x50, 0x25, 0x8d, 0xca, 0x0c, 0x2b, 0x9f, 0xfa, 0x3e, + 0x53, 0xac, 0x31, 0x52, 0x7f, 0x67, 0xa6, 0x92, 0xa6, 0xa3, 0xdb, 0xa8, + 0x94, 0x4b, 0x22, 0x33, 0x1d, 0x5f, 0x5f, 0xcf, 0x48, 0x21, 0xa3, 0x5d, + 0x30, 0x5b, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, + 0x02, 0x02, 0x04, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, + 0x04, 0x14, 0xc1, 0x2f, 0xad, 0xc4, 0xd5, 0x01, 0xf8, 0x91, 0xe2, 0xcf, + 0xc1, 0xbe, 0xe6, 0x0b, 0x22, 0xe7, 0x2d, 0x3b, 0x5b, 0xd8, 0x30, 0x1f, + 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xc1, + 0x2f, 0xad, 0xc4, 0xd5, 0x01, 0xf8, 0x91, 0xe2, 0xcf, 0xc1, 0xbe, 0xe6, + 0x0b, 0x22, 0xe7, 0x2d, 0x3b, 0x5b, 0xd8, 0x30, 0x0c, 0x06, 0x03, 0x55, + 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x40, 0x00, + 0x30, 0x3d, 0x02, 0x1d, 0x00, 0xfe, 0x1c, 0x56, 0xb3, 0xa3, 0xb9, 0xd5, + 0xb8, 0x72, 0x9c, 0x22, 0xd6, 0x80, 0x97, 0x5f, 0x87, 0x02, 0x22, 0x17, + 0x1a, 0xf2, 0x44, 0xf9, 0xb6, 0xeb, 0x17, 0x42, 0x33, 0x02, 0x1c, 0x44, + 0xa7, 0x43, 0x3b, 0x7d, 0xc3, 0x47, 0x15, 0xa2, 0x01, 0x71, 0x5b, 0x6f, + 0xf0, 0x36, 0xa5, 0x9b, 0xdb, 0x0b, 0xe0, 0x13, 0x96, 0x47, 0x06, 0x2f, + 0x4f, 0xfb, 0x49, 0x30, 0x82, 0x02, 0x80, 0x30, 0x82, 0x02, 0x26, 0xa0, + 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0x99, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, + 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, + 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x38, 0x30, + 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x4d, 0x61, 0x74, 0x72, + 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, + 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, + 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, 0x70, 0x72, 0x69, 0x6d, + 0x65, 0x32, 0x35, 0x36, 0x76, 0x31, 0x29, 0x30, 0x1e, 0x17, 0x0d, 0x31, + 0x34, 0x30, 0x33, 0x31, 0x33, 0x32, 0x33, 0x32, 0x31, 0x32, 0x33, 0x5a, + 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x32, 0x32, 0x33, 0x32, 0x31, + 0x32, 0x33, 0x5a, 0x30, 0x81, 0x99, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, + 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, + 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, + 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x2f, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, + 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, + 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, + 0x72, 0x76, 0x65, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x32, 0x35, 0x36, + 0x76, 0x31, 0x29, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, + 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xd3, 0x5a, 0xde, 0x56, 0x14, 0x08, + 0xe2, 0x45, 0xd1, 0x0b, 0xa9, 0x77, 0x8a, 0x70, 0x5f, 0x87, 0x8c, 0xb4, + 0x5b, 0x2f, 0xcd, 0x69, 0x7c, 0x05, 0x61, 0x7f, 0xe9, 0xe3, 0x66, 0xbf, + 0x80, 0x3f, 0x94, 0x88, 0x19, 0xaa, 0x8a, 0xff, 0xb4, 0x28, 0xf6, 0x0e, + 0xbb, 0x14, 0x7a, 0x39, 0x65, 0x4b, 0x2b, 0x7d, 0x52, 0x44, 0x9c, 0x5c, + 0x5b, 0x09, 0x69, 0x98, 0x16, 0x31, 0x92, 0xda, 0xcc, 0x58, 0xa3, 0x5d, + 0x30, 0x5b, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, + 0x02, 0x02, 0x04, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, + 0x04, 0x14, 0x69, 0x0e, 0xfa, 0x47, 0x3e, 0x6d, 0x40, 0xf9, 0x29, 0x7f, + 0xf7, 0x6f, 0x66, 0x86, 0xb8, 0x7a, 0x34, 0xbb, 0x25, 0xeb, 0x30, 0x1f, + 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x69, + 0x0e, 0xfa, 0x47, 0x3e, 0x6d, 0x40, 0xf9, 0x29, 0x7f, 0xf7, 0x6f, 0x66, + 0x86, 0xb8, 0x7a, 0x34, 0xbb, 0x25, 0xeb, 0x30, 0x0c, 0x06, 0x03, 0x55, + 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, + 0x30, 0x45, 0x02, 0x20, 0x42, 0x69, 0xbf, 0x41, 0x62, 0xc9, 0xa6, 0x51, + 0xb2, 0x0e, 0xd9, 0x39, 0x0c, 0x0c, 0x55, 0x4c, 0xc3, 0x62, 0x17, 0xaa, + 0xe9, 0xf3, 0x8b, 0xba, 0x0c, 0xf9, 0xe3, 0x09, 0xb2, 0x9d, 0xea, 0xd8, + 0x02, 0x21, 0x00, 0x82, 0x03, 0x21, 0xfd, 0x7e, 0xbc, 0x44, 0xb7, 0x09, + 0x8a, 0x25, 0xce, 0x5a, 0x66, 0x8e, 0x79, 0x72, 0x5a, 0xb4, 0x10, 0xb5, + 0x16, 0xce, 0x67, 0x02, 0x8f, 0x91, 0x5e, 0x1c, 0x5d, 0xef, 0xa3, 0x30, + 0x82, 0x02, 0xbc, 0x30, 0x82, 0x02, 0x42, 0xa0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x02, 0x23, 0x28, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x03, 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, + 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x2e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, + 0x53, 0x4c, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, + 0x20, 0x28, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, + 0x75, 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, 0x63, 0x70, 0x33, 0x38, 0x34, + 0x72, 0x31, 0x29, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, + 0x33, 0x32, 0x33, 0x32, 0x31, 0x32, 0x37, 0x5a, 0x17, 0x0d, 0x31, 0x37, + 0x30, 0x33, 0x31, 0x32, 0x32, 0x33, 0x32, 0x31, 0x32, 0x37, 0x5a, 0x30, + 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x22, + 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x6e, 0x73, + 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, + 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, + 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, + 0x74, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2e, + 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, 0x53, 0x4c, 0x20, 0x53, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x20, 0x28, 0x45, 0x6c, 0x6c, + 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x63, 0x75, 0x72, 0x76, 0x65, 0x20, + 0x73, 0x65, 0x63, 0x70, 0x33, 0x38, 0x34, 0x72, 0x31, 0x29, 0x30, 0x76, + 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, + 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0x9e, 0x04, + 0x34, 0x99, 0xef, 0x8a, 0x25, 0x1d, 0x84, 0xf2, 0xf2, 0x40, 0xc4, 0xd5, + 0xd1, 0x53, 0x7d, 0x54, 0xec, 0x20, 0x36, 0xdf, 0x1a, 0xe2, 0xe4, 0x70, + 0xf8, 0xd3, 0x39, 0xa0, 0x39, 0x18, 0x3d, 0xb1, 0xfa, 0x2d, 0xec, 0xa2, + 0xc1, 0x46, 0xdf, 0x6d, 0x94, 0x8f, 0xde, 0xdc, 0xd2, 0x3d, 0x19, 0x2f, + 0x16, 0xec, 0x52, 0x58, 0x3a, 0x80, 0xc1, 0xc3, 0xbf, 0x85, 0x27, 0x16, + 0x42, 0x07, 0xe0, 0x02, 0xf1, 0xd7, 0x95, 0xc9, 0x10, 0xec, 0xb0, 0xa0, + 0x98, 0x8a, 0x42, 0xb5, 0x51, 0xe8, 0x21, 0xfb, 0x29, 0xaf, 0xf9, 0x45, + 0xa8, 0xb2, 0x76, 0x10, 0x46, 0xef, 0xe4, 0xec, 0xdf, 0xc1, 0xa3, 0x5d, + 0x30, 0x5b, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, + 0x02, 0x02, 0x04, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, + 0x04, 0x14, 0x44, 0xed, 0xfc, 0x8b, 0x17, 0x42, 0x6e, 0x61, 0xf6, 0x35, + 0x93, 0x3d, 0x3f, 0x81, 0x97, 0x6f, 0x67, 0x68, 0x5a, 0x1b, 0x30, 0x1f, + 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x44, + 0xed, 0xfc, 0x8b, 0x17, 0x42, 0x6e, 0x61, 0xf6, 0x35, 0x93, 0x3d, 0x3f, + 0x81, 0x97, 0x6f, 0x67, 0x68, 0x5a, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, + 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x68, 0x00, + 0x30, 0x65, 0x02, 0x31, 0x00, 0xd4, 0x64, 0xae, 0x1c, 0xdb, 0x14, 0xf8, + 0x91, 0xc8, 0x17, 0xd4, 0xef, 0xd0, 0x8b, 0x36, 0x6e, 0xf6, 0x47, 0x65, + 0xe5, 0xb6, 0xe8, 0xed, 0xe4, 0xb5, 0x6d, 0x44, 0xb8, 0x70, 0x60, 0xa1, + 0xbb, 0xbb, 0x68, 0x19, 0x29, 0x82, 0xa4, 0xfa, 0xd5, 0xe7, 0x9f, 0x0f, + 0xb4, 0xf9, 0xa4, 0xdb, 0x95, 0x02, 0x30, 0x3e, 0xb6, 0x30, 0x06, 0x6d, + 0xad, 0xf0, 0x25, 0x08, 0xb6, 0x30, 0xfa, 0xce, 0x84, 0x33, 0x2b, 0xd6, + 0xc2, 0xae, 0x6c, 0x85, 0xcc, 0x42, 0xcc, 0x02, 0x19, 0x0c, 0x18, 0x7b, + 0x55, 0x7b, 0x17, 0x3c, 0xe7, 0xce, 0x14, 0x4f, 0x74, 0x80, 0x29, 0xcd, + 0x98, 0x87, 0x4d, 0x46, 0x58, 0xa4, 0xde +}; diff --git a/testkeys/EC/ALL_EC_CAS_EXCEPT_P521.pem b/testkeys/EC/ALL_EC_CAS_EXCEPT_P521.pem new file mode 100644 index 0000000..ece3cc1 --- /dev/null +++ b/testkeys/EC/ALL_EC_CAS_EXCEPT_P521.pem @@ -0,0 +1,63 @@ +-----BEGIN CERTIFICATE----- +MIICYzCCAhqgAwIBAgICG1gwCgYIKoZIzj0EAwIwgZoxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEjMCEGA1UECgwaSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbi4xDTALBgNVBAsMBFRlc3QxODA2BgNVBAMML01hdHJp +eFNTTCBTYW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHByaW1lMTkydjEpMB4XDTE0 +MDMxNzIxMzcwN1oXDTE3MDMxNjIxMzcwN1owgZoxCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEjMCEGA1UECgwaSW5zaWRlIFNlY3Vy +ZSBDb3Jwb3JhdGlvbi4xDTALBgNVBAsMBFRlc3QxODA2BgNVBAMML01hdHJpeFNT +TCBTYW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHByaW1lMTkydjEpMEkwEwYHKoZI +zj0CAQYIKoZIzj0DAQEDMgAEWe6hXbueMoJ8mFq4cGMHr/INsxUnjAF2QbZqmqFF +iCP7C+Y9gNYKzPsAV+4Yk2Tgo14wXDAMBgNVHQ8EBQMDBwSAMB0GA1UdDgQWBBST +P7NaOFXdtNZuhMxmzowmWxwXIDAfBgNVHSMEGDAWgBSTP7NaOFXdtNZuhMxmzowm +WxwXIDAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCAzcAMDQCGHjQslCOPivsv/kl +7g+5rcbsZpN2Hc0pGwIYY/o3qkVNF0avpCOE/O/W9RzOXjIbG0IH +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICbDCCAhqgAwIBAgICH0AwCgYIKoZIzj0EAwIwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDIyNHIxKTAeFw0xNDAz +MTMyMzIwNDBaFw0xNzAzMTIyMzIwNDBaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3AyMjRyMSkwTjAQBgcqhkjOPQIB +BgUrgQQAIQM6AAT9C7N1JTVedaODi1F+/7geKoxbjs7X4cOaUCWNygwrn/o+U6wx +Un9nppKmo9uolEsiMx1fX89IIaNdMFswCwYDVR0PBAQDAgIEMB0GA1UdDgQWBBTB +L63E1QH4keLPwb7mCyLnLTtb2DAfBgNVHSMEGDAWgBTBL63E1QH4keLPwb7mCyLn +LTtb2DAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0AAMD0CHQD+HFazo7nVuHKc +ItaAl1+HAiIXGvJE+bbrF0IzAhxEp0M7fcNHFaIBcVtv8Dalm9sL4BOWRwYvT/tJ +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICgDCCAiagAwIBAgIBATAKBggqhkjOPQQDAjCBmTELMAkGA1UEBhMCVVMxCzAJ +BgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMSIwIAYDVQQKDBlJbnNpZGUgU2Vj +dXJlIENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MTgwNgYDVQQDDC9NYXRyaXhT +U0wgU2FtcGxlIENBIChFbGxpcHRpYyBjdXJ2ZSBwcmltZTI1NnYxKTAeFw0xNDAz +MTMyMzIxMjNaFw0xNzAzMTIyMzIxMjNaMIGZMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxODA2BgNVBAMML01hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHByaW1lMjU2djEpMFkwEwYHKoZIzj0C +AQYIKoZIzj0DAQcDQgAE01reVhQI4kXRC6l3inBfh4y0Wy/NaXwFYX/p42a/gD+U +iBmqiv+0KPYOuxR6OWVLK31SRJxcWwlpmBYxktrMWKNdMFswCwYDVR0PBAQDAgIE +MB0GA1UdDgQWBBRpDvpHPm1A+Sl/929mhrh6NLsl6zAfBgNVHSMEGDAWgBRpDvpH +Pm1A+Sl/929mhrh6NLsl6zAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0gAMEUC +IEJpv0FiyaZRsg7ZOQwMVUzDYheq6fOLugz54wmynerYAiEAggMh/X68RLcJiiXO +WmaOeXJatBC1Fs5nAo+RXhxd76M= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICvDCCAkKgAwIBAgICIygwCgYIKoZIzj0EAwMwgZgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNl +Y3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDE3MDUGA1UEAwwuTWF0cml4 +U1NMIFNhbXBsZSBDQSAoRWxsaXB0aWMgY3VydmUgc2VjcDM4NHIxKTAeFw0xNDAz +MTMyMzIxMjdaFw0xNzAzMTIyMzIxMjdaMIGYMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QxNzA1BgNVBAMMLk1hdHJpeFNTTCBT +YW1wbGUgQ0EgKEVsbGlwdGljIGN1cnZlIHNlY3AzODRyMSkwdjAQBgcqhkjOPQIB +BgUrgQQAIgNiAASeBDSZ74olHYTy8kDE1dFTfVTsIDbfGuLkcPjTOaA5GD2x+i3s +osFG322Uj97c0j0ZLxbsUlg6gMHDv4UnFkIH4ALx15XJEOywoJiKQrVR6CH7Ka/5 +RaiydhBG7+Ts38GjXTBbMAsGA1UdDwQEAwICBDAdBgNVHQ4EFgQURO38ixdCbmH2 +NZM9P4GXb2doWhswHwYDVR0jBBgwFoAURO38ixdCbmH2NZM9P4GXb2doWhswDAYD +VR0TBAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA1GSuHNsU+JHIF9Tv0Is2bvZH +ZeW26O3ktW1EuHBgobu7aBkpgqT61eefD7T5pNuVAjA+tjAGba3wJQi2MPrOhDMr +1sKubIXMQswCGQwYe1V7FzznzhRPdIApzZiHTUZYpN4= +-----END CERTIFICATE----- diff --git a/testkeys/ECDH_RSA/1024_ECDH-RSA_CA.h b/testkeys/ECDH_RSA/1024_ECDH-RSA_CA.h new file mode 100644 index 0000000..c7de0ab --- /dev/null +++ b/testkeys/ECDH_RSA/1024_ECDH-RSA_CA.h @@ -0,0 +1,66 @@ +/** + * @file 1024_ECDH-RSA_CA.h + * @version $Format:%h%d$ + * + * Summary. + */ +unsigned char ECDHRSA1024CA[] = { +48, 130, 2, 246, 48, 130, 2, 95, 160, 3, 2, 1, 2, +2, 5, 49, 48, 48, 48, 48, 48, 13, 6, 9, 42, 134, +72, 134, 247, 13, 1, 1, 11, 5, 0, 48, 129, 170, 49, +73, 48, 71, 6, 3, 85, 4, 3, 12, 64, 83, 97, 109, +112, 108, 101, 32, 77, 97, 116, 114, 105, 120, 32, 82, 83, +65, 45, 49, 48, 50, 52, 32, 67, 101, 114, 116, 105, 102, +105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, +116, 121, 32, 102, 111, 114, 32, 69, 67, 68, 72, 95, 82, +83, 65, 32, 83, 117, 105, 116, 101, 115, 49, 11, 48, 9, +6, 3, 85, 4, 6, 12, 2, 85, 83, 49, 11, 48, 9, +6, 3, 85, 4, 8, 12, 2, 87, 65, 49, 16, 48, 14, +6, 3, 85, 4, 7, 12, 7, 83, 101, 97, 116, 116, 108, +101, 49, 34, 48, 32, 6, 3, 85, 4, 10, 12, 25, 73, +110, 115, 105, 100, 101, 32, 83, 101, 99, 117, 114, 101, 32, +67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, 49, 13, +48, 11, 6, 3, 85, 4, 11, 12, 4, 84, 101, 115, 116, +48, 30, 23, 13, 49, 52, 48, 51, 49, 51, 50, 51, 51, +54, 53, 54, 90, 23, 13, 49, 55, 48, 51, 49, 50, 50, +51, 51, 54, 53, 54, 90, 48, 129, 170, 49, 73, 48, 71, +6, 3, 85, 4, 3, 12, 64, 83, 97, 109, 112, 108, 101, +32, 77, 97, 116, 114, 105, 120, 32, 82, 83, 65, 45, 49, +48, 50, 52, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, +116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, +102, 111, 114, 32, 69, 67, 68, 72, 95, 82, 83, 65, 32, +83, 117, 105, 116, 101, 115, 49, 11, 48, 9, 6, 3, 85, +4, 6, 12, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, +4, 8, 12, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, +4, 7, 12, 7, 83, 101, 97, 116, 116, 108, 101, 49, 34, +48, 32, 6, 3, 85, 4, 10, 12, 25, 73, 110, 115, 105, +100, 101, 32, 83, 101, 99, 117, 114, 101, 32, 67, 111, 114, +112, 111, 114, 97, 116, 105, 111, 110, 49, 13, 48, 11, 6, +3, 85, 4, 11, 12, 4, 84, 101, 115, 116, 48, 129, 159, +48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, +5, 0, 3, 129, 141, 0, 48, 129, 137, 2, 129, 129, 0, +249, 12, 249, 57, 4, 33, 129, 113, 73, 137, 92, 145, 48, +230, 252, 126, 227, 81, 196, 219, 148, 230, 67, 133, 231, 42, +102, 25, 240, 192, 55, 183, 136, 13, 143, 151, 108, 28, 86, +77, 110, 206, 25, 142, 89, 70, 170, 192, 197, 41, 10, 185, +161, 19, 44, 131, 88, 108, 134, 178, 142, 94, 44, 69, 245, +181, 4, 122, 120, 206, 110, 30, 102, 245, 103, 159, 132, 160, +197, 180, 211, 197, 14, 195, 38, 39, 210, 222, 23, 100, 46, +66, 22, 150, 192, 138, 90, 169, 219, 16, 248, 170, 222, 169, +110, 26, 91, 104, 84, 216, 245, 164, 67, 252, 208, 65, 155, +212, 253, 147, 76, 87, 55, 79, 35, 160, 34, 109, 2, 3, +1, 0, 1, 163, 38, 48, 36, 48, 18, 6, 3, 85, 29, +19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, 2, 1, +0, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, +3, 2, 0, 4, 48, 13, 6, 9, 42, 134, 72, 134, 247, +13, 1, 1, 11, 5, 0, 3, 129, 129, 0, 214, 26, 73, +141, 164, 26, 253, 194, 208, 235, 145, 156, 237, 3, 48, 79, +188, 232, 59, 63, 158, 247, 78, 114, 147, 125, 230, 50, 201, +223, 117, 247, 72, 16, 89, 150, 11, 141, 199, 146, 9, 176, +148, 243, 155, 78, 244, 11, 192, 80, 98, 75, 191, 131, 163, +208, 37, 109, 206, 136, 37, 165, 62, 122, 24, 74, 210, 200, +119, 70, 113, 220, 51, 62, 203, 53, 81, 184, 228, 72, 22, +183, 67, 81, 174, 92, 56, 23, 67, 4, 13, 109, 72, 133, +99, 207, 36, 252, 3, 82, 6, 194, 140, 133, 147, 123, 56, +133, 128, 215, 148, 114, 56, 121, 135, 224, 16, 244, 68, 205, +38, 208, 186, 102, 138, 189, 44, 249}; diff --git a/testkeys/ECDH_RSA/1024_ECDH-RSA_CA.pem b/testkeys/ECDH_RSA/1024_ECDH-RSA_CA.pem new file mode 100644 index 0000000..e8a3a5c --- /dev/null +++ b/testkeys/ECDH_RSA/1024_ECDH-RSA_CA.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC9jCCAl+gAwIBAgIFMTAwMDAwDQYJKoZIhvcNAQELBQAwgaoxSTBHBgNVBAMM +QFNhbXBsZSBNYXRyaXggUlNBLTEwMjQgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IGZv +ciBFQ0RIX1JTQSBTdWl0ZXMxCzAJBgNVBAYMAlVTMQswCQYDVQQIDAJXQTEQMA4G +A1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNlY3VyZSBDb3Jwb3JhdGlv +bjENMAsGA1UECwwEVGVzdDAeFw0xNDAzMTMyMzM2NTZaFw0xNzAzMTIyMzM2NTZa +MIGqMUkwRwYDVQQDDEBTYW1wbGUgTWF0cml4IFJTQS0xMDI0IENlcnRpZmljYXRl +IEF1dGhvcml0eSBmb3IgRUNESF9SU0EgU3VpdGVzMQswCQYDVQQGDAJVUzELMAkG +A1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1 +cmUgQ29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QwgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBAPkM+TkEIYFxSYlckTDm/H7jUcTblOZDhecqZhnwwDe3iA2Pl2wc +Vk1uzhmOWUaqwMUpCrmhEyyDWGyGso5eLEX1tQR6eM5uHmb1Z5+EoMW008UOwyYn +0t4XZC5CFpbAilqp2xD4qt6pbhpbaFTY9aRD/NBBm9T9k0xXN08joCJtAgMBAAGj +JjAkMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgAEMA0GCSqGSIb3 +DQEBCwUAA4GBANYaSY2kGv3C0OuRnO0DME+86Ds/nvdOcpN95jLJ33X3SBBZlguN +x5IJsJTzm070C8BQYku/g6PQJW3OiCWlPnoYStLId0Zx3DM+yzVRuORIFrdDUa5c +OBdDBA1tSIVjzyT8A1IGwoyFk3s4hYDXlHI4eYfgEPREzSbQumaKvSz5 +-----END CERTIFICATE----- diff --git a/testkeys/ECDH_RSA/2048_ECDH-RSA_CA.h b/testkeys/ECDH_RSA/2048_ECDH-RSA_CA.h new file mode 100644 index 0000000..bce2863 --- /dev/null +++ b/testkeys/ECDH_RSA/2048_ECDH-RSA_CA.h @@ -0,0 +1,86 @@ +/** + * @file 2048_ECDH-RSA_CA.h + * @version $Format:%h%d$ + * + * Summary. + */ +unsigned char ECDHRSA2048CA[] = { +48, 130, 3, 251, 48, 130, 2, 227, 160, 3, 2, 1, 2, +2, 5, 49, 49, 48, 48, 48, 48, 13, 6, 9, 42, 134, +72, 134, 247, 13, 1, 1, 11, 5, 0, 48, 129, 170, 49, +73, 48, 71, 6, 3, 85, 4, 3, 12, 64, 83, 97, 109, +112, 108, 101, 32, 77, 97, 116, 114, 105, 120, 32, 82, 83, +65, 45, 50, 48, 52, 56, 32, 67, 101, 114, 116, 105, 102, +105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, +116, 121, 32, 102, 111, 114, 32, 69, 67, 68, 72, 95, 82, +83, 65, 32, 115, 117, 105, 116, 101, 115, 49, 11, 48, 9, +6, 3, 85, 4, 6, 12, 2, 85, 83, 49, 11, 48, 9, +6, 3, 85, 4, 8, 12, 2, 87, 65, 49, 16, 48, 14, +6, 3, 85, 4, 7, 12, 7, 83, 101, 97, 116, 116, 108, +101, 49, 34, 48, 32, 6, 3, 85, 4, 10, 12, 25, 73, +110, 115, 105, 100, 101, 32, 83, 101, 99, 117, 114, 101, 32, +67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, 49, 13, +48, 11, 6, 3, 85, 4, 11, 12, 4, 84, 101, 115, 116, +48, 30, 23, 13, 49, 52, 48, 51, 49, 51, 50, 51, 51, +55, 49, 54, 90, 23, 13, 49, 55, 48, 51, 49, 50, 50, +51, 51, 55, 49, 54, 90, 48, 129, 170, 49, 73, 48, 71, +6, 3, 85, 4, 3, 12, 64, 83, 97, 109, 112, 108, 101, +32, 77, 97, 116, 114, 105, 120, 32, 82, 83, 65, 45, 50, +48, 52, 56, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, +116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, +102, 111, 114, 32, 69, 67, 68, 72, 95, 82, 83, 65, 32, +115, 117, 105, 116, 101, 115, 49, 11, 48, 9, 6, 3, 85, +4, 6, 12, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, +4, 8, 12, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, +4, 7, 12, 7, 83, 101, 97, 116, 116, 108, 101, 49, 34, +48, 32, 6, 3, 85, 4, 10, 12, 25, 73, 110, 115, 105, +100, 101, 32, 83, 101, 99, 117, 114, 101, 32, 67, 111, 114, +112, 111, 114, 97, 116, 105, 111, 110, 49, 13, 48, 11, 6, +3, 85, 4, 11, 12, 4, 84, 101, 115, 116, 48, 130, 1, +34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, +1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, +130, 1, 1, 0, 183, 154, 29, 250, 115, 103, 178, 210, 143, +131, 146, 83, 240, 184, 185, 156, 118, 11, 230, 53, 35, 91, +60, 204, 239, 28, 32, 115, 251, 87, 32, 180, 82, 138, 12, +240, 132, 176, 46, 245, 91, 56, 130, 133, 121, 211, 43, 45, +103, 251, 59, 185, 126, 18, 93, 76, 93, 27, 90, 182, 220, +194, 50, 217, 43, 61, 125, 113, 12, 139, 59, 249, 245, 11, +136, 247, 176, 17, 105, 249, 86, 109, 230, 87, 210, 40, 62, +1, 201, 80, 94, 193, 65, 22, 234, 58, 162, 147, 235, 120, +253, 122, 110, 90, 160, 21, 25, 159, 216, 149, 13, 111, 125, +135, 141, 42, 207, 107, 197, 234, 75, 72, 101, 55, 242, 186, +6, 59, 33, 78, 153, 6, 121, 115, 121, 145, 206, 148, 52, +242, 104, 222, 104, 57, 17, 190, 190, 219, 255, 27, 92, 34, +162, 200, 85, 3, 117, 34, 80, 109, 224, 100, 207, 224, 34, +134, 173, 123, 35, 7, 156, 41, 0, 237, 132, 241, 199, 154, +15, 20, 66, 212, 157, 75, 191, 59, 165, 94, 121, 66, 26, +79, 217, 14, 253, 173, 215, 228, 122, 86, 133, 176, 108, 117, +222, 161, 244, 207, 214, 107, 225, 100, 123, 87, 242, 191, 195, +92, 196, 110, 32, 0, 176, 102, 133, 138, 231, 173, 68, 23, +207, 111, 199, 232, 1, 167, 124, 69, 176, 6, 248, 206, 9, +142, 149, 89, 63, 4, 252, 146, 174, 49, 161, 205, 92, 211, +2, 3, 1, 0, 1, 163, 38, 48, 36, 48, 18, 6, 3, +85, 29, 19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, +2, 1, 0, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, +4, 4, 3, 2, 0, 4, 48, 13, 6, 9, 42, 134, 72, +134, 247, 13, 1, 1, 11, 5, 0, 3, 130, 1, 1, 0, +166, 239, 77, 200, 194, 203, 224, 78, 200, 212, 60, 11, 97, +94, 115, 135, 129, 86, 211, 109, 9, 162, 188, 157, 209, 172, +186, 1, 130, 166, 90, 243, 6, 251, 55, 6, 9, 207, 218, +110, 98, 4, 56, 64, 72, 202, 193, 111, 14, 34, 65, 200, +222, 162, 31, 5, 202, 101, 19, 20, 215, 91, 170, 128, 246, +255, 10, 230, 190, 71, 202, 85, 41, 12, 240, 200, 52, 141, +219, 105, 110, 1, 232, 157, 185, 200, 85, 134, 152, 39, 76, +146, 202, 248, 184, 197, 223, 155, 202, 157, 9, 192, 89, 200, +34, 205, 178, 0, 242, 10, 160, 143, 227, 246, 229, 126, 150, +170, 199, 174, 162, 225, 123, 238, 133, 185, 96, 31, 177, 41, +220, 66, 109, 202, 216, 184, 230, 132, 111, 98, 188, 122, 131, +229, 123, 184, 171, 162, 213, 61, 95, 245, 215, 0, 16, 220, +128, 174, 62, 68, 20, 39, 94, 142, 138, 77, 65, 244, 159, +214, 35, 139, 126, 198, 210, 141, 60, 142, 235, 100, 116, 130, +118, 111, 123, 13, 10, 159, 39, 206, 215, 76, 157, 226, 106, +20, 198, 254, 226, 206, 154, 30, 231, 69, 81, 148, 71, 17, +120, 219, 233, 190, 193, 74, 196, 226, 43, 98, 160, 173, 184, +31, 65, 227, 93, 118, 156, 56, 209, 143, 115, 169, 53, 169, +111, 183, 132, 165, 150, 206, 223, 183, 29, 25, 105, 183, 64, +197, 214, 243, 184, 176, 77, 28, 153, 158}; diff --git a/testkeys/ECDH_RSA/2048_ECDH-RSA_CA.pem b/testkeys/ECDH_RSA/2048_ECDH-RSA_CA.pem new file mode 100644 index 0000000..ab0d3c8 --- /dev/null +++ b/testkeys/ECDH_RSA/2048_ECDH-RSA_CA.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIID+zCCAuOgAwIBAgIFMTEwMDAwDQYJKoZIhvcNAQELBQAwgaoxSTBHBgNVBAMM +QFNhbXBsZSBNYXRyaXggUlNBLTIwNDggQ2VydGlmaWNhdGUgQXV0aG9yaXR5IGZv +ciBFQ0RIX1JTQSBzdWl0ZXMxCzAJBgNVBAYMAlVTMQswCQYDVQQIDAJXQTEQMA4G +A1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNlY3VyZSBDb3Jwb3JhdGlv +bjENMAsGA1UECwwEVGVzdDAeFw0xNDAzMTMyMzM3MTZaFw0xNzAzMTIyMzM3MTZa +MIGqMUkwRwYDVQQDDEBTYW1wbGUgTWF0cml4IFJTQS0yMDQ4IENlcnRpZmljYXRl +IEF1dGhvcml0eSBmb3IgRUNESF9SU0Egc3VpdGVzMQswCQYDVQQGDAJVUzELMAkG +A1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1 +cmUgQ29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQC3mh36c2ey0o+DklPwuLmcdgvmNSNbPMzvHCBz+1cgtFKK +DPCEsC71WziChXnTKy1n+zu5fhJdTF0bWrbcwjLZKz19cQyLO/n1C4j3sBFp+VZt +5lfSKD4ByVBewUEW6jqik+t4/XpuWqAVGZ/YlQ1vfYeNKs9rxepLSGU38roGOyFO +mQZ5c3mRzpQ08mjeaDkRvr7b/xtcIqLIVQN1IlBt4GTP4CKGrXsjB5wpAO2E8cea +DxRC1J1LvzulXnlCGk/ZDv2t1+R6VoWwbHXeofTP1mvhZHtX8r/DXMRuIACwZoWK +561EF89vx+gBp3xFsAb4zgmOlVk/BPySrjGhzVzTAgMBAAGjJjAkMBIGA1UdEwEB +/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgAEMA0GCSqGSIb3DQEBCwUAA4IBAQCm +703IwsvgTsjUPAthXnOHgVbTbQmivJ3RrLoBgqZa8wb7NwYJz9puYgQ4QEjKwW8O +IkHI3qIfBcplExTXW6qA9v8K5r5HylUpDPDINI3baW4B6J25yFWGmCdMksr4uMXf +m8qdCcBZyCLNsgDyCqCP4/blfpaqx66i4XvuhblgH7Ep3EJtyti45oRvYrx6g+V7 +uKui1T1f9dcAENyArj5EFCdejopNQfSf1iOLfsbSjTyO62R0gnZvew0KnyfO10yd +4moUxv7izpoe50VRlEcReNvpvsFKxOIrYqCtuB9B4112nDjRj3OpNalvt4Slls7f +tx0ZabdAxdbzuLBNHJme +-----END CERTIFICATE----- diff --git a/testkeys/ECDH_RSA/256_ECDH-RSA.h b/testkeys/ECDH_RSA/256_ECDH-RSA.h new file mode 100644 index 0000000..4beec41 --- /dev/null +++ b/testkeys/ECDH_RSA/256_ECDH-RSA.h @@ -0,0 +1,81 @@ +/** + * @file 256_ECDH-RSA.h + * @version $Format:%h%d$ + * + * Summary. + */ +unsigned char ECDHRSA256[] = { +48, 130, 3, 179, 48, 130, 3, 28, 160, 3, 2, 1, 2, +2, 2, 46, 224, 48, 13, 6, 9, 42, 134, 72, 134, 247, +13, 1, 1, 11, 5, 0, 48, 129, 170, 49, 73, 48, 71, +6, 3, 85, 4, 3, 12, 64, 83, 97, 109, 112, 108, 101, +32, 77, 97, 116, 114, 105, 120, 32, 82, 83, 65, 45, 49, +48, 50, 52, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, +116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, +102, 111, 114, 32, 69, 67, 68, 72, 95, 82, 83, 65, 32, +83, 117, 105, 116, 101, 115, 49, 11, 48, 9, 6, 3, 85, +4, 6, 12, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, +4, 8, 12, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, +4, 7, 12, 7, 83, 101, 97, 116, 116, 108, 101, 49, 34, +48, 32, 6, 3, 85, 4, 10, 12, 25, 73, 110, 115, 105, +100, 101, 32, 83, 101, 99, 117, 114, 101, 32, 67, 111, 114, +112, 111, 114, 97, 116, 105, 111, 110, 49, 13, 48, 11, 6, +3, 85, 4, 11, 12, 4, 84, 101, 115, 116, 48, 30, 23, +13, 49, 52, 48, 51, 49, 51, 50, 51, 51, 55, 53, 50, +90, 23, 13, 49, 55, 48, 51, 49, 50, 50, 51, 51, 55, +53, 50, 90, 48, 129, 164, 49, 11, 48, 9, 6, 3, 85, +4, 6, 19, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, +4, 8, 12, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, +4, 7, 12, 7, 83, 101, 97, 116, 116, 108, 101, 49, 34, +48, 32, 6, 3, 85, 4, 10, 12, 25, 73, 110, 115, 105, +100, 101, 32, 83, 101, 99, 117, 114, 101, 32, 67, 111, 114, +112, 111, 114, 97, 116, 105, 111, 110, 49, 13, 48, 11, 6, +3, 85, 4, 11, 12, 4, 84, 101, 115, 116, 49, 67, 48, +65, 6, 3, 85, 4, 3, 12, 58, 77, 97, 116, 114, 105, +120, 83, 83, 76, 32, 83, 97, 109, 112, 108, 101, 32, 69, +67, 68, 72, 95, 82, 83, 65, 32, 67, 101, 114, 116, 32, +40, 69, 108, 108, 105, 112, 116, 105, 99, 32, 99, 117, 114, +118, 101, 32, 112, 114, 105, 109, 101, 50, 53, 54, 118, 49, +41, 48, 89, 48, 19, 6, 7, 42, 134, 72, 206, 61, 2, +1, 6, 8, 42, 134, 72, 206, 61, 3, 1, 7, 3, 66, +0, 4, 151, 62, 143, 194, 217, 167, 170, 180, 158, 44, 228, +49, 213, 151, 244, 174, 61, 110, 138, 239, 163, 165, 39, 194, +230, 51, 87, 108, 160, 245, 184, 226, 199, 143, 117, 186, 141, +4, 139, 254, 221, 58, 43, 36, 116, 82, 238, 114, 226, 142, +43, 218, 103, 126, 214, 235, 174, 136, 110, 203, 86, 67, 147, +189, 163, 130, 1, 49, 48, 130, 1, 45, 48, 9, 6, 3, +85, 29, 19, 4, 2, 48, 0, 48, 29, 6, 3, 85, 29, +14, 4, 22, 4, 20, 34, 62, 226, 129, 202, 161, 71, 71, +4, 169, 253, 219, 27, 175, 35, 102, 245, 141, 194, 250, 48, +129, 197, 6, 3, 85, 29, 35, 4, 129, 189, 48, 129, 186, +161, 129, 176, 164, 129, 173, 48, 129, 170, 49, 73, 48, 71, +6, 3, 85, 4, 3, 12, 64, 83, 97, 109, 112, 108, 101, +32, 77, 97, 116, 114, 105, 120, 32, 82, 83, 65, 45, 49, +48, 50, 52, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, +116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, +102, 111, 114, 32, 69, 67, 68, 72, 95, 82, 83, 65, 32, +83, 117, 105, 116, 101, 115, 49, 11, 48, 9, 6, 3, 85, +4, 6, 12, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, +4, 8, 12, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, +4, 7, 12, 7, 83, 101, 97, 116, 116, 108, 101, 49, 34, +48, 32, 6, 3, 85, 4, 10, 12, 25, 73, 110, 115, 105, +100, 101, 32, 83, 101, 99, 117, 114, 101, 32, 67, 111, 114, +112, 111, 114, 97, 116, 105, 111, 110, 49, 13, 48, 11, 6, +3, 85, 4, 11, 12, 4, 84, 101, 115, 116, 130, 5, 49, +48, 48, 48, 48, 48, 29, 6, 3, 85, 29, 37, 4, 22, +48, 20, 6, 8, 43, 6, 1, 5, 5, 7, 3, 1, 6, +8, 43, 6, 1, 5, 5, 7, 3, 2, 48, 26, 6, 3, +85, 29, 17, 4, 19, 48, 17, 130, 9, 108, 111, 99, 97, +108, 104, 111, 115, 116, 135, 4, 127, 0, 0, 1, 48, 13, +6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, +3, 129, 129, 0, 13, 48, 12, 208, 6, 240, 156, 227, 27, +116, 160, 136, 2, 20, 96, 84, 23, 130, 138, 97, 140, 246, +200, 155, 252, 37, 161, 185, 33, 252, 56, 144, 222, 136, 189, +208, 36, 127, 10, 104, 140, 224, 120, 231, 101, 73, 100, 135, +19, 129, 247, 43, 33, 183, 191, 1, 109, 202, 134, 118, 212, +207, 11, 174, 77, 108, 39, 120, 43, 181, 90, 226, 54, 76, +134, 19, 201, 101, 156, 10, 173, 58, 75, 27, 221, 157, 211, +238, 147, 47, 185, 46, 184, 47, 60, 226, 112, 24, 117, 246, +165, 72, 143, 60, 98, 43, 73, 19, 80, 50, 214, 28, 224, +235, 162, 148, 241, 160, 13, 136, 219, 27, 38, 4, 253, 39, +21, 89}; diff --git a/testkeys/ECDH_RSA/256_ECDH-RSA.pem b/testkeys/ECDH_RSA/256_ECDH-RSA.pem new file mode 100644 index 0000000..8fe8f92 --- /dev/null +++ b/testkeys/ECDH_RSA/256_ECDH-RSA.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDszCCAxygAwIBAgICLuAwDQYJKoZIhvcNAQELBQAwgaoxSTBHBgNVBAMMQFNh +bXBsZSBNYXRyaXggUlNBLTEwMjQgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IGZvciBF +Q0RIX1JTQSBTdWl0ZXMxCzAJBgNVBAYMAlVTMQswCQYDVQQIDAJXQTEQMA4GA1UE +BwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNlY3VyZSBDb3Jwb3JhdGlvbjEN +MAsGA1UECwwEVGVzdDAeFw0xNDAzMTMyMzM3NTJaFw0xNzAzMTIyMzM3NTJaMIGk +MQswCQYDVQQGEwJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAg +BgNVBAoMGUluc2lkZSBTZWN1cmUgQ29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3Qx +QzBBBgNVBAMMOk1hdHJpeFNTTCBTYW1wbGUgRUNESF9SU0EgQ2VydCAoRWxsaXB0 +aWMgY3VydmUgcHJpbWUyNTZ2MSkwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASX +Po/C2aeqtJ4s5DHVl/SuPW6K76OlJ8LmM1dsoPW44sePdbqNBIv+3TorJHRS7nLi +jivaZ37W666IbstWQ5O9o4IBMTCCAS0wCQYDVR0TBAIwADAdBgNVHQ4EFgQUIj7i +gcqhR0cEqf3bG68jZvWNwvowgcUGA1UdIwSBvTCBuqGBsKSBrTCBqjFJMEcGA1UE +AwxAU2FtcGxlIE1hdHJpeCBSU0EtMTAyNCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkg +Zm9yIEVDREhfUlNBIFN1aXRlczELMAkGA1UEBgwCVVMxCzAJBgNVBAgMAldBMRAw +DgYDVQQHDAdTZWF0dGxlMSIwIAYDVQQKDBlJbnNpZGUgU2VjdXJlIENvcnBvcmF0 +aW9uMQ0wCwYDVQQLDARUZXN0ggUxMDAwMDAdBgNVHSUEFjAUBggrBgEFBQcDAQYI +KwYBBQUHAwIwGgYDVR0RBBMwEYIJbG9jYWxob3N0hwR/AAABMA0GCSqGSIb3DQEB +CwUAA4GBAA0wDNAG8JzjG3SgiAIUYFQXgophjPbIm/wlobkh/DiQ3oi90CR/CmiM +4HjnZUlkhxOB9ysht78BbcqGdtTPC65NbCd4K7Va4jZMhhPJZZwKrTpLG92d0+6T +L7kuuC884nAYdfalSI88YitJE1Ay1hzg66KU8aANiNsbJgT9JxVZ +-----END CERTIFICATE----- diff --git a/testkeys/ECDH_RSA/256_ECDH-RSA_KEY.h b/testkeys/ECDH_RSA/256_ECDH-RSA_KEY.h new file mode 100644 index 0000000..db9d0e7 --- /dev/null +++ b/testkeys/ECDH_RSA/256_ECDH-RSA_KEY.h @@ -0,0 +1,17 @@ +/** + * @file 256_ECDH-RSA_KEY.h + * @version $Format:%h%d$ + * + * Summary. + */ +unsigned char ECDHRSA256KEY[] = { +48, 119, 2, 1, 1, 4, 32, 220, 150, 150, 73, 80, 21, +37, 147, 194, 63, 165, 6, 0, 237, 106, 81, 191, 114, 146, +139, 229, 196, 115, 139, 102, 209, 92, 21, 103, 122, 149, 120, +160, 10, 6, 8, 42, 134, 72, 206, 61, 3, 1, 7, 161, +68, 3, 66, 0, 4, 151, 62, 143, 194, 217, 167, 170, 180, +158, 44, 228, 49, 213, 151, 244, 174, 61, 110, 138, 239, 163, +165, 39, 194, 230, 51, 87, 108, 160, 245, 184, 226, 199, 143, +117, 186, 141, 4, 139, 254, 221, 58, 43, 36, 116, 82, 238, +114, 226, 142, 43, 218, 103, 126, 214, 235, 174, 136, 110, 203, +86, 67, 147, 189}; diff --git a/testkeys/ECDH_RSA/256_ECDH-RSA_KEY.pem b/testkeys/ECDH_RSA/256_ECDH-RSA_KEY.pem new file mode 100644 index 0000000..40dcc06 --- /dev/null +++ b/testkeys/ECDH_RSA/256_ECDH-RSA_KEY.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEINyWlklQFSWTwj+lBgDtalG/cpKL5cRzi2bRXBVnepV4oAoGCCqGSM49 +AwEHoUQDQgAElz6PwtmnqrSeLOQx1Zf0rj1uiu+jpSfC5jNXbKD1uOLHj3W6jQSL +/t06KyR0Uu5y4o4r2md+1uuuiG7LVkOTvQ== +-----END EC PRIVATE KEY----- diff --git a/testkeys/ECDH_RSA/521_ECDH-RSA.h b/testkeys/ECDH_RSA/521_ECDH-RSA.h new file mode 100644 index 0000000..d6632f2 --- /dev/null +++ b/testkeys/ECDH_RSA/521_ECDH-RSA.h @@ -0,0 +1,96 @@ +/** + * @file 521_ECDH-RSA.h + * @version $Format:%h%d$ + * + * Summary. + */ +unsigned char ECDHRSA521[] = { +48, 130, 4, 118, 48, 130, 3, 94, 160, 3, 2, 1, 2, +2, 2, 50, 200, 48, 13, 6, 9, 42, 134, 72, 134, 247, +13, 1, 1, 11, 5, 0, 48, 129, 170, 49, 73, 48, 71, +6, 3, 85, 4, 3, 12, 64, 83, 97, 109, 112, 108, 101, +32, 77, 97, 116, 114, 105, 120, 32, 82, 83, 65, 45, 50, +48, 52, 56, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, +116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, +102, 111, 114, 32, 69, 67, 68, 72, 95, 82, 83, 65, 32, +115, 117, 105, 116, 101, 115, 49, 11, 48, 9, 6, 3, 85, +4, 6, 12, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, +4, 8, 12, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, +4, 7, 12, 7, 83, 101, 97, 116, 116, 108, 101, 49, 34, +48, 32, 6, 3, 85, 4, 10, 12, 25, 73, 110, 115, 105, +100, 101, 32, 83, 101, 99, 117, 114, 101, 32, 67, 111, 114, +112, 111, 114, 97, 116, 105, 111, 110, 49, 13, 48, 11, 6, +3, 85, 4, 11, 12, 4, 84, 101, 115, 116, 48, 30, 23, +13, 49, 52, 48, 51, 49, 51, 50, 51, 51, 56, 53, 57, +90, 23, 13, 49, 55, 48, 51, 49, 50, 50, 51, 51, 56, +53, 57, 90, 48, 129, 163, 49, 11, 48, 9, 6, 3, 85, +4, 6, 19, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, +4, 8, 12, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, +4, 7, 12, 7, 83, 101, 97, 116, 116, 108, 101, 49, 34, +48, 32, 6, 3, 85, 4, 10, 12, 25, 73, 110, 115, 105, +100, 101, 32, 83, 101, 99, 117, 114, 101, 32, 67, 111, 114, +112, 111, 114, 97, 116, 105, 111, 110, 49, 13, 48, 11, 6, +3, 85, 4, 11, 12, 4, 84, 101, 115, 116, 49, 66, 48, +64, 6, 3, 85, 4, 3, 12, 57, 77, 97, 116, 114, 105, +120, 83, 83, 76, 32, 83, 97, 109, 112, 108, 101, 32, 69, +67, 68, 72, 95, 82, 83, 65, 32, 67, 101, 114, 116, 32, +40, 69, 108, 108, 105, 112, 116, 105, 99, 32, 99, 117, 114, +118, 101, 32, 115, 101, 99, 112, 53, 50, 49, 114, 49, 41, +48, 129, 155, 48, 16, 6, 7, 42, 134, 72, 206, 61, 2, +1, 6, 5, 43, 129, 4, 0, 35, 3, 129, 134, 0, 4, +0, 49, 27, 198, 186, 141, 142, 7, 108, 83, 30, 218, 91, +85, 229, 245, 125, 112, 242, 232, 237, 198, 157, 31, 31, 11, +216, 151, 244, 158, 244, 187, 107, 16, 187, 15, 26, 233, 26, +16, 96, 109, 202, 12, 220, 203, 245, 34, 180, 155, 185, 243, +150, 60, 162, 158, 98, 248, 102, 52, 243, 181, 195, 23, 115, +117, 1, 6, 229, 46, 242, 242, 164, 81, 22, 19, 150, 54, +220, 137, 217, 53, 193, 85, 81, 167, 167, 233, 5, 197, 98, +75, 2, 155, 225, 103, 232, 229, 58, 151, 188, 27, 83, 179, +191, 57, 88, 134, 117, 151, 255, 253, 91, 112, 242, 75, 97, +114, 118, 223, 164, 219, 5, 129, 183, 162, 210, 156, 243, 195, +110, 136, 163, 130, 1, 49, 48, 130, 1, 45, 48, 9, 6, +3, 85, 29, 19, 4, 2, 48, 0, 48, 29, 6, 3, 85, +29, 14, 4, 22, 4, 20, 219, 236, 141, 150, 59, 25, 34, +120, 254, 102, 173, 32, 113, 3, 247, 79, 133, 237, 198, 162, +48, 129, 197, 6, 3, 85, 29, 35, 4, 129, 189, 48, 129, +186, 161, 129, 176, 164, 129, 173, 48, 129, 170, 49, 73, 48, +71, 6, 3, 85, 4, 3, 12, 64, 83, 97, 109, 112, 108, +101, 32, 77, 97, 116, 114, 105, 120, 32, 82, 83, 65, 45, +50, 48, 52, 56, 32, 67, 101, 114, 116, 105, 102, 105, 99, +97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, +32, 102, 111, 114, 32, 69, 67, 68, 72, 95, 82, 83, 65, +32, 115, 117, 105, 116, 101, 115, 49, 11, 48, 9, 6, 3, +85, 4, 6, 12, 2, 85, 83, 49, 11, 48, 9, 6, 3, +85, 4, 8, 12, 2, 87, 65, 49, 16, 48, 14, 6, 3, +85, 4, 7, 12, 7, 83, 101, 97, 116, 116, 108, 101, 49, +34, 48, 32, 6, 3, 85, 4, 10, 12, 25, 73, 110, 115, +105, 100, 101, 32, 83, 101, 99, 117, 114, 101, 32, 67, 111, +114, 112, 111, 114, 97, 116, 105, 111, 110, 49, 13, 48, 11, +6, 3, 85, 4, 11, 12, 4, 84, 101, 115, 116, 130, 5, +49, 49, 48, 48, 48, 48, 29, 6, 3, 85, 29, 37, 4, +22, 48, 20, 6, 8, 43, 6, 1, 5, 5, 7, 3, 1, +6, 8, 43, 6, 1, 5, 5, 7, 3, 2, 48, 26, 6, +3, 85, 29, 17, 4, 19, 48, 17, 130, 9, 108, 111, 99, +97, 108, 104, 111, 115, 116, 135, 4, 127, 0, 0, 1, 48, +13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, +0, 3, 130, 1, 1, 0, 3, 203, 82, 167, 137, 226, 139, +225, 2, 127, 209, 52, 63, 218, 84, 141, 182, 161, 42, 16, +125, 63, 189, 57, 100, 245, 175, 148, 127, 1, 231, 178, 179, +139, 75, 181, 55, 124, 36, 105, 226, 38, 202, 199, 58, 72, +32, 106, 80, 112, 157, 27, 111, 10, 110, 107, 40, 121, 59, +57, 148, 138, 176, 146, 68, 250, 113, 65, 117, 84, 248, 5, +99, 106, 161, 250, 24, 62, 52, 108, 246, 42, 152, 216, 55, +186, 125, 70, 21, 58, 43, 252, 177, 3, 239, 81, 133, 213, +141, 134, 208, 91, 97, 117, 65, 31, 78, 88, 249, 50, 189, +89, 87, 177, 186, 38, 55, 153, 138, 54, 171, 113, 44, 87, +135, 108, 247, 24, 75, 141, 39, 206, 168, 34, 45, 54, 172, +143, 172, 150, 9, 235, 199, 134, 159, 211, 164, 202, 6, 130, +191, 231, 151, 199, 123, 175, 175, 203, 21, 154, 127, 244, 219, +83, 216, 0, 80, 154, 121, 8, 149, 145, 73, 74, 62, 171, +222, 217, 49, 211, 95, 118, 254, 86, 20, 224, 141, 8, 9, +209, 84, 55, 32, 78, 9, 193, 107, 253, 58, 141, 137, 184, +53, 85, 27, 21, 149, 175, 40, 243, 16, 87, 143, 24, 138, +237, 215, 232, 52, 197, 180, 99, 255, 192, 171, 47, 212, 129, +226, 163, 64, 144, 14, 221, 249, 65, 121, 118, 117, 143, 100, +20, 6, 42, 241, 73, 99, 19, 173, 174, 208, 233, 27, 253, +16, 243}; diff --git a/testkeys/ECDH_RSA/521_ECDH-RSA.pem b/testkeys/ECDH_RSA/521_ECDH-RSA.pem new file mode 100644 index 0000000..ea85305 --- /dev/null +++ b/testkeys/ECDH_RSA/521_ECDH-RSA.pem @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEdjCCA16gAwIBAgICMsgwDQYJKoZIhvcNAQELBQAwgaoxSTBHBgNVBAMMQFNh +bXBsZSBNYXRyaXggUlNBLTIwNDggQ2VydGlmaWNhdGUgQXV0aG9yaXR5IGZvciBF +Q0RIX1JTQSBzdWl0ZXMxCzAJBgNVBAYMAlVTMQswCQYDVQQIDAJXQTEQMA4GA1UE +BwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNlY3VyZSBDb3Jwb3JhdGlvbjEN +MAsGA1UECwwEVGVzdDAeFw0xNDAzMTMyMzM4NTlaFw0xNzAzMTIyMzM4NTlaMIGj +MQswCQYDVQQGEwJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAg +BgNVBAoMGUluc2lkZSBTZWN1cmUgQ29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3Qx +QjBABgNVBAMMOU1hdHJpeFNTTCBTYW1wbGUgRUNESF9SU0EgQ2VydCAoRWxsaXB0 +aWMgY3VydmUgc2VjcDUyMXIxKTCBmzAQBgcqhkjOPQIBBgUrgQQAIwOBhgAEADEb +xrqNjgdsUx7aW1Xl9X1w8ujtxp0fHwvYl/Se9LtrELsPGukaEGBtygzcy/UitJu5 +85Y8op5i+GY087XDF3N1AQblLvLypFEWE5Y23InZNcFVUaen6QXFYksCm+Fn6OU6 +l7wbU7O/OViGdZf//Vtw8kthcnbfpNsFgbei0pzzw26Io4IBMTCCAS0wCQYDVR0T +BAIwADAdBgNVHQ4EFgQU2+yNljsZInj+Zq0gcQP3T4XtxqIwgcUGA1UdIwSBvTCB +uqGBsKSBrTCBqjFJMEcGA1UEAwxAU2FtcGxlIE1hdHJpeCBSU0EtMjA0OCBDZXJ0 +aWZpY2F0ZSBBdXRob3JpdHkgZm9yIEVDREhfUlNBIHN1aXRlczELMAkGA1UEBgwC +VVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMSIwIAYDVQQKDBlJbnNp +ZGUgU2VjdXJlIENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0ggUxMTAwMDAdBgNV +HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGgYDVR0RBBMwEYIJbG9jYWxob3N0 +hwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBAQADy1KnieKL4QJ/0TQ/2lSNtqEqEH0/ +vTlk9a+UfwHnsrOLS7U3fCRp4ibKxzpIIGpQcJ0bbwpuayh5OzmUirCSRPpxQXVU ++AVjaqH6GD40bPYqmNg3un1GFTor/LED71GF1Y2G0FthdUEfTlj5Mr1ZV7G6JjeZ +ijarcSxXh2z3GEuNJ86oIi02rI+slgnrx4af06TKBoK/55fHe6+vyxWaf/TbU9gA +UJp5CJWRSUo+q97ZMdNfdv5WFOCNCAnRVDcgTgnBa/06jYm4NVUbFZWvKPMQV48Y +iu3X6DTFtGP/wKsv1IHio0CQDt35QXl2dY9kFAYq8UljE62u0Okb/RDz +-----END CERTIFICATE----- diff --git a/testkeys/ECDH_RSA/521_ECDH-RSA_KEY.h b/testkeys/ECDH_RSA/521_ECDH-RSA_KEY.h new file mode 100644 index 0000000..ae713b2 --- /dev/null +++ b/testkeys/ECDH_RSA/521_ECDH-RSA_KEY.h @@ -0,0 +1,25 @@ +/** + * @file 521_ECDH-RSA_KEY.h + * @version $Format:%h%d$ + * + * Summary. + */ +unsigned char ECDHRSA521KEY[] = { +48, 129, 219, 2, 1, 1, 4, 65, 107, 194, 80, 213, 12, +72, 105, 38, 223, 124, 205, 235, 27, 233, 4, 234, 49, 223, +57, 51, 220, 150, 253, 177, 7, 251, 223, 113, 241, 138, 171, +98, 101, 197, 138, 177, 201, 9, 128, 60, 62, 9, 239, 184, +91, 68, 42, 236, 151, 107, 50, 126, 249, 99, 140, 100, 2, +69, 75, 104, 233, 152, 98, 149, 46, 160, 7, 6, 5, 43, +129, 4, 0, 35, 161, 129, 137, 3, 129, 134, 0, 4, 0, +49, 27, 198, 186, 141, 142, 7, 108, 83, 30, 218, 91, 85, +229, 245, 125, 112, 242, 232, 237, 198, 157, 31, 31, 11, 216, +151, 244, 158, 244, 187, 107, 16, 187, 15, 26, 233, 26, 16, +96, 109, 202, 12, 220, 203, 245, 34, 180, 155, 185, 243, 150, +60, 162, 158, 98, 248, 102, 52, 243, 181, 195, 23, 115, 117, +1, 6, 229, 46, 242, 242, 164, 81, 22, 19, 150, 54, 220, +137, 217, 53, 193, 85, 81, 167, 167, 233, 5, 197, 98, 75, +2, 155, 225, 103, 232, 229, 58, 151, 188, 27, 83, 179, 191, +57, 88, 134, 117, 151, 255, 253, 91, 112, 242, 75, 97, 114, +118, 223, 164, 219, 5, 129, 183, 162, 210, 156, 243, 195, 110, +136}; diff --git a/testkeys/ECDH_RSA/521_ECDH-RSA_KEY.pem b/testkeys/ECDH_RSA/521_ECDH-RSA_KEY.pem new file mode 100644 index 0000000..541214e --- /dev/null +++ b/testkeys/ECDH_RSA/521_ECDH-RSA_KEY.pem @@ -0,0 +1,10 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQAIw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MIHbAgEBBEFrwlDVDEhpJt98zesb6QTqMd85M9yW/bEH+99x8YqrYmXFirHJCYA8 +PgnvuFtEKuyXazJ++WOMZAJFS2jpmGKVLqAHBgUrgQQAI6GBiQOBhgAEADEbxrqN +jgdsUx7aW1Xl9X1w8ujtxp0fHwvYl/Se9LtrELsPGukaEGBtygzcy/UitJu585Y8 +op5i+GY087XDF3N1AQblLvLypFEWE5Y23InZNcFVUaen6QXFYksCm+Fn6OU6l7wb +U7O/OViGdZf//Vtw8kthcnbfpNsFgbei0pzzw26I +-----END EC PRIVATE KEY----- diff --git a/testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS.h b/testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS.h new file mode 100644 index 0000000..938fe96 --- /dev/null +++ b/testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS.h @@ -0,0 +1,145 @@ +/** + * @file ALL_ECDH-RSA_CAS.h + * @version $Format:%h%d$ + * + * Summary. + */ +unsigned char ECDHRSACAS[] = { +48, 130, 2, 246, 48, 130, 2, 95, 160, 3, 2, 1, 2, +2, 5, 49, 48, 48, 48, 48, 48, 13, 6, 9, 42, 134, +72, 134, 247, 13, 1, 1, 11, 5, 0, 48, 129, 170, 49, +73, 48, 71, 6, 3, 85, 4, 3, 12, 64, 83, 97, 109, +112, 108, 101, 32, 77, 97, 116, 114, 105, 120, 32, 82, 83, +65, 45, 49, 48, 50, 52, 32, 67, 101, 114, 116, 105, 102, +105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, +116, 121, 32, 102, 111, 114, 32, 69, 67, 68, 72, 95, 82, +83, 65, 32, 83, 117, 105, 116, 101, 115, 49, 11, 48, 9, +6, 3, 85, 4, 6, 12, 2, 85, 83, 49, 11, 48, 9, +6, 3, 85, 4, 8, 12, 2, 87, 65, 49, 16, 48, 14, +6, 3, 85, 4, 7, 12, 7, 83, 101, 97, 116, 116, 108, +101, 49, 34, 48, 32, 6, 3, 85, 4, 10, 12, 25, 73, +110, 115, 105, 100, 101, 32, 83, 101, 99, 117, 114, 101, 32, +67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, 49, 13, +48, 11, 6, 3, 85, 4, 11, 12, 4, 84, 101, 115, 116, +48, 30, 23, 13, 49, 52, 48, 51, 49, 51, 50, 51, 51, +54, 53, 54, 90, 23, 13, 49, 55, 48, 51, 49, 50, 50, +51, 51, 54, 53, 54, 90, 48, 129, 170, 49, 73, 48, 71, +6, 3, 85, 4, 3, 12, 64, 83, 97, 109, 112, 108, 101, +32, 77, 97, 116, 114, 105, 120, 32, 82, 83, 65, 45, 49, +48, 50, 52, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, +116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, +102, 111, 114, 32, 69, 67, 68, 72, 95, 82, 83, 65, 32, +83, 117, 105, 116, 101, 115, 49, 11, 48, 9, 6, 3, 85, +4, 6, 12, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, +4, 8, 12, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, +4, 7, 12, 7, 83, 101, 97, 116, 116, 108, 101, 49, 34, +48, 32, 6, 3, 85, 4, 10, 12, 25, 73, 110, 115, 105, +100, 101, 32, 83, 101, 99, 117, 114, 101, 32, 67, 111, 114, +112, 111, 114, 97, 116, 105, 111, 110, 49, 13, 48, 11, 6, +3, 85, 4, 11, 12, 4, 84, 101, 115, 116, 48, 129, 159, +48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, +5, 0, 3, 129, 141, 0, 48, 129, 137, 2, 129, 129, 0, +249, 12, 249, 57, 4, 33, 129, 113, 73, 137, 92, 145, 48, +230, 252, 126, 227, 81, 196, 219, 148, 230, 67, 133, 231, 42, +102, 25, 240, 192, 55, 183, 136, 13, 143, 151, 108, 28, 86, +77, 110, 206, 25, 142, 89, 70, 170, 192, 197, 41, 10, 185, +161, 19, 44, 131, 88, 108, 134, 178, 142, 94, 44, 69, 245, +181, 4, 122, 120, 206, 110, 30, 102, 245, 103, 159, 132, 160, +197, 180, 211, 197, 14, 195, 38, 39, 210, 222, 23, 100, 46, +66, 22, 150, 192, 138, 90, 169, 219, 16, 248, 170, 222, 169, +110, 26, 91, 104, 84, 216, 245, 164, 67, 252, 208, 65, 155, +212, 253, 147, 76, 87, 55, 79, 35, 160, 34, 109, 2, 3, +1, 0, 1, 163, 38, 48, 36, 48, 18, 6, 3, 85, 29, +19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, 2, 1, +0, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, +3, 2, 0, 4, 48, 13, 6, 9, 42, 134, 72, 134, 247, +13, 1, 1, 11, 5, 0, 3, 129, 129, 0, 214, 26, 73, +141, 164, 26, 253, 194, 208, 235, 145, 156, 237, 3, 48, 79, +188, 232, 59, 63, 158, 247, 78, 114, 147, 125, 230, 50, 201, +223, 117, 247, 72, 16, 89, 150, 11, 141, 199, 146, 9, 176, +148, 243, 155, 78, 244, 11, 192, 80, 98, 75, 191, 131, 163, +208, 37, 109, 206, 136, 37, 165, 62, 122, 24, 74, 210, 200, +119, 70, 113, 220, 51, 62, 203, 53, 81, 184, 228, 72, 22, +183, 67, 81, 174, 92, 56, 23, 67, 4, 13, 109, 72, 133, +99, 207, 36, 252, 3, 82, 6, 194, 140, 133, 147, 123, 56, +133, 128, 215, 148, 114, 56, 121, 135, 224, 16, 244, 68, 205, +38, 208, 186, 102, 138, 189, 44, 249, +48, 130, 3, 251, 48, 130, 2, 227, 160, 3, 2, 1, 2, +2, 5, 49, 49, 48, 48, 48, 48, 13, 6, 9, 42, 134, +72, 134, 247, 13, 1, 1, 11, 5, 0, 48, 129, 170, 49, +73, 48, 71, 6, 3, 85, 4, 3, 12, 64, 83, 97, 109, +112, 108, 101, 32, 77, 97, 116, 114, 105, 120, 32, 82, 83, +65, 45, 50, 48, 52, 56, 32, 67, 101, 114, 116, 105, 102, +105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, +116, 121, 32, 102, 111, 114, 32, 69, 67, 68, 72, 95, 82, +83, 65, 32, 115, 117, 105, 116, 101, 115, 49, 11, 48, 9, +6, 3, 85, 4, 6, 12, 2, 85, 83, 49, 11, 48, 9, +6, 3, 85, 4, 8, 12, 2, 87, 65, 49, 16, 48, 14, +6, 3, 85, 4, 7, 12, 7, 83, 101, 97, 116, 116, 108, +101, 49, 34, 48, 32, 6, 3, 85, 4, 10, 12, 25, 73, +110, 115, 105, 100, 101, 32, 83, 101, 99, 117, 114, 101, 32, +67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, 49, 13, +48, 11, 6, 3, 85, 4, 11, 12, 4, 84, 101, 115, 116, +48, 30, 23, 13, 49, 52, 48, 51, 49, 51, 50, 51, 51, +55, 49, 54, 90, 23, 13, 49, 55, 48, 51, 49, 50, 50, +51, 51, 55, 49, 54, 90, 48, 129, 170, 49, 73, 48, 71, +6, 3, 85, 4, 3, 12, 64, 83, 97, 109, 112, 108, 101, +32, 77, 97, 116, 114, 105, 120, 32, 82, 83, 65, 45, 50, +48, 52, 56, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, +116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, +102, 111, 114, 32, 69, 67, 68, 72, 95, 82, 83, 65, 32, +115, 117, 105, 116, 101, 115, 49, 11, 48, 9, 6, 3, 85, +4, 6, 12, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, +4, 8, 12, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, +4, 7, 12, 7, 83, 101, 97, 116, 116, 108, 101, 49, 34, +48, 32, 6, 3, 85, 4, 10, 12, 25, 73, 110, 115, 105, +100, 101, 32, 83, 101, 99, 117, 114, 101, 32, 67, 111, 114, +112, 111, 114, 97, 116, 105, 111, 110, 49, 13, 48, 11, 6, +3, 85, 4, 11, 12, 4, 84, 101, 115, 116, 48, 130, 1, +34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, +1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, +130, 1, 1, 0, 183, 154, 29, 250, 115, 103, 178, 210, 143, +131, 146, 83, 240, 184, 185, 156, 118, 11, 230, 53, 35, 91, +60, 204, 239, 28, 32, 115, 251, 87, 32, 180, 82, 138, 12, +240, 132, 176, 46, 245, 91, 56, 130, 133, 121, 211, 43, 45, +103, 251, 59, 185, 126, 18, 93, 76, 93, 27, 90, 182, 220, +194, 50, 217, 43, 61, 125, 113, 12, 139, 59, 249, 245, 11, +136, 247, 176, 17, 105, 249, 86, 109, 230, 87, 210, 40, 62, +1, 201, 80, 94, 193, 65, 22, 234, 58, 162, 147, 235, 120, +253, 122, 110, 90, 160, 21, 25, 159, 216, 149, 13, 111, 125, +135, 141, 42, 207, 107, 197, 234, 75, 72, 101, 55, 242, 186, +6, 59, 33, 78, 153, 6, 121, 115, 121, 145, 206, 148, 52, +242, 104, 222, 104, 57, 17, 190, 190, 219, 255, 27, 92, 34, +162, 200, 85, 3, 117, 34, 80, 109, 224, 100, 207, 224, 34, +134, 173, 123, 35, 7, 156, 41, 0, 237, 132, 241, 199, 154, +15, 20, 66, 212, 157, 75, 191, 59, 165, 94, 121, 66, 26, +79, 217, 14, 253, 173, 215, 228, 122, 86, 133, 176, 108, 117, +222, 161, 244, 207, 214, 107, 225, 100, 123, 87, 242, 191, 195, +92, 196, 110, 32, 0, 176, 102, 133, 138, 231, 173, 68, 23, +207, 111, 199, 232, 1, 167, 124, 69, 176, 6, 248, 206, 9, +142, 149, 89, 63, 4, 252, 146, 174, 49, 161, 205, 92, 211, +2, 3, 1, 0, 1, 163, 38, 48, 36, 48, 18, 6, 3, +85, 29, 19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, +2, 1, 0, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, +4, 4, 3, 2, 0, 4, 48, 13, 6, 9, 42, 134, 72, +134, 247, 13, 1, 1, 11, 5, 0, 3, 130, 1, 1, 0, +166, 239, 77, 200, 194, 203, 224, 78, 200, 212, 60, 11, 97, +94, 115, 135, 129, 86, 211, 109, 9, 162, 188, 157, 209, 172, +186, 1, 130, 166, 90, 243, 6, 251, 55, 6, 9, 207, 218, +110, 98, 4, 56, 64, 72, 202, 193, 111, 14, 34, 65, 200, +222, 162, 31, 5, 202, 101, 19, 20, 215, 91, 170, 128, 246, +255, 10, 230, 190, 71, 202, 85, 41, 12, 240, 200, 52, 141, +219, 105, 110, 1, 232, 157, 185, 200, 85, 134, 152, 39, 76, +146, 202, 248, 184, 197, 223, 155, 202, 157, 9, 192, 89, 200, +34, 205, 178, 0, 242, 10, 160, 143, 227, 246, 229, 126, 150, +170, 199, 174, 162, 225, 123, 238, 133, 185, 96, 31, 177, 41, +220, 66, 109, 202, 216, 184, 230, 132, 111, 98, 188, 122, 131, +229, 123, 184, 171, 162, 213, 61, 95, 245, 215, 0, 16, 220, +128, 174, 62, 68, 20, 39, 94, 142, 138, 77, 65, 244, 159, +214, 35, 139, 126, 198, 210, 141, 60, 142, 235, 100, 116, 130, +118, 111, 123, 13, 10, 159, 39, 206, 215, 76, 157, 226, 106, +20, 198, 254, 226, 206, 154, 30, 231, 69, 81, 148, 71, 17, +120, 219, 233, 190, 193, 74, 196, 226, 43, 98, 160, 173, 184, +31, 65, 227, 93, 118, 156, 56, 209, 143, 115, 169, 53, 169, +111, 183, 132, 165, 150, 206, 223, 183, 29, 25, 105, 183, 64, +197, 214, 243, 184, 176, 77, 28, 153, 158}; diff --git a/testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS.pem b/testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS.pem new file mode 100644 index 0000000..0fc4eda --- /dev/null +++ b/testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS.pem @@ -0,0 +1,42 @@ +-----BEGIN CERTIFICATE----- +MIIC9jCCAl+gAwIBAgIFMTAwMDAwDQYJKoZIhvcNAQELBQAwgaoxSTBHBgNVBAMM +QFNhbXBsZSBNYXRyaXggUlNBLTEwMjQgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IGZv +ciBFQ0RIX1JTQSBTdWl0ZXMxCzAJBgNVBAYMAlVTMQswCQYDVQQIDAJXQTEQMA4G +A1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNlY3VyZSBDb3Jwb3JhdGlv +bjENMAsGA1UECwwEVGVzdDAeFw0xNDAzMTMyMzM2NTZaFw0xNzAzMTIyMzM2NTZa +MIGqMUkwRwYDVQQDDEBTYW1wbGUgTWF0cml4IFJTQS0xMDI0IENlcnRpZmljYXRl +IEF1dGhvcml0eSBmb3IgRUNESF9SU0EgU3VpdGVzMQswCQYDVQQGDAJVUzELMAkG +A1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1 +cmUgQ29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QwgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBAPkM+TkEIYFxSYlckTDm/H7jUcTblOZDhecqZhnwwDe3iA2Pl2wc +Vk1uzhmOWUaqwMUpCrmhEyyDWGyGso5eLEX1tQR6eM5uHmb1Z5+EoMW008UOwyYn +0t4XZC5CFpbAilqp2xD4qt6pbhpbaFTY9aRD/NBBm9T9k0xXN08joCJtAgMBAAGj +JjAkMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgAEMA0GCSqGSIb3 +DQEBCwUAA4GBANYaSY2kGv3C0OuRnO0DME+86Ds/nvdOcpN95jLJ33X3SBBZlguN +x5IJsJTzm070C8BQYku/g6PQJW3OiCWlPnoYStLId0Zx3DM+yzVRuORIFrdDUa5c +OBdDBA1tSIVjzyT8A1IGwoyFk3s4hYDXlHI4eYfgEPREzSbQumaKvSz5 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID+zCCAuOgAwIBAgIFMTEwMDAwDQYJKoZIhvcNAQELBQAwgaoxSTBHBgNVBAMM +QFNhbXBsZSBNYXRyaXggUlNBLTIwNDggQ2VydGlmaWNhdGUgQXV0aG9yaXR5IGZv +ciBFQ0RIX1JTQSBzdWl0ZXMxCzAJBgNVBAYMAlVTMQswCQYDVQQIDAJXQTEQMA4G +A1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNlY3VyZSBDb3Jwb3JhdGlv +bjENMAsGA1UECwwEVGVzdDAeFw0xNDAzMTMyMzM3MTZaFw0xNzAzMTIyMzM3MTZa +MIGqMUkwRwYDVQQDDEBTYW1wbGUgTWF0cml4IFJTQS0yMDQ4IENlcnRpZmljYXRl +IEF1dGhvcml0eSBmb3IgRUNESF9SU0Egc3VpdGVzMQswCQYDVQQGDAJVUzELMAkG +A1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1 +cmUgQ29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQC3mh36c2ey0o+DklPwuLmcdgvmNSNbPMzvHCBz+1cgtFKK +DPCEsC71WziChXnTKy1n+zu5fhJdTF0bWrbcwjLZKz19cQyLO/n1C4j3sBFp+VZt +5lfSKD4ByVBewUEW6jqik+t4/XpuWqAVGZ/YlQ1vfYeNKs9rxepLSGU38roGOyFO +mQZ5c3mRzpQ08mjeaDkRvr7b/xtcIqLIVQN1IlBt4GTP4CKGrXsjB5wpAO2E8cea +DxRC1J1LvzulXnlCGk/ZDv2t1+R6VoWwbHXeofTP1mvhZHtX8r/DXMRuIACwZoWK +561EF89vx+gBp3xFsAb4zgmOlVk/BPySrjGhzVzTAgMBAAGjJjAkMBIGA1UdEwEB +/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgAEMA0GCSqGSIb3DQEBCwUAA4IBAQCm +703IwsvgTsjUPAthXnOHgVbTbQmivJ3RrLoBgqZa8wb7NwYJz9puYgQ4QEjKwW8O +IkHI3qIfBcplExTXW6qA9v8K5r5HylUpDPDINI3baW4B6J25yFWGmCdMksr4uMXf +m8qdCcBZyCLNsgDyCqCP4/blfpaqx66i4XvuhblgH7Ep3EJtyti45oRvYrx6g+V7 +uKui1T1f9dcAENyArj5EFCdejopNQfSf1iOLfsbSjTyO62R0gnZvew0KnyfO10yd +4moUxv7izpoe50VRlEcReNvpvsFKxOIrYqCtuB9B4112nDjRj3OpNalvt4Slls7f +tx0ZabdAxdbzuLBNHJme +-----END CERTIFICATE----- diff --git a/testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS_EXCEPT_1024.h b/testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS_EXCEPT_1024.h new file mode 100644 index 0000000..0d63b0c --- /dev/null +++ b/testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS_EXCEPT_1024.h @@ -0,0 +1,88 @@ +const static unsigned char ECDHRSACAS[] = { + 0x30, 0x82, 0x03, 0xfb, 0x30, 0x82, 0x02, 0xe3, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x05, 0x31, 0x31, 0x30, 0x30, 0x30, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, + 0x81, 0xaa, 0x31, 0x49, 0x30, 0x47, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x40, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x4d, 0x61, 0x74, 0x72, + 0x69, 0x78, 0x20, 0x52, 0x53, 0x41, 0x2d, 0x32, 0x30, 0x34, 0x38, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x45, 0x43, 0x44, 0x48, 0x5f, 0x52, 0x53, 0x41, 0x20, 0x73, + 0x75, 0x69, 0x74, 0x65, 0x73, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x0c, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, + 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, + 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, + 0x54, 0x65, 0x73, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, + 0x31, 0x33, 0x32, 0x33, 0x33, 0x37, 0x31, 0x36, 0x5a, 0x17, 0x0d, 0x31, + 0x37, 0x30, 0x33, 0x31, 0x32, 0x32, 0x33, 0x33, 0x37, 0x31, 0x36, 0x5a, + 0x30, 0x81, 0xaa, 0x31, 0x49, 0x30, 0x47, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x40, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x4d, 0x61, 0x74, + 0x72, 0x69, 0x78, 0x20, 0x52, 0x53, 0x41, 0x2d, 0x32, 0x30, 0x34, 0x38, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x45, 0x43, 0x44, 0x48, 0x5f, 0x52, 0x53, 0x41, 0x20, + 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x0c, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, + 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, + 0x19, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, + 0x04, 0x54, 0x65, 0x73, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xb7, 0x9a, 0x1d, 0xfa, 0x73, 0x67, 0xb2, 0xd2, 0x8f, 0x83, + 0x92, 0x53, 0xf0, 0xb8, 0xb9, 0x9c, 0x76, 0x0b, 0xe6, 0x35, 0x23, 0x5b, + 0x3c, 0xcc, 0xef, 0x1c, 0x20, 0x73, 0xfb, 0x57, 0x20, 0xb4, 0x52, 0x8a, + 0x0c, 0xf0, 0x84, 0xb0, 0x2e, 0xf5, 0x5b, 0x38, 0x82, 0x85, 0x79, 0xd3, + 0x2b, 0x2d, 0x67, 0xfb, 0x3b, 0xb9, 0x7e, 0x12, 0x5d, 0x4c, 0x5d, 0x1b, + 0x5a, 0xb6, 0xdc, 0xc2, 0x32, 0xd9, 0x2b, 0x3d, 0x7d, 0x71, 0x0c, 0x8b, + 0x3b, 0xf9, 0xf5, 0x0b, 0x88, 0xf7, 0xb0, 0x11, 0x69, 0xf9, 0x56, 0x6d, + 0xe6, 0x57, 0xd2, 0x28, 0x3e, 0x01, 0xc9, 0x50, 0x5e, 0xc1, 0x41, 0x16, + 0xea, 0x3a, 0xa2, 0x93, 0xeb, 0x78, 0xfd, 0x7a, 0x6e, 0x5a, 0xa0, 0x15, + 0x19, 0x9f, 0xd8, 0x95, 0x0d, 0x6f, 0x7d, 0x87, 0x8d, 0x2a, 0xcf, 0x6b, + 0xc5, 0xea, 0x4b, 0x48, 0x65, 0x37, 0xf2, 0xba, 0x06, 0x3b, 0x21, 0x4e, + 0x99, 0x06, 0x79, 0x73, 0x79, 0x91, 0xce, 0x94, 0x34, 0xf2, 0x68, 0xde, + 0x68, 0x39, 0x11, 0xbe, 0xbe, 0xdb, 0xff, 0x1b, 0x5c, 0x22, 0xa2, 0xc8, + 0x55, 0x03, 0x75, 0x22, 0x50, 0x6d, 0xe0, 0x64, 0xcf, 0xe0, 0x22, 0x86, + 0xad, 0x7b, 0x23, 0x07, 0x9c, 0x29, 0x00, 0xed, 0x84, 0xf1, 0xc7, 0x9a, + 0x0f, 0x14, 0x42, 0xd4, 0x9d, 0x4b, 0xbf, 0x3b, 0xa5, 0x5e, 0x79, 0x42, + 0x1a, 0x4f, 0xd9, 0x0e, 0xfd, 0xad, 0xd7, 0xe4, 0x7a, 0x56, 0x85, 0xb0, + 0x6c, 0x75, 0xde, 0xa1, 0xf4, 0xcf, 0xd6, 0x6b, 0xe1, 0x64, 0x7b, 0x57, + 0xf2, 0xbf, 0xc3, 0x5c, 0xc4, 0x6e, 0x20, 0x00, 0xb0, 0x66, 0x85, 0x8a, + 0xe7, 0xad, 0x44, 0x17, 0xcf, 0x6f, 0xc7, 0xe8, 0x01, 0xa7, 0x7c, 0x45, + 0xb0, 0x06, 0xf8, 0xce, 0x09, 0x8e, 0x95, 0x59, 0x3f, 0x04, 0xfc, 0x92, + 0xae, 0x31, 0xa1, 0xcd, 0x5c, 0xd3, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, + 0x26, 0x30, 0x24, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, + 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, + 0x02, 0x00, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xa6, + 0xef, 0x4d, 0xc8, 0xc2, 0xcb, 0xe0, 0x4e, 0xc8, 0xd4, 0x3c, 0x0b, 0x61, + 0x5e, 0x73, 0x87, 0x81, 0x56, 0xd3, 0x6d, 0x09, 0xa2, 0xbc, 0x9d, 0xd1, + 0xac, 0xba, 0x01, 0x82, 0xa6, 0x5a, 0xf3, 0x06, 0xfb, 0x37, 0x06, 0x09, + 0xcf, 0xda, 0x6e, 0x62, 0x04, 0x38, 0x40, 0x48, 0xca, 0xc1, 0x6f, 0x0e, + 0x22, 0x41, 0xc8, 0xde, 0xa2, 0x1f, 0x05, 0xca, 0x65, 0x13, 0x14, 0xd7, + 0x5b, 0xaa, 0x80, 0xf6, 0xff, 0x0a, 0xe6, 0xbe, 0x47, 0xca, 0x55, 0x29, + 0x0c, 0xf0, 0xc8, 0x34, 0x8d, 0xdb, 0x69, 0x6e, 0x01, 0xe8, 0x9d, 0xb9, + 0xc8, 0x55, 0x86, 0x98, 0x27, 0x4c, 0x92, 0xca, 0xf8, 0xb8, 0xc5, 0xdf, + 0x9b, 0xca, 0x9d, 0x09, 0xc0, 0x59, 0xc8, 0x22, 0xcd, 0xb2, 0x00, 0xf2, + 0x0a, 0xa0, 0x8f, 0xe3, 0xf6, 0xe5, 0x7e, 0x96, 0xaa, 0xc7, 0xae, 0xa2, + 0xe1, 0x7b, 0xee, 0x85, 0xb9, 0x60, 0x1f, 0xb1, 0x29, 0xdc, 0x42, 0x6d, + 0xca, 0xd8, 0xb8, 0xe6, 0x84, 0x6f, 0x62, 0xbc, 0x7a, 0x83, 0xe5, 0x7b, + 0xb8, 0xab, 0xa2, 0xd5, 0x3d, 0x5f, 0xf5, 0xd7, 0x00, 0x10, 0xdc, 0x80, + 0xae, 0x3e, 0x44, 0x14, 0x27, 0x5e, 0x8e, 0x8a, 0x4d, 0x41, 0xf4, 0x9f, + 0xd6, 0x23, 0x8b, 0x7e, 0xc6, 0xd2, 0x8d, 0x3c, 0x8e, 0xeb, 0x64, 0x74, + 0x82, 0x76, 0x6f, 0x7b, 0x0d, 0x0a, 0x9f, 0x27, 0xce, 0xd7, 0x4c, 0x9d, + 0xe2, 0x6a, 0x14, 0xc6, 0xfe, 0xe2, 0xce, 0x9a, 0x1e, 0xe7, 0x45, 0x51, + 0x94, 0x47, 0x11, 0x78, 0xdb, 0xe9, 0xbe, 0xc1, 0x4a, 0xc4, 0xe2, 0x2b, + 0x62, 0xa0, 0xad, 0xb8, 0x1f, 0x41, 0xe3, 0x5d, 0x76, 0x9c, 0x38, 0xd1, + 0x8f, 0x73, 0xa9, 0x35, 0xa9, 0x6f, 0xb7, 0x84, 0xa5, 0x96, 0xce, 0xdf, + 0xb7, 0x1d, 0x19, 0x69, 0xb7, 0x40, 0xc5, 0xd6, 0xf3, 0xb8, 0xb0, 0x4d, + 0x1c, 0x99, 0x9e +}; diff --git a/testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS_EXCEPT_1024.pem b/testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS_EXCEPT_1024.pem new file mode 100644 index 0000000..ab0d3c8 --- /dev/null +++ b/testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS_EXCEPT_1024.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIID+zCCAuOgAwIBAgIFMTEwMDAwDQYJKoZIhvcNAQELBQAwgaoxSTBHBgNVBAMM +QFNhbXBsZSBNYXRyaXggUlNBLTIwNDggQ2VydGlmaWNhdGUgQXV0aG9yaXR5IGZv +ciBFQ0RIX1JTQSBzdWl0ZXMxCzAJBgNVBAYMAlVTMQswCQYDVQQIDAJXQTEQMA4G +A1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSW5zaWRlIFNlY3VyZSBDb3Jwb3JhdGlv +bjENMAsGA1UECwwEVGVzdDAeFw0xNDAzMTMyMzM3MTZaFw0xNzAzMTIyMzM3MTZa +MIGqMUkwRwYDVQQDDEBTYW1wbGUgTWF0cml4IFJTQS0yMDQ4IENlcnRpZmljYXRl +IEF1dGhvcml0eSBmb3IgRUNESF9SU0Egc3VpdGVzMQswCQYDVQQGDAJVUzELMAkG +A1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUluc2lkZSBTZWN1 +cmUgQ29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQC3mh36c2ey0o+DklPwuLmcdgvmNSNbPMzvHCBz+1cgtFKK +DPCEsC71WziChXnTKy1n+zu5fhJdTF0bWrbcwjLZKz19cQyLO/n1C4j3sBFp+VZt +5lfSKD4ByVBewUEW6jqik+t4/XpuWqAVGZ/YlQ1vfYeNKs9rxepLSGU38roGOyFO +mQZ5c3mRzpQ08mjeaDkRvr7b/xtcIqLIVQN1IlBt4GTP4CKGrXsjB5wpAO2E8cea +DxRC1J1LvzulXnlCGk/ZDv2t1+R6VoWwbHXeofTP1mvhZHtX8r/DXMRuIACwZoWK +561EF89vx+gBp3xFsAb4zgmOlVk/BPySrjGhzVzTAgMBAAGjJjAkMBIGA1UdEwEB +/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgAEMA0GCSqGSIb3DQEBCwUAA4IBAQCm +703IwsvgTsjUPAthXnOHgVbTbQmivJ3RrLoBgqZa8wb7NwYJz9puYgQ4QEjKwW8O +IkHI3qIfBcplExTXW6qA9v8K5r5HylUpDPDINI3baW4B6J25yFWGmCdMksr4uMXf +m8qdCcBZyCLNsgDyCqCP4/blfpaqx66i4XvuhblgH7Ep3EJtyti45oRvYrx6g+V7 +uKui1T1f9dcAENyArj5EFCdejopNQfSf1iOLfsbSjTyO62R0gnZvew0KnyfO10yd +4moUxv7izpoe50VRlEcReNvpvsFKxOIrYqCtuB9B4112nDjRj3OpNalvt4Slls7f +tx0ZabdAxdbzuLBNHJme +-----END CERTIFICATE----- diff --git a/testkeys/ECDH_RSA/CAcertRSA.h b/testkeys/ECDH_RSA/CAcertRSA.h new file mode 100644 index 0000000..dbb9d9f --- /dev/null +++ b/testkeys/ECDH_RSA/CAcertRSA.h @@ -0,0 +1,71 @@ +/** + * @file CAcertRSA.h + * @version $Format:%h%d$ + * + * Summary. + */ +unsigned char CAcertSrvEcRsaBuf[] = { +48, 130, 3, 52, 48, 130, 2, 157, 160, 3, 2, 1, 2, +2, 9, 0, 168, 68, 15, 142, 229, 144, 170, 222, 48, 13, +6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, 0, +48, 112, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, +85, 83, 49, 11, 48, 9, 6, 3, 85, 4, 8, 19, 2, +87, 65, 49, 16, 48, 14, 6, 3, 85, 4, 7, 19, 7, +83, 101, 97, 116, 116, 108, 101, 49, 16, 48, 14, 6, 3, +85, 4, 10, 19, 7, 80, 101, 101, 114, 83, 101, 99, 49, +13, 48, 11, 6, 3, 85, 4, 11, 19, 4, 84, 101, 115, +116, 49, 33, 48, 31, 6, 3, 85, 4, 3, 20, 24, 82, +83, 65, 32, 67, 65, 32, 102, 111, 114, 32, 69, 67, 68, +72, 95, 82, 83, 65, 32, 116, 101, 115, 116, 48, 30, 23, +13, 49, 49, 48, 54, 48, 57, 50, 50, 51, 57, 52, 49, +90, 23, 13, 49, 49, 48, 55, 48, 57, 50, 50, 51, 57, +52, 49, 90, 48, 112, 49, 11, 48, 9, 6, 3, 85, 4, +6, 19, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, 4, +8, 19, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, 4, +7, 19, 7, 83, 101, 97, 116, 116, 108, 101, 49, 16, 48, +14, 6, 3, 85, 4, 10, 19, 7, 80, 101, 101, 114, 83, +101, 99, 49, 13, 48, 11, 6, 3, 85, 4, 11, 19, 4, +84, 101, 115, 116, 49, 33, 48, 31, 6, 3, 85, 4, 3, +20, 24, 82, 83, 65, 32, 67, 65, 32, 102, 111, 114, 32, +69, 67, 68, 72, 95, 82, 83, 65, 32, 116, 101, 115, 116, +48, 129, 159, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, +1, 1, 1, 5, 0, 3, 129, 141, 0, 48, 129, 137, 2, +129, 129, 0, 203, 146, 214, 171, 106, 68, 180, 89, 179, 190, +34, 82, 28, 223, 201, 129, 103, 247, 227, 76, 218, 30, 30, +239, 11, 24, 81, 48, 217, 86, 186, 252, 170, 127, 92, 180, +183, 95, 72, 57, 158, 241, 73, 70, 213, 37, 175, 255, 199, +9, 126, 162, 219, 227, 161, 161, 229, 239, 112, 77, 47, 115, +126, 45, 179, 131, 152, 189, 181, 242, 205, 74, 239, 40, 151, +236, 173, 23, 183, 39, 169, 44, 146, 14, 214, 48, 39, 38, +166, 154, 235, 178, 207, 247, 50, 5, 102, 99, 96, 104, 190, +13, 121, 38, 52, 107, 103, 172, 22, 94, 79, 213, 5, 107, +249, 68, 78, 100, 55, 135, 249, 188, 106, 140, 90, 117, 120, +21, 2, 3, 1, 0, 1, 163, 129, 213, 48, 129, 210, 48, +29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 171, 17, 0, +68, 33, 201, 218, 203, 181, 192, 77, 128, 154, 112, 222, 25, +139, 101, 201, 182, 48, 129, 162, 6, 3, 85, 29, 35, 4, +129, 154, 48, 129, 151, 128, 20, 171, 17, 0, 68, 33, 201, +218, 203, 181, 192, 77, 128, 154, 112, 222, 25, 139, 101, 201, +182, 161, 116, 164, 114, 48, 112, 49, 11, 48, 9, 6, 3, +85, 4, 6, 19, 2, 85, 83, 49, 11, 48, 9, 6, 3, +85, 4, 8, 19, 2, 87, 65, 49, 16, 48, 14, 6, 3, +85, 4, 7, 19, 7, 83, 101, 97, 116, 116, 108, 101, 49, +16, 48, 14, 6, 3, 85, 4, 10, 19, 7, 80, 101, 101, +114, 83, 101, 99, 49, 13, 48, 11, 6, 3, 85, 4, 11, +19, 4, 84, 101, 115, 116, 49, 33, 48, 31, 6, 3, 85, +4, 3, 20, 24, 82, 83, 65, 32, 67, 65, 32, 102, 111, +114, 32, 69, 67, 68, 72, 95, 82, 83, 65, 32, 116, 101, +115, 116, 130, 9, 0, 168, 68, 15, 142, 229, 144, 170, 222, +48, 12, 6, 3, 85, 29, 19, 4, 5, 48, 3, 1, 1, +255, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, +5, 5, 0, 3, 129, 129, 0, 120, 146, 208, 60, 20, 232, +68, 59, 76, 219, 104, 232, 57, 25, 112, 159, 82, 182, 100, +240, 165, 54, 87, 95, 206, 185, 182, 89, 162, 5, 124, 136, +203, 204, 38, 176, 31, 115, 2, 217, 27, 224, 243, 46, 207, +234, 111, 8, 101, 201, 226, 147, 195, 102, 3, 198, 148, 174, +233, 116, 222, 9, 181, 45, 35, 60, 104, 239, 87, 233, 121, +148, 46, 10, 110, 127, 61, 129, 46, 195, 173, 151, 82, 91, +187, 63, 28, 45, 67, 62, 31, 122, 164, 169, 107, 242, 181, +222, 125, 69, 86, 197, 249, 253, 55, 64, 161, 64, 24, 18, +250, 223, 213, 28, 226, 0, 249, 202, 73, 221, 58, 43, 51, +189, 96, 200, 120, 172}; diff --git a/testkeys/ECDH_RSA/CAcertRSA.pem b/testkeys/ECDH_RSA/CAcertRSA.pem new file mode 100644 index 0000000..fe38e6e --- /dev/null +++ b/testkeys/ECDH_RSA/CAcertRSA.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDNDCCAp2gAwIBAgIJAKhED47lkKreMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV +BAYTAlVTMQswCQYDVQQIEwJXQTEQMA4GA1UEBxMHU2VhdHRsZTEQMA4GA1UEChMH +UGVlclNlYzENMAsGA1UECxMEVGVzdDEhMB8GA1UEAxQYUlNBIENBIGZvciBFQ0RI +X1JTQSB0ZXN0MB4XDTExMDYwOTIyMzk0MVoXDTExMDcwOTIyMzk0MVowcDELMAkG +A1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMRAwDgYDVQQK +EwdQZWVyU2VjMQ0wCwYDVQQLEwRUZXN0MSEwHwYDVQQDFBhSU0EgQ0EgZm9yIEVD +REhfUlNBIHRlc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMuS1qtqRLRZ +s74iUhzfyYFn9+NM2h4e7wsYUTDZVrr8qn9ctLdfSDme8UlG1SWv/8cJfqLb46Gh +5e9wTS9zfi2zg5i9tfLNSu8ol+ytF7cnqSySDtYwJyammuuyz/cyBWZjYGi+DXkm +NGtnrBZeT9UFa/lETmQ3h/m8aoxadXgVAgMBAAGjgdUwgdIwHQYDVR0OBBYEFKsR +AEQhydrLtcBNgJpw3hmLZcm2MIGiBgNVHSMEgZowgZeAFKsRAEQhydrLtcBNgJpw +3hmLZcm2oXSkcjBwMQswCQYDVQQGEwJVUzELMAkGA1UECBMCV0ExEDAOBgNVBAcT +B1NlYXR0bGUxEDAOBgNVBAoTB1BlZXJTZWMxDTALBgNVBAsTBFRlc3QxITAfBgNV +BAMUGFJTQSBDQSBmb3IgRUNESF9SU0EgdGVzdIIJAKhED47lkKreMAwGA1UdEwQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAeJLQPBToRDtM22joORlwn1K2ZPClNldf +zrm2WaIFfIjLzCawH3MC2Rvg8y7P6m8IZcnik8NmA8aUrul03gm1LSM8aO9X6XmU +Lgpufz2BLsOtl1Jbuz8cLUM+H3qkqWvytd59RVbF+f03QKFAGBL639Uc4gD5yknd +OiszvWDIeKw= +-----END CERTIFICATE----- diff --git a/testkeys/ECDH_RSA/CAprivKeyRSA.pem b/testkeys/ECDH_RSA/CAprivKeyRSA.pem new file mode 100644 index 0000000..cd275a8 --- /dev/null +++ b/testkeys/ECDH_RSA/CAprivKeyRSA.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMuS1qtqRLRZs74i +UhzfyYFn9+NM2h4e7wsYUTDZVrr8qn9ctLdfSDme8UlG1SWv/8cJfqLb46Gh5e9w +TS9zfi2zg5i9tfLNSu8ol+ytF7cnqSySDtYwJyammuuyz/cyBWZjYGi+DXkmNGtn +rBZeT9UFa/lETmQ3h/m8aoxadXgVAgMBAAECgYAGD24CllxLPixiqaTmJSdbidvQ +UXZg1SzqmKO6H448bM8qkXjzyIte48NtGgW4ZH/pzfeOI5uoMSimMyKpGfgUmJyq +MXFN0GYkClS3F0/X1+BGHnUPwfiwiDECZJ9uF5i0sYjdiPSb4JDFMnWqQ/86vTEi +IpwIG9mKSD83xGRblQJBAOyh1SgF2VUW7XddpQeC1LbzemJyLXI9AwtxgTi553Iz +6BNAJouHJdKsrTjXX7QPPldxgF9F9cC7m53AEJkf3jsCQQDcPFPoKCCYGCGllOTW +qh73lUlhcyrFd2Qt64l96iRYtcTf/sooy8KS0m9shRorkKoLSfIKJRLCr77aXmCD +hA3vAkAhz225bjyDX+dGKuctj4/9JATUlCPSMs2AkRM5m7ZqJuh996iKPyE0XN/T +Q1K1U4hAzkLdWg2nICc3/v1gI6GJAkBf71eNlY09M6XUfxt/9vMuXjVs4cIL6ooV +BrkJxGi4y9VKza46Pygu1MP8va48s/Oen0Nz79pQPEYi0WGxaGC5AkAU21Zlawjt +/uDlGeIAVM9BwmLkynIuO60dZsbGReReE6BZ2+hhLeC762DzHa9cW7KPJHQmzQ9N +Nk8iv6EWTvAA +-----END PRIVATE KEY----- diff --git a/testkeys/ECDH_RSA/ecdsaCert.h b/testkeys/ECDH_RSA/ecdsaCert.h new file mode 100644 index 0000000..7b4dab7 --- /dev/null +++ b/testkeys/ECDH_RSA/ecdsaCert.h @@ -0,0 +1,57 @@ +/** + * @file ecdsaCert.h + * @version $Format:%h%d$ + * + * Summary. + */ +unsigned char certSrvEcRsaBuf[] = { +48, 130, 2, 123, 48, 130, 1, 228, 160, 3, 2, 1, 2, +2, 1, 1, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, +1, 1, 5, 5, 0, 48, 112, 49, 11, 48, 9, 6, 3, +85, 4, 6, 19, 2, 85, 83, 49, 11, 48, 9, 6, 3, +85, 4, 8, 19, 2, 87, 65, 49, 16, 48, 14, 6, 3, +85, 4, 7, 19, 7, 83, 101, 97, 116, 116, 108, 101, 49, +16, 48, 14, 6, 3, 85, 4, 10, 19, 7, 80, 101, 101, +114, 83, 101, 99, 49, 13, 48, 11, 6, 3, 85, 4, 11, +19, 4, 84, 101, 115, 116, 49, 33, 48, 31, 6, 3, 85, +4, 3, 20, 24, 82, 83, 65, 32, 67, 65, 32, 102, 111, +114, 32, 69, 67, 68, 72, 95, 82, 83, 65, 32, 116, 101, +115, 116, 48, 30, 23, 13, 49, 49, 48, 54, 48, 57, 50, +50, 52, 48, 49, 49, 90, 23, 13, 49, 50, 48, 54, 48, +56, 50, 50, 52, 48, 49, 49, 90, 48, 97, 49, 11, 48, +9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 11, 48, +9, 6, 3, 85, 4, 8, 19, 2, 87, 65, 49, 16, 48, +14, 6, 3, 85, 4, 10, 19, 7, 80, 101, 101, 114, 83, +101, 99, 49, 13, 48, 11, 6, 3, 85, 4, 11, 19, 4, +84, 101, 115, 116, 49, 36, 48, 34, 6, 3, 85, 4, 3, +20, 27, 69, 67, 68, 72, 95, 82, 83, 65, 32, 83, 101, +114, 118, 101, 114, 32, 67, 101, 114, 116, 105, 102, 105, 99, +97, 116, 101, 48, 89, 48, 19, 6, 7, 42, 134, 72, 206, +61, 2, 1, 6, 8, 42, 134, 72, 206, 61, 3, 1, 7, +3, 66, 0, 4, 167, 138, 67, 50, 246, 201, 43, 173, 247, +243, 111, 237, 76, 118, 230, 197, 212, 245, 171, 81, 34, 165, +20, 106, 16, 65, 82, 196, 131, 8, 162, 11, 207, 80, 3, +126, 251, 151, 158, 116, 17, 153, 212, 56, 79, 226, 75, 146, +208, 252, 255, 244, 66, 166, 241, 99, 224, 232, 98, 18, 249, +111, 96, 92, 163, 123, 48, 121, 48, 9, 6, 3, 85, 29, +19, 4, 2, 48, 0, 48, 44, 6, 9, 96, 134, 72, 1, +134, 248, 66, 1, 13, 4, 31, 22, 29, 79, 112, 101, 110, +83, 83, 76, 32, 71, 101, 110, 101, 114, 97, 116, 101, 100, +32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 48, +29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 211, 55, 100, +135, 53, 126, 69, 147, 55, 219, 208, 41, 2, 222, 120, 232, +49, 67, 173, 183, 48, 31, 6, 3, 85, 29, 35, 4, 24, +48, 22, 128, 20, 171, 17, 0, 68, 33, 201, 218, 203, 181, +192, 77, 128, 154, 112, 222, 25, 139, 101, 201, 182, 48, 13, +6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, 0, +3, 129, 129, 0, 197, 173, 139, 148, 26, 76, 65, 188, 52, +249, 143, 182, 66, 81, 239, 233, 116, 215, 126, 188, 240, 10, +123, 107, 34, 70, 107, 32, 11, 15, 229, 70, 182, 252, 106, +12, 225, 85, 4, 127, 69, 53, 184, 189, 13, 244, 131, 183, +115, 90, 95, 102, 223, 170, 188, 247, 66, 119, 41, 220, 101, +28, 40, 35, 195, 80, 239, 122, 157, 231, 255, 68, 176, 65, +120, 55, 119, 239, 81, 242, 96, 60, 176, 43, 216, 142, 186, +163, 41, 144, 40, 236, 58, 86, 30, 246, 169, 172, 203, 67, +84, 142, 81, 167, 36, 166, 41, 63, 105, 152, 190, 220, 158, +88, 20, 63, 228, 207, 253, 219, 88, 247, 77, 100, 223, 24, +63, 149}; diff --git a/testkeys/ECDH_RSA/ecdsaCert.pem b/testkeys/ECDH_RSA/ecdsaCert.pem new file mode 100644 index 0000000..0a4ace8 --- /dev/null +++ b/testkeys/ECDH_RSA/ecdsaCert.pem @@ -0,0 +1,55 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, ST=WA, L=Seattle, O=PeerSec, OU=Test, CN=RSA CA for ECDH_RSA test + Validity + Not Before: Jun 9 22:40:11 2011 GMT + Not After : Jun 8 22:40:11 2012 GMT + Subject: C=US, ST=WA, O=PeerSec, OU=Test, CN=ECDH_RSA Server Certificate + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:a7:8a:43:32:f6:c9:2b:ad:f7:f3:6f:ed:4c:76: + e6:c5:d4:f5:ab:51:22:a5:14:6a:10:41:52:c4:83: + 08:a2:0b:cf:50:03:7e:fb:97:9e:74:11:99:d4:38: + 4f:e2:4b:92:d0:fc:ff:f4:42:a6:f1:63:e0:e8:62: + 12:f9:6f:60:5c + ASN1 OID: prime256v1 + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + D3:37:64:87:35:7E:45:93:37:DB:D0:29:02:DE:78:E8:31:43:AD:B7 + X509v3 Authority Key Identifier: + keyid:AB:11:00:44:21:C9:DA:CB:B5:C0:4D:80:9A:70:DE:19:8B:65:C9:B6 + + Signature Algorithm: sha1WithRSAEncryption + c5:ad:8b:94:1a:4c:41:bc:34:f9:8f:b6:42:51:ef:e9:74:d7: + 7e:bc:f0:0a:7b:6b:22:46:6b:20:0b:0f:e5:46:b6:fc:6a:0c: + e1:55:04:7f:45:35:b8:bd:0d:f4:83:b7:73:5a:5f:66:df:aa: + bc:f7:42:77:29:dc:65:1c:28:23:c3:50:ef:7a:9d:e7:ff:44: + b0:41:78:37:77:ef:51:f2:60:3c:b0:2b:d8:8e:ba:a3:29:90: + 28:ec:3a:56:1e:f6:a9:ac:cb:43:54:8e:51:a7:24:a6:29:3f: + 69:98:be:dc:9e:58:14:3f:e4:cf:fd:db:58:f7:4d:64:df:18: + 3f:95 +-----BEGIN CERTIFICATE----- +MIICezCCAeSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBwMQswCQYDVQQGEwJVUzEL +MAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxEDAOBgNVBAoTB1BlZXJTZWMx +DTALBgNVBAsTBFRlc3QxITAfBgNVBAMUGFJTQSBDQSBmb3IgRUNESF9SU0EgdGVz +dDAeFw0xMTA2MDkyMjQwMTFaFw0xMjA2MDgyMjQwMTFaMGExCzAJBgNVBAYTAlVT +MQswCQYDVQQIEwJXQTEQMA4GA1UEChMHUGVlclNlYzENMAsGA1UECxMEVGVzdDEk +MCIGA1UEAxQbRUNESF9SU0EgU2VydmVyIENlcnRpZmljYXRlMFkwEwYHKoZIzj0C +AQYIKoZIzj0DAQcDQgAEp4pDMvbJK63382/tTHbmxdT1q1EipRRqEEFSxIMIogvP +UAN++5eedBGZ1DhP4kuS0Pz/9EKm8WPg6GIS+W9gXKN7MHkwCQYDVR0TBAIwADAs +BglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYD +VR0OBBYEFNM3ZIc1fkWTN9vQKQLeeOgxQ623MB8GA1UdIwQYMBaAFKsRAEQhydrL +tcBNgJpw3hmLZcm2MA0GCSqGSIb3DQEBBQUAA4GBAMWti5QaTEG8NPmPtkJR7+l0 +13688Ap7ayJGayALD+VGtvxqDOFVBH9FNbi9DfSDt3NaX2bfqrz3Qncp3GUcKCPD +UO96nef/RLBBeDd371HyYDywK9iOuqMpkCjsOlYe9qmsy0NUjlGnJKYpP2mYvtye +WBQ/5M/921j3TWTfGD+V +-----END CERTIFICATE----- diff --git a/testkeys/ECDH_RSA/ecdsaPrivKey.h b/testkeys/ECDH_RSA/ecdsaPrivKey.h new file mode 100644 index 0000000..33fc59a --- /dev/null +++ b/testkeys/ECDH_RSA/ecdsaPrivKey.h @@ -0,0 +1,18 @@ +/** + * @file ecdsaPrivKey.h + * @version $Format:%h%d$ + * + * Summary. + */ +unsigned char privkeySrvEcRsaBuf[] = { +48, 129, 135, 2, 1, 0, 48, 19, 6, 7, 42, 134, 72, +206, 61, 2, 1, 6, 8, 42, 134, 72, 206, 61, 3, 1, +7, 4, 109, 48, 107, 2, 1, 1, 4, 32, 78, 245, 76, +207, 201, 165, 197, 229, 71, 68, 183, 240, 231, 229, 227, 172, +231, 241, 209, 197, 155, 49, 225, 107, 223, 26, 143, 28, 128, +247, 135, 70, 161, 68, 3, 66, 0, 4, 167, 138, 67, 50, +246, 201, 43, 173, 247, 243, 111, 237, 76, 118, 230, 197, 212, +245, 171, 81, 34, 165, 20, 106, 16, 65, 82, 196, 131, 8, +162, 11, 207, 80, 3, 126, 251, 151, 158, 116, 17, 153, 212, +56, 79, 226, 75, 146, 208, 252, 255, 244, 66, 166, 241, 99, +224, 232, 98, 18, 249, 111, 96, 92}; diff --git a/testkeys/ECDH_RSA/ecdsaPrivKey.pem b/testkeys/ECDH_RSA/ecdsaPrivKey.pem new file mode 100644 index 0000000..d0d386f --- /dev/null +++ b/testkeys/ECDH_RSA/ecdsaPrivKey.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgTvVMz8mlxeVHRLfw +5+XjrOfx0cWbMeFr3xqPHID3h0ahRANCAASnikMy9skrrffzb+1MdubF1PWrUSKl +FGoQQVLEgwiiC89QA377l550EZnUOE/iS5LQ/P/0QqbxY+DoYhL5b2Bc +-----END PRIVATE KEY----- diff --git a/testkeys/PSK/psk.h b/testkeys/PSK/psk.h new file mode 100644 index 0000000..b118442 --- /dev/null +++ b/testkeys/PSK/psk.h @@ -0,0 +1,42 @@ +/** + * @file psk.h + * @version $Format:%h%d$ + * + * Example Pre-Shared Key header file with randomly generated data. + */ + +typedef struct { + unsigned char id[16]; + unsigned char key[16]; +} pskStruct_t; + +#define PSK_HEADER_TABLE_COUNT (sizeof(PSK_HEADER_TABLE) / sizeof(pskStruct_t)) + +static const pskStruct_t PSK_HEADER_TABLE[] = { + /* This first id (the string "Client_identity", with null terminator) + and key will negotiate with: + openssl s_server -psk 33c841e5a8164812370b4757d6888630 ... + */ + {{0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x00}, + {0x33, 0xc8, 0x41, 0xe5, 0xa8, 0x16, 0x48, 0x12, 0x37, + 0x0b, 0x47, 0x57, 0xd6, 0x88, 0x86, 0x30} + }, + /* The following ids and keys are randomly generated */ + {{0x37, 0x30, 0x31, 0x35, 0x46, 0x33, 0x33, 0x35, 0x42, + 0x37, 0x43, 0x30, 0x33, 0x43, 0x38, 0x39}, + {0xac, 0xc5, 0xb5, 0x79, 0xe1, 0x00, 0xf6, 0xa9, 0x8f, + 0xb4, 0x8b, 0xf7, 0x55, 0xa9, 0x1f, 0x33} + }, + {{0x32, 0x43, 0x38, 0x39, 0x38, 0x44, 0x36, 0x35, 0x36, + 0x32, 0x44, 0x34, 0x35, 0x41, 0x37, 0x30}, + {0x9d, 0x3f, 0x10, 0x1b, 0xfd, 0x5c, 0xe3, 0x18, 0xfa, + 0x66, 0x34, 0xad, 0x87, 0xa0, 0xe1, 0x40} + }, + {{0x30, 0x43, 0x43, 0x39, 0x33, 0x33, 0x37, 0x30, 0x43, + 0x39, 0x42, 0x37, 0x39, 0x36, 0x37, 0x31}, + {0xa2, 0x7c, 0x3e, 0x53, 0x7c, 0x34, 0xb8, 0x52, 0x0b, + 0x21, 0x93, 0x29, 0x07, 0x59, 0x40, 0x29} + } +}; + diff --git a/testkeys/RSA/1024_RSA.h b/testkeys/RSA/1024_RSA.h new file mode 100644 index 0000000..1a42186 --- /dev/null +++ b/testkeys/RSA/1024_RSA.h @@ -0,0 +1,106 @@ +/** + * @file testkeys/RSA/1024_RSA.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated X.509 certificate as binary DER. +Certificate: + Data: + Version: 3 + Serial Number: + 31:32:33:34:35 + Issuer: CN=Sample Matrix RSA-1024 Certificate Authority, C=US, ST=WA, L=Seattle, O=INSIDE Secure Corporation, OU=Test + Validity: + Not Before: 2014/03/24 + Not After : 2017/03/23 + Subject: CN=Sample Matrix RSA-1024 Certificate, C=US, ST=WA, L=Seattle, O=INSIDE Secure Corporation, OU=Test + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (1024 bit) + Modulus: + ab:4a:fb:85:cb:17:ce:79:81:53:6a:80:3e:28:08:87: + 08:0a:88:53:bd:23:97:22:11:8e:52:d9:fc:b5:99:6e: + 5d:5c:a4:4d:f4:70:a2:88:61:c5:aa:63:e6:9a:f7:f4: + 8c:04:a6:bb:76:83:aa:41:c2:26:94:cd:9d:55:00:7f: + e1:ff:fb:bd:85:77:b4:69:18:7e:a9:48:a3:21:27:4f: + 7a:9d:32:c3:b6:9b:39:68:b8:76:10:ba:84:86:d1:ec: + 01:cc:ca:1f:c1:4a:5a:b9:20:99:8d:39:f3:ae:5d:11: + 7c:23:27:52:95:52:5c:89:00:8a:89:ea:d0:c2:45:7f + Exponent: 65537 + X509v3 extensions (critical: 0x1000): + X509v3 Subject Alternative Name: DNS + localhost + X509v3 Subject Alternative Name: iPAddress + 127.0.0.1 + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: 0x0 + X509v3 Extended Key Usage: 0x6 + TLS WWW server authentication + TLS WWW client authentication + X509v3 Authority Key Identifier: + f7:24:88:83:93:89:4d:d9:03:55:c1:38:27:17:40:e5: + ec:e1:d4:b0 + Signature Algorithm: sha256WithRSAEncryption + 1b:f2:ef:53:00:62:af:0e:66:03:39:5d:82:67:61:51: + 3b:51:c1:e5:8a:8e:91:8e:10:a6:54:5b:26:de:02:19: + d6:b0:05:e4:a7:7a:52:b0:74:a1:2d:57:4e:16:b9:ff: + 9e:2a:ce:54:bf:c5:fa:9f:9d:8f:4c:af:1b:36:a3:02: + 58:d8:94:e8:ce:bc:4b:83:e6:77:34:88:46:e9:e9:8a: + 92:a7:dc:8c:2f:67:0b:d5:ae:93:25:53:63:07:21:f0: + 4a:23:96:85:14:93:03:a6:9c:60:e8:58:27:61:bb:b9: + 6b:2d:90:d3:99:19:09:db:b4:cd:d8:44:89:22:de:67 +*/ +#define RSA1024_SIZE 771 +const static unsigned char RSA1024[RSA1024_SIZE] = + "\x30\x82\x02\xff\x30\x82\x02\x68\xa0\x03\x02\x01\x02\x02\x05\x31" + "\x32\x33\x34\x35\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01" + "\x0b\x05\x00\x30\x81\x96\x31\x35\x30\x33\x06\x03\x55\x04\x03\x0c" + "\x2c\x53\x61\x6d\x70\x6c\x65\x20\x4d\x61\x74\x72\x69\x78\x20\x52" + "\x53\x41\x2d\x31\x30\x32\x34\x20\x43\x65\x72\x74\x69\x66\x69\x63" + "\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x0b\x30" + "\x09\x06\x03\x55\x04\x06\x0c\x02\x55\x53\x31\x0b\x30\x09\x06\x03" + "\x55\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07" + "\x0c\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06\x03\x55" + "\x04\x0a\x0c\x19\x49\x4e\x53\x49\x44\x45\x20\x53\x65\x63\x75\x72" + "\x65\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30" + "\x0b\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x30\x1e\x17\x0d" + "\x31\x34\x30\x33\x32\x34\x31\x36\x33\x36\x34\x33\x5a\x17\x0d\x31" + "\x37\x30\x33\x32\x33\x31\x36\x33\x36\x34\x33\x5a\x30\x81\x8c\x31" + "\x2b\x30\x29\x06\x03\x55\x04\x03\x0c\x22\x53\x61\x6d\x70\x6c\x65" + "\x20\x4d\x61\x74\x72\x69\x78\x20\x52\x53\x41\x2d\x31\x30\x32\x34" + "\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x31\x0b\x30\x09" + "\x06\x03\x55\x04\x06\x0c\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55" + "\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c" + "\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06\x03\x55\x04" + "\x0a\x0c\x19\x49\x4e\x53\x49\x44\x45\x20\x53\x65\x63\x75\x72\x65" + "\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30\x0b" + "\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x30\x81\x9f\x30\x0d" + "\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d" + "\x00\x30\x81\x89\x02\x81\x81\x00\xab\x4a\xfb\x85\xcb\x17\xce\x79" + "\x81\x53\x6a\x80\x3e\x28\x08\x87\x08\x0a\x88\x53\xbd\x23\x97\x22" + "\x11\x8e\x52\xd9\xfc\xb5\x99\x6e\x5d\x5c\xa4\x4d\xf4\x70\xa2\x88" + "\x61\xc5\xaa\x63\xe6\x9a\xf7\xf4\x8c\x04\xa6\xbb\x76\x83\xaa\x41" + "\xc2\x26\x94\xcd\x9d\x55\x00\x7f\xe1\xff\xfb\xbd\x85\x77\xb4\x69" + "\x18\x7e\xa9\x48\xa3\x21\x27\x4f\x7a\x9d\x32\xc3\xb6\x9b\x39\x68" + "\xb8\x76\x10\xba\x84\x86\xd1\xec\x01\xcc\xca\x1f\xc1\x4a\x5a\xb9" + "\x20\x99\x8d\x39\xf3\xae\x5d\x11\x7c\x23\x27\x52\x95\x52\x5c\x89" + "\x00\x8a\x89\xea\xd0\xc2\x45\x7f\x02\x03\x01\x00\x01\xa3\x61\x30" + "\x5f\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\xf7\x24" + "\x88\x83\x93\x89\x4d\xd9\x03\x55\xc1\x38\x27\x17\x40\xe5\xec\xe1" + "\xd4\xb0\x30\x1a\x06\x03\x55\x1d\x11\x04\x13\x30\x11\x82\x09\x6c" + "\x6f\x63\x61\x6c\x68\x6f\x73\x74\x87\x04\x7f\x00\x00\x01\x30\x20" + "\x06\x03\x55\x1d\x25\x01\x01\xff\x04\x16\x30\x14\x06\x08\x2b\x06" + "\x01\x05\x05\x07\x03\x01\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x02" + "\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x03" + "\x81\x81\x00\x1b\xf2\xef\x53\x00\x62\xaf\x0e\x66\x03\x39\x5d\x82" + "\x67\x61\x51\x3b\x51\xc1\xe5\x8a\x8e\x91\x8e\x10\xa6\x54\x5b\x26" + "\xde\x02\x19\xd6\xb0\x05\xe4\xa7\x7a\x52\xb0\x74\xa1\x2d\x57\x4e" + "\x16\xb9\xff\x9e\x2a\xce\x54\xbf\xc5\xfa\x9f\x9d\x8f\x4c\xaf\x1b" + "\x36\xa3\x02\x58\xd8\x94\xe8\xce\xbc\x4b\x83\xe6\x77\x34\x88\x46" + "\xe9\xe9\x8a\x92\xa7\xdc\x8c\x2f\x67\x0b\xd5\xae\x93\x25\x53\x63" + "\x07\x21\xf0\x4a\x23\x96\x85\x14\x93\x03\xa6\x9c\x60\xe8\x58\x27" + "\x61\xbb\xb9\x6b\x2d\x90\xd3\x99\x19\x09\xdb\xb4\xcd\xd8\x44\x89" + "\x22\xde\x67"; diff --git a/testkeys/RSA/1024_RSA.pem b/testkeys/RSA/1024_RSA.pem new file mode 100644 index 0000000..c44518a --- /dev/null +++ b/testkeys/RSA/1024_RSA.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIC/zCCAmigAwIBAgIFMTIzNDUwDQYJKoZIhvcNAQELBQAwgZYxNTAzBgNVBAMM +LFNhbXBsZSBNYXRyaXggUlNBLTEwMjQgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQsw +CQYDVQQGDAJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNV +BAoMGUlOU0lERSBTZWN1cmUgQ29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QwHhcN +MTQwMzI0MTYzNjQzWhcNMTcwMzIzMTYzNjQzWjCBjDErMCkGA1UEAwwiU2FtcGxl +IE1hdHJpeCBSU0EtMTAyNCBDZXJ0aWZpY2F0ZTELMAkGA1UEBgwCVVMxCzAJBgNV +BAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMSIwIAYDVQQKDBlJTlNJREUgU2VjdXJl +IENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCrSvuFyxfOeYFTaoA+KAiHCAqIU70jlyIRjlLZ/LWZbl1cpE30cKKI +YcWqY+aa9/SMBKa7doOqQcImlM2dVQB/4f/7vYV3tGkYfqlIoyEnT3qdMsO2mzlo +uHYQuoSG0ewBzMofwUpauSCZjTnzrl0RfCMnUpVSXIkAionq0MJFfwIDAQABo2Ew +XzAfBgNVHSMEGDAWgBT3JIiDk4lN2QNVwTgnF0Dl7OHUsDAaBgNVHREEEzARggls +b2NhbGhvc3SHBH8AAAEwIAYDVR0lAQH/BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC +MA0GCSqGSIb3DQEBCwUAA4GBABvy71MAYq8OZgM5XYJnYVE7UcHlio6RjhCmVFsm +3gIZ1rAF5Kd6UrB0oS1XTha5/54qzlS/xfqfnY9Mrxs2owJY2JTozrxLg+Z3NIhG +6emKkqfcjC9nC9WukyVTYwch8EojloUUkwOmnGDoWCdhu7lrLZDTmRkJ27TN2ESJ +It5n +-----END CERTIFICATE----- diff --git a/testkeys/RSA/1024_RSA_CA.h b/testkeys/RSA/1024_RSA_CA.h new file mode 100644 index 0000000..ca7841d --- /dev/null +++ b/testkeys/RSA/1024_RSA_CA.h @@ -0,0 +1,104 @@ +/** + * @file testkeys/RSA/1024_RSA_CA.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated X.509 certificate as binary DER. +Certificate: + Data: + Version: 3 + Serial Number: + 31:32:33:34 + Issuer: CN=Sample Matrix RSA-1024 Certificate Authority, C=US, ST=WA, L=Seattle, O=INSIDE Secure Corporation, OU=Test + Validity: + Not Before: 2014/03/24 + Not After : 2017/03/23 + Subject: CN=Sample Matrix RSA-1024 Certificate Authority, C=US, ST=WA, L=Seattle, O=INSIDE Secure Corporation, OU=Test + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (1024 bit) + Modulus: + bf:40:50:f2:e2:38:39:21:38:74:91:22:71:04:1d:c6: + 31:35:4a:a9:37:c6:b1:61:14:e1:a7:de:6f:19:0f:cf: + 14:a0:ea:54:73:d6:20:9d:37:34:80:bb:c6:74:8c:4d: + 9c:51:16:0d:d6:34:e7:a7:04:bc:e0:93:e8:1f:9a:3e: + 98:dc:5d:16:e3:d5:e1:86:22:df:62:89:9b:67:ce:84: + da:30:76:a8:cd:20:c7:1b:35:70:a8:e2:aa:2d:da:a8: + 8c:30:b5:2c:22:0c:e5:53:11:b4:b5:16:0d:1c:b9:9f: + f5:e0:42:c1:e8:03:d2:b6:7b:71:2e:a7:01:8a:69:f9 + Exponent: 65537 + X509v3 extensions (critical: 0x208): + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: 0x4 + X509v3 Extended Key Usage: 0x0 + X509v3 Subject Key Identifier: + f7:24:88:83:93:89:4d:d9:03:55:c1:38:27:17:40:e5: + ec:e1:d4:b0 + X509v3 Authority Key Identifier: + f7:24:88:83:93:89:4d:d9:03:55:c1:38:27:17:40:e5: + ec:e1:d4:b0 + Signature Algorithm: sha256WithRSAEncryption + 41:96:d9:c1:38:df:74:de:e4:7f:c6:7a:d7:ca:dd:ef: + f9:cc:75:79:83:ac:37:73:dd:64:9b:0a:98:84:7f:9d: + 66:42:c7:cd:8c:98:1c:f5:7a:31:d5:17:67:a8:c9:62: + 8e:a2:36:8a:fc:da:f8:64:cd:9c:6b:78:2d:ef:7c:f3: + ca:ca:e3:86:c7:85:f7:93:27:51:43:54:f7:bc:b9:d0: + 27:18:6d:c6:ba:0e:e0:c5:17:ac:55:23:a2:b4:1f:1c: + 56:0c:27:81:44:42:40:cf:10:1b:22:0c:d3:89:9f:09: + f2:f3:33:6b:d3:1c:3b:92:a7:ab:5e:bd:3a:e9:82:8c +*/ +#define RSA1024CA_SIZE 785 +const static unsigned char RSA1024CA[RSA1024CA_SIZE] = + "\x30\x82\x03\x0d\x30\x82\x02\x76\xa0\x03\x02\x01\x02\x02\x04\x31" + "\x32\x33\x34\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b" + "\x05\x00\x30\x81\x96\x31\x35\x30\x33\x06\x03\x55\x04\x03\x0c\x2c" + "\x53\x61\x6d\x70\x6c\x65\x20\x4d\x61\x74\x72\x69\x78\x20\x52\x53" + "\x41\x2d\x31\x30\x32\x34\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61" + "\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x0b\x30\x09" + "\x06\x03\x55\x04\x06\x0c\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55" + "\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c" + "\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06\x03\x55\x04" + "\x0a\x0c\x19\x49\x4e\x53\x49\x44\x45\x20\x53\x65\x63\x75\x72\x65" + "\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30\x0b" + "\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x30\x1e\x17\x0d\x31" + "\x34\x30\x33\x32\x34\x31\x36\x32\x36\x34\x36\x5a\x17\x0d\x31\x37" + "\x30\x33\x32\x33\x31\x36\x32\x36\x34\x36\x5a\x30\x81\x96\x31\x35" + "\x30\x33\x06\x03\x55\x04\x03\x0c\x2c\x53\x61\x6d\x70\x6c\x65\x20" + "\x4d\x61\x74\x72\x69\x78\x20\x52\x53\x41\x2d\x31\x30\x32\x34\x20" + "\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68" + "\x6f\x72\x69\x74\x79\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x0c\x02" + "\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x57\x41\x31" + "\x10\x30\x0e\x06\x03\x55\x04\x07\x0c\x07\x53\x65\x61\x74\x74\x6c" + "\x65\x31\x22\x30\x20\x06\x03\x55\x04\x0a\x0c\x19\x49\x4e\x53\x49" + "\x44\x45\x20\x53\x65\x63\x75\x72\x65\x20\x43\x6f\x72\x70\x6f\x72" + "\x61\x74\x69\x6f\x6e\x31\x0d\x30\x0b\x06\x03\x55\x04\x0b\x0c\x04" + "\x54\x65\x73\x74\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7" + "\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81" + "\x00\xbf\x40\x50\xf2\xe2\x38\x39\x21\x38\x74\x91\x22\x71\x04\x1d" + "\xc6\x31\x35\x4a\xa9\x37\xc6\xb1\x61\x14\xe1\xa7\xde\x6f\x19\x0f" + "\xcf\x14\xa0\xea\x54\x73\xd6\x20\x9d\x37\x34\x80\xbb\xc6\x74\x8c" + "\x4d\x9c\x51\x16\x0d\xd6\x34\xe7\xa7\x04\xbc\xe0\x93\xe8\x1f\x9a" + "\x3e\x98\xdc\x5d\x16\xe3\xd5\xe1\x86\x22\xdf\x62\x89\x9b\x67\xce" + "\x84\xda\x30\x76\xa8\xcd\x20\xc7\x1b\x35\x70\xa8\xe2\xaa\x2d\xda" + "\xa8\x8c\x30\xb5\x2c\x22\x0c\xe5\x53\x11\xb4\xb5\x16\x0d\x1c\xb9" + "\x9f\xf5\xe0\x42\xc1\xe8\x03\xd2\xb6\x7b\x71\x2e\xa7\x01\x8a\x69" + "\xf9\x02\x03\x01\x00\x01\xa3\x66\x30\x64\x30\x12\x06\x03\x55\x1d" + "\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01\x00\x30\x1d" + "\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xf7\x24\x88\x83\x93\x89\x4d" + "\xd9\x03\x55\xc1\x38\x27\x17\x40\xe5\xec\xe1\xd4\xb0\x30\x1f\x06" + "\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\xf7\x24\x88\x83\x93\x89" + "\x4d\xd9\x03\x55\xc1\x38\x27\x17\x40\xe5\xec\xe1\xd4\xb0\x30\x0e" + "\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x00\x04\x30\x0d" + "\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x03\x81\x81" + "\x00\x41\x96\xd9\xc1\x38\xdf\x74\xde\xe4\x7f\xc6\x7a\xd7\xca\xdd" + "\xef\xf9\xcc\x75\x79\x83\xac\x37\x73\xdd\x64\x9b\x0a\x98\x84\x7f" + "\x9d\x66\x42\xc7\xcd\x8c\x98\x1c\xf5\x7a\x31\xd5\x17\x67\xa8\xc9" + "\x62\x8e\xa2\x36\x8a\xfc\xda\xf8\x64\xcd\x9c\x6b\x78\x2d\xef\x7c" + "\xf3\xca\xca\xe3\x86\xc7\x85\xf7\x93\x27\x51\x43\x54\xf7\xbc\xb9" + "\xd0\x27\x18\x6d\xc6\xba\x0e\xe0\xc5\x17\xac\x55\x23\xa2\xb4\x1f" + "\x1c\x56\x0c\x27\x81\x44\x42\x40\xcf\x10\x1b\x22\x0c\xd3\x89\x9f" + "\x09\xf2\xf3\x33\x6b\xd3\x1c\x3b\x92\xa7\xab\x5e\xbd\x3a\xe9\x82" + "\x8c"; diff --git a/testkeys/RSA/1024_RSA_CA.pem b/testkeys/RSA/1024_RSA_CA.pem new file mode 100644 index 0000000..a0418a1 --- /dev/null +++ b/testkeys/RSA/1024_RSA_CA.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDDTCCAnagAwIBAgIEMTIzNDANBgkqhkiG9w0BAQsFADCBljE1MDMGA1UEAwws +U2FtcGxlIE1hdHJpeCBSU0EtMTAyNCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxCzAJ +BgNVBAYMAlVTMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UE +CgwZSU5TSURFIFNlY3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDAeFw0x +NDAzMjQxNjI2NDZaFw0xNzAzMjMxNjI2NDZaMIGWMTUwMwYDVQQDDCxTYW1wbGUg +TWF0cml4IFJTQS0xMDI0IENlcnRpZmljYXRlIEF1dGhvcml0eTELMAkGA1UEBgwC +VVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMSIwIAYDVQQKDBlJTlNJ +REUgU2VjdXJlIENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MIGfMA0GCSqGSIb3 +DQEBAQUAA4GNADCBiQKBgQC/QFDy4jg5ITh0kSJxBB3GMTVKqTfGsWEU4afebxkP +zxSg6lRz1iCdNzSAu8Z0jE2cURYN1jTnpwS84JPoH5o+mNxdFuPV4YYi32KJm2fO +hNowdqjNIMcbNXCo4qot2qiMMLUsIgzlUxG0tRYNHLmf9eBCwegD0rZ7cS6nAYpp ++QIDAQABo2YwZDASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBT3JIiDk4lN +2QNVwTgnF0Dl7OHUsDAfBgNVHSMEGDAWgBT3JIiDk4lN2QNVwTgnF0Dl7OHUsDAO +BgNVHQ8BAf8EBAMCAAQwDQYJKoZIhvcNAQELBQADgYEAQZbZwTjfdN7kf8Z618rd +7/nMdXmDrDdz3WSbCpiEf51mQsfNjJgc9Xox1RdnqMlijqI2ivza+GTNnGt4Le98 +88rK44bHhfeTJ1FDVPe8udAnGG3Gug7gxResVSOitB8cVgwngURCQM8QGyIM04mf +CfLzM2vTHDuSp6tevTrpgow= +-----END CERTIFICATE----- diff --git a/testkeys/RSA/1024_RSA_KEY.h b/testkeys/RSA/1024_RSA_KEY.h new file mode 100644 index 0000000..7f969d6 --- /dev/null +++ b/testkeys/RSA/1024_RSA_KEY.h @@ -0,0 +1,50 @@ +/** + * @file testkeys/RSA/1024_RSA_KEY.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated private key as binary DER. +*/ +#define RSA1024KEY_SIZE 609 +const static unsigned char RSA1024KEY[RSA1024KEY_SIZE] = + "\x30\x82\x02\x5d\x02\x01\x00\x02\x81\x81\x00\xab\x4a\xfb\x85\xcb" + "\x17\xce\x79\x81\x53\x6a\x80\x3e\x28\x08\x87\x08\x0a\x88\x53\xbd" + "\x23\x97\x22\x11\x8e\x52\xd9\xfc\xb5\x99\x6e\x5d\x5c\xa4\x4d\xf4" + "\x70\xa2\x88\x61\xc5\xaa\x63\xe6\x9a\xf7\xf4\x8c\x04\xa6\xbb\x76" + "\x83\xaa\x41\xc2\x26\x94\xcd\x9d\x55\x00\x7f\xe1\xff\xfb\xbd\x85" + "\x77\xb4\x69\x18\x7e\xa9\x48\xa3\x21\x27\x4f\x7a\x9d\x32\xc3\xb6" + "\x9b\x39\x68\xb8\x76\x10\xba\x84\x86\xd1\xec\x01\xcc\xca\x1f\xc1" + "\x4a\x5a\xb9\x20\x99\x8d\x39\xf3\xae\x5d\x11\x7c\x23\x27\x52\x95" + "\x52\x5c\x89\x00\x8a\x89\xea\xd0\xc2\x45\x7f\x02\x03\x01\x00\x01" + "\x02\x81\x80\x2b\x1d\x84\x91\xf8\xbc\xd5\x4b\xe0\x31\x8e\xed\x18" + "\xb8\x1a\xed\x62\x28\xc4\x87\xcf\x63\xd5\xf6\xcd\x54\x75\xa6\x48" + "\xe5\xac\xe9\x0a\xb6\xf6\xe4\x68\x52\xb1\x96\x82\x85\xae\x8d\xd6" + "\xcd\xca\xfb\xd3\x02\x98\xb5\x36\xef\x8d\x3b\x60\x13\x36\x01\x4b" + "\x48\xca\x06\xfc\xbf\x9e\xfd\x1f\x5b\x94\xae\x8f\x7e\xd3\xd8\x88" + "\x36\x0d\x50\x8f\x65\x79\xb3\xaa\x69\xde\x64\x2f\xb9\x43\x44\x32" + "\xfe\xe4\x2b\x7e\x4a\x7e\xdd\xb8\xf7\x1b\x74\x8c\x2e\xd6\x73\x0a" + "\x0e\xdc\xfb\x85\x83\x6d\x3b\xa1\xea\xc6\x5b\x5a\xe1\x2c\xe4\x47" + "\xf5\x51\x81\x02\x41\x00\xe0\x74\xf8\xee\xe1\xf0\xb5\xb6\xbc\xf4" + "\x04\x79\x2c\x1d\xcf\x7d\xae\x91\xa1\x2f\x82\x94\xe8\x50\x7f\x6f" + "\x88\xac\x36\xbd\x78\xe6\x3c\xfe\x86\xe7\x89\x65\x82\x04\x49\x91" + "\x18\x98\xa2\x01\x45\xb9\x07\x7c\xcd\x2c\x85\xcb\x7b\x16\x8e\xd3" + "\x2a\x6e\xf1\xab\x7e\xc3\x02\x41\x00\xc3\x5d\x63\xb2\x1c\x11\x3c" + "\x9d\x6f\x72\x42\x1e\xbc\x10\x2b\x45\x4f\x0e\x28\xa7\x42\x37\x58" + "\x13\xc8\x55\xf1\x20\x94\xc0\xcb\x54\x31\xb7\xb6\x0e\x61\xc8\x39" + "\x1d\x81\x50\xeb\x4a\x28\x2e\x19\x6b\x49\xb5\xb4\x4c\x10\x6b\xaf" + "\xf0\x90\x10\x25\x0c\x4e\xec\xaa\x95\x02\x40\x5a\xe9\xe6\x1e\x53" + "\xf3\xbc\x96\x6c\xc8\x65\xbb\x72\xcc\x0c\x4b\xfa\xd6\x4f\xb4\x3f" + "\xae\xf2\xbe\x10\x2f\xeb\xea\xdd\x2d\x37\x78\x02\x42\x91\xff\xdc" + "\x5d\xfa\x20\xa4\x6f\x99\xc7\xd0\xee\xb4\xff\xf1\xf1\x71\xe5\x53" + "\xb8\x0c\x7e\x21\x91\x94\x81\x65\x6f\xb2\x23\x02\x41\x00\xb2\x87" + "\xfb\x7d\x5e\x6c\xda\x09\xbd\x38\x9a\xf7\xdf\x40\x9f\x6a\x5d\x0e" + "\x41\x54\x68\x0c\x8f\x6e\xb4\x9a\xe5\x19\xb3\x16\x64\x39\x72\x9d" + "\xc1\xbf\x6e\xd8\x3c\x69\x9c\x2d\x48\x77\xa2\x34\x4e\x82\x5e\xff" + "\xaf\xdd\xfa\xfb\x8d\xf2\xb6\x94\x2a\x67\x0f\x10\xf3\xe9\x02\x41" + "\x00\xde\x7a\x66\x2d\xb6\x63\xa4\x02\x8c\x55\xed\x2c\x7d\x91\x73" + "\xab\x65\x76\xc5\x0c\x85\x64\x80\xb5\x90\xc1\x48\x80\x15\x0d\x60" + "\xdf\x6f\x17\x92\x3f\xdb\x19\xd1\x7f\xf0\x89\x3f\x6d\xa7\x29\xd9" + "\x18\xe9\x94\xdb\x7d\x6a\x68\xe7\xbc\xf3\x0c\xf8\x18\x2f\xb8\xdd" + "\xe4"; diff --git a/testkeys/RSA/1024_RSA_KEY.pem b/testkeys/RSA/1024_RSA_KEY.pem new file mode 100644 index 0000000..92e4423 --- /dev/null +++ b/testkeys/RSA/1024_RSA_KEY.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQCrSvuFyxfOeYFTaoA+KAiHCAqIU70jlyIRjlLZ/LWZbl1cpE30 +cKKIYcWqY+aa9/SMBKa7doOqQcImlM2dVQB/4f/7vYV3tGkYfqlIoyEnT3qdMsO2 +mzlouHYQuoSG0ewBzMofwUpauSCZjTnzrl0RfCMnUpVSXIkAionq0MJFfwIDAQAB +AoGAKx2Ekfi81UvgMY7tGLga7WIoxIfPY9X2zVR1pkjlrOkKtvbkaFKxloKFro3W +zcr70wKYtTbvjTtgEzYBS0jKBvy/nv0fW5Suj37T2Ig2DVCPZXmzqmneZC+5Q0Qy +/uQrfkp+3bj3G3SMLtZzCg7c+4WDbTuh6sZbWuEs5Ef1UYECQQDgdPju4fC1trz0 +BHksHc99rpGhL4KU6FB/b4isNr145jz+hueJZYIESZEYmKIBRbkHfM0shct7Fo7T +Km7xq37DAkEAw11jshwRPJ1vckIevBArRU8OKKdCN1gTyFXxIJTAy1Qxt7YOYcg5 +HYFQ60ooLhlrSbW0TBBrr/CQECUMTuyqlQJAWunmHlPzvJZsyGW7cswMS/rWT7Q/ +rvK+EC/r6t0tN3gCQpH/3F36IKRvmcfQ7rT/8fFx5VO4DH4hkZSBZW+yIwJBALKH ++31ebNoJvTia999An2pdDkFUaAyPbrSa5RmzFmQ5cp3Bv27YPGmcLUh3ojROgl7/ +r936+43ytpQqZw8Q8+kCQQDeemYttmOkAoxV7Sx9kXOrZXbFDIVkgLWQwUiAFQ1g +328Xkj/bGdF/8Ik/bacp2RjplNt9amjnvPMM+BgvuN3k +-----END RSA PRIVATE KEY----- diff --git a/testkeys/RSA/2048_RSA.h b/testkeys/RSA/2048_RSA.h new file mode 100644 index 0000000..89f7ba9 --- /dev/null +++ b/testkeys/RSA/2048_RSA.h @@ -0,0 +1,138 @@ +/** + * @file testkeys/RSA/2048_RSA.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated X.509 certificate as binary DER. +Certificate: + Data: + Version: 3 + Serial Number: + 32:33:34:35:36 + Issuer: CN=Sample Matrix RSA-2048 Certificate Authority, C=US, ST=WA, L=Seattle, O=INSIDE Secure Corporation, OU=Test + Validity: + Not Before: 2014/03/24 + Not After : 2017/03/23 + Subject: CN=Sample Matrix RSA-2048 Certificate, C=US, ST=WA, L=Seattle, O=INSIDE Secure Corporation, OU=Test + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + ad:6a:33:ee:a2:73:6d:68:ba:bd:2d:b1:b5:54:f0:04: + 14:ff:bd:d7:5b:4c:69:e7:f4:66:7f:ac:06:e1:95:77: + 6b:9d:9a:1f:51:61:e6:d2:92:50:dc:0f:5d:15:0c:9e: + d3:37:a6:f9:77:36:76:74:da:3f:50:7f:9c:df:52:c9: + 32:4c:da:22:31:eb:94:b0:cf:56:ee:91:86:30:a9:24: + 29:01:2f:83:d1:08:73:94:97:e1:db:88:85:3b:e1:46: + 2b:c5:ff:03:ea:7c:74:a6:89:64:41:cc:88:e7:9c:af: + 33:fb:48:e7:5b:ca:6f:90:75:7a:42:a2:ba:8a:4e:06: + 38:87:51:66:96:c1:ef:8a:e2:b2:e7:63:57:f4:fa:f8: + a6:4d:4d:43:28:ac:3a:4c:ee:33:5d:f1:21:0d:d4:fc: + 9e:23:f0:29:d8:f6:55:66:36:1a:29:7a:6d:33:2f:0d: + 30:72:f8:b4:2b:7f:e9:61:75:49:dd:fd:3b:2c:29:df: + 7b:b1:96:32:0c:98:c4:36:3c:d8:0c:82:d3:c7:f4:f0: + f4:c4:e2:7c:d4:56:ae:74:60:fc:c2:e9:44:da:f4:74: + 12:05:6a:4f:bc:ba:bb:4c:04:aa:43:9d:50:88:a7:a2: + 38:73:5a:01:01:40:cd:d2:7c:79:c8:78:dc:26:44:e5 + Exponent: 65537 + X509v3 extensions (critical: 0x1000): + X509v3 Subject Alternative Name: DNS + localhost + X509v3 Subject Alternative Name: iPAddress + 127.0.0.1 + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: 0x0 + X509v3 Extended Key Usage: 0x6 + TLS WWW server authentication + TLS WWW client authentication + X509v3 Authority Key Identifier: + f4:9f:e9:91:43:ac:1c:9b:dd:07:40:2d:69:67:3c:ef: + d4:ea:db:54 + Signature Algorithm: sha256WithRSAEncryption + 01:06:8f:2e:6c:82:8c:fc:cf:a6:f6:af:fc:b8:89:48: + 9e:f9:e3:fa:9b:72:cc:12:31:b1:7e:0b:9d:c6:56:27: + de:ec:03:de:03:ad:2e:b2:e2:05:7d:bc:a2:4f:e8:a7: + fb:e0:4a:1e:79:54:82:35:5f:f2:6e:06:c4:2a:2a:81: + b7:d1:ed:28:42:b5:82:a6:fe:62:4d:04:58:5f:53:9d: + 90:ee:c6:4c:d2:15:de:2f:ed:1c:a1:18:ef:a2:d3:9d: + 71:7a:c8:fa:ce:4b:a6:c6:bf:f0:ad:b0:dd:2e:4e:b3: + 2f:6f:ed:ae:94:b7:91:29:89:77:7a:a0:89:b1:6f:95: + a4:15:7d:1b:04:41:ec:c5:46:89:35:24:b9:de:ed:e7: + 5d:71:13:d7:9e:3d:a2:04:e6:8e:7c:f8:9c:f8:27:1b: + 2a:db:42:e3:89:d0:57:6e:b7:f0:14:93:1b:44:c8:ce: + ac:23:cb:8d:0a:af:4b:57:19:a3:56:12:06:ef:c5:1d: + d2:82:a0:54:0a:ab:bb:95:4b:30:8c:ed:fb:b2:c3:8a: + c7:eb:f0:59:48:d8:35:c7:7c:cc:a7:fb:a8:67:5d:ff: + f7:2e:75:83:ad:83:15:32:28:de:b9:d0:8e:f2:6b:c2: + c9:dc:2b:23:bf:4a:3f:3b:af:7f:b5:d3:a3:ba:e6:23 +*/ +#define RSA2048_SIZE 1032 +const static unsigned char RSA2048[RSA2048_SIZE] = + "\x30\x82\x04\x04\x30\x82\x02\xec\xa0\x03\x02\x01\x02\x02\x05\x32" + "\x33\x34\x35\x36\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01" + "\x0b\x05\x00\x30\x81\x96\x31\x35\x30\x33\x06\x03\x55\x04\x03\x0c" + "\x2c\x53\x61\x6d\x70\x6c\x65\x20\x4d\x61\x74\x72\x69\x78\x20\x52" + "\x53\x41\x2d\x32\x30\x34\x38\x20\x43\x65\x72\x74\x69\x66\x69\x63" + "\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x0b\x30" + "\x09\x06\x03\x55\x04\x06\x0c\x02\x55\x53\x31\x0b\x30\x09\x06\x03" + "\x55\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07" + "\x0c\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06\x03\x55" + "\x04\x0a\x0c\x19\x49\x4e\x53\x49\x44\x45\x20\x53\x65\x63\x75\x72" + "\x65\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30" + "\x0b\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x30\x1e\x17\x0d" + "\x31\x34\x30\x33\x32\x34\x31\x36\x33\x39\x30\x33\x5a\x17\x0d\x31" + "\x37\x30\x33\x32\x33\x31\x36\x33\x39\x30\x33\x5a\x30\x81\x8c\x31" + "\x2b\x30\x29\x06\x03\x55\x04\x03\x0c\x22\x53\x61\x6d\x70\x6c\x65" + "\x20\x4d\x61\x74\x72\x69\x78\x20\x52\x53\x41\x2d\x32\x30\x34\x38" + "\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x31\x0b\x30\x09" + "\x06\x03\x55\x04\x06\x0c\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55" + "\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c" + "\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06\x03\x55\x04" + "\x0a\x0c\x19\x49\x4e\x53\x49\x44\x45\x20\x53\x65\x63\x75\x72\x65" + "\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30\x0b" + "\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x30\x82\x01\x22\x30" + "\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82" + "\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xad\x6a\x33\xee" + "\xa2\x73\x6d\x68\xba\xbd\x2d\xb1\xb5\x54\xf0\x04\x14\xff\xbd\xd7" + "\x5b\x4c\x69\xe7\xf4\x66\x7f\xac\x06\xe1\x95\x77\x6b\x9d\x9a\x1f" + "\x51\x61\xe6\xd2\x92\x50\xdc\x0f\x5d\x15\x0c\x9e\xd3\x37\xa6\xf9" + "\x77\x36\x76\x74\xda\x3f\x50\x7f\x9c\xdf\x52\xc9\x32\x4c\xda\x22" + "\x31\xeb\x94\xb0\xcf\x56\xee\x91\x86\x30\xa9\x24\x29\x01\x2f\x83" + "\xd1\x08\x73\x94\x97\xe1\xdb\x88\x85\x3b\xe1\x46\x2b\xc5\xff\x03" + "\xea\x7c\x74\xa6\x89\x64\x41\xcc\x88\xe7\x9c\xaf\x33\xfb\x48\xe7" + "\x5b\xca\x6f\x90\x75\x7a\x42\xa2\xba\x8a\x4e\x06\x38\x87\x51\x66" + "\x96\xc1\xef\x8a\xe2\xb2\xe7\x63\x57\xf4\xfa\xf8\xa6\x4d\x4d\x43" + "\x28\xac\x3a\x4c\xee\x33\x5d\xf1\x21\x0d\xd4\xfc\x9e\x23\xf0\x29" + "\xd8\xf6\x55\x66\x36\x1a\x29\x7a\x6d\x33\x2f\x0d\x30\x72\xf8\xb4" + "\x2b\x7f\xe9\x61\x75\x49\xdd\xfd\x3b\x2c\x29\xdf\x7b\xb1\x96\x32" + "\x0c\x98\xc4\x36\x3c\xd8\x0c\x82\xd3\xc7\xf4\xf0\xf4\xc4\xe2\x7c" + "\xd4\x56\xae\x74\x60\xfc\xc2\xe9\x44\xda\xf4\x74\x12\x05\x6a\x4f" + "\xbc\xba\xbb\x4c\x04\xaa\x43\x9d\x50\x88\xa7\xa2\x38\x73\x5a\x01" + "\x01\x40\xcd\xd2\x7c\x79\xc8\x78\xdc\x26\x44\xe5\x02\x03\x01\x00" + "\x01\xa3\x61\x30\x5f\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16" + "\x80\x14\xf4\x9f\xe9\x91\x43\xac\x1c\x9b\xdd\x07\x40\x2d\x69\x67" + "\x3c\xef\xd4\xea\xdb\x54\x30\x1a\x06\x03\x55\x1d\x11\x04\x13\x30" + "\x11\x82\x09\x6c\x6f\x63\x61\x6c\x68\x6f\x73\x74\x87\x04\x7f\x00" + "\x00\x01\x30\x20\x06\x03\x55\x1d\x25\x01\x01\xff\x04\x16\x30\x14" + "\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2b\x06\x01\x05" + "\x05\x07\x03\x02\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01" + "\x0b\x05\x00\x03\x82\x01\x01\x00\x01\x06\x8f\x2e\x6c\x82\x8c\xfc" + "\xcf\xa6\xf6\xaf\xfc\xb8\x89\x48\x9e\xf9\xe3\xfa\x9b\x72\xcc\x12" + "\x31\xb1\x7e\x0b\x9d\xc6\x56\x27\xde\xec\x03\xde\x03\xad\x2e\xb2" + "\xe2\x05\x7d\xbc\xa2\x4f\xe8\xa7\xfb\xe0\x4a\x1e\x79\x54\x82\x35" + "\x5f\xf2\x6e\x06\xc4\x2a\x2a\x81\xb7\xd1\xed\x28\x42\xb5\x82\xa6" + "\xfe\x62\x4d\x04\x58\x5f\x53\x9d\x90\xee\xc6\x4c\xd2\x15\xde\x2f" + "\xed\x1c\xa1\x18\xef\xa2\xd3\x9d\x71\x7a\xc8\xfa\xce\x4b\xa6\xc6" + "\xbf\xf0\xad\xb0\xdd\x2e\x4e\xb3\x2f\x6f\xed\xae\x94\xb7\x91\x29" + "\x89\x77\x7a\xa0\x89\xb1\x6f\x95\xa4\x15\x7d\x1b\x04\x41\xec\xc5" + "\x46\x89\x35\x24\xb9\xde\xed\xe7\x5d\x71\x13\xd7\x9e\x3d\xa2\x04" + "\xe6\x8e\x7c\xf8\x9c\xf8\x27\x1b\x2a\xdb\x42\xe3\x89\xd0\x57\x6e" + "\xb7\xf0\x14\x93\x1b\x44\xc8\xce\xac\x23\xcb\x8d\x0a\xaf\x4b\x57" + "\x19\xa3\x56\x12\x06\xef\xc5\x1d\xd2\x82\xa0\x54\x0a\xab\xbb\x95" + "\x4b\x30\x8c\xed\xfb\xb2\xc3\x8a\xc7\xeb\xf0\x59\x48\xd8\x35\xc7" + "\x7c\xcc\xa7\xfb\xa8\x67\x5d\xff\xf7\x2e\x75\x83\xad\x83\x15\x32" + "\x28\xde\xb9\xd0\x8e\xf2\x6b\xc2\xc9\xdc\x2b\x23\xbf\x4a\x3f\x3b" + "\xaf\x7f\xb5\xd3\xa3\xba\xe6\x23"; diff --git a/testkeys/RSA/2048_RSA.pem b/testkeys/RSA/2048_RSA.pem new file mode 100644 index 0000000..0710678 --- /dev/null +++ b/testkeys/RSA/2048_RSA.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEBDCCAuygAwIBAgIFMjM0NTYwDQYJKoZIhvcNAQELBQAwgZYxNTAzBgNVBAMM +LFNhbXBsZSBNYXRyaXggUlNBLTIwNDggQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQsw +CQYDVQQGDAJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNV +BAoMGUlOU0lERSBTZWN1cmUgQ29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QwHhcN +MTQwMzI0MTYzOTAzWhcNMTcwMzIzMTYzOTAzWjCBjDErMCkGA1UEAwwiU2FtcGxl +IE1hdHJpeCBSU0EtMjA0OCBDZXJ0aWZpY2F0ZTELMAkGA1UEBgwCVVMxCzAJBgNV +BAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMSIwIAYDVQQKDBlJTlNJREUgU2VjdXJl +IENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEArWoz7qJzbWi6vS2xtVTwBBT/vddbTGnn9GZ/rAbhlXdrnZof +UWHm0pJQ3A9dFQye0zem+Xc2dnTaP1B/nN9SyTJM2iIx65Swz1bukYYwqSQpAS+D +0QhzlJfh24iFO+FGK8X/A+p8dKaJZEHMiOecrzP7SOdbym+QdXpCorqKTgY4h1Fm +lsHviuKy52NX9Pr4pk1NQyisOkzuM13xIQ3U/J4j8CnY9lVmNhopem0zLw0wcvi0 +K3/pYXVJ3f07LCnfe7GWMgyYxDY82AyC08f08PTE4nzUVq50YPzC6UTa9HQSBWpP +vLq7TASqQ51QiKeiOHNaAQFAzdJ8ech43CZE5QIDAQABo2EwXzAfBgNVHSMEGDAW +gBT0n+mRQ6wcm90HQC1pZzzv1OrbVDAaBgNVHREEEzARgglsb2NhbGhvc3SHBH8A +AAEwIAYDVR0lAQH/BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEB +CwUAA4IBAQABBo8ubIKM/M+m9q/8uIlInvnj+ptyzBIxsX4LncZWJ97sA94DrS6y +4gV9vKJP6Kf74EoeeVSCNV/ybgbEKiqBt9HtKEK1gqb+Yk0EWF9TnZDuxkzSFd4v +7RyhGO+i051xesj6zkumxr/wrbDdLk6zL2/trpS3kSmJd3qgibFvlaQVfRsEQezF +Rok1JLne7eddcRPXnj2iBOaOfPic+CcbKttC44nQV2638BSTG0TIzqwjy40Kr0tX +GaNWEgbvxR3SgqBUCqu7lUswjO37ssOKx+vwWUjYNcd8zKf7qGdd//cudYOtgxUy +KN650I7ya8LJ3Csjv0o/O69/tdOjuuYj +-----END CERTIFICATE----- diff --git a/testkeys/RSA/2048_RSA_CA.h b/testkeys/RSA/2048_RSA_CA.h new file mode 100644 index 0000000..334ac81 --- /dev/null +++ b/testkeys/RSA/2048_RSA_CA.h @@ -0,0 +1,136 @@ +/** + * @file testkeys/RSA/2048_RSA_CA.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated X.509 certificate as binary DER. +Certificate: + Data: + Version: 3 + Serial Number: + 32:33:34:35:36:37 + Issuer: CN=Sample Matrix RSA-2048 Certificate Authority, C=US, ST=WA, L=Seattle, O=INSIDE Secure Corporation, OU=Test + Validity: + Not Before: 2014/03/24 + Not After : 2017/03/23 + Subject: CN=Sample Matrix RSA-2048 Certificate Authority, C=US, ST=WA, L=Seattle, O=INSIDE Secure Corporation, OU=Test + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + cc:ab:5b:40:3b:0a:4b:c0:83:5c:68:e5:f4:00:5a:15: + 1a:e3:78:f3:a0:41:23:93:5a:c1:c6:fa:04:90:a3:45: + 8e:30:5c:91:8a:6d:84:bf:78:c0:cb:b1:ee:65:af:aa: + 5d:ba:f1:35:04:b5:40:94:ed:bc:8c:f5:eb:a1:bb:8f: + a2:fa:b7:aa:ec:53:77:8b:af:b6:d1:78:f1:58:59:00: + 6c:8f:98:44:1d:73:4c:e1:1a:8a:b0:61:80:dd:c0:df: + 9b:74:5f:d0:7c:66:66:23:dc:30:9c:4d:e0:ec:da:6e: + 04:c4:c8:62:a2:21:11:ef:28:dc:6d:e9:31:b7:7a:9e: + ca:db:ba:c2:9c:93:1e:24:a9:9a:74:be:a4:26:4e:bb: + 5f:79:04:d3:41:72:05:a2:53:9a:44:20:01:48:44:5d: + 33:72:63:3f:aa:a2:77:09:f5:c3:e2:26:b5:12:87:21: + ad:4a:e7:99:99:ef:3d:b2:fa:bd:b2:c2:6a:ce:a6:3a: + 85:7a:3f:20:94:ba:15:7f:7a:82:e9:6f:be:a0:ba:ea: + d0:e4:3a:39:a8:bb:55:60:b8:28:3a:d1:a3:07:50:51: + f5:80:2b:f4:5a:82:1b:7d:56:a9:31:04:23:b1:34:d2: + 71:d5:1c:92:82:d5:b6:fc:74:86:06:6a:f1:e8:72:d1 + Exponent: 65537 + X509v3 extensions (critical: 0x208): + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: 0x4 + X509v3 Extended Key Usage: 0x0 + X509v3 Subject Key Identifier: + f4:9f:e9:91:43:ac:1c:9b:dd:07:40:2d:69:67:3c:ef: + d4:ea:db:54 + X509v3 Authority Key Identifier: + f4:9f:e9:91:43:ac:1c:9b:dd:07:40:2d:69:67:3c:ef: + d4:ea:db:54 + Signature Algorithm: sha256WithRSAEncryption + 80:61:52:61:22:4d:fc:47:cf:56:08:cd:b0:13:b5:ad: + 3b:b6:0a:71:57:c2:c0:fe:01:ff:89:60:18:68:ee:e0: + 81:1e:9c:43:4b:31:a6:5b:c8:25:84:4b:11:2a:5e:fa: + a7:bf:67:8e:3a:cf:8f:6e:ea:3a:ef:da:c4:32:61:a9: + 5d:2b:8b:f4:8b:2b:8a:d1:9d:18:d7:0f:d2:9b:e1:fa: + 00:af:d6:fe:ff:47:1d:7a:55:e9:83:3e:ca:ef:4b:0d: + e8:2c:42:f6:bf:6d:81:0a:52:af:a9:e3:f9:19:c9:56: + 40:5d:58:1e:f1:fe:37:8e:50:17:fa:0f:66:9c:91:8e: + 88:e7:5c:c9:30:8c:35:16:92:70:7a:34:aa:c4:f0:ba: + 90:15:47:2c:af:ae:86:0c:b5:95:e5:28:62:a3:20:56: + bf:b7:1a:4b:4f:e9:f3:c4:18:f0:bf:c3:d3:7a:cf:e9: + 40:9f:88:88:60:75:6b:98:b5:3d:ab:30:ca:5b:95:c7: + a2:f8:66:47:03:71:89:c0:57:f2:eb:b3:a9:49:f2:10: + fe:a8:7d:6b:90:66:f8:9f:46:9f:b4:2c:5f:e3:15:f7: + d3:44:d7:e9:17:3d:51:19:8c:2e:4d:b1:cb:37:70:94: + 56:28:8c:c5:6c:93:13:b3:eb:1a:0c:70:4e:d4:35:2f +*/ +#define RSA2048CA_SIZE 1048 +const static unsigned char RSA2048CA[RSA2048CA_SIZE] = + "\x30\x82\x04\x14\x30\x82\x02\xfc\xa0\x03\x02\x01\x02\x02\x06\x32" + "\x33\x34\x35\x36\x37\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01" + "\x01\x0b\x05\x00\x30\x81\x96\x31\x35\x30\x33\x06\x03\x55\x04\x03" + "\x0c\x2c\x53\x61\x6d\x70\x6c\x65\x20\x4d\x61\x74\x72\x69\x78\x20" + "\x52\x53\x41\x2d\x32\x30\x34\x38\x20\x43\x65\x72\x74\x69\x66\x69" + "\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x0b" + "\x30\x09\x06\x03\x55\x04\x06\x0c\x02\x55\x53\x31\x0b\x30\x09\x06" + "\x03\x55\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04" + "\x07\x0c\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06\x03" + "\x55\x04\x0a\x0c\x19\x49\x4e\x53\x49\x44\x45\x20\x53\x65\x63\x75" + "\x72\x65\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d" + "\x30\x0b\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x30\x1e\x17" + "\x0d\x31\x34\x30\x33\x32\x34\x31\x36\x32\x37\x30\x33\x5a\x17\x0d" + "\x31\x37\x30\x33\x32\x33\x31\x36\x32\x37\x30\x33\x5a\x30\x81\x96" + "\x31\x35\x30\x33\x06\x03\x55\x04\x03\x0c\x2c\x53\x61\x6d\x70\x6c" + "\x65\x20\x4d\x61\x74\x72\x69\x78\x20\x52\x53\x41\x2d\x32\x30\x34" + "\x38\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75" + "\x74\x68\x6f\x72\x69\x74\x79\x31\x0b\x30\x09\x06\x03\x55\x04\x06" + "\x0c\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x57" + "\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c\x07\x53\x65\x61\x74" + "\x74\x6c\x65\x31\x22\x30\x20\x06\x03\x55\x04\x0a\x0c\x19\x49\x4e" + "\x53\x49\x44\x45\x20\x53\x65\x63\x75\x72\x65\x20\x43\x6f\x72\x70" + "\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30\x0b\x06\x03\x55\x04\x0b" + "\x0c\x04\x54\x65\x73\x74\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86" + "\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82" + "\x01\x0a\x02\x82\x01\x01\x00\xcc\xab\x5b\x40\x3b\x0a\x4b\xc0\x83" + "\x5c\x68\xe5\xf4\x00\x5a\x15\x1a\xe3\x78\xf3\xa0\x41\x23\x93\x5a" + "\xc1\xc6\xfa\x04\x90\xa3\x45\x8e\x30\x5c\x91\x8a\x6d\x84\xbf\x78" + "\xc0\xcb\xb1\xee\x65\xaf\xaa\x5d\xba\xf1\x35\x04\xb5\x40\x94\xed" + "\xbc\x8c\xf5\xeb\xa1\xbb\x8f\xa2\xfa\xb7\xaa\xec\x53\x77\x8b\xaf" + "\xb6\xd1\x78\xf1\x58\x59\x00\x6c\x8f\x98\x44\x1d\x73\x4c\xe1\x1a" + "\x8a\xb0\x61\x80\xdd\xc0\xdf\x9b\x74\x5f\xd0\x7c\x66\x66\x23\xdc" + "\x30\x9c\x4d\xe0\xec\xda\x6e\x04\xc4\xc8\x62\xa2\x21\x11\xef\x28" + "\xdc\x6d\xe9\x31\xb7\x7a\x9e\xca\xdb\xba\xc2\x9c\x93\x1e\x24\xa9" + "\x9a\x74\xbe\xa4\x26\x4e\xbb\x5f\x79\x04\xd3\x41\x72\x05\xa2\x53" + "\x9a\x44\x20\x01\x48\x44\x5d\x33\x72\x63\x3f\xaa\xa2\x77\x09\xf5" + "\xc3\xe2\x26\xb5\x12\x87\x21\xad\x4a\xe7\x99\x99\xef\x3d\xb2\xfa" + "\xbd\xb2\xc2\x6a\xce\xa6\x3a\x85\x7a\x3f\x20\x94\xba\x15\x7f\x7a" + "\x82\xe9\x6f\xbe\xa0\xba\xea\xd0\xe4\x3a\x39\xa8\xbb\x55\x60\xb8" + "\x28\x3a\xd1\xa3\x07\x50\x51\xf5\x80\x2b\xf4\x5a\x82\x1b\x7d\x56" + "\xa9\x31\x04\x23\xb1\x34\xd2\x71\xd5\x1c\x92\x82\xd5\xb6\xfc\x74" + "\x86\x06\x6a\xf1\xe8\x72\xd1\x02\x03\x01\x00\x01\xa3\x66\x30\x64" + "\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01" + "\xff\x02\x01\x00\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xf4" + "\x9f\xe9\x91\x43\xac\x1c\x9b\xdd\x07\x40\x2d\x69\x67\x3c\xef\xd4" + "\xea\xdb\x54\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14" + "\xf4\x9f\xe9\x91\x43\xac\x1c\x9b\xdd\x07\x40\x2d\x69\x67\x3c\xef" + "\xd4\xea\xdb\x54\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04" + "\x03\x02\x00\x04\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01" + "\x0b\x05\x00\x03\x82\x01\x01\x00\x80\x61\x52\x61\x22\x4d\xfc\x47" + "\xcf\x56\x08\xcd\xb0\x13\xb5\xad\x3b\xb6\x0a\x71\x57\xc2\xc0\xfe" + "\x01\xff\x89\x60\x18\x68\xee\xe0\x81\x1e\x9c\x43\x4b\x31\xa6\x5b" + "\xc8\x25\x84\x4b\x11\x2a\x5e\xfa\xa7\xbf\x67\x8e\x3a\xcf\x8f\x6e" + "\xea\x3a\xef\xda\xc4\x32\x61\xa9\x5d\x2b\x8b\xf4\x8b\x2b\x8a\xd1" + "\x9d\x18\xd7\x0f\xd2\x9b\xe1\xfa\x00\xaf\xd6\xfe\xff\x47\x1d\x7a" + "\x55\xe9\x83\x3e\xca\xef\x4b\x0d\xe8\x2c\x42\xf6\xbf\x6d\x81\x0a" + "\x52\xaf\xa9\xe3\xf9\x19\xc9\x56\x40\x5d\x58\x1e\xf1\xfe\x37\x8e" + "\x50\x17\xfa\x0f\x66\x9c\x91\x8e\x88\xe7\x5c\xc9\x30\x8c\x35\x16" + "\x92\x70\x7a\x34\xaa\xc4\xf0\xba\x90\x15\x47\x2c\xaf\xae\x86\x0c" + "\xb5\x95\xe5\x28\x62\xa3\x20\x56\xbf\xb7\x1a\x4b\x4f\xe9\xf3\xc4" + "\x18\xf0\xbf\xc3\xd3\x7a\xcf\xe9\x40\x9f\x88\x88\x60\x75\x6b\x98" + "\xb5\x3d\xab\x30\xca\x5b\x95\xc7\xa2\xf8\x66\x47\x03\x71\x89\xc0" + "\x57\xf2\xeb\xb3\xa9\x49\xf2\x10\xfe\xa8\x7d\x6b\x90\x66\xf8\x9f" + "\x46\x9f\xb4\x2c\x5f\xe3\x15\xf7\xd3\x44\xd7\xe9\x17\x3d\x51\x19" + "\x8c\x2e\x4d\xb1\xcb\x37\x70\x94\x56\x28\x8c\xc5\x6c\x93\x13\xb3" + "\xeb\x1a\x0c\x70\x4e\xd4\x35\x2f"; diff --git a/testkeys/RSA/2048_RSA_CA.pem b/testkeys/RSA/2048_RSA_CA.pem new file mode 100644 index 0000000..84ea095 --- /dev/null +++ b/testkeys/RSA/2048_RSA_CA.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEFDCCAvygAwIBAgIGMjM0NTY3MA0GCSqGSIb3DQEBCwUAMIGWMTUwMwYDVQQD +DCxTYW1wbGUgTWF0cml4IFJTQS0yMDQ4IENlcnRpZmljYXRlIEF1dGhvcml0eTEL +MAkGA1UEBgwCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMSIwIAYD +VQQKDBlJTlNJREUgU2VjdXJlIENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MB4X +DTE0MDMyNDE2MjcwM1oXDTE3MDMyMzE2MjcwM1owgZYxNTAzBgNVBAMMLFNhbXBs +ZSBNYXRyaXggUlNBLTIwNDggQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQswCQYDVQQG +DAJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUlO +U0lERSBTZWN1cmUgQ29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMq1tAOwpLwINcaOX0AFoVGuN486BBI5Na +wcb6BJCjRY4wXJGKbYS/eMDLse5lr6pduvE1BLVAlO28jPXrobuPovq3quxTd4uv +ttF48VhZAGyPmEQdc0zhGoqwYYDdwN+bdF/QfGZmI9wwnE3g7NpuBMTIYqIhEe8o +3G3pMbd6nsrbusKckx4kqZp0vqQmTrtfeQTTQXIFolOaRCABSERdM3JjP6qidwn1 +w+ImtRKHIa1K55mZ7z2y+r2ywmrOpjqFej8glLoVf3qC6W++oLrq0OQ6Oai7VWC4 +KDrRowdQUfWAK/Raght9VqkxBCOxNNJx1RySgtW2/HSGBmrx6HLRAgMBAAGjZjBk +MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFPSf6ZFDrByb3QdALWlnPO/U +6ttUMB8GA1UdIwQYMBaAFPSf6ZFDrByb3QdALWlnPO/U6ttUMA4GA1UdDwEB/wQE +AwIABDANBgkqhkiG9w0BAQsFAAOCAQEAgGFSYSJN/EfPVgjNsBO1rTu2CnFXwsD+ +Af+JYBho7uCBHpxDSzGmW8glhEsRKl76p79njjrPj27qOu/axDJhqV0ri/SLK4rR +nRjXD9Kb4foAr9b+/0cdelXpgz7K70sN6CxC9r9tgQpSr6nj+RnJVkBdWB7x/jeO +UBf6D2ackY6I51zJMIw1FpJwejSqxPC6kBVHLK+uhgy1leUoYqMgVr+3GktP6fPE +GPC/w9N6z+lAn4iIYHVrmLU9qzDKW5XHovhmRwNxicBX8uuzqUnyEP6ofWuQZvif +Rp+0LF/jFffTRNfpFz1RGYwuTbHLN3CUViiMxWyTE7PrGgxwTtQ1Lw== +-----END CERTIFICATE----- diff --git a/testkeys/RSA/2048_RSA_KEY.h b/testkeys/RSA/2048_RSA_KEY.h new file mode 100644 index 0000000..774ad7b --- /dev/null +++ b/testkeys/RSA/2048_RSA_KEY.h @@ -0,0 +1,86 @@ +/** + * @file testkeys/RSA/2048_RSA_KEY.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated private key as binary DER. +*/ +#define RSA2048KEY_SIZE 1191 +const static unsigned char RSA2048KEY[RSA2048KEY_SIZE] = + "\x30\x82\x04\xa3\x02\x01\x00\x02\x82\x01\x01\x00\xad\x6a\x33\xee" + "\xa2\x73\x6d\x68\xba\xbd\x2d\xb1\xb5\x54\xf0\x04\x14\xff\xbd\xd7" + "\x5b\x4c\x69\xe7\xf4\x66\x7f\xac\x06\xe1\x95\x77\x6b\x9d\x9a\x1f" + "\x51\x61\xe6\xd2\x92\x50\xdc\x0f\x5d\x15\x0c\x9e\xd3\x37\xa6\xf9" + "\x77\x36\x76\x74\xda\x3f\x50\x7f\x9c\xdf\x52\xc9\x32\x4c\xda\x22" + "\x31\xeb\x94\xb0\xcf\x56\xee\x91\x86\x30\xa9\x24\x29\x01\x2f\x83" + "\xd1\x08\x73\x94\x97\xe1\xdb\x88\x85\x3b\xe1\x46\x2b\xc5\xff\x03" + "\xea\x7c\x74\xa6\x89\x64\x41\xcc\x88\xe7\x9c\xaf\x33\xfb\x48\xe7" + "\x5b\xca\x6f\x90\x75\x7a\x42\xa2\xba\x8a\x4e\x06\x38\x87\x51\x66" + "\x96\xc1\xef\x8a\xe2\xb2\xe7\x63\x57\xf4\xfa\xf8\xa6\x4d\x4d\x43" + "\x28\xac\x3a\x4c\xee\x33\x5d\xf1\x21\x0d\xd4\xfc\x9e\x23\xf0\x29" + "\xd8\xf6\x55\x66\x36\x1a\x29\x7a\x6d\x33\x2f\x0d\x30\x72\xf8\xb4" + "\x2b\x7f\xe9\x61\x75\x49\xdd\xfd\x3b\x2c\x29\xdf\x7b\xb1\x96\x32" + "\x0c\x98\xc4\x36\x3c\xd8\x0c\x82\xd3\xc7\xf4\xf0\xf4\xc4\xe2\x7c" + "\xd4\x56\xae\x74\x60\xfc\xc2\xe9\x44\xda\xf4\x74\x12\x05\x6a\x4f" + "\xbc\xba\xbb\x4c\x04\xaa\x43\x9d\x50\x88\xa7\xa2\x38\x73\x5a\x01" + "\x01\x40\xcd\xd2\x7c\x79\xc8\x78\xdc\x26\x44\xe5\x02\x03\x01\x00" + "\x01\x02\x82\x01\x00\x1d\xde\x65\x03\x7d\x47\x94\x58\xad\x91\x58" + "\x05\x7b\xce\x1d\x69\x16\x94\xd6\x05\xf9\xdb\xb7\x82\x14\x3e\x73" + "\x4f\x16\x00\x54\xd6\x34\xda\xf8\x68\xdc\x83\x98\x56\x3c\x8d\x60" + "\xd9\xe4\x96\x73\x8e\x07\xa3\x56\x47\x31\x99\x57\xdd\xd8\x99\x7f" + "\x2b\xfb\xc1\x1b\x69\x3c\x18\xb0\x99\xa3\x2f\x88\x74\xcb\xc1\x95" + "\x65\xcb\x4f\x26\x52\xec\x1d\x20\x29\xfc\x1f\x10\x89\x4f\x7f\xbf" + "\x68\x4c\x4a\x7c\x0a\xb2\x0f\x70\x55\x24\x56\x3b\x61\x53\xd8\xc8" + "\xdc\x89\xd8\x1a\xcc\xb2\x8f\x5d\x87\x3b\xf0\x2a\x37\x1f\x84\xe7" + "\x65\x4f\xeb\xf2\x74\x27\x2b\x58\x2f\x75\x18\xb6\xf8\x45\x6b\xc5" + "\x82\x31\x5a\x44\xd3\x09\x13\xf9\x5b\xd7\x41\x7f\x20\x88\x96\xc6" + "\x14\x72\x81\x83\x70\x42\xd1\xb4\x2c\x47\xd2\x4e\xbf\x31\xac\x98" + "\x2b\xe2\xcc\x8d\x1f\x54\xfe\x2d\x8e\x31\xbb\x5a\x0c\x6f\x6f\x94" + "\x8c\x8d\x36\x7e\x85\xf3\x16\xf0\x87\x69\x4e\x66\x19\x8b\xcf\x60" + "\x5d\x5d\xa9\x33\xb6\x52\x89\xdf\x54\xf6\x23\x93\x0f\x9d\x12\x51" + "\x79\x78\x72\x5f\xe8\x25\x8e\xae\xa2\x1e\x7e\xd4\x67\xcf\xe6\x10" + "\x74\xa3\x05\x31\x7e\xb5\xa8\x9d\xbf\xab\x6d\xe6\x76\x2e\xce\xcf" + "\x3a\xe8\xc7\xbd\x21\x02\x81\x81\x00\xdd\xaf\xe7\xc0\xac\xe9\x31" + "\x52\x30\x2b\x87\x58\x86\xfa\x11\xd2\xd6\xe3\x4c\x7f\x72\x19\xf9" + "\x67\x5d\x3c\xa2\x8b\x20\xce\x21\x0c\x5c\x68\x0d\x64\x49\x5a\x5c" + "\xd4\x6e\x46\x14\xfc\x0c\xb9\xec\xc0\x81\x3c\xe9\x82\xd4\x6d\x71" + "\x51\x77\x48\x1c\xf1\xa0\xd0\x8d\xb7\xde\x98\xdd\x80\x29\x44\x68" + "\xce\x86\xf6\xb2\xff\x78\xb2\xcd\xa0\x11\x01\x84\xef\x3c\xb7\x2d" + "\x59\xdc\xea\x2b\x4d\x19\x8a\x14\x2e\xb3\x4e\xd8\x77\x58\x66\x2d" + "\xb2\xae\x9b\xdb\xb1\x9e\x87\xbe\x99\x01\x4d\x8a\x8f\xcc\xff\x06" + "\xd9\x5e\xe5\xa0\xc2\xb1\xc8\x35\x6b\x02\x81\x81\x00\xc8\x41\x90" + "\x97\xa4\x5a\xbc\xbf\x66\xc7\xb7\x89\xd8\x22\xdd\xf5\xc7\x45\xa9" + "\x51\x94\x28\xe0\xdf\x95\xe0\xcf\x19\xf7\xc4\x8e\xb4\x6c\x81\xd9" + "\xbe\xf0\x58\x25\xe4\xaf\x6e\x41\x4b\xdf\x1a\x5f\x3d\x93\xdf\x18" + "\x87\x2c\x66\x91\x49\x4a\x7a\xdc\x2a\x96\x7a\x8c\xd0\x4e\xf8\x58" + "\x35\xed\xb8\x85\x51\x2b\x6d\x51\xf7\x84\x4c\xd2\x6a\xb1\x52\x1c" + "\x15\x2d\xd6\x16\x87\xea\x89\xa4\xf3\x36\x7a\x3c\x04\xa8\x09\xc0" + "\x74\x7c\xfb\xc4\x6c\x0f\xe3\xf1\x62\x74\x46\x7a\x46\x32\x15\x39" + "\x07\x67\x1c\xe7\x5b\x54\xfb\xcc\x0c\xb5\x48\xb2\xef\x02\x81\x80" + "\x71\xba\x2d\x45\x5e\x2f\x5f\x7b\x0f\x75\x35\x41\x08\x35\xbf\xf1" + "\x0f\x06\x9a\x97\x03\x1d\x2a\x22\x89\xe5\x72\x69\xb7\x91\xa7\xc8" + "\xa4\x9b\x48\xcb\x7b\x0a\x1d\x77\x69\x7f\x10\x82\xe1\xb0\x7c\x31" + "\xa1\xdb\x72\xdc\x08\x48\x81\x0a\xcf\x0b\xb2\xb5\x8e\xcf\x8e\xf4" + "\x96\x00\x8c\x19\x94\x92\x20\xc6\x5a\xdc\xb2\xa5\x76\xf1\x1b\xa6" + "\x13\x33\x59\x54\x36\x2c\xae\xda\x5c\x07\xd1\xe1\x02\xca\x20\x62" + "\x78\xe0\x69\x12\x88\xca\x1a\x85\x81\x28\x3a\x03\x9c\x15\x7d\x85" + "\x16\xf3\x05\xb3\x91\xf1\xff\x3c\x82\x7f\x81\x02\x80\x9b\xfa\x33" + "\x02\x81\x80\x5c\x83\x0d\x8d\x40\x7c\x3a\x9e\x21\x99\x3a\x0d\x10" + "\x30\x6b\x61\xd3\xc1\x36\xcb\x5d\x2a\xd5\x57\xf5\x21\x7a\x0b\x81" + "\x0e\xe8\xee\x29\x02\x83\xd9\x55\xa7\x23\x3a\x56\x61\x15\x01\x3b" + "\xfc\x2e\xeb\x7f\x98\x9c\xf8\x35\x66\xdc\xcf\x82\xfc\xe7\x21\x35" + "\x8b\x3f\xea\x2b\xd1\x46\xcf\x03\x17\x2f\x5f\xa4\x34\x48\x9d\x94" + "\x1c\xf9\x48\x18\xca\xd9\xf6\x5e\xca\x7c\x76\x25\xbf\x98\xd8\x52" + "\xde\x7d\x43\x99\x6d\x87\xdf\x48\xad\xf6\xbc\x05\x4b\x44\x84\x3b" + "\x3b\x23\xd9\xb1\xe1\x64\x0b\x2b\x73\x8a\xde\x02\x90\xa0\x5f\x6e" + "\x90\x3b\x39\x02\x81\x81\x00\xc0\x61\x4e\xb6\xf2\x3f\x9a\x4c\xf0" + "\x0f\x4f\x72\x3a\x14\x9c\x91\xc8\xbd\xe6\x72\x5d\x82\x79\xf2\xfd" + "\xdb\xee\x6c\x42\xe8\x41\xc5\x5f\x5c\xb1\x83\x87\x03\xc9\x5e\xa9" + "\xb1\x99\x86\xf2\x06\xd8\x97\xd2\xa0\x40\x12\x4a\x89\xec\xc4\xdc" + "\xa5\x95\x33\xaa\x18\x9a\x39\xb1\x5e\xdb\x5f\x03\x37\xc2\x99\x4f" + "\xe1\xf5\x38\xb0\x67\xf3\x8d\xf5\x98\x1e\x29\x54\x4e\x36\x9d\x7b" + "\x5c\x78\x7f\xcb\xce\x32\x57\xf7\x6a\xd2\x32\x0f\x4f\x8c\xbe\xc1" + "\xd5\xa2\xd3\xba\xe4\x2d\x14\x9e\x02\x11\xce\x52\x7b\xbf\x33\x42" + "\xb4\xff\xbc\x8a\x74\xcf\x47"; diff --git a/testkeys/RSA/2048_RSA_KEY.pem b/testkeys/RSA/2048_RSA_KEY.pem new file mode 100644 index 0000000..a6973e3 --- /dev/null +++ b/testkeys/RSA/2048_RSA_KEY.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEArWoz7qJzbWi6vS2xtVTwBBT/vddbTGnn9GZ/rAbhlXdrnZof +UWHm0pJQ3A9dFQye0zem+Xc2dnTaP1B/nN9SyTJM2iIx65Swz1bukYYwqSQpAS+D +0QhzlJfh24iFO+FGK8X/A+p8dKaJZEHMiOecrzP7SOdbym+QdXpCorqKTgY4h1Fm +lsHviuKy52NX9Pr4pk1NQyisOkzuM13xIQ3U/J4j8CnY9lVmNhopem0zLw0wcvi0 +K3/pYXVJ3f07LCnfe7GWMgyYxDY82AyC08f08PTE4nzUVq50YPzC6UTa9HQSBWpP +vLq7TASqQ51QiKeiOHNaAQFAzdJ8ech43CZE5QIDAQABAoIBAB3eZQN9R5RYrZFY +BXvOHWkWlNYF+du3ghQ+c08WAFTWNNr4aNyDmFY8jWDZ5JZzjgejVkcxmVfd2Jl/ +K/vBG2k8GLCZoy+IdMvBlWXLTyZS7B0gKfwfEIlPf79oTEp8CrIPcFUkVjthU9jI +3InYGsyyj12HO/AqNx+E52VP6/J0JytYL3UYtvhFa8WCMVpE0wkT+VvXQX8giJbG +FHKBg3BC0bQsR9JOvzGsmCvizI0fVP4tjjG7Wgxvb5SMjTZ+hfMW8IdpTmYZi89g +XV2pM7ZSid9U9iOTD50SUXl4cl/oJY6uoh5+1GfP5hB0owUxfrWonb+rbeZ2Ls7P +OujHvSECgYEA3a/nwKzpMVIwK4dYhvoR0tbjTH9yGflnXTyiiyDOIQxcaA1kSVpc +1G5GFPwMuezAgTzpgtRtcVF3SBzxoNCNt96Y3YApRGjOhvay/3iyzaARAYTvPLct +WdzqK00ZihQus07Yd1hmLbKum9uxnoe+mQFNio/M/wbZXuWgwrHINWsCgYEAyEGQ +l6RavL9mx7eJ2CLd9cdFqVGUKODfleDPGffEjrRsgdm+8Fgl5K9uQUvfGl89k98Y +hyxmkUlKetwqlnqM0E74WDXtuIVRK21R94RM0mqxUhwVLdYWh+qJpPM2ejwEqAnA +dHz7xGwP4/FidEZ6RjIVOQdnHOdbVPvMDLVIsu8CgYBxui1FXi9few91NUEINb/x +DwaalwMdKiKJ5XJpt5GnyKSbSMt7Ch13aX8QguGwfDGh23LcCEiBCs8LsrWOz470 +lgCMGZSSIMZa3LKldvEbphMzWVQ2LK7aXAfR4QLKIGJ44GkSiMoahYEoOgOcFX2F +FvMFs5Hx/zyCf4ECgJv6MwKBgFyDDY1AfDqeIZk6DRAwa2HTwTbLXSrVV/UheguB +DujuKQKD2VWnIzpWYRUBO/wu63+YnPg1ZtzPgvznITWLP+or0UbPAxcvX6Q0SJ2U +HPlIGMrZ9l7KfHYlv5jYUt59Q5lth99Irfa8BUtEhDs7I9mx4WQLK3OK3gKQoF9u +kDs5AoGBAMBhTrbyP5pM8A9PcjoUnJHIveZyXYJ58v3b7mxC6EHFX1yxg4cDyV6p +sZmG8gbYl9KgQBJKiezE3KWVM6oYmjmxXttfAzfCmU/h9TiwZ/ON9ZgeKVRONp17 +XHh/y84yV/dq0jIPT4y+wdWi07rkLRSeAhHOUnu/M0K0/7yKdM9H +-----END RSA PRIVATE KEY----- diff --git a/testkeys/RSA/3072_RSA.h b/testkeys/RSA/3072_RSA.h new file mode 100644 index 0000000..270f505 --- /dev/null +++ b/testkeys/RSA/3072_RSA.h @@ -0,0 +1,96 @@ +#define RSA3072_SIZE 1217 +const unsigned char RSA3072[] = { +48, 130, 4, 189, 48, 130, 3, 37, 160, 3, 2, 1, 2, +2, 9, 0, 183, 93, 196, 185, 117, 17, 179, 236, 48, 13, +6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, +48, 98, 49, 37, 48, 35, 6, 3, 85, 4, 3, 12, 28, +84, 101, 115, 116, 32, 83, 101, 114, 118, 101, 114, 32, 67, +65, 32, 99, 101, 114, 116, 32, 119, 105, 116, 104, 32, 82, +83, 65, 49, 17, 48, 15, 6, 3, 85, 4, 8, 12, 8, +72, 101, 108, 115, 105, 110, 107, 105, 49, 11, 48, 9, 6, +3, 85, 4, 6, 19, 2, 70, 73, 49, 25, 48, 23, 6, +3, 85, 4, 10, 12, 16, 73, 78, 83, 73, 68, 69, 32, +83, 101, 99, 117, 114, 101, 32, 79, 121, 48, 30, 23, 13, +49, 53, 49, 50, 49, 55, 48, 49, 50, 53, 53, 50, 90, +23, 13, 50, 53, 49, 50, 49, 52, 48, 49, 50, 53, 53, +50, 90, 48, 95, 49, 34, 48, 32, 6, 3, 85, 4, 3, +12, 25, 84, 101, 115, 116, 32, 83, 101, 114, 118, 101, 114, +32, 99, 101, 114, 116, 32, 119, 105, 116, 104, 32, 82, 83, +65, 49, 17, 48, 15, 6, 3, 85, 4, 8, 12, 8, 72, +101, 108, 115, 105, 110, 107, 105, 49, 11, 48, 9, 6, 3, +85, 4, 6, 19, 2, 70, 73, 49, 25, 48, 23, 6, 3, +85, 4, 10, 12, 16, 73, 78, 83, 73, 68, 69, 32, 83, +101, 99, 117, 114, 101, 32, 79, 121, 48, 130, 1, 162, 48, +13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, +0, 3, 130, 1, 143, 0, 48, 130, 1, 138, 2, 130, 1, +129, 0, 199, 146, 213, 117, 21, 230, 9, 166, 241, 115, 32, +54, 223, 33, 236, 155, 173, 175, 141, 230, 255, 113, 17, 191, +255, 142, 72, 87, 137, 234, 56, 41, 239, 92, 149, 82, 185, +228, 99, 82, 68, 95, 191, 167, 61, 30, 195, 246, 106, 210, +120, 19, 131, 44, 174, 88, 55, 218, 147, 97, 81, 161, 25, +35, 153, 202, 179, 20, 227, 175, 76, 243, 195, 184, 254, 78, +216, 24, 51, 161, 26, 224, 104, 229, 229, 208, 190, 87, 232, +137, 135, 250, 198, 45, 175, 70, 63, 33, 69, 43, 162, 175, +98, 128, 231, 94, 47, 22, 197, 206, 175, 201, 111, 200, 216, +70, 120, 252, 36, 203, 74, 63, 152, 189, 22, 64, 64, 122, +181, 146, 53, 215, 153, 241, 126, 44, 210, 140, 4, 58, 172, +57, 69, 142, 11, 58, 93, 206, 124, 146, 150, 134, 39, 237, +38, 11, 241, 141, 199, 152, 227, 133, 69, 200, 105, 24, 183, +218, 78, 184, 179, 198, 7, 39, 178, 116, 245, 30, 48, 131, +121, 81, 62, 74, 27, 50, 11, 239, 61, 63, 136, 250, 31, +57, 237, 73, 166, 66, 213, 31, 39, 144, 61, 199, 51, 15, +145, 121, 83, 38, 211, 66, 91, 193, 146, 44, 41, 157, 36, +50, 96, 255, 14, 10, 240, 242, 187, 159, 130, 161, 173, 244, +169, 35, 240, 59, 207, 40, 158, 142, 14, 78, 96, 24, 219, +2, 112, 182, 224, 107, 156, 208, 210, 71, 216, 50, 92, 171, +142, 111, 222, 56, 221, 193, 111, 65, 78, 132, 130, 244, 97, +85, 58, 177, 179, 124, 53, 120, 192, 135, 45, 117, 32, 43, +33, 36, 50, 7, 196, 51, 85, 238, 109, 117, 69, 174, 116, +170, 14, 32, 172, 125, 147, 30, 166, 4, 166, 250, 83, 216, +238, 149, 73, 39, 80, 232, 150, 79, 165, 166, 38, 176, 167, +132, 41, 234, 124, 42, 142, 162, 57, 201, 141, 181, 144, 178, +173, 11, 219, 32, 195, 224, 137, 17, 17, 97, 212, 80, 152, +89, 119, 252, 243, 172, 136, 68, 162, 0, 95, 225, 115, 74, +177, 12, 34, 237, 198, 76, 55, 58, 5, 38, 227, 20, 96, +135, 131, 45, 84, 134, 135, 224, 195, 77, 2, 3, 1, 0, +1, 163, 121, 48, 119, 48, 9, 6, 3, 85, 29, 19, 4, +2, 48, 0, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, +20, 173, 122, 217, 168, 200, 62, 56, 100, 213, 76, 104, 235, +239, 213, 115, 57, 11, 197, 34, 146, 48, 31, 6, 3, 85, +29, 35, 4, 24, 48, 22, 128, 20, 190, 37, 164, 180, 255, +204, 122, 161, 217, 46, 118, 184, 125, 119, 117, 228, 146, 163, +28, 102, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, +4, 3, 2, 2, 132, 48, 26, 6, 3, 85, 29, 17, 4, +19, 48, 17, 130, 9, 108, 111, 99, 97, 108, 104, 111, 115, +116, 135, 4, 127, 0, 0, 1, 48, 13, 6, 9, 42, 134, +72, 134, 247, 13, 1, 1, 11, 5, 0, 3, 130, 1, 129, +0, 73, 55, 76, 194, 157, 77, 215, 146, 251, 92, 236, 39, +204, 244, 102, 12, 184, 136, 152, 48, 148, 5, 175, 199, 174, +208, 214, 48, 77, 8, 30, 195, 18, 214, 41, 153, 227, 239, +141, 68, 54, 202, 223, 247, 222, 100, 195, 122, 66, 220, 177, +183, 19, 47, 190, 245, 49, 108, 37, 244, 151, 140, 111, 187, +250, 217, 245, 36, 95, 220, 251, 164, 193, 1, 32, 73, 210, +79, 87, 16, 30, 197, 160, 214, 50, 92, 67, 169, 197, 15, +2, 81, 160, 9, 135, 150, 52, 134, 81, 37, 248, 8, 179, +247, 96, 220, 141, 234, 44, 66, 15, 45, 22, 124, 38, 139, +173, 86, 100, 148, 242, 68, 11, 51, 18, 166, 0, 103, 155, +7, 248, 166, 173, 170, 33, 22, 181, 8, 254, 174, 250, 144, +11, 231, 25, 46, 68, 125, 128, 133, 4, 48, 215, 6, 103, +9, 126, 54, 107, 30, 223, 54, 141, 96, 74, 222, 83, 209, +173, 13, 174, 128, 23, 46, 130, 180, 68, 26, 110, 176, 115, +79, 18, 153, 222, 61, 141, 0, 198, 210, 9, 206, 213, 123, +195, 174, 77, 60, 30, 209, 228, 52, 195, 163, 54, 80, 147, +166, 26, 165, 169, 65, 136, 14, 21, 25, 121, 208, 67, 112, +7, 108, 157, 74, 252, 18, 44, 252, 184, 85, 113, 49, 180, +26, 197, 206, 22, 90, 101, 27, 94, 93, 204, 158, 244, 175, +97, 227, 158, 222, 53, 63, 202, 140, 199, 131, 254, 164, 220, +74, 246, 65, 46, 35, 156, 11, 226, 207, 77, 185, 21, 189, +153, 57, 122, 217, 240, 143, 91, 129, 34, 189, 100, 88, 163, +56, 23, 198, 24, 65, 118, 182, 165, 154, 86, 102, 144, 132, +2, 95, 3, 181, 181, 237, 123, 246, 156, 188, 45, 178, 212, +147, 205, 17, 146, 51, 220, 220, 204, 125, 52, 23, 44, 175, +219, 107, 187, 97, 16, 92, 148, 191, 94, 85, 61, 212, 107, +93, 146, 108, 40, 237, 35, 221, 172, 30, 160, 195, 15, 201, +53, 80, 44, 169, 182, 210, 210, 110, 38, 98, 226, 6, 77, +132, 138, 68, 13, 114, 22, 62, 126, 57, 216, 168, 248, 225, +110, 112, 241, 219, 156, 155, 61, 136}; diff --git a/testkeys/RSA/3072_RSA.pem b/testkeys/RSA/3072_RSA.pem new file mode 100644 index 0000000..acbb2a4 --- /dev/null +++ b/testkeys/RSA/3072_RSA.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEvTCCAyWgAwIBAgIJALddxLl1EbPsMA0GCSqGSIb3DQEBCwUAMGIxJTAjBgNV +BAMMHFRlc3QgU2VydmVyIENBIGNlcnQgd2l0aCBSU0ExETAPBgNVBAgMCEhlbHNp +bmtpMQswCQYDVQQGEwJGSTEZMBcGA1UECgwQSU5TSURFIFNlY3VyZSBPeTAeFw0x +NTEyMTcwMTI1NTJaFw0yNTEyMTQwMTI1NTJaMF8xIjAgBgNVBAMMGVRlc3QgU2Vy +dmVyIGNlcnQgd2l0aCBSU0ExETAPBgNVBAgMCEhlbHNpbmtpMQswCQYDVQQGEwJG +STEZMBcGA1UECgwQSU5TSURFIFNlY3VyZSBPeTCCAaIwDQYJKoZIhvcNAQEBBQAD +ggGPADCCAYoCggGBAMeS1XUV5gmm8XMgNt8h7Jutr43m/3ERv/+OSFeJ6jgp71yV +UrnkY1JEX7+nPR7D9mrSeBODLK5YN9qTYVGhGSOZyrMU469M88O4/k7YGDOhGuBo +5eXQvlfoiYf6xi2vRj8hRSuir2KA514vFsXOr8lvyNhGePwky0o/mL0WQEB6tZI1 +15nxfizSjAQ6rDlFjgs6Xc58kpaGJ+0mC/GNx5jjhUXIaRi32k64s8YHJ7J09R4w +g3lRPkobMgvvPT+I+h857UmmQtUfJ5A9xzMPkXlTJtNCW8GSLCmdJDJg/w4K8PK7 +n4KhrfSpI/A7zyiejg5OYBjbAnC24Guc0NJH2DJcq45v3jjdwW9BToSC9GFVOrGz +fDV4wIctdSArISQyB8QzVe5tdUWudKoOIKx9kx6mBKb6U9julUknUOiWT6WmJrCn +hCnqfCqOojnJjbWQsq0L2yDD4IkREWHUUJhZd/zzrIhEogBf4XNKsQwi7cZMNzoF +JuMUYIeDLVSGh+DDTQIDAQABo3kwdzAJBgNVHRMEAjAAMB0GA1UdDgQWBBStetmo +yD44ZNVMaOvv1XM5C8UikjAfBgNVHSMEGDAWgBS+JaS0/8x6odkudrh9d3XkkqMc +ZjAOBgNVHQ8BAf8EBAMCAoQwGgYDVR0RBBMwEYIJbG9jYWxob3N0hwR/AAABMA0G +CSqGSIb3DQEBCwUAA4IBgQBJN0zCnU3Xkvtc7CfM9GYMuIiYMJQFr8eu0NYwTQge +wxLWKZnj741ENsrf995kw3pC3LG3Ey++9TFsJfSXjG+7+tn1JF/c+6TBASBJ0k9X +EB7FoNYyXEOpxQ8CUaAJh5Y0hlEl+Aiz92DcjeosQg8tFnwmi61WZJTyRAszEqYA +Z5sH+KatqiEWtQj+rvqQC+cZLkR9gIUEMNcGZwl+Nmse3zaNYEreU9GtDa6AFy6C +tEQabrBzTxKZ3j2NAMbSCc7Ve8OuTTwe0eQ0w6M2UJOmGqWpQYgOFRl50ENwB2yd +SvwSLPy4VXExtBrFzhZaZRteXcye9K9h457eNT/KjMeD/qTcSvZBLiOcC+LPTbkV +vZk5etnwj1uBIr1kWKM4F8YYQXa2pZpWZpCEAl8DtbXte/acvC2y1JPNEZIz3NzM +fTQXLK/ba7thEFyUv15VPdRrXZJsKO0j3aweoMMPyTVQLKm20tJuJmLiBk2EikQN +chY+fjnYqPjhbnDx25ybPYg= +-----END CERTIFICATE----- diff --git a/testkeys/RSA/3072_RSA_CA.h b/testkeys/RSA/3072_RSA_CA.h new file mode 100644 index 0000000..dc35baa --- /dev/null +++ b/testkeys/RSA/3072_RSA_CA.h @@ -0,0 +1,94 @@ +#define RSA3072CA_SIZE 1193 +const unsigned char RSA3072CA[] = { +48, 130, 4, 165, 48, 130, 3, 13, 160, 3, 2, 1, 2, +2, 9, 0, 207, 212, 150, 54, 124, 90, 48, 139, 48, 13, +6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, +48, 96, 49, 35, 48, 33, 6, 3, 85, 4, 3, 12, 26, +84, 101, 115, 116, 32, 82, 111, 111, 116, 32, 67, 65, 32, +99, 101, 114, 116, 32, 119, 105, 116, 104, 32, 82, 83, 65, +49, 17, 48, 15, 6, 3, 85, 4, 8, 12, 8, 72, 101, +108, 115, 105, 110, 107, 105, 49, 11, 48, 9, 6, 3, 85, +4, 6, 19, 2, 70, 73, 49, 25, 48, 23, 6, 3, 85, +4, 10, 12, 16, 73, 78, 83, 73, 68, 69, 32, 83, 101, +99, 117, 114, 101, 32, 79, 121, 48, 30, 23, 13, 49, 53, +49, 50, 49, 55, 48, 49, 50, 53, 53, 50, 90, 23, 13, +50, 53, 49, 50, 49, 52, 48, 49, 50, 53, 53, 50, 90, +48, 98, 49, 37, 48, 35, 6, 3, 85, 4, 3, 12, 28, +84, 101, 115, 116, 32, 83, 101, 114, 118, 101, 114, 32, 67, +65, 32, 99, 101, 114, 116, 32, 119, 105, 116, 104, 32, 82, +83, 65, 49, 17, 48, 15, 6, 3, 85, 4, 8, 12, 8, +72, 101, 108, 115, 105, 110, 107, 105, 49, 11, 48, 9, 6, +3, 85, 4, 6, 19, 2, 70, 73, 49, 25, 48, 23, 6, +3, 85, 4, 10, 12, 16, 73, 78, 83, 73, 68, 69, 32, +83, 101, 99, 117, 114, 101, 32, 79, 121, 48, 130, 1, 162, +48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, +5, 0, 3, 130, 1, 143, 0, 48, 130, 1, 138, 2, 130, +1, 129, 0, 204, 66, 222, 95, 73, 247, 182, 252, 172, 199, +91, 247, 77, 104, 182, 184, 189, 104, 151, 103, 176, 226, 35, +191, 39, 211, 132, 146, 248, 147, 244, 75, 158, 62, 114, 180, +92, 47, 147, 28, 131, 72, 219, 239, 51, 113, 154, 160, 63, +100, 56, 80, 106, 59, 246, 7, 94, 87, 67, 23, 77, 146, +207, 38, 66, 134, 222, 164, 248, 137, 163, 48, 0, 101, 246, +167, 242, 23, 12, 168, 249, 168, 232, 217, 109, 66, 74, 250, +117, 191, 192, 100, 133, 249, 61, 10, 47, 54, 12, 199, 170, +184, 67, 110, 158, 198, 175, 227, 187, 170, 165, 45, 137, 2, +72, 5, 8, 164, 14, 206, 169, 252, 38, 91, 188, 224, 79, +42, 81, 54, 146, 19, 55, 204, 42, 151, 24, 107, 147, 168, +172, 48, 87, 127, 82, 15, 168, 43, 208, 181, 78, 126, 126, +129, 202, 2, 125, 207, 234, 155, 112, 231, 243, 4, 147, 193, +204, 99, 174, 189, 207, 7, 40, 10, 106, 44, 170, 13, 74, +92, 185, 217, 156, 96, 6, 193, 237, 176, 127, 79, 185, 58, +255, 44, 113, 49, 44, 150, 160, 216, 50, 206, 19, 86, 145, +187, 248, 136, 50, 108, 222, 215, 73, 77, 62, 131, 235, 183, +91, 177, 89, 68, 198, 138, 244, 208, 38, 77, 105, 34, 56, +83, 243, 144, 36, 227, 118, 0, 14, 209, 43, 91, 214, 201, +200, 64, 89, 254, 209, 78, 76, 226, 165, 96, 86, 129, 244, +164, 142, 191, 82, 224, 134, 68, 142, 247, 105, 40, 172, 117, +186, 70, 250, 13, 225, 118, 144, 26, 118, 190, 175, 58, 170, +195, 173, 244, 219, 229, 220, 220, 57, 155, 194, 19, 67, 253, +187, 103, 15, 94, 103, 167, 120, 227, 100, 158, 143, 71, 168, +223, 238, 13, 133, 117, 217, 211, 220, 184, 129, 7, 194, 195, +173, 193, 232, 124, 71, 35, 171, 91, 13, 83, 249, 231, 191, +244, 41, 3, 103, 24, 56, 208, 130, 105, 228, 80, 243, 55, +247, 196, 78, 127, 79, 198, 185, 244, 248, 229, 192, 84, 99, +251, 118, 215, 200, 122, 49, 62, 130, 184, 245, 213, 143, 41, +73, 82, 241, 86, 185, 26, 182, 229, 120, 241, 2, 3, 1, +0, 1, 163, 96, 48, 94, 48, 12, 6, 3, 85, 29, 19, +4, 5, 48, 3, 1, 1, 255, 48, 29, 6, 3, 85, 29, +14, 4, 22, 4, 20, 190, 37, 164, 180, 255, 204, 122, 161, +217, 46, 118, 184, 125, 119, 117, 228, 146, 163, 28, 102, 48, +31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 192, +149, 52, 26, 196, 246, 209, 110, 71, 39, 3, 59, 38, 0, +31, 108, 228, 107, 235, 216, 48, 14, 6, 3, 85, 29, 15, +1, 1, 255, 4, 4, 3, 2, 2, 132, 48, 13, 6, 9, +42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, 3, 130, +1, 129, 0, 102, 53, 89, 156, 251, 9, 41, 46, 235, 34, +109, 248, 71, 10, 60, 167, 188, 192, 210, 11, 61, 225, 218, +81, 5, 33, 82, 33, 208, 168, 187, 21, 84, 140, 101, 162, +12, 39, 189, 248, 89, 123, 40, 31, 90, 92, 226, 117, 19, +161, 156, 152, 208, 222, 112, 41, 51, 208, 237, 142, 122, 76, +246, 57, 213, 182, 198, 146, 60, 128, 32, 52, 34, 34, 82, +114, 164, 226, 143, 137, 25, 71, 159, 155, 26, 221, 80, 139, +76, 206, 167, 246, 216, 186, 85, 107, 172, 60, 154, 61, 240, +243, 18, 103, 81, 98, 105, 85, 223, 91, 71, 130, 87, 117, +50, 11, 167, 41, 245, 150, 176, 15, 236, 125, 232, 107, 252, +149, 151, 54, 131, 208, 218, 8, 157, 133, 113, 77, 142, 20, +33, 168, 122, 241, 239, 87, 138, 157, 232, 168, 218, 202, 27, +156, 37, 216, 210, 161, 177, 152, 9, 199, 201, 172, 141, 174, +130, 104, 72, 155, 213, 124, 165, 86, 203, 224, 114, 223, 223, +163, 193, 62, 50, 243, 169, 117, 44, 61, 160, 133, 26, 215, +20, 163, 195, 240, 15, 238, 129, 251, 8, 244, 249, 117, 244, +72, 139, 20, 48, 93, 124, 0, 87, 27, 74, 49, 134, 168, +121, 228, 78, 117, 106, 66, 104, 220, 217, 179, 63, 60, 172, +62, 141, 214, 86, 36, 53, 1, 45, 185, 237, 203, 253, 193, +117, 24, 75, 242, 71, 110, 152, 107, 145, 24, 223, 160, 205, +74, 182, 152, 202, 230, 122, 199, 89, 21, 88, 176, 54, 121, +18, 49, 34, 54, 51, 224, 59, 80, 249, 240, 105, 22, 20, +142, 60, 83, 136, 136, 87, 140, 220, 144, 121, 173, 136, 18, +123, 148, 119, 41, 135, 172, 253, 19, 141, 131, 17, 203, 139, +187, 71, 255, 94, 157, 228, 118, 72, 3, 63, 177, 178, 228, +158, 132, 182, 0, 253, 127, 185, 222, 171, 101, 0, 98, 139, +41, 89, 96, 121, 231, 122, 219, 129, 254, 248, 151, 223, 102, +134, 71, 43, 197, 20, 228, 28, 248, 154, 16, 52, 157, 199, +204, 77, 209, 118, 10, 211, 107, 127, 55, 47, 142, 155, 98, +107, 239, 183, 142, 108, 53, 226, 159, 26, 226}; diff --git a/testkeys/RSA/3072_RSA_CA.pem b/testkeys/RSA/3072_RSA_CA.pem new file mode 100644 index 0000000..9f4d189 --- /dev/null +++ b/testkeys/RSA/3072_RSA_CA.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEpTCCAw2gAwIBAgIJAM/UljZ8WjCLMA0GCSqGSIb3DQEBCwUAMGAxIzAhBgNV +BAMMGlRlc3QgUm9vdCBDQSBjZXJ0IHdpdGggUlNBMREwDwYDVQQIDAhIZWxzaW5r +aTELMAkGA1UEBhMCRkkxGTAXBgNVBAoMEElOU0lERSBTZWN1cmUgT3kwHhcNMTUx +MjE3MDEyNTUyWhcNMjUxMjE0MDEyNTUyWjBiMSUwIwYDVQQDDBxUZXN0IFNlcnZl +ciBDQSBjZXJ0IHdpdGggUlNBMREwDwYDVQQIDAhIZWxzaW5raTELMAkGA1UEBhMC +RkkxGTAXBgNVBAoMEElOU0lERSBTZWN1cmUgT3kwggGiMA0GCSqGSIb3DQEBAQUA +A4IBjwAwggGKAoIBgQDMQt5fSfe2/KzHW/dNaLa4vWiXZ7DiI78n04SS+JP0S54+ +crRcL5Mcg0jb7zNxmqA/ZDhQajv2B15XQxdNks8mQobepPiJozAAZfan8hcMqPmo +6NltQkr6db/AZIX5PQovNgzHqrhDbp7Gr+O7qqUtiQJIBQikDs6p/CZbvOBPKlE2 +khM3zCqXGGuTqKwwV39SD6gr0LVOfn6BygJ9z+qbcOfzBJPBzGOuvc8HKApqLKoN +Sly52ZxgBsHtsH9PuTr/LHExLJag2DLOE1aRu/iIMmze10lNPoPrt1uxWUTGivTQ +Jk1pIjhT85Ak43YADtErW9bJyEBZ/tFOTOKlYFaB9KSOv1LghkSO92korHW6RvoN +4XaQGna+rzqqw6302+Xc3DmbwhND/btnD15np3jjZJ6PR6jf7g2FddnT3LiBB8LD +rcHofEcjq1sNU/nnv/QpA2cYONCCaeRQ8zf3xE5/T8a59PjlwFRj+3bXyHoxPoK4 +9dWPKUlS8Va5GrblePECAwEAAaNgMF4wDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQU +viWktP/MeqHZLna4fXd15JKjHGYwHwYDVR0jBBgwFoAUwJU0GsT20W5HJwM7JgAf +bORr69gwDgYDVR0PAQH/BAQDAgKEMA0GCSqGSIb3DQEBCwUAA4IBgQBmNVmc+wkp +LusibfhHCjynvMDSCz3h2lEFIVIh0Ki7FVSMZaIMJ734WXsoH1pc4nUToZyY0N5w +KTPQ7Y56TPY51bbGkjyAIDQiIlJypOKPiRlHn5sa3VCLTM6n9ti6VWusPJo98PMS +Z1FiaVXfW0eCV3UyC6cp9ZawD+x96Gv8lZc2g9DaCJ2FcU2OFCGoevHvV4qd6Kja +yhucJdjSobGYCcfJrI2ugmhIm9V8pVbL4HLf36PBPjLzqXUsPaCFGtcUo8PwD+6B ++wj0+XX0SIsUMF18AFcbSjGGqHnkTnVqQmjc2bM/PKw+jdZWJDUBLbnty/3BdRhL +8kdumGuRGN+gzUq2mMrmesdZFViwNnkSMSI2M+A7UPnwaRYUjjxTiIhXjNyQea2I +EnuUdymHrP0TjYMRy4u7R/9eneR2SAM/sbLknoS2AP1/ud6rZQBiiylZYHnnetuB +/viX32aGRyvFFOQc+JoQNJ3HzE3RdgrTa383L46bYmvvt45sNeKfGuI= +-----END CERTIFICATE----- diff --git a/testkeys/RSA/3072_RSA_KEY.h b/testkeys/RSA/3072_RSA_KEY.h new file mode 100644 index 0000000..4e2be4c --- /dev/null +++ b/testkeys/RSA/3072_RSA_KEY.h @@ -0,0 +1,139 @@ +#define RSA3072KEY_SIZE 1769 +const unsigned char RSA3072KEY[] = { +48, 130, 6, 229, 2, 1, 0, 2, 130, 1, 129, 0, 199, +146, 213, 117, 21, 230, 9, 166, 241, 115, 32, 54, 223, 33, +236, 155, 173, 175, 141, 230, 255, 113, 17, 191, 255, 142, 72, +87, 137, 234, 56, 41, 239, 92, 149, 82, 185, 228, 99, 82, +68, 95, 191, 167, 61, 30, 195, 246, 106, 210, 120, 19, 131, +44, 174, 88, 55, 218, 147, 97, 81, 161, 25, 35, 153, 202, +179, 20, 227, 175, 76, 243, 195, 184, 254, 78, 216, 24, 51, +161, 26, 224, 104, 229, 229, 208, 190, 87, 232, 137, 135, 250, +198, 45, 175, 70, 63, 33, 69, 43, 162, 175, 98, 128, 231, +94, 47, 22, 197, 206, 175, 201, 111, 200, 216, 70, 120, 252, +36, 203, 74, 63, 152, 189, 22, 64, 64, 122, 181, 146, 53, +215, 153, 241, 126, 44, 210, 140, 4, 58, 172, 57, 69, 142, +11, 58, 93, 206, 124, 146, 150, 134, 39, 237, 38, 11, 241, +141, 199, 152, 227, 133, 69, 200, 105, 24, 183, 218, 78, 184, +179, 198, 7, 39, 178, 116, 245, 30, 48, 131, 121, 81, 62, +74, 27, 50, 11, 239, 61, 63, 136, 250, 31, 57, 237, 73, +166, 66, 213, 31, 39, 144, 61, 199, 51, 15, 145, 121, 83, +38, 211, 66, 91, 193, 146, 44, 41, 157, 36, 50, 96, 255, +14, 10, 240, 242, 187, 159, 130, 161, 173, 244, 169, 35, 240, +59, 207, 40, 158, 142, 14, 78, 96, 24, 219, 2, 112, 182, +224, 107, 156, 208, 210, 71, 216, 50, 92, 171, 142, 111, 222, +56, 221, 193, 111, 65, 78, 132, 130, 244, 97, 85, 58, 177, +179, 124, 53, 120, 192, 135, 45, 117, 32, 43, 33, 36, 50, +7, 196, 51, 85, 238, 109, 117, 69, 174, 116, 170, 14, 32, +172, 125, 147, 30, 166, 4, 166, 250, 83, 216, 238, 149, 73, +39, 80, 232, 150, 79, 165, 166, 38, 176, 167, 132, 41, 234, +124, 42, 142, 162, 57, 201, 141, 181, 144, 178, 173, 11, 219, +32, 195, 224, 137, 17, 17, 97, 212, 80, 152, 89, 119, 252, +243, 172, 136, 68, 162, 0, 95, 225, 115, 74, 177, 12, 34, +237, 198, 76, 55, 58, 5, 38, 227, 20, 96, 135, 131, 45, +84, 134, 135, 224, 195, 77, 2, 3, 1, 0, 1, 2, 130, +1, 129, 0, 151, 242, 82, 116, 175, 180, 145, 250, 185, 240, +70, 65, 160, 199, 42, 103, 40, 232, 245, 104, 63, 105, 237, +242, 185, 118, 177, 219, 124, 84, 136, 104, 93, 38, 167, 69, +241, 228, 82, 62, 107, 114, 94, 239, 204, 152, 36, 232, 243, +81, 197, 60, 77, 237, 241, 219, 150, 194, 226, 221, 0, 146, +96, 26, 123, 216, 25, 90, 185, 51, 89, 170, 106, 132, 233, +146, 75, 242, 185, 52, 90, 203, 42, 242, 134, 115, 212, 200, +7, 114, 214, 197, 246, 167, 7, 192, 187, 5, 240, 173, 21, +82, 228, 243, 113, 180, 130, 179, 154, 237, 15, 103, 149, 165, +92, 12, 227, 198, 77, 153, 61, 177, 135, 239, 199, 6, 42, +81, 130, 246, 139, 233, 215, 250, 70, 111, 135, 234, 52, 186, +27, 48, 11, 165, 231, 36, 140, 17, 79, 69, 40, 55, 130, +36, 139, 136, 34, 100, 40, 232, 93, 169, 181, 132, 173, 135, +181, 75, 16, 14, 142, 73, 34, 95, 117, 254, 152, 53, 97, +8, 104, 144, 147, 149, 70, 121, 103, 30, 194, 10, 34, 149, +187, 146, 118, 139, 144, 17, 178, 136, 175, 160, 53, 73, 246, +12, 18, 2, 225, 83, 201, 185, 153, 135, 60, 78, 91, 15, +117, 122, 234, 190, 26, 54, 186, 120, 108, 28, 149, 96, 95, +245, 16, 91, 14, 103, 143, 196, 9, 58, 95, 78, 208, 135, +64, 160, 106, 188, 121, 126, 126, 210, 56, 89, 17, 168, 238, +54, 42, 151, 42, 250, 170, 152, 15, 168, 55, 57, 26, 245, +76, 39, 178, 202, 158, 121, 64, 236, 82, 173, 126, 153, 235, +60, 200, 252, 138, 234, 235, 178, 173, 228, 191, 98, 127, 223, +214, 36, 49, 231, 183, 23, 114, 216, 79, 98, 189, 227, 134, +225, 139, 103, 220, 67, 124, 136, 33, 95, 57, 247, 154, 250, +218, 106, 81, 227, 100, 63, 76, 141, 158, 102, 63, 155, 193, +254, 227, 239, 52, 17, 109, 20, 251, 60, 14, 20, 15, 152, +248, 179, 153, 227, 158, 42, 86, 123, 11, 119, 97, 76, 12, +215, 27, 183, 82, 161, 227, 132, 35, 89, 179, 173, 205, 67, +112, 129, 50, 241, 84, 201, 62, 195, 190, 129, 2, 129, 193, +0, 243, 163, 50, 146, 127, 179, 166, 140, 134, 125, 107, 117, +200, 193, 155, 58, 90, 134, 141, 239, 236, 163, 180, 233, 109, +151, 34, 154, 73, 24, 212, 110, 66, 221, 118, 124, 87, 12, +123, 70, 0, 222, 152, 207, 133, 170, 217, 85, 19, 61, 109, +249, 12, 195, 167, 56, 138, 186, 158, 123, 165, 54, 120, 216, +205, 68, 175, 112, 7, 34, 87, 5, 226, 131, 164, 131, 86, +75, 154, 204, 89, 41, 27, 96, 138, 43, 0, 199, 80, 47, +146, 98, 191, 127, 51, 178, 208, 187, 192, 215, 127, 126, 106, +163, 90, 168, 180, 57, 78, 28, 63, 37, 239, 85, 236, 98, +202, 186, 102, 137, 37, 4, 18, 29, 236, 56, 162, 132, 67, +232, 252, 102, 23, 76, 203, 248, 33, 240, 109, 244, 81, 86, +43, 92, 250, 208, 254, 47, 159, 99, 192, 167, 155, 186, 55, +223, 102, 236, 88, 163, 208, 128, 213, 36, 11, 150, 172, 99, +200, 164, 8, 223, 123, 132, 58, 249, 231, 144, 41, 81, 106, +225, 236, 242, 237, 130, 157, 131, 33, 149, 54, 237, 2, 129, +193, 0, 209, 179, 65, 53, 65, 193, 79, 67, 70, 27, 236, +114, 120, 67, 192, 115, 196, 165, 19, 238, 227, 179, 13, 68, +254, 195, 74, 105, 12, 206, 146, 198, 237, 62, 167, 199, 21, +147, 248, 85, 205, 244, 75, 141, 133, 163, 150, 125, 195, 117, +203, 8, 186, 64, 205, 49, 117, 4, 207, 90, 130, 206, 246, +91, 158, 65, 28, 114, 76, 221, 190, 76, 78, 183, 76, 51, +100, 59, 69, 241, 47, 140, 32, 181, 203, 103, 24, 152, 178, +54, 190, 34, 126, 91, 206, 112, 211, 208, 69, 128, 130, 149, +216, 115, 97, 92, 111, 22, 159, 8, 231, 41, 230, 48, 251, +123, 99, 247, 236, 36, 139, 57, 115, 145, 16, 98, 240, 18, +186, 253, 115, 61, 83, 155, 58, 227, 90, 112, 188, 88, 45, +156, 169, 120, 115, 119, 154, 149, 200, 30, 165, 67, 33, 244, +59, 145, 12, 23, 226, 161, 197, 68, 32, 207, 207, 232, 180, +87, 33, 84, 156, 116, 57, 62, 19, 200, 197, 134, 21, 71, +60, 44, 94, 41, 129, 226, 195, 59, 56, 244, 209, 225, 2, +129, 193, 0, 158, 226, 119, 209, 136, 12, 45, 122, 9, 30, +243, 156, 109, 94, 173, 15, 130, 7, 171, 186, 162, 117, 36, +62, 242, 100, 20, 129, 207, 87, 172, 249, 119, 11, 156, 0, +124, 120, 60, 80, 43, 178, 254, 174, 158, 250, 11, 31, 107, +27, 173, 131, 52, 42, 199, 251, 156, 165, 21, 67, 135, 59, +157, 213, 173, 15, 180, 229, 119, 17, 146, 244, 216, 130, 135, +31, 203, 128, 36, 164, 77, 36, 252, 160, 153, 154, 111, 184, +139, 119, 106, 156, 145, 75, 175, 248, 86, 29, 139, 38, 62, +19, 192, 17, 101, 199, 13, 57, 45, 210, 71, 240, 66, 67, +163, 147, 205, 167, 127, 196, 194, 106, 4, 50, 149, 97, 93, +194, 169, 210, 223, 254, 232, 5, 2, 35, 128, 102, 158, 30, +45, 136, 231, 96, 140, 133, 12, 175, 27, 223, 222, 188, 175, +86, 226, 167, 3, 36, 240, 173, 108, 5, 8, 122, 168, 64, +11, 142, 75, 67, 134, 49, 208, 8, 44, 185, 218, 164, 109, +253, 149, 153, 94, 128, 18, 26, 19, 4, 120, 59, 42, 5, +2, 129, 192, 45, 60, 6, 175, 239, 76, 60, 197, 221, 68, +190, 191, 126, 147, 214, 218, 226, 43, 93, 222, 101, 61, 197, +122, 1, 158, 172, 217, 118, 74, 197, 60, 166, 6, 162, 248, +125, 254, 26, 78, 160, 11, 183, 148, 130, 164, 100, 29, 34, +225, 176, 247, 99, 254, 0, 133, 79, 161, 198, 252, 214, 68, +192, 189, 200, 168, 112, 243, 115, 3, 78, 62, 117, 168, 114, +134, 143, 115, 125, 197, 230, 36, 203, 21, 140, 23, 228, 37, +100, 36, 12, 229, 177, 238, 41, 221, 10, 195, 221, 138, 56, +33, 12, 188, 238, 222, 154, 147, 253, 160, 85, 5, 35, 195, +163, 43, 221, 199, 168, 39, 197, 228, 145, 186, 84, 23, 147, +131, 230, 212, 47, 92, 166, 65, 80, 245, 164, 23, 183, 121, +41, 245, 166, 84, 246, 75, 113, 140, 39, 203, 252, 136, 59, +181, 204, 119, 160, 109, 50, 149, 4, 209, 138, 102, 105, 137, +224, 4, 255, 138, 153, 233, 52, 67, 224, 206, 169, 85, 32, +23, 234, 178, 3, 105, 222, 187, 196, 179, 108, 184, 218, 225, +2, 129, 193, 0, 186, 166, 168, 57, 118, 72, 237, 131, 103, +179, 255, 89, 5, 105, 250, 210, 17, 252, 73, 88, 161, 192, +230, 131, 2, 30, 149, 42, 141, 46, 147, 11, 4, 92, 245, +101, 217, 176, 139, 208, 55, 8, 13, 148, 148, 193, 95, 175, +206, 100, 130, 144, 78, 160, 251, 131, 107, 161, 255, 73, 60, +134, 14, 132, 145, 98, 130, 200, 42, 143, 191, 126, 238, 253, +63, 170, 104, 129, 185, 47, 242, 232, 179, 188, 54, 116, 184, +115, 53, 70, 191, 99, 239, 27, 196, 192, 202, 255, 106, 136, +105, 49, 106, 8, 166, 234, 170, 236, 112, 157, 125, 195, 3, +254, 198, 117, 191, 169, 99, 116, 200, 97, 185, 43, 189, 226, +28, 244, 76, 88, 195, 204, 62, 162, 79, 100, 47, 132, 93, +120, 207, 90, 140, 130, 83, 20, 199, 171, 70, 165, 82, 244, +104, 5, 49, 204, 141, 168, 26, 40, 195, 242, 160, 189, 206, +216, 83, 222, 93, 227, 87, 132, 74, 149, 75, 11, 207, 15, +129, 4, 221, 142, 218, 55, 251, 177, 21, 195, 206, 102, 143, +62}; diff --git a/testkeys/RSA/3072_RSA_KEY.pem b/testkeys/RSA/3072_RSA_KEY.pem new file mode 100644 index 0000000..7185f83 --- /dev/null +++ b/testkeys/RSA/3072_RSA_KEY.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG5QIBAAKCAYEAx5LVdRXmCabxcyA23yHsm62vjeb/cRG//45IV4nqOCnvXJVS +ueRjUkRfv6c9HsP2atJ4E4Msrlg32pNhUaEZI5nKsxTjr0zzw7j+TtgYM6Ea4Gjl +5dC+V+iJh/rGLa9GPyFFK6KvYoDnXi8Wxc6vyW/I2EZ4/CTLSj+YvRZAQHq1kjXX +mfF+LNKMBDqsOUWOCzpdznySloYn7SYL8Y3HmOOFRchpGLfaTrizxgcnsnT1HjCD +eVE+ShsyC+89P4j6HzntSaZC1R8nkD3HMw+ReVMm00JbwZIsKZ0kMmD/Dgrw8ruf +gqGt9Kkj8DvPKJ6ODk5gGNsCcLbga5zQ0kfYMlyrjm/eON3Bb0FOhIL0YVU6sbN8 +NXjAhy11ICshJDIHxDNV7m11Ra50qg4grH2THqYEpvpT2O6VSSdQ6JZPpaYmsKeE +Kep8Ko6iOcmNtZCyrQvbIMPgiRERYdRQmFl3/POsiESiAF/hc0qxDCLtxkw3OgUm +4xRgh4MtVIaH4MNNAgMBAAECggGBAJfyUnSvtJH6ufBGQaDHKmco6PVoP2nt8rl2 +sdt8VIhoXSanRfHkUj5rcl7vzJgk6PNRxTxN7fHblsLi3QCSYBp72BlauTNZqmqE +6ZJL8rk0Wssq8oZz1MgHctbF9qcHwLsF8K0VUuTzcbSCs5rtD2eVpVwM48ZNmT2x +h+/HBipRgvaL6df6Rm+H6jS6GzALpeckjBFPRSg3giSLiCJkKOhdqbWErYe1SxAO +jkkiX3X+mDVhCGiQk5VGeWcewgoilbuSdouQEbKIr6A1SfYMEgLhU8m5mYc8TlsP +dXrqvho2unhsHJVgX/UQWw5nj8QJOl9O0IdAoGq8eX5+0jhZEajuNiqXKvqqmA+o +Nzka9UwnssqeeUDsUq1+mes8yPyK6uuyreS/Yn/f1iQx57cXcthPYr3jhuGLZ9xD +fIghXzn3mvraalHjZD9MjZ5mP5vB/uPvNBFtFPs8DhQPmPizmeOeKlZ7C3dhTAzX +G7dSoeOEI1mzrc1DcIEy8VTJPsO+gQKBwQDzozKSf7OmjIZ9a3XIwZs6WoaN7+yj +tOltlyKaSRjUbkLddnxXDHtGAN6Yz4Wq2VUTPW35DMOnOIq6nnulNnjYzUSvcAci +VwXig6SDVkuazFkpG2CKKwDHUC+SYr9/M7LQu8DXf35qo1qotDlOHD8l71XsYsq6 +ZoklBBId7DiihEPo/GYXTMv4IfBt9FFWK1z60P4vn2PAp5u6N99m7Fij0IDVJAuW +rGPIpAjfe4Q6+eeQKVFq4ezy7YKdgyGVNu0CgcEA0bNBNUHBT0NGG+xyeEPAc8Sl +E+7jsw1E/sNKaQzOksbtPqfHFZP4Vc30S42Fo5Z9w3XLCLpAzTF1BM9ags72W55B +HHJM3b5MTrdMM2Q7RfEvjCC1y2cYmLI2viJ+W85w09BFgIKV2HNhXG8WnwjnKeYw ++3tj9+wkizlzkRBi8BK6/XM9U5s641pwvFgtnKl4c3ealcgepUMh9DuRDBfiocVE +IM/P6LRXIVScdDk+E8jFhhVHPCxeKYHiwzs49NHhAoHBAJ7id9GIDC16CR7znG1e +rQ+CB6u6onUkPvJkFIHPV6z5dwucAHx4PFArsv6unvoLH2sbrYM0Ksf7nKUVQ4c7 +ndWtD7TldxGS9NiChx/LgCSkTST8oJmab7iLd2qckUuv+FYdiyY+E8ARZccNOS3S +R/BCQ6OTzad/xMJqBDKVYV3CqdLf/ugFAiOAZp4eLYjnYIyFDK8b3968r1bipwMk +8K1sBQh6qEALjktDhjHQCCy52qRt/ZWZXoASGhMEeDsqBQKBwC08Bq/vTDzF3US+ +v36T1triK13eZT3FegGerNl2SsU8pgai+H3+Gk6gC7eUgqRkHSLhsPdj/gCFT6HG +/NZEwL3IqHDzcwNOPnWocoaPc33F5iTLFYwX5CVkJAzlse4p3QrD3Yo4IQy87t6a +k/2gVQUjw6Mr3ceoJ8XkkbpUF5OD5tQvXKZBUPWkF7d5KfWmVPZLcYwny/yIO7XM +d6BtMpUE0YpmaYngBP+Kmek0Q+DOqVUgF+qyA2neu8SzbLja4QKBwQC6pqg5dkjt +g2ez/1kFafrSEfxJWKHA5oMCHpUqjS6TCwRc9WXZsIvQNwgNlJTBX6/OZIKQTqD7 +g2uh/0k8hg6EkWKCyCqPv37u/T+qaIG5L/Los7w2dLhzNUa/Y+8bxMDK/2qIaTFq +CKbqquxwnX3DA/7Gdb+pY3TIYbkrveIc9ExYw8w+ok9kL4RdeM9ajIJTFMerRqVS +9GgFMcyNqBoow/Kgvc7YU95d41eESpVLC88PgQTdjto3+7EVw85mjz4= +-----END RSA PRIVATE KEY----- diff --git a/testkeys/RSA/4096_RSA.h b/testkeys/RSA/4096_RSA.h new file mode 100644 index 0000000..c2b8703 --- /dev/null +++ b/testkeys/RSA/4096_RSA.h @@ -0,0 +1,202 @@ +/** + * @file testkeys/RSA/4096_RSA.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated X.509 certificate as binary DER. +Certificate: + Data: + Version: 3 + Serial Number: + 33:34:35:36 + Issuer: CN=Sample Matrix RSA-4096 Certificate Authority, C=US, ST=WA, L=Seattle, O=INSIDE Secure Corporation, OU=Test + Validity: + Not Before: 2014/03/24 + Not After : 2017/03/23 + Subject: CN=Sample Matrix RSA-4096 Certificate, C=US, ST=WA, L=Seattle, O=INSIDE Secure Corporation, OU=Test + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + c8:f2:db:39:ad:f4:43:97:a2:6d:85:2c:17:14:26:25: + e9:8f:b8:71:3c:58:5b:2d:18:0f:ad:76:a7:fe:8f:46: + 4c:67:c3:1e:70:e0:82:d3:77:67:9d:6d:76:a2:ca:79: + 70:d2:ae:be:21:a6:a7:42:ea:30:cb:96:15:a6:21:62: + 66:a5:dd:ff:23:78:c9:e0:9f:73:b8:08:1e:0e:49:85: + 8d:df:55:24:42:c1:4b:c9:de:03:a0:cf:c7:af:25:fd: + 6a:e8:ea:fc:d3:09:85:db:6b:9e:4a:8d:71:91:e9:84: + a7:75:6d:dd:2e:60:8c:af:30:fa:dd:1e:0d:04:5c:7b: + c2:35:0d:ee:5b:e5:62:81:b9:98:f1:ce:3f:92:59:1f: + d0:e4:17:48:fb:fe:a0:b3:2c:7c:01:c0:19:56:a1:20: + 08:06:7d:70:f2:2f:b2:ad:44:c2:e4:5b:84:2b:98:06: + 87:af:54:2b:b7:e4:fe:53:2f:f2:d7:b4:34:4d:46:df: + 44:2e:72:04:d7:34:3e:de:bf:55:74:7f:3e:d4:c3:3d: + 1f:7c:24:f2:ed:4f:38:1d:f4:b2:47:5e:e9:2c:23:f3: + dd:bb:16:d9:1c:ba:53:1a:1c:f1:02:f1:8e:ec:79:5b: + f9:55:21:66:12:6f:9e:f0:9e:3f:dc:be:d6:31:35:c2: + f2:78:b6:0a:9b:22:a3:a6:9d:d3:f5:4f:05:49:00:c4: + c2:c2:87:43:06:fc:43:3c:da:f6:fa:bd:f7:99:fb:d5: + 64:6f:69:d9:4d:b9:c5:1a:07:d6:df:40:b7:4a:6b:16: + c8:2c:23:5f:e2:ee:7c:66:dd:3b:7c:80:40:9a:b9:d8: + 99:f7:de:71:3d:f7:35:86:0f:6b:f9:01:e9:53:f9:17: + cf:1f:6e:f8:ac:fa:2f:5f:33:13:33:fa:f1:cf:7d:6b: + b9:d6:a3:68:16:84:60:89:6f:2c:c8:e7:f2:e0:c9:7f: + 84:ce:e9:45:18:96:9a:99:ac:0e:0e:61:ea:33:bf:3d: + b1:8b:92:9e:df:c6:75:66:56:7a:9a:a9:9b:d8:77:64: + ad:f6:41:c4:32:3b:8e:e9:90:55:fe:e3:0b:2c:43:37: + aa:8a:79:38:b4:89:9b:2d:ac:e7:6e:3f:23:b3:30:a2: + 84:21:97:8d:2d:02:14:ac:fa:67:4b:6c:bc:33:f5:89: + 88:8a:57:dd:96:9c:6a:5a:06:62:33:b1:e0:aa:70:c8: + 05:81:82:62:3d:a0:4c:df:71:a8:7e:7d:b3:c6:70:f1: + 60:ac:d6:46:d8:85:b7:6b:5f:b7:a1:86:b6:f5:ca:f6: + a2:8d:e9:78:37:13:1d:e0:d3:13:9f:0e:20:2c:26:87 + Exponent: 65537 + X509v3 extensions (critical: 0x1000): + X509v3 Subject Alternative Name: DNS + localhost + X509v3 Subject Alternative Name: iPAddress + 127.0.0.1 + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: 0x0 + X509v3 Extended Key Usage: 0x6 + TLS WWW server authentication + TLS WWW client authentication + X509v3 Authority Key Identifier: + 6c:42:84:c5:e0:4b:dc:70:f2:99:d0:1c:83:4a:e2:51: + 47:65:1e:fa + Signature Algorithm: sha256WithRSAEncryption + b9:75:fa:72:bb:3d:06:b0:ae:98:5d:fc:c6:dd:8b:4f: + 18:7c:e4:92:93:74:5f:1b:18:28:c7:22:1c:35:71:79: + 55:58:d8:65:ae:f2:2b:ba:b4:6a:2e:86:c2:c1:51:06: + cc:4c:70:b8:f8:72:7b:84:cd:cc:ee:f5:e2:c9:c8:da: + 33:a2:c2:b6:19:e0:81:83:14:d0:cd:fe:20:95:c4:53: + fe:6e:bb:9b:8f:ea:8e:00:7e:22:19:cd:a5:94:98:ea: + da:01:ac:5a:8d:8c:13:0e:82:96:01:70:a0:c3:fa:38: + ab:36:75:8d:17:d8:4a:20:e1:29:21:9b:39:c3:03:d5: + bb:25:a8:56:c1:c7:9d:1f:bf:6b:80:60:07:2e:e9:be: + 1b:ff:3b:be:4b:0d:bb:3a:cb:ff:2a:0c:24:a6:f3:e9: + 63:f4:a3:ec:44:5f:52:0c:e5:16:4b:38:c8:3b:33:dd: + ef:4d:8c:44:dc:5d:55:1b:e4:1b:20:7f:af:16:47:23: + 97:4b:31:50:4c:36:46:76:a1:29:91:25:69:2b:e9:8c: + e3:48:da:2c:d3:0f:ed:58:38:af:1f:f4:74:a3:12:13: + aa:b0:61:cd:12:72:ec:6f:41:3e:fa:35:a4:7b:2e:81: + 31:1e:2a:0e:33:f1:1c:2c:2e:e9:cb:4a:b4:9e:37:0d: + ce:e2:fe:63:19:04:67:9c:96:1f:0e:b9:c2:88:f7:f9: + 12:32:5f:dc:cd:14:db:27:ea:f0:40:22:f2:9d:cb:f4: + 46:42:61:9e:b9:f1:a0:af:32:52:54:26:01:97:39:ea: + 8f:84:22:6e:f8:64:9e:2e:ef:80:46:8b:a1:c3:a4:9a: + 4a:19:09:49:bd:42:23:d3:c5:e7:8f:3a:a2:9c:a1:85: + ce:e0:47:08:46:b0:e8:07:75:46:8e:bf:d2:1e:13:c8: + 26:48:46:6f:a6:d9:a3:73:bc:fd:cd:b2:69:3c:be:b7: + 6b:c6:a0:a1:84:0a:e5:02:85:81:fd:bd:92:22:6c:30: + 29:04:56:1d:dc:26:2a:45:5c:50:69:3b:39:38:d8:76: + 5b:30:03:a0:a0:be:17:c4:ab:e0:d8:e8:55:33:38:72: + 89:7f:96:b1:82:02:8d:b5:be:89:18:7a:1d:b4:a7:7a: + 5f:f5:e0:eb:33:4f:a8:96:44:6a:11:09:01:db:07:08: + e9:d9:bc:28:1a:10:30:69:82:1f:3a:b0:88:70:b8:27: + 8d:7e:31:ef:1e:4f:5b:c9:d2:d7:7e:e1:ac:fa:7e:09: + 5e:e8:ea:61:76:02:d5:2e:09:bc:ff:0c:fb:d5:ba:e3: + cc:7c:a2:75:1a:9c:e8:a2:46:ac:45:f7:7e:54:d7:8f +*/ +#define RSA4096_SIZE 1543 +const static unsigned char RSA4096[RSA4096_SIZE] = + "\x30\x82\x06\x03\x30\x82\x03\xeb\xa0\x03\x02\x01\x02\x02\x04\x33" + "\x34\x35\x36\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b" + "\x05\x00\x30\x81\x96\x31\x35\x30\x33\x06\x03\x55\x04\x03\x0c\x2c" + "\x53\x61\x6d\x70\x6c\x65\x20\x4d\x61\x74\x72\x69\x78\x20\x52\x53" + "\x41\x2d\x34\x30\x39\x36\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61" + "\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x0b\x30\x09" + "\x06\x03\x55\x04\x06\x0c\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55" + "\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c" + "\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06\x03\x55\x04" + "\x0a\x0c\x19\x49\x4e\x53\x49\x44\x45\x20\x53\x65\x63\x75\x72\x65" + "\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30\x0b" + "\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x30\x1e\x17\x0d\x31" + "\x34\x30\x33\x32\x34\x31\x36\x34\x31\x31\x30\x5a\x17\x0d\x31\x37" + "\x30\x33\x32\x33\x31\x36\x34\x31\x31\x30\x5a\x30\x81\x8c\x31\x2b" + "\x30\x29\x06\x03\x55\x04\x03\x0c\x22\x53\x61\x6d\x70\x6c\x65\x20" + "\x4d\x61\x74\x72\x69\x78\x20\x52\x53\x41\x2d\x34\x30\x39\x36\x20" + "\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x31\x0b\x30\x09\x06" + "\x03\x55\x04\x06\x0c\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04" + "\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c\x07" + "\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06\x03\x55\x04\x0a" + "\x0c\x19\x49\x4e\x53\x49\x44\x45\x20\x53\x65\x63\x75\x72\x65\x20" + "\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30\x0b\x06" + "\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x30\x82\x02\x22\x30\x0d" + "\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02" + "\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\xc8\xf2\xdb\x39\xad" + "\xf4\x43\x97\xa2\x6d\x85\x2c\x17\x14\x26\x25\xe9\x8f\xb8\x71\x3c" + "\x58\x5b\x2d\x18\x0f\xad\x76\xa7\xfe\x8f\x46\x4c\x67\xc3\x1e\x70" + "\xe0\x82\xd3\x77\x67\x9d\x6d\x76\xa2\xca\x79\x70\xd2\xae\xbe\x21" + "\xa6\xa7\x42\xea\x30\xcb\x96\x15\xa6\x21\x62\x66\xa5\xdd\xff\x23" + "\x78\xc9\xe0\x9f\x73\xb8\x08\x1e\x0e\x49\x85\x8d\xdf\x55\x24\x42" + "\xc1\x4b\xc9\xde\x03\xa0\xcf\xc7\xaf\x25\xfd\x6a\xe8\xea\xfc\xd3" + "\x09\x85\xdb\x6b\x9e\x4a\x8d\x71\x91\xe9\x84\xa7\x75\x6d\xdd\x2e" + "\x60\x8c\xaf\x30\xfa\xdd\x1e\x0d\x04\x5c\x7b\xc2\x35\x0d\xee\x5b" + "\xe5\x62\x81\xb9\x98\xf1\xce\x3f\x92\x59\x1f\xd0\xe4\x17\x48\xfb" + "\xfe\xa0\xb3\x2c\x7c\x01\xc0\x19\x56\xa1\x20\x08\x06\x7d\x70\xf2" + "\x2f\xb2\xad\x44\xc2\xe4\x5b\x84\x2b\x98\x06\x87\xaf\x54\x2b\xb7" + "\xe4\xfe\x53\x2f\xf2\xd7\xb4\x34\x4d\x46\xdf\x44\x2e\x72\x04\xd7" + "\x34\x3e\xde\xbf\x55\x74\x7f\x3e\xd4\xc3\x3d\x1f\x7c\x24\xf2\xed" + "\x4f\x38\x1d\xf4\xb2\x47\x5e\xe9\x2c\x23\xf3\xdd\xbb\x16\xd9\x1c" + "\xba\x53\x1a\x1c\xf1\x02\xf1\x8e\xec\x79\x5b\xf9\x55\x21\x66\x12" + "\x6f\x9e\xf0\x9e\x3f\xdc\xbe\xd6\x31\x35\xc2\xf2\x78\xb6\x0a\x9b" + "\x22\xa3\xa6\x9d\xd3\xf5\x4f\x05\x49\x00\xc4\xc2\xc2\x87\x43\x06" + "\xfc\x43\x3c\xda\xf6\xfa\xbd\xf7\x99\xfb\xd5\x64\x6f\x69\xd9\x4d" + "\xb9\xc5\x1a\x07\xd6\xdf\x40\xb7\x4a\x6b\x16\xc8\x2c\x23\x5f\xe2" + "\xee\x7c\x66\xdd\x3b\x7c\x80\x40\x9a\xb9\xd8\x99\xf7\xde\x71\x3d" + "\xf7\x35\x86\x0f\x6b\xf9\x01\xe9\x53\xf9\x17\xcf\x1f\x6e\xf8\xac" + "\xfa\x2f\x5f\x33\x13\x33\xfa\xf1\xcf\x7d\x6b\xb9\xd6\xa3\x68\x16" + "\x84\x60\x89\x6f\x2c\xc8\xe7\xf2\xe0\xc9\x7f\x84\xce\xe9\x45\x18" + "\x96\x9a\x99\xac\x0e\x0e\x61\xea\x33\xbf\x3d\xb1\x8b\x92\x9e\xdf" + "\xc6\x75\x66\x56\x7a\x9a\xa9\x9b\xd8\x77\x64\xad\xf6\x41\xc4\x32" + "\x3b\x8e\xe9\x90\x55\xfe\xe3\x0b\x2c\x43\x37\xaa\x8a\x79\x38\xb4" + "\x89\x9b\x2d\xac\xe7\x6e\x3f\x23\xb3\x30\xa2\x84\x21\x97\x8d\x2d" + "\x02\x14\xac\xfa\x67\x4b\x6c\xbc\x33\xf5\x89\x88\x8a\x57\xdd\x96" + "\x9c\x6a\x5a\x06\x62\x33\xb1\xe0\xaa\x70\xc8\x05\x81\x82\x62\x3d" + "\xa0\x4c\xdf\x71\xa8\x7e\x7d\xb3\xc6\x70\xf1\x60\xac\xd6\x46\xd8" + "\x85\xb7\x6b\x5f\xb7\xa1\x86\xb6\xf5\xca\xf6\xa2\x8d\xe9\x78\x37" + "\x13\x1d\xe0\xd3\x13\x9f\x0e\x20\x2c\x26\x87\x02\x03\x01\x00\x01" + "\xa3\x61\x30\x5f\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80" + "\x14\x6c\x42\x84\xc5\xe0\x4b\xdc\x70\xf2\x99\xd0\x1c\x83\x4a\xe2" + "\x51\x47\x65\x1e\xfa\x30\x1a\x06\x03\x55\x1d\x11\x04\x13\x30\x11" + "\x82\x09\x6c\x6f\x63\x61\x6c\x68\x6f\x73\x74\x87\x04\x7f\x00\x00" + "\x01\x30\x20\x06\x03\x55\x1d\x25\x01\x01\xff\x04\x16\x30\x14\x06" + "\x08\x2b\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2b\x06\x01\x05\x05" + "\x07\x03\x02\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b" + "\x05\x00\x03\x82\x02\x01\x00\xb9\x75\xfa\x72\xbb\x3d\x06\xb0\xae" + "\x98\x5d\xfc\xc6\xdd\x8b\x4f\x18\x7c\xe4\x92\x93\x74\x5f\x1b\x18" + "\x28\xc7\x22\x1c\x35\x71\x79\x55\x58\xd8\x65\xae\xf2\x2b\xba\xb4" + "\x6a\x2e\x86\xc2\xc1\x51\x06\xcc\x4c\x70\xb8\xf8\x72\x7b\x84\xcd" + "\xcc\xee\xf5\xe2\xc9\xc8\xda\x33\xa2\xc2\xb6\x19\xe0\x81\x83\x14" + "\xd0\xcd\xfe\x20\x95\xc4\x53\xfe\x6e\xbb\x9b\x8f\xea\x8e\x00\x7e" + "\x22\x19\xcd\xa5\x94\x98\xea\xda\x01\xac\x5a\x8d\x8c\x13\x0e\x82" + "\x96\x01\x70\xa0\xc3\xfa\x38\xab\x36\x75\x8d\x17\xd8\x4a\x20\xe1" + "\x29\x21\x9b\x39\xc3\x03\xd5\xbb\x25\xa8\x56\xc1\xc7\x9d\x1f\xbf" + "\x6b\x80\x60\x07\x2e\xe9\xbe\x1b\xff\x3b\xbe\x4b\x0d\xbb\x3a\xcb" + "\xff\x2a\x0c\x24\xa6\xf3\xe9\x63\xf4\xa3\xec\x44\x5f\x52\x0c\xe5" + "\x16\x4b\x38\xc8\x3b\x33\xdd\xef\x4d\x8c\x44\xdc\x5d\x55\x1b\xe4" + "\x1b\x20\x7f\xaf\x16\x47\x23\x97\x4b\x31\x50\x4c\x36\x46\x76\xa1" + "\x29\x91\x25\x69\x2b\xe9\x8c\xe3\x48\xda\x2c\xd3\x0f\xed\x58\x38" + "\xaf\x1f\xf4\x74\xa3\x12\x13\xaa\xb0\x61\xcd\x12\x72\xec\x6f\x41" + "\x3e\xfa\x35\xa4\x7b\x2e\x81\x31\x1e\x2a\x0e\x33\xf1\x1c\x2c\x2e" + "\xe9\xcb\x4a\xb4\x9e\x37\x0d\xce\xe2\xfe\x63\x19\x04\x67\x9c\x96" + "\x1f\x0e\xb9\xc2\x88\xf7\xf9\x12\x32\x5f\xdc\xcd\x14\xdb\x27\xea" + "\xf0\x40\x22\xf2\x9d\xcb\xf4\x46\x42\x61\x9e\xb9\xf1\xa0\xaf\x32" + "\x52\x54\x26\x01\x97\x39\xea\x8f\x84\x22\x6e\xf8\x64\x9e\x2e\xef" + "\x80\x46\x8b\xa1\xc3\xa4\x9a\x4a\x19\x09\x49\xbd\x42\x23\xd3\xc5" + "\xe7\x8f\x3a\xa2\x9c\xa1\x85\xce\xe0\x47\x08\x46\xb0\xe8\x07\x75" + "\x46\x8e\xbf\xd2\x1e\x13\xc8\x26\x48\x46\x6f\xa6\xd9\xa3\x73\xbc" + "\xfd\xcd\xb2\x69\x3c\xbe\xb7\x6b\xc6\xa0\xa1\x84\x0a\xe5\x02\x85" + "\x81\xfd\xbd\x92\x22\x6c\x30\x29\x04\x56\x1d\xdc\x26\x2a\x45\x5c" + "\x50\x69\x3b\x39\x38\xd8\x76\x5b\x30\x03\xa0\xa0\xbe\x17\xc4\xab" + "\xe0\xd8\xe8\x55\x33\x38\x72\x89\x7f\x96\xb1\x82\x02\x8d\xb5\xbe" + "\x89\x18\x7a\x1d\xb4\xa7\x7a\x5f\xf5\xe0\xeb\x33\x4f\xa8\x96\x44" + "\x6a\x11\x09\x01\xdb\x07\x08\xe9\xd9\xbc\x28\x1a\x10\x30\x69\x82" + "\x1f\x3a\xb0\x88\x70\xb8\x27\x8d\x7e\x31\xef\x1e\x4f\x5b\xc9\xd2" + "\xd7\x7e\xe1\xac\xfa\x7e\x09\x5e\xe8\xea\x61\x76\x02\xd5\x2e\x09" + "\xbc\xff\x0c\xfb\xd5\xba\xe3\xcc\x7c\xa2\x75\x1a\x9c\xe8\xa2\x46" + "\xac\x45\xf7\x7e\x54\xd7\x8f"; diff --git a/testkeys/RSA/4096_RSA.pem b/testkeys/RSA/4096_RSA.pem new file mode 100644 index 0000000..594bfa8 --- /dev/null +++ b/testkeys/RSA/4096_RSA.pem @@ -0,0 +1,35 @@ +-----BEGIN CERTIFICATE----- +MIIGAzCCA+ugAwIBAgIEMzQ1NjANBgkqhkiG9w0BAQsFADCBljE1MDMGA1UEAwws +U2FtcGxlIE1hdHJpeCBSU0EtNDA5NiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxCzAJ +BgNVBAYMAlVTMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UE +CgwZSU5TSURFIFNlY3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDAeFw0x +NDAzMjQxNjQxMTBaFw0xNzAzMjMxNjQxMTBaMIGMMSswKQYDVQQDDCJTYW1wbGUg +TWF0cml4IFJTQS00MDk2IENlcnRpZmljYXRlMQswCQYDVQQGDAJVUzELMAkGA1UE +CAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUlOU0lERSBTZWN1cmUg +Q29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQDI8ts5rfRDl6JthSwXFCYl6Y+4cTxYWy0YD612p/6PRkxnwx5w +4ILTd2edbXaiynlw0q6+IaanQuowy5YVpiFiZqXd/yN4yeCfc7gIHg5JhY3fVSRC +wUvJ3gOgz8evJf1q6Or80wmF22ueSo1xkemEp3Vt3S5gjK8w+t0eDQRce8I1De5b +5WKBuZjxzj+SWR/Q5BdI+/6gsyx8AcAZVqEgCAZ9cPIvsq1EwuRbhCuYBoevVCu3 +5P5TL/LXtDRNRt9ELnIE1zQ+3r9VdH8+1MM9H3wk8u1POB30skde6Swj8927Ftkc +ulMaHPEC8Y7seVv5VSFmEm+e8J4/3L7WMTXC8ni2Cpsio6ad0/VPBUkAxMLCh0MG +/EM82vb6vfeZ+9Vkb2nZTbnFGgfW30C3SmsWyCwjX+LufGbdO3yAQJq52Jn33nE9 +9zWGD2v5AelT+RfPH274rPovXzMTM/rxz31rudajaBaEYIlvLMjn8uDJf4TO6UUY +lpqZrA4OYeozvz2xi5Ke38Z1ZlZ6mqmb2HdkrfZBxDI7jumQVf7jCyxDN6qKeTi0 +iZstrOduPyOzMKKEIZeNLQIUrPpnS2y8M/WJiIpX3ZacaloGYjOx4KpwyAWBgmI9 +oEzfcah+fbPGcPFgrNZG2IW3a1+3oYa29cr2oo3peDcTHeDTE58OICwmhwIDAQAB +o2EwXzAfBgNVHSMEGDAWgBRsQoTF4EvccPKZ0ByDSuJRR2Ue+jAaBgNVHREEEzAR +gglsb2NhbGhvc3SHBH8AAAEwIAYDVR0lAQH/BBYwFAYIKwYBBQUHAwEGCCsGAQUF +BwMCMA0GCSqGSIb3DQEBCwUAA4ICAQC5dfpyuz0GsK6YXfzG3YtPGHzkkpN0XxsY +KMciHDVxeVVY2GWu8iu6tGouhsLBUQbMTHC4+HJ7hM3M7vXiycjaM6LCthnggYMU +0M3+IJXEU/5uu5uP6o4AfiIZzaWUmOraAaxajYwTDoKWAXCgw/o4qzZ1jRfYSiDh +KSGbOcMD1bslqFbBx50fv2uAYAcu6b4b/zu+Sw27Osv/KgwkpvPpY/Sj7ERfUgzl +Fks4yDsz3e9NjETcXVUb5Bsgf68WRyOXSzFQTDZGdqEpkSVpK+mM40jaLNMP7Vg4 +rx/0dKMSE6qwYc0ScuxvQT76NaR7LoExHioOM/EcLC7py0q0njcNzuL+YxkEZ5yW +Hw65woj3+RIyX9zNFNsn6vBAIvKdy/RGQmGeufGgrzJSVCYBlznqj4Qibvhkni7v +gEaLocOkmkoZCUm9QiPTxeePOqKcoYXO4EcIRrDoB3VGjr/SHhPIJkhGb6bZo3O8 +/c2yaTy+t2vGoKGECuUChYH9vZIibDApBFYd3CYqRVxQaTs5ONh2WzADoKC+F8Sr +4NjoVTM4col/lrGCAo21vokYeh20p3pf9eDrM0+olkRqEQkB2wcI6dm8KBoQMGmC +HzqwiHC4J41+Me8eT1vJ0td+4az6fgle6OphdgLVLgm8/wz71brjzHyidRqc6KJG +rEX3flTXjw== +-----END CERTIFICATE----- diff --git a/testkeys/RSA/4096_RSA_CA.h b/testkeys/RSA/4096_RSA_CA.h new file mode 100644 index 0000000..992e6aa --- /dev/null +++ b/testkeys/RSA/4096_RSA_CA.h @@ -0,0 +1,200 @@ +/** + * @file testkeys/RSA/4096_RSA_CA.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated X.509 certificate as binary DER. +Certificate: + Data: + Version: 3 + Serial Number: + 33:34:35:36:37 + Issuer: CN=Sample Matrix RSA-4096 Certificate Authority, C=US, ST=WA, L=Seattle, O=INSIDE Secure Corporation, OU=Test + Validity: + Not Before: 2014/03/24 + Not After : 2017/03/23 + Subject: CN=Sample Matrix RSA-4096 Certificate Authority, C=US, ST=WA, L=Seattle, O=INSIDE Secure Corporation, OU=Test + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + bb:b1:44:44:a1:d5:d9:0d:e2:36:49:26:be:69:cb:0e: + 88:4a:28:ef:ae:2c:4f:9d:25:c5:8a:bf:9e:51:e4:77: + 56:4b:4d:75:91:1d:4a:d2:cc:b3:0b:2f:e4:42:72:fa: + b2:9f:d2:27:e0:0c:c3:fe:83:3a:96:a0:d4:a5:9a:94: + 60:ba:0c:bf:ab:8e:68:cf:1f:c4:72:6d:57:ce:60:23: + 4c:09:f4:f8:6b:c6:59:da:d7:cc:3a:c2:98:83:b5:fc: + 37:43:8f:1c:00:4a:8e:0d:49:f5:f1:eb:a6:4f:c5:31: + 0d:6f:2e:f4:66:0a:f5:dc:eb:af:1c:71:63:e1:56:13: + ae:5a:ca:fc:98:b1:63:10:42:f0:9b:8b:90:e3:d3:d7: + e1:b9:5f:0f:cb:fd:c7:74:6b:54:5f:2d:d1:71:ba:0c: + 94:74:33:c0:3e:e1:97:67:0f:2a:5d:ee:4e:dc:7b:fe: + dd:2b:64:65:41:19:b0:6d:94:55:18:0c:6f:70:3c:c2: + 24:57:a1:fc:be:eb:f0:f0:f9:85:a2:a3:66:82:27:fb: + 70:c3:dc:72:5f:e7:60:d7:3b:0c:85:6b:c1:c5:58:57: + bb:ad:f0:4d:01:a3:ca:91:9c:4b:97:15:66:e3:19:2a: + 58:83:44:e2:18:19:fc:90:49:71:b0:59:75:3a:e6:74: + f9:6c:43:fe:02:c9:c0:b9:a8:09:80:39:3c:ea:86:7d: + 62:4b:94:43:f2:4a:63:34:44:03:22:35:98:b6:9b:67: + c6:93:64:80:94:a8:99:de:d7:87:03:1a:98:1c:f9:d0: + 6f:79:aa:de:8c:2f:b5:22:a9:ff:11:fc:aa:5b:2f:4c: + c5:e6:44:65:85:e4:ba:77:bd:33:83:68:33:56:d1:57: + 40:50:00:88:69:6a:16:89:4f:ef:90:67:56:61:79:69: + a2:84:9f:ed:91:cb:4c:bb:af:f2:9d:ef:e3:32:6c:37: + 64:ea:75:ff:c5:ec:88:bd:6b:43:fe:68:14:d4:c7:9b: + f4:ae:74:ea:e1:b4:63:2a:0e:f5:9c:be:9f:6e:4e:8f: + 09:3e:43:8d:4f:b3:05:25:fe:fa:7b:e6:1d:e6:e8:20: + 1b:4c:30:3d:e0:b7:76:69:0b:f1:07:03:1f:8f:57:bf: + 55:cf:11:98:b6:99:df:7b:9b:be:98:16:bb:d2:81:c1: + eb:9f:08:ae:7e:44:a9:a7:79:49:02:ac:8a:81:bc:92: + c6:d1:ef:cc:9d:14:b2:f4:09:af:1c:b2:0b:02:32:dd: + cd:fc:09:83:3e:1c:33:58:2b:77:d5:48:a6:5b:75:9f: + 66:31:11:53:47:c8:c7:44:09:c9:93:c4:1c:32:08:69 + Exponent: 65537 + X509v3 extensions (critical: 0x208): + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: 0x4 + X509v3 Extended Key Usage: 0x0 + X509v3 Subject Key Identifier: + 6c:42:84:c5:e0:4b:dc:70:f2:99:d0:1c:83:4a:e2:51: + 47:65:1e:fa + X509v3 Authority Key Identifier: + 6c:42:84:c5:e0:4b:dc:70:f2:99:d0:1c:83:4a:e2:51: + 47:65:1e:fa + Signature Algorithm: sha256WithRSAEncryption + 66:b4:58:98:67:1b:db:ce:63:5f:c3:71:89:a0:ad:99: + 10:c0:27:bc:5b:c3:a0:b1:cd:b6:ed:dc:16:06:33:3a: + 52:62:55:07:7c:6c:be:c7:ec:16:6b:7f:26:7c:75:70: + 29:19:15:88:40:5d:25:fa:50:39:0c:6a:3c:c7:10:ca: + a9:b9:44:30:66:93:49:0f:0a:1a:6f:78:a1:43:b3:48: + 4d:6a:91:3e:a9:be:bc:d9:94:78:29:e0:c4:87:97:94: + 99:04:94:2a:21:f0:a2:31:98:fd:23:8f:c0:32:e2:b1: + f6:e4:86:5f:3d:94:6f:84:97:3e:ce:9f:b7:7d:86:fe: + a8:28:2c:d9:b8:d0:ef:9a:7f:ca:3c:da:af:07:0f:df: + d3:18:5d:27:d6:9e:82:1b:09:d4:51:3a:75:7e:37:b6: + e2:5c:e6:44:3e:51:07:25:b2:e6:f6:0e:98:44:23:0d: + 5f:15:ec:3f:61:56:5f:41:84:46:3b:4e:6a:3f:4d:6c: + 9a:b0:85:85:b9:29:f3:b3:02:94:b5:c3:96:78:c0:d5: + 61:12:f6:61:0a:8b:9b:80:d6:3c:a4:1a:0d:4d:79:73: + 76:a4:8f:9a:e9:76:f3:8b:76:b9:6d:a2:f5:27:bb:c6: + ac:e4:25:01:ba:03:35:35:02:c8:cf:ad:79:1c:1f:94: + 3e:b2:db:b8:a7:e8:6e:8b:44:15:a2:af:4a:67:9b:ba: + 68:49:85:ee:93:c4:5f:97:77:e0:b4:90:8e:59:ec:26: + 08:a4:52:b4:9d:15:7b:5c:3f:5e:5b:5b:82:69:ff:f9: + 8d:fe:0e:0d:22:14:dd:39:6a:a2:03:5d:df:fe:60:1c: + 92:f9:1f:09:ad:ad:95:33:b4:b0:7c:4c:63:9f:30:d4: + 86:7d:8a:4b:06:f9:6a:66:cd:86:0e:fc:fc:c2:65:a9: + 61:3e:ed:ac:d5:f4:c5:95:8f:64:1a:9e:14:6f:e0:98: + b8:96:cc:0e:a2:b1:1a:20:07:60:ce:d2:9c:30:30:e0: + 53:fc:1f:ef:e1:23:ab:3d:77:c8:d0:71:dd:ac:9e:1c: + a4:7e:37:76:79:fd:90:5b:c2:77:81:cf:41:1f:10:9c: + 17:5c:ba:ba:0c:ca:f0:dd:1a:bb:2a:5d:a8:c6:3c:28: + 13:dd:a3:d5:a3:cc:34:2c:b0:09:42:a3:f1:95:d7:4a: + d5:b2:af:a3:ad:c2:72:67:48:6d:5d:5a:23:7f:b6:39: + f7:a5:cd:c3:01:9b:7e:91:57:ad:69:fa:6a:1b:5d:25: + 67:c8:1e:4c:08:6c:1b:e5:d6:37:a0:c9:98:c3:66:64: + 66:d5:72:30:5c:b3:15:c8:66:22:05:2e:da:61:a9:ca +*/ +#define RSA4096CA_SIZE 1559 +const static unsigned char RSA4096CA[RSA4096CA_SIZE] = + "\x30\x82\x06\x13\x30\x82\x03\xfb\xa0\x03\x02\x01\x02\x02\x05\x33" + "\x34\x35\x36\x37\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01" + "\x0b\x05\x00\x30\x81\x96\x31\x35\x30\x33\x06\x03\x55\x04\x03\x0c" + "\x2c\x53\x61\x6d\x70\x6c\x65\x20\x4d\x61\x74\x72\x69\x78\x20\x52" + "\x53\x41\x2d\x34\x30\x39\x36\x20\x43\x65\x72\x74\x69\x66\x69\x63" + "\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x0b\x30" + "\x09\x06\x03\x55\x04\x06\x0c\x02\x55\x53\x31\x0b\x30\x09\x06\x03" + "\x55\x04\x08\x0c\x02\x57\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x07" + "\x0c\x07\x53\x65\x61\x74\x74\x6c\x65\x31\x22\x30\x20\x06\x03\x55" + "\x04\x0a\x0c\x19\x49\x4e\x53\x49\x44\x45\x20\x53\x65\x63\x75\x72" + "\x65\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30" + "\x0b\x06\x03\x55\x04\x0b\x0c\x04\x54\x65\x73\x74\x30\x1e\x17\x0d" + "\x31\x34\x30\x33\x32\x34\x31\x36\x34\x31\x30\x33\x5a\x17\x0d\x31" + "\x37\x30\x33\x32\x33\x31\x36\x34\x31\x30\x33\x5a\x30\x81\x96\x31" + "\x35\x30\x33\x06\x03\x55\x04\x03\x0c\x2c\x53\x61\x6d\x70\x6c\x65" + "\x20\x4d\x61\x74\x72\x69\x78\x20\x52\x53\x41\x2d\x34\x30\x39\x36" + "\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74" + "\x68\x6f\x72\x69\x74\x79\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x0c" + "\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x57\x41" + "\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c\x07\x53\x65\x61\x74\x74" + "\x6c\x65\x31\x22\x30\x20\x06\x03\x55\x04\x0a\x0c\x19\x49\x4e\x53" + "\x49\x44\x45\x20\x53\x65\x63\x75\x72\x65\x20\x43\x6f\x72\x70\x6f" + "\x72\x61\x74\x69\x6f\x6e\x31\x0d\x30\x0b\x06\x03\x55\x04\x0b\x0c" + "\x04\x54\x65\x73\x74\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48" + "\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02" + "\x0a\x02\x82\x02\x01\x00\xbb\xb1\x44\x44\xa1\xd5\xd9\x0d\xe2\x36" + "\x49\x26\xbe\x69\xcb\x0e\x88\x4a\x28\xef\xae\x2c\x4f\x9d\x25\xc5" + "\x8a\xbf\x9e\x51\xe4\x77\x56\x4b\x4d\x75\x91\x1d\x4a\xd2\xcc\xb3" + "\x0b\x2f\xe4\x42\x72\xfa\xb2\x9f\xd2\x27\xe0\x0c\xc3\xfe\x83\x3a" + "\x96\xa0\xd4\xa5\x9a\x94\x60\xba\x0c\xbf\xab\x8e\x68\xcf\x1f\xc4" + "\x72\x6d\x57\xce\x60\x23\x4c\x09\xf4\xf8\x6b\xc6\x59\xda\xd7\xcc" + "\x3a\xc2\x98\x83\xb5\xfc\x37\x43\x8f\x1c\x00\x4a\x8e\x0d\x49\xf5" + "\xf1\xeb\xa6\x4f\xc5\x31\x0d\x6f\x2e\xf4\x66\x0a\xf5\xdc\xeb\xaf" + "\x1c\x71\x63\xe1\x56\x13\xae\x5a\xca\xfc\x98\xb1\x63\x10\x42\xf0" + "\x9b\x8b\x90\xe3\xd3\xd7\xe1\xb9\x5f\x0f\xcb\xfd\xc7\x74\x6b\x54" + "\x5f\x2d\xd1\x71\xba\x0c\x94\x74\x33\xc0\x3e\xe1\x97\x67\x0f\x2a" + "\x5d\xee\x4e\xdc\x7b\xfe\xdd\x2b\x64\x65\x41\x19\xb0\x6d\x94\x55" + "\x18\x0c\x6f\x70\x3c\xc2\x24\x57\xa1\xfc\xbe\xeb\xf0\xf0\xf9\x85" + "\xa2\xa3\x66\x82\x27\xfb\x70\xc3\xdc\x72\x5f\xe7\x60\xd7\x3b\x0c" + "\x85\x6b\xc1\xc5\x58\x57\xbb\xad\xf0\x4d\x01\xa3\xca\x91\x9c\x4b" + "\x97\x15\x66\xe3\x19\x2a\x58\x83\x44\xe2\x18\x19\xfc\x90\x49\x71" + "\xb0\x59\x75\x3a\xe6\x74\xf9\x6c\x43\xfe\x02\xc9\xc0\xb9\xa8\x09" + "\x80\x39\x3c\xea\x86\x7d\x62\x4b\x94\x43\xf2\x4a\x63\x34\x44\x03" + "\x22\x35\x98\xb6\x9b\x67\xc6\x93\x64\x80\x94\xa8\x99\xde\xd7\x87" + "\x03\x1a\x98\x1c\xf9\xd0\x6f\x79\xaa\xde\x8c\x2f\xb5\x22\xa9\xff" + "\x11\xfc\xaa\x5b\x2f\x4c\xc5\xe6\x44\x65\x85\xe4\xba\x77\xbd\x33" + "\x83\x68\x33\x56\xd1\x57\x40\x50\x00\x88\x69\x6a\x16\x89\x4f\xef" + "\x90\x67\x56\x61\x79\x69\xa2\x84\x9f\xed\x91\xcb\x4c\xbb\xaf\xf2" + "\x9d\xef\xe3\x32\x6c\x37\x64\xea\x75\xff\xc5\xec\x88\xbd\x6b\x43" + "\xfe\x68\x14\xd4\xc7\x9b\xf4\xae\x74\xea\xe1\xb4\x63\x2a\x0e\xf5" + "\x9c\xbe\x9f\x6e\x4e\x8f\x09\x3e\x43\x8d\x4f\xb3\x05\x25\xfe\xfa" + "\x7b\xe6\x1d\xe6\xe8\x20\x1b\x4c\x30\x3d\xe0\xb7\x76\x69\x0b\xf1" + "\x07\x03\x1f\x8f\x57\xbf\x55\xcf\x11\x98\xb6\x99\xdf\x7b\x9b\xbe" + "\x98\x16\xbb\xd2\x81\xc1\xeb\x9f\x08\xae\x7e\x44\xa9\xa7\x79\x49" + "\x02\xac\x8a\x81\xbc\x92\xc6\xd1\xef\xcc\x9d\x14\xb2\xf4\x09\xaf" + "\x1c\xb2\x0b\x02\x32\xdd\xcd\xfc\x09\x83\x3e\x1c\x33\x58\x2b\x77" + "\xd5\x48\xa6\x5b\x75\x9f\x66\x31\x11\x53\x47\xc8\xc7\x44\x09\xc9" + "\x93\xc4\x1c\x32\x08\x69\x02\x03\x01\x00\x01\xa3\x66\x30\x64\x30" + "\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff" + "\x02\x01\x00\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x6c\x42" + "\x84\xc5\xe0\x4b\xdc\x70\xf2\x99\xd0\x1c\x83\x4a\xe2\x51\x47\x65" + "\x1e\xfa\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x6c" + "\x42\x84\xc5\xe0\x4b\xdc\x70\xf2\x99\xd0\x1c\x83\x4a\xe2\x51\x47" + "\x65\x1e\xfa\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03" + "\x02\x00\x04\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b" + "\x05\x00\x03\x82\x02\x01\x00\x66\xb4\x58\x98\x67\x1b\xdb\xce\x63" + "\x5f\xc3\x71\x89\xa0\xad\x99\x10\xc0\x27\xbc\x5b\xc3\xa0\xb1\xcd" + "\xb6\xed\xdc\x16\x06\x33\x3a\x52\x62\x55\x07\x7c\x6c\xbe\xc7\xec" + "\x16\x6b\x7f\x26\x7c\x75\x70\x29\x19\x15\x88\x40\x5d\x25\xfa\x50" + "\x39\x0c\x6a\x3c\xc7\x10\xca\xa9\xb9\x44\x30\x66\x93\x49\x0f\x0a" + "\x1a\x6f\x78\xa1\x43\xb3\x48\x4d\x6a\x91\x3e\xa9\xbe\xbc\xd9\x94" + "\x78\x29\xe0\xc4\x87\x97\x94\x99\x04\x94\x2a\x21\xf0\xa2\x31\x98" + "\xfd\x23\x8f\xc0\x32\xe2\xb1\xf6\xe4\x86\x5f\x3d\x94\x6f\x84\x97" + "\x3e\xce\x9f\xb7\x7d\x86\xfe\xa8\x28\x2c\xd9\xb8\xd0\xef\x9a\x7f" + "\xca\x3c\xda\xaf\x07\x0f\xdf\xd3\x18\x5d\x27\xd6\x9e\x82\x1b\x09" + "\xd4\x51\x3a\x75\x7e\x37\xb6\xe2\x5c\xe6\x44\x3e\x51\x07\x25\xb2" + "\xe6\xf6\x0e\x98\x44\x23\x0d\x5f\x15\xec\x3f\x61\x56\x5f\x41\x84" + "\x46\x3b\x4e\x6a\x3f\x4d\x6c\x9a\xb0\x85\x85\xb9\x29\xf3\xb3\x02" + "\x94\xb5\xc3\x96\x78\xc0\xd5\x61\x12\xf6\x61\x0a\x8b\x9b\x80\xd6" + "\x3c\xa4\x1a\x0d\x4d\x79\x73\x76\xa4\x8f\x9a\xe9\x76\xf3\x8b\x76" + "\xb9\x6d\xa2\xf5\x27\xbb\xc6\xac\xe4\x25\x01\xba\x03\x35\x35\x02" + "\xc8\xcf\xad\x79\x1c\x1f\x94\x3e\xb2\xdb\xb8\xa7\xe8\x6e\x8b\x44" + "\x15\xa2\xaf\x4a\x67\x9b\xba\x68\x49\x85\xee\x93\xc4\x5f\x97\x77" + "\xe0\xb4\x90\x8e\x59\xec\x26\x08\xa4\x52\xb4\x9d\x15\x7b\x5c\x3f" + "\x5e\x5b\x5b\x82\x69\xff\xf9\x8d\xfe\x0e\x0d\x22\x14\xdd\x39\x6a" + "\xa2\x03\x5d\xdf\xfe\x60\x1c\x92\xf9\x1f\x09\xad\xad\x95\x33\xb4" + "\xb0\x7c\x4c\x63\x9f\x30\xd4\x86\x7d\x8a\x4b\x06\xf9\x6a\x66\xcd" + "\x86\x0e\xfc\xfc\xc2\x65\xa9\x61\x3e\xed\xac\xd5\xf4\xc5\x95\x8f" + "\x64\x1a\x9e\x14\x6f\xe0\x98\xb8\x96\xcc\x0e\xa2\xb1\x1a\x20\x07" + "\x60\xce\xd2\x9c\x30\x30\xe0\x53\xfc\x1f\xef\xe1\x23\xab\x3d\x77" + "\xc8\xd0\x71\xdd\xac\x9e\x1c\xa4\x7e\x37\x76\x79\xfd\x90\x5b\xc2" + "\x77\x81\xcf\x41\x1f\x10\x9c\x17\x5c\xba\xba\x0c\xca\xf0\xdd\x1a" + "\xbb\x2a\x5d\xa8\xc6\x3c\x28\x13\xdd\xa3\xd5\xa3\xcc\x34\x2c\xb0" + "\x09\x42\xa3\xf1\x95\xd7\x4a\xd5\xb2\xaf\xa3\xad\xc2\x72\x67\x48" + "\x6d\x5d\x5a\x23\x7f\xb6\x39\xf7\xa5\xcd\xc3\x01\x9b\x7e\x91\x57" + "\xad\x69\xfa\x6a\x1b\x5d\x25\x67\xc8\x1e\x4c\x08\x6c\x1b\xe5\xd6" + "\x37\xa0\xc9\x98\xc3\x66\x64\x66\xd5\x72\x30\x5c\xb3\x15\xc8\x66" + "\x22\x05\x2e\xda\x61\xa9\xca"; diff --git a/testkeys/RSA/4096_RSA_CA.pem b/testkeys/RSA/4096_RSA_CA.pem new file mode 100644 index 0000000..7b2d87a --- /dev/null +++ b/testkeys/RSA/4096_RSA_CA.pem @@ -0,0 +1,35 @@ +-----BEGIN CERTIFICATE----- +MIIGEzCCA/ugAwIBAgIFMzQ1NjcwDQYJKoZIhvcNAQELBQAwgZYxNTAzBgNVBAMM +LFNhbXBsZSBNYXRyaXggUlNBLTQwOTYgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQsw +CQYDVQQGDAJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNV +BAoMGUlOU0lERSBTZWN1cmUgQ29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QwHhcN +MTQwMzI0MTY0MTAzWhcNMTcwMzIzMTY0MTAzWjCBljE1MDMGA1UEAwwsU2FtcGxl +IE1hdHJpeCBSU0EtNDA5NiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxCzAJBgNVBAYM +AlVTMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSU5T +SURFIFNlY3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDCCAiIwDQYJKoZI +hvcNAQEBBQADggIPADCCAgoCggIBALuxRESh1dkN4jZJJr5pyw6ISijvrixPnSXF +ir+eUeR3VktNdZEdStLMswsv5EJy+rKf0ifgDMP+gzqWoNSlmpRgugy/q45ozx/E +cm1XzmAjTAn0+GvGWdrXzDrCmIO1/DdDjxwASo4NSfXx66ZPxTENby70Zgr13Ouv +HHFj4VYTrlrK/JixYxBC8JuLkOPT1+G5Xw/L/cd0a1RfLdFxugyUdDPAPuGXZw8q +Xe5O3Hv+3StkZUEZsG2UVRgMb3A8wiRXofy+6/Dw+YWio2aCJ/tww9xyX+dg1zsM +hWvBxVhXu63wTQGjypGcS5cVZuMZKliDROIYGfyQSXGwWXU65nT5bEP+AsnAuagJ +gDk86oZ9YkuUQ/JKYzREAyI1mLabZ8aTZICUqJne14cDGpgc+dBvearejC+1Iqn/ +EfyqWy9MxeZEZYXkune9M4NoM1bRV0BQAIhpahaJT++QZ1ZheWmihJ/tkctMu6/y +ne/jMmw3ZOp1/8XsiL1rQ/5oFNTHm/SudOrhtGMqDvWcvp9uTo8JPkONT7MFJf76 +e+Yd5uggG0wwPeC3dmkL8QcDH49Xv1XPEZi2md97m76YFrvSgcHrnwiufkSpp3lJ +AqyKgbySxtHvzJ0UsvQJrxyyCwIy3c38CYM+HDNYK3fVSKZbdZ9mMRFTR8jHRAnJ +k8QcMghpAgMBAAGjZjBkMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFGxC +hMXgS9xw8pnQHINK4lFHZR76MB8GA1UdIwQYMBaAFGxChMXgS9xw8pnQHINK4lFH +ZR76MA4GA1UdDwEB/wQEAwIABDANBgkqhkiG9w0BAQsFAAOCAgEAZrRYmGcb285j +X8NxiaCtmRDAJ7xbw6Cxzbbt3BYGMzpSYlUHfGy+x+wWa38mfHVwKRkViEBdJfpQ +OQxqPMcQyqm5RDBmk0kPChpveKFDs0hNapE+qb682ZR4KeDEh5eUmQSUKiHwojGY +/SOPwDLisfbkhl89lG+Elz7On7d9hv6oKCzZuNDvmn/KPNqvBw/f0xhdJ9aeghsJ +1FE6dX43tuJc5kQ+UQclsub2DphEIw1fFew/YVZfQYRGO05qP01smrCFhbkp87MC +lLXDlnjA1WES9mEKi5uA1jykGg1NeXN2pI+a6Xbzi3a5baL1J7vGrOQlAboDNTUC +yM+teRwflD6y27in6G6LRBWir0pnm7poSYXuk8Rfl3fgtJCOWewmCKRStJ0Ve1w/ +Xltbgmn/+Y3+Dg0iFN05aqIDXd/+YByS+R8Jra2VM7SwfExjnzDUhn2KSwb5ambN +hg78/MJlqWE+7azV9MWVj2QanhRv4Ji4lswOorEaIAdgztKcMDDgU/wf7+Ejqz13 +yNBx3ayeHKR+N3Z5/ZBbwneBz0EfEJwXXLq6DMrw3Rq7Kl2oxjwoE92j1aPMNCyw +CUKj8ZXXStWyr6OtwnJnSG1dWiN/tjn3pc3DAZt+kVetafpqG10lZ8geTAhsG+XW +N6DJmMNmZGbVcjBcsxXIZiIFLtphqco= +-----END CERTIFICATE----- diff --git a/testkeys/RSA/4096_RSA_KEY.h b/testkeys/RSA/4096_RSA_KEY.h new file mode 100644 index 0000000..2f98169 --- /dev/null +++ b/testkeys/RSA/4096_RSA_KEY.h @@ -0,0 +1,209 @@ +/** + * @file testkeys/RSA/4096_RSA_KEY.h + * @version $Format:%h%d$ + * + * Auto generated from PEM file. + */ +/* + Auto generated private key as binary DER. +*/ +#define RSA4096KEY_SIZE 2348 +const static unsigned char RSA4096KEY[RSA4096KEY_SIZE] = +{ + 0x30, 0x82, 0x09, 0x28, 0x02, 0x01, 0x00, 0x02, 0x82, 0x02, 0x01, 0x00, + 0xc8, 0xf2, 0xdb, 0x39, 0xad, 0xf4, 0x43, 0x97, 0xa2, 0x6d, 0x85, 0x2c, + 0x17, 0x14, 0x26, 0x25, 0xe9, 0x8f, 0xb8, 0x71, 0x3c, 0x58, 0x5b, 0x2d, + 0x18, 0x0f, 0xad, 0x76, 0xa7, 0xfe, 0x8f, 0x46, 0x4c, 0x67, 0xc3, 0x1e, + 0x70, 0xe0, 0x82, 0xd3, 0x77, 0x67, 0x9d, 0x6d, 0x76, 0xa2, 0xca, 0x79, + 0x70, 0xd2, 0xae, 0xbe, 0x21, 0xa6, 0xa7, 0x42, 0xea, 0x30, 0xcb, 0x96, + 0x15, 0xa6, 0x21, 0x62, 0x66, 0xa5, 0xdd, 0xff, 0x23, 0x78, 0xc9, 0xe0, + 0x9f, 0x73, 0xb8, 0x08, 0x1e, 0x0e, 0x49, 0x85, 0x8d, 0xdf, 0x55, 0x24, + 0x42, 0xc1, 0x4b, 0xc9, 0xde, 0x03, 0xa0, 0xcf, 0xc7, 0xaf, 0x25, 0xfd, + 0x6a, 0xe8, 0xea, 0xfc, 0xd3, 0x09, 0x85, 0xdb, 0x6b, 0x9e, 0x4a, 0x8d, + 0x71, 0x91, 0xe9, 0x84, 0xa7, 0x75, 0x6d, 0xdd, 0x2e, 0x60, 0x8c, 0xaf, + 0x30, 0xfa, 0xdd, 0x1e, 0x0d, 0x04, 0x5c, 0x7b, 0xc2, 0x35, 0x0d, 0xee, + 0x5b, 0xe5, 0x62, 0x81, 0xb9, 0x98, 0xf1, 0xce, 0x3f, 0x92, 0x59, 0x1f, + 0xd0, 0xe4, 0x17, 0x48, 0xfb, 0xfe, 0xa0, 0xb3, 0x2c, 0x7c, 0x01, 0xc0, + 0x19, 0x56, 0xa1, 0x20, 0x08, 0x06, 0x7d, 0x70, 0xf2, 0x2f, 0xb2, 0xad, + 0x44, 0xc2, 0xe4, 0x5b, 0x84, 0x2b, 0x98, 0x06, 0x87, 0xaf, 0x54, 0x2b, + 0xb7, 0xe4, 0xfe, 0x53, 0x2f, 0xf2, 0xd7, 0xb4, 0x34, 0x4d, 0x46, 0xdf, + 0x44, 0x2e, 0x72, 0x04, 0xd7, 0x34, 0x3e, 0xde, 0xbf, 0x55, 0x74, 0x7f, + 0x3e, 0xd4, 0xc3, 0x3d, 0x1f, 0x7c, 0x24, 0xf2, 0xed, 0x4f, 0x38, 0x1d, + 0xf4, 0xb2, 0x47, 0x5e, 0xe9, 0x2c, 0x23, 0xf3, 0xdd, 0xbb, 0x16, 0xd9, + 0x1c, 0xba, 0x53, 0x1a, 0x1c, 0xf1, 0x02, 0xf1, 0x8e, 0xec, 0x79, 0x5b, + 0xf9, 0x55, 0x21, 0x66, 0x12, 0x6f, 0x9e, 0xf0, 0x9e, 0x3f, 0xdc, 0xbe, + 0xd6, 0x31, 0x35, 0xc2, 0xf2, 0x78, 0xb6, 0x0a, 0x9b, 0x22, 0xa3, 0xa6, + 0x9d, 0xd3, 0xf5, 0x4f, 0x05, 0x49, 0x00, 0xc4, 0xc2, 0xc2, 0x87, 0x43, + 0x06, 0xfc, 0x43, 0x3c, 0xda, 0xf6, 0xfa, 0xbd, 0xf7, 0x99, 0xfb, 0xd5, + 0x64, 0x6f, 0x69, 0xd9, 0x4d, 0xb9, 0xc5, 0x1a, 0x07, 0xd6, 0xdf, 0x40, + 0xb7, 0x4a, 0x6b, 0x16, 0xc8, 0x2c, 0x23, 0x5f, 0xe2, 0xee, 0x7c, 0x66, + 0xdd, 0x3b, 0x7c, 0x80, 0x40, 0x9a, 0xb9, 0xd8, 0x99, 0xf7, 0xde, 0x71, + 0x3d, 0xf7, 0x35, 0x86, 0x0f, 0x6b, 0xf9, 0x01, 0xe9, 0x53, 0xf9, 0x17, + 0xcf, 0x1f, 0x6e, 0xf8, 0xac, 0xfa, 0x2f, 0x5f, 0x33, 0x13, 0x33, 0xfa, + 0xf1, 0xcf, 0x7d, 0x6b, 0xb9, 0xd6, 0xa3, 0x68, 0x16, 0x84, 0x60, 0x89, + 0x6f, 0x2c, 0xc8, 0xe7, 0xf2, 0xe0, 0xc9, 0x7f, 0x84, 0xce, 0xe9, 0x45, + 0x18, 0x96, 0x9a, 0x99, 0xac, 0x0e, 0x0e, 0x61, 0xea, 0x33, 0xbf, 0x3d, + 0xb1, 0x8b, 0x92, 0x9e, 0xdf, 0xc6, 0x75, 0x66, 0x56, 0x7a, 0x9a, 0xa9, + 0x9b, 0xd8, 0x77, 0x64, 0xad, 0xf6, 0x41, 0xc4, 0x32, 0x3b, 0x8e, 0xe9, + 0x90, 0x55, 0xfe, 0xe3, 0x0b, 0x2c, 0x43, 0x37, 0xaa, 0x8a, 0x79, 0x38, + 0xb4, 0x89, 0x9b, 0x2d, 0xac, 0xe7, 0x6e, 0x3f, 0x23, 0xb3, 0x30, 0xa2, + 0x84, 0x21, 0x97, 0x8d, 0x2d, 0x02, 0x14, 0xac, 0xfa, 0x67, 0x4b, 0x6c, + 0xbc, 0x33, 0xf5, 0x89, 0x88, 0x8a, 0x57, 0xdd, 0x96, 0x9c, 0x6a, 0x5a, + 0x06, 0x62, 0x33, 0xb1, 0xe0, 0xaa, 0x70, 0xc8, 0x05, 0x81, 0x82, 0x62, + 0x3d, 0xa0, 0x4c, 0xdf, 0x71, 0xa8, 0x7e, 0x7d, 0xb3, 0xc6, 0x70, 0xf1, + 0x60, 0xac, 0xd6, 0x46, 0xd8, 0x85, 0xb7, 0x6b, 0x5f, 0xb7, 0xa1, 0x86, + 0xb6, 0xf5, 0xca, 0xf6, 0xa2, 0x8d, 0xe9, 0x78, 0x37, 0x13, 0x1d, 0xe0, + 0xd3, 0x13, 0x9f, 0x0e, 0x20, 0x2c, 0x26, 0x87, 0x02, 0x03, 0x01, 0x00, + 0x01, 0x02, 0x82, 0x02, 0x00, 0x47, 0x8f, 0xcd, 0x28, 0x86, 0x5d, 0x85, + 0xb0, 0xbb, 0x84, 0x7b, 0x37, 0x8f, 0x64, 0x7a, 0x8d, 0x67, 0xd6, 0xe9, + 0xdd, 0x51, 0x9b, 0x39, 0xa5, 0x1e, 0x7b, 0x7e, 0xcf, 0xd1, 0xd5, 0xe2, + 0xda, 0x2b, 0x1d, 0x8c, 0xac, 0x0b, 0x90, 0xb8, 0xa6, 0x6c, 0x50, 0x77, + 0x0c, 0xe3, 0x81, 0xe7, 0xcf, 0x45, 0xb1, 0x91, 0xcf, 0x5e, 0x16, 0x86, + 0x5c, 0x5b, 0x20, 0x53, 0x70, 0x38, 0x77, 0x78, 0x4e, 0x1d, 0xb6, 0x16, + 0x0f, 0xe5, 0x66, 0xff, 0xa5, 0xc1, 0xc3, 0x29, 0x17, 0xa2, 0xf4, 0x7d, + 0x94, 0x55, 0x48, 0xe2, 0x7e, 0x4e, 0x53, 0x9e, 0x14, 0xde, 0xbe, 0xb6, + 0x07, 0x28, 0xda, 0xa4, 0x11, 0xd2, 0x7f, 0xee, 0x27, 0x69, 0x54, 0x6b, + 0xda, 0x0f, 0x42, 0x48, 0xd4, 0x84, 0x4c, 0x6d, 0x37, 0xf3, 0x96, 0xeb, + 0x30, 0x28, 0x72, 0xf3, 0xc6, 0xf4, 0x0f, 0x72, 0xad, 0x5f, 0xff, 0x5c, + 0x9c, 0x2a, 0x36, 0x50, 0xa6, 0xc1, 0x0d, 0x38, 0x7e, 0x70, 0x45, 0x1a, + 0x5f, 0xd3, 0xdd, 0xdf, 0x65, 0x68, 0x33, 0xc2, 0x63, 0x18, 0x72, 0xbe, + 0x71, 0xf0, 0x76, 0x9c, 0xfc, 0xf7, 0x49, 0x15, 0x8a, 0x5d, 0xb1, 0x49, + 0xfc, 0xee, 0x12, 0xb4, 0x73, 0xe6, 0x17, 0xed, 0xd0, 0xf5, 0x89, 0xbc, + 0xd3, 0x1e, 0x80, 0xfe, 0xdd, 0xae, 0xd8, 0x9b, 0x05, 0xae, 0xfe, 0xb1, + 0x78, 0x98, 0x63, 0xa8, 0xc8, 0x9b, 0xf4, 0x5a, 0x60, 0x84, 0xef, 0x33, + 0x30, 0x8a, 0x3c, 0xf9, 0x86, 0xd3, 0x2e, 0x5b, 0xf5, 0x29, 0x80, 0x41, + 0x7c, 0x4d, 0xac, 0xb7, 0x94, 0x5b, 0x6f, 0x1d, 0xe1, 0x9b, 0xf2, 0x3f, + 0x3f, 0x7a, 0x88, 0x45, 0x03, 0xbe, 0xaa, 0x50, 0x2b, 0xed, 0x80, 0x9b, + 0x06, 0xc1, 0x5a, 0x4f, 0x81, 0xc4, 0x92, 0x5f, 0x99, 0x85, 0x19, 0x41, + 0x25, 0xf9, 0x85, 0x4e, 0xac, 0x9b, 0x84, 0xdc, 0xda, 0xd4, 0xeb, 0xae, + 0xc5, 0xe5, 0xdc, 0x00, 0x09, 0x15, 0x75, 0x85, 0x4b, 0xf0, 0xe3, 0x31, + 0x87, 0x3d, 0xe5, 0x8e, 0xf1, 0x00, 0x20, 0xc7, 0x9b, 0xa4, 0xf2, 0x70, + 0x4e, 0x6e, 0x80, 0xe2, 0xbc, 0x35, 0x76, 0xae, 0xca, 0xc8, 0xb1, 0x47, + 0xe4, 0x26, 0x90, 0x57, 0xad, 0x15, 0xa4, 0x54, 0x71, 0x33, 0xb1, 0x71, + 0x98, 0x6d, 0x96, 0xc4, 0x8d, 0xc7, 0x34, 0xa9, 0x32, 0x6a, 0xef, 0xd8, + 0x0a, 0x86, 0x32, 0xe2, 0x89, 0x0a, 0xd1, 0xd8, 0x0a, 0x6a, 0x84, 0x14, + 0x77, 0xde, 0x3a, 0xb9, 0xd3, 0xda, 0xae, 0x17, 0xf8, 0x0c, 0x63, 0xa5, + 0x41, 0x56, 0x58, 0xa8, 0xc4, 0x84, 0xd1, 0xb2, 0xf8, 0xe3, 0x1d, 0xbf, + 0x91, 0xf7, 0xb4, 0x46, 0xd6, 0xc7, 0x53, 0xb2, 0xeb, 0x89, 0x28, 0x64, + 0x68, 0x80, 0xf4, 0x72, 0xf8, 0xd7, 0x50, 0xab, 0x27, 0x70, 0x5c, 0x4d, + 0x20, 0x43, 0x8c, 0x52, 0xa0, 0x55, 0xef, 0xff, 0xfb, 0x46, 0x8c, 0x62, + 0x14, 0x97, 0xd0, 0x55, 0x76, 0x2c, 0xe8, 0xe8, 0xa5, 0x96, 0x5d, 0x7c, + 0x0d, 0x01, 0xcf, 0xba, 0x32, 0x2e, 0x8c, 0x16, 0x40, 0x66, 0x46, 0x0d, + 0x50, 0x38, 0x2a, 0x65, 0x14, 0xe0, 0x34, 0xbe, 0x5d, 0xeb, 0xbe, 0xd6, + 0xfe, 0x8b, 0xa3, 0x6a, 0x11, 0x8b, 0xda, 0xbf, 0x7a, 0x55, 0x4a, 0x34, + 0xbf, 0x9b, 0x3d, 0x23, 0xd3, 0x6e, 0x9a, 0x3f, 0x4b, 0x60, 0x58, 0x84, + 0x31, 0x2b, 0xe8, 0x92, 0xed, 0x14, 0x57, 0x14, 0x08, 0xae, 0x21, 0x0f, + 0x0a, 0xd2, 0x9c, 0x75, 0x2f, 0x2d, 0xd0, 0x14, 0xb5, 0x14, 0xfa, 0xa1, + 0x1d, 0xef, 0xdf, 0x2a, 0xf8, 0x67, 0xc8, 0xb8, 0x9f, 0x1d, 0x89, 0xe9, + 0xe5, 0xa8, 0x44, 0x4f, 0x3a, 0xc4, 0xd5, 0xdb, 0xfa, 0xb2, 0x8b, 0x68, + 0x66, 0xbc, 0xdf, 0xb3, 0x68, 0x5b, 0x2c, 0x92, 0xf8, 0x49, 0xc3, 0x2d, + 0xf9, 0x02, 0x82, 0x01, 0x01, 0x00, 0xf7, 0x7c, 0x65, 0xc6, 0x43, 0x0b, + 0x60, 0x60, 0xfd, 0xfc, 0xe0, 0xcd, 0x37, 0xfc, 0x98, 0xfb, 0x6b, 0xb8, + 0x4f, 0x8b, 0xdb, 0x79, 0x0c, 0x52, 0xeb, 0x62, 0xd5, 0x44, 0x67, 0x4f, + 0x67, 0x11, 0x02, 0x5b, 0x37, 0x2f, 0xcc, 0x31, 0x17, 0x44, 0x42, 0x96, + 0x76, 0xc8, 0x5d, 0x46, 0x1b, 0xd7, 0xad, 0x7a, 0x4c, 0x16, 0xdc, 0xab, + 0x1d, 0xe9, 0x64, 0xd3, 0xc4, 0xe4, 0x46, 0x76, 0x05, 0xb4, 0x09, 0x8b, + 0xb3, 0xba, 0xca, 0x68, 0xba, 0xf0, 0x50, 0x7a, 0x24, 0x33, 0xc1, 0xb5, + 0xf2, 0xb7, 0xa0, 0xd8, 0xfd, 0xbd, 0x57, 0xe0, 0x32, 0x15, 0x9c, 0xb0, + 0xc3, 0x74, 0xd0, 0xb1, 0xe8, 0x26, 0xd8, 0xd1, 0x22, 0x56, 0x0e, 0xd7, + 0x39, 0xe6, 0xed, 0x0e, 0x62, 0x4c, 0x05, 0x37, 0x05, 0x7d, 0x19, 0x10, + 0xa7, 0xf2, 0x36, 0x76, 0x34, 0xee, 0xa7, 0xc0, 0x0a, 0xf8, 0x78, 0x2f, + 0x8d, 0xd4, 0x68, 0x44, 0xd1, 0x19, 0x39, 0x00, 0x8b, 0xa6, 0x9c, 0x48, + 0xcb, 0x4a, 0xe0, 0x53, 0x78, 0x8a, 0x0e, 0x52, 0xe4, 0xb2, 0xb2, 0x6a, + 0x19, 0xd8, 0xb2, 0x29, 0x54, 0xc3, 0xb7, 0x0f, 0xdd, 0x04, 0xa5, 0x73, + 0xec, 0x53, 0x8c, 0x80, 0xd7, 0x9e, 0x46, 0x14, 0xba, 0x0d, 0xa2, 0xaa, + 0xf2, 0xc6, 0x42, 0xa7, 0xbb, 0xbe, 0x16, 0x21, 0xb9, 0xe0, 0x4b, 0x28, + 0x3a, 0xec, 0x9a, 0x1f, 0x96, 0xff, 0x9b, 0x67, 0x34, 0x78, 0x81, 0xec, + 0x11, 0x8d, 0x86, 0x01, 0xdd, 0xb2, 0x32, 0xf7, 0x9b, 0xa1, 0x29, 0xfd, + 0xf7, 0xd7, 0x7a, 0x1f, 0x24, 0x86, 0x62, 0xcd, 0xa2, 0x73, 0x27, 0x87, + 0x1e, 0x3f, 0x45, 0xc1, 0xef, 0xf9, 0x2e, 0x1b, 0xa5, 0x0d, 0x69, 0x9f, + 0xc7, 0x70, 0xea, 0x55, 0xd7, 0x09, 0x7d, 0x0f, 0x65, 0xcd, 0xe5, 0xb6, + 0x6d, 0xd4, 0x77, 0x7d, 0xe1, 0xaf, 0xaf, 0xe6, 0x31, 0x45, 0x02, 0x82, + 0x01, 0x01, 0x00, 0xcf, 0xdc, 0x9b, 0x30, 0x30, 0x03, 0x1a, 0x74, 0xce, + 0x7b, 0xd2, 0x9a, 0x04, 0xda, 0x91, 0x27, 0xe8, 0x74, 0x7c, 0x1c, 0x4f, + 0xeb, 0x98, 0x9e, 0x71, 0x56, 0x99, 0x0d, 0xdd, 0x09, 0x4a, 0xdb, 0xc9, + 0xcc, 0xfc, 0x62, 0x31, 0x57, 0x2e, 0x7b, 0xa2, 0x9b, 0x58, 0xf4, 0xa2, + 0x9d, 0x52, 0xa9, 0xb5, 0x4d, 0xa6, 0x2b, 0x24, 0xbe, 0x42, 0xf6, 0xa7, + 0xe7, 0xf2, 0xd9, 0xc8, 0xde, 0x6a, 0x84, 0x35, 0x8a, 0xb4, 0xf1, 0x1e, + 0x92, 0x62, 0xa0, 0x55, 0xe9, 0xcd, 0x64, 0x17, 0x11, 0xe3, 0x28, 0xdc, + 0x16, 0x37, 0x6c, 0xc0, 0xf5, 0xf3, 0x2f, 0x76, 0xd6, 0xa1, 0x63, 0x49, + 0x3f, 0x74, 0xf8, 0x78, 0x38, 0x0d, 0x3b, 0x7f, 0xf7, 0xd7, 0x9d, 0x7e, + 0x65, 0x25, 0x8a, 0x30, 0xe7, 0x07, 0xed, 0xdf, 0x55, 0x21, 0x9e, 0xf0, + 0x04, 0xb4, 0xf2, 0xf7, 0x5d, 0x4c, 0x67, 0x1f, 0xa2, 0x6f, 0xfd, 0xe8, + 0x24, 0xf0, 0xac, 0x7c, 0x6d, 0x2b, 0x3b, 0x93, 0xa9, 0x7f, 0x88, 0xa6, + 0xaa, 0xbe, 0x70, 0xa1, 0xdd, 0x2f, 0xb2, 0x37, 0x13, 0x85, 0xa6, 0xd3, + 0x1d, 0x71, 0x2d, 0x9d, 0x77, 0x0f, 0x82, 0x9a, 0x9e, 0x57, 0x49, 0xae, + 0x94, 0xce, 0x8b, 0x27, 0xcf, 0x64, 0xe8, 0x2b, 0xc0, 0x20, 0x0f, 0x05, + 0x22, 0x34, 0x1e, 0x19, 0x94, 0x6a, 0xe1, 0xbe, 0xa6, 0x36, 0xc9, 0x44, + 0xa5, 0x4a, 0x2c, 0x85, 0x2f, 0xfc, 0xdd, 0x70, 0xa1, 0xbf, 0xcf, 0x70, + 0x2c, 0x78, 0xb4, 0xe1, 0x76, 0x89, 0x12, 0xe0, 0x4d, 0xd9, 0xf0, 0x1d, + 0x77, 0xac, 0xc5, 0xa1, 0x5b, 0x5e, 0x58, 0x0a, 0xd3, 0x64, 0x61, 0xce, + 0x36, 0x2c, 0x7e, 0x8a, 0x6d, 0xd9, 0xe7, 0x90, 0x0a, 0x47, 0x30, 0xca, + 0xf0, 0x90, 0x77, 0x69, 0xb8, 0x00, 0x90, 0xa5, 0xdc, 0x51, 0x30, 0x94, + 0xc9, 0xac, 0xdc, 0xc7, 0x9c, 0xc7, 0x5b, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xb0, 0xe4, 0x66, 0x6e, 0x56, 0x9f, 0x7c, 0x0c, 0xf7, 0x9d, 0xd7, 0x24, + 0x77, 0xdf, 0x01, 0x8d, 0xbb, 0x89, 0xea, 0xb9, 0x81, 0x6e, 0xbd, 0x03, + 0x4b, 0xa1, 0xc1, 0xe3, 0xf9, 0x9f, 0xc4, 0x80, 0x60, 0xd9, 0xc7, 0xd1, + 0x4f, 0x36, 0xcb, 0x75, 0x8b, 0xce, 0xb6, 0x2a, 0x32, 0x99, 0x18, 0xef, + 0x88, 0xdc, 0x80, 0x24, 0x5b, 0x27, 0xa7, 0xe2, 0x99, 0xa1, 0xcf, 0xfa, + 0x85, 0xee, 0x77, 0xd7, 0x1e, 0x77, 0x8f, 0x48, 0x74, 0xc2, 0x74, 0xd3, + 0xae, 0x02, 0x0f, 0x7c, 0x3a, 0xfa, 0x0c, 0xf9, 0x79, 0x6b, 0x7f, 0xb9, + 0xe5, 0x64, 0xa7, 0x07, 0xd1, 0x8e, 0x7a, 0xb6, 0x35, 0x30, 0xe4, 0x49, + 0x57, 0xf1, 0xeb, 0x83, 0xed, 0x69, 0xa2, 0xc6, 0x4f, 0x2c, 0x57, 0xd0, + 0x14, 0x6e, 0x26, 0x6b, 0x2b, 0x0e, 0x3f, 0xac, 0x9d, 0x86, 0xd2, 0x00, + 0xbf, 0x40, 0x41, 0xd7, 0x25, 0x38, 0x80, 0x3c, 0x91, 0x26, 0x96, 0xfa, + 0x5b, 0x46, 0xeb, 0x8a, 0x73, 0xec, 0x87, 0xfa, 0x05, 0xeb, 0x43, 0x9e, + 0x11, 0xec, 0xe7, 0xf0, 0x5e, 0x1b, 0xfe, 0x4b, 0x67, 0xd4, 0xa8, 0xf4, + 0x97, 0x15, 0x2c, 0x99, 0xd4, 0x94, 0xce, 0x17, 0x4d, 0xb7, 0x0d, 0xe6, + 0xe0, 0x1a, 0x92, 0x7d, 0x8a, 0x86, 0x7b, 0xae, 0x80, 0x18, 0x19, 0xd6, + 0x1d, 0x45, 0x8f, 0xf1, 0x24, 0x67, 0x25, 0xee, 0xd5, 0x9e, 0xbc, 0xb4, + 0x08, 0x64, 0xb5, 0x19, 0x69, 0x6b, 0xcd, 0x84, 0x05, 0x83, 0xb1, 0xed, + 0x5c, 0x06, 0xa5, 0x63, 0x85, 0x7b, 0x34, 0xb9, 0xfc, 0x5c, 0xe4, 0x23, + 0x75, 0xdd, 0x9b, 0x3e, 0x89, 0xc3, 0x47, 0x38, 0x5c, 0x68, 0xe9, 0x58, + 0x86, 0xbf, 0x55, 0xb3, 0x07, 0x8b, 0x1f, 0xe7, 0xb2, 0x67, 0x16, 0xa3, + 0x7e, 0x93, 0x11, 0xe6, 0x20, 0x49, 0xcb, 0xa8, 0xf0, 0x9b, 0xb6, 0x43, + 0x78, 0x0b, 0xa5, 0xad, 0x02, 0x82, 0x01, 0x00, 0x0a, 0x1c, 0x7d, 0x20, + 0x16, 0xf5, 0xcf, 0xaf, 0xa6, 0xeb, 0xb7, 0x0e, 0xee, 0xf5, 0x82, 0xe2, + 0x22, 0x18, 0xa8, 0x80, 0xe8, 0x12, 0x59, 0xd6, 0x3b, 0x45, 0x2f, 0x24, + 0xd1, 0x7f, 0xc6, 0x38, 0x72, 0xd4, 0x99, 0xe2, 0x5c, 0xec, 0x14, 0xc2, + 0xc6, 0xe2, 0x2f, 0xad, 0x96, 0xcb, 0x78, 0x5d, 0xf1, 0x07, 0xd9, 0xf1, + 0x77, 0x54, 0x1a, 0x05, 0xcd, 0x9d, 0x26, 0xdf, 0x19, 0x3a, 0x58, 0x8c, + 0x1d, 0xde, 0xa5, 0x76, 0xa5, 0x3a, 0x11, 0xba, 0x22, 0xf3, 0xc0, 0x9e, + 0x01, 0xd1, 0x48, 0xef, 0x8f, 0xe5, 0x34, 0xc5, 0x01, 0x8d, 0xf5, 0x4a, + 0x75, 0xc9, 0x73, 0x08, 0x55, 0x63, 0xd4, 0xd8, 0xd1, 0x60, 0x48, 0xa4, + 0x80, 0x51, 0x1a, 0x17, 0xfb, 0x32, 0x08, 0x65, 0x74, 0x83, 0x88, 0x8b, + 0x35, 0xb5, 0xfa, 0x70, 0xb4, 0xd4, 0x45, 0xc9, 0x1b, 0xe7, 0x59, 0xf4, + 0x1a, 0x41, 0xd8, 0x98, 0xcd, 0x56, 0x1e, 0xaf, 0x05, 0x4e, 0x7a, 0x2f, + 0xe7, 0xba, 0xf3, 0x0d, 0x3e, 0xae, 0x47, 0x9d, 0x4b, 0x02, 0x6b, 0x73, + 0x8b, 0xe2, 0x53, 0x3a, 0x0e, 0x42, 0xfc, 0x62, 0x6f, 0xaa, 0x7f, 0x02, + 0xa7, 0x6a, 0xd4, 0x6c, 0x2d, 0x25, 0xe7, 0xf6, 0x34, 0xf5, 0x8d, 0xbf, + 0x0d, 0x81, 0xc7, 0x0d, 0x73, 0xfe, 0x79, 0xf2, 0x8c, 0xe3, 0xff, 0x5f, + 0x03, 0xdb, 0x2a, 0x07, 0x18, 0x63, 0xc1, 0xfb, 0xf0, 0x6e, 0xa9, 0x2a, + 0x4c, 0x74, 0x51, 0xd4, 0x51, 0x6c, 0x98, 0x62, 0x94, 0x25, 0x23, 0xfd, + 0xdb, 0x13, 0x6e, 0x6a, 0x93, 0xc4, 0x62, 0x8f, 0x2a, 0x8e, 0x3b, 0x44, + 0xa5, 0x22, 0x2b, 0x5b, 0xe6, 0xa0, 0x14, 0x02, 0x03, 0xd1, 0xdc, 0x2b, + 0xbb, 0x82, 0x04, 0x7c, 0x87, 0x22, 0xb4, 0xa4, 0x5a, 0x6c, 0x2c, 0xfa, + 0xdc, 0x56, 0x9f, 0x4c, 0x71, 0xb0, 0x6d, 0xcc, 0x3f, 0x99, 0x8c, 0xc9, + 0x02, 0x82, 0x01, 0x00, 0x45, 0xee, 0xc9, 0x30, 0x7a, 0xb0, 0xb4, 0x5d, + 0x16, 0xdb, 0xaa, 0x6d, 0x59, 0x2a, 0xd6, 0x99, 0x42, 0x4d, 0x71, 0x72, + 0x6c, 0xf2, 0x3e, 0xa8, 0xcf, 0xb5, 0xfd, 0x4b, 0x2c, 0x9e, 0x1b, 0x74, + 0x14, 0x69, 0x9c, 0xcc, 0x2f, 0x69, 0x52, 0x4c, 0x66, 0x16, 0x44, 0xdb, + 0x2b, 0x51, 0xd6, 0x1f, 0x83, 0x5f, 0x19, 0x2d, 0x10, 0x5a, 0x6d, 0x71, + 0xdc, 0x97, 0xdd, 0x58, 0x08, 0x72, 0x20, 0xf0, 0xe2, 0xf5, 0x32, 0x20, + 0xfe, 0xfb, 0x51, 0x1a, 0x18, 0x6b, 0x19, 0xc5, 0xae, 0xcf, 0x3c, 0xb6, + 0x17, 0x81, 0x02, 0x20, 0x56, 0xf8, 0xe4, 0x21, 0x63, 0xaa, 0x58, 0xd1, + 0xc3, 0xf5, 0x13, 0x53, 0x9f, 0xa4, 0xa4, 0x00, 0x98, 0x1a, 0x5f, 0x12, + 0x46, 0x1d, 0xee, 0x17, 0x3a, 0xf2, 0xad, 0x1f, 0x11, 0x3b, 0xfc, 0x95, + 0xdf, 0x6b, 0xe6, 0x44, 0xb6, 0xfd, 0x67, 0x99, 0xa2, 0xf9, 0xbb, 0x52, + 0xda, 0xb9, 0xfb, 0xb3, 0xb2, 0xf1, 0xf2, 0x34, 0x96, 0xb4, 0x77, 0xec, + 0xe8, 0x63, 0xac, 0x4c, 0xaf, 0x83, 0x8f, 0x6e, 0x7b, 0x3d, 0x33, 0xfc, + 0x83, 0x35, 0x90, 0xa0, 0xe5, 0x96, 0xd7, 0x50, 0x80, 0xf0, 0xab, 0xec, + 0xed, 0x1d, 0x36, 0xdf, 0xf3, 0xe1, 0xba, 0xe0, 0x04, 0xef, 0x1a, 0x54, + 0x34, 0x65, 0x06, 0xd4, 0x02, 0x2d, 0x2d, 0xec, 0x53, 0x9f, 0x0d, 0x53, + 0xaf, 0x42, 0x51, 0x74, 0x6b, 0xc1, 0x45, 0x35, 0x0f, 0xa6, 0x66, 0x48, + 0x46, 0xf9, 0x85, 0x8f, 0x90, 0x69, 0x6e, 0xb4, 0xbf, 0x26, 0x72, 0x77, + 0x90, 0x76, 0xb1, 0x1f, 0x1f, 0x7e, 0x75, 0x96, 0x81, 0x83, 0x53, 0x67, + 0x05, 0x78, 0x5f, 0x4e, 0x8d, 0xaa, 0x4e, 0xcb, 0x58, 0x1d, 0x27, 0xbe, + 0x9a, 0x2f, 0x07, 0xd4, 0x4c, 0x15, 0x19, 0x58, 0x7d, 0x14, 0xa0, 0x38, + 0xf0, 0x06, 0x41, 0x89, 0x73, 0xe5, 0xa4, 0x37 +}; diff --git a/testkeys/RSA/4096_RSA_KEY.pem b/testkeys/RSA/4096_RSA_KEY.pem new file mode 100644 index 0000000..f2dc1cb --- /dev/null +++ b/testkeys/RSA/4096_RSA_KEY.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKAIBAAKCAgEAyPLbOa30Q5eibYUsFxQmJemPuHE8WFstGA+tdqf+j0ZMZ8Me +cOCC03dnnW12osp5cNKuviGmp0LqMMuWFaYhYmal3f8jeMngn3O4CB4OSYWN31Uk +QsFLyd4DoM/HryX9aujq/NMJhdtrnkqNcZHphKd1bd0uYIyvMPrdHg0EXHvCNQ3u +W+VigbmY8c4/klkf0OQXSPv+oLMsfAHAGVahIAgGfXDyL7KtRMLkW4QrmAaHr1Qr +t+T+Uy/y17Q0TUbfRC5yBNc0Pt6/VXR/PtTDPR98JPLtTzgd9LJHXuksI/PduxbZ +HLpTGhzxAvGO7Hlb+VUhZhJvnvCeP9y+1jE1wvJ4tgqbIqOmndP1TwVJAMTCwodD +BvxDPNr2+r33mfvVZG9p2U25xRoH1t9At0prFsgsI1/i7nxm3Tt8gECaudiZ995x +Pfc1hg9r+QHpU/kXzx9u+Kz6L18zEzP68c99a7nWo2gWhGCJbyzI5/LgyX+EzulF +GJaamawODmHqM789sYuSnt/GdWZWepqpm9h3ZK32QcQyO47pkFX+4wssQzeqink4 +tImbLaznbj8jszCihCGXjS0CFKz6Z0tsvDP1iYiKV92WnGpaBmIzseCqcMgFgYJi +PaBM33Gofn2zxnDxYKzWRtiFt2tft6GGtvXK9qKN6Xg3Ex3g0xOfDiAsJocCAwEA +AQKCAgBHj80ohl2FsLuEezePZHqNZ9bp3VGbOaUee37P0dXi2isdjKwLkLimbFB3 +DOOB589FsZHPXhaGXFsgU3A4d3hOHbYWD+Vm/6XBwykXovR9lFVI4n5OU54U3r62 +ByjapBHSf+4naVRr2g9CSNSETG0385brMChy88b0D3KtX/9cnCo2UKbBDTh+cEUa +X9Pd32VoM8JjGHK+cfB2nPz3SRWKXbFJ/O4StHPmF+3Q9Ym80x6A/t2u2JsFrv6x +eJhjqMib9FpghO8zMIo8+YbTLlv1KYBBfE2st5Rbbx3hm/I/P3qIRQO+qlAr7YCb +BsFaT4HEkl+ZhRlBJfmFTqybhNza1OuuxeXcAAkVdYVL8OMxhz3ljvEAIMebpPJw +Tm6A4rw1dq7KyLFH5CaQV60VpFRxM7FxmG2WxI3HNKkyau/YCoYy4okK0dgKaoQU +d946udParhf4DGOlQVZYqMSE0bL44x2/kfe0RtbHU7LriShkaID0cvjXUKsncFxN +IEOMUqBV7//7RoxiFJfQVXYs6Oilll18DQHPujIujBZAZkYNUDgqZRTgNL5d677W +/oujahGL2r96VUo0v5s9I9Numj9LYFiEMSvoku0UVxQIriEPCtKcdS8t0BS1FPqh +He/fKvhnyLifHYnp5ahETzrE1dv6sotoZrzfs2hbLJL4ScMt+QKCAQEA93xlxkML +YGD9/ODNN/yY+2u4T4vbeQxS62LVRGdPZxECWzcvzDEXREKWdshdRhvXrXpMFtyr +Helk08TkRnYFtAmLs7rKaLrwUHokM8G18reg2P29V+AyFZyww3TQsegm2NEiVg7X +OebtDmJMBTcFfRkQp/I2djTup8AK+HgvjdRoRNEZOQCLppxIy0rgU3iKDlLksrJq +GdiyKVTDtw/dBKVz7FOMgNeeRhS6DaKq8sZCp7u+FiG54EsoOuyaH5b/m2c0eIHs +EY2GAd2yMveboSn999d6HySGYs2icyeHHj9Fwe/5LhulDWmfx3DqVdcJfQ9lzeW2 +bdR3feGvr+YxRQKCAQEAz9ybMDADGnTOe9KaBNqRJ+h0fBxP65iecVaZDd0JStvJ +zPxiMVcue6KbWPSinVKptU2mKyS+Qvan5/LZyN5qhDWKtPEekmKgVenNZBcR4yjc +FjdswPXzL3bWoWNJP3T4eDgNO3/3151+ZSWKMOcH7d9VIZ7wBLTy911MZx+ib/3o +JPCsfG0rO5Opf4imqr5wod0vsjcThabTHXEtnXcPgpqeV0mulM6LJ89k6CvAIA8F +IjQeGZRq4b6mNslEpUoshS/83XChv89wLHi04XaJEuBN2fAdd6zFoVteWArTZGHO +Nix+im3Z55AKRzDK8JB3abgAkKXcUTCUyazcx5zHWwKCAQEAsORmblaffAz3ndck +d98BjbuJ6rmBbr0DS6HB4/mfxIBg2cfRTzbLdYvOtioymRjviNyAJFsnp+KZoc/6 +he531x53j0h0wnTTrgIPfDr6DPl5a3+55WSnB9GOerY1MORJV/Hrg+1posZPLFfQ +FG4maysOP6ydhtIAv0BB1yU4gDyRJpb6W0brinPsh/oF60OeEezn8F4b/ktn1Kj0 +lxUsmdSUzhdNtw3m4BqSfYqGe66AGBnWHUWP8SRnJe7Vnry0CGS1GWlrzYQFg7Ht +XAalY4V7NLn8XOQjdd2bPonDRzhcaOlYhr9VsweLH+eyZxajfpMR5iBJy6jwm7ZD +eAulrQKCAQAKHH0gFvXPr6brtw7u9YLiIhiogOgSWdY7RS8k0X/GOHLUmeJc7BTC +xuIvrZbLeF3xB9nxd1QaBc2dJt8ZOliMHd6ldqU6Eboi88CeAdFI74/lNMUBjfVK +dclzCFVj1NjRYEikgFEaF/syCGV0g4iLNbX6cLTURckb51n0GkHYmM1WHq8FTnov +57rzDT6uR51LAmtzi+JTOg5C/GJvqn8Cp2rUbC0l5/Y09Y2/DYHHDXP+efKM4/9f +A9sqBxhjwfvwbqkqTHRR1FFsmGKUJSP92xNuapPEYo8qjjtEpSIrW+agFAID0dwr +u4IEfIcitKRabCz63FafTHGwbcw/mYzJAoIBAEXuyTB6sLRdFtuqbVkq1plCTXFy +bPI+qM+1/Ussnht0FGmczC9pUkxmFkTbK1HWH4NfGS0QWm1x3JfdWAhyIPDi9TIg +/vtRGhhrGcWuzzy2F4ECIFb45CFjqljRw/UTU5+kpACYGl8SRh3uFzryrR8RO/yV +32vmRLb9Z5mi+btS2rn7s7Lx8jSWtHfs6GOsTK+Dj257PTP8gzWQoOWW11CA8Kvs +7R023/PhuuAE7xpUNGUG1AItLexTnw1Tr0JRdGvBRTUPpmZIRvmFj5BpbrS/JnJ3 +kHaxHx9+dZaBg1NnBXhfTo2qTstYHSe+mi8H1EwVGVh9FKA48AZBiXPlpDc= +-----END RSA PRIVATE KEY----- diff --git a/testkeys/RSA/ALL_RSA_CAS.h b/testkeys/RSA/ALL_RSA_CAS.h new file mode 100644 index 0000000..6aa791e --- /dev/null +++ b/testkeys/RSA/ALL_RSA_CAS.h @@ -0,0 +1,269 @@ +/** + * @file ALL_RSA_CAS.h + * @version $Format:%h%d$ + * + * Summary. + */ +unsigned char RSACAS[] = { +48, 130, 3, 13, 48, 130, 2, 118, 160, 3, 2, 1, 2, +2, 4, 49, 50, 51, 52, 48, 13, 6, 9, 42, 134, 72, +134, 247, 13, 1, 1, 11, 5, 0, 48, 129, 150, 49, 53, +48, 51, 6, 3, 85, 4, 3, 12, 44, 83, 97, 109, 112, +108, 101, 32, 77, 97, 116, 114, 105, 120, 32, 82, 83, 65, +45, 49, 48, 50, 52, 32, 67, 101, 114, 116, 105, 102, 105, +99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, +121, 49, 11, 48, 9, 6, 3, 85, 4, 6, 12, 2, 85, +83, 49, 11, 48, 9, 6, 3, 85, 4, 8, 12, 2, 87, +65, 49, 16, 48, 14, 6, 3, 85, 4, 7, 12, 7, 83, +101, 97, 116, 116, 108, 101, 49, 34, 48, 32, 6, 3, 85, +4, 10, 12, 25, 73, 78, 83, 73, 68, 69, 32, 83, 101, +99, 117, 114, 101, 32, 67, 111, 114, 112, 111, 114, 97, 116, +105, 111, 110, 49, 13, 48, 11, 6, 3, 85, 4, 11, 12, +4, 84, 101, 115, 116, 48, 30, 23, 13, 49, 52, 48, 51, +50, 52, 49, 54, 50, 54, 52, 54, 90, 23, 13, 49, 55, +48, 51, 50, 51, 49, 54, 50, 54, 52, 54, 90, 48, 129, +150, 49, 53, 48, 51, 6, 3, 85, 4, 3, 12, 44, 83, +97, 109, 112, 108, 101, 32, 77, 97, 116, 114, 105, 120, 32, +82, 83, 65, 45, 49, 48, 50, 52, 32, 67, 101, 114, 116, +105, 102, 105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, +114, 105, 116, 121, 49, 11, 48, 9, 6, 3, 85, 4, 6, +12, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, 4, 8, +12, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, 4, 7, +12, 7, 83, 101, 97, 116, 116, 108, 101, 49, 34, 48, 32, +6, 3, 85, 4, 10, 12, 25, 73, 78, 83, 73, 68, 69, +32, 83, 101, 99, 117, 114, 101, 32, 67, 111, 114, 112, 111, +114, 97, 116, 105, 111, 110, 49, 13, 48, 11, 6, 3, 85, +4, 11, 12, 4, 84, 101, 115, 116, 48, 129, 159, 48, 13, +6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, +3, 129, 141, 0, 48, 129, 137, 2, 129, 129, 0, 191, 64, +80, 242, 226, 56, 57, 33, 56, 116, 145, 34, 113, 4, 29, +198, 49, 53, 74, 169, 55, 198, 177, 97, 20, 225, 167, 222, +111, 25, 15, 207, 20, 160, 234, 84, 115, 214, 32, 157, 55, +52, 128, 187, 198, 116, 140, 77, 156, 81, 22, 13, 214, 52, +231, 167, 4, 188, 224, 147, 232, 31, 154, 62, 152, 220, 93, +22, 227, 213, 225, 134, 34, 223, 98, 137, 155, 103, 206, 132, +218, 48, 118, 168, 205, 32, 199, 27, 53, 112, 168, 226, 170, +45, 218, 168, 140, 48, 181, 44, 34, 12, 229, 83, 17, 180, +181, 22, 13, 28, 185, 159, 245, 224, 66, 193, 232, 3, 210, +182, 123, 113, 46, 167, 1, 138, 105, 249, 2, 3, 1, 0, +1, 163, 102, 48, 100, 48, 18, 6, 3, 85, 29, 19, 1, +1, 255, 4, 8, 48, 6, 1, 1, 255, 2, 1, 0, 48, +29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 247, 36, 136, +131, 147, 137, 77, 217, 3, 85, 193, 56, 39, 23, 64, 229, +236, 225, 212, 176, 48, 31, 6, 3, 85, 29, 35, 4, 24, +48, 22, 128, 20, 247, 36, 136, 131, 147, 137, 77, 217, 3, +85, 193, 56, 39, 23, 64, 229, 236, 225, 212, 176, 48, 14, +6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 0, +4, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, +11, 5, 0, 3, 129, 129, 0, 65, 150, 217, 193, 56, 223, +116, 222, 228, 127, 198, 122, 215, 202, 221, 239, 249, 204, 117, +121, 131, 172, 55, 115, 221, 100, 155, 10, 152, 132, 127, 157, +102, 66, 199, 205, 140, 152, 28, 245, 122, 49, 213, 23, 103, +168, 201, 98, 142, 162, 54, 138, 252, 218, 248, 100, 205, 156, +107, 120, 45, 239, 124, 243, 202, 202, 227, 134, 199, 133, 247, +147, 39, 81, 67, 84, 247, 188, 185, 208, 39, 24, 109, 198, +186, 14, 224, 197, 23, 172, 85, 35, 162, 180, 31, 28, 86, +12, 39, 129, 68, 66, 64, 207, 16, 27, 34, 12, 211, 137, +159, 9, 242, 243, 51, 107, 211, 28, 59, 146, 167, 171, 94, +189, 58, 233, 130, 140, +48, 130, 4, 20, 48, 130, 2, 252, 160, 3, 2, 1, 2, +2, 6, 50, 51, 52, 53, 54, 55, 48, 13, 6, 9, 42, +134, 72, 134, 247, 13, 1, 1, 11, 5, 0, 48, 129, 150, +49, 53, 48, 51, 6, 3, 85, 4, 3, 12, 44, 83, 97, +109, 112, 108, 101, 32, 77, 97, 116, 114, 105, 120, 32, 82, +83, 65, 45, 50, 48, 52, 56, 32, 67, 101, 114, 116, 105, +102, 105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, +105, 116, 121, 49, 11, 48, 9, 6, 3, 85, 4, 6, 12, +2, 85, 83, 49, 11, 48, 9, 6, 3, 85, 4, 8, 12, +2, 87, 65, 49, 16, 48, 14, 6, 3, 85, 4, 7, 12, +7, 83, 101, 97, 116, 116, 108, 101, 49, 34, 48, 32, 6, +3, 85, 4, 10, 12, 25, 73, 78, 83, 73, 68, 69, 32, +83, 101, 99, 117, 114, 101, 32, 67, 111, 114, 112, 111, 114, +97, 116, 105, 111, 110, 49, 13, 48, 11, 6, 3, 85, 4, +11, 12, 4, 84, 101, 115, 116, 48, 30, 23, 13, 49, 52, +48, 51, 50, 52, 49, 54, 50, 55, 48, 51, 90, 23, 13, +49, 55, 48, 51, 50, 51, 49, 54, 50, 55, 48, 51, 90, +48, 129, 150, 49, 53, 48, 51, 6, 3, 85, 4, 3, 12, +44, 83, 97, 109, 112, 108, 101, 32, 77, 97, 116, 114, 105, +120, 32, 82, 83, 65, 45, 50, 48, 52, 56, 32, 67, 101, +114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 65, 117, 116, +104, 111, 114, 105, 116, 121, 49, 11, 48, 9, 6, 3, 85, +4, 6, 12, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, +4, 8, 12, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, +4, 7, 12, 7, 83, 101, 97, 116, 116, 108, 101, 49, 34, +48, 32, 6, 3, 85, 4, 10, 12, 25, 73, 78, 83, 73, +68, 69, 32, 83, 101, 99, 117, 114, 101, 32, 67, 111, 114, +112, 111, 114, 97, 116, 105, 111, 110, 49, 13, 48, 11, 6, +3, 85, 4, 11, 12, 4, 84, 101, 115, 116, 48, 130, 1, +34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, +1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, +130, 1, 1, 0, 204, 171, 91, 64, 59, 10, 75, 192, 131, +92, 104, 229, 244, 0, 90, 21, 26, 227, 120, 243, 160, 65, +35, 147, 90, 193, 198, 250, 4, 144, 163, 69, 142, 48, 92, +145, 138, 109, 132, 191, 120, 192, 203, 177, 238, 101, 175, 170, +93, 186, 241, 53, 4, 181, 64, 148, 237, 188, 140, 245, 235, +161, 187, 143, 162, 250, 183, 170, 236, 83, 119, 139, 175, 182, +209, 120, 241, 88, 89, 0, 108, 143, 152, 68, 29, 115, 76, +225, 26, 138, 176, 97, 128, 221, 192, 223, 155, 116, 95, 208, +124, 102, 102, 35, 220, 48, 156, 77, 224, 236, 218, 110, 4, +196, 200, 98, 162, 33, 17, 239, 40, 220, 109, 233, 49, 183, +122, 158, 202, 219, 186, 194, 156, 147, 30, 36, 169, 154, 116, +190, 164, 38, 78, 187, 95, 121, 4, 211, 65, 114, 5, 162, +83, 154, 68, 32, 1, 72, 68, 93, 51, 114, 99, 63, 170, +162, 119, 9, 245, 195, 226, 38, 181, 18, 135, 33, 173, 74, +231, 153, 153, 239, 61, 178, 250, 189, 178, 194, 106, 206, 166, +58, 133, 122, 63, 32, 148, 186, 21, 127, 122, 130, 233, 111, +190, 160, 186, 234, 208, 228, 58, 57, 168, 187, 85, 96, 184, +40, 58, 209, 163, 7, 80, 81, 245, 128, 43, 244, 90, 130, +27, 125, 86, 169, 49, 4, 35, 177, 52, 210, 113, 213, 28, +146, 130, 213, 182, 252, 116, 134, 6, 106, 241, 232, 114, 209, +2, 3, 1, 0, 1, 163, 102, 48, 100, 48, 18, 6, 3, +85, 29, 19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, +2, 1, 0, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, +20, 244, 159, 233, 145, 67, 172, 28, 155, 221, 7, 64, 45, +105, 103, 60, 239, 212, 234, 219, 84, 48, 31, 6, 3, 85, +29, 35, 4, 24, 48, 22, 128, 20, 244, 159, 233, 145, 67, +172, 28, 155, 221, 7, 64, 45, 105, 103, 60, 239, 212, 234, +219, 84, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, +4, 3, 2, 0, 4, 48, 13, 6, 9, 42, 134, 72, 134, +247, 13, 1, 1, 11, 5, 0, 3, 130, 1, 1, 0, 128, +97, 82, 97, 34, 77, 252, 71, 207, 86, 8, 205, 176, 19, +181, 173, 59, 182, 10, 113, 87, 194, 192, 254, 1, 255, 137, +96, 24, 104, 238, 224, 129, 30, 156, 67, 75, 49, 166, 91, +200, 37, 132, 75, 17, 42, 94, 250, 167, 191, 103, 142, 58, +207, 143, 110, 234, 58, 239, 218, 196, 50, 97, 169, 93, 43, +139, 244, 139, 43, 138, 209, 157, 24, 215, 15, 210, 155, 225, +250, 0, 175, 214, 254, 255, 71, 29, 122, 85, 233, 131, 62, +202, 239, 75, 13, 232, 44, 66, 246, 191, 109, 129, 10, 82, +175, 169, 227, 249, 25, 201, 86, 64, 93, 88, 30, 241, 254, +55, 142, 80, 23, 250, 15, 102, 156, 145, 142, 136, 231, 92, +201, 48, 140, 53, 22, 146, 112, 122, 52, 170, 196, 240, 186, +144, 21, 71, 44, 175, 174, 134, 12, 181, 149, 229, 40, 98, +163, 32, 86, 191, 183, 26, 75, 79, 233, 243, 196, 24, 240, +191, 195, 211, 122, 207, 233, 64, 159, 136, 136, 96, 117, 107, +152, 181, 61, 171, 48, 202, 91, 149, 199, 162, 248, 102, 71, +3, 113, 137, 192, 87, 242, 235, 179, 169, 73, 242, 16, 254, +168, 125, 107, 144, 102, 248, 159, 70, 159, 180, 44, 95, 227, +21, 247, 211, 68, 215, 233, 23, 61, 81, 25, 140, 46, 77, +177, 203, 55, 112, 148, 86, 40, 140, 197, 108, 147, 19, 179, +235, 26, 12, 112, 78, 212, 53, 47, +48, 130, 6, 19, 48, 130, 3, 251, 160, 3, 2, 1, 2, +2, 5, 51, 52, 53, 54, 55, 48, 13, 6, 9, 42, 134, +72, 134, 247, 13, 1, 1, 11, 5, 0, 48, 129, 150, 49, +53, 48, 51, 6, 3, 85, 4, 3, 12, 44, 83, 97, 109, +112, 108, 101, 32, 77, 97, 116, 114, 105, 120, 32, 82, 83, +65, 45, 52, 48, 57, 54, 32, 67, 101, 114, 116, 105, 102, +105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, +116, 121, 49, 11, 48, 9, 6, 3, 85, 4, 6, 12, 2, +85, 83, 49, 11, 48, 9, 6, 3, 85, 4, 8, 12, 2, +87, 65, 49, 16, 48, 14, 6, 3, 85, 4, 7, 12, 7, +83, 101, 97, 116, 116, 108, 101, 49, 34, 48, 32, 6, 3, +85, 4, 10, 12, 25, 73, 78, 83, 73, 68, 69, 32, 83, +101, 99, 117, 114, 101, 32, 67, 111, 114, 112, 111, 114, 97, +116, 105, 111, 110, 49, 13, 48, 11, 6, 3, 85, 4, 11, +12, 4, 84, 101, 115, 116, 48, 30, 23, 13, 49, 52, 48, +51, 50, 52, 49, 54, 52, 49, 48, 51, 90, 23, 13, 49, +55, 48, 51, 50, 51, 49, 54, 52, 49, 48, 51, 90, 48, +129, 150, 49, 53, 48, 51, 6, 3, 85, 4, 3, 12, 44, +83, 97, 109, 112, 108, 101, 32, 77, 97, 116, 114, 105, 120, +32, 82, 83, 65, 45, 52, 48, 57, 54, 32, 67, 101, 114, +116, 105, 102, 105, 99, 97, 116, 101, 32, 65, 117, 116, 104, +111, 114, 105, 116, 121, 49, 11, 48, 9, 6, 3, 85, 4, +6, 12, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, 4, +8, 12, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, 4, +7, 12, 7, 83, 101, 97, 116, 116, 108, 101, 49, 34, 48, +32, 6, 3, 85, 4, 10, 12, 25, 73, 78, 83, 73, 68, +69, 32, 83, 101, 99, 117, 114, 101, 32, 67, 111, 114, 112, +111, 114, 97, 116, 105, 111, 110, 49, 13, 48, 11, 6, 3, +85, 4, 11, 12, 4, 84, 101, 115, 116, 48, 130, 2, 34, +48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, +5, 0, 3, 130, 2, 15, 0, 48, 130, 2, 10, 2, 130, +2, 1, 0, 187, 177, 68, 68, 161, 213, 217, 13, 226, 54, +73, 38, 190, 105, 203, 14, 136, 74, 40, 239, 174, 44, 79, +157, 37, 197, 138, 191, 158, 81, 228, 119, 86, 75, 77, 117, +145, 29, 74, 210, 204, 179, 11, 47, 228, 66, 114, 250, 178, +159, 210, 39, 224, 12, 195, 254, 131, 58, 150, 160, 212, 165, +154, 148, 96, 186, 12, 191, 171, 142, 104, 207, 31, 196, 114, +109, 87, 206, 96, 35, 76, 9, 244, 248, 107, 198, 89, 218, +215, 204, 58, 194, 152, 131, 181, 252, 55, 67, 143, 28, 0, +74, 142, 13, 73, 245, 241, 235, 166, 79, 197, 49, 13, 111, +46, 244, 102, 10, 245, 220, 235, 175, 28, 113, 99, 225, 86, +19, 174, 90, 202, 252, 152, 177, 99, 16, 66, 240, 155, 139, +144, 227, 211, 215, 225, 185, 95, 15, 203, 253, 199, 116, 107, +84, 95, 45, 209, 113, 186, 12, 148, 116, 51, 192, 62, 225, +151, 103, 15, 42, 93, 238, 78, 220, 123, 254, 221, 43, 100, +101, 65, 25, 176, 109, 148, 85, 24, 12, 111, 112, 60, 194, +36, 87, 161, 252, 190, 235, 240, 240, 249, 133, 162, 163, 102, +130, 39, 251, 112, 195, 220, 114, 95, 231, 96, 215, 59, 12, +133, 107, 193, 197, 88, 87, 187, 173, 240, 77, 1, 163, 202, +145, 156, 75, 151, 21, 102, 227, 25, 42, 88, 131, 68, 226, +24, 25, 252, 144, 73, 113, 176, 89, 117, 58, 230, 116, 249, +108, 67, 254, 2, 201, 192, 185, 168, 9, 128, 57, 60, 234, +134, 125, 98, 75, 148, 67, 242, 74, 99, 52, 68, 3, 34, +53, 152, 182, 155, 103, 198, 147, 100, 128, 148, 168, 153, 222, +215, 135, 3, 26, 152, 28, 249, 208, 111, 121, 170, 222, 140, +47, 181, 34, 169, 255, 17, 252, 170, 91, 47, 76, 197, 230, +68, 101, 133, 228, 186, 119, 189, 51, 131, 104, 51, 86, 209, +87, 64, 80, 0, 136, 105, 106, 22, 137, 79, 239, 144, 103, +86, 97, 121, 105, 162, 132, 159, 237, 145, 203, 76, 187, 175, +242, 157, 239, 227, 50, 108, 55, 100, 234, 117, 255, 197, 236, +136, 189, 107, 67, 254, 104, 20, 212, 199, 155, 244, 174, 116, +234, 225, 180, 99, 42, 14, 245, 156, 190, 159, 110, 78, 143, +9, 62, 67, 141, 79, 179, 5, 37, 254, 250, 123, 230, 29, +230, 232, 32, 27, 76, 48, 61, 224, 183, 118, 105, 11, 241, +7, 3, 31, 143, 87, 191, 85, 207, 17, 152, 182, 153, 223, +123, 155, 190, 152, 22, 187, 210, 129, 193, 235, 159, 8, 174, +126, 68, 169, 167, 121, 73, 2, 172, 138, 129, 188, 146, 198, +209, 239, 204, 157, 20, 178, 244, 9, 175, 28, 178, 11, 2, +50, 221, 205, 252, 9, 131, 62, 28, 51, 88, 43, 119, 213, +72, 166, 91, 117, 159, 102, 49, 17, 83, 71, 200, 199, 68, +9, 201, 147, 196, 28, 50, 8, 105, 2, 3, 1, 0, 1, +163, 102, 48, 100, 48, 18, 6, 3, 85, 29, 19, 1, 1, +255, 4, 8, 48, 6, 1, 1, 255, 2, 1, 0, 48, 29, +6, 3, 85, 29, 14, 4, 22, 4, 20, 108, 66, 132, 197, +224, 75, 220, 112, 242, 153, 208, 28, 131, 74, 226, 81, 71, +101, 30, 250, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, +22, 128, 20, 108, 66, 132, 197, 224, 75, 220, 112, 242, 153, +208, 28, 131, 74, 226, 81, 71, 101, 30, 250, 48, 14, 6, +3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 0, 4, +48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, +5, 0, 3, 130, 2, 1, 0, 102, 180, 88, 152, 103, 27, +219, 206, 99, 95, 195, 113, 137, 160, 173, 153, 16, 192, 39, +188, 91, 195, 160, 177, 205, 182, 237, 220, 22, 6, 51, 58, +82, 98, 85, 7, 124, 108, 190, 199, 236, 22, 107, 127, 38, +124, 117, 112, 41, 25, 21, 136, 64, 93, 37, 250, 80, 57, +12, 106, 60, 199, 16, 202, 169, 185, 68, 48, 102, 147, 73, +15, 10, 26, 111, 120, 161, 67, 179, 72, 77, 106, 145, 62, +169, 190, 188, 217, 148, 120, 41, 224, 196, 135, 151, 148, 153, +4, 148, 42, 33, 240, 162, 49, 152, 253, 35, 143, 192, 50, +226, 177, 246, 228, 134, 95, 61, 148, 111, 132, 151, 62, 206, +159, 183, 125, 134, 254, 168, 40, 44, 217, 184, 208, 239, 154, +127, 202, 60, 218, 175, 7, 15, 223, 211, 24, 93, 39, 214, +158, 130, 27, 9, 212, 81, 58, 117, 126, 55, 182, 226, 92, +230, 68, 62, 81, 7, 37, 178, 230, 246, 14, 152, 68, 35, +13, 95, 21, 236, 63, 97, 86, 95, 65, 132, 70, 59, 78, +106, 63, 77, 108, 154, 176, 133, 133, 185, 41, 243, 179, 2, +148, 181, 195, 150, 120, 192, 213, 97, 18, 246, 97, 10, 139, +155, 128, 214, 60, 164, 26, 13, 77, 121, 115, 118, 164, 143, +154, 233, 118, 243, 139, 118, 185, 109, 162, 245, 39, 187, 198, +172, 228, 37, 1, 186, 3, 53, 53, 2, 200, 207, 173, 121, +28, 31, 148, 62, 178, 219, 184, 167, 232, 110, 139, 68, 21, +162, 175, 74, 103, 155, 186, 104, 73, 133, 238, 147, 196, 95, +151, 119, 224, 180, 144, 142, 89, 236, 38, 8, 164, 82, 180, +157, 21, 123, 92, 63, 94, 91, 91, 130, 105, 255, 249, 141, +254, 14, 13, 34, 20, 221, 57, 106, 162, 3, 93, 223, 254, +96, 28, 146, 249, 31, 9, 173, 173, 149, 51, 180, 176, 124, +76, 99, 159, 48, 212, 134, 125, 138, 75, 6, 249, 106, 102, +205, 134, 14, 252, 252, 194, 101, 169, 97, 62, 237, 172, 213, +244, 197, 149, 143, 100, 26, 158, 20, 111, 224, 152, 184, 150, +204, 14, 162, 177, 26, 32, 7, 96, 206, 210, 156, 48, 48, +224, 83, 252, 31, 239, 225, 35, 171, 61, 119, 200, 208, 113, +221, 172, 158, 28, 164, 126, 55, 118, 121, 253, 144, 91, 194, +119, 129, 207, 65, 31, 16, 156, 23, 92, 186, 186, 12, 202, +240, 221, 26, 187, 42, 93, 168, 198, 60, 40, 19, 221, 163, +213, 163, 204, 52, 44, 176, 9, 66, 163, 241, 149, 215, 74, +213, 178, 175, 163, 173, 194, 114, 103, 72, 109, 93, 90, 35, +127, 182, 57, 247, 165, 205, 195, 1, 155, 126, 145, 87, 173, +105, 250, 106, 27, 93, 37, 103, 200, 30, 76, 8, 108, 27, +229, 214, 55, 160, 201, 152, 195, 102, 100, 102, 213, 114, 48, +92, 179, 21, 200, 102, 34, 5, 46, 218, 97, 169, 202}; diff --git a/testkeys/RSA/ALL_RSA_CAS.pem b/testkeys/RSA/ALL_RSA_CAS.pem new file mode 100644 index 0000000..a85f09c --- /dev/null +++ b/testkeys/RSA/ALL_RSA_CAS.pem @@ -0,0 +1,78 @@ +-----BEGIN CERTIFICATE----- +MIIDDTCCAnagAwIBAgIEMTIzNDANBgkqhkiG9w0BAQsFADCBljE1MDMGA1UEAwws +U2FtcGxlIE1hdHJpeCBSU0EtMTAyNCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxCzAJ +BgNVBAYMAlVTMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UE +CgwZSU5TSURFIFNlY3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDAeFw0x +NDAzMjQxNjI2NDZaFw0xNzAzMjMxNjI2NDZaMIGWMTUwMwYDVQQDDCxTYW1wbGUg +TWF0cml4IFJTQS0xMDI0IENlcnRpZmljYXRlIEF1dGhvcml0eTELMAkGA1UEBgwC +VVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMSIwIAYDVQQKDBlJTlNJ +REUgU2VjdXJlIENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MIGfMA0GCSqGSIb3 +DQEBAQUAA4GNADCBiQKBgQC/QFDy4jg5ITh0kSJxBB3GMTVKqTfGsWEU4afebxkP +zxSg6lRz1iCdNzSAu8Z0jE2cURYN1jTnpwS84JPoH5o+mNxdFuPV4YYi32KJm2fO +hNowdqjNIMcbNXCo4qot2qiMMLUsIgzlUxG0tRYNHLmf9eBCwegD0rZ7cS6nAYpp ++QIDAQABo2YwZDASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBT3JIiDk4lN +2QNVwTgnF0Dl7OHUsDAfBgNVHSMEGDAWgBT3JIiDk4lN2QNVwTgnF0Dl7OHUsDAO +BgNVHQ8BAf8EBAMCAAQwDQYJKoZIhvcNAQELBQADgYEAQZbZwTjfdN7kf8Z618rd +7/nMdXmDrDdz3WSbCpiEf51mQsfNjJgc9Xox1RdnqMlijqI2ivza+GTNnGt4Le98 +88rK44bHhfeTJ1FDVPe8udAnGG3Gug7gxResVSOitB8cVgwngURCQM8QGyIM04mf +CfLzM2vTHDuSp6tevTrpgow= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEFDCCAvygAwIBAgIGMjM0NTY3MA0GCSqGSIb3DQEBCwUAMIGWMTUwMwYDVQQD +DCxTYW1wbGUgTWF0cml4IFJTQS0yMDQ4IENlcnRpZmljYXRlIEF1dGhvcml0eTEL +MAkGA1UEBgwCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMSIwIAYD +VQQKDBlJTlNJREUgU2VjdXJlIENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MB4X +DTE0MDMyNDE2MjcwM1oXDTE3MDMyMzE2MjcwM1owgZYxNTAzBgNVBAMMLFNhbXBs +ZSBNYXRyaXggUlNBLTIwNDggQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQswCQYDVQQG +DAJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUlO +U0lERSBTZWN1cmUgQ29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMq1tAOwpLwINcaOX0AFoVGuN486BBI5Na +wcb6BJCjRY4wXJGKbYS/eMDLse5lr6pduvE1BLVAlO28jPXrobuPovq3quxTd4uv +ttF48VhZAGyPmEQdc0zhGoqwYYDdwN+bdF/QfGZmI9wwnE3g7NpuBMTIYqIhEe8o +3G3pMbd6nsrbusKckx4kqZp0vqQmTrtfeQTTQXIFolOaRCABSERdM3JjP6qidwn1 +w+ImtRKHIa1K55mZ7z2y+r2ywmrOpjqFej8glLoVf3qC6W++oLrq0OQ6Oai7VWC4 +KDrRowdQUfWAK/Raght9VqkxBCOxNNJx1RySgtW2/HSGBmrx6HLRAgMBAAGjZjBk +MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFPSf6ZFDrByb3QdALWlnPO/U +6ttUMB8GA1UdIwQYMBaAFPSf6ZFDrByb3QdALWlnPO/U6ttUMA4GA1UdDwEB/wQE +AwIABDANBgkqhkiG9w0BAQsFAAOCAQEAgGFSYSJN/EfPVgjNsBO1rTu2CnFXwsD+ +Af+JYBho7uCBHpxDSzGmW8glhEsRKl76p79njjrPj27qOu/axDJhqV0ri/SLK4rR +nRjXD9Kb4foAr9b+/0cdelXpgz7K70sN6CxC9r9tgQpSr6nj+RnJVkBdWB7x/jeO +UBf6D2ackY6I51zJMIw1FpJwejSqxPC6kBVHLK+uhgy1leUoYqMgVr+3GktP6fPE +GPC/w9N6z+lAn4iIYHVrmLU9qzDKW5XHovhmRwNxicBX8uuzqUnyEP6ofWuQZvif +Rp+0LF/jFffTRNfpFz1RGYwuTbHLN3CUViiMxWyTE7PrGgxwTtQ1Lw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGEzCCA/ugAwIBAgIFMzQ1NjcwDQYJKoZIhvcNAQELBQAwgZYxNTAzBgNVBAMM +LFNhbXBsZSBNYXRyaXggUlNBLTQwOTYgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQsw +CQYDVQQGDAJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNV +BAoMGUlOU0lERSBTZWN1cmUgQ29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QwHhcN +MTQwMzI0MTY0MTAzWhcNMTcwMzIzMTY0MTAzWjCBljE1MDMGA1UEAwwsU2FtcGxl +IE1hdHJpeCBSU0EtNDA5NiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxCzAJBgNVBAYM +AlVTMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSU5T +SURFIFNlY3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDCCAiIwDQYJKoZI +hvcNAQEBBQADggIPADCCAgoCggIBALuxRESh1dkN4jZJJr5pyw6ISijvrixPnSXF +ir+eUeR3VktNdZEdStLMswsv5EJy+rKf0ifgDMP+gzqWoNSlmpRgugy/q45ozx/E +cm1XzmAjTAn0+GvGWdrXzDrCmIO1/DdDjxwASo4NSfXx66ZPxTENby70Zgr13Ouv +HHFj4VYTrlrK/JixYxBC8JuLkOPT1+G5Xw/L/cd0a1RfLdFxugyUdDPAPuGXZw8q +Xe5O3Hv+3StkZUEZsG2UVRgMb3A8wiRXofy+6/Dw+YWio2aCJ/tww9xyX+dg1zsM +hWvBxVhXu63wTQGjypGcS5cVZuMZKliDROIYGfyQSXGwWXU65nT5bEP+AsnAuagJ +gDk86oZ9YkuUQ/JKYzREAyI1mLabZ8aTZICUqJne14cDGpgc+dBvearejC+1Iqn/ +EfyqWy9MxeZEZYXkune9M4NoM1bRV0BQAIhpahaJT++QZ1ZheWmihJ/tkctMu6/y +ne/jMmw3ZOp1/8XsiL1rQ/5oFNTHm/SudOrhtGMqDvWcvp9uTo8JPkONT7MFJf76 +e+Yd5uggG0wwPeC3dmkL8QcDH49Xv1XPEZi2md97m76YFrvSgcHrnwiufkSpp3lJ +AqyKgbySxtHvzJ0UsvQJrxyyCwIy3c38CYM+HDNYK3fVSKZbdZ9mMRFTR8jHRAnJ +k8QcMghpAgMBAAGjZjBkMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFGxC +hMXgS9xw8pnQHINK4lFHZR76MB8GA1UdIwQYMBaAFGxChMXgS9xw8pnQHINK4lFH +ZR76MA4GA1UdDwEB/wQEAwIABDANBgkqhkiG9w0BAQsFAAOCAgEAZrRYmGcb285j +X8NxiaCtmRDAJ7xbw6Cxzbbt3BYGMzpSYlUHfGy+x+wWa38mfHVwKRkViEBdJfpQ +OQxqPMcQyqm5RDBmk0kPChpveKFDs0hNapE+qb682ZR4KeDEh5eUmQSUKiHwojGY +/SOPwDLisfbkhl89lG+Elz7On7d9hv6oKCzZuNDvmn/KPNqvBw/f0xhdJ9aeghsJ +1FE6dX43tuJc5kQ+UQclsub2DphEIw1fFew/YVZfQYRGO05qP01smrCFhbkp87MC +lLXDlnjA1WES9mEKi5uA1jykGg1NeXN2pI+a6Xbzi3a5baL1J7vGrOQlAboDNTUC +yM+teRwflD6y27in6G6LRBWir0pnm7poSYXuk8Rfl3fgtJCOWewmCKRStJ0Ve1w/ +Xltbgmn/+Y3+Dg0iFN05aqIDXd/+YByS+R8Jra2VM7SwfExjnzDUhn2KSwb5ambN +hg78/MJlqWE+7azV9MWVj2QanhRv4Ji4lswOorEaIAdgztKcMDDgU/wf7+Ejqz13 +yNBx3ayeHKR+N3Z5/ZBbwneBz0EfEJwXXLq6DMrw3Rq7Kl2oxjwoE92j1aPMNCyw +CUKj8ZXXStWyr6OtwnJnSG1dWiN/tjn3pc3DAZt+kVetafpqG10lZ8geTAhsG+XW +N6DJmMNmZGbVcjBcsxXIZiIFLtphqco= +-----END CERTIFICATE----- diff --git a/testkeys/RSA/ALL_RSA_CAS_EXCEPT_1024.h b/testkeys/RSA/ALL_RSA_CAS_EXCEPT_1024.h new file mode 100644 index 0000000..6740a77 --- /dev/null +++ b/testkeys/RSA/ALL_RSA_CAS_EXCEPT_1024.h @@ -0,0 +1,319 @@ +const static unsigned char RSACAS[] = { + 0x30, 0x82, 0x04, 0x14, 0x30, 0x82, 0x02, 0xfc, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x06, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, + 0x30, 0x81, 0x96, 0x31, 0x35, 0x30, 0x33, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x2c, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x4d, 0x61, 0x74, + 0x72, 0x69, 0x78, 0x20, 0x52, 0x53, 0x41, 0x2d, 0x32, 0x30, 0x34, 0x38, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x0c, 0x02, 0x55, 0x53, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, + 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, + 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x4e, 0x53, 0x49, 0x44, 0x45, 0x20, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x30, 0x1e, 0x17, + 0x0d, 0x31, 0x34, 0x30, 0x33, 0x32, 0x34, 0x31, 0x36, 0x32, 0x37, 0x30, + 0x33, 0x5a, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x32, 0x33, 0x31, 0x36, + 0x32, 0x37, 0x30, 0x33, 0x5a, 0x30, 0x81, 0x96, 0x31, 0x35, 0x30, 0x33, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2c, 0x53, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x20, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x20, 0x52, 0x53, 0x41, + 0x2d, 0x32, 0x30, 0x34, 0x38, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x0c, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, + 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x4e, + 0x53, 0x49, 0x44, 0x45, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, + 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, + 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, + 0x73, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, + 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xcc, + 0xab, 0x5b, 0x40, 0x3b, 0x0a, 0x4b, 0xc0, 0x83, 0x5c, 0x68, 0xe5, 0xf4, + 0x00, 0x5a, 0x15, 0x1a, 0xe3, 0x78, 0xf3, 0xa0, 0x41, 0x23, 0x93, 0x5a, + 0xc1, 0xc6, 0xfa, 0x04, 0x90, 0xa3, 0x45, 0x8e, 0x30, 0x5c, 0x91, 0x8a, + 0x6d, 0x84, 0xbf, 0x78, 0xc0, 0xcb, 0xb1, 0xee, 0x65, 0xaf, 0xaa, 0x5d, + 0xba, 0xf1, 0x35, 0x04, 0xb5, 0x40, 0x94, 0xed, 0xbc, 0x8c, 0xf5, 0xeb, + 0xa1, 0xbb, 0x8f, 0xa2, 0xfa, 0xb7, 0xaa, 0xec, 0x53, 0x77, 0x8b, 0xaf, + 0xb6, 0xd1, 0x78, 0xf1, 0x58, 0x59, 0x00, 0x6c, 0x8f, 0x98, 0x44, 0x1d, + 0x73, 0x4c, 0xe1, 0x1a, 0x8a, 0xb0, 0x61, 0x80, 0xdd, 0xc0, 0xdf, 0x9b, + 0x74, 0x5f, 0xd0, 0x7c, 0x66, 0x66, 0x23, 0xdc, 0x30, 0x9c, 0x4d, 0xe0, + 0xec, 0xda, 0x6e, 0x04, 0xc4, 0xc8, 0x62, 0xa2, 0x21, 0x11, 0xef, 0x28, + 0xdc, 0x6d, 0xe9, 0x31, 0xb7, 0x7a, 0x9e, 0xca, 0xdb, 0xba, 0xc2, 0x9c, + 0x93, 0x1e, 0x24, 0xa9, 0x9a, 0x74, 0xbe, 0xa4, 0x26, 0x4e, 0xbb, 0x5f, + 0x79, 0x04, 0xd3, 0x41, 0x72, 0x05, 0xa2, 0x53, 0x9a, 0x44, 0x20, 0x01, + 0x48, 0x44, 0x5d, 0x33, 0x72, 0x63, 0x3f, 0xaa, 0xa2, 0x77, 0x09, 0xf5, + 0xc3, 0xe2, 0x26, 0xb5, 0x12, 0x87, 0x21, 0xad, 0x4a, 0xe7, 0x99, 0x99, + 0xef, 0x3d, 0xb2, 0xfa, 0xbd, 0xb2, 0xc2, 0x6a, 0xce, 0xa6, 0x3a, 0x85, + 0x7a, 0x3f, 0x20, 0x94, 0xba, 0x15, 0x7f, 0x7a, 0x82, 0xe9, 0x6f, 0xbe, + 0xa0, 0xba, 0xea, 0xd0, 0xe4, 0x3a, 0x39, 0xa8, 0xbb, 0x55, 0x60, 0xb8, + 0x28, 0x3a, 0xd1, 0xa3, 0x07, 0x50, 0x51, 0xf5, 0x80, 0x2b, 0xf4, 0x5a, + 0x82, 0x1b, 0x7d, 0x56, 0xa9, 0x31, 0x04, 0x23, 0xb1, 0x34, 0xd2, 0x71, + 0xd5, 0x1c, 0x92, 0x82, 0xd5, 0xb6, 0xfc, 0x74, 0x86, 0x06, 0x6a, 0xf1, + 0xe8, 0x72, 0xd1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x66, 0x30, 0x64, + 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, + 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xf4, 0x9f, 0xe9, 0x91, 0x43, + 0xac, 0x1c, 0x9b, 0xdd, 0x07, 0x40, 0x2d, 0x69, 0x67, 0x3c, 0xef, 0xd4, + 0xea, 0xdb, 0x54, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0xf4, 0x9f, 0xe9, 0x91, 0x43, 0xac, 0x1c, 0x9b, + 0xdd, 0x07, 0x40, 0x2d, 0x69, 0x67, 0x3c, 0xef, 0xd4, 0xea, 0xdb, 0x54, + 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, + 0x03, 0x02, 0x00, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, + 0x80, 0x61, 0x52, 0x61, 0x22, 0x4d, 0xfc, 0x47, 0xcf, 0x56, 0x08, 0xcd, + 0xb0, 0x13, 0xb5, 0xad, 0x3b, 0xb6, 0x0a, 0x71, 0x57, 0xc2, 0xc0, 0xfe, + 0x01, 0xff, 0x89, 0x60, 0x18, 0x68, 0xee, 0xe0, 0x81, 0x1e, 0x9c, 0x43, + 0x4b, 0x31, 0xa6, 0x5b, 0xc8, 0x25, 0x84, 0x4b, 0x11, 0x2a, 0x5e, 0xfa, + 0xa7, 0xbf, 0x67, 0x8e, 0x3a, 0xcf, 0x8f, 0x6e, 0xea, 0x3a, 0xef, 0xda, + 0xc4, 0x32, 0x61, 0xa9, 0x5d, 0x2b, 0x8b, 0xf4, 0x8b, 0x2b, 0x8a, 0xd1, + 0x9d, 0x18, 0xd7, 0x0f, 0xd2, 0x9b, 0xe1, 0xfa, 0x00, 0xaf, 0xd6, 0xfe, + 0xff, 0x47, 0x1d, 0x7a, 0x55, 0xe9, 0x83, 0x3e, 0xca, 0xef, 0x4b, 0x0d, + 0xe8, 0x2c, 0x42, 0xf6, 0xbf, 0x6d, 0x81, 0x0a, 0x52, 0xaf, 0xa9, 0xe3, + 0xf9, 0x19, 0xc9, 0x56, 0x40, 0x5d, 0x58, 0x1e, 0xf1, 0xfe, 0x37, 0x8e, + 0x50, 0x17, 0xfa, 0x0f, 0x66, 0x9c, 0x91, 0x8e, 0x88, 0xe7, 0x5c, 0xc9, + 0x30, 0x8c, 0x35, 0x16, 0x92, 0x70, 0x7a, 0x34, 0xaa, 0xc4, 0xf0, 0xba, + 0x90, 0x15, 0x47, 0x2c, 0xaf, 0xae, 0x86, 0x0c, 0xb5, 0x95, 0xe5, 0x28, + 0x62, 0xa3, 0x20, 0x56, 0xbf, 0xb7, 0x1a, 0x4b, 0x4f, 0xe9, 0xf3, 0xc4, + 0x18, 0xf0, 0xbf, 0xc3, 0xd3, 0x7a, 0xcf, 0xe9, 0x40, 0x9f, 0x88, 0x88, + 0x60, 0x75, 0x6b, 0x98, 0xb5, 0x3d, 0xab, 0x30, 0xca, 0x5b, 0x95, 0xc7, + 0xa2, 0xf8, 0x66, 0x47, 0x03, 0x71, 0x89, 0xc0, 0x57, 0xf2, 0xeb, 0xb3, + 0xa9, 0x49, 0xf2, 0x10, 0xfe, 0xa8, 0x7d, 0x6b, 0x90, 0x66, 0xf8, 0x9f, + 0x46, 0x9f, 0xb4, 0x2c, 0x5f, 0xe3, 0x15, 0xf7, 0xd3, 0x44, 0xd7, 0xe9, + 0x17, 0x3d, 0x51, 0x19, 0x8c, 0x2e, 0x4d, 0xb1, 0xcb, 0x37, 0x70, 0x94, + 0x56, 0x28, 0x8c, 0xc5, 0x6c, 0x93, 0x13, 0xb3, 0xeb, 0x1a, 0x0c, 0x70, + 0x4e, 0xd4, 0x35, 0x2f, 0x30, 0x82, 0x04, 0xa5, 0x30, 0x82, 0x03, 0x0d, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xcf, 0xd4, 0x96, 0x36, + 0x7c, 0x5a, 0x30, 0x8b, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x60, 0x31, 0x23, 0x30, + 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1a, 0x54, 0x65, 0x73, 0x74, + 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x63, 0x65, 0x72, + 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x52, 0x53, 0x41, 0x31, 0x11, + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x08, 0x48, 0x65, 0x6c, + 0x73, 0x69, 0x6e, 0x6b, 0x69, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x46, 0x49, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x10, 0x49, 0x4e, 0x53, 0x49, 0x44, 0x45, 0x20, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x4f, 0x79, 0x30, 0x1e, 0x17, + 0x0d, 0x31, 0x35, 0x31, 0x32, 0x31, 0x37, 0x30, 0x31, 0x32, 0x35, 0x35, + 0x32, 0x5a, 0x17, 0x0d, 0x32, 0x35, 0x31, 0x32, 0x31, 0x34, 0x30, 0x31, + 0x32, 0x35, 0x35, 0x32, 0x5a, 0x30, 0x62, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1c, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x43, 0x41, 0x20, 0x63, 0x65, 0x72, + 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x52, 0x53, 0x41, 0x31, 0x11, + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x08, 0x48, 0x65, 0x6c, + 0x73, 0x69, 0x6e, 0x6b, 0x69, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x46, 0x49, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x10, 0x49, 0x4e, 0x53, 0x49, 0x44, 0x45, 0x20, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x4f, 0x79, 0x30, 0x82, 0x01, + 0xa2, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x8f, 0x00, 0x30, 0x82, 0x01, + 0x8a, 0x02, 0x82, 0x01, 0x81, 0x00, 0xcc, 0x42, 0xde, 0x5f, 0x49, 0xf7, + 0xb6, 0xfc, 0xac, 0xc7, 0x5b, 0xf7, 0x4d, 0x68, 0xb6, 0xb8, 0xbd, 0x68, + 0x97, 0x67, 0xb0, 0xe2, 0x23, 0xbf, 0x27, 0xd3, 0x84, 0x92, 0xf8, 0x93, + 0xf4, 0x4b, 0x9e, 0x3e, 0x72, 0xb4, 0x5c, 0x2f, 0x93, 0x1c, 0x83, 0x48, + 0xdb, 0xef, 0x33, 0x71, 0x9a, 0xa0, 0x3f, 0x64, 0x38, 0x50, 0x6a, 0x3b, + 0xf6, 0x07, 0x5e, 0x57, 0x43, 0x17, 0x4d, 0x92, 0xcf, 0x26, 0x42, 0x86, + 0xde, 0xa4, 0xf8, 0x89, 0xa3, 0x30, 0x00, 0x65, 0xf6, 0xa7, 0xf2, 0x17, + 0x0c, 0xa8, 0xf9, 0xa8, 0xe8, 0xd9, 0x6d, 0x42, 0x4a, 0xfa, 0x75, 0xbf, + 0xc0, 0x64, 0x85, 0xf9, 0x3d, 0x0a, 0x2f, 0x36, 0x0c, 0xc7, 0xaa, 0xb8, + 0x43, 0x6e, 0x9e, 0xc6, 0xaf, 0xe3, 0xbb, 0xaa, 0xa5, 0x2d, 0x89, 0x02, + 0x48, 0x05, 0x08, 0xa4, 0x0e, 0xce, 0xa9, 0xfc, 0x26, 0x5b, 0xbc, 0xe0, + 0x4f, 0x2a, 0x51, 0x36, 0x92, 0x13, 0x37, 0xcc, 0x2a, 0x97, 0x18, 0x6b, + 0x93, 0xa8, 0xac, 0x30, 0x57, 0x7f, 0x52, 0x0f, 0xa8, 0x2b, 0xd0, 0xb5, + 0x4e, 0x7e, 0x7e, 0x81, 0xca, 0x02, 0x7d, 0xcf, 0xea, 0x9b, 0x70, 0xe7, + 0xf3, 0x04, 0x93, 0xc1, 0xcc, 0x63, 0xae, 0xbd, 0xcf, 0x07, 0x28, 0x0a, + 0x6a, 0x2c, 0xaa, 0x0d, 0x4a, 0x5c, 0xb9, 0xd9, 0x9c, 0x60, 0x06, 0xc1, + 0xed, 0xb0, 0x7f, 0x4f, 0xb9, 0x3a, 0xff, 0x2c, 0x71, 0x31, 0x2c, 0x96, + 0xa0, 0xd8, 0x32, 0xce, 0x13, 0x56, 0x91, 0xbb, 0xf8, 0x88, 0x32, 0x6c, + 0xde, 0xd7, 0x49, 0x4d, 0x3e, 0x83, 0xeb, 0xb7, 0x5b, 0xb1, 0x59, 0x44, + 0xc6, 0x8a, 0xf4, 0xd0, 0x26, 0x4d, 0x69, 0x22, 0x38, 0x53, 0xf3, 0x90, + 0x24, 0xe3, 0x76, 0x00, 0x0e, 0xd1, 0x2b, 0x5b, 0xd6, 0xc9, 0xc8, 0x40, + 0x59, 0xfe, 0xd1, 0x4e, 0x4c, 0xe2, 0xa5, 0x60, 0x56, 0x81, 0xf4, 0xa4, + 0x8e, 0xbf, 0x52, 0xe0, 0x86, 0x44, 0x8e, 0xf7, 0x69, 0x28, 0xac, 0x75, + 0xba, 0x46, 0xfa, 0x0d, 0xe1, 0x76, 0x90, 0x1a, 0x76, 0xbe, 0xaf, 0x3a, + 0xaa, 0xc3, 0xad, 0xf4, 0xdb, 0xe5, 0xdc, 0xdc, 0x39, 0x9b, 0xc2, 0x13, + 0x43, 0xfd, 0xbb, 0x67, 0x0f, 0x5e, 0x67, 0xa7, 0x78, 0xe3, 0x64, 0x9e, + 0x8f, 0x47, 0xa8, 0xdf, 0xee, 0x0d, 0x85, 0x75, 0xd9, 0xd3, 0xdc, 0xb8, + 0x81, 0x07, 0xc2, 0xc3, 0xad, 0xc1, 0xe8, 0x7c, 0x47, 0x23, 0xab, 0x5b, + 0x0d, 0x53, 0xf9, 0xe7, 0xbf, 0xf4, 0x29, 0x03, 0x67, 0x18, 0x38, 0xd0, + 0x82, 0x69, 0xe4, 0x50, 0xf3, 0x37, 0xf7, 0xc4, 0x4e, 0x7f, 0x4f, 0xc6, + 0xb9, 0xf4, 0xf8, 0xe5, 0xc0, 0x54, 0x63, 0xfb, 0x76, 0xd7, 0xc8, 0x7a, + 0x31, 0x3e, 0x82, 0xb8, 0xf5, 0xd5, 0x8f, 0x29, 0x49, 0x52, 0xf1, 0x56, + 0xb9, 0x1a, 0xb6, 0xe5, 0x78, 0xf1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, + 0x60, 0x30, 0x5e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, + 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, + 0x04, 0x16, 0x04, 0x14, 0xbe, 0x25, 0xa4, 0xb4, 0xff, 0xcc, 0x7a, 0xa1, + 0xd9, 0x2e, 0x76, 0xb8, 0x7d, 0x77, 0x75, 0xe4, 0x92, 0xa3, 0x1c, 0x66, + 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, + 0x14, 0xc0, 0x95, 0x34, 0x1a, 0xc4, 0xf6, 0xd1, 0x6e, 0x47, 0x27, 0x03, + 0x3b, 0x26, 0x00, 0x1f, 0x6c, 0xe4, 0x6b, 0xeb, 0xd8, 0x30, 0x0e, 0x06, + 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, + 0x84, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x81, 0x00, 0x66, 0x35, 0x59, + 0x9c, 0xfb, 0x09, 0x29, 0x2e, 0xeb, 0x22, 0x6d, 0xf8, 0x47, 0x0a, 0x3c, + 0xa7, 0xbc, 0xc0, 0xd2, 0x0b, 0x3d, 0xe1, 0xda, 0x51, 0x05, 0x21, 0x52, + 0x21, 0xd0, 0xa8, 0xbb, 0x15, 0x54, 0x8c, 0x65, 0xa2, 0x0c, 0x27, 0xbd, + 0xf8, 0x59, 0x7b, 0x28, 0x1f, 0x5a, 0x5c, 0xe2, 0x75, 0x13, 0xa1, 0x9c, + 0x98, 0xd0, 0xde, 0x70, 0x29, 0x33, 0xd0, 0xed, 0x8e, 0x7a, 0x4c, 0xf6, + 0x39, 0xd5, 0xb6, 0xc6, 0x92, 0x3c, 0x80, 0x20, 0x34, 0x22, 0x22, 0x52, + 0x72, 0xa4, 0xe2, 0x8f, 0x89, 0x19, 0x47, 0x9f, 0x9b, 0x1a, 0xdd, 0x50, + 0x8b, 0x4c, 0xce, 0xa7, 0xf6, 0xd8, 0xba, 0x55, 0x6b, 0xac, 0x3c, 0x9a, + 0x3d, 0xf0, 0xf3, 0x12, 0x67, 0x51, 0x62, 0x69, 0x55, 0xdf, 0x5b, 0x47, + 0x82, 0x57, 0x75, 0x32, 0x0b, 0xa7, 0x29, 0xf5, 0x96, 0xb0, 0x0f, 0xec, + 0x7d, 0xe8, 0x6b, 0xfc, 0x95, 0x97, 0x36, 0x83, 0xd0, 0xda, 0x08, 0x9d, + 0x85, 0x71, 0x4d, 0x8e, 0x14, 0x21, 0xa8, 0x7a, 0xf1, 0xef, 0x57, 0x8a, + 0x9d, 0xe8, 0xa8, 0xda, 0xca, 0x1b, 0x9c, 0x25, 0xd8, 0xd2, 0xa1, 0xb1, + 0x98, 0x09, 0xc7, 0xc9, 0xac, 0x8d, 0xae, 0x82, 0x68, 0x48, 0x9b, 0xd5, + 0x7c, 0xa5, 0x56, 0xcb, 0xe0, 0x72, 0xdf, 0xdf, 0xa3, 0xc1, 0x3e, 0x32, + 0xf3, 0xa9, 0x75, 0x2c, 0x3d, 0xa0, 0x85, 0x1a, 0xd7, 0x14, 0xa3, 0xc3, + 0xf0, 0x0f, 0xee, 0x81, 0xfb, 0x08, 0xf4, 0xf9, 0x75, 0xf4, 0x48, 0x8b, + 0x14, 0x30, 0x5d, 0x7c, 0x00, 0x57, 0x1b, 0x4a, 0x31, 0x86, 0xa8, 0x79, + 0xe4, 0x4e, 0x75, 0x6a, 0x42, 0x68, 0xdc, 0xd9, 0xb3, 0x3f, 0x3c, 0xac, + 0x3e, 0x8d, 0xd6, 0x56, 0x24, 0x35, 0x01, 0x2d, 0xb9, 0xed, 0xcb, 0xfd, + 0xc1, 0x75, 0x18, 0x4b, 0xf2, 0x47, 0x6e, 0x98, 0x6b, 0x91, 0x18, 0xdf, + 0xa0, 0xcd, 0x4a, 0xb6, 0x98, 0xca, 0xe6, 0x7a, 0xc7, 0x59, 0x15, 0x58, + 0xb0, 0x36, 0x79, 0x12, 0x31, 0x22, 0x36, 0x33, 0xe0, 0x3b, 0x50, 0xf9, + 0xf0, 0x69, 0x16, 0x14, 0x8e, 0x3c, 0x53, 0x88, 0x88, 0x57, 0x8c, 0xdc, + 0x90, 0x79, 0xad, 0x88, 0x12, 0x7b, 0x94, 0x77, 0x29, 0x87, 0xac, 0xfd, + 0x13, 0x8d, 0x83, 0x11, 0xcb, 0x8b, 0xbb, 0x47, 0xff, 0x5e, 0x9d, 0xe4, + 0x76, 0x48, 0x03, 0x3f, 0xb1, 0xb2, 0xe4, 0x9e, 0x84, 0xb6, 0x00, 0xfd, + 0x7f, 0xb9, 0xde, 0xab, 0x65, 0x00, 0x62, 0x8b, 0x29, 0x59, 0x60, 0x79, + 0xe7, 0x7a, 0xdb, 0x81, 0xfe, 0xf8, 0x97, 0xdf, 0x66, 0x86, 0x47, 0x2b, + 0xc5, 0x14, 0xe4, 0x1c, 0xf8, 0x9a, 0x10, 0x34, 0x9d, 0xc7, 0xcc, 0x4d, + 0xd1, 0x76, 0x0a, 0xd3, 0x6b, 0x7f, 0x37, 0x2f, 0x8e, 0x9b, 0x62, 0x6b, + 0xef, 0xb7, 0x8e, 0x6c, 0x35, 0xe2, 0x9f, 0x1a, 0xe2, 0x30, 0x82, 0x06, + 0x13, 0x30, 0x82, 0x03, 0xfb, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x05, + 0x33, 0x34, 0x35, 0x36, 0x37, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x96, 0x31, + 0x35, 0x30, 0x33, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2c, 0x53, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x20, + 0x52, 0x53, 0x41, 0x2d, 0x34, 0x30, 0x39, 0x36, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x0c, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, + 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, + 0x19, 0x49, 0x4e, 0x53, 0x49, 0x44, 0x45, 0x20, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, + 0x04, 0x54, 0x65, 0x73, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, + 0x33, 0x32, 0x34, 0x31, 0x36, 0x34, 0x31, 0x30, 0x33, 0x5a, 0x17, 0x0d, + 0x31, 0x37, 0x30, 0x33, 0x32, 0x33, 0x31, 0x36, 0x34, 0x31, 0x30, 0x33, + 0x5a, 0x30, 0x81, 0x96, 0x31, 0x35, 0x30, 0x33, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0c, 0x2c, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x4d, 0x61, + 0x74, 0x72, 0x69, 0x78, 0x20, 0x52, 0x53, 0x41, 0x2d, 0x34, 0x30, 0x39, + 0x36, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x0c, 0x02, 0x55, 0x53, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, + 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, + 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x19, 0x49, 0x4e, 0x53, 0x49, 0x44, 0x45, + 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x70, + 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x30, 0x0b, 0x06, + 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x30, 0x82, + 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, + 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xbb, 0xb1, 0x44, 0x44, 0xa1, + 0xd5, 0xd9, 0x0d, 0xe2, 0x36, 0x49, 0x26, 0xbe, 0x69, 0xcb, 0x0e, 0x88, + 0x4a, 0x28, 0xef, 0xae, 0x2c, 0x4f, 0x9d, 0x25, 0xc5, 0x8a, 0xbf, 0x9e, + 0x51, 0xe4, 0x77, 0x56, 0x4b, 0x4d, 0x75, 0x91, 0x1d, 0x4a, 0xd2, 0xcc, + 0xb3, 0x0b, 0x2f, 0xe4, 0x42, 0x72, 0xfa, 0xb2, 0x9f, 0xd2, 0x27, 0xe0, + 0x0c, 0xc3, 0xfe, 0x83, 0x3a, 0x96, 0xa0, 0xd4, 0xa5, 0x9a, 0x94, 0x60, + 0xba, 0x0c, 0xbf, 0xab, 0x8e, 0x68, 0xcf, 0x1f, 0xc4, 0x72, 0x6d, 0x57, + 0xce, 0x60, 0x23, 0x4c, 0x09, 0xf4, 0xf8, 0x6b, 0xc6, 0x59, 0xda, 0xd7, + 0xcc, 0x3a, 0xc2, 0x98, 0x83, 0xb5, 0xfc, 0x37, 0x43, 0x8f, 0x1c, 0x00, + 0x4a, 0x8e, 0x0d, 0x49, 0xf5, 0xf1, 0xeb, 0xa6, 0x4f, 0xc5, 0x31, 0x0d, + 0x6f, 0x2e, 0xf4, 0x66, 0x0a, 0xf5, 0xdc, 0xeb, 0xaf, 0x1c, 0x71, 0x63, + 0xe1, 0x56, 0x13, 0xae, 0x5a, 0xca, 0xfc, 0x98, 0xb1, 0x63, 0x10, 0x42, + 0xf0, 0x9b, 0x8b, 0x90, 0xe3, 0xd3, 0xd7, 0xe1, 0xb9, 0x5f, 0x0f, 0xcb, + 0xfd, 0xc7, 0x74, 0x6b, 0x54, 0x5f, 0x2d, 0xd1, 0x71, 0xba, 0x0c, 0x94, + 0x74, 0x33, 0xc0, 0x3e, 0xe1, 0x97, 0x67, 0x0f, 0x2a, 0x5d, 0xee, 0x4e, + 0xdc, 0x7b, 0xfe, 0xdd, 0x2b, 0x64, 0x65, 0x41, 0x19, 0xb0, 0x6d, 0x94, + 0x55, 0x18, 0x0c, 0x6f, 0x70, 0x3c, 0xc2, 0x24, 0x57, 0xa1, 0xfc, 0xbe, + 0xeb, 0xf0, 0xf0, 0xf9, 0x85, 0xa2, 0xa3, 0x66, 0x82, 0x27, 0xfb, 0x70, + 0xc3, 0xdc, 0x72, 0x5f, 0xe7, 0x60, 0xd7, 0x3b, 0x0c, 0x85, 0x6b, 0xc1, + 0xc5, 0x58, 0x57, 0xbb, 0xad, 0xf0, 0x4d, 0x01, 0xa3, 0xca, 0x91, 0x9c, + 0x4b, 0x97, 0x15, 0x66, 0xe3, 0x19, 0x2a, 0x58, 0x83, 0x44, 0xe2, 0x18, + 0x19, 0xfc, 0x90, 0x49, 0x71, 0xb0, 0x59, 0x75, 0x3a, 0xe6, 0x74, 0xf9, + 0x6c, 0x43, 0xfe, 0x02, 0xc9, 0xc0, 0xb9, 0xa8, 0x09, 0x80, 0x39, 0x3c, + 0xea, 0x86, 0x7d, 0x62, 0x4b, 0x94, 0x43, 0xf2, 0x4a, 0x63, 0x34, 0x44, + 0x03, 0x22, 0x35, 0x98, 0xb6, 0x9b, 0x67, 0xc6, 0x93, 0x64, 0x80, 0x94, + 0xa8, 0x99, 0xde, 0xd7, 0x87, 0x03, 0x1a, 0x98, 0x1c, 0xf9, 0xd0, 0x6f, + 0x79, 0xaa, 0xde, 0x8c, 0x2f, 0xb5, 0x22, 0xa9, 0xff, 0x11, 0xfc, 0xaa, + 0x5b, 0x2f, 0x4c, 0xc5, 0xe6, 0x44, 0x65, 0x85, 0xe4, 0xba, 0x77, 0xbd, + 0x33, 0x83, 0x68, 0x33, 0x56, 0xd1, 0x57, 0x40, 0x50, 0x00, 0x88, 0x69, + 0x6a, 0x16, 0x89, 0x4f, 0xef, 0x90, 0x67, 0x56, 0x61, 0x79, 0x69, 0xa2, + 0x84, 0x9f, 0xed, 0x91, 0xcb, 0x4c, 0xbb, 0xaf, 0xf2, 0x9d, 0xef, 0xe3, + 0x32, 0x6c, 0x37, 0x64, 0xea, 0x75, 0xff, 0xc5, 0xec, 0x88, 0xbd, 0x6b, + 0x43, 0xfe, 0x68, 0x14, 0xd4, 0xc7, 0x9b, 0xf4, 0xae, 0x74, 0xea, 0xe1, + 0xb4, 0x63, 0x2a, 0x0e, 0xf5, 0x9c, 0xbe, 0x9f, 0x6e, 0x4e, 0x8f, 0x09, + 0x3e, 0x43, 0x8d, 0x4f, 0xb3, 0x05, 0x25, 0xfe, 0xfa, 0x7b, 0xe6, 0x1d, + 0xe6, 0xe8, 0x20, 0x1b, 0x4c, 0x30, 0x3d, 0xe0, 0xb7, 0x76, 0x69, 0x0b, + 0xf1, 0x07, 0x03, 0x1f, 0x8f, 0x57, 0xbf, 0x55, 0xcf, 0x11, 0x98, 0xb6, + 0x99, 0xdf, 0x7b, 0x9b, 0xbe, 0x98, 0x16, 0xbb, 0xd2, 0x81, 0xc1, 0xeb, + 0x9f, 0x08, 0xae, 0x7e, 0x44, 0xa9, 0xa7, 0x79, 0x49, 0x02, 0xac, 0x8a, + 0x81, 0xbc, 0x92, 0xc6, 0xd1, 0xef, 0xcc, 0x9d, 0x14, 0xb2, 0xf4, 0x09, + 0xaf, 0x1c, 0xb2, 0x0b, 0x02, 0x32, 0xdd, 0xcd, 0xfc, 0x09, 0x83, 0x3e, + 0x1c, 0x33, 0x58, 0x2b, 0x77, 0xd5, 0x48, 0xa6, 0x5b, 0x75, 0x9f, 0x66, + 0x31, 0x11, 0x53, 0x47, 0xc8, 0xc7, 0x44, 0x09, 0xc9, 0x93, 0xc4, 0x1c, + 0x32, 0x08, 0x69, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x66, 0x30, 0x64, + 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, + 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x6c, 0x42, 0x84, 0xc5, 0xe0, + 0x4b, 0xdc, 0x70, 0xf2, 0x99, 0xd0, 0x1c, 0x83, 0x4a, 0xe2, 0x51, 0x47, + 0x65, 0x1e, 0xfa, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0x6c, 0x42, 0x84, 0xc5, 0xe0, 0x4b, 0xdc, 0x70, + 0xf2, 0x99, 0xd0, 0x1c, 0x83, 0x4a, 0xe2, 0x51, 0x47, 0x65, 0x1e, 0xfa, + 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, + 0x03, 0x02, 0x00, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, + 0x66, 0xb4, 0x58, 0x98, 0x67, 0x1b, 0xdb, 0xce, 0x63, 0x5f, 0xc3, 0x71, + 0x89, 0xa0, 0xad, 0x99, 0x10, 0xc0, 0x27, 0xbc, 0x5b, 0xc3, 0xa0, 0xb1, + 0xcd, 0xb6, 0xed, 0xdc, 0x16, 0x06, 0x33, 0x3a, 0x52, 0x62, 0x55, 0x07, + 0x7c, 0x6c, 0xbe, 0xc7, 0xec, 0x16, 0x6b, 0x7f, 0x26, 0x7c, 0x75, 0x70, + 0x29, 0x19, 0x15, 0x88, 0x40, 0x5d, 0x25, 0xfa, 0x50, 0x39, 0x0c, 0x6a, + 0x3c, 0xc7, 0x10, 0xca, 0xa9, 0xb9, 0x44, 0x30, 0x66, 0x93, 0x49, 0x0f, + 0x0a, 0x1a, 0x6f, 0x78, 0xa1, 0x43, 0xb3, 0x48, 0x4d, 0x6a, 0x91, 0x3e, + 0xa9, 0xbe, 0xbc, 0xd9, 0x94, 0x78, 0x29, 0xe0, 0xc4, 0x87, 0x97, 0x94, + 0x99, 0x04, 0x94, 0x2a, 0x21, 0xf0, 0xa2, 0x31, 0x98, 0xfd, 0x23, 0x8f, + 0xc0, 0x32, 0xe2, 0xb1, 0xf6, 0xe4, 0x86, 0x5f, 0x3d, 0x94, 0x6f, 0x84, + 0x97, 0x3e, 0xce, 0x9f, 0xb7, 0x7d, 0x86, 0xfe, 0xa8, 0x28, 0x2c, 0xd9, + 0xb8, 0xd0, 0xef, 0x9a, 0x7f, 0xca, 0x3c, 0xda, 0xaf, 0x07, 0x0f, 0xdf, + 0xd3, 0x18, 0x5d, 0x27, 0xd6, 0x9e, 0x82, 0x1b, 0x09, 0xd4, 0x51, 0x3a, + 0x75, 0x7e, 0x37, 0xb6, 0xe2, 0x5c, 0xe6, 0x44, 0x3e, 0x51, 0x07, 0x25, + 0xb2, 0xe6, 0xf6, 0x0e, 0x98, 0x44, 0x23, 0x0d, 0x5f, 0x15, 0xec, 0x3f, + 0x61, 0x56, 0x5f, 0x41, 0x84, 0x46, 0x3b, 0x4e, 0x6a, 0x3f, 0x4d, 0x6c, + 0x9a, 0xb0, 0x85, 0x85, 0xb9, 0x29, 0xf3, 0xb3, 0x02, 0x94, 0xb5, 0xc3, + 0x96, 0x78, 0xc0, 0xd5, 0x61, 0x12, 0xf6, 0x61, 0x0a, 0x8b, 0x9b, 0x80, + 0xd6, 0x3c, 0xa4, 0x1a, 0x0d, 0x4d, 0x79, 0x73, 0x76, 0xa4, 0x8f, 0x9a, + 0xe9, 0x76, 0xf3, 0x8b, 0x76, 0xb9, 0x6d, 0xa2, 0xf5, 0x27, 0xbb, 0xc6, + 0xac, 0xe4, 0x25, 0x01, 0xba, 0x03, 0x35, 0x35, 0x02, 0xc8, 0xcf, 0xad, + 0x79, 0x1c, 0x1f, 0x94, 0x3e, 0xb2, 0xdb, 0xb8, 0xa7, 0xe8, 0x6e, 0x8b, + 0x44, 0x15, 0xa2, 0xaf, 0x4a, 0x67, 0x9b, 0xba, 0x68, 0x49, 0x85, 0xee, + 0x93, 0xc4, 0x5f, 0x97, 0x77, 0xe0, 0xb4, 0x90, 0x8e, 0x59, 0xec, 0x26, + 0x08, 0xa4, 0x52, 0xb4, 0x9d, 0x15, 0x7b, 0x5c, 0x3f, 0x5e, 0x5b, 0x5b, + 0x82, 0x69, 0xff, 0xf9, 0x8d, 0xfe, 0x0e, 0x0d, 0x22, 0x14, 0xdd, 0x39, + 0x6a, 0xa2, 0x03, 0x5d, 0xdf, 0xfe, 0x60, 0x1c, 0x92, 0xf9, 0x1f, 0x09, + 0xad, 0xad, 0x95, 0x33, 0xb4, 0xb0, 0x7c, 0x4c, 0x63, 0x9f, 0x30, 0xd4, + 0x86, 0x7d, 0x8a, 0x4b, 0x06, 0xf9, 0x6a, 0x66, 0xcd, 0x86, 0x0e, 0xfc, + 0xfc, 0xc2, 0x65, 0xa9, 0x61, 0x3e, 0xed, 0xac, 0xd5, 0xf4, 0xc5, 0x95, + 0x8f, 0x64, 0x1a, 0x9e, 0x14, 0x6f, 0xe0, 0x98, 0xb8, 0x96, 0xcc, 0x0e, + 0xa2, 0xb1, 0x1a, 0x20, 0x07, 0x60, 0xce, 0xd2, 0x9c, 0x30, 0x30, 0xe0, + 0x53, 0xfc, 0x1f, 0xef, 0xe1, 0x23, 0xab, 0x3d, 0x77, 0xc8, 0xd0, 0x71, + 0xdd, 0xac, 0x9e, 0x1c, 0xa4, 0x7e, 0x37, 0x76, 0x79, 0xfd, 0x90, 0x5b, + 0xc2, 0x77, 0x81, 0xcf, 0x41, 0x1f, 0x10, 0x9c, 0x17, 0x5c, 0xba, 0xba, + 0x0c, 0xca, 0xf0, 0xdd, 0x1a, 0xbb, 0x2a, 0x5d, 0xa8, 0xc6, 0x3c, 0x28, + 0x13, 0xdd, 0xa3, 0xd5, 0xa3, 0xcc, 0x34, 0x2c, 0xb0, 0x09, 0x42, 0xa3, + 0xf1, 0x95, 0xd7, 0x4a, 0xd5, 0xb2, 0xaf, 0xa3, 0xad, 0xc2, 0x72, 0x67, + 0x48, 0x6d, 0x5d, 0x5a, 0x23, 0x7f, 0xb6, 0x39, 0xf7, 0xa5, 0xcd, 0xc3, + 0x01, 0x9b, 0x7e, 0x91, 0x57, 0xad, 0x69, 0xfa, 0x6a, 0x1b, 0x5d, 0x25, + 0x67, 0xc8, 0x1e, 0x4c, 0x08, 0x6c, 0x1b, 0xe5, 0xd6, 0x37, 0xa0, 0xc9, + 0x98, 0xc3, 0x66, 0x64, 0x66, 0xd5, 0x72, 0x30, 0x5c, 0xb3, 0x15, 0xc8, + 0x66, 0x22, 0x05, 0x2e, 0xda, 0x61, 0xa9, 0xca +}; diff --git a/testkeys/RSA/ALL_RSA_CAS_EXCEPT_1024.pem b/testkeys/RSA/ALL_RSA_CAS_EXCEPT_1024.pem new file mode 100644 index 0000000..741f1e2 --- /dev/null +++ b/testkeys/RSA/ALL_RSA_CAS_EXCEPT_1024.pem @@ -0,0 +1,86 @@ +-----BEGIN CERTIFICATE----- +MIIEFDCCAvygAwIBAgIGMjM0NTY3MA0GCSqGSIb3DQEBCwUAMIGWMTUwMwYDVQQD +DCxTYW1wbGUgTWF0cml4IFJTQS0yMDQ4IENlcnRpZmljYXRlIEF1dGhvcml0eTEL +MAkGA1UEBgwCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMSIwIAYD +VQQKDBlJTlNJREUgU2VjdXJlIENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MB4X +DTE0MDMyNDE2MjcwM1oXDTE3MDMyMzE2MjcwM1owgZYxNTAzBgNVBAMMLFNhbXBs +ZSBNYXRyaXggUlNBLTIwNDggQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQswCQYDVQQG +DAJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUlO +U0lERSBTZWN1cmUgQ29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMq1tAOwpLwINcaOX0AFoVGuN486BBI5Na +wcb6BJCjRY4wXJGKbYS/eMDLse5lr6pduvE1BLVAlO28jPXrobuPovq3quxTd4uv +ttF48VhZAGyPmEQdc0zhGoqwYYDdwN+bdF/QfGZmI9wwnE3g7NpuBMTIYqIhEe8o +3G3pMbd6nsrbusKckx4kqZp0vqQmTrtfeQTTQXIFolOaRCABSERdM3JjP6qidwn1 +w+ImtRKHIa1K55mZ7z2y+r2ywmrOpjqFej8glLoVf3qC6W++oLrq0OQ6Oai7VWC4 +KDrRowdQUfWAK/Raght9VqkxBCOxNNJx1RySgtW2/HSGBmrx6HLRAgMBAAGjZjBk +MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFPSf6ZFDrByb3QdALWlnPO/U +6ttUMB8GA1UdIwQYMBaAFPSf6ZFDrByb3QdALWlnPO/U6ttUMA4GA1UdDwEB/wQE +AwIABDANBgkqhkiG9w0BAQsFAAOCAQEAgGFSYSJN/EfPVgjNsBO1rTu2CnFXwsD+ +Af+JYBho7uCBHpxDSzGmW8glhEsRKl76p79njjrPj27qOu/axDJhqV0ri/SLK4rR +nRjXD9Kb4foAr9b+/0cdelXpgz7K70sN6CxC9r9tgQpSr6nj+RnJVkBdWB7x/jeO +UBf6D2ackY6I51zJMIw1FpJwejSqxPC6kBVHLK+uhgy1leUoYqMgVr+3GktP6fPE +GPC/w9N6z+lAn4iIYHVrmLU9qzDKW5XHovhmRwNxicBX8uuzqUnyEP6ofWuQZvif +Rp+0LF/jFffTRNfpFz1RGYwuTbHLN3CUViiMxWyTE7PrGgxwTtQ1Lw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEpTCCAw2gAwIBAgIJAM/UljZ8WjCLMA0GCSqGSIb3DQEBCwUAMGAxIzAhBgNV +BAMMGlRlc3QgUm9vdCBDQSBjZXJ0IHdpdGggUlNBMREwDwYDVQQIDAhIZWxzaW5r +aTELMAkGA1UEBhMCRkkxGTAXBgNVBAoMEElOU0lERSBTZWN1cmUgT3kwHhcNMTUx +MjE3MDEyNTUyWhcNMjUxMjE0MDEyNTUyWjBiMSUwIwYDVQQDDBxUZXN0IFNlcnZl +ciBDQSBjZXJ0IHdpdGggUlNBMREwDwYDVQQIDAhIZWxzaW5raTELMAkGA1UEBhMC +RkkxGTAXBgNVBAoMEElOU0lERSBTZWN1cmUgT3kwggGiMA0GCSqGSIb3DQEBAQUA +A4IBjwAwggGKAoIBgQDMQt5fSfe2/KzHW/dNaLa4vWiXZ7DiI78n04SS+JP0S54+ +crRcL5Mcg0jb7zNxmqA/ZDhQajv2B15XQxdNks8mQobepPiJozAAZfan8hcMqPmo +6NltQkr6db/AZIX5PQovNgzHqrhDbp7Gr+O7qqUtiQJIBQikDs6p/CZbvOBPKlE2 +khM3zCqXGGuTqKwwV39SD6gr0LVOfn6BygJ9z+qbcOfzBJPBzGOuvc8HKApqLKoN +Sly52ZxgBsHtsH9PuTr/LHExLJag2DLOE1aRu/iIMmze10lNPoPrt1uxWUTGivTQ +Jk1pIjhT85Ak43YADtErW9bJyEBZ/tFOTOKlYFaB9KSOv1LghkSO92korHW6RvoN +4XaQGna+rzqqw6302+Xc3DmbwhND/btnD15np3jjZJ6PR6jf7g2FddnT3LiBB8LD +rcHofEcjq1sNU/nnv/QpA2cYONCCaeRQ8zf3xE5/T8a59PjlwFRj+3bXyHoxPoK4 +9dWPKUlS8Va5GrblePECAwEAAaNgMF4wDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQU +viWktP/MeqHZLna4fXd15JKjHGYwHwYDVR0jBBgwFoAUwJU0GsT20W5HJwM7JgAf +bORr69gwDgYDVR0PAQH/BAQDAgKEMA0GCSqGSIb3DQEBCwUAA4IBgQBmNVmc+wkp +LusibfhHCjynvMDSCz3h2lEFIVIh0Ki7FVSMZaIMJ734WXsoH1pc4nUToZyY0N5w +KTPQ7Y56TPY51bbGkjyAIDQiIlJypOKPiRlHn5sa3VCLTM6n9ti6VWusPJo98PMS +Z1FiaVXfW0eCV3UyC6cp9ZawD+x96Gv8lZc2g9DaCJ2FcU2OFCGoevHvV4qd6Kja +yhucJdjSobGYCcfJrI2ugmhIm9V8pVbL4HLf36PBPjLzqXUsPaCFGtcUo8PwD+6B ++wj0+XX0SIsUMF18AFcbSjGGqHnkTnVqQmjc2bM/PKw+jdZWJDUBLbnty/3BdRhL +8kdumGuRGN+gzUq2mMrmesdZFViwNnkSMSI2M+A7UPnwaRYUjjxTiIhXjNyQea2I +EnuUdymHrP0TjYMRy4u7R/9eneR2SAM/sbLknoS2AP1/ud6rZQBiiylZYHnnetuB +/viX32aGRyvFFOQc+JoQNJ3HzE3RdgrTa383L46bYmvvt45sNeKfGuI= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGEzCCA/ugAwIBAgIFMzQ1NjcwDQYJKoZIhvcNAQELBQAwgZYxNTAzBgNVBAMM +LFNhbXBsZSBNYXRyaXggUlNBLTQwOTYgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQsw +CQYDVQQGDAJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNV +BAoMGUlOU0lERSBTZWN1cmUgQ29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3QwHhcN +MTQwMzI0MTY0MTAzWhcNMTcwMzIzMTY0MTAzWjCBljE1MDMGA1UEAwwsU2FtcGxl +IE1hdHJpeCBSU0EtNDA5NiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxCzAJBgNVBAYM +AlVTMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZSU5T +SURFIFNlY3VyZSBDb3Jwb3JhdGlvbjENMAsGA1UECwwEVGVzdDCCAiIwDQYJKoZI +hvcNAQEBBQADggIPADCCAgoCggIBALuxRESh1dkN4jZJJr5pyw6ISijvrixPnSXF +ir+eUeR3VktNdZEdStLMswsv5EJy+rKf0ifgDMP+gzqWoNSlmpRgugy/q45ozx/E +cm1XzmAjTAn0+GvGWdrXzDrCmIO1/DdDjxwASo4NSfXx66ZPxTENby70Zgr13Ouv +HHFj4VYTrlrK/JixYxBC8JuLkOPT1+G5Xw/L/cd0a1RfLdFxugyUdDPAPuGXZw8q +Xe5O3Hv+3StkZUEZsG2UVRgMb3A8wiRXofy+6/Dw+YWio2aCJ/tww9xyX+dg1zsM +hWvBxVhXu63wTQGjypGcS5cVZuMZKliDROIYGfyQSXGwWXU65nT5bEP+AsnAuagJ +gDk86oZ9YkuUQ/JKYzREAyI1mLabZ8aTZICUqJne14cDGpgc+dBvearejC+1Iqn/ +EfyqWy9MxeZEZYXkune9M4NoM1bRV0BQAIhpahaJT++QZ1ZheWmihJ/tkctMu6/y +ne/jMmw3ZOp1/8XsiL1rQ/5oFNTHm/SudOrhtGMqDvWcvp9uTo8JPkONT7MFJf76 +e+Yd5uggG0wwPeC3dmkL8QcDH49Xv1XPEZi2md97m76YFrvSgcHrnwiufkSpp3lJ +AqyKgbySxtHvzJ0UsvQJrxyyCwIy3c38CYM+HDNYK3fVSKZbdZ9mMRFTR8jHRAnJ +k8QcMghpAgMBAAGjZjBkMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFGxC +hMXgS9xw8pnQHINK4lFHZR76MB8GA1UdIwQYMBaAFGxChMXgS9xw8pnQHINK4lFH +ZR76MA4GA1UdDwEB/wQEAwIABDANBgkqhkiG9w0BAQsFAAOCAgEAZrRYmGcb285j +X8NxiaCtmRDAJ7xbw6Cxzbbt3BYGMzpSYlUHfGy+x+wWa38mfHVwKRkViEBdJfpQ +OQxqPMcQyqm5RDBmk0kPChpveKFDs0hNapE+qb682ZR4KeDEh5eUmQSUKiHwojGY +/SOPwDLisfbkhl89lG+Elz7On7d9hv6oKCzZuNDvmn/KPNqvBw/f0xhdJ9aeghsJ +1FE6dX43tuJc5kQ+UQclsub2DphEIw1fFew/YVZfQYRGO05qP01smrCFhbkp87MC +lLXDlnjA1WES9mEKi5uA1jykGg1NeXN2pI+a6Xbzi3a5baL1J7vGrOQlAboDNTUC +yM+teRwflD6y27in6G6LRBWir0pnm7poSYXuk8Rfl3fgtJCOWewmCKRStJ0Ve1w/ +Xltbgmn/+Y3+Dg0iFN05aqIDXd/+YByS+R8Jra2VM7SwfExjnzDUhn2KSwb5ambN +hg78/MJlqWE+7azV9MWVj2QanhRv4Ji4lswOorEaIAdgztKcMDDgU/wf7+Ejqz13 +yNBx3ayeHKR+N3Z5/ZBbwneBz0EfEJwXXLq6DMrw3Rq7Kl2oxjwoE92j1aPMNCyw +CUKj8ZXXStWyr6OtwnJnSG1dWiN/tjn3pc3DAZt+kVetafpqG10lZ8geTAhsG+XW +N6DJmMNmZGbVcjBcsxXIZiIFLtphqco= +-----END CERTIFICATE----- diff --git a/testkeys/readme.txt b/testkeys/readme.txt new file mode 100644 index 0000000..0840726 --- /dev/null +++ b/testkeys/readme.txt @@ -0,0 +1,26 @@ +The testkeys directory contains test keys in various formats for use by +included MatrixSSL test and example applications. + +DO NOT USE THESE DEFAULT KEYS IN PRODUCTION ENVIRONMENTS. + +DH/'bits'_DH_PARAMS.* # PKCS3 Public DH parameters + +EC/'bits'_EC.* # X.509 ECDH-ECDSA Certificate, signed by _EC_CA +EC/'bits'_EC_KEY.* # ECC Private Key corresponding with Certificate +EC/'bits'_EC_CA.* # X.509 Self-Signed ECDH-ECDSA Certificate Authority +EC/ALL_EC_CAS.* # All _EC_CA certificates concatenated + +ECDH_RSA/'bits'_ECDH-RSA_CA.* # X.509 Self-Signed RSA Certificate Authority +ECDH_RSA/'bits'_ECDH-RSA_KEY.* # ECC Private key corresponding with certificate +ECDH_RSA/256_ECDH-RSA.* # X.509 ECDH-RSA Certificate, signed by 1024_ECDH-RSA_CA +ECDH_RSA/521_ECDH-RSA.* # X.509 ECDH-RSA Certificate, signed by 2048_ECDH-RSA_CA + +ECDH_RSA/ALL_ECDH-RSA_CAS.* # All _ECDH-RSA_CA certificates concatenated + +PSK/psk.h # Pre-shared symmetric keys + +RSA/'bits'_RSA.* # X.509 RSA Certificate, signed by _RSA_CA +RSA/'bits'_RSA_KEY.* # RSA Private Key corresponding with Certificate +RSA/'bits'_RSA_CA.* # X.509 Self-Signed RSA Certificate Authority +RSA/ALL_RSA_CAS.* # All _RSA_CA certificates concatenated +