aacs.c 18.7 KB
Newer Older
1 2
/*
 * This file is part of libaacs
3
 * Copyright (C) 2009-2010  Obliter0n
4
 *
gates's avatar
gates committed
5 6 7 8
 * 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.
9
 *
gates's avatar
gates committed
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
gates's avatar
gates committed
12 13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
14
 *
gates's avatar
gates committed
15 16 17
 * 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/>.
18 19
 */

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

npzacs's avatar
npzacs committed
24 25
#include <util/attributes.h>

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

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

npzacs's avatar
npzacs committed
44

npzacs's avatar
npzacs committed
45 46 47 48
struct aacs {
    uint8_t pk[16], mk[16], vuk[16], vid[16], *uks;
    uint32_t num_uks;
    struct config_file_t *cf;
49
    struct title_entry_list_t *ce;
50 51 52 53

    uint32_t num_titles;
    uint16_t current_cps_unit;
    uint16_t *cps_units;  /* [0] = first play ; [1] = top menu ; [2] = title 1 ... */
npzacs's avatar
npzacs committed
54 55
};

56 57 58
static const uint8_t empty_key[] = "\x00\x00\x00\x00\x00\x00\x00\x00"
                                   "\x00\x00\x00\x00\x00\x00\x00\x00";

npzacs's avatar
npzacs committed
59 60
static int _validate_pk(uint8_t *pk, uint8_t *cvalue, uint8_t *uv, uint8_t *vd,
                        uint8_t *mk)
cRTrn13's avatar
cRTrn13 committed
61
{
62 63
    gcry_cipher_hd_t gcry_h;
    int a, ret = 0;
cRTrn13's avatar
cRTrn13 committed
64
    uint8_t dec_vd[16];
65
    char str[40];
cRTrn13's avatar
cRTrn13 committed
66

67
    DEBUG(DBG_AACS, "Validate processing key %s...\n", print_hex(str, pk, 16));
cRTrn13's avatar
cRTrn13 committed
68
    DEBUG(DBG_AACS, " Using:\n");
69 70 71
    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));
72

73 74 75
    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);
76

cRTrn13's avatar
cRTrn13 committed
77 78 79 80
    for (a = 0; a < 4; a++) {
        mk[a + 12] ^= uv[a];
    }

81 82 83
    gcry_cipher_setkey(gcry_h, mk, 16);
    gcry_cipher_decrypt (gcry_h, dec_vd, 16, vd, 16);
    gcry_cipher_close(gcry_h);
84

cRTrn13's avatar
cRTrn13 committed
85 86
    if (!memcmp(dec_vd, "\x01\x23\x45\x67\x89\xAB\xCD\xEF", 8)) {
        DEBUG(DBG_AACS, "Processing key is valid!\n");
87
        ret = 1;
cRTrn13's avatar
cRTrn13 committed
88 89
    }

90
    return ret;
cRTrn13's avatar
cRTrn13 committed
91
}
92

npzacs's avatar
npzacs committed
93
static int _calc_mk(AACS *aacs, const char *path)
cRTrn13's avatar
keyfile  
cRTrn13 committed
94 95 96
{
    int a, num_uvs = 0;
    size_t len;
97
    uint8_t *buf = NULL, *rec, *uvs;
cRTrn13's avatar
keyfile  
cRTrn13 committed
98 99
    MKB *mkb = NULL;

100 101 102 103
    /* Skip if retrieved from config file */
    if (memcmp(aacs->mk, empty_key, 16))
      return 1;

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

106 107 108 109 110 111 112 113 114 115
    if ((mkb = mkb_open(path))) {
        DEBUG(DBG_AACS, "Get UVS...\n");
        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
116

117 118
        DEBUG(DBG_AACS, "Get cvalues...\n");
        rec = mkb_cvalues(mkb, &len);
119 120 121 122 123
        if (aacs->cf->pkl) {
            pk_list *pkcursor = aacs->cf->pkl;
            while (pkcursor && pkcursor->key) {
                hexstring_to_hex_array(aacs->pk, sizeof(aacs->pk),
                                       pkcursor->key);
124 125 126
                DEBUG(DBG_AACS, "Trying processing key...\n");

                for (a = 0; a < num_uvs; a++) {
gates's avatar
gates committed
127 128
                    if (_validate_pk(aacs->pk, rec + a * 16, uvs + 1 + a * 5,
                      mkb_mk_dv(mkb), aacs->mk)) {
129 130
                        mkb_close(mkb);
                        X_FREE(buf);
131

132 133
                        char str[40];
                        DEBUG(DBG_AACS, "Media key: %s\n", print_hex(str, aacs->mk,
gates's avatar
gates committed
134
                                                                     16));
135 136 137 138
                        return 1;
                    }
                }

139
                pkcursor = pkcursor->next;
cRTrn13's avatar
keyfile  
cRTrn13 committed
140
            }
141
        }
cRTrn13's avatar
keyfile  
cRTrn13 committed
142

143 144
        mkb_close(mkb);
        X_FREE(buf);
cRTrn13's avatar
keyfile  
cRTrn13 committed
145 146 147 148
    }

    return 0;
}
149

