diff --git a/enzevalos_iphone/SMIME.swift b/enzevalos_iphone/SMIME.swift index c085701adaff27877cfae1a8964474ad1fe3b40b..f64eb623d747144184800c20dd673a779148da9c 100644 --- a/enzevalos_iphone/SMIME.swift +++ b/enzevalos_iphone/SMIME.swift @@ -62,7 +62,9 @@ class SMIME { var CAs : [String] = [] for k in CAKeychain.allKeys() { - CAs.append(CAKeychain[k]!) + if let ca = CAKeychain[k] { + CAs.append(ca) + } } return CAs @@ -105,10 +107,10 @@ class SMIME { for (cert, key) in certsAndKeys { let (certFP, _, _) = getFingerprintFromPem(pem: cert) - if (certFP != nil) { - certsKeychain[certFP!] = cert - privateKeyKeychain[certFP!] = key - fingerprints.append(certFP!) + if let certFP = certFP { + certsKeychain[certFP] = cert + privateKeyKeychain[certFP] = key + fingerprints.append(certFP) } } @@ -182,22 +184,21 @@ class SMIME { */ func decrypt(data: Data, fromAddr: String, isMailNew: Bool) throws -> CryptoObject { var outputData: Data = data - let text = String(data: data, encoding: .utf8)! - var fp = getOwnKeyFP() - let cert = certsKeychain[fp!]! // TODO ERROR!!! - let key = privateKeyKeychain[fp!]! + guard var fp = getOwnKeyFP() , let cert = certsKeychain[fp], let key = privateKeyKeychain[fp], let text = String(data: data, encoding: .utf8) else { + return CryptoObject(chiphertext: data, plaintext: nil, decryptedData: nil, sigState: .NoPublicKey, encState: .UnableToDecrypt, signKey: nil, encType: .SMIME, signedAdrs: []) + } var (decStr, errArr) = decryptWithPem(message: text, certAsPem: cert, keyAsPem: key) var encState = EncryptionState.UnableToDecrypt - if decStr != nil && (errArr == nil || errArr!.count == 0) { + if let errArr = errArr, errArr.count == 0 && decStr != nil { encState = EncryptionState.ValidedEncryptedWithCurrentKey } else { let fps = privateKeyKeychain.allKeys() - for f in fps{ - if f != fp{ - (decStr, errArr) = decryptWithPem(message: text, certAsPem: certsKeychain[f]!, keyAsPem: privateKeyKeychain[f]!) + for f in fps { + if f != fp, let certAsPem = certsKeychain[f], let keyAsPem = privateKeyKeychain[f] { + (decStr, errArr) = decryptWithPem(message: text, certAsPem: certAsPem, keyAsPem: keyAsPem) if decStr != nil{ fp = f encState = EncryptionState.ValidEncryptedWithOldKey @@ -207,8 +208,8 @@ class SMIME { } } - if decStr != nil { - outputData = decStr!.data(using: .utf8)! + if let decStr = decStr, let decData = decStr.data(using: .utf8) { + outputData = decData } /** @@ -216,7 +217,7 @@ class SMIME { * the email wasn't meant for us and we shouldn't be able to decrypt it anyway * there is something wrong with the e-mail */ - if (errArr != nil && errArr!.count > 0) { + if let errArr = errArr, errArr.count > 0 { throw SMIMEError(message: "Decryption failed!", errorArray: errArr, type: SMIMEError.ErrorType.decryption) } @@ -227,7 +228,8 @@ class SMIME { let sigState = verifyCryptoObj.signatureState let addresses = verifyCryptoObj.signedAdrs let plainText = verifyCryptoObj.plaintext - let decryptedData = plainText!.data(using: .utf8)! + let decryptedData = plainText?.data(using: .utf8) + return CryptoObject(chiphertext: data, plaintext: plainText, decryptedData: decryptedData, sigState: sigState, encState: encState, signKey: signKey, encType: CryptoScheme.SMIME, signedAdrs: addresses, signedKeys: signedKeys) } @@ -252,15 +254,23 @@ class SMIME { guard let cert = certsKeychain[fp], let key = privateKeyKeychain[fp] else { throw SMIMEError(message: "No signing key....", errorArray: nil, type: SMIMEError.ErrorType.missingKey) } - let text = String(data: plainData, encoding: .utf8) + guard let text = String(data: plainData, encoding: .utf8) else { + throw SMIMEError(message: "No data...", errorArray: nil, type: SMIMEError.ErrorType.noData) + + } - let (sigText, errArr) = signWithPem(message: text!, certAsPem: cert, keyAsPem: key, detached: detached) + let (sigText, errArr) = signWithPem(message: text, certAsPem: cert, keyAsPem: key, detached: detached) - if (errArr != nil && errArr!.count > 0) { + if let errArr = errArr, errArr.count > 0 { throw SMIMEError(message: "Signing failed!", errorArray: errArr, type: SMIMEError.ErrorType.signing) } + if let sigText = sigText { + return CryptoObject(chiphertext: sigText.data(using: .utf8), plaintext: text, decryptedData: plainData, sigState: SignatureState.ValidSignature, encState: EncryptionState.NoEncryption, signKey: fp, encType: CryptoScheme.SMIME, signedAdrs: [myEmail]) + } else { + throw SMIMEError(message: "Signing failed! No signed data...", errorArray: errArr, type: SMIMEError.ErrorType.signing) + } - return CryptoObject(chiphertext: sigText!.data(using: .utf8), plaintext: text, decryptedData: plainData, sigState: SignatureState.ValidSignature, encState: EncryptionState.NoEncryption, signKey: fp, encType: CryptoScheme.SMIME, signedAdrs: [myEmail]) + } /** @@ -276,7 +286,9 @@ class SMIME { func verify(data: Data?, string: String? = nil, email: String, isMailNew: Bool) -> CryptoObject { var CAs : [String] = [] CAKeychain.allKeys().forEach({ (key) in - CAs.append(CAKeychain[key]!) + if let ca = CAKeychain[key] { + CAs.append(ca) + } }) guard data != nil || string != nil else { return CryptoObject(chiphertext: nil, plaintext: nil, decryptedData: nil, sigState: .NoSignature, encState: .UnableToDecrypt, signKey: nil, encType: .UNKNOWN, signedAdrs: []) @@ -292,17 +304,16 @@ class SMIME { let (verStr, certsFPArrWithNil, errArr) = verifyWithCApem(message: text, pemCAArr: CAs) guard let certsFPArr = certsFPArrWithNil, certsFPArr.count > 0 else { - let errors = errArr! - - for error in errors { - let reason = getErrorReasonString(errCode: error) - // check reasons to identify different error causes - // string comaprison necessary because doesn't have fixed error codes... - if reason == "no content type" { - return CryptoObject(chiphertext: data, plaintext: text, decryptedData: nil, sigState: .NoSignature, encState: EncryptionState.NoEncryption, signKey: nil, encType: .UNKNOWN, signedAdrs: []) + if let errors = errArr { + for error in errors { + let reason = getErrorReasonString(errCode: error) + // check reasons to identify different error causes + // string comaprison necessary because doesn't have fixed error codes... + if reason == "no content type" { + return CryptoObject(chiphertext: data, plaintext: text, decryptedData: nil, sigState: .NoSignature, encState: EncryptionState.NoEncryption, signKey: nil, encType: .UNKNOWN, signedAdrs: []) + } } } - return CryptoObject(chiphertext: data, plaintext: text, decryptedData: nil, sigState: .InvalidSignature, encState: EncryptionState.NoEncryption, signKey: nil, encType: .UNKNOWN, signedAdrs: []) } @@ -356,8 +367,11 @@ class SMIME { let (fp, _) = arg return fp }) - - return CryptoObject(chiphertext: data, plaintext: verStr!, decryptedData: nil, sigState: sigState, encState: EncryptionState.NoEncryption, signKey: nil, encType: .SMIME, signedAdrs: signedAddresses, signedKeys: signKeyFps) + if let verStr = verStr { + return CryptoObject(chiphertext: data, plaintext: verStr, decryptedData: nil, sigState: sigState, encState: EncryptionState.NoEncryption, signKey: nil, encType: .SMIME, signedAdrs: signedAddresses, signedKeys: signKeyFps) + } else { + return CryptoObject(chiphertext: data, plaintext: text, decryptedData: nil, sigState: .NoSignature, encState: EncryptionState.NoEncryption, signKey: nil, encType: .UNKNOWN, signedAdrs: []) + } } /** @@ -395,8 +409,8 @@ class SMIME { // if we want to encrypt with the user's own key, retrieve the key and handle errors if encryptForMyId { - if ownFp != nil { - pems.append(certsKeychain[ownFp!]!) + if let ownFp = ownFp, let cert = certsKeychain[ownFp] { + pems.append(cert) } else { throw SMIMEError(message: "Tried to encrypt email with the user's key but no cert for own key present!", errorArray: nil, type: SMIMEError.ErrorType.other) @@ -421,11 +435,14 @@ class SMIME { // do the actual encryption // NOTE: sigText can't be nil b/c we force signing so we either sign successfully or we throw an exception and never reach this code block let (encStr, errArr) = encryptWithPem(message: sigText!, certPems: pems) - if errArr != nil && errArr!.count > 0 { + if let errArr = errArr, errArr.count > 0 { throw SMIMEError(message: "Encryption failed!", errorArray: errArr, type: SMIMEError.ErrorType.encryption) } - - return CryptoObject(chiphertext: encStr!.data(using: .utf8), plaintext: plainText, decryptedData: plainData, sigState: SignatureState.ValidSignature, encState: EncryptionState.ValidedEncryptedWithCurrentKey, signKey: ownFp, encType: CryptoScheme.SMIME, signedAdrs: [ownAddr]) + if let encStr = encStr { + return CryptoObject(chiphertext: encStr.data(using: .utf8), plaintext: plainText, decryptedData: plainData, sigState: SignatureState.ValidSignature, encState: EncryptionState.ValidedEncryptedWithCurrentKey, signKey: ownFp, encType: CryptoScheme.SMIME, signedAdrs: [ownAddr]) + } + throw SMIMEError(message: "Encryption failed! No data...", errorArray: errArr, type: SMIMEError.ErrorType.encryption) + } /** @@ -504,12 +521,18 @@ class SMIME { let certArr: [String]? = result?.extractField(field: ResultAttribute.certificates) let fpArr: [String]? = result?.extractField(field: ResultAttribute.fingerprints) - let numCerts = Int((result?.num_certs)!) + + var numCerts = 0 + if let n = result?.num_certs { + numCerts = Int(n) + } var certFPArr: [(String, String)] = [] if (numCerts > 0) { for i in 0...(numCerts-1) { - certFPArr.append( ((fpArr?[i])!, (certArr?[i])!) ) + if let fp = fpArr?[i], let cert = certArr?[i] { + certFPArr.append((fp, cert)) + } } } diff --git a/enzevalos_iphone/SMIMEHelpers.swift b/enzevalos_iphone/SMIMEHelpers.swift index c73e6de691a824e439371339dccc76733436cf0c..fdae468d7aeb0fcf48b299d165710f0606abe203 100644 --- a/enzevalos_iphone/SMIMEHelpers.swift +++ b/enzevalos_iphone/SMIMEHelpers.swift @@ -19,6 +19,7 @@ class SMIMEError : Error { case signing case other case missingKey + case noData } func errorArrayToString() -> [String] {