aacs.c 10.7 KB
Newer Older
Accident's avatar
 
Accident committed
1 2 3
#if HAVE_CONFIG_H
#include "config.h"
#endif
cRTrn13's avatar
cRTrn13 committed
4

Accident's avatar
 
Accident committed
5
#if HAVE_MALLOC_H
cRTrn13's avatar
cRTrn13 committed
6
#include <malloc.h>
Accident's avatar
 
Accident committed
7 8 9 10 11 12
#endif

#if HAVE_STDLIB_H
#include <stdlib.h>
#endif

npzacs's avatar
npzacs committed
13 14 15 16
#if HAVE_INTTYPES_H
#include <inttypes.h>
#endif

Accident's avatar
 
Accident committed
17
#include <stdio.h>
cRTrn13's avatar
openssl  
cRTrn13 committed
18
#include <string.h>
19
#include <openssl/evp.h>
cRTrn13's avatar
cRTrn13 committed
20 21

#include "aacs.h"
22
#include "crypto.h"
cRTrn13's avatar
cRTrn13 committed
23
#include "mmc.h"
cRTrn13's avatar
cRTrn13 committed
24
#include "../util/macro.h"
25
#include "../util/logging.h"
26
#include "../file/file.h"
cRTrn13's avatar
cRTrn13 committed
27

cRTrn13's avatar
cRTrn13 committed
28 29
int _validate_pk(uint8_t *pk, uint8_t *cvalue, uint8_t *uv, uint8_t *vd, uint8_t *mk)
{
30
    int a, ret = 0;
cRTrn13's avatar
cRTrn13 committed
31 32 33 34 35 36 37
    uint8_t dec_vd[16];

    DEBUG(DBG_AACS, "Validate processing key %s...\n", print_hex(pk, 16));
    DEBUG(DBG_AACS, " Using:\n");
    DEBUG(DBG_AACS, "   UV: %s\n", print_hex(uv, 4));
    DEBUG(DBG_AACS, "   cvalue: %s\n", print_hex(cvalue, 16));
    DEBUG(DBG_AACS, "   Verification data: %s\n", print_hex(vd, 16));
38

39 40 41 42 43
    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    EVP_CIPHER_CTX_set_key_length(ctx, 16);
    EVP_DecryptInit(ctx, EVP_aes_128_ecb(), pk, NULL);
    EVP_DecryptUpdate(ctx, mk, (int*)16, cvalue, 16);
    EVP_DecryptFinal(ctx, mk, (int*)16);
44

cRTrn13's avatar
cRTrn13 committed
45 46 47 48
    for (a = 0; a < 4; a++) {
        mk[a + 12] ^= uv[a];
    }

49 50 51 52
    EVP_DecryptInit(ctx, NULL, mk, NULL);
    EVP_DecryptUpdate(ctx, dec_vd, (int*)16, vd, 16);
    EVP_DecryptFinal(ctx, dec_vd, (int*)16);
    EVP_CIPHER_CTX_cleanup(ctx);
53

cRTrn13's avatar
cRTrn13 committed
54 55
    if (!memcmp(dec_vd, "\x01\x23\x45\x67\x89\xAB\xCD\xEF", 8)) {
        DEBUG(DBG_AACS, "Processing key is valid!\n");
56
        ret = 1;
cRTrn13's avatar
cRTrn13 committed
57 58
    }

59
    return ret;
cRTrn13's avatar
cRTrn13 committed
60
}
61

