nstool/lib/libnx/source/AcidBinary.cpp

122 lines
3.1 KiB
C++
Raw Normal View History

#include <nx/AcidBinary.h>
nx::AcidBinary::AcidBinary()
{
clear();
}
nx::AcidBinary::AcidBinary(const AcidBinary & other)
{
2018-06-24 08:18:54 +00:00
*this = other;
}
2018-06-24 08:18:54 +00:00
bool nx::AcidBinary::operator==(const AcidBinary & other) const
{
2018-06-24 08:18:54 +00:00
return AciBinary::operator==(other) \
&& (mEmbeddedPublicKey == other.mEmbeddedPublicKey);
}
2018-06-24 08:18:54 +00:00
bool nx::AcidBinary::operator!=(const AcidBinary & other) const
{
2018-06-24 08:18:54 +00:00
return !(*this == other);
}
2018-06-24 08:18:54 +00:00
void nx::AcidBinary::operator=(const AcidBinary & other)
{
2018-06-24 08:18:54 +00:00
if (other.getBytes().size())
{
2018-06-24 08:18:54 +00:00
importBinary(other.getBytes().data(), other.getBytes().size());
}
else
{
AciBinary::operator=(other);
mEmbeddedPublicKey = other.mEmbeddedPublicKey;
}
}
2018-06-24 08:18:54 +00:00
void nx::AcidBinary::toBytes()
{
AciBinary::setHeaderOffset(crypto::rsa::kRsa2048Size); // not include signature
AciBinary::exportBinary();
2018-06-24 08:18:54 +00:00
mRawBinary.alloc(AciBinary::getBytes().size() + crypto::rsa::kRsa2048Size * 2);
2018-06-24 08:18:54 +00:00
memcpy(mRawBinary.data() + crypto::rsa::kRsa2048Size, mEmbeddedPublicKey.modulus, crypto::rsa::kRsa2048Size);
memcpy(mRawBinary.data() + crypto::rsa::kRsa2048Size * 2, AciBinary::getBytes().data(), AciBinary::getBytes().size());
}
void nx::AcidBinary::signBinary(const crypto::rsa::sRsa2048Key & key)
{
2018-06-24 08:18:54 +00:00
if (mRawBinary.size() == 0)
{
exportBinary();
}
2018-03-22 05:26:22 +00:00
byte_t hash[crypto::sha::kSha256HashLen];
2018-06-24 08:18:54 +00:00
crypto::sha::Sha256(mRawBinary.data() + crypto::rsa::kRsa2048Size, mRawBinary.size() - crypto::rsa::kRsa2048Size, hash);
2018-06-24 08:18:54 +00:00
if (crypto::rsa::pkcs::rsaSign(key, crypto::sha::HASH_SHA256, hash, mRawBinary.data()) != 0)
{
throw fnd::Exception(kModuleName, "Failed to sign ACID");
}
}
2018-06-24 08:18:54 +00:00
void nx::AcidBinary::fromBytes(const byte_t * bytes, size_t len)
{
if (len <= crypto::rsa::kRsa2048Size*2)
{
throw fnd::Exception(kModuleName, "ACID binary too small");
}
// import aci binary past sig + pubkey
AciBinary::importBinary(bytes + crypto::rsa::kRsa2048Size * 2, len - crypto::rsa::kRsa2048Size * 2);
// save internal copy
2018-06-24 08:18:54 +00:00
size_t acid_size = AciBinary::getBytes().size() + crypto::rsa::kRsa2048Size * 2;
if (acid_size > len)
{
throw fnd::Exception(kModuleName, "ACID binary too small");
}
2018-06-24 08:18:54 +00:00
mRawBinary.alloc(acid_size);
memcpy(mRawBinary.data(), bytes, mRawBinary.size());
memcpy(mEmbeddedPublicKey.modulus, bytes + crypto::rsa::kRsa2048Size, crypto::rsa::kRsa2048Size);
}
2018-04-21 09:19:41 +00:00
void nx::AcidBinary::verifyBinary(const crypto::rsa::sRsa2048Key & key) const
{
2018-06-24 08:18:54 +00:00
if (mRawBinary.size() == 0)
{
throw fnd::Exception(kModuleName, "No ACID binary exists to verify");
}
2018-03-22 05:26:22 +00:00
byte_t hash[crypto::sha::kSha256HashLen];
2018-06-24 08:18:54 +00:00
crypto::sha::Sha256(mRawBinary.data() + crypto::rsa::kRsa2048Size, mRawBinary.size() - crypto::rsa::kRsa2048Size, hash);
2018-06-24 08:18:54 +00:00
if (crypto::rsa::pss::rsaVerify(key, crypto::sha::HASH_SHA256, hash, mRawBinary.data()) != 0)
{
throw fnd::Exception(kModuleName, "Failed to verify ACID");
}
}
2018-06-24 08:18:54 +00:00
const fnd::Vec<byte_t>& nx::AcidBinary::getBytes() const
{
return mRawBinary;
}
void nx::AcidBinary::clear()
{
AciBinary::clear();
mRawBinary.clear();
mEmbeddedPublicKey = crypto::rsa::sRsa2048Key();
}
const crypto::rsa::sRsa2048Key & nx::AcidBinary::getNcaHeader2RsaKey() const
{
return mEmbeddedPublicKey;
}
void nx::AcidBinary::setNcaHeader2RsaKey(const crypto::rsa::sRsa2048Key & key)
{
mEmbeddedPublicKey = key;
}