aacs.c 29.5 KB
Newer Older
1 2
/*
 * This file is part of libaacs
3
 * Copyright (C) 2009-2010  Obliter0n
npzacs's avatar
npzacs committed
4
 * Copyright (C) 2009-2010  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
struct aacs {
npzacs's avatar
npzacs committed
48 49 50 51 52
    /* current disc */
    char     *path;
    int       mkb_version;
    uint8_t   disc_id[20];

53 54
    /* VID is cached for BD-J */
    uint8_t   vid[16];
55 56
    /* PMSN is cached for BD-J */
    uint8_t   pmsn[16];
npzacs's avatar
npzacs committed
57 58 59 60

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

npzacs's avatar
npzacs committed
62 63 64 65 66 67
    /* CPS unit of currently selected title */
    uint16_t  current_cps_unit;

    /* title -> CPS unit mappings */
    uint32_t  num_titles;
    uint16_t *cps_units;  /* [0] = first play ; [1] = top menu ; [2] = title 1 ... */
68 69 70 71

    /* bus encryption */
    int       bee;        /* bus encryption enabled flag in content certificate */
    int       bec;        /* bus encryption capable flag in drive certificate */
72
    uint8_t   read_data_key[16];
73 74 75 76

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

79 80
static const uint8_t empty_key[] = "\x00\x00\x00\x00\x00\x00\x00\x00"
                                   "\x00\x00\x00\x00\x00\x00\x00\x00";
81 82
static const uint8_t aacs_iv[]   = "\x0b\xa0\xf8\xdd\xfe\xa6\x1f\xb3"
                                   "\xd8\xdf\x9f\x56\x6a\x05\x0f\x78";
83

84 85
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
86
                        uint8_t *mk)
cRTrn13's avatar
cRTrn13 committed
87
{
88
    gcry_cipher_hd_t gcry_h;
npzacs's avatar
npzacs committed
89
    int a;
cRTrn13's avatar
cRTrn13 committed
90
    uint8_t dec_vd[16];
91
    char str[40];
cRTrn13's avatar
cRTrn13 committed
92

93
    DEBUG(DBG_AACS, "Validate processing key %s...\n", print_hex(str, pk, 16));
cRTrn13's avatar
cRTrn13 committed
94
    DEBUG(DBG_AACS, " Using:\n");
95 96 97
    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));
98

99 100 101
    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);
102

cRTrn13's avatar
cRTrn13 committed
103 104 105 106
    for (a = 0; a < 4; a++) {
        mk[a + 12] ^= uv[a];
    }

107 108 109
    gcry_cipher_setkey(gcry_h, mk, 16);
    gcry_cipher_decrypt (gcry_h, dec_vd, 16, vd, 16);
    gcry_cipher_close(gcry_h);
110

cRTrn13's avatar
cRTrn13 committed
111
    if (!memcmp(dec_vd, "\x01\x23\x45\x67\x89\xAB\xCD\xEF", 8)) {
npzacs's avatar
npzacs committed
112
        DEBUG(DBG_AACS, "Processing key %s is valid!\n", print_hex(str, pk, 16));
npzacs's avatar
npzacs committed
113
        return AACS_SUCCESS;
cRTrn13's avatar
cRTrn13 committed
114 115
    }

npzacs's avatar
npzacs committed
116
    return AACS_ERROR_NO_PK;
cRTrn13's avatar
cRTrn13 committed
117
}
118

119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
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);
}

static void _update_drl(MKB *mkb)
{
    uint32_t version = mkb_version(mkb);
    uint32_t cache_version;

    if (!cache_get("drl", &cache_version, NULL, NULL) || cache_version < version) {
        size_t drl_len;
        const uint8_t *drl_rec = mkb_drive_revokation_entries(mkb, &drl_len);
        const uint8_t *v_rec   = mkb_type_and_version_record(mkb);

        if (drl_rec && v_rec) {
            drl_rec -= 4;
            drl_len += 4;

            uint8_t *data = malloc(12 + drl_len);
            memcpy(data,      v_rec,   12);
            memcpy(data + 12, drl_rec, drl_len);
            if (!_rl_verify_signature(data, drl_len + 12)) {
                DEBUG(DBG_AACS | DBG_CRIT, "invalid drive revocation list signature, not using it\n");
            } else {
                cache_save("drl", version, data, drl_len + 12);
            }
            X_FREE(data);
        }
    }
}

