From e888fedd6e6aeffd30d35606115f22a87f123743 Mon Sep 17 00:00:00 2001 From: jakcron Date: Mon, 3 Jul 2017 01:18:59 +1000 Subject: [PATCH] Initial commit of support libraries. --- NXTools.sln | 48 + NXTools.vcxproj | 119 ++ NXTools.vcxproj.filters | 17 + lib/crypto/aes_ctr_stream.cpp | 138 ++ lib/crypto/aes_ctr_stream.h | 162 +++ lib/crypto/aes_ctr_stream.o | Bin 0 -> 51496 bytes lib/crypto/crypto.cpp | 229 ++++ lib/crypto/crypto.h | 152 ++ lib/crypto/crypto.o | Bin 0 -> 9656 bytes lib/crypto/crypto.vcxproj | 128 ++ lib/crypto/crypto.vcxproj.filters | 36 + lib/crypto/makefile | 33 + lib/crypto/polarssl/aes.c | 1352 ++++++++++++++++++ lib/crypto/polarssl/aes.h | 202 +++ lib/crypto/polarssl/aes.o | Bin 0 -> 14888 bytes lib/crypto/polarssl/base64.c | 269 ++++ lib/crypto/polarssl/base64.h | 88 ++ lib/crypto/polarssl/base64.o | Bin 0 -> 3896 bytes lib/crypto/polarssl/bignum.c | 2135 +++++++++++++++++++++++++++++ lib/crypto/polarssl/bignum.h | 685 +++++++++ lib/crypto/polarssl/bignum.o | Bin 0 -> 35360 bytes lib/crypto/polarssl/bn_mul.h | 864 ++++++++++++ lib/crypto/polarssl/config.h | 1013 ++++++++++++++ lib/crypto/polarssl/rsa.c | 1466 ++++++++++++++++++++ lib/crypto/polarssl/rsa.h | 597 ++++++++ lib/crypto/polarssl/rsa.o | Bin 0 -> 14440 bytes lib/crypto/polarssl/sha1.c | 624 +++++++++ lib/crypto/polarssl/sha1.h | 180 +++ lib/crypto/polarssl/sha1.o | Bin 0 -> 12424 bytes lib/crypto/polarssl/sha2.c | 705 ++++++++++ lib/crypto/polarssl/sha2.h | 183 +++ lib/crypto/polarssl/sha2.o | Bin 0 -> 24200 bytes lib/fnd/elf.h | 216 +++ lib/fnd/exception.cpp | 58 + lib/fnd/exception.h | 35 + lib/fnd/exception.o | Bin 0 -> 7352 bytes lib/fnd/file_io.cpp | 44 + lib/fnd/file_io.h | 19 + lib/fnd/file_io.o | Bin 0 -> 11368 bytes lib/fnd/fnd.vcxproj | 136 ++ lib/fnd/fnd.vcxproj.filters | 54 + lib/fnd/makefile | 33 + lib/fnd/memory_blob.cpp | 58 + lib/fnd/memory_blob.h | 41 + lib/fnd/memory_blob.o | Bin 0 -> 33608 bytes lib/fnd/string_conv.cpp | 147 ++ lib/fnd/string_conv.h | 50 + lib/fnd/string_conv.o | Bin 0 -> 61992 bytes lib/fnd/types.h | 59 + lib/libcrypto.a | Bin 0 -> 176472 bytes lib/libfnd.a | Bin 0 -> 124986 bytes lib/libnx.a | 1 + lib/makefile | 10 + lib/nx/makefile | 33 + lib/nx/nx.vcxproj | 119 ++ lib/nx/nx.vcxproj.filters | 17 + makefile | 0 57 files changed, 12555 insertions(+) create mode 100644 NXTools.sln create mode 100644 NXTools.vcxproj create mode 100644 NXTools.vcxproj.filters create mode 100644 lib/crypto/aes_ctr_stream.cpp create mode 100644 lib/crypto/aes_ctr_stream.h create mode 100644 lib/crypto/aes_ctr_stream.o create mode 100644 lib/crypto/crypto.cpp create mode 100644 lib/crypto/crypto.h create mode 100644 lib/crypto/crypto.o create mode 100644 lib/crypto/crypto.vcxproj create mode 100644 lib/crypto/crypto.vcxproj.filters create mode 100644 lib/crypto/makefile create mode 100644 lib/crypto/polarssl/aes.c create mode 100644 lib/crypto/polarssl/aes.h create mode 100644 lib/crypto/polarssl/aes.o create mode 100644 lib/crypto/polarssl/base64.c create mode 100644 lib/crypto/polarssl/base64.h create mode 100644 lib/crypto/polarssl/base64.o create mode 100644 lib/crypto/polarssl/bignum.c create mode 100644 lib/crypto/polarssl/bignum.h create mode 100644 lib/crypto/polarssl/bignum.o create mode 100644 lib/crypto/polarssl/bn_mul.h create mode 100644 lib/crypto/polarssl/config.h create mode 100644 lib/crypto/polarssl/rsa.c create mode 100644 lib/crypto/polarssl/rsa.h create mode 100644 lib/crypto/polarssl/rsa.o create mode 100644 lib/crypto/polarssl/sha1.c create mode 100644 lib/crypto/polarssl/sha1.h create mode 100644 lib/crypto/polarssl/sha1.o create mode 100644 lib/crypto/polarssl/sha2.c create mode 100644 lib/crypto/polarssl/sha2.h create mode 100644 lib/crypto/polarssl/sha2.o create mode 100644 lib/fnd/elf.h create mode 100644 lib/fnd/exception.cpp create mode 100644 lib/fnd/exception.h create mode 100644 lib/fnd/exception.o create mode 100644 lib/fnd/file_io.cpp create mode 100644 lib/fnd/file_io.h create mode 100644 lib/fnd/file_io.o create mode 100644 lib/fnd/fnd.vcxproj create mode 100644 lib/fnd/fnd.vcxproj.filters create mode 100644 lib/fnd/makefile create mode 100644 lib/fnd/memory_blob.cpp create mode 100644 lib/fnd/memory_blob.h create mode 100644 lib/fnd/memory_blob.o create mode 100644 lib/fnd/string_conv.cpp create mode 100644 lib/fnd/string_conv.h create mode 100644 lib/fnd/string_conv.o create mode 100644 lib/fnd/types.h create mode 100644 lib/libcrypto.a create mode 100644 lib/libfnd.a create mode 100644 lib/libnx.a create mode 100644 lib/makefile create mode 100644 lib/nx/makefile create mode 100644 lib/nx/nx.vcxproj create mode 100644 lib/nx/nx.vcxproj.filters create mode 100644 makefile diff --git a/NXTools.sln b/NXTools.sln new file mode 100644 index 0000000..a231123 --- /dev/null +++ b/NXTools.sln @@ -0,0 +1,48 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfnd", "lib\fnd\fnd.vcxproj", "{4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcrypto", "lib\crypto\crypto.vcxproj", "{6ADBB60D-DBA0-411D-BD2D-A355EF8E0FE1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libnx", "lib\nx\nx.vcxproj", "{91BA9E79-8242-4F7D-B997-0DFEC95EA22B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Debug|x64.ActiveCfg = Debug|x64 + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Debug|x64.Build.0 = Debug|x64 + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Debug|x86.ActiveCfg = Debug|Win32 + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Debug|x86.Build.0 = Debug|Win32 + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Release|x64.ActiveCfg = Release|x64 + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Release|x64.Build.0 = Release|x64 + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Release|x86.ActiveCfg = Release|Win32 + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Release|x86.Build.0 = Release|Win32 + {6ADBB60D-DBA0-411D-BD2D-A355EF8E0FE1}.Debug|x64.ActiveCfg = Debug|x64 + {6ADBB60D-DBA0-411D-BD2D-A355EF8E0FE1}.Debug|x64.Build.0 = Debug|x64 + {6ADBB60D-DBA0-411D-BD2D-A355EF8E0FE1}.Debug|x86.ActiveCfg = Debug|Win32 + {6ADBB60D-DBA0-411D-BD2D-A355EF8E0FE1}.Debug|x86.Build.0 = Debug|Win32 + {6ADBB60D-DBA0-411D-BD2D-A355EF8E0FE1}.Release|x64.ActiveCfg = Release|x64 + {6ADBB60D-DBA0-411D-BD2D-A355EF8E0FE1}.Release|x64.Build.0 = Release|x64 + {6ADBB60D-DBA0-411D-BD2D-A355EF8E0FE1}.Release|x86.ActiveCfg = Release|Win32 + {6ADBB60D-DBA0-411D-BD2D-A355EF8E0FE1}.Release|x86.Build.0 = Release|Win32 + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Debug|x64.ActiveCfg = Debug|x64 + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Debug|x64.Build.0 = Debug|x64 + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Debug|x86.ActiveCfg = Debug|Win32 + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Debug|x86.Build.0 = Debug|Win32 + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Release|x64.ActiveCfg = Release|x64 + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Release|x64.Build.0 = Release|x64 + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Release|x86.ActiveCfg = Release|Win32 + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/NXTools.vcxproj b/NXTools.vcxproj new file mode 100644 index 0000000..647aa09 --- /dev/null +++ b/NXTools.vcxproj @@ -0,0 +1,119 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {0A4197A1-76AD-4BF7-A29D-5CED369B72FD} + NXTools + 10.0.15063.0 + libnx + + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + \ No newline at end of file diff --git a/NXTools.vcxproj.filters b/NXTools.vcxproj.filters new file mode 100644 index 0000000..6a1782f --- /dev/null +++ b/NXTools.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + \ No newline at end of file diff --git a/lib/crypto/aes_ctr_stream.cpp b/lib/crypto/aes_ctr_stream.cpp new file mode 100644 index 0000000..dc8d5f7 --- /dev/null +++ b/lib/crypto/aes_ctr_stream.cpp @@ -0,0 +1,138 @@ +#include "aes_ctr_stream.h" + +using namespace crypto; + +AesCtrStream::AesCtrStream() +{ +} + + +AesCtrStream::~AesCtrStream() +{ +} + +void AesCtrStream::seek(size_t offset) +{ + offset_ = offset; + seek_internal(offset_); +} + +void AesCtrStream::read(size_t size, uint8_t * out) +{ + size_t read_len = 0; + size_t read_size = 0; + for (size_t pos = 0; pos < size; pos += read_size, offset_ += read_size) + { + // calculate read size + read_size = (size - pos) < kIoBufferLen ? (size - pos) : kIoBufferLen; + + // read data + read_internal(read_size, read_len, io_buffer_); + if (read_size != read_len) + { + throw fnd::Exception(kModuleName, "Stream read length unexpected"); + } + + // crypt data + GenerateXorPad(offset_); + xor_data(read_size, pad_buffer_, io_buffer_, out + pos); + } +} + +void AesCtrStream::read(size_t offset, size_t size, uint8_t * out) +{ + seek(offset); + read(size, out); +} + +void AesCtrStream::write(size_t size, const uint8_t * in) +{ + size_t write_len = 0; + size_t write_size = 0; + for (size_t pos = 0; pos < size; pos += write_size, offset_ += write_size) + { + // calculate write size + write_size = (size - pos) < kIoBufferLen ? (size - pos) : kIoBufferLen; + + // crypt data + GenerateXorPad(offset_); + xor_data(write_size, pad_buffer_, in + pos, io_buffer_); + + // write data + write_internal(write_size, write_len, io_buffer_); + if (write_size != write_len) + { + throw fnd::Exception(kModuleName, "Stream write length unexpected"); + } + } +} + +void AesCtrStream::write(size_t offset, size_t size, const uint8_t * in) +{ + seek(offset); + write(size, in); +} + +void AesCtrStream::AddRegion(size_t start, size_t end, const uint8_t aes_key[crypto::kAes128KeySize], const uint8_t aes_ctr[crypto::kAesBlockSize]) +{ + if (start >= end) + { + throw fnd::Exception(kModuleName, "Illegal start/end position"); + } + if (aes_key == nullptr || aes_ctr == nullptr) + { + throw fnd::Exception(kModuleName, "Illegal aes configuration (nullptr)"); + } + + regions_.push_back(CryptRegion(start, end, aes_key, aes_ctr)); +} + +void AesCtrStream::GenerateXorPad(size_t start) +{ + size_t pad_size = 0; + for (size_t pos = 0; pos < kIoBufferLen; pos += pad_size) + { + CryptRegion* cur_region = nullptr; + CryptRegion* next_region = nullptr; + for (size_t idx = 0; idx < regions_.size(); idx++) + { + if (regions_[idx].is_in_region(start + pos)) + { + cur_region = ®ions_[idx]; + } + else if (regions_[idx].start() > (start + pos) && (next_region == nullptr || next_region->start() > regions_[idx].start())) + { + next_region = ®ions_[idx]; + } + } + + // if this exists in the a crypto region + if (cur_region != nullptr) + { + pad_size = cur_region->remaining_size(start + pos); + if (pad_size > kIoBufferLen - pos) + { + pad_size = kIoBufferLen - pos; + } + cur_region->GenerateXorpad(start + pos, pad_size, pad_buffer_ + pos); + } + + // there is a crypto region ahead, bridge the gap + else if (next_region != nullptr) + { + pad_size = next_region->start() - (start + pos); + if (pad_size > kIoBufferLen - pos) + { + pad_size = kIoBufferLen - pos; + } + memset(pad_buffer_ + pos, 0, pad_size); + } + // there are no more crypto regions + else + { + pad_size = kIoBufferLen - pos; + memset(pad_buffer_ + pos, 0, pad_size); + } + } + +} diff --git a/lib/crypto/aes_ctr_stream.h b/lib/crypto/aes_ctr_stream.h new file mode 100644 index 0000000..ace3a87 --- /dev/null +++ b/lib/crypto/aes_ctr_stream.h @@ -0,0 +1,162 @@ +#pragma once +#include +#include +#include +#include + +namespace crypto +{ + class AesCtrStream + { + public: + AesCtrStream(); + ~AesCtrStream(); + + void seek(size_t offset); + void read(size_t size, uint8_t* out); + void read(size_t offset, size_t size, uint8_t* out); + void write(size_t size, const uint8_t* in); + void write(size_t offset, size_t size, const uint8_t* in); + + void AddRegion(size_t start, size_t end, const uint8_t aes_key[crypto::kAes128KeySize], const uint8_t aes_ctr[crypto::kAesBlockSize]); + + protected: + // Virtual methods for implementation of seek/read/write + virtual void seek_internal(size_t offset) = 0; + virtual void read_internal(size_t size, size_t& read_len, uint8_t* out) = 0; + virtual void write_internal(size_t size, size_t& write_len, const uint8_t* in) = 0; + + private: + const std::string kModuleName = "AES_CTR_STREAM"; + static const size_t kIoBufferLen = 0x10000; + + // private implementation of crypto region + class CryptRegion + { + public: + // stubbed constructor + CryptRegion() : + start_(0), + end_(0), + is_plaintext_(true) + { + CleanUp(); + } + + // plaintext constructor + CryptRegion(size_t start, size_t end) : + start_(start), + end_(end), + is_plaintext_(true) + { + CleanUp(); + } + + // encrypted constructor + CryptRegion(size_t start, size_t end, const uint8_t aes_key[crypto::kAes128KeySize], const uint8_t aes_ctr[crypto::kAesBlockSize]) : + start_(start), + end_(end), + is_plaintext_(false) + { + CleanUp(); + memcpy(aes_key_, aes_key, crypto::kAes128KeySize); + memcpy(ctr_init_, aes_ctr, crypto::kAesBlockSize); + memcpy(ctr_, ctr_init_, crypto::kAesBlockSize); + } + + // destructor + ~CryptRegion() + { + CleanUp(); + } + + size_t start() const { return start_; } + size_t end() const { return end_; } + size_t size() const { return end_ - start_; } + size_t remaining_size(size_t start) const { return end_ - start; } + const uint8_t* aes_key() const { return aes_key_; } + uint8_t* aes_ctr() { return ctr_; } + + bool is_in_region(size_t start) const { return start >= start_ && start < end_; } + bool is_in_region(size_t start, size_t end) const { return is_in_region(start) && end > start_ && end <= end_; } + + void UpdateAesCtr(size_t start) + { + if (is_in_region(start)) + crypto::AesIncrementCounter(ctr_init_, ((start - start_) >> 4), ctr_); + } + + void GenerateXorpad(size_t start, size_t size, uint8_t* out) + { + // don't operate if requested size exceeds region size + if (is_in_region(start, start + size) == false) + { + return; + } + + if (is_plaintext_ == true) + { + memset(out, 0, size); + return; + } + + // parameters + size_t block_offset = (start - start_) & 0xf; + size_t block_num = size >> 4; + for (size_t pos = 0; pos < block_num; pos += (kPadBufferLen >> 4)) + { + // clear pad buffer + memset(pad_buffer_, 0, kPadBufferCapacity); + + // encrypt pad buffer to create xorpad + UpdateAesCtr(start + (pos << 4)); + crypto::AesCtr(pad_buffer_, kPadBufferCapacity, aes_key(), aes_ctr(), pad_buffer_); + + // determine the number of blocks to copy to xorpad + size_t copy_size = kPadBufferLen < ((block_num - pos) << 4) ? kPadBufferLen : ((block_num - pos) << 4); + + // copy + memcpy(out + (pos << 4), pad_buffer_ + block_offset, copy_size); + } + } + private: + static const size_t kPadBufferLen = 0x10000; + static const size_t kPadBufferCapacity = kPadBufferLen + crypto::kAesBlockSize; // has an extra block to accomodate non block aligned starts + + size_t start_; + size_t end_; + bool is_plaintext_; + uint8_t aes_key_[crypto::kAes128KeySize]; + uint8_t ctr_init_[crypto::kAesBlockSize]; + uint8_t ctr_[crypto::kAesBlockSize]; + uint8_t pad_buffer_[kPadBufferCapacity]; + + void CleanUp() + { + memset(aes_key_, 0, crypto::kAes128KeySize); + memset(ctr_init_, 0, crypto::kAesBlockSize); + memset(ctr_, 0, crypto::kAesBlockSize); + } + }; + + + + inline void xor_data(size_t size, const uint8_t* data1, const uint8_t* data2, uint8_t* out) + { + for (size_t idx = 0; idx < size; idx++) + { + out[idx] = data1[idx] ^ data2[idx]; + } + } + + // Crypto Regions + size_t offset_; + std::vector regions_; + + // IO Buffer + uint8_t io_buffer_[kIoBufferLen]; + uint8_t pad_buffer_[kIoBufferLen]; + + void GenerateXorPad(size_t start); + }; +} \ No newline at end of file diff --git a/lib/crypto/aes_ctr_stream.o b/lib/crypto/aes_ctr_stream.o new file mode 100644 index 0000000000000000000000000000000000000000..a4d7d788b711b39f42f02eedaf255e8dfbb933bd GIT binary patch literal 51496 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 literal 0 HcmV?d00001 diff --git a/lib/crypto/crypto.cpp b/lib/crypto/crypto.cpp new file mode 100644 index 0000000..52847f0 --- /dev/null +++ b/lib/crypto/crypto.cpp @@ -0,0 +1,229 @@ +#include "crypto.h" +#include "polarssl/aes.h" +#include "polarssl/sha1.h" +#include "polarssl/sha2.h" +#include "polarssl/rsa.h" + +using namespace crypto; + +int GetWrappedHashType(HashType type) +{ + switch (type) + { + case crypto::HASH_SHA1: + return SIG_RSA_SHA1; + break; + case crypto::HASH_SHA256: + return SIG_RSA_SHA256; + break; + default: + return SIG_RSA_RAW; + break; + } + return 0; +} + +uint32_t GetWrappedHashSize(HashType type) +{ + uint32_t size = 0; + + switch (type) + { + case crypto::HASH_SHA1: + size = kSha1HashLen; + break; + case crypto::HASH_SHA256: + size = kSha256HashLen; + break; + default: + break; + } + return size; +} + +inline uint32_t getbe32(const uint8_t* data) { return data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; } +inline void putbe32(uint8_t* data, uint32_t val) { data[0] = val >> 24; data[1] = val >> 16; data[2] = val >> 8; data[3] = val; } + +void crypto::Sha1(const uint8_t* in, uint64_t size, uint8_t hash[kSha1HashLen]) +{ + sha1(in, size, hash); +} + +void crypto::Sha256(const uint8_t* in, uint64_t size, uint8_t hash[kSha256HashLen]) +{ + sha2(in, size, hash, false); +} + +void crypto::AesCtr(const uint8_t* in, uint64_t size, const uint8_t key[kAes128KeySize], uint8_t ctr[kAesBlockSize], uint8_t* out) +{ + aes_context ctx; + uint8_t block[kAesBlockSize] = { 0 }; + size_t counterOffset = 0; + + aes_setkey_enc(&ctx, key, 128); + aes_crypt_ctr(&ctx, size, &counterOffset, ctr, block, in, out); +} + +void crypto::AesIncrementCounter(const uint8_t in[kAesBlockSize], size_t block_num, uint8_t out[kAesBlockSize]) +{ + memcpy(out, in, kAesBlockSize); + + uint32_t ctr[4]; + ctr[3] = getbe32(&in[0]); + ctr[2] = getbe32(&in[4]); + ctr[1] = getbe32(&in[8]); + ctr[0] = getbe32(&in[12]); + + for (uint32_t i = 0; i < 4; i++) { + uint64_t total = ctr[i] + block_num; + // if there wasn't a wrap around, add the two together and exit + if (total <= 0xffffffff) { + ctr[i] += block_num; + break; + } + + // add the difference + ctr[i] = (uint32_t)(total - 0x100000000); + // carry to next word + block_num = (uint32_t)(total >> 32); + } + + putbe32(&out[0], ctr[3]); + putbe32(&out[4], ctr[2]); + putbe32(&out[8], ctr[1]); + putbe32(&out[12], ctr[0]); +} + +void crypto::AesCbcDecrypt(const uint8_t* in, uint64_t size, const uint8_t key[kAes128KeySize], uint8_t iv[kAesBlockSize], uint8_t* out) +{ + aes_context ctx; + aes_setkey_dec(&ctx, key, 128); + aes_crypt_cbc(&ctx, AES_DECRYPT, size, iv, in, out); +} + +void crypto::AesCbcEncrypt(const uint8_t* in, uint64_t size, const uint8_t key[kAes128KeySize], uint8_t iv[kAesBlockSize], uint8_t* out) +{ + aes_context ctx; + aes_setkey_enc(&ctx, key, 128); + aes_crypt_cbc(&ctx, AES_ENCRYPT, size, iv, in, out); +} + +int crypto::RsaSign(const sRsa1024Key & key, HashType hash_type, const uint8_t * hash, uint8_t signature[kRsa1024Size]) +{ + int ret; + rsa_context ctx; + rsa_init(&ctx, RSA_PKCS_V15, 0); + + ctx.len = kRsa1024Size; + mpi_read_binary(&ctx.D, key.priv_exponent, ctx.len); + mpi_read_binary(&ctx.N, key.modulus, ctx.len); + + ret = rsa_rsassa_pkcs1_v15_sign(&ctx, RSA_PRIVATE, GetWrappedHashType(hash_type), GetWrappedHashSize(hash_type), hash, signature); + + rsa_free(&ctx); + + return ret; +} + +int crypto::RsaVerify(const sRsa1024Key & key, HashType hash_type, const uint8_t * hash, const uint8_t signature[kRsa1024Size]) +{ + static const uint8_t public_exponent[3] = { 0x01, 0x00, 0x01 }; + + int ret; + rsa_context ctx; + rsa_init(&ctx, RSA_PKCS_V15, 0); + + ctx.len = kRsa1024Size; + mpi_read_binary(&ctx.E, public_exponent, sizeof(public_exponent)); + mpi_read_binary(&ctx.N, key.modulus, ctx.len); + + ret = rsa_rsassa_pkcs1_v15_verify(&ctx, RSA_PUBLIC, GetWrappedHashType(hash_type), GetWrappedHashSize(hash_type), hash, signature); + + rsa_free(&ctx); + + return ret; +} + +int crypto::RsaSign(const sRsa2048Key & key, HashType hash_type, const uint8_t * hash, uint8_t signature[kRsa2048Size]) +{ + int ret; + rsa_context ctx; + rsa_init(&ctx, RSA_PKCS_V15, 0); + + ctx.len = kRsa2048Size; + mpi_read_binary(&ctx.D, key.priv_exponent, ctx.len); + mpi_read_binary(&ctx.N, key.modulus, ctx.len); + + ret = rsa_rsassa_pkcs1_v15_sign(&ctx, RSA_PRIVATE, GetWrappedHashType(hash_type), GetWrappedHashSize(hash_type), hash, signature); + + rsa_free(&ctx); + + return ret; +} + +int crypto::RsaVerify(const sRsa2048Key & key, HashType hash_type, const uint8_t * hash, const uint8_t signature[kRsa2048Size]) +{ + static const uint8_t public_exponent[3] = { 0x01, 0x00, 0x01 }; + + int ret; + rsa_context ctx; + rsa_init(&ctx, RSA_PKCS_V15, 0); + + ctx.len = kRsa2048Size; + mpi_read_binary(&ctx.E, public_exponent, sizeof(public_exponent)); + mpi_read_binary(&ctx.N, key.modulus, ctx.len); + + ret = rsa_rsassa_pkcs1_v15_verify(&ctx, RSA_PUBLIC, GetWrappedHashType(hash_type), GetWrappedHashSize(hash_type), hash, signature); + + rsa_free(&ctx); + + return ret; +} + +int crypto::RsaSign(const sRsa4096Key & key, HashType hash_type, const uint8_t * hash, uint8_t signature[kRsa4096Size]) +{ + int ret; + rsa_context ctx; + rsa_init(&ctx, RSA_PKCS_V15, 0); + + ctx.len = kRsa4096Size; + mpi_read_binary(&ctx.D, key.priv_exponent, ctx.len); + mpi_read_binary(&ctx.N, key.modulus, ctx.len); + + ret = rsa_rsassa_pkcs1_v15_sign(&ctx, RSA_PRIVATE, GetWrappedHashType(hash_type), GetWrappedHashSize(hash_type), hash, signature); + + rsa_free(&ctx); + + return ret; +} + +int crypto::RsaVerify(const sRsa4096Key & key, HashType hash_type, const uint8_t * hash, const uint8_t signature[kRsa4096Size]) +{ + static const uint8_t public_exponent[3] = { 0x01, 0x00, 0x01 }; + + int ret; + rsa_context ctx; + rsa_init(&ctx, RSA_PKCS_V15, 0); + + ctx.len = kRsa4096Size; + mpi_read_binary(&ctx.E, public_exponent, sizeof(public_exponent)); + mpi_read_binary(&ctx.N, key.modulus, ctx.len); + + ret = rsa_rsassa_pkcs1_v15_verify(&ctx, RSA_PUBLIC, GetWrappedHashType(hash_type), GetWrappedHashSize(hash_type), hash, signature); + + rsa_free(&ctx); + + return ret; +} + +int crypto::EcdsaSign(const sEcc240PrivateKey & key, HashType hash_type, const uint8_t * hash, sEcc240Point & signature) +{ + return 1; +} + +int crypto::EcdsaVerify(const sEcc240Point& key, HashType hash_type, const uint8_t* hash, const sEcc240Point& signature) +{ + return 1; +} + + diff --git a/lib/crypto/crypto.h b/lib/crypto/crypto.h new file mode 100644 index 0000000..d368b5c --- /dev/null +++ b/lib/crypto/crypto.h @@ -0,0 +1,152 @@ +#pragma once +#include +#include + +namespace crypto +{ + const size_t kSha1HashLen = 20; + const size_t kSha256HashLen = 32; + const size_t kAes128KeySize = 0x10; + const size_t kAesBlockSize = 0x10; + const size_t KAesCcmNonceSize = 0xc; + const size_t kRsa1024Size = 0x80; + const size_t kRsa2048Size = 0x100; + const size_t kRsa4096Size = 0x200; + const size_t kRsaPublicExponentSize = 4; + const size_t kEcdsaSize = 0x3C; + const size_t kEcParam240Bit = 0x1E; + + enum HashType + { + HASH_SHA1, + HASH_SHA256 + }; + + enum SignType + { + SIGN_RSA_1024, + SIGN_RSA_2048, + SIGN_RSA_4096, + SIGN_ECDSA_240, + }; + +#pragma pack (push, 1) + struct sAes128Key + { + uint8_t key[kAes128KeySize]; + + void set(const uint8_t key[kAes128KeySize]) + { + memcpy(this->key, key, kAes128KeySize); + } + }; + + struct sAesIvCtr + { + uint8_t iv[kAesBlockSize]; + }; + + struct sRsa1024Key + { + uint8_t modulus[kRsa1024Size]; + uint8_t priv_exponent[kRsa1024Size]; + uint8_t public_exponent[kRsaPublicExponentSize]; + + void operator=(const sRsa1024Key& other) + { + memcpy(this->modulus, modulus, kRsa1024Size); + memcpy(this->priv_exponent, priv_exponent, kRsa1024Size); + memcpy(this->public_exponent, other.public_exponent, kRsaPublicExponentSize); + } + + bool operator==(const sRsa1024Key& other) + { + return memcmp(this->modulus, other.modulus, kRsa1024Size) == 0 && memcmp(this->priv_exponent, other.priv_exponent, kRsa1024Size) == 0 && memcpy(this->public_exponent, other.public_exponent, kRsaPublicExponentSize) == 0; + } + }; + + struct sRsa2048Key + { + uint8_t modulus[kRsa2048Size]; + uint8_t priv_exponent[kRsa2048Size]; + uint8_t public_exponent[kRsaPublicExponentSize]; + + void operator=(const sRsa2048Key& other) + { + memcpy(this->modulus, other.modulus, kRsa2048Size); + memcpy(this->priv_exponent, other.priv_exponent, kRsa2048Size); + memcpy(this->public_exponent, other.public_exponent, kRsaPublicExponentSize); + } + + bool operator==(const sRsa2048Key& other) + { + return memcmp(this->modulus, other.modulus, kRsa2048Size) == 0 && memcmp(this->priv_exponent, other.priv_exponent, kRsa2048Size) == 0 && memcpy(this->public_exponent, other.public_exponent, kRsaPublicExponentSize) == 0; + } + }; + + struct sRsa4096Key + { + uint8_t modulus[kRsa4096Size]; + uint8_t priv_exponent[kRsa4096Size]; + uint8_t public_exponent[kRsaPublicExponentSize]; + + void operator=(const sRsa4096Key& other) + { + memcpy(this->modulus, other.modulus, kRsa4096Size); + memcpy(this->priv_exponent, other.priv_exponent, kRsa4096Size); + memcpy(this->public_exponent, other.public_exponent, kRsaPublicExponentSize); + } + + bool operator==(const sRsa4096Key& other) + { + return memcmp(this->modulus, other.modulus, kRsa4096Size) == 0 && memcmp(this->priv_exponent, other.priv_exponent, kRsa4096Size) == 0 && memcpy(this->public_exponent, other.public_exponent, kRsaPublicExponentSize) == 0; + } + }; + + struct sEcc240Point + { + uint8_t r[kEcParam240Bit]; + uint8_t s[kEcParam240Bit]; + + void operator=(const sEcc240Point& other) + { + memcpy(this->r, other.r, kEcParam240Bit); + memcpy(this->s, other.s, kEcParam240Bit); + } + + bool operator==(const sEcc240Point& other) + { + return memcmp(this->r, other.r, kEcParam240Bit) == 0 && memcmp(this->s, other.s, kEcParam240Bit) == 0; + } + }; + + struct sEcc240PrivateKey + { + uint8_t k[kEcParam240Bit]; // stub + }; +#pragma pack (pop) + + void Sha1(const uint8_t* in, uint64_t size, uint8_t hash[kSha1HashLen]); + void Sha256(const uint8_t* in, uint64_t size, uint8_t hash[kSha256HashLen]); + + // aes-128 + void AesCtr(const uint8_t* in, uint64_t size, const uint8_t key[kAes128KeySize], uint8_t ctr[kAesBlockSize], uint8_t* out); + void AesIncrementCounter(const uint8_t in[kAesBlockSize], size_t block_num, uint8_t out[kAesBlockSize]); + + void AesCbcDecrypt(const uint8_t* in, uint64_t size, const uint8_t key[kAes128KeySize], uint8_t iv[kAesBlockSize], uint8_t* out); + void AesCbcEncrypt(const uint8_t* in, uint64_t size, const uint8_t key[kAes128KeySize], uint8_t iv[kAesBlockSize], uint8_t* out); + + + // rsa1024 + int RsaSign(const sRsa1024Key& key, HashType hash_type, const uint8_t* hash, uint8_t signature[kRsa1024Size]); + int RsaVerify(const sRsa1024Key& key, HashType hash_type, const uint8_t* hash, const uint8_t signature[kRsa1024Size]); + // rsa2048 + int RsaSign(const sRsa2048Key& key, HashType hash_type, const uint8_t* hash, uint8_t signature[kRsa2048Size]); + int RsaVerify(const sRsa2048Key& key, HashType hash_type, const uint8_t* hash, const uint8_t signature[kRsa2048Size]); + // rsa4096 + int RsaSign(const sRsa4096Key& key, HashType hash_type, const uint8_t* hash, uint8_t signature[kRsa4096Size]); + int RsaVerify(const sRsa4096Key& key, HashType hash_type, const uint8_t* hash, const uint8_t signature[kRsa4096Size]); + // ecdsa + int EcdsaSign(const sEcc240PrivateKey& key, HashType hash_type, const uint8_t* hash, sEcc240Point& signature); + int EcdsaVerify(const sEcc240Point& key, HashType hash_type, const uint8_t* hash, const sEcc240Point& signature); +} \ No newline at end of file diff --git a/lib/crypto/crypto.o b/lib/crypto/crypto.o new file mode 100644 index 0000000000000000000000000000000000000000..fdd8387ec38173d781bbc9d0b20e415e920c69b4 GIT binary patch literal 9656 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 O{0fcJK^N!y+CKn|No0)x literal 0 HcmV?d00001 diff --git a/lib/crypto/crypto.vcxproj b/lib/crypto/crypto.vcxproj new file mode 100644 index 0000000..a5118d2 --- /dev/null +++ b/lib/crypto/crypto.vcxproj @@ -0,0 +1,128 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {6ADBB60D-DBA0-411D-BD2D-A355EF8E0FE1} + crypto + 10.0.15063.0 + libcrypto + + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/crypto/crypto.vcxproj.filters b/lib/crypto/crypto.vcxproj.filters new file mode 100644 index 0000000..7335da3 --- /dev/null +++ b/lib/crypto/crypto.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + + + + \ No newline at end of file diff --git a/lib/crypto/makefile b/lib/crypto/makefile new file mode 100644 index 0000000..6b16e04 --- /dev/null +++ b/lib/crypto/makefile @@ -0,0 +1,33 @@ +# Sources +SRC_DIR = . polarssl +OBJS = $(foreach dir,$(SRC_DIR),$(subst .cpp,.o,$(wildcard $(dir)/*.cpp))) $(foreach dir,$(SRC_DIR),$(subst .c,.o,$(wildcard $(dir)/*.c))) + +INC_DIR = .. +INCS = $(foreach dir,$(INC_DIR), -I"$(dir)") + +# Compiler Settings +CXXFLAGS = -std=c++11 $(INCS) -D__STDC_FORMAT_MACROS -Wall -Wno-unused-but-set-variable -Wno-unused-value +ifeq ($(OS),Windows_NT) + # Windows Only Flags/Libs + CC = x86_64-w64-mingw32-gcc + CXX = x86_64-w64-mingw32-g++ + CFLAGS += + CXXFLAGS += +else + # *nix Only Flags/Libs + CFLAGS += + CXXFLAGS += +endif + +# Output +OUTPUT = ../lib$(shell basename $(CURDIR)).a + +main: build + +rebuild: clean build + +build: $(OBJS) + ar cr -o $(OUTPUT) $(OBJS) + +clean: + rm -rf $(OUTPUT) $(OBJS) \ No newline at end of file diff --git a/lib/crypto/polarssl/aes.c b/lib/crypto/polarssl/aes.c new file mode 100644 index 0000000..65c2b1f --- /dev/null +++ b/lib/crypto/polarssl/aes.c @@ -0,0 +1,1352 @@ +/* + * FIPS-197 compliant AES implementation + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + */ + +#include "config.h" + +#if defined(POLARSSL_AES_C) + +#include "aes.h" +#if defined(POLARSSL_PADLOCK_C) +#include "padlock.h" +#endif + +#if !defined(POLARSSL_AES_ALT) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ +} +#endif + +#if defined(POLARSSL_PADLOCK_C) && \ + ( defined(POLARSSL_HAVE_X86) || defined(PADLOCK_ALIGN16) ) +static int aes_padlock_ace = -1; +#endif + +#if defined(POLARSSL_AES_ROM_TABLES) +/* + * Forward S-box + */ +static const unsigned char FSb[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 +}; + +/* + * Forward tables + */ +#define FT \ +\ + V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ + V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ + V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ + V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ + V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ + V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ + V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ + V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ + V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ + V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ + V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ + V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ + V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ + V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ + V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ + V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ + V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ + V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ + V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ + V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ + V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ + V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ + V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ + V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ + V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ + V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ + V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ + V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ + V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ + V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ + V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ + V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ + V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ + V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ + V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ + V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ + V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ + V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ + V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ + V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ + V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ + V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ + V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ + V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ + V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ + V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ + V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ + V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ + V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ + V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ + V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ + V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ + V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ + V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ + V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ + V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ + V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ + V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ + V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ + V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ + V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ + V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ + V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ + V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t FT0[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t FT1[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t FT2[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t FT3[256] = { FT }; +#undef V + +#undef FT + +/* + * Reverse S-box + */ +static const unsigned char RSb[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D +}; + +/* + * Reverse tables + */ +#define RT \ +\ + V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ + V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ + V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ + V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ + V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ + V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ + V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ + V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ + V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ + V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ + V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ + V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ + V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ + V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ + V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ + V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ + V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ + V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ + V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ + V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ + V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ + V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ + V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ + V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ + V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ + V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ + V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ + V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ + V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ + V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ + V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ + V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ + V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ + V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ + V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ + V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ + V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ + V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ + V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ + V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ + V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ + V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ + V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ + V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ + V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ + V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ + V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ + V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ + V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ + V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ + V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ + V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ + V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ + V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ + V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ + V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ + V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ + V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ + V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ + V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ + V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ + V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ + V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ + V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t RT0[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t RT1[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t RT2[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t RT3[256] = { RT }; +#undef V + +#undef RT + +/* + * Round constants + */ +static const uint32_t RCON[10] = +{ + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x0000001B, 0x00000036 +}; + +#else + +/* + * Forward S-box & tables + */ +static unsigned char FSb[256]; +static uint32_t FT0[256]; +static uint32_t FT1[256]; +static uint32_t FT2[256]; +static uint32_t FT3[256]; + +/* + * Reverse S-box & tables + */ +static unsigned char RSb[256]; +static uint32_t RT0[256]; +static uint32_t RT1[256]; +static uint32_t RT2[256]; +static uint32_t RT3[256]; + +/* + * Round constants + */ +static uint32_t RCON[10]; + +/* + * Tables generation code + */ +#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) +#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) +#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 ) + +static int aes_init_done = 0; + +static void aes_gen_tables( void ) +{ + int i, x, y, z; + int pow[256]; + int log[256]; + + /* + * compute pow and log tables over GF(2^8) + */ + for( i = 0, x = 1; i < 256; i++ ) + { + pow[i] = x; + log[x] = i; + x = ( x ^ XTIME( x ) ) & 0xFF; + } + + /* + * calculate the round constants + */ + for( i = 0, x = 1; i < 10; i++ ) + { + RCON[i] = (uint32_t) x; + x = XTIME( x ) & 0xFF; + } + + /* + * generate the forward and reverse S-boxes + */ + FSb[0x00] = 0x63; + RSb[0x63] = 0x00; + + for( i = 1; i < 256; i++ ) + { + x = pow[255 - log[i]]; + + y = x; y = ( (y << 1) | (y >> 7) ) & 0xFF; + x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF; + x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF; + x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF; + x ^= y ^ 0x63; + + FSb[i] = (unsigned char) x; + RSb[x] = (unsigned char) i; + } + + /* + * generate the forward and reverse tables + */ + for( i = 0; i < 256; i++ ) + { + x = FSb[i]; + y = XTIME( x ) & 0xFF; + z = ( y ^ x ) & 0xFF; + + FT0[i] = ( (uint32_t) y ) ^ + ( (uint32_t) x << 8 ) ^ + ( (uint32_t) x << 16 ) ^ + ( (uint32_t) z << 24 ); + + FT1[i] = ROTL8( FT0[i] ); + FT2[i] = ROTL8( FT1[i] ); + FT3[i] = ROTL8( FT2[i] ); + + x = RSb[i]; + + RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^ + ( (uint32_t) MUL( 0x09, x ) << 8 ) ^ + ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^ + ( (uint32_t) MUL( 0x0B, x ) << 24 ); + + RT1[i] = ROTL8( RT0[i] ); + RT2[i] = ROTL8( RT1[i] ); + RT3[i] = ROTL8( RT2[i] ); + } +} + +#endif + +/* + * AES key schedule (encryption) + */ +int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize ) +{ + unsigned int i; + uint32_t *RK; + +#if !defined(POLARSSL_AES_ROM_TABLES) + if( aes_init_done == 0 ) + { + aes_gen_tables(); + aes_init_done = 1; + + } +#endif + + switch( keysize ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH ); + } + +#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = padlock_supports( PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + + for( i = 0; i < (keysize >> 5); i++ ) + { + GET_UINT32_LE( RK[i], key, i << 2 ); + } + + switch( ctx->nr ) + { + case 10: + + for( i = 0; i < 10; i++, RK += 4 ) + { + RK[4] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 ); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; + } + break; + + case 12: + + for( i = 0; i < 8; i++, RK += 6 ) + { + RK[6] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 ); + + RK[7] = RK[1] ^ RK[6]; + RK[8] = RK[2] ^ RK[7]; + RK[9] = RK[3] ^ RK[8]; + RK[10] = RK[4] ^ RK[9]; + RK[11] = RK[5] ^ RK[10]; + } + break; + + case 14: + + for( i = 0; i < 7; i++, RK += 8 ) + { + RK[8] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 ); + + RK[9] = RK[1] ^ RK[8]; + RK[10] = RK[2] ^ RK[9]; + RK[11] = RK[3] ^ RK[10]; + + RK[12] = RK[4] ^ + ( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); + + RK[13] = RK[5] ^ RK[12]; + RK[14] = RK[6] ^ RK[13]; + RK[15] = RK[7] ^ RK[14]; + } + break; + + default: + + break; + } + + return( 0 ); +} + +/* + * AES key schedule (decryption) + */ +int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize ) +{ + int i, j; + aes_context cty; + uint32_t *RK; + uint32_t *SK; + int ret; + + switch( keysize ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH ); + } + +#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = padlock_supports( PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + + ret = aes_setkey_enc( &cty, key, keysize ); + if( ret != 0 ) + return( ret ); + + SK = cty.rk + cty.nr * 4; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) + { + for( j = 0; j < 4; j++, SK++ ) + { + *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ + RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ + RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ + RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; + } + } + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + memset( &cty, 0, sizeof( aes_context ) ); + + return( 0 ); +} + +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ + FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y3 >> 24 ) & 0xFF ]; \ + \ + X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ + FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y0 >> 24 ) & 0xFF ]; \ + \ + X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ + FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y1 >> 24 ) & 0xFF ]; \ + \ + X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ + FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y2 >> 24 ) & 0xFF ]; \ +} + +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ + RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y1 >> 24 ) & 0xFF ]; \ + \ + X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ + RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y2 >> 24 ) & 0xFF ]; \ + \ + X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ + RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y3 >> 24 ) & 0xFF ]; \ + \ + X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ + RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y0 >> 24 ) & 0xFF ]; \ +} + +/* + * AES-ECB block encryption/decryption + */ +int aes_crypt_ecb( aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + +#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86) + if( aes_padlock_ace ) + { + if( padlock_xcryptecb( ctx, mode, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + RK = ctx->rk; + + GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; + GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; + GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; + GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; + + if( mode == AES_DECRYPT ) + { + for( i = (ctx->nr >> 1) - 1; i > 0; i-- ) + { + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); + } + + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + + X0 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y0 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); + + X1 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y1 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); + + X2 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y2 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); + + X3 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y3 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); + } + else /* AES_ENCRYPT */ + { + for( i = (ctx->nr >> 1) - 1; i > 0; i-- ) + { + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); + } + + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + + X0 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); + + X1 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); + + X2 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); + + X3 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); + } + + PUT_UINT32_LE( X0, output, 0 ); + PUT_UINT32_LE( X1, output, 4 ); + PUT_UINT32_LE( X2, output, 8 ); + PUT_UINT32_LE( X3, output, 12 ); + + return( 0 ); +} + +/* + * AES-CBC buffer encryption/decryption + */ +int aes_crypt_cbc( aes_context *ctx, + int mode, + uint64_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[16]; + + if( length % 16 ) + return( POLARSSL_ERR_AES_INVALID_INPUT_LENGTH ); + +#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86) + if( aes_padlock_ace ) + { + if( padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == AES_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + aes_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + aes_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} + +#if defined(POLARSSL_CIPHER_MODE_CFB) +/* + * AES-CFB128 buffer encryption/decryption + */ +int aes_crypt_cfb128( aes_context *ctx, + int mode, + uint64_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n = *iv_off; + + if( mode == AES_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = (n + 1) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = (n + 1) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /*POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +/* + * AES-CTR buffer encryption/decryption + */ +int aes_crypt_ctr( aes_context *ctx, + uint64_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n = *nc_off; + + while( length-- ) + { + if( n == 0 ) { + aes_crypt_ecb( ctx, AES_ENCRYPT, nonce_counter, stream_block ); + + for( i = 16; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = (n + 1) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* POLARSSL_CIPHER_MODE_CTR */ +#endif /* !POLARSSL_AES_ALT */ + +#if defined(POLARSSL_SELF_TEST) + +#include + +/* + * AES test vectors from: + * + * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip + */ +static const unsigned char aes_test_ecb_dec[3][16] = +{ + { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, + 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, + { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, + 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, + { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, + 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } +}; + +static const unsigned char aes_test_ecb_enc[3][16] = +{ + { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, + 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, + { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, + 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, + { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, + 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } +}; + +static const unsigned char aes_test_cbc_dec[3][16] = +{ + { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, + 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, + { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, + 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, + { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, + 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } +}; + +static const unsigned char aes_test_cbc_enc[3][16] = +{ + { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, + 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, + { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, + 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, + { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, + 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } +}; + +#if defined(POLARSSL_CIPHER_MODE_CFB) +/* + * AES-CFB128 test vectors from: + * + * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + */ +static const unsigned char aes_test_cfb128_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char aes_test_cfb128_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_cfb128_pt[64] = +{ + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, + 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, + 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, + 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 +}; + +static const unsigned char aes_test_cfb128_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, + 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, + 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, + 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, + 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, + 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, + 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, + 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, + 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, + 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, + 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, + 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, + 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, + 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, + 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, + 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } +}; +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +/* + * AES-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc3686.html + */ + +static const unsigned char aes_test_ctr_key[3][16] = +{ + { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, + { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, + { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } +}; + +static const unsigned char aes_test_ctr_nonce_counter[3][16] = +{ + { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } +}; + +static const unsigned char aes_test_ctr_pt[3][48] = +{ + { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23 } +}; + +static const unsigned char aes_test_ctr_ct[3][48] = +{ + { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, + 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 }, + { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, + 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, + 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, + 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 }, + { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9, + 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7, + 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36, + 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53, + 0x25, 0xB2, 0x07, 0x2F } +}; + +static const int aes_test_ctr_len[3] = + { 16, 32, 36 }; +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +/* + * Checkup routine + */ +int aes_self_test( int verbose ) +{ + int i, j, u, v; + unsigned char key[32]; + unsigned char buf[64]; + unsigned char prv[16]; + unsigned char iv[16]; +#if defined(POLARSSL_CIPHER_MODE_CTR) || defined(POLARSSL_CIPHER_MODE_CFB) + size_t offset; +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + int len; + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + aes_context ctx; + + memset( key, 0, 32 ); + + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + printf( " AES-ECB-%3d (%s): ", 128 + u * 64, + ( v == AES_DECRYPT ) ? "dec" : "enc" ); + + memset( buf, 0, 16 ); + + if( v == AES_DECRYPT ) + { + aes_setkey_dec( &ctx, key, 128 + u * 64 ); + + for( j = 0; j < 10000; j++ ) + aes_crypt_ecb( &ctx, v, buf, buf ); + + if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + } + else + { + aes_setkey_enc( &ctx, key, 128 + u * 64 ); + + for( j = 0; j < 10000; j++ ) + aes_crypt_ecb( &ctx, v, buf, buf ); + + if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + printf( "passed\n" ); + } + + if( verbose != 0 ) + printf( "\n" ); + + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + printf( " AES-CBC-%3d (%s): ", 128 + u * 64, + ( v == AES_DECRYPT ) ? "dec" : "enc" ); + + memset( iv , 0, 16 ); + memset( prv, 0, 16 ); + memset( buf, 0, 16 ); + + if( v == AES_DECRYPT ) + { + aes_setkey_dec( &ctx, key, 128 + u * 64 ); + + for( j = 0; j < 10000; j++ ) + aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); + + if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + } + else + { + aes_setkey_enc( &ctx, key, 128 + u * 64 ); + + for( j = 0; j < 10000; j++ ) + { + unsigned char tmp[16]; + + aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); + + memcpy( tmp, prv, 16 ); + memcpy( prv, buf, 16 ); + memcpy( buf, tmp, 16 ); + } + + if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + printf( "passed\n" ); + } + + if( verbose != 0 ) + printf( "\n" ); + +#if defined(POLARSSL_CIPHER_MODE_CFB) + /* + * CFB128 mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + printf( " AES-CFB128-%3d (%s): ", 128 + u * 64, + ( v == AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_cfb128_iv, 16 ); + memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 ); + + offset = 0; + aes_setkey_enc( &ctx, key, 128 + u * 64 ); + + if( v == AES_DECRYPT ) + { + memcpy( buf, aes_test_cfb128_ct[u], 64 ); + aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); + + if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + } + else + { + memcpy( buf, aes_test_cfb128_pt, 64 ); + aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); + + if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + printf( "passed\n" ); + } + + if( verbose != 0 ) + printf( "\n" ); +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + printf( " AES-CTR-128 (%s): ", + ( v == AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 ); + memcpy( key, aes_test_ctr_key[u], 16 ); + + offset = 0; + aes_setkey_enc( &ctx, key, 128 ); + + if( v == AES_DECRYPT ) + { + len = aes_test_ctr_len[u]; + memcpy( buf, aes_test_ctr_ct[u], len ); + + aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf ); + + if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + } + else + { + len = aes_test_ctr_len[u]; + memcpy( buf, aes_test_ctr_pt[u], len ); + + aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf ); + + if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + printf( "passed\n" ); + } + + if( verbose != 0 ) + printf( "\n" ); +#endif /* POLARSSL_CIPHER_MODE_CTR */ + + return( 0 ); +} + +#endif + +#endif diff --git a/lib/crypto/polarssl/aes.h b/lib/crypto/polarssl/aes.h new file mode 100644 index 0000000..92fca54 --- /dev/null +++ b/lib/crypto/polarssl/aes.h @@ -0,0 +1,202 @@ +/** + * \file aes.h + * + * \brief AES block cipher + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_AES_H +#define POLARSSL_AES_H + +#include "config.h" + +#include + +#ifdef _MSC_VER +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +#define AES_ENCRYPT 1 +#define AES_DECRYPT 0 + +#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ +#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ + +#if !defined(POLARSSL_AES_ALT) +// Regular implementation +// + +/** + * \brief AES context structure + */ +typedef struct +{ + int nr; /*!< number of rounds */ + uint32_t *rk; /*!< AES round keys */ + uint32_t buf[68]; /*!< unaligned data */ +} +aes_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief AES key schedule (encryption) + * + * \param ctx AES context to be initialized + * \param key encryption key + * \param keysize must be 128, 192 or 256 + * + * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH + */ +int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize ); + +/** + * \brief AES key schedule (decryption) + * + * \param ctx AES context to be initialized + * \param key decryption key + * \param keysize must be 128, 192 or 256 + * + * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH + */ +int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize ); + +/** + * \brief AES-ECB block encryption/decryption + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if successful + */ +int aes_crypt_ecb( aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief AES-CBC buffer encryption/decryption + * Length should be a multiple of the block + * size (16 bytes) + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH + */ +int aes_crypt_cbc( aes_context *ctx, + int mode, + uint64_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/** + * \brief AES-CFB128 buffer encryption/decryption. + * + * Note: Due to the nature of CFB you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. + * + * both + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param length length of the input data + * \param iv_off offset in IV (updated after use) + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful + */ +int aes_crypt_cfb128( aes_context *ctx, + int mode, + uint64_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/** + * \brief AES-CTR buffer encryption/decryption + * + * Warning: You have to keep the maximum use of your counter in mind! + * + * Note: Due to the nature of CTR you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. + * + * \param length The length of the data + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be 0 at the start of a stream. + * \param nonce_counter The 128-bit nonce and counter. + * \param stream_block The saved stream-block for resuming. Is overwritten + * by the function. + * \param input The input data stream + * \param output The output data stream + * + * \return 0 if successful + */ +int aes_crypt_ctr( aes_context *ctx, + uint64_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_AES_ALT */ +#include "polarssl/aes_alt.h" +#endif /* POLARSSL_AES_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int aes_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* aes.h */ diff --git a/lib/crypto/polarssl/aes.o b/lib/crypto/polarssl/aes.o new file mode 100644 index 0000000000000000000000000000000000000000..dc224002f04f8b8dd0b1ff7d8296b7bf40907601 GIT binary patch literal 14888 zcmeI3e{dA#8OQhXgZvWN@O#mEU-w9ux~!yPpm(X?8zAsnY5BrxRCk!mn> zIm)`mM#oHJYb*cYFt%DdV`Ih<&827}QX3h{;Kvd4YhYu7LI}&50?hX@eIz;c5}A*2=UJtxh-p zrf)vpRitVCsnL&5ox-&K)EII9r-|NQ;UqLr3>6@(1nO}@FSW}bsb(i}5FG@X>OMT84r5?7` z&6EGrJ|1T<<(Mz;LHpkLqgZr}VLwV5>Z@-tk|JN zz3@yGasTeNp8G;pcWEp57)s5beZpJbq zY}I9Sv$nWDHU>Ghk*#pEVqe-(BAZL z;WuMr!Jn>y+GAxc&B&Amw^Tv%jm*^GmbN?$lqL&D9w>m#ikg7l5%q4b4dK%&h6YjZ zMAIV0=q*D+zA>2o~j$23U%fYpNaBfDIql zRE+Bykvg7hLt4#KsLYa&_cm6RT`T{kl;eGa8p z*y)wot__20i-KFb(Y2Fc{3+L-a9j&@^l|O>m+rzhuT_4EQt z58FLGKP!D9rBAoh7i5ow2#kbD!L3Cw5<0{?Ev@I9k1xluVD9RH6y5y8^YAb`e+zdj zg?G7%pD$POS#lM>Ot(^)ofdK!r4$uw`MGw~y`29YMjs`}6+JZw3W`{rA_hylC2Z?f zJ61$*PYvM%)@-wX7?*rAwHJV~3-4NTvL&J;4@vQ1fL5m{5#Oh$j}*XWpqr_KC}Bx^ z?X?BEDUDg3BBA|yAnh2m%5hEm((<84Vb2&2n5o@ZW8+z@RAl4`G`l}F0AX~%$cu3E zt)+!qow+aA{TSwjupZxMm33l7m+iI6)Bk{-#FME)WQxM3DcpkDU_75rwlKFxQm{i9 zqS~;?i#{kYc3~^>gO4nPEz)=vTM22hnZ_=RYQdkKA-2yitrx^NoN$!LarsgNrjB@z zRm0Ogv&_~3vt_q#*7fLS&GWFx4Cq#MF}=$41iNwlgIU`HTWdhRqoj`%m-InKK)rb~ z18meb%2y~{GHAvQie*dGv@T<5Q30@IL6&r(S9+4taiohB64HmbGy;@{f#a$*yguP@ zbJx05={VAp6%x`zTp9sNmt{#$@k&osI*xQuAt8N~OCL2_cWc4a*C*lNj}2Jb+Zmi) zvHc^5#CicQi^_c=D|S$9N9xV1&x##YOTLQ@rHADz?_%)c2MfCb&@;nX6#?l(T>4-R zX)x!J26Nfc$GP+nmxkKN7e!SeXbG6}NQ1d-=}|6yluJWxJkns!BMs)VrN_ARFqa<7 zAw8Ny`Z$-)o(16R<6L?;hcuY;)EdlX*E)L^fb=MrhT3=>0_Hr@U@luadlrE77?+0H zc%;FcM;gp!OCL2F_XmvD{jicw`xN)RuSU6hZvOvAx$A=srlLL29gOdhkYW#acM2X1 z#pIxO<8aio0oX&|$%kd_(eGfgXU_q5im)eVf*T8aKJ&rJM|G9s*1=@Yo*3>FVNXsE zHx~AMCW(`eyyj!io-IxRdC-PFfjQ&G!rsx5S^wcqk!#J(wNrT3+=+LJTx)Kwox-!` zPP|iqjAx0-wNrTZw~6Nv$ati4?G&E4uEkuY{NrSjOWR>ZabbY;$b^p0AB@mq)?n5JB25S zc*ssK5^<++u@xJ#6H6fCwp=RWPT|QS?i4PAFB`k?6#1EB$ES+8Q#dH%P*{A}-X(ql zxK%ffuY%tIdd!v=;OllLeBExp(TsK7Xx4PB)UAS9m3Z0!pFz=HaK=t!D5%5lsii%C z#Z&zy@WpJjz5t(PJ0RBx{%i-Cx^%0yShuhg9N5&sc&+JxPvb5NEa2xM9scyk_CkK` z*p*gnuO1(Sqz*j*LkS}AZHI;~uqL55OzC79H4@XT|rq@7vJETEj zFk=RE^Oj;bgYF8!tpje2JK@&46Y7`1>f$lV$WP!lf$6T(G>xt5V6BpkjctD^1a@3U zUAe2(4Al~yp<8ziuhi#F7w%3LiqkRO*uCmb*-Ow#)#`^D;Zn0^5PE3vn7wyrt@0FuL)xVh|43g54oFyx0a` zCEAwWWZtn-qj41cJgPnT7s%0z^8#$cs}`ObnD9f56$=pz!H+89=ah_YwG8NilkmkK z-6Q5x295&)IBevvK10Hw3BTo}dV{H2aXf_e$De{ibl?KD%f7B#y!e_(W!;LFresTG ze$|4i`IlYMB4W`^(fL(#=U2^}Ex9OHL8SvfUaAG|3kA+AD=O{)7fc6^e|WXvk6YiF z8rqt-c*>;w^@Wf{q%9Pw@NX5e(%-bxmr?o;;HM3zd|kdO{{W@GgU6+|{{E?$9s%?u zr9X{bqS9kVe*TjI%p&siQl69eRC)5=7wICYs(E8$vSEc*)tuZQpQ}`8Lt<@1RWfm3 zQmb0okZjPZRx~$jRq=I=jfo~;P3w}0s_Sm5yR13c5MQHJiR_70^>=S*XiSjV|N0RD z1#BL?fM;FR6bnVNu*mBs_-{4fM>Wq?jcXBHx1S-O_`@UG0k?@OOwUW;i5$Dgebq+X zF(-_9-Pat5pe8TBJR)<=nIWI*PFO{?D1=aRu1#dXF3-5Kub$UHx(d6qJ{)n!oG{OO zGbAB{bFr+eBO;?iS=8~L!q-C}m;bx2mN{^p#|!-r|7OSIf9xLaJ3!j{i}0>#cgTl* z=k?E3cg#FEQx@r=hE0a(S@6gEzXVt=``f-o<>kY^bNhAz3t+wi?E`Ug&yv7iZk7C; zHNpCMJ&e8#xH(B;I|WxJsAy1eT&wURekKG(eslz0#Lt1C;8O&(InFo1vE%R}I~R%| z6fPIk&VRAuXJ>PCuh5y6%`a8_f^2@d;xwOVdTaBER}!b{Yu5tLQO6&e09;}(faezY zLw?`+NHtCD0r154l3Y4Z`0!_dqs|4`L2!wE0s{?+=Bl{11HV|}72?vAcZ z#I?pmBP0qM->`9gvOW=C;flpqh%E8-8@2j+vE9_iSFNePyJ7WOcdq0H?PaVxTF(X{Ij*M!RoKyb0IH&x>oRhteefVTrY;3zUw5Iv+ zD$Z%1F7n~Ga8C1gIp@@_6EtD$`q2FS%!ij#eeL`-uP^f9S8`7C{kuN=cFt)Xc!)T< z6{|LLhU|bR7>^J?LN63{J&AwHIrZatH1+NL#IN?@-}m94a!z)`wDEBLt9cfBM!~f*N>v3a;%eE_{TB{HLwGV&UhkuB|aOJ@t?%(k5(Zn@_ z#x=KlIp;KQnRC+boRj`2=cFH?a<(5x|6ms_^UqrfDix7ho43Mw)>abb-52;;={Lc zPVbYy;GEujp5vVM=~p?YedsXfr2ir3q+f!Yle@o2e;VhczmRj%ujQQdS8`7JEu547 z&p9Xk-*8U)uX0ZMgPfE8NzO@s5*--X{Y(1OI4Au}IVb%Z&Pl(4bJB0&obC;dUrN&hhCq@RB-8xN#^4(FtQDd(iWkaN;s%Q@+{aZdV=b58m@I4Avn&Po4W z&Po3S=cKREI%0iY;>0i$|>EFpY>9=xD`j2u>`a3u${cg@l{~+hGyR{QO zyaW$~;IjQ7qgup=>pr~Rhi~-Z9X?$A=e->D`Lj>{5g)D&|9QJAr^^O%{%s$AhYw%x z!%xzA4}KTm6ja{@1GGPLKIG!qMJoT9bl!vcv5AV`>*8+x2;{*F^W&eoswtqjI`3M} XxH|7@V_cnUZD(AaYwc!Som2fA_)8#M literal 0 HcmV?d00001 diff --git a/lib/crypto/polarssl/base64.c b/lib/crypto/polarssl/base64.c new file mode 100644 index 0000000..c99192a --- /dev/null +++ b/lib/crypto/polarssl/base64.c @@ -0,0 +1,269 @@ +/* + * RFC 1521 base64 encoding/decoding + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#if defined(POLARSSL_BASE64_C) + +#include "base64.h" + +#ifdef _MSC_VER +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +static const unsigned char base64_enc_map[64] = +{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/' +}; + +static const unsigned char base64_dec_map[128] = +{ + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, + 127, 64, 127, 127, 127, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 127, 127, 127, 127, 127, 127, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 127, 127, 127, 127, 127 +}; + +/* + * Encode a buffer into base64 format + */ +int base64_encode( unsigned char *dst, size_t *dlen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + int C1, C2, C3; + unsigned char *p; + + if( slen == 0 ) + return( 0 ); + + n = (slen << 3) / 6; + + switch( (slen << 3) - (n * 6) ) + { + case 2: n += 3; break; + case 4: n += 2; break; + default: break; + } + + if( *dlen < n + 1 ) + { + *dlen = n + 1; + return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n = (slen / 3) * 3; + + for( i = 0, p = dst; i < n; i += 3 ) + { + C1 = *src++; + C2 = *src++; + C3 = *src++; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; + *p++ = base64_enc_map[C3 & 0x3F]; + } + + if( i < slen ) + { + C1 = *src++; + C2 = ((i + 1) < slen) ? *src++ : 0; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + + if( (i + 1) < slen ) + *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; + else *p++ = '='; + + *p++ = '='; + } + + *dlen = p - dst; + *p = 0; + + return( 0 ); +} + +/* + * Decode a base64-formatted buffer + */ +int base64_decode( unsigned char *dst, size_t *dlen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + uint32_t j, x; + unsigned char *p; + + for( i = j = n = 0; i < slen; i++ ) + { + if( ( slen - i ) >= 2 && + src[i] == '\r' && src[i + 1] == '\n' ) + continue; + + if( src[i] == '\n' ) + continue; + + if( src[i] == '=' && ++j > 2 ){ + printf("err 0 char[%lu] = '%c' (0x%x)\n",i,src[i],src[i]); + return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + } + + if( src[i] > 127 || base64_dec_map[src[i]] == 127 ){ + printf("err 1 char[%lu] = '%c' (0x%x)\n",i,src[i],src[i]); + return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + } + + if( base64_dec_map[src[i]] < 64 && j != 0 ){ + printf("err 2 char[%lu] = '%c' (0x%x)\n",i,src[i],src[i]); + return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + } + + n++; + } + + if( n == 0 ) + return( 0 ); + + + n = ((n * 6) + 7) >> 3; + + if( (*dlen+4) < n ) + { + *dlen = n; + return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ ) + { + if( *src == '\r' || *src == '\n' ) + continue; + + j -= ( base64_dec_map[*src] == 64 ); + x = (x << 6) | ( base64_dec_map[*src] & 0x3F ); + + if( ++n == 4 ) + { + n = 0; + if( j > 0 ) *p++ = (unsigned char)( x >> 16 ); + if( j > 1 ) *p++ = (unsigned char)( x >> 8 ); + if( j > 2 ) *p++ = (unsigned char)( x ); + } + } + + *dlen = p - dst; + + return( 0 ); +} + +#if defined(POLARSSL_SELF_TEST) + +#include +#include + +static const unsigned char base64_test_dec[64] = +{ + 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, + 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, + 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, + 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13, + 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31, + 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38, + 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B, + 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97 +}; + +static const unsigned char base64_test_enc[] = + "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK" + "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw=="; + +/* + * Checkup routine + */ +int base64_self_test( int verbose ) +{ + size_t len; + const unsigned char *src; + unsigned char buffer[128]; + + if( verbose != 0 ) + printf( " Base64 encoding test: " ); + + len = sizeof( buffer ); + src = base64_test_dec; + + if( base64_encode( buffer, &len, src, 64 ) != 0 || + memcmp( base64_test_enc, buffer, 88 ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n Base64 decoding test: " ); + + len = sizeof( buffer ); + src = base64_test_enc; + + if( base64_decode( buffer, &len, src, 88 ) != 0 || + memcmp( base64_test_dec, buffer, 64 ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n\n" ); + + return( 0 ); +} + +#endif + +#endif diff --git a/lib/crypto/polarssl/base64.h b/lib/crypto/polarssl/base64.h new file mode 100644 index 0000000..604893e --- /dev/null +++ b/lib/crypto/polarssl/base64.h @@ -0,0 +1,88 @@ +/** + * \file base64.h + * + * \brief RFC 1521 base64 encoding/decoding + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_BASE64_H +#define POLARSSL_BASE64_H + +#include +#include + +#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ +#define POLARSSL_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encode a buffer into base64 format + * + * \param dst destination buffer + * \param dlen size of the buffer + * \param src source buffer + * \param slen amount of data to be encoded + * + * \return 0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL. + * *dlen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dlen = 0 to obtain the + * required buffer size in *dlen + */ +int base64_encode( unsigned char *dst, size_t *dlen, + const unsigned char *src, size_t slen ); + +/** + * \brief Decode a base64-formatted buffer + * + * \param dst destination buffer + * \param dlen size of the buffer + * \param src source buffer + * \param slen amount of data to be decoded + * + * \return 0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or + * POLARSSL_ERR_BASE64_INVALID_CHARACTER if the input data is + * not correct. *dlen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dlen = 0 to obtain the + * required buffer size in *dlen + */ +int base64_decode( unsigned char *dst, size_t *dlen, + const unsigned char *src, size_t slen ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int base64_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* base64.h */ diff --git a/lib/crypto/polarssl/base64.o b/lib/crypto/polarssl/base64.o new file mode 100644 index 0000000000000000000000000000000000000000..66b93394e7ed0d3bf05ab64652840dcb4f8404c2 GIT binary patch literal 3896 zcmb_dTW}Lq7(Sa#ue5B+MZqG(OQ8`OS}6CH2Fk)wE@Cm<9EM5LV7a8N$)*%$3JfdC zPKFtDbcPvqeDFjDu=&mg%q5e2We=?$4r1(5b+FJqfBM zsXFaYD&g0uR87@VRnCf2<+wPmg0oKJhM#&}pc}@c3jxd0D|-c|(_CXe&&rd>3LDfT?0&8o+7pJ{|YpO+0X@ z6CE`8qcr+Hrn>C18K@JYb~|y;8TY3W51hjHkF-vy6VjEM4>3^OpH4g|e~f+F9!-@q zA{3CJo8+u?u?{-Lr4dO@K~#_m_KBO%P*oSeX(T$Y&}6ENoxUbxNB-x{=Mpc?500%! zOxT+{C0VU*lJ)}8KMhcldamOnXxBl2QD%p7lMuF#BRANbtH1eR*6+ZqgPkAdW48|T zlEvQNlCf7L4jb0w%;Yt=Ll7qe)2#Er>a;M}#IYpIHVjf*ZLFRl#;BTTb*yZ%D;K~D zZz_b_W4ly2C8)zG$Kcld_|j<74vaHEyZH@P%l5{`ee5T^A^VLRf>raRZ|g&g?ICn} zO&Yy`{%z-DPna=XuphWwx%eHY;VnrKYwFQd42FnALsyhb&VstG}T%VYGb9--gS*}2i(=0*f)82f45I~nT?#AW*g`8Ex8*f;_WUbAfieH9e+&3xOgv&MUEukb*b=&}M!;`? z4^5hF_@@;Hfc06)3}>!eL22?8SA=C1<2SbjI3zny4o zA$xv{Dvw1wC;5FQ59ESaa0-S(ELsWHSFFQ`mlcGEClI3Na38l=$Z=D?z;RqeQhZp% zho@yRX7+`bs}b-ymVL1|53scyH)ZzL0k#c37kmZO9f*e3wt9oaV2+0Rf=9!F0aNS= z<%yu}?+ICyC=Eo8_bJDW$Q}H^@a%J4AtYP^|D*)|bqTzU51&2$i4yq7CGao#5aRh^ zojQC-H#m-NIFf(CKR?o+95?g&K!>!PkBS*5#ZW@laNHi}5XbFt-m}FqkM^SyaRR)# W_BijBz}>tqtcSORAwC;!&doo%L}`)$ literal 0 HcmV?d00001 diff --git a/lib/crypto/polarssl/bignum.c b/lib/crypto/polarssl/bignum.c new file mode 100644 index 0000000..2a40ff4 --- /dev/null +++ b/lib/crypto/polarssl/bignum.c @@ -0,0 +1,2135 @@ +/* + * Multi-precision integer library + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * This MPI implementation is based on: + * + * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf + * http://www.stillhq.com/extracted/gnupg-api/mpi/ + * http://math.libtomcrypt.com/files/tommath.pdf + */ + +#include "config.h" + +#if defined(POLARSSL_BIGNUM_C) + +#include "bignum.h" +#include "bn_mul.h" + +#include + +#define ciL (sizeof(t_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define biH (ciL << 2) /* half limb size */ + +/* + * Convert between bits/chars and number of limbs + */ +#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL) +#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL) + +/* + * Initialize one MPI + */ +void mpi_init( mpi *X ) +{ + if( X == NULL ) + return; + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Unallocate one MPI + */ +void mpi_free( mpi *X ) +{ + if( X == NULL ) + return; + + if( X->p != NULL ) + { + memset( X->p, 0, X->n * ciL ); + free( X->p ); + } + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Enlarge to the specified number of limbs + */ +int mpi_grow( mpi *X, size_t nblimbs ) +{ + t_uint *p; + + if( nblimbs > POLARSSL_MPI_MAX_LIMBS ) + return( POLARSSL_ERR_MPI_MALLOC_FAILED ); + + if( X->n < nblimbs ) + { + if( ( p = (t_uint *) malloc( nblimbs * ciL ) ) == NULL ) + return( POLARSSL_ERR_MPI_MALLOC_FAILED ); + + memset( p, 0, nblimbs * ciL ); + + if( X->p != NULL ) + { + memcpy( p, X->p, X->n * ciL ); + memset( X->p, 0, X->n * ciL ); + free( X->p ); + } + + X->n = nblimbs; + X->p = p; + } + + return( 0 ); +} + +/* + * Copy the contents of Y into X + */ +int mpi_copy( mpi *X, const mpi *Y ) +{ + int ret; + size_t i; + + if( X == Y ) + return( 0 ); + + for( i = Y->n - 1; i > 0; i-- ) + if( Y->p[i] != 0 ) + break; + i++; + + X->s = Y->s; + + MPI_CHK( mpi_grow( X, i ) ); + + memset( X->p, 0, X->n * ciL ); + memcpy( X->p, Y->p, i * ciL ); + +cleanup: + + return( ret ); +} + +/* + * Swap the contents of X and Y + */ +void mpi_swap( mpi *X, mpi *Y ) +{ + mpi T; + + memcpy( &T, X, sizeof( mpi ) ); + memcpy( X, Y, sizeof( mpi ) ); + memcpy( Y, &T, sizeof( mpi ) ); +} + +/* + * Set value from integer + */ +int mpi_lset( mpi *X, t_sint z ) +{ + int ret; + + MPI_CHK( mpi_grow( X, 1 ) ); + memset( X->p, 0, X->n * ciL ); + + X->p[0] = ( z < 0 ) ? -z : z; + X->s = ( z < 0 ) ? -1 : 1; + +cleanup: + + return( ret ); +} + +/* + * Get a specific bit + */ +int mpi_get_bit( const mpi *X, size_t pos ) +{ + if( X->n * biL <= pos ) + return( 0 ); + + return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01; +} + +/* + * Set a bit to a specific value of 0 or 1 + */ +int mpi_set_bit( mpi *X, size_t pos, unsigned char val ) +{ + int ret = 0; + size_t off = pos / biL; + size_t idx = pos % biL; + + if( val != 0 && val != 1 ) + return POLARSSL_ERR_MPI_BAD_INPUT_DATA; + + if( X->n * biL <= pos ) + { + if( val == 0 ) + return ( 0 ); + + MPI_CHK( mpi_grow( X, off + 1 ) ); + } + + X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx ); + +cleanup: + + return( ret ); +} + +/* + * Return the number of least significant bits + */ +size_t mpi_lsb( const mpi *X ) +{ + size_t i, j, count = 0; + + for( i = 0; i < X->n; i++ ) + for( j = 0; j < biL; j++, count++ ) + if( ( ( X->p[i] >> j ) & 1 ) != 0 ) + return( count ); + + return( 0 ); +} + +/* + * Return the number of most significant bits + */ +size_t mpi_msb( const mpi *X ) +{ + size_t i, j; + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + + for( j = biL; j > 0; j-- ) + if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 ) + break; + + return( ( i * biL ) + j ); +} + +/* + * Return the total size in bytes + */ +size_t mpi_size( const mpi *X ) +{ + return( ( mpi_msb( X ) + 7 ) >> 3 ); +} + +/* + * Convert an ASCII character to digit value + */ +static int mpi_get_digit( t_uint *d, int radix, char c ) +{ + *d = 255; + + if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; + if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; + if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; + + if( *d >= (t_uint) radix ) + return( POLARSSL_ERR_MPI_INVALID_CHARACTER ); + + return( 0 ); +} + +/* + * Import from an ASCII string + */ +int mpi_read_string( mpi *X, int radix, const char *s ) +{ + int ret; + size_t i, j, slen, n; + t_uint d; + mpi T; + + if( radix < 2 || radix > 16 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + mpi_init( &T ); + + slen = strlen( s ); + + if( radix == 16 ) + { + n = BITS_TO_LIMBS( slen << 2 ); + + MPI_CHK( mpi_grow( X, n ) ); + MPI_CHK( mpi_lset( X, 0 ) ); + + for( i = slen, j = 0; i > 0; i--, j++ ) + { + if( i == 1 && s[i - 1] == '-' ) + { + X->s = -1; + break; + } + + MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); + X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 ); + } + } + else + { + MPI_CHK( mpi_lset( X, 0 ) ); + + for( i = 0; i < slen; i++ ) + { + if( i == 0 && s[i] == '-' ) + { + X->s = -1; + continue; + } + + MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); + MPI_CHK( mpi_mul_int( &T, X, radix ) ); + + if( X->s == 1 ) + { + MPI_CHK( mpi_add_int( X, &T, d ) ); + } + else + { + MPI_CHK( mpi_sub_int( X, &T, d ) ); + } + } + } + +cleanup: + + mpi_free( &T ); + + return( ret ); +} + +/* + * Helper to write the digits high-order first + */ +static int mpi_write_hlp( mpi *X, int radix, char **p ) +{ + int ret; + t_uint r; + + if( radix < 2 || radix > 16 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + MPI_CHK( mpi_mod_int( &r, X, radix ) ); + MPI_CHK( mpi_div_int( X, NULL, X, radix ) ); + + if( mpi_cmp_int( X, 0 ) != 0 ) + MPI_CHK( mpi_write_hlp( X, radix, p ) ); + + if( r < 10 ) + *(*p)++ = (char)( r + 0x30 ); + else + *(*p)++ = (char)( r + 0x37 ); + +cleanup: + + return( ret ); +} + +/* + * Export into an ASCII string + */ +int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen ) +{ + int ret = 0; + size_t n; + char *p; + mpi T; + + if( radix < 2 || radix > 16 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + n = mpi_msb( X ); + if( radix >= 4 ) n >>= 1; + if( radix >= 16 ) n >>= 1; + n += 3; + + if( *slen < n ) + { + *slen = n; + return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL ); + } + + p = s; + mpi_init( &T ); + + if( X->s == -1 ) + *p++ = '-'; + + if( radix == 16 ) + { + int c; + size_t i, j, k; + + for( i = X->n, k = 0; i > 0; i-- ) + { + for( j = ciL; j > 0; j-- ) + { + c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; + + if( c == 0 && k == 0 && ( i + j + 3 ) != 0 ) + continue; + + *(p++) = "0123456789ABCDEF" [c / 16]; + *(p++) = "0123456789ABCDEF" [c % 16]; + k = 1; + } + } + } + else + { + MPI_CHK( mpi_copy( &T, X ) ); + + if( T.s == -1 ) + T.s = 1; + + MPI_CHK( mpi_write_hlp( &T, radix, &p ) ); + } + + *p++ = '\0'; + *slen = p - s; + +cleanup: + + mpi_free( &T ); + + return( ret ); +} + +#if defined(POLARSSL_FS_IO) +/* + * Read X from an opened file + */ +int mpi_read_file( mpi *X, int radix, FILE *fin ) +{ + t_uint d; + size_t slen; + char *p; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ POLARSSL_MPI_RW_BUFFER_SIZE ]; + + memset( s, 0, sizeof( s ) ); + if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) + return( POLARSSL_ERR_MPI_FILE_IO_ERROR ); + + slen = strlen( s ); + if( slen == sizeof( s ) - 2 ) + return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL ); + + if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } + if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } + + p = s + slen; + while( --p >= s ) + if( mpi_get_digit( &d, radix, *p ) != 0 ) + break; + + return( mpi_read_string( X, radix, p + 1 ) ); +} + +/* + * Write X into an opened file (or stdout if fout == NULL) + */ +int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout ) +{ + int ret; + size_t n, slen, plen; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ POLARSSL_MPI_RW_BUFFER_SIZE ]; + + n = sizeof( s ); + memset( s, 0, n ); + n -= 2; + + MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) ); + + if( p == NULL ) p = ""; + + plen = strlen( p ); + slen = strlen( s ); + s[slen++] = '\r'; + s[slen++] = '\n'; + + if( fout != NULL ) + { + if( fwrite( p, 1, plen, fout ) != plen || + fwrite( s, 1, slen, fout ) != slen ) + return( POLARSSL_ERR_MPI_FILE_IO_ERROR ); + } + else + printf( "%s%s", p, s ); + +cleanup: + + return( ret ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * Import X from unsigned binary data, big endian + */ +int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t i, j, n; + + for( n = 0; n < buflen; n++ ) + if( buf[n] != 0 ) + break; + + MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) ); + MPI_CHK( mpi_lset( X, 0 ) ); + + for( i = buflen, j = 0; i > n; i--, j++ ) + X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3); + +cleanup: + + return( ret ); +} + +/* + * Export X into unsigned binary data, big endian + */ +int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen ) +{ + size_t i, j, n; + + n = mpi_size( X ); + + if( buflen < n ) + return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL ); + + memset( buf, 0, buflen ); + + for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- ) + buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) ); + + return( 0 ); +} + +/* + * Left-shift: X <<= count + */ +int mpi_shift_l( mpi *X, size_t count ) +{ + int ret; + size_t i, v0, t1; + t_uint r0 = 0, r1; + + v0 = count / (biL ); + t1 = count & (biL - 1); + + i = mpi_msb( X ) + count; + + if( X->n * biL < i ) + MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) ); + + ret = 0; + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = X->n; i > v0; i-- ) + X->p[i - 1] = X->p[i - v0 - 1]; + + for( ; i > 0; i-- ) + X->p[i - 1] = 0; + } + + /* + * shift by count % limb_size + */ + if( t1 > 0 ) + { + for( i = v0; i < X->n; i++ ) + { + r1 = X->p[i] >> (biL - t1); + X->p[i] <<= t1; + X->p[i] |= r0; + r0 = r1; + } + } + +cleanup: + + return( ret ); +} + +/* + * Right-shift: X >>= count + */ +int mpi_shift_r( mpi *X, size_t count ) +{ + size_t i, v0, v1; + t_uint r0 = 0, r1; + + v0 = count / biL; + v1 = count & (biL - 1); + + if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) + return mpi_lset( X, 0 ); + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = 0; i < X->n - v0; i++ ) + X->p[i] = X->p[i + v0]; + + for( ; i < X->n; i++ ) + X->p[i] = 0; + } + + /* + * shift by count % limb_size + */ + if( v1 > 0 ) + { + for( i = X->n; i > 0; i-- ) + { + r1 = X->p[i - 1] << (biL - v1); + X->p[i - 1] >>= v1; + X->p[i - 1] |= r0; + r0 = r1; + } + } + + return( 0 ); +} + +/* + * Compare unsigned values + */ +int mpi_cmp_abs( const mpi *X, const mpi *Y ) +{ + size_t i, j; + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( 1 ); + if( j > i ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mpi_cmp_mpi( const mpi *X, const mpi *Y ) +{ + size_t i, j; + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( X->s ); + if( j > i ) return( -Y->s ); + + if( X->s > 0 && Y->s < 0 ) return( 1 ); + if( Y->s > 0 && X->s < 0 ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mpi_cmp_int( const mpi *X, t_sint z ) +{ + mpi Y; + t_uint p[1]; + + *p = ( z < 0 ) ? -z : z; + Y.s = ( z < 0 ) ? -1 : 1; + Y.n = 1; + Y.p = p; + + return( mpi_cmp_mpi( X, &Y ) ); +} + +/* + * Unsigned addition: X = |A| + |B| (HAC 14.7) + */ +int mpi_add_abs( mpi *X, const mpi *A, const mpi *B ) +{ + int ret; + size_t i, j; + t_uint *o, *p, c; + + if( X == B ) + { + const mpi *T = A; A = X; B = T; + } + + if( X != A ) + MPI_CHK( mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned additions. + */ + X->s = 1; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MPI_CHK( mpi_grow( X, j ) ); + + o = B->p; p = X->p; c = 0; + + for( i = 0; i < j; i++, o++, p++ ) + { + *p += c; c = ( *p < c ); + *p += *o; c += ( *p < *o ); + } + + while( c != 0 ) + { + if( i >= X->n ) + { + MPI_CHK( mpi_grow( X, i + 1 ) ); + p = X->p + i; + } + + *p += c; c = ( *p < c ); i++; p++; + } + +cleanup: + + return( ret ); +} + +/* + * Helper for mpi substraction + */ +static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d ) +{ + size_t i; + t_uint c, z; + + for( i = c = 0; i < n; i++, s++, d++ ) + { + z = ( *d < c ); *d -= c; + c = ( *d < *s ) + z; *d -= *s; + } + + while( c != 0 ) + { + z = ( *d < c ); *d -= c; + c = z; i++; d++; + } +} + +/* + * Unsigned substraction: X = |A| - |B| (HAC 14.9) + */ +int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B ) +{ + mpi TB; + int ret; + size_t n; + + if( mpi_cmp_abs( A, B ) < 0 ) + return( POLARSSL_ERR_MPI_NEGATIVE_VALUE ); + + mpi_init( &TB ); + + if( X == B ) + { + MPI_CHK( mpi_copy( &TB, B ) ); + B = &TB; + } + + if( X != A ) + MPI_CHK( mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned substractions. + */ + X->s = 1; + + ret = 0; + + for( n = B->n; n > 0; n-- ) + if( B->p[n - 1] != 0 ) + break; + + mpi_sub_hlp( n, B->p, X->p ); + +cleanup: + + mpi_free( &TB ); + + return( ret ); +} + +/* + * Signed addition: X = A + B + */ +int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B ) +{ + int ret, s = A->s; + + if( A->s * B->s < 0 ) + { + if( mpi_cmp_abs( A, B ) >= 0 ) + { + MPI_CHK( mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MPI_CHK( mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MPI_CHK( mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed substraction: X = A - B + */ +int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B ) +{ + int ret, s = A->s; + + if( A->s * B->s > 0 ) + { + if( mpi_cmp_abs( A, B ) >= 0 ) + { + MPI_CHK( mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MPI_CHK( mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MPI_CHK( mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed addition: X = A + b + */ +int mpi_add_int( mpi *X, const mpi *A, t_sint b ) +{ + mpi _B; + t_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mpi_add_mpi( X, A, &_B ) ); +} + +/* + * Signed substraction: X = A - b + */ +int mpi_sub_int( mpi *X, const mpi *A, t_sint b ) +{ + mpi _B; + t_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mpi_sub_mpi( X, A, &_B ) ); +} + +/* + * Helper for mpi multiplication + */ +static void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b ) +{ + t_uint c = 0, t = 0; + +#if defined(MULADDC_HUIT) + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_HUIT + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#else + for( ; i >= 16; i -= 16 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#endif + + t++; + + do { + *d += c; c = ( *d < c ); d++; + } + while( c != 0 ); +} + +/* + * Baseline multiplication: X = A * B (HAC 14.12) + */ +int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B ) +{ + int ret; + size_t i, j; + mpi TA, TB; + + mpi_init( &TA ); mpi_init( &TB ); + + if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; } + if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; } + + for( i = A->n; i > 0; i-- ) + if( A->p[i - 1] != 0 ) + break; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MPI_CHK( mpi_grow( X, i + j ) ); + MPI_CHK( mpi_lset( X, 0 ) ); + + for( i++; j > 0; j-- ) + mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] ); + + X->s = A->s * B->s; + +cleanup: + + mpi_free( &TB ); mpi_free( &TA ); + + return( ret ); +} + +/* + * Baseline multiplication: X = A * b + */ +int mpi_mul_int( mpi *X, const mpi *A, t_sint b ) +{ + mpi _B; + t_uint p[1]; + + _B.s = 1; + _B.n = 1; + _B.p = p; + p[0] = b; + + return( mpi_mul_mpi( X, A, &_B ) ); +} + +/* + * Division by mpi: A = Q * B + R (HAC 14.20) + */ +int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B ) +{ + int ret; + size_t i, n, t, k; + mpi X, Y, Z, T1, T2; + + if( mpi_cmp_int( B, 0 ) == 0 ) + return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO ); + + mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z ); + mpi_init( &T1 ); mpi_init( &T2 ); + + if( mpi_cmp_abs( A, B ) < 0 ) + { + if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) ); + if( R != NULL ) MPI_CHK( mpi_copy( R, A ) ); + return( 0 ); + } + + MPI_CHK( mpi_copy( &X, A ) ); + MPI_CHK( mpi_copy( &Y, B ) ); + X.s = Y.s = 1; + + MPI_CHK( mpi_grow( &Z, A->n + 2 ) ); + MPI_CHK( mpi_lset( &Z, 0 ) ); + MPI_CHK( mpi_grow( &T1, 2 ) ); + MPI_CHK( mpi_grow( &T2, 3 ) ); + + k = mpi_msb( &Y ) % biL; + if( k < biL - 1 ) + { + k = biL - 1 - k; + MPI_CHK( mpi_shift_l( &X, k ) ); + MPI_CHK( mpi_shift_l( &Y, k ) ); + } + else k = 0; + + n = X.n - 1; + t = Y.n - 1; + MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) ); + + while( mpi_cmp_mpi( &X, &Y ) >= 0 ) + { + Z.p[n - t]++; + mpi_sub_mpi( &X, &X, &Y ); + } + mpi_shift_r( &Y, biL * (n - t) ); + + for( i = n; i > t ; i-- ) + { + if( X.p[i] >= Y.p[t] ) + Z.p[i - t - 1] = ~0; + else + { +#if defined(POLARSSL_HAVE_UDBL) + t_udbl r; + + r = (t_udbl) X.p[i] << biL; + r |= (t_udbl) X.p[i - 1]; + r /= Y.p[t]; + if( r > ((t_udbl) 1 << biL) - 1) + r = ((t_udbl) 1 << biL) - 1; + + Z.p[i - t - 1] = (t_uint) r; +#else + /* + * __udiv_qrnnd_c, from gmp/longlong.h + */ + t_uint q0, q1, r0, r1; + t_uint d0, d1, d, m; + + d = Y.p[t]; + d0 = ( d << biH ) >> biH; + d1 = ( d >> biH ); + + q1 = X.p[i] / d1; + r1 = X.p[i] - d1 * q1; + r1 <<= biH; + r1 |= ( X.p[i - 1] >> biH ); + + m = q1 * d0; + if( r1 < m ) + { + q1--, r1 += d; + while( r1 >= d && r1 < m ) + q1--, r1 += d; + } + r1 -= m; + + q0 = r1 / d1; + r0 = r1 - d1 * q0; + r0 <<= biH; + r0 |= ( X.p[i - 1] << biH ) >> biH; + + m = q0 * d0; + if( r0 < m ) + { + q0--, r0 += d; + while( r0 >= d && r0 < m ) + q0--, r0 += d; + } + r0 -= m; + + Z.p[i - t - 1] = ( q1 << biH ) | q0; +#endif + } + + Z.p[i - t - 1]++; + do + { + Z.p[i - t - 1]--; + + MPI_CHK( mpi_lset( &T1, 0 ) ); + T1.p[0] = (t < 1) ? 0 : Y.p[t - 1]; + T1.p[1] = Y.p[t]; + MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); + + MPI_CHK( mpi_lset( &T2, 0 ) ); + T2.p[0] = (i < 2) ? 0 : X.p[i - 2]; + T2.p[1] = (i < 1) ? 0 : X.p[i - 1]; + T2.p[2] = X.p[i]; + } + while( mpi_cmp_mpi( &T1, &T2 ) > 0 ); + + MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); + MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) ); + MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); + + if( mpi_cmp_int( &X, 0 ) < 0 ) + { + MPI_CHK( mpi_copy( &T1, &Y ) ); + MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) ); + MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) ); + Z.p[i - t - 1]--; + } + } + + if( Q != NULL ) + { + mpi_copy( Q, &Z ); + Q->s = A->s * B->s; + } + + if( R != NULL ) + { + mpi_shift_r( &X, k ); + X.s = A->s; + mpi_copy( R, &X ); + + if( mpi_cmp_int( R, 0 ) == 0 ) + R->s = 1; + } + +cleanup: + + mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z ); + mpi_free( &T1 ); mpi_free( &T2 ); + + return( ret ); +} + +/* + * Division by int: A = Q * b + R + */ +int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b ) +{ + mpi _B; + t_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mpi_div_mpi( Q, R, A, &_B ) ); +} + +/* + * Modulo: R = A mod B + */ +int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B ) +{ + int ret; + + if( mpi_cmp_int( B, 0 ) < 0 ) + return POLARSSL_ERR_MPI_NEGATIVE_VALUE; + + MPI_CHK( mpi_div_mpi( NULL, R, A, B ) ); + + while( mpi_cmp_int( R, 0 ) < 0 ) + MPI_CHK( mpi_add_mpi( R, R, B ) ); + + while( mpi_cmp_mpi( R, B ) >= 0 ) + MPI_CHK( mpi_sub_mpi( R, R, B ) ); + +cleanup: + + return( ret ); +} + +/* + * Modulo: r = A mod b + */ +int mpi_mod_int( t_uint *r, const mpi *A, t_sint b ) +{ + size_t i; + t_uint x, y, z; + + if( b == 0 ) + return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO ); + + if( b < 0 ) + return POLARSSL_ERR_MPI_NEGATIVE_VALUE; + + /* + * handle trivial cases + */ + if( b == 1 ) + { + *r = 0; + return( 0 ); + } + + if( b == 2 ) + { + *r = A->p[0] & 1; + return( 0 ); + } + + /* + * general case + */ + for( i = A->n, y = 0; i > 0; i-- ) + { + x = A->p[i - 1]; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + + x <<= biH; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + } + + /* + * If A is negative, then the current y represents a negative value. + * Flipping it to the positive side. + */ + if( A->s < 0 && y != 0 ) + y = b - y; + + *r = y; + + return( 0 ); +} + +/* + * Fast Montgomery initialization (thanks to Tom St Denis) + */ +static void mpi_montg_init( t_uint *mm, const mpi *N ) +{ + t_uint x, m0 = N->p[0]; + + x = m0; + x += ( ( m0 + 2 ) & 4 ) << 1; + x *= ( 2 - ( m0 * x ) ); + + if( biL >= 16 ) x *= ( 2 - ( m0 * x ) ); + if( biL >= 32 ) x *= ( 2 - ( m0 * x ) ); + if( biL >= 64 ) x *= ( 2 - ( m0 * x ) ); + + *mm = ~x + 1; +} + +/* + * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) + */ +static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T ) +{ + size_t i, n, m; + t_uint u0, u1, *d; + + memset( T->p, 0, T->n * ciL ); + + d = T->p; + n = N->n; + m = ( B->n < n ) ? B->n : n; + + for( i = 0; i < n; i++ ) + { + /* + * T = (T + u0*B + u1*N) / 2^biL + */ + u0 = A->p[i]; + u1 = ( d[0] + u0 * B->p[0] ) * mm; + + mpi_mul_hlp( m, B->p, d, u0 ); + mpi_mul_hlp( n, N->p, d, u1 ); + + *d++ = u0; d[n + 1] = 0; + } + + memcpy( A->p, d, (n + 1) * ciL ); + + if( mpi_cmp_abs( A, N ) >= 0 ) + mpi_sub_hlp( n, N->p, A->p ); + else + /* prevent timing attacks */ + mpi_sub_hlp( n, A->p, T->p ); +} + +/* + * Montgomery reduction: A = A * R^-1 mod N + */ +static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T ) +{ + t_uint z = 1; + mpi U; + + U.n = U.s = (int) z; + U.p = &z; + + mpi_montmul( A, &U, N, mm, T ); +} + +/* + * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) + */ +int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR ) +{ + int ret; + size_t wbits, wsize, one = 1; + size_t i, j, nblimbs; + size_t bufsize, nbits; + t_uint ei, mm, state; + mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos; + int neg; + + if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + if( mpi_cmp_int( E, 0 ) < 0 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + /* + * Init temps and window size + */ + mpi_montg_init( &mm, N ); + mpi_init( &RR ); mpi_init( &T ); + memset( W, 0, sizeof( W ) ); + + i = mpi_msb( E ); + + wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : + ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; + + if( wsize > POLARSSL_MPI_WINDOW_SIZE ) + wsize = POLARSSL_MPI_WINDOW_SIZE; + + j = N->n + 1; + MPI_CHK( mpi_grow( X, j ) ); + MPI_CHK( mpi_grow( &W[1], j ) ); + MPI_CHK( mpi_grow( &T, j * 2 ) ); + + /* + * Compensate for negative A (and correct at the end) + */ + neg = ( A->s == -1 ); + + mpi_init( &Apos ); + if( neg ) + { + MPI_CHK( mpi_copy( &Apos, A ) ); + Apos.s = 1; + A = &Apos; + } + + /* + * If 1st call, pre-compute R^2 mod N + */ + if( _RR == NULL || _RR->p == NULL ) + { + MPI_CHK( mpi_lset( &RR, 1 ) ); + MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) ); + MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) ); + + if( _RR != NULL ) + memcpy( _RR, &RR, sizeof( mpi ) ); + } + else + memcpy( &RR, _RR, sizeof( mpi ) ); + + /* + * W[1] = A * R^2 * R^-1 mod N = A * R mod N + */ + if( mpi_cmp_mpi( A, N ) >= 0 ) + mpi_mod_mpi( &W[1], A, N ); + else mpi_copy( &W[1], A ); + + mpi_montmul( &W[1], &RR, N, mm, &T ); + + /* + * X = R^2 * R^-1 mod N = R mod N + */ + MPI_CHK( mpi_copy( X, &RR ) ); + mpi_montred( X, N, mm, &T ); + + if( wsize > 1 ) + { + /* + * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) + */ + j = one << (wsize - 1); + + MPI_CHK( mpi_grow( &W[j], N->n + 1 ) ); + MPI_CHK( mpi_copy( &W[j], &W[1] ) ); + + for( i = 0; i < wsize - 1; i++ ) + mpi_montmul( &W[j], &W[j], N, mm, &T ); + + /* + * W[i] = W[i - 1] * W[1] + */ + for( i = j + 1; i < (one << wsize); i++ ) + { + MPI_CHK( mpi_grow( &W[i], N->n + 1 ) ); + MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) ); + + mpi_montmul( &W[i], &W[1], N, mm, &T ); + } + } + + nblimbs = E->n; + bufsize = 0; + nbits = 0; + wbits = 0; + state = 0; + + while( 1 ) + { + if( bufsize == 0 ) + { + if( nblimbs-- == 0 ) + break; + + bufsize = sizeof( t_uint ) << 3; + } + + bufsize--; + + ei = (E->p[nblimbs] >> bufsize) & 1; + + /* + * skip leading 0s + */ + if( ei == 0 && state == 0 ) + continue; + + if( ei == 0 && state == 1 ) + { + /* + * out of window, square X + */ + mpi_montmul( X, X, N, mm, &T ); + continue; + } + + /* + * add ei to current window + */ + state = 2; + + nbits++; + wbits |= (ei << (wsize - nbits)); + + if( nbits == wsize ) + { + /* + * X = X^wsize R^-1 mod N + */ + for( i = 0; i < wsize; i++ ) + mpi_montmul( X, X, N, mm, &T ); + + /* + * X = X * W[wbits] R^-1 mod N + */ + mpi_montmul( X, &W[wbits], N, mm, &T ); + + state--; + nbits = 0; + wbits = 0; + } + } + + /* + * process the remaining bits + */ + for( i = 0; i < nbits; i++ ) + { + mpi_montmul( X, X, N, mm, &T ); + + wbits <<= 1; + + if( (wbits & (one << wsize)) != 0 ) + mpi_montmul( X, &W[1], N, mm, &T ); + } + + /* + * X = A^E * R * R^-1 mod N = A^E mod N + */ + mpi_montred( X, N, mm, &T ); + + if( neg ) + { + X->s = -1; + mpi_add_mpi( X, N, X ); + } + +cleanup: + + for( i = (one << (wsize - 1)); i < (one << wsize); i++ ) + mpi_free( &W[i] ); + + mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos ); + + if( _RR == NULL ) + mpi_free( &RR ); + + return( ret ); +} + +/* + * Greatest common divisor: G = gcd(A, B) (HAC 14.54) + */ +int mpi_gcd( mpi *G, const mpi *A, const mpi *B ) +{ + int ret; + size_t lz, lzt; + mpi TG, TA, TB; + + mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB ); + + MPI_CHK( mpi_copy( &TA, A ) ); + MPI_CHK( mpi_copy( &TB, B ) ); + + lz = mpi_lsb( &TA ); + lzt = mpi_lsb( &TB ); + + if ( lzt < lz ) + lz = lzt; + + MPI_CHK( mpi_shift_r( &TA, lz ) ); + MPI_CHK( mpi_shift_r( &TB, lz ) ); + + TA.s = TB.s = 1; + + while( mpi_cmp_int( &TA, 0 ) != 0 ) + { + MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) ); + MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) ); + + if( mpi_cmp_mpi( &TA, &TB ) >= 0 ) + { + MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) ); + MPI_CHK( mpi_shift_r( &TA, 1 ) ); + } + else + { + MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) ); + MPI_CHK( mpi_shift_r( &TB, 1 ) ); + } + } + + MPI_CHK( mpi_shift_l( &TB, lz ) ); + MPI_CHK( mpi_copy( G, &TB ) ); + +cleanup: + + mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB ); + + return( ret ); +} + +int mpi_fill_random( mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + + MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) ); + MPI_CHK( mpi_lset( X, 0 ) ); + + MPI_CHK( f_rng( p_rng, (unsigned char *) X->p, size ) ); + +cleanup: + return( ret ); +} + +/* + * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) + */ +int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N ) +{ + int ret; + mpi G, TA, TU, U1, U2, TB, TV, V1, V2; + + if( mpi_cmp_int( N, 0 ) <= 0 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 ); + mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV ); + mpi_init( &V1 ); mpi_init( &V2 ); + + MPI_CHK( mpi_gcd( &G, A, N ) ); + + if( mpi_cmp_int( &G, 1 ) != 0 ) + { + ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + MPI_CHK( mpi_mod_mpi( &TA, A, N ) ); + MPI_CHK( mpi_copy( &TU, &TA ) ); + MPI_CHK( mpi_copy( &TB, N ) ); + MPI_CHK( mpi_copy( &TV, N ) ); + + MPI_CHK( mpi_lset( &U1, 1 ) ); + MPI_CHK( mpi_lset( &U2, 0 ) ); + MPI_CHK( mpi_lset( &V1, 0 ) ); + MPI_CHK( mpi_lset( &V2, 1 ) ); + + do + { + while( ( TU.p[0] & 1 ) == 0 ) + { + MPI_CHK( mpi_shift_r( &TU, 1 ) ); + + if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) + { + MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) ); + MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) ); + } + + MPI_CHK( mpi_shift_r( &U1, 1 ) ); + MPI_CHK( mpi_shift_r( &U2, 1 ) ); + } + + while( ( TV.p[0] & 1 ) == 0 ) + { + MPI_CHK( mpi_shift_r( &TV, 1 ) ); + + if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) + { + MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) ); + MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) ); + } + + MPI_CHK( mpi_shift_r( &V1, 1 ) ); + MPI_CHK( mpi_shift_r( &V2, 1 ) ); + } + + if( mpi_cmp_mpi( &TU, &TV ) >= 0 ) + { + MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) ); + MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) ); + MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) ); + } + else + { + MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) ); + MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) ); + MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) ); + } + } + while( mpi_cmp_int( &TU, 0 ) != 0 ); + + while( mpi_cmp_int( &V1, 0 ) < 0 ) + MPI_CHK( mpi_add_mpi( &V1, &V1, N ) ); + + while( mpi_cmp_mpi( &V1, N ) >= 0 ) + MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) ); + + MPI_CHK( mpi_copy( X, &V1 ) ); + +cleanup: + + mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 ); + mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV ); + mpi_free( &V1 ); mpi_free( &V2 ); + + return( ret ); +} + +#if defined(POLARSSL_GENPRIME) + +static const int small_prime[] = +{ + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251, 257, 263, 269, + 271, 277, 281, 283, 293, 307, 311, 313, + 317, 331, 337, 347, 349, 353, 359, 367, + 373, 379, 383, 389, 397, 401, 409, 419, + 421, 431, 433, 439, 443, 449, 457, 461, + 463, 467, 479, 487, 491, 499, 503, 509, + 521, 523, 541, 547, 557, 563, 569, 571, + 577, 587, 593, 599, 601, 607, 613, 617, + 619, 631, 641, 643, 647, 653, 659, 661, + 673, 677, 683, 691, 701, 709, 719, 727, + 733, 739, 743, 751, 757, 761, 769, 773, + 787, 797, 809, 811, 821, 823, 827, 829, + 839, 853, 857, 859, 863, 877, 881, 883, + 887, 907, 911, 919, 929, 937, 941, 947, + 953, 967, 971, 977, 983, 991, 997, -103 +}; + +/* + * Miller-Rabin primality test (HAC 4.24) + */ +int mpi_is_prime( mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, xs; + size_t i, j, n, s; + mpi W, R, T, A, RR; + + if( mpi_cmp_int( X, 0 ) == 0 || + mpi_cmp_int( X, 1 ) == 0 ) + return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); + + if( mpi_cmp_int( X, 2 ) == 0 ) + return( 0 ); + + mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A ); + mpi_init( &RR ); + + xs = X->s; X->s = 1; + + /* + * test trivial factors first + */ + if( ( X->p[0] & 1 ) == 0 ) + return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); + + for( i = 0; small_prime[i] > 0; i++ ) + { + t_uint r; + + if( mpi_cmp_int( X, small_prime[i] ) <= 0 ) + return( 0 ); + + MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) ); + + if( r == 0 ) + return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); + } + + /* + * W = |X| - 1 + * R = W >> lsb( W ) + */ + MPI_CHK( mpi_sub_int( &W, X, 1 ) ); + s = mpi_lsb( &W ); + MPI_CHK( mpi_copy( &R, &W ) ); + MPI_CHK( mpi_shift_r( &R, s ) ); + + i = mpi_msb( X ); + /* + * HAC, table 4.4 + */ + n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 : + ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 : + ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 ); + + for( i = 0; i < n; i++ ) + { + /* + * pick a random A, 1 < A < |X| - 1 + */ + MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + if( mpi_cmp_mpi( &A, &W ) >= 0 ) + { + j = mpi_msb( &A ) - mpi_msb( &W ); + MPI_CHK( mpi_shift_r( &A, j + 1 ) ); + } + A.p[0] |= 3; + + /* + * A = A^R mod |X| + */ + MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) ); + + if( mpi_cmp_mpi( &A, &W ) == 0 || + mpi_cmp_int( &A, 1 ) == 0 ) + continue; + + j = 1; + while( j < s && mpi_cmp_mpi( &A, &W ) != 0 ) + { + /* + * A = A * A mod |X| + */ + MPI_CHK( mpi_mul_mpi( &T, &A, &A ) ); + MPI_CHK( mpi_mod_mpi( &A, &T, X ) ); + + if( mpi_cmp_int( &A, 1 ) == 0 ) + break; + + j++; + } + + /* + * not prime if A != |X| - 1 or A == 1 + */ + if( mpi_cmp_mpi( &A, &W ) != 0 || + mpi_cmp_int( &A, 1 ) == 0 ) + { + ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE; + break; + } + } + +cleanup: + + X->s = xs; + + mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A ); + mpi_free( &RR ); + + return( ret ); +} + +/* + * Prime number generation + */ +int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t k, n; + mpi Y; + + if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + mpi_init( &Y ); + + n = BITS_TO_LIMBS( nbits ); + + MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); + + k = mpi_msb( X ); + if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) ); + if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) ); + + X->p[0] |= 3; + + if( dh_flag == 0 ) + { + while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) + { + if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + MPI_CHK( mpi_add_int( X, X, 2 ) ); + } + } + else + { + MPI_CHK( mpi_sub_int( &Y, X, 1 ) ); + MPI_CHK( mpi_shift_r( &Y, 1 ) ); + + while( 1 ) + { + if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 ) + { + if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 ) + break; + + if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + } + + if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + MPI_CHK( mpi_add_int( &Y, X, 1 ) ); + MPI_CHK( mpi_add_int( X, X, 2 ) ); + MPI_CHK( mpi_shift_r( &Y, 1 ) ); + } + } + +cleanup: + + mpi_free( &Y ); + + return( ret ); +} + +#endif + +#if defined(POLARSSL_SELF_TEST) + +#define GCD_PAIR_COUNT 3 + +static const int gcd_pairs[GCD_PAIR_COUNT][3] = +{ + { 693, 609, 21 }, + { 1764, 868, 28 }, + { 768454923, 542167814, 1 } +}; + +/* + * Checkup routine + */ +int mpi_self_test( int verbose ) +{ + int ret, i; + mpi A, E, N, X, Y, U, V; + + mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X ); + mpi_init( &Y ); mpi_init( &U ); mpi_init( &V ); + + MPI_CHK( mpi_read_string( &A, 16, + "EFE021C2645FD1DC586E69184AF4A31E" \ + "D5F53E93B5F123FA41680867BA110131" \ + "944FE7952E2517337780CB0DB80E61AA" \ + "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); + + MPI_CHK( mpi_read_string( &E, 16, + "B2E7EFD37075B9F03FF989C7C5051C20" \ + "34D2A323810251127E7BF8625A4F49A5" \ + "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ + "5B5C25763222FEFCCFC38B832366C29E" ) ); + + MPI_CHK( mpi_read_string( &N, 16, + "0066A198186C18C10B2F5ED9B522752A" \ + "9830B69916E535C8F047518A889A43A5" \ + "94B6BED27A168D31D4A52F88925AA8F5" ) ); + + MPI_CHK( mpi_mul_mpi( &X, &A, &N ) ); + + MPI_CHK( mpi_read_string( &U, 16, + "602AB7ECA597A3D6B56FF9829A5E8B85" \ + "9E857EA95A03512E2BAE7391688D264A" \ + "A5663B0341DB9CCFD2C4C5F421FEC814" \ + "8001B72E848A38CAE1C65F78E56ABDEF" \ + "E12D3C039B8A02D6BE593F0BBBDA56F1" \ + "ECF677152EF804370C1A305CAF3B5BF1" \ + "30879B56C61DE584A0F53A2447A51E" ) ); + + if( verbose != 0 ) + printf( " MPI test #1 (mul_mpi): " ); + + if( mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n" ); + + MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) ); + + MPI_CHK( mpi_read_string( &U, 16, + "256567336059E52CAE22925474705F39A94" ) ); + + MPI_CHK( mpi_read_string( &V, 16, + "6613F26162223DF488E9CD48CC132C7A" \ + "0AC93C701B001B092E4E5B9F73BCD27B" \ + "9EE50D0657C77F374E903CDFA4C642" ) ); + + if( verbose != 0 ) + printf( " MPI test #2 (div_mpi): " ); + + if( mpi_cmp_mpi( &X, &U ) != 0 || + mpi_cmp_mpi( &Y, &V ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n" ); + + MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) ); + + MPI_CHK( mpi_read_string( &U, 16, + "36E139AEA55215609D2816998ED020BB" \ + "BD96C37890F65171D948E9BC7CBAA4D9" \ + "325D24D6A3C12710F10A09FA08AB87" ) ); + + if( verbose != 0 ) + printf( " MPI test #3 (exp_mod): " ); + + if( mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n" ); + +#if defined(POLARSSL_GENPRIME) + MPI_CHK( mpi_inv_mod( &X, &A, &N ) ); + + MPI_CHK( mpi_read_string( &U, 16, + "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ + "C3DBA76456363A10869622EAC2DD84EC" \ + "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); + + if( verbose != 0 ) + printf( " MPI test #4 (inv_mod): " ); + + if( mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n" ); +#endif + + if( verbose != 0 ) + printf( " MPI test #5 (simple gcd): " ); + + for ( i = 0; i < GCD_PAIR_COUNT; i++) + { + MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) ); + MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) ); + + MPI_CHK( mpi_gcd( &A, &X, &Y ) ); + + if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) + { + if( verbose != 0 ) + printf( "failed at %d\n", i ); + + return( 1 ); + } + } + + if( verbose != 0 ) + printf( "passed\n" ); + +cleanup: + + if( ret != 0 && verbose != 0 ) + printf( "Unexpected error, return code = %08X\n", ret ); + + mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X ); + mpi_free( &Y ); mpi_free( &U ); mpi_free( &V ); + + if( verbose != 0 ) + printf( "\n" ); + + return( ret ); +} + +#endif + +#endif diff --git a/lib/crypto/polarssl/bignum.h b/lib/crypto/polarssl/bignum.h new file mode 100644 index 0000000..afa9e61 --- /dev/null +++ b/lib/crypto/polarssl/bignum.h @@ -0,0 +1,685 @@ +/** + * \file bignum.h + * + * \brief Multi-precision integer library + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_BIGNUM_H +#define POLARSSL_BIGNUM_H + +#include +#include + +#include "config.h" + +#ifdef _MSC_VER +#include +#if (_MSC_VER <= 1200) +typedef signed short int16_t; +typedef unsigned short uint16_t; +#else +typedef INT16 int16_t; +typedef UINT16 uint16_t; +#endif +typedef INT32 int32_t; +typedef INT64 int64_t; +typedef UINT32 uint32_t; +typedef UINT64 uint64_t; +#else +#include +#endif + +#define POLARSSL_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ +#define POLARSSL_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */ +#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */ +#define POLARSSL_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */ +#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */ +#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */ +#define POLARSSL_ERR_MPI_MALLOC_FAILED -0x0010 /**< Memory allocation failed. */ + +#define MPI_CHK(f) if( ( ret = f ) != 0 ) goto cleanup + +/* + * Maximum size MPIs are allowed to grow to in number of limbs. + */ +#define POLARSSL_MPI_MAX_LIMBS 10000 + +#if !defined(POLARSSL_CONFIG_OPTIONS) +/* + * Maximum window size used for modular exponentiation. Default: 6 + * Minimum value: 1. Maximum value: 6. + * + * Result is an array of ( 2 << POLARSSL_MPI_WINDOW_SIZE ) MPIs used + * for the sliding window calculation. (So 64 by default) + * + * Reduction in size, reduces speed. + */ +#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ + +/* + * Maximum size of MPIs allowed in bits and bytes for user-MPIs. + * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) + * + * Note: Calculations can results temporarily in larger MPIs. So the number + * of limbs required (POLARSSL_MPI_MAX_LIMBS) is higher. + */ +#define POLARSSL_MPI_MAX_SIZE 512 /**< Maximum number of bytes for usable MPIs. */ + +#endif /* !POLARSSL_CONFIG_OPTIONS */ + +#define POLARSSL_MPI_MAX_BITS ( 8 * POLARSSL_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ + +/* + * When reading from files with mpi_read_file() and writing to files with + * mpi_write_file() the buffer should have space + * for a (short) label, the MPI (in the provided radix), the newline + * characters and the '\0'. + * + * By default we assume at least a 10 char label, a minimum radix of 10 + * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). + * Autosized at compile time for at least a 10 char label, a minimum radix + * of 10 (decimal) for a number of POLARSSL_MPI_MAX_BITS size. + * + * This used to be statically sized to 1250 for a maximum of 4096 bit + * numbers (1234 decimal chars). + * + * Calculate using the formula: + * POLARSSL_MPI_RW_BUFFER_SIZE = ceil(POLARSSL_MPI_MAX_BITS / ln(10) * ln(2)) + + * LabelSize + 6 + */ +#define POLARSSL_MPI_MAX_BITS_SCALE100 ( 100 * POLARSSL_MPI_MAX_BITS ) +#define LN_2_DIV_LN_10_SCALE100 332 +#define POLARSSL_MPI_RW_BUFFER_SIZE ( ((POLARSSL_MPI_MAX_BITS_SCALE100 + LN_2_DIV_LN_10_SCALE100 - 1) / LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) + +/* + * Define the base integer type, architecture-wise + */ +#if defined(POLARSSL_HAVE_INT8) +typedef signed char t_sint; +typedef unsigned char t_uint; +typedef uint16_t t_udbl; +#define POLARSSL_HAVE_UDBL +#else +#if defined(POLARSSL_HAVE_INT16) +typedef int16_t t_sint; +typedef uint16_t t_uint; +typedef uint32_t t_udbl; +#define POLARSSL_HAVE_UDBL +#else + #if ( defined(_MSC_VER) && defined(_M_AMD64) ) + typedef int64_t t_sint; + typedef uint64_t t_uint; + #else + #if ( defined(__GNUC__) && ( \ + defined(__amd64__) || defined(__x86_64__) || \ + defined(__ppc64__) || defined(__powerpc64__) || \ + defined(__ia64__) || defined(__alpha__) || \ + (defined(__sparc__) && defined(__arch64__)) || \ + defined(__s390x__) ) ) + typedef int64_t t_sint; + typedef uint64_t t_uint; + typedef unsigned int t_udbl __attribute__((mode(TI))); + #define POLARSSL_HAVE_UDBL + #else + typedef int32_t t_sint; + typedef uint32_t t_uint; + #if ( defined(_MSC_VER) && defined(_M_IX86) ) + typedef uint64_t t_udbl; + #define POLARSSL_HAVE_UDBL + #else + #if defined( POLARSSL_HAVE_LONGLONG ) + typedef unsigned long long t_udbl; + #define POLARSSL_HAVE_UDBL + #endif + #endif + #endif + #endif +#endif /* POLARSSL_HAVE_INT16 */ +#endif /* POLARSSL_HAVE_INT8 */ + +/** + * \brief MPI structure + */ +typedef struct +{ + int s; /*!< integer sign */ + size_t n; /*!< total # of limbs */ + t_uint *p; /*!< pointer to limbs */ +} +mpi; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize one MPI + * + * \param X One MPI to initialize. + */ +void mpi_init( mpi *X ); + +/** + * \brief Unallocate one MPI + * + * \param X One MPI to unallocate. + */ +void mpi_free( mpi *X ); + +/** + * \brief Enlarge to the specified number of limbs + * + * \param X MPI to grow + * \param nblimbs The target number of limbs + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_grow( mpi *X, size_t nblimbs ); + +/** + * \brief Copy the contents of Y into X + * + * \param X Destination MPI + * \param Y Source MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_copy( mpi *X, const mpi *Y ); + +/** + * \brief Swap the contents of X and Y + * + * \param X First MPI value + * \param Y Second MPI value + */ +void mpi_swap( mpi *X, mpi *Y ); + +/** + * \brief Set value from integer + * + * \param X MPI to set + * \param z Value to use + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_lset( mpi *X, t_sint z ); + +/** + * \brief Get a specific bit from X + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * + * \return Either a 0 or a 1 + */ +int mpi_get_bit( const mpi *X, size_t pos ); + +/** + * \brief Set a bit of X to a specific value of 0 or 1 + * + * \note Will grow X if necessary to set a bit to 1 in a not yet + * existing limb. Will not grow if bit should be set to 0 + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * \param val The value to set the bit to (0 or 1) + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1 + */ +int mpi_set_bit( mpi *X, size_t pos, unsigned char val ); + +/** + * \brief Return the number of zero-bits before the least significant + * '1' bit + * + * Note: Thus also the zero-based index of the least significant '1' bit + * + * \param X MPI to use + */ +size_t mpi_lsb( const mpi *X ); + +/** + * \brief Return the number of bits up to and including the most + * significant '1' bit' + * + * Note: Thus also the one-based index of the most significant '1' bit + * + * \param X MPI to use + */ +size_t mpi_msb( const mpi *X ); + +/** + * \brief Return the total size in bytes + * + * \param X MPI to use + */ +size_t mpi_size( const mpi *X ); + +/** + * \brief Import from an ASCII string + * + * \param X Destination MPI + * \param radix Input numeric base + * \param s Null-terminated string buffer + * + * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code + */ +int mpi_read_string( mpi *X, int radix, const char *s ); + +/** + * \brief Export into an ASCII string + * + * \param X Source MPI + * \param radix Output numeric base + * \param s String buffer + * \param slen String buffer size + * + * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code. + * *slen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *slen = 0 to obtain the + * minimum required buffer size in *slen. + */ +int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen ); + +#if defined(POLARSSL_FS_IO) +/** + * \brief Read X from an opened file + * + * \param X Destination MPI + * \param radix Input numeric base + * \param fin Input file handle + * + * \return 0 if successful, POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if + * the file read buffer is too small or a + * POLARSSL_ERR_MPI_XXX error code + */ +int mpi_read_file( mpi *X, int radix, FILE *fin ); + +/** + * \brief Write X into an opened file, or stdout if fout is NULL + * + * \param p Prefix, can be NULL + * \param X Source MPI + * \param radix Output numeric base + * \param fout Output file handle (can be NULL) + * + * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code + * + * \note Set fout == NULL to print X on the console. + */ +int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout ); +#endif /* POLARSSL_FS_IO */ + +/** + * \brief Import X from unsigned binary data, big endian + * + * \param X Destination MPI + * \param buf Input buffer + * \param buflen Input buffer size + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen ); + +/** + * \brief Export X into unsigned binary data, big endian + * + * \param X Source MPI + * \param buf Output buffer + * \param buflen Output buffer size + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough + */ +int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen ); + +/** + * \brief Left-shift: X <<= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_shift_l( mpi *X, size_t count ); + +/** + * \brief Right-shift: X >>= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_shift_r( mpi *X, size_t count ); + +/** + * \brief Compare unsigned values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if |X| is greater than |Y|, + * -1 if |X| is lesser than |Y| or + * 0 if |X| is equal to |Y| + */ +int mpi_cmp_abs( const mpi *X, const mpi *Y ); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if X is greater than Y, + * -1 if X is lesser than Y or + * 0 if X is equal to Y + */ +int mpi_cmp_mpi( const mpi *X, const mpi *Y ); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param z The integer value to compare to + * + * \return 1 if X is greater than z, + * -1 if X is lesser than z or + * 0 if X is equal to z + */ +int mpi_cmp_int( const mpi *X, t_sint z ); + +/** + * \brief Unsigned addition: X = |A| + |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_add_abs( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Unsigned substraction: X = |A| - |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A + */ +int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Signed addition: X = A + B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Signed substraction: X = A - B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Signed addition: X = A + b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to add + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_add_int( mpi *X, const mpi *A, t_sint b ); + +/** + * \brief Signed substraction: X = A - b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to subtract + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_sub_int( mpi *X, const mpi *A, t_sint b ); + +/** + * \brief Baseline multiplication: X = A * B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Baseline multiplication: X = A * b + * Note: b is an unsigned integer type, thus + * Negative values of b are ignored. + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to multiply with + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_mul_int( mpi *X, const mpi *A, t_sint b ); + +/** + * \brief Division by mpi: A = Q * B + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0 + * + * \note Either Q or R can be NULL. + */ +int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B ); + +/** + * \brief Division by int: A = Q * b + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0 + * + * \note Either Q or R can be NULL. + */ +int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b ); + +/** + * \brief Modulo: R = A mod B + * + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0, + * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B < 0 + */ +int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B ); + +/** + * \brief Modulo: r = A mod b + * + * \param r Destination t_uint + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0, + * POLARSSL_ERR_MPI_NEGATIVE_VALUE if b < 0 + */ +int mpi_mod_int( t_uint *r, const mpi *A, t_sint b ); + +/** + * \brief Sliding-window exponentiation: X = A^E mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param E Exponent MPI + * \param N Modular MPI + * \param _RR Speed-up MPI used for recalculations + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even or if + * E is negative + * + * \note _RR is used to avoid re-computing R*R mod N across + * multiple calls, which speeds up things a bit. It can + * be set to NULL if the extra performance is unneeded. + */ +int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR ); + +/** + * \brief Fill an MPI X with size bytes of random + * + * \param X Destination MPI + * \param size Size in bytes + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_fill_random( mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Greatest common divisor: G = gcd(A, B) + * + * \param G Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_gcd( mpi *G, const mpi *A, const mpi *B ); + +/** + * \brief Modular inverse: X = A^-1 mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param N Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil + POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N + */ +int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N ); + +/** + * \brief Miller-Rabin primality test + * + * \param X MPI to check + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime + */ +int mpi_is_prime( mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Prime number generation + * + * \param X Destination MPI + * \param nbits Required size of X in bits ( 3 <= nbits <= POLARSSL_MPI_MAX_BITS ) + * \param dh_flag If 1, then (X-1)/2 will be prime too + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 + */ +int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mpi_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* bignum.h */ diff --git a/lib/crypto/polarssl/bignum.o b/lib/crypto/polarssl/bignum.o new file mode 100644 index 0000000000000000000000000000000000000000..39f4810f2b709827808f4972c7ea4ec1806577d7 GIT binary patch literal 35360 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 literal 0 HcmV?d00001 diff --git a/lib/crypto/polarssl/bn_mul.h b/lib/crypto/polarssl/bn_mul.h new file mode 100644 index 0000000..7c7b4f7 --- /dev/null +++ b/lib/crypto/polarssl/bn_mul.h @@ -0,0 +1,864 @@ +/** + * \file bn_mul.h + * + * \brief Multi-precision integer library + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * Multiply source vector [s] with b, add result + * to destination vector [d] and set carry c. + * + * Currently supports: + * + * . IA-32 (386+) . AMD64 / EM64T + * . IA-32 (SSE2) . Motorola 68000 + * . PowerPC, 32-bit . MicroBlaze + * . PowerPC, 64-bit . TriCore + * . SPARC v8 . ARM v3+ + * . Alpha . MIPS32 + * . C, longlong . C, generic + */ +#ifndef POLARSSL_BN_MUL_H +#define POLARSSL_BN_MUL_H + +#include "bignum.h" + +#if defined(POLARSSL_HAVE_ASM) + +#if defined(__GNUC__) +#if defined(__i386__) + +#define MULADDC_INIT \ + __asm__( " \ + movl %%ebx, %0; \ + movl %5, %%esi; \ + movl %6, %%edi; \ + movl %7, %%ecx; \ + movl %8, %%ebx; \ + " + +#define MULADDC_CORE \ + " \ + lodsl; \ + mull %%ebx; \ + addl %%ecx, %%eax; \ + adcl $0, %%edx; \ + addl (%%edi), %%eax; \ + adcl $0, %%edx; \ + movl %%edx, %%ecx; \ + stosl; \ + " + +#if defined(POLARSSL_HAVE_SSE2) + +#define MULADDC_HUIT \ + " \ + movd %%ecx, %%mm1; \ + movd %%ebx, %%mm0; \ + movd (%%edi), %%mm3; \ + paddq %%mm3, %%mm1; \ + movd (%%esi), %%mm2; \ + pmuludq %%mm0, %%mm2; \ + movd 4(%%esi), %%mm4; \ + pmuludq %%mm0, %%mm4; \ + movd 8(%%esi), %%mm6; \ + pmuludq %%mm0, %%mm6; \ + movd 12(%%esi), %%mm7; \ + pmuludq %%mm0, %%mm7; \ + paddq %%mm2, %%mm1; \ + movd 4(%%edi), %%mm3; \ + paddq %%mm4, %%mm3; \ + movd 8(%%edi), %%mm5; \ + paddq %%mm6, %%mm5; \ + movd 12(%%edi), %%mm4; \ + paddq %%mm4, %%mm7; \ + movd %%mm1, (%%edi); \ + movd 16(%%esi), %%mm2; \ + pmuludq %%mm0, %%mm2; \ + psrlq $32, %%mm1; \ + movd 20(%%esi), %%mm4; \ + pmuludq %%mm0, %%mm4; \ + paddq %%mm3, %%mm1; \ + movd 24(%%esi), %%mm6; \ + pmuludq %%mm0, %%mm6; \ + movd %%mm1, 4(%%edi); \ + psrlq $32, %%mm1; \ + movd 28(%%esi), %%mm3; \ + pmuludq %%mm0, %%mm3; \ + paddq %%mm5, %%mm1; \ + movd 16(%%edi), %%mm5; \ + paddq %%mm5, %%mm2; \ + movd %%mm1, 8(%%edi); \ + psrlq $32, %%mm1; \ + paddq %%mm7, %%mm1; \ + movd 20(%%edi), %%mm5; \ + paddq %%mm5, %%mm4; \ + movd %%mm1, 12(%%edi); \ + psrlq $32, %%mm1; \ + paddq %%mm2, %%mm1; \ + movd 24(%%edi), %%mm5; \ + paddq %%mm5, %%mm6; \ + movd %%mm1, 16(%%edi); \ + psrlq $32, %%mm1; \ + paddq %%mm4, %%mm1; \ + movd 28(%%edi), %%mm5; \ + paddq %%mm5, %%mm3; \ + movd %%mm1, 20(%%edi); \ + psrlq $32, %%mm1; \ + paddq %%mm6, %%mm1; \ + movd %%mm1, 24(%%edi); \ + psrlq $32, %%mm1; \ + paddq %%mm3, %%mm1; \ + movd %%mm1, 28(%%edi); \ + addl $32, %%edi; \ + addl $32, %%esi; \ + psrlq $32, %%mm1; \ + movd %%mm1, %%ecx; \ + " + +#define MULADDC_STOP \ + " \ + emms; \ + movl %4, %%ebx; \ + movl %%ecx, %1; \ + movl %%edi, %2; \ + movl %%esi, %3; \ + " \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ecx", "edx", "esi", "edi" \ + ); + +#else + +#define MULADDC_STOP \ + " \ + movl %4, %%ebx; \ + movl %%ecx, %1; \ + movl %%edi, %2; \ + movl %%esi, %3; \ + " \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ecx", "edx", "esi", "edi" \ + ); +#endif /* SSE2 */ +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_INIT \ + __asm__( "movq %0, %%rsi " :: "m" (s)); \ + __asm__( "movq %0, %%rdi " :: "m" (d)); \ + __asm__( "movq %0, %%rcx " :: "m" (c)); \ + __asm__( "movq %0, %%rbx " :: "m" (b)); \ + __asm__( "xorq %r8, %r8 " ); + +#define MULADDC_CORE \ + __asm__( "movq (%rsi),%rax " ); \ + __asm__( "mulq %rbx " ); \ + __asm__( "addq $8, %rsi " ); \ + __asm__( "addq %rcx, %rax " ); \ + __asm__( "movq %r8, %rcx " ); \ + __asm__( "adcq $0, %rdx " ); \ + __asm__( "nop " ); \ + __asm__( "addq %rax, (%rdi) " ); \ + __asm__( "adcq %rdx, %rcx " ); \ + __asm__( "addq $8, %rdi " ); + +#define MULADDC_STOP \ + __asm__( "movq %%rcx, %0 " : "=m" (c)); \ + __asm__( "movq %%rdi, %0 " : "=m" (d)); \ + __asm__( "movq %%rsi, %0 " : "=m" (s) :: \ + "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" ); + +#endif /* AMD64 */ + +#if defined(__mc68020__) || defined(__mcpu32__) + +#define MULADDC_INIT \ + __asm__( "movl %0, %%a2 " :: "m" (s)); \ + __asm__( "movl %0, %%a3 " :: "m" (d)); \ + __asm__( "movl %0, %%d3 " :: "m" (c)); \ + __asm__( "movl %0, %%d2 " :: "m" (b)); \ + __asm__( "moveq #0, %d0 " ); + +#define MULADDC_CORE \ + __asm__( "movel %a2@+, %d1 " ); \ + __asm__( "mulul %d2, %d4:%d1 " ); \ + __asm__( "addl %d3, %d1 " ); \ + __asm__( "addxl %d0, %d4 " ); \ + __asm__( "moveq #0, %d3 " ); \ + __asm__( "addl %d1, %a3@+ " ); \ + __asm__( "addxl %d4, %d3 " ); + +#define MULADDC_STOP \ + __asm__( "movl %%d3, %0 " : "=m" (c)); \ + __asm__( "movl %%a3, %0 " : "=m" (d)); \ + __asm__( "movl %%a2, %0 " : "=m" (s) :: \ + "d0", "d1", "d2", "d3", "d4", "a2", "a3" ); + +#define MULADDC_HUIT \ + __asm__( "movel %a2@+, %d1 " ); \ + __asm__( "mulul %d2, %d4:%d1 " ); \ + __asm__( "addxl %d3, %d1 " ); \ + __asm__( "addxl %d0, %d4 " ); \ + __asm__( "addl %d1, %a3@+ " ); \ + __asm__( "movel %a2@+, %d1 " ); \ + __asm__( "mulul %d2, %d3:%d1 " ); \ + __asm__( "addxl %d4, %d1 " ); \ + __asm__( "addxl %d0, %d3 " ); \ + __asm__( "addl %d1, %a3@+ " ); \ + __asm__( "movel %a2@+, %d1 " ); \ + __asm__( "mulul %d2, %d4:%d1 " ); \ + __asm__( "addxl %d3, %d1 " ); \ + __asm__( "addxl %d0, %d4 " ); \ + __asm__( "addl %d1, %a3@+ " ); \ + __asm__( "movel %a2@+, %d1 " ); \ + __asm__( "mulul %d2, %d3:%d1 " ); \ + __asm__( "addxl %d4, %d1 " ); \ + __asm__( "addxl %d0, %d3 " ); \ + __asm__( "addl %d1, %a3@+ " ); \ + __asm__( "movel %a2@+, %d1 " ); \ + __asm__( "mulul %d2, %d4:%d1 " ); \ + __asm__( "addxl %d3, %d1 " ); \ + __asm__( "addxl %d0, %d4 " ); \ + __asm__( "addl %d1, %a3@+ " ); \ + __asm__( "movel %a2@+, %d1 " ); \ + __asm__( "mulul %d2, %d3:%d1 " ); \ + __asm__( "addxl %d4, %d1 " ); \ + __asm__( "addxl %d0, %d3 " ); \ + __asm__( "addl %d1, %a3@+ " ); \ + __asm__( "movel %a2@+, %d1 " ); \ + __asm__( "mulul %d2, %d4:%d1 " ); \ + __asm__( "addxl %d3, %d1 " ); \ + __asm__( "addxl %d0, %d4 " ); \ + __asm__( "addl %d1, %a3@+ " ); \ + __asm__( "movel %a2@+, %d1 " ); \ + __asm__( "mulul %d2, %d3:%d1 " ); \ + __asm__( "addxl %d4, %d1 " ); \ + __asm__( "addxl %d0, %d3 " ); \ + __asm__( "addl %d1, %a3@+ " ); \ + __asm__( "addxl %d0, %d3 " ); + +#endif /* MC68000 */ + +#if defined(__powerpc__) || defined(__ppc__) +#if defined(__powerpc64__) || defined(__ppc64__) + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + __asm__( "ld r3, %0 " :: "m" (s)); \ + __asm__( "ld r4, %0 " :: "m" (d)); \ + __asm__( "ld r5, %0 " :: "m" (c)); \ + __asm__( "ld r6, %0 " :: "m" (b)); \ + __asm__( "addi r3, r3, -8 " ); \ + __asm__( "addi r4, r4, -8 " ); \ + __asm__( "addic r5, r5, 0 " ); + +#define MULADDC_CORE \ + __asm__( "ldu r7, 8(r3) " ); \ + __asm__( "mulld r8, r7, r6 " ); \ + __asm__( "mulhdu r9, r7, r6 " ); \ + __asm__( "adde r8, r8, r5 " ); \ + __asm__( "ld r7, 8(r4) " ); \ + __asm__( "addze r5, r9 " ); \ + __asm__( "addc r8, r8, r7 " ); \ + __asm__( "stdu r8, 8(r4) " ); + +#define MULADDC_STOP \ + __asm__( "addze r5, r5 " ); \ + __asm__( "addi r4, r4, 8 " ); \ + __asm__( "addi r3, r3, 8 " ); \ + __asm__( "std r5, %0 " : "=m" (c)); \ + __asm__( "std r4, %0 " : "=m" (d)); \ + __asm__( "std r3, %0 " : "=m" (s) :: \ + "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); + +#else + +#define MULADDC_INIT \ + __asm__( "ld %%r3, %0 " :: "m" (s)); \ + __asm__( "ld %%r4, %0 " :: "m" (d)); \ + __asm__( "ld %%r5, %0 " :: "m" (c)); \ + __asm__( "ld %%r6, %0 " :: "m" (b)); \ + __asm__( "addi %r3, %r3, -8 " ); \ + __asm__( "addi %r4, %r4, -8 " ); \ + __asm__( "addic %r5, %r5, 0 " ); + +#define MULADDC_CORE \ + __asm__( "ldu %r7, 8(%r3) " ); \ + __asm__( "mulld %r8, %r7, %r6 " ); \ + __asm__( "mulhdu %r9, %r7, %r6 " ); \ + __asm__( "adde %r8, %r8, %r5 " ); \ + __asm__( "ld %r7, 8(%r4) " ); \ + __asm__( "addze %r5, %r9 " ); \ + __asm__( "addc %r8, %r8, %r7 " ); \ + __asm__( "stdu %r8, 8(%r4) " ); + +#define MULADDC_STOP \ + __asm__( "addze %r5, %r5 " ); \ + __asm__( "addi %r4, %r4, 8 " ); \ + __asm__( "addi %r3, %r3, 8 " ); \ + __asm__( "std %%r5, %0 " : "=m" (c)); \ + __asm__( "std %%r4, %0 " : "=m" (d)); \ + __asm__( "std %%r3, %0 " : "=m" (s) :: \ + "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); + +#endif + +#else /* PPC32 */ + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + __asm__( "lwz r3, %0 " :: "m" (s)); \ + __asm__( "lwz r4, %0 " :: "m" (d)); \ + __asm__( "lwz r5, %0 " :: "m" (c)); \ + __asm__( "lwz r6, %0 " :: "m" (b)); \ + __asm__( "addi r3, r3, -4 " ); \ + __asm__( "addi r4, r4, -4 " ); \ + __asm__( "addic r5, r5, 0 " ); + +#define MULADDC_CORE \ + __asm__( "lwzu r7, 4(r3) " ); \ + __asm__( "mullw r8, r7, r6 " ); \ + __asm__( "mulhwu r9, r7, r6 " ); \ + __asm__( "adde r8, r8, r5 " ); \ + __asm__( "lwz r7, 4(r4) " ); \ + __asm__( "addze r5, r9 " ); \ + __asm__( "addc r8, r8, r7 " ); \ + __asm__( "stwu r8, 4(r4) " ); + +#define MULADDC_STOP \ + __asm__( "addze r5, r5 " ); \ + __asm__( "addi r4, r4, 4 " ); \ + __asm__( "addi r3, r3, 4 " ); \ + __asm__( "stw r5, %0 " : "=m" (c)); \ + __asm__( "stw r4, %0 " : "=m" (d)); \ + __asm__( "stw r3, %0 " : "=m" (s) :: \ + "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); + +#else + +#define MULADDC_INIT \ + __asm__( "lwz %%r3, %0 " :: "m" (s)); \ + __asm__( "lwz %%r4, %0 " :: "m" (d)); \ + __asm__( "lwz %%r5, %0 " :: "m" (c)); \ + __asm__( "lwz %%r6, %0 " :: "m" (b)); \ + __asm__( "addi %r3, %r3, -4 " ); \ + __asm__( "addi %r4, %r4, -4 " ); \ + __asm__( "addic %r5, %r5, 0 " ); + +#define MULADDC_CORE \ + __asm__( "lwzu %r7, 4(%r3) " ); \ + __asm__( "mullw %r8, %r7, %r6 " ); \ + __asm__( "mulhwu %r9, %r7, %r6 " ); \ + __asm__( "adde %r8, %r8, %r5 " ); \ + __asm__( "lwz %r7, 4(%r4) " ); \ + __asm__( "addze %r5, %r9 " ); \ + __asm__( "addc %r8, %r8, %r7 " ); \ + __asm__( "stwu %r8, 4(%r4) " ); + +#define MULADDC_STOP \ + __asm__( "addze %r5, %r5 " ); \ + __asm__( "addi %r4, %r4, 4 " ); \ + __asm__( "addi %r3, %r3, 4 " ); \ + __asm__( "stw %%r5, %0 " : "=m" (c)); \ + __asm__( "stw %%r4, %0 " : "=m" (d)); \ + __asm__( "stw %%r3, %0 " : "=m" (s) :: \ + "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); + +#endif + +#endif /* PPC32 */ +#endif /* PPC64 */ + +#if defined(__sparc__) && defined(__sparc64__) + +#define MULADDC_INIT \ + __asm__( \ + " \ + ldx %3, %%o0; \ + ldx %4, %%o1; \ + ld %5, %%o2; \ + ld %6, %%o3; \ + " + +#define MULADDC_CORE \ + " \ + ld [%%o0], %%o4; \ + inc 4, %%o0; \ + ld [%%o1], %%o5; \ + umul %%o3, %%o4, %%o4; \ + addcc %%o4, %%o2, %%o4; \ + rd %%y, %%g1; \ + addx %%g1, 0, %%g1; \ + addcc %%o4, %%o5, %%o4; \ + st %%o4, [%%o1]; \ + addx %%g1, 0, %%o2; \ + inc 4, %%o1; \ + " + +#define MULADDC_STOP \ + " \ + st %%o2, %0; \ + stx %%o1, %1; \ + stx %%o0, %2; \ + " \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); +#endif /* SPARCv9 */ + +#if defined(__sparc__) && !defined(__sparc64__) + +#define MULADDC_INIT \ + __asm__( \ + " \ + ld %3, %%o0; \ + ld %4, %%o1; \ + ld %5, %%o2; \ + ld %6, %%o3; \ + " + +#define MULADDC_CORE \ + " \ + ld [%%o0], %%o4; \ + inc 4, %%o0; \ + ld [%%o1], %%o5; \ + umul %%o3, %%o4, %%o4; \ + addcc %%o4, %%o2, %%o4; \ + rd %%y, %%g1; \ + addx %%g1, 0, %%g1; \ + addcc %%o4, %%o5, %%o4; \ + st %%o4, [%%o1]; \ + addx %%g1, 0, %%o2; \ + inc 4, %%o1; \ + " + +#define MULADDC_STOP \ + " \ + st %%o2, %0; \ + st %%o1, %1; \ + st %%o0, %2; \ + " \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#endif /* SPARCv8 */ + +#if defined(__microblaze__) || defined(microblaze) + +#define MULADDC_INIT \ + __asm__( "lwi r3, %0 " :: "m" (s)); \ + __asm__( "lwi r4, %0 " :: "m" (d)); \ + __asm__( "lwi r5, %0 " :: "m" (c)); \ + __asm__( "lwi r6, %0 " :: "m" (b)); \ + __asm__( "andi r7, r6, 0xffff" ); \ + __asm__( "bsrli r6, r6, 16 " ); + +#define MULADDC_CORE \ + __asm__( "lhui r8, r3, 0 " ); \ + __asm__( "addi r3, r3, 2 " ); \ + __asm__( "lhui r9, r3, 0 " ); \ + __asm__( "addi r3, r3, 2 " ); \ + __asm__( "mul r10, r9, r6 " ); \ + __asm__( "mul r11, r8, r7 " ); \ + __asm__( "mul r12, r9, r7 " ); \ + __asm__( "mul r13, r8, r6 " ); \ + __asm__( "bsrli r8, r10, 16 " ); \ + __asm__( "bsrli r9, r11, 16 " ); \ + __asm__( "add r13, r13, r8 " ); \ + __asm__( "add r13, r13, r9 " ); \ + __asm__( "bslli r10, r10, 16 " ); \ + __asm__( "bslli r11, r11, 16 " ); \ + __asm__( "add r12, r12, r10 " ); \ + __asm__( "addc r13, r13, r0 " ); \ + __asm__( "add r12, r12, r11 " ); \ + __asm__( "addc r13, r13, r0 " ); \ + __asm__( "lwi r10, r4, 0 " ); \ + __asm__( "add r12, r12, r10 " ); \ + __asm__( "addc r13, r13, r0 " ); \ + __asm__( "add r12, r12, r5 " ); \ + __asm__( "addc r5, r13, r0 " ); \ + __asm__( "swi r12, r4, 0 " ); \ + __asm__( "addi r4, r4, 4 " ); + +#define MULADDC_STOP \ + __asm__( "swi r5, %0 " : "=m" (c)); \ + __asm__( "swi r4, %0 " : "=m" (d)); \ + __asm__( "swi r3, %0 " : "=m" (s) :: \ + "r3", "r4" , "r5" , "r6" , "r7" , "r8" , \ + "r9", "r10", "r11", "r12", "r13" ); + +#endif /* MicroBlaze */ + +#if defined(__tricore__) + +#define MULADDC_INIT \ + __asm__( "ld.a %%a2, %0 " :: "m" (s)); \ + __asm__( "ld.a %%a3, %0 " :: "m" (d)); \ + __asm__( "ld.w %%d4, %0 " :: "m" (c)); \ + __asm__( "ld.w %%d1, %0 " :: "m" (b)); \ + __asm__( "xor %d5, %d5 " ); + +#define MULADDC_CORE \ + __asm__( "ld.w %d0, [%a2+] " ); \ + __asm__( "madd.u %e2, %e4, %d0, %d1 " ); \ + __asm__( "ld.w %d0, [%a3] " ); \ + __asm__( "addx %d2, %d2, %d0 " ); \ + __asm__( "addc %d3, %d3, 0 " ); \ + __asm__( "mov %d4, %d3 " ); \ + __asm__( "st.w [%a3+], %d2 " ); + +#define MULADDC_STOP \ + __asm__( "st.w %0, %%d4 " : "=m" (c)); \ + __asm__( "st.a %0, %%a3 " : "=m" (d)); \ + __asm__( "st.a %0, %%a2 " : "=m" (s) :: \ + "d0", "d1", "e2", "d4", "a2", "a3" ); + +#endif /* TriCore */ + +#if defined(__arm__) + +#if defined(__thumb__) && !defined(__thumb2__) + +#define MULADDC_INIT \ + __asm__( \ + " \ + ldr r0, %3; \ + ldr r1, %4; \ + ldr r2, %5; \ + ldr r3, %6; \ + lsr r7, r3, #16; \ + mov r9, r7; \ + lsl r7, r3, #16; \ + lsr r7, r7, #16; \ + mov r8, r7; \ + " + +#define MULADDC_CORE \ + " \ + ldmia r0!, {r6}; \ + lsr r7, r6, #16; \ + lsl r6, r6, #16; \ + lsr r6, r6, #16; \ + mov r4, r8; \ + mul r4, r6; \ + mov r3, r9; \ + mul r6, r3; \ + mov r5, r9; \ + mul r5, r7; \ + mov r3, r8; \ + mul r7, r3; \ + lsr r3, r6, #16; \ + add r5, r5, r3; \ + lsr r3, r7, #16; \ + add r5, r5, r3; \ + add r4, r4, r2; \ + mov r2, #0; \ + adc r5, r2; \ + lsl r3, r6, #16; \ + add r4, r4, r3; \ + adc r5, r2; \ + lsl r3, r7, #16; \ + add r4, r4, r3; \ + adc r5, r2; \ + ldr r3, [r1]; \ + add r4, r4, r3; \ + adc r2, r5; \ + stmia r1!, {r4}; \ + " + +#define MULADDC_STOP \ + " \ + str r2, %0; \ + str r1, %1; \ + str r0, %2; \ + " \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "r8", "r9", "cc" \ + ); + +#else + +#define MULADDC_INIT \ + __asm__( \ + " \ + ldr r0, %3; \ + ldr r1, %4; \ + ldr r2, %5; \ + ldr r3, %6; \ + " + +#define MULADDC_CORE \ + " \ + ldr r4, [r0], #4; \ + mov r5, #0; \ + ldr r6, [r1]; \ + umlal r2, r5, r3, r4; \ + adds r7, r6, r2; \ + adc r2, r5, #0; \ + str r7, [r1], #4; \ + " + +#define MULADDC_STOP \ + " \ + str r2, %0; \ + str r1, %1; \ + str r0, %2; \ + " \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "cc" \ + ); + +#endif /* Thumb */ + +#endif /* ARMv3 */ + +#if defined(__alpha__) + +#define MULADDC_INIT \ + __asm__( "ldq $1, %0 " :: "m" (s)); \ + __asm__( "ldq $2, %0 " :: "m" (d)); \ + __asm__( "ldq $3, %0 " :: "m" (c)); \ + __asm__( "ldq $4, %0 " :: "m" (b)); + +#define MULADDC_CORE \ + __asm__( "ldq $6, 0($1) " ); \ + __asm__( "addq $1, 8, $1 " ); \ + __asm__( "mulq $6, $4, $7 " ); \ + __asm__( "umulh $6, $4, $6 " ); \ + __asm__( "addq $7, $3, $7 " ); \ + __asm__( "cmpult $7, $3, $3 " ); \ + __asm__( "ldq $5, 0($2) " ); \ + __asm__( "addq $7, $5, $7 " ); \ + __asm__( "cmpult $7, $5, $5 " ); \ + __asm__( "stq $7, 0($2) " ); \ + __asm__( "addq $2, 8, $2 " ); \ + __asm__( "addq $6, $3, $3 " ); \ + __asm__( "addq $5, $3, $3 " ); + +#define MULADDC_STOP \ + __asm__( "stq $3, %0 " : "=m" (c)); \ + __asm__( "stq $2, %0 " : "=m" (d)); \ + __asm__( "stq $1, %0 " : "=m" (s) :: \ + "$1", "$2", "$3", "$4", "$5", "$6", "$7" ); + +#endif /* Alpha */ + +#if defined(__mips__) + +#define MULADDC_INIT \ + __asm__( "lw $10, %0 " :: "m" (s)); \ + __asm__( "lw $11, %0 " :: "m" (d)); \ + __asm__( "lw $12, %0 " :: "m" (c)); \ + __asm__( "lw $13, %0 " :: "m" (b)); + +#define MULADDC_CORE \ + __asm__( "lw $14, 0($10) " ); \ + __asm__( "multu $13, $14 " ); \ + __asm__( "addi $10, $10, 4 " ); \ + __asm__( "mflo $14 " ); \ + __asm__( "mfhi $9 " ); \ + __asm__( "addu $14, $12, $14 " ); \ + __asm__( "lw $15, 0($11) " ); \ + __asm__( "sltu $12, $14, $12 " ); \ + __asm__( "addu $15, $14, $15 " ); \ + __asm__( "sltu $14, $15, $14 " ); \ + __asm__( "addu $12, $12, $9 " ); \ + __asm__( "sw $15, 0($11) " ); \ + __asm__( "addu $12, $12, $14 " ); \ + __asm__( "addi $11, $11, 4 " ); + +#define MULADDC_STOP \ + __asm__( "sw $12, %0 " : "=m" (c)); \ + __asm__( "sw $11, %0 " : "=m" (d)); \ + __asm__( "sw $10, %0 " : "=m" (s) :: \ + "$9", "$10", "$11", "$12", "$13", "$14", "$15" ); + +#endif /* MIPS */ +#endif /* GNUC */ + +#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + +#define MULADDC_INIT \ + ____asm__ mov esi, s \ + ____asm__ mov edi, d \ + ____asm__ mov ecx, c \ + ____asm__ mov ebx, b + +#define MULADDC_CORE \ + ____asm__ lodsd \ + ____asm__ mul ebx \ + ____asm__ add eax, ecx \ + ____asm__ adc edx, 0 \ + ____asm__ add eax, [edi] \ + ____asm__ adc edx, 0 \ + ____asm__ mov ecx, edx \ + ____asm__ stosd + +#if defined(POLARSSL_HAVE_SSE2) + +#define EMIT ____asm__ _emit + +#define MULADDC_HUIT \ + EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ + EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ + EMIT 0x0F EMIT 0x6E EMIT 0x1F \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x16 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ + EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ + EMIT 0x0F EMIT 0x7E EMIT 0x0F \ + EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ + EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ + EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x7E EMIT 0xC9 + +#define MULADDC_STOP \ + EMIT 0x0F EMIT 0x77 \ + ____asm__ mov c, ecx \ + ____asm__ mov d, edi \ + ____asm__ mov s, esi \ + +#else + +#define MULADDC_STOP \ + ____asm__ mov c, ecx \ + ____asm__ mov d, edi \ + ____asm__ mov s, esi \ + +#endif /* SSE2 */ +#endif /* MSVC */ + +#endif /* POLARSSL_HAVE_ASM */ + +#if !defined(MULADDC_CORE) +#if defined(POLARSSL_HAVE_UDBL) + +#define MULADDC_INIT \ +{ \ + t_udbl r; \ + t_uint r0, r1; + +#define MULADDC_CORE \ + r = *(s++) * (t_udbl) b; \ + r0 = r; \ + r1 = r >> biL; \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#else +#define MULADDC_INIT \ +{ \ + t_uint s0, s1, b0, b1; \ + t_uint r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_CORE \ + s0 = ( *s << biH ) >> biH; \ + s1 = ( *s >> biH ); s++; \ + rx = s0 * b1; r0 = s0 * b0; \ + ry = s1 * b0; r1 = s1 * b1; \ + r1 += ( rx >> biH ); \ + r1 += ( ry >> biH ); \ + rx <<= biH; ry <<= biH; \ + r0 += rx; r1 += (r0 < rx); \ + r0 += ry; r1 += (r0 < ry); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#endif /* C (generic) */ +#endif /* C (longlong) */ + +#endif /* bn_mul.h */ diff --git a/lib/crypto/polarssl/config.h b/lib/crypto/polarssl/config.h new file mode 100644 index 0000000..2c43ff4 --- /dev/null +++ b/lib/crypto/polarssl/config.h @@ -0,0 +1,1013 @@ +/** + * \file config.h + * + * \brief Configuration options (set of defines) + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +#ifndef POLARSSL_CONFIG_H +#define POLARSSL_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def POLARSSL_HAVE_INT8 + * + * The system uses 8-bit wide native integers. + * + * Uncomment if native integers are 8-bit wide. +#define POLARSSL_HAVE_INT8 + */ + +/** + * \def POLARSSL_HAVE_INT16 + * + * The system uses 16-bit wide native integers. + * + * Uncomment if native integers are 16-bit wide. +#define POLARSSL_HAVE_INT16 + */ + +/** + * \def POLARSSL_HAVE_LONGLONG + * + * The compiler supports the 'long long' type. + * (Only used on 32-bit platforms) + */ +#define POLARSSL_HAVE_LONGLONG + +/** + * \def POLARSSL_HAVE_ASM + * + * The compiler has support for asm() + * + * Uncomment to enable the use of assembly code. + * + * Requires support for asm() in compiler. + * + * Used in: + * library/timing.c + * library/padlock.c + * include/polarssl/bn_mul.h + * + */ +//#define POLARSSL_HAVE_ASM + +/** + * \def POLARSSL_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + * +#define POLARSSL_HAVE_SSE2 + */ +/* \} name */ + +/** + * \name SECTION: PolarSSL feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def POLARSSL_XXX_ALT + * + * Uncomment a macro to let PolarSSL use your alternate core implementation of + * a symmetric or hash algorithm (e.g. platform specific assembly optimized + * implementations). Keep in mind that the function prototypes should remain + * the same. + * + * Example: In case you uncomment POLARSSL_AES_ALT, PolarSSL will no longer + * provide the "struct aes_context" definition and omit the base function + * declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation for core algorithm + * functions +#define POLARSSL_AES_ALT +#define POLARSSL_ARC4_ALT +#define POLARSSL_BLOWFISH_ALT +#define POLARSSL_CAMELLIA_ALT +#define POLARSSL_DES_ALT +#define POLARSSL_XTEA_ALT +#define POLARSSL_MD2_ALT +#define POLARSSL_MD4_ALT +#define POLARSSL_MD5_ALT +#define POLARSSL_SHA1_ALT +#define POLARSSL_SHA2_ALT +#define POLARSSL_SHA4_ALT + */ + +/** + * \def POLARSSL_AES_ROM_TABLES + * + * Store the AES tables in ROM. + * + * Uncomment this macro to store the AES tables in ROM. + * +#define POLARSSL_AES_ROM_TABLES + */ + +/** + * \def POLARSSL_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +//#define POLARSSL_CIPHER_MODE_CFB + +/** + * \def POLARSSL_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CTR + +/** + * \def POLARSSL_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * TLS_RSA_WITH_NULL_MD5 + * TLS_RSA_WITH_NULL_SHA + * TLS_RSA_WITH_NULL_SHA256 + * + * Uncomment this macro to enable the NULL cipher and ciphersuites +#define POLARSSL_CIPHER_NULL_CIPHER + */ + +/** + * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * TLS_RSA_WITH_DES_CBC_SHA + * TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites +#define POLARSSL_ENABLE_WEAK_CIPHERSUITES + */ + +/** + * \def POLARSSL_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of error_strerror() in + * third party libraries easier. + * + * Disable if you run into name conflicts and want to really remove the + * error_strerror() + */ +//#define POLARSSL_ERROR_STRERROR_DUMMY + +/** + * \def POLARSSL_GENPRIME + * + * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C + * + * Enable the RSA prime-number generation code. + */ +//#define POLARSSL_GENPRIME + +/** + * \def POLARSSL_FS_IO + * + * Enable functions that use the filesystem. + */ +//#define POLARSSL_FS_IO + +/** + * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. +#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES + */ + +/** + * \def POLARSSL_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. +#define POLARSSL_NO_PLATFORM_ENTROPY + */ + +/** + * \def POLARSSL_PKCS1_V21 + * + * Requires: POLARSSL_MD_C, POLARSSL_RSA_C + * + * Enable support for PKCS#1 v2.1 encoding. + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +//#define POLARSSL_PKCS1_V21 + +/** + * \def POLARSSL_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +#define POLARSSL_RSA_NO_CRT + + +/** + * \def POLARSSL_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +//#define POLARSSL_SELF_TEST + +/** + * \def POLARSSL_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, PolarSSL can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +//#define POLARSSL_SSL_ALERT_MESSAGES + +/** + * \def POLARSSL_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * +#define POLARSSL_SSL_DEBUG_ALL + */ + +/** + * \def POLARSSL_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. +#define POLARSSL_SSL_HW_RECORD_ACCEL + */ + +/** + * \def POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (POLARSSL_SSL_SRV_C) + * + * Comment this macro to disable support for SSLv2 Client Hello messages. + */ +//#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + +/** + * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * Uncomment to prevent an error. + * +#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + */ + +/** + * \def POLARSSL_ZLIB_SUPPORT + * + * If set, the SSL/TLS module uses ZLIB to support compression and + * decompression of packet data. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB +#define POLARSSL_ZLIB_SUPPORT + */ +/* \} name */ + +/** + * \name SECTION: PolarSSL modules + * + * This section enables or disables entire modules in PolarSSL + * \{ + */ + +/** + * \def POLARSSL_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/ssl_tls.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_WITH_AES_128_CBC_SHA + * TLS_RSA_WITH_AES_256_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * TLS_RSA_WITH_AES_128_CBC_SHA256 + * TLS_RSA_WITH_AES_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * TLS_RSA_WITH_AES_128_GCM_SHA256 + * TLS_RSA_WITH_AES_256_GCM_SHA384 + * + * PEM uses AES for decrypting encrypted keys. + */ +#define POLARSSL_AES_C + +/** + * \def POLARSSL_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites: + * TLS_RSA_WITH_RC4_128_MD5 + * TLS_RSA_WITH_RC4_128_SHA + */ +//#define POLARSSL_ARC4_C + +/** + * \def POLARSSL_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509parse.c + */ +//#define POLARSSL_ASN1_PARSE_C + +/** + * \def POLARSSL_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + */ +//#define POLARSSL_ASN1_WRITE_C + +/** + * \def POLARSSL_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +#define POLARSSL_BASE64_C + +/** + * \def POLARSSL_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/rsa.c + * library/ssl_tls.c + * library/x509parse.c + * + * This module is required for RSA and DHM support. + */ +#define POLARSSL_BIGNUM_C + +/** + * \def POLARSSL_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +//#define POLARSSL_BLOWFISH_C + +/** + * \def POLARSSL_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + */ +//#define POLARSSL_CAMELLIA_C + +/** + * \def POLARSSL_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * This module is used for testing (ssl_client/server). + */ +//#define POLARSSL_CERTS_C + +/** + * \def POLARSSL_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: + * + * Uncomment to enable generic cipher wrappers. + */ +//#define POLARSSL_CIPHER_C + +/** + * \def POLARSSL_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-256-based random generator + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: POLARSSL_AES_C + * + * This module provides the CTR_DRBG AES-256 random number generator. + */ +//#define POLARSSL_CTR_DRBG_C + +/** + * \def POLARSSL_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +//#define POLARSSL_DEBUG_C + +/** + * \def POLARSSL_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * + * PEM uses DES/3DES for decrypting encrypted keys. + */ +//#define POLARSSL_DES_C + +/** + * \def POLARSSL_DHM_C + * + * Enable the Diffie-Hellman-Merkle key exchange. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_DHE_RSA_WITH_DES_CBC_SHA + * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + */ +//#define POLARSSL_DHM_C + +/** + * \def POLARSSL_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: POLARSSL_SHA4_C + * + * This module provides a generic entropy pool + */ +//#define POLARSSL_ENTROPY_C + +/** + * \def POLARSSL_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables err_strerror(). + */ +//#define POLARSSL_ERROR_C + +/** + * \def POLARSSL_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES + * + * Module: library/gcm.c + * + * Requires: POLARSSL_AES_C + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_WITH_AES_128_GCM_SHA256 + * TLS_RSA_WITH_AES_256_GCM_SHA384 + */ +//#define POLARSSL_GCM_C + +/** + * \def POLARSSL_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: POLARSSL_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. +#define POLARSSL_HAVEGE_C + */ + +/** + * \def POLARSSL_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +//#define POLARSSL_MD_C + +/** + * \def POLARSSL_MD2_C + * + * Enable the MD2 hash algorithm + * + * Module: library/md2.c + * Caller: library/x509parse.c + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + * +#define POLARSSL_MD2_C + */ + +/** + * \def POLARSSL_MD4_C + * + * Enable the MD4 hash algorithm + * + * Module: library/md4.c + * Caller: library/x509parse.c + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + * +#define POLARSSL_MD4_C + */ + +/** + * \def POLARSSL_MD5_C + * + * Enable the MD5 hash algorithm + * + * Module: library/md5.c + * Caller: library/pem.c + * library/ssl_tls.c + * library/x509parse.c + * + * This module is required for SSL/TLS and X.509. + * PEM uses MD5 for decrypting encrypted keys. + */ +//#define POLARSSL_MD5_C + +/** + * \def POLARSSL_NET_C + * + * Enable the TCP/IP networking routines. + * + * Module: library/net.c + * Caller: + * + * This module provides TCP/IP networking routines. + */ +//#define POLARSSL_NET_C + +/** + * \def POLARSSL_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * This modules adds support for the VIA PadLock on x86. + */ +//#define POLARSSL_PADLOCK_C + +/** + * \def POLARSSL_PBKDF2_C + * + * Enable PKCS#5 PBKDF2 key derivation function + * DEPRECATED: Use POLARSSL_PKCS5_C instead + * + * Module: library/pbkdf2.c + * + * Requires: POLARSSL_PKCS5_C + * + * This module adds support for the PKCS#5 PBKDF2 key derivation function. +#define POLARSSL_PBKDF2_C + */ + +/** + * \def POLARSSL_PEM_C + * + * Enable PEM decoding + * + * Module: library/pem.c + * Caller: library/x509parse.c + * + * Requires: POLARSSL_BASE64_C + * + * This modules adds support for decoding PEM files. + */ +//#define POLARSSL_PEM_C + +/** + * \def POLARSSL_PKCS5_C + * + * Enable PKCS#5 functions + * + * Module: library/pkcs5.c + * + * Requires: POLARSSL_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +//#define POLARSSL_PKCS5_C + +/** + * \def POLARSSL_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/ssl_srv.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) +#define POLARSSL_PKCS11_C + */ + +/** + * \def POLARSSL_PKCS12_C + * + * Enable PKCS#12 PBE functions + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/x509parse.c + * + * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_CIPHER_C, POLARSSL_MD_C + * Can use: POLARSSL_ARC4_C + * + * This module enables PKCS#12 functions. + */ +//#define POLARSSL_PKCS12_C + +/** + * \def POLARSSL_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * Requires: POLARSSL_BIGNUM_C + * + * This module is required for SSL/TLS and MD5-signed certificates. + */ +#define POLARSSL_RSA_C + +/** + * \def POLARSSL_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509parse.c + * + * This module is required for SSL/TLS and SHA1-signed certificates. + */ +#define POLARSSL_SHA1_C + +/** + * \def POLARSSL_SHA2_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/sha2.c + * Caller: library/md_wrap.c + * library/x509parse.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define POLARSSL_SHA2_C + +/** + * \def POLARSSL_SHA4_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * + * Module: library/sha4.c + * Caller: library/md_wrap.c + * library/x509parse.c + * + * This module adds support for SHA-384 and SHA-512. + */ +//#define POLARSSL_SHA4_C + +/** + * \def POLARSSL_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: POLARSSL_SSL_CACHE_C + */ +//#define POLARSSL_SSL_CACHE_C + +/** + * \def POLARSSL_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +//#define POLARSSL_SSL_CLI_C + +/** + * \def POLARSSL_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +//#define POLARSSL_SSL_SRV_C + +/** + * \def POLARSSL_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: POLARSSL_MD5_C, POLARSSL_SHA1_C, POLARSSL_X509_PARSE_C + * + * This module is required for SSL/TLS. + */ +//#define POLARSSL_SSL_TLS_C + +/** + * \def POLARSSL_TIMING_C + * + * Enable the portable timing interface. + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +//#define POLARSSL_TIMING_C + +/** + * \def POLARSSL_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +//#define POLARSSL_VERSION_C + +/** + * \def POLARSSL_X509_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509parse.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_RSA_C + * + * This module is required for X.509 certificate parsing. + */ +//#define POLARSSL_X509_PARSE_C + +/** + * \def POLARSSL_X509_WRITE_C + * + * Enable X.509 buffer writing. + * + * Module: library/x509write.c + * + * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C + * + * This module is required for X.509 certificate request writing. + */ +//#define POLARSSL_X509_WRITE_C + +/** + * \def POLARSSL_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +//#define POLARSSL_XTEA_C +/* \} name */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * Our advice is to enable POLARSSL_CONFIG_OPTIONS and change values here + * only if you have a good reason and know the consequences. + * + * If POLARSSL_CONFIG_OPTIONS is undefined here the options in the module + * header file take precedence. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * + * Uncomment POLARSSL_CONFIG_OPTIONS to enable using the values defined here. + * \{ + */ +//#define POLARSSL_CONFIG_OPTIONS /**< Enable config.h module value configuration */ + +#if defined(POLARSSL_CONFIG_OPTIONS) + +// MPI / BIGNUM options +// +#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +#define POLARSSL_MPI_MAX_SIZE 512 /**< Maximum number of bytes for usable MPIs. */ + +// CTR_DRBG options +// +#define CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default */ +#define CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +#define CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +#define CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +#define CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +// Entropy options +// +#define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +#define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ + +// SSL Cache options +// +#define SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +#define SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +// SSL options +// +#define SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ + +#endif /* POLARSSL_CONFIG_OPTIONS */ + +/* \} name */ +#endif /* config.h */ diff --git a/lib/crypto/polarssl/rsa.c b/lib/crypto/polarssl/rsa.c new file mode 100644 index 0000000..29dd7bf --- /dev/null +++ b/lib/crypto/polarssl/rsa.c @@ -0,0 +1,1466 @@ +/* + * The RSA public-key cryptosystem + * + * Copyright (C) 2006-2011, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * RSA was designed by Ron Rivest, Adi Shamir and Len Adleman. + * + * http://theory.lcs.mit.edu/~rivest/rsapaper.pdf + * http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf + */ + +#include "config.h" + +#if defined(POLARSSL_RSA_C) + +#include "rsa.h" + +#if defined(POLARSSL_PKCS1_V21) +#include "md.h" +#endif + +#include +#include + +/* + * Initialize an RSA context + */ +void rsa_init( rsa_context *ctx, + int padding, + int hash_id ) +{ + memset( ctx, 0, sizeof( rsa_context ) ); + + ctx->padding = padding; + ctx->hash_id = hash_id; +} + +#if defined(POLARSSL_GENPRIME) + +/* + * Generate an RSA keypair + */ +int rsa_gen_key( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ) +{ + int ret; + mpi P1, Q1, H, G; + + if( f_rng == NULL || nbits < 128 || exponent < 3 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + mpi_init( &P1 ); mpi_init( &Q1 ); mpi_init( &H ); mpi_init( &G ); + + /* + * find primes P and Q with Q < P so that: + * GCD( E, (P-1)*(Q-1) ) == 1 + */ + MPI_CHK( mpi_lset( &ctx->E, exponent ) ); + + do + { + MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0, + f_rng, p_rng ) ); + + MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0, + f_rng, p_rng ) ); + + if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) + mpi_swap( &ctx->P, &ctx->Q ); + + if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) + continue; + + MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); + if( mpi_msb( &ctx->N ) != nbits ) + continue; + + MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); + MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); + MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) ); + } + while( mpi_cmp_int( &G, 1 ) != 0 ); + + /* + * D = E^-1 mod ((P-1)*(Q-1)) + * DP = D mod (P - 1) + * DQ = D mod (Q - 1) + * QP = Q^-1 mod P + */ + MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); + MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); + MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); + MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); + + ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3; + +cleanup: + + mpi_free( &P1 ); mpi_free( &Q1 ); mpi_free( &H ); mpi_free( &G ); + + if( ret != 0 ) + { + rsa_free( ctx ); + return( POLARSSL_ERR_RSA_KEY_GEN_FAILED + ret ); + } + + return( 0 ); +} + +#endif + +/* + * Check a public RSA key + */ +int rsa_check_pubkey( const rsa_context *ctx ) +{ + if( !ctx->N.p || !ctx->E.p ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + if( ( ctx->N.p[0] & 1 ) == 0 || + ( ctx->E.p[0] & 1 ) == 0 ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + if( mpi_msb( &ctx->N ) < 128 || + mpi_msb( &ctx->N ) > POLARSSL_MPI_MAX_BITS ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + if( mpi_msb( &ctx->E ) < 2 || + mpi_msb( &ctx->E ) > 64 ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + return( 0 ); +} + +/* + * Check a private RSA key + */ +int rsa_check_privkey( const rsa_context *ctx ) +{ + int ret; + mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP; + + if( ( ret = rsa_check_pubkey( ctx ) ) != 0 ) + return( ret ); + + if( !ctx->P.p || !ctx->Q.p || !ctx->D.p ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + mpi_init( &PQ ); mpi_init( &DE ); mpi_init( &P1 ); mpi_init( &Q1 ); + mpi_init( &H ); mpi_init( &I ); mpi_init( &G ); mpi_init( &G2 ); + mpi_init( &L1 ); mpi_init( &L2 ); mpi_init( &DP ); mpi_init( &DQ ); + mpi_init( &QP ); + + MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) ); + MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) ); + MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); + MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); + MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) ); + + MPI_CHK( mpi_gcd( &G2, &P1, &Q1 ) ); + MPI_CHK( mpi_div_mpi( &L1, &L2, &H, &G2 ) ); + MPI_CHK( mpi_mod_mpi( &I, &DE, &L1 ) ); + + MPI_CHK( mpi_mod_mpi( &DP, &ctx->D, &P1 ) ); + MPI_CHK( mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) ); + MPI_CHK( mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) ); + /* + * Check for a valid PKCS1v2 private key + */ + if( mpi_cmp_mpi( &PQ, &ctx->N ) != 0 || + mpi_cmp_mpi( &DP, &ctx->DP ) != 0 || + mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 || + mpi_cmp_mpi( &QP, &ctx->QP ) != 0 || + mpi_cmp_int( &L2, 0 ) != 0 || + mpi_cmp_int( &I, 1 ) != 0 || + mpi_cmp_int( &G, 1 ) != 0 ) + { + ret = POLARSSL_ERR_RSA_KEY_CHECK_FAILED; + } + +cleanup: + mpi_free( &PQ ); mpi_free( &DE ); mpi_free( &P1 ); mpi_free( &Q1 ); + mpi_free( &H ); mpi_free( &I ); mpi_free( &G ); mpi_free( &G2 ); + mpi_free( &L1 ); mpi_free( &L2 ); mpi_free( &DP ); mpi_free( &DQ ); + mpi_free( &QP ); + + if( ret == POLARSSL_ERR_RSA_KEY_CHECK_FAILED ) + return( ret ); + + if( ret != 0 ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED + ret ); + + return( 0 ); +} + +/* + * Do an RSA public key operation + */ +int rsa_public( rsa_context *ctx, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t olen; + mpi T; + + mpi_init( &T ); + + MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); + + if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + mpi_free( &T ); + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + + olen = ctx->len; + MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); + MPI_CHK( mpi_write_binary( &T, output, olen ) ); + +cleanup: + + mpi_free( &T ); + + if( ret != 0 ) + return( POLARSSL_ERR_RSA_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Do an RSA private key operation + */ +int rsa_private( rsa_context *ctx, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t olen; + mpi T, T1, T2; + + mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 ); + + MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); + + if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + mpi_free( &T ); + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + +#if defined(POLARSSL_RSA_NO_CRT) + MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) ); +#else + /* + * faster decryption using the CRT + * + * T1 = input ^ dP mod P + * T2 = input ^ dQ mod Q + */ + MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) ); + MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) ); + + /* + * T = (T1 - T2) * (Q^-1 mod P) mod P + */ + MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) ); + MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) ); + MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) ); + + /* + * output = T2 + T * Q + */ + MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) ); + MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) ); +#endif + + olen = ctx->len; + MPI_CHK( mpi_write_binary( &T, output, olen ) ); + +cleanup: + + mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 ); + + if( ret != 0 ) + return( POLARSSL_ERR_RSA_PRIVATE_FAILED + ret ); + + return( 0 ); +} + +#if defined(POLARSSL_PKCS1_V21) +/** + * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. + * + * \param dst buffer to mask + * \param dlen length of destination buffer + * \param src source of the mask generation + * \param slen length of the source buffer + * \param md_ctx message digest context to use + */ +static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, size_t slen, + md_context_t *md_ctx ) +{ + unsigned char mask[POLARSSL_MD_MAX_SIZE]; + unsigned char counter[4]; + unsigned char *p; + unsigned int hlen; + size_t i, use_len; + + memset( mask, 0, POLARSSL_MD_MAX_SIZE ); + memset( counter, 0, 4 ); + + hlen = md_ctx->md_info->size; + + // Generate and apply dbMask + // + p = dst; + + while( dlen > 0 ) + { + use_len = hlen; + if( dlen < hlen ) + use_len = dlen; + + md_starts( md_ctx ); + md_update( md_ctx, src, slen ); + md_update( md_ctx, counter, 4 ); + md_finish( md_ctx, mask ); + + for( i = 0; i < use_len; ++i ) + *p++ ^= mask[i]; + + counter[3]++; + + dlen -= use_len; + } +} +#endif + +#if defined(POLARSSL_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function + */ +int rsa_rsaes_oaep_encrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t olen; + int ret; + unsigned char *p = output; + unsigned int hlen; + const md_info_t *md_info; + md_context_t md_ctx; + + if( ctx->padding != RSA_PKCS_V21 || f_rng == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + md_info = md_info_from_type( ctx->hash_id ); + + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + hlen = md_get_size( md_info ); + + if( olen < ilen + 2 * hlen + 2 || f_rng == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + memset( output, 0, olen ); + + *p++ = 0; + + // Generate a random octet string seed + // + if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) + return( POLARSSL_ERR_RSA_RNG_FAILED + ret ); + + p += hlen; + + // Construct DB + // + md( md_info, label, label_len, p ); + p += hlen; + p += olen - 2 * hlen - 2 - ilen; + *p++ = 1; + memcpy( p, input, ilen ); + + md_init_ctx( &md_ctx, md_info ); + + // maskedDB: Apply dbMask to DB + // + mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, + &md_ctx ); + + // maskedSeed: Apply seedMask to seed + // + mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, + &md_ctx ); + + md_free_ctx( &md_ctx ); + + return( ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, output, output ) + : rsa_private( ctx, output, output ) ); +} +#endif /* POLARSSL_PKCS1_V21 */ + +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function + */ +int rsa_rsaes_pkcs1_v15_encrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t nb_pad, olen; + int ret; + unsigned char *p = output; + + if( ctx->padding != RSA_PKCS_V15 || f_rng == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + if( olen < ilen + 11 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad = olen - 3 - ilen; + + *p++ = 0; + if( mode == RSA_PUBLIC ) + { + *p++ = RSA_CRYPT; + + while( nb_pad-- > 0 ) + { + int rng_dl = 100; + + do { + ret = f_rng( p_rng, p, 1 ); + } while( *p == 0 && --rng_dl && ret == 0 ); + + // Check if RNG failed to generate data + // + if( rng_dl == 0 || ret != 0) + return POLARSSL_ERR_RSA_RNG_FAILED + ret; + + p++; + } + } + else + { + *p++ = RSA_SIGN; + + while( nb_pad-- > 0 ) + *p++ = 0xFF; + } + + *p++ = 0; + memcpy( p, input, ilen ); + + return( ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, output, output ) + : rsa_private( ctx, output, output ) ); +} + +/* + * Add the message padding, then do an RSA operation + */ +int rsa_pkcs1_encrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + switch( ctx->padding ) + { + case RSA_PKCS_V15: + return rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen, + input, output ); + +#if defined(POLARSSL_PKCS1_V21) + case RSA_PKCS_V21: + return rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0, + ilen, input, output ); +#endif + + default: + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(POLARSSL_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function + */ +int rsa_rsaes_oaep_decrypt( rsa_context *ctx, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + int ret; + size_t ilen; + unsigned char *p; + unsigned char buf[POLARSSL_MPI_MAX_SIZE]; + unsigned char lhash[POLARSSL_MD_MAX_SIZE]; + unsigned int hlen; + const md_info_t *md_info; + md_context_t md_ctx; + + if( ctx->padding != RSA_PKCS_V21 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, input, buf ) + : rsa_private( ctx, input, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + if( *p++ != 0 ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + + md_info = md_info_from_type( ctx->hash_id ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + hlen = md_get_size( md_info ); + + md_init_ctx( &md_ctx, md_info ); + + // Generate lHash + // + md( md_info, label, label_len, lhash ); + + // seed: Apply seedMask to maskedSeed + // + mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, + &md_ctx ); + + // DB: Apply dbMask to maskedDB + // + mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, + &md_ctx ); + + p += hlen; + md_free_ctx( &md_ctx ); + + // Check validity + // + if( memcmp( lhash, p, hlen ) != 0 ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + + p += hlen; + + while( *p == 0 && p < buf + ilen ) + p++; + + if( p == buf + ilen ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + + if( *p++ != 0x01 ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + + if (ilen - (p - buf) > output_max_len) + return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); + + *olen = ilen - (p - buf); + memcpy( output, p, *olen ); + + return( 0 ); +} +#endif /* POLARSSL_PKCS1_V21 */ + +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function + */ +int rsa_rsaes_pkcs1_v15_decrypt( rsa_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len) +{ + int ret, correct = 1; + size_t ilen, pad_count = 0; + unsigned char *p, *q; + unsigned char bt; + unsigned char buf[POLARSSL_MPI_MAX_SIZE]; + + if( ctx->padding != RSA_PKCS_V15 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, input, buf ) + : rsa_private( ctx, input, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + if( *p++ != 0 ) + correct = 0; + + bt = *p++; + if( ( bt != RSA_CRYPT && mode == RSA_PRIVATE ) || + ( bt != RSA_SIGN && mode == RSA_PUBLIC ) ) + { + correct = 0; + } + + if( bt == RSA_CRYPT ) + { + while( *p != 0 && p < buf + ilen - 1 ) + pad_count += ( *p++ != 0 ); + + correct &= ( *p == 0 && p < buf + ilen - 1 ); + + q = p; + + // Also pass over all other bytes to reduce timing differences + // + while ( q < buf + ilen - 1 ) + pad_count += ( *q++ != 0 ); + + // Prevent compiler optimization of pad_count + // + correct |= pad_count & 0x100000; /* Always 0 unless 1M bit keys */ + p++; + } + else + { + while( *p == 0xFF && p < buf + ilen - 1 ) + pad_count += ( *p++ == 0xFF ); + + correct &= ( *p == 0 && p < buf + ilen - 1 ); + + q = p; + + // Also pass over all other bytes to reduce timing differences + // + while ( q < buf + ilen - 1 ) + pad_count += ( *q++ != 0 ); + + // Prevent compiler optimization of pad_count + // + correct |= pad_count & 0x100000; /* Always 0 unless 1M bit keys */ + p++; + } + + if( correct == 0 ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + + if (ilen - (p - buf) > output_max_len) + return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); + + *olen = ilen - (p - buf); + memcpy( output, p, *olen ); + + return( 0 ); +} + +/* + * Do an RSA operation, then remove the message padding + */ +int rsa_pkcs1_decrypt( rsa_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len) +{ + switch( ctx->padding ) + { + case RSA_PKCS_V15: + return rsa_rsaes_pkcs1_v15_decrypt( ctx, mode, olen, input, output, + output_max_len ); + +#if defined(POLARSSL_PKCS1_V21) + case RSA_PKCS_V21: + return rsa_rsaes_oaep_decrypt( ctx, mode, NULL, 0, olen, input, + output, output_max_len ); +#endif + + default: + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(POLARSSL_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function + */ +int rsa_rsassa_pss_sign( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + size_t olen; + unsigned char *p = sig; + unsigned char salt[POLARSSL_MD_MAX_SIZE]; + unsigned int slen, hlen, offset = 0; + int ret; + size_t msb; + const md_info_t *md_info; + md_context_t md_ctx; + + if( ctx->padding != RSA_PKCS_V21 || f_rng == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + switch( hash_id ) + { + case SIG_RSA_MD2: + case SIG_RSA_MD4: + case SIG_RSA_MD5: + hashlen = 16; + break; + + case SIG_RSA_SHA1: + hashlen = 20; + break; + + case SIG_RSA_SHA224: + hashlen = 28; + break; + + case SIG_RSA_SHA256: + hashlen = 32; + break; + + case SIG_RSA_SHA384: + hashlen = 48; + break; + + case SIG_RSA_SHA512: + hashlen = 64; + break; + + default: + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + + md_info = md_info_from_type( ctx->hash_id ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + hlen = md_get_size( md_info ); + slen = hlen; + + if( olen < hlen + slen + 2 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + memset( sig, 0, olen ); + + msb = mpi_msb( &ctx->N ) - 1; + + // Generate salt of length slen + // + if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) + return( POLARSSL_ERR_RSA_RNG_FAILED + ret ); + + // Note: EMSA-PSS encoding is over the length of N - 1 bits + // + msb = mpi_msb( &ctx->N ) - 1; + p += olen - hlen * 2 - 2; + *p++ = 0x01; + memcpy( p, salt, slen ); + p += slen; + + md_init_ctx( &md_ctx, md_info ); + + // Generate H = Hash( M' ) + // + md_starts( &md_ctx ); + md_update( &md_ctx, p, 8 ); + md_update( &md_ctx, hash, hashlen ); + md_update( &md_ctx, salt, slen ); + md_finish( &md_ctx, p ); + + // Compensate for boundary condition when applying mask + // + if( msb % 8 == 0 ) + offset = 1; + + // maskedDB: Apply dbMask to DB + // + mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx ); + + md_free_ctx( &md_ctx ); + + msb = mpi_msb( &ctx->N ) - 1; + sig[0] &= 0xFF >> ( olen * 8 - msb ); + + p += hlen; + *p++ = 0xBC; + + return( ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, sig, sig ) + : rsa_private( ctx, sig, sig ) ); +} +#endif /* POLARSSL_PKCS1_V21 */ + +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function + */ +/* + * Do an RSA operation to sign the message digest + */ +int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + size_t nb_pad, olen; + unsigned char *p = sig; + + if( ctx->padding != RSA_PKCS_V15 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + switch( hash_id ) + { + case SIG_RSA_RAW: + nb_pad = olen - 3 - hashlen; + break; + + case SIG_RSA_MD2: + case SIG_RSA_MD4: + case SIG_RSA_MD5: + nb_pad = olen - 3 - 34; + break; + + case SIG_RSA_SHA1: + nb_pad = olen - 3 - 35; + break; + + case SIG_RSA_SHA224: + nb_pad = olen - 3 - 47; + break; + + case SIG_RSA_SHA256: + nb_pad = olen - 3 - 51; + break; + + case SIG_RSA_SHA384: + nb_pad = olen - 3 - 67; + break; + + case SIG_RSA_SHA512: + nb_pad = olen - 3 - 83; + break; + + + default: + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + + if( ( nb_pad < 8 ) || ( nb_pad > olen ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + *p++ = 0; + *p++ = RSA_SIGN; + memset( p, 0xFF, nb_pad ); + p += nb_pad; + *p++ = 0; + + switch( hash_id ) + { + case SIG_RSA_RAW: + memcpy( p, hash, hashlen ); + break; + + case SIG_RSA_MD2: + memcpy( p, ASN1_HASH_MDX, 18 ); + memcpy( p + 18, hash, 16 ); + p[13] = 2; break; + + case SIG_RSA_MD4: + memcpy( p, ASN1_HASH_MDX, 18 ); + memcpy( p + 18, hash, 16 ); + p[13] = 4; break; + + case SIG_RSA_MD5: + memcpy( p, ASN1_HASH_MDX, 18 ); + memcpy( p + 18, hash, 16 ); + p[13] = 5; break; + + case SIG_RSA_SHA1: + memcpy( p, ASN1_HASH_SHA1, 15 ); + memcpy( p + 15, hash, 20 ); + break; + + case SIG_RSA_SHA224: + memcpy( p, ASN1_HASH_SHA2X, 19 ); + memcpy( p + 19, hash, 28 ); + p[1] += 28; p[14] = 4; p[18] += 28; break; + + case SIG_RSA_SHA256: + memcpy( p, ASN1_HASH_SHA2X, 19 ); + memcpy( p + 19, hash, 32 ); + p[1] += 32; p[14] = 1; p[18] += 32; break; + + case SIG_RSA_SHA384: + memcpy( p, ASN1_HASH_SHA2X, 19 ); + memcpy( p + 19, hash, 48 ); + p[1] += 48; p[14] = 2; p[18] += 48; break; + + case SIG_RSA_SHA512: + memcpy( p, ASN1_HASH_SHA2X, 19 ); + memcpy( p + 19, hash, 64 ); + p[1] += 64; p[14] = 3; p[18] += 64; break; + + default: + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + + return( ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, sig, sig ) + : rsa_private( ctx, sig, sig ) ); +} + +/* + * Do an RSA operation to sign the message digest + */ +int rsa_pkcs1_sign( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + switch( ctx->padding ) + { + case RSA_PKCS_V15: + return rsa_rsassa_pkcs1_v15_sign( ctx, mode, hash_id, + hashlen, hash, sig ); + +#if defined(POLARSSL_PKCS1_V21) + case RSA_PKCS_V21: + return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, hash_id, + hashlen, hash, sig ); +#endif + + default: + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(POLARSSL_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int rsa_rsassa_pss_verify( rsa_context *ctx, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + int ret; + size_t siglen; + unsigned char *p; + unsigned char buf[POLARSSL_MPI_MAX_SIZE]; + unsigned char result[POLARSSL_MD_MAX_SIZE]; + unsigned char zeros[8]; + unsigned int hlen; + size_t slen, msb; + const md_info_t *md_info; + md_context_t md_ctx; + + if( ctx->padding != RSA_PKCS_V21 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + siglen = ctx->len; + + if( siglen < 16 || siglen > sizeof( buf ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, sig, buf ) + : rsa_private( ctx, sig, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + if( buf[siglen - 1] != 0xBC ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + + switch( hash_id ) + { + case SIG_RSA_MD2: + case SIG_RSA_MD4: + case SIG_RSA_MD5: + hashlen = 16; + break; + + case SIG_RSA_SHA1: + hashlen = 20; + break; + + case SIG_RSA_SHA224: + hashlen = 28; + break; + + case SIG_RSA_SHA256: + hashlen = 32; + break; + + case SIG_RSA_SHA384: + hashlen = 48; + break; + + case SIG_RSA_SHA512: + hashlen = 64; + break; + + default: + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + + md_info = md_info_from_type( ctx->hash_id ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + hlen = md_get_size( md_info ); + slen = siglen - hlen - 1; + + memset( zeros, 0, 8 ); + + // Note: EMSA-PSS verification is over the length of N - 1 bits + // + msb = mpi_msb( &ctx->N ) - 1; + + // Compensate for boundary condition when applying mask + // + if( msb % 8 == 0 ) + { + p++; + siglen -= 1; + } + if( buf[0] >> ( 8 - siglen * 8 + msb ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + md_init_ctx( &md_ctx, md_info ); + + mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx ); + + buf[0] &= 0xFF >> ( siglen * 8 - msb ); + + while( *p == 0 && p < buf + siglen ) + p++; + + if( p == buf + siglen || + *p++ != 0x01 ) + { + md_free_ctx( &md_ctx ); + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } + + slen -= p - buf; + + // Generate H = Hash( M' ) + // + md_starts( &md_ctx ); + md_update( &md_ctx, zeros, 8 ); + md_update( &md_ctx, hash, hashlen ); + md_update( &md_ctx, p, slen ); + md_finish( &md_ctx, result ); + + md_free_ctx( &md_ctx ); + + if( memcmp( p + slen, result, hlen ) == 0 ) + return( 0 ); + else + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); +} +#endif /* POLARSSL_PKCS1_V21 */ + +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function + */ +int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + int ret; + size_t len, siglen; + unsigned char *p, c; + unsigned char buf[POLARSSL_MPI_MAX_SIZE]; + + if( ctx->padding != RSA_PKCS_V15 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + siglen = ctx->len; + + if( siglen < 16 || siglen > sizeof( buf ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, sig, buf ) + : rsa_private( ctx, sig, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + if( *p++ != 0 || *p++ != RSA_SIGN ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + + while( *p != 0 ) + { + if( p >= buf + siglen - 1 || *p != 0xFF ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + p++; + } + p++; + + len = siglen - ( p - buf ); + + if( len == 33 && hash_id == SIG_RSA_SHA1 ) + { + if( memcmp( p, ASN1_HASH_SHA1_ALT, 13 ) == 0 && + memcmp( p + 13, hash, 20 ) == 0 ) + return( 0 ); + else + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + } + if( len == 34 ) + { + c = p[13]; + p[13] = 0; + + if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( ( c == 2 && hash_id == SIG_RSA_MD2 ) || + ( c == 4 && hash_id == SIG_RSA_MD4 ) || + ( c == 5 && hash_id == SIG_RSA_MD5 ) ) + { + if( memcmp( p + 18, hash, 16 ) == 0 ) + return( 0 ); + else + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + } + } + + if( len == 35 && hash_id == SIG_RSA_SHA1 ) + { + if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 && + memcmp( p + 15, hash, 20 ) == 0 ) + return( 0 ); + else + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + } + if( ( len == 19 + 28 && p[14] == 4 && hash_id == SIG_RSA_SHA224 ) || + ( len == 19 + 32 && p[14] == 1 && hash_id == SIG_RSA_SHA256 ) || + ( len == 19 + 48 && p[14] == 2 && hash_id == SIG_RSA_SHA384 ) || + ( len == 19 + 64 && p[14] == 3 && hash_id == SIG_RSA_SHA512 ) ) + { + c = p[1] - 17; + p[1] = 17; + p[14] = 0; + + if( p[18] == c && + memcmp( p, ASN1_HASH_SHA2X, 18 ) == 0 && + memcmp( p + 19, hash, c ) == 0 ) + return( 0 ); + else + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + } + + if( len == hashlen && hash_id == SIG_RSA_RAW ) + { + if( memcmp( p, hash, hashlen ) == 0 ) + return( 0 ); + else + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + } + + return( POLARSSL_ERR_RSA_INVALID_PADDING ); +} + +/* + * Do an RSA operation and check the message digest + */ +int rsa_pkcs1_verify( rsa_context *ctx, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + switch( ctx->padding ) + { + case RSA_PKCS_V15: + return rsa_rsassa_pkcs1_v15_verify( ctx, mode, hash_id, + hashlen, hash, sig ); + +#if defined(POLARSSL_PKCS1_V21) + case RSA_PKCS_V21: + return rsa_rsassa_pss_verify( ctx, mode, hash_id, + hashlen, hash, sig ); +#endif + + default: + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } +} + +/* + * Free the components of an RSA key + */ +void rsa_free( rsa_context *ctx ) +{ + mpi_free( &ctx->RQ ); mpi_free( &ctx->RP ); mpi_free( &ctx->RN ); + mpi_free( &ctx->QP ); mpi_free( &ctx->DQ ); mpi_free( &ctx->DP ); + mpi_free( &ctx->Q ); mpi_free( &ctx->P ); mpi_free( &ctx->D ); + mpi_free( &ctx->E ); mpi_free( &ctx->N ); +} + +#if defined(POLARSSL_SELF_TEST) + +#include "polarssl/sha1.h" + +/* + * Example RSA-1024 keypair, for test purposes + */ +#define KEY_LEN 128 + +#define RSA_N "9292758453063D803DD603D5E777D788" \ + "8ED1D5BF35786190FA2F23EBC0848AEA" \ + "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ + "7130B9CED7ACDF54CFC7555AC14EEBAB" \ + "93A89813FBF3C4F8066D2D800F7C38A8" \ + "1AE31942917403FF4946B0A83D3D3E05" \ + "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ + "5E94BB77B07507233A0BC7BAC8F90F79" + +#define RSA_E "10001" + +#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ + "66CA472BC44D253102F8B4A9D3BFA750" \ + "91386C0077937FE33FA3252D28855837" \ + "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ + "DF79C5CE07EE72C7F123142198164234" \ + "CABB724CF78B8173B9F880FC86322407" \ + "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ + "071513A1E85B5DFA031F21ECAE91A34D" + +#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ + "2C01CAD19EA484A87EA4377637E75500" \ + "FCB2005C5C7DD6EC4AC023CDA285D796" \ + "C3D9E75E1EFC42488BB4F1D13AC30A57" + +#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ + "E211C2B9E5DB1ED0BF61D0D9899620F4" \ + "910E4168387E3C30AA1E00C339A79508" \ + "8452DD96A9A5EA5D9DCA68DA636032AF" + +#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \ + "3C94D22288ACD763FD8E5600ED4A702D" \ + "F84198A5F06C2E72236AE490C93F07F8" \ + "3CC559CD27BC2D1CA488811730BB5725" + +#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \ + "D8AAEA56749EA28623272E4F7D0592AF" \ + "7C1F1313CAC9471B5C523BFE592F517B" \ + "407A1BD76C164B93DA2D32A383E58357" + +#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \ + "F38D18D2B2F0E2DD275AA977E2BF4411" \ + "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \ + "A74206CEC169D74BF5A8C50D6F48EA08" + +#define PT_LEN 24 +#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ + "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" + +static int myrand( void *rng_state, unsigned char *output, size_t len ) +{ + size_t i; + + if( rng_state != NULL ) + rng_state = NULL; + + for( i = 0; i < len; ++i ) + output[i] = rand(); + + return( 0 ); +} + +/* + * Checkup routine + */ +int rsa_self_test( int verbose ) +{ + size_t len; + rsa_context rsa; + unsigned char rsa_plaintext[PT_LEN]; + unsigned char rsa_decrypted[PT_LEN]; + unsigned char rsa_ciphertext[KEY_LEN]; +#if defined(POLARSSL_SHA1_C) + unsigned char sha1sum[20]; +#endif + + rsa_init( &rsa, RSA_PKCS_V15, 0 ); + + rsa.len = KEY_LEN; + mpi_read_string( &rsa.N , 16, RSA_N ); + mpi_read_string( &rsa.E , 16, RSA_E ); + mpi_read_string( &rsa.D , 16, RSA_D ); + mpi_read_string( &rsa.P , 16, RSA_P ); + mpi_read_string( &rsa.Q , 16, RSA_Q ); + mpi_read_string( &rsa.DP, 16, RSA_DP ); + mpi_read_string( &rsa.DQ, 16, RSA_DQ ); + mpi_read_string( &rsa.QP, 16, RSA_QP ); + + if( verbose != 0 ) + printf( " RSA key validation: " ); + + if( rsa_check_pubkey( &rsa ) != 0 || + rsa_check_privkey( &rsa ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n PKCS#1 encryption : " ); + + memcpy( rsa_plaintext, RSA_PT, PT_LEN ); + + if( rsa_pkcs1_encrypt( &rsa, &myrand, NULL, RSA_PUBLIC, PT_LEN, + rsa_plaintext, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n PKCS#1 decryption : " ); + + if( rsa_pkcs1_decrypt( &rsa, RSA_PRIVATE, &len, + rsa_ciphertext, rsa_decrypted, + sizeof(rsa_decrypted) ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + +#if defined(POLARSSL_SHA1_C) + if( verbose != 0 ) + printf( "passed\n PKCS#1 data sign : " ); + + sha1( rsa_plaintext, PT_LEN, sha1sum ); + + if( rsa_pkcs1_sign( &rsa, NULL, NULL, RSA_PRIVATE, SIG_RSA_SHA1, 20, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n PKCS#1 sig. verify: " ); + + if( rsa_pkcs1_verify( &rsa, RSA_PUBLIC, SIG_RSA_SHA1, 20, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n\n" ); +#endif /* POLARSSL_SHA1_C */ + + rsa_free( &rsa ); + + return( 0 ); +} + +#endif + +#endif diff --git a/lib/crypto/polarssl/rsa.h b/lib/crypto/polarssl/rsa.h new file mode 100644 index 0000000..8edc21d --- /dev/null +++ b/lib/crypto/polarssl/rsa.h @@ -0,0 +1,597 @@ +/** + * \file rsa.h + * + * \brief The RSA public-key cryptosystem + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_RSA_H +#define POLARSSL_RSA_H + +#include "bignum.h" + +/* + * RSA Error codes + */ +#define POLARSSL_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */ +#define POLARSSL_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */ +#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the libraries validity check. */ +#define POLARSSL_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */ +#define POLARSSL_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */ +#define POLARSSL_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ +#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ +#define POLARSSL_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ + +/* + * PKCS#1 constants + */ +#define SIG_RSA_RAW 0 +#define SIG_RSA_MD2 2 +#define SIG_RSA_MD4 3 +#define SIG_RSA_MD5 4 +#define SIG_RSA_SHA1 5 +#define SIG_RSA_SHA224 14 +#define SIG_RSA_SHA256 11 +#define SIG_RSA_SHA384 12 +#define SIG_RSA_SHA512 13 + +#define RSA_PUBLIC 0 +#define RSA_PRIVATE 1 + +#define RSA_PKCS_V15 0 +#define RSA_PKCS_V21 1 + +#define RSA_SIGN 1 +#define RSA_CRYPT 2 + +#define ASN1_STR_CONSTRUCTED_SEQUENCE "\x30" +#define ASN1_STR_NULL "\x05" +#define ASN1_STR_OID "\x06" +#define ASN1_STR_OCTET_STRING "\x04" + +#define OID_DIGEST_ALG_MDX "\x2A\x86\x48\x86\xF7\x0D\x02\x00" +#define OID_HASH_ALG_SHA1 "\x2b\x0e\x03\x02\x1a" +#define OID_HASH_ALG_SHA2X "\x60\x86\x48\x01\x65\x03\x04\x02\x00" + +#define OID_ISO_MEMBER_BODIES "\x2a" +#define OID_ISO_IDENTIFIED_ORG "\x2b" + +/* + * ISO Member bodies OID parts + */ +#define OID_COUNTRY_US "\x86\x48" +#define OID_RSA_DATA_SECURITY "\x86\xf7\x0d" + +/* + * ISO Identified organization OID parts + */ +#define OID_OIW_SECSIG_SHA1 "\x0e\x03\x02\x1a" + +/* + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * Digest ::= OCTET STRING + */ +#define ASN1_HASH_MDX \ +( \ + ASN1_STR_CONSTRUCTED_SEQUENCE "\x20" \ + ASN1_STR_CONSTRUCTED_SEQUENCE "\x0C" \ + ASN1_STR_OID "\x08" \ + OID_DIGEST_ALG_MDX \ + ASN1_STR_NULL "\x00" \ + ASN1_STR_OCTET_STRING "\x10" \ +) + +#define ASN1_HASH_SHA1 \ + ASN1_STR_CONSTRUCTED_SEQUENCE "\x21" \ + ASN1_STR_CONSTRUCTED_SEQUENCE "\x09" \ + ASN1_STR_OID "\x05" \ + OID_HASH_ALG_SHA1 \ + ASN1_STR_NULL "\x00" \ + ASN1_STR_OCTET_STRING "\x14" + +#define ASN1_HASH_SHA1_ALT \ + ASN1_STR_CONSTRUCTED_SEQUENCE "\x1F" \ + ASN1_STR_CONSTRUCTED_SEQUENCE "\x07" \ + ASN1_STR_OID "\x05" \ + OID_HASH_ALG_SHA1 \ + ASN1_STR_OCTET_STRING "\x14" + +#define ASN1_HASH_SHA2X \ + ASN1_STR_CONSTRUCTED_SEQUENCE "\x11" \ + ASN1_STR_CONSTRUCTED_SEQUENCE "\x0d" \ + ASN1_STR_OID "\x09" \ + OID_HASH_ALG_SHA2X \ + ASN1_STR_NULL "\x00" \ + ASN1_STR_OCTET_STRING "\x00" + +/** + * \brief RSA context structure + */ +typedef struct +{ + int ver; /*!< always 0 */ + size_t len; /*!< size(N) in chars */ + + mpi N; /*!< public modulus */ + mpi E; /*!< public exponent */ + + mpi D; /*!< private exponent */ + mpi P; /*!< 1st prime factor */ + mpi Q; /*!< 2nd prime factor */ + mpi DP; /*!< D % (P - 1) */ + mpi DQ; /*!< D % (Q - 1) */ + mpi QP; /*!< 1 / (Q % P) */ + + mpi RN; /*!< cached R^2 mod N */ + mpi RP; /*!< cached R^2 mod P */ + mpi RQ; /*!< cached R^2 mod Q */ + + int padding; /*!< RSA_PKCS_V15 for 1.5 padding and + RSA_PKCS_v21 for OAEP/PSS */ + int hash_id; /*!< Hash identifier of md_type_t as + specified in the md.h header file + for the EME-OAEP and EMSA-PSS + encoding */ +} +rsa_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize an RSA context + * + * Note: Set padding to RSA_PKCS_V21 for the RSAES-OAEP + * encryption scheme and the RSASSA-PSS signature scheme. + * + * \param ctx RSA context to be initialized + * \param padding RSA_PKCS_V15 or RSA_PKCS_V21 + * \param hash_id RSA_PKCS_V21 hash identifier + * + * \note The hash_id parameter is actually ignored + * when using RSA_PKCS_V15 padding. + */ +void rsa_init( rsa_context *ctx, + int padding, + int hash_id); + +/** + * \brief Generate an RSA keypair + * + * \param ctx RSA context that will hold the key + * \param f_rng RNG function + * \param p_rng RNG parameter + * \param nbits size of the public key in bits + * \param exponent public exponent (e.g., 65537) + * + * \note rsa_init() must be called beforehand to setup + * the RSA context. + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + */ +int rsa_gen_key( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ); + +/** + * \brief Check a public RSA key + * + * \param ctx RSA context to be checked + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + */ +int rsa_check_pubkey( const rsa_context *ctx ); + +/** + * \brief Check a private RSA key + * + * \param ctx RSA context to be checked + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + */ +int rsa_check_privkey( const rsa_context *ctx ); + +/** + * \brief Do an RSA public key operation + * + * \param ctx RSA context + * \param input input buffer + * \param output output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note This function does NOT take care of message + * padding. Also, be sure to set input[0] = 0 or assure that + * input is smaller than N. + * + * \note The input and output buffers must be large + * enough (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_public( rsa_context *ctx, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Do an RSA private key operation + * + * \param ctx RSA context + * \param input input buffer + * \param output output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The input and output buffers must be large + * enough (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_private( rsa_context *ctx, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Generic wrapper to perform a PKCS#1 encryption using the + * mode from the context. Add the message padding, then do an + * RSA operation. + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param ilen contains the plaintext length + * \param input buffer holding the data to be encrypted + * \param output buffer that will hold the ciphertext + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_pkcs1_encrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Perform a PKCS#1 v1.5 encryption (RSAES-PKCS1-v1_5-ENCRYPT) + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for padding) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param ilen contains the plaintext length + * \param input buffer holding the data to be encrypted + * \param output buffer that will hold the ciphertext + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_rsaes_pkcs1_v15_encrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Perform a PKCS#1 v2.1 OAEP encryption (RSAES-OAEP-ENCRYPT) + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param label buffer holding the custom label to use + * \param label_len contains the label length + * \param ilen contains the plaintext length + * \param input buffer holding the data to be encrypted + * \param output buffer that will hold the ciphertext + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_rsaes_oaep_encrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Generic wrapper to perform a PKCS#1 decryption using the + * mode from the context. Do an RSA operation, then remove + * the message padding + * + * \param ctx RSA context + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param olen will contain the plaintext length + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int rsa_pkcs1_decrypt( rsa_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief Perform a PKCS#1 v1.5 decryption (RSAES-PKCS1-v1_5-DECRYPT) + * + * \param ctx RSA context + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param olen will contain the plaintext length + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int rsa_rsaes_pkcs1_v15_decrypt( rsa_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief Perform a PKCS#1 v2.1 OAEP decryption (RSAES-OAEP-DECRYPT) + * + * \param ctx RSA context + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param label buffer holding the custom label to use + * \param label_len contains the label length + * \param olen will contain the plaintext length + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int rsa_rsaes_oaep_decrypt( rsa_context *ctx, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief Generic wrapper to perform a PKCS#1 signature using the + * mode from the context. Do a private RSA operation to sign + * a message digest + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} + * \param hashlen message digest length (for SIG_RSA_RAW only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note In case of PKCS#1 v2.1 encoding keep in mind that + * the hash_id in the RSA context is the one used for the + * encoding. hash_id in the function call is the type of hash + * that is encoded. According to RFC 3447 it is advised to + * keep both hashes the same. + */ +int rsa_pkcs1_sign( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief Perform a PKCS#1 v1.5 signature (RSASSA-PKCS1-v1_5-SIGN) + * + * \param ctx RSA context + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} + * \param hashlen message digest length (for SIG_RSA_RAW only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief Perform a PKCS#1 v2.1 PSS signature (RSASSA-PSS-SIGN) + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} + * \param hashlen message digest length (for SIG_RSA_RAW only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note In case of PKCS#1 v2.1 encoding keep in mind that + * the hash_id in the RSA context is the one used for the + * encoding. hash_id in the function call is the type of hash + * that is encoded. According to RFC 3447 it is advised to + * keep both hashes the same. + */ +int rsa_rsassa_pss_sign( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief Generic wrapper to perform a PKCS#1 verification using the + * mode from the context. Do a public RSA operation and check + * the message digest + * + * \param ctx points to an RSA public key + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} + * \param hashlen message digest length (for SIG_RSA_RAW only) + * \param hash buffer holding the message digest + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note In case of PKCS#1 v2.1 encoding keep in mind that + * the hash_id in the RSA context is the one used for the + * verification. hash_id in the function call is the type of hash + * that is verified. According to RFC 3447 it is advised to + * keep both hashes the same. + */ +int rsa_pkcs1_verify( rsa_context *ctx, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief Perform a PKCS#1 v1.5 verification (RSASSA-PKCS1-v1_5-VERIFY) + * + * \param ctx points to an RSA public key + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} + * \param hashlen message digest length (for SIG_RSA_RAW only) + * \param hash buffer holding the message digest + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY) + * \brief Do a public RSA and check the message digest + * + * \param ctx points to an RSA public key + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} + * \param hashlen message digest length (for SIG_RSA_RAW only) + * \param hash buffer holding the message digest + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note In case of PKCS#1 v2.1 encoding keep in mind that + * the hash_id in the RSA context is the one used for the + * verification. hash_id in the function call is the type of hash + * that is verified. According to RFC 3447 it is advised to + * keep both hashes the same. + */ +int rsa_rsassa_pss_verify( rsa_context *ctx, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief Free the components of an RSA key + * + * \param ctx RSA Context to free + */ +void rsa_free( rsa_context *ctx ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int rsa_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* rsa.h */ diff --git a/lib/crypto/polarssl/rsa.o b/lib/crypto/polarssl/rsa.o new file mode 100644 index 0000000000000000000000000000000000000000..b6e8102869a1ef1b3afc1ff4ea074adc9396dfab GIT binary patch literal 14440 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 jm*2UXeYpJ2)#=0KcdlbTTz= + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#include "config.h" + +#if defined(POLARSSL_SHA1_C) + +#include "sha1.h" + +#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST) +#include +#endif + +#if !defined(POLARSSL_SHA1_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * SHA-1 context setup + */ +void sha1_starts( sha1_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; +} + +void sha1_process( sha1_context *ctx, const unsigned char data[64] ) +{ + uint32_t temp, W[16], A, B, C, D, E; + + GET_UINT32_BE( W[ 0], data, 0 ); + GET_UINT32_BE( W[ 1], data, 4 ); + GET_UINT32_BE( W[ 2], data, 8 ); + GET_UINT32_BE( W[ 3], data, 12 ); + GET_UINT32_BE( W[ 4], data, 16 ); + GET_UINT32_BE( W[ 5], data, 20 ); + GET_UINT32_BE( W[ 6], data, 24 ); + GET_UINT32_BE( W[ 7], data, 28 ); + GET_UINT32_BE( W[ 8], data, 32 ); + GET_UINT32_BE( W[ 9], data, 36 ); + GET_UINT32_BE( W[10], data, 40 ); + GET_UINT32_BE( W[11], data, 44 ); + GET_UINT32_BE( W[12], data, 48 ); + GET_UINT32_BE( W[13], data, 52 ); + GET_UINT32_BE( W[14], data, 56 ); + GET_UINT32_BE( W[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define R(t) \ +( \ + temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ + W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ + ( W[t & 0x0F] = S(temp,1) ) \ +) + +#define P(a,b,c,d,e,x) \ +{ \ + e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define K 0x5A827999 + + P( A, B, C, D, E, W[0] ); + P( E, A, B, C, D, W[1] ); + P( D, E, A, B, C, W[2] ); + P( C, D, E, A, B, W[3] ); + P( B, C, D, E, A, W[4] ); + P( A, B, C, D, E, W[5] ); + P( E, A, B, C, D, W[6] ); + P( D, E, A, B, C, W[7] ); + P( C, D, E, A, B, W[8] ); + P( B, C, D, E, A, W[9] ); + P( A, B, C, D, E, W[10] ); + P( E, A, B, C, D, W[11] ); + P( D, E, A, B, C, W[12] ); + P( C, D, E, A, B, W[13] ); + P( B, C, D, E, A, W[14] ); + P( A, B, C, D, E, W[15] ); + P( E, A, B, C, D, R(16) ); + P( D, E, A, B, C, R(17) ); + P( C, D, E, A, B, R(18) ); + P( B, C, D, E, A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0x6ED9EBA1 + + P( A, B, C, D, E, R(20) ); + P( E, A, B, C, D, R(21) ); + P( D, E, A, B, C, R(22) ); + P( C, D, E, A, B, R(23) ); + P( B, C, D, E, A, R(24) ); + P( A, B, C, D, E, R(25) ); + P( E, A, B, C, D, R(26) ); + P( D, E, A, B, C, R(27) ); + P( C, D, E, A, B, R(28) ); + P( B, C, D, E, A, R(29) ); + P( A, B, C, D, E, R(30) ); + P( E, A, B, C, D, R(31) ); + P( D, E, A, B, C, R(32) ); + P( C, D, E, A, B, R(33) ); + P( B, C, D, E, A, R(34) ); + P( A, B, C, D, E, R(35) ); + P( E, A, B, C, D, R(36) ); + P( D, E, A, B, C, R(37) ); + P( C, D, E, A, B, R(38) ); + P( B, C, D, E, A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) ((x & y) | (z & (x | y))) +#define K 0x8F1BBCDC + + P( A, B, C, D, E, R(40) ); + P( E, A, B, C, D, R(41) ); + P( D, E, A, B, C, R(42) ); + P( C, D, E, A, B, R(43) ); + P( B, C, D, E, A, R(44) ); + P( A, B, C, D, E, R(45) ); + P( E, A, B, C, D, R(46) ); + P( D, E, A, B, C, R(47) ); + P( C, D, E, A, B, R(48) ); + P( B, C, D, E, A, R(49) ); + P( A, B, C, D, E, R(50) ); + P( E, A, B, C, D, R(51) ); + P( D, E, A, B, C, R(52) ); + P( C, D, E, A, B, R(53) ); + P( B, C, D, E, A, R(54) ); + P( A, B, C, D, E, R(55) ); + P( E, A, B, C, D, R(56) ); + P( D, E, A, B, C, R(57) ); + P( C, D, E, A, B, R(58) ); + P( B, C, D, E, A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0xCA62C1D6 + + P( A, B, C, D, E, R(60) ); + P( E, A, B, C, D, R(61) ); + P( D, E, A, B, C, R(62) ); + P( C, D, E, A, B, R(63) ); + P( B, C, D, E, A, R(64) ); + P( A, B, C, D, E, R(65) ); + P( E, A, B, C, D, R(66) ); + P( D, E, A, B, C, R(67) ); + P( C, D, E, A, B, R(68) ); + P( B, C, D, E, A, R(69) ); + P( A, B, C, D, E, R(70) ); + P( E, A, B, C, D, R(71) ); + P( D, E, A, B, C, R(72) ); + P( C, D, E, A, B, R(73) ); + P( B, C, D, E, A, R(74) ); + P( A, B, C, D, E, R(75) ); + P( E, A, B, C, D, R(76) ); + P( D, E, A, B, C, R(77) ); + P( C, D, E, A, B, R(78) ); + P( B, C, D, E, A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; +} + +/* + * SHA-1 process buffer + */ +void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) +{ + size_t fill; + uint32_t left; + + if( ilen <= 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + sha1_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + sha1_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); +} + +static const unsigned char sha1_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-1 final digest + */ +void sha1_finish( sha1_context *ctx, unsigned char output[20] ) +{ + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, msglen, 0 ); + PUT_UINT32_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + sha1_update( ctx, sha1_padding, padn ); + sha1_update( ctx, msglen, 8 ); + + PUT_UINT32_BE( ctx->state[0], output, 0 ); + PUT_UINT32_BE( ctx->state[1], output, 4 ); + PUT_UINT32_BE( ctx->state[2], output, 8 ); + PUT_UINT32_BE( ctx->state[3], output, 12 ); + PUT_UINT32_BE( ctx->state[4], output, 16 ); +} + +#endif /* !POLARSSL_SHA1_ALT */ + +/* + * output = SHA-1( input buffer ) + */ +void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) +{ + sha1_context ctx; + + sha1_starts( &ctx ); + sha1_update( &ctx, input, ilen ); + sha1_finish( &ctx, output ); + + memset( &ctx, 0, sizeof( sha1_context ) ); +} + +#if defined(POLARSSL_FS_IO) +/* + * output = SHA-1( file contents ) + */ +int sha1_file( const char *path, unsigned char output[20] ) +{ + FILE *f; + size_t n; + sha1_context ctx; + unsigned char buf[1024]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_SHA1_FILE_IO_ERROR ); + + sha1_starts( &ctx ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + sha1_update( &ctx, buf, n ); + + sha1_finish( &ctx, output ); + + memset( &ctx, 0, sizeof( sha1_context ) ); + + if( ferror( f ) != 0 ) + { + fclose( f ); + return( POLARSSL_ERR_SHA1_FILE_IO_ERROR ); + } + + fclose( f ); + return( 0 ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * SHA-1 HMAC context setup + */ +void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen ) +{ + size_t i; + unsigned char sum[20]; + + if( keylen > 64 ) + { + sha1( key, keylen, sum ); + keylen = 20; + key = sum; + } + + memset( ctx->ipad, 0x36, 64 ); + memset( ctx->opad, 0x5C, 64 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + sha1_starts( ctx ); + sha1_update( ctx, ctx->ipad, 64 ); + + memset( sum, 0, sizeof( sum ) ); +} + +/* + * SHA-1 HMAC process buffer + */ +void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) +{ + sha1_update( ctx, input, ilen ); +} + +/* + * SHA-1 HMAC final digest + */ +void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] ) +{ + unsigned char tmpbuf[20]; + + sha1_finish( ctx, tmpbuf ); + sha1_starts( ctx ); + sha1_update( ctx, ctx->opad, 64 ); + sha1_update( ctx, tmpbuf, 20 ); + sha1_finish( ctx, output ); + + memset( tmpbuf, 0, sizeof( tmpbuf ) ); +} + +/* + * SHA1 HMAC context reset + */ +void sha1_hmac_reset( sha1_context *ctx ) +{ + sha1_starts( ctx ); + sha1_update( ctx, ctx->ipad, 64 ); +} + +/* + * output = HMAC-SHA-1( hmac key, input buffer ) + */ +void sha1_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[20] ) +{ + sha1_context ctx; + + sha1_hmac_starts( &ctx, key, keylen ); + sha1_hmac_update( &ctx, input, ilen ); + sha1_hmac_finish( &ctx, output ); + + memset( &ctx, 0, sizeof( sha1_context ) ); +} + +#if defined(POLARSSL_SELF_TEST) +/* + * FIPS-180-1 test vectors + */ +static unsigned char sha1_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const int sha1_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha1_test_sum[3][20] = +{ + { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, + 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, + { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, + 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, + { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, + 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } +}; + +/* + * RFC 2202 test vectors + */ +static unsigned char sha1_hmac_test_key[7][26] = +{ + { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" + "\x0B\x0B\x0B\x0B" }, + { "Jefe" }, + { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA" }, + { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19" }, + { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" + "\x0C\x0C\x0C\x0C" }, + { "" }, /* 0xAA 80 times */ + { "" } +}; + +static const int sha1_hmac_test_keylen[7] = +{ + 20, 4, 20, 25, 20, 80, 80 +}; + +static unsigned char sha1_hmac_test_buf[7][74] = +{ + { "Hi There" }, + { "what do ya want for nothing?" }, + { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" }, + { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" }, + { "Test With Truncation" }, + { "Test Using Larger Than Block-Size Key - Hash Key First" }, + { "Test Using Larger Than Block-Size Key and Larger" + " Than One Block-Size Data" } +}; + +static const int sha1_hmac_test_buflen[7] = +{ + 8, 28, 50, 50, 20, 54, 73 +}; + +static const unsigned char sha1_hmac_test_sum[7][20] = +{ + { 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B, + 0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00 }, + { 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74, + 0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79 }, + { 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3, + 0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3 }, + { 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84, + 0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA }, + { 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2, + 0x7B, 0xE1 }, + { 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70, + 0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12 }, + { 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B, + 0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91 } +}; + +/* + * Checkup routine + */ +int sha1_self_test( int verbose ) +{ + int i, j, buflen; + unsigned char buf[1024]; + unsigned char sha1sum[20]; + sha1_context ctx; + + /* + * SHA-1 + */ + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + printf( " SHA-1 test #%d: ", i + 1 ); + + sha1_starts( &ctx ); + + if( i == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + sha1_update( &ctx, buf, buflen ); + } + else + sha1_update( &ctx, sha1_test_buf[i], + sha1_test_buflen[i] ); + + sha1_finish( &ctx, sha1sum ); + + if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n" ); + } + + if( verbose != 0 ) + printf( "\n" ); + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + printf( " HMAC-SHA-1 test #%d: ", i + 1 ); + + if( i == 5 || i == 6 ) + { + memset( buf, '\xAA', buflen = 80 ); + sha1_hmac_starts( &ctx, buf, buflen ); + } + else + sha1_hmac_starts( &ctx, sha1_hmac_test_key[i], + sha1_hmac_test_keylen[i] ); + + sha1_hmac_update( &ctx, sha1_hmac_test_buf[i], + sha1_hmac_test_buflen[i] ); + + sha1_hmac_finish( &ctx, sha1sum ); + + buflen = ( i == 4 ) ? 12 : 20; + + if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n" ); + } + + if( verbose != 0 ) + printf( "\n" ); + + return( 0 ); +} + +#endif + +#endif diff --git a/lib/crypto/polarssl/sha1.h b/lib/crypto/polarssl/sha1.h new file mode 100644 index 0000000..0bb3ba1 --- /dev/null +++ b/lib/crypto/polarssl/sha1.h @@ -0,0 +1,180 @@ +/** + * \file sha1.h + * + * \brief SHA-1 cryptographic hash function + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_SHA1_H +#define POLARSSL_SHA1_H + +#include "config.h" + +#include + +#ifdef _MSC_VER +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +#define POLARSSL_ERR_SHA1_FILE_IO_ERROR -0x0076 /**< Read/write error in file. */ + +#if !defined(POLARSSL_SHA1_ALT) +// Regular implementation +// + +/** + * \brief SHA-1 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + + unsigned char ipad[64]; /*!< HMAC: inner padding */ + unsigned char opad[64]; /*!< HMAC: outer padding */ +} +sha1_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-1 context setup + * + * \param ctx context to be initialized + */ +void sha1_starts( sha1_context *ctx ); + +/** + * \brief SHA-1 process buffer + * + * \param ctx SHA-1 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief SHA-1 final digest + * + * \param ctx SHA-1 context + * \param output SHA-1 checksum result + */ +void sha1_finish( sha1_context *ctx, unsigned char output[20] ); + +/* Internal use */ +void sha1_process( sha1_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_SHA1_ALT */ +#include "polarssl/sha1_alt.h" +#endif /* POLARSSL_SHA1_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = SHA-1( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-1 checksum result + */ +void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ); + +/** + * \brief Output = SHA-1( file contents ) + * + * \param path input file name + * \param output SHA-1 checksum result + * + * \return 0 if successful, or POLARSSL_ERR_SHA1_FILE_IO_ERROR + */ +int sha1_file( const char *path, unsigned char output[20] ); + +/** + * \brief SHA-1 HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param key HMAC secret key + * \param keylen length of the HMAC key + */ +void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen ); + +/** + * \brief SHA-1 HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief SHA-1 HMAC final digest + * + * \param ctx HMAC context + * \param output SHA-1 HMAC checksum result + */ +void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] ); + +/** + * \brief SHA-1 HMAC context reset + * + * \param ctx HMAC context to be reset + */ +void sha1_hmac_reset( sha1_context *ctx ); + +/** + * \brief Output = HMAC-SHA-1( hmac key, input buffer ) + * + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output HMAC-SHA-1 result + */ +void sha1_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[20] ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int sha1_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* sha1.h */ diff --git a/lib/crypto/polarssl/sha1.o b/lib/crypto/polarssl/sha1.o new file mode 100644 index 0000000000000000000000000000000000000000..e4d13d792a92dc296df087845ea6d5fb0bd24b90 GIT binary patch literal 12424 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 + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The SHA-256 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#include "config.h" + +#if defined(POLARSSL_SHA2_C) + +#include "sha2.h" + +#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST) +#include +#endif + +#if !defined(POLARSSL_SHA2_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * SHA-256 context setup + */ +void sha2_starts( sha2_context *ctx, int is224 ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is224 == 0 ) + { + /* SHA-256 */ + ctx->state[0] = 0x6A09E667; + ctx->state[1] = 0xBB67AE85; + ctx->state[2] = 0x3C6EF372; + ctx->state[3] = 0xA54FF53A; + ctx->state[4] = 0x510E527F; + ctx->state[5] = 0x9B05688C; + ctx->state[6] = 0x1F83D9AB; + ctx->state[7] = 0x5BE0CD19; + } + else + { + /* SHA-224 */ + ctx->state[0] = 0xC1059ED8; + ctx->state[1] = 0x367CD507; + ctx->state[2] = 0x3070DD17; + ctx->state[3] = 0xF70E5939; + ctx->state[4] = 0xFFC00B31; + ctx->state[5] = 0x68581511; + ctx->state[6] = 0x64F98FA7; + ctx->state[7] = 0xBEFA4FA4; + } + + ctx->is224 = is224; +} + +void sha2_process( sha2_context *ctx, const unsigned char data[64] ) +{ + uint32_t temp1, temp2, W[64]; + uint32_t A, B, C, D, E, F, G, H; + + GET_UINT32_BE( W[ 0], data, 0 ); + GET_UINT32_BE( W[ 1], data, 4 ); + GET_UINT32_BE( W[ 2], data, 8 ); + GET_UINT32_BE( W[ 3], data, 12 ); + GET_UINT32_BE( W[ 4], data, 16 ); + GET_UINT32_BE( W[ 5], data, 20 ); + GET_UINT32_BE( W[ 6], data, 24 ); + GET_UINT32_BE( W[ 7], data, 28 ); + GET_UINT32_BE( W[ 8], data, 32 ); + GET_UINT32_BE( W[ 9], data, 36 ); + GET_UINT32_BE( W[10], data, 40 ); + GET_UINT32_BE( W[11], data, 44 ); + GET_UINT32_BE( W[12], data, 48 ); + GET_UINT32_BE( W[13], data, 52 ); + GET_UINT32_BE( W[14], data, 56 ); + GET_UINT32_BE( W[15], data, 60 ); + +#define SHR(x,n) ((x & 0xFFFFFFFF) >> n) +#define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) + +#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) +#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) + +#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) +#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) + +#define F0(x,y,z) ((x & y) | (z & (x | y))) +#define F1(x,y,z) (z ^ (x & (y ^ z))) + +#define R(t) \ +( \ + W[t] = S1(W[t - 2]) + W[t - 7] + \ + S0(W[t - 15]) + W[t - 16] \ +) + +#define P(a,b,c,d,e,f,g,h,x,K) \ +{ \ + temp1 = h + S3(e) + F1(e,f,g) + K + x; \ + temp2 = S2(a) + F0(a,b,c); \ + d += temp1; h = temp1 + temp2; \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + F = ctx->state[5]; + G = ctx->state[6]; + H = ctx->state[7]; + + P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 ); + P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 ); + P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF ); + P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 ); + P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B ); + P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 ); + P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 ); + P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 ); + P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 ); + P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 ); + P( G, H, A, B, C, D, E, F, W[10], 0x243185BE ); + P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 ); + P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 ); + P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE ); + P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 ); + P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 ); + P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 ); + P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 ); + P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 ); + P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC ); + P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F ); + P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA ); + P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC ); + P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA ); + P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 ); + P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D ); + P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 ); + P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 ); + P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 ); + P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 ); + P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 ); + P( B, C, D, E, F, G, H, A, R(31), 0x14292967 ); + P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 ); + P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 ); + P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC ); + P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 ); + P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 ); + P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB ); + P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E ); + P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 ); + P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 ); + P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B ); + P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 ); + P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 ); + P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 ); + P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 ); + P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 ); + P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 ); + P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 ); + P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 ); + P( G, H, A, B, C, D, E, F, R(50), 0x2748774C ); + P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 ); + P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 ); + P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A ); + P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F ); + P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 ); + P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE ); + P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F ); + P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 ); + P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 ); + P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA ); + P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB ); + P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 ); + P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 ); + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; + ctx->state[5] += F; + ctx->state[6] += G; + ctx->state[7] += H; +} + +/* + * SHA-256 process buffer + */ +void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen ) +{ + size_t fill; + uint32_t left; + + if( ilen <= 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + sha2_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + sha2_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); +} + +static const unsigned char sha2_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-256 final digest + */ +void sha2_finish( sha2_context *ctx, unsigned char output[32] ) +{ + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, msglen, 0 ); + PUT_UINT32_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + sha2_update( ctx, sha2_padding, padn ); + sha2_update( ctx, msglen, 8 ); + + PUT_UINT32_BE( ctx->state[0], output, 0 ); + PUT_UINT32_BE( ctx->state[1], output, 4 ); + PUT_UINT32_BE( ctx->state[2], output, 8 ); + PUT_UINT32_BE( ctx->state[3], output, 12 ); + PUT_UINT32_BE( ctx->state[4], output, 16 ); + PUT_UINT32_BE( ctx->state[5], output, 20 ); + PUT_UINT32_BE( ctx->state[6], output, 24 ); + + if( ctx->is224 == 0 ) + PUT_UINT32_BE( ctx->state[7], output, 28 ); +} + +#endif /* !POLARSSL_SHA2_ALT */ + +/* + * output = SHA-256( input buffer ) + */ +void sha2( const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ) +{ + sha2_context ctx; + + sha2_starts( &ctx, is224 ); + sha2_update( &ctx, input, ilen ); + sha2_finish( &ctx, output ); + + memset( &ctx, 0, sizeof( sha2_context ) ); +} + +#if defined(POLARSSL_FS_IO) +/* + * output = SHA-256( file contents ) + */ +int sha2_file( const char *path, unsigned char output[32], int is224 ) +{ + FILE *f; + size_t n; + sha2_context ctx; + unsigned char buf[1024]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_SHA2_FILE_IO_ERROR ); + + sha2_starts( &ctx, is224 ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + sha2_update( &ctx, buf, n ); + + sha2_finish( &ctx, output ); + + memset( &ctx, 0, sizeof( sha2_context ) ); + + if( ferror( f ) != 0 ) + { + fclose( f ); + return( POLARSSL_ERR_SHA2_FILE_IO_ERROR ); + } + + fclose( f ); + return( 0 ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * SHA-256 HMAC context setup + */ +void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, size_t keylen, + int is224 ) +{ + size_t i; + unsigned char sum[32]; + + if( keylen > 64 ) + { + sha2( key, keylen, sum, is224 ); + keylen = ( is224 ) ? 28 : 32; + key = sum; + } + + memset( ctx->ipad, 0x36, 64 ); + memset( ctx->opad, 0x5C, 64 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + sha2_starts( ctx, is224 ); + sha2_update( ctx, ctx->ipad, 64 ); + + memset( sum, 0, sizeof( sum ) ); +} + +/* + * SHA-256 HMAC process buffer + */ +void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, size_t ilen ) +{ + sha2_update( ctx, input, ilen ); +} + +/* + * SHA-256 HMAC final digest + */ +void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] ) +{ + int is224, hlen; + unsigned char tmpbuf[32]; + + is224 = ctx->is224; + hlen = ( is224 == 0 ) ? 32 : 28; + + sha2_finish( ctx, tmpbuf ); + sha2_starts( ctx, is224 ); + sha2_update( ctx, ctx->opad, 64 ); + sha2_update( ctx, tmpbuf, hlen ); + sha2_finish( ctx, output ); + + memset( tmpbuf, 0, sizeof( tmpbuf ) ); +} + +/* + * SHA-256 HMAC context reset + */ +void sha2_hmac_reset( sha2_context *ctx ) +{ + sha2_starts( ctx, ctx->is224 ); + sha2_update( ctx, ctx->ipad, 64 ); +} + +/* + * output = HMAC-SHA-256( hmac key, input buffer ) + */ +void sha2_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ) +{ + sha2_context ctx; + + sha2_hmac_starts( &ctx, key, keylen, is224 ); + sha2_hmac_update( &ctx, input, ilen ); + sha2_hmac_finish( &ctx, output ); + + memset( &ctx, 0, sizeof( sha2_context ) ); +} + +#if defined(POLARSSL_SELF_TEST) +/* + * FIPS-180-2 test vectors + */ +static unsigned char sha2_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const int sha2_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha2_test_sum[6][32] = +{ + /* + * SHA-224 test vectors + */ + { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, + 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, + 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, + 0xE3, 0x6C, 0x9D, 0xA7 }, + { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, + 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, + 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, + 0x52, 0x52, 0x25, 0x25 }, + { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, + 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, + 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, + 0x4E, 0xE7, 0xAD, 0x67 }, + + /* + * SHA-256 test vectors + */ + { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, + 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, + 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, + 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, + { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, + 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, + 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, + 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, + { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, + 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, + 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, + 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } +}; + +/* + * RFC 4231 test vectors + */ +static unsigned char sha2_hmac_test_key[7][26] = +{ + { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" + "\x0B\x0B\x0B\x0B" }, + { "Jefe" }, + { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA" }, + { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19" }, + { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" + "\x0C\x0C\x0C\x0C" }, + { "" }, /* 0xAA 131 times */ + { "" } +}; + +static const int sha2_hmac_test_keylen[7] = +{ + 20, 4, 20, 25, 20, 131, 131 +}; + +static unsigned char sha2_hmac_test_buf[7][153] = +{ + { "Hi There" }, + { "what do ya want for nothing?" }, + { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" }, + { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" }, + { "Test With Truncation" }, + { "Test Using Larger Than Block-Size Key - Hash Key First" }, + { "This is a test using a larger than block-size key " + "and a larger than block-size data. The key needs to " + "be hashed before being used by the HMAC algorithm." } +}; + +static const int sha2_hmac_test_buflen[7] = +{ + 8, 28, 50, 50, 20, 54, 152 +}; + +static const unsigned char sha2_hmac_test_sum[14][32] = +{ + /* + * HMAC-SHA-224 test vectors + */ + { 0x89, 0x6F, 0xB1, 0x12, 0x8A, 0xBB, 0xDF, 0x19, + 0x68, 0x32, 0x10, 0x7C, 0xD4, 0x9D, 0xF3, 0x3F, + 0x47, 0xB4, 0xB1, 0x16, 0x99, 0x12, 0xBA, 0x4F, + 0x53, 0x68, 0x4B, 0x22 }, + { 0xA3, 0x0E, 0x01, 0x09, 0x8B, 0xC6, 0xDB, 0xBF, + 0x45, 0x69, 0x0F, 0x3A, 0x7E, 0x9E, 0x6D, 0x0F, + 0x8B, 0xBE, 0xA2, 0xA3, 0x9E, 0x61, 0x48, 0x00, + 0x8F, 0xD0, 0x5E, 0x44 }, + { 0x7F, 0xB3, 0xCB, 0x35, 0x88, 0xC6, 0xC1, 0xF6, + 0xFF, 0xA9, 0x69, 0x4D, 0x7D, 0x6A, 0xD2, 0x64, + 0x93, 0x65, 0xB0, 0xC1, 0xF6, 0x5D, 0x69, 0xD1, + 0xEC, 0x83, 0x33, 0xEA }, + { 0x6C, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3C, 0xAC, + 0x6A, 0x2A, 0xBC, 0x1B, 0xB3, 0x82, 0x62, 0x7C, + 0xEC, 0x6A, 0x90, 0xD8, 0x6E, 0xFC, 0x01, 0x2D, + 0xE7, 0xAF, 0xEC, 0x5A }, + { 0x0E, 0x2A, 0xEA, 0x68, 0xA9, 0x0C, 0x8D, 0x37, + 0xC9, 0x88, 0xBC, 0xDB, 0x9F, 0xCA, 0x6F, 0xA8 }, + { 0x95, 0xE9, 0xA0, 0xDB, 0x96, 0x20, 0x95, 0xAD, + 0xAE, 0xBE, 0x9B, 0x2D, 0x6F, 0x0D, 0xBC, 0xE2, + 0xD4, 0x99, 0xF1, 0x12, 0xF2, 0xD2, 0xB7, 0x27, + 0x3F, 0xA6, 0x87, 0x0E }, + { 0x3A, 0x85, 0x41, 0x66, 0xAC, 0x5D, 0x9F, 0x02, + 0x3F, 0x54, 0xD5, 0x17, 0xD0, 0xB3, 0x9D, 0xBD, + 0x94, 0x67, 0x70, 0xDB, 0x9C, 0x2B, 0x95, 0xC9, + 0xF6, 0xF5, 0x65, 0xD1 }, + + /* + * HMAC-SHA-256 test vectors + */ + { 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53, + 0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B, + 0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7, + 0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7 }, + { 0x5B, 0xDC, 0xC1, 0x46, 0xBF, 0x60, 0x75, 0x4E, + 0x6A, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xC7, + 0x5A, 0x00, 0x3F, 0x08, 0x9D, 0x27, 0x39, 0x83, + 0x9D, 0xEC, 0x58, 0xB9, 0x64, 0xEC, 0x38, 0x43 }, + { 0x77, 0x3E, 0xA9, 0x1E, 0x36, 0x80, 0x0E, 0x46, + 0x85, 0x4D, 0xB8, 0xEB, 0xD0, 0x91, 0x81, 0xA7, + 0x29, 0x59, 0x09, 0x8B, 0x3E, 0xF8, 0xC1, 0x22, + 0xD9, 0x63, 0x55, 0x14, 0xCE, 0xD5, 0x65, 0xFE }, + { 0x82, 0x55, 0x8A, 0x38, 0x9A, 0x44, 0x3C, 0x0E, + 0xA4, 0xCC, 0x81, 0x98, 0x99, 0xF2, 0x08, 0x3A, + 0x85, 0xF0, 0xFA, 0xA3, 0xE5, 0x78, 0xF8, 0x07, + 0x7A, 0x2E, 0x3F, 0xF4, 0x67, 0x29, 0x66, 0x5B }, + { 0xA3, 0xB6, 0x16, 0x74, 0x73, 0x10, 0x0E, 0xE0, + 0x6E, 0x0C, 0x79, 0x6C, 0x29, 0x55, 0x55, 0x2B }, + { 0x60, 0xE4, 0x31, 0x59, 0x1E, 0xE0, 0xB6, 0x7F, + 0x0D, 0x8A, 0x26, 0xAA, 0xCB, 0xF5, 0xB7, 0x7F, + 0x8E, 0x0B, 0xC6, 0x21, 0x37, 0x28, 0xC5, 0x14, + 0x05, 0x46, 0x04, 0x0F, 0x0E, 0xE3, 0x7F, 0x54 }, + { 0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB, + 0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44, + 0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93, + 0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2 } +}; + +/* + * Checkup routine + */ +int sha2_self_test( int verbose ) +{ + int i, j, k, buflen; + unsigned char buf[1024]; + unsigned char sha2sum[32]; + sha2_context ctx; + + for( i = 0; i < 6; i++ ) + { + j = i % 3; + k = i < 3; + + if( verbose != 0 ) + printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); + + sha2_starts( &ctx, k ); + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + sha2_update( &ctx, buf, buflen ); + } + else + sha2_update( &ctx, sha2_test_buf[j], + sha2_test_buflen[j] ); + + sha2_finish( &ctx, sha2sum ); + + if( memcmp( sha2sum, sha2_test_sum[i], 32 - k * 4 ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n" ); + } + + if( verbose != 0 ) + printf( "\n" ); + + for( i = 0; i < 14; i++ ) + { + j = i % 7; + k = i < 7; + + if( verbose != 0 ) + printf( " HMAC-SHA-%d test #%d: ", 256 - k * 32, j + 1 ); + + if( j == 5 || j == 6 ) + { + memset( buf, '\xAA', buflen = 131 ); + sha2_hmac_starts( &ctx, buf, buflen, k ); + } + else + sha2_hmac_starts( &ctx, sha2_hmac_test_key[j], + sha2_hmac_test_keylen[j], k ); + + sha2_hmac_update( &ctx, sha2_hmac_test_buf[j], + sha2_hmac_test_buflen[j] ); + + sha2_hmac_finish( &ctx, sha2sum ); + + buflen = ( j == 4 ) ? 16 : 32 - k * 4; + + if( memcmp( sha2sum, sha2_hmac_test_sum[i], buflen ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n" ); + } + + if( verbose != 0 ) + printf( "\n" ); + + return( 0 ); +} + +#endif + +#endif diff --git a/lib/crypto/polarssl/sha2.h b/lib/crypto/polarssl/sha2.h new file mode 100644 index 0000000..f271974 --- /dev/null +++ b/lib/crypto/polarssl/sha2.h @@ -0,0 +1,183 @@ +/** + * \file sha2.h + * + * \brief SHA-224 and SHA-256 cryptographic hash function + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_SHA2_H +#define POLARSSL_SHA2_H + +#include "config.h" + +#include + +#ifdef _MSC_VER +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +#define POLARSSL_ERR_SHA2_FILE_IO_ERROR -0x0078 /**< Read/write error in file. */ + +// Regular implementation +// + +/** + * \brief SHA-256 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[8]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + + unsigned char ipad[64]; /*!< HMAC: inner padding */ + unsigned char opad[64]; /*!< HMAC: outer padding */ + int is224; /*!< 0 => SHA-256, else SHA-224 */ +} +sha2_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-256 context setup + * + * \param ctx context to be initialized + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void sha2_starts( sha2_context *ctx, int is224 ); + +/** + * \brief SHA-256 process buffer + * + * \param ctx SHA-256 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief SHA-256 final digest + * + * \param ctx SHA-256 context + * \param output SHA-224/256 checksum result + */ +void sha2_finish( sha2_context *ctx, unsigned char output[32] ); + +/* Internal use */ +void sha2_process( sha2_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = SHA-256( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-224/256 checksum result + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void sha2( const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ); + +/** + * \brief Output = SHA-256( file contents ) + * + * \param path input file name + * \param output SHA-224/256 checksum result + * \param is224 0 = use SHA256, 1 = use SHA224 + * + * \return 0 if successful, or POLARSSL_ERR_SHA2_FILE_IO_ERROR + */ +int sha2_file( const char *path, unsigned char output[32], int is224 ); + +/** + * \brief SHA-256 HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, size_t keylen, + int is224 ); + +/** + * \brief SHA-256 HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief SHA-256 HMAC final digest + * + * \param ctx HMAC context + * \param output SHA-224/256 HMAC checksum result + */ +void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] ); + +/** + * \brief SHA-256 HMAC context reset + * + * \param ctx HMAC context to be reset + */ +void sha2_hmac_reset( sha2_context *ctx ); + +/** + * \brief Output = HMAC-SHA-256( hmac key, input buffer ) + * + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output HMAC-SHA-224/256 result + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void sha2_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int sha2_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* sha2.h */ diff --git a/lib/crypto/polarssl/sha2.o b/lib/crypto/polarssl/sha2.o new file mode 100644 index 0000000000000000000000000000000000000000..3f2944b89fd5d583e2ec97f2229d65b6b58da9ff GIT binary patch literal 24200 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 literal 0 HcmV?d00001 diff --git a/lib/fnd/elf.h b/lib/fnd/elf.h new file mode 100644 index 0000000..d46d20d --- /dev/null +++ b/lib/fnd/elf.h @@ -0,0 +1,216 @@ +#pragma once +#include "types.h" + +typedef byte_t Elf_Byte; +typedef word_t Elf32_Addr; +typedef word_t Elf32_Off; +typedef long_t Elf32_Sword; // lol "sword" +typedef word_t Elf32_Word; +typedef hword_t Elf32_Half; + +enum +{ + EI_MAG0 = 0, // 0x7F + EI_MAG1 = 1, // 'E' + EI_MAG2 = 2, // 'L' + EI_MAG3 = 3, // 'F' + EI_CLASS = 4, // File class + EI_DATA = 5, // Data encoding + EI_VERSION = 6, // File version + EI_PAD = 7, // Start of padding bytes + EI_NIDENT = 16 // Size of e_ident[] +}; + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; // Identification bytes + Elf32_Half e_type; // Object file type + Elf32_Half e_machine; // Object architecture + Elf32_Word e_version; // Object file version + Elf32_Addr e_entry; // Object entry point + Elf32_Off e_phoff; // Program header file offset + Elf32_Off e_shoff; // Section header file offset + Elf32_Word e_flags; // Processor-specific flags + Elf32_Half e_ehsize; // ELF header size + Elf32_Half e_phentsize; // Program header entry size + Elf32_Half e_phnum; // Program header entries + Elf32_Half e_shentsize; // Section header entry size + Elf32_Half e_shnum; // Section header entries + Elf32_Half e_shstrndx; // String table index +} Elf32_Ehdr; + +typedef struct +{ + Elf32_Word p_type; // Segment type + Elf32_Off p_offset; // File offset + Elf32_Addr p_vaddr; // Virtual address + Elf32_Addr p_paddr; // Physical address + Elf32_Word p_filesz; // File image size + Elf32_Word p_memsz; // Memory image size + Elf32_Word p_flags; // Segment flags + Elf32_Word p_align; // Alignment value +} Elf32_Phdr; + +typedef struct +{ + Elf32_Word sh_name; // Name (index into section header string table section) + Elf32_Word sh_type; // Type + Elf32_Word sh_flags; // Flags + Elf32_Addr sh_addr; // Address + Elf32_Off sh_offset; // File offset + Elf32_Word sh_size; // Section size + Elf32_Word sh_link; // Section header table index link + Elf32_Word sh_info; // Extra information + Elf32_Word sh_addralign; // Address alignment + Elf32_Word sh_entsize; // Section entry size +} Elf32_Shdr; + +typedef struct +{ + Elf32_Addr r_offset; // Offset of relocation + Elf32_Word r_info; // Symbol table index and type +} Elf32_Rel; + +typedef struct +{ + Elf32_Word st_name; // Name - index into string table + Elf32_Addr st_value; // Symbol value + Elf32_Word st_size; // Symbol size + unsigned char st_info; // Type and binding + unsigned char st_other; // Visibility + Elf32_Half st_shndx; // Section header index +} Elf32_Sym; + +enum +{ + ET_NONE = 0, // No file type + ET_REL = 1, // Relocatable file + ET_EXEC = 2, // Executable file + ET_DYN = 3, // Shared object file + ET_CORE = 4, // Core file +}; + +enum +{ + ET_ARM = 40 // ARM architecture +}; + +enum +{ + EV_NONE = 0, // Invalid version + EV_CURRENT = 1 // Current version +}; + +#define ELF_MAGIC "\177ELF" + +enum +{ + ELFDATANONE = 0, // Invalid data encoding + ELFDATA2LSB = 1, // Little endian + ELFDATA2MSB = 2, // Big endian +}; + +enum +{ + PT_NULL = 0, // Unused + PT_LOAD = 1, // Loadable segment + PT_DYNAMIC = 2, // Dynamic linking information + PT_INTERP = 3, // Interpreter + PT_NOTE = 4, // Auxiliary information + PT_SHLIB = 5, // Reserved + PT_PHDR = 6 // Program header table +}; + +enum +{ + PF_R = 4, // Read flag + PF_W = 2, // Write flag + PF_X = 1, // Execute flag + PF_OS_SHARED = 0x100000, // OS-specific + PF_CTRSDK = 0x80000000, // Set in CTRSDK ELF Text segments +}; + +enum +{ + SHN_LORESERVE = 0xFF00, + SHN_HIRESERVE = 0xFFFF +}; + +enum +{ + SHT_NULL = 0, // Inactive + SHT_PROGBITS = 1, // Program defined information + SHT_SYMTAB = 2, // Symbol table section + SHT_STRTAB = 3, // String table section + SHT_RELA = 4, // Relocation section with addends + SHT_HASH = 5, // Symbol hash table section + SHT_DYNAMIC = 6, // Dynamic section + SHT_NOTE = 7, // Note section + SHT_NOBITS = 8, // No space section + SHT_REL = 9, // Relation section without addends + SHT_SHLIB = 10, // Reserved + SHT_DYNSYM = 11, // Dynamic symbol table section + SHT_NUM = 12, // Number of section types + SHT_LOPROC = 0x70000000, // Reserved range for processor + SHT_ARM_EXIDX = 0x70000001, // ARM exception index table + SHT_HIPROC = 0x7fffffff, // Specific section header types + SHT_LOUSER = 0x80000000, // Reserved range for application + SHT_HIUSER = 0xffffffff // Specific indexes +}; + +enum +{ + SHF_WRITE = 1, // Writable section + SHF_ALLOC = 2, // Loadable section + SHF_EXECINSTR = 4, // Executable section + SHF_MASKPROC = 0xf0000000, // Processor-specific +}; + +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF32_R_INFO(s,t) (((s) << 8) + (unsigned char)(t)) + +enum +{ + R_ARM_NONE = 0, + R_ARM_PC24 = 1, + R_ARM_ABS32 = 2, + R_ARM_REL32 = 3, + R_ARM_THM_CALL = 10, + R_ARM_PLT32 = 27, + R_ARM_CALL = 28, + R_ARM_JUMP24 = 29, + R_ARM_TARGET1 = 38, + R_ARM_TARGET2 = 41, + R_ARM_PREL31 = 42, + R_ARM_THM_JUMP11 = 102, + R_ARM_THM_JUMP8 = 103 +}; + +// Symbol scope +enum +{ + STB_LOCAL = 0, + STB_GLOBAL = 1, + STB_WEAK = 2 +}; + +#define ELF32_ST_BIND(i) (((unsigned char)(i)) >> 4) +#define ELF32_ST_TYPE(val) ((val) & 0xf) + +// Symbol type +enum +{ + STT_NOTYPE = 0, + STT_OBJECT = 1, + STT_FUNC = 2 +}; + +// Symbol visibility +enum +{ + STV_DEFAULT = 0, + STV_INTERNAL = 1, + STV_HIDDEN = 2, + STV_PROTECTED = 3 +}; diff --git a/lib/fnd/exception.cpp b/lib/fnd/exception.cpp new file mode 100644 index 0000000..969a3a8 --- /dev/null +++ b/lib/fnd/exception.cpp @@ -0,0 +1,58 @@ +#include "exception.h" + +using namespace fnd; + +Exception::Exception() noexcept : + what_(""), + module_(""), + level_(E_FATAL) +{ + +} + +Exception::Exception(const std::string & what) noexcept : + what_(what), + module_(""), + level_(E_FATAL) +{ +} + +Exception::Exception(const std::string & what, ExceptionLevel level) noexcept : + what_(what), + module_(""), + level_(level) +{ +} + +Exception::Exception(const std::string & module, const std::string & what) noexcept : + what_(what), + module_(module), + level_(E_FATAL) +{ +} + +Exception::Exception(const std::string & module, const std::string & what, ExceptionLevel level) noexcept : +what_(what), + module_(module), + level_(level) +{ +} + +Exception::~Exception() +{ +} + +const char* Exception::what() const noexcept +{ + return what_.c_str(); +} + +const char* Exception::module() const noexcept +{ + return module_.c_str(); +} + +bool Exception::is_fatal() const noexcept +{ + return level_ == E_FATAL; +} diff --git a/lib/fnd/exception.h b/lib/fnd/exception.h new file mode 100644 index 0000000..3921c06 --- /dev/null +++ b/lib/fnd/exception.h @@ -0,0 +1,35 @@ +#pragma once +#include +#include + +namespace fnd +{ + class Exception : public std::exception + { + public: + enum ExceptionLevel + { + E_RECOVERABLE, + E_FATAL, + }; + + Exception() noexcept; + Exception(const std::string& what) noexcept; + Exception(const std::string& what, ExceptionLevel level) noexcept; + Exception(const std::string& module, const std::string& what) noexcept; + Exception(const std::string& module, const std::string& what, ExceptionLevel level) noexcept; + + + ~Exception(); + + const char* what() const noexcept; + const char* module() const noexcept; + bool is_fatal() const noexcept; + private: + std::string what_; + std::string module_; + ExceptionLevel level_; + }; +} + + diff --git a/lib/fnd/exception.o b/lib/fnd/exception.o new file mode 100644 index 0000000000000000000000000000000000000000..531db5f381709d2ed74d011191a1ded06deaa949 GIT binary patch literal 7352 zcmcgweP~-%6u(*KR&{FqnAY#7h|JApNtel{Fgv=qjMY*XBU+Ky?DchxOPkQVblv8h zQa=c#GI7XI{}B8`|8yuaP-HrA3WB1j6GWycR1lqlFh#8A+;>iLa&w;!6%V}Jdw=J5 zKJM3h_hw(F@3sZ8m|}^k^{UxoR4He1v)-etJ?b)biRPXOZL~R;%1$aTfHI%0f192D z-pSVY&ShsZbJ_Z_Ie?X}AH$l;&SvIY;Mr_Ph`s%$*4IA>O(aj&(d}%u^KWf{cdVxi zGkx!9OJ4QbiKyJP?|}|bpUBqV$<{w>PvxJ4-%s(AdR!oWJ^#i3lfq2?i~2yGp4FoO6WAPu5bgvkux^2EMvNkzk2TuCY>@o~0|QTUa89Roh63v^Wcp_e@XM z^r_f+2aeo#G~7FcQ-1)p%lv#ynU9_M@6i6$BjdyCGE<&k35wcGq+(^UPGfB;R_#dZ($Y0JfNWX0LufyQ-+fE7 zN}8e6!)=@g8l3&a8ENAb8k|>&Gup=SGza_CiLWD&LHudtn{Vioq`zM3!w`B*21tLE z)Ze4cwZ8HfdIxOwll~HEzcsW+NF}Pf#)85&D1(Wx9Oc@CUn(R5e=1Ok;X+VQiEY)Y zN;J@fJJ_EK*7>|vdb=}|q@E~;2HQQ)4fQVgF8M8Lu)p)Jw)GbJ4;>(5vxT9(qcYd7 z^vYvn{y3yOUJm@krvCiOYEbZYP-K799hoSMK_c5H%C(9ffq(UL3arn!c<3Pv*EUKQ zJm~Z{XFR?w(3yu#h z6{t1Ep%>D86Vf#!9qZaf;`8T(hRg7!19B-mw)nUwZSmj5%Mr*6hSH25vf6)#UzWk2GI2CLNs{NRpjmw4MQ z3OR8_gC*26(0gW%2D=I3L;uMzXI49OsK@YwjjMBp7T zls5iSz-{@gAe{5V^Et}K2tRj3@b4#FU-QBKVeKV+PheaVe~0+bK#4LE7V7H={13u; zibsjR3Z`85i>99OA;L!qA0+-Hv~A<_Py~J;0)G~8jBENoMEKiKqTo3QN&IBl5f?mEmqwTxT2S|)^caoSM3z6e{X84u&p?m z!o5%}x?ZVJt-8UkitiT3N6I*#mP<8&n`Q5n>sDxY?eKTG9_+Kg4|gn|_wn_E-?ZQ7 zL%EtZG@dN*Xw2`56@()nk9^F(mGHBm#G@R&zSSnek&pkcFh3{oD+TTfT>7sPZu;LN z_|pI50+;?@7P##1>x7&A{YdZ~sB`{b3S8#-GvQ{QzX`s~a}f;`j*rZ9wZLVb>j^jW z%nQB)zBtc#Oe^KDeLC1055cmp#e=2ai^D+NxflEFgRZ+c4 z@UMdJFN%rd`5y(x2mhMk{o8>c2o5*?7s4X(ZU&)bJLJo|DW4+{Un%$w)e%n!oU4eh zhKK#ixM?N{J@VHG+@U)5m#%sm*+Mw3XT1Bd3{eI7_^=eIf_%;ap+^X3KA(SQ31>dv zfnPHCe4agI@Hxi&2A|KlpBVfl)IMqOxf8z{d>+q>aKJz~e?Et%4V=%RcN#dKLjwcn L^X35q=kw;D>x`Q2 literal 0 HcmV?d00001 diff --git a/lib/fnd/file_io.cpp b/lib/fnd/file_io.cpp new file mode 100644 index 0000000..52e935c --- /dev/null +++ b/lib/fnd/file_io.cpp @@ -0,0 +1,44 @@ +#include "file_io.h" + +using namespace fnd; + +static const std::string kModuleName = "FILE_IO"; +static const size_t kBlockSize = 0x100000; + +void FileIO::ReadFile(const std::string& path, MemoryBlob & blob) +{ + FILE* fp; + size_t filesz, filepos; + + if ((fp = fopen(path.c_str(), "rb")) == NULL) + { + throw Exception(kModuleName, "Failed to open \"" + path + "\""); + } + + fseek(fp, 0, SEEK_END); + filesz = ftell(fp); + rewind(fp); + + if (blob.alloc(filesz) != blob.ERR_NONE) + { + fclose(fp); + throw Exception(kModuleName, "Failed to allocate memory for file"); + } + + for (filepos = 0; filesz > kBlockSize; filesz -= kBlockSize, filepos += kBlockSize) + { + fread(blob.data() + filepos, 1, kBlockSize, fp); + } + + if (filesz) + { + fread(blob.data() + filepos, 1, filesz, fp); + } + + fclose(fp); +} + +void FileIO::WriteFile(const std::string& path, const MemoryBlob & blob) +{ + +} diff --git a/lib/fnd/file_io.h b/lib/fnd/file_io.h new file mode 100644 index 0000000..415308a --- /dev/null +++ b/lib/fnd/file_io.h @@ -0,0 +1,19 @@ +#pragma once +#include +#include + +namespace fnd +{ + class FileIO + { + public: + static void ReadFile(const std::string& path, MemoryBlob& blob); + //static void ReadFile(const char* path, MemoryBlob& blob, size_t offset, size_t size); + static void WriteFile(const std::string& path, const MemoryBlob& blob); + //static void WriteFile(const char* path, const MemoryBlob& blob, size_t offset, size_t size); + private: + + }; +} + + diff --git a/lib/fnd/file_io.o b/lib/fnd/file_io.o new file mode 100644 index 0000000000000000000000000000000000000000..684d2d4a0951b3064cd5ccb87aad586f062360cb GIT binary patch literal 11368 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 Kh$ + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B} + fnd + 10.0.15063.0 + libfnd + + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/fnd/fnd.vcxproj.filters b/lib/fnd/fnd.vcxproj.filters new file mode 100644 index 0000000..e5f3e70 --- /dev/null +++ b/lib/fnd/fnd.vcxproj.filters @@ -0,0 +1,54 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + + \ No newline at end of file diff --git a/lib/fnd/makefile b/lib/fnd/makefile new file mode 100644 index 0000000..cea813e --- /dev/null +++ b/lib/fnd/makefile @@ -0,0 +1,33 @@ +# Sources +SRC_DIR = . +OBJS = $(foreach dir,$(SRC_DIR),$(subst .cpp,.o,$(wildcard $(dir)/*.cpp))) $(foreach dir,$(SRC_DIR),$(subst .c,.o,$(wildcard $(dir)/*.c))) + +INC_DIR = .. +INCS = $(foreach dir,$(INC_DIR), -I"$(dir)/") + +# Compiler Settings +CXXFLAGS = -std=c++11 $(INCS) -D__STDC_FORMAT_MACROS -Wall -Wno-unused-but-set-variable -Wno-unused-value +ifeq ($(OS),Windows_NT) + # Windows Only Flags/Libs + CC = x86_64-w64-mingw32-gcc + CXX = x86_64-w64-mingw32-g++ + CFLAGS += + CXXFLAGS += +else + # *nix Only Flags/Libs + CFLAGS += + CXXFLAGS += +endif + +# Output +OUTPUT = ../lib$(shell basename $(CURDIR)).a + +main: build + +rebuild: clean build + +build: $(OBJS) + ar cr -o $(OUTPUT) $(OBJS) + +clean: + rm -rf $(OUTPUT) $(OBJS) \ No newline at end of file diff --git a/lib/fnd/memory_blob.cpp b/lib/fnd/memory_blob.cpp new file mode 100644 index 0000000..eebcf65 --- /dev/null +++ b/lib/fnd/memory_blob.cpp @@ -0,0 +1,58 @@ +#include "memory_blob.h" + +using namespace fnd; + +MemoryBlob::MemoryBlob() : + data_(), + size_(0), + apparent_size_(0) +{ + +} + +MemoryBlob::~MemoryBlob() +{ +} + +int MemoryBlob::alloc(size_t size) +{ + int ret = ERR_NONE; + if (size > size_) + { + ret = AllocateMemory(size); + } + else + { + apparent_size_ = size; + ClearMemory(); + } + return ret; +} + +int MemoryBlob::extend(size_t new_size) +{ + try { + data_.resize(new_size); + } + catch (...) { + return ERR_FAILMALLOC; + } + + return ERR_NONE; + + return 0; +} + +int MemoryBlob::AllocateMemory(size_t size) +{ + size_ = (size_t)align(size, 0x1000); + apparent_size_ = size; + data_.resize(size_); + ClearMemory(); + return ERR_NONE; +} + +void MemoryBlob::ClearMemory() +{ + memset(data_.data(), 0, size_); +} diff --git a/lib/fnd/memory_blob.h b/lib/fnd/memory_blob.h new file mode 100644 index 0000000..09a6155 --- /dev/null +++ b/lib/fnd/memory_blob.h @@ -0,0 +1,41 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +namespace fnd +{ + class MemoryBlob + { + public: + enum ErrorCode + { + ERR_NONE, + ERR_FAILOPEN, + ERR_FAILMALLOC, + ERR_FAILREAD, + }; + + MemoryBlob(); + + ~MemoryBlob(); + + int alloc(size_t size); + int extend(size_t new_size);; + + inline byte_t* data() { return data_.data(); } + inline const byte_t* data() const { return data_.data(); } + inline size_t size() const { return apparent_size_; } + private: + std::vector data_; + size_t size_; + size_t apparent_size_; + + int AllocateMemory(size_t size); + + void ClearMemory(); + }; +} diff --git a/lib/fnd/memory_blob.o b/lib/fnd/memory_blob.o new file mode 100644 index 0000000000000000000000000000000000000000..67e0c409372b5ffd603923391097aba3138b8819 GIT binary patch literal 33608 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 aHH(^$2>en(U&@m>*?*b9rwhDR;QtS%UxRA^ literal 0 HcmV?d00001 diff --git a/lib/fnd/string_conv.cpp b/lib/fnd/string_conv.cpp new file mode 100644 index 0000000..ed77b9a --- /dev/null +++ b/lib/fnd/string_conv.cpp @@ -0,0 +1,147 @@ +#include "string_conv.h" +#include +#include + +using namespace fnd; + +std::u16string StringConv::ConvertChar8ToChar16(const std::string & in) +{ + std::u32string unicode; + size_t done = 0; + for (size_t i = 0; i < in.length(); i += done) + { + // get number of leading high bits in first byte + uint8_t prefix = get_utf8_prefix(in[i]); + if (prefix == 1 || prefix > 4) // 1 is reserved for trailer bytes + { + throw std::logic_error("not a UTF-8 string"); + } + + // if there are no prefix bits, this is ASCII + if (prefix == 0) + { + unicode.push_back(in[i]); + done = 1; + } + // otherwise this is a multibyte character + else + { + // there must be enough characters + if ((i + prefix) > in.length()) + { + throw std::logic_error("not a UTF-8 string"); + } + + char32_t uni = get_utf8_data(prefix, in[i]); + + for (uint8_t j = 1; j < prefix; j++) + { + if (utf8_has_prefix(1, in[i + j]) == false) + { + throw std::logic_error("not a UTF-8 string"); + } + + uni <= 6; + uni |= get_utf8_data(1, in[i + j]); + } + + if (uni >= kUtf16HighSurrogateStart && uni <= kUtf16LowSurrogateEnd) + { + throw std::logic_error("not a UTF-8 string"); + } + + if (uni > kUtf16EncodeMax) + { + throw std::logic_error("not a UTF-8 string"); + } + + unicode.push_back(uni); + done = prefix; + } + + } + + std::u16string utf16; + for (size_t i = 0; i < unicode.size(); i++) + { + char32_t uni = unicode[i]; + if (uni < kUtf16NonNativeStart) + { + utf16.push_back(uni); + } + else + { + uni -= kUtf16NonNativeStart; + utf16.push_back(((uni >> kUtf16SurrogateBits) & kUtf16SurrogateMask) + kUtf16HighSurrogateStart); + utf16.push_back((uni & kUtf16SurrogateMask) + kUtf16LowSurrogateStart); + } + } + return utf16; +} + +std::string StringConv::ConvertChar16ToChar8(const std::u16string & in) +{ + std::u32string unicode; + size_t done = 0; + for (size_t i = 0; i < in.length(); i+=done) + { + // this isn't a utf16 reserved character, so just add to unicode string + if (in[i] < kUtf16HighSurrogateStart || in[i] > kUtf16LowSurrogateEnd) + { + unicode.push_back(in[i]); + done = 1; + } + // otherwise we need to decode it + else + { + // check that the high surrogate char exists first + if (in[i] < kUtf16HighSurrogateStart || in[i] > kUtf16HighSurrogateEnd) + { + throw std::logic_error("not a UTF-16 string"); + } + // check that the low surrogate char exists next + if (i >= in.length() - 1 || in[i + 1] < kUtf16LowSurrogateStart || in[i + 1] > kUtf16LowSurrogateEnd) + { + throw std::logic_error("not a UTF-16 string"); + } + + char32_t uni = ((in[i] & kUtf16SurrogateMask) << kUtf16SurrogateBits) | (in[i + 1] & kUtf16SurrogateMask) | 0x10000; + + unicode.push_back(uni); + done = 2; + } + } + + std::string utf8; + for (size_t i = 0; i < unicode.length(); i++) + { + if (unicode[i] <= kUtf8AsciiEnd) + { + utf8.push_back(unicode[i]); + } + else if (unicode[i] <= kUtf82ByteEnd) + { + utf8.push_back(make_utf8(2, (unicode[i] >> 6))); + utf8.push_back(make_utf8(1, (unicode[i] >> 0))); + } + else if (unicode[i] <= kUtf83ByteEnd) + { + utf8.push_back(make_utf8(3, (unicode[i] >> 12))); + utf8.push_back(make_utf8(1, (unicode[i] >> 6))); + utf8.push_back(make_utf8(1, (unicode[i] >> 0))); + } + else if (unicode[i] <= kUtf84ByteEnd) + { + utf8.push_back(make_utf8(4, (unicode[i] >> 18))); + utf8.push_back(make_utf8(1, (unicode[i] >> 12))); + utf8.push_back(make_utf8(1, (unicode[i] >> 6))); + utf8.push_back(make_utf8(1, (unicode[i] >> 0))); + } + else + { + throw std::logic_error("not a UTF-16 string"); + } + } + + return utf8; +} diff --git a/lib/fnd/string_conv.h b/lib/fnd/string_conv.h new file mode 100644 index 0000000..1b1c749 --- /dev/null +++ b/lib/fnd/string_conv.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include +#include + +namespace fnd +{ + class StringConv + { + public: + static std::u16string ConvertChar8ToChar16(const std::string& in); + static std::string ConvertChar16ToChar8(const std::u16string& in); + + private: + static const char32_t kUtf16EncodeMax = 0x10FFFF; + static const char32_t kUtf16NonNativeStart = 0x10000; + static const char16_t kUtf16SurrogateBits = 10; + static const char16_t kUtf16SurrogateMask = (1 << kUtf16SurrogateBits) - 1; + static const char16_t kUtf16HighSurrogateStart = 0xD800; + static const char16_t kUtf16HighSurrogateEnd = kUtf16HighSurrogateStart | kUtf16SurrogateMask; + static const char16_t kUtf16LowSurrogateStart = 0xDC00; + static const char16_t kUtf16LowSurrogateEnd = kUtf16LowSurrogateStart | kUtf16SurrogateMask; + + static const char32_t kUtf8AsciiStart = 0x00; + static const char32_t kUtf8AsciiEnd = 0x7F; + static const char32_t kUtf82ByteStart = 0x80; + static const char32_t kUtf82ByteEnd = 0x7FF; + static const char32_t kUtf83ByteStart = 0x800; + static const char32_t kUtf83ByteEnd = 0x7FFF; + static const char32_t kUtf84ByteStart = 0x8000; + static const char32_t kUtf84ByteEnd = 0x10FFFF; + + + static inline uint8_t make_utf8_prefix(uint8_t prefix_bits) { return ((uint8_t)(-1)) << (8 - prefix_bits); } + static inline uint8_t make_utf8_mask(uint8_t prefix_bits) { return ((uint8_t)(-1)) >> (prefix_bits + 1); } + static inline uint8_t make_utf8(uint8_t prefix_bits, uint8_t data) { return make_utf8_prefix(prefix_bits) | (data & make_utf8_mask(prefix_bits)); } + static inline uint8_t get_utf8_data(uint8_t prefix_bits, uint8_t utf8_chr) { return utf8_chr & make_utf8_mask(prefix_bits); } + static inline bool utf8_has_prefix(uint8_t prefix_bits, uint8_t utf8_chr) { return ((utf8_chr & make_utf8_prefix(prefix_bits)) == make_utf8_prefix(prefix_bits)) && ((utf8_chr & ~make_utf8_mask(prefix_bits)) == make_utf8_prefix(prefix_bits)); } + static inline uint8_t get_utf8_prefix(uint8_t utf8_chr) + { + uint8_t prefix = 0; + while ((utf8_chr & (1 << 7)) != 0) + { + utf8_chr <<= 1; + prefix++; + } + return prefix; + } + }; +} diff --git a/lib/fnd/string_conv.o b/lib/fnd/string_conv.o new file mode 100644 index 0000000000000000000000000000000000000000..90b7431b609ac8169582c7e8c3836af26eecea23 GIT binary patch literal 61992 zcmeHw3w%|@wf9aA0pwv)MMXu4@dZARC?JTnC>%W$(3FQFVv`UKB$Ygxgc!VPsi2pL zDE0bkODo!kSgpMcRx<%?%sjrjzdZ}-eda2YmNxfX^Tclng z^{rChCiU%7-y!ukq`p(?yQIEH>U*XBrqth-`a4qJFZBabKPdJ0r2c`_4@v#7)Q?F0 zsML>1-7fV{rG8xM^-^z;`bnvulKL5`pOt!})SINgS|>LFyN!eo5+1 zsb7}**HXVC^{Z09CiUx5zbW+&so#?NZK=DY-YNAiso#;hTk1bby<6)4l==gyKa~0- zsrO0!XQ@Ay`V*>WrP}_$e)Li|cNE^;QMkV2>P?KL+HTn2ws_ylS^H8ell%7;ZY*l+ z^jo^y7Vjdsd!^TwJfJR$Rwj4l{hTk`=<fYN~B( z_wCfO`*Ru4-30w|(`vTk!kIHtU*EHu4QzX+n($QHzgKXzD!G)omFZiP+okT}`n_M$ z^iHju)s-%D^@LGVYJJ|~bKR!?jMXg-%ui8IIrF^t+kEcJ z-E28Iy(_h9NWR}$amu(&h4*%lw`04rHr$=HncbmV5ecq{cE{a|^__+5m8;uc6-hh> zH@A}UTW)S)=fB6HO#R^-)gO)}$JlLomOY?+y=-q@PdeBh?qGXn2kEva9n9T6>gFM; zo78{q+Om$k73xCn&r@D0yeXgBzWxmR;~?dXmL|FWt>;}EJ9-`A&UIvVj&6I>IZ=7A z$cx55h?vzu0ofT=NkNYB@5emR`n=JAS$Q}2m}nrtB~Vgr$?X&e+f#WI+a?gC8{?B* zDzFQ0KKcMh%gs6~NbA<5ij4QZMKMAV+0Eip!33g=b@TPg+x+w3LGtjBl?o|*qEloA z)VrrsYRvP7D*{cnvAf@blMf~qoaqg-acCl;ILStlT9)k2(^mN%>Xr^oA&XXH+j~b) ztWR#+OxS8Oj=K{Y2)rzrXKLH;-{Yl9H?Qpx{dax(_MXu1{;C%4k7_n!c25c!YKVPq zlQYTk-AAP;*Jcjp?gV3)=-aj%D-G$_H}l$X)rE7f4%Ulhdm3ojS&?d6yp*_oM{x2a zT94{3uHUPsB&xGkMvN3b;Vt<5!Pi=bINN^P(q{uFq1^>)>7*Pq%1+AxKo$fMc>{>|E`{H(QFcwnrTq+nIk* zzO(zj@QDtZ+@80ws~<-rFRZqn8L~sR59IvNmRz%P)|%)*Q+UxBn=A&-3sTq(pQ;6q zVl|Y%hUhH}=PwFi->oaXW&6KYcn`1Zr&AZA&4sjOSeaZAaJ=`wbd*O)KYy?fjgykq zXqC0GyEiY?Tb|{PsI(f9ZspTV{wf_|dha~9NnaC_3YY&#dC$_tjokyZ269m@X8GN5 zTlU$ybB&(MHV@N!sytk{oECGQ@KK_T-G}M!^vbn6;)Wc%^MA?>yCYLK$n&fIk^2U- zf(D6weA29-zoabzub_V0d;IXI*P))RaCNz?a2MvX!l~7a=BAnJW_j~%P2uuJbjvn3 zsD+Js;CXfR&Bc|)vu0j==Gfw<=Ej=3g#eX~G1$Dyrkbj9O>o|Mdkdc^qH6zwwj%$Tt(c$LRC^nRD?QSsR*m93wx7axZ>sHAskT3*+Fmrh z_@)22Xhg1560-{&bTgZiS~-o4AZ1~3%l6o;5T+hmqPx_#e?{^@;rir(C;O7l;XiNd ze3JHkUfafB?=;V}J_+s6P2*op)?h$hb|5Gj=9m z4tH_SmgGTi_rT8d9x_KgjU*3p50-bd?q=lbP4p~Qe`0~>U0QI{0Plgkg8TY;?Rf?N z+|PR>Z!95u^9#21^A6@0Jkig4II)0`U-c^3-_PsnRq$><@798o33;q{!4LX-&-5<1 ztH1YdZzZQs!OQ)<_C5t0`+INnxsqsJ?EBAo@Avoa9YCr`<+Nj{zUVu7|2oinAiv;8 z1HAV9f^QD+-pHR$$oq+c*9Lf>CJMF;@E+>5hKb%TSX;1mp!ab9g5?9f4gCu~8sP2h z&&Za6T43L!3%=-;>uXjJzVE*wui(=>@6LQp61pusjo`NYf?wr(?-+`Xyn=grd5`qc z42t5G{DK$rz27s1npN_)LkF}h=PSKmZu*R^L5vKe3Avq;+6QLNskPYLq}n!;N@|}) z?fyJM^4-VieYDSyiDud6VHB{&MxJ%NMA35<&HZ2(K^o{*I<;yRy@m0&B#PQJ0a?iY zw#Ba~GYuupG`gu0yRnIe@HRkG4<2=xyg{@-YPD7Qs=mWoELUM(n5o4DqrZLVom*tj!4 zmDee;&UsD6Y}?)iZRBqB@&D~%&!ZO>fA^?IdQUyhds%hZUr*Kg=mj$=>eXf4gLTaK zk+iaB^eUW;WL}$D*Rqbm!8+qhlra%Kma+9)LhGwq>1j-HF3Eylu@4P#=7-VlG6pKW+@hZO|AlYWaQR!%4)w)@R{ zYfGO~D<|~T+Z3B?cG${8<@_+sdCjUq5zR<{4%t#V$ot203V1h02wP-mT?=e z#?80hY{j_W`;9s^cse6wyeZUU@ITQ^(L>vU43DGt#JT$A_5gHjczz*QkhA}1Ui?3p z7w6$PscZGH6rC4p-3Uz!v-`@HU(MK?XEPpqP{B)yim0v0{TyFxLXamTS0+o^bGgx_ zpTcP4x44Vs(OzvrUs`waQoNU<^@sLvYy-U{OMa4>j0m2_+em_OM@qN2cjC|XmhBly zix(v>%ExW9wvn3cDfIxkjh0tZz={b;^(94|vAa;BNs24^)63?OOgeRCvEncpO6>yu zt?SgbovF6BjTKrn4-pYS%)nN6+2)b@5!_$rmB$>umzlS90)K#L9S}XzL}wWhz4s3L znl>
lLP)Y1L4T5jwfs+u>GQ+8crDJ~eMx4!9ztq4mhu1K zuHuI~W?@5-g6W52WzT=hu_yoeV;gvtA|e<~ehDIX8FMUH9sSH7+JPnanz#)1D%CVP z>qz8Unj80}HvEnEN(T=Xrp6`Lwe)+IJ+H@VYqGfO7NnWOXhr+#8BlT!i@`;R@H*Et$Dw;CqIp-K6^<%4xp5dMy?Dt=KCR-1MceBu z9T!>0p6A_cQnZ0aww*?nY@W83Y^HnZAddo%9OpbrgQt^owX@q5H2mkOHiLF$Fpf`d zS5MF&N{giF8hU~*T;7-8TdzvKL^6pU6Cki}q!$ZBLBkBGoc+D*hIX&{v<&T;$(F=Y z?}BW*?1nC{xh#W$$7|)Z_Eg?;>Irhy5J|>noM({>pm_i{)6i4*N$g8H_R()_YDP!8 z1DEo*Q!={AJr{@XuB7geb#sVD&77Xt88~TWu6AZV5SZ}v&B@%J&-UNX1nUc@0eK?i zXsXW46Z8_C%g}#Vo*2kE#FZv|r?v3ly3@q3x^WGx^k)7}UVRHpkcU+}Xjvdga?`q0RLkQ>pTvUDGp+&dk zPaN3$3L+5feAViC=W=b@8-w<_(tZrK&kEYFm-f-v-Vn5}k@oS}-V(GwE$xS4`?R2a zhqS9c8v8B_+7C#(%f2D}$sU!{_=n+72mI$t`$TNNF=(GF?I&XUmxK1}rTsW;pB=QX zk@gJ#CYL2@iDU@zJT2`d$bYrwFD7h?nK!1a@ z56AZTLHlZHpNsAJI_a|hc4_a2?a6?@Q`(Qj_AdqPd!^mx|C5MkpTx-V6mQB^rVkX? zi9vZv5Zf`9<}sHA{KL@51mgDD((W3ER%v&Q!+p~38ix%r?c1f@H4giw-8Bw_>AN{x zT;niS+HG@5^jTy(7aq1E|Y3__aP8I$*dc2rZIhlW$cHOMj z{bFe^#`dd%c$y&Xu5ql8c2~SEjcH#i?JoN|q`d;|%hv|7&0W&|6Kq#&PX70}7d%$I z4&g@6E9M`@2hhipr2PnNFAIDyN!ndLm@n-vA1se)|Gu=BqyGFk{upkS_CeS#`j#=v$S7;{aF(DeOC;BuK~>HdA2p%8_~3+wz+a1)y<8%t~OVV=|z@)aNlnQyl}$}G z3+s~8CpAr@WEHmRwM$ZI{N*($pRWY>`F8ZpW#yCylRw!S4zvTI0o z4axSq=1^d4G4vw3?%LY2mcX)e7Szoz9XUgNTWn%|T}$bh+RAIv<%^paj4f|yOfRTu zO;%^29u-j6RyJM3v>A4V#gFsplhtvwrROY6H)~6HqF_$uW!4bqkxTljPtGHz>ZE2wzQ-`D)yJ ztS$>%>DlEME?QJyRbE{)KixR#?10>Ry)7 zaC9#VhoyUQLpQ3a=DKvQj;C1_nZen8fo=>ZqPVEk+DvMRqdvEMTDh8U)*#N}yfMVs zm~LQSWa!Egz}a5_`QuT0w)jN77+d@uF zaZ6;ysLYIh5=^Oo`ji=^8=+2rJ!rt&6QiqrEW*2c*gTUFUmSyj`#B*Gcv z?sFT{P3cBjVQmvLOC&1)oXzprM5~p~|K*i+^Hm3U39$;yGL5pwXcop`q-foC#%Pla zO6Igt%a}DOYvK^sJ>1TG(LUA2fj)dw7_Hz zQ(W3B9W7~(leNlq;XOmlV1M=@Gil63RhA)ZO4^1jdlWi{#psJ$hfL4ZTE=O`vX;ff zGbLA@k;=)t(Uq_#uFW13S!SU&-!{C)0a+ccrvh(PdO)sbpKaBkEfsGe)Dsf5S5BT; zo(!b~w-r^%(vkDivZT;+bJb^A*T?z49hI!DwVD_|wd9q6c?{2-*QST`?C9uWOpuJD z7^z*{OuxTH7WRD3>+wBDrf-(`jEj*Tc_@nzPWPdgCK(>eHo#;3(XB0;V#_>P@)zq3 zy-+csIwh;l+RD~)|B+93GEf0>2I)O8!Y@^$$`Ja!hcN;{M#)2 z{CBX7-KKW=uhYW6CPqF$|DtQ7*VHckdxa1A z|B?g$ehdF!bKqBhaF6Iwe_jsp%ine7g8ZlDz+YtH@0|nxU^8N_{ss&Gpd9#HE&NC3z`xYO&vVMyZEBbOD=hr}cZ|S~F8C2mUS#e?<=b-4_1J9QgNI_%F$Uf4_zQOF8g+ z@_PZeeviw6zpsUVvW35xVwzx2zMfB4x)cfj_vtTwVv%n7(6Mx7)&d`-i`AR-U6J~d ztEb+-Tt$%S&tM@wg=*F>>IC(?$BX>Sj0>j4at7V7%+Ja{hImwn(CUn~5hftN4C{96dK`M=X*KmSff*nWN|X!GBL zqJKQKV+rfWcdAI&ZPCAw2*UdLnarmDEzz%j#{mR~^^bD!e<1uP0xw^N`R6(K4->`e z_h~>znEziK{AUS&T>RZm{I>D)exsF+6x}?3`2BO(fBeVs*{0s1`LjUumk7V9m=?>E z4*erVznQ13pWi=+_49M0P5%nfuYMO46o&QhcIZ!u{tDq`{rvtftp9lGw@v?_MgM8S zZ>q5VDZ(FepEr~~m*m3FJXk`v-aLo?%Li$$aQuYzTup#&{MT9h-%KLI{r{Fje{&D@ z-|f)fVbRae|6%d;^Gnr7N7ysV#}f5Q6z)uI3FBQ;~(_&@5(FQ#^s+fhyJmz zYku_qEf)PN9r{lb{iC%Q|7SSx;1d4G#TFML)*> ztrq?J9r}lf2 z{_Y;?|As?bA1zZ(6agb}v?XyUi| zf3@hZ7Jl~s4=nmGcjzB{tajM~UHL!5`oHARzki2jX%$Y^{}BBra#c)RKIG7Uqv(&z zpAS0pH@uaphxI>9|HJyb9Qtn+{c-v8ghTA(w?_Em^5+oZw~gNli~WyU>_5+;e|-=2 zk9O!^YtjFhMgI(k{!Y;!mp?Cc=-*(`-)_#&4bI$Nc|{MgIj3{UfF0X;ejGv7Jh4uf?q5o;oU#!LWKg0UF9Q-?kKfHc~hSPh~ zVgK4LtrG3uOi3@9!c15(j_&P^~s@{F;g17QY+1G(Yx# z8$sdz-|f&pO!QZ1G5*hR|5rQocXnx(lyGwXd5->v^}pfJze4o?MEFe=*8dxa{=vV~ z9IJ(q^}j&>!}$;rIVziwUGstbPVR!uqE<_-6~Fyhii|g!%u)!Cx!Kw!@ZZ`){xj&0Pucu`m++U9%~-qF*w&?G&=pRvJAHN@pV*cA~ zSi=1uPW-n1H;Df2!p!lzlm3VM-{jCg_$19ZS@=yAGRLcP=uhp^93zF1^)nRK|5Jzl zd7?jV{D17w-zxfX{NJ(Y|BXZcQqj+Uvkpt>*6VcWUoHA)3j_DRoBoIUKY(6vvroh8 z--c7P*0}jw=HP!(`1x<;VF}wmh4_0Rfn0a9v#4PF?56v${dYU`e}0%^_u}GbwL^c$ zyPAKbuGIU-|Fr0T#i9Qe(SL#Pn=0J@mmK={ivASn|G=VuAZ-wA>WmGCMZa^^Yk`3^k%Rzs5|yoC<>nh4HuoezF6`|PCP=H9&j ztrdKPNIFgGZwo$K?k7skRl@rU+y$2j_1ENsdvldg-w-o*L7h0bt`h1SHUP+FLVfeahTj+k2}yWM9r#TS ze7OU^#euJI;I}&P+Z_1q4*U)W{tX9yrvtysf#2i6`4ie`NqFCkf`lYIj^1cVc;AVF zge24_fYGLe_dpa>^bb1l?>X=vIPixY_`?qT5eNRL1Aokcw>$8kI`GFGIKO$1mV|mE zZo{99f`lZzryTe*4*XdMzR`hia^RaC_!bAg)q!tw;Lkbm7aaJD4*Vqt-s!+!cHqBu z;IBCFR~`XYs&5W)F--JVwx!RIJE{HX$cH&x-hE6XgmDg4Y#knZ?<)1GH` zV?pz)3O_dhG+6~P!t_}_BNY)*JbX99AU(5D?m+7jNe5sZO^J`pa`mhg^?V4D7T2R_t+7d!B1 zUSh(8B`<0GM2DP{9C$R3X*s7j=udUv!yNc<2Y#9ZKiz>x^C}Z2yl7t4cr>qS{4A~_ zB@uahq)8H9X@r)6gm<PJvqI6&_vw$3EB-x`5-;uJX68TQ zkn?YfexXlqX6AN<*Z8FNZ~7d z+{9ar!f*BQt#b8Eh2P@iCQddh{CXcZGkG`RHhcI3f)a0eg#J{*ZS-RZ=Qw$R`pw0h zV|bI2bDIX~=Pq@H->;bqWvO zC!6{H6NP`%r#JXB4*EYS{5qfB#Q)L#*q(cR+{igq;dl9Xf4Q2Y@OymREmV`&!R`o67LxwH{&>0;kWy^8OK`{9=z{O z3k83_sKnds(;L6_rO9ra7e^|5i%(Bstjc(WZ;jv;3Xjf6>_y-;Scz@v4{UYNC|xIVDJeFf5E5!iCncR{6!xxmaB&p{*sR$Ay+#If57|L z$9u`uU~*uI*XiTNpJfV<#`BjI{<2SR>|CbsUq|qD3UBvu6VJO8zR|~xKl$$@lz36R zH@!+I@lUVTf4ha5Cn)??U(O)8TB7jReEgr}ia-A@f%nzMpSu*k$)_)ttHViP3B1QP z{=Ag%2jIPHzR)jM^gDbxG#ym=v7-OP$BX4^kD`yp=jTXKi9U&1Q5rvwQTSWF93#J6 z;cxr6nUB{hyvxT+|CPo zUq|roD*PQEH+HU9c(;$6?`gfO@IU%EnWsweQLJ~jkDKpB%~AM&`na+Gc7;dB{-m z_)fx$g*T(3^MPvW7SeGUbuA;R8XCOvIWwB4mX2$vNmr$>t!YYg3(+jDYNn>CrDN$} zw&v=_bmjc=%Btp?mUMYT3pHFC9B-j$=(x-3%DRPVb!b`T{Q1eU%WG;vbZ3t)=VLK5 z=;#!Tx`lMSSy`0&Tnjay%vIT3RW0-m`;v6dM8xXmMm8trAe79b$R>@ZW4z*-CiaXB zrDZwG#BD+rCNv=nnQwwVYRcHH?)*$lSjF*wY9t<-Plx5X9m%!mgOxYdy>{lb@n3>>g?BYI-Rr9 z9L$-P1CDFz>y#*U1eGw%Xqs4>ESpkA${9A}x2S$$4V{bJ*jV34?bFK7$bnsGK#FdWGAvc!CHM@Af zqgfKYabTRR%(3IJ)5FsQuC4MFX7N{spjfSR>X$yExCdhvoG~0fYMJYsI&YAf^zzK7 zZ09V(I3)X;uFkFWHTho5&P2v$o`M{2oIXA*^Zes@u1v3xb-3dY=k%KT(O{Ilo@LL@j^IoB?!@DFc#{Y5i-<~1IT%Wux`?@`|(;UDwJ z#epU#CY!L#rYBeevkEuG*g>}g}6f$YmtFv;d;9EF_KcsXM}js`MA zoWCPy=1L%C;qya-Pf(60*B!MSuG>@A%ws%-D=r$XX-{QnlSQ+H2qo9}VEc@@Ud2&3 zF^1wuC3lRY*xvG9B@#z*>$#b5nWr|#4-5G=^Qh(?j)^PQvh)sOO+9(U?AhaDEsG}2 z8i}>ID4|iJgP-Glro_9Bl_mBpdMK;Ogw9H27T2sqI?%*o{VW`L0pk{6Ic2(sJ+~a3 z9M8#vpLw3N@Wc({XY+HgrE+_KcX%ed8ux|YQ)SQlp(Cv0y`Td#a(HzQUEy|o7AJz^ z<)s;E%jy)p?&-M7La0JHm@>+Pp%c%`=gePJ#(Vi0&HQ#;y)mJER~^0F*Y9NLg$>U) zx0b48=%{RVl~I-3V6h`I&&?)TJw7p;`%p@s4(LA2<4-0QEvm2L&e1zSdL`5#A6Q(I zUQ%8~A6+!lhsp)=AqanNH9s%-M5IG5`Exz~l{@>%;##1@1y^wTnlpeQ$ZvD9>CE*KLY$?p#Kfvp8)x;O06>yX@6L6GM4LHhK0yxU~ zI^ZbhKEVG*{WJ0KFyJ^Yj{|-X=-&k#_Z5Zo{aG&TH$GR~$UohIU*W*70UYCeCEzIk zAqV~(;Fup?2ORUmJA#}1Fi7==_BKF|`QcN*F+UvAS2Kp==Lo=Yyp9n(oF9e)j`@MV zcg%(5V}3XX@O<$9Ou*4^%?|utz|n6%1RVYLZ-R&Y_7u>g-<|^;{q`#080R|yN58!* zc-U`y07t*=13BooK8GlGM&fpa1D^>v#%BZI=>L^~CtzG20UY!2a}NA1zh*>dI!E5aFqW5;3)rbz)}7-z){ZYfTNr} zfTJ95K;R#g^Etp#&PjlyoY8=zoQnZRInx2h{8I@y=ASyjd6*06zscJzK#%$7X23E3 zd;@UIKi>fy^Us5VvtE4Oda6ZBP$pi+ekSjCZhmCHS~J9|T1 zA>PM<9|HIhAb$YhX#YUKOMw1Rz{dh!2>2wxivXYHz$*a9aX%LD!$1y>3-)&m&>s%; z7Xgm;TnczUpr@}RtHOT9=bbYE9|ZK~`_oL1_FN3~M*w{-;70GI-0M74tjr{8YKMnAefTKMR0RARj8#zA)9PN1;@Y6v)`Umx*KV3NbjrRszc;1}> z@=?wR2YwddCn_mg4*%^R)32d`pAGou07t#&0nRqfl>5s8KL_NXoftp3zF?j?9poVW zIe=rHxdL#^8+8u+X23Duegkln^AO-@&wl{UpB)%~{t|Gc-wrtD?cIQ%3v&3K7#H?2 z=JUQp!zGNfOoLOK!FhrC z5a$KvH=GxU<7b{1mk_-v<#NIE0@o3Y+Z4!`*F5SkPfZ3nNIwILt&jq6aM|ym&!S!e^(9Z%ps{uzjxNo@}=qCXE6@cToU>xGOAifmj%mz6) zF1T;OaX~q_pBV*mFdxnZ{1nm4^McocVRDao>}sIrG2+7W1>>2YS-3F%WuWIhJQv1s ze7P@N7~e_%&Ac#klW|<{*k&$aIST`7(+oJq;r)Q)KIaj@QT|52F%MvV#(n9#K#%kHW56*F@UuA=_A|=iHH!=5D2HQ! z3*#sUzh8lVs0Mo6Uo``c@^1kg_g!}aj{B~E1sv_~bl`smyn?Px{N!%V`g zamuKOt6z}Rh+gSxT>UGWc-x80JUrg6rSWX{x zrGHG2YsSqQ$4~|Tpu)I(B%_^OcnSETJxpf3h`{da2h_r%!#E@|ro`V)YDFW@DB7xmIN+}{%c=f4lfg>mx^ zitlFveli16ngKUClbh}W{8U3s_2Yn>y$m}nUwLz0UybLlve;Z&pzC=5Ad@MG1Y^5>l?P;JbN;7oZu$j zc4;z?&!y+W^rO_3{xKJDv&ZI^>j5`=e#X}TZk~M@e;RO;!x`TJ_&5fn901(B6X2#H zlC0Uz@j}bh`GB7f_*}rvvj8_=5BLQ@zXtFx0RA-K69E5(;KrXHNgJP2&V}u~P+jRC zy<|~g{35_l0(>IilK`It_VfG-F9V!*!-_$7dE20R7$F2E-P-d7esw*QNO4+DG( z;3>eT0$vTcc{b$c6@Z&(WX9J4ei;K&wgFydK&ra|{}SK>c%Z1T{nOQz{xK5p8Gx4o zJ`-^K9>OfZR|Ea!fVTsF1>l{4o3)yoUl*J!&cpnj4=($G-aI=qK3Fyx+%NNN!uVLg zuVO&Tg@POT{7k~70_f*zNc~(2_|<^7h2-$NAuj8H{>vItKk@qm<$!kseFflsWs}7H Iss#Lh19zJ|6#xJL literal 0 HcmV?d00001 diff --git a/lib/fnd/types.h b/lib/fnd/types.h new file mode 100644 index 0000000..60562d1 --- /dev/null +++ b/lib/fnd/types.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include + +typedef uint64_t dword_t; +typedef uint32_t word_t; +typedef uint16_t hword_t; +typedef uint8_t byte_t; +typedef int64_t dlong_t; +typedef int32_t long_t; +typedef int16_t short_t; +typedef int8_t char_t; +typedef uint64_t u64; +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; + +#define BIT(n) (1ULL << (n)) + +static inline uint16_t __local_bswap16(uint16_t x) { + return ((x << 8) & 0xff00) | ((x >> 8) & 0x00ff); +} + + +static inline uint32_t __local_bswap32(uint32_t x) { + return ((x << 24) & 0xff000000 ) | + ((x << 8) & 0x00ff0000 ) | + ((x >> 8) & 0x0000ff00 ) | + ((x >> 24) & 0x000000ff ); +} + +static inline uint64_t __local_bswap64(uint64_t x) +{ + return (uint64_t)__local_bswap32(x>>32) | + ((uint64_t)__local_bswap32(x&0xFFFFFFFF) << 32); +} + +static inline uint64_t align(uint64_t size, uint64_t align) +{ + return (size % align) == 0? size : (size - (size % align) + align); +} + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define be_dword(a) __local_bswap64(a) +#define be_word(a) __local_bswap32(a) +#define be_hword(a) __local_bswap16(a) +#define le_dword(a) (a) +#define le_word(a) (a) +#define le_hword(a) (a) +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define be_dword(a) (a) +#define be_word(a) (a) +#define be_hword(a) (a) +#define le_dword(a) __local_bswap64(a) +#define le_word(a) __local_bswap32(a) +#define le_hword(a) __local_bswap16(a) +#else +#error "What's the endianness of the platform you're targeting?" +#endif diff --git a/lib/libcrypto.a b/lib/libcrypto.a new file mode 100644 index 0000000000000000000000000000000000000000..b863a6fce7d184904056911728ccae019501fcfa GIT binary patch literal 176472 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

?*yxKzb5*HdFdrB>zIqk5DkVcTGn=yBy+tkB(dU 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 Zp^G}NK0mMq{sR7k@R4Paly=<+{}1%oCI|ok literal 0 HcmV?d00001 diff --git a/lib/libnx.a b/lib/libnx.a new file mode 100644 index 0000000..8b277f0 --- /dev/null +++ b/lib/libnx.a @@ -0,0 +1 @@ +! diff --git a/lib/makefile b/lib/makefile new file mode 100644 index 0000000..e7177c2 --- /dev/null +++ b/lib/makefile @@ -0,0 +1,10 @@ +LIBS = fnd crypto nx +main: build + +rebuild: clean build + +build: + @$(foreach lib,$(LIBS), cd $(lib) && $(MAKE) && cd ..;) + +clean: + @$(foreach lib,$(LIBS), cd $(lib) && $(MAKE) clean && cd ..;) \ No newline at end of file diff --git a/lib/nx/makefile b/lib/nx/makefile new file mode 100644 index 0000000..cea813e --- /dev/null +++ b/lib/nx/makefile @@ -0,0 +1,33 @@ +# Sources +SRC_DIR = . +OBJS = $(foreach dir,$(SRC_DIR),$(subst .cpp,.o,$(wildcard $(dir)/*.cpp))) $(foreach dir,$(SRC_DIR),$(subst .c,.o,$(wildcard $(dir)/*.c))) + +INC_DIR = .. +INCS = $(foreach dir,$(INC_DIR), -I"$(dir)/") + +# Compiler Settings +CXXFLAGS = -std=c++11 $(INCS) -D__STDC_FORMAT_MACROS -Wall -Wno-unused-but-set-variable -Wno-unused-value +ifeq ($(OS),Windows_NT) + # Windows Only Flags/Libs + CC = x86_64-w64-mingw32-gcc + CXX = x86_64-w64-mingw32-g++ + CFLAGS += + CXXFLAGS += +else + # *nix Only Flags/Libs + CFLAGS += + CXXFLAGS += +endif + +# Output +OUTPUT = ../lib$(shell basename $(CURDIR)).a + +main: build + +rebuild: clean build + +build: $(OBJS) + ar cr -o $(OUTPUT) $(OBJS) + +clean: + rm -rf $(OUTPUT) $(OBJS) \ No newline at end of file diff --git a/lib/nx/nx.vcxproj b/lib/nx/nx.vcxproj new file mode 100644 index 0000000..523c070 --- /dev/null +++ b/lib/nx/nx.vcxproj @@ -0,0 +1,119 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B} + nx + 10.0.15063.0 + libnx + + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + \ No newline at end of file diff --git a/lib/nx/nx.vcxproj.filters b/lib/nx/nx.vcxproj.filters new file mode 100644 index 0000000..6a1782f --- /dev/null +++ b/lib/nx/nx.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + \ No newline at end of file diff --git a/makefile b/makefile new file mode 100644 index 0000000..e69de29