1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <drm_rights_manager.h>
18#include <drm_inner.h>
19#include <drm_file.h>
20#include <drm_i18n.h>
21
22static int32_t drm_getString(uint8_t* string, int32_t len, int32_t handle)
23{
24    int32_t i;
25
26    for (i = 0; i < len; i++) {
27        if (DRM_FILE_FAILURE == DRM_file_read(handle, &string[i], 1))
28            return FALSE;
29        if (string[i] == '\n') {
30            string[i + 1] = '\0';
31            break;
32        }
33    }
34    return TRUE;
35}
36
37static int32_t drm_putString(uint8_t* string, int32_t handle)
38{
39    int32_t i = 0;
40
41    for (i = 0;; i++) {
42        if (string[i] == '\0')
43            break;
44        if (DRM_FILE_FAILURE == DRM_file_write(handle, &string[i], 1))
45            return FALSE;
46    }
47    return TRUE;
48}
49
50static int32_t drm_writeToUidTxt(uint8_t* Uid, int32_t* id)
51{
52    int32_t length;
53    int32_t i;
54    uint8_t idStr[8];
55    int32_t idMax;
56    uint8_t(*uidStr)[256];
57    uint16_t nameUcs2[MAX_FILENAME_LEN];
58    int32_t nameLen;
59    int32_t bytesConsumed;
60    int32_t handle;
61    int32_t fileRes;
62
63    if (*id < 1)
64        return FALSE;
65
66    /* convert in ucs2 */
67    nameLen = strlen(DRM_UID_FILE_PATH);
68    nameLen = DRM_i18n_mbsToWcs(DRM_CHARSET_UTF8,
69                        (uint8_t *)DRM_UID_FILE_PATH,
70                        nameLen,
71                        nameUcs2,
72                        MAX_FILENAME_LEN,
73                        &bytesConsumed);
74    fileRes = DRM_file_open(nameUcs2,
75                        nameLen,
76                        DRM_FILE_MODE_READ,
77                        &handle);
78    if (DRM_FILE_SUCCESS != fileRes) {
79        DRM_file_open(nameUcs2,
80                        nameLen,
81                        DRM_FILE_MODE_WRITE,
82                        &handle);
83        DRM_file_write(handle, (uint8_t *)"0\n", 2);
84        DRM_file_close(handle);
85        DRM_file_open(nameUcs2,
86                        nameLen,
87                        DRM_FILE_MODE_READ,
88                        &handle);
89    }
90
91    if (!drm_getString(idStr, 8, handle)) {
92        DRM_file_close(handle);
93        return FALSE;
94    }
95    idMax = atoi((char *)idStr);
96
97    if (idMax < *id)
98        uidStr = malloc((idMax + 1) * 256);
99    else
100        uidStr = malloc(idMax * 256);
101
102    for (i = 0; i < idMax; i++) {
103        if (!drm_getString(uidStr[i], 256, handle)) {
104            DRM_file_close(handle);
105            free(uidStr);
106            return FALSE;
107        }
108    }
109    length = strlen((char *)Uid);
110    strcpy((char *)uidStr[*id - 1], (char *)Uid);
111    uidStr[*id - 1][length] = '\n';
112    uidStr[*id - 1][length + 1] = '\0';
113    if (idMax < (*id))
114        idMax++;
115    DRM_file_close(handle);
116
117    DRM_file_open(nameUcs2,
118                    nameLen,
119                    DRM_FILE_MODE_WRITE,
120                    &handle);
121    sprintf((char *)idStr, "%d", idMax);
122
123    if (!drm_putString(idStr, handle)) {
124        DRM_file_close(handle);
125        free(uidStr);
126        return FALSE;
127    }
128    if (DRM_FILE_FAILURE == DRM_file_write(handle, (uint8_t *)"\n", 1)) {
129        DRM_file_close(handle);
130        free(uidStr);
131        return FALSE;
132    }
133    for (i = 0; i < idMax; i++) {
134        if (!drm_putString(uidStr[i], handle)) {
135            DRM_file_close(handle);
136            free(uidStr);
137            return FALSE;
138        }
139    }
140    if (DRM_FILE_FAILURE == DRM_file_write(handle, (uint8_t *)"\n", 1)) {
141        DRM_file_close(handle);
142        free(uidStr);
143        return FALSE;
144    }
145    DRM_file_close(handle);
146    free(uidStr);
147    return TRUE;
148}
149
150/* See objmng_files.h */
151int32_t drm_readFromUidTxt(uint8_t* Uid, int32_t* id, int32_t option)
152{
153    int32_t i;
154    uint8_t p[256] = { 0 };
155    uint8_t idStr[8];
156    int32_t idMax = 0;
157    uint16_t nameUcs2[MAX_FILENAME_LEN];
158    int32_t nameLen = 0;
159    int32_t bytesConsumed;
160    int32_t handle;
161    int32_t fileRes;
162
163    if (NULL == id || NULL == Uid)
164        return FALSE;
165
166    DRM_file_startup();
167
168    /* convert in ucs2 */
169    nameLen = strlen(DRM_UID_FILE_PATH);
170    nameLen = DRM_i18n_mbsToWcs(DRM_CHARSET_UTF8,
171                        (uint8_t *)DRM_UID_FILE_PATH,
172                        nameLen,
173                        nameUcs2,
174                        MAX_FILENAME_LEN,
175                        &bytesConsumed);
176    fileRes = DRM_file_open(nameUcs2,
177                        nameLen,
178                        DRM_FILE_MODE_READ,
179                        &handle);
180    if (DRM_FILE_SUCCESS != fileRes) {
181        DRM_file_open(nameUcs2,
182                        nameLen,
183                        DRM_FILE_MODE_WRITE,
184                        &handle);
185        DRM_file_write(handle, (uint8_t *)"0\n", 2);
186        DRM_file_close(handle);
187        DRM_file_open(nameUcs2,
188                        nameLen,
189                        DRM_FILE_MODE_READ,
190                        &handle);
191    }
192
193    if (!drm_getString(idStr, 8, handle)) {
194        DRM_file_close(handle);
195        return FALSE;
196    }
197    idMax = atoi((char *)idStr);
198
199    if (option == GET_UID) {
200        if (*id < 1 || *id > idMax) {
201            DRM_file_close(handle);
202            return FALSE;
203        }
204        for (i = 1; i <= *id; i++) {
205            if (!drm_getString(Uid, 256, handle)) {
206                DRM_file_close(handle);
207                return FALSE;
208            }
209        }
210        DRM_file_close(handle);
211        return TRUE;
212    }
213    if (option == GET_ID) {
214        *id = -1;
215        for (i = 1; i <= idMax; i++) {
216            if (!drm_getString(p, 256, handle)) {
217                DRM_file_close(handle);
218                return FALSE;
219            }
220            if (strstr((char *)p, (char *)Uid) != NULL
221                && strlen((char *)p) == strlen((char *)Uid) + 1) {
222                *id = i;
223                DRM_file_close(handle);
224                return TRUE;
225            }
226            if ((*id == -1) && (strlen((char *)p) < 3))
227                *id = i;
228        }
229        if (*id != -1) {
230            DRM_file_close(handle);
231            return FALSE;
232        }
233        *id = idMax + 1;
234        DRM_file_close(handle);
235        return FALSE;
236    }
237    DRM_file_close(handle);
238    return FALSE;
239}
240
241static int32_t drm_acquireId(uint8_t* uid, int32_t* id)
242{
243    if (TRUE == drm_readFromUidTxt(uid, id, GET_ID))
244        return TRUE;
245
246    drm_writeToUidTxt(uid, id);
247
248    return FALSE; /* The Uid is not exit, then return FALSE indicate it */
249}
250
251int32_t drm_writeOrReadInfo(int32_t id, T_DRM_Rights* Ro, int32_t* RoAmount, int32_t option)
252{
253    uint8_t fullname[MAX_FILENAME_LEN] = {0};
254    int32_t tmpRoAmount;
255    uint16_t nameUcs2[MAX_FILENAME_LEN];
256    int32_t nameLen = 0;
257    int32_t bytesConsumed;
258    int32_t handle;
259    int32_t fileRes;
260
261    sprintf((char *)fullname, ANDROID_DRM_CORE_PATH"%d"EXTENSION_NAME_INFO, id);
262
263    /* convert in ucs2 */
264    nameLen = strlen((char *)fullname);
265    nameLen = DRM_i18n_mbsToWcs(DRM_CHARSET_UTF8,
266                        fullname,
267                        nameLen,
268                        nameUcs2,
269                        MAX_FILENAME_LEN,
270                        &bytesConsumed);
271    fileRes = DRM_file_open(nameUcs2,
272                            nameLen,
273                            DRM_FILE_MODE_READ,
274                            &handle);
275    if (DRM_FILE_SUCCESS != fileRes) {
276        if (GET_ALL_RO == option || GET_A_RO == option)
277            return FALSE;
278
279        if (GET_ROAMOUNT == option) {
280            *RoAmount = -1;
281            return TRUE;
282        }
283    }
284
285    DRM_file_close(handle);
286    DRM_file_open(nameUcs2,
287                nameLen,
288                DRM_FILE_MODE_READ | DRM_FILE_MODE_WRITE,
289                &handle);
290
291    switch(option) {
292    case GET_ROAMOUNT:
293        if (DRM_FILE_FAILURE == DRM_file_read(handle, (uint8_t*)RoAmount, sizeof(int32_t))) {
294            DRM_file_close(handle);
295            return FALSE;
296        }
297        break;
298    case GET_ALL_RO:
299        DRM_file_setPosition(handle, sizeof(int32_t));
300
301        if (DRM_FILE_FAILURE == DRM_file_read(handle, (uint8_t*)Ro, (*RoAmount) * sizeof(T_DRM_Rights))) {
302            DRM_file_close(handle);
303            return FALSE;
304        }
305        break;
306    case SAVE_ALL_RO:
307        if (DRM_FILE_FAILURE == DRM_file_write(handle, (uint8_t*)RoAmount, sizeof(int32_t))) {
308            DRM_file_close(handle);
309            return FALSE;
310        }
311
312        if (NULL != Ro && *RoAmount >= 1) {
313            if (DRM_FILE_FAILURE == DRM_file_write(handle, (uint8_t*) Ro, (*RoAmount) * sizeof(T_DRM_Rights))) {
314                DRM_file_close(handle);
315                return FALSE;
316            }
317        }
318        break;
319    case GET_A_RO:
320        DRM_file_setPosition(handle, sizeof(int32_t) + (*RoAmount - 1) * sizeof(T_DRM_Rights));
321
322        if (DRM_FILE_FAILURE == DRM_file_read(handle, (uint8_t*)Ro, sizeof(T_DRM_Rights))) {
323            DRM_file_close(handle);
324            return FALSE;
325        }
326        break;
327    case SAVE_A_RO:
328        DRM_file_setPosition(handle, sizeof(int32_t) + (*RoAmount - 1) * sizeof(T_DRM_Rights));
329
330        if (DRM_FILE_FAILURE == DRM_file_write(handle, (uint8_t*)Ro, sizeof(T_DRM_Rights))) {
331            DRM_file_close(handle);
332            return FALSE;
333        }
334
335        DRM_file_setPosition(handle, 0);
336        if (DRM_FILE_FAILURE == DRM_file_read(handle, (uint8_t*)&tmpRoAmount, sizeof(int32_t))) {
337            DRM_file_close(handle);
338            return FALSE;
339        }
340        if (tmpRoAmount < *RoAmount) {
341            DRM_file_setPosition(handle, 0);
342            DRM_file_write(handle, (uint8_t*)RoAmount, sizeof(int32_t));
343        }
344        break;
345    default:
346        DRM_file_close(handle);
347        return FALSE;
348    }
349
350    DRM_file_close(handle);
351    return TRUE;
352}
353
354int32_t drm_appendRightsInfo(T_DRM_Rights* rights)
355{
356    int32_t id;
357    int32_t roAmount;
358
359    if (NULL == rights)
360        return FALSE;
361
362    drm_acquireId(rights->uid, &id);
363
364    if (FALSE == drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT))
365        return FALSE;
366
367    if (-1 == roAmount)
368        roAmount = 0;
369
370    /* The RO amount increase */
371    roAmount++;
372
373    /* Save the rights information */
374    if (FALSE == drm_writeOrReadInfo(id, rights, &roAmount, SAVE_A_RO))
375        return FALSE;
376
377    return TRUE;
378}
379
380int32_t drm_getMaxIdFromUidTxt()
381{
382    uint8_t idStr[8];
383    int32_t idMax = 0;
384    uint16_t nameUcs2[MAX_FILENAME_LEN] = {0};
385    int32_t nameLen = 0;
386    int32_t bytesConsumed;
387    int32_t handle;
388    int32_t fileRes;
389
390    /* convert in ucs2 */
391    nameLen = strlen(DRM_UID_FILE_PATH);
392    nameLen = DRM_i18n_mbsToWcs(DRM_CHARSET_UTF8,
393                        (uint8_t *)DRM_UID_FILE_PATH,
394                        nameLen,
395                        nameUcs2,
396                        MAX_FILENAME_LEN,
397                        &bytesConsumed);
398    fileRes = DRM_file_open(nameUcs2,
399                        nameLen,
400                        DRM_FILE_MODE_READ,
401                        &handle);
402
403    /* this means the uid.txt file is not exist, so there is not any DRM object */
404    if (DRM_FILE_SUCCESS != fileRes)
405        return 0;
406
407    if (!drm_getString(idStr, 8, handle)) {
408        DRM_file_close(handle);
409        return -1;
410    }
411    DRM_file_close(handle);
412
413    idMax = atoi((char *)idStr);
414    return idMax;
415}
416
417int32_t drm_removeIdInfoFile(int32_t id)
418{
419    uint8_t filename[MAX_FILENAME_LEN] = {0};
420    uint16_t nameUcs2[MAX_FILENAME_LEN];
421    int32_t nameLen = 0;
422    int32_t bytesConsumed;
423
424    if (id <= 0)
425        return FALSE;
426
427    sprintf((char *)filename, ANDROID_DRM_CORE_PATH"%d"EXTENSION_NAME_INFO, id);
428
429    /* convert in ucs2 */
430    nameLen = strlen((char *)filename);
431    nameLen = DRM_i18n_mbsToWcs(DRM_CHARSET_UTF8,
432                        filename,
433                        nameLen,
434                        nameUcs2,
435                        MAX_FILENAME_LEN,
436                        &bytesConsumed);
437    if (DRM_FILE_SUCCESS != DRM_file_delete(nameUcs2, nameLen))
438        return FALSE;
439
440    return TRUE;
441}
442
443int32_t drm_updateUidTxtWhenDelete(int32_t id)
444{
445    uint16_t nameUcs2[MAX_FILENAME_LEN];
446    int32_t nameLen = 0;
447    int32_t bytesConsumed;
448    int32_t handle;
449    int32_t fileRes;
450    int32_t bufferLen;
451    uint8_t *buffer;
452    uint8_t idStr[8];
453    int32_t idMax;
454
455    if (id <= 0)
456        return FALSE;
457
458    nameLen = strlen(DRM_UID_FILE_PATH);
459    nameLen = DRM_i18n_mbsToWcs(DRM_CHARSET_UTF8,
460                        (uint8_t *)DRM_UID_FILE_PATH,
461                        nameLen,
462                        nameUcs2,
463                        MAX_FILENAME_LEN,
464                        &bytesConsumed);
465    bufferLen = DRM_file_getFileLength(nameUcs2, nameLen);
466    if (bufferLen <= 0)
467        return FALSE;
468
469    buffer = (uint8_t *)malloc(bufferLen);
470    if (NULL == buffer)
471        return FALSE;
472
473    fileRes = DRM_file_open(nameUcs2,
474                            nameLen,
475                            DRM_FILE_MODE_READ,
476                            &handle);
477    if (DRM_FILE_SUCCESS != fileRes) {
478        free(buffer);
479        return FALSE;
480    }
481
482    drm_getString(idStr, 8, handle);
483    idMax = atoi((char *)idStr);
484
485    bufferLen -= strlen((char *)idStr);
486    fileRes = DRM_file_read(handle, buffer, bufferLen);
487    buffer[bufferLen] = '\0';
488    DRM_file_close(handle);
489
490    /* handle this buffer */
491    {
492        uint8_t *pStart, *pEnd;
493        int32_t i, movLen;
494
495        pStart = buffer;
496        pEnd = pStart;
497        for (i = 0; i < id; i++) {
498            if (pEnd != pStart)
499                pStart = ++pEnd;
500            while ('\n' != *pEnd)
501                pEnd++;
502            if (pStart == pEnd)
503                pStart--;
504        }
505        movLen = bufferLen - (pEnd - buffer);
506        memmove(pStart, pEnd, movLen);
507        bufferLen -= (pEnd - pStart);
508    }
509
510    if (DRM_FILE_SUCCESS != DRM_file_delete(nameUcs2, nameLen)) {
511        free(buffer);
512        return FALSE;
513    }
514
515    fileRes = DRM_file_open(nameUcs2,
516        nameLen,
517        DRM_FILE_MODE_WRITE,
518        &handle);
519    if (DRM_FILE_SUCCESS != fileRes) {
520        free(buffer);
521        return FALSE;
522    }
523    sprintf((char *)idStr, "%d", idMax);
524    drm_putString(idStr, handle);
525    DRM_file_write(handle, (uint8_t*)"\n", 1);
526    DRM_file_write(handle, buffer, bufferLen);
527    free(buffer);
528    DRM_file_close(handle);
529    return TRUE;
530}
531
532int32_t drm_getKey(uint8_t* uid, uint8_t* KeyValue)
533{
534    T_DRM_Rights ro;
535    int32_t id, roAmount;
536
537    if (NULL == uid || NULL == KeyValue)
538        return FALSE;
539
540    if (FALSE == drm_readFromUidTxt(uid, &id, GET_ID))
541        return FALSE;
542
543    if (FALSE == drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT))
544        return FALSE;
545
546    if (roAmount <= 0)
547        return FALSE;
548
549    memset(&ro, 0, sizeof(T_DRM_Rights));
550    roAmount = 1;
551    if (FALSE == drm_writeOrReadInfo(id, &ro, &roAmount, GET_A_RO))
552        return FALSE;
553
554    memcpy(KeyValue, ro.KeyValue, DRM_KEY_LEN);
555    return TRUE;
556}
557
558void drm_discardPaddingByte(uint8_t *decryptedBuf, int32_t *decryptedBufLen)
559{
560    int32_t tmpLen = *decryptedBufLen;
561    int32_t i;
562
563    if (NULL == decryptedBuf || *decryptedBufLen < 0)
564        return;
565
566    /* Check whether the last several bytes are padding or not */
567    for (i = 1; i < decryptedBuf[tmpLen - 1]; i++) {
568        if (decryptedBuf[tmpLen - 1 - i] != decryptedBuf[tmpLen - 1])
569            break; /* Not the padding bytes */
570    }
571    if (i == decryptedBuf[tmpLen - 1]) /* They are padding bytes */
572        *decryptedBufLen = tmpLen - i;
573    return;
574}
575
576int32_t drm_aesDecBuffer(uint8_t * Buffer, int32_t * BufferLen, AES_KEY *key)
577{
578    uint8_t dbuf[3 * DRM_ONE_AES_BLOCK_LEN], buf[DRM_ONE_AES_BLOCK_LEN];
579    uint64_t i, len, wlen = DRM_ONE_AES_BLOCK_LEN, curLen, restLen;
580    uint8_t *pTarget, *pTargetHead;
581
582    pTargetHead = Buffer;
583    pTarget = Buffer;
584    curLen = 0;
585    restLen = *BufferLen;
586
587    if (restLen > 2 * DRM_ONE_AES_BLOCK_LEN) {
588        len = 2 * DRM_ONE_AES_BLOCK_LEN;
589    } else {
590        len = restLen;
591    }
592    memcpy(dbuf, Buffer, (size_t)len);
593    restLen -= len;
594    Buffer += len;
595
596    if (len < 2 * DRM_ONE_AES_BLOCK_LEN) { /* The original file is less than one block in length */
597        len -= DRM_ONE_AES_BLOCK_LEN;
598        /* Decrypt from position len to position len + DRM_ONE_AES_BLOCK_LEN */
599        AES_decrypt((dbuf + len), (dbuf + len), key);
600
601        /* Undo the CBC chaining */
602        for (i = 0; i < len; ++i)
603            dbuf[i] ^= dbuf[i + DRM_ONE_AES_BLOCK_LEN];
604
605        /* Output the decrypted bytes */
606        memcpy(pTarget, dbuf, (size_t)len);
607        pTarget += len;
608    } else {
609        uint8_t *b1 = dbuf, *b2 = b1 + DRM_ONE_AES_BLOCK_LEN, *b3 = b2 + DRM_ONE_AES_BLOCK_LEN, *bt;
610
611        for (;;) { /* While some ciphertext remains, prepare to decrypt block b2 */
612            /* Read in the next block to see if ciphertext stealing is needed */
613            b3 = Buffer;
614            if (restLen > DRM_ONE_AES_BLOCK_LEN) {
615                len = DRM_ONE_AES_BLOCK_LEN;
616            } else {
617                len = restLen;
618            }
619            restLen -= len;
620            Buffer += len;
621
622            /* Decrypt the b2 block */
623            AES_decrypt((uint8_t *)b2, buf, key);
624
625            if (len == 0 || len == DRM_ONE_AES_BLOCK_LEN) { /* No ciphertext stealing */
626                /* Unchain CBC using the previous ciphertext block in b1 */
627                for (i = 0; i < DRM_ONE_AES_BLOCK_LEN; ++i)
628                    buf[i] ^= b1[i];
629            } else { /* Partial last block - use ciphertext stealing */
630                wlen = len;
631                /* Produce last 'len' bytes of plaintext by xoring with */
632                /* The lowest 'len' bytes of next block b3 - C[N-1] */
633                for (i = 0; i < len; ++i)
634                    buf[i] ^= b3[i];
635
636                /* Reconstruct the C[N-1] block in b3 by adding in the */
637                /* Last (DRM_ONE_AES_BLOCK_LEN - len) bytes of C[N-2] in b2 */
638                for (i = len; i < DRM_ONE_AES_BLOCK_LEN; ++i)
639                    b3[i] = buf[i];
640
641                /* Decrypt the C[N-1] block in b3 */
642                AES_decrypt((uint8_t *)b3, (uint8_t *)b3, key);
643
644                /* Produce the last but one plaintext block by xoring with */
645                /* The last but two ciphertext block */
646                for (i = 0; i < DRM_ONE_AES_BLOCK_LEN; ++i)
647                    b3[i] ^= b1[i];
648
649                /* Write decrypted plaintext blocks */
650                memcpy(pTarget, b3, DRM_ONE_AES_BLOCK_LEN);
651                pTarget += DRM_ONE_AES_BLOCK_LEN;
652            }
653
654            /* Write the decrypted plaintext block */
655            memcpy(pTarget, buf, (size_t)wlen);
656            pTarget += wlen;
657
658            if (len != DRM_ONE_AES_BLOCK_LEN) {
659                *BufferLen = pTarget - pTargetHead;
660                return 0;
661            }
662
663            /* Advance the buffer pointers */
664            bt = b1, b1 = b2, b2 = b3, b3 = bt;
665        }
666    }
667    return 0;
668}
669
670int32_t drm_updateDcfDataLen(uint8_t* pDcfLastData, uint8_t* keyValue, int32_t* moreBytes)
671{
672    AES_KEY key;
673    int32_t len = DRM_TWO_AES_BLOCK_LEN;
674
675    if (NULL == pDcfLastData || NULL == keyValue)
676        return FALSE;
677
678    AES_set_decrypt_key(keyValue, DRM_KEY_LEN * 8, &key);
679
680    if (drm_aesDecBuffer(pDcfLastData, &len, &key) < 0)
681        return FALSE;
682
683    drm_discardPaddingByte(pDcfLastData, &len);
684
685    *moreBytes = DRM_TWO_AES_BLOCK_LEN - len;
686
687    return TRUE;
688}
689