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"
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -2,161 +2,164 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <fnd/exception.h>
|
||||
#include <crypto/crypto.h>
|
||||
#include <crypto/aes.h>
|
||||
|
||||
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<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>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="aes.h" />
|
||||
<ClInclude Include="aes_ctr_stream.h" />
|
||||
<ClInclude Include="crypto.h" />
|
||||
<ClInclude Include="rsa.h" />
|
||||
<ClInclude Include="sha.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="aes.cpp" />
|
||||
<ClCompile Include="aes_ctr_stream.cpp" />
|
||||
<ClCompile Include="crypto.cpp" />
|
||||
<ClCompile Include="rsa.cpp" />
|
||||
<ClCompile Include="sha.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="makefile" />
|
||||
|
|
|
@ -18,7 +18,13 @@
|
|||
<ClInclude Include="aes_ctr_stream.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</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>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
|
@ -26,7 +32,13 @@
|
|||
<ClCompile Include="aes_ctr_stream.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</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>
|
||||
</ClCompile>
|
||||
</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