aacs.c 6.68 KB
Newer Older
cRTrn13's avatar
cRTrn13 committed
1 2

#include <stdio.h>
cRTrn13's avatar
cRTrn13 committed
3
#include <malloc.h>
cRTrn13's avatar
openssl  
cRTrn13 committed
4
#include <string.h>
cRTrn13's avatar
cRTrn13 committed
5 6

#include "aacs.h"
7
#include "crypto.h"
cRTrn13's avatar
cRTrn13 committed
8
#include "mmc.h"
cRTrn13's avatar
cRTrn13 committed
9
#include "../util/macro.h"
10
#include "../util/logging.h"
11
#include "../file/file.h"
cRTrn13's avatar
cRTrn13 committed
12

cRTrn13's avatar
cRTrn13 committed
13
int _calc_pk(AACS_KEYS *aacs);
cRTrn13's avatar
keyfile  
cRTrn13 committed
14
int _calc_mk(AACS_KEYS *aacs, const char *path);
cRTrn13's avatar
cRTrn13 committed
15 16
int _calc_vuk(AACS_KEYS *aacs, const char *path);
int _calc_uks(AACS_KEYS *aacs, const char *path);
cRTrn13's avatar
openssl  
cRTrn13 committed
17
int _validate_pk(uint8_t *pk, uint8_t *cvalue, uint8_t *uv, uint8_t *vd, uint8_t *mk);
cRTrn13's avatar
keyfile  
cRTrn13 committed
18
int _verify_ts(uint8_t *buf, size_t size);
19

20

cRTrn13's avatar
keyfile  
cRTrn13 committed
21 22
int _calc_mk(AACS_KEYS *aacs, const char *path)
{
23 24
    DEBUG(DBG_AACS, "Calculate media key...\n");

cRTrn13's avatar
keyfile  
cRTrn13 committed
25 26
    int a, num_uvs = 0;
    size_t len;
cRTrn13's avatar
cRTrn13 committed
27
    uint8_t *buf = NULL, *rec, *uvs, *key_pos, *pks;
cRTrn13's avatar
cRTrn13 committed
28
    uint16_t num_pks;
cRTrn13's avatar
keyfile  
cRTrn13 committed
29 30
    MKB *mkb = NULL;

31 32 33 34 35 36 37 38 39 40
    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
41

42 43 44 45 46 47 48 49 50 51 52 53
        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);
54 55

                        DEBUG(DBG_AACS, "Media key: %s\n", print_hex(aacs->mk, 16));
56 57 58 59 60
                        return 1;
                    }
                }

                key_pos += 16;
cRTrn13's avatar
keyfile  
cRTrn13 committed
61
            }
62
        }
cRTrn13's avatar
keyfile  
cRTrn13 committed
63

64 65
        mkb_close(mkb);
        X_FREE(buf);
cRTrn13's avatar
keyfile  
cRTrn13 committed
66 67 68 69
    }

    return 0;
}
70

cRTrn13's avatar
cRTrn13 committed
71
int _calc_vuk(AACS_KEYS *aacs, const char *path)
cRTrn13's avatar
openssl  
cRTrn13 committed
72 73 74
{
    int a;
    AES_KEY aes;
cRTrn13's avatar
cRTrn13 committed
75
    MMC* mmc = NULL;
cRTrn13's avatar
openssl  
cRTrn13 committed
76

77 78
    DEBUG(DBG_AACS, "Calculate volume unique key...\n");

cRTrn13's avatar
cRTrn13 committed
79
    if ((mmc = mmc_open(path,
cRTrn13's avatar
cRTrn13 committed
80 81 82 83
            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)))) {
84
        if (mmc_read_vid(mmc, aacs->vid)) {
cRTrn13's avatar
cRTrn13 committed
85
            AES_set_decrypt_key(aacs->mk, 128, &aes);
86
            AES_decrypt(aacs->vid, aacs->vuk, &aes);
cRTrn13's avatar
openssl  
cRTrn13 committed
87 88

            for (a = 0; a < 16; a++) {
89
                aacs->vuk[a] ^= aacs->vid[a];
cRTrn13's avatar
openssl  
cRTrn13 committed
90
            }
cRTrn13's avatar
cRTrn13 committed
91 92

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

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

cRTrn13's avatar
openssl  
cRTrn13 committed
96 97 98
            return 1;
        }

cRTrn13's avatar
cRTrn13 committed
99 100
        mmc_close(mmc);
    }
cRTrn13's avatar
openssl  
cRTrn13 committed
101

102 103
    DEBUG(DBG_AACS, "Error calculating VUK!\n");

cRTrn13's avatar
openssl  
cRTrn13 committed
104 105 106
    return 0;
}

