]> git.saurik.com Git - apple/security.git/blob - keychain/SecurityUnitTests/SecItemTests.m
Security-59754.41.1.tar.gz
[apple/security.git] / keychain / SecurityUnitTests / SecItemTests.m
1 /*
2 * Copyright (c) 2019 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 #import <XCTest/XCTest.h>
26
27 @interface SecItemTests : XCTestCase
28
29 @end
30
31 @implementation SecItemTests
32
33 - (void)setUp {
34 [self deleteAll];
35 }
36
37 - (void)tearDown {
38 [self deleteAll];
39 }
40
41
42
43 - (void)testAddGenericPassword {
44 NSDictionary *attrs;
45
46 attrs = [self addGenericPassword:@"delete-me" service:@"delete-me"];
47 XCTAssertNotNil(attrs, "should create genp");
48 XCTAssertNil(attrs[@"OSStatus"], "should have no error");
49 }
50
51 - (void)testAddTwoGenericPassword {
52 NSDictionary *attrs;
53
54 attrs = [self addGenericPassword:@"delete-me" service:@"delete-me"];
55 XCTAssertNotNil(attrs, "should create genp");
56 XCTAssertNil(attrs[@"OSStatus"], "should have no error");
57
58 attrs = [self addGenericPassword:@"delete-me2s" service:@"delete-me"];
59 XCTAssertNotNil(attrs, "should create genp");
60 XCTAssertNil(attrs[@"OSStatus"], "should have no error");
61 }
62
63 - (void)testAddCollidingGenericPassword {
64 NSDictionary *attrs;
65
66 attrs = [self addGenericPassword:@"delete-me" service:@"delete-me"];
67 XCTAssertNotNil(attrs, "should create genp");
68
69 attrs = [self addGenericPassword:@"delete-me" service:@"delete-me"];
70 XCTAssertNotNil(attrs, "should create genp");
71 XCTAssertEqual([attrs[@"OSStatus"] integerValue], errSecDuplicateItem, "should have duplicate item");
72 }
73
74
75 - (void)testMoveGenericPassword {
76 NSDictionary *attrs;
77
78 attrs = [self addGenericPassword:@"delete-me" service:@"delete-me"];
79 XCTAssertNotNil(attrs, "should create genp");
80
81 attrs = [self addGenericPassword:@"delete-me" service:@"delete-me"];
82 XCTAssertNotNil(attrs, "should create genp");
83 XCTAssertEqual([attrs[@"OSStatus"] integerValue], errSecDuplicateItem, "should have duplicate item");
84
85 XCTAssertEqual([self moveGenericPassword:@"delete-me" service:@"delete-me"
86 newAccount:@"delete-me2" newService:@"delete-me2"],
87 noErr);
88
89 XCTAssertEqual([self moveGenericPassword:@"delete-me" service:@"delete-me"
90 newAccount:@"delete-me2" newService:@"delete-me2"],
91 errSecItemNotFound);
92
93 }
94
95 //-MARK: helper functions
96
97 - (void)deleteAll {
98 NSDictionary *allGenericPassword = @{
99 (id)kSecClass : (id)kSecClassGenericPassword,
100 (id)kSecUseDataProtectionKeychain : @(YES),
101 };
102 (void)SecItemDelete((__bridge CFDictionaryRef)allGenericPassword);
103 }
104
105
106 - (NSDictionary *)addGenericPassword:(NSString *)account service:(NSString *)service
107 {
108 NSDictionary* addQuery = @{
109 (id)kSecClass : (id)kSecClassGenericPassword,
110 (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding],
111 (id)kSecAttrAccount : account,
112 (id)kSecAttrService : service,
113 (id)kSecAttrAccessible : (id)kSecAttrAccessibleAfterFirstUnlock,
114 (id)kSecUseDataProtectionKeychain : @(YES),
115 (id)kSecReturnAttributes : @(YES),
116 };
117 CFTypeRef result = NULL;
118
119 OSStatus status = SecItemAdd((__bridge CFDictionaryRef)addQuery, &result);
120 if (status != 0) {
121 return @{ @"OSStatus": @(status) };
122 }
123 if (result == NULL) {
124 return NULL;
125 }
126 if (CFGetTypeID(result) != CFDictionaryGetTypeID()) {
127 CFRelease(result);
128 return NULL;
129 }
130
131 return (__bridge NSDictionary *)result;
132 }
133
134
135 - (OSStatus)moveGenericPassword:(NSString *)account service:(NSString *)service
136 newAccount:(NSString *)newAccount newService:(NSString *)newService
137 {
138 NSDictionary* updateQuery = @{
139 (id)kSecClass : (id)kSecClassGenericPassword,
140 (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding],
141 (id)kSecAttrAccount : account,
142 (id)kSecAttrService : service,
143 (id)kSecAttrAccessible : (id)kSecAttrAccessibleAfterFirstUnlock,
144 (id)kSecUseDataProtectionKeychain : @(YES),
145 (id)kSecReturnAttributes : @(YES),
146 };
147 NSDictionary *newAttributes = @{
148 (id)kSecAttrAccount : newAccount,
149 (id)kSecAttrService : newService,
150 };
151
152 OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)updateQuery, (__bridge CFDictionaryRef)newAttributes);
153 return status;
154 }
155
156
157 @end