Skip to content

Commit dbb58fc

Browse files
committed
Proper errors thrown. Removed debug print. Added aes encryption unit tests.
1 parent dc6ba96 commit dbb58fc

File tree

8 files changed

+83
-19
lines changed

8 files changed

+83
-19
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ To add support for NFC YubiKeys in your application, follow these steps:
147147
<string>A0000005272101</string> // OATH AID
148148
<string>A000000308</string> // PIV AID
149149
<string>A000000527200101</string> // YubiKey application/OTP AID (for HMAC SHA1 challenge-response)
150+
<string>A000000151000000</string> // YubiKey Security Domain
150151
</array>
151152
</plist>
152153
```

YubiKit/YubiKit/Connections/SCP/YKFSCPProcessor.m

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#import "YKFAPDU.h"
2626
#import "YKFSCPProcessor.h"
2727
#import "YKFTLVRecord.h"
28+
#import "YKFSessionError.h"
29+
#import "YKFSessionError+Private.h"
2830

2931
@interface YKFSCPProcessor ()
3032
@property (nonatomic, strong) YKFSCPState *state;
@@ -55,7 +57,6 @@ + (void)processorWithSCPKeyParams:(id<YKFSCPKeyParamsProtocol> _Nonnull)scpKeyPa
5557
if ([scpKeyParams isKindOfClass:[YKFSCP03KeyParams class]]) {
5658
YKFSCP03KeyParams *scp03KeyParams = (YKFSCP03KeyParams *)scpKeyParams;
5759
NSData *hostChallenge = [NSData ykf_randomDataOfSize:8];
58-
NSLog(@"Send challenge: %@", [hostChallenge ykf_hexadecimalString]);
5960

6061
uint8_t insInitializeUpdate = 0x50;
6162
YKFAPDU *apdu = [[YKFAPDU alloc] initWithCla:0x80 ins:insInitializeUpdate p1:scp03KeyParams.keyRef.kvn p2:0x00 data:hostChallenge type:YKFAPDUTypeShort];
@@ -68,7 +69,7 @@ + (void)processorWithSCPKeyParams:(id<YKFSCPKeyParamsProtocol> _Nonnull)scpKeyPa
6869

6970
if (result.length < 29) { // Ensure sufficient length
7071
if (completion) {
71-
completion(nil, [NSError errorWithDomain:@"SCPErrorDomain" code:-2 userInfo:@{NSLocalizedDescriptionKey: @"Unexpected result"}]);
72+
completion(nil, [YKFSessionError errorWithCode:YKFSessionErrorUnexpectedResult]);
7273
}
7374
return;
7475
}
@@ -87,7 +88,7 @@ + (void)processorWithSCPKeyParams:(id<YKFSCPKeyParamsProtocol> _Nonnull)scpKeyPa
8788

8889
if (![genCardCryptogram ykf_constantTimeCompareWithData:cardCryptogram]) {
8990
if (completion) {
90-
completion(nil, [NSError errorWithDomain:@"SCPErrorDomain" code:-3 userInfo:@{NSLocalizedDescriptionKey: @"Invalid card cryptogram"}]);
91+
completion(nil, [YKFSessionError errorWithCode:YKFSessionErrorUnexpectedResult]);
9192
}
9293
return;
9394
}
@@ -177,7 +178,8 @@ + (void)processorWithSCPKeyParams:(id<YKFSCPKeyParamsProtocol> _Nonnull)scpKeyPa
177178
}
178179
NSArray<YKFTLVRecord *> *tlvs = [YKFTLVRecord sequenceOfRecordsFromData:result];
179180
if (tlvs.count != 2 || [tlvs[0] tag] != 0x5f49 || [tlvs[1] tag] != 0x86) {
180-
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"Invalid response TLVs" userInfo:nil];
181+
completion(nil, [YKFSessionError errorWithCode:YKFSessionErrorUnexpectedResult]);
182+
return;
181183
}
182184

183185
NSData *epkSdEckaEncodedPoint = tlvs[0].value;
@@ -225,12 +227,8 @@ + (void)processorWithSCPKeyParams:(id<YKFSCPKeyParamsProtocol> _Nonnull)scpKeyPa
225227

226228
YKFSCPProcessor *processor = [[YKFSCPProcessor alloc] initWithState:state];
227229
completion(processor, nil);
228-
229-
NSLog(@"✅ done configuring SCP11");
230230
}];
231231
}
232-
233-
234232
}
235233

236234

@@ -241,8 +239,6 @@ - (void)executeCommand:(YKFAPDU *)apdu
241239
usingSmartCardInterface:(YKFSmartCardInterface *)smartCardInterface
242240
completion:(YKFSmartCardInterfaceResponseBlock)completion {
243241

244-
NSLog(@"👾 process %@, %@", apdu, self.state);
245-
246242
NSData *data;
247243
if (encrypt) {
248244
NSError *error = nil;
@@ -271,7 +267,6 @@ - (void)executeCommand:(YKFAPDU *)apdu
271267
YKFAPDU *processedAPDU = [[YKFAPDU alloc] initWithCla:cla ins:apdu.ins p1:apdu.p1 p2:apdu.p2 data:dataAndMac type:apdu.type];
272268

273269
NSMutableData *resultData = [NSMutableData new];
274-
275270
[smartCardInterface executeRecursiveCommand:processedAPDU sendRemainingIns:sendRemainingIns timeout:20 data:resultData completion:^(NSData * _Nullable result, NSError * _Nullable error) {
276271
if (error) {
277272
completion(nil, error);

YubiKit/YubiKit/Connections/SCP/YKFSCPSecurityDomainSession.m

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#import "YKFNSDataAdditions+Private.h"
2424
#import "YKFSCPProcessor.h"
2525
#import "YKFSCPKeyParamsProtocol.h"
26+
#import "YKFSessionError.h"
27+
#import "YKFSessionError+Private.h"
2628

2729
@implementation YKFSecurityDomainSession
2830

@@ -97,7 +99,8 @@ - (void)getCertificateBundleWithKeyRef:(YKFSCPKeyRef *)keyRef completion:(YKFSec
9799
}
98100
}
99101
if (records.count != certs.count) {
100-
NSLog(@"ERROR");
102+
completion(nil, [YKFSessionError errorWithCode:YKFSessionErrorUnexpectedResult]);
103+
return;
101104
}
102105
completion(certs, nil);
103106
}];

YubiKit/YubiKit/Connections/SCP/YKFSCPState.m

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@ - (instancetype)initWithSessionKeys:(YKFSCPSessionKeys *)sessionKeys macChain:(N
2828
return self;
2929
}
3030

31-
- (NSData *)encrypt:(NSData *)data error:(NSError **)error {
32-
NSLog(@"👾 encrypt %@ using %@", [data ykf_hexadecimalString], self);
33-
31+
- (NSData *)encrypt:(NSData *)data error:(NSError **)error {
3432
NSData *paddedData = [data ykf_bitPadded];
3533
NSMutableData *ivData = [NSMutableData dataWithLength:12];
3634
uint32_t encCounterBE = CFSwapInt32HostToBig(self.encCounter);
@@ -44,8 +42,6 @@ - (NSData *)encrypt:(NSData *)data error:(NSError **)error {
4442
}
4543

4644
- (NSData *)decrypt:(NSData *)data error:(NSError **)error {
47-
NSLog(@"decrypt: %@", [data ykf_hexadecimalString]);
48-
4945
NSMutableData *ivData = [NSMutableData data];
5046
uint8_t paddingByte = 0x80;
5147
[ivData appendBytes:&paddingByte length:1];
@@ -60,7 +56,6 @@ - (NSData *)decrypt:(NSData *)data error:(NSError **)error {
6056

6157
if (!decrypted) return nil;
6258

63-
NSLog(@"decrypted: %@", [decrypted ykf_hexadecimalString]);
6459
return [self unpadData:decrypted];
6560
}
6661

YubiKit/YubiKit/Connections/Shared/Errors/YKFSessionError.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,11 @@ typedef NS_ENUM(NSUInteger, YKFSessionErrorCode) {
7171

7272
/*! Invalid session state. This can be caused by another session connecting to the Yubkey or stale stored state.
7373
*/
74-
YKFSessionErrorInvalidSessionStateStatusCode = 0x000008
74+
YKFSessionErrorInvalidSessionStateStatusCode = 0x000008,
75+
76+
/*! Unexpected result. This is caused when the YubiKey returns unexpected data.
77+
*/
78+
YKFSessionErrorUnexpectedResult = 0x000009
7579
};
7680

7781
/*!

YubiKit/YubiKit/Connections/Shared/Errors/YKFSessionError.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
static NSString* const YKFSessionErrorConnectionLostDescription = @"Connection lost.";
2626
static NSString* const YKFSessionErrorNoConnectionDescription = @"Connection is not found.";
2727
static NSString* const YKFSessionErrorInvalidSessionStateDescription = @"Invalid session state.";
28+
static NSString* const YKFSessionErrorUnexpectedResultDescription = @"Unexpted data returned by YubiKey.";
2829

2930
#pragma mark - YKFSessionError
3031

@@ -56,6 +57,7 @@ + (void)buildErrorMap {
5657
@(YKFSessionErrorConnectionLost): YKFSessionErrorConnectionLostDescription,
5758
@(YKFSessionErrorNoConnection): YKFSessionErrorNoConnectionDescription,
5859
@(YKFSessionErrorInvalidSessionStateStatusCode): YKFSessionErrorInvalidSessionStateDescription,
60+
@(YKFSessionErrorUnexpectedResult): YKFSessionErrorUnexpectedResultDescription,
5961
};
6062
}
6163

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright 2018-2025 Yubico AB
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#import <XCTest/XCTest.h>
16+
#import "YKFTestCase.h"
17+
#import "YKFNSDataAdditions+Private.h"
18+
#import "YKFSCPKeyRef.h"
19+
#import "YKFSCPState.h"
20+
#import "YKFSCPStaticKeys.h"
21+
#import "YKFSCPSessionKeys.h"
22+
23+
@interface YKFSCPTests : XCTestCase
24+
25+
@end
26+
27+
@implementation YKFSCPTests
28+
29+
-(void)testEncryptAESECB {
30+
NSData *key = [NSData dataFromHexString:@"5ec1bf26a34a6300c23bb45a9f8420495e472259a729439158766cfee5497c2b"];
31+
NSData *msg = [@"Hello World!0000" dataUsingEncoding: NSUTF8StringEncoding];
32+
NSData *expectedResult = [NSData dataFromHexString:@"0cb774fc5a0a3d4fbb9a6b582cb56b84"];
33+
NSData *result = [msg ykf_cryptOperation:kCCEncrypt algorithm:kCCAlgorithmAES mode:kCCModeECB key:key iv:nil];
34+
XCTAssertEqualObjects(result, expectedResult);
35+
}
36+
37+
-(void)testDecryptAESECB {
38+
NSData *data = [NSData dataFromHexString:@"0cb774fc5a0a3d4fbb9a6b582cb56b84fa4e95678dbb6cc763bb4ce68df9155ffa4e95678dbb6cc763bb4ce68df9155ffa4e95678dbb6cc763bb4ce68df9155f"];
39+
NSData *key = [NSData dataFromHexString:@"5ec1bf26a34a6300c23bb45a9f8420495e472259a729439158766cfee5497c2b"];
40+
NSString *result = [[NSString alloc] initWithData:[data ykf_cryptOperation:kCCDecrypt algorithm:kCCAlgorithmAES mode:kCCModeECB key:key iv:nil] encoding: NSUTF8StringEncoding];
41+
NSString *expectedResult = @"Hello World!0000000000000000000000000000000000000000000000000000";
42+
XCTAssertEqualObjects(result, expectedResult);
43+
}
44+
45+
-(void)testEncryptAESCBC {
46+
NSData *key = [NSData dataFromHexString:@"5ec1bf26a34a6300c23bb45a9f842049"];
47+
NSData *iv = [NSData dataFromHexString:@"000102030405060708090a0b0c0d0e0f"];
48+
NSData *msg = [@"Hello World!0000" dataUsingEncoding: NSUTF8StringEncoding];
49+
NSData *expectedResult = [NSData dataFromHexString:@"9dcb09c51227ea753fad4c6bda8efa46"];
50+
NSData *result = [msg ykf_cryptOperation:kCCEncrypt algorithm:kCCAlgorithmAES mode:kCCModeCBC key:key iv:iv];
51+
XCTAssertEqualObjects(result, expectedResult);
52+
}
53+
54+
-(void)testDecryptAESCBC {
55+
NSData *data = [NSData dataFromHexString:@"9dcb09c51227ea753fad4c6bda8efa46"];
56+
NSData *key = [NSData dataFromHexString:@"5ec1bf26a34a6300c23bb45a9f842049"];
57+
NSData *iv = [NSData dataFromHexString:@"000102030405060708090a0b0c0d0e0f"];
58+
NSString *result = [[NSString alloc] initWithData:[data ykf_cryptOperation:kCCDecrypt algorithm:kCCAlgorithmAES mode:kCCModeCBC key:key iv:iv] encoding: NSUTF8StringEncoding];
59+
NSString *expectedResult = @"Hello World!0000";
60+
XCTAssertEqualObjects(result, expectedResult);
61+
}
62+
63+
@end

YubiKitTests/HostApp/Info.plist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
<string>A0000005272101</string>
6060
<string>A000000308</string>
6161
<string>A000000527200101</string>
62+
<string>A000000151000000</string>
6263
</array>
6364
</dict>
6465
</plist>

0 commit comments

Comments
 (0)