aacs.c 10.9 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

npzacs's avatar
npzacs committed
5
#include <inttypes.h>
6
#include <openssl/evp.h>
cRTrn13's avatar
cRTrn13 committed
7 8

#include "aacs.h"
9
#include "crypto.h"
cRTrn13's avatar
cRTrn13 committed
10
#include "mmc.h"
11
#include "mkb.h"
cRTrn13's avatar
cRTrn13 committed
12
#include "../util/macro.h"
13
#include "../util/logging.h"
14
#include "../file/file.h"
cRTrn13's avatar
cRTrn13 committed
15

gates's avatar
gates committed
16 17
int _validate_pk(uint8_t *pk, uint8_t *cvalue, uint8_t *uv, uint8_t *vd,
                 uint8_t *mk)
cRTrn13's avatar
cRTrn13 committed
18
{
19
    int a, ret = 0;
cRTrn13's avatar
cRTrn13 committed
20 21 22 23 24 25 26
    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));
27

28 29 30 31 32
    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);
33

cRTrn13's avatar
cRTrn13 committed
34 35 36 37
    for (a = 0; a < 4; a++) {
        mk[a + 12] ^= uv[a];
    }

38 39 40 41
    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);
42

cRTrn13's avatar
cRTrn13 committed
43 44
    if (!memcmp(dec_vd, "\x01\x23\x45\x67\x89\xAB\xCD\xEF", 8)) {
        DEBUG(DBG_AACS, "Processing key is valid!\n");
45
        ret = 1;
cRTrn13's avatar
cRTrn13 committed
46 47
    }

48
    return ret;
cRTrn13's avatar
cRTrn13 committed
49
}
50

cRTrn13's avatar
cRTrn13 committed
51
int _calc_mk(AACS *aacs, const char *path)
cRTrn13's avatar
keyfile  
cRTrn13 committed
52 53 54
{
    int a, num_uvs = 0;
    size_t len;
cRTrn13's avatar
cRTrn13 committed
55
    uint8_t *buf = NULL, *rec, *uvs, *key_pos, *pks;
cRTrn13's avatar
cRTrn13 committed
56
    uint16_t num_pks;
cRTrn13's avatar
keyfile  
cRTrn13 committed
57 58
    MKB *mkb = NULL;

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

61 62 63 64 65 66 67 68 69 70
    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
71

72 73 74 75 76 77 78 79 80
        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++) {
gates's avatar
gates committed
81 82
                    if (_validate_pk(aacs->pk, rec + a * 16, uvs + 1 + a * 5,
                      mkb_mk_dv(mkb), aacs->mk)) {
83 84
                        mkb_close(mkb);
                        X_FREE(buf);
85

gates's avatar
gates committed
86 87
                        DEBUG(DBG_AACS, "Media key: %s\n", print_hex(aacs->mk,
                                                                     16));
88 89 90 91 92
                        return 1;
                    }
                }

                key_pos += 16;
cRTrn13's avatar
keyfile  
cRTrn13 committed
93
            }
94
        }
cRTrn13's avatar
keyfile  
cRTrn13 committed
95

96 97
        mkb_close(mkb);
        X_FREE(buf);
cRTrn13's avatar
keyfile  
cRTrn13 committed
98 99 100 101
    }

    return 0;
}
102

cRTrn13's avatar
cRTrn13 committed
103
int _calc_vuk(AACS *aacs, const char *path)
cRTrn13's avatar
openssl  
cRTrn13 committed
104 105
{
    int a;
cRTrn13's avatar
cRTrn13 committed
106
    MMC* mmc = NULL;
cRTrn13's avatar
openssl  
cRTrn13 committed
107

108 109
    DEBUG(DBG_AACS, "Calculate volume unique key...\n");

cRTrn13's avatar
cRTrn13 committed
110
    if ((mmc = mmc_open(path,
cRTrn13's avatar
cRTrn13 committed
111 112 113 114
            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)))) {
115
        if (mmc_read_vid(mmc, aacs->vid)) {
116 117 118 119 120 121
            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
122 123

            for (a = 0; a < 16; a++) {
124
                aacs->vuk[a] ^= aacs->vid[a];
cRTrn13's avatar
openssl  
cRTrn13 committed
125
            }
cRTrn13's avatar
cRTrn13 committed
126 127

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

gates's avatar
gates committed
129 130
            DEBUG(DBG_AACS, "Volume unique key: %s\n", print_hex(aacs->vuk,
                                                                 16));
131

cRTrn13's avatar
openssl  
cRTrn13 committed
132 133 134
            return 1;
        }

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

138 139
    DEBUG(DBG_AACS, "Error calculating VUK!\n");

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

cRTrn13's avatar
cRTrn13 committed
143
int _calc_uks(AACS *aacs, const char *path)
cRTrn13's avatar
openssl  
cRTrn13 committed
144
{
145
    FILE_H *fp = NULL;
146
    uint8_t buf[16];
cRTrn13's avatar
openssl  
cRTrn13 committed
147
    char f_name[100];
148
    uint64_t f_pos;
npzacs's avatar
npzacs committed
149
    int i;
cRTrn13's avatar
openssl  
cRTrn13 committed
150

151 152 153
    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
154

155
    if ((fp = file_open(f_name, "rb"))) {
156
        if ((file_read(fp, buf, 4)) == 4) {
npzacs's avatar
npzacs committed
157
            f_pos = MKINT_BE32(buf);
cRTrn13's avatar
openssl  
cRTrn13 committed
158

npzacs's avatar
npzacs committed
159
            // Read number of keys
cRTrn13's avatar
cRTrn13 committed
160
            file_seek(fp, f_pos, SEEK_SET);
npzacs's avatar
npzacs committed
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
            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
184

185 186 187 188 189 190
                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
191

gates's avatar
gates committed
192 193
                DEBUG(DBG_AACS, "Unit key %d: %s\n", i,
                      print_hex(aacs->uks + 16*i, 16));
npzacs's avatar
npzacs committed
194
            }
cRTrn13's avatar
openssl  
cRTrn13 committed
195

npzacs's avatar
npzacs committed
196
            file_close(fp);
cRTrn13's avatar
openssl  
cRTrn13 committed
197

npzacs's avatar
npzacs committed
198
            return aacs->num_uks;
199 200 201
        }

        file_close(fp);
cRTrn13's avatar
openssl  
cRTrn13 committed
202 203
    }

204 205
    DEBUG(DBG_AACS, "Could not calculate unit keys!\n");

cRTrn13's avatar
openssl  
cRTrn13 committed
206 207 208
    return 0;
}

