aacs.c 35.1 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 26
#include <util/attributes.h>

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

103
    DEBUG(DBG_AACS, "Validate processing key %s...\n", print_hex(str, pk, 16));
cRTrn13's avatar
cRTrn13 committed
104
    DEBUG(DBG_AACS, " Using:\n");
105 106 107
    DEBUG(DBG_AACS, "   UV: %s\n", print_hex(str, uv, 4));
    DEBUG(DBG_AACS, "   cvalue: %s\n", print_hex(str, cvalue, 16));
    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
        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 135 136 137 138 139 140 141
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) {
        DEBUG(DBG_AACS, "revocation list size mismatch\n");
        return 0;
    }

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

142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
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) {
        DEBUG(DBG_AACS | DBG_CRIT, "ignoring empty %s\n", name);
        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)) {
          DEBUG(DBG_AACS | DBG_CRIT, "invalid %s signature, not using it\n", name);
        } 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 229 230 231 232 233 234 235 236 237 238 239 240 241 242
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];
    DEBUG(DBG_AACS, "Processing key: %s\n",  print_hex(str, pk, 16));
}

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 258 259 260 261 262 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
        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) {
        DEBUG(DBG_AACS | DBG_CRIT, "could not find applying device key (device 0x%x)\n", device_number);
    } else {
        char str[128];
        DEBUG(DBG_AACS, "Applying device key is #%d %s\n", key_idx, print_hex(str, dkl->key, 16));
        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);
        *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 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 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 365 366 367 368 369 370 371 372 373 374 375 376

        /* 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) {
                DEBUG(DBG_AACS | DBG_CRIT, "device 0x%x is revoked\n", device_number);
                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) {
            DEBUG(DBG_AACS | DBG_CRIT, "could not find applying subset-difference for device 0x%x\n", device_number);
            /* try next device */
            continue;
        }

        DEBUG(DBG_AACS, "Applying subset-difference for device 0x%x is #%d:\n", device_number, uvs_idx);
        DEBUG(DBG_AACS,"  UV: 0x%08x  U mask: 0x%08x  V mask: 0x%08x\n", uv, u_mask, v_mask);

        /* 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) {

            DEBUG(DBG_AACS, "Media key: %s\n", print_hex(str, mk, 16));
            return AACS_SUCCESS;
        }

        DEBUG(DBG_AACS | DBG_CRIT, "Processing key %s is invalid!\n", print_hex(str, pk, 16));

        /* 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 387 388 389 390 391 392
    f_name = str_printf("%s/%s", aacs->path, file);
    fp = file_open(f_name, "rb");
    X_FREE(f_name);

    return fp;
}

npzacs's avatar
npzacs committed
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
static MKB *_mkb_open(AACS *aacs)
{
    AACS_FILE_H *fp;
    MKB         *mkb;

    fp = _file_open(aacs, "AACS/MKB_RO.inf");
    if (!fp) {
        DEBUG(DBG_AACS | DBG_CRIT, "Error opening MKB file (AACS/MKB_RO.inf)\n");
        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

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

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 436
            mkb_close(mkb);
            return AACS_SUCCESS;
        }

        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

446 447
        DEBUG(DBG_AACS, "Get cvalues...\n");
        rec = mkb_cvalues(mkb, &len);
448

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

                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];
458
                        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
        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
            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)) {
496
            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;
        }

501
        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 533 534 535 536
    int error_code = _mmc_read_auth(aacs, hcl, MMC_READ_VID, aacs->vid, NULL);
    if (error_code != AACS_SUCCESS) {
        DEBUG(DBG_AACS, "Error reading VID!\n");
    } 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 545
    int error_code = _mmc_read_auth(aacs, hcl, MMC_READ_DATA_KEYS, aacs->read_data_key, NULL);
    if (error_code != AACS_SUCCESS) {
        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 554
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) {
        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 566 567
        DEBUG(DBG_AACS, "Using VUK from config file\n");
        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
        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];
601
    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 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657

  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;

    DEBUG(DBG_AACS, "Assigning CPS units to titles ...\n");

    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);

    DEBUG(DBG_AACS, "Title FP : CPS unit %d\n", first_play);
    DEBUG(DBG_AACS, "Title TM : CPS unit %d\n", top_menu);

    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);
        DEBUG(DBG_AACS, "Title %02d : CPS unit %d\n", i - 1, aacs->cps_units[i]);
    }

    /* 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) {
            DEBUG(DBG_AACS, " *** Invalid CPS unit for title %d: %d !\n", (int) i - 1, aacs->cps_units[i]);
            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
                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 683

            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 691 692 693 694 695
        }

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

            DEBUG(DBG_AACS, "Found volume id for %s: %s\n",
                  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 698

            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 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721
        }

        if (ce->entry.uk) {
            DEBUG(DBG_AACS, "Acquire CPS unit keys from keydb config file...\n");

            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);

                DEBUG(DBG_AACS, "Unit key %d from keydb entry: %s\n",
                      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 733 734
    if (cf) {
        DEBUG(DBG_AACS, "Searching for keydb config entry...\n");
        _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

748 749
    DEBUG(DBG_AACS, "Calculate CPS unit keys...\n");

npzacs's avatar
npzacs committed
750
    fp = _file_open(aacs, "AACS/Unit_Key_RO.inf");
npzacs's avatar
npzacs committed
751
    if (!fp) {
npzacs's avatar
npzacs committed
752
        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
            DEBUG(DBG_AACS, "%d CPS unit keys\n", aacs->num_uks);
npzacs's avatar
npzacs committed
768

npzacs's avatar
npzacs committed
769 770 771 772 773
        } else {
            aacs->num_uks = 0;
            DEBUG(DBG_AACS | DBG_CRIT, "Error reading number of unit keys\n");
            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 781 782 783 784
            file_seek(fp, f_pos, SEEK_SET);
            if ((file_read(fp, buf, 16)) != 16) {
                DEBUG(DBG_AACS, "Unit key %d: read error\n", i);
                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 790 791
            char str[40];
            DEBUG(DBG_AACS, "Unit key %d: %s\n", i,
                  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 804 805
        return error_code;
    }

    file_close(fp);

    DEBUG(DBG_AACS | DBG_CRIT, "Error reading unit keys\n");
    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/Unit_Key_RO.inf");
npzacs's avatar
npzacs committed
817
    if (!fp) {
npzacs's avatar
npzacs committed
818
        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 830
        crypto_aacs_title_hash(ukf_buf, f_size, aacs->disc_id);
        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
        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/Content000.cer");
850
    if (!fp) {
npzacs's avatar
npzacs committed
851
        DEBUG(DBG_AACS | DBG_CRIT, "Unable to open content certificate (AACS/Content000.cer)\n");
852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886
        return 0;
    }

    if (file_read(fp, buf, 2) == 2) {
        bee = (buf[1] & 0x80) >> 7;
        DEBUG(DBG_AACS, "Bus Encryption Enabled flag in content certificate: %d\n", bee);
    } else {
        DEBUG(DBG_AACS | DBG_CRIT, "Failed to read Bus Encryption Enabled flag from content certificate file\n");
    }

    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;
        DEBUG(DBG_AACS, "Bus Encryption Capable flag in drive certificate: %d\n", bec);
    } else {
        DEBUG(DBG_AACS | DBG_CRIT, "Unable to read drive certificate\n");
    }

    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

npzacs's avatar
npzacs committed
895 896 897 898
        /* Clear copy_permission_indicator bits */
        buf[i] &= ~0xc0;
    }
    return 1;
