mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-09-21 11:51:48 +02:00
IOSC: Implement ImportCertificate
Same as VerifyPublicKeySign, we currently only support RSA keys (which is all we need right now).
This commit is contained in:
parent
1a8144c702
commit
4a3537285b
2 changed files with 80 additions and 0 deletions
|
@ -19,6 +19,7 @@
|
||||||
#include "Common/Crypto/AES.h"
|
#include "Common/Crypto/AES.h"
|
||||||
#include "Common/Crypto/ec.h"
|
#include "Common/Crypto/ec.h"
|
||||||
#include "Common/ScopeGuard.h"
|
#include "Common/ScopeGuard.h"
|
||||||
|
#include "Common/Swap.h"
|
||||||
#include "Core/IOS/Device.h"
|
#include "Core/IOS/Device.h"
|
||||||
#include "Core/IOS/IOSC.h"
|
#include "Core/IOS/IOSC.h"
|
||||||
#include "Core/ec_wii.h"
|
#include "Core/ec_wii.h"
|
||||||
|
@ -243,6 +244,83 @@ ReturnCode IOSC::VerifyPublicKeySign(const std::array<u8, 20>& sha1, Handle sign
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ImportCertParameters
|
||||||
|
{
|
||||||
|
size_t offset;
|
||||||
|
size_t size;
|
||||||
|
size_t signature_offset;
|
||||||
|
size_t public_key_offset;
|
||||||
|
size_t public_key_exponent_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
static ReturnCode GetImportCertParameters(const u8* cert, ImportCertParameters* parameters)
|
||||||
|
{
|
||||||
|
// TODO: Add support for ECC signature type.
|
||||||
|
const u32 signature_type = Common::swap32(cert + offsetof(Cert, type));
|
||||||
|
switch (static_cast<SignatureType>(signature_type))
|
||||||
|
{
|
||||||
|
case SignatureType::RSA2048:
|
||||||
|
{
|
||||||
|
const u32 key_type = Common::swap32(cert + offsetof(Cert, rsa2048.header.public_key_type));
|
||||||
|
|
||||||
|
// TODO: Add support for ECC public key type.
|
||||||
|
if (static_cast<PublicKeyType>(key_type) != PublicKeyType::RSA2048)
|
||||||
|
return IOSC_INVALID_FORMAT;
|
||||||
|
|
||||||
|
parameters->offset = offsetof(Cert, rsa2048.signature.issuer);
|
||||||
|
parameters->size = sizeof(Cert::rsa2048) - parameters->offset;
|
||||||
|
parameters->signature_offset = offsetof(Cert, rsa2048.signature.sig);
|
||||||
|
parameters->public_key_offset = offsetof(Cert, rsa2048.public_key);
|
||||||
|
parameters->public_key_exponent_offset = offsetof(Cert, rsa2048.exponent);
|
||||||
|
return IPC_SUCCESS;
|
||||||
|
}
|
||||||
|
case SignatureType::RSA4096:
|
||||||
|
{
|
||||||
|
parameters->offset = offsetof(Cert, rsa4096.signature.issuer);
|
||||||
|
parameters->size = sizeof(Cert::rsa4096) - parameters->offset;
|
||||||
|
parameters->signature_offset = offsetof(Cert, rsa4096.signature.sig);
|
||||||
|
parameters->public_key_offset = offsetof(Cert, rsa4096.public_key);
|
||||||
|
parameters->public_key_exponent_offset = offsetof(Cert, rsa4096.exponent);
|
||||||
|
return IPC_SUCCESS;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
WARN_LOG(IOS, "Unknown signature type: %08x", signature_type);
|
||||||
|
return IOSC_INVALID_FORMAT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnCode IOSC::ImportCertificate(const u8* cert, Handle signer_handle, Handle dest_handle,
|
||||||
|
u32 pid)
|
||||||
|
{
|
||||||
|
if (!HasOwnership(signer_handle, pid) || !HasOwnership(dest_handle, pid))
|
||||||
|
return IOSC_EACCES;
|
||||||
|
|
||||||
|
const KeyEntry* signer_entry = FindEntry(signer_handle, SearchMode::IncludeRootKey);
|
||||||
|
const KeyEntry* dest_entry = FindEntry(dest_handle, SearchMode::IncludeRootKey);
|
||||||
|
if (!signer_entry || !dest_entry)
|
||||||
|
return IOSC_EINVAL;
|
||||||
|
|
||||||
|
if (signer_entry->type != TYPE_PUBLIC_KEY || dest_entry->type != TYPE_PUBLIC_KEY)
|
||||||
|
return IOSC_INVALID_OBJTYPE;
|
||||||
|
|
||||||
|
ImportCertParameters parameters;
|
||||||
|
const ReturnCode ret = GetImportCertParameters(cert, ¶meters);
|
||||||
|
if (ret != IPC_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
std::array<u8, 20> sha1;
|
||||||
|
mbedtls_sha1(cert + parameters.offset, parameters.size, sha1.data());
|
||||||
|
|
||||||
|
if (VerifyPublicKeySign(sha1, signer_handle, cert + parameters.signature_offset, pid) !=
|
||||||
|
IPC_SUCCESS)
|
||||||
|
{
|
||||||
|
return IOSC_FAIL_CHECKVALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ImportPublicKey(dest_handle, cert + parameters.public_key_offset,
|
||||||
|
cert + parameters.public_key_exponent_offset, pid);
|
||||||
|
}
|
||||||
|
|
||||||
ReturnCode IOSC::GetOwnership(Handle handle, u32* owner) const
|
ReturnCode IOSC::GetOwnership(Handle handle, u32* owner) const
|
||||||
{
|
{
|
||||||
const KeyEntry* entry = FindEntry(handle);
|
const KeyEntry* entry = FindEntry(handle);
|
||||||
|
|
|
@ -187,6 +187,8 @@ public:
|
||||||
|
|
||||||
ReturnCode VerifyPublicKeySign(const std::array<u8, 20>& sha1, Handle signer_handle,
|
ReturnCode VerifyPublicKeySign(const std::array<u8, 20>& sha1, Handle signer_handle,
|
||||||
const u8* signature, u32 pid) const;
|
const u8* signature, u32 pid) const;
|
||||||
|
// Import a certificate (signed by the certificate in signer_handle) into dest_handle.
|
||||||
|
ReturnCode ImportCertificate(const u8* cert, Handle signer_handle, Handle dest_handle, u32 pid);
|
||||||
|
|
||||||
// Ownership
|
// Ownership
|
||||||
ReturnCode GetOwnership(Handle handle, u32* owner) const;
|
ReturnCode GetOwnership(Handle handle, u32* owner) const;
|
||||||
|
|
Loading…
Reference in a new issue