aacs.c 35.5 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
    BD_DEBUG(DBG_AACS, "Validate processing key %s...\n", str_print_hex(str, pk, 16));
npzacs's avatar
npzacs committed
104
    BD_DEBUG(DBG_AACS, " Using:\n");
npzacs's avatar
npzacs committed
105 106 107
    BD_DEBUG(DBG_AACS, "   UV: %s\n", str_print_hex(str, uv, 4));
    BD_DEBUG(DBG_AACS, "   cvalue: %s\n", str_print_hex(str, cvalue, 16));
    BD_DEBUG(DBG_AACS, "   Verification data: %s\n", str_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", str_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",  str_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
        BD_DEBUG(DBG_AACS, "Applying device key is #%d %s\n", key_idx, str_print_hex(str, dkl->key, 16));
npzacs's avatar
npzacs committed
262
        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", str_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", str_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
    if (aacs->fopen) {
        return aacs->fopen(aacs->fopen_handle, file);
    }
npzacs's avatar
npzacs committed
385 386 387
    if (!aacs->path) {
        return NULL;
    }
npzacs's avatar
npzacs committed
388

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

    return fp;
}

npzacs's avatar
npzacs committed
396 397 398 399 400
static MKB *_mkb_open(AACS *aacs)
{
    AACS_FILE_H *fp;
    MKB         *mkb;

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

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

    return mkb;
}

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

420
    /* Skip if retrieved from config file */
421 422 423
    if (memcmp(mk, empty_key, 16)) {
        return AACS_SUCCESS;
    }
424

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

npzacs's avatar
npzacs committed
427
    if ((mkb = _mkb_open(aacs))) {
428

npzacs's avatar
npzacs committed
429
        aacs->mkb_version = mkb_version(mkb);
430
        _update_rl(mkb);
431 432 433

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

npzacs's avatar
npzacs committed
439
        BD_DEBUG(DBG_AACS, "Get UVS...\n");
440 441 442 443 444 445 446 447
        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
448

npzacs's avatar
npzacs committed
449
        BD_DEBUG(DBG_AACS, "Get cvalues...\n");
450
        rec = mkb_cvalues(mkb, &len);
451

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

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

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

468
        mkb_close(mkb);
cRTrn13's avatar
keyfile  
cRTrn13 committed
469

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

npzacs's avatar
npzacs committed
474
    return AACS_ERROR_CORRUPTED_DISC;
cRTrn13's avatar
keyfile  
cRTrn13 committed
475
}
476

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

npzacs's avatar
npzacs committed
484 485
    int error_code = AACS_ERROR_NO_CERT;

486
    const uint8_t *drive_cert = mmc_get_drive_cert(mmc);
487

npzacs's avatar
npzacs committed
488
    for (; hcl ; hcl = hcl->next) {
489 490 491

        char tmp_str[2*92+1];

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

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

npzacs's avatar
npzacs committed
504
        BD_DEBUG(DBG_AACS, "Trying host certificate (id 0x%s)...\n",
npzacs's avatar
npzacs committed
505
              str_print_hex(tmp_str, hcl->host_cert + 4, 6));
506

npzacs's avatar
npzacs committed
507
        int mmc_result = mmc_read_auth(mmc, hcl->host_priv_key, hcl->host_cert, type, p1, p2);
npzacs's avatar
npzacs committed
508 509 510 511 512 513 514 515 516 517 518
        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;
519 520 521 522 523
        }
    }

    mmc_close(mmc);

npzacs's avatar
npzacs committed
524
    return error_code;
525
}
cRTrn13's avatar
openssl  
cRTrn13 committed
526

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

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

npzacs's avatar
npzacs committed
544
static int _read_read_data_key(AACS *aacs, cert_list *hcl)
Janusz Dziemidowicz's avatar
Janusz Dziemidowicz committed
545
{
npzacs's avatar
npzacs committed
546 547
    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
548
        BD_DEBUG(DBG_AACS, "Error reading data keys!\n");
Janusz Dziemidowicz's avatar
Janusz Dziemidowicz committed
549
    }
npzacs's avatar
npzacs committed
550 551
    return error_code;
}
Janusz Dziemidowicz's avatar
Janusz Dziemidowicz committed
552

npzacs's avatar
npzacs committed
553 554 555 556
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
557
        BD_DEBUG(DBG_AACS, "Error reading PMSN!\n");