cRTrn13's avatar
cRTrn13 committed
62
int _calc_mk(AACS *aacs, const char *path)
cRTrn13's avatar
keyfile  
cRTrn13 committed
63 64 65
{
    int a, num_uvs = 0;
    size_t len;
cRTrn13's avatar
cRTrn13 committed
66
    uint8_t *buf = NULL, *rec, *uvs, *key_pos, *pks;
cRTrn13's avatar
cRTrn13 committed
67
    uint16_t num_pks;
cRTrn13's avatar
keyfile  
cRTrn13 committed
68 69
    MKB *mkb = NULL;

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

72 73 74 75 76 77 78 79 80 81
    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
82

83 84 85 86 87 88 89 90 91 92 93 94
        DEBUG(DBG_AACS, "Get cvalues...\n");
        rec = mkb_cvalues(mkb, &len);
        if ((pks = configfile_record(aacs->kf, KF_PK_ARRAY, &num_pks, NULL))) {
            key_pos = pks;
            while (key_pos < pks + num_pks * 16) {
                memcpy(aacs->pk, key_pos, 16);
                DEBUG(DBG_AACS, "Trying processing key...\n");

                for (a = 0; a < num_uvs; a++) {
                    if (_validate_pk(aacs->pk, rec + a * 16, uvs + 1 + a * 5, mkb_mk_dv(mkb), aacs->mk)) {
                        mkb_close(mkb);
                        X_FREE(buf);
95 96

                        DEBUG(DBG_AACS, "Media key: %s\n", print_hex(aacs->mk, 16));
97 98 99 100 101
                        return 1;
                    }
                }

                key_pos += 16;
cRTrn13's avatar
keyfile  
cRTrn13 committed
102
            }
103
        }
cRTrn13's avatar
keyfile  
cRTrn13 committed
104

105 106
        mkb_close(mkb);
        X_FREE(buf);
cRTrn13's avatar
keyfile  
cRTrn13 committed
107 108 109 110
    }

    return 0;
}
111

cRTrn13's avatar
cRTrn13 committed
112
int _calc_vuk(AACS *aacs, const char *path)
cRTrn13's avatar
openssl  
cRTrn13 committed
113 114
{
    int a;
cRTrn13's avatar
cRTrn13 committed
115
    MMC* mmc = NULL;
cRTrn13's avatar
openssl  
cRTrn13 committed
116

117 118
    DEBUG(DBG_AACS, "Calculate volume unique key...\n");

cRTrn13's avatar
cRTrn13 committed
119
    if ((mmc = mmc_open(path,
cRTrn13's avatar
cRTrn13 committed
120 121 122 123
            configfile_record(aacs->kf, KF_HOST_PRIV_KEY, NULL, NULL),
            configfile_record(aacs->kf, KF_HOST_CERT, NULL, NULL),
            configfile_record(aacs->kf, KF_HOST_NONCE, NULL, NULL),
            configfile_record(aacs->kf, KF_HOST_KEY_POINT, NULL, NULL)))) {
124
        if (mmc_read_vid(mmc, aacs->vid)) {
125 126 127 128 129 130
            EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
            EVP_CIPHER_CTX_set_key_length(ctx, 16);
            EVP_DecryptInit(ctx, EVP_aes_128_ecb(), aacs->mk, NULL);
            EVP_DecryptUpdate(ctx, aacs->vuk, (int*)16, aacs->vid, 16);
            EVP_DecryptFinal(ctx, aacs->vuk, (int*)16);
            EVP_CIPHER_CTX_cleanup(ctx);
cRTrn13's avatar
openssl  
cRTrn13 committed
131 132

            for (a = 0; a < 16; a++) {
133
                aacs->vuk[a] ^= aacs->vid[a];
cRTrn13's avatar
openssl  
cRTrn13 committed
134
            }
cRTrn13's avatar
cRTrn13 committed
135 136

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

138 139
            DEBUG(DBG_AACS, "Volume unique key: %s\n", print_hex(aacs->vuk, 16));

cRTrn13's avatar
openssl  
cRTrn13 committed
140 141 142
            return 1;
        }

cRTrn13's avatar
cRTrn13 committed
143 144
        mmc_close(mmc);
    }
cRTrn13's avatar
openssl  
cRTrn13 committed
145

146 147
    DEBUG(DBG_AACS, "Error calculating VUK!\n");

cRTrn13's avatar
openssl  
cRTrn13 committed
148 149 150
    return 0;
}

