Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Modules/CryptoLib/Sources/CryptoObjC/include/Decrypt.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (nullable id)cdocInfo:(NSString *)fullPath error:(NSError **)error;
+ (void)decryptFile:(NSString *)fullPath withCert:(NSData *)certData withToken:(id)smartToken
completion:(void (^)(NSDictionary<NSString*,NSData*> * _Nullable, NSError * _Nullable))completion;
+ (NSDictionary<NSString*,NSData*> * _Nullable)decryptFile:(NSString *)fullPath withPassword:(NSString*)password error:(NSError**)error;
+ (NSDictionary<NSString*,NSData*> * _Nullable)decryptFile:(NSString *)fullPath withPassword:(NSString*)password lockIndex:(NSInteger)lockIndex error:(NSError**)error NS_SWIFT_NAME(decryptFile(_:withPassword:lockIndex:));
@end

NS_ASSUME_NONNULL_END
63 changes: 49 additions & 14 deletions Modules/CryptoLib/Sources/CryptoObjC/include/Decrypt.mm
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ static CertType certTypeFromLabel(NSString * _Nullable type) {

@implementation Addressee (label)

- (instancetype)initWithLabel:(const std::string &)label pub:(NSData*)pub concatKDFAlgorithmURI:(NSString *)concatKDFAlgorithmURI {
- (instancetype)initWithLabel:(const std::string &)label pub:(NSData*)pub concatKDFAlgorithmURI:(NSString *)concatKDFAlgorithmURI lockIndex:(NSInteger)lockIndex {
std::map<std::string, std::string> info = libcdoc::Lock::parseLabel(label);
NSString *cn = info.contains("cn") ? [NSString stringWithStdString:info["cn"]] : [NSString stringWithStdString:label];
NSString *type = info.contains("type") ? [NSString stringWithStdString:info["type"]] : nil;
Expand All @@ -46,7 +46,7 @@ - (instancetype)initWithLabel:(const std::string &)label pub:(NSData*)pub concat
}
}

if (self = [self initWithCnVal:cn serialNumber:serial certType:certTypeFromLabel(type) validTo:validTo data:pub concatKDFAlgorithmURI:concatKDFAlgorithmURI lockLabel:@"" lockType:@""]) {
if (self = [self initWithCnVal:cn serialNumber:serial certType:certTypeFromLabel(type) validTo:validTo data:pub concatKDFAlgorithmURI:concatKDFAlgorithmURI lockLabel:([NSString stringWithStdString:label] ?: @"") lockType:@"" lockIndex:lockIndex]) {
}
return self;
}
Expand Down Expand Up @@ -105,17 +105,19 @@ + (CdocInfo*)cdocInfo:(NSString *)fullPath error:(NSError**)error {
return [NSError cryptoError:@"Parsing failed" error:error];
}
NSMutableArray<Addressee*> *addressees = [[NSMutableArray alloc] init];
for(const libcdoc::Lock &lock: reader->getLocks())
const auto &locks = reader->getLocks();
for(NSInteger lockIndex = 0; lockIndex < (NSInteger)locks.size(); lockIndex++)
{
const libcdoc::Lock &lock = locks[lockIndex];
if(lock.isCDoc1()) {
NSString* concatKDFAlgorithmURI = @"";
if (!lock.isRSA()) {
concatKDFAlgorithmURI = [NSString stringWithStdString:lock.getString(libcdoc::Lock::CONCAT_DIGEST)];
}
[addressees addObject:[[Addressee alloc] initWithLabel:lock.label pub:[NSData dataFromVector:lock.getBytes(libcdoc::Lock::CERT)] concatKDFAlgorithmURI:concatKDFAlgorithmURI]];
[addressees addObject:[[Addressee alloc] initWithLabel:lock.label pub:[NSData dataFromVector:lock.getBytes(libcdoc::Lock::CERT)] concatKDFAlgorithmURI:concatKDFAlgorithmURI lockIndex:lockIndex]];
} else if(lock.isPKI()) {
[addressees addObject:[[Addressee alloc] initWithLabel:lock.label pub:[NSData dataFromVector:lock.getBytes(libcdoc::Lock::RCPT_KEY)] concatKDFAlgorithmURI:@""]];
} else if(lock.isSymmetric()) {
[addressees addObject:[[Addressee alloc] initWithLabel:lock.label pub:[NSData dataFromVector:lock.getBytes(libcdoc::Lock::RCPT_KEY)] concatKDFAlgorithmURI:@"" lockIndex:lockIndex]];
} else if(lock.type == libcdoc::Lock::Type::PASSWORD) {
std::map<std::string, std::string> info = libcdoc::Lock::parseLabel(lock.label);
NSString *cnVal = info.contains("label")
? [NSString stringWithStdString:info["label"]]
Expand All @@ -129,9 +131,30 @@ + (CdocInfo*)cdocInfo:(NSString *)fullPath error:(NSError**)error {
data:[NSData data]
concatKDFAlgorithmURI:@""
lockLabel:rawLockLabel
lockType:lockTypeName(lock.type)]];
lockType:lockTypeName(lock.type)
lockIndex:lockIndex]];
} else if(lock.isSymmetric()) {
[addressees addObject:[[Addressee alloc]
initWithCnVal:[NSString stringWithStdString:lock.label] ?: @""
serialNumber:nil
certType:CertTypeUnknownType
validTo:nil
data:[NSData data]
concatKDFAlgorithmURI:@""
lockLabel:@""
lockType:@""
lockIndex:lockIndex]];
} else {
[addressees addObject:[[Addressee alloc] initWithData:[NSData data] cnVal:@"Unknown capsule"]];
[addressees addObject:[[Addressee alloc]
initWithCnVal:@"Unknown capsule"
serialNumber:nil
certType:CertTypeUnknownType
validTo:nil
data:[NSData data]
concatKDFAlgorithmURI:@""
lockLabel:@""
lockType:@""
lockIndex:lockIndex]];
}
}
if (cdocInfo != nil) {
Expand Down Expand Up @@ -199,7 +222,7 @@ + (void)decryptFile:(NSString *)fullPath withCert:(NSData *)certData withToken:(
});
}

