Commit cf498f65 authored by cRTrn13's avatar cRTrn13
Browse files

AACS functional to decrypt but no AACS-Auth yet so need patched drive atm

parent 5eb86ffe
......@@ -20,7 +20,7 @@ uint8_t *configfile_record(CONFIGFILE *kf, enum configfile_types type, uint16_t
}
if (kf->buf[pos] == type) {
DEBUG(DBG_CONFIGFILE, "CONFIGFILE record 0x%02x retrieved (0x%08x)\n", type, kf->buf + pos + 10);
DEBUG(DBG_CONFIGFILE, "Retrieved CONFIGFILE record 0x%02x (0x%08x)\n", type, kf->buf + pos + 10);
return kf->buf + pos + 10; // only return ptr to first byte of entry
}
......
......@@ -51,6 +51,8 @@ int _calc_mk(AACS_KEYS *aacs, const char *path)
if (_validate_pk(aacs->pk, rec + a * 16, uvs + 1 + a * 5, mkb_mk_dv(mkb), aacs->mk)) {
mkb_close(mkb);
X_FREE(buf);
DEBUG(DBG_AACS, "Media key: %s\n", print_hex(aacs->mk, 16));
return 1;
}
}
......@@ -73,12 +75,14 @@ int _calc_vuk(AACS_KEYS *aacs, const char *path)
uint8_t vid[16];
MMC* mmc = NULL;
DEBUG(DBG_AACS, "Calculate volume unique key...\n");
if ((mmc = mmc_open(path,
configfile_record(aacs->kf, KF_HOST_PRIV_KEY, NULL, NULL),
configfile_record(aacs->kf, KF_HOST_CERT, NULL, NULL),
configfile_record(aacs->kf, KF_HOST_NONCE, NULL, NULL),
configfile_record(aacs->kf, KF_HOST_KEY_POINT, NULL, NULL)))) {
if (mmc_read_vid(mmc)) {
if (mmc_read_vid(mmc, vid)) {
AES_set_decrypt_key(aacs->mk, 128, &aes);
AES_decrypt(vid, aacs->vuk, &aes);
......@@ -88,12 +92,16 @@ int _calc_vuk(AACS_KEYS *aacs, const char *path)
mmc_close(mmc);
DEBUG(DBG_AACS, "Volume unique key: %s\n", print_hex(aacs->vuk, 16));
return 1;
}
mmc_close(mmc);
}
DEBUG(DBG_AACS, "Error calculating VUK!\n");
return 0;
}
......@@ -101,28 +109,39 @@ int _calc_uks(AACS_KEYS *aacs, const char *path)
{
AES_KEY aes;
FILE_H *fp = NULL;
unsigned char buf[16];
uint8_t buf[16];
char f_name[100];
uint64_t f_pos;
snprintf(f_name, 100, "/%s/AACS/Unit_Key_RO.inf", path);
DEBUG(DBG_AACS, "Calculate CPS unit keys...\n");
snprintf(f_name , 100, "/%s/AACS/Unit_Key_RO.inf", path);
if ((fp = file_open(f_name, "rb"))) {
file_read(fp, buf, 4);
if ((file_read(fp, buf, 4)) == 4) {
f_pos = MKINT_BE32(buf) + 48;
f_pos = MKINT_BE32(buf) + 48;
file_seek(fp, f_pos, SEEK_SET);
if ((file_read(fp, buf, 16)) == 16) {
// TODO: support more than a single UK!!!
aacs->uks = malloc(16);
file_seek(fp, f_pos, SEEK_SET);
file_read(fp, buf, 16);
AES_set_decrypt_key(aacs->vuk, 128, &aes);
AES_decrypt(buf, aacs->uks, &aes);
AES_set_decrypt_key(aacs->vuk, 128, &aes);
AES_decrypt(buf, aacs->uks, &aes);
file_close(fp);
file_close(fp);
DEBUG(DBG_AACS, "Unit key 1: %s\n", print_hex(aacs->uks, 16));
return 1;
return 1;
}
}
file_close(fp);
}
DEBUG(DBG_AACS, "Could not calculate unit keys!\n");
return 0;
}
......@@ -156,18 +175,26 @@ int _validate_pk(uint8_t *pk, uint8_t *cvalue, uint8_t *uv, uint8_t *vd, uint8_t
return 0;
}
int _verify_ts(uint8_t *buf, size_t size)
{
return 1;
}
AACS_KEYS *aacs_open(const char *path, const char *configfile_path)
{
AACS_KEYS *aacs = malloc(sizeof(AACS_KEYS));
aacs->uks = NULL;
aacs->kf = NULL;
if ((aacs->kf = configfile_open(configfile_path))) {
DEBUG(DBG_AACS, "Starting AACS waterfall...\n");
//_calc_pk(aacs);
if (_calc_mk(aacs, path)) {
if (_calc_vuk(aacs, path)) {
if (_calc_vuk(aacs, path)) {
if (_calc_uks(aacs, path)) {
DEBUG(DBG_AACS, "AACS initialized (0x%08x)!\n", aacs);
// configfile_close(aacs->kf);
DEBUG(DBG_AACS, "AACS initialized! (0x%08x)\n", aacs);
return aacs;
}
}
......@@ -179,17 +206,17 @@ AACS_KEYS *aacs_open(const char *path, const char *configfile_path)
void aacs_close(AACS_KEYS *aacs)
{
configfile_close(aacs->kf);
X_FREE(aacs->uks);
DEBUG(DBG_AACS, "AACS destroyed! (0x%08x)\n", aacs);
X_FREE(aacs);
}
int aacs_decrypt_unit(AACS_KEYS *aacs, uint8_t *buf, uint32_t len)
int aacs_decrypt_unit(AACS_KEYS *aacs, uint8_t *buf, uint32_t len, uint64_t offset)
{
if (len % 6144) {
if (offset % 6144) {
AES_cbc_encrypt(buf, buf, len, &aacs->aes, aacs->iv, 0);
return 1;
} else {
int a;
uint8_t key[16], iv[] = { 0x0b, 0xa0, 0xf8, 0xdd, 0xfe, 0xa6, 0x1f, 0xb3, 0xd8, 0xdf, 0x9f, 0x56, 0x6a, 0x05, 0x0f, 0x78 };
......@@ -204,7 +231,11 @@ int aacs_decrypt_unit(AACS_KEYS *aacs, uint8_t *buf, uint32_t len)
}
AES_set_decrypt_key(key, 128, &aacs->aes);
AES_cbc_encrypt(buf + 16, buf + 16, 6144 - 16, &aacs->aes, iv, 0);
AES_cbc_encrypt(buf + 16, buf + 16, 6144 - 16, &aacs->aes, aacs->iv, 0);
}
if (_verify_ts(buf,len)) {
DEBUG(DBG_AACS, "Decrypted %s unit [%d bytes] from offset %ld (0x%08x)\n", len % 6144 ? "PARTIAL" : "FULL", len, offset, aacs);
return 1;
}
......
......@@ -26,6 +26,6 @@ struct aacs_keys {
AACS_KEYS *aacs_open(const char *path, const char *keyfile_path);
void aacs_close(AACS_KEYS *aacs);
int aacs_decrypt_unit(AACS_KEYS *aacs, uint8_t *buf, uint32_t len);
int aacs_decrypt_unit(AACS_KEYS *aacs, uint8_t *buf, uint32_t len, uint64_t offset);
#endif /* AACS_H_ */
......@@ -9,8 +9,9 @@
#include "mmc.h"
#include "crypto.h"
#include "../util/macro.h"
#include "../file/file.h"
#include "../util/macro.h"
#include "../util/logging.h"
int _mmc_send_cmd(MMC *mmc, const uint8_t *cmd, uint8_t *buf, size_t tx, size_t rx);
void _mmc_report_key(MMC *mmc, uint8_t agid, uint32_t addr, uint8_t blocks, uint8_t format, uint8_t *buf, uint16_t len);
......@@ -19,43 +20,51 @@ void _mmc_send_key(MMC *mmc, uint8_t agid, uint8_t format, uint8_t *buf, uint16_
int _mmc_send_cmd(MMC *mmc, const uint8_t *cmd, uint8_t *buf, size_t tx, size_t rx)
{
if (!mmc->fd)
return -1;
struct cdrom_generic_command cgc;
struct request_sense sense;
if (mmc->fd) {
struct cdrom_generic_command cgc;
struct request_sense sense;
memset(&cgc, 0, sizeof(cgc));
memcpy(cgc.cmd, cmd, CDROM_PACKET_SIZE);
cgc.sense = &sense;
cgc.timeout = 5000;
if (buf) {
if (tx) {
cgc.data_direction = CGC_DATA_WRITE;
cgc.buflen = tx;
cgc.buffer = buf;
} else if (rx) {
cgc.data_direction = CGC_DATA_READ;
cgc.buflen = rx;
cgc.buffer = buf;
}
} else {
cgc.data_direction = CGC_DATA_NONE;
cgc.buflen = 0;
cgc.buffer = NULL;
}
memset(&cgc, 0, sizeof(cgc));
memcpy(cgc.cmd, cmd, CDROM_PACKET_SIZE);
cgc.sense = &sense;
cgc.timeout = 5000;
int a = ioctl(mmc->fd, CDROM_SEND_PACKET, &cgc);
if (buf) {
DEBUG(DBG_MMC, "Send MMC cmd %s: (0x%08x)\n", print_hex((uint8_t *)cmd, 16), mmc);
if (tx) {
cgc.data_direction = CGC_DATA_WRITE;
cgc.buflen = tx;
cgc.buffer = buf;
} else if (rx) {
cgc.data_direction = CGC_DATA_READ;
cgc.buflen = rx;
cgc.buffer = buf;
DEBUG(DBG_MMC, " Buffer: %s -> (0x%08x)\n", print_hex(buf, tx), mmc);
} else {
DEBUG(DBG_MMC, " Buffer: %s <- (0x%08x)\n", print_hex(buf, rx), mmc);
}
} else {
cgc.data_direction = CGC_DATA_NONE;
cgc.buflen = 0;
cgc.buffer = NULL;
}
int a = ioctl(mmc->fd, CDROM_SEND_PACKET, &cgc);
mmc->sk = sense.sense_key & 0x0f;
mmc->asc = sense.asc;
mmc->ascq = sense.ascq;
mmc->sk = sense.sense_key & 0x0f;
mmc->asc = sense.asc;
mmc->ascq = sense.ascq;
if (a) {
DEBUG(DBG_MMC, " Send succeeded! (0x%08x)\n", print_hex(buf, tx), mmc);
return 1;
}
}
if (a<0)
return -1;
else
return 0;
return 0;
}
void _mmc_report_key(MMC *mmc, uint8_t agid, uint32_t addr, uint8_t blocks, uint8_t format, uint8_t *buf, uint16_t len)
......@@ -64,6 +73,8 @@ void _mmc_report_key(MMC *mmc, uint8_t agid, uint32_t addr, uint8_t blocks, uint
memset(cmd, 0, 16);
memset(buf, 0, len);
DEBUG(DBG_MMC, "MMC report key... (0x%08x)\n", mmc);
cmd[0] = 0xa4;
cmd[2] = (addr >> 24) & 0xff;
cmd[3] = (addr >> 16) & 0xff;
......@@ -83,6 +94,8 @@ void _mmc_send_key(MMC *mmc, uint8_t agid, uint8_t format, uint8_t *buf, uint16_
uint8_t cmd[16];
memset(cmd, 0, 16);
DEBUG(DBG_MMC, "MMC send key... (0x%08x)\n", mmc);
cmd[0] = 0xa3;
cmd[7] = 0x02;
cmd[8] = (len >> 8) & 0xff;
......@@ -103,12 +116,16 @@ MMC *mmc_open(const char *path, uint8_t *host_priv_key, uint8_t *host_cert, uint
memcpy(mmc->host_nonce, host_nonce, 20);
memcpy(mmc->host_key_point, host_key_point, 40);
DEBUG(DBG_MMC, "Opening MMC drive... (0x%08x)\n", mmc);
if ((proc_mounts->internal = setmntent("/proc/mounts", "r"))) {
while ((mount_entry = getmntent(proc_mounts->internal)) != NULL)
if (strcmp(mount_entry->mnt_dir, path) == 0) {
int a = open(mount_entry->mnt_fsname, O_RDONLY | O_NONBLOCK);
if (a >= 0) {
mmc->fd = a;
DEBUG(DBG_MMC, "MMC drive opened - fd: %d (0x%08x)\n", a, mmc);
}
}
}
......@@ -125,10 +142,12 @@ void mmc_close(MMC *mmc)
if (mmc->fd)
close(mmc->fd);
DEBUG(DBG_MMC, "Closed MMC drive (0x%08x)\n", mmc);
X_FREE(mmc);
}
int mmc_read_vid(MMC *mmc)
int mmc_read_vid(MMC *mmc, uint8_t *vid)
{
int a;
uint8_t agid, buf[116], cmd[16], hkp[40], hks[40], dn[20], dc[92], dkp[40], dks[40];
......@@ -137,6 +156,8 @@ int mmc_read_vid(MMC *mmc)
memset(hks, 0, 40);
memset(buf, 0, 116);
DEBUG(DBG_MMC, "Reading VID from drive... (0x%08x)\n", mmc);
for (a = 0; a < 4; a++) {
_mmc_report_key(mmc, a, 0, 0, 0x3f, buf, 2);
}
......@@ -144,7 +165,7 @@ int mmc_read_vid(MMC *mmc)
_mmc_report_key(mmc, 0, 0, 0, 0, buf, 8);
agid = (buf[7] & 0xff) >> 6;
int patched = 0; //todo: get rid of this
int patched = 1; //todo: get rid of this
if (!patched) {
memset(buf, 0, 116);
buf[1] = 0x72;
......@@ -181,10 +202,14 @@ int mmc_read_vid(MMC *mmc)
cmd[10] = (agid << 6) & 0xc0;
if (_mmc_send_cmd(mmc, cmd, buf, 0, 36) == 0) {
memcpy(mmc->vid, buf + 4, 16);
memcpy(vid, buf + 4, 16);
DEBUG(DBG_MMC, "VID: %s (0x%08x)\n", print_hex(vid, 16), mmc);
return 1;
}
DEBUG(DBG_MMC, "Unable to read VID from drive! (0x%08x)\n", mmc);
return 0;
}
......@@ -9,12 +9,11 @@ typedef struct mmc MMC;
struct mmc {
int fd;
uint8_t sk, asc, ascq;
uint8_t vid[16];
uint8_t host_priv_key[10], host_cert[92], host_nonce[20], host_key_point[40];
};
MMC *mmc_open(const char *path, uint8_t *host_priv_key, uint8_t *host_cert, uint8_t *host_nonce, uint8_t *host_key_point);
void mmc_close(MMC *drive);
int mmc_read_vid(MMC *drive);
int mmc_read_vid(MMC *mmc, uint8_t *vid);
#endif /* MMC_H_ */
......@@ -13,6 +13,7 @@ enum {
DBG_FILE = 4,
DBG_AACS = 8,
DBG_MKB = 16,
DBG_MMC = 32
} debug_mask;
char *print_hex(uint8_t *str, int count);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment