Skip to content

Commit 4d6b38a

Browse files
authored
Merge pull request #78 from outfoxx/feature/accessibility
Add accessibility support to `SecKey`, `SecKeyPair`, `SecCertificate` & `SecIdentity`
2 parents a3ed0f8 + 9e5dccf commit 4d6b38a

21 files changed

+677
-355
lines changed

.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,3 @@
66
/TestResults
77

88
/ShieldHost/**/xcuserdata/
9-
/ShieldHost/**/project.xcworkspace/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict/>
5+
</plist>

ShieldHost/ShieldHost.xcodeproj/project.pbxproj

+16-36
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88

99
/* Begin PBXBuildFile section */
1010
AA2151F02975D9CF0072F6CA /* ShieldHostApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA2151EF2975D9CF0072F6CA /* ShieldHostApp.swift */; };
11-
AA2151F42975D9D00072F6CA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AA2151F32975D9D00072F6CA /* Assets.xcassets */; };
12-
AA2151F82975D9D00072F6CA /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AA2151F72975D9D00072F6CA /* Preview Assets.xcassets */; };
1311
AA2152422975DF5F0072F6CA /* CertificationRequestBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA2152342975DF5F0072F6CA /* CertificationRequestBuilderTests.swift */; };
1412
AA2152442975DF5F0072F6CA /* HmacTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA2152362975DF5F0072F6CA /* HmacTests.swift */; };
1513
AA2152452975DF5F0072F6CA /* OIDTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA2152372975DF5F0072F6CA /* OIDTests.swift */; };
@@ -26,8 +24,6 @@
2624
AA2152632975E3600072F6CA /* Shield in Frameworks */ = {isa = PBXBuildFile; productRef = AA2152622975E3600072F6CA /* Shield */; };
2725
AA5768A12975E7C300142200 /* ShieldHost Watch App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = AA5768A02975E7C300142200 /* ShieldHost Watch App.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
2826
AA5768A62975E7C300142200 /* ShieldHostApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA5768A52975E7C300142200 /* ShieldHostApp.swift */; };
29-
AA5768AA2975E7C400142200 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AA5768A92975E7C400142200 /* Assets.xcassets */; };
30-
AA5768AD2975E7C400142200 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AA5768AC2975E7C400142200 /* Preview Assets.xcassets */; };
3127
AA5768E02975E85E00142200 /* Shield in Frameworks */ = {isa = PBXBuildFile; productRef = AA5768DF2975E85E00142200 /* Shield */; };
3228
AA5768E12975E87C00142200 /* HmacTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA2152362975DF5F0072F6CA /* HmacTests.swift */; };
3329
AA5768E22975E87C00142200 /* DistinguishedNameComposerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA2152382975DF5F0072F6CA /* DistinguishedNameComposerTests.swift */; };
@@ -42,6 +38,8 @@
4238
AA5768EC2975E87C00142200 /* DigestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA21523D2975DF5F0072F6CA /* DigestTests.swift */; };
4339
AA5768ED2975E87C00142200 /* CertificateBuilderECTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA21523A2975DF5F0072F6CA /* CertificateBuilderECTests.swift */; };
4440
AA5768EE2975E87C00142200 /* DistinguishedNameParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA2152402975DF5F0072F6CA /* DistinguishedNameParserTests.swift */; };
41+
AAC4C7862ADDFFAD00487E0A /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC4C7852ADDFFAD00487E0A /* Utils.swift */; };
42+
AAC4C7872ADDFFAD00487E0A /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC4C7852ADDFFAD00487E0A /* Utils.swift */; };
4543
AADD77C929A3E278005D0955 /* CertificateDecoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AADD77C629A3E278005D0955 /* CertificateDecoderTests.swift */; };
4644
AADD77CA29A3E278005D0955 /* CertificateDecoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AADD77C629A3E278005D0955 /* CertificateDecoderTests.swift */; };
4745
/* End PBXBuildFile section */
@@ -87,10 +85,7 @@
8785
/* Begin PBXFileReference section */
8886
AA2151EC2975D9CF0072F6CA /* ShieldHost.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ShieldHost.app; sourceTree = BUILT_PRODUCTS_DIR; };
8987
AA2151EF2975D9CF0072F6CA /* ShieldHostApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShieldHostApp.swift; sourceTree = "<group>"; };
90-
AA2151F12975D9CF0072F6CA /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
91-
AA2151F32975D9D00072F6CA /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
9288
AA2151F52975D9D00072F6CA /* ShieldHost.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShieldHost.entitlements; sourceTree = "<group>"; };
93-
AA2151F72975D9D00072F6CA /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
9489
AA2151FD2975D9D00072F6CA /* ShieldHostTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ShieldHostTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
9590
AA21521F2975DCA40072F6CA /* Shield */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Shield; path = ..; sourceTree = "<group>"; };
9691
AA2152342975DF5F0072F6CA /* CertificationRequestBuilderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CertificationRequestBuilderTests.swift; sourceTree = "<group>"; };
@@ -109,10 +104,9 @@
109104
AA57689B2975E7C300142200 /* ShieldHost Watch Container.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ShieldHost Watch Container.app"; sourceTree = BUILT_PRODUCTS_DIR; };
110105
AA5768A02975E7C300142200 /* ShieldHost Watch App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ShieldHost Watch App.app"; sourceTree = BUILT_PRODUCTS_DIR; };
111106
AA5768A52975E7C300142200 /* ShieldHostApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShieldHostApp.swift; sourceTree = "<group>"; };
112-
AA5768A72975E7C300142200 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
113-
AA5768A92975E7C400142200 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
114-
AA5768AC2975E7C400142200 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
115107
AA5768B22975E7C400142200 /* ShieldHost Watch AppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ShieldHost Watch AppTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
108+
AAC4C7812ADDCBE600487E0A /* ShieldHost Watch App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "ShieldHost Watch App.entitlements"; sourceTree = "<group>"; };
109+
AAC4C7852ADDFFAD00487E0A /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; };
116110
AADD77C629A3E278005D0955 /* CertificateDecoderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CertificateDecoderTests.swift; sourceTree = "<group>"; };
117111
/* End PBXFileReference section */
118112