159
static int _calc_mk(AACS *aacs, uint8_t *mk, pk_list *pkl)
cRTrn13's avatar
keyfile  
cRTrn13 committed
160 161 162
{
    int a, num_uvs = 0;
    size_t len;
163
    uint8_t *buf = NULL;
cRTrn13's avatar
keyfile  
cRTrn13 committed
164
    MKB *mkb = NULL;
165
    const uint8_t *rec, *uvs;
cRTrn13's avatar
keyfile  
cRTrn13 committed
166

167
    /* Skip if retrieved from config file */
168 169 170
    if (memcmp(mk, empty_key, 16)) {
        return AACS_SUCCESS;
    }
171

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

npzacs's avatar
npzacs committed
174
    if ((mkb = mkb_open(aacs->path))) {
175
        DEBUG(DBG_AACS, "Get UVS...\n");
176
        _update_drl(mkb);
npzacs's avatar
npzacs committed
177
        aacs->mkb_version = mkb_version(mkb);
178 179 180 181 182 183 184 185
        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
186

187 188
        DEBUG(DBG_AACS, "Get cvalues...\n");
        rec = mkb_cvalues(mkb, &len);
189

npzacs's avatar
npzacs committed
190
        for (; pkl; pkl = pkl->next) {
191 192 193
                DEBUG(DBG_AACS, "Trying processing key...\n");

                for (a = 0; a < num_uvs; a++) {
npzacs's avatar
npzacs committed
194
                    if (AACS_SUCCESS == _validate_pk(pkl->key, rec + a * 16, uvs + 1 + a * 5,
195
                      mkb_mk_dv(mkb), mk)) {
196 197
                        mkb_close(mkb);
                        X_FREE(buf);
198

199
                        char str[40];
200
                        DEBUG(DBG_AACS, "Media key: %s\n", print_hex(str, mk, 16));
npzacs's avatar
npzacs committed
201
                        return AACS_SUCCESS;
202 203
                    }
                }
cRTrn13's avatar
keyfile  
cRTrn13 committed
204 205
            }

206 207
        mkb_close(mkb);
        X_FREE(buf);
cRTrn13's avatar
keyfile  
cRTrn13 committed
208

npzacs's avatar
npzacs committed
209
        DEBUG(DBG_AACS | DBG_CRIT, "Error calculating media key. Missing right processing key ?\n");
npzacs's avatar
npzacs committed
210
        return AACS_ERROR_NO_PK;
npzacs's avatar
npzacs committed
211
    }
npzacs's avatar
npzacs committed
212

npzacs's avatar
npzacs committed
213
    DEBUG(DBG_AACS | DBG_CRIT, "Error opening %s/AACS/MKB_RO.inf\n", aacs->path);
npzacs's avatar
npzacs committed
214
    return AACS_ERROR_CORRUPTED_DISC;
cRTrn13's avatar
keyfile  
cRTrn13 committed
215
}
216

