Certificate provide signature verification call

This commit is contained in:
luigoalma 2021-05-06 16:58:43 +01:00 committed by d0k3
parent be289b4c55
commit 4b5ac1a8e0
4 changed files with 73 additions and 32 deletions

View File

@ -1,5 +1,6 @@
#include "cert.h" #include "cert.h"
#include "disadiff.h" #include "disadiff.h"
#include "rsa.h"
typedef struct { typedef struct {
char magic[4]; // "CERT" char magic[4]; // "CERT"
@ -230,6 +231,73 @@ u32 Certificate_GetFullSize(const Certificate* cert, u32* size) {
return 0; return 0;
} }
static inline u32 _Certificate_KeytypeSignatureSize(u32 keytype) {
if (keytype == 0)
return 0x200;
else if (keytype == 1)
return 0x100;
else if (keytype == 2)
return 0x3C;
return 0;
}
static inline u32 _Certificate_VerifyRSA4096(const Certificate* cert, const void* sig, const void* data, u32 data_size, bool sha256) {
(void)cert; (void)sig; (void)data; (void)data_size; (void)sha256;
return 2; // not implemented
}
// noipa, to avoid form of inlining, cloning, etc, to avoid the extra stack usage when unneeded
static __attribute__((noipa)) bool _Certificate_SetKey2048Misaligned(const Certificate* cert) {
u32 mod[2048/8];
u32 exp;
memcpy(mod, cert->data->pub_key_data, 2048/8);
exp = getle32(&cert->data->pub_key_data[2048/8]);
return RSA_setKey2048(3, mod, exp);
}
static inline u32 _Certificate_VerifyRSA2048(const Certificate* cert, const void* sig, const void* data, u32 data_size, bool sha256) {
if (!sha256)
return 2; // not implemented
int ret;
if (((u32)&cert->data->pub_key_data[0]) & 0x3)
ret = !_Certificate_SetKey2048Misaligned(cert);
else
ret = !RSA_setKey2048(3, (const u32*)(const void*)&cert->data->pub_key_data[0], getle32(&cert->data->pub_key_data[2048/8]));
if (ret)
return ret;
return !RSA_verify2048(sig, data, data_size);
}
static inline u32 _Certificate_VerifyECC(const Certificate* cert, const void* sig, const void* data, u32 data_size, bool sha256) {
(void)cert; (void)sig; (void)data; (void)data_size; (void)sha256;
return 2; // not implemented
}
u32 Certificate_VerifySignatureBlock(const Certificate* cert, const void* sig, u32 sig_size, const void* data, u32 data_size, bool sha256) {
if (!sig || !sig_size || (!data && data_size) || !Certificate_IsValid(cert))
return 1;
u32 keytype = getbe32(cert->data->keytype);
u32 _sig_size = _Certificate_KeytypeSignatureSize(keytype);
if (sig_size != _sig_size)
return 1;
if (keytype == 0)
return _Certificate_VerifyRSA4096(cert, sig, data, data_size, sha256);
if (keytype == 1)
return _Certificate_VerifyRSA2048(cert, sig, data, data_size, sha256);
if (keytype == 2)
return _Certificate_VerifyECC(cert, sig, data, data_size, sha256);
return 1;
}
static u32 _Certificate_AllocCopyOutImpl(const Certificate* cert, Certificate* out_cert) { static u32 _Certificate_AllocCopyOutImpl(const Certificate* cert, Certificate* out_cert) {
u32 sig_size = _Certificate_GetSignatureChunkSizeFromType(getbe32(cert->sig->sig_type)); u32 sig_size = _Certificate_GetSignatureChunkSizeFromType(getbe32(cert->sig->sig_type));
u32 data_size = _Certificate_GetDataChunkSizeFromType(getbe32(cert->data->keytype)); u32 data_size = _Certificate_GetDataChunkSizeFromType(getbe32(cert->data->keytype));

View File

@ -43,6 +43,7 @@ u32 Certificate_GetEccXY(const Certificate* cert, void* X, void* Y);
u32 Certificate_GetSignatureChunkSize(const Certificate* cert, u32* size); u32 Certificate_GetSignatureChunkSize(const Certificate* cert, u32* size);
u32 Certificate_GetDataChunkSize(const Certificate* cert, u32* size); u32 Certificate_GetDataChunkSize(const Certificate* cert, u32* size);
u32 Certificate_GetFullSize(const Certificate* cert, u32* size); u32 Certificate_GetFullSize(const Certificate* cert, u32* size);
u32 Certificate_VerifySignatureBlock(const Certificate* cert, const void* sig, u32 sig_size, const void* data, u32 data_size, bool sha256);
u32 Certificate_AllocCopyOut(const Certificate* cert, Certificate* out_cert); u32 Certificate_AllocCopyOut(const Certificate* cert, Certificate* out_cert);
u32 Certificate_RawCopy(const Certificate* cert, void* raw); u32 Certificate_RawCopy(const Certificate* cert, void* raw);
u32 Certificate_Cleanup(Certificate* cert); u32 Certificate_Cleanup(Certificate* cert);

View File

@ -29,30 +29,16 @@ u32 ValidateTwlTicket(Ticket* ticket) {
u32 ValidateTicketSignature(Ticket* ticket) { u32 ValidateTicketSignature(Ticket* ticket) {
Certificate cert; Certificate cert;
u32 mod[2048/8];
u32 exp = 0;
// grab cert from certs.db // grab cert from certs.db
if (LoadCertFromCertDb(&cert, (char*)(ticket->issuer)) != 0) if (LoadCertFromCertDb(&cert, (char*)(ticket->issuer)) != 0)
return 1; return 1;
// current code only expects RSA2048 int ret = Certificate_VerifySignatureBlock(&cert, &(ticket->signature), 0x100, (void*)&(ticket->issuer), GetTicketSize(ticket) - 0x140, true);
u32 mod_size;
if (Certificate_GetModulusSize(&cert, &mod_size) != 0 ||
mod_size != 2048/8 ||
Certificate_GetModulus(&cert, &mod) != 0 ||
Certificate_GetExponent(&cert, &exp) != 0) {
Certificate_Cleanup(&cert);
return 1;
}
Certificate_Cleanup(&cert); Certificate_Cleanup(&cert);
if (!RSA_setKey2048(3, mod, exp) || return ret;
!RSA_verify2048((void*) &(ticket->signature), (void*) &(ticket->issuer), GetTicketSize(ticket) - 0x140))
return 1;
return 0;
} }
u32 BuildFakeTicket(Ticket* ticket, u8* title_id) { u32 BuildFakeTicket(Ticket* ticket, u8* title_id) {

View File

@ -25,30 +25,16 @@ u32 ValidateTwlTmd(TitleMetaData* tmd) {
u32 ValidateTmdSignature(TitleMetaData* tmd) { u32 ValidateTmdSignature(TitleMetaData* tmd) {
Certificate cert; Certificate cert;
u32 mod[2048/8];
u32 exp = 0;
// grab cert from certs.db // grab cert from certs.db
if (LoadCertFromCertDb(&cert, (char*)(tmd->issuer)) != 0) if (LoadCertFromCertDb(&cert, (char*)(tmd->issuer)) != 0)
return 1; return 1;
// current code only expects RSA2048 int ret = Certificate_VerifySignatureBlock(&cert, &(tmd->signature), 0x100, (void*)&(tmd->issuer), 0xC4, true);
u32 mod_size;
if (Certificate_GetModulusSize(&cert, &mod_size) != 0 ||
mod_size != 2048/8 ||
Certificate_GetModulus(&cert, &mod) != 0 ||
Certificate_GetExponent(&cert, &exp) != 0) {
Certificate_Cleanup(&cert);
return 1;
}
Certificate_Cleanup(&cert); Certificate_Cleanup(&cert);
if (!RSA_setKey2048(3, mod, exp) || return ret;
!RSA_verify2048((void*) &(tmd->signature), (void*) &(tmd->issuer), 0xC4))
return 1;
return 0;
} }
u32 VerifyTmd(TitleMetaData* tmd) { u32 VerifyTmd(TitleMetaData* tmd) {