npzacs's avatar
npzacs committed
150
static int _calc_vuk(AACS *aacs, const char *path)
cRTrn13's avatar
openssl  
cRTrn13 committed
151
{
152
    int a;
cRTrn13's avatar
cRTrn13 committed
153
    MMC* mmc = NULL;
cRTrn13's avatar
openssl  
cRTrn13 committed
154

155 156 157 158
    /* Skip if retrieved from config file */
    if (memcmp(aacs->vuk, empty_key, 16))
      return 1;

159 160
    DEBUG(DBG_AACS, "Calculate volume unique key...\n");

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
    /* Use VID given in config file if available */
    if (memcmp(aacs->vid, empty_key, 16))
    {
        gcry_cipher_hd_t gcry_h;
        gcry_cipher_open(&gcry_h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0);
        gcry_cipher_setkey(gcry_h, aacs->mk, 16);
        gcry_cipher_decrypt(gcry_h, aacs->vuk, 16, aacs->vid, 16);
        gcry_cipher_close(gcry_h);

        for (a = 0; a < 16; a++) {
            aacs->vuk[a] ^= aacs->vid[a];
        }

        char str[40];
        DEBUG(DBG_AACS, "Volume unique key: %s\n",
              print_hex(str, aacs->vuk, 16));

        return 1;
    }

181 182 183 184 185 186 187 188 189 190 191 192
    cert_list *hccursor = aacs->cf->host_cert_list;
    while (hccursor && hccursor->host_priv_key) {
        uint8_t priv_key[20], cert[92], nonce[20], key_point[40];
        hexstring_to_hex_array(priv_key, sizeof(priv_key),
                               hccursor->host_priv_key);
        hexstring_to_hex_array(cert, sizeof(cert), hccursor->host_cert);
        hexstring_to_hex_array(nonce, sizeof(nonce), hccursor->host_nonce);
        hexstring_to_hex_array(key_point, sizeof(key_point),
                               hccursor->host_key_point);

        if ((mmc = mmc_open(path, priv_key, cert, nonce, key_point))) {
            if (mmc_read_vid(mmc, aacs->vid)) {
193 194 195 196 197 198
                gcry_cipher_hd_t gcry_h;
                gcry_cipher_open(&gcry_h, GCRY_CIPHER_AES,
                                 GCRY_CIPHER_MODE_ECB, 0);
                gcry_cipher_setkey(gcry_h, aacs->mk, 16);
                gcry_cipher_decrypt(gcry_h, aacs->vuk, 16, aacs->vid, 16);
                gcry_cipher_close(gcry_h);
cRTrn13's avatar
cRTrn13 committed
199

200 201 202 203 204
                for (a = 0; a < 16; a++) {
                    aacs->vuk[a] ^= aacs->vid[a];
                }

                mmc_close(mmc);
cRTrn13's avatar
openssl  
cRTrn13 committed
205

206 207 208
                char str[40];
                DEBUG(DBG_AACS, "Volume unique key: %s\n", print_hex(str, aacs->vuk,
                                                                    16));
209

210 211 212 213
                return 1;
            }

            mmc_close(mmc);
cRTrn13's avatar
openssl  
cRTrn13 committed
214 215
        }

216
        hccursor = hccursor->next;
cRTrn13's avatar
cRTrn13 committed
217
    }
cRTrn13's avatar
openssl  
cRTrn13 committed
218

219 220
    DEBUG(DBG_AACS, "Error calculating VUK!\n");

cRTrn13's avatar
openssl  
cRTrn13 committed
221 222 223
    return 0;
}