217 218 219 220
static MKB *_get_hrl_mkb(MMC *mmc)
{
    MKB     *mkb = NULL;
    uint8_t *data;
npzacs's avatar
npzacs committed
221
    int      mkb_size;
222

npzacs's avatar
npzacs committed
223
    data = mmc_read_mkb(mmc, 0, &mkb_size);
224 225

    /* check acquired hrl signature */
npzacs's avatar
npzacs committed
226 227 228
    if (data && mkb_size > 0) {
        if (_rl_verify_signature(data, mkb_size)) {
            mkb = mkb_init(data, mkb_size);
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 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
            DEBUG(DBG_AACS, "Partial hrl mkb read. Version: %d\n", mkb_version(mkb));
        } else {
            DEBUG(DBG_AACS | DBG_CRIT, "invalid host revocation list signature, not using it\n");
            X_FREE(data);
        }
    }

    if (mkb) {
        /* use latest version, keep cache up-to-date */
        uint32_t size;
        size = mkb_data_size(mkb);
        data = cache_get_or_update("hrl", mkb_data(mkb), &size, mkb_version(mkb));

        if (!_rl_verify_signature(data, size)) {
            DEBUG(DBG_AACS | DBG_CRIT, "invalid cached revocation list signature, replacing it\n");
            cache_save("hrl", mkb_version(mkb), mkb_data(mkb), mkb_data_size(mkb));
            X_FREE(data);
        } else {
            /* use cached version */
            mkb_close(mkb);
            mkb = mkb_init(data, size);
        }

    } else {
        /* use cached version */
        uint32_t size;
        data = cache_get_or_update("hrl", NULL, &size, 0);
        if (data && size > 0) {
            if (!_rl_verify_signature(data, size)) {
                mkb = mkb_init(data, size);
            } else {
                DEBUG(DBG_AACS | DBG_CRIT, "invalid cached revocation list signature, deleting cache\n");
                cache_remove("hrl");
            }
        }
    }


    if (mkb) {
        DEBUG(DBG_AACS, "Using hrl version %d\n", mkb_version(mkb));
    }

    return mkb;
}

npzacs's avatar
npzacs committed
274
static int _mmc_read_auth(AACS *aacs, cert_list *hcl, int type, uint8_t *p1, uint8_t *p2)
cRTrn13's avatar
openssl  
cRTrn13 committed
275
{
cRTrn13's avatar
cRTrn13 committed
276
    MMC* mmc = NULL;
npzacs's avatar
npzacs committed
277
    if (!(mmc = mmc_open(aacs->path))) {
npzacs's avatar
npzacs committed
278
        return AACS_ERROR_MMC_OPEN;
279 280
    }

npzacs's avatar
npzacs committed
281 282
    int error_code = AACS_ERROR_NO_CERT;

283
    MKB *hrl_mkb = _get_hrl_mkb(mmc);
284
    const uint8_t *drive_cert = mmc_get_drive_cert(mmc);
285

npzacs's avatar
npzacs committed
286
    for (; hcl ; hcl = hcl->next) {
287 288 289

        char tmp_str[2*92+1];

npzacs's avatar
npzacs committed
290
        if (!crypto_aacs_verify_host_cert(hcl->host_cert)) {
npzacs's avatar
npzacs committed
291
            DEBUG(DBG_AACS, "Not using invalid host certificate %s.\n",
npzacs's avatar
npzacs committed
292
                  print_hex(tmp_str, hcl->host_cert, 92));
npzacs's avatar
npzacs committed
293 294
            continue;
        }
295

npzacs's avatar
npzacs committed
296
        if (mkb_host_cert_is_revoked(hrl_mkb, hcl->host_cert + 4) > 0) {
297
            DEBUG(DBG_AACS | DBG_CRIT, "Host certificate %s has been revoked.\n",
npzacs's avatar
npzacs committed
298
                  print_hex(tmp_str, hcl->host_cert + 4, 6));
299 300 301 302
            error_code = AACS_ERROR_CERT_REVOKED;
            //continue;
        }

npzacs's avatar
npzacs committed
303
        if (drive_cert && (drive_cert[1] & 0x01) && !(hcl->host_cert[1] & 0x01)) {
304
            DEBUG(DBG_AACS, "Certificate (id 0x%s) does not support bus encryption\n",
npzacs's avatar
npzacs committed
305
                  print_hex(tmp_str, hcl->host_cert + 4, 6));
306 307 308
            //continue;
        }

309
        DEBUG(DBG_AACS, "Trying host certificate (id 0x%s)...\n",
npzacs's avatar
npzacs committed
310
              print_hex(tmp_str, hcl->host_cert + 4, 6));
311

npzacs's avatar
npzacs committed
312
        int mmc_result = mmc_read_auth(mmc, hcl->host_priv_key, hcl->host_cert, type, p1, p2);
npzacs's avatar
npzacs committed
313 314
        switch (mmc_result) {
            case MMC_SUCCESS:
315
                mkb_close(hrl_mkb);
npzacs's avatar
npzacs committed
316 317 318 319 320 321 322 323 324
                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;
325 326 327
        }
    }

328
    mkb_close(hrl_mkb);
329 330
    mmc_close(mmc);

npzacs's avatar
npzacs committed
331
    return error_code;
332
}
cRTrn13's avatar
openssl  
cRTrn13 committed
333

