aacs.c 8.97 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 25 26 27 28 29 30 31 32 33
int _validate_pk(uint8_t *pk, uint8_t *cvalue, uint8_t *uv, uint8_t *vd, uint8_t *mk)
{
    int a;
    AES_KEY aes;
    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));
34

cRTrn13's avatar
cRTrn13 committed
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
    AES_set_decrypt_key(pk, 128, &aes);
    AES_decrypt(cvalue, mk, &aes);

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

    AES_set_decrypt_key(mk, 128, &aes);
    AES_decrypt(vd, dec_vd, &aes);

    if (!memcmp(dec_vd, "\x01\x23\x45\x67\x89\xAB\xCD\xEF", 8)) {
        DEBUG(DBG_AACS, "Processing key is valid!\n");
        return 1;
    }

    return 0;
}
52

cRTrn13's avatar
cRTrn13 committed
53
int _calc_mk(AACS *aacs, const char *path)
cRTrn13's avatar
keyfile  
cRTrn13 committed
54
{
55 56
    DEBUG(DBG_AACS, "Calculate media key...\n");

cRTrn13's avatar
keyfile  
cRTrn13 committed
57 58
    int a, num_uvs = 0;
    size_t len;
cRTrn13's avatar
cRTrn13 committed
59
    uint8_t *buf = NULL, *rec, *uvs, *key_pos, *pks;
cRTrn13's avatar
cRTrn13 committed
60
    uint16_t num_pks;
cRTrn13's avatar
keyfile  
cRTrn13 committed
61 62
    MKB *mkb = NULL;

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

74 75 76 77 78 79 80 81 82 83 84 85
        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);
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 106
{
    int a;
    AES_KEY aes;
cRTrn13's avatar
cRTrn13 committed
107
    MMC* mmc = NULL;
cRTrn13's avatar
openssl  
cRTrn13 committed
108

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

cRTrn13's avatar
cRTrn13 committed
111
    if ((mmc = mmc_open(path,
cRTrn13's avatar
cRTrn13 committed
112 113 114 115
            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)))) {
116
        if (mmc_read_vid(mmc, aacs->vid)) {
cRTrn13's avatar
cRTrn13 committed
117
            AES_set_decrypt_key(aacs->mk, 128, &aes);
118
            AES_decrypt(aacs->vid, aacs->vuk, &aes);
cRTrn13's avatar
openssl  
cRTrn13 committed
119 120

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

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

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

cRTrn13's avatar
openssl  
cRTrn13 committed
128 129 130
            return 1;
        }

cRTrn13's avatar
cRTrn13 committed
131 132
        mmc_close(mmc);
    }
cRTrn13's avatar
openssl  
cRTrn13 committed
133

134 135
    DEBUG(DBG_AACS, "Error calculating VUK!\n");

cRTrn13's avatar
openssl  
cRTrn13 committed
136 137 138
    return 0;
}

cRTrn13's avatar
cRTrn13 committed
139
int _calc_uks(AACS *aacs, const char *path)
cRTrn13's avatar
openssl  
cRTrn13 committed
140 141
{
    AES_KEY aes;
142
    FILE_H *fp = NULL;
143
    uint8_t buf[16];
cRTrn13's avatar
openssl  
cRTrn13 committed
144
    char f_name[100];
145
    uint64_t f_pos;
cRTrn13's avatar
openssl  
cRTrn13 committed
146

147 148 149
    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
150

151
    if ((fp = file_open(f_name, "rb"))) {
152 153
        if ((file_read(fp, buf, 4)) == 4) {
            f_pos = MKINT_BE32(buf) + 48;
cRTrn13's avatar
openssl  
cRTrn13 committed
154

cRTrn13's avatar
cRTrn13 committed
155
            file_seek(fp, f_pos, SEEK_SET);
156 157 158
            if ((file_read(fp, buf, 16)) == 16) {
                // TODO: support more than a single UK!!!
                aacs->uks = malloc(16);
cRTrn13's avatar
openssl  
cRTrn13 committed
159

160 161
                AES_set_decrypt_key(aacs->vuk, 128, &aes);
                AES_decrypt(buf, aacs->uks, &aes);
cRTrn13's avatar
openssl  
cRTrn13 committed
162

163
                file_close(fp);
cRTrn13's avatar
openssl  
cRTrn13 committed
164

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

167 168 169 170 171
                return 1;
            }
        }

        file_close(fp);
cRTrn13's avatar
openssl  
cRTrn13 committed
172 173
    }

174 175
    DEBUG(DBG_AACS, "Could not calculate unit keys!\n");

cRTrn13's avatar
openssl  
cRTrn13 committed
176 177 178
    return 0;
}

cRTrn13's avatar
cRTrn13 committed
179 180


