diff --git a/lib/crypto/aes.cpp b/lib/crypto/aes.cpp new file mode 100644 index 0000000..3da5f42 --- /dev/null +++ b/lib/crypto/aes.cpp @@ -0,0 +1,153 @@ +#include "aes.h" +#include "polarssl/aes.h" + +using namespace crypto::aes; + +inline void XorBlock(const uint8_t a[kAesBlockSize], const uint8_t b[kAesBlockSize], uint8_t out[kAesBlockSize]) +{ + for (uint8_t i = 0; i < 16; i++) + { + out[i] = a[i] ^ b[i]; + } +} + +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::aes::AesEcbDecrypt(const uint8_t * in, uint64_t size, const uint8_t key[kAes128KeySize], uint8_t * out) +{ + aes_context ctx; + aes_setkey_dec(&ctx, key, 128); + aes_crypt_ecb(&ctx, AES_DECRYPT, in, out); +} + +void crypto::aes::AesEcbEncrypt(const uint8_t * in, uint64_t size, const uint8_t key[kAes128KeySize], uint8_t * out) +{ + aes_context ctx; + aes_setkey_enc(&ctx, key, 128); + aes_crypt_ecb(&ctx, AES_ENCRYPT, in, out); +} + +void crypto::aes::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::aes::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::aes::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::aes::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); +} + +void crypto::aes::AesXtsDecryptSector(const uint8_t * in, uint64_t sector_size, const uint8_t key1[kAes128KeySize], const uint8_t key2[kAes128KeySize], uint8_t tweak[kAesBlockSize], uint8_t * out) +{ + aes_context data_ctx, tweak_ctx; + aes_setkey_dec(&data_ctx, key1, 128); + aes_setkey_enc(&tweak_ctx, key2, 128); + + uint8_t enc_tweak[kAesBlockSize]; + aes_crypt_ecb(&tweak_ctx, AES_ENCRYPT, tweak, enc_tweak); + + size_t block_num = sector_size / kAesBlockSize; + uint8_t block[kAesBlockSize]; + for (size_t i = 0; i < block_num; i++) + { + XorBlock(in + (i * kAesBlockSize), enc_tweak, block); + aes_crypt_ecb(&data_ctx, AES_DECRYPT, block, block); + XorBlock(block, enc_tweak, out + i * kAesBlockSize); + GaloisFunc(enc_tweak); + } + + if (sector_size % kAesBlockSize) + { + // TODO: implement ciphertext stealing + } +} + +void crypto::aes::AesXtsEncryptSector(const uint8_t * in, uint64_t sector_size, const uint8_t key1[kAes128KeySize], const uint8_t key2[kAes128KeySize], uint8_t tweak[kAesBlockSize], uint8_t * out) +{ + aes_context data_ctx, tweak_ctx; + aes_setkey_enc(&data_ctx, key1, 128); + aes_setkey_enc(&tweak_ctx, key2, 128); + + uint8_t enc_tweak[kAesBlockSize]; + aes_crypt_ecb(&tweak_ctx, AES_ENCRYPT, tweak, enc_tweak); + + size_t block_num = sector_size / kAesBlockSize; + uint8_t block[kAesBlockSize]; + for (size_t i = 0; i < block_num; i++) + { + XorBlock(in + (i * kAesBlockSize), enc_tweak, block); + aes_crypt_ecb(&data_ctx, AES_ENCRYPT, block, block); + XorBlock(block, enc_tweak, out + (i * kAesBlockSize)); + GaloisFunc(enc_tweak); + } + + if (sector_size % kAesBlockSize) + { + // TODO: implement ciphertext stealing + } +} + +void crypto::aes::AesXtsMakeTweak(uint8_t tweak[kAesBlockSize], uint64_t block_index) +{ + memset(tweak, 0, kAesBlockSize); + AesIncrementCounter(tweak, block_index, tweak); +} + +void crypto::aes::GaloisFunc(uint8_t x[kAesBlockSize]) +{ + uint8_t t = x[15]; + + for (uint8_t i = 16; i > 0; i--) + { + x[i] = (x[i] << 1) | (x[i - 1] & 0x80 ? 1 : 0); + } + + x[0] = (x[0] << 1) ^ (t & 0x80 ? 0x87 : 0x00); +} \ No newline at end of file diff --git a/lib/crypto/aes.h b/lib/crypto/aes.h new file mode 100644 index 0000000..71a607a --- /dev/null +++ b/lib/crypto/aes.h @@ -0,0 +1,67 @@ +#pragma once +#include +#include + +namespace crypto +{ +namespace aes +{ + const size_t kAes128KeySize = 0x10; + const size_t kAesBlockSize = 0x10; + const size_t KAesCcmNonceSize = 0xc; + +#pragma pack (push, 1) + struct sAes128Key + { + uint8_t key[kAes128KeySize]; + + void set(const uint8_t key[kAes128KeySize]) + { + memcpy(this->key, key, kAes128KeySize); + } + + void operator=(const sAes128Key& other) + { + set(other.key); + } + }; + + struct sAesXts128Key + { + sAes128Key key1; + sAes128Key key2; + }; + + struct sAesIvCtr + { + uint8_t iv[kAesBlockSize]; + + void set(const uint8_t iv[kAes128KeySize]) + { + memcpy(this->iv, iv, kAes128KeySize); + } + + void operator=(const sAesIvCtr& other) + { + set(other.iv); + } + }; +#pragma pack (pop) + + // aes-128 + void AesEcbDecrypt(const uint8_t* in, uint64_t size, const uint8_t key[kAes128KeySize], uint8_t* out); + void AesEcbEncrypt(const uint8_t* in, uint64_t size, const uint8_t key[kAes128KeySize], uint8_t* out); + + 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); + + void AesXtsDecryptSector(const uint8_t* in, uint64_t sector_size, const uint8_t key1[kAes128KeySize], const uint8_t key2[kAes128KeySize], uint8_t tweak[kAesBlockSize], uint8_t* out); + void AesXtsEncryptSector(const uint8_t* in, uint64_t sector_size, const uint8_t key1[kAes128KeySize], const uint8_t key2[kAes128KeySize], uint8_t tweak[kAesBlockSize], uint8_t* out); + void AesXtsMakeTweak(uint8_t tweak[kAesBlockSize], uint64_t block_index); + + void GaloisFunc(uint8_t x[kAesBlockSize]); +} +} \ No newline at end of file diff --git a/lib/crypto/aes_ctr_stream.cpp b/lib/crypto/aes_ctr_stream.cpp index dc8d5f7..a02c642 100644 --- a/lib/crypto/aes_ctr_stream.cpp +++ b/lib/crypto/aes_ctr_stream.cpp @@ -1,6 +1,6 @@ #include "aes_ctr_stream.h" -using namespace crypto; +using namespace crypto::aes; AesCtrStream::AesCtrStream() { @@ -73,7 +73,7 @@ void AesCtrStream::write(size_t offset, size_t size, const uint8_t * in) 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]) +void AesCtrStream::AddRegion(size_t start, size_t end, const uint8_t aes_key[kAes128KeySize], const uint8_t aes_ctr[kAesBlockSize]) { if (start >= end) { diff --git a/lib/crypto/aes_ctr_stream.h b/lib/crypto/aes_ctr_stream.h index ace3a87..963df7b 100644 --- a/lib/crypto/aes_ctr_stream.h +++ b/lib/crypto/aes_ctr_stream.h @@ -2,161 +2,164 @@ #include #include #include -#include +#include namespace crypto { - class AesCtrStream + namespace aes { - 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 + class AesCtrStream { public: - // stubbed constructor - CryptRegion() : - start_(0), - end_(0), - is_plaintext_(true) - { - CleanUp(); - } + AesCtrStream(); + ~AesCtrStream(); - // plaintext constructor - CryptRegion(size_t start, size_t end) : - start_(start), - end_(end), - is_plaintext_(true) - { - CleanUp(); - } + 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); - // 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); - } + void AddRegion(size_t start, size_t end, const uint8_t aes_key[kAes128KeySize], const uint8_t aes_ctr[kAesBlockSize]); - // destructor - ~CryptRegion() - { - CleanUp(); - } + 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; - 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 + const std::string kModuleName = "AES_CTR_STREAM"; + static const size_t kIoBufferLen = 0x10000; - 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() + // private implementation of crypto region + class CryptRegion { - memset(aes_key_, 0, crypto::kAes128KeySize); - memset(ctr_init_, 0, crypto::kAesBlockSize); - memset(ctr_, 0, crypto::kAesBlockSize); + 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[kAes128KeySize], const uint8_t aes_ctr[kAesBlockSize]) : + start_(start), + end_(end), + is_plaintext_(false) + { + CleanUp(); + memcpy(aes_key_, aes_key, kAes128KeySize); + memcpy(ctr_init_, aes_ctr, kAesBlockSize); + memcpy(ctr_, ctr_init_, 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)) + 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)); + 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 + kAesBlockSize; // has an extra block to accomodate non block aligned starts + + size_t start_; + size_t end_; + bool is_plaintext_; + uint8_t aes_key_[kAes128KeySize]; + uint8_t ctr_init_[kAesBlockSize]; + uint8_t ctr_[kAesBlockSize]; + uint8_t pad_buffer_[kPadBufferCapacity]; + + void CleanUp() + { + memset(aes_key_, 0, kAes128KeySize); + memset(ctr_init_, 0, kAesBlockSize); + memset(ctr_, 0, 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); }; - - - - 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/crypto.cpp b/lib/crypto/crypto.cpp deleted file mode 100644 index 52847f0..0000000 --- a/lib/crypto/crypto.cpp +++ /dev/null @@ -1,229 +0,0 @@ -#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 deleted file mode 100644 index d368b5c..0000000 --- a/lib/crypto/crypto.h +++ /dev/null @@ -1,152 +0,0 @@ -#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.vcxproj b/lib/crypto/crypto.vcxproj index a5118d2..cf638c2 100644 --- a/lib/crypto/crypto.vcxproj +++ b/lib/crypto/crypto.vcxproj @@ -112,12 +112,16 @@ + - + + + - + + diff --git a/lib/crypto/crypto.vcxproj.filters b/lib/crypto/crypto.vcxproj.filters index 7335da3..b8415e2 100644 --- a/lib/crypto/crypto.vcxproj.filters +++ b/lib/crypto/crypto.vcxproj.filters @@ -18,7 +18,13 @@ Header Files - + + Header Files + + + Header Files + + Header Files @@ -26,7 +32,13 @@ Source Files - + + Source Files + + + Source Files + + Source Files diff --git a/lib/crypto/rsa.cpp b/lib/crypto/rsa.cpp new file mode 100644 index 0000000..b848ddf --- /dev/null +++ b/lib/crypto/rsa.cpp @@ -0,0 +1,148 @@ +#include "rsa.h" +#include "polarssl/rsa.h" + +using namespace crypto::rsa; +using namespace crypto::sha; + +int GetWrappedHashType(HashType type) +{ + switch (type) + { + case HASH_SHA1: + return SIG_RSA_SHA1; + break; + case 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 HASH_SHA1: + size = kSha1HashLen; + break; + case HASH_SHA256: + size = kSha256HashLen; + break; + default: + break; + } + return size; +} + +int crypto::rsa::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::rsa::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::rsa::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::rsa::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::rsa::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::rsa::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; +} \ No newline at end of file diff --git a/lib/crypto/rsa.h b/lib/crypto/rsa.h new file mode 100644 index 0000000..f87b9e4 --- /dev/null +++ b/lib/crypto/rsa.h @@ -0,0 +1,91 @@ +#pragma once +#include +#include +#include + +namespace crypto +{ + namespace rsa + { + const size_t kRsa1024Size = 0x80; + const size_t kRsa2048Size = 0x100; + const size_t kRsa4096Size = 0x200; + const size_t kRsaPublicExponentSize = 4; + + enum RsaType + { + RSA_1024, + RSA_2048, + RSA_4096, + }; + +#pragma pack (push, 1) + 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; + } + }; +#pragma pack (pop) + + // rsa1024 + int RsaSign(const sRsa1024Key& key, sha::HashType hash_type, const uint8_t* hash, uint8_t signature[kRsa1024Size]); + int RsaVerify(const sRsa1024Key& key, sha::HashType hash_type, const uint8_t* hash, const uint8_t signature[kRsa1024Size]); + // rsa2048 + int RsaSign(const sRsa2048Key& key, sha::HashType hash_type, const uint8_t* hash, uint8_t signature[kRsa2048Size]); + int RsaVerify(const sRsa2048Key& key, sha::HashType hash_type, const uint8_t* hash, const uint8_t signature[kRsa2048Size]); + // rsa4096 + int RsaSign(const sRsa4096Key& key, sha::HashType hash_type, const uint8_t* hash, uint8_t signature[kRsa4096Size]); + int RsaVerify(const sRsa4096Key& key, sha::HashType hash_type, const uint8_t* hash, const uint8_t signature[kRsa4096Size]); + } +} diff --git a/lib/crypto/sha.cpp b/lib/crypto/sha.cpp new file mode 100644 index 0000000..3839f99 --- /dev/null +++ b/lib/crypto/sha.cpp @@ -0,0 +1,15 @@ +#include "sha.h" +#include "polarssl/sha1.h" +#include "polarssl/sha2.h" + +using namespace crypto::sha; + +void crypto::sha::Sha1(const uint8_t* in, uint64_t size, uint8_t hash[kSha1HashLen]) +{ + sha1(in, size, hash); +} + +void crypto::sha::Sha256(const uint8_t* in, uint64_t size, uint8_t hash[kSha256HashLen]) +{ + sha2(in, size, hash, false); +} \ No newline at end of file diff --git a/lib/crypto/sha.h b/lib/crypto/sha.h new file mode 100644 index 0000000..59b8037 --- /dev/null +++ b/lib/crypto/sha.h @@ -0,0 +1,83 @@ +#pragma once +#include +#include + +namespace crypto +{ + namespace sha + { + const size_t kSha1HashLen = 20; + const size_t kSha256HashLen = 32; + + enum HashType + { + HASH_SHA1, + HASH_SHA256 + }; + +#pragma pack (push, 1) + struct sSha1Hash + { + uint8_t bytes[kSha1HashLen]; + + void set(const uint8_t hash[kSha1HashLen]) + { + memcpy(this->bytes, hash, kSha1HashLen); + } + + void operator=(const sSha1Hash& other) + { + set(other.bytes); + } + + bool compare(const uint8_t hash[kSha1HashLen]) + { + return memcmp(this->bytes, hash, kSha1HashLen) == 0; + } + + bool compare(const sSha1Hash& other) + { + return memcmp(this->bytes, other.bytes, kSha1HashLen) == 0; + } + + bool operator==(const sSha1Hash& other) + { + return compare(other); + } + }; + + struct sSha256Hash + { + uint8_t bytes[kSha256HashLen]; + + void set(const uint8_t hash[kSha256HashLen]) + { + memcpy(this->bytes, hash, kSha256HashLen); + } + + void operator=(const sSha256Hash& other) + { + set(other.bytes); + } + + bool compare(const uint8_t hash[kSha256HashLen]) + { + return memcmp(this->bytes, hash, kSha256HashLen) == 0; + } + + bool compare(const sSha256Hash& other) + { + return memcmp(this->bytes, other.bytes, kSha256HashLen) == 0; + } + + bool operator==(const sSha256Hash& other) + { + return compare(other); + } + }; +#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]); + } +} \ No newline at end of file