npzacs's avatar
npzacs committed
334
static int _read_vid(AACS *aacs, cert_list *hcl)
335
{
npzacs's avatar
npzacs committed
336 337 338
    /* Use VID given in config file if available */
    if (memcmp(aacs->vid, empty_key, 16)) {
        return AACS_SUCCESS;
339 340
    }

npzacs's avatar
npzacs committed
341 342 343 344 345 346
    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);
347 348 349 350
    }
    return error_code;
}

npzacs's avatar
npzacs committed
351
static int _read_read_data_key(AACS *aacs, cert_list *hcl)
Janusz Dziemidowicz's avatar
Janusz Dziemidowicz committed
352
{
npzacs's avatar
npzacs committed
353 354 355
    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
356
    }
npzacs's avatar
npzacs committed
357 358
    return error_code;
}
Janusz Dziemidowicz's avatar
Janusz Dziemidowicz committed
359

npzacs's avatar
npzacs committed
360 361 362 363 364
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
365 366 367 368
    }
    return error_code;
}

369
static int _calc_vuk(AACS *aacs, uint8_t *mk, uint8_t *vuk, config_file *cf)
370
{
npzacs's avatar
npzacs committed
371 372
    int error_code;

373
    /* Skip if retrieved from config file */
374
    if (memcmp(vuk, empty_key, 16)) {
npzacs's avatar
npzacs committed
375 376 377
        DEBUG(DBG_AACS, "Using VUK from config file\n");
        return AACS_SUCCESS;
    }
378

npzacs's avatar
npzacs committed
379
    /* get cached vuk */
380
    if (keycache_find("vuk", aacs->disc_id, vuk, 16)) {
npzacs's avatar
npzacs committed
381
        DEBUG(DBG_AACS, "Using cached VUK\n");
npzacs's avatar
npzacs committed
382
        return AACS_SUCCESS;
npzacs's avatar
npzacs committed
383 384
    }

385 386 387 388
    if (!cf) {
        return AACS_ERROR_NO_CONFIG;
    }

389
    /* make sure we have media key */
390
    error_code = _calc_mk(aacs, mk, cf->pkl);
npzacs's avatar
npzacs committed
391 392
    if (error_code != AACS_SUCCESS) {
        return error_code;
393 394
    }

npzacs's avatar
npzacs committed
395
    /* acquire VID */
396
    error_code = _read_vid(aacs, cf->host_cert_list);
npzacs's avatar
npzacs committed
397 398 399
    if (error_code != AACS_SUCCESS) {
        return error_code;
    }
400

npzacs's avatar
npzacs committed
401
    /* calculate VUK */
402

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

npzacs's avatar
npzacs committed
405
    int a;
npzacs's avatar
npzacs committed
406
    for (a = 0; a < 16; a++) {
407
        vuk[a] ^= aacs->vid[a];
npzacs's avatar
npzacs committed
408
    }
409

npzacs's avatar
npzacs committed
410
    char str[40];
411
    DEBUG(DBG_AACS, "Volume unique key: %s\n", print_hex(str, vuk, 16));
412

npzacs's avatar
npzacs committed
413
    /* cache vuk */
414
    keycache_save("vuk", aacs->disc_id, vuk, 16);
npzacs's avatar
npzacs committed
415

npzacs's avatar
npzacs committed
416
    return AACS_SUCCESS;
cRTrn13's avatar
openssl  
cRTrn13 committed
417 418
}

