diff --git a/Makefile b/Makefile index 0013374..c67b531 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,12 @@ +include Makefile.inc + +$(info === Build configuration ===) +$(info Archtecture: $(ARCH)) +$(info Operating system: $(OS)) + CRYPTOPP_DIR=external/psf-cryptopp CRYPTOPP_LIB=$(CRYPTOPP_DIR)/libcryptopp.a -PSCRYPTO=pscrypto/pscrypto.dll +PSCRYPTO=pscrypto/$(call lib-name,pscrypto) all : $(CRYPTOPP_LIB) $(PSCRYPTO) @@ -13,3 +19,5 @@ $(PSCRYPTO) : $(CRYPTOPP_LIB) clean : $(MAKE) -C pscrypto/ clean $(MAKE) -C $(CRYPTOPP_DIR) clean + +.PHONY : all clean diff --git a/Makefile.inc b/Makefile.inc new file mode 100644 index 0000000..c9ac01b --- /dev/null +++ b/Makefile.inc @@ -0,0 +1,68 @@ +# Common makefile helper file + +# Note - := means expand all and save result, = means expand all each time +AR := $(PREFIX)ar +CC := $(PREFIX)gcc +CXX := $(PREFIX)g++ +LD := $(PREFIX)ld +STRIP := $(PREFIX)strip + +# Get a good guess as to our compile target +gcc_machine := $(subst -, ,$(shell $(CC) -dumpmachine)) + +GCC_ARCH := $(word 1,$(gcc_machine)) +OS := $(word 3,$(gcc_machine)) + +ifeq "$(ARCH)" "" + ifeq "$(GCC_ARCH)" "" + $(error "Unable to determine architecture") + endif +endif + +ifeq "$(OS)" "" +$(error "Unable to determine operating system") +endif + +# Consolidate the GCC architecture value. +# If it was user defined, and it disagrees with the GCC value, we are probably +# trying a multilib build +ifdef ARCH + # user arch and GCC arch did not match + ifneq "$(ARCH)" "$(GCC_ARCH)" + ifeq ($(findstring $(ARCH), i686 x86_64),) + $(error "Unsupported architecture $(ARCH)") + endif + + ifeq "$(ARCH)" "i686" + CFLAGS := $(CFLAGS) -m32 + CXXFLAGS := $(CXXFLAGS) -m32 + LDFLAGS := $(LDFLAGS) -m32 + else ifeq "$(ARCH)" "x86_64") + CFLAGS := $(CFLAGS) -m64 + CXXFLAGS := $(CXXFLAGS) -m64 + LDFLAGS := $(LDFLAGS) -m64 + endif + endif +else + ifeq ($(findstring $(GCC_ARCH), i686 x86_64),) + $(error "Unsupported architecture $(ARCH)") + endif + + ARCH := $(GCC_ARCH) +endif + +ifeq ($(findstring $(OS), linux cygwin mingw32),) +$(error "Unsupported operating system $(OS)") +endif + +# Output artifact functions +ifeq "$(OS)" "mingw32" + lib-name = $(1).dll + exe-name = $(1).exe +else ifeq "$(OS)" "cygwin" + lib-name = $(1).dll + exe-name = $(1).exe +else + lib-name = lib$(1).so + exe-name = $(1) +endif diff --git a/external/psf-cryptopp b/external/psf-cryptopp index d9be78c..81a4a88 160000 --- a/external/psf-cryptopp +++ b/external/psf-cryptopp @@ -1 +1 @@ -Subproject commit d9be78c72cbe270efecd90193f16b10007b6aa1d +Subproject commit 81a4a88fbfafbebe874b14010422cf82ff23b1c5 diff --git a/pscrypto/Makefile b/pscrypto/Makefile index 3d22f5d..b72ce0c 100644 --- a/pscrypto/Makefile +++ b/pscrypto/Makefile @@ -1,17 +1,26 @@ +include ../Makefile.inc + +#### Sources SRCS = pscrypto.cpp OBJS := $(SRCS:.cpp=.o) -# TODO: this needs to be fixed for linux -LIB = pscrypto.dll -TEST = pscrypto +#### Artifacts +OUT_NAME=pscrypto +LIB = $(call lib-name,$(OUT_NAME)) +TEST = $(call exe-name,$(OUT_NAME)) -AR = $(PREFIX)ar -CXX = $(PREFIX)g++ -LD = $(PREFIX)g++ -STRIP = $(PREFIX)strip +#### Flags +CXXFLAGS := $(CFLAGS) -DBUILD_DLL -I../external/psf-cryptopp +LDFLAGS := -L../external/psf-cryptopp -CXXFLAGS := $(CFLAGS) -DBUILD_DLL -I../external/psf-cryptopp -fPIC -LDFLAGS := -L../external/psf-cryptopp -static-libgcc -static-libstdc++ +# Handle OS compiler quirks +ifeq "$(OS)" "mingw32" + LDFLAGS := $(LDFLAGS) -static-libgcc -static-libstdc++ +else ifeq "$(OS)" "cygwin" + LDFLAGS := $(LDFLAGS) -static-libgcc -static-libstdc++ +else + CXXFLAGS := $(CXXFLAGS) -fPIC +endif ifdef DEBUG CXXFLAGS += -g @@ -22,7 +31,12 @@ endif LIB_FLAGS=$(LDFLAGS) -Wl,-soname=$(LIB) LIBS=-lcryptopp -all : $(OBJS) $(LIB) $(TEST) +#### Recipes + +all : $(OBJS) $(LIB) + +test : all $(TEST) + ./$(TEST) %.o : %.cpp $(CXX) $(CXXFLAGS) -c $< -o $@ @@ -40,4 +54,6 @@ ifndef DEBUG endif clean : - rm -f $(OBJS) $(LIB) *.pyc + rm -f $(OBJS) $(LIB) $(TEST) *.pyc + +.PHONY : all test clean diff --git a/pscrypto/pscrypto.cpp b/pscrypto/pscrypto.cpp index 2dbc1f9..14e1c43 100644 --- a/pscrypto/pscrypto.cpp +++ b/pscrypto/pscrypto.cpp @@ -66,65 +66,27 @@ using CryptoPP::SecByteBlock; #include using namespace std; -DLL_EXPORT DH * DH_Start(const byte * p, const byte * g, byte * privKey, byte * pubKey); -bool ValidateMD5MAC(); +#include "pscrypto.h" #define min(x, y) (((x) > (y)) ? (y) : (x)) -/*key = "377b60f8790f91b35a9da82945743da9" -label = "master secret" -msg = "b4aea1559444a20b6112a2892de40eac00000000c8aea155b53d187076b79abab59001b600000000" -#msg = "" -expect = "5aa15de41f5220cf5cca489155e1438c5aa15de4" - -print "Key: " + key -print "Msg: " + msg - -# append the label -msg = label + hexToBin(msg)*/ - -int main(int argc, char* argv[]) +DLL_EXPORT bool PSCrypto_Init(int major, int minor) { - DH dh; - AutoSeededRandomPool rnd(0x128); + return PSCRYPTO_VERSION_MAJOR == major && PSCRYPTO_VERSION_MINOR == minor; +} - cout << "Generating parameters..." << endl; - dh.AccessGroupParameters().Initialize(rnd, 128); - // for server, we are given p and g - // use this: dh.AccessGroupParameters().Initialize(p, g); +DLL_EXPORT void PSCrypto_Get_Version(int * major, int * minor) +{ + if(major && minor) + { + *major = PSCRYPTO_VERSION_MAJOR; + *minor = PSCRYPTO_VERSION_MINOR; + } +} - cout << "Generating Keypair..." << endl; - - SecByteBlock privKey(dh.PrivateKeyLength()); - SecByteBlock pubKey(dh.PublicKeyLength()); - dh.GenerateKeyPair(rnd, privKey, pubKey); - - const Integer& p = dh.GetGroupParameters().GetModulus(); - cout << "P: " << hex << p << endl; - - Integer q = (p-1)/2; - cout << "Q: " << q << endl; - - const Integer& g = dh.GetGroupParameters().GetGenerator(); - cout << "G: " << g << endl; - - Integer r = dh.GetGroupParameters().GetSubgroupOrder(); - cout << "Subgroup order: " << r << endl; - - cout << "Key generation test..." << endl; - - byte buf1[16] = { - 'a','a','b','b', - 'a','a','b','b', - 'a','a','b','b', - 'a','a','b','c'}; - byte buf2[16]; - byte buf3[16]; - - - cout << "Output " << DH_Start(buf1, buf1, buf2, buf3) << endl; - - return 0; +DLL_EXPORT const char * PSCrypto_Version_String() +{ + return PSCRYPTO_VERSION_STRING; } DLL_EXPORT DH * DH_Start(const byte * p, const byte * g, byte * privKey, byte * pubKey) @@ -292,7 +254,7 @@ DLL_EXPORT void MD5Test() } -void HMACTest() +static void HMACTest() { AutoSeededRandomPool prng; @@ -340,7 +302,7 @@ void HMACTest() } } -bool ValidateMD5MAC() +static bool ValidateMD5MAC() { const byte keys[2][MD5MAC::KEYLENGTH]={ {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff}, @@ -399,3 +361,59 @@ bool ValidateMD5MAC() return pass; } + +/*key = "377b60f8790f91b35a9da82945743da9" +label = "master secret" +msg = "b4aea1559444a20b6112a2892de40eac00000000c8aea155b53d187076b79abab59001b600000000" +#msg = "" +expect = "5aa15de41f5220cf5cca489155e1438c5aa15de4" + +print "Key: " + key +print "Msg: " + msg + +# append the label +msg = label + hexToBin(msg)*/ + +int main(int argc, char* argv[]) +{ + DH dh; + AutoSeededRandomPool rnd(0x128); + + cout << "Generating parameters..." << endl; + dh.AccessGroupParameters().Initialize(rnd, 128); + // for server, we are given p and g + // use this: dh.AccessGroupParameters().Initialize(p, g); + + cout << "Generating Keypair..." << endl; + + SecByteBlock privKey(dh.PrivateKeyLength()); + SecByteBlock pubKey(dh.PublicKeyLength()); + dh.GenerateKeyPair(rnd, privKey, pubKey); + + const Integer& p = dh.GetGroupParameters().GetModulus(); + cout << "P: " << hex << p << endl; + + Integer q = (p-1)/2; + cout << "Q: " << q << endl; + + const Integer& g = dh.GetGroupParameters().GetGenerator(); + cout << "G: " << g << endl; + + Integer r = dh.GetGroupParameters().GetSubgroupOrder(); + cout << "Subgroup order: " << r << endl; + + cout << "Key generation test..." << endl; + + byte buf1[16] = { + 'a','a','b','b', + 'a','a','b','b', + 'a','a','b','b', + 'a','a','b','c'}; + byte buf2[16]; + byte buf3[16]; + + + cout << "Output " << DH_Start(buf1, buf1, buf2, buf3) << endl; + + return 0; +} diff --git a/pscrypto/pscrypto.h b/pscrypto/pscrypto.h new file mode 100644 index 0000000..a9b5f66 --- /dev/null +++ b/pscrypto/pscrypto.h @@ -0,0 +1,128 @@ +#ifndef PSCRYPTO_H +#define PSCRYPTO_H + +#define _PS_STRINGIZE(S) #S + +#define PSCRYPTO_VERSION_MAJOR 1 +#define PSCRYPTO_VERSION_MINOR 0 + +#define PSCRYPTO_VERSION_STRING _PS_STRINGIZE(PSCRYPTO_VERSION_MAJOR) "." _PS_STRINGIZE(PSCRYPTO_VERSION_MINOR) + +#ifdef __cplusplus +extern "C" { +#endif + +// NOTE: all crypto is 128-bit (16 bytes) which is terrible and pretty much ineffective. + +// Version verification + +/// Returns initialization status. 1 for okay, 0 for failure +bool PSCrypto_Init(int major, int minor); + +/// Returns version numbers +void PSCrypto_Get_Version(int * major, int * minor); + +/// Returns version string +const char * PSCrypto_Version_String(); + +// Diffie-Helman (shared secret agreement) + +/** + * Starts a Diffie-Helman key exchange with another party who's P and G values + * are already known. + * + * @param p 16 bytes of P value + * @param g 16 bytes of G value + * @param privKey A generated private key (16 bytes) [out] + * @param pubKey A generated public key (16 bytes) [out] + * @returns Newly created CryptoPP DH object or NULL on failure + */ +DH * DH_Start(const byte * p, const byte * g, byte * privKey, byte * pubKey); + +/** + * Starts a new Diffie-Helman key exchange + * + * @param privKey A generated private key (16 bytes) [out] + * @param pubKey A generated public key (16 bytes) [out] + * @param p Generated P value (16 bytes) [out] + * @param g Generated G value (16 bytes) [out] + * @returns Newly created CryptoPP DH object or NULL on failure + */ +DH * DH_Start_Generate(byte * privKey, byte * pubKey, byte * p, byte * g); + +/** + * Perform an agreement with another party to come to a shared secret + * + * @param dh A previously created DH object + * @param agreedValue A generated 128-bit shared secret when function returns true [out] + * @param privKey Our private key + * @param otherPubKey The other party's public key + * @returns True on a successful agreement. False on some failure + */ +bool DH_Agree(DH * dh, byte * agreedValue, const byte * privKey, const byte * otherPubKey); + +/// Free created DH object +void Free_DH(DH * ptr); + +// RC5 (encryption and decryption) + +/** + * Initialize an RC5 instance with the specfied key + * + * @param key The input key buffer + * @param keyLen The input key length in bytes + * @param encrypt True for an encryption instance. False for decryption + * @returns A newly created RC5 instance or NULL on failure + */ +void * RC5_Init(byte * key, size_t keyLen, bool encrypt); + +/** + * Perform an RC5 decryption + * + * @param dec A previously created RC5 decryption instance + * @param ct A ciphertext buffer + * @param ptLen The length of the ciphertext. Must be aligned to the size of an + * RC5 block (16 bytes) + * @param pt A pointer to a destination plaintext buffer of size ctLen [out] + * @returns True on a successful decryption + */ +bool RC5_Decrypt(RC5::Decryption * dec, byte * ct, size_t ctLen, byte * pt); + +/** + * Perform an RC5 encryption + * + * @param enc A previously created RC5 encryption instance + * @param pt A plaintext buffer + * @param ptLen The length of the plaintext. Must be aligned to the size of an + * RC5 block (16 bytes) + * @param ct A pointer to a destination ciphertext buffer of size ptLen [out] + * @returns True on a successful encryption + */ +bool RC5_Encrypt(RC5::Encryption * enc, byte * pt, size_t ptLen, byte * ct); + +/// Free a previously created RC5 object +void Free_RC5(RC5 * ptr); + +// MD5MAC (packet integrity and authenticity) + +/** + * Performs a single MD5 MAC computation + * + * @param key Input key buffer + * @param keyLen Size of the input key buffer + * @param msg Message to create a MAC for + * @param msgLen Length of the message + * @param outBuf Output buffer to receive the MAC value (16 for a full MAC) + * @param outBufLen Output buffer length. If the length is smaller than the size + * of a single MAC, the result will be truncated. If it is + * bigger, multiple MAC values will be concatenated until the + * size is reached. + * @returns Returns true on a successful MAC + */ +bool MD5_MAC(byte * key, size_t keyLen, byte * msg, size_t msgLen, byte * outBuf, size_t outBufLen); + +#ifdef __cplusplus +} +#endif + +#endif