forked from Mirror/GodMode9
Make cert bundle building nicer
At least in the caller perspective. Also break down some functionalities into separate funcs, interally calling them on cert.c to avoid too many checks. And tried to avoid too much repeated code.
This commit is contained in:
parent
1f96b5e9e6
commit
3bfb9ef6ec
@ -8,7 +8,7 @@ typedef struct {
|
|||||||
u8 garbage[4]; // literally garbage values
|
u8 garbage[4]; // literally garbage values
|
||||||
} PACKED_STRUCT CertsDbPartitionHeader;
|
} PACKED_STRUCT CertsDbPartitionHeader;
|
||||||
|
|
||||||
static void GetCertDBPath(char* path, bool emunand) {
|
static inline void GetCertDBPath(char* path, bool emunand) {
|
||||||
path[0] = emunand ? '4' : '1';
|
path[0] = emunand ? '4' : '1';
|
||||||
strcpy(&path[1], ":/dbs/certs.db");
|
strcpy(&path[1], ":/dbs/certs.db");
|
||||||
}
|
}
|
||||||
@ -65,6 +65,8 @@ static struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline void _Certificate_CleanupImpl(Certificate* cert);
|
||||||
|
|
||||||
bool Certificate_IsValid(const Certificate* cert) {
|
bool Certificate_IsValid(const Certificate* cert) {
|
||||||
if (!cert || !cert->sig || !cert->data)
|
if (!cert || !cert->sig || !cert->data)
|
||||||
return false;
|
return false;
|
||||||
@ -228,9 +230,34 @@ u32 Certificate_GetFullSize(const Certificate* cert, u32* size) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Certificate_RawCopy(const Certificate* cert, void* raw) {
|
static u32 _Certificate_AllocCopyOutImpl(const Certificate* cert, Certificate* out_cert) {
|
||||||
if (!raw || !Certificate_IsValid(cert)) return 1;
|
u32 sig_size = _Certificate_GetSignatureChunkSizeFromType(getbe32(cert->sig->sig_type));
|
||||||
|
u32 data_size = _Certificate_GetDataChunkSizeFromType(getbe32(cert->data->keytype));
|
||||||
|
|
||||||
|
if (sig_size == 0 || data_size == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
out_cert->sig = (CertificateSignature*)malloc(sig_size);
|
||||||
|
out_cert->data = (CertificateBody*)malloc(data_size);
|
||||||
|
|
||||||
|
if (!out_cert->sig || !out_cert->data) {
|
||||||
|
_Certificate_CleanupImpl(out_cert);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(out_cert->sig, cert->sig, sig_size);
|
||||||
|
memcpy(out_cert->data, cert->data, data_size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 Certificate_AllocCopyOut(const Certificate* cert, Certificate* out_cert) {
|
||||||
|
if (!out_cert || !Certificate_IsValid(cert)) return 1;
|
||||||
|
|
||||||
|
return _Certificate_AllocCopyOutImpl(cert, out_cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 _Certificate_RawCopyImpl(const Certificate* cert, void* raw) {
|
||||||
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));
|
||||||
|
|
||||||
@ -243,6 +270,12 @@ u32 Certificate_RawCopy(const Certificate* cert, void* raw) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 Certificate_RawCopy(const Certificate* cert, void* raw) {
|
||||||
|
if (!raw || !Certificate_IsValid(cert)) return 1;
|
||||||
|
|
||||||
|
return _Certificate_RawCopyImpl(cert, raw);
|
||||||
|
}
|
||||||
|
|
||||||
// ptr free check, to not free if ptr is pointing to static storage!!
|
// ptr free check, to not free if ptr is pointing to static storage!!
|
||||||
static inline void _Certificate_SafeFree(void* ptr) {
|
static inline void _Certificate_SafeFree(void* ptr) {
|
||||||
if ((u32)ptr >= (u32)&_CommonCertsStorage && (u32)ptr < (u32)&_CommonCertsStorage + sizeof(_CommonCertsStorage))
|
if ((u32)ptr >= (u32)&_CommonCertsStorage && (u32)ptr < (u32)&_CommonCertsStorage + sizeof(_CommonCertsStorage))
|
||||||
@ -251,13 +284,17 @@ static inline void _Certificate_SafeFree(void* ptr) {
|
|||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Certificate_Cleanup(Certificate* cert) {
|
static inline void _Certificate_CleanupImpl(Certificate* cert) {
|
||||||
if (!cert) return 1;
|
|
||||||
|
|
||||||
_Certificate_SafeFree(cert->sig);
|
_Certificate_SafeFree(cert->sig);
|
||||||
_Certificate_SafeFree(cert->data);
|
_Certificate_SafeFree(cert->data);
|
||||||
cert->sig = NULL;
|
cert->sig = NULL;
|
||||||
cert->data = NULL;
|
cert->data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 Certificate_Cleanup(Certificate* cert) {
|
||||||
|
if (!cert) return 1;
|
||||||
|
|
||||||
|
_Certificate_CleanupImpl(cert);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -400,11 +437,99 @@ static void _SaveToCertStorage(const Certificate* cert, u32 ident) {
|
|||||||
if (sig_size + data_size != raw_size)
|
if (sig_size + data_size != raw_size)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!Certificate_RawCopy(cert, raw_space)) {
|
if (!_Certificate_RawCopyImpl(cert, raw_space)) {
|
||||||
_CommonCertsStorage.loaded_certs_flg |= ident;
|
_CommonCertsStorage.loaded_certs_flg |= ident;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// grumble grumble, gotta avoid repeated code when possible or at least if significant enough
|
||||||
|
|
||||||
|
static u32 _DisaOpenCertDb(char (*path)[16], bool emunand, DisaDiffRWInfo* info, u8** cache, u32* offset, u32* max_offset) {
|
||||||
|
GetCertDBPath(*path, emunand);
|
||||||
|
|
||||||
|
u8* _cache = NULL;
|
||||||
|
if (GetDisaDiffRWInfo(*path, info, false) != 0) return 1;
|
||||||
|
_cache = (u8*)malloc(info->size_dpfs_lvl2);
|
||||||
|
if (!_cache) return 1;
|
||||||
|
if (BuildDisaDiffDpfsLvl2Cache(*path, info, _cache, info->size_dpfs_lvl2) != 0) {
|
||||||
|
free(_cache);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
CertsDbPartitionHeader header;
|
||||||
|
|
||||||
|
if (ReadDisaDiffIvfcLvl4(*path, info, 0, sizeof(CertsDbPartitionHeader), &header) != sizeof(CertsDbPartitionHeader)) {
|
||||||
|
free(_cache);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getbe32(header.magic) != 0x43455254 /* 'CERT' */ ||
|
||||||
|
getbe32(header.unk) != 0 ||
|
||||||
|
getle32(header.used_size) & 0xFF) {
|
||||||
|
free(_cache);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*cache = _cache;
|
||||||
|
|
||||||
|
*offset = sizeof(CertsDbPartitionHeader);
|
||||||
|
*max_offset = getle32(header.used_size) + sizeof(CertsDbPartitionHeader);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 _ProcessNextCertDbEntry(const char* path, DisaDiffRWInfo* info, Certificate* cert, u32 *full_size, char (*full_issuer)[0x41], u32* offset, u32 max_offset) {
|
||||||
|
u8 sig_type_data[4];
|
||||||
|
u8 keytype_data[4];
|
||||||
|
|
||||||
|
if (*offset + 4 > max_offset) return 1;
|
||||||
|
|
||||||
|
if (ReadDisaDiffIvfcLvl4(path, info, *offset, 4, sig_type_data) != 4)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
u32 sig_type = getbe32(sig_type_data);
|
||||||
|
|
||||||
|
if (sig_type == 0x10002 || sig_type == 0x10005) return 1; // ECC signs not allowed on db
|
||||||
|
|
||||||
|
u32 sig_size = _Certificate_GetSignatureChunkSizeFromType(sig_type);
|
||||||
|
if (sig_size == 0) return 1;
|
||||||
|
|
||||||
|
u32 keytype_off = *offset + sig_size + offsetof(CertificateBody, keytype);
|
||||||
|
if (keytype_off + 4 > max_offset) return 1;
|
||||||
|
|
||||||
|
if (ReadDisaDiffIvfcLvl4(path, info, keytype_off, 4, keytype_data) != 4)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
u32 keytype = getbe32(keytype_data);
|
||||||
|
|
||||||
|
if (keytype == 2) return 1; // ECC keys not allowed on db
|
||||||
|
|
||||||
|
u32 data_size = _Certificate_GetDataChunkSizeFromType(keytype);
|
||||||
|
if (data_size == 0) return 1;
|
||||||
|
|
||||||
|
*full_size = sig_size + data_size;
|
||||||
|
if (*offset + *full_size > max_offset) return 1;
|
||||||
|
|
||||||
|
cert->sig = (CertificateSignature*)malloc(sig_size);
|
||||||
|
cert->data = (CertificateBody*)malloc(data_size);
|
||||||
|
if (!cert->sig || !cert->data)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (ReadDisaDiffIvfcLvl4(path, info, *offset, sig_size, cert->sig) != sig_size)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (ReadDisaDiffIvfcLvl4(path, info, *offset + sig_size, data_size, cert->data) != data_size)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!Certificate_IsValid(cert))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (snprintf(*full_issuer, 0x41, "%s-%s", cert->data->issuer, cert->data->name) > 0x40)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
u32 LoadCertFromCertDb(bool emunand, Certificate* cert, const char* issuer) {
|
u32 LoadCertFromCertDb(bool emunand, Certificate* cert, const char* issuer) {
|
||||||
if (!issuer || !cert) return 1;
|
if (!issuer || !cert) return 1;
|
||||||
|
|
||||||
@ -416,34 +541,13 @@ u32 LoadCertFromCertDb(bool emunand, Certificate* cert, const char* issuer) {
|
|||||||
Certificate cert_local = {NULL, NULL};
|
Certificate cert_local = {NULL, NULL};
|
||||||
|
|
||||||
char path[16];
|
char path[16];
|
||||||
GetCertDBPath(path, emunand);
|
|
||||||
|
|
||||||
DisaDiffRWInfo info;
|
DisaDiffRWInfo info;
|
||||||
u8* cache = NULL;
|
u8* cache;
|
||||||
if (GetDisaDiffRWInfo(path, &info, false) != 0) return 1;
|
|
||||||
cache = malloc(info.size_dpfs_lvl2);
|
u32 offset, max_offset;
|
||||||
if (!cache) return 1;
|
|
||||||
if (BuildDisaDiffDpfsLvl2Cache(path, &info, cache, info.size_dpfs_lvl2) != 0) {
|
if (_DisaOpenCertDb(&path, emunand, &info, &cache, &offset, &max_offset))
|
||||||
free(cache);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
|
|
||||||
CertsDbPartitionHeader header;
|
|
||||||
|
|
||||||
if (ReadDisaDiffIvfcLvl4(path, &info, 0, sizeof(CertsDbPartitionHeader), &header) != sizeof(CertsDbPartitionHeader)) {
|
|
||||||
free(cache);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getbe32(header.magic) != 0x43455254 /* 'CERT' */ ||
|
|
||||||
getbe32(header.unk) != 0 ||
|
|
||||||
getle32(header.used_size) & 0xFF) {
|
|
||||||
free(cache);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 offset = sizeof(CertsDbPartitionHeader);
|
|
||||||
u32 max_offset = getle32(header.used_size) + sizeof(CertsDbPartitionHeader);
|
|
||||||
|
|
||||||
u32 ret = 1;
|
u32 ret = 1;
|
||||||
|
|
||||||
@ -452,52 +556,9 @@ u32 LoadCertFromCertDb(bool emunand, Certificate* cert, const char* issuer) {
|
|||||||
// so most cases of bad data, leads to giving up
|
// so most cases of bad data, leads to giving up
|
||||||
while (offset < max_offset) {
|
while (offset < max_offset) {
|
||||||
char full_issuer[0x41];
|
char full_issuer[0x41];
|
||||||
u8 sig_type_data[4];
|
u32 full_size;
|
||||||
u8 keytype_data[4];
|
|
||||||
|
|
||||||
if (offset + 4 > max_offset) break;
|
if (_ProcessNextCertDbEntry(path, &info, &cert_local, &full_size, &full_issuer, &offset, max_offset))
|
||||||
|
|
||||||
if (ReadDisaDiffIvfcLvl4(path, &info, offset, 4, sig_type_data) != 4)
|
|
||||||
break;
|
|
||||||
|
|
||||||
u32 sig_type = getbe32(sig_type_data);
|
|
||||||
|
|
||||||
if (sig_type == 0x10002 || sig_type == 0x10005) break; // ECC signs not allowed on db
|
|
||||||
|
|
||||||
u32 sig_size = _Certificate_GetSignatureChunkSizeFromType(sig_type);
|
|
||||||
if (sig_size == 0) break;
|
|
||||||
|
|
||||||
u32 keytype_off = offset + sig_size + offsetof(CertificateBody, keytype);
|
|
||||||
if (keytype_off + 4 > max_offset) break;
|
|
||||||
|
|
||||||
if (ReadDisaDiffIvfcLvl4(path, &info, keytype_off, 4, keytype_data) != 4)
|
|
||||||
break;
|
|
||||||
|
|
||||||
u32 keytype = getbe32(keytype_data);
|
|
||||||
|
|
||||||
if (keytype == 2) break; // ECC keys not allowed on db
|
|
||||||
|
|
||||||
u32 data_size = _Certificate_GetDataChunkSizeFromType(keytype);
|
|
||||||
if (data_size == 0) break;
|
|
||||||
|
|
||||||
u32 full_size = sig_size + data_size;
|
|
||||||
if (offset + full_size > max_offset) break;
|
|
||||||
|
|
||||||
cert_local.sig = (CertificateSignature*)malloc(sig_size);
|
|
||||||
cert_local.data = (CertificateBody*)malloc(data_size);
|
|
||||||
if (!cert_local.sig || !cert_local.data)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (ReadDisaDiffIvfcLvl4(path, &info, offset, sig_size, cert_local.sig) != sig_size)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (ReadDisaDiffIvfcLvl4(path, &info, offset + sig_size, data_size, cert_local.data) != data_size)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!Certificate_IsValid(&cert_local))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (snprintf(full_issuer, 0x41, "%s-%s", cert_local.data->issuer, cert_local.data->name) > 0x40)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!strcmp(full_issuer, issuer)) {
|
if (!strcmp(full_issuer, issuer)) {
|
||||||
@ -505,13 +566,13 @@ u32 LoadCertFromCertDb(bool emunand, Certificate* cert, const char* issuer) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Certificate_Cleanup(&cert_local);
|
_Certificate_CleanupImpl(&cert_local);
|
||||||
|
|
||||||
offset += full_size;
|
offset += full_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
Certificate_Cleanup(&cert_local);
|
_Certificate_CleanupImpl(&cert_local);
|
||||||
} else {
|
} else {
|
||||||
_SaveToCertStorage(&cert_local, _ident);
|
_SaveToCertStorage(&cert_local, _ident);
|
||||||
}
|
}
|
||||||
@ -521,3 +582,122 @@ u32 LoadCertFromCertDb(bool emunand, Certificate* cert, const char* issuer) {
|
|||||||
free(cache);
|
free(cache);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// I dont expect many certs on a cert bundle, so I'll cap it to 8
|
||||||
|
u32 BuildRawCertBundleFromCertDb(void* rawout, size_t* size, const char* const* cert_issuers, int count) {
|
||||||
|
if (!rawout || !size || !cert_issuers || count < 0 || count > 8) return 1;
|
||||||
|
if (!*size && count) return 1;
|
||||||
|
if (!count) { // *shrug*
|
||||||
|
*size = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
if (!cert_issuers[i])
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Certificate certs[8];
|
||||||
|
u8 certs_loaded = 0;
|
||||||
|
|
||||||
|
memset(certs, 0, sizeof(certs));
|
||||||
|
|
||||||
|
int loaded_count = 0;
|
||||||
|
|
||||||
|
// search static storage first
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
u32 _ident = _Issuer_To_StorageIdent(cert_issuers[i]);
|
||||||
|
if (_LoadFromCertStorage(&certs[i], _ident)) {
|
||||||
|
certs_loaded |= BIT(i);
|
||||||
|
++loaded_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 2 && loaded_count != count && !ret; ++i) {
|
||||||
|
Certificate cert_local = {NULL, NULL};
|
||||||
|
|
||||||
|
char path[16];
|
||||||
|
DisaDiffRWInfo info;
|
||||||
|
u8* cache;
|
||||||
|
|
||||||
|
u32 offset, max_offset;
|
||||||
|
|
||||||
|
if (_DisaOpenCertDb(&path, i ? true : false, &info, &cache, &offset, &max_offset))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
while (offset < max_offset) {
|
||||||
|
char full_issuer[0x41];
|
||||||
|
u32 full_size;
|
||||||
|
|
||||||
|
if (_ProcessNextCertDbEntry(path, &info, &cert_local, &full_size, &full_issuer, &offset, max_offset))
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (int j = 0; j < count; j++) {
|
||||||
|
if (certs_loaded & BIT(j)) continue;
|
||||||
|
if (!strcmp(full_issuer, cert_issuers[j])) {
|
||||||
|
ret = _Certificate_AllocCopyOutImpl(&cert_local, &certs[j]);
|
||||||
|
if (ret) break;
|
||||||
|
certs_loaded |= BIT(j);
|
||||||
|
++loaded_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// while at it, try to save to static storage, if applicable
|
||||||
|
u32 _ident = _Issuer_To_StorageIdent(full_issuer);
|
||||||
|
_SaveToCertStorage(&cert_local, _ident);
|
||||||
|
|
||||||
|
_Certificate_CleanupImpl(&cert_local);
|
||||||
|
|
||||||
|
if (loaded_count == count || ret) // early exit
|
||||||
|
break;
|
||||||
|
|
||||||
|
offset += full_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret && loaded_count == count) {
|
||||||
|
u8* out = (u8*)rawout;
|
||||||
|
size_t limit = *size, written = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
u32 sig_size = _Certificate_GetSignatureChunkSizeFromType(getbe32(certs[i].sig->sig_type));
|
||||||
|
u32 data_size = _Certificate_GetDataChunkSizeFromType(getbe32(certs[i].data->keytype));
|
||||||
|
|
||||||
|
if (sig_size == 0 || data_size == 0) {
|
||||||
|
ret = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 full_size = sig_size + data_size;
|
||||||
|
|
||||||
|
if (written + full_size > limit) {
|
||||||
|
ret = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_Certificate_RawCopyImpl(&certs[i], out)) {
|
||||||
|
ret = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
out += full_size;
|
||||||
|
written += full_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
*size = written;
|
||||||
|
} else {
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
if (certs_loaded & BIT(i))
|
||||||
|
_Certificate_CleanupImpl(&certs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@ -43,7 +43,9 @@ 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_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);
|
||||||
|
|
||||||
u32 LoadCertFromCertDb(bool emunand, Certificate* cert, const char* issuer);
|
u32 LoadCertFromCertDb(bool emunand, Certificate* cert, const char* issuer);
|
||||||
|
u32 BuildRawCertBundleFromCertDb(void* rawout, size_t* size, const char* const* cert_issuers, int count);
|
||||||
|
@ -60,50 +60,15 @@ u32 BuildCiaCert(u8* ciacert) {
|
|||||||
0x18, 0x83, 0xAF, 0xE0, 0xF4, 0xE5, 0x62, 0xBA, 0x69, 0xEE, 0x72, 0x2A, 0xC2, 0x4E, 0x95, 0xB3
|
0x18, 0x83, 0xAF, 0xE0, 0xF4, 0xE5, 0x62, 0xBA, 0x69, 0xEE, 0x72, 0x2A, 0xC2, 0x4E, 0x95, 0xB3
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* issuer_ca = !IS_DEVKIT ? "Root-CA00000003" : "Root-CA00000004";
|
static const char* const retail_issuers[] = {"Root-CA00000003", "Root-CA00000003-XS0000000c", "Root-CA00000003-CP0000000b"};
|
||||||
const char* issuer_xs = !IS_DEVKIT ? "Root-CA00000003-XS0000000c" : "Root-CA00000004-XS00000009";
|
static const char* const dev_issuers[] = {"Root-CA00000004", "Root-CA00000004-XS00000009", "Root-CA00000004-CP0000000a"};
|
||||||
const char* issuer_cp = !IS_DEVKIT ? "Root-CA00000003-CP0000000b" : "Root-CA00000004-CP0000000a";
|
|
||||||
|
|
||||||
// open certs.db file on SysNAND or EmuNAND
|
size_t size = CIA_CERT_SIZE;
|
||||||
Certificate cert_ca;
|
if (BuildRawCertBundleFromCertDb(ciacert, &size, !IS_DEVKIT ? retail_issuers : dev_issuers, 3) ||
|
||||||
Certificate cert_xs;
|
size != CIA_CERT_SIZE) {
|
||||||
Certificate cert_cp;
|
|
||||||
if (LoadCertFromCertDb(false, &cert_ca, issuer_ca) != 0 && LoadCertFromCertDb(true, &cert_ca, issuer_ca) != 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (LoadCertFromCertDb(false, &cert_xs, issuer_xs) != 0 && LoadCertFromCertDb(true, &cert_xs, issuer_xs) != 0) {
|
|
||||||
Certificate_Cleanup(&cert_ca);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LoadCertFromCertDb(false, &cert_cp, issuer_cp) != 0 && LoadCertFromCertDb(true, &cert_cp, issuer_cp) != 0) {
|
|
||||||
Certificate_Cleanup(&cert_ca);
|
|
||||||
Certificate_Cleanup(&cert_xs);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 cert_size_ca;
|
|
||||||
u32 cert_size_xs;
|
|
||||||
u32 cert_size_cp;
|
|
||||||
if (Certificate_GetFullSize(&cert_ca, &cert_size_ca) != 0 ||
|
|
||||||
cert_size_ca != 0x400 ||
|
|
||||||
Certificate_GetFullSize(&cert_xs, &cert_size_xs) != 0 ||
|
|
||||||
cert_size_xs != 0x300 ||
|
|
||||||
Certificate_GetFullSize(&cert_cp, &cert_size_cp) != 0 ||
|
|
||||||
cert_size_cp != 0x300 ||
|
|
||||||
Certificate_RawCopy(&cert_ca, ciacert) != 0 ||
|
|
||||||
Certificate_RawCopy(&cert_xs, &ciacert[0x400]) != 0 ||
|
|
||||||
Certificate_RawCopy(&cert_cp, &ciacert[0x700]) != 0) {
|
|
||||||
Certificate_Cleanup(&cert_ca);
|
|
||||||
Certificate_Cleanup(&cert_xs);
|
|
||||||
Certificate_Cleanup(&cert_cp);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Certificate_Cleanup(&cert_ca);
|
|
||||||
Certificate_Cleanup(&cert_xs);
|
|
||||||
Certificate_Cleanup(&cert_cp);
|
|
||||||
|
|
||||||
// check the certificate hash
|
// check the certificate hash
|
||||||
u8 cert_hash[0x20];
|
u8 cert_hash[0x20];
|
||||||
sha_quick(cert_hash, ciacert, CIA_CERT_SIZE, SHA256_MODE);
|
sha_quick(cert_hash, ciacert, CIA_CERT_SIZE, SHA256_MODE);
|
||||||
|
@ -98,36 +98,15 @@ u32 BuildTicketCert(u8* tickcert) {
|
|||||||
0xC6, 0x4B, 0xD4, 0x8F, 0xDF, 0x13, 0x21, 0x3D, 0xFC, 0x72, 0xFC, 0x8D, 0x9F, 0xDD, 0x01, 0x0E
|
0xC6, 0x4B, 0xD4, 0x8F, 0xDF, 0x13, 0x21, 0x3D, 0xFC, 0x72, 0xFC, 0x8D, 0x9F, 0xDD, 0x01, 0x0E
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* issuer_xs = !IS_DEVKIT ? "Root-CA00000003-XS0000000c" : "Root-CA00000004-XS00000009";
|
static const char* const retail_issuers[] = {"Root-CA00000003-XS0000000c", "Root-CA00000003"};
|
||||||
const char* issuer_ca = !IS_DEVKIT ? "Root-CA00000003" : "Root-CA00000004";
|
static const char* const dev_issuers[] = {"Root-CA00000004-XS00000009", "Root-CA00000004"};
|
||||||
|
|
||||||
// open certs.db file on SysNAND or EmuNAND
|
size_t size = TICKET_CDNCERT_SIZE;
|
||||||
Certificate cert_xs;
|
if (BuildRawCertBundleFromCertDb(tickcert, &size, !IS_DEVKIT ? retail_issuers : dev_issuers, 2) ||
|
||||||
Certificate cert_ca;
|
size != TICKET_CDNCERT_SIZE) {
|
||||||
if (LoadCertFromCertDb(false, &cert_xs, issuer_xs) != 0 && LoadCertFromCertDb(true, &cert_xs, issuer_xs) != 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (LoadCertFromCertDb(false, &cert_ca, issuer_ca) != 0 && LoadCertFromCertDb(true, &cert_ca, issuer_ca) != 0) {
|
|
||||||
Certificate_Cleanup(&cert_xs);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 cert_size_xs;
|
|
||||||
u32 cert_size_ca;
|
|
||||||
if (Certificate_GetFullSize(&cert_xs, &cert_size_xs) != 0 ||
|
|
||||||
cert_size_xs != 0x300 ||
|
|
||||||
Certificate_GetFullSize(&cert_ca, &cert_size_ca) != 0 ||
|
|
||||||
cert_size_ca != 0x400 ||
|
|
||||||
Certificate_RawCopy(&cert_xs, tickcert) != 0 ||
|
|
||||||
Certificate_RawCopy(&cert_ca, &tickcert[0x300]) != 0) {
|
|
||||||
Certificate_Cleanup(&cert_xs);
|
|
||||||
Certificate_Cleanup(&cert_ca);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Certificate_Cleanup(&cert_xs);
|
|
||||||
Certificate_Cleanup(&cert_ca);
|
|
||||||
|
|
||||||
// check the certificate hash
|
// check the certificate hash
|
||||||
u8 cert_hash[0x20];
|
u8 cert_hash[0x20];
|
||||||
sha_quick(cert_hash, tickcert, TICKET_CDNCERT_SIZE, SHA256_MODE);
|
sha_quick(cert_hash, tickcert, TICKET_CDNCERT_SIZE, SHA256_MODE);
|
||||||
|
@ -130,36 +130,15 @@ u32 BuildTmdCert(u8* tmdcert) {
|
|||||||
0xC2, 0xE9, 0xCA, 0x93, 0x94, 0xF4, 0x29, 0xA0, 0x38, 0x54, 0x75, 0xFF, 0xAB, 0x6E, 0x8E, 0x71
|
0xC2, 0xE9, 0xCA, 0x93, 0x94, 0xF4, 0x29, 0xA0, 0x38, 0x54, 0x75, 0xFF, 0xAB, 0x6E, 0x8E, 0x71
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* issuer_cp = !IS_DEVKIT ? "Root-CA00000003-CP0000000b" : "Root-CA00000004-CP0000000a";
|
static const char* const retail_issuers[] = {"Root-CA00000003-CP0000000b", "Root-CA00000003"};
|
||||||
const char* issuer_ca = !IS_DEVKIT ? "Root-CA00000003" : "Root-CA00000004";
|
static const char* const dev_issuers[] = {"Root-CA00000004-CP0000000a", "Root-CA00000004"};
|
||||||
|
|
||||||
// open certs.db file on SysNAND or EmuNAND
|
size_t size = TMD_CDNCERT_SIZE;
|
||||||
Certificate cert_cp;
|
if (BuildRawCertBundleFromCertDb(tmdcert, &size, !IS_DEVKIT ? retail_issuers : dev_issuers, 2) ||
|
||||||
Certificate cert_ca;
|
size != TMD_CDNCERT_SIZE) {
|
||||||
if (LoadCertFromCertDb(false, &cert_cp, issuer_cp) != 0 && LoadCertFromCertDb(true, &cert_cp, issuer_cp) != 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (LoadCertFromCertDb(false, &cert_ca, issuer_ca) != 0 && LoadCertFromCertDb(true, &cert_ca, issuer_ca) != 0) {
|
|
||||||
Certificate_Cleanup(&cert_cp);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 cert_size_cp;
|
|
||||||
u32 cert_size_ca;
|
|
||||||
if (Certificate_GetFullSize(&cert_cp, &cert_size_cp) != 0 ||
|
|
||||||
cert_size_cp != 0x300 ||
|
|
||||||
Certificate_GetFullSize(&cert_ca, &cert_size_ca) != 0 ||
|
|
||||||
cert_size_ca != 0x400 ||
|
|
||||||
Certificate_RawCopy(&cert_cp, tmdcert) != 0 ||
|
|
||||||
Certificate_RawCopy(&cert_ca, &tmdcert[0x300]) != 0) {
|
|
||||||
Certificate_Cleanup(&cert_cp);
|
|
||||||
Certificate_Cleanup(&cert_ca);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Certificate_Cleanup(&cert_cp);
|
|
||||||
Certificate_Cleanup(&cert_ca);
|
|
||||||
|
|
||||||
// check the certificate hash
|
// check the certificate hash
|
||||||
u8 cert_hash[0x20];
|
u8 cert_hash[0x20];
|
||||||
sha_quick(cert_hash, tmdcert, TMD_CDNCERT_SIZE, SHA256_MODE);
|
sha_quick(cert_hash, tmdcert, TMD_CDNCERT_SIZE, SHA256_MODE);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user