cRTrn13's avatar
cRTrn13 committed
151
int _calc_uks(AACS *aacs, const char *path)
cRTrn13's avatar
openssl  
cRTrn13 committed
152
{
153
    FILE_H *fp = NULL;
154
    uint8_t buf[16];
cRTrn13's avatar
openssl  
cRTrn13 committed
155
    char f_name[100];
156
    uint64_t f_pos;
npzacs's avatar
npzacs committed
157
    int i;
cRTrn13's avatar
openssl  
cRTrn13 committed
158

159 160 161
    DEBUG(DBG_AACS, "Calculate CPS unit keys...\n");

    snprintf(f_name , 100, "/%s/AACS/Unit_Key_RO.inf", path);
cRTrn13's avatar
openssl  
cRTrn13 committed
162

163
    if ((fp = file_open(f_name, "rb"))) {
164
        if ((file_read(fp, buf, 4)) == 4) {
npzacs's avatar
npzacs committed
165
            f_pos = MKINT_BE32(buf);
cRTrn13's avatar
openssl  
cRTrn13 committed
166

npzacs's avatar
npzacs committed
167
            // Read number of keys
cRTrn13's avatar
cRTrn13 committed
168
            file_seek(fp, f_pos, SEEK_SET);
npzacs's avatar
npzacs committed
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
            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
192

193 194 195 196 197 198
                EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
                EVP_CIPHER_CTX_set_key_length(ctx, 16);
                EVP_DecryptInit(ctx, EVP_aes_128_ecb(), aacs->vuk, NULL);
                EVP_DecryptUpdate(ctx, aacs->uks + 16*i, (int*)16, buf, 16);
                EVP_DecryptFinal(ctx, aacs->uks, (int*)16);
                EVP_CIPHER_CTX_cleanup(ctx);
cRTrn13's avatar
openssl  
cRTrn13 committed
199

npzacs's avatar
npzacs committed
200 201
                DEBUG(DBG_AACS, "Unit key %d: %s\n", i, print_hex(aacs->uks + 16*i, 16));
            }
cRTrn13's avatar
openssl  
cRTrn13 committed
202

npzacs's avatar
npzacs committed
203
            file_close(fp);
cRTrn13's avatar
openssl  
cRTrn13 committed
204

npzacs's avatar
npzacs committed
205
            return aacs->num_uks;
206 207 208
        }

        file_close(fp);
cRTrn13's avatar
openssl  
cRTrn13 committed
209 210
    }

211 212
    DEBUG(DBG_AACS, "Could not calculate unit keys!\n");

cRTrn13's avatar
openssl  
cRTrn13 committed
213 214 215
    return 0;
}

cRTrn13's avatar
cRTrn13 committed
216 217


