├── PrivacyPolicyForSkpAndKsc.pdf ├── KeyShareConsumer ├── Settings.bundle │ ├── en.lproj │ │ └── Root.strings │ └── Root.plist ├── AppDelegate.h ├── main.m ├── KeyShareConsumer.entitlements ├── KeyDetailViewController.h ├── MiniZip │ ├── mztools.h │ ├── ioapi.h │ ├── ioapi.c │ ├── mztools.c │ ├── zip.h │ └── unzip.h ├── ViewController.h ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── Objective-Zip │ ├── ZipException.h │ ├── ZipWriteStream.h │ ├── ZipReadStream.h │ ├── ZipException.m │ ├── FileInZipInfo.m │ ├── FileInZipInfo.h │ ├── ZipWriteStream.m │ ├── ZipReadStream.m │ ├── ZipFile.h │ └── ZipFile.m ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── KeyChainDataSource.h ├── AppDelegate.m ├── KeyDetailViewController.m ├── ViewController.m └── KeyChainDataSource.mm ├── KeyShareConsumer.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── project.pbxproj ├── KeyShareConsumerTests ├── Info.plist └── KeyShareConsumerTests.m ├── LICENSE ├── README.markdown └── iOS13Notes.md /PrivacyPolicyForSkpAndKsc.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Purebred/KeyShareConsumer/HEAD/PrivacyPolicyForSkpAndKsc.pdf -------------------------------------------------------------------------------- /KeyShareConsumer/Settings.bundle/en.lproj/Root.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Purebred/KeyShareConsumer/HEAD/KeyShareConsumer/Settings.bundle/en.lproj/Root.strings -------------------------------------------------------------------------------- /KeyShareConsumer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /KeyShareConsumer/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // KeyShareConsumer 4 | 5 | #import 6 | 7 | @interface AppDelegate : UIResponder 8 | 9 | @property (strong, nonatomic) UIWindow *window; 10 | 11 | 12 | @end 13 | 14 | -------------------------------------------------------------------------------- /KeyShareConsumer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // KeyShareConsumer 4 | // 5 | 6 | #import 7 | #import "AppDelegate.h" 8 | 9 | int main(int argc, char * argv[]) { 10 | @autoreleasepool { 11 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /KeyShareConsumer/KeyShareConsumer.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.icloud-container-identifiers 6 | 7 | com.apple.developer.icloud-services 8 | 9 | com.apple.developer.ubiquity-kvstore-identifier 10 | $(TeamIdentifierPrefix)$(CFBundleIdentifier) 11 | 12 | 13 | -------------------------------------------------------------------------------- /KeyShareConsumer/KeyDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KeyDetailViewController.h 3 | // KeyShareConsumer 4 | 5 | #import 6 | #import "KeyChainDataSource.h" 7 | #import "ViewController.h" 8 | 9 | @interface KeyDetailViewController : UIViewController 10 | { 11 | KeyChainDataSource* keyChain; 12 | } 13 | @property (nonatomic, retain) IBOutlet UITableView *tableView; 14 | @property (nonatomic, retain) IBOutlet UIButton *importButton; 15 | @property (nonatomic, retain) IBOutlet UIButton *cancelButton; 16 | @property (nonatomic, retain) KeyChainDataSource *keyChain; 17 | @property (nonatomic, retain) ViewController *dpvc; 18 | @property (nonatomic, assign) long itemIndex; 19 | @end 20 | -------------------------------------------------------------------------------- /KeyShareConsumer/MiniZip/mztools.h: -------------------------------------------------------------------------------- 1 | /* 2 | Additional tools for Minizip 3 | Code: Xavier Roche '2004 4 | License: Same as ZLIB (www.gzip.org) 5 | */ 6 | 7 | #ifndef _zip_tools_H 8 | #define _zip_tools_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #ifndef _ZLIB_H 15 | #include "zlib.h" 16 | #endif 17 | 18 | #include "unzip.h" 19 | 20 | /* Repair a ZIP file (missing central directory) 21 | file: file to recover 22 | fileOut: output file after recovery 23 | fileOutTmp: temporary file name used for recovery 24 | */ 25 | extern int ZEXPORT unzRepair(const char* file, 26 | const char* fileOut, 27 | const char* fileOutTmp, 28 | uLong* nRecovered, 29 | uLong* bytesRecovered); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /KeyShareConsumerTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | $(PRODUCT_NAME) 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | BNDL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | UIFileSharingEnabled 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /KeyShareConsumerTests/KeyShareConsumerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // KeyShareConsumerTests.m 3 | // KeyShareConsumerTests 4 | // 5 | 6 | #import 7 | #import 8 | 9 | @interface KeyShareConsumerTests : XCTestCase 10 | 11 | @end 12 | 13 | @implementation KeyShareConsumerTests 14 | 15 | - (void)setUp { 16 | [super setUp]; 17 | // Put setup code here. This method is called before the invocation of each test method in the class. 18 | } 19 | 20 | - (void)tearDown { 21 | // Put teardown code here. This method is called after the invocation of each test method in the class. 22 | [super tearDown]; 23 | } 24 | 25 | - (void)testExample { 26 | // This is an example of a functional test case. 27 | XCTAssert(YES, @"Pass"); 28 | } 29 | 30 | - (void)testPerformanceExample { 31 | // This is an example of a performance test case. 32 | [self measureBlock:^{ 33 | // Put the code you want to measure the time of here. 34 | }]; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /KeyShareConsumer/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // KeyShareConsumer 4 | 5 | #import 6 | #import "KeyChainDataSource.h" 7 | 8 | @interface ViewController : UIViewController 9 | { 10 | //provides information about key chain contents 11 | KeyChainDataSource* keyChain; 12 | 13 | //table view to display summary of key chain contents 14 | IBOutlet UITableView* tableViewKeyChain; 15 | 16 | //string to receive password entered by user 17 | NSString* passwordFromUser; 18 | 19 | //buffer to receive PKCS12 file read from iCloud 20 | NSData* pkcs12Data; 21 | } 22 | 23 | //Callbacks used by KeyDetailViewController for iTunes file sharing 24 | - (void)import:(long)index; 25 | - (void)dismissWithoutImporting:(long)index; 26 | 27 | //Button click handlers 28 | - (IBAction)openImportDocumentPicker:(id)sender; 29 | - (IBAction)clearKeyChain:(id)sender; 30 | 31 | @property (nonatomic, retain) UITableView *tableViewKeyChain; 32 | @property (nonatomic, retain) KeyChainDataSource *keyChain; 33 | @property (nonatomic, assign) int imageWidth; 34 | 35 | @end 36 | 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /KeyShareConsumer/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /KeyShareConsumer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | $(PRODUCT_NAME) 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.1 21 | CFBundleSignature 22 | ???? 23 | CFBundleURLTypes 24 | 25 | 26 | CFBundleURLName 27 | red.hound.keyshareconsumer 28 | CFBundleURLSchemes 29 | 30 | keyshareconsumer 31 | 32 | 33 | 34 | CFBundleVersion 35 | 2 36 | LSRequiresIPhoneOS 37 | 38 | UIFileSharingEnabled 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIMainStoryboardFile 43 | Main 44 | UIRequiredDeviceCapabilities 45 | 46 | armv7 47 | 48 | UISupportedInterfaceOrientations 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationLandscapeLeft 52 | UIInterfaceOrientationLandscapeRight 53 | 54 | UISupportedInterfaceOrientations~ipad 55 | 56 | UIInterfaceOrientationPortrait 57 | UIInterfaceOrientationPortraitUpsideDown 58 | UIInterfaceOrientationLandscapeLeft 59 | UIInterfaceOrientationLandscapeRight 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /KeyShareConsumer/Objective-Zip/ZipException.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZipException.h 3 | // Objective-Zip v. 0.7.2 4 | // 5 | // Created by Gianluca Bertani on 25/12/09. 6 | // Copyright 2009-10 Flying Dolphin Studio. All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions 10 | // are met: 11 | // 12 | // * Redistributions of source code must retain the above copyright notice, 13 | // this list of conditions and the following disclaimer. 14 | // * Redistributions in binary form must reproduce the above copyright notice, 15 | // this list of conditions and the following disclaimer in the documentation 16 | // and/or other materials provided with the distribution. 17 | // * Neither the name of Gianluca Bertani nor the names of its contributors 18 | // may be used to endorse or promote products derived from this software 19 | // without specific prior written permission. 20 | // 21 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | // POSSIBILITY OF SUCH DAMAGE. 32 | // 33 | 34 | #import 35 | 36 | 37 | @interface ZipException : NSException { 38 | 39 | @private 40 | NSInteger _error; 41 | } 42 | 43 | - (id) initWithReason:(NSString *)reason; 44 | - (id) initWithError:(NSInteger)error reason:(NSString *)reason; 45 | 46 | @property (nonatomic, readonly) NSInteger error; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /KeyShareConsumer/Objective-Zip/ZipWriteStream.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZipWriteStream.h 3 | // Objective-Zip v. 0.7.2 4 | // 5 | // Created by Gianluca Bertani on 25/12/09. 6 | // Copyright 2009-10 Flying Dolphin Studio. All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions 10 | // are met: 11 | // 12 | // * Redistributions of source code must retain the above copyright notice, 13 | // this list of conditions and the following disclaimer. 14 | // * Redistributions in binary form must reproduce the above copyright notice, 15 | // this list of conditions and the following disclaimer in the documentation 16 | // and/or other materials provided with the distribution. 17 | // * Neither the name of Gianluca Bertani nor the names of its contributors 18 | // may be used to endorse or promote products derived from this software 19 | // without specific prior written permission. 20 | // 21 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | // POSSIBILITY OF SUCH DAMAGE. 32 | // 33 | 34 | #import 35 | 36 | #include "zip.h" 37 | 38 | 39 | @interface ZipWriteStream : NSObject { 40 | NSString *_fileNameInZip; 41 | 42 | @private 43 | zipFile _zipFile; 44 | } 45 | 46 | - (id) initWithZipFileStruct:(zipFile)zipFile fileNameInZip:(NSString *)fileNameInZip; 47 | 48 | - (void) writeData:(NSData *)data; 49 | - (void) finishedWriting; 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /KeyShareConsumer/Objective-Zip/ZipReadStream.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZipReadStream.h 3 | // Objective-Zip v. 0.7.2 4 | // 5 | // Created by Gianluca Bertani on 28/12/09. 6 | // Copyright 2009-10 Flying Dolphin Studio. All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions 10 | // are met: 11 | // 12 | // * Redistributions of source code must retain the above copyright notice, 13 | // this list of conditions and the following disclaimer. 14 | // * Redistributions in binary form must reproduce the above copyright notice, 15 | // this list of conditions and the following disclaimer in the documentation 16 | // and/or other materials provided with the distribution. 17 | // * Neither the name of Gianluca Bertani nor the names of its contributors 18 | // may be used to endorse or promote products derived from this software 19 | // without specific prior written permission. 20 | // 21 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | // POSSIBILITY OF SUCH DAMAGE. 32 | // 33 | 34 | #import 35 | 36 | #include "unzip.h" 37 | 38 | 39 | @interface ZipReadStream : NSObject { 40 | NSString *_fileNameInZip; 41 | 42 | @private 43 | unzFile _unzFile; 44 | } 45 | 46 | - (id) initWithUnzFileStruct:(unzFile)unzFile fileNameInZip:(NSString *)fileNameInZip; 47 | 48 | - (NSData *)readDataOfLength:(NSUInteger)length; 49 | - (void) finishedReading; 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /KeyShareConsumer/Objective-Zip/ZipException.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZipException.m 3 | // Objective-Zip v. 0.7.2 4 | // 5 | // Created by Gianluca Bertani on 25/12/09. 6 | // Copyright 2009-10 Flying Dolphin Studio. All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions 10 | // are met: 11 | // 12 | // * Redistributions of source code must retain the above copyright notice, 13 | // this list of conditions and the following disclaimer. 14 | // * Redistributions in binary form must reproduce the above copyright notice, 15 | // this list of conditions and the following disclaimer in the documentation 16 | // and/or other materials provided with the distribution. 17 | // * Neither the name of Gianluca Bertani nor the names of its contributors 18 | // may be used to endorse or promote products derived from this software 19 | // without specific prior written permission. 20 | // 21 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | // POSSIBILITY OF SUCH DAMAGE. 32 | // 33 | 34 | #import "ZipException.h" 35 | 36 | 37 | @implementation ZipException 38 | 39 | - (id) initWithReason:(NSString *)reason { 40 | if ((self= [super initWithName:@"ZipException" reason:reason userInfo:nil])) { 41 | _error= 0; 42 | } 43 | 44 | return self; 45 | } 46 | 47 | - (id) initWithError:(NSInteger)error reason:(NSString *)reason { 48 | if ((self= [super initWithName:@"ZipException" reason:reason userInfo:nil])) { 49 | _error= error; 50 | } 51 | 52 | return self; 53 | } 54 | 55 | @synthesize error= _error; 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /KeyShareConsumer/Objective-Zip/FileInZipInfo.m: -------------------------------------------------------------------------------- 1 | // 2 | // FileInZipInfo.m 3 | // Objective-Zip v. 0.7.2 4 | // 5 | // Created by Gianluca Bertani on 27/12/09. 6 | // Copyright 2009-10 Flying Dolphin Studio. All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions 10 | // are met: 11 | // 12 | // * Redistributions of source code must retain the above copyright notice, 13 | // this list of conditions and the following disclaimer. 14 | // * Redistributions in binary form must reproduce the above copyright notice, 15 | // this list of conditions and the following disclaimer in the documentation 16 | // and/or other materials provided with the distribution. 17 | // * Neither the name of Gianluca Bertani nor the names of its contributors 18 | // may be used to endorse or promote products derived from this software 19 | // without specific prior written permission. 20 | // 21 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | // POSSIBILITY OF SUCH DAMAGE. 32 | // 33 | 34 | #import "FileInZipInfo.h" 35 | 36 | 37 | @implementation FileInZipInfo 38 | 39 | - (id) initWithName:(NSString *)name length:(NSUInteger)length level:(ZipCompressionLevel)level crypted:(BOOL)crypted size:(NSUInteger)size date:(NSDate *)date crc32:(NSUInteger)crc32 { 40 | if ((self = [super init])) { 41 | _name= name; 42 | _length= length; 43 | _level= level; 44 | _crypted= crypted; 45 | _size= size; 46 | _date= date; 47 | _crc32= crc32; 48 | } 49 | 50 | return self; 51 | } 52 | 53 | @synthesize name= _name; 54 | @synthesize length= _length; 55 | @synthesize level= _level; 56 | @synthesize crypted= _crypted; 57 | @synthesize size= _size; 58 | @synthesize date= _date; 59 | @synthesize crc32= _crc32; 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /KeyShareConsumer/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /KeyShareConsumer/Objective-Zip/FileInZipInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // FileInZipInfo.h 3 | // Objective-Zip v. 0.7.2 4 | // 5 | // Created by Gianluca Bertani on 27/12/09. 6 | // Copyright 2009-10 Flying Dolphin Studio. All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions 10 | // are met: 11 | // 12 | // * Redistributions of source code must retain the above copyright notice, 13 | // this list of conditions and the following disclaimer. 14 | // * Redistributions in binary form must reproduce the above copyright notice, 15 | // this list of conditions and the following disclaimer in the documentation 16 | // and/or other materials provided with the distribution. 17 | // * Neither the name of Gianluca Bertani nor the names of its contributors 18 | // may be used to endorse or promote products derived from this software 19 | // without specific prior written permission. 20 | // 21 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | // POSSIBILITY OF SUCH DAMAGE. 32 | // 33 | 34 | #import 35 | #import "ZipFile.h" 36 | 37 | 38 | @interface FileInZipInfo : NSObject { 39 | 40 | @private 41 | NSUInteger _length; 42 | ZipCompressionLevel _level; 43 | BOOL _crypted; 44 | NSUInteger _size; 45 | NSDate *_date; 46 | NSUInteger _crc32; 47 | NSString *_name; 48 | } 49 | 50 | - (id) initWithName:(NSString *)name length:(NSUInteger)length level:(ZipCompressionLevel)level crypted:(BOOL)crypted size:(NSUInteger)size date:(NSDate *)date crc32:(NSUInteger)crc32; 51 | 52 | @property (nonatomic, readonly) NSString *name; 53 | @property (nonatomic, readonly) NSUInteger length; 54 | @property (nonatomic, readonly) ZipCompressionLevel level; 55 | @property (nonatomic, readonly) BOOL crypted; 56 | @property (nonatomic, readonly) NSUInteger size; 57 | @property (nonatomic, readonly) NSDate *date; 58 | @property (nonatomic, readonly) NSUInteger crc32; 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /KeyShareConsumer/MiniZip/ioapi.h: -------------------------------------------------------------------------------- 1 | /* ioapi.h -- IO base function header for compress/uncompress .zip 2 | files using zlib + zip or unzip API 3 | 4 | Version 1.01e, February 12th, 2005 5 | 6 | Copyright (C) 1998-2005 Gilles Vollant 7 | */ 8 | 9 | #ifndef _ZLIBIOAPI_H 10 | #define _ZLIBIOAPI_H 11 | 12 | 13 | #define ZLIB_FILEFUNC_SEEK_CUR (1) 14 | #define ZLIB_FILEFUNC_SEEK_END (2) 15 | #define ZLIB_FILEFUNC_SEEK_SET (0) 16 | 17 | #define ZLIB_FILEFUNC_MODE_READ (1) 18 | #define ZLIB_FILEFUNC_MODE_WRITE (2) 19 | #define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) 20 | 21 | #define ZLIB_FILEFUNC_MODE_EXISTING (4) 22 | #define ZLIB_FILEFUNC_MODE_CREATE (8) 23 | 24 | 25 | #ifndef ZCALLBACK 26 | 27 | #if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) 28 | #define ZCALLBACK CALLBACK 29 | #else 30 | #define ZCALLBACK 31 | #endif 32 | #endif 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); 39 | typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); 40 | typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); 41 | typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); 42 | typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); 43 | typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); 44 | typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); 45 | 46 | typedef struct zlib_filefunc_def_s 47 | { 48 | open_file_func zopen_file; 49 | read_file_func zread_file; 50 | write_file_func zwrite_file; 51 | tell_file_func ztell_file; 52 | seek_file_func zseek_file; 53 | close_file_func zclose_file; 54 | testerror_file_func zerror_file; 55 | voidpf opaque; 56 | } zlib_filefunc_def; 57 | 58 | 59 | 60 | void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); 61 | 62 | #define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) 63 | #define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) 64 | #define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) 65 | #define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) 66 | #define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) 67 | #define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) 68 | 69 | 70 | #ifdef __cplusplus 71 | } 72 | #endif 73 | 74 | #endif 75 | 76 | -------------------------------------------------------------------------------- /KeyShareConsumer/Objective-Zip/ZipWriteStream.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZipWriteStream.m 3 | // Objective-Zip v. 0.7.2 4 | // 5 | // Created by Gianluca Bertani on 25/12/09. 6 | // Copyright 2009-10 Flying Dolphin Studio. All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions 10 | // are met: 11 | // 12 | // * Redistributions of source code must retain the above copyright notice, 13 | // this list of conditions and the following disclaimer. 14 | // * Redistributions in binary form must reproduce the above copyright notice, 15 | // this list of conditions and the following disclaimer in the documentation 16 | // and/or other materials provided with the distribution. 17 | // * Neither the name of Gianluca Bertani nor the names of its contributors 18 | // may be used to endorse or promote products derived from this software 19 | // without specific prior written permission. 20 | // 21 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | // POSSIBILITY OF SUCH DAMAGE. 32 | // 33 | 34 | #import "ZipWriteStream.h" 35 | #import "ZipException.h" 36 | 37 | #include "zip.h" 38 | 39 | 40 | @implementation ZipWriteStream 41 | 42 | 43 | - (id) initWithZipFileStruct:(zipFile)zipFile fileNameInZip:(NSString *)fileNameInZip { 44 | if ((self= [super init])) { 45 | _zipFile= zipFile; 46 | _fileNameInZip= fileNameInZip; 47 | } 48 | 49 | return self; 50 | } 51 | 52 | - (void) writeData:(NSData *)data { 53 | int err= zipWriteInFileInZip(_zipFile, [data bytes], (unsigned)[data length]); 54 | if (err < 0) { 55 | NSString *reason= [NSString stringWithFormat:@"Error in writing '%@' in the zipfile", _fileNameInZip]; 56 | @throw [[ZipException alloc] initWithError:err reason:reason]; 57 | } 58 | } 59 | 60 | - (void) finishedWriting { 61 | int err= zipCloseFileInZip(_zipFile); 62 | if (err != ZIP_OK) { 63 | NSString *reason= [NSString stringWithFormat:@"Error in closing '%@' in the zipfile", _fileNameInZip]; 64 | @throw [[ZipException alloc] initWithError:err reason:reason]; 65 | } 66 | } 67 | 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /KeyShareConsumer/Objective-Zip/ZipReadStream.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZipReadStream.m 3 | // Objective-Zip v. 0.7.2 4 | // 5 | // Created by Gianluca Bertani on 28/12/09. 6 | // Copyright 2009-10 Flying Dolphin Studio. All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions 10 | // are met: 11 | // 12 | // * Redistributions of source code must retain the above copyright notice, 13 | // this list of conditions and the following disclaimer. 14 | // * Redistributions in binary form must reproduce the above copyright notice, 15 | // this list of conditions and the following disclaimer in the documentation 16 | // and/or other materials provided with the distribution. 17 | // * Neither the name of Gianluca Bertani nor the names of its contributors 18 | // may be used to endorse or promote products derived from this software 19 | // without specific prior written permission. 20 | // 21 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | // POSSIBILITY OF SUCH DAMAGE. 32 | // 33 | 34 | #import "ZipReadStream.h" 35 | #import "ZipException.h" 36 | 37 | #include "unzip.h" 38 | 39 | 40 | @implementation ZipReadStream 41 | 42 | 43 | - (id) initWithUnzFileStruct:(unzFile)unzFile fileNameInZip:(NSString *)fileNameInZip { 44 | if ((self= [super init])) { 45 | _unzFile= unzFile; 46 | _fileNameInZip= fileNameInZip; 47 | } 48 | 49 | return self; 50 | } 51 | 52 | - (NSData *)readDataOfLength:(NSUInteger)length { 53 | NSMutableData *data = [NSMutableData dataWithLength:length]; 54 | int bytes = unzReadCurrentFile(_unzFile, [data mutableBytes], (unsigned)length); 55 | if (bytes < 0) { 56 | NSString *reason= [NSString stringWithFormat:@"Error in reading '%@' in the zipfile", _fileNameInZip]; 57 | @throw [[ZipException alloc] initWithError:bytes reason:reason]; 58 | } 59 | 60 | [data setLength:bytes]; 61 | return data; 62 | } 63 | 64 | - (void) finishedReading { 65 | int err= unzCloseCurrentFile(_unzFile); 66 | if (err != UNZ_OK) { 67 | NSString *reason= [NSString stringWithFormat:@"Error in closing '%@' in the zipfile", _fileNameInZip]; 68 | @throw [[ZipException alloc] initWithError:err reason:reason]; 69 | } 70 | } 71 | 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /KeyShareConsumer/KeyChainDataSource.h: -------------------------------------------------------------------------------- 1 | // 2 | // KeyChainDataSource.h 3 | // KeyShareConsumer 4 | 5 | #import 6 | 7 | /** 8 | KeyChainDataSource has three modes of usage, each defined by the type of 9 | item sought in the key chain. 10 | */ 11 | enum KeyChainDataSourceMode 12 | { 13 | KSM_Certificates, 14 | KSM_Identities, 15 | KSM_Keys 16 | }; 17 | 18 | /** 19 | The KeyChainDataSource class is intended to function as a data source for table views displaying 20 | various information from a key chain. Each KeyStore instance is associated with a type 21 | of key chain item, i.e., identity, certificate, key. 22 | 23 | Each item is a section in the table with various information appropriate to the item 24 | displayed in the section. 25 | 26 | Should only be used with tables with table style UITableViewStyleGrouped. 27 | */ 28 | @interface KeyChainDataSource : NSObject 29 | { 30 | 31 | @public 32 | //!When false, empty attributes are not returned, when true empty attributes are returned with 33 | // empty string value. 34 | bool displayEmptyAttributes; 35 | 36 | //!userQuery can be specified to change the search behavior applied by KeyChainDataSource 37 | // before serving data to a table view. 38 | NSMutableDictionary* userQuery; 39 | 40 | //!mode indicates the type of object associated with an instance (set upon instantiation) 41 | enum KeyChainDataSourceMode mode; 42 | 43 | @private 44 | //!initialized indicates whether LoadKeyChainContents has been successfully executed. 45 | bool initialized; 46 | 47 | //!items contains the values retrieved from the key chain 48 | NSMutableArray* items; 49 | 50 | //!dictionary with friendly attribute names (prepared in init) 51 | NSMutableDictionary* attrNames; 52 | } 53 | 54 | //Public properties 55 | @property (nonatomic, assign) bool displayEmptyAttributes; 56 | @property (nonatomic, retain) NSMutableDictionary* userQuery; 57 | 58 | //Private properties 59 | @property (nonatomic, retain) NSArray* items; 60 | @property (nonatomic, assign) enum KeyChainDataSourceMode mode; 61 | @property (nonatomic, assign) bool initialized; 62 | @property (nonatomic, retain) NSMutableDictionary* attrNames; 63 | 64 | - (id) initWithMode:(enum KeyChainDataSourceMode)mode; 65 | - (void) ClearContents; 66 | - (void) LoadKeyChainContents; 67 | - (NSString*) GetIdentityNameAtIndex:(long)index; 68 | - (NSString*) GetEmailAddressAtIndex:(long)index; 69 | - (void) removeObjectAtIndex:(long)index; 70 | - (size_t) numItems; 71 | - (SecIdentityRef) GetIdentityAtIndex:(long)index; 72 | - (NSData*) GetPKCS12AtIndex:(long)index; 73 | - (NSData*) GetPrivateKeyAtIndex:(long)index; 74 | 75 | - (int) numAttrGroups:(long)index; 76 | - (NSString*) getAttrStringAtIndex:(long)index attrGroup:(long)attrGroup; 77 | 78 | - (NSString*) getAttrNameAtSection:(long)sectionIndex attrIndex:(long)attrIndex; 79 | - (NSString*) getAttrValueAtSection:(long)sectionIndex attrIndex:(long)attrIndex; 80 | - (NSString*) getAttrValueAtSection:(long)sectionIndex attrType:(CFTypeRef)attrType; 81 | 82 | - (SecCertificateRef) getCertificateAt:(long)index; 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /KeyShareConsumer/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // KeyShareConsumer 4 | 5 | #import "AppDelegate.h" 6 | 7 | @interface AppDelegate () 8 | 9 | @end 10 | 11 | @implementation AppDelegate 12 | 13 | 14 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 15 | // Override point for customization after application launch. 16 | [self registerDefaultsFromSettingsBundle]; 17 | return YES; 18 | } 19 | 20 | - (void)applicationWillResignActive:(UIApplication *)application { 21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application { 26 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 27 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 28 | } 29 | 30 | - (void)applicationWillEnterForeground:(UIApplication *)application { 31 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 32 | } 33 | 34 | - (void)applicationDidBecomeActive:(UIApplication *)application { 35 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 36 | } 37 | 38 | - (void)applicationWillTerminate:(UIApplication *)application { 39 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 40 | } 41 | 42 | #pragma NSUserDefaults 43 | - (void)registerDefaultsFromSettingsBundle { 44 | // this function writes default settings as settings 45 | NSString *settingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"]; 46 | if(!settingsBundle) { 47 | NSLog(@"Could not find Settings.bundle"); 48 | return; 49 | } 50 | 51 | NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[settingsBundle stringByAppendingPathComponent:@"Root.plist"]]; 52 | NSArray *preferences = [settings objectForKey:@"PreferenceSpecifiers"]; 53 | 54 | NSMutableDictionary *defaultsToRegister = [[NSMutableDictionary alloc] initWithCapacity:[preferences count]]; 55 | for(NSDictionary *prefSpecification in preferences) { 56 | NSString *key = [prefSpecification objectForKey:@"Key"]; 57 | if(key) { 58 | [defaultsToRegister setObject:[prefSpecification objectForKey:@"DefaultValue"] forKey:key]; 59 | NSLog(@"writing as default %@ to the key %@",[prefSpecification objectForKey:@"DefaultValue"],key); 60 | } 61 | } 62 | 63 | [[NSUserDefaults standardUserDefaults] registerDefaults:defaultsToRegister]; 64 | 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /KeyShareConsumer/Objective-Zip/ZipFile.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZipFile.h 3 | // Objective-Zip v. 0.7.2 4 | // 5 | // Created by Gianluca Bertani on 25/12/09. 6 | // Copyright 2009-10 Flying Dolphin Studio. All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions 10 | // are met: 11 | // 12 | // * Redistributions of source code must retain the above copyright notice, 13 | // this list of conditions and the following disclaimer. 14 | // * Redistributions in binary form must reproduce the above copyright notice, 15 | // this list of conditions and the following disclaimer in the documentation 16 | // and/or other materials provided with the distribution. 17 | // * Neither the name of Gianluca Bertani nor the names of its contributors 18 | // may be used to endorse or promote products derived from this software 19 | // without specific prior written permission. 20 | // 21 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | // POSSIBILITY OF SUCH DAMAGE. 32 | // 33 | 34 | #import 35 | 36 | #include "zip.h" 37 | #include "unzip.h" 38 | 39 | 40 | typedef enum { 41 | ZipFileModeUnzip, 42 | ZipFileModeCreate, 43 | ZipFileModeAppend 44 | } ZipFileMode; 45 | 46 | typedef enum { 47 | ZipCompressionLevelDefault= -1, 48 | ZipCompressionLevelNone= 0, 49 | ZipCompressionLevelFastest= 1, 50 | ZipCompressionLevelBest= 9 51 | } ZipCompressionLevel; 52 | 53 | @class ZipReadStream; 54 | @class ZipWriteStream; 55 | @class FileInZipInfo; 56 | 57 | @interface ZipFile : NSObject { 58 | NSString *_fileName; 59 | ZipFileMode _mode; 60 | 61 | @private 62 | zipFile _zipFile; 63 | unzFile _unzFile; 64 | } 65 | 66 | - (id) initWithFileName:(NSString *)fileName mode:(ZipFileMode)mode; 67 | 68 | - (ZipWriteStream *) writeFileInZipWithName:(NSString *)fileNameInZip compressionLevel:(ZipCompressionLevel)compressionLevel; 69 | - (ZipWriteStream *) writeFileInZipWithName:(NSString *)fileNameInZip fileDate:(NSDate *)fileDate compressionLevel:(ZipCompressionLevel)compressionLevel; 70 | - (ZipWriteStream *) writeFileInZipWithName:(NSString *)fileNameInZip fileDate:(NSDate *)fileDate compressionLevel:(ZipCompressionLevel)compressionLevel password:(NSString *)password crc32:(NSUInteger)crc32; 71 | 72 | - (NSUInteger) numFilesInZip; 73 | - (NSArray *) listFileInZipInfos; 74 | 75 | - (void) goToFirstFileInZip; 76 | - (BOOL) goToNextFileInZip; 77 | - (BOOL) locateFileInZip:(NSString *)fileNameInZip; 78 | 79 | - (FileInZipInfo *) getCurrentFileInZipInfo; 80 | 81 | - (ZipReadStream *) readCurrentFileInZip; 82 | - (ZipReadStream *) readCurrentFileInZipWithPassword:(NSString *)password; 83 | 84 | - (void) close; 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /KeyShareConsumer/KeyDetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // KeyDetailViewController.m 3 | // KeyShareConsumer 4 | 5 | #import "KeyDetailViewController.h" 6 | 7 | @interface KeyDetailViewController () 8 | 9 | @end 10 | 11 | @implementation KeyDetailViewController 12 | @synthesize keyChain; 13 | 14 | - (void)viewDidLoad { 15 | [super viewDidLoad]; 16 | [_tableView setDelegate:self]; 17 | } 18 | 19 | - (void)didReceiveMemoryWarning { 20 | [super didReceiveMemoryWarning]; 21 | } 22 | 23 | #pragma mark - Table view data source 24 | 25 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 26 | { 27 | //always one section for the details view, with the possibility that there is one row per attribute or per group of attributes 28 | return 1; 29 | } 30 | 31 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 32 | { 33 | if(keyChain) 34 | return [keyChain numAttrGroups:_itemIndex]; 35 | else 36 | return 0; 37 | } 38 | 39 | #define FONT_SIZE 14.0f 40 | #define CELL_CONTENT_MARGIN 10.0f 41 | 42 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath; 43 | { 44 | CGRect frameRect = [self.tableView frame]; 45 | 46 | NSString *detail = [keyChain getAttrValueAtSection:_itemIndex attrIndex:indexPath.row]; 47 | NSString *label = NSLocalizedString(@"Miscellaneous properties", @"Row label in key details view"); 48 | 49 | /* 50 | CGSize constraint = CGSizeMake(frameRect.size.width - (CELL_CONTENT_MARGIN * 2) - 44, 20000.0f); 51 | CGSize detailSize = [detail sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:NSLineBreakByCharWrapping]; 52 | CGSize labelSize = [label sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:NSLineBreakByCharWrapping]; 53 | */ 54 | 55 | NSAttributedString *attributedTextDetail = 56 | [[NSAttributedString alloc] 57 | initWithString:detail 58 | attributes:@ 59 | { 60 | NSFontAttributeName: [UIFont systemFontOfSize:FONT_SIZE] 61 | }]; 62 | CGRect rectDetail = [attributedTextDetail boundingRectWithSize:(CGSize){frameRect.size.width, CGFLOAT_MAX} 63 | options:NSStringDrawingUsesLineFragmentOrigin 64 | context:nil]; 65 | CGSize detailSize = rectDetail.size; 66 | 67 | NSAttributedString *attributedTextLabel = 68 | [[NSAttributedString alloc] 69 | initWithString:label 70 | attributes:@ 71 | { 72 | NSFontAttributeName: [UIFont systemFontOfSize:FONT_SIZE] 73 | }]; 74 | CGRect rectLabel = [attributedTextLabel boundingRectWithSize:(CGSize){frameRect.size.width, CGFLOAT_MAX} 75 | options:NSStringDrawingUsesLineFragmentOrigin 76 | context:nil]; 77 | CGSize labelSize = rectLabel.size; 78 | 79 | 80 | CGFloat height = MAX(detailSize.height + labelSize.height, 44.0f); 81 | 82 | return height + (CELL_CONTENT_MARGIN * 2); 83 | } 84 | 85 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 86 | { 87 | static NSString *CellIdentifier = @"Cell"; 88 | 89 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 90 | if (cell == nil) 91 | { 92 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; 93 | } 94 | 95 | NSString* attrNameLabelString = [keyChain getAttrNameAtSection:_itemIndex attrIndex:indexPath.row]; 96 | NSString* attrValueLabelString = [keyChain getAttrValueAtSection:_itemIndex attrIndex:indexPath.row]; 97 | 98 | [cell.textLabel setText:attrNameLabelString]; 99 | cell.detailTextLabel.numberOfLines = 0; 100 | [cell.detailTextLabel setText:attrValueLabelString]; 101 | 102 | return cell; 103 | } 104 | 105 | #pragma mark - Table view delegate 106 | 107 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 108 | { 109 | } 110 | 111 | - (IBAction)OnShareWithiTunes:(id)sender 112 | { 113 | [_dpvc import:self.itemIndex]; 114 | } 115 | 116 | - (IBAction)OnCancel:(id)sender 117 | { 118 | [_dpvc dismissWithoutImporting:self.itemIndex]; 119 | } 120 | @end 121 | -------------------------------------------------------------------------------- /KeyShareConsumer/MiniZip/ioapi.c: -------------------------------------------------------------------------------- 1 | /* ioapi.c -- IO base function header for compress/uncompress .zip 2 | files using zlib + zip or unzip API 3 | 4 | Version 1.01e, February 12th, 2005 5 | 6 | Copyright (C) 1998-2005 Gilles Vollant 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "zlib.h" 14 | #include "ioapi.h" 15 | 16 | 17 | 18 | /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ 19 | 20 | #ifndef SEEK_CUR 21 | #define SEEK_CUR 1 22 | #endif 23 | 24 | #ifndef SEEK_END 25 | #define SEEK_END 2 26 | #endif 27 | 28 | #ifndef SEEK_SET 29 | #define SEEK_SET 0 30 | #endif 31 | 32 | voidpf ZCALLBACK fopen_file_func OF(( 33 | voidpf opaque, 34 | const char* filename, 35 | int mode)); 36 | 37 | uLong ZCALLBACK fread_file_func OF(( 38 | voidpf opaque, 39 | voidpf stream, 40 | void* buf, 41 | uLong size)); 42 | 43 | uLong ZCALLBACK fwrite_file_func OF(( 44 | voidpf opaque, 45 | voidpf stream, 46 | const void* buf, 47 | uLong size)); 48 | 49 | long ZCALLBACK ftell_file_func OF(( 50 | voidpf opaque, 51 | voidpf stream)); 52 | 53 | long ZCALLBACK fseek_file_func OF(( 54 | voidpf opaque, 55 | voidpf stream, 56 | uLong offset, 57 | int origin)); 58 | 59 | int ZCALLBACK fclose_file_func OF(( 60 | voidpf opaque, 61 | voidpf stream)); 62 | 63 | int ZCALLBACK ferror_file_func OF(( 64 | voidpf opaque, 65 | voidpf stream)); 66 | 67 | 68 | voidpf ZCALLBACK fopen_file_func (opaque, filename, mode) 69 | voidpf opaque; 70 | const char* filename; 71 | int mode; 72 | { 73 | FILE* file = NULL; 74 | const char* mode_fopen = NULL; 75 | if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) 76 | mode_fopen = "rb"; 77 | else 78 | if (mode & ZLIB_FILEFUNC_MODE_EXISTING) 79 | mode_fopen = "r+b"; 80 | else 81 | if (mode & ZLIB_FILEFUNC_MODE_CREATE) 82 | mode_fopen = "wb"; 83 | 84 | if ((filename!=NULL) && (mode_fopen != NULL)) 85 | file = fopen(filename, mode_fopen); 86 | return file; 87 | } 88 | 89 | 90 | uLong ZCALLBACK fread_file_func (opaque, stream, buf, size) 91 | voidpf opaque; 92 | voidpf stream; 93 | void* buf; 94 | uLong size; 95 | { 96 | uLong ret; 97 | ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); 98 | return ret; 99 | } 100 | 101 | 102 | uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size) 103 | voidpf opaque; 104 | voidpf stream; 105 | const void* buf; 106 | uLong size; 107 | { 108 | uLong ret; 109 | ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); 110 | return ret; 111 | } 112 | 113 | long ZCALLBACK ftell_file_func (opaque, stream) 114 | voidpf opaque; 115 | voidpf stream; 116 | { 117 | long ret; 118 | ret = ftell((FILE *)stream); 119 | return ret; 120 | } 121 | 122 | long ZCALLBACK fseek_file_func (opaque, stream, offset, origin) 123 | voidpf opaque; 124 | voidpf stream; 125 | uLong offset; 126 | int origin; 127 | { 128 | int fseek_origin=0; 129 | long ret; 130 | switch (origin) 131 | { 132 | case ZLIB_FILEFUNC_SEEK_CUR : 133 | fseek_origin = SEEK_CUR; 134 | break; 135 | case ZLIB_FILEFUNC_SEEK_END : 136 | fseek_origin = SEEK_END; 137 | break; 138 | case ZLIB_FILEFUNC_SEEK_SET : 139 | fseek_origin = SEEK_SET; 140 | break; 141 | default: return -1; 142 | } 143 | ret = 0; 144 | fseek((FILE *)stream, offset, fseek_origin); 145 | return ret; 146 | } 147 | 148 | int ZCALLBACK fclose_file_func (opaque, stream) 149 | voidpf opaque; 150 | voidpf stream; 151 | { 152 | int ret; 153 | ret = fclose((FILE *)stream); 154 | return ret; 155 | } 156 | 157 | int ZCALLBACK ferror_file_func (opaque, stream) 158 | voidpf opaque; 159 | voidpf stream; 160 | { 161 | int ret; 162 | ret = ferror((FILE *)stream); 163 | return ret; 164 | } 165 | 166 | void fill_fopen_filefunc (pzlib_filefunc_def) 167 | zlib_filefunc_def* pzlib_filefunc_def; 168 | { 169 | pzlib_filefunc_def->zopen_file = fopen_file_func; 170 | pzlib_filefunc_def->zread_file = fread_file_func; 171 | pzlib_filefunc_def->zwrite_file = fwrite_file_func; 172 | pzlib_filefunc_def->ztell_file = ftell_file_func; 173 | pzlib_filefunc_def->zseek_file = fseek_file_func; 174 | pzlib_filefunc_def->zclose_file = fclose_file_func; 175 | pzlib_filefunc_def->zerror_file = ferror_file_func; 176 | pzlib_filefunc_def->opaque = NULL; 177 | } 178 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | NOTE: the `key_sharing_2025` branch features changes that aim to demonstrate minimal changes required to interoperate with the key sharing 2025 implementation. The `master` branch and remainder of this README address the legacy key sharing mechanism. The [KeyShareConsumer2025](https://github.com/Purebred/KeyShareConsumer2025) and [SampleKeyProvider2025](https://github.com/Purebred/SampleKeyProvider2025) projects provide complete examples of a key sharing 2025 implementation. 2 | 3 | The KeyShareConsumer app is intended to illustrate usage of the document provider interface exposed by the Purebred Registration app. This interface can be used to import cryptographic keys provisioned using the Purebred Registration app, the SampleKeyProvider app or PKCS12 files stored in the user's iCloud account. 4 | 5 | Document provider extensions were introduced in iOS 8 and are described [here](https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/FileProvider.html). As additional background, a sample document provider was presented during the WWDC 2014 conference. Source code is available [here](https://github.com/master-nevi/WWDC-2014/tree/master/NewBox%20An%20Introduction%20to%20iCloud%20Document%20enhancements%20in%20iOS%208.0). 6 | 7 | Purebred Registration provides the key sharing interface as an easier alternative to importing PKCS12 files using iTunes file sharing or implementing support for a certificate enrollment protocol. Using the interface requires your app to present the `UIDocumentPickerViewController`, which will enable the user to select which key to import, and implement the `UIDocumentPickerDelegate` interface, which will enable your app to import keys. In the Key Share Consumer sample, this code is present in `ViewController.m`. A `UIDocumentPickerViewController` instance is displayed in the click handler for the "Import Key" button. The `ViewController` class implements `UIDocumentPickerDelegate`. 8 | 9 | When the user uses the Purebred Registration app interface, the PKCS12 password is passed to your app via the pasteboard. When the user selects a file from their iCloud account, the user will need to be prompted to enter a password. In either case, the PKCS12 file and password are processed in the `importP12` method of the `ViewController` class. To enable the Purebred Registration interface tap Import Key then tap Locations. This will display a list of providers including More. Tap More. If the Purebred Registration app is installed, it will be listed on the Manage Storage Providers view. Turn the switch on for the Purebred Key Chain row then tap Done. Now when Import Key and Locations are tapped, the Purebred Key Chain option will be available. 10 | 11 | The list of keys displayed by a provider can be filtered using a uniform type identifier (UTI) value that indicates the type of key the caller wants to import. The list of UTIs currently supported by the Purebred Registration app and SampleKeyProvider app are as follows: 12 | 13 | * com.rsa.pkcs-12 14 | * purebred.select.all 15 | * purebred.select.all_user 16 | * purebred.select.all-user 17 | * purebred.select.device 18 | * purebred.select.signature 19 | * purebred.select.encryption 20 | * purebred.select.authentication 21 | * purebred.select.no_filter 22 | * purebred.select.no-filter 23 | * purebred.zip.all 24 | * purebred.zip.all_user 25 | * purebred.zip.all-user 26 | * purebred.zip.device 27 | * purebred.zip.signature 28 | * purebred.zip.encryption 29 | * purebred.zip.authentication 30 | * purebred.zip.no_filter 31 | * purebred.zip.no-filter 32 | 33 | NOTE* UTI values with "-" have been added to support custom app distribution as "_" are not allowed. 34 | 35 | Bundle identifiers need to be updated to reflect bundle identifiers associated with the signer. These include: 36 | 37 | Bundle Identifier for KeyShareConsumer 38 | 39 | By default, the Purebred Registration app serves up the most recent keys for the indicated types. The no_filter option can be used to cause all available keys for the indicated types to be displayed. 40 | 41 | Details on obtaining and testing the Purebred Registration app will be posted soon. See [here](http://iase.disa.mil/pki-pke/Pages/mobile.aspx). 42 | 43 | ViewController.h/ViewController.m 44 | ------ 45 | Main view controller that enables the user to import a key into Key Share Consumer's key chain or to clear the contents of Key Share Consumer's key chain. Code related to key sharing interface is in the import button click handler and the `UIDocumentPickerDelegate` implementation. Implements `UITableViewDelegate` and `UITableViewDataSource` to display items from the key chain, as served by an instance of `KeyChainDataSource`. 46 | 47 | KeyChainDataSource.h/KeyChainDataSource.mm 48 | ------ 49 | Provides interface to key chain to populate table views. 50 | 51 | KeyDetailViewController.h/KeyDetailViewController.m 52 | ------ 53 | Sample view controller to display details of a selected key chain item. Implements `UITableViewDelegate` and `UITableViewDataSource` to display details of a selected item from the key chain, as served by an instance of `KeyChainDataSource`. 54 | 55 | AppDelegate.h/AppDelegate.m 56 | ------ 57 | Uninteresting boilerplate `AppDelegate` implementation. 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /iOS13Notes.md: -------------------------------------------------------------------------------- 1 | Note, iOS13.1 beta 2 appears to have resolved the issue with the mechanism underpinning the key sharing interface in Purebred v1.5 (2) and below. Thus, the changes described below may not be adopted. 2 | 3 | # Purebred's Key Sharing interface 4 | 5 | The Purebred Registration app is used to provision derived credentials and recovered encryption credentials to iOS, Android, selected Windows 10 and Yubikey devices. On all except iOS, keys are provisioned such that third party and system applications can use the keys via system-provided APIs. On iOS, keys are provisioned such that keys can be exported from the Purebred app into system or third party applications. 6 | 7 | The Purebred Registration app has included support for sharing derived credentials with other apps since iOS 8. Credentials are shared using the document provider framework defined by Apple. Apps importing keys do not require any Purebred-specific API but use the [UIDocumentPickerViewController](https://developer.apple.com/documentation/uikit/uidocumentpickerextensionviewcontroller?language=objc) in concert with either Apple's standard com.rsa.pkcs-12 uniform type identifier (UTI) or UTIs defined by the Purebred app to obtain a PKCS 12 or set of PKCS 12 files. Passwords for the PKCS 12 file(s) are shared via the system pasteboard in parallel with the sharing of the PKCS 12 file(s). Purebred-defined UTIs allow for display of specific types of credentials, i.e., signature, authentication, encryption. This is different from display of different types of files, i.e., PDF, JPEG, etc. Additionally, the Purebred-defined UTIs can be paired with a UTI indicating not to filter based on issuance date. 8 | 9 | # Key Sharing and iOS13 10 | 11 | Since iOS13/iPadOS 13 beta 1, the key sharing capability of the Purebred Registration app has been in a state of flux, working in some cases and not working in other cases. Several feedback submissions have been provided, forum discussions posted and etc. following beta 1 and over the course of the subsequent beta releases. The simplest summary is available in the forum post to the iOS13 beta forum titled [NSExtensionFileProviderSupportsEnumeration set to NO not respected on first run](https://forums.developer.apple.com/thread/120997). As noted in the forum post, the mechanisms used to share keys no longer works as expected, but can be made to work via an unsustainable series of install/uninstall/reinstall steps with the value of the NSExtensionFileProviderSupportsEnumeration value in the file provider's Info.plist altered. After executing the steps noted in the forum post, the existing mechanisms continue to work as before. 12 | 13 | The NSExtensionFileProviderSupportsEnumeration setting referenced in the forum post was introduced in iOS 11 as part of changes to the document provider mechanisms. The changes facilitate the use of the Files app that was introduced in iOS 11. As part of these changes, a standard user interface provided by the system for all file provider interactions, vs. user interfaces provided specific to each file provider type. Purebred did not adopt these APIs in part due to the nature of the files being shared, which do not lend themselves to use of the Files app nor standard user actions like delete, rename or move. 14 | 15 | # Purebred Registration v1.5 (112) beta 16 | 17 | A beta release of the Purebred Registration app is being made available for testing by mobility offices and vendors due to the relatively significant changes required to mitigate the iOS13 issue noted above. This release adds support for NSExtensionFileProviderSupportsEnumeration and use of the standard system-provided user interface for browsing file providers. The intent is for this release to require no changes to vendor code, i.e., existing invocation of UIDocumentPickerViewController should continue to work as before. However, changes to the user experience are unavoidable and some changes to vendors applications may be warranted to avoid some deprecated interfaces. 18 | 19 | The user experience changes are due to how the user interface interrogates the file provider and how the UI handles files that do not correspond to UTIs requested by the consuming application. In previous releases, the Purebred Registration app provided the user interface and received a list of UTIs desired by the consuming application. This enabled the app to display only credentials of the types desired by the consuming application. In the new implementation, the Purebred Registration app only provides the file provider, not the user interface. File providers do not receive a list of UTIs from the consuming application and cannot filter the list of files returned. The standard user interface shows all files listed by a file provider in all cases, with files that do not match a requested UTI grayed out. 20 | 21 | To avoid a single long list of mostly grayed out files, this release features a folder-based display for key sharing. The folders correspond to the Purebred-defined UTIs. The folder names and corresponding UTIs are as follows: 22 | 23 | - All Credentials [purebred.select.all] 24 | - All Credentials (PKCS-12) [com.rsa.pkcs-12] 25 | - All Credentials (unfiltered) [purebred.select.all with 26 | purebred.select.no_filter] 27 | - All User Credentials [purebred.select.all_user] 28 | - Authentication Credentials [purebred.select.authentication] 29 | - Device Credentials [purebred.select.device] 30 | - Digital Signature Credentials [purebred.select.signature] 31 | - Encryption Credentials [purebred.select.encryption] 32 | 33 | Each folder's contents is a list of certificate files associated with the indicated UTI along with a zip file associated with the corresponding purebred.zip UTI. As noted, most files will appear as grayed out under typical use. User documentation describing steps required to import keys into various products should be updated to reflect this. The Key Share Consumer sample app can be used to experiment with various UTI combinations. 34 | 35 | This approach was elected to retain as much flexibility as possible relative to the previous set of UTIs. Lost in this release is the pairing of the no_filter UTIs with UTIs other than purebred.select.all/purebred.zip.all, which was retained due to current prevalence of use. Flexibility is retained owing to limited time for vendors to test prior to the general release of iOS13 and iPadOS13. Future versions of the Purebred Registration app may reduce the set of UTIs provided, add support for use of tags, etc. 36 | 37 | 38 | -------------------------------------------------------------------------------- /KeyShareConsumer/Settings.bundle/Root.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | StringsTable 6 | Root 7 | PreferenceSpecifiers 8 | 9 | 10 | Title 11 | User selected keys 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | Type 17 | PSToggleSwitchSpecifier 18 | Title 19 | All keys (com.rsa.pkcs-12) 20 | Key 21 | toggle_com_rsa_pkcs12 22 | DefaultValue 23 | 24 | 25 | 26 | Type 27 | PSToggleSwitchSpecifier 28 | Title 29 | All keys (purebred.select.all) 30 | Key 31 | toggle_purebred_select_all 32 | DefaultValue 33 | 34 | 35 | 36 | Type 37 | PSToggleSwitchSpecifier 38 | Title 39 | All user keys (purebred.select.all.user) 40 | Key 41 | toggle_purebred_select_all_user 42 | DefaultValue 43 | 44 | 45 | 46 | Type 47 | PSToggleSwitchSpecifier 48 | Title 49 | All user keys (purebred.select.all-user) 50 | Key 51 | toggle_purebred_select_all-user 52 | DefaultValue 53 | 54 | 55 | 56 | Type 57 | PSToggleSwitchSpecifier 58 | Title 59 | Signature keys (purebred.select.signature) 60 | Key 61 | toggle_purebred_select_signature 62 | DefaultValue 63 | 64 | 65 | 66 | Type 67 | PSToggleSwitchSpecifier 68 | Title 69 | All encryption keys (purebred.select.encryption) 70 | Key 71 | toggle_purebred_select_encryption 72 | DefaultValue 73 | 74 | 75 | 76 | Type 77 | PSToggleSwitchSpecifier 78 | Title 79 | All authentication keys (purebred.select.authentication) 80 | Key 81 | toggle_purebred_select_authentication 82 | DefaultValue 83 | 84 | 85 | 86 | Type 87 | PSToggleSwitchSpecifier 88 | Title 89 | All device keys (purebred.select.device) 90 | Key 91 | toggle_purebred_select_device 92 | DefaultValue 93 | 94 | 95 | 96 | Type 97 | PSToggleSwitchSpecifier 98 | Title 99 | All device keys (purebred.zip.all) 100 | Key 101 | toggle_purebred_zip_all 102 | DefaultValue 103 | 104 | 105 | 106 | Type 107 | PSToggleSwitchSpecifier 108 | Title 109 | All user keys (purebred.zip.all.user) 110 | Key 111 | toggle_purebred_zip_all_user 112 | DefaultValue 113 | 114 | 115 | 116 | Type 117 | PSToggleSwitchSpecifier 118 | Title 119 | All user keys (purebred.zip.all-user) 120 | Key 121 | toggle_purebred_zip_all-user 122 | DefaultValue 123 | 124 | 125 | 126 | Type 127 | PSToggleSwitchSpecifier 128 | Title 129 | Signature keys (purebred.zip.signature) 130 | Key 131 | toggle_purebred_zip_signature 132 | DefaultValue 133 | 134 | 135 | 136 | Type 137 | PSToggleSwitchSpecifier 138 | Title 139 | All encryption keys (purebred.zip.encryption) 140 | Key 141 | toggle_purebred_zip_encryption 142 | DefaultValue 143 | 144 | 145 | 146 | Type 147 | PSToggleSwitchSpecifier 148 | Title 149 | All authentication keys (purebred.zip.authentication) 150 | Key 151 | toggle_purebred_zip_authentication 152 | DefaultValue 153 | 154 | 155 | 156 | Type 157 | PSToggleSwitchSpecifier 158 | Title 159 | All device keys (purebred.zip.device) 160 | Key 161 | toggle_purebred_zip_device 162 | DefaultValue 163 | 164 | 165 | 166 | Type 167 | PSToggleSwitchSpecifier 168 | Title 169 | Do not filter on notBefore for zip files (purebred.zip.no_filter) 170 | Key 171 | toggle_purebred_zip_no_filter 172 | DefaultValue 173 | 174 | 175 | 176 | Type 177 | PSToggleSwitchSpecifier 178 | Title 179 | Do not filter on notBefore (purebred.select.no_filter) 180 | Key 181 | toggle_purebred_select_no_filter 182 | DefaultValue 183 | 184 | 185 | 186 | Type 187 | PSToggleSwitchSpecifier 188 | Title 189 | Do not filter on notBefore for zip files (purebred.zip.no-filter) 190 | Key 191 | toggle_purebred_zip_no-filter 192 | DefaultValue 193 | 194 | 195 | 196 | Type 197 | PSToggleSwitchSpecifier 198 | Title 199 | Do not filter on notBefore (purebred.select.no-filter) 200 | Key 201 | toggle_purebred_select_no-filter 202 | DefaultValue 203 | 204 | 205 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /KeyShareConsumer/MiniZip/mztools.c: -------------------------------------------------------------------------------- 1 | /* 2 | Additional tools for Minizip 3 | Code: Xavier Roche '2004 4 | License: Same as ZLIB (www.gzip.org) 5 | */ 6 | 7 | /* Code */ 8 | #include 9 | #include 10 | #include 11 | #include "zlib.h" 12 | #include "unzip.h" 13 | #include "mztools.h" 14 | 15 | #define READ_8(adr) ((unsigned char)*(adr)) 16 | #define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) ) 17 | #define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) ) 18 | 19 | #define WRITE_8(buff, n) do { \ 20 | *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \ 21 | } while(0) 22 | #define WRITE_16(buff, n) do { \ 23 | WRITE_8((unsigned char*)(buff), n); \ 24 | WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \ 25 | } while(0) 26 | #define WRITE_32(buff, n) do { \ 27 | WRITE_16((unsigned char*)(buff), (n) & 0xffff); \ 28 | WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ 29 | } while(0) 30 | 31 | extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered) 32 | const char* file; 33 | const char* fileOut; 34 | const char* fileOutTmp; 35 | uLong* nRecovered; 36 | uLong* bytesRecovered; 37 | { 38 | int err = Z_OK; 39 | FILE* fpZip = fopen(file, "rb"); 40 | FILE* fpOut = fopen(fileOut, "wb"); 41 | FILE* fpOutCD = fopen(fileOutTmp, "wb"); 42 | if (fpZip != NULL && fpOut != NULL) { 43 | int entries = 0; 44 | uLong totalBytes = 0; 45 | char header[30]; 46 | char filename[256]; 47 | char extra[1024]; 48 | int offset = 0; 49 | int offsetCD = 0; 50 | while ( fread(header, 1, 30, fpZip) == 30 ) { 51 | int currentOffset = offset; 52 | 53 | /* File entry */ 54 | if (READ_32(header) == 0x04034b50) { 55 | unsigned int version = READ_16(header + 4); 56 | unsigned int gpflag = READ_16(header + 6); 57 | unsigned int method = READ_16(header + 8); 58 | unsigned int filetime = READ_16(header + 10); 59 | unsigned int filedate = READ_16(header + 12); 60 | unsigned int crc = READ_32(header + 14); /* crc */ 61 | unsigned int cpsize = READ_32(header + 18); /* compressed size */ 62 | unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */ 63 | unsigned int fnsize = READ_16(header + 26); /* file name length */ 64 | unsigned int extsize = READ_16(header + 28); /* extra field length */ 65 | filename[0] = extra[0] = '\0'; 66 | 67 | /* Header */ 68 | if (fwrite(header, 1, 30, fpOut) == 30) { 69 | offset += 30; 70 | } else { 71 | err = Z_ERRNO; 72 | break; 73 | } 74 | 75 | /* Filename */ 76 | if (fnsize > 0) { 77 | if (fread(filename, 1, fnsize, fpZip) == fnsize) { 78 | if (fwrite(filename, 1, fnsize, fpOut) == fnsize) { 79 | offset += fnsize; 80 | } else { 81 | err = Z_ERRNO; 82 | break; 83 | } 84 | } else { 85 | err = Z_ERRNO; 86 | break; 87 | } 88 | } else { 89 | err = Z_STREAM_ERROR; 90 | break; 91 | } 92 | 93 | /* Extra field */ 94 | if (extsize > 0) { 95 | if (fread(extra, 1, extsize, fpZip) == extsize) { 96 | if (fwrite(extra, 1, extsize, fpOut) == extsize) { 97 | offset += extsize; 98 | } else { 99 | err = Z_ERRNO; 100 | break; 101 | } 102 | } else { 103 | err = Z_ERRNO; 104 | break; 105 | } 106 | } 107 | 108 | /* Data */ 109 | { 110 | int dataSize = cpsize; 111 | if (dataSize == 0) { 112 | dataSize = uncpsize; 113 | } 114 | if (dataSize > 0) { 115 | char* data = malloc(dataSize); 116 | if (data != NULL) { 117 | if ((int)fread(data, 1, dataSize, fpZip) == dataSize) { 118 | if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) { 119 | offset += dataSize; 120 | totalBytes += dataSize; 121 | } else { 122 | err = Z_ERRNO; 123 | } 124 | } else { 125 | err = Z_ERRNO; 126 | } 127 | free(data); 128 | if (err != Z_OK) { 129 | break; 130 | } 131 | } else { 132 | err = Z_MEM_ERROR; 133 | break; 134 | } 135 | } 136 | } 137 | 138 | /* Central directory entry */ 139 | { 140 | char cdeHeader[46]; 141 | char* comment = ""; 142 | int comsize = (int) strlen(comment); 143 | WRITE_32(cdeHeader, 0x02014b50); 144 | WRITE_16(cdeHeader + 4, version); 145 | WRITE_16(cdeHeader + 6, version); 146 | WRITE_16(cdeHeader + 8, gpflag); 147 | WRITE_16(cdeHeader + 10, method); 148 | WRITE_16(cdeHeader + 12, filetime); 149 | WRITE_16(cdeHeader + 14, filedate); 150 | WRITE_32(cdeHeader + 16, crc); 151 | WRITE_32(cdeHeader + 20, cpsize); 152 | WRITE_32(cdeHeader + 24, uncpsize); 153 | WRITE_16(cdeHeader + 28, fnsize); 154 | WRITE_16(cdeHeader + 30, extsize); 155 | WRITE_16(cdeHeader + 32, comsize); 156 | WRITE_16(cdeHeader + 34, 0); /* disk # */ 157 | WRITE_16(cdeHeader + 36, 0); /* int attrb */ 158 | WRITE_32(cdeHeader + 38, 0); /* ext attrb */ 159 | WRITE_32(cdeHeader + 42, currentOffset); 160 | /* Header */ 161 | if (fwrite(cdeHeader, 1, 46, fpOutCD) == 46) { 162 | offsetCD += 46; 163 | 164 | /* Filename */ 165 | if (fnsize > 0) { 166 | if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) { 167 | offsetCD += fnsize; 168 | } else { 169 | err = Z_ERRNO; 170 | break; 171 | } 172 | } else { 173 | err = Z_STREAM_ERROR; 174 | break; 175 | } 176 | 177 | /* Extra field */ 178 | if (extsize > 0) { 179 | if (fwrite(extra, 1, extsize, fpOutCD) == extsize) { 180 | offsetCD += extsize; 181 | } else { 182 | err = Z_ERRNO; 183 | break; 184 | } 185 | } 186 | 187 | /* Comment field */ 188 | if (comsize > 0) { 189 | if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) { 190 | offsetCD += comsize; 191 | } else { 192 | err = Z_ERRNO; 193 | break; 194 | } 195 | } 196 | 197 | 198 | } else { 199 | err = Z_ERRNO; 200 | break; 201 | } 202 | } 203 | 204 | /* Success */ 205 | entries++; 206 | 207 | } else { 208 | break; 209 | } 210 | } 211 | 212 | /* Final central directory */ 213 | { 214 | int entriesZip = entries; 215 | char fcdHeader[22]; 216 | char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; 217 | int comsize = (int) strlen(comment); 218 | if (entriesZip > 0xffff) { 219 | entriesZip = 0xffff; 220 | } 221 | WRITE_32(fcdHeader, 0x06054b50); 222 | WRITE_16(fcdHeader + 4, 0); /* disk # */ 223 | WRITE_16(fcdHeader + 6, 0); /* disk # */ 224 | WRITE_16(fcdHeader + 8, entriesZip); /* hack */ 225 | WRITE_16(fcdHeader + 10, entriesZip); /* hack */ 226 | WRITE_32(fcdHeader + 12, offsetCD); /* size of CD */ 227 | WRITE_32(fcdHeader + 16, offset); /* offset to CD */ 228 | WRITE_16(fcdHeader + 20, comsize); /* comment */ 229 | 230 | /* Header */ 231 | if (fwrite(fcdHeader, 1, 22, fpOutCD) == 22) { 232 | 233 | /* Comment field */ 234 | if (comsize > 0) { 235 | if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) { 236 | err = Z_ERRNO; 237 | } 238 | } 239 | 240 | } else { 241 | err = Z_ERRNO; 242 | } 243 | } 244 | 245 | /* Final merge (file + central directory) */ 246 | fclose(fpOutCD); 247 | if (err == Z_OK) { 248 | fpOutCD = fopen(fileOutTmp, "rb"); 249 | if (fpOutCD != NULL) { 250 | int nRead; 251 | char buffer[8192]; 252 | while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) { 253 | if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) { 254 | err = Z_ERRNO; 255 | break; 256 | } 257 | } 258 | fclose(fpOutCD); 259 | } 260 | } 261 | 262 | /* Close */ 263 | fclose(fpZip); 264 | fclose(fpOut); 265 | 266 | /* Wipe temporary file */ 267 | (void)remove(fileOutTmp); 268 | 269 | /* Number of recovered entries */ 270 | if (err == Z_OK) { 271 | if (nRecovered != NULL) { 272 | *nRecovered = entries; 273 | } 274 | if (bytesRecovered != NULL) { 275 | *bytesRecovered = totalBytes; 276 | } 277 | } 278 | } else { 279 | err = Z_STREAM_ERROR; 280 | } 281 | return err; 282 | } 283 | -------------------------------------------------------------------------------- /KeyShareConsumer/MiniZip/zip.h: -------------------------------------------------------------------------------- 1 | /* zip.h -- IO for compress .zip files using zlib 2 | Version 1.01e, February 12th, 2005 3 | 4 | Copyright (C) 1998-2005 Gilles Vollant 5 | 6 | This unzip package allow creates .ZIP file, compatible with PKZip 2.04g 7 | WinZip, InfoZip tools and compatible. 8 | Multi volume ZipFile (span) are not supported. 9 | Encryption compatible with pkzip 2.04g only supported 10 | Old compressions used by old PKZip 1.x are not supported 11 | 12 | For uncompress .zip file, look at unzip.h 13 | 14 | 15 | I WAIT FEEDBACK at mail info@winimage.com 16 | Visit also http://www.winimage.com/zLibDll/unzip.html for evolution 17 | 18 | Condition of use and distribution are the same than zlib : 19 | 20 | This software is provided 'as-is', without any express or implied 21 | warranty. In no event will the authors be held liable for any damages 22 | arising from the use of this software. 23 | 24 | Permission is granted to anyone to use this software for any purpose, 25 | including commercial applications, and to alter it and redistribute it 26 | freely, subject to the following restrictions: 27 | 28 | 1. The origin of this software must not be misrepresented; you must not 29 | claim that you wrote the original software. If you use this software 30 | in a product, an acknowledgment in the product documentation would be 31 | appreciated but is not required. 32 | 2. Altered source versions must be plainly marked as such, and must not be 33 | misrepresented as being the original software. 34 | 3. This notice may not be removed or altered from any source distribution. 35 | 36 | 37 | */ 38 | 39 | /* for more info about .ZIP format, see 40 | http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip 41 | http://www.info-zip.org/pub/infozip/doc/ 42 | PkWare has also a specification at : 43 | ftp://ftp.pkware.com/probdesc.zip 44 | */ 45 | 46 | #ifndef _zip_H 47 | #define _zip_H 48 | 49 | #ifdef __cplusplus 50 | extern "C" { 51 | #endif 52 | 53 | #ifndef _ZLIB_H 54 | #include "zlib.h" 55 | #endif 56 | 57 | #ifndef _ZLIBIOAPI_H 58 | #include "ioapi.h" 59 | #endif 60 | 61 | #if defined(STRICTZIP) || defined(STRICTZIPUNZIP) 62 | /* like the STRICT of WIN32, we define a pointer that cannot be converted 63 | from (void*) without cast */ 64 | typedef struct TagzipFile__ { int unused; } zipFile__; 65 | typedef zipFile__ *zipFile; 66 | #else 67 | typedef voidp zipFile; 68 | #endif 69 | 70 | #define ZIP_OK (0) 71 | #define ZIP_EOF (0) 72 | #define ZIP_ERRNO (Z_ERRNO) 73 | #define ZIP_PARAMERROR (-102) 74 | #define ZIP_BADZIPFILE (-103) 75 | #define ZIP_INTERNALERROR (-104) 76 | 77 | #ifndef DEF_MEM_LEVEL 78 | # if MAX_MEM_LEVEL >= 8 79 | # define DEF_MEM_LEVEL 8 80 | # else 81 | # define DEF_MEM_LEVEL MAX_MEM_LEVEL 82 | # endif 83 | #endif 84 | /* default memLevel */ 85 | 86 | /* tm_zip contain date/time info */ 87 | typedef struct tm_zip_s 88 | { 89 | uInt tm_sec; /* seconds after the minute - [0,59] */ 90 | uInt tm_min; /* minutes after the hour - [0,59] */ 91 | uInt tm_hour; /* hours since midnight - [0,23] */ 92 | uInt tm_mday; /* day of the month - [1,31] */ 93 | uInt tm_mon; /* months since January - [0,11] */ 94 | uInt tm_year; /* years - [1980..2044] */ 95 | } tm_zip; 96 | 97 | typedef struct 98 | { 99 | tm_zip tmz_date; /* date in understandable format */ 100 | uLong dosDate; /* if dos_date == 0, tmu_date is used */ 101 | /* uLong flag; */ /* general purpose bit flag 2 bytes */ 102 | 103 | uLong internal_fa; /* internal file attributes 2 bytes */ 104 | uLong external_fa; /* external file attributes 4 bytes */ 105 | } zip_fileinfo; 106 | 107 | typedef const char* zipcharpc; 108 | 109 | 110 | #define APPEND_STATUS_CREATE (0) 111 | #define APPEND_STATUS_CREATEAFTER (1) 112 | #define APPEND_STATUS_ADDINZIP (2) 113 | 114 | extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); 115 | /* 116 | Create a zipfile. 117 | pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on 118 | an Unix computer "zlib/zlib113.zip". 119 | if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip 120 | will be created at the end of the file. 121 | (useful if the file contain a self extractor code) 122 | if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will 123 | add files in existing zip (be sure you don't add file that doesn't exist) 124 | If the zipfile cannot be opened, the return value is NULL. 125 | Else, the return value is a zipFile Handle, usable with other function 126 | of this zip package. 127 | */ 128 | 129 | /* Note : there is no delete function into a zipfile. 130 | If you want delete file into a zipfile, you must open a zipfile, and create another 131 | Of couse, you can use RAW reading and writing to copy the file you did not want delte 132 | */ 133 | 134 | extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, 135 | int append, 136 | zipcharpc* globalcomment, 137 | zlib_filefunc_def* pzlib_filefunc_def)); 138 | 139 | extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, 140 | const char* filename, 141 | const zip_fileinfo* zipfi, 142 | const void* extrafield_local, 143 | uInt size_extrafield_local, 144 | const void* extrafield_global, 145 | uInt size_extrafield_global, 146 | const char* comment, 147 | int method, 148 | int level)); 149 | /* 150 | Open a file in the ZIP for writing. 151 | filename : the filename in zip (if NULL, '-' without quote will be used 152 | *zipfi contain supplemental information 153 | if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local 154 | contains the extrafield data the the local header 155 | if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global 156 | contains the extrafield data the the local header 157 | if comment != NULL, comment contain the comment string 158 | method contain the compression method (0 for store, Z_DEFLATED for deflate) 159 | level contain the level of compression (can be Z_DEFAULT_COMPRESSION) 160 | */ 161 | 162 | 163 | extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, 164 | const char* filename, 165 | const zip_fileinfo* zipfi, 166 | const void* extrafield_local, 167 | uInt size_extrafield_local, 168 | const void* extrafield_global, 169 | uInt size_extrafield_global, 170 | const char* comment, 171 | int method, 172 | int level, 173 | int raw)); 174 | 175 | /* 176 | Same than zipOpenNewFileInZip, except if raw=1, we write raw file 177 | */ 178 | 179 | extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, 180 | const char* filename, 181 | const zip_fileinfo* zipfi, 182 | const void* extrafield_local, 183 | uInt size_extrafield_local, 184 | const void* extrafield_global, 185 | uInt size_extrafield_global, 186 | const char* comment, 187 | int method, 188 | int level, 189 | int raw, 190 | int windowBits, 191 | int memLevel, 192 | int strategy, 193 | const char* password, 194 | uLong crcForCtypting)); 195 | 196 | /* 197 | Same than zipOpenNewFileInZip2, except 198 | windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 199 | password : crypting password (NULL for no crypting) 200 | crcForCtypting : crc of file to compress (needed for crypting) 201 | */ 202 | 203 | 204 | extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, 205 | const void* buf, 206 | unsigned len)); 207 | /* 208 | Write data in the zipfile 209 | */ 210 | 211 | extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); 212 | /* 213 | Close the current file in the zipfile 214 | */ 215 | 216 | extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, 217 | uLong uncompressed_size, 218 | uLong crc32)); 219 | /* 220 | Close the current file in the zipfile, for fiel opened with 221 | parameter raw=1 in zipOpenNewFileInZip2 222 | uncompressed_size and crc32 are value for the uncompressed size 223 | */ 224 | 225 | extern int ZEXPORT zipClose OF((zipFile file, 226 | const char* global_comment)); 227 | /* 228 | Close the zipfile 229 | */ 230 | 231 | #ifdef __cplusplus 232 | } 233 | #endif 234 | 235 | #endif /* _zip_H */ 236 | -------------------------------------------------------------------------------- /KeyShareConsumer/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 45 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 102 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /KeyShareConsumer/MiniZip/unzip.h: -------------------------------------------------------------------------------- 1 | /* unzip.h -- IO for uncompress .zip files using zlib 2 | Version 1.01e, February 12th, 2005 3 | 4 | Copyright (C) 1998-2005 Gilles Vollant 5 | 6 | This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g 7 | WinZip, InfoZip tools and compatible. 8 | 9 | Multi volume ZipFile (span) are not supported. 10 | Encryption compatible with pkzip 2.04g only supported 11 | Old compressions used by old PKZip 1.x are not supported 12 | 13 | 14 | I WAIT FEEDBACK at mail info@winimage.com 15 | Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution 16 | 17 | Condition of use and distribution are the same than zlib : 18 | 19 | This software is provided 'as-is', without any express or implied 20 | warranty. In no event will the authors be held liable for any damages 21 | arising from the use of this software. 22 | 23 | Permission is granted to anyone to use this software for any purpose, 24 | including commercial applications, and to alter it and redistribute it 25 | freely, subject to the following restrictions: 26 | 27 | 1. The origin of this software must not be misrepresented; you must not 28 | claim that you wrote the original software. If you use this software 29 | in a product, an acknowledgment in the product documentation would be 30 | appreciated but is not required. 31 | 2. Altered source versions must be plainly marked as such, and must not be 32 | misrepresented as being the original software. 33 | 3. This notice may not be removed or altered from any source distribution. 34 | 35 | 36 | */ 37 | 38 | /* for more info about .ZIP format, see 39 | http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip 40 | http://www.info-zip.org/pub/infozip/doc/ 41 | PkWare has also a specification at : 42 | ftp://ftp.pkware.com/probdesc.zip 43 | */ 44 | 45 | #ifndef _unz_H 46 | #define _unz_H 47 | 48 | #ifdef __cplusplus 49 | extern "C" { 50 | #endif 51 | 52 | #ifndef _ZLIB_H 53 | #include "zlib.h" 54 | #endif 55 | 56 | #ifndef _ZLIBIOAPI_H 57 | #include "ioapi.h" 58 | #endif 59 | 60 | #if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) 61 | /* like the STRICT of WIN32, we define a pointer that cannot be converted 62 | from (void*) without cast */ 63 | typedef struct TagunzFile__ { int unused; } unzFile__; 64 | typedef unzFile__ *unzFile; 65 | #else 66 | typedef voidp unzFile; 67 | #endif 68 | 69 | 70 | #define UNZ_OK (0) 71 | #define UNZ_END_OF_LIST_OF_FILE (-100) 72 | #define UNZ_ERRNO (Z_ERRNO) 73 | #define UNZ_EOF (0) 74 | #define UNZ_PARAMERROR (-102) 75 | #define UNZ_BADZIPFILE (-103) 76 | #define UNZ_INTERNALERROR (-104) 77 | #define UNZ_CRCERROR (-105) 78 | 79 | /* tm_unz contain date/time info */ 80 | typedef struct tm_unz_s 81 | { 82 | uInt tm_sec; /* seconds after the minute - [0,59] */ 83 | uInt tm_min; /* minutes after the hour - [0,59] */ 84 | uInt tm_hour; /* hours since midnight - [0,23] */ 85 | uInt tm_mday; /* day of the month - [1,31] */ 86 | uInt tm_mon; /* months since January - [0,11] */ 87 | uInt tm_year; /* years - [1980..2044] */ 88 | } tm_unz; 89 | 90 | /* unz_global_info structure contain global data about the ZIPfile 91 | These data comes from the end of central dir */ 92 | typedef struct unz_global_info_s 93 | { 94 | uLong number_entry; /* total number of entries in 95 | the central dir on this disk */ 96 | uLong size_comment; /* size of the global comment of the zipfile */ 97 | } unz_global_info; 98 | 99 | 100 | /* unz_file_info contain information about a file in the zipfile */ 101 | typedef struct unz_file_info_s 102 | { 103 | uLong version; /* version made by 2 bytes */ 104 | uLong version_needed; /* version needed to extract 2 bytes */ 105 | uLong flag; /* general purpose bit flag 2 bytes */ 106 | uLong compression_method; /* compression method 2 bytes */ 107 | uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ 108 | uLong crc; /* crc-32 4 bytes */ 109 | uLong compressed_size; /* compressed size 4 bytes */ 110 | uLong uncompressed_size; /* uncompressed size 4 bytes */ 111 | uLong size_filename; /* filename length 2 bytes */ 112 | uLong size_file_extra; /* extra field length 2 bytes */ 113 | uLong size_file_comment; /* file comment length 2 bytes */ 114 | 115 | uLong disk_num_start; /* disk number start 2 bytes */ 116 | uLong internal_fa; /* internal file attributes 2 bytes */ 117 | uLong external_fa; /* external file attributes 4 bytes */ 118 | 119 | tm_unz tmu_date; 120 | } unz_file_info; 121 | 122 | extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, 123 | const char* fileName2, 124 | int iCaseSensitivity)); 125 | /* 126 | Compare two filename (fileName1,fileName2). 127 | If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) 128 | If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi 129 | or strcasecmp) 130 | If iCaseSenisivity = 0, case sensitivity is defaut of your operating system 131 | (like 1 on Unix, 2 on Windows) 132 | */ 133 | 134 | 135 | extern unzFile ZEXPORT unzOpen OF((const char *path)); 136 | /* 137 | Open a Zip file. path contain the full pathname (by example, 138 | on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer 139 | "zlib/zlib113.zip". 140 | If the zipfile cannot be opened (file don't exist or in not valid), the 141 | return value is NULL. 142 | Else, the return value is a unzFile Handle, usable with other function 143 | of this unzip package. 144 | */ 145 | 146 | extern unzFile ZEXPORT unzOpen2 OF((const char *path, 147 | zlib_filefunc_def* pzlib_filefunc_def)); 148 | /* 149 | Open a Zip file, like unzOpen, but provide a set of file low level API 150 | for read/write the zip file (see ioapi.h) 151 | */ 152 | 153 | extern int ZEXPORT unzClose OF((unzFile file)); 154 | /* 155 | Close a ZipFile opened with unzipOpen. 156 | If there is files inside the .Zip opened with unzOpenCurrentFile (see later), 157 | these files MUST be closed with unzipCloseCurrentFile before call unzipClose. 158 | return UNZ_OK if there is no problem. */ 159 | 160 | extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, 161 | unz_global_info *pglobal_info)); 162 | /* 163 | Write info about the ZipFile in the *pglobal_info structure. 164 | No preparation of the structure is needed 165 | return UNZ_OK if there is no problem. */ 166 | 167 | 168 | extern int ZEXPORT unzGetGlobalComment OF((unzFile file, 169 | char *szComment, 170 | uLong uSizeBuf)); 171 | /* 172 | Get the global comment string of the ZipFile, in the szComment buffer. 173 | uSizeBuf is the size of the szComment buffer. 174 | return the number of byte copied or an error code <0 175 | */ 176 | 177 | 178 | /***************************************************************************/ 179 | /* Unzip package allow you browse the directory of the zipfile */ 180 | 181 | extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); 182 | /* 183 | Set the current file of the zipfile to the first file. 184 | return UNZ_OK if there is no problem 185 | */ 186 | 187 | extern int ZEXPORT unzGoToNextFile OF((unzFile file)); 188 | /* 189 | Set the current file of the zipfile to the next file. 190 | return UNZ_OK if there is no problem 191 | return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. 192 | */ 193 | 194 | extern int ZEXPORT unzLocateFile OF((unzFile file, 195 | const char *szFileName, 196 | int iCaseSensitivity)); 197 | /* 198 | Try locate the file szFileName in the zipfile. 199 | For the iCaseSensitivity signification, see unzStringFileNameCompare 200 | 201 | return value : 202 | UNZ_OK if the file is found. It becomes the current file. 203 | UNZ_END_OF_LIST_OF_FILE if the file is not found 204 | */ 205 | 206 | 207 | /* ****************************************** */ 208 | /* Ryan supplied functions */ 209 | /* unz_file_info contain information about a file in the zipfile */ 210 | typedef struct unz_file_pos_s 211 | { 212 | uLong pos_in_zip_directory; /* offset in zip file directory */ 213 | uLong num_of_file; /* # of file */ 214 | } unz_file_pos; 215 | 216 | extern int ZEXPORT unzGetFilePos( 217 | unzFile file, 218 | unz_file_pos* file_pos); 219 | 220 | extern int ZEXPORT unzGoToFilePos( 221 | unzFile file, 222 | unz_file_pos* file_pos); 223 | 224 | /* ****************************************** */ 225 | 226 | extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, 227 | unz_file_info *pfile_info, 228 | char *szFileName, 229 | uLong fileNameBufferSize, 230 | void *extraField, 231 | uLong extraFieldBufferSize, 232 | char *szComment, 233 | uLong commentBufferSize)); 234 | /* 235 | Get Info about the current file 236 | if pfile_info!=NULL, the *pfile_info structure will contain somes info about 237 | the current file 238 | if szFileName!=NULL, the filemane string will be copied in szFileName 239 | (fileNameBufferSize is the size of the buffer) 240 | if extraField!=NULL, the extra field information will be copied in extraField 241 | (extraFieldBufferSize is the size of the buffer). 242 | This is the Central-header version of the extra field 243 | if szComment!=NULL, the comment string of the file will be copied in szComment 244 | (commentBufferSize is the size of the buffer) 245 | */ 246 | 247 | /***************************************************************************/ 248 | /* for reading the content of the current zipfile, you can open it, read data 249 | from it, and close it (you can close it before reading all the file) 250 | */ 251 | 252 | extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); 253 | /* 254 | Open for reading data the current file in the zipfile. 255 | If there is no error, the return value is UNZ_OK. 256 | */ 257 | 258 | extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, 259 | const char* password)); 260 | /* 261 | Open for reading data the current file in the zipfile. 262 | password is a crypting password 263 | If there is no error, the return value is UNZ_OK. 264 | */ 265 | 266 | extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, 267 | int* method, 268 | int* level, 269 | int raw)); 270 | /* 271 | Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) 272 | if raw==1 273 | *method will receive method of compression, *level will receive level of 274 | compression 275 | note : you can set level parameter as NULL (if you did not want known level, 276 | but you CANNOT set method parameter as NULL 277 | */ 278 | 279 | extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, 280 | int* method, 281 | int* level, 282 | int raw, 283 | const char* password)); 284 | /* 285 | Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) 286 | if raw==1 287 | *method will receive method of compression, *level will receive level of 288 | compression 289 | note : you can set level parameter as NULL (if you did not want known level, 290 | but you CANNOT set method parameter as NULL 291 | */ 292 | 293 | 294 | extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); 295 | /* 296 | Close the file in zip opened with unzOpenCurrentFile 297 | Return UNZ_CRCERROR if all the file was read but the CRC is not good 298 | */ 299 | 300 | extern int ZEXPORT unzReadCurrentFile OF((unzFile file, 301 | voidp buf, 302 | unsigned len)); 303 | /* 304 | Read bytes from the current file (opened by unzOpenCurrentFile) 305 | buf contain buffer where data must be copied 306 | len the size of buf. 307 | 308 | return the number of byte copied if somes bytes are copied 309 | return 0 if the end of file was reached 310 | return <0 with error code if there is an error 311 | (UNZ_ERRNO for IO error, or zLib error for uncompress error) 312 | */ 313 | 314 | extern z_off_t ZEXPORT unztell OF((unzFile file)); 315 | /* 316 | Give the current position in uncompressed data 317 | */ 318 | 319 | extern int ZEXPORT unzeof OF((unzFile file)); 320 | /* 321 | return 1 if the end of file was reached, 0 elsewhere 322 | */ 323 | 324 | extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, 325 | voidp buf, 326 | unsigned len)); 327 | /* 328 | Read extra field from the current file (opened by unzOpenCurrentFile) 329 | This is the local-header version of the extra field (sometimes, there is 330 | more info in the local-header version than in the central-header) 331 | 332 | if buf==NULL, it return the size of the local extra field 333 | 334 | if buf!=NULL, len is the size of the buffer, the extra header is copied in 335 | buf. 336 | the return value is the number of bytes copied in buf, or (if <0) 337 | the error code 338 | */ 339 | 340 | /***************************************************************************/ 341 | 342 | /* Get the current file offset */ 343 | extern uLong ZEXPORT unzGetOffset (unzFile file); 344 | 345 | /* Set the current file offset */ 346 | extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); 347 | 348 | 349 | 350 | #ifdef __cplusplus 351 | } 352 | #endif 353 | 354 | #endif /* _unz_H */ 355 | -------------------------------------------------------------------------------- /KeyShareConsumer/Objective-Zip/ZipFile.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZipFile.m 3 | // Objective-Zip v. 0.7.2 4 | // 5 | // Created by Gianluca Bertani on 25/12/09. 6 | // Copyright 2009-10 Flying Dolphin Studio. All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions 10 | // are met: 11 | // 12 | // * Redistributions of source code must retain the above copyright notice, 13 | // this list of conditions and the following disclaimer. 14 | // * Redistributions in binary form must reproduce the above copyright notice, 15 | // this list of conditions and the following disclaimer in the documentation 16 | // and/or other materials provided with the distribution. 17 | // * Neither the name of Gianluca Bertani nor the names of its contributors 18 | // may be used to endorse or promote products derived from this software 19 | // without specific prior written permission. 20 | // 21 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | // POSSIBILITY OF SUCH DAMAGE. 32 | // 33 | 34 | #import "ZipFile.h" 35 | #import "ZipException.h" 36 | #import "ZipReadStream.h" 37 | #import "ZipWriteStream.h" 38 | #import "FileInZipInfo.h" 39 | 40 | #define FILE_IN_ZIP_MAX_NAME_LENGTH (256) 41 | 42 | 43 | @implementation ZipFile 44 | 45 | 46 | - (id) initWithFileName:(NSString *)fileName mode:(ZipFileMode)mode { 47 | if ((self= [super init])) { 48 | _fileName= fileName; 49 | _mode= mode; 50 | 51 | switch (mode) { 52 | case ZipFileModeUnzip: 53 | _unzFile= unzOpen([_fileName cStringUsingEncoding:NSUTF8StringEncoding]); 54 | if (_unzFile == NULL) { 55 | NSString *reason= [NSString stringWithFormat:@"Can't open '%@'", _fileName]; 56 | @throw [[ZipException alloc] initWithReason:reason]; 57 | } 58 | break; 59 | 60 | case ZipFileModeCreate: 61 | _zipFile= zipOpen([_fileName cStringUsingEncoding:NSUTF8StringEncoding], APPEND_STATUS_CREATE); 62 | if (_zipFile == NULL) { 63 | NSString *reason= [NSString stringWithFormat:@"Can't open '%@'", _fileName]; 64 | @throw [[ZipException alloc] initWithReason:reason]; 65 | } 66 | break; 67 | 68 | case ZipFileModeAppend: 69 | _zipFile= zipOpen([_fileName cStringUsingEncoding:NSUTF8StringEncoding], APPEND_STATUS_ADDINZIP); 70 | if (_zipFile == NULL) { 71 | NSString *reason= [NSString stringWithFormat:@"Can't open '%@'", _fileName]; 72 | @throw [[ZipException alloc] initWithReason:reason]; 73 | } 74 | break; 75 | 76 | default: { 77 | NSString *reason= [NSString stringWithFormat:@"Unknown mode %d", _mode]; 78 | @throw [[ZipException alloc] initWithReason:reason]; 79 | } 80 | } 81 | } 82 | 83 | return self; 84 | } 85 | 86 | - (ZipWriteStream *) writeFileInZipWithName:(NSString *)fileNameInZip compressionLevel:(ZipCompressionLevel)compressionLevel { 87 | if (_mode == ZipFileModeUnzip) { 88 | NSString *reason= [NSString stringWithFormat:@"Operation not permitted with Unzip mode"]; 89 | @throw [[ZipException alloc] initWithReason:reason]; 90 | } 91 | 92 | NSDate *now= [NSDate date]; 93 | NSCalendar *calendar= [NSCalendar currentCalendar]; 94 | NSDateComponents *date= [calendar components:(NSCalendarUnitSecond | NSCalendarUnitMinute | NSCalendarUnitHour | NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear) fromDate:now]; 95 | zip_fileinfo zi; 96 | zi.tmz_date.tm_sec= (uInt)[date second]; 97 | zi.tmz_date.tm_min= (uInt)[date minute]; 98 | zi.tmz_date.tm_hour= (uInt)[date hour]; 99 | zi.tmz_date.tm_mday= (uInt)[date day]; 100 | zi.tmz_date.tm_mon= (uInt)[date month] -1; 101 | zi.tmz_date.tm_year= (uInt)[date year]; 102 | zi.internal_fa= 0; 103 | zi.external_fa= 0; 104 | zi.dosDate= 0; 105 | 106 | int err= zipOpenNewFileInZip3( 107 | _zipFile, 108 | [fileNameInZip cStringUsingEncoding:NSUTF8StringEncoding], 109 | &zi, 110 | NULL, 0, NULL, 0, NULL, 111 | (compressionLevel != ZipCompressionLevelNone) ? Z_DEFLATED : 0, 112 | compressionLevel, 0, 113 | -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, 114 | NULL, 0); 115 | if (err != ZIP_OK) { 116 | NSString *reason= [NSString stringWithFormat:@"Error in opening '%@' in zipfile", fileNameInZip]; 117 | @throw [[ZipException alloc] initWithError:err reason:reason]; 118 | } 119 | 120 | return [[ZipWriteStream alloc] initWithZipFileStruct:_zipFile fileNameInZip:fileNameInZip]; 121 | } 122 | 123 | - (ZipWriteStream *) writeFileInZipWithName:(NSString *)fileNameInZip fileDate:(NSDate *)fileDate compressionLevel:(ZipCompressionLevel)compressionLevel { 124 | if (_mode == ZipFileModeUnzip) { 125 | NSString *reason= [NSString stringWithFormat:@"Operation not permitted with Unzip mode"]; 126 | @throw [[ZipException alloc] initWithReason:reason]; 127 | } 128 | 129 | NSCalendar *calendar= [NSCalendar currentCalendar]; 130 | NSDateComponents *date= [calendar components:(NSCalendarUnitSecond | NSCalendarUnitMinute | NSCalendarUnitHour | NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear) fromDate:fileDate]; 131 | zip_fileinfo zi; 132 | zi.tmz_date.tm_sec= (uInt)[date second]; 133 | zi.tmz_date.tm_min= (uInt)[date minute]; 134 | zi.tmz_date.tm_hour= (uInt)[date hour]; 135 | zi.tmz_date.tm_mday= (uInt)[date day]; 136 | zi.tmz_date.tm_mon= (uInt)[date month] -1; 137 | zi.tmz_date.tm_year= (uInt)[date year]; 138 | zi.internal_fa= 0; 139 | zi.external_fa= 0; 140 | zi.dosDate= 0; 141 | 142 | int err= zipOpenNewFileInZip3( 143 | _zipFile, 144 | [fileNameInZip cStringUsingEncoding:NSUTF8StringEncoding], 145 | &zi, 146 | NULL, 0, NULL, 0, NULL, 147 | (compressionLevel != ZipCompressionLevelNone) ? Z_DEFLATED : 0, 148 | compressionLevel, 0, 149 | -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, 150 | NULL, 0); 151 | if (err != ZIP_OK) { 152 | NSString *reason= [NSString stringWithFormat:@"Error in opening '%@' in zipfile", fileNameInZip]; 153 | @throw [[ZipException alloc] initWithError:err reason:reason]; 154 | } 155 | 156 | return [[ZipWriteStream alloc] initWithZipFileStruct:_zipFile fileNameInZip:fileNameInZip]; 157 | } 158 | 159 | - (ZipWriteStream *) writeFileInZipWithName:(NSString *)fileNameInZip fileDate:(NSDate *)fileDate compressionLevel:(ZipCompressionLevel)compressionLevel password:(NSString *)password crc32:(NSUInteger)crc32 { 160 | if (_mode == ZipFileModeUnzip) { 161 | NSString *reason= [NSString stringWithFormat:@"Operation not permitted with Unzip mode"]; 162 | @throw [[ZipException alloc] initWithReason:reason]; 163 | } 164 | 165 | NSCalendar *calendar= [NSCalendar currentCalendar]; 166 | NSDateComponents *date= [calendar components:(NSCalendarUnitSecond | NSCalendarUnitMinute | NSCalendarUnitHour | NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear) fromDate:fileDate]; 167 | zip_fileinfo zi; 168 | zi.tmz_date.tm_sec= (uInt)[date second]; 169 | zi.tmz_date.tm_min= (uInt)[date minute]; 170 | zi.tmz_date.tm_hour= (uInt)[date hour]; 171 | zi.tmz_date.tm_mday= (uInt)[date day]; 172 | zi.tmz_date.tm_mon= (uInt)[date month] -1; 173 | zi.tmz_date.tm_year= (uInt)[date year]; 174 | zi.internal_fa= 0; 175 | zi.external_fa= 0; 176 | zi.dosDate= 0; 177 | 178 | int err= zipOpenNewFileInZip3( 179 | _zipFile, 180 | [fileNameInZip cStringUsingEncoding:NSUTF8StringEncoding], 181 | &zi, 182 | NULL, 0, NULL, 0, NULL, 183 | (compressionLevel != ZipCompressionLevelNone) ? Z_DEFLATED : 0, 184 | compressionLevel, 0, 185 | -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, 186 | [password cStringUsingEncoding:NSUTF8StringEncoding], crc32); 187 | if (err != ZIP_OK) { 188 | NSString *reason= [NSString stringWithFormat:@"Error in opening '%@' in zipfile", fileNameInZip]; 189 | @throw [[ZipException alloc] initWithError:err reason:reason]; 190 | } 191 | 192 | return [[ZipWriteStream alloc] initWithZipFileStruct:_zipFile fileNameInZip:fileNameInZip]; 193 | } 194 | 195 | - (NSUInteger) numFilesInZip { 196 | if (_mode != ZipFileModeUnzip) { 197 | NSString *reason= [NSString stringWithFormat:@"Operation not permitted without Unzip mode"]; 198 | @throw [[ZipException alloc] initWithReason:reason]; 199 | } 200 | 201 | unz_global_info gi; 202 | int err= unzGetGlobalInfo(_unzFile, &gi); 203 | if (err != UNZ_OK) { 204 | NSString *reason= [NSString stringWithFormat:@"Error in getting global info in '%@'", _fileName]; 205 | @throw [[ZipException alloc] initWithError:err reason:reason]; 206 | } 207 | 208 | return gi.number_entry; 209 | } 210 | 211 | - (NSArray *) listFileInZipInfos { 212 | int num= (uInt)[self numFilesInZip]; 213 | if (num < 1) 214 | return [[NSArray alloc] init]; 215 | 216 | NSMutableArray *files= [[NSMutableArray alloc] initWithCapacity:num]; 217 | 218 | [self goToFirstFileInZip]; 219 | for (int i= 0; i < num; i++) { 220 | FileInZipInfo *info= [self getCurrentFileInZipInfo]; 221 | [files addObject:info]; 222 | 223 | if ((i +1) < num) 224 | [self goToNextFileInZip]; 225 | } 226 | 227 | return files; 228 | } 229 | 230 | - (void) goToFirstFileInZip { 231 | if (_mode != ZipFileModeUnzip) { 232 | NSString *reason= [NSString stringWithFormat:@"Operation not permitted without Unzip mode"]; 233 | @throw [[ZipException alloc] initWithReason:reason]; 234 | } 235 | 236 | int err= unzGoToFirstFile(_unzFile); 237 | if (err != UNZ_OK) { 238 | NSString *reason= [NSString stringWithFormat:@"Error in going to first file in zip in '%@'", _fileName]; 239 | @throw [[ZipException alloc] initWithError:err reason:reason]; 240 | } 241 | } 242 | 243 | - (BOOL) goToNextFileInZip { 244 | if (_mode != ZipFileModeUnzip) { 245 | NSString *reason= [NSString stringWithFormat:@"Operation not permitted without Unzip mode"]; 246 | @throw [[ZipException alloc] initWithReason:reason]; 247 | } 248 | 249 | int err= unzGoToNextFile(_unzFile); 250 | if (err == UNZ_END_OF_LIST_OF_FILE) 251 | return NO; 252 | 253 | if (err != UNZ_OK) { 254 | NSString *reason= [NSString stringWithFormat:@"Error in going to next file in zip in '%@'", _fileName]; 255 | @throw [[ZipException alloc] initWithError:err reason:reason]; 256 | } 257 | 258 | return YES; 259 | } 260 | 261 | - (BOOL) locateFileInZip:(NSString *)fileNameInZip { 262 | if (_mode != ZipFileModeUnzip) { 263 | NSString *reason= [NSString stringWithFormat:@"Operation not permitted without Unzip mode"]; 264 | @throw [[ZipException alloc] initWithReason:reason]; 265 | } 266 | 267 | int err= unzLocateFile(_unzFile, [fileNameInZip cStringUsingEncoding:NSUTF8StringEncoding], 1); 268 | if (err == UNZ_END_OF_LIST_OF_FILE) 269 | return NO; 270 | 271 | if (err != UNZ_OK) { 272 | NSString *reason= [NSString stringWithFormat:@"Error in going to next file in zip in '%@'", _fileName]; 273 | @throw [[ZipException alloc] initWithError:err reason:reason]; 274 | } 275 | 276 | return YES; 277 | } 278 | 279 | - (FileInZipInfo *) getCurrentFileInZipInfo { 280 | if (_mode != ZipFileModeUnzip) { 281 | NSString *reason= [NSString stringWithFormat:@"Operation not permitted without Unzip mode"]; 282 | @throw [[ZipException alloc] initWithReason:reason]; 283 | } 284 | 285 | char filename_inzip[FILE_IN_ZIP_MAX_NAME_LENGTH]; 286 | unz_file_info file_info; 287 | 288 | int err= unzGetCurrentFileInfo(_unzFile, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0); 289 | if (err != UNZ_OK) { 290 | NSString *reason= [NSString stringWithFormat:@"Error in getting current file info in '%@'", _fileName]; 291 | @throw [[ZipException alloc] initWithError:err reason:reason]; 292 | } 293 | 294 | NSString *name= [NSString stringWithCString:filename_inzip encoding:NSUTF8StringEncoding]; 295 | 296 | ZipCompressionLevel level= ZipCompressionLevelNone; 297 | if (file_info.compression_method != 0) { 298 | switch ((file_info.flag & 0x6) / 2) { 299 | case 0: 300 | level= ZipCompressionLevelDefault; 301 | break; 302 | 303 | case 1: 304 | level= ZipCompressionLevelBest; 305 | break; 306 | 307 | default: 308 | level= ZipCompressionLevelFastest; 309 | break; 310 | } 311 | } 312 | 313 | BOOL crypted= ((file_info.flag & 1) != 0); 314 | 315 | NSDateComponents *components= [[NSDateComponents alloc] init]; 316 | [components setDay:file_info.tmu_date.tm_mday]; 317 | [components setMonth:file_info.tmu_date.tm_mon +1]; 318 | [components setYear:file_info.tmu_date.tm_year]; 319 | [components setHour:file_info.tmu_date.tm_hour]; 320 | [components setMinute:file_info.tmu_date.tm_min]; 321 | [components setSecond:file_info.tmu_date.tm_sec]; 322 | NSCalendar *calendar= [NSCalendar currentCalendar]; 323 | NSDate *date= [calendar dateFromComponents:components]; 324 | 325 | FileInZipInfo *info= [[FileInZipInfo alloc] initWithName:name length:file_info.uncompressed_size level:level crypted:crypted size:file_info.compressed_size date:date crc32:file_info.crc]; 326 | return info; 327 | } 328 | 329 | - (ZipReadStream *) readCurrentFileInZip { 330 | if (_mode != ZipFileModeUnzip) { 331 | NSString *reason= [NSString stringWithFormat:@"Operation not permitted without Unzip mode"]; 332 | @throw [[ZipException alloc] initWithReason:reason]; 333 | } 334 | 335 | char filename_inzip[FILE_IN_ZIP_MAX_NAME_LENGTH]; 336 | unz_file_info file_info; 337 | 338 | int err= unzGetCurrentFileInfo(_unzFile, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0); 339 | if (err != UNZ_OK) { 340 | NSString *reason= [NSString stringWithFormat:@"Error in getting current file info in '%@'", _fileName]; 341 | @throw [[ZipException alloc] initWithError:err reason:reason]; 342 | } 343 | 344 | NSString *fileNameInZip= [NSString stringWithCString:filename_inzip encoding:NSUTF8StringEncoding]; 345 | 346 | err= unzOpenCurrentFilePassword(_unzFile, NULL); 347 | if (err != UNZ_OK) { 348 | NSString *reason= [NSString stringWithFormat:@"Error in opening current file in '%@'", _fileName]; 349 | @throw [[ZipException alloc] initWithError:err reason:reason]; 350 | } 351 | 352 | return [[ZipReadStream alloc] initWithUnzFileStruct:_unzFile fileNameInZip:fileNameInZip]; 353 | } 354 | 355 | - (ZipReadStream *) readCurrentFileInZipWithPassword:(NSString *)password { 356 | if (_mode != ZipFileModeUnzip) { 357 | NSString *reason= [NSString stringWithFormat:@"Operation not permitted without Unzip mode"]; 358 | @throw [[ZipException alloc] initWithReason:reason]; 359 | } 360 | 361 | char filename_inzip[FILE_IN_ZIP_MAX_NAME_LENGTH]; 362 | unz_file_info file_info; 363 | 364 | int err= unzGetCurrentFileInfo(_unzFile, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0); 365 | if (err != UNZ_OK) { 366 | NSString *reason= [NSString stringWithFormat:@"Error in getting current file info in '%@'", _fileName]; 367 | @throw [[ZipException alloc] initWithError:err reason:reason]; 368 | } 369 | 370 | NSString *fileNameInZip= [NSString stringWithCString:filename_inzip encoding:NSUTF8StringEncoding]; 371 | 372 | err= unzOpenCurrentFilePassword(_unzFile, [password cStringUsingEncoding:NSUTF8StringEncoding]); 373 | if (err != UNZ_OK) { 374 | NSString *reason= [NSString stringWithFormat:@"Error in opening current file in '%@'", _fileName]; 375 | @throw [[ZipException alloc] initWithError:err reason:reason]; 376 | } 377 | 378 | return [[ZipReadStream alloc] initWithUnzFileStruct:_unzFile fileNameInZip:fileNameInZip]; 379 | } 380 | 381 | - (void) close { 382 | switch (_mode) { 383 | case ZipFileModeUnzip: { 384 | int err= unzClose(_unzFile); 385 | if (err != UNZ_OK) { 386 | NSString *reason= [NSString stringWithFormat:@"Error in closing '%@'", _fileName]; 387 | @throw [[ZipException alloc] initWithError:err reason:reason]; 388 | } 389 | break; 390 | } 391 | 392 | case ZipFileModeCreate: { 393 | int err= zipClose(_zipFile, NULL); 394 | if (err != ZIP_OK) { 395 | NSString *reason= [NSString stringWithFormat:@"Error in closing '%@'", _fileName]; 396 | @throw [[ZipException alloc] initWithError:err reason:reason]; 397 | } 398 | break; 399 | } 400 | 401 | case ZipFileModeAppend: { 402 | int err= zipClose(_zipFile, NULL); 403 | if (err != ZIP_OK) { 404 | NSString *reason= [NSString stringWithFormat:@"Error in closing '%@'", _fileName]; 405 | @throw [[ZipException alloc] initWithError:err reason:reason]; 406 | } 407 | break; 408 | } 409 | 410 | default: { 411 | NSString *reason= [NSString stringWithFormat:@"Unknown mode %d", _mode]; 412 | @throw [[ZipException alloc] initWithReason:reason]; 413 | } 414 | } 415 | } 416 | 417 | 418 | @end 419 | -------------------------------------------------------------------------------- /KeyShareConsumer.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5540EDF91D0F2D3A002A585C /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 5540EDF81D0F2D3A002A585C /* Settings.bundle */; }; 11 | 5546A29F1ECB87B800C5050E /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 5546A28C1ECB87B800C5050E /* ioapi.c */; }; 12 | 5546A2A01ECB87B800C5050E /* mztools.c in Sources */ = {isa = PBXBuildFile; fileRef = 5546A28E1ECB87B800C5050E /* mztools.c */; }; 13 | 5546A2A11ECB87B800C5050E /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 5546A2901ECB87B800C5050E /* unzip.c */; }; 14 | 5546A2A21ECB87B800C5050E /* zip.c in Sources */ = {isa = PBXBuildFile; fileRef = 5546A2921ECB87B800C5050E /* zip.c */; }; 15 | 5546A2A31ECB87B800C5050E /* FileInZipInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 5546A2961ECB87B800C5050E /* FileInZipInfo.m */; }; 16 | 5546A2A41ECB87B800C5050E /* ZipException.m in Sources */ = {isa = PBXBuildFile; fileRef = 5546A2981ECB87B800C5050E /* ZipException.m */; }; 17 | 5546A2A51ECB87B800C5050E /* ZipFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 5546A29A1ECB87B800C5050E /* ZipFile.m */; }; 18 | 5546A2A61ECB87B800C5050E /* ZipReadStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 5546A29C1ECB87B800C5050E /* ZipReadStream.m */; }; 19 | 5546A2A71ECB87B800C5050E /* ZipWriteStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 5546A29E1ECB87B800C5050E /* ZipWriteStream.m */; }; 20 | 5546A2AA1ECB87E300C5050E /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 5546A2A91ECB87E300C5050E /* libz.tbd */; }; 21 | 556911551BED585D00F670C3 /* KeyChainDataSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 556911521BED585D00F670C3 /* KeyChainDataSource.mm */; }; 22 | 556911561BED585D00F670C3 /* KeyDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 556911541BED585D00F670C3 /* KeyDetailViewController.m */; }; 23 | 55FE83131B6BB72B0072DCCD /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 55FE83121B6BB72B0072DCCD /* main.m */; }; 24 | 55FE83161B6BB72B0072DCCD /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 55FE83151B6BB72B0072DCCD /* AppDelegate.m */; }; 25 | 55FE83191B6BB72B0072DCCD /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 55FE83181B6BB72B0072DCCD /* ViewController.m */; }; 26 | 55FE831C1B6BB72B0072DCCD /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 55FE831A1B6BB72B0072DCCD /* Main.storyboard */; }; 27 | 55FE831E1B6BB72B0072DCCD /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 55FE831D1B6BB72B0072DCCD /* Images.xcassets */; }; 28 | 55FE83211B6BB72B0072DCCD /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 55FE831F1B6BB72B0072DCCD /* LaunchScreen.xib */; }; 29 | 55FE832D1B6BB72B0072DCCD /* KeyShareConsumerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 55FE832C1B6BB72B0072DCCD /* KeyShareConsumerTests.m */; }; 30 | /* End PBXBuildFile section */ 31 | 32 | /* Begin PBXContainerItemProxy section */ 33 | 55FE83271B6BB72B0072DCCD /* PBXContainerItemProxy */ = { 34 | isa = PBXContainerItemProxy; 35 | containerPortal = 55FE83051B6BB72B0072DCCD /* Project object */; 36 | proxyType = 1; 37 | remoteGlobalIDString = 55FE830C1B6BB72B0072DCCD; 38 | remoteInfo = KeyShareConsumer; 39 | }; 40 | /* End PBXContainerItemProxy section */ 41 | 42 | /* Begin PBXFileReference section */ 43 | 55016C501B6F99BB00CFBF56 /* KeyShareConsumer.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = KeyShareConsumer.entitlements; sourceTree = ""; }; 44 | 5540EDF81D0F2D3A002A585C /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; 45 | 5546A28C1ECB87B800C5050E /* ioapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioapi.c; sourceTree = ""; }; 46 | 5546A28D1ECB87B800C5050E /* ioapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioapi.h; sourceTree = ""; }; 47 | 5546A28E1ECB87B800C5050E /* mztools.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mztools.c; sourceTree = ""; }; 48 | 5546A28F1ECB87B800C5050E /* mztools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mztools.h; sourceTree = ""; }; 49 | 5546A2901ECB87B800C5050E /* unzip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unzip.c; sourceTree = ""; }; 50 | 5546A2911ECB87B800C5050E /* unzip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unzip.h; sourceTree = ""; }; 51 | 5546A2921ECB87B800C5050E /* zip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip.c; sourceTree = ""; }; 52 | 5546A2931ECB87B800C5050E /* zip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zip.h; sourceTree = ""; }; 53 | 5546A2951ECB87B800C5050E /* FileInZipInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileInZipInfo.h; sourceTree = ""; }; 54 | 5546A2961ECB87B800C5050E /* FileInZipInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FileInZipInfo.m; sourceTree = ""; }; 55 | 5546A2971ECB87B800C5050E /* ZipException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZipException.h; sourceTree = ""; }; 56 | 5546A2981ECB87B800C5050E /* ZipException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZipException.m; sourceTree = ""; }; 57 | 5546A2991ECB87B800C5050E /* ZipFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZipFile.h; sourceTree = ""; }; 58 | 5546A29A1ECB87B800C5050E /* ZipFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZipFile.m; sourceTree = ""; }; 59 | 5546A29B1ECB87B800C5050E /* ZipReadStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZipReadStream.h; sourceTree = ""; }; 60 | 5546A29C1ECB87B800C5050E /* ZipReadStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZipReadStream.m; sourceTree = ""; }; 61 | 5546A29D1ECB87B800C5050E /* ZipWriteStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZipWriteStream.h; sourceTree = ""; }; 62 | 5546A29E1ECB87B800C5050E /* ZipWriteStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZipWriteStream.m; sourceTree = ""; }; 63 | 5546A2A91ECB87E300C5050E /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 64 | 556911511BED585D00F670C3 /* KeyChainDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyChainDataSource.h; sourceTree = ""; }; 65 | 556911521BED585D00F670C3 /* KeyChainDataSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyChainDataSource.mm; sourceTree = ""; }; 66 | 556911531BED585D00F670C3 /* KeyDetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyDetailViewController.h; sourceTree = ""; }; 67 | 556911541BED585D00F670C3 /* KeyDetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KeyDetailViewController.m; sourceTree = ""; }; 68 | 55FE830D1B6BB72B0072DCCD /* KeyShareConsumer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KeyShareConsumer.app; sourceTree = BUILT_PRODUCTS_DIR; }; 69 | 55FE83111B6BB72B0072DCCD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 70 | 55FE83121B6BB72B0072DCCD /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 71 | 55FE83141B6BB72B0072DCCD /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 72 | 55FE83151B6BB72B0072DCCD /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 73 | 55FE83171B6BB72B0072DCCD /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 74 | 55FE83181B6BB72B0072DCCD /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 75 | 55FE831B1B6BB72B0072DCCD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 76 | 55FE831D1B6BB72B0072DCCD /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 77 | 55FE83201B6BB72B0072DCCD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 78 | 55FE83261B6BB72B0072DCCD /* KeyShareConsumerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KeyShareConsumerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 79 | 55FE832B1B6BB72B0072DCCD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 80 | 55FE832C1B6BB72B0072DCCD /* KeyShareConsumerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeyShareConsumerTests.m; sourceTree = ""; }; 81 | /* End PBXFileReference section */ 82 | 83 | /* Begin PBXFrameworksBuildPhase section */ 84 | 55FE830A1B6BB72B0072DCCD /* Frameworks */ = { 85 | isa = PBXFrameworksBuildPhase; 86 | buildActionMask = 2147483647; 87 | files = ( 88 | 5546A2AA1ECB87E300C5050E /* libz.tbd in Frameworks */, 89 | ); 90 | runOnlyForDeploymentPostprocessing = 0; 91 | }; 92 | 55FE83231B6BB72B0072DCCD /* Frameworks */ = { 93 | isa = PBXFrameworksBuildPhase; 94 | buildActionMask = 2147483647; 95 | files = ( 96 | ); 97 | runOnlyForDeploymentPostprocessing = 0; 98 | }; 99 | /* End PBXFrameworksBuildPhase section */ 100 | 101 | /* Begin PBXGroup section */ 102 | 5546A28B1ECB87B800C5050E /* MiniZip */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 5546A28C1ECB87B800C5050E /* ioapi.c */, 106 | 5546A28D1ECB87B800C5050E /* ioapi.h */, 107 | 5546A28E1ECB87B800C5050E /* mztools.c */, 108 | 5546A28F1ECB87B800C5050E /* mztools.h */, 109 | 5546A2901ECB87B800C5050E /* unzip.c */, 110 | 5546A2911ECB87B800C5050E /* unzip.h */, 111 | 5546A2921ECB87B800C5050E /* zip.c */, 112 | 5546A2931ECB87B800C5050E /* zip.h */, 113 | ); 114 | path = MiniZip; 115 | sourceTree = ""; 116 | }; 117 | 5546A2941ECB87B800C5050E /* Objective-Zip */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 5546A2951ECB87B800C5050E /* FileInZipInfo.h */, 121 | 5546A2961ECB87B800C5050E /* FileInZipInfo.m */, 122 | 5546A2971ECB87B800C5050E /* ZipException.h */, 123 | 5546A2981ECB87B800C5050E /* ZipException.m */, 124 | 5546A2991ECB87B800C5050E /* ZipFile.h */, 125 | 5546A29A1ECB87B800C5050E /* ZipFile.m */, 126 | 5546A29B1ECB87B800C5050E /* ZipReadStream.h */, 127 | 5546A29C1ECB87B800C5050E /* ZipReadStream.m */, 128 | 5546A29D1ECB87B800C5050E /* ZipWriteStream.h */, 129 | 5546A29E1ECB87B800C5050E /* ZipWriteStream.m */, 130 | ); 131 | path = "Objective-Zip"; 132 | sourceTree = ""; 133 | }; 134 | 5546A2A81ECB87E300C5050E /* Frameworks */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | 5546A2A91ECB87E300C5050E /* libz.tbd */, 138 | ); 139 | name = Frameworks; 140 | sourceTree = ""; 141 | }; 142 | 55FE83041B6BB72B0072DCCD = { 143 | isa = PBXGroup; 144 | children = ( 145 | 55FE830F1B6BB72B0072DCCD /* KeyShareConsumer */, 146 | 55FE83291B6BB72B0072DCCD /* KeyShareConsumerTests */, 147 | 55FE830E1B6BB72B0072DCCD /* Products */, 148 | 5546A2A81ECB87E300C5050E /* Frameworks */, 149 | ); 150 | sourceTree = ""; 151 | }; 152 | 55FE830E1B6BB72B0072DCCD /* Products */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | 55FE830D1B6BB72B0072DCCD /* KeyShareConsumer.app */, 156 | 55FE83261B6BB72B0072DCCD /* KeyShareConsumerTests.xctest */, 157 | ); 158 | name = Products; 159 | sourceTree = ""; 160 | }; 161 | 55FE830F1B6BB72B0072DCCD /* KeyShareConsumer */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | 5546A28B1ECB87B800C5050E /* MiniZip */, 165 | 5546A2941ECB87B800C5050E /* Objective-Zip */, 166 | 5540EDF81D0F2D3A002A585C /* Settings.bundle */, 167 | 556911511BED585D00F670C3 /* KeyChainDataSource.h */, 168 | 556911521BED585D00F670C3 /* KeyChainDataSource.mm */, 169 | 556911531BED585D00F670C3 /* KeyDetailViewController.h */, 170 | 556911541BED585D00F670C3 /* KeyDetailViewController.m */, 171 | 55016C501B6F99BB00CFBF56 /* KeyShareConsumer.entitlements */, 172 | 55FE83141B6BB72B0072DCCD /* AppDelegate.h */, 173 | 55FE83151B6BB72B0072DCCD /* AppDelegate.m */, 174 | 55FE83171B6BB72B0072DCCD /* ViewController.h */, 175 | 55FE83181B6BB72B0072DCCD /* ViewController.m */, 176 | 55FE831A1B6BB72B0072DCCD /* Main.storyboard */, 177 | 55FE831D1B6BB72B0072DCCD /* Images.xcassets */, 178 | 55FE831F1B6BB72B0072DCCD /* LaunchScreen.xib */, 179 | 55FE83101B6BB72B0072DCCD /* Supporting Files */, 180 | ); 181 | path = KeyShareConsumer; 182 | sourceTree = ""; 183 | }; 184 | 55FE83101B6BB72B0072DCCD /* Supporting Files */ = { 185 | isa = PBXGroup; 186 | children = ( 187 | 55FE83111B6BB72B0072DCCD /* Info.plist */, 188 | 55FE83121B6BB72B0072DCCD /* main.m */, 189 | ); 190 | name = "Supporting Files"; 191 | sourceTree = ""; 192 | }; 193 | 55FE83291B6BB72B0072DCCD /* KeyShareConsumerTests */ = { 194 | isa = PBXGroup; 195 | children = ( 196 | 55FE832C1B6BB72B0072DCCD /* KeyShareConsumerTests.m */, 197 | 55FE832A1B6BB72B0072DCCD /* Supporting Files */, 198 | ); 199 | path = KeyShareConsumerTests; 200 | sourceTree = ""; 201 | }; 202 | 55FE832A1B6BB72B0072DCCD /* Supporting Files */ = { 203 | isa = PBXGroup; 204 | children = ( 205 | 55FE832B1B6BB72B0072DCCD /* Info.plist */, 206 | ); 207 | name = "Supporting Files"; 208 | sourceTree = ""; 209 | }; 210 | /* End PBXGroup section */ 211 | 212 | /* Begin PBXNativeTarget section */ 213 | 55FE830C1B6BB72B0072DCCD /* KeyShareConsumer */ = { 214 | isa = PBXNativeTarget; 215 | buildConfigurationList = 55FE83301B6BB72B0072DCCD /* Build configuration list for PBXNativeTarget "KeyShareConsumer" */; 216 | buildPhases = ( 217 | 55FE83091B6BB72B0072DCCD /* Sources */, 218 | 55FE830A1B6BB72B0072DCCD /* Frameworks */, 219 | 55FE830B1B6BB72B0072DCCD /* Resources */, 220 | ); 221 | buildRules = ( 222 | ); 223 | dependencies = ( 224 | ); 225 | name = KeyShareConsumer; 226 | productName = KeyShareConsumer; 227 | productReference = 55FE830D1B6BB72B0072DCCD /* KeyShareConsumer.app */; 228 | productType = "com.apple.product-type.application"; 229 | }; 230 | 55FE83251B6BB72B0072DCCD /* KeyShareConsumerTests */ = { 231 | isa = PBXNativeTarget; 232 | buildConfigurationList = 55FE83331B6BB72B0072DCCD /* Build configuration list for PBXNativeTarget "KeyShareConsumerTests" */; 233 | buildPhases = ( 234 | 55FE83221B6BB72B0072DCCD /* Sources */, 235 | 55FE83231B6BB72B0072DCCD /* Frameworks */, 236 | 55FE83241B6BB72B0072DCCD /* Resources */, 237 | ); 238 | buildRules = ( 239 | ); 240 | dependencies = ( 241 | 55FE83281B6BB72B0072DCCD /* PBXTargetDependency */, 242 | ); 243 | name = KeyShareConsumerTests; 244 | productName = KeyShareConsumerTests; 245 | productReference = 55FE83261B6BB72B0072DCCD /* KeyShareConsumerTests.xctest */; 246 | productType = "com.apple.product-type.bundle.unit-test"; 247 | }; 248 | /* End PBXNativeTarget section */ 249 | 250 | /* Begin PBXProject section */ 251 | 55FE83051B6BB72B0072DCCD /* Project object */ = { 252 | isa = PBXProject; 253 | attributes = { 254 | LastUpgradeCheck = 0710; 255 | ORGANIZATIONNAME = "Red Hound Software, Inc."; 256 | TargetAttributes = { 257 | 55FE830C1B6BB72B0072DCCD = { 258 | CreatedOnToolsVersion = 6.1.1; 259 | DevelopmentTeam = M355KP63QV; 260 | SystemCapabilities = { 261 | com.apple.iCloud = { 262 | enabled = 1; 263 | }; 264 | }; 265 | }; 266 | 55FE83251B6BB72B0072DCCD = { 267 | CreatedOnToolsVersion = 6.1.1; 268 | DevelopmentTeam = M355KP63QV; 269 | TestTargetID = 55FE830C1B6BB72B0072DCCD; 270 | }; 271 | }; 272 | }; 273 | buildConfigurationList = 55FE83081B6BB72B0072DCCD /* Build configuration list for PBXProject "KeyShareConsumer" */; 274 | compatibilityVersion = "Xcode 3.2"; 275 | developmentRegion = English; 276 | hasScannedForEncodings = 0; 277 | knownRegions = ( 278 | English, 279 | en, 280 | Base, 281 | ); 282 | mainGroup = 55FE83041B6BB72B0072DCCD; 283 | productRefGroup = 55FE830E1B6BB72B0072DCCD /* Products */; 284 | projectDirPath = ""; 285 | projectRoot = ""; 286 | targets = ( 287 | 55FE830C1B6BB72B0072DCCD /* KeyShareConsumer */, 288 | 55FE83251B6BB72B0072DCCD /* KeyShareConsumerTests */, 289 | ); 290 | }; 291 | /* End PBXProject section */ 292 | 293 | /* Begin PBXResourcesBuildPhase section */ 294 | 55FE830B1B6BB72B0072DCCD /* Resources */ = { 295 | isa = PBXResourcesBuildPhase; 296 | buildActionMask = 2147483647; 297 | files = ( 298 | 5540EDF91D0F2D3A002A585C /* Settings.bundle in Resources */, 299 | 55FE831C1B6BB72B0072DCCD /* Main.storyboard in Resources */, 300 | 55FE83211B6BB72B0072DCCD /* LaunchScreen.xib in Resources */, 301 | 55FE831E1B6BB72B0072DCCD /* Images.xcassets in Resources */, 302 | ); 303 | runOnlyForDeploymentPostprocessing = 0; 304 | }; 305 | 55FE83241B6BB72B0072DCCD /* Resources */ = { 306 | isa = PBXResourcesBuildPhase; 307 | buildActionMask = 2147483647; 308 | files = ( 309 | ); 310 | runOnlyForDeploymentPostprocessing = 0; 311 | }; 312 | /* End PBXResourcesBuildPhase section */ 313 | 314 | /* Begin PBXSourcesBuildPhase section */ 315 | 55FE83091B6BB72B0072DCCD /* Sources */ = { 316 | isa = PBXSourcesBuildPhase; 317 | buildActionMask = 2147483647; 318 | files = ( 319 | 5546A29F1ECB87B800C5050E /* ioapi.c in Sources */, 320 | 5546A2A71ECB87B800C5050E /* ZipWriteStream.m in Sources */, 321 | 55FE83191B6BB72B0072DCCD /* ViewController.m in Sources */, 322 | 5546A2A41ECB87B800C5050E /* ZipException.m in Sources */, 323 | 5546A2A31ECB87B800C5050E /* FileInZipInfo.m in Sources */, 324 | 55FE83161B6BB72B0072DCCD /* AppDelegate.m in Sources */, 325 | 5546A2A21ECB87B800C5050E /* zip.c in Sources */, 326 | 556911551BED585D00F670C3 /* KeyChainDataSource.mm in Sources */, 327 | 5546A2A01ECB87B800C5050E /* mztools.c in Sources */, 328 | 55FE83131B6BB72B0072DCCD /* main.m in Sources */, 329 | 5546A2A61ECB87B800C5050E /* ZipReadStream.m in Sources */, 330 | 5546A2A11ECB87B800C5050E /* unzip.c in Sources */, 331 | 556911561BED585D00F670C3 /* KeyDetailViewController.m in Sources */, 332 | 5546A2A51ECB87B800C5050E /* ZipFile.m in Sources */, 333 | ); 334 | runOnlyForDeploymentPostprocessing = 0; 335 | }; 336 | 55FE83221B6BB72B0072DCCD /* Sources */ = { 337 | isa = PBXSourcesBuildPhase; 338 | buildActionMask = 2147483647; 339 | files = ( 340 | 55FE832D1B6BB72B0072DCCD /* KeyShareConsumerTests.m in Sources */, 341 | ); 342 | runOnlyForDeploymentPostprocessing = 0; 343 | }; 344 | /* End PBXSourcesBuildPhase section */ 345 | 346 | /* Begin PBXTargetDependency section */ 347 | 55FE83281B6BB72B0072DCCD /* PBXTargetDependency */ = { 348 | isa = PBXTargetDependency; 349 | target = 55FE830C1B6BB72B0072DCCD /* KeyShareConsumer */; 350 | targetProxy = 55FE83271B6BB72B0072DCCD /* PBXContainerItemProxy */; 351 | }; 352 | /* End PBXTargetDependency section */ 353 | 354 | /* Begin PBXVariantGroup section */ 355 | 55FE831A1B6BB72B0072DCCD /* Main.storyboard */ = { 356 | isa = PBXVariantGroup; 357 | children = ( 358 | 55FE831B1B6BB72B0072DCCD /* Base */, 359 | ); 360 | name = Main.storyboard; 361 | sourceTree = ""; 362 | }; 363 | 55FE831F1B6BB72B0072DCCD /* LaunchScreen.xib */ = { 364 | isa = PBXVariantGroup; 365 | children = ( 366 | 55FE83201B6BB72B0072DCCD /* Base */, 367 | ); 368 | name = LaunchScreen.xib; 369 | sourceTree = ""; 370 | }; 371 | /* End PBXVariantGroup section */ 372 | 373 | /* Begin XCBuildConfiguration section */ 374 | 55FE832E1B6BB72B0072DCCD /* Debug */ = { 375 | isa = XCBuildConfiguration; 376 | buildSettings = { 377 | ALWAYS_SEARCH_USER_PATHS = NO; 378 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 379 | CLANG_CXX_LIBRARY = "libc++"; 380 | CLANG_ENABLE_MODULES = YES; 381 | CLANG_ENABLE_OBJC_ARC = YES; 382 | CLANG_WARN_BOOL_CONVERSION = YES; 383 | CLANG_WARN_CONSTANT_CONVERSION = YES; 384 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 385 | CLANG_WARN_EMPTY_BODY = YES; 386 | CLANG_WARN_ENUM_CONVERSION = YES; 387 | CLANG_WARN_INT_CONVERSION = YES; 388 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 389 | CLANG_WARN_UNREACHABLE_CODE = YES; 390 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 391 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 392 | COPY_PHASE_STRIP = NO; 393 | ENABLE_STRICT_OBJC_MSGSEND = YES; 394 | ENABLE_TESTABILITY = YES; 395 | GCC_C_LANGUAGE_STANDARD = gnu99; 396 | GCC_DYNAMIC_NO_PIC = NO; 397 | GCC_OPTIMIZATION_LEVEL = 0; 398 | GCC_PREPROCESSOR_DEFINITIONS = ( 399 | "DEBUG=1", 400 | "$(inherited)", 401 | ); 402 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 403 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 404 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 405 | GCC_WARN_UNDECLARED_SELECTOR = YES; 406 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 407 | GCC_WARN_UNUSED_FUNCTION = YES; 408 | GCC_WARN_UNUSED_VARIABLE = YES; 409 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 410 | MTL_ENABLE_DEBUG_INFO = YES; 411 | ONLY_ACTIVE_ARCH = NO; 412 | SDKROOT = iphoneos; 413 | TARGETED_DEVICE_FAMILY = "1,2"; 414 | }; 415 | name = Debug; 416 | }; 417 | 55FE832F1B6BB72B0072DCCD /* Release */ = { 418 | isa = XCBuildConfiguration; 419 | buildSettings = { 420 | ALWAYS_SEARCH_USER_PATHS = NO; 421 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 422 | CLANG_CXX_LIBRARY = "libc++"; 423 | CLANG_ENABLE_MODULES = YES; 424 | CLANG_ENABLE_OBJC_ARC = YES; 425 | CLANG_WARN_BOOL_CONVERSION = YES; 426 | CLANG_WARN_CONSTANT_CONVERSION = YES; 427 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 428 | CLANG_WARN_EMPTY_BODY = YES; 429 | CLANG_WARN_ENUM_CONVERSION = YES; 430 | CLANG_WARN_INT_CONVERSION = YES; 431 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 432 | CLANG_WARN_UNREACHABLE_CODE = YES; 433 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 434 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 435 | COPY_PHASE_STRIP = YES; 436 | ENABLE_NS_ASSERTIONS = NO; 437 | ENABLE_STRICT_OBJC_MSGSEND = YES; 438 | GCC_C_LANGUAGE_STANDARD = gnu99; 439 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 440 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 441 | GCC_WARN_UNDECLARED_SELECTOR = YES; 442 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 443 | GCC_WARN_UNUSED_FUNCTION = YES; 444 | GCC_WARN_UNUSED_VARIABLE = YES; 445 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 446 | MTL_ENABLE_DEBUG_INFO = NO; 447 | SDKROOT = iphoneos; 448 | TARGETED_DEVICE_FAMILY = "1,2"; 449 | VALIDATE_PRODUCT = YES; 450 | }; 451 | name = Release; 452 | }; 453 | 55FE83311B6BB72B0072DCCD /* Debug */ = { 454 | isa = XCBuildConfiguration; 455 | buildSettings = { 456 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 457 | CODE_SIGN_ENTITLEMENTS = KeyShareConsumer/KeyShareConsumer.entitlements; 458 | CODE_SIGN_IDENTITY = "iPhone Developer"; 459 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 460 | DEVELOPMENT_TEAM = M355KP63QV; 461 | INFOPLIST_FILE = KeyShareConsumer/Info.plist; 462 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 463 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 464 | PRODUCT_BUNDLE_IDENTIFIER = "red.hound.custom-app.KeyShareConsumer"; 465 | PRODUCT_NAME = "$(TARGET_NAME)"; 466 | PROVISIONING_PROFILE = ""; 467 | VALID_ARCHS = "arm64 armv7"; 468 | }; 469 | name = Debug; 470 | }; 471 | 55FE83321B6BB72B0072DCCD /* Release */ = { 472 | isa = XCBuildConfiguration; 473 | buildSettings = { 474 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 475 | CODE_SIGN_ENTITLEMENTS = KeyShareConsumer/KeyShareConsumer.entitlements; 476 | CODE_SIGN_IDENTITY = "iPhone Developer"; 477 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 478 | DEVELOPMENT_TEAM = M355KP63QV; 479 | INFOPLIST_FILE = KeyShareConsumer/Info.plist; 480 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 481 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 482 | PRODUCT_BUNDLE_IDENTIFIER = "red.hound.custom-app.KeyShareConsumer"; 483 | PRODUCT_NAME = "$(TARGET_NAME)"; 484 | PROVISIONING_PROFILE = ""; 485 | VALID_ARCHS = "arm64 armv7"; 486 | }; 487 | name = Release; 488 | }; 489 | 55FE83341B6BB72B0072DCCD /* Debug */ = { 490 | isa = XCBuildConfiguration; 491 | buildSettings = { 492 | BUNDLE_LOADER = "$(TEST_HOST)"; 493 | DEVELOPMENT_TEAM = M355KP63QV; 494 | FRAMEWORK_SEARCH_PATHS = ( 495 | "$(SDKROOT)/Developer/Library/Frameworks", 496 | "$(inherited)", 497 | ); 498 | GCC_PREPROCESSOR_DEFINITIONS = ( 499 | "DEBUG=1", 500 | "$(inherited)", 501 | ); 502 | INFOPLIST_FILE = KeyShareConsumerTests/Info.plist; 503 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 504 | ONLY_ACTIVE_ARCH = YES; 505 | PRODUCT_BUNDLE_IDENTIFIER = "red.hound.$(PRODUCT_NAME:rfc1034identifier)"; 506 | PRODUCT_NAME = "$(TARGET_NAME)"; 507 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/KeyShareConsumer.app/KeyShareConsumer"; 508 | VALID_ARCHS = "arm64 armv7"; 509 | }; 510 | name = Debug; 511 | }; 512 | 55FE83351B6BB72B0072DCCD /* Release */ = { 513 | isa = XCBuildConfiguration; 514 | buildSettings = { 515 | BUNDLE_LOADER = "$(TEST_HOST)"; 516 | DEVELOPMENT_TEAM = M355KP63QV; 517 | FRAMEWORK_SEARCH_PATHS = ( 518 | "$(SDKROOT)/Developer/Library/Frameworks", 519 | "$(inherited)", 520 | ); 521 | INFOPLIST_FILE = KeyShareConsumerTests/Info.plist; 522 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 523 | PRODUCT_BUNDLE_IDENTIFIER = "red.hound.$(PRODUCT_NAME:rfc1034identifier)"; 524 | PRODUCT_NAME = "$(TARGET_NAME)"; 525 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/KeyShareConsumer.app/KeyShareConsumer"; 526 | VALID_ARCHS = "arm64 armv7"; 527 | }; 528 | name = Release; 529 | }; 530 | /* End XCBuildConfiguration section */ 531 | 532 | /* Begin XCConfigurationList section */ 533 | 55FE83081B6BB72B0072DCCD /* Build configuration list for PBXProject "KeyShareConsumer" */ = { 534 | isa = XCConfigurationList; 535 | buildConfigurations = ( 536 | 55FE832E1B6BB72B0072DCCD /* Debug */, 537 | 55FE832F1B6BB72B0072DCCD /* Release */, 538 | ); 539 | defaultConfigurationIsVisible = 0; 540 | defaultConfigurationName = Release; 541 | }; 542 | 55FE83301B6BB72B0072DCCD /* Build configuration list for PBXNativeTarget "KeyShareConsumer" */ = { 543 | isa = XCConfigurationList; 544 | buildConfigurations = ( 545 | 55FE83311B6BB72B0072DCCD /* Debug */, 546 | 55FE83321B6BB72B0072DCCD /* Release */, 547 | ); 548 | defaultConfigurationIsVisible = 0; 549 | defaultConfigurationName = Release; 550 | }; 551 | 55FE83331B6BB72B0072DCCD /* Build configuration list for PBXNativeTarget "KeyShareConsumerTests" */ = { 552 | isa = XCConfigurationList; 553 | buildConfigurations = ( 554 | 55FE83341B6BB72B0072DCCD /* Debug */, 555 | 55FE83351B6BB72B0072DCCD /* Release */, 556 | ); 557 | defaultConfigurationIsVisible = 0; 558 | defaultConfigurationName = Release; 559 | }; 560 | /* End XCConfigurationList section */ 561 | }; 562 | rootObject = 55FE83051B6BB72B0072DCCD /* Project object */; 563 | } 564 | -------------------------------------------------------------------------------- /KeyShareConsumer/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // KeyShareConsumer 4 | 5 | #import "ViewController.h" 6 | #import 7 | #import "KeyDetailViewController.h" 8 | #import 9 | 10 | #import "ZipFile.h" 11 | #import "FileInZipInfo.h" 12 | #import "ZipReadStream.h" 13 | 14 | @interface ViewController () 15 | @end 16 | 17 | @implementation ViewController 18 | @synthesize tableViewKeyChain; 19 | @synthesize keyChain; 20 | 21 | //------------------------------------------------------------------------------ 22 | #pragma mark - View controller functions 23 | //------------------------------------------------------------------------------ 24 | - (void)viewDidLoad 25 | { 26 | [super viewDidLoad]; 27 | 28 | //Set this class as the table delegate 29 | [tableViewKeyChain setDelegate:self]; 30 | 31 | //Create a key chain data source object targeting identities 32 | keyChain = [[KeyChainDataSource alloc] initWithMode:KSM_Identities]; 33 | 34 | //load the key chain to serve as backend for the table view 35 | [keyChain LoadKeyChainContents]; 36 | } 37 | 38 | - (void)didReceiveMemoryWarning 39 | { 40 | [super didReceiveMemoryWarning]; 41 | // Dispose of any resources that can be recreated. 42 | } 43 | 44 | //------------------------------------------------------------------------------ 45 | #pragma mark - Button click handlers 46 | //------------------------------------------------------------------------------ 47 | - (IBAction)openImportDocumentPicker:(id)sender 48 | { 49 | //Clear the pasteboard, since a password may be provided via that mechanism 50 | //UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; 51 | //[pasteboard setString:@""]; 52 | //passwordFromUser = @""; 53 | 54 | NSUserDefaults* standardDefaults = [NSUserDefaults standardUserDefaults]; 55 | [standardDefaults synchronize]; 56 | 57 | NSMutableArray* utis = [[NSMutableArray alloc]init]; 58 | 59 | if([standardDefaults boolForKey:@"toggle_com_rsa_pkcs12"]) 60 | [utis addObject:@"com.rsa.pkcs-12"]; 61 | if([standardDefaults boolForKey:@"toggle_purebred_select_all"]) 62 | [utis addObject:@"purebred.select.all"]; 63 | if([standardDefaults boolForKey:@"toggle_purebred_select_all_user"]) 64 | [utis addObject:@"purebred.select.all_user"]; 65 | if([standardDefaults boolForKey:@"toggle_purebred_select_all-user"]) 66 | [utis addObject:@"purebred.select.all-user"]; 67 | if([standardDefaults boolForKey:@"toggle_purebred_select_signature"]) 68 | [utis addObject:@"purebred.select.signature"]; 69 | if([standardDefaults boolForKey:@"toggle_purebred_select_encryption"]) 70 | [utis addObject:@"purebred.select.encryption"]; 71 | if([standardDefaults boolForKey:@"toggle_purebred_select_authentication"]) 72 | [utis addObject:@"purebred.select.authentication"]; 73 | if([standardDefaults boolForKey:@"toggle_purebred_select_device"]) 74 | [utis addObject:@"purebred.select.device"]; 75 | if([standardDefaults boolForKey:@"toggle_purebred_select_no_filter"]) 76 | [utis addObject:@"purebred.select.no_filter"]; 77 | if([standardDefaults boolForKey:@"toggle_purebred_select_no-filter"]) 78 | [utis addObject:@"purebred.select.no-filter"]; 79 | if([standardDefaults boolForKey:@"toggle_purebred_select_no-filter"]) 80 | [utis addObject:@"purebred.select.no-filter"]; 81 | if([standardDefaults boolForKey:@"toggle_purebred_select_no-filter"]) 82 | [utis addObject:@"purebred.select.no-filter"]; 83 | if([standardDefaults boolForKey:@"toggle_purebred_zip_all"]) 84 | [utis addObject:@"purebred.zip.all"]; 85 | if([standardDefaults boolForKey:@"toggle_purebred_zip_all_user"]) 86 | [utis addObject:@"purebred.zip.all_user"]; 87 | if([standardDefaults boolForKey:@"toggle_purebred_zip_all-user"]) 88 | [utis addObject:@"purebred.zip.all-user"]; 89 | if([standardDefaults boolForKey:@"toggle_purebred_zip_signature"]) 90 | [utis addObject:@"purebred.zip.signature"]; 91 | if([standardDefaults boolForKey:@"toggle_purebred_zip_encryption"]) 92 | [utis addObject:@"purebred.zip.encryption"]; 93 | if([standardDefaults boolForKey:@"toggle_purebred_zip_authentication"]) 94 | [utis addObject:@"purebred.zip.authentication"]; 95 | if([standardDefaults boolForKey:@"toggle_purebred_zip_device"]) 96 | [utis addObject:@"purebred.zip.device"]; 97 | if([standardDefaults boolForKey:@"toggle_purebred_zip_no_filter"]) 98 | [utis addObject:@"purebred.zip.no_filter"]; 99 | if([standardDefaults boolForKey:@"toggle_purebred_zip_no-filter"]) 100 | [utis addObject:@"purebred.zip.no-filter"]; 101 | 102 | if(0 == [utis count]) 103 | [utis addObject:@"com.rsa.pkcs-12"]; 104 | 105 | //Display the UIDocumentPickerViewController to enable the user to select a key to import. Purebred Registration only works with UIDocumentPickerModeOpen mode. 106 | UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:utis inMode:UIDocumentPickerModeOpen]; 107 | documentPicker.delegate = self; 108 | documentPicker.modalPresentationStyle = UIModalPresentationFormSheet; 109 | [self presentViewController:documentPicker animated:YES completion:nil]; 110 | } 111 | 112 | - (IBAction)clearKeyChain:(id)sender 113 | { 114 | [self resetKeychain]; 115 | [keyChain LoadKeyChainContents]; 116 | [[self tableViewKeyChain] reloadData]; 117 | } 118 | 119 | //------------------------------------------------------------------------------ 120 | #pragma mark - UIDocumentPickerViewController delegate functions 121 | //------------------------------------------------------------------------------ 122 | - (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller 123 | { 124 | NSLog(@"Cancelled"); 125 | } 126 | 127 | - (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray*)urls { 128 | NSURL* url = urls[0]; 129 | if(controller.documentPickerMode == UIDocumentPickerModeOpen) 130 | { 131 | BOOL startAccessingWorked = [url startAccessingSecurityScopedResource]; 132 | NSURL *ubiquityURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; 133 | NSLog(@"ubiquityURL %@",ubiquityURL); 134 | NSLog(@"start %d",startAccessingWorked); 135 | 136 | NSFileCoordinator *fileCoordinator = [[NSFileCoordinator alloc] init]; 137 | NSError *error; 138 | [fileCoordinator coordinateReadingItemAtURL:url options:0 error:&error byAccessor:^(NSURL *newURL) { 139 | NSData *data = [NSData dataWithContentsOfURL:newURL]; 140 | 141 | NSLog(@"error %@",error); 142 | NSLog(@"data %@",data); 143 | if(nil == data) 144 | return; 145 | 146 | // Read the password from the pasteboard 147 | UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; 148 | NSString* pw = [pasteboard string]; 149 | 150 | if(nil != pw && 0 != [pw length]) 151 | { 152 | passwordFromUser = pw; 153 | } 154 | 155 | pkcs12Data = data; 156 | }]; 157 | [url stopAccessingSecurityScopedResource]; 158 | 159 | if(nil == passwordFromUser || 0 == [passwordFromUser length]) 160 | { 161 | UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Enter Password" message:@"Please enter the password for the selected PKCS #12 file" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles: @"OK", nil]; 162 | alert.alertViewStyle = UIAlertViewStyleSecureTextInput; 163 | [alert show]; 164 | } 165 | else{ 166 | /* 167 | NSString* p12File = @"tmp.p12"; 168 | 169 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 170 | NSString *documentsDirectory = [paths objectAtIndex:0]; 171 | NSString *p12Path = [documentsDirectory stringByAppendingPathComponent:p12File]; 172 | 173 | NSLog(@"Password: %@", passwordFromUser); 174 | //Write the private key and certificate to a pair of files 175 | [pkcs12Data writeToFile:p12Path atomically:YES]; 176 | */ 177 | 178 | [self importP12:pkcs12Data password:passwordFromUser]; 179 | } 180 | } 181 | } 182 | 183 | //------------------------------------------------------------------------------ 184 | #pragma mark - Table view data source 185 | //------------------------------------------------------------------------------ 186 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 187 | { 188 | return 1; 189 | } 190 | 191 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 192 | { 193 | //The KeyChainDataSource is written to supply cells in groups where each group is an identity. 194 | //This view is written to list each identity on one row. Thus, return the number of sections 195 | //recognized by the data source. 196 | return [keyChain numItems]; 197 | } 198 | #define FONT_SIZE 14.0f 199 | #define CELL_CONTENT_MARGIN 10.0f 200 | 201 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath; 202 | { 203 | NSString *text = [keyChain GetIdentityNameAtIndex:indexPath.row]; 204 | 205 | CGRect frameRect = [tableView frame]; 206 | //CGSize constraint = CGSizeMake(frameRect.size.width - (CELL_CONTENT_MARGIN * 2), 20000.0f); 207 | 208 | //CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:NSLineBreakByCharWrapping]; 209 | 210 | NSAttributedString *attributedText = 211 | [[NSAttributedString alloc] 212 | initWithString:text 213 | attributes:@ 214 | { 215 | NSFontAttributeName: [UIFont systemFontOfSize:FONT_SIZE] 216 | }]; 217 | CGRect rect = [attributedText boundingRectWithSize:(CGSize){frameRect.size.width, CGFLOAT_MAX} 218 | options:NSStringDrawingUsesLineFragmentOrigin 219 | context:nil]; 220 | CGSize size = rect.size; 221 | 222 | CGFloat height = MAX(size.height, 44.0f); 223 | 224 | return height + (CELL_CONTENT_MARGIN * 2); 225 | } 226 | 227 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 228 | { 229 | static NSString *CellIdentifier = @"Cell"; 230 | 231 | UILabel* label = nil; 232 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 233 | if (cell == nil) 234 | { 235 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] ; 236 | 237 | label = [[UILabel alloc] initWithFrame:CGRectZero] ; 238 | [label setLineBreakMode:NSLineBreakByCharWrapping]; 239 | //[label setMinimumFontSize:FONT_SIZE]; 240 | [label setNumberOfLines:0]; 241 | [label setFont:[UIFont systemFontOfSize:FONT_SIZE]]; 242 | [label setTag:1]; 243 | 244 | [[cell contentView] addSubview:label]; 245 | 246 | } 247 | NSString *text = [keyChain GetIdentityNameAtIndex:indexPath.row]; 248 | 249 | CGRect frameRect = [tableView frame]; 250 | //CGSize constraint = CGSizeMake(frameRect.size.width - (CELL_CONTENT_MARGIN * 2), 20000.0f); 251 | 252 | //CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:NSLineBreakByCharWrapping]; 253 | 254 | NSAttributedString *attributedText = 255 | [[NSAttributedString alloc] 256 | initWithString:text 257 | attributes:@ 258 | { 259 | NSFontAttributeName: [UIFont systemFontOfSize:FONT_SIZE] 260 | }]; 261 | CGRect rect = [attributedText boundingRectWithSize:(CGSize){frameRect.size.width, CGFLOAT_MAX} 262 | options:NSStringDrawingUsesLineFragmentOrigin 263 | context:nil]; 264 | CGSize size = rect.size; 265 | 266 | if (!label) 267 | label = (UILabel*)[cell viewWithTag:1]; 268 | 269 | //display the keys icon for each entry in the table 270 | UIImage* image = [UIImage imageNamed:@"0155-keys.png"]; 271 | [cell.imageView setImage:image]; 272 | 273 | self.imageWidth = 44; 274 | 275 | [label setText:text]; 276 | [label setFrame:CGRectMake((CELL_CONTENT_MARGIN*2) + self.imageWidth, CELL_CONTENT_MARGIN, frameRect.size.width - (CELL_CONTENT_MARGIN * 2) - self.imageWidth, MAX(size.height, 44.0f))]; 277 | 278 | cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; 279 | 280 | return cell; 281 | } 282 | 283 | - (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView 284 | editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath 285 | { 286 | return UITableViewCellEditingStyleDelete; 287 | } 288 | 289 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 290 | { 291 | // If the table view is asking to commit a delete command... 292 | if (editingStyle == UITableViewCellEditingStyleDelete) 293 | { 294 | // We remove the row being deleted from the source 295 | [keyChain removeObjectAtIndex:[indexPath row]]; 296 | 297 | [tableView reloadData]; 298 | } 299 | } 300 | 301 | //------------------------------------------------------------------------------ 302 | #pragma mark - Table view delegate 303 | //------------------------------------------------------------------------------ 304 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 305 | { 306 | UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil]; 307 | KeyDetailViewController *kdvc = [storyboard instantiateViewControllerWithIdentifier:@"KeyDetailViewController"]; 308 | [kdvc setKeyChain:[self keyChain]]; 309 | [kdvc setItemIndex:indexPath.row]; 310 | [kdvc setDpvc:self]; 311 | [self presentViewController:kdvc animated:YES completion:nil]; 312 | } 313 | 314 | //------------------------------------------------------------------------------ 315 | #pragma mark - Callbacks used by KeyDetailViewController for iTunes file sharing 316 | //------------------------------------------------------------------------------ 317 | 318 | /** 319 | Called when "Share with iTunes" button is clicked on the KeyDetailViewController. 320 | */ 321 | - (void) import:(long)row 322 | { 323 | //Read the identity and private key for the indicated item using the KeyChainDataSource instance. 324 | SecIdentityRef identity = [keyChain GetIdentityAtIndex:row]; 325 | NSData* privateKeyBits = [keyChain GetPrivateKeyAtIndex:row]; 326 | 327 | //If either could not be read, display an error and return. 328 | if(nil == identity || nil == privateKeyBits) 329 | { 330 | UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Complete",nil) message:@"Fail to retrieve selected identity or private key" delegate:nil cancelButtonTitle:NSLocalizedString(@"Close",nil) otherButtonTitles:nil]; 331 | [alertView show]; 332 | 333 | return; 334 | } 335 | 336 | //Copy the certificate from the SecIdentityRef object 337 | SecCertificateRef cert = nil; 338 | OSStatus status = SecIdentityCopyCertificate(identity, &cert ); 339 | 340 | //If copy operation failed, display an error and return 341 | if(nil == cert || 0 != status) 342 | { 343 | UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Complete",nil) message:@"Fail to load certificate or private key" delegate:nil cancelButtonTitle:NSLocalizedString(@"Close",nil) otherButtonTitles:nil]; 344 | [alertView show]; 345 | 346 | return; 347 | } 348 | 349 | //Get the binary encoded representation of the certificate to write to a file 350 | NSData *decodedData = (__bridge_transfer NSData *) SecCertificateCopyData(cert); 351 | if(nil == decodedData) 352 | { 353 | UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Complete",nil) message:@"Fail to copy certificate data" delegate:nil cancelButtonTitle:NSLocalizedString(@"Close",nil) otherButtonTitles:nil]; 354 | [alertView show]; 355 | 356 | return; 357 | } 358 | 359 | //Get the destination folder for the files 360 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 361 | NSString *documentsDirectory = [paths objectAtIndex:0]; 362 | 363 | //Generate a file name using the sha1 hash of the certificate with .p8 extension for private key and .der for certificate 364 | NSString* hash = [self sha1:decodedData]; 365 | NSString* p8File = [hash stringByAppendingString:@".p8"]; 366 | NSString* derFile = [hash stringByAppendingString:@".der"]; 367 | NSString *p8Path = [documentsDirectory stringByAppendingPathComponent:p8File]; 368 | NSString *derPath = [documentsDirectory stringByAppendingPathComponent:derFile]; 369 | 370 | //Write the private key and certificate to a pair of files 371 | [privateKeyBits writeToFile:p8Path atomically:YES]; 372 | [decodedData writeToFile:derPath atomically:YES]; 373 | 374 | //Prepare a message to display to the user indicating the hash used to name the files 375 | NSString* msg = [NSString stringWithFormat:@"Shared using hash %s", [hash UTF8String]]; 376 | UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Complete",nil) message:msg delegate:nil cancelButtonTitle:NSLocalizedString(@"Close",nil) otherButtonTitles:nil]; 377 | [alertView show]; 378 | 379 | //dismiss the details view controller 380 | [self dismissWithoutImporting:row]; 381 | } 382 | 383 | /** 384 | Called when "Return to key chain" button is clicked on the KeyDetailViewController. 385 | */ 386 | - (void) dismissWithoutImporting:(long)row 387 | { 388 | [self dismissViewControllerAnimated:NO completion:nil]; 389 | NSIndexPath* indexPath = [[self tableViewKeyChain] indexPathForSelectedRow]; 390 | [[self tableViewKeyChain] deselectRowAtIndexPath:indexPath animated:NO]; 391 | } 392 | 393 | //------------------------------------------------------------------------------ 394 | #pragma mark - Utility functions 395 | //------------------------------------------------------------------------------ 396 | -(void)resetKeychain { 397 | [self deleteAllKeysForSecClass:kSecClassGenericPassword]; 398 | [self deleteAllKeysForSecClass:kSecClassInternetPassword]; 399 | [self deleteAllKeysForSecClass:kSecClassCertificate]; 400 | [self deleteAllKeysForSecClass:kSecClassKey]; 401 | [self deleteAllKeysForSecClass:kSecClassIdentity]; 402 | } 403 | 404 | -(void)deleteAllKeysForSecClass:(CFTypeRef)secClass { 405 | NSMutableDictionary* dict = [NSMutableDictionary dictionary]; 406 | [dict setObject:(__bridge id)secClass forKey:(__bridge id)kSecClass]; 407 | OSStatus result = SecItemDelete((__bridge CFDictionaryRef) dict); 408 | NSAssert(result == noErr || result == errSecItemNotFound, @"Error deleting keychain data (%d)", (int)result); 409 | } 410 | 411 | //Called when preparing file names for iTunes file sharing 412 | - (NSString *)sha1:(NSData*)data 413 | { 414 | uint8_t digest[CC_SHA1_DIGEST_LENGTH]; 415 | 416 | CC_SHA1(data.bytes, (CC_LONG)data.length, digest); 417 | 418 | NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2]; 419 | 420 | for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) 421 | { 422 | [output appendFormat:@"%02x", digest[i]]; 423 | if(10 == i) 424 | [output appendString:@"\n"]; 425 | } 426 | 427 | return output; 428 | } 429 | 430 | //Called to solicit password from user when file is chosen from iCloud (or other non-Purebred source) 431 | - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 432 | { 433 | if(1 == buttonIndex) 434 | { 435 | passwordFromUser = [[alertView textFieldAtIndex:0] text]; 436 | if(nil != passwordFromUser && 0 != [passwordFromUser length]) 437 | { 438 | [self importP12:pkcs12Data password:passwordFromUser]; 439 | } 440 | } 441 | } 442 | 443 | //Called to parse a PKCS12 object, decrypt it and import it into app's key chain 444 | - (void)importP12:(NSData*) pkcs12DataToImport password:(NSString*)password 445 | { 446 | //Get the destination folder for the files 447 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 448 | NSString *documentsDirectory = [paths objectAtIndex:0]; 449 | 450 | //Generate a file name using the sha1 hash of the certificate with .p8 extension for private key and .der for certificate 451 | NSString* p12File = @"p12ForReview.p12"; 452 | NSString* passFile = @"p12Password.txt"; 453 | NSString *p8Path = [documentsDirectory stringByAppendingPathComponent:p12File]; 454 | NSString *passPath = [documentsDirectory stringByAppendingPathComponent:passFile]; 455 | 456 | //Write the private key and certificate to a pair of files 457 | [pkcs12DataToImport writeToFile:p8Path atomically:YES]; 458 | [password writeToFile:passPath atomically:YES encoding:NSUTF8StringEncoding error:nil]; 459 | 460 | 461 | CFDataRef inPKCS12Data = (__bridge CFDataRef)pkcs12DataToImport; 462 | 463 | OSStatus securityError = errSecSuccess; 464 | 465 | //SecPKCS12Import requires a dictionary with a single value (only one option is supported) 466 | NSMutableDictionary * optionsDictionary = [[NSMutableDictionary alloc] init]; 467 | [optionsDictionary setObject:(id)password forKey:(id)kSecImportExportPassphrase]; 468 | [optionsDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnRef]; 469 | [optionsDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; 470 | [optionsDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes]; 471 | 472 | //Create an array to receive the data parsed from the PKCS12 blob 473 | CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); 474 | 475 | //Parse the PKCS12 blob 476 | securityError = SecPKCS12Import(inPKCS12Data, (CFDictionaryRef)optionsDictionary, &items); 477 | if(0 == securityError) 478 | { 479 | long count = CFArrayGetCount(items); 480 | if(count > 1) 481 | { 482 | NSLog(@"%s %d %s - %s", __FILE__, __LINE__, __PRETTY_FUNCTION__, "SecPKCS12Import returned more than one item. Ignoring all but the first item."); 483 | } 484 | 485 | for(long ii = 0; ii < count; ++ii) 486 | { 487 | //get the first time from the array populated by SecPKCS12Import 488 | CFDictionaryRef pkcs12Contents = (CFDictionaryRef)CFArrayGetValueAtIndex(items, ii); 489 | 490 | //we're primarily interested in the identity value 491 | if(CFDictionaryContainsKey(pkcs12Contents, kSecImportItemIdentity)) 492 | { 493 | //Grab the identity from the dictionary 494 | SecIdentityRef identity = (SecIdentityRef)CFDictionaryGetValue(pkcs12Contents, kSecImportItemIdentity); 495 | 496 | NSString* tagstr = @"red.hound.purebred.pkcs12"; 497 | 498 | NSMutableDictionary* dict = [[NSMutableDictionary alloc]init]; 499 | [dict setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnPersistentRef]; 500 | [dict setObject:(__bridge id)identity forKey:(id)kSecValueRef]; 501 | [dict setObject:tagstr forKey:(id)kSecAttrLabel]; 502 | [dict setObject:(id)kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly forKey:(id)kSecAttrAccessible]; 503 | CFTypeRef persistent_ref; 504 | securityError = SecItemAdd((CFDictionaryRef)dict, &persistent_ref); 505 | 506 | if(errSecSuccess != securityError) 507 | { 508 | NSLog(@"%s %d %s - %s %s", __FILE__, __LINE__, __PRETTY_FUNCTION__, "SecItemAdd failed to import identity harvested from PKCS #12 data with error code ", [[[NSNumber numberWithInt:securityError] stringValue] UTF8String]); 509 | 510 | if(errSecDuplicateItem == securityError) 511 | { 512 | NSLog(@"Failed to import because item is there already"); 513 | } 514 | else 515 | { 516 | NSString *alertMessage = [NSString stringWithFormat:@"Failed to import key from PKCS #12 file with error code %d", (int)securityError]; 517 | NSLog(@"%@", alertMessage); 518 | dispatch_async(dispatch_get_main_queue(), ^{ 519 | UIAlertController *alertController = [UIAlertController 520 | alertControllerWithTitle:@"Import Error" 521 | message:alertMessage 522 | preferredStyle:UIAlertControllerStyleAlert]; 523 | [alertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:nil]]; 524 | [self presentViewController:alertController animated:YES completion:nil]; 525 | }); 526 | } 527 | } 528 | 529 | [keyChain LoadKeyChainContents]; 530 | [[self tableViewKeyChain] reloadData]; 531 | } 532 | 533 | if(errSecSuccess == securityError && CFDictionaryContainsKey(pkcs12Contents, kSecImportItemTrust)) 534 | { 535 | //SecTrustRef trust = (SecTrustRef)CFDictionaryGetValue (pkcs12Contents, kSecImportItemTrust); 536 | //evaluate the trust and output an error log if there is a problem, if desired 537 | } 538 | 539 | if(errSecSuccess == securityError && CFDictionaryContainsKey(pkcs12Contents, kSecImportItemCertChain)) 540 | { 541 | //CFArrayRef certChain = (CFArrayRef)CFDictionaryGetValue (pkcs12Contents, kSecImportItemCertChain); 542 | //import certificates from chain, if desired 543 | } 544 | } 545 | 546 | } 547 | else 548 | { 549 | //Get the destination folder for the files 550 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 551 | NSString *documentsDirectory = [paths objectAtIndex:0]; 552 | 553 | //Generate a file name using the sha1 hash of the certificate with .p8 extension for private key and .der for certificate 554 | NSString* zipFile = @"tmp.zip"; 555 | NSString *zipPath = [documentsDirectory stringByAppendingPathComponent:zipFile]; 556 | 557 | [pkcs12DataToImport writeToFile:zipPath atomically:YES]; 558 | 559 | ZipFile *unzipFile= [[ZipFile alloc] initWithFileName:zipPath mode:ZipFileModeUnzip]; 560 | if(NULL != unzipFile) 561 | { 562 | NSArray *infos= [unzipFile listFileInZipInfos]; 563 | [unzipFile goToFirstFileInZip]; 564 | 565 | for (FileInZipInfo *info in infos) 566 | { 567 | ZipReadStream *read1= [unzipFile readCurrentFileInZip]; 568 | 569 | NSData *data= [read1 readDataOfLength:info.length]; 570 | 571 | if(data) 572 | { 573 | [self importP12:data password:password]; 574 | } 575 | 576 | 577 | [read1 finishedReading]; 578 | [unzipFile goToNextFileInZip]; 579 | } 580 | 581 | [unzipFile close]; 582 | [[NSFileManager defaultManager] removeItemAtPath:zipPath error:nil]; 583 | } 584 | else{ 585 | NSString *alertMessage = [NSString stringWithFormat:@"Failed to parse or decrypt PKCS #12 file with error code %d", (int)securityError]; 586 | NSLog(@"%@", alertMessage); 587 | dispatch_async(dispatch_get_main_queue(), ^{ 588 | UIAlertController *alertController = [UIAlertController 589 | alertControllerWithTitle:@"Import Error" 590 | message:alertMessage 591 | preferredStyle:UIAlertControllerStyleAlert]; 592 | [alertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:nil]]; 593 | [self presentViewController:alertController animated:YES completion:nil]; 594 | }); 595 | } 596 | } 597 | } 598 | 599 | @end 600 | -------------------------------------------------------------------------------- /KeyShareConsumer/KeyChainDataSource.mm: -------------------------------------------------------------------------------- 1 | // 2 | // KeyChainDataSource.mm 3 | // KeyShareConsumer 4 | 5 | #import "KeyChainDataSource.h" 6 | #import 7 | 8 | #include 9 | 10 | //-------------------------------------------------------------- 11 | // Arrays containing attributes for each type of item associated 12 | // with this class: certificate, key, identity 13 | //-------------------------------------------------------------- 14 | CFTypeRef g_certAttrs[] = { 15 | kSecAttrAccessible, 16 | kSecAttrAccessGroup, 17 | kSecAttrCertificateType, 18 | kSecAttrCertificateEncoding, 19 | kSecAttrLabel, 20 | kSecAttrSubject, 21 | kSecAttrIssuer, 22 | kSecAttrSerialNumber, 23 | kSecAttrSubjectKeyID, 24 | kSecAttrPublicKeyHash, 25 | NULL 26 | }; 27 | 28 | CFTypeRef g_keyAttrs[] = { 29 | kSecAttrAccessible, 30 | kSecAttrAccessGroup, 31 | kSecAttrKeyClass, 32 | kSecAttrLabel, 33 | kSecAttrApplicationLabel, 34 | kSecAttrIsPermanent, 35 | kSecAttrApplicationTag, 36 | kSecAttrKeyType, 37 | kSecAttrKeySizeInBits, 38 | kSecAttrEffectiveKeySize, 39 | kSecAttrCanEncrypt, 40 | kSecAttrCanDecrypt, 41 | kSecAttrCanDerive, 42 | kSecAttrCanSign, 43 | kSecAttrCanVerify, 44 | kSecAttrCanWrap, 45 | kSecAttrCanUnwrap, 46 | NULL 47 | }; 48 | 49 | CFTypeRef g_identityAttrs[] = { 50 | kSecAttrAccessible, 51 | kSecAttrAccessGroup, 52 | kSecAttrCertificateType, 53 | kSecAttrCertificateEncoding, 54 | kSecAttrLabel, 55 | kSecAttrSubject, 56 | kSecAttrIssuer, 57 | kSecAttrSerialNumber, 58 | kSecAttrSubjectKeyID, 59 | kSecAttrPublicKeyHash, 60 | kSecAttrKeyClass, 61 | kSecAttrApplicationLabel, 62 | kSecAttrIsPermanent, 63 | kSecAttrApplicationTag, 64 | kSecAttrKeyType, 65 | kSecAttrKeySizeInBits, 66 | kSecAttrEffectiveKeySize, 67 | kSecAttrCanEncrypt, 68 | kSecAttrCanDecrypt, 69 | kSecAttrCanDerive, 70 | kSecAttrCanSign, 71 | kSecAttrCanVerify, 72 | kSecAttrCanWrap, 73 | kSecAttrCanUnwrap, 74 | NULL 75 | }; 76 | 77 | //-------------------------------------------------------------- 78 | // Arrays containing attributes that are grouped together in a 79 | // single table cell for display purposes, i.e., a single string 80 | // is returned containing information for all attributes in the 81 | // group. 82 | //-------------------------------------------------------------- 83 | CFTypeRef g_keyRelatedAttrs[] = { 84 | kSecAttrKeyClass, 85 | kSecAttrKeyType, 86 | kSecAttrKeySizeInBits, 87 | kSecAttrEffectiveKeySize, 88 | NULL 89 | }; 90 | 91 | CFTypeRef g_capabilityRelatedAttrs[] = { 92 | kSecAttrCanEncrypt, 93 | kSecAttrCanDecrypt, 94 | kSecAttrCanDerive, 95 | kSecAttrCanSign, 96 | kSecAttrCanVerify, 97 | kSecAttrCanWrap, 98 | kSecAttrCanUnwrap, 99 | NULL 100 | }; 101 | 102 | CFTypeRef g_certRelatedAttrs[] = { 103 | kSecAttrCertificateType, 104 | kSecAttrCertificateEncoding, 105 | kSecAttrSubject, 106 | kSecAttrIssuer, 107 | kSecAttrSerialNumber, 108 | kSecAttrSubjectKeyID, 109 | kSecAttrPublicKeyHash, 110 | NULL 111 | }; 112 | 113 | CFTypeRef g_miscRelatedAttrs[] = { 114 | kSecAttrLabel, 115 | kSecAttrAccessible, 116 | kSecAttrAccessGroup, 117 | kSecAttrApplicationLabel, 118 | kSecAttrIsPermanent, 119 | kSecAttrApplicationTag, 120 | NULL 121 | }; 122 | 123 | //-------------------------------------------------------------- 124 | // Internal conversion helper functions 125 | //-------------------------------------------------------------- 126 | @interface KeyChainDataSource (ConversionRoutines) 127 | 128 | //These return strings that should be autoreleased 129 | + (NSString*) getCFDateAsString:(CFDateRef) date; 130 | + (NSString*) getCFNumberAsString:(CFNumberRef) number; 131 | + (NSString*) getCFBooleanAsString:(CFBooleanRef) cfBool; 132 | + (NSString*) getCertificateTypeAsString:(CFNumberRef) number; 133 | + (NSString*) getKeyTypeAsString:(CFNumberRef) number; 134 | + (NSString*) getKeyClassAsString:(CFNumberRef) number; 135 | + (NSString*) getCertificateEncodingAsString:(CFNumberRef) number; 136 | + (NSString*) getAttrAccessibleAsString:(CFStringRef) attrAccessible; 137 | 138 | //The return freshly alloc'ed string 139 | + (NSString*) getDataAsAsciiHexString:(NSData*)data; 140 | + (NSString*) getDataAsNameString:(NSData*)data; 141 | 142 | @end 143 | 144 | @implementation KeyChainDataSource (ConversionRoutines) 145 | 146 | + (NSString*) getCFDateAsString:(CFDateRef) date 147 | { 148 | NSDate* nsDate = (__bridge NSDate*)date; 149 | return [nsDate description]; 150 | } 151 | 152 | + (NSString*) getCFNumberAsString:(CFNumberRef) number 153 | { 154 | NSNumber* nsNumber = (__bridge NSNumber*)number; 155 | return [nsNumber stringValue]; 156 | } 157 | 158 | + (NSString*) getCFBooleanAsString:(CFBooleanRef) cfBool 159 | { 160 | if(CFBooleanGetValue(cfBool)) 161 | return NSLocalizedString(@"Yes", nil); 162 | else 163 | return NSLocalizedString(@"No", nil); 164 | } 165 | 166 | + (NSString*) getCertificateTypeAsString:(CFNumberRef) number 167 | { 168 | NSNumber* nsNumber = (__bridge NSNumber*)number; 169 | switch([nsNumber intValue]) 170 | { 171 | case 1: 172 | return NSLocalizedString(@"X509v1", nil); 173 | case 2: 174 | return NSLocalizedString(@"X509v2", nil); 175 | case 3: 176 | return NSLocalizedString(@"X509v3", nil); 177 | default: 178 | return NSLocalizedString(@"Unknown type", nil); 179 | } 180 | } 181 | 182 | + (NSString*) getKeyClassAsString:(CFNumberRef) number 183 | { 184 | NSString* nStr = [self getCFNumberAsString:number]; 185 | 186 | if(NSOrderedSame == [(NSString*)kSecAttrKeyClassPublic compare:nStr]) 187 | return NSLocalizedString(@"Public key", nil); 188 | else if(NSOrderedSame == [(NSString*)kSecAttrKeyClassPrivate compare:nStr]) 189 | return NSLocalizedString(@"Private key", nil); 190 | else if(NSOrderedSame == [(NSString*)kSecAttrKeyClassSymmetric compare:nStr]) 191 | return NSLocalizedString(@"Symmetric key", nil); 192 | else 193 | return NSLocalizedString(@"Unknown type", nil); 194 | } 195 | 196 | + (NSString*) getKeyTypeAsString:(CFNumberRef) number 197 | { 198 | NSString* nStr = [self getCFNumberAsString:number]; 199 | 200 | if(NSOrderedSame == [(NSString*)kSecAttrKeyTypeRSA compare:nStr]) 201 | return NSLocalizedString(@"RSA", nil); 202 | else if(NSOrderedSame == [(NSString*)kSecAttrKeyTypeRSA compare:nStr]) 203 | return NSLocalizedString(@"Elliptic curve", nil); 204 | else 205 | return NSLocalizedString(@"Unknown type", nil); 206 | } 207 | 208 | + (NSString*) getAttrAccessibleAsString:(CFStringRef) attrAccessible 209 | { 210 | NSString* nStr = (__bridge NSString*)attrAccessible; 211 | 212 | if(NSOrderedSame == [(NSString*)kSecAttrAccessibleWhenUnlocked compare:nStr]) 213 | return NSLocalizedString(@"kSecAttrAccessibleWhenUnlocked", nil); 214 | else if(NSOrderedSame == [(NSString*)kSecAttrAccessibleAfterFirstUnlock compare:nStr]) 215 | return NSLocalizedString(@"kSecAttrAccessibleAfterFirstUnlock", nil); 216 | else if(NSOrderedSame == [(NSString*)kSecAttrAccessibleAlways compare:nStr]) 217 | return NSLocalizedString(@"kSecAttrAccessibleAlways", nil); 218 | else if(NSOrderedSame == [(NSString*)kSecAttrAccessibleWhenUnlockedThisDeviceOnly compare:nStr]) 219 | return NSLocalizedString(@"kSecAttrAccessibleWhenUnlockedThisDeviceOnly", nil); 220 | else if(NSOrderedSame == [(NSString*)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly compare:nStr]) 221 | return NSLocalizedString(@"kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly", nil); 222 | else if(NSOrderedSame == [(NSString*)kSecAttrAccessibleAlwaysThisDeviceOnly compare:nStr]) 223 | return NSLocalizedString(@"kSecAttrAccessibleAlwaysThisDeviceOnly", nil); 224 | else 225 | return NSLocalizedString(@"Unknown type", nil); 226 | } 227 | 228 | + (NSString*) getCertificateEncodingAsString:(CFNumberRef) number 229 | { 230 | NSNumber* nsNumber = (__bridge NSNumber*)number; 231 | if(3 == [nsNumber intValue]) 232 | return NSLocalizedString(@"DER", nil); 233 | else 234 | return NSLocalizedString(@"Unknown type", nil); 235 | } 236 | 237 | + (NSString *) hexString:(NSData*)data 238 | { 239 | NSUInteger bytesCount = [data length]; 240 | if (bytesCount) { 241 | const char *hexChars = "0123456789ABCDEF"; 242 | const unsigned char *dataBuffer = (unsigned char*)[data bytes]; 243 | char *chars = (char*)malloc(sizeof(char) * (bytesCount * 2 + 1)); 244 | char *s = chars; 245 | for (unsigned i = 0; i < bytesCount; ++i) { 246 | *s++ = hexChars[((*dataBuffer & 0xF0) >> 4)]; 247 | *s++ = hexChars[(*dataBuffer & 0x0F)]; 248 | dataBuffer++; 249 | } 250 | *s = '\0'; 251 | NSString *hexString = [NSString stringWithUTF8String:chars]; 252 | free(chars); 253 | return hexString; 254 | } 255 | return @""; 256 | } 257 | 258 | + (NSString*) getDataAsAsciiHexString:(NSData*)data 259 | { 260 | return [self hexString:data]; 261 | } 262 | 263 | + (NSString*) getDataAsNameString:(NSData*)data 264 | { 265 | //Implement after linking useful PKE support 266 | return nil; 267 | } 268 | 269 | @end 270 | 271 | //-------------------------------------------------------------- 272 | // Internal conversion helper functions 273 | //-------------------------------------------------------------- 274 | @interface KeyChainDataSource (PrivateMethods) 275 | 276 | - (void) populateAttrMap; 277 | - (int) countAttributesAtIndex:(long)index; 278 | - (NSString*) getAttrValueAsString:(CFTypeRef)attribute value:(CFTypeRef)value; 279 | 280 | @end 281 | 282 | @implementation KeyChainDataSource (PrivateMethods) 283 | 284 | - (void) populateAttrMap 285 | { 286 | if(attrNames) 287 | { 288 | //[attrNames release]; 289 | attrNames = nil; 290 | } 291 | 292 | attrNames = [[NSMutableDictionary alloc] init]; 293 | 294 | //Set up the friendly names for each attribute that can be read from one 295 | //of the three types of items this class cares about. 296 | [attrNames setObject:(id)@"Accessible" forKey:(id)kSecAttrAccessible]; 297 | [attrNames setObject:(id)@"Access group" forKey:(id)kSecAttrAccessGroup]; 298 | [attrNames setObject:(id)@"Certificate type" forKey:(id)kSecAttrCertificateType]; 299 | [attrNames setObject:(id)@"Certificate encoding" forKey:(id)kSecAttrCertificateEncoding]; 300 | [attrNames setObject:(id)@"Label" forKey:(id)kSecAttrLabel]; 301 | 302 | //Re-enable these if linking in a certificate parser 303 | //[attrNames setObject:(id)@"Subject" forKey:(id)kSecAttrSubject]; 304 | //[attrNames setObject:(id)@"Issuer" forKey:(id)kSecAttrIssuer]; 305 | [attrNames setObject:(id)@"Serial number" forKey:(id)kSecAttrSerialNumber]; 306 | [attrNames setObject:(id)@"Subject key ID" forKey:(id)kSecAttrSubjectKeyID]; 307 | [attrNames setObject:(id)@"Public key hash" forKey:(id)kSecAttrPublicKeyHash]; 308 | [attrNames setObject:(id)@"Key class" forKey:(id)kSecAttrKeyClass]; 309 | [attrNames setObject:(id)@"Application label" forKey:(id)kSecAttrApplicationLabel]; 310 | [attrNames setObject:(id)@"Is permanent" forKey:(id)kSecAttrIsPermanent]; 311 | [attrNames setObject:(id)@"Application tag" forKey:(id)kSecAttrApplicationTag]; 312 | [attrNames setObject:(id)@"Key type" forKey:(id)kSecAttrKeyType]; 313 | [attrNames setObject:(id)@"Key size in bits" forKey:(id)kSecAttrKeySizeInBits]; 314 | [attrNames setObject:(id)@"Effective key size" forKey:(id)kSecAttrEffectiveKeySize]; 315 | [attrNames setObject:(id)@"Can encrypt" forKey:(id)kSecAttrCanEncrypt]; 316 | [attrNames setObject:(id)@"Can decrypt" forKey:(id)kSecAttrCanDecrypt]; 317 | [attrNames setObject:(id)@"Can derive" forKey:(id)kSecAttrCanDerive]; 318 | [attrNames setObject:(id)@"Can sign" forKey:(id)kSecAttrCanSign]; 319 | [attrNames setObject:(id)@"Can verify" forKey:(id)kSecAttrCanVerify]; 320 | [attrNames setObject:(id)@"Can wrap" forKey:(id)kSecAttrCanWrap]; 321 | [attrNames setObject:(id)@"Can unwrap" forKey:(id)kSecAttrCanUnwrap]; 322 | } 323 | 324 | - (int) countAttributesAtIndex:(long)index 325 | { 326 | int count = 0; 327 | 328 | CFTypeRef* attrs = NULL; 329 | 330 | switch (mode) { 331 | case KSM_Certificates: 332 | attrs = g_certAttrs; 333 | break; 334 | case KSM_Identities: 335 | attrs = g_identityAttrs; 336 | break; 337 | case KSM_Keys: 338 | attrs = g_keyAttrs; 339 | break; 340 | default: 341 | return 0; 342 | } 343 | 344 | @try 345 | { 346 | CFDictionaryRef dict = (__bridge CFDictionaryRef)[items objectAtIndex:index]; 347 | 348 | for(int ii = 0; attrs[ii]; ++ii) 349 | { 350 | if(true == CFDictionaryGetValueIfPresent(dict, attrs[ii], NULL)) 351 | ++count; 352 | } 353 | } 354 | @catch (NSException* rangeException) 355 | { 356 | return 0; 357 | } 358 | 359 | return count; 360 | } 361 | 362 | - (NSString*) getAttrValueAsString:(CFTypeRef)attribute value:(CFTypeRef)value 363 | { 364 | NSString* attributeValueString = nil; 365 | 366 | if(kSecAttrAccessible == attribute) 367 | { 368 | attributeValueString = [KeyChainDataSource getAttrAccessibleAsString:(CFStringRef)value]; 369 | } 370 | else if(kSecAttrAccessGroup == attribute) 371 | { 372 | attributeValueString = [[NSString alloc] initWithString:(__bridge NSString*)value] ; 373 | } 374 | else if(kSecAttrCertificateType == attribute) 375 | { 376 | attributeValueString = [KeyChainDataSource getCertificateTypeAsString:(CFNumberRef)value]; 377 | } 378 | else if(kSecAttrCertificateEncoding == attribute) 379 | { 380 | attributeValueString = [KeyChainDataSource getCertificateEncodingAsString:(CFNumberRef)value]; 381 | } 382 | else if(kSecAttrLabel == attribute) 383 | { 384 | attributeValueString = [[NSString alloc] initWithString:(__bridge NSString*)value] ; 385 | } 386 | else if(kSecAttrSubject == attribute) 387 | { 388 | attributeValueString = [KeyChainDataSource getDataAsNameString:(__bridge NSData*)value]; 389 | } 390 | else if(kSecAttrIssuer == attribute) 391 | { 392 | attributeValueString = [KeyChainDataSource getDataAsNameString:(__bridge NSData*)value]; 393 | } 394 | else if(kSecAttrSerialNumber == attribute) 395 | { 396 | attributeValueString = [KeyChainDataSource getDataAsAsciiHexString:(__bridge NSData*)value]; 397 | } 398 | else if(kSecAttrSubjectKeyID == attribute) 399 | { 400 | attributeValueString = [KeyChainDataSource getDataAsAsciiHexString:(__bridge NSData*)value]; 401 | } 402 | else if(kSecAttrPublicKeyHash == attribute) 403 | { 404 | attributeValueString = [KeyChainDataSource getDataAsAsciiHexString:(__bridge NSData*)value]; 405 | } 406 | else if(kSecAttrKeyClass == attribute) 407 | { 408 | attributeValueString = [KeyChainDataSource getKeyClassAsString:(CFNumberRef)value]; 409 | } 410 | else if(kSecAttrApplicationLabel == attribute) 411 | { 412 | attributeValueString = [KeyChainDataSource getDataAsAsciiHexString:(__bridge NSData*)value]; 413 | } 414 | else if(kSecAttrIsPermanent == attribute) 415 | { 416 | attributeValueString = [KeyChainDataSource getCFBooleanAsString:(CFBooleanRef)value]; 417 | } 418 | else if(kSecAttrApplicationTag == attribute) 419 | { 420 | if(CFGetTypeID(value) == CFDataGetTypeID()) 421 | { 422 | NSData* d = (__bridge NSData*)value; 423 | attributeValueString = [NSString stringWithUTF8String:(char*)[d bytes]]; 424 | } 425 | else 426 | { 427 | attributeValueString = [[NSString alloc] initWithString:(__bridge NSString*)value] ; 428 | } 429 | } 430 | else if(kSecAttrKeyType == attribute) 431 | { 432 | attributeValueString = [KeyChainDataSource getKeyTypeAsString:(CFNumberRef)value]; 433 | } 434 | else if(kSecAttrKeySizeInBits == attribute) 435 | { 436 | attributeValueString = [KeyChainDataSource getCFNumberAsString:(CFNumberRef)value]; 437 | } 438 | else if(kSecAttrEffectiveKeySize == attribute) 439 | { 440 | attributeValueString = [KeyChainDataSource getCFNumberAsString:(CFNumberRef)value]; 441 | } 442 | else if(kSecAttrCanEncrypt == attribute) 443 | { 444 | attributeValueString = [KeyChainDataSource getCFBooleanAsString:(CFBooleanRef)value]; 445 | } 446 | else if(kSecAttrCanDecrypt == attribute) 447 | { 448 | attributeValueString = [KeyChainDataSource getCFBooleanAsString:(CFBooleanRef)value]; 449 | } 450 | else if(kSecAttrCanDerive == attribute) 451 | { 452 | attributeValueString = [KeyChainDataSource getCFBooleanAsString:(CFBooleanRef)value]; 453 | } 454 | else if(kSecAttrCanSign == attribute) 455 | { 456 | attributeValueString = [KeyChainDataSource getCFBooleanAsString:(CFBooleanRef)value]; 457 | } 458 | else if(kSecAttrCanVerify == attribute) 459 | { 460 | attributeValueString = [KeyChainDataSource getCFBooleanAsString:(CFBooleanRef)value]; 461 | } 462 | else if(kSecAttrCanWrap == attribute) 463 | { 464 | attributeValueString = [KeyChainDataSource getCFBooleanAsString:(CFBooleanRef)value]; 465 | } 466 | else if(kSecAttrCanUnwrap == attribute) 467 | { 468 | attributeValueString = [KeyChainDataSource getCFBooleanAsString:(CFBooleanRef)value]; 469 | } 470 | else 471 | { 472 | attributeValueString = @"Unknown value"; 473 | } 474 | 475 | return attributeValueString; 476 | } 477 | 478 | @end 479 | 480 | //-------------------------------------------------------------- 481 | // KeyChainDataSource implementation 482 | //-------------------------------------------------------------- 483 | @implementation KeyChainDataSource 484 | 485 | //Public members 486 | @synthesize displayEmptyAttributes; 487 | @synthesize userQuery; 488 | 489 | //Private members 490 | @synthesize items; 491 | @synthesize mode; 492 | @synthesize initialized; 493 | @synthesize attrNames; 494 | 495 | - (int) numAttrGroups:(long)index 496 | { 497 | return [self countAttributesAtIndex:index]; 498 | } 499 | 500 | - (NSString*) getAttrStringForGroup:(CFTypeRef*)attrArray forItem:(long)index 501 | { 502 | std::ostringstream oss; 503 | for(int ii = 0; attrArray[ii]; ++ii) 504 | { 505 | NSString* attrName = (NSString*)[attrNames objectForKey:(__bridge id)attrArray[ii]]; 506 | if(attrName) 507 | { 508 | NSString* attrValue = [self getAttrValueAtSection:index attrType:attrArray[ii]]; 509 | if(attrValue) 510 | { 511 | oss << [attrName UTF8String] << ": " << [attrValue UTF8String] << std::endl; 512 | } 513 | } 514 | } 515 | NSString* retVal = [[NSString alloc] initWithCString:oss.str().c_str() encoding:NSUTF8StringEncoding] ; 516 | return retVal; 517 | } 518 | 519 | - (NSString*) getAttrStringAtIndex:(long)index attrGroup:(long)attrGroup 520 | { 521 | return [self getAttrValueAtSection:index attrIndex:attrGroup]; 522 | } 523 | 524 | /** 525 | LoadKeyChainContents prepares a dictionary containing a query filter based on the current mode. 526 | The results are stored in the items member variable with mode-specific contents. 527 | */ 528 | - (void) LoadKeyChainContents 529 | { 530 | [self ClearContents]; 531 | 532 | OSStatus resultCode = noErr; 533 | 534 | if(nil == userQuery) 535 | { 536 | NSMutableDictionary * query = [[NSMutableDictionary alloc] init]; 537 | 538 | //Set up the invariant pieces of the query 539 | [query setObject:(id)kSecMatchLimitAll forKey:(id)kSecMatchLimit]; 540 | [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnRef]; 541 | [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; 542 | [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes]; 543 | 544 | //Set up the mode-specific pieces of the query 545 | switch(mode) 546 | { 547 | case KSM_Certificates: 548 | { 549 | [query setObject:(id)kSecClassCertificate forKey:(id)kSecClass]; 550 | break; 551 | } 552 | case KSM_Identities: 553 | { 554 | [query setObject:(id)kSecClassIdentity forKey:(id)kSecClass]; 555 | break; 556 | } 557 | case KSM_Keys: 558 | { 559 | [query setObject:(id)kSecClassKey forKey:(id)kSecClass]; 560 | break; 561 | } 562 | } 563 | 564 | CFTypeRef result = nil; 565 | //Execute the query saving the results in items. 566 | resultCode = SecItemCopyMatching((CFDictionaryRef)query, &result); 567 | items = (__bridge_transfer NSMutableArray*)result; 568 | 569 | //[query release]; 570 | } 571 | else 572 | { 573 | CFTypeRef result = nil; 574 | resultCode = SecItemCopyMatching((CFDictionaryRef)userQuery, &result); 575 | items = (__bridge_transfer NSMutableArray*)result; 576 | } 577 | 578 | if(resultCode != noErr) 579 | { 580 | //clean up anything that might have landed in items 581 | [self ClearContents]; 582 | } 583 | else 584 | { 585 | //set the initialized flag 586 | initialized = true; 587 | } 588 | 589 | return; 590 | } 591 | 592 | //-------------------------------------------------------------- 593 | // KeyChainDataSource initialization/destruction 594 | //-------------------------------------------------------------- 595 | - (id) init 596 | { 597 | self = [super init]; 598 | if(self) 599 | { 600 | mode = KSM_Identities; 601 | initialized = false; 602 | items = nil; 603 | displayEmptyAttributes = false; 604 | [self populateAttrMap]; 605 | } 606 | return self; 607 | } 608 | 609 | - (id) initWithMode:(enum KeyChainDataSourceMode)kcdsMode 610 | { 611 | self = [super init]; 612 | if(self) 613 | { 614 | mode = kcdsMode; 615 | initialized = false; 616 | items = nil; 617 | displayEmptyAttributes = false; 618 | [self populateAttrMap]; 619 | } 620 | return self; 621 | } 622 | 623 | - (void)dealloc 624 | { 625 | //[items release]; 626 | items = nil; 627 | 628 | //[attrNames release]; 629 | attrNames = nil; 630 | 631 | //[userQuery release]; 632 | userQuery = nil; 633 | 634 | [self ClearContents]; 635 | //[super dealloc]; 636 | } 637 | 638 | - (void) ClearContents 639 | { 640 | //[items release]; 641 | items = nil; 642 | 643 | initialized = false; 644 | } 645 | 646 | - (size_t) numItems 647 | { 648 | //each item gets its own section 649 | if(nil == items) 650 | return 0; 651 | else 652 | return [items count]; 653 | } 654 | 655 | - (NSString*) GetEmailAddressAtIndex:(long)index 656 | { 657 | //Implement after linking useful PKE support 658 | return nil; 659 | } 660 | 661 | - (NSString*) GetCommonNameAtIndex:(long)index 662 | { 663 | SecCertificateRef certRef = [self getCertificateAt:index]; 664 | if(certRef) 665 | { 666 | CFStringRef summaryRef = SecCertificateCopySubjectSummary(certRef); 667 | return (__bridge_transfer NSString*)summaryRef; 668 | } 669 | 670 | return nil; 671 | } 672 | - (NSString*) GetIdentityNameAtIndex:(long)index 673 | { 674 | //look for email address first, failing that use the default keychain label 675 | NSString* emailAddress = [self GetEmailAddressAtIndex:index]; 676 | if(!emailAddress) 677 | { 678 | NSString* subject = [self GetCommonNameAtIndex:index]; 679 | if(!subject) 680 | return [self getAttrValueAtSection:index attrType:kSecAttrLabel]; 681 | else 682 | return subject; 683 | } 684 | else 685 | return emailAddress; 686 | } 687 | 688 | - (SecIdentityRef) GetIdentityAtIndex:(long)index 689 | { 690 | if(index >= [items count]) 691 | return nil; 692 | CFDictionaryRef item = (__bridge CFDictionaryRef)[items objectAtIndex:index]; 693 | 694 | SecIdentityRef identity = nil; 695 | CFTypeRef value; 696 | if(CFDictionaryGetValueIfPresent(item, kSecValueRef, &value)) 697 | { 698 | identity = (SecIdentityRef)value; 699 | } 700 | 701 | return identity; 702 | } 703 | 704 | - (NSData*) GetPrivateKeyAtIndex:(long)index 705 | { 706 | if(index >= [items count]) 707 | return nil; 708 | CFDictionaryRef item = (__bridge CFDictionaryRef)[items objectAtIndex:index]; 709 | 710 | NSData* privateKey = nil; 711 | CFTypeRef label; 712 | if(CFDictionaryGetValueIfPresent(item, kSecValueData, &label)) 713 | { 714 | CFDataRef aCFString = (CFDataRef)label; 715 | privateKey = (__bridge NSData *)aCFString; 716 | } 717 | return privateKey; 718 | } 719 | 720 | - (void) removeObjectAtIndex:(long)index 721 | { 722 | if(index >= [items count]) 723 | return; 724 | 725 | CFDictionaryRef item = (__bridge CFDictionaryRef)[items objectAtIndex:index]; 726 | 727 | CFTypeRef value; 728 | if(CFDictionaryGetValueIfPresent(item, kSecValueRef, &value)) 729 | { 730 | SecIdentityRef identity = (SecIdentityRef)value; 731 | 732 | NSMutableDictionary * query = [[NSMutableDictionary alloc] init]; 733 | 734 | //Set up the invariant pieces of the query 735 | [query setObject:(__bridge id)identity forKey:(id)kSecValueRef]; 736 | 737 | //Execute the query saving the results in items. 738 | OSStatus resultCode = SecItemDelete((CFDictionaryRef) query); 739 | query = nil; 740 | 741 | if(errSecSuccess == resultCode) 742 | { 743 | [self LoadKeyChainContents]; 744 | } 745 | else 746 | { 747 | NSLog(@"Failed to delete selected identity with error code %d.", (int)resultCode); 748 | 749 | } 750 | } 751 | } 752 | 753 | - (NSString*) getAttrNameAtSection:(long)sectionIndex attrIndex:(long)attrIndex 754 | { 755 | CFTypeRef attribute, value; 756 | NSString* attrFriendlyName = nil; 757 | 758 | @try 759 | { 760 | CFDictionaryRef dict = (__bridge CFDictionaryRef)[items objectAtIndex:sectionIndex]; 761 | CFTypeRef* attrs = NULL; 762 | 763 | switch (mode) { 764 | case KSM_Certificates: 765 | attrs = g_certAttrs; 766 | break; 767 | case KSM_Identities: 768 | attrs = g_identityAttrs; 769 | break; 770 | case KSM_Keys: 771 | attrs = g_keyAttrs; 772 | break; 773 | default: 774 | return 0; 775 | } 776 | 777 | for(int ii = 0, jj = 0; attrs[ii]; ++ii) 778 | { 779 | if(CFDictionaryGetValueIfPresent(dict, attrs[ii], &value)) 780 | { 781 | if(jj == attrIndex) 782 | { 783 | attribute = attrs[ii]; 784 | break; 785 | } 786 | else 787 | ++jj; 788 | } 789 | } 790 | } 791 | @catch (NSException* rangeException) 792 | { 793 | return 0; 794 | } 795 | 796 | //get the friendly name of the attribute 797 | attrFriendlyName = (NSString*)[attrNames objectForKey:(__bridge id)attribute]; 798 | if(nil == attrFriendlyName) 799 | attrFriendlyName = NSLocalizedString(@"Unrecognized attribute",nil); 800 | 801 | return attrFriendlyName; 802 | } 803 | 804 | /** 805 | This function returns the attrIndex-th present value from the sectionIndex-th item 806 | */ 807 | - (NSString*) getAttrValueAtSection:(long)sectionIndex attrIndex:(long)attrIndex 808 | { 809 | CFTypeRef attribute, value; 810 | 811 | @try 812 | { 813 | CFDictionaryRef dict = (__bridge CFDictionaryRef)[items objectAtIndex:sectionIndex]; 814 | CFTypeRef* attrs = NULL; 815 | 816 | switch (mode) { 817 | case KSM_Certificates: 818 | attrs = g_certAttrs; 819 | break; 820 | case KSM_Identities: 821 | attrs = g_identityAttrs; 822 | break; 823 | case KSM_Keys: 824 | attrs = g_keyAttrs; 825 | break; 826 | default: 827 | return 0; 828 | } 829 | 830 | for(int ii = 0, jj = 0; attrs[ii]; ++ii) 831 | { 832 | if(CFDictionaryGetValueIfPresent(dict, attrs[ii], &value)) 833 | { 834 | if(jj == attrIndex) 835 | { 836 | attribute = attrs[ii]; 837 | break; 838 | } 839 | else 840 | ++jj; 841 | } 842 | } 843 | } 844 | @catch (NSException* rangeException) 845 | { 846 | return nil; 847 | } 848 | 849 | return [self getAttrValueAsString:attribute value:value]; 850 | } 851 | 852 | - (NSString*) getAttrValueAtSection:(long)sectionIndex attrType:(CFTypeRef)attrType 853 | { 854 | CFTypeRef value; 855 | 856 | @try 857 | { 858 | CFDictionaryRef dict = (__bridge CFDictionaryRef)[items objectAtIndex:sectionIndex]; 859 | if(!CFDictionaryGetValueIfPresent(dict, attrType, &value)) 860 | { 861 | return nil; 862 | } 863 | } 864 | @catch (NSException* rangeException) 865 | { 866 | return nil; 867 | } 868 | 869 | return [self getAttrValueAsString:attrType value:value]; 870 | } 871 | 872 | - (SecCertificateRef) getCertificateAt:(long)index 873 | { 874 | if(index >= [items count]) 875 | return nil; 876 | 877 | switch (mode) { 878 | case KSM_Certificates: 879 | { 880 | CFDictionaryRef dict = (__bridge CFDictionaryRef)[items objectAtIndex:index]; 881 | SecCertificateRef cert = (SecCertificateRef)CFDictionaryGetValue(dict, kSecValueRef); 882 | return cert; 883 | } 884 | case KSM_Identities: 885 | { 886 | CFDictionaryRef dict = (__bridge CFDictionaryRef)[items objectAtIndex:index]; 887 | SecIdentityRef identity = (SecIdentityRef)CFDictionaryGetValue(dict, kSecValueRef); 888 | SecCertificateRef cert = nil; 889 | OSStatus stat = SecIdentityCopyCertificate(identity, &cert); 890 | if(errSecSuccess == stat) 891 | return cert; 892 | else 893 | return nil; 894 | } 895 | case KSM_Keys: 896 | { 897 | return nil; 898 | } 899 | default: 900 | { 901 | return nil; 902 | } 903 | } 904 | } 905 | 906 | - (NSData*) GetPKCS12AtIndex:(long)index 907 | { 908 | //Implement after linking useful PKE support 909 | return nil; 910 | } 911 | 912 | @end 913 | --------------------------------------------------------------------------------