Janusz Dziemidowicz's avatar
Janusz Dziemidowicz committed
558 559 560 561
    }
    return error_code;
}

562
static int _calc_vuk(AACS *aacs, uint8_t *mk, uint8_t *vuk, config_file *cf)
563
{
npzacs's avatar
npzacs committed
564 565
    int error_code;

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

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

578 579 580 581
    if (!cf) {
        return AACS_ERROR_NO_CONFIG;
    }

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

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

npzacs's avatar
npzacs committed
594
    /* calculate VUK */
595

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

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

npzacs's avatar
npzacs committed
603
    char str[40];
npzacs's avatar
npzacs committed
604
    BD_DEBUG(DBG_AACS, "Volume unique key: %s\n", str_print_hex(str, vuk, 16));
605

npzacs's avatar
npzacs committed
606
    /* cache vuk */
607
    keycache_save("vuk", aacs->disc_id, vuk, 16);
npzacs's avatar
npzacs committed
608

npzacs's avatar
npzacs committed
609
    return AACS_SUCCESS;
cRTrn13's avatar
openssl  
cRTrn13 committed
610 611
}

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

  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
626
    BD_DEBUG(DBG_AACS, "Assigning CPS units to titles ...\n");
627 628 629 630 631 632 633 634 635

    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
636 637
    BD_DEBUG(DBG_AACS, "Title FP : CPS unit %d\n", first_play);
    BD_DEBUG(DBG_AACS, "Title TM : CPS unit %d\n", top_menu);
638 639 640 641 642 643 644 645 646

    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
647
        BD_DEBUG(DBG_AACS, "Title %02d : CPS unit %d\n", i - 1, aacs->cps_units[i]);
648 649 650 651 652 653 654
    }

    /* 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
655
            BD_DEBUG(DBG_AACS, " *** Invalid CPS unit for title %d: %d !\n", (int) i - 1, aacs->cps_units[i]);
656 657 658 659 660
            aacs->cps_units[i] = 0;
        }
    }
}

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

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

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

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

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

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

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

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

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

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

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

            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
716
                BD_DEBUG(DBG_AACS, "Unit key %d from keydb entry: %s\n",
npzacs's avatar
npzacs committed
717
                      aacs->num_uks,
npzacs's avatar
npzacs committed
718
                      str_print_hex(str, aacs->uks + (16 * (aacs->num_uks - 1)), 16));
npzacs's avatar
npzacs committed
719 720 721 722 723 724

                ukcursor = ukcursor->next;
            }
        }
}

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

733 734
    uint8_t mk[16] = {0}, vuk[16] = {0};

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

739 740 741 742
        /* Skip if retrieved from config file */
        if (aacs->uks) {
            return AACS_SUCCESS;
        }
743
    }
744

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

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

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

npzacs's avatar
npzacs committed
759 760
    if ((file_read(fp, buf, 4)) == 4) {
        f_pos = MKINT_BE32(buf);
npzacs's avatar
npzacs committed
761

npzacs's avatar
npzacs committed
762 763 764 765
        // 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
766

npzacs's avatar
npzacs committed
767 768
            X_FREE(aacs->uks);
            aacs->uks = calloc(aacs->num_uks, 16);
npzacs's avatar
npzacs committed
769

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

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

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

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

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

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

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

800
        file_close(fp);
cRTrn13's avatar
openssl  
cRTrn13 committed
801

npzacs's avatar
npzacs committed
802 803 804 805 806
        return error_code;
    }

    file_close(fp);

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

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

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

    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
831
    if ((file_read(fp, ukf_buf, f_size)) == f_size) {
npzacs's avatar
npzacs committed
832
        crypto_aacs_title_hash(ukf_buf, f_size, aacs->disc_id);
npzacs's avatar
npzacs committed
833
        BD_DEBUG(DBG_AACS, "Disc ID: %s\n", str_print_hex(str, aacs->disc_id, 20));
cRTrn13's avatar
cRTrn13 committed
834

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

    file_close(fp);
    X_FREE(ukf_buf);

npzacs's avatar
npzacs committed
843
    return result;
844
}
cRTrn13's avatar
cRTrn13 committed
845

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

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

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

    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
881
        BD_DEBUG(DBG_AACS, "Bus Encryption Capable flag in drive certificate: %d\n", bec);
882
    } else {
npzacs's avatar
npzacs committed
883
        BD_DEBUG(DBG_AACS | DBG_CRIT, "Unable to read drive certificate\n");
884 885 886 887 888 889