419 420
static uint16_t _read_u16(AACS_FILE_H *fp)
{
npzacs's avatar
npzacs committed
421
  uint8_t data[2] = {0, 0};
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467

  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
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
static AACS_FILE_H *_open_unit_key_file(const char *path)
{
    AACS_FILE_H *fp;
    char        *f_name;

    f_name = str_printf("%s/AACS/Unit_Key_RO.inf", path);
    fp = file_open(f_name, "rb");

    if (!fp) {
        DEBUG(DBG_AACS | DBG_CRIT, "Error opening unit key file %s\n", f_name);
    }

    X_FREE(f_name);
    return fp;
}

484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
static AACS_FILE_H *_open_content_certificate_file(const char *path)
{
    AACS_FILE_H *fp;
    char        *f_name;

    f_name = str_printf("%s/AACS/Content000.cer", path);
    fp = file_open(f_name, "rb");

    if (!fp) {
        DEBUG(DBG_AACS | DBG_CRIT, "Error opening content certificate file %s\n", f_name);
    }

    X_FREE(f_name);
    return fp;
}

npzacs's avatar
npzacs committed
500
/* Function that collects keys from keydb config entry */
501 502
static void _find_config_entry(AACS *aacs, title_entry_list *ce,
                               uint8_t *mk, uint8_t *vuk)
npzacs's avatar
npzacs committed
503 504 505 506 507 508 509
{
    char str[48];

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

        while (ce && ce->entry.discid) {
npzacs's avatar
npzacs committed
510
            if (!memcmp(aacs->disc_id, ce->entry.discid, 20)) {
npzacs's avatar
npzacs committed
511
                DEBUG(DBG_AACS, "Found config entry for discid %s\n",
npzacs's avatar
npzacs committed
512
                      print_hex(str, ce->entry.discid, 20));
npzacs's avatar
npzacs committed
513 514 515 516 517 518 519 520 521 522
                break;
            }

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

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

            DEBUG(DBG_AACS, "Found media key for %s: %s\n",
526
                  ce->entry.discid, print_hex(str, mk, 16));
npzacs's avatar
npzacs committed
527 528 529 530 531 532 533 534 535 536 537
        }

        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) {
538
            hexstring_to_hex_array(vuk, 16, ce->entry.vuk);
npzacs's avatar
npzacs committed
539 540

            DEBUG(DBG_AACS, "Found volume unique key for %s: %s\n",
541
                  ce->entry.discid, print_hex(str, vuk, 16));
npzacs's avatar
npzacs committed
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
        }

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

564
static int _calc_uks(AACS *aacs, config_file *cf)
cRTrn13's avatar
openssl  
cRTrn13 committed
565
{
566
    AACS_FILE_H *fp = NULL;
567
    uint8_t  buf[16];
568
    uint64_t f_pos;
569
    unsigned int i;
npzacs's avatar
npzacs committed
570
    int error_code;
cRTrn13's avatar
openssl  
cRTrn13 committed
571

572 573
    uint8_t mk[16] = {0}, vuk[16] = {0};

574 575 576
    if (cf) {
        DEBUG(DBG_AACS, "Searching for keydb config entry...\n");
        _find_config_entry(aacs, cf->list, mk, vuk);
577

578 579 580 581
        /* Skip if retrieved from config file */
        if (aacs->uks) {
            return AACS_SUCCESS;
        }
582
    }
583

584
    /* Make sure we have VUK */
585
    error_code = _calc_vuk(aacs, mk, vuk, cf);
npzacs's avatar
npzacs committed
586 587
    if (error_code != AACS_SUCCESS) {
        return error_code;
588
    }
589

590 591
    DEBUG(DBG_AACS, "Calculate CPS unit keys...\n");

npzacs's avatar
npzacs committed
592
    fp = _open_unit_key_file(aacs->path);
npzacs's avatar
npzacs committed
593 594 595
    if (!fp) {
        return AACS_ERROR_CORRUPTED_DISC;
    }
cRTrn13's avatar
openssl  
cRTrn13 committed
596

npzacs's avatar
npzacs committed
597 598
    if ((file_read(fp, buf, 4)) == 4) {
        f_pos = MKINT_BE32(buf);
npzacs's avatar
npzacs committed
599

npzacs's avatar
npzacs committed
600 601 602 603
        // 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
604

npzacs's avatar
npzacs committed
605 606
            X_FREE(aacs->uks);
            aacs->uks = calloc(aacs->num_uks, 16);
npzacs's avatar
npzacs committed
607

npzacs's avatar
npzacs committed
608
            DEBUG(DBG_AACS, "%d CPS unit keys\n", aacs->num_uks);
npzacs's avatar
npzacs committed
609

npzacs's avatar
npzacs committed
610 611 612 613 614
        } 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
615

npzacs's avatar
npzacs committed
616 617 618
        // Read keys
        for (i = 0; i < aacs->num_uks; i++) {
            f_pos += 48;
cRTrn13's avatar
openssl  
cRTrn13 committed
619

npzacs's avatar
npzacs committed
620 621 622 623 624 625
            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
626
            }
cRTrn13's avatar
openssl  
cRTrn13 committed
627

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

npzacs's avatar
npzacs committed
630 631 632
            char str[40];
            DEBUG(DBG_AACS, "Unit key %d: %s\n", i,
                  print_hex(str, aacs->uks + 16*i, 16));
633 634
        }

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

638
        file_close(fp);
cRTrn13's avatar
openssl  
cRTrn13 committed
639

npzacs's avatar
npzacs committed
640 641 642 643 644 645 646
        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
647 648
}

