mirror of
https://github.com/darlinghq/darling-security.git
synced 2024-11-23 12:09:41 +00:00
156 lines
4.8 KiB
Objective-C
156 lines
4.8 KiB
Objective-C
//
|
|
// KCDer.m
|
|
// Security
|
|
//
|
|
//
|
|
|
|
#import <Foundation/Foundation.h>
|
|
|
|
#include <KeychainCircle/KCDer.h>
|
|
#import <KeychainCircle/KCError.h>
|
|
#import <os/overflow.h>
|
|
|
|
// These should probably be shared with security, but we don't export our der'izing functions yet.
|
|
|
|
|
|
static const uint8_t* kcder_decode_data_internal(NSData** data, bool copy,
|
|
NSError**error,
|
|
const uint8_t* der, const uint8_t *der_end)
|
|
{
|
|
if (NULL == der)
|
|
return NULL;
|
|
|
|
size_t payload_size = 0;
|
|
const uint8_t *payload = ccder_decode_tl(CCDER_OCTET_STRING, &payload_size, der, der_end);
|
|
|
|
uintptr_t payload_end_computed = 0;
|
|
if(os_add_overflow((uintptr_t)payload, payload_size, &payload_end_computed)) {
|
|
KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Bad payload size");
|
|
return NULL;
|
|
}
|
|
if (NULL == payload || payload_end_computed > (uintptr_t) der_end) {
|
|
KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Unknown data encoding");
|
|
return NULL;
|
|
}
|
|
|
|
*data = copy ? [NSData dataWithBytes: (void*)payload length: payload_size] :
|
|
[NSData dataWithBytesNoCopy: (void*)payload length:payload_size freeWhenDone:NO];
|
|
|
|
if (NULL == *data) {
|
|
KCJoiningErrorCreate(kAllocationFailure, error, @"Allocation failure!");
|
|
return NULL;
|
|
}
|
|
|
|
return payload + payload_size;
|
|
}
|
|
|
|
|
|
const uint8_t* kcder_decode_data_nocopy(NSData** data,
|
|
NSError**error,
|
|
const uint8_t* der, const uint8_t *der_end)
|
|
{
|
|
return kcder_decode_data_internal(data, NO, error, der, der_end);
|
|
}
|
|
|
|
const uint8_t* kcder_decode_data(NSData** data,
|
|
NSError**error,
|
|
const uint8_t* der, const uint8_t *der_end) {
|
|
return kcder_decode_data_internal(data, YES, error, der, der_end);
|
|
}
|
|
|
|
|
|
size_t kcder_sizeof_data(NSData* data, NSError** error) {
|
|
return ccder_sizeof_raw_octet_string(data.length);
|
|
}
|
|
|
|
uint8_t* kcder_encode_data_optional(NSData* _Nullable data, NSError**error,
|
|
const uint8_t *der, uint8_t *der_end)
|
|
{
|
|
if (data == nil) return der_end;
|
|
|
|
return kcder_encode_data(data, error, der, der_end);
|
|
|
|
}
|
|
|
|
|
|
uint8_t* kcder_encode_data(NSData* data, NSError**error,
|
|
const uint8_t *der, uint8_t *der_end)
|
|
{
|
|
return ccder_encode_tl(CCDER_OCTET_STRING, data.length, der,
|
|
ccder_encode_body(data.length, data.bytes, der, der_end));
|
|
|
|
}
|
|
|
|
|
|
const uint8_t* kcder_decode_string(NSString** string, NSError**error,
|
|
const uint8_t* der, const uint8_t *der_end)
|
|
{
|
|
if (NULL == der)
|
|
return NULL;
|
|
|
|
size_t payload_size = 0;
|
|
const uint8_t *payload = ccder_decode_tl(CCDER_UTF8_STRING, &payload_size, der, der_end);
|
|
|
|
uintptr_t payload_end_computed = 0;
|
|
if(os_add_overflow((uintptr_t)payload, payload_size, &payload_end_computed)) {
|
|
KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Bad payload size");
|
|
return NULL;
|
|
}
|
|
if (NULL == payload || payload_end_computed > (uintptr_t) der_end) {
|
|
KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Unknown string encoding");
|
|
return NULL;
|
|
}
|
|
|
|
*string = [[NSString alloc] initWithBytes:payload length:payload_size encoding:NSUTF8StringEncoding];
|
|
|
|
if (nil == *string) {
|
|
KCJoiningErrorCreate(kAllocationFailure, error, @"Allocation failure!");
|
|
return NULL;
|
|
}
|
|
|
|
return payload + payload_size;
|
|
}
|
|
|
|
|
|
size_t kcder_sizeof_string(NSString* string, NSError** error)
|
|
{
|
|
return ccder_sizeof(CCDER_UTF8_STRING, [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
|
|
}
|
|
|
|
|
|
uint8_t* kcder_encode_string(NSString* string, NSError** error,
|
|
const uint8_t *der, uint8_t *der_end)
|
|
{
|
|
// Obey the NULL allowed rules.
|
|
if (!der_end)
|
|
return NULL;
|
|
|
|
NSUInteger max = (der_end - der);
|
|
void *buffer = der_end - max;
|
|
NSUInteger used = 0;
|
|
if (![string getBytes:buffer
|
|
maxLength:max
|
|
usedLength:&used
|
|
encoding:NSUTF8StringEncoding
|
|
options:0
|
|
range:NSMakeRange(0, string.length)
|
|
remainingRange:nil]) {
|
|
KCJoiningErrorCreate(kDERStringEncodingFailed, error, @"String encoding failed");
|
|
return NULL;
|
|
}
|
|
|
|
return ccder_encode_tl(CCDER_UTF8_STRING, used, der,
|
|
ccder_encode_body(used, buffer, der, der_end));
|
|
|
|
}
|
|
|
|
uint8_t *kcder_encode_raw_octet_space(size_t s_size, uint8_t **location,
|
|
const uint8_t *der, uint8_t *der_end) {
|
|
der_end = ccder_encode_body_nocopy(s_size, der, der_end);
|
|
if (der_end && location)
|
|
*location = der_end;
|
|
|
|
return ccder_encode_tl(CCDER_OCTET_STRING, s_size, der, der_end);
|
|
}
|
|
|