90afb5b611f3f28e88ba6909202d83933feb9c5a
[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 <WebCore/CFURLExtras.h>
35 #include <wtf/ProcessPrivilege.h>
36 #include <wtf/Vector.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)
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(values[i]);
431
432         // Ignore values we don't recognize.
433         if (typeFromCFTypeRef(values[i]) == Unknown)
434             continue;
435
436         encode(encoder, keys[i]);
437         encode(encoder, values[i]);
438     }
439 }
440
441 bool decode(Decoder& decoder, RetainPtr<CFDictionaryRef>& result)
442 {
443     bool isNull = false;
444     if (!decoder.decode(isNull))
445         return false;
446     if (isNull) {
447         result = nullptr;
448         return true;
449     }
450
451     uint64_t size;
452     if (!decoder.decode(size))
453         return false;
454
455     RetainPtr<CFMutableDictionaryRef> dictionary = adoptCF(CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
456     for (uint64_t i = 0; i < size; ++i) {
457         // Try to decode the key name.
458         RetainPtr<CFTypeRef> key;
459         if (!decode(decoder, key))
460             return false;
461
462         RetainPtr<CFTypeRef> value;
463         if (!decode(decoder, value))
464             return false;
465
466         CFDictionarySetValue(dictionary.get(), key.get(), value.get());
467     }
468
469     result = adoptCF(dictionary.leakRef());
470     return true;
471 }
472
473 void encode(Encoder& encoder, CFNumberRef number)
474 {
475     CFNumberType numberType = CFNumberGetType(number);
476
477     Vector<uint8_t> buffer(CFNumberGetByteSize(number));
478     bool result = CFNumberGetValue(number, numberType, buffer.data());
479     ASSERT_UNUSED(result, result);
480
481     encoder.encodeEnum(numberType);
482     encoder << IPC::DataReference(buffer);
483 }
484
485 static size_t sizeForNumberType(CFNumberType numberType)
486 {
487     switch (numberType) {
488     case kCFNumberSInt8Type:
489         return sizeof(SInt8);
490     case kCFNumberSInt16Type:
491         return sizeof(SInt16);
492     case kCFNumberSInt32Type:
493         return sizeof(SInt32);
494     case kCFNumberSInt64Type:
495         return sizeof(SInt64);
496     case kCFNumberFloat32Type:
497         return sizeof(Float32);
498     case kCFNumberFloat64Type:
499         return sizeof(Float64);
500     case kCFNumberCharType:
501         return sizeof(char);
502     case kCFNumberShortType:
503         return sizeof(short);
504     case kCFNumberIntType:
505         return sizeof(int);
506     case kCFNumberLongType:
507         return sizeof(long);
508     case kCFNumberLongLongType:
509         return sizeof(long long);
510     case kCFNumberFloatType:
511         return sizeof(float);
512     case kCFNumberDoubleType:
513         return sizeof(double);
514     case kCFNumberCFIndexType:
515         return sizeof(CFIndex);
516     case kCFNumberNSIntegerType:
517 #ifdef __LP64__
518         return sizeof(long);
519 #else
520         return sizeof(int);
521 #endif
522     case kCFNumberCGFloatType:
523 #ifdef __LP64__
524         return sizeof(double);
525 #else
526         return sizeof(float);
527 #endif
528     }
529
530     return 0;
531 }
532
533 bool decode(Decoder& decoder, RetainPtr<CFNumberRef>& result)
534 {
535     CFNumberType numberType;
536     if (!decoder.decodeEnum(numberType))
537         return false;
538
539     IPC::DataReference dataReference;
540     if (!decoder.decode(dataReference))
541         return false;
542
543     size_t neededBufferSize = sizeForNumberType(numberType);
544     if (!neededBufferSize || dataReference.size() != neededBufferSize)
545         return false;
546
547     ASSERT(dataReference.data());
548     CFNumberRef number = CFNumberCreate(0, numberType, dataReference.data());
549     result = adoptCF(number);
550
551     return true;
552 }
553
554 void encode(Encoder& encoder, CFStringRef string)
555 {
556     CFIndex length = CFStringGetLength(string);
557     CFStringEncoding encoding = CFStringGetFastestEncoding(string);
558
559     CFRange range = CFRangeMake(0, length);
560     CFIndex bufferLength = 0;
561
562     CFIndex numConvertedBytes = CFStringGetBytes(string, range, encoding, 0, false, 0, 0, &bufferLength);
563     ASSERT(numConvertedBytes == length);
564
565     Vector<UInt8, 128> buffer(bufferLength);
566     numConvertedBytes = CFStringGetBytes(string, range, encoding, 0, false, buffer.data(), buffer.size(), &bufferLength);
567     ASSERT(numConvertedBytes == length);
568
569     encoder.encodeEnum(encoding);
570     encoder << IPC::DataReference(buffer);
571 }
572
573 bool decode(Decoder& decoder, RetainPtr<CFStringRef>& result)
574 {
575     CFStringEncoding encoding;
576     if (!decoder.decodeEnum(encoding))
577         return false;
578
579     if (!CFStringIsEncodingAvailable(encoding))
580         return false;
581     
582     IPC::DataReference dataReference;
583     if (!decoder.decode(dataReference))
584         return false;
585
586     CFStringRef string = CFStringCreateWithBytes(0, dataReference.data(), dataReference.size(), encoding, false);
587     if (!string)
588         return false;
589
590     result = adoptCF(string);
591     return true;
592 }
593
594 void encode(Encoder& encoder, CFURLRef url)
595 {
596     CFURLRef baseURL = CFURLGetBaseURL(url);
597     encoder << static_cast<bool>(baseURL);
598     if (baseURL)
599         encode(encoder, baseURL);
600
601     URLCharBuffer urlBytes;
602     getURLBytes(url, urlBytes);
603     IPC::DataReference dataReference(reinterpret_cast<const uint8_t*>(urlBytes.data()), urlBytes.size());
604     encoder << dataReference;
605 }
606
607 bool decode(Decoder& decoder, RetainPtr<CFURLRef>& result)
608 {
609     RetainPtr<CFURLRef> baseURL;
610     bool hasBaseURL;
611     if (!decoder.decode(hasBaseURL))
612         return false;
613     if (hasBaseURL) {
614         if (!decode(decoder, baseURL))
615             return false;
616     }
617
618     IPC::DataReference urlBytes;
619     if (!decoder.decode(urlBytes))
620         return false;
621
622 #if USE(FOUNDATION)
623     // FIXME: Move this to ArgumentCodersCFMac.mm and change this file back to be C++
624     // instead of Objective-C++.
625     if (urlBytes.isEmpty()) {
626         // CFURL can't hold an empty URL, unlike NSURL.
627         // FIXME: This discards base URL, which seems incorrect.
628         result = (__bridge CFURLRef)[NSURL URLWithString:@""];
629         return true;
630     }
631 #endif
632
633     result = createCFURLFromBuffer(reinterpret_cast<const char*>(urlBytes.data()), urlBytes.size(), baseURL.get());
634     return result;
635 }
636
637 void encode(Encoder& encoder, SecCertificateRef certificate)
638 {
639     RetainPtr<CFDataRef> data = adoptCF(SecCertificateCopyData(certificate));
640     encode(encoder, data.get());
641 }
642
643 bool decode(Decoder& decoder, RetainPtr<SecCertificateRef>& result)
644 {
645     RetainPtr<CFDataRef> data;
646     if (!decode(decoder, data))
647         return false;
648
649     result = adoptCF(SecCertificateCreateWithData(0, data.get()));
650     return true;
651 }
652
653 #if PLATFORM(IOS)
654 static bool secKeyRefDecodingAllowed;
655
656 void setAllowsDecodingSecKeyRef(bool allowsDecodingSecKeyRef)
657 {
658     secKeyRefDecodingAllowed = allowsDecodingSecKeyRef;
659 }
660
661 static CFDataRef copyPersistentRef(SecKeyRef key)
662 {
663     RELEASE_ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessCredentials));
664     // This function differs from SecItemCopyPersistentRef in that it specifies an access group.
665     // This is necessary in case there are multiple copies of the key in the keychain, because we
666     // need a reference to the one that the Networking process will be able to access.
667     CFDataRef persistentRef = nullptr;
668     SecItemCopyMatching((CFDictionaryRef)@{
669         (id)kSecReturnPersistentRef: @YES,
670         (id)kSecValueRef: (id)key,
671         (id)kSecAttrSynchronizable: (id)kSecAttrSynchronizableAny,
672         (id)kSecAttrAccessGroup: @"com.apple.identities",
673     }, (CFTypeRef*)&persistentRef);
674
675     return persistentRef;
676 }
677 #endif
678
679 void encode(Encoder& encoder, SecIdentityRef identity)
680 {
681     SecCertificateRef certificate = nullptr;
682     SecIdentityCopyCertificate(identity, &certificate);
683     encode(encoder, certificate);
684     CFRelease(certificate);
685
686     SecKeyRef key = nullptr;
687     SecIdentityCopyPrivateKey(identity, &key);
688
689     CFDataRef keyData = nullptr;
690 #if PLATFORM(IOS)
691     keyData = copyPersistentRef(key);
692 #endif
693 #if PLATFORM(MAC)
694     RELEASE_ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessCredentials));
695     SecKeychainItemCreatePersistentReference((SecKeychainItemRef)key, &keyData);
696 #endif
697     CFRelease(key);
698
699     encoder << !!keyData;
700     if (keyData) {
701         encode(encoder, keyData);
702         CFRelease(keyData);
703     }
704 }
705
706 bool decode(Decoder& decoder, RetainPtr<SecIdentityRef>& result)
707 {
708 #if PLATFORM(COCOA)
709     RELEASE_ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessCredentials));
710 #endif
711
712     RetainPtr<SecCertificateRef> certificate;
713     if (!decode(decoder, certificate))
714         return false;
715
716     bool hasKey;
717     if (!decoder.decode(hasKey))
718         return false;
719
720     if (!hasKey)
721         return true;
722
723     RetainPtr<CFDataRef> keyData;
724     if (!decode(decoder, keyData))
725         return false;
726
727     SecKeyRef key = nullptr;
728 #if PLATFORM(IOS)
729     if (secKeyRefDecodingAllowed)
730         SecKeyFindWithPersistentRef(keyData.get(), &key);
731 #endif
732 #if PLATFORM(MAC)
733     SecKeychainItemCopyFromPersistentReference(keyData.get(), (SecKeychainItemRef*)&key);
734 #endif
735     if (key) {
736         result = adoptCF(SecIdentityCreate(kCFAllocatorDefault, certificate.get(), key));
737         CFRelease(key);
738     }
739
740     return true;
741 }
742
743 #if HAVE(SEC_KEYCHAIN)
744 void encode(Encoder& encoder, SecKeychainItemRef keychainItem)
745 {
746     RELEASE_ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessCredentials));
747
748     CFDataRef data;
749     if (SecKeychainItemCreatePersistentReference(keychainItem, &data) == errSecSuccess) {
750         encode(encoder, data);
751         CFRelease(data);
752     }
753 }
754
755 bool decode(Decoder& decoder, RetainPtr<SecKeychainItemRef>& result)
756 {
757     RELEASE_ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessCredentials));
758
759     RetainPtr<CFDataRef> data;
760     if (!IPC::decode(decoder, data))
761         return false;
762
763     SecKeychainItemRef item;
764     if (SecKeychainItemCopyFromPersistentReference(data.get(), &item) != errSecSuccess || !item)
765         return false;
766     
767     result = adoptCF(item);
768     return true;
769 }
770 #endif
771
772 #if HAVE(SEC_ACCESS_CONTROL)
773 void encode(Encoder& encoder, SecAccessControlRef accessControl)
774 {
775     RetainPtr<CFDataRef> data = adoptCF(SecAccessControlCopyData(accessControl));
776     if (data)
777         encode(encoder, data.get());
778 }
779
780 bool decode(Decoder& decoder, RetainPtr<SecAccessControlRef>& result)
781 {
782     RetainPtr<CFDataRef> data;
783     if (!decode(decoder, data))
784         return false;
785
786     result = adoptCF(SecAccessControlCreateFromData(kCFAllocatorDefault, data.get(), nullptr));
787     if (!result)
788         return false;
789
790     return true;
791 }
792 #endif
793
794 #if HAVE(SEC_TRUST_SERIALIZATION)
795 void encode(Encoder& encoder, SecTrustRef trust)
796 {
797     auto data = adoptCF(SecTrustSerialize(trust, nullptr));
798     if (!data) {
799         encoder << false;
800         return;
801     }
802
803     encoder << true;
804     IPC::encode(encoder, data.get());
805 }
806
807 bool decode(Decoder& decoder, RetainPtr<SecTrustRef>& result)
808 {
809     bool hasTrust;
810     if (!decoder.decode(hasTrust))
811         return false;
812
813     if (!hasTrust)
814         return true;
815
816     RetainPtr<CFDataRef> trustData;
817     if (!IPC::decode(decoder, trustData))
818         return false;
819
820     auto trust = adoptCF(SecTrustDeserialize(trustData.get(), nullptr));
821     if (!trust)
822         return false;
823
824     result = WTFMove(trust);
825     return true;
826 }
827 #endif
828
829 } // namespace IPC