aacs.c 9.39 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
13
#endif

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

#include <stdio.h>
cRTrn13's avatar
openssl    
cRTrn13 committed
14
#include <string.h>
cRTrn13's avatar
cRTrn13 committed
15
16

#include "aacs.h"
17
#include "crypto.h"
cRTrn13's avatar
cRTrn13 committed
18
#include "mmc.h"
cRTrn13's avatar
cRTrn13 committed
19
#include "../util/macro.h"
20
#include "../util/logging.h"
21
#include "../file/file.h"
cRTrn13's avatar
cRTrn13 committed
22

cRTrn13's avatar
cRTrn13 committed
23
24
int _validate_pk(uint8_t *pk, uint8_t *cvalue, uint8_t *uv, uint8_t *vd, uint8_t *mk)
{
25
    int a, ret = 0;
cRTrn13's avatar
cRTrn13 committed
26
    AES_KEY aes;
27
    gcry_cipher_hd_t gcry_h;
cRTrn13's avatar
cRTrn13 committed
28
29
30
31
32
33
34
    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));
35

36
37
38
39
40
41
42
    gcry_cipher_open(&gcry_h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, NULL);

    gcry_cipher_setkey(gcry_h, pk, 16);
    gcry_cipher_decrypt (gcry_h, mk, 16, cvalue, 16);

    //AES_set_decrypt_key(pk, 128, &aes);
    //AES_decrypt(cvalue, mk, &aes);
cRTrn13's avatar
cRTrn13 committed
43
44
45
46
47

    for (a = 0; a < 4; a++) {
        mk[a + 12] ^= uv[a];
    }

48
49
50
51
52
    gcry_cipher_setkey(gcry_h, mk, 16);
    gcry_cipher_decrypt (gcry_h, dec_vd, 16, vd, 16);

   // AES_set_decrypt_key(mk, 128, &aes);
   // AES_decrypt(vd, dec_vd, &aes);
cRTrn13's avatar
cRTrn13 committed
53
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
60
61
    gcry_cipher_close(gcry_h);

    return ret;
cRTrn13's avatar
cRTrn13 committed
62
}
63

cRTrn13's avatar
cRTrn13 committed
64
int _calc_mk(AACS *aacs, const char *path)
cRTrn13's avatar
keyfile    
cRTrn13 committed
65
{
66
67
    DEBUG(DBG_AACS, "Calculate media key...\n");

cRTrn13's avatar
keyfile    
cRTrn13 committed
68
69
    int a, num_uvs = 0;
    size_t len;
cRTrn13's avatar
cRTrn13 committed
70
    uint8_t *buf = NULL, *rec, *uvs, *key_pos, *pks;
cRTrn13's avatar
cRTrn13 committed
71
    uint16_t num_pks;
cRTrn13's avatar
keyfile    
cRTrn13 committed
72
73
    MKB *mkb = NULL;

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

85
86
87
88
89
90
91
92
93
94
95
96
        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);
97
98

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

                key_pos += 16;
cRTrn13's avatar
keyfile    
cRTrn13 committed
104
            }
105
        }
cRTrn13's avatar
keyfile    
cRTrn13 committed
106

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

    return 0;
}
113

