├── .gitignore ├── .travis.yml ├── Makefile ├── README.md ├── build ├── .gitignore └── makefile ├── lib └── tropicssl │ ├── include │ └── tropicssl │ │ ├── aes.h │ │ ├── bignum.h │ │ ├── bn_mul.h │ │ ├── config.h │ │ ├── padlock.h │ │ ├── rsa.h │ │ └── sha1.h │ └── library │ ├── Makefile │ ├── aes.c │ ├── bignum.c │ ├── build.mk │ ├── padlock.c │ ├── rsa.c │ └── sha1.c ├── license.txt ├── src ├── build.mk ├── coap.cpp ├── coap.h ├── events.cpp ├── events.h ├── handshake.cpp ├── handshake.h ├── spark_descriptor.h ├── spark_protocol.cpp └── spark_protocol.h └── tests ├── ConstructorFixture.cpp ├── ConstructorFixture.h ├── Main.cpp ├── TestAES.cpp ├── TestCoAP.cpp ├── TestDescriptor.cpp ├── TestEvents.cpp ├── TestHandshake.cpp ├── TestQueue.cpp ├── TestSparkProtocol.cpp ├── TestStateMachine.cpp ├── TestUserFunctions.cpp └── UnitTest++ ├── Makefile └── src ├── AssertException.cpp ├── AssertException.h ├── CheckMacros.h ├── Checks.cpp ├── Checks.h ├── Config.h ├── CurrentTest.cpp ├── CurrentTest.h ├── DeferredTestReporter.cpp ├── DeferredTestReporter.h ├── DeferredTestResult.cpp ├── DeferredTestResult.h ├── ExecuteTest.h ├── MemoryOutStream.cpp ├── MemoryOutStream.h ├── Posix ├── SignalTranslator.cpp ├── SignalTranslator.h ├── TimeHelpers.cpp └── TimeHelpers.h ├── ReportAssert.cpp ├── ReportAssert.h ├── Test.cpp ├── Test.h ├── TestDetails.cpp ├── TestDetails.h ├── TestList.cpp ├── TestList.h ├── TestMacros.h ├── TestReporter.cpp ├── TestReporter.h ├── TestReporterStdout.cpp ├── TestReporterStdout.h ├── TestResults.cpp ├── TestResults.h ├── TestRunner.cpp ├── TestRunner.h ├── TestSuite.h ├── TimeConstraint.cpp ├── TimeConstraint.h ├── TimeHelpers.h ├── UnitTest++.h ├── Win32 ├── TimeHelpers.cpp └── TimeHelpers.h ├── XmlTestReporter.cpp └── XmlTestReporter.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | 4 | # Libraries 5 | *.lib 6 | *.a 7 | 8 | # Shared objects (inc. Windows DLLs) 9 | *.dll 10 | *.so 11 | *.so.* 12 | *.dylib 13 | *.dSYM 14 | 15 | # Executables 16 | *.exe 17 | *.out 18 | *.app 19 | tests/testSparkCoreCommunication 20 | 21 | # Debug folder 22 | Debug/* 23 | 24 | # Release folder 25 | Release/* 26 | 27 | # build folder 28 | *.map 29 | *.lst 30 | *.d 31 | *.o 32 | 33 | # Platform-specific settings 34 | .settings/* 35 | .cproject 36 | .project 37 | .DS_Store 38 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | compiler: 3 | - gcc 4 | script: make test 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CXX ?= g++ 2 | CXXFLAGS ?= -g -Wall -W -Winline -ansi 3 | CXXFLAGS += -Ilib/tropicssl/include -Isrc -Itests/UnitTest++/src 4 | RM = rm 5 | 6 | .SUFFIXES: .o .cpp 7 | 8 | name = SparkCoreCommunication 9 | lib = src/lib$(name).a 10 | test = tests/test$(name) 11 | testlibdir = tests/UnitTest++ 12 | testlib = UnitTest++ 13 | testlibpath = $(testlibdir)/lib$(testlib).a 14 | testrunner = tests/Main.cpp 15 | ssllibdir = lib/tropicssl/library 16 | ssllib = $(ssllibdir)/libtropicssl.a 17 | 18 | objects = src/handshake.o \ 19 | src/coap.o \ 20 | src/spark_protocol.o \ 21 | src/events.o 22 | 23 | testobjects = tests/ConstructorFixture.o \ 24 | tests/TestHandshake.o \ 25 | tests/TestAES.o \ 26 | tests/TestCoAP.o \ 27 | tests/TestQueue.o \ 28 | tests/TestStateMachine.o \ 29 | tests/TestSparkProtocol.o \ 30 | tests/TestDescriptor.o \ 31 | tests/TestUserFunctions.o \ 32 | tests/TestEvents.o 33 | 34 | LDFLAGS ?= -L$(ssllibdir) -ltropicssl -Lsrc -l$(name) -L$(testlibdir) -l$(testlib) 35 | 36 | all: $(lib) 37 | 38 | $(lib): $(objects) 39 | @echo Creating spark communication library... 40 | @$(AR) cr $(lib) $(objects) 41 | 42 | .cpp.o: 43 | @$(CXX) $(CXXFLAGS) -c -o $@ $< 44 | 45 | clean: 46 | -@$(RM) $(objects) $(lib) $(testobjects) 2> /dev/null 47 | 48 | 49 | ############### tests ############# 50 | 51 | test: $(lib) $(testlibpath) $(testobjects) $(ssllib) 52 | @$(CXX) $(testrunner) $(CXXFLAGS) $(testobjects) $(LDFLAGS) -o $(test) 53 | @echo running unit tests... 54 | @./$(test) 55 | 56 | $(testlibpath): 57 | $(MAKE) -C $(testlibdir) 58 | 59 | testclean: 60 | $(MAKE) -C $(testlibdir) clean 61 | 62 | 63 | ############# ssl library ########### 64 | 65 | $(ssllib): 66 | $(MAKE) -C $(ssllibdir) 67 | 68 | sslclean: 69 | $(MAKE) -C $(ssllibdir) clean 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/spark/core-communication-lib.svg)](https://travis-ci.org/spark/core-communication-lib) 2 | 3 | # Core Communication Library 4 | 5 | This repository holds the firmware libraries used for the communication between the Spark Core and the Cloud service. 6 | 7 | Follow [this link](https://github.com/spark/core-firmware/blob/master/README.md) to find out how to build and use this repository. 8 | 9 | ### SECURITY OVERVIEW 10 | 11 | * [RSA encrypt initial handshake message to cloud](https://github.com/spark/core-communication-lib/blob/master/src/spark_protocol.cpp#L102) 12 | * [Decrypt return message from Cloud with an RSA private key on the Core](https://github.com/spark/core-communication-lib/blob/master/src/handshake.cpp#L53) 13 | * [Verify HMAC signature](https://github.com/spark/core-communication-lib/blob/master/src/spark_protocol.cpp#L1022) 14 | * If everything checks out, AES-128-CBC session key is saved and IV is rotated with every message exchanged 15 | * [encrypt](https://github.com/spark/core-communication-lib/blob/master/src/spark_protocol.cpp#L989) 16 | * [decrypt](https://github.com/spark/core-communication-lib/blob/master/src/spark_protocol.cpp#L267) 17 | 18 | ### CREDITS AND ATTRIBUTIONS 19 | 20 | The Spark application team: Zachary Crockett, Satish Nair, Zach Supalla, David Middlecamp and Mohit Bhoite. 21 | 22 | The core-communication-lib uses the GNU GCC toolchain for ARM Cortex-M processors and XySSL/TropicSSL libraries. 23 | 24 | ### LICENSE 25 | Unless stated elsewhere, file headers or otherwise, the license as stated in the LICENSE file. 26 | 27 | ### CONTRIBUTE 28 | 29 | Want to contribute to the Spark Core project? Follow [this link]() to find out how. 30 | 31 | ### CONNECT 32 | 33 | Having problems or have awesome suggestions? Connect with us [here.](https://community.sparkdevices.com/) 34 | 35 | ### VERSION HISTORY 36 | 37 | Latest Version: v1.0.0 38 | 39 | 40 | -------------------------------------------------------------------------------- /build/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled objects and dependancies 2 | obj/ -------------------------------------------------------------------------------- /build/makefile: -------------------------------------------------------------------------------- 1 | 2 | # Define the compiler/tools prefix 3 | GCC_PREFIX ?= arm-none-eabi- 4 | 5 | # Define tools 6 | CC = $(GCC_PREFIX)gcc 7 | AR = $(GCC_PREFIX)ar 8 | OBJCOPY = $(GCC_PREFIX)objcopy 9 | 10 | RM = rm -f 11 | MKDIR = mkdir -p 12 | 13 | # Recursive wildcard function 14 | rwildcard = $(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)) 15 | 16 | # Define the build path, this is where all of the dependancies and 17 | # object files will be placed. 18 | # Note: Currently set to /build/obj directory and set relative to 19 | # the dir which makefile is invoked. If the makefile is moved to the project 20 | # root, BUILD_PATH = build can be used to store the build products in 21 | # the build directory. 22 | BUILD_PATH = obj 23 | 24 | # Path to the root of source files, in this case root of the project to 25 | # inclue ../src and ../lib dirs. 26 | # Note: Consider relocating source files in lib to src, or build a 27 | # seperate library. 28 | SRC_PATH = .. 29 | 30 | # Target this makefile is building. 31 | TARGET = libcore-communication-lib.a 32 | 33 | # Find all build.mk makefiles in each source directory in the src tree. 34 | SRC_MAKEFILES := $(call rwildcard,$(SRC_PATH)/,build.mk) 35 | 36 | # Include all build.mk defines source files. 37 | include $(SRC_MAKEFILES) 38 | 39 | # Additional include directories, applied to objects built for this target. 40 | INCLUDE_DIRS += 41 | 42 | # Compiler flags 43 | CFLAGS = -g3 -gdwarf-2 -Os -mcpu=cortex-m3 -mthumb 44 | CFLAGS += $(patsubst %,-I$(SRC_PATH)/%,$(INCLUDE_DIRS)) -I. 45 | CFLAGS += -ffunction-sections -fmessage-length=0 -Wall 46 | 47 | # Generate dependancy files automatically. 48 | CFLAGS += -MD -MP -MF $@.d 49 | 50 | # Target specific defines 51 | CFLAGS += -DSPARK_PRODUCT_ID=$(SPARK_PRODUCT_ID) 52 | CFLAGS += -DPRODUCT_FIRMWARE_VERSION=$(PRODUCT_FIRMWARE_VERSION) 53 | 54 | ifeq ("$(USE_SWD_JTAG)","y") 55 | CFLAGS += -DUSE_SWD_JTAG 56 | endif 57 | 58 | ifeq ("$(DEBUG_BUILD)","y") 59 | CFLAGS += -DDEBUG_BUILD 60 | else 61 | CFLAGS += -DRELEASE_BUILD 62 | endif 63 | 64 | # C++ specific flags 65 | CPPFLAGS = -fno-exceptions -fno-rtti 66 | 67 | SPARK_PRODUCT_ID ?= 65535 68 | PRODUCT_FIRMWARE_VERSION ?= 65535 69 | 70 | # Collect all object and dep files 71 | ALLOBJ += $(addprefix $(BUILD_PATH)/, $(CSRC:.c=.o)) 72 | ALLOBJ += $(addprefix $(BUILD_PATH)/, $(CPPSRC:.cpp=.o)) 73 | ALLOBJ += $(addprefix $(BUILD_PATH)/, $(ASRC:.S=.o)) 74 | 75 | ALLDEPS += $(addprefix $(BUILD_PATH)/, $(CSRC:.c=.o.d)) 76 | ALLDEPS += $(addprefix $(BUILD_PATH)/, $(CPPSRC:.cpp=.o.d)) 77 | ALLDEPS += $(addprefix $(BUILD_PATH)/, $(ASRC:.S=.o.d)) 78 | 79 | # All Target 80 | all: check_external_deps $(TARGET) 81 | 82 | # Check for external dependancies, none in this case. 83 | check_external_deps: 84 | 85 | # Tool invocations 86 | $(TARGET) : $(ALLOBJ) 87 | @echo 'Building target: $@' 88 | @echo 'Invoking: ARM GCC Archiver' 89 | $(AR) -r $@ $^ 90 | @echo ' ' 91 | 92 | # C compiler to build .o from .c in $(BUILD_DIR) 93 | $(BUILD_PATH)/%.o : $(SRC_PATH)/%.c 94 | @echo Building file: $< 95 | @echo Invoking: ARM GCC C Compiler 96 | $(MKDIR) $(dir $@) 97 | $(CC) $(CFLAGS) -c -o $@ $< 98 | @echo 99 | 100 | # CPP compiler to build .o from .cpp in $(BUILD_DIR) 101 | # Note: Calls standard $(CC) - gcc will invoke g++ as appropriate 102 | $(BUILD_PATH)/%.o : $(SRC_PATH)/%.cpp 103 | @echo Building file: $< 104 | @echo Invoking: ARM GCC CPP Compiler 105 | $(MKDIR) $(dir $@) 106 | $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< 107 | @echo 108 | 109 | # Other Targets 110 | clean: 111 | $(RM) $(ALLOBJ) $(ALLDEPS) $(TARGET) 112 | @echo ' ' 113 | 114 | .PHONY: all clean 115 | .SECONDARY: 116 | 117 | # Include auto generated dependancy files 118 | -include $(ALLDEPS) 119 | 120 | -------------------------------------------------------------------------------- /lib/tropicssl/include/tropicssl/aes.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file aes.h 3 | * 4 | * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine 5 | * 6 | * Copyright (C) 2009 Paul Bakker 7 | * 8 | * All rights reserved. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * * Neither the names of PolarSSL or XySSL nor the names of its contributors 20 | * may be used to endorse or promote products derived from this software 21 | * without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | */ 35 | #ifndef TROPICSSL_AES_H 36 | #define TROPICSSL_AES_H 37 | 38 | #define AES_ENCRYPT 1 39 | #define AES_DECRYPT 0 40 | 41 | /** 42 | * \brief AES context structure 43 | */ 44 | typedef struct { 45 | int nr; /*!< number of rounds */ 46 | unsigned long *rk; /*!< AES round keys */ 47 | unsigned long buf[68]; /*!< unaligned data */ 48 | } aes_context; 49 | 50 | #ifdef __cplusplus 51 | extern "C" { 52 | #endif 53 | 54 | /** 55 | * \brief AES key schedule (encryption) 56 | * 57 | * \param ctx AES context to be initialized 58 | * \param key encryption key 59 | * \param keysize must be 128, 192 or 256 60 | */ 61 | void aes_setkey_enc(aes_context * ctx, const unsigned char *key, int keysize); 62 | 63 | /** 64 | * \brief AES key schedule (decryption) 65 | * 66 | * \param ctx AES context to be initialized 67 | * \param key decryption key 68 | * \param keysize must be 128, 192 or 256 69 | */ 70 | void aes_setkey_dec(aes_context * ctx, const unsigned char *key, int keysize); 71 | 72 | /** 73 | * \brief AES-ECB block encryption/decryption 74 | * 75 | * \param ctx AES context 76 | * \param mode AES_ENCRYPT or AES_DECRYPT 77 | * \param input 16-byte input block 78 | * \param output 16-byte output block 79 | */ 80 | void aes_crypt_ecb(aes_context * ctx, 81 | int mode, 82 | const unsigned char input[16], 83 | unsigned char output[16]); 84 | 85 | /** 86 | * \brief AES-CBC buffer encryption/decryption 87 | * 88 | * \param ctx AES context 89 | * \param mode AES_ENCRYPT or AES_DECRYPT 90 | * \param length length of the input data 91 | * \param iv initialization vector (updated after use) 92 | * \param input buffer holding the input data 93 | * \param output buffer holding the output data 94 | */ 95 | void aes_crypt_cbc(aes_context * ctx, 96 | int mode, 97 | int length, 98 | unsigned char iv[16], 99 | const unsigned char *input, 100 | unsigned char *output); 101 | 102 | /** 103 | * \brief AES-CFB128 buffer encryption/decryption 104 | * 105 | * \param ctx AES context 106 | * \param mode AES_ENCRYPT or AES_DECRYPT 107 | * \param length length of the input data 108 | * \param iv_off offset in IV (updated after use) 109 | * \param iv initialization vector (updated after use) 110 | * \param input buffer holding the input data 111 | * \param output buffer holding the output data 112 | */ 113 | void aes_crypt_cfb128(aes_context * ctx, 114 | int mode, 115 | int length, 116 | int *iv_off, 117 | unsigned char iv[16], 118 | const unsigned char *input, 119 | unsigned char *output); 120 | 121 | /** 122 | * \brief Checkup routine 123 | * 124 | * \return 0 if successful, or 1 if the test failed 125 | */ 126 | int aes_self_test(int verbose); 127 | 128 | #ifdef __cplusplus 129 | } 130 | #endif 131 | #endif /* aes.h */ 132 | -------------------------------------------------------------------------------- /lib/tropicssl/include/tropicssl/bignum.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file bignum.h 3 | * 4 | * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine 5 | * 6 | * Copyright (C) 2009 Paul Bakker 7 | * 8 | * All rights reserved. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * * Neither the names of PolarSSL or XySSL nor the names of its contributors 20 | * may be used to endorse or promote products derived from this software 21 | * without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | */ 35 | #ifndef TROPICSSL_BIGNUM_H 36 | #define TROPICSSL_BIGNUM_H 37 | 38 | #include 39 | 40 | #define TROPICSSL_ERR_MPI_FILE_IO_ERROR -0x0002 41 | #define TROPICSSL_ERR_MPI_BAD_INPUT_DATA -0x0004 42 | #define TROPICSSL_ERR_MPI_INVALID_CHARACTER -0x0006 43 | #define TROPICSSL_ERR_MPI_BUFFER_TOO_SMALL -0x0008 44 | #define TROPICSSL_ERR_MPI_NEGATIVE_VALUE -0x000A 45 | #define TROPICSSL_ERR_MPI_DIVISION_BY_ZERO -0x000C 46 | #define TROPICSSL_ERR_MPI_NOT_ACCEPTABLE -0x000E 47 | 48 | #define MPI_CHK(f) if( ( ret = f ) != 0 ) goto cleanup 49 | 50 | /* 51 | * Define the base integer type, architecture-wise 52 | */ 53 | #if defined(TROPICSSL_HAVE_INT8) 54 | typedef unsigned char t_int; 55 | typedef unsigned short t_dbl; 56 | #else 57 | #if defined(TROPICSSL_HAVE_INT16) 58 | typedef unsigned short t_int; 59 | typedef unsigned long t_dbl; 60 | #else 61 | typedef unsigned long t_int; 62 | #if defined(_MSC_VER) && defined(_M_IX86) 63 | typedef unsigned __int64 t_dbl; 64 | #else 65 | #if defined(__amd64__) || defined(__x86_64__) || \ 66 | defined(__ppc64__) || defined(__powerpc64__) || \ 67 | defined(__ia64__) || defined(__alpha__) 68 | typedef unsigned int t_dbl __attribute__ ((mode(TI))); 69 | #else 70 | typedef unsigned long long t_dbl; 71 | #endif 72 | #endif 73 | #endif 74 | #endif 75 | 76 | /** 77 | * \brief MPI structure 78 | */ 79 | typedef struct { 80 | int s; /*!< integer sign */ 81 | int n; /*!< total # of limbs */ 82 | t_int *p; /*!< pointer to limbs */ 83 | } mpi; 84 | 85 | #ifdef __cplusplus 86 | extern "C" { 87 | #endif 88 | 89 | /** 90 | * \brief Initialize one MPI 91 | */ 92 | void mpi_init(mpi * X); 93 | 94 | /** 95 | * \brief Unallocate one MPI 96 | */ 97 | void mpi_free(mpi * X); 98 | 99 | /** 100 | * \brief Enlarge to the specified number of limbs 101 | * 102 | * \return 0 if successful, 103 | * 1 if memory allocation failed 104 | */ 105 | int mpi_grow(mpi * X, int nblimbs); 106 | 107 | /** 108 | * \brief Copy the contents of Y into X 109 | * 110 | * \return 0 if successful, 111 | * 1 if memory allocation failed 112 | */ 113 | int mpi_copy(mpi * X, const mpi * Y); 114 | 115 | /** 116 | * \brief Swap the contents of X and Y 117 | */ 118 | void mpi_swap(mpi * X, mpi * Y); 119 | 120 | /** 121 | * \brief Set value from integer 122 | * 123 | * \return 0 if successful, 124 | * 1 if memory allocation failed 125 | */ 126 | int mpi_lset(mpi * X, int z); 127 | 128 | /** 129 | * \brief Return the number of least significant bits 130 | */ 131 | int mpi_lsb(const mpi * X); 132 | 133 | /** 134 | * \brief Return the number of most significant bits 135 | */ 136 | int mpi_msb(const mpi * X); 137 | 138 | /** 139 | * \brief Return the total size in bytes 140 | */ 141 | int mpi_size(const mpi * X); 142 | 143 | /** 144 | * \brief Import from an ASCII string 145 | * 146 | * \param X destination mpi 147 | * \param radix input numeric base 148 | * \param s null-terminated string buffer 149 | * 150 | * \return 0 if successful, or an TROPICSSL_ERR_MPI_XXX error code 151 | */ 152 | int mpi_read_string(mpi * X, int radix, const char *s); 153 | 154 | /** 155 | * \brief Export into an ASCII string 156 | * 157 | * \param X source mpi 158 | * \param radix output numeric base 159 | * \param s string buffer 160 | * \param slen string buffer size 161 | * 162 | * \return 0 if successful, or an TROPICSSL_ERR_MPI_XXX error code 163 | * 164 | * \note Call this function with *slen = 0 to obtain the 165 | * minimum required buffer size in *slen. 166 | */ 167 | int mpi_write_string(const mpi * X, int radix, char *s, int *slen); 168 | 169 | /** 170 | * \brief Read X from an opened file 171 | * 172 | * \param X destination mpi 173 | * \param radix input numeric base 174 | * \param fin input file handle 175 | * 176 | * \return 0 if successful, or an TROPICSSL_ERR_MPI_XXX error code 177 | */ 178 | int mpi_read_file(mpi * X, int radix, FILE * fin); 179 | 180 | /** 181 | * \brief Write X into an opened file, or stdout 182 | * 183 | * \param p prefix, can be NULL 184 | * \param X source mpi 185 | * \param radix output numeric base 186 | * \param fout output file handle 187 | * 188 | * \return 0 if successful, or an TROPICSSL_ERR_MPI_XXX error code 189 | * 190 | * \note Set fout == NULL to print X on the console. 191 | */ 192 | int mpi_write_file(const char *p, const mpi * X, int radix, FILE * fout); 193 | 194 | /** 195 | * \brief Import X from unsigned binary data, big endian 196 | * 197 | * \param X destination mpi 198 | * \param buf input buffer 199 | * \param buflen input buffer size 200 | * 201 | * \return 0 if successful, 202 | * 1 if memory allocation failed 203 | */ 204 | int mpi_read_binary(mpi * X, const unsigned char *buf, int buflen); 205 | 206 | /** 207 | * \brief Export X into unsigned binary data, big endian 208 | * 209 | * \param X source mpi 210 | * \param buf output buffer 211 | * \param buflen output buffer size 212 | * 213 | * \return 0 if successful, 214 | * TROPICSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough 215 | * 216 | * \note Call this function with *buflen = 0 to obtain the 217 | * minimum required buffer size in *buflen. 218 | */ 219 | int mpi_write_binary(const mpi * X, unsigned char *buf, int buflen); 220 | 221 | /** 222 | * \brief Left-shift: X <<= count 223 | * 224 | * \return 0 if successful, 225 | * 1 if memory allocation failed 226 | */ 227 | int mpi_shift_l(mpi * X, int count); 228 | 229 | /** 230 | * \brief Right-shift: X >>= count 231 | * 232 | * \return 0 if successful, 233 | * 1 if memory allocation failed 234 | */ 235 | int mpi_shift_r(mpi * X, int count); 236 | 237 | /** 238 | * \brief Compare unsigned values 239 | * 240 | * \return 1 if |X| is greater than |Y|, 241 | * -1 if |X| is lesser than |Y| or 242 | * 0 if |X| is equal to |Y| 243 | */ 244 | int mpi_cmp_abs(const mpi * X, const mpi * Y); 245 | 246 | /** 247 | * \brief Compare signed values 248 | * 249 | * \return 1 if X is greater than Y, 250 | * -1 if X is lesser than Y or 251 | * 0 if X is equal to Y 252 | */ 253 | int mpi_cmp_mpi(const mpi * X, const mpi * Y); 254 | 255 | /** 256 | * \brief Compare signed values 257 | * 258 | * \return 1 if X is greater than z, 259 | * -1 if X is lesser than z or 260 | * 0 if X is equal to z 261 | */ 262 | int mpi_cmp_int(const mpi * X, int z); 263 | 264 | /** 265 | * \brief Unsigned addition: X = |A| + |B| 266 | * 267 | * \return 0 if successful, 268 | * 1 if memory allocation failed 269 | */ 270 | int mpi_add_abs(mpi * X, const mpi * A, const mpi * B); 271 | 272 | /** 273 | * \brief Unsigned substraction: X = |A| - |B| 274 | * 275 | * \return 0 if successful, 276 | * TROPICSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A 277 | */ 278 | int mpi_sub_abs(mpi * X, const mpi * A, const mpi * B); 279 | 280 | /** 281 | * \brief Signed addition: X = A + B 282 | * 283 | * \return 0 if successful, 284 | * 1 if memory allocation failed 285 | */ 286 | int mpi_add_mpi(mpi * X, const mpi * A, const mpi * B); 287 | 288 | /** 289 | * \brief Signed substraction: X = A - B 290 | * 291 | * \return 0 if successful, 292 | * 1 if memory allocation failed 293 | */ 294 | int mpi_sub_mpi(mpi * X, const mpi * A, const mpi * B); 295 | 296 | /** 297 | * \brief Signed addition: X = A + b 298 | * 299 | * \return 0 if successful, 300 | * 1 if memory allocation failed 301 | */ 302 | int mpi_add_int(mpi * X, const mpi * A, int b); 303 | 304 | /** 305 | * \brief Signed substraction: X = A - b 306 | * 307 | * \return 0 if successful, 308 | * 1 if memory allocation failed 309 | */ 310 | int mpi_sub_int(mpi * X, const mpi * A, int b); 311 | 312 | /** 313 | * \brief Baseline multiplication: X = A * B 314 | * 315 | * \return 0 if successful, 316 | * 1 if memory allocation failed 317 | */ 318 | int mpi_mul_mpi(mpi * X, const mpi * A, const mpi * B); 319 | 320 | /** 321 | * \brief Baseline multiplication: X = A * b 322 | * 323 | * \return 0 if successful, 324 | * 1 if memory allocation failed 325 | */ 326 | int mpi_mul_int(mpi * X, const mpi * A, t_int b); 327 | 328 | /** 329 | * \brief Division by mpi: A = Q * B + R 330 | * 331 | * \return 0 if successful, 332 | * 1 if memory allocation failed, 333 | * TROPICSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0 334 | * 335 | * \note Either Q or R can be NULL. 336 | */ 337 | int mpi_div_mpi(mpi * Q, mpi * R, const mpi * A, const mpi * B); 338 | 339 | /** 340 | * \brief Division by int: A = Q * b + R 341 | * 342 | * \return 0 if successful, 343 | * 1 if memory allocation failed, 344 | * TROPICSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0 345 | * 346 | * \note Either Q or R can be NULL. 347 | */ 348 | int mpi_div_int(mpi * Q, mpi * R, const mpi * A, int b); 349 | 350 | /** 351 | * \brief Modulo: R = A mod B 352 | * 353 | * \return 0 if successful, 354 | * 1 if memory allocation failed, 355 | * TROPICSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0 356 | */ 357 | int mpi_mod_mpi(mpi * R, const mpi * A, const mpi * B); 358 | 359 | /** 360 | * \brief Modulo: r = A mod b 361 | * 362 | * \return 0 if successful, 363 | * 1 if memory allocation failed, 364 | * TROPICSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0 365 | */ 366 | int mpi_mod_int(t_int * r, const mpi * A, int b); 367 | 368 | /** 369 | * \brief Sliding-window exponentiation: X = A^E mod N 370 | * 371 | * \return 0 if successful, 372 | * 1 if memory allocation failed, 373 | * TROPICSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even 374 | * 375 | * \note _RR is used to avoid re-computing R*R mod N across 376 | * multiple calls, which speeds up things a bit. It can 377 | * be set to NULL if the extra performance is unneeded. 378 | */ 379 | int mpi_exp_mod(mpi * X, const mpi * A, const mpi * E, const mpi * N, mpi * _RR); 380 | 381 | /** 382 | * \brief Greatest common divisor: G = gcd(A, B) 383 | * 384 | * \return 0 if successful, 385 | * 1 if memory allocation failed 386 | */ 387 | int mpi_gcd(mpi * G, const mpi * A, const mpi * B); 388 | 389 | /** 390 | * \brief Modular inverse: X = A^-1 mod N 391 | * 392 | * \return 0 if successful, 393 | * 1 if memory allocation failed, 394 | * TROPICSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil 395 | * TROPICSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N 396 | */ 397 | int mpi_inv_mod(mpi * X, const mpi * A, const mpi * N); 398 | 399 | /** 400 | * \brief Miller-Rabin primality test 401 | * 402 | * \return 0 if successful (probably prime), 403 | * 1 if memory allocation failed, 404 | * TROPICSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime 405 | */ 406 | int mpi_is_prime(mpi * X, int (*f_rng) (void *), void *p_rng); 407 | 408 | /** 409 | * \brief Prime number generation 410 | * 411 | * \param X destination mpi 412 | * \param nbits required size of X in bits 413 | * \param dh_flag if 1, then (X-1)/2 will be prime too 414 | * \param f_rng RNG function 415 | * \param p_rng RNG parameter 416 | * 417 | * \return 0 if successful (probably prime), 418 | * 1 if memory allocation failed, 419 | * TROPICSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 420 | */ 421 | int mpi_gen_prime(mpi * X, int nbits, int dh_flag, 422 | int (*f_rng) (void *), void *p_rng); 423 | 424 | /** 425 | * \brief Checkup routine 426 | * 427 | * \return 0 if successful, or 1 if the test failed 428 | */ 429 | int mpi_self_test(int verbose); 430 | 431 | #ifdef __cplusplus 432 | } 433 | #endif 434 | #endif /* bignum.h */ 435 | -------------------------------------------------------------------------------- /lib/tropicssl/include/tropicssl/config.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file config.h 3 | * 4 | * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine 5 | * 6 | * Copyright (C) 2009 Paul Bakker 7 | * 8 | * All rights reserved. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * * Neither the names of PolarSSL or XySSL nor the names of its contributors 20 | * may be used to endorse or promote products derived from this software 21 | * without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | * 35 | * This set of compile-time options may be used to enable 36 | * or disable features selectively, and reduce the global 37 | * memory footprint. 38 | */ 39 | #ifndef TROPICSSL_CONFIG_H 40 | #define TROPICSSL_CONFIG_H 41 | 42 | #ifndef _CRT_SECURE_NO_DEPRECATE 43 | #define _CRT_SECURE_NO_DEPRECATE 1 44 | #endif 45 | 46 | /* 47 | * Uncomment if native integers are 8-bit wide. 48 | * 49 | #define TROPICSSL_HAVE_INT8 50 | */ 51 | 52 | /* 53 | * Uncomment if native integers are 16-bit wide. 54 | * 55 | #define TROPICSSL_HAVE_INT16 56 | */ 57 | 58 | /* 59 | * Uncomment if the compiler supports long long. 60 | * 61 | #define TROPICSSL_HAVE_LONGLONG 62 | */ 63 | 64 | /* 65 | * Uncomment to enable the use of assembly code. 66 | */ 67 | #define TROPICSSL_HAVE_ASM 68 | 69 | /* 70 | * Uncomment if the CPU supports SSE2 (IA-32 specific). 71 | * 72 | #define TROPICSSL_HAVE_SSE2 73 | */ 74 | 75 | /* 76 | * Enable all SSL/TLS debugging messages. 77 | */ 78 | #define TROPICSSL_DEBUG_MSG 79 | 80 | /* 81 | * Enable the checkup functions (*_self_test). 82 | */ 83 | #define TROPICSSL_SELF_TEST 84 | 85 | /* 86 | * Enable the prime-number generation code. 87 | */ 88 | #define TROPICSSL_GENPRIME 89 | 90 | /* 91 | * Uncomment this macro to store the AES tables in ROM. 92 | * 93 | */ 94 | #define TROPICSSL_AES_ROM_TABLES 95 | 96 | /* 97 | * Module: library/aes.c 98 | * Caller: library/ssl_tls.c 99 | * 100 | * This module enables the following ciphersuites: 101 | * SSL_RSA_AES_128_SHA 102 | * SSL_RSA_AES_256_SHA 103 | * SSL_EDH_RSA_AES_256_SHA 104 | */ 105 | #define TROPICSSL_AES_C 106 | 107 | /* 108 | * Module: library/arc4.c 109 | * Caller: library/ssl_tls.c 110 | * 111 | * This module enables the following ciphersuites: 112 | * SSL_RSA_RC4_128_MD5 113 | * SSL_RSA_RC4_128_SHA 114 | */ 115 | #define TROPICSSL_ARC4_C 116 | 117 | /* 118 | * Module: library/base64.c 119 | * Caller: library/x509parse.c 120 | * 121 | * This module is required for X.509 support. 122 | */ 123 | #define TROPICSSL_BASE64_C 124 | 125 | /* 126 | * Module: library/bignum.c 127 | * Caller: library/dhm.c 128 | * library/rsa.c 129 | * library/ssl_tls.c 130 | * library/x509parse.c 131 | * 132 | * This module is required for RSA and DHM support. 133 | */ 134 | #define TROPICSSL_BIGNUM_C 135 | 136 | /* 137 | * Module: library/camellia.c 138 | * Caller: 139 | * 140 | * This module enabled the following cipher suites: 141 | */ 142 | #define TROPICSSL_CAMELLIA_C 143 | 144 | /* 145 | * Module: library/certs.c 146 | * Caller: 147 | * 148 | * This module is used for testing (ssl_client/server). 149 | */ 150 | #define TROPICSSL_CERTS_C 151 | 152 | /* 153 | * Module: library/debug.c 154 | * Caller: library/ssl_cli.c 155 | * library/ssl_srv.c 156 | * library/ssl_tls.c 157 | * 158 | * This module provides debugging functions. 159 | */ 160 | #define TROPICSSL_DEBUG_C 161 | 162 | /* 163 | * Module: library/des.c 164 | * Caller: library/ssl_tls.c 165 | * 166 | * This module enables the following ciphersuites: 167 | * SSL_RSA_DES_168_SHA 168 | * SSL_EDH_RSA_DES_168_SHA 169 | */ 170 | #define TROPICSSL_DES_C 171 | 172 | /* 173 | * Module: library/dhm.c 174 | * Caller: library/ssl_cli.c 175 | * library/ssl_srv.c 176 | * 177 | * This module enables the following ciphersuites: 178 | * SSL_EDH_RSA_DES_168_SHA 179 | * SSL_EDH_RSA_AES_256_SHA 180 | */ 181 | #define TROPICSSL_DHM_C 182 | 183 | /* 184 | * Module: library/havege.c 185 | * Caller: 186 | * 187 | * This module enables the HAVEGE random number generator. 188 | */ 189 | #define TROPICSSL_HAVEGE_C 190 | 191 | /* 192 | * Module: library/md2.c 193 | * Caller: library/x509parse.c 194 | * 195 | * Uncomment to enable support for (rare) MD2-signed X.509 certs. 196 | * 197 | #define TROPICSSL_MD2_C 198 | */ 199 | 200 | /* 201 | * Module: library/md4.c 202 | * Caller: library/x509parse.c 203 | * 204 | * Uncomment to enable support for (rare) MD4-signed X.509 certs. 205 | * 206 | #define TROPICSSL_MD4_C 207 | */ 208 | 209 | /* 210 | * Module: library/md5.c 211 | * Caller: library/ssl_tls.c 212 | * library/x509parse.c 213 | * 214 | * This module is required for SSL/TLS and X.509. 215 | */ 216 | #define TROPICSSL_MD5_C 217 | 218 | /* 219 | * Module: library/net.c 220 | * Caller: 221 | * 222 | * This module provides TCP/IP networking routines. 223 | */ 224 | #define TROPICSSL_NET_C 225 | 226 | /* 227 | * Module: library/padlock.c 228 | * Caller: library/aes.c 229 | * 230 | * This modules adds support for the VIA PadLock on x86. 231 | */ 232 | #define TROPICSSL_PADLOCK_C 233 | 234 | /* 235 | * Module: library/rsa.c 236 | * Caller: library/ssl_cli.c 237 | * library/ssl_srv.c 238 | * library/ssl_tls.c 239 | * library/x509.c 240 | * 241 | * This module is required for SSL/TLS and MD5-signed certificates. 242 | */ 243 | #define TROPICSSL_RSA_C 244 | 245 | /* 246 | * Module: library/sha1.c 247 | * Caller: library/ssl_cli.c 248 | * library/ssl_srv.c 249 | * library/ssl_tls.c 250 | * library/x509parse.c 251 | * 252 | * This module is required for SSL/TLS and SHA1-signed certificates. 253 | */ 254 | #define TROPICSSL_SHA1_C 255 | 256 | /* 257 | * Module: library/sha2.c 258 | * Caller: 259 | * 260 | * This module adds support for SHA-224 and SHA-256. 261 | */ 262 | #define TROPICSSL_SHA2_C 263 | 264 | /* 265 | * Module: library/sha4.c 266 | * Caller: 267 | * 268 | * This module adds support for SHA-384 and SHA-512. 269 | */ 270 | #define TROPICSSL_SHA4_C 271 | 272 | /* 273 | * Module: library/ssl_cli.c 274 | * Caller: 275 | * 276 | * This module is required for SSL/TLS client support. 277 | */ 278 | #define TROPICSSL_SSL_CLI_C 279 | 280 | /* 281 | * Module: library/ssl_srv.c 282 | * Caller: 283 | * 284 | * This module is required for SSL/TLS server support. 285 | */ 286 | #define TROPICSSL_SSL_SRV_C 287 | 288 | /* 289 | * Module: library/ssl_tls.c 290 | * Caller: library/ssl_cli.c 291 | * library/ssl_srv.c 292 | * 293 | * This module is required for SSL/TLS. 294 | */ 295 | #define TROPICSSL_SSL_TLS_C 296 | 297 | /* 298 | * Module: library/timing.c 299 | * Caller: library/havege.c 300 | * 301 | * This module is used by the HAVEGE random number generator. 302 | */ 303 | #define TROPICSSL_TIMING_C 304 | 305 | /* 306 | * Module: library/x509parse.c 307 | * Caller: library/ssl_cli.c 308 | * library/ssl_srv.c 309 | * library/ssl_tls.c 310 | * 311 | * This module is required for X.509 certificate parsing. 312 | */ 313 | #define TROPICSSL_X509_PARSE_C 314 | 315 | /* 316 | * Module: library/x509_write.c 317 | * Caller: 318 | * 319 | * This module is required for X.509 certificate writing. 320 | */ 321 | #define TROPICSSL_X509_WRITE_C 322 | 323 | /* 324 | * Module: library/xtea.c 325 | * Caller: 326 | */ 327 | #define TROPICSSL_XTEA_C 328 | 329 | #endif /* config.h */ 330 | -------------------------------------------------------------------------------- /lib/tropicssl/include/tropicssl/padlock.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file padlock.h 3 | * 4 | * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine 5 | * 6 | * Copyright (C) 2009 Paul Bakker 7 | * 8 | * All rights reserved. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * * Neither the names of PolarSSL or XySSL nor the names of its contributors 20 | * may be used to endorse or promote products derived from this software 21 | * without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | */ 35 | #ifndef TROPICSSL_PADLOCK_H 36 | #define TROPICSSL_PADLOCK_H 37 | 38 | #include "tropicssl/aes.h" 39 | 40 | #if (defined(__GNUC__) && defined(__i386__)) 41 | 42 | #ifndef TROPICSSL_HAVE_X86 43 | #define TROPICSSL_HAVE_X86 44 | #endif 45 | 46 | #define PADLOCK_RNG 0x000C 47 | #define PADLOCK_ACE 0x00C0 48 | #define PADLOCK_PHE 0x0C00 49 | #define PADLOCK_PMM 0x3000 50 | 51 | #define PADLOCK_ALIGN16(x) (unsigned long *) (16 + ((long) x & ~15)) 52 | 53 | #ifdef __cplusplus 54 | extern "C" { 55 | #endif 56 | 57 | /** 58 | * \brief PadLock detection routine 59 | * 60 | * \return 1 if CPU has support for the feature, 0 otherwise 61 | */ 62 | int padlock_supports(int feature); 63 | 64 | /** 65 | * \brief PadLock AES-ECB block en(de)cryption 66 | * 67 | * \param ctx AES context 68 | * \param mode AES_ENCRYPT or AES_DECRYPT 69 | * \param input 16-byte input block 70 | * \param output 16-byte output block 71 | * 72 | * \return 0 if success, 1 if operation failed 73 | */ 74 | int padlock_xcryptecb(aes_context * ctx, 75 | int mode, 76 | const unsigned char input[16], 77 | unsigned char output[16]); 78 | 79 | /** 80 | * \brief PadLock AES-CBC buffer en(de)cryption 81 | * 82 | * \param ctx AES context 83 | * \param mode AES_ENCRYPT or AES_DECRYPT 84 | * \param length length of the input data 85 | * \param iv initialization vector (updated after use) 86 | * \param input buffer holding the input data 87 | * \param output buffer holding the output data 88 | * 89 | * \return 0 if success, 1 if operation failed 90 | */ 91 | int padlock_xcryptcbc(aes_context * ctx, 92 | int mode, 93 | int length, 94 | unsigned char iv[16], 95 | const unsigned char *input, 96 | unsigned char *output); 97 | 98 | #ifdef __cplusplus 99 | } 100 | #endif 101 | #endif /* HAVE_X86 */ 102 | #endif /* padlock.h */ 103 | -------------------------------------------------------------------------------- /lib/tropicssl/include/tropicssl/rsa.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file rsa.h 3 | * 4 | * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine 5 | * 6 | * Copyright (C) 2009 Paul Bakker 7 | * 8 | * All rights reserved. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * * Neither the names of PolarSSL or XySSL nor the names of its contributors 20 | * may be used to endorse or promote products derived from this software 21 | * without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | */ 35 | #ifndef TROPICSSL_RSA_H 36 | #define TROPICSSL_RSA_H 37 | 38 | #include "tropicssl/bignum.h" 39 | 40 | #define TROPICSSL_ERR_RSA_BAD_INPUT_DATA -0x0400 41 | #define TROPICSSL_ERR_RSA_INVALID_PADDING -0x0410 42 | #define TROPICSSL_ERR_RSA_KEY_GEN_FAILED -0x0420 43 | #define TROPICSSL_ERR_RSA_KEY_CHECK_FAILED -0x0430 44 | #define TROPICSSL_ERR_RSA_PUBLIC_FAILED -0x0440 45 | #define TROPICSSL_ERR_RSA_PRIVATE_FAILED -0x0450 46 | #define TROPICSSL_ERR_RSA_VERIFY_FAILED -0x0460 47 | #define TROPICSSL_ERR_RSA_OUTPUT_TO_LARGE -0x0470 48 | 49 | /* 50 | * PKCS#1 constants 51 | */ 52 | #define RSA_RAW 0 53 | #define RSA_MD2 2 54 | #define RSA_MD4 3 55 | #define RSA_MD5 4 56 | #define RSA_SHA1 5 57 | #define RSA_SHA256 6 58 | 59 | #define RSA_PUBLIC 0 60 | #define RSA_PRIVATE 1 61 | 62 | #define RSA_PKCS_V15 0 63 | #define RSA_PKCS_V21 1 64 | 65 | #define RSA_SIGN 1 66 | #define RSA_CRYPT 2 67 | 68 | /* 69 | * DigestInfo ::= SEQUENCE { 70 | * digestAlgorithm DigestAlgorithmIdentifier, 71 | * digest Digest } 72 | * 73 | * DigestAlgorithmIdentifier ::= AlgorithmIdentifier 74 | * 75 | * Digest ::= OCTET STRING 76 | */ 77 | #define ASN1_HASH_MDX \ 78 | "\x30\x20\x30\x0C\x06\x08\x2A\x86\x48" \ 79 | "\x86\xF7\x0D\x02\x00\x05\x00\x04\x10" 80 | 81 | #define ASN1_HASH_SHA1 \ 82 | "\x30\x21\x30\x09\x06\x05\x2B\x0E\x03" \ 83 | "\x02\x1A\x05\x00\x04\x14" 84 | 85 | /** 86 | * \brief RSA context structure 87 | */ 88 | typedef struct { 89 | int ver; /*!< always 0 */ 90 | int len; /*!< size(N) in chars */ 91 | 92 | mpi N; /*!< public modulus */ 93 | mpi E; /*!< public exponent */ 94 | 95 | mpi D; /*!< private exponent */ 96 | mpi P; /*!< 1st prime factor */ 97 | mpi Q; /*!< 2nd prime factor */ 98 | mpi DP; /*!< D % (P - 1) */ 99 | mpi DQ; /*!< D % (Q - 1) */ 100 | mpi QP; /*!< 1 / (Q % P) */ 101 | 102 | mpi RN; /*!< cached R^2 mod N */ 103 | mpi RP; /*!< cached R^2 mod P */ 104 | mpi RQ; /*!< cached R^2 mod Q */ 105 | 106 | int padding; /*!< 1.5 or OAEP/PSS */ 107 | int hash_id; /*!< hash identifier */ 108 | int (*f_rng) (void *); /*!< RNG function */ 109 | void *p_rng; /*!< RNG parameter */ 110 | } rsa_context; 111 | 112 | #ifdef __cplusplus 113 | extern "C" { 114 | #endif 115 | 116 | /** 117 | * \brief Initialize an RSA context 118 | * 119 | * \param ctx RSA context to be initialized 120 | * \param padding RSA_PKCS_V15 or RSA_PKCS_V21 121 | * \param hash_id RSA_PKCS_V21 hash identifier 122 | * \param f_rng RNG function 123 | * \param p_rng RNG parameter 124 | * 125 | * \note The hash_id parameter is actually ignored 126 | * when using RSA_PKCS_V15 padding. 127 | * 128 | * \note Currently (xyssl-0.8), RSA_PKCS_V21 padding 129 | * is not supported. 130 | */ 131 | void rsa_init(rsa_context * ctx, 132 | int padding, 133 | int hash_id, int (*f_rng) (void *), void *p_rng); 134 | 135 | /** 136 | * \brief Generate an RSA keypair 137 | * 138 | * \param ctx RSA context that will hold the key 139 | * \param nbits size of the public key in bits 140 | * \param exponent public exponent (e.g., 65537) 141 | * 142 | * \note rsa_init() must be called beforehand to setup 143 | * the RSA context (especially f_rng and p_rng). 144 | * 145 | * \return 0 if successful, or an TROPICSSL_ERR_RSA_XXX error code 146 | */ 147 | int rsa_gen_key(rsa_context * ctx, int nbits, int exponent); 148 | 149 | /** 150 | * \brief Check a public RSA key 151 | * 152 | * \param ctx RSA context to be checked 153 | * 154 | * \return 0 if successful, or an TROPICSSL_ERR_RSA_XXX error code 155 | */ 156 | int rsa_check_pubkey(const rsa_context * ctx); 157 | 158 | /** 159 | * \brief Check a private RSA key 160 | * 161 | * \param ctx RSA context to be checked 162 | * 163 | * \return 0 if successful, or an TROPICSSL_ERR_RSA_XXX error code 164 | */ 165 | int rsa_check_privkey(const rsa_context * ctx); 166 | 167 | /** 168 | * \brief Do an RSA public key operation 169 | * 170 | * \param ctx RSA context 171 | * \param input input buffer 172 | * \param output output buffer 173 | * 174 | * \return 0 if successful, or an TROPICSSL_ERR_RSA_XXX error code 175 | * 176 | * \note This function does NOT take care of message 177 | * padding. Also, be sure to set input[0] = 0. 178 | * 179 | * \note The input and output buffers must be large 180 | * enough (eg. 128 bytes if RSA-1024 is used). 181 | */ 182 | int rsa_public(rsa_context * ctx, 183 | const unsigned char *input, 184 | unsigned char *output); 185 | 186 | /** 187 | * \brief Do an RSA private key operation 188 | * 189 | * \param ctx RSA context 190 | * \param input input buffer 191 | * \param output output buffer 192 | * 193 | * \return 0 if successful, or an TROPICSSL_ERR_RSA_XXX error code 194 | * 195 | * \note The input and output buffers must be large 196 | * enough (eg. 128 bytes if RSA-1024 is used). 197 | */ 198 | int rsa_private(rsa_context * ctx, 199 | const unsigned char *input, 200 | unsigned char *output); 201 | 202 | /** 203 | * \brief Add the message padding, then do an RSA operation 204 | * 205 | * \param ctx RSA context 206 | * \param mode RSA_PUBLIC or RSA_PRIVATE 207 | * \param ilen contains the the plaintext length 208 | * \param input buffer holding the data to be encrypted 209 | * \param output buffer that will hold the ciphertext 210 | * 211 | * \return 0 if successful, or an TROPICSSL_ERR_RSA_XXX error code 212 | * 213 | * \note The output buffer must be as large as the size 214 | * of ctx->N (eg. 128 bytes if RSA-1024 is used). 215 | */ 216 | int rsa_pkcs1_encrypt(rsa_context * ctx, 217 | int mode, int ilen, 218 | const unsigned char *input, 219 | unsigned char *output); 220 | 221 | /** 222 | * \brief Do an RSA operation, then remove the message padding 223 | * 224 | * \param ctx RSA context 225 | * \param mode RSA_PUBLIC or RSA_PRIVATE 226 | * \param input buffer holding the encrypted data 227 | * \param output buffer that will hold the plaintext 228 | * \param olen will contain the plaintext length 229 | * \param output_max_len maximum length of the output buffer 230 | * 231 | * \return 0 if successful, or an TROPICSSL_ERR_RSA_XXX error code 232 | * 233 | * \note The output buffer must be as large as the size 234 | * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise 235 | * an error is thrown. 236 | */ 237 | int rsa_pkcs1_decrypt(rsa_context * ctx, 238 | int mode, int *olen, 239 | const unsigned char *input, 240 | unsigned char *output, 241 | int output_max_len); 242 | 243 | /** 244 | * \brief Do a private RSA to sign a message digest 245 | * 246 | * \param ctx RSA context 247 | * \param mode RSA_PUBLIC or RSA_PRIVATE 248 | * \param hash_id RSA_RAW, RSA_MD{2,4,5} or RSA_SHA{1,256} 249 | * \param hashlen message digest length (for RSA_RAW only) 250 | * \param hash buffer holding the message digest 251 | * \param sig buffer that will hold the ciphertext 252 | * 253 | * \return 0 if the signing operation was successful, 254 | * or an TROPICSSL_ERR_RSA_XXX error code 255 | * 256 | * \note The "sig" buffer must be as large as the size 257 | * of ctx->N (eg. 128 bytes if RSA-1024 is used). 258 | */ 259 | int rsa_pkcs1_sign(rsa_context * ctx, 260 | int mode, 261 | int hash_id, 262 | int hashlen, 263 | const unsigned char *hash, 264 | unsigned char *sig); 265 | 266 | /** 267 | * \brief Do a public RSA and check the message digest 268 | * 269 | * \param ctx points to an RSA public key 270 | * \param mode RSA_PUBLIC or RSA_PRIVATE 271 | * \param hash_id RSA_RAW, RSA_MD{2,4,5} or RSA_SHA{1,256} 272 | * \param hashlen message digest length (for RSA_RAW only) 273 | * \param hash buffer holding the message digest 274 | * \param sig buffer holding the ciphertext 275 | * 276 | * \return 0 if the verify operation was successful, 277 | * or an TROPICSSL_ERR_RSA_XXX error code 278 | * 279 | * \note The "sig" buffer must be as large as the size 280 | * of ctx->N (eg. 128 bytes if RSA-1024 is used). 281 | */ 282 | int rsa_pkcs1_verify(rsa_context * ctx, 283 | int mode, 284 | int hash_id, 285 | int hashlen, 286 | const unsigned char *hash, 287 | const unsigned char *sig); 288 | 289 | /** 290 | * \brief Free the components of an RSA key 291 | */ 292 | void rsa_free(rsa_context * ctx); 293 | 294 | /** 295 | * \brief Checkup routine 296 | * 297 | * \return 0 if successful, or 1 if the test failed 298 | */ 299 | int rsa_self_test(int verbose); 300 | 301 | #ifdef __cplusplus 302 | } 303 | #endif 304 | #endif /* rsa.h */ 305 | -------------------------------------------------------------------------------- /lib/tropicssl/include/tropicssl/sha1.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file sha1.h 3 | * 4 | * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine 5 | * 6 | * Copyright (C) 2009 Paul Bakker 7 | * 8 | * All rights reserved. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * * Neither the names of PolarSSL or XySSL nor the names of its contributors 20 | * may be used to endorse or promote products derived from this software 21 | * without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | */ 35 | #ifndef TROPICSSL_SHA1_H 36 | #define TROPICSSL_SHA1_H 37 | 38 | /** 39 | * \brief SHA-1 context structure 40 | */ 41 | typedef struct { 42 | unsigned long total[2]; /*!< number of bytes processed */ 43 | unsigned long state[5]; /*!< intermediate digest state */ 44 | unsigned char buffer[64]; /*!< data block being processed */ 45 | 46 | unsigned char ipad[64]; /*!< HMAC: inner padding */ 47 | unsigned char opad[64]; /*!< HMAC: outer padding */ 48 | } sha1_context; 49 | 50 | #ifdef __cplusplus 51 | extern "C" { 52 | #endif 53 | 54 | /** 55 | * \brief SHA-1 context setup 56 | * 57 | * \param ctx context to be initialized 58 | */ 59 | void sha1_starts(sha1_context * ctx); 60 | 61 | /** 62 | * \brief SHA-1 process buffer 63 | * 64 | * \param ctx SHA-1 context 65 | * \param input buffer holding the data 66 | * \param ilen length of the input data 67 | */ 68 | void sha1_update(sha1_context * ctx, const unsigned char *input, int ilen); 69 | 70 | /** 71 | * \brief SHA-1 final digest 72 | * 73 | * \param ctx SHA-1 context 74 | * \param output SHA-1 checksum result 75 | */ 76 | void sha1_finish(sha1_context * ctx, unsigned char output[20]); 77 | 78 | /** 79 | * \brief Output = SHA-1( input buffer ) 80 | * 81 | * \param input buffer holding the data 82 | * \param ilen length of the input data 83 | * \param output SHA-1 checksum result 84 | */ 85 | void sha1(const unsigned char *input, int ilen, unsigned char output[20]); 86 | 87 | /** 88 | * \brief Output = SHA-1( file contents ) 89 | * 90 | * \param path input file name 91 | * \param output SHA-1 checksum result 92 | * 93 | * \return 0 if successful, 1 if fopen failed, 94 | * or 2 if fread failed 95 | */ 96 | int sha1_file(const char *path, unsigned char output[20]); 97 | 98 | /** 99 | * \brief SHA-1 HMAC context setup 100 | * 101 | * \param ctx HMAC context to be initialized 102 | * \param key HMAC secret key 103 | * \param keylen length of the HMAC key 104 | */ 105 | void sha1_hmac_starts(sha1_context * ctx, const unsigned char *key, 106 | int keylen); 107 | 108 | /** 109 | * \brief SHA-1 HMAC process buffer 110 | * 111 | * \param ctx HMAC context 112 | * \param input buffer holding the data 113 | * \param ilen length of the input data 114 | */ 115 | void sha1_hmac_update(sha1_context * ctx, const unsigned char *input, 116 | int ilen); 117 | 118 | /** 119 | * \brief SHA-1 HMAC final digest 120 | * 121 | * \param ctx HMAC context 122 | * \param output SHA-1 HMAC checksum result 123 | */ 124 | void sha1_hmac_finish(sha1_context * ctx, unsigned char output[20]); 125 | 126 | /** 127 | * \brief Output = HMAC-SHA-1( hmac key, input buffer ) 128 | * 129 | * \param key HMAC secret key 130 | * \param keylen length of the HMAC key 131 | * \param input buffer holding the data 132 | * \param ilen length of the input data 133 | * \param output HMAC-SHA-1 result 134 | */ 135 | void sha1_hmac(const unsigned char *key, int keylen, 136 | const unsigned char *input, int ilen, 137 | unsigned char output[20]); 138 | 139 | /** 140 | * \brief Checkup routine 141 | * 142 | * \return 0 if successful, or 1 if the test failed 143 | */ 144 | int sha1_self_test(int verbose); 145 | 146 | #ifdef __cplusplus 147 | } 148 | #endif 149 | #endif /* sha1.h */ 150 | -------------------------------------------------------------------------------- /lib/tropicssl/library/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Also see "include/tropicssl/config.h" 3 | 4 | # Suggested value for TROPICSSL_CFLAGS_EXTRA_WARNINGS to pass 5 | # on the command line, for gcc (GCC) 4.4.6 20120305 6 | # (Red Hat 4.4.6-4): 7 | # 8 | # make all 'TROPICSSL_CFLAGS_EXTRA_WARNINGS= -Wextra -Wformat=2 9 | # -fstrict-aliasing -Wstrict-aliasing -Wfloat-equal 10 | # -Wundef -Wpointer-arith -Wbad-function-cast 11 | # -Wcast-qual -Wcast-align -Wwrite-strings -Waddress 12 | # -Waggregate-return -Wstrict-prototypes 13 | # -Wold-style-declaration -Wold-style-definition 14 | # -Wmissing-parameter-type -Wmissing-prototypes 15 | # -Wmissing-declarations -Wmissing-field-initializers 16 | # -Wmissing-noreturn -Wmissing-format-attribute -Wpacked 17 | # -Wredundant-decls -Wnested-externs' 18 | # 19 | 20 | CFLAGS = -I../include -D_FILE_OFFSET_BITS=64 -Wall $(TROPICSSL_CFLAGS_EXTRA_WARNINGS) 21 | OFLAGS = -Os 22 | 23 | ifndef TROPICSSL_CFLAGS_NO_WARNINGS_AS_ERRORS 24 | CFLAGS += -Werror 25 | endif # TROPICSSL_CFLAGS_NO_WARNINGS_AS_ERRORS 26 | 27 | # MicroBlaze specific options: 28 | # CFLAGS += -mno-xl-soft-mul -mxl-barrel-shift 29 | 30 | # To compile on Plan9: 31 | # CFLAGS += -D_BSD_EXTENSION 32 | 33 | # To compile as a shared library: 34 | ifdef TROPICSSL_SHARED 35 | CFLAGS += -fPIC 36 | endif # TROPICSSL_SHARED 37 | 38 | DLEXT=so 39 | # OSX shared library extension: 40 | # DLEXT=dylib 41 | 42 | # OBJS= aes.o arc4.o base64.o \ 43 | # bignum.o certs.o debug.o \ 44 | # des.o dhm.o havege.o \ 45 | # md2.o md4.o md5.o \ 46 | # net.o padlock.o rsa.o \ 47 | # sha1.o sha2.o sha4.o \ 48 | # ssl_cli.o ssl_srv.o ssl_tls.o \ 49 | # timing.o x509parse.o xtea.o \ 50 | # camellia.o 51 | OBJS = aes.o bignum.o padlock.o rsa.o sha1.o 52 | 53 | .PHONY: all 54 | 55 | ifdef TROPICSSL_SHARED 56 | all: shared 57 | else # TROPICSSL_SHARED 58 | all: static 59 | endif # TROPICSSL_SHARED 60 | 61 | .PHONY: static 62 | 63 | static: libtropicssl.a 64 | 65 | .PHONY: shared 66 | 67 | shared: libtropicssl.$(DLEXT) 68 | 69 | libtropicssl.a: $(OBJS) 70 | @echo " AR $@" 71 | $(AR) r $@ $(OBJS) 72 | @echo " RL $@" 73 | ranlib $@ 74 | 75 | libtropicssl.so: libtropicssl.a 76 | @echo " LD $@" 77 | $(CC) -shared -Wl,-soname,$@ -o $@ $(OBJS) 78 | 79 | libtropicssl.dylib: libtropicssl.a 80 | @echo " LD $@" 81 | $(CC) -dynamiclib -o $@ $(OBJS) 82 | 83 | .c.o: 84 | @echo " CC $<" 85 | $(CC) $(CFLAGS) $(OFLAGS) -c $< 86 | 87 | .PHONY: clean 88 | 89 | clean: 90 | rm -f *.o libtropicssl.* 91 | 92 | -------------------------------------------------------------------------------- /lib/tropicssl/library/build.mk: -------------------------------------------------------------------------------- 1 | # This file is a makefile included from the top level makefile which 2 | # defines the sources built for the target. 3 | 4 | # Define the prefix to this directory. 5 | # Note: The name must be unique within this build and should be 6 | # based on the root of the project 7 | TARGET_LIB_TROPICSSL_PATH = lib/tropicssl 8 | TARGET_LIB_TROPICSSL_LIB_PATH = $(TARGET_LIB_TROPICSSL_PATH)/library 9 | 10 | # Add tropicssl include to all objects built for this target 11 | INCLUDE_DIRS += $(TARGET_LIB_TROPICSSL_PATH)/include 12 | 13 | # C source files included in this build. 14 | CSRC += $(TARGET_LIB_TROPICSSL_LIB_PATH)/aes.c 15 | CSRC += $(TARGET_LIB_TROPICSSL_LIB_PATH)/bignum.c 16 | CSRC += $(TARGET_LIB_TROPICSSL_LIB_PATH)/padlock.c 17 | CSRC += $(TARGET_LIB_TROPICSSL_LIB_PATH)/rsa.c 18 | CSRC += $(TARGET_LIB_TROPICSSL_LIB_PATH)/sha1.c 19 | 20 | # C++ source files included in this build. 21 | CPPSRC += 22 | 23 | # ASM source files included in this build. 24 | ASRC += 25 | 26 | -------------------------------------------------------------------------------- /lib/tropicssl/library/padlock.c: -------------------------------------------------------------------------------- 1 | /* 2 | * VIA PadLock support functions 3 | * 4 | * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine 5 | * 6 | * Copyright (C) 2009 Paul Bakker 7 | * 8 | * All rights reserved. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * * Neither the names of PolarSSL or XySSL nor the names of its contributors 20 | * may be used to endorse or promote products derived from this software 21 | * without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | */ 35 | /* 36 | * This implementation is based on the VIA PadLock Programming Guide: 37 | * 38 | * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/ 39 | * programming_guide.pdf 40 | */ 41 | 42 | #include "tropicssl/config.h" 43 | 44 | #if defined(TROPICSSL_PADLOCK_C) 45 | 46 | #include "tropicssl/aes.h" 47 | #include "tropicssl/padlock.h" 48 | 49 | #if defined(TROPICSSL_HAVE_X86) 50 | 51 | #include 52 | 53 | /* 54 | * PadLock detection routine 55 | */ 56 | int padlock_supports(int feature) 57 | { 58 | static int flags = -1; 59 | int ebx, edx; 60 | 61 | if (flags == -1) { 62 | asm("movl %%ebx, %0 \n" "movl $0xC0000000, %%eax \n" "cpuid \n" "cmpl $0xC0000001, %%eax \n" "movl $0, %%edx \n" "jb unsupported \n" "movl $0xC0000001, %%eax \n" "cpuid \n" "unsupported: \n" "movl %%edx, %1 \n" "movl %2, %%ebx \n":"=m"(ebx), 63 | "=m" 64 | (edx) 65 | : "m"(ebx) 66 | : "eax", "ecx", "edx"); 67 | 68 | flags = edx; 69 | } 70 | 71 | return (flags & feature); 72 | } 73 | 74 | /* 75 | * PadLock AES-ECB block en(de)cryption 76 | */ 77 | int padlock_xcryptecb(aes_context * ctx, 78 | int mode, 79 | const unsigned char input[16], 80 | unsigned char output[16]) 81 | { 82 | int ebx; 83 | unsigned long *rk; 84 | unsigned long *blk; 85 | unsigned long *ctrl; 86 | unsigned char buf[256]; 87 | 88 | rk = ctx->rk; 89 | blk = PADLOCK_ALIGN16(buf); 90 | memcpy(blk, input, 16); 91 | 92 | ctrl = blk + 4; 93 | *ctrl = 0x80 | ctx->nr | ((ctx->nr + (mode ^ 1) - 10) << 9); 94 | 95 | asm("pushfl; popfl \n" "movl %%ebx, %0 \n" "movl $1, %%ecx \n" "movl %2, %%edx \n" "movl %3, %%ebx \n" "movl %4, %%esi \n" "movl %4, %%edi \n" ".byte 0xf3,0x0f,0xa7,0xc8\n" "movl %1, %%ebx \n":"=m"(ebx) 96 | : "m"(ebx), "m"(ctrl), "m"(rk), "m"(blk) 97 | : "ecx", "edx", "esi", "edi"); 98 | 99 | memcpy(output, blk, 16); 100 | 101 | return (0); 102 | } 103 | 104 | /* 105 | * PadLock AES-CBC buffer en(de)cryption 106 | */ 107 | int padlock_xcryptcbc(aes_context * ctx, 108 | int mode, 109 | int length, 110 | unsigned char iv[16], 111 | const unsigned char *input, 112 | unsigned char *output) 113 | { 114 | int ebx, count; 115 | unsigned long *rk; 116 | unsigned long *iw; 117 | unsigned long *ctrl; 118 | unsigned char buf[256]; 119 | 120 | if (((long)input & 15) != 0 || ((long)output & 15) != 0) 121 | return (1); 122 | 123 | rk = ctx->rk; 124 | iw = PADLOCK_ALIGN16(buf); 125 | memcpy(iw, iv, 16); 126 | 127 | ctrl = iw + 4; 128 | *ctrl = 0x80 | ctx->nr | ((ctx->nr + (mode ^ 1) - 10) << 9); 129 | 130 | count = (length + 15) >> 4; 131 | 132 | asm("pushfl; popfl \n" "movl %%ebx, %0 \n" "movl %2, %%ecx \n" "movl %3, %%edx \n" "movl %4, %%ebx \n" "movl %5, %%esi \n" "movl %6, %%edi \n" "movl %7, %%eax \n" ".byte 0xf3,0x0f,0xa7,0xd0\n" "movl %1, %%ebx \n":"=m"(ebx) 133 | : "m"(ebx), "m"(count), "m"(ctrl), 134 | "m"(rk), "m"(input), "m"(output), "m"(iw) 135 | : "eax", "ecx", "edx", "esi", "edi"); 136 | 137 | memcpy(iv, iw, 16); 138 | 139 | return (0); 140 | } 141 | 142 | #endif 143 | 144 | #endif 145 | -------------------------------------------------------------------------------- /lib/tropicssl/library/sha1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * FIPS-180-1 compliant SHA-1 implementation 3 | * 4 | * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine 5 | * 6 | * Copyright (C) 2009 Paul Bakker 7 | * 8 | * All rights reserved. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * * Neither the names of PolarSSL or XySSL nor the names of its contributors 20 | * may be used to endorse or promote products derived from this software 21 | * without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | */ 35 | /* 36 | * The SHA-1 standard was published by NIST in 1993. 37 | * 38 | * http://www.itl.nist.gov/fipspubs/fip180-1.htm 39 | */ 40 | 41 | #include "tropicssl/config.h" 42 | 43 | #if defined(TROPICSSL_SHA1_C) 44 | 45 | #include "tropicssl/sha1.h" 46 | 47 | #include 48 | #include 49 | 50 | /* 51 | * 32-bit integer manipulation macros (big endian) 52 | */ 53 | #ifndef GET_ULONG_BE 54 | #define GET_ULONG_BE(n,b,i) \ 55 | { \ 56 | (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ 57 | | ( (unsigned long) (b)[(i) + 1] << 16 ) \ 58 | | ( (unsigned long) (b)[(i) + 2] << 8 ) \ 59 | | ( (unsigned long) (b)[(i) + 3] ); \ 60 | } 61 | #endif 62 | 63 | #ifndef PUT_ULONG_BE 64 | #define PUT_ULONG_BE(n,b,i) \ 65 | { \ 66 | (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ 67 | (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ 68 | (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ 69 | (b)[(i) + 3] = (unsigned char) ( (n) ); \ 70 | } 71 | #endif 72 | 73 | /* 74 | * SHA-1 context setup 75 | */ 76 | void sha1_starts(sha1_context * ctx) 77 | { 78 | ctx->total[0] = 0; 79 | ctx->total[1] = 0; 80 | 81 | ctx->state[0] = 0x67452301; 82 | ctx->state[1] = 0xEFCDAB89; 83 | ctx->state[2] = 0x98BADCFE; 84 | ctx->state[3] = 0x10325476; 85 | ctx->state[4] = 0xC3D2E1F0; 86 | } 87 | 88 | static void sha1_process(sha1_context * ctx, const unsigned char data[64]) 89 | { 90 | unsigned long temp, W[16], A, B, C, D, E; 91 | 92 | GET_ULONG_BE(W[0], data, 0); 93 | GET_ULONG_BE(W[1], data, 4); 94 | GET_ULONG_BE(W[2], data, 8); 95 | GET_ULONG_BE(W[3], data, 12); 96 | GET_ULONG_BE(W[4], data, 16); 97 | GET_ULONG_BE(W[5], data, 20); 98 | GET_ULONG_BE(W[6], data, 24); 99 | GET_ULONG_BE(W[7], data, 28); 100 | GET_ULONG_BE(W[8], data, 32); 101 | GET_ULONG_BE(W[9], data, 36); 102 | GET_ULONG_BE(W[10], data, 40); 103 | GET_ULONG_BE(W[11], data, 44); 104 | GET_ULONG_BE(W[12], data, 48); 105 | GET_ULONG_BE(W[13], data, 52); 106 | GET_ULONG_BE(W[14], data, 56); 107 | GET_ULONG_BE(W[15], data, 60); 108 | 109 | #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) 110 | 111 | #define R(t) \ 112 | ( \ 113 | temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ 114 | W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ 115 | ( W[t & 0x0F] = S(temp,1) ) \ 116 | ) 117 | 118 | #define P(a,b,c,d,e,x) \ 119 | { \ 120 | e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ 121 | } 122 | 123 | A = ctx->state[0]; 124 | B = ctx->state[1]; 125 | C = ctx->state[2]; 126 | D = ctx->state[3]; 127 | E = ctx->state[4]; 128 | 129 | #define F(x,y,z) (z ^ (x & (y ^ z))) 130 | #define K 0x5A827999 131 | 132 | P(A, B, C, D, E, W[0]); 133 | P(E, A, B, C, D, W[1]); 134 | P(D, E, A, B, C, W[2]); 135 | P(C, D, E, A, B, W[3]); 136 | P(B, C, D, E, A, W[4]); 137 | P(A, B, C, D, E, W[5]); 138 | P(E, A, B, C, D, W[6]); 139 | P(D, E, A, B, C, W[7]); 140 | P(C, D, E, A, B, W[8]); 141 | P(B, C, D, E, A, W[9]); 142 | P(A, B, C, D, E, W[10]); 143 | P(E, A, B, C, D, W[11]); 144 | P(D, E, A, B, C, W[12]); 145 | P(C, D, E, A, B, W[13]); 146 | P(B, C, D, E, A, W[14]); 147 | P(A, B, C, D, E, W[15]); 148 | P(E, A, B, C, D, R(16)); 149 | P(D, E, A, B, C, R(17)); 150 | P(C, D, E, A, B, R(18)); 151 | P(B, C, D, E, A, R(19)); 152 | 153 | #undef K 154 | #undef F 155 | 156 | #define F(x,y,z) (x ^ y ^ z) 157 | #define K 0x6ED9EBA1 158 | 159 | P(A, B, C, D, E, R(20)); 160 | P(E, A, B, C, D, R(21)); 161 | P(D, E, A, B, C, R(22)); 162 | P(C, D, E, A, B, R(23)); 163 | P(B, C, D, E, A, R(24)); 164 | P(A, B, C, D, E, R(25)); 165 | P(E, A, B, C, D, R(26)); 166 | P(D, E, A, B, C, R(27)); 167 | P(C, D, E, A, B, R(28)); 168 | P(B, C, D, E, A, R(29)); 169 | P(A, B, C, D, E, R(30)); 170 | P(E, A, B, C, D, R(31)); 171 | P(D, E, A, B, C, R(32)); 172 | P(C, D, E, A, B, R(33)); 173 | P(B, C, D, E, A, R(34)); 174 | P(A, B, C, D, E, R(35)); 175 | P(E, A, B, C, D, R(36)); 176 | P(D, E, A, B, C, R(37)); 177 | P(C, D, E, A, B, R(38)); 178 | P(B, C, D, E, A, R(39)); 179 | 180 | #undef K 181 | #undef F 182 | 183 | #define F(x,y,z) ((x & y) | (z & (x | y))) 184 | #define K 0x8F1BBCDC 185 | 186 | P(A, B, C, D, E, R(40)); 187 | P(E, A, B, C, D, R(41)); 188 | P(D, E, A, B, C, R(42)); 189 | P(C, D, E, A, B, R(43)); 190 | P(B, C, D, E, A, R(44)); 191 | P(A, B, C, D, E, R(45)); 192 | P(E, A, B, C, D, R(46)); 193 | P(D, E, A, B, C, R(47)); 194 | P(C, D, E, A, B, R(48)); 195 | P(B, C, D, E, A, R(49)); 196 | P(A, B, C, D, E, R(50)); 197 | P(E, A, B, C, D, R(51)); 198 | P(D, E, A, B, C, R(52)); 199 | P(C, D, E, A, B, R(53)); 200 | P(B, C, D, E, A, R(54)); 201 | P(A, B, C, D, E, R(55)); 202 | P(E, A, B, C, D, R(56)); 203 | P(D, E, A, B, C, R(57)); 204 | P(C, D, E, A, B, R(58)); 205 | P(B, C, D, E, A, R(59)); 206 | 207 | #undef K 208 | #undef F 209 | 210 | #define F(x,y,z) (x ^ y ^ z) 211 | #define K 0xCA62C1D6 212 | 213 | P(A, B, C, D, E, R(60)); 214 | P(E, A, B, C, D, R(61)); 215 | P(D, E, A, B, C, R(62)); 216 | P(C, D, E, A, B, R(63)); 217 | P(B, C, D, E, A, R(64)); 218 | P(A, B, C, D, E, R(65)); 219 | P(E, A, B, C, D, R(66)); 220 | P(D, E, A, B, C, R(67)); 221 | P(C, D, E, A, B, R(68)); 222 | P(B, C, D, E, A, R(69)); 223 | P(A, B, C, D, E, R(70)); 224 | P(E, A, B, C, D, R(71)); 225 | P(D, E, A, B, C, R(72)); 226 | P(C, D, E, A, B, R(73)); 227 | P(B, C, D, E, A, R(74)); 228 | P(A, B, C, D, E, R(75)); 229 | P(E, A, B, C, D, R(76)); 230 | P(D, E, A, B, C, R(77)); 231 | P(C, D, E, A, B, R(78)); 232 | P(B, C, D, E, A, R(79)); 233 | 234 | #undef K 235 | #undef F 236 | 237 | ctx->state[0] += A; 238 | ctx->state[1] += B; 239 | ctx->state[2] += C; 240 | ctx->state[3] += D; 241 | ctx->state[4] += E; 242 | } 243 | 244 | /* 245 | * SHA-1 process buffer 246 | */ 247 | void sha1_update(sha1_context * ctx, const unsigned char *input, int ilen) 248 | { 249 | int fill; 250 | unsigned long left; 251 | 252 | if (ilen <= 0) 253 | return; 254 | 255 | left = ctx->total[0] & 0x3F; 256 | fill = 64 - left; 257 | 258 | ctx->total[0] += ilen; 259 | ctx->total[0] &= 0xFFFFFFFF; 260 | 261 | if (ctx->total[0] < (unsigned long)ilen) 262 | ctx->total[1]++; 263 | 264 | if (left && ilen >= fill) { 265 | memcpy((void *)(ctx->buffer + left), (const void *)input, fill); 266 | sha1_process(ctx, ctx->buffer); 267 | input += fill; 268 | ilen -= fill; 269 | left = 0; 270 | } 271 | 272 | while (ilen >= 64) { 273 | sha1_process(ctx, input); 274 | input += 64; 275 | ilen -= 64; 276 | } 277 | 278 | if (ilen > 0) { 279 | memcpy((void *)(ctx->buffer + left), (const void *)input, ilen); 280 | } 281 | } 282 | 283 | static const unsigned char sha1_padding[64] = { 284 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 285 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 286 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 288 | }; 289 | 290 | /* 291 | * SHA-1 final digest 292 | */ 293 | void sha1_finish(sha1_context * ctx, unsigned char output[20]) 294 | { 295 | unsigned long last, padn; 296 | unsigned long high, low; 297 | unsigned char msglen[8]; 298 | 299 | high = (ctx->total[0] >> 29) 300 | | (ctx->total[1] << 3); 301 | low = (ctx->total[0] << 3); 302 | 303 | PUT_ULONG_BE(high, msglen, 0); 304 | PUT_ULONG_BE(low, msglen, 4); 305 | 306 | last = ctx->total[0] & 0x3F; 307 | padn = (last < 56) ? (56 - last) : (120 - last); 308 | 309 | sha1_update(ctx, sha1_padding, padn); 310 | sha1_update(ctx, msglen, 8); 311 | 312 | PUT_ULONG_BE(ctx->state[0], output, 0); 313 | PUT_ULONG_BE(ctx->state[1], output, 4); 314 | PUT_ULONG_BE(ctx->state[2], output, 8); 315 | PUT_ULONG_BE(ctx->state[3], output, 12); 316 | PUT_ULONG_BE(ctx->state[4], output, 16); 317 | } 318 | 319 | /* 320 | * output = SHA-1( input buffer ) 321 | */ 322 | void sha1(const unsigned char *input, int ilen, unsigned char output[20]) 323 | { 324 | sha1_context ctx; 325 | 326 | sha1_starts(&ctx); 327 | sha1_update(&ctx, input, ilen); 328 | sha1_finish(&ctx, output); 329 | 330 | memset(&ctx, 0, sizeof(sha1_context)); 331 | } 332 | 333 | /* 334 | * output = SHA-1( file contents ) 335 | */ 336 | int sha1_file(const char *path, unsigned char output[20]) 337 | { 338 | FILE *f; 339 | size_t n; 340 | sha1_context ctx; 341 | unsigned char buf[1024]; 342 | 343 | if ((f = fopen(path, "rb")) == NULL) 344 | return (1); 345 | 346 | sha1_starts(&ctx); 347 | 348 | while ((n = fread(buf, 1, sizeof(buf), f)) > 0) 349 | sha1_update(&ctx, buf, (int)n); 350 | 351 | sha1_finish(&ctx, output); 352 | 353 | memset(&ctx, 0, sizeof(sha1_context)); 354 | 355 | if (ferror(f) != 0) { 356 | fclose(f); 357 | return (2); 358 | } 359 | 360 | fclose(f); 361 | return (0); 362 | } 363 | 364 | /* 365 | * SHA-1 HMAC context setup 366 | */ 367 | void sha1_hmac_starts(sha1_context * ctx, const unsigned char *key, int keylen) 368 | { 369 | int i; 370 | unsigned char sum[20]; 371 | 372 | if (keylen > 64) { 373 | sha1(key, keylen, sum); 374 | keylen = 20; 375 | key = sum; 376 | } 377 | 378 | memset(ctx->ipad, 0x36, 64); 379 | memset(ctx->opad, 0x5C, 64); 380 | 381 | for (i = 0; i < keylen; i++) { 382 | ctx->ipad[i] = (unsigned char)(ctx->ipad[i] ^ key[i]); 383 | ctx->opad[i] = (unsigned char)(ctx->opad[i] ^ key[i]); 384 | } 385 | 386 | sha1_starts(ctx); 387 | sha1_update(ctx, ctx->ipad, 64); 388 | 389 | memset(sum, 0, sizeof(sum)); 390 | } 391 | 392 | /* 393 | * SHA-1 HMAC process buffer 394 | */ 395 | void sha1_hmac_update(sha1_context * ctx, const unsigned char *input, int ilen) 396 | { 397 | sha1_update(ctx, input, ilen); 398 | } 399 | 400 | /* 401 | * SHA-1 HMAC final digest 402 | */ 403 | void sha1_hmac_finish(sha1_context * ctx, unsigned char output[20]) 404 | { 405 | unsigned char tmpbuf[20]; 406 | 407 | sha1_finish(ctx, tmpbuf); 408 | sha1_starts(ctx); 409 | sha1_update(ctx, ctx->opad, 64); 410 | sha1_update(ctx, tmpbuf, 20); 411 | sha1_finish(ctx, output); 412 | 413 | memset(tmpbuf, 0, sizeof(tmpbuf)); 414 | } 415 | 416 | /* 417 | * output = HMAC-SHA-1( hmac key, input buffer ) 418 | */ 419 | void sha1_hmac(const unsigned char *key, int keylen, 420 | const unsigned char *input, int ilen, 421 | unsigned char output[20]) 422 | { 423 | sha1_context ctx; 424 | 425 | sha1_hmac_starts(&ctx, key, keylen); 426 | sha1_hmac_update(&ctx, input, ilen); 427 | sha1_hmac_finish(&ctx, output); 428 | 429 | memset(&ctx, 0, sizeof(sha1_context)); 430 | } 431 | 432 | #if defined(TROPICSSL_SELF_TEST) 433 | /* 434 | * FIPS-180-1 test vectors 435 | */ 436 | static unsigned char sha1_test_buf[3][57] = { 437 | {"abc"}, 438 | {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"}, 439 | {""} 440 | }; 441 | 442 | static const int sha1_test_buflen[3] = { 443 | 3, 56, 1000 444 | }; 445 | 446 | static const unsigned char sha1_test_sum[3][20] = { 447 | { 448 | 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, 449 | 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D}, 450 | { 451 | 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, 452 | 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1}, 453 | { 454 | 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, 455 | 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F} 456 | }; 457 | 458 | /* 459 | * RFC 2202 test vectors 460 | */ 461 | static unsigned char sha1_hmac_test_key[7][26] = { 462 | { 463 | "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" 464 | "\x0B\x0B\x0B\x0B"}, 465 | {"Jefe"}, 466 | { 467 | "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" 468 | "\xAA\xAA\xAA\xAA"}, 469 | { 470 | "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" 471 | "\x11\x12\x13\x14\x15\x16\x17\x18\x19"}, 472 | { 473 | "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" 474 | "\x0C\x0C\x0C\x0C"}, 475 | {""}, /* 0xAA 80 times */ 476 | {""} 477 | }; 478 | 479 | static const int sha1_hmac_test_keylen[7] = { 480 | 20, 4, 20, 25, 20, 80, 80 481 | }; 482 | 483 | static unsigned char sha1_hmac_test_buf[7][74] = { 484 | {"Hi There"}, 485 | {"what do ya want for nothing?"}, 486 | { 487 | "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" 488 | "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" 489 | "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" 490 | "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" 491 | "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"}, 492 | { 493 | "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" 494 | "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" 495 | "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" 496 | "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" 497 | "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"}, 498 | {"Test With Truncation"}, 499 | {"Test Using Larger Than Block-Size Key - Hash Key First"}, 500 | { 501 | "Test Using Larger Than Block-Size Key and Larger" 502 | " Than One Block-Size Data"} 503 | }; 504 | 505 | static const int sha1_hmac_test_buflen[7] = { 506 | 8, 28, 50, 50, 20, 54, 73 507 | }; 508 | 509 | static const unsigned char sha1_hmac_test_sum[7][20] = { 510 | { 511 | 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B, 512 | 0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00}, 513 | { 514 | 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74, 515 | 0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79}, 516 | { 517 | 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3, 518 | 0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3}, 519 | { 520 | 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84, 521 | 0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA}, 522 | { 523 | 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2, 524 | 0x7B, 0xE1}, 525 | { 526 | 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70, 527 | 0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12}, 528 | { 529 | 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B, 530 | 0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91} 531 | }; 532 | 533 | /* 534 | * Checkup routine 535 | */ 536 | int sha1_self_test(int verbose) 537 | { 538 | int i, j, buflen; 539 | unsigned char buf[1024]; 540 | unsigned char sha1sum[20]; 541 | sha1_context ctx; 542 | 543 | /* 544 | * SHA-1 545 | */ 546 | for (i = 0; i < 3; i++) { 547 | if (verbose != 0) 548 | printf(" SHA-1 test #%d: ", i + 1); 549 | 550 | sha1_starts(&ctx); 551 | 552 | if (i == 2) { 553 | memset(buf, 'a', buflen = 1000); 554 | 555 | for (j = 0; j < 1000; j++) 556 | sha1_update(&ctx, buf, buflen); 557 | } else 558 | sha1_update(&ctx, sha1_test_buf[i], 559 | sha1_test_buflen[i]); 560 | 561 | sha1_finish(&ctx, sha1sum); 562 | 563 | if (memcmp(sha1sum, sha1_test_sum[i], 20) != 0) { 564 | if (verbose != 0) 565 | printf("failed\n"); 566 | 567 | return (1); 568 | } 569 | 570 | if (verbose != 0) 571 | printf("passed\n"); 572 | } 573 | 574 | if (verbose != 0) 575 | printf("\n"); 576 | 577 | for (i = 0; i < 7; i++) { 578 | if (verbose != 0) 579 | printf(" HMAC-SHA-1 test #%d: ", i + 1); 580 | 581 | if (i == 5 || i == 6) { 582 | memset(buf, '\xAA', buflen = 80); 583 | sha1_hmac_starts(&ctx, buf, buflen); 584 | } else 585 | sha1_hmac_starts(&ctx, sha1_hmac_test_key[i], 586 | sha1_hmac_test_keylen[i]); 587 | 588 | sha1_hmac_update(&ctx, sha1_hmac_test_buf[i], 589 | sha1_hmac_test_buflen[i]); 590 | 591 | sha1_hmac_finish(&ctx, sha1sum); 592 | 593 | buflen = (i == 4) ? 12 : 20; 594 | 595 | if (memcmp(sha1sum, sha1_hmac_test_sum[i], buflen) != 0) { 596 | if (verbose != 0) 597 | printf("failed\n"); 598 | 599 | return (1); 600 | } 601 | 602 | if (verbose != 0) 603 | printf("passed\n"); 604 | } 605 | 606 | if (verbose != 0) 607 | printf("\n"); 608 | 609 | return (0); 610 | } 611 | 612 | #endif 613 | 614 | #endif 615 | -------------------------------------------------------------------------------- /src/build.mk: -------------------------------------------------------------------------------- 1 | # This file is a makefile included from the top level makefile which 2 | # defines the sources built for the target. 3 | 4 | # Define the prefix to this directory. 5 | # Note: The name must be unique within this build and should be 6 | # based on the root of the project 7 | TARGET_SRC_PATH = src 8 | 9 | # Add tropicssl include to all objects built for this target 10 | INCLUDE_DIRS += $(TARGET_SRC_PATH) 11 | 12 | # C source files included in this build. 13 | CSRC += 14 | 15 | # C++ source files included in this build. 16 | CPPSRC += $(TARGET_SRC_PATH)/coap.cpp 17 | CPPSRC += $(TARGET_SRC_PATH)/handshake.cpp 18 | CPPSRC += $(TARGET_SRC_PATH)/spark_protocol.cpp 19 | CPPSRC += $(TARGET_SRC_PATH)/events.cpp 20 | 21 | # ASM source files included in this build. 22 | ASRC += 23 | 24 | -------------------------------------------------------------------------------- /src/coap.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file coap.cpp 4 | * @authors Zachary Crockett 5 | * @version V1.0.0 6 | * @date 15-Nov-2013 7 | * @brief COAP 8 | ****************************************************************************** 9 | Copyright (c) 2013 Spark Labs, Inc. All rights reserved. 10 | 11 | This program is free software; you can redistribute it and/or 12 | modify it under the terms of the GNU Lesser General Public 13 | License as published by the Free Software Foundation, either 14 | version 3 of the License, or (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public 22 | License along with this program; if not, see . 23 | ****************************************************************************** 24 | */ 25 | #include "coap.h" 26 | 27 | CoAPCode::Enum CoAP::code(const unsigned char *message) 28 | { 29 | switch (message[1]) 30 | { 31 | case 0x00: return CoAPCode::EMPTY; 32 | case 0x01: return CoAPCode::GET; 33 | case 0x02: return CoAPCode::POST; 34 | case 0x03: return CoAPCode::PUT; 35 | case 0x45: return CoAPCode::CONTENT; 36 | default: return CoAPCode::ERROR; 37 | } 38 | } 39 | 40 | CoAPType::Enum CoAP::type(const unsigned char *message) 41 | { 42 | switch (message[0] & 0x30) 43 | { 44 | case 0x00: return CoAPType::CON; 45 | case 0x10: return CoAPType::NON; 46 | default: 47 | case 0x20: return CoAPType::ACK; 48 | case 0x30: return CoAPType::RESET; 49 | } 50 | } 51 | 52 | size_t CoAP::option_decode(unsigned char **option) 53 | { 54 | unsigned char nibble = **option & 0x0f; 55 | size_t option_length; 56 | if (13 > nibble) 57 | { 58 | option_length = nibble; 59 | (*option)++; 60 | } 61 | else if (13 == nibble) 62 | { 63 | (*option)++; 64 | option_length = **option + 13; 65 | (*option)++; 66 | } 67 | else if (14 == nibble) 68 | { 69 | option_length = ((*(*option + 1) << 8) | *(*option + 2)) + 269; 70 | (*option) += 3; 71 | } 72 | else 73 | { 74 | // 15 == nibble, reserved value in CoAP spec 75 | option_length = 0; 76 | } 77 | return option_length; 78 | } 79 | -------------------------------------------------------------------------------- /src/coap.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file coap.h 4 | * @authors Zachary Crockett 5 | * @version V1.0.0 6 | * @date 15-Nov-2013 7 | * @brief COAP 8 | ****************************************************************************** 9 | Copyright (c) 2013 Spark Labs, Inc. All rights reserved. 10 | 11 | This library is free software; you can redistribute it and/or 12 | modify it under the terms of the GNU Lesser General Public 13 | License as published by the Free Software Foundation, either 14 | version 3 of the License, or (at your option) any later version. 15 | 16 | This library is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public 22 | License along with this library; if not, see . 23 | ****************************************************************************** 24 | */ 25 | 26 | #include 27 | 28 | namespace CoAPMessageType { 29 | enum Enum { 30 | HELLO, 31 | DESCRIBE, 32 | FUNCTION_CALL, 33 | VARIABLE_REQUEST, 34 | UPDATE_BEGIN, 35 | UPDATE_DONE, 36 | CHUNK, 37 | EVENT, 38 | KEY_CHANGE, 39 | SIGNAL_START, 40 | SIGNAL_STOP, 41 | TIME, 42 | EMPTY_ACK, 43 | PING, 44 | ERROR 45 | }; 46 | } 47 | 48 | namespace CoAPCode { 49 | enum Enum { 50 | GET, 51 | POST, 52 | PUT, 53 | EMPTY, 54 | CONTENT, 55 | ERROR 56 | }; 57 | } 58 | 59 | namespace CoAPType { 60 | enum Enum { 61 | CON, 62 | NON, 63 | ACK, 64 | RESET 65 | }; 66 | } 67 | 68 | class CoAP 69 | { 70 | public: 71 | static CoAPCode::Enum code(const unsigned char *message); 72 | static CoAPType::Enum type(const unsigned char *message); 73 | static size_t option_decode(unsigned char **option); 74 | }; 75 | -------------------------------------------------------------------------------- /src/events.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file events.cpp 4 | * @authors Zachary Crockett 5 | * @version V1.0.0 6 | * @date 26-Feb-2014 7 | * @brief Internal CoAP event message creation 8 | ****************************************************************************** 9 | Copyright (c) 2014 Spark Labs, Inc. All rights reserved. 10 | 11 | This library is free software; you can redistribute it and/or 12 | modify it under the terms of the GNU Lesser General Public 13 | License as published by the Free Software Foundation, either 14 | version 3 of the License, or (at your option) any later version. 15 | 16 | This library is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public 22 | License along with this library; if not, see . 23 | ****************************************************************************** 24 | */ 25 | #include "events.h" 26 | #include 27 | 28 | size_t event(uint8_t buf[], uint16_t message_id, const char *event_name, 29 | const char *data, int ttl, EventType::Enum event_type) 30 | { 31 | uint8_t *p = buf; 32 | *p++ = 0x50; // non-confirmable, no token 33 | *p++ = 0x02; // code 0.02 POST request 34 | *p++ = message_id >> 8; 35 | *p++ = message_id & 0xff; 36 | *p++ = 0xb1; // one-byte Uri-Path option 37 | *p++ = event_type; 38 | 39 | size_t name_data_len = strnlen(event_name, 63); 40 | p += event_name_uri_path(p, event_name, name_data_len); 41 | 42 | if (60 != ttl) 43 | { 44 | *p++ = 0x33; 45 | *p++ = (ttl >> 16) & 0xff; 46 | *p++ = (ttl >> 8) & 0xff; 47 | *p++ = ttl & 0xff; 48 | } 49 | 50 | if (NULL != data) 51 | { 52 | name_data_len = strnlen(data, 255); 53 | 54 | *p++ = 0xff; 55 | memcpy(p, data, name_data_len); 56 | p += name_data_len; 57 | } 58 | 59 | return p - buf; 60 | } 61 | 62 | // Private, used by two subscription variants below 63 | uint8_t *subscription_prelude(uint8_t buf[], uint16_t message_id, 64 | const char *event_name) 65 | { 66 | uint8_t *p = buf; 67 | *p++ = 0x40; // confirmable, no token 68 | *p++ = 0x01; // code 0.01 GET request 69 | *p++ = message_id >> 8; 70 | *p++ = message_id & 0xff; 71 | *p++ = 0xb1; // one-byte Uri-Path option 72 | *p++ = 'e'; 73 | 74 | if (NULL != event_name) 75 | { 76 | size_t len = strnlen(event_name, 63); 77 | p += event_name_uri_path(p, event_name, len); 78 | } 79 | 80 | return p; 81 | } 82 | 83 | size_t subscription(uint8_t buf[], uint16_t message_id, 84 | const char *event_name, const char *device_id) 85 | { 86 | uint8_t *p = subscription_prelude(buf, message_id, event_name); 87 | 88 | if (NULL != device_id) 89 | { 90 | size_t len = strnlen(device_id, 63); 91 | 92 | *p++ = 0xff; 93 | memcpy(p, device_id, len); 94 | p += len; 95 | } 96 | 97 | return p - buf; 98 | } 99 | 100 | size_t subscription(uint8_t buf[], uint16_t message_id, 101 | const char *event_name, SubscriptionScope::Enum scope) 102 | { 103 | uint8_t *p = subscription_prelude(buf, message_id, event_name); 104 | 105 | switch (scope) 106 | { 107 | case SubscriptionScope::MY_DEVICES: 108 | *p++ = 0x41; // one-byte Uri-Query option 109 | *p++ = 'u'; 110 | break; 111 | case SubscriptionScope::FIREHOSE: 112 | default: 113 | // unfiltered firehose is not allowed 114 | if (NULL == event_name || 0 == *event_name) 115 | { 116 | return -1; 117 | } 118 | } 119 | 120 | return p - buf; 121 | } 122 | 123 | size_t event_name_uri_path(uint8_t buf[], const char *name, size_t name_len) 124 | { 125 | if (0 == name_len) 126 | { 127 | return 0; 128 | } 129 | else if (name_len < 13) 130 | { 131 | buf[0] = name_len; 132 | memcpy(buf + 1, name, name_len); 133 | return name_len + 1; 134 | } 135 | else 136 | { 137 | buf[0] = 0x0d; 138 | buf[1] = name_len - 13; 139 | memcpy(buf + 2, name, name_len); 140 | return name_len + 2; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/events.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file events.h 4 | * @authors Zachary Crockett 5 | * @version V1.0.0 6 | * @date 26-Feb-2014 7 | * @brief Internal CoAP event message creation 8 | ****************************************************************************** 9 | Copyright (c) 2014 Spark Labs, Inc. All rights reserved. 10 | 11 | This library is free software; you can redistribute it and/or 12 | modify it under the terms of the GNU Lesser General Public 13 | License as published by the Free Software Foundation, either 14 | version 3 of the License, or (at your option) any later version. 15 | 16 | This library is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public 22 | License along with this library; if not, see . 23 | ****************************************************************************** 24 | */ 25 | #ifndef __EVENTS_H 26 | #define __EVENTS_H 27 | 28 | #include 29 | #include 30 | 31 | namespace EventType { 32 | enum Enum { 33 | PUBLIC = 'e', 34 | PRIVATE = 'E' 35 | }; 36 | } 37 | 38 | namespace SubscriptionScope { 39 | enum Enum { 40 | MY_DEVICES, 41 | FIREHOSE 42 | }; 43 | } 44 | 45 | typedef void (*EventHandler)(const char *event_name, const char *data); 46 | 47 | struct FilteringEventHandler 48 | { 49 | char filter[64]; 50 | EventHandler handler; 51 | }; 52 | 53 | size_t event(uint8_t buf[], uint16_t message_id, const char *event_name, 54 | const char *data, int ttl, EventType::Enum event_type); 55 | 56 | size_t subscription(uint8_t buf[], uint16_t message_id, 57 | const char *event_name, const char *device_id); 58 | 59 | size_t subscription(uint8_t buf[], uint16_t message_id, 60 | const char *event_name, SubscriptionScope::Enum scope); 61 | 62 | size_t event_name_uri_path(uint8_t buf[], const char *name, size_t name_len); 63 | 64 | #endif // __EVENTS_H 65 | -------------------------------------------------------------------------------- /src/handshake.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file handshake.cpp 4 | * @authors Zachary Crockett 5 | * @version V1.0.0 6 | * @date 15-Nov-2013 7 | * @brief HANDSHAKE 8 | ****************************************************************************** 9 | Copyright (c) 2013 Spark Labs, Inc. All rights reserved. 10 | 11 | This program is free software; you can redistribute it and/or 12 | modify it under the terms of the GNU Lesser General Public 13 | License as published by the Free Software Foundation, either 14 | version 3 of the License, or (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public 22 | License along with this program; if not, see . 23 | ****************************************************************************** 24 | */ 25 | #include "handshake.h" 26 | 27 | int ciphertext_from_nonce_and_id(const unsigned char *nonce, 28 | const unsigned char *id, 29 | const unsigned char *pubkey, 30 | unsigned char *ciphertext) 31 | { 32 | unsigned char plaintext[52]; 33 | 34 | memcpy(plaintext, nonce, 40); 35 | memcpy(plaintext + 40, id, 12); 36 | 37 | rsa_context rsa; 38 | init_rsa_context_with_public_key(&rsa, pubkey); 39 | 40 | int ret = rsa_pkcs1_encrypt(&rsa, RSA_PUBLIC, 52, plaintext, ciphertext); 41 | rsa_free(&rsa); 42 | return ret; 43 | } 44 | 45 | int decipher_aes_credentials(const unsigned char *private_key, 46 | const unsigned char *ciphertext, 47 | unsigned char *aes_credentials) 48 | { 49 | rsa_context rsa; 50 | init_rsa_context_with_private_key(&rsa, private_key); 51 | 52 | int len = 128; 53 | int ret = rsa_pkcs1_decrypt(&rsa, RSA_PRIVATE, &len, ciphertext, 54 | aes_credentials, 40); 55 | rsa_free(&rsa); 56 | return ret; 57 | } 58 | 59 | void calculate_ciphertext_hmac(const unsigned char *ciphertext, 60 | const unsigned char *hmac_key, 61 | unsigned char *hmac) 62 | { 63 | sha1_hmac(hmac_key, 40, ciphertext, 128, hmac); 64 | } 65 | 66 | int verify_signature(const unsigned char *signature, 67 | const unsigned char *pubkey, 68 | const unsigned char *expected_hmac) 69 | { 70 | rsa_context rsa; 71 | init_rsa_context_with_public_key(&rsa, pubkey); 72 | 73 | int ret = rsa_pkcs1_verify(&rsa, RSA_PUBLIC, RSA_RAW, 20, 74 | expected_hmac, signature); 75 | rsa_free(&rsa); 76 | return ret; 77 | } 78 | 79 | void init_rsa_context_with_public_key(rsa_context *rsa, 80 | const unsigned char *pubkey) 81 | { 82 | rsa_init(rsa, RSA_PKCS_V15, RSA_RAW, NULL, NULL); 83 | 84 | rsa->len = 256; 85 | mpi_read_binary(&rsa->N, pubkey + 33, 256); 86 | mpi_read_string(&rsa->E, 16, "10001"); 87 | } 88 | 89 | /* Very simple ASN.1 parsing. 90 | * Mainly needed because, even though all the RSA big integers 91 | * are always a specific number of bytes, the key generation 92 | * and encoding process sometimes pads each number with a 93 | * leading zero byte. 94 | */ 95 | void init_rsa_context_with_private_key(rsa_context *rsa, 96 | const unsigned char *private_key) 97 | { 98 | rsa_init(rsa, RSA_PKCS_V15, RSA_RAW, NULL, NULL); 99 | 100 | rsa->len = 128; 101 | 102 | int i = 9; 103 | if (private_key[i] & 1) 104 | { 105 | // key contains an extra zero byte 106 | ++i; 107 | } 108 | ++i; 109 | 110 | mpi_read_binary(&rsa->N, private_key + i, 128); 111 | mpi_read_string(&rsa->E, 16, "10001"); 112 | 113 | i = i + 135; 114 | if (private_key[i] & 1) 115 | { 116 | // key contains an extra zero byte 117 | ++i; 118 | } 119 | ++i; 120 | 121 | mpi_read_binary(&rsa->D, private_key + i, 128); 122 | 123 | i = i + 129; 124 | if (private_key[i] & 1) 125 | { 126 | // key contains an extra zero byte 127 | ++i; 128 | } 129 | ++i; 130 | 131 | mpi_read_binary(&rsa->P, private_key + i, 64); 132 | 133 | i = i + 65; 134 | if (private_key[i] & 1) 135 | { 136 | // key contains an extra zero byte 137 | ++i; 138 | } 139 | ++i; 140 | 141 | mpi_read_binary(&rsa->Q, private_key + i, 64); 142 | 143 | i = i + 65; 144 | if (private_key[i] & 1) 145 | { 146 | // key contains an extra zero byte 147 | ++i; 148 | } 149 | ++i; 150 | 151 | mpi_read_binary(&rsa->DP, private_key + i, 64); 152 | 153 | i = i + 65; 154 | if (private_key[i] & 1) 155 | { 156 | // key contains an extra zero byte 157 | ++i; 158 | } 159 | ++i; 160 | 161 | mpi_read_binary(&rsa->DQ, private_key + i, 64); 162 | 163 | i = i + 65; 164 | if (private_key[i] & 1) 165 | { 166 | // key contains an extra zero byte 167 | ++i; 168 | } 169 | ++i; 170 | 171 | mpi_read_binary(&rsa->QP, private_key + i, 64); 172 | } 173 | -------------------------------------------------------------------------------- /src/handshake.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file handshake.h 4 | * @authors Zachary Crockett 5 | * @version V1.0.0 6 | * @date 15-Nov-2013 7 | * @brief HANDSHAKE 8 | ****************************************************************************** 9 | Copyright (c) 2013 Spark Labs, Inc. All rights reserved. 10 | 11 | This library is free software; you can redistribute it and/or 12 | modify it under the terms of the GNU Lesser General Public 13 | License as published by the Free Software Foundation, either 14 | version 3 of the License, or (at your option) any later version. 15 | 16 | This library is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public 22 | License along with this library; if not, see . 23 | ****************************************************************************** 24 | */ 25 | #include "tropicssl/rsa.h" 26 | #include "tropicssl/sha1.h" 27 | #include 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | int ciphertext_from_nonce_and_id(const unsigned char *nonce, 34 | const unsigned char *id, 35 | const unsigned char *pubkey, 36 | unsigned char *ciphertext); 37 | 38 | int decipher_aes_credentials(const unsigned char *private_key, 39 | const unsigned char *ciphertext, 40 | unsigned char *aes_credentials); 41 | 42 | void calculate_ciphertext_hmac(const unsigned char *ciphertext, 43 | const unsigned char *hmac_key, 44 | unsigned char *hmac); 45 | 46 | int verify_signature(const unsigned char *signature, 47 | const unsigned char *pubkey, 48 | const unsigned char *expected_hmac); 49 | 50 | void init_rsa_context_with_public_key(rsa_context *rsa, 51 | const unsigned char *pubkey); 52 | 53 | void init_rsa_context_with_private_key(rsa_context *rsa, 54 | const unsigned char *private_key); 55 | 56 | #ifdef __cplusplus 57 | } 58 | #endif 59 | 60 | -------------------------------------------------------------------------------- /src/spark_descriptor.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file spark_descriptor.h 4 | * @authors Zachary Crockett 5 | * @version V1.0.0 6 | * @date 15-Nov-2013 7 | * @brief SPARK DESCRIPTOR 8 | ****************************************************************************** 9 | Copyright (c) 2013 Spark Labs, Inc. All rights reserved. 10 | 11 | This library is free software; you can redistribute it and/or 12 | modify it under the terms of the GNU Lesser General Public 13 | License as published by the Free Software Foundation, either 14 | version 3 of the License, or (at your option) any later version. 15 | 16 | This library is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public 22 | License along with this library; if not, see . 23 | ****************************************************************************** 24 | */ 25 | 26 | // Deferring to ASN.1 type codes 27 | namespace SparkReturnType { 28 | enum Enum { 29 | BOOLEAN = 1, 30 | INT = 2, 31 | STRING = 4, 32 | DOUBLE = 9 33 | }; 34 | } 35 | 36 | struct SparkDescriptor 37 | { 38 | int (*num_functions)(void); 39 | void (*copy_function_key)(char *destination, int function_index); 40 | int (*call_function)(const char *function_key, const char *arg); 41 | 42 | int (*num_variables)(void); 43 | void (*copy_variable_key)(char *destination, int variable_index); 44 | SparkReturnType::Enum (*variable_type)(const char *variable_key); 45 | void *(*get_variable)(const char *variable_key); 46 | 47 | bool (*was_ota_upgrade_successful)(void); 48 | void (*ota_upgrade_status_sent)(void); 49 | }; 50 | -------------------------------------------------------------------------------- /src/spark_protocol.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file spark_protocol.h 4 | * @authors Zachary Crockett 5 | * @version V1.0.0 6 | * @date 15-Nov-2013 7 | * @brief SPARK PROTOCOL 8 | ****************************************************************************** 9 | Copyright (c) 2013 Spark Labs, Inc. All rights reserved. 10 | 11 | This library is free software; you can redistribute it and/or 12 | modify it under the terms of the GNU Lesser General Public 13 | License as published by the Free Software Foundation, either 14 | version 3 of the License, or (at your option) any later version. 15 | 16 | This library is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public 22 | License along with this library; if not, see . 23 | ****************************************************************************** 24 | */ 25 | 26 | #ifndef __SPARK_PROTOCOL_H 27 | #define __SPARK_PROTOCOL_H 28 | 29 | #include 30 | #include "spark_descriptor.h" 31 | #include "coap.h" 32 | #include "events.h" 33 | #include "tropicssl/rsa.h" 34 | #include "tropicssl/aes.h" 35 | 36 | #if !defined(arraySize) 37 | # define arraySize(a) (sizeof((a))/sizeof((a[0]))) 38 | #endif 39 | 40 | typedef unsigned long system_tick_t; // This needs to match the definition of millis 41 | 42 | namespace ProtocolState { 43 | enum Enum { 44 | READ_NONCE 45 | }; 46 | } 47 | 48 | namespace ChunkReceivedCode { 49 | enum Enum { 50 | OK = 0x44, 51 | BAD = 0x80 52 | }; 53 | } 54 | 55 | struct SparkKeys 56 | { 57 | unsigned char *core_private; 58 | unsigned char *server_public; 59 | }; 60 | 61 | struct SparkCallbacks 62 | { 63 | int (*send)(const unsigned char *buf, int buflen); 64 | int (*receive)(unsigned char *buf, int buflen); 65 | void (*prepare_for_firmware_update)(void); 66 | void (*finish_firmware_update)(void); 67 | long unsigned int (*calculate_crc)(unsigned char *buf, long unsigned int buflen); 68 | unsigned short (*save_firmware_chunk)(unsigned char *buf, long unsigned int buflen); 69 | void (*signal)(bool on); 70 | system_tick_t (*millis)(); 71 | void (*set_time)(time_t t); 72 | }; 73 | 74 | class SparkProtocol 75 | { 76 | public: 77 | static const int MAX_FUNCTION_ARG_LENGTH = 64; 78 | static const int MAX_FUNCTION_KEY_LENGTH = 12; 79 | static const int MAX_VARIABLE_KEY_LENGTH = 12; 80 | static const int MAX_EVENT_NAME_LENGTH = 64; 81 | static const int MAX_EVENT_DATA_LENGTH = 64; 82 | static const int MAX_EVENT_TTL_SECONDS = 16777215; 83 | static int presence_announcement(unsigned char *buf, const char *id); 84 | 85 | SparkProtocol(); 86 | 87 | void init(const char *id, 88 | const SparkKeys &keys, 89 | const SparkCallbacks &callbacks, 90 | const SparkDescriptor &descriptor); 91 | int handshake(void); 92 | bool event_loop(void); 93 | bool is_initialized(void); 94 | void reset_updating(void); 95 | 96 | int set_key(const unsigned char *signed_encrypted_credentials); 97 | int blocking_send(const unsigned char *buf, int length); 98 | int blocking_receive(unsigned char *buf, int length); 99 | 100 | CoAPMessageType::Enum received_message(unsigned char *buf, int length); 101 | void hello(unsigned char *buf, bool newly_upgraded); 102 | void key_changed(unsigned char *buf, unsigned char token); 103 | void function_return(unsigned char *buf, unsigned char token, 104 | int return_value); 105 | void variable_value(unsigned char *buf, unsigned char token, 106 | unsigned char message_id_msb, unsigned char message_id_lsb, 107 | bool return_value); 108 | void variable_value(unsigned char *buf, unsigned char token, 109 | unsigned char message_id_msb, unsigned char message_id_lsb, 110 | int return_value); 111 | void variable_value(unsigned char *buf, unsigned char token, 112 | unsigned char message_id_msb, unsigned char message_id_lsb, 113 | double return_value); 114 | int variable_value(unsigned char *buf, unsigned char token, 115 | unsigned char message_id_msb, unsigned char message_id_lsb, 116 | const void *return_value, int length); 117 | bool send_event(const char *event_name, const char *data, 118 | int ttl, EventType::Enum event_type); 119 | bool send_subscription(const char *event_name, const char *device_id); 120 | bool send_subscription(const char *event_name, SubscriptionScope::Enum scope); 121 | bool add_event_handler(const char *event_name, EventHandler handler); 122 | size_t time_request(unsigned char *buf); 123 | bool send_time_request(void); 124 | void chunk_received(unsigned char *buf, unsigned char token, 125 | ChunkReceivedCode::Enum code); 126 | void chunk_missed(unsigned char *buf, unsigned short chunk_index); 127 | void update_ready(unsigned char *buf, unsigned char token); 128 | int description(unsigned char *buf, unsigned char token, 129 | unsigned char message_id_msb, unsigned char message_id_lsb); 130 | void ping(unsigned char *buf); 131 | 132 | /********** Queue **********/ 133 | const int QUEUE_SIZE; 134 | int queue_bytes_available(); 135 | int queue_push(const char *src, int length); 136 | int queue_pop(char *dst, int length); 137 | 138 | /********** State Machine **********/ 139 | ProtocolState::Enum state(); 140 | 141 | private: 142 | char device_id[12]; 143 | unsigned char server_public_key[294]; 144 | unsigned char core_private_key[612]; 145 | aes_context aes; 146 | 147 | int (*callback_send)(const unsigned char *buf, int buflen); 148 | int (*callback_receive)(unsigned char *buf, int buflen); 149 | void (*callback_prepare_for_firmware_update)(void); 150 | void (*callback_finish_firmware_update)(void); 151 | long unsigned int (*callback_calculate_crc)(unsigned char *buf, long unsigned int buflen); 152 | unsigned short (*callback_save_firmware_chunk)(unsigned char *buf, long unsigned int buflen); 153 | void (*callback_signal)(bool on); 154 | system_tick_t (*callback_millis)(); 155 | void (*callback_set_time)(time_t t); 156 | FilteringEventHandler event_handlers[4]; 157 | 158 | SparkDescriptor descriptor; 159 | 160 | unsigned char key[16]; 161 | unsigned char iv_send[16]; 162 | unsigned char iv_receive[16]; 163 | unsigned char salt[8]; 164 | unsigned short _message_id; 165 | unsigned char _token; 166 | system_tick_t last_message_millis; 167 | system_tick_t last_chunk_millis; 168 | unsigned short chunk_index; 169 | bool expecting_ping_ack; 170 | bool initialized; 171 | bool updating; 172 | char function_arg[MAX_FUNCTION_ARG_LENGTH]; 173 | 174 | size_t wrap(unsigned char *buf, size_t msglen); 175 | bool handle_received_message(void); 176 | unsigned short next_message_id(); 177 | unsigned char next_token(); 178 | void encrypt(unsigned char *buf, int length); 179 | void separate_response(unsigned char *buf, unsigned char token, unsigned char code); 180 | inline void empty_ack(unsigned char *buf, 181 | unsigned char message_id_msb, 182 | unsigned char message_id_lsb); 183 | inline void coded_ack(unsigned char *buf, 184 | unsigned char token, 185 | unsigned char code, 186 | unsigned char message_id_msb, 187 | unsigned char message_id_lsb); 188 | 189 | /********** Queue **********/ 190 | unsigned char queue[640]; 191 | const unsigned char *queue_mem_boundary; 192 | unsigned char *queue_front; 193 | unsigned char *queue_back; 194 | void queue_init(void); 195 | }; 196 | 197 | #endif // __SPARK_PROTOCOL_H 198 | -------------------------------------------------------------------------------- /tests/ConstructorFixture.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file ConstructorFixture.cpp 4 | * @authors Zachary Crockett 5 | * @version V1.0.0 6 | * @date 10-Jan-2014 7 | * @brief Fixture for testing SparkProtocol 8 | ****************************************************************************** 9 | Copyright (c) 2013 Spark Labs, Inc. All rights reserved. 10 | 11 | This library is free software; you can redistribute it and/or 12 | modify it under the terms of the GNU Lesser General Public 13 | License as published by the Free Software Foundation, either 14 | version 3 of the License, or (at your option) any later version. 15 | 16 | This library is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public 22 | License along with this library; if not, see . 23 | ****************************************************************************** 24 | */ 25 | 26 | #include "ConstructorFixture.h" 27 | #include 28 | 29 | const uint8_t ConstructorFixture::nonce[41] = 30 | "\x31\xE8\x30\x24\x6F\x2D\x7D\x98\x7C\x42\x47\x7E\xF0\x33\xF4\x24" 31 | "\xFF\x62\xD3\x82\xB1\x7A\x09\x31\x13\x0B\x23\x63\x98\xDE\x90\x84" 32 | "\x71\x41\xF5\x83\x04\x84\x17\x7B"; 33 | 34 | const char ConstructorFixture::id[13] = 35 | "\x54\xE1\xC8\x88\xF6\xD9\x49\x2B\xEB\xEE\x1E\xE9"; 36 | 37 | uint8_t ConstructorFixture::pubkey[295] = 38 | "\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01" 39 | "\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01" 40 | "\x00\xA4\x4B\x8F\x50\xBF\xD7\x94\x77\xF6\xC9\xBC\xEB\x1A\x00\xF3" 41 | "\x1D\x31\x51\xA8\xE0\xB0\xD4\x0F\x3C\xFF\x49\x85\x71\xBA\xFA\x54" 42 | "\x80\x9C\x91\x3D\x24\xD8\x9A\x4F\x99\x64\x30\xFC\xB5\x96\x44\xB1" 43 | "\x24\x8A\xA8\xD2\xC1\xBE\xEA\x3D\x95\x9B\x2F\xB2\x0F\x1C\x9D\xF7" 44 | "\x26\x51\xE9\x74\x7B\x8E\x7B\x3A\xEF\xF5\x47\x83\xC9\x71\x85\xEF" 45 | "\x3C\x51\x10\x35\x40\xA5\x79\x61\xFB\x21\x60\x1E\xDB\xCC\xA3\xE7" 46 | "\x98\x18\xA5\x61\x4E\x7C\xB2\x91\xB9\x92\xA7\x81\x5C\x49\x35\xF2" 47 | "\x0B\x23\x71\xCA\xFE\x10\x4D\x9D\x50\x04\xD8\xF1\x0F\x19\xD8\xC3" 48 | "\x7A\x63\x9D\xF5\x22\x23\x67\x09\x12\xDC\x8D\xC9\x0F\x7F\xCC\xD4" 49 | "\x52\x64\x96\xCF\x7A\x2C\x76\x32\x38\xCA\x9B\x7A\xC7\xD4\x27\x0F" 50 | "\x3F\xD1\xFB\x8A\x62\x04\x8B\xB7\x03\x25\x18\xCB\xF4\x3B\x0A\x90" 51 | "\x50\x2A\x5E\xBE\x1F\xC8\x36\x3E\x8F\x79\xD2\xB3\xDA\xE1\x44\xE3" 52 | "\x09\xF7\x12\x17\x49\x00\xC9\x38\x8C\xA3\xFF\xDD\x6A\xD1\x43\xB8" 53 | "\x05\xF8\x6A\x4A\xB6\xE0\x19\x2A\x02\x45\x92\x6F\xF9\x61\xB7\xE8" 54 | "\x39\x17\x05\x19\x14\x28\xB3\x8E\x4F\x63\xA5\x7F\x87\x7A\xA7\x62" 55 | "\x6B\x7A\x8C\xFD\xD3\x10\xED\x9E\xAB\x8B\xC5\xA1\x28\xB6\x17\x8E" 56 | "\x3D\x02\x03\x01\x00\x01"; 57 | 58 | uint8_t ConstructorFixture::private_key[613] = 59 | "\x30\x82\x02\x5E\x02\x01\x00\x02\x81\x81\x00\xC4\xC8\xEB\xFA\x99" 60 | "\xA5\xD1\xE5\xF9\x9D\x33\xEA\x1C\x93\xF2\x4A\x71\xC7\x1E\xA0\x1E" 61 | "\xE6\x71\x87\x39\x5E\x5F\x69\x56\x4F\x76\xC1\x83\x61\x10\xEA\x78" 62 | "\x69\x6E\x5A\xA2\x4D\x5E\x83\x4E\x41\xD0\xE5\x44\xBC\x48\x5F\x7D" 63 | "\x85\x65\x24\xB0\x9C\x9C\x3C\xD0\x0F\x42\x6A\x6D\x46\x51\x9C\x3E" 64 | "\xDC\x88\x33\x84\xC5\xF4\x6D\xAD\x89\xFD\x01\xDC\x2B\x3F\xB0\x6F" 65 | "\x12\x80\xEC\xE2\xD9\x53\x00\x66\x93\x58\x3C\x0B\x15\x66\xEA\x47" 66 | "\xD9\xDD\x8F\x49\xEE\xD7\x1A\x81\xBA\xE6\x58\x5C\x63\x7A\xDD\xC5" 67 | "\x11\xF1\xD2\xCE\x8C\x01\x60\xAD\xF3\xB4\x5F\x02\x03\x01\x00\x01" 68 | "\x02\x81\x81\x00\xBB\xC5\x58\xDE\xF4\x13\xB4\xF8\xB3\xB9\x5C\x5B" 69 | "\x2C\xCF\xC3\x27\x63\xEF\xF3\x7A\x28\x62\x0D\xBC\x51\x72\x8A\xAA" 70 | "\x51\xD0\x5B\x6A\x05\x79\xEE\x91\x3D\x3A\xA5\x31\x58\xA3\x68\xE6" 71 | "\xF4\x1A\x7B\x40\xF9\xD8\x8B\x5A\x8A\xC4\x69\xA1\x9B\xE0\xA4\x78" 72 | "\xA6\xB3\x98\xD3\x96\x20\x7B\xE4\x93\x9A\x0E\xFE\xD9\x44\x54\x6C" 73 | "\xCF\x2D\x5E\x9B\x91\x94\x58\x90\x30\xAC\x08\xA5\xE1\x8E\x5F\x84" 74 | "\xC3\x36\xD0\xCD\x0F\x10\xBF\x05\x6E\x29\x27\x8A\x16\x7A\xC6\xC2" 75 | "\x78\xCF\x2C\xBC\x5E\x5B\x00\x38\x3E\x66\xBF\x12\x2B\x20\x17\x8E" 76 | "\xE7\xE2\x7A\x09\x02\x41\x00\xEA\x0B\x61\xD6\x8D\x8C\xAD\x1C\xFC" 77 | "\x0A\x6F\x37\x69\x3A\xD7\x9F\x3C\x4E\xFF\xFA\x97\x72\x5C\x31\x36" 78 | "\x1F\x12\x23\x4B\x00\x29\x70\x82\x5F\x3F\xBF\x98\xE3\x35\x24\xD2" 79 | "\x3F\xE6\x88\x9D\xA6\x72\xE3\x4A\x09\xEA\xCA\xF2\x42\xCE\x8B\xB6" 80 | "\x18\x04\xAC\x01\x73\x4C\xCD\x02\x41\x00\xD7\x3E\xBE\x61\xA3\xF0" 81 | "\x75\x2B\xE4\xDD\x60\x67\xA6\x9E\x6A\xDF\x41\xB1\x71\xC9\x54\xDA" 82 | "\xF1\xB6\xAC\xEB\x3E\x12\x3C\xA8\x6C\xCB\x75\xFC\xDA\xE5\x69\xBF" 83 | "\xB1\x61\x4F\x4F\xD0\x32\x21\xF8\x52\x27\x1C\x59\x69\xBE\x3E\xB3" 84 | "\xF3\x16\x41\xBC\xAF\x3A\x6F\x15\x05\xDB\x02\x40\x5A\x18\xE9\xA0" 85 | "\x1B\xBB\xB5\x04\xBC\x6E\x13\xE4\x63\xE9\x18\x0A\x9F\xBF\xD5\xC1" 86 | "\x15\x3E\x1C\x09\x81\xC9\x32\x45\x4D\xE1\x11\x12\xD3\xCD\x71\x10" 87 | "\x03\xFE\x2B\x7E\x32\x46\x11\x2C\x34\x6C\x58\x3B\xF1\x4B\xA2\x0C" 88 | "\x60\x78\xA1\x64\x9D\x43\xDF\xC0\x8B\x8A\x64\x5D\x02\x41\x00\xD3" 89 | "\x42\xDE\x11\x6F\x9A\xDF\x26\x49\xE7\x8E\x6B\xAD\x79\xE7\x63\x61" 90 | "\x53\x0C\x5F\x93\x4D\xA1\xD8\xAE\x37\xE6\x20\x78\x30\xC7\x37\x9B" 91 | "\x82\xA6\x46\x6D\x58\x9C\x7C\xEA\x1F\x68\x35\x0C\x6A\x72\x17\xB9" 92 | "\x17\x79\x56\x24\xAC\xF2\x76\x71\xE7\x04\x05\xD2\x69\x4B\xE9\x02" 93 | "\x41\x00\x83\x7B\x91\x02\x66\xA0\x81\xA9\xBD\xBA\xA2\x86\x3D\x2B" 94 | "\x03\x61\xE8\x8F\x05\x12\xE3\x33\xAF\x6C\x9D\xFD\x22\xBF\xC5\xC0" 95 | "\x3B\xD3\x69\x45\x37\xAF\x3D\xC5\xFE\x91\x14\x73\x5C\x8E\xEC\xEE" 96 | "\xA3\x1B\x90\xB7\x23\x43\xC3\x5D\x7E\xF8\xBE\xDB\x3E\x62\x1A\x17" 97 | "\xE9\xBF\x00\x00"; 98 | 99 | const uint8_t ConstructorFixture::signed_encrypted_credentials[385] = 100 | "\x0B\xAD\x19\x22\xB6\x60\xF4\xC7\xB4\xEA\x34\xD9\xBF\xBB\x31\xDC" 101 | "\x1A\x60\x99\xD8\x57\xF5\x4A\x88\xC7\x5C\x61\x2F\x91\x59\xE9\xE6" 102 | "\x9E\x6B\x1F\x86\xCF\x83\xE3\xE5\xE7\x8F\x7B\x89\x12\x63\xEC\xA2" 103 | "\x85\xA7\x87\x11\x41\xC2\xE0\xA1\x5C\x4F\xD3\x1D\x23\xDD\x19\xF5" 104 | "\x38\xB0\x6C\x4B\x70\xE4\x26\x31\xE6\x16\x81\x2A\x82\x80\xA6\xE0" 105 | "\x78\x3E\xE3\xDE\xB2\x29\x0F\x81\x72\x48\x27\x6E\x48\x01\x13\xED" 106 | "\xFF\x09\x8D\xFC\xBB\xA2\x46\x5C\xB2\x07\xDC\x8D\x58\x36\x8B\xA8" 107 | "\x21\xA6\x5D\xAC\x6E\x6E\xF0\x8E\x39\x5A\xD3\x71\x65\x92\x6B\xF0" 108 | "\x9E\x27\x75\x13\x79\xA7\xCD\xAD\x74\xF8\xAF\xA4\x4D\xDA\x11\x1D" 109 | "\x0A\x8F\xE7\x7B\xFC\xB7\x1A\x45\x45\x88\x01\x7E\x86\x03\x3D\x75" 110 | "\xE2\x37\x9C\x3D\x26\x51\x59\x3F\x73\xF7\x36\x44\xD1\xB7\x6C\x59" 111 | "\x72\x0E\xE9\x42\x10\x48\xE0\xA0\xB5\x3F\x11\x35\xD2\x5C\x6F\x55" 112 | "\x98\x13\xAF\xEF\x0C\xFE\x2D\x36\xB9\x63\x20\xD7\x69\x81\xE8\xAB" 113 | "\x2E\x78\x0A\xFD\x27\x5B\x4E\xC9\x1F\x1A\xC1\xFB\x06\x86\x8E\x63" 114 | "\xA3\xE5\xDC\x97\x05\x09\x16\x5A\xD2\x54\x1C\xA0\x16\x67\x53\x4C" 115 | "\xFB\x30\x6A\xB6\x85\x4E\x96\x11\xCF\xA1\xC4\x85\x4F\x1B\xB5\xD6" 116 | "\x8A\x91\xEA\x26\xD1\xA7\xD0\x25\x58\x93\x05\x93\x2B\xEC\x93\xD2" 117 | "\xCD\x96\x3D\x03\xF4\xEB\x80\x9E\x17\x3E\x64\xB2\xA1\xA8\x95\xB8" 118 | "\xE5\xB0\xC9\xD8\x39\xDA\x18\x32\xC1\xC7\xF8\x85\x62\xBA\x8F\x2E" 119 | "\x45\xA2\x41\x31\x2F\x26\x44\x5B\xA6\xA4\x4D\x70\xCD\xC0\xFB\x8B" 120 | "\x68\x6A\xBA\x0E\xE0\xD5\xF4\x28\x31\x6C\xC7\xE5\x40\x30\x6A\xC1" 121 | "\xEE\x2F\x3F\xA6\x74\x81\x3D\xA1\xDC\xBA\x34\xE4\xC7\x44\x58\x3F" 122 | "\x0C\x99\xD0\xCD\xC0\xC0\x4A\x9F\x10\x95\x50\x49\x09\xCE\x09\xE2" 123 | "\xF7\xBD\x88\x2E\xAE\x86\xCD\x19\x1E\xAC\x3A\x0E\xB2\x29\x1B\x6B"; 124 | 125 | int ConstructorFixture::bytes_sent[2] = { 0, 0 }; 126 | int ConstructorFixture::bytes_received[2] = { 0, 0 }; 127 | uint8_t ConstructorFixture::sent_buf_0[256]; 128 | uint8_t ConstructorFixture::sent_buf_1[256]; 129 | 130 | uint8_t ConstructorFixture::message_to_receive[98]; 131 | long unsigned int ConstructorFixture::mock_crc = 0; 132 | unsigned short ConstructorFixture::next_chunk_index = 0; 133 | uint8_t ConstructorFixture::saved_firmware_chunk[72]; 134 | bool ConstructorFixture::did_prepare_for_update = false; 135 | bool ConstructorFixture::did_finish_update = false; 136 | bool ConstructorFixture::nothing_to_receive = false; 137 | bool ConstructorFixture::function_called = false; 138 | int ConstructorFixture::variable_to_get = -98765; 139 | bool ConstructorFixture::signal_called_with = false; 140 | time_t ConstructorFixture::set_time_called_with = -1; 141 | EventHandlerCalledWith ConstructorFixture::event_handlers_called_with[2]; 142 | 143 | ConstructorFixture::ConstructorFixture() 144 | { 145 | bytes_sent[0] = bytes_sent[1] = 0; 146 | bytes_received[0] = bytes_received[1] = 0; 147 | keys.core_private = private_key; 148 | keys.server_public = pubkey; 149 | callbacks.send = mock_send; 150 | callbacks.receive = mock_receive; 151 | callbacks.prepare_for_firmware_update = mock_prepare_for_firmware_update; 152 | callbacks.calculate_crc = mock_calculate_crc; 153 | callbacks.save_firmware_chunk = mock_save_firmware_chunk; 154 | callbacks.finish_firmware_update = mock_finish_firmware_update; 155 | callbacks.signal = mock_signal; 156 | callbacks.millis = mock_millis; 157 | callbacks.set_time = mock_set_time; 158 | descriptor.num_functions = mock_num_functions; 159 | descriptor.copy_function_key = mock_copy_function_key; 160 | descriptor.call_function = mock_call_function; 161 | descriptor.num_variables = mock_num_variables; 162 | descriptor.copy_variable_key = mock_copy_variable_key; 163 | descriptor.get_variable = mock_get_variable; 164 | descriptor.was_ota_upgrade_successful = mock_ota_status_check; 165 | descriptor.variable_type = mock_variable_type; 166 | mock_crc = 0; 167 | next_chunk_index = 1; 168 | memset(saved_firmware_chunk, 0, 72); 169 | did_prepare_for_update = false; 170 | did_finish_update = false; 171 | nothing_to_receive = false; 172 | function_called = false; 173 | variable_to_get = -98765; 174 | spark_protocol.init(id, keys, callbacks, descriptor); 175 | } 176 | 177 | int ConstructorFixture::mock_send(const unsigned char *buf, int buflen) 178 | { 179 | if (0 < buflen) 180 | { 181 | if (0 == bytes_sent[0] || 1 == bytes_sent[0]) 182 | { 183 | uint8_t *dst = sent_buf_0; 184 | if (20 == buflen) 185 | { 186 | // blocking send test, part 1 187 | buflen = 1; 188 | } 189 | else if (19 == buflen) 190 | { 191 | // blocking send test, part 2 192 | dst = sent_buf_0 + 1; 193 | } 194 | // event loop tests send 16 + 2 or 32 + 2 195 | else if (34 != buflen && 18 != buflen) 196 | { 197 | // handshake, send first several bytes 198 | buflen = 11; 199 | } 200 | memcpy(dst, buf, buflen); 201 | bytes_sent[0] += buflen; 202 | } 203 | else if (11 == bytes_sent[0]) 204 | { 205 | // handshake, send remaining bytes 206 | memcpy(sent_buf_0 + 11, buf, buflen); 207 | bytes_sent[0] += buflen; 208 | } 209 | else 210 | { 211 | memcpy(sent_buf_1, buf, buflen); 212 | bytes_sent[1] += buflen; 213 | } 214 | } 215 | else buflen = 0; 216 | return buflen; 217 | } 218 | 219 | int ConstructorFixture::mock_receive(unsigned char *buf, int buflen) 220 | { 221 | if (nothing_to_receive) 222 | return 0; 223 | 224 | if (0 < buflen) 225 | { 226 | if (0 == bytes_received[0] || 7 == bytes_received[0]) 227 | { 228 | if (40 == buflen) 229 | { 230 | // handshake, receive first several bytes 231 | buflen = 7; 232 | memcpy(buf, nonce, buflen); 233 | } 234 | else if (33 == buflen) 235 | { 236 | // handshake, receive remainint bytes 237 | memcpy(buf, nonce + 7, buflen); 238 | } 239 | else 240 | { 241 | // event_loop 242 | memcpy(buf, message_to_receive, buflen); 243 | } 244 | bytes_received[0] += buflen; 245 | } 246 | else 247 | { 248 | if (384 == buflen) 249 | { 250 | // handshake 251 | memcpy(buf, signed_encrypted_credentials, buflen); 252 | } 253 | else if (20 == buflen) 254 | { 255 | // blocking receive test, part 1 256 | buflen = 1; 257 | memcpy(buf, message_to_receive, buflen); 258 | } 259 | else if (19 == buflen) 260 | { 261 | // blocking receive test, part 2 262 | memcpy(buf, message_to_receive, buflen); 263 | } 264 | else 265 | { 266 | // event_loop 267 | memcpy(buf, message_to_receive + 2, buflen); 268 | } 269 | bytes_received[1] += buflen; 270 | } 271 | } 272 | else buflen = 0; 273 | return buflen; 274 | } 275 | 276 | void ConstructorFixture::mock_prepare_for_firmware_update(void) 277 | { 278 | did_prepare_for_update = true; 279 | } 280 | 281 | long unsigned int ConstructorFixture::mock_calculate_crc(unsigned char *, long unsigned int) 282 | { 283 | return mock_crc; 284 | } 285 | 286 | unsigned short ConstructorFixture::mock_save_firmware_chunk(unsigned char *buf, long unsigned int buflen) 287 | { 288 | memcpy(saved_firmware_chunk, buf, buflen); 289 | return next_chunk_index; 290 | } 291 | 292 | void ConstructorFixture::mock_finish_firmware_update(void) 293 | { 294 | did_finish_update = true; 295 | } 296 | 297 | int ConstructorFixture::mock_num_functions(void) 298 | { 299 | return 1; 300 | } 301 | 302 | void ConstructorFixture::mock_copy_function_key(char *dst, int i) 303 | { 304 | const char *funcs[1] = { "brew\0\0\0\0\0\0\0\0" }; 305 | memcpy(dst, funcs[i], SparkProtocol::MAX_FUNCTION_KEY_LENGTH); 306 | } 307 | 308 | int ConstructorFixture::mock_call_function(const char *function_key, 309 | const char *arg) 310 | { 311 | const char *prevent_warning; 312 | prevent_warning = function_key; 313 | prevent_warning = arg; 314 | function_called = true; 315 | return 456; 316 | } 317 | 318 | int ConstructorFixture::mock_num_variables(void) 319 | { 320 | return 1; 321 | } 322 | 323 | void ConstructorFixture::mock_copy_variable_key(char *dst, int i) 324 | { 325 | const char *vars[1] = { "temperature\0" }; 326 | memcpy(dst, vars[i], SparkProtocol::MAX_VARIABLE_KEY_LENGTH); 327 | } 328 | 329 | void *ConstructorFixture::mock_get_variable(const char *variable_key) 330 | { 331 | const char *prevent_warning; 332 | prevent_warning = variable_key; 333 | return &variable_to_get; 334 | } 335 | 336 | void ConstructorFixture::mock_signal(bool on) 337 | { 338 | signal_called_with = on; 339 | } 340 | 341 | system_tick_t ConstructorFixture::next_millis = 0; 342 | 343 | system_tick_t ConstructorFixture::mock_millis(void) 344 | { 345 | return next_millis; 346 | } 347 | 348 | bool ConstructorFixture::mock_ota_status_check(void) 349 | { 350 | return false; 351 | } 352 | 353 | SparkReturnType::Enum ConstructorFixture::mock_variable_type(const char *variable_key) 354 | { 355 | const char *prevent_warning; 356 | prevent_warning = variable_key; 357 | return SparkReturnType::INT; 358 | } 359 | 360 | void ConstructorFixture::mock_set_time(time_t t) 361 | { 362 | set_time_called_with = t; 363 | } 364 | 365 | void ConstructorFixture::mock_event_handler_0(const char *event_name, const char *data) 366 | { 367 | memcpy(event_handlers_called_with[0].event_name, event_name, strlen(event_name)); 368 | if (data) 369 | { 370 | memcpy(event_handlers_called_with[0].data, data, strlen(event_name)); 371 | } 372 | else 373 | { 374 | event_handlers_called_with[0].data[0] = 0; 375 | } 376 | } 377 | 378 | void ConstructorFixture::mock_event_handler_1(const char *event_name, const char *data) 379 | { 380 | memcpy(event_handlers_called_with[1].event_name, event_name, strlen(event_name)); 381 | if (data) 382 | { 383 | memcpy(event_handlers_called_with[1].data, data, strlen(event_name)); 384 | } 385 | else 386 | { 387 | event_handlers_called_with[1].data[0] = 0; 388 | } 389 | } 390 | -------------------------------------------------------------------------------- /tests/ConstructorFixture.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file ConstructorFixture.h 4 | * @authors Zachary Crockett 5 | * @version V1.0.0 6 | * @date 10-Jan-2014 7 | * @brief Fixture for testing SparkProtocol 8 | ****************************************************************************** 9 | Copyright (c) 2013 Spark Labs, Inc. All rights reserved. 10 | 11 | This library is free software; you can redistribute it and/or 12 | modify it under the terms of the GNU Lesser General Public 13 | License as published by the Free Software Foundation, either 14 | version 3 of the License, or (at your option) any later version. 15 | 16 | This library is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public 22 | License along with this library; if not, see . 23 | ****************************************************************************** 24 | */ 25 | 26 | #ifndef __CONSTRUCTOR_FIXTURE_H 27 | #define __CONSTRUCTOR_FIXTURE_H 28 | 29 | #include 30 | #include "spark_protocol.h" 31 | 32 | struct EventHandlerCalledWith 33 | { 34 | char event_name[64]; 35 | char data[64]; 36 | }; 37 | 38 | struct ConstructorFixture 39 | { 40 | static const uint8_t nonce[41]; 41 | static const char id[13]; 42 | static uint8_t pubkey[295]; 43 | static uint8_t private_key[613]; 44 | static const uint8_t signed_encrypted_credentials[385]; 45 | static int bytes_sent[2]; 46 | static int bytes_received[2]; 47 | static uint8_t sent_buf_0[256]; 48 | static uint8_t sent_buf_1[256]; 49 | static int mock_send(const unsigned char *buf, int buflen); 50 | static int mock_receive(unsigned char *buf, int buflen); 51 | static uint8_t message_to_receive[98]; 52 | static void mock_prepare_for_firmware_update(void); 53 | static long unsigned int mock_crc; 54 | static long unsigned int mock_calculate_crc(unsigned char *buf, long unsigned int buflen); 55 | static unsigned short next_chunk_index; 56 | static unsigned short mock_save_firmware_chunk(unsigned char *buf, long unsigned int buflen); 57 | static bool did_prepare_for_update; 58 | static bool did_finish_update; 59 | static bool nothing_to_receive; 60 | static uint8_t saved_firmware_chunk[72]; 61 | static void mock_finish_firmware_update(void); 62 | static bool function_called; 63 | static int mock_num_functions(void); 64 | static void mock_copy_function_key(char *destination, int function_index); 65 | static int mock_call_function(const char *function_key, const char *arg); 66 | static int mock_num_variables(void); 67 | static void mock_copy_variable_key(char *destination, int variable_index); 68 | static void *mock_get_variable(const char *variable_key); 69 | static void mock_signal(bool on); 70 | static bool signal_called_with; 71 | static int variable_to_get; 72 | static system_tick_t next_millis; 73 | static system_tick_t mock_millis(void); 74 | static bool mock_ota_status_check(void); 75 | static SparkReturnType::Enum mock_variable_type(const char *variable_key); 76 | static void mock_set_time(time_t t); 77 | static time_t set_time_called_with; 78 | static EventHandlerCalledWith event_handlers_called_with[2]; 79 | static void mock_event_handler_0(const char *event_name, const char *data); 80 | static void mock_event_handler_1(const char *event_name, const char *data); 81 | 82 | ConstructorFixture(); 83 | SparkKeys keys; 84 | SparkCallbacks callbacks; 85 | SparkDescriptor descriptor; 86 | SparkProtocol spark_protocol; 87 | }; 88 | 89 | #endif // __CONSTRUCTOR_FIXTURE_H 90 | -------------------------------------------------------------------------------- /tests/Main.cpp: -------------------------------------------------------------------------------- 1 | #include "UnitTest++.h" 2 | 3 | int main(int, char const *[]) 4 | { 5 | return UnitTest::RunAllTests(); 6 | } 7 | -------------------------------------------------------------------------------- /tests/TestAES.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "UnitTest++.h" 4 | #include "tropicssl/aes.h" 5 | 6 | struct AESFixture 7 | { 8 | static const uint8_t credentials[40]; 9 | static const uint8_t ciphertext[32]; 10 | static const uint8_t plaintext[32]; 11 | }; 12 | 13 | const uint8_t AESFixture::credentials[40] = { 14 | 0x50, 0x8e, 0x8a, 0xfd, 0x78, 0x73, 0x23, 0x38, 15 | 0x67, 0xd6, 0x56, 0xc0, 0xca, 0x46, 0x04, 0x8e, 16 | 0x0a, 0xbb, 0x06, 0xe3, 0x9b, 0xc5, 0x7e, 0x2c, 17 | 0x9b, 0xce, 0x0b, 0xdf, 0xc5, 0x52, 0xc8, 0x2d, 18 | 0xf6, 0x48, 0x0d, 0x23, 0xc5, 0x0e, 0x2d, 0x6d }; 19 | 20 | const uint8_t AESFixture::ciphertext[32] = { 21 | 0xcf, 0x05, 0x07, 0x47, 0x67, 0x64, 0x15, 0x8c, 22 | 0x7b, 0x63, 0xd0, 0x4c, 0x9d, 0x17, 0xe0, 0x12, 23 | 0xc2, 0xc1, 0x84, 0x10, 0x5b, 0xdd, 0x5e, 0x36, 24 | 0xb8, 0xad, 0x8f, 0x61, 0xdb, 0x7e, 0x85, 0xd1 }; 25 | 26 | const uint8_t AESFixture::plaintext[32] = { 27 | 0x53, 0x75, 0x70, 0x65, 0x72, 0x20, 0x73, 0x65, 28 | 0x63, 0x72, 0x65, 0x74, 0x20, 0x6d, 0x65, 0x73, 29 | 0x73, 0x61, 0x67, 0x65, 0x0a, 0x0b, 0x0b, 0x0b, 30 | 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }; 31 | 32 | 33 | TEST_FIXTURE(AESFixture, SuccessfullyDecryptsOpenSSLExample) 34 | { 35 | unsigned char buf[32]; 36 | memcpy(buf, ciphertext, 32); 37 | 38 | unsigned char iv[16]; 39 | memcpy(iv, credentials + 16, 16); 40 | 41 | aes_context ctx; 42 | aes_setkey_dec(&ctx, credentials, 128); 43 | aes_crypt_cbc(&ctx, AES_DECRYPT, 32, iv, buf, buf); 44 | 45 | CHECK_ARRAY_EQUAL(plaintext, buf, 32); 46 | } 47 | 48 | TEST_FIXTURE(AESFixture, EncryptsSameAsOpenSSL) 49 | { 50 | uint8_t buf[32]; 51 | memcpy(buf, plaintext, 32); 52 | 53 | unsigned char iv[16]; 54 | memcpy(iv, credentials + 16, 16); 55 | 56 | aes_context ctx; 57 | aes_setkey_enc(&ctx, credentials, 128); 58 | /* Note length 21, without PKCS #7 padding */ 59 | aes_crypt_cbc(&ctx, AES_ENCRYPT, 21, iv, buf, buf); 60 | 61 | CHECK_ARRAY_EQUAL(ciphertext, buf, 32); 62 | } 63 | 64 | TEST(AESSelfTestSucceeds) 65 | { 66 | CHECK_EQUAL(0, aes_self_test(0)); 67 | } 68 | -------------------------------------------------------------------------------- /tests/TestDescriptor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "UnitTest++.h" 3 | #include "spark_descriptor.h" 4 | 5 | struct FunctionFixture { 6 | static int execute_a_function(const char *func_key, const char *arg); 7 | static int get_number_of_funcs(void); 8 | static void copy_a_function_key(char *destination, int function_index); 9 | }; 10 | 11 | int FunctionFixture::execute_a_function(const char *func_key, 12 | const char *arg) 13 | { 14 | const char *prevent_warning; 15 | prevent_warning = func_key; 16 | prevent_warning = arg; 17 | return 99; 18 | } 19 | 20 | int FunctionFixture::get_number_of_funcs(void) 21 | { 22 | return 3; 23 | } 24 | 25 | void FunctionFixture::copy_a_function_key(char *destination, int function_index) 26 | { 27 | const char *function_keys[] = { 28 | "brew\0\0\0\0\0\0\0\0", "clean\0\0\0\0\0\0\0", "bean_alert\0\0" }; 29 | memcpy(destination, function_keys[function_index], 12); 30 | } 31 | 32 | SUITE(Descriptor) 33 | { 34 | TEST_FIXTURE(FunctionFixture, DescriptorKnowsNumberOfRegisteredFunctions) 35 | { 36 | SparkDescriptor descriptor; 37 | descriptor.num_functions = get_number_of_funcs; 38 | CHECK_EQUAL(3, descriptor.num_functions()); 39 | } 40 | 41 | TEST_FIXTURE(FunctionFixture, DescriptorCanAccessArrayOfFunctionKeys) 42 | { 43 | SparkDescriptor descriptor; 44 | descriptor.copy_function_key = copy_a_function_key; 45 | char buf[12]; 46 | descriptor.copy_function_key(buf, 2); 47 | CHECK_EQUAL("bean_alert\0\0", buf); 48 | } 49 | 50 | TEST_FIXTURE(FunctionFixture, DescriptorCanCallRegisteredFunction) 51 | { 52 | SparkDescriptor descriptor; 53 | descriptor.call_function = execute_a_function; 54 | const char *function_key = "brew"; 55 | const char *arg = "32,240"; 56 | int return_value = descriptor.call_function(function_key, arg); 57 | CHECK_EQUAL(99, return_value); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /tests/TestEvents.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file TestEvents.cpp 4 | * @authors Zachary Crockett 5 | * @version V1.0.0 6 | * @date 26-Feb-2014 7 | * @brief Unit tests for CoAP event message creation 8 | ****************************************************************************** 9 | Copyright (c) 2014 Spark Labs, Inc. All rights reserved. 10 | 11 | This library is free software; you can redistribute it and/or 12 | modify it under the terms of the GNU Lesser General Public 13 | License as published by the Free Software Foundation, either 14 | version 3 of the License, or (at your option) any later version. 15 | 16 | This library is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public 22 | License along with this library; if not, see . 23 | ****************************************************************************** 24 | */ 25 | #include 26 | #include "UnitTest++.h" 27 | #include "events.h" 28 | 29 | static uint8_t buf[54]; 30 | size_t len; 31 | 32 | SUITE(Events) 33 | { 34 | /***** publishing *****/ 35 | 36 | TEST(LengthOfSingleCharEventWithNoDataIs8) 37 | { 38 | const size_t expected = 8; 39 | len = event(buf, 0xf649, "x", NULL, 60, EventType::PUBLIC); 40 | CHECK_EQUAL(expected, len); 41 | } 42 | 43 | TEST(ExpectedBufForSingleCharEventWithNoData) 44 | { 45 | const uint8_t expected[] = { 46 | 0x50, 0x02, 0xf6, 0x49, 0xb1, 'e', 0x01, 'x' }; 47 | len = event(buf, 0xf649, "x", NULL, 60, EventType::PUBLIC); 48 | CHECK_ARRAY_EQUAL(expected, buf, len); 49 | } 50 | 51 | TEST(LengthOfLongerMessageWithNoData) 52 | { 53 | const size_t expected = 27; 54 | len = event(buf, 0xf649, "front-door-unlocked", NULL, 60, EventType::PRIVATE); 55 | CHECK_EQUAL(expected, len); 56 | } 57 | 58 | TEST(ExpectedBufForLongerMessageWithNoData) 59 | { 60 | const uint8_t expected[] = { 61 | 0x50, 0x02, 0xf6, 0x49, 0xb1, 'E', 0x0d, 0x06, 62 | 'f','r','o','n','t','-','d','o','o','r','-', 63 | 'u','n','l','o','c','k','e','d' }; 64 | len = event(buf, 0xf649, "front-door-unlocked", NULL, 60, EventType::PRIVATE); 65 | CHECK_ARRAY_EQUAL(expected, buf, len); 66 | } 67 | 68 | TEST(LengthOfSingleCharEventNameUriPathIs2) 69 | { 70 | const size_t expected = 2; 71 | len = event_name_uri_path(buf, "x", 1); 72 | CHECK_EQUAL(expected, len); 73 | } 74 | 75 | TEST(ExpectedBufForSingleCharEventNameUriPath) 76 | { 77 | const uint8_t expected[] = { 0x01, 'x' }; 78 | len = event_name_uri_path(buf, "x", 1); 79 | CHECK_ARRAY_EQUAL(expected, buf, len); 80 | } 81 | 82 | TEST(LengthOfLongerEventNameUriPath) 83 | { 84 | const char name[] = "front-door-unlocked"; 85 | const size_t name_len = strlen(name); 86 | const size_t expected = name_len + 2; 87 | len = event_name_uri_path(buf, name, name_len); 88 | CHECK_EQUAL(expected, len); 89 | } 90 | 91 | TEST(ExpectedBufForLongerEventNameUriPath) 92 | { 93 | const uint8_t expected[] = { 0x0d, 0x06, 'f','r','o','n','t', 94 | '-','d','o','o','r','-','u','n','l','o','c','k','e','d' }; 95 | len = event_name_uri_path(buf, "front-door-unlocked", 19); 96 | CHECK_ARRAY_EQUAL(expected, buf, len); 97 | } 98 | 99 | TEST(LengthOfLongEventWithDataAndTtl) 100 | { 101 | const size_t expected = 54; 102 | len = event(buf, 0x7654, "weather/us/mn/minneapolis", 103 | "t:5F,d:-2F,p:15%", 3600, EventType::PUBLIC); 104 | CHECK_EQUAL(expected, len); 105 | } 106 | 107 | TEST(ExpectedBufForLongEventWithDataAndTtl) 108 | { 109 | const uint8_t expected[] = { 110 | 0x50, 0x02, 0x76, 0x54, 0xb1, 'e', 0x0d, 0x0c, 111 | 'w','e','a','t','h','e','r','/','u','s','/','m','n','/', 112 | 'm','i','n','n','e','a','p','o','l','i','s', 113 | 0x33, 0x00, 0x0e, 0x10, 0xff, 114 | 't',':','5','F',',','d',':','-','2','F',',','p',':','1','5','%' }; 115 | len = event(buf, 0x7654, "weather/us/mn/minneapolis", 116 | "t:5F,d:-2F,p:15%", 3600, EventType::PUBLIC); 117 | CHECK_ARRAY_EQUAL(expected, buf, len); 118 | } 119 | 120 | 121 | /***** subscribing *****/ 122 | 123 | TEST(LengthOfSubscriptionToOneDeviceFiltered) 124 | { 125 | const size_t expected = 39; 126 | len = subscription(buf, 0x8888, "weather", "53ff73065067544816300187"); 127 | CHECK_EQUAL(expected, len); 128 | } 129 | 130 | TEST(ExpectedBufForSubscriptionToOneDeviceFiltered) 131 | { 132 | const uint8_t expected[] = { 133 | 0x40, 0x01, 0x88, 0x88, 0xB1, 'e', 0x07, 134 | 'w', 'e', 'a', 't', 'h', 'e', 'r', 0xFF, 135 | '5','3','f','f','7','3','0','6','5','0','6','7', 136 | '5','4','4','8','1','6','3','0','0','1','8','7' }; 137 | len = subscription(buf, 0x8888, "weather", "53ff73065067544816300187"); 138 | CHECK_ARRAY_EQUAL(expected, buf, len); 139 | } 140 | 141 | TEST(LengthOfSubscriptionToOneDeviceUnfilteredWithNull) 142 | { 143 | const size_t expected = 31; 144 | len = subscription(buf, 0x7000, NULL, "53ff73065067544816300187"); 145 | CHECK_EQUAL(expected, len); 146 | } 147 | 148 | TEST(LengthOfSubscriptionToOneDeviceUnfilteredWithEmptyString) 149 | { 150 | const size_t expected = 31; 151 | len = subscription(buf, 0x7000, "", "53ff73065067544816300187"); 152 | CHECK_EQUAL(expected, len); 153 | } 154 | 155 | TEST(ExpectedBufForSubscriptionToOneDeviceUnfilteredWithNull) 156 | { 157 | const uint8_t expected[] = { 158 | 0x40, 0x01, 0x70, 0x00, 0xB1, 'e', 0xFF, 159 | '5','3','f','f','7','3','0','6','5','0','6','7', 160 | '5','4','4','8','1','6','3','0','0','1','8','7' }; 161 | len = subscription(buf, 0x7000, NULL, "53ff73065067544816300187"); 162 | CHECK_ARRAY_EQUAL(expected, buf, len); 163 | } 164 | 165 | TEST(ExpectedBufForSubscriptionToOneDeviceUnfilteredWithEmptyString) 166 | { 167 | const uint8_t expected[] = { 168 | 0x40, 0x01, 0x70, 0x00, 0xB1, 'e', 0xFF, 169 | '5','3','f','f','7','3','0','6','5','0','6','7', 170 | '5','4','4','8','1','6','3','0','0','1','8','7' }; 171 | len = subscription(buf, 0x7000, "", "53ff73065067544816300187"); 172 | CHECK_ARRAY_EQUAL(expected, buf, len); 173 | } 174 | 175 | TEST(LengthOfSubscriptionToMyDevicesFiltered) 176 | { 177 | const size_t expected = 20; 178 | len = subscription(buf, 0x1113, "motion/open", SubscriptionScope::MY_DEVICES); 179 | CHECK_EQUAL(expected, len); 180 | } 181 | 182 | TEST(ExpectedBufForSubscriptionToMyDevicesFiltered) 183 | { 184 | const uint8_t expected[] = { 185 | 0x40, 0x01, 0x11, 0x13, 0xB1, 'e', 0x0B, 186 | 'm', 'o', 't', 'i', 'o', 'n', '/', 'o', 'p', 'e', 'n', 187 | 0x41, 'u' }; 188 | len = subscription(buf, 0x1113, "motion/open", SubscriptionScope::MY_DEVICES); 189 | CHECK_ARRAY_EQUAL(expected, buf, len); 190 | } 191 | 192 | TEST(LengthOfSubscriptionToMyDevicesUnfiltered) 193 | { 194 | const size_t expected = 8; 195 | len = subscription(buf, 0x1114, NULL, SubscriptionScope::MY_DEVICES); 196 | CHECK_EQUAL(expected, len); 197 | } 198 | 199 | TEST(ExpectedBufForSubscriptionToMyDevicesUnfiltered) 200 | { 201 | const uint8_t expected[] = { 202 | 0x40, 0x01, 0x11, 0x14, 0xB1, 'e', 0x41, 'u' }; 203 | len = subscription(buf, 0x1114, NULL, SubscriptionScope::MY_DEVICES); 204 | CHECK_ARRAY_EQUAL(expected, buf, len); 205 | } 206 | 207 | TEST(LengthOfSubscriptionToFirehoseFiltered) 208 | { 209 | const size_t expected = 34; 210 | len = subscription(buf, 0x1115, "China/ShenZhen/FuTianKouAn", 211 | SubscriptionScope::FIREHOSE); 212 | CHECK_EQUAL(expected, len); 213 | } 214 | 215 | TEST(ExpectedBufForSubscriptionToFirehoseFiltered) 216 | { 217 | const uint8_t expected[] = { 218 | 0x40, 0x01, 0x11, 0x15, 0xB1, 'e', 0x0D, 0x0D, 219 | 'C','h','i','n','a','/','S','h','e','n','Z','h','e','n','/', 220 | 'F','u','T','i','a','n','K','o','u','A','n' }; 221 | len = subscription(buf, 0x1115, "China/ShenZhen/FuTianKouAn", 222 | SubscriptionScope::FIREHOSE); 223 | CHECK_ARRAY_EQUAL(expected, buf, len); 224 | } 225 | 226 | TEST(LengthOfDisallowedFirehoseUnfiltered) 227 | { 228 | const size_t expected = -1; 229 | len = subscription(buf, 0x1116, NULL, SubscriptionScope::FIREHOSE); 230 | CHECK_EQUAL(expected, len); 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /tests/TestHandshake.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "UnitTest++.h" 3 | #include "handshake.h" 4 | #include "tropicssl/rsa.h" 5 | 6 | struct HandshakeFixture 7 | { 8 | static const uint8_t nonce[41]; 9 | static const uint8_t id[13]; 10 | static const uint8_t pubkey[295]; 11 | static const uint8_t private_key[613]; 12 | static const uint8_t encrypted_aes_credentials[129]; 13 | static const uint8_t expected_hmac[21]; 14 | static const uint8_t signature[257]; 15 | }; 16 | 17 | const uint8_t HandshakeFixture::nonce[41] = 18 | "\x5D\x60\x41\xD1\x67\xBF\x18\xAF\x1D\xDA\xA4\x7C\x18\x83\x92\xA1" 19 | "\x04\xDE\xB0\xFF\xB9\x92\x2A\x12\xA6\x28\x9C\x60\x3E\x4F\xEB\x35" 20 | "\x8C\x18\xF9\xA1\x8A\x61\x0D\xA4"; 21 | 22 | const uint8_t HandshakeFixture::id[13] = 23 | "\x1A\x11\x8A\xD1\xC8\x86\xD5\x42\x40\xCE\x4B\x17"; 24 | 25 | const uint8_t HandshakeFixture::pubkey[295] = 26 | "\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01" 27 | "\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01" 28 | "\x00\xBB\xA0\x8A\x8D\xA3\xC5\x50\x2A\x8D\x7D\xE6\x0B\x6E\x39\x37" 29 | "\x14\xF5\x4A\xE2\xE7\xA3\x65\x2E\x50\x18\x4D\xB8\x2E\x83\x87\x9C" 30 | "\xEC\x4F\xF4\x48\xBD\x22\x85\x15\xD8\x77\xDD\xFB\x98\x69\xB4\x77" 31 | "\xF5\xEE\x37\xFB\xFF\xA4\xAE\x58\x3D\x05\x6F\x04\x43\xFA\x4F\x29" 32 | "\x7A\x56\x8A\x01\xEC\xF2\xAC\xB8\xAC\x8A\x9F\x7C\x31\xA3\xC0\xF2" 33 | "\xB2\x48\xF1\xF0\x7E\xB0\x5B\x20\x33\x34\x3C\x98\xAE\xE7\xC6\x8E" 34 | "\x13\xBC\x1D\x3A\x9E\xA2\x68\x8E\x7B\x9D\x12\x70\x4C\x5A\xE3\xDE" 35 | "\x8E\xD6\xE2\xFC\xA3\xDA\x36\xEF\xEA\x5F\x3E\xBF\xC5\x87\x3D\x93" 36 | "\x23\xC9\xB9\x2F\x4D\x67\xFB\x3F\xAF\x87\x85\xC9\x45\x2C\x25\x84" 37 | "\x82\x03\x38\x5D\x2E\x7B\x8A\x75\xFD\xB1\x8C\xE7\x18\xE3\x71\x06" 38 | "\x0A\x96\xD8\x81\xB0\xAB\x21\x31\x9B\x3A\x26\x08\xE2\xE8\x24\xC4" 39 | "\xD8\x88\x41\xE9\x17\x84\x52\x63\x06\x48\xD6\x89\xDE\xB5\x08\xDA" 40 | "\x2E\x61\x71\x87\xBA\x26\x2F\xE0\x02\x5A\x85\x97\x33\x27\x62\xA5" 41 | "\x39\x9C\xF4\x82\xFA\xEF\x9A\x4A\x97\xC0\x3D\x3A\xFF\xAE\x1B\x8D" 42 | "\xE5\x5E\x6B\xDB\x7F\x77\xFB\x0C\xB4\x80\x54\x80\x44\x49\xE2\x3B" 43 | "\x2D\x1E\x23\x2E\x68\x4F\xDA\xD6\xB0\xC8\xDA\x2D\x37\xDF\x4A\x00" 44 | "\x8B\x02\x03\x01\x00\x01"; 45 | 46 | const uint8_t HandshakeFixture::private_key[613] = 47 | "\x30\x82\x02\x5B\x02\x01\x00\x02\x81\x81\x00\xA8\x7C\xF2\xB1\x66" 48 | "\x0B\x5B\xFB\xD9\x7D\x62\x3A\xA0\x06\x75\xC1\xD4\x12\x2F\x67\xF9" 49 | "\xC3\x10\x87\x9F\xC7\x9B\x91\x70\xE5\x46\x8E\x27\x53\x06\x80\xCC" 50 | "\x09\xEE\x77\x77\x7F\x55\xEC\xAB\xAF\x63\xD7\xBD\xD8\x0B\x4D\x04" 51 | "\x01\xB9\x0D\xDD\x0D\x87\x25\x5A\x12\x39\x54\x90\x81\xCE\x07\x3B" 52 | "\xDC\x47\x01\xA6\xE6\xD9\x54\xCE\x71\xA5\xBD\x53\x48\x1E\xB4\x10" 53 | "\xEC\x6A\xBE\x94\xF0\xCD\x28\xD5\x76\x06\x0F\x02\x80\x11\x16\x8F" 54 | "\xEF\xBB\x4C\xFA\xDA\xA8\x48\x24\x64\xD1\xA1\x92\x2F\xB9\x4D\xE4" 55 | "\x32\x38\xD2\x5C\xE2\x30\xC1\x5E\xDB\xD8\xA1\x02\x03\x01\x00\x01" 56 | "\x02\x81\x80\x14\xE2\xC8\x42\xED\x5F\x63\x1B\xA9\x2E\x3D\xCA\xFE" 57 | "\xA3\x4E\x5D\xA4\xA8\x4C\x70\x1B\x29\xEF\x16\xA0\xDB\xE1\x90\xF9" 58 | "\xE9\xB2\x01\x55\x26\x99\x9B\xC5\xAF\x45\x7C\x51\xB7\xDB\x32\xE7" 59 | "\x65\x6A\x7F\x07\xED\x8C\x19\x13\xF2\x12\xBA\x81\x38\x78\x14\x4D" 60 | "\x42\x0D\x11\x16\xF7\xD5\xAA\xFB\x4C\x24\xE8\x56\xD8\xCB\x25\x37" 61 | "\xEC\x3D\x20\xF3\xCE\xDA\x09\xDC\x8C\xC0\x30\x35\xC7\x3F\xFA\x2C" 62 | "\x9A\x46\x6D\xED\x82\x3D\x08\xC7\xD7\x06\xD1\x9C\x7F\x5A\x91\x24" 63 | "\x23\x7B\x9A\xEA\x12\x5D\xC0\x4B\x2A\xCC\x5E\xB9\x0C\x4D\xBD\x75" 64 | "\x1E\x5C\xF1\x02\x41\x00\xDB\x45\x35\x37\xCB\x27\x56\x5A\xA8\x1D" 65 | "\x3D\x4A\x28\xB9\xF7\xD3\x10\xDF\x14\x47\x5F\x2E\x13\xC5\x02\x35" 66 | "\x14\x0D\xFC\x89\xFE\xE5\x85\xDB\x65\x42\x15\x2B\xA2\xF4\x6E\x3B" 67 | "\x78\xBF\xC6\xAC\x9D\x52\xC0\x28\x27\xE8\x5C\xC8\x91\x50\xD1\x61" 68 | "\xA6\x19\x59\xF0\xFB\x07\x02\x41\x00\xC4\xB6\x15\xE2\xB1\xE6\x78" 69 | "\x43\x4C\xE6\x89\x93\x4F\x94\xFB\xC6\x2E\x3F\xC3\xF1\x36\xA3\xD8" 70 | "\xC5\xB4\xC8\x65\xFE\xD8\xC8\x22\xA2\x3D\xBD\xAC\x9E\x00\x00\xC4" 71 | "\x00\x36\x60\x31\x27\xDA\xFD\x69\x6C\x83\xB6\xE7\x67\x03\x38\x01" 72 | "\xB5\x0D\x9C\xD0\x6E\x33\x2E\x9D\x17\x02\x40\x71\xE1\x16\xCB\x9C" 73 | "\x5A\x18\xD2\x4A\x9F\xAC\xF6\x38\x02\xA5\xC0\x5B\xF1\xD0\x01\x65" 74 | "\x60\x73\xEA\x0C\xC4\x6E\x5E\xF9\x3A\xDE\x44\x6C\x69\xCE\xC4\x2C" 75 | "\x64\x96\x64\x66\x5F\xC2\xCD\xAF\x2C\x75\x24\xC6\x21\xD4\xE0\x2C" 76 | "\x58\x0A\x88\xB3\xC6\x08\x53\x00\x50\x54\xBF\x02\x40\x72\x94\x95" 77 | "\x7E\xEC\x9D\x10\x64\x33\x40\xFD\xD5\xDE\xBF\x2B\x40\xAE\xE3\xD9" 78 | "\xA0\x81\x71\x42\xED\x36\x76\x9C\x62\xAB\xA7\x37\xF5\x44\xFD\x5C" 79 | "\xB4\xD3\xCF\x9E\x5B\x79\x50\xE2\x91\x12\x90\x15\x7E\x6D\xE2\x76" 80 | "\x3B\x9C\xB6\x5C\xD8\x37\x4B\xA6\x64\xEA\x4F\x36\x95\x02\x40\x07" 81 | "\xFE\xA4\xF4\xB7\xF4\xD6\x6F\x45\xE5\xA9\x52\xC6\xD2\xDD\x6B\x0C" 82 | "\xA2\x48\x36\x22\x33\x37\x1B\xE3\x05\xA0\x2F\xDC\xD9\xB3\xDB\x91" 83 | "\x6D\xDA\xB3\x6A\xD6\x68\x16\x08\x13\xC3\xBE\xE0\x68\xC5\xBF\x8E" 84 | "\xC0\x27\x20\x63\xF6\xAF\x95\x48\x73\x74\x57\x8F\x40\x3F\x80\x00" 85 | "\x00\x00\x00\x00"; 86 | 87 | const uint8_t HandshakeFixture::encrypted_aes_credentials[129] = 88 | "\x3C\xB1\x5F\x90\xC9\xAE\xFB\xDC\xF0\x44\xB3\x63\x03\x55\x9E\x67" 89 | "\x2A\xC0\xFE\x90\x1A\x8A\xB9\xE1\x16\xFB\x90\x8D\x3C\x8C\x29\xB5" 90 | "\x3D\xE2\xA2\x89\x4B\x60\xCF\x2D\x72\xD8\xFF\xEC\x9B\x91\x6C\x86" 91 | "\x34\x9B\x3C\xE1\xEA\xE4\x43\x40\x17\x8A\x0A\x00\x9A\xC0\x7F\x32" 92 | "\xE5\x65\x56\xA5\xA8\x36\xC1\x86\xD8\x05\x77\x01\xBF\xB6\x6D\x29" 93 | "\x33\xE4\x6D\xD0\x3C\xA0\x3A\xD4\xCB\xEA\x4A\xAD\x66\x96\x05\x41" 94 | "\x91\x07\xFE\x8A\x65\x6F\xBA\xC7\xFA\x73\xA3\x40\x91\xBC\x18\xF6" 95 | "\x5C\x9E\x4B\xD3\x64\x76\xD8\x4E\x6D\xFB\x57\x1E\x54\x14\x51\x52"; 96 | 97 | const uint8_t HandshakeFixture::expected_hmac[21] = 98 | "\x34\xA4\x7A\x49\xB4\xF4\xBE\xD3\x74\x95\xA5\xFC\x0B\x3E\x0F\x41" 99 | "\x4A\xE6\xB9\x2B"; 100 | 101 | const uint8_t HandshakeFixture::signature[257] = 102 | "\x13\xA4\x31\x5A\x28\x18\x89\x6A\xB9\xF3\xC1\xB9\x29\x33\xC5\x93" 103 | "\x14\xD7\x96\xAA\x38\x2A\xC1\x12\xE8\x67\xE9\x94\x56\xD1\xCC\x16" 104 | "\xA4\xA4\x4B\xD2\x01\xA8\xC5\x52\x5B\xAF\x8D\x38\x67\xC6\x0D\x3A" 105 | "\x21\xEC\x14\xCA\x91\x29\x33\xD1\xBC\x9F\x41\x05\xE1\xB0\x2B\xB6" 106 | "\x16\x55\xBA\xBC\x7D\x71\x5B\xE9\xCB\xE6\xF1\x30\x5E\x99\x64\x76" 107 | "\x8D\x76\x21\xD1\x5B\xA1\x03\xCA\xF6\xEA\x71\x5C\x1D\x3D\xAA\x54" 108 | "\x38\x44\xE7\xC9\x5C\x82\xE3\xB0\x18\xF6\x49\xBC\x91\x09\x36\x4B" 109 | "\x0F\x06\xAD\xB8\x42\x28\x21\x3C\x30\x26\x42\x3F\x1A\x43\x7D\x85" 110 | "\xFB\x40\x4D\x95\xDF\x50\xCD\x73\x97\x28\x71\xD1\xF9\x7E\xD1\xB1" 111 | "\xF5\xAA\x5E\x4D\xB7\x4F\xB4\xD5\x75\x62\x8D\xA2\x0F\x69\x7A\x3B" 112 | "\xA9\x04\x8C\xB9\xF1\xC2\xA7\x33\x92\xBA\x53\x9C\x0F\x5C\x10\x40" 113 | "\x49\x99\xA8\x03\xB2\x12\xAD\x28\xEE\xF0\x64\x86\xB9\x40\x8B\xB9" 114 | "\x97\x45\xB2\x1D\x89\x3C\x2A\xE9\x39\x75\x88\x11\x7B\x6D\x8F\xE9" 115 | "\x90\x30\x5D\x73\x21\xB6\xBC\xFD\x5B\xA7\x2F\xEB\x4B\x18\x88\x13" 116 | "\x6A\xBE\x0B\xC6\xA5\xC6\xDA\xC7\xC8\x7E\x01\x48\xFA\xFF\x52\xD7" 117 | "\xCB\x1B\x64\x52\x61\x01\x14\x31\x2D\x57\x2B\x1B\xEE\xA4\x65\x70"; 118 | 119 | TEST_FIXTURE(HandshakeFixture, NoErrorsGeneratingCiphertext) 120 | { 121 | uint8_t ciphertext[256]; 122 | int err = ciphertext_from_nonce_and_id(nonce, id, pubkey, ciphertext); 123 | CHECK_EQUAL(0, err); 124 | } 125 | 126 | TEST(RSASelfTestSucceeds) 127 | { 128 | CHECK_EQUAL(0, rsa_self_test(0)); 129 | } 130 | 131 | TEST(MPISelfTestSucceeds) 132 | { 133 | CHECK_EQUAL(0, mpi_self_test(0)); 134 | } 135 | 136 | TEST(SHA1SelfTestSucceeds) 137 | { 138 | CHECK_EQUAL(0, sha1_self_test(0)); 139 | } 140 | 141 | TEST_FIXTURE(HandshakeFixture, FixturePublicKeyIsValid) 142 | { 143 | rsa_context rsa; 144 | init_rsa_context_with_public_key(&rsa, pubkey); 145 | CHECK_EQUAL(0, rsa_check_pubkey(&rsa)); 146 | } 147 | 148 | TEST_FIXTURE(HandshakeFixture, FixturePrivateKeyIsValid) 149 | { 150 | rsa_context rsa; 151 | init_rsa_context_with_private_key(&rsa, private_key); 152 | CHECK_EQUAL(0, rsa_check_privkey(&rsa)); 153 | } 154 | 155 | TEST_FIXTURE(HandshakeFixture, NoErrorsInRSADecryption) 156 | { 157 | uint8_t aes_credentials[40]; 158 | int err = decipher_aes_credentials(private_key, 159 | encrypted_aes_credentials, 160 | aes_credentials); 161 | CHECK_EQUAL(0, err); 162 | } 163 | 164 | TEST_FIXTURE(HandshakeFixture, RSADecryptionMatchesOpenSSLExample) 165 | { 166 | uint8_t expected[41] = 167 | "\x3E\x78\xEB\x7A\x0B\xB2\x1D\xFB\xF2\xB1\x53\x4B\x06\xE5\x66\x12" 168 | "\x14\x5A\x01\xF1\x07\x0E\x40\xA1\x11\x88\xF7\x84\xC4\x9B\xC6\x53" 169 | "\xC5\x76\x94\xFC\x1F\x3B\x7D\x72"; 170 | uint8_t aes_credentials[40]; 171 | decipher_aes_credentials(private_key, 172 | encrypted_aes_credentials, 173 | aes_credentials); 174 | CHECK_ARRAY_EQUAL(expected, aes_credentials, 40); 175 | } 176 | 177 | TEST_FIXTURE(HandshakeFixture, HMACMatchesOpenSSLExample) 178 | { 179 | uint8_t hmac[20]; 180 | uint8_t hmac_key[40]; 181 | decipher_aes_credentials(private_key, 182 | encrypted_aes_credentials, 183 | hmac_key); 184 | calculate_ciphertext_hmac(encrypted_aes_credentials, hmac_key, hmac); 185 | CHECK_ARRAY_EQUAL(expected_hmac, hmac, 20); 186 | } 187 | 188 | TEST_FIXTURE(HandshakeFixture, VerifiedSignatureIsHMAC) 189 | { 190 | int err = verify_signature(signature, pubkey, expected_hmac); 191 | CHECK_EQUAL(0, err); 192 | } 193 | -------------------------------------------------------------------------------- /tests/TestQueue.cpp: -------------------------------------------------------------------------------- 1 | #include "UnitTest++.h" 2 | #include "spark_protocol.h" 3 | 4 | SUITE(Queue) 5 | { 6 | TEST(QueueAvailableBeginsEqualToConst) 7 | { 8 | SparkProtocol spark_protocol; 9 | int size = spark_protocol.QUEUE_SIZE - 1; 10 | int available = spark_protocol.queue_bytes_available(); 11 | CHECK_EQUAL(size, available); 12 | } 13 | 14 | TEST(QueueAvailableAfterPushIsSizeMinusOne) 15 | { 16 | SparkProtocol spark_protocol; 17 | char buf[1] = {'x'}; 18 | spark_protocol.queue_push(buf, 1); 19 | int available = spark_protocol.queue_bytes_available(); 20 | CHECK_EQUAL(spark_protocol.QUEUE_SIZE - 1 - 1, available); 21 | } 22 | 23 | TEST(QueueAvailableAfterPush5Pop2IsSizeMinusThree) 24 | { 25 | SparkProtocol spark_protocol; 26 | char buf[6] = "Spark"; 27 | spark_protocol.queue_push(buf, 5); 28 | spark_protocol.queue_pop(buf, 2); 29 | int available = spark_protocol.queue_bytes_available(); 30 | CHECK_EQUAL(spark_protocol.QUEUE_SIZE - 1 - 3, available); 31 | } 32 | 33 | TEST(QueueWrapsAsRingBuffer) 34 | { 35 | SparkProtocol spark_protocol; 36 | int too_big = spark_protocol.QUEUE_SIZE + 16; 37 | char buf[too_big]; 38 | memset(buf, 42, too_big); 39 | spark_protocol.queue_push(buf, 500); 40 | spark_protocol.queue_pop(buf, 400); 41 | spark_protocol.queue_push(buf + 500, too_big - 500); 42 | int available = spark_protocol.queue_bytes_available(); 43 | // we've pushed too_big bytes and popped 400, so too_big - 400 is used 44 | CHECK_EQUAL(spark_protocol.QUEUE_SIZE - 1 - too_big + 400, available); 45 | } 46 | 47 | TEST(InitialQueueCannotOverfill) 48 | { 49 | SparkProtocol spark_protocol; 50 | int too_big = spark_protocol.QUEUE_SIZE + 16; 51 | char buf[too_big]; 52 | memset(buf, 42, too_big); 53 | int written = spark_protocol.queue_push(buf, too_big); 54 | CHECK_EQUAL(spark_protocol.QUEUE_SIZE - 1, written); 55 | } 56 | 57 | TEST(QueuePopsRequestedAmount) 58 | { 59 | SparkProtocol spark_protocol; 60 | char buf[300]; 61 | memset(buf, '*', 300); 62 | spark_protocol.queue_push(buf, 300); 63 | int popped = spark_protocol.queue_pop(buf, 300); 64 | CHECK_EQUAL(300, popped); 65 | } 66 | 67 | TEST(QueueCanCopyOversizeInStages) 68 | { 69 | SparkProtocol spark_protocol; 70 | char src_buf[900]; 71 | memset(src_buf, 'Z', 300); 72 | memset(src_buf + 300, 'a', 300); 73 | memset(src_buf + 600, 'c', 300); 74 | char dst_buf[900]; 75 | memset(dst_buf, '*', 900); 76 | int written1 = spark_protocol.queue_push(src_buf, 900); 77 | spark_protocol.queue_pop(dst_buf, written1); 78 | int written2 = spark_protocol.queue_push(src_buf + written1, 900 - written1); 79 | spark_protocol.queue_pop(dst_buf + written1, written2); 80 | CHECK_ARRAY_EQUAL(src_buf, dst_buf, 900); 81 | } 82 | 83 | TEST(FullQueueShowsZeroAvailable) 84 | { 85 | SparkProtocol spark_protocol; 86 | int size = spark_protocol.QUEUE_SIZE - 1; 87 | char buf[size]; 88 | memset(buf, '$', size); 89 | spark_protocol.queue_push(buf, size); 90 | int available = spark_protocol.queue_bytes_available(); 91 | CHECK_EQUAL(0, available); 92 | } 93 | 94 | TEST(QueueCannotPopMoreThanFilled) 95 | { 96 | SparkProtocol spark_protocol; 97 | char buf[1]; 98 | int popped = spark_protocol.queue_pop(buf, 1); 99 | CHECK_EQUAL(0, popped); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /tests/TestStateMachine.cpp: -------------------------------------------------------------------------------- 1 | #include "UnitTest++.h" 2 | #include "spark_protocol.h" 3 | 4 | SUITE(StateMachine) 5 | { 6 | TEST(InitialStateIs_READ_NONCE) 7 | { 8 | SparkProtocol spark_protocol; 9 | ProtocolState::Enum state = spark_protocol.state(); 10 | CHECK_EQUAL(ProtocolState::READ_NONCE, state); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/TestUserFunctions.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file TestUserFunctions.cpp 4 | * @authors Zachary Crockett 5 | * @version V1.0.0 6 | * @date 10-Jan-2014 7 | * @brief User Function Tests 8 | ****************************************************************************** 9 | Copyright (c) 2014 Spark Labs, Inc. All rights reserved. 10 | 11 | This library is free software; you can redistribute it and/or 12 | modify it under the terms of the GNU Lesser General Public 13 | License as published by the Free Software Foundation, either 14 | version 3 of the License, or (at your option) any later version. 15 | 16 | This library is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public 22 | License along with this library; if not, see . 23 | ****************************************************************************** 24 | */ 25 | 26 | #include "UnitTest++.h" 27 | #include "spark_protocol.h" 28 | #include "ConstructorFixture.h" 29 | 30 | SUITE(UserFunctions) 31 | { 32 | TEST_FIXTURE(ConstructorFixture, ArgLen63Succeeds) 33 | { 34 | uint8_t function_call[82] = { 35 | 0x00, 0x50, 36 | 0x94, 0x57, 0x84, 0x8C, 0xDF, 0x53, 0xC1, 0xC2, 37 | 0xF3, 0x59, 0x0C, 0x64, 0xDF, 0xBB, 0x19, 0xB1, 38 | 0x58, 0x55, 0x63, 0x4D, 0x4C, 0x5F, 0x83, 0xA4, 39 | 0xC9, 0x5B, 0x0A, 0x94, 0xDA, 0x62, 0x58, 0x58, 40 | 0x58, 0x1E, 0x17, 0xED, 0x66, 0x0A, 0x3E, 0xEB, 41 | 0x12, 0x10, 0x4C, 0x91, 0x1B, 0xCE, 0x7B, 0x5A, 42 | 0x92, 0xD0, 0x00, 0x45, 0x91, 0x28, 0x5A, 0x99, 43 | 0xE0, 0xAD, 0x43, 0x24, 0x28, 0x46, 0xB6, 0x94, 44 | 0x30, 0x80, 0x6C, 0xD8, 0xF9, 0x0D, 0x15, 0x6F, 45 | 0xFD, 0x5E, 0xCE, 0xB2, 0xFE, 0x57, 0xE8, 0xE3 }; 46 | memcpy(message_to_receive, function_call, 82); 47 | spark_protocol.handshake(); 48 | bytes_received[0] = bytes_sent[0] = 0; 49 | bool success = spark_protocol.event_loop(); 50 | CHECK(success); 51 | } 52 | 53 | TEST_FIXTURE(ConstructorFixture, ArgLen64Fails) 54 | { 55 | uint8_t function_call[82] = { 56 | 0x00, 0x50, 57 | 0x46, 0xE5, 0xBA, 0xEB, 0xD5, 0x31, 0xA3, 0x03, 58 | 0x42, 0x59, 0x19, 0x08, 0x35, 0xCF, 0xC1, 0x63, 59 | 0xF0, 0xED, 0x7F, 0x75, 0x39, 0xFF, 0x6E, 0xDD, 60 | 0x6E, 0xD1, 0x50, 0xA2, 0xAC, 0xC0, 0x39, 0x77, 61 | 0xA3, 0x06, 0x70, 0x88, 0xF8, 0xAC, 0x68, 0x69, 62 | 0xCA, 0xCD, 0xAC, 0x7B, 0x62, 0x74, 0xAF, 0x53, 63 | 0x3E, 0xE2, 0xC4, 0x21, 0x07, 0x8C, 0x67, 0xD1, 64 | 0x3E, 0x2D, 0x6A, 0x76, 0x70, 0x2D, 0x57, 0x55, 65 | 0x82, 0x89, 0xD0, 0xC2, 0xB9, 0x8E, 0x1C, 0xE2, 66 | 0x6E, 0xE3, 0x5E, 0x20, 0xC2, 0x7B, 0x19, 0x1D }; 67 | memcpy(message_to_receive, function_call, 82); 68 | spark_protocol.handshake(); 69 | bytes_received[0] = bytes_sent[0] = 0; 70 | bool success = spark_protocol.event_loop(); 71 | CHECK(!success); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /tests/UnitTest++/Makefile: -------------------------------------------------------------------------------- 1 | CXX = g++ 2 | CXXFLAGS ?= -g -Wall -W -Winline -ansi 3 | LDFLAGS ?= 4 | SED = sed 5 | MV = mv 6 | RM = rm 7 | 8 | .SUFFIXES: .o .cpp 9 | 10 | lib = libUnitTest++.a 11 | 12 | src = src/AssertException.cpp \ 13 | src/Test.cpp \ 14 | src/Checks.cpp \ 15 | src/TestRunner.cpp \ 16 | src/TestResults.cpp \ 17 | src/TestReporter.cpp \ 18 | src/TestReporterStdout.cpp \ 19 | src/ReportAssert.cpp \ 20 | src/TestList.cpp \ 21 | src/TimeConstraint.cpp \ 22 | src/TestDetails.cpp \ 23 | src/MemoryOutStream.cpp \ 24 | src/DeferredTestReporter.cpp \ 25 | src/DeferredTestResult.cpp \ 26 | src/XmlTestReporter.cpp \ 27 | src/CurrentTest.cpp 28 | 29 | ifeq ($(MSYSTEM), MINGW32) 30 | src += src/Win32/TimeHelpers.cpp 31 | else 32 | src += src/Posix/SignalTranslator.cpp \ 33 | src/Posix/TimeHelpers.cpp 34 | endif 35 | 36 | objects = $(patsubst %.cpp, %.o, $(src)) 37 | dependencies = $(subst .o,.d,$(objects)) 38 | 39 | define make-depend 40 | $(CXX) $(CXXFLAGS) -M $1 | \ 41 | $(SED) -e 's,\($(notdir $2)\) *:,$(dir $2)\1: ,' > $3.tmp 42 | $(SED) -e 's/#.*//' \ 43 | -e 's/^[^:]*: *//' \ 44 | -e 's/ *\\$$//' \ 45 | -e '/^$$/ d' \ 46 | -e 's/$$/ :/' $3.tmp >> $3.tmp 47 | $(MV) $3.tmp $3 48 | endef 49 | 50 | 51 | all: $(lib) 52 | 53 | 54 | $(lib): $(objects) 55 | @echo Creating $(lib) library... 56 | @ar cr $(lib) $(objects) 57 | 58 | clean: 59 | -@$(RM) $(objects) $(dependencies) $(lib) 2> /dev/null 60 | 61 | %.o : %.cpp 62 | @echo $< 63 | @$(call make-depend,$<,$@,$(subst .o,.d,$@)) 64 | @$(CXX) $(CXXFLAGS) -c $< -o $(patsubst %.cpp, %.o, $<) 65 | 66 | 67 | ifneq "$(MAKECMDGOALS)" "clean" 68 | -include $(dependencies) 69 | endif 70 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/AssertException.cpp: -------------------------------------------------------------------------------- 1 | #include "AssertException.h" 2 | #include 3 | 4 | namespace UnitTest { 5 | 6 | AssertException::AssertException(char const* description, char const* filename, int lineNumber) 7 | : m_lineNumber(lineNumber) 8 | { 9 | using namespace std; 10 | 11 | strcpy(m_description, description); 12 | strcpy(m_filename, filename); 13 | } 14 | 15 | AssertException::~AssertException() throw() 16 | { 17 | } 18 | 19 | char const* AssertException::what() const throw() 20 | { 21 | return m_description; 22 | } 23 | 24 | char const* AssertException::Filename() const 25 | { 26 | return m_filename; 27 | } 28 | 29 | int AssertException::LineNumber() const 30 | { 31 | return m_lineNumber; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/AssertException.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_ASSERTEXCEPTION_H 2 | #define UNITTEST_ASSERTEXCEPTION_H 3 | 4 | #include 5 | 6 | 7 | namespace UnitTest { 8 | 9 | class AssertException : public std::exception 10 | { 11 | public: 12 | AssertException(char const* description, char const* filename, int lineNumber); 13 | virtual ~AssertException() throw(); 14 | 15 | virtual char const* what() const throw(); 16 | 17 | char const* Filename() const; 18 | int LineNumber() const; 19 | 20 | private: 21 | char m_description[512]; 22 | char m_filename[256]; 23 | int m_lineNumber; 24 | }; 25 | 26 | } 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/CheckMacros.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_CHECKMACROS_H 2 | #define UNITTEST_CHECKMACROS_H 3 | 4 | #include "Checks.h" 5 | #include "AssertException.h" 6 | #include "MemoryOutStream.h" 7 | #include "TestDetails.h" 8 | #include "CurrentTest.h" 9 | 10 | #ifdef CHECK 11 | #error UnitTest++ redefines CHECK 12 | #endif 13 | 14 | #ifdef CHECK_EQUAL 15 | #error UnitTest++ redefines CHECK_EQUAL 16 | #endif 17 | 18 | #ifdef CHECK_CLOSE 19 | #error UnitTest++ redefines CHECK_CLOSE 20 | #endif 21 | 22 | #ifdef CHECK_ARRAY_EQUAL 23 | #error UnitTest++ redefines CHECK_ARRAY_EQUAL 24 | #endif 25 | 26 | #ifdef CHECK_ARRAY_CLOSE 27 | #error UnitTest++ redefines CHECK_ARRAY_CLOSE 28 | #endif 29 | 30 | #ifdef CHECK_ARRAY2D_CLOSE 31 | #error UnitTest++ redefines CHECK_ARRAY2D_CLOSE 32 | #endif 33 | 34 | #define CHECK(value) \ 35 | do \ 36 | { \ 37 | try { \ 38 | if (!UnitTest::Check(value)) \ 39 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), #value); \ 40 | } \ 41 | catch (...) { \ 42 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ 43 | "Unhandled exception in CHECK(" #value ")"); \ 44 | } \ 45 | } while (0) 46 | 47 | #define CHECK_EQUAL(expected, actual) \ 48 | do \ 49 | { \ 50 | try { \ 51 | UnitTest::CheckEqual(*UnitTest::CurrentTest::Results(), expected, actual, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \ 52 | } \ 53 | catch (...) { \ 54 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ 55 | "Unhandled exception in CHECK_EQUAL(" #expected ", " #actual ")"); \ 56 | } \ 57 | } while (0) 58 | 59 | #define CHECK_CLOSE(expected, actual, tolerance) \ 60 | do \ 61 | { \ 62 | try { \ 63 | UnitTest::CheckClose(*UnitTest::CurrentTest::Results(), expected, actual, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \ 64 | } \ 65 | catch (...) { \ 66 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ 67 | "Unhandled exception in CHECK_CLOSE(" #expected ", " #actual ")"); \ 68 | } \ 69 | } while (0) 70 | 71 | #define CHECK_ARRAY_EQUAL(expected, actual, count) \ 72 | do \ 73 | { \ 74 | try { \ 75 | UnitTest::CheckArrayEqual(*UnitTest::CurrentTest::Results(), expected, actual, count, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \ 76 | } \ 77 | catch (...) { \ 78 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ 79 | "Unhandled exception in CHECK_ARRAY_EQUAL(" #expected ", " #actual ")"); \ 80 | } \ 81 | } while (0) 82 | 83 | #define CHECK_ARRAY_CLOSE(expected, actual, count, tolerance) \ 84 | do \ 85 | { \ 86 | try { \ 87 | UnitTest::CheckArrayClose(*UnitTest::CurrentTest::Results(), expected, actual, count, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \ 88 | } \ 89 | catch (...) { \ 90 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ 91 | "Unhandled exception in CHECK_ARRAY_CLOSE(" #expected ", " #actual ")"); \ 92 | } \ 93 | } while (0) 94 | 95 | #define CHECK_ARRAY2D_CLOSE(expected, actual, rows, columns, tolerance) \ 96 | do \ 97 | { \ 98 | try { \ 99 | UnitTest::CheckArray2DClose(*UnitTest::CurrentTest::Results(), expected, actual, rows, columns, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \ 100 | } \ 101 | catch (...) { \ 102 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ 103 | "Unhandled exception in CHECK_ARRAY_CLOSE(" #expected ", " #actual ")"); \ 104 | } \ 105 | } while (0) 106 | 107 | 108 | #define CHECK_THROW(expression, ExpectedExceptionType) \ 109 | do \ 110 | { \ 111 | bool caught_ = false; \ 112 | try { expression; } \ 113 | catch (ExpectedExceptionType const&) { caught_ = true; } \ 114 | catch (...) {} \ 115 | if (!caught_) \ 116 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), "Expected exception: \"" #ExpectedExceptionType "\" not thrown"); \ 117 | } while(0) 118 | 119 | #define CHECK_ASSERT(expression) \ 120 | CHECK_THROW(expression, UnitTest::AssertException); 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/Checks.cpp: -------------------------------------------------------------------------------- 1 | #include "Checks.h" 2 | #include 3 | 4 | namespace UnitTest { 5 | 6 | namespace { 7 | 8 | void CheckStringsEqual(TestResults& results, char const* expected, char const* actual, 9 | TestDetails const& details) 10 | { 11 | using namespace std; 12 | 13 | if (strcmp(expected, actual)) 14 | { 15 | UnitTest::MemoryOutStream stream; 16 | stream << "Expected " << expected << " but was " << actual; 17 | 18 | results.OnTestFailure(details, stream.GetText()); 19 | } 20 | } 21 | 22 | } 23 | 24 | 25 | void CheckEqual(TestResults& results, char const* expected, char const* actual, 26 | TestDetails const& details) 27 | { 28 | CheckStringsEqual(results, expected, actual, details); 29 | } 30 | 31 | void CheckEqual(TestResults& results, char* expected, char* actual, 32 | TestDetails const& details) 33 | { 34 | CheckStringsEqual(results, expected, actual, details); 35 | } 36 | 37 | void CheckEqual(TestResults& results, char* expected, char const* actual, 38 | TestDetails const& details) 39 | { 40 | CheckStringsEqual(results, expected, actual, details); 41 | } 42 | 43 | void CheckEqual(TestResults& results, char const* expected, char* actual, 44 | TestDetails const& details) 45 | { 46 | CheckStringsEqual(results, expected, actual, details); 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/Checks.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_CHECKS_H 2 | #define UNITTEST_CHECKS_H 3 | 4 | #include "Config.h" 5 | #include "TestResults.h" 6 | #include "MemoryOutStream.h" 7 | 8 | namespace UnitTest { 9 | 10 | 11 | template< typename Value > 12 | bool Check(Value const value) 13 | { 14 | return !!value; // doing double negative to avoid silly VS warnings 15 | } 16 | 17 | 18 | template< typename Expected, typename Actual > 19 | void CheckEqual(TestResults& results, Expected const& expected, Actual const& actual, TestDetails const& details) 20 | { 21 | if (!(expected == actual)) 22 | { 23 | UnitTest::MemoryOutStream stream; 24 | stream << "Expected " << expected << " but was " << actual; 25 | 26 | results.OnTestFailure(details, stream.GetText()); 27 | } 28 | } 29 | 30 | void CheckEqual(TestResults& results, char const* expected, char const* actual, TestDetails const& details); 31 | 32 | void CheckEqual(TestResults& results, char* expected, char* actual, TestDetails const& details); 33 | 34 | void CheckEqual(TestResults& results, char* expected, char const* actual, TestDetails const& details); 35 | 36 | void CheckEqual(TestResults& results, char const* expected, char* actual, TestDetails const& details); 37 | 38 | template< typename Expected, typename Actual, typename Tolerance > 39 | bool AreClose(Expected const& expected, Actual const& actual, Tolerance const& tolerance) 40 | { 41 | return (actual >= (expected - tolerance)) && (actual <= (expected + tolerance)); 42 | } 43 | 44 | template< typename Expected, typename Actual, typename Tolerance > 45 | void CheckClose(TestResults& results, Expected const& expected, Actual const& actual, Tolerance const& tolerance, 46 | TestDetails const& details) 47 | { 48 | if (!AreClose(expected, actual, tolerance)) 49 | { 50 | UnitTest::MemoryOutStream stream; 51 | stream << "Expected " << expected << " +/- " << tolerance << " but was " << actual; 52 | 53 | results.OnTestFailure(details, stream.GetText()); 54 | } 55 | } 56 | 57 | 58 | template< typename Expected, typename Actual > 59 | void CheckArrayEqual(TestResults& results, Expected const& expected, Actual const& actual, 60 | int const count, TestDetails const& details) 61 | { 62 | bool equal = true; 63 | for (int i = 0; i < count; ++i) 64 | equal &= (expected[i] == actual[i]); 65 | 66 | if (!equal) 67 | { 68 | UnitTest::MemoryOutStream stream; 69 | 70 | stream << "Expected [ "; 71 | 72 | for (int expectedIndex = 0; expectedIndex < count; ++expectedIndex) 73 | stream << expected[expectedIndex] << " "; 74 | 75 | stream << "] but was [ "; 76 | 77 | for (int actualIndex = 0; actualIndex < count; ++actualIndex) 78 | stream << actual[actualIndex] << " "; 79 | 80 | stream << "]"; 81 | 82 | results.OnTestFailure(details, stream.GetText()); 83 | } 84 | } 85 | 86 | template< typename Expected, typename Actual, typename Tolerance > 87 | bool ArrayAreClose(Expected const& expected, Actual const& actual, int const count, Tolerance const& tolerance) 88 | { 89 | bool equal = true; 90 | for (int i = 0; i < count; ++i) 91 | equal &= AreClose(expected[i], actual[i], tolerance); 92 | return equal; 93 | } 94 | 95 | template< typename Expected, typename Actual, typename Tolerance > 96 | void CheckArrayClose(TestResults& results, Expected const& expected, Actual const& actual, 97 | int const count, Tolerance const& tolerance, TestDetails const& details) 98 | { 99 | bool equal = ArrayAreClose(expected, actual, count, tolerance); 100 | 101 | if (!equal) 102 | { 103 | UnitTest::MemoryOutStream stream; 104 | 105 | stream << "Expected [ "; 106 | for (int expectedIndex = 0; expectedIndex < count; ++expectedIndex) 107 | stream << expected[expectedIndex] << " "; 108 | stream << "] +/- " << tolerance << " but was [ "; 109 | 110 | for (int actualIndex = 0; actualIndex < count; ++actualIndex) 111 | stream << actual[actualIndex] << " "; 112 | stream << "]"; 113 | 114 | results.OnTestFailure(details, stream.GetText()); 115 | } 116 | } 117 | 118 | template< typename Expected, typename Actual, typename Tolerance > 119 | void CheckArray2DClose(TestResults& results, Expected const& expected, Actual const& actual, 120 | int const rows, int const columns, Tolerance const& tolerance, TestDetails const& details) 121 | { 122 | bool equal = true; 123 | for (int i = 0; i < rows; ++i) 124 | equal &= ArrayAreClose(expected[i], actual[i], columns, tolerance); 125 | 126 | if (!equal) 127 | { 128 | UnitTest::MemoryOutStream stream; 129 | 130 | stream << "Expected [ "; 131 | 132 | for (int expectedRow = 0; expectedRow < rows; ++expectedRow) 133 | { 134 | stream << "[ "; 135 | for (int expectedColumn = 0; expectedColumn < columns; ++expectedColumn) 136 | stream << expected[expectedRow][expectedColumn] << " "; 137 | stream << "] "; 138 | } 139 | 140 | stream << "] +/- " << tolerance << " but was [ "; 141 | 142 | for (int actualRow = 0; actualRow < rows; ++actualRow) 143 | { 144 | stream << "[ "; 145 | for (int actualColumn = 0; actualColumn < columns; ++actualColumn) 146 | stream << actual[actualRow][actualColumn] << " "; 147 | stream << "] "; 148 | } 149 | 150 | stream << "]"; 151 | 152 | results.OnTestFailure(details, stream.GetText()); 153 | } 154 | } 155 | 156 | } 157 | 158 | #endif 159 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/Config.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_CONFIG_H 2 | #define UNITTEST_CONFIG_H 3 | 4 | // Standard defines documented here: http://predef.sourceforge.net 5 | 6 | #if defined(_MSC_VER) 7 | #pragma warning(disable:4127) // conditional expression is constant 8 | #pragma warning(disable:4702) // unreachable code 9 | #pragma warning(disable:4722) // destructor never returns, potential memory leak 10 | 11 | #if (_MSC_VER == 1200) // VC6 12 | #pragma warning(disable:4786) 13 | #pragma warning(disable:4290) 14 | #endif 15 | #endif 16 | 17 | #if defined(unix) || defined(__unix__) || defined(__unix) || defined(linux) || \ 18 | defined(__APPLE__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 19 | #define UNITTEST_POSIX 20 | #endif 21 | 22 | #if defined(__MINGW32__) 23 | #define UNITTEST_MINGW 24 | #endif 25 | 26 | // by default, MemoryOutStream is implemented in terms of std::ostringstream, which can be expensive. 27 | // uncomment this line to use the custom MemoryOutStream (no deps on std::ostringstream). 28 | 29 | //#define UNITTEST_USE_CUSTOM_STREAMS 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/CurrentTest.cpp: -------------------------------------------------------------------------------- 1 | #include "CurrentTest.h" 2 | #include 3 | 4 | namespace UnitTest { 5 | 6 | TestResults*& CurrentTest::Results() 7 | { 8 | static TestResults* testResults = NULL; 9 | return testResults; 10 | } 11 | 12 | const TestDetails*& CurrentTest::Details() 13 | { 14 | static const TestDetails* testDetails = NULL; 15 | return testDetails; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/CurrentTest.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_CURRENTTESTRESULTS_H 2 | #define UNITTEST_CURRENTTESTRESULTS_H 3 | 4 | namespace UnitTest { 5 | 6 | class TestResults; 7 | class TestDetails; 8 | 9 | namespace CurrentTest 10 | { 11 | TestResults*& Results(); 12 | const TestDetails*& Details(); 13 | } 14 | 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/DeferredTestReporter.cpp: -------------------------------------------------------------------------------- 1 | #include "DeferredTestReporter.h" 2 | #include "TestDetails.h" 3 | 4 | using namespace UnitTest; 5 | 6 | void DeferredTestReporter::ReportTestStart(TestDetails const& details) 7 | { 8 | m_results.push_back(DeferredTestResult(details.suiteName, details.testName)); 9 | } 10 | 11 | void DeferredTestReporter::ReportFailure(TestDetails const& details, char const* failure) 12 | { 13 | DeferredTestResult& r = m_results.back(); 14 | r.failed = true; 15 | r.failures.push_back(DeferredTestResult::Failure(details.lineNumber, failure)); 16 | r.failureFile = details.filename; 17 | } 18 | 19 | void DeferredTestReporter::ReportTestFinish(TestDetails const&, float secondsElapsed) 20 | { 21 | DeferredTestResult& r = m_results.back(); 22 | r.timeElapsed = secondsElapsed; 23 | } 24 | 25 | DeferredTestReporter::DeferredTestResultList& DeferredTestReporter::GetResults() 26 | { 27 | return m_results; 28 | } 29 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/DeferredTestReporter.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_DEFERREDTESTREPORTER_H 2 | #define UNITTEST_DEFERREDTESTREPORTER_H 3 | 4 | #include "TestReporter.h" 5 | #include "DeferredTestResult.h" 6 | #include "Config.h" 7 | 8 | #include 9 | 10 | namespace UnitTest 11 | { 12 | 13 | class DeferredTestReporter : public TestReporter 14 | { 15 | public: 16 | virtual void ReportTestStart(TestDetails const& details); 17 | virtual void ReportFailure(TestDetails const& details, char const* failure); 18 | virtual void ReportTestFinish(TestDetails const& details, float secondsElapsed); 19 | 20 | typedef std::vector< DeferredTestResult > DeferredTestResultList; 21 | DeferredTestResultList& GetResults(); 22 | 23 | private: 24 | DeferredTestResultList m_results; 25 | }; 26 | 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/DeferredTestResult.cpp: -------------------------------------------------------------------------------- 1 | #include "DeferredTestResult.h" 2 | #include "Config.h" 3 | 4 | namespace UnitTest 5 | { 6 | 7 | DeferredTestResult::DeferredTestResult() 8 | : suiteName("") 9 | , testName("") 10 | , failureFile("") 11 | , timeElapsed(0.0f) 12 | , failed(false) 13 | { 14 | } 15 | 16 | DeferredTestResult::DeferredTestResult(char const* suite, char const* test) 17 | : suiteName(suite) 18 | , testName(test) 19 | , failureFile("") 20 | , timeElapsed(0.0f) 21 | , failed(false) 22 | { 23 | } 24 | 25 | DeferredTestResult::~DeferredTestResult() 26 | { 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/DeferredTestResult.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_DEFERREDTESTRESULT_H 2 | #define UNITTEST_DEFERREDTESTRESULT_H 3 | 4 | #include "Config.h" 5 | 6 | #include 7 | #include 8 | 9 | namespace UnitTest 10 | { 11 | 12 | struct DeferredTestResult 13 | { 14 | DeferredTestResult(); 15 | DeferredTestResult(char const* suite, char const* test); 16 | ~DeferredTestResult(); 17 | 18 | std::string suiteName; 19 | std::string testName; 20 | std::string failureFile; 21 | 22 | typedef std::pair< int, std::string > Failure; 23 | typedef std::vector< Failure > FailureVec; 24 | FailureVec failures; 25 | 26 | float timeElapsed; 27 | bool failed; 28 | }; 29 | 30 | } 31 | 32 | #endif //UNITTEST_DEFERREDTESTRESULT_H 33 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/ExecuteTest.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_EXECUTE_TEST_H 2 | #define UNITTEST_EXECUTE_TEST_H 3 | 4 | #include "TestDetails.h" 5 | #include "MemoryOutStream.h" 6 | #include "AssertException.h" 7 | #include "CurrentTest.h" 8 | 9 | #ifdef UNITTEST_POSIX 10 | #include "Posix/SignalTranslator.h" 11 | #endif 12 | 13 | namespace UnitTest { 14 | 15 | template< typename T > 16 | void ExecuteTest(T& testObject, TestDetails const& details) 17 | { 18 | CurrentTest::Details() = &details; 19 | 20 | try 21 | { 22 | #ifdef UNITTEST_POSIX 23 | UNITTEST_THROW_SIGNALS 24 | #endif 25 | testObject.RunImpl(); 26 | } 27 | catch (AssertException const& e) 28 | { 29 | CurrentTest::Results()->OnTestFailure( 30 | TestDetails(details.testName, details.suiteName, e.Filename(), e.LineNumber()), e.what()); 31 | } 32 | catch (std::exception const& e) 33 | { 34 | MemoryOutStream stream; 35 | stream << "Unhandled exception: " << e.what(); 36 | CurrentTest::Results()->OnTestFailure(details, stream.GetText()); 37 | } 38 | catch (...) 39 | { 40 | CurrentTest::Results()->OnTestFailure(details, "Unhandled exception: Crash!"); 41 | } 42 | } 43 | 44 | } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/MemoryOutStream.cpp: -------------------------------------------------------------------------------- 1 | #include "MemoryOutStream.h" 2 | 3 | #ifndef UNITTEST_USE_CUSTOM_STREAMS 4 | 5 | 6 | namespace UnitTest { 7 | 8 | char const* MemoryOutStream::GetText() const 9 | { 10 | m_text = this->str(); 11 | return m_text.c_str(); 12 | } 13 | 14 | 15 | } 16 | 17 | 18 | #else 19 | 20 | 21 | #include 22 | #include 23 | 24 | namespace UnitTest { 25 | 26 | namespace { 27 | 28 | template 29 | void FormatToStream(MemoryOutStream& stream, char const* format, ValueType const& value) 30 | { 31 | using namespace std; 32 | 33 | char txt[32]; 34 | sprintf(txt, format, value); 35 | stream << txt; 36 | } 37 | 38 | int RoundUpToMultipleOfPow2Number (int n, int pow2Number) 39 | { 40 | return (n + (pow2Number - 1)) & ~(pow2Number - 1); 41 | } 42 | 43 | } 44 | 45 | 46 | MemoryOutStream::MemoryOutStream(int const size) 47 | : m_capacity (0) 48 | , m_buffer (0) 49 | 50 | { 51 | GrowBuffer(size); 52 | } 53 | 54 | MemoryOutStream::~MemoryOutStream() 55 | { 56 | delete [] m_buffer; 57 | } 58 | 59 | char const* MemoryOutStream::GetText() const 60 | { 61 | return m_buffer; 62 | } 63 | 64 | MemoryOutStream& MemoryOutStream::operator << (char const* txt) 65 | { 66 | using namespace std; 67 | 68 | int const bytesLeft = m_capacity - (int)strlen(m_buffer); 69 | int const bytesRequired = (int)strlen(txt) + 1; 70 | 71 | if (bytesRequired > bytesLeft) 72 | { 73 | int const requiredCapacity = bytesRequired + m_capacity - bytesLeft; 74 | GrowBuffer(requiredCapacity); 75 | } 76 | 77 | strcat(m_buffer, txt); 78 | return *this; 79 | } 80 | 81 | MemoryOutStream& MemoryOutStream::operator << (int const n) 82 | { 83 | FormatToStream(*this, "%i", n); 84 | return *this; 85 | } 86 | 87 | MemoryOutStream& MemoryOutStream::operator << (long const n) 88 | { 89 | FormatToStream(*this, "%li", n); 90 | return *this; 91 | } 92 | 93 | MemoryOutStream& MemoryOutStream::operator << (unsigned long const n) 94 | { 95 | FormatToStream(*this, "%lu", n); 96 | return *this; 97 | } 98 | 99 | MemoryOutStream& MemoryOutStream::operator << (float const f) 100 | { 101 | FormatToStream(*this, "%ff", f); 102 | return *this; 103 | } 104 | 105 | MemoryOutStream& MemoryOutStream::operator << (void const* p) 106 | { 107 | FormatToStream(*this, "%p", p); 108 | return *this; 109 | } 110 | 111 | MemoryOutStream& MemoryOutStream::operator << (unsigned int const s) 112 | { 113 | FormatToStream(*this, "%u", s); 114 | return *this; 115 | } 116 | 117 | MemoryOutStream& MemoryOutStream::operator <<(double const d) 118 | { 119 | FormatToStream(*this, "%f", d); 120 | return *this; 121 | } 122 | 123 | int MemoryOutStream::GetCapacity() const 124 | { 125 | return m_capacity; 126 | } 127 | 128 | 129 | void MemoryOutStream::GrowBuffer(int const desiredCapacity) 130 | { 131 | int const newCapacity = RoundUpToMultipleOfPow2Number(desiredCapacity, GROW_CHUNK_SIZE); 132 | 133 | using namespace std; 134 | 135 | char* buffer = new char[newCapacity]; 136 | if (m_buffer) 137 | strcpy(buffer, m_buffer); 138 | else 139 | strcpy(buffer, ""); 140 | 141 | delete [] m_buffer; 142 | m_buffer = buffer; 143 | m_capacity = newCapacity; 144 | } 145 | 146 | } 147 | 148 | 149 | #endif 150 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/MemoryOutStream.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_MEMORYOUTSTREAM_H 2 | #define UNITTEST_MEMORYOUTSTREAM_H 3 | 4 | #include "Config.h" 5 | 6 | #ifndef UNITTEST_USE_CUSTOM_STREAMS 7 | 8 | #include 9 | 10 | namespace UnitTest 11 | { 12 | 13 | class MemoryOutStream : public std::ostringstream 14 | { 15 | public: 16 | MemoryOutStream() {} 17 | ~MemoryOutStream() {} 18 | char const* GetText() const; 19 | 20 | private: 21 | MemoryOutStream(MemoryOutStream const&); 22 | void operator =(MemoryOutStream const&); 23 | 24 | mutable std::string m_text; 25 | }; 26 | 27 | } 28 | 29 | #else 30 | 31 | #include 32 | 33 | namespace UnitTest 34 | { 35 | 36 | class MemoryOutStream 37 | { 38 | public: 39 | explicit MemoryOutStream(int const size = 256); 40 | ~MemoryOutStream(); 41 | 42 | char const* GetText() const; 43 | 44 | MemoryOutStream& operator << (char const* txt); 45 | MemoryOutStream& operator << (int n); 46 | MemoryOutStream& operator << (long n); 47 | MemoryOutStream& operator << (unsigned long n); 48 | MemoryOutStream& operator << (float f); 49 | MemoryOutStream& operator << (double d); 50 | MemoryOutStream& operator << (void const* p); 51 | MemoryOutStream& operator << (unsigned int s); 52 | 53 | enum { GROW_CHUNK_SIZE = 32 }; 54 | int GetCapacity() const; 55 | 56 | private: 57 | void operator= (MemoryOutStream const&); 58 | void GrowBuffer(int capacity); 59 | 60 | int m_capacity; 61 | char* m_buffer; 62 | }; 63 | 64 | } 65 | 66 | #endif 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/Posix/SignalTranslator.cpp: -------------------------------------------------------------------------------- 1 | #include "SignalTranslator.h" 2 | 3 | namespace UnitTest { 4 | 5 | sigjmp_buf* SignalTranslator::s_jumpTarget = 0; 6 | 7 | namespace { 8 | 9 | void SignalHandler(int sig) 10 | { 11 | siglongjmp(*SignalTranslator::s_jumpTarget, sig ); 12 | } 13 | 14 | } 15 | 16 | 17 | SignalTranslator::SignalTranslator() 18 | { 19 | m_oldJumpTarget = s_jumpTarget; 20 | s_jumpTarget = &m_currentJumpTarget; 21 | 22 | struct sigaction action; 23 | action.sa_flags = 0; 24 | action.sa_handler = SignalHandler; 25 | sigemptyset( &action.sa_mask ); 26 | 27 | sigaction( SIGSEGV, &action, &m_old_SIGSEGV_action ); 28 | sigaction( SIGFPE , &action, &m_old_SIGFPE_action ); 29 | sigaction( SIGTRAP, &action, &m_old_SIGTRAP_action ); 30 | sigaction( SIGBUS , &action, &m_old_SIGBUS_action ); 31 | sigaction( SIGILL , &action, &m_old_SIGBUS_action ); 32 | } 33 | 34 | SignalTranslator::~SignalTranslator() 35 | { 36 | sigaction( SIGILL , &m_old_SIGBUS_action , 0 ); 37 | sigaction( SIGBUS , &m_old_SIGBUS_action , 0 ); 38 | sigaction( SIGTRAP, &m_old_SIGTRAP_action, 0 ); 39 | sigaction( SIGFPE , &m_old_SIGFPE_action , 0 ); 40 | sigaction( SIGSEGV, &m_old_SIGSEGV_action, 0 ); 41 | 42 | s_jumpTarget = m_oldJumpTarget; 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/Posix/SignalTranslator.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_SIGNALTRANSLATOR_H 2 | #define UNITTEST_SIGNALTRANSLATOR_H 3 | 4 | #include 5 | #include 6 | 7 | namespace UnitTest { 8 | 9 | class SignalTranslator 10 | { 11 | public: 12 | SignalTranslator(); 13 | ~SignalTranslator(); 14 | 15 | static sigjmp_buf* s_jumpTarget; 16 | 17 | private: 18 | sigjmp_buf m_currentJumpTarget; 19 | sigjmp_buf* m_oldJumpTarget; 20 | 21 | struct sigaction m_old_SIGFPE_action; 22 | struct sigaction m_old_SIGTRAP_action; 23 | struct sigaction m_old_SIGSEGV_action; 24 | struct sigaction m_old_SIGBUS_action; 25 | struct sigaction m_old_SIGABRT_action; 26 | struct sigaction m_old_SIGALRM_action; 27 | }; 28 | 29 | #if !defined (__GNUC__) 30 | #define UNITTEST_EXTENSION 31 | #else 32 | #define UNITTEST_EXTENSION __extension__ 33 | #endif 34 | 35 | #define UNITTEST_THROW_SIGNALS \ 36 | UnitTest::SignalTranslator sig; \ 37 | if (UNITTEST_EXTENSION sigsetjmp(*UnitTest::SignalTranslator::s_jumpTarget, 1) != 0) \ 38 | throw ("Unhandled system exception"); 39 | 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/Posix/TimeHelpers.cpp: -------------------------------------------------------------------------------- 1 | #include "TimeHelpers.h" 2 | #include 3 | 4 | namespace UnitTest { 5 | 6 | Timer::Timer() 7 | { 8 | m_startTime.tv_sec = 0; 9 | m_startTime.tv_usec = 0; 10 | } 11 | 12 | void Timer::Start() 13 | { 14 | gettimeofday(&m_startTime, 0); 15 | } 16 | 17 | double Timer::GetTimeInMs() const 18 | { 19 | struct timeval currentTime; 20 | gettimeofday(¤tTime, 0); 21 | 22 | double const dsecs = currentTime.tv_sec - m_startTime.tv_sec; 23 | double const dus = currentTime.tv_usec - m_startTime.tv_usec; 24 | 25 | return (dsecs * 1000.0) + (dus / 1000.0); 26 | } 27 | 28 | void TimeHelpers::SleepMs(int ms) 29 | { 30 | usleep(ms * 1000); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/Posix/TimeHelpers.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TIMEHELPERS_H 2 | #define UNITTEST_TIMEHELPERS_H 3 | 4 | #include 5 | 6 | namespace UnitTest { 7 | 8 | class Timer 9 | { 10 | public: 11 | Timer(); 12 | void Start(); 13 | double GetTimeInMs() const; 14 | 15 | private: 16 | struct timeval m_startTime; 17 | }; 18 | 19 | 20 | namespace TimeHelpers 21 | { 22 | void SleepMs (int ms); 23 | } 24 | 25 | 26 | } 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/ReportAssert.cpp: -------------------------------------------------------------------------------- 1 | #include "ReportAssert.h" 2 | #include "AssertException.h" 3 | 4 | namespace UnitTest { 5 | 6 | void ReportAssert(char const* description, char const* filename, int lineNumber) 7 | { 8 | throw AssertException(description, filename, lineNumber); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/ReportAssert.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_ASSERT_H 2 | #define UNITTEST_ASSERT_H 3 | 4 | namespace UnitTest { 5 | 6 | void ReportAssert(char const* description, char const* filename, int lineNumber); 7 | 8 | } 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/Test.cpp: -------------------------------------------------------------------------------- 1 | #include "Config.h" 2 | #include "Test.h" 3 | #include "TestList.h" 4 | #include "TestResults.h" 5 | #include "AssertException.h" 6 | #include "MemoryOutStream.h" 7 | #include "ExecuteTest.h" 8 | 9 | #ifdef UNITTEST_POSIX 10 | #include "Posix/SignalTranslator.h" 11 | #endif 12 | 13 | namespace UnitTest { 14 | 15 | TestList& Test::GetTestList() 16 | { 17 | static TestList s_list; 18 | return s_list; 19 | } 20 | 21 | Test::Test(char const* testName, char const* suiteName, char const* filename, int lineNumber) 22 | : m_details(testName, suiteName, filename, lineNumber) 23 | , next(0) 24 | , m_timeConstraintExempt(false) 25 | { 26 | } 27 | 28 | Test::~Test() 29 | { 30 | } 31 | 32 | void Test::Run() 33 | { 34 | ExecuteTest(*this, m_details); 35 | } 36 | 37 | void Test::RunImpl() const 38 | { 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/Test.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TEST_H 2 | #define UNITTEST_TEST_H 3 | 4 | #include "TestDetails.h" 5 | 6 | namespace UnitTest { 7 | 8 | class TestResults; 9 | class TestList; 10 | 11 | class Test 12 | { 13 | public: 14 | explicit Test(char const* testName, char const* suiteName = "DefaultSuite", char const* filename = "", int lineNumber = 0); 15 | virtual ~Test(); 16 | void Run(); 17 | 18 | TestDetails const m_details; 19 | Test* next; 20 | mutable bool m_timeConstraintExempt; 21 | 22 | static TestList& GetTestList(); 23 | 24 | virtual void RunImpl() const; 25 | 26 | private: 27 | Test(Test const&); 28 | Test& operator =(Test const&); 29 | }; 30 | 31 | 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/TestDetails.cpp: -------------------------------------------------------------------------------- 1 | #include "TestDetails.h" 2 | 3 | namespace UnitTest { 4 | 5 | TestDetails::TestDetails(char const* testName_, char const* suiteName_, char const* filename_, int lineNumber_) 6 | : suiteName(suiteName_) 7 | , testName(testName_) 8 | , filename(filename_) 9 | , lineNumber(lineNumber_) 10 | { 11 | } 12 | 13 | TestDetails::TestDetails(const TestDetails& details, int lineNumber_) 14 | : suiteName(details.suiteName) 15 | , testName(details.testName) 16 | , filename(details.filename) 17 | , lineNumber(lineNumber_) 18 | { 19 | } 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/TestDetails.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TESTDETAILS_H 2 | #define UNITTEST_TESTDETAILS_H 3 | 4 | namespace UnitTest { 5 | 6 | class TestDetails 7 | { 8 | public: 9 | TestDetails(char const* testName, char const* suiteName, char const* filename, int lineNumber); 10 | TestDetails(const TestDetails& details, int lineNumber); 11 | 12 | char const* const suiteName; 13 | char const* const testName; 14 | char const* const filename; 15 | int const lineNumber; 16 | 17 | TestDetails(TestDetails const&); // Why is it public? --> http://gcc.gnu.org/bugs.html#cxx_rvalbind 18 | private: 19 | TestDetails& operator=(TestDetails const&); 20 | }; 21 | 22 | } 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/TestList.cpp: -------------------------------------------------------------------------------- 1 | #include "TestList.h" 2 | #include "Test.h" 3 | 4 | #include 5 | 6 | namespace UnitTest { 7 | 8 | TestList::TestList() 9 | : m_head(0) 10 | , m_tail(0) 11 | { 12 | } 13 | 14 | void TestList::Add(Test* test) 15 | { 16 | if (m_tail == 0) 17 | { 18 | assert(m_head == 0); 19 | m_head = test; 20 | m_tail = test; 21 | } 22 | else 23 | { 24 | m_tail->next = test; 25 | m_tail = test; 26 | } 27 | } 28 | 29 | Test* TestList::GetHead() const 30 | { 31 | return m_head; 32 | } 33 | 34 | ListAdder::ListAdder(TestList& list, Test* test) 35 | { 36 | list.Add(test); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/TestList.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TESTLIST_H 2 | #define UNITTEST_TESTLIST_H 3 | 4 | 5 | namespace UnitTest { 6 | 7 | class Test; 8 | 9 | class TestList 10 | { 11 | public: 12 | TestList(); 13 | void Add (Test* test); 14 | 15 | Test* GetHead() const; 16 | 17 | private: 18 | Test* m_head; 19 | Test* m_tail; 20 | }; 21 | 22 | 23 | class ListAdder 24 | { 25 | public: 26 | ListAdder(TestList& list, Test* test); 27 | }; 28 | 29 | } 30 | 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/TestMacros.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TESTMACROS_H 2 | #define UNITTEST_TESTMACROS_H 3 | 4 | #include "Config.h" 5 | #include "ExecuteTest.h" 6 | #include "AssertException.h" 7 | #include "TestDetails.h" 8 | #include "MemoryOutStream.h" 9 | 10 | #ifndef UNITTEST_POSIX 11 | #define UNITTEST_THROW_SIGNALS 12 | #else 13 | #include "Posix/SignalTranslator.h" 14 | #endif 15 | 16 | #ifdef TEST 17 | #error UnitTest++ redefines TEST 18 | #endif 19 | 20 | #ifdef TEST_EX 21 | #error UnitTest++ redefines TEST_EX 22 | #endif 23 | 24 | #ifdef TEST_FIXTURE_EX 25 | #error UnitTest++ redefines TEST_FIXTURE_EX 26 | #endif 27 | 28 | #define SUITE(Name) \ 29 | namespace Suite##Name { \ 30 | namespace UnitTestSuite { \ 31 | inline char const* GetSuiteName () { \ 32 | return #Name ; \ 33 | } \ 34 | } \ 35 | } \ 36 | namespace Suite##Name 37 | 38 | #define TEST_EX(Name, List) \ 39 | class Test##Name : public UnitTest::Test \ 40 | { \ 41 | public: \ 42 | Test##Name() : Test(#Name, UnitTestSuite::GetSuiteName(), __FILE__, __LINE__) {} \ 43 | private: \ 44 | virtual void RunImpl() const; \ 45 | } test##Name##Instance; \ 46 | \ 47 | UnitTest::ListAdder adder##Name (List, &test##Name##Instance); \ 48 | \ 49 | void Test##Name::RunImpl() const 50 | 51 | 52 | #define TEST(Name) TEST_EX(Name, UnitTest::Test::GetTestList()) 53 | 54 | 55 | #define TEST_FIXTURE_EX(Fixture, Name, List) \ 56 | class Fixture##Name##Helper : public Fixture \ 57 | { \ 58 | public: \ 59 | explicit Fixture##Name##Helper(UnitTest::TestDetails const& details) : m_details(details) {} \ 60 | void RunImpl(); \ 61 | UnitTest::TestDetails const& m_details; \ 62 | private: \ 63 | Fixture##Name##Helper(Fixture##Name##Helper const&); \ 64 | Fixture##Name##Helper& operator =(Fixture##Name##Helper const&); \ 65 | }; \ 66 | \ 67 | class Test##Fixture##Name : public UnitTest::Test \ 68 | { \ 69 | public: \ 70 | Test##Fixture##Name() : Test(#Name, UnitTestSuite::GetSuiteName(), __FILE__, __LINE__) {} \ 71 | private: \ 72 | virtual void RunImpl() const; \ 73 | } test##Fixture##Name##Instance; \ 74 | \ 75 | UnitTest::ListAdder adder##Fixture##Name (List, &test##Fixture##Name##Instance); \ 76 | \ 77 | void Test##Fixture##Name::RunImpl() const \ 78 | { \ 79 | bool ctorOk = false; \ 80 | try { \ 81 | Fixture##Name##Helper fixtureHelper(m_details); \ 82 | ctorOk = true; \ 83 | UnitTest::ExecuteTest(fixtureHelper, m_details); \ 84 | } \ 85 | catch (UnitTest::AssertException const& e) \ 86 | { \ 87 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(m_details.testName, m_details.suiteName, e.Filename(), e.LineNumber()), e.what()); \ 88 | } \ 89 | catch (std::exception const& e) \ 90 | { \ 91 | UnitTest::MemoryOutStream stream; \ 92 | stream << "Unhandled exception: " << e.what(); \ 93 | UnitTest::CurrentTest::Results()->OnTestFailure(m_details, stream.GetText()); \ 94 | } \ 95 | catch (...) { \ 96 | if (ctorOk) \ 97 | { \ 98 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(m_details, __LINE__), \ 99 | "Unhandled exception while destroying fixture " #Fixture); \ 100 | } \ 101 | else \ 102 | { \ 103 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(m_details, __LINE__), \ 104 | "Unhandled exception while constructing fixture " #Fixture); \ 105 | } \ 106 | } \ 107 | } \ 108 | void Fixture##Name##Helper::RunImpl() 109 | 110 | #define TEST_FIXTURE(Fixture,Name) TEST_FIXTURE_EX(Fixture, Name, UnitTest::Test::GetTestList()) 111 | 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/TestReporter.cpp: -------------------------------------------------------------------------------- 1 | #include "TestReporter.h" 2 | 3 | namespace UnitTest { 4 | 5 | 6 | TestReporter::~TestReporter() 7 | { 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/TestReporter.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TESTREPORTER_H 2 | #define UNITTEST_TESTREPORTER_H 3 | 4 | namespace UnitTest { 5 | 6 | class TestDetails; 7 | 8 | class TestReporter 9 | { 10 | public: 11 | virtual ~TestReporter(); 12 | 13 | virtual void ReportTestStart(TestDetails const& test) = 0; 14 | virtual void ReportFailure(TestDetails const& test, char const* failure) = 0; 15 | virtual void ReportTestFinish(TestDetails const& test, float secondsElapsed) = 0; 16 | virtual void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed) = 0; 17 | }; 18 | 19 | } 20 | #endif 21 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/TestReporterStdout.cpp: -------------------------------------------------------------------------------- 1 | #include "TestReporterStdout.h" 2 | #include 3 | 4 | #include "TestDetails.h" 5 | 6 | // cstdio doesn't pull in namespace std on VC6, so we do it here. 7 | #if defined(_MSC_VER) && (_MSC_VER == 1200) 8 | namespace std {} 9 | #endif 10 | 11 | namespace UnitTest { 12 | 13 | void TestReporterStdout::ReportFailure(TestDetails const& details, char const* failure) 14 | { 15 | #if defined(__APPLE__) || defined(__GNUG__) 16 | char const* const errorFormat = "%s:%d: error: Failure in %s: %s\n"; 17 | #else 18 | char const* const errorFormat = "%s(%d): error: Failure in %s: %s\n"; 19 | #endif 20 | 21 | using namespace std; 22 | printf(errorFormat, details.filename, details.lineNumber, details.testName, failure); 23 | } 24 | 25 | void TestReporterStdout::ReportTestStart(TestDetails const& /*test*/) 26 | { 27 | } 28 | 29 | void TestReporterStdout::ReportTestFinish(TestDetails const& /*test*/, float) 30 | { 31 | } 32 | 33 | void TestReporterStdout::ReportSummary(int const totalTestCount, int const failedTestCount, 34 | int const failureCount, float secondsElapsed) 35 | { 36 | using namespace std; 37 | 38 | if (failureCount > 0) 39 | printf("FAILURE: %d out of %d tests failed (%d failures).\n", failedTestCount, totalTestCount, failureCount); 40 | else 41 | printf("Success: %d tests passed.\n", totalTestCount); 42 | 43 | printf("Test time: %.2f seconds.\n", secondsElapsed); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/TestReporterStdout.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TESTREPORTERSTDOUT_H 2 | #define UNITTEST_TESTREPORTERSTDOUT_H 3 | 4 | #include "TestReporter.h" 5 | 6 | namespace UnitTest { 7 | 8 | class TestReporterStdout : public TestReporter 9 | { 10 | private: 11 | virtual void ReportTestStart(TestDetails const& test); 12 | virtual void ReportFailure(TestDetails const& test, char const* failure); 13 | virtual void ReportTestFinish(TestDetails const& test, float secondsElapsed); 14 | virtual void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed); 15 | }; 16 | 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/TestResults.cpp: -------------------------------------------------------------------------------- 1 | #include "TestResults.h" 2 | #include "TestReporter.h" 3 | 4 | #include "TestDetails.h" 5 | 6 | namespace UnitTest { 7 | 8 | TestResults::TestResults(TestReporter* testReporter) 9 | : m_testReporter(testReporter) 10 | , m_totalTestCount(0) 11 | , m_failedTestCount(0) 12 | , m_failureCount(0) 13 | , m_currentTestFailed(false) 14 | { 15 | } 16 | 17 | void TestResults::OnTestStart(TestDetails const& test) 18 | { 19 | ++m_totalTestCount; 20 | m_currentTestFailed = false; 21 | if (m_testReporter) 22 | m_testReporter->ReportTestStart(test); 23 | } 24 | 25 | void TestResults::OnTestFailure(TestDetails const& test, char const* failure) 26 | { 27 | ++m_failureCount; 28 | if (!m_currentTestFailed) 29 | { 30 | ++m_failedTestCount; 31 | m_currentTestFailed = true; 32 | } 33 | 34 | if (m_testReporter) 35 | m_testReporter->ReportFailure(test, failure); 36 | } 37 | 38 | void TestResults::OnTestFinish(TestDetails const& test, float secondsElapsed) 39 | { 40 | if (m_testReporter) 41 | m_testReporter->ReportTestFinish(test, secondsElapsed); 42 | } 43 | 44 | int TestResults::GetTotalTestCount() const 45 | { 46 | return m_totalTestCount; 47 | } 48 | 49 | int TestResults::GetFailedTestCount() const 50 | { 51 | return m_failedTestCount; 52 | } 53 | 54 | int TestResults::GetFailureCount() const 55 | { 56 | return m_failureCount; 57 | } 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/TestResults.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TESTRESULTS_H 2 | #define UNITTEST_TESTRESULTS_H 3 | 4 | namespace UnitTest { 5 | 6 | class TestReporter; 7 | class TestDetails; 8 | 9 | class TestResults 10 | { 11 | public: 12 | explicit TestResults(TestReporter* reporter = 0); 13 | 14 | void OnTestStart(TestDetails const& test); 15 | void OnTestFailure(TestDetails const& test, char const* failure); 16 | void OnTestFinish(TestDetails const& test, float secondsElapsed); 17 | 18 | int GetTotalTestCount() const; 19 | int GetFailedTestCount() const; 20 | int GetFailureCount() const; 21 | 22 | private: 23 | TestReporter* m_testReporter; 24 | int m_totalTestCount; 25 | int m_failedTestCount; 26 | int m_failureCount; 27 | 28 | bool m_currentTestFailed; 29 | 30 | TestResults(TestResults const&); 31 | TestResults& operator =(TestResults const&); 32 | }; 33 | 34 | } 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/TestRunner.cpp: -------------------------------------------------------------------------------- 1 | #include "TestRunner.h" 2 | #include "TestResults.h" 3 | #include "TestReporter.h" 4 | #include "TestReporterStdout.h" 5 | #include "TimeHelpers.h" 6 | #include "MemoryOutStream.h" 7 | 8 | #include 9 | 10 | 11 | namespace UnitTest { 12 | 13 | int RunAllTests() 14 | { 15 | TestReporterStdout reporter; 16 | TestRunner runner(reporter); 17 | return runner.RunTestsIf(Test::GetTestList(), NULL, True(), 0); 18 | } 19 | 20 | 21 | TestRunner::TestRunner(TestReporter& reporter) 22 | : m_reporter(&reporter) 23 | , m_result(new TestResults(&reporter)) 24 | , m_timer(new Timer) 25 | { 26 | m_timer->Start(); 27 | } 28 | 29 | TestRunner::~TestRunner() 30 | { 31 | delete m_result; 32 | delete m_timer; 33 | } 34 | 35 | int TestRunner::Finish() const 36 | { 37 | float const secondsElapsed = static_cast(m_timer->GetTimeInMs() / 1000.0); 38 | m_reporter->ReportSummary(m_result->GetTotalTestCount(), 39 | m_result->GetFailedTestCount(), 40 | m_result->GetFailureCount(), 41 | secondsElapsed); 42 | 43 | return m_result->GetFailureCount(); 44 | } 45 | 46 | bool TestRunner::IsTestInSuite(const Test* const curTest, char const* suiteName) const 47 | { 48 | using namespace std; 49 | return (suiteName == NULL) || !strcmp(curTest->m_details.suiteName, suiteName); 50 | } 51 | 52 | void TestRunner::RunTest(TestResults* const result, Test* const curTest, int const maxTestTimeInMs) const 53 | { 54 | CurrentTest::Results() = result; 55 | 56 | Timer testTimer; 57 | testTimer.Start(); 58 | 59 | result->OnTestStart(curTest->m_details); 60 | 61 | curTest->Run(); 62 | 63 | double const testTimeInMs = testTimer.GetTimeInMs(); 64 | if (maxTestTimeInMs > 0 && testTimeInMs > maxTestTimeInMs && !curTest->m_timeConstraintExempt) 65 | { 66 | MemoryOutStream stream; 67 | stream << "Global time constraint failed. Expected under " << maxTestTimeInMs << 68 | "ms but took " << testTimeInMs << "ms."; 69 | 70 | result->OnTestFailure(curTest->m_details, stream.GetText()); 71 | } 72 | 73 | result->OnTestFinish(curTest->m_details, static_cast(testTimeInMs/1000.0)); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/TestRunner.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TESTRUNNER_H 2 | #define UNITTEST_TESTRUNNER_H 3 | 4 | #include "Test.h" 5 | #include "TestList.h" 6 | #include "CurrentTest.h" 7 | 8 | namespace UnitTest { 9 | 10 | class TestReporter; 11 | class TestResults; 12 | class Timer; 13 | 14 | int RunAllTests(); 15 | 16 | struct True 17 | { 18 | bool operator()(const Test* const) const 19 | { 20 | return true; 21 | } 22 | }; 23 | 24 | class TestRunner 25 | { 26 | public: 27 | explicit TestRunner(TestReporter& reporter); 28 | ~TestRunner(); 29 | 30 | template 31 | int RunTestsIf(TestList const& list, char const* suiteName, 32 | const Predicate& predicate, int maxTestTimeInMs) const 33 | { 34 | Test* curTest = list.GetHead(); 35 | 36 | while (curTest != 0) 37 | { 38 | if (IsTestInSuite(curTest, suiteName) && predicate(curTest)) 39 | RunTest(m_result, curTest, maxTestTimeInMs); 40 | 41 | curTest = curTest->next; 42 | } 43 | 44 | return Finish(); 45 | } 46 | 47 | private: 48 | TestReporter* m_reporter; 49 | TestResults* m_result; 50 | Timer* m_timer; 51 | 52 | int Finish() const; 53 | bool IsTestInSuite(const Test* const curTest, char const* suiteName) const; 54 | void RunTest(TestResults* const result, Test* const curTest, int const maxTestTimeInMs) const; 55 | }; 56 | 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/TestSuite.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TESTSUITE_H 2 | #define UNITTEST_TESTSUITE_H 3 | 4 | namespace UnitTestSuite 5 | { 6 | inline char const* GetSuiteName () 7 | { 8 | return "DefaultSuite"; 9 | } 10 | } 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/TimeConstraint.cpp: -------------------------------------------------------------------------------- 1 | #include "TimeConstraint.h" 2 | #include "TestResults.h" 3 | #include "MemoryOutStream.h" 4 | #include "CurrentTest.h" 5 | 6 | namespace UnitTest { 7 | 8 | 9 | TimeConstraint::TimeConstraint(int ms, TestDetails const& details) 10 | : m_details(details) 11 | , m_maxMs(ms) 12 | { 13 | m_timer.Start(); 14 | } 15 | 16 | TimeConstraint::~TimeConstraint() 17 | { 18 | double const totalTimeInMs = m_timer.GetTimeInMs(); 19 | if (totalTimeInMs > m_maxMs) 20 | { 21 | MemoryOutStream stream; 22 | stream << "Time constraint failed. Expected to run test under " << m_maxMs << 23 | "ms but took " << totalTimeInMs << "ms."; 24 | 25 | UnitTest::CurrentTest::Results()->OnTestFailure(m_details, stream.GetText()); 26 | } 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/TimeConstraint.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TIMECONSTRAINT_H 2 | #define UNITTEST_TIMECONSTRAINT_H 3 | 4 | #include "TimeHelpers.h" 5 | 6 | namespace UnitTest { 7 | 8 | class TestResults; 9 | class TestDetails; 10 | 11 | class TimeConstraint 12 | { 13 | public: 14 | TimeConstraint(int ms, TestDetails const& details); 15 | ~TimeConstraint(); 16 | 17 | private: 18 | void operator=(TimeConstraint const&); 19 | TimeConstraint(TimeConstraint const&); 20 | 21 | Timer m_timer; 22 | TestDetails const& m_details; 23 | int const m_maxMs; 24 | }; 25 | 26 | #define UNITTEST_TIME_CONSTRAINT(ms) \ 27 | UnitTest::TimeConstraint unitTest__timeConstraint__(ms, UnitTest::TestDetails(m_details, __LINE__)) 28 | 29 | #define UNITTEST_TIME_CONSTRAINT_EXEMPT() do { m_timeConstraintExempt = true; } while (0) 30 | 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/TimeHelpers.h: -------------------------------------------------------------------------------- 1 | #include "Config.h" 2 | 3 | #if defined UNITTEST_POSIX 4 | #include "Posix/TimeHelpers.h" 5 | #else 6 | #include "Win32/TimeHelpers.h" 7 | #endif 8 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/UnitTest++.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTESTCPP_H 2 | #define UNITTESTCPP_H 3 | 4 | //lint -esym(1509,*Fixture) 5 | 6 | #include "Config.h" 7 | #include "Test.h" 8 | #include "TestList.h" 9 | #include "TestSuite.h" 10 | #include "TestResults.h" 11 | 12 | #include "TestMacros.h" 13 | 14 | #include "CheckMacros.h" 15 | #include "TestRunner.h" 16 | #include "TimeConstraint.h" 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/Win32/TimeHelpers.cpp: -------------------------------------------------------------------------------- 1 | #include "TimeHelpers.h" 2 | #include 3 | 4 | namespace UnitTest { 5 | 6 | Timer::Timer() 7 | : m_threadHandle(::GetCurrentThread()) 8 | , m_startTime(0) 9 | { 10 | #if defined(_MSC_VER) && (_MSC_VER == 1200) // VC6 doesn't have DWORD_PTR? 11 | typedef unsigned long DWORD_PTR; 12 | #endif 13 | 14 | DWORD_PTR systemMask; 15 | ::GetProcessAffinityMask(GetCurrentProcess(), &m_processAffinityMask, &systemMask); 16 | ::SetThreadAffinityMask(m_threadHandle, 1); 17 | ::QueryPerformanceFrequency(reinterpret_cast< LARGE_INTEGER* >(&m_frequency)); 18 | ::SetThreadAffinityMask(m_threadHandle, m_processAffinityMask); 19 | } 20 | 21 | void Timer::Start() 22 | { 23 | m_startTime = GetTime(); 24 | } 25 | 26 | double Timer::GetTimeInMs() const 27 | { 28 | __int64 const elapsedTime = GetTime() - m_startTime; 29 | double const seconds = double(elapsedTime) / double(m_frequency); 30 | return seconds * 1000.0; 31 | } 32 | 33 | __int64 Timer::GetTime() const 34 | { 35 | LARGE_INTEGER curTime; 36 | ::SetThreadAffinityMask(m_threadHandle, 1); 37 | ::QueryPerformanceCounter(&curTime); 38 | ::SetThreadAffinityMask(m_threadHandle, m_processAffinityMask); 39 | return curTime.QuadPart; 40 | } 41 | 42 | void TimeHelpers::SleepMs(int const ms) 43 | { 44 | ::Sleep(ms); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/Win32/TimeHelpers.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TIMEHELPERS_H 2 | #define UNITTEST_TIMEHELPERS_H 3 | 4 | #include "../Config.h" 5 | 6 | 7 | #ifdef UNITTEST_MINGW 8 | #ifndef __int64 9 | #define __int64 long long 10 | #endif 11 | #endif 12 | 13 | namespace UnitTest { 14 | 15 | class Timer 16 | { 17 | public: 18 | Timer(); 19 | void Start(); 20 | double GetTimeInMs() const; 21 | 22 | private: 23 | __int64 GetTime() const; 24 | 25 | void* m_threadHandle; 26 | 27 | #if defined(_WIN64) 28 | unsigned __int64 m_processAffinityMask; 29 | #else 30 | unsigned long m_processAffinityMask; 31 | #endif 32 | 33 | __int64 m_startTime; 34 | __int64 m_frequency; 35 | }; 36 | 37 | 38 | namespace TimeHelpers 39 | { 40 | void SleepMs (int ms); 41 | } 42 | 43 | 44 | } 45 | 46 | 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/XmlTestReporter.cpp: -------------------------------------------------------------------------------- 1 | #include "XmlTestReporter.h" 2 | #include "Config.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using std::string; 9 | using std::ostringstream; 10 | using std::ostream; 11 | 12 | namespace { 13 | 14 | void ReplaceChar(string& str, char c, string const& replacement) 15 | { 16 | for (size_t pos = str.find(c); pos != string::npos; pos = str.find(c, pos + 1)) 17 | str.replace(pos, 1, replacement); 18 | } 19 | 20 | string XmlEscape(string const& value) 21 | { 22 | string escaped = value; 23 | 24 | ReplaceChar(escaped, '&', "&"); 25 | ReplaceChar(escaped, '<', "<"); 26 | ReplaceChar(escaped, '>', ">"); 27 | ReplaceChar(escaped, '\'', "'"); 28 | ReplaceChar(escaped, '\"', """); 29 | 30 | return escaped; 31 | } 32 | 33 | string BuildFailureMessage(string const& file, int line, string const& message) 34 | { 35 | ostringstream failureMessage; 36 | failureMessage << file << "(" << line << ") : " << message; 37 | return failureMessage.str(); 38 | } 39 | 40 | } 41 | 42 | namespace UnitTest { 43 | 44 | XmlTestReporter::XmlTestReporter(ostream& ostream) 45 | : m_ostream(ostream) 46 | { 47 | } 48 | 49 | void XmlTestReporter::ReportSummary(int totalTestCount, int failedTestCount, 50 | int failureCount, float secondsElapsed) 51 | { 52 | AddXmlElement(m_ostream, NULL); 53 | 54 | BeginResults(m_ostream, totalTestCount, failedTestCount, failureCount, secondsElapsed); 55 | 56 | DeferredTestResultList const& results = GetResults(); 57 | for (DeferredTestResultList::const_iterator i = results.begin(); i != results.end(); ++i) 58 | { 59 | BeginTest(m_ostream, *i); 60 | 61 | if (i->failed) 62 | AddFailure(m_ostream, *i); 63 | 64 | EndTest(m_ostream, *i); 65 | } 66 | 67 | EndResults(m_ostream); 68 | } 69 | 70 | void XmlTestReporter::AddXmlElement(ostream& os, char const* encoding) 71 | { 72 | os << ""; 78 | } 79 | 80 | void XmlTestReporter::BeginResults(std::ostream& os, int totalTestCount, int failedTestCount, 81 | int failureCount, float secondsElapsed) 82 | { 83 | os << ""; 89 | } 90 | 91 | void XmlTestReporter::EndResults(std::ostream& os) 92 | { 93 | os << ""; 94 | } 95 | 96 | void XmlTestReporter::BeginTest(std::ostream& os, DeferredTestResult const& result) 97 | { 98 | os << ""; 108 | else 109 | os << "/>"; 110 | } 111 | 112 | void XmlTestReporter::AddFailure(std::ostream& os, DeferredTestResult const& result) 113 | { 114 | os << ">"; // close element 115 | 116 | for (DeferredTestResult::FailureVec::const_iterator it = result.failures.begin(); 117 | it != result.failures.end(); 118 | ++it) 119 | { 120 | string const escapedMessage = XmlEscape(it->second); 121 | string const message = BuildFailureMessage(result.failureFile, it->first, escapedMessage); 122 | 123 | os << ""; 124 | } 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /tests/UnitTest++/src/XmlTestReporter.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_XMLTESTREPORTER_H 2 | #define UNITTEST_XMLTESTREPORTER_H 3 | 4 | #include "DeferredTestReporter.h" 5 | 6 | #include 7 | 8 | namespace UnitTest 9 | { 10 | 11 | class XmlTestReporter : public DeferredTestReporter 12 | { 13 | public: 14 | explicit XmlTestReporter(std::ostream& ostream); 15 | 16 | virtual void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed); 17 | 18 | private: 19 | XmlTestReporter(XmlTestReporter const&); 20 | XmlTestReporter& operator=(XmlTestReporter const&); 21 | 22 | void AddXmlElement(std::ostream& os, char const* encoding); 23 | void BeginResults(std::ostream& os, int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed); 24 | void EndResults(std::ostream& os); 25 | void BeginTest(std::ostream& os, DeferredTestResult const& result); 26 | void AddFailure(std::ostream& os, DeferredTestResult const& result); 27 | void EndTest(std::ostream& os, DeferredTestResult const& result); 28 | 29 | std::ostream& m_ostream; 30 | }; 31 | 32 | } 33 | 34 | #endif 35 | --------------------------------------------------------------------------------