Move URL from WebCore to WTF
[WebKit-https.git] / Source / WebKit / Shared / cf / ArgumentCodersCF.cpp
1 /*
2  * Copyright (C) 2010-2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 // FIXME: This is a .cpp but has ObjC in it?
27
28 #include "config.h"
29 #include "ArgumentCodersCF.h"
30
31 #include "DataReference.h"
32 #include "Decoder.h"
33 #include "Encoder.h"
34 #include <wtf/ProcessPrivilege.h>
35 #include <wtf/Vector.h>
36 #include <wtf/cf/CFURLExtras.h>
37 #include <wtf/spi/cocoa/SecuritySPI.h>
38
39 #if USE(FOUNDATION)
40 #import <Foundation/Foundation.h>
41 #endif
42
43 #if USE(APPLE_INTERNAL_SDK)
44 #include <Security/SecIdentityPriv.h>
45 #endif
46
47 extern "C" SecIdentityRef SecIdentityCreate(CFAllocatorRef allocator, SecCertificateRef certificate, SecKeyRef privateKey);
48
49 #if PLATFORM(IOS_FAMILY)
50 #if USE(APPLE_INTERNAL_SDK)
51 #include <Security/SecKeyPriv.h>
52 #endif
53
54 extern "C" OSStatus SecKeyFindWithPersistentRef(CFDataRef persistentRef, SecKeyRef* lookedUpData);
55 #endif
56
57 #if HAVE(SEC_ACCESS_CONTROL)
58 #if USE(APPLE_INTERNAL_SDK)
59 #include <Security/SecAccessControlPriv.h>
60 #endif
61
62 extern "C" SecAccessControlRef SecAccessControlCreateFromData(CFAllocatorRef allocator, CFDataRef data, CFErrorRef *error);
63 extern "C" CFDataRef SecAccessControlCopyData(SecAccessControlRef access_control);
64 #endif
65
66 using namespace WebCore;
67
68 namespace IPC {
69
70 CFTypeRef tokenNullTypeRef()
71 {
72     static CFStringRef tokenNullType = CFSTR("WKNull");
73     return tokenNullType;
74 }
75
76 enum CFType {
77     CFArray,
78     CFBoolean,
79     CFData,
80     CFDate,
81     CFDictionary,
82     CFNull,
83     CFNumber,
84     CFString,
85     CFURL,
86     SecCertificate,
87     SecIdentity,
88 #if HAVE(SEC_KEYCHAIN)
89     SecKeychainItem,
90 #endif
91 #if HAVE(SEC_ACCESS_CONTROL)
92     SecAccessControl,
93 #endif
94 #if HAVE(SEC_TRUST_SERIALIZATION)
95     SecTrust,
96 #endif
97     Null,
98     Unknown,
99 };
100
101 static CFType typeFromCFTypeRef(CFTypeRef type)
102 {
103     ASSERT(type);
104
105     if (type == tokenNullTypeRef())
106         return Null;
107
108     CFTypeID typeID = CFGetTypeID(type);
109     if (typeID == CFArrayGetTypeID())
110         return CFArray;
111     if (typeID == CFBooleanGetTypeID())
112         return CFBoolean;
113     if (typeID == CFDataGetTypeID())
114         return CFData;
115     if (typeID == CFDateGetTypeID())
116         return CFDate;
117     if (typeID == CFDictionaryGetTypeID())
118         return CFDictionary;
119     if (typeID == CFNullGetTypeID())
120         return CFNull;
121     if (typeID == CFNumberGetTypeID())
122         return CFNumber;
123     if (typeID == CFStringGetTypeID())
124         return CFString;
125     if (typeID == CFURLGetTypeID())
126         return CFURL;
127     if (typeID == SecCertificateGetTypeID())
128         return SecCertificate;
129     if (typeID == SecIdentityGetTypeID())
130         return SecIdentity;
131 #if HAVE(SEC_KEYCHAIN)
132     if (typeID == SecKeychainItemGetTypeID())
133         return SecKeychainItem;
134 #endif
135 #if HAVE(SEC_ACCESS_CONTROL)
136     if (typeID == SecAccessControlGetTypeID())
137         return SecAccessControl;
138 #endif
139 #if HAVE(SEC_TRUST_SERIALIZATION)
140     if (typeID == SecTrustGetTypeID())
141         return SecTrust;
142 #endif
143
144     ASSERT_NOT_REACHED();
145     return Unknown;
146 }
147
148 void encode(Encoder& encoder, CFTypeRef typeRef)
149 {
150     CFType type = typeFromCFTypeRef(typeRef);
151     encoder.encodeEnum(type);
152
153     switch (type) {
154     case CFArray:
155         encode(encoder, static_cast<CFArrayRef>(typeRef));
156         return;
157     case CFBoolean:
158         encode(encoder, static_cast<CFBooleanRef>(typeRef));
159         return;
160     case CFData:
161         encode(encoder, static_cast<CFDataRef>(typeRef));
162         return;
163     case CFDate:
164         encode(encoder, static_cast<CFDateRef>(typeRef));
165         return;
166     case CFDictionary:
167         encode(encoder, static_cast<CFDictionaryRef>(typeRef));
168         return;
169     case CFNull:
170         return;
171     case CFNumber:
172         encode(encoder, static_cast<CFNumberRef>(typeRef));
173         return;
174     case CFString:
175         encode(encoder, static_cast<CFStringRef>(typeRef));
176         return;
177     case CFURL:
178         encode(encoder, static_cast<CFURLRef>(typeRef));
179         return;
180     case SecCertificate:
181         encode(encoder, static_cast<SecCertificateRef>(const_cast<void*>(typeRef)));
182         return;
183     case SecIdentity:
184         encode(encoder, static_cast<SecIdentityRef>(const_cast<void*>(typeRef)));
185         return;
186 #if HAVE(SEC_KEYCHAIN)
187     case SecKeychainItem:
188         encode(encoder, static_cast<SecKeychainItemRef>(const_cast<void*>(typeRef)));
189         return;
190 #endif
191 #if HAVE(SEC_ACCESS_CONTROL)
192     case SecAccessControl:
193         encode(encoder, static_cast<SecAccessControlRef>(const_cast<void*>(typeRef)));
194         return;
195 #endif
196 #if HAVE(SEC_TRUST_SERIALIZATION)
197     case SecTrust:
198         encode(encoder, static_cast<SecTrustRef>(const_cast<void*>(typeRef)));
199         return;
200 #endif
201     case Null:
202         return;
203     case Unknown:
204         break;
205     }
206
207     ASSERT_NOT_REACHED();
208 }
209
210 bool decode(Decoder& decoder, RetainPtr<CFTypeRef>& result)
211 {
212     CFType type;
213     if (!decoder.decodeEnum(type))
214         return false;
215
216     switch (type) {
217     case CFArray: {
218         RetainPtr<CFArrayRef> array;
219         if (!decode(decoder, array))
220             return false;
221         result = adoptCF(array.leakRef());
222         return true;
223     }
224     case CFBoolean: {
225         RetainPtr<CFBooleanRef> boolean;
226         if (!decode(decoder, boolean))
227             return false;
228         result = adoptCF(boolean.leakRef());
229         return true;
230     }
231     case CFData: {
232         RetainPtr<CFDataRef> data;
233         if (!decode(decoder, data))
234             return false;
235         result = adoptCF(data.leakRef());
236         return true;
237     }
238     case CFDate: {
239         RetainPtr<CFDateRef> date;
240         if (!decode(decoder, date))
241             return false;
242         result = adoptCF(date.leakRef());
243         return true;
244     }
245     case CFDictionary: {
246         RetainPtr<CFDictionaryRef> dictionary;
247         if (!decode(decoder, dictionary))
248             return false;
249         result = adoptCF(dictionary.leakRef());
250         return true;
251     }
252     case CFNull:
253         result = adoptCF(kCFNull);
254         return true;
255     case CFNumber: {
256         RetainPtr<CFNumberRef> number;
257         if (!decode(decoder, number))
258             return false;
259         result = adoptCF(number.leakRef());
260         return true;
261     }
262     case CFString: {
263         RetainPtr<CFStringRef> string;
264         if (!decode(decoder, string))
265             return false;
266         result = adoptCF(string.leakRef());
267         return true;
268     }
269     case CFURL: {
270         RetainPtr<CFURLRef> url;
271         if (!decode(decoder, url))
272             return false;
273         result = adoptCF(url.leakRef());
274         return true;
275     }
276     case SecCertificate: {
277         RetainPtr<SecCertificateRef> certificate;
278         if (!decode(decoder, certificate))
279             return false;
280         result = adoptCF(certificate.leakRef());
281         return true;
282     }
283     case SecIdentity: {
284         RetainPtr<SecIdentityRef> identity;
285         if (!decode(decoder, identity))
286             return false;
287         result = adoptCF(identity.leakRef());
288         return true;
289     }
290 #if HAVE(SEC_KEYCHAIN)
291     case SecKeychainItem: {
292         RetainPtr<SecKeychainItemRef> keychainItem;
293         if (!decode(decoder, keychainItem))
294             return false;
295         result = adoptCF(keychainItem.leakRef());
296         return true;
297     }
298 #endif
299 #if HAVE(SEC_ACCESS_CONTROL)
300     case SecAccessControl: {
301         RetainPtr<SecAccessControlRef> accessControl;
302         if (!decode(decoder, accessControl))
303             return false;
304         result = adoptCF(accessControl.leakRef());
305         return true;
306     }
307 #endif
308 #if HAVE(SEC_TRUST_SERIALIZATION)
309     case SecTrust: {
310         RetainPtr<SecTrustRef> trust;
311         if (!decode(decoder, trust))
312             return false;
313         result = adoptCF(trust.leakRef());
314         return true;
315     }
316 #endif
317     case Null:
318         result = tokenNullTypeRef();
319         return true;
320     case Unknown:
321         ASSERT_NOT_REACHED();
322         return false;
323     }
324
325     return false;
326 }
327
328 void encode(Encoder& encoder, CFArrayRef array)
329 {
330     CFIndex size = CFArrayGetCount(array);
331     Vector<CFTypeRef, 32> values(size);
332
333     CFArrayGetValues(array, CFRangeMake(0, size), values.data());
334
335     encoder << static_cast<uint64_t>(size);
336
337     for (CFIndex i = 0; i < size; ++i) {
338         ASSERT(values[i]);
339
340         encode(encoder, values[i]);
341     }
342 }
343
344 bool decode(Decoder& decoder, RetainPtr<CFArrayRef>& result)
345 {
346     uint64_t size;
347     if (!decoder.decode(size))
348         return false;
349
350     RetainPtr<CFMutableArrayRef> array = adoptCF(CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks));
351
352     for (size_t i = 0; i < size; ++i) {
353         RetainPtr<CFTypeRef> element;
354         if (!decode(decoder, element))
355             return false;
356
357         CFArrayAppendValue(array.get(), element.get());
358     }
359
360     result = adoptCF(array.leakRef());
361     return true;
362 }
363
364 void encode(Encoder& encoder, CFBooleanRef boolean)
365 {
366     encoder << static_cast<bool>(CFBooleanGetValue(boolean));
367 }
368
369 bool decode(Decoder& decoder, RetainPtr<CFBooleanRef>& result)
370 {
371     bool boolean;
372     if (!decoder.decode(boolean))
373         return false;
374
375     result = adoptCF(boolean ? kCFBooleanTrue : kCFBooleanFalse);
376     return true;
377 }
378
379 void encode(Encoder& encoder, CFDataRef data)
380 {
381     CFIndex length = CFDataGetLength(data);
382     const UInt8* bytePtr = CFDataGetBytePtr(data);
383
384     encoder << IPC::DataReference(bytePtr, length);
385 }
386
387 bool decode(Decoder& decoder, RetainPtr<CFDataRef>& result)
388 {
389     IPC::DataReference dataReference;
390     if (!decoder.decode(dataReference))
391         return false;
392
393     result = adoptCF(CFDataCreate(0, dataReference.data(), dataReference.size()));
394     return true;
395 }
396
397 void encode(Encoder& encoder, CFDateRef date)
398 {
399     encoder << static_cast<double>(CFDateGetAbsoluteTime(date));
400 }
401
402 bool decode(Decoder& decoder, RetainPtr<CFDateRef>& result)
403 {
404     double absoluteTime;
405     if (!decoder.decode(absoluteTime))
406         return false;
407
408     result = adoptCF(CFDateCreate(0, absoluteTime));
409     return true;
410 }
411
412 void encode(Encoder& encoder, CFDictionaryRef dictionary)
413 {
414     if (!dictionary) {
415         encoder << true;
416         return;
417     }
418     encoder << false;
419
420     CFIndex size = CFDictionaryGetCount(dictionary);
421     Vector<CFTypeRef, 32> keys(size);
422     Vector<CFTypeRef, 32> values(size);
423     
424     CFDictionaryGetKeysAndValues(dictionary, keys.data(), values.data());
425
426     encoder << static_cast<uint64_t>(size);
427
428     for (CFIndex i = 0; i < size; ++i) {
429         ASSERT(keys[i]);
430         ASSERT(CFGetTypeID(keys[i]) == CFStringGetTypeID());
431         ASSERT(values[i]);
432
433         // Ignore values we don't recognize.
434         if (typeFromCFTypeRef(values[i]) == Unknown)
435             continue;
436
437         encode(encoder, static_cast<CFStringRef>(keys[i]));
438         encode(encoder, values[i]);
439     }
440 }
441
442 bool decode(Decoder& decoder, RetainPtr<CFDictionaryRef>& result)
443 {
444     bool isNull = false;
445     if (!decoder.decode(isNull))
446         return false;
447     if (isNull) {
448         result = nullptr;
449         return true;
450     }
451
452     uint64_t size;
453     if (!decoder.decode(size))
454         return false;
455
456     RetainPtr<CFMutableDictionaryRef> dictionary = adoptCF(CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
457     for (uint64_t i = 0; i < size; ++i) {
458         // Try to decode the key name.
459         RetainPtr<CFStringRef> key;
460         if (!decode(decoder, key))
461             return false;
462
463         RetainPtr<CFTypeRef> value;
464         if (!decode(decoder, value))
465             return false;
466
467         CFDictionarySetValue(dictionary.get(), key.get(), value.get());
468     }
469
470     result = adoptCF(dictionary.leakRef());
471     return true;
472 }
473
474 void encode(Encoder& encoder, CFNumberRef number)
475 {
476     CFNumberType numberType = CFNumberGetType(number);
477
478     Vector<uint8_t> buffer(CFNumberGetByteSize(number));
479     bool result = CFNumberGetValue(number, numberType, buffer.data());
480     ASSERT_UNUSED(result, result);
481
482     encoder.encodeEnum(numberType);
483     encoder << IPC::DataReference(buffer);
484 }
485
486 static size_t sizeForNumberType(CFNumberType numberType)
487 {
488     switch (numberType) {
489     case kCFNumberSInt8Type:
490         return sizeof(SInt8);
491     case kCFNumberSInt16Type:
492         return sizeof(SInt16);
493     case kCFNumberSInt32Type:
494         return sizeof(SInt32);
495     case kCFNumberSInt64Type:
496         return sizeof(SInt64);
497     case kCFNumberFloat32Type:
498         return sizeof(Float32);
499     case kCFNumberFloat64Type:
500         return sizeof(Float64);
501     case kCFNumberCharType:
502         return sizeof(char);
503     case kCFNumberShortType:
504         return sizeof(short);
505     case kCFNumberIntType:
506         return sizeof(int);
507     case kCFNumberLongType:
508         return sizeof(long);
509     case kCFNumberLongLongType:
510         return sizeof(long long);
511     case kCFNumberFloatType:
512         return sizeof(float);
513     case kCFNumberDoubleType:
514         return sizeof(double);
515     case kCFNumberCFIndexType:
516         return sizeof(CFIndex);
517     case kCFNumberNSIntegerType:
518 #ifdef __LP64__
519         return sizeof(long);
520 #else
521         return sizeof(int);
522 #endif
523     case kCFNumberCGFloatType:
524 #ifdef __LP64__
525         return sizeof(double);
526 #else
527         return sizeof(float);
528 #endif
529     }
530
531     return 0;
532 }
533
534 bool decode(Decoder& decoder, RetainPtr<CFNumberRef>& result)
535 {
536     CFNumberType numberType;
537     if (!decoder.decodeEnum(numberType))
538         return false;
539
540     IPC::DataReference dataReference;
541     if (!decoder.decode(dataReference))
542         return false;
543
544     size_t neededBufferSize = sizeForNumberType(numberType);
545     if (!neededBufferSize || dataReference.size() != neededBufferSize)
546         return false;
547
548     ASSERT(dataReference.data());
549     CFNumberRef number = CFNumberCreate(0, numberType, dataReference.data());
550     result = adoptCF(number);
551
552     return true;
553 }
554
555 void encode(Encoder& encoder, CFStringRef string)
556 {
557     CFIndex length = CFStringGetLength(string);
558     CFStringEncoding encoding = CFStringGetFastestEncoding(string);
559
560     CFRange range = CFRangeMake(0, length);
561     CFIndex bufferLength = 0;
562
563     CFIndex numConvertedBytes = CFStringGetBytes(string, range, encoding, 0, false, 0, 0, &bufferLength);
564     ASSERT(numConvertedBytes == length);
565
566     Vector<UInt8, 128> buffer(bufferLength);
567     numConvertedBytes = CFStringGetBytes(string, range, encoding, 0, false, buffer.data(), buffer.size(), &bufferLength);
568     ASSERT(numConvertedBytes == length);
569
570     encoder.encodeEnum(encoding);
571     encoder << IPC::DataReference(buffer);
572 }
573
574 bool decode(Decoder& decoder, RetainPtr<CFStringRef>& result)
575 {
576     CFStringEncoding encoding;
577     if (!decoder.decodeEnum(encoding))
578         return false;
579
580     if (!CFStringIsEncodingAvailable(encoding))
581         return false;
582     
583     IPC::DataReference dataReference;
584     if (!decoder.decode(dataReference))
585         return false;
586
587     CFStringRef string = CFStringCreateWithBytes(0, dataReference.data(), dataReference.size(), encoding, false);
588     if (!string)
589         return false;
590
591     result = adoptCF(string);
592     return true;
593 }
594
595 void encode(Encoder& encoder, CFURLRef url)
596 {
597     CFURLRef baseURL = CFURLGetBaseURL(url);
598     encoder << static_cast<bool>(baseURL);
599     if (baseURL)
600         encode(encoder, baseURL);
601
602     WTF::URLCharBuffer urlBytes;
603     WTF::getURLBytes(url, urlBytes);
604     IPC::DataReference dataReference(reinterpret_cast<const uint8_t*>(urlBytes.data()), urlBytes.size());
605     encoder << dataReference;
606 }
607
608 bool decode(Decoder& decoder, RetainPtr<CFURLRef>& result)
609 {
610     RetainPtr<CFURLRef> baseURL;
611     bool hasBaseURL;
612     if (!decoder.decode(hasBaseURL))
613         return false;
614     if (hasBaseURL) {
615         if (!decode(decoder, baseURL))
616             return false;
617     }
618
619     IPC::DataReference urlBytes;
620     if (!decoder.decode(urlBytes))
621         return false;
622
623 #if USE(FOUNDATION)
624     // FIXME: Move this to ArgumentCodersCFMac.mm and change this file back to be C++
625     // instead of Objective-C++.
626     if (urlBytes.isEmpty()) {
627         // CFURL can't hold an empty URL, unlike NSURL.
628         // FIXME: This discards base URL, which seems incorrect.
629         result = (__bridge CFURLRef)[NSURL URLWithString:@""];
630         return true;
631     }
632 #endif
633
634     result = WTF::createCFURLFromBuffer(reinterpret_cast<const char*>(urlBytes.data()), urlBytes.size(), baseURL.get());
635     return result;
636 }
637
638 void encode(Encoder& encoder, SecCertificateRef certificate)
639 {
640     RetainPtr<CFDataRef> data = adoptCF(SecCertificateCopyData(certificate));
641     encode(encoder, data.get());
642 }
643
644 bool decode(Decoder& decoder, RetainPtr<SecCertificateRef>& result)
645 {
646     RetainPtr<CFDataRef> data;
647     if (!decode(decoder, data))
648         return false;
649
650     result = adoptCF(SecCertificateCreateWithData(0, data.get()));
651     return true;
652 }
653
654 #if PLATFORM(IOS_FAMILY)
655 static bool secKeyRefDecodingAllowed;
656
657 void setAllowsDecodingSecKeyRef(bool allowsDecodingSecKeyRef)
658 {
659     secKeyRefDecodingAllowed = allowsDecodingSecKeyRef;
660 }
661
662 static CFDataRef copyPersistentRef(SecKeyRef key)
663 {
664     RELEASE_ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessCredentials));
665     // This function differs from SecItemCopyPersistentRef in that it specifies an access group.
666     // This is necessary in case there are multiple copies of the key in the keychain, because we
667     // need a reference to the one that the Networking process will be able to access.
668     CFDataRef persistentRef = nullptr;
669     SecItemCopyMatching((CFDictionaryRef)@{
670         (id)kSecReturnPersistentRef: @YES,
671         (id)kSecValueRef: (id)key,
672         (id)kSecAttrSynchronizable: (id)kSecAttrSynchronizableAny,
673         (id)kSecAttrAccessGroup: @"com.apple.identities",
674     }, (CFTypeRef*)&persistentRef);
675
676     return persistentRef;
677 }
678 #endif
679
680 void encode(Encoder& encoder, SecIdentityRef identity)
681 {
682     SecCertificateRef certificate = nullptr;
683     SecIdentityCopyCertificate(identity, &certificate);
684     encode(encoder, certificate);
685     CFRelease(certificate);
686
687     SecKeyRef key = nullptr;
688     SecIdentityCopyPrivateKey(identity, &key);
689
690     CFDataRef keyData = nullptr;
691 #if PLATFORM(IOS_FAMILY)
692     keyData = copyPersistentRef(key);
693 #endif
694 #if PLATFORM(MAC)
695     RELEASE_ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessCredentials));
696     SecKeychainItemCreatePersistentReference((SecKeychainItemRef)key, &keyData);
697 #endif
698     CFRelease(key);
699
700     encoder << !!keyData;
701     if (keyData) {
702         encode(encoder, keyData);
703         CFRelease(keyData);
704     }
705 }
706
707 bool decode(Decoder& decoder, RetainPtr<SecIdentityRef>& result)
708 {
709 #if PLATFORM(COCOA)
710     RELEASE_ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessCredentials));
711 #endif
712
713     RetainPtr<SecCertificateRef> certificate;
714     if (!decode(decoder, certificate))
715         return false;
716
717     bool hasKey;
718     if (!decoder.decode(hasKey))
719         return false;
720
721     if (!hasKey)
722         return true;
723
724     RetainPtr<CFDataRef> keyData;
725     if (!decode(decoder, keyData))
726         return false;
727
728     SecKeyRef key = nullptr;
729 #if PLATFORM(IOS_FAMILY)
730     if (secKeyRefDecodingAllowed)
731         SecKeyFindWithPersistentRef(keyData.get(), &key);
732 #endif
733 #if PLATFORM(MAC)
734     SecKeychainItemCopyFromPersistentReference(keyData.get(), (SecKeychainItemRef*)&key);
735 #endif
736     if (key) {
737         result = adoptCF(SecIdentityCreate(kCFAllocatorDefault, certificate.get(), key));
738         CFRelease(key);
739     }
740
741     return true;
742 }
743
744 #if HAVE(SEC_KEYCHAIN)
745 void encode(Encoder& encoder, SecKeychainItemRef keychainItem)
746 {
747     RELEASE_ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessCredentials));
748
749     CFDataRef data;
750     if (SecKeychainItemCreatePersistentReference(keychainItem, &data) == errSecSuccess) {
751         encode(encoder, data);
752         CFRelease(data);
753     }
754 }
755
756 bool decode(Decoder& decoder, RetainPtr<SecKeychainItemRef>& result)
757 {
758     RELEASE_ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessCredentials));
759
760     RetainPtr<CFDataRef> data;
761     if (!IPC::decode(decoder, data))
762         return false;
763
764     SecKeychainItemRef item;
765     if (SecKeychainItemCopyFromPersistentReference(data.get(), &item) != errSecSuccess || !item)
766         return false;
767     
768     result = adoptCF(item);
769     return true;
770 }
771 #endif
772
773 #if HAVE(SEC_ACCESS_CONTROL)
774 void encode(Encoder& encoder, SecAccessControlRef accessControl)
775 {
776     RetainPtr<CFDataRef> data = adoptCF(SecAccessControlCopyData(accessControl));
777     if (data)
778         encode(encoder, data.get());
779 }
780
781 bool decode(Decoder& decoder, RetainPtr<SecAccessControlRef>& result)
782 {
783     RetainPtr<CFDataRef> data;
784     if (!decode(decoder, data))
785         return false;
786
787     result = adoptCF(SecAccessControlCreateFromData(kCFAllocatorDefault, data.get(), nullptr));
788     if (!result)
789         return false;
790
791     return true;
792 }
793 #endif
794
795 #if HAVE(SEC_TRUST_SERIALIZATION)
796 void encode(Encoder& encoder, SecTrustRef trust)
797 {
798     auto data = adoptCF(SecTrustSerialize(trust, nullptr));
799     if (!data) {
800         encoder << false;
801         return;
802     }
803
804     encoder << true;
805     IPC::encode(encoder, data.get());
806 }
807
808 bool decode(Decoder& decoder, RetainPtr<SecTrustRef>& result)
809 {
810     bool hasTrust;
811     if (!decoder.decode(hasTrust))
812         return false;
813
814     if (!hasTrust)
815         return true;
816
817     RetainPtr<CFDataRef> trustData;
818     if (!IPC::decode(decoder, trustData))
819         return false;
820
821     auto trust = adoptCF(SecTrustDeserialize(trustData.get(), nullptr));
822     if (!trust)
823         return false;
824
825     result = WTFMove(trust);
826     return true;
827 }
828 #endif
829
830 } // namespace IPC