+ (NSDictionary<NSString*,NSData*> *)decryptFile:(NSString *)fullPath withPassword:(NSString*)password error:(NSError**)error {
+ (NSDictionary<NSString*,NSData*> *)decryptFile:(NSString *)fullPath withPassword:(NSString*)password lockIndex:(NSInteger)lockIndex error:(NSError**)error {
struct PasswordBackend: public libcdoc::CryptoBackend {
NSString *password;
PasswordBackend(NSString *pass) : password(pass) {}
Expand All @@ -213,12 +236,24 @@ + (void)decryptFile:(NSString *)fullPath withCert:(NSData *)certData withToken:(
return [NSError cryptoError:@"Failed to create CDocReader" error:error];
}

int idx = -1;
const auto& locks = reader->getLocks();
for (size_t i = 0; i < locks.size(); i++) {
if (locks[i].type == libcdoc::Lock::Type::PASSWORD) {
idx = (int)i;
break;
BOOL isSelectedLockUsable = lockIndex >= 0
&& lockIndex < (NSInteger)locks.size()
&& locks[lockIndex].type == libcdoc::Lock::Type::PASSWORD;
if (lockIndex >= 0 && !isSelectedLockUsable) {
NSLog(@"Lock %ld is not a password lock (%zu lock(s) in container), falling back to the first password lock",
(long)lockIndex, locks.size());
}

NSInteger idx = -1;
if (isSelectedLockUsable) {
idx = lockIndex;
} else {
for (size_t i = 0; i < locks.size(); i++) {
if (locks[i].type == libcdoc::Lock::Type::PASSWORD) {
idx = (NSInteger)i;
break;
}
}
}
if (idx < 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import Foundation
@objc public var concatKDFAlgorithmURI: String
@objc public let lockLabel: String
@objc public let lockType: String
@objc public let lockIndex: Int

@objc public init(
data: Data,
Expand All @@ -27,7 +28,8 @@ import Foundation
validTo: Date?,
concatKDFAlgorithmURI: String = "",
lockLabel: String = "",
lockType: String = ""
lockType: String = "",
lockIndex: Int = -1
) {
self.identifier = cnVal
self.data = data
Expand All @@ -39,6 +41,7 @@ import Foundation
self.concatKDFAlgorithmURI = concatKDFAlgorithmURI
self.lockLabel = lockLabel
self.lockType = lockType
self.lockIndex = lockIndex
}

@objc public convenience init(data: Data, cnVal: String) {
Expand All @@ -61,7 +64,8 @@ import Foundation
data: Data,
concatKDFAlgorithmURI: String = "",
lockLabel: String = "",
lockType: String = ""
lockType: String = "",
lockIndex: Int = -1
) {
let split = cnVal.split(separator: ",").map { String($0) }
if split.count >= 3 {
Expand All @@ -80,6 +84,7 @@ import Foundation
self.concatKDFAlgorithmURI = concatKDFAlgorithmURI
self.lockLabel = lockLabel
self.lockType = lockType
self.lockIndex = lockIndex
}

public init(cert: Data, x509: X509Certificate?) {
Expand All @@ -101,6 +106,7 @@ import Foundation
concatKDFAlgorithmURI = ""
lockLabel = ""
lockType = ""
lockIndex = -1
}

convenience public init(cert: Data) {
Expand Down
7 changes: 6 additions & 1 deletion Modules/CryptoLib/Sources/CryptoSwift/CryptoContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -402,12 +402,17 @@ extension CryptoContainer {
containerFile: URL,
recipients: [Addressee],
password: String,
lockIndex: Int = -1,
fileManager: FileManagerProtocol = Container.shared.fileManager()
) async throws -> CryptoContainerProtocol {
let decryptedData: [String: Data] = try await withCheckedThrowingContinuation { continuation in
DispatchQueue.global(qos: .userInitiated).async {
do {
let result = try Decrypt.decryptFile(containerFile.resolvedPath, withPassword: password)
let result = try Decrypt.decryptFile(
containerFile.resolvedPath,
withPassword: password,
lockIndex: lockIndex
)
continuation.resume(returning: result)
} catch let nsError as NSError where nsError.code == libcdocWrongKeyCode {
continuation.resume(throwing: CryptoError.wrongDecryptionKey)
Expand Down
32 changes: 32 additions & 0 deletions Modules/CryptoLib/Tests/CryptoSwiftTests/AddresseeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,36 @@ struct AddresseeTests {
#expect(addressee.lockLabel == "")
#expect(addressee.lockType == "")
}

@Test
func init_lockIndexDefaultsToNoLock() {
let addressee = Addressee(
data: Data(),
cnVal: "USER,TEST,38001010001",
givenName: "TEST",
surname: "USER",
serialNumber: nil,
certType: .iDCardType,
validTo: nil
)

#expect(addressee.lockIndex == -1)
}

@Test
func cnValInit_keepsTheLockIndexItWasBuiltFrom() {
let addressee = Addressee(
cnVal: "myKey",
serialNumber: nil,
certType: .passwordType,
validTo: nil,
data: Data(),
concatKDFAlgorithmURI: "",
lockLabel: "data:v=1&label=myKey&type=pw",
lockType: "PASSWORD",
lockIndex: 2
)

#expect(addressee.lockIndex == 2)
}
}
Loading
Loading