2017-08-05 13:09:50 +00:00
|
|
|
#include <nx/AcidBinary.h>
|
2017-07-17 08:21:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
nx::AcidBinary::AcidBinary()
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
nx::AcidBinary::AcidBinary(const AcidBinary & other)
|
|
|
|
{
|
|
|
|
copyFrom(other);
|
|
|
|
}
|
|
|
|
|
2018-03-22 05:26:22 +00:00
|
|
|
nx::AcidBinary::AcidBinary(const byte_t * bytes, size_t len)
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
|
|
|
importBinary(bytes, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
void nx::AcidBinary::clear()
|
|
|
|
{
|
|
|
|
AciBinary::clear();
|
|
|
|
mEmbeddedPublicKey = crypto::rsa::sRsa2048Key();
|
|
|
|
}
|
|
|
|
|
2017-07-18 14:17:32 +00:00
|
|
|
const crypto::rsa::sRsa2048Key & nx::AcidBinary::getNcaHeader2RsaKey() const
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
|
|
|
return mEmbeddedPublicKey;
|
|
|
|
}
|
|
|
|
|
2017-07-18 14:17:32 +00:00
|
|
|
void nx::AcidBinary::setNcaHeader2RsaKey(const crypto::rsa::sRsa2048Key & key)
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
|
|
|
mEmbeddedPublicKey = key;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool nx::AcidBinary::isEqual(const AcidBinary & other) const
|
|
|
|
{
|
|
|
|
return AciBinary::operator==(other) \
|
|
|
|
&& (mEmbeddedPublicKey == other.mEmbeddedPublicKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
void nx::AcidBinary::copyFrom(const AcidBinary & other)
|
|
|
|
{
|
|
|
|
if (other.getSize())
|
|
|
|
{
|
|
|
|
importBinary(other.getBytes(), other.getSize());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
AciBinary::operator=(other);
|
|
|
|
mEmbeddedPublicKey = other.mEmbeddedPublicKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool nx::AcidBinary::operator==(const AcidBinary & other) const
|
|
|
|
{
|
|
|
|
return isEqual(other);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool nx::AcidBinary::operator!=(const AcidBinary & other) const
|
|
|
|
{
|
|
|
|
return !isEqual(other);
|
|
|
|
}
|
|
|
|
|
|
|
|
void nx::AcidBinary::operator=(const AcidBinary & other)
|
|
|
|
{
|
|
|
|
copyFrom(other);
|
|
|
|
}
|
|
|
|
|
2018-03-22 05:26:22 +00:00
|
|
|
const byte_t * nx::AcidBinary::getBytes() const
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
|
|
|
return mBinaryBlob.getBytes();
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t nx::AcidBinary::getSize() const
|
|
|
|
{
|
|
|
|
return mBinaryBlob.getSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
void nx::AcidBinary::exportBinary()
|
|
|
|
{
|
|
|
|
AciBinary::setHeaderOffset(crypto::rsa::kRsa2048Size); // not include signature
|
|
|
|
AciBinary::exportBinary();
|
|
|
|
mBinaryBlob.alloc(AciBinary::getSize() + crypto::rsa::kRsa2048Size * 2);
|
|
|
|
|
|
|
|
memcpy(mBinaryBlob.getBytes() + crypto::rsa::kRsa2048Size, mEmbeddedPublicKey.modulus, crypto::rsa::kRsa2048Size);
|
|
|
|
memcpy(mBinaryBlob.getBytes() + crypto::rsa::kRsa2048Size * 2, AciBinary::getBytes(), AciBinary::getSize());
|
|
|
|
}
|
|
|
|
|
|
|
|
void nx::AcidBinary::signBinary(const crypto::rsa::sRsa2048Key & key)
|
|
|
|
{
|
|
|
|
if (mBinaryBlob.getSize() == 0)
|
|
|
|
{
|
|
|
|
exportBinary();
|
|
|
|
}
|
|
|
|
|
2018-03-22 05:26:22 +00:00
|
|
|
byte_t hash[crypto::sha::kSha256HashLen];
|
2017-07-17 08:21:39 +00:00
|
|
|
crypto::sha::Sha256(mBinaryBlob.getBytes() + crypto::rsa::kRsa2048Size, mBinaryBlob.getSize() - crypto::rsa::kRsa2048Size, hash);
|
|
|
|
|
|
|
|
if (crypto::rsa::pkcs::rsaSign(key, crypto::sha::HASH_SHA256, hash, mBinaryBlob.getBytes()) != 0)
|
|
|
|
{
|
|
|
|
throw fnd::Exception(kModuleName, "Failed to sign ACID");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-22 05:26:22 +00:00
|
|
|
void nx::AcidBinary::importBinary(const byte_t * bytes, size_t len)
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
|
|
|
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
|
|
|
|
size_t acid_size = AciBinary::getSize() + crypto::rsa::kRsa2048Size * 2;
|
|
|
|
if (acid_size > len)
|
|
|
|
{
|
|
|
|
throw fnd::Exception(kModuleName, "ACID binary too small");
|
|
|
|
}
|
|
|
|
|
|
|
|
mBinaryBlob.alloc(acid_size);
|
|
|
|
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
|
|
|
|
memcpy(mEmbeddedPublicKey.modulus, bytes + crypto::rsa::kRsa2048Size, crypto::rsa::kRsa2048Size);
|
|
|
|
}
|
|
|
|
|
|
|
|
void nx::AcidBinary::verifyBinary(const crypto::rsa::sRsa2048Key & key)
|
|
|
|
{
|
|
|
|
if (mBinaryBlob.getSize() == 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];
|
2017-07-17 08:21:39 +00:00
|
|
|
crypto::sha::Sha256(mBinaryBlob.getBytes() + crypto::rsa::kRsa2048Size, mBinaryBlob.getSize() - crypto::rsa::kRsa2048Size, hash);
|
|
|
|
|
|
|
|
if (crypto::rsa::pkcs::rsaVerify(key, crypto::sha::HASH_SHA256, hash, mBinaryBlob.getBytes()) != 0)
|
|
|
|
{
|
|
|
|
throw fnd::Exception(kModuleName, "Failed to verify ACID");
|
|
|
|
}
|
|
|
|
}
|