649 650
static int _calc_title_hash(const char *path, uint8_t *title_hash)
{
651
    AACS_FILE_H *fp = NULL;
652 653 654
    uint8_t *ukf_buf;
    char     str[48];
    int64_t  f_size;
npzacs's avatar
npzacs committed
655
    int      result = AACS_SUCCESS;
656

npzacs's avatar
npzacs committed
657 658 659
    fp = _open_unit_key_file(path);
    if (!fp) {
        return AACS_ERROR_CORRUPTED_DISC;
660 661 662 663 664 665 666 667
    }

    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
668 669 670
    if ((file_read(fp, ukf_buf, f_size)) == f_size) {
        crypto_aacs_title_hash(ukf_buf, f_size, title_hash);
        DEBUG(DBG_AACS, "Disc ID: %s\n", print_hex(str, title_hash, 20));
cRTrn13's avatar
cRTrn13 committed
671

npzacs's avatar
npzacs committed
672 673 674
    } else {
        result = AACS_ERROR_CORRUPTED_DISC;
        DEBUG(DBG_AACS | DBG_CRIT, "Failed to read %"PRIu64" bytes from unit key file %s/AACS/Unit_Key_RO.inf", f_size, path);
675 676 677 678 679
    }

    file_close(fp);
    X_FREE(ukf_buf);

npzacs's avatar
npzacs committed
680
    return result;
681
}
cRTrn13's avatar
cRTrn13 committed
682

