7 #import <Foundation/Foundation.h>
9 #include <KeychainCircle/KCDer.h>
10 #import <KeychainCircle/KCError.h>
11 #import <os/overflow.h>
13 // These should probably be shared with security, but we don't export our der'izing functions yet.
16 static const uint8_t* kcder_decode_data_internal(NSData** data, bool copy,
18 const uint8_t* der, const uint8_t *der_end)
23 size_t payload_size = 0;
24 const uint8_t *payload = ccder_decode_tl(CCDER_OCTET_STRING, &payload_size, der, der_end);
26 uintptr_t payload_end_computed = 0;
27 if(os_add_overflow((uintptr_t)payload, payload_size, &payload_end_computed)) {
28 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Bad payload size");
31 if (NULL == payload || payload_end_computed > (uintptr_t) der_end) {
32 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Unknown data encoding");
36 *data = copy ? [NSData dataWithBytes: (void*)payload length: payload_size] :
37 [NSData dataWithBytesNoCopy: (void*)payload length:payload_size freeWhenDone:NO];
40 KCJoiningErrorCreate(kAllocationFailure, error, @"Allocation failure!");
44 return payload + payload_size;
48 const uint8_t* kcder_decode_data_nocopy(NSData** data,
50 const uint8_t* der, const uint8_t *der_end)
52 return kcder_decode_data_internal(data, NO, error, der, der_end);
55 const uint8_t* kcder_decode_data(NSData** data,
57 const uint8_t* der, const uint8_t *der_end) {
58 return kcder_decode_data_internal(data, YES, error, der, der_end);
62 size_t kcder_sizeof_data(NSData* data, NSError** error) {
63 return ccder_sizeof_raw_octet_string(data.length);
66 uint8_t* kcder_encode_data_optional(NSData* _Nullable data, NSError**error,
67 const uint8_t *der, uint8_t *der_end)
69 if (data == nil) return der_end;
71 return kcder_encode_data(data, error, der, der_end);
76 uint8_t* kcder_encode_data(NSData* data, NSError**error,
77 const uint8_t *der, uint8_t *der_end)
79 return ccder_encode_tl(CCDER_OCTET_STRING, data.length, der,
80 ccder_encode_body(data.length, data.bytes, der, der_end));
85 const uint8_t* kcder_decode_string(NSString** string, NSError**error,
86 const uint8_t* der, const uint8_t *der_end)
91 size_t payload_size = 0;
92 const uint8_t *payload = ccder_decode_tl(CCDER_UTF8_STRING, &payload_size, der, der_end);
94 uintptr_t payload_end_computed = 0;
95 if(os_add_overflow((uintptr_t)payload, payload_size, &payload_end_computed)) {
96 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Bad payload size");
99 if (NULL == payload || payload_end_computed > (uintptr_t) der_end) {
100 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Unknown string encoding");
104 *string = [[NSString alloc] initWithBytes:payload length:payload_size encoding:NSUTF8StringEncoding];
106 if (nil == *string) {
107 KCJoiningErrorCreate(kAllocationFailure, error, @"Allocation failure!");
111 return payload + payload_size;
115 size_t kcder_sizeof_string(NSString* string, NSError** error)
117 return ccder_sizeof(CCDER_UTF8_STRING, [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
121 uint8_t* kcder_encode_string(NSString* string, NSError** error,
122 const uint8_t *der, uint8_t *der_end)
124 // Obey the NULL allowed rules.
128 NSUInteger max = (der_end - der);
129 void *buffer = der_end - max;
131 if (![string getBytes:buffer
134 encoding:NSUTF8StringEncoding
136 range:NSMakeRange(0, string.length)
137 remainingRange:nil]) {
138 KCJoiningErrorCreate(kDERStringEncodingFailed, error, @"String encoding failed");
142 return ccder_encode_tl(CCDER_UTF8_STRING, used, der,
143 ccder_encode_body(used, buffer, der, der_end));
147 uint8_t *kcder_encode_raw_octet_space(size_t s_size, uint8_t **location,
148 const uint8_t *der, uint8_t *der_end) {
149 der_end = ccder_encode_body_nocopy(s_size, der, der_end);
150 if (der_end && location)
153 return ccder_encode_tl(CCDER_OCTET_STRING, s_size, der, der_end);