@@ -178,22 +172,11 @@
178172
isa = PBXGroup;
179173
children = (
180174
AA2151EF2975D9CF0072F6CA /* ShieldHostApp.swift */,
181-
AA2151F12975D9CF0072F6CA /* ContentView.swift */,
182-
AA2151F32975D9D00072F6CA /* Assets.xcassets */,
183175
AA2151F52975D9D00072F6CA /* ShieldHost.entitlements */,
184-
AA2151F62975D9D00072F6CA /* Preview Content */,
185176
);
186177
path = ShieldHost;
187178
sourceTree = "<group>";
188179
};
189-
AA2151F62975D9D00072F6CA /* Preview Content */ = {
190-
isa = PBXGroup;
191-
children = (
192-
AA2151F72975D9D00072F6CA /* Preview Assets.xcassets */,
193-
);
194-
path = "Preview Content";
195-
sourceTree = "<group>";
196-
};
197180
AA21521E2975DCA40072F6CA /* Packages */ = {
198181
isa = PBXGroup;
199182
children = (
@@ -219,6 +202,7 @@
219202
AA21523F2975DF5F0072F6CA /* SecIdentityTests.swift */,
220203
AA2152402975DF5F0072F6CA /* DistinguishedNameParserTests.swift */,
221204
AA2152412975DF5F0072F6CA /* SecKeyPairTests.swift */,
205+
AAC4C7852ADDFFAD00487E0A /* Utils.swift */,
222206
);
223207
name = Tests;
224208
path = ../Tests;
@@ -234,22 +218,12 @@
234218
AA5768A42975E7C300142200 /* ShieldHost Watch App */ = {
235219
isa = PBXGroup;
236220
children = (
221+
AAC4C7812ADDCBE600487E0A /* ShieldHost Watch App.entitlements */,
237222
AA5768A52975E7C300142200 /* ShieldHostApp.swift */,
238-
AA5768A72975E7C300142200 /* ContentView.swift */,
239-
AA5768A92975E7C400142200 /* Assets.xcassets */,
240-
AA5768AB2975E7C400142200 /* Preview Content */,
241223
);
242224
path = "ShieldHost Watch App";
243225
sourceTree = "<group>";
244226
};
245-
AA5768AB2975E7C400142200 /* Preview Content */ = {
246-
isa = PBXGroup;
247-
children = (
248-
AA5768AC2975E7C400142200 /* Preview Assets.xcassets */,
249-
);
250-
path = "Preview Content";
251-
sourceTree = "<group>";
252-
};
253227
/* End PBXGroup section */
254228

255229
/* Begin PBXNativeTarget section */
@@ -402,8 +376,6 @@
402376
isa = PBXResourcesBuildPhase;
403377
buildActionMask = 2147483647;
404378
files = (
405-
AA2151F82975D9D00072F6CA /* Preview Assets.xcassets in Resources */,
406-
AA2151F42975D9D00072F6CA /* Assets.xcassets in Resources */,
407379
);
408380
runOnlyForDeploymentPostprocessing = 0;
409381
};
@@ -425,8 +397,6 @@
425397
isa = PBXResourcesBuildPhase;
426398
buildActionMask = 2147483647;
427399
files = (
428-
AA5768AD2975E7C400142200 /* Preview Assets.xcassets in Resources */,
429-
AA5768AA2975E7C400142200 /* Assets.xcassets in Resources */,
430400
);
431401
runOnlyForDeploymentPostprocessing = 0;
432402
};
@@ -457,6 +427,7 @@
457427
AA2152452975DF5F0072F6CA /* OIDTests.swift in Sources */,
458428
AA2152462975DF5F0072F6CA /* DistinguishedNameComposerTests.swift in Sources */,
459429
AA2152492975DF5F0072F6CA /* SecKeyTests.swift in Sources */,
430+
AAC4C7862ADDFFAD00487E0A /* Utils.swift in Sources */,
460431
AA21524D2975DF5F0072F6CA /* SecIdentityTests.swift in Sources */,
461432
AA21524A2975DF5F0072F6CA /* SecCertificateTests.swift in Sources */,
462433
AA21524E2975DF5F0072F6CA /* DistinguishedNameParserTests.swift in Sources */,
@@ -486,6 +457,7 @@
486457
AA5768EE2975E87C00142200 /* DistinguishedNameParserTests.swift in Sources */,
487458
AA5768E72975E87C00142200 /* SecIdentityTests.swift in Sources */,
488459
AA5768EC2975E87C00142200 /* DigestTests.swift in Sources */,
460+
AAC4C7872ADDFFAD00487E0A /* Utils.swift in Sources */,
489461
AA5768E82975E87C00142200 /* CryptorTests.swift in Sources */,
490462
AA5768E22975E87C00142200 /* DistinguishedNameComposerTests.swift in Sources */,
491463
AA5768ED2975E87C00142200 /* CertificateBuilderECTests.swift in Sources */,
@@ -765,8 +737,10 @@
765737
AA5768C52975E7C500142200 /* Debug */ = {
766738
isa = XCBuildConfiguration;
767739
buildSettings = {
740+
CODE_SIGN_ENTITLEMENTS = "ShieldHost Watch App/ShieldHost Watch App.entitlements";
768741
CODE_SIGN_STYLE = Automatic;
769742
CURRENT_PROJECT_VERSION = 1;
743+
DEVELOPMENT_TEAM = "";
770744
ENABLE_PREVIEWS = YES;
771745
GENERATE_INFOPLIST_FILE = YES;
772746
INFOPLIST_KEY_CFBundleDisplayName = ShieldHost;
@@ -790,8 +764,10 @@
790764
AA5768C62975E7C500142200 /* Release */ = {
791765
isa = XCBuildConfiguration;
792766
buildSettings = {
767+
CODE_SIGN_ENTITLEMENTS = "ShieldHost Watch App/ShieldHost Watch App.entitlements";
793768
CODE_SIGN_STYLE = Automatic;
794769
CURRENT_PROJECT_VERSION = 1;
770+
DEVELOPMENT_TEAM = "";
795771
ENABLE_PREVIEWS = YES;
796772
GENERATE_INFOPLIST_FILE = YES;
797773
INFOPLIST_KEY_CFBundleDisplayName = ShieldHost;
@@ -819,6 +795,7 @@
819795
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
820796
CODE_SIGN_STYLE = Automatic;
821797
CURRENT_PROJECT_VERSION = 1;
798+
DEVELOPMENT_TEAM = "";
822799
INFOPLIST_KEY_CFBundleDisplayName = ShieldHost;
823800
MARKETING_VERSION = 1.0;
824801
PRODUCT_BUNDLE_IDENTIFIER = io.outfoxx.ShieldHost;
@@ -834,6 +811,7 @@
834811
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
835812
CODE_SIGN_STYLE = Automatic;
836813
CURRENT_PROJECT_VERSION = 1;
814+
DEVELOPMENT_TEAM = "";
837815
INFOPLIST_KEY_CFBundleDisplayName = ShieldHost;
838816
MARKETING_VERSION = 1.0;
839817
PRODUCT_BUNDLE_IDENTIFIER = io.outfoxx.ShieldHost;
@@ -851,6 +829,7 @@
851829
BUNDLE_LOADER = "$(TEST_HOST)";
852830
CODE_SIGN_STYLE = Automatic;
853831
CURRENT_PROJECT_VERSION = 1;
832+
DEVELOPMENT_TEAM = "";
854833
GENERATE_INFOPLIST_FILE = YES;
855834
MARKETING_VERSION = 1.0;
856835
PRODUCT_BUNDLE_IDENTIFIER = "io.outfoxx.ShieldHost-Watch-AppTests";
@@ -870,6 +849,7 @@
870849
BUNDLE_LOADER = "$(TEST_HOST)";
871850
CODE_SIGN_STYLE = Automatic;
872851
CURRENT_PROJECT_VERSION = 1;
852+
DEVELOPMENT_TEAM = "";
873853
GENERATE_INFOPLIST_FILE = YES;
874854
MARKETING_VERSION = 1.0;
875855
PRODUCT_BUNDLE_IDENTIFIER = "io.outfoxx.ShieldHost-Watch-AppTests";

ShieldHost/ShieldHost.xcodeproj/project.xcworkspace/contents.xcworkspacedata

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>IDEDidComputeMac32BitWarning</key>
6+
<true/>
7+
</dict>
8+
</plist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
{
2+
"object": {
3+
"pins": [
4+
{
5+
"package": "BigInt",
6+
"repositoryURL": "https://github.com/attaswift/BigInt.git",
7+
"state": {
8+
"branch": null,
9+
"revision": "0ed110f7555c34ff468e72e1686e59721f2b0da6",
10+
"version": "5.3.0"
11+
}
12+
},
13+
{
14+
"package": "Float16",
15+
"repositoryURL": "https://github.com/SusanDoggie/Float16.git",
16+
"state": {
17+
"branch": null,
18+
"revision": "936ae66adccf1c91bcaeeb9c0cddde78a13695c3",
19+
"version": "1.1.1"
20+
}
21+
},
22+
{
23+
"package": "PotentCodables",
24+
"repositoryURL": "https://github.com/outfoxx/PotentCodables.git",
25+
"state": {
26+
"branch": null,
27+
"revision": "0c423eb5fdbbefffd36926430bf99f9f998c0cad",
28+
"version": "3.1.1"
29+
}
30+
},
31+
{
32+
"package": "Regex",
33+
"repositoryURL": "https://github.com/sharplet/Regex.git",
34+
"state": {
35+
"branch": null,
36+
"revision": "76c2b73d4281d77fc3118391877efd1bf972f515",
37+
"version": "2.1.1"
38+
}
39+
},
40+
{
41+
"package": "swift-algorithms",
42+
"repositoryURL": "https://github.com/apple/swift-algorithms",
43+
"state": {
44+
"branch": null,
45+
"revision": "b14b7f4c528c942f121c8b860b9410b2bf57825e",
46+
"version": "1.0.0"
47+
}
48+
},
49+
{
50+
"package": "swift-collections",
51+
"repositoryURL": "https://github.com/apple/swift-collections.git",
52+
"state": {
53+
"branch": null,
54+
"revision": "937e904258d22af6e447a0b72c0bc67583ef64a2",
55+
"version": "1.0.4"
56+
}
57+
},
58+
{
59+
"package": "SwiftDocCPlugin",
60+
"repositoryURL": "https://github.com/apple/swift-docc-plugin",
61+
"state": {
62+
"branch": null,
63+
"revision": "10bc670db657d11bdd561e07de30a9041311b2b1",
64+
"version": "1.1.0"
65+
}
66+
},
67+
{
68+
"package": "SymbolKit",
69+
"repositoryURL": "https://github.com/apple/swift-docc-symbolkit",
70+
"state": {
71+
"branch": null,
72+
"revision": "b45d1f2ed151d057b54504d653e0da5552844e34",
73+
"version": "1.0.0"
74+
}
75+
},
76+
{
77+
"package": "swift-numerics",
78+
"repositoryURL": "https://github.com/apple/swift-numerics",
79+
"state": {
80+
"branch": null,
81+
"revision": "0a5bc04095a675662cf24757cc0640aa2204253b",
82+
"version": "1.0.2"
83+
}
84+
}
85+
]
86+
},
87+
"version": 1
88+
}

Sources/ShieldSecurity/AlgorithmIdentifier.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public extension AlgorithmIdentifier {
6868

6969
case .ec:
7070
let curve: OID
71-
switch try publicKey.attributes()[kSecAttrKeySizeInBits as String] as? Int ?? 0 {
71+
switch try publicKey.keyAttributes()[kSecAttrKeySizeInBits as String] as? Int ?? 0 {
7272
case 192:
7373
// P-192, secp192r1
7474
curve = iso.memberBody.us.ansix962.curves.prime.prime192v1.oid
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//
2+
// SecAccessibility.swift
3+
// Shield
4+
//
5+
// Copyright © 2021 Outfox, inc.
6+
//
7+
//
8+
// Distributed under the MIT License, See LICENSE for details.
9+
//
10+
11+
import Security
12+
13+
14+
public enum SecAccessibility: Equatable {
15+
case `default`
16+
case unlocked(afterFirst: Bool, shared: Bool)
17+
case passcodeEnabled
18+
#if ACCESSIBILITY_ALWAYS_ENABLED
19+
case always(shared: Bool)
20+
#endif
21+
}
22+
23+
24+
extension SecAccessibility {
25+
26+
var attr: Any {
27+
28+
switch self {
29+
30+
#if ACCESSIBILITY_ALWAYS_ENABLED
31+
case .always(shared: true):
32+
return kSecAttrAccessibleAlways as String
33+
34+
case .always(shared: false):
35+
return kSecAttrAccessibleAlwaysThisDeviceOnly as String
36+
#endif
37+
38+
case .unlocked(afterFirst: true, shared: true):
39+
return kSecAttrAccessibleAfterFirstUnlock as String
40+
41+
case .unlocked(afterFirst: true, shared: false):
42+
return kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly as String
43+
44+
case .unlocked(afterFirst: false, shared: true), .default:
45+
return kSecAttrAccessibleWhenUnlocked as String
46+
47+
case .unlocked(afterFirst: false, shared: false):
48+
return kSecAttrAccessibleWhenUnlockedThisDeviceOnly as String
49+
50+
case .passcodeEnabled:
51+
return kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly as String
52+
}
53+
}
54+
55+
}

0 commit comments

Comments
 (0)