├── 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 |
--------------------------------------------------------------------------------