From 3089069c8b10baf5ad7a33886206f608f3fdeb35 Mon Sep 17 00:00:00 2001 From: jakcron Date: Fri, 22 Jun 2018 21:57:55 +0800 Subject: [PATCH] [es] Add es::CertificateBody --- lib/libes/include/es/CertificateBody.h | 69 +++++++ lib/libes/include/es/cert.h | 11 +- lib/libes/source/CertificateBody.cpp | 269 +++++++++++++++++++++++++ 3 files changed, 344 insertions(+), 5 deletions(-) create mode 100644 lib/libes/include/es/CertificateBody.h create mode 100644 lib/libes/source/CertificateBody.cpp diff --git a/lib/libes/include/es/CertificateBody.h b/lib/libes/include/es/CertificateBody.h new file mode 100644 index 0000000..2dd0cdb --- /dev/null +++ b/lib/libes/include/es/CertificateBody.h @@ -0,0 +1,69 @@ +#pragma once +#include +#include +#include +#include + +namespace es +{ + class CertificateBody + : public fnd::ISerialiseableBinary + { + public: + CertificateBody(); + CertificateBody(const CertificateBody& other); + + void operator=(const CertificateBody& other); + bool operator==(const CertificateBody& other) const; + bool operator!=(const CertificateBody& other) const; + + void importBinary(byte_t* src, size_t size); + void exportBinary(); + + const byte_t* getBytes() const; + size_t getSize() const; + + void clear(); + + const std::string& getIssuer() const; + void setIssuer(const std::string& issuer); + + es::cert::PublicKeyType getPublicKeyType() const; + void setPublicKeyType(cert::PublicKeyType type); + + const std::string& getSubject() const; + void setSubject(const std::string& subject); + + uint32_t getCertId() const; + void setCertId(uint32_t id); + + const crypto::rsa::sRsa4096Key& getRsa4098PublicKey() const; + void setRsa4098PublicKey(const crypto::rsa::sRsa4096Key& key); + + const crypto::rsa::sRsa2048Key& getRsa2048PublicKey() const; + void setRsa2048PublicKey(const crypto::rsa::sRsa2048Key& key); + + const crypto::ecdsa::sEcdsa240Point& getEcdsa240PublicKey() const; + void setEcdsa240PublicKey(const crypto::ecdsa::sEcdsa240Point& key); + + private: + const std::string kModuleName = "CERTIFICATE_BODY"; + + // raw binary + fnd::MemoryBlob mBinaryBlob; + + // variables + std::string mIssuer; + std::string mSubject; + uint32_t mCertId; + cert::PublicKeyType mPublicKeyType; + + crypto::rsa::sRsa4096Key mRsa4096PublicKey; + crypto::rsa::sRsa2048Key mRsa2048PublicKey; + crypto::ecdsa::sEcdsa240Point mEcdsa240PublicKey; + + // helpers + bool isEqual(const CertificateBody& other) const; + void copyFrom(const CertificateBody& other); + }; +} \ No newline at end of file diff --git a/lib/libes/include/es/cert.h b/lib/libes/include/es/cert.h index af261fc..ab4ec0a 100644 --- a/lib/libes/include/es/cert.h +++ b/lib/libes/include/es/cert.h @@ -3,6 +3,7 @@ #include #include #include +#include namespace es { @@ -19,31 +20,31 @@ namespace es static const size_t kSubjectSize = 0x40; } #pragma pack(push,1) - struct sCertificateBody + struct sCertificateHeader { char issuer[cert::kIssuerSize]; be_uint32_t key_type; char subject[cert::kSubjectSize]; be_uint32_t cert_id; - } + }; struct sRsa4096PublicKeyBlock { byte_t modulus[crypto::rsa::kRsa4096Size]; - byte_t public_exponent[0x4]; + byte_t public_exponent[crypto::rsa::kRsaPublicExponentSize]; byte_t padding[0x34]; }; struct sRsa2048PublicKeyBlock { byte_t modulus[crypto::rsa::kRsa2048Size]; - byte_t public_exponent[0x4]; + byte_t public_exponent[crypto::rsa::kRsaPublicExponentSize]; byte_t padding[0x34]; }; struct sEcdsa240PublicKeyBlock { - byte_t public_key[0x3C]; + crypto::ecdsa::sEcdsa240Point public_key; byte_t padding[0x3C]; }; #pragma pack(pop) diff --git a/lib/libes/source/CertificateBody.cpp b/lib/libes/source/CertificateBody.cpp new file mode 100644 index 0000000..627720b --- /dev/null +++ b/lib/libes/source/CertificateBody.cpp @@ -0,0 +1,269 @@ +#include + +es::CertificateBody::CertificateBody() +{ + clear(); +} + +es::CertificateBody::CertificateBody(const CertificateBody& other) +{ + copyFrom(other); +} + +void es::CertificateBody::operator=(const CertificateBody& other) +{ + copyFrom(other); +} + +bool es::CertificateBody::operator==(const CertificateBody& other) const +{ + return isEqual(other); +} + +bool es::CertificateBody::operator!=(const CertificateBody& other) const +{ + return !(*this == other); +} + +void es::CertificateBody::importBinary(byte_t* src, size_t size) +{ + clear(); + + // check minimum size + if (size < sizeof(sCertificateHeader)) + { + throw fnd::Exception(kModuleName, "Certificate too small"); + } + + const sCertificateHeader* hdr = (const sCertificateHeader*)src; + + // get public key size + size_t pubkeySize = 0; + switch (hdr->key_type.get()) + { + case (cert::RSA4096): + pubkeySize = sizeof(sRsa4096PublicKeyBlock); + break; + case (cert::RSA2048): + pubkeySize = sizeof(sRsa2048PublicKeyBlock); + break; + case (cert::ECDSA240): + pubkeySize = sizeof(sEcdsa240PublicKeyBlock); + break; + default: + throw fnd::Exception(kModuleName, "Unknown public key type"); + } + + // check total size + if (size < (sizeof(sCertificateHeader) + pubkeySize)) + { + throw fnd::Exception(kModuleName, "Certificate too small"); + } + + // save raw binary + mBinaryBlob.alloc((sizeof(sCertificateHeader) + pubkeySize)); + memcpy(mBinaryBlob.getBytes(), src, mBinaryBlob.getSize()); + + // save hdr variables + hdr = (const sCertificateHeader*)mBinaryBlob.getBytes(); + + if (hdr->issuer[0] != 0) + mIssuer = std::string(hdr->issuer, cert::kIssuerSize); + mPublicKeyType = (cert::PublicKeyType)hdr->key_type.get(); + if (hdr->subject[0] != 0) + mSubject = std::string(hdr->subject, cert::kSubjectSize); + mCertId = hdr->cert_id.get(); + + // save public key + if (mPublicKeyType == cert::RSA4096) + { + const sRsa4096PublicKeyBlock* pubkey = (const sRsa4096PublicKeyBlock*)(mBinaryBlob.getBytes() + sizeof(sCertificateHeader)); + memcpy(mRsa4096PublicKey.modulus, pubkey->modulus, sizeof(mRsa4096PublicKey.modulus)); + memcpy(mRsa4096PublicKey.public_exponent, pubkey->public_exponent, sizeof(mRsa4096PublicKey.public_exponent)); + } + else if (mPublicKeyType == cert::RSA2048) + { + const sRsa2048PublicKeyBlock* pubkey = (const sRsa2048PublicKeyBlock*)(mBinaryBlob.getBytes() + sizeof(sCertificateHeader)); + memcpy(mRsa2048PublicKey.modulus, pubkey->modulus, sizeof(mRsa2048PublicKey.modulus)); + memcpy(mRsa2048PublicKey.public_exponent, pubkey->public_exponent, sizeof(mRsa2048PublicKey.public_exponent)); + } + else if (mPublicKeyType == cert::ECDSA240) + { + const sEcdsa240PublicKeyBlock* pubkey = (const sEcdsa240PublicKeyBlock*)(mBinaryBlob.getBytes() + sizeof(sCertificateHeader)); + mEcdsa240PublicKey = pubkey->public_key; + } +} + +void es::CertificateBody::exportBinary() +{ + // get public key size + size_t pubkeySize = 0; + switch (mPublicKeyType) + { + case (cert::RSA4096): + pubkeySize = sizeof(sRsa4096PublicKeyBlock); + break; + case (cert::RSA2048): + pubkeySize = sizeof(sRsa2048PublicKeyBlock); + break; + case (cert::ECDSA240): + pubkeySize = sizeof(sEcdsa240PublicKeyBlock); + break; + default: + throw fnd::Exception(kModuleName, "Unknown public key type"); + } + + mBinaryBlob.alloc(sizeof(sCertificateHeader) + pubkeySize); + sCertificateHeader* hdr = (sCertificateHeader*)mBinaryBlob.getBytes(); + + // copy header vars + strncpy(hdr->issuer, mIssuer.c_str(), cert::kIssuerSize); + hdr->key_type = mPublicKeyType; + strncpy(hdr->subject, mSubject.c_str(), cert::kSubjectSize); + hdr->cert_id = mCertId; + + // copy public key + if (mPublicKeyType == cert::RSA4096) + { + sRsa4096PublicKeyBlock* pubkey = (sRsa4096PublicKeyBlock*)(mBinaryBlob.getBytes() + sizeof(sCertificateHeader)); + memcpy(pubkey->modulus, mRsa4096PublicKey.modulus, sizeof(mRsa4096PublicKey.modulus)); + memcpy(pubkey->public_exponent, mRsa4096PublicKey.public_exponent, sizeof(mRsa4096PublicKey.public_exponent)); + } + else if (mPublicKeyType == cert::RSA2048) + { + sRsa2048PublicKeyBlock* pubkey = (sRsa2048PublicKeyBlock*)(mBinaryBlob.getBytes() + sizeof(sCertificateHeader)); + memcpy(pubkey->modulus, mRsa2048PublicKey.modulus, sizeof(mRsa2048PublicKey.modulus)); + memcpy(pubkey->public_exponent, mRsa2048PublicKey.public_exponent, sizeof(mRsa2048PublicKey.public_exponent)); + } + else if (mPublicKeyType == cert::ECDSA240) + { + sEcdsa240PublicKeyBlock* pubkey = (sEcdsa240PublicKeyBlock*)(mBinaryBlob.getBytes() + sizeof(sCertificateHeader)); + pubkey->public_key = mEcdsa240PublicKey; + } +} + +const byte_t* es::CertificateBody::getBytes() const +{ + return mBinaryBlob.getBytes(); +} + +size_t es::CertificateBody::getSize() const +{ + return mBinaryBlob.getSize(); +} + +void es::CertificateBody::clear() +{ + mIssuer.clear(); + mSubject.clear(); + mCertId = 0; + mPublicKeyType = cert::RSA2048; + + memset(&mRsa4096PublicKey, 0, sizeof(crypto::rsa::sRsa4096Key)); + memset(&mRsa2048PublicKey, 0, sizeof(crypto::rsa::sRsa2048Key)); + memset(&mEcdsa240PublicKey, 0, sizeof(crypto::ecdsa::sEcdsa240Point)); +} + +const std::string& es::CertificateBody::getIssuer() const +{ + return mIssuer; +} + +void es::CertificateBody::setIssuer(const std::string& issuer) +{ + if (issuer.size() > cert::kIssuerSize) + { + throw fnd::Exception(kModuleName, "Issuer name too long"); + } + + mIssuer = issuer; +} + +es::cert::PublicKeyType es::CertificateBody::getPublicKeyType() const +{ + return mPublicKeyType; +} + +void es::CertificateBody::setPublicKeyType(cert::PublicKeyType type) +{ + mPublicKeyType = type; +} + +const std::string& es::CertificateBody::getSubject() const +{ + return mSubject; +} + +void es::CertificateBody::setSubject(const std::string& subject) +{ + if (subject.size() > cert::kSubjectSize) + { + throw fnd::Exception(kModuleName, "Subject name too long"); + } + + mSubject = subject; +} + +uint32_t es::CertificateBody::getCertId() const +{ + return mCertId; +} + +void es::CertificateBody::setCertId(uint32_t id) +{ + mCertId = id; +} + +const crypto::rsa::sRsa4096Key& es::CertificateBody::getRsa4098PublicKey() const +{ + return mRsa4096PublicKey; +} + +void es::CertificateBody::setRsa4098PublicKey(const crypto::rsa::sRsa4096Key& key) +{ + mRsa4096PublicKey = key; +} + +const crypto::rsa::sRsa2048Key& es::CertificateBody::getRsa2048PublicKey() const +{ + return mRsa2048PublicKey; +} + +void es::CertificateBody::setRsa2048PublicKey(const crypto::rsa::sRsa2048Key& key) +{ + mRsa2048PublicKey = key; +} + +const crypto::ecdsa::sEcdsa240Point& es::CertificateBody::getEcdsa240PublicKey() const +{ + return mEcdsa240PublicKey; +} + +void es::CertificateBody::setEcdsa240PublicKey(const crypto::ecdsa::sEcdsa240Point& key) +{ + mEcdsa240PublicKey = key; +} + +bool es::CertificateBody::isEqual(const CertificateBody& other) const +{ + return (mIssuer == other.mIssuer) \ + && (mSubject == other.mSubject) \ + && (mCertId == other.mCertId) \ + && (mPublicKeyType == other.mPublicKeyType) \ + && (mRsa4096PublicKey == other.mRsa4096PublicKey) \ + && (mRsa2048PublicKey == other.mRsa2048PublicKey) \ + && (mEcdsa240PublicKey == other.mEcdsa240PublicKey); + +} + +void es::CertificateBody::copyFrom(const CertificateBody& other) +{ + mBinaryBlob = other.mBinaryBlob; + mIssuer = other.mIssuer; + mSubject = other.mSubject; + mCertId = other.mCertId; + mPublicKeyType = other.mPublicKeyType; + mRsa4096PublicKey = other.mRsa4096PublicKey; + mRsa2048PublicKey = other.mRsa2048PublicKey; + mEcdsa240PublicKey = other.mEcdsa240PublicKey; +}