cRTrn13's avatar
cRTrn13 committed
107
int _calc_uks(AACS_KEYS *aacs, const char *path)
cRTrn13's avatar
openssl  
cRTrn13 committed
108 109
{
    AES_KEY aes;
110
    FILE_H *fp = NULL;
111
    uint8_t buf[16];
cRTrn13's avatar
openssl  
cRTrn13 committed
112
    char f_name[100];
113
    uint64_t f_pos;
cRTrn13's avatar
openssl  
cRTrn13 committed
114

115 116 117
    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
118

119
    if ((fp = file_open(f_name, "rb"))) {
120 121
        if ((file_read(fp, buf, 4)) == 4) {
            f_pos = MKINT_BE32(buf) + 48;
cRTrn13's avatar
openssl  
cRTrn13 committed
122

cRTrn13's avatar
cRTrn13 committed
123
            file_seek(fp, f_pos, SEEK_SET);
124 125 126
            if ((file_read(fp, buf, 16)) == 16) {
                // TODO: support more than a single UK!!!
                aacs->uks = malloc(16);
cRTrn13's avatar
openssl  
cRTrn13 committed
127

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

131
                file_close(fp);
cRTrn13's avatar
openssl  
cRTrn13 committed
132

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

135 136 137 138 139
                return 1;
            }
        }

        file_close(fp);
cRTrn13's avatar
openssl  
cRTrn13 committed
140 141
    }

142 143
    DEBUG(DBG_AACS, "Could not calculate unit keys!\n");

cRTrn13's avatar
openssl  
cRTrn13 committed
144 145 146 147 148 149 150 151 152
    return 0;
}

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];

153 154 155 156 157 158
    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));

cRTrn13's avatar
openssl  
cRTrn13 committed
159 160 161 162 163 164 165 166 167 168 169
    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)) {
170
        DEBUG(DBG_AACS, "Processing key is valid!\n");
cRTrn13's avatar
openssl  
cRTrn13 committed
171 172 173 174 175 176
        return 1;
    }

    return 0;
}

177 178
int _verify_ts(uint8_t *buf, size_t size)
{
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
    uint8_t *ptr;

    for (ptr=buf; ptr < buf+size; ptr++) {
        if(*ptr == 0x47) {
            uint8_t *ptr2;

            for (ptr2=ptr; ptr2 < buf + size; ptr2 += 192) {
                if (*ptr2 != 0x47) {
                    return 0;
                }
            }
        }
        ptr++;
    }

194 195 196
    return 1;
}

cRTrn13's avatar
cRTrn13 committed
197
AACS_KEYS *aacs_open(const char *path, const char *configfile_path)
cRTrn13's avatar
cRTrn13 committed
198
{
cRTrn13's avatar
cRTrn13 committed
199 200
    DEBUG(DBG_AACS, "libaacs v%s\n", LIBAACS_VERSION);

cRTrn13's avatar
cRTrn13 committed
201
    AACS_KEYS *aacs = malloc(sizeof(AACS_KEYS));
202

203
    aacs->uks = NULL;
cRTrn13's avatar
cRTrn13 committed
204
    aacs->kf = NULL;
cRTrn13's avatar
cRTrn13 committed
205
    if ((aacs->kf = configfile_open(configfile_path))) {
206 207 208
        DEBUG(DBG_AACS, "Starting AACS waterfall...\n");
        //_calc_pk(aacs);
        if (_calc_mk(aacs, path)) {
209
           if (_calc_vuk(aacs, path)) {
210
                if (_calc_uks(aacs, path)) {
cRTrn13's avatar
cRTrn13 committed
211
                    configfile_close(aacs->kf);
212 213

                    DEBUG(DBG_AACS, "AACS initialized! (0x%08x)\n", aacs);
214 215 216 217
                    return aacs;
                }
            }
        }
cRTrn13's avatar
cRTrn13 committed
218
    }
cRTrn13's avatar
cRTrn13 committed
219

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

cRTrn13's avatar
cRTrn13 committed
222
    return NULL;
cRTrn13's avatar
cRTrn13 committed
223 224
}

cRTrn13's avatar
cRTrn13 committed
225
void aacs_close(AACS_KEYS *aacs)
cRTrn13's avatar
cRTrn13 committed
226
{
227 228 229
    X_FREE(aacs->uks);

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

cRTrn13's avatar
cRTrn13 committed
231 232 233
    X_FREE(aacs);
}

234
int aacs_decrypt_unit(AACS_KEYS *aacs, uint8_t *buf, uint32_t len, uint64_t offset)
235
{
236
    if (offset % 6144) {
cRTrn13's avatar
cRTrn13 committed
237 238 239 240
        AES_cbc_encrypt(buf, 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 };
241

cRTrn13's avatar
cRTrn13 committed
242
        memcpy(aacs->iv, iv, 16);
243

cRTrn13's avatar
cRTrn13 committed
244 245
        AES_set_encrypt_key(aacs->uks, 128, &aacs->aes);
        AES_encrypt(buf, key, &aacs->aes);
246

cRTrn13's avatar
cRTrn13 committed
247 248 249
        for (a = 0; a < 16; a++) {
            key[a] ^= buf[a];
        }
cRTrn13's avatar
cRTrn13 committed
250

cRTrn13's avatar
cRTrn13 committed
251
        AES_set_decrypt_key(key, 128, &aacs->aes);
cRTrn13's avatar
cRTrn13 committed
252
        AES_cbc_encrypt(buf + 16, buf + 16, len - 16, &aacs->aes, aacs->iv, 0);
253 254 255 256
    }

    if (_verify_ts(buf,len)) {
        DEBUG(DBG_AACS, "Decrypted %s unit [%d bytes] from offset %ld (0x%08x)\n", len % 6144 ? "PARTIAL" : "FULL", len, offset, aacs);
cRTrn13's avatar
cRTrn13 committed
257 258 259 260 261

        return 1;
    }

    return 0;
262
}