cRTrn13's avatar
cRTrn13 committed
114
int _calc_vuk(AACS *aacs, const char *path)
cRTrn13's avatar
openssl    
cRTrn13 committed
115
116
117
{
    int a;
    AES_KEY aes;
cRTrn13's avatar
cRTrn13 committed
118
    MMC* mmc = NULL;
cRTrn13's avatar
openssl    
cRTrn13 committed
119

120
121
    DEBUG(DBG_AACS, "Calculate volume unique key...\n");

cRTrn13's avatar
cRTrn13 committed
122
    if ((mmc = mmc_open(path,
cRTrn13's avatar
cRTrn13 committed
123
124
125
126
            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)))) {
127
        if (mmc_read_vid(mmc, aacs->vid)) {
cRTrn13's avatar
cRTrn13 committed
128
            AES_set_decrypt_key(aacs->mk, 128, &aes);
129
            AES_decrypt(aacs->vid, aacs->vuk, &aes);
cRTrn13's avatar
openssl    
cRTrn13 committed
130
131

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

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

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

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

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

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

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

cRTrn13's avatar
cRTrn13 committed
150
int _calc_uks(AACS *aacs, const char *path)
cRTrn13's avatar
openssl    
cRTrn13 committed
151
152
{
    AES_KEY aes;
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;
cRTrn13's avatar
openssl    
cRTrn13 committed
157

158
159
160
    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
161

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

cRTrn13's avatar
cRTrn13 committed
166
            file_seek(fp, f_pos, SEEK_SET);
167
168
169
            if ((file_read(fp, buf, 16)) == 16) {
                // TODO: support more than a single UK!!!
                aacs->uks = malloc(16);
cRTrn13's avatar
openssl    
cRTrn13 committed
170

171
172
                AES_set_decrypt_key(aacs->vuk, 128, &aes);
                AES_decrypt(buf, aacs->uks, &aes);
cRTrn13's avatar
openssl    
cRTrn13 committed
173

174
                file_close(fp);
cRTrn13's avatar
openssl    
cRTrn13 committed
175

176
                DEBUG(DBG_AACS, "Unit key 1: %s\n", print_hex(aacs->uks, 16));
cRTrn13's avatar
openssl    
cRTrn13 committed
177

178
179
180
181
182
                return 1;
            }
        }

        file_close(fp);
cRTrn13's avatar
openssl    
cRTrn13 committed
183
184
    }

185
186
    DEBUG(DBG_AACS, "Could not calculate unit keys!\n");

cRTrn13's avatar
openssl    
cRTrn13 committed
187
188
189
    return 0;
}

cRTrn13's avatar
cRTrn13 committed
190
191


192
193
int _verify_ts(uint8_t *buf, size_t size)
{
194
195
    uint8_t *ptr;

cRTrn13's avatar
cRTrn13 committed
196
197
198
199
200
201
202
    if (size < 192) {
        return 1;
    }

    for (ptr=buf; ptr < buf+192; ptr++) {
        int failed = 0;
        if (*ptr == 0x47) {
203
204
205
206
            uint8_t *ptr2;

            for (ptr2=ptr; ptr2 < buf + size; ptr2 += 192) {
                if (*ptr2 != 0x47) {
cRTrn13's avatar
cRTrn13 committed
207
208
                    failed = 1;
                    break;
209
210
                }
            }
cRTrn13's avatar
cRTrn13 committed
211
212
213
            if (!failed) {
                return 1;
            }
214
215
216
217
        }
        ptr++;
    }

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

cRTrn13's avatar
cRTrn13 committed
220
    return 0;
221
222
}

cRTrn13's avatar
cRTrn13 committed
223
int _find_vuk(AACS *aacs, const char *path)
224
{
cRTrn13's avatar
cRTrn13 committed
225
    uint8_t *vuks, *key_pos, hash[20], *ukf_buf;
cRTrn13's avatar
cRTrn13 committed
226
    FILE_H *fp = NULL;
cRTrn13's avatar
cRTrn13 committed
227
    uint64_t f_size;
228
    uint16_t num_vuks;
cRTrn13's avatar
cRTrn13 committed
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
    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 {
            DEBUG(DBG_AACS, "Failed to read %d bytes from unit key file!\n", f_size);
            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);
254

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

cRTrn13's avatar
cRTrn13 committed
258
259
    X_FREE(ukf_buf);

260
261
262
    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
263
            if (!memcmp(hash, key_pos, 20)) {
264
265
                uint8_t desc[11];

cRTrn13's avatar
cRTrn13 committed
266
                memcpy(desc, key_pos + 20, 10);
267
268
                desc[10] = 0;

cRTrn13's avatar
cRTrn13 committed
269
                memcpy(aacs->vuk, key_pos + 30, 16);
270
271

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

                return 1;
274
275
276
277
278
279
            }

            key_pos += 46;
        }
    }

280
    return 0;
281
282
}