181 182
int _verify_ts(uint8_t *buf, size_t size)
{
183 184
    uint8_t *ptr;

cRTrn13's avatar
cRTrn13 committed
185 186 187 188 189 190 191
    if (size < 192) {
        return 1;
    }

    for (ptr=buf; ptr < buf+192; ptr++) {
        int failed = 0;
        if (*ptr == 0x47) {
192 193 194 195
            uint8_t *ptr2;

            for (ptr2=ptr; ptr2 < buf + size; ptr2 += 192) {
                if (*ptr2 != 0x47) {
cRTrn13's avatar
cRTrn13 committed
196 197
                    failed = 1;
                    break;
198 199
                }
            }
cRTrn13's avatar
cRTrn13 committed
200 201 202
            if (!failed) {
                return 1;
            }
203 204 205 206
        }
        ptr++;
    }

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

cRTrn13's avatar
cRTrn13 committed
209
    return 0;
210 211
}

cRTrn13's avatar
cRTrn13 committed
212
int _find_vuk(AACS *aacs, const char *path)
213
{
cRTrn13's avatar
cRTrn13 committed
214
    uint8_t *vuks, *key_pos, hash[20], *ukf_buf;
cRTrn13's avatar
cRTrn13 committed
215
    FILE_H *fp = NULL;
cRTrn13's avatar
cRTrn13 committed
216
    uint64_t f_size;
217
    uint16_t num_vuks;
cRTrn13's avatar
cRTrn13 committed
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
    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);
243

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

cRTrn13's avatar
cRTrn13 committed
247 248
    X_FREE(ukf_buf);

249 250 251
    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
252
            if (!memcmp(hash, key_pos, 20)) {
253 254
                uint8_t desc[11];

cRTrn13's avatar
cRTrn13 committed
255
                memcpy(desc, key_pos + 20, 10);
256 257
                desc[10] = 0;

cRTrn13's avatar
cRTrn13 committed
258
                memcpy(aacs->vuk, key_pos + 30, 16);
259 260

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

                return 1;
263 264 265 266 267 268
            }

            key_pos += 46;
        }
    }

269
    return 0;
270 271
}

cRTrn13's avatar
cRTrn13 committed
272
int _decrypt_unit(AACS *aacs, uint8_t *buf, uint32_t len, uint64_t offset, uint32_t curr_uk)
cRTrn13's avatar
cRTrn13 committed
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 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
{
    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
314
AACS *aacs_open(const char *path, const char *configfile_path)
cRTrn13's avatar
cRTrn13 committed
315
{
cRTrn13's avatar
cRTrn13 committed
316
    DEBUG(DBG_AACS, "libaacs v%s [%ld]\n", LIBAACS_VERSION, sizeof(AACS));
cRTrn13's avatar
cRTrn13 committed
317

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

320
    aacs->uks = NULL;
cRTrn13's avatar
cRTrn13 committed
321
    aacs->kf = NULL;
cRTrn13's avatar
cRTrn13 committed
322
    if ((aacs->kf = configfile_open(configfile_path))) {
323 324 325 326 327 328 329 330 331 332
        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;
            }
        }

333 334 335
        DEBUG(DBG_AACS, "Starting AACS waterfall...\n");
        //_calc_pk(aacs);
        if (_calc_mk(aacs, path)) {
336
           if (_calc_vuk(aacs, path)) {
337
                if (_calc_uks(aacs, path)) {
cRTrn13's avatar
cRTrn13 committed
338
                    configfile_close(aacs->kf);
339 340

                    DEBUG(DBG_AACS, "AACS initialized! (0x%08x)\n", aacs);
341 342 343 344
                    return aacs;
                }
            }
        }
cRTrn13's avatar
cRTrn13 committed
345
    }
cRTrn13's avatar
cRTrn13 committed
346

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

cRTrn13's avatar
cRTrn13 committed
349
    return NULL;
cRTrn13's avatar
cRTrn13 committed
350 351
}

cRTrn13's avatar
cRTrn13 committed
352
void aacs_close(AACS *aacs)
cRTrn13's avatar
cRTrn13 committed
353
{
354 355 356
    X_FREE(aacs->uks);

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

cRTrn13's avatar
cRTrn13 committed
358 359 360
    X_FREE(aacs);
}

cRTrn13's avatar
cRTrn13 committed
361
int aacs_decrypt_unit(AACS *aacs, uint8_t *buf, uint32_t len, uint64_t offset)
362
{
cRTrn13's avatar
cRTrn13 committed
363
    return _decrypt_unit(aacs, buf, len, offset, 0);
364
}
cRTrn13's avatar
cRTrn13 committed
365

cRTrn13's avatar
cRTrn13 committed
366
uint8_t *aacs_get_vid(AACS *aacs)
cRTrn13's avatar
cRTrn13 committed
367 368 369
{
    return aacs->vid;
}