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 <parser_rel.h>
18#include <parser_dm.h>
19#include <xml_tinyParser.h>
20#include <wbxml_tinyparser.h>
21#include <drm_decoder.h>
22#include <svc_drm.h>
23
24/* See parser_rel.h */
25int32_t drm_monthDays(int32_t year, int32_t month)
26{
27    switch (month) {
28    case 1:
29    case 3:
30    case 5:
31    case 7:
32    case 8:
33    case 10:
34    case 12:
35        return 31;
36    case 4:
37    case 6:
38    case 9:
39    case 11:
40        return 30;
41    case 2:
42        if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))
43            return 29;
44        else
45            return 28;
46    default:
47        return -1;
48    }
49}
50
51int32_t drm_checkDate(int32_t year, int32_t month, int32_t day,
52                      int32_t hour, int32_t min, int32_t sec)
53{
54    if (month >= 1 && month <= 12 &&
55        day >= 1 && day <= drm_monthDays(year, month) &&
56        hour >= 0 && hour <= 23 &&
57        min >= 0 && min <= 59 && sec >= 0 && sec <= 59)
58        return 0;
59    else
60        return -1;
61}
62
63static int32_t drm_getStartEndTime(uint8_t * pValue, int32_t valueLen,
64                                   T_DRM_DATETIME * dateTime)
65{
66    int32_t year, mon, day, hour, min, sec;
67    uint8_t pTmp[64] = {0};
68
69    strncpy((char *)pTmp, (char *)pValue, valueLen);
70    {
71        uint8_t * pHead = pTmp;
72        uint8_t * pEnd = NULL;
73        uint8_t tmpByte;
74
75        /** get year */
76        pEnd = (uint8_t *)strstr((char *)pHead, "-");
77        if(NULL == pEnd)
78            return FALSE;
79        tmpByte = *pEnd;
80        *pEnd = '\0';
81        year = atoi((char *)pHead);
82        pHead = pEnd + 1;
83        *pEnd = tmpByte;
84
85        /** get month */
86        pEnd = (uint8_t *)strstr((char *)pHead, "-");
87        if(NULL == pEnd)
88            return FALSE;
89        tmpByte = *pEnd;
90        *pEnd = '\0';
91        mon = atoi((char *)pHead);
92        pHead = pEnd + 1;
93        *pEnd = tmpByte;
94
95        /** get day */
96        pEnd = (uint8_t *)strstr((char *)pHead, "T");
97        if(NULL == pEnd)
98            return FALSE;
99        tmpByte = *pEnd;
100        *pEnd = '\0';
101        day = atoi((char *)pHead);
102        pHead = pEnd + 1;
103        *pEnd = tmpByte;
104
105        /** get hour */
106        pEnd = (uint8_t *)strstr((char *)pHead, ":");
107        if(NULL == pEnd)
108            return FALSE;
109        tmpByte = *pEnd;
110        *pEnd = '\0';
111        hour = atoi((char *)pHead);
112        pHead = pEnd + 1;
113        *pEnd = tmpByte;
114
115        /** get minute */
116        pEnd = (uint8_t *)strstr((char *)pHead, ":");
117        if(NULL == pEnd)
118            return FALSE;
119        tmpByte = *pEnd;
120        *pEnd = '\0';
121        min = atoi((char *)pHead);
122        pHead = pEnd + 1;
123        *pEnd = tmpByte;
124
125        /** get second */
126        sec = atoi((char *)pHead);
127    }
128    if (0 != drm_checkDate(year, mon, day, hour, min, sec))
129        return FALSE;
130
131    YMD_HMS_2_INT(year, mon, day, dateTime->date, hour, min, sec,
132                  dateTime->time);
133    return TRUE;
134}
135
136static int32_t drm_checkWhetherHasUnknowConstraint(uint8_t* drm_constrain)
137{
138    char* begin_constrain = "<o-ex:constraint>";
139    char* end_constrain = "</o-ex:constraint>";
140    char* constrain_begin = strstr((char*)drm_constrain,begin_constrain);
141    char* constrain_end = strstr((char*)drm_constrain,end_constrain);
142    uint32_t constrain_len = 0;
143
144    if(NULL == constrain_begin)
145        return FALSE;
146
147    if(NULL == constrain_end)
148        return TRUE;
149
150    /* compute valid characters length */
151    {
152        uint32_t constrain_begin_len = strlen(begin_constrain);
153        char* cur_pos = constrain_begin + constrain_begin_len;
154
155        constrain_len = (constrain_end - constrain_begin) - constrain_begin_len;
156
157        while(cur_pos < constrain_end){
158            if(isspace(*cur_pos))
159                constrain_len--;
160
161            cur_pos++;
162        }
163    }
164
165    /* check all constraints */
166    {
167        #define DRM_ALL_CONSTRAINT_COUNT 5
168
169        int32_t i = 0;
170        int32_t has_datetime = FALSE;
171        int32_t has_start_or_end = FALSE;
172
173        char* all_vaild_constraints[DRM_ALL_CONSTRAINT_COUNT][2] = {
174            {"<o-dd:count>","</o-dd:count>"},
175            {"<o-dd:interval>","</o-dd:interval>"},
176            {"<o-dd:datetime>","</o-dd:datetime>"},
177            {"<o-dd:start>","</o-dd:start>"},
178            {"<o-dd:end>","</o-dd:end>"}
179        };
180
181        for(i = 0; i < DRM_ALL_CONSTRAINT_COUNT; i++){
182            char*start = strstr((char*)drm_constrain,all_vaild_constraints[i][0]);
183
184            if(start && (start < constrain_end)){
185                char* end = strstr((char*)drm_constrain,all_vaild_constraints[i][1]);
186
187                if(end && (end < constrain_end)){
188                    if(0 == strncmp(all_vaild_constraints[i][0],"<o-dd:datetime>",strlen("<o-dd:datetime>"))){
189                        constrain_len -= strlen(all_vaild_constraints[i][0]);
190                        constrain_len -= strlen(all_vaild_constraints[i][1]);
191
192                        if(0 == constrain_len)
193                            return TRUE;
194
195                        has_datetime = TRUE;
196                        continue;
197                    }
198
199                    if((0 == strncmp(all_vaild_constraints[i][0],"<o-dd:start>",strlen("<o-dd:start>")))
200                        || (0 == strncmp(all_vaild_constraints[i][0],"<o-dd:end>",strlen("<o-dd:end>")))){
201                        if(FALSE == has_datetime)
202                            return TRUE;
203                        else
204                            has_start_or_end = TRUE;
205                    }
206
207                    constrain_len -= (end - start);
208                    constrain_len -= strlen(all_vaild_constraints[i][1]);
209
210                    if(0 == constrain_len)
211                        if(has_datetime != has_start_or_end)
212                            return TRUE;
213                        else
214                            return FALSE;
215                }
216                else
217                    return TRUE;
218            }
219        }
220
221        if(has_datetime != has_start_or_end)
222            return TRUE;
223
224        if(constrain_len)
225            return TRUE;
226        else
227            return FALSE;
228    }
229}
230
231static int32_t drm_getRightValue(uint8_t * buffer, int32_t bufferLen,
232                                 T_DRM_Rights * ro, uint8_t * operation,
233                                 uint8_t oper_char)
234{
235    uint8_t *pBuf, *pValue;
236    uint8_t sProperty[256];
237    int32_t valueLen;
238    int32_t year, mon, day, hour, min, sec;
239    T_DRM_Rights_Constraint *pConstraint;
240    int32_t *bIsAble;
241    uint8_t *ret = NULL;
242    int32_t flag = 0;
243
244    if (operation == NULL) {
245        switch (oper_char) {
246        case REL_TAG_PLAY:
247            pConstraint = &(ro->PlayConstraint);
248            bIsAble = &(ro->bIsPlayable);
249            break;
250        case REL_TAG_DISPLAY:
251            pConstraint = &(ro->DisplayConstraint);
252            bIsAble = &(ro->bIsDisplayable);
253            break;
254        case REL_TAG_EXECUTE:
255            pConstraint = &(ro->ExecuteConstraint);
256            bIsAble = &(ro->bIsExecuteable);
257            break;
258        case REL_TAG_PRINT:
259            pConstraint = &(ro->PrintConstraint);
260            bIsAble = &(ro->bIsPrintable);
261            break;
262        default:
263            return FALSE; /* The input parm is err */
264        }
265    } else {
266        if (strcmp((char *)operation, "play") == 0) {
267            pConstraint = &(ro->PlayConstraint);
268            bIsAble = &(ro->bIsPlayable);
269        } else if (strcmp((char *)operation, "display") == 0) {
270            pConstraint = &(ro->DisplayConstraint);
271            bIsAble = &(ro->bIsDisplayable);
272        } else if (strcmp((char *)operation, "execute") == 0) {
273            pConstraint = &(ro->ExecuteConstraint);
274            bIsAble = &(ro->bIsExecuteable);
275        } else if (strcmp((char *)operation, "print") == 0) {
276            pConstraint = &(ro->PrintConstraint);
277            bIsAble = &(ro->bIsPrintable);
278        } else
279            return FALSE; /* The input parm is err */
280    }
281
282    if (operation == NULL) {
283        sprintf((char *)sProperty, "%c%c%c%c", REL_TAG_RIGHTS,
284                     REL_TAG_AGREEMENT, REL_TAG_PERMISSION, oper_char);
285        ret = WBXML_DOM_getNode(buffer, bufferLen, sProperty);
286    } else {
287        sprintf((char *)sProperty,
288                     "o-ex:rights\\o-ex:agreement\\o-ex:permission\\o-dd:%s",
289                     operation);
290        ret = XML_DOM_getNode(buffer, sProperty);
291    }
292    CHECK_VALIDITY(ret);
293    if (NULL == ret)
294        return TRUE;
295    WRITE_RO_FLAG(*bIsAble, 1, pConstraint->Indicator, DRM_NO_CONSTRAINT); /* If exit first assume have utter rights */
296    flag = 1;
297
298    if (operation == NULL) { /* If father element node is not exit then return */
299        sprintf((char *)sProperty, "%c%c%c%c%c", REL_TAG_RIGHTS,
300                     REL_TAG_AGREEMENT, REL_TAG_PERMISSION, oper_char,
301                     REL_TAG_CONSTRAINT);
302        ret = WBXML_DOM_getNode(buffer, bufferLen, sProperty);
303    } else {
304        sprintf((char *)sProperty,
305                     "o-ex:rights\\o-ex:agreement\\o-ex:permission\\o-dd:%s\\o-ex:constraint",
306                     operation);
307        ret = XML_DOM_getNode(buffer, sProperty);
308    }
309
310    CHECK_VALIDITY(ret);
311    if (ret == NULL)
312        return TRUE;
313
314    if(TRUE == drm_checkWhetherHasUnknowConstraint(ret))
315        return FALSE;
316
317    *bIsAble = 0;
318    pConstraint->Indicator = DRM_NO_PERMISSION; /* If exit constraint assume have no rights */
319    flag = 2;
320
321    if (operation == NULL) {
322        sprintf((char *)sProperty, "%c%c%c%c%c%c", REL_TAG_RIGHTS,
323                     REL_TAG_AGREEMENT, REL_TAG_PERMISSION, oper_char,
324                     REL_TAG_CONSTRAINT, REL_TAG_INTERVAL);
325        pBuf =
326            WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
327                                   &valueLen);
328    } else {
329        sprintf((char *)sProperty,
330                     "o-ex:rights\\o-ex:agreement\\o-ex:permission\\o-dd:%s\\o-ex:constraint\\o-dd:interval",
331                     operation);
332        pBuf = XML_DOM_getNodeValue(buffer, sProperty, &pValue, &valueLen);
333    }
334    CHECK_VALIDITY(pBuf);
335    if (pBuf) { /* If interval element exit then get the value */
336        uint8_t pTmp[64] = {0};
337
338        strncpy((char *)pTmp, (char *)pValue, valueLen);
339        {
340            uint8_t * pHead = pTmp + 1;
341            uint8_t * pEnd = NULL;
342            uint8_t tmpChar;
343
344            /** get year */
345            pEnd = (uint8_t *)strstr((char *)pHead, "Y");
346            if(NULL == pEnd)
347                return FALSE;
348            tmpChar = *pEnd;
349            *pEnd = '\0';
350            year = atoi((char *)pHead);
351            pHead = pEnd + 1;
352            *pEnd = tmpChar;
353
354            /** get month */
355            pEnd = (uint8_t *)strstr((char *)pHead, "M");
356            if(NULL == pEnd)
357                return FALSE;
358            tmpChar = *pEnd;
359            *pEnd = '\0';
360            mon = atoi((char *)pHead);
361            pHead = pEnd + 1;
362            *pEnd = tmpChar;
363
364            /** get day */
365            pEnd = (uint8_t *)strstr((char *)pHead, "D");
366            if(NULL == pEnd)
367                return FALSE;
368            tmpChar = *pEnd;
369            *pEnd = '\0';
370            day = atoi((char *)pHead);
371            pHead = pEnd + 2;
372            *pEnd = tmpChar;
373
374            /** get hour */
375            pEnd = (uint8_t *)strstr((char *)pHead, "H");
376            if(NULL == pEnd)
377                return FALSE;
378            tmpChar = *pEnd;
379            *pEnd = '\0';
380            hour = atoi((char *)pHead);
381            pHead = pEnd + 1;
382            *pEnd = tmpChar;
383
384            /** get minute */
385            pEnd = (uint8_t *)strstr((char *)pHead, "M");
386            if(NULL == pEnd)
387                return FALSE;
388            tmpChar = *pEnd;
389            *pEnd = '\0';
390            min = atoi((char *)pHead);
391            pHead = pEnd + 1;
392            *pEnd = tmpChar;
393
394            /** get second */
395            pEnd = (uint8_t *)strstr((char *)pHead, "S");
396            if(NULL == pEnd)
397                return FALSE;
398            tmpChar = *pEnd;
399            *pEnd = '\0';
400            sec = atoi((char *)pHead);
401            pHead = pEnd + 1;
402            *pEnd = tmpChar;
403        }
404
405        if (year < 0 || mon < 0 || day < 0 || hour < 0
406            || min < 0 || sec < 0)
407            return FALSE;
408        YMD_HMS_2_INT(year, mon, day, pConstraint->Interval.date, hour,
409                      min, sec, pConstraint->Interval.time);
410        WRITE_RO_FLAG(*bIsAble, 1, pConstraint->Indicator,
411                      DRM_INTERVAL_CONSTRAINT);
412        flag = 3;
413    }
414
415    if (operation == NULL) {
416        sprintf((char *)sProperty, "%c%c%c%c%c%c", REL_TAG_RIGHTS,
417                     REL_TAG_AGREEMENT, REL_TAG_PERMISSION, oper_char,
418                     REL_TAG_CONSTRAINT, REL_TAG_COUNT);
419        pBuf =
420            WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
421                                   &valueLen);
422    } else {
423        sprintf((char *)sProperty,
424                     "o-ex:rights\\o-ex:agreement\\o-ex:permission\\o-dd:%s\\o-ex:constraint\\o-dd:count",
425                     operation);
426        pBuf = XML_DOM_getNodeValue(buffer, sProperty, &pValue, &valueLen);
427    }
428    CHECK_VALIDITY(pBuf);
429    if (pBuf) { /* If count element exit the  get the value */
430        uint8_t pTmp[16] = {0};
431        int32_t i;
432
433        for (i = 0; i < valueLen; i++) { /* Check the count format */
434            if (0 == isdigit(*(pValue + i)))
435                return FALSE;
436        }
437
438        strncpy((char *)pTmp, (char *)pValue, valueLen);
439        pConstraint->Count = atoi((char *)pTmp);
440
441    if(0 == pConstraint->Count)
442    {
443      WRITE_RO_FLAG(*bIsAble, 0, pConstraint->Indicator, DRM_NO_PERMISSION);
444    }
445    else if( pConstraint->Count > 0)
446    {
447      WRITE_RO_FLAG(*bIsAble, 1, pConstraint->Indicator, DRM_COUNT_CONSTRAINT);
448    }
449    else  /* < 0 */
450    {
451       return FALSE;
452    }
453
454        flag = 3;
455    }
456
457    if (operation == NULL) {
458        sprintf((char *)sProperty, "%c%c%c%c%c%c%c", REL_TAG_RIGHTS,
459                     REL_TAG_AGREEMENT, REL_TAG_PERMISSION, oper_char,
460                     REL_TAG_CONSTRAINT, REL_TAG_DATETIME, REL_TAG_START);
461        pBuf =
462            WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
463                                   &valueLen);
464    } else {
465        sprintf((char *)sProperty,
466                     "o-ex:rights\\o-ex:agreement\\o-ex:permission\\o-dd:%s\\o-ex:constraint\\o-dd:datetime\\o-dd:start",
467                     operation);
468        pBuf = XML_DOM_getNodeValue(buffer, sProperty, &pValue, &valueLen);
469    }
470    CHECK_VALIDITY(pBuf);
471    if (pBuf) { /* If start element exit then get the value */
472        if (FALSE ==
473            drm_getStartEndTime(pValue, valueLen, &pConstraint->StartTime))
474            return FALSE;
475        WRITE_RO_FLAG(*bIsAble, 1, pConstraint->Indicator, DRM_START_TIME_CONSTRAINT);
476        flag = 3;
477    }
478
479    if (operation == NULL) {
480        sprintf((char *)sProperty, "%c%c%c%c%c%c%c", REL_TAG_RIGHTS,
481                     REL_TAG_AGREEMENT, REL_TAG_PERMISSION, oper_char,
482                     REL_TAG_CONSTRAINT, REL_TAG_DATETIME, REL_TAG_END);
483        pBuf =
484            WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
485                                   &valueLen);
486    } else {
487        sprintf((char *)sProperty,
488                     "o-ex:rights\\o-ex:agreement\\o-ex:permission\\o-dd:%s\\o-ex:constraint\\o-dd:datetime\\o-dd:end",
489                     operation);
490        pBuf = XML_DOM_getNodeValue(buffer, sProperty, &pValue, &valueLen);
491    }
492    CHECK_VALIDITY(pBuf);
493    if (pBuf) {
494        if (FALSE ==
495            drm_getStartEndTime(pValue, valueLen, &pConstraint->EndTime))
496            return FALSE;
497        WRITE_RO_FLAG(*bIsAble, 1, pConstraint->Indicator, DRM_END_TIME_CONSTRAINT);
498        flag = 3;
499    }
500
501    if (2 == flag)
502        WRITE_RO_FLAG(*bIsAble, 1, pConstraint->Indicator, DRM_NO_CONSTRAINT); /* If exit first assume have utter rights */
503    return TRUE;
504}
505
506/* See parser_rel.h */
507int32_t drm_relParser(uint8_t* buffer, int32_t bufferLen, int32_t Format, T_DRM_Rights* pRights)
508{
509    uint8_t *pBuf, *pValue;
510    uint8_t sProperty[256];
511    int32_t valueLen;
512
513    if (TYPE_DRM_RIGHTS_WBXML != Format && TYPE_DRM_RIGHTS_XML != Format) /* It is not the support parse format */
514        return FALSE;
515
516    if (TYPE_DRM_RIGHTS_XML == Format) {
517        /* Check whether it is a CD, and parse it using TYPE_DRM_RIGHTS_XML */
518        if (NULL != drm_strnstr(buffer, (uint8_t *)HEADERS_CONTENT_ID, bufferLen))
519            return FALSE;
520
521        pBuf =
522            XML_DOM_getNodeValue(buffer,
523                                 (uint8_t *)"o-ex:rights\\o-ex:context\\o-dd:version",
524                                 &pValue, &valueLen);
525        CHECK_VALIDITY(pBuf);
526
527        if (pBuf) {
528            if (valueLen > 8) /* Check version lenth */
529                return FALSE;
530
531           /* error version */
532           if(strncmp(pValue,"1.0",valueLen))
533                return FALSE;
534
535            strncpy((char *)pRights->Version, (char *)pValue, valueLen);
536        } else
537            return FALSE;
538
539        /* this means there is more than one version label in rights */
540        if(strstr((char*)pBuf, "<o-dd:version>"))
541            return FALSE;
542
543        pBuf =
544            XML_DOM_getNodeValue(buffer,
545                                 (uint8_t *)"o-ex:rights\\o-ex:agreement\\o-ex:asset\\ds:KeyInfo\\ds:KeyValue",
546                                 &pValue, &valueLen);
547        CHECK_VALIDITY(pBuf);
548        if (pBuf) { /* Get keyvalue */
549            int32_t keyLen;
550
551            if (24 != valueLen)
552                return FALSE;
553
554            keyLen = drm_decodeBase64(NULL, 0, pValue, &valueLen);
555            if (keyLen < 0)
556                return FALSE;
557
558            if (DRM_KEY_LEN != drm_decodeBase64(pRights->KeyValue, keyLen, pValue, &valueLen))
559                return FALSE;
560        }
561
562        pBuf =
563            XML_DOM_getNodeValue(buffer,
564                                 (uint8_t *)"o-ex:rights\\o-ex:agreement\\o-ex:asset\\o-ex:context\\o-dd:uid",
565                                 &pValue, &valueLen);
566        CHECK_VALIDITY(pBuf);
567        if (pBuf) {
568            if (valueLen > DRM_UID_LEN)
569                return FALSE;
570            strncpy((char *)pRights->uid, (char *)pValue, valueLen);
571            pRights->uid[valueLen] = '\0';
572        } else
573            return FALSE;
574
575        /* this means there is more than one uid label in rights */
576        if(strstr((char*)pBuf, "<o-dd:uid>"))
577            return FALSE;
578
579        if (FALSE ==
580            drm_getRightValue(buffer, bufferLen, pRights, (uint8_t *)"play", 0))
581            return FALSE;
582
583        if (FALSE ==
584            drm_getRightValue(buffer, bufferLen, pRights, (uint8_t *)"display", 0))
585            return FALSE;
586
587        if (FALSE ==
588            drm_getRightValue(buffer, bufferLen, pRights, (uint8_t *)"execute", 0))
589            return FALSE;
590
591        if (FALSE ==
592            drm_getRightValue(buffer, bufferLen, pRights, (uint8_t *)"print", 0))
593            return FALSE;
594    } else if (TYPE_DRM_RIGHTS_WBXML == Format) {
595        if (!REL_CHECK_WBXML_HEADER(buffer))
596            return FALSE;
597
598        sprintf((char *)sProperty, "%c%c%c", REL_TAG_RIGHTS, REL_TAG_CONTEXT,
599                     REL_TAG_VERSION);
600        pBuf =
601            WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
602                                   &valueLen);
603        CHECK_VALIDITY(pBuf);
604
605        if (pBuf) {
606            if (valueLen > 8) /* Check version lenth */
607                return FALSE;
608            strncpy((char *)pRights->Version, (char *)pValue, valueLen);
609        } else
610            return FALSE;
611
612        sprintf((char *)sProperty, "%c%c%c%c%c",
613                     REL_TAG_RIGHTS, REL_TAG_AGREEMENT, REL_TAG_ASSET,
614                     REL_TAG_KEYINFO, REL_TAG_KEYVALUE);
615        pBuf =
616            WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
617                                   &valueLen);
618        CHECK_VALIDITY(pBuf);
619        if (pBuf) {
620            if (DRM_KEY_LEN != valueLen)
621                return FALSE;
622            memcpy(pRights->KeyValue, pValue, DRM_KEY_LEN);
623            memset(pValue, 0, DRM_KEY_LEN); /* Clean the KeyValue */
624        }
625
626        sprintf((char *)sProperty, "%c%c%c%c%c",
627                     REL_TAG_RIGHTS, REL_TAG_AGREEMENT, REL_TAG_ASSET,
628                     REL_TAG_CONTEXT, REL_TAG_UID);
629        pBuf =
630            WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
631                                   &valueLen);
632        CHECK_VALIDITY(pBuf);
633        if (pBuf) {
634            if (valueLen > DRM_UID_LEN)
635                return FALSE;
636            strncpy((char *)pRights->uid, (char *)pValue, valueLen);
637            pRights->uid[valueLen] = '\0';
638        } else
639            return FALSE;
640
641        if (FALSE ==
642            drm_getRightValue(buffer, bufferLen, pRights, NULL,
643                              REL_TAG_PLAY))
644            return FALSE;
645
646        if (FALSE ==
647            drm_getRightValue(buffer, bufferLen, pRights, NULL,
648                              REL_TAG_DISPLAY))
649            return FALSE;
650
651        if (FALSE ==
652            drm_getRightValue(buffer, bufferLen, pRights, NULL,
653                              REL_TAG_EXECUTE))
654            return FALSE;
655
656        if (FALSE ==
657            drm_getRightValue(buffer, bufferLen, pRights, NULL,
658                              REL_TAG_PRINT))
659            return FALSE;
660    }
661
662    return TRUE;
663}
664