]> git.saurik.com Git - apple/security.git/blobdiff - protocol/SecProtocolTypes.m
Security-58286.200.222.tar.gz
[apple/security.git] / protocol / SecProtocolTypes.m
diff --git a/protocol/SecProtocolTypes.m b/protocol/SecProtocolTypes.m
new file mode 100644 (file)
index 0000000..04666e3
--- /dev/null
@@ -0,0 +1,417 @@
+//
+//  SecProtocolTypes.m
+//  Security
+//
+
+#include "utilities/SecCFRelease.h"
+
+#define OS_OBJECT_HAVE_OBJC_SUPPORT 1
+
+#define SEC_NULL_BAD_INPUT ((void *_Nonnull)NULL)
+#define SEC_NULL_OUT_OF_MEMORY SEC_NULL_BAD_INPUT
+
+#define SEC_NIL_BAD_INPUT ((void *_Nonnull)nil)
+#define SEC_NIL_OUT_OF_MEMORY SEC_NIL_BAD_INPUT
+
+#define SEC_CONCRETE_CLASS_NAME(external_type) SecConcrete_##external_type
+#define SEC_CONCRETE_PREFIX_STR "SecConcrete_"
+
+#define SEC_OBJECT_DECL_INTERNAL_OBJC(external_type)                                                                                                   \
+       @class SEC_CONCRETE_CLASS_NAME(external_type);                                                                                                          \
+       typedef SEC_CONCRETE_CLASS_NAME(external_type) *external_type##_t
+
+#define SEC_OBJECT_IMPL_INTERNAL_OBJC_WITH_PROTOCOL_AND_VISBILITY(external_type, _protocol, visibility, ...)   \
+       @protocol OS_OBJECT_CLASS(external_type) <_protocol>                                                                                                            \
+       @end                                                                                                                                                                                                            \
+       visibility                                                                                                                                                                                                      \
+       @interface SEC_CONCRETE_CLASS_NAME(external_type) : NSObject<OS_OBJECT_CLASS(external_type)>                            \
+               _Pragma("clang diagnostic push")                                                                                                                                        \
+               _Pragma("clang diagnostic ignored \"-Wobjc-interface-ivars\"")                                                                          \
+                       __VA_ARGS__                                                                                                                                                                             \
+               _Pragma("clang diagnostic pop")                                                                                                                                         \
+       @end                                                                                                                                                                                                    \
+       typedef int _useless_typedef_oio_##external_type
+
+#define SEC_OBJECT_IMPL_INTERNAL_OBJC_WITH_PROTOCOL(external_type, _protocol, ...)                                             \
+       SEC_OBJECT_IMPL_INTERNAL_OBJC_WITH_PROTOCOL_AND_VISBILITY(external_type, _protocol, ,__VA_ARGS__)
+
+#define SEC_OBJECT_IMPL_INTERNAL_OBJC(external_type, ...)                                                                                              \
+       SEC_OBJECT_IMPL_INTERNAL_OBJC_WITH_PROTOCOL(external_type, NSObject, ##__VA_ARGS__)
+
+#define SEC_OBJECT_IMPL_INTERNAL_OBJC_WITH_VISIBILITY(external_type, visibility, ...)                                  \
+       SEC_OBJECT_IMPL_INTERNAL_OBJC_WITH_PROTOCOL_AND_VISBILITY(external_type, NSObject, visibility, ##__VA_ARGS__)
+
+#define SEC_OBJECT_IMPL 1
+
+SEC_OBJECT_DECL_INTERNAL_OBJC(sec_array);
+SEC_OBJECT_DECL_INTERNAL_OBJC(sec_identity);
+SEC_OBJECT_DECL_INTERNAL_OBJC(sec_trust);
+SEC_OBJECT_DECL_INTERNAL_OBJC(sec_certificate);
+SEC_OBJECT_DECL_INTERNAL_OBJC(sec_tls_extension);
+SEC_OBJECT_DECL_INTERNAL_OBJC(sec_object);
+SEC_OBJECT_DECL_INTERNAL_OBJC(sec_protocol_options);
+SEC_OBJECT_DECL_INTERNAL_OBJC(sec_protocol_metadata);
+
+#import <Security/SecProtocolPriv.h>
+
+#import <Foundation/Foundation.h>
+#import <CoreFoundation/CoreFoundation.h>
+#import <os/log.h>
+#import <xpc/private.h>
+
+#import <os/object.h>
+
+#ifndef SEC_ANALYZER_HIDE_DEADSTORE
+#  ifdef __clang_analyzer__
+#    define SEC_ANALYZER_HIDE_DEADSTORE(var) do { if (var) {} } while (0)
+#  else // __clang_analyzer__
+#    define SEC_ANALYZER_HIDE_DEADSTORE(var) do {} while (0)
+#  endif // __clang_analyzer__
+#endif // SEC_ANALYZER_HIDE_DEADSTORE
+
+SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_array,
+{
+       xpc_object_t xpc_array;
+});
+
+@implementation SEC_CONCRETE_CLASS_NAME(sec_array)
+
+- (instancetype)init
+{
+       self = [super init];
+       if (self == nil) {
+               return SEC_NIL_OUT_OF_MEMORY;
+       }
+       self->xpc_array = xpc_array_create(NULL, 0);
+       return self;
+}
+
+- (void)dealloc
+{
+       if (self->xpc_array != nil) {
+               xpc_array_apply(self->xpc_array, ^bool(size_t index, __unused xpc_object_t value) {
+                       void *pointer = xpc_array_get_pointer(self->xpc_array, index);
+                       sec_object_t object = (sec_object_t)CFBridgingRelease(pointer);
+                       SEC_ANALYZER_HIDE_DEADSTORE(object);
+                       object = nil;
+                       return true;
+               });
+               self->xpc_array = nil;
+       }
+}
+
+sec_array_t
+sec_array_create(void)
+{
+       return [[SEC_CONCRETE_CLASS_NAME(sec_array) alloc] init];
+}
+
+void
+sec_array_append(sec_array_t array, sec_object_t object)
+{
+       if (array != NULL &&
+               array->xpc_array != NULL && xpc_get_type(array->xpc_array) == XPC_TYPE_ARRAY &&
+               object != NULL) {
+               void *retained_pointer = __DECONST(void *, CFBridgingRetain(object));
+               xpc_array_set_pointer(array->xpc_array, XPC_ARRAY_APPEND, retained_pointer);
+               // 'Leak' the retain, and save the pointer into the array
+       }
+}
+
+size_t
+sec_array_get_count(sec_array_t array)
+{
+       if (array != NULL &&
+               array->xpc_array != NULL && xpc_get_type(array->xpc_array) == XPC_TYPE_ARRAY) {
+               return xpc_array_get_count(array->xpc_array);
+       }
+       return 0;
+}
+
+bool
+sec_array_apply(sec_array_t array, sec_array_applier_t applier)
+{
+       if (array != NULL &&
+               array->xpc_array != NULL && xpc_get_type(array->xpc_array) == XPC_TYPE_ARRAY) {
+               return xpc_array_apply(array->xpc_array, ^bool(size_t index, __unused xpc_object_t value) {
+                       void *pointer = xpc_array_get_pointer(array->xpc_array, index);
+                       return applier(index, (__bridge sec_object_t)(pointer));
+               });
+       }
+       return false;
+}
+
+@end
+
+SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_identity,
+{
+       SecIdentityRef identity;
+    CFArrayRef certs;
+});
+
+@implementation SEC_CONCRETE_CLASS_NAME(sec_identity)
+
+- (instancetype)initWithIdentity:(SecIdentityRef)_identity
+{
+       if (_identity == NULL) {
+               return SEC_NIL_BAD_INPUT;
+       }
+
+       self = [super init];
+       if (self == nil) {
+               return SEC_NIL_OUT_OF_MEMORY;
+       }
+       self->identity = __DECONST(SecIdentityRef, CFRetainSafe(_identity));
+       return self;
+}
+
+- (instancetype)initWithIdentityAndCertificates:(SecIdentityRef)_identity certificates:(CFArrayRef)certificates
+{
+    if (_identity == NULL) {
+        return SEC_NIL_BAD_INPUT;
+    }
+    
+    self = [super init];
+    if (self == nil) {
+        return SEC_NIL_OUT_OF_MEMORY;
+    }
+    self->identity = __DECONST(SecIdentityRef, CFRetainSafe(_identity));
+    self->certs = __DECONST(CFArrayRef, CFRetainSafe(certificates));
+    
+    return self;
+}
+
+- (void)dealloc
+{
+       if (self->identity != NULL) {
+               CFRelease(self->identity);
+               self->identity = NULL;
+        
+        if (self->certs) {
+            CFRelease(self->certs);
+        }
+        self->certs = NULL;
+       }
+}
+
+sec_identity_t
+sec_identity_create(SecIdentityRef identity)
+{
+       return [[SEC_CONCRETE_CLASS_NAME(sec_identity) alloc] initWithIdentity:identity];
+}
+
+sec_identity_t
+sec_identity_create_with_certificates(SecIdentityRef identity, CFArrayRef certificates)
+{
+    return [[SEC_CONCRETE_CLASS_NAME(sec_identity) alloc] initWithIdentityAndCertificates:identity certificates:certificates];
+}
+
+SecIdentityRef
+sec_identity_copy_ref(sec_identity_t object)
+{
+       if (object == NULL) {
+               return SEC_NULL_BAD_INPUT;
+       }
+       if (object->identity != NULL) {
+               return __DECONST(SecIdentityRef, CFRetain(object->identity));
+       }
+       return SEC_NULL_BAD_INPUT;
+}
+
+CFArrayRef
+sec_identity_copy_certificates_ref(sec_identity_t object)
+{
+    if (object == NULL) {
+        return SEC_NULL_BAD_INPUT;
+    }
+    if (object->certs != NULL) {
+        return __DECONST(CFArrayRef, CFRetain(object->certs));
+    }
+    return SEC_NULL_BAD_INPUT;
+}
+
+@end
+
+SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_certificate,
+{
+       SecCertificateRef certificate;
+});
+
+@implementation SEC_CONCRETE_CLASS_NAME(sec_certificate)
+
+- (instancetype)initWithCertificate:(SecCertificateRef)_certificate
+{
+       if (_certificate == NULL) {
+               return SEC_NIL_BAD_INPUT;
+       }
+
+       self = [super init];
+       if (self == nil) {
+               return SEC_NIL_OUT_OF_MEMORY;
+       }
+       self->certificate = __DECONST(SecCertificateRef, CFRetainSafe(_certificate));
+       return self;
+}
+
+- (void)dealloc
+{
+       if (self->certificate != NULL) {
+               CFRelease(self->certificate);
+               self->certificate = NULL;
+       }
+}
+
+sec_certificate_t
+sec_certificate_create(SecCertificateRef certificate)
+{
+       return [[SEC_CONCRETE_CLASS_NAME(sec_certificate) alloc] initWithCertificate:certificate];
+}
+
+SecCertificateRef
+sec_certificate_copy_ref(sec_certificate_t object)
+{
+       if (object == NULL) {
+               return SEC_NULL_BAD_INPUT;
+       }
+       if (object->certificate != NULL) {
+               return __DECONST(SecCertificateRef, CFRetain(object->certificate));
+       }
+       return SEC_NULL_BAD_INPUT;
+}
+
+@end
+
+SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_trust,
+{
+       SecTrustRef trust;
+});
+
+@implementation SEC_CONCRETE_CLASS_NAME(sec_trust)
+
+- (instancetype)initWithTrust:(SecTrustRef)_trust
+{
+       if (_trust == NULL) {
+               return SEC_NIL_BAD_INPUT;
+       }
+
+       self = [super init];
+       if (self == nil) {
+               return SEC_NIL_OUT_OF_MEMORY;
+       }
+       self->trust = __DECONST(SecTrustRef, CFRetainSafe(_trust));
+       return self;
+}
+
+- (void)dealloc
+{
+       if (self->trust != NULL) {
+               CFRelease(self->trust);
+               self->trust = NULL;
+       }
+}
+
+sec_trust_t
+sec_trust_create(SecTrustRef trust)
+{
+       return [[SEC_CONCRETE_CLASS_NAME(sec_trust) alloc] initWithTrust:trust];
+}
+
+SecTrustRef
+sec_trust_copy_ref(sec_trust_t object)
+{
+       if (object == NULL) {
+               return SEC_NULL_BAD_INPUT;
+       }
+       if (object->trust != NULL) {
+               return __DECONST(SecTrustRef, CFRetain(object->trust));
+       }
+       return SEC_NULL_BAD_INPUT;
+}
+
+@end
+
+SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_tls_extension,
+{
+       uint16_t type;
+    sec_protocol_tls_ext_add_callback adder;
+    sec_protocol_tls_ext_parse_callback parser;
+    sec_protocol_tls_ext_free_callback freer;
+});
+
+@implementation SEC_CONCRETE_CLASS_NAME(sec_tls_extension)
+
+- (instancetype)initWithCallbacks:(uint16_t)ext_type
+                            adder:(sec_protocol_tls_ext_add_callback)add_block
+                           parser:(sec_protocol_tls_ext_parse_callback)parse_block
+                            freer:(sec_protocol_tls_ext_free_callback)free_block
+{
+    if (add_block == nil) {
+        return SEC_NIL_BAD_INPUT;
+    }
+    if (parse_block == nil) {
+        return SEC_NIL_BAD_INPUT;
+    }
+    if (free_block == nil) {
+        return SEC_NIL_BAD_INPUT;
+    }
+
+    self = [super init];
+    if (self == nil) {
+        return SEC_NIL_OUT_OF_MEMORY;
+    }
+
+    self->type = ext_type;
+    self->adder = add_block;
+    self->parser = parse_block;
+    self->freer = free_block;
+    return self;
+}
+
+uint16_t
+sec_tls_extension_get_type(sec_tls_extension_t extension)
+{
+       if (extension == NULL) {
+               return 0;
+       }
+
+       return extension->type;
+}
+
+sec_protocol_tls_ext_add_callback
+sec_tls_extension_copy_add_block(sec_tls_extension_t extension)
+{
+       if (extension == NULL) {
+               return SEC_NULL_BAD_INPUT;
+       }
+
+       return extension->adder;
+}
+
+sec_protocol_tls_ext_parse_callback
+sec_tls_extension_copy_parse_block(sec_tls_extension_t extension)
+{
+       if (extension == NULL) {
+               return SEC_NULL_BAD_INPUT;
+       }
+
+       return extension->parser;
+}
+
+sec_protocol_tls_ext_free_callback
+sec_tls_extension_copy_free_block(sec_tls_extension_t extension)
+{
+       if (extension == NULL) {
+               return SEC_NULL_BAD_INPUT;
+       }
+
+       return extension->freer;
+}
+
+sec_tls_extension_t
+sec_tls_extension_create(uint16_t type, sec_protocol_tls_ext_add_callback adder, sec_protocol_tls_ext_parse_callback parser, sec_protocol_tls_ext_free_callback freer)
+{
+    return [[SEC_CONCRETE_CLASS_NAME(sec_tls_extension) alloc] initWithCallbacks:type adder:adder parser:parser freer:freer];
+}
+
+@end
+