1//
2//  der_plist.c
3//  utilities
4//
5//  Created by Mitch Adler on 7/2/12.
6//  Copyright (c) 2012 Apple Inc. All rights reserved.
7//
8
9#include <stdio.h>
10
11#include "utilities/SecCFRelease.h"
12#include "utilities/der_plist.h"
13#include "utilities/der_plist_internal.h"
14
15#include <corecrypto/ccder.h>
16#include <CoreFoundation/CoreFoundation.h>
17
18//
19// der..CFPropertyList
20//
21// We support:
22//
23//   CFBoolean
24//   CFData
25//   CFDate
26//   CFString
27//   CFNumber
28//   CFNull
29//
30//   CFArray
31//   CFDictionary
32//
33//
34
35const uint8_t* der_decode_plist(CFAllocatorRef allocator, CFOptionFlags mutability,
36                                CFPropertyListRef* pl, CFErrorRef *error,
37                                const uint8_t* der, const uint8_t *der_end)
38{    if (NULL == der)
39    return NULL;
40
41    ccder_tag tag;
42    if (NULL == ccder_decode_tag(&tag, der, der_end))
43        return NULL;
44
45    switch (tag) {
46		case CCDER_NULL:
47			return der_decode_null(allocator, mutability, (CFNullRef*)pl, error, der, der_end);
48        case CCDER_BOOLEAN:
49            return der_decode_boolean(allocator, mutability, (CFBooleanRef*)pl, error, der, der_end);
50        case CCDER_OCTET_STRING:
51            return der_decode_data(allocator, mutability, (CFDataRef*)pl, error, der, der_end);
52        case CCDER_GENERALIZED_TIME:
53            return der_decode_date(allocator, mutability, (CFDateRef*)pl, error, der, der_end);
54        case CCDER_CONSTRUCTED_SEQUENCE:
55            return der_decode_array(allocator, mutability, (CFArrayRef*)pl, error, der, der_end);
56        case CCDER_UTF8_STRING:
57            return der_decode_string(allocator, mutability, (CFStringRef*)pl, error, der, der_end);
58        case CCDER_INTEGER:
59            return der_decode_number(allocator, mutability, (CFNumberRef*)pl, error, der, der_end);
60        case CCDER_CONSTRUCTED_SET:
61            return der_decode_dictionary(allocator, mutability, (CFDictionaryRef*)pl, error, der, der_end);
62        default:
63            SecCFDERCreateError(kSecDERErrorUnsupportedDERType, CFSTR("Unsupported DER Type"), NULL, error);
64            return NULL;
65    }
66}
67
68
69size_t der_sizeof_plist(CFPropertyListRef pl, CFErrorRef *error)
70{
71    if (!pl) {
72        SecCFDERCreateError(kSecDERErrorUnsupportedCFObject, CFSTR("Null CFType"), NULL, error);
73        return 0;
74    }
75
76    CFTypeID  dataType = CFGetTypeID(pl);
77
78    if (CFArrayGetTypeID() == dataType)
79        return der_sizeof_array((CFArrayRef) pl, error);
80    else if (CFBooleanGetTypeID() == dataType)
81        return der_sizeof_boolean((CFBooleanRef) pl, error);
82    else if (CFDataGetTypeID() == dataType)
83        return der_sizeof_data((CFDataRef) pl, error);
84    else if (CFDateGetTypeID() == dataType)
85        return der_sizeof_date((CFDateRef) pl, error);
86    else if (CFDictionaryGetTypeID() == dataType)
87        return der_sizeof_dictionary((CFDictionaryRef) pl, error);
88    else if (CFStringGetTypeID() == dataType)
89        return der_sizeof_string((CFStringRef) pl, error);
90    else if (CFNumberGetTypeID() == dataType)
91        return der_sizeof_number((CFNumberRef) pl, error);
92	if (CFNullGetTypeID() == dataType)
93		return der_sizeof_null((CFNullRef) pl, error);
94	else {
95        SecCFDERCreateError(kSecDERErrorUnsupportedCFObject, CFSTR("Unsupported CFType"), NULL, error);
96        return 0;
97    }
98}
99
100
101uint8_t* der_encode_plist(CFPropertyListRef pl, CFErrorRef *error,
102                          const uint8_t *der, uint8_t *der_end)
103{
104    if (!pl) {
105        SecCFDERCreateError(kSecDERErrorUnsupportedCFObject, CFSTR("Null CFType"), NULL, error);
106        return NULL;
107    }
108
109    CFTypeID  dataType = CFGetTypeID(pl);
110
111    if (CFArrayGetTypeID() == dataType)
112        return der_encode_array((CFArrayRef) pl, error, der, der_end);
113    else if (CFBooleanGetTypeID() == dataType)
114        return der_encode_boolean((CFBooleanRef) pl, error, der, der_end);
115    else if (CFDataGetTypeID() == dataType)
116        return der_encode_data((CFDataRef) pl, error, der, der_end);
117    else if (CFDateGetTypeID() == dataType)
118        return der_encode_date((CFDateRef) pl, error, der, der_end);
119    else if (CFDictionaryGetTypeID() == dataType)
120        return der_encode_dictionary((CFDictionaryRef) pl, error, der, der_end);
121    else if (CFStringGetTypeID() == dataType)
122        return der_encode_string((CFStringRef) pl, error, der, der_end);
123    else if (CFNumberGetTypeID() == dataType)
124        return der_encode_number((CFNumberRef) pl, error, der, der_end);
125	else if (CFNullGetTypeID() == dataType)
126		return der_encode_null((CFNullRef) pl, error, der, der_end);
127    else {
128        SecCFDERCreateError(kSecDERErrorUnsupportedCFObject, CFSTR("Unsupported CFType"), NULL, error);
129        return NULL;
130    }
131}
132