218 219
int _verify_ts(uint8_t *buf, size_t size)
{
220 221
    uint8_t *ptr;

cRTrn13's avatar
cRTrn13 committed
222 223 224 225 226 227 228
    if (size < 192) {
        return 1;
    }

    for (ptr=buf; ptr < buf+192; ptr++) {
        int failed = 0;
        if (*ptr == 0x47) {
229 230 231 232
            uint8_t *ptr2;

            for (ptr2=ptr; ptr2 < buf + size; ptr2 += 192) {
                if (*ptr2 != 0x47) {
cRTrn13's avatar
cRTrn13 committed
233 234
                    failed = 1;
                    break;
235 236
                }
            }
cRTrn13's avatar
cRTrn13 committed
237 238 239
            if (!failed) {
                return 1;
            }
240 241 242 243
        }
        ptr++;
    }

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

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

cRTrn13's avatar
cRTrn13 committed
249
int _find_vuk(AACS *aacs, const char *path)
250
{
cRTrn13's avatar
cRTrn13 committed
251
    uint8_t *vuks, *key_pos, hash[20], *ukf_buf;
cRTrn13's avatar
cRTrn13 committed
252
    FILE_H *fp = NULL;
cRTrn13's avatar
cRTrn13 committed
253
    uint64_t f_size;
254
    uint16_t num_vuks;
cRTrn13's avatar
cRTrn13 committed
255 256 257 258 259 260 261 262 263 264 265 266 267 268
    char f_name[100];

    snprintf(f_name , 100, "/%s/AACS/Unit_Key_RO.inf", path);

    if ((fp = file_open(f_name, "rb"))) {
        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) {

        } else {
npzacs's avatar
npzacs committed
269
            DEBUG(DBG_AACS, "Failed to read %"PRIu64" bytes from unit key file!\n", f_size);
cRTrn13's avatar
cRTrn13 committed
270 271 272 273 274 275 276 277 278 279
            file_close(fp);
            X_FREE(ukf_buf);
            return 0;
        }
    } else {
        DEBUG(DBG_AACS, "Failed to open unit key file: %s!\n", f_name);
        return 0;
    }

    file_close(fp);
280

281
    crypto_aacs_title_hash(ukf_buf, f_size, hash);
cRTrn13's avatar
cRTrn13 committed
282 283
    DEBUG(DBG_AACS, "Disc ID: %s\n", print_hex(hash, 20));

cRTrn13's avatar
cRTrn13 committed
284 285
    X_FREE(ukf_buf);

286 287 288
    if ((vuks = configfile_record(aacs->kf, KF_VUK_ARRAY, &num_vuks, NULL))) {
        key_pos = vuks;
        while (key_pos < vuks + num_vuks * 46) {
cRTrn13's avatar
cRTrn13 committed
289
            if (!memcmp(hash, key_pos, 20)) {
290 291
                uint8_t desc[11];

cRTrn13's avatar
cRTrn13 committed
292
                memcpy(desc, key_pos + 20, 10);
293 294
                desc[10] = 0;

cRTrn13's avatar
cRTrn13 committed
295
                memcpy(aacs->vuk, key_pos + 30, 16);
296 297

                DEBUG(DBG_AACS, "Found volume unique key for %s: %s\n", desc, print_hex(aacs->vuk, 16));
298 299

                return 1;
300 301 302 303 304 305
            }

            key_pos += 46;
        }
    }

306
    return 0;
307 308
}

cRTrn13's avatar
cRTrn13 committed
309
int _decrypt_unit(AACS *aacs, uint8_t *buf, uint32_t len, uint64_t offset, uint32_t curr_uk)
cRTrn13's avatar
cRTrn13 committed
310 311 312 313 314
{
    uint8_t *tmp_buf = malloc(len);

    memcpy(tmp_buf, buf, len);

cRTrn13's avatar
cRTrn13 committed
315 316
    int a;
    uint8_t key[16], iv[] = { 0x0b, 0xa0, 0xf8, 0xdd, 0xfe, 0xa6, 0x1f, 0xb3, 0xd8, 0xdf, 0x9f, 0x56, 0x6a, 0x05, 0x0f, 0x78 };
cRTrn13's avatar
cRTrn13 committed
317

318 319 320 321 322 323
    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    EVP_CIPHER_CTX_set_key_length(ctx, 16);
    EVP_DecryptInit(ctx, EVP_aes_128_ecb(), aacs->uks + curr_uk * 16, NULL);
    EVP_DecryptUpdate(ctx, key, (int*)16, tmp_buf, 16);
    EVP_DecryptFinal(ctx, key, (int*)16);
    EVP_CIPHER_CTX_cleanup(ctx);
cRTrn13's avatar
cRTrn13 committed
324

cRTrn13's avatar
cRTrn13 committed
325 326
    for (a = 0; a < 16; a++) {
        key[a] ^= tmp_buf[a];
cRTrn13's avatar
cRTrn13 committed
327 328
    }

329 330 331 332 333 334 335 336
    int tmplen = len - 16;
    ctx = EVP_CIPHER_CTX_new();
    EVP_CIPHER_CTX_set_key_length(ctx, 16);
    EVP_DecryptInit(ctx, EVP_aes_128_ecb(), key, iv);
    EVP_DecryptUpdate(ctx, tmp_buf + 16, &tmplen, tmp_buf + 16,
                      len - 16);
    EVP_DecryptFinal(ctx, tmp_buf + 16, &tmplen);
    EVP_CIPHER_CTX_cleanup(ctx);
cRTrn13's avatar
cRTrn13 committed
337

cRTrn13's avatar
cRTrn13 committed
338
    if (_verify_ts(tmp_buf,len)) {
npzacs's avatar
npzacs committed
339
        DEBUG(DBG_AACS, "Decrypted %s unit [%d bytes] from offset %ld (%p)\n", len % 6144 ? "PARTIAL" : "FULL", len, offset, aacs);
cRTrn13's avatar
cRTrn13 committed
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354

        memcpy(buf, tmp_buf, len);

        X_FREE(tmp_buf);

        return 1;
    } else if (curr_uk < aacs->num_uks - 1) {
        return _decrypt_unit(aacs, buf, len, offset, curr_uk++);
    }

    X_FREE(tmp_buf);

    return 0;
}

