1 /* 2 * Copyright (c) 2021-2024 Apple Inc. All rights reserved. 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 * https://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 * This file contains function declarations for tls-keychain.c, which deals 17 * with TLS certificate fetching and evaluation. 18 */ 19 20 #ifndef __TLS_KEYCHAIN_H__ 21 #define __TLS_KEYCHAIN_H__ 22 23 #if __APPLE__ 24 #include <Security/Security.h> 25 #endif 26 27 //====================================================================================================================== 28 // MARK: - Macros 29 30 #define SRP_APPLICATION_IDENTIFIER "com.apple.srp-mdns-proxy" // Application identifier for srp-mdns-proxy 31 #define DNSSD_PROXY_APPLICATION_IDENTIFIER "com.apple.dnssd-proxy" // Application identifier for dnssd-proxy 32 #define KEYCHAIN_ACCESS_GROUP SRP_APPLICATION_IDENTIFIER // Keychain access group of dnssd-proxy and mDNSResponder 33 #define DNSSD_PROXY_IDENTITY_NAME SRP_APPLICATION_IDENTIFIER " identity" // The identity name used by dnssd-proxy 34 #define KEY_ATTRIBUTE_LABEL_PREFIX "Key " // User-visible string put into the attribute label of the private key 35 #define CERTIFICATE_ATTRIBUTE_LABEL_PREFIX "Certificate " // User-visible string put into the attribute label of the certificate 36 37 // The TLS certificate in the keychain will be updated every two weeks(1209600s). 38 #define TLS_CERTIFICATE_VALID_PERIOD_SECS 1209600 39 // The TLS certificate that has been created for more than four weeks(2419200s) will be deleted from iCloud keychain no 40 // matter who creates it. 41 #define TLS_CERTIFICATE_EXISTENCE_PERIOD_SECS (TLS_CERTIFICATE_VALID_PERIOD_SECS * 2) 42 43 //====================================================================================================================== 44 // MARK: - Structures 45 46 // Context set in sec_protocol_options_set_verify_block() when trying to setup TLS connection with the server. 47 typedef struct tls_keychain_context_t tls_keychain_context_t; 48 struct tls_keychain_context_t { 49 #if __APPLE__ 50 sec_protocol_metadata_t _Nonnull metadata; 51 sec_trust_t _Nonnull trust_ref; 52 bool trusts_alternative_server_certificates; 53 #else // __APPLE__ 54 uint8_t not_a_real_member; 55 #endif // __APPLE__ 56 }; 57 58 //====================================================================================================================== 59 // MARK: - Functions 60 61 /*! 62 * @brief 63 * Get the TLS certificate from the iCloud keychain. 64 * 65 * @result 66 * True if the operation succeeds, otherwise, false. 67 */ 68 bool 69 tls_cert_init(void); 70 71 /*! 72 * @brief 73 * Specify alternative trusted TLS certificates that can be used to perform trust evaluation. 74 * 75 * @param certs 76 * An array of TLS certificates as CFDataRef objects. 77 * 78 * @result 79 * kNoErr if the trusted server certificates were successfully updated. Otherwise, a non-zero error code to indicate why 80 * the operation failed. 81 * 82 * @discussion 83 * Calling this function for the second time after the first call overrides the previously configured certificates. 84 * Calling this function with NULL clears any alternative certificate that we have trusted before. 85 */ 86 OSStatus 87 tls_cert_set_alternative_trusted_certificates(CFArrayRef _Nullable certs); 88 89 /*! 90 * @brief 91 * Given the context, verify if the current TLS certificate should be trusted or not. 92 * 93 * @param context 94 * Variables that are required to finish the TLS certificate evaluation. 95 * 96 * @result 97 * True if it is trusted, false if not. 98 */ 99 bool 100 tls_cert_evaluate(const tls_keychain_context_t * _Nonnull context); 101 102 /*! 103 * @brief 104 * Release the TLS certificate get from iCloud keychain. 105 * 106 * @discussion 107 * If the certificate has been fetched from iCloud keychain, it will be released. If not, nothing will happen. 108 */ 109 void 110 tls_cert_dispose(void); 111 112 #ifdef __APPLE__ 113 114 /*! 115 * @brief 116 * Add the identity into keychain. 117 * 118 * @param identity 119 * A SecIdentityRef that contains a pair of SecKeyRef private key and SecCertificateRef certificate. 120 * 121 * @param uuid 122 * An UUID that will be used to set three properties of the SecIdentityRef containing a pair of SecKeyRef and SecCertificateRef: 123 * 1. UUID is used to set SecKeyRef's attribute label: "Key <UUID>". 124 * 2. UUID is used to set SecCertificate's attribute label: "Certificate <UUID>". 125 * 3. UUID is used to set the common name property in the subjects of SecCertificateRef: "<App Identifier> <UUID>". 126 * All the properties set above are used to match the specific SecItem when manipulating them. 127 * 128 * @result 129 * errSecSuccess if the identity is added into keychain successfully, otherwise, an error code to indicate the error. 130 * 131 * @discussion 132 * When an identity is added into keychain, the private key part of the identity will remain locally, and it will not be synced to iCloud keychain. 133 * The certificate part of the identity will be synced to iCloud keychain. 134 */ 135 OSStatus 136 keychain_identity_add(const SecIdentityRef _Nonnull identity, const CFStringRef _Nonnull uuid); 137 138 /*! 139 * @brief 140 * Retrieve the identity added by <code>keychain_identity_add()</code> on the same device. 141 * 142 * @param out_identity 143 * A pointer to a SecIdentityRef variable that can be used to return the retrieved identity. 144 * 145 * @param out_identity_creation_time 146 * A pointer to a CFAbsoluteTime variable that can be used to return the creation time of the identity. 147 * 148 * @result 149 * errSecSuccess if the identity is found, errSecItemNotFound if the identity is not found, otherwise, an error code to indicate the error. 150 * 151 * @discussion 152 * Note that the identity being returned here is the one that gets added by <code>keychain_identity_add()</code> on the same device. 153 * Which means the identity can only be returned to its creator by this function. 154 */ 155 OSStatus 156 keychain_identity_copy(CF_RETURNS_RETAINED SecIdentityRef * _Nonnull out_identity, 157 CFAbsoluteTime * _Nonnull out_identity_creation_time); 158 159 /*! 160 * @brief 161 * Remove the identity added by <code>keychain_identity_add()</code> on the same device. 162 * 163 * @result 164 * errSecSuccess if the identity is removed from keychain, errSecItemNotFound if the identity is not found. Otherwise, an error code to indicate the error. 165 * 166 * @discussion 167 * Here the identity is said to be removed from keychain if: 168 * 1. The private key of the identity is removed from the local keychain. 169 * 2. The certificate of the identity is removed from the iCloud keychain. 170 */ 171 OSStatus 172 keychain_identity_remove(void); 173 174 /*! 175 * @brief 176 * Retrieve all the certificates from iCloud keychain that are added by <code>keychain_identity_add()</code>. 177 * 178 * @param out_certificates 179 * A pointer to a CFArrayRef variable that can be used to return the retrieved SecCertificateRef array. 180 * 181 * @result 182 * errSecSuccess if the certificates on the iCloud keychain are found, errSecItemNotFound if the certificates are not found, otherwise an error code to indicate 183 * the error. 184 */ 185 OSStatus 186 keychain_certificates_copy(CF_RETURNS_RETAINED CFArrayRef * const _Nonnull out_certificates); 187 188 /*! 189 * @brief 190 * Removes all the certificates that are more than TLS_CERTIFICATE_EXISTENCE_PERIOD_SECS seconds old. 191 * 192 * @result 193 * errSecSuccess if there is any expired certificate that has been removed from keychain, errSecItemNotFound if the identity is not found. Otherwise, an error 194 * code to indicate the error. 195 */ 196 OSStatus 197 keychain_certificates_remove_expired(void); 198 199 #endif // __APPLE__ 200 201 #endif // __TLS_KEYCHAIN_H__ 202