static void build_header(void) { u32 i; memset(hdr, 0, sizeof hdr); memcpy(hdr, "SCEUF\0\0\0", 8); wbe64(hdr + 0x08, 1); wbe64(hdr + 0x10, 0xf411); wbe64(hdr + 0x18, n_files); wbe64(hdr + 0x20, 0x50 + n_files * 0x40); wbe64(hdr + 0x28, data_size); for (i = 0; i < n_files; i++) { wbe64(hdr + 0x30 + 0x20 * i + 0x00, files[i].id); wbe64(hdr + 0x30 + 0x20 * i + 0x08, files[i].offset); wbe64(hdr + 0x30 + 0x20 * i + 0x10, files[i].len); wbe64(hdr + 0x30 + 0x20 * i + 0x18, 0); wbe64(hdr + 0x30 + 0x20 * n_files + 0x20 * i, i); calc_hmac(files[i].ptr, files[i].len, hdr + 0x30 + 0x20 * n_files + 0x20 * i + 0x08); } calc_hmac(hdr, 0x30 + 0x40 * n_files, hdr + 0x30 + 0x40 * n_files); }
static int datablob_hmac_append(struct encrypted_key_payload *epayload, const u8 *master_key, size_t master_keylen) { u8 derived_key[HASH_SIZE]; u8 *digest; int ret; ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen); if (ret < 0) goto out; digest = epayload->format + epayload->datablob_len; ret = calc_hmac(digest, derived_key, sizeof derived_key, epayload->format, epayload->datablob_len); if (!ret) dump_hmac(NULL, digest, HASH_SIZE); out: return ret; }
/* test HMAC */ int verify_hmac(const void *data, size_t datalen, int hid, unsigned char *hmac, char *key, int keylen) { unsigned char *our_hmac; int rc; our_hmac = malloc(gcry_md_get_algo_dlen(hid)); if (!our_hmac) return -1; rc = calc_hmac(data, datalen, hid, our_hmac, key, keylen); if (rc) goto out_free; rc = memcmp(our_hmac, hmac, gcry_md_get_algo_dlen(hid)); out_free: if (our_hmac) free(our_hmac); return rc; }
/* verify HMAC before decrypting encrypted key */ static int datablob_hmac_verify(struct encrypted_key_payload *epayload, const u8 *format, const u8 *master_key, size_t master_keylen) { u8 derived_key[HASH_SIZE]; u8 digest[HASH_SIZE]; int ret; char *p; unsigned short len; ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen); if (ret < 0) goto out; len = epayload->datablob_len; if (!format) { p = epayload->master_desc; len -= strlen(epayload->format) + 1; } else p = epayload->format; ret = calc_hmac(digest, derived_key, sizeof derived_key, p, len); if (ret < 0) goto out; ret = memcmp(digest, epayload->format + epayload->datablob_len, sizeof digest); if (ret) { ret = -EINVAL; dump_hmac("datablob", epayload->format + epayload->datablob_len, HASH_SIZE); dump_hmac("calc", digest, HASH_SIZE); } out: return ret; }