IOSC: Implement ImportCertificate

Same as VerifyPublicKeySign, we currently only support RSA keys
(which is all we need right now).
This commit is contained in:
Léo Lam 2017-06-10 16:54:49 +02:00
parent 1a8144c702
commit 4a3537285b
2 changed files with 80 additions and 0 deletions

View file

@ -19,6 +19,7 @@
#include "Common/Crypto/AES.h"
#include "Common/Crypto/ec.h"
#include "Common/ScopeGuard.h"
#include "Common/Swap.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IOSC.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, &parameters);
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
{
const KeyEntry* entry = FindEntry(handle);

View file

@ -187,6 +187,8 @@ public:
ReturnCode VerifyPublicKeySign(const std::array<u8, 20>& sha1, Handle signer_handle,
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
ReturnCode GetOwnership(Handle handle, u32* owner) const;