mirror of
https://github.com/jakcron/nstool.git
synced 2024-12-22 10:45:28 +00:00
[crypto] Split code in crypto to rsa, aes, sha files. Also namespaces.
This commit is contained in:
parent
600eccaeed
commit
e8e9fbd907
153
lib/crypto/aes.cpp
Normal file
153
lib/crypto/aes.cpp
Normal 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
67
lib/crypto/aes.h
Normal 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]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,161 +2,164 @@
|
||||||
#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
|
||||||
{
|
{
|
||||||
class AesCtrStream
|
namespace aes
|
||||||
{
|
{
|
||||||
public:
|
class AesCtrStream
|
||||||
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:
|
public:
|
||||||
// stubbed constructor
|
AesCtrStream();
|
||||||
CryptRegion() :
|
~AesCtrStream();
|
||||||
start_(0),
|
|
||||||
end_(0),
|
|
||||||
is_plaintext_(true)
|
|
||||||
{
|
|
||||||
CleanUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
// plaintext constructor
|
void seek(size_t offset);
|
||||||
CryptRegion(size_t start, size_t end) :
|
void read(size_t size, uint8_t* out);
|
||||||
start_(start),
|
void read(size_t offset, size_t size, uint8_t* out);
|
||||||
end_(end),
|
void write(size_t size, const uint8_t* in);
|
||||||
is_plaintext_(true)
|
void write(size_t offset, size_t size, const uint8_t* in);
|
||||||
{
|
|
||||||
CleanUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
// encrypted constructor
|
void AddRegion(size_t start, size_t end, const uint8_t aes_key[kAes128KeySize], const uint8_t aes_ctr[kAesBlockSize]);
|
||||||
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
|
protected:
|
||||||
~CryptRegion()
|
// Virtual methods for implementation of seek/read/write
|
||||||
{
|
virtual void seek_internal(size_t offset) = 0;
|
||||||
CleanUp();
|
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:
|
private:
|
||||||
static const size_t kPadBufferLen = 0x10000;
|
const std::string kModuleName = "AES_CTR_STREAM";
|
||||||
static const size_t kPadBufferCapacity = kPadBufferLen + crypto::kAesBlockSize; // has an extra block to accomodate non block aligned starts
|
static const size_t kIoBufferLen = 0x10000;
|
||||||
|
|
||||||
size_t start_;
|
// private implementation of crypto region
|
||||||
size_t end_;
|
class CryptRegion
|
||||||
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);
|
public:
|
||||||
memset(ctr_init_, 0, crypto::kAesBlockSize);
|
// stubbed constructor
|
||||||
memset(ctr_, 0, crypto::kAesBlockSize);
|
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<CryptRegion> 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<CryptRegion> regions_;
|
|
||||||
|
|
||||||
// IO Buffer
|
|
||||||
uint8_t io_buffer_[kIoBufferLen];
|
|
||||||
uint8_t pad_buffer_[kIoBufferLen];
|
|
||||||
|
|
||||||
void GenerateXorPad(size_t start);
|
|
||||||
};
|
|
||||||
}
|
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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" />
|
||||||
|
|
|
@ -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
148
lib/crypto/rsa.cpp
Normal 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
91
lib/crypto/rsa.h
Normal 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
15
lib/crypto/sha.cpp
Normal 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
83
lib/crypto/sha.h
Normal 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]);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue