aacs.c 18.9 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
    uint8_t pk[16], mk[16], vuk[16], vid[16], disc_id[20], *uks;
npzacs's avatar
npzacs committed
49 50
    uint32_t num_uks;
    struct config_file_t *cf;
51
    struct title_entry_list_t *ce;
52 53 54 55

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

58 59 60
static const uint8_t empty_key[] = "\x00\x00\x00\x00\x00\x00\x00\x00"
                                   "\x00\x00\x00\x00\x00\x00\x00\x00";

61 62
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
63
                        uint8_t *mk)
cRTrn13's avatar
cRTrn13 committed
64
{
65 66
    gcry_cipher_hd_t gcry_h;
    int a, ret = 0;
cRTrn13's avatar
cRTrn13 committed
67
    uint8_t dec_vd[16];
68
    char str[40];
cRTrn13's avatar
cRTrn13 committed
69

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

76 77 78
    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);
79

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

84 85 86
    gcry_cipher_setkey(gcry_h, mk, 16);
    gcry_cipher_decrypt (gcry_h, dec_vd, 16, vd, 16);
    gcry_cipher_close(gcry_h);
87

cRTrn13's avatar
cRTrn13 committed
88
    if (!memcmp(dec_vd, "\x01\x23\x45\x67\x89\xAB\xCD\xEF", 8)) {
npzacs's avatar
npzacs committed
89
        DEBUG(DBG_AACS, "Processing key %s is valid!\n", print_hex(str, pk, 16));
90
        ret = 1;
cRTrn13's avatar
cRTrn13 committed
91 92
    }

93
    return ret;
cRTrn13's avatar
cRTrn13 committed
94
}
95

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

104 105 106 107
    /* Skip if retrieved from config file */
    if (memcmp(aacs->mk, empty_key, 16))
      return 1;

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

110 111 112 113 114 115 116 117 118 119
    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
120

121 122
        DEBUG(DBG_AACS, "Get cvalues...\n");
        rec = mkb_cvalues(mkb, &len);
123 124 125 126 127
        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);
128 129 130
                DEBUG(DBG_AACS, "Trying processing key...\n");

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

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

143
                pkcursor = pkcursor->next;
cRTrn13's avatar
keyfile  
cRTrn13 committed
144
            }
145
        }
cRTrn13's avatar
keyfile  
cRTrn13 committed
146

147 148
        mkb_close(mkb);
        X_FREE(buf);
cRTrn13's avatar
keyfile  
cRTrn13 committed
149 150
    }

npzacs's avatar
npzacs committed
151 152
    DEBUG(DBG_AACS, "Error calculating media key!\n");

cRTrn13's avatar
keyfile  
cRTrn13 committed
153 154
    return 0;
}
155

156
static int _read_vid(AACS *aacs, const char *path)
cRTrn13's avatar
openssl  
cRTrn13 committed
157
{
158 159 160 161 162
    /* Use VID given in config file if available */
    if (memcmp(aacs->vid, empty_key, 16)) {
        return 1;
    }

cRTrn13's avatar
cRTrn13 committed
163
    MMC* mmc = NULL;
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
    if (!(mmc = mmc_open(path))) {
        return 0;
    }

    cert_list *hccursor = aacs->cf->host_cert_list;
    while (hccursor && hccursor->host_priv_key && hccursor->host_cert) {

        char tmp_str[2*92+1];
        uint8_t priv_key[20], cert[92];
        hexstring_to_hex_array(priv_key, sizeof(priv_key), hccursor->host_priv_key);
        hexstring_to_hex_array(cert,     sizeof(cert),     hccursor->host_cert);

        if (!crypto_aacs_verify_host_cert(cert)) {
	    DEBUG(DBG_AACS, "Not using invalid host certificate %s.\n",
		  print_hex(tmp_str, cert, 92));

	    hccursor = hccursor->next;
	    continue;
	}

        DEBUG(DBG_AACS, "Trying host certificate (id 0x%s)...\n",
              print_hex(tmp_str, cert + 4, 6));

npzacs's avatar
npzacs committed
187 188
        int mmc_result = mmc_read_vid(mmc, priv_key, cert, aacs->vid);
        if (mmc_result == MMC_SUCCESS) {
189 190 191 192 193 194 195 196 197 198 199 200
            mmc_close(mmc);
            return 1;
        }

        hccursor = hccursor->next;
    }

    mmc_close(mmc);

    DEBUG(DBG_AACS, "Error reading VID!\n");
    return 0;
}
cRTrn13's avatar
openssl  
cRTrn13 committed
201

202 203
static int _calc_vuk(AACS *aacs, const char *path)
{
204 205 206 207
    /* Skip if retrieved from config file */
    if (memcmp(aacs->vuk, empty_key, 16))
      return 1;

npzacs's avatar
npzacs committed
208 209 210 211 212 213
    /* get cached vuk */
    if (keycache_find("vuk", aacs->disc_id, aacs->vuk, 16)) {
        DEBUG(DBG_AACS, "Using cached VUK\n");
        return 1;
    }

214 215 216 217 218
    /* make sure we have media key */
    if (!_calc_mk(aacs, path)) {
        return 0;
    }

219 220
    DEBUG(DBG_AACS, "Calculate volume unique key...\n");

221 222 223
    if (_read_vid(aacs, path)) {

        int a;
224
        gcry_cipher_hd_t gcry_h;
225

226 227 228 229 230 231 232 233 234 235
        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];
236
        DEBUG(DBG_AACS, "Volume unique key: %s\n", print_hex(str, aacs->vuk, 16));
237

npzacs's avatar
npzacs committed
238 239 240
        /* cache vuk */
        keycache_save("vuk", aacs->disc_id, aacs->vuk, 16);

241 242 243
        return 1;
    }

244 245
    DEBUG(DBG_AACS, "Error calculating VUK!\n");

cRTrn13's avatar
openssl  
cRTrn13 committed
246 247 248
    return 0;
}

249 250
static uint16_t _read_u16(AACS_FILE_H *fp)
{
npzacs's avatar
npzacs committed
251
  uint8_t data[2] = {0, 0};
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

  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
298
static int _calc_uks(AACS *aacs, const char *path)
cRTrn13's avatar
openssl  
cRTrn13 committed
299
{
300
    AACS_FILE_H *fp = NULL;
301 302
    char    *f_name;
    uint8_t  buf[16];
303
    uint64_t f_pos;
304
    unsigned int i;
cRTrn13's avatar
openssl  
cRTrn13 committed
305

306 307
    /* Skip if retrieved from config file */
    if (aacs->uks)
308
        return 1;
309

310 311
    /* Make sure we have VUK */
    if (!_calc_vuk(aacs, path)) {
312
        return 0;
313
    }
314

315 316
    DEBUG(DBG_AACS, "Calculate CPS unit keys...\n");

npzacs's avatar
npzacs committed
317
    f_name = str_printf("%s/AACS/Unit_Key_RO.inf", path);
318 319
    fp = file_open(f_name, "rb");
    X_FREE(f_name);
cRTrn13's avatar
openssl  
cRTrn13 committed
320

321
    if (fp) {
322
        if ((file_read(fp, buf, 4)) == 4) {
npzacs's avatar
npzacs committed
323
            f_pos = MKINT_BE32(buf);
cRTrn13's avatar
openssl  
cRTrn13 committed
324

npzacs's avatar
npzacs committed
325
            // Read number of keys
cRTrn13's avatar
cRTrn13 committed
326
            file_seek(fp, f_pos, SEEK_SET);
npzacs's avatar
npzacs committed
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
            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
350

351 352 353 354 355 356
                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
357

358
                char str[40];
gates's avatar
gates committed
359
                DEBUG(DBG_AACS, "Unit key %d: %s\n", i,
360
                      print_hex(str, aacs->uks + 16*i, 16));
npzacs's avatar
npzacs committed
361
            }
cRTrn13's avatar
openssl  
cRTrn13 committed
362

363 364
            _read_uks_map(aacs, fp);

npzacs's avatar
npzacs committed
365
            file_close(fp);
cRTrn13's avatar
openssl  
cRTrn13 committed
366

npzacs's avatar
npzacs committed
367
            return aacs->num_uks;
368 369 370
        }

        file_close(fp);
cRTrn13's avatar
openssl  
cRTrn13 committed
371 372
    }

373 374
    DEBUG(DBG_AACS, "Could not calculate unit keys!\n");

cRTrn13's avatar
openssl  
cRTrn13 committed
375 376 377
    return 0;
}