899 900
}

901
static int _decrypt_unit(AACS *aacs, uint8_t *out_buf, const uint8_t *in_buf, uint32_t curr_uk)
cRTrn13's avatar
cRTrn13 committed
902
{
903 904
    /* inbuf == NULL means in-place decryption */

905 906
    gcry_cipher_hd_t gcry_h;
    int a;
907
    uint8_t key[16];
908

909 910 911 912
    if (AACS_UNLIKELY(in_buf != NULL)) {
        memcpy(out_buf, in_buf, 16); /* first 16 bytes are plain */
    }

913 914
    gcry_cipher_open(&gcry_h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0);
    gcry_cipher_setkey(gcry_h, aacs->uks + curr_uk * 16, 16);
915
    gcry_cipher_encrypt(gcry_h, key, 16, out_buf, 16); /* here out_buf is plain data fron in_buf */
916
    gcry_cipher_close(gcry_h);
cRTrn13's avatar
cRTrn13 committed
917

cRTrn13's avatar
cRTrn13 committed
918
    for (a = 0; a < 16; a++) {
919
        key[a] ^= out_buf[a]; /* here out_buf is plain data fron in_buf */
cRTrn13's avatar
cRTrn13 committed
920 921
    }

922 923
    gcry_cipher_open(&gcry_h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0);
    gcry_cipher_setkey(gcry_h, key, 16);
924
    gcry_cipher_setiv(gcry_h, aacs_iv, 16);
925 926 927 928 929
    if (AACS_UNLIKELY(in_buf != NULL)) {
        gcry_cipher_decrypt(gcry_h, out_buf + 16, ALIGNED_UNIT_LEN - 16, in_buf + 16, ALIGNED_UNIT_LEN - 16);
    } else {
        gcry_cipher_decrypt(gcry_h, out_buf + 16, ALIGNED_UNIT_LEN - 16, NULL, 0);
    }
930
    gcry_cipher_close(gcry_h);
cRTrn13's avatar
cRTrn13 committed
931

npzacs's avatar
npzacs committed
932
    if (_verify_ts(out_buf)) {
cRTrn13's avatar
cRTrn13 committed
933 934 935 936 937 938
        return 1;
    }

    return 0;
}