683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726
static int _get_bus_encryption_enabled(const char *path)
{
    AACS_FILE_H *fp = NULL;
    uint8_t buf[2];
    int bee = 0;

    fp = _open_content_certificate_file(path);
    if (!fp) {
        DEBUG(DBG_AACS | DBG_CRIT, "Unable to open content certificate\n");
        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
727
static int _verify_ts(uint8_t *buf, size_t size)
728
{
729 730
    uint8_t *ptr;

cRTrn13's avatar
cRTrn13 committed
731 732 733 734 735 736 737
    if (size < 192) {
        return 1;
    }

    for (ptr=buf; ptr < buf+192; ptr++) {
        int failed = 0;
        if (*ptr == 0x47) {
738 739 740 741
            uint8_t *ptr2;

            for (ptr2=ptr; ptr2 < buf + size; ptr2 += 192) {
                if (*ptr2 != 0x47) {
cRTrn13's avatar
cRTrn13 committed
742 743
                    failed = 1;
                    break;
744 745
                }
            }
cRTrn13's avatar
cRTrn13 committed
746 747 748
            if (!failed) {
                return 1;
            }
749 750 751 752
        }
        ptr++;
    }

cRTrn13's avatar
cRTrn13 committed
753
    DEBUG(DBG_AACS, "Failed to verify TS!\n");
754

cRTrn13's avatar
cRTrn13 committed
755
    return 0;
756 757
}

758
#define ALIGNED_UNIT_LEN 6144
759
static int _decrypt_unit(AACS *aacs, uint8_t *out_buf, const uint8_t *in_buf, uint32_t curr_uk)
cRTrn13's avatar
cRTrn13 committed
760
{
761 762
    gcry_cipher_hd_t gcry_h;
    int a;
763
    uint8_t key[16];
764 765 766

    gcry_cipher_open(&gcry_h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0);
    gcry_cipher_setkey(gcry_h, aacs->uks + curr_uk * 16, 16);
767
    gcry_cipher_encrypt(gcry_h, key, 16, in_buf, 16);
768
    gcry_cipher_close(gcry_h);
cRTrn13's avatar
cRTrn13 committed
769

cRTrn13's avatar
cRTrn13 committed
770
    for (a = 0; a < 16; a++) {
771
        key[a] ^= in_buf[a];
cRTrn13's avatar
cRTrn13 committed
772 773
    }

774 775
    memcpy(out_buf, in_buf, 16); /* first 16 bytes are plain */

776 777
    gcry_cipher_open(&gcry_h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0);
    gcry_cipher_setkey(gcry_h, key, 16);
778
    gcry_cipher_setiv(gcry_h, aacs_iv, 16);
779
    gcry_cipher_decrypt(gcry_h, out_buf + 16, ALIGNED_UNIT_LEN - 16, in_buf + 16, ALIGNED_UNIT_LEN - 16);
780
    gcry_cipher_close(gcry_h);
cRTrn13's avatar
cRTrn13 committed
781

782
    if (_verify_ts(out_buf, ALIGNED_UNIT_LEN)) {
cRTrn13's avatar
cRTrn13 committed
783 784 785
        return 1;
    }

786
    if (curr_uk < aacs->num_uks - 1) {
787
        return _decrypt_unit(aacs, out_buf, in_buf, curr_uk++);
npzacs's avatar
npzacs committed
788 789
    }

cRTrn13's avatar
cRTrn13 committed
790 791 792
    return 0;
}

793
#define SECTOR_LEN 2048
794
static void _decrypt_bus(AACS *aacs, uint8_t *buf)
795 796 797 798 799
{
    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);
800
    gcry_cipher_setiv(gcry_h, aacs_iv, 16);
801
    gcry_cipher_decrypt(gcry_h, buf + 16, SECTOR_LEN - 16, NULL, 0);
802 803 804
    gcry_cipher_close(gcry_h);
}

npzacs's avatar
npzacs committed
805 806
void aacs_get_version(int *major, int *minor, int *micro)
{
npzacs's avatar
npzacs committed
807 808 809
    *major = AACS_VERSION_MAJOR;
    *minor = AACS_VERSION_MINOR;
    *micro = AACS_VERSION_MICRO;
npzacs's avatar
npzacs committed
810 811
}

npzacs's avatar
npzacs committed
812
/* aacs_open2() wrapper for backwards compability */
cRTrn13's avatar
cRTrn13 committed
813
AACS *aacs_open(const char *path, const char *configfile_path)
npzacs's avatar
npzacs committed
814 815 816 817 818 819 820 821 822 823 824 825 826 827
{
    int error_code;
    AACS *aacs;

    aacs = aacs_open2(path, configfile_path, &error_code);
    if (error_code == AACS_SUCCESS) {
        return aacs;
    }

    aacs_close(aacs);
    return NULL;
}

AACS *aacs_open2(const char *path, const char *configfile_path, int *error_code)
cRTrn13's avatar
cRTrn13 committed
828
{
npzacs's avatar
npzacs committed
829
    DEBUG(DBG_AACS, "libaacs "AACS_VERSION_STRING" [%zd]\n", sizeof(AACS));
cRTrn13's avatar
cRTrn13 committed
830

831
    DEBUG(DBG_AACS, "Initializing libgcrypt...\n");
npzacs's avatar
npzacs committed
832
    if (!crypto_init()) {
npzacs's avatar
npzacs committed
833
        DEBUG(DBG_AACS | DBG_CRIT, "Failed to initialize libgcrypt\n");
834 835
        return NULL;
    }
836

cRTrn13's avatar
cRTrn13 committed
837
    AACS *aacs = calloc(1, sizeof(AACS));
838
    config_file *cf;
839

npzacs's avatar
npzacs committed
840 841
    aacs->path = str_printf("%s", path);

npzacs's avatar
npzacs committed
842 843 844 845 846
    *error_code = _calc_title_hash(path, aacs->disc_id);
    if (*error_code != AACS_SUCCESS) {
        aacs_close(aacs);
        return NULL;
    }
npzacs's avatar
npzacs committed
847

848 849
    cf = keydbcfg_config_load(configfile_path);

npzacs's avatar
npzacs committed
850
    DEBUG(DBG_AACS, "Starting AACS waterfall...\n");
851 852 853 854
    *error_code = _calc_uks(aacs, cf);
    if (*error_code != AACS_SUCCESS) {
        DEBUG(DBG_AACS, "Failed to initialize AACS!\n");
    }
cRTrn13's avatar
cRTrn13 committed
855

856 857 858
    aacs->bee = _get_bus_encryption_enabled(path);
    aacs->bec = _get_bus_encryption_capable(path);

npzacs's avatar
npzacs committed
859
    if (*error_code == AACS_SUCCESS && aacs->bee && aacs->bec) {
860 861 862 863 864 865

        if (!cf) {
            *error_code = AACS_ERROR_NO_CONFIG;
            return aacs;
        }

866 867 868 869
        *error_code = _read_read_data_key(aacs, cf->host_cert_list);
        if (*error_code != AACS_SUCCESS) {
            DEBUG(DBG_AACS | DBG_CRIT, "Unable to initialize bus encryption required by drive and disc\n");
        }
npzacs's avatar
npzacs committed
870
    }
871

872 873 874 875
    keydbcfg_config_file_close(cf);

    DEBUG(DBG_AACS, "AACS initialized!\n");

npzacs's avatar
npzacs committed
876
    return aacs;
cRTrn13's avatar
cRTrn13 committed
877 878
}

cRTrn13's avatar
cRTrn13 committed
879
void aacs_close(AACS *aacs)
cRTrn13's avatar
cRTrn13 committed
880
{
npzacs's avatar
npzacs committed
881 882 883
    if (!aacs)
        return;

npzacs's avatar
npzacs committed
884 885 886 887 888
    /* erase sensitive data */
    if (aacs->uks) {
        memset(aacs->uks, 0, 16 * aacs->num_uks);
    }

889
    X_FREE(aacs->uks);
890
    X_FREE(aacs->cps_units);
npzacs's avatar
npzacs committed
891
    X_FREE(aacs->path);
892

893
    DEBUG(DBG_AACS, "AACS destroyed!\n");
cRTrn13's avatar
cRTrn13 committed
894

npzacs's avatar
npzacs committed
895 896 897
    /* erase sensitive data */
    memset(aacs, 0, sizeof(*aacs));

cRTrn13's avatar
cRTrn13 committed
898 899 900
    X_FREE(aacs);
}