aacs.c 35.4 KB
Newer Older
1 2
/*
 * This file is part of libaacs
3
 * Copyright (C) 2009-2010  Obliter0n
4
 * Copyright (C) 2009-2013  npzacs
5
 *
gates's avatar
gates committed
6 7 8 9
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
10
 *
gates's avatar
gates committed
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
gates's avatar
gates committed
13 14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
15
 *
gates's avatar
gates committed
16 17 18
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see
 * <http://www.gnu.org/licenses/>.
19 20
 */

npzacs's avatar
npzacs committed
21 22 23 24
#if HAVE_CONFIG_H
#include "config.h"
#endif

npzacs's avatar
npzacs committed
25
#include "util/attributes.h"
npzacs's avatar
npzacs committed
26

npzacs's avatar
npzacs committed
27
#include "aacs-version.h"
cRTrn13's avatar
cRTrn13 committed
28
#include "aacs.h"
29
#include "crypto.h"
cRTrn13's avatar
cRTrn13 committed
30
#include "mmc.h"
31
#include "mkb.h"
gates's avatar
gates committed
32
#include "file/file.h"
gates's avatar
gates committed
33
#include "file/keydbcfg.h"
34 35
#include "util/macro.h"
#include "util/logging.h"
36
#include "util/strutl.h"
cRTrn13's avatar
cRTrn13 committed
37

38
#include <inttypes.h>
39
#include <string.h>
40
#include <stdio.h>
npzacs's avatar
npzacs committed
41 42 43
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
44
#include <gcrypt.h>
45

npzacs's avatar
npzacs committed
46

npzacs's avatar
npzacs committed
47 48 49 50
#define SECTOR_LEN       2048  /* bus encryption block size */
#define ALIGNED_UNIT_LEN 6144  /* aacs block size */


npzacs's avatar
npzacs committed
51
struct aacs {
npzacs's avatar
npzacs committed
52 53 54
    void           *fopen_handle;
    AACS_FILE_OPEN2 fopen;

npzacs's avatar
npzacs committed
55 56 57 58 59
    /* current disc */
    char     *path;
    int       mkb_version;
    uint8_t   disc_id[20];

60 61
    /* VID is cached for BD-J */
    uint8_t   vid[16];
62 63
    /* PMSN is cached for BD-J */
    uint8_t   pmsn[16];
npzacs's avatar
npzacs committed
64 65
    /* Media key is cached for BD+ */
    uint8_t   mk[16];
npzacs's avatar
npzacs committed
66 67 68 69

    /* unit key for each CPS unit */
    uint32_t  num_uks;
    uint8_t  *uks;
npzacs's avatar
npzacs committed
70

npzacs's avatar
npzacs committed
71 72
    /* CPS unit of currently selected title */
    uint16_t  current_cps_unit;
73
    uint8_t   cps_unit_selected;
npzacs's avatar
npzacs committed
74 75 76 77

    /* title -> CPS unit mappings */
    uint32_t  num_titles;
    uint16_t *cps_units;  /* [0] = first play ; [1] = top menu ; [2] = title 1 ... */
78 79 80 81

    /* bus encryption */
    int       bee;        /* bus encryption enabled flag in content certificate */
    int       bec;        /* bus encryption capable flag in drive certificate */
82
    uint8_t   read_data_key[16];
83 84 85 86

    /* AACS Online (BD-J) */
    uint8_t   device_nonce[16];
    uint8_t   device_binding_id[16];
npzacs's avatar
npzacs committed
87 88
};