939
static void _decrypt_bus(AACS *aacs, uint8_t *buf)
940 941 942 943 944
{
    gcry_cipher_hd_t gcry_h;

    gcry_cipher_open(&gcry_h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0);
    gcry_cipher_setkey(gcry_h, aacs->read_data_key, 16);
945
    gcry_cipher_setiv(gcry_h, aacs_iv, 16);
946
    gcry_cipher_decrypt(gcry_h, buf + 16, SECTOR_LEN - 16, NULL, 0);
947 948 949
    gcry_cipher_close(gcry_h);
}

npzacs's avatar
npzacs committed
950 951
void aacs_get_version(int *major, int *minor, int *micro)
{
npzacs's avatar
npzacs committed
952 953 954
    *major = AACS_VERSION_MAJOR;
    *minor = AACS_VERSION_MINOR;
    *micro = AACS_VERSION_MICRO;
npzacs's avatar
npzacs committed
955 956
}

npzacs's avatar
npzacs committed
957
/* aacs_open2() wrapper for backwards compability */
cRTrn13's avatar
cRTrn13 committed
958
AACS *aacs_open(const char *path, const char *configfile_path)
npzacs's avatar
npzacs committed
959 960 961 962 963
{
    int error_code;
    AACS *aacs;

    aacs = aacs_open2(path, configfile_path, &error_code);
npzacs's avatar
npzacs committed
964
    if (!aacs || error_code == AACS_SUCCESS) {
npzacs's avatar
npzacs committed
965 966 967 968 969 970 971
        return aacs;
    }

    aacs_close(aacs);
    return NULL;
}

npzacs's avatar
npzacs committed
972
/* aacs_open_device() wrapper for backward compability */
npzacs's avatar
npzacs committed
973
AACS *aacs_open2(const char *path, const char *configfile_path, int *error_code)
npzacs's avatar
npzacs committed
974 975 976 977 978 979 980 981 982
{
    AACS *aacs = aacs_init();
    if (aacs) {
        *error_code = aacs_open_device(aacs, path, configfile_path);
    }
    return aacs;
}

AACS *aacs_init()
cRTrn13's avatar
cRTrn13 committed
983
{
npzacs's avatar
npzacs committed
984
    DEBUG(DBG_AACS, "libaacs "AACS_VERSION_STRING" [%u]\n", (unsigned)sizeof(AACS));