224 225 226 227 228 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
static uint16_t _read_u16(AACS_FILE_H *fp)
{
  uint8_t data[2];

  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
273
static int _calc_uks(AACS *aacs, const char *path)
cRTrn13's avatar
openssl  
cRTrn13 committed
274
{
275
    AACS_FILE_H *fp = NULL;
276 277
    char    *f_name;
    uint8_t  buf[16];
278
    uint64_t f_pos;
279
    unsigned int i;
cRTrn13's avatar
openssl  
cRTrn13 committed
280

281 282
    /* Skip if retrieved from config file */
    if (aacs->uks)
283
        return 1;
284 285 286

    /* Fail if we don't have a volume unique key */
    if (!memcmp(aacs->vuk, empty_key, 16))
287
        return 0;
288

289 290
    DEBUG(DBG_AACS, "Calculate CPS unit keys...\n");

291 292 293
    f_name = str_printf("/%s/AACS/Unit_Key_RO.inf", path);
    fp = file_open(f_name, "rb");
    X_FREE(f_name);
cRTrn13's avatar
openssl  
cRTrn13 committed
294

295
    if (fp) {
296
        if ((file_read(fp, buf, 4)) == 4) {
npzacs's avatar
npzacs committed
297
            f_pos = MKINT_BE32(buf);
cRTrn13's avatar
openssl  
cRTrn13 committed
298

npzacs's avatar
npzacs committed
299
            // Read number of keys
cRTrn13's avatar
cRTrn13 committed
300
            file_seek(fp, f_pos, SEEK_SET);
npzacs's avatar
npzacs committed
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
            if ((file_read(fp, buf, 2)) == 2) {
                aacs->num_uks = MKINT_BE16(buf);

                X_FREE(aacs->uks);
                aacs->uks = calloc(aacs->num_uks, 16);

                DEBUG(DBG_AACS, "%d CPS unit keys\n", aacs->num_uks);

            } else {
                aacs->num_uks = 0;
                DEBUG(DBG_AACS, "Error reading number of unit keys!\n");
            }

            // Read keys
            for (i = 0; i < aacs->num_uks; i++) {
                f_pos += 48;

                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;
                    break;
                }
cRTrn13's avatar
openssl  
cRTrn13 committed
324

325 326 327 328 329 330
                gcry_cipher_hd_t gcry_h;
                gcry_cipher_open(&gcry_h, GCRY_CIPHER_AES,
                                 GCRY_CIPHER_MODE_ECB, 0);
                gcry_cipher_setkey(gcry_h, aacs->vuk, 16);
                gcry_cipher_decrypt(gcry_h, aacs->uks + 16*i, 16, buf, 16);
                gcry_cipher_close(gcry_h);
cRTrn13's avatar
openssl  
cRTrn13 committed
331

332
                char str[40];
gates's avatar
gates committed
333
                DEBUG(DBG_AACS, "Unit key %d: %s\n", i,
334
                      print_hex(str, aacs->uks + 16*i, 16));
npzacs's avatar
npzacs committed
335
            }
cRTrn13's avatar
openssl  
cRTrn13 committed
336

337 338
            _read_uks_map(aacs, fp);

npzacs's avatar
npzacs committed
339
            file_close(fp);
cRTrn13's avatar
openssl  
cRTrn13 committed
340

npzacs's avatar
npzacs committed
341
            return aacs->num_uks;
342 343 344
        }

        file_close(fp);
cRTrn13's avatar
openssl  
cRTrn13 committed
345 346
    }

347 348
    DEBUG(DBG_AACS, "Could not calculate unit keys!\n");

cRTrn13's avatar
openssl  
cRTrn13 committed
349 350 351
    return 0;
}

352 353
static int _calc_title_hash(const char *path, uint8_t *title_hash)
{
354
    AACS_FILE_H *fp = NULL;
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
    uint8_t *ukf_buf;
    char     str[48];
    int64_t  f_size;
    char    *f_name;

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

    if (!(fp = file_open(f_name, "rb"))) {
        DEBUG(DBG_AACS, "Failed to open unit key file: %s!\n", f_name);
        X_FREE(f_name);
        return 0;
    }

    X_FREE(f_name);

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

    ukf_buf = malloc(f_size);

    if ((file_read(fp, ukf_buf, f_size)) != f_size) {
cRTrn13's avatar
cRTrn13 committed
377

378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
        DEBUG(DBG_AACS, "Failed to read %"PRIu64" bytes from unit key file!\n", f_size);

        file_close(fp);
        X_FREE(ukf_buf);

        return 0;
    }

    crypto_aacs_title_hash(ukf_buf, f_size, title_hash);
    DEBUG(DBG_AACS, "Disc ID: %s\n", print_hex(str, title_hash, 20));

    file_close(fp);
    X_FREE(ukf_buf);

    return 1;
}
cRTrn13's avatar
cRTrn13 committed
394

npzacs's avatar
npzacs committed
395
static int _verify_ts(uint8_t *buf, size_t size)
396
{
397 398
    uint8_t *ptr;

cRTrn13's avatar
cRTrn13 committed
399 400 401 402 403 404 405
    if (size < 192) {
        return 1;
    }

    for (ptr=buf; ptr < buf+192; ptr++) {
        int failed = 0;
        if (*ptr == 0x47) {
406 407 408 409
            uint8_t *ptr2;

            for (ptr2=ptr; ptr2 < buf + size; ptr2 += 192) {
                if (*ptr2 != 0x47) {
cRTrn13's avatar
cRTrn13 committed
410 411
                    failed = 1;
                    break;
412 413
                }
            }
cRTrn13's avatar
cRTrn13 committed
414 415 416
            if (!failed) {
                return 1;
            }
417 418 419 420
        }
        ptr++;
    }

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

cRTrn13's avatar
cRTrn13 committed
423
    return 0;
424 425
}

426
/* Function that collects keys from keydb config entry */
npzacs's avatar
npzacs committed
427
static uint32_t _find_config_entry(AACS *aacs, const char *path)
428
{
429
    uint8_t hash[20], discid[20];
430
    char str[48];
431 432 433
    uint32_t retval = 0;
    aacs->uks = NULL;
    aacs->num_uks = 0;
cRTrn13's avatar
cRTrn13 committed
434

435
    if (!_calc_title_hash(path, hash)) {
cRTrn13's avatar
cRTrn13 committed
436 437 438
        return 0;
    }

439 440 441 442 443 444 445
    if (aacs->cf) {
        aacs->ce = aacs->cf->list;
        while (aacs->ce && aacs->ce->entry.discid) {
            memset(discid, 0, sizeof(discid));
            hexstring_to_hex_array(discid, sizeof(discid),
                                   aacs->ce->entry.discid);
            if (!memcmp(hash, discid, 20)) {
446 447 448
                DEBUG(DBG_AACS, "Found config entry for discid %s\n",
                      aacs->ce->entry.discid);
                break;
449 450
            }

451
            aacs->ce = aacs->ce->next;
452
        }
453

454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
        if (aacs->ce->entry.mek) {
            hexstring_to_hex_array(aacs->mk, sizeof(aacs->mk),
                                    aacs->ce->entry.mek);

            DEBUG(DBG_AACS, "Found media key for %s: %s\n",
                  aacs->ce->entry.discid, print_hex(str, aacs->mk, 16));

            retval = 1;
        }

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

            DEBUG(DBG_AACS, "Found volume id for %s: %s\n",
                  aacs->ce->entry.discid, print_hex(str, aacs->vid, 16));

            retval = 1;
        }

474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
        if (aacs->ce->entry.vuk) {
            hexstring_to_hex_array(aacs->vuk, sizeof(aacs->vuk),
                                    aacs->ce->entry.vuk);

            DEBUG(DBG_AACS, "Found volume unique key for %s: %s\n",
                  aacs->ce->entry.discid, print_hex(str, aacs->vuk, 16));

            retval = 1;
        }

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

            digit_key_pair_list *ukcursor = aacs->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);

                char str[40];
                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;
            }
        }
503 504
    }

505
    if (aacs->num_uks)
506
        retval = aacs->num_uks;
507 508

    return retval;
509 510
}

511
#define ALIGNED_UNIT_LEN 6144
512
static int _decrypt_unit(AACS *aacs, uint8_t *out_buf, const uint8_t *in_buf, uint32_t curr_uk)
cRTrn13's avatar
cRTrn13 committed
513
{
514 515 516 517 518 519 520
    gcry_cipher_hd_t gcry_h;
    int a;
    uint8_t key[16], iv[] = "\x0b\xa0\xf8\xdd\xfe\xa6\x1f\xb3"
                            "\xd8\xdf\x9f\x56\x6a\x05\x0f\x78";

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

cRTrn13's avatar
cRTrn13 committed
524
    for (a = 0; a < 16; a++) {
525
        key[a] ^= in_buf[a];
cRTrn13's avatar
cRTrn13 committed
526 527
    }

528 529
    memcpy(out_buf, in_buf, 16); /* first 16 bytes are plain */

530 531 532
    gcry_cipher_open(&gcry_h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0);
    gcry_cipher_setkey(gcry_h, key, 16);
    gcry_cipher_setiv(gcry_h, iv, 16);
533
    gcry_cipher_decrypt(gcry_h, out_buf + 16, ALIGNED_UNIT_LEN - 16, in_buf + 16, ALIGNED_UNIT_LEN - 16);
534
    gcry_cipher_close(gcry_h);
cRTrn13's avatar
cRTrn13 committed
535

536
    if (_verify_ts(out_buf, ALIGNED_UNIT_LEN)) {
cRTrn13's avatar
cRTrn13 committed
537 538 539
        return 1;
    }

540
    if (curr_uk < aacs->num_uks - 1) {
541
        return _decrypt_unit(aacs, out_buf, in_buf, curr_uk++);
npzacs's avatar
npzacs committed
542 543
    }

cRTrn13's avatar
cRTrn13 committed
544 545 546
    return 0;
}

cRTrn13's avatar
cRTrn13 committed
547
AACS *aacs_open(const char *path, const char *configfile_path)
cRTrn13's avatar
cRTrn13 committed
548
{
npzacs's avatar
npzacs committed
549
    DEBUG(DBG_AACS, "libaacs [%zd]\n", sizeof(AACS));
cRTrn13's avatar
cRTrn13 committed
550

551 552 553 554 555 556
    DEBUG(DBG_AACS, "Initializing libgcrypt...\n");
    if (!crypto_init())
    {
        DEBUG(DBG_AACS, "Failed to initialize libgcrypt\n");
        return NULL;
    }
557 558 559 560 561 562 563 564 565

    char *cfgfile = NULL;
    if (configfile_path) {
        cfgfile = (char*)malloc(strlen(configfile_path) + 1);
        strcpy(cfgfile, configfile_path);
    } else {
        /* If no configfile path given, check for configfiles in user's home or
         * under /etc.
         */
npzacs's avatar
npzacs committed
566
        cfgfile = keydbcfg_find_config_file();
npzacs's avatar
npzacs committed
567 568 569
        if (!cfgfile) {
            DEBUG(DBG_AACS, "No configfile found!\n");
            return NULL;
570 571 572
        }
    }

cRTrn13's avatar
cRTrn13 committed
573
    AACS *aacs = calloc(1, sizeof(AACS));
574

575 576
    aacs->cf = keydbcfg_new_config_file();
    if (keydbcfg_parse_config(aacs->cf, cfgfile)) {
npzacs's avatar
npzacs committed
577 578
        X_FREE(cfgfile);

579 580
        DEBUG(DBG_AACS, "Searching for keydb config entry...\n");
        if(_find_config_entry(aacs, path)) {
581
            if (_calc_uks(aacs, path)) {
582 583 584
                keydbcfg_config_file_close(aacs->cf);
                aacs->cf = NULL;

npzacs's avatar
npzacs committed
585
                DEBUG(DBG_AACS, "AACS initialized! (%p)\n", aacs);
586 587 588 589
                return aacs;
            }
        }

590 591 592
        DEBUG(DBG_AACS, "Starting AACS waterfall...\n");
        //_calc_pk(aacs);
        if (_calc_mk(aacs, path)) {
593
           if (_calc_vuk(aacs, path)) {
594
                if (_calc_uks(aacs, path)) {
npzacs's avatar
npzacs committed
595
                    DEBUG(DBG_AACS, "AACS initialized! (%p)\n", aacs);
596 597 598 599
                    return aacs;
                }
            }
        }
600 601 602

        keydbcfg_config_file_close(aacs->cf);
        aacs->cf = NULL;
cRTrn13's avatar
cRTrn13 committed
603
    }
cRTrn13's avatar
cRTrn13 committed
604

npzacs's avatar
npzacs committed
605
    DEBUG(DBG_AACS, "Failed to initialize AACS! (%p)\n", aacs);
cRTrn13's avatar
cRTrn13 committed
606

npzacs's avatar
npzacs committed
607
    X_FREE(cfgfile);
608 609
    aacs_close(aacs);

cRTrn13's avatar
cRTrn13 committed
610
    return NULL;
cRTrn13's avatar
cRTrn13 committed
611 612
}

cRTrn13's avatar
cRTrn13 committed
613
void aacs_close(AACS *aacs)
cRTrn13's avatar
cRTrn13 committed
614
{
615
    X_FREE(aacs->uks);
616
    X_FREE(aacs->cps_units);
617

npzacs's avatar
npzacs committed
618
    DEBUG(DBG_AACS, "AACS destroyed! (%p)\n", aacs);
cRTrn13's avatar
cRTrn13 committed
619

cRTrn13's avatar
cRTrn13 committed
620 621 622
    X_FREE(aacs);
}

623
int aacs_decrypt_unit(AACS *aacs, uint8_t *buf)
624
{
625 626
    uint8_t out_buf[ALIGNED_UNIT_LEN];

627 628 629 630 631
    if (!(buf[0] & 0xc0)) {
        // TP_extra_header Copy_permission_indicator == 0, unit is not encrypted
        return 1;
    }

632
    if (_decrypt_unit(aacs, out_buf, buf, aacs->current_cps_unit)) {
633
        memcpy(buf, out_buf, ALIGNED_UNIT_LEN);
634 635 636 637 638 639 640

        // Clear copy_permission_indicator bits
        int i;
        for (i = 0; i < 6144; i += 192) {
            buf[i] &= ~0xc0;
        }

641 642 643
        return 1;
    }

644
    DEBUG(DBG_AACS, "Failed decrypting unit [6144 bytes] (%p)\n", aacs);
645

646
    return 0;
647
}
cRTrn13's avatar
cRTrn13 committed
648

649
const uint8_t *aacs_get_vid(AACS *aacs)
cRTrn13's avatar
cRTrn13 committed
650 651 652
{
    return aacs->vid;
}
653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679

void aacs_select_title(AACS *aacs, uint32_t title)
{
    if (!aacs) {
        return;
    }

    if (!aacs->cps_units) {
        DEBUG(DBG_AACS|DBG_CRIT, "aacs_select_title(): CPS units not read ! (%p)\n", aacs);
        return;
    }

    if (title == 0xffff) {
        /* first play */
        aacs->current_cps_unit = aacs->cps_units[0];
        DEBUG(DBG_AACS, "aacs_set_title(first_play): CPS unit %d (%p)\n", aacs->current_cps_unit, aacs);
        return;
    }

    if (title <= aacs->num_titles) {
        aacs->current_cps_unit = aacs->cps_units[title + 1];
        DEBUG(DBG_AACS, "aacs_set_title(%d): CPS unit %d (%p)\n", title, aacs->current_cps_unit, aacs);
        return;
    }

    DEBUG(DBG_AACS|DBG_CRIT, "aacs_set_title(%d): invalid title ! (%p)\n", title, aacs);
}