cRTrn13's avatar
cRTrn13 committed
209 210


211 212
int _verify_ts(uint8_t *buf, size_t size)
{
213 214
    uint8_t *ptr;

cRTrn13's avatar
cRTrn13 committed
215 216 217 218 219 220 221
    if (size < 192) {
        return 1;
    }

    for (ptr=buf; ptr < buf+192; ptr++) {
        int failed = 0;
        if (*ptr == 0x47) {
222 223 224 225
            uint8_t *ptr2;

            for (ptr2=ptr; ptr2 < buf + size; ptr2 += 192) {
                if (*ptr2 != 0x47) {
cRTrn13's avatar
cRTrn13 committed
226 227
                    failed = 1;
                    break;
228 229
                }
            }
cRTrn13's avatar
cRTrn13 committed
230 231 232
            if (!failed) {
                return 1;
            }
233 234 235 236
        }
        ptr++;
    }

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

cRTrn13's avatar
cRTrn13 committed
239
    return 0;
240 241
}

cRTrn13's avatar
cRTrn13 committed
242
int _find_vuk(AACS *aacs, const char *path)
243
{
cRTrn13's avatar
cRTrn13 committed
244
    uint8_t *vuks, *key_pos, hash[20], *ukf_buf;
cRTrn13's avatar
cRTrn13 committed
245
    FILE_H *fp = NULL;
cRTrn13's avatar
cRTrn13 committed
246
    uint64_t f_size;
247
    uint16_t num_vuks;
cRTrn13's avatar
cRTrn13 committed
248 249 250 251 252 253 254 255 256 257 258 259 260 261
    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 {
gates's avatar
gates committed
262 263 264
            DEBUG(DBG_AACS,
                  "Failed to read %"PRIu64" bytes from unit key file!\n",
                  f_size);
cRTrn13's avatar
cRTrn13 committed
265 266 267 268 269 270 271 272 273 274
            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);
275

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

cRTrn13's avatar
cRTrn13 committed
279 280
    X_FREE(ukf_buf);

281 282 283
    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
284
            if (!memcmp(hash, key_pos, 20)) {
285 286
                uint8_t desc[11];

cRTrn13's avatar
cRTrn13 committed
287
                memcpy(desc, key_pos + 20, 10);
288 289
                desc[10] = 0;

cRTrn13's avatar
cRTrn13 committed
290
                memcpy(aacs->vuk, key_pos + 30, 16);
291

gates's avatar
gates committed
292 293
                DEBUG(DBG_AACS, "Found volume unique key for %s: %s\n", desc,
                      print_hex(aacs->vuk, 16));
294 295

                return 1;
296 297 298 299 300 301
            }

            key_pos += 46;
        }
    }

302
    return 0;
303 304
}

gates's avatar
gates committed
305 306
int _decrypt_unit(AACS *aacs, uint8_t *buf, uint32_t len, uint64_t offset,
                  uint32_t curr_uk)
cRTrn13's avatar
cRTrn13 committed
307 308 309 310 311
{
    uint8_t *tmp_buf = malloc(len);

    memcpy(tmp_buf, buf, len);

cRTrn13's avatar
cRTrn13 committed
312
    int a;
gates's avatar
gates committed
313 314
    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
315

316 317 318 319 320 321
    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
322

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

327 328 329 330 331 332 333 334
    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
335

cRTrn13's avatar
cRTrn13 committed
336
    if (_verify_ts(tmp_buf,len)) {
gates's avatar
gates committed
337 338
        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
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353

        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
354
AACS *aacs_open(const char *path, const char *configfile_path)
cRTrn13's avatar
cRTrn13 committed
355
{
cRTrn13's avatar
cRTrn13 committed
356
    DEBUG(DBG_AACS, "libaacs v%s [%ld]\n", LIBAACS_VERSION, sizeof(AACS));
cRTrn13's avatar
cRTrn13 committed
357

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

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

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

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

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

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

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

392 393
    aacs_close(aacs);

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

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

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

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

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

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