cRTrn13's avatar
cRTrn13 committed
283
int _decrypt_unit(AACS *aacs, uint8_t *buf, uint32_t len, uint64_t offset, uint32_t curr_uk)
cRTrn13's avatar
cRTrn13 committed
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
{
    uint8_t *tmp_buf = malloc(len);

    memcpy(tmp_buf, buf, len);

    if (offset % 6144) {
        AES_cbc_encrypt(tmp_buf, tmp_buf, len, &aacs->aes, aacs->iv, 0);
    } else {
        int a;
        uint8_t key[16], iv[] = { 0x0b, 0xa0, 0xf8, 0xdd, 0xfe, 0xa6, 0x1f, 0xb3, 0xd8, 0xdf, 0x9f, 0x56, 0x6a, 0x05, 0x0f, 0x78 };

        memcpy(aacs->iv, iv, 16);

        AES_set_encrypt_key(aacs->uks + curr_uk * 16, 128, &aacs->aes);
        AES_encrypt(tmp_buf, key, &aacs->aes);

        for (a = 0; a < 16; a++) {
            key[a] ^= tmp_buf[a];
        }

        AES_set_decrypt_key(key, 128, &aacs->aes);
        AES_cbc_encrypt(tmp_buf + 16, tmp_buf + 16, len - 16, &aacs->aes, aacs->iv, 0);
    }

    if (_verify_ts(tmp_buf,len)) {
        DEBUG(DBG_AACS, "Decrypted %s unit [%d bytes] from offset %ld (0x%08x)\n", len % 6144 ? "PARTIAL" : "FULL", len, offset, aacs);

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

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

331
332
    gcry_cipher_open (aacs->gcry_h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, NULL);

333
    aacs->uks = NULL;
cRTrn13's avatar
cRTrn13 committed
334
    aacs->kf = NULL;
cRTrn13's avatar
cRTrn13 committed
335
    if ((aacs->kf = configfile_open(configfile_path))) {
336
337
338
339
340
341
342
343
344
345
        DEBUG(DBG_AACS, "Searching for VUK...\n");
        if(_find_vuk(aacs, path)) {
            if (_calc_uks(aacs, path)) {
                configfile_close(aacs->kf);

                DEBUG(DBG_AACS, "AACS initialized! (0x%08x)\n", aacs);
                return aacs;
            }
        }

346
347
348
        DEBUG(DBG_AACS, "Starting AACS waterfall...\n");
        //_calc_pk(aacs);
        if (_calc_mk(aacs, path)) {
349
           if (_calc_vuk(aacs, path)) {
350
                if (_calc_uks(aacs, path)) {
cRTrn13's avatar
cRTrn13 committed
351
                    configfile_close(aacs->kf);
352
353

                    DEBUG(DBG_AACS, "AACS initialized! (0x%08x)\n", aacs);
354
355
356
357
                    return aacs;
                }
            }
        }
cRTrn13's avatar
cRTrn13 committed
358
    }
cRTrn13's avatar
cRTrn13 committed
359

cRTrn13's avatar
cRTrn13 committed
360
361
    DEBUG(DBG_AACS, "Failed to initialize AACS! (0x%08x)\n", aacs);

cRTrn13's avatar
cRTrn13 committed
362
    return NULL;
cRTrn13's avatar
cRTrn13 committed
363
364
}

cRTrn13's avatar
cRTrn13 committed
365
void aacs_close(AACS *aacs)
cRTrn13's avatar
cRTrn13 committed
366
{
367
368
369
    X_FREE(aacs->uks);

    DEBUG(DBG_AACS, "AACS destroyed! (0x%08x)\n", aacs);
cRTrn13's avatar
cRTrn13 committed
370

cRTrn13's avatar
cRTrn13 committed
371
372
373
    X_FREE(aacs);
}

cRTrn13's avatar
cRTrn13 committed
374
int aacs_decrypt_unit(AACS *aacs, uint8_t *buf, uint32_t len, uint64_t offset)
375
{
cRTrn13's avatar
cRTrn13 committed
376
    return _decrypt_unit(aacs, buf, len, offset, 0);
377
}
cRTrn13's avatar
cRTrn13 committed
378

cRTrn13's avatar
cRTrn13 committed
379
uint8_t *aacs_get_vid(AACS *aacs)
cRTrn13's avatar
cRTrn13 committed
380
381
382
{
    return aacs->vid;
}