378 379
static int _calc_title_hash(const char *path, uint8_t *title_hash)
{
380
    AACS_FILE_H *fp = NULL;
381 382 383 384 385
    uint8_t *ukf_buf;
    char     str[48];
    int64_t  f_size;
    char    *f_name;

npzacs's avatar
npzacs committed
386
    f_name = str_printf("%s/AACS/Unit_Key_RO.inf", path);
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402

    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
403

404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
        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
420

npzacs's avatar
npzacs committed
421
static int _verify_ts(uint8_t *buf, size_t size)
422
{
423 424
    uint8_t *ptr;

cRTrn13's avatar
cRTrn13 committed
425 426 427 428 429 430 431
    if (size < 192) {
        return 1;
    }

    for (ptr=buf; ptr < buf+192; ptr++) {
        int failed = 0;
        if (*ptr == 0x47) {
432 433 434 435
            uint8_t *ptr2;

            for (ptr2=ptr; ptr2 < buf + size; ptr2 += 192) {
                if (*ptr2 != 0x47) {
cRTrn13's avatar
cRTrn13 committed
436 437
                    failed = 1;
                    break;
438 439
                }
            }
cRTrn13's avatar
cRTrn13 committed
440 441 442
            if (!failed) {
                return 1;
            }
443 444 445 446
        }
        ptr++;
    }

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

cRTrn13's avatar
cRTrn13 committed
449
    return 0;
450 451
}

452
/* Function that collects keys from keydb config entry */
453
static void _find_config_entry(AACS *aacs)
454
{
npzacs's avatar
npzacs committed
455
    uint8_t discid[20];
456
    char str[48];
npzacs's avatar
npzacs committed
457

458 459
    aacs->uks = NULL;
    aacs->num_uks = 0;
cRTrn13's avatar
cRTrn13 committed
460

npzacs's avatar
npzacs committed
461
    if (aacs->cf && aacs->cf->list) {
462 463 464 465 466
        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);
npzacs's avatar
npzacs committed
467
            if (!memcmp(aacs->disc_id, discid, 20)) {
468 469 470
                DEBUG(DBG_AACS, "Found config entry for discid %s\n",
                      aacs->ce->entry.discid);
                break;
471 472
            }

473
            aacs->ce = aacs->ce->next;
474
        }
475

476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
        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));
        }

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

492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
        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));
        }

        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;
            }
        }
519
    }
520 521
}

522
#define ALIGNED_UNIT_LEN 6144
523
static int _decrypt_unit(AACS *aacs, uint8_t *out_buf, const uint8_t *in_buf, uint32_t curr_uk)
cRTrn13's avatar
cRTrn13 committed
524
{
525 526 527 528 529 530 531
    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);
532
    gcry_cipher_encrypt(gcry_h, key, 16, in_buf, 16);
533
    gcry_cipher_close(gcry_h);
cRTrn13's avatar
cRTrn13 committed
534

cRTrn13's avatar
cRTrn13 committed
535
    for (a = 0; a < 16; a++) {
536
        key[a] ^= in_buf[a];
cRTrn13's avatar
cRTrn13 committed
537 538
    }

539 540
    memcpy(out_buf, in_buf, 16); /* first 16 bytes are plain */

541 542 543
    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);
544
    gcry_cipher_decrypt(gcry_h, out_buf + 16, ALIGNED_UNIT_LEN - 16, in_buf + 16, ALIGNED_UNIT_LEN - 16);
545
    gcry_cipher_close(gcry_h);
cRTrn13's avatar
cRTrn13 committed
546

547
    if (_verify_ts(out_buf, ALIGNED_UNIT_LEN)) {
cRTrn13's avatar
cRTrn13 committed
548 549 550
        return 1;
    }

551
    if (curr_uk < aacs->num_uks - 1) {
552
        return _decrypt_unit(aacs, out_buf, in_buf, curr_uk++);
npzacs's avatar
npzacs committed
553 554
    }

cRTrn13's avatar
cRTrn13 committed
555 556 557
    return 0;
}

