[crypto] Split code in crypto to rsa, aes, sha files. Also namespaces.

This commit is contained in:
jakcron 2017-07-05 18:54:49 +10:00
parent 600eccaeed
commit e8e9fbd907
12 changed files with 724 additions and 529 deletions

153
lib/crypto/aes.cpp Normal file
View file

@ -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);
}

67
lib/crypto/aes.h Normal file
View file

@ -0,0 +1,67 @@
#pragma once
#include <cstdint>
#include <cstring>
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]);
}
}

View file

@ -1,6 +1,6 @@
#include "aes_ctr_stream.h" #include "aes_ctr_stream.h"
using namespace crypto; using namespace crypto::aes;
AesCtrStream::AesCtrStream() AesCtrStream::AesCtrStream()
{ {
@ -73,7 +73,7 @@ void AesCtrStream::write(size_t offset, size_t size, const uint8_t * in)
write(size, 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) if (start >= end)
{ {

View file

@ -2,9 +2,11 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <fnd/exception.h> #include <fnd/exception.h>
#include <crypto/crypto.h> #include <crypto/aes.h>
namespace crypto namespace crypto
{
namespace aes
{ {
class AesCtrStream class AesCtrStream
{ {
@ -18,7 +20,7 @@ namespace crypto
void write(size_t size, const uint8_t* in); void write(size_t size, const uint8_t* in);
void write(size_t offset, 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]); void AddRegion(size_t start, size_t end, const uint8_t aes_key[kAes128KeySize], const uint8_t aes_ctr[kAesBlockSize]);
protected: protected:
// Virtual methods for implementation of seek/read/write // Virtual methods for implementation of seek/read/write
@ -53,15 +55,15 @@ namespace crypto
} }
// encrypted constructor // encrypted constructor
CryptRegion(size_t start, size_t end, const uint8_t aes_key[crypto::kAes128KeySize], const uint8_t aes_ctr[crypto::kAesBlockSize]) : CryptRegion(size_t start, size_t end, const uint8_t aes_key[kAes128KeySize], const uint8_t aes_ctr[kAesBlockSize]) :
start_(start), start_(start),
end_(end), end_(end),
is_plaintext_(false) is_plaintext_(false)
{ {
CleanUp(); CleanUp();
memcpy(aes_key_, aes_key, crypto::kAes128KeySize); memcpy(aes_key_, aes_key, kAes128KeySize);
memcpy(ctr_init_, aes_ctr, crypto::kAesBlockSize); memcpy(ctr_init_, aes_ctr, kAesBlockSize);
memcpy(ctr_, ctr_init_, crypto::kAesBlockSize); memcpy(ctr_, ctr_init_, kAesBlockSize);
} }
// destructor // destructor
@ -83,7 +85,7 @@ namespace crypto
void UpdateAesCtr(size_t start) void UpdateAesCtr(size_t start)
{ {
if (is_in_region(start)) if (is_in_region(start))
crypto::AesIncrementCounter(ctr_init_, ((start - start_) >> 4), ctr_); AesIncrementCounter(ctr_init_, ((start - start_) >> 4), ctr_);
} }
void GenerateXorpad(size_t start, size_t size, uint8_t* out) void GenerateXorpad(size_t start, size_t size, uint8_t* out)
@ -110,7 +112,7 @@ namespace crypto
// encrypt pad buffer to create xorpad // encrypt pad buffer to create xorpad
UpdateAesCtr(start + (pos << 4)); UpdateAesCtr(start + (pos << 4));
crypto::AesCtr(pad_buffer_, kPadBufferCapacity, aes_key(), aes_ctr(), pad_buffer_); AesCtr(pad_buffer_, kPadBufferCapacity, aes_key(), aes_ctr(), pad_buffer_);
// determine the number of blocks to copy to xorpad // determine the number of blocks to copy to xorpad
size_t copy_size = kPadBufferLen < ((block_num - pos) << 4) ? kPadBufferLen : ((block_num - pos) << 4); size_t copy_size = kPadBufferLen < ((block_num - pos) << 4) ? kPadBufferLen : ((block_num - pos) << 4);
@ -121,21 +123,21 @@ namespace crypto
} }
private: private:
static const size_t kPadBufferLen = 0x10000; static const size_t kPadBufferLen = 0x10000;
static const size_t kPadBufferCapacity = kPadBufferLen + crypto::kAesBlockSize; // has an extra block to accomodate non block aligned starts static const size_t kPadBufferCapacity = kPadBufferLen + kAesBlockSize; // has an extra block to accomodate non block aligned starts
size_t start_; size_t start_;
size_t end_; size_t end_;
bool is_plaintext_; bool is_plaintext_;
uint8_t aes_key_[crypto::kAes128KeySize]; uint8_t aes_key_[kAes128KeySize];
uint8_t ctr_init_[crypto::kAesBlockSize]; uint8_t ctr_init_[kAesBlockSize];
uint8_t ctr_[crypto::kAesBlockSize]; uint8_t ctr_[kAesBlockSize];
uint8_t pad_buffer_[kPadBufferCapacity]; uint8_t pad_buffer_[kPadBufferCapacity];
void CleanUp() void CleanUp()
{ {
memset(aes_key_, 0, crypto::kAes128KeySize); memset(aes_key_, 0, kAes128KeySize);
memset(ctr_init_, 0, crypto::kAesBlockSize); memset(ctr_init_, 0, kAesBlockSize);
memset(ctr_, 0, crypto::kAesBlockSize); memset(ctr_, 0, kAesBlockSize);
} }
}; };
@ -160,3 +162,4 @@ namespace crypto
void GenerateXorPad(size_t start); void GenerateXorPad(size_t start);
}; };
} }
}

View file

@ -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;
}

View file

@ -1,152 +0,0 @@
#pragma once
#include <cstdint>
#include <cstring>
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);
}

View file

@ -112,12 +112,16 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="aes.h" />
<ClInclude Include="aes_ctr_stream.h" /> <ClInclude Include="aes_ctr_stream.h" />
<ClInclude Include="crypto.h" /> <ClInclude Include="rsa.h" />
<ClInclude Include="sha.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="aes.cpp" />
<ClCompile Include="aes_ctr_stream.cpp" /> <ClCompile Include="aes_ctr_stream.cpp" />
<ClCompile Include="crypto.cpp" /> <ClCompile Include="rsa.cpp" />
<ClCompile Include="sha.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="makefile" /> <None Include="makefile" />

View file

@ -18,7 +18,13 @@
<ClInclude Include="aes_ctr_stream.h"> <ClInclude Include="aes_ctr_stream.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="crypto.h"> <ClInclude Include="aes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="sha.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="rsa.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
</ItemGroup> </ItemGroup>
@ -26,7 +32,13 @@
<ClCompile Include="aes_ctr_stream.cpp"> <ClCompile Include="aes_ctr_stream.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="crypto.cpp"> <ClCompile Include="aes.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="sha.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="rsa.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>

148
lib/crypto/rsa.cpp Normal file
View file

@ -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;
}

91
lib/crypto/rsa.h Normal file
View file

@ -0,0 +1,91 @@
#pragma once
#include <cstdint>
#include <cstring>
#include <crypto/sha.h>
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]);
}
}

15
lib/crypto/sha.cpp Normal file
View file

@ -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);
}

83
lib/crypto/sha.h Normal file
View file

@ -0,0 +1,83 @@
#pragma once
#include <cstdint>
#include <cstring>
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]);
}
}