SecServerEncryptionSupport.c
1 // 2 // SecServerEncryptionSupport.c 3 // sec 4 // 5 // 6 7 #include <TargetConditionals.h> 8 9 #include <AssertMacros.h> 10 #include <Security/SecServerEncryptionSupport.h> 11 #include <Security/SecECKeyPriv.h> 12 13 #include <utilities/SecCFError.h> 14 #include <utilities/SecCFWrappers.h> 15 16 #include <Security/SecKeyInternal.h> 17 18 #include <Security/SecBasePriv.h> 19 20 #include <corecrypto/ccsha2.h> 21 #include <corecrypto/ccecies.h> 22 #include <corecrypto/ccaes.h> 23 #include <corecrypto/ccder.h> 24 25 // 26 // We assume that SecKey is set up for this to work. 27 // Specifically ccrng_seckey needs to be initialized 28 // 29 // As it happens we work in terms of SecKeys at the 30 // higher level, so we're good. 31 // 32 33 const uint32_t kBlobCipherKeySize = CCAES_KEY_SIZE_128; 34 const uint32_t kBlobMacSize = 16; 35 36 static void InitServerECIES(ccecies_gcm_t ecies, const struct ccmode_gcm *gcm_mode) 37 { 38 ccecies_encrypt_gcm_setup(ecies, 39 ccsha256_di(), 40 ccrng_seckey, 41 gcm_mode, 42 kBlobCipherKeySize, 43 kBlobMacSize, 44 ECIES_EXPORT_PUB_STANDARD 45 +ECIES_EPH_PUBKEY_IN_SHAREDINFO1 46 +ECIES_LEGACY_IV); 47 } 48 49 // 50 // Der Encode 51 // 52 53 // 54 // EncryptedPayloadToServerVersion ::= INTEGER {v1(1)} 55 // 56 // EncryptedPayloadToServer ::= SEQUENCE { 57 // version EncryptedPayloadToServerVersion DEFAULT v1, 58 // ephemeralPublicKey OCTET STRING, 59 // GCMEncryptedData OCTET STRING, 60 // GCMTag OCTET STRING 61 // } 62 63 64 enum { 65 SERVER_BLOB_ENCRYPTED_DATA = 0 66 }; 67 68 static size_t sizeof_implicit_nocopy(ccder_tag implicit_tag, size_t space) 69 { 70 return ccder_sizeof(implicit_tag, space); 71 } 72 73 static uint8_t *encode_implicit_nocopy(ccder_tag implicit_tag, size_t size, uint8_t**start, const uint8_t *der, uint8_t *der_end) 74 { 75 if (start == NULL) 76 return NULL; 77 78 return ccder_encode_tl(implicit_tag, size, der, 79 (*start = ccder_encode_body_nocopy(size, der, der_end))); 80 } 81 82 static uint8_t *encode_octect_string_nocopy(size_t size, uint8_t**start, const uint8_t *der, uint8_t *der_end) 83 { 84 return encode_implicit_nocopy(CCDER_OCTET_STRING, size, start, der, der_end); 85 } 86 87 static size_t sizeof_server_blob(size_t public_key_size, 88 size_t ciphertext_size, 89 size_t verifier_size) 90 { 91 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, 92 sizeof_implicit_nocopy(CCDER_OCTET_STRING, public_key_size) + 93 sizeof_implicit_nocopy(CCDER_OCTET_STRING, ciphertext_size) + 94 sizeof_implicit_nocopy(CCDER_OCTET_STRING, verifier_size)); 95 } 96 97 98 static uint8_t* encode_empty_server_blob_for(size_t public_key_size, uint8_t **public_key_start, 99 size_t ciphertext_size, uint8_t **ciphertext, 100 size_t verifier_size, uint8_t **verifier, 101 const uint8_t *der, uint8_t *der_end) 102 { 103 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, 104 encode_octect_string_nocopy(public_key_size, public_key_start, der, 105 encode_octect_string_nocopy(ciphertext_size, ciphertext, der, 106 encode_octect_string_nocopy(verifier_size, verifier, der, der_end)))); 107 } 108 109 static const uint8_t* decode_octect_string(size_t* size, const uint8_t ** start, const uint8_t *der, const uint8_t* der_end) 110 { 111 if (size == NULL) 112 return NULL; 113 114 der = ccder_decode_tl(CCDER_OCTET_STRING, size, der, der_end); 115 116 if (der && start) { 117 *start = der; 118 der += *size; 119 } 120 121 return der; 122 } 123 124 static const uint8_t* decode_server_blob(size_t *public_key_size, const uint8_t **public_key_start, 125 size_t *ciphertext_size, const uint8_t **ciphertext, 126 size_t *verifier_size, const uint8_t **verifier, 127 CFErrorRef *error, const uint8_t *der, const uint8_t *der_end) 128 { 129 const uint8_t *sequence_end; 130 der = ccder_decode_sequence_tl(&sequence_end, der, der_end); 131 132 if (der_end != sequence_end) 133 der = NULL; 134 135 der = decode_octect_string(public_key_size, public_key_start, der, der_end); 136 der = decode_octect_string(ciphertext_size, ciphertext, der, der_end); 137 der = decode_octect_string(verifier_size, verifier, der, der_end); 138 139 return der; 140 } 141 142 static CFMutableDataRef CreateDataForEncodeEncryptedBlobOf(ccec_pub_ctx_t public_key, 143 size_t public_key_size, uint8_t **public_key_start, 144 size_t ciphertext_size, uint8_t **ciphertext, 145 size_t verifier_size, uint8_t **verifier, 146 CFErrorRef *error) 147 { 148 CFMutableDataRef result = NULL; 149 CFMutableDataRef allocated = CFDataCreateMutableWithScratch(kCFAllocatorDefault, sizeof_server_blob(public_key_size, ciphertext_size, verifier_size)); 150 151 require_action_quiet(allocated, fail, SecError(errSecAllocate, error, CFSTR("failed to create data"))); 152 153 uint8_t *der = CFDataGetMutableBytePtr(allocated); 154 uint8_t *der_end = der + CFDataGetLength(allocated); 155 156 der = encode_empty_server_blob_for(public_key_size, public_key_start, 157 ciphertext_size, ciphertext, 158 verifier_size, verifier, 159 der, der_end); 160 161 require_action_quiet(der, fail, SecError(errSecParam, error, CFSTR("Encoding failed"))); 162 163 CFRetainAssign(result, allocated); 164 165 fail: 166 CFReleaseNull(allocated); 167 return result; 168 } 169 170 static bool ParseAndFindEncryptedData(CFDataRef blob, 171 size_t *public_key_size, const uint8_t **public_key_start, 172 size_t *ciphertext_size, const uint8_t **ciphertext, 173 size_t *verifier_size, const uint8_t **verifier, 174 CFErrorRef *error) 175 { 176 bool success = false; 177 const uint8_t *der = CFDataGetBytePtr(blob); 178 const uint8_t *der_end = der + CFDataGetLength(blob); 179 der = decode_server_blob(public_key_size, public_key_start, 180 ciphertext_size, ciphertext, 181 verifier_size, verifier, 182 error, der, der_end); 183 184 require_action_quiet(der == der_end, fail, SecError(errSecParam, error, CFSTR("Blob failed to decode"))); 185 186 success = true; 187 fail: 188 return success; 189 190 } 191 192 static size_t ccec_x963_pub_export_size(ccec_pub_ctx_t key) 193 { 194 return ccec_x963_export_size(0,key); 195 } 196 197 CFDataRef SecCopyEncryptedToServerKey(SecKeyRef publicKey, CFDataRef dataToEncrypt, CFErrorRef *error) 198 { 199 __block CFDataRef result = NULL; 200 201 202 SecECDoWithPubKey(publicKey, error, ^(ccec_pub_ctx_t public_key) { 203 CFMutableDataRef encrypted = NULL; 204 205 struct ccecies_gcm ecies_encrypt; 206 InitServerECIES(&ecies_encrypt, ccaes_gcm_encrypt_mode()); 207 208 size_t plain_size = CFDataGetLength(dataToEncrypt); 209 size_t encrypted_size = ccecies_encrypt_gcm_ciphertext_size(public_key, &ecies_encrypt, plain_size); 210 211 CFMutableDataRef encryption_temp = CFDataCreateMutableWithScratch(kCFAllocatorDefault, encrypted_size); 212 require_action_quiet(encryption_temp, errout, SecError(errSecAllocate, error, CFSTR("failed to create data"))); 213 214 uint8_t *encryption_buffer = (uint8_t *) CFDataGetMutableBytePtr(encryption_temp); 215 216 int encrypt_result = ccecies_encrypt_gcm(public_key, 217 &ecies_encrypt, 218 plain_size, CFDataGetBytePtr(dataToEncrypt), 219 0, NULL, 220 0, NULL, 221 &encrypted_size, encryption_buffer); 222 223 224 size_t public_key_size = ccec_x963_pub_export_size(public_key); 225 uint8_t *public_key_data = NULL; 226 size_t ciphertext_size = plain_size; 227 uint8_t *ciphertext = NULL; 228 size_t tag_size = kBlobMacSize; 229 uint8_t *tag = NULL; 230 231 require_action_quiet(public_key_size + ciphertext_size + tag_size == encrypted_size, errout, SecError(errSecInternal, error, CFSTR("Allocation mismatch"))); 232 233 encrypted = CreateDataForEncodeEncryptedBlobOf(public_key, 234 public_key_size, &public_key_data, 235 ciphertext_size, &ciphertext, 236 tag_size, &tag, 237 error); 238 require_quiet(encrypted, errout); 239 240 // 241 // Core crypto SPI a work in progress, until then we copy. 242 // 243 244 memcpy(public_key_data, encryption_buffer, public_key_size); 245 memcpy(ciphertext, encryption_buffer + public_key_size, ciphertext_size); 246 memcpy(tag, encryption_buffer + public_key_size + ciphertext_size, tag_size); 247 248 require_action_quiet(encrypt_result == 0, errout, SecError(errSecBadReq, error, CFSTR("ccecies_encrypt_gcm failed %d"), encrypt_result)); 249 250 CFRetainAssign(result, encrypted); 251 errout: 252 CFReleaseSafe(encryption_temp); 253 CFReleaseSafe(encrypted); 254 }); 255 256 257 return result; 258 } 259 260 261 CFDataRef SecCopyDecryptedForServer(SecKeyRef serverFullKey, CFDataRef blob, CFErrorRef* error) 262 { 263 __block CFDataRef result = NULL; 264 265 SecECDoWithFullKey(serverFullKey, error, ^(ccec_full_ctx_t private_key) { 266 CFMutableDataRef plain = NULL; 267 CFMutableDataRef crypto_buffer = NULL; 268 size_t encrypted_size; 269 270 size_t plain_size; 271 272 struct ccecies_gcm ecies_decrypt; 273 InitServerECIES(&ecies_decrypt, ccaes_gcm_decrypt_mode()); 274 size_t public_key_size; 275 const uint8_t *public_key_start = NULL; 276 size_t ciphertext_size; 277 const uint8_t *ciphertext = NULL; 278 size_t verifier_size; 279 const uint8_t *verifier = NULL; 280 281 require_quiet(ParseAndFindEncryptedData(blob, 282 &public_key_size, &public_key_start, 283 &ciphertext_size, &ciphertext, 284 &verifier_size, &verifier, 285 error), errout); 286 287 require_quiet(public_key_start, errout); // Silence analyzer, shouldn't ever happen. 288 require_quiet(ciphertext, errout); // Silence analyzer, shouldn't ever happen. 289 require_quiet(verifier, errout); // Silence analyzer, shouldn't ever happen. 290 291 encrypted_size = public_key_size + ciphertext_size + verifier_size; 292 crypto_buffer = CFDataCreateMutableWithScratch(kCFAllocatorDefault, encrypted_size); 293 require_action_quiet(crypto_buffer, errout, SecError(errSecAllocate, error, CFSTR("failed to create data"))); 294 295 uint8_t *crypto_buffer_ptr = CFDataGetMutableBytePtr(crypto_buffer); 296 memcpy(crypto_buffer_ptr, public_key_start, public_key_size); 297 memcpy(crypto_buffer_ptr + public_key_size, ciphertext, ciphertext_size); 298 memcpy(crypto_buffer_ptr + public_key_size + ciphertext_size, verifier, verifier_size); 299 300 301 plain_size = ccecies_decrypt_gcm_plaintext_size(private_key, &ecies_decrypt, encrypted_size); 302 plain = CFDataCreateMutableWithScratch(kCFAllocatorDefault, plain_size); 303 304 int decrypt_result = ccecies_decrypt_gcm(private_key, 305 &ecies_decrypt, 306 encrypted_size, crypto_buffer_ptr, 307 0, NULL, 308 0, NULL, 309 &plain_size, CFDataGetMutableBytePtr(plain)); 310 311 require_action_quiet(decrypt_result == 0, errout, SecError(errSecBadReq, error, CFSTR("ccecies_decrypt_gcm failed %d"), decrypt_result)); 312 313 CFRetainAssign(result, plain); 314 315 errout: 316 CFReleaseSafe(plain); 317 CFReleaseSafe(crypto_buffer); 318 }); 319 320 return result; 321 } 322 323 #if TARGET_OS_OSX 324 #include <Security/SecTrustInternal.h> 325 #endif 326 327 CFDataRef SecCopyEncryptedToServer(SecTrustRef trustedEvaluation, CFDataRef dataToEncrypt, CFErrorRef *error) 328 { 329 CFDataRef result = NULL; 330 SecKeyRef trustKey = SecTrustCopyKey(trustedEvaluation); 331 332 require_action_quiet(trustKey, fail, 333 SecError(errSecInteractionNotAllowed, error, CFSTR("Failed to get key out of trust ref, was it evaluated?"))); 334 335 336 result = SecCopyEncryptedToServerKey(trustKey, dataToEncrypt, error); 337 338 fail: 339 CFReleaseNull(trustKey); 340 return result; 341 }