diff --git a/lib/libes/include/es/SignatureBlock.h b/lib/libes/include/es/SignatureBlock.h new file mode 100644 index 0000000..86ab6c8 --- /dev/null +++ b/lib/libes/include/es/SignatureBlock.h @@ -0,0 +1,53 @@ +#pragma once +#include +#include +#include +#include + +namespace es +{ + class SignatureBlock + : public fnd::ISerialiseableBinary + { + public: + SignatureBlock(); + SignatureBlock(const SignatureBlock& other); + + void operator=(const SignatureBlock& other); + bool operator==(const SignatureBlock& other) const; + bool operator!=(const SignatureBlock& other) const; + + void importBinary(byte_t* src, size_t size); + void exportBinary(); + + const byte_t* getBytes() const; + size_t getSize() const; + + void clear(); + + es::sign::SignType getSignType() const; + void setSignType(es::sign::SignType type); + + bool isLittleEndian() const; + void setLittleEndian(bool isLE); + + const fnd::MemoryBlob& getSignature() const; + void setSignature(const fnd::MemoryBlob& signature); + + + private: + const std::string kModuleName = "SIGNATURE_BLOCK"; + + // raw binary + fnd::MemoryBlob mBinaryBlob; + + // variables + es::sign::SignType mSignType; + bool mIsLittleEndian; + fnd::MemoryBlob mSignature; + + // helpers + bool isEqual(const SignatureBlock& other) const; + void copyFrom(const SignatureBlock& other); + }; +} \ No newline at end of file diff --git a/lib/libes/source/SignatureBlock.cpp b/lib/libes/source/SignatureBlock.cpp new file mode 100644 index 0000000..d8d6fba --- /dev/null +++ b/lib/libes/source/SignatureBlock.cpp @@ -0,0 +1,197 @@ +#include + +es::SignatureBlock::SignatureBlock() +{ + clear(); +} + +es::SignatureBlock::SignatureBlock(const SignatureBlock& other) +{ + copyFrom(other); +} + +void es::SignatureBlock::operator=(const SignatureBlock& other) +{ + copyFrom(other); +} + +bool es::SignatureBlock::operator==(const SignatureBlock& other) const +{ + return isEqual(other); +} + +bool es::SignatureBlock::operator!=(const SignatureBlock& other) const +{ + return !(*this == other); +} + +void es::SignatureBlock::importBinary(byte_t* src, size_t size) +{ + clear(); + + size_t totalSize = 0; + size_t sigSize = 0; + uint32_t signType = 0; + + // try Big Endian sign type + signType = ((be_uint32_t*)src)->get(); + switch (signType) + { + case (sign::SIGN_RSA4096_SHA1): + case (sign::SIGN_RSA4096_SHA256): + totalSize = sizeof(sRsa4096SignBlock); + sigSize = crypto::rsa::kRsa4096Size; + break; + case (sign::SIGN_RSA2048_SHA1): + case (sign::SIGN_RSA2048_SHA256): + totalSize = sizeof(sRsa2048SignBlock); + sigSize = crypto::rsa::kRsa2048Size; + break; + case (sign::SIGN_ECDSA240_SHA1): + case (sign::SIGN_ECDSA240_SHA256): + totalSize = sizeof(sEcdsa240SignBlock); + sigSize = sign::kEcdsaSigSize; + break; + } + + // try Big Endian sign type + if (totalSize == 0) + { + signType = ((le_uint32_t*)src)->get(); + switch (signType) + { + case (sign::SIGN_RSA4096_SHA1): + case (sign::SIGN_RSA4096_SHA256): + totalSize = sizeof(sRsa4096SignBlock); + sigSize = crypto::rsa::kRsa4096Size; + break; + case (sign::SIGN_RSA2048_SHA1): + case (sign::SIGN_RSA2048_SHA256): + totalSize = sizeof(sRsa2048SignBlock); + sigSize = crypto::rsa::kRsa2048Size; + break; + case (sign::SIGN_ECDSA240_SHA1): + case (sign::SIGN_ECDSA240_SHA256): + totalSize = sizeof(sEcdsa240SignBlock); + sigSize = sign::kEcdsaSigSize; + break; + default: + throw fnd::Exception(kModuleName, "Unknown signature type"); + } + + mIsLittleEndian = true; + } + + if (totalSize > size) + { + throw fnd::Exception(kModuleName, "Certificate too small"); + } + + mBinaryBlob.alloc(totalSize); + memcpy(mBinaryBlob.getBytes(), src, totalSize); + + mSignType = (sign::SignType)signType; + mSignature.alloc(sigSize); + memcpy(mSignature.getBytes(), mBinaryBlob.getBytes() + 4, sigSize); +} + +void es::SignatureBlock::exportBinary() +{ + size_t totalSize = 0; + size_t sigSize = 0; + + switch (mSignType) + { + case (sign::SIGN_RSA4096_SHA1): + case (sign::SIGN_RSA4096_SHA256): + totalSize = sizeof(sRsa4096SignBlock); + sigSize = crypto::rsa::kRsa4096Size; + break; + case (sign::SIGN_RSA2048_SHA1): + case (sign::SIGN_RSA2048_SHA256): + totalSize = sizeof(sRsa2048SignBlock); + sigSize = crypto::rsa::kRsa2048Size; + break; + case (sign::SIGN_ECDSA240_SHA1): + case (sign::SIGN_ECDSA240_SHA256): + totalSize = sizeof(sEcdsa240SignBlock); + sigSize = sign::kEcdsaSigSize; + break; + default: + throw fnd::Exception(kModuleName, "Unknown signature type"); + } + + if (mSignature.getSize() != sigSize) + throw fnd::Exception(kModuleName, "Signature size is incorrect"); + + // commit to binary + mBinaryBlob.alloc(totalSize); + if (mIsLittleEndian) + *(le_uint32_t*)(mBinaryBlob.getBytes()) = mSignType; + else + *(be_uint32_t*)(mBinaryBlob.getBytes()) = mSignType; + memcpy(mBinaryBlob.getBytes() + 4, mSignature.getBytes(), sigSize); +} + +const byte_t* es::SignatureBlock::getBytes() const +{ + return mBinaryBlob.getBytes(); +} + +size_t es::SignatureBlock::getSize() const +{ + return mBinaryBlob.getSize(); +} + +void es::SignatureBlock::clear() +{ + mBinaryBlob.clear(); + mSignType = sign::SIGN_RSA4096_SHA1; + mIsLittleEndian = false; + mSignature.clear(); +} + +es::sign::SignType es::SignatureBlock::getSignType() const +{ + return mSignType; +} + +void es::SignatureBlock::setSignType(es::sign::SignType type) +{ + mSignType = type; +} + +bool es::SignatureBlock::isLittleEndian() const +{ + return mIsLittleEndian; +} + +void es::SignatureBlock::setLittleEndian(bool isLE) +{ + mIsLittleEndian = isLE; +} + +const fnd::MemoryBlob& es::SignatureBlock::getSignature() const +{ + return mSignature; +} + +void es::SignatureBlock::setSignature(const fnd::MemoryBlob& signature) +{ + mSignature = signature; +} + +bool es::SignatureBlock::isEqual(const SignatureBlock& other) const +{ + return (mSignType == other.mSignType) \ + && (mIsLittleEndian == other.mIsLittleEndian) \ + && (mSignature == other.mSignature); +} + +void es::SignatureBlock::copyFrom(const SignatureBlock& other) +{ + mBinaryBlob = other.mBinaryBlob; + mSignType = other.mSignType; + mIsLittleEndian = other.mIsLittleEndian; + mSignature = other.mSignature; +}