cRTrn13's avatar
cRTrn13 committed
355
AACS *aacs_open(const char *path, const char *configfile_path)
cRTrn13's avatar
cRTrn13 committed
356
{
cRTrn13's avatar
cRTrn13 committed
357
    DEBUG(DBG_AACS, "libaacs v%s [%ld]\n", LIBAACS_VERSION, sizeof(AACS));
cRTrn13's avatar
cRTrn13 committed
358

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

cRTrn13's avatar
cRTrn13 committed
361
    if ((aacs->kf = configfile_open(configfile_path))) {
362 363 364 365
        DEBUG(DBG_AACS, "Searching for VUK...\n");
        if(_find_vuk(aacs, path)) {
            if (_calc_uks(aacs, path)) {
                configfile_close(aacs->kf);
366
                aacs->kf = NULL;
367

npzacs's avatar
npzacs committed
368
                DEBUG(DBG_AACS, "AACS initialized! (%p)\n", aacs);
369 370 371 372
                return aacs;
            }
        }

373 374 375
        DEBUG(DBG_AACS, "Starting AACS waterfall...\n");
        //_calc_pk(aacs);
        if (_calc_mk(aacs, path)) {
376
           if (_calc_vuk(aacs, path)) {
377
                if (_calc_uks(aacs, path)) {
cRTrn13's avatar
cRTrn13 committed
378
                    configfile_close(aacs->kf);
379
                    aacs->kf = NULL;
380

npzacs's avatar
npzacs committed
381
                    DEBUG(DBG_AACS, "AACS initialized! (%p)\n", aacs);
382 383 384 385
                    return aacs;
                }
            }
        }
386 387 388

        configfile_close(aacs->kf);
        aacs->kf = NULL;
cRTrn13's avatar
cRTrn13 committed
389
    }
cRTrn13's avatar
cRTrn13 committed
390

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

393 394
    aacs_close(aacs);

cRTrn13's avatar
cRTrn13 committed
395
    return NULL;
cRTrn13's avatar
cRTrn13 committed
396 397
}

cRTrn13's avatar
cRTrn13 committed
398
void aacs_close(AACS *aacs)
cRTrn13's avatar
cRTrn13 committed
399
{
400 401
    X_FREE(aacs->uks);

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

cRTrn13's avatar
cRTrn13 committed
404 405 406
    X_FREE(aacs);
}

cRTrn13's avatar
cRTrn13 committed
407
int aacs_decrypt_unit(AACS *aacs, uint8_t *buf, uint32_t len, uint64_t offset)
408
{
cRTrn13's avatar
cRTrn13 committed
409
    return _decrypt_unit(aacs, buf, len, offset, 0);
410
}
cRTrn13's avatar
cRTrn13 committed
411

cRTrn13's avatar
cRTrn13 committed
412
uint8_t *aacs_get_vid(AACS *aacs)
cRTrn13's avatar
cRTrn13 committed
413 414 415
{
    return aacs->vid;
}