npzacs's avatar
npzacs committed
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
static int _load_config(AACS *aacs, const char *configfile_path)
{
    int config_ok = 0;

    aacs->cf = keydbcfg_new_config_file();

    /* try to load KEYDB.cfg */

    if (configfile_path) {
        config_ok = keydbcfg_parse_config(aacs->cf, configfile_path);

    } else {
        /* If no configfile path given, check for config files in user's home or
         * under /etc.
         */
        char *cfgfile = keydbcfg_find_config_file();
        config_ok = keydbcfg_parse_config(aacs->cf, cfgfile);
        X_FREE(cfgfile);
    }

    /* Try to load simple (aacskeys) config files */

    config_ok = keydbcfg_load_pk_file(aacs->cf)   || config_ok;
    config_ok = keydbcfg_load_cert_file(aacs->cf) || config_ok;

    if (!config_ok) {
        DEBUG(DBG_AACS, "No valid configuration files found!\n");
    }

    return config_ok;
}

npzacs's avatar
npzacs committed
590 591
void aacs_get_version(int *major, int *minor, int *micro)
{
npzacs's avatar
npzacs committed
592 593 594
    *major = AACS_VERSION_MAJOR;
    *minor = AACS_VERSION_MINOR;
    *micro = AACS_VERSION_MICRO;
npzacs's avatar
npzacs committed
595 596
}

cRTrn13's avatar
cRTrn13 committed
597
AACS *aacs_open(const char *path, const char *configfile_path)
cRTrn13's avatar
cRTrn13 committed
598
{
npzacs's avatar
npzacs committed
599
    DEBUG(DBG_AACS, "libaacs [%zd]\n", sizeof(AACS));
cRTrn13's avatar
cRTrn13 committed
600

601 602 603 604 605 606
    DEBUG(DBG_AACS, "Initializing libgcrypt...\n");
    if (!crypto_init())
    {
        DEBUG(DBG_AACS, "Failed to initialize libgcrypt\n");
        return NULL;
    }
607

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

610 611 612 613 614
    if (!_calc_title_hash(path, aacs->disc_id)) {
        aacs_close(aacs);
        return NULL;
    }

npzacs's avatar
npzacs committed
615
    if (_load_config(aacs, configfile_path)) {
616
        DEBUG(DBG_AACS, "Searching for keydb config entry...\n");
617
        _find_config_entry(aacs);
618

619
        DEBUG(DBG_AACS, "Starting AACS waterfall...\n");
620
        if (_calc_uks(aacs, path)) {
npzacs's avatar
npzacs committed
621 622 623
            keydbcfg_config_file_close(aacs->cf);
            aacs->cf = NULL;

624 625
            DEBUG(DBG_AACS, "AACS initialized! (%p)\n", aacs);
            return aacs;
626
        }
627 628 629

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

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

634 635
    aacs_close(aacs);

cRTrn13's avatar
cRTrn13 committed
636
    return NULL;
cRTrn13's avatar
cRTrn13 committed
637 638
}

cRTrn13's avatar
cRTrn13 committed
639
void aacs_close(AACS *aacs)
cRTrn13's avatar
cRTrn13 committed
640
{
641
    X_FREE(aacs->uks);
642
    X_FREE(aacs->cps_units);
643

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

cRTrn13's avatar
cRTrn13 committed
646 647 648
    X_FREE(aacs);
}

649
int aacs_decrypt_unit(AACS *aacs, uint8_t *buf)
650
{
651 652
    uint8_t out_buf[ALIGNED_UNIT_LEN];

653 654 655 656 657
    if (!(buf[0] & 0xc0)) {
        // TP_extra_header Copy_permission_indicator == 0, unit is not encrypted
        return 1;
    }

658
    if (_decrypt_unit(aacs, out_buf, buf, aacs->current_cps_unit)) {
659
        memcpy(buf, out_buf, ALIGNED_UNIT_LEN);
660 661 662 663 664 665 666

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

667 668 669
        return 1;
    }

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

672
    return 0;
673
}
cRTrn13's avatar
cRTrn13 committed
674

npzacs's avatar
npzacs committed
675 676 677 678 679
const uint8_t *aacs_get_disc_id(AACS *aacs)
{
    return aacs->disc_id;
}

680
const uint8_t *aacs_get_vid(AACS *aacs)
cRTrn13's avatar
cRTrn13 committed
681 682 683
{
    return aacs->vid;
}
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

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