89 90 91 92
static const uint8_t empty_key[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const uint8_t aacs_iv[16]   = { 0x0b, 0xa0, 0xf8, 0xdd, 0xfe, 0xa6, 0x1f, 0xb3,
                                       0xd8, 0xdf, 0x9f, 0x56, 0x6a, 0x05, 0x0f, 0x78 };
93

94 95
static int _validate_pk(const uint8_t *pk,
                        const uint8_t *cvalue, const uint8_t *uv, const uint8_t *vd,
npzacs's avatar
npzacs committed
96
                        uint8_t *mk)
cRTrn13's avatar
cRTrn13 committed
97
{
98
    gcry_cipher_hd_t gcry_h;
npzacs's avatar
npzacs committed
99
    int a;
cRTrn13's avatar
cRTrn13 committed
100
    uint8_t dec_vd[16];
101
    char str[40];
cRTrn13's avatar
cRTrn13 committed
102

npzacs's avatar
npzacs committed
103 104 105 106 107
    BD_DEBUG(DBG_AACS, "Validate processing key %s...\n", print_hex(str, pk, 16));
    BD_DEBUG(DBG_AACS, " Using:\n");
    BD_DEBUG(DBG_AACS, "   UV: %s\n", print_hex(str, uv, 4));
    BD_DEBUG(DBG_AACS, "   cvalue: %s\n", print_hex(str, cvalue, 16));
    BD_DEBUG(DBG_AACS, "   Verification data: %s\n", print_hex(str, vd, 16));
108

109 110 111
    gcry_cipher_open(&gcry_h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0);
    gcry_cipher_setkey(gcry_h, pk, 16);
    gcry_cipher_decrypt(gcry_h, mk, 16, cvalue, 16);
112

cRTrn13's avatar
cRTrn13 committed
113 114 115 116
    for (a = 0; a < 4; a++) {
        mk[a + 12] ^= uv[a];
    }

117 118 119
    gcry_cipher_setkey(gcry_h, mk, 16);
    gcry_cipher_decrypt (gcry_h, dec_vd, 16, vd, 16);
    gcry_cipher_close(gcry_h);
120

cRTrn13's avatar
cRTrn13 committed
121
    if (!memcmp(dec_vd, "\x01\x23\x45\x67\x89\xAB\xCD\xEF", 8)) {
npzacs's avatar
npzacs committed
122
        BD_DEBUG(DBG_AACS, "Processing key %s is valid!\n", print_hex(str, pk, 16));
npzacs's avatar
npzacs committed
123
        return AACS_SUCCESS;
cRTrn13's avatar
cRTrn13 committed
124 125
    }

npzacs's avatar
npzacs committed
126
    return AACS_ERROR_NO_PK;
cRTrn13's avatar
cRTrn13 committed
127
}
128

129 130 131 132 133 134
static int _rl_verify_signature(const uint8_t *rl, size_t size)
{
    int    entries = MKINT_BE32(rl + 12 + 8);
    size_t len     = 12 + 12 + 8 * entries; /* type_and_version_rec=12, rl_header=12, rl=entries*8 */

    if (len + 40 > size) {
npzacs's avatar
npzacs committed
135
        BD_DEBUG(DBG_AACS, "revocation list size mismatch\n");
136 137 138 139 140 141
        return 0;
    }

    return crypto_aacs_verify_aacsla(rl + len, rl, len);
}

142 143 144 145 146 147
static void _save_rl(const char *name, uint32_t version, const uint8_t *version_rec,
                     const uint8_t *rl_rec, size_t rl_len)
{
    int len     = MKINT_BE24(rl_rec - 3);
    int entries = MKINT_BE32(rl_rec + 4); /* entries in first signature block */
    if (len < 4 || !entries) {
npzacs's avatar
npzacs committed
148
        BD_DEBUG(DBG_AACS | DBG_CRIT, "ignoring empty %s\n", name);
149 150 151 152 153 154 155 156 157 158 159
        return;
    }

    if (rl_rec && version_rec) {
        rl_rec -= 4;
        rl_len += 4;

        uint8_t *data = malloc(12 + rl_len);
        memcpy(data,      version_rec, 12);
        memcpy(data + 12, rl_rec,      rl_len);
        if (!_rl_verify_signature(data, rl_len + 12)) {
npzacs's avatar
npzacs committed
160
          BD_DEBUG(DBG_AACS | DBG_CRIT, "invalid %s signature, not using it\n", name);
161 162 163 164 165 166 167 168
        } else {
          cache_save(name, version, data, rl_len + 12);
        }
        X_FREE(data);
    }
}

static void _update_rl(MKB *mkb)
169 170 171
{
    uint32_t version = mkb_version(mkb);
    uint32_t cache_version;
172
    size_t   rl_len;
173 174

    if (!cache_get("drl", &cache_version, NULL, NULL) || cache_version < version) {
175 176 177 178 179 180 181 182 183 184 185
        const uint8_t *version_rec = mkb_type_and_version_record(mkb);
        const uint8_t *drl_rec     = mkb_drive_revokation_entries(mkb, &rl_len);
        if (drl_rec && rl_len > 8) {
            _save_rl("drl", version, version_rec, drl_rec, rl_len);
        }
    }
    if (!cache_get("hrl", &cache_version, NULL, NULL) || cache_version < version) {
        const uint8_t *version_rec = mkb_type_and_version_record(mkb);
        const uint8_t *hrl_rec     = mkb_host_revokation_entries(mkb, &rl_len);
        if (hrl_rec && rl_len > 8) {
            _save_rl("hrl", version, version_rec, hrl_rec, rl_len);
186 187 188 189
        }
    }
}

190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
static uint32_t _calc_v_mask(uint32_t uv)
{
    uint32_t v_mask = 0xffffffff;

    while (!(uv & ~v_mask)) {
        v_mask <<= 1;
    }

    return v_mask;
}

static void _calc_pk(const uint8_t *dk, uint8_t *pk, uint32_t uv, uint32_t v_mask, uint32_t dev_key_v_mask)
{
    unsigned char left_child[16], right_child[16];

    crypto_aesg3(dk, left_child, right_child, pk);

    while (dev_key_v_mask != v_mask) {

        int i;
        for (i = 31; i >= 0; i--) {
            if (!(dev_key_v_mask & (1ul << i))) {
                break;
            }
        }

        uint8_t curr_key[16];
        if (!(uv & (1ul << i))) {
            memcpy(curr_key, left_child, 16);
        } else {
            memcpy(curr_key, right_child, 16);
        }

        crypto_aesg3(curr_key, left_child, right_child, pk);

        dev_key_v_mask = ((int) dev_key_v_mask) >> 1;
    }

    char str[40];
npzacs's avatar
npzacs committed
229
    BD_DEBUG(DBG_AACS, "Processing key: %s\n",  print_hex(str, pk, 16));
230 231 232 233 234 235 236 237 238 239 240 241 242
}

static dk_list *_find_dk(dk_list *dkl, uint32_t *p_dev_key_v_mask, uint32_t uv, uint32_t u_mask)
{
    uint32_t device_number = dkl->node;
    uint32_t dev_key_uv, dev_key_u_mask, dev_key_v_mask;
    unsigned key_idx = 0;

    for (; dkl; dkl = dkl->next) {
        if (device_number != dkl->node) {
            /* wrong device */
            continue;
        }
npzacs's avatar
npzacs committed
243 244 245
        if (!dkl->uv) {
            continue;
        }
246 247 248 249 250 251 252 253 254 255 256 257
        key_idx++;
        dev_key_uv     = dkl->uv;
        dev_key_u_mask = 0xffffffff << dkl->u_mask_shift;
        dev_key_v_mask = _calc_v_mask(dev_key_uv);

        if ((u_mask == dev_key_u_mask) &&
            ((uv & dev_key_v_mask) == (dev_key_uv & dev_key_v_mask))) {
            break;
        }
    }

    if (!dkl) {
npzacs's avatar
npzacs committed
258
        BD_DEBUG(DBG_AACS | DBG_CRIT, "could not find applying device key (device 0x%x)\n", device_number);
259 260
    } else {
        char str[128];
npzacs's avatar
npzacs committed
261 262
        BD_DEBUG(DBG_AACS, "Applying device key is #%d %s\n", key_idx, print_hex(str, dkl->key, 16));
        BD_DEBUG(DBG_AACS, "  UV: 0x%08x  U mask: 0x%08x  V mask: 0x%08x\n", dev_key_uv, dev_key_u_mask, dev_key_v_mask);
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
        *p_dev_key_v_mask = dev_key_v_mask;
    }

    return dkl;
}

static int _calc_pk_mk(MKB *mkb, dk_list *dkl, uint8_t *mk)
{
    /* calculate processing key and media key using device keys */

    const uint8_t *uvs, *cvalues;
    unsigned num_uvs;
    size_t len;
    char str[128];

    /* get mkb data */

    uvs     = mkb_subdiff_records(mkb, &len);
    cvalues = mkb_cvalues(mkb, &len);
    num_uvs = len / 5;

    if (num_uvs < 1) {
        return AACS_ERROR_CORRUPTED_DISC;
    }

    /* loop over all known devices */

    dk_list *dk_num;
    uint32_t device_number = (uint32_t)-1;

    for (dk_num = dkl; dk_num; dk_num = dk_num->next) {

        /* find next device */

        if (device_number == dk_num->node) {
            continue;
        }
300
        device_number = dk_num->node;
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316

        /* find applying subset difference */

        unsigned uvs_idx;
        uint32_t u_mask, v_mask, uv;

        for (uvs_idx = 0; uvs_idx < num_uvs; uvs_idx++) {
            const uint8_t *p_uv = uvs + 1 + 5 * uvs_idx;
            uint8_t u_mask_shift = p_uv[-1];

            uv = MKINT_BE32(p_uv);
            if (!uv) {
                continue;
            }

            if (u_mask_shift & 0xc0) {
npzacs's avatar
npzacs committed
317
                BD_DEBUG(DBG_AACS | DBG_CRIT, "device 0x%x is revoked\n", device_number);
318 319 320 321 322 323 324 325 326 327 328 329 330 331
                uvs_idx = num_uvs;

            } else {

                u_mask = 0xffffffff << u_mask_shift;
                v_mask = _calc_v_mask(uv);

                if (((device_number & u_mask) == (uv & u_mask)) && ((device_number & v_mask) != (uv & v_mask))) {
                    break;
                }
            }
        }

        if (uvs_idx >= num_uvs) {
npzacs's avatar
npzacs committed
332
            BD_DEBUG(DBG_AACS | DBG_CRIT, "could not find applying subset-difference for device 0x%x\n", device_number);
333 334 335 336
            /* try next device */
            continue;
        }

npzacs's avatar
npzacs committed
337 338
        BD_DEBUG(DBG_AACS, "Applying subset-difference for device 0x%x is #%d:\n", device_number, uvs_idx);
        BD_DEBUG(DBG_AACS,"  UV: 0x%08x  U mask: 0x%08x  V mask: 0x%08x\n", uv, u_mask, v_mask);
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364

        /* find applying device key */

        uint32_t dev_key_v_mask = 0;
        dk_list *dk;

        dk = _find_dk(dk_num, &dev_key_v_mask, uv, u_mask);
        if (!dk) {
            /* try next device */
            continue;
        }

        /* calculate processing key */

        uint8_t pk[16];
        _calc_pk(dk->key, pk, uv, v_mask, dev_key_v_mask);

        /* calculate and verify media key */

        if ( _validate_pk(pk,
                          cvalues + uvs_idx * 16,
                          uvs + 1 + uvs_idx * 5,
                          mkb_mk_dv(mkb),
                          mk)
             == AACS_SUCCESS) {

npzacs's avatar
npzacs committed
365
            BD_DEBUG(DBG_AACS, "Media key: %s\n", print_hex(str, mk, 16));
366 367 368
            return AACS_SUCCESS;
        }

npzacs's avatar
npzacs committed
369
        BD_DEBUG(DBG_AACS | DBG_CRIT, "Processing key %s is invalid!\n", print_hex(str, pk, 16));
370 371 372 373 374 375 376

        /* try next device */
    }

    return AACS_ERROR_NO_DK;
}

npzacs's avatar
npzacs committed
377 378 379 380 381
static AACS_FILE_H *_file_open(AACS *aacs, const char *file)
{
    AACS_FILE_H *fp;
    char        *f_name;

npzacs's avatar
npzacs committed
382 383 384 385
    if (aacs->fopen) {
        return aacs->fopen(aacs->fopen_handle, file);
    }

npzacs's avatar
npzacs committed
386
    f_name = str_printf("%s" DIR_SEP "%s", aacs->path, file);
npzacs's avatar
npzacs committed
387 388 389 390 391 392
    fp = file_open(f_name, "rb");
    X_FREE(f_name);

    return fp;
}

npzacs's avatar
npzacs committed
393 394 395 396 397
static MKB *_mkb_open(AACS *aacs)
{
    AACS_FILE_H *fp;
    MKB         *mkb;

npzacs's avatar
npzacs committed
398
    fp = _file_open(aacs, "AACS" DIR_SEP "MKB_RO.inf");
npzacs's avatar
npzacs committed
399
    if (!fp) {
npzacs's avatar
npzacs committed
400
        BD_DEBUG(DBG_AACS | DBG_CRIT, "Error opening MKB file (AACS/MKB_RO.inf)\n");
npzacs's avatar
npzacs committed
401 402 403 404 405 406 407 408 409
        return NULL;
    }

    mkb = mkb_read(fp);
    file_close(fp);

    return mkb;
}

410
static int _calc_mk(AACS *aacs, uint8_t *mk, pk_list *pkl, dk_list *dkl)
cRTrn13's avatar
keyfile  
cRTrn13 committed
411 412 413 414
{
    int a, num_uvs = 0;
    size_t len;
    MKB *mkb = NULL;
415
    const uint8_t *rec, *uvs;
cRTrn13's avatar
keyfile  
cRTrn13 committed
416

417
    /* Skip if retrieved from config file */
418 419 420
    if (memcmp(mk, empty_key, 16)) {
        return AACS_SUCCESS;
    }
421

npzacs's avatar
npzacs committed
422
    BD_DEBUG(DBG_AACS, "Calculate media key...\n");
cRTrn13's avatar
cRTrn13 committed
423

npzacs's avatar
npzacs committed
424
    if ((mkb = _mkb_open(aacs))) {
425

npzacs's avatar
npzacs committed
426
        aacs->mkb_version = mkb_version(mkb);
427
        _update_rl(mkb);
428 429 430

        /* try device keys first */
        if (dkl && _calc_pk_mk(mkb, dkl, mk) == AACS_SUCCESS) {
npzacs's avatar
npzacs committed
431
            memcpy(aacs->mk, mk, sizeof(aacs->mk));
432 433 434 435
            mkb_close(mkb);
            return AACS_SUCCESS;
        }

npzacs's avatar
npzacs committed
436
        BD_DEBUG(DBG_AACS, "Get UVS...\n");
437 438 439 440 441 442 443 444
        uvs = mkb_subdiff_records(mkb, &len);
        rec = uvs;
        while (rec < uvs + len) {
            if (rec[0] & 0xc0)
                break;
            rec += 5;
            num_uvs++;
        }
cRTrn13's avatar
keyfile  
cRTrn13 committed
445

npzacs's avatar
npzacs committed
446
        BD_DEBUG(DBG_AACS, "Get cvalues...\n");
447
        rec = mkb_cvalues(mkb, &len);
448

npzacs's avatar
npzacs committed
449
        for (; pkl; pkl = pkl->next) {
npzacs's avatar
npzacs committed
450
                BD_DEBUG(DBG_AACS, "Trying processing key...\n");
451 452

                for (a = 0; a < num_uvs; a++) {
npzacs's avatar
npzacs committed
453
                    if (AACS_SUCCESS == _validate_pk(pkl->key, rec + a * 16, uvs + 1 + a * 5,
454
                      mkb_mk_dv(mkb), mk)) {
455
                        mkb_close(mkb);
456

457
                        char str[40];
npzacs's avatar
npzacs committed
458
                        BD_DEBUG(DBG_AACS, "Media key: %s\n", print_hex(str, mk, 16));
npzacs's avatar
npzacs committed
459
                        memcpy(aacs->mk, mk, sizeof(aacs->mk));
npzacs's avatar
npzacs committed
460
                        return AACS_SUCCESS;
461 462
                    }
                }
cRTrn13's avatar
keyfile  
cRTrn13 committed
463 464
            }

465
        mkb_close(mkb);
cRTrn13's avatar
keyfile  
cRTrn13 committed
466

npzacs's avatar
npzacs committed
467
        BD_DEBUG(DBG_AACS | DBG_CRIT, "Error calculating media key. Missing right processing key ?\n");
npzacs's avatar
npzacs committed
468
        return AACS_ERROR_NO_PK;
npzacs's avatar
npzacs committed
469
    }
npzacs's avatar
npzacs committed
470

npzacs's avatar
npzacs committed
471
    return AACS_ERROR_CORRUPTED_DISC;
cRTrn13's avatar
keyfile  
cRTrn13 committed
472
}
473

npzacs's avatar
npzacs committed
474
static int _mmc_read_auth(AACS *aacs, cert_list *hcl, int type, uint8_t *p1, uint8_t *p2)
cRTrn13's avatar
openssl  
cRTrn13 committed
475
{
cRTrn13's avatar
cRTrn13 committed
476
    MMC* mmc = NULL;
npzacs's avatar
npzacs committed
477
    if (!(mmc = mmc_open(aacs->path))) {
npzacs's avatar
npzacs committed
478
        return AACS_ERROR_MMC_OPEN;
479 480
    }

npzacs's avatar
npzacs committed
481 482
    int error_code = AACS_ERROR_NO_CERT;

483
    const uint8_t *drive_cert = mmc_get_drive_cert(mmc);
484

npzacs's avatar
npzacs committed
485
    for (; hcl ; hcl = hcl->next) {
486 487 488

        char tmp_str[2*92+1];

npzacs's avatar
npzacs committed
489
        if (!crypto_aacs_verify_host_cert(hcl->host_cert)) {
npzacs's avatar
npzacs committed
490
            BD_DEBUG(DBG_AACS, "Not using invalid host certificate %s.\n",
npzacs's avatar
npzacs committed
491
                  print_hex(tmp_str, hcl->host_cert, 92));
npzacs's avatar
npzacs committed
492 493
            continue;
        }
494

npzacs's avatar
npzacs committed
495
        if (drive_cert && (drive_cert[1] & 0x01) && !(hcl->host_cert[1] & 0x01)) {
npzacs's avatar
npzacs committed
496
            BD_DEBUG(DBG_AACS, "Certificate (id 0x%s) does not support bus encryption\n",
npzacs's avatar
npzacs committed
497
                  print_hex(tmp_str, hcl->host_cert + 4, 6));
498 499 500
            //continue;
        }

npzacs's avatar
npzacs committed
501
        BD_DEBUG(DBG_AACS, "Trying host certificate (id 0x%s)...\n",
npzacs's avatar
npzacs committed
502
              print_hex(tmp_str, hcl->host_cert + 4, 6));
503

npzacs's avatar
npzacs committed
504
        int mmc_result = mmc_read_auth(mmc, hcl->host_priv_key, hcl->host_cert, type, p1, p2);
npzacs's avatar
npzacs committed
505 506 507 508 509 510 511 512 513 514 515
        switch (mmc_result) {
            case MMC_SUCCESS:
                mmc_close(mmc);
                return AACS_SUCCESS;
            case MMC_ERROR_CERT_REVOKED:
                error_code = AACS_ERROR_CERT_REVOKED;
                break;
            case MMC_ERROR:
            default:
                error_code = AACS_ERROR_MMC_FAILURE;
                break;
516 517 518 519 520
        }
    }

    mmc_close(mmc);

npzacs's avatar
npzacs committed
521
    return error_code;
522
}
cRTrn13's avatar
openssl  
cRTrn13 committed
523

npzacs's avatar
npzacs committed
524
static int _read_vid(AACS *aacs, cert_list *hcl)
525
{
npzacs's avatar
npzacs committed
526 527 528
    /* Use VID given in config file if available */
    if (memcmp(aacs->vid, empty_key, 16)) {
        return AACS_SUCCESS;
529 530
    }

npzacs's avatar
npzacs committed
531 532
    int error_code = _mmc_read_auth(aacs, hcl, MMC_READ_VID, aacs->vid, NULL);
    if (error_code != AACS_SUCCESS) {
npzacs's avatar
npzacs committed
533
        BD_DEBUG(DBG_AACS, "Error reading VID!\n");
npzacs's avatar
npzacs committed
534 535 536
    } else {
        /* cache vid */
        keycache_save("vid", aacs->disc_id, aacs->vid, 16);
537 538 539 540
    }
    return error_code;
}

npzacs's avatar
npzacs committed
541
static int _read_read_data_key(AACS *aacs, cert_list *hcl)
Janusz Dziemidowicz's avatar
Janusz Dziemidowicz committed
542
{
npzacs's avatar
npzacs committed
543 544
    int error_code = _mmc_read_auth(aacs, hcl, MMC_READ_DATA_KEYS, aacs->read_data_key, NULL);
    if (error_code != AACS_SUCCESS) {
npzacs's avatar
npzacs committed
545
        BD_DEBUG(DBG_AACS, "Error reading data keys!\n");
Janusz Dziemidowicz's avatar
Janusz Dziemidowicz committed
546
    }
npzacs's avatar
npzacs committed
547 548
    return error_code;
}
Janusz Dziemidowicz's avatar
Janusz Dziemidowicz committed
549

npzacs's avatar
npzacs committed
550 551 552 553
static int _read_pmsn(AACS *aacs, cert_list *hcl)
{
    int error_code = _mmc_read_auth(aacs, hcl, MMC_READ_PMSN, aacs->pmsn, NULL);
    if (error_code != AACS_SUCCESS) {
npzacs's avatar
npzacs committed
554
        BD_DEBUG(DBG_AACS, "Error reading PMSN!\n");
Janusz Dziemidowicz's avatar
Janusz Dziemidowicz committed
555 556 557 558
    }
    return error_code;
}

559
static int _calc_vuk(AACS *aacs, uint8_t *mk, uint8_t *vuk, config_file *cf)
560
{
npzacs's avatar
npzacs committed
561 562
    int error_code;

563
    /* Skip if retrieved from config file */
564
    if (memcmp(vuk, empty_key, 16)) {
npzacs's avatar
npzacs committed
565
        BD_DEBUG(DBG_AACS, "Using VUK from config file\n");
npzacs's avatar
npzacs committed
566 567
        return AACS_SUCCESS;
    }
568

npzacs's avatar
npzacs committed
569
    /* get cached vuk */
570
    if (keycache_find("vuk", aacs->disc_id, vuk, 16)) {
npzacs's avatar
npzacs committed
571
        BD_DEBUG(DBG_AACS, "Using cached VUK\n");
npzacs's avatar
npzacs committed
572
        return AACS_SUCCESS;
npzacs's avatar
npzacs committed
573 574
    }

575 576 577 578
    if (!cf) {
        return AACS_ERROR_NO_CONFIG;
    }

579
    /* make sure we have media key */
580
    error_code = _calc_mk(aacs, mk, cf->pkl, cf->dkl);
npzacs's avatar
npzacs committed
581 582
    if (error_code != AACS_SUCCESS) {
        return error_code;
583 584
    }

npzacs's avatar
npzacs committed
585
    /* acquire VID */
586
    error_code = _read_vid(aacs, cf->host_cert_list);
npzacs's avatar
npzacs committed
587 588 589
    if (error_code != AACS_SUCCESS) {
        return error_code;
    }
590

npzacs's avatar
npzacs committed
591
    /* calculate VUK */
592

npzacs's avatar
npzacs committed
593
    crypto_aes128d(mk, aacs->vid, vuk);
594

npzacs's avatar
npzacs committed
595
    int a;
npzacs's avatar
npzacs committed
596
    for (a = 0; a < 16; a++) {
597
        vuk[a] ^= aacs->vid[a];
npzacs's avatar
npzacs committed
598
    }
599

npzacs's avatar
npzacs committed
600
    char str[40];
npzacs's avatar
npzacs committed
601
    BD_DEBUG(DBG_AACS, "Volume unique key: %s\n", print_hex(str, vuk, 16));
602

npzacs's avatar
npzacs committed
603
    /* cache vuk */
604
    keycache_save("vuk", aacs->disc_id, vuk, 16);
npzacs's avatar
npzacs committed
605

npzacs's avatar
npzacs committed
606
    return AACS_SUCCESS;
cRTrn13's avatar
openssl  
cRTrn13 committed
607 608
}

609 610
static uint16_t _read_u16(AACS_FILE_H *fp)
{
npzacs's avatar
npzacs committed
611
  uint8_t data[2] = {0, 0};
612 613 614 615 616 617 618 619 620 621 622

  file_read(fp, data, sizeof(uint16_t));

  return MKINT_BE16(data);
}

static void _read_uks_map(AACS *aacs, AACS_FILE_H *fp)
{
    uint16_t first_play, top_menu;
    unsigned i;

npzacs's avatar
npzacs committed
623
    BD_DEBUG(DBG_AACS, "Assigning CPS units to titles ...\n");
624 625 626 627 628 629 630 631 632

    X_FREE(aacs->cps_units);
    aacs->current_cps_unit = 0;

    file_seek(fp, 16 + 4, SEEK_SET);

    first_play = _read_u16(fp);
    top_menu   = _read_u16(fp);

npzacs's avatar
npzacs committed
633 634
    BD_DEBUG(DBG_AACS, "Title FP : CPS unit %d\n", first_play);
    BD_DEBUG(DBG_AACS, "Title TM : CPS unit %d\n", top_menu);
635 636 637 638 639 640 641 642 643

    aacs->num_titles   = _read_u16(fp);
    aacs->cps_units    = calloc(sizeof(uint16_t), aacs->num_titles + 2);
    aacs->cps_units[0] = first_play;
    aacs->cps_units[1] = top_menu;

    for (i = 2; i < aacs->num_titles + 2; i++) {
        _read_u16(fp); /* reserved */
        aacs->cps_units[i] = _read_u16(fp);
npzacs's avatar
npzacs committed
644
        BD_DEBUG(DBG_AACS, "Title %02d : CPS unit %d\n", i - 1, aacs->cps_units[i]);
645 646 647 648 649 650 651
    }

    /* validate */
    for (i = 0; i < aacs->num_titles + 2; i++) {
        if (aacs->cps_units[i])
            aacs->cps_units[i]--; /* number [1...N] --> index [0...N-1] */
        if (aacs->cps_units[i] >= aacs->num_uks) {
npzacs's avatar
npzacs committed
652
            BD_DEBUG(DBG_AACS, " *** Invalid CPS unit for title %d: %d !\n", (int) i - 1, aacs->cps_units[i]);
653 654 655 656 657
            aacs->cps_units[i] = 0;
        }
    }
}

npzacs's avatar
npzacs committed
658
/* Function that collects keys from keydb config entry */
659 660
static void _find_config_entry(AACS *aacs, title_entry_list *ce,
                               uint8_t *mk, uint8_t *vuk)
npzacs's avatar
npzacs committed
661 662 663 664 665 666 667
{
    char str[48];

    aacs->uks = NULL;
    aacs->num_uks = 0;

        while (ce && ce->entry.discid) {
npzacs's avatar
npzacs committed
668
            if (!memcmp(aacs->disc_id, ce->entry.discid, 20)) {
npzacs's avatar
npzacs committed
669
                BD_DEBUG(DBG_AACS, "Found config entry for discid %s\n",
npzacs's avatar
npzacs committed
670
                      print_hex(str, ce->entry.discid, 20));
npzacs's avatar
npzacs committed
671 672 673 674 675 676 677 678 679 680
                break;
            }

            ce = ce->next;
        }
        if (!ce) {
            return;
        }

        if (ce->entry.mek) {
681
            hexstring_to_hex_array(mk, 16, ce->entry.mek);
npzacs's avatar
npzacs committed
682

npzacs's avatar
npzacs committed
683
            BD_DEBUG(DBG_AACS, "Found media key for %s: %s\n",
684
                  ce->entry.discid, print_hex(str, mk, 16));
npzacs's avatar
npzacs committed
685 686 687 688 689 690
        }

        if (ce->entry.vid) {
            hexstring_to_hex_array(aacs->vid, sizeof(aacs->vid),
                                    ce->entry.vid);

npzacs's avatar
npzacs committed
691
            BD_DEBUG(DBG_AACS, "Found volume id for %s: %s\n",
npzacs's avatar
npzacs committed
692 693 694 695
                  ce->entry.discid, print_hex(str, aacs->vid, 16));
        }

        if (ce->entry.vuk) {
696
            hexstring_to_hex_array(vuk, 16, ce->entry.vuk);
npzacs's avatar
npzacs committed
697

npzacs's avatar
npzacs committed
698
            BD_DEBUG(DBG_AACS, "Found volume unique key for %s: %s\n",
699
                  ce->entry.discid, print_hex(str, vuk, 16));
npzacs's avatar
npzacs committed
700 701 702
        }

        if (ce->entry.uk) {
npzacs's avatar
npzacs committed
703
            BD_DEBUG(DBG_AACS, "Acquire CPS unit keys from keydb config file...\n");
npzacs's avatar
npzacs committed
704 705 706 707 708 709 710 711 712

            digit_key_pair_list *ukcursor = ce->entry.uk;
            while (ukcursor && ukcursor->key_pair.key) {
                aacs->num_uks++;

                aacs->uks = (uint8_t*)realloc(aacs->uks, 16 * aacs->num_uks);
                hexstring_to_hex_array(aacs->uks + (16 * (aacs->num_uks - 1)), 16,
                                      ukcursor->key_pair.key);

npzacs's avatar
npzacs committed
713
                BD_DEBUG(DBG_AACS, "Unit key %d from keydb entry: %s\n",
npzacs's avatar
npzacs committed
714 715 716 717 718 719 720 721
                      aacs->num_uks,
                      print_hex(str, aacs->uks + (16 * (aacs->num_uks - 1)), 16));

                ukcursor = ukcursor->next;
            }
        }
}

722
static int _calc_uks(AACS *aacs, config_file *cf)
cRTrn13's avatar
openssl  
cRTrn13 committed
723
{
724
    AACS_FILE_H *fp = NULL;
725
    uint8_t  buf[16];
726
    uint64_t f_pos;
727
    unsigned int i;
npzacs's avatar
npzacs committed
728
    int error_code;
cRTrn13's avatar
openssl  
cRTrn13 committed
729

730 731
    uint8_t mk[16] = {0}, vuk[16] = {0};

732
    if (cf) {
npzacs's avatar
npzacs committed
733
        BD_DEBUG(DBG_AACS, "Searching for keydb config entry...\n");
734
        _find_config_entry(aacs, cf->list, mk, vuk);
735

736 737 738 739
        /* Skip if retrieved from config file */
        if (aacs->uks) {
            return AACS_SUCCESS;
        }
740
    }
741

742
    /* Make sure we have VUK */
743
    error_code = _calc_vuk(aacs, mk, vuk, cf);
npzacs's avatar
npzacs committed
744 745
    if (error_code != AACS_SUCCESS) {
        return error_code;
746
    }
747

npzacs's avatar
npzacs committed
748
    BD_DEBUG(DBG_AACS, "Calculate CPS unit keys...\n");
749

npzacs's avatar
npzacs committed
750
    fp = _file_open(aacs, "AACS" DIR_SEP "Unit_Key_RO.inf");
npzacs's avatar
npzacs committed
751
    if (!fp) {
npzacs's avatar
npzacs committed
752
        BD_DEBUG(DBG_AACS | DBG_CRIT, "Error opening unit key file (AACS/Unit_Key_RO.inf)\n");
npzacs's avatar
npzacs committed
753 754
        return AACS_ERROR_CORRUPTED_DISC;
    }
cRTrn13's avatar
openssl  
cRTrn13 committed
755

npzacs's avatar
npzacs committed
756 757
    if ((file_read(fp, buf, 4)) == 4) {
        f_pos = MKINT_BE32(buf);
npzacs's avatar
npzacs committed
758

npzacs's avatar
npzacs committed
759 760 761 762
        // Read number of keys
        file_seek(fp, f_pos, SEEK_SET);
        if ((file_read(fp, buf, 2)) == 2) {
            aacs->num_uks = MKINT_BE16(buf);
npzacs's avatar
npzacs committed
763

npzacs's avatar
npzacs committed
764 765
            X_FREE(aacs->uks);
            aacs->uks = calloc(aacs->num_uks, 16);
npzacs's avatar
npzacs committed
766

npzacs's avatar
npzacs committed
767
            BD_DEBUG(DBG_AACS, "%d CPS unit keys\n", aacs->num_uks);
npzacs's avatar
npzacs committed
768

npzacs's avatar
npzacs committed
769 770
        } else {
            aacs->num_uks = 0;
npzacs's avatar
npzacs committed
771
            BD_DEBUG(DBG_AACS | DBG_CRIT, "Error reading number of unit keys\n");
npzacs's avatar
npzacs committed
772 773
            error_code = AACS_ERROR_CORRUPTED_DISC;
        }
cRTrn13's avatar
openssl  
cRTrn13 committed
774

npzacs's avatar
npzacs committed
775 776 777
        // Read keys
        for (i = 0; i < aacs->num_uks; i++) {
            f_pos += 48;
cRTrn13's avatar
openssl  
cRTrn13 committed
778

npzacs's avatar
npzacs committed
779 780
            file_seek(fp, f_pos, SEEK_SET);
            if ((file_read(fp, buf, 16)) != 16) {
npzacs's avatar
npzacs committed
781
                BD_DEBUG(DBG_AACS, "Unit key %d: read error\n", i);
npzacs's avatar
npzacs committed
782 783 784
                aacs->num_uks = i;
                error_code = AACS_ERROR_CORRUPTED_DISC;
                break;
npzacs's avatar
npzacs committed
785
            }
cRTrn13's avatar
openssl  
cRTrn13 committed
786

npzacs's avatar
npzacs committed
787
            crypto_aes128d(vuk, buf, aacs->uks + 16*i);
cRTrn13's avatar
openssl  
cRTrn13 committed
788

npzacs's avatar
npzacs committed
789
            char str[40];
npzacs's avatar
npzacs committed
790
            BD_DEBUG(DBG_AACS, "Unit key %d: %s\n", i,
npzacs's avatar
npzacs committed
791
                  print_hex(str, aacs->uks + 16*i, 16));
792 793
        }

npzacs's avatar
npzacs committed
794 795 796
        /* failing next is not fatal, it just slows down things */
        _read_uks_map(aacs, fp);

797
        file_close(fp);
cRTrn13's avatar
openssl  
cRTrn13 committed
798

npzacs's avatar
npzacs committed
799 800 801 802 803
        return error_code;
    }

    file_close(fp);

npzacs's avatar
npzacs committed
804
    BD_DEBUG(DBG_AACS | DBG_CRIT, "Error reading unit keys\n");
npzacs's avatar
npzacs committed
805
    return AACS_ERROR_CORRUPTED_DISC;
cRTrn13's avatar
openssl  
cRTrn13 committed
806 807
}

npzacs's avatar
npzacs committed
808
static int _calc_title_hash(AACS *aacs)
809
{
810
    AACS_FILE_H *fp = NULL;
811 812 813
    uint8_t *ukf_buf;
    char     str[48];
    int64_t  f_size;
npzacs's avatar
npzacs committed
814
    int      result = AACS_SUCCESS;
815

npzacs's avatar
npzacs committed
816
    fp = _file_open(aacs, "AACS" DIR_SEP "Unit_Key_RO.inf");
npzacs's avatar
npzacs committed
817
    if (!fp) {
npzacs's avatar
npzacs committed
818
        BD_DEBUG(DBG_AACS | DBG_CRIT, "Error opening unit key file (AACS/Unit_Key_RO.inf)\n");
npzacs's avatar
npzacs committed
819
        return AACS_ERROR_CORRUPTED_DISC;
820 821 822 823 824 825 826 827
    }

    file_seek(fp, 0, SEEK_END);
    f_size = file_tell(fp);
    file_seek(fp, 0, SEEK_SET);

    ukf_buf = malloc(f_size);

npzacs's avatar
npzacs committed
828
    if ((file_read(fp, ukf_buf, f_size)) == f_size) {
npzacs's avatar
npzacs committed
829
        crypto_aacs_title_hash(ukf_buf, f_size, aacs->disc_id);
npzacs's avatar
npzacs committed
830
        BD_DEBUG(DBG_AACS, "Disc ID: %s\n", print_hex(str, aacs->disc_id, 20));
cRTrn13's avatar
cRTrn13 committed
831

npzacs's avatar
npzacs committed
832 833
    } else {
        result = AACS_ERROR_CORRUPTED_DISC;
npzacs's avatar
npzacs committed
834
        BD_DEBUG(DBG_AACS | DBG_CRIT, "Failed to read %lu bytes from unit key file (AACS/Unit_Key_RO.inf)", (unsigned long)f_size);
835 836 837 838 839
    }

    file_close(fp);
    X_FREE(ukf_buf);

npzacs's avatar
npzacs committed
840
    return result;
841
}
cRTrn13's avatar
cRTrn13 committed
842

npzacs's avatar
npzacs committed
843
static int _get_bus_encryption_enabled(AACS *aacs)
844 845 846 847 848
{
    AACS_FILE_H *fp = NULL;
    uint8_t buf[2];
    int bee = 0;

npzacs's avatar
npzacs committed
849
    fp = _file_open(aacs, "AACS" DIR_SEP "Content000.cer");
850
    if (!fp) {
npzacs's avatar
npzacs committed
851
        BD_DEBUG(DBG_AACS | DBG_CRIT, "Unable to open content certificate (AACS/Content000.cer)\n");
852 853 854 855 856
        return 0;
    }

    if (file_read(fp, buf, 2) == 2) {
        bee = (buf[1] & 0x80) >> 7;
npzacs's avatar
npzacs committed
857
        BD_DEBUG(DBG_AACS, "Bus Encryption Enabled flag in content certificate: %d\n", bee);
858
    } else {
npzacs's avatar
npzacs committed
859
        BD_DEBUG(DBG_AACS | DBG_CRIT, "Failed to read Bus Encryption Enabled flag from content certificate file\n");
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877
    }

    file_close(fp);
    return bee;
}

static int _get_bus_encryption_capable(const char *path)
{
    MMC* mmc = NULL;
    uint8_t drive_cert[92];
    int bec = 0;

    if (!(mmc = mmc_open(path))) {
        return 0;
    }

    if (mmc_read_drive_cert(mmc, drive_cert) == MMC_SUCCESS) {
        bec = drive_cert[1] & 1;
npzacs's avatar
npzacs committed
878
        BD_DEBUG(DBG_AACS, "Bus Encryption Capable flag in drive certificate: %d\n", bec);
879
    } else {
npzacs's avatar
npzacs committed
880
        BD_DEBUG(DBG_AACS | DBG_CRIT, "Unable to read drive certificate\n");
881 882 883 884 885 886
    }

    mmc_close(mmc);
    return bec;
}

npzacs's avatar
npzacs committed
887
static int _verify_ts(uint8_t *buf)
888
{
npzacs's avatar
npzacs committed
889 890 891 892
    int i;
    for (i = 0; i < ALIGNED_UNIT_LEN; i += 192) {
        if (AACS_UNLIKELY(buf[i + 4] != 0